Scenario/Document/Components/ScenarioComponent.hpp
1 #pragma once
2 #include <Scenario/Document/BaseScenario/BaseScenario.hpp>
3 #include <Scenario/Document/Event/EventModel.hpp>
4 #include <Scenario/Document/Interval/IntervalModel.hpp>
5 #include <Scenario/Document/State/ItemModel/MessageItemModel.hpp>
6 #include <Scenario/Document/State/StateModel.hpp>
7 #include <Scenario/Document/TimeSync/TimeSyncModel.hpp>
8 #include <Scenario/Process/Algorithms/Accessors.hpp>
9 #include <Scenario/Process/ScenarioModel.hpp>
10 
11 #include <score/document/DocumentContext.hpp>
12 #include <score/model/Component.hpp>
13 #include <score/model/ComponentSerialization.hpp>
14 #include <score/tools/IdentifierGeneration.hpp>
15 
16 #include <ossia/detail/algorithms.hpp>
17 
18 #include <list>
19 
20 template <
21  typename Component_T, typename Scenario_T, typename IntervalComponent_T,
22  bool HasOwnership = true>
24  : public Component_T
25  , public Nano::Observer
26 {
27 public:
28  struct IntervalPair
29  {
31  Scenario::IntervalModel& element;
32  IntervalComponent_T& component;
33  };
34 
36  template <typename... Args>
38  : Component_T{std::forward<Args>(args)...}
39  {
40  init();
41  }
42 
45  template <typename... Args>
47  : Component_T{std::forward<Args>(args)...}
48  {
49  }
50 
52  void init() { setup<Scenario::IntervalModel>(); }
53 
54  const std::list<IntervalPair>& intervals_pairs() const { return m_intervals; }
55 
56  void clear()
57  {
58  for(auto element : m_intervals)
59  do_cleanup(element);
60 
61  m_intervals.clear();
62  }
63 
65 
66  template <typename elt_t>
67  void remove(const elt_t& element)
68  {
69  using map_t = MatchingComponent<elt_t, true>;
70  auto& container = this->*map_t::local_container;
71 
72  auto it = ossia::find_if(
73  container, [&](auto pair) { return &pair.element == &element; });
74 
75  if(it != container.end())
76  {
77  do_cleanup(*it);
78  container.erase(it);
79  }
80  }
81 
82 private:
83  template <typename T, bool dummy = true>
84  struct MatchingComponent;
85 
86  template <typename Pair_T>
87  void do_cleanup(const Pair_T& pair)
88  {
89  if constexpr(HasOwnership)
90  {
91  Component_T::removing(pair.element, pair.component);
92  pair.element.components().remove(pair.component);
93  }
94  else
95  {
96  auto t = Component_T::removing(pair.element, pair.component);
97  pair.element.components().erase(pair.component);
98  Component_T::removed(pair.element, pair.component, std::move(t));
99  }
100  }
101 
102  template <typename elt_t>
103  void setup()
104  {
105  using map_t = MatchingComponent<elt_t, true>;
106  auto&& member = map_t::scenario_container(Component_T::process());
107 
108  for(auto& elt : member)
109  {
110  add(elt);
111  }
112 
113  member.mutable_added.template connect<
114  SimpleHierarchicalScenarioComponent, &SimpleHierarchicalScenarioComponent::add>(
115  this);
116 
117  member.removing.template connect<
119  &SimpleHierarchicalScenarioComponent::remove>(this);
120  }
121 
122 #if defined(SCORE_SERIALIZABLE_COMPONENTS)
123  template <typename elt_t>
124  void add(elt_t& element)
125  {
126  add(element, typename score::is_component_serializable<
127  typename MatchingComponent<elt_t, true>::type>::type{});
128  }
129 
130  template <typename elt_t>
131  void add(elt_t& element, score::serializable_tag)
132  {
133  using map_t = MatchingComponent<elt_t, true>;
134  using component_t = typename map_t::type;
135 
136  // Since the component may be serializable, we first look if
137  // we can deserialize it.
138  auto comp = score::deserialize_component<component_t>(
139  element.components(), [&](auto&& deserializer) {
140  Component_T::template load<component_t>(deserializer, element);
141  });
142 
143  // Maybe we could not deserialize it
144  if(!comp)
145  {
146  comp = Component_T::template make<component_t>(
147  getStrongId(element.components()), element);
148  }
149 
150  // We try to add it
151  if(comp)
152  {
153  element.components().add(comp);
154  (this->*map_t::local_container)
155  .emplace_back(typename map_t::pair_type{element, *comp});
156  }
157  }
158 
159  template <typename elt_t>
160  void add(elt_t& element, score::not_serializable_tag)
161 #else
162  template <typename elt_t>
163  void add(elt_t& element)
164 #endif
165  {
166  // We can just create a new component directly
167  using map_t = MatchingComponent<elt_t, true>;
168  auto comp = Component_T::make(getStrongId(element.components()), element);
169  if(comp)
170  {
171  element.components().add(comp);
172  (this->*map_t::local_container)
173  .emplace_back(typename map_t::pair_type{element, *comp});
174  }
175  }
176 
177  std::list<IntervalPair> m_intervals;
178 
179  template <bool dummy>
180  struct MatchingComponent<Scenario::IntervalModel, dummy>
181  {
182  using type = IntervalComponent_T;
183  using pair_type = IntervalPair;
184  static const constexpr auto local_container
185  = &SimpleHierarchicalScenarioComponent::m_intervals;
186  static const constexpr auto scenario_container
188  };
189 };
190 
191 template <
192  typename Component_T, typename Scenario_T, typename IntervalComponent_T,
193  typename EventComponent_T, typename TimeSyncComponent_T, typename StateComponent_T,
194  bool HasOwnership = true>
196  : public Component_T
197  , public Nano::Observer
198 {
199 public:
201  {
203  Scenario::IntervalModel& element;
204  IntervalComponent_T& component;
205  };
206  struct EventPair
207  {
209  Scenario::EventModel& element;
210  EventComponent_T& component;
211  };
213  {
215  Scenario::TimeSyncModel& element;
216  TimeSyncComponent_T& component;
217  };
218  struct StatePair
219  {
221  Scenario::StateModel& element;
222  StateComponent_T& component;
223  };
224 
226  template <typename... Args>
228  : Component_T{std::forward<Args>(args)...}
229  {
230  init();
231  }
232 
235  template <typename... Args>
237  : Component_T{std::forward<Args>(args)...}
238  {
239  }
240 
242  void init()
243  {
244  setup<Scenario::TimeSyncModel>();
245  setup<Scenario::EventModel>();
246  setup<Scenario::StateModel>();
247  setup<Scenario::IntervalModel>();
248  }
249 
250  const std::list<IntervalPair>& intervals_pairs() const { return m_intervals; }
251  const std::list<EventPair>& events_pairs() const { return m_events; }
252  const std::list<StatePair>& states_pairs() const { return m_states; }
253  const std::list<TimeSyncPair>& timeSyncs_pairs() const { return m_timeSyncs; }
254 
255  void clear()
256  {
257  for(auto element : m_intervals)
258  do_cleanup(element);
259  for(auto element : m_states)
260  do_cleanup(element);
261  for(auto element : m_events)
262  do_cleanup(element);
263  for(auto element : m_timeSyncs)
264  do_cleanup(element);
265 
266  m_intervals.clear();
267  m_states.clear();
268  m_events.clear();
269  m_timeSyncs.clear();
270  }
271 
272  ~HierarchicalScenarioComponent() { clear(); }
273 
274  template <typename elt_t>
275  void remove(const elt_t& element)
276  {
277  using map_t = MatchingComponent<elt_t, true>;
278  auto& container = this->*map_t::local_container;
279 
280  auto it = ossia::find_if(
281  container, [&](auto pair) { return &pair.element == &element; });
282 
283  if(it != container.end())
284  {
285  do_cleanup(*it);
286  container.erase(it);
287  }
288  }
289 
290 private:
291  template <typename T, bool dummy = true>
292  struct MatchingComponent;
293 
294  template <typename Pair_T>
295  void do_cleanup(const Pair_T& pair)
296  {
297  if constexpr(HasOwnership)
298  {
299  Component_T::removing(pair.element, pair.component);
300  pair.element.components().remove(pair.component);
301  }
302  else
303  {
304  auto t = Component_T::removing(pair.element, pair.component);
305  pair.element.components().erase(pair.component);
306  Component_T::removed(pair.element, pair.component, std::move(t));
307  }
308  }
309 
310  template <typename elt_t>
311  void setup()
312  {
313  using map_t = MatchingComponent<elt_t, true>;
314  auto&& member = map_t::scenario_container(Component_T::process());
315 
316  for(auto& elt : member)
317  {
318  add(elt);
319  }
320 
321  member.mutable_added.template connect<&HierarchicalScenarioComponent::add<elt_t>>(
322  this);
323  member.removing.template connect<&HierarchicalScenarioComponent::remove<elt_t>>(
324  this);
325  }
326 
327  template <typename elt_t>
328  void add(elt_t& element)
329  {
330 #if defined(SCORE_SERIALIZABLE_COMPONENTS)
331  using component_t = typename MatchingComponent<elt_t, true>::type;
332  constexpr bool is_serializable
333  = std::is_base_of<score::SerializableComponent, component_t>::value;
334  if constexpr(is_serializable)
335  {
336  using map_t = MatchingComponent<elt_t, true>;
337  using component_t = typename map_t::type;
338 
339  // Since the component may be serializable, we first look if
340  // we can deserialize it.
341  auto comp = score::deserialize_component<component_t>(
342  element.components(), [&](auto&& deserializer) {
343  Component_T::template load<component_t>(deserializer, element);
344  });
345 
346  // Maybe we could not deserialize it
347  if(!comp)
348  {
349  comp = Component_T::template make<component_t>(element);
350  }
351 
352  // We try to add it
353  if(comp)
354  {
355  element.components().add(comp);
356  (this->*map_t::local_container)
357  .emplace_back(typename map_t::pair_type{element, *comp});
358  }
359  }
360  else
361 #endif
362  {
363  // We can just create a new component directly
364  using map_t = MatchingComponent<elt_t, true>;
365  auto comp = Component_T::template make<typename map_t::type>(element);
366  if(comp)
367  {
368  element.components().add(comp);
369  (this->*map_t::local_container)
370  .emplace_back(typename map_t::pair_type{element, *comp});
371  }
372  }
373  }
374 
375  std::list<TimeSyncPair> m_timeSyncs;
376  std::list<EventPair> m_events;
377  std::list<StatePair> m_states;
378  std::list<IntervalPair> m_intervals;
379 
380  template <bool dummy>
381  struct MatchingComponent<Scenario::IntervalModel, dummy>
382  {
383  using type = IntervalComponent_T;
384  using pair_type = IntervalPair;
385  static const constexpr auto local_container
386  = &HierarchicalScenarioComponent::m_intervals;
387  static const constexpr auto scenario_container
389  };
390  template <bool dummy>
391  struct MatchingComponent<Scenario::EventModel, dummy>
392  {
393  using type = EventComponent_T;
394  using pair_type = EventPair;
395  static const constexpr auto local_container
396  = &HierarchicalScenarioComponent::m_events;
397  static const constexpr auto scenario_container
399  };
400  template <bool dummy>
401  struct MatchingComponent<Scenario::TimeSyncModel, dummy>
402  {
403  using type = TimeSyncComponent_T;
404  using pair_type = TimeSyncPair;
405  static const constexpr auto local_container
406  = &HierarchicalScenarioComponent::m_timeSyncs;
407  static const constexpr auto scenario_container
409  };
410  template <bool dummy>
411  struct MatchingComponent<Scenario::StateModel, dummy>
412  {
413  using type = StateComponent_T;
414  using pair_type = StatePair;
415  static const constexpr auto local_container
416  = &HierarchicalScenarioComponent::m_states;
417  static const constexpr auto scenario_container
419  };
420 };
421 
422 template <
423  typename Component_T, typename BaseScenario_T, typename IntervalComponent_T,
424  typename EventComponent_T, typename TimeSyncComponent_T, typename StateComponent_T>
426  : public Component_T
427  , public Nano::Observer
428 {
429 public:
431  {
433  Scenario::IntervalModel& element;
434  IntervalComponent_T& component;
435  };
436  struct EventPair
437  {
439  Scenario::EventModel& element;
440  EventComponent_T& component;
441  };
443  {
445  Scenario::TimeSyncModel& element;
446  TimeSyncComponent_T& component;
447  };
448  struct StatePair
449  {
451  Scenario::StateModel& element;
452  StateComponent_T& component;
453  };
454 
455  template <typename... Args>
456  HierarchicalBaseScenario(Args&&... args)
457  : Component_T{std::forward<Args>(args)...}
458  , m_timeSyncs{setup<Scenario::TimeSyncModel>(0), setup<Scenario::TimeSyncModel>(1)}
459  , m_events{setup<Scenario::EventModel>(0), setup<Scenario::EventModel>(1)}
460  , m_states{setup<Scenario::StateModel>(0), setup<Scenario::StateModel>(1)}
461  , m_intervals{setup<Scenario::IntervalModel>(0)}
462  {
463  }
464 
465  const auto& intervals() const { return m_intervals; }
466  const auto& events() const { return m_events; }
467  const auto& states() const { return m_states; }
468  const auto& timeSyncs() const { return m_timeSyncs; }
469 
470  void clear()
471  {
472  for(auto element : m_intervals)
473  cleanup(element);
474  for(auto element : m_states)
475  cleanup(element);
476  for(auto element : m_events)
477  cleanup(element);
478  for(auto element : m_timeSyncs)
479  cleanup(element);
480 
481  m_intervals.clear();
482  m_states.clear();
483  m_events.clear();
484  m_timeSyncs.clear();
485  }
486 
487  ~HierarchicalBaseScenario() { clear(); }
488 
489 private:
490  template <typename T, bool dummy = true>
491  struct MatchingComponent;
492 
493  template <typename Pair_T>
494  void cleanup(const Pair_T& pair)
495  {
496  Component_T::removing(pair.element, pair.component);
497  pair.element.components().remove(pair.component);
498  }
499 
500  template <typename elt_t>
501  auto setup(int pos)
502  {
503  using map_t = MatchingComponent<elt_t, true>;
504  auto&& member = map_t::scenario_container(this->process());
505 
506  return add(member[pos], pos);
507  }
508 
509  template <typename elt_t>
510  auto add(elt_t& element, int pos)
511  {
512  using map_t = MatchingComponent<elt_t, true>;
513  auto comp = Component_T::template make<typename map_t::type>(
514  getStrongId(element.components()), element);
515 
516  SCORE_ASSERT(comp);
517  element.components().add(comp);
518  return typename map_t::pair_type{element, *comp};
519  }
520 
521  template <typename elt_t>
522  void remove(const elt_t& element)
523  {
524  using map_t = MatchingComponent<elt_t, true>;
525  auto& container = this->*map_t::local_container;
526 
527  auto it = find_if(container, [&](auto pair) { return &pair.element == &element; });
528 
529  if(it != container.end())
530  {
531  cleanup(*it);
532  container.erase(it);
533  }
534  }
535 
536  std::list<TimeSyncPair> m_timeSyncs;
537  std::list<EventPair> m_events;
538  std::list<StatePair> m_states;
539  std::list<IntervalPair> m_intervals;
540 
541  template <bool dummy>
542  struct MatchingComponent<Scenario::IntervalModel, dummy>
543  {
544  using type = IntervalComponent_T;
545  using pair_type = IntervalPair;
546  static const constexpr auto local_container = &HierarchicalBaseScenario::m_intervals;
547  static const constexpr auto scenario_container
549  };
550  template <bool dummy>
551  struct MatchingComponent<Scenario::EventModel, dummy>
552  {
553  using type = EventComponent_T;
554  using pair_type = EventPair;
555  static const constexpr auto local_container = &HierarchicalBaseScenario::m_events;
556  static const constexpr auto scenario_container
558  };
559  template <bool dummy>
560  struct MatchingComponent<Scenario::TimeSyncModel, dummy>
561  {
562  using type = TimeSyncComponent_T;
563  using pair_type = TimeSyncPair;
564  static const constexpr auto local_container = &HierarchicalBaseScenario::m_timeSyncs;
565  static const constexpr auto scenario_container
567  };
568  template <bool dummy>
569  struct MatchingComponent<Scenario::StateModel, dummy>
570  {
571  using type = StateComponent_T;
572  using pair_type = StatePair;
573  static const constexpr auto local_container = &HierarchicalBaseScenario::m_states;
574  static const constexpr auto scenario_container
576  };
577 };
Definition: Scenario/Document/Components/ScenarioComponent.hpp:428
Definition: Scenario/Document/Components/ScenarioComponent.hpp:198
HierarchicalScenarioComponent(Args &&... args)
The default constructor will also initialize the children.
Definition: Scenario/Document/Components/ScenarioComponent.hpp:227
void init()
Do not forget to call this when using the lazy constructor.
Definition: Scenario/Document/Components/ScenarioComponent.hpp:242
HierarchicalScenarioComponent(score::lazy_init_t, Args &&... args)
Definition: Scenario/Document/Components/ScenarioComponent.hpp:236
Definition: EventModel.hpp:36
Definition: IntervalModel.hpp:50
Definition: StateModel.hpp:63
Definition: TimeSyncModel.hpp:35
Definition: Scenario/Document/Components/ScenarioComponent.hpp:26
SimpleHierarchicalScenarioComponent(Args &&... args)
The default constructor will also initialize the children.
Definition: Scenario/Document/Components/ScenarioComponent.hpp:37
void init()
Do not forget to call this when using the lazy constructor.
Definition: Scenario/Document/Components/ScenarioComponent.hpp:52
SimpleHierarchicalScenarioComponent(score::lazy_init_t, Args &&... args)
Definition: Scenario/Document/Components/ScenarioComponent.hpp:46
Main plug-in of score.
Definition: score-plugin-dataflow/Dataflow/PortItem.hpp:14
Definition: Scenario/Document/Components/ScenarioComponent.hpp:437
Definition: Scenario/Document/Components/ScenarioComponent.hpp:431
Definition: Scenario/Document/Components/ScenarioComponent.hpp:449
Definition: Scenario/Document/Components/ScenarioComponent.hpp:443
Definition: Scenario/Document/Components/ScenarioComponent.hpp:207
Definition: Scenario/Document/Components/ScenarioComponent.hpp:201
Definition: Scenario/Document/Components/ScenarioComponent.hpp:219
Definition: Scenario/Document/Components/ScenarioComponent.hpp:213
Definition: ScenarioInterface.hpp:55
Definition: Scenario/Document/Components/ScenarioComponent.hpp:29
Definition: lib/score/model/Component.hpp:16