summaryrefslogtreecommitdiff
path: root/share/qtcreator/qml/qmlpuppet
diff options
context:
space:
mode:
authorMiikka Heikkinen <miikka.heikkinen@qt.io>2019-10-31 10:46:14 +0200
committerMiikka Heikkinen <miikka.heikkinen@qt.io>2019-11-08 12:53:21 +0000
commitc67965fb2932a129ba6aa87875007fd5b70b24fd (patch)
tree102dc22716b776fbe9a8e68ce5c4685bf84ee33c /share/qtcreator/qml/qmlpuppet
parent96f3cef06ac52f2cb82aa4078306c673a040f839 (diff)
downloadqt-creator-c67965fb2932a129ba6aa87875007fd5b70b24fd.tar.gz
QmlDesigner: Add ScaleGizmo to 3D edit view
ScaleGizmo allows scaling in the direction of local or global axes, as well as uniform scaling. Any scale component cannot be made negative with ScaleGizmo. Change-Id: I9b98d9593e07ded340178b07b73fa1b72421ba20 Fixes: QDS-1195 Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io> Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io>
Diffstat (limited to 'share/qtcreator/qml/qmlpuppet')
-rw-r--r--share/qtcreator/qml/qmlpuppet/mockfiles/Arrow.qml91
-rw-r--r--share/qtcreator/qml/qmlpuppet/mockfiles/DirectionalDraggable.qml124
-rw-r--r--share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml59
-rw-r--r--share/qtcreator/qml/qmlpuppet/mockfiles/MoveGizmo.qml24
-rw-r--r--share/qtcreator/qml/qmlpuppet/mockfiles/ScaleGizmo.qml159
-rw-r--r--share/qtcreator/qml/qmlpuppet/mockfiles/ScaleRod.qml72
-rw-r--r--share/qtcreator/qml/qmlpuppet/mockfiles/meshes/scalerod.meshbin0 -> 1756 bytes
-rw-r--r--share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/mousearea3d.cpp91
-rw-r--r--share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/mousearea3d.h15
-rw-r--r--share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp49
-rw-r--r--share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.h11
-rw-r--r--share/qtcreator/qml/qmlpuppet/qmlpuppet.qrc4
12 files changed, 561 insertions, 138 deletions
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/Arrow.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/Arrow.qml
index 0176a55dfa..67ae4c7b29 100644
--- a/share/qtcreator/qml/qmlpuppet/mockfiles/Arrow.qml
+++ b/share/qtcreator/qml/qmlpuppet/mockfiles/Arrow.qml
@@ -27,104 +27,29 @@ import QtQuick 2.0
import QtQuick3D 1.0
import MouseArea3D 1.0
-Model {
+DirectionalDraggable {
id: arrow
- rotationOrder: Node.XYZr
source: "meshes/arrow.mesh"
- property View3D view3D
- property alias color: material.emissiveColor
- property Node targetNode: null
- property bool dragging: false
-
- readonly property bool hovering: mouseAreaYZ.hovering || mouseAreaXZ.hovering
-
- property var _pointerPosPressed
- property var _targetStartPos
-
signal positionCommit()
signal positionMove()
- materials: DefaultMaterial {
- id: material
- emissiveColor: "white"
- lighting: DefaultMaterial.NoLighting
- }
-
- function handlePressed(mouseArea, pointerPosition)
+ function localPos(sceneRelativeDistance)
{
- if (!targetNode)
- return;
-
- var maskedPosition = Qt.vector3d(pointerPosition.x, 0, 0);
- _pointerPosPressed = mouseArea.mapPositionToScene(maskedPosition);
- var sp = targetNode.scenePosition;
- _targetStartPos = Qt.vector3d(sp.x, sp.y, sp.z);
- dragging = true;
- }
-
- function posInParent(mouseArea, pointerPosition)
- {
- var maskedPosition = Qt.vector3d(pointerPosition.x, 0, 0);
- var scenePointerPos = mouseArea.mapPositionToScene(maskedPosition);
- 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 targetNode.parent.mapPositionFromScene(newScenePos);
}
- function handleDragged(mouseArea, pointerPosition)
- {
- if (!targetNode)
- return;
-
- targetNode.position = posInParent(mouseArea, pointerPosition);
- arrow.positionMove();
- }
-
- function handleReleased(mouseArea, pointerPosition)
- {
- if (!targetNode)
- return;
-
- targetNode.position = posInParent(mouseArea, pointerPosition);
- dragging = false;
- arrow.positionCommit();
+ onDragged: {
+ targetNode.position = localPos(sceneRelativeDistance);
+ positionMove();
}
- MouseArea3D {
- id: mouseAreaYZ
- view3D: arrow.view3D
- x: 0
- y: -1.5
- width: 12
- height: 3
- rotation: Qt.vector3d(0, 0, 90)
- grabsMouse: targetNode
- onPressed: arrow.handlePressed(mouseAreaYZ, pointerPosition)
- onDragged: arrow.handleDragged(mouseAreaYZ, pointerPosition)
- onReleased: arrow.handleReleased(mouseAreaYZ, pointerPosition)
- }
-
- MouseArea3D {
- id: mouseAreaXZ
- view3D: arrow.view3D
- x: 0
- y: -1.5
- width: 12
- height: 3
- rotation: Qt.vector3d(0, 90, 90)
- grabsMouse: targetNode
- onPressed: arrow.handlePressed(mouseAreaXZ, pointerPosition)
- onDragged: arrow.handleDragged(mouseAreaXZ, pointerPosition)
- onReleased: arrow.handleReleased(mouseAreaXZ, pointerPosition)
+ onReleased: {
+ targetNode.position = localPos(sceneRelativeDistance);
+ positionCommit();
}
}
-
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/DirectionalDraggable.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/DirectionalDraggable.qml
new file mode 100644
index 0000000000..243744210e
--- /dev/null
+++ b/share/qtcreator/qml/qmlpuppet/mockfiles/DirectionalDraggable.qml
@@ -0,0 +1,124 @@
+/****************************************************************************
+**
+** 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
+ rotationOrder: Node.XYZr
+
+ property View3D view3D
+ property alias color: material.emissiveColor
+ property Node targetNode: null
+ property bool dragging: false
+ property bool active: false
+
+ readonly property bool hovering: mouseAreaYZ.hovering || mouseAreaXZ.hovering
+
+ property var _pointerPosPressed
+ property var _targetStartPos
+
+ signal pressed(var mouseArea)
+ signal dragged(var mouseArea, vector3d sceneRelativeDistance)
+ signal released(var mouseArea, vector3d sceneRelativeDistance)
+
+ materials: DefaultMaterial {
+ id: material
+ emissiveColor: "white"
+ lighting: DefaultMaterial.NoLighting
+ }
+
+ function handlePressed(mouseArea, scenePos)
+ {
+ if (!targetNode)
+ return;
+
+ var maskedPosition = Qt.vector3d(scenePos.x, 0, 0);
+ _pointerPosPressed = mouseArea.mapPositionToScene(maskedPosition);
+ var sp = targetNode.scenePosition;
+ _targetStartPos = Qt.vector3d(sp.x, sp.y, sp.z);
+ dragging = true;
+ pressed(mouseArea);
+ }
+
+ function calcRelativeDistance(mouseArea, scenePos)
+ {
+ var maskedPosition = Qt.vector3d(scenePos.x, 0, 0);
+ var scenePointerPos = mouseArea.mapPositionToScene(maskedPosition);
+ 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: mouseAreaYZ
+ view3D: rootModel.view3D
+ x: 0
+ y: -1.5
+ width: 12
+ height: 3
+ rotation: Qt.vector3d(0, 0, 90)
+ grabsMouse: targetNode
+ active: rootModel.active
+ onPressed: rootModel.handlePressed(mouseAreaYZ, scenePos)
+ onDragged: rootModel.handleDragged(mouseAreaYZ, scenePos)
+ onReleased: rootModel.handleReleased(mouseAreaYZ, scenePos)
+ }
+
+ MouseArea3D {
+ id: mouseAreaXZ
+ view3D: rootModel.view3D
+ x: 0
+ y: -1.5
+ width: 12
+ height: 3
+ rotation: Qt.vector3d(0, 90, 90)
+ grabsMouse: targetNode
+ active: rootModel.active
+ onPressed: rootModel.handlePressed(mouseAreaXZ, scenePos)
+ onDragged: rootModel.handleDragged(mouseAreaXZ, scenePos)
+ onReleased: rootModel.handleReleased(mouseAreaXZ, scenePos)
+ }
+}
+
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml
index b227cee23e..1dcca048e7 100644
--- a/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml
+++ b/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml
@@ -48,8 +48,8 @@ Window {
property var cameraGizmos: []
signal objectClicked(var object)
- signal commitObjectPosition(var object)
- signal moveObjectPosition(var object)
+ signal commitObjectProperty(var object, var propName)
+ signal changeObjectProperty(var object, var propName)
function selectObject(object) {
selectedNode = object;
@@ -113,11 +113,26 @@ Window {
position: viewWindow.selectedNode ? viewWindow.selectedNode.scenePosition
: Qt.vector3d(0, 0, 0)
globalOrientation: globalControl.checked
- visible: selectedNode
+ visible: selectedNode && moveToolControl.checked
view3D: overlayView
- onPositionCommit: viewWindow.commitObjectPosition(selectedNode)
- onPositionMove: viewWindow.moveObjectPosition(selectedNode)
+ onPositionCommit: viewWindow.commitObjectProperty(selectedNode, "position")
+ onPositionMove: viewWindow.changeObjectProperty(selectedNode, "position")
+ }
+
+ ScaleGizmo {
+ id: scaleGizmo
+ scale: autoScale.getScale(Qt.vector3d(5, 5, 5))
+ highlightOnHover: true
+ targetNode: viewWindow.selectedNode
+ position: viewWindow.selectedNode ? viewWindow.selectedNode.scenePosition
+ : Qt.vector3d(0, 0, 0)
+ globalOrientation: globalControl.checked
+ visible: selectedNode && scaleToolControl.checked
+ view3D: overlayView
+
+ onScaleCommit: viewWindow.commitObjectProperty(selectedNode, "scale")
+ onScaleChange: viewWindow.changeObjectProperty(selectedNode, "scale")
}
AutoScaleHelper {
@@ -186,11 +201,11 @@ Window {
Overlay2D {
id: gizmoLabel
- targetNode: moveGizmo
+ targetNode: moveGizmo.visible ? moveGizmo : scaleGizmo
targetView: overlayView
offsetX: 0
offsetY: 45
- visible: moveGizmo.dragging
+ visible: targetNode.dragging
Rectangle {
color: "white"
@@ -203,11 +218,18 @@ Window {
id: gizmoLabelText
text: {
var l = Qt.locale();
- selectedNode
- ? qsTr("x:") + Number(selectedNode.position.x).toLocaleString(l, 'f', 1)
- + qsTr(" y:") + Number(selectedNode.position.y).toLocaleString(l, 'f', 1)
- + qsTr(" z:") + Number(selectedNode.position.z).toLocaleString(l, 'f', 1)
- : "";
+ var targetProperty;
+ if (viewWindow.selectedNode) {
+ if (gizmoLabel.targetNode === moveGizmo)
+ targetProperty = viewWindow.selectedNode.position;
+ else
+ targetProperty = viewWindow.selectedNode.scale;
+ return qsTr("x:") + Number(targetProperty.x).toLocaleString(l, 'f', 1)
+ + qsTr(" y:") + Number(targetProperty.y).toLocaleString(l, 'f', 1)
+ + qsTr(" z:") + Number(targetProperty.z).toLocaleString(l, 'f', 1);
+ } else {
+ return "";
+ }
}
anchors.centerIn: parent
}
@@ -252,6 +274,19 @@ Window {
text: qsTr("Use Global Orientation")
onCheckedChanged: cameraControl.forceActiveFocus()
}
+ Column {
+ x: 8
+ RadioButton {
+ id: moveToolControl
+ checked: false
+ text: qsTr("Move Tool")
+ }
+ RadioButton {
+ id: scaleToolControl
+ checked: true
+ text: qsTr("Scale Tool")
+ }
+ }
}
Text {
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/MoveGizmo.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/MoveGizmo.qml
index 7ad5a2a011..c035f9c85e 100644
--- a/share/qtcreator/qml/qmlpuppet/mockfiles/MoveGizmo.qml
+++ b/share/qtcreator/qml/qmlpuppet/mockfiles/MoveGizmo.qml
@@ -49,8 +49,9 @@ Node {
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)
+ : Qt.rgba(1, 0, 0, 1)
view3D: moveGizmo.view3D
+ active: moveGizmo.visible
onPositionCommit: moveGizmo.positionCommit()
onPositionMove: moveGizmo.positionMove()
@@ -61,9 +62,10 @@ Node {
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)
+ 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()
@@ -74,9 +76,10 @@ Node {
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)
+ 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()
@@ -108,13 +111,14 @@ Node {
rotation: view3D.camera.rotation
grabsMouse: moveGizmo.targetNode
priority: 1
+ active: moveGizmo.visible
property var _pointerPosPressed
property var _targetStartPos
- function posInParent(pointerPosition)
+ function localPos(scenePos)
{
- var scenePointerPos = mapPositionToScene(pointerPosition);
+ var scenePointerPos = mapPositionToScene(scenePos);
var sceneRelativeDistance = Qt.vector3d(
scenePointerPos.x - _pointerPosPressed.x,
scenePointerPos.y - _pointerPosPressed.y,
@@ -132,7 +136,7 @@ Node {
if (!moveGizmo.targetNode)
return;
- _pointerPosPressed = mapPositionToScene(pointerPosition);
+ _pointerPosPressed = mapPositionToScene(scenePos);
var sp = moveGizmo.targetNode.scenePosition;
_targetStartPos = Qt.vector3d(sp.x, sp.y, sp.z);
}
@@ -140,14 +144,14 @@ Node {
if (!moveGizmo.targetNode)
return;
- moveGizmo.targetNode.position = posInParent(pointerPosition);
+ moveGizmo.targetNode.position = localPos(scenePos);
moveGizmo.positionMove();
}
onReleased: {
if (!moveGizmo.targetNode)
return;
- moveGizmo.targetNode.position = posInParent(pointerPosition);
+ moveGizmo.targetNode.position = localPos(scenePos);
moveGizmo.positionCommit();
}
}
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/ScaleGizmo.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/ScaleGizmo.qml
new file mode 100644
index 0000000000..7f4a4f69b8
--- /dev/null
+++ b/share/qtcreator/qml/qmlpuppet/mockfiles/ScaleGizmo.qml
@@ -0,0 +1,159 @@
+/****************************************************************************
+**
+** 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
+
+Node {
+ id: scaleGizmo
+
+ property View3D view3D
+ property bool highlightOnHover: false
+ property Node targetNode: null
+ property bool globalOrientation: true
+ readonly property bool dragging: scaleRodX.dragging || scaleRodY.dragging || scaleRodZ.dragging
+ || centerMouseArea.dragging
+
+ signal scaleCommit()
+ signal scaleChange()
+
+ Node {
+ rotation: globalOrientation || !targetNode ? Qt.vector3d(0, 0, 0) : targetNode.sceneRotation
+
+ 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
+
+ onScaleCommit: scaleGizmo.scaleCommit()
+ onScaleChange: scaleGizmo.scaleChange()
+ }
+
+ 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
+
+ onScaleCommit: scaleGizmo.scaleCommit()
+ onScaleChange: scaleGizmo.scaleChange()
+ }
+
+ 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
+
+ onScaleCommit: scaleGizmo.scaleCommit()
+ onScaleChange: scaleGizmo.scaleChange()
+ }
+ }
+
+ Model {
+ id: centerCube
+
+ source: "#Cube"
+ 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: scaleGizmo.view3D
+ x: -60
+ y: -60
+ width: 120
+ height: 120
+ rotation: view3D.camera.rotation
+ grabsMouse: scaleGizmo.targetNode
+ priority: 1
+ active: scaleGizmo.visible
+
+ property var _startScale
+ property var _startScreenPos
+
+ function localScale(screenPos)
+ {
+ var yDelta = screenPos.y - _startScreenPos.y;
+ if (yDelta === 0)
+ return;
+ var scaler = 1.0 + (yDelta * 0.025);
+ if (scaler === 0 )
+ scaler = 0.0001;
+ if (scaler < 0)
+ scaler = -scaler;
+ return Qt.vector3d(scaler * _startScale.x,
+ scaler * _startScale.y,
+ scaler * _startScale.z);
+ }
+
+ onPressed: {
+ if (!scaleGizmo.targetNode)
+ return;
+
+ // Recreate vector so we don't follow the changes in targetNode.scale
+ _startScale = Qt.vector3d(scaleGizmo.targetNode.scale.x,
+ scaleGizmo.targetNode.scale.y,
+ scaleGizmo.targetNode.scale.z);
+ _startScreenPos = screenPos;
+ }
+ onDragged: {
+ if (!scaleGizmo.targetNode)
+ return;
+
+ scaleGizmo.targetNode.scale = localScale(screenPos);
+ scaleGizmo.scaleChange();
+ }
+ onReleased: {
+ if (!scaleGizmo.targetNode)
+ return;
+
+ scaleGizmo.targetNode.scale = localScale(screenPos);
+ scaleGizmo.scaleCommit();
+ }
+ }
+ }
+}
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/ScaleRod.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/ScaleRod.qml
new file mode 100644
index 0000000000..4ef6d8a0a7
--- /dev/null
+++ b/share/qtcreator/qml/qmlpuppet/mockfiles/ScaleRod.qml
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** 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
+
+DirectionalDraggable {
+ id: scaleRod
+ source: "meshes/scalerod.mesh"
+
+ signal scaleCommit()
+ signal scaleChange()
+
+ property var _startScale
+
+ Model {
+ source: "#Cube"
+ y: 10
+ scale: Qt.vector3d(0.025, 0.025, 0.025)
+ materials: DefaultMaterial {
+ id: material
+ emissiveColor: scaleRod.color
+ lighting: DefaultMaterial.NoLighting
+ }
+ }
+
+ 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,
+ targetNode.sceneScale.y,
+ targetNode.sceneScale.z);
+ }
+
+ onDragged: {
+ targetNode.scale = localScale(mouseArea, sceneRelativeDistance);
+ scaleChange();
+ }
+
+ onReleased: {
+ targetNode.scale = localScale(mouseArea, sceneRelativeDistance);
+ scaleCommit();
+ }
+}
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/meshes/scalerod.mesh b/share/qtcreator/qml/qmlpuppet/mockfiles/meshes/scalerod.mesh
new file mode 100644
index 0000000000..b3c1bd883f
--- /dev/null
+++ b/share/qtcreator/qml/qmlpuppet/mockfiles/meshes/scalerod.mesh
Binary files differ
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/mousearea3d.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/mousearea3d.cpp
index 4c1fdcc78e..fe84ed13a6 100644
--- a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/mousearea3d.cpp
+++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/mousearea3d.cpp
@@ -60,6 +60,11 @@ bool MouseArea3D::grabsMouse() const
return m_grabsMouse;
}
+bool MouseArea3D::active() const
+{
+ return m_active;
+}
+
qreal MouseArea3D::x() const
{
return m_x;
@@ -103,6 +108,15 @@ void MouseArea3D::setGrabsMouse(bool grabsMouse)
emit grabsMouseChanged(grabsMouse);
}
+void MouseArea3D::setActive(bool active)
+{
+ if (m_active == active)
+ return;
+
+ m_active = active;
+ emit activeChanged(active);
+}
+
void MouseArea3D::setX(qreal x)
{
if (qFuzzyCompare(m_x, x))
@@ -190,6 +204,73 @@ 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
+QVector3D MouseArea3D::getNewScale(QQuick3DNode *node, const QVector3D &startScale,
+ const QVector3D &pressPos,
+ const QVector3D &sceneRelativeDistance, float scaler)
+{
+ 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;
+
+ // 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;
+ QVector3D curScale = getScale(newTransform);
+ if (qFuzzyIsNull(curScale.x()))
+ curScale.setX(nonZeroValue);
+ if (qFuzzyIsNull(curScale.y()))
+ curScale.setY(nonZeroValue);
+ if (qFuzzyIsNull(curScale.z()))
+ 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();
+
+ // 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;
+ 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());
+ }
+ scaleVec *= startScale;
+
+ newTransform = parentTransform;
+ newTransform.scale(scaleVec);
+
+ const QMatrix4x4 localTransform = parentTransform.inverted() * newTransform;
+ return getScale(localTransform);
+ }
+
+ return startScale;
+}
+
QVector3D MouseArea3D::getMousePosInPlane(const QPointF &mousePosInView) const
{
const QVector3D mousePos1(float(mousePosInView.x()), float(mousePosInView.y()), 0);
@@ -207,8 +288,8 @@ 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)) {
+ if (!m_active || (m_grabsMouse && s_mouseGrab && s_mouseGrab != this
+ && (m_priority <= s_mouseGrab->m_priority || s_mouseGrab->m_dragging))) {
return false;
}
@@ -227,7 +308,7 @@ bool MouseArea3D::eventFilter(QObject *, QEvent *event)
m_mousePosInPlane = getMousePosInPlane(mouseEvent->pos());
if (mouseOnTopOfMouseArea(m_mousePosInPlane)) {
setDragging(true);
- emit pressed(m_mousePosInPlane);
+ emit pressed(m_mousePosInPlane, mouseEvent->globalPos());
if (m_grabsMouse) {
if (s_mouseGrab && s_mouseGrab != this) {
s_mouseGrab->setDragging(false);
@@ -250,7 +331,7 @@ bool MouseArea3D::eventFilter(QObject *, QEvent *event)
if (qFuzzyCompare(mousePosInPlane.z(), -1))
mousePosInPlane = m_mousePosInPlane;
setDragging(false);
- emit released(mousePosInPlane);
+ emit released(mousePosInPlane, mouseEvent->globalPos());
if (m_grabsMouse) {
if (s_mouseGrab && s_mouseGrab != this) {
s_mouseGrab->setDragging(false);
@@ -290,7 +371,7 @@ bool MouseArea3D::eventFilter(QObject *, QEvent *event)
if (m_dragging && !qFuzzyCompare(mousePosInPlane.z(), -1)) {
m_mousePosInPlane = mousePosInPlane;
- emit dragged(mousePosInPlane);
+ emit dragged(mousePosInPlane, mouseEvent->globalPos());
}
break;
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/mousearea3d.h b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/mousearea3d.h
index 99a34be353..a7e1fa261e 100644
--- a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/mousearea3d.h
+++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/mousearea3d.h
@@ -49,6 +49,7 @@ class MouseArea3D : public QQuick3DNode
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_PROPERTY(int active READ active WRITE setActive NOTIFY activeChanged)
Q_INTERFACES(QQmlParserStatus)
@@ -66,10 +67,12 @@ public:
bool hovering() const;
bool dragging() const;
bool grabsMouse() const;
+ bool active() const;
public slots:
void setView3D(QQuick3DViewport *view3D);
void setGrabsMouse(bool grabsMouse);
+ void setActive(bool active);
void setX(qreal x);
void setY(qreal y);
@@ -82,6 +85,10 @@ public slots:
const QVector3D &planePos,
const QVector3D &planeNormal) const;
+ Q_INVOKABLE QVector3D getNewScale(QQuick3DNode *node, const QVector3D &startScale,
+ const QVector3D &pressPos,
+ const QVector3D &sceneRelativeDistance, float scaler);
+
signals:
void view3DChanged();
@@ -93,9 +100,10 @@ signals:
void hoveringChanged();
void draggingChanged();
- void pressed(const QVector3D &pointerPosition);
- void released(const QVector3D &pointerPosition);
- void dragged(const QVector3D &pointerPosition);
+ void activeChanged(bool active);
+ void pressed(const QVector3D &scenePos, const QPoint &screenPos);
+ void released(const QVector3D &scenePos, const QPoint &screenPos);
+ void dragged(const QVector3D &scenePos, const QPoint &screenPos);
void grabsMouseChanged(bool grabsMouse);
protected:
@@ -118,6 +126,7 @@ private:
bool m_hovering = false;
bool m_dragging = false;
+ bool m_active = false;
QVector3D getMousePosInPlane(const QPointF &mousePosInView) const;
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp
index d97cc2d503..dbbd8f050e 100644
--- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp
+++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp
@@ -97,12 +97,12 @@ QObject *Qt5InformationNodeInstanceServer::createEditView3D(QQmlEngine *engine)
}
QObject::connect(window, SIGNAL(objectClicked(QVariant)), this, SLOT(objectClicked(QVariant)));
- QObject::connect(window, SIGNAL(commitObjectPosition(QVariant)),
- this, SLOT(handleObjectPositionCommit(QVariant)));
- QObject::connect(window, SIGNAL(moveObjectPosition(QVariant)),
- this, SLOT(handleObjectPositionMove(QVariant)));
- QObject::connect(&m_moveTimer, &QTimer::timeout,
- this, &Qt5InformationNodeInstanceServer::handleObjectPositionMoveTimeout);
+ QObject::connect(window, SIGNAL(commitObjectProperty(QVariant, QVariant)),
+ this, SLOT(handleObjectPropertyCommit(QVariant, QVariant)));
+ QObject::connect(window, SIGNAL(changeObjectProperty(QVariant, QVariant)),
+ this, SLOT(handleObjectPropertyChange(QVariant, QVariant)));
+ QObject::connect(&m_propertyChangeTimer, &QTimer::timeout,
+ this, &Qt5InformationNodeInstanceServer::handleObjectPropertyChangeTimeout);
//For macOS we have to use the 4.1 core profile
QSurfaceFormat surfaceFormat = window->requestedFormat();
@@ -188,28 +188,36 @@ void Qt5InformationNodeInstanceServer::modifyVariantValue(
}
}
-void Qt5InformationNodeInstanceServer::handleObjectPositionCommit(const QVariant &object)
+void Qt5InformationNodeInstanceServer::handleObjectPropertyCommit(const QVariant &object,
+ const QVariant &propName)
{
- modifyVariantValue(object, "position", ValuesModifiedCommand::TransactionOption::End);
- m_movedNode = {};
- m_moveTimer.stop();
+ modifyVariantValue(object, propName.toByteArray(),
+ ValuesModifiedCommand::TransactionOption::End);
+ m_changedNode = {};
+ m_changedProperty = {};
+ m_propertyChangeTimer.stop();
}
-void Qt5InformationNodeInstanceServer::handleObjectPositionMove(const QVariant &object)
+void Qt5InformationNodeInstanceServer::handleObjectPropertyChange(const QVariant &object,
+ const QVariant &propName)
{
- if (m_movedNode.isNull()) {
- modifyVariantValue(object, "position", ValuesModifiedCommand::TransactionOption::Start);
- } else {
- if (!m_moveTimer.isActive())
- m_moveTimer.start();
+ PropertyName propertyName(propName.toByteArray());
+ if (m_changedProperty != propertyName || m_changedNode != object) {
+ if (!m_changedNode.isNull())
+ handleObjectPropertyCommit(m_changedNode, m_changedProperty);
+ modifyVariantValue(object, propertyName,
+ ValuesModifiedCommand::TransactionOption::Start);
+ } else if (!m_propertyChangeTimer.isActive()) {
+ m_propertyChangeTimer.start();
}
- m_movedNode = object;
+ m_changedNode = object;
+ m_changedProperty = propertyName;
}
Qt5InformationNodeInstanceServer::Qt5InformationNodeInstanceServer(NodeInstanceClientInterface *nodeInstanceClient) :
Qt5NodeInstanceServer(nodeInstanceClient)
{
- m_moveTimer.setInterval(100);
+ m_propertyChangeTimer.setInterval(100);
}
void Qt5InformationNodeInstanceServer::sendTokenBack()
@@ -282,9 +290,10 @@ void Qt5InformationNodeInstanceServer::modifyProperties(
nodeInstanceClient()->valuesModified(createValuesModifiedCommand(properties));
}
-void Qt5InformationNodeInstanceServer::handleObjectPositionMoveTimeout()
+void Qt5InformationNodeInstanceServer::handleObjectPropertyChangeTimeout()
{
- modifyVariantValue(m_movedNode, "position", ValuesModifiedCommand::TransactionOption::None);
+ modifyVariantValue(m_changedNode, m_changedProperty,
+ ValuesModifiedCommand::TransactionOption::None);
}
QObject *Qt5InformationNodeInstanceServer::findRootNodeOf3DViewport(
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.h b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.h
index e8a0291a9f..918d18db67 100644
--- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.h
+++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.h
@@ -51,8 +51,8 @@ public:
private slots:
void objectClicked(const QVariant &object);
- void handleObjectPositionCommit(const QVariant &object);
- void handleObjectPositionMove(const QVariant &object);
+ void handleObjectPropertyCommit(const QVariant &object, const QVariant &propName);
+ void handleObjectPropertyChange(const QVariant &object, const QVariant &propName);
protected:
void collectItemChangesAndSendChangeCommands() override;
@@ -64,7 +64,7 @@ protected:
void modifyProperties(const QVector<InstancePropertyValueTriple> &properties);
private:
- void handleObjectPositionMoveTimeout();
+ void handleObjectPropertyChangeTimeout();
QObject *createEditView3D(QQmlEngine *engine);
void setup3DEditView(const QList<ServerNodeInstance> &instanceList);
QObject *findRootNodeOf3DViewport(const QList<ServerNodeInstance> &instanceList) const;
@@ -81,8 +81,9 @@ private:
QSet<ServerNodeInstance> m_parentChangedSet;
QList<ServerNodeInstance> m_completedComponentList;
QList<TokenCommand> m_tokenList;
- QTimer m_moveTimer;
- QVariant m_movedNode;
+ QTimer m_propertyChangeTimer;
+ QVariant m_changedNode;
+ PropertyName m_changedProperty;
};
} // namespace QmlDesigner
diff --git a/share/qtcreator/qml/qmlpuppet/qmlpuppet.qrc b/share/qtcreator/qml/qmlpuppet/qmlpuppet.qrc
index 4bbd30e8fc..ec02e9d256 100644
--- a/share/qtcreator/qml/qmlpuppet/qmlpuppet.qrc
+++ b/share/qtcreator/qml/qmlpuppet/qmlpuppet.qrc
@@ -15,7 +15,11 @@
<file>mockfiles/LightGizmo.qml</file>
<file>mockfiles/IconGizmo.qml</file>
<file>mockfiles/Overlay2D.qml</file>
+ <file>mockfiles/DirectionalDraggable.qml</file>
+ <file>mockfiles/ScaleRod.qml</file>
+ <file>mockfiles/ScaleGizmo.qml</file>
<file>mockfiles/meshes/arrow.mesh</file>
+ <file>mockfiles/meshes/scalerod.mesh</file>
<file>mockfiles/images/camera-pick-icon.png</file>
<file>mockfiles/images/camera-pick-icon@2x.png</file>
<file>mockfiles/images/light-pick-icon.png</file>