Loading...
Searching...
No Matches
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
20template <
21 typename Component_T, typename Scenario_T, typename IntervalComponent_T,
22 bool HasOwnership = true>
24 : public Component_T
25 , public Nano::Observer
26{
27public:
29 {
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
82private:
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
191template <
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{
199public:
201 {
204 IntervalComponent_T& component;
205 };
207 {
209 Scenario::EventModel& element;
210 EventComponent_T& component;
211 };
213 {
216 TimeSyncComponent_T& component;
217 };
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
290private:
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
422template <
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{
429public:
431 {
434 IntervalComponent_T& component;
435 };
437 {
439 Scenario::EventModel& element;
440 EventComponent_T& component;
441 };
443 {
446 TimeSyncComponent_T& component;
447 };
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
489private:
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:34
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:13
STL namespace.
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