From f9ecc8b57ae9c09dcb57085174f66ac6897b6efa Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Thu, 15 Dec 2022 17:32:00 +0200 Subject: [PATCH] QmlDesigner: Ensure all View3Ds are rendered when one is If View3Ds share resources such as materials, changing such shared resource doesn't in all cases make all using View3Ds dirty until one of the views is rendered. For purposes of rendering 2D view, this is too late, as we determine the list of items to render before any is rendered. Fixed the issue by ensuring all View3D items in the scene are added to the list of items to render if any of them are added to that list. Fixes: QDS-8346 Change-Id: Ib18ce0d37978857efdb67e15976e1fecdc1b6c96 Reviewed-by: Mahmoud Badri Reviewed-by: Reviewed-by: Thomas Hartmann --- .../instances/nodeinstanceserver.cpp | 15 ++++++++++++ .../qml2puppet/instances/nodeinstanceserver.h | 1 + .../instances/qt5rendernodeinstanceserver.cpp | 24 +++++++++++++++---- 3 files changed, 36 insertions(+), 4 deletions(-) diff --git a/src/tools/qml2puppet/qml2puppet/instances/nodeinstanceserver.cpp b/src/tools/qml2puppet/qml2puppet/instances/nodeinstanceserver.cpp index d3209e4ccbe..05692d000bd 100644 --- a/src/tools/qml2puppet/qml2puppet/instances/nodeinstanceserver.cpp +++ b/src/tools/qml2puppet/qml2puppet/instances/nodeinstanceserver.cpp @@ -1043,6 +1043,21 @@ QList NodeInstanceServer::allGroupStateInstances() const return groups; } +QList NodeInstanceServer::allView3DInstances() const +{ + QList view3Ds; + std::copy_if(nodeInstances().cbegin(), + nodeInstances().cend(), + std::back_inserter(view3Ds), + [](const ServerNodeInstance &instance) { + return instance.isValid() + && ServerNodeInstance::isSubclassOf(instance.internalObject(), + QByteArrayLiteral("QQuick3DViewport")); + }); + + return view3Ds; +} + void NodeInstanceServer::setStateInstance(const ServerNodeInstance &stateInstance) { m_activeStateInstance = stateInstance; diff --git a/src/tools/qml2puppet/qml2puppet/instances/nodeinstanceserver.h b/src/tools/qml2puppet/qml2puppet/instances/nodeinstanceserver.h index 59236a236fc..70b0c841859 100644 --- a/src/tools/qml2puppet/qml2puppet/instances/nodeinstanceserver.h +++ b/src/tools/qml2puppet/qml2puppet/instances/nodeinstanceserver.h @@ -179,6 +179,7 @@ public: ServerNodeInstance rootNodeInstance() const; QList allGroupStateInstances() const; + QList allView3DInstances() const; void notifyPropertyChange(qint32 instanceid, const PropertyName &propertyName); diff --git a/src/tools/qml2puppet/qml2puppet/instances/qt5rendernodeinstanceserver.cpp b/src/tools/qml2puppet/qml2puppet/instances/qt5rendernodeinstanceserver.cpp index 07212ec4590..223a7249b1e 100644 --- a/src/tools/qml2puppet/qml2puppet/instances/qt5rendernodeinstanceserver.cpp +++ b/src/tools/qml2puppet/qml2puppet/instances/qt5rendernodeinstanceserver.cpp @@ -56,6 +56,7 @@ void Qt5RenderNodeInstanceServer::collectItemChangesAndSendChangeCommands() if (quickWindow() && nodeInstanceClient()->bytesToWrite() < 10000) { bool windowDirty = false; + bool hasView3D = false; foreach (QQuickItem *item, allItems()) { if (item) { if (Internal::QuickItemNodeInstance::unifiedRenderPath()) { @@ -65,8 +66,13 @@ void Qt5RenderNodeInstanceServer::collectItemChangesAndSendChangeCommands() } } else { if (hasInstanceForObject(item)) { - if (QQuickDesignerSupport::isDirty(item, QQuickDesignerSupport::ContentUpdateMask)) + if (QQuickDesignerSupport::isDirty(item, QQuickDesignerSupport::ContentUpdateMask)) { + if (!hasView3D && ServerNodeInstance::isSubclassOf( + item, QByteArrayLiteral("QQuick3DViewport"))) { + hasView3D = true; + } m_dirtyInstanceSet.insert(instanceForObject(item)); + } if (QQuickItem *effectParent = parentEffectItem(item)) { if ((QQuickDesignerSupport::isDirty( item, @@ -100,9 +106,19 @@ void Qt5RenderNodeInstanceServer::collectItemChangesAndSendChangeCommands() nodeInstanceClient()->pixmapChanged(createPixmapChangedCommand({rootNodeInstance()})); } else { if (!m_dirtyInstanceSet.isEmpty()) { - nodeInstanceClient()->pixmapChanged( - createPixmapChangedCommand(QtHelpers::toList(m_dirtyInstanceSet))); - m_dirtyInstanceSet.clear(); + auto renderList = QtHelpers::toList(m_dirtyInstanceSet); + + // If there is a View3D to be rendered, add all other View3Ds to be rendered + // as well, in case they share materials. + if (hasView3D) { + const QList view3Ds = allView3DInstances(); + for (auto &view3D : view3Ds) { + if (!m_dirtyInstanceSet.contains(view3D)) + renderList.append(view3D); + } + } + + nodeInstanceClient()->pixmapChanged(createPixmapChangedCommand(renderList)); } }