diff options
author | Miikka Heikkinen <miikka.heikkinen@qt.io> | 2022-05-16 16:01:16 +0300 |
---|---|---|
committer | Miikka Heikkinen <miikka.heikkinen@qt.io> | 2022-05-27 08:49:14 +0000 |
commit | d92bdcce40d805420ea573a0864582cb5be6f2bb (patch) | |
tree | 7a08a26894992a70d2092a348378326ea8c3c6eb | |
parent | 07d9075d478163fa15b24da424d9948d1d46ae05 (diff) |
QmlDesigner: Show form editor preview for 3D material root nodes
Fixes: QDS-6561
Change-Id: I62a06eb6c83b0a4813a1b20f91b09e17b04a1332
Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Samuel Ghinet <samuel.ghinet@qt.io>
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
16 files changed, 426 insertions, 195 deletions
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/instances.pri b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/instances.pri index d3a81cc370..2d3b4ceedf 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/instances.pri +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/instances.pri @@ -46,7 +46,9 @@ HEADERS += $$PWD/qt5nodeinstanceserver.h \ $$PWD/positionernodeinstance.h \ $$PWD/layoutnodeinstance.h \ $$PWD/qt3dpresentationnodeinstance.h \ + $$PWD/quick3dmaterialnodeinstance.h \ $$PWD/quick3dnodeinstance.h \ + $$PWD/quick3drenderablenodeinstance.h \ $$PWD/quick3dtexturenodeinstance.h \ $$PWD/viewconfig.h \ $$PWD/animationdriver.h @@ -79,7 +81,9 @@ SOURCES += $$PWD/qt5nodeinstanceserver.cpp \ $$PWD/positionernodeinstance.cpp \ $$PWD/layoutnodeinstance.cpp \ $$PWD/qt3dpresentationnodeinstance.cpp \ + $$PWD/quick3dmaterialnodeinstance.cpp \ $$PWD/quick3dnodeinstance.cpp \ + $$PWD/quick3drenderablenodeinstance.cpp \ $$PWD/quick3dtexturenodeinstance.cpp \ $$PWD/viewconfig.cpp \ $$PWD/animationdriver.cpp diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5nodeinstanceserver.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5nodeinstanceserver.cpp index 908e06ea50..32f63a8cd6 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5nodeinstanceserver.cpp +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5nodeinstanceserver.cpp @@ -202,6 +202,12 @@ QList<QQuickItem*> Qt5NodeInstanceServer::allItems() const return QList<QQuickItem*>(); } +bool Qt5NodeInstanceServer::rootIsRenderable3DObject() const +{ + return rootNodeInstance().isSubclassOf("QQuick3DNode") + || rootNodeInstance().isSubclassOf("QQuick3DMaterial"); +} + bool Qt5NodeInstanceServer::initRhi(RenderViewData &viewData) { #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) @@ -398,8 +404,6 @@ QImage Qt5NodeInstanceServer::grabItem(QQuickItem *item) QQuickItemPrivate *pItem = QQuickItemPrivate::get(item); - const bool rootIs3dNode = rootNodeInstance().isSubclassOf("QQuick3DNode"); - const bool renderEffects = qEnvironmentVariableIsSet("QMLPUPPET_RENDER_EFFECTS"); if (renderEffects) { @@ -429,7 +433,7 @@ QImage Qt5NodeInstanceServer::grabItem(QQuickItem *item) if (instance.isValid()) renderBoundingRect = instance.boundingRect(); - else if (rootIs3dNode) + else if (rootIsRenderable3DObject()) renderBoundingRect = item->boundingRect(); else renderBoundingRect = ServerNodeInstance::effectAdjustedBoundingRect(item); diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5nodeinstanceserver.h b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5nodeinstanceserver.h index a0c7929603..4c6dd2c743 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5nodeinstanceserver.h +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5nodeinstanceserver.h @@ -80,6 +80,7 @@ protected: void resetAllItems(); void setupScene(const CreateSceneCommand &command) override; QList<QQuickItem*> allItems() const; + bool rootIsRenderable3DObject() const; struct RenderViewData { QPointer<QQuickWindow> window = nullptr; diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5rendernodeinstanceserver.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5rendernodeinstanceserver.cpp index 553b69e481..2ff2339576 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5rendernodeinstanceserver.cpp +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5rendernodeinstanceserver.cpp @@ -133,7 +133,7 @@ void Qt5RenderNodeInstanceServer::collectItemChangesAndSendChangeCommands() nodeInstanceClient()->synchronizeWithClientProcess(); } - if (rootNodeInstance().isSubclassOf("QQuick3DNode") && rootNodeInstance().contentItem() + if (rootIsRenderable3DObject() && rootNodeInstance().contentItem() && DesignerSupport::isDirty(rootNodeInstance().contentItem(), DesignerSupport::AllMask) && nodeInstanceClient()->bytesToWrite() < 10000) { diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3dmaterialnodeinstance.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3dmaterialnodeinstance.cpp new file mode 100644 index 0000000000..fbfe6c2a2e --- /dev/null +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3dmaterialnodeinstance.cpp @@ -0,0 +1,57 @@ +/**************************************************************************** +** +** Copyright (C) 2022 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. +** +****************************************************************************/ + +#include "quick3dmaterialnodeinstance.h" + +namespace QmlDesigner { +namespace Internal { + +Quick3DMaterialNodeInstance::Quick3DMaterialNodeInstance(QObject *node) + : Quick3DRenderableNodeInstance(node) +{ +} + +Quick3DMaterialNodeInstance::~Quick3DMaterialNodeInstance() +{ +} + +void Quick3DMaterialNodeInstance::initialize(const ObjectNodeInstance::Pointer &objectNodeInstance, + InstanceContainer::NodeFlags flags) +{ + m_dummyRootViewCreateFunction = "createViewForMaterial"; + + Quick3DRenderableNodeInstance::initialize(objectNodeInstance, flags); +} + +Quick3DMaterialNodeInstance::Pointer Quick3DMaterialNodeInstance::create(QObject *object) +{ + Pointer instance(new Quick3DMaterialNodeInstance(object)); + instance->populateResetHashes(); + return instance; +} + +} // namespace Internal +} // namespace QmlDesigner + diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3dmaterialnodeinstance.h b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3dmaterialnodeinstance.h new file mode 100644 index 0000000000..b55cbb3f30 --- /dev/null +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3dmaterialnodeinstance.h @@ -0,0 +1,52 @@ +/**************************************************************************** +** +** Copyright (C) 2022 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 + +#include <QtGlobal> + +#include "quick3drenderablenodeinstance.h" + +QT_FORWARD_DECLARE_CLASS(QQuick3DMaterial) + +namespace QmlDesigner { +namespace Internal { + +class Quick3DMaterialNodeInstance : public Quick3DRenderableNodeInstance +{ +public: + using Pointer = QSharedPointer<Quick3DMaterialNodeInstance>; + + ~Quick3DMaterialNodeInstance() override; + static Pointer create(QObject *objectToBeWrapped); + void initialize(const ObjectNodeInstance::Pointer &objectNodeInstance, + InstanceContainer::NodeFlags flags) override; + +protected: + explicit Quick3DMaterialNodeInstance(QObject *node); +}; + +} // namespace Internal +} // namespace QmlDesigner diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3dnodeinstance.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3dnodeinstance.cpp index 0c70ccca8f..95dd4a7eff 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3dnodeinstance.cpp +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3dnodeinstance.cpp @@ -26,45 +26,28 @@ #include "quick3dnodeinstance.h" #include "qt5nodeinstanceserver.h" #include "qt5informationnodeinstanceserver.h" -#include "quickitemnodeinstance.h" -#include "../editor3d/generalhelper.h" - -#include <qmlprivategate.h> - -#include <QDebug> -#include <QHash> -#include <QQmlExpression> -#include <QQmlProperty> - -#include <cmath> #ifdef QUICK3D_MODULE #include <private/qquick3dobject_p.h> #include <private/qquick3dnode_p.h> -#include <private/qquick3dmodel_p.h> #include <private/qquick3dnode_p_p.h> #include <private/qquick3drepeater_p.h> #include <private/qquick3dloader_p.h> #if defined(QUICK3D_ASSET_UTILS_MODULE) && QT_VERSION > QT_VERSION_CHECK(6, 2, 0) #include <private/qquick3druntimeloader_p.h> #endif -#include <private/qquickstategroup_p.h> #endif - namespace QmlDesigner { namespace Internal { -const QRectF preview3dBoundingRect(0, 0, 640, 480); - Quick3DNodeInstance::Quick3DNodeInstance(QObject *node) - : ObjectNodeInstance(node) + : Quick3DRenderableNodeInstance(node) { } Quick3DNodeInstance::~Quick3DNodeInstance() { - delete m_dummyRootView; } void Quick3DNodeInstance::initialize(const ObjectNodeInstance::Pointer &objectNodeInstance, @@ -96,156 +79,10 @@ void Quick3DNodeInstance::initialize(const ObjectNodeInstance::Pointer &objectNo } } -#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) - // In case this is the scene root, we need to create a dummy View3D for the scene - // in preview puppets - if (instanceId() == 0 && (!nodeInstanceServer()->isInformationServer())) { - auto helper = new QmlDesigner::Internal::GeneralHelper(); - engine()->rootContext()->setContextProperty("_generalHelper", helper); - - QQmlComponent component(engine()); - component.loadUrl(QUrl("qrc:/qtquickplugin/mockfiles/qt6/ModelNode3DImageView.qml")); - m_dummyRootView = qobject_cast<QQuickItem *>(component.create()); + m_dummyRootViewCreateFunction = "createViewForNode"; - QMetaObject::invokeMethod( - m_dummyRootView, "createViewForNode", - Q_ARG(QVariant, QVariant::fromValue(object()))); - - nodeInstanceServer()->setRootItem(m_dummyRootView); - } -#endif // QT_VERSION + Quick3DRenderableNodeInstance::initialize(objectNodeInstance, flags); #endif // QUICK3D_MODULE - ObjectNodeInstance::initialize(objectNodeInstance, flags); -} - -QImage Quick3DNodeInstance::renderImage() const -{ -#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) - if (!isRootNodeInstance() || !m_dummyRootView) - return {}; - - QSize size = preview3dBoundingRect.size().toSize(); - nodeInstanceServer()->quickWindow()->resize(size); - m_dummyRootView->setSize(size); - - // Just render the window once to update spatial nodes - nodeInstanceServer()->renderWindow(); - - QMetaObject::invokeMethod(m_dummyRootView, "fitToViewPort", Qt::DirectConnection); - - QRectF renderBoundingRect = m_dummyRootView->boundingRect(); - QImage renderImage; - - if (QuickItemNodeInstance::unifiedRenderPath()) { - renderImage = nodeInstanceServer()->grabWindow(); - renderImage = renderImage.copy(renderBoundingRect.toRect()); - } else { - renderImage = nodeInstanceServer()->grabItem(m_dummyRootView); - } - - // When grabbing an offscreen window the device pixel ratio is 1 - renderImage.setDevicePixelRatio(1); - - return renderImage; -#endif - return {}; -} - -QImage Quick3DNodeInstance::renderPreviewImage(const QSize &previewImageSize) const -{ -#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) - if (!isRootNodeInstance() || !m_dummyRootView) - return {}; - - nodeInstanceServer()->quickWindow()->resize(previewImageSize); - m_dummyRootView->setSize(previewImageSize); - - // Just render the window once to update spatial nodes - nodeInstanceServer()->renderWindow(); - - QMetaObject::invokeMethod(m_dummyRootView, "fitToViewPort", Qt::DirectConnection); - - QRectF previewItemBoundingRect = boundingRect(); - - if (previewItemBoundingRect.isValid()) { - const QSize size = previewImageSize; - if (m_dummyRootView->isVisible()) { - QImage image; - image = nodeInstanceServer()->grabWindow(); - image = image.copy(previewItemBoundingRect.toRect()); - image = image.scaledToWidth(size.width()); - return image; - } else { - QImage transparentImage(size, QImage::Format_ARGB32_Premultiplied); - transparentImage.fill(Qt::transparent); - return transparentImage; - } - } -#else - Q_UNUSED(previewImageSize) -#endif - return {}; -} - -bool Quick3DNodeInstance::isRenderable() const -{ - return m_dummyRootView; -} - -bool Quick3DNodeInstance::hasContent() const -{ - return true; -} - -QRectF Quick3DNodeInstance::boundingRect() const -{ - //The information server has no m_dummyRootView therefore we use the hardcoded value - if (nodeInstanceServer()->isInformationServer()) - return preview3dBoundingRect; - - if (m_dummyRootView) - return m_dummyRootView->boundingRect(); - return ObjectNodeInstance::boundingRect(); -} - -QRectF Quick3DNodeInstance::contentItemBoundingBox() const -{ - return boundingRect(); -} - -QPointF Quick3DNodeInstance::position() const -{ - return QPointF(0, 0); -} - -QSizeF Quick3DNodeInstance::size() const -{ - return boundingRect().size(); -} - -QList<ServerNodeInstance> Quick3DNodeInstance::stateInstances() const -{ - QList<ServerNodeInstance> instanceList; -#ifdef QUICK3D_MODULE - if (auto obj3D = quick3DNode()) { - const QList<QQuickState *> stateList = QQuick3DObjectPrivate::get(obj3D)->_states()->states(); - for (QQuickState *state : stateList) { - if (state && nodeInstanceServer()->hasInstanceForObject(state)) - instanceList.append(nodeInstanceServer()->instanceForObject(state)); - } - } -#endif - return instanceList; -} - -QQuickItem *Quick3DNodeInstance::contentItem() const -{ - return m_dummyRootView; -} - -Qt5NodeInstanceServer *Quick3DNodeInstance::qt5NodeInstanceServer() const -{ - return qobject_cast<Qt5NodeInstanceServer *>(nodeInstanceServer()); } QQuick3DNode *Quick3DNodeInstance::quick3DNode() const diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3dnodeinstance.h b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3dnodeinstance.h index b3b4f78972..ea44f277fb 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3dnodeinstance.h +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3dnodeinstance.h @@ -27,16 +27,14 @@ #include <QtGlobal> -#include "objectnodeinstance.h" - -#include <designersupportdelegate.h> +#include "quick3drenderablenodeinstance.h" QT_FORWARD_DECLARE_CLASS(QQuick3DNode) namespace QmlDesigner { namespace Internal { -class Quick3DNodeInstance : public ObjectNodeInstance +class Quick3DNodeInstance : public Quick3DRenderableNodeInstance { public: using Pointer = QSharedPointer<Quick3DNodeInstance>; @@ -47,28 +45,11 @@ public: void initialize(const ObjectNodeInstance::Pointer &objectNodeInstance, InstanceContainer::NodeFlags flags) override; - QImage renderImage() const override; - QImage renderPreviewImage(const QSize &previewImageSize) const override; - - bool isRenderable() const override; - bool hasContent() const override; - QRectF boundingRect() const override; - QRectF contentItemBoundingBox() const override; - QPointF position() const override; - QSizeF size() const override; - - QList<ServerNodeInstance> stateInstances() const override; - - QQuickItem *contentItem() const override; - protected: explicit Quick3DNodeInstance(QObject *node); private: - Qt5NodeInstanceServer *qt5NodeInstanceServer() const; QQuick3DNode *quick3DNode() const; - - QQuickItem *m_dummyRootView = nullptr; }; } // namespace Internal diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3drenderablenodeinstance.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3drenderablenodeinstance.cpp new file mode 100644 index 0000000000..589f57cb5f --- /dev/null +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3drenderablenodeinstance.cpp @@ -0,0 +1,209 @@ +/**************************************************************************** +** +** Copyright (C) 2022 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. +** +****************************************************************************/ + +#include "quick3drenderablenodeinstance.h" +#include "qt5nodeinstanceserver.h" +#include "quickitemnodeinstance.h" +#include "../editor3d/generalhelper.h" + +#ifdef QUICK3D_MODULE +#include <private/qquick3dobject_p.h> +#include <private/qquickstategroup_p.h> +#endif + + +namespace QmlDesigner { +namespace Internal { + +const QRectF preview3dBoundingRect(0, 0, 640, 480); + +Quick3DRenderableNodeInstance::Quick3DRenderableNodeInstance(QObject *node) + : ObjectNodeInstance(node) +{ +} + +Quick3DRenderableNodeInstance::~Quick3DRenderableNodeInstance() +{ + delete m_dummyRootView; +} + +void Quick3DRenderableNodeInstance::initialize(const ObjectNodeInstance::Pointer &objectNodeInstance, + InstanceContainer::NodeFlags flags) +{ +#ifdef QUICK3D_MODULE +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + // In case this is the scene root, we need to create a dummy View3D for the scene + // in preview puppets + if (instanceId() == 0 && (!nodeInstanceServer()->isInformationServer())) { + auto helper = new QmlDesigner::Internal::GeneralHelper(); + engine()->rootContext()->setContextProperty("_generalHelper", helper); + + QQmlComponent component(engine()); + component.loadUrl(QUrl("qrc:/qtquickplugin/mockfiles/qt6/ModelNode3DImageView.qml")); + m_dummyRootView = qobject_cast<QQuickItem *>(component.create()); + + QMetaObject::invokeMethod(m_dummyRootView, m_dummyRootViewCreateFunction, + Q_ARG(QVariant, QVariant::fromValue(object()))); + + nodeInstanceServer()->setRootItem(m_dummyRootView); + } +#endif // QT_VERSION +#endif // QUICK3D_MODULE + ObjectNodeInstance::initialize(objectNodeInstance, flags); +} + +QImage Quick3DRenderableNodeInstance::renderImage() const +{ +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + if (!isRootNodeInstance() || !m_dummyRootView) + return {}; + + QSize size = preview3dBoundingRect.size().toSize(); + nodeInstanceServer()->quickWindow()->resize(size); + m_dummyRootView->setSize(size); + + // Just render the window once to update spatial nodes + nodeInstanceServer()->renderWindow(); + + QMetaObject::invokeMethod(m_dummyRootView, "fitToViewPort", Qt::DirectConnection); + + QRectF renderBoundingRect = m_dummyRootView->boundingRect(); + QImage renderImage; + + if (QuickItemNodeInstance::unifiedRenderPath()) { + renderImage = nodeInstanceServer()->grabWindow(); + renderImage = renderImage.copy(renderBoundingRect.toRect()); + } else { + renderImage = nodeInstanceServer()->grabItem(m_dummyRootView); + } + + // When grabbing an offscreen window the device pixel ratio is 1 + renderImage.setDevicePixelRatio(1); + + return renderImage; +#endif + return {}; +} + +QImage Quick3DRenderableNodeInstance::renderPreviewImage(const QSize &previewImageSize) const +{ +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + if (!isRootNodeInstance() || !m_dummyRootView) + return {}; + + nodeInstanceServer()->quickWindow()->resize(previewImageSize); + m_dummyRootView->setSize(previewImageSize); + + // Just render the window once to update spatial nodes + nodeInstanceServer()->renderWindow(); + + QMetaObject::invokeMethod(m_dummyRootView, "fitToViewPort", Qt::DirectConnection); + + QRectF previewItemBoundingRect = boundingRect(); + + if (previewItemBoundingRect.isValid()) { + const QSize size = previewImageSize; + if (m_dummyRootView->isVisible()) { + QImage image; + image = nodeInstanceServer()->grabWindow(); + image = image.copy(previewItemBoundingRect.toRect()); + image = image.scaledToWidth(size.width()); + return image; + } else { + QImage transparentImage(size, QImage::Format_ARGB32_Premultiplied); + transparentImage.fill(Qt::transparent); + return transparentImage; + } + } +#else + Q_UNUSED(previewImageSize) +#endif + return {}; +} + +bool Quick3DRenderableNodeInstance::isRenderable() const +{ + return m_dummyRootView; +} + +bool Quick3DRenderableNodeInstance::hasContent() const +{ + return true; +} + +QRectF Quick3DRenderableNodeInstance::boundingRect() const +{ + //The information server has no m_dummyRootView therefore we use the hardcoded value + if (nodeInstanceServer()->isInformationServer()) + return preview3dBoundingRect; + + if (m_dummyRootView) + return m_dummyRootView->boundingRect(); + return ObjectNodeInstance::boundingRect(); +} + +QRectF Quick3DRenderableNodeInstance::contentItemBoundingBox() const +{ + return boundingRect(); +} + +QPointF Quick3DRenderableNodeInstance::position() const +{ + return QPointF(0, 0); +} + +QSizeF Quick3DRenderableNodeInstance::size() const +{ + return boundingRect().size(); +} + +QList<ServerNodeInstance> Quick3DRenderableNodeInstance::stateInstances() const +{ + QList<ServerNodeInstance> instanceList; +#ifdef QUICK3D_MODULE + if (auto obj3D = qobject_cast<QQuick3DObject *>(object())) { + const QList<QQuickState *> stateList = QQuick3DObjectPrivate::get(obj3D)->_states()->states(); + for (QQuickState *state : stateList) { + if (state && nodeInstanceServer()->hasInstanceForObject(state)) + instanceList.append(nodeInstanceServer()->instanceForObject(state)); + } + } +#endif + return instanceList; +} + +QQuickItem *Quick3DRenderableNodeInstance::contentItem() const +{ + return m_dummyRootView; +} + +Qt5NodeInstanceServer *Quick3DRenderableNodeInstance::qt5NodeInstanceServer() const +{ + return qobject_cast<Qt5NodeInstanceServer *>(nodeInstanceServer()); +} + +} // namespace Internal +} // namespace QmlDesigner + diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3drenderablenodeinstance.h b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3drenderablenodeinstance.h new file mode 100644 index 0000000000..ae03cb1b90 --- /dev/null +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3drenderablenodeinstance.h @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** Copyright (C) 2022 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 + +#include <QtGlobal> + +#include "objectnodeinstance.h" + +namespace QmlDesigner { +namespace Internal { + +class Quick3DRenderableNodeInstance : public ObjectNodeInstance +{ +public: + ~Quick3DRenderableNodeInstance() override; + void initialize(const ObjectNodeInstance::Pointer &objectNodeInstance, + InstanceContainer::NodeFlags flags) override; + + QImage renderImage() const override; + QImage renderPreviewImage(const QSize &previewImageSize) const override; + + bool isRenderable() const override; + bool hasContent() const override; + QRectF boundingRect() const override; + QRectF contentItemBoundingBox() const override; + QPointF position() const override; + QSizeF size() const override; + + QList<ServerNodeInstance> stateInstances() const override; + + QQuickItem *contentItem() const override; + +protected: + explicit Quick3DRenderableNodeInstance(QObject *node); + Qt5NodeInstanceServer *qt5NodeInstanceServer() const; + + QByteArray m_dummyRootViewCreateFunction; + +private: + QQuickItem *m_dummyRootView = nullptr; +}; + +} // namespace Internal +} // namespace QmlDesigner diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/servernodeinstance.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/servernodeinstance.cpp index f6c7f94bca..a4fdde97ec 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/servernodeinstance.cpp +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/servernodeinstance.cpp @@ -39,6 +39,7 @@ #include "qt3dpresentationnodeinstance.h" #include "quickitemnodeinstance.h" +#include "quick3dmaterialnodeinstance.h" #include "quick3dnodeinstance.h" #include "quick3dtexturenodeinstance.h" @@ -203,6 +204,8 @@ Internal::ObjectNodeInstance::Pointer ServerNodeInstance::createInstance(QObject instance = Internal::Quick3DTextureNodeInstance::create(objectToBeWrapped); else if (isSubclassOf(objectToBeWrapped, "QQuick3DNode")) instance = Internal::Quick3DNodeInstance::create(objectToBeWrapped); + else if (isSubclassOf(objectToBeWrapped, "QQuick3DMaterial")) + instance = Internal::Quick3DMaterialNodeInstance::create(objectToBeWrapped); else if (isSubclassOf(objectToBeWrapped, "QQmlComponent")) instance = Internal::ComponentNodeInstance::create(objectToBeWrapped); else if (objectToBeWrapped->inherits("QQmlAnchorChanges")) diff --git a/src/plugins/qmldesigner/components/formeditor/formeditorview.cpp b/src/plugins/qmldesigner/components/formeditor/formeditorview.cpp index 9fc14da999..6c6e67be81 100644 --- a/src/plugins/qmldesigner/components/formeditor/formeditorview.cpp +++ b/src/plugins/qmldesigner/components/formeditor/formeditorview.cpp @@ -659,7 +659,7 @@ static void updateTransitions(FormEditorScene *scene, const QmlItemNode &qmlItem void FormEditorView::instancesCompleted(const QVector<ModelNode> &completedNodeList) { - if (Qml3DNode::isValidQml3DNode(rootModelNode())) { + if (Qml3DNode::isValidVisualRoot(rootModelNode())) { if (completedNodeList.contains(rootModelNode())) { FormEditorItem *item = scene()->itemForQmlItemNode(rootModelNode()); if (item) @@ -736,7 +736,7 @@ void FormEditorView::instancesRenderImageChanged(const QVector<ModelNode> &nodeL if (QmlItemNode::isValidQmlItemNode(node)) if (FormEditorItem *item = scene()->itemForQmlItemNode(QmlItemNode(node))) item->update(); - if (Qml3DNode::isValidQml3DNode(node)) { + if (Qml3DNode::isValidVisualRoot(node)) { if (FormEditorItem *item = scene()->itemForQmlItemNode(node)) item->update(); } @@ -811,7 +811,7 @@ void FormEditorView::setupFormEditorWidget() if (QmlItemNode::isValidQmlItemNode(rootModelNode())) setupFormEditorItemTree(rootModelNode()); - if (Qml3DNode::isValidQml3DNode(rootModelNode())) + if (Qml3DNode::isValidVisualRoot(rootModelNode())) setupFormEditor3DView(); m_formEditorWidget->initialize(); @@ -923,7 +923,7 @@ void FormEditorView::checkRootModelNode() QTC_ASSERT(rootModelNode().isValid(), return); if (!rootModelNode().metaInfo().isGraphicalItem() - && !Qml3DNode::isValidQml3DNode(rootModelNode())) + && !Qml3DNode::isValidVisualRoot(rootModelNode())) m_formEditorWidget->showErrorMessageBox( {DocumentMessage(tr("%1 is not supported as the root element by Form Editor.") .arg(rootModelNode().simplifiedTypeName()))}); diff --git a/src/plugins/qmldesigner/designercore/include/qml3dnode.h b/src/plugins/qmldesigner/designercore/include/qml3dnode.h index d52cacb49b..87d06dca7e 100644 --- a/src/plugins/qmldesigner/designercore/include/qml3dnode.h +++ b/src/plugins/qmldesigner/designercore/include/qml3dnode.h @@ -49,6 +49,7 @@ public: Qml3DNode(const ModelNode &modelNode) : QmlVisualNode(modelNode) {} bool isValid() const override; static bool isValidQml3DNode(const ModelNode &modelNode); + static bool isValidVisualRoot(const ModelNode &modelNode); // From QmlObjectNode void setVariantProperty(const PropertyName &name, const QVariant &value) override; diff --git a/src/plugins/qmldesigner/designercore/model/qml3dnode.cpp b/src/plugins/qmldesigner/designercore/model/qml3dnode.cpp index 7f6f07b001..c6698df6e6 100644 --- a/src/plugins/qmldesigner/designercore/model/qml3dnode.cpp +++ b/src/plugins/qmldesigner/designercore/model/qml3dnode.cpp @@ -58,6 +58,15 @@ bool Qml3DNode::isValidQml3DNode(const ModelNode &modelNode) && (modelNode.metaInfo().isSubclassOf("QtQuick3D.Node")); } +bool Qml3DNode::isValidVisualRoot(const ModelNode &modelNode) +{ + return isValidQmlObjectNode(modelNode) + && modelNode.metaInfo().isValid() + && ((modelNode.metaInfo().isSubclassOf("QtQuick3D.Node")) + || (modelNode.metaInfo().isSubclassOf("QtQuick3D.Material"))); + +} + void Qml3DNode::setVariantProperty(const PropertyName &name, const QVariant &value) { if (isBlocked(name)) diff --git a/src/tools/qml2puppet/CMakeLists.txt b/src/tools/qml2puppet/CMakeLists.txt index 890cbbf5dc..15c5231d05 100644 --- a/src/tools/qml2puppet/CMakeLists.txt +++ b/src/tools/qml2puppet/CMakeLists.txt @@ -231,7 +231,9 @@ extend_qtc_executable(qml2puppet qt5previewnodeinstanceserver.cpp qt5previewnodeinstanceserver.h qt5rendernodeinstanceserver.cpp qt5rendernodeinstanceserver.h qt5testnodeinstanceserver.cpp qt5testnodeinstanceserver.h + quick3dmaterialnodeinstance.cpp quick3dmaterialnodeinstance.h quick3dnodeinstance.cpp quick3dnodeinstance.h + quick3drenderablenodeinstance.cpp quick3drenderablenodeinstance.h quick3dtexturenodeinstance.cpp quick3dtexturenodeinstance.h quickitemnodeinstance.cpp quickitemnodeinstance.h servernodeinstance.cpp servernodeinstance.h diff --git a/src/tools/qml2puppet/qml2puppet.qbs b/src/tools/qml2puppet/qml2puppet.qbs index f51dd11b75..0031fe34c9 100644 --- a/src/tools/qml2puppet/qml2puppet.qbs +++ b/src/tools/qml2puppet/qml2puppet.qbs @@ -223,8 +223,12 @@ QtcTool { "instances/qmlpropertychangesnodeinstance.h", "instances/qmlstatenodeinstance.cpp", "instances/qmlstatenodeinstance.h", + "instances/quick3dmaterialnodeinstance.cpp", + "instances/quick3dmaterialnodeinstance.h", "instances/quick3dnodeinstance.cpp", "instances/quick3dnodeinstance.h", + "instances/quick3drenderablenodeinstance.cpp", + "instances/quick3drenderablenodeinstance.h", "instances/quick3dtexturenodeinstance.cpp", "instances/quick3dtexturenodeinstance.h", "instances/qmltransitionnodeinstance.cpp", |