forked from qt-creator/qt-creator
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:
@@ -30,9 +30,10 @@ namespace QmlDesigner {
|
||||
BundleMaterial::BundleMaterial(QObject *parent,
|
||||
const QString &name,
|
||||
const QString &qml,
|
||||
const TypeName &type,
|
||||
const QUrl &icon,
|
||||
const QStringList &files)
|
||||
: QObject(parent), m_name(name), m_qml(qml), m_icon(icon), m_files(files) {}
|
||||
: QObject(parent), m_name(name), m_qml(qml), m_type(type), m_icon(icon), m_files(files) {}
|
||||
|
||||
bool BundleMaterial::filter(const QString &searchText)
|
||||
{
|
||||
@@ -54,6 +55,11 @@ QString BundleMaterial::qml() const
|
||||
return m_qml;
|
||||
}
|
||||
|
||||
TypeName BundleMaterial::type() const
|
||||
{
|
||||
return m_type;
|
||||
}
|
||||
|
||||
QStringList BundleMaterial::files() const
|
||||
{
|
||||
return m_files;
|
||||
|
@@ -25,6 +25,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "qmldesignercorelib_global.h"
|
||||
|
||||
#include <QDataStream>
|
||||
#include <QObject>
|
||||
#include <QUrl>
|
||||
@@ -43,6 +45,7 @@ public:
|
||||
BundleMaterial(QObject *parent,
|
||||
const QString &name,
|
||||
const QString &qml,
|
||||
const TypeName &type,
|
||||
const QUrl &icon,
|
||||
const QStringList &files);
|
||||
|
||||
@@ -50,6 +53,7 @@ public:
|
||||
|
||||
QUrl icon() const;
|
||||
QString qml() const;
|
||||
TypeName type() const;
|
||||
QStringList files() const;
|
||||
bool visible() const;
|
||||
|
||||
@@ -59,6 +63,7 @@ signals:
|
||||
private:
|
||||
QString m_name;
|
||||
QString m_qml;
|
||||
TypeName m_type;
|
||||
QUrl m_icon;
|
||||
QStringList m_files;
|
||||
|
||||
|
@@ -28,6 +28,7 @@
|
||||
#include "bundleimporter.h"
|
||||
#include "bundlematerial.h"
|
||||
#include "bundlematerialcategory.h"
|
||||
#include "qmldesignerconstants.h"
|
||||
#include "utils/qtcassert.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
@@ -121,6 +122,8 @@ void MaterialBrowserBundleModel::loadMaterialBundle()
|
||||
|
||||
m_matBundleExists = true;
|
||||
|
||||
const QString bundleId = m_matBundleObj.value("id").toString();
|
||||
|
||||
const QJsonObject catsObj = m_matBundleObj.value("categories").toObject();
|
||||
const QStringList categories = catsObj.keys();
|
||||
for (const QString &cat : categories) {
|
||||
@@ -136,8 +139,14 @@ void MaterialBrowserBundleModel::loadMaterialBundle()
|
||||
for (const auto /*QJson{Const,}ValueRef*/ &asset : assetsArr)
|
||||
files.append(asset.toString());
|
||||
|
||||
auto bundleMat = new BundleMaterial(category, mat, matObj.value("qml").toString(),
|
||||
QUrl::fromLocalFile(matBundleDir.filePath(matObj.value("icon").toString())), files);
|
||||
QUrl icon = QUrl::fromLocalFile(matBundleDir.filePath(matObj.value("icon").toString()));
|
||||
QString qml = matObj.value("qml").toString();
|
||||
TypeName type = QLatin1String("%1.%2.%3").arg(
|
||||
QLatin1String(Constants::COMPONENT_BUNDLES_FOLDER).mid(1),
|
||||
bundleId,
|
||||
qml.chopped(4)).toLatin1(); // chopped(4): remove .qml
|
||||
|
||||
auto bundleMat = new BundleMaterial(category, mat, qml, type, icon, files);
|
||||
|
||||
category->addBundleMaterial(bundleMat);
|
||||
}
|
||||
@@ -149,7 +158,7 @@ void MaterialBrowserBundleModel::loadMaterialBundle()
|
||||
for (const auto /*QJson{Const,}ValueRef*/ &file : sharedFilesArr)
|
||||
sharedFiles.append(file.toString());
|
||||
|
||||
m_importer = new Internal::BundleImporter(matBundleDir.path(), "MaterialBundle", sharedFiles);
|
||||
m_importer = new Internal::BundleImporter(matBundleDir.path(), bundleId, sharedFiles);
|
||||
connect(m_importer, &Internal::BundleImporter::importFinished, this, [&](const QmlDesigner::NodeMetaInfo &metaInfo) {
|
||||
if (metaInfo.isValid())
|
||||
emit addBundleMaterialToProjectRequested(metaInfo);
|
||||
@@ -223,7 +232,10 @@ void MaterialBrowserBundleModel::applyToSelected(BundleMaterial *mat, bool add)
|
||||
|
||||
void MaterialBrowserBundleModel::addMaterial(BundleMaterial *mat)
|
||||
{
|
||||
m_importer->importComponent(mat->qml(), mat->files());
|
||||
QString err = m_importer->importComponent(mat->qml(), mat->files());
|
||||
|
||||
if (!err.isEmpty())
|
||||
qWarning() << __FUNCTION__ << err;
|
||||
}
|
||||
|
||||
} // namespace QmlDesigner
|
||||
|
@@ -129,23 +129,47 @@ 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) {
|
||||
applyBundleMaterialToDropTarget({}, metaInfo);
|
||||
});
|
||||
}
|
||||
|
||||
return createWidgetInfo(m_widget.data(),
|
||||
"MaterialBrowser",
|
||||
WidgetInfo::LeftPane,
|
||||
0,
|
||||
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::widgetInfo", [&] {
|
||||
ModelNode newMatNode = createModelNode(metaInfo.typeName(), metaInfo.majorVersion(),
|
||||
executeInTransaction("MaterialBrowserView::applyBundleMaterialToDropTarget", [&] {
|
||||
ModelNode newMatNode;
|
||||
if (metaInfo.isValid()) {
|
||||
newMatNode = createModelNode(metaInfo.typeName(), metaInfo.majorVersion(),
|
||||
metaInfo.minorVersion());
|
||||
matLib.defaultNodeListProperty().reparentHere(newMatNode);
|
||||
|
||||
@@ -156,6 +180,9 @@ WidgetInfo MaterialBrowserView::widgetInfo()
|
||||
|
||||
VariantProperty objNameProp = newMatNode.variantProperty("objectName");
|
||||
objNameProp.setValue(newName);
|
||||
} else {
|
||||
newMatNode = bundleMat;
|
||||
}
|
||||
|
||||
if (m_bundleMaterialDropTarget.isValid()) {
|
||||
QmlObjectNode qmlObjNode(m_bundleMaterialDropTarget);
|
||||
@@ -188,19 +215,11 @@ WidgetInfo MaterialBrowserView::widgetInfo()
|
||||
} else {
|
||||
qmlObjNode.setBindingProperty("materials", newMatNode.id());
|
||||
}
|
||||
|
||||
m_bundleMaterialDropTarget = {};
|
||||
}
|
||||
|
||||
m_bundleMaterialAddToSelected = false;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
return createWidgetInfo(m_widget.data(),
|
||||
"MaterialBrowser",
|
||||
WidgetInfo::LeftPane,
|
||||
0,
|
||||
tr("Material Browser"));
|
||||
});
|
||||
}
|
||||
|
||||
void MaterialBrowserView::modelAttached(Model *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();
|
||||
|
||||
|
||||
ModelNode defaultMat = getBundleMaterialDefaultInstance(m_draggedBundleMaterial->type());
|
||||
if (defaultMat.isValid())
|
||||
applyBundleMaterialToDropTarget(defaultMat);
|
||||
else
|
||||
m_widget->materialBrowserBundleModel()->addMaterial(m_draggedBundleMaterial);
|
||||
|
||||
m_draggedBundleMaterial = nullptr;
|
||||
}
|
||||
}
|
||||
|
@@ -25,7 +25,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <abstractview.h>
|
||||
#include "abstractview.h"
|
||||
#include "nodemetainfo.h"
|
||||
|
||||
#include <QPointer>
|
||||
|
||||
@@ -67,6 +68,8 @@ private:
|
||||
void refreshModel(bool updateImages);
|
||||
bool isMaterial(const ModelNode &node) const;
|
||||
void loadPropertyGroups();
|
||||
void applyBundleMaterialToDropTarget(const ModelNode &bundleMat, const NodeMetaInfo &metaInfo = {});
|
||||
ModelNode getBundleMaterialDefaultInstance(const TypeName &type);
|
||||
|
||||
QPointer<MaterialBrowserWidget> m_widget;
|
||||
ModelNode m_bundleMaterialDropTarget;
|
||||
|
Reference in New Issue
Block a user