mirror of
https://github.com/alicevision/Meshroom.git
synced 2025-05-03 20:26:49 +02:00
593 lines
24 KiB
QML
593 lines
24 KiB
QML
import Qt3D.Core 2.15
|
|
import Qt3D.Render 2.15
|
|
import Qt3D.Input 2.15
|
|
import Qt3D.Extras 2.15
|
|
import QtQuick 2.15
|
|
import Qt3D.Logic 2.15
|
|
import QtQuick.Controls 2.15
|
|
import Utils 1.0
|
|
|
|
|
|
/**
|
|
* Simple transformation gizmo entirely made with Qt3D entities.
|
|
* Uses Python Transformations3DHelper to compute matrices.
|
|
* This TransformGizmo entity should only be instantiated in EntityWithGizmo entity which is its wrapper.
|
|
* It means, to use it for a specified application, make sure to instantiate EntityWithGizmo.
|
|
*/
|
|
Entity {
|
|
id: root
|
|
property Camera camera
|
|
property var windowSize
|
|
property Layer frontLayerComponent // Used to draw gizmo on top of everything
|
|
property var window
|
|
readonly property alias gizmoScale: gizmoScaleLookSlider.value
|
|
property bool uniformScale: false // By default, the scale is not uniform
|
|
property bool focusGizmoPriority: false // If true, it is used to give the priority to the current transformation (and not to a upper-level binding)
|
|
property Transform gizmoDisplayTransform: Transform {
|
|
id: gizmoDisplayTransform
|
|
scale: root.gizmoScale * (camera.position.minus(gizmoDisplayTransform.translation)).length() // The gizmo needs a constant apparent size
|
|
}
|
|
// Component the object controlled by the gizmo must use
|
|
property Transform objectTransform : Transform {
|
|
translation: gizmoDisplayTransform.translation
|
|
rotation: gizmoDisplayTransform.rotation
|
|
scale3D: Qt.vector3d(1,1,1)
|
|
}
|
|
|
|
signal pickedChanged(bool pressed)
|
|
signal gizmoChanged(var translation, var rotation, var scale, int type)
|
|
|
|
function emitGizmoChanged(type) {
|
|
const translation = gizmoDisplayTransform.translation // Position in space
|
|
const rotation = Qt.vector3d(gizmoDisplayTransform.rotationX, gizmoDisplayTransform.rotationY, gizmoDisplayTransform.rotationZ) // Euler angles
|
|
const scale = objectTransform.scale3D // Scale of the object
|
|
|
|
gizmoChanged(translation, rotation, scale, type)
|
|
root.focusGizmoPriority = false
|
|
}
|
|
|
|
components: [gizmoDisplayTransform, mouseHandler, frontLayerComponent]
|
|
|
|
|
|
/***** ENUMS *****/
|
|
|
|
enum Axis {
|
|
X,
|
|
Y,
|
|
Z
|
|
}
|
|
|
|
enum Type {
|
|
TRANSLATION,
|
|
ROTATION,
|
|
SCALE,
|
|
ALL
|
|
}
|
|
|
|
function convertAxisEnum(axis) {
|
|
switch (axis) {
|
|
case TransformGizmo.Axis.X: return Qt.vector3d(1,0,0)
|
|
case TransformGizmo.Axis.Y: return Qt.vector3d(0,1,0)
|
|
case TransformGizmo.Axis.Z: return Qt.vector3d(0,0,1)
|
|
}
|
|
}
|
|
|
|
function convertTypeEnum(type) {
|
|
switch (type) {
|
|
case TransformGizmo.Type.TRANSLATION: return "TRANSLATION"
|
|
case TransformGizmo.Type.ROTATION: return "ROTATION"
|
|
case TransformGizmo.Type.SCALE: return "SCALE"
|
|
case TransformGizmo.Type.ALL: return "ALL"
|
|
}
|
|
}
|
|
|
|
/***** TRANSFORMATIONS (using local vars) *****/
|
|
|
|
/**
|
|
* @brief Translate locally the gizmo and the object.
|
|
*
|
|
* @remarks
|
|
* To make local translation, we need to recompute a new matrix.
|
|
* Update gizmoDisplayTransform's matrix and all its properties while avoiding the override of translation property.
|
|
* Update objectTransform in the same time thanks to binding on translation property.
|
|
*
|
|
* @param initialModelMatrix object containing position, rotation and scale matrices + rotation quaternion
|
|
* @param translateVec vector3d used to make the local translation
|
|
*/
|
|
function doRelativeTranslation(initialModelMatrix, translateVec) {
|
|
Transformations3DHelper.relativeLocalTranslate(
|
|
gizmoDisplayTransform,
|
|
initialModelMatrix.position,
|
|
initialModelMatrix.rotation,
|
|
initialModelMatrix.scale,
|
|
translateVec
|
|
)
|
|
}
|
|
|
|
/**
|
|
* @brief Rotate the gizmo and the object around a specific axis.
|
|
*
|
|
* @remarks
|
|
* To make local rotation around an axis, we need to recompute a new matrix from a quaternion.
|
|
* Update gizmoDisplayTransform's matrix and all its properties while avoiding the override of rotation, rotationX, rotationY and rotationZ properties.
|
|
* Update objectTransform in the same time thanks to binding on rotation property.
|
|
*
|
|
* @param initialModelMatrix object containing position, rotation and scale matrices + rotation quaternion
|
|
* @param axis vector3d describing the axis to rotate around
|
|
* @param degree angle of rotation in degrees
|
|
*/
|
|
function doRelativeRotation(initialModelMatrix, axis, degree) {
|
|
Transformations3DHelper.relativeLocalRotate(
|
|
gizmoDisplayTransform,
|
|
initialModelMatrix.position,
|
|
initialModelMatrix.quaternion,
|
|
initialModelMatrix.scale,
|
|
axis,
|
|
degree
|
|
)
|
|
}
|
|
|
|
/**
|
|
* @brief Scale the object relatively to its current scale.
|
|
*
|
|
* @remarks
|
|
* To change scale of the object, we need to recompute a new matrix to avoid overriding bindings.
|
|
* Update objectTransform properties only (gizmoDisplayTransform is not affected).
|
|
*
|
|
* @param initialModelMatrix object containing position, rotation and scale matrices + rotation quaternion
|
|
* @param scaleVec vector3d used to make the relative scale
|
|
*/
|
|
function doRelativeScale(initialModelMatrix, scaleVec) {
|
|
Transformations3DHelper.relativeLocalScale(
|
|
objectTransform,
|
|
initialModelMatrix.position,
|
|
initialModelMatrix.rotation,
|
|
initialModelMatrix.scale,
|
|
scaleVec
|
|
)
|
|
}
|
|
|
|
/**
|
|
* @brief Reset the translation of the gizmo and the object.
|
|
*
|
|
* @remarks
|
|
* Update gizmoDisplayTransform's matrix and all its properties while avoiding the override of translation property.
|
|
* Update objectTransform in the same time thanks to binding on translation property.
|
|
*/
|
|
function resetTranslation() {
|
|
const mat = gizmoDisplayTransform.matrix
|
|
const newMat = Qt.matrix4x4(
|
|
mat.m11, mat.m12, mat.m13, 0,
|
|
mat.m21, mat.m22, mat.m23, 0,
|
|
mat.m31, mat.m32, mat.m33, 0,
|
|
mat.m41, mat.m42, mat.m43, 1
|
|
)
|
|
gizmoDisplayTransform.setMatrix(newMat)
|
|
}
|
|
|
|
/**
|
|
* @brief Reset the rotation of the gizmo and the object.
|
|
*
|
|
* @remarks
|
|
* Update gizmoDisplayTransform's quaternion while avoiding the override of rotationX, rotationY and rotationZ properties.
|
|
* Update objectTransform in the same time thanks to binding on rotation property.
|
|
* Here, we can change the rotation property (but not rotationX, rotationY and rotationZ because they can be used in upper-level bindings).
|
|
*
|
|
* @note
|
|
* We could implement a way of changing the matrix instead of overriding rotation (quaternion) property.
|
|
*/
|
|
function resetRotation() {
|
|
gizmoDisplayTransform.rotation = Qt.quaternion(1,0,0,0)
|
|
}
|
|
|
|
/**
|
|
* @brief Reset the scale of the object.
|
|
*
|
|
* @remarks
|
|
* To reset the scale, we make the difference of the current one to 1 and recompute the matrix.
|
|
* Like this, we kind of apply an inverse scale transformation.
|
|
* It prevents overriding scale3D property (because it can be used in upper-level binding).
|
|
*/
|
|
function resetScale() {
|
|
const modelMat = Transformations3DHelper.modelMatrixToMatrices(objectTransform.matrix)
|
|
const scaleDiff = Qt.vector3d(
|
|
-(objectTransform.scale3D.x - 1),
|
|
-(objectTransform.scale3D.y - 1),
|
|
-(objectTransform.scale3D.z - 1)
|
|
)
|
|
doRelativeScale(modelMat, scaleDiff)
|
|
}
|
|
|
|
/***** DEVICES *****/
|
|
|
|
MouseDevice { id: mouseSourceDevice }
|
|
|
|
MouseHandler {
|
|
id: mouseHandler
|
|
sourceDevice: enabled ? mouseSourceDevice : null
|
|
property var objectPicker: null
|
|
property bool enabled: false
|
|
|
|
onPositionChanged: {
|
|
if (objectPicker && objectPicker.button === Qt.LeftButton) {
|
|
root.focusGizmoPriority = true
|
|
|
|
// Get the selected axis
|
|
const pickedAxis = convertAxisEnum(objectPicker.gizmoAxis)
|
|
|
|
// TRANSLATION or SCALE transformation
|
|
if (objectPicker.gizmoType === TransformGizmo.Type.TRANSLATION || objectPicker.gizmoType === TransformGizmo.Type.SCALE) {
|
|
// Compute the vector PickedPosition -> CurrentMousePoint
|
|
const pickedPosition = objectPicker.screenPoint
|
|
const mouseVector = Qt.vector2d(mouse.x - pickedPosition.x, -(mouse.y - pickedPosition.y))
|
|
|
|
// Transform the positive picked axis vector from World Coord to Screen Coord
|
|
const gizmoLocalPointOnAxis = gizmoDisplayTransform.matrix.times(Qt.vector4d(pickedAxis.x, pickedAxis.y, pickedAxis.z, 1))
|
|
const gizmoCenterPoint = gizmoDisplayTransform.matrix.times(Qt.vector4d(0, 0, 0, 1))
|
|
const screenPoint2D = Transformations3DHelper.pointFromWorldToScreen(gizmoLocalPointOnAxis, camera, windowSize)
|
|
const screenCenter2D = Transformations3DHelper.pointFromWorldToScreen(gizmoCenterPoint, camera, windowSize)
|
|
const screenAxisVector = Qt.vector2d(screenPoint2D.x - screenCenter2D.x, -(screenPoint2D.y - screenCenter2D.y))
|
|
|
|
// Get the cosinus of the angle from the screenAxisVector to the mouseVector
|
|
// It will be used as a intensity factor
|
|
const cosAngle = screenAxisVector.dotProduct(mouseVector) / (screenAxisVector.length() * mouseVector.length())
|
|
const offset = cosAngle * mouseVector.length() / objectPicker.scaleUnit
|
|
|
|
// Do the transformation
|
|
if (objectPicker.gizmoType === TransformGizmo.Type.TRANSLATION && offset !== 0) {
|
|
doRelativeTranslation(objectPicker.modelMatrix, pickedAxis.times(offset)) // Do a translation from the initial Object Model Matrix when we picked the gizmo
|
|
} else if (objectPicker.gizmoType === TransformGizmo.Type.SCALE && offset !== 0) {
|
|
if (root.uniformScale)
|
|
doRelativeScale(objectPicker.modelMatrix, Qt.vector3d(1, 1, 1).times(offset)) // Do a uniform scale from the initial Object Model Matrix when we picked the gizmo
|
|
else
|
|
doRelativeScale(objectPicker.modelMatrix, pickedAxis.times(offset)) // Do a scale on one axis from the initial Object Model Matrix when we picked the gizmo
|
|
}
|
|
|
|
return
|
|
}
|
|
// ROTATION transformation
|
|
else if (objectPicker.gizmoType === TransformGizmo.Type.ROTATION) {
|
|
// Get Screen Coordinates of the gizmo center
|
|
const gizmoCenterPoint = gizmoDisplayTransform.matrix.times(Qt.vector4d(0, 0, 0, 1))
|
|
const screenCenter2D = Transformations3DHelper.pointFromWorldToScreen(gizmoCenterPoint, camera, root.windowSize)
|
|
|
|
// Get the vector screenCenter2D -> PickedPosition
|
|
const originalVector = Qt.vector2d(objectPicker.screenPoint.x - screenCenter2D.x, -(objectPicker.screenPoint.y - screenCenter2D.y))
|
|
|
|
// Compute the vector screenCenter2D -> CurrentMousePoint
|
|
const mouseVector = Qt.vector2d(mouse.x - screenCenter2D.x, -(mouse.y - screenCenter2D.y))
|
|
|
|
// Get the angle from the originalVector to the mouseVector
|
|
const angle = Math.atan2(-originalVector.y * mouseVector.x + originalVector.x * mouseVector.y, originalVector.x * mouseVector.x + originalVector.y * mouseVector.y) * 180 / Math.PI
|
|
|
|
// Get the orientation of the gizmo in function of the camera
|
|
const gizmoLocalAxisVector = gizmoDisplayTransform.matrix.times(Qt.vector4d(pickedAxis.x, pickedAxis.y, pickedAxis.z, 0))
|
|
const gizmoToCameraVector = camera.position.toVector4d().minus(gizmoCenterPoint)
|
|
const orientation = gizmoLocalAxisVector.dotProduct(gizmoToCameraVector) > 0 ? 1 : -1
|
|
|
|
if (angle !== 0) doRelativeRotation(objectPicker.modelMatrix, pickedAxis, angle * orientation) // Do a rotation from the initial Object Model Matrix when we picked the gizmo
|
|
|
|
return
|
|
}
|
|
}
|
|
|
|
if (objectPicker && objectPicker.button === Qt.RightButton) {
|
|
resetMenu.popup(window)
|
|
}
|
|
}
|
|
onReleased: {
|
|
if (objectPicker && mouse.button === Qt.LeftButton) {
|
|
const type = objectPicker.gizmoType
|
|
objectPicker = null // To prevent going again in the onPositionChanged
|
|
emitGizmoChanged(type)
|
|
}
|
|
}
|
|
}
|
|
|
|
Menu {
|
|
id: resetMenu
|
|
|
|
MenuItem {
|
|
text: "Reset Translation"
|
|
onTriggered: {
|
|
resetTranslation()
|
|
emitGizmoChanged(TransformGizmo.Type.TRANSLATION)
|
|
}
|
|
}
|
|
MenuItem {
|
|
text: "Reset Rotation"
|
|
onTriggered: {
|
|
resetRotation()
|
|
emitGizmoChanged(TransformGizmo.Type.ROTATION)
|
|
}
|
|
}
|
|
MenuItem {
|
|
text: "Reset Scale"
|
|
onTriggered: {
|
|
resetScale()
|
|
emitGizmoChanged(TransformGizmo.Type.SCALE)
|
|
}
|
|
}
|
|
MenuItem {
|
|
text: "Reset All"
|
|
onTriggered: {
|
|
resetTranslation()
|
|
resetRotation()
|
|
resetScale()
|
|
emitGizmoChanged(TransformGizmo.Type.ALL)
|
|
}
|
|
}
|
|
MenuItem {
|
|
text: "Gizmo Scale Look"
|
|
Slider {
|
|
id: gizmoScaleLookSlider
|
|
anchors.right: parent.right
|
|
anchors.rightMargin: 10
|
|
height: parent.height
|
|
width: parent.width * 0.40
|
|
|
|
from: 0.06
|
|
to: 0.30
|
|
stepSize: 0.01
|
|
value: 0.15
|
|
}
|
|
}
|
|
}
|
|
|
|
/***** GIZMO'S BASIC COMPONENTS *****/
|
|
|
|
Entity {
|
|
id: centerSphereEntity
|
|
components: [centerSphereMesh, centerSphereMaterial, frontLayerComponent]
|
|
|
|
SphereMesh {
|
|
id: centerSphereMesh
|
|
radius: 0.04
|
|
rings: 8
|
|
slices: 8
|
|
}
|
|
PhongMaterial {
|
|
id: centerSphereMaterial
|
|
property color base: "white"
|
|
ambient: base
|
|
shininess: 0.2
|
|
}
|
|
}
|
|
|
|
// AXIS GIZMO INSTANTIATOR => X, Y and Z
|
|
NodeInstantiator {
|
|
model: 3
|
|
|
|
Entity {
|
|
id: axisContainer
|
|
property int axis : {
|
|
switch (index) {
|
|
case 0: return TransformGizmo.Axis.X
|
|
case 1: return TransformGizmo.Axis.Y
|
|
case 2: return TransformGizmo.Axis.Z
|
|
}
|
|
}
|
|
property color baseColor: {
|
|
switch (axis) {
|
|
case TransformGizmo.Axis.X: return "#e63b55" // Red
|
|
case TransformGizmo.Axis.Y: return "#83c414" // Green
|
|
case TransformGizmo.Axis.Z: return "#3387e2" // Blue
|
|
}
|
|
}
|
|
property real lineRadius: 0.011
|
|
|
|
// SCALE ENTITY
|
|
Entity {
|
|
id: scaleEntity
|
|
|
|
Entity {
|
|
id: axisCylinder
|
|
components: [cylinderMesh, cylinderTransform, scaleMaterial, frontLayerComponent]
|
|
|
|
CylinderMesh {
|
|
id: cylinderMesh
|
|
length: 0.5
|
|
radius: axisContainer.lineRadius
|
|
rings: 2
|
|
slices: 16
|
|
}
|
|
Transform {
|
|
id: cylinderTransform
|
|
matrix: {
|
|
const offset = cylinderMesh.length / 2 + centerSphereMesh.radius
|
|
const m = Qt.matrix4x4()
|
|
switch (axis) {
|
|
case TransformGizmo.Axis.X: {
|
|
m.translate(Qt.vector3d(offset, 0, 0))
|
|
m.rotate(90, Qt.vector3d(0, 0, 1))
|
|
break
|
|
}
|
|
case TransformGizmo.Axis.Y: {
|
|
m.translate(Qt.vector3d(0, offset, 0))
|
|
break
|
|
}
|
|
case TransformGizmo.Axis.Z: {
|
|
m.translate(Qt.vector3d(0, 0, offset))
|
|
m.rotate(90, Qt.vector3d(1, 0, 0))
|
|
break
|
|
}
|
|
}
|
|
return m
|
|
}
|
|
}
|
|
}
|
|
|
|
Entity {
|
|
id: axisScaleBox
|
|
components: [cubeScaleMesh, cubeScaleTransform, scaleMaterial, scalePicker, frontLayerComponent]
|
|
|
|
CuboidMesh {
|
|
id: cubeScaleMesh
|
|
property real edge: 0.06
|
|
xExtent: edge
|
|
yExtent: edge
|
|
zExtent: edge
|
|
}
|
|
Transform {
|
|
id: cubeScaleTransform
|
|
matrix: {
|
|
const offset = cylinderMesh.length + centerSphereMesh.radius
|
|
const m = Qt.matrix4x4()
|
|
switch(axis) {
|
|
case TransformGizmo.Axis.X: {
|
|
m.translate(Qt.vector3d(offset, 0, 0))
|
|
m.rotate(90, Qt.vector3d(0, 0, 1))
|
|
break
|
|
}
|
|
case TransformGizmo.Axis.Y: {
|
|
m.translate(Qt.vector3d(0, offset, 0))
|
|
break
|
|
}
|
|
case TransformGizmo.Axis.Z: {
|
|
m.translate(Qt.vector3d(0, 0, offset))
|
|
m.rotate(90, Qt.vector3d(1, 0, 0))
|
|
break
|
|
}
|
|
}
|
|
return m
|
|
}
|
|
}
|
|
}
|
|
|
|
PhongMaterial {
|
|
id: scaleMaterial
|
|
ambient: baseColor
|
|
}
|
|
|
|
TransformGizmoPicker {
|
|
id: scalePicker
|
|
mouseController: mouseHandler
|
|
gizmoMaterial: scaleMaterial
|
|
gizmoBaseColor: baseColor
|
|
gizmoAxis: axis
|
|
gizmoType: TransformGizmo.Type.SCALE
|
|
|
|
onPickedChanged: {
|
|
// Save the current transformations of the OBJECT
|
|
this.modelMatrix = Transformations3DHelper.modelMatrixToMatrices(objectTransform.matrix)
|
|
// Compute a scale unit at picking time
|
|
this.scaleUnit = Transformations3DHelper.computeScaleUnitFromModelMatrix(convertAxisEnum(gizmoAxis), gizmoDisplayTransform.matrix, camera, root.windowSize)
|
|
// Prevent camera transformations
|
|
root.pickedChanged(picker.isPressed)
|
|
}
|
|
}
|
|
}
|
|
|
|
// TRANSLATION ENTITY
|
|
Entity {
|
|
id: positionEntity
|
|
components: [coneMesh, coneTransform, positionMaterial, positionPicker, frontLayerComponent]
|
|
|
|
ConeMesh {
|
|
id: coneMesh
|
|
bottomRadius: 0.035
|
|
topRadius: 0.001
|
|
hasBottomEndcap: true
|
|
hasTopEndcap: true
|
|
length: 0.13
|
|
rings: 2
|
|
slices: 8
|
|
}
|
|
Transform {
|
|
id: coneTransform
|
|
matrix: {
|
|
const offset = cylinderMesh.length + centerSphereMesh.radius + 0.4
|
|
const m = Qt.matrix4x4()
|
|
switch (axis) {
|
|
case TransformGizmo.Axis.X: {
|
|
m.translate(Qt.vector3d(offset, 0, 0))
|
|
m.rotate(-90, Qt.vector3d(0, 0, 1))
|
|
break
|
|
}
|
|
case TransformGizmo.Axis.Y: {
|
|
m.translate(Qt.vector3d(0, offset, 0))
|
|
break
|
|
}
|
|
case TransformGizmo.Axis.Z: {
|
|
m.translate(Qt.vector3d(0, 0, offset))
|
|
m.rotate(90, Qt.vector3d(1, 0, 0))
|
|
break
|
|
}
|
|
}
|
|
return m
|
|
}
|
|
}
|
|
PhongMaterial {
|
|
id: positionMaterial
|
|
ambient: baseColor
|
|
}
|
|
|
|
TransformGizmoPicker {
|
|
id: positionPicker
|
|
mouseController: mouseHandler
|
|
gizmoMaterial: positionMaterial
|
|
gizmoBaseColor: baseColor
|
|
gizmoAxis: axis
|
|
gizmoType: TransformGizmo.Type.TRANSLATION
|
|
|
|
onPickedChanged: {
|
|
// Save the current transformations of the OBJECT
|
|
this.modelMatrix = Transformations3DHelper.modelMatrixToMatrices(objectTransform.matrix)
|
|
// Compute a scale unit at picking time
|
|
this.scaleUnit = Transformations3DHelper.computeScaleUnitFromModelMatrix(convertAxisEnum(gizmoAxis), gizmoDisplayTransform.matrix, camera, root.windowSize)
|
|
// Prevent camera transformations
|
|
root.pickedChanged(picker.isPressed)
|
|
}
|
|
}
|
|
}
|
|
|
|
// ROTATION ENTITY
|
|
Entity {
|
|
id: rotationEntity
|
|
components: [torusMesh, torusTransform, rotationMaterial, rotationPicker, frontLayerComponent]
|
|
|
|
TorusMesh {
|
|
id: torusMesh
|
|
radius: cylinderMesh.length + 0.25
|
|
minorRadius: axisContainer.lineRadius
|
|
slices: 8
|
|
rings: 32
|
|
}
|
|
Transform {
|
|
id: torusTransform
|
|
matrix: {
|
|
const scaleDiff = 2 * torusMesh.minorRadius + 0.01 // Just to make sure there is no face overlapping
|
|
const m = Qt.matrix4x4()
|
|
switch (axis) {
|
|
case TransformGizmo.Axis.X: m.rotate(90, Qt.vector3d(0, 1, 0)); break
|
|
case TransformGizmo.Axis.Y: m.rotate(90, Qt.vector3d(1, 0, 0)); m.scale(Qt.vector3d(1 - scaleDiff, 1 - scaleDiff, 1 - scaleDiff)); break
|
|
case TransformGizmo.Axis.Z: m.scale(Qt.vector3d(1 - 2 * scaleDiff, 1 - 2 * scaleDiff, 1 - 2 * scaleDiff)); break
|
|
}
|
|
return m
|
|
}
|
|
}
|
|
PhongMaterial {
|
|
id: rotationMaterial
|
|
ambient: baseColor
|
|
}
|
|
|
|
TransformGizmoPicker {
|
|
id: rotationPicker
|
|
mouseController: mouseHandler
|
|
gizmoMaterial: rotationMaterial
|
|
gizmoBaseColor: baseColor
|
|
gizmoAxis: axis
|
|
gizmoType: TransformGizmo.Type.ROTATION
|
|
|
|
onPickedChanged: {
|
|
// Save the current transformations of the OBJECT
|
|
this.modelMatrix = Transformations3DHelper.modelMatrixToMatrices(objectTransform.matrix)
|
|
// No need to compute a scale unit for rotation
|
|
// Prevent camera transformations
|
|
root.pickedChanged(picker.isPressed)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|