MayaFlux 1.0.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
Creator.hpp
Go to the documentation of this file.
1#pragma once
2
3#include "Domain.hpp"
4#include "Evolve.hpp"
5#include "Mint.hpp"
6#include "Registry.hpp"
7
11
12namespace MayaFlux {
13
14namespace Core {
15 class VKImage;
16}
17
18namespace Kakshya {
19 class VideoStreamContainer;
20}
21
22namespace IO {
23 using TextureResolver = std::function<std::shared_ptr<Core::VKImage>(const std::string& path)>;
24 struct CameraConfig;
25}
26
28 std::optional<Domain> domain;
29 std::optional<uint32_t> channel;
30 std::optional<std::vector<uint32_t>> channels;
31
32 CreationContext() = default;
34 : domain(d)
35 {
36 }
37 CreationContext(Domain d, uint32_t ch)
38 : domain(d)
39 , channel(ch)
40 {
41 }
42 CreationContext(Domain d, std::vector<uint32_t> ch)
43 : domain(d)
44 , channels(std::move(ch))
45 {
46 }
47 CreationContext(uint32_t ch)
48 : channel(ch)
49 {
50 }
51 CreationContext(std::vector<uint32_t> ch)
52 : channels(std::move(ch))
53 {
54 }
55};
56
57MAYAFLUX_API void register_node(const std::shared_ptr<Nodes::Node>& node, const CreationContext& ctx);
58MAYAFLUX_API void register_network(const std::shared_ptr<Nodes::Network::NodeNetwork>& network, const CreationContext& ctx);
59MAYAFLUX_API void register_buffer(const std::shared_ptr<Buffers::Buffer>& buffer, const CreationContext& ctx);
60MAYAFLUX_API void register_container(const std::shared_ptr<Kakshya::SoundFileContainer>& container, const Domain& domain);
61MAYAFLUX_API void register_container(const std::shared_ptr<Kakshya::VideoStreamContainer>& container, const Domain& domain);
62
63/**
64 * @brief Thin domain wrapper that adds subscript channel-binding syntax.
65 *
66 * Audio[0] and Audio[{0,1}] produce a CreationContext consumed immediately
67 * by operator|. Implicit conversion to Domain keeps all existing call sites
68 * that accept a plain Domain parameter working without change.
69 */
70struct DomainSpec {
72
73 /** @brief Bind a single channel to this domain. */
74 [[nodiscard]] CreationContext operator[](uint32_t ch) const
75 {
76 return { value, ch };
77 }
78
79 /** @brief Bind multiple channels to this domain. */
80 [[nodiscard]] CreationContext operator[](std::initializer_list<uint32_t> chs) const
81 {
82 return { value, std::vector<uint32_t>(chs) };
83 }
84
85 /** @brief Implicit decay to Domain for call sites that accept Domain directly. */
86 operator Domain() const { return value; }
87
88 /** @brief Implicit decay to CreationContext for bare ptr | Audio usage. */
89 operator CreationContext() const { return { value }; }
90};
91
92class MAYAFLUX_API MeshGroupHandle {
93public:
94 explicit MeshGroupHandle(std::vector<std::shared_ptr<Buffers::MeshBuffer>> buffers);
96
98
99 auto begin() { return m_buffers.begin(); }
100 auto end() { return m_buffers.end(); }
101 [[nodiscard]] auto begin() const { return m_buffers.begin(); }
102 [[nodiscard]] auto end() const { return m_buffers.end(); }
103
104 [[nodiscard]] bool empty() const { return m_buffers.empty(); }
105 [[nodiscard]] size_t size() const { return m_buffers.size(); }
106
107 std::shared_ptr<Buffers::MeshBuffer>& operator[](size_t i) { return m_buffers[i]; }
108
109private:
110 std::vector<std::shared_ptr<Buffers::MeshBuffer>> m_buffers;
111};
112
113class MAYAFLUX_API Creator {
114public:
115 /**
116 * @brief Sets a system going from a config: state that persists, a rule
117 * that advances it every cycle, and rendering attached.
118 *
119 * Overloaded on the config it is given: RelaxationGridBuffer::GridConfig
120 * (optionally with a seed callable), VolumeGridBuffer::FlowConfig over a
121 * volume, or SpatialFieldConfig over a field-compatible network. Each call
122 * performs the whole sequence and returns the real object, which then
123 * advances on its own each cycle. The call sets it going and does not step
124 * it. Every call requires RenderConfig::target_window.
125 *
126 * @code
127 * auto life = vega.evolve(grid_config, seed, { .target_window = window });
128 * auto smoke = vega.evolve(volume, flow_config, { .target_window = window });
129 * @endcode
130 *
131 * @see Evolve
132 */
134
135 /**
136 * @brief Builds a visible structure from a StructureConfig: resolves its
137 * source, constructs and registers what it needs, and attaches
138 * rendering.
139 *
140 * Overloaded on the arrangement: StructureConfig::Object, Model, Instances,
141 * Assembly or Isosurface. Each call returns the real buffer. For Object,
142 * Model and Instances the node or network is reached through the buffer's
143 * get_node or get_network. Mint builds form and does not advance state,
144 * which is what evolve is for. Every config requires
145 * RenderConfig::target_window.
146 *
147 * @code
148 * auto form = vega.mint(StructureConfig::Object {
149 * .mesh = mesh,
150 * .render = { .target_window = window } });
151 * @endcode
152 *
153 * @see Mint
154 * @see StructureConfig
155 */
157
158#include "Generated/CreatorDeclarations.inc"
159
160 auto read_audio(const std::string& filepath) -> std::shared_ptr<Kakshya::SoundFileContainer>
161 {
162 auto container = load_sound_container(filepath);
163 MF_LIVE_EXPOSE_AUTO(container);
164 return container;
165 }
166
167 auto read_audio() -> std::shared_ptr<Kakshya::SoundFileContainer>
168 {
169 auto container = choose_audio();
170 if (container)
171 MF_LIVE_EXPOSE_AUTO(container);
172 return container;
173 }
174
175 auto read_image(const std::string& filepath,
176 int desired_channels = 4,
177 std::optional<Kakshya::Region> region = std::nullopt)
178 -> std::shared_ptr<Buffers::TextureBuffer>
179 {
180 auto buffer = load_image_buffer(filepath, desired_channels, std::move(region));
182 return buffer;
183 }
184
185 auto read_image(int desired_channels = 4,
186 std::optional<Kakshya::Region> region = std::nullopt)
187 -> std::shared_ptr<Buffers::TextureBuffer>
188 {
189 auto buffer = choose_image(desired_channels, std::move(region));
190 if (buffer)
192 return buffer;
193 }
194
195 /**
196 * @brief Load a supported Composite file into an owning container.
197 *
198 * CSV and TSV are supported now. Without a supplied layout, fields
199 * remain UTF-8 text. This does not register the container as a signal.
200 *
201 * @param filepath Source file path.
202 * @param layout Optional exact field layout for typed values.
203 * @return Loaded container, or nullptr on failure.
204 */
206 const std::string& filepath,
207 std::optional<Kakshya::CompositeLayout> layout = std::nullopt)
208 -> std::shared_ptr<Kakshya::CompositeContainer>
209 {
210 auto container = load_composite_container(filepath, std::move(layout));
211 if (container)
212 MF_LIVE_EXPOSE_AUTO(container);
213 return container;
214 }
215
216 /**
217 * @brief Choose a CSV or TSV file and load it as Composite data.
218 * @return Loaded container, or nullptr on cancellation or failure.
219 */
220 auto read_file() -> std::shared_ptr<Kakshya::CompositeContainer>
221 {
222 auto container = choose_composite();
223 if (container)
224 MF_LIVE_EXPOSE_AUTO(container);
225 return container;
226 }
227
228 auto read_volume(const std::string& filepath) -> std::shared_ptr<Buffers::VolumeGridBuffer>
229 {
230 auto buffer = load_volume_buffer(filepath);
232 return buffer;
233 }
234
235 auto read_volume() -> std::shared_ptr<Buffers::VolumeGridBuffer>
236 {
237 auto buffer = choose_volume();
238 if (buffer)
240 return buffer;
241 }
242
243 auto read_mesh(const std::string& filepath) -> MeshGroupHandle
244 {
245 return MeshGroupHandle(load_mesh_buffers(filepath));
246 }
247
249 {
251 }
252
254 const std::string& filepath,
255 IO::TextureResolver resolver = nullptr)
256 -> std::shared_ptr<Nodes::Network::MeshNetwork>
257 {
258 auto network = load_mesh_network(filepath, std::move(resolver));
260 return network;
261 }
262
263 auto read_mesh_network() -> std::shared_ptr<Nodes::Network::MeshNetwork>
264 {
266 if (network)
268 return network;
269 }
270
271 // ═══════════════════════════════════════════════════════════════
272 // Camera (Special - defined in Creator.cpp)
273 // ═══════════════════════════════════════════════════════════════
274
275 /**
276 * @brief Open a camera device as a live source container.
277 *
278 * Opens via IOManager::open_camera() and returns the container, like
279 * read_audio() returns its container. Nothing is hooked until you pipe it
280 * into Graphics, or call IOManager::hook_camera_to_buffer().
281 *
282 * @param config Device name, resolution hint, fps hint, format override.
283 * @return Opened CameraContainer, or nullptr on failure.
284 */
285 std::shared_ptr<Kakshya::CameraContainer> read_camera(const IO::CameraConfig& config);
286
287 /**
288 * @brief Let the user pick a camera and capture mode, then read it as above.
289 *
290 * Opens the pickers via choose_camera(). Blocks until the user chooses or
291 * closes a window.
292 *
293 * @return Opened CameraContainer, or nullptr on cancellation or failure.
294 */
295 std::shared_ptr<Kakshya::CameraContainer> read_camera();
296
297 // ═══════════════════════════════════════════════════════════════
298 // Input Node Creation (Special - defined in Creator.cpp)
299 // ═══════════════════════════════════════════════════════════════
300
301 /**
302 * @brief Create and register HID input node.
303 * @param config HID input configuration.
304 * @param binding HID input binding.
305 * @return Shared pointer to HIDNode (already registered).
306 */
307 std::shared_ptr<Nodes::Input::HIDNode> read_hid(
308 const Nodes::Input::HIDConfig& config,
309 const Core::InputBinding& binding);
310
311 /**
312 * @brief Create and register MIDI input node.
313 * @param config MIDI input configuration.
314 * @param binding MIDI input binding.
315 * @return Shared pointer to MIDINode (already registered).
316 */
317 std::shared_ptr<Nodes::Input::MIDINode> read_midi(
318 const Nodes::Input::MIDIConfig& config,
319 const Core::InputBinding& binding);
320
321 /**
322 * @brief Create and register OSC input node.
323 * @param config OSC input configuration.
324 * @param binding OSC input binding (use InputBinding::osc("/address")).
325 * @return Shared pointer to OSCNode (already registered).
326 */
327 std::shared_ptr<Nodes::Input::OSCNode> read_osc(
328 const Nodes::Input::OSCConfig& config,
329 const Core::InputBinding& binding);
330
331 /**
332 * @brief Create and register tablet input node.
333 * @param config Tablet input configuration.
334 * @param binding Tablet input binding (use InputBinding::tablet(id)).
335 * @return Shared pointer to TabletNode (already registered).
336 */
337 std::shared_ptr<Nodes::Input::TabletNode> read_tablet(
338 const Nodes::Input::TabletConfig& config,
339 const Core::InputBinding& binding);
340
341 /**
342 * @brief Create and register generic input node.
343 * @param config Generic input configuration.
344 * @param binding Generic input binding.
345 * @return Shared pointer to InputNode (already registered).
346 */
347 std::shared_ptr<Nodes::Input::InputNode> read_input(
348 const Nodes::Input::InputConfig& config,
349 const Core::InputBinding& binding);
350
351private:
352 std::shared_ptr<Kakshya::SoundFileContainer> load_sound_container(const std::string& filepath);
353 std::shared_ptr<Kakshya::CompositeContainer> load_composite_container(
354 const std::string& filepath,
355 std::optional<Kakshya::CompositeLayout> layout);
356 std::shared_ptr<Buffers::TextureBuffer> load_image_buffer(
357 const std::string& filepath, int desired_channels,
358 std::optional<Kakshya::Region> region);
359 std::shared_ptr<Buffers::VolumeGridBuffer> load_volume_buffer(const std::string& filepath);
360 std::vector<std::shared_ptr<Buffers::MeshBuffer>> load_mesh_buffers(const std::string& filepath);
361 std::shared_ptr<Nodes::Network::MeshNetwork> load_mesh_network(const std::string& filepath, IO::TextureResolver resolver);
362};
363
364// ═══════════════════════════════════════════════════════════════
365// New pipe operators -- shared_ptr<T> | CreationContext
366// DomainSpec converts implicitly to CreationContext so
367// | Audio, | Audio[0], | Audio[{0,1}], | Graphics all route here.
368// ═══════════════════════════════════════════════════════════════
369
370template <typename T>
371 requires std::is_base_of_v<Nodes::Node, T>
372std::shared_ptr<T> operator|(std::shared_ptr<T> obj, const CreationContext& ctx)
373{
374 register_node(std::static_pointer_cast<Nodes::Node>(obj), ctx);
375 return obj;
376}
377
378template <typename T>
379 requires std::is_base_of_v<Nodes::Network::NodeNetwork, T>
380std::shared_ptr<T> operator|(std::shared_ptr<T> obj, const CreationContext& ctx)
381{
382 register_network(std::static_pointer_cast<Nodes::Network::NodeNetwork>(obj), ctx);
383 return obj;
384}
385
386template <typename T>
387 requires std::is_base_of_v<Buffers::Buffer, T>
388std::shared_ptr<T> operator|(std::shared_ptr<T> obj, const CreationContext& ctx)
389{
390 register_buffer(std::static_pointer_cast<Buffers::Buffer>(obj), ctx);
391 return obj;
392}
393
394inline std::shared_ptr<Kakshya::SoundFileContainer> operator|(
395 std::shared_ptr<Kakshya::SoundFileContainer> obj,
396 const CreationContext& ctx)
397{
398 if (ctx.domain)
399 register_container(obj, ctx.domain.value());
400 return obj;
401}
402
403/**
404 * @brief Hook a video or camera container to a buffer in the Graphics domain.
405 *
406 * Returns the same container, with its real type. A video file loaded with
407 * VideoReadOptions::EXTRACT_AUDIO also has its audio hooked, so one pipe
408 * registers both. Reach the buffers with get_associated_buffer and
409 * get_associated_buffers. A container that is already hooked is not hooked
410 * again.
411 *
412 * @code
413 * auto camera = vega.read_camera() | Graphics;
414 * auto picture = get_associated_buffer(camera);
415 * @endcode
416 */
417template <typename T>
418 requires std::is_base_of_v<Kakshya::VideoStreamContainer, T>
419std::shared_ptr<T> operator|(std::shared_ptr<T> obj, const CreationContext& ctx)
420{
421 if (ctx.domain)
422 register_container(obj, ctx.domain.value());
423 return obj;
424}
425
426/**
427 * @brief Domain constant for Audio domain.
428 *
429 * Supports subscript syntax for channel binding:
430 * @code
431 * auto wave = vega.Sine(440.f) | Audio[0];
432 * auto net = vega.ModalNetwork(16, 220.0) | Audio[{0, 1}];
433 * @endcode
434 */
435static constexpr DomainSpec Audio { .value = Domain::AUDIO };
436
437/**
438 * @brief Domain constant for Graphics domain.
439 *
440 * @code
441 * auto tex = vega.TextureBuffer(...) | Graphics;
442 * @endcode
443 */
445
446/**
447 * @brief Global Creator instance.
448 *
449 * Every call on vega is one of three kinds:
450 * - Class-named factories (Sine, AudioBuffer, ModalNetwork, TextureBuffer and
451 * the rest of the registry) construct the class with exactly its
452 * constructor arguments. The pipe registers the result in a domain.
453 * - read_* loaders take a source and return the real object. read_audio,
454 * read_image, read_file, read_mesh and read_mesh_network load from a path
455 * or, with no argument, from the matching choose_* call. read_file
456 * returns a CompositeContainer for supported structured formats.
457 * read_mesh returns a MeshGroupHandle that the pipe registers. read_hid,
458 * read_midi, read_osc, read_tablet and read_input create an input node and
459 * register it against a binding.
460 * - evolve and mint take a config and perform the whole sequence, returning
461 * the real object with rendering attached.
462 *
463 * @code
464 * auto wave = vega.Sine(440.f) | Audio[0];
465 * auto buf = vega.AudioBuffer(0, 512) | Audio[0];
466 * auto net = vega.ModalNetwork(16, 220.0) | Audio[{0, 1}];
467 * auto tex = vega.TextureBuffer(...) | Graphics;
468 *
469 * auto sfx = vega.read_audio("x.wav") | Audio;
470 * auto image = vega.read_image("x.png") | Graphics;
471 * auto records = vega.read_file("x.csv");
472 * auto meshes = vega.read_mesh("x.fbx") | Graphics;
473 * auto pad = vega.read_midi(config, binding);
474 *
475 * auto life = vega.evolve(grid_config, seed, { .target_window = window });
476 * auto smoke = vega.evolve(volume, flow_config, { .target_window = window });
477 * auto form = vega.mint(StructureConfig::Object {
478 * .mesh = mesh,
479 * .render = { .target_window = window } });
480 * @endcode
481 */
482extern MAYAFLUX_API Creator vega;
483
484} // namespace MayaFlux
Core::GlobalNetworkConfig network
Definition Config.cpp:43
Dialog-backed loading and file-type helpers.
#define MF_LIVE_EXPOSE_AUTO(ptr)
Auto-expose variant that deduces the key prefix from the shared_ptr element type.
std::shared_ptr< NetworkGeometryBuffer > buffer
auto read_audio() -> std::shared_ptr< Kakshya::SoundFileContainer >
Definition Creator.hpp:167
auto read_audio(const std::string &filepath) -> std::shared_ptr< Kakshya::SoundFileContainer >
Definition Creator.hpp:160
Evolve evolve
Sets a system going from a config: state that persists, a rule that advances it every cycle,...
Definition Creator.hpp:133
auto read_file() -> std::shared_ptr< Kakshya::CompositeContainer >
Choose a CSV or TSV file and load it as Composite data.
Definition Creator.hpp:220
auto read_file(const std::string &filepath, std::optional< Kakshya::CompositeLayout > layout=std::nullopt) -> std::shared_ptr< Kakshya::CompositeContainer >
Load a supported Composite file into an owning container.
Definition Creator.hpp:205
auto read_mesh_network(const std::string &filepath, IO::TextureResolver resolver=nullptr) -> std::shared_ptr< Nodes::Network::MeshNetwork >
Definition Creator.hpp:253
auto read_image(const std::string &filepath, int desired_channels=4, std::optional< Kakshya::Region > region=std::nullopt) -> std::shared_ptr< Buffers::TextureBuffer >
Definition Creator.hpp:175
auto read_volume(const std::string &filepath) -> std::shared_ptr< Buffers::VolumeGridBuffer >
Definition Creator.hpp:228
auto read_mesh() -> MeshGroupHandle
Definition Creator.hpp:248
auto read_mesh_network() -> std::shared_ptr< Nodes::Network::MeshNetwork >
Definition Creator.hpp:263
auto read_mesh(const std::string &filepath) -> MeshGroupHandle
Definition Creator.hpp:243
auto read_volume() -> std::shared_ptr< Buffers::VolumeGridBuffer >
Definition Creator.hpp:235
auto read_image(int desired_channels=4, std::optional< Kakshya::Region > region=std::nullopt) -> std::shared_ptr< Buffers::TextureBuffer >
Definition Creator.hpp:185
Mint mint
Builds a visible structure from a StructureConfig: resolves its source, constructs and registers what...
Definition Creator.hpp:156
Sets a system going from a config: state that persists, a rule that advances it every cycle,...
Definition Evolve.hpp:92
std::vector< std::shared_ptr< Buffers::MeshBuffer > > m_buffers
Definition Creator.hpp:110
std::shared_ptr< Buffers::MeshBuffer > & operator[](size_t i)
Definition Creator.hpp:107
Turns a structural config into a registered and rendered object.
Definition Mint.hpp:28
std::function< std::shared_ptr< Core::VKImage >(const std::string &)> TextureResolver
Callable that maps a raw material texture path to a GPU image.
Definition Depot.hpp:31
@ Core
Core engine, backend, subsystems.
@ Kakshya
Containers[Signalsource, Stream, File], Regions, DataProcessors.
@ IO
Networking, file handling, streaming.
std::shared_ptr< Buffers::TextureBuffer > choose_image(int desired_channels, std::optional< Kakshya::Region > region)
Present a native open-file dialog filtered to image formats and load the chosen file via IOManager::l...
Definition Depot.cpp:228
Creator vega
Global Creator instance.
Definition Creator.cpp:28
void register_node(const std::shared_ptr< Nodes::Node > &node, const Nodes::ProcessingToken &token, uint32_t channel)
Definition Graph.cpp:139
std::shared_ptr< Nodes::Network::MeshNetwork > choose_mesh_network(IO::TextureResolver resolver)
Present a native open-file dialog filtered to 3D model formats and load the chosen file as a MeshNetw...
Definition Depot.cpp:278
void register_buffer(const std::shared_ptr< Buffers::Buffer > &buffer, const CreationContext &ctx)
Definition Creator.cpp:83
std::vector< std::shared_ptr< Buffers::MeshBuffer > > choose_mesh()
Present a native open-file dialog filtered to 3D model formats and load the chosen file via IOManager...
Definition Depot.cpp:267
std::shared_ptr< Kakshya::SoundFileContainer > choose_audio()
Present a native open-file dialog filtered to audio formats and load the chosen file via IOManager::l...
Definition Depot.cpp:193
std::shared_ptr< Kakshya::CompositeContainer > choose_composite()
Choose a CSV or TSV file and load it as a CompositeContainer.
Definition Depot.cpp:242
void register_container(const std::shared_ptr< Kakshya::SoundFileContainer > &container, const Domain &domain)
Definition Creator.cpp:107
Domain
Unified domain enum combining all three ProcessingToken subsystems.
Definition Domain.hpp:22
@ AUDIO
Standard real-time audio processing domain.
Definition Domain.hpp:33
@ GRAPHICS
Standard real-time graphics processing domain.
Definition Domain.hpp:55
static constexpr DomainSpec Audio
Domain constant for Audio domain.
Definition Creator.hpp:435
std::shared_ptr< Buffers::VolumeGridBuffer > choose_volume()
Present a native open-file dialog filtered to volume formats and load the chosen file via IOManager::...
Definition Depot.cpp:291
static constexpr DomainSpec Graphics
Domain constant for Graphics domain.
Definition Creator.hpp:444
void register_network(const std::shared_ptr< Nodes::Network::NodeNetwork > &network, const CreationContext &ctx)
Definition Creator.cpp:53
std::shared_ptr< T > operator|(std::shared_ptr< T > obj, const CreationContext &ctx)
Definition Creator.hpp:372
Main namespace for the Maya Flux audio engine.
Definition Runtime.cpp:12
Specifies what input an InputNode wants to receive.
CreationContext(std::vector< uint32_t > ch)
Definition Creator.hpp:51
std::optional< uint32_t > channel
Definition Creator.hpp:29
CreationContext(Domain d, std::vector< uint32_t > ch)
Definition Creator.hpp:42
CreationContext(uint32_t ch)
Definition Creator.hpp:47
CreationContext(Domain d, uint32_t ch)
Definition Creator.hpp:37
std::optional< std::vector< uint32_t > > channels
Definition Creator.hpp:30
std::optional< Domain > domain
Definition Creator.hpp:28
CreationContext operator[](uint32_t ch) const
Bind a single channel to this domain.
Definition Creator.hpp:74
CreationContext operator[](std::initializer_list< uint32_t > chs) const
Bind multiple channels to this domain.
Definition Creator.hpp:80
Thin domain wrapper that adds subscript channel-binding syntax.
Definition Creator.hpp:70
Configuration for opening a camera device via FFmpeg.
Unified configuration for all HID input types.
Definition HIDNode.hpp:21
Configuration for InputNode behavior.
Definition InputNode.hpp:67
MIDI input node configuration.
Definition MIDINode.hpp:10
Configuration for OSC input node argument extraction.
Definition OSCNode.hpp:16
Selects which part of a tablet frame becomes the node's scalar.