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