From fccc02de96861d2909bfae7078c65d4e10ec2497 Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Tue, 30 Jun 2020 14:48:34 +0300 Subject: [PATCH] QmlDesigner: Allow starting free drag on initial selection press Changed object selection to be done on press instead of click, and the initial press now also starts free drag of the selected object after a short distance moved to prevent accidental drags. Change-Id: I61656661cd734d167ef9f8db42d986f0e97402a3 Fixes: QDS-2376 Reviewed-by: Thomas Hartmann Reviewed-by: Mahmoud Badri --- .../qml/qmlpuppet/mockfiles/EditView3D.qml | 49 ++++++++++++++++++- .../qml/qmlpuppet/mockfiles/MoveGizmo.qml | 1 + .../qmlpuppet/mockfiles/PlanarDraggable.qml | 1 + .../qml/qmlpuppet/mockfiles/RotateGizmo.qml | 1 + .../qml/qmlpuppet/mockfiles/ScaleGizmo.qml | 1 + .../qml2puppet/editor3d/mousearea3d.cpp | 32 +++++++++++- .../qml2puppet/editor3d/mousearea3d.h | 5 ++ 7 files changed, 86 insertions(+), 4 deletions(-) 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; }; }