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 <mahmoud.badri@qt.io>
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
Miikka Heikkinen
2022-12-15 17:32:00 +02:00
parent 76565fa8d7
commit f9ecc8b57a
3 changed files with 36 additions and 4 deletions

View File

@@ -1043,6 +1043,21 @@ QList<ServerNodeInstance> NodeInstanceServer::allGroupStateInstances() const
return groups; return groups;
} }
QList<ServerNodeInstance> NodeInstanceServer::allView3DInstances() const
{
QList<ServerNodeInstance> 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) void NodeInstanceServer::setStateInstance(const ServerNodeInstance &stateInstance)
{ {
m_activeStateInstance = stateInstance; m_activeStateInstance = stateInstance;

View File

@@ -179,6 +179,7 @@ public:
ServerNodeInstance rootNodeInstance() const; ServerNodeInstance rootNodeInstance() const;
QList<ServerNodeInstance> allGroupStateInstances() const; QList<ServerNodeInstance> allGroupStateInstances() const;
QList<ServerNodeInstance> allView3DInstances() const;
void notifyPropertyChange(qint32 instanceid, const PropertyName &propertyName); void notifyPropertyChange(qint32 instanceid, const PropertyName &propertyName);

View File

@@ -56,6 +56,7 @@ void Qt5RenderNodeInstanceServer::collectItemChangesAndSendChangeCommands()
if (quickWindow() && nodeInstanceClient()->bytesToWrite() < 10000) { if (quickWindow() && nodeInstanceClient()->bytesToWrite() < 10000) {
bool windowDirty = false; bool windowDirty = false;
bool hasView3D = false;
foreach (QQuickItem *item, allItems()) { foreach (QQuickItem *item, allItems()) {
if (item) { if (item) {
if (Internal::QuickItemNodeInstance::unifiedRenderPath()) { if (Internal::QuickItemNodeInstance::unifiedRenderPath()) {
@@ -65,8 +66,13 @@ void Qt5RenderNodeInstanceServer::collectItemChangesAndSendChangeCommands()
} }
} else { } else {
if (hasInstanceForObject(item)) { 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)); m_dirtyInstanceSet.insert(instanceForObject(item));
}
if (QQuickItem *effectParent = parentEffectItem(item)) { if (QQuickItem *effectParent = parentEffectItem(item)) {
if ((QQuickDesignerSupport::isDirty( if ((QQuickDesignerSupport::isDirty(
item, item,
@@ -100,9 +106,19 @@ void Qt5RenderNodeInstanceServer::collectItemChangesAndSendChangeCommands()
nodeInstanceClient()->pixmapChanged(createPixmapChangedCommand({rootNodeInstance()})); nodeInstanceClient()->pixmapChanged(createPixmapChangedCommand({rootNodeInstance()}));
} else { } else {
if (!m_dirtyInstanceSet.isEmpty()) { if (!m_dirtyInstanceSet.isEmpty()) {
nodeInstanceClient()->pixmapChanged( auto renderList = QtHelpers::toList(m_dirtyInstanceSet);
createPixmapChangedCommand(QtHelpers::toList(m_dirtyInstanceSet)));
m_dirtyInstanceSet.clear(); // 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<ServerNodeInstance> view3Ds = allView3DInstances();
for (auto &view3D : view3Ds) {
if (!m_dirtyInstanceSet.contains(view3D))
renderList.append(view3D);
}
}
nodeInstanceClient()->pixmapChanged(createPixmapChangedCommand(renderList));
} }
} }