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