MayaFlux 0.4.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches

◆ finalise()

void MayaFlux::Nexus::Wiring::finalise ( )

Apply the configured wiring.

Resolves the builder state into a coroutine (if any scheduling modifier was set) or an immediate call (if bind was used), and registers the result with Fabric.

Definition at line 250 of file Wiring.cpp.

251{
252 auto& scheduler = m_fabric.m_scheduler;
253 auto& ev_manager = m_fabric.m_event_manager;
254 const uint32_t id = m_entity_id;
255 auto& reg = m_fabric.m_registrations[id];
256
257 bool has_any_path = !std::holds_alternative<std::monostate>(m_factory)
258 || m_event_factory.has_value()
259 || m_bind_attach.has_value()
260 || !m_move_steps.empty()
261 || !std::holds_alternative<std::monostate>(m_trigger)
262 || m_interval.has_value();
263
264 reg.commit_driven = !has_any_path;
265
266 // ------------------------------------------------------------------
267 // Register named callables before any early return.
268 // ------------------------------------------------------------------
269 std::visit([&](const auto& ptr) {
270 using T = std::decay_t<decltype(*ptr)>;
271 if constexpr (std::is_same_v<T, Emitter>) {
272 if (!ptr->fn_name().empty()) {
273 m_fabric.m_influence_fns.try_emplace(
274 ptr->fn_name(), std::make_shared<Emitter::InfluenceFn>(ptr->fn()));
275 }
276 } else if constexpr (std::is_same_v<T, Sensor>) {
277 if (!ptr->fn_name().empty()) {
278 m_fabric.m_perception_fns.try_emplace(
279 ptr->fn_name(), std::make_shared<Sensor::PerceptionFn>(ptr->fn()));
280 }
281 } else if constexpr (std::is_same_v<T, Agent>) {
282 if (!ptr->influence_fn_name().empty()) {
283 m_fabric.m_influence_fns.try_emplace(
284 ptr->influence_fn_name(), std::make_shared<Emitter::InfluenceFn>(ptr->influence_fn()));
285 }
286 if (!ptr->perception_fn_name().empty()) {
287 m_fabric.m_perception_fns.try_emplace(
288 ptr->perception_fn_name(), std::make_shared<Sensor::PerceptionFn>(ptr->perception_fn()));
289 }
290 }
291 },
292 reg.member);
293
294 // ------------------------------------------------------------------
295 // Routine factory path
296 // ------------------------------------------------------------------
297 if (!std::holds_alternative<std::monostate>(m_factory)) {
298 auto name = make_name("nexus_task");
299 reg.task_name = name;
300 std::visit([&](auto& factory) {
301 using F = std::decay_t<decltype(factory)>;
302 if constexpr (!std::is_same_v<F, std::monostate>) {
303 scheduler.add_task(
304 std::make_shared<std::invoke_result_t<F>>(factory()),
305 name, false);
306 }
307 },
308 m_factory);
309 m_fabric.m_registrations[m_entity_id].wiring.emplace(std::move(*this));
310 return;
311 }
312
313 // ------------------------------------------------------------------
314 // Event factory path
315 // ------------------------------------------------------------------
316 if (m_event_factory.has_value()) {
317 auto name = make_name("nexus_event");
318 reg.event_name = name;
319 ev_manager.add_event(
320 std::make_shared<Vruta::Event>((*m_event_factory)(scheduler)),
321 name);
322 m_fabric.m_registrations[m_entity_id].wiring.emplace(std::move(*this));
323 return;
324 }
325
326 // ------------------------------------------------------------------
327 // Immediate bind path
328 // ------------------------------------------------------------------
329 if (m_bind_attach.has_value()) {
330 (*m_bind_attach)();
331
332 if (m_duration.has_value() && m_bind_detach.has_value()) {
333 auto timer = std::make_shared<Kriya::Timer>(scheduler, m_duration_token);
334 auto detach = *m_bind_detach;
335 timer->schedule(*m_duration, [timer, detach]() {
336 detach();
337 });
338 }
339 m_fabric.m_registrations[m_entity_id].wiring.emplace(std::move(*this));
340 return;
341 }
342
343 // ------------------------------------------------------------------
344 // Choreographed position path
345 // ------------------------------------------------------------------
346 if (!m_move_steps.empty()) {
347 auto name = make_name("nexus_chain");
348 reg.chain_name = name;
349
350 Kriya::EventChain chain(scheduler, name);
351 auto& fab = m_fabric;
352 for (auto& step : m_move_steps) {
353 glm::vec3 pos = step.position;
354 chain.then([&fab, pos, id]() {
355 std::visit([&pos](const auto& ptr) {
356 ptr->set_position(pos);
357 },
358 fab.m_registrations[id].member);
359 fab.fire(id);
360 },
361 step.delay_seconds);
362 }
363 if (m_times > 1) {
364 chain.times(m_times);
365 }
366 chain.start();
367 m_fabric.m_registrations[m_entity_id].wiring.emplace(std::move(*this));
368 return;
369 }
370
371 // ------------------------------------------------------------------
372 // Trigger path
373 // ------------------------------------------------------------------
374 if (!std::holds_alternative<std::monostate>(m_trigger)) {
375 std::visit([&](auto& trig) {
376 using T = std::decay_t<decltype(trig)>;
377
378 if constexpr (std::is_same_v<T, KeyTrigger>) {
379 auto name = make_name("nexus_event");
380 reg.event_name = name;
381 auto& fab = m_fabric;
382 ev_manager.add_event(
383 std::make_shared<Vruta::Event>(
384 trig.held
385 ? Kriya::key_held(trig.window, trig.key,
386 [&fab, id]() { fab.fire(id); })
387 : Kriya::key_pressed(trig.window, trig.key,
388 [&fab, id]() { fab.fire(id); })),
389 name);
390
391 if (trig.on_release) {
392 auto release_name = make_name("nexus_event_release");
393 reg.chain_name = release_name;
394 ev_manager.add_event(
395 std::make_shared<Vruta::Event>(
396 Kriya::key_released(trig.window, trig.key, *trig.on_release)),
397 release_name);
398 }
399
400 } else if constexpr (std::is_same_v<T, MouseTrigger>) {
401 auto name = make_name("nexus_event");
402 reg.event_name = name;
403 Fabric& fab = m_fabric;
404 uint32_t eid = m_entity_id;
405 ev_manager.add_event(
406 std::make_shared<Vruta::Event>(
407 trig.held
408 ? Kriya::mouse_dragged(trig.window, trig.button,
409 [&fab, eid](double px, double py) {
410 fab.m_registrations[eid].pending_cursor = glm::vec2(px, py);
411 fab.fire(eid);
412 })
413 : Kriya::mouse_pressed(trig.window, trig.button,
414 [&fab, eid](double px, double py) {
415 fab.m_registrations[eid].pending_cursor = glm::vec2(px, py);
416 fab.fire(eid);
417 })),
418 name);
419 if (trig.on_release) {
420 auto release_name = make_name("nexus_event_release");
421 reg.chain_name = release_name;
422 ev_manager.add_event(
423 std::make_shared<Vruta::Event>(
424 Kriya::mouse_released(trig.window, trig.button, *trig.on_release)),
425 release_name);
426 }
427
428 } else if constexpr (std::is_same_v<T, NetworkTrigger>) {
429 auto name = make_name("nexus_task");
430 reg.task_name = name;
431 scheduler.add_task(
432 std::make_shared<Vruta::SoundRoutine>(
433 network_loop(*trig.source, m_fabric, id)),
434 name, false);
435
436 } else if constexpr (std::is_same_v<T, WindowEventTrigger>) {
437 auto name = make_name("nexus_event");
438 reg.event_name = name;
439 Fabric& fab = m_fabric;
440 ev_manager.add_event(
441 std::make_shared<Vruta::Event>(
442 window_event_source_loop(*trig.source, trig.filter, fab, id)),
443 name);
444 }
445 },
446 m_trigger);
447 m_fabric.m_registrations[m_entity_id].wiring.emplace(std::move(*this));
448 return;
449 }
450
451 // ------------------------------------------------------------------
452 // Metro path
453 // ------------------------------------------------------------------
454 if (m_interval.has_value()) {
455 auto pos_fn = m_position_fn;
456 auto name = make_name("nexus_metro");
457 reg.task_name = name;
458 auto& fab = m_fabric;
459
460 scheduler.add_task(
461 Kriya::metro(*m_interval, [&fab, id, pos_fn]() mutable {
462 if (pos_fn.has_value()) {
463 glm::vec3 p = (*pos_fn)();
464 std::visit([&p](const auto& ptr) {
465 ptr->set_position(p);
466 },
467 fab.m_registrations[id].member);
468 }
469 fab.fire(id); }, m_metro_token), name, false);
470
471 if (m_duration.has_value()) {
472 auto cancel_name = make_name("nexus_metro_cancel");
473 auto timer = std::make_shared<Kriya::Timer>(scheduler);
474 timer->schedule(*m_duration, [name, timer, &scheduler]() {
475 scheduler.cancel_task(name);
476 });
477 }
478 }
479
480 m_fabric.m_registrations[m_entity_id].wiring.emplace(std::move(*this));
481}
const uint8_t * ptr
std::unordered_map< std::string, std::shared_ptr< Sensor::PerceptionFn > > m_perception_fns
Definition Fabric.hpp:300
Vruta::TaskScheduler & m_scheduler
Definition Fabric.hpp:288
std::unordered_map< uint32_t, Registration > m_registrations
Definition Fabric.hpp:292
std::unordered_map< std::string, std::shared_ptr< Emitter::InfluenceFn > > m_influence_fns
Definition Fabric.hpp:299
Vruta::EventManager & m_event_manager
Definition Fabric.hpp:289
std::optional< std::function< void()> > m_bind_detach
Definition Wiring.hpp:294
Vruta::Event window_event_source_loop(Vruta::WindowEventSource &source, Vruta::WindowEventFilter filter, Fabric &fabric, uint32_t id)
Definition Wiring.cpp:513
std::string make_name(const char *prefix) const
Definition Wiring.cpp:219
friend class Fabric
Definition Wiring.hpp:225
std::optional< std::function< void()> > m_bind_attach
Definition Wiring.hpp:293
std::optional< double > m_duration
Definition Wiring.hpp:280
Vruta::ProcessingToken m_metro_token
Definition Wiring.hpp:285
Vruta::ProcessingToken m_duration_token
Definition Wiring.hpp:286
std::optional< double > m_interval
Definition Wiring.hpp:279
const Factory & factory() const
Active factory variant set by use for non-Event factories.
Definition Wiring.hpp:333
std::vector< MoveStep > m_move_steps
Definition Wiring.hpp:283
std::optional< PositionFn > m_position_fn
Definition Wiring.hpp:281
@ Kriya
Automatable tasks and fluent scheduling api for Nodes and Buffers.
Tendency< A, C > chain(const Tendency< A, B > &first, const Tendency< B, C > &second)
Sequential composition: evaluate first, feed result into second.
Definition Tendency.hpp:82
Vruta::Event key_released(std::shared_ptr< Core::Window > window, IO::Keys key, std::function< void()> callback)
Creates an Event coroutine that triggers on specific key release.
Vruta::Event key_pressed(std::shared_ptr< Core::Window > window, IO::Keys key, std::function< void()> callback)
Creates an Event coroutine that triggers on specific key press.
Vruta::Event key_held(std::shared_ptr< Core::Window > window, IO::Keys key, std::function< void()> callback)
Creates an Event coroutine that triggers on key press and repeats while held.
Vruta::Event mouse_released(std::shared_ptr< Core::Window > window, IO::MouseButtons button, std::function< void(double, double)> callback)
Creates an Event coroutine that triggers on specific mouse button release.
Vruta::Event mouse_pressed(std::shared_ptr< Core::Window > window, IO::MouseButtons button, std::function< void(double, double)> callback)
Creates an Event coroutine that triggers on specific mouse button press.
Vruta::Event mouse_dragged(std::shared_ptr< Core::Window > window, IO::MouseButtons button, std::function< void(double, double)> callback)
Creates an Event coroutine that triggers on mouse drag with specific button.
std::shared_ptr< Vruta::Routine > metro(double interval_seconds, std::function< void()> callback, Vruta::ProcessingToken token)
Creates a periodic event generator that executes a callback at regular intervals.
Definition Tasks.cpp:12

References factory(), MayaFlux::Kriya::key_held(), MayaFlux::Kriya::key_pressed(), MayaFlux::Kriya::key_released(), m_bind_attach, m_bind_detach, m_duration, m_duration_token, m_entity_id, m_event_factory, MayaFlux::Nexus::Fabric::m_event_manager, m_fabric, m_factory, MayaFlux::Nexus::Fabric::m_influence_fns, m_interval, m_metro_token, m_move_steps, MayaFlux::Nexus::Fabric::m_perception_fns, m_position_fn, MayaFlux::Nexus::Fabric::m_registrations, MayaFlux::Nexus::Fabric::m_scheduler, m_times, m_trigger, make_name(), MayaFlux::Kriya::metro(), MayaFlux::Kriya::mouse_dragged(), MayaFlux::Kriya::mouse_pressed(), MayaFlux::Kriya::mouse_released(), ptr, and window_event_source_loop().

+ Here is the call graph for this function: