diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/EditCameraController.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/EditCameraController.qml index 20dd112d614..13793699530 100644 --- a/share/qtcreator/qml/qmlpuppet/mockfiles/EditCameraController.qml +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/EditCameraController.qml @@ -46,10 +46,11 @@ Item { readonly property vector3d _defaultCameraPosition: Qt.vector3d(0, 600, 600) readonly property vector3d _defaultCameraRotation: Qt.vector3d(-45, 0, 0) readonly property real _defaultCameraLookAtDistance: _defaultCameraPosition.length() + property bool ignoreToolState: false function restoreCameraState(cameraState) { - if (!camera) + if (!camera || ignoreToolState) return; _lookAtPoint = cameraState[0]; @@ -75,7 +76,7 @@ Item { function storeCameraState(delay) { - if (!camera) + if (!camera || ignoreToolState) return; var cameraState = []; diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/EffectNodeView.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/EffectNodeView.qml index 9259e0d08fd..cb2e5810214 100644 --- a/share/qtcreator/qml/qmlpuppet/mockfiles/EffectNodeView.qml +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/EffectNodeView.qml @@ -57,7 +57,7 @@ View3D { source: "#Sphere" materials: [ DefaultMaterial { - diffuseColor: "green" + diffuseColor: "#4aee45" } ] } diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/IconRenderer3D.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/IconRenderer3D.qml index 99c20047a46..8119c00f34e 100644 --- a/share/qtcreator/qml/qmlpuppet/mockfiles/IconRenderer3D.qml +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/IconRenderer3D.qml @@ -45,7 +45,7 @@ Item { cameraControl.focusObject(selectionBox.model, viewCamera.eulerRotation, true, true); if (cameraControl._zoomFactor < 0.1) view3D.importScene.scale = view3D.importScene.scale.times(10); - if (cameraControl._zoomFactor > 100) + if (cameraControl._zoomFactor > 10) view3D.importScene.scale = view3D.importScene.scale.times(0.1); selectionBox.visible = false; @@ -82,6 +82,7 @@ Item { id: cameraControl camera: view3D.camera view3d: view3D + ignoreToolState: true } } } diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/ModelNode3DImageView.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/ModelNode3DImageView.qml index b0ed2114ea4..44580a0b302 100644 --- a/share/qtcreator/qml/qmlpuppet/mockfiles/ModelNode3DImageView.qml +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/ModelNode3DImageView.qml @@ -36,11 +36,17 @@ Item { property View3D view: null property alias contentItem: contentItem + property var previewObject + property var materialViewComponent property var effectViewComponent + property var modelViewComponent + + property bool ready: false function destroyView() { + previewObject = null; if (view) { // Destroy is async, so make sure we don't get any more updates for the old view _generalHelper.enableItemUpdate(view, false); @@ -57,6 +63,10 @@ Item { createViewForMaterial(obj); else if (obj instanceof Effect) createViewForEffect(obj); + else if (obj instanceof Model) + createViewForModel(obj); + + previewObject = obj; } function createViewForMaterial(material) @@ -79,6 +89,26 @@ Item { view = effectViewComponent.createObject(viewRect, {"previewEffect": effect}); } + function createViewForModel(model) + { + if (!modelViewComponent) + modelViewComponent = Qt.createComponent("ModelNodeView.qml"); + + // Always recreate the view to ensure model is up to date + if (modelViewComponent.status === Component.Ready) + view = modelViewComponent.createObject(viewRect, {"sourceModel": model}); + } + + function afterRender() + { + if (previewObject instanceof Model) { + view.fitModel(); + ready = view.ready; + } else { + ready = true; + } + } + Item { id: contentItem anchors.fill: parent diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/ModelNodeView.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/ModelNodeView.qml new file mode 100644 index 00000000000..1379a27a057 --- /dev/null +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/ModelNodeView.qml @@ -0,0 +1,96 @@ +/**************************************************************************** +** +** Copyright (C) 2020 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. +** +****************************************************************************/ + +import QtQuick 2.15 +import QtQuick3D 1.15 + +View3D { + id: root + anchors.fill: parent + environment: sceneEnv + camera: theCamera + + property bool ready: false + property real prevZoomFactor: -1 + property Model sourceModel + + function fitModel() + { + cameraControl.focusObject(model, theCamera.eulerRotation, true, false); + + if (cameraControl._zoomFactor < 0.1) { + model.scale = model.scale.times(10); + } else if (cameraControl._zoomFactor > 10) { + model.scale = model.scale.times(0.1); + } else { + // We need one more render after zoom factor change, so only set ready when zoom factor + // or scaling hasn't changed from the previous frame + ready = _generalHelper.fuzzyCompare(cameraControl._zoomFactor, prevZoomFactor); + prevZoomFactor = cameraControl._zoomFactor; + } + } + + SceneEnvironment { + id: sceneEnv + antialiasingMode: SceneEnvironment.MSAA + antialiasingQuality: SceneEnvironment.High + } + + EditCameraController { + id: cameraControl + camera: theCamera + anchors.fill: parent + view3d: root + ignoreToolState: true + } + + DirectionalLight { + eulerRotation.x: -30 + eulerRotation.y: -30 + } + + PerspectiveCamera { + id: theCamera + z: 600 + y: 600 + eulerRotation.x: -45 + clipFar: 10000 + clipNear: 1 + } + + Model { + id: model + eulerRotation.y: 45 + + source: sourceModel.source + geometry: sourceModel.geometry + + materials: [ + DefaultMaterial { + diffuseColor: "#4aee45" + } + ] + } +} diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.cpp index ae2f235673f..afa02625d4d 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.cpp +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.cpp @@ -211,6 +211,11 @@ QVector4D GeneralHelper::focusObjectToCamera(QQuick3DCamera *camera, float defau return QVector4D(lookAt, cameraZoomFactor); } +bool GeneralHelper::fuzzyCompare(double a, double b) +{ + return qFuzzyCompare(a, b); +} + void GeneralHelper::delayedPropertySet(QObject *obj, int delay, const QString &property, const QVariant &value) { diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.h b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.h index 5e3adbf16bb..92893cc546a 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.h +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.h @@ -69,6 +69,7 @@ public: QQuick3DNode *targetObject, QQuick3DViewport *viewPort, float oldZoom, bool updateZoom = true, bool closeUp = false); + Q_INVOKABLE bool fuzzyCompare(double a, double b); Q_INVOKABLE void delayedPropertySet(QObject *obj, int delay, const QString &property, const QVariant& value); Q_INVOKABLE QQuick3DNode *resolvePick(QQuick3DNode *pickNode); diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp index 54e36f7420b..05f86ae4d34 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp @@ -541,18 +541,25 @@ void Qt5InformationNodeInstanceServer::doRenderModelNode3DImageView() Q_ARG(QVariant, QVariant::fromValue(renderSize.width())), Q_ARG(QVariant, QVariant::fromValue(renderSize.height()))); - updateNodesRecursive(m_ModelNode3DImageViewContentItem); + QImage renderImage; + bool ready = false; + int count = 0; // Ensure we don't ever get stuck in an infinite loop + while (!ready && ++count < 10) { + updateNodesRecursive(m_ModelNode3DImageViewContentItem); - // Fake render loop signaling to update things like QML items as 3D textures - m_editView3D->beforeSynchronizing(); - m_editView3D->beforeRendering(); + // Fake render loop signaling to update things like QML items as 3D textures + m_ModelNode3DImageView->beforeSynchronizing(); + m_ModelNode3DImageView->beforeRendering(); - QSizeF size = qobject_cast(m_ModelNode3DImageViewContentItem)->size(); - QRectF renderRect(QPointF(0., 0.), size); - QImage renderImage = designerSupport()->renderImageForItem(m_ModelNode3DImageViewContentItem, - renderRect, size.toSize()); - m_editView3D->afterRendering(); + QSizeF size = qobject_cast(m_ModelNode3DImageViewContentItem)->size(); + QRectF renderRect(QPointF(0., 0.), size); + renderImage = designerSupport()->renderImageForItem(m_ModelNode3DImageViewContentItem, + renderRect, size.toSize()); + m_ModelNode3DImageView->afterRendering(); + QMetaObject::invokeMethod(m_ModelNode3DImageViewRootItem, "afterRender"); + ready = QQmlProperty::read(m_ModelNode3DImageViewRootItem, "ready").value(); + } QMetaObject::invokeMethod(m_ModelNode3DImageViewRootItem, "destroyView"); // Key number is selected so that it is unlikely to conflict other ImageContainer use. diff --git a/share/qtcreator/qml/qmlpuppet/qmlpuppet.qrc b/share/qtcreator/qml/qmlpuppet/qmlpuppet.qrc index 02878b81b6e..9b01f0249db 100644 --- a/share/qtcreator/qml/qmlpuppet/qmlpuppet.qrc +++ b/share/qtcreator/qml/qmlpuppet/qmlpuppet.qrc @@ -43,6 +43,7 @@ mockfiles/ModelNode3DImageView.qml mockfiles/MaterialNodeView.qml mockfiles/EffectNodeView.qml + mockfiles/ModelNodeView.qml mockfiles/meshes/arrow.mesh mockfiles/meshes/scalerod.mesh mockfiles/meshes/ring.mesh diff --git a/src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp b/src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp index baa0f6a245d..b7a59274b23 100644 --- a/src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp +++ b/src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp @@ -1412,6 +1412,9 @@ void DesignerActionManager::createDefaultModelNodePreviewImageHandlers() registerModelNodePreviewHandler( ModelNodePreviewImageHandler("QtQuick3D.Material", ModelNodeOperations::previewImageDataFor3DNode)); + registerModelNodePreviewHandler( + ModelNodePreviewImageHandler("QtQuick3D.Model", + ModelNodeOperations::previewImageDataFor3DNode)); // TODO - Disabled until QTBUG-86616 is fixed // registerModelNodePreviewHandler(