MayaFlux 0.5.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
Schema.hpp
Go to the documentation of this file.
1#pragma once
2
5
6#include <nlohmann/json.hpp>
7
9
10/**
11 * @brief Current schema version written by StateEncoder and accepted by StateDecoder.
12 *
13 * History:
14 * 1 - initial (positions only)
15 * 2 - added color, size, wiring
16 * 3 - added audio_sinks, render_sinks
17 * 4 - added sink_type pixel row
18 * 5 - added subkind, locus_nav fields, expanses array
19 */
20inline constexpr uint32_t k_schema_version = 5;
21
22/**
23 * @brief RGBA32F EXR layout constants shared between encoder and decoder.
24 *
25 * Row 0: position.xyz, intensity
26 * Row 1: color.rgb, size
27 * Row 2: radius, query_radius, entity_type_norm, 0
28 * Row 3: trigger_kind, time_kind, sink_type_bits, first_audio_channel
29 * Row 4: locus_nav.fov, locus_nav.near, locus_nav.far, locus_nav.speed
30 */
31inline constexpr uint32_t k_exr_rows = 5;
32inline constexpr uint32_t k_channels = 4;
33
34// =============================================================================
35// Range normalization records
36// =============================================================================
37
38struct Range {
39 float min { 0.0F };
40 float max { 1.0F };
41
42 static constexpr auto describe()
43 {
44 return std::make_tuple(
47 }
48};
49
50struct RangeSet {
57
58 static constexpr auto describe()
59 {
60 return std::make_tuple(
61 Reflect::member("position.x", &RangeSet::pos_x),
62 Reflect::member("position.y", &RangeSet::pos_y),
63 Reflect::member("position.z", &RangeSet::pos_z),
70 Reflect::member("query_radius", &RangeSet::query_radius));
71 }
72};
73
74// =============================================================================
75// Wiring records
76// =============================================================================
77
78/**
79 * @brief Serializable wiring strategies.
80 *
81 * Enumerator names are lowercased by Reflect:: for JSON: commit_driven,
82 * every, move_to, unsupported. The decoder treats Unsupported as a
83 * commit_driven fallback with a warning.
84 */
85enum class WiringKind : uint8_t {
87 Every,
88 MoveTo,
89 Scroll,
91};
92
93struct WiringStep {
94 glm::vec3 position {};
95 double delay_seconds { 0.0 };
96
97 static constexpr auto describe()
98 {
99 return std::make_tuple(
102 }
103};
104
107 std::optional<double> interval;
108 std::optional<double> duration;
109 std::optional<size_t> times;
110 std::optional<std::vector<WiringStep>> steps;
111
112 static constexpr auto describe()
113 {
114 return std::make_tuple(
120 }
121};
122
123// =============================================================================
124// Sink records
125// =============================================================================
126
128 uint32_t channel {};
129 std::string fn_name;
130
131 static constexpr auto describe()
132 {
133 return std::make_tuple(
136 }
137};
138
140 std::string fn_name;
141
142 static constexpr auto describe()
143 {
144 return std::make_tuple(
146 }
147};
148
149// =============================================================================
150// Locus navigation fields
151// =============================================================================
152
153/**
154 * @brief Serializable subset of Kinesis::NavigationConfig sufficient to seed
155 * a Locus on reconstruct. Dynamic nav state (velocity, yaw accumulation)
156 * is transient and is not encoded.
157 *
158 * @note view_targets are live RenderProcessor pointers and cannot be serialized.
159 * StateDecoder warns on reconstruct; the caller must reconnect them.
160 */
162 glm::vec3 eye {};
163 glm::vec3 target {};
164 glm::vec3 up { 0.0F, 1.0F, 0.0F };
165 float fov { 60.0F };
166 float near_plane { 0.01F };
167 float far_plane { 1000.0F };
168 float speed { 1.0F };
169
170 static constexpr auto describe()
171 {
172 return std::make_tuple(
180 }
181};
182
183// =============================================================================
184// Entity record
185// =============================================================================
186
187/**
188 * @brief Per-entity JSON record.
189 *
190 * `kind` is one of "emitter", "sensor", "agent".
191 * `subkind` is empty for plain Agent, "locus" for Locus, "presence" for Presence.
192 * `locus_nav` is present only when subkind == "locus".
193 */
195 uint32_t id {};
196 std::string kind;
197 std::string subkind;
198 glm::vec3 position {};
199 float intensity { 0.0F };
200 float radius { 0.0F };
201 float query_radius { 0.0F };
202 std::optional<glm::vec3> color;
203 std::optional<float> size;
204 std::string influence_fn_name;
206 std::string radiate_fn_name;
208 std::vector<AudioSinkRecord> audio_sinks;
209 std::vector<RenderSinkRecord> render_sinks;
210 std::optional<LocusNavRecord> locus_nav;
212 std::optional<float> falloff_radius;
213
236};
237
238// =============================================================================
239// Expanse record
240// =============================================================================
241
242/**
243 * @brief Per-expanse JSON record.
244 *
245 * Only the function names are serializable; the containment predicate and
246 * crossing callbacks are closures that must be resolved from the Fabric's
247 * function registry on reconstruct. If fn_name is empty the expanse cannot
248 * be reconstructed and the decoder skips it with a warning.
249 */
251 uint32_t id {};
252 std::string fn_name;
253 std::string on_enter_fn_name;
254 std::string on_exit_fn_name;
255
256 static constexpr auto describe()
257 {
258 return std::make_tuple(
263 }
264};
265
266// =============================================================================
267// Fabric schema
268// =============================================================================
269
272 std::string fabric_name;
273 std::vector<EntityRecord> entities;
274 std::vector<ExpanseRecord> expanses;
276
277 static constexpr auto describe()
278 {
279 return std::make_tuple(
285 }
286};
287
288// =============================================================================
289// Tapestry schema
290// =============================================================================
291
292/**
293 * @brief Entry in the Tapestry envelope pointing to one Fabric's EXR+JSON pair.
294 */
295struct FabricRef {
296 std::string name;
297 std::string base_path;
298
299 static constexpr auto describe()
300 {
301 return std::make_tuple(
304 }
305};
306
307/**
308 * @brief Tapestry-level named Expanse record. Lives in tapestry.json rather
309 * than any individual fabric file because Tapestry-owned Expanses may
310 * be registered on multiple Fabrics.
311 *
312 * `fabric_ids` lists the runtime Fabric ids that had this Expanse registered
313 * at encode time. On reconstruct the decoder resolves Fabrics by name and
314 * calls Fabric::add_expanse for each.
315 */
317 std::string name;
318 std::string fn_name;
319 std::string on_enter_fn_name;
320 std::string on_exit_fn_name;
321 std::vector<std::string> fabric_names;
322
323 static constexpr auto describe()
324 {
325 return std::make_tuple(
331 }
332};
333
336 std::vector<FabricRef> fabrics;
337 std::vector<TapestryExpanseRecord> expanses;
338 nlohmann::json user_state;
339
340 static constexpr auto describe()
341 {
342 return std::make_tuple(
347 }
348};
349
350// =============================================================================
351// Kind helpers shared between encoder and decoder
352// =============================================================================
353
354/**
355 * @brief Map Fabric::Kind to its lowercase JSON string token via magic_enum.
356 */
357inline std::string kind_to_string(Fabric::Kind k)
358{
360}
361
362/**
363 * @brief Return true if @p s maps to a known Fabric::Kind token.
364 *
365 * Call this as a gate before parse_kind. Unrecognised strings should be
366 * warned and skipped at the call site; parse_kind assumes the string is valid.
367 */
368inline bool kind_known(std::string_view s)
369{
370 return Reflect::string_to_enum_case_insensitive<Fabric::Kind>(s).has_value();
371}
372
373/**
374 * @brief Parse a JSON kind token to Fabric::Kind (case-insensitive).
375 *
376 * Precondition: kind_known(s) is true. Behaviour is undefined for
377 * unrecognised strings; guard with kind_known before calling.
378 */
379inline Fabric::Kind parse_kind(std::string_view s)
380{
381 return *Reflect::string_to_enum_case_insensitive<Fabric::Kind>(s);
382}
383
384} // namespace MayaFlux::Nexus::State
float k
constexpr uint32_t k_schema_version
Current schema version written by StateEncoder and accepted by StateDecoder.
Definition Schema.hpp:20
bool kind_known(std::string_view s)
Return true if s maps to a known Fabric::Kind token.
Definition Schema.hpp:368
Fabric::Kind parse_kind(std::string_view s)
Parse a JSON kind token to Fabric::Kind (case-insensitive).
Definition Schema.hpp:379
constexpr uint32_t k_exr_rows
RGBA32F EXR layout constants shared between encoder and decoder.
Definition Schema.hpp:31
constexpr uint32_t k_channels
Definition Schema.hpp:32
WiringKind
Serializable wiring strategies.
Definition Schema.hpp:85
std::string kind_to_string(Fabric::Kind k)
Map Fabric::Kind to its lowercase JSON string token via magic_enum.
Definition Schema.hpp:357
std::string enum_to_lowercase_string(EnumType value) noexcept
Universal enum to lowercase string converter using magic_enum.
constexpr auto opt_member(std::string_view key, std::optional< T > Class::*ptr)
Definition Mirror.hpp:43
constexpr auto member(std::string_view key, T Class::*ptr)
Definition Mirror.hpp:37
static constexpr auto describe()
Definition Schema.hpp:131
std::optional< LocusNavRecord > locus_nav
Definition Schema.hpp:210
static constexpr auto describe()
Definition Schema.hpp:214
std::optional< float > size
Definition Schema.hpp:203
std::optional< glm::vec3 > color
Definition Schema.hpp:202
std::vector< AudioSinkRecord > audio_sinks
Definition Schema.hpp:208
std::optional< float > falloff_radius
Definition Schema.hpp:212
std::vector< RenderSinkRecord > render_sinks
Definition Schema.hpp:209
Per-entity JSON record.
Definition Schema.hpp:194
static constexpr auto describe()
Definition Schema.hpp:256
Per-expanse JSON record.
Definition Schema.hpp:250
static constexpr auto describe()
Definition Schema.hpp:299
Entry in the Tapestry envelope pointing to one Fabric's EXR+JSON pair.
Definition Schema.hpp:295
static constexpr auto describe()
Definition Schema.hpp:277
std::vector< EntityRecord > entities
Definition Schema.hpp:273
std::vector< ExpanseRecord > expanses
Definition Schema.hpp:274
static constexpr auto describe()
Definition Schema.hpp:170
Serializable subset of Kinesis::NavigationConfig sufficient to seed a Locus on reconstruct.
Definition Schema.hpp:161
static constexpr auto describe()
Definition Schema.hpp:58
static constexpr auto describe()
Definition Schema.hpp:42
static constexpr auto describe()
Definition Schema.hpp:142
std::vector< std::string > fabric_names
Definition Schema.hpp:321
Tapestry-level named Expanse record.
Definition Schema.hpp:316
std::vector< FabricRef > fabrics
Definition Schema.hpp:336
std::vector< TapestryExpanseRecord > expanses
Definition Schema.hpp:337
static constexpr auto describe()
Definition Schema.hpp:340
std::optional< size_t > times
Definition Schema.hpp:109
std::optional< double > interval
Definition Schema.hpp:107
static constexpr auto describe()
Definition Schema.hpp:112
std::optional< std::vector< WiringStep > > steps
Definition Schema.hpp:110
std::optional< double > duration
Definition Schema.hpp:108
static constexpr auto describe()
Definition Schema.hpp:97