QmlDesigner: Avoid duplicate bundle material instance creation

When apply a material from the material bundle directly to a model in
the 3D scene, check frist if there is an existing material that has no
properties set, if so apply it instead of creating a new instance.
Also few tweaks.

Change-Id: I4ddadfd84442164b671645af5e4f5d9e8dcb7cb0
Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io>
This commit is contained in:
Mahmoud Badri
2022-09-22 15:04:04 +03:00
parent 0371478836
commit 70c4acae67
5 changed files with 136 additions and 62 deletions

View File

@@ -129,70 +129,23 @@ WidgetInfo MaterialBrowserView::widgetInfo()
MaterialBrowserBundleModel *matBrowserBundleModel = m_widget->materialBrowserBundleModel().data();
connect(matBrowserBundleModel, &MaterialBrowserBundleModel::applyToSelectedTriggered, this,
[&] (BundleMaterial *material, bool add) {
[&] (BundleMaterial *bundleMat, bool add) {
if (!m_selectedModel.isValid())
return;
m_bundleMaterialDropTarget = m_selectedModel;
m_bundleMaterialAddToSelected = add;
m_widget->materialBrowserBundleModel()->addMaterial(material);
ModelNode defaultMat = getBundleMaterialDefaultInstance(bundleMat->type());
if (defaultMat.isValid())
applyBundleMaterialToDropTarget(defaultMat);
else
m_widget->materialBrowserBundleModel()->addMaterial(bundleMat);
});
connect(matBrowserBundleModel, &MaterialBrowserBundleModel::addBundleMaterialToProjectRequested, this,
[&] (const QmlDesigner::NodeMetaInfo &metaInfo) {
ModelNode matLib = materialLibraryNode();
if (!matLib.isValid())
return;
executeInTransaction("MaterialBrowserView::widgetInfo", [&] {
ModelNode newMatNode = createModelNode(metaInfo.typeName(), metaInfo.majorVersion(),
metaInfo.minorVersion());
matLib.defaultNodeListProperty().reparentHere(newMatNode);
static QRegularExpression rgx("([A-Z])([a-z]*)");
QString newName = QString::fromLatin1(metaInfo.simplifiedTypeName()).replace(rgx, " \\1\\2").trimmed();
QString newId = model()->generateIdFromName(newName, "material");
newMatNode.setIdWithRefactoring(newId);
VariantProperty objNameProp = newMatNode.variantProperty("objectName");
objNameProp.setValue(newName);
if (m_bundleMaterialDropTarget.isValid()) {
QmlObjectNode qmlObjNode(m_bundleMaterialDropTarget);
if (m_bundleMaterialAddToSelected) {
// TODO: unify this logic as it exist elsewhere also
auto expToList = [](const QString &exp) {
QString copy = exp;
copy = copy.remove("[").remove("]");
QStringList tmp = copy.split(',', Qt::SkipEmptyParts);
for (QString &str : tmp)
str = str.trimmed();
return tmp;
};
auto listToExp = [](QStringList &stringList) {
if (stringList.size() > 1)
return QString("[" + stringList.join(",") + "]");
if (stringList.size() == 1)
return stringList.first();
return QString();
};
QStringList matList = expToList(qmlObjNode.expression("materials"));
matList.append(newMatNode.id());
QString updatedExp = listToExp(matList);
qmlObjNode.setBindingProperty("materials", updatedExp);
} else {
qmlObjNode.setBindingProperty("materials", newMatNode.id());
}
m_bundleMaterialDropTarget = {};
}
m_bundleMaterialAddToSelected = false;
});
applyBundleMaterialToDropTarget({}, metaInfo);
});
}
@@ -203,6 +156,72 @@ WidgetInfo MaterialBrowserView::widgetInfo()
tr("Material Browser"));
}
void MaterialBrowserView::applyBundleMaterialToDropTarget(const ModelNode &bundleMat,
const NodeMetaInfo &metaInfo)
{
if (!bundleMat.isValid() && !metaInfo.isValid())
return;
ModelNode matLib = materialLibraryNode();
if (!matLib.isValid())
return;
executeInTransaction("MaterialBrowserView::applyBundleMaterialToDropTarget", [&] {
ModelNode newMatNode;
if (metaInfo.isValid()) {
newMatNode = createModelNode(metaInfo.typeName(), metaInfo.majorVersion(),
metaInfo.minorVersion());
matLib.defaultNodeListProperty().reparentHere(newMatNode);
static QRegularExpression rgx("([A-Z])([a-z]*)");
QString newName = QString::fromLatin1(metaInfo.simplifiedTypeName()).replace(rgx, " \\1\\2").trimmed();
QString newId = model()->generateIdFromName(newName, "material");
newMatNode.setIdWithRefactoring(newId);
VariantProperty objNameProp = newMatNode.variantProperty("objectName");
objNameProp.setValue(newName);
} else {
newMatNode = bundleMat;
}
if (m_bundleMaterialDropTarget.isValid()) {
QmlObjectNode qmlObjNode(m_bundleMaterialDropTarget);
if (m_bundleMaterialAddToSelected) {
// TODO: unify this logic as it exist elsewhere also
auto expToList = [](const QString &exp) {
QString copy = exp;
copy = copy.remove("[").remove("]");
QStringList tmp = copy.split(',', Qt::SkipEmptyParts);
for (QString &str : tmp)
str = str.trimmed();
return tmp;
};
auto listToExp = [](QStringList &stringList) {
if (stringList.size() > 1)
return QString("[" + stringList.join(",") + "]");
if (stringList.size() == 1)
return stringList.first();
return QString();
};
QStringList matList = expToList(qmlObjNode.expression("materials"));
matList.append(newMatNode.id());
QString updatedExp = listToExp(matList);
qmlObjNode.setBindingProperty("materials", updatedExp);
} else {
qmlObjNode.setBindingProperty("materials", newMatNode.id());
}
m_bundleMaterialDropTarget = {};
m_bundleMaterialAddToSelected = false;
}
});
}
void MaterialBrowserView::modelAttached(Model *model)
{
AbstractView::modelAttached(model);
@@ -382,6 +401,28 @@ void QmlDesigner::MaterialBrowserView::loadPropertyGroups()
m_propertyGroupsLoaded = m_widget->materialBrowserModel()->loadPropertyGroups(matPropsPath);
}
ModelNode MaterialBrowserView::getBundleMaterialDefaultInstance(const TypeName &type)
{
const QList<ModelNode> materials = m_widget->materialBrowserModel()->materials();
for (const ModelNode &mat : materials) {
if (mat.type() == type) {
bool isDefault = true;
const QList<AbstractProperty> props = mat.properties();
for (const AbstractProperty &prop : props) {
if (prop.name() != "objectName") {
isDefault = false;
break;
}
}
if (isDefault)
return mat;
}
}
return {};
}
void MaterialBrowserView::importsChanged(const QList<Import> &addedImports, const QList<Import> &removedImports)
{
Q_UNUSED(addedImports)
@@ -420,7 +461,14 @@ void MaterialBrowserView::customNotification(const AbstractView *view, const QSt
m_widget->materialBrowserModel()->deleteSelectedMaterial();
} else if (identifier == "drop_bundle_material") {
m_bundleMaterialDropTarget = nodeList.first();
m_widget->materialBrowserBundleModel()->addMaterial(m_draggedBundleMaterial);
ModelNode defaultMat = getBundleMaterialDefaultInstance(m_draggedBundleMaterial->type());
if (defaultMat.isValid())
applyBundleMaterialToDropTarget(defaultMat);
else
m_widget->materialBrowserBundleModel()->addMaterial(m_draggedBundleMaterial);
m_draggedBundleMaterial = nullptr;
}
}