MayaFlux 0.5.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
Wiring.hpp
Go to the documentation of this file.
1#pragma once
2
4
8
10
11namespace MayaFlux::Core {
12class Window;
13}
14
15namespace MayaFlux::Vruta {
16class TaskScheduler;
17class EventManager;
18class Routine;
19class SoundRoutine;
20class GraphicsRoutine;
21class CrossRoutine;
22class Event;
23}
24
25namespace MayaFlux::Nexus {
26
27class Fabric;
28
29/**
30 * @class Wiring
31 * @brief Fluent builder that wires an entity into Fabric's scheduling infrastructure.
32 *
33 * Obtained via @c Fabric::wire. Describes when and how the object's function
34 * is invoked. Call @c finalise() to apply the configuration.
35 *
36 * No coroutine is created unless a scheduling modifier is set. @c bind()
37 * performs an immediate single call with no coroutine. Any scheduling
38 * modifier (@c every, @c on, @c move_to, @c position_from, @c use) creates
39 * and registers a coroutine owned by Fabric.
40 */
41class MAYAFLUX_API Wiring {
42public:
43 using PositionFn = std::function<glm::vec3()>;
44 using SoundFactory = std::function<Vruta::SoundRoutine()>;
45 using GraphicsFactory = std::function<Vruta::GraphicsRoutine()>;
46 using CrossFactory = std::function<Vruta::CrossRoutine()>;
48 using NullFunc = std::nullptr_t;
49 static constexpr NullFunc no_release = nullptr;
50
51 // =====================================================================
52 // Scheduling modifiers
53 // =====================================================================
54
55 /**
56 * @brief Fire the entity on a recurring interval.
57 * @param interval_seconds Period between invocations.
58 * @param token Scheduler rate to use (default: SAMPLE_ACCURATE).
59 */
60 Wiring& every(double interval_seconds, Vruta::ProcessingToken token = Vruta::ProcessingToken::SAMPLE_ACCURATE);
61
62 /**
63 * @brief Limit a recurring registration to a fixed duration then cancel.
64 * @param seconds Total active time. Pairs with @c every().
65 * @param token If set, uses the specified scheduler's clock for timing; otherwise defaults to SAMPLE_ACCURATE.
66 */
67 Wiring& for_duration(double seconds, Vruta::ProcessingToken token = Vruta::ProcessingToken::SAMPLE_ACCURATE);
68
69 /**
70 * @brief Fire the entity on a key event from a window.
71 * @param window Source window.
72 * @param key Key to listen for.
73 */
74 Wiring& on(std::shared_ptr<Core::Window> window, IO::Keys key);
75
76 /**
77 * @brief Fire the entity repeatedly while a key is held, invoking a release callback on release.
78 * @param window Source window.
79 * @param key Key to listen for.
80 * @param held If true, fires on repeat ticks while held.
81 * @param on_release Called when the key is released.
82 */
83 Wiring& on(std::shared_ptr<Core::Window> window, IO::Keys key, bool held,
84 std::function<void()> on_release = nullptr);
85
86 /**
87 * @brief Fire the entity on a mouse button event from a window.
88 * @param window Source window.
89 * @param button Mouse button to listen for.
90 */
91 Wiring& on(std::shared_ptr<Core::Window> window, IO::MouseButtons button);
92
93 /**
94 * @brief Fire the entity on mouse-motion events while @p button is held.
95 *
96 * Mirrors the key held overload. Cursor position is available via
97 * InfluenceContext on each qualifying event.
98 *
99 * @param window Source window.
100 * @param button Button that must be pressed for the entity to fire.
101 * @param held Pass @c true to select the motion-while-held path.
102 * @param on_release Called when the button is released.
103 */
104 Wiring& on(std::shared_ptr<Core::Window> window, IO::MouseButtons button, bool held,
105 std::function<void(double, double)> on_release = nullptr);
106
107 /**
108 * @brief Fire the entity on mouse button press and invoke a release callback on release.
109 * @param window Source window.
110 * @param button Mouse button to listen for.
111 * @param on_release Called with cursor position when the button is released. Cancelled with the wiring.
112 */
113 Wiring& on(std::shared_ptr<Core::Window> window, IO::MouseButtons button,
114 std::function<void(double, double)> on_release);
115
116 /**
117 * @brief Fire the entity on each incoming message from a network source.
118 * @param source OSC or raw network source.
119 */
120 Wiring& on(Vruta::NetworkSource& source);
121
122 /**
123 * @brief Fire the entity on each matching window event.
124 * @param source Event stream.
125 * @param filter Optional filter criteria.
126 */
128
129 /**
130 * @brief Fire the entity on each mouse scroll event from a window.
131 *
132 * The scroll delta (dx, dy) is passed directly to the emitter's fn via a
133 * shared glm::vec2 written before invoke(). No new InfluenceContext fields
134 * are added; read the delta through the captured shared_ptr in your fn.
135 *
136 * @param window Source window.
137 * @param fn Called with (dx, dy) on each scroll event.
138 */
139 Wiring& on_scroll(std::shared_ptr<Core::Window> window,
140 std::function<void(double, double)> fn);
141
142 /**
143 * @brief Choreograph a position move as an EventChain step.
144 * @param pos Target position.
145 * @param delay_seconds Delay after the previous step (0 = immediate on start).
146 */
147 Wiring& move_to(const glm::vec3& pos, double delay_seconds = 0.0);
148
149 /**
150 * @brief Drive position from a callable evaluated on each @c every() tick.
151 * @param fn Returns the new position on each invocation.
152 */
153 Wiring& position_from(PositionFn fn);
154
155 /**
156 * @brief Drive position from a named callable evaluated on each @c every() tick.
157 * @param fn_name Identifier used for state encoding.
158 * @param fn Returns the new position on each invocation.
159 */
160 Wiring& position_from(std::string fn_name, PositionFn fn);
161
162 /**
163 * @brief Repeat the configured sequence or choreography N times.
164 * @param count Number of repetitions.
165 */
166 Wiring& times(size_t count);
167
168 /**
169 * @brief Delegate coroutine creation entirely to the caller.
170 *
171 * Fabric registers the entity with the spatial index and adds the
172 * returned coroutine. All timing and entity commit logic is the
173 * caller's responsibility.
174 */
175 Wiring& use(SoundFactory factory);
176 Wiring& use(GraphicsFactory factory);
177 Wiring& use(CrossFactory factory);
178 Wiring& use(EventFactory factory);
179
180 /** @brief Register a named factory. */
181 Wiring& use(std::string fn_name, SoundFactory factory);
182 Wiring& use(std::string fn_name, GraphicsFactory factory);
183 Wiring& use(std::string fn_name, CrossFactory factory);
184 Wiring& use(std::string fn_name, EventFactory factory);
185
186 // =====================================================================
187 // Immediate bind — no coroutine
188 // =====================================================================
189
190 /**
191 * @brief Call the entity's influence function once immediately.
192 *
193 * No coroutine is created. If @c for_duration was set, a Timer fires
194 * the detach function after expiry.
195 */
196 Wiring& bind();
197
198 /**
199 * @brief Call a custom function once immediately instead of the entity's own.
200 * @param fn Callable to invoke in place of the entity's influence function.
201 */
202 Wiring& bind(std::function<void()> fn);
203
204 /**
205 * @brief Call attach immediately; call detach after @c for_duration expires
206 * or on explicit @c cancel().
207 * @param attach Called immediately on finalise().
208 * @param detach Called on expiry or cancellation.
209 */
210 Wiring& bind(std::function<void()> attach, std::function<void()> detach);
211
212 /** @brief Call a named custom function once immediately. */
213 Wiring& bind(std::string fn_name, std::function<void()> fn);
214
215 /** @brief Call named attach/detach functions. */
216 Wiring& bind(std::string attach_name, std::function<void()> attach,
217 std::string detach_name, std::function<void()> detach);
218
219 // =====================================================================
220 // Terminal
221 // =====================================================================
222
223 /**
224 * @brief Apply the configured wiring.
225 *
226 * Resolves the builder state into a coroutine (if any scheduling
227 * modifier was set) or an immediate call (if @c bind was used),
228 * and registers the result with Fabric.
229 */
230 void finalise();
231
232 /**
233 * @brief Cancel an active wiring and release any owned coroutine.
234 */
235 void cancel();
236
237private:
238 friend class Fabric;
239
240 explicit Wiring(Fabric& fabric, uint32_t entity_id)
241 : m_fabric(fabric)
242 , m_entity_id(entity_id)
243 {
244 }
245
246 // =====================================================================
247 // Stored configuration
248 // =====================================================================
249
250 struct MoveStep {
251 glm::vec3 position;
253 };
254
255 struct KeyTrigger {
256 std::shared_ptr<Core::Window> window;
258 std::optional<std::function<void()>> on_release;
259 bool held {};
260 };
261
263 std::shared_ptr<Core::Window> window;
265 std::optional<std::function<void(double, double)>> on_release;
266 bool held {};
267 };
268
270 std::shared_ptr<Core::Window> window;
271 std::function<void(double, double)> fn;
272 };
273
277
282
287
288 using Trigger = std::variant<
289 std::monostate,
296 using Factory = std::variant<std::monostate, SoundFactory, GraphicsFactory, CrossFactory>;
297 using EFactory = std::optional<EventFactory>;
298
299 std::string make_name(const char* prefix) const;
301 uint32_t m_entity_id;
302 bool m_has_scheduling {};
303
304 std::optional<double> m_interval;
305 std::optional<double> m_duration;
306 std::optional<PositionFn> m_position_fn;
308 std::vector<MoveStep> m_move_steps;
309 size_t m_times { 1 };
310 Vruta::ProcessingToken m_metro_token { Vruta::ProcessingToken::SAMPLE_ACCURATE };
311 Vruta::ProcessingToken m_duration_token { Vruta::ProcessingToken::SAMPLE_ACCURATE };
312
316 std::string m_factory_name;
317
318 std::optional<std::function<void()>> m_bind_attach;
319 std::optional<std::function<void()>> m_bind_detach;
322
323 Vruta::Event window_event_source_loop(Vruta::WindowEventSource& source, Vruta::WindowEventFilter filter, Fabric& fabric, uint32_t id);
324
325public:
326 // =====================================================================
327 // Move semantics
328 // =====================================================================
329 ~Wiring() = default;
330 Wiring(const Wiring&) = delete;
331 Wiring& operator=(const Wiring&) = delete;
332 Wiring(Wiring&&) noexcept = default;
333 Wiring& operator=(Wiring&&) = delete;
334
335 // =====================================================================
336 // Introspection
337 // =====================================================================
338
339 /** @brief Stable id of the wired entity. */
340 [[nodiscard]] uint32_t entity_id() const { return m_entity_id; }
341
342 /** @brief Recurring interval in seconds, if @c every was called. */
343 [[nodiscard]] std::optional<double> interval() const { return m_interval; }
344
345 /** @brief Active duration in seconds, if @c for_duration was called. */
346 [[nodiscard]] std::optional<double> duration() const { return m_duration; }
347
348 /** @brief Repetition count set by @c times, default 1. */
349 [[nodiscard]] size_t times_count() const { return m_times; }
350
351 /** @brief Choreography steps from @c move_to calls. */
352 [[nodiscard]] const std::vector<MoveStep>& move_steps() const { return m_move_steps; }
353
354 /** @brief True if @c on_scroll was called. */
355 [[nodiscard]] bool is_scroll() const { return std::holds_alternative<ScrollTrigger>(m_trigger); }
356
357 /** @brief Active trigger variant set by @c on. */
358 [[nodiscard]] const Trigger& trigger() const { return m_trigger; }
359
360 /** @brief Active factory variant set by @c use for non-Event factories. */
361 [[nodiscard]] const Factory& factory() const { return m_factory; }
362
363 /** @brief Active event-factory, if @c use(EventFactory) was called. */
364 [[nodiscard]] const EFactory& event_factory() const { return m_event_factory; }
365
366 /** @brief True if @c position_from was called. */
367 [[nodiscard]] bool has_position_fn() const { return m_position_fn.has_value(); }
368
369 /** @brief True if any @c bind overload was called. */
370 [[nodiscard]] bool has_bind() const { return m_bind_attach.has_value(); }
371
372 /** @brief True if @c bind(attach, detach) was called. */
373 [[nodiscard]] bool has_bind_detach() const { return m_bind_detach.has_value(); }
374
375 /** @brief Name of the position function, empty if anonymous. */
376 [[nodiscard]] const std::string& position_fn_name() const { return m_position_fn_name; }
377
378 /** @brief Name of the active factory, empty if anonymous or none. */
379 [[nodiscard]] const std::string& factory_name() const { return m_factory_name; }
380
381 /** @brief Name of the bind attach function, empty if anonymous or none. */
382 [[nodiscard]] const std::string& bind_attach_name() const { return m_bind_attach_name; }
383
384 /** @brief Name of the bind detach function, empty if anonymous or none. */
385 [[nodiscard]] const std::string& bind_detach_name() const { return m_bind_detach_name; }
386};
387
388} // namespace MayaFlux::Nexus
size_t count
Orchestrates spatial indexing and scheduling for Nexus objects.
Definition Fabric.hpp:38
std::optional< std::function< void()> > m_bind_detach
Definition Wiring.hpp:319
bool has_position_fn() const
True if position_from was called.
Definition Wiring.hpp:367
const Trigger & trigger() const
Active trigger variant set by on.
Definition Wiring.hpp:358
std::string m_position_fn_name
Definition Wiring.hpp:307
bool is_scroll() const
True if on_scroll was called.
Definition Wiring.hpp:355
bool has_bind_detach() const
True if bind(attach, detach) was called.
Definition Wiring.hpp:373
std::function< Vruta::CrossRoutine()> CrossFactory
Definition Wiring.hpp:46
std::string m_bind_attach_name
Definition Wiring.hpp:320
std::nullptr_t NullFunc
Definition Wiring.hpp:48
const std::string & position_fn_name() const
Name of the position function, empty if anonymous.
Definition Wiring.hpp:376
const std::string & bind_attach_name() const
Name of the bind attach function, empty if anonymous or none.
Definition Wiring.hpp:382
const std::string & factory_name() const
Name of the active factory, empty if anonymous or none.
Definition Wiring.hpp:379
Wiring(Wiring &&) noexcept=default
const EFactory & event_factory() const
Active event-factory, if use(EventFactory) was called.
Definition Wiring.hpp:364
std::function< glm::vec3()> PositionFn
Definition Wiring.hpp:43
std::optional< std::function< void()> > m_bind_attach
Definition Wiring.hpp:318
const std::vector< MoveStep > & move_steps() const
Choreography steps from move_to calls.
Definition Wiring.hpp:352
std::optional< double > m_duration
Definition Wiring.hpp:305
std::optional< EventFactory > EFactory
Definition Wiring.hpp:297
Wiring & operator=(const Wiring &)=delete
std::function< Vruta::GraphicsRoutine()> GraphicsFactory
Definition Wiring.hpp:45
std::function< Vruta::Event(Vruta::TaskScheduler &)> EventFactory
Definition Wiring.hpp:47
const std::string & bind_detach_name() const
Name of the bind detach function, empty if anonymous or none.
Definition Wiring.hpp:385
std::optional< double > m_interval
Definition Wiring.hpp:304
const Factory & factory() const
Active factory variant set by use for non-Event factories.
Definition Wiring.hpp:361
bool has_bind() const
True if any bind overload was called.
Definition Wiring.hpp:370
std::optional< double > interval() const
Recurring interval in seconds, if every was called.
Definition Wiring.hpp:343
std::optional< double > duration() const
Active duration in seconds, if for_duration was called.
Definition Wiring.hpp:346
Wiring(const Wiring &)=delete
std::string m_bind_detach_name
Definition Wiring.hpp:321
std::vector< MoveStep > m_move_steps
Definition Wiring.hpp:308
std::string m_factory_name
Definition Wiring.hpp:316
size_t times_count() const
Repetition count set by times, default 1.
Definition Wiring.hpp:349
std::optional< PositionFn > m_position_fn
Definition Wiring.hpp:306
Wiring(Fabric &fabric, uint32_t entity_id)
Definition Wiring.hpp:240
std::variant< std::monostate, SoundFactory, GraphicsFactory, CrossFactory > Factory
Definition Wiring.hpp:296
std::variant< std::monostate, KeyTrigger, MouseTrigger, NetworkTrigger, EventTrigger, WindowEventTrigger, ScrollTrigger > Trigger
Definition Wiring.hpp:295
std::function< Vruta::SoundRoutine()> SoundFactory
Definition Wiring.hpp:44
Fluent builder that wires an entity into Fabric's scheduling infrastructure.
Definition Wiring.hpp:41
Coroutine resumed by more than one clock.
Definition Routine.hpp:642
Base for event filters used by EventSources to match signals to awaiters.
Abstract base for all awaitable signal sources.
Coroutine type for event-driven suspension.
Definition Event.hpp:26
A C++20 coroutine-based graphics processing task with frame-accurate timing.
Definition Routine.hpp:496
Awaitable broadcast message stream for a network endpoint.
A C++20 coroutine-based audio processing task with sample-accurate timing.
Definition Routine.hpp:316
Token-based multimodal task scheduling system for unified coroutine processing.
Definition Scheduler.hpp:51
Awaitable stream of GLFW window input events.
MouseButtons
Enumeration for mouse buttons.
Definition Keys.hpp:147
void on_scroll(const std::shared_ptr< Core::Window > &window, std::function< void(double, double)> callback, std::string name)
Schedule a mouse scroll handler.
Definition Chronie.cpp:250
std::shared_ptr< Core::Window > window
Definition Wiring.hpp:256
std::optional< std::function< void()> > on_release
Definition Wiring.hpp:258
std::optional< std::function< void(double, double)> > on_release
Definition Wiring.hpp:265
std::shared_ptr< Core::Window > window
Definition Wiring.hpp:263
std::function< void(double, double)> fn
Definition Wiring.hpp:271
std::shared_ptr< Core::Window > window
Definition Wiring.hpp:270
Filter criteria for GLFW window input events.