diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/mousearea3d.h b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/mousearea3d.h index 1cb91cab337..8d911839ac6 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/mousearea3d.h +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/mousearea3d.h @@ -81,23 +81,10 @@ public: QQuick3DNode *pickNode() const; MouseArea3D *dragHelper() const; + QVector3D getMousePosInPlane(const MouseArea3D *helper, const QPointF &mousePosInView) const; + static qreal mouseDragMultiplier() { return .02; } -public slots: - void setView3D(QQuick3DViewport *view3D); - void setGrabsMouse(bool grabsMouse); - void setActive(bool active); - void setCirclePickArea(const QPointF &pickArea); - void setMinAngle(qreal angle); - void setPickNode(QQuick3DNode *node); - void setDragHelper(MouseArea3D *dragHelper); - - void setX(qreal x); - void setY(qreal y); - void setWidth(qreal width); - void setHeight(qreal height); - void setPriority(int level); - Q_INVOKABLE QVector3D rayIntersectsPlane(const QVector3D &rayPos0, const QVector3D &rayPos1, const QVector3D &planePos, @@ -120,6 +107,21 @@ public slots: Q_INVOKABLE void forceMoveEvent(double x, double y); Q_INVOKABLE void forceReleaseEvent(double x, double y); +public slots: + void setView3D(QQuick3DViewport *view3D); + void setGrabsMouse(bool grabsMouse); + void setActive(bool active); + void setCirclePickArea(const QPointF &pickArea); + void setMinAngle(qreal angle); + void setPickNode(QQuick3DNode *node); + void setDragHelper(MouseArea3D *dragHelper); + + void setX(qreal x); + void setY(qreal y); + void setWidth(qreal width); + void setHeight(qreal height); + void setPriority(int level); + signals: void view3DChanged(); @@ -153,7 +155,6 @@ private: void setHovering(bool enable); QVector3D getNormal() const; QVector3D getCameraToNodeDir(QQuick3DNode *node) const; - QVector3D getMousePosInPlane(const MouseArea3D *helper, const QPointF &mousePosInView) const; Q_DISABLE_COPY(MouseArea3D) QQuick3DViewport *m_view3D = nullptr; diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp index 24dad5961dc..02d78866bb3 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp @@ -428,18 +428,33 @@ void Qt5InformationNodeInstanceServer::getNodeAtPos(const QPointF &pos) Q_ARG(QVariant, pos.x()), Q_ARG(QVariant, pos.y())); QObject *gizmoObj = qvariant_cast(gizmoVar); - QVariant instance = -1; + qint32 instanceId = -1; if (gizmoObj && hasInstanceForObject(gizmoObj)) { - instance = instanceForObject(gizmoObj).instanceId(); + instanceId = instanceForObject(gizmoObj).instanceId(); } else { QQuick3DModel *hitModel = helper->pickViewAt(editView, pos.x(), pos.y()).objectHit(); QObject *resolvedPick = helper->resolvePick(hitModel); if (hasInstanceForObject(resolvedPick)) - instance = instanceForObject(resolvedPick).instanceId(); + instanceId = instanceForObject(resolvedPick).instanceId(); } - nodeInstanceClient()->handlePuppetToCreatorCommand({PuppetToCreatorCommand::NodeAtPos, instance}); + // Also get the intersection with an axis plane of the scene. + QVector3D pos3d; + if (editView) { + Internal::MouseArea3D ma; + ma.setView3D(editView); + ma.setEulerRotation({90, 0, 0}); // Default grid plane (XZ plane) + QVector3D planePos = ma.getMousePosInPlane(nullptr, pos); + const float limit = 10000000; // Remove extremes on nearly parallel plane + if (!qFuzzyCompare(planePos.z(), -1.f) && qAbs(planePos.x()) < limit && qAbs(planePos.y()) < limit) + pos3d = {planePos.x(), 0, planePos.y()}; + } + QVariantList data; + data.append(instanceId); + data.append(pos3d); + nodeInstanceClient()->handlePuppetToCreatorCommand({PuppetToCreatorCommand::NodeAtPos, + QVariant::fromValue(data)}); #else Q_UNUSED(pos) #endif diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp b/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp index ae6dcaea866..b9f91d56970 100644 --- a/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp +++ b/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp @@ -295,15 +295,16 @@ void Edit3DView::customNotification(const AbstractView *view, const QString &ide * Response from puppet process for the model at requested position * * @param modelNode Node picked at the requested position or invalid node if nothing could be picked + * @param pos3d 3D scene position of the requested view position */ -void Edit3DView::nodeAtPosReady(const ModelNode &modelNode) +void Edit3DView::nodeAtPosReady(const ModelNode &modelNode, const QVector3D &pos3d) { if (m_nodeAtPosReqType == NodeAtPosReqType::ContextMenu) { // Make sure right-clicked item is selected. Due to a bug in puppet side right-clicking an item // while the context-menu is shown doesn't select the item. if (modelNode.isValid() && !modelNode.isSelected()) setSelectedModelNode(modelNode); - m_edit3DWidget->showContextMenu(m_contextMenuPos, modelNode); + m_edit3DWidget->showContextMenu(m_contextMenuPos, modelNode, pos3d); } else if (m_nodeAtPosReqType == NodeAtPosReqType::MaterialDrop) { if (m_droppedMaterial.isValid() && modelNode.isValid() && modelNode.isSubclassOf("QtQuick3D.Model")) { diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dview.h b/src/plugins/qmldesigner/components/edit3d/edit3dview.h index 635bbaf574b..68d217b38ea 100644 --- a/src/plugins/qmldesigner/components/edit3d/edit3dview.h +++ b/src/plugins/qmldesigner/components/edit3d/edit3dview.h @@ -63,7 +63,7 @@ public: void modelAboutToBeDetached(Model *model) override; void importsChanged(const QList &addedImports, const QList &removedImports) override; void customNotification(const AbstractView *view, const QString &identifier, const QList &nodeList, const QList &data) override; - void nodeAtPosReady(const ModelNode &modelNode) override; + void nodeAtPosReady(const ModelNode &modelNode, const QVector3D &pos3d) override; void sendInputEvent(QInputEvent *e) const; void edit3DViewResized(const QSize &size) const; diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp b/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp index 60d6d7ed633..e439ccf00c3 100644 --- a/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp +++ b/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp @@ -238,7 +238,7 @@ void Edit3DWidget::onCreateAction() int activeScene = m_view->rootModelNode().auxiliaryData("active3dScene@Internal").toInt(); auto modelNode = QmlVisualNode::createQml3DNode(m_view, m_nameToEntry.value(action->data().toString()), - activeScene).modelNode(); + activeScene, m_contextMenuPos3d).modelNode(); QTC_ASSERT(modelNode.isValid(), return); m_view->setSelectedModelNode(modelNode); @@ -296,9 +296,10 @@ void Edit3DWidget::showBackgroundColorMenu(bool show, const QPoint &pos) m_backgroundColorMenu->close(); } -void Edit3DWidget::showContextMenu(const QPoint &pos, const ModelNode &modelNode) +void Edit3DWidget::showContextMenu(const QPoint &pos, const ModelNode &modelNode, const QVector3D &pos3d) { m_contextMenuTarget = modelNode; + m_contextMenuPos3d = pos3d; const bool isValid = modelNode.isValid(); const bool isModel = isValid && modelNode.isSubclassOf("QtQuick3D.Model"); diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dwidget.h b/src/plugins/qmldesigner/components/edit3d/edit3dwidget.h index b9f288f0cbf..dec3bd113dc 100644 --- a/src/plugins/qmldesigner/components/edit3d/edit3dwidget.h +++ b/src/plugins/qmldesigner/components/edit3d/edit3dwidget.h @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -57,7 +58,7 @@ public: QMenu *backgroundColorMenu() const; void showBackgroundColorMenu(bool show, const QPoint &pos); - void showContextMenu(const QPoint &pos, const ModelNode &modelNode); + void showContextMenu(const QPoint &pos, const ModelNode &modelNode, const QVector3D &pos3d); void updateCreateSubMenu(const QStringList &keys, const QHash> &entriesMap); @@ -85,6 +86,7 @@ private: QPointer m_deleteAction; QPointer m_createSubMenu; ModelNode m_contextMenuTarget; + QVector3D m_contextMenuPos3d; QHash m_nameToEntry; }; diff --git a/src/plugins/qmldesigner/designercore/include/abstractview.h b/src/plugins/qmldesigner/designercore/include/abstractview.h index 065e3382157..a08b3a2255f 100644 --- a/src/plugins/qmldesigner/designercore/include/abstractview.h +++ b/src/plugins/qmldesigner/designercore/include/abstractview.h @@ -38,6 +38,7 @@ #include #include +#include #include @@ -166,7 +167,7 @@ public: void emitUpdateActiveScene3D(const QVariantMap &sceneState); void emitModelNodelPreviewPixmapChanged(const ModelNode &node, const QPixmap &pixmap); void emitImport3DSupportChanged(const QVariantMap &supportMap); - void emitNodeAtPosResult(const ModelNode &modelNode); + void emitNodeAtPosResult(const ModelNode &modelNode, const QVector3D &pos3d); void sendTokenToInstances(const QString &token, int number, const QVector &nodeVector); @@ -232,7 +233,7 @@ public: virtual void renderImage3DChanged(const QImage &image); virtual void updateActiveScene3D(const QVariantMap &sceneState); virtual void updateImport3DSupport(const QVariantMap &supportMap); - virtual void nodeAtPosReady(const ModelNode &modelNode); + virtual void nodeAtPosReady(const ModelNode &modelNode, const QVector3D &pos3d); virtual void modelNodePreviewPixmapChanged(const ModelNode &node, const QPixmap &pixmap); virtual void dragStarted(QMimeData *mimeData); diff --git a/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp b/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp index 222a5fa079e..2b64b12cd31 100644 --- a/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp +++ b/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp @@ -1706,8 +1706,12 @@ void NodeInstanceView::handlePuppetToCreatorCommand(const PuppetToCreatorCommand const QVariantMap supportMap = qvariant_cast(command.data()); emitImport3DSupportChanged(supportMap); } else if (command.type() == PuppetToCreatorCommand::NodeAtPos) { - ModelNode modelNode = modelNodeForInternalId(command.data().toUInt()); - emitNodeAtPosResult(modelNode); + auto data = qvariant_cast(command.data()); + if (data.size() == 2) { + ModelNode modelNode = modelNodeForInternalId(data[0].toInt()); + QVector3D pos3d = data[1].value(); + emitNodeAtPosResult(modelNode, pos3d); + } } } diff --git a/src/plugins/qmldesigner/designercore/model/abstractview.cpp b/src/plugins/qmldesigner/designercore/model/abstractview.cpp index 6ec1cbc7f0e..5e0e07fde1f 100644 --- a/src/plugins/qmldesigner/designercore/model/abstractview.cpp +++ b/src/plugins/qmldesigner/designercore/model/abstractview.cpp @@ -408,8 +408,9 @@ void AbstractView::updateImport3DSupport(const QVariantMap & /*supportMap*/) { } -// a Quick3DModel that is picked at the requested position in the 3D Editor -void AbstractView::nodeAtPosReady(const ModelNode & /*modelNode*/) {} +// a Quick3DNode that is picked at the requested view position in the 3D Editor and the 3D scene +// position of the requested view position. +void AbstractView::nodeAtPosReady(const ModelNode & /*modelNode*/, const QVector3D &/*pos3d*/) {} void AbstractView::modelNodePreviewPixmapChanged(const ModelNode & /*node*/, const QPixmap & /*pixmap*/) { @@ -802,10 +803,10 @@ void AbstractView::emitImport3DSupportChanged(const QVariantMap &supportMap) model()->d->notifyImport3DSupportChanged(supportMap); } -void AbstractView::emitNodeAtPosResult(const ModelNode &modelNode) +void AbstractView::emitNodeAtPosResult(const ModelNode &modelNode, const QVector3D &pos3d) { if (model()) - model()->d->notifyNodeAtPosResult(modelNode); + model()->d->notifyNodeAtPosResult(modelNode, pos3d); } void AbstractView::emitRewriterEndTransaction() diff --git a/src/plugins/qmldesigner/designercore/model/model.cpp b/src/plugins/qmldesigner/designercore/model/model.cpp index e1344a50957..f6f852bf47d 100644 --- a/src/plugins/qmldesigner/designercore/model/model.cpp +++ b/src/plugins/qmldesigner/designercore/model/model.cpp @@ -598,9 +598,9 @@ void ModelPrivate::notifyImport3DSupportChanged(const QVariantMap &supportMap) notifyInstanceChanges([&](AbstractView *view) { view->updateImport3DSupport(supportMap); }); } -void ModelPrivate::notifyNodeAtPosResult(const ModelNode &modelNode) +void ModelPrivate::notifyNodeAtPosResult(const ModelNode &modelNode, const QVector3D &pos3d) { - notifyInstanceChanges([&](AbstractView *view) { view->nodeAtPosReady(modelNode); }); + notifyInstanceChanges([&](AbstractView *view) { view->nodeAtPosReady(modelNode, pos3d); }); } void ModelPrivate::notifyDragStarted(QMimeData *mimeData) diff --git a/src/plugins/qmldesigner/designercore/model/model_p.h b/src/plugins/qmldesigner/designercore/model/model_p.h index f2c31a1730a..c001e7fd6d1 100644 --- a/src/plugins/qmldesigner/designercore/model/model_p.h +++ b/src/plugins/qmldesigner/designercore/model/model_p.h @@ -29,6 +29,7 @@ #include #include #include +#include #include "modelnode.h" #include "abstractview.h" @@ -186,7 +187,7 @@ public: void notifyUpdateActiveScene3D(const QVariantMap &sceneState); void notifyModelNodePreviewPixmapChanged(const ModelNode &node, const QPixmap &pixmap); void notifyImport3DSupportChanged(const QVariantMap &supportMap); - void notifyNodeAtPosResult(const ModelNode &modelNode); + void notifyNodeAtPosResult(const ModelNode &modelNode, const QVector3D &pos3d); void notifyDragStarted(QMimeData *mimeData); void notifyDragEnded(); diff --git a/src/plugins/qmldesigner/designercore/model/qmlvisualnode.cpp b/src/plugins/qmldesigner/designercore/model/qmlvisualnode.cpp index b375804c311..eec4d4dc997 100644 --- a/src/plugins/qmldesigner/designercore/model/qmlvisualnode.cpp +++ b/src/plugins/qmldesigner/designercore/model/qmlvisualnode.cpp @@ -288,7 +288,7 @@ QmlObjectNode QmlVisualNode::createQmlObjectNode(AbstractView *view, QList propertyBindingList; QList propertyEnumList; if (itemLibraryEntry.qmlSource().isEmpty()) { - QList > propertyPairList = position.propertyPairList(); + QList > propertyPairList; for (const auto &property : itemLibraryEntry.properties()) { if (property.type() == "binding") { @@ -302,6 +302,8 @@ QmlObjectNode QmlVisualNode::createQmlObjectNode(AbstractView *view, propertyPairList.append({property.name(), property.value()}); } } + // Add position last so it'll override any default position specified in the entry + propertyPairList.append(position.propertyPairList()); ModelNode::NodeSourceType nodeSourceType = ModelNode::NodeWithoutSource; if (itemLibraryEntry.typeName() == "QtQml.Component")