forked from qt-creator/qt-creator
QmlDesigner: Add planar move and scale handles to gizmos
Change-Id: Icae60ec35fc84d731243a005e97b174fa9a94815 Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io> Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io>
This commit is contained in:
@@ -278,12 +278,12 @@ Window {
|
|||||||
x: 8
|
x: 8
|
||||||
RadioButton {
|
RadioButton {
|
||||||
id: moveToolControl
|
id: moveToolControl
|
||||||
checked: false
|
checked: true
|
||||||
text: qsTr("Move Tool")
|
text: qsTr("Move Tool")
|
||||||
}
|
}
|
||||||
RadioButton {
|
RadioButton {
|
||||||
id: scaleToolControl
|
id: scaleToolControl
|
||||||
checked: true
|
checked: false
|
||||||
text: qsTr("Scale Tool")
|
text: qsTr("Scale Tool")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -35,7 +35,8 @@ Node {
|
|||||||
property Node targetNode: null
|
property Node targetNode: null
|
||||||
property bool globalOrientation: true
|
property bool globalOrientation: true
|
||||||
readonly property bool dragging: arrowX.dragging || arrowY.dragging || arrowZ.dragging
|
readonly property bool dragging: arrowX.dragging || arrowY.dragging || arrowZ.dragging
|
||||||
|| centerMouseArea.dragging
|
|| planeX.dragging || planeY.dragging || planeZ.dragging
|
||||||
|
|| centerBall.dragging
|
||||||
|
|
||||||
signal positionCommit()
|
signal positionCommit()
|
||||||
signal positionMove()
|
signal positionMove()
|
||||||
@@ -45,7 +46,6 @@ Node {
|
|||||||
|
|
||||||
Arrow {
|
Arrow {
|
||||||
id: arrowX
|
id: arrowX
|
||||||
objectName: "Arrow X"
|
|
||||||
rotation: Qt.vector3d(0, 0, -90)
|
rotation: Qt.vector3d(0, 0, -90)
|
||||||
targetNode: moveGizmo.targetNode
|
targetNode: moveGizmo.targetNode
|
||||||
color: highlightOnHover && (hovering || dragging) ? Qt.lighter(Qt.rgba(1, 0, 0, 1))
|
color: highlightOnHover && (hovering || dragging) ? Qt.lighter(Qt.rgba(1, 0, 0, 1))
|
||||||
@@ -59,7 +59,6 @@ Node {
|
|||||||
|
|
||||||
Arrow {
|
Arrow {
|
||||||
id: arrowY
|
id: arrowY
|
||||||
objectName: "Arrow Y"
|
|
||||||
rotation: Qt.vector3d(0, 0, 0)
|
rotation: Qt.vector3d(0, 0, 0)
|
||||||
targetNode: moveGizmo.targetNode
|
targetNode: moveGizmo.targetNode
|
||||||
color: highlightOnHover && (hovering || dragging) ? Qt.lighter(Qt.rgba(0, 0.6, 0, 1))
|
color: highlightOnHover && (hovering || dragging) ? Qt.lighter(Qt.rgba(0, 0.6, 0, 1))
|
||||||
@@ -73,7 +72,6 @@ Node {
|
|||||||
|
|
||||||
Arrow {
|
Arrow {
|
||||||
id: arrowZ
|
id: arrowZ
|
||||||
objectName: "Arrow Z"
|
|
||||||
rotation: Qt.vector3d(90, 0, 0)
|
rotation: Qt.vector3d(90, 0, 0)
|
||||||
targetNode: moveGizmo.targetNode
|
targetNode: moveGizmo.targetNode
|
||||||
color: highlightOnHover && (hovering || dragging) ? Qt.lighter(Qt.rgba(0, 0, 1, 1))
|
color: highlightOnHover && (hovering || dragging) ? Qt.lighter(Qt.rgba(0, 0, 1, 1))
|
||||||
@@ -85,75 +83,72 @@ Node {
|
|||||||
onPositionMove: moveGizmo.positionMove()
|
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()
|
||||||
}
|
}
|
||||||
|
|
||||||
Model {
|
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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PlanarMoveHandle {
|
||||||
id: centerBall
|
id: centerBall
|
||||||
|
|
||||||
source: "#Sphere"
|
source: "#Sphere"
|
||||||
scale: Qt.vector3d(0.024, 0.024, 0.024)
|
color: highlightOnHover && (hovering || dragging) ? Qt.lighter(Qt.rgba(0.5, 0.5, 0.5, 1))
|
||||||
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)
|
: Qt.rgba(0.5, 0.5, 0.5, 1)
|
||||||
lighting: DefaultMaterial.NoLighting
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea3D {
|
|
||||||
id: centerMouseArea
|
|
||||||
view3D: moveGizmo.view3D
|
|
||||||
x: -60
|
|
||||||
y: -60
|
|
||||||
width: 120
|
|
||||||
height: 120
|
|
||||||
rotation: view3D.camera.rotation
|
rotation: view3D.camera.rotation
|
||||||
grabsMouse: moveGizmo.targetNode
|
|
||||||
priority: 1
|
priority: 1
|
||||||
|
targetNode: moveGizmo.targetNode
|
||||||
|
|
||||||
|
view3D: moveGizmo.view3D
|
||||||
active: moveGizmo.visible
|
active: moveGizmo.visible
|
||||||
|
|
||||||
property var _pointerPosPressed
|
onPositionCommit: moveGizmo.positionCommit()
|
||||||
property var _targetStartPos
|
onPositionMove: moveGizmo.positionMove()
|
||||||
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
118
share/qtcreator/qml/qmlpuppet/mockfiles/PlanarDraggable.qml
Normal file
118
share/qtcreator/qml/qmlpuppet/mockfiles/PlanarDraggable.qml
Normal file
@@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
55
share/qtcreator/qml/qmlpuppet/mockfiles/PlanarMoveHandle.qml
Normal file
55
share/qtcreator/qml/qmlpuppet/mockfiles/PlanarMoveHandle.qml
Normal file
@@ -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();
|
||||||
|
}
|
||||||
|
}
|
@@ -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();
|
||||||
|
}
|
||||||
|
}
|
@@ -35,6 +35,7 @@ Node {
|
|||||||
property Node targetNode: null
|
property Node targetNode: null
|
||||||
property bool globalOrientation: true
|
property bool globalOrientation: true
|
||||||
readonly property bool dragging: scaleRodX.dragging || scaleRodY.dragging || scaleRodZ.dragging
|
readonly property bool dragging: scaleRodX.dragging || scaleRodY.dragging || scaleRodZ.dragging
|
||||||
|
|| planeX.dragging || planeY.dragging || planeZ.dragging
|
||||||
|| centerMouseArea.dragging
|
|| centerMouseArea.dragging
|
||||||
|
|
||||||
signal scaleCommit()
|
signal scaleCommit()
|
||||||
@@ -45,13 +46,13 @@ Node {
|
|||||||
|
|
||||||
ScaleRod {
|
ScaleRod {
|
||||||
id: scaleRodX
|
id: scaleRodX
|
||||||
objectName: "scaleRod X"
|
|
||||||
rotation: Qt.vector3d(0, 0, -90)
|
rotation: Qt.vector3d(0, 0, -90)
|
||||||
targetNode: scaleGizmo.targetNode
|
targetNode: scaleGizmo.targetNode
|
||||||
color: highlightOnHover && (hovering || dragging) ? Qt.lighter(Qt.rgba(1, 0, 0, 1))
|
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: scaleGizmo.view3D
|
view3D: scaleGizmo.view3D
|
||||||
active: scaleGizmo.visible
|
active: scaleGizmo.visible
|
||||||
|
globalOrientation: scaleGizmo.globalOrientation
|
||||||
|
|
||||||
onScaleCommit: scaleGizmo.scaleCommit()
|
onScaleCommit: scaleGizmo.scaleCommit()
|
||||||
onScaleChange: scaleGizmo.scaleChange()
|
onScaleChange: scaleGizmo.scaleChange()
|
||||||
@@ -59,13 +60,13 @@ Node {
|
|||||||
|
|
||||||
ScaleRod {
|
ScaleRod {
|
||||||
id: scaleRodY
|
id: scaleRodY
|
||||||
objectName: "scaleRod Y"
|
|
||||||
rotation: Qt.vector3d(0, 0, 0)
|
rotation: Qt.vector3d(0, 0, 0)
|
||||||
targetNode: scaleGizmo.targetNode
|
targetNode: scaleGizmo.targetNode
|
||||||
color: highlightOnHover && (hovering || dragging) ? Qt.lighter(Qt.rgba(0, 0.6, 0, 1))
|
color: highlightOnHover && (hovering || dragging) ? Qt.lighter(Qt.rgba(0, 0.6, 0, 1))
|
||||||
: Qt.rgba(0, 0.6, 0, 1)
|
: Qt.rgba(0, 0.6, 0, 1)
|
||||||
view3D: scaleGizmo.view3D
|
view3D: scaleGizmo.view3D
|
||||||
active: scaleGizmo.visible
|
active: scaleGizmo.visible
|
||||||
|
globalOrientation: scaleGizmo.globalOrientation
|
||||||
|
|
||||||
onScaleCommit: scaleGizmo.scaleCommit()
|
onScaleCommit: scaleGizmo.scaleCommit()
|
||||||
onScaleChange: scaleGizmo.scaleChange()
|
onScaleChange: scaleGizmo.scaleChange()
|
||||||
@@ -73,13 +74,67 @@ Node {
|
|||||||
|
|
||||||
ScaleRod {
|
ScaleRod {
|
||||||
id: scaleRodZ
|
id: scaleRodZ
|
||||||
objectName: "scaleRod Z"
|
|
||||||
rotation: Qt.vector3d(90, 0, 0)
|
rotation: Qt.vector3d(90, 0, 0)
|
||||||
targetNode: scaleGizmo.targetNode
|
targetNode: scaleGizmo.targetNode
|
||||||
color: highlightOnHover && (hovering || dragging) ? Qt.lighter(Qt.rgba(0, 0, 1, 1))
|
color: highlightOnHover && (hovering || dragging) ? Qt.lighter(Qt.rgba(0, 0, 1, 1))
|
||||||
: Qt.rgba(0, 0, 1, 1)
|
: Qt.rgba(0, 0, 1, 1)
|
||||||
view3D: scaleGizmo.view3D
|
view3D: scaleGizmo.view3D
|
||||||
active: scaleGizmo.visible
|
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()
|
onScaleCommit: scaleGizmo.scaleCommit()
|
||||||
onScaleChange: scaleGizmo.scaleChange()
|
onScaleChange: scaleGizmo.scaleChange()
|
||||||
|
@@ -31,6 +31,8 @@ DirectionalDraggable {
|
|||||||
id: scaleRod
|
id: scaleRod
|
||||||
source: "meshes/scalerod.mesh"
|
source: "meshes/scalerod.mesh"
|
||||||
|
|
||||||
|
property bool globalOrientation: false
|
||||||
|
|
||||||
signal scaleCommit()
|
signal scaleCommit()
|
||||||
signal scaleChange()
|
signal scaleChange()
|
||||||
|
|
||||||
@@ -39,7 +41,7 @@ DirectionalDraggable {
|
|||||||
Model {
|
Model {
|
||||||
source: "#Cube"
|
source: "#Cube"
|
||||||
y: 10
|
y: 10
|
||||||
scale: Qt.vector3d(0.025, 0.025, 0.025)
|
scale: Qt.vector3d(0.020, 0.020, 0.020)
|
||||||
materials: DefaultMaterial {
|
materials: DefaultMaterial {
|
||||||
id: material
|
id: material
|
||||||
emissiveColor: scaleRod.color
|
emissiveColor: scaleRod.color
|
||||||
@@ -47,12 +49,6 @@ DirectionalDraggable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function localScale(mouseArea, sceneRelativeDistance)
|
|
||||||
{
|
|
||||||
return mouseArea.getNewScale(targetNode, _startScale, _pointerPosPressed,
|
|
||||||
sceneRelativeDistance, sceneScale.x);
|
|
||||||
}
|
|
||||||
|
|
||||||
onPressed: {
|
onPressed: {
|
||||||
// Recreate vector so we don't follow the changes in targetNode.sceneScale
|
// Recreate vector so we don't follow the changes in targetNode.sceneScale
|
||||||
_startScale = Qt.vector3d(targetNode.sceneScale.x,
|
_startScale = Qt.vector3d(targetNode.sceneScale.x,
|
||||||
@@ -61,12 +57,16 @@ DirectionalDraggable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onDragged: {
|
onDragged: {
|
||||||
targetNode.scale = localScale(mouseArea, sceneRelativeDistance);
|
targetNode.scale = mouseArea.getNewScale(targetNode, _startScale,
|
||||||
|
_pointerPosPressed, sceneRelativeDistance,
|
||||||
|
globalOrientation);
|
||||||
scaleChange();
|
scaleChange();
|
||||||
}
|
}
|
||||||
|
|
||||||
onReleased: {
|
onReleased: {
|
||||||
targetNode.scale = localScale(mouseArea, sceneRelativeDistance);
|
targetNode.scale = mouseArea.getNewScale(targetNode, _startScale,
|
||||||
|
_pointerPosPressed, sceneRelativeDistance,
|
||||||
|
globalOrientation);
|
||||||
scaleCommit();
|
scaleCommit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -204,31 +204,33 @@ QVector3D MouseArea3D::rayIntersectsPlane(const QVector3D &rayPos0,
|
|||||||
return rayPos0 + distanceFromRayPos0ToPlane * rayDirection;
|
return rayPos0 + distanceFromRayPos0ToPlane * rayDirection;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get a new scale based on a relative scene distance along an axis (used to adjust scale via drag)
|
// Get a new scale based on a relative scene distance along a drag axis.
|
||||||
// This function never returns a negative scaling
|
// 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,
|
QVector3D MouseArea3D::getNewScale(QQuick3DNode *node, const QVector3D &startScale,
|
||||||
const QVector3D &pressPos,
|
const QVector3D &pressPos,
|
||||||
const QVector3D &sceneRelativeDistance, float scaler)
|
const QVector3D &sceneRelativeDistance, bool global)
|
||||||
{
|
{
|
||||||
if (node) {
|
if (node) {
|
||||||
// Note: This only returns correct scale when scale is positive
|
// Note: This only returns correct scale when scale is positive
|
||||||
auto getScale = [&](const QMatrix4x4 &m) -> QVector3D {
|
auto getScale = [&](const QMatrix4x4 &m) -> QVector3D {
|
||||||
return QVector3D(m.column(0).length(), m.column(1).length(), m.column(2).length());
|
return QVector3D(m.column(0).length(), m.column(1).length(), m.column(2).length());
|
||||||
};
|
};
|
||||||
const float constantDragScaler = 0.1f;
|
|
||||||
const float nonZeroValue = 0.0001f;
|
const float nonZeroValue = 0.0001f;
|
||||||
|
|
||||||
if (qFuzzyIsNull(scaler))
|
|
||||||
scaler = nonZeroValue;
|
|
||||||
|
|
||||||
const QVector3D scenePos = node->scenePosition();
|
const QVector3D scenePos = node->scenePosition();
|
||||||
const QMatrix4x4 parentTransform = node->parentNode()->sceneTransform();
|
const QMatrix4x4 parentTransform = node->parentNode()->sceneTransform();
|
||||||
QMatrix4x4 newTransform = node->sceneTransform();
|
QMatrix4x4 newTransform = node->sceneTransform();
|
||||||
QVector3D normalRelDist = sceneRelativeDistance.normalized();
|
const QVector3D nodeToPressPos = pressPos - scenePos;
|
||||||
float direction = QVector3D::dotProduct((pressPos - scenePos).normalized(), normalRelDist);
|
const QVector3D nodeToRelPos = nodeToPressPos + sceneRelativeDistance;
|
||||||
float magnitude = constantDragScaler * sceneRelativeDistance.length() / scaler;
|
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
|
// Reset everything but rotation to ensure translation and scale don't affect rotation below
|
||||||
newTransform(0, 3) = 0;
|
newTransform(0, 3) = 0;
|
||||||
newTransform(1, 3) = 0;
|
newTransform(1, 3) = 0;
|
||||||
newTransform(2, 3) = 0;
|
newTransform(2, 3) = 0;
|
||||||
@@ -241,24 +243,29 @@ QVector3D MouseArea3D::getNewScale(QQuick3DNode *node, const QVector3D &startSca
|
|||||||
curScale.setZ(nonZeroValue);
|
curScale.setZ(nonZeroValue);
|
||||||
newTransform.scale({1.f / curScale.x(), 1.f / curScale.y(), 1.f / curScale.z()});
|
newTransform.scale({1.f / curScale.x(), 1.f / curScale.y(), 1.f / curScale.z()});
|
||||||
|
|
||||||
// Rotate relative distance according to object rotation
|
// Rotate the local scale vector so that scale axes are parallel to global axes for easier
|
||||||
normalRelDist = newTransform.inverted().map(normalRelDist).normalized();
|
// scale vector manipulation
|
||||||
|
if (!global)
|
||||||
|
scaleDirVector = newTransform.inverted().map(scaleDirVector).normalized();
|
||||||
|
|
||||||
// Ensure scaling is always positive/negative according to direction
|
// Ensure scaling is always positive/negative according to direction
|
||||||
normalRelDist.setX(qAbs(normalRelDist.x()));
|
scaleDirVector.setX(qAbs(scaleDirVector.x()));
|
||||||
normalRelDist.setY(qAbs(normalRelDist.y()));
|
scaleDirVector.setY(qAbs(scaleDirVector.y()));
|
||||||
normalRelDist.setZ(qAbs(normalRelDist.z()));
|
scaleDirVector.setZ(qAbs(scaleDirVector.z()));
|
||||||
QVector3D scaleVec = normalRelDist;
|
|
||||||
|
// 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;
|
scaleVec *= magnitude;
|
||||||
if (direction > 0) {
|
|
||||||
scaleVec.setX(scaleVec.x() + 1.f);
|
// Zero axes on scale vector indicate directions we don't want scaling to affect
|
||||||
scaleVec.setY(scaleVec.y() + 1.f);
|
if (qFuzzyIsNull(scaleVec.x()))
|
||||||
scaleVec.setZ(scaleVec.z() + 1.f);
|
scaleVec.setX(1.f);
|
||||||
} else {
|
if (qFuzzyIsNull(scaleVec.y()))
|
||||||
scaleVec.setX(1.f - scaleVec.x());
|
scaleVec.setY(1.f);
|
||||||
scaleVec.setY(1.f - scaleVec.y());
|
if (qFuzzyIsNull(scaleVec.z()))
|
||||||
scaleVec.setZ(1.f - scaleVec.z());
|
scaleVec.setZ(1.f);
|
||||||
}
|
|
||||||
scaleVec *= startScale;
|
scaleVec *= startScale;
|
||||||
|
|
||||||
newTransform = parentTransform;
|
newTransform = parentTransform;
|
||||||
|
@@ -87,7 +87,7 @@ public slots:
|
|||||||
|
|
||||||
Q_INVOKABLE QVector3D getNewScale(QQuick3DNode *node, const QVector3D &startScale,
|
Q_INVOKABLE QVector3D getNewScale(QQuick3DNode *node, const QVector3D &startScale,
|
||||||
const QVector3D &pressPos,
|
const QVector3D &pressPos,
|
||||||
const QVector3D &sceneRelativeDistance, float scaler);
|
const QVector3D &sceneRelativeDistance, bool global);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void view3DChanged();
|
void view3DChanged();
|
||||||
|
@@ -16,6 +16,9 @@
|
|||||||
<file>mockfiles/IconGizmo.qml</file>
|
<file>mockfiles/IconGizmo.qml</file>
|
||||||
<file>mockfiles/Overlay2D.qml</file>
|
<file>mockfiles/Overlay2D.qml</file>
|
||||||
<file>mockfiles/DirectionalDraggable.qml</file>
|
<file>mockfiles/DirectionalDraggable.qml</file>
|
||||||
|
<file>mockfiles/PlanarDraggable.qml</file>
|
||||||
|
<file>mockfiles/PlanarMoveHandle.qml</file>
|
||||||
|
<file>mockfiles/PlanarScaleHandle.qml</file>
|
||||||
<file>mockfiles/ScaleRod.qml</file>
|
<file>mockfiles/ScaleRod.qml</file>
|
||||||
<file>mockfiles/ScaleGizmo.qml</file>
|
<file>mockfiles/ScaleGizmo.qml</file>
|
||||||
<file>mockfiles/meshes/arrow.mesh</file>
|
<file>mockfiles/meshes/arrow.mesh</file>
|
||||||
|
Reference in New Issue
Block a user