Loading...
Searching...
No Matches
score-plugin-nodal/Nodal/Executor.hpp
1#pragma once
2#include <Process/Execution/ProcessComponent.hpp>
3
4#include <Nodal/Process.hpp>
5
6#include <score/model/ComponentHierarchy.hpp>
7
8#include <ossia/dataflow/node_process.hpp>
9#include <ossia/detail/hash_map.hpp>
10namespace Nodal
11{
13 : public Execution::ProcessComponent_T<Nodal::Model, ossia::node_process>
14{
15 COMPONENT_METADATA("e85e0114-2a7e-4569-8a1d-f00c9fd22960")
16public:
21
22 NodalExecutorBase(Model& element, const Execution::Context& ctx, QObject* parent);
23
25
27 {
28 std::shared_ptr<Execution::ProcessComponent> comp;
29 };
30
31 ossia::hash_map<Id<Process::ProcessModel>, RegisteredNode> m_nodes;
32
35
36 ::Execution::ProcessComponent* make(Process::ProcessModel& process) { return nullptr; }
37 void added(::Execution::ProcessComponent& e);
38
39 std::function<void()>
41
42 template <typename Component_T, typename Element, typename Fun>
43 void removed(const Element& elt, const Component_T& comp, Fun f)
44 {
45 if(f)
46 f();
47 }
48
49 template <typename Models>
50 auto& models() const
51 {
52 static_assert(
53 std::is_same<Models, Process::ProcessModel>::value,
54 "Node component must be passed Process::ProcessModel as child.");
55
56 return process().nodes;
57 }
58
59private:
60 void reg(const RegisteredNode& fx, Execution::Transaction& vec);
61 void unreg(const RegisteredNode& fx, Execution::Transaction& vec);
62};
63
65 : public NodalExecutorBase
66 , public Nano::Observer
67{
68public:
74
75 struct ChildPair
76 {
78 : model{m}
79 , component{c}
80 {
81 }
82 ChildModel_T* model{};
83 ChildComponent_T* component{};
84 };
85
86 template <typename... Args>
87 HierarchyManager(Args&&... args)
88 : ParentComponent_T{std::forward<Args>(args)...}
89 , m_componentFactory{
90 score::AppComponents().template interfaces<ChildComponentFactoryList_T>()}
91 {
92 init_hierarchy();
93 }
94
95 void init_hierarchy()
96 {
97 auto& child_models = process().nodes;
98 for(auto& child_model : child_models)
99 {
100 add(child_model);
101 }
102
103 child_models.mutable_added.template connect<&hierarchy_t::add>(this);
104
105 child_models.removing.template connect<&hierarchy_t::remove>(this);
106 }
107
108 const auto& children() const { return m_children; }
109
110 void add(Process::ProcessModel& model)
111 {
112 // Will return a factory for the given process if available
113 if(auto factory = m_componentFactory.factory(model))
114 {
115 // The subclass should provide this function to construct
116 // the correct component relative to this process.
117 auto comp = this->make(*factory, model);
118 if(comp)
119 {
120 model.components().add(comp);
121 m_children.emplace_back(ChildPair{&model, comp});
122 this->added(*comp);
123 }
124 }
125 else
126 {
127 auto comp = ParentComponent_T::make(model);
128 if(comp)
129 {
130 model.components().add(comp);
131 m_children.emplace_back(ChildPair{&model, comp});
132 ParentComponent_T::added(*comp);
133 }
134 }
135 }
136
137 void remove(const ChildModel_T& model)
138 {
139 auto it
140 = ossia::find_if(m_children, [&](auto pair) { return pair.model == &model; });
141
142 if(it != m_children.end())
143 {
144 do_cleanup(*it);
145 m_children.erase(it);
146 }
147 }
148
149 void clear()
150 {
151 for(const auto& element : m_children)
152 {
153 do_cleanup(element);
154 }
155 m_children.clear();
156 }
157
158 ~HierarchyManager() { clear(); }
159
160private:
161 void do_cleanup(const ChildPair& pair)
162 {
163 auto t = ParentComponent_T::removing(*pair.model, *pair.component);
164 pair.model->components().erase(*pair.component);
165 ParentComponent_T::removed(*pair.model, *pair.component, std::move(t));
166 }
167
168 const ChildComponentFactoryList_T& m_componentFactory;
169
170 std::vector<ChildPair> m_children; // todo map ? multi_index with both index
171 // of the component and of the process ?
172};
173
174class NodalExecutor final : public HierarchyManager
175{
176public:
177 NodalExecutor(Nodal::Model& element, const ::Execution::Context& ctx, QObject* parent)
178 : HierarchyManager{element, ctx, parent}
179 {
180 // TODO passthrough ?
181 }
182
183 void cleanup() override;
184
185 NodalExecutor(const NodalExecutor&) = delete;
186 NodalExecutor(NodalExecutor&&) = delete;
187 NodalExecutor& operator=(const NodalExecutor&) = delete;
188 NodalExecutor& operator=(NodalExecutor&&) = delete;
190};
191
194}
Definition Process/Execution/ProcessComponent.hpp:119
Definition Process/Execution/ProcessComponent.hpp:102
Definition Process/Execution/ProcessComponent.hpp:154
Definition Process/Execution/ProcessComponent.hpp:48
Definition score-plugin-nodal/Nodal/Executor.hpp:67
Definition score-plugin-nodal/Nodal/Process.hpp:14
Definition score-plugin-nodal/Nodal/Executor.hpp:14
Definition score-plugin-nodal/Nodal/Executor.hpp:175
The Process class.
Definition score-lib-process/Process/Process.hpp:61
A component that has a reference to a specific context object.
Definition lib/score/model/Component.hpp:58
Base toolkit upon which the software is built.
Definition Application.cpp:90
STL namespace.
Definition ExecutionContext.hpp:76
Definition Process/Execution/ProcessComponent.hpp:89
Definition ExecutionTransaction.hpp:18
Definition score-plugin-nodal/Nodal/Executor.hpp:76
Definition score-plugin-nodal/Nodal/Executor.hpp:27