diff --git a/src/plugins/qmldesigner/CMakeLists.txt b/src/plugins/qmldesigner/CMakeLists.txt index 866901d5418..a5644fc66e5 100644 --- a/src/plugins/qmldesigner/CMakeLists.txt +++ b/src/plugins/qmldesigner/CMakeLists.txt @@ -825,6 +825,7 @@ extend_qtc_plugin(QmlDesigner materialbrowserwidget.cpp materialbrowserwidget.h materialbrowsermodel.cpp materialbrowsermodel.h materialbrowsertexturesmodel.cpp materialbrowsertexturesmodel.h + materialutils.cpp materialutils.h ) extend_qtc_plugin(QmlDesigner diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp b/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp index 304f8e305f9..1ebcf635d97 100644 --- a/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp +++ b/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp @@ -12,6 +12,7 @@ #include "edit3dcanvas.h" #include "edit3dviewconfig.h" #include "edit3dwidget.h" +#include "materialutils.h" #include "metainfo.h" #include "nodehints.h" #include "nodeinstanceview.h" @@ -324,7 +325,7 @@ void Edit3DView::nodeAtPosReady(const ModelNode &modelNode, const QVector3D &pos createdNode = QmlVisualNode::createQml3DNode( this, m_droppedEntry, edit3DWidget()->canvas()->activeScene(), pos3d).modelNode(); if (createdNode.metaInfo().isQtQuick3DModel()) - assignMaterialTo3dModel(createdNode); + MaterialUtils::assignMaterialTo3dModel(this, createdNode); }); if (createdNode.isValid()) setSelectedModelNode(createdNode); @@ -332,7 +333,7 @@ void Edit3DView::nodeAtPosReady(const ModelNode &modelNode, const QVector3D &pos bool isModel = modelNode.metaInfo().isQtQuick3DModel(); if (m_droppedModelNode.isValid() && isModel) { executeInTransaction(__FUNCTION__, [&] { - assignMaterialTo3dModel(modelNode, m_droppedModelNode); + MaterialUtils::assignMaterialTo3dModel(this, modelNode, m_droppedModelNode); }); } } else if (m_nodeAtPosReqType == NodeAtPosReqType::BundleMaterialDrop) { diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp b/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp index bf2202717f9..1e842298dd5 100644 --- a/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp +++ b/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp @@ -8,6 +8,7 @@ #include "edit3dcanvas.h" #include "edit3dview.h" #include "edit3dvisibilitytogglesmenu.h" +#include "materialutils.h" #include "metainfo.h" #include "modelnodeoperations.h" #include "nodeabstractproperty.h" @@ -387,7 +388,7 @@ void Edit3DWidget::onCreateAction() // if added node is a Model, assign it a material if (modelNode.metaInfo().isQtQuick3DModel()) - m_view->assignMaterialTo3dModel(modelNode); + MaterialUtils::assignMaterialTo3dModel(m_view, modelNode); }); } diff --git a/src/plugins/qmldesigner/components/formeditor/dragtool.cpp b/src/plugins/qmldesigner/components/formeditor/dragtool.cpp index 8d01c46d7cb..4b128c2d54b 100644 --- a/src/plugins/qmldesigner/components/formeditor/dragtool.cpp +++ b/src/plugins/qmldesigner/components/formeditor/dragtool.cpp @@ -7,6 +7,7 @@ #include "formeditorview.h" #include "assetslibrarywidget.h" #include "assetslibrarymodel.h" +#include "materialutils.h" #include #include #include @@ -441,7 +442,7 @@ void DragTool::handleView3dDrop() const QList models = dragNode.modelNode().subModelNodesOfType( model->qtQuick3DModelMetaInfo()); QTC_ASSERT(models.size() == 1, return); - view()->assignMaterialTo3dModel(models.at(0)); + MaterialUtils::assignMaterialTo3dModel(view(), models.at(0)); } } } diff --git a/src/plugins/qmldesigner/components/materialbrowser/materialutils.cpp b/src/plugins/qmldesigner/components/materialbrowser/materialutils.cpp new file mode 100644 index 00000000000..76924bedbcd --- /dev/null +++ b/src/plugins/qmldesigner/components/materialbrowser/materialutils.cpp @@ -0,0 +1,71 @@ +// 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 + +#include "materialutils.h" + +#include "abstractview.h" +#include "nodelistproperty.h" +#include "nodemetainfo.h" +#include "qmlobjectnode.h" +#include "variantproperty.h" + +#include + +namespace QmlDesigner { + +// Assigns given material to a 3D model. +// The assigned material is also inserted into material library if not already there. +// If given material is not valid, first existing material from material library is used, +// or if material library is empty, a new material is created. +// This function should be called only from inside a transaction, as it potentially does many +// changes to model. +void MaterialUtils::assignMaterialTo3dModel(AbstractView *view, const ModelNode &modelNode, + const ModelNode &materialNode) +{ + QTC_ASSERT(modelNode.isValid() && modelNode.metaInfo().isQtQuick3DModel(), return); + + ModelNode matLib = view->materialLibraryNode(); + + if (!matLib.isValid()) + return; + + ModelNode newMaterialNode; + + if (materialNode.isValid() && materialNode.metaInfo().isQtQuick3DMaterial()) { + newMaterialNode = materialNode; + } else { + const QList materials = matLib.directSubModelNodes(); + if (materials.size() > 0) { + for (const ModelNode &mat : materials) { + if (mat.metaInfo().isQtQuick3DMaterial()) { + newMaterialNode = mat; + break; + } + } + } + + // if no valid material, create a new default material + if (!newMaterialNode.isValid()) { + NodeMetaInfo metaInfo = view->model()->qtQuick3DPrincipledMaterialMetaInfo(); + newMaterialNode = view->createModelNode("QtQuick3D.PrincipledMaterial", + metaInfo.majorVersion(), + metaInfo.minorVersion()); + newMaterialNode.validId(); + } + } + + QTC_ASSERT(newMaterialNode.isValid(), return); + + VariantProperty matNameProp = newMaterialNode.variantProperty("objectName"); + if (matNameProp.value().isNull()) + matNameProp.setValue("New Material"); + + if (!newMaterialNode.hasParentProperty() + || newMaterialNode.parentProperty() != matLib.defaultNodeListProperty()) { + matLib.defaultNodeListProperty().reparentHere(newMaterialNode); + } + + QmlObjectNode(modelNode).setBindingProperty("materials", newMaterialNode.id()); +} + +} // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/materialbrowser/materialutils.h b/src/plugins/qmldesigner/components/materialbrowser/materialutils.h new file mode 100644 index 00000000000..e273ef74a44 --- /dev/null +++ b/src/plugins/qmldesigner/components/materialbrowser/materialutils.h @@ -0,0 +1,20 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0 +#pragma once + +#include "modelnode.h" + +namespace QmlDesigner { + +class AbstractView; + +class MaterialUtils +{ +public: + MaterialUtils(); + + static void assignMaterialTo3dModel(AbstractView *view, const ModelNode &modelNode, + const ModelNode &materialNode = {}); +}; + +} // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp b/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp index 0be28e3baf9..b63ddae890c 100644 --- a/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp +++ b/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -710,7 +711,7 @@ void NavigatorTreeModel::handleItemLibraryItemDrop(const QMimeData *mimeData, in newQmlObjectNode.destroy(); return; } - m_view->assignMaterialTo3dModel(targetNode, newModelNode); + MaterialUtils::assignMaterialTo3dModel(m_view, targetNode, newModelNode); } ChooseFromPropertyListDialog *dialog = ChooseFromPropertyListDialog::createIfNeeded( @@ -751,9 +752,9 @@ void NavigatorTreeModel::handleItemLibraryItemDrop(const QMimeData *mimeData, in const QList models = newModelNode.subModelNodesOfType( m_view->model()->qtQuick3DModelMetaInfo()); QTC_ASSERT(models.size() == 1, return); - m_view->assignMaterialTo3dModel(models.at(0)); + MaterialUtils::assignMaterialTo3dModel(m_view, models.at(0)); } else if (newModelNode.metaInfo().isQtQuick3DModel()) { - m_view->assignMaterialTo3dModel(newModelNode); + MaterialUtils::assignMaterialTo3dModel(m_view, newModelNode); } if (!validContainer) { @@ -836,7 +837,7 @@ void NavigatorTreeModel::handleMaterialDrop(const QMimeData *mimeData, const QMo ModelNode matNode = m_view->modelNodeForInternalId(internalId); m_view->executeInTransaction(__FUNCTION__, [&] { - m_view->assignMaterialTo3dModel(targetNode, matNode); + MaterialUtils::assignMaterialTo3dModel(m_view, targetNode, matNode); }); } diff --git a/src/plugins/qmldesigner/designercore/include/abstractview.h b/src/plugins/qmldesigner/designercore/include/abstractview.h index cdfd94757e8..ed618653ce6 100644 --- a/src/plugins/qmldesigner/designercore/include/abstractview.h +++ b/src/plugins/qmldesigner/designercore/include/abstractview.h @@ -231,7 +231,6 @@ public: ModelNode materialLibraryNode(); bool isPartOfMaterialLibrary(const ModelNode &node); ModelNode active3DSceneNode(); - void assignMaterialTo3dModel(const ModelNode &modelNode, const ModelNode &materialNode = {}); ModelNode getTextureDefaultInstance(const QString &source); const NodeInstanceView *nodeInstanceView() const; diff --git a/src/plugins/qmldesigner/designercore/model/abstractview.cpp b/src/plugins/qmldesigner/designercore/model/abstractview.cpp index 2bfc4c1c06f..409a290573a 100644 --- a/src/plugins/qmldesigner/designercore/model/abstractview.cpp +++ b/src/plugins/qmldesigner/designercore/model/abstractview.cpp @@ -8,7 +8,6 @@ #include "model_p.h" #include "internalnode_p.h" #include "nodeinstanceview.h" -#include "qmlobjectnode.h" #include #include #include @@ -879,60 +878,6 @@ ModelNode AbstractView::active3DSceneNode() return {}; } -// Assigns given material to a 3D model. -// The assigned material is also inserted into material library if not already there. -// If given material is not valid, first existing material from material library is used, -// or if material library is empty, a new material is created. -// This function should be called only from inside a transaction, as it potentially does many -// changes to model. -void AbstractView::assignMaterialTo3dModel(const ModelNode &modelNode, const ModelNode &materialNode) -{ - QTC_ASSERT(modelNode.isValid() && modelNode.metaInfo().isQtQuick3DModel(), return ); - - ModelNode matLib = materialLibraryNode(); - - if (!matLib.isValid()) - return; - - ModelNode newMaterialNode; - - if (materialNode.isValid() && materialNode.metaInfo().isQtQuick3DMaterial()) { - newMaterialNode = materialNode; - } else { - const QList materials = matLib.directSubModelNodes(); - if (materials.size() > 0) { - for (const ModelNode &mat : materials) { - if (mat.metaInfo().isQtQuick3DMaterial()) { - newMaterialNode = mat; - break; - } - } - } - - // if no valid material, create a new default material - if (!newMaterialNode.isValid()) { - NodeMetaInfo metaInfo = model()->qtQuick3DPrincipledMaterialMetaInfo(); - newMaterialNode = createModelNode("QtQuick3D.PrincipledMaterial", - metaInfo.majorVersion(), - metaInfo.minorVersion()); - newMaterialNode.validId(); - } - } - - QTC_ASSERT(newMaterialNode.isValid(), return); - - VariantProperty matNameProp = newMaterialNode.variantProperty("objectName"); - if (matNameProp.value().isNull()) - matNameProp.setValue("New Material"); - - if (!newMaterialNode.hasParentProperty() - || newMaterialNode.parentProperty() != matLib.defaultNodeListProperty()) { - matLib.defaultNodeListProperty().reparentHere(newMaterialNode); - } - - QmlObjectNode(modelNode).setBindingProperty("materials", newMaterialNode.id()); -} - ModelNode AbstractView::getTextureDefaultInstance(const QString &source) { ModelNode matLib = materialLibraryNode();