QmlPuppet: Add separate set of qml files for Qt6 for 3D editor

Import QtQuick3D 1.15 no longer works in Qt 6.2, so provide a separate
set of qml files for each major Qt version.

Fixes: QDS-4642
Change-Id: I3e17fb248f71f87fb9a40dcad3c03e037cafb0f4
Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io>
Reviewed-by: Samuel Ghinet <samuel.ghinet@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
This commit is contained in:
Miikka Heikkinen
2021-06-28 14:04:43 +03:00
parent 48348b8dc4
commit b058b6e841
80 changed files with 4839 additions and 62 deletions
@@ -0,0 +1,55 @@
<RCC>
<qresource prefix="/qtquickplugin">
<file>mockfiles/meshes/arrow.mesh</file>
<file>mockfiles/meshes/scalerod.mesh</file>
<file>mockfiles/meshes/ring.mesh</file>
<file>mockfiles/meshes/ringselect.mesh</file>
<file>mockfiles/meshes/axishelper.mesh</file>
<file>mockfiles/images/editor_camera.png</file>
<file>mockfiles/images/editor_camera@2x.png</file>
<file>mockfiles/images/area.png</file>
<file>mockfiles/images/area@2x.png</file>
<file>mockfiles/images/directional.png</file>
<file>mockfiles/images/directional@2x.png</file>
<file>mockfiles/images/point.png</file>
<file>mockfiles/images/point@2x.png</file>
<file>mockfiles/images/spot.png</file>
<file>mockfiles/images/spot@2x.png</file>
<file>mockfiles/qt5/AdjustableArrow.qml</file>
<file>mockfiles/qt5/AreaLightHandle.qml</file>
<file>mockfiles/qt5/Arrow.qml</file>
<file>mockfiles/qt5/AutoScaleHelper.qml</file>
<file>mockfiles/qt5/AxisHelper.qml</file>
<file>mockfiles/qt5/AxisHelperArm.qml</file>
<file>mockfiles/qt5/CameraFrustum.qml</file>
<file>mockfiles/qt5/CameraGizmo.qml</file>
<file>mockfiles/qt5/DirectionalDraggable.qml</file>
<file>mockfiles/qt5/EditCameraController.qml</file>
<file>mockfiles/qt5/EditView3D.qml</file>
<file>mockfiles/qt5/FadeHandle.qml</file>
<file>mockfiles/qt5/HelperGrid.qml</file>
<file>mockfiles/qt5/IconGizmo.qml</file>
<file>mockfiles/qt5/IconRenderer3D.qml</file>
<file>mockfiles/qt5/LightGizmo.qml</file>
<file>mockfiles/qt5/LightIconGizmo.qml</file>
<file>mockfiles/qt5/LightModel.qml</file>
<file>mockfiles/qt5/Line3D.qml</file>
<file>mockfiles/qt5/MaterialNodeView.qml</file>
<file>mockfiles/qt5/ModelNode2DImageView.qml</file>
<file>mockfiles/qt5/ModelNode3DImageView.qml</file>
<file>mockfiles/qt5/ModelNodeView.qml</file>
<file>mockfiles/qt5/MoveGizmo.qml</file>
<file>mockfiles/qt5/NodeNodeView.qml</file>
<file>mockfiles/qt5/Overlay2D.qml</file>
<file>mockfiles/qt5/PlanarDraggable.qml</file>
<file>mockfiles/qt5/PlanarMoveHandle.qml</file>
<file>mockfiles/qt5/PlanarScaleHandle.qml</file>
<file>mockfiles/qt5/RotateGizmo.qml</file>
<file>mockfiles/qt5/RotateRing.qml</file>
<file>mockfiles/qt5/ScaleGizmo.qml</file>
<file>mockfiles/qt5/ScaleRod.qml</file>
<file>mockfiles/qt5/SceneView3D.qml</file>
<file>mockfiles/qt5/SelectionBox.qml</file>
<file>mockfiles/qt5/SpotLightHandle.qml</file>
</qresource>
</RCC>
@@ -0,0 +1,55 @@
<RCC>
<qresource prefix="/qtquickplugin">
<file>mockfiles/meshes/arrow.mesh</file>
<file>mockfiles/meshes/scalerod.mesh</file>
<file>mockfiles/meshes/ring.mesh</file>
<file>mockfiles/meshes/ringselect.mesh</file>
<file>mockfiles/meshes/axishelper.mesh</file>
<file>mockfiles/images/editor_camera.png</file>
<file>mockfiles/images/editor_camera@2x.png</file>
<file>mockfiles/images/area.png</file>
<file>mockfiles/images/area@2x.png</file>
<file>mockfiles/images/directional.png</file>
<file>mockfiles/images/directional@2x.png</file>
<file>mockfiles/images/point.png</file>
<file>mockfiles/images/point@2x.png</file>
<file>mockfiles/images/spot.png</file>
<file>mockfiles/images/spot@2x.png</file>
<file>mockfiles/qt6/AdjustableArrow.qml</file>
<file>mockfiles/qt6/AreaLightHandle.qml</file>
<file>mockfiles/qt6/Arrow.qml</file>
<file>mockfiles/qt6/AutoScaleHelper.qml</file>
<file>mockfiles/qt6/AxisHelper.qml</file>
<file>mockfiles/qt6/AxisHelperArm.qml</file>
<file>mockfiles/qt6/CameraFrustum.qml</file>
<file>mockfiles/qt6/CameraGizmo.qml</file>
<file>mockfiles/qt6/DirectionalDraggable.qml</file>
<file>mockfiles/qt6/EditCameraController.qml</file>
<file>mockfiles/qt6/EditView3D.qml</file>
<file>mockfiles/qt6/FadeHandle.qml</file>
<file>mockfiles/qt6/HelperGrid.qml</file>
<file>mockfiles/qt6/IconGizmo.qml</file>
<file>mockfiles/qt6/IconRenderer3D.qml</file>
<file>mockfiles/qt6/LightGizmo.qml</file>
<file>mockfiles/qt6/LightIconGizmo.qml</file>
<file>mockfiles/qt6/LightModel.qml</file>
<file>mockfiles/qt6/Line3D.qml</file>
<file>mockfiles/qt6/MaterialNodeView.qml</file>
<file>mockfiles/qt6/ModelNode2DImageView.qml</file>
<file>mockfiles/qt6/ModelNode3DImageView.qml</file>
<file>mockfiles/qt6/ModelNodeView.qml</file>
<file>mockfiles/qt6/MoveGizmo.qml</file>
<file>mockfiles/qt6/NodeNodeView.qml</file>
<file>mockfiles/qt6/Overlay2D.qml</file>
<file>mockfiles/qt6/PlanarDraggable.qml</file>
<file>mockfiles/qt6/PlanarMoveHandle.qml</file>
<file>mockfiles/qt6/PlanarScaleHandle.qml</file>
<file>mockfiles/qt6/RotateGizmo.qml</file>
<file>mockfiles/qt6/RotateRing.qml</file>
<file>mockfiles/qt6/ScaleGizmo.qml</file>
<file>mockfiles/qt6/ScaleRod.qml</file>
<file>mockfiles/qt6/SceneView3D.qml</file>
<file>mockfiles/qt6/SelectionBox.qml</file>
<file>mockfiles/qt6/SpotLightHandle.qml</file>
</qresource>
</RCC>
@@ -28,7 +28,7 @@ import QtQuick3D 1.15
DirectionalDraggable {
id: arrow
source: "meshes/arrow.mesh"
source: "../meshes/arrow.mesh"
signal positionCommit()
signal positionMove()
@@ -42,7 +42,7 @@ Node {
property bool hovering: false
property vector3d cameraRotation: armRoot.camRotPos
source: "meshes/axishelper.mesh"
source: "../meshes/axishelper.mesh"
materials: DefaultMaterial {
id: posMat
diffuseColor: posModel.hovering ? armRoot.hoverColor : armRoot.color
@@ -49,12 +49,12 @@ Model {
signal rotateCommit()
signal rotateChange()
source: "meshes/ring.mesh"
source: "../meshes/ring.mesh"
Model {
id: pickModel
objectName: "PickModel for " + rotateRing.objectName
source: "meshes/ringselect.mesh"
source: "../meshes/ringselect.mesh"
pickable: true
}
@@ -29,7 +29,7 @@ import MouseArea3D 1.0
DirectionalDraggable {
id: scaleRod
source: "meshes/scalerod.mesh"
source: "../meshes/scalerod.mesh"
property vector3d axis
@@ -0,0 +1,51 @@
/****************************************************************************
**
** Copyright (C) 2020 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 6.0
import QtQuick3D 6.0
import LineGeometry 1.0
DirectionalDraggable {
id: arrowRoot
Model {
geometry: LineGeometry {
id: lineGeometry
name: "Edit 3D ScalableArrow"
startPos: Qt.vector3d(0, 0, 0)
endPos: Qt.vector3d(0, 1, 0)
}
scale: Qt.vector3d(1, arrowRoot.length, 1)
materials: [ arrowRoot.material ]
}
Model {
id: arrowHead
source: "#Cone"
materials: [ arrowRoot.material ]
y: arrowRoot.length - 3
scale: Qt.vector3d(0.02, 0.035, 0.02)
}
}
@@ -0,0 +1,85 @@
/****************************************************************************
**
** Copyright (C) 2020 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 6.0
import QtQuick3D 6.0
DirectionalDraggable {
id: handleRoot
property string currentLabel
property point currentMousePos
property string propName
property real propValue: 0
property real newValue: 0
property real baseScale: 5
scale: autoScaler.getScale(Qt.vector3d(baseScale, baseScale, baseScale))
length: 3
offset: -1.5
Model {
id: handle
source: "#Sphere"
materials: [ handleRoot.material ]
scale: Qt.vector3d(0.02, 0.02, 0.02)
}
AutoScaleHelper {
id: autoScaler
active: handleRoot.active
view3D: handleRoot.view3D
}
property real _startValue
property real _startScale
signal valueCommit()
signal valueChange()
function updateValue(relativeDistance, screenPos)
{
handleRoot.newValue = Math.round(Math.min(999999, Math.max(0, _startValue + (relativeDistance * _startScale))));
var l = Qt.locale();
handleRoot.currentLabel = propName + qsTr(": ") + Number(newValue).toLocaleString(l, 'f', 0);
handleRoot.currentMousePos = screenPos;
}
onPressed: (mouseArea, screenPos)=> {
_startScale = autoScaler.relativeScale * baseScale;
_startValue = propValue;
updateValue(0, screenPos);
}
onDragged: (mouseArea, sceneRelativeDistance, relativeDistance, screenPos)=> {
updateValue(relativeDistance, screenPos);
handleRoot.valueChange();
}
onReleased: (mouseArea, sceneRelativeDistance, relativeDistance, screenPos)=> {
updateValue(relativeDistance, screenPos);
handleRoot.valueCommit();
}
}
@@ -0,0 +1,63 @@
/****************************************************************************
**
** 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 6.0
import QtQuick3D 6.0
DirectionalDraggable {
id: arrow
source: "../meshes/arrow.mesh"
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 ? targetNode.parent.mapPositionFromScene(newScenePos) : newScenePos;
}
onPressed: {
if (targetNode == multiSelectionNode)
_generalHelper.restartMultiSelection();
}
onDragged: (mouseArea, sceneRelativeDistance)=> {
targetNode.position = localPos(sceneRelativeDistance);
if (targetNode == multiSelectionNode)
_generalHelper.moveMultiSelection(false);
positionMove();
}
onReleased: (mouseArea, sceneRelativeDistance)=> {
targetNode.position = localPos(sceneRelativeDistance);
if (targetNode == multiSelectionNode)
_generalHelper.moveMultiSelection(true);
positionCommit();
}
}
@@ -0,0 +1,74 @@
/****************************************************************************
**
** 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 6.0
import QtQuick3D 6.0
import MouseArea3D 1.0
Node {
id: overlayNode
property View3D view3D
property Camera camera: view3D.camera
property bool active: true
// Read-only
property real relativeScale: 1
onActiveChanged: updateScale()
onSceneTransformChanged: updateScale()
// Trigger delayed update on camera change to ensure camera values are correct
onCameraChanged: _generalHelper.requestOverlayUpdate();
Connections {
target: camera
function onSceneTransformChanged() { updateScale() }
}
Connections {
target: _generalHelper
function onOverlayUpdateNeeded() { updateScale() }
}
function getScale(baseScale)
{
return Qt.vector3d(baseScale.x * relativeScale, baseScale.y * relativeScale,
baseScale.z * relativeScale);
}
function updateScale()
{
if (active)
relativeScale = helper.getRelativeScale(overlayNode);
else
relativeScale = 1;
}
MouseArea3D {
id: helper
active: false
view3D: overlayNode.view3D
}
}
@@ -0,0 +1,133 @@
/****************************************************************************
**
** 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 6.0
import QtQuick3D 6.0
View3D {
id: axisHelperView
property var editCameraCtrl
property Node selectedNode
camera: axisHelperCamera
Node {
OrthographicCamera {
id: axisHelperCamera
rotation: editCameraCtrl.camera ? editCameraCtrl.camera.rotation : Qt.quaternion(1, 0, 0, 0)
position: editCameraCtrl.camera ? editCameraCtrl.camera.position.minus(editCameraCtrl._lookAtPoint)
.normalized().times(600) : Qt.vector3d(0, 0, 0)
}
AutoScaleHelper {
id: autoScale
view3D: axisHelperView
position: axisHelperGizmo.scenePosition
}
Node {
id: axisHelperGizmo
scale: autoScale.getScale(Qt.vector3d(4, 4, 4))
AxisHelperArm {
id: armX
eulerRotation: Qt.vector3d(0, 0, -90)
color: Qt.rgba(1, 0, 0, 1)
hoverColor: Qt.lighter(Qt.rgba(1, 0, 0, 1))
view3D: axisHelperView
camRotPos: Qt.vector3d(0, 90, 0)
camRotNeg: Qt.vector3d(0, -90, 0)
}
AxisHelperArm {
id: armY
eulerRotation: Qt.vector3d(0, 0, 0)
color: Qt.rgba(0, 0.6, 0, 1)
hoverColor: Qt.lighter(Qt.rgba(0, 0.6, 0, 1))
view3D: axisHelperView
camRotPos: Qt.vector3d(-90, 0, 0)
camRotNeg: Qt.vector3d(90, 0, 0)
}
AxisHelperArm {
id: armZ
eulerRotation: Qt.vector3d(90, 0, 0)
color: Qt.rgba(0, 0, 1, 1)
hoverColor: Qt.lighter(Qt.rgba(0, 0, 1, 1))
view3D: axisHelperView
camRotPos: Qt.vector3d(0, 0, 0)
camRotNeg: Qt.vector3d(0, 180, 0)
}
}
}
MouseArea {
anchors.fill: parent
hoverEnabled: true
acceptedButtons: Qt.LeftButton
property var pickObj: null
function cancelHover()
{
if (pickObj) {
pickObj.hovering = false;
pickObj = null;
}
}
function pick(mouse)
{
var result = axisHelperView.pick(mouse.x, mouse.y);
if (result.objectHit) {
if (result.objectHit !== pickObj) {
cancelHover();
pickObj = result.objectHit;
pickObj.hovering = true;
}
} else {
cancelHover();
}
}
onPositionChanged: (mouse)=> {
pick(mouse);
}
onPressed: (mouse)=> {
pick(mouse);
if (pickObj) {
axisHelperView.editCameraCtrl.focusObject(axisHelperView.selectedNode,
pickObj.cameraRotation, false, false);
} else {
mouse.accepted = false;
}
}
onExited: cancelHover()
onCanceled: cancelHover()
}
}
@@ -0,0 +1,70 @@
/****************************************************************************
**
** 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 6.0
import QtQuick3D 6.0
Node {
id: armRoot
property alias posModel: posModel
property alias negModel: negModel
property View3D view3D
property color hoverColor
property color color
property vector3d camRotPos
property vector3d camRotNeg
Model {
id: posModel
property bool hovering: false
property vector3d cameraRotation: armRoot.camRotPos
source: "../meshes/axishelper.mesh"
materials: DefaultMaterial {
id: posMat
diffuseColor: posModel.hovering ? armRoot.hoverColor : armRoot.color
lighting: DefaultMaterial.NoLighting
}
pickable: true
}
Model {
id: negModel
property bool hovering: false
property vector3d cameraRotation: armRoot.camRotNeg
source: "#Sphere"
y: -6
scale: Qt.vector3d(0.025, 0.025, 0.025)
materials: DefaultMaterial {
id: negMat
diffuseColor: negModel.hovering ? armRoot.hoverColor : armRoot.color
lighting: DefaultMaterial.NoLighting
}
pickable: true
}
}
@@ -0,0 +1,61 @@
/****************************************************************************
**
** Copyright (C) 2020 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 6.0
import QtQuick3D 6.0
import CameraGeometry 1.0
Model {
id: cameraFrustum
property alias geometryName: cameraGeometry.name // Name must be unique for each geometry
property alias viewPortRect: cameraGeometry.viewPortRect
property Node targetNode: null
property Node scene: null
property bool selected: false
function updateGeometry()
{
cameraGeometry.update();
}
position: targetNode ? targetNode.scenePosition : Qt.vector3d(0, 0, 0)
rotation: targetNode ? targetNode.sceneRotation : Qt.quaternion(1, 0, 0, 0)
geometry: cameraGeometry
materials: [
DefaultMaterial {
id: defaultMaterial
diffuseColor: cameraFrustum.selected ? "#FF0000" : "#555555"
lighting: DefaultMaterial.NoLighting
cullMode: Material.NoCulling
}
]
CameraGeometry {
id: cameraGeometry
camera: cameraFrustum.scene && cameraFrustum.targetNode ? cameraFrustum.targetNode : null
}
}
@@ -0,0 +1,57 @@
/****************************************************************************
**
** 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 6.0
import QtQuick3D 6.0
IconGizmo {
id: cameraGizmo
property Model frustumModel: null
iconSource: "qrc:///qtquickplugin/mockfiles/images/editor_camera.png"
function connectFrustum(frustum)
{
frustumModel = frustum;
frustum.selected = selected;
frustum.selected = Qt.binding(function() {return selected;});
frustum.scene = scene;
frustum.scene = Qt.binding(function() {return scene;});
frustum.targetNode = targetNode;
frustum.targetNode = Qt.binding(function() {return targetNode;});
frustum.visible = visible || (targetNode && selected && activeScene === scene);
frustum.visible = Qt.binding(function() {return visible || (targetNode && selected && activeScene === scene);});
}
onActiveSceneChanged: {
if (frustumModel && activeScene == scene)
frustumModel.updateGeometry();
}
}
@@ -0,0 +1,144 @@
/****************************************************************************
**
** 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 6.0
import QtQuick3D 6.0
import MouseArea3D 1.0
Model {
id: rootModel
property View3D view3D
property alias color: material.diffuseColor
property Node targetNode: null
property bool dragging: mouseAreaYZ.dragging || mouseAreaXZ.dragging
property bool active: false
property MouseArea3D dragHelper: null
property alias material: material
property real length: 12
property real offset: 0
readonly property bool hovering: mouseAreaYZ.hovering || mouseAreaXZ.hovering
property vector3d _scenePosPressed
property real _posPressed
property vector3d _targetStartPos
signal pressed(var mouseArea, point screenPos)
signal dragged(var mouseArea, vector3d sceneRelativeDistance, real relativeDistance, point screenPos)
signal released(var mouseArea, vector3d sceneRelativeDistance, real relativeDistance, point screenPos)
DefaultMaterial {
id: material
diffuseColor: "white"
lighting: DefaultMaterial.NoLighting
}
materials: [ material ]
function handlePressed(mouseArea, planePos, screenPos)
{
if (!targetNode)
return;
var maskedPosition = Qt.vector3d(planePos.x, 0, 0);
_posPressed = planePos.x;
_scenePosPressed = mouseArea.dragHelper.mapPositionToScene(maskedPosition);
_targetStartPos = mouseArea.pivotScenePosition(targetNode);
pressed(mouseArea, screenPos);
}
function calcRelativeDistance(mouseArea, planePos)
{
var maskedPosition = Qt.vector3d(planePos.x, 0, 0);
var scenePointerPos = mouseArea.dragHelper.mapPositionToScene(maskedPosition);
return scenePointerPos.minus(_scenePosPressed);
}
function handleDragged(mouseArea, planePos, screenPos)
{
if (!targetNode)
return;
dragged(mouseArea, calcRelativeDistance(mouseArea, planePos), planePos.x - _posPressed, screenPos);
}
function handleReleased(mouseArea, planePos, screenPos)
{
if (!targetNode)
return;
released(mouseArea, calcRelativeDistance(mouseArea, planePos), planePos.x - _posPressed, screenPos);
}
MouseArea3D {
id: mouseAreaYZ
view3D: rootModel.view3D
x: rootModel.offset
y: -1.5
width: rootModel.length
height: 3
eulerRotation: Qt.vector3d(0, 0, 90)
grabsMouse: targetNode
active: rootModel.active
dragHelper: rootModel.dragHelper
priority: 5
onPressed: (planePos, screenPos)=> {
rootModel.handlePressed(mouseAreaYZ, planePos, screenPos);
}
onDragged: (planePos, screenPos)=> {
rootModel.handleDragged(mouseAreaYZ, planePos, screenPos);
}
onReleased: (planePos, screenPos)=> {
rootModel.handleReleased(mouseAreaYZ, planePos, screenPos);
}
}
MouseArea3D {
id: mouseAreaXZ
view3D: rootModel.view3D
x: rootModel.offset
y: -1.5
width: rootModel.length
height: 3
eulerRotation: Qt.vector3d(0, 90, 90)
grabsMouse: targetNode
active: rootModel.active
dragHelper: rootModel.dragHelper
priority: 5
onPressed: (planePos, screenPos)=> {
rootModel.handlePressed(mouseAreaXZ, planePos, screenPos);
}
onDragged: (planePos, screenPos)=> {
rootModel.handleDragged(mouseAreaXZ, planePos, screenPos);
}
onReleased: (planePos, screenPos)=> {
rootModel.handleReleased(mouseAreaXZ, planePos, screenPos);
}
}
}
@@ -0,0 +1,184 @@
/****************************************************************************
**
** 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 6.0
import QtQuick3D 6.0
Item {
id: cameraCtrl
property Camera camera: null
property View3D view3d: null
property string sceneId
property vector3d _lookAtPoint
property vector3d _pressPoint
property vector3d _prevPoint
property vector3d _startRotation
property vector3d _startPosition
property vector3d _startLookAtPoint
property matrix4x4 _startTransform
property bool _dragging
property int _button
property real _zoomFactor: 1
property Camera _prevCamera: null
readonly property vector3d _defaultCameraPosition: Qt.vector3d(0, 600, 600)
readonly property vector3d _defaultCameraRotation: Qt.vector3d(-45, 0, 0)
readonly property real _defaultCameraLookAtDistance: _defaultCameraPosition.length()
property bool ignoreToolState: false
function restoreCameraState(cameraState)
{
if (!camera || ignoreToolState)
return;
_lookAtPoint = cameraState[0];
_zoomFactor = cameraState[1];
camera.position = cameraState[2];
camera.rotation = cameraState[3];
_generalHelper.zoomCamera(camera, 0, _defaultCameraLookAtDistance, _lookAtPoint,
_zoomFactor, false);
}
function restoreDefaultState()
{
if (!camera)
return;
_lookAtPoint = Qt.vector3d(0, 0, 0);
_zoomFactor = 1;
camera.position = _defaultCameraPosition;
camera.eulerRotation = _defaultCameraRotation;
_generalHelper.zoomCamera(camera, 0, _defaultCameraLookAtDistance, _lookAtPoint,
_zoomFactor, false);
}
function storeCameraState(delay)
{
if (!camera || ignoreToolState)
return;
var cameraState = [];
cameraState[0] = _lookAtPoint;
cameraState[1] = _zoomFactor;
cameraState[2] = camera.position;
cameraState[3] = camera.rotation;
_generalHelper.storeToolState(sceneId, "editCamState", cameraState, delay);
}
function focusObject(targetObject, rotation, updateZoom, closeUp)
{
if (!camera)
return;
camera.eulerRotation = rotation;
var newLookAtAndZoom = _generalHelper.focusObjectToCamera(
camera, _defaultCameraLookAtDistance, targetObject, view3d, _zoomFactor,
updateZoom, closeUp);
_lookAtPoint = newLookAtAndZoom.toVector3d();
_zoomFactor = newLookAtAndZoom.w;
storeCameraState(0);
}
function zoomRelative(distance)
{
if (!camera)
return;
_zoomFactor = _generalHelper.zoomCamera(camera, distance, _defaultCameraLookAtDistance,
_lookAtPoint, _zoomFactor, true);
}
onCameraChanged: {
if (camera && _prevCamera) {
// Reset zoom on previous camera to ensure it's properties are good to copy to new cam
_generalHelper.zoomCamera(_prevCamera, 0, _defaultCameraLookAtDistance, _lookAtPoint,
1, false);
camera.position = _prevCamera.position;
camera.rotation = _prevCamera.rotation;
// Apply correct zoom to new camera
_generalHelper.zoomCamera(camera, 0, _defaultCameraLookAtDistance, _lookAtPoint,
_zoomFactor, false);
}
_prevCamera = camera;
}
MouseArea {
id: mouseHandler
acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton
hoverEnabled: false
anchors.fill: parent
onPositionChanged: (mouse)=> {
if (cameraCtrl.camera && mouse.modifiers === Qt.AltModifier && cameraCtrl._dragging) {
var currentPoint = Qt.vector3d(mouse.x, mouse.y, 0);
if (cameraCtrl._button == Qt.LeftButton) {
_generalHelper.orbitCamera(cameraCtrl.camera, cameraCtrl._startRotation,
cameraCtrl._lookAtPoint, cameraCtrl._pressPoint,
currentPoint);
} else if (cameraCtrl._button == Qt.MiddleButton) {
cameraCtrl._lookAtPoint = _generalHelper.panCamera(
cameraCtrl.camera, cameraCtrl._startTransform,
cameraCtrl._startPosition, cameraCtrl._startLookAtPoint,
cameraCtrl._pressPoint, currentPoint, _zoomFactor);
} else if (cameraCtrl._button == Qt.RightButton) {
cameraCtrl.zoomRelative(currentPoint.y - cameraCtrl._prevPoint.y)
cameraCtrl._prevPoint = currentPoint;
}
}
}
onPressed: (mouse)=> {
if (cameraCtrl.camera && mouse.modifiers === Qt.AltModifier) {
cameraCtrl._dragging = true;
cameraCtrl._startRotation = cameraCtrl.camera.eulerRotation;
cameraCtrl._startPosition = cameraCtrl.camera.position;
cameraCtrl._startLookAtPoint = _lookAtPoint;
cameraCtrl._pressPoint = Qt.vector3d(mouse.x, mouse.y, 0);
cameraCtrl._prevPoint = cameraCtrl._pressPoint;
cameraCtrl._button = mouse.button;
cameraCtrl._startTransform = cameraCtrl.camera.sceneTransform;
} else {
mouse.accepted = false;
}
}
function handleRelease() {
cameraCtrl._dragging = false;
cameraCtrl.storeCameraState(0);
}
onReleased: handleRelease()
onCanceled: handleRelease()
onWheel: (wheel)=> {
if (cameraCtrl.camera) {
// Empirically determined divisor for nice zoom
cameraCtrl.zoomRelative(wheel.angleDelta.y / -40);
cameraCtrl.storeCameraState(500);
}
}
}
}
@@ -0,0 +1,884 @@
/****************************************************************************
**
** 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 6.0
import QtQuick3D 6.0
import MouseArea3D 1.0
Item {
id: viewRoot
width: 1024
height: 768
visible: true
property Node activeScene: null
property View3D editView: null
property string sceneId
property bool showEditLight: false
property bool showGrid: true
property bool usePerspective: true
property bool globalOrientation: false
property alias contentItem: contentItem
enum SelectionMode { Item, Group }
enum TransformMode { Move, Rotate, Scale }
property int selectionMode: EditView3D.SelectionMode.Item
property int transformMode: EditView3D.TransformMode.Move
property Node selectedNode: null // This is multiSelectionNode in multi-selection case
property var selectedNodes: [] // All selected nodes
property var lightIconGizmos: []
property var cameraGizmos: []
property var selectionBoxes: []
property rect viewPortRect: Qt.rect(0, 0, 1000, 1000)
property bool shuttingDown: false
property real fps: 0
signal selectionChanged(var selectedNodes)
signal commitObjectProperty(var objects, var propNames)
signal changeObjectProperty(var objects, var propNames)
signal notifyActiveSceneChange()
onUsePerspectiveChanged: _generalHelper.storeToolState(sceneId, "usePerspective", usePerspective)
onShowEditLightChanged: _generalHelper.storeToolState(sceneId, "showEditLight", showEditLight)
onGlobalOrientationChanged: _generalHelper.storeToolState(sceneId, "globalOrientation", globalOrientation)
onShowGridChanged: _generalHelper.storeToolState(sceneId, "showGrid", showGrid);
onSelectionModeChanged: _generalHelper.storeToolState(sceneId, "selectionMode", selectionMode);
onTransformModeChanged: _generalHelper.storeToolState(sceneId, "transformMode", transformMode);
onActiveSceneChanged: updateActiveScene()
function aboutToShutDown()
{
shuttingDown = true;
}
function createEditView()
{
var component = Qt.createComponent("SceneView3D.qml");
if (component.status === Component.Ready) {
editView = component.createObject(viewRect,
{"usePerspective": usePerspective,
"showSceneLight": showEditLight,
"showGrid": showGrid,
"importScene": activeScene,
"cameraZoomFactor": cameraControl._zoomFactor,
"z": 1});
editView.usePerspective = Qt.binding(function() {return usePerspective;});
editView.showSceneLight = Qt.binding(function() {return showEditLight;});
editView.showGrid = Qt.binding(function() {return showGrid;});
editView.cameraZoomFactor = Qt.binding(function() {return cameraControl._zoomFactor;});
selectionBoxes.length = 0;
return true;
}
return false;
}
function updateActiveScene()
{
if (editView) {
// Destroy is async, so make sure we don't get any more updates for the old editView
_generalHelper.enableItemUpdate(editView, false);
editView.visible = false;
editView.destroy();
}
// importScene cannot be updated after initial set, so we need to reconstruct entire View3D
if (createEditView()) {
if (activeScene) {
var toolStates = _generalHelper.getToolStates(sceneId);
if (Object.keys(toolStates).length > 0) {
updateToolStates(toolStates, true);
} else {
// Don't inherit the edit light state from the previous scene, but rather
// turn the edit light on for scenes that do not have any scene
// lights, and turn it off for scenes that have.
var hasSceneLight = false;
for (var i = 0; i < lightIconGizmos.length; ++i) {
if (lightIconGizmos[i].scene === activeScene) {
hasSceneLight = true;
break;
}
}
showEditLight = !hasSceneLight;
storeCurrentToolStates();
}
} else {
// When active scene is deleted, this function gets called by object deletion
// handlers without going through setActiveScene, so make sure sceneId is cleared.
// This is skipped during application shutdown, as calling QQuickText::setText()
// during application shutdown can crash the application.
if (!shuttingDown) {
sceneId = "";
storeCurrentToolStates();
}
}
notifyActiveSceneChange();
}
}
function setActiveScene(newScene, newSceneId)
{
var needExplicitUpdate = !activeScene && !newScene;
sceneId = newSceneId;
activeScene = newScene;
if (needExplicitUpdate)
updateActiveScene();
}
// Disables edit view update if scene doesn't match current activeScene.
// If it matches, updates are enabled.
function enableEditViewUpdate(scene)
{
if (editView)
_generalHelper.enableItemUpdate(editView, (scene && scene === activeScene));
}
function handleActiveSceneIdChange(newId)
{
if (sceneId !== newId) {
sceneId = newId;
storeCurrentToolStates();
}
}
function fitToView()
{
if (editView) {
var targetNode = selectionBoxes.length > 0
? selectionBoxes[0].model : null;
cameraControl.focusObject(targetNode, editView.camera.eulerRotation, true, false);
}
}
// If resetToDefault is true, tool states not specifically set to anything will be reset to
// their default state.
function updateToolStates(toolStates, resetToDefault)
{
if ("showEditLight" in toolStates)
showEditLight = toolStates.showEditLight;
else if (resetToDefault)
showEditLight = false;
if ("showGrid" in toolStates)
showGrid = toolStates.showGrid;
else if (resetToDefault)
showGrid = true;
if ("usePerspective" in toolStates)
usePerspective = toolStates.usePerspective;
else if (resetToDefault)
usePerspective = true;
if ("globalOrientation" in toolStates)
globalOrientation = toolStates.globalOrientation;
else if (resetToDefault)
globalOrientation = false;
if ("selectionMode" in toolStates)
selectionMode = toolStates.selectionMode;
else if (resetToDefault)
selectionMode = EditView3D.SelectionMode.Item;
if ("transformMode" in toolStates)
transformMode = toolStates.transformMode;
else if (resetToDefault)
transformMode = EditView3D.TransformMode.Move;
if ("editCamState" in toolStates)
cameraControl.restoreCameraState(toolStates.editCamState);
else if (resetToDefault)
cameraControl.restoreDefaultState();
}
function storeCurrentToolStates()
{
_generalHelper.storeToolState(sceneId, "showEditLight", showEditLight)
_generalHelper.storeToolState(sceneId, "showGrid", showGrid)
_generalHelper.storeToolState(sceneId, "usePerspective", usePerspective)
_generalHelper.storeToolState(sceneId, "globalOrientation", globalOrientation)
_generalHelper.storeToolState(sceneId, "selectionMode", selectionMode);
_generalHelper.storeToolState(sceneId, "transformMode", transformMode);
cameraControl.storeCameraState(0);
}
function ensureSelectionBoxes(count)
{
var needMore = count - selectionBoxes.length
if (needMore > 0) {
var component = Qt.createComponent("SelectionBox.qml");
if (component.status === Component.Ready) {
for (var i = 0; i < needMore; ++i) {
var geometryName = _generalHelper.generateUniqueName("SelectionBoxGeometry");
var boxParent = null;
if (editView)
boxParent = editView.sceneHelpers;
var box = component.createObject(boxParent, {"view3D": editView,
"geometryName": geometryName});
selectionBoxes[selectionBoxes.length] = box;
box.view3D = Qt.binding(function() {return editView;});
}
}
}
}
function selectObjects(objects)
{
// Create selection boxes as necessary. One more box than is actually needed is created, so
// that we always have a previously created box to use for new selection.
// This fixes an occasional visual glitch when creating a new box.
ensureSelectionBoxes(objects.length + 1)
var i;
for (i = 0; i < objects.length; ++i)
selectionBoxes[i].targetNode = objects[i];
for (i = objects.length; i < selectionBoxes.length; ++i)
selectionBoxes[i].targetNode = null;
selectedNodes = objects;
if (objects.length === 0) {
selectedNode = null;
} else if (objects.length > 1) {
selectedNode = multiSelectionNode;
_generalHelper.setMultiSelectionTargets(multiSelectionNode, objects);
} else {
selectedNode = objects[0];
}
}
function handleObjectClicked(object, multi)
{
var clickedObject;
// Click on locked object is treated same as click on empty space
if (!_generalHelper.isLocked(object))
clickedObject = object;
if (selectionMode === EditView3D.SelectionMode.Group) {
while (clickedObject && clickedObject !== activeScene
&& (activeScene instanceof Model || clickedObject.parent !== activeScene)) {
clickedObject = clickedObject.parent;
}
}
// Object selection logic:
// Regular click: Clear any multiselection, single-selects the clicked object
// Ctrl-click: No objects selected: Act as single select
// One or more objects selected: Multiselect
// Null object always clears entire selection
var newSelection = [];
if (clickedObject) {
if (multi && selectedNodes.length > 0) {
var deselect = false;
for (var i = 0; i < selectedNodes.length; ++i) {
// Multiselecting already selected object clears that object from selection
if (selectedNodes[i] !== clickedObject)
newSelection[newSelection.length] = selectedNodes[i];
else
deselect = true;
}
if (!deselect)
newSelection[newSelection.length] = clickedObject;
} else {
newSelection[0] = clickedObject;
}
}
selectObjects(newSelection);
selectionChanged(newSelection);
}
function addLightGizmo(scene, obj)
{
// Insert into first available gizmo if we don't already have gizmo for this object
var slotFound = -1;
for (var i = 0; i < lightIconGizmos.length; ++i) {
if (!lightIconGizmos[i].targetNode) {
slotFound = i;
} else if (lightIconGizmos[i].targetNode === obj) {
lightIconGizmos[i].scene = scene;
return;
}
}
if (slotFound !== -1) {
lightIconGizmos[slotFound].scene = scene;
lightIconGizmos[slotFound].targetNode = obj;
lightIconGizmos[slotFound].locked = _generalHelper.isLocked(obj);
lightIconGizmos[slotFound].hidden = _generalHelper.isHidden(obj);
_generalHelper.registerGizmoTarget(obj);
return;
}
// No free gizmos available, create a new one
var gizmoComponent = Qt.createComponent("LightIconGizmo.qml");
if (gizmoComponent.status === Component.Ready) {
_generalHelper.registerGizmoTarget(obj);
var gizmo = gizmoComponent.createObject(overlayView,
{"view3D": overlayView, "targetNode": obj,
"selectedNodes": selectedNodes, "scene": scene,
"activeScene": activeScene,
"locked": _generalHelper.isLocked(obj),
"hidden": _generalHelper.isHidden(obj)});
lightIconGizmos[lightIconGizmos.length] = gizmo;
gizmo.clicked.connect(handleObjectClicked);
gizmo.selectedNodes = Qt.binding(function() {return selectedNodes;});
gizmo.activeScene = Qt.binding(function() {return activeScene;});
}
}
function addCameraGizmo(scene, obj)
{
// Insert into first available gizmo if we don't already have gizmo for this object
var slotFound = -1;
for (var i = 0; i < cameraGizmos.length; ++i) {
if (!cameraGizmos[i].targetNode) {
slotFound = i;
} else if (cameraGizmos[i].targetNode === obj) {
cameraGizmos[i].scene = scene;
return;
}
}
if (slotFound !== -1) {
cameraGizmos[slotFound].scene = scene;
cameraGizmos[slotFound].targetNode = obj;
cameraGizmos[slotFound].locked = _generalHelper.isLocked(obj);
cameraGizmos[slotFound].hidden = _generalHelper.isHidden(obj);
_generalHelper.registerGizmoTarget(obj);
return;
}
// No free gizmos available, create a new one
var gizmoComponent = Qt.createComponent("CameraGizmo.qml");
var frustumComponent = Qt.createComponent("CameraFrustum.qml");
if (gizmoComponent.status === Component.Ready && frustumComponent.status === Component.Ready) {
_generalHelper.registerGizmoTarget(obj);
var geometryName = _generalHelper.generateUniqueName("CameraGeometry");
var frustum = frustumComponent.createObject(
overlayScene,
{"geometryName": geometryName, "viewPortRect": viewPortRect});
var gizmo = gizmoComponent.createObject(
overlayView,
{"view3D": overlayView, "targetNode": obj,
"selectedNodes": selectedNodes, "scene": scene, "activeScene": activeScene,
"locked": _generalHelper.isLocked(obj), "hidden": _generalHelper.isHidden(obj)});
cameraGizmos[cameraGizmos.length] = gizmo;
gizmo.clicked.connect(handleObjectClicked);
gizmo.selectedNodes = Qt.binding(function() {return selectedNodes;});
gizmo.activeScene = Qt.binding(function() {return activeScene;});
frustum.viewPortRect = Qt.binding(function() {return viewPortRect;});
gizmo.connectFrustum(frustum);
}
}
function releaseLightGizmo(obj)
{
for (var i = 0; i < lightIconGizmos.length; ++i) {
if (lightIconGizmos[i].targetNode === obj) {
lightIconGizmos[i].scene = null;
lightIconGizmos[i].targetNode = null;
_generalHelper.unregisterGizmoTarget(obj);
return;
}
}
}
function releaseCameraGizmo(obj)
{
for (var i = 0; i < cameraGizmos.length; ++i) {
if (cameraGizmos[i].targetNode === obj) {
cameraGizmos[i].scene = null;
cameraGizmos[i].targetNode = null;
_generalHelper.unregisterGizmoTarget(obj);
return;
}
}
}
function updateLightGizmoScene(scene, obj)
{
for (var i = 0; i < lightIconGizmos.length; ++i) {
if (lightIconGizmos[i].targetNode === obj) {
lightIconGizmos[i].scene = scene;
return;
}
}
}
function updateCameraGizmoScene(scene, obj)
{
for (var i = 0; i < cameraGizmos.length; ++i) {
if (cameraGizmos[i].targetNode === obj) {
cameraGizmos[i].scene = scene;
return;
}
}
}
Component.onCompleted: {
createEditView();
selectObjects([]);
// Work-around the fact that the projection matrix for the camera is not calculated until
// the first frame is rendered, so any initial calls to mapFrom3DScene() will fail.
_generalHelper.requestOverlayUpdate();
}
onWidthChanged: _generalHelper.requestOverlayUpdate()
onHeightChanged: _generalHelper.requestOverlayUpdate()
Connections {
target: _generalHelper
function onLockedStateChanged(node)
{
for (var i = 0; i < cameraGizmos.length; ++i) {
if (cameraGizmos[i].targetNode === node) {
cameraGizmos[i].locked = _generalHelper.isLocked(node);
return;
}
}
for (var i = 0; i < lightIconGizmos.length; ++i) {
if (lightIconGizmos[i].targetNode === node) {
lightIconGizmos[i].locked = _generalHelper.isLocked(node);
return;
}
}
}
function onHiddenStateChanged(node)
{
for (var i = 0; i < cameraGizmos.length; ++i) {
if (cameraGizmos[i].targetNode === node) {
cameraGizmos[i].hidden = _generalHelper.isHidden(node);
return;
}
}
for (var i = 0; i < lightIconGizmos.length; ++i) {
if (lightIconGizmos[i].targetNode === node) {
lightIconGizmos[i].hidden = _generalHelper.isHidden(node);
return;
}
}
}
}
Node {
id: overlayScene
PerspectiveCamera {
id: overlayPerspectiveCamera
clipFar: viewRoot.editView ? viewRoot.editView.perspectiveCamera.clipFar : 1000
clipNear: viewRoot.editView ? viewRoot.editView.perspectiveCamera.clipNear : 1
position: viewRoot.editView ? viewRoot.editView.perspectiveCamera.position : Qt.vector3d(0, 0, 0)
rotation: viewRoot.editView ? viewRoot.editView.perspectiveCamera.rotation : Qt.quaternion(1, 0, 0, 0)
}
OrthographicCamera {
id: overlayOrthoCamera
clipFar: viewRoot.editView ? viewRoot.editView.orthoCamera.clipFar : 1000
clipNear: viewRoot.editView ? viewRoot.editView.orthoCamera.clipNear : 1
position: viewRoot.editView ? viewRoot.editView.orthoCamera.position : Qt.vector3d(0, 0, 0)
rotation: viewRoot.editView ? viewRoot.editView.orthoCamera.rotation : Qt.quaternion(1, 0, 0, 0)
scale: viewRoot.editView ? viewRoot.editView.orthoCamera.scale : Qt.vector3d(0, 0, 0)
}
MouseArea3D {
id: gizmoDragHelper
view3D: overlayView
}
Node {
id: multiSelectionNode
objectName: "multiSelectionNode"
}
MoveGizmo {
id: moveGizmo
scale: autoScale.getScale(Qt.vector3d(5, 5, 5))
highlightOnHover: true
targetNode: viewRoot.selectedNode
globalOrientation: viewRoot.globalOrientation
visible: viewRoot.selectedNode && transformMode === EditView3D.TransformMode.Move
view3D: overlayView
dragHelper: gizmoDragHelper
property var propertyNames: ["position"]
onPositionCommit: {
if (targetNode == multiSelectionNode)
viewRoot.commitObjectProperty(_generalHelper.multiSelectionTargets(), propertyNames);
else
viewRoot.commitObjectProperty([viewRoot.selectedNode], propertyNames);
}
onPositionMove: {
if (targetNode == multiSelectionNode)
viewRoot.changeObjectProperty(_generalHelper.multiSelectionTargets(), propertyNames);
else
viewRoot.changeObjectProperty([viewRoot.selectedNode], propertyNames);
}
}
ScaleGizmo {
id: scaleGizmo
scale: autoScale.getScale(Qt.vector3d(5, 5, 5))
highlightOnHover: true
targetNode: viewRoot.selectedNode
visible: viewRoot.selectedNode && transformMode === EditView3D.TransformMode.Scale
view3D: overlayView
dragHelper: gizmoDragHelper
property var propertyNames: ["scale"]
property var propertyNamesMulti: ["position", "scale"]
onScaleCommit: {
if (targetNode == multiSelectionNode)
viewRoot.commitObjectProperty(_generalHelper.multiSelectionTargets(), propertyNamesMulti);
else
viewRoot.commitObjectProperty([viewRoot.selectedNode], propertyNames);
}
onScaleChange: {
if (targetNode == multiSelectionNode)
viewRoot.changeObjectProperty(_generalHelper.multiSelectionTargets(), propertyNamesMulti);
else
viewRoot.changeObjectProperty([viewRoot.selectedNode], propertyNames);
}
}
RotateGizmo {
id: rotateGizmo
scale: autoScale.getScale(Qt.vector3d(7, 7, 7))
highlightOnHover: true
targetNode: viewRoot.selectedNode
globalOrientation: viewRoot.globalOrientation
visible: viewRoot.selectedNode && transformMode === EditView3D.TransformMode.Rotate
view3D: overlayView
dragHelper: gizmoDragHelper
property var propertyNames: ["eulerRotation"]
property var propertyNamesMulti: ["position", "eulerRotation"]
onRotateCommit: {
if (targetNode == multiSelectionNode)
viewRoot.commitObjectProperty(_generalHelper.multiSelectionTargets(), propertyNamesMulti);
else
viewRoot.commitObjectProperty([viewRoot.selectedNode], propertyNames);
}
onRotateChange: {
if (targetNode == multiSelectionNode)
viewRoot.changeObjectProperty(_generalHelper.multiSelectionTargets(), propertyNamesMulti);
else
viewRoot.changeObjectProperty([viewRoot.selectedNode], propertyNames);
}
}
LightGizmo {
id: lightGizmo
targetNode: viewRoot.selectedNode != multiSelectionNode ? viewRoot.selectedNode : null
view3D: overlayView
dragHelper: gizmoDragHelper
onPropertyValueCommit: (propName)=> {
viewRoot.commitObjectProperty([targetNode], [propName]);
}
onPropertyValueChange: (propName)=> {
viewRoot.changeObjectProperty([targetNode], [propName]);
}
}
AutoScaleHelper {
id: autoScale
view3D: overlayView
position: moveGizmo.scenePosition
}
AutoScaleHelper {
id: pivotAutoScale
view3D: overlayView
position: pivotLine.startPos
}
Line3D {
id: pivotLine
visible: viewRoot.selectedNode && viewRoot.selectedNode != multiSelectionNode
name: "3D Edit View Pivot Line"
color: "#ddd600"
startPos: viewRoot.selectedNode ? viewRoot.selectedNode.scenePosition
: Qt.vector3d(0, 0, 0)
Connections {
target: viewRoot
function onSelectedNodeChanged()
{
pivotLine.endPos = gizmoDragHelper.pivotScenePosition(viewRoot.selectedNode);
}
}
Connections {
target: viewRoot.selectedNode
function onSceneTransformChanged()
{
pivotLine.endPos = gizmoDragHelper.pivotScenePosition(viewRoot.selectedNode);
}
}
Model {
id: pivotCap
source: "#Sphere"
scale: pivotAutoScale.getScale(Qt.vector3d(0.03, 0.03, 0.03))
position: pivotLine.startPos
materials: [
DefaultMaterial {
id: lineMat
lighting: DefaultMaterial.NoLighting
cullMode: Material.NoCulling
diffuseColor: pivotLine.color
}
]
}
}
}
Item {
id: contentItem
anchors.fill: parent
Rectangle {
id: viewRect
anchors.fill: parent
gradient: Gradient {
GradientStop { position: 1.0; color: "#222222" }
GradientStop { position: 0.0; color: "#999999" }
}
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.LeftButton
hoverEnabled: false
property MouseArea3D freeDraggerArea
property point pressPoint
property bool initialMoveBlock: false
onPressed: (mouse)=> {
if (viewRoot.editView) {
var pickResult = viewRoot.editView.pick(mouse.x, mouse.y);
handleObjectClicked(_generalHelper.resolvePick(pickResult.objectHit),
mouse.modifiers & Qt.ControlModifier);
if (pickResult.objectHit) {
if (transformMode === EditView3D.TransformMode.Move)
freeDraggerArea = moveGizmo.freeDraggerArea;
else if (transformMode === EditView3D.TransformMode.Rotate)
freeDraggerArea = rotateGizmo.freeDraggerArea;
else if (transformMode === EditView3D.TransformMode.Scale)
freeDraggerArea = scaleGizmo.freeDraggerArea;
pressPoint.x = mouse.x;
pressPoint.y = mouse.y;
initialMoveBlock = true;
} else {
mouse.accepted = false;
}
}
}
onPositionChanged: (mouse)=> {
if (freeDraggerArea) {
if (initialMoveBlock && Math.abs(pressPoint.x - mouse.x) + Math.abs(pressPoint.y - mouse.y) > 10) {
// Don't force press event at actual press, as that puts the gizmo
// in free-dragging state, which is bad UX if drag is not actually done
freeDraggerArea.forcePressEvent(pressPoint.x, pressPoint.y);
freeDraggerArea.forceMoveEvent(mouse.x, mouse.y);
initialMoveBlock = false;
} else {
freeDraggerArea.forceMoveEvent(mouse.x, mouse.y);
}
}
}
function handleRelease(mouse)
{
if (freeDraggerArea) {
if (initialMoveBlock)
freeDraggerArea.forceReleaseEvent(pressPoint.x, pressPoint.y);
else
freeDraggerArea.forceReleaseEvent(mouse.x, mouse.y);
freeDraggerArea = null;
}
}
onReleased: (mouse)=> {
handleRelease(mouse);
}
onCanceled: (mouse)=> {
handleRelease(mouse);
}
}
DropArea {
anchors.fill: parent
}
View3D {
id: overlayView
anchors.fill: parent
camera: viewRoot.usePerspective ? overlayPerspectiveCamera : overlayOrthoCamera
importScene: overlayScene
z: 2
}
Overlay2D {
id: gizmoLabel
targetNode: moveGizmo.visible ? moveGizmo : scaleGizmo
targetView: overlayView
visible: targetNode.dragging
z: 3
Rectangle {
color: "white"
x: -width / 2
y: -height - 8
width: gizmoLabelText.width + 4
height: gizmoLabelText.height + 4
border.width: 1
Text {
id: gizmoLabelText
text: {
// This is skipped during application shutdown, as calling QQuickText::setText()
// during application shutdown can crash the application.
if (shuttingDown)
return text;
var l = Qt.locale();
var targetProperty;
if (viewRoot.selectedNode) {
if (gizmoLabel.targetNode === moveGizmo)
targetProperty = viewRoot.selectedNode.position;
else
targetProperty = viewRoot.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
}
}
}
Rectangle {
id: rotateGizmoLabel
color: "white"
x: rotateGizmo.currentMousePos.x - (10 + width)
y: rotateGizmo.currentMousePos.y - (10 + height)
width: rotateGizmoLabelText.width + 4
height: rotateGizmoLabelText.height + 4
border.width: 1
visible: rotateGizmo.dragging
parent: rotateGizmo.view3D
z: 3
Text {
id: rotateGizmoLabelText
text: {
// This is skipped during application shutdown, as calling QQuickText::setText()
// during application shutdown can crash the application.
if (shuttingDown)
return text;
var l = Qt.locale();
if (rotateGizmo.targetNode) {
var degrees = rotateGizmo.currentAngle * (180 / Math.PI);
return Number(degrees).toLocaleString(l, 'f', 1);
} else {
return "";
}
}
anchors.centerIn: parent
}
}
Rectangle {
id: lightGizmoLabel
color: "white"
x: lightGizmo.currentMousePos.x - (10 + width)
y: lightGizmo.currentMousePos.y - (10 + height)
width: lightGizmoLabelText.width + 4
height: lightGizmoLabelText.height + 4
border.width: 1
visible: lightGizmo.dragging
parent: lightGizmo.view3D
z: 3
Text {
id: lightGizmoLabelText
text: lightGizmo.currentLabel
anchors.centerIn: parent
}
}
EditCameraController {
id: cameraControl
camera: viewRoot.editView ? viewRoot.editView.camera : null
anchors.fill: parent
view3d: viewRoot.editView
sceneId: viewRoot.sceneId
}
}
AxisHelper {
anchors.right: parent.right
anchors.top: parent.top
width: 100
height: width
editCameraCtrl: cameraControl
selectedNode : viewRoot.selectedNodes.length ? selectionBoxes[0].model : null
}
Text {
id: sceneLabel
text: viewRoot.sceneId
anchors.top: parent.top
anchors.left: parent.left
anchors.margins: 4
font.pixelSize: 14
color: "white"
}
Text {
id: fpsLabel
text: viewRoot.fps
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.margins: 4
font.pixelSize: 12
color: "white"
visible: viewRoot.fps > 0
}
}
}
@@ -0,0 +1,128 @@
/****************************************************************************
**
** Copyright (C) 2020 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 6.0
import QtQuick3D 6.0
DirectionalDraggable {
id: handleRoot
property string currentLabel
property point currentMousePos
property real fadeScale
property real baseScale: 5
property real dragScale: 1
scale: autoScaler.getScale(Qt.vector3d(baseScale, baseScale, baseScale))
length: 3
offset: -1.5
Model {
id: handle
source: "#Sphere"
materials: [ handleRoot.material ]
scale: Qt.vector3d(0.02, 0.02, 0.02)
}
AutoScaleHelper {
id: autoScaler
active: handleRoot.active
view3D: handleRoot.view3D
}
property real _q // quadratic fade
property real _l // linear fade
property real _c // constant fade
property real _d: 20 // Divisor from fadeScale calc in lightGizmo
property real _startScale
property real _startFadeScale
property string _currentProp
signal valueCommit(string propName)
signal valueChange(string propName)
function updateFade(relativeDistance, screenPos)
{
// Solved from fadeScale equation in LightGizmo
var newValue = 0;
var _x = Math.max(0, (_startFadeScale - (relativeDistance * _startScale)) / 100);
// Fades capped to range 0-10 because property editor caps them to that range
if (_currentProp === "quadraticFade") {
if (_x === 0)
newValue = 10;
else
newValue = Math.max(0, Math.min(10, -(_c - _d + (_l * _x)) / (_x * _x)));
if (newValue < 0.01)
newValue = 0; // To avoid having tiny positive value when UI shows 0.00
targetNode.quadraticFade = newValue;
} else if (_currentProp === "linearFade") {
if (_x === 0)
newValue = 10;
else
newValue = Math.max(0, Math.min(10, -(_c - _d) / _x));
if (newValue < 0.01)
newValue = 0; // To avoid having tiny positive value when UI shows 0.00
targetNode.linearFade = newValue;
} else {
// Since pure constant fade equates to infinitely long cone, fadeScale calc assumes
// linear fade of one in this case.
newValue = Math.max(0, Math.min(10, _d - _x));
targetNode.constantFade = newValue;
}
var l = Qt.locale();
handleRoot.currentLabel = _currentProp + qsTr(": ") + Number(newValue).toLocaleString(l, 'f', 2);
handleRoot.currentMousePos = screenPos;
}
onPressed: (mouseArea, screenPos)=> {
_startScale = autoScaler.relativeScale * baseScale * dragScale;
_startFadeScale = fadeScale;
_l = targetNode.linearFade;
_c = targetNode.constantFade;
_q = targetNode.quadraticFade;
if (targetNode.quadraticFade === 0) {
if (targetNode.linearFade === 0) {
_currentProp = "constantFade";
} else {
_currentProp = "linearFade";
}
} else {
_currentProp = "quadraticFade";
}
updateFade(0, screenPos);
}
onDragged: (mouseArea, sceneRelativeDistance, relativeDistance, screenPos)=> {
updateFade(relativeDistance, screenPos);
handleRoot.valueChange(_currentProp);
}
onReleased: (mouseArea, sceneRelativeDistance, relativeDistance, screenPos)=> {
updateFade(relativeDistance, screenPos);
handleRoot.valueCommit(_currentProp);
}
}
@@ -0,0 +1,108 @@
/****************************************************************************
**
** 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 6.0
import QtQuick3D 6.0
import GridGeometry 1.0
Node {
id: grid
property alias lines: gridGeometry.lines
property alias step: gridGeometry.step
property alias subdivAlpha: subGridMaterial.opacity
eulerRotation.x: 90
// Note: Only one instance of HelperGrid is supported, as the geometry names are fixed
Model { // Main grid lines
geometry: GridGeometry {
id: gridGeometry
name: "3D Edit View Helper Grid"
}
materials: [
DefaultMaterial {
id: mainGridMaterial
diffuseColor: "#aaaaaa"
lighting: DefaultMaterial.NoLighting
cullMode: Material.NoCulling
}
]
}
Model { // Subdivision lines
geometry: GridGeometry {
lines: gridGeometry.lines
step: gridGeometry.step
isSubdivision: true
name: "3D Edit View Helper Grid subdivisions"
}
materials: [
DefaultMaterial {
id: subGridMaterial
diffuseColor: mainGridMaterial.diffuseColor
lighting: DefaultMaterial.NoLighting
cullMode: Material.NoCulling
}
]
}
Model { // Z Axis
geometry: GridGeometry {
lines: gridGeometry.lines
step: gridGeometry.step
isCenterLine: true
name: "3D Edit View Helper Grid Z Axis"
}
materials: [
DefaultMaterial {
id: vCenterLineMaterial
diffuseColor: "#00a1d2"
lighting: DefaultMaterial.NoLighting
cullMode: Material.NoCulling
}
]
}
Model { // X Axis
eulerRotation.z: 90
geometry: GridGeometry {
lines: gridGeometry.lines
step: gridGeometry.step
isCenterLine: true
name: "3D Edit View Helper Grid X Axis"
}
materials: [
DefaultMaterial {
id: hCenterLineMaterial
diffuseColor: "#cb211a"
lighting: DefaultMaterial.NoLighting
cullMode: Material.NoCulling
}
]
}
}
@@ -0,0 +1,121 @@
/****************************************************************************
**
** 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 6.0
import QtQuick3D 6.0
Item {
id: iconGizmo
property Node activeScene: null
property Node scene: null
property View3D view3D
property bool highlightOnHover: true
property Node targetNode: null
property var selectedNodes: []
readonly property bool selected: {
for (var i = 0; i < selectedNodes.length; ++i) {
if (selectedNodes[i] === targetNode)
return true;
}
return false;
}
property bool hasMouse: false
property bool hidden: false
property bool locked: false
property alias iconSource: iconImage.source
signal clicked(Node node, bool multi)
onSelectedChanged: {
if (selected)
hasMouse = false;
}
visible: activeScene === scene && !hidden && (targetNode ? targetNode.visible : false)
Overlay2D {
id: iconOverlay
targetNode: iconGizmo.targetNode
targetView: view3D
visible: iconGizmo.visible && !isBehindCamera
Rectangle {
id: iconRect
width: iconImage.width
height: iconImage.height
x: -width / 2
y: -height / 2
color: "transparent"
border.color: "#7777ff"
border.width: !iconGizmo.locked && iconGizmo.highlightOnHover && iconGizmo.hasMouse ? 2 : 0
radius: 5
opacity: iconGizmo.selected ? 0.2 : 1
Image {
id: iconImage
fillMode: Image.Pad
MouseArea {
id: iconMouseArea
anchors.fill: parent
onPressed: (mouse)=> {
// Ignore singleselection mouse presses when we have single object selected
// so that the icon gizmo doesn't hijack mouse clicks meant for other gizmos
if (iconGizmo.selected && !(mouse.modifiers & Qt.ControlModifier)
&& selectedNodes.length === 1) {
mouse.accepted = false;
}
}
onClicked: (mouse)=> {
iconGizmo.clicked(iconGizmo.targetNode,
mouse.modifiers & Qt.ControlModifier);
}
hoverEnabled: iconGizmo.highlightOnHover && !iconGizmo.selected
acceptedButtons: Qt.LeftButton
// onPositionChanged, onContainsMouseAreaChanged, and hasMouse are used instead
// of just using containsMouse directly, because containsMouse
// cannot be relied upon to update correctly in some situations.
// This is likely because the overlapping 3D mouse areas of the gizmos get
// the mouse events instead of this area, so mouse leaving the area
// doesn't always update containsMouse property.
onPositionChanged: {
if (!iconGizmo.selected)
iconGizmo.hasMouse = containsMouse;
}
onContainsMouseChanged: {
if (!iconGizmo.selected)
iconGizmo.hasMouse = containsMouse;
else
iconGizmo.hasMouse = false;
}
}
}
}
}
}
@@ -0,0 +1,88 @@
/****************************************************************************
**
** Copyright (C) 2020 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 6.0
import QtQuick3D 6.0
Item {
id: viewRoot
width: 1024
height: 1024
visible: true
property alias view3D: view3D
property alias camPos: viewCamera.position
function setSceneToBox()
{
selectionBox.targetNode = view3D.importScene;
}
function fitAndHideBox()
{
cameraControl.focusObject(selectionBox.model, viewCamera.eulerRotation, true, true);
if (cameraControl._zoomFactor < 0.1)
view3D.importScene.scale = view3D.importScene.scale.times(10);
if (cameraControl._zoomFactor > 10)
view3D.importScene.scale = view3D.importScene.scale.times(0.1);
selectionBox.visible = false;
}
View3D {
id: view3D
camera: viewCamera
environment: sceneEnv
SceneEnvironment {
id: sceneEnv
antialiasingMode: SceneEnvironment.MSAA
antialiasingQuality: SceneEnvironment.VeryHigh
}
PerspectiveCamera {
id: viewCamera
position: Qt.vector3d(-200, 200, 200)
eulerRotation: Qt.vector3d(-45, -45, 0)
}
DirectionalLight {
rotation: viewCamera.rotation
}
SelectionBox {
id: selectionBox
view3D: view3D
geometryName: "SB"
}
EditCameraController {
id: cameraControl
camera: view3D.camera
view3d: view3D
ignoreToolState: true
}
}
}
@@ -0,0 +1,356 @@
/****************************************************************************
**
** Copyright (C) 2020 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 6.0
import QtQuick3D 6.0
import MouseArea3D 1.0
import LightUtils 1.0
Node {
id: lightGizmo
property View3D view3D
property Node targetNode: null
property MouseArea3D dragHelper: null
property color color: Qt.rgba(1, 1, 0, 1)
property real fadeScale: {
// Value indicates area where intensity is above certain percent of total brightness.
if (lightGizmo.targetNode instanceof SpotLight || lightGizmo.targetNode instanceof PointLight) {
var l = targetNode.linearFade;
var q = targetNode.quadraticFade;
var c = targetNode.constantFade;
var d = 20; // divisor to target intensity value. E.g. 20 = 1/20 = 5%
if (l === 0 && q === 0)
l = 1; // For pure constant fade, cone would be infinite, so pretend we have linear fade
// Solved from equation in shader:
// 1 / d = 1 / (c + (l + q * dist) * dist);
if (q === 0)
return 100 * Math.max(((d - c) / l), 1);
else
return 100 * ((Math.sqrt(4 * q * (d - c) + (l * l)) - l) / (2 * q));
} else {
return 100;
}
}
readonly property bool dragging: primaryArrow.dragging
|| spotLightHandle.dragging
|| spotLightInnerHandle.dragging
|| spotLightFadeHandle.dragging
|| areaHeightHandle.dragging
|| areaWidthHandle.dragging
|| pointLightFadeHandle.dragging
property point currentMousePos
property string currentLabel
property int brightnessDecimals: _generalHelper.brightnessScaler() > 10. ? 0 : 2;
property real brightnessMultiplier: Math.pow(10, brightnessDecimals);
signal propertyValueCommit(string propName)
signal propertyValueChange(string propName)
position: targetNode ? targetNode.scenePosition : Qt.vector3d(0, 0, 0)
visible: lightGizmo.targetNode instanceof SpotLight
|| lightGizmo.targetNode instanceof AreaLight
|| lightGizmo.targetNode instanceof DirectionalLight
|| lightGizmo.targetNode instanceof PointLight
AutoScaleHelper {
id: autoScaler
view3D: lightGizmo.view3D
}
Node {
id: pointLightParts
rotation: lightGizmo.view3D.camera.rotation
visible: lightGizmo.targetNode instanceof PointLight
LightModel {
id: pointModel
geometryName: "Edit 3D PointLight"
geometryType: LightGeometry.Point
material: lightMaterial
scale: Qt.vector3d(lightGizmo.fadeScale, lightGizmo.fadeScale, lightGizmo.fadeScale)
}
FadeHandle {
id: pointLightFadeHandle
view3D: lightGizmo.view3D
color: (hovering || dragging) ? Qt.rgba(1, 1, 1, 1) : lightGizmo.color
position: lightGizmo.targetNode instanceof PointLight ? Qt.vector3d(-pointModel.scale.x, 0, 0)
: Qt.vector3d(0, 0, 0)
eulerRotation: Qt.vector3d(0, 0, -90)
targetNode: lightGizmo.targetNode instanceof PointLight ? lightGizmo.targetNode : null
active: lightGizmo.targetNode instanceof PointLight
dragHelper: lightGizmo.dragHelper
fadeScale: lightGizmo.fadeScale
onCurrentMousePosChanged: {
lightGizmo.currentMousePos = currentMousePos;
lightGizmo.currentLabel = currentLabel;
}
onValueChange: (propName)=> {
lightGizmo.propertyValueChange(propName);
}
onValueCommit: (propName)=> {
lightGizmo.propertyValueCommit(propName);
}
}
}
Node {
rotation: !lightGizmo.targetNode ? Qt.quaternion(1, 0, 0, 0)
: lightGizmo.targetNode.sceneRotation
Node {
id: spotParts
visible: lightGizmo.targetNode instanceof SpotLight
LightModel {
id: spotModel
property real coneXYScale: spotParts.visible && lightGizmo.targetNode
? lightGizmo.fadeScale * Math.tan(Math.PI * lightGizmo.targetNode.coneAngle / 180)
: 1
geometryName: "Edit 3D SpotLight Cone"
geometryType: LightGeometry.Spot
material: lightMaterial
scale: Qt.vector3d(coneXYScale, coneXYScale,
spotParts.visible && lightGizmo.targetNode && lightGizmo.targetNode.coneAngle > 90
? -lightGizmo.fadeScale : lightGizmo.fadeScale)
}
LightModel {
id: spotInnerModel
property real coneXYScale: spotParts.visible && lightGizmo.targetNode
? lightGizmo.fadeScale * Math.tan(Math.PI * lightGizmo.targetNode.innerConeAngle / 180)
: 1
geometryName: "Edit 3D SpotLight Inner Cone"
geometryType: LightGeometry.Spot
material: lightMaterial
scale: Qt.vector3d(coneXYScale, coneXYScale,
spotParts.visible && lightGizmo.targetNode && lightGizmo.targetNode.innerConeAngle > 90
? -lightGizmo.fadeScale : lightGizmo.fadeScale)
}
SpotLightHandle {
id: spotLightHandle
view3D: lightGizmo.view3D
color: (hovering || dragging) ? Qt.rgba(1, 1, 1, 1) : lightGizmo.color
position: lightGizmo.targetNode instanceof SpotLight ? Qt.vector3d(0, spotModel.scale.y, -spotModel.scale.z)
: Qt.vector3d(0, 0, 0)
targetNode: lightGizmo.targetNode instanceof SpotLight ? lightGizmo.targetNode : null
active: lightGizmo.targetNode instanceof SpotLight
dragHelper: lightGizmo.dragHelper
propName: "coneAngle"
propValue: lightGizmo.targetNode instanceof SpotLight ? targetNode.coneAngle : 0
onNewValueChanged: targetNode.coneAngle = newValue
onCurrentMousePosChanged: {
lightGizmo.currentMousePos = currentMousePos;
lightGizmo.currentLabel = currentLabel;
}
onValueChange: lightGizmo.propertyValueChange(propName)
onValueCommit: {
if (targetNode.innerConeAngle > targetNode.coneAngle)
targetNode.innerConeAngle = targetNode.coneAngle;
lightGizmo.propertyValueCommit(propName)
lightGizmo.propertyValueCommit(spotLightInnerHandle.propName);
}
}
SpotLightHandle {
id: spotLightInnerHandle
view3D: lightGizmo.view3D
color: (hovering || dragging) ? Qt.rgba(1, 1, 1, 1) : lightGizmo.color
position: lightGizmo.targetNode instanceof SpotLight ? Qt.vector3d(0, -spotInnerModel.scale.y, -spotInnerModel.scale.z)
: Qt.vector3d(0, 0, 0)
eulerRotation: Qt.vector3d(180, 0, 0)
targetNode: lightGizmo.targetNode instanceof SpotLight ? lightGizmo.targetNode : null
active: lightGizmo.targetNode instanceof SpotLight
dragHelper: lightGizmo.dragHelper
propName: "innerConeAngle"
propValue: lightGizmo.targetNode instanceof SpotLight ? targetNode.innerConeAngle : 0
onNewValueChanged: targetNode.innerConeAngle = newValue
onCurrentMousePosChanged: {
lightGizmo.currentMousePos = currentMousePos;
lightGizmo.currentLabel = currentLabel;
}
onValueChange: lightGizmo.propertyValueChange(propName)
onValueCommit: {
if (targetNode.coneAngle < targetNode.innerConeAngle)
targetNode.coneAngle = targetNode.innerConeAngle;
lightGizmo.propertyValueCommit(propName)
lightGizmo.propertyValueCommit(spotLightHandle.propName);
}
}
FadeHandle {
id: spotLightFadeHandle
view3D: lightGizmo.view3D
color: (hovering || dragging) ? Qt.rgba(1, 1, 1, 1) : lightGizmo.color
position: lightGizmo.targetNode instanceof SpotLight ? Qt.vector3d(spotModel.scale.x / 2, 0, -spotInnerModel.scale.z / 2)
: Qt.vector3d(0, 0, 0)
eulerRotation: Qt.vector3d(90, 0, 0)
targetNode: lightGizmo.targetNode instanceof SpotLight ? lightGizmo.targetNode : null
active: lightGizmo.targetNode instanceof SpotLight
dragHelper: lightGizmo.dragHelper
fadeScale: lightGizmo.fadeScale
dragScale: 2
onCurrentMousePosChanged: {
lightGizmo.currentMousePos = currentMousePos;
lightGizmo.currentLabel = currentLabel;
}
onValueChange: (propName)=> {
lightGizmo.propertyValueChange(propName);
}
onValueCommit: (propName)=> {
lightGizmo.propertyValueCommit(propName);
}
}
}
Node {
id: areaParts
visible: lightGizmo.targetNode instanceof AreaLight
LightModel {
id: areaModel
geometryName: "Edit 3D AreaLight"
geometryType: LightGeometry.Area
material: lightMaterial
scale: areaParts.visible ? Qt.vector3d(lightGizmo.targetNode.width / 2,
lightGizmo.targetNode.height / 2, 1)
.times(lightGizmo.targetNode.scale)
: Qt.vector3d(1, 1, 1)
}
AreaLightHandle {
id: areaWidthHandle
view3D: lightGizmo.view3D
color: (hovering || dragging) ? Qt.rgba(1, 1, 1, 1) : lightGizmo.color
position: lightGizmo.targetNode instanceof AreaLight ? Qt.vector3d(-areaModel.scale.x, 0, 0)
: Qt.vector3d(0, 0, 0)
eulerRotation: Qt.vector3d(0, 0, 90)
targetNode: lightGizmo.targetNode instanceof AreaLight ? lightGizmo.targetNode : null
active: lightGizmo.targetNode instanceof AreaLight
dragHelper: lightGizmo.dragHelper
propName: "width"
propValue: lightGizmo.targetNode instanceof AreaLight ? targetNode.width : 0
onNewValueChanged: targetNode.width = newValue
onCurrentMousePosChanged: {
lightGizmo.currentMousePos = currentMousePos;
lightGizmo.currentLabel = currentLabel;
}
onValueChange: lightGizmo.propertyValueChange(propName)
onValueCommit: lightGizmo.propertyValueCommit(propName)
}
AreaLightHandle {
id: areaHeightHandle
view3D: lightGizmo.view3D
color: (hovering || dragging) ? Qt.rgba(1, 1, 1, 1) : lightGizmo.color
position: lightGizmo.targetNode instanceof AreaLight ? Qt.vector3d(0, -areaModel.scale.y, 0)
: Qt.vector3d(0, 0, 0)
eulerRotation: Qt.vector3d(0, 0, 180)
targetNode: lightGizmo.targetNode instanceof AreaLight ? lightGizmo.targetNode : null
active: lightGizmo.targetNode instanceof AreaLight
dragHelper: lightGizmo.dragHelper
propName: "height"
propValue: lightGizmo.targetNode instanceof AreaLight ? targetNode.height : 0
onNewValueChanged: targetNode.height = newValue
onCurrentMousePosChanged: {
lightGizmo.currentMousePos = currentMousePos;
lightGizmo.currentLabel = currentLabel;
}
onValueChange: lightGizmo.propertyValueChange(propName)
onValueCommit: lightGizmo.propertyValueCommit(propName)
}
}
LightModel {
id: directionalModel
geometryName: "Edit 3D DirLight"
geometryType: LightGeometry.Directional
material: lightMaterial
visible: lightGizmo.targetNode instanceof DirectionalLight
scale: autoScaler.getScale(Qt.vector3d(50, 50, 50))
}
AdjustableArrow {
id: primaryArrow
eulerRotation: Qt.vector3d(-90, 0, 0)
targetNode: lightGizmo.targetNode
color: (hovering || dragging) ? Qt.rgba(1, 1, 1, 1) : lightGizmo.color
view3D: lightGizmo.view3D
active: lightGizmo.visible
dragHelper: lightGizmo.dragHelper
scale: autoScaler.getScale(Qt.vector3d(5, 5, 5))
length: targetNode ? Math.max(1.0, 1.0 + targetNode.brightness / _generalHelper.brightnessScaler() * 10.0) + 3 : 10
property real _startBrightness
function updateBrightness(relativeDistance, screenPos)
{
var currentValue = Math.max(0, (_startBrightness + relativeDistance * _generalHelper.brightnessScaler() / 10.0));
currentValue *= brightnessMultiplier;
currentValue = Math.round(currentValue);
currentValue /= brightnessMultiplier;
var l = Qt.locale();
lightGizmo.currentLabel = "brightness" + qsTr(": ") + Number(currentValue).toLocaleString(l, 'f', brightnessDecimals);
lightGizmo.currentMousePos = screenPos;
targetNode.brightness = currentValue;
}
onPressed: (mouseArea, screenPos)=> {
_startBrightness = targetNode.brightness;
updateBrightness(0, screenPos);
}
onDragged: (mouseArea, sceneRelativeDistance, relativeDistance, screenPos)=> {
updateBrightness(relativeDistance, screenPos);
lightGizmo.propertyValueChange("brightness");
}
onReleased: (mouseArea, sceneRelativeDistance, relativeDistance, screenPos)=> {
updateBrightness(relativeDistance, screenPos);
lightGizmo.propertyValueCommit("brightness");
}
}
DefaultMaterial {
id: lightMaterial
diffuseColor: lightGizmo.color
lighting: DefaultMaterial.NoLighting
cullMode: Material.NoCulling
}
}
}
@@ -0,0 +1,44 @@
/****************************************************************************
**
** Copyright (C) 2020 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 6.0
import QtQuick3D 6.0
import LightUtils 1.0
IconGizmo {
id: lightIconGizmo
property color overlayColor: targetNode ? targetNode.color : "transparent"
iconSource: targetNode
? targetNode instanceof DirectionalLight
? "image://IconGizmoImageProvider/directional.png:" + overlayColor
: targetNode instanceof AreaLight
? "image://IconGizmoImageProvider/area.png:" + overlayColor
: targetNode instanceof PointLight
? "image://IconGizmoImageProvider/point.png:" + overlayColor
: "image://IconGizmoImageProvider/spot.png:" + overlayColor
: "image://IconGizmoImageProvider/point.png:" + overlayColor
}
@@ -0,0 +1,50 @@
/****************************************************************************
**
** Copyright (C) 2020 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 6.0
import QtQuick3D 6.0
import LightUtils 1.0
Model {
id: lightModel
property alias geometryName: lightGeometry.name // Name must be unique for each geometry
property alias geometryType: lightGeometry.lightType
property Material material
function updateGeometry()
{
lightGeometry.update();
}
scale: Qt.vector3d(50, 50, 50)
geometry: lightGeometry
materials: [ material ]
LightGeometry {
id: lightGeometry
}
}
@@ -0,0 +1,50 @@
/****************************************************************************
**
** Copyright (C) 2020 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 6.0
import QtQuick3D 6.0
import LineGeometry 1.0
Node {
id: pivotLine
property alias startPos: lineGeometry.startPos
property alias endPos: lineGeometry.endPos
property alias name: lineGeometry.name // Name must be unique for each line
property alias color: lineMat.diffuseColor
Model {
geometry: LineGeometry {
id: lineGeometry
}
materials: [
DefaultMaterial {
id: lineMat
lighting: DefaultMaterial.NoLighting
cullMode: Material.NoCulling
}
]
}
}
@@ -0,0 +1,59 @@
/****************************************************************************
**
** Copyright (C) 2020 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 QtQuick3D 6.0
View3D {
id: root
anchors.fill: parent
environment: sceneEnv
property Material previewMaterial
SceneEnvironment {
id: sceneEnv
antialiasingMode: SceneEnvironment.MSAA
antialiasingQuality: SceneEnvironment.High
}
Node {
DirectionalLight {
eulerRotation.x: -30
eulerRotation.y: -30
}
PerspectiveCamera {
z: 120
clipFar: 1000
clipNear: 1
}
Model {
id: model
source: "#Sphere"
materials: previewMaterial
}
}
}
@@ -0,0 +1,45 @@
/****************************************************************************
**
** Copyright (C) 2020 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 6.0
Item {
id: root
width: 150
height: 150
property alias contentItem: contentItem
/*
View3D {
// Dummy view to hold the context in case View3D items are used in the component
// TODO remove when QTBUG-87678 is fixed
}
*/
Item {
id: contentItem
}
}
@@ -0,0 +1,124 @@
/****************************************************************************
**
** Copyright (C) 2020 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 6.0
import QtQuick3D 6.0
Item {
id: root
width: 150
height: 150
visible: true
property View3D view: null
property alias contentItem: contentItem
property var previewObject
property var materialViewComponent
property var modelViewComponent
property var nodeViewComponent
property bool ready: false
function destroyView()
{
previewObject = null;
if (view)
view.destroy();
}
function createViewForObject(obj)
{
if (obj instanceof Material)
createViewForMaterial(obj);
else if (obj instanceof Model)
createViewForModel(obj);
else if (obj instanceof Node)
createViewForNode(obj);
previewObject = obj;
}
function createViewForMaterial(material)
{
if (!materialViewComponent)
materialViewComponent = Qt.createComponent("MaterialNodeView.qml");
// Always recreate the view to ensure material is up to date
if (materialViewComponent.status === Component.Ready)
view = materialViewComponent.createObject(viewRect, {"previewMaterial": material});
}
function createViewForModel(model)
{
if (!modelViewComponent)
modelViewComponent = Qt.createComponent("ModelNodeView.qml");
// Always recreate the view to ensure model is up to date
if (modelViewComponent.status === Component.Ready)
view = modelViewComponent.createObject(viewRect, {"sourceModel": model});
}
function createViewForNode(node)
{
if (!nodeViewComponent)
nodeViewComponent = Qt.createComponent("NodeNodeView.qml");
// Always recreate the view to ensure node is up to date
if (nodeViewComponent.status === Component.Ready)
view = nodeViewComponent.createObject(viewRect, {"importScene": node});
}
function afterRender()
{
if (previewObject instanceof Node) {
view.fitToViewPort();
ready = view.ready;
} else {
ready = true;
}
}
View3D {
// Dummy view to hold the context
// TODO remove when QTBUG-87678 is fixed
}
Item {
id: contentItem
anchors.fill: parent
Rectangle {
id: viewRect
anchors.fill: parent
gradient: Gradient {
GradientStop { position: 1.0; color: "#222222" }
GradientStop { position: 0.0; color: "#999999" }
}
}
}
}
@@ -0,0 +1,96 @@
/****************************************************************************
**
** Copyright (C) 2020 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 6.0
import QtQuick3D 6.0
View3D {
id: root
anchors.fill: parent
environment: sceneEnv
camera: theCamera
property bool ready: false
property real prevZoomFactor: -1
property Model sourceModel
function fitToViewPort()
{
cameraControl.focusObject(model, theCamera.eulerRotation, true, false);
if (cameraControl._zoomFactor < 0.1) {
model.scale = model.scale.times(10);
} else if (cameraControl._zoomFactor > 10) {
model.scale = model.scale.times(0.1);
} else {
// We need one more render after zoom factor change, so only set ready when zoom factor
// or scaling hasn't changed from the previous frame
ready = _generalHelper.fuzzyCompare(cameraControl._zoomFactor, prevZoomFactor);
prevZoomFactor = cameraControl._zoomFactor;
}
}
SceneEnvironment {
id: sceneEnv
antialiasingMode: SceneEnvironment.MSAA
antialiasingQuality: SceneEnvironment.High
}
EditCameraController {
id: cameraControl
camera: theCamera
anchors.fill: parent
view3d: root
ignoreToolState: true
}
DirectionalLight {
eulerRotation.x: -30
eulerRotation.y: -30
}
PerspectiveCamera {
id: theCamera
z: 600
y: 600
eulerRotation.x: -45
clipFar: 10000
clipNear: 1
}
Model {
id: model
eulerRotation.y: 45
source: sourceModel.source
geometry: sourceModel.geometry
materials: [
DefaultMaterial {
diffuseColor: "#4aee45"
}
]
}
}
@@ -0,0 +1,175 @@
/****************************************************************************
**
** 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 6.0
import QtQuick3D 6.0
import MouseArea3D 1.0
Node {
id: moveGizmo
property View3D view3D
property bool highlightOnHover: false
property Node targetNode: null
property bool globalOrientation: true
readonly property bool dragging: arrowX.dragging || arrowY.dragging || arrowZ.dragging
|| planeX.dragging || planeY.dragging || planeZ.dragging
|| centerBall.dragging
property MouseArea3D dragHelper: null
property alias freeDraggerArea: centerBall.mouseArea
position: dragHelper.pivotScenePosition(targetNode)
onTargetNodeChanged: position = dragHelper.pivotScenePosition(targetNode)
Connections {
target: moveGizmo.targetNode
function onSceneTransformChanged()
{
moveGizmo.position = moveGizmo.dragHelper.pivotScenePosition(moveGizmo.targetNode);
}
}
signal positionCommit()
signal positionMove()
Node {
rotation: globalOrientation || !moveGizmo.targetNode ? Qt.quaternion(1, 0, 0, 0)
: moveGizmo.targetNode.sceneRotation
Arrow {
id: arrowX
eulerRotation: 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)
view3D: moveGizmo.view3D
active: moveGizmo.visible
dragHelper: moveGizmo.dragHelper
onPositionCommit: moveGizmo.positionCommit()
onPositionMove: moveGizmo.positionMove()
}
Arrow {
id: arrowY
eulerRotation: Qt.vector3d(0, 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
dragHelper: moveGizmo.dragHelper
onPositionCommit: moveGizmo.positionCommit()
onPositionMove: moveGizmo.positionMove()
}
Arrow {
id: arrowZ
eulerRotation: Qt.vector3d(90, 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
dragHelper: moveGizmo.dragHelper
onPositionCommit: moveGizmo.positionCommit()
onPositionMove: moveGizmo.positionMove()
}
PlanarMoveHandle {
id: planeX
y: 10
z: 10
eulerRotation: 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
dragHelper: moveGizmo.dragHelper
onPositionCommit: moveGizmo.positionCommit()
onPositionMove: moveGizmo.positionMove()
}
PlanarMoveHandle {
id: planeY
x: 10
z: 10
eulerRotation: 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
dragHelper: moveGizmo.dragHelper
onPositionCommit: moveGizmo.positionCommit()
onPositionMove: moveGizmo.positionMove()
}
PlanarMoveHandle {
id: planeZ
x: 10
y: 10
eulerRotation: 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
dragHelper: moveGizmo.dragHelper
onPositionCommit: moveGizmo.positionCommit()
onPositionMove: moveGizmo.positionMove()
}
}
PlanarMoveHandle {
id: centerBall
source: "#Sphere"
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: 10
targetNode: moveGizmo.targetNode
view3D: moveGizmo.view3D
active: moveGizmo.visible
dragHelper: moveGizmo.dragHelper
onPositionCommit: moveGizmo.positionCommit()
onPositionMove: moveGizmo.positionMove()
}
}
@@ -0,0 +1,96 @@
/****************************************************************************
**
** Copyright (C) 2020 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 6.0
import QtQuick3D 6.0
View3D {
id: root
anchors.fill: parent
environment: sceneEnv
camera: theCamera
property bool ready: false
property bool first: true
property real prevZoomFactor: -1
function fitToViewPort()
{
if (first) {
first = false;
selectionBox.targetNode = root.importScene;
} else {
cameraControl.focusObject(selectionBox.model, theCamera.eulerRotation, true, false);
if (cameraControl._zoomFactor < 0.1) {
root.importScene.scale = root.importScene.scale.times(10);
} else if (cameraControl._zoomFactor > 10) {
root.importScene.scale = root.importScene.scale.times(0.1);
} else {
// We need one more render after zoom factor change, so only set ready when zoom factor
// or scaling hasn't changed from the previous frame
ready = _generalHelper.fuzzyCompare(cameraControl._zoomFactor, prevZoomFactor);
prevZoomFactor = cameraControl._zoomFactor;
selectionBox.visible = false;
}
}
}
SceneEnvironment {
id: sceneEnv
antialiasingMode: SceneEnvironment.MSAA
antialiasingQuality: SceneEnvironment.High
}
SelectionBox {
id: selectionBox
view3D: root
geometryName: "NodeNodeViewSB"
}
EditCameraController {
id: cameraControl
camera: theCamera
anchors.fill: parent
view3d: root
ignoreToolState: true
}
DirectionalLight {
eulerRotation.x: -30
eulerRotation.y: -30
}
PerspectiveCamera {
id: theCamera
z: 600
y: 600
x: 600
eulerRotation.x: -45
eulerRotation.y: -45
clipFar: 10000
clipNear: 1
}
}
@@ -0,0 +1,69 @@
/****************************************************************************
**
** 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 6.0
import QtQuick3D 6.0
Item {
id: root
property Node targetNode
property View3D targetView
property vector3d offset: Qt.vector3d(0, 0, 0)
property bool isBehindCamera
onTargetNodeChanged: updateOverlay()
Connections {
target: targetNode
function onSceneTransformChanged() { updateOverlay() }
}
Connections {
target: targetView.camera
function onSceneTransformChanged() { updateOverlay() }
}
Connections {
target: _generalHelper
function onOverlayUpdateNeeded() { updateOverlay() }
}
function updateOverlay()
{
var scenePos = targetNode ? targetNode.scenePosition : Qt.vector3d(0, 0, 0);
// Need separate variable as scenePos is reference to read-only property
var scenePosWithOffset = Qt.vector3d(scenePos.x + offset.x,
scenePos.y + offset.y,
scenePos.z + offset.z);
var viewPos = targetView ? targetView.mapFrom3DScene(scenePosWithOffset)
: Qt.vector3d(0, 0, 0);
root.x = viewPos.x;
root.y = viewPos.y;
isBehindCamera = viewPos.z <= 0;
}
}
@@ -0,0 +1,119 @@
/****************************************************************************
**
** 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 6.0
import QtQuick3D 6.0
import MouseArea3D 1.0
Model {
id: rootModel
property View3D view3D
property alias color: gizmoMaterial.diffuseColor
property alias priority: mouseArea.priority
property Node targetNode: null
property bool dragging: mouseArea.dragging
property bool active: false
property MouseArea3D dragHelper: null
property alias mouseArea: mouseArea
readonly property bool hovering: mouseArea.hovering
property vector3d _scenePosPressed
property vector2d _planePosPressed
property vector3d _targetStartPos
signal pressed(var mouseArea)
signal dragged(var mouseArea, vector3d sceneRelativeDistance, vector2d relativeDistance)
signal released(var mouseArea, vector3d sceneRelativeDistance, vector2d relativeDistance)
source: "#Rectangle"
DefaultMaterial {
id: gizmoMaterial
diffuseColor: "white"
lighting: DefaultMaterial.NoLighting
cullMode: Material.NoCulling
}
materials: gizmoMaterial
function handlePressed(mouseArea, planePos)
{
if (!targetNode)
return;
_planePosPressed = planePos;
_scenePosPressed = mouseArea.dragHelper.mapPositionToScene(planePos.toVector3d());
_targetStartPos = mouseArea.pivotScenePosition(targetNode);
pressed(mouseArea);
}
function calcRelativeDistance(mouseArea, planePos)
{
var scenePointerPos = mouseArea.dragHelper.mapPositionToScene(planePos.toVector3d());
return scenePointerPos.minus(_scenePosPressed);
}
function handleDragged(mouseArea, planePos)
{
if (!targetNode)
return;
dragged(mouseArea, calcRelativeDistance(mouseArea, planePos),
planePos.minus(_planePosPressed));
}
function handleReleased(mouseArea, planePos)
{
if (!targetNode)
return;
released(mouseArea, calcRelativeDistance(mouseArea, planePos),
planePos.minus(_planePosPressed));
}
MouseArea3D {
id: mouseArea
view3D: rootModel.view3D
x: -60
y: -60
width: 120
height: 120
grabsMouse: targetNode
active: rootModel.active
dragHelper: rootModel.dragHelper
onPressed: (planePos)=> {
rootModel.handlePressed(mouseArea, planePos);
}
onDragged: (planePos)=> {
rootModel.handleDragged(mouseArea, planePos);
}
onReleased: (planePos)=> {
rootModel.handleReleased(mouseArea, planePos);
}
}
}
@@ -0,0 +1,64 @@
/****************************************************************************
**
** 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 6.0
import QtQuick3D 6.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 ? targetNode.parent.mapPositionFromScene(newScenePos) : newScenePos;
}
onPressed: {
if (targetNode == multiSelectionNode)
_generalHelper.restartMultiSelection();
}
onDragged: (mouseArea, sceneRelativeDistance)=> {
targetNode.position = localPos(sceneRelativeDistance);
if (targetNode == multiSelectionNode)
_generalHelper.moveMultiSelection(false);
positionMove();
}
onReleased: (mouseArea, sceneRelativeDistance)=> {
targetNode.position = localPos(sceneRelativeDistance);
if (targetNode == multiSelectionNode)
_generalHelper.moveMultiSelection(true);
positionCommit();
}
}
@@ -0,0 +1,64 @@
/****************************************************************************
**
** 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 6.0
import QtQuick3D 6.0
import MouseArea3D 1.0
PlanarDraggable {
id: planarHandle
scale: Qt.vector3d(0.024, 0.024, 0.024)
property bool globalOrientation: false
property vector3d axisX
property vector3d axisY
signal scaleCommit()
signal scaleChange()
property vector3d _startScale
onPressed: {
if (targetNode == multiSelectionNode)
_generalHelper.restartMultiSelection();
_startScale = targetNode.scale;
}
onDragged: (mouseArea, sceneRelativeDistance, relativeDistance)=> {
targetNode.scale = mouseArea.getNewScale(_startScale, relativeDistance.times(scale.x),
axisX, axisY);
if (targetNode == multiSelectionNode)
_generalHelper.scaleMultiSelection(false);
scaleChange();
}
onReleased: (mouseArea, sceneRelativeDistance, relativeDistance)=> {
targetNode.scale = mouseArea.getNewScale(_startScale, relativeDistance.times(scale.x),
axisX, axisY);
if (targetNode == multiSelectionNode)
_generalHelper.scaleMultiSelection(true);
scaleCommit();
}
}
@@ -0,0 +1,293 @@
/****************************************************************************
**
** 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 6.0
import QtQuick3D 6.0
import MouseArea3D 1.0
Node {
id: rotateGizmo
property View3D view3D
property bool highlightOnHover: true
property Node targetNode: null
property bool globalOrientation: true
readonly property bool dragging: cameraRing.dragging
|| rotRingX.dragging || rotRingY.dragging || rotRingZ.dragging
property MouseArea3D dragHelper: null
property real currentAngle
property point currentMousePos
property alias freeDraggerArea: mouseAreaFree
property bool blocked: false
position: dragHelper.pivotScenePosition(targetNode)
onTargetNodeChanged: {
position = dragHelper.pivotScenePosition(targetNode);
blocked = _generalHelper.isRotationBlocked(targetNode);
}
Connections {
target: rotateGizmo.targetNode
function onSceneTransformChanged()
{
rotateGizmo.position = dragHelper.pivotScenePosition(targetNode);
}
}
Connections {
target: _generalHelper
function onRotationBlocksChanged()
{
blocked = _generalHelper.isRotationBlocked(targetNode);
}
}
signal rotateCommit()
signal rotateChange()
function copyRingProperties(srcRing) {
draggingRing.rotation = srcRing.sceneRotation;
draggingRing.color = srcRing.color;
draggingRing.scale = srcRing.scale;
}
onDraggingChanged: {
if (rotRingX.dragging)
copyRingProperties(rotRingX)
else if (rotRingY.dragging)
copyRingProperties(rotRingY)
else if (rotRingZ.dragging)
copyRingProperties(rotRingZ)
}
Node {
id: rotNode
rotation: globalOrientation || !rotateGizmo.targetNode ? Qt.quaternion(1, 0, 0, 0)
: rotateGizmo.targetNode.sceneRotation
visible: !rotateGizmo.dragging && !freeRotator.dragging
RotateRing {
id: rotRingX
objectName: "Rotate Ring X"
eulerRotation: Qt.vector3d(0, 90, 0)
targetNode: rotateGizmo.targetNode
color: rotateGizmo.blocked ? Qt.rgba(0.5, 0.5, 0.5, 1)
: highlightOnHover && (hovering || dragging)
? Qt.lighter(Qt.rgba(1, 0, 0, 1)) : Qt.rgba(1, 0, 0, 1)
priority: 40
view3D: rotateGizmo.view3D
active: rotateGizmo.visible && !rotateGizmo.blocked
dragHelper: rotateGizmo.dragHelper
onRotateCommit: rotateGizmo.rotateCommit()
onRotateChange: rotateGizmo.rotateChange()
onCurrentAngleChanged: rotateGizmo.currentAngle = currentAngle
onCurrentMousePosChanged: rotateGizmo.currentMousePos = currentMousePos
}
RotateRing {
id: rotRingY
objectName: "Rotate Ring Y"
eulerRotation: Qt.vector3d(90, 0, 0)
targetNode: rotateGizmo.targetNode
color: rotateGizmo.blocked ? Qt.rgba(0.5, 0.5, 0.5, 1)
: highlightOnHover && (hovering || dragging)
? Qt.lighter(Qt.rgba(0, 0.6, 0, 1)) : Qt.rgba(0, 0.6, 0, 1)
// Just a smidge smaller than higher priority rings so that it doesn't obscure them
scale: Qt.vector3d(0.998, 0.998, 0.998)
priority: 30
view3D: rotateGizmo.view3D
active: rotateGizmo.visible && !rotateGizmo.blocked
dragHelper: rotateGizmo.dragHelper
onRotateCommit: rotateGizmo.rotateCommit()
onRotateChange: rotateGizmo.rotateChange()
onCurrentAngleChanged: rotateGizmo.currentAngle = currentAngle
onCurrentMousePosChanged: rotateGizmo.currentMousePos = currentMousePos
}
RotateRing {
id: rotRingZ
objectName: "Rotate Ring Z"
eulerRotation: Qt.vector3d(0, 0, 0)
targetNode: rotateGizmo.targetNode
color: rotateGizmo.blocked ? Qt.rgba(0.5, 0.5, 0.5, 1)
: highlightOnHover && (hovering || dragging)
? Qt.lighter(Qt.rgba(0, 0, 1, 1)) : Qt.rgba(0, 0, 1, 1)
// Just a smidge smaller than higher priority rings so that it doesn't obscure them
scale: Qt.vector3d(0.996, 0.996, 0.996)
priority: 20
view3D: rotateGizmo.view3D
active: rotateGizmo.visible && !rotateGizmo.blocked
dragHelper: rotateGizmo.dragHelper
onRotateCommit: rotateGizmo.rotateCommit()
onRotateChange: rotateGizmo.rotateChange()
onCurrentAngleChanged: rotateGizmo.currentAngle = currentAngle
onCurrentMousePosChanged: rotateGizmo.currentMousePos = currentMousePos
}
}
RotateRing {
// This ring is used as visual proxy during dragging to display the currently dragged
// plane in static position, as rotation planes can wobble when ancestors don't have
// uniform scaling.
// Camera ring doesn't need dragging proxy as it doesn't wobble.
id: draggingRing
objectName: "draggingRing"
targetNode: rotateGizmo.targetNode
view3D: rotateGizmo.view3D
active: false
visible: rotRingX.dragging || rotRingY.dragging || rotRingZ.dragging
}
RotateRing {
id: cameraRing
objectName: "cameraRing"
rotation: rotateGizmo.view3D.camera.rotation
targetNode: rotateGizmo.targetNode
color: rotateGizmo.blocked ? Qt.rgba(0.5, 0.5, 0.5, 1)
: highlightOnHover && (hovering || dragging)
? Qt.lighter(Qt.rgba(0.5, 0.5, 0.5, 1))
: Qt.rgba(0.5, 0.5, 0.5, 1)
scale: Qt.vector3d(1.1, 1.1, 1.1)
priority: 10
view3D: rotateGizmo.view3D
active: rotateGizmo.visible && !rotateGizmo.blocked
dragHelper: rotateGizmo.dragHelper
visible: !rotRingX.dragging && !rotRingY.dragging && !rotRingZ.dragging && !freeRotator.dragging
onRotateCommit: rotateGizmo.rotateCommit()
onRotateChange: rotateGizmo.rotateChange()
onCurrentAngleChanged: rotateGizmo.currentAngle = currentAngle
onCurrentMousePosChanged: rotateGizmo.currentMousePos = currentMousePos
}
Model {
id: freeRotator
source: "#Sphere"
materials: DefaultMaterial {
id: material
diffuseColor: "black"
opacity: mouseAreaFree.hovering && !rotateGizmo.blocked ? 0.15 : 0
lighting: DefaultMaterial.NoLighting
}
scale: Qt.vector3d(0.15, 0.15, 0.15)
visible: !rotateGizmo.dragging && !dragging
property bool dragging: false
property vector3d _pointerPosPressed
property vector3d _startRotation
function handlePressed(screenPos)
{
if (!rotateGizmo.targetNode)
return;
if (targetNode == multiSelectionNode)
_generalHelper.restartMultiSelection();
// Need to recreate vector as we need to adjust it and we can't do that on reference of
// scenePosition, which is read-only property
var scenePos = rotateGizmo.dragHelper.pivotScenePosition(rotateGizmo.targetNode);
_pointerPosPressed = Qt.vector3d(screenPos.x, screenPos.y, 0);
// Recreate vector so we don't follow the changes in targetNode.rotation
_startRotation = Qt.vector3d(rotateGizmo.targetNode.eulerRotation.x,
rotateGizmo.targetNode.eulerRotation.y,
rotateGizmo.targetNode.eulerRotation.z);
// Ensure we never set NaN values for rotation, even if target node originally has them
if (isNaN(_startRotation.x))
_startRotation.x = 0;
if (isNaN(_startRotation.y))
_startRotation.y = 0;
if (isNaN(_startRotation.z))
_startRotation.z = 0;
dragging = true;
}
function handleDragged(screenPos)
{
if (!rotateGizmo.targetNode)
return;
mouseAreaFree.applyFreeRotation(
rotateGizmo.targetNode, _startRotation, _pointerPosPressed,
Qt.vector3d(screenPos.x, screenPos.y, 0));
if (targetNode == multiSelectionNode)
_generalHelper.rotateMultiSelection(false);
rotateGizmo.rotateChange();
}
function handleReleased(screenPos)
{
if (!rotateGizmo.targetNode)
return;
mouseAreaFree.applyFreeRotation(
rotateGizmo.targetNode, _startRotation, _pointerPosPressed,
Qt.vector3d(screenPos.x, screenPos.y, 0));
if (targetNode == multiSelectionNode)
_generalHelper.rotateMultiSelection(true);
rotateGizmo.rotateCommit();
dragging = false;
if (targetNode == multiSelectionNode)
_generalHelper.resetMultiSelectionNode();
}
MouseArea3D {
id: mouseAreaFree
view3D: rotateGizmo.view3D
rotation: rotateGizmo.view3D.camera.rotation
objectName: "Free rotator plane"
x: -50
y: -50
width: 100
height: 100
circlePickArea: Qt.point(25, 50)
grabsMouse: rotateGizmo.targetNode
active: rotateGizmo.visible && !rotateGizmo.blocked
dragHelper: rotateGizmo.dragHelper
onPressed: (planePos, screenPos)=> {
freeRotator.handlePressed(screenPos);
}
onDragged: (planePos, screenPos)=> {
freeRotator.handleDragged(screenPos);
}
onReleased: (planePos, screenPos)=> {
freeRotator.handleReleased(screenPos);
}
}
}
}
@@ -0,0 +1,164 @@
/****************************************************************************
**
** 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 6.0
import QtQuick3D 6.0
import MouseArea3D 1.0
Model {
id: rotateRing
property View3D view3D
property alias color: material.diffuseColor
property Node targetNode: null
property bool dragging: mouseAreaMain.dragging
property bool active: false
property alias hovering: mouseAreaMain.hovering
property alias priority: mouseAreaMain.priority
property real currentAngle
property point currentMousePos
property MouseArea3D dragHelper: null
property vector3d _pointerPosPressed
property vector3d _targetPosOnScreen
property vector3d _startRotation
property bool _trackBall
signal rotateCommit()
signal rotateChange()
source: "../meshes/ring.mesh"
Model {
id: pickModel
objectName: "PickModel for " + rotateRing.objectName
source: "../meshes/ringselect.mesh"
pickable: true
}
materials: DefaultMaterial {
id: material
diffuseColor: "white"
lighting: DefaultMaterial.NoLighting
}
function applyLocalRotation(screenPos)
{
currentAngle = mouseAreaMain.dragHelper.getNewRotationAngle(
targetNode, _pointerPosPressed, Qt.vector3d(screenPos.x, screenPos.y, 0),
_targetPosOnScreen, currentAngle, _trackBall);
mouseAreaMain.dragHelper.applyRotationAngleToNode(targetNode, _startRotation, currentAngle);
}
function handlePressed(screenPos, angle)
{
if (!targetNode)
return;
if (targetNode == multiSelectionNode)
_generalHelper.restartMultiSelection();
// Need to recreate vector as we need to adjust it and we can't do that on reference of
// scenePosition, which is read-only property
var scenePos = mouseAreaMain.pivotScenePosition(targetNode);
_targetPosOnScreen = view3D.mapFrom3DScene(scenePos);
_targetPosOnScreen.z = 0;
_pointerPosPressed = Qt.vector3d(screenPos.x, screenPos.y, 0);
_trackBall = angle < 0.1;
// Recreate vector so we don't follow the changes in targetNode.eulerRotation
_startRotation = Qt.vector3d(targetNode.eulerRotation.x,
targetNode.eulerRotation.y,
targetNode.eulerRotation.z);
// Ensure we never set NaN values for rotation, even if target node originally has them
if (isNaN(_startRotation.x))
_startRotation.x = 0;
if (isNaN(_startRotation.y))
_startRotation.y = 0;
if (isNaN(_startRotation.z))
_startRotation.z = 0;
currentAngle = 0;
currentMousePos = screenPos;
}
function handleDragged(screenPos)
{
if (!targetNode)
return;
applyLocalRotation(screenPos);
if (targetNode == multiSelectionNode)
_generalHelper.rotateMultiSelection(false);
currentMousePos = screenPos;
rotateChange();
}
function handleReleased(screenPos)
{
if (!targetNode)
return;
applyLocalRotation(screenPos);
if (targetNode == multiSelectionNode)
_generalHelper.rotateMultiSelection(true);
rotateCommit();
currentAngle = 0;
currentMousePos = screenPos;
if (targetNode == multiSelectionNode)
_generalHelper.resetMultiSelectionNode();
}
MouseArea3D {
id: mouseAreaMain
view3D: rotateRing.view3D
objectName: "Main plane of " + rotateRing.objectName
x: -30
y: -30
width: 60
height: 60
circlePickArea: Qt.point(9.2, 1.4)
grabsMouse: targetNode
active: rotateRing.active
pickNode: pickModel
minAngle: 0.05
dragHelper: rotateRing.dragHelper
onPressed: (planePos, screenPos, angle)=> {
rotateRing.handlePressed(screenPos, angle);
}
onDragged: (planePos, screenPos)=> {
rotateRing.handleDragged(screenPos);
}
onReleased: (planePos, screenPos)=> {
rotateRing.handleReleased(screenPos);
}
}
}
@@ -0,0 +1,241 @@
/****************************************************************************
**
** 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 6.0
import QtQuick3D 6.0
import MouseArea3D 1.0
Node {
id: scaleGizmo
property View3D view3D
property bool highlightOnHover: false
property Node targetNode: null
readonly property bool dragging: scaleRodX.dragging || scaleRodY.dragging || scaleRodZ.dragging
|| planeX.dragging || planeY.dragging || planeZ.dragging
|| centerMouseArea.dragging
property MouseArea3D dragHelper: null
property alias freeDraggerArea: centerMouseArea
position: dragHelper.pivotScenePosition(targetNode)
onTargetNodeChanged: position = dragHelper.pivotScenePosition(targetNode)
Connections {
target: scaleGizmo.targetNode
function onSceneTransformChanged()
{
scaleGizmo.position = scaleGizmo.dragHelper.pivotScenePosition(scaleGizmo.targetNode);
}
}
signal scaleCommit()
signal scaleChange()
Node {
rotation: !targetNode ? Qt.quaternion(1, 0, 0, 0) : targetNode.sceneRotation
ScaleRod {
id: scaleRodX
eulerRotation: Qt.vector3d(0, 0, -90)
axis: Qt.vector3d(1, 0, 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
dragHelper: scaleGizmo.dragHelper
onScaleCommit: scaleGizmo.scaleCommit()
onScaleChange: scaleGizmo.scaleChange()
}
ScaleRod {
id: scaleRodY
eulerRotation: Qt.vector3d(0, 0, 0)
axis: Qt.vector3d(0, 1, 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
dragHelper: scaleGizmo.dragHelper
onScaleCommit: scaleGizmo.scaleCommit()
onScaleChange: scaleGizmo.scaleChange()
}
ScaleRod {
id: scaleRodZ
eulerRotation: Qt.vector3d(90, 0, 0)
axis: Qt.vector3d(0, 0, 1)
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
dragHelper: scaleGizmo.dragHelper
onScaleCommit: scaleGizmo.scaleCommit()
onScaleChange: scaleGizmo.scaleChange()
}
PlanarScaleHandle {
id: planeX
y: 10
z: 10
eulerRotation: Qt.vector3d(0, 90, 0)
axisX: Qt.vector3d(0, 0, -1)
axisY: Qt.vector3d(0, 1, 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
dragHelper: scaleGizmo.dragHelper
onScaleCommit: scaleGizmo.scaleCommit()
onScaleChange: scaleGizmo.scaleChange()
}
PlanarScaleHandle {
id: planeY
x: 10
z: 10
eulerRotation: Qt.vector3d(90, 0, 0)
axisX: Qt.vector3d(1, 0, 0)
axisY: Qt.vector3d(0, 0, 1)
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
dragHelper: scaleGizmo.dragHelper
onScaleCommit: scaleGizmo.scaleCommit()
onScaleChange: scaleGizmo.scaleChange()
}
PlanarScaleHandle {
id: planeZ
x: 10
y: 10
eulerRotation: Qt.vector3d(0, 0, 0)
axisX: Qt.vector3d(1, 0, 0)
axisY: Qt.vector3d(0, 1, 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
dragHelper: scaleGizmo.dragHelper
onScaleCommit: scaleGizmo.scaleCommit()
onScaleChange: scaleGizmo.scaleChange()
}
}
Model {
id: centerCube
source: "#Cube"
scale: Qt.vector3d(0.024, 0.024, 0.024)
materials: DefaultMaterial {
id: material
diffuseColor: 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: 10
active: scaleGizmo.visible
dragHelper: scaleGizmo.dragHelper
property vector3d _startScale
property point _startScreenPos
function localScale(screenPos)
{
var yDelta = screenPos.y - _startScreenPos.y;
if (yDelta === 0)
return _startScale;
var scaler = 1.0 + (yDelta * 0.025);
if (scaler === 0)
scaler = 0.0001;
return Qt.vector3d(scaler * _startScale.x,
scaler * _startScale.y,
scaler * _startScale.z);
}
onPressed: (planePos, screenPos)=> {
if (!scaleGizmo.targetNode)
return;
if (targetNode == multiSelectionNode)
_generalHelper.restartMultiSelection();
// 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: (planePos, screenPos)=> {
if (!scaleGizmo.targetNode)
return;
scaleGizmo.targetNode.scale = localScale(screenPos);
if (targetNode == multiSelectionNode)
_generalHelper.scaleMultiSelection(false);
scaleGizmo.scaleChange();
}
onReleased: (planePos, screenPos)=> {
if (!scaleGizmo.targetNode)
return;
scaleGizmo.targetNode.scale = localScale(screenPos);
if (targetNode == multiSelectionNode)
_generalHelper.scaleMultiSelection(true);
scaleGizmo.scaleCommit();
}
}
}
}
@@ -0,0 +1,73 @@
/****************************************************************************
**
** 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 6.0
import QtQuick3D 6.0
import MouseArea3D 1.0
DirectionalDraggable {
id: scaleRod
source: "../meshes/scalerod.mesh"
property vector3d axis
signal scaleCommit()
signal scaleChange()
property vector3d _startScale
Model {
source: "#Cube"
y: 10
scale: Qt.vector3d(0.020, 0.020, 0.020)
materials: DefaultMaterial {
id: material
diffuseColor: scaleRod.color
lighting: DefaultMaterial.NoLighting
}
}
onPressed: {
if (targetNode == multiSelectionNode)
_generalHelper.restartMultiSelection();
_startScale = targetNode.scale;
}
onDragged: (mouseArea, sceneRelativeDistance, relativeDistance)=> {
targetNode.scale = mouseArea.getNewScale(_startScale, Qt.vector2d(relativeDistance, 0),
axis, Qt.vector3d(0, 0, 0));
if (targetNode == multiSelectionNode)
_generalHelper.scaleMultiSelection(false);
scaleChange();
}
onReleased: (mouseArea, sceneRelativeDistance, relativeDistance)=> {
targetNode.scale = mouseArea.getNewScale(_startScale, Qt.vector2d(relativeDistance, 0),
axis, Qt.vector3d(0, 0, 0));
if (targetNode == multiSelectionNode)
_generalHelper.scaleMultiSelection(true);
scaleCommit();
}
}
@@ -0,0 +1,92 @@
/****************************************************************************
**
** Copyright (C) 2020 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 QtQuick3D 6.0
View3D {
id: sceneView
anchors.fill: parent
property bool usePerspective: false
property alias showSceneLight: sceneLight.visible
property alias showGrid: helperGrid.visible
property alias sceneHelpers: sceneHelpers
property alias perspectiveCamera: scenePerspectiveCamera
property alias orthoCamera: sceneOrthoCamera
property double cameraZoomFactor: .55;
// Empirical cameraZoomFactor values at which the grid zoom level is doubled. The values are
// approximately uniformally distributed over the non-linear range of cameraZoomFactor.
readonly property var grid_thresholds: [0.55, 1.10, 2.35, 4.9, 10.0, 20.5, 42.0, 85.0, 999999.0]
property var thresIdx: 1
property var thresPerc: 1.0 // percentage of cameraZoomFactor to the current grid zoom threshold (0.0 - 1.0)
camera: usePerspective ? scenePerspectiveCamera : sceneOrthoCamera
onCameraZoomFactorChanged: {
thresIdx = Math.max(1, grid_thresholds.findIndex(v => v > cameraZoomFactor));
thresPerc = (grid_thresholds[thresIdx] - cameraZoomFactor) / (grid_thresholds[thresIdx] - grid_thresholds[thresIdx - 1]);
}
Node {
id: sceneHelpers
HelperGrid {
id: helperGrid
lines: Math.pow(2, grid_thresholds.length - thresIdx - 1);
step: 100 * grid_thresholds[0] * Math.pow(2, thresIdx - 1);
subdivAlpha: thresPerc;
}
PointLight {
id: sceneLight
position: usePerspective ? scenePerspectiveCamera.position
: sceneOrthoCamera.position
quadraticFade: 0
linearFade: 0
}
// Initial camera position and rotation should be such that they look at origin.
// Otherwise EditCameraController._lookAtPoint needs to be initialized to correct
// point.
PerspectiveCamera {
id: scenePerspectiveCamera
z: 600
y: 600
eulerRotation.x: -45
clipFar: 100000
clipNear: 1
}
OrthographicCamera {
id: sceneOrthoCamera
z: 600
y: 600
eulerRotation.x: -45
clipFar: 100000
clipNear: -10000
}
}
}
@@ -0,0 +1,65 @@
/****************************************************************************
**
** 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 6.0
import QtQuick3D 6.0
import SelectionBoxGeometry 1.0
Node {
id: selectionBox
property View3D view3D
property Node targetNode: null
property alias model: selectionBoxModel
property alias geometryName: selectionBoxGeometry.name
SelectionBoxGeometry {
id: selectionBoxGeometry
name: "Selection Box of 3D Edit View"
view3D: selectionBox.view3D
targetNode: selectionBox.targetNode
rootNode: selectionBox
}
Model {
id: selectionBoxModel
geometry: selectionBoxGeometry
scale: selectionBox.targetNode ? selectionBox.targetNode.scale : Qt.vector3d(1, 1, 1)
rotation: selectionBox.targetNode ? selectionBox.targetNode.rotation : Qt.quaternion(1, 0, 0, 0)
position: selectionBox.targetNode ? selectionBox.targetNode.position : Qt.vector3d(0, 0, 0)
pivot: selectionBox.targetNode ? selectionBox.targetNode.pivot : Qt.vector3d(0, 0, 0)
visible: selectionBox.targetNode && !selectionBoxGeometry.isEmpty
materials: [
DefaultMaterial {
diffuseColor: "#fff600"
lighting: DefaultMaterial.NoLighting
cullMode: Material.NoCulling
}
]
}
}
@@ -0,0 +1,82 @@
/****************************************************************************
**
** Copyright (C) 2020 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 6.0
import QtQuick3D 6.0
DirectionalDraggable {
id: handleRoot
property string currentLabel
property point currentMousePos
property string propName
property real propValue: 0
property real newValue: 0
scale: autoScaler.getScale(Qt.vector3d(5, 5, 5))
length: 3
offset: -1.5
Model {
id: handle
source: "#Sphere"
materials: [ handleRoot.material ]
scale: Qt.vector3d(0.02, 0.02, 0.02)
}
AutoScaleHelper {
id: autoScaler
active: handleRoot.active
view3D: handleRoot.view3D
}
property real _startAngle
signal valueCommit()
signal valueChange()
function updateAngle(relativeDistance, screenPos)
{
handleRoot.newValue = Math.round(Math.min(180, Math.max(0, _startAngle + relativeDistance)));
var l = Qt.locale();
handleRoot.currentLabel = propName + qsTr(": ") + Number(newValue).toLocaleString(l, 'f', 0);
handleRoot.currentMousePos = screenPos;
}
onPressed: (mouseArea, screenPos)=> {
_startAngle = propValue;
updateAngle(0, screenPos);
}
onDragged: (mouseArea, sceneRelativeDistance, relativeDistance, screenPos)=> {
updateAngle(relativeDistance, screenPos);
handleRoot.valueChange();
}
onReleased: (mouseArea, sceneRelativeDistance, relativeDistance, screenPos)=> {
updateAngle(relativeDistance, screenPos);
handleRoot.valueCommit();
}
}
@@ -96,11 +96,13 @@ void IconRenderer::setupRender()
if (auto scene = qobject_cast<QQuick3DNode *>(iconItem)) {
qmlRegisterType<QmlDesigner::Internal::SelectionBoxGeometry>("SelectionBoxGeometry", 1, 0, "SelectionBoxGeometry");
QQmlComponent component(engine);
component.loadUrl(QUrl("qrc:/qtquickplugin/mockfiles/IconRenderer3D.qml"));
m_containerItem = qobject_cast<QQuickItem *>(component.create());
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
component.loadUrl(QUrl("qrc:/qtquickplugin/mockfiles/qt5/IconRenderer3D.qml"));
m_containerItem = qobject_cast<QQuickItem *>(component.create());
DesignerSupport::setRootItem(view, m_containerItem);
#else
component.loadUrl(QUrl("qrc:/qtquickplugin/mockfiles/qt6/IconRenderer3D.qml"));
m_containerItem = qobject_cast<QQuickItem *>(component.create());
m_window->contentItem()->setSize(m_containerItem->size());
m_window->setGeometry(0, 0, m_containerItem->width(), m_containerItem->height());
m_containerItem->setParentItem(m_window->contentItem());
@@ -392,8 +392,11 @@ void Qt5InformationNodeInstanceServer::createEditView3D()
new QmlDesigner::Internal::IconGizmoImageProvider);
m_3dHelper = helper;
createAuxiliaryQuickView(QUrl("qrc:/qtquickplugin/mockfiles/EditView3D.qml"), m_editView3DData);
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
createAuxiliaryQuickView(QUrl("qrc:/qtquickplugin/mockfiles/qt6/EditView3D.qml"), m_editView3DData);
#else
createAuxiliaryQuickView(QUrl("qrc:/qtquickplugin/mockfiles/qt5/EditView3D.qml"), m_editView3DData);
#endif
if (m_editView3DData.rootItem)
helper->setParent(m_editView3DData.rootItem);
#endif
@@ -1192,12 +1195,22 @@ void Qt5InformationNodeInstanceServer::initializeAuxiliaryViews()
#ifdef QUICK3D_MODULE
if (isQuick3DMode())
createEditView3D();
createAuxiliaryQuickView(QUrl("qrc:/qtquickplugin/mockfiles/ModelNode3DImageView.qml"),
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
createAuxiliaryQuickView(QUrl("qrc:/qtquickplugin/mockfiles/qt6/ModelNode3DImageView.qml"),
m_modelNode3DImageViewData);
#else
createAuxiliaryQuickView(QUrl("qrc:/qtquickplugin/mockfiles/qt5/ModelNode3DImageView.qml"),
m_modelNode3DImageViewData);
#endif
#endif
createAuxiliaryQuickView(QUrl("qrc:/qtquickplugin/mockfiles/ModelNode2DImageView.qml"),
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
createAuxiliaryQuickView(QUrl("qrc:/qtquickplugin/mockfiles/qt6/ModelNode2DImageView.qml"),
m_modelNode2DImageViewData);
#else
createAuxiliaryQuickView(QUrl("qrc:/qtquickplugin/mockfiles/qt5/ModelNode2DImageView.qml"),
m_modelNode2DImageViewData);
#endif
m_modelNode2DImageViewData.window->setDefaultAlphaBuffer(true);
m_modelNode2DImageViewData.window->setColor(Qt::transparent);
}
@@ -29,6 +29,9 @@ include (import3d/import3d.pri)
SOURCES += $$PWD/qml2puppetmain.cpp
RESOURCES += $$PWD/../qmlpuppet.qrc
versionAtLeast(QT_VERSION, 6.0.0): RESOURCES += $$PWD/../editor3d_qt6.qrc
else: RESOURCES += $$PWD/../editor3d_qt5.qrc
DISTFILES += Info.plist
unix:!openbsd:!osx: LIBS += -lrt # posix shared memory
@@ -9,58 +9,7 @@
<file>mockfiles/SwipeView.qml</file>
<file>mockfiles/GenericBackend.qml</file>
<file>mockfiles/Dialog.qml</file>
<file>mockfiles/IconRenderer3D.qml</file>
<file>mockfiles/EditView3D.qml</file>
<file>mockfiles/EditCameraController.qml</file>
<file>mockfiles/Arrow.qml</file>
<file>mockfiles/AutoScaleHelper.qml</file>
<file>mockfiles/MoveGizmo.qml</file>
<file>mockfiles/CameraFrustum.qml</file>
<file>mockfiles/CameraGizmo.qml</file>
<file>mockfiles/LightModel.qml</file>
<file>mockfiles/LightIconGizmo.qml</file>
<file>mockfiles/LightGizmo.qml</file>
<file>mockfiles/AdjustableArrow.qml</file>
<file>mockfiles/FadeHandle.qml</file>
<file>mockfiles/AreaLightHandle.qml</file>
<file>mockfiles/SpotLightHandle.qml</file>
<file>mockfiles/IconGizmo.qml</file>
<file>mockfiles/Overlay2D.qml</file>
<file>mockfiles/HelperGrid.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/ScaleGizmo.qml</file>
<file>mockfiles/ToolBarButton.qml</file>
<file>mockfiles/ToggleButton.qml</file>
<file>mockfiles/RotateGizmo.qml</file>
<file>mockfiles/RotateRing.qml</file>
<file>mockfiles/SceneView3D.qml</file>
<file>mockfiles/SelectionBox.qml</file>
<file>mockfiles/AxisHelper.qml</file>
<file>mockfiles/AxisHelperArm.qml</file>
<file>mockfiles/Line3D.qml</file>
<file>mockfiles/ModelNode3DImageView.qml</file>
<file>mockfiles/ModelNode2DImageView.qml</file>
<file>mockfiles/MaterialNodeView.qml</file>
<file>mockfiles/ModelNodeView.qml</file>
<file>mockfiles/NodeNodeView.qml</file>
<file>mockfiles/meshes/arrow.mesh</file>
<file>mockfiles/meshes/scalerod.mesh</file>
<file>mockfiles/meshes/ring.mesh</file>
<file>mockfiles/meshes/ringselect.mesh</file>
<file>mockfiles/meshes/axishelper.mesh</file>
<file>mockfiles/images/editor_camera.png</file>
<file>mockfiles/images/editor_camera@2x.png</file>
<file>mockfiles/images/area.png</file>
<file>mockfiles/images/area@2x.png</file>
<file>mockfiles/images/directional.png</file>
<file>mockfiles/images/directional@2x.png</file>
<file>mockfiles/images/point.png</file>
<file>mockfiles/images/point@2x.png</file>
<file>mockfiles/images/spot.png</file>
<file>mockfiles/images/spot@2x.png</file>
</qresource>
</RCC>
+14
View File
@@ -107,6 +107,20 @@ add_qtc_executable(qml2puppet
DESTINATION ${DESTDIR}
)
extend_qtc_executable(qml2puppet
CONDITION Qt5_VERSION VERSION_GREATER_EQUAL 6.0.0
SOURCES_PREFIX "${SRCDIR}/"
SOURCES
"editor3d_qt6.qrc"
)
extend_qtc_executable(qml2puppet
CONDITION Qt5_VERSION VERSION_LESS 6.0.0
SOURCES_PREFIX "${SRCDIR}/"
SOURCES
"editor3d_qt5.qrc"
)
extend_qtc_executable(qml2puppet
CONDITION UNIX AND (NOT APPLE)
DEPENDS rt
+14
View File
@@ -166,6 +166,20 @@ QtcTool {
files: ["sharedmemory_qt.cpp"]
}
Group {
name: "puppet2 3D editor Qt5"
condition: !product.usesQt6
prefix: puppetDir + "/"
files: ["editor3d_qt5.qrc"]
}
Group {
name: "puppet2 3D editor Qt6"
condition: product.usesQt6
prefix: puppetDir + "/"
files: ["editor3d_qt6.qrc"]
}
Group {
name: "puppet2 sources"
prefix: puppetDir + "/qml2puppet/"