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 
29 namespace Scenario
30 {
31 template <
32  typename MoveBraceCommand_T, // SetMinDuration or setMaxDuration
33  typename Scenario_T, typename ToolPalette_T>
34 class MoveIntervalBraceState final : public StateBase<Scenario_T>
35 {
36 public:
38  const ToolPalette_T& stateMachine, const Scenario_T& scenarioPath,
39  const score::CommandStackFacade& stack, score::ObjectLocker& locker,
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  auto date = this->currentPoint.date - *m_initialDate + *m_initialDuration;
86 
87  date = stateMachine.magnetic().getPosition(&stateMachine.model(), date);
88 
89  this->m_dispatcher.submit(cstr, date, false);
90  }
91  });
92 
93  QObject::connect(
94  released, &QState::entered, [&]() { this->m_dispatcher.commit(); });
95  }
96 
97  auto rollbackState = new QState{this};
98  score::make_transition<score::Cancel_Transition>(mainState, rollbackState);
99  rollbackState->addTransition(finalState);
100  QObject::connect(
101  rollbackState, &QState::entered, [&]() { m_dispatcher.rollback(); });
102 
103  this->setInitialState(mainState);
104  }
106 
107 private:
108  std::optional<TimeVal> m_initialDate;
109  std::optional<TimeVal> m_initialDuration;
110 };
111 
112 template <
113  typename MoveTimeSyncCommand_T, // MoveEventMeta
114  typename Scenario_T, typename ToolPalette_T>
115 class MoveTimeSyncState final : public StateBase<Scenario_T>
116 {
117 public:
119  const ToolPalette_T& stateMachine, const Scenario_T& scenarioPath,
120  const score::CommandStackFacade& stack, score::ObjectLocker& locker,
121  QState* parent)
122  : StateBase<Scenario_T>{scenarioPath, parent}
123  , m_dispatcher{stack}
124  {
125  this->setObjectName("MoveTimeSyncState");
126  using namespace Scenario::Command;
127  auto finalState = new QFinalState{this};
128 
129  auto mainState = new QState{this};
130  {
131  auto pressed = new QState{mainState};
132  auto released = new QState{mainState};
133  auto moving = new QState{mainState};
134 
135  // General setup
136  mainState->setInitialState(pressed);
137  released->addTransition(finalState);
138 
139  score::make_transition<MoveOnAnything_Transition<Scenario_T>>(
140  pressed, moving, *this);
141  score::make_transition<ReleaseOnAnything_Transition>(pressed, finalState);
142  score::make_transition<MoveOnAnything_Transition<Scenario_T>>(
143  moving, moving, *this);
144  score::make_transition<ReleaseOnAnything_Transition>(moving, released);
145 
146  // What happens in each state.
147  QObject::connect(pressed, &QState::entered, [&]() {
148  if(!this->clickedTimeSync)
149  return;
150 
151  auto& scenar = stateMachine.model();
152 
153  auto prev_csts
154  = previousNonGraphIntervals(scenar.timeSync(*this->clickedTimeSync), scenar);
155  if(!prev_csts.empty())
156  {
157  // We find the one that starts the latest.
158  TimeVal t = TimeVal::zero();
159  for(const auto& cst_id : prev_csts)
160  {
161  const auto& other_date = scenar.interval(cst_id).date();
162  if(other_date > t)
163  t = other_date;
164  }
165  this->m_pressedPrevious = t;
166  }
167  else
168  {
169  this->m_pressedPrevious = std::nullopt;
170  }
171  });
172 
173  QObject::connect(moving, &QState::entered, [&]() {
174  if(!this->clickedTimeSync)
175  return;
176 
177  // Get the 1st event on the timesync.
178  auto& scenar = stateMachine.model();
179  auto& tn = scenar.timeSync(*this->clickedTimeSync);
180  SCORE_ASSERT(!tn.events().empty());
181  const auto& ev_id = tn.events().front();
182  auto date = this->currentPoint.date;
183 
184  date = stateMachine.magnetic().getPosition(&stateMachine.model(), date);
185 
186  if(this->m_pressedPrevious)
187  {
188  date = max(date, *this->m_pressedPrevious);
189  }
190 
191  m_dispatcher.submit(
192  this->m_scenario, ev_id, date, this->currentPoint.y,
193  stateMachine.editionSettings().expandMode(),
194  stateMachine.editionSettings().lockMode());
195  });
196 
197  QObject::connect(released, &QState::entered, [&]() {
198  m_dispatcher.commit();
199  m_pressedPrevious = {};
200  });
201  }
202 
203  auto rollbackState = new QState{this};
204  score::make_transition<score::Cancel_Transition>(mainState, rollbackState);
205  rollbackState->addTransition(finalState);
206  QObject::connect(
207  rollbackState, &QState::entered, [&]() { m_dispatcher.rollback(); });
208 
209  this->setInitialState(mainState);
210  }
211 
213  std::optional<TimeVal> m_pressedPrevious;
214 };
215 }
Definition: MoveStates.hpp:35
Definition: MoveStates.hpp:116
Definition: ScenarioPaletteBaseStates.hpp:20
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:14
Definition: TimeValue.hpp:21