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>
This commit is contained in:
Miikka Heikkinen
2022-05-16 16:01:16 +03:00
parent 07d9075d47
commit d92bdcce40
16 changed files with 426 additions and 195 deletions

View File

@@ -46,7 +46,9 @@ HEADERS += $$PWD/qt5nodeinstanceserver.h \
$$PWD/positionernodeinstance.h \ $$PWD/positionernodeinstance.h \
$$PWD/layoutnodeinstance.h \ $$PWD/layoutnodeinstance.h \
$$PWD/qt3dpresentationnodeinstance.h \ $$PWD/qt3dpresentationnodeinstance.h \
$$PWD/quick3dmaterialnodeinstance.h \
$$PWD/quick3dnodeinstance.h \ $$PWD/quick3dnodeinstance.h \
$$PWD/quick3drenderablenodeinstance.h \
$$PWD/quick3dtexturenodeinstance.h \ $$PWD/quick3dtexturenodeinstance.h \
$$PWD/viewconfig.h \ $$PWD/viewconfig.h \
$$PWD/animationdriver.h $$PWD/animationdriver.h
@@ -79,7 +81,9 @@ SOURCES += $$PWD/qt5nodeinstanceserver.cpp \
$$PWD/positionernodeinstance.cpp \ $$PWD/positionernodeinstance.cpp \
$$PWD/layoutnodeinstance.cpp \ $$PWD/layoutnodeinstance.cpp \
$$PWD/qt3dpresentationnodeinstance.cpp \ $$PWD/qt3dpresentationnodeinstance.cpp \
$$PWD/quick3dmaterialnodeinstance.cpp \
$$PWD/quick3dnodeinstance.cpp \ $$PWD/quick3dnodeinstance.cpp \
$$PWD/quick3drenderablenodeinstance.cpp \
$$PWD/quick3dtexturenodeinstance.cpp \ $$PWD/quick3dtexturenodeinstance.cpp \
$$PWD/viewconfig.cpp \ $$PWD/viewconfig.cpp \
$$PWD/animationdriver.cpp $$PWD/animationdriver.cpp

View File

