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