Visual Computing Library
Loading...
Searching...
No Matches
render_app.h
1/*****************************************************************************
2 * VCLib *
3 * Visual Computing Library *
4 * *
5 * Copyright(C) 2021-2025 *
6 * Visual Computing Lab *
7 * ISTI - Italian National Research Council *
8 * *
9 * All rights reserved. *
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the Mozilla Public License Version 2.0 as published *
13 * by the Mozilla Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 * This program is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
19 * Mozilla Public License Version 2.0 *
20 * (https://www.mozilla.org/en-US/MPL/2.0/) for more details. *
21 ****************************************************************************/
22
23#ifndef VCL_RENDER_RENDER_APP_H
24#define VCL_RENDER_RENDER_APP_H
25
26#include "concepts/blocker_event_drawer.h"
27#include "concepts/canvas.h"
28#include "concepts/event_drawer.h"
29#include "concepts/window_manager.h"
30#include "input.h"
31#include "read_buffer_types.h"
32
33#include <vclib/space/core/point.h>
34
35namespace vcl {
36
56template<
57 template<typename>
58 typename WindowManagerT,
59 template<typename>
60 typename CanvasT,
61 template<typename>
62 typename... Drawers>
63class RenderApp :
64 public WindowManagerT<RenderApp<WindowManagerT, CanvasT, Drawers...>>,
65 public CanvasT<RenderApp<WindowManagerT, CanvasT, Drawers...>>,
66 public Drawers<RenderApp<WindowManagerT, CanvasT, Drawers...>>...
67{
68 using WindowManagerType = WindowManagerT<RenderApp>;
69 using CanvasType = CanvasT<RenderApp>;
70
71 static_assert(
73 "The first template parameter type of the RenderApp class must be a "
74 "class that satisfies the WindowManagerConcept.");
75
76 static_assert(
78 "The second template parameter type of the RenderApp class must be a "
79 "class that satisfies the CanvasConcept.");
80
81 static_assert(
83 "All the Drawer types must satisfy the DrawerConcept.");
84
85 KeyModifiers mKeyModifiers = {KeyModifier::NO_MODIFIER};
86
87 // hide CanvasType member functions
88 using CanvasType::onInit;
89 using CanvasType::onPaint;
90 using CanvasType::onReadDepth;
91 using CanvasType::onResize;
92 using CanvasType::onScreenshot;
93 using CanvasType::setDefaultClearColor;
94 using CanvasType::size;
95
96 // hide WindowManagerType member functions
97 using WindowManagerType::displayId;
98 using WindowManagerType::winId;
99
100protected:
101 using CanvasType::viewId;
102
103 // TODO: find a way to hide the Drawer member functions here
104
105public:
106 using ParentType = WindowManagerType::ParentType;
107
108 // Attorneys
109 class CNV;
110 class WM;
111 class DRW;
112
113 RenderApp(ParentType* parent = nullptr) :
114 RenderApp("RenderApp", 1024, 768, parent)
115 {
116 }
117
118 RenderApp(
119 const std::string& windowTitle,
120 uint width = 1024,
121 uint height = 768,
122 ParentType* parent = nullptr) :
123 WindowManagerType(windowTitle, width, height, parent),
124 CanvasType(
125 (void*) WindowManagerType::winId(),
126 width * WindowManagerType::dpiScale().x(),
127 height * WindowManagerType::dpiScale().y(),
128 WindowManagerType::displayId()),
130 width * WindowManagerType::dpiScale().x(),
131 height * WindowManagerType::dpiScale().y())...
132 {
133 }
134
135private:
155 template<typename D, typename... Others>
157 {
158 bool block = false;
159 if constexpr (EventDrawerConcept<D>) {
160 if constexpr (BlockerEventDrawerConcept<D>) {
161 block = lambda.template operator()<D>(this);
162 }
163 else {
164 lambda.template operator()<D>(this);
165 }
166 }
167 if constexpr (sizeof...(Others) > 0) {
168 if (!block) {
170 }
171 }
172 }
173
174 // Base case when there are no drawers
175 void callEventFunForDrawers(auto lambda) {}
176
177 /***** Member functions called by WindowManagerType *****/
178 // Documentation is in the RenderApp::WM inner class
179
180 void wmInit()
181 {
182 CanvasType::onInit();
183 (static_cast<Drawers<RenderApp>*>(this)->onInit(CanvasType::viewId()),
184 ...);
185 }
186
187 void wmResize(uint width, uint height)
188 {
189 CanvasType::onResize(width, height);
190
191 // call the onResize member function of each Drawer object.
192 // NOTE: use static_cast<Drawers*>(this)->function() to call the
193 // right VIRTUAL function of the Drawer object.
194 (static_cast<Drawers<RenderApp>*>(this)->onResize(width, height), ...);
195 }
196
197 void wmPaint() { CanvasType::onPaint(); }
198
199 void wmSetModifiers(const KeyModifiers& modifiers)
200 {
201 mKeyModifiers = modifiers;
202 }
203
204 void wmKeyPress(Key::Enum key)
205 {
206 // given this object t and the type of a Drawer D, call the event member
207 // function of the Drawer object
208 auto lambda = [&]<typename D>(auto* t) {
209 // NOTE: use static_cast<Drawers*>(this)->function() to call the
210 // right VIRTUAL function of the Drawer object.
211 return static_cast<D*>(t)->onKeyPress(key, mKeyModifiers);
212 };
213
214 // call the lambda for all the drawers
215 callEventFunForDrawers<Drawers<RenderApp>...>(lambda);
216 }
217
218 void wmKeyRelease(Key::Enum key)
219 {
220 // given this object t and the type of a Drawer D, call the event member
221 // function of the Drawer object
222 auto lambda = [&]<typename D>(auto* t) {
223 // NOTE: use static_cast<Drawers*>(this)->function() to call the
224 // right VIRTUAL function of the Drawer object.
225 return static_cast<D*>(t)->onKeyRelease(key, mKeyModifiers);
226 };
227
228 // call the lambda for all the drawers
229 callEventFunForDrawers<Drawers<RenderApp>...>(lambda);
230 }
231
232 void wmMouseMove(double x, double y)
233 {
234 // given this object t and the type of a Drawer D, call the event member
235 // function of the Drawer object
236 auto lambda = [&]<typename D>(auto* t) {
237 // NOTE: use static_cast<Drawers*>(this)->function() to call the
238 // right VIRTUAL function of the Drawer object.
239 return static_cast<D*>(t)->onMouseMove(x, y, mKeyModifiers);
240 };
241
242 // call the lambda for all the drawers
243 callEventFunForDrawers<Drawers<RenderApp>...>(lambda);
244 }
245
246 void wmMousePress(MouseButton::Enum button, double x, double y)
247 {
248 // given this object t and the type of a Drawer D, call the event member
249 // function of the Drawer object
250 auto lambda = [&]<typename D>(auto* t) {
251 // NOTE: use static_cast<Drawers*>(this)->function() to call the
252 // right VIRTUAL function of the Drawer object.
253 return static_cast<D*>(t)->onMousePress(
254 button, x, y, mKeyModifiers);
255 };
256
257 // call the lambda for all the drawers
258 callEventFunForDrawers<Drawers<RenderApp>...>(lambda);
259 }
260
261 void wmMouseRelease(MouseButton::Enum button, double x, double y)
262 {
263 // given this object t and the type of a Drawer D, call the event member
264 // function of the Drawer object
265 auto lambda = [&]<typename D>(auto* t) {
266 // NOTE: use static_cast<Drawers*>(this)->function() to call the
267 // right VIRTUAL function of the Drawer object.
268 return static_cast<D*>(t)->onMouseRelease(
269 button, x, y, mKeyModifiers);
270 };
271
272 // call the lambda for all the drawers
273 callEventFunForDrawers<Drawers<RenderApp>...>(lambda);
274 }
275
276 void wmMouseDoubleClick(MouseButton::Enum button, double x, double y)
277 {
278 // given this object t and the type of a Drawer D, call the event member
279 // function of the Drawer object
280 auto lambda = [&]<typename D>(auto* t) {
281 // NOTE: use static_cast<Drawers*>(this)->function() to call the
282 // right VIRTUAL function of the Drawer object.
283 return static_cast<D*>(t)->onMouseDoubleClick(
284 button, x, y, mKeyModifiers);
285 };
286
287 // call the lambda for all the drawers
288 callEventFunForDrawers<Drawers<RenderApp>...>(lambda);
289 }
290
291 void wmMouseScroll(double x, double y)
292 {
293 // given this object t and the type of a Drawer D, call the event member
294 // function of the Drawer object
295 auto lambda = [&]<typename D>(auto* t) {
296 // NOTE: use static_cast<Drawers*>(this)->function() to call the
297 // right VIRTUAL function of the Drawer object.
298 return static_cast<D*>(t)->onMouseScroll(x, y, mKeyModifiers);
299 };
300
301 // call the lambda for all the drawers
302 callEventFunForDrawers<Drawers<RenderApp>...>(lambda);
303 }
304
305 /***** Member functions called by CanvasType *****/
306 // Documentation is in the RenderApp::CNV inner class
307
308 void cnvDraw()
309 {
310 // call the onDraw member function of each Drawer object.
311 // NOTE: use static_cast<Drawers*>(this)->function() to call the
312 // right VIRTUAL function of the Drawer object.
313 (static_cast<Drawers<RenderApp>*>(this)->onDraw(CanvasType::viewId()),
314 ...);
315 }
316
317 void cnvDrawContent()
318 {
319 // call the onDrawContent member function of each Drawer object.
320 // NOTE: use static_cast<Drawers*>(this)->function() to call the
321 // right VIRTUAL function of the Drawer object.
322 (static_cast<Drawers<RenderApp>*>(this)->onDrawContent(
323 CanvasType::viewId()),
324 ...);
325 }
326
327 void cnvPostDraw()
328 {
329 // call the onPostDraw member function of each Drawer object.
330 // NOTE: use static_cast<Drawers*>(this)->function() to call the
331 // right VIRTUAL function of the Drawer object.
332 (..., static_cast<Drawers<RenderApp>*>(this)->onPostDraw());
333 }
334
335 /***** Member functions called by Drawer objects *****/
336 // Documentation is in the RenderApp::DRW inner class
337
338 void* dWindowPtr() { return WindowManagerType::windowPtr(); }
339
340 vcl::Point2<uint> dCanvasSize() const { return CanvasType::size(); }
341
342 void dSetCanvasDefaultClearColor(const Color& color)
343 {
344 CanvasType::setDefaultClearColor(color);
345 }
346
347 auto dCanvasFrameBuffer() const { return CanvasType::frameBuffer(); }
348
349 [[nodiscard]] bool dReadDepth(
350 const Point2i& point,
351 ReadBufferTypes::CallbackReadBuffer callback = nullptr)
352 {
353 return CanvasType::onReadDepth(point, callback);
354 }
355
356 void dScreenshot(const std::string& filename, uint width, uint height)
357 {
358 CanvasType::onScreenshot(filename, width, height);
359 }
360};
361
362/*** Inner classes: Attorneys ***/
363// (https://tinyurl.com/kp8m28je)
364
378template<
379 template<typename>
380 typename WindowManagerT,
381 template<typename>
382 typename CanvasT,
383 template<typename>
384 typename... Drawers>
385class RenderApp<WindowManagerT, CanvasT, Drawers...>::WM
386{
388
389 friend WindowManagerType;
390
397 static void init(RenderApp* r) { r->wmInit(); }
398
408 static void resize(RenderApp* r, uint width, uint height)
409 {
410 r->wmResize(width, height);
411 }
412
417 static void paint(RenderApp* r) { r->wmPaint(); }
418
424 {
425 r->wmSetModifiers(modifiers);
426 }
427
438 static void keyPress(RenderApp* r, Key::Enum key) { r->wmKeyPress(key); }
439
450 static void keyRelease(RenderApp* r, Key::Enum key)
451 {
452 r->wmKeyRelease(key);
453 }
454
466 static void mouseMove(RenderApp* r, double x, double y)
467 {
468 r->wmMouseMove(x, y);
469 }
470
484 static void mousePress(
485 RenderApp* r,
486 MouseButton::Enum button,
487 double x,
488 double y)
489 {
490 r->wmMousePress(button, x, y);
491 }
492
506 static void mouseRelease(
507 RenderApp* r,
508 MouseButton::Enum button,
509 double x,
510 double y)
511 {
512 r->wmMouseRelease(button, x, y);
513 }
514
528 static void mouseDoubleClick(
529 RenderApp* r,
530 MouseButton::Enum button,
531 double x,
532 double y)
533 {
534 r->wmMouseDoubleClick(button, x, y);
535 }
536
549 static void mouseScroll(RenderApp* r, double x, double y)
550 {
551 r->wmMouseScroll(x, y);
552 }
553};
554
567template<
568 template<typename>
569 typename WindowManagerT,
570 template<typename>
571 typename CanvasT,
572 template<typename>
573 typename... Drawers>
574class RenderApp<WindowManagerT, CanvasT, Drawers...>::CNV
575{
577
578 friend CanvasType;
579
584 static void draw(RenderApp* r) { r->cnvDraw(); }
585
593 static void drawContent(RenderApp* r) { r->cnvDrawContent(); }
594
600 static void postDraw(RenderApp* r) { r->cnvPostDraw(); }
601};
602
615template<
616 template<typename>
617 typename WindowManagerT,
618 template<typename>
619 typename CanvasT,
620 template<typename>
621 typename... Drawers>
622class RenderApp<WindowManagerT, CanvasT, Drawers...>::DRW
623{
624 // TODO: right now all the function in this inner class are public,
625 // because variadic friends are still not allowed in C++.
626 // It will allowed in C++26: https://stackoverflow.com/a/78246001/5851101
627 // As soon as this feature will be available on all the major compilers,
628 // the functions will be made private.
629 // friend Drawers<RenderApp<WindowManagerT, CanvasT, Drawers...>>...;
630
631public: // TODO - remove this when C++26 is supported
646 static void* windowPtr(RenderApp* r) { return r->dWindowPtr(); }
647
657 {
658 return r->dCanvasSize();
659 }
660
669 static void setCanvasDefaultClearColor(RenderApp* r, const Color& color)
670 {
671 r->dSetCanvasDefaultClearColor(color);
672 }
673
684 static auto canvasFrameBuffer(const RenderApp* r)
685 {
686 return r->dCanvasFrameBuffer();
687 }
688
701 [[nodiscard]] static bool readDepth(
702 RenderApp* r,
703 const Point2i& point,
704 ReadBufferTypes::CallbackReadBuffer callback = nullptr)
705 {
706 return r->dReadDepth(point, callback);
707 }
708
720 static void screenshot(
721 RenderApp* r,
722 const std::string& filename,
723 uint width = 0,
724 uint height = 0)
725 {
726 r->dScreenshot(filename, width, height);
727 }
728};
729
730} // namespace vcl
731
732#endif // VCL_RENDER_RENDER_APP_H
The Color class represents a 32 bit color.
Definition color.h:48
The Point class represents an N-dimensional point containing N scalar values.
Definition point.h:58
The RenderApp::CNV inner class is an Attorney that allow access to some private member functions of t...
Definition render_app.h:575
static void postDraw(RenderApp *r)
The CanvasType has finished drawing and has submitted the new frame, and asks the RenderApp to call t...
Definition render_app.h:600
static void drawContent(RenderApp *r)
The CanvasType wants to draw only the content of the objects, without any decorator (e....
Definition render_app.h:593
static void draw(RenderApp *r)
The CanvasType is ready to draw, and asks the RenderApp to call the onDraw(uint()) function for every...
Definition render_app.h:584
The RenderApp::DRW inner class is an Attorney that allow access to some private member functions of t...
Definition render_app.h:623
static void * windowPtr(RenderApp *r)
A Drawer object can request the window pointer of the window manager (the exact meaning of the window...
Definition render_app.h:646
static Point2< uint > canvasSize(const RenderApp *r)
A Drawer object can request the size of the canvas. This function is called by the Drawer object to r...
Definition render_app.h:656
static bool readDepth(RenderApp *r, const Point2i &point, ReadBufferTypes::CallbackReadBuffer callback=nullptr)
A Drawer object can request the depth value at a specific point on the canvas. This function is calle...
Definition render_app.h:701
static auto canvasFrameBuffer(const RenderApp *r)
A Drawer object can request the frame buffer of the canvas.
Definition render_app.h:684
static void screenshot(RenderApp *r, const std::string &filename, uint width=0, uint height=0)
A Drawer object can request a screenshot of the canvas. This function is called by the Drawer object ...
Definition render_app.h:720
static void setCanvasDefaultClearColor(RenderApp *r, const Color &color)
A Drawer object can set the default clear color of the canvas.
Definition render_app.h:669
The RenderApp::WM inner class is an Attorney that allow access to some private member functions of th...
Definition render_app.h:386
static void keyRelease(RenderApp *r, Key::Enum key)
The WindowManagerType calls this member function when a key is released.
Definition render_app.h:450
static void keyPress(RenderApp *r, Key::Enum key)
The WindowManagerType calls this member function when a key is pressed.
Definition render_app.h:438
static void paint(RenderApp *r)
The WindowManagerType calls this member function when the window triggers a paint event.
Definition render_app.h:417
static void init(RenderApp *r)
The WindowManagerType calls this member function when the window render backend is initialized....
Definition render_app.h:397
static void setModifiers(RenderApp *r, const KeyModifiers &modifiers)
The WindowManagerType calls this member function when the current modifiers are updated.
Definition render_app.h:423
static void mousePress(RenderApp *r, MouseButton::Enum button, double x, double y)
The WindowManagerType calls this member function when a mouse button is pressed.
Definition render_app.h:484
static void mouseScroll(RenderApp *r, double x, double y)
The WindowManagerType calls this member function when the mouse wheel is scrolled.
Definition render_app.h:549
static void resize(RenderApp *r, uint width, uint height)
The WindowManagerType calls this member function when the window is resized, telling the new width an...
Definition render_app.h:408
static void mouseRelease(RenderApp *r, MouseButton::Enum button, double x, double y)
The WindowManagerType calls this member function when a mouse button is released.
Definition render_app.h:506
static void mouseDoubleClick(RenderApp *r, MouseButton::Enum button, double x, double y)
The WindowManagerType calls this member function when a mouse button is double clicked.
Definition render_app.h:528
static void mouseMove(RenderApp *r, double x, double y)
The WindowManagerType calls this member function when the mouse cursor is moved.
Definition render_app.h:466
The RenderApp class is a template class that combines a canvas, a window manager, and a set of drawer...
Definition render_app.h:67
void callEventFunForDrawers(auto lambda)
Calls a lambda function - that represents an event - for every Drawer object listed in the template p...
Definition render_app.h:156
A class representing a line segment in n-dimensional space. The class is parameterized by a PointConc...
Definition segment.h:43
Definition blocker_event_drawer.h:33
The CanvasConcept concept is used to check if a class satisfies the requirements of the Canvas concep...
Definition canvas.h:102
Definition drawer.h:31
Definition event_drawer.h:33
The WindowManagerConcept concept is used to check if a class satisfies the requirements of the Window...
Definition window_manager.h:95
Point2< int > Point2i
A convenience alias for a 2-dimensional Point with integer components.
Definition point.h:731