diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml index 1dcca048e72..88cee4535d0 100644 --- a/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml @@ -278,12 +278,12 @@ Window { x: 8 RadioButton { id: moveToolControl - checked: false + checked: true text: qsTr("Move Tool") } RadioButton { id: scaleToolControl - checked: true + checked: false text: qsTr("Scale Tool") } } diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/MoveGizmo.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/MoveGizmo.qml index c035f9c85ed..b8e6cdafb94 100644 --- a/share/qtcreator/qml/qmlpuppet/mockfiles/MoveGizmo.qml +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/MoveGizmo.qml @@ -35,7 +35,8 @@ Node { property Node targetNode: null property bool globalOrientation: true readonly property bool dragging: arrowX.dragging || arrowY.dragging || arrowZ.dragging - || centerMouseArea.dragging + || planeX.dragging || planeY.dragging || planeZ.dragging + || centerBall.dragging signal positionCommit() signal positionMove() @@ -45,7 +46,6 @@ Node { 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)) @@ -59,7 +59,6 @@ Node { 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.6, 0, 1)) @@ -73,7 +72,6 @@ Node { 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, 1, 1)) @@ -85,75 +83,72 @@ Node { onPositionMove: moveGizmo.positionMove() } + PlanarMoveHandle { + id: planeX + + y: 10 + z: 10 + + rotation: Qt.vector3d(0, 90, 0) + targetNode: moveGizmo.targetNode + color: highlightOnHover && (hovering || dragging) ? Qt.lighter(Qt.rgba(1, 0, 0, 1)) + : Qt.rgba(1, 0, 0, 1) + view3D: moveGizmo.view3D + active: moveGizmo.visible + + onPositionCommit: moveGizmo.positionCommit() + onPositionMove: moveGizmo.positionMove() + } + + PlanarMoveHandle { + id: planeY + + x: 10 + z: 10 + + 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 + active: moveGizmo.visible + + onPositionCommit: moveGizmo.positionCommit() + onPositionMove: moveGizmo.positionMove() + } + + PlanarMoveHandle { + id: planeZ + + x: 10 + y: 10 + + 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 + active: moveGizmo.visible + + onPositionCommit: moveGizmo.positionCommit() + onPositionMove: moveGizmo.positionMove() + } } - Model { + PlanarMoveHandle { 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 - } + color: highlightOnHover && (hovering || dragging) ? Qt.lighter(Qt.rgba(0.5, 0.5, 0.5, 1)) + : Qt.rgba(0.5, 0.5, 0.5, 1) + rotation: view3D.camera.rotation + priority: 1 + targetNode: moveGizmo.targetNode - MouseArea3D { - id: centerMouseArea - view3D: moveGizmo.view3D - x: -60 - y: -60 - width: 120 - height: 120 - rotation: view3D.camera.rotation - grabsMouse: moveGizmo.targetNode - priority: 1 - active: moveGizmo.visible + view3D: moveGizmo.view3D + active: moveGizmo.visible - property var _pointerPosPressed - property var _targetStartPos - - function localPos(scenePos) - { - var scenePointerPos = mapPositionToScene(scenePos); - 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(scenePos); - var sp = moveGizmo.targetNode.scenePosition; - _targetStartPos = Qt.vector3d(sp.x, sp.y, sp.z); - } - onDragged: { - if (!moveGizmo.targetNode) - return; - - moveGizmo.targetNode.position = localPos(scenePos); - moveGizmo.positionMove(); - } - onReleased: { - if (!moveGizmo.targetNode) - return; - - moveGizmo.targetNode.position = localPos(scenePos); - moveGizmo.positionCommit(); - } - } + onPositionCommit: moveGizmo.positionCommit() + onPositionMove: moveGizmo.positionMove() } } diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/PlanarDraggable.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/PlanarDraggable.qml new file mode 100644 index 00000000000..f931ef77c49 --- /dev/null +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/PlanarDraggable.qml @@ -0,0 +1,118 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick3D 1.0 +import MouseArea3D 1.0 + +Model { + id: rootModel + + property View3D view3D + property alias color: gizmoMaterial.emissiveColor + property alias priority: mouseArea.priority + property Node targetNode: null + property bool dragging: false + property bool active: false + + readonly property bool hovering: mouseArea.hovering + + property var _pointerPosPressed + property var _targetStartPos + + signal pressed(var mouseArea) + signal dragged(var mouseArea, vector3d sceneRelativeDistance) + signal released(var mouseArea, vector3d sceneRelativeDistance) + + rotationOrder: Node.XYZr + source: "#Rectangle" + + // Workaround for Material.DisableCulling bug QTBUG-79768: Show the back with another model + Model { + source: rootModel.source + rotationOrder: rootModel.rotationOrder + materials: gizmoMaterial + rotation: Qt.vector3d(0, 180, 0) + } + + DefaultMaterial { + id: gizmoMaterial + emissiveColor: "white" + lighting: DefaultMaterial.NoLighting + } + materials: gizmoMaterial + + function handlePressed(mouseArea, scenePos) + { + if (!targetNode) + return; + + _pointerPosPressed = mouseArea.mapPositionToScene(scenePos); + var sp = targetNode.scenePosition; + _targetStartPos = Qt.vector3d(sp.x, sp.y, sp.z); + dragging = true; + pressed(mouseArea); + } + + function calcRelativeDistance(mouseArea, scenePos) + { + var scenePointerPos = mouseArea.mapPositionToScene(scenePos); + return Qt.vector3d(scenePointerPos.x - _pointerPosPressed.x, + scenePointerPos.y - _pointerPosPressed.y, + scenePointerPos.z - _pointerPosPressed.z); + } + + function handleDragged(mouseArea, scenePos) + { + if (!targetNode) + return; + + dragged(mouseArea, calcRelativeDistance(mouseArea, scenePos)); + } + + function handleReleased(mouseArea, scenePos) + { + if (!targetNode) + return; + + released(mouseArea, calcRelativeDistance(mouseArea, scenePos)); + dragging = false; + } + + MouseArea3D { + id: mouseArea + view3D: rootModel.view3D + x: -60 + y: -60 + width: 120 + height: 120 + grabsMouse: targetNode + active: rootModel.active + onPressed: rootModel.handlePressed(mouseArea, scenePos) + onDragged: rootModel.handleDragged(mouseArea, scenePos) + onReleased: rootModel.handleReleased(mouseArea, scenePos) + } +} + diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/PlanarMoveHandle.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/PlanarMoveHandle.qml new file mode 100644 index 00000000000..f79ae6e248e --- /dev/null +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/PlanarMoveHandle.qml @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick3D 1.0 +import MouseArea3D 1.0 + +PlanarDraggable { + id: planarHandle + scale: Qt.vector3d(0.024, 0.024, 0.024) + + signal positionCommit() + signal positionMove() + + function localPos(sceneRelativeDistance) + { + var newScenePos = Qt.vector3d( + _targetStartPos.x + sceneRelativeDistance.x, + _targetStartPos.y + sceneRelativeDistance.y, + _targetStartPos.z + sceneRelativeDistance.z); + return targetNode.parent.mapPositionFromScene(newScenePos); + } + + onDragged: { + targetNode.position = localPos(sceneRelativeDistance); + positionMove(); + } + + onReleased: { + targetNode.position = localPos(sceneRelativeDistance); + positionCommit(); + } +} diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/PlanarScaleHandle.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/PlanarScaleHandle.qml new file mode 100644 index 00000000000..dfdfb7c1969 --- /dev/null +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/PlanarScaleHandle.qml @@ -0,0 +1,61 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick3D 1.0 +import MouseArea3D 1.0 + +PlanarDraggable { + id: planarHandle + scale: Qt.vector3d(0.024, 0.024, 0.024) + + property bool globalOrientation: false + + signal scaleCommit() + signal scaleChange() + + property var _startScale + + onPressed: { + // Recreate vector so we don't follow the changes in targetNode.sceneScale + _startScale = Qt.vector3d(targetNode.sceneScale.x, + targetNode.sceneScale.y, + targetNode.sceneScale.z); + } + + onDragged: { + targetNode.scale = mouseArea.getNewScale(targetNode, _startScale, + _pointerPosPressed, sceneRelativeDistance, + globalOrientation); + scaleChange(); + } + + onReleased: { + targetNode.scale = mouseArea.getNewScale(targetNode, _startScale, + _pointerPosPressed, sceneRelativeDistance, + globalOrientation); + scaleCommit(); + } +} diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/ScaleGizmo.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/ScaleGizmo.qml index 7f4a4f69b8a..8a55812e71a 100644 --- a/share/qtcreator/qml/qmlpuppet/mockfiles/ScaleGizmo.qml +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/ScaleGizmo.qml @@ -35,6 +35,7 @@ Node { property Node targetNode: null property bool globalOrientation: true readonly property bool dragging: scaleRodX.dragging || scaleRodY.dragging || scaleRodZ.dragging + || planeX.dragging || planeY.dragging || planeZ.dragging || centerMouseArea.dragging signal scaleCommit() @@ -45,13 +46,13 @@ Node { ScaleRod { id: scaleRodX - objectName: "scaleRod X" rotation: Qt.vector3d(0, 0, -90) targetNode: scaleGizmo.targetNode color: highlightOnHover && (hovering || dragging) ? Qt.lighter(Qt.rgba(1, 0, 0, 1)) : Qt.rgba(1, 0, 0, 1) view3D: scaleGizmo.view3D active: scaleGizmo.visible + globalOrientation: scaleGizmo.globalOrientation onScaleCommit: scaleGizmo.scaleCommit() onScaleChange: scaleGizmo.scaleChange() @@ -59,13 +60,13 @@ Node { ScaleRod { id: scaleRodY - objectName: "scaleRod Y" rotation: Qt.vector3d(0, 0, 0) targetNode: scaleGizmo.targetNode color: highlightOnHover && (hovering || dragging) ? Qt.lighter(Qt.rgba(0, 0.6, 0, 1)) : Qt.rgba(0, 0.6, 0, 1) view3D: scaleGizmo.view3D active: scaleGizmo.visible + globalOrientation: scaleGizmo.globalOrientation onScaleCommit: scaleGizmo.scaleCommit() onScaleChange: scaleGizmo.scaleChange() @@ -73,13 +74,67 @@ Node { ScaleRod { id: scaleRodZ - objectName: "scaleRod Z" rotation: Qt.vector3d(90, 0, 0) targetNode: scaleGizmo.targetNode color: highlightOnHover && (hovering || dragging) ? Qt.lighter(Qt.rgba(0, 0, 1, 1)) : Qt.rgba(0, 0, 1, 1) view3D: scaleGizmo.view3D active: scaleGizmo.visible + globalOrientation: scaleGizmo.globalOrientation + + onScaleCommit: scaleGizmo.scaleCommit() + onScaleChange: scaleGizmo.scaleChange() + } + + PlanarScaleHandle { + id: planeX + + y: 10 + z: 10 + + rotation: Qt.vector3d(0, 90, 0) + targetNode: scaleGizmo.targetNode + color: highlightOnHover && (hovering || dragging) ? Qt.lighter(Qt.rgba(1, 0, 0, 1)) + : Qt.rgba(1, 0, 0, 1) + view3D: scaleGizmo.view3D + active: scaleGizmo.visible + globalOrientation: scaleGizmo.globalOrientation + + onScaleCommit: scaleGizmo.scaleCommit() + onScaleChange: scaleGizmo.scaleChange() + } + + PlanarScaleHandle { + id: planeY + + x: 10 + z: 10 + + rotation: Qt.vector3d(90, 0, 0) + targetNode: scaleGizmo.targetNode + color: highlightOnHover && (hovering || dragging) ? Qt.lighter(Qt.rgba(0, 0.6, 0, 1)) + : Qt.rgba(0, 0.6, 0, 1) + view3D: scaleGizmo.view3D + active: scaleGizmo.visible + globalOrientation: scaleGizmo.globalOrientation + + onScaleCommit: scaleGizmo.scaleCommit() + onScaleChange: scaleGizmo.scaleChange() + } + + PlanarScaleHandle { + id: planeZ + + x: 10 + y: 10 + + rotation: Qt.vector3d(0, 0, 0) + targetNode: scaleGizmo.targetNode + color: highlightOnHover && (hovering || dragging) ? Qt.lighter(Qt.rgba(0, 0, 1, 1)) + : Qt.rgba(0, 0, 1, 1) + view3D: scaleGizmo.view3D + active: scaleGizmo.visible + globalOrientation: scaleGizmo.globalOrientation onScaleCommit: scaleGizmo.scaleCommit() onScaleChange: scaleGizmo.scaleChange() @@ -121,7 +176,7 @@ Node { if (yDelta === 0) return; var scaler = 1.0 + (yDelta * 0.025); - if (scaler === 0 ) + if (scaler === 0) scaler = 0.0001; if (scaler < 0) scaler = -scaler; diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/ScaleRod.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/ScaleRod.qml index 4ef6d8a0a72..85fc39f900e 100644 --- a/share/qtcreator/qml/qmlpuppet/mockfiles/ScaleRod.qml +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/ScaleRod.qml @@ -31,6 +31,8 @@ DirectionalDraggable { id: scaleRod source: "meshes/scalerod.mesh" + property bool globalOrientation: false + signal scaleCommit() signal scaleChange() @@ -39,7 +41,7 @@ DirectionalDraggable { Model { source: "#Cube" y: 10 - scale: Qt.vector3d(0.025, 0.025, 0.025) + scale: Qt.vector3d(0.020, 0.020, 0.020) materials: DefaultMaterial { id: material emissiveColor: scaleRod.color @@ -47,12 +49,6 @@ DirectionalDraggable { } } - function localScale(mouseArea, sceneRelativeDistance) - { - return mouseArea.getNewScale(targetNode, _startScale, _pointerPosPressed, - sceneRelativeDistance, sceneScale.x); - } - onPressed: { // Recreate vector so we don't follow the changes in targetNode.sceneScale _startScale = Qt.vector3d(targetNode.sceneScale.x, @@ -61,12 +57,16 @@ DirectionalDraggable { } onDragged: { - targetNode.scale = localScale(mouseArea, sceneRelativeDistance); + targetNode.scale = mouseArea.getNewScale(targetNode, _startScale, + _pointerPosPressed, sceneRelativeDistance, + globalOrientation); scaleChange(); } onReleased: { - targetNode.scale = localScale(mouseArea, sceneRelativeDistance); + targetNode.scale = mouseArea.getNewScale(targetNode, _startScale, + _pointerPosPressed, sceneRelativeDistance, + globalOrientation); scaleCommit(); } } diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/mousearea3d.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/mousearea3d.cpp index fe84ed13a62..d4135de9732 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/mousearea3d.cpp +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/mousearea3d.cpp @@ -204,34 +204,36 @@ QVector3D MouseArea3D::rayIntersectsPlane(const QVector3D &rayPos0, return rayPos0 + distanceFromRayPos0ToPlane * rayDirection; } -// Get a new scale based on a relative scene distance along an axis (used to adjust scale via drag) -// This function never returns a negative scaling +// Get a new scale based on a relative scene distance along a drag axis. +// This function never returns a negative scaling. +// Note that scaling a rotated object in global coordinate space can't be meaningfully done without +// distorting the object beyond what current scale property can represent, so global scaling is +// effectively same as local scaling. QVector3D MouseArea3D::getNewScale(QQuick3DNode *node, const QVector3D &startScale, const QVector3D &pressPos, - const QVector3D &sceneRelativeDistance, float scaler) + const QVector3D &sceneRelativeDistance, bool global) { if (node) { // Note: This only returns correct scale when scale is positive auto getScale = [&](const QMatrix4x4 &m) -> QVector3D { return QVector3D(m.column(0).length(), m.column(1).length(), m.column(2).length()); }; - const float constantDragScaler = 0.1f; const float nonZeroValue = 0.0001f; - if (qFuzzyIsNull(scaler)) - scaler = nonZeroValue; - const QVector3D scenePos = node->scenePosition(); const QMatrix4x4 parentTransform = node->parentNode()->sceneTransform(); QMatrix4x4 newTransform = node->sceneTransform(); - QVector3D normalRelDist = sceneRelativeDistance.normalized(); - float direction = QVector3D::dotProduct((pressPos - scenePos).normalized(), normalRelDist); - float magnitude = constantDragScaler * sceneRelativeDistance.length() / scaler; + const QVector3D nodeToPressPos = pressPos - scenePos; + const QVector3D nodeToRelPos = nodeToPressPos + sceneRelativeDistance; + const float sceneToPressLen = nodeToPressPos.length(); + QVector3D scaleDirVector = nodeToRelPos; + float magnitude = (scaleDirVector.length() / sceneToPressLen); + scaleDirVector.normalize(); - // Reset everything but rotation to ensure translation and scale do not affect rotate below - newTransform(0,3) = 0; - newTransform(1,3) = 0; - newTransform(2,3) = 0; + // Reset everything but rotation to ensure translation and scale don't affect rotation below + newTransform(0, 3) = 0; + newTransform(1, 3) = 0; + newTransform(2, 3) = 0; QVector3D curScale = getScale(newTransform); if (qFuzzyIsNull(curScale.x())) curScale.setX(nonZeroValue); @@ -241,24 +243,29 @@ QVector3D MouseArea3D::getNewScale(QQuick3DNode *node, const QVector3D &startSca curScale.setZ(nonZeroValue); newTransform.scale({1.f / curScale.x(), 1.f / curScale.y(), 1.f / curScale.z()}); - // Rotate relative distance according to object rotation - normalRelDist = newTransform.inverted().map(normalRelDist).normalized(); + // Rotate the local scale vector so that scale axes are parallel to global axes for easier + // scale vector manipulation + if (!global) + scaleDirVector = newTransform.inverted().map(scaleDirVector).normalized(); // Ensure scaling is always positive/negative according to direction - normalRelDist.setX(qAbs(normalRelDist.x())); - normalRelDist.setY(qAbs(normalRelDist.y())); - normalRelDist.setZ(qAbs(normalRelDist.z())); - QVector3D scaleVec = normalRelDist; + scaleDirVector.setX(qAbs(scaleDirVector.x())); + scaleDirVector.setY(qAbs(scaleDirVector.y())); + scaleDirVector.setZ(qAbs(scaleDirVector.z())); + + // Make sure the longest scale vec axis is equal to 1 before applying magnitude to avoid + // initial jump in size when planar drag starts + float maxDir = qMax(qMax(scaleDirVector.x(), scaleDirVector.y()), scaleDirVector.z()); + QVector3D scaleVec = scaleDirVector / maxDir; scaleVec *= magnitude; - if (direction > 0) { - scaleVec.setX(scaleVec.x() + 1.f); - scaleVec.setY(scaleVec.y() + 1.f); - scaleVec.setZ(scaleVec.z() + 1.f); - } else { - scaleVec.setX(1.f - scaleVec.x()); - scaleVec.setY(1.f - scaleVec.y()); - scaleVec.setZ(1.f - scaleVec.z()); - } + + // Zero axes on scale vector indicate directions we don't want scaling to affect + if (qFuzzyIsNull(scaleVec.x())) + scaleVec.setX(1.f); + if (qFuzzyIsNull(scaleVec.y())) + scaleVec.setY(1.f); + if (qFuzzyIsNull(scaleVec.z())) + scaleVec.setZ(1.f); scaleVec *= startScale; newTransform = parentTransform; diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/mousearea3d.h b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/mousearea3d.h index a7e1fa261e7..af465576829 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/mousearea3d.h +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/mousearea3d.h @@ -87,7 +87,7 @@ public slots: Q_INVOKABLE QVector3D getNewScale(QQuick3DNode *node, const QVector3D &startScale, const QVector3D &pressPos, - const QVector3D &sceneRelativeDistance, float scaler); + const QVector3D &sceneRelativeDistance, bool global); signals: void view3DChanged(); diff --git a/share/qtcreator/qml/qmlpuppet/qmlpuppet.qrc b/share/qtcreator/qml/qmlpuppet/qmlpuppet.qrc index ec02e9d2567..fd17d551d8a 100644 --- a/share/qtcreator/qml/qmlpuppet/qmlpuppet.qrc +++ b/share/qtcreator/qml/qmlpuppet/qmlpuppet.qrc @@ -16,6 +16,9 @@ mockfiles/IconGizmo.qml mockfiles/Overlay2D.qml mockfiles/DirectionalDraggable.qml + mockfiles/PlanarDraggable.qml + mockfiles/PlanarMoveHandle.qml + mockfiles/PlanarScaleHandle.qml mockfiles/ScaleRod.qml mockfiles/ScaleGizmo.qml mockfiles/meshes/arrow.mesh