MayaFlux 1.0.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
Atelier.cpp
Go to the documentation of this file.
1#include "Atelier.hpp"
2
4
13
15
16// =============================================================================
17// Lifecycle
18// =============================================================================
19
21{
22 static Atelier a;
23 return a;
24}
25
26Atelier::Atelier() = default;
27Atelier::~Atelier() = default;
28
30 std::shared_ptr<Nodes::NodeGraphManager> node_graph_manager,
31 std::shared_ptr<Buffers::BufferManager> buffer_manager,
32 std::shared_ptr<Vruta::TaskScheduler> scheduler,
33 std::shared_ptr<Vruta::EventManager> event_manager,
34 std::shared_ptr<Core::WindowManager> window_manager)
35{
36 if (m_initialized) {
38 "Portal::Forma already initialized");
39 return true;
40 }
41
42 m_node_graph_manager = std::move(node_graph_manager);
43 m_buffer_manager = std::move(buffer_manager);
44 m_scheduler = std::move(scheduler);
45 m_event_manager = std::move(event_manager);
46 m_window_manager = std::move(window_manager);
47
48 m_bridge = std::make_unique<Bridge>(*m_scheduler, *m_buffer_manager);
49 m_inspect = std::make_unique<Inspector>(
51
52 m_initialized = true;
53
55 "Portal::Forma initialized");
56 return true;
57}
58
60{
61 if (!m_initialized)
62 return;
63
64 m_bridge.reset();
65 m_inspect.reset();
66 m_atlas_images.clear();
67
68 m_node_graph_manager = nullptr;
69 m_buffer_manager = nullptr;
70 m_scheduler = nullptr;
71 m_event_manager = nullptr;
72 m_window_manager = nullptr;
73
74 m_initialized = false;
75
77 "Portal::Forma shutdown");
78}
79
81{
82 if (!m_initialized) {
83 error<std::runtime_error>(Journal::Component::Portal, Journal::Context::API,
84 std::source_location::current(),
85 "Portal::Forma not initialized - cannot get bridge");
86 }
87 return *m_bridge;
88}
89
91{
92 if (!m_initialized) {
93 error<std::runtime_error>(Journal::Component::Portal, Journal::Context::API,
94 std::source_location::current(),
95 "Portal::Forma not initialized - cannot get inspector");
96 }
97 return *m_inspect;
98}
99
100// =============================================================================
101// Construction
102// =============================================================================
103
104std::shared_ptr<Core::Window> Atelier::create_window(const Core::WindowCreateInfo& info)
105{
106 if (!m_initialized) {
107 error<std::runtime_error>(Journal::Component::Portal, Journal::Context::API,
108 std::source_location::current(),
109 "Portal::Forma not initialized - cannot create window");
110 }
111
112 auto window = m_window_manager->create_window(info);
113 window->show();
114 return window;
115}
116
117std::shared_ptr<Buffers::FormaBuffer> Atelier::create_buffer(Graphics::RenderConfig render)
118{
119 if (!m_initialized) {
120 error<std::runtime_error>(Journal::Component::Portal, Journal::Context::API,
121 std::source_location::current(),
122 "Portal::Forma not initialized - cannot create buffer");
123 }
124
125 if (!render.target_window) {
126 error<std::invalid_argument>(Journal::Component::Portal, Journal::Context::API,
127 std::source_location::current(),
128 "Portal::Forma create_buffer requires a target window");
129 }
130
132 render.triangulate = true;
133
134 auto buf = std::make_shared<Buffers::FormaBuffer>(k_capacity_bytes, render.topology);
136
137 const auto height = std::max(render.target_window->get_create_info().height, 1U);
138 buf->setup_rendering(render);
139
140 if (auto processor = buf->get_render_processor()) {
141 Graphics::MillSpec spec = processor->get_mill_spec();
143 spec.width_scale = 2.0F / static_cast<float>(height);
144 processor->set_mill_spec(spec);
145 }
146 return buf;
147}
148
149std::pair<std::shared_ptr<Layer>, std::shared_ptr<Context>>
150Atelier::create_layer(const std::shared_ptr<Core::Window>& window, std::string name)
151{
152 auto layer = std::make_shared<Layer>();
153 auto ctx = std::make_shared<Context>(layer, window, *m_event_manager, std::move(name));
154
155 MayaFlux::store(ctx);
156
157 return { std::move(layer), std::move(ctx) };
158}
159
161{
162 if (!config.layer && config.ctx) {
163 config.layer = config.ctx->layer();
164 } else if (config.layer && !config.ctx) {
165 config.ctx = std::make_shared<Context>(config.layer, config.window, *m_event_manager, config.name);
166 MayaFlux::store(config.ctx);
167 } else if (!config.layer) {
168 auto [layer, ctx] = create_layer(config.window, config.name);
169 config.layer = std::move(layer);
170 config.ctx = std::move(ctx);
171 }
172 return Surface(std::move(config));
173}
174
176{
178 .window = create_window(window_info),
179 .name = std::move(name),
180 });
181}
182
184 Surface& surface,
185 const Plot::SeriesSpec& spec,
186 uint32_t relate_to,
187 const std::shared_ptr<Buffers::FormaBuffer>& batch)
188{
189 const bool has_labels = !spec.labels.empty() || !spec.tick_labels.empty()
190 || (spec.legend && !spec.legend->entries.empty());
191 std::shared_ptr<Buffers::FormaBuffer> owned_batch;
192 const auto target_of = [&](Graphics::PrimitiveTopology topology) -> FormaTarget {
193 if (!batch && !owned_batch) {
194 Graphics::RenderConfig render = surface.render_config();
195 if (has_labels) {
196 render.fragment_shader = "forma_plot.frag.spv";
197 render.additional_textures.emplace_back("text", nullptr);
198 }
199 owned_batch = create_buffer(std::move(render));
200 }
201 const auto& target_batch = batch ? batch : owned_batch;
202 return FormaTarget::slice_of(target_batch, topology);
203 };
204
205 const auto legend = spec.legend
206 ? std::optional<Plot::LegendLayout>(Plot::layout_legend(*spec.legend))
207 : std::nullopt;
208 if (legend) {
209 for (const auto& swatch : legend->swatches) {
210 (void)Plot::place_rect(surface,
211 target_of(Graphics::PrimitiveTopology::TRIANGLE_STRIP), swatch, relate_to);
212 }
213 }
214
215 for (const auto& label : spec.labels) {
216 (void)Plot::place_label(surface,
218 }
219
220 for (const auto& ticks : spec.tick_labels) {
221 for (const auto& label : Plot::plot_tick_labels(ticks)) {
222 (void)Plot::place_label(surface,
224 }
225 }
226
227 if (legend) {
228 for (const auto& label : legend->labels) {
229 (void)Plot::place_label(surface,
231 }
232 }
233}
234
235} // namespace MayaFlux::Portal::Forma::internal
#define MF_INFO(comp, ctx,...)
#define MF_WARN(comp, ctx,...)
uint32_t label
Definition Contours.cpp:16
std::weak_ptr< Core::Window > window
Definition Picker.cpp:23
size_t a
PrimitiveTopology topology
std::string name
Definition VKDevice.cpp:123
uint32_t height
Two-way binding orchestrator for Forma elements.
Definition Bridge.hpp:74
static FormaTarget slice_of(const std::shared_ptr< Buffers::FormaBuffer > &buffer, std::optional< Graphics::PrimitiveTopology > topology=std::nullopt)
A new empty slice of buffer, drawn after the others.
Definition Target.cpp:19
Where an element's geometry and texture are written.
Definition Target.hpp:22
Forma subsystem for live introspection.
Definition Inspector.hpp:39
Portal::Graphics::RenderConfig render_config(Portal::Graphics::RenderConfig base={}) const
base targeting this Surface's window.
Definition Surface.hpp:227
Named owner of a (Window, Layer, Context) triple: the Forma canvas.
Definition Surface.hpp:121
Surface create_surface(SurfaceConfig config)
Build a Surface from a SurfaceConfig, creating Layer and Context when config.layer/config....
Definition Atelier.cpp:160
std::shared_ptr< Buffers::BufferManager > m_buffer_manager
Definition Atelier.hpp:291
std::shared_ptr< Nodes::NodeGraphManager > m_node_graph_manager
Definition Atelier.hpp:290
std::shared_ptr< Vruta::TaskScheduler > m_scheduler
Definition Atelier.hpp:292
bool initialize(std::shared_ptr< Nodes::NodeGraphManager > node_graph_manager, std::shared_ptr< Buffers::BufferManager > buffer_manager, std::shared_ptr< Vruta::TaskScheduler > scheduler, std::shared_ptr< Vruta::EventManager > event_manager, std::shared_ptr< Core::WindowManager > window_manager)
Definition Atelier.cpp:29
void place_adornments(Surface &surface, const Plot::SeriesSpec &spec, uint32_t relate_to, const std::shared_ptr< Buffers::FormaBuffer > &batch={})
Create and place every adornment declared on spec.
Definition Atelier.cpp:183
std::shared_ptr< Core::Window > create_window(const Core::WindowCreateInfo &info)
Create a window through the stored WindowManager and show it.
Definition Atelier.cpp:104
std::unique_ptr< Bridge > m_bridge
Definition Atelier.hpp:296
std::unique_ptr< Inspector > m_inspect
Definition Atelier.hpp:297
std::shared_ptr< Core::WindowManager > m_window_manager
Definition Atelier.hpp:294
Inspector & inspector()
Inspector instance constructed during initialize.
Definition Atelier.cpp:90
std::shared_ptr< Buffers::FormaBuffer > create_buffer(Graphics::RenderConfig render)
The single buffer construction path.
Definition Atelier.cpp:117
std::unordered_map< const Text::GlyphAtlas *, Text::AtlasImage > m_atlas_images
Definition Atelier.hpp:298
Bridge & bridge()
Bridge instance constructed during initialize.
Definition Atelier.cpp:80
std::shared_ptr< Vruta::EventManager > m_event_manager
Definition Atelier.hpp:293
std::pair< std::shared_ptr< Layer >, std::shared_ptr< Context > > create_layer(const std::shared_ptr< Core::Window > &window, std::string name)
Construct a Layer and a Context wired to window.
Definition Atelier.cpp:150
Process-wide Forma workshop.
Definition Atelier.hpp:55
@ GRAPHICS_BACKEND
Standard graphics processing backend configuration.
@ API
API calls from external code.
@ Portal
High-level user-facing API layer.
uint32_t place_label(Surface &surface, FormaTarget buf, const LabelSpec &spec, uint32_t relate_to)
Place a text label element onto surface using a text-capable target.
Definition Plot.cpp:15
LegendLayout layout_legend(const LegendSpec &spec)
Expand a legend spec into swatch rectangle specs and text label specs.
Definition PlotSpec.cpp:346
std::vector< LabelSpec > plot_tick_labels(const TickLabelsSpec &spec)
Generate construction-free tick label specs.
Definition PlotSpec.cpp:237
uint32_t place_rect(Surface &surface, FormaTarget buf, const RectSpec &spec, uint32_t relate_to)
Place a filled rectangle element onto surface using a target.
Definition Plot.cpp:68
constexpr size_t k_capacity_bytes
Definition Atelier.hpp:37
PrimitiveTopology
Vertex assembly primitive topology.
std::shared_ptr< T > store(std::shared_ptr< T > obj)
Transfer ownership of an existing object to the persistent store for process lifetime.
Definition Persist.hpp:28
Configuration for creating a single window instance.
std::optional< LegendSpec > legend
Optional legend to materialize when the plot is placed.
std::vector< TickLabelsSpec > tick_labels
Concrete tick label generation specs resolved at done() time.
std::vector< LabelSpec > labels
Explicit text labels to materialize when the plot is placed.
std::shared_ptr< Core::Window > window
Target window. Must outlive the Surface.
Definition Surface.hpp:28
std::shared_ptr< Layer > layer
Pre-built Layer, constructed against window.
Definition Surface.hpp:40
std::string name
Unique name scoping the Context's event coroutines.
Definition Surface.hpp:36
std::shared_ptr< Context > ctx
Pre-built Context, already wired to window.
Definition Surface.hpp:44
The single argument every Surface-creating function in this module takes, at every level of abstracti...
Definition Surface.hpp:26
@ WorldPlane
Held in the XY plane, viewpoint ignored.
float width_scale
World units of total ribbon width per unit of a vertex's scalar.
How a PrimitiveMill shapes spans.
std::shared_ptr< Core::Window > target_window
std::vector< std::pair< std::string, std::shared_ptr< Core::VKImage > > > additional_textures
bool triangulate
Reduce supplied spans to triangles before drawing them.
Unified rendering configuration for graphics buffers.