Loading...
Searching...
No Matches
MoveStates.hpp
1#pragma once
2#include <Scenario/Commands/Scenario/Displacement/MoveEventMeta.hpp>
3#include <Scenario/Commands/Scenario/Merge/MergeEvents.hpp>
4#include <Scenario/Document/Event/EventPresenter.hpp>
5#include <Scenario/Document/Event/EventView.hpp>
6#include <Scenario/Document/Interval/Temporal/TemporalIntervalPresenter.hpp>
7#include <Scenario/Document/Interval/Temporal/TemporalIntervalView.hpp>
8#include <Scenario/Document/State/StatePresenter.hpp>
9#include <Scenario/Document/State/StateView.hpp>
10#include <Scenario/Document/TimeSync/TimeSyncPresenter.hpp>
11#include <Scenario/Document/TimeSync/TimeSyncView.hpp>
12#include <Scenario/Document/TimeSync/TriggerView.hpp>
13#include <Scenario/Palette/ScenarioPaletteBaseStates.hpp>
14#include <Scenario/Palette/Tools/ScenarioRollbackStrategy.hpp>
15#include <Scenario/Palette/Transitions/AnythingTransitions.hpp>
16#include <Scenario/Palette/Transitions/EventTransitions.hpp>
17#include <Scenario/Palette/Transitions/IntervalTransitions.hpp>
18#include <Scenario/Palette/Transitions/NothingTransitions.hpp>
19#include <Scenario/Palette/Transitions/TimeSyncTransitions.hpp>
20#include <Scenario/Process/Algorithms/Accessors.hpp>
21
22#include <score/command/Dispatchers/MultiOngoingCommandDispatcher.hpp>
23#include <score/command/Dispatchers/SingleOngoingCommandDispatcher.hpp>
24#include <score/locking/ObjectLocker.hpp>
25
26#include <QApplication>
27#include <QFinalState>
28
29namespace Scenario
30{
31template <
32 typename MoveBraceCommand_T, // SetMinDuration or setMaxDuration
33 typename Scenario_T, typename ToolPalette_T>
34class MoveIntervalBraceState final : public StateBase<Scenario_T>
35{
36public:
38 const ToolPalette_T& stateMachine, const Scenario_T& scenarioPath,
40 QState* parent)
41 : StateBase<Scenario_T>{scenarioPath, parent}
42 , m_dispatcher{stack}
43 {
44 this->setObjectName("MoveIntervalBraceState");
45 using namespace Scenario::Command;
46 auto finalState = new QFinalState{this};
47
48 auto mainState = new QState{this};
49 {
50 auto pressed = new QState{mainState};
51 auto released = new QState{mainState};
52 auto moving = new QState{mainState};
53
54 mainState->setInitialState(pressed);
55 released->addTransition(finalState);
56
57 score::make_transition<MoveOnAnything_Transition<Scenario_T>>(
58 pressed, moving, *this);
59 score::make_transition<ReleaseOnAnything_Transition>(pressed, finalState);
60
61 score::make_transition<MoveOnAnything_Transition<Scenario_T>>(
62 moving, moving, *this);
63 score::make_transition<ReleaseOnAnything_Transition>(moving, released);
64
65 QObject::connect(pressed, &QState::entered, [&]() {
66 this->m_initialDate = this->currentPoint.date;
67 if(this->clickedInterval)
68 {
69 auto& scenar = stateMachine.model();
70 auto& cstr = scenar.interval(*this->clickedInterval);
71 this->m_initialDuration
72 = ((cstr.duration)
73 .*MoveBraceCommand_T::corresponding_member)(); // = interval
74 // MinDuration
75 // or
76 // maxDuration
77 }
78 });
79
80 QObject::connect(moving, &QState::entered, [&]() {
81 if(this->clickedInterval)
82 {
83 auto& scenar = stateMachine.model();
84 auto& cstr = scenar.interval(*this->clickedInterval);
85 const auto duration
86 = this->currentPoint.date - *m_initialDate + *m_initialDuration;
87
88 // Magnetism operates on scenario dates, not interval durations.
89 const TimeVal date = stateMachine.magnetic().getPosition(
90 &stateMachine.model(), cstr.date() + duration);
91
92 this->m_dispatcher.submit(cstr, date - cstr.date(), false);
93 }
94 });
95
96 QObject::connect(
97 released, &QState::entered, [&]() { this->m_dispatcher.commit(); });
98 }
99
100 auto rollbackState = new QState{this};
101 score::make_transition<score::Cancel_Transition>(mainState, rollbackState);
102 rollbackState->addTransition(finalState);
103 QObject::connect(
104 rollbackState, &QState::entered, [&]() { m_dispatcher.rollback(); });
105
106 this->setInitialState(mainState);
107 }
109
110private:
111 std::optional<TimeVal> m_initialDate;
112 std::optional<TimeVal> m_initialDuration;
113};
114
115template <
116 typename MoveTimeSyncCommand_T, // MoveEventMeta
117 typename Scenario_T, typename ToolPalette_T>
118class MoveTimeSyncState final : public StateBase<Scenario_T>
119{
120public:
122 const ToolPalette_T& stateMachine, const Scenario_T& scenarioPath,
124 QState* parent)
125 : StateBase<Scenario_T>{scenarioPath, parent}
126 , m_dispatcher{stack}
127 {
128 this->setObjectName("MoveTimeSyncState");
129 using namespace Scenario::Command;
130 auto finalState = new QFinalState{this};
131
132 auto mainState = new QState{this};
133 {
134 auto pressed = new QState{mainState};
135 auto released = new QState{mainState};
136 auto moving = new QState{mainState};
137
138 // General setup
139 mainState->setInitialState(pressed);
140 released->addTransition(finalState);
141
142 score::make_transition<MoveOnAnything_Transition<Scenario_T>>(
143 pressed, moving, *this);
144 score::make_transition<ReleaseOnAnything_Transition>(pressed, finalState);
145 score::make_transition<MoveOnAnything_Transition<Scenario_T>>(
146 moving, moving, *this);
147 score::make_transition<ReleaseOnAnything_Transition>(moving, released);
148
149 // What happens in each state.
150 QObject::connect(pressed, &QState::entered, [&]() {
151 if(!this->clickedTimeSync)
152 return;
153
154 auto& scenar = stateMachine.model();
155
156 auto prev_csts
157 = previousNonGraphIntervals(scenar.timeSync(*this->clickedTimeSync), scenar);
158 if(!prev_csts.empty())
159 {
160 // We find the one that starts the latest.
161 TimeVal t = TimeVal::zero();
162 for(const auto& cst_id : prev_csts)
163 {
164 const auto& other_date = scenar.interval(cst_id).date();
165 if(other_date > t)
166 t = other_date;
167 }
168 this->m_pressedPrevious = t;
169 }
170 else
171 {
172 this->m_pressedPrevious = std::nullopt;
173 }
174 });
175
176 QObject::connect(moving, &QState::entered, [&]() {
177 if(!this->clickedTimeSync)
178 return;
179
180 // Get the 1st event on the timesync.
181 auto& scenar = stateMachine.model();
182 auto& tn = scenar.timeSync(*this->clickedTimeSync);
183 SCORE_ASSERT(!tn.events().empty());
184 const auto& ev_id = tn.events().front();
185 auto date = this->currentPoint.date;
186
187 date = stateMachine.magnetic().getPosition(&stateMachine.model(), date);
188
189 if(this->m_pressedPrevious)
190 {
191 date = max(date, *this->m_pressedPrevious);
192 }
193
194 m_dispatcher.submit(
195 this->m_scenario, ev_id, date, this->currentPoint.y,
196 stateMachine.editionSettings().expandMode(),
197 stateMachine.editionSettings().lockMode());
198 });
199
200 QObject::connect(released, &QState::entered, [&]() {
201 m_dispatcher.commit();
202 m_pressedPrevious = {};
203 });
204 }
205
206 auto rollbackState = new QState{this};
207 score::make_transition<score::Cancel_Transition>(mainState, rollbackState);
208 rollbackState->addTransition(finalState);
209 QObject::connect(
210 rollbackState, &QState::entered, [&]() { m_dispatcher.rollback(); });
211
212 this->setInitialState(mainState);
213 }
214
216 std::optional<TimeVal> m_pressedPrevious;
217};
218}
Definition MoveStates.hpp:35
Definition MoveStates.hpp:119
Definition ScenarioPaletteBaseStates.hpp:20
The SingleOngoingCommandDispatcher class.
Definition SingleOngoingCommandDispatcher.hpp:17
A small abstraction layer over the score::CommandStack.
Definition CommandStackFacade.hpp:20
The ObjectLocker class.
Definition ObjectLocker.hpp:21
Main plug-in of score.
Definition score-plugin-dataflow/Dataflow/PortItem.hpp:13
Definition TimeValue.hpp:21