Visual Computing Library  devel
Loading...
Searching...
No Matches
render_app.h
1/*****************************************************************************
2 * VCLib *
3 * Visual Computing Library *
4 * *
5 * Copyright(C) 2021-2026 *
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 uint dCanvasViewId() const { return CanvasType::viewId(); }
350
351 vcl::Point2<uint> dCanvasSize() const { return CanvasType::size(); }
352
353 void dSetCanvasDefaultClearColor(const Color& color)
354 {
355 CanvasType::setDefaultClearColor(color);
356 }
357
358 auto dCanvasFrameBuffer() const { return CanvasType::frameBuffer(); }
359
360 [[nodiscard]] bool dReadDepth(
361 const Point2i& point,
362 ReadBufferTypes::CallbackReadBuffer callback = nullptr)
363 {
364 return CanvasType::onReadDepth(point, callback);
365 }
366
367 [[nodiscard]] bool dReadId(
368 const Point2i& point,
369 ReadBufferTypes::CallbackReadBuffer callback = nullptr)
370 {
371 return CanvasType::onReadId(point, callback);
372 }
373
374 void dScreenshot(const std::string& filename, uint multiplier = 1)
375 {
376 CanvasType::onScreenshot(filename, multiplier);
377 }
378};
379
380/*** Inner classes: Attorneys ***/
381// (https://tinyurl.com/kp8m28je)
382
396template<
397 template<typename>
398 typename WindowManagerT,
399 template<typename>
400 typename CanvasT,
401 template<typename>
402 typename... Drawers>
403class RenderApp<WindowManagerT, CanvasT, Drawers...>::WM
404{
406
407 friend WindowManagerType;
408
415 static void init(RenderApp* r) { r->wmInit(); }
416
426 static void resize(RenderApp* r, uint width, uint height)
427 {
428 r->wmResize(width, height);
429 }
430
435 static void paint(RenderApp* r) { r->wmPaint(); }
436
442 {
443 r->wmSetModifiers(modifiers);
444 }
445
456 static void keyPress(RenderApp* r, Key::Enum key) { r->wmKeyPress(key); }
457
468 static void keyRelease(RenderApp* r, Key::Enum key)
469 {
470 r->wmKeyRelease(key);
471 }
472
484 static void mouseMove(RenderApp* r, double x, double y)
485 {
486 r->wmMouseMove(x, y);
487 }
488
502 static void mousePress(
503 RenderApp* r,
504 MouseButton::Enum button,
505 double x,
506 double y)
507 {
508 r->wmMousePress(button, x, y);
509 }
510
524 static void mouseRelease(
525 RenderApp* r,
526 MouseButton::Enum button,
527 double x,
528 double y)
529 {
530 r->wmMouseRelease(button, x, y);
531 }
532
546 static void mouseDoubleClick(
547 RenderApp* r,
548 MouseButton::Enum button,
549 double x,
550 double y)
551 {
552 r->wmMouseDoubleClick(button, x, y);
553 }
554
567 static void mouseScroll(RenderApp* r, double x, double y)
568 {
569 r->wmMouseScroll(x, y);
570 }
571};
572
585template<
586 template<typename>
587 typename WindowManagerT,
588 template<typename>
589 typename CanvasT,
590 template<typename>
591 typename... Drawers>
592class RenderApp<WindowManagerT, CanvasT, Drawers...>::CNV
593{
595
596 friend CanvasType;
597
602 static void draw(RenderApp* r) { r->cnvDraw(); }
603
611 static void drawContent(RenderApp* r) { r->cnvDrawContent(); }
612
620 static void drawId(RenderApp* r) { r->cnvDrawId(); }
621
627 static void postDraw(RenderApp* r) { r->cnvPostDraw(); }
628};
629
642template<
643 template<typename>
644 typename WindowManagerT,
645 template<typename>
646 typename CanvasT,
647 template<typename>
648 typename... Drawers>
649class RenderApp<WindowManagerT, CanvasT, Drawers...>::DRW
650{
651 // TODO: right now all the function in this inner class are public,
652 // because variadic friends are still not allowed in C++.
653 // It will allowed in C++26: https://stackoverflow.com/a/78246001/5851101
654 // As soon as this feature will be available on all the major compilers,
655 // the functions will be made private.
656 // friend Drawers<RenderApp<WindowManagerT, CanvasT, Drawers...>>...;
657
658public: // TODO - remove this when C++26 is supported
673 static void* windowPtr(RenderApp* r) { return r->dWindowPtr(); }
674
682 static uint canvasViewId(const RenderApp* r) { return r->dCanvasViewId(); }
683
693 {
694 return r->dCanvasSize();
695 }
696
705 static void setCanvasDefaultClearColor(RenderApp* r, const Color& color)
706 {
707 r->dSetCanvasDefaultClearColor(color);
708 }
709
720 static auto canvasFrameBuffer(const RenderApp* r)
721 {
722 return r->dCanvasFrameBuffer();
723 }
724
740 [[nodiscard]] static bool readDepth(
741 RenderApp* r,
742 const Point2i& point,
743 ReadBufferTypes::CallbackReadBuffer callback = nullptr)
744 {
745 return r->dReadDepth(point, callback);
746 }
747
763 [[nodiscard]] static bool readId(
764 RenderApp* r,
765 const Point2i& point,
766 ReadBufferTypes::CallbackReadBuffer callback = nullptr)
767 {
768 return r->dReadId(point, callback);
769 }
770
780 static void screenshot(
781 RenderApp* r,
782 const std::string& filename,
783 uint multiplier = 1)
784 {
785 r->dScreenshot(filename, multiplier);
786 }
787};
788
789} // namespace vcl
790
791#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:55
The RenderApp::CNV inner class is an Attorney that allow access to some private member functions of t...
Definition render_app.h:593
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:627
static void drawContent(RenderApp *r)
The CanvasType wants to draw only the content of the objects, without any decorator (e....
Definition render_app.h:611
static void drawId(RenderApp *r)
The CanvasType wants to draw only the IDs of the objects, without any decorator (e....
Definition render_app.h:620
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:602
The RenderApp::DRW inner class is an Attorney that allow access to some private member functions of t...
Definition render_app.h:650
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:673
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:692
static uint canvasViewId(const RenderApp *r)
A Drawer object can request the viewId of the canvas. This function is called by the Drawer object to...
Definition render_app.h:682
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:740
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:763
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:780
static auto canvasFrameBuffer(const RenderApp *r)
A Drawer object can request the frame buffer of the canvas.
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:705
The RenderApp::WM inner class is an Attorney that allow access to some private member functions of th...
Definition render_app.h:404
static void keyRelease(RenderApp *r, Key::Enum key)
The WindowManagerType calls this member function when a key is released.
Definition render_app.h:468
static void keyPress(RenderApp *r, Key::Enum key)
The WindowManagerType calls this member function when a key is pressed.
Definition render_app.h:456
static void paint(RenderApp *r)
The WindowManagerType calls this member function when the window triggers a paint event.
Definition render_app.h:435
static void init(RenderApp *r)
The WindowManagerType calls this member function when the window render backend is initialized....
Definition render_app.h:415
static void setModifiers(RenderApp *r, const KeyModifiers &modifiers)
The WindowManagerType calls this member function when the current modifiers are updated.
Definition render_app.h:441
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:502
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:567
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:426
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:524
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:546
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:484
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:41
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:707