diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml index efbfcd56421..2bf81b837f1 100644 --- a/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml @@ -543,15 +543,60 @@ Item { MouseArea { anchors.fill: parent acceptedButtons: Qt.LeftButton - onClicked: { + hoverEnabled: false + + property MouseArea3D freeDraggerArea + property point pressPoint + property bool initialMoveBlock: false + + onPressed: { if (viewRoot.editView) { var pickResult = viewRoot.editView.pick(mouse.x, mouse.y); handleObjectClicked(_generalHelper.resolvePick(pickResult.objectHit), mouse.modifiers & Qt.ControlModifier); - if (!pickResult.objectHit) + + if (pickResult.objectHit) { + if (transformMode === EditView3D.TransformMode.Move) + freeDraggerArea = moveGizmo.freeDraggerArea; + else if (transformMode === EditView3D.TransformMode.Rotate) + freeDraggerArea = rotateGizmo.freeDraggerArea; + else if (transformMode === EditView3D.TransformMode.Scale) + freeDraggerArea = scaleGizmo.freeDraggerArea; + pressPoint.x = mouse.x; + pressPoint.y = mouse.y; + initialMoveBlock = true; + } else { mouse.accepted = false; + } } } + onPositionChanged: { + if (freeDraggerArea) { + if (initialMoveBlock && Math.abs(pressPoint.x - mouse.x) + Math.abs(pressPoint.y - mouse.y) > 10) { + // Don't force press event at actual press, as that puts the gizmo + // in free-dragging state, which is bad UX if drag is not actually done + freeDraggerArea.forcePressEvent(pressPoint.x, pressPoint.y); + freeDraggerArea.forceMoveEvent(mouse.x, mouse.y); + initialMoveBlock = false; + } else { + freeDraggerArea.forceMoveEvent(mouse.x, mouse.y); + } + } + } + + function handleRelease(mouse) + { + if (freeDraggerArea) { + if (initialMoveBlock) + freeDraggerArea.forceReleaseEvent(pressPoint.x, pressPoint.y); + else + freeDraggerArea.forceReleaseEvent(mouse.x, mouse.y); + freeDraggerArea = null; + } + } + + onReleased: handleRelease(mouse) + onCanceled: handleRelease(mouse) } DropArea { diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/MoveGizmo.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/MoveGizmo.qml index 493e6cc3c25..98777031fb8 100644 --- a/share/qtcreator/qml/qmlpuppet/mockfiles/MoveGizmo.qml +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/MoveGizmo.qml @@ -38,6 +38,7 @@ Node { || planeX.dragging || planeY.dragging || planeZ.dragging || centerBall.dragging property MouseArea3D dragHelper: null + property alias freeDraggerArea: centerBall.mouseArea position: dragHelper.pivotScenePosition(targetNode) diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/PlanarDraggable.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/PlanarDraggable.qml index 9015a127d95..41a44f23863 100644 --- a/share/qtcreator/qml/qmlpuppet/mockfiles/PlanarDraggable.qml +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/PlanarDraggable.qml @@ -37,6 +37,7 @@ Model { property bool dragging: mouseArea.dragging property bool active: false property MouseArea3D dragHelper: null + property alias mouseArea: mouseArea readonly property bool hovering: mouseArea.hovering diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/RotateGizmo.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/RotateGizmo.qml index 54d2d3a0a3e..8ed85f32969 100644 --- a/share/qtcreator/qml/qmlpuppet/mockfiles/RotateGizmo.qml +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/RotateGizmo.qml @@ -39,6 +39,7 @@ Node { property MouseArea3D dragHelper: null property real currentAngle property point currentMousePos + property alias freeDraggerArea: mouseAreaFree position: dragHelper.pivotScenePosition(targetNode) diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/ScaleGizmo.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/ScaleGizmo.qml index 3b4918e272c..ff64957699a 100644 --- a/share/qtcreator/qml/qmlpuppet/mockfiles/ScaleGizmo.qml +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/ScaleGizmo.qml @@ -37,6 +37,7 @@ Node { || planeX.dragging || planeY.dragging || planeZ.dragging || centerMouseArea.dragging property MouseArea3D dragHelper: null + property alias freeDraggerArea: centerMouseArea position: dragHelper.pivotScenePosition(targetNode) diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/mousearea3d.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/mousearea3d.cpp index 89c33c29005..03ec0f56d99 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/mousearea3d.cpp +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/mousearea3d.cpp @@ -512,6 +512,32 @@ double MouseArea3D::getRelativeScale(QQuick3DNode *node) const return (scenePos1 - scenePos2).length() / 100.; } +void MouseArea3D::forcePressEvent(double x, double y) +{ + m_forceCaptureNextPress = true; + + Qt::MouseButtons buttons; + Qt::KeyboardModifiers mods; + QMouseEvent event(QEvent::MouseButtonPress, QPointF(x, y), Qt::LeftButton, buttons, mods); + eventFilter(m_view3D, &event); +} + +void QmlDesigner::Internal::MouseArea3D::forceMoveEvent(double x, double y) +{ + Qt::MouseButtons buttons; + Qt::KeyboardModifiers mods; + QMouseEvent event(QEvent::MouseMove, QPointF(x, y), Qt::LeftButton, buttons, mods); + eventFilter(m_view3D, &event); +} + +void QmlDesigner::Internal::MouseArea3D::forceReleaseEvent(double x, double y) +{ + Qt::MouseButtons buttons; + Qt::KeyboardModifiers mods; + QMouseEvent event(QEvent::MouseButtonRelease, QPointF(x, y), Qt::LeftButton, buttons, mods); + eventFilter(m_view3D, &event); +} + QVector3D MouseArea3D::getMousePosInPlane(const MouseArea3D *helper, const QPointF &mousePosInView) const { @@ -535,7 +561,8 @@ QVector3D MouseArea3D::getMousePosInPlane(const MouseArea3D *helper, bool MouseArea3D::eventFilter(QObject *, QEvent *event) { if (!m_active || (m_grabsMouse && s_mouseGrab && s_mouseGrab != this - && (m_priority <= s_mouseGrab->m_priority || s_mouseGrab->m_dragging))) { + && (m_priority <= s_mouseGrab->m_priority || s_mouseGrab->m_dragging + || s_mouseGrab->m_forceCaptureNextPress))) { return false; } @@ -596,7 +623,8 @@ bool MouseArea3D::eventFilter(QObject *, QEvent *event) m_dragHelper->setScale(sceneScale()); } m_mousePosInPlane = getMousePosInPlane(m_dragHelper, mouseEvent->pos()); - if (mouseOnTopOfMouseArea(m_mousePosInPlane, mouseEvent->pos())) { + if (m_forceCaptureNextPress || mouseOnTopOfMouseArea(m_mousePosInPlane, mouseEvent->pos())) { + m_forceCaptureNextPress = false; setDragging(true); emit pressed(m_mousePosInPlane.toVector2D(), mouseEvent->pos(), pickAngle); if (m_grabsMouse) { diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/mousearea3d.h b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/mousearea3d.h index 11b6de3f0f9..1cb91cab337 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/mousearea3d.h +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/mousearea3d.h @@ -116,6 +116,10 @@ public slots: Q_INVOKABLE QVector3D pivotScenePosition(QQuick3DNode *node) const; Q_INVOKABLE double getRelativeScale(QQuick3DNode *node) const; + Q_INVOKABLE void forcePressEvent(double x, double y); + Q_INVOKABLE void forceMoveEvent(double x, double y); + Q_INVOKABLE void forceReleaseEvent(double x, double y); + signals: void view3DChanged(); @@ -171,6 +175,7 @@ private: qreal m_minAngle = 0.; QQuick3DNode *m_pickNode = nullptr; MouseArea3D *m_dragHelper = nullptr; + bool m_forceCaptureNextPress = false; }; }