MayaFlux 1.0.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
FormFactory.cpp
Go to the documentation of this file.
1#include "FormFactory.hpp"
2
6
8
9namespace {
10 void join_strip(std::vector<Kakshya::MeshVertex>& strip, const std::vector<Kakshya::MeshVertex>& quad)
11 {
12 strip.push_back(strip.back());
13 strip.push_back(quad.front());
14 strip.insert(strip.end(), quad.begin(), quad.end());
15 }
16}
17
19 Kinesis::AABB2D bounds,
20 float handle_w,
21 glm::vec3 track_color,
22 glm::vec3 handle_color,
23 const std::function<glm::vec2()>& live_offset)
24{
25 GeometryFn<float> fn = [bounds, handle_w, track_color, handle_color, live_offset](
26 float v, std::vector<uint8_t>& out, Element& el) {
27 const glm::vec2 shift = live_offset ? live_offset() : glm::vec2(0.F);
28 const Kinesis::AABB2D live = bounds.translated(shift);
29
30 float x = live.min.x + v * (live.width() - handle_w);
31 float yt = live.min.y + live.height() * 0.35F;
32 float yb = live.min.y + live.height() * 0.65F;
33
34 Kinesis::AABB2D track { .min = glm::vec2(live.min.x, yt), .max = glm::vec2(live.max.x, yb) };
35 Kinesis::AABB2D handle { .min = glm::vec2(x, live.min.y), .max = glm::vec2(x + handle_w, live.max.y) };
36
37 const Kinesis::AABB2D fill { .min = track.min, .max = { x + handle_w * 0.5F, track.max.y } };
38
39 auto verts = Kakshya::to_mesh_vertices(Kinesis::filled_rect(track, track_color));
40 join_strip(verts, Kakshya::to_mesh_vertices(Kinesis::filled_rect(fill, glm::mix(track_color, handle_color, 0.5F))));
41 join_strip(verts, Kakshya::to_mesh_vertices(Kinesis::filled_rect(handle, handle_color)));
42
43 write_verts(out, verts);
44
45 el.bounds_hint = handle;
46 el.contains = {};
47 };
48
49 return { std::move(fn),
51 static_cast<size_t>(16) * sizeof(Kakshya::MeshVertex),
52 drag_with<float>(Kinesis::axis_fraction(bounds, handle_w, true, live_offset)) };
53}
54
56 Kinesis::AABB2D bounds,
57 float handle_h,
58 glm::vec3 track_color,
59 glm::vec3 handle_color,
60 const std::function<glm::vec2()>& live_offset)
61{
62 GeometryFn<float> fn = [bounds, handle_h, track_color, handle_color, live_offset](
63 float v, std::vector<uint8_t>& out, Element& el) {
64 const glm::vec2 shift = live_offset ? live_offset() : glm::vec2(0.F);
65 const Kinesis::AABB2D live = bounds.translated(shift);
66
67 const float y = live.min.y + v * (live.height() - handle_h);
68 const float xl = live.min.x + live.width() * 0.35F;
69 const float xr = live.min.x + live.width() * 0.65F;
70
71 const Kinesis::AABB2D track { .min = { xl, live.min.y }, .max = { xr, live.max.y } };
72 const Kinesis::AABB2D handle { .min = { live.min.x, y }, .max = { live.max.x, y + handle_h } };
73
74 const Kinesis::AABB2D fill { .min = track.min, .max = { track.max.x, y + handle_h * 0.5F } };
75
76 auto verts = Kakshya::to_mesh_vertices(Kinesis::filled_rect(track, track_color));
77 join_strip(verts, Kakshya::to_mesh_vertices(Kinesis::filled_rect(fill, glm::mix(track_color, handle_color, 0.5F))));
78 join_strip(verts, Kakshya::to_mesh_vertices(Kinesis::filled_rect(handle, handle_color)));
79
80 write_verts(out, verts);
81
82 el.bounds_hint = handle;
83 el.contains = {};
84 };
85
86 return { std::move(fn),
88 static_cast<size_t>(16) * sizeof(Kakshya::MeshVertex),
89 drag_with<float>(Kinesis::axis_fraction(bounds, handle_h, false, live_offset)) };
90}
91
93 Kinesis::AABB2D region,
94 float angle_start,
95 float angle_end,
96 glm::vec3 color,
97 const std::function<glm::vec2()>& live_offset)
98{
99 const glm::vec2 center = region.center();
100 const float radius = std::min(region.width(), region.height()) * 0.5F;
101
102 GeometryFn<float> fn = [center, radius, angle_start, angle_end, color, live_offset](
103 float v, std::vector<uint8_t>& out, Element& el) {
104 const glm::vec2 shift = live_offset ? live_offset() : glm::vec2(0.F);
105 const glm::vec2 live_center = center + shift;
106
107 const float angle = angle_start + v * (angle_end - angle_start);
108 const glm::vec2 tip = live_center + radius * glm::vec2(std::cos(angle), std::sin(angle));
109
110 using V = Kakshya::LineVertex;
111 const std::vector<V> verts = {
112 { .position = { live_center.x, live_center.y, 0 }, .color = color },
113 { .position = { tip.x, tip.y, 0 }, .color = color },
114 };
115
116 write_verts(out, verts);
117
118 el.bounds_hint = Kinesis::AABB2D::from_ndc(live_center, glm::vec2(radius));
119 el.contains = Kinesis::circular_bounds(live_center, radius);
120 };
121
122 return { std::move(fn),
124 static_cast<size_t>(2) * sizeof(Kakshya::LineVertex),
125 drag_with<float>(Kinesis::angle_fraction(center, angle_start, angle_end, live_offset)) };
126}
127
129 glm::vec3 color,
130 float size,
131 float hit_radius)
132{
133 GeometryFn<glm::vec2> fn = [color, size, hit_radius](glm::vec2 pos, std::vector<uint8_t>& out, Element& el) {
135 .position = { pos.x, pos.y, 0.0F },
136 .color = color,
137 .size = size,
138 });
139 el.bounds_hint = Kinesis::AABB2D::from_ndc(pos, glm::vec2(hit_radius));
140 el.contains = Kinesis::circular_bounds(pos, hit_radius);
141 };
142
143 return { std::move(fn),
145 sizeof(Kakshya::PointVertex),
146 follow_move() };
147}
148
150 Kinesis::AABB2D bounds,
151 glm::vec3 color,
152 float size,
153 const std::function<glm::vec2()>& live_offset)
154{
155 GeometryFn<glm::vec2> fn = [bounds, color, size, live_offset](
156 glm::vec2 v, std::vector<uint8_t>& out, Element& el) {
157 const glm::vec2 shift = live_offset ? live_offset() : glm::vec2(0.F);
158 const Kinesis::AABB2D live = bounds.translated(shift);
159
160 float x = live.min.x + v.x * live.width();
161 float y = live.min.y + v.y * live.height();
162
163 using V = Kakshya::PointVertex;
164 std::vector<V> verts = {
165 { .position = { x, y, 0 }, .color = color, .size = size },
166 };
167
168 write_verts(out, verts);
169
170 el.bounds_hint = live;
171 el.contains = Kinesis::polygon_bounds(std::span<const glm::vec2> {
172 std::array<glm::vec2, 4> {
173 live.min,
174 glm::vec2(live.max.x, live.min.y),
175 live.max,
176 glm::vec2(live.min.x, live.max.y) } });
177 };
178
179 return { std::move(fn),
181 sizeof(Kakshya::PointVertex),
182 drag_with<glm::vec2>(Kinesis::unit_square(bounds, live_offset)) };
183}
184
186 std::span<const glm::vec2> path,
187 FormaTarget handle_buf,
188 float half_thickness,
189 glm::vec3 track_color,
190 glm::vec3 fill_color,
191 glm::vec3 handle_color,
192 float handle_size,
193 const std::function<glm::vec2()>& live_offset)
194{
195 std::vector<glm::vec2> pts(path.begin(), path.end());
196
197 std::vector<float> seg_lengths;
198 seg_lengths.reserve(pts.size() > 0 ? pts.size() - 1 : 0);
199 float total_len = 0.0F;
200 for (size_t i = 0; i + 1 < pts.size(); ++i) {
201 float l = glm::length(pts[i + 1] - pts[i]);
202 seg_lengths.push_back(l);
203 total_len += l;
204 }
205
206 Kinesis::AABB2D aabb { .min = pts.empty() ? glm::vec2(0.F) : pts[0],
207 .max = pts.empty() ? glm::vec2(0.F) : pts[0] };
208 for (const auto& p : pts) {
209 aabb.min = glm::min(aabb.min, p);
210 aabb.max = glm::max(aabb.max, p);
211 }
212 aabb = aabb.expanded(half_thickness);
213
214 auto project = Kinesis::path_fraction(path, live_offset);
215 const size_t cap = pts.size() * 4 * sizeof(Kakshya::LineVertex);
216
217 GeometryFn<float> fn = [pts = std::move(pts),
218 seg_lengths = std::move(seg_lengths),
219 total_len,
220 aabb,
221 handle_buf = std::move(handle_buf),
222 half_thickness,
223 track_color,
224 fill_color,
225 handle_color,
226 handle_size,
227 live_offset](float v, std::vector<uint8_t>& out, Element& el) {
228 if (pts.size() < 2) {
229 out.clear();
230 return;
231 }
232
233 const glm::vec2 shift = live_offset ? live_offset() : glm::vec2(0.F);
234
235 const float target = std::clamp(v, 0.0F, 1.0F) * total_len;
236
237 // Arc-length interpolation is translation-invariant. It is computed
238 // in pts' own (unshifted) frame, and the shift is applied once to
239 // the result.
240 glm::vec2 handle_pos = pts.front();
241 float accumulated = 0.0F;
242 size_t split_seg = 0;
243 float split_t = 0.0F;
244 for (size_t i = 0; i < seg_lengths.size(); ++i) {
245 if (accumulated + seg_lengths[i] >= target || i + 1 == seg_lengths.size()) {
246 split_t = seg_lengths[i] > 0.0F
247 ? (target - accumulated) / seg_lengths[i]
248 : 0.0F;
249 split_t = std::clamp(split_t, 0.0F, 1.0F);
250 handle_pos = glm::mix(pts[i], pts[i + 1], split_t);
251 split_seg = i;
252 break;
253 }
254 accumulated += seg_lengths[i];
255 }
256 handle_pos += shift;
257
258 std::vector<glm::vec2> live_pts;
259 live_pts.reserve(pts.size());
260 for (const auto& p : pts)
261 live_pts.push_back(p + shift);
262
263 auto verts = Kinesis::polyline(live_pts, track_color);
264
265 auto fill = Kinesis::polyline(
266 std::span<const glm::vec2>(live_pts).subspan(0, split_seg + 1),
267 fill_color);
268 verts.insert(verts.end(), fill.begin(), fill.end());
269
270 if (split_t > 0.0F) {
271 verts.push_back({ .position = { live_pts[split_seg].x, live_pts[split_seg].y, 0.0F }, .color = fill_color });
272 verts.push_back({ .position = { handle_pos.x, handle_pos.y, 0.0F }, .color = fill_color });
273 }
274
275 write_verts(out, verts);
276
277 el.bounds_hint = aabb.translated(shift);
278 el.contains = Kinesis::stroke_bounds(live_pts, half_thickness);
279
280 if (handle_buf) {
282 .position = { handle_pos.x, handle_pos.y, 0.0F },
283 .color = handle_color,
284 .size = handle_size,
285 };
286 std::vector<uint8_t> hbytes(sizeof(hv));
287 std::memcpy(hbytes.data(), &hv, sizeof(hv));
288 handle_buf.submit(hbytes);
289 }
290 };
291
292 return { std::move(fn),
294 cap,
295 drag_with<float>(std::move(project)) };
296}
297
299 Kinesis::AABB2D region,
300 glm::vec3 color_off,
301 glm::vec3 color_on,
302 const std::function<glm::vec2()>& live_offset)
303{
304 GeometryFn<bool> fn = [region, color_off, color_on, live_offset](
305 bool v, std::vector<uint8_t>& out, Element& el) {
306 const glm::vec2 shift = live_offset ? live_offset() : glm::vec2(0.F);
307 const Kinesis::AABB2D live = region.translated(shift);
308
309 write_verts(out, Kakshya::to_mesh_vertices(Kinesis::filled_rect(live, v ? color_on : color_off)));
310 el.bounds_hint = live;
311 el.contains = {};
312 };
313
314 return { std::move(fn),
316 static_cast<size_t>(4) * sizeof(Kakshya::MeshVertex),
317 press_flip() };
318}
319
321 Kinesis::AABB2D bounds,
322 bool horizontal,
323 glm::vec3 fill_color,
324 glm::vec3 track_color,
325 const std::function<glm::vec2()>& live_offset)
326{
327 GeometryFn<float> fn = [bounds, horizontal, fill_color, track_color, live_offset](
328 float v, std::vector<uint8_t>& out, Element& el) {
329 const glm::vec2 shift = live_offset ? live_offset() : glm::vec2(0.F);
330 const Kinesis::AABB2D live = bounds.translated(shift);
331
332 const float t = std::clamp(v, 0.F, 1.F);
333
334 Kinesis::AABB2D fill {}, remainder {};
335 if (horizontal) {
336 const float split = live.min.x + t * live.width();
337 fill = { .min = live.min, .max = { split, live.max.y } };
338 remainder = { .min = { split, live.min.y }, .max = live.max };
339 } else {
340 const float split = live.min.y + t * live.height();
341 fill = { .min = live.min, .max = { live.max.x, split } };
342 remainder = { .min = { live.min.x, split }, .max = live.max };
343 }
344
345 auto verts = Kakshya::to_mesh_vertices(Kinesis::filled_rect(fill, fill_color));
346 auto rest = Kakshya::to_mesh_vertices(Kinesis::filled_rect(remainder, track_color));
347 verts.insert(verts.end(), rest.begin(), rest.end());
348
349 write_verts(out, verts);
350
351 el.bounds_hint = live;
352 el.contains = {};
353 };
354
355 return { std::move(fn),
357 static_cast<size_t>(8) * sizeof(Kakshya::MeshVertex) };
358}
359
361 float arm_len,
362 glm::vec3 color,
363 float thickness,
364 float hit_radius)
365{
366 GeometryFn<glm::vec2> fn = [arm_len, color, thickness, hit_radius](
367 glm::vec2 pos, std::vector<uint8_t>& out, Element& el) {
368 using V = Kakshya::LineVertex;
369 const std::array<V, 4> verts { {
370 { .position = { pos.x - arm_len, pos.y, 0.F }, .color = color, .thickness = thickness },
371 { .position = { pos.x + arm_len, pos.y, 0.F }, .color = color, .thickness = thickness },
372 { .position = { pos.x, pos.y - arm_len, 0.F }, .color = color, .thickness = thickness },
373 { .position = { pos.x, pos.y + arm_len, 0.F }, .color = color, .thickness = thickness },
374 } };
375 write_verts(out, verts);
376 el.bounds_hint = Kinesis::AABB2D::from_ndc(pos, glm::vec2(arm_len));
377 el.contains = Kinesis::circular_bounds(pos, hit_radius);
378 };
379
380 return { std::move(fn),
382 static_cast<size_t>(4) * sizeof(Kakshya::LineVertex),
383 follow_move() };
384}
385
387 Kinesis::AABB2D bounds,
388 glm::vec3 color,
389 float thickness,
390 const std::function<glm::vec2()>& live_offset,
391 size_t samples)
392{
393 GeometryFn<std::vector<float>> fn = [bounds, color, thickness, live_offset](
394 const std::vector<float>& v, std::vector<uint8_t>& out, Element& el) {
395 const glm::vec2 shift = live_offset ? live_offset() : glm::vec2(0.F);
396 const Kinesis::AABB2D live = bounds.translated(shift);
397
398 if (v.size() < 2) {
399 out.clear();
400 el.bounds_hint = live;
401 el.contains = Kinesis::polygon_bounds(std::span<const glm::vec2> {
402 std::array<glm::vec2, 4> {
403 live.min,
404 glm::vec2(live.max.x, live.min.y),
405 live.max,
406 glm::vec2(live.min.x, live.max.y) } });
407 return;
408 }
409
410 const auto n = v.size();
411 const float x_step = live.width() / static_cast<float>(n - 1);
412
413 std::vector<Kakshya::LineVertex> verts;
414 verts.reserve((n - 1) * 2);
415
416 for (size_t i = 0; i + 1 < n; ++i) {
417 const float xa = live.min.x + static_cast<float>(i) * x_step;
418 const float xb = live.min.x + static_cast<float>(i + 1) * x_step;
419 const float ya = live.min.y + std::clamp(v[i], 0.F, 1.F) * live.height();
420 const float yb = live.min.y + std::clamp(v[i + 1], 0.F, 1.F) * live.height();
421
422 verts.push_back({ .position = { xa, ya, 0.F }, .color = color, .thickness = thickness });
423 verts.push_back({ .position = { xb, yb, 0.F }, .color = color, .thickness = thickness });
424 }
425
426 write_verts(out, verts);
427
428 el.bounds_hint = live;
429 el.contains = Kinesis::polygon_bounds(std::span<const glm::vec2> {
430 std::array<glm::vec2, 4> {
431 live.min,
432 glm::vec2(live.max.x, live.min.y),
433 live.max,
434 glm::vec2(live.min.x, live.max.y) } });
435 };
436
437 Form<std::vector<float>> form { std::move(fn) };
439 if (samples > 1)
440 form.capacity = (samples - 1) * 2 * sizeof(Kakshya::LineVertex);
441 form.wire = paint_over(bounds);
442 return form;
443}
444
446 Context& ctx,
447 uint32_t id,
448 const std::shared_ptr<MappedState<std::vector<float>>>& state,
449 Kinesis::AABB2D bounds)
450{
451 struct DragState {
452 std::optional<size_t> prev_index;
453 };
454 auto ds = std::make_shared<DragState>();
455
457 [state, bounds, ds](uint32_t, glm::vec2 ndc) {
458 auto& v = state->value;
459 if (v.empty())
460 return;
461
462 const float t = (ndc.x - bounds.min.x) / bounds.width();
463 const float a = (ndc.y - bounds.min.y) / bounds.height();
464
465 Kinesis::stroke_samples(v, ds->prev_index, t, a);
466 ++state->version;
467 });
468
469 ctx.on_release(id, IO::MouseButtons::Left, [ds](uint32_t, glm::vec2) {
470 ds->prev_index = std::nullopt;
471 });
472}
473
475 Kinesis::AABB2D track,
476 glm::vec3 color)
477{
478 GeometryFn<glm::vec2> fn = [track, color](
479 glm::vec2 extent, std::vector<uint8_t>& out, Element& el) {
480 const float len = std::clamp(extent.y, 0.F, 1.F) * track.height();
481 const float top = track.max.y - std::clamp(extent.x, 0.F, 1.F) * (track.height() - len);
482 const Kinesis::AABB2D bar { .min = { track.min.x, top - len }, .max = { track.max.x, top } };
483
485
486 el.bounds_hint = track;
487 el.contains = {};
488 };
489
490 return { std::move(fn),
492 static_cast<size_t>(4) * sizeof(Kakshya::MeshVertex) };
493}
494
495} // namespace MayaFlux::Portal::Forma::Geometry
glm::vec3 color
Definition Decoder.cpp:97
bool size
float radius
size_t a
std::vector< float > * out
void on_release(uint32_t id, IO::MouseButtons btn, PressFn fn)
Called when a mouse button is released over an element.
Definition Context.cpp:43
void on_drag(uint32_t id, IO::MouseButtons btn, MoveFn fn)
Called on each mouse-move event while btn is held, tracking the element where the drag began even whe...
Definition Context.cpp:53
Event wiring between a Layer and a window surface.
Definition Context.hpp:41
Where an element's geometry and texture are written.
Definition Target.hpp:22
std::vector< MeshVertex > to_mesh_vertices(std::span< const Vertex > vertices, glm::vec2 weight_range)
Batch-project raw Vertex vector to MeshVertex.
void stroke_samples(std::span< float > samples, std::optional< size_t > &previous, float position, float level) noexcept
Write a level into an evenly spaced sample array at a fractional position, filling linearly from the ...
Definition Stroke.hpp:24
std::function< bool(glm::vec2)> polygon_bounds(std::span< const glm::vec2 > vertices)
Containment test for a convex or concave polygon.
Definition Bounds.hpp:272
std::vector< Kakshya::LineVertex > polyline(std::span< const glm::vec2 > pts, glm::vec3 color, float thickness)
Polyline as a LINE_LIST (open path, 2 * (pts.size() - 1) vertices).
std::function< glm::vec2(glm::vec2)> unit_square(AABB2D bounds, const std::function< glm::vec2()> &live_offset={}) noexcept
Unit-square coordinates of a point within bounds.
std::function< float(glm::vec2)> path_fraction(std::span< const glm::vec2 > points, const std::function< glm::vec2()> &live_offset={})
Normalized arc-length position of the closest point on a polyline.
std::function< float(glm::vec2)> angle_fraction(glm::vec2 center, float angle_start, float angle_end, const std::function< glm::vec2()> &live_offset={}) noexcept
Fraction along an angular sweep about center.
std::function< bool(glm::vec2)> stroke_bounds(std::span< const glm::vec2 > points, float half_thickness)
Containment test for a polyline with a uniform half-thickness.
Definition Bounds.hpp:312
std::function< bool(glm::vec2)> circular_bounds(glm::vec2 center, float radius) noexcept
Containment test for a circle.
Definition Bounds.hpp:253
std::array< Kakshya::Vertex, 4 > filled_rect(Kinesis::AABB2D region, glm::vec3 color)
Generate a filled TRIANGLE_STRIP quad from an AABB2D.
std::function< float(glm::vec2)> axis_fraction(AABB2D bounds, float handle_extent=0.F, bool horizontal=true, const std::function< glm::vec2()> &live_offset={}) noexcept
Fraction along one axis of bounds, inverse to fader placement.
Form< float > level_meter(Kinesis::AABB2D bounds, bool horizontal, glm::vec3 fill_color, glm::vec3 track_color, const std::function< glm::vec2()> &live_offset)
Geometry function for a level meter in NDC space.
Form< std::vector< float > > drawable_canvas(Kinesis::AABB2D bounds, glm::vec3 color, float thickness, const std::function< glm::vec2()> &live_offset, size_t samples)
Geometry function for a drawable curve canvas in NDC space.
Form< float > vertical_fader(Kinesis::AABB2D bounds, float handle_h, glm::vec3 track_color, glm::vec3 handle_color, const std::function< glm::vec2()> &live_offset)
Geometry function for a vertical fader in NDC space.
void wire_canvas_drag(Context &ctx, uint32_t id, const std::shared_ptr< MappedState< std::vector< float > > > &state, Kinesis::AABB2D bounds)
Wire drag interaction for a drawable canvas element.
auto follow_move()
Produce a Form::wire that writes the cursor position on hover.
Form< glm::vec2 > scroll_indicator(Kinesis::AABB2D track, glm::vec3 color)
Geometry function for Scrollable's default scroll indicator visual.
Form< float > radial(Kinesis::AABB2D region, float angle_start, float angle_end, glm::vec3 color, const std::function< glm::vec2()> &live_offset)
Geometry function for a radial indicator in NDC space.
auto paint_over(Kinesis::AABB2D bounds)
Produce a Form::wire that registers canvas painting over bounds.
Form< bool > toggle(Kinesis::AABB2D region, glm::vec3 color_off, glm::vec3 color_on, const std::function< glm::vec2()> &live_offset)
Geometry function for a boolean toggle in NDC space.
Form< glm::vec2 > position_picker(Kinesis::AABB2D bounds, glm::vec3 color, float size, const std::function< glm::vec2()> &live_offset)
Geometry function for a 2D position picker in NDC space.
Form< float > horizontal_fader(Kinesis::AABB2D bounds, float handle_w, glm::vec3 track_color, glm::vec3 handle_color, const std::function< glm::vec2()> &live_offset)
Geometry function for a horizontal fader in NDC space.
auto press_flip(IO::MouseButtons btn=IO::MouseButtons::Left)
Produce a Form::wire that registers a press flipping a bool state.
Form< glm::vec2 > point(glm::vec3 color, float size, float hit_radius)
Geometry function for a positioned point in NDC space.
void write_verts(std::vector< uint8_t > &out, const std::vector< V > &verts)
Write a vertex array into a GeometryFn output buffer.
Definition Geometry.hpp:35
Form< float > stroke_slider(std::span< const glm::vec2 > path, FormaTarget handle_buf, float half_thickness, glm::vec3 track_color, glm::vec3 fill_color, glm::vec3 handle_color, float handle_size, const std::function< glm::vec2()> &live_offset)
Geometry function for a value scrubber along an arbitrary polyline.
Form< glm::vec2 > crosshair(float arm_len, glm::vec3 color, float thickness, float hit_radius)
Geometry function for a crosshair indicator in NDC space.
std::function< void(T value, std::vector< uint8_t > &out_bytes, Element &element)> GeometryFn
Geometry function signature.
Definition Mapped.hpp:71
Vertex type for line primitives (LINE_LIST / LINE_STRIP topology)
Vertex type for indexed triangle mesh primitives (TRIANGLE_LIST topology)
Vertex type for point primitives (POINT_LIST topology)
static AABB2D from_ndc(glm::vec2 center, glm::vec2 half) noexcept
Definition Bounds.hpp:94
float height() const noexcept
Definition Bounds.hpp:80
bool contains(glm::vec2 p) const noexcept
Definition Bounds.hpp:67
AABB2D translated(glm::vec2 offset) const noexcept
Definition Bounds.hpp:84
glm::vec2 center() const noexcept
Definition Bounds.hpp:82
float width() const noexcept
Definition Bounds.hpp:79
Axis-aligned bounding rectangle in a 2D coordinate space.
Definition Bounds.hpp:63
bool contains(const glm::vec3 &p) const noexcept
Definition Bounds.hpp:192
AABB3D translated(const glm::vec3 &offset) const noexcept
Definition Bounds.hpp:210
AABB3D expanded(float margin) const noexcept
Definition Bounds.hpp:215
A bounded, renderable region on a window surface.
Definition Element.hpp:61
Graphics::PrimitiveTopology topology
Topology matching the vertex kind geometry writes.
Definition Geometry.hpp:88
A geometry function plus everything its realization requires.
Definition Geometry.hpp:83
Value carrier for a Mapped primitive.
Definition Mapped.hpp:40