MayaFlux 1.0.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
Collapsible.cpp
Go to the documentation of this file.
1#include "Collapsible.hpp"
2#include "Entry.hpp"
3
5
9
11
12namespace {
13
14 [[nodiscard]] GeometryFn<bool> collapsible_header_geom(
15 float y_top,
16 float x_min,
17 float x_max,
18 float row_h,
19 glm::vec3 color_closed,
20 glm::vec3 color_open)
21 {
22 return [y_top, x_min, x_max, row_h, color_closed, color_open](
23 bool open, std::vector<uint8_t>& out, Element& el) {
24 const float bot = y_top - row_h;
25 const glm::vec3 col = open ? color_open : color_closed;
26
27 const size_t stride = Kakshya::VertexLayout::for_meshes().stride_bytes;
28 out.assign(static_cast<size_t>(6) * stride, 0);
29
30 const glm::vec3 bl { x_min, bot, 0.F };
31 const glm::vec3 br { x_max, bot, 0.F };
32 const glm::vec3 tl { x_min, y_top, 0.F };
33 const glm::vec3 tr { x_max, y_top, 0.F };
34
35 auto write = [&](size_t idx, glm::vec3 pos) {
36 auto* v = out.data() + idx * stride;
37 std::memcpy(v, &pos, 12);
38 std::memcpy(v + 12, &col, 12);
39 };
40
41 write(0, bl);
42 write(1, br);
43 write(2, tl);
44 write(3, br);
45 write(4, tr);
46 write(5, tl);
47
48 el.bounds_hint = Kinesis::AABB2D {
49 .min = { x_min, bot },
50 .max = { x_max, y_top },
51 };
52 };
53 }
54
55} // namespace
56
57// =============================================================================
58// Collapsible
59// =============================================================================
60
62 FormaTarget in_buf,
63 Surface& surface,
64 LayoutCursor& cursor,
65 float x_min, float x_max, float row_h)
66{
67 buf = std::move(in_buf);
68
69 const Kinesis::AABB2D advanced = cursor.advance(row_h);
70 const float y_top = advanced.max.y;
71 const Kinesis::AABB2D row_rect { .min = { x_min, advanced.min.y }, .max = { x_max, y_top } };
72
73 auto open_state = std::make_shared<MappedState<bool>>();
74 open_state->write(m_initially_open);
75
76 uint32_t hid = 0;
77
78 if (m_label_text.empty()) {
79 Mapped<bool> mapped;
80 mapped.state = open_state;
81 mapped.geometry_fn = collapsible_header_geom(y_top, x_min, x_max, row_h, m_color_closed, m_color_open);
82 mapped.element.buffer = buf;
83 mapped.element.bounds_hint = row_rect;
84
85 hid = surface.layer().add(mapped.element);
86 mapped.element.id = hid;
87 open_state->id = hid;
88 mapped.sync();
89
90 surface.ctx().on_press(hid, IO::MouseButtons::Left,
91 [m = std::move(mapped), open = open_state, surface, hid](uint32_t, glm::vec2) mutable {
92 const bool next = !open->value;
93 open->write(next);
94 for (auto rel_id : surface.layer().related_ids(hid))
95 surface.layer().set_visible(rel_id, next);
96 m.sync();
97 });
98 } else {
99 const glm::uvec2 dims = row_pixel_dims(surface.window(), x_min, x_max, row_h);
100
101 auto params = std::make_shared<Portal::Text::PressParams>(Portal::Text::PressParams {
103 .background = { m_initially_open ? m_color_open : m_color_closed, 1.F },
104 .render_bounds = dims,
105 });
106
107 Element el;
108 el.buffer = buf;
109 el.bounds_hint = row_rect;
110 el.with_text(m_label_text, *params, row_rect);
111
112 hid = surface.layer().add(el);
113 open_state->id = hid;
114
115 auto repress = [el, surface, params, label_text = m_label_text,
116 open = open_state, color_closed = m_color_closed,
117 color_open = m_color_open, x_min, x_max, row_h]() mutable {
118 params->render_bounds = row_pixel_dims(surface.window(), x_min, x_max, row_h);
119 params->background = { open->value ? color_open : color_closed, 1.F };
120 el.set_text(label_text, *params);
121 };
122
123 surface.ctx().on_press(hid, IO::MouseButtons::Left,
124 [open = open_state, surface, hid, repress](uint32_t, glm::vec2) mutable {
125 const bool next = !open->value;
126 open->write(next);
127 for (auto rel_id : surface.layer().related_ids(hid))
128 surface.layer().set_visible(rel_id, next);
129 repress();
130 });
131
132 surface.ctx().on_resize(hid,
133 [repress](uint32_t, uint32_t) mutable { repress(); });
134 }
135
136 header_bounds = row_rect;
137 header_id = hid;
138 open = open_state;
139 cursor_out = cursor;
140 return *this;
141}
142
144 FormaTarget in_buf,
145 Surface& surface,
146 LayoutCursor& cursor,
147 float row_h)
148{
149 return place(std::move(in_buf), surface, cursor,
150 cursor.x_min(), cursor.x_max(), row_h);
151}
152
153void Collapsible::attach(Layer& layer, uint32_t body_id) const
154{
155 if (!open)
156 return;
157
158 layer.relate(header_id, body_id);
159 layer.set_visible(body_id, open->value);
160}
161
162// =============================================================================
163// Free function escape hatch
164// =============================================================================
165
167 FormaTarget buf,
168 Surface& surface,
169 LayoutCursor& cursor,
170 float x_min,
171 float x_max,
172 float row_h,
173 bool initially_open,
174 glm::vec3 color_closed,
175 glm::vec3 color_open,
176 std::string label)
177{
178 return Collapsible {}
179 .initially_open(initially_open)
180 .closed_color(color_closed)
181 .open_color(color_open)
182 .label(std::move(label))
183 .place(std::move(buf), surface, cursor, x_min, x_max, row_h);
184}
185
186} // namespace MayaFlux::Portal::Forma
uint32_t label
Definition Contours.cpp:16
std::vector< float > * out
void on_press(uint32_t id, IO::MouseButtons btn, PressFn fn)
Called when a mouse button is pressed over an element.
Definition Context.cpp:38
Where an element's geometry and texture are written.
Definition Target.hpp:22
uint32_t id() const noexcept
Explicit id accessor, for clarity in chained expressions.
Definition Layer.hpp:73
bool set_visible(uint32_t id, bool visible)
Definition Layer.cpp:91
bool relate(uint32_t primary_id, uint32_t related_id)
Record that related_id belongs with primary_id.
Definition Layer.cpp:205
std::vector< uint32_t > related_ids(uint32_t primary_id) const
Return the ids related to primary_id, or empty if none.
Definition Layer.cpp:237
Slot add(Element element)
Add an element to the layer.
Definition Layer.cpp:9
Flat registry of Elements on a surface.
Definition Layer.hpp:24
Kinesis::AABB2D advance(float height)
Advance the cursor downward by height and return the NDC AABB occupied by the primitive just placed,...
Reactive Y-position accumulator for vertical primitive stacking.
const std::shared_ptr< Core::Window > & window() const noexcept
Access the rendering target window.
Definition Surface.hpp:178
Context & ctx() noexcept
Access the event router.
Definition Surface.hpp:170
Layer & layer() noexcept
Access the spatial registry.
Definition Surface.hpp:159
Named owner of a (Window, Layer, Context) triple: the Forma canvas.
Definition Surface.hpp:121
void open(std::span< const float > mask, std::span< float > tmp, std::span< float > dst, uint32_t w, uint32_t h, uint32_t radius)
Morphological opening writing into dst.
Collapsible make_collapsible(FormaTarget buf, Surface &surface, LayoutCursor &cursor, float x_min, float x_max, float row_h, bool initially_open, glm::vec3 color_closed, glm::vec3 color_open, std::string label)
Construct a collapsible header strip.
glm::uvec2 row_pixel_dims(const std::shared_ptr< Core::Window > &window, float x_min, float x_max, float row_h)
Convert an NDC row rect into integer pixel dimensions.
Definition Entry.cpp:12
uint32_t stride_bytes
Total bytes per vertex (stride in Vulkan terms) e.g., 3 floats (position) + 3 floats (normal) = 24 by...
static VertexLayout for_meshes(uint32_t stride=60)
Factory: layout for MeshVertex (position, color, weight, uv, normal, tangent)
Axis-aligned bounding rectangle in a 2D coordinate space.
Definition Bounds.hpp:63
glm::vec4 m_label_color
Label text color. Default opaque white.
Kinesis::AABB2D header_bounds
NDC region occupied by the header strip. Valid after place().
std::shared_ptr< MappedState< bool > > open
Open/closed state. Valid after place(). Write to toggle.
MAYAFLUX_API Collapsible & place(FormaTarget buf, Surface &surface, LayoutCursor &cursor, float x_min, float x_max, float row_h)
Register the header element and wire the toggle callback.
uint32_t header_id
Element id of the header strip. Valid after place().
Collapsible & closed_color(glm::vec3 c)
std::string m_label_text
Text label drawn over the header. Empty = color only.
glm::vec3 m_color_closed
Background color when closed. Default: glm::vec3(0.25F).
Collapsible & open_color(glm::vec3 c)
FormaTarget buf
FormaBuffer backing the header geometry. Valid after place().
Collapsible & label(std::string text)
Draw a text label over the header, background included.
Collapsible & initially_open(bool v)
glm::vec3 m_color_open
Background color when open. Default: glm::vec3(0.35F).
MAYAFLUX_API void attach(Layer &layer, uint32_t body_id) const
Relate a body element to this collapsible and sync its visibility to the current open state.
bool m_initially_open
Starting toggle state. Default: true (open).
LayoutCursor cursor_out
Cursor positioned below the header, ready for body elements. Valid after place().
A collapsible header strip.
FormaTarget buffer
Where this region's rendered output is written: a buffer of its own, or a slice of one it shares.
Definition Element.hpp:82
uint32_t id
Stable id assigned by Layer::add. Never zero.
Definition Element.hpp:63
std::optional< Kinesis::AABB2D > bounds_hint
Optional fast-reject bounds in NDC space.
Definition Element.hpp:67
A bounded, renderable region on a window surface.
Definition Element.hpp:61
std::shared_ptr< MappedState< T > > state
Shared value carrier. External systems hold a copy of this ptr.
Definition Mapped.hpp:98
void sync(Layer *layer=nullptr)
Call whenever state may have changed: once per graphics tick for a continuously-changing source with ...
Definition Mapped.hpp:149
GeometryFn< T > geometry_fn
Geometry regeneration function. Set once at construction.
Definition Mapped.hpp:101
Element element
The Element registered with the Layer.
Definition Mapped.hpp:105
Infrastructure for a continuously-mapped value whose GPU geometry tracks it.
Definition Mapped.hpp:96
glm::vec4 color
RGBA color applied to all glyphs not covered by a span in spans.
Definition InkPress.hpp:70
Construction parameters for press().
Definition InkPress.hpp:65