@@ -202,6 +202,12 @@ QList<QQuickItem*> Qt5NodeInstanceServer::allItems() const
return QList<QQuickItem*>(); return QList<QQuickItem*>();
} }
bool Qt5NodeInstanceServer::rootIsRenderable3DObject() const
{
return rootNodeInstance().isSubclassOf("QQuick3DNode")
|| rootNodeInstance().isSubclassOf("QQuick3DMaterial");
}
bool Qt5NodeInstanceServer::initRhi(RenderViewData &viewData) bool Qt5NodeInstanceServer::initRhi(RenderViewData &viewData)
{ {
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
@@ -398,8 +404,6 @@ QImage Qt5NodeInstanceServer::grabItem(QQuickItem *item)
QQuickItemPrivate *pItem = QQuickItemPrivate::get(item); QQuickItemPrivate *pItem = QQuickItemPrivate::get(item);
const bool rootIs3dNode = rootNodeInstance().isSubclassOf("QQuick3DNode");
const bool renderEffects = qEnvironmentVariableIsSet("QMLPUPPET_RENDER_EFFECTS"); const bool renderEffects = qEnvironmentVariableIsSet("QMLPUPPET_RENDER_EFFECTS");
if (renderEffects) { if (renderEffects) {
@@ -429,7 +433,7 @@ QImage Qt5NodeInstanceServer::grabItem(QQuickItem *item)
if (instance.isValid()) if (instance.isValid())
renderBoundingRect = instance.boundingRect(); renderBoundingRect = instance.boundingRect();
else if (rootIs3dNode) else if (rootIsRenderable3DObject())
renderBoundingRect = item->boundingRect(); renderBoundingRect = item->boundingRect();
else else
renderBoundingRect = ServerNodeInstance::effectAdjustedBoundingRect(item); renderBoundingRect = ServerNodeInstance::effectAdjustedBoundingRect(item);

View File

@@ -80,6 +80,7 @@ protected:
void resetAllItems(); void resetAllItems();
void setupScene(const CreateSceneCommand &command) override; void setupScene(const CreateSceneCommand &command) override;
QList<QQuickItem*> allItems() const; QList<QQuickItem*> allItems() const;
bool rootIsRenderable3DObject() const;
struct RenderViewData { struct RenderViewData {
QPointer<QQuickWindow> window = nullptr; QPointer<QQuickWindow> window = nullptr;

View File

@@ -133,7 +133,7 @@ void Qt5RenderNodeInstanceServer::collectItemChangesAndSendChangeCommands()
nodeInstanceClient()->synchronizeWithClientProcess(); nodeInstanceClient()->synchronizeWithClientProcess();
} }
if (rootNodeInstance().isSubclassOf("QQuick3DNode") && rootNodeInstance().contentItem() if (rootIsRenderable3DObject() && rootNodeInstance().contentItem()
&& DesignerSupport::isDirty(rootNodeInstance().contentItem(), && DesignerSupport::isDirty(rootNodeInstance().contentItem(),
DesignerSupport::AllMask) DesignerSupport::AllMask)
&& nodeInstanceClient()->bytesToWrite() < 10000) { && nodeInstanceClient()->bytesToWrite() < 10000) {

View File

@@ -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

View File

@@ -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

View File

@@ -26,45 +26,28 @@
#include "quick3dnodeinstance.h" #include "quick3dnodeinstance.h"
#include "qt5nodeinstanceserver.h" #include "qt5nodeinstanceserver.h"
#include "qt5informationnodeinstanceserver.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 #ifdef QUICK3D_MODULE
#include <private/qquick3dobject_p.h> #include <private/qquick3dobject_p.h>
#include <private/qquick3dnode_p.h> #include <private/qquick3dnode_p.h>
#include <private/qquick3dmodel_p.h>
#include <private/qquick3dnode_p_p.h> #include <private/qquick3dnode_p_p.h>
#include <private/qquick3drepeater_p.h> #include <private/qquick3drepeater_p.h>
#include <private/qquick3dloader_p.h> #include <private/qquick3dloader_p.h>
#if defined(QUICK3D_ASSET_UTILS_MODULE) && QT_VERSION > QT_VERSION_CHECK(6, 2, 0) #if defined(QUICK3D_ASSET_UTILS_MODULE) && QT_VERSION > QT_VERSION_CHECK(6, 2, 0)
#include <private/qquick3druntimeloader_p.h> #include <private/qquick3druntimeloader_p.h>
#endif #endif
#include <private/qquickstategroup_p.h>
#endif #endif
namespace QmlDesigner { namespace QmlDesigner {
namespace Internal { namespace Internal {
const QRectF preview3dBoundingRect(0, 0, 640, 480);
Quick3DNodeInstance::Quick3DNodeInstance(QObject *node) Quick3DNodeInstance::Quick3DNodeInstance(QObject *node)
: ObjectNodeInstance(node) : Quick3DRenderableNodeInstance(node)
{ {
} }
Quick3DNodeInstance::~Quick3DNodeInstance() Quick3DNodeInstance::~Quick3DNodeInstance()
{ {
delete m_dummyRootView;
} }
void Quick3DNodeInstance::initialize(const ObjectNodeInstance::Pointer &objectNodeInstance, 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) m_dummyRootViewCreateFunction = "createViewForNode";
// 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()); Quick3DRenderableNodeInstance::initialize(objectNodeInstance, flags);
component.loadUrl(QUrl("qrc:/qtquickplugin/mockfiles/qt6/ModelNode3DImageView.qml"));
m_dummyRootView = qobject_cast<QQuickItem *>(component.create());
QMetaObject::invokeMethod(
m_dummyRootView, "createViewForNode",
Q_ARG(QVariant, QVariant::fromValue(object())));
nodeInstanceServer()->setRootItem(m_dummyRootView);
}
#endif // QT_VERSION
#endif // QUICK3D_MODULE #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 QQuick3DNode *Quick3DNodeInstance::quick3DNode() const

View File

@@ -27,16 +27,14 @@
#include <QtGlobal> #include <QtGlobal>
#include "objectnodeinstance.h" #include "quick3drenderablenodeinstance.h"
#include <designersupportdelegate.h>
QT_FORWARD_DECLARE_CLASS(QQuick3DNode) QT_FORWARD_DECLARE_CLASS(QQuick3DNode)
namespace QmlDesigner { namespace QmlDesigner {
namespace Internal { namespace Internal {
class Quick3DNodeInstance : public ObjectNodeInstance class Quick3DNodeInstance : public Quick3DRenderableNodeInstance
{ {
public: public:
using Pointer = QSharedPointer<Quick3DNodeInstance>; using Pointer = QSharedPointer<Quick3DNodeInstance>;
@@ -47,28 +45,11 @@ public:
void initialize(const ObjectNodeInstance::Pointer &objectNodeInstance, void initialize(const ObjectNodeInstance::Pointer &objectNodeInstance,
InstanceContainer::NodeFlags flags) override; 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: protected:
explicit Quick3DNodeInstance(QObject *node); explicit Quick3DNodeInstance(QObject *node);
private: private:
Qt5NodeInstanceServer *qt5NodeInstanceServer() const;
QQuick3DNode *quick3DNode() const; QQuick3DNode *quick3DNode() const;
QQuickItem *m_dummyRootView = nullptr;
}; };
} // namespace Internal } // namespace Internal

View File

@@ -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

View File

@@ -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

View File

@@ -39,6 +39,7 @@
#include "qt3dpresentationnodeinstance.h" #include "qt3dpresentationnodeinstance.h"
#include "quickitemnodeinstance.h" #include "quickitemnodeinstance.h"
#include "quick3dmaterialnodeinstance.h"
#include "quick3dnodeinstance.h" #include "quick3dnodeinstance.h"
#include "quick3dtexturenodeinstance.h" #include "quick3dtexturenodeinstance.h"
@@ -203,6 +204,8 @@ Internal::ObjectNodeInstance::Pointer ServerNodeInstance::createInstance(QObject
instance = Internal::Quick3DTextureNodeInstance::create(objectToBeWrapped); instance = Internal::Quick3DTextureNodeInstance::create(objectToBeWrapped);
else if (isSubclassOf(objectToBeWrapped, "QQuick3DNode")) else if (isSubclassOf(objectToBeWrapped, "QQuick3DNode"))
instance = Internal::Quick3DNodeInstance::create(objectToBeWrapped); instance = Internal::Quick3DNodeInstance::create(objectToBeWrapped);
else if (isSubclassOf(objectToBeWrapped, "QQuick3DMaterial"))
instance = Internal::Quick3DMaterialNodeInstance::create(objectToBeWrapped);
else if (isSubclassOf(objectToBeWrapped, "QQmlComponent")) else if (isSubclassOf(objectToBeWrapped, "QQmlComponent"))
instance = Internal::ComponentNodeInstance::create(objectToBeWrapped); instance = Internal::ComponentNodeInstance::create(objectToBeWrapped);
else if (objectToBeWrapped->inherits("QQmlAnchorChanges")) else if (objectToBeWrapped->inherits("QQmlAnchorChanges"))

View File

@@ -659,7 +659,7 @@ static void updateTransitions(FormEditorScene *scene, const QmlItemNode &qmlItem
void FormEditorView::instancesCompleted(const QVector<ModelNode> &completedNodeList) void FormEditorView::instancesCompleted(const QVector<ModelNode> &completedNodeList)
{ {
if (Qml3DNode::isValidQml3DNode(rootModelNode())) { if (Qml3DNode::isValidVisualRoot(rootModelNode())) {
if (completedNodeList.contains(rootModelNode())) { if (completedNodeList.contains(rootModelNode())) {
FormEditorItem *item = scene()->itemForQmlItemNode(rootModelNode()); FormEditorItem *item = scene()->itemForQmlItemNode(rootModelNode());
if (item) if (item)
@@ -736,7 +736,7 @@ void FormEditorView::instancesRenderImageChanged(const QVector<ModelNode> &nodeL
if (QmlItemNode::isValidQmlItemNode(node)) if (QmlItemNode::isValidQmlItemNode(node))
if (FormEditorItem *item = scene()->itemForQmlItemNode(QmlItemNode(node))) if (FormEditorItem *item = scene()->itemForQmlItemNode(QmlItemNode(node)))
item->update(); item->update();
if (Qml3DNode::isValidQml3DNode(node)) { if (Qml3DNode::isValidVisualRoot(node)) {
if (FormEditorItem *item = scene()->itemForQmlItemNode(node)) if (FormEditorItem *item = scene()->itemForQmlItemNode(node))
item->update(); item->update();
} }
@@ -811,7 +811,7 @@ void FormEditorView::setupFormEditorWidget()
if (QmlItemNode::isValidQmlItemNode(rootModelNode())) if (QmlItemNode::isValidQmlItemNode(rootModelNode()))
setupFormEditorItemTree(rootModelNode()); setupFormEditorItemTree(rootModelNode());
if (Qml3DNode::isValidQml3DNode(rootModelNode())) if (Qml3DNode::isValidVisualRoot(rootModelNode()))
setupFormEditor3DView(); setupFormEditor3DView();
m_formEditorWidget->initialize(); m_formEditorWidget->initialize();
@@ -923,7 +923,7 @@ void FormEditorView::checkRootModelNode()
QTC_ASSERT(rootModelNode().isValid(), return); QTC_ASSERT(rootModelNode().isValid(), return);
if (!rootModelNode().metaInfo().isGraphicalItem() if (!rootModelNode().metaInfo().isGraphicalItem()
&& !Qml3DNode::isValidQml3DNode(rootModelNode())) && !Qml3DNode::isValidVisualRoot(rootModelNode()))
m_formEditorWidget->showErrorMessageBox( m_formEditorWidget->showErrorMessageBox(
{DocumentMessage(tr("%1 is not supported as the root element by Form Editor.") {DocumentMessage(tr("%1 is not supported as the root element by Form Editor.")
.arg(rootModelNode().simplifiedTypeName()))}); .arg(rootModelNode().simplifiedTypeName()))});

View File

@@ -49,6 +49,7 @@ public:
Qml3DNode(const ModelNode &modelNode) : QmlVisualNode(modelNode) {} Qml3DNode(const ModelNode &modelNode) : QmlVisualNode(modelNode) {}
bool isValid() const override; bool isValid() const override;
static bool isValidQml3DNode(const ModelNode &modelNode); static bool isValidQml3DNode(const ModelNode &modelNode);
static bool isValidVisualRoot(const ModelNode &modelNode);
// From QmlObjectNode // From QmlObjectNode
void setVariantProperty(const PropertyName &name, const QVariant &value) override; void setVariantProperty(const PropertyName &name, const QVariant &value) override;

View File

@@ -58,6 +58,15 @@ bool Qml3DNode::isValidQml3DNode(const ModelNode &modelNode)
&& (modelNode.metaInfo().isSubclassOf("QtQuick3D.Node")); && (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) void Qml3DNode::setVariantProperty(const PropertyName &name, const QVariant &value)
{ {
if (isBlocked(name)) if (isBlocked(name))

View File

@@ -231,7 +231,9 @@ extend_qtc_executable(qml2puppet
qt5previewnodeinstanceserver.cpp qt5previewnodeinstanceserver.h qt5previewnodeinstanceserver.cpp qt5previewnodeinstanceserver.h
qt5rendernodeinstanceserver.cpp qt5rendernodeinstanceserver.h qt5rendernodeinstanceserver.cpp qt5rendernodeinstanceserver.h
qt5testnodeinstanceserver.cpp qt5testnodeinstanceserver.h qt5testnodeinstanceserver.cpp qt5testnodeinstanceserver.h
quick3dmaterialnodeinstance.cpp quick3dmaterialnodeinstance.h
quick3dnodeinstance.cpp quick3dnodeinstance.h quick3dnodeinstance.cpp quick3dnodeinstance.h
quick3drenderablenodeinstance.cpp quick3drenderablenodeinstance.h
quick3dtexturenodeinstance.cpp quick3dtexturenodeinstance.h quick3dtexturenodeinstance.cpp quick3dtexturenodeinstance.h
quickitemnodeinstance.cpp quickitemnodeinstance.h quickitemnodeinstance.cpp quickitemnodeinstance.h
servernodeinstance.cpp servernodeinstance.h servernodeinstance.cpp servernodeinstance.h

View File

@@ -223,8 +223,12 @@ QtcTool {
"instances/qmlpropertychangesnodeinstance.h", "instances/qmlpropertychangesnodeinstance.h",
"instances/qmlstatenodeinstance.cpp", "instances/qmlstatenodeinstance.cpp",
"instances/qmlstatenodeinstance.h", "instances/qmlstatenodeinstance.h",
"instances/quick3dmaterialnodeinstance.cpp",
"instances/quick3dmaterialnodeinstance.h",
"instances/quick3dnodeinstance.cpp", "instances/quick3dnodeinstance.cpp",
"instances/quick3dnodeinstance.h", "instances/quick3dnodeinstance.h",
"instances/quick3drenderablenodeinstance.cpp",
"instances/quick3drenderablenodeinstance.h",
"instances/quick3dtexturenodeinstance.cpp", "instances/quick3dtexturenodeinstance.cpp",
"instances/quick3dtexturenodeinstance.h", "instances/quick3dtexturenodeinstance.h",
"instances/qmltransitionnodeinstance.cpp", "instances/qmltransitionnodeinstance.cpp",