Visual Computing Library  devel
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 cnvDrawId()
328 {
329 // call the onDrawId 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)->onDrawId(CanvasType::viewId()),
333 ...);
334 }
335
336 void cnvPostDraw()
337 {
338 // call the onPostDraw member function of each Drawer object.
339 // NOTE: use static_cast<Drawers*>(this)->function() to call the
340 // right VIRTUAL function of the Drawer object.
341 (..., static_cast<Drawers<RenderApp>*>(this)->onPostDraw());
342 }
343
344 /***** Member functions called by Drawer objects *****/
345 // Documentation is in the RenderApp::DRW inner class
346
347 void* dWindowPtr() { return WindowManagerType::windowPtr(); }
348
349 vcl::Point2<uint> dCanvasSize() const { return CanvasType::size(); }
350
351 void dSetCanvasDefaultClearColor(const Color& color)
352 {
353 CanvasType::setDefaultClearColor(color);
354 }
355
356 auto dCanvasFrameBuffer() const { return CanvasType::frameBuffer(); }
357
358 [[nodiscard]] bool dReadDepth(
359 const Point2i& point,
360 ReadBufferTypes::CallbackReadBuffer callback = nullptr)
361 {
362 return CanvasType::onReadDepth(point, callback);
363 }
364
365 [[nodiscard]] bool dReadId(
366 const Point2i& point,
367 ReadBufferTypes::CallbackReadBuffer callback = nullptr)
368 {
369 return CanvasType::onReadId(point, callback);
370 }
371
372 void dScreenshot(const std::string& filename, uint multiplier = 1)
373 {
374 CanvasType::onScreenshot(filename, multiplier);
375 }
376};
377
378/*** Inner classes: Attorneys ***/
379// (https://tinyurl.com/kp8m28je)
380
394template<
395 template<typename>
396 typename WindowManagerT,
397 template<typename>
398 typename CanvasT,
399 template<typename>
400 typename... Drawers>
401class RenderApp<WindowManagerT, CanvasT, Drawers...>::WM
402{
404
405 friend WindowManagerType;
406
413 static void init(RenderApp* r) { r->wmInit(); }
414
424 static void resize(RenderApp* r, uint width, uint height)
425 {
426 r->wmResize(width, height);
427 }
428
433 static void paint(RenderApp* r) { r->wmPaint(); }
434
440 {
441 r->wmSetModifiers(modifiers);
442 }
443
454 static void keyPress(RenderApp* r, Key::Enum key) { r->wmKeyPress(key); }
455
466 static void keyRelease(RenderApp* r, Key::Enum key)
467 {
468 r->wmKeyRelease(key);
469 }
470
482 static void mouseMove(RenderApp* r, double x, double y)
483 {
484 r->wmMouseMove(x, y);
485 }
486
500 static void mousePress(
501 RenderApp* r,
502 MouseButton::Enum button,
503 double x,
504 double y)
505 {
506 r->wmMousePress(button, x, y);
507 }
508
522 static void mouseRelease(
523 RenderApp* r,
524 MouseButton::Enum button,
525 double x,
526 double y)
527 {
528 r->wmMouseRelease(button, x, y);
529 }
530
544 static void mouseDoubleClick(
545 RenderApp* r,
546 MouseButton::Enum button,
547 double x,
548 double y)
549 {
550 r->wmMouseDoubleClick(button, x, y);
551 }
552
565 static void mouseScroll(RenderApp* r, double x, double y)
566 {
567 r->wmMouseScroll(x, y);
568 }
569};
570
583template<
584 template<typename>
585 typename WindowManagerT,
586 template<typename>
587 typename CanvasT,
588 template<typename>
589 typename... Drawers>
590class RenderApp<WindowManagerT, CanvasT, Drawers...>::CNV
591{
593
594 friend CanvasType;
595
600 static void draw(RenderApp* r) { r->cnvDraw(); }
601
609 static void drawContent(RenderApp* r) { r->cnvDrawContent(); }
610
618 static void drawId(RenderApp* r) { r->cnvDrawId(); }
619
625 static void postDraw(RenderApp* r) { r->cnvPostDraw(); }
626};
627
640template<
641 template<typename>
642 typename WindowManagerT,
643 template<typename>
644 typename CanvasT,
645 template<typename>
646 typename... Drawers>
647class RenderApp<WindowManagerT, CanvasT, Drawers...>::DRW
648{
649 // TODO: right now all the function in this inner class are public,
650 // because variadic friends are still not allowed in C++.
651 // It will allowed in C++26: https://stackoverflow.com/a/78246001/5851101
652 // As soon as this feature will be available on all the major compilers,
653 // the functions will be made private.
654 // friend Drawers<RenderApp<WindowManagerT, CanvasT, Drawers...>>...;
655
656public: // TODO - remove this when C++26 is supported
671 static void* windowPtr(RenderApp* r) { return r->dWindowPtr(); }
672
682 {
683 return r->dCanvasSize();
684 }
685
694 static void setCanvasDefaultClearColor(RenderApp* r, const Color& color)
695 {
696 r->dSetCanvasDefaultClearColor(color);
697 }
698
709 static auto canvasFrameBuffer(const RenderApp* r)
710 {
711 return r->dCanvasFrameBuffer();
712 }
713
729 [[nodiscard]] static bool readDepth(
730 RenderApp* r,
731 const Point2i& point,
732 ReadBufferTypes::CallbackReadBuffer callback = nullptr)
733 {
734 return r->dReadDepth(point, callback);
735 }
736
752 [[nodiscard]] static bool readId(
753 RenderApp* r,
754 const Point2i& point,
755 ReadBufferTypes::CallbackReadBuffer callback = nullptr)
756 {
757 return r->dReadId(point, callback);
758 }
759
769 static void screenshot(
770 RenderApp* r,
771 const std::string& filename,
772 uint multiplier = 1)
773 {
774 r->dScreenshot(filename, multiplier);
775 }
776};
777
778} // namespace vcl
779
780#endif // VCL_RENDER_RENDER_APP_H
A class representing a box in N-dimensional space.
Definition box.h:46
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:55
The RenderApp::CNV inner class is an Attorney that allow access to some private member functions of t...
Definition render_app.h:591
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:625
static void drawContent(RenderApp *r)
The CanvasType wants to draw only the content of the objects, without any decorator (e....
Definition render_app.h:609
static void drawId(RenderApp *r)
The CanvasType wants to draw only the IDs of the objects, without any decorator (e....
Definition render_app.h:618
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:600
The RenderApp::DRW inner class is an Attorney that allow access to some private member functions of t...
Definition render_app.h:648
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:671
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:681
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:729
static bool readId(RenderApp *r, const Point2i &point, ReadBufferTypes::CallbackReadBuffer callback=nullptr)
A Drawer object can request the ID at a specific point on the canvas. This function is called by the ...
Definition render_app.h:752
static void screenshot(RenderApp *r, const std::string &filename, uint multiplier=1)
A Drawer object can request a screenshot of the canvas. This function is called by the Drawer object ...
Definition render_app.h:769
static auto canvasFrameBuffer(const RenderApp *r)
A Drawer object can request the frame buffer of the canvas.
Definition render_app.h:709
static void setCanvasDefaultClearColor(RenderApp *r, const Color &color)
A Drawer object can set the default clear color of the canvas.
Definition render_app.h:694
The RenderApp::WM inner class is an Attorney that allow access to some private member functions of th...
Definition render_app.h:402
static void keyRelease(RenderApp *r, Key::Enum key)
The WindowManagerType calls this member function when a key is released.
Definition render_app.h:466
static void keyPress(RenderApp *r, Key::Enum key)
The WindowManagerType calls this member function when a key is pressed.
Definition render_app.h:454
static void paint(RenderApp *r)
The WindowManagerType calls this member function when the window triggers a paint event.
Definition render_app.h:433
static void init(RenderApp *r)
The WindowManagerType calls this member function when the window render backend is initialized....
Definition render_app.h:413
static void setModifiers(RenderApp *r, const KeyModifiers &modifiers)
The WindowManagerType calls this member function when the current modifiers are updated.
Definition render_app.h:439
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:500
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:565
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:424
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:522
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:544
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:482
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
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:99
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:706