diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/camerageometry.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/camerageometry.cpp index 0e654d7fc78..9c81fdc9703 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/camerageometry.cpp +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/camerageometry.cpp @@ -35,6 +35,7 @@ #include #include #include +#include #include @@ -70,31 +71,31 @@ void CameraGeometry::setCamera(QQuick3DCamera *camera) m_camera = camera; if (auto perspectiveCamera = qobject_cast(m_camera)) { QObject::connect(perspectiveCamera, &QQuick3DPerspectiveCamera::clipNearChanged, - this, &CameraGeometry::update); + this, &CameraGeometry::handleCameraPropertyChange); QObject::connect(perspectiveCamera, &QQuick3DPerspectiveCamera::clipFarChanged, - this, &CameraGeometry::update); + this, &CameraGeometry::handleCameraPropertyChange); QObject::connect(perspectiveCamera, &QQuick3DPerspectiveCamera::fieldOfViewChanged, - this, &CameraGeometry::update); + this, &CameraGeometry::handleCameraPropertyChange); QObject::connect(perspectiveCamera, &QQuick3DPerspectiveCamera::fieldOfViewOrientationChanged, - this, &CameraGeometry::update); + this, &CameraGeometry::handleCameraPropertyChange); if (auto frustumCamera = qobject_cast(m_camera)) { QObject::connect(frustumCamera, &QQuick3DFrustumCamera::topChanged, - this, &CameraGeometry::update); + this, &CameraGeometry::handleCameraPropertyChange); QObject::connect(frustumCamera, &QQuick3DFrustumCamera::bottomChanged, - this, &CameraGeometry::update); + this, &CameraGeometry::handleCameraPropertyChange); QObject::connect(frustumCamera, &QQuick3DFrustumCamera::rightChanged, - this, &CameraGeometry::update); + this, &CameraGeometry::handleCameraPropertyChange); QObject::connect(frustumCamera, &QQuick3DFrustumCamera::leftChanged, - this, &CameraGeometry::update); + this, &CameraGeometry::handleCameraPropertyChange); } } else if (auto orthoCamera = qobject_cast(m_camera)) { QObject::connect(orthoCamera, &QQuick3DOrthographicCamera::clipNearChanged, - this, &CameraGeometry::update); + this, &CameraGeometry::handleCameraPropertyChange); QObject::connect(orthoCamera, &QQuick3DOrthographicCamera::clipFarChanged, - this, &CameraGeometry::update); + this, &CameraGeometry::handleCameraPropertyChange); } else if (auto customCamera = qobject_cast(m_camera)) { QObject::connect(customCamera, &QQuick3DCustomCamera::projectionChanged, - this, &CameraGeometry::update); + this, &CameraGeometry::handleCameraPropertyChange); } emit cameraChanged(); update(); @@ -110,48 +111,28 @@ void CameraGeometry::setViewPortRect(const QRectF &rect) update(); } +void CameraGeometry::handleCameraPropertyChange() +{ + m_cameraUpdatePending = true; + update(); +} + QSSGRenderGraphObject *CameraGeometry::updateSpatialNode(QSSGRenderGraphObject *node) { if (!m_camera) return node; + // 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; + } + if (!m_camera->cameraNode()) { -#if QT_VERSION <= QT_VERSION_CHECK(5, 14, 1) - // 5.14.1 doesn't yet have function to force camera node creation, so we must do it - // the hard way - auto camera = new QSSGRenderCamera(); - bool changed = false; - if (auto perspCamera = qobject_cast(m_camera)) { - changed |= qUpdateIfNeeded(camera->clipNear, perspCamera->clipNear()); - changed |= qUpdateIfNeeded(camera->clipFar, perspCamera->clipFar()); - changed |= qUpdateIfNeeded(camera->fov, qDegreesToRadians(perspCamera->fieldOfView())); - changed |= qUpdateIfNeeded(camera->fovHorizontal, perspCamera->fieldOfViewOrientation() - == QQuick3DCamera::FieldOfViewOrientation::Horizontal); - changed |= qUpdateIfNeeded(camera->enableFrustumClipping, perspCamera->frustumCullingEnabled()); - if (auto frustCamera = qobject_cast(m_camera)) { - camera->flags.setFlag(QSSGRenderNode::Flag::CameraFrustumProjection, true); - changed |= qUpdateIfNeeded(camera->top, frustCamera->top()); - changed |= qUpdateIfNeeded(camera->bottom, frustCamera->bottom()); - changed |= qUpdateIfNeeded(camera->right, frustCamera->right()); - changed |= qUpdateIfNeeded(camera->left, frustCamera->left()); - } - } else if (auto orthoCamera = qobject_cast(m_camera)) { - camera->flags.setFlag(QSSGRenderNode::Flag::Orthographic, true); - changed |= qUpdateIfNeeded(camera->clipNear, orthoCamera->clipNear()); - changed |= qUpdateIfNeeded(camera->clipFar, orthoCamera->clipFar()); - changed |= qUpdateIfNeeded(camera->enableFrustumClipping, orthoCamera->frustumCullingEnabled()); - } else if (auto customCamera = qobject_cast(m_camera)) { - camera->flags.setFlag(QSSGRenderNode::Flag::CameraCustomProjection, true); - changed |= qUpdateIfNeeded(camera->projection, customCamera->projection()); - changed |= qUpdateIfNeeded(camera->enableFrustumClipping, customCamera->frustumCullingEnabled()); - } - if (changed) - camera->flags.setFlag(QSSGRenderNode::Flag::CameraDirty); - m_camera->setCameraNode(camera); -#else // Doing explicit viewport mapping forces cameraNode creation m_camera->mapToViewport({}, m_viewPortRect.width(), m_viewPortRect.height()); -#endif } node = QQuick3DGeometry::updateSpatialNode(node); diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/camerageometry.h b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/camerageometry.h index 9c0f5e1e3c4..73722cd7a1f 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/camerageometry.h +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/camerageometry.h @@ -49,6 +49,7 @@ public: public Q_SLOTS: void setCamera(QQuick3DCamera *camera); void setViewPortRect(const QRectF &rect); + void handleCameraPropertyChange(); Q_SIGNALS: void cameraChanged(); @@ -62,6 +63,7 @@ private: QVector3D &minBounds, QVector3D &maxBounds); QQuick3DCamera *m_camera = nullptr; QRectF m_viewPortRect; + bool m_cameraUpdatePending = false; }; }