From 340f1ce19afc73a6232b870121ac3782c3134bbd Mon Sep 17 00:00:00 2001 From: Ali Kianian Date: Fri, 30 Aug 2024 16:23:19 +0300 Subject: [PATCH] QmlDesigner: Don't display the camera, if it has no scene Fixes: QDS-13490 Change-Id: I82bf07866f667dd39773f7e5e172ebd36c36e46e Reviewed-by: Mahmoud Badri --- src/tools/qml2puppet/editor3d_qt6.qrc | 1 + .../mockfiles/qt6/CameraDisplay.qml | 82 ++++++++++ .../qml2puppet/mockfiles/qt6/CameraView.qml | 149 +++++++----------- .../qml2puppet/editor3d/generalhelper.cpp | 14 ++ .../qml2puppet/editor3d/generalhelper.h | 1 + 5 files changed, 156 insertions(+), 91 deletions(-) create mode 100644 src/tools/qml2puppet/mockfiles/qt6/CameraDisplay.qml diff --git a/src/tools/qml2puppet/editor3d_qt6.qrc b/src/tools/qml2puppet/editor3d_qt6.qrc index e1de7a0903d..e75e671e7e0 100644 --- a/src/tools/qml2puppet/editor3d_qt6.qrc +++ b/src/tools/qml2puppet/editor3d_qt6.qrc @@ -24,6 +24,7 @@ mockfiles/qt6/AdjustableArrow.qml mockfiles/qt6/Arrow.qml mockfiles/qt6/AutoScaleHelper.qml + mockfiles/qt6/CameraDisplay.qml mockfiles/qt6/CameraFrustum.qml mockfiles/qt6/CameraGizmo.qml mockfiles/qt6/CameraView.qml diff --git a/src/tools/qml2puppet/mockfiles/qt6/CameraDisplay.qml b/src/tools/qml2puppet/mockfiles/qt6/CameraDisplay.qml new file mode 100644 index 00000000000..f1eb741c7a9 --- /dev/null +++ b/src/tools/qml2puppet/mockfiles/qt6/CameraDisplay.qml @@ -0,0 +1,82 @@ +// Copyright (C) 2024 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +import QtQuick +import QtQuick3D + +Item { + id: cameraDisplay + + required property Camera camera + required property size preferredSize + required property size viewPortSize + required property var activeScene + required property var activeSceneEnvironment + + implicitWidth: view3D.dispSize.width + implicitHeight: view3D.dispSize.height + clip: true + + View3D { + id: view3D + + readonly property bool isOrthographicCamera: _generalHelper.isOrthographicCamera(view3D.camera) + property size dispSize: calculateSize(cameraDisplay.viewPortSize, cameraDisplay.preferredSize) + readonly property real magnificationFactor: cameraDisplay.viewPortSize.width === 0 + ? 1.0 + : (view3D.dispSize.width / cameraDisplay.viewPortSize.width) + + transformOrigin: Item.Center + anchors.centerIn: parent + + camera: cameraDisplay.camera + importScene: cameraDisplay.activeScene + environment: cameraDisplay.activeSceneEnvironment ?? defaultSceneEnvironment + + function calculateSize(viewPortSize: size, preferredSize : size) { + if (_generalHelper.fuzzyCompare(viewPortSize.width, 0) + || _generalHelper.fuzzyCompare(viewPortSize.height, 0)) { + return Qt.size(0, 0) + } + + let aspectRatio = viewPortSize.height / viewPortSize.width + var calculatedHeight = preferredSize.width * aspectRatio + if (calculatedHeight <= preferredSize.height) + return Qt.size(preferredSize.width, calculatedHeight) + + var calculatedWidth = preferredSize.height / aspectRatio; + return Qt.size(calculatedWidth, preferredSize.height); + } + } + + SceneEnvironment { + id: defaultSceneEnvironment + + antialiasingMode: SceneEnvironment.MSAA + antialiasingQuality: SceneEnvironment.High + } + + states: [ + State { + name: "orthoCamera" + when: view3D.isOrthographicCamera + PropertyChanges { + target: view3D + + width: cameraDisplay.viewPortSize.width + height: cameraDisplay.viewPortSize.height + scale: view3D.magnificationFactor + } + }, + State { + name: "nonOrthoCamera" + when: !view3D.isOrthographicCamera + PropertyChanges { + target: view3D + + width: view3D.dispSize.width + height: view3D.dispSize.height + scale: 1.0 + } + } + ] +} diff --git a/src/tools/qml2puppet/mockfiles/qt6/CameraView.qml b/src/tools/qml2puppet/mockfiles/qt6/CameraView.qml index 3bc67468099..fe886a71d68 100644 --- a/src/tools/qml2puppet/mockfiles/qt6/CameraView.qml +++ b/src/tools/qml2puppet/mockfiles/qt6/CameraView.qml @@ -3,7 +3,7 @@ import QtQuick import QtQuick3D -Item { +Rectangle { id: cameraView required property bool showCameraView @@ -16,44 +16,57 @@ Item { property var activeSceneEnvironment property var preferredCamera - width: loader.width - height: loader.height + width: priv.loaderSize.width + 2 + height: priv.loaderSize.height + 2 + anchors.bottom: parent.bottom anchors.margins: 10 - visible: loader.active - onTargetNodeChanged: loader.updateCamera() - onAlwaysOnChanged: loader.updateCamera() - onPreferredCameraChanged: loader.updateCamera() + visible: priv.cameraViewIsOn + + onTargetNodeChanged: priv.updateCamera() + onAlwaysOnChanged: priv.updateCamera() + onPreferredCameraChanged: priv.updateCamera() onActiveSceneChanged: forceReload() - Component.onCompleted: loader.updateCamera() + Component.onCompleted: priv.updateCamera() + + border.width: 1 + border.color: "lightslategray" + color: "black" function forceReload() { - loader.forceDeactive = true - loader.oldCamera = null - loader.updateCamera() - loader.forceDeactive = false + priv.forceDeactive = true + priv.oldCamera = null + priv.updateCamera() + priv.forceDeactive = false } - Loader { - id: loader + QtObject { + id: priv property Camera camera property Camera oldCamera + property bool view3dRootNodeExists property bool forceDeactive: false - - active: !forceDeactive && (cameraView.alwaysOn || cameraView.showCameraView) && loader.camera + readonly property bool cameraViewIsOn: !forceDeactive && (cameraView.alwaysOn || cameraView.showCameraView) && priv.camera + readonly property bool cameraHasValidScene: priv.cameraViewIsOn && priv.view3dRootNodeExists + property Loader activeLoader + readonly property size loaderSize: activeLoader && activeLoader.active + ? Qt.size(activeLoader.width, activeLoader.height) + : Qt.size(-2, -2) function updateCamera() { - loader.camera = activeCamera() + let activeCam = activeCamera() + priv.camera = activeCam + priv.view3dRootNodeExists = _generalHelper.view3dRootNode(activeCam) } function activeCamera() { if (cameraView.alwaysOn) { if (_generalHelper.isCamera(cameraView.targetNode)) return cameraView.targetNode - else if (loader.oldCamera) - return loader.oldCamera + else if (priv.oldCamera) + return priv.oldCamera else return cameraView.preferredCamera } else if (_generalHelper.isCamera(cameraView.targetNode)) { @@ -63,82 +76,36 @@ Item { } onCameraChanged: { - if (loader.camera) - loader.oldCamera = loader.camera - } - - sourceComponent: Rectangle { - id: cameraRect - - implicitWidth: view3D.dispSize.width + 2 - implicitHeight: view3D.dispSize.height + 2 - border.width: 1 - border.color: "lightslategray" - color: "black" - - View3D { - id: view3D - - readonly property bool isOrthographicCamera: _generalHelper.isOrthographicCamera(view3D.camera) - property size dispSize: calculateSize(cameraView.viewPortSize, cameraView.preferredSize) - readonly property real magnificationFactor: cameraView.viewPortSize.width === 0 - ? 1.0 - : (view3D.dispSize.width / cameraView.viewPortSize.width) - - transformOrigin: Item.Center - anchors.centerIn: parent - - camera: loader.camera - importScene: cameraView.activeScene - environment: cameraView.activeSceneEnvironment ?? defaultSceneEnvironment - - function calculateSize(viewPortSize: size, preferredSize : size){ - if (_generalHelper.fuzzyCompare(viewPortSize.width, 0) - || _generalHelper.fuzzyCompare(viewPortSize.height, 0)) - return Qt.size(0, 0) - - let aspectRatio = viewPortSize.height / viewPortSize.width - var calculatedHeight = preferredSize.width * aspectRatio - if (calculatedHeight <= preferredSize.height) - return Qt.size(preferredSize.width, calculatedHeight) - - var calculatedWidth = preferredSize.height / aspectRatio; - return Qt.size(calculatedWidth, preferredSize.height); - } - - states: [ - State { - name: "orthoCamera" - when: view3D.isOrthographicCamera - PropertyChanges { - target: view3D - - width: cameraView.viewPortSize.width - height: cameraView.viewPortSize.height - scale: view3D.magnificationFactor - } - }, - State { - name: "nonOrthoCamera" - when: !view3D.isOrthographicCamera - PropertyChanges { - target: view3D - - width: view3D.dispSize.width - height: view3D.dispSize.height - scale: 1.0 - } - } - ] - } + if (priv.camera) + priv.oldCamera = priv.camera } } - SceneEnvironment { - id: defaultSceneEnvironment + Loader { + id: cameraLoader - antialiasingMode: SceneEnvironment.MSAA - antialiasingQuality: SceneEnvironment.High + active: priv.cameraViewIsOn && priv.cameraHasValidScene + onLoaded: priv.activeLoader = this + sourceComponent: CameraDisplay { + camera: priv.camera + preferredSize: cameraView.preferredSize + viewPortSize: cameraView.viewPortSize + activeScene: cameraView.activeScene + activeSceneEnvironment: cameraView.activeSceneEnvironment + } + } + + Loader { + id: errorLoader + + active: priv.cameraViewIsOn && !priv.cameraHasValidScene + onLoaded: priv.activeLoader = this + sourceComponent: Text { + font.pixelSize: 14 + color: "yellow" + text: qsTr("Camera does not have a valid view") + padding: 10 + } } states: [ diff --git a/src/tools/qml2puppet/qml2puppet/editor3d/generalhelper.cpp b/src/tools/qml2puppet/qml2puppet/editor3d/generalhelper.cpp index e58192e54f8..9392787e4c6 100644 --- a/src/tools/qml2puppet/qml2puppet/editor3d/generalhelper.cpp +++ b/src/tools/qml2puppet/qml2puppet/editor3d/generalhelper.cpp @@ -692,6 +692,20 @@ bool GeneralHelper::isOrthographicCamera(QQuick3DNode *node) const return node && qobject_cast(node); } +QQuick3DNode *GeneralHelper::view3dRootNode(QQuick3DNode *node) const +{ + if (!node) + return nullptr; + + QQuick3DNode *parentNode = node->parentNode(); + while (parentNode) { + if (parentNode->inherits("QQuick3DSceneRootNode")) + return parentNode; + parentNode = parentNode->parentNode(); + } + return nullptr; +} + // Emitter gizmo model creation is done in C++ as creating dynamic properties and // assigning materials to dynamically created models is lot simpler in C++ QQuick3DNode *GeneralHelper::createParticleEmitterGizmoModel(QQuick3DNode *emitter, diff --git a/src/tools/qml2puppet/qml2puppet/editor3d/generalhelper.h b/src/tools/qml2puppet/qml2puppet/editor3d/generalhelper.h index 4aa66bd7419..aec9c4970e6 100644 --- a/src/tools/qml2puppet/qml2puppet/editor3d/generalhelper.h +++ b/src/tools/qml2puppet/qml2puppet/editor3d/generalhelper.h @@ -97,6 +97,7 @@ public: Q_INVOKABLE bool isPickable(QQuick3DNode *node) const; Q_INVOKABLE bool isCamera(QQuick3DNode *node) const; Q_INVOKABLE bool isOrthographicCamera(QQuick3DNode *node) const; + Q_INVOKABLE QQuick3DNode *view3dRootNode(QQuick3DNode *node) const; Q_INVOKABLE QQuick3DNode *createParticleEmitterGizmoModel(QQuick3DNode *emitter, QQuick3DMaterial *material) const;