API Documentation
Loading...
Searching...
No Matches
ScenePaintEngine.h
Go to the documentation of this file.
1#pragma once
2#include "DLLInfo.h"
3#if NDEVR_VIEWPORT
4#include <NDEVR/QTTools.h>
5#include <NDEVR/Material.h>
6#include <NDEVR/Model.h>
7#include <NDEVR/Geometry.h>
8#include <NDEVR/ShapeConstructors.h>
9#include <NDEVR/TextConstructor.h>
10#include <QTextItem>
11#include <QScreen>
12#include <QSize>
13#include <QPaintEngine>
14namespace NDEVR
15{
16 class ScenePaintEngine;
17 class WidgetIterator;
18 class DesignObjectLookup;
19 /**--------------------------------------------------------------------------------------------------
20 \brief A QPaintDevice that 'paints' the widgets by turning them into 3D Model objects inside a model
21 heirarchy.
22 **/
23 class NDEVR_API ScenePaintDevice : public QPaintDevice
24 {
25 public:
26 ScenePaintDevice(Model& model);
27 virtual QPaintEngine* paintEngine() const override;
28 void setRoot(Model& model);
29 virtual int metric(PaintDeviceMetric metric) const override
30 {
31 switch (metric)
32 {
33 case PdmWidth: return 1024;
34 case PdmHeight: return 1024;
35 case PdmWidthMM: return 1024;
36 case PdmHeightMM: return 1024;
37 case PdmNumColors: return INT_MAX;
38 case PdmDepth: return 1;
39 case PdmDpiX: return m_dpi[X];
40 case PdmDpiY: return m_dpi[Y];
41 case PdmPhysicalDpiX: return m_physical_dpi[X];
42 case PdmPhysicalDpiY: return m_physical_dpi[Y];
43 case PdmDevicePixelRatio: return m_device_pixel_ratio;
44 case PdmDevicePixelRatioScaled: return m_device_pixel_ratio_scaled;
45 }
46 return 0;
47 }
48 void setPhysicalDPI(int dpi_x, int dpi_y) { m_physical_dpi = { dpi_x , dpi_y }; }
49 void setDevicePixelRatio(int ratio) { m_device_pixel_ratio = ratio; }
50 void setDevicePixelRatioScaled(int ratio) { m_device_pixel_ratio_scaled = ratio; }
51 void setDPI(int dpi) { m_dpi = dpi; }
52 void setDPIX(int dpi) { m_dpi[X] = dpi; }
53 void setDPIY(int dpi) { m_dpi[Y] = dpi; }
54 ScenePaintEngine* scenePaintEngine() { return m_paint_engine; }
55
56 void drawWidget(QWidget* widget, QPainter& painter, QPoint offset, uint04 depth);
57 protected:
58 Vector<2, int> m_dpi = {1024, 1024};
59 Vector<2, int> m_physical_dpi = { 1024, 1024 };
60 int m_device_pixel_ratio = 1;
61 int m_device_pixel_ratio_scaled = 1;
62 QWidget* m_widget = nullptr;
63 ScenePaintEngine* m_paint_engine;
64 Time m_last_update_update;
65 };
66 /**--------------------------------------------------------------------------------------------------
67 \brief A QPaintEngine that 'paints' the widgets by turning them into 3D Model objects.
68 **/
69 class NDEVR_API ScenePaintEngine : public QPaintEngine
70 {
71 public:
72 ScenePaintEngine();
73 explicit ScenePaintEngine(Model& scene);
74 virtual ~ScenePaintEngine()
75 {}
76 static void AutoWidgetsToPDF(File file, WidgetIterator reports, QSize size = QSize(), bool send_file = false);
77 static Buffer<QSize> WidgetsToModel(const WidgetIterator& reports, Model& model, QSize size = QSize(), bool is_flat = false);
78 static void PrepareWidgetsToModel(const Buffer<QWidget*>& widgets, QSize size = QSize());
79 static Buffer<UUID> PrepareWidgetsViews(DesignObjectLookup& lookup, const WidgetIterator& reports, QSize size = QSize());
80 static Buffer<UUID> PrepareWidgetsViews(DesignObjectLookup& lookup, const Buffer<QWidget*>& widgets, QSize size = QSize());
81 static void WidgetsToPDF(const File& file, const Buffer<QWidget*>& widgets, QSize size = QSize());
82 static void ModelsToPDF(const File& file, DesignObjectLookup& lookup, const Buffer<UUID>& camera_ids, fltp08 dpi);
83 void updateClipping(Model& model);
84 void setCurrentName(const String& current_name);
85
86
87 void setRoot(Model& new_root);
88 virtual bool begin(QPaintDevice*) override
89 {
90 return true;
91 }
92 virtual bool end() override
93 {
94 return true;
95 }
96 void pushModel();
97 void popModel();
98 void resetExtraDepth();
99 virtual void updateState(const QPaintEngineState& state) override;
100
101 template<class t_type>
102 void drawRectsT(const t_type* rect, int rect_count)
103 {
104 Model model = m_models.last().createChild();
105 setupShapeModel(model);
106 Geometry geo = model.createChildGeometry();
107 if (!m_is_flat)
108 geo.setProperty(DesignObject::e_name, "RectsT");
109 geo.setTransform(getTransform(false));
110 geo.setGeometryType(GeometryType::e_convex_polygons);
111 geo.setupVertexTable(0, Geometry::VertexMode::e_cartesian_3F);
112 for (uint04 i = 0; i < cast<uint04>(rect_count); i++)
113 {
114 ShapeConstructors::Rectangle(geo, Matrix<fltp08>::OffsetMatrix(
115 Vertex<3, fltp08>(rect->center().x(), rect->center().y(), 0.0))
116 .scale(Vector<3, fltp08>(rect->width() / 2.0, rect->height() / 2.0, 1.0)));
117 }
118 geo.autoCalculateIndices(PrimitiveProperty::Solid);
119 geo.updateModifiedTime();
120 finishShape(true);
121 }
122 virtual void drawRects(const QRect* rects, int rectCount) override
123 {
124 drawRectsT(rects, rectCount);
125 }
126 virtual void drawRects(const QRectF* rects, int rectCount) override
127 {
128 drawRectsT(rects, rectCount);
129 }
130 template<class t_type>
131 void drawLinesT(const t_type* lines, int line_count)
132 {
133 Model model = m_models.last().createChild();
134 setupShapeModel(model);
135 Geometry geo = model.createChildGeometry();
136 if (!m_is_flat)
137 geo.setProperty(DesignObject::e_name, "LinesT");
138 geo.setTransform(getTransform(false));
139 geo.setGeometryType(GeometryType::e_linework);
140 geo.setPrimitiveMode(PrimitiveProperty::Solid, PrimitiveMode::e_lines);
141 geo.setPrimitiveMode(PrimitiveProperty::Outline, PrimitiveMode::e_lines);
142 geo.setupVertexTable(0, Geometry::VertexMode::e_cartesian_3F);
143 uint04 primitive_start = geo.addPrimitives(PrimitiveProperty::Outline, cast<uint04>(line_count));
144 uint04 vertex_start = geo.addVertices(cast<uint04>(line_count) * 2);
145 for (uint04 i = 0; i < cast<uint04>(line_count); i++)
146 {
147 geo.setVertex(VertexProperty::Position, vertex_start + 2 * i, Vertex<3, fltp08>(lines[i].x1(), lines[i].y1(), 0.0));
148 geo.setVertex(VertexProperty::Position, vertex_start + 2 * i + 1, Vertex<3, fltp08>(lines[i].x2(), lines[i].y2(), 0.0));
149 geo.setPrimitive(PrimitiveProperty::Outline, primitive_start + i, vertex_start + Vector<2, uint04>(2 * i, 2 * i + 1));
150 }
151 geo.autoCalculateIndices(PrimitiveProperty::Solid);
152 geo.updateModifiedTime();
153 finishShape(false);
154 }
155 virtual void drawLines(const QLine* lines, int line_count) override
156 {
157 drawLinesT<QLine>(lines, line_count);
158 }
159 virtual void drawLines(const QLineF* lines, int line_count) override
160 {
161 drawLinesT<QLineF>(lines, line_count);
162 }
163
164 template<class t_type>
165 void drawEllipseT(const t_type& r)
166 {
167 if (r.width() == 0 || r.height() == 0)
168 {
169 if (r.width() == 0 && r.height() == 0)
170 {
171 QPointF p(r.center().x(), r.center().y());
172 drawPoints(&p, 1);
173 }
174 else if (r.width() == 0)
175 {
176 QPointF p1(r.center().x(), r.center().y() - r.height() / 2.0);
177 QPointF p2(r.center().x(), r.center().y() + r.height() / 2.0);
178 QLineF l(p1, p2);
179 drawLines(&l, 1);
180 }
181 else if (r.height() == 0)
182 {
183 QPointF p1(r.center().x() - r.width() / 2.0, r.center().y());
184 QPointF p2(r.center().x() + r.width() / 2.0, r.center().y());
185 QLineF l(p1, p2);
186 drawLines(&l, 1);
187 }
188 return;
189 }
190 Model model = m_models.last().createChild();
191 setupShapeModel(model);
192
193 Geometry geo = model.createChildGeometry();
194 if (!m_is_flat)
195 geo.setProperty(DesignObject::e_name, "EllipseT");
196 geo.setTransform(getTransform(false));
197 geo.setGeometryType(GeometryType::e_convex_polygons);
198 geo.setupVertexTable(0, Geometry::VertexMode::e_cartesian_3F);
199 ShapeConstructors::Circle(geo, Matrix<fltp08>::OffsetMatrix(Vertex<3, fltp08>(r.center().x(), r.center().y(), 0.0))
200 .scale(Vector<3, fltp08>(r.width() / 2.0, r.height() / 2.0, 1.0)));
201 geo.autoCalculateIndices(PrimitiveProperty::Solid);
202 finishShape(true);
203 }
204 virtual void drawEllipse(const QRectF& r) override
205 {
206 drawEllipseT(r);
207 }
208 virtual void drawEllipse(const QRect& r) override
209 {
210 drawEllipseT(r);
211 }
212 static QPalette ScenePalette();
213 static QStyle* SceneStyle();
214 virtual void drawPath(const QPainterPath& path) override;
215 template<class t_type>
216 void drawPointsT(const t_type* points, int point_count)
217 {
218 Model model = m_models.last().createChild();
219 setupShapeModel(model, false);
220
221 Geometry geo = model.createChildGeometry();
222 geo.setTransform(getTransform(false));
223 geo.setGeometryType(GeometryType::e_points);
224 if (!m_is_flat)
225 geo.setProperty(DesignObject::e_name, "PointsT");
226 geo.setupVertexTable(0, Geometry::VertexMode::e_cartesian_3F);
227 uint04 vertex_start = geo.addVertices(cast<uint04>(point_count));
228 for (uint04 i = 0; i < cast<uint04>(point_count); i++)
229 {
230 geo.setVertex(VertexProperty::Position, vertex_start + i, Vertex<3, fltp08>(points[i].x(), points[i].y(), 0.0));
231 }
232 geo.autoCalculateIndices(PrimitiveProperty::Solid);
233 finishShape(false);
234 }
235 virtual void drawPoints(const QPointF* points, int point_count) override
236 {
237 drawPointsT(points, point_count);
238 }
239 virtual void drawPoints(const QPoint* points, int point_count) override
240 {
241 drawPointsT(points, point_count);
242 }
243 template<class t_type>
244 void drawPolygonT(const t_type * points, int point_count, PolygonDrawMode mode)
245 {
246 if (point_count <= 0)
247 return;
248 Model model = m_is_clipping ? m_models.last() : m_models.last().createChild();
249 if(!m_is_clipping)
250 setupShapeModel(model, mode != PolygonDrawMode::PolylineMode);
251
252 Geometry geo = model.createChildGeometry();
253 if(!m_is_flat)
254 geo.setProperty(DesignObject::e_name, "PolygonT");
255 geo.setTransform(getTransform(false));
256 if (mode == PolygonDrawMode::ConvexMode)
257 geo.setGeometryType(GeometryType::e_convex_polygons);
258 else if (mode == PolygonDrawMode::PolylineMode)
259 geo.setGeometryType(GeometryType::e_linework);
260 else
261 geo.setGeometryType(GeometryType::e_concave_polygons);
262
263 Polygon<fltp08> poly(point_count);
264 for (uint04 i = 0; i < cast<uint04>(point_count); i++)
265 {
266 poly.add(Vertex<2, fltp08>(points[i].x(), points[i].y()));
267 }
268 poly.simplify();
269 geo.setupVertexTable(poly.vertexCount(), Geometry::VertexMode::e_cartesian_3F);
270 geo.addPrimitives(PrimitiveProperty::Outline, poly.vertexCount() + 1);
271 for (uint04 i = 0; i < poly.vertexCount(); i++)
272 {
273 geo.setVertex(VertexProperty::Position, i, poly.vertex(i).as<3, fltp08>(0.0));
274 geo.setPrimitive(PrimitiveProperty::Outline, i, i);
275 }
276 geo.setPrimitive(PrimitiveProperty::Outline, poly.vertexCount(), 0);
277 if(!m_is_clipping)
278 geo.autoCalculateIndices(PrimitiveProperty::Solid);
279 geo.setGeometryProperty(Geometry::e_is_clipping_geo, m_is_clipping);
280 finishShape(true);
281 }
282 virtual void drawPolygon(const QPointF* points, int point_count, PolygonDrawMode mode) override
283 {
284 drawPolygonT(points, point_count, mode);
285 }
286 virtual void drawPolygon(const QPoint* points, int point_count, PolygonDrawMode mode) override
287 {
288 drawPolygonT(points, point_count, mode);
289 }
290
291 virtual void drawPixmap(const QRectF& r, const QPixmap& pm, const QRectF& sr) override
292 {
293 QImage image = pm.toImage();
294 drawImage(r, image, sr);
295
296 }
297 virtual void drawTextItem(const QPointF& p, const QTextItem& text_item) override;
298 virtual void drawTiledPixmap(const QRectF& r, const QPixmap& pixmap, const QPointF& s) override
299 {
300 drawImage(r, pixmap.toImage(), QRectF(s, QSizeF(1.0, 1.0)));
301 }
302 virtual void drawImage(const QRectF& r, const QImage& image, const QRectF& sr, Qt::ImageConversionFlags flags = Qt::AutoColor) override;
303 virtual Type type() const override
304 {
305 return Type::User;
306 }
307 static PaintEngineFeatures SceneRenderFeatures();
308 void finishShape(bool is_solid);
309 Matrix<fltp08> getTransform(bool is_text) const;
310 void setupShapeModel(Model& model, bool has_solid = true, bool is_text = false);
311 Material currentMaterial(PrimitiveProperty property, bool is_text);
312 void setIsFlat(bool is_flat) { m_is_flat = is_flat; };
313 bool isFlat() const { return m_is_flat; }
314 Material createCurrentMaterial(PrimitiveProperty property, bool is_text);
315 [[nodiscard]] bool hasOutline() const;
316 [[nodiscard]] bool hasSolid() const;
317 fltp08 currentThickness() const
318 {
319 return state->pen().widthF();
320 }
321 RGBColor currentFillColor() const
322 {
323 return QTTools::convert(state->brush().color());
324 }
325 RGBColor currentOutlineColor() const
326 {
327 return QTTools::convert(state->pen().color());
328 }
329 const Model& root() const
330 {
331 return m_root;
332 }
333 protected:
334 String m_current_image;
335 Dictionary<UUID, Material> m_materials;
336#if NDEVR_TEXT_MODEL
337 Dictionary<String, DynamicPointer<TextConstructor>> m_text_constructors;
338#endif
339 Model m_root;
340 Buffer<Model> m_models;
341 uint04 m_extra_depth = 0;
342 uint04 m_geometry_depth = 0;
343 bool m_is_clipping;
344 bool m_is_flat = false;
345 };
346}
347#endif
#define NDEVR_API
Definition DLLInfo.h:50
Definition ACIColor.h:37
uint32_t uint04
-Defines an alias representing a 4 byte, unsigned integer -Can represent exact integer values 0 throu...
Definition BaseValues.hpp:96
@ Y
Definition BaseValues.hpp:169
@ X
Definition BaseValues.hpp:167
double fltp08
Defines an alias representing an 8 byte floating-point number.
Definition BaseValues.hpp:149