ScenarioCreation_FromNothing.hpp
1 #pragma once
2 #include "ScenarioCreationState.hpp"
3 
4 #include <Scenario/Application/ScenarioEditionSettings.hpp>
5 #include <Scenario/Commands/Scenario/Creations/CreateEvent_State.hpp>
6 #include <Scenario/Commands/Scenario/Creations/CreateState.hpp>
7 #include <Scenario/Commands/Scenario/Displacement/MoveNewEvent.hpp>
8 #include <Scenario/Commands/Scenario/Displacement/MoveNewState.hpp>
9 #include <Scenario/Document/TimeSync/TimeSyncModel.hpp>
10 #include <Scenario/Palette/Transitions/AnythingTransitions.hpp>
11 #include <Scenario/Palette/Transitions/EventTransitions.hpp>
12 #include <Scenario/Palette/Transitions/IntervalTransitions.hpp>
13 #include <Scenario/Palette/Transitions/NothingTransitions.hpp>
14 #include <Scenario/Palette/Transitions/StateTransitions.hpp>
15 #include <Scenario/Palette/Transitions/TimeSyncTransitions.hpp>
16 
17 #include <QFinalState>
18 
19 namespace Scenario
20 {
21 template <typename Scenario_T, typename ToolPalette_T>
22 class Creation_FromNothing final : public CreationState<Scenario_T, ToolPalette_T>
23 {
24 public:
26  const ToolPalette_T& stateMachine, const Scenario_T& scenarioPath,
27  const score::CommandStackFacade& stack, QState* parent)
28  : CreationState<Scenario_T, ToolPalette_T>{
29  stateMachine, stack, scenarioPath, parent}
30  {
31  this->setObjectName("ScenarioCreation_FromNothing");
32  using namespace Scenario::Command;
33  auto finalState = new QFinalState{this};
34  QObject::connect(finalState, &QState::entered, [&]() { this->clearCreatedIds(); });
35 
36  auto mainState = new QState{this};
37  mainState->setObjectName("Main state");
38  {
39  auto pressed = new QState{mainState};
40  auto released = new QState{mainState};
41  auto move_nothing = new StrongQState<MoveOnNothing>{mainState};
42  auto move_state = new StrongQState<MoveOnState>{mainState};
43  auto move_event = new StrongQState<MoveOnEvent>{mainState};
44  auto move_timesync = new StrongQState<MoveOnTimeSync>{mainState};
45 
46  pressed->setObjectName("Pressed");
47  released->setObjectName("Released");
48  move_nothing->setObjectName("Move on Nothing");
49  move_state->setObjectName("Move on State");
50  move_event->setObjectName("Move on Event");
51  move_timesync->setObjectName("Move on Sync");
52 
53  // General setup
54  mainState->setInitialState(pressed);
55  released->addTransition(finalState);
56 
57  // Release
58  score::make_transition<ReleaseOnAnything_Transition>(mainState, released);
59 
60  // Pressed -> ...
61  score::make_transition<MoveOnNothing_Transition<Scenario_T>>(
62  pressed, move_nothing, *this);
63 
65  // MoveOnNothing -> MoveOnNothing.
66  score::make_transition<MoveOnNothing_Transition<Scenario_T>>(
67  move_nothing, move_nothing, *this);
68 
69  // MoveOnNothing -> MoveOnState.
70  this->add_transition(move_nothing, move_state, [&]() {
71  this->rollback();
72  createToState();
73  });
74 
75  // MoveOnNothing -> MoveOnEvent.
76  this->add_transition(move_nothing, move_event, [&]() {
77  this->rollback();
78  createToEvent();
79  });
80 
81  // MoveOnNothing -> MoveOnTimeSync
82  this->add_transition(move_nothing, move_timesync, [&]() {
83  this->rollback();
84  createToTimeSync();
85  });
86 
88  // MoveOnState -> MoveOnNothing
89  this->add_transition(move_state, move_nothing, [&]() {
90  this->rollback();
91  createToNothing();
92  });
93 
94  // MoveOnState -> MoveOnState
95  // We don't do anything, the interval should not move.
96 
97  // MoveOnState -> MoveOnEvent
98  this->add_transition(move_state, move_event, [&]() {
99  this->rollback();
100  createToEvent();
101  });
102 
103  // MoveOnState -> MoveOnTimeSync
104  this->add_transition(move_state, move_timesync, [&]() {
105  this->rollback();
106  createToTimeSync();
107  });
108 
110  // MoveOnEvent -> MoveOnNothing
111  this->add_transition(move_event, move_nothing, [&]() {
112  this->rollback();
113  createToNothing();
114  });
115 
116  // MoveOnEvent -> MoveOnState
117  this->add_transition(move_event, move_state, [&]() {
118  this->rollback();
119  createToState();
120  });
121 
122  // MoveOnEvent -> MoveOnEvent
123  score::make_transition<MoveOnEvent_Transition<Scenario_T>>(
124  move_event, move_event, *this);
125 
126  // MoveOnEvent -> MoveOnTimeSync
127  this->add_transition(move_event, move_timesync, [&]() {
128  this->rollback();
129  createToTimeSync();
130  });
131 
133  // MoveOnTimeSync -> MoveOnNothing
134  this->add_transition(move_timesync, move_nothing, [&]() {
135  this->rollback();
136  createToNothing();
137  });
138 
139  // MoveOnTimeSync -> MoveOnState
140  this->add_transition(move_timesync, move_state, [&]() {
141  this->rollback();
142  createToState();
143  });
144 
145  // MoveOnTimeSync -> MoveOnEvent
146  this->add_transition(move_timesync, move_event, [&]() {
147  this->rollback();
148  createToEvent();
149  });
150 
151  // MoveOnTimeSync -> MoveOnTimeSync
152  score::make_transition<MoveOnTimeSync_Transition<Scenario_T>>(
153  move_timesync, move_timesync, *this);
154 
155  // What happens in each state.
156  QObject::connect(pressed, &QState::entered, [&]() {
157  this->currentPoint.date = stateMachine.magnetic().getPosition(
158  &stateMachine.model(), this->currentPoint.date);
159  this->m_clickedPoint = this->currentPoint;
160 
161  this->clickedEvent = this->m_parentSM.model().startEvent().id();
162  createToNothing();
163  });
164 
165  QObject::connect(move_nothing, &QState::entered, [&]() {
166  if(this->createdIntervals.empty() || this->createdEvents.empty())
167  {
168  this->rollback();
169  return;
170  }
171 
172  this->currentPoint.date = stateMachine.magnetic().getPosition(
173  &stateMachine.model(), this->currentPoint.date);
174 
175  if(this->clickedEvent != this->m_parentSM.model().startEvent().id()
176  && this->currentPoint.date <= this->m_clickedPoint.date)
177  {
178  this->currentPoint.date = this->m_clickedPoint.date + TimeVal::fromMsecs(10);
179  }
180  else if(
181  this->clickedEvent == this->m_parentSM.model().startEvent().id()
182  && this->currentPoint.date <= TimeVal::fromMsecs(10))
183  {
184  this->currentPoint.date = TimeVal::fromMsecs(10);
185  }
186 
187  Scenario::EditionSettings& settings = this->m_parentSM.editionSettings();
188  this->m_dispatcher.template submit<MoveNewEvent>(
189  this->m_scenario, this->createdIntervals.last(), this->createdEvents.last(),
190  this->currentPoint.date, this->currentPoint.y,
191  settings.tool() == Tool::CreateSequence);
192  });
193 
194  QObject::connect(move_timesync, &QState::entered, [&]() {
195  if(this->createdStates.empty())
196  {
197  this->rollback();
198  return;
199  }
200 
201  if(this->currentPoint.date <= this->m_clickedPoint.date)
202  {
203  return;
204  }
205 
206  this->m_dispatcher.template submit<MoveNewState>(
207  this->m_scenario, this->createdStates.last(), this->currentPoint.y);
208  });
209 
210  QObject::connect(move_event, &QState::entered, [&]() {
211  if(this->createdStates.empty())
212  {
213  this->rollback();
214  return;
215  }
216 
217  if(this->currentPoint.date <= this->m_clickedPoint.date)
218  {
219  return;
220  }
221 
222  this->m_dispatcher.template submit<MoveNewState>(
223  this->m_scenario, this->createdStates.last(), this->currentPoint.y);
224  });
225 
226  QObject::connect(released, &QState::entered, this, &Creation_FromNothing::commit);
227  }
228 
229  auto rollbackState = new QState{this};
230  rollbackState->setObjectName("Rollback");
231  score::make_transition<score::Cancel_Transition>(mainState, rollbackState);
232  rollbackState->addTransition(finalState);
233 
234  QObject::connect(
235  rollbackState, &QState::entered, this, &Creation_FromNothing::rollback);
236 
237  this->setInitialState(mainState);
238  }
239 
240 private:
241  void createInitialState()
242  {
243  if(this->clickedEvent)
244  {
245  auto cmd = new Scenario::Command::CreateState{
246  this->m_scenario, *this->clickedEvent, this->currentPoint.y};
247  this->m_dispatcher.submit(cmd);
248 
249  this->createdStates.append(cmd->createdState());
250  }
251  }
252 
253  void createToNothing()
254  {
255  createInitialState();
256  this->createToNothing_base(this->createdStates.first());
257  }
258  void createToState()
259  {
260  SCORE_ASSERT(bool(this->hoveredState));
261 
262  const auto& state = this->m_parentSM.model().states.at(*this->hoveredState);
263  if(!bool(state.previousInterval()))
264  {
265  createInitialState();
266  this->createToState_base(this->createdStates.first());
267  }
268  }
269  void createToEvent()
270  {
271  if(this->hoveredEvent != this->clickedEvent)
272  {
273  createInitialState();
274  this->createToEvent_base(this->createdStates.first());
275  }
276  }
277  void createToTimeSync()
278  {
279  createInitialState();
280  this->createToTimeSync_base(this->createdStates.first());
281  }
282 };
283 }
Definition: CreateState.hpp:22
Definition: ScenarioCreation_FromNothing.hpp:23
Creation_FromNothing(const ToolPalette_T &stateMachine, const Scenario_T &scenarioPath, const score::CommandStackFacade &stack, QState *parent)
Definition: ScenarioCreation_FromNothing.hpp:25
Definition: ScenarioCreationState.hpp:66
Definition: ScenarioEditionSettings.hpp:14
A small abstraction layer over the score::CommandStack.
Definition: CommandStackFacade.hpp:20
Main plug-in of score.
Definition: score-plugin-dataflow/Dataflow/PortItem.hpp:14