NDEVR
API Documentation
ScenePaintEngine.h
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;
23 class NDEVR_API ScenePaintDevice : public QPaintDevice
24 {
25 public:
31 virtual QPaintEngine* paintEngine() const override;
36 void setRoot(Model& model);
37 virtual int metric(PaintDeviceMetric metric) const override;
43 void setPhysicalDPI(int dpi_x, int dpi_y) { m_physical_dpi = { dpi_x , dpi_y }; }
48 void setDevicePixelRatio(int ratio) { m_device_pixel_ratio = ratio; }
58 void setDPI(int dpi) { m_dpi = dpi; }
63 void setDPIX(int dpi) { m_dpi[X] = dpi; }
68 void setDPIY(int dpi) { m_dpi[Y] = dpi; }
74
82 void drawWidget(QWidget* widget, QPainter& painter, QPoint offset, uint04 depth);
83 protected:
84 Vector<2, int> m_dpi = {1024, 1024};
85 Vector<2, int> m_physical_dpi = { 1024, 1024 };
88 QWidget* m_widget = nullptr;
91 };
92
95 class NDEVR_API ScenePaintEngine : public QPaintEngine
96 {
97 public:
98 ScenePaintEngine();
103 explicit ScenePaintEngine(Model& scene);
104 virtual ~ScenePaintEngine()
105 {}
113 static void AutoWidgetsToPDF(File file, WidgetIterator reports, QSize size = QSize(), bool send_file = false);
122 static Buffer<QSize> WidgetsToModel(const WidgetIterator& reports, Model& model, QSize size = QSize(), bool is_flat = false);
128 static void PrepareWidgetsToModel(const Buffer<QWidget*>& widgets, QSize size = QSize());
136 static Buffer<UUID> PrepareWidgetsViews(DesignObjectLookup& lookup, const WidgetIterator& reports, QSize size = QSize());
144 static Buffer<UUID> PrepareWidgetsViews(DesignObjectLookup& lookup, const Buffer<QWidget*>& widgets, QSize size = QSize());
151 static void WidgetsToPDF(const File& file, const Buffer<QWidget*>& widgets, QSize size = QSize());
160 static void ModelsToPDF(const File& file, DesignObjectLookup& lookup, const Buffer<UUID>& camera_ids, fltp08 dpi, fltp04 margins = 20.0f);
165 void updateClipping(Model& model);
170 void setCurrentName(const String& current_name);
171
172
177 void setRoot(Model& new_root);
178 virtual bool begin(QPaintDevice*) override
179 {
180 return true;
181 }
182 virtual bool end() override
183 {
184 return true;
185 }
187 void pushModel();
189 void popModel();
192 virtual void updateState(const QPaintEngineState& state) override;
193
194 template<class t_type>
195 void drawRectsT(const t_type* rect, int rect_count)
196 {
197 Model model = m_models.last().createChild();
198 setupShapeModel(model);
199 Geometry geo = model.createChildGeometry();
200 if (!m_is_flat)
201 geo.set<NDPO::name>("RectsT");
202 geo.set<NDPO::transform>(getTransform(false));
205 for (uint04 i = 0; i < cast<uint04>(rect_count); i++)
206 {
207 ShapeConstructors::Rectangle(geo, Matrix<fltp08>::OffsetMatrix(
208 Vertex<3, fltp08>(rect->center().x(), rect->center().y(), 0.0))
209 .scale(Vector<3, fltp08>(rect->width() / 2.0, rect->height() / 2.0, 1.0)));
210 }
212 geo.updateModifiedTime();
213 finishShape(true);
214 }
215 virtual void drawRects(const QRect* rects, int rectCount) override
216 {
217 drawRectsT(rects, rectCount);
218 }
219 virtual void drawRects(const QRectF* rects, int rectCount) override
220 {
221 drawRectsT(rects, rectCount);
222 }
223 template<class t_type>
224 void drawLinesT(const t_type* lines, int line_count)
225 {
226 Model model = m_models.last().createChild();
227 setupShapeModel(model);
228 Geometry geo = model.createChildGeometry();
229 if (!m_is_flat)
230 geo.set<NDPO::name>("LinesT");
231 geo.set<NDPO::transform>(getTransform(false));
232 geo.setGeometryType(GeometryType::e_linework);
233 geo.setPrimitiveMode(PrimitiveProperty::Solid, PrimitiveMode::e_lines);
234 geo.setPrimitiveMode(PrimitiveProperty::Outline, PrimitiveMode::e_lines);
235 geo.setupVertexTable(0, Geometry::VertexMode::e_cartesian_3F);
236 uint04 primitive_start = geo.addPrimitives(PrimitiveProperty::Outline, cast<uint04>(line_count));
237 uint04 vertex_start = geo.addVertices(cast<uint04>(line_count) * 2);
238 for (uint04 i = 0; i < cast<uint04>(line_count); i++)
239 {
240 geo.setVertex(VertexProperty::Position, vertex_start + 2 * i, Vertex<3, fltp08>(lines[i].x1(), lines[i].y1(), 0.0));
241 geo.setVertex(VertexProperty::Position, vertex_start + 2 * i + 1, Vertex<3, fltp08>(lines[i].x2(), lines[i].y2(), 0.0));
242 geo.setPrimitive(PrimitiveProperty::Outline, primitive_start + i, vertex_start + Vector<2, uint04>(2 * i, 2 * i + 1));
243 }
244 geo.autoCalculateIndices(PrimitiveProperty::Solid);
245 geo.updateModifiedTime();
246 finishShape(false);
247 }
248 virtual void drawLines(const QLine* lines, int line_count) override
249 {
250 drawLinesT<QLine>(lines, line_count);
251 }
252 virtual void drawLines(const QLineF* lines, int line_count) override
253 {
254 drawLinesT<QLineF>(lines, line_count);
255 }
256
257 template<class t_type>
258 void drawEllipseT(const t_type& r)
259 {
260 if (r.width() == 0 || r.height() == 0)
261 {
262 if (r.width() == 0 && r.height() == 0)
263 {
264 QPointF p(r.center().x(), r.center().y());
265 drawPoints(&p, 1);
266 }
267 else if (r.width() == 0)
268 {
269 QPointF p1(r.center().x(), r.center().y() - r.height() / 2.0);
270 QPointF p2(r.center().x(), r.center().y() + r.height() / 2.0);
271 QLineF l(p1, p2);
272 drawLines(&l, 1);
273 }
274 else if (r.height() == 0)
275 {
276 QPointF p1(r.center().x() - r.width() / 2.0, r.center().y());
277 QPointF p2(r.center().x() + r.width() / 2.0, r.center().y());
278 QLineF l(p1, p2);
279 drawLines(&l, 1);
280 }
281 return;
282 }
283 Model model = m_models.last().createChild();
284 setupShapeModel(model);
285
286 Geometry geo = model.createChildGeometry();
287 if (!m_is_flat)
288 geo.set<NDPO::name>("EllipseT");
289 geo.set<NDPO::transform>(getTransform(false));
290 geo.setGeometryType(GeometryType::e_convex_polygons);
291 geo.setupVertexTable(0, Geometry::VertexMode::e_cartesian_3F);
292 ShapeConstructors::Circle(geo, Matrix<fltp08>::OffsetMatrix(Vertex<3, fltp08>(r.center().x(), r.center().y(), 0.0))
293 .scale(Vector<3, fltp08>(r.width() / 2.0, r.height() / 2.0, 1.0)));
294 geo.autoCalculateIndices(PrimitiveProperty::Solid);
295 finishShape(true);
296 }
297 virtual void drawEllipse(const QRectF& r) override
298 {
299 drawEllipseT(r);
300 }
301 virtual void drawEllipse(const QRect& r) override
302 {
303 drawEllipseT(r);
304 }
309 static QPalette ScenePalette();
314 static QStyle* SceneStyle();
315 virtual void drawPath(const QPainterPath& path) override;
316 template<class t_type>
317 void drawPointsT(const t_type* points, int point_count)
318 {
319 Model model = m_models.last().createChild();
320 setupShapeModel(model, false);
321
322 Geometry geo = model.createChildGeometry();
323 geo.set<NDPO::transform>(getTransform(false));
325 if (!m_is_flat)
326 geo.set<NDPO::name>("PointsT");
328 uint04 vertex_start = geo.addVertices(cast<uint04>(point_count));
329 for (uint04 i = 0; i < cast<uint04>(point_count); i++)
330 {
331 geo.setVertex(VertexProperty::Position, vertex_start + i, Vertex<3, fltp08>(points[i].x(), points[i].y(), 0.0));
332 }
334 finishShape(false);
335 }
336 virtual void drawPoints(const QPointF* points, int point_count) override
337 {
338 drawPointsT(points, point_count);
339 }
340 virtual void drawPoints(const QPoint* points, int point_count) override
341 {
342 drawPointsT(points, point_count);
343 }
344 template<class t_type>
345 void drawPolygonT(const t_type * points, int point_count, PolygonDrawMode mode)
346 {
347 if (point_count <= 0)
348 return;
349 Model model = m_is_clipping ? m_models.last() : m_models.last().createChild();
350 if(!m_is_clipping)
351 setupShapeModel(model, mode != PolygonDrawMode::PolylineMode);
352
353 Geometry geo = model.createChildGeometry();
354 if(!m_is_flat)
355 geo.set<NDPO::name>("PolygonT");
356 geo.set<NDPO::transform>(getTransform(false));
357 if (mode == PolygonDrawMode::ConvexMode)
358 geo.setGeometryType(GeometryType::e_convex_polygons);
359 else if (mode == PolygonDrawMode::PolylineMode)
360 geo.setGeometryType(GeometryType::e_linework);
361 else
362 geo.setGeometryType(GeometryType::e_concave_polygons);
363
364 Polygon<fltp08> poly(point_count);
365 for (uint04 i = 0; i < cast<uint04>(point_count); i++)
366 {
367 poly.add(Vertex<2, fltp08>(points[i].x(), points[i].y()));
368 }
369 poly.simplify();
370 geo.setupVertexTable(poly.vertexCount(), Geometry::VertexMode::e_cartesian_3F);
371 geo.addPrimitives(PrimitiveProperty::Outline, poly.vertexCount() + 1);
372 for (uint04 i = 0; i < poly.vertexCount(); i++)
373 {
374 geo.setVertex(VertexProperty::Position, i, poly.vertex(i).as<3, fltp08>(0.0));
375 geo.setPrimitive(PrimitiveProperty::Outline, i, i);
376 }
377 geo.setPrimitive(PrimitiveProperty::Outline, poly.vertexCount(), 0);
378 if(!m_is_clipping)
379 geo.autoCalculateIndices(PrimitiveProperty::Solid);
380 geo.set<NDPG::is_clipping_geo>(m_is_clipping);
381 finishShape(true);
382 }
383 virtual void drawPolygon(const QPointF* points, int point_count, PolygonDrawMode mode) override
384 {
385 drawPolygonT(points, point_count, mode);
386 }
387 virtual void drawPolygon(const QPoint* points, int point_count, PolygonDrawMode mode) override
388 {
389 drawPolygonT(points, point_count, mode);
390 }
391
392 virtual void drawPixmap(const QRectF& r, const QPixmap& pm, const QRectF& sr) override
393 {
394 QImage image = pm.toImage();
395 drawImage(r, image, sr);
396
397 }
398 virtual void drawTextItem(const QPointF& p, const QTextItem& text_item) override;
399 virtual void drawTiledPixmap(const QRectF& r, const QPixmap& pixmap, const QPointF& s) override
400 {
401 drawImage(r, pixmap.toImage(), QRectF(s, QSizeF(1.0, 1.0)));
402 }
403 virtual void drawImage(const QRectF& r, const QImage& image, const QRectF& sr, Qt::ImageConversionFlags flags = Qt::AutoColor) override;
404 virtual Type type() const override
405 {
406 return Type::User;
407 }
412 static PaintEngineFeatures SceneRenderFeatures();
417 void finishShape(bool is_solid);
423 Matrix<fltp08> getTransform(bool is_text) const;
430 void setupShapeModel(Model& model, bool has_solid = true, bool is_text = false);
442 void setIsFlat(bool is_flat) { m_is_flat = is_flat; };
447 bool isFlat() const { return m_is_flat; }
459 [[nodiscard]] bool hasOutline() const;
464 [[nodiscard]] bool hasSolid() const;
465 fltp08 currentThickness() const
466 {
467 return state->pen().widthF();
468 }
469 RGBColor currentFillColor() const
470 {
471 return QTTools::convert(state->brush().color());
472 }
473 RGBColor currentOutlineColor() const
474 {
475 return QTTools::convert(state->pen().color());
476 }
477 const Model& root() const
478 {
479 return m_root;
480 }
481 protected:
489 bool m_is_flat = false;
490 };
491}
492#endif
The equivelent of std::vector but with a bit more control.
Definition Buffer.hpp:58
A core class where all Design Objects including models, materials, and geometries are stored.
void set(t_property_type property, const t_type &value)
Sets a property value in the database.
A hash-based key-value store, useful for quick associative lookups.
Definition Dictionary.h:64
Logic for reading or writing to a file as well as navigating filesystems or other common file operati...
Definition File.h:53
A core class within the model hierarchy containing vertex-based data (Usually 3D data) within a set c...
Definition Geometry.h:143
@ e_cartesian_3F
3D Cartesian coordinates, single-precision float.
Definition Geometry.h:156
void updateModifiedTime(Time time=Time::SystemTime())
Updates the modified timestamp for this geometry.
void setupVertexTable(uint04 vertex_size, VertexMode position, VertexMode normal=VertexMode::e_no_vertex, VertexMode color=VertexMode::e_no_vertex, VertexMode texture=VertexMode::e_no_vertex, VertexMode tangent=VertexMode::e_no_vertex, VertexMode bitangent=VertexMode::e_no_vertex, VertexMode bones=VertexMode::e_no_vertex)
Configures the vertex table with the specified modes for standard properties.
void autoCalculateIndices(PrimitiveProperty property, const void *lock=nullptr, const Matrix< fltp08 > &transform=Matrix< fltp08 >(1.0), LogPtr log=LogPtr())
Automatically calculates primitive indices (e.g.
uint04 addVertices(uint04 size)
Adds multiple vertices to the geometry.
Definition Geometry.h:1195
void setGeometryType(GeometryType geometry_type)
Sets the geometry type identifier.
void setVertex(VertexProperty property, uint04 index, const t_type &vector)
Sets a standard vertex property value at the given index.
Definition Geometry.h:1654
Container responsible for storing and setting the appearance of a Model or Geometry within the NDEVR ...
Definition Material.h:153
Templated logic for doing matrix multiplication.
Definition Matrix.hpp:182
A core class that represents a node on model hierarchy.
Definition Model.h:292
Model createChild()
Creates a new child model and appends it to this model's child list.
Geometry createChildGeometry()
Creates a new child geometry for this model.
static QColor convert(const RGBColor &color)
Converts an NDEVR RGBColor to a QColor.
Represents a color in the RGB space with optional alpha transparency.
Definition RGBColor.h:57
void drawWidget(QWidget *widget, QPainter &painter, QPoint offset, uint04 depth)
Draws a QWidget into the 3D scene hierarchy.
Vector< 2, int > m_physical_dpi
Physical DPI for both axes.
int m_device_pixel_ratio_scaled
The scaled device pixel ratio.
void setDPIY(int dpi)
Sets the vertical DPI.
void setDPIX(int dpi)
Sets the horizontal DPI.
ScenePaintEngine * m_paint_engine
The underlying paint engine.
void setDPI(int dpi)
Sets the DPI for both axes.
void setDevicePixelRatioScaled(int ratio)
Sets the scaled device pixel ratio.
QWidget * m_widget
The widget being painted.
void setPhysicalDPI(int dpi_x, int dpi_y)
Sets the physical DPI for the paint device.
Vector< 2, int > m_dpi
Logical DPI for both axes.
ScenePaintEngine * scenePaintEngine()
Retrieves the underlying scene paint engine.
void setRoot(Model &model)
Sets the root model for painting.
int m_device_pixel_ratio
The device pixel ratio.
void setDevicePixelRatio(int ratio)
Sets the device pixel ratio.
ScenePaintDevice(Model &model)
Constructs a scene paint device rooted at the given model.
Time m_last_update_update
Timestamp of the last update.
A QPaintEngine that 'paints' the widgets by turning them into 3D Model objects.
Model m_root
The root model of the paint hierarchy.
static Buffer< UUID > PrepareWidgetsViews(DesignObjectLookup &lookup, const Buffer< QWidget * > &widgets, QSize size=QSize())
Prepares camera views from widgets for rendering.
void setRoot(Model &new_root)
Sets the root model for the paint engine.
uint04 m_geometry_depth
The current geometry depth in the hierarchy.
Matrix< fltp08 > getTransform(bool is_text) const
Computes the current transform matrix for painting.
void setupShapeModel(Model &model, bool has_solid=true, bool is_text=false)
Sets up a model for a painted shape with appropriate materials.
String m_current_image
The current image resource identifier being drawn.
static Buffer< QSize > WidgetsToModel(const WidgetIterator &reports, Model &model, QSize size=QSize(), bool is_flat=false)
Converts widget reports into 3D model objects.
void updateClipping(Model &model)
Updates the clipping region for the given model.
Material createCurrentMaterial(PrimitiveProperty property, bool is_text)
Creates a new material for the given property type using current paint state.
static Buffer< UUID > PrepareWidgetsViews(DesignObjectLookup &lookup, const WidgetIterator &reports, QSize size=QSize())
Prepares camera views from widget reports for rendering.
bool m_is_clipping
Whether clipping is currently active.
void popModel()
Pops the current model from the model stack, returning to the parent.
Material currentMaterial(PrimitiveProperty property, bool is_text)
Retrieves or creates the current material for the given property type.
uint04 m_extra_depth
Extra depth offset for z-ordering painted elements.
static QPalette ScenePalette()
Retrieves the palette used for scene painting.
void finishShape(bool is_solid)
Finalizes the current shape model after geometry creation.
void setCurrentName(const String &current_name)
Sets the current name used for naming new child models.
static void PrepareWidgetsToModel(const Buffer< QWidget * > &widgets, QSize size=QSize())
Prepares widgets for model conversion by resizing and laying out.
Dictionary< UUID, Material > m_materials
Cache of materials created during painting.
Buffer< Model > m_models
Stack of models for nested painting.
ScenePaintEngine(Model &scene)
Constructs a scene paint engine rooted at the given model.
static PaintEngineFeatures SceneRenderFeatures()
Retrieves the supported paint engine features for scene rendering.
static QStyle * SceneStyle()
Retrieves the style used for scene painting.
void pushModel()
Pushes a new child model onto the model stack for nested painting.
bool hasSolid() const
Checks whether the current paint state has a solid brush.
static void ModelsToPDF(const File &file, DesignObjectLookup &lookup, const Buffer< UUID > &camera_ids, fltp08 dpi, fltp04 margins=20.0f)
Renders 3D model views to a PDF file.
void setIsFlat(bool is_flat)
Sets whether the output should be flat (2D) or hierarchical.
void resetExtraDepth()
Resets the extra depth counter used for z-ordering painted elements.
bool m_is_flat
Whether the engine is in flat (2D) mode.
bool isFlat() const
Checks whether the engine is in flat (2D) mode.
static void WidgetsToPDF(const File &file, const Buffer< QWidget * > &widgets, QSize size=QSize())
Renders widgets directly to a PDF file.
static void AutoWidgetsToPDF(File file, WidgetIterator reports, QSize size=QSize(), bool send_file=false)
Converts widget reports to a PDF file and optionally sends the file.
bool hasOutline() const
Checks whether the current paint state has an outline pen.
static void Rectangle(Geometry &mesh, const Matrix< fltp08 > &trans=Matrix< fltp08 >(1), fltp08 top_length=2.0, fltp08 bottom_length=2.0, fltp08 left_length=2.0, fltp08 right_length=2.0, fltp08 vertical_skew=0.0, fltp08 horizontal_skew=0.0)
Appends a rectangle to the mesh with configurable edge lengths and skew.
The core String class for the NDEVR API.
Definition String.h:95
Represents a timestamp with utilities for manipulation and conversion.
Definition Time.h:62
A fixed-size array with N dimensions used as the basis for geometric and mathematical types.
Definition Vector.hpp:62
A point in N-dimensional space, used primarily for spatial location information.
Definition Vertex.hpp:44
Provides a way to iterate over a series of widgets, useful for printing dialogs or turning Widgets in...
The primary namespace for the NDEVR SDK.
@ type
The type identifier string for this model node.
Definition Model.h:58
@ Position
XYZ position of the vertex.
float fltp04
Defines an alias representing a 4 byte floating-point number Bit layout is as follows: -Sign: 1 bit a...
uint32_t uint04
-Defines an alias representing a 4 byte, unsigned integer -Can represent exact integer values 0 throu...
@ e_points
Point cloud or discrete points.
@ e_convex_polygons
Convex polygon meshes.
double fltp08
Defines an alias representing an 8 byte floating-point number.
@ name
The display name of the object.
@ transform
A 4x4 transform matrix that maps local coordinates into global space.
PrimitiveProperty
Describes which rendering property a primitive index buffer corresponds to.
@ Solid
Solid filled rendering of primitives.
constexpr t_to cast(const Angle< t_from > &value)
Casts an Angle from one backing type to another.
Definition Angle.h:408