summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMahmoud Badri <mahmoud.badri@qt.io>2022-08-19 13:04:26 +0300
committerMahmoud Badri <mahmoud.badri@qt.io>2022-08-22 13:26:18 +0000
commitfc4ebb0cab19eb9e4a87262ea079c5ad74d9bf2b (patch)
tree2cf25654fc4bb1e8b106e05a762882bb38e4a4a7
parent86d1526564b2aad91ac84039af9e97e69f072ae7 (diff)
downloadqt-creator-fc4ebb0cab19eb9e4a87262ea079c5ad74d9bf2b.tar.gz
QmlDesigner: Create a context menu for the 3D Editor
For now only 1 action is implemented (edit material), more actions are coming next. Task-number: QDS-7414 Task-number: QDS-7398 Change-Id: Id8e36c23d9a4d35ee94d55d3d6b15df78241a05d Reviewed-by: <github-actions-qt-creator@cristianadam.eu> Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io>
-rw-r--r--share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp48
-rw-r--r--share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.h1
-rw-r--r--src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp6
-rw-r--r--src/plugins/qmldesigner/components/edit3d/edit3dcanvas.cpp3
-rw-r--r--src/plugins/qmldesigner/components/edit3d/edit3dview.cpp32
-rw-r--r--src/plugins/qmldesigner/components/edit3d/edit3dview.h9
-rw-r--r--src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp28
-rw-r--r--src/plugins/qmldesigner/components/edit3d/edit3dwidget.h16
-rw-r--r--src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp3
9 files changed, 111 insertions, 35 deletions
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp
index dae4f975b4..b94fa31fc6 100644
--- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp
+++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp
@@ -291,6 +291,10 @@ void Qt5InformationNodeInstanceServer::handleInputEvents()
// data stored internally in QMutableEventPoint to potentially be updated by system
// before the event is delivered.
QGuiApplication::sendEvent(m_editView3DData.window, me);
+
+ // Context menu requested
+ if (command.button() == Qt::RightButton && command.modifiers() == Qt::NoModifier)
+ getModelAtPos(command.pos());
}
}
@@ -405,6 +409,29 @@ void Qt5InformationNodeInstanceServer::removeRotationBlocks(const QVector<qint32
#endif
}
+void Qt5InformationNodeInstanceServer::getModelAtPos(const QPointF &pos)
+{
+#ifdef QUICK3D_MODULE
+ // pick a Quick3DModel at view position
+ auto helper = qobject_cast<QmlDesigner::Internal::GeneralHelper *>(m_3dHelper);
+ if (!helper)
+ return;
+
+ QQmlProperty editViewProp(m_editView3DData.rootItem, "editView", context());
+ QObject *obj = qvariant_cast<QObject *>(editViewProp.read());
+ QQuick3DViewport *editView = qobject_cast<QQuick3DViewport *>(obj);
+
+ QQuick3DModel *hitModel = helper->pickViewAt(editView, pos.x(), pos.y()).objectHit();
+
+ // filter out picks of models created dynamically or inside components
+ QQuick3DModel *resolvedPick = qobject_cast<QQuick3DModel *>(helper->resolvePick(hitModel));
+
+ QVariant instance = resolvedPick ? instanceForObject(resolvedPick).instanceId() : -1;
+ nodeInstanceClient()->handlePuppetToCreatorCommand({PuppetToCreatorCommand::ModelAtPos, instance});
+ return;
+#endif
+}
+
void Qt5InformationNodeInstanceServer::createEditView3D()
{
#ifdef QUICK3D_MODULE
@@ -2399,26 +2426,7 @@ void Qt5InformationNodeInstanceServer::view3DAction(const View3DActionCommand &c
#endif
#ifdef QUICK3D_MODULE
case View3DActionCommand::GetModelAtPos: {
- // pick a Quick3DModel at view position
- auto helper = qobject_cast<QmlDesigner::Internal::GeneralHelper *>(m_3dHelper);
- if (!helper)
- return;
-
- QQmlProperty editViewProp(m_editView3DData.rootItem, "editView", context());
- QObject *obj = qvariant_cast<QObject *>(editViewProp.read());
- QQuick3DViewport *editView = qobject_cast<QQuick3DViewport *>(obj);
-
- QPointF pos = command.value().toPointF();
- QQuick3DModel *hitModel = helper->pickViewAt(editView, pos.x(), pos.y()).objectHit();
-
- // filter out picks of models created dynamically or inside components
- QQuick3DModel *resolvedPick = qobject_cast<QQuick3DModel *>(helper->resolvePick(hitModel));
-
- if (resolvedPick) {
- ServerNodeInstance instance = instanceForObject(resolvedPick);
- nodeInstanceClient()->handlePuppetToCreatorCommand(
- {PuppetToCreatorCommand::ModelAtPos, QVariant(instance.instanceId())});
- }
+ getModelAtPos(command.value().toPointF());
return;
}
#endif
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.h b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.h
index ea104442a6..87c1d53d54 100644
--- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.h
+++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.h
@@ -148,6 +148,7 @@ private:
void updateMaterialPreviewData(const QVector<PropertyValueContainer> &valueChanges);
void updateRotationBlocks(const QVector<PropertyValueContainer> &valueChanges);
void removeRotationBlocks(const QVector<qint32> &instanceIds);
+ void getModelAtPos(const QPointF &pos);
void createAuxiliaryQuickView(const QUrl &url, RenderViewData &viewData);
#ifdef QUICK3D_PARTICLES_MODULE
diff --git a/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp b/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp
index 068e9cf2fd..8df917be69 100644
--- a/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp
+++ b/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp
@@ -796,7 +796,11 @@ void addNewSignalHandler(const SelectionContext &selectionState)
// Open a model's material in the material editor
void editMaterial(const SelectionContext &selectionContext)
{
- ModelNode modelNode = selectionContext.currentSingleSelectedNode();
+ ModelNode modelNode = selectionContext.targetNode();
+
+ if (!modelNode.isValid())
+ modelNode = selectionContext.currentSingleSelectedNode();
+
QTC_ASSERT(modelNode.isValid(), return);
BindingProperty prop = modelNode.bindingProperty("materials");
diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dcanvas.cpp b/src/plugins/qmldesigner/components/edit3d/edit3dcanvas.cpp
index 02d798c1f6..98c052dc18 100644
--- a/src/plugins/qmldesigner/components/edit3d/edit3dcanvas.cpp
+++ b/src/plugins/qmldesigner/components/edit3d/edit3dcanvas.cpp
@@ -102,6 +102,9 @@ QWidget *Edit3DCanvas::busyIndicator() const
void Edit3DCanvas::mousePressEvent(QMouseEvent *e)
{
+ if (e->button() == Qt::RightButton && e->modifiers() == Qt::NoModifier)
+ m_parent->view()->startContextMenu(e->pos());
+
m_parent->view()->sendInputEvent(e);
QWidget::mousePressEvent(e);
}
diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp b/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp
index f848b58b3f..fb844b1c85 100644
--- a/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp
+++ b/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp
@@ -239,14 +239,25 @@ void Edit3DView::customNotification(const AbstractView *view, const QString &ide
resetPuppet();
}
+/**
+ * @brief get model at position from puppet process
+ *
+ * Response from puppet process for the model at requested position
+ *
+ * @param modelNode 3D model picked at the requested position, invalid node if no model exists
+ */
void Edit3DView::modelAtPosReady(const ModelNode &modelNode)
{
- if (!m_droppedMaterial.isValid() || !modelNode.isValid())
- return;
-
- executeInTransaction(__FUNCTION__, [&] {
- assignMaterialTo3dModel(modelNode, m_droppedMaterial);
- });
+ if (m_modelAtPosReqType == ModelAtPosReqType::ContextMenu) {
+ m_edit3DWidget->showContextMenu(m_contextMenuPos, modelNode);
+ } else if (m_modelAtPosReqType == ModelAtPosReqType::MaterialDrop) {
+ if (m_droppedMaterial.isValid() && modelNode.isValid()) {
+ executeInTransaction(__FUNCTION__, [&] {
+ assignMaterialTo3dModel(modelNode, m_droppedMaterial);
+ });
+ }
+ }
+ m_modelAtPosReqType = ModelAtPosReqType::None;
}
void Edit3DView::sendInputEvent(QInputEvent *e) const
@@ -631,8 +642,17 @@ void Edit3DView::addQuick3DImport()
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 modelAtPosReady() is received from puppet
+void Edit3DView::startContextMenu(const QPoint &pos)
+{
+ m_contextMenuPos = pos;
+ m_modelAtPosReqType = ModelAtPosReqType::ContextMenu;
+}
+
void Edit3DView::dropMaterial(const ModelNode &matNode, const QPointF &pos)
{
+ m_modelAtPosReqType = ModelAtPosReqType::MaterialDrop;
m_droppedMaterial = matNode;
QmlDesignerPlugin::instance()->viewManager().nodeInstanceView()->view3DAction({View3DActionCommand::GetModelAtPos, pos});
}
diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dview.h b/src/plugins/qmldesigner/components/edit3d/edit3dview.h
index 8b242058ef..0d3e9ff16f 100644
--- a/src/plugins/qmldesigner/components/edit3d/edit3dview.h
+++ b/src/plugins/qmldesigner/components/edit3d/edit3dview.h
@@ -79,9 +79,16 @@ public:
void setSeeker(SeekerSlider *slider);
void addQuick3DImport();
+ void startContextMenu(const QPoint &pos);
void dropMaterial(const ModelNode &matNode, const QPointF &pos);
private:
+ enum class ModelAtPosReqType {
+ MaterialDrop,
+ ContextMenu,
+ None
+ };
+
void createEdit3DWidget();
void checkImports();
@@ -120,6 +127,8 @@ private:
int particlemode;
ModelCache<QImage> m_canvasCache;
ModelNode m_droppedMaterial;
+ ModelAtPosReqType m_modelAtPosReqType;
+ QPoint m_contextMenuPos;
};
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp b/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp
index a6672b9f16..8643bc091b 100644
--- a/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp
+++ b/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp
@@ -30,6 +30,7 @@
#include "edit3dwidget.h"
#include "edit3dvisibilitytogglesmenu.h"
#include "metainfo.h"
+#include "modelnodeoperations.h"
#include "qmldesignerconstants.h"
#include "qmldesignerplugin.h"
#include "qmlvisualnode.h"
@@ -49,8 +50,8 @@
namespace QmlDesigner {
-Edit3DWidget::Edit3DWidget(Edit3DView *view) :
- m_view(view)
+Edit3DWidget::Edit3DWidget(Edit3DView *view)
+ : m_view(view)
{
setAcceptDrops(true);
@@ -146,6 +147,8 @@ Edit3DWidget::Edit3DWidget(Edit3DView *view) :
handleActions(view->backgroundColorActions(), m_backgroundColorMenu, false);
+ createContextMenu();
+
view->setSeeker(seeker);
seeker->setToolTip(QLatin1String("Seek particle system time when paused."));
@@ -173,6 +176,18 @@ Edit3DWidget::Edit3DWidget(Edit3DView *view) :
showCanvas(false);
}
+void Edit3DWidget::createContextMenu()
+{
+ m_contextMenu = new QMenu(this);
+ m_editMaterialAction = m_contextMenu->addAction(tr("Edit Material"), [&] {
+ SelectionContext selCtx(m_view);
+ selCtx.setTargetNode(m_contextMenuTarget);
+ ModelNodeOperations::editMaterial(selCtx);
+ });
+
+ // TODO: add more actions: delete, create, etc
+}
+
void Edit3DWidget::contextHelp(const Core::IContext::HelpCallback &callback) const
{
if (m_view)
@@ -221,6 +236,15 @@ void Edit3DWidget::showBackgroundColorMenu(bool show, const QPoint &pos)
m_backgroundColorMenu->close();
}
+void Edit3DWidget::showContextMenu(const QPoint &pos, const ModelNode &modelNode)
+{
+ m_contextMenuTarget = modelNode;
+
+ m_editMaterialAction->setEnabled(modelNode.isValid());
+
+ m_contextMenu->popup(mapToGlobal(pos));
+}
+
void Edit3DWidget::linkActivated(const QString &link)
{
Q_UNUSED(link)
diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dwidget.h b/src/plugins/qmldesigner/components/edit3d/edit3dwidget.h
index 7d40fd5471..6b3e773fdc 100644
--- a/src/plugins/qmldesigner/components/edit3d/edit3dwidget.h
+++ b/src/plugins/qmldesigner/components/edit3d/edit3dwidget.h
@@ -24,11 +24,13 @@
****************************************************************************/
#pragma once
-#include <QtWidgets/qwidget.h>
-#include <QtWidgets/qlabel.h>
-#include <QtWidgets/qmenu.h>
-#include <QtCore/qpointer.h>
+#include <QLabel>
+#include <QMenu>
+#include <QPointer>
+#include <QWidget>
+
#include <coreplugin/icontext.h>
+#include <modelnode.h>
namespace QmlDesigner {
@@ -54,12 +56,15 @@ public:
QMenu *backgroundColorMenu() const;
void showBackgroundColorMenu(bool show, const QPoint &pos);
+ void showContextMenu(const QPoint &pos, const ModelNode &modelNode);
+
protected:
void dragEnterEvent(QDragEnterEvent *dragEnterEvent) override;
void dropEvent(QDropEvent *dropEvent) override;
private:
void linkActivated(const QString &link);
+ void createContextMenu();
QPointer<Edit3DView> m_edit3DView;
QPointer<Edit3DView> m_view;
@@ -69,6 +74,9 @@ private:
Core::IContext *m_context = nullptr;
QPointer<QMenu> m_visibilityTogglesMenu;
QPointer<QMenu> m_backgroundColorMenu;
+ QPointer<QMenu> m_contextMenu;
+ QPointer<QAction> m_editMaterialAction;
+ ModelNode m_contextMenuTarget;
};
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp b/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp
index 1a703463cc..d723a21792 100644
--- a/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp
+++ b/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp
@@ -1707,8 +1707,7 @@ void NodeInstanceView::handlePuppetToCreatorCommand(const PuppetToCreatorCommand
emitImport3DSupportChanged(supportMap);
} else if (command.type() == PuppetToCreatorCommand::ModelAtPos) {
ModelNode modelNode = modelNodeForInternalId(command.data().toUInt());
- if (modelNode.isValid())
- emitModelAtPosResult(modelNode);
+ emitModelAtPosResult(modelNode);
}
}