From 3b3e2e1baaee823a5a211c7700de38d51006327c Mon Sep 17 00:00:00 2001 From: Mahmoud Badri Date: Thu, 25 Aug 2022 12:27:41 +0300 Subject: [PATCH] QmlDesigner: Add "Create" submenu to the 3D Editor's context menu Allow adding Quick3D Node-based items to the 3D scene using the contxt menu. Fixes: QDS-7397 Fixes: QDS-7399 Fixes: QDS-7400 Change-Id: Ib0a9b1c0243e3e945b4925262f68d80d2460f516 Reviewed-by: Qt CI Bot Reviewed-by: Samuel Ghinet Reviewed-by: Miikka Heikkinen --- .../components/edit3d/edit3dview.cpp | 33 ++++++++++-- .../components/edit3d/edit3dview.h | 6 +++ .../components/edit3d/edit3dwidget.cpp | 53 ++++++++++++++++++- .../components/edit3d/edit3dwidget.h | 7 +++ 4 files changed, 95 insertions(+), 4 deletions(-) diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp b/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp index 5a598dbd0e5..50a312b193e 100644 --- a/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp +++ b/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp @@ -23,13 +23,13 @@ ** ****************************************************************************/ -#include "designmodewidget.h" #include "edit3dactions.h" #include "edit3dcanvas.h" #include "edit3dview.h" #include "edit3dwidget.h" #include "edit3dviewconfig.h" #include "backgroundcolorselection.h" +#include "metainfo.h" #include #include @@ -52,11 +52,13 @@ namespace QmlDesigner { Edit3DView::Edit3DView(QObject *parent) : AbstractView(parent) { + m_compressionTimer.setInterval(1000); + m_compressionTimer.setSingleShot(true); + connect(&m_compressionTimer, &QTimer::timeout, this, &Edit3DView::handleEntriesChanged); } Edit3DView::~Edit3DView() -{ -} +{} void Edit3DView::createEdit3DWidget() { @@ -206,6 +208,31 @@ void Edit3DView::modelAttached(Model *model) } edit3DWidget()->canvas()->busyIndicator()->show(); + + connect(model->metaInfo().itemLibraryInfo(), &ItemLibraryInfo::entriesChanged, this, + &Edit3DView::onEntriesChanged, Qt::UniqueConnection); +} + +void Edit3DView::onEntriesChanged() +{ + m_compressionTimer.start(); +} + +void Edit3DView::handleEntriesChanged() +{ + QMap> entriesMap { + {"Camera", {}}, + {"Lights", {}}, + {"Models", {}} + }; + + const QList itemLibEntries = model()->metaInfo().itemLibraryInfo()->entries(); + for (const ItemLibraryEntry &entry : itemLibEntries) { + if (entry.typeName().startsWith("QtQuick3D.") && entriesMap.contains(entry.category())) + entriesMap[entry.category()].append(entry); + } + + m_edit3DWidget->updateCreateSubMenu(entriesMap); } void Edit3DView::modelAboutToBeDetached(Model *model) diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dview.h b/src/plugins/qmldesigner/components/edit3d/edit3dview.h index 0d3e9ff16fd..208ccc1e68b 100644 --- a/src/plugins/qmldesigner/components/edit3d/edit3dview.h +++ b/src/plugins/qmldesigner/components/edit3d/edit3dview.h @@ -35,6 +35,7 @@ #include #include #include +#include QT_BEGIN_NAMESPACE QT_END_NAMESPACE @@ -82,6 +83,9 @@ public: void startContextMenu(const QPoint &pos); void dropMaterial(const ModelNode &matNode, const QPointF &pos); +private slots: + void onEntriesChanged(); + private: enum class ModelAtPosReqType { MaterialDrop, @@ -91,6 +95,7 @@ private: void createEdit3DWidget(); void checkImports(); + void handleEntriesChanged(); Edit3DAction *createSelectBackgrounColorAction(); Edit3DAction *createGridColorSelectionAction(); @@ -129,6 +134,7 @@ private: ModelNode m_droppedMaterial; ModelAtPosReqType m_modelAtPosReqType; QPoint m_contextMenuPos; + QTimer m_compressionTimer; }; } // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp b/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp index c7885996cec..de864763648 100644 --- a/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp +++ b/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp @@ -23,7 +23,6 @@ ** ****************************************************************************/ -#include "designersettings.h" #include "edit3dactions.h" #include "edit3dcanvas.h" #include "edit3dview.h" @@ -42,6 +41,7 @@ #include #include #include +#include #include #include @@ -193,6 +193,57 @@ void Edit3DWidget::createContextMenu() }); } +// Called by the view to update the "create" sub-menu when the Quick3D entries are ready +void Edit3DWidget::updateCreateSubMenu(const QMap> &entriesMap) +{ + if (!m_contextMenu) + return; + + if (m_createSubMenu) { + m_contextMenu->removeAction(m_createSubMenu->menuAction()); + m_createSubMenu.clear(); + } + + m_nameToEntry.clear(); + m_createSubMenu = m_contextMenu->addMenu(tr("Create")); + + const QStringList categories = entriesMap.keys(); + for (const QString &cat : categories) { + QMenu *catMenu = m_createSubMenu->addMenu(cat); + + QList entries = entriesMap.value(cat); + std::sort(entries.begin(), entries.end(), [](const ItemLibraryEntry &a, const ItemLibraryEntry &b) { + return a.name() < b.name(); + }); + for (const ItemLibraryEntry &entry : std::as_const(entries)) { + QAction *action = catMenu->addAction(entry.name(), this, &Edit3DWidget::onCreateAction); + action->setData(entry.name()); + m_nameToEntry.insert(entry.name(), entry); + } + } +} + +// Action triggered from the "create" sub-menu +void Edit3DWidget::onCreateAction() +{ + QAction *action = qobject_cast(sender()); + if (!action) + return; + + m_view->executeInTransaction(__FUNCTION__, [&] { + int activeScene = m_view->rootModelNode().auxiliaryData("active3dScene@Internal").toInt(); + + auto modelNode = QmlVisualNode::createQml3DNode(m_view, m_nameToEntry.value(action->data().toString()), + activeScene).modelNode(); + QTC_ASSERT(modelNode.isValid(), return); + m_view->setSelectedModelNode(modelNode); + + // if added node is a Model, assign it a material + if (modelNode.isSubclassOf("QtQuick3D.Model")) + m_view->assignMaterialTo3dModel(modelNode); + }); +} + void Edit3DWidget::contextHelp(const Core::IContext::HelpCallback &callback) const { if (m_view) diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dwidget.h b/src/plugins/qmldesigner/components/edit3d/edit3dwidget.h index 7315f5a6b1d..6663690b653 100644 --- a/src/plugins/qmldesigner/components/edit3d/edit3dwidget.h +++ b/src/plugins/qmldesigner/components/edit3d/edit3dwidget.h @@ -30,6 +30,7 @@ #include #include +#include "itemlibraryinfo.h" #include namespace QmlDesigner { @@ -57,6 +58,10 @@ public: void showBackgroundColorMenu(bool show, const QPoint &pos); void showContextMenu(const QPoint &pos, const ModelNode &modelNode); + void updateCreateSubMenu(const QMap> &entriesMap); + +private slots: + void onCreateAction(); protected: void dragEnterEvent(QDragEnterEvent *dragEnterEvent) override; @@ -77,7 +82,9 @@ private: QPointer m_contextMenu; QPointer m_editMaterialAction; QPointer m_deleteAction; + QPointer m_createSubMenu; ModelNode m_contextMenuTarget; + QHash m_nameToEntry; }; } // namespace QmlDesigner