diff options
author | Miikka Heikkinen <miikka.heikkinen@qt.io> | 2022-06-13 14:51:27 +0300 |
---|---|---|
committer | Miikka Heikkinen <miikka.heikkinen@qt.io> | 2022-06-16 13:53:43 +0000 |
commit | 9c3636af497f8bdb2745bf85cc0286c9c6675987 (patch) | |
tree | 7c429f23a29451c7302eaac21efe9e36a7a380fd | |
parent | 50aadacb6e670597fc308d409bcdae96e7efa9c0 (diff) | |
download | qt-creator-9c3636af497f8bdb2745bf85cc0286c9c6675987.tar.gz |
QmlDesigner: Ensure materials render properly after puppet reset
This is a workaround for quick3d issue QTBUG-103316, where
material library materials for editor are properly initialized only
if the first encountered View3D in the scene is also rendered first.
Fixes: QDS-7084
Change-Id: I8bb6a8e6bfe2fcffddfe86f92157d386fdf4095d
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
-rw-r--r-- | share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp | 42 | ||||
-rw-r--r-- | share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.h | 1 |
2 files changed, 42 insertions, 1 deletions
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp index d614901ca9..97a60b5405 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp @@ -848,6 +848,18 @@ void Qt5InformationNodeInstanceServer::updateActiveSceneToEditView3D(bool timerC m_activeSceneIdUpdateTimer.stop(); } + // We may have to substitute another scene to work around QTBUG-103316 + // The worked around issue is that if a material is used in multiple scenes, there is some + // kind of ownership for it in the first View3D that uses it, so if that view is not rendered + // first, the material will not be properly initialized for other views using it. + // To make materials work properly, we ensure that views are rendered at least once in the + // order they appear in the scene. + if (!m_priorityView3DsToRender.isEmpty()) { + QObject *sceneRoot = find3DSceneRoot(m_priorityView3DsToRender.first()); + if (sceneRoot) + activeSceneVar = objectToVariant(sceneRoot); + } + QMetaObject::invokeMethod(m_editView3DData.rootItem, "setActiveScene", Qt::QueuedConnection, Q_ARG(QVariant, activeSceneVar), Q_ARG(QVariant, QVariant::fromValue(sceneId))); @@ -1010,7 +1022,7 @@ void Qt5InformationNodeInstanceServer::doRender3DEditView() // If we have only one or no render queued, send the result to the creator side. // Otherwise, we'll hold on that until we have rendered all pending frames to ensure sent // results are correct. - if (m_need3DEditViewRender <= 1) { + if (m_priorityView3DsToRender.isEmpty() && m_need3DEditViewRender <= 1) { nodeInstanceClient()->handlePuppetToCreatorCommand({PuppetToCreatorCommand::Render3DView, QVariant::fromValue(imgContainer)}); #ifdef QUICK3D_PARTICLES_MODULE @@ -1021,6 +1033,25 @@ void Qt5InformationNodeInstanceServer::doRender3DEditView() #endif } + if (!m_priorityView3DsToRender.isEmpty()) { + static int tryCounter = 0; + QObject *sceneRoot = find3DSceneRoot(m_priorityView3DsToRender.first()); + bool needAnotherRender = false; + if (sceneRoot) { + // Active scene is updated asynchronously, so verify we are actually rendering + // the correct priority scene + QObject *activeScene = QQmlProperty::read(m_editView3DData.rootItem, "activeScene").value<QObject *>(); + needAnotherRender = activeScene != sceneRoot; + } + + if (!needAnotherRender || ++tryCounter > 10) { + m_priorityView3DsToRender.removeFirst(); + updateActiveSceneToEditView3D(); + tryCounter = 0; + } + ++m_need3DEditViewRender; + } + if (m_need3DEditViewRender > 0) { // We queue another render even if the requested render count was one, because another // render is needed to ensure gizmo geometries are properly updated. @@ -1057,6 +1088,13 @@ void Qt5InformationNodeInstanceServer::doRenderModelNodeImageView() { // This crashes on Qt 6.0.x due to QtQuick3D issue, so the preview generation is disabled #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) || QT_VERSION >= QT_VERSION_CHECK(6, 1, 0) + if (!m_priorityView3DsToRender.isEmpty()) { + // Postpone any preview renders until we have rendered the priority views to ensure + // materials in material library are properly initialized + m_renderModelNodeImageViewTimer.start(17); + return; + } + RequestModelNodePreviewImageCommand cmd = *m_modelNodePreviewImageCommands.begin(); ServerNodeInstance instance; if (cmd.renderItemId() >= 0) @@ -1574,6 +1612,8 @@ void Qt5InformationNodeInstanceServer::add3DViewPorts(const QList<ServerNodeInst for (const ServerNodeInstance &instance : instanceList) { if (instance.isSubclassOf("QQuick3DViewport")) { QObject *obj = instance.internalObject(); + if (!m_editView3DSetupDone) + m_priorityView3DsToRender.append(obj); // Workaround for quick3d bug QTBUG-103316 if (!m_view3Ds.contains(obj)) { m_view3Ds << obj; QObject::connect(obj, SIGNAL(widthChanged()), this, SLOT(handleView3DSizeChange())); diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.h b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.h index 9f6e450690..c85a2730c4 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.h +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.h @@ -165,6 +165,7 @@ private: QSet<QObject *> m_view3Ds; QMultiHash<QObject *, QObject *> m_3DSceneMap; // key: scene root, value: node QObject *m_active3DView = nullptr; + QList<QObject *> m_priorityView3DsToRender; QObject *m_active3DScene = nullptr; QSet<ServerNodeInstance> m_parentChangedSet; QList<ServerNodeInstance> m_completedComponentList; |