MayaFlux 0.4.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
Fabric.hpp
Go to the documentation of this file.
1#pragma once
2
3#include "Expanse.hpp"
7#include "Wiring.hpp"
8
10
11namespace MayaFlux::Vruta {
12class TaskScheduler;
13class EventManager;
14}
15
16namespace MayaFlux::Nexus {
17
18/**
19 * @class Fabric
20 * @brief Orchestrates spatial indexing and scheduling for Nexus objects.
21 *
22 * Plain object, not a subsystem. Constructed with references to the engine's
23 * scheduler and event manager. Owns a @c Kinesis::SpatialIndex3D populated
24 * only for objects that have a position set.
25 *
26 * Objects are registered via @c wire(), which returns a @c Wiring builder.
27 * The builder describes when and how the object's function is invoked.
28 * All coroutines and events are owned by the scheduler and event manager
29 * respectively. Fabric holds only the names needed to cancel them.
30 *
31 * @c commit() updates all positions in the index, publishes the snapshot,
32 * and fires all registered objects. @c fire(id) fires a single object
33 * against the current snapshot without republishing.
34 *
35 * Spatial queries read the last published snapshot and are safe from any
36 * thread.
37 */
38class MAYAFLUX_API Fabric {
39public:
40 enum class Kind : uint8_t {
41 Emitter,
42 Sensor,
43 Agent,
44 };
45
46 /**
47 * @brief Construct with scheduler and event manager from the engine.
48 * @param scheduler Used to register coroutines created by Wiring.
49 * @param event_manager Used to register event-driven coroutines.
50 * @param cell_size Grid cell edge length for the spatial index.
51 */
52 explicit Fabric(
53 Vruta::TaskScheduler& scheduler,
54 Vruta::EventManager& event_manager,
55 float cell_size = 1.0F);
56
57 ~Fabric();
58
59 Fabric(const Fabric&) = delete;
60 Fabric& operator=(const Fabric&) = delete;
61 Fabric(Fabric&&) = delete;
62 Fabric& operator=(Fabric&&) = delete;
63
64 /**
65 * @brief Assigned name, empty if the Fabric was constructed outside a Tapestry.
66 */
67 [[nodiscard]] const std::string& name() const { return m_name; }
68
69 /**
70 * @brief Set or replace the Fabric's name. Typically called by Tapestry.
71 */
72 void set_name(std::string name) { m_name = std::move(name); }
73
74 /**
75 * @brief Stable id for this Fabric, assigned by Tapestry at construction.
76 */
77 [[nodiscard]] uint32_t id() const { return m_fabric_id; }
78
79 /**
80 * @brief Set or replace the Fabric's id. Typically called by Tapestry.
81 */
82 void set_id(uint32_t id) { m_fabric_id = id; }
83
84 // =========================================================================
85 // Registration
86 // =========================================================================
87
88 /**
89 * @brief Begin wiring an Emitter into the Fabric.
90 * @param emitter Object to register.
91 * @return Wiring builder. Call @c Wiring::finalise() to apply.
92 */
93 [[nodiscard]] Wiring wire(std::shared_ptr<Emitter> emitter);
94
95 /**
96 * @brief Begin wiring a Sensor into the Fabric.
97 * @param sensor Object to register.
98 * @return Wiring builder. Call @c Wiring::finalise() to apply.
99 */
100 [[nodiscard]] Wiring wire(std::shared_ptr<Sensor> sensor);
101
102 /**
103 * @brief Begin wiring an Agent into the Fabric.
104 * @param agent Object to register.
105 * @return Wiring builder. Call @c Wiring::finalise() to apply.
106 */
107 [[nodiscard]] Wiring wire(std::shared_ptr<Agent> agent);
108
109 /**
110 * @brief Remove a registered object by id, cancelling any associated tasks.
111 * @param id Stable id assigned at registration.
112 */
113 void remove(uint32_t id);
114
115 /**
116 * @brief Register an Expanse for per-commit crossing detection.
117 *
118 * On each commit, after the snapshot publishes, the Expanse's predicate is
119 * evaluated against every indexed position and membership is diffed against
120 * the previous commit. Entry and exit actions fire for the difference.
121 *
122 * @param expanse Expanse to register. Its id is assigned here.
123 * @return Stable id assigned to the Expanse.
124 */
125 uint32_t add_expanse(std::shared_ptr<Expanse> expanse);
126
127 /**
128 * @brief Remove a registered Expanse. Does not fire exit actions.
129 * @param id Id assigned at registration.
130 */
131 void remove_expanse(uint32_t id);
132
133 // =========================================================================
134 // Commit
135 // =========================================================================
136
137 /**
138 * @brief Update all positions, publish the snapshot, fire all registered objects.
139 *
140 * For each object with a position, calls @c m_index->update() then
141 * @c m_index->publish(). Then fires each object's function with a
142 * context built from the new snapshot.
143 */
144 void commit();
145
146 /**
147 * @brief Fire a single object against the current snapshot without republishing.
148 * @param id Id assigned at registration.
149 */
150 void fire(uint32_t id);
151
152 // =========================================================================
153 // Spatial queries
154 // =========================================================================
155
156 /**
157 * @brief Find all objects within a radius of a point.
158 * @param center Query origin.
159 * @param radius Search radius in world-space units.
160 * @return Unsorted results with squared distances.
161 */
162 [[nodiscard]] std::vector<Kinesis::QueryResult> within_radius(
163 const glm::vec3& center, float radius) const;
164
165 /**
166 * @brief Find the k nearest objects to a point.
167 * @param center Query origin.
168 * @param k Maximum number of results.
169 * @return Results sorted by ascending squared distance.
170 */
171 [[nodiscard]] std::vector<Kinesis::QueryResult> k_nearest(
172 const glm::vec3& center, uint32_t k) const;
173
174 /**
175 * @brief Access the finalised wiring for an entity for introspection.
176 * @param id Entity id assigned at registration.
177 * @return Pointer to the wiring, or nullptr if id is not registered
178 * or @c finalise() has not yet been called.
179 */
180 [[nodiscard]] const Wiring* wiring_for(uint32_t id) const;
181
182 /**
183 * @brief List all registered entity ids in insertion order.
184 */
185 [[nodiscard]] std::vector<uint32_t> all_ids() const;
186
187 /**
188 * @brief Return the kind of entity registered under @p id.
189 * @throws std::out_of_range if id is not registered.
190 */
191 [[nodiscard]] Kind kind(uint32_t id) const;
192
193 /**
194 * @brief Get the Emitter registered under @p id.
195 * @return The Emitter, or nullptr if id is not an Emitter or not registered.
196 */
197 [[nodiscard]] std::shared_ptr<Emitter> get_emitter(uint32_t id) const;
198
199 /**
200 * @brief Get the Sensor registered under @p id.
201 * @return The Sensor, or nullptr if id is not a Sensor or not registered.
202 */
203 [[nodiscard]] std::shared_ptr<Sensor> get_sensor(uint32_t id) const;
204
205 /**
206 * @brief Get the Agent registered under @p id.
207 * @return The Agent, or nullptr if id is not an Agent or not registered.
208 */
209 [[nodiscard]] std::shared_ptr<Agent> get_agent(uint32_t id) const;
210
211 // =========================================================================
212 // Function registry
213 // =========================================================================
214
215 /**
216 * @brief Look up a registered influence function by name.
217 * @return Shared pointer to the stored function, or nullptr if not found.
218 */
219 [[nodiscard]] std::shared_ptr<Emitter::InfluenceFn> resolve_influence_fn(std::string_view name) const;
220
221 /**
222 * @brief Look up a registered perception function by name.
223 * @return Shared pointer to the stored function, or nullptr if not found.
224 */
225 [[nodiscard]] std::shared_ptr<Sensor::PerceptionFn> resolve_perception_fn(std::string_view name) const;
226
227 /**
228 * @brief Look up a registered Expanse containment function by name.
229 * @return Shared pointer to the stored function, or nullptr if not found.
230 */
231 [[nodiscard]] std::shared_ptr<Expanse::ContainsFn> resolve_expanse_fn(std::string_view name) const;
232
233 /**
234 * @brief Look up a registered radiation function by name.
235 * @return Shared pointer to the stored function, or nullptr if not found.
236 */
237 [[nodiscard]] std::shared_ptr<Presence::RadiateFn> resolve_radiate_fn(std::string_view name) const;
238
239 /**
240 * @brief Look up a registered Expanse crossing function by name.
241 *
242 * Used for both on_enter and on_exit callables; both share the same
243 * registry since CrossingFn has a uniform signature.
244 *
245 * @return Shared pointer to the stored function, or nullptr if not found.
246 */
247 [[nodiscard]] std::shared_ptr<Expanse::CrossingFn> resolve_crossing_fn(std::string_view name) const;
248
249 // =========================================================================
250 // Expanse introspection
251 // =========================================================================
252
253 /**
254 * @brief Stable ids of all registered Expanses in insertion order.
255 */
256 [[nodiscard]] std::vector<uint32_t> all_expanse_ids() const;
257
258 /**
259 * @brief Look up a registered Expanse by id.
260 * @return The Expanse, or nullptr if id is not registered.
261 */
262 [[nodiscard]] std::shared_ptr<Expanse> get_expanse(uint32_t id) const;
263
264private:
265 friend class Wiring;
266
267 std::string m_name;
268
269 using Member = std::variant<
270 std::shared_ptr<Emitter>,
271 std::shared_ptr<Sensor>,
272 std::shared_ptr<Agent>>;
273
276 std::string task_name;
277 std::string event_name;
278 std::string chain_name;
279 bool commit_driven { false };
280 std::optional<uint32_t> spatial_id;
281 std::optional<Wiring> wiring;
282 std::optional<glm::vec2> pending_cursor;
283 };
284
285 uint32_t assign_id(Member& m);
286 void fire(const Registration& reg) const;
287
290
291 std::unique_ptr<Kinesis::SpatialIndex3D> m_index;
292 std::unordered_map<uint32_t, Registration> m_registrations;
293 std::unordered_map<uint32_t, std::shared_ptr<Expanse>> m_expanses;
294
295 uint32_t m_fabric_id { 0 };
296 uint32_t m_next_id { 1 };
297 uint32_t m_next_expanse_id { 1 };
298
299 std::unordered_map<std::string, std::shared_ptr<Emitter::InfluenceFn>> m_influence_fns;
300 std::unordered_map<std::string, std::shared_ptr<Sensor::PerceptionFn>> m_perception_fns;
301 std::unordered_map<std::string, std::shared_ptr<Expanse::ContainsFn>> m_expanse_fns;
302 std::unordered_map<std::string, std::shared_ptr<Expanse::CrossingFn>> m_crossing_fns;
303 std::unordered_map<std::string, std::shared_ptr<Presence::RadiateFn>> m_radiate_fns;
304};
305
306} // namespace MayaFlux::Nexus
Object that both perceives nearby entities and acts on MayaFlux objects.
Definition Agent.hpp:28
Object that acts on existing MayaFlux objects when committed.
Definition Emitter.hpp:24
std::unordered_map< std::string, std::shared_ptr< Expanse::CrossingFn > > m_crossing_fns
Definition Fabric.hpp:302
std::unordered_map< uint32_t, std::shared_ptr< Expanse > > m_expanses
Definition Fabric.hpp:293
void set_id(uint32_t id)
Set or replace the Fabric's id.
Definition Fabric.hpp:82
std::unique_ptr< Kinesis::SpatialIndex3D > m_index
Definition Fabric.hpp:291
std::unordered_map< std::string, std::shared_ptr< Expanse::ContainsFn > > m_expanse_fns
Definition Fabric.hpp:301
std::variant< std::shared_ptr< Emitter >, std::shared_ptr< Sensor >, std::shared_ptr< Agent > > Member
Definition Fabric.hpp:272
Fabric & operator=(const Fabric &)=delete
Fabric(Fabric &&)=delete
std::unordered_map< std::string, std::shared_ptr< Presence::RadiateFn > > m_radiate_fns
Definition Fabric.hpp:303
std::unordered_map< std::string, std::shared_ptr< Sensor::PerceptionFn > > m_perception_fns
Definition Fabric.hpp:300
Fabric & operator=(Fabric &&)=delete
const std::string & name() const
Assigned name, empty if the Fabric was constructed outside a Tapestry.
Definition Fabric.hpp:67
Fabric(const Fabric &)=delete
void set_name(std::string name)
Set or replace the Fabric's name.
Definition Fabric.hpp:72
Vruta::TaskScheduler & m_scheduler
Definition Fabric.hpp:288
uint32_t id() const
Stable id for this Fabric, assigned by Tapestry at construction.
Definition Fabric.hpp:77
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
Orchestrates spatial indexing and scheduling for Nexus objects.
Definition Fabric.hpp:38
Object that reacts to nearby entities when committed.
Definition Sensor.hpp:19
Fluent builder that wires an entity into Fabric's scheduling infrastructure.
Definition Wiring.hpp:41
Token-based multimodal task scheduling system for unified coroutine processing.
Definition Scheduler.hpp:51
std::optional< Wiring > wiring
Definition Fabric.hpp:281
std::optional< glm::vec2 > pending_cursor
Definition Fabric.hpp:282
std::optional< uint32_t > spatial_id
Definition Fabric.hpp:280