C
Qt Cluster: Rendering and Recovery from Main UI Failure
// Copyright (C) 2022 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause // This file is part of the Qt Safe Renderer module #include "gaugenode.h" #include <QtQuick/qsgnode.h> #include <QtQuick/qsgflatcolormaterial.h> #include <QtMath> #define EXTRAVERTICES 3 GaugeNode::GaugeNode(const int &numVertices, const QColor &color = QColor(255, 0, 0), const bool &doNotFill = false) : QSGGeometryNode() , m_geometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), numVertices+EXTRAVERTICES) , m_material(nullptr) , m_numVertices(numVertices) , m_doNotFill(doNotFill) , m_color(color) , m_cutRad(0.0) , m_lefttoright(true) { initGeometry(); } GaugeNode::~GaugeNode() { if (m_material) delete m_material; } void GaugeNode::setColor(const QColor &color) { if (m_color == color) return; m_color = color; m_dirtyBits |= QSGNode::DirtyMaterial; } void GaugeNode::setCutRad(const float &cutRad) { if (m_cutRad == cutRad) return; m_cutRad = cutRad; } void GaugeNode::setDoNotFill(const bool &doNotFill) { if (m_doNotFill == doNotFill) return; m_doNotFill = doNotFill; if (m_doNotFill) m_geometry.setDrawingMode(QSGGeometry::DrawLineStrip); else m_geometry.setDrawingMode(QSGGeometry::DrawTriangleStrip); m_dirtyBits |= QSGNode::DirtyGeometry; } void GaugeNode::setBackCutRad(const double &backCutRad) { if (backCutRad == m_backCutRad) return; m_backCutRad = backCutRad; m_dirtyBits |= QSGNode::DirtyGeometry; } void GaugeNode::setRadius(const double &radius) { if (m_radius == radius) return; m_radius = radius; m_dirtyBits |= QSGNode::DirtyGeometry; } void GaugeNode::setArcDistPerVert(const double &dist) { if (dist == m_arc_dist_per_vertices) return; m_arc_dist_per_vertices = dist; m_dirtyBits |= QSGNode::DirtyGeometry; } void GaugeNode::setNumVertices(const int &numVertices) { if (numVertices == m_numVertices) return; m_numVertices = numVertices; m_geometry.allocate(m_numVertices + 3); m_dirtyBits |= QSGNode::DirtyGeometry; } void GaugeNode::setFillWidth(const double &fillWidth) { if (m_fillWidth == fillWidth) return; m_fillWidth = fillWidth; m_dirtyBits |= QSGNode::DirtyGeometry; } void GaugeNode::setBoundingRect(const QRectF &rect) { if (rect.width() == m_width && rect.height() == m_height) return; m_height = rect.height(); m_width = rect.width(); setCenterPoint(rect.center()); m_dirtyBits |= QSGNode::DirtyGeometry; } void GaugeNode::setCenterPoint(const QPointF ¢er) { m_center_x = center.x(); m_center_y = center.y(); } void GaugeNode::setLeftToRight(const bool <r) { if (m_lefttoright == ltr) return; m_lefttoright = ltr; m_dirtyBits |= QSGNode::DirtyMaterial; } void GaugeNode::drawGeometryTexturePoint2D() { QSGGeometry::TexturedPoint2D *vertices = m_geometry.vertexDataAsTexturedPoint2D(); double current_angle_rad = 0.0; double currentRadius = m_radius; double d_arc_point_x = m_center_x + (currentRadius - m_fillWidth) * qCos(m_backCutRad); double d_arc_point_y = m_center_y + (currentRadius - m_fillWidth) * qSin(m_backCutRad); vertices[0].set(d_arc_point_x, d_arc_point_y, d_arc_point_x / m_width, d_arc_point_y / m_height); d_arc_point_x = m_center_x + currentRadius * qCos(m_backCutRad); d_arc_point_y = m_center_y + currentRadius * qSin(m_backCutRad); vertices[1].set(d_arc_point_x, d_arc_point_y, d_arc_point_x / m_width, d_arc_point_y / m_height); d_arc_point_x = 0; d_arc_point_y = 0; for (int i = 0; i < m_numVertices; ++i) { current_angle_rad = m_backCutRad + i * m_arc_dist_per_vertices + m_arc_dist_per_vertices; if (i % 2 == 0) currentRadius -= m_fillWidth; else currentRadius += m_fillWidth; d_arc_point_x = m_center_x + currentRadius * qCos(current_angle_rad); d_arc_point_y = m_center_y + currentRadius * qSin(current_angle_rad); vertices[i + 2].set(d_arc_point_x, d_arc_point_y, d_arc_point_x / m_width, d_arc_point_y / m_height); } d_arc_point_x = m_center_x + (currentRadius - m_fillWidth) * qCos(current_angle_rad); d_arc_point_y = m_center_y + (currentRadius - m_fillWidth) * qSin(current_angle_rad); vertices[m_numVertices + 2].set(d_arc_point_x, d_arc_point_y, d_arc_point_x / m_width, d_arc_point_y / m_height); } void GaugeNode::drawMaterial() { static_cast<QSGFlatColorMaterial *>(m_material)->setColor(m_color); } void GaugeNode::draw() { if (m_dirtyBits == 0) return; if (m_dirtyBits.testFlag(QSGNode::DirtyGeometry)) drawGeometryTexturePoint2D(); if (m_dirtyBits.testFlag(QSGNode::DirtyMaterial)) drawMaterial(); markDirty(m_dirtyBits); m_dirtyBits = DirtyState(); } //Could be used to optimize vertices if only geometry is changed void GaugeNode::drawGeometry() { QSGGeometry::Point2D *vertices = m_geometry.vertexDataAsPoint2D(); double d_arc_point_x = 0.0; double d_arc_point_y = 0.0; double current_angle_rad = 0.0; double currentRadius = m_radius; vertices[0].set(m_center_x + (currentRadius - m_fillWidth) * qCos(m_backCutRad), m_center_y + (currentRadius - m_fillWidth) * qSin(m_backCutRad)); vertices[1].set(m_center_x + currentRadius * qCos(m_backCutRad), m_center_y + currentRadius * qSin(m_backCutRad)); for (int i = 0; i < m_numVertices; ++i) { current_angle_rad = m_backCutRad + i * m_arc_dist_per_vertices + m_arc_dist_per_vertices; if (i % 2 == 0) currentRadius -= m_fillWidth; else currentRadius += m_fillWidth; d_arc_point_x = m_center_x + currentRadius * qCos(current_angle_rad); d_arc_point_y = m_center_y + currentRadius * qSin(current_angle_rad); vertices[i + 2].set(d_arc_point_x, d_arc_point_y); } vertices[m_numVertices + 2].set(m_center_x + (currentRadius - m_fillWidth) * qCos(current_angle_rad), m_center_y + (currentRadius - m_fillWidth) * qSin(current_angle_rad)); markDirty(QSGNode::DirtyGeometry | QSGNode::DirtyMaterial); } void GaugeNode::initGeometry() { m_geometry.setLineWidth(1); if (m_doNotFill) m_geometry.setDrawingMode(QSGGeometry::DrawLineStrip); else m_geometry.setDrawingMode(QSGGeometry::DrawTriangleStrip); setGeometry(&m_geometry); QSGFlatColorMaterial *material = new QSGFlatColorMaterial; material->setColor(m_color); m_material = static_cast<QSGMaterial *>(material); setMaterial(m_material); }