diff options
5 files changed, 237 insertions, 82 deletions
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/Arrow.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/Arrow.qml index 74eaeac509..0176a55dfa 100644 --- a/share/qtcreator/qml/qmlpuppet/mockfiles/Arrow.qml +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/Arrow.qml @@ -35,7 +35,7 @@ Model { property View3D view3D property alias color: material.emissiveColor property Node targetNode: null - property bool isDragging: false + property bool dragging: false readonly property bool hovering: mouseAreaYZ.hovering || mouseAreaXZ.hovering @@ -47,7 +47,7 @@ Model { materials: DefaultMaterial { id: material - emissiveColor: mouseAreaFront.hovering ? "white" : Qt.rgba(1.0, 0.0, 0.0, 1.0) + emissiveColor: "white" lighting: DefaultMaterial.NoLighting } @@ -60,7 +60,7 @@ Model { _pointerPosPressed = mouseArea.mapPositionToScene(maskedPosition); var sp = targetNode.scenePosition; _targetStartPos = Qt.vector3d(sp.x, sp.y, sp.z); - isDragging = true; + dragging = true; } function posInParent(mouseArea, pointerPosition) @@ -95,7 +95,7 @@ Model { return; targetNode.position = posInParent(mouseArea, pointerPosition); - isDragging = false; + dragging = false; arrow.positionCommit(); } diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml index b4a86490c5..e19e75acb8 100644 --- a/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml @@ -112,11 +112,7 @@ Window { targetNode: viewWindow.selectedNode position: viewWindow.selectedNode ? viewWindow.selectedNode.scenePosition : Qt.vector3d(0, 0, 0) - - rotation: globalControl.checked || !viewWindow.selectedNode - ? Qt.vector3d(0, 0, 0) - : viewWindow.selectedNode.sceneRotation - + globalOrientation: globalControl.checked visible: selectedNode view3D: overlayView @@ -194,7 +190,7 @@ Window { targetView: overlayView offsetX: 0 offsetY: 45 - visible: moveGizmo.isDragging + visible: moveGizmo.dragging Rectangle { color: "white" diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/MoveGizmo.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/MoveGizmo.qml index ded8acc7d3..7ad5a2a011 100644 --- a/share/qtcreator/qml/qmlpuppet/mockfiles/MoveGizmo.qml +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/MoveGizmo.qml @@ -25,56 +25,131 @@ import QtQuick 2.0 import QtQuick3D 1.0 +import MouseArea3D 1.0 Node { - id: arrows + id: moveGizmo property View3D view3D property bool highlightOnHover: false property Node targetNode: null - readonly property bool isDragging: arrowX.isDragging || arrowY.isDragging || arrowZ.isDragging - - scale: Qt.vector3d(5, 5, 5) + property bool globalOrientation: true + readonly property bool dragging: arrowX.dragging || arrowY.dragging || arrowZ.dragging + || centerMouseArea.dragging signal positionCommit() signal positionMove() - Arrow { - id: arrowX - objectName: "Arrow X" - rotation: Qt.vector3d(0, 0, -90) - targetNode: arrows.targetNode - color: highlightOnHover && hovering ? Qt.lighter(Qt.rgba(1, 0, 0, 1)) - : Qt.rgba(1, 0, 0, 1) - view3D: arrows.view3D - - onPositionCommit: arrows.positionCommit() - onPositionMove: arrows.positionMove() - } + Node { + rotation: globalOrientation || !targetNode ? Qt.vector3d(0, 0, 0) : targetNode.sceneRotation + + Arrow { + id: arrowX + objectName: "Arrow X" + rotation: Qt.vector3d(0, 0, -90) + targetNode: moveGizmo.targetNode + color: highlightOnHover && (hovering || dragging) ? Qt.lighter(Qt.rgba(1, 0, 0, 1)) + : Qt.rgba(1, 0, 0, 1) + view3D: moveGizmo.view3D + + onPositionCommit: moveGizmo.positionCommit() + onPositionMove: moveGizmo.positionMove() + } + + Arrow { + id: arrowY + objectName: "Arrow Y" + rotation: Qt.vector3d(0, 0, 0) + targetNode: moveGizmo.targetNode + color: highlightOnHover && (hovering || dragging) ? Qt.lighter(Qt.rgba(0, 0, 1, 1)) + : Qt.rgba(0, 0, 1, 1) + view3D: moveGizmo.view3D + + onPositionCommit: moveGizmo.positionCommit() + onPositionMove: moveGizmo.positionMove() + } + + Arrow { + id: arrowZ + objectName: "Arrow Z" + rotation: Qt.vector3d(90, 0, 0) + targetNode: moveGizmo.targetNode + color: highlightOnHover && (hovering || dragging) ? Qt.lighter(Qt.rgba(0, 0.6, 0, 1)) + : Qt.rgba(0, 0.6, 0, 1) + view3D: moveGizmo.view3D + + onPositionCommit: moveGizmo.positionCommit() + onPositionMove: moveGizmo.positionMove() + } - Arrow { - id: arrowY - objectName: "Arrow Y" - rotation: Qt.vector3d(0, 0, 0) - targetNode: arrows.targetNode - color: highlightOnHover && hovering ? Qt.lighter(Qt.rgba(0, 0, 1, 1)) - : Qt.rgba(0, 0, 1, 1) - view3D: arrows.view3D - - onPositionCommit: arrows.positionCommit() - onPositionMove: arrows.positionMove() } - Arrow { - id: arrowZ - objectName: "Arrow Z" - rotation: Qt.vector3d(90, 0, 0) - targetNode: arrows.targetNode - color: highlightOnHover && hovering ? Qt.lighter(Qt.rgba(0, 0.6, 0, 1)) - : Qt.rgba(0, 0.6, 0, 1) - view3D: arrows.view3D - - onPositionCommit: arrows.positionCommit() - onPositionMove: arrows.positionMove() + Model { + id: centerBall + + source: "#Sphere" + scale: Qt.vector3d(0.024, 0.024, 0.024) + materials: DefaultMaterial { + id: material + emissiveColor: highlightOnHover + && (centerMouseArea.hovering || centerMouseArea.dragging) + ? Qt.lighter(Qt.rgba(0.5, 0.5, 0.5, 1)) + : Qt.rgba(0.5, 0.5, 0.5, 1) + lighting: DefaultMaterial.NoLighting + } + + MouseArea3D { + id: centerMouseArea + view3D: moveGizmo.view3D + x: -60 + y: -60 + width: 120 + height: 120 + rotation: view3D.camera.rotation + grabsMouse: moveGizmo.targetNode + priority: 1 + + property var _pointerPosPressed + property var _targetStartPos + + function posInParent(pointerPosition) + { + var scenePointerPos = mapPositionToScene(pointerPosition); + var sceneRelativeDistance = Qt.vector3d( + scenePointerPos.x - _pointerPosPressed.x, + scenePointerPos.y - _pointerPosPressed.y, + scenePointerPos.z - _pointerPosPressed.z); + + var newScenePos = Qt.vector3d( + _targetStartPos.x + sceneRelativeDistance.x, + _targetStartPos.y + sceneRelativeDistance.y, + _targetStartPos.z + sceneRelativeDistance.z); + + return moveGizmo.targetNode.parent.mapPositionFromScene(newScenePos); + } + + onPressed: { + if (!moveGizmo.targetNode) + return; + + _pointerPosPressed = mapPositionToScene(pointerPosition); + var sp = moveGizmo.targetNode.scenePosition; + _targetStartPos = Qt.vector3d(sp.x, sp.y, sp.z); + } + onDragged: { + if (!moveGizmo.targetNode) + return; + + moveGizmo.targetNode.position = posInParent(pointerPosition); + moveGizmo.positionMove(); + } + onReleased: { + if (!moveGizmo.targetNode) + return; + + moveGizmo.targetNode.position = posInParent(pointerPosition); + moveGizmo.positionCommit(); + } + } } } diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/mousearea3d.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/mousearea3d.cpp index e3ec5c704b..4c1fdcc78e 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/mousearea3d.cpp +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/mousearea3d.cpp @@ -80,6 +80,11 @@ qreal MouseArea3D::height() const return m_height; } +int MouseArea3D::priority() const +{ + return m_priority; +} + void MouseArea3D::setView3D(QQuick3DViewport *view3D) { if (m_view3D == view3D) @@ -134,6 +139,15 @@ void MouseArea3D::setHeight(qreal height) emit heightChanged(height); } +void MouseArea3D::setPriority(int level) +{ + if (m_priority == level) + return; + + m_priority = level; + emit priorityChanged(level); +} + void MouseArea3D::componentComplete() { if (!m_view3D) { @@ -193,51 +207,94 @@ QVector3D MouseArea3D::getMousePosInPlane(const QPointF &mousePosInView) const bool MouseArea3D::eventFilter(QObject *, QEvent *event) { + if (m_grabsMouse && s_mouseGrab && s_mouseGrab != this + && (m_priority <= s_mouseGrab->m_priority || s_mouseGrab->m_dragging)) { + return false; + } + + auto mouseOnTopOfMouseArea = [this](const QVector3D &mousePosInPlane) -> bool { + return !qFuzzyCompare(mousePosInPlane.z(), -1) + && mousePosInPlane.x() >= float(m_x) + && mousePosInPlane.x() <= float(m_x + m_width) + && mousePosInPlane.y() >= float(m_y) + && mousePosInPlane.y() <= float(m_y + m_height); + }; + switch (event->type()) { + case QEvent::MouseButtonPress: { + auto const mouseEvent = static_cast<QMouseEvent *>(event); + if (mouseEvent->button() == Qt::LeftButton) { + m_mousePosInPlane = getMousePosInPlane(mouseEvent->pos()); + if (mouseOnTopOfMouseArea(m_mousePosInPlane)) { + setDragging(true); + emit pressed(m_mousePosInPlane); + if (m_grabsMouse) { + if (s_mouseGrab && s_mouseGrab != this) { + s_mouseGrab->setDragging(false); + s_mouseGrab->setHovering(false); + } + s_mouseGrab = this; + setHovering(true); + } + event->accept(); + return true; + } + } + break; + } + case QEvent::MouseButtonRelease: { + auto const mouseEvent = static_cast<QMouseEvent *>(event); + if (mouseEvent->button() == Qt::LeftButton) { + if (m_dragging) { + QVector3D mousePosInPlane = getMousePosInPlane(mouseEvent->pos()); + if (qFuzzyCompare(mousePosInPlane.z(), -1)) + mousePosInPlane = m_mousePosInPlane; + setDragging(false); + emit released(mousePosInPlane); + if (m_grabsMouse) { + if (s_mouseGrab && s_mouseGrab != this) { + s_mouseGrab->setDragging(false); + s_mouseGrab->setHovering(false); + } + if (mouseOnTopOfMouseArea(mousePosInPlane)) { + s_mouseGrab = this; + setHovering(true); + } else { + s_mouseGrab = nullptr; + setHovering(false); + } + } + event->accept(); + return true; + } + } + break; + } + case QEvent::MouseMove: case QEvent::HoverMove: { - if (m_grabsMouse && s_mouseGrab && s_mouseGrab != this) - break; - auto const mouseEvent = static_cast<QMouseEvent *>(event); const QVector3D mousePosInPlane = getMousePosInPlane(mouseEvent->pos()); - if (qFuzzyCompare(mousePosInPlane.z(), -1)) - break; - - const bool mouseOnTopOfMouseArea = - mousePosInPlane.x() >= float(m_x) && - mousePosInPlane.x() <= float(m_x + m_width) && - mousePosInPlane.y() >= float(m_y) && - mousePosInPlane.y() <= float(m_y + m_height); + const bool hasMouse = mouseOnTopOfMouseArea(mousePosInPlane); - const bool buttonPressed = QGuiApplication::mouseButtons().testFlag(Qt::LeftButton); + setHovering(hasMouse); - // The filter will detect a mouse press on the view, but not a mouse release, since the - // former is not accepted by the view, which means that the release will end up being - // sent elsewhere. So we need this extra logic inside HoverMove, rather than in - // MouseButtonRelease, which would otherwise be more elegant. + if (m_grabsMouse) { + if (m_hovering && s_mouseGrab && s_mouseGrab != this) + s_mouseGrab->setHovering(false); - if (m_hovering != mouseOnTopOfMouseArea) { - m_hovering = mouseOnTopOfMouseArea; - emit hoveringChanged(); + if (m_hovering || m_dragging) + s_mouseGrab = this; + else if (s_mouseGrab == this) + s_mouseGrab = nullptr; } - if (!m_dragging && m_hovering && buttonPressed) { - m_dragging = true; - emit pressed(mousePosInPlane); - emit draggingChanged(); - } else if (m_dragging && !buttonPressed) { - m_dragging = false; - emit released(mousePosInPlane); - emit draggingChanged(); - } - - if (m_grabsMouse) - s_mouseGrab = m_hovering || m_dragging ? this : nullptr; - - if (m_dragging) + if (m_dragging && !qFuzzyCompare(mousePosInPlane.z(), -1)) { + m_mousePosInPlane = mousePosInPlane; emit dragged(mousePosInPlane); + } - break; } + break; + } default: break; } @@ -245,6 +302,24 @@ bool MouseArea3D::eventFilter(QObject *, QEvent *event) return false; } +void MouseArea3D::setDragging(bool enable) +{ + if (m_dragging == enable) + return; + + m_dragging = enable; + emit draggingChanged(); +} + +void MouseArea3D::setHovering(bool enable) +{ + if (m_hovering == enable) + return; + + m_hovering = enable; + emit hoveringChanged(); +} + } } diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/mousearea3d.h b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/mousearea3d.h index b42b438b47..99a34be353 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/mousearea3d.h +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/mousearea3d.h @@ -48,6 +48,7 @@ class MouseArea3D : public QQuick3DNode Q_PROPERTY(qreal height READ height WRITE setHeight NOTIFY heightChanged) Q_PROPERTY(bool hovering READ hovering NOTIFY hoveringChanged) Q_PROPERTY(bool dragging READ dragging NOTIFY draggingChanged) + Q_PROPERTY(int priority READ priority WRITE setPriority NOTIFY priorityChanged) Q_INTERFACES(QQmlParserStatus) @@ -60,6 +61,7 @@ public: qreal y() const; qreal width() const; qreal height() const; + int priority() const; bool hovering() const; bool dragging() const; @@ -73,6 +75,7 @@ public slots: 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, @@ -86,6 +89,7 @@ signals: void yChanged(qreal y); void widthChanged(qreal width); void heightChanged(qreal height); + void priorityChanged(int level); void hoveringChanged(); void draggingChanged(); @@ -100,6 +104,9 @@ protected: bool eventFilter(QObject *obj, QEvent *event) override; private: + void setDragging(bool enable); + void setHovering(bool enable); + Q_DISABLE_COPY(MouseArea3D) QQuick3DViewport *m_view3D = nullptr; @@ -107,6 +114,7 @@ private: qreal m_y; qreal m_width; qreal m_height; + int m_priority = 0; bool m_hovering = false; bool m_dragging = false; @@ -115,6 +123,7 @@ private: static MouseArea3D *s_mouseGrab; bool m_grabsMouse; + QVector3D m_mousePosInPlane; }; } |
