QmlPuppet: Change custom 3D geometries to use public API

Custom geometries often break and code becomes convoluted with
version ifdeffing, so refactor the custom geometries to use public
geometry api, which works both in Qt5 and Qt6.

Fixes: QDS-4611
Change-Id: I2d78776a14d5c8153b52806842254dbedb5de83d
Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io>
This commit is contained in:
Miikka Heikkinen
2021-06-23 16:29:37 +03:00
parent a86c480d50
commit 48348b8dc4
16 changed files with 286 additions and 301 deletions
@@ -27,7 +27,6 @@
#include "camerageometry.h"
#include <QtQuick3DRuntimeRender/private/qssgrendergeometry_p.h>
#include <QtQuick3DRuntimeRender/private/qssgrendercamera_p.h>
#include <QtQuick3D/private/qquick3dcustomcamera_p.h>
#include <QtQuick3D/private/qquick3dfrustumcamera_p.h>
@@ -35,7 +34,6 @@
#include <QtQuick3D/private/qquick3dperspectivecamera_p.h>
#include <QtQuick3D/private/qquick3dutils_p.h>
#include <QtCore/qmath.h>
#include <QtCore/qtimer.h>
#include <limits>
@@ -43,7 +41,7 @@ namespace QmlDesigner {
namespace Internal {
CameraGeometry::CameraGeometry()
: QQuick3DGeometry()
: GeometryBase()
{
}
@@ -51,19 +49,6 @@ CameraGeometry::~CameraGeometry()
{
}
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
QString CameraGeometry::name() const
{
return objectName();
}
void CameraGeometry::setName(const QString &name)
{
setObjectName(name);
emit nameChanged();
}
#endif
QQuick3DCamera *CameraGeometry::camera() const
{
return m_camera;
@@ -111,7 +96,7 @@ void CameraGeometry::setCamera(QQuick3DCamera *camera)
this, &CameraGeometry::handleCameraPropertyChange);
}
emit cameraChanged();
update();
handleCameraPropertyChange();
}
void CameraGeometry::setViewPortRect(const QRectF &rect)
@@ -121,26 +106,37 @@ void CameraGeometry::setViewPortRect(const QRectF &rect)
m_viewPortRect = rect;
emit viewPortRectChanged();
update();
updateGeometry();
}
void CameraGeometry::handleCameraPropertyChange()
{
m_cameraUpdatePending = true;
clear();
setStride(12); // To avoid div by zero inside QtQuick3D
update();
}
QSSGRenderGraphObject *CameraGeometry::updateSpatialNode(QSSGRenderGraphObject *node)
{
if (m_cameraUpdatePending) {
m_cameraUpdatePending = false;
updateGeometry();
}
return QQuick3DGeometry::updateSpatialNode(node);
}
void CameraGeometry::doUpdateGeometry()
{
if (!m_camera)
return node;
return;
// If camera properties have been updated, we need to defer updating the frustum geometry
// to the next frame to ensure camera's spatial node has been properly updated.
if (m_cameraUpdatePending) {
QTimer::singleShot(0, this, &CameraGeometry::update);
m_cameraUpdatePending = false;
return node;
update();
return;
}
if (!m_camera->cameraNode()) {
@@ -148,11 +144,7 @@ QSSGRenderGraphObject *CameraGeometry::updateSpatialNode(QSSGRenderGraphObject *
m_camera->mapToViewport({}, m_viewPortRect.width(), m_viewPortRect.height());
}
setStride(12); // Silence a warning
node = QQuick3DGeometry::updateSpatialNode(node);
QSSGRenderGeometry *geometry = static_cast<QSSGRenderGeometry *>(node);
geometry->clear();
GeometryBase::doUpdateGeometry();
QByteArray vertexData;
QByteArray indexData;
@@ -160,25 +152,11 @@ QSSGRenderGraphObject *CameraGeometry::updateSpatialNode(QSSGRenderGraphObject *
QVector3D maxBounds;
fillVertexData(vertexData, indexData, minBounds, maxBounds);
geometry->setStride(12);
#if QT_VERSION < QT_VERSION_CHECK(6, 1, 0)
geometry->addAttribute(QSSGRenderGeometry::Attribute::PositionSemantic, 0,
QSSGRenderGeometry::Attribute::ComponentType::F32Type);
geometry->addAttribute(QSSGRenderGeometry::Attribute::IndexSemantic, 0,
QSSGRenderGeometry::Attribute::ComponentType::U16Type);
geometry->setPrimitiveType(QSSGRenderGeometry::Lines);
#else
geometry->addAttribute(QSSGMesh::RuntimeMeshData::Attribute::PositionSemantic, 0,
QSSGMesh::Mesh::ComponentType::Float32);
geometry->addAttribute(QSSGMesh::RuntimeMeshData::Attribute::IndexSemantic, 0,
QSSGMesh::Mesh::ComponentType::UnsignedInt16);
geometry->setPrimitiveType(QSSGMesh::Mesh::DrawMode::Lines);
#endif
geometry->setVertexData(vertexData);
geometry->setIndexData(indexData);
geometry->setBounds(minBounds, maxBounds);
return node;
addAttribute(QQuick3DGeometry::Attribute::IndexSemantic, 0,
QQuick3DGeometry::Attribute::U16Type);
setVertexData(vertexData);
setIndexData(indexData);
setBounds(minBounds, maxBounds);
}
void CameraGeometry::fillVertexData(QByteArray &vertexData, QByteArray &indexData,
@@ -27,29 +27,19 @@
#ifdef QUICK3D_MODULE
#include <QtQuick3D/private/qquick3dgeometry_p.h>
#include "geometrybase.h"
#include <QtQuick3D/private/qquick3dcamera_p.h>
namespace QmlDesigner {
namespace Internal {
class CameraGeometry : public QQuick3DGeometry
class CameraGeometry : public GeometryBase
{
Q_OBJECT
Q_PROPERTY(QQuick3DCamera *camera READ camera WRITE setCamera NOTIFY cameraChanged)
Q_PROPERTY(QRectF viewPortRect READ viewPortRect WRITE setViewPortRect NOTIFY viewPortRectChanged)
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
// Name property was removed in Qt 6, so define it here for compatibility.
// Name maps to object name.
Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
public:
QString name() const;
void setName(const QString &name);
signals:
void nameChanged();
#endif
public:
CameraGeometry();
~CameraGeometry() override;
@@ -68,10 +58,12 @@ signals:
protected:
QSSGRenderGraphObject *updateSpatialNode(QSSGRenderGraphObject *node) override;
void doUpdateGeometry() override;
private:
void fillVertexData(QByteArray &vertexData, QByteArray &indexData,
QVector3D &minBounds, QVector3D &maxBounds);
QQuick3DCamera *m_camera = nullptr;
QRectF m_viewPortRect;
bool m_cameraUpdatePending = false;
@@ -1,5 +1,6 @@
HEADERS += $$PWD/generalhelper.h \
$$PWD/mousearea3d.h \
$$PWD/geometrybase.h \
$$PWD/camerageometry.h \
$$PWD/lightgeometry.h \
$$PWD/gridgeometry.h \
@@ -9,6 +10,7 @@ HEADERS += $$PWD/generalhelper.h \
SOURCES += $$PWD/generalhelper.cpp \
$$PWD/mousearea3d.cpp \
$$PWD/geometrybase.cpp \
$$PWD/camerageometry.cpp \
$$PWD/lightgeometry.cpp \
$$PWD/gridgeometry.cpp \
@@ -0,0 +1,81 @@
/****************************************************************************
**
** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#ifdef QUICK3D_MODULE
#include "geometrybase.h"
namespace QmlDesigner {
namespace Internal {
GeometryBase::GeometryBase()
: QQuick3DGeometry()
{
m_updatetimer.setSingleShot(true);
m_updatetimer.setInterval(0);
connect(&m_updatetimer, &QTimer::timeout, this, &GeometryBase::doUpdateGeometry);
updateGeometry();
setStride(12); // To avoid div by zero inside QtQuick3D
}
GeometryBase::~GeometryBase()
{
}
void GeometryBase::doUpdateGeometry()
{
clear();
setStride(12);
addAttribute(QQuick3DGeometry::Attribute::PositionSemantic, 0,
QQuick3DGeometry::Attribute::F32Type);
setPrimitiveType(QQuick3DGeometry::PrimitiveType::Lines);
update();
}
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
QString GeometryBase::name() const
{
return objectName();
}
void GeometryBase::setName(const QString &name)
{
setObjectName(name);
emit nameChanged();
}
#endif
void GeometryBase::updateGeometry()
{
m_updatetimer.start();
}
}
}
#endif // QUICK3D_MODULE
@@ -0,0 +1,69 @@
/****************************************************************************
**
** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
#ifdef QUICK3D_MODULE
#include <QtQuick3D/private/qquick3dgeometry_p.h>
#include <QTimer>
namespace QmlDesigner {
namespace Internal {
class GeometryBase : public QQuick3DGeometry
{
Q_OBJECT
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
// Name property was removed in Qt 6, so define it here for compatibility.
// Name maps to object name.
Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
public:
QString name() const;
void setName(const QString &name);
signals:
void nameChanged();
#endif
public:
GeometryBase();
~GeometryBase() override;
protected:
void updateGeometry();
virtual void doUpdateGeometry();
private:
QTimer m_updatetimer;
};
}
}
QML_DECLARE_TYPE(QmlDesigner::Internal::GeometryBase)
#endif // QUICK3D_MODULE
@@ -27,33 +27,19 @@
#include "gridgeometry.h"
#include <QtQuick3DRuntimeRender/private/qssgrendergeometry_p.h>
namespace QmlDesigner {
namespace Internal {
GridGeometry::GridGeometry()
: QQuick3DGeometry()
: GeometryBase()
{
updateGeometry();
}
GridGeometry::~GridGeometry()
{
}
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
QString GridGeometry::name() const
{
return objectName();
}
void GridGeometry::setName(const QString &name)
{
setObjectName(name);
emit nameChanged();
}
#endif
int GridGeometry::lines() const
{
return m_lines;
@@ -79,7 +65,7 @@ void GridGeometry::setLines(int count)
return;
m_lines = qMax(count, 1);
emit linesChanged();
update();
updateGeometry();
}
// Space between lines
@@ -90,7 +76,7 @@ void GridGeometry::setStep(float step)
return;
m_step = step;
emit stepChanged();
update();
updateGeometry();
}
void GridGeometry::setIsCenterLine(bool enabled)
@@ -100,36 +86,22 @@ void GridGeometry::setIsCenterLine(bool enabled)
m_isCenterLine = enabled;
emit isCenterLineChanged();
update();
updateGeometry();
}
QSSGRenderGraphObject *GridGeometry::updateSpatialNode(QSSGRenderGraphObject *node)
void GridGeometry::doUpdateGeometry()
{
setStride(12); // Silence a warning
node = QQuick3DGeometry::updateSpatialNode(node);
QSSGRenderGeometry *geometry = static_cast<QSSGRenderGeometry *>(node);
geometry->clear();
GeometryBase::doUpdateGeometry();
QByteArray vertexData;
fillVertexData(vertexData);
geometry->setStride(12);
#if QT_VERSION < QT_VERSION_CHECK(6, 1, 0)
geometry->addAttribute(QSSGRenderGeometry::Attribute::PositionSemantic, 0,
QSSGRenderGeometry::Attribute::ComponentType::F32Type);
geometry->setPrimitiveType(QSSGRenderGeometry::Lines);
#else
geometry->addAttribute(QSSGMesh::RuntimeMeshData::Attribute::PositionSemantic, 0,
QSSGMesh::Mesh::ComponentType::Float32);
geometry->setPrimitiveType(QSSGMesh::Mesh::DrawMode::Lines);
#endif
geometry->setVertexData(vertexData);
setVertexData(vertexData);
int lastIndex = (vertexData.size() - 1) / int(sizeof(QVector3D));
auto vertexPtr = reinterpret_cast<QVector3D *>(vertexData.data());
geometry->setBounds(QVector3D(vertexPtr[0][0], vertexPtr[0][1], 0.0),
QVector3D(vertexPtr[lastIndex][0], vertexPtr[lastIndex][1], 0.0));
return node;
setBounds(QVector3D(vertexPtr[0][0], vertexPtr[0][1], 0.0),
QVector3D(vertexPtr[lastIndex][0], vertexPtr[lastIndex][1], 0.0));
}
void GridGeometry::fillVertexData(QByteArray &vertexData)
@@ -27,12 +27,12 @@
#ifdef QUICK3D_MODULE
#include <QtQuick3D/private/qquick3dgeometry_p.h>
#include "geometrybase.h"
namespace QmlDesigner {
namespace Internal {
class GridGeometry : public QQuick3DGeometry
class GridGeometry : public GeometryBase
{
Q_OBJECT
@@ -41,17 +41,6 @@ class GridGeometry : public QQuick3DGeometry
Q_PROPERTY(bool isCenterLine READ isCenterLine WRITE setIsCenterLine NOTIFY isCenterLineChanged)
Q_PROPERTY(bool isSubdivision MEMBER m_isSubdivision)
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
// Name property was removed in Qt 6, so define it here for compatibility.
// Name maps to object name.
Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
public:
QString name() const;
void setName(const QString &name);
signals:
void nameChanged();
#endif
public:
GridGeometry();
~GridGeometry() override;
@@ -71,7 +60,7 @@ signals:
void isCenterLineChanged();
protected:
QSSGRenderGraphObject *updateSpatialNode(QSSGRenderGraphObject *node) override;
void doUpdateGeometry() override;
private:
void fillVertexData(QByteArray &vertexData);
@@ -37,7 +37,7 @@ namespace QmlDesigner {
namespace Internal {
LightGeometry::LightGeometry()
: QQuick3DGeometry()
: GeometryBase()
{
}
@@ -45,19 +45,6 @@ LightGeometry::~LightGeometry()
{
}
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
QString LightGeometry::name() const
{
return objectName();
}
void LightGeometry::setName(const QString &name)
{
setObjectName(name);
emit nameChanged();
}
#endif
LightGeometry::LightType LightGeometry::lightType() const
{
return m_lightType;
@@ -71,45 +58,29 @@ void LightGeometry::setLightType(LightGeometry::LightType lightType)
m_lightType = lightType;
emit lightTypeChanged();
update();
updateGeometry();
}
QSSGRenderGraphObject *LightGeometry::updateSpatialNode(QSSGRenderGraphObject *node)
void LightGeometry::doUpdateGeometry()
{
if (m_lightType == LightType::Invalid)
return node;
return;
setStride(12); // Silence a warning
node = QQuick3DGeometry::updateSpatialNode(node);
QSSGRenderGeometry *geometry = static_cast<QSSGRenderGeometry *>(node);
geometry->clear();
GeometryBase::doUpdateGeometry();
QByteArray vertexData;
QByteArray indexData;
QVector3D minBounds;
QVector3D maxBounds;
fillVertexData(vertexData, indexData, minBounds, maxBounds);
geometry->setStride(12);
#if QT_VERSION < QT_VERSION_CHECK(6, 1, 0)
geometry->addAttribute(QSSGRenderGeometry::Attribute::PositionSemantic, 0,
QSSGRenderGeometry::Attribute::ComponentType::F32Type);
geometry->addAttribute(QSSGRenderGeometry::Attribute::IndexSemantic, 0,
QSSGRenderGeometry::Attribute::ComponentType::U16Type);
geometry->setPrimitiveType(QSSGRenderGeometry::Lines);
#else
geometry->addAttribute(QSSGMesh::RuntimeMeshData::Attribute::PositionSemantic, 0,
QSSGMesh::Mesh::ComponentType::Float32);
geometry->addAttribute(QSSGMesh::RuntimeMeshData::Attribute::IndexSemantic, 0,
QSSGMesh::Mesh::ComponentType::UnsignedInt16);
geometry->setPrimitiveType(QSSGMesh::Mesh::DrawMode::Lines);
#endif
geometry->setVertexData(vertexData);
geometry->setIndexData(indexData);
geometry->setBounds(minBounds, maxBounds);
addAttribute(QQuick3DGeometry::Attribute::IndexSemantic, 0,
QQuick3DGeometry::Attribute::U16Type);
return node;
setVertexData(vertexData);
setIndexData(indexData);
setBounds(minBounds, maxBounds);
}
void LightGeometry::fillVertexData(QByteArray &vertexData, QByteArray &indexData,
@@ -27,27 +27,16 @@
#ifdef QUICK3D_MODULE
#include <QtQuick3D/private/qquick3dgeometry_p.h>
#include "geometrybase.h"
namespace QmlDesigner {
namespace Internal {
class LightGeometry : public QQuick3DGeometry
class LightGeometry : public GeometryBase
{
Q_OBJECT
Q_PROPERTY(LightType lightType READ lightType WRITE setLightType NOTIFY lightTypeChanged)
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
// Name property was removed in Qt 6, so define it here for compatibility.
// Name maps to object name.
Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
public:
QString name() const;
void setName(const QString &name);
signals:
void nameChanged();
#endif
public:
enum class LightType {
Invalid,
@@ -70,7 +59,7 @@ signals:
void lightTypeChanged();
protected:
QSSGRenderGraphObject *updateSpatialNode(QSSGRenderGraphObject *node) override;
void doUpdateGeometry() override;
private:
void fillVertexData(QByteArray &vertexData, QByteArray &indexData,
@@ -27,13 +27,11 @@
#include "linegeometry.h"
#include <QtQuick3DRuntimeRender/private/qssgrendergeometry_p.h>
namespace QmlDesigner {
namespace Internal {
LineGeometry::LineGeometry()
: QQuick3DGeometry()
: GeometryBase()
{
}
@@ -41,19 +39,6 @@ LineGeometry::~LineGeometry()
{
}
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
QString LineGeometry::name() const
{
return objectName();
}
void LineGeometry::setName(const QString &name)
{
setObjectName(name);
emit nameChanged();
}
#endif
QVector3D LineGeometry::startPos() const
{
return m_startPos;
@@ -69,7 +54,7 @@ void LineGeometry::setStartPos(const QVector3D &pos)
if (pos != m_startPos) {
m_startPos = pos;
emit startPosChanged();
update();
updateGeometry();
}
}
@@ -78,16 +63,13 @@ void LineGeometry::setEndPos(const QVector3D &pos)
if (pos != m_endPos) {
m_endPos = pos;
emit endPosChanged();
update();
updateGeometry();
}
}
QSSGRenderGraphObject *LineGeometry::updateSpatialNode(QSSGRenderGraphObject *node)
void LineGeometry::doUpdateGeometry()
{
setStride(12); // Silence a warning
node = QQuick3DGeometry::updateSpatialNode(node);
QSSGRenderGeometry *geometry = static_cast<QSSGRenderGeometry *>(node);
geometry->clear();
GeometryBase::doUpdateGeometry();
QByteArray vertexData;
vertexData.resize(2 * 3 * 4); // 2 vertices of 3 floats each 4 bytes
@@ -100,20 +82,8 @@ QSSGRenderGraphObject *LineGeometry::updateSpatialNode(QSSGRenderGraphObject *no
dataPtr[4] = m_endPos[1];
dataPtr[5] = m_endPos[2];
geometry->setStride(12);
#if QT_VERSION < QT_VERSION_CHECK(6, 1, 0)
geometry->addAttribute(QSSGRenderGeometry::Attribute::PositionSemantic, 0,
QSSGRenderGeometry::Attribute::ComponentType::F32Type);
geometry->setPrimitiveType(QSSGRenderGeometry::Lines);
#else
geometry->addAttribute(QSSGMesh::RuntimeMeshData::Attribute::PositionSemantic, 0,
QSSGMesh::Mesh::ComponentType::Float32);
geometry->setPrimitiveType(QSSGMesh::Mesh::DrawMode::Lines);
#endif
geometry->setVertexData(vertexData);
geometry->setBounds(m_startPos, m_endPos);
return node;
setVertexData(vertexData);
setBounds(m_startPos, m_endPos);
}
}
@@ -27,29 +27,19 @@
#ifdef QUICK3D_MODULE
#include <QtQuick3D/private/qquick3dgeometry_p.h>
#include "geometrybase.h"
#include <QtGui/QVector3D>
namespace QmlDesigner {
namespace Internal {
class LineGeometry : public QQuick3DGeometry
class LineGeometry : public GeometryBase
{
Q_OBJECT
Q_PROPERTY(QVector3D startPos READ startPos WRITE setStartPos NOTIFY startPosChanged)
Q_PROPERTY(QVector3D endPos READ endPos WRITE setEndPos NOTIFY endPosChanged)
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
// Name property was removed in Qt 6, so define it here for compatibility.
// Name maps to object name.
Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
public:
QString name() const;
void setName(const QString &name);
signals:
void nameChanged();
#endif
public:
LineGeometry();
~LineGeometry() override;
@@ -66,7 +56,7 @@ signals:
void endPosChanged();
protected:
QSSGRenderGraphObject *updateSpatialNode(QSSGRenderGraphObject *node) override;
void doUpdateGeometry() override;
private:
QVector3D m_startPos;
@@ -27,7 +27,6 @@
#include "selectionboxgeometry.h"
#include <QtQuick3DRuntimeRender/private/qssgrendergeometry_p.h>
#include <QtQuick3DRuntimeRender/private/qssgrendermodel_p.h>
#include <QtQuick3DRuntimeRender/private/qssgrendercontextcore_p.h>
#include <QtQuick3DRuntimeRender/private/qssgrenderbuffermanager_p.h>
@@ -36,7 +35,6 @@
#include <QtQuick3D/qquick3dobject.h>
#include <QtQuick/qquickwindow.h>
#include <QtCore/qvector.h>
#include <QtCore/qtimer.h>
#include <limits>
@@ -49,7 +47,7 @@ static const QVector3D maxVec = QVector3D(floatMax, floatMax, floatMax);
static const QVector3D minVec = QVector3D(floatMin, floatMin, floatMin);
SelectionBoxGeometry::SelectionBoxGeometry()
: QQuick3DGeometry()
: GeometryBase()
{
}
@@ -60,19 +58,6 @@ SelectionBoxGeometry::~SelectionBoxGeometry()
m_connections.clear();
}
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
QString SelectionBoxGeometry::name() const
{
return objectName();
}
void SelectionBoxGeometry::setName(const QString &name)
{
setObjectName(name);
emit nameChanged();
}
#endif
QQuick3DNode *SelectionBoxGeometry::targetNode() const
{
return m_targetNode;
@@ -93,11 +78,26 @@ bool QmlDesigner::Internal::SelectionBoxGeometry::isEmpty() const
return m_isEmpty;
}
void SelectionBoxGeometry::setEmpty(bool isEmpty)
{
if (m_isEmpty != isEmpty) {
m_isEmpty = isEmpty;
emit isEmptyChanged();
}
}
QSSGBounds3 SelectionBoxGeometry::bounds() const
{
return m_bounds;
}
void SelectionBoxGeometry::clearGeometry()
{
clear();
setStride(12); // To avoid div by zero inside QtQuick3D
setEmpty(true);
}
void SelectionBoxGeometry::setTargetNode(QQuick3DNode *targetNode)
{
if (m_targetNode == targetNode)
@@ -109,17 +109,18 @@ void SelectionBoxGeometry::setTargetNode(QQuick3DNode *targetNode)
if (auto model = qobject_cast<QQuick3DModel *>(m_targetNode)) {
QObject::connect(model, &QQuick3DModel::sourceChanged,
this, &SelectionBoxGeometry::targetMeshUpdated, Qt::QueuedConnection);
this, &SelectionBoxGeometry::spatialNodeUpdateNeeded, Qt::QueuedConnection);
QObject::connect(model, &QQuick3DModel::geometryChanged,
this, &SelectionBoxGeometry::targetMeshUpdated, Qt::QueuedConnection);
this, &SelectionBoxGeometry::spatialNodeUpdateNeeded, Qt::QueuedConnection);
}
if (m_targetNode) {
QObject::connect(m_targetNode, &QQuick3DNode::parentChanged,
this, &SelectionBoxGeometry::update, Qt::QueuedConnection);
this, &SelectionBoxGeometry::spatialNodeUpdateNeeded, Qt::QueuedConnection);
}
clearGeometry();
emit targetNodeChanged();
update();
spatialNodeUpdateNeeded();
}
void SelectionBoxGeometry::setRootNode(QQuick3DNode *rootNode)
@@ -130,7 +131,7 @@ void SelectionBoxGeometry::setRootNode(QQuick3DNode *rootNode)
m_rootNode = rootNode;
emit rootNodeChanged();
update();
spatialNodeUpdateNeeded();
}
void SelectionBoxGeometry::setView3D(QQuick3DViewport *view)
@@ -141,24 +142,31 @@ void SelectionBoxGeometry::setView3D(QQuick3DViewport *view)
m_view3D = view;
emit view3DChanged();
update();
spatialNodeUpdateNeeded();
}
QSSGRenderGraphObject *SelectionBoxGeometry::updateSpatialNode(QSSGRenderGraphObject *node)
{
// If target node mesh has been updated, we need to defer updating the box geometry
// to the next frame to ensure target node geometry has been updated
if (m_meshUpdatePending) {
QTimer::singleShot(0, this, &SelectionBoxGeometry::update);
m_meshUpdatePending = false;
return node;
if (m_spatialNodeUpdatePending) {
m_spatialNodeUpdatePending = false;
updateGeometry();
}
setStride(12); // Silence a warning
node = QQuick3DGeometry::updateSpatialNode(node);
QSSGRenderGeometry *geometry = static_cast<QSSGRenderGeometry *>(node);
return QQuick3DGeometry::updateSpatialNode(node);
}
void SelectionBoxGeometry::doUpdateGeometry()
{
// Some changes require a frame to be rendered for us to be able to calculate geometry,
// so defer calculations until after next frame.
if (m_spatialNodeUpdatePending) {
update();
return;
}
GeometryBase::doUpdateGeometry();
geometry->clear();
for (auto &connection : qAsConst(m_connections))
QObject::disconnect(connection);
m_connections.clear();
@@ -186,15 +194,10 @@ QSSGRenderGraphObject *SelectionBoxGeometry::updateSpatialNode(QSSGRenderGraphOb
rootRN->localTransform = m;
rootRN->markDirty(QSSGRenderNode::TransformDirtyFlag::TransformNotDirty);
rootRN->calculateGlobalVariables();
m_spatialNodeUpdatePending = false;
} else if (!m_spatialNodeUpdatePending) {
// Necessary spatial nodes do not yet exist. Defer selection box creation one frame.
m_spatialNodeUpdatePending = true;
// A necessary spatial node doesn't yet exist. Defer selection box creation one frame.
// Note: We don't share pending flag with target mesh update, which is checked and
// cleared at the beginning of this method, as there would be potential for an endless
// loop in case we can't ever resolve one of the spatial nodes.
QTimer::singleShot(0, this, &SelectionBoxGeometry::update);
return node;
update();
}
getBounds(m_targetNode, vertexData, indexData, minBounds, maxBounds);
appendVertexData(QMatrix4x4(), vertexData, indexData, minBounds, maxBounds);
@@ -212,34 +215,15 @@ QSSGRenderGraphObject *SelectionBoxGeometry::updateSpatialNode(QSSGRenderGraphOb
appendVertexData(QMatrix4x4(), vertexData, indexData, minBounds, maxBounds);
}
geometry->setStride(12);
#if QT_VERSION < QT_VERSION_CHECK(6, 1, 0)
geometry->addAttribute(QSSGRenderGeometry::Attribute::PositionSemantic, 0,
QSSGRenderGeometry::Attribute::ComponentType::F32Type);
geometry->addAttribute(QSSGRenderGeometry::Attribute::IndexSemantic, 0,
QSSGRenderGeometry::Attribute::ComponentType::U16Type);
geometry->setPrimitiveType(QSSGRenderGeometry::Lines);
#else
geometry->addAttribute(QSSGMesh::RuntimeMeshData::Attribute::PositionSemantic, 0,
QSSGMesh::Mesh::ComponentType::Float32);
geometry->addAttribute(QSSGMesh::RuntimeMeshData::Attribute::IndexSemantic, 0,
QSSGMesh::Mesh::ComponentType::UnsignedInt16);
geometry->setPrimitiveType(QSSGMesh::Mesh::DrawMode::Lines);
#endif
geometry->setVertexData(vertexData);
geometry->setIndexData(indexData);
geometry->setBounds(minBounds, maxBounds);
addAttribute(QQuick3DGeometry::Attribute::IndexSemantic, 0,
QQuick3DGeometry::Attribute::U16Type);
setVertexData(vertexData);
setIndexData(indexData);
setBounds(minBounds, maxBounds);
m_bounds = QSSGBounds3(minBounds, maxBounds);
bool empty = minBounds.isNull() && maxBounds.isNull();
if (m_isEmpty != empty) {
m_isEmpty = empty;
// Delay notification until we're done with spatial node updates
QTimer::singleShot(0, this, &SelectionBoxGeometry::isEmptyChanged);
}
return node;
setEmpty(minBounds.isNull() && maxBounds.isNull());
}
void SelectionBoxGeometry::getBounds(
@@ -405,18 +389,19 @@ void SelectionBoxGeometry::appendVertexData(const QMatrix4x4 &m, QByteArray &ver
void SelectionBoxGeometry::trackNodeChanges(QQuick3DNode *node)
{
m_connections << QObject::connect(node, &QQuick3DNode::sceneScaleChanged,
this, &SelectionBoxGeometry::update, Qt::QueuedConnection);
this, &SelectionBoxGeometry::updateGeometry, Qt::QueuedConnection);
m_connections << QObject::connect(node, &QQuick3DNode::sceneRotationChanged,
this, &SelectionBoxGeometry::update, Qt::QueuedConnection);
this, &SelectionBoxGeometry::updateGeometry, Qt::QueuedConnection);
m_connections << QObject::connect(node, &QQuick3DNode::scenePositionChanged,
this, &SelectionBoxGeometry::update, Qt::QueuedConnection);
this, &SelectionBoxGeometry::updateGeometry, Qt::QueuedConnection);
m_connections << QObject::connect(node, &QQuick3DNode::pivotChanged,
this, &SelectionBoxGeometry::update, Qt::QueuedConnection);
this, &SelectionBoxGeometry::updateGeometry, Qt::QueuedConnection);
}
void SelectionBoxGeometry::targetMeshUpdated()
void SelectionBoxGeometry::spatialNodeUpdateNeeded()
{
m_meshUpdatePending = true;
m_spatialNodeUpdatePending = true;
clearGeometry();
update();
}
@@ -27,15 +27,16 @@
#ifdef QUICK3D_MODULE
#include "geometrybase.h"
#include <QtQuick3D/private/qquick3dnode_p.h>
#include <QtQuick3D/private/qquick3dgeometry_p.h>
#include <QtQuick3D/private/qquick3dviewport_p.h>
#include <QtQuick3DUtils/private/qssgbounds3_p.h>
namespace QmlDesigner {
namespace Internal {
class SelectionBoxGeometry : public QQuick3DGeometry
class SelectionBoxGeometry : public GeometryBase
{
Q_OBJECT
Q_PROPERTY(QQuick3DNode *targetNode READ targetNode WRITE setTargetNode NOTIFY targetNodeChanged)
@@ -43,17 +44,6 @@ class SelectionBoxGeometry : public QQuick3DGeometry
Q_PROPERTY(QQuick3DViewport *view3D READ view3D WRITE setView3D NOTIFY view3DChanged)
Q_PROPERTY(bool isEmpty READ isEmpty NOTIFY isEmptyChanged)
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
// Name property was removed in Qt 6, so define it here for compatibility.
// Name maps to object name.
Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
public:
QString name() const;
void setName(const QString &name);
signals:
void nameChanged();
#endif
public:
SelectionBoxGeometry();
~SelectionBoxGeometry() override;
@@ -62,6 +52,7 @@ public:
QQuick3DNode *rootNode() const;
QQuick3DViewport *view3D() const;
bool isEmpty() const;
void setEmpty(bool isEmpty);
QSSGBounds3 bounds() const;
@@ -78,6 +69,7 @@ signals:
protected:
QSSGRenderGraphObject *updateSpatialNode(QSSGRenderGraphObject *node) override;
void doUpdateGeometry() override;
private:
void getBounds(QQuick3DNode *node, QByteArray &vertexData,
@@ -85,7 +77,8 @@ private:
void appendVertexData(const QMatrix4x4 &m, QByteArray &vertexData, QByteArray &indexData,
const QVector3D &minBounds, const QVector3D &maxBounds);
void trackNodeChanges(QQuick3DNode *node);
void targetMeshUpdated();
void spatialNodeUpdateNeeded();
void clearGeometry();
QQuick3DNode *m_targetNode = nullptr;
QQuick3DViewport *m_view3D = nullptr;
@@ -94,7 +87,6 @@ private:
QVector<QMetaObject::Connection> m_connections;
QSSGBounds3 m_bounds;
bool m_spatialNodeUpdatePending = false;
bool m_meshUpdatePending = false;
};
}
@@ -373,6 +373,8 @@ void Qt5InformationNodeInstanceServer::createEditView3D()
#ifdef QUICK3D_MODULE
qmlRegisterRevision<QQuick3DNode, 1>("MouseArea3D", 1, 0);
qmlRegisterType<QmlDesigner::Internal::MouseArea3D>("MouseArea3D", 1, 0, "MouseArea3D");
qmlRegisterUncreatableType<QmlDesigner::Internal::GeometryBase>("GeometryBase", 1, 0, "GeometryBase",
"Abstract Base Class");
qmlRegisterType<QmlDesigner::Internal::CameraGeometry>("CameraGeometry", 1, 0, "CameraGeometry");
qmlRegisterType<QmlDesigner::Internal::LightGeometry>("LightUtils", 1, 0, "LightGeometry");
qmlRegisterType<QmlDesigner::Internal::GridGeometry>("GridGeometry", 1, 0, "GridGeometry");
+1
View File
@@ -129,6 +129,7 @@ extend_qtc_executable(qml2puppet
SOURCES
generalhelper.cpp generalhelper.h
mousearea3d.cpp mousearea3d.h
geometrybase.cpp geometrybase.h
camerageometry.cpp camerageometry.h
lightgeometry.cpp lightgeometry.h
gridgeometry.cpp gridgeometry.h
+2
View File
@@ -232,6 +232,7 @@ QtcTool {
"instances/capturenodeinstanceserverdispatcher.h",
"editor3d/generalhelper.cpp",
"editor3d/mousearea3d.cpp",
"editor3d/geometrybase.cpp",
"editor3d/camerageometry.cpp",
"editor3d/lightgeometry.cpp",
"editor3d/gridgeometry.cpp",
@@ -249,6 +250,7 @@ QtcTool {
Group {
name: "3d-only puppet2 headers"
files: [
"editor3d/geometrybase.h",
"editor3d/camerageometry.h",
"editor3d/generalhelper.h",
"editor3d/gridgeometry.h",