MayaFlux 0.4.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
Expanse.hpp
Go to the documentation of this file.
1#pragma once
2
3namespace MayaFlux::Nexus {
4
5/**
6 * @class Expanse
7 * @brief A defined region of space with a containment test and crossing actions.
8 *
9 * An Expanse is an extent, not a point. It holds a containment predicate that
10 * answers whether a world position lies within it, and two actions fired when
11 * an entity crosses its edge: one on entry, one on exit. The Fabric evaluates
12 * the predicate against every indexed position on each commit and diffs
13 * membership against the previous commit, firing the actions for the
14 * difference. The Expanse does not query; the Fabric drives it, because only
15 * the Fabric sees consecutive snapshots.
16 *
17 * The containment predicate is a plain function from position to bool. A fixed
18 * box, a sphere, a half-space, or an extent driven by an evolving value are all
19 * the same kind of thing: the predicate closes over whatever state shapes the
20 * region, so an Expanse whose bounds move or breathe is expressed by a
21 * predicate that reads that state, with no change to the mechanism.
22 *
23 * The entry and exit actions receive the crossing entity id. What crossing
24 * means computationally is the action's decision: a tone gated, a parameter
25 * written, another entity activated, a value pushed. The Expanse supplies the
26 * spatial fact of crossing; the action supplies the consequence.
27 *
28 * The id is assigned by Fabric on registration and is stable for the Expanse's
29 * lifetime.
30 */
31class MAYAFLUX_API Expanse {
32public:
33 using ContainsFn = std::function<bool(const glm::vec3&)>;
34 using CrossingFn = std::function<void(uint32_t)>;
35
36 /**
37 * @brief Construct with a containment predicate and crossing actions.
38 * @param contains Returns true when a world position lies within the Expanse.
39 * @param on_enter Fired with the entity id when it enters. May be empty.
40 * @param on_exit Fired with the entity id when it leaves. May be empty.
41 */
42 Expanse(ContainsFn contains, CrossingFn on_enter, CrossingFn on_exit)
43 : m_contains(std::move(contains))
44 , m_on_enter(std::move(on_enter))
45 , m_on_exit(std::move(on_exit))
46 {
47 }
48
49 /**
50 * @brief Construct with a named containment predicate and crossing actions.
51 * @param fn_name Identifier used for state encoding.
52 * @param contains Returns true when a world position lies within the Expanse.
53 * @param on_enter Fired with the entity id when it enters. May be empty.
54 * @param on_exit Fired with the entity id when it leaves. May be empty.
55 */
56 Expanse(std::string fn_name, ContainsFn contains, CrossingFn on_enter, CrossingFn on_exit)
57 : m_fn_name(std::move(fn_name))
58 , m_contains(std::move(contains))
59 , m_on_enter(std::move(on_enter))
60 , m_on_exit(std::move(on_exit))
61 {
62 }
63
64 /**
65 * @brief Construct with named containment predicate and named crossing actions.
66 * @param fn_name Identifier for the containment predicate.
67 * @param on_enter_fn_name Identifier for the on_enter callable.
68 * @param on_exit_fn_name Identifier for the on_exit callable.
69 * @param contains Returns true when a world position lies within the Expanse.
70 * @param on_enter Fired with the entity id when it enters. May be empty.
71 * @param on_exit Fired with the entity id when it leaves. May be empty.
72 */
73 Expanse(std::string fn_name,
74 std::string on_enter_fn_name,
75 std::string on_exit_fn_name,
76 ContainsFn contains,
77 CrossingFn on_enter,
78 CrossingFn on_exit)
79 : m_fn_name(std::move(fn_name))
80 , m_on_enter_fn_name(std::move(on_enter_fn_name))
81 , m_on_exit_fn_name(std::move(on_exit_fn_name))
82 , m_contains(std::move(contains))
83 , m_on_enter(std::move(on_enter))
84 , m_on_exit(std::move(on_exit))
85 {
86 }
87
88 /** @brief Test whether a world position lies within the Expanse. */
89 [[nodiscard]] bool contains(const glm::vec3& p) const
90 {
91 return m_contains && m_contains(p);
92 }
93
94 /** @brief Identifier assigned to the containment predicate, empty if anonymous. */
95 [[nodiscard]] const std::string& fn_name() const { return m_fn_name; }
96
97 /** @brief Set or replace the predicate identifier. */
98 void set_fn_name(std::string name) { m_fn_name = std::move(name); }
99
100 /** @brief Identifier assigned to the on_enter callable, empty if anonymous. */
101 [[nodiscard]] const std::string& on_enter_fn_name() const { return m_on_enter_fn_name; }
102
103 /** @brief Set or replace the on_enter callable identifier. */
104 void set_on_enter_fn_name(std::string name) { m_on_enter_fn_name = std::move(name); }
105
106 /** @brief Identifier assigned to the on_exit callable, empty if anonymous. */
107 [[nodiscard]] const std::string& on_exit_fn_name() const { return m_on_exit_fn_name; }
108
109 /** @brief Set or replace the on_exit callable identifier. */
110 void set_on_exit_fn_name(std::string name) { m_on_exit_fn_name = std::move(name); }
111
112 /** @brief Stable id assigned by Fabric on registration. */
113 [[nodiscard]] uint32_t id() const { return m_id; }
114
115 /** @brief Entity ids inside this Expanse for @p fabric_id, or nullptr if that fabric has no occupants. */
116 [[nodiscard]] const std::unordered_set<uint32_t>* occupants(uint32_t fabric_id) const
117 {
118 auto it = m_occupants_by_fabric.find(fabric_id);
119 return it != m_occupants_by_fabric.end() ? &it->second : nullptr;
120 }
121
122 /** @brief All fabric ids that currently have at least one occupant inside this Expanse. */
123 [[nodiscard]] std::vector<uint32_t> occupied_fabrics() const
124 {
125 std::vector<uint32_t> result;
126 result.reserve(m_occupants_by_fabric.size());
127 for (const auto& [fid, _] : m_occupants_by_fabric)
128 result.push_back(fid);
129 return result;
130 }
131
132 /**
133 * @brief Evaluate a spatial snapshot from one Fabric against this Expanse.
134 *
135 * Runs the containment predicate against each position in @p snapshot,
136 * diffs the result against the previous occupant set for @p fabric_id,
137 * fires @c on_enter / @c on_exit for the difference, and updates the
138 * stored set. Each Fabric maintains independent occupant state.
139 *
140 * @param fabric_id Stable id of the calling Fabric.
141 * @param snapshot All indexed positions from that Fabric's spatial index.
142 */
143 void evaluate(uint32_t fabric_id,
144 std::span<const std::pair<uint32_t, glm::vec3>> snapshot);
145
146private:
147 std::string m_fn_name;
149 std::string m_on_exit_fn_name;
153
154 uint32_t m_id { 0 };
155 std::unordered_map<uint32_t, std::unordered_set<uint32_t>> m_occupants_by_fabric;
156
157 friend class Fabric;
158};
159
160} // namespace MayaFlux::Nexus
void set_on_exit_fn_name(std::string name)
Set or replace the on_exit callable identifier.
Definition Expanse.hpp:110
const std::string & on_enter_fn_name() const
Identifier assigned to the on_enter callable, empty if anonymous.
Definition Expanse.hpp:101
const std::unordered_set< uint32_t > * occupants(uint32_t fabric_id) const
Entity ids inside this Expanse for fabric_id, or nullptr if that fabric has no occupants.
Definition Expanse.hpp:116
std::string m_on_enter_fn_name
Definition Expanse.hpp:148
std::unordered_map< uint32_t, std::unordered_set< uint32_t > > m_occupants_by_fabric
Definition Expanse.hpp:155
std::function< void(uint32_t)> CrossingFn
Definition Expanse.hpp:34
std::vector< uint32_t > occupied_fabrics() const
All fabric ids that currently have at least one occupant inside this Expanse.
Definition Expanse.hpp:123
void set_fn_name(std::string name)
Set or replace the predicate identifier.
Definition Expanse.hpp:98
const std::string & on_exit_fn_name() const
Identifier assigned to the on_exit callable, empty if anonymous.
Definition Expanse.hpp:107
std::string m_on_exit_fn_name
Definition Expanse.hpp:149
std::function< bool(const glm::vec3 &)> ContainsFn
Definition Expanse.hpp:33
uint32_t id() const
Stable id assigned by Fabric on registration.
Definition Expanse.hpp:113
const std::string & fn_name() const
Identifier assigned to the containment predicate, empty if anonymous.
Definition Expanse.hpp:95
bool contains(const glm::vec3 &p) const
Test whether a world position lies within the Expanse.
Definition Expanse.hpp:89
Expanse(std::string fn_name, std::string on_enter_fn_name, std::string on_exit_fn_name, ContainsFn contains, CrossingFn on_enter, CrossingFn on_exit)
Construct with named containment predicate and named crossing actions.
Definition Expanse.hpp:73
void set_on_enter_fn_name(std::string name)
Set or replace the on_enter callable identifier.
Definition Expanse.hpp:104
Expanse(ContainsFn contains, CrossingFn on_enter, CrossingFn on_exit)
Construct with a containment predicate and crossing actions.
Definition Expanse.hpp:42
Expanse(std::string fn_name, ContainsFn contains, CrossingFn on_enter, CrossingFn on_exit)
Construct with a named containment predicate and crossing actions.
Definition Expanse.hpp:56
A defined region of space with a containment test and crossing actions.
Definition Expanse.hpp:31
Orchestrates spatial indexing and scheduling for Nexus objects.
Definition Fabric.hpp:38