From 5544cdc276612de1c1672fc89a808e4f471f713f Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Fri, 25 Nov 2022 17:01:53 +0200 Subject: [PATCH] QmlDesigner: Don't create duplicate default texture instance Whenever an operation involving an asset image would result in creation of a new texture node, it now checks first if a matching texture node already exists and uses that instead. Fixes: QDS-8435 Change-Id: I3d091aafcd09afdec897bc4da79789c1d84056e8 Reviewed-by: Mahmoud Badri --- .../contentlibrary/contentlibraryview.cpp | 23 ++++++++++----- .../materialbrowser/materialbrowserview.cpp | 4 +++ .../propertyeditor/propertyeditorvalue.cpp | 28 +++++++++++++------ .../designercore/include/abstractview.h | 1 + .../designercore/model/abstractview.cpp | 24 ++++++++++++++++ 5 files changed, 64 insertions(+), 16 deletions(-) diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.cpp b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.cpp index e9221b160d3..ae1d87276bd 100644 --- a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.cpp +++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.cpp @@ -75,20 +75,29 @@ WidgetInfo ContentLibraryView::widgetInfo() return; NodeMetaInfo metaInfo = model()->metaInfo("QtQuick3D.Texture"); - ModelNode newTexNode = createModelNode("QtQuick3D.Texture", metaInfo.majorVersion(), - metaInfo.minorVersion()); - newTexNode.validId(); - VariantProperty sourceProp = newTexNode.variantProperty("source"); - sourceProp.setValue(QLatin1String("images/%1").arg(texPath.split('/').last())); - matLib.defaultNodeListProperty().reparentHere(newTexNode); + + QString sourceVal = QLatin1String("images/%1").arg(texPath.split('/').last()); + ModelNode texNode = getTextureDefaultInstance(sourceVal); + if (!texNode.isValid()) { + texNode = createModelNode("QtQuick3D.Texture", metaInfo.majorVersion(), + metaInfo.minorVersion()); + texNode.validId(); + VariantProperty sourceProp = texNode.variantProperty("source"); + sourceProp.setValue(sourceVal); + matLib.defaultNodeListProperty().reparentHere(texNode); + } // assign the texture as scene environment's light probe if (mode == ContentLibraryWidget::AddTextureMode::LightProbe && m_activeSceneEnv.isValid()) { BindingProperty lightProbeProp = m_activeSceneEnv.bindingProperty("lightProbe"); - lightProbeProp.setExpression(newTexNode.id()); + lightProbeProp.setExpression(texNode.id()); VariantProperty bgModeProp = m_activeSceneEnv.variantProperty("backgroundMode"); bgModeProp.setValue(QVariant::fromValue(Enumeration("SceneEnvironment", "SkyBox"))); } + QTimer::singleShot(0, this, [this, texNode]() { + if (model() && texNode.isValid()) + emitCustomNotification("selected_texture_changed", {texNode}); + }); }); }); diff --git a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.cpp b/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.cpp index 33bf07c2409..cba8f32199f 100644 --- a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.cpp +++ b/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.cpp @@ -435,6 +435,10 @@ void MaterialBrowserView::customNotification(const AbstractView *view, int idx = m_widget->materialBrowserModel()->materialIndex(nodeList.first()); if (idx != -1) m_widget->materialBrowserModel()->selectMaterial(idx); + } else if (identifier == "selected_texture_changed") { + int idx = m_widget->materialBrowserTexturesModel()->textureIndex(nodeList.first()); + if (idx != -1) + m_widget->materialBrowserTexturesModel()->selectTexture(idx); } else if (identifier == "refresh_material_browser") { QTimer::singleShot(0, model(), [this]() { refreshModel(true); diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.cpp b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.cpp index 28ee93cbb2d..6bca126ae69 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.cpp +++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.cpp @@ -500,18 +500,28 @@ void PropertyEditorValue::commitDrop(const QString &dropData) m_modelNode.view()->executeInTransaction(__FUNCTION__, [&] { QmlDesigner::ModelNode texture = m_modelNode.view()->modelNodeForInternalId(dropData.toInt()); if (!texture || !texture.metaInfo().isQtQuick3DTexture()) { - // create a texture node - QmlDesigner::NodeMetaInfo metaInfo = m_modelNode.view()->model()->metaInfo("QtQuick3D.Texture"); - texture = m_modelNode.view()->createModelNode("QtQuick3D.Texture", metaInfo.majorVersion(), - metaInfo.minorVersion()); - texture.validId(); - m_modelNode.view()->materialLibraryNode().defaultNodeListProperty().reparentHere(texture); - - // set texture source Utils::FilePath imagePath = Utils::FilePath::fromString(dropData); Utils::FilePath currFilePath = QmlDesigner::DocumentManager::currentFilePath(); + QString sourceVal = imagePath.relativePathFrom(currFilePath).toString(); + texture = m_modelNode.view()->getTextureDefaultInstance(sourceVal); + + if (!texture.isValid()) { + // create a texture node + QmlDesigner::NodeMetaInfo metaInfo = m_modelNode.view()->model()->metaInfo("QtQuick3D.Texture"); + texture = m_modelNode.view()->createModelNode("QtQuick3D.Texture", metaInfo.majorVersion(), + metaInfo.minorVersion()); + texture.validId(); + m_modelNode.view()->materialLibraryNode().defaultNodeListProperty().reparentHere(texture); + } + + // set texture source QmlDesigner::VariantProperty srcProp = texture.variantProperty("source"); - srcProp.setValue(imagePath.relativePathFrom(currFilePath).toString()); + srcProp.setValue(sourceVal); + + QTimer::singleShot(0, this, [this, texture]() { + if (m_modelNode.isValid() && texture.isValid() && m_modelNode.view()) + m_modelNode.view()->emitCustomNotification("selected_texture_changed", {texture}); + }); } // assign the texture to the property diff --git a/src/plugins/qmldesigner/designercore/include/abstractview.h b/src/plugins/qmldesigner/designercore/include/abstractview.h index 2afc56e6e0a..55f7ddcf9d0 100644 --- a/src/plugins/qmldesigner/designercore/include/abstractview.h +++ b/src/plugins/qmldesigner/designercore/include/abstractview.h @@ -230,6 +230,7 @@ public: ModelNode materialLibraryNode(); ModelNode active3DSceneNode(); void assignMaterialTo3dModel(const ModelNode &modelNode, const ModelNode &materialNode = {}); + ModelNode getTextureDefaultInstance(const QString &source); const NodeInstanceView *nodeInstanceView() const; RewriterView *rewriterView() const; diff --git a/src/plugins/qmldesigner/designercore/model/abstractview.cpp b/src/plugins/qmldesigner/designercore/model/abstractview.cpp index fe5d5a18ca8..20d39362a0e 100644 --- a/src/plugins/qmldesigner/designercore/model/abstractview.cpp +++ b/src/plugins/qmldesigner/designercore/model/abstractview.cpp @@ -915,6 +915,30 @@ void AbstractView::assignMaterialTo3dModel(const ModelNode &modelNode, const Mod modelMatsProp.setExpression(newMaterialNode.id()); } +ModelNode AbstractView::getTextureDefaultInstance(const QString &source) +{ + ModelNode matLib = materialLibraryNode(); + if (!matLib.isValid()) + return {}; + + const QList matLibNodes = matLib.directSubModelNodes(); + for (const ModelNode &tex : matLibNodes) { + if (tex.isValid() && tex.metaInfo().isQtQuick3DTexture()) { + const QList props = tex.properties(); + if (props.size() != 1) + continue; + const AbstractProperty &prop = props[0]; + if (prop.name() == "source" && prop.isVariantProperty() + && prop.toVariantProperty().value().toString() == source) { + return tex; + } + } + } + + return {}; +} + + ModelNode AbstractView::currentStateNode() const { if (model())