MayaFlux 1.0.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
Agent.hpp
Go to the documentation of this file.
1#pragma once
2
6
8
9namespace MayaFlux::Buffers {
10class VKBuffer;
11}
12
13namespace MayaFlux::Nexus {
14
15/**
16 * @class Agent
17 * @brief Object that both perceives nearby entities and acts on MayaFlux objects.
18 *
19 * Constructed with a query radius and, optionally, a perception function and an
20 * influence function. Position is optional: call @c set_position before registering with
21 * @c Fabric if spatial behaviour is required. Without a position the spatial
22 * index is not consulted and @c spatial_results will be empty on each commit.
23 *
24 * On each commit the perception function is invoked first, then the influence
25 * function. Both receive contexts populated from the same spatial snapshot.
26 *
27 * The id is assigned by @c Fabric::wire and is stable for the object's lifetime.
28 *
29 * RenderConfig and AttachConfig take designated initializers.
30 *
31 * @code
32 * agent->attach(buf, { .on_move = AttachConfig::OnMove::Carry });
33 * agent->render(mgr, { .target_window = window });
34 * @endcode
35 */
36class MAYAFLUX_API Agent {
37public:
38 using InfluenceFn = std::function<void(const InfluenceContext&)>;
39 using PerceptionFn = std::function<void(const PerceptionContext&)>;
40
41 /**
42 * @brief Construct with only a query radius, for an Agent whose behaviour comes
43 * from typed influences and perceptions.
44 * @param query_radius Radius passed to the spatial index on each commit.
45 * Ignored if no position has been set.
46 */
47 explicit Agent(float query_radius = 1.0F)
48 : m_query_radius(query_radius)
49 {
50 }
51
52 /**
53 * @brief Construct with query radius, perception function, and influence function.
54 * @param query_radius Radius passed to the spatial index on each commit.
55 * Ignored if no position has been set.
56 * @param perception Called first on every commit.
57 * @param influence Called second on every commit.
58 */
59 explicit Agent(float query_radius, PerceptionFn perception, InfluenceFn influence)
60 : m_query_radius(query_radius)
61 , m_perception_fn(std::move(perception))
62 , m_influence_fn(std::move(influence))
63 {
64 }
65
66 /**
67 * @brief Construct with named perception and influence functions.
68 * @param query_radius Radius passed to the spatial index on each commit.
69 * @param perception_fn_name Identifier for the perception function.
70 * @param perception Called first on every commit.
71 * @param influence_fn_name Identifier for the influence function.
72 * @param influence Called second on every commit.
73 */
75 std::string perception_fn_name, PerceptionFn perception,
76 std::string influence_fn_name, InfluenceFn influence)
77 : m_query_radius(query_radius)
78 , m_perception_fn_name(std::move(perception_fn_name))
79 , m_perception_fn(std::move(perception))
80 , m_influence_fn_name(std::move(influence_fn_name))
81 , m_influence_fn(std::move(influence))
82 {
83 }
84
85 virtual ~Agent() = default;
86
87 /** @brief Identifier assigned to the perception function, empty if anonymous. */
88 [[nodiscard]] const std::string& perception_fn_name() const { return m_perception_fn_name; }
89
90 /** @brief Identifier assigned to the influence function, empty if anonymous. */
91 [[nodiscard]] const std::string& influence_fn_name() const { return m_influence_fn_name; }
92
93 /** @brief Set or replace the perception function's identifier. */
94 void set_perception_fn_name(std::string name) { m_perception_fn_name = std::move(name); }
95
96 /** @brief Set or replace the influence function's identifier. */
97 void set_influence_fn_name(std::string name) { m_influence_fn_name = std::move(name); }
98
99 /** @brief The perception function itself. */
100 [[nodiscard]] const PerceptionFn& perception_fn() const { return m_perception_fn; }
101
102 /** @brief The influence function itself. */
103 [[nodiscard]] const InfluenceFn& influence_fn() const { return m_influence_fn; }
104
105 /**
106 * @brief Return the current position, if set.
107 */
108 [[nodiscard]] const std::optional<glm::vec3>& position() const { return m_position; }
109
110 /**
111 * @brief Set the position, enabling spatial indexing and queries for this object.
112 * @param p World-space coordinates.
113 */
114 void set_position(const glm::vec3& p) { m_position = p; }
115
116 /**
117 * @brief Clear the position, removing this object from spatial operations.
118 */
119 void clear_position() { m_position.reset(); }
120
121 /** @brief Set the orientation. Local +Z is forward. Unset means no rotation. */
122 void set_orientation(const glm::quat& q) { m_orientation = q; }
123
124 /** @brief Clear the orientation. */
125 void clear_orientation() { m_orientation.reset(); }
126
127 /** @brief Get the current orientation, if set. */
128 [[nodiscard]] const std::optional<glm::quat>& orientation() const { return m_orientation; }
129
130 /**
131 * @brief Return the query radius.
132 */
133 [[nodiscard]] float query_radius() const { return m_query_radius; }
134
135 /**
136 * @brief Set the query radius.
137 * @param r New radius in world-space units.
138 */
139 void set_query_radius(float r) { m_query_radius = r; }
140
141 /**
142 * @brief Return the stable object id assigned by Fabric.
143 */
144 [[nodiscard]] uint32_t id() const { return m_id; }
145
146 // =========================================================================
147 // Output sinks
148 // =========================================================================
149
150 /** @brief Register an audio output on @p channel. */
151 void sink_audio(Buffers::BufferManager& mgr, uint32_t channel)
152 {
153 add_audio_sink(m_audio_sinks, mgr, channel);
154 }
155
156 /** @brief Register an audio output on @p channel with a producer function. */
157 void sink_audio(Buffers::BufferManager& mgr, uint32_t channel,
158 std::function<Kakshya::DataVariant(const InfluenceContext&)> fn,
159 std::string fn_name = "")
160 {
161 add_audio_sink(m_audio_sinks, mgr, channel, std::move(fn), std::move(fn_name));
162 }
163
164 /** @brief Unregister the audio sink on @p channel. */
165 void remove_audio_sink(Buffers::BufferManager& mgr, uint32_t channel)
166 {
167 Nexus::remove_audio_sink(m_audio_sinks, mgr, channel);
168 }
169
170 /** @brief Register a render output targeting @p window. */
172 {
173 add_render_sink(m_render_sinks, mgr, config, {}, "", m_position);
174 }
175
176 /** @brief Register a render output targeting @p window with a producer function. */
178 std::string fn_name, RenderFn fn)
179 {
180 add_render_sink(m_render_sinks, mgr, config, std::move(fn), std::move(fn_name), m_position);
181 }
182
183 [[nodiscard]] const std::vector<AudioSink>& audio_sinks() const { return m_audio_sinks; }
184 [[nodiscard]] const std::vector<RenderSink>& render_sinks() const { return m_render_sinks; }
185
186 /**
187 * @brief Make an existing, already rendered buffer the look of this object.
188 *
189 * The buffer is neither registered nor written to. Its geometry is read
190 * once and the object takes its position from the centroid, or from the
191 * vertex at config.index, plus config.offset. Every render processor the
192 * buffer has is placed at the object's position and orientation. If the
193 * object is moved from outside, config.on_move decides whether the move
194 * becomes the new offset or carries the buffer. If the object already has
195 * a position, that position is kept and becomes the offset. Replaces any
196 * previous attachment. The buffer is a live object, so an attachment is not
197 * part of encoded state and must be made again after decoding.
198 *
199 * @param buf Buffer to attach. Ignored if null.
200 * @param config Anchor vertex, offset and move behaviour.
201 */
202 void attach(const std::shared_ptr<Buffers::VKBuffer>& buf, const AttachConfig& config = {});
203
204 /** @brief Release the attached buffer and reset its placement. */
205 void detach();
206
207 /**
208 * @brief Read the attached buffer's geometry again and move the anchor to match.
209 *
210 * The object keeps its position. Blocks for a ComputeMeshBuffer, so call it
211 * off the graphics thread.
212 */
213 void recenter();
214
215 /** @brief True while a buffer is attached. */
216 [[nodiscard]] bool attached() const { return m_attachment.has_value(); }
217
218 /**
219 * @brief Add an influence of any type, with as many targets as are wanted.
220 * @tparam T Type the producer returns; whatever the targets take.
221 * @param producer Builds the value from the influence context.
222 * @return The influence, to add its targets with Influence::add_target.
223 *
224 * Runs on every influence after the influence function. Typed influences
225 * are runtime objects and are not part of encoded state.
226 */
227 template <typename T>
228 std::shared_ptr<Influence<T>> add_influence(typename Influence<T>::Producer producer)
229 {
230 auto influence = std::make_shared<Influence<T>>(std::move(producer));
231 m_influences.emplace_back(influence,
232 [influence](const InfluenceContext& ctx) { influence->invoke(ctx); });
233 return influence;
234 }
235
236 /** @brief Stop an influence added with add_influence(). */
237 template <typename T>
238 void remove_influence(const std::shared_ptr<Influence<T>>& influence)
239 {
240 std::erase_if(m_influences,
241 [&influence](const auto& entry) { return entry.first == influence; });
242 }
243
244 /** @brief Stop every influence added with add_influence(). */
245 void clear_influences() { m_influences.clear(); }
246
247 /**
248 * @brief Add a perception of any type, with as many targets as are wanted.
249 * @tparam T Type the source returns; whatever the targets take.
250 * @param source Reads the value, using the perception context.
251 * @return The perception, to add its targets with Perception::add_target.
252 *
253 * Runs on every perception before the perception function, so the function
254 * can use what the targets received. Typed perceptions are runtime objects
255 * and are not part of encoded state.
256 */
257 template <typename T>
258 std::shared_ptr<Perception<T>> add_perception(typename Perception<T>::Source source)
259 {
260 auto perception = std::make_shared<Perception<T>>(std::move(source));
261 m_perceptions.emplace_back(perception,
262 [perception](const PerceptionContext& ctx) { perception->invoke(ctx); });
263 return perception;
264 }
265
266 /** @brief Stop a perception added with add_perception(). */
267 template <typename T>
268 void remove_perception(const std::shared_ptr<Perception<T>>& perception)
269 {
270 std::erase_if(m_perceptions,
271 [&perception](const auto& entry) { return entry.first == perception; });
272 }
273
274 /** @brief Stop every perception added with add_perception(). */
275 void clear_perceptions() { m_perceptions.clear(); }
276
277 /* @brief Return the render processor for the sink targeting @p window, or nullptr if not found. */
278 std::shared_ptr<Buffers::RenderProcessor> get_render_processor(
279 const std::shared_ptr<Core::Window>& window) const
280 {
281 auto it = std::ranges::find_if(m_render_sinks,
282 [&window](const RenderSink& s) { return s.window == window; });
283 return it != m_render_sinks.end() ? it->renderer : nullptr;
284 }
285
286 /** @brief Unregister the render sink targeting @p window. */
287 void remove_render(Buffers::BufferManager& mgr, const std::shared_ptr<Core::Window>& window)
288 {
289 remove_render_sink(m_render_sinks, mgr, window);
290 }
291
292 /** @brief Push @p samples to all registered audio sinks. */
293 void set_audio_data(std::span<const double> samples)
294 {
295 push_audio_data(m_audio_sinks, samples);
296 }
297
298 /**
299 * @brief Set pre-packed interleaved vertex bytes to all registered render sinks.
300 *
301 * data must point to N contiguous 60-byte Vertex records.
302 * byte_count must be a multiple of 60.
303 */
304 void set_vertices(const void* data, size_t byte_count);
305
306 /**
307 * @brief Set typed vertex data to all registered render sinks.
308 * @tparam T One of Kakshya::PointVertex, Kakshya::LineVertex, Kakshya::MeshVertex, Kakshya::Vertex.
309 */
310 template <typename T>
311 void set_vertices(std::span<const T> vertices)
312 {
313 static_assert(sizeof(T) == 60, "set_vertices: T must be a 60-byte vertex type");
314 set_vertices(vertices.data(), vertices.size_bytes());
315 }
316
317 /** @brief Set the intensity, a general-purpose parameter for influence functions. */
318 void set_intensity(float i) { m_intensity = i; }
319
320 /** @brief Get the current intensity. */
321 [[nodiscard]] float intensity() const { return m_intensity; }
322
323 /** @brief Set the radius, a general-purpose parameter for influence functions. */
324 void set_radius(float r) { m_radius = r; }
325
326 /** @brief Get the current radius. */
327 [[nodiscard]] float radius() const { return m_radius; }
328
329 /** @brief Set the color, a general-purpose parameter for influence functions. */
330 void set_color(const glm::vec3& c) { m_color = c; }
331
332 /** @brief Clear the color, resetting it to an unset state. */
333 void clear_color() { m_color.reset(); }
334
335 /** @brief Get the current color, if set. */
336 [[nodiscard]] const std::optional<glm::vec3>& color() const { return m_color; }
337
338 /** @brief Set the size, a general-purpose parameter for influence functions. */
339 void set_size(float s) { m_size = s; }
340
341 /** @brief Clear the size, resetting it to an unset state. */
342 void clear_size() { m_size.reset(); }
343
344 /** @brief Get the current size, if set. */
345 [[nodiscard]] const std::optional<float>& size() const { return m_size; }
346
347 /**
348 * @brief Invoke the perception function with the supplied context.
349 * @param ctx Populated context for this commit.
350 */
351 virtual void invoke_perception(const PerceptionContext& ctx)
352 {
353 for (const auto& [handle, perception] : m_perceptions) {
354 perception(ctx);
355 }
356 if (m_perception_fn) {
357 m_perception_fn(ctx);
358 }
359 }
360
361 /**
362 * @brief Invoke the influence function with the supplied context.
363 * @param ctx Populated context for this commit.
364 */
365 virtual void invoke_influence(const InfluenceContext& ctx) const
366 {
367 if (m_influence_fn) {
368 m_influence_fn(ctx);
369 }
370 dispatch_audio_sinks(m_audio_sinks, ctx);
371 dispatch_render_sinks(m_render_sinks, ctx);
372 if (m_attachment)
373 apply_attachment(*m_attachment, ctx);
374 for (const auto& [handle, influence] : m_influences) {
375 influence(ctx);
376 }
377 }
378
379private:
380 std::optional<glm::vec3> m_position;
381 std::optional<glm::quat> m_orientation;
382 std::optional<glm::vec3> m_color;
383 std::optional<float> m_size;
384 float m_intensity { 1.0F };
385 float m_radius { 1.0F };
386
392 uint32_t m_id {};
393
394 mutable std::vector<AudioSink> m_audio_sinks;
395 mutable std::vector<RenderSink> m_render_sinks;
396 mutable std::optional<Attachment> m_attachment;
397 std::vector<std::pair<std::shared_ptr<void>, InfluenceFn>> m_influences;
398 std::vector<std::pair<std::shared_ptr<void>, PerceptionFn>> m_perceptions;
399
400 void follow_attachment();
401
402 friend class Fabric;
403};
404
405} // namespace MayaFlux::Nexus
float query_radius
Definition Decoder.cpp:96
std::weak_ptr< Core::Window > window
Definition Picker.cpp:23
double q
std::string name
Definition VKDevice.cpp:123
Token-based multimodal buffer management system for unified data stream processing.
void set_color(const glm::vec3 &c)
Set the color, a general-purpose parameter for influence functions.
Definition Agent.hpp:330
float radius() const
Get the current radius.
Definition Agent.hpp:327
void set_influence_fn_name(std::string name)
Set or replace the influence function's identifier.
Definition Agent.hpp:97
const std::optional< glm::vec3 > & position() const
Return the current position, if set.
Definition Agent.hpp:108
Agent(float query_radius, PerceptionFn perception, InfluenceFn influence)
Construct with query radius, perception function, and influence function.
Definition Agent.hpp:59
void set_intensity(float i)
Set the intensity, a general-purpose parameter for influence functions.
Definition Agent.hpp:318
void set_orientation(const glm::quat &q)
Set the orientation.
Definition Agent.hpp:122
const std::optional< glm::vec3 > & color() const
Get the current color, if set.
Definition Agent.hpp:336
InfluenceFn m_influence_fn
Definition Agent.hpp:391
virtual void invoke_influence(const InfluenceContext &ctx) const
Invoke the influence function with the supplied context.
Definition Agent.hpp:365
PerceptionFn m_perception_fn
Definition Agent.hpp:389
void remove_audio_sink(Buffers::BufferManager &mgr, uint32_t channel)
Unregister the audio sink on channel.
Definition Agent.hpp:165
void set_size(float s)
Set the size, a general-purpose parameter for influence functions.
Definition Agent.hpp:339
std::shared_ptr< Perception< T > > add_perception(typename Perception< T >::Source source)
Add a perception of any type, with as many targets as are wanted.
Definition Agent.hpp:258
virtual void invoke_perception(const PerceptionContext &ctx)
Invoke the perception function with the supplied context.
Definition Agent.hpp:351
std::optional< glm::quat > m_orientation
Definition Agent.hpp:381
uint32_t id() const
Return the stable object id assigned by Fabric.
Definition Agent.hpp:144
const std::vector< AudioSink > & audio_sinks() const
Definition Agent.hpp:183
Agent(float query_radius=1.0F)
Construct with only a query radius, for an Agent whose behaviour comes from typed influences and perc...
Definition Agent.hpp:47
std::vector< AudioSink > m_audio_sinks
Definition Agent.hpp:394
void clear_position()
Clear the position, removing this object from spatial operations.
Definition Agent.hpp:119
void render(Buffers::BufferManager &mgr, const Portal::Graphics::RenderConfig &config)
Register a render output targeting window.
Definition Agent.hpp:171
std::optional< float > m_size
Definition Agent.hpp:383
std::vector< std::pair< std::shared_ptr< void >, InfluenceFn > > m_influences
Definition Agent.hpp:397
std::optional< glm::vec3 > m_position
Definition Agent.hpp:380
void remove_influence(const std::shared_ptr< Influence< T > > &influence)
Stop an influence added with add_influence().
Definition Agent.hpp:238
const InfluenceFn & influence_fn() const
The influence function itself.
Definition Agent.hpp:103
const std::optional< glm::quat > & orientation() const
Get the current orientation, if set.
Definition Agent.hpp:128
std::function< void(const PerceptionContext &)> PerceptionFn
Definition Agent.hpp:39
float intensity() const
Get the current intensity.
Definition Agent.hpp:321
void sink_audio(Buffers::BufferManager &mgr, uint32_t channel)
Register an audio output on channel.
Definition Agent.hpp:151
void clear_orientation()
Clear the orientation.
Definition Agent.hpp:125
std::vector< std::pair< std::shared_ptr< void >, PerceptionFn > > m_perceptions
Definition Agent.hpp:398
const std::string & influence_fn_name() const
Identifier assigned to the influence function, empty if anonymous.
Definition Agent.hpp:91
const std::optional< float > & size() const
Get the current size, if set.
Definition Agent.hpp:345
void clear_influences()
Stop every influence added with add_influence().
Definition Agent.hpp:245
std::shared_ptr< Influence< T > > add_influence(typename Influence< T >::Producer producer)
Add an influence of any type, with as many targets as are wanted.
Definition Agent.hpp:228
void clear_size()
Clear the size, resetting it to an unset state.
Definition Agent.hpp:342
bool attached() const
True while a buffer is attached.
Definition Agent.hpp:216
void set_audio_data(std::span< const double > samples)
Push samples to all registered audio sinks.
Definition Agent.hpp:293
std::optional< glm::vec3 > m_color
Definition Agent.hpp:382
void render(Buffers::BufferManager &mgr, const Portal::Graphics::RenderConfig &config, std::string fn_name, RenderFn fn)
Register a render output targeting window with a producer function.
Definition Agent.hpp:177
void clear_color()
Clear the color, resetting it to an unset state.
Definition Agent.hpp:333
std::optional< Attachment > m_attachment
Definition Agent.hpp:396
void remove_perception(const std::shared_ptr< Perception< T > > &perception)
Stop a perception added with add_perception().
Definition Agent.hpp:268
std::shared_ptr< Buffers::RenderProcessor > get_render_processor(const std::shared_ptr< Core::Window > &window) const
Definition Agent.hpp:278
void set_query_radius(float r)
Set the query radius.
Definition Agent.hpp:139
std::string m_perception_fn_name
Definition Agent.hpp:388
void set_radius(float r)
Set the radius, a general-purpose parameter for influence functions.
Definition Agent.hpp:324
void set_perception_fn_name(std::string name)
Set or replace the perception function's identifier.
Definition Agent.hpp:94
void remove_render(Buffers::BufferManager &mgr, const std::shared_ptr< Core::Window > &window)
Unregister the render sink targeting window.
Definition Agent.hpp:287
const std::string & perception_fn_name() const
Identifier assigned to the perception function, empty if anonymous.
Definition Agent.hpp:88
Agent(float query_radius, std::string perception_fn_name, PerceptionFn perception, std::string influence_fn_name, InfluenceFn influence)
Construct with named perception and influence functions.
Definition Agent.hpp:74
std::string m_influence_fn_name
Definition Agent.hpp:390
const PerceptionFn & perception_fn() const
The perception function itself.
Definition Agent.hpp:100
std::vector< RenderSink > m_render_sinks
Definition Agent.hpp:395
float query_radius() const
Return the query radius.
Definition Agent.hpp:133
void set_vertices(std::span< const T > vertices)
Set typed vertex data to all registered render sinks.
Definition Agent.hpp:311
void clear_perceptions()
Stop every perception added with add_perception().
Definition Agent.hpp:275
void set_position(const glm::vec3 &p)
Set the position, enabling spatial indexing and queries for this object.
Definition Agent.hpp:114
std::function< void(const InfluenceContext &)> InfluenceFn
Definition Agent.hpp:38
void sink_audio(Buffers::BufferManager &mgr, uint32_t channel, std::function< Kakshya::DataVariant(const InfluenceContext &)> fn, std::string fn_name="")
Register an audio output on channel with a producer function.
Definition Agent.hpp:157
virtual ~Agent()=default
const std::vector< RenderSink > & render_sinks() const
Definition Agent.hpp:184
Object that both perceives nearby entities and acts on MayaFlux objects.
Definition Agent.hpp:36
Orchestrates spatial indexing and scheduling for Nexus objects.
Definition Fabric.hpp:38
std::function< T(const Context &)> Producer
Definition Influence.hpp:93
A value of any type, built from the influence context and handed to its targets.
Definition Influence.hpp:91
std::function< T(const PerceptionContext &)> Source
A value of any type, read from the world through the perception context and handed to its targets.
std::variant< std::vector< double >, std::vector< float >, std::vector< uint8_t >, std::vector< uint16_t >, std::vector< uint32_t >, std::vector< std::complex< float > >, std::vector< std::complex< double > >, std::vector< glm::vec2 >, std::vector< glm::vec3 >, std::vector< glm::vec4 >, std::vector< glm::mat4 > > DataVariant
Multi-type data storage for different precision needs.
Definition NDData.hpp:70
void apply_attachment(Attachment &attachment, const InfluenceContext &ctx)
Rebuild the transform from ctx and place every render processor of the buffer.
std::function< void(const InfluenceContext &)> RenderFn
Definition Sinks.hpp:26
void remove_render_sink(std::vector< RenderSink > &sinks, Buffers::BufferManager &mgr, const std::shared_ptr< Core::Window > &window)
Unregister and destroy the render sink targeting window.
Definition Sinks.cpp:194
void follow_attachment(Attachment &attachment, std::optional< glm::vec3 > &position, const std::optional< glm::quat > &orientation)
Set position from the buffer, or fold an outside move into the attachment.
void dispatch_render_sinks(std::vector< RenderSink > &sinks, const InfluenceContext &ctx)
For each sink that has a producer fn, call it and push the result.
Definition Sinks.cpp:215
void push_audio_data(std::vector< AudioSink > &sinks, std::span< const double > samples)
Push samples to every audio sink in sinks.
Definition Sinks.cpp:64
void dispatch_audio_sinks(std::vector< AudioSink > &sinks, const InfluenceContext &ctx)
For each sink that has a producer fn, call it and push the result.
Definition Sinks.cpp:71
void add_audio_sink(std::vector< AudioSink > &sinks, Buffers::BufferManager &mgr, uint32_t channel, std::function< Kakshya::DataVariant(const InfluenceContext &)> fn, std::string fn_name)
Create and register an audio sink on channel.
Definition Sinks.cpp:18
void add_render_sink(std::vector< RenderSink > &sinks, Buffers::BufferManager &mgr, const Portal::Graphics::RenderConfig &config, RenderFn fn, std::string fn_name, const std::optional< glm::vec3 > &initial_position)
Create and register a render sink targeting window.
Definition Sinks.cpp:95
How an Agent attaches to a buffer that already exists.
Data passed to an Emitter or Agent influence function on each commit.
Definition Influence.hpp:17
Data passed to a Sensor or Agent perception function on each commit.
std::shared_ptr< Core::Window > window
Definition Sinks.hpp:69
Holds the plumbing for one graphics output registered from a Nexus object.
Definition Sinks.hpp:63
Unified rendering configuration for graphics buffers.