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};
62
64 : public NodalExecutorBase
65 , public Nano::Observer
66{
67public:
73
74 struct ChildPair
75 {
77 : model{m}
78 , component{c}
79 {
80 }
81 ChildModel_T* model{};
82 ChildComponent_T* component{};
83 };
84
85 template <typename... Args>
86 HierarchyManager(Args&&... args)
87 : ParentComponent_T{std::forward<Args>(args)...}
88 , m_componentFactory{
89 score::AppComponents().template interfaces<ChildComponentFactoryList_T>()}
90 {
91 init_hierarchy();
92 }
93
94 void init_hierarchy()
95 {
96 auto& child_models = process().nodes;
97 for(auto& child_model : child_models)
98 {
99 add(child_model);
100 }
101
102 child_models.mutable_added.template connect<&hierarchy_t::add>(this);
103
104 child_models.removing.template connect<&hierarchy_t::remove>(this);
105 }
106
107 const auto& children() const { return m_children; }
108
109 void add(Process::ProcessModel& model)
110 {
111 // Will return a factory for the given process if available
112 if(auto factory = m_componentFactory.factory(model))
113 {
114 // The subclass should provide this function to construct
115 // the correct component relative to this process.
116 auto comp = this->make(*factory, model);
117 if(comp)
118 {
119 model.components().add(comp);
120 m_children.emplace_back(ChildPair{&model, comp});
121 this->added(*comp);
122 }
123 }
124 else
125 {
126 auto comp = ParentComponent_T::make(model);
127 if(comp)
128 {
129 model.components().add(comp);
130 m_children.emplace_back(ChildPair{&model, comp});
131 ParentComponent_T::added(*comp);
132 }
133 }
134 }
135
136 void remove(const ChildModel_T& model)
137 {
138 auto it
139 = ossia::find_if(m_children, [&](auto pair) { return pair.model == &model; });
140
141 if(it != m_children.end())
142 {
143 do_cleanup(*it);
144 m_children.erase(it);
145 }
146 }
147
148 void clear()
149 {
150 for(const auto& element : m_children)
151 {
152 do_cleanup(element);
153 }
154 m_children.clear();
155 }
156
157 ~HierarchyManager() { clear(); }
158
159private:
160 void do_cleanup(const ChildPair& pair)
161 {
162 auto t = ParentComponent_T::removing(*pair.model, *pair.component);
163 pair.model->components().erase(*pair.component);
164 ParentComponent_T::removed(*pair.model, *pair.component, std::move(t));
165 }
166
167 const ChildComponentFactoryList_T& m_componentFactory;
168
169 std::vector<ChildPair> m_children; // todo map ? multi_index with both index
170 // of the component and of the process ?
171};
172
173class NodalExecutor final : public HierarchyManager
174{
175public:
176 NodalExecutor(Nodal::Model& element, const ::Execution::Context& ctx, QObject* parent)
177 : HierarchyManager{element, ctx, parent}
178 {
179 // TODO passthrough ?
180 }
181
182 void cleanup() override;
183
184 NodalExecutor(const NodalExecutor&) = delete;
185 NodalExecutor(NodalExecutor&&) = delete;
186 NodalExecutor& operator=(const NodalExecutor&) = delete;
187 NodalExecutor& operator=(NodalExecutor&&) = delete;
189};
190
193}
Definition Process/Execution/ProcessComponent.hpp:131
Definition Process/Execution/ProcessComponent.hpp:114
Definition Process/Execution/ProcessComponent.hpp:166
Definition Process/Execution/ProcessComponent.hpp:48
Definition score-plugin-nodal/Nodal/Executor.hpp:66
Definition score-plugin-nodal/Nodal/Process.hpp:15
Definition score-plugin-nodal/Nodal/Executor.hpp:14
Definition score-plugin-nodal/Nodal/Executor.hpp:174
The Process class.
Definition score-lib-process/Process/Process.hpp:80
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:108
STL namespace.
Definition ExecutionContext.hpp:201
Definition Process/Execution/ProcessComponent.hpp:101
Definition ExecutionTransaction.hpp:21
Definition score-plugin-nodal/Nodal/Executor.hpp:75
Definition score-plugin-nodal/Nodal/Executor.hpp:27