MayaFlux 1.0.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
NodeQuery.cpp
Go to the documentation of this file.
1#include "Inspector.hpp"
2
9
11
12namespace {
13
14 std::string_view role_label(Nodes::ModulatorRole role)
15 {
16 switch (role) {
18 return "freq";
20 return "amp";
22 return "sig";
24 return "lhs";
26 return "rhs";
28 return "->";
29 default:
30 return "mod";
31 }
32 }
33
34} // namespace
35
37 const Nodes::ModulatorTree& tree,
38 Surface& surface,
39 LayoutCursor& cursor,
40 float x_min, float x_max, float row_h, int depth)
41{
42 const float ind = x_min + static_cast<float>(depth) * k_inspect_indent;
43
44 const std::string header_label = std::string(role_label(tree.role))
46
47 auto node_ref = tree.node;
48 std::vector<EntrySpec> entrys {
49 EntrySpec {
50 .label = "out",
51 .reader = [node_ref] { return std::to_string(node_ref->get_last_output()); },
52 },
53 };
54
55 auto hbuf = make_header_buffer(surface.window());
56 auto rbufs = make_row_buffers(surface.window(), entrys.size());
57
58 auto group = make_entry_group(entrys, header_label, std::move(hbuf), rbufs,
59 surface, cursor, ind, x_max, row_h, false);
60
61 InspectResult result;
62 result.group = std::move(group);
63
64 for (const auto& child : tree.modulators) {
65 auto child_result = inspect_modulator_tree(
66 child, surface, cursor,
67 x_min, x_max, row_h, depth + 1);
68 surface.layer().relate(
69 result.group.header.header_id,
70 child_result.group.header.header_id);
71 result.children.push_back(std::move(child_result));
72 }
73
74 return result;
75}
76
77// -----------------------------------------------------------------------------
78// Single node
79// -----------------------------------------------------------------------------
80
82 const std::shared_ptr<Nodes::Node>& n,
83 Surface& surface,
84 LayoutCursor& cursor,
85 float x_min, float x_max, float row_h, int depth)
86{
87 const float ind = x_min + static_cast<float>(depth) * k_inspect_indent;
88 const std::string header_label = Reflect::short_dynamic_type_name(*n);
89
90 auto node_ref = n;
91 std::vector<EntrySpec> entrys {
92 EntrySpec {
93 .label = "out",
94 .reader = [node_ref] { return std::to_string(node_ref->get_last_output()); },
95 },
96 };
97
98 auto hbuf = make_header_buffer(surface.window());
99 auto rbufs = make_row_buffers(surface.window(), entrys.size());
100
101 auto group = make_entry_group(entrys, header_label, std::move(hbuf), rbufs,
102 surface, cursor, ind, x_max, row_h, false);
103
104 InspectResult result;
105 result.group = std::move(group);
106
107 for (const auto& tree : n->get_modulator_tree()) {
108 auto child = inspect_modulator_tree(
109 tree, surface, cursor,
110 x_min, x_max, row_h, depth + 1);
111 surface.layer().relate(
112 result.group.header.header_id,
113 child.group.header.header_id);
114 result.children.push_back(std::move(child));
115 }
116
117 return result;
118}
119
120// -----------------------------------------------------------------------------
121// RootNode: single channel
122// -----------------------------------------------------------------------------
123
125 Nodes::ProcessingToken token, uint32_t channel,
126 Surface& surface,
127 LayoutCursor& cursor,
128 float x_min, float x_max, float row_h, int depth)
129{
130 auto& root = m_ngm.get_root_node(token, channel);
131
132 const float ind = x_min + static_cast<float>(depth) * k_inspect_indent;
133 const std::string header_label = token == Nodes::ProcessingToken::AUDIO_RATE
134 ? "root [ch " + std::to_string(channel) + "]"
135 : "root";
136
137 std::vector<EntrySpec> entrys {
138 EntrySpec {
139 .label = "nodes",
140 .reader = [&root] { return std::to_string(root.get_node_size()); },
141 },
142 };
143
144 auto hbuf = make_header_buffer(surface.window());
145 auto rbufs = make_row_buffers(surface.window(), entrys.size());
146
147 auto group = make_entry_group(entrys, header_label, std::move(hbuf), rbufs,
148 surface, cursor, ind, x_max, row_h, false);
149
150 InspectResult result;
151 result.group = std::move(group);
152
153 for (const auto& n : root.nodes()) {
154 if (!n)
155 continue;
156 auto node_result = node(
157 n, surface, cursor,
158 x_min, x_max, row_h, depth + 1);
159 surface.layer().relate(result.group.header.header_id, node_result.group.header.header_id);
160 result.children.push_back(std::move(node_result));
161 }
162
163 return result;
164}
165
166// -----------------------------------------------------------------------------
167// RootNode: all channels (or single root for non-audio tokens)
168// -----------------------------------------------------------------------------
169
172 Surface& surface,
173 LayoutCursor& cursor,
174 float x_min, float x_max, float row_h, int depth)
175{
177 return root_node(token, 0, surface, cursor, x_min, x_max, row_h, depth);
178
179 auto channels = m_ngm.get_all_channels(token);
180 std::ranges::sort(channels);
181
182 const float ind = x_min + static_cast<float>(depth) * k_inspect_indent;
183 const std::string header_label = "root [" + std::to_string(channels.size()) + " ch]";
184
185 auto& ngm = m_ngm;
186 std::vector<EntrySpec> entrys {
187 EntrySpec {
188 .label = "channels",
189 .reader = [&ngm, token] { return std::to_string(ngm.get_all_channels(token).size()); },
190 },
191 };
192
193 auto hbuf = make_header_buffer(surface.window());
194 auto rbufs = make_row_buffers(surface.window(), entrys.size());
195 auto group = make_entry_group(entrys, header_label, std::move(hbuf), rbufs,
196 surface, cursor, ind, x_max, row_h, false);
197
198 InspectResult result;
199 result.group = std::move(group);
200
201 for (const auto ch : channels) {
202 auto ch_result = root_node(token, ch, surface, cursor, x_min, x_max, row_h, depth + 1);
203 surface.layer().relate(result.group.header.header_id, ch_result.group.header.header_id);
204 result.children.push_back(std::move(ch_result));
205 }
206 return result;
207}
208// -----------------------------------------------------------------------------
209// Single network
210// -----------------------------------------------------------------------------
211
213 const std::shared_ptr<Nodes::Network::NodeNetwork>& net,
214 Surface& surface,
215 LayoutCursor& cursor,
216 float x_min, float x_max, float row_h, int depth)
217{
218 const float ind = x_min + static_cast<float>(depth) * k_inspect_indent;
219
220 const std::string header_label
221 = std::string(Reflect::enum_to_string(net->get_topology()))
222 + " / "
223 + std::string(Reflect::enum_to_string(net->get_output_mode()));
224
225 auto net_ref = net;
226 std::vector<EntrySpec> entrys {
227 EntrySpec {
228 .label = "nodes",
229 .reader = [net_ref] { return std::to_string(net_ref->get_node_count()); },
230 },
231 EntrySpec {
232 .label = "enabled",
233 .reader = [net_ref] { return net_ref->is_enabled() ? "true" : "false"; },
234 },
235 EntrySpec {
236 .label = "channels",
237 .reader = [net_ref] {
238 const auto ch = net_ref->get_registered_channels();
239 std::string s;
240 for (size_t i = 0; i < ch.size(); ++i) {
241 if (i)
242 s += ',';
243 s += std::to_string(ch[i]);
244 }
245 return s.empty() ? "-" : s;
246 },
247 },
248 };
249
250 auto hbuf = make_header_buffer(surface.window());
251 auto rbufs = make_row_buffers(surface.window(), entrys.size());
252
253 auto group = make_entry_group(entrys, header_label, std::move(hbuf), rbufs,
254 surface, cursor, ind, x_max, row_h, false);
255
256 InspectResult result;
257 result.group = std::move(group);
258 return result;
259}
260
261// -----------------------------------------------------------------------------
262// NodeGraphManager
263// -----------------------------------------------------------------------------
264
266 Surface& surface,
267 LayoutCursor& cursor,
268 float x_min, float x_max, float row_h)
269{
271 return *m_node_graph_result;
272 }
273
274 const auto tokens = m_ngm.get_active_tokens();
275
276 const std::string root_label = "NodeGraphManager ["
277 + std::to_string(tokens.size()) + " token"
278 + (tokens.size() == 1 ? "" : "s") + "]";
279
280 auto& ngm = m_ngm;
281 std::vector<EntrySpec> root_entrys {
282 EntrySpec {
283 .label = "tokens",
284 .reader = [&ngm] { return std::to_string(ngm.get_active_tokens().size()); },
285 },
286 };
287
288 auto hbuf = make_header_buffer(surface.window());
289 auto rbufs = make_row_buffers(surface.window(), root_entrys.size());
290
291 auto root_group = make_entry_group(root_entrys, root_label, std::move(hbuf), rbufs,
292 surface, cursor, x_min, x_max, row_h, false);
293
294 InspectResult& result = m_node_graph_result.emplace();
295 result.group = std::move(root_group);
296
297 for (const auto tok : tokens) {
298 const std::string tok_label = std::string(Reflect::enum_to_string(tok));
299 const bool multichannel = tok == Nodes::ProcessingToken::AUDIO_RATE;
300 auto channels = m_ngm.get_all_channels(tok);
301 if (multichannel)
302 std::ranges::sort(channels);
303
304 std::vector<EntrySpec> tok_entrys {
305 EntrySpec {
306 .label = "nodes",
307 .reader = [&ngm, tok] { return std::to_string(ngm.get_node_count(tok)); },
308 },
309 EntrySpec {
310 .label = "networks",
311 .reader = [&ngm, tok] { return std::to_string(ngm.get_network_count(tok)); },
312 },
313 };
314
315 auto tok_hbuf = make_header_buffer(surface.window());
316 auto tok_rbufs = make_row_buffers(surface.window(), tok_entrys.size());
317
318 auto tok_group = make_entry_group(tok_entrys, tok_label, std::move(tok_hbuf), tok_rbufs,
319 surface, cursor, x_min + k_inspect_indent, x_max, row_h, false);
320
321 InspectResult tok_result;
322 tok_result.group = std::move(tok_group);
323 surface.layer().relate(result.group.header.header_id, tok_result.group.header.header_id);
324
325 // ----- Networks section -----
326 {
327 auto net_hbuf = make_header_buffer(surface.window());
328 auto net_group = make_entry_group({}, "Networks", std::move(net_hbuf), {},
329 surface, cursor, x_min + 2.F * k_inspect_indent, x_max, row_h, false);
330
331 InspectResult net_section;
332 net_section.group = std::move(net_group);
333 surface.layer().relate(tok_result.group.header.header_id, net_section.group.header.header_id);
334
335 if (multichannel) {
336 for (const auto ch : channels) {
337 auto ch_hbuf = make_header_buffer(surface.window());
338 auto ch_group = make_entry_group({}, "ch " + std::to_string(ch), std::move(ch_hbuf), {},
339 surface, cursor, x_min + 3.F * k_inspect_indent, x_max, row_h, false);
340
341 InspectResult ch_result;
342 ch_result.group = std::move(ch_group);
343 surface.layer().relate(net_section.group.header.header_id, ch_result.group.header.header_id);
344
345 for (const auto& net : m_ngm.get_networks(tok, ch)) {
346 if (!net)
347 continue;
348 auto nr = node_network(net, surface, cursor, x_min, x_max, row_h, 4);
349 surface.layer().relate(ch_result.group.header.header_id, nr.group.header.header_id);
350 ch_result.children.push_back(std::move(nr));
351 }
352
353 net_section.children.push_back(std::move(ch_result));
354 }
355 } else {
356 for (const auto& net : m_ngm.get_networks(tok, 0)) {
357 if (!net)
358 continue;
359 auto nr = node_network(net, surface, cursor, x_min, x_max, row_h, 3);
360 surface.layer().relate(net_section.group.header.header_id, nr.group.header.header_id);
361 net_section.children.push_back(std::move(nr));
362 }
363 }
364
365 tok_result.children.push_back(std::move(net_section));
366 }
367
368 // ----- Nodes section -----
369 {
370 auto nodes_hbuf = make_header_buffer(surface.window());
371 auto nodes_group = make_entry_group({}, "Nodes", std::move(nodes_hbuf), {},
372 surface, cursor, x_min + 2.F * k_inspect_indent, x_max, row_h, false);
373
374 InspectResult nodes_section;
375 nodes_section.group = std::move(nodes_group);
376 surface.layer().relate(tok_result.group.header.header_id, nodes_section.group.header.header_id);
377
378 if (multichannel) {
379 for (const auto ch : channels) {
380 auto rn = root_node(tok, ch, surface, cursor, x_min, x_max, row_h, 3);
381 surface.layer().relate(nodes_section.group.header.header_id, rn.group.header.header_id);
382 nodes_section.children.push_back(std::move(rn));
383 }
384 } else {
385 auto rn = root_node(tok, 0, surface, cursor, x_min, x_max, row_h, 3);
386 surface.layer().relate(nodes_section.group.header.header_id, rn.group.header.header_id);
387 nodes_section.children.push_back(std::move(rn));
388 }
389
390 tok_result.children.push_back(std::move(nodes_section));
391 }
392
393 result.children.push_back(std::move(tok_result));
394 }
395
396 return result;
397}
398
399} // namespace MayaFlux::Portal::Forma
uint32_t channels
uint32_t depth
RootNode & get_root_node(ProcessingToken token, unsigned int channel)
Gets or creates the root node for a specific token and channel.
std::vector< ProcessingToken > get_active_tokens() const
Gets all currently active processing tokens (domains)
std::vector< std::shared_ptr< Network::NodeNetwork > > get_networks(ProcessingToken token, uint32_t channel=0) const
Get all networks for a specific token.
std::vector< unsigned int > get_all_channels(ProcessingToken token) const
Gets all channel indices for a given processing token.
std::shared_ptr< Buffers::FormaBuffer > make_header_buffer(const std::shared_ptr< Core::Window > &window) const
A "text"-slotted buffer, registered with the BufferManager.
Definition Inspector.cpp:11
Nodes::NodeGraphManager & m_ngm
InspectResult inspect_modulator_tree(const Nodes::ModulatorTree &tree, Surface &surface, LayoutCursor &cursor, float x_min, float x_max, float row_h, int depth)
Definition NodeQuery.cpp:36
std::vector< EntryBuffer > make_row_buffers(const std::shared_ptr< Core::Window > &window, size_t count) const
count row targets, slices of one "text"-slotted buffer, for make_entry_group's rows.
Definition Inspector.cpp:24
std::optional< InspectResult > m_node_graph_result
InspectResult & node_graph_manager(Surface &surface, LayoutCursor &cursor, float x_min=-0.95F, float x_max=0.95F, float row_h=0.05F)
Inspect the full NodeGraphManager state across all active tokens.
InspectResult node_network(const std::shared_ptr< Nodes::Network::NodeNetwork > &net, Surface &surface, LayoutCursor &cursor, float x_min=-0.95F, float x_max=0.95F, float row_h=0.05F, int depth=0)
Inspect a NodeNetwork and its per-network metadata.
InspectResult root_node(Nodes::ProcessingToken token, uint32_t channel, Surface &surface, LayoutCursor &cursor, float x_min=-0.95F, float x_max=0.95F, float row_h=0.05F, int depth=0)
Inspect a single RootNode for a specific token and channel.
InspectResult node(const std::shared_ptr< Nodes::Node > &n, Surface &surface, LayoutCursor &cursor, float x_min=-0.95F, float x_max=0.95F, float row_h=0.05F, int depth=0)
Inspect a single Node and its full modulator tree.
Definition NodeQuery.cpp:81
bool relate(uint32_t primary_id, uint32_t related_id)
Record that related_id belongs with primary_id.
Definition Layer.cpp:205
Reactive Y-position accumulator for vertical primitive stacking.
const std::shared_ptr< Core::Window > & window() const noexcept
Access the rendering target window.
Definition Surface.hpp:178
Layer & layer() noexcept
Access the spatial registry.
Definition Surface.hpp:159
Named owner of a (Window, Layer, Context) triple: the Forma canvas.
Definition Surface.hpp:121
ProcessingToken
Enumerates the different processing domains for nodes.
@ AUDIO_RATE
Nodes that process at the audio sample rate.
ModulatorRole
Describes the role a modulator node plays relative to its owner.
Definition Node.hpp:21
EntryGroup make_entry_group(std::span< const EntrySpec > entrys, std::string_view header_label, FormaTarget header_buf, std::span< const EntryBuffer > row_bufs, Surface &surface, LayoutCursor &cursor, float x_min, float x_max, float row_h, bool initially_open)
Construct a collapsible header followed by N entry rows under it.
Definition Entry.cpp:104
constexpr float k_inspect_indent
constexpr std::string_view enum_to_string(EnumType value) noexcept
Universal enum to string converter using magic_enum (original case)
std::string short_dynamic_type_name(const T &obj) noexcept
Returns the unqualified dynamic type name of obj.
Definition TypeInfo.hpp:95
std::vector< ModulatorTree > modulators
Definition Node.hpp:37
std::shared_ptr< Node > node
Definition Node.hpp:36
Recursive tree node describing a modulator and all of its own modulators.
Definition Node.hpp:34
uint32_t header_id
Element id of the header strip. Valid after place().
A single entry to display in a EntryGroup body row.
Definition Entry.hpp:29
std::vector< InspectResult > children
Result of an introspect call.