aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiikka Heikkinen <miikka.heikkinen@qt.io>2022-05-16 16:01:16 +0300
committerMiikka Heikkinen <miikka.heikkinen@qt.io>2022-05-27 08:49:14 +0000
commitd92bdcce40d805420ea573a0864582cb5be6f2bb (patch)
tree7a08a26894992a70d2092a348378326ea8c3c6eb
parent07d9075d478163fa15b24da424d9948d1d46ae05 (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>
-rw-r--r--share/qtcreator/qml/qmlpuppet/qml2puppet/instances/instances.pri4
-rw-r--r--share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5nodeinstanceserver.cpp10
-rw-r--r--share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5nodeinstanceserver.h1
-rw-r--r--share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5rendernodeinstanceserver.cpp2
-rw-r--r--share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3dmaterialnodeinstance.cpp57
-rw-r--r--share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3dmaterialnodeinstance.h52
-rw-r--r--share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3dnodeinstance.cpp169
-rw-r--r--share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3dnodeinstance.h23
-rw-r--r--share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3drenderablenodeinstance.cpp209
-rw-r--r--share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3drenderablenodeinstance.h67
-rw-r--r--share/qtcreator/qml/qmlpuppet/qml2puppet/instances/servernodeinstance.cpp3
-rw-r--r--src/plugins/qmldesigner/components/formeditor/formeditorview.cpp8
-rw-r--r--src/plugins/qmldesigner/designercore/include/qml3dnode.h1
-rw-r--r--src/plugins/qmldesigner/designercore/model/qml3dnode.cpp9
-rw-r--r--src/tools/qml2puppet/CMakeLists.txt2
-rw-r--r--src/tools/qml2puppet/qml2puppet.qbs4
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",