2022-08-19 15:59:36 +02:00
|
|
|
// Copyright (C) 2022 The Qt Company Ltd.
|
|
|
|
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
|
2022-03-18 17:28:28 +02:00
|
|
|
|
|
|
|
|
#include "materialbrowserview.h"
|
2022-08-09 12:56:47 +03:00
|
|
|
#include "bindingproperty.h"
|
2022-09-01 15:03:01 +03:00
|
|
|
#include "bundlematerial.h"
|
2022-03-18 17:28:28 +02:00
|
|
|
#include "materialbrowsermodel.h"
|
2022-08-24 13:11:33 +02:00
|
|
|
#include "materialbrowserwidget.h"
|
2022-09-01 15:03:01 +03:00
|
|
|
#include "materialbrowserbundlemodel.h"
|
2022-03-18 17:28:28 +02:00
|
|
|
#include "nodeabstractproperty.h"
|
2022-08-12 11:47:36 +03:00
|
|
|
#include "nodemetainfo.h"
|
2022-03-18 17:28:28 +02:00
|
|
|
#include "qmlobjectnode.h"
|
|
|
|
|
#include "variantproperty.h"
|
2022-08-09 12:56:47 +03:00
|
|
|
|
2022-03-18 17:28:28 +02:00
|
|
|
#include <coreplugin/icore.h>
|
2022-08-09 12:56:47 +03:00
|
|
|
#include <designmodecontext.h>
|
2022-03-18 17:28:28 +02:00
|
|
|
#include <nodeinstanceview.h>
|
2022-08-24 13:11:33 +02:00
|
|
|
#include <nodemetainfo.h>
|
2022-09-01 15:03:01 +03:00
|
|
|
#include <nodelistproperty.h>
|
2022-03-18 17:28:28 +02:00
|
|
|
#include <qmldesignerconstants.h>
|
|
|
|
|
|
|
|
|
|
#include <QQuickItem>
|
2022-09-01 15:03:01 +03:00
|
|
|
#include <QRegularExpression>
|
|
|
|
|
#include <QTimer>
|
2022-03-18 17:28:28 +02:00
|
|
|
|
|
|
|
|
namespace QmlDesigner {
|
|
|
|
|
|
2022-09-15 13:07:45 +02:00
|
|
|
MaterialBrowserView::MaterialBrowserView() {}
|
2022-03-18 17:28:28 +02:00
|
|
|
|
|
|
|
|
MaterialBrowserView::~MaterialBrowserView()
|
|
|
|
|
{}
|
|
|
|
|
|
|
|
|
|
bool MaterialBrowserView::hasWidget() const
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
WidgetInfo MaterialBrowserView::widgetInfo()
|
|
|
|
|
{
|
|
|
|
|
if (m_widget.isNull()) {
|
2022-08-04 12:40:06 +03:00
|
|
|
m_widget = new MaterialBrowserWidget(this);
|
|
|
|
|
|
|
|
|
|
auto matEditorContext = new Internal::MaterialBrowserContext(m_widget.data());
|
|
|
|
|
Core::ICore::addContextObject(matEditorContext);
|
|
|
|
|
|
2022-05-25 21:42:15 +03:00
|
|
|
MaterialBrowserModel *matBrowserModel = m_widget->materialBrowserModel().data();
|
|
|
|
|
|
|
|
|
|
// custom notifications below are sent to the MaterialEditor
|
|
|
|
|
|
|
|
|
|
connect(matBrowserModel, &MaterialBrowserModel::selectedIndexChanged, this, [&] (int idx) {
|
|
|
|
|
ModelNode matNode = m_widget->materialBrowserModel()->materialAt(idx);
|
|
|
|
|
emitCustomNotification("selected_material_changed", {matNode}, {});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
connect(matBrowserModel, &MaterialBrowserModel::applyToSelectedTriggered, this,
|
|
|
|
|
[&] (const ModelNode &material, bool add) {
|
|
|
|
|
emitCustomNotification("apply_to_selected_triggered", {material}, {add});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
connect(matBrowserModel, &MaterialBrowserModel::renameMaterialTriggered, this,
|
|
|
|
|
[&] (const ModelNode &material, const QString &newName) {
|
|
|
|
|
emitCustomNotification("rename_material", {material}, {newName});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
connect(matBrowserModel, &MaterialBrowserModel::addNewMaterialTriggered, this, [&] {
|
|
|
|
|
emitCustomNotification("add_new_material");
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
connect(matBrowserModel, &MaterialBrowserModel::duplicateMaterialTriggered, this,
|
|
|
|
|
[&] (const ModelNode &material) {
|
|
|
|
|
emitCustomNotification("duplicate_material", {material});
|
|
|
|
|
});
|
2022-08-09 12:56:47 +03:00
|
|
|
|
|
|
|
|
connect(matBrowserModel, &MaterialBrowserModel::pasteMaterialPropertiesTriggered, this,
|
2022-08-12 11:47:36 +03:00
|
|
|
[&] (const ModelNode &material, const QList<AbstractProperty> &props, bool all) {
|
2022-08-09 12:56:47 +03:00
|
|
|
QmlObjectNode mat(material);
|
|
|
|
|
executeInTransaction(__FUNCTION__, [&] {
|
2022-08-12 11:47:36 +03:00
|
|
|
if (all) { // all material properties copied
|
|
|
|
|
// remove current properties
|
|
|
|
|
const PropertyNameList propNames = material.propertyNames();
|
|
|
|
|
for (const PropertyName &propName : propNames) {
|
|
|
|
|
if (propName != "objectName")
|
|
|
|
|
mat.removeProperty(propName);
|
|
|
|
|
}
|
2022-08-09 12:56:47 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// apply pasted properties
|
|
|
|
|
for (const AbstractProperty &prop : props) {
|
|
|
|
|
if (prop.name() == "objectName")
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (prop.isVariantProperty())
|
|
|
|
|
mat.setVariantProperty(prop.name(), prop.toVariantProperty().value());
|
|
|
|
|
else if (prop.isBindingProperty())
|
|
|
|
|
mat.setBindingProperty(prop.name(), prop.toBindingProperty().expression());
|
2022-09-26 14:31:50 +03:00
|
|
|
else if (!all)
|
|
|
|
|
mat.removeProperty(prop.name());
|
2022-08-09 12:56:47 +03:00
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
});
|
2022-09-01 15:03:01 +03:00
|
|
|
|
|
|
|
|
connect(m_widget, &MaterialBrowserWidget::bundleMaterialDragStarted, this,
|
|
|
|
|
[&] (QmlDesigner::BundleMaterial *bundleMat) {
|
|
|
|
|
m_draggedBundleMaterial = bundleMat;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
MaterialBrowserBundleModel *matBrowserBundleModel = m_widget->materialBrowserBundleModel().data();
|
|
|
|
|
|
|
|
|
|
connect(matBrowserBundleModel, &MaterialBrowserBundleModel::applyToSelectedTriggered, this,
|
2022-09-22 15:04:04 +03:00
|
|
|
[&] (BundleMaterial *bundleMat, bool add) {
|
2022-09-01 15:03:01 +03:00
|
|
|
if (!m_selectedModel.isValid())
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
m_bundleMaterialDropTarget = m_selectedModel;
|
|
|
|
|
m_bundleMaterialAddToSelected = add;
|
2022-09-22 15:04:04 +03:00
|
|
|
|
|
|
|
|
ModelNode defaultMat = getBundleMaterialDefaultInstance(bundleMat->type());
|
|
|
|
|
if (defaultMat.isValid())
|
|
|
|
|
applyBundleMaterialToDropTarget(defaultMat);
|
|
|
|
|
else
|
|
|
|
|
m_widget->materialBrowserBundleModel()->addMaterial(bundleMat);
|
2022-09-01 15:03:01 +03:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
connect(matBrowserBundleModel, &MaterialBrowserBundleModel::addBundleMaterialToProjectRequested, this,
|
|
|
|
|
[&] (const QmlDesigner::NodeMetaInfo &metaInfo) {
|
2022-09-22 15:04:04 +03:00
|
|
|
applyBundleMaterialToDropTarget({}, metaInfo);
|
2022-09-01 15:03:01 +03:00
|
|
|
});
|
2022-03-18 17:28:28 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return createWidgetInfo(m_widget.data(),
|
|
|
|
|
"MaterialBrowser",
|
|
|
|
|
WidgetInfo::LeftPane,
|
|
|
|
|
0,
|
|
|
|
|
tr("Material Browser"));
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-22 15:04:04 +03:00
|
|
|
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();
|
2022-09-22 16:36:53 +03:00
|
|
|
if (newName.endsWith(" Material"))
|
|
|
|
|
newName.chop(9); // remove trailing " Material"
|
2022-09-22 15:04:04 +03:00
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-18 17:28:28 +02:00
|
|
|
void MaterialBrowserView::modelAttached(Model *model)
|
|
|
|
|
{
|
|
|
|
|
AbstractView::modelAttached(model);
|
|
|
|
|
|
|
|
|
|
m_widget->clearSearchFilter();
|
2022-08-24 13:11:33 +02:00
|
|
|
m_widget->materialBrowserModel()->setHasMaterialRoot(
|
|
|
|
|
rootModelNode().metaInfo().isQtQuick3DMaterial());
|
2022-03-18 17:28:28 +02:00
|
|
|
m_hasQuick3DImport = model->hasImport("QtQuick3D");
|
2022-06-17 14:10:03 +03:00
|
|
|
|
2022-08-22 16:09:42 +03:00
|
|
|
loadPropertyGroups();
|
|
|
|
|
|
2022-06-17 14:10:03 +03:00
|
|
|
// Project load is already very busy and may even trigger puppet reset, so let's wait a moment
|
|
|
|
|
// before refreshing the model
|
|
|
|
|
QTimer::singleShot(1000, this, [this]() {
|
2022-06-16 15:30:25 +03:00
|
|
|
refreshModel(true);
|
|
|
|
|
});
|
2022-03-18 17:28:28 +02:00
|
|
|
}
|
|
|
|
|
|
2022-06-16 15:30:25 +03:00
|
|
|
void MaterialBrowserView::refreshModel(bool updateImages)
|
2022-03-18 17:28:28 +02:00
|
|
|
{
|
2022-06-28 12:38:12 +03:00
|
|
|
if (!model() || !model()->nodeInstanceView())
|
|
|
|
|
return;
|
|
|
|
|
|
2022-03-18 17:28:28 +02:00
|
|
|
ModelNode matLib = modelNodeForId(Constants::MATERIAL_LIB_ID);
|
|
|
|
|
QList <ModelNode> materials;
|
|
|
|
|
|
|
|
|
|
if (m_hasQuick3DImport && matLib.isValid()) {
|
|
|
|
|
const QList <ModelNode> matLibNodes = matLib.directSubModelNodes();
|
|
|
|
|
for (const ModelNode &node : matLibNodes) {
|
|
|
|
|
if (isMaterial(node))
|
|
|
|
|
materials.append(node);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m_widget->materialBrowserModel()->setMaterials(materials, m_hasQuick3DImport);
|
|
|
|
|
|
2022-06-16 15:30:25 +03:00
|
|
|
if (updateImages) {
|
|
|
|
|
for (const ModelNode &node : std::as_const(materials))
|
|
|
|
|
model()->nodeInstanceView()->previewImageDataForGenericNode(node, {});
|
|
|
|
|
}
|
2022-03-18 17:28:28 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool MaterialBrowserView::isMaterial(const ModelNode &node) const
|
|
|
|
|
{
|
2022-08-24 13:11:33 +02:00
|
|
|
return node.metaInfo().isQtQuick3DMaterial();
|
2022-03-18 17:28:28 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MaterialBrowserView::modelAboutToBeDetached(Model *model)
|
|
|
|
|
{
|
2022-08-01 14:29:09 +03:00
|
|
|
m_widget->materialBrowserModel()->setMaterials({}, m_hasQuick3DImport);
|
|
|
|
|
|
2022-03-18 17:28:28 +02:00
|
|
|
AbstractView::modelAboutToBeDetached(model);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MaterialBrowserView::selectedNodesChanged(const QList<ModelNode> &selectedNodeList,
|
2022-07-07 18:04:18 +02:00
|
|
|
[[maybe_unused]] const QList<ModelNode> &lastSelectedNodeList)
|
2022-03-18 17:28:28 +02:00
|
|
|
{
|
2022-09-01 15:03:01 +03:00
|
|
|
m_selectedModel = {};
|
2022-03-18 17:28:28 +02:00
|
|
|
|
|
|
|
|
for (const ModelNode &node : selectedNodeList) {
|
2022-08-24 13:11:33 +02:00
|
|
|
if (node.metaInfo().isQtQuick3DModel()) {
|
2022-09-01 15:03:01 +03:00
|
|
|
m_selectedModel = node;
|
2022-03-18 17:28:28 +02:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-01 15:03:01 +03:00
|
|
|
m_widget->materialBrowserModel()->setHasModelSelection(m_selectedModel.isValid());
|
2022-05-24 14:14:14 +03:00
|
|
|
|
|
|
|
|
if (!m_autoSelectModelMaterial)
|
|
|
|
|
return;
|
|
|
|
|
|
2022-09-01 15:03:01 +03:00
|
|
|
if (selectedNodeList.size() > 1 || !m_selectedModel.isValid())
|
2022-03-18 17:28:28 +02:00
|
|
|
return;
|
|
|
|
|
|
2022-09-01 15:03:01 +03:00
|
|
|
QmlObjectNode qmlObjNode(m_selectedModel);
|
2022-03-18 17:28:28 +02:00
|
|
|
QString matExp = qmlObjNode.expression("materials");
|
|
|
|
|
if (matExp.isEmpty())
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
QString matId = matExp.remove('[').remove(']').split(',', Qt::SkipEmptyParts).at(0);
|
|
|
|
|
ModelNode mat = modelNodeForId(matId);
|
|
|
|
|
if (!mat.isValid())
|
|
|
|
|
return;
|
|
|
|
|
|
2022-05-24 14:14:14 +03:00
|
|
|
// if selected object is a model, select its material in the material browser and editor
|
2022-03-18 17:28:28 +02:00
|
|
|
int idx = m_widget->materialBrowserModel()->materialIndex(mat);
|
|
|
|
|
m_widget->materialBrowserModel()->selectMaterial(idx);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MaterialBrowserView::modelNodePreviewPixmapChanged(const ModelNode &node, const QPixmap &pixmap)
|
|
|
|
|
{
|
|
|
|
|
if (isMaterial(node))
|
|
|
|
|
m_widget->updateMaterialPreview(node, pixmap);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MaterialBrowserView::variantPropertiesChanged(const QList<VariantProperty> &propertyList,
|
2022-07-07 18:04:18 +02:00
|
|
|
[[maybe_unused]] PropertyChangeFlags propertyChange)
|
2022-03-18 17:28:28 +02:00
|
|
|
{
|
|
|
|
|
for (const VariantProperty &property : propertyList) {
|
|
|
|
|
ModelNode node(property.parentModelNode());
|
|
|
|
|
|
|
|
|
|
if (isMaterial(node) && property.name() == "objectName")
|
|
|
|
|
m_widget->materialBrowserModel()->updateMaterialName(node);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MaterialBrowserView::nodeReparented(const ModelNode &node,
|
|
|
|
|
const NodeAbstractProperty &newPropertyParent,
|
|
|
|
|
const NodeAbstractProperty &oldPropertyParent,
|
2022-07-07 18:04:18 +02:00
|
|
|
[[maybe_unused]] PropertyChangeFlags propertyChange)
|
2022-03-18 17:28:28 +02:00
|
|
|
{
|
|
|
|
|
if (!isMaterial(node))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
ModelNode newParentNode = newPropertyParent.parentModelNode();
|
|
|
|
|
ModelNode oldParentNode = oldPropertyParent.parentModelNode();
|
2022-08-31 10:24:05 +02:00
|
|
|
bool matAdded = newParentNode.id() == Constants::MATERIAL_LIB_ID;
|
|
|
|
|
bool matRemoved = oldParentNode.id() == Constants::MATERIAL_LIB_ID;
|
2022-03-18 17:28:28 +02:00
|
|
|
|
|
|
|
|
if (matAdded || matRemoved) {
|
2022-06-21 11:14:22 +03:00
|
|
|
if (matAdded && !m_puppetResetPending) {
|
|
|
|
|
// Workaround to fix various material issues all likely caused by QTBUG-103316
|
2022-06-16 15:30:25 +03:00
|
|
|
resetPuppet();
|
2022-06-21 11:14:22 +03:00
|
|
|
m_puppetResetPending = true;
|
|
|
|
|
}
|
2022-06-16 15:30:25 +03:00
|
|
|
refreshModel(!matAdded);
|
2022-03-18 17:28:28 +02:00
|
|
|
int idx = m_widget->materialBrowserModel()->materialIndex(node);
|
|
|
|
|
m_widget->materialBrowserModel()->selectMaterial(idx);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MaterialBrowserView::nodeAboutToBeRemoved(const ModelNode &removedNode)
|
|
|
|
|
{
|
|
|
|
|
// removing the material editor node
|
2022-08-31 10:24:05 +02:00
|
|
|
if (removedNode.id() == Constants::MATERIAL_LIB_ID) {
|
2022-03-18 17:28:28 +02:00
|
|
|
m_widget->materialBrowserModel()->setMaterials({}, m_hasQuick3DImport);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// not a material under the material editor
|
|
|
|
|
if (!isMaterial(removedNode)
|
|
|
|
|
|| removedNode.parentProperty().parentModelNode().id() != Constants::MATERIAL_LIB_ID) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m_widget->materialBrowserModel()->removeMaterial(removedNode);
|
|
|
|
|
}
|
|
|
|
|
|
2022-07-07 18:04:18 +02:00
|
|
|
void MaterialBrowserView::nodeRemoved([[maybe_unused]] const ModelNode &removedNode,
|
2022-03-18 17:28:28 +02:00
|
|
|
const NodeAbstractProperty &parentProperty,
|
2022-07-07 18:04:18 +02:00
|
|
|
[[maybe_unused]] PropertyChangeFlags propertyChange)
|
2022-03-18 17:28:28 +02:00
|
|
|
{
|
|
|
|
|
if (parentProperty.parentModelNode().id() != Constants::MATERIAL_LIB_ID)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
m_widget->materialBrowserModel()->updateSelectedMaterial();
|
|
|
|
|
}
|
|
|
|
|
|
2022-08-22 16:09:42 +03:00
|
|
|
void QmlDesigner::MaterialBrowserView::loadPropertyGroups()
|
|
|
|
|
{
|
|
|
|
|
if (!m_hasQuick3DImport || m_propertyGroupsLoaded)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
QString matPropsPath = model()->metaInfo("QtQuick3D.Material").importDirectoryPath()
|
|
|
|
|
+ "/designer/propertyGroups.json";
|
|
|
|
|
m_propertyGroupsLoaded = m_widget->materialBrowserModel()->loadPropertyGroups(matPropsPath);
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-22 15:04:04 +03:00
|
|
|
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 {};
|
|
|
|
|
}
|
|
|
|
|
|
2022-07-07 18:04:18 +02:00
|
|
|
void MaterialBrowserView::importsChanged([[maybe_unused]] const QList<Import> &addedImports,
|
|
|
|
|
[[maybe_unused]] const QList<Import> &removedImports)
|
2022-03-18 17:28:28 +02:00
|
|
|
{
|
|
|
|
|
bool hasQuick3DImport = model()->hasImport("QtQuick3D");
|
|
|
|
|
|
|
|
|
|
if (hasQuick3DImport == m_hasQuick3DImport)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
m_hasQuick3DImport = hasQuick3DImport;
|
2022-06-17 14:10:03 +03:00
|
|
|
|
2022-08-22 16:09:42 +03:00
|
|
|
loadPropertyGroups();
|
|
|
|
|
|
2022-06-21 11:14:22 +03:00
|
|
|
// Import change will trigger puppet reset, so we don't want to update previews immediately
|
|
|
|
|
refreshModel(false);
|
2022-03-18 17:28:28 +02:00
|
|
|
}
|
|
|
|
|
|
2022-07-07 18:04:18 +02:00
|
|
|
void MaterialBrowserView::customNotification(const AbstractView *view,
|
|
|
|
|
const QString &identifier,
|
|
|
|
|
const QList<ModelNode> &nodeList,
|
|
|
|
|
[[maybe_unused]] const QList<QVariant> &data)
|
2022-03-18 17:28:28 +02:00
|
|
|
{
|
|
|
|
|
if (view == this)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (identifier == "selected_material_changed") {
|
|
|
|
|
int idx = m_widget->materialBrowserModel()->materialIndex(nodeList.first());
|
|
|
|
|
if (idx != -1)
|
|
|
|
|
m_widget->materialBrowserModel()->selectMaterial(idx);
|
2022-08-05 17:14:05 +03:00
|
|
|
} else if (identifier == "refresh_material_browser") {
|
|
|
|
|
QTimer::singleShot(0, this, [this]() {
|
|
|
|
|
refreshModel(true);
|
|
|
|
|
});
|
2022-08-04 12:40:06 +03:00
|
|
|
} else if (identifier == "delete_selected_material") {
|
|
|
|
|
m_widget->materialBrowserModel()->deleteSelectedMaterial();
|
2022-09-01 15:03:01 +03:00
|
|
|
} else if (identifier == "drop_bundle_material") {
|
|
|
|
|
m_bundleMaterialDropTarget = nodeList.first();
|
2022-09-22 15:04:04 +03:00
|
|
|
|
|
|
|
|
|
|
|
|
|
ModelNode defaultMat = getBundleMaterialDefaultInstance(m_draggedBundleMaterial->type());
|
|
|
|
|
if (defaultMat.isValid())
|
|
|
|
|
applyBundleMaterialToDropTarget(defaultMat);
|
|
|
|
|
else
|
|
|
|
|
m_widget->materialBrowserBundleModel()->addMaterial(m_draggedBundleMaterial);
|
|
|
|
|
|
2022-09-01 15:03:01 +03:00
|
|
|
m_draggedBundleMaterial = nullptr;
|
2022-03-18 17:28:28 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-21 11:14:22 +03:00
|
|
|
void MaterialBrowserView::instancesCompleted(const QVector<ModelNode> &completedNodeList)
|
|
|
|
|
{
|
|
|
|
|
for (const ModelNode &node : completedNodeList) {
|
|
|
|
|
// We use root node completion as indication of puppet reset
|
|
|
|
|
if (node.isRootNode()) {
|
|
|
|
|
m_puppetResetPending = false;
|
|
|
|
|
QTimer::singleShot(1000, this, [this]() {
|
2022-06-27 11:07:32 +03:00
|
|
|
if (!model() || !model()->nodeInstanceView())
|
|
|
|
|
return;
|
2022-06-21 11:14:22 +03:00
|
|
|
const QList<ModelNode> materials = m_widget->materialBrowserModel()->materials();
|
|
|
|
|
for (const ModelNode &node : materials)
|
|
|
|
|
model()->nodeInstanceView()->previewImageDataForGenericNode(node, {});
|
|
|
|
|
});
|
|
|
|
|
break;
|
|
|
|
|
}
|
2022-03-18 17:28:28 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace QmlDesigner
|