From 91998cd80aa4c248c250276053a6b1c9dc032168 Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Tue, 10 Jan 2023 14:12:18 +0200 Subject: [PATCH] QmlDesigner: When changing material type, copy base color All material types have a so called base color that determines the diffuse color of the material, though the property is named differently in different material types: DefaultMaterial: diffuseColor PrincipledMaterial: baseColor SpecularGlossyMaterial: albedoColor When changing a material type in material editor, if the base color or the corresponding base map properties have been set, the values are copied to the corresponding property in the new type. Fixes: QDS-8738 Change-Id: Ia8e767ebf9b2d9026ff107e4245b37a788fd98d4 Reviewed-by: Mahmoud Badri Reviewed-by: Thomas Hartmann --- .../materialeditorcontextobject.cpp | 84 ++++++++++++++++++- 1 file changed, 83 insertions(+), 1 deletion(-) diff --git a/src/plugins/qmldesigner/components/materialeditor/materialeditorcontextobject.cpp b/src/plugins/qmldesigner/components/materialeditor/materialeditorcontextobject.cpp index 3f788e7f3fd..22e6964f60e 100644 --- a/src/plugins/qmldesigner/components/materialeditor/materialeditorcontextobject.cpp +++ b/src/plugins/qmldesigner/components/materialeditor/materialeditorcontextobject.cpp @@ -4,13 +4,16 @@ #include "materialeditorcontextobject.h" #include +#include +#include #include #include #include #include #include #include -#include +#include +#include #include #include @@ -129,6 +132,48 @@ void MaterialEditorContextObject::changeTypeName(const QString &typeName) incompatibleProperties.append(property.name()); } + // When switching between material types, copy base (diffuse) color and map properties of + // source type into corresponding properties of the target type. + const QList baseColors = {"baseColor", "diffuseColor", "albedoColor"}; + const QList baseMaps = {"baseColorMap", "diffuseMap", "albedoMap"}; + int sourceIndex = -1; + int targetIndex = -1; + NodeMetaInfo oldMetaInfo = m_selectedMaterial.metaInfo(); + struct CopyData { + CopyData() {}; + CopyData(PropertyName n) : name(n) {} + PropertyName name; + QVariant value; + bool isBinding = false; + }; + QHash copyMap; + + if (oldMetaInfo.isQtQuick3DPrincipledMaterial()) + sourceIndex = 0; + else if (oldMetaInfo.isQtQuick3DDefaultMaterial()) + sourceIndex = 1; + else if (oldMetaInfo.isQtQuick3DSpecularGlossyMaterial()) + sourceIndex = 2; + + if (metaInfo.isQtQuick3DPrincipledMaterial()) + targetIndex = 0; + else if (metaInfo.isQtQuick3DDefaultMaterial()) + targetIndex = 1; + else if (metaInfo.isQtQuick3DSpecularGlossyMaterial()) + targetIndex = 2; + + if (sourceIndex >= 0 && targetIndex >= 0) { + if (incompatibleProperties.contains(baseColors[sourceIndex])) { + copyMap.insert(baseColors[sourceIndex], baseColors[targetIndex]); + incompatibleProperties.removeOne(baseColors[sourceIndex]); + } + if (incompatibleProperties.contains(baseMaps[sourceIndex])) { + copyMap.insert(baseMaps[sourceIndex], baseMaps[targetIndex]); + incompatibleProperties.removeOne(baseMaps[sourceIndex]); + } + } + const auto ©Keys = copyMap.keys(); + Utils::sort(incompatibleProperties); // Create a dialog showing incompatible properties and signals @@ -159,10 +204,47 @@ void MaterialEditorContextObject::changeTypeName(const QString &typeName) m_selectedMaterial.removeProperty(p); } + if (!copyKeys.isEmpty()) { + // Copy mapped properties to new name. Note that this will only copy the base + // property value and adjust the keyframe groups. Any other bindings related + // to the property will be ignored. + const QList timeLines = QmlObjectNode(m_selectedMaterial).allTimelines(); + for (const auto &key : std::as_const(copyKeys)) { + CopyData ©Data = copyMap[key]; + for (const auto &timeLineNode : timeLines) { + QmlTimeline timeLine(timeLineNode); + if (timeLine.hasKeyframeGroup(m_selectedMaterial, key)) { + QmlTimelineKeyframeGroup group = timeLine.keyframeGroup(m_selectedMaterial, + key); + group.setPropertyName(copyData.name); + } + } + // Property value itself cannot be copied until type has been changed, so store it + AbstractProperty prop = m_selectedMaterial.property(key); + if (prop.isValid()) { + if (prop.isBindingProperty()) { + copyData.isBinding = true; + copyData.value = prop.toBindingProperty().expression(); + } else { + copyData.value = prop.toVariantProperty().value(); + } + } + m_selectedMaterial.removeProperty(key); + } + } + if (m_selectedMaterial.isRootNode()) rewriterView->changeRootNodeType(metaInfo.typeName(), metaInfo.majorVersion(), metaInfo.minorVersion()); else m_selectedMaterial.changeType(metaInfo.typeName(), metaInfo.majorVersion(), metaInfo.minorVersion()); + + for (const auto &key : copyKeys) { + const CopyData ©Data = copyMap[key]; + if (copyData.isBinding) + m_selectedMaterial.bindingProperty(copyData.name).setExpression(copyData.value.toString()); + else + m_selectedMaterial.variantProperty(copyData.name).setValue(copyData.value); + } }); }