diff --git a/src/plugins/qmldesigner/CMakeLists.txt b/src/plugins/qmldesigner/CMakeLists.txt index 1c58e2ba88f..78f4e908a54 100644 --- a/src/plugins/qmldesigner/CMakeLists.txt +++ b/src/plugins/qmldesigner/CMakeLists.txt @@ -477,7 +477,6 @@ 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/componentcore/modelnodeoperations.cpp b/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp index d59b69f63ae..afd2ae12b31 100644 --- a/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp +++ b/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include @@ -2093,7 +2092,7 @@ void handleMaterialDrop(const QMimeData *mimeData, const ModelNode &targetNode) ModelNode matNode = view->modelNodeForInternalId(internalId); view->executeInTransaction(__FUNCTION__, [&] { - MaterialUtils::assignMaterialTo3dModel(view, targetNode, matNode); + Utils3D::assignMaterialTo3dModel(view, targetNode, matNode); }); } diff --git a/src/plugins/qmldesigner/components/componentcore/utils3d.cpp b/src/plugins/qmldesigner/components/componentcore/utils3d.cpp index 465514bbb6c..1673c854d6b 100644 --- a/src/plugins/qmldesigner/components/componentcore/utils3d.cpp +++ b/src/plugins/qmldesigner/components/componentcore/utils3d.cpp @@ -3,14 +3,20 @@ #include "utils3d.h" +#include #include #include #include #include #include +#include +#include +#include #include #include +#include + #include #include @@ -342,5 +348,111 @@ ModelNode createMaterial(AbstractView *view, const NodeMetaInfo &metaInfo) } #endif +void addQuick3DImportAndView3D(AbstractView *view) +{ + DesignDocument *document = QmlDesignerPlugin::instance()->currentDesignDocument(); + if (!view || !view->model() || !document || document->inFileComponentModelActive()) { + Core::AsynchronousMessageBox::warning(Tr::tr("Failed to Add Import"), + Tr::tr("Could not add QtQuick3D import to the document.")); + return; + } + + QString importName{"QtQuick3D"}; + if (view->model()->hasImport(importName)) + return; + + view->executeInTransaction(__FUNCTION__, [&] { + Import import = Import::createLibraryImport(importName); + view->model()->changeImports({import}, {}); + + if (!view->rootModelNode().metaInfo().isQtQuickItem()) + return; + + ensureMaterialLibraryNode(view); +#ifndef QDS_USE_PROJECTSTORAGE + }); + view->executeInTransaction(__FUNCTION__, [&] { +#endif + NodeMetaInfo view3dInfo = view->model()->qtQuick3DView3DMetaInfo(); + if (!view->allModelNodesOfType(view3dInfo).isEmpty()) + return; + + const QList entries = view->model()->itemLibraryEntries(); + // Use template file to identify correct entry, as name could be localized in the future + const QString view3dSource{"extendedview3D_template.qml"}; + auto templateMatch = [&view3dSource](const ItemLibraryEntry &entry) -> bool { + return entry.templatePath().endsWith(view3dSource); + }; + auto iter = std::ranges::find_if(entries, templateMatch); + if (iter == entries.end()) + return; + + NodeAbstractProperty targetProp = view->rootModelNode().defaultNodeAbstractProperty(); + QmlObjectNode newQmlObjectNode = QmlItemNode::createQmlObjectNode( + view, *iter, QPointF(), targetProp, false); + + const QList models = newQmlObjectNode.modelNode().subModelNodesOfType( + view->model()->qtQuick3DModelMetaInfo()); + if (!models.isEmpty()) + assignMaterialTo3dModel(view, models.at(0)); + }); +} + +// 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 assignMaterialTo3dModel(AbstractView *view, const ModelNode &modelNode, + const ModelNode &materialNode) +{ + QTC_ASSERT(modelNode.metaInfo().isQtQuick3DModel(), return); + + ModelNode matLib = Utils3D::materialLibraryNode(view); + + if (!matLib) + return; + + ModelNode newMaterialNode; + + if (materialNode.metaInfo().isQtQuick3DMaterial()) { + newMaterialNode = materialNode; + } else { + const QList materials = matLib.directSubModelNodes(); + auto isMaterial = [](const ModelNode &node) -> bool { + return node.metaInfo().isQtQuick3DMaterial(); + }; + if (auto iter = std::ranges::find_if(materials, isMaterial); iter != materials.end()) + newMaterialNode = *iter; + + // if no valid material, create a new default material + if (!newMaterialNode) { +#ifdef QDS_USE_PROJECTSTORAGE + newMaterialNode = view->createModelNode("PrincipledMaterial"); +#else + NodeMetaInfo metaInfo = view->model()->qtQuick3DPrincipledMaterialMetaInfo(); + newMaterialNode = view->createModelNode("QtQuick3D.PrincipledMaterial", + metaInfo.majorVersion(), + metaInfo.minorVersion()); +#endif + newMaterialNode.ensureIdExists(); + } + } + + QTC_ASSERT(newMaterialNode, 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 Utils3D } // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/componentcore/utils3d.h b/src/plugins/qmldesigner/components/componentcore/utils3d.h index 6a7899589c3..b14784d0291 100644 --- a/src/plugins/qmldesigner/components/componentcore/utils3d.h +++ b/src/plugins/qmldesigner/components/componentcore/utils3d.h @@ -54,5 +54,10 @@ ModelNode createMaterial(AbstractView *view, const TypeName &typeName); ModelNode createMaterial(AbstractView *view, const NodeMetaInfo &metaInfo); #endif +void addQuick3DImportAndView3D(AbstractView *view); +void assignMaterialTo3dModel(AbstractView *view, const ModelNode &modelNode, + const ModelNode &materialNode = {}); + + } // namespace Utils3D } // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.cpp b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.cpp index 83415587fdc..7ec0ff221bd 100644 --- a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.cpp +++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.cpp @@ -35,8 +35,6 @@ #include -#include - #ifndef QMLDESIGNER_TEST #include #include @@ -77,23 +75,7 @@ WidgetInfo ContentLibraryView::widgetInfo() m_bundleHelper = std::make_unique(this, m_widget); connect(m_widget, &ContentLibraryWidget::importQtQuick3D, this, [&] { - DesignDocument *document = QmlDesignerPlugin::instance()->currentDesignDocument(); - if (document && !document->inFileComponentModelActive() && model()) { -#ifdef QDS_USE_PROJECTSTORAGE - Import import = Import::createLibraryImport("QtQuick3D"); - model()->changeImports({import}, {}); - return; -#else - if (ModelUtils::addImportWithCheck( - "QtQuick3D", - [](const Import &import) { return !import.hasVersion() || import.majorVersion() >= 6; }, - model())) { - return; - } -#endif - } - Core::AsynchronousMessageBox::warning(tr("Failed to Add Import"), - tr("Could not add QtQuick3D import to project.")); + Utils3D::addQuick3DImportAndView3D(this); }); connect(m_widget, &ContentLibraryWidget::bundleMaterialDragStarted, this, [&] (QmlDesigner::ContentLibraryMaterial *mat) { diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp b/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp index e23c926fec7..8887b8f176d 100644 --- a/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp +++ b/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp @@ -17,7 +17,6 @@ #include #include #include -#include #include #include #include @@ -33,7 +32,6 @@ #include #include -#include #include @@ -481,7 +479,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()) - MaterialUtils::assignMaterialTo3dModel(this, createdNode); + Utils3D::assignMaterialTo3dModel(this, createdNode); }); if (createdNode.isValid()) setSelectedModelNode(createdNode); @@ -489,7 +487,7 @@ void Edit3DView::nodeAtPosReady(const ModelNode &modelNode, const QVector3D &pos bool isModel = modelNode.metaInfo().isQtQuick3DModel(); if (m_droppedModelNode.isValid() && isModel) { executeInTransaction(__FUNCTION__, [&] { - MaterialUtils::assignMaterialTo3dModel(this, modelNode, m_droppedModelNode); + Utils3D::assignMaterialTo3dModel(this, modelNode, m_droppedModelNode); }); } } else if (m_nodeAtPosReqType == NodeAtPosReqType::BundleMaterialDrop) { @@ -1400,27 +1398,6 @@ Edit3DBakeLightsAction *Edit3DView::bakeLightsAction() const return m_bakeLightsAction.get(); } -void Edit3DView::addQuick3DImport() -{ - DesignDocument *document = QmlDesignerPlugin::instance()->currentDesignDocument(); - if (document && !document->inFileComponentModelActive() && model()) { -#ifdef QDS_USE_PROJECTSTORAGE - Import import = Import::createLibraryImport("QtQuick3D"); - model()->changeImports({import}, {}); - return; -#else - if (ModelUtils::addImportWithCheck( - "QtQuick3D", - [](const Import &import) { return !import.hasVersion() || import.majorVersion() >= 6; }, - model())) { - return; - } -#endif - } - Core::AsynchronousMessageBox::warning(tr("Failed to Add Import"), - tr("Could not add QtQuick3D import to project.")); -} - // This method is called upon right-clicking the view to prepare for context-menu creation. The actual // context menu is created when nodeAtPosReady() is received from puppet void Edit3DView::startContextMenu(const QPoint &pos) diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dview.h b/src/plugins/qmldesigner/components/edit3d/edit3dview.h index 5e45ee80889..e6dd069b0cf 100644 --- a/src/plugins/qmldesigner/components/edit3d/edit3dview.h +++ b/src/plugins/qmldesigner/components/edit3d/edit3dview.h @@ -93,7 +93,6 @@ public: Edit3DAction *edit3DAction(View3DActionType type) const; Edit3DBakeLightsAction *bakeLightsAction() const; - void addQuick3DImport(); void startContextMenu(const QPoint &pos); void showContextMenu(); void dropMaterial(const ModelNode &matNode, const QPointF &pos); diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp b/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp index 78a610ffefc..e3553ff5a36 100644 --- a/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp +++ b/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp @@ -17,7 +17,6 @@ #include #include #include -#include #include #include #include @@ -566,7 +565,7 @@ void Edit3DWidget::onCreateAction(QAction *action) // if added node is a Model, assign it a material if (modelNode.metaInfo().isQtQuick3DModel()) - MaterialUtils::assignMaterialTo3dModel(m_view, modelNode); + Utils3D::assignMaterialTo3dModel(m_view, modelNode); }); } @@ -732,8 +731,7 @@ void Edit3DWidget::showContextMenu(const QPoint &pos, const ModelNode &modelNode void Edit3DWidget::linkActivated([[maybe_unused]] const QString &link) { - if (m_view) - m_view->addQuick3DImport(); + Utils3D::addQuick3DImportAndView3D(m_view); } Edit3DCanvas *Edit3DWidget::canvas() const diff --git a/src/plugins/qmldesigner/components/formeditor/dragtool.cpp b/src/plugins/qmldesigner/components/formeditor/dragtool.cpp index ec9897aeeac..9ea9c9a8feb 100644 --- a/src/plugins/qmldesigner/components/formeditor/dragtool.cpp +++ b/src/plugins/qmldesigner/components/formeditor/dragtool.cpp @@ -7,13 +7,13 @@ #include "assetslibrarywidget.h" #include "formeditorscene.h" #include "formeditorview.h" -#include "materialutils.h" #include "qmldesignerconstants.h" #include #include #include #include #include +#include #include @@ -455,7 +455,7 @@ void DragTool::handleView3dDrop() const QList models = dragNode.modelNode().subModelNodesOfType( model->qtQuick3DModelMetaInfo()); QTC_ASSERT(models.size() == 1, return); - MaterialUtils::assignMaterialTo3dModel(view(), models.at(0)); + Utils3D::assignMaterialTo3dModel(view(), models.at(0)); } } } diff --git a/src/plugins/qmldesigner/components/materialbrowser/materialutils.cpp b/src/plugins/qmldesigner/components/materialbrowser/materialutils.cpp deleted file mode 100644 index 1a1071de347..00000000000 --- a/src/plugins/qmldesigner/components/materialbrowser/materialutils.cpp +++ /dev/null @@ -1,76 +0,0 @@ -// 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 - -#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 = Utils3D::materialLibraryNode(view); - - 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()) { -#ifdef QDS_USE_PROJECTSTORAGE - newMaterialNode = view->createModelNode("PrincipledMaterial"); -#else - NodeMetaInfo metaInfo = view->model()->qtQuick3DPrincipledMaterialMetaInfo(); - newMaterialNode = view->createModelNode("QtQuick3D.PrincipledMaterial", - metaInfo.majorVersion(), - metaInfo.minorVersion()); -#endif - newMaterialNode.ensureIdExists(); - } - } - - 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 deleted file mode 100644 index e273ef74a44..00000000000 --- a/src/plugins/qmldesigner/components/materialbrowser/materialutils.h +++ /dev/null @@ -1,20 +0,0 @@ -// 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 7787e0ef829..4e045375347 100644 --- a/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp +++ b/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp @@ -20,7 +20,6 @@ #include #include #include -#include #include #include #include @@ -773,7 +772,7 @@ void NavigatorTreeModel::handleItemLibraryItemDrop(const QMimeData *mimeData, in newQmlObjectNode.destroy(); return; } - MaterialUtils::assignMaterialTo3dModel(m_view, targetNode, newModelNode); + Utils3D::assignMaterialTo3dModel(m_view, targetNode, newModelNode); } else { ChooseFromPropertyListDialog *dialog = ChooseFromPropertyListDialog::createIfNeeded( targetNode, newModelNode, Core::ICore::dialogParent()); @@ -814,9 +813,9 @@ void NavigatorTreeModel::handleItemLibraryItemDrop(const QMimeData *mimeData, in const QList models = newModelNode.subModelNodesOfType( m_view->model()->qtQuick3DModelMetaInfo()); QTC_ASSERT(models.size() == 1, return); - MaterialUtils::assignMaterialTo3dModel(m_view, models.at(0)); + Utils3D::assignMaterialTo3dModel(m_view, models.at(0)); } else if (newModelNode.metaInfo().isQtQuick3DModel()) { - MaterialUtils::assignMaterialTo3dModel(m_view, newModelNode); + Utils3D::assignMaterialTo3dModel(m_view, newModelNode); } if (!validContainer) {