diff options
author | Eike Ziller <eike.ziller@qt.io> | 2019-11-28 08:24:10 +0100 |
---|---|---|
committer | Eike Ziller <eike.ziller@qt.io> | 2019-11-28 08:24:10 +0100 |
commit | 6fc85b49fa43c28af6f5726550513fd6974ebae8 (patch) | |
tree | 74f917f587914a27642fe3b97a6130cbd1fac732 /share/qtcreator/qml | |
parent | 2059cb31f0544626e12b2fa828ca60f27cd8e2d3 (diff) | |
parent | 6b1d54421e3831576c8d169bf38caf1ab503c84a (diff) | |
download | qt-creator-6fc85b49fa43c28af6f5726550513fd6974ebae8.tar.gz |
Merge remote-tracking branch 'origin/4.11'
Conflicts:
src/plugins/designer/codemodelhelpers.cpp
Change-Id: I78906f2fbbfd27d254589a272ebca423b0b80699
Diffstat (limited to 'share/qtcreator/qml')
53 files changed, 1459 insertions, 263 deletions
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/AutoScaleHelper.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/AutoScaleHelper.qml index 9ffd3aa85b..dc4c38d100 100644 --- a/share/qtcreator/qml/qmlpuppet/mockfiles/AutoScaleHelper.qml +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/AutoScaleHelper.qml @@ -46,7 +46,7 @@ Node { } Connections { - target: designStudioNativeCameraControlHelper + target: _generalHelper onOverlayUpdateNeeded: updateScale() } @@ -81,6 +81,7 @@ Node { MouseArea3D { id: helper + active: false view3D: overlayNode.view3D } } diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/AxisHelper.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/AxisHelper.qml new file mode 100644 index 0000000000..86c60db721 --- /dev/null +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/AxisHelper.qml @@ -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 2.0 +import QtQuick3D 1.0 + +View3D { + id: axisHelperView + + property var editCameraCtrl + property Node selectedNode + + camera: axisHelperCamera + + Node { + OrthographicCamera { + id: axisHelperCamera + rotation: editCameraCtrl.camera.rotation + position: editCameraCtrl.camera.position.minus(editCameraCtrl._lookAtPoint) + .normalized().times(600) + } + + AutoScaleHelper { + id: autoScale + view3D: axisHelperView + position: axisHelperGizmo.scenePosition + } + + Node { + id: axisHelperGizmo + scale: autoScale.getScale(Qt.vector3d(4, 4, 4)) + + AxisHelperArm { + id: armX + rotation: 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 + rotation: 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 + rotation: 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: { + pick(mouse); + } + + onPressed: { + pick(mouse); + if (pickObj) { + axisHelperView.editCameraCtrl.fitObject(axisHelperView.selectedNode, + pickObj.cameraRotation); + } else { + mouse.accepted = false; + } + } + + onExited: cancelHover() + onCanceled: cancelHover() + } +} diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/cameracontrolhelper.h b/share/qtcreator/qml/qmlpuppet/mockfiles/AxisHelperArm.qml index ae17196044..23d2f9bbaf 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/cameracontrolhelper.h +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/AxisHelperArm.qml @@ -23,40 +23,48 @@ ** ****************************************************************************/ -#pragma once +import QtQuick 2.0 +import QtQuick3D 1.0 -#include <QtCore/QObject> -#include <QtCore/QTimer> +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 -namespace QmlDesigner { -namespace Internal { -class CameraControlHelper : public QObject -{ - Q_OBJECT - Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged) + Model { + id: posModel -public: - CameraControlHelper(); + property bool hovering: false + property vector3d cameraRotation: armRoot.camRotPos - bool enabled(); - void setEnabled(bool enabled); + source: "meshes/axishelper.mesh" + materials: DefaultMaterial { + id: posMat + emissiveColor: posModel.hovering ? armRoot.hoverColor : armRoot.color + lighting: DefaultMaterial.NoLighting + } + pickable: true + } - Q_INVOKABLE void requestOverlayUpdate(); - Q_INVOKABLE QString generateUniqueName(const QString &nameRoot); + Model { + id: negModel -public slots: - void handleUpdateTimer(); + property bool hovering: false + property vector3d cameraRotation: armRoot.camRotNeg -signals: - void updateInputs(); - void enabledChanged(bool enabled); - void overlayUpdateNeeded(); - -private: - bool m_enabled = false; - QTimer m_inputUpdateTimer; - QTimer m_overlayUpdateTimer; -}; - -} + source: "#Sphere" + y: -6 + scale: Qt.vector3d(0.025, 0.025, 0.025) + materials: DefaultMaterial { + id: negMat + emissiveColor: negModel.hovering ? armRoot.hoverColor : armRoot.color + lighting: DefaultMaterial.NoLighting + } + pickable: true + } } diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/CameraGizmo.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/CameraGizmo.qml index e158128a5f..3b6badbb28 100644 --- a/share/qtcreator/qml/qmlpuppet/mockfiles/CameraGizmo.qml +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/CameraGizmo.qml @@ -31,21 +31,26 @@ IconGizmo { id: cameraGizmo iconSource: "qrc:///qtquickplugin/mockfiles/images/editor_camera.png" - gizmoModel.geometry: cameraGeometry property alias geometryName: cameraGeometry.name // Name must be unique for each geometry property alias viewPortRect: cameraGeometry.viewPortRect + Model { + id: gizmoModel + geometry: cameraGeometry + visible: cameraGizmo.visible + materials: [ + DefaultMaterial { + id: defaultMaterial + emissiveColor: cameraGizmo.targetNode === cameraGizmo.selectedNode ? "#FF0000" + : "#555555" + lighting: DefaultMaterial.NoLighting + cullingMode: Material.DisableCulling + } + ] + } + CameraGeometry { id: cameraGeometry camera: cameraGizmo.targetNode } - - gizmoModel.materials: [ - DefaultMaterial { - id: defaultMaterial - emissiveColor: cameraGizmo.targetNode === cameraGizmo.selectedNode ? "#FF0000" : "#555555" - lighting: DefaultMaterial.NoLighting - cullingMode: Material.DisableCulling - } - ] } diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/DirectionalDraggable.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/DirectionalDraggable.qml index 243744210e..7ccfaa9816 100644 --- a/share/qtcreator/qml/qmlpuppet/mockfiles/DirectionalDraggable.qml +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/DirectionalDraggable.qml @@ -34,7 +34,7 @@ Model { property View3D view3D property alias color: material.emissiveColor property Node targetNode: null - property bool dragging: false + property bool dragging: mouseAreaYZ.dragging || mouseAreaXZ.dragging property bool active: false readonly property bool hovering: mouseAreaYZ.hovering || mouseAreaXZ.hovering @@ -61,7 +61,6 @@ Model { _pointerPosPressed = mouseArea.mapPositionToScene(maskedPosition); var sp = targetNode.scenePosition; _targetStartPos = Qt.vector3d(sp.x, sp.y, sp.z); - dragging = true; pressed(mouseArea); } @@ -88,7 +87,6 @@ Model { return; released(mouseArea, calcRelativeDistance(mouseArea, scenePos)); - dragging = false; } MouseArea3D { diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/EditCameraController.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/EditCameraController.qml new file mode 100644 index 0000000000..dba7e30f96 --- /dev/null +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/EditCameraController.qml @@ -0,0 +1,128 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +import QtQuick 2.12 +import QtQuick3D 1.0 + +Item { + id: cameraCtrl + + property Camera camera: null + property View3D view3d: null + + 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 real _defaultCameraLookAtDistance: 0 + property Camera _prevCamera: null + + function fitObject(targetObject, rotation) + { + camera.rotation = rotation; + var newLookAtAndZoom = _generalHelper.fitObjectToCamera( + camera, _defaultCameraLookAtDistance, targetObject, view3d); + _lookAtPoint = newLookAtAndZoom.toVector3d(); + _zoomFactor = newLookAtAndZoom.w; + } + + function zoomRelative(distance) + { + _zoomFactor = _generalHelper.zoomCamera(camera, distance, _defaultCameraLookAtDistance, + _lookAtPoint, _zoomFactor, true); + } + + Component.onCompleted: { + cameraCtrl._defaultCameraLookAtDistance = cameraCtrl.camera.position.length(); + } + + onCameraChanged: { + if (_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: { + if (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: { + if (mouse.modifiers === Qt.AltModifier) { + cameraCtrl._dragging = true; + cameraCtrl._startRotation = cameraCtrl.camera.rotation; + 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; + } + } + + onReleased: cameraCtrl._dragging = false; + onCanceled: cameraCtrl._dragging = false; + onWheel: { + // Emprically determined divisor for nice zoom + cameraCtrl.zoomRelative(wheel.angleDelta.y / -40); + } + } +} diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml index 9db9d0c8a8..2200048fa5 100644 --- a/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml @@ -26,7 +26,6 @@ import QtQuick 2.12 import QtQuick.Window 2.0 import QtQuick3D 1.0 -import QtQuick3D.Helpers 1.0 import QtQuick.Controls 2.0 import QtGraphicalEffects 1.0 @@ -39,8 +38,8 @@ Window { flags: Qt.WindowStaysOnTopHint | Qt.Window | Qt.WindowTitleHint | Qt.WindowCloseButtonHint property alias scene: editView.importScene - property alias showEditLight: editLightCheckbox.checked - property alias usePerspective: usePerspectiveCheckbox.checked + property alias showEditLight: btnEditViewLight.toggled + property alias usePerspective: btnPerspective.toggled property Node selectedNode: null @@ -56,9 +55,14 @@ Window { selectedNode = object; } - function emitObjectClicked(object) { - selectObject(object); - objectClicked(object); + function handleObjectClicked(object) { + var theObject = object; + if (btnSelectGroup.selected) { + while (theObject && theObject.parent !== scene) + theObject = theObject.parent; + } + selectObject(theObject); + objectClicked(theObject); } function addLightGizmo(obj) @@ -69,7 +73,7 @@ Window { {"view3D": overlayView, "targetNode": obj, "selectedNode": selectedNode}); lightGizmos[lightGizmos.length] = gizmo; - gizmo.clicked.connect(emitObjectClicked); + gizmo.clicked.connect(handleObjectClicked); gizmo.selectedNode = Qt.binding(function() {return selectedNode;}); } } @@ -78,13 +82,13 @@ Window { { var component = Qt.createComponent("CameraGizmo.qml"); if (component.status === Component.Ready) { - var geometryName = designStudioNativeCameraControlHelper.generateUniqueName("CameraGeometry"); + var geometryName = _generalHelper.generateUniqueName("CameraGeometry"); var gizmo = component.createObject( overlayScene, {"view3D": overlayView, "targetNode": obj, "geometryName": geometryName, "viewPortRect": viewPortRect, "selectedNode": selectedNode}); cameraGizmos[cameraGizmos.length] = gizmo; - gizmo.clicked.connect(emitObjectClicked); + gizmo.clicked.connect(handleObjectClicked); gizmo.viewPortRect = Qt.binding(function() {return viewPortRect;}); gizmo.selectedNode = Qt.binding(function() {return selectedNode;}); } @@ -92,10 +96,10 @@ Window { // 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. - Component.onCompleted: designStudioNativeCameraControlHelper.requestOverlayUpdate(); + Component.onCompleted: _generalHelper.requestOverlayUpdate(); - onWidthChanged: designStudioNativeCameraControlHelper.requestOverlayUpdate(); - onHeightChanged: designStudioNativeCameraControlHelper.requestOverlayUpdate(); + onWidthChanged: _generalHelper.requestOverlayUpdate(); + onHeightChanged: _generalHelper.requestOverlayUpdate(); Node { id: overlayScene @@ -114,6 +118,7 @@ Window { clipNear: editOrthoCamera.clipNear position: editOrthoCamera.position rotation: editOrthoCamera.rotation + scale: editOrthoCamera.scale } MoveGizmo { @@ -123,7 +128,7 @@ Window { targetNode: viewWindow.selectedNode position: viewWindow.selectedNode ? viewWindow.selectedNode.scenePosition : Qt.vector3d(0, 0, 0) - globalOrientation: globalControl.checked + globalOrientation: btnLocalGlobal.toggled visible: selectedNode && btnMove.selected view3D: overlayView @@ -138,7 +143,7 @@ Window { targetNode: viewWindow.selectedNode position: viewWindow.selectedNode ? viewWindow.selectedNode.scenePosition : Qt.vector3d(0, 0, 0) - globalOrientation: globalControl.checked + globalOrientation: false visible: selectedNode && btnScale.selected view3D: overlayView @@ -153,7 +158,7 @@ Window { targetNode: viewWindow.selectedNode position: viewWindow.selectedNode ? viewWindow.selectedNode.scenePosition : Qt.vector3d(0, 0, 0) - globalOrientation: globalControl.checked + globalOrientation: btnLocalGlobal.toggled visible: selectedNode && btnRotate.selected view3D: overlayView @@ -169,16 +174,19 @@ Window { } Rectangle { - id: sceneBg - color: "#FFFFFF" anchors.fill: parent focus: true + gradient: Gradient { + GradientStop { position: 1.0; color: "#222222" } + GradientStop { position: 0.0; color: "#999999" } + } + TapHandler { // check tapping/clicking an object in the scene onTapped: { var pickResult = editView.pick(eventPoint.scenePosition.x, eventPoint.scenePosition.y); - emitObjectClicked(pickResult.objectHit); + handleObjectClicked(pickResult.objectHit); } } @@ -200,6 +208,12 @@ Window { step: 50 } + SelectionBox { + id: selectionBox + view3D: editView + targetNode: viewWindow.selectedNode + } + PointLight { id: editLight visible: showEditLight @@ -209,11 +223,14 @@ Window { 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: editPerspectiveCamera z: -600 - y: 200 - rotation.x: 30 + y: 600 + rotation.x: 45 clipFar: 100000 clipNear: 1 } @@ -221,10 +238,10 @@ Window { OrthographicCamera { id: editOrthoCamera z: -600 - y: 200 - rotation.x: 30 + y: 600 + rotation.x: 45 clipFar: 100000 - clipNear: 1 + clipNear: -10000 } } } @@ -240,14 +257,12 @@ Window { id: gizmoLabel targetNode: moveGizmo.visible ? moveGizmo : scaleGizmo targetView: overlayView - offsetX: 0 - offsetY: 45 visible: targetNode.dragging Rectangle { color: "white" x: -width / 2 - y: -height + y: -height - 8 width: gizmoLabelText.width + 4 height: gizmoLabelText.height + 4 border.width: 1 @@ -273,19 +288,11 @@ Window { } } - WasdController { + EditCameraController { id: cameraControl - controlledObject: editView.camera - acceptedButtons: Qt.RightButton - - onInputsNeedProcessingChanged: designStudioNativeCameraControlHelper.enabled - = cameraControl.inputsNeedProcessing - - // Use separate native timer as QML timers don't work inside Qt Design Studio - Connections { - target: designStudioNativeCameraControlHelper - onUpdateInputs: cameraControl.processInputs() - } + camera: editView.camera + anchors.fill: parent + view3d: editView } } @@ -301,7 +308,8 @@ Window { spacing: 5 padding: 5 - property var group: [btnSelectItem, btnSelectGroup, btnMove, btnRotate, btnScale] + property var groupSelect: [btnSelectGroup, btnSelectItem] + property var groupTransform: [btnMove, btnRotate, btnScale] ToolBarButton { id: btnSelectItem @@ -310,7 +318,7 @@ Window { shortcut: "Q" currentShortcut: selected ? "" : shortcut tool: "item_selection" - buttonsGroup: col.group + buttonsGroup: col.groupSelect } ToolBarButton { @@ -319,7 +327,7 @@ Window { shortcut: "Q" currentShortcut: btnSelectItem.currentShortcut === shortcut ? "" : shortcut tool: "group_selection" - buttonsGroup: col.group + buttonsGroup: col.groupSelect } Rectangle { // separator @@ -331,11 +339,12 @@ Window { ToolBarButton { id: btnMove + selected: true tooltip: qsTr("Move current selection") - shortcut: "M" + shortcut: "W" currentShortcut: shortcut tool: "move" - buttonsGroup: col.group + buttonsGroup: col.groupTransform } ToolBarButton { @@ -344,60 +353,96 @@ Window { shortcut: "E" currentShortcut: shortcut tool: "rotate" - buttonsGroup: col.group + buttonsGroup: col.groupTransform } ToolBarButton { id: btnScale tooltip: qsTr("Scale current selection") - shortcut: "T" + shortcut: "R" currentShortcut: shortcut tool: "scale" - buttonsGroup: col.group + buttonsGroup: col.groupTransform + } + + Rectangle { // separator + width: 25 + height: 1 + color: "#f1f1f1" + anchors.horizontalCenter: parent.horizontalCenter + } + + ToolBarButton { + id: btnFit + tooltip: qsTr("Fit camera to current selection") + shortcut: "F" + currentShortcut: shortcut + tool: "fit" + togglable: false + + onSelectedChanged: { + if (selected) { + var targetNode = viewWindow.selectedNode ? selectionBox.model : null; + cameraControl.fitObject(targetNode, editView.camera.rotation); + } + } } } } - Column { - y: 8 + AxisHelper { anchors.right: parent.right - CheckBox { - id: editLightCheckbox - checked: false - text: qsTr("Use Edit View Light") - onCheckedChanged: cameraControl.forceActiveFocus() + anchors.top: parent.top + width: 100 + height: width + editCameraCtrl: cameraControl + selectedNode : viewWindow.selectedNode ? selectionBox.model : null + } + + Rectangle { // top controls bar + color: "#aa000000" + width: 265 + height: btnPerspective.height + 10 + anchors.top: parent.top + anchors.right: parent.right + anchors.rightMargin: 100 + + ToggleButton { + id: btnPerspective + anchors.top: parent.top + anchors.topMargin: 5 + anchors.left: parent.left + anchors.leftMargin: 5 + tooltip: qsTr("Toggle Perspective / Orthographic Projection") + states: [{iconId: "ortho", text: qsTr("Orthographic")}, {iconId: "persp", text: qsTr("Perspective")}] } - CheckBox { - id: usePerspectiveCheckbox - checked: true - text: qsTr("Use Perspective Projection") - onCheckedChanged: { - // Since WasdController always acts on active camera, we need to update pos/rot - // to the other camera when we change - if (checked) { - editPerspectiveCamera.position = editOrthoCamera.position; - editPerspectiveCamera.rotation = editOrthoCamera.rotation; - } else { - editOrthoCamera.position = editPerspectiveCamera.position; - editOrthoCamera.rotation = editPerspectiveCamera.rotation; - } - designStudioNativeCameraControlHelper.requestOverlayUpdate(); - cameraControl.forceActiveFocus(); - } + ToggleButton { + id: btnLocalGlobal + anchors.top: parent.top + anchors.topMargin: 5 + anchors.left: parent.left + anchors.leftMargin: 100 + tooltip: qsTr("Toggle Global / Local Orientation") + states: [{iconId: "local", text: qsTr("Local")}, {iconId: "global", text: qsTr("Global")}] } - CheckBox { - id: globalControl - checked: true - text: qsTr("Use Global Orientation") - onCheckedChanged: cameraControl.forceActiveFocus() + ToggleButton { + id: btnEditViewLight + anchors.top: parent.top + anchors.topMargin: 5 + anchors.left: parent.left + anchors.leftMargin: 165 + toggleBackground: true + tooltip: qsTr("Toggle Edit Light") + states: [{iconId: "edit_light_off", text: qsTr("Edit Light Off")}, {iconId: "edit_light_on", text: qsTr("Edit Light On")}] } } Text { id: helpText - text: qsTr("Camera: W,A,S,D,R,F,right mouse drag") + color: "white" + text: qsTr("Camera controls: ALT + mouse press and drag. Left: Rotate, Middle: Pan, Right/Wheel: Zoom.") anchors.bottom: parent.bottom } } diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/HelperGrid.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/HelperGrid.qml index 54af572a7b..2d70c0b95c 100644 --- a/share/qtcreator/qml/qmlpuppet/mockfiles/HelperGrid.qml +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/HelperGrid.qml @@ -45,7 +45,7 @@ Node { materials: [ DefaultMaterial { id: mainGridMaterial - emissiveColor: "#e6e6e6" + emissiveColor: "#cccccc" lighting: DefaultMaterial.NoLighting cullingMode: Material.DisableCulling } diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/IconGizmo.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/IconGizmo.qml index 8623b87a84..3d4183a9dc 100644 --- a/share/qtcreator/qml/qmlpuppet/mockfiles/IconGizmo.qml +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/IconGizmo.qml @@ -25,6 +25,7 @@ import QtQuick 2.0 import QtQuick3D 1.0 +import QtGraphicalEffects 1.12 Node { id: iconGizmo @@ -34,8 +35,8 @@ Node { property Node targetNode: null property Node selectedNode: null - property alias gizmoModel: gizmoModel property alias iconSource: iconImage.source + property alias overlayColor: colorOverlay.color signal positionCommit() signal clicked(Node node) @@ -44,30 +45,25 @@ Node { rotation: targetNode ? targetNode.sceneRotation : Qt.vector3d(0, 0, 0) visible: targetNode ? targetNode.visible : false - Model { - id: gizmoModel - visible: iconGizmo.visible - } Overlay2D { - id: gizmoLabel - targetNode: gizmoModel + id: iconOverlay + targetNode: iconGizmo targetView: view3D - offsetX: 0 - offsetY: 0 visible: iconGizmo.visible && !isBehindCamera parent: view3D Rectangle { + id: iconRect width: iconImage.width height: iconImage.height x: -width / 2 - y: -height + y: -height / 2 color: "transparent" border.color: "#7777ff" - border.width: iconGizmo.selectedNode === iconGizmo.targetNode - || (iconGizmo.highlightOnHover && iconMouseArea.containsMouse) ? 2 : 0 + border.width: iconGizmo.selectedNode !== iconGizmo.targetNode + && iconGizmo.highlightOnHover && iconMouseArea.containsMouse ? 2 : 0 radius: 5 - opacity: iconGizmo.selectedNode === iconGizmo.targetNode ? 0.3 : 1 + opacity: iconGizmo.selectedNode === iconGizmo.targetNode ? 0.2 : 1 Image { id: iconImage fillMode: Image.Pad @@ -81,6 +77,15 @@ Node { ? Qt.LeftButton : Qt.NoButton } } + ColorOverlay { + id: colorOverlay + anchors.fill: parent + cached: true + source: iconImage + color: "transparent" + opacity: 0.6 + } + } } } diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/LightGizmo.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/LightGizmo.qml index 888b2fce5c..6e321f8398 100644 --- a/share/qtcreator/qml/qmlpuppet/mockfiles/LightGizmo.qml +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/LightGizmo.qml @@ -29,14 +29,13 @@ import QtQuick3D 1.0 IconGizmo { id: lightGizmo - iconSource: "qrc:///qtquickplugin/mockfiles/images/light-pick-icon.png" - gizmoModel.source: "#Sphere" - gizmoModel.scale: Qt.vector3d(0.10, 0.10, 0.10) - gizmoModel.materials: [ - DefaultMaterial { - id: defaultMaterial - emissiveColor: "yellow" - lighting: DefaultMaterial.NoLighting - } - ] + iconSource: targetNode + ? targetNode instanceof DirectionalLight + ? "qrc:///qtquickplugin/mockfiles/images/directional_light_gradient.png" + : targetNode instanceof AreaLight + ? "qrc:///qtquickplugin/mockfiles/images/area_light_gradient.png" + : "qrc:///qtquickplugin/mockfiles/images/point_light_gradient.png" + : "qrc:///qtquickplugin/mockfiles/images/point_light_gradient.png" + + overlayColor: targetNode ? targetNode.color : "transparent" } diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/Overlay2D.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/Overlay2D.qml index 1392c60cb2..f4a85226b7 100644 --- a/share/qtcreator/qml/qmlpuppet/mockfiles/Overlay2D.qml +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/Overlay2D.qml @@ -31,8 +31,7 @@ Item { property Node targetNode property View3D targetView - property real offsetX: 0 - property real offsetY: 0 + property vector3d offset: Qt.vector3d(0, 0, 0) property bool isBehindCamera @@ -49,14 +48,16 @@ Item { } Connections { - target: designStudioNativeCameraControlHelper + target: _generalHelper onOverlayUpdateNeeded: updateOverlay() } function updateOverlay() { var scenePos = targetNode ? targetNode.scenePosition : Qt.vector3d(0, 0, 0); - var scenePosWithOffset = Qt.vector3d(scenePos.x + offsetX, scenePos.y + offsetY, scenePos.z); + 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; diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/PlanarDraggable.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/PlanarDraggable.qml index 7bb1085e65..bd4fcd388b 100644 --- a/share/qtcreator/qml/qmlpuppet/mockfiles/PlanarDraggable.qml +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/PlanarDraggable.qml @@ -34,7 +34,7 @@ Model { property alias color: gizmoMaterial.emissiveColor property alias priority: mouseArea.priority property Node targetNode: null - property bool dragging: false + property bool dragging: mouseArea.dragging property bool active: false readonly property bool hovering: mouseArea.hovering @@ -65,7 +65,6 @@ Model { _pointerPosPressed = mouseArea.mapPositionToScene(scenePos); var sp = targetNode.scenePosition; _targetStartPos = Qt.vector3d(sp.x, sp.y, sp.z); - dragging = true; pressed(mouseArea); } @@ -91,7 +90,6 @@ Model { return; released(mouseArea, calcRelativeDistance(mouseArea, scenePos)); - dragging = false; } MouseArea3D { diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/RotateGizmo.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/RotateGizmo.qml index b2f42b39e2..b730e86910 100644 --- a/share/qtcreator/qml/qmlpuppet/mockfiles/RotateGizmo.qml +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/RotateGizmo.qml @@ -134,8 +134,7 @@ Node { targetNode: rotateGizmo.targetNode color: highlightOnHover && (hovering || dragging) ? Qt.lighter(Qt.rgba(0.5, 0.5, 0.5, 1)) : Qt.rgba(0.5, 0.5, 0.5, 1) - // Just a smidge smaller than higher priority rings so that it doesn't obscure them - scale: Qt.vector3d(0.994, 0.994, 0.994) + scale: Qt.vector3d(1.1, 1.1, 1.1) priority: 10 view3D: rotateGizmo.view3D active: rotateGizmo.visible diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/RotateRing.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/RotateRing.qml index 634eb017c9..3d21f8fd6a 100644 --- a/share/qtcreator/qml/qmlpuppet/mockfiles/RotateRing.qml +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/RotateRing.qml @@ -33,7 +33,7 @@ Model { property View3D view3D property alias color: material.emissiveColor property Node targetNode: null - property bool dragging: false + property bool dragging: mouseAreaMain.dragging property bool active: false property alias hovering: mouseAreaMain.hovering property alias priority: mouseAreaMain.priority @@ -80,7 +80,6 @@ Model { _targetPosOnScreen = view3D.mapFrom3DScene(targetNode.scenePosition); _targetPosOnScreen.z = 0; _pointerPosPressed = Qt.vector3d(screenPos.x, screenPos.y, 0); - dragging = true; _trackBall = angle < 0.1; // Recreate vector so we don't follow the changes in targetNode.rotation @@ -108,7 +107,6 @@ Model { applyLocalRotation(screenPos); rotateCommit(); - dragging = false; currentAngle = 0; currentMousePos = screenPos; } diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/SelectionBox.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/SelectionBox.qml new file mode 100644 index 0000000000..995b4badd8 --- /dev/null +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/SelectionBox.qml @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick3D 1.0 +import SelectionBoxGeometry 1.0 + +Node { + id: selectionBox + + property View3D view3D + property Node targetNode: null + property alias model: selectionBoxModel + + 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.vector3d(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) + orientation: selectionBox.targetNode ? selectionBox.targetNode.orientation : Node.LeftHanded + rotationOrder: selectionBox.targetNode ? selectionBox.targetNode.rotationOrder : Node.YXZ + + visible: selectionBox.targetNode && !selectionBoxGeometry.isEmpty + + materials: [ + DefaultMaterial { + emissiveColor: "#fff600" + lighting: DefaultMaterial.NoLighting + cullingMode: Material.DisableCulling + } + ] + } +} diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/ToggleButton.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/ToggleButton.qml new file mode 100644 index 0000000000..a0ebeabbd4 --- /dev/null +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/ToggleButton.qml @@ -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 2.12 +import QtQuick 2.0 +import QtQuick.Controls 2.0 + +Rectangle { + property bool toggled: false + property string tooltip + property bool toggleBackground: false // show a black background for the toggled state + property var states: [] // array of 2 state-objects, idx 0: untoggled, idx 1: toggled + + id: root + color: toggleBackground && toggled ? "#aa000000" : mouseArea.containsMouse ? "#44000000" : "#00000000" + width: img.width + txt.width + 5 + height: img.height + + Image { + id: img + anchors.verticalCenter: parent.verticalCenter + source: "qrc:///qtquickplugin/mockfiles/images/" + root.states[toggled ? 1 : 0].iconId + ".png" + } + + Text { + id: txt + color: "#b5b5b5" + anchors.verticalCenter: parent.verticalCenter + anchors.left: img.right + text: root.states[toggled ? 1 : 0].text + } + + ToolTip { + text: tooltip + visible: mouseArea.containsMouse + delay: 1000 + } + + MouseArea { + id: mouseArea + cursorShape: "PointingHandCursor" + hoverEnabled: true + anchors.fill: parent + onClicked: root.toggled = !root.toggled + } +} + + diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/ToolBarButton.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/ToolBarButton.qml index cbc450ed2b..38a8608e47 100644 --- a/share/qtcreator/qml/qmlpuppet/mockfiles/ToolBarButton.qml +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/ToolBarButton.qml @@ -34,6 +34,7 @@ Rectangle { property string currentShortcut property string tool property variant buttonsGroup: [] + property bool togglable: true id: root width: img.width + 5 @@ -71,6 +72,11 @@ Rectangle { root.buttonsGroup[i].selected = false; root.selected = true; + + if (!root.togglable) { + // Deselect button after a short while (selection acts as simple click indicator) + _generalHelper.delayedPropertySet(root, 200, "selected", false); + } } } } diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/images/area_light_gradient.png b/share/qtcreator/qml/qmlpuppet/mockfiles/images/area_light_gradient.png Binary files differnew file mode 100644 index 0000000000..bd6404a36c --- /dev/null +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/images/area_light_gradient.png diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/images/area_light_gradient@2x.png b/share/qtcreator/qml/qmlpuppet/mockfiles/images/area_light_gradient@2x.png Binary files differnew file mode 100644 index 0000000000..463f3ac481 --- /dev/null +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/images/area_light_gradient@2x.png diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/images/directional_light_gradient.png b/share/qtcreator/qml/qmlpuppet/mockfiles/images/directional_light_gradient.png Binary files differnew file mode 100644 index 0000000000..f3c013e157 --- /dev/null +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/images/directional_light_gradient.png diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/images/directional_light_gradient@2x.png b/share/qtcreator/qml/qmlpuppet/mockfiles/images/directional_light_gradient@2x.png Binary files differnew file mode 100644 index 0000000000..87d60515f5 --- /dev/null +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/images/directional_light_gradient@2x.png diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/images/edit_light_off.png b/share/qtcreator/qml/qmlpuppet/mockfiles/images/edit_light_off.png Binary files differnew file mode 100644 index 0000000000..73e6e92374 --- /dev/null +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/images/edit_light_off.png diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/images/edit_light_off@2x.png b/share/qtcreator/qml/qmlpuppet/mockfiles/images/edit_light_off@2x.png Binary files differnew file mode 100644 index 0000000000..5166264e16 --- /dev/null +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/images/edit_light_off@2x.png diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/images/edit_light_on.png b/share/qtcreator/qml/qmlpuppet/mockfiles/images/edit_light_on.png Binary files differnew file mode 100644 index 0000000000..7660c28546 --- /dev/null +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/images/edit_light_on.png diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/images/edit_light_on@2x.png b/share/qtcreator/qml/qmlpuppet/mockfiles/images/edit_light_on@2x.png Binary files differnew file mode 100644 index 0000000000..836bd2a0d5 --- /dev/null +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/images/edit_light_on@2x.png diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/images/fit_active.png b/share/qtcreator/qml/qmlpuppet/mockfiles/images/fit_active.png Binary files differnew file mode 100644 index 0000000000..056e9ec3c8 --- /dev/null +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/images/fit_active.png diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/images/fit_active@2x.png b/share/qtcreator/qml/qmlpuppet/mockfiles/images/fit_active@2x.png Binary files differnew file mode 100644 index 0000000000..4b05f83d46 --- /dev/null +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/images/fit_active@2x.png diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/images/fit_selected.png b/share/qtcreator/qml/qmlpuppet/mockfiles/images/fit_selected.png Binary files differnew file mode 100644 index 0000000000..b8f98d9f12 --- /dev/null +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/images/fit_selected.png diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/images/fit_selected@2x.png b/share/qtcreator/qml/qmlpuppet/mockfiles/images/fit_selected@2x.png Binary files differnew file mode 100644 index 0000000000..eac4361253 --- /dev/null +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/images/fit_selected@2x.png diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/images/global.png b/share/qtcreator/qml/qmlpuppet/mockfiles/images/global.png Binary files differnew file mode 100644 index 0000000000..1bd09c680a --- /dev/null +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/images/global.png diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/images/global@2x.png b/share/qtcreator/qml/qmlpuppet/mockfiles/images/global@2x.png Binary files differnew file mode 100644 index 0000000000..a2a857fb10 --- /dev/null +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/images/global@2x.png diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/images/local.png b/share/qtcreator/qml/qmlpuppet/mockfiles/images/local.png Binary files differnew file mode 100644 index 0000000000..0a608f6816 --- /dev/null +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/images/local.png diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/images/local@2x.png b/share/qtcreator/qml/qmlpuppet/mockfiles/images/local@2x.png Binary files differnew file mode 100644 index 0000000000..a5c931e750 --- /dev/null +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/images/local@2x.png diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/images/ortho.png b/share/qtcreator/qml/qmlpuppet/mockfiles/images/ortho.png Binary files differnew file mode 100644 index 0000000000..35b36203fa --- /dev/null +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/images/ortho.png diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/images/ortho@2x.png b/share/qtcreator/qml/qmlpuppet/mockfiles/images/ortho@2x.png Binary files differnew file mode 100644 index 0000000000..443c73e444 --- /dev/null +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/images/ortho@2x.png diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/images/persp.png b/share/qtcreator/qml/qmlpuppet/mockfiles/images/persp.png Binary files differnew file mode 100644 index 0000000000..9a48e76399 --- /dev/null +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/images/persp.png diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/images/persp@2x.png b/share/qtcreator/qml/qmlpuppet/mockfiles/images/persp@2x.png Binary files differnew file mode 100644 index 0000000000..88a4eab9c6 --- /dev/null +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/images/persp@2x.png diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/images/point_light_gradient.png b/share/qtcreator/qml/qmlpuppet/mockfiles/images/point_light_gradient.png Binary files differnew file mode 100644 index 0000000000..5136b39fc2 --- /dev/null +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/images/point_light_gradient.png diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/images/point_light_gradient@2x.png b/share/qtcreator/qml/qmlpuppet/mockfiles/images/point_light_gradient@2x.png Binary files differnew file mode 100644 index 0000000000..ccbfb1c846 --- /dev/null +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/images/point_light_gradient@2x.png diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/meshes/axishelper.mesh b/share/qtcreator/qml/qmlpuppet/mockfiles/meshes/axishelper.mesh Binary files differnew file mode 100644 index 0000000000..3e9e4958e4 --- /dev/null +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/meshes/axishelper.mesh diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/cameracontrolhelper.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/cameracontrolhelper.cpp deleted file mode 100644 index 1091e45911..0000000000 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/cameracontrolhelper.cpp +++ /dev/null @@ -1,78 +0,0 @@ -/**************************************************************************** -** -** 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. -** -****************************************************************************/ -#include "cameracontrolhelper.h" - -#include <QHash> - -namespace QmlDesigner { -namespace Internal { - -CameraControlHelper::CameraControlHelper() - : QObject() -{ - m_inputUpdateTimer.setInterval(16); - QObject::connect(&m_inputUpdateTimer, &QTimer::timeout, - this, &CameraControlHelper::handleUpdateTimer); - - m_overlayUpdateTimer.setInterval(16); - m_overlayUpdateTimer.setSingleShot(true); - QObject::connect(&m_overlayUpdateTimer, &QTimer::timeout, - this, &CameraControlHelper::overlayUpdateNeeded); -} - -bool CameraControlHelper::enabled() -{ - return m_enabled; -} - -void CameraControlHelper::handleUpdateTimer() -{ - emit updateInputs(); -} - -void CameraControlHelper::setEnabled(bool enabled) -{ - if (enabled) - m_inputUpdateTimer.start(); - else - m_inputUpdateTimer.stop(); - m_enabled = enabled; -} - -void CameraControlHelper::requestOverlayUpdate() -{ - if (!m_overlayUpdateTimer.isActive()) - m_overlayUpdateTimer.start(); -} - -QString CameraControlHelper::generateUniqueName(const QString &nameRoot) -{ - static QHash<QString, int> counters; - int count = counters[nameRoot]++; - return QStringLiteral("%1_%2").arg(nameRoot).arg(count); -} - -} -} diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/editor3d.pri b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/editor3d.pri index e8f546e818..7b515e7a60 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/editor3d.pri +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/editor3d.pri @@ -1,9 +1,11 @@ -HEADERS += $$PWD/cameracontrolhelper.h \ +HEADERS += $$PWD/generalhelper.h \ $$PWD/mousearea3d.h \ $$PWD/camerageometry.h \ - $$PWD/gridgeometry.h + $$PWD/gridgeometry.h \ + $$PWD/selectionboxgeometry.h -SOURCES += $$PWD/cameracontrolhelper.cpp \ +SOURCES += $$PWD/generalhelper.cpp \ $$PWD/mousearea3d.cpp \ $$PWD/camerageometry.cpp \ - $$PWD/gridgeometry.cpp + $$PWD/gridgeometry.cpp \ + $$PWD/selectionboxgeometry.cpp diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.cpp new file mode 100644 index 0000000000..850a440a12 --- /dev/null +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.cpp @@ -0,0 +1,210 @@ +/**************************************************************************** +** +** 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. +** +****************************************************************************/ +#include "generalhelper.h" + +#ifdef QUICK3D_MODULE + +#include "selectionboxgeometry.h" + +#include <QtQuick3D/private/qquick3dorthographiccamera_p.h> +#include <QtQuick3D/private/qquick3dperspectivecamera_p.h> +#include <QtQuick3D/private/qquick3dobject_p_p.h> +#include <QtQuick3D/private/qquick3dcamera_p.h> +#include <QtQuick3D/private/qquick3dnode_p.h> +#include <QtQuick3D/private/qquick3dmodel_p.h> +#include <QtQuick3D/private/qquick3dviewport_p.h> +#include <QtQuick3D/private/qquick3ddefaultmaterial_p.h> +#include <QtQuick3DRuntimeRender/private/qssgrendercontextcore_p.h> +#include <QtQuick3DRuntimeRender/private/qssgrenderbuffermanager_p.h> +#include <QtQuick3DRuntimeRender/private/qssgrendermodel_p.h> +#include <QtQuick3DUtils/private/qssgbounds3_p.h> +#include <QtQuick/qquickwindow.h> +#include <QtCore/qmath.h> + +namespace QmlDesigner { +namespace Internal { + +GeneralHelper::GeneralHelper() + : QObject() +{ + m_overlayUpdateTimer.setInterval(16); + m_overlayUpdateTimer.setSingleShot(true); + QObject::connect(&m_overlayUpdateTimer, &QTimer::timeout, + this, &GeneralHelper::overlayUpdateNeeded); +} + +void GeneralHelper::requestOverlayUpdate() +{ + if (!m_overlayUpdateTimer.isActive()) + m_overlayUpdateTimer.start(); +} + +QString GeneralHelper::generateUniqueName(const QString &nameRoot) +{ + static QHash<QString, int> counters; + int count = counters[nameRoot]++; + return QStringLiteral("%1_%2").arg(nameRoot).arg(count); +} + +void GeneralHelper::orbitCamera(QQuick3DCamera *camera, const QVector3D &startRotation, + const QVector3D &lookAtPoint, const QVector3D &pressPos, + const QVector3D ¤tPos) +{ + QVector3D dragVector = currentPos - pressPos; + + if (dragVector.length() < 0.001f) + return; + + camera->setRotation(startRotation); + QVector3D newRotation(dragVector.y(), dragVector.x(), 0.f); + newRotation *= 0.5f; // Emprically determined multiplier for nice drag + newRotation += startRotation; + + camera->setRotation(newRotation); + + const QVector3D oldLookVector = camera->position() - lookAtPoint; + QMatrix4x4 m = camera->sceneTransform(); + const float *dataPtr(m.data()); + QVector3D newLookVector(-dataPtr[8], -dataPtr[9], -dataPtr[10]); + newLookVector.normalize(); + newLookVector *= oldLookVector.length(); + + camera->setPosition(lookAtPoint + newLookVector); +} + +// Pans camera and returns the new look-at point +QVector3D GeneralHelper::panCamera(QQuick3DCamera *camera, const QMatrix4x4 startTransform, + const QVector3D &startPosition, const QVector3D &startLookAt, + const QVector3D &pressPos, const QVector3D ¤tPos, + float zoomFactor) +{ + QVector3D dragVector = currentPos - pressPos; + + if (dragVector.length() < 0.001f) + return startLookAt; + + const float *dataPtr(startTransform.data()); + const QVector3D xAxis = QVector3D(dataPtr[0], dataPtr[1], dataPtr[2]).normalized(); + const QVector3D yAxis = QVector3D(dataPtr[4], dataPtr[5], dataPtr[6]).normalized(); + const QVector3D xDelta = -1.f * xAxis * dragVector.x(); + const QVector3D yDelta = yAxis * dragVector.y(); + const QVector3D delta = (xDelta + yDelta) * zoomFactor; + + camera->setPosition(startPosition + delta); + return startLookAt + delta; +} + +float GeneralHelper::zoomCamera(QQuick3DCamera *camera, float distance, float defaultLookAtDistance, + const QVector3D &lookAt, float zoomFactor, bool relative) +{ + // Emprically determined divisor for nice zoom + float multiplier = 1.f + (distance / 40.f); + float newZoomFactor = relative ? qBound(.0001f, zoomFactor * multiplier, 10000.f) + : zoomFactor; + + if (qobject_cast<QQuick3DOrthographicCamera *>(camera)) { + // Ortho camera we can simply scale + camera->setScale(QVector3D(newZoomFactor, newZoomFactor, newZoomFactor)); + } else if (qobject_cast<QQuick3DPerspectiveCamera *>(camera)) { + // Perspective camera is zoomed by moving camera forward or backward while keeping the + // look-at point the same + const QVector3D lookAtVec = (camera->position() - lookAt).normalized(); + const float newDistance = defaultLookAtDistance * newZoomFactor; + camera->setPosition(lookAt + (lookAtVec * newDistance)); + } + + return newZoomFactor; +} + +// Return value contains new lookAt point (xyz) and zoom factor (w) +QVector4D GeneralHelper::fitObjectToCamera(QQuick3DCamera *camera, float defaultLookAtDistance, + QQuick3DNode *targetObject, QQuick3DViewport *viewPort) +{ + if (!camera) + return QVector4D(0.f, 0.f, 0.f, 1.f); + + QVector3D lookAt = targetObject ? targetObject->scenePosition() : QVector3D(); + + // Get object bounds + qreal maxExtent = 200.; + if (auto modelNode = qobject_cast<QQuick3DModel *>(targetObject)) { + auto targetPriv = QQuick3DObjectPrivate::get(targetObject); + if (auto renderModel = static_cast<QSSGRenderModel *>(targetPriv->spatialNode)) { + QWindow *window = static_cast<QWindow *>(viewPort->window()); + if (window) { + auto context = QSSGRenderContextInterface::getRenderContextInterface(quintptr(window)); + if (!context.isNull()) { + QSSGBounds3 bounds; + auto geometry = qobject_cast<SelectionBoxGeometry *>(modelNode->geometry()); + if (geometry) { + bounds = geometry->bounds(); + } else { + auto bufferManager = context->bufferManager(); + bounds = renderModel->getModelBounds(bufferManager); + } + + QVector3D center = bounds.center(); + const QVector3D e = bounds.extents(); + const QVector3D s = targetObject->sceneScale(); + qreal maxScale = qSqrt(qreal(s.x() * s.x() + s.y() * s.y() + s.z() * s.z())); + maxExtent = qSqrt(qreal(e.x() * e.x() + e.y() * e.y() + e.z() * e.z())); + maxExtent *= maxScale; + + // Adjust lookAt to look directly at the center of the object bounds + lookAt = renderModel->globalTransform.map(center); + lookAt.setZ(-lookAt.z()); // Render node transforms have inverted z + } + } + } + } + + // Reset camera position to default zoom + QMatrix4x4 m = camera->sceneTransform(); + const float *dataPtr(m.data()); + QVector3D newLookVector(-dataPtr[8], -dataPtr[9], -dataPtr[10]); + newLookVector.normalize(); + newLookVector *= defaultLookAtDistance; + + camera->setPosition(lookAt + newLookVector); + + // Emprically determined algorithm for nice zoom + float newZoomFactor = qBound(.0001f, float(maxExtent / 700.), 10000.f); + + return QVector4D(lookAt, + zoomCamera(camera, 0, defaultLookAtDistance, lookAt, newZoomFactor, false)); +} + +void GeneralHelper::delayedPropertySet(QObject *obj, int delay, const QString &property, + const QVariant &value) +{ + QTimer::singleShot(delay, [obj, property, value]() { + obj->setProperty(property.toLatin1().constData(), value); + }); +} + +} +} + +#endif // QUICK3D_MODULE diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.h b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.h new file mode 100644 index 0000000000..16007e6798 --- /dev/null +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** 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. +** +****************************************************************************/ + +#pragma once + +#ifdef QUICK3D_MODULE + +#include <QtCore/qobject.h> +#include <QtCore/qtimer.h> +#include <QtCore/qhash.h> +#include <QtGui/qvector3d.h> +#include <QtGui/qmatrix4x4.h> + +QT_BEGIN_NAMESPACE +class QQuick3DCamera; +class QQuick3DNode; +class QQuick3DViewport; +QT_END_NAMESPACE + +namespace QmlDesigner { +namespace Internal { + +class GeneralHelper : public QObject +{ + Q_OBJECT + +public: + GeneralHelper(); + + Q_INVOKABLE void requestOverlayUpdate(); + Q_INVOKABLE QString generateUniqueName(const QString &nameRoot); + + Q_INVOKABLE void orbitCamera(QQuick3DCamera *camera, const QVector3D &startRotation, + const QVector3D &lookAtPoint, const QVector3D &pressPos, + const QVector3D ¤tPos); + Q_INVOKABLE QVector3D panCamera(QQuick3DCamera *camera, const QMatrix4x4 startTransform, + const QVector3D &startPosition, const QVector3D &startLookAt, + const QVector3D &pressPos, const QVector3D ¤tPos, + float zoomFactor); + Q_INVOKABLE float zoomCamera(QQuick3DCamera *camera, float distance, + float defaultLookAtDistance, const QVector3D &lookAt, + float zoomFactor, bool relative); + Q_INVOKABLE QVector4D fitObjectToCamera(QQuick3DCamera *camera, float defaultLookAtDistance, + QQuick3DNode *targetObject, QQuick3DViewport *viewPort); + Q_INVOKABLE void delayedPropertySet(QObject *obj, int delay, const QString &property, + const QVariant& value); + +signals: + void overlayUpdateNeeded(); + +private: + QTimer m_overlayUpdateTimer; +}; + +} +} + +#endif // QUICK3D_MODULE diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/mousearea3d.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/mousearea3d.cpp index 31ed661125..d571b24dcb 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/mousearea3d.cpp +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/mousearea3d.cpp @@ -37,7 +37,6 @@ namespace QmlDesigner { namespace Internal { MouseArea3D *MouseArea3D::s_mouseGrab = nullptr; -static const qreal s_mouseDragMultiplier = .02; MouseArea3D::MouseArea3D(QQuick3DNode *parent) : QQuick3DNode(parent) @@ -124,6 +123,13 @@ void MouseArea3D::setGrabsMouse(bool grabsMouse) return; m_grabsMouse = grabsMouse; + + if (!m_grabsMouse && s_mouseGrab == this) { + setDragging(false); + setHovering(false); + s_mouseGrab = nullptr; + } + emit grabsMouseChanged(); } @@ -133,6 +139,13 @@ void MouseArea3D::setActive(bool active) return; m_active = active; + + if (!m_active && s_mouseGrab == this) { + setDragging(false); + setHovering(false); + s_mouseGrab = nullptr; + } + emit activeChanged(); } @@ -340,7 +353,7 @@ qreal QmlDesigner::Internal::MouseArea3D::getNewRotationAngle( dragDir = (screenDragDir - nodePos).normalized(); const QVector3D pressToCurrent = (currentPos - pressPos); float magnitude = QVector3D::dotProduct(pressToCurrent, dragDir); - qreal angle = -s_mouseDragMultiplier * qreal(magnitude); + qreal angle = -mouseDragMultiplier() * qreal(magnitude); return angle; } else { const QVector3D nodeToPress = (pressPos - nodePos).normalized(); @@ -397,7 +410,7 @@ void MouseArea3D::applyFreeRotation(QQuick3DNode *node, const QVector3D &startRo QVector3D finalAxis = (dragVector.x() * yAxis + dragVector.y() * xAxis); - qreal degrees = qRadiansToDegrees(qreal(finalAxis.length()) * s_mouseDragMultiplier); + qreal degrees = qRadiansToDegrees(qreal(finalAxis.length()) * mouseDragMultiplier()); finalAxis.normalize(); diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/mousearea3d.h b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/mousearea3d.h index e227b3f9dd..c824b92969 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/mousearea3d.h +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/mousearea3d.h @@ -51,7 +51,7 @@ class MouseArea3D : public QQuick3DNode Q_PROPERTY(bool hovering READ hovering NOTIFY hoveringChanged) Q_PROPERTY(bool dragging READ dragging NOTIFY draggingChanged) Q_PROPERTY(int priority READ priority WRITE setPriority NOTIFY priorityChanged) - Q_PROPERTY(int active READ active WRITE setActive NOTIFY activeChanged) + Q_PROPERTY(bool active READ active WRITE setActive NOTIFY activeChanged) Q_PROPERTY(QPointF circlePickArea READ circlePickArea WRITE setCirclePickArea NOTIFY circlePickAreaChanged) Q_PROPERTY(qreal minAngle READ minAngle WRITE setMinAngle NOTIFY minAngleChanged) Q_PROPERTY(QQuick3DNode *pickNode READ pickNode WRITE setPickNode NOTIFY pickNodeChanged) @@ -77,6 +77,8 @@ public: qreal minAngle() const; QQuick3DNode *pickNode() const; + static qreal mouseDragMultiplier() { return .02; } + public slots: void setView3D(QQuick3DViewport *view3D); void setGrabsMouse(bool grabsMouse); @@ -157,7 +159,7 @@ private: QVector3D getMousePosInPlane(const QPointF &mousePosInView) const; static MouseArea3D *s_mouseGrab; - bool m_grabsMouse; + bool m_grabsMouse = false; QVector3D m_mousePosInPlane; QPointF m_circlePickArea; qreal m_minAngle = 0.; diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/selectionboxgeometry.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/selectionboxgeometry.cpp new file mode 100644 index 0000000000..7770061923 --- /dev/null +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/selectionboxgeometry.cpp @@ -0,0 +1,336 @@ +/**************************************************************************** +** +** 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. +** +****************************************************************************/ + +#ifdef QUICK3D_MODULE + +#include "selectionboxgeometry.h" + +#include <QtQuick3DRuntimeRender/private/qssgrendergeometry_p.h> +#include <QtQuick3DRuntimeRender/private/qssgrendermodel_p.h> +#include <QtQuick3DRuntimeRender/private/qssgrendercontextcore_p.h> +#include <QtQuick3DRuntimeRender/private/qssgrenderbuffermanager_p.h> +#include <QtQuick3D/private/qquick3dmodel_p.h> +#include <QtQuick3D/private/qquick3dobject_p_p.h> +#include <QtQuick/qquickwindow.h> +#include <QtCore/qvector.h> + +#include <limits> + +namespace QmlDesigner { +namespace Internal { + +SelectionBoxGeometry::SelectionBoxGeometry() + : QQuick3DGeometry() +{ +} + +SelectionBoxGeometry::~SelectionBoxGeometry() +{ + for (auto &connection : qAsConst(m_connections)) + QObject::disconnect(connection); + m_connections.clear(); +} + +QQuick3DNode *SelectionBoxGeometry::targetNode() const +{ + return m_targetNode; +} + +QQuick3DNode *SelectionBoxGeometry::rootNode() const +{ + return m_rootNode; +} + +QQuick3DViewport *SelectionBoxGeometry::view3D() const +{ + return m_view3D; +} + +bool QmlDesigner::Internal::SelectionBoxGeometry::isEmpty() const +{ + return m_isEmpty; +} + +QSSGBounds3 SelectionBoxGeometry::bounds() const +{ + return m_bounds; +} + +void SelectionBoxGeometry::setTargetNode(QQuick3DNode *targetNode) +{ + if (m_targetNode == targetNode) + return; + + if (m_targetNode) + m_targetNode->disconnect(this); + m_targetNode = targetNode; + + if (auto model = qobject_cast<QQuick3DModel *>(m_targetNode)) { + QObject::connect(model, &QQuick3DModel::sourceChanged, + this, &SelectionBoxGeometry::update, Qt::QueuedConnection); + QObject::connect(model, &QQuick3DModel::geometryChanged, + this, &SelectionBoxGeometry::update, Qt::QueuedConnection); + } + + emit targetNodeChanged(); + update(); +} + +void SelectionBoxGeometry::setRootNode(QQuick3DNode *rootNode) +{ + if (m_rootNode == rootNode) + return; + + m_rootNode = rootNode; + + emit rootNodeChanged(); + update(); +} + +void SelectionBoxGeometry::setView3D(QQuick3DViewport *view) +{ + if (m_view3D == view) + return; + + m_view3D = view; + + emit view3DChanged(); + update(); +} + +QSSGRenderGraphObject *SelectionBoxGeometry::updateSpatialNode(QSSGRenderGraphObject *node) +{ + node = QQuick3DGeometry::updateSpatialNode(node); + QSSGRenderGeometry *geometry = static_cast<QSSGRenderGeometry *>(node); + + geometry->clear(); + for (auto &connection : qAsConst(m_connections)) + QObject::disconnect(connection); + m_connections.clear(); + + QByteArray vertexData; + QByteArray indexData; + + static const float floatMin = std::numeric_limits<float>::lowest(); + static const float floatMax = std::numeric_limits<float>::max(); + + QVector3D minBounds = QVector3D(floatMax, floatMax, floatMax); + QVector3D maxBounds = QVector3D(floatMin, floatMin, floatMin); + + if (m_targetNode) { + auto rootPriv = QQuick3DObjectPrivate::get(m_rootNode); + auto targetPriv = QQuick3DObjectPrivate::get(m_targetNode); + auto rootRN = static_cast<QSSGRenderNode *>(rootPriv->spatialNode); + auto targetRN = static_cast<QSSGRenderNode *>(targetPriv->spatialNode); + if (rootRN && targetRN) { + // Explicitly set local transform of root node to target node parent's global transform + // to avoid having to reparent the selection box. This has to be done directly on render + // nodes. + targetRN->parent->calculateGlobalVariables(); + QMatrix4x4 m = targetRN->parent->globalTransform; + rootRN->localTransform = m; + rootRN->markDirty(QSSGRenderNode::TransformDirtyFlag::TransformNotDirty); + rootRN->calculateGlobalVariables(); + } + getBounds(m_targetNode, vertexData, indexData, minBounds, maxBounds, QMatrix4x4()); + } else { + // Fill some dummy data so geometry won't get rejected + appendVertexData(vertexData, indexData, minBounds, maxBounds); + } + + geometry->addAttribute(QSSGRenderGeometry::Attribute::PositionSemantic, 0, + QSSGRenderGeometry::Attribute::ComponentType::F32Type); + geometry->addAttribute(QSSGRenderGeometry::Attribute::IndexSemantic, 0, + QSSGRenderGeometry::Attribute::ComponentType::U16Type); + geometry->setStride(12); + geometry->setVertexData(vertexData); + geometry->setIndexData(indexData); + geometry->setPrimitiveType(QSSGRenderGeometry::Lines); + geometry->setBounds(minBounds, maxBounds); + + m_bounds = QSSGBounds3(minBounds, maxBounds); + + bool empty = minBounds.isNull() && maxBounds.isNull(); + if (m_isEmpty != empty) { + m_isEmpty = empty; + // Delay notification until we're done with spatial node updates + QTimer::singleShot(0, this, &SelectionBoxGeometry::isEmptyChanged); + } + + return node; +} + +void SelectionBoxGeometry::getBounds(QQuick3DNode *node, QByteArray &vertexData, + QByteArray &indexData, QVector3D &minBounds, + QVector3D &maxBounds, const QMatrix4x4 &transform) +{ + QMatrix4x4 fullTransform; + auto nodePriv = QQuick3DObjectPrivate::get(node); + auto renderNode = static_cast<QSSGRenderNode *>(nodePriv->spatialNode); + + // All transforms are relative to targetNode transform, so its local transform is ignored + if (node != m_targetNode) { + if (renderNode) { + if (renderNode->flags.testFlag(QSSGRenderNode::Flag::TransformDirty)) + renderNode->calculateLocalTransform(); + fullTransform = transform * renderNode->localTransform; + } + + m_connections << QObject::connect(node, &QQuick3DNode::scaleChanged, + this, &SelectionBoxGeometry::update, Qt::QueuedConnection); + m_connections << QObject::connect(node, &QQuick3DNode::rotationChanged, + this, &SelectionBoxGeometry::update, Qt::QueuedConnection); + m_connections << QObject::connect(node, &QQuick3DNode::positionChanged, + this, &SelectionBoxGeometry::update, Qt::QueuedConnection); + m_connections << QObject::connect(node, &QQuick3DNode::pivotChanged, + this, &SelectionBoxGeometry::update, Qt::QueuedConnection); + m_connections << QObject::connect(node, &QQuick3DNode::orientationChanged, + this, &SelectionBoxGeometry::update, Qt::QueuedConnection); + m_connections << QObject::connect(node, &QQuick3DNode::rotationOrderChanged, + this, &SelectionBoxGeometry::update, Qt::QueuedConnection); + } + + QVector<QVector3D> minBoundsVec; + QVector<QVector3D> maxBoundsVec; + + // Check for children + const auto children = node->childItems(); + for (const auto child : children) { + if (auto childNode = qobject_cast<QQuick3DNode *>(child)) { + QVector3D newMinBounds = minBounds; + QVector3D newMaxBounds = maxBounds; + getBounds(childNode, vertexData, indexData, newMinBounds, newMaxBounds, fullTransform); + minBoundsVec << newMinBounds; + maxBoundsVec << newMaxBounds; + } + } + + // Combine all child bounds + for (const auto &newBounds : qAsConst(minBoundsVec)) { + minBounds.setX(qMin(newBounds.x(), minBounds.x())); + minBounds.setY(qMin(newBounds.y(), minBounds.y())); + minBounds.setZ(qMin(newBounds.z(), minBounds.z())); + } + for (const auto &newBounds : qAsConst(maxBoundsVec)) { + maxBounds.setX(qMax(newBounds.x(), maxBounds.x())); + maxBounds.setY(qMax(newBounds.y(), maxBounds.y())); + maxBounds.setZ(qMax(newBounds.z(), maxBounds.z())); + } + + if (auto modelNode = qobject_cast<QQuick3DModel *>(node)) { + if (auto renderModel = static_cast<QSSGRenderModel *>(renderNode)) { + QWindow *window = static_cast<QWindow *>(m_view3D->window()); + if (window) { + auto context = QSSGRenderContextInterface::getRenderContextInterface( + quintptr(window)); + if (!context.isNull()) { + auto bufferManager = context->bufferManager(); + QSSGBounds3 bounds = renderModel->getModelBounds(bufferManager); + QVector3D center = bounds.center(); + QVector3D extents = bounds.extents(); + QVector3D localMin = center - extents; + QVector3D localMax = center + extents; + + // Transform all corners of the local bounding box to find final extent in + // in parent space + + auto checkCorner = [&minBounds, &maxBounds, &fullTransform] + (const QVector3D &corner) { + QVector3D mappedCorner = fullTransform.map(corner); + minBounds.setX(qMin(mappedCorner.x(), minBounds.x())); + minBounds.setY(qMin(mappedCorner.y(), minBounds.y())); + minBounds.setZ(qMin(mappedCorner.z(), minBounds.z())); + maxBounds.setX(qMax(mappedCorner.x(), maxBounds.x())); + maxBounds.setY(qMax(mappedCorner.y(), maxBounds.y())); + maxBounds.setZ(qMax(mappedCorner.z(), maxBounds.z())); + }; + + checkCorner(localMin); + checkCorner(localMax); + checkCorner(QVector3D(localMin.x(), localMin.y(), localMax.z())); + checkCorner(QVector3D(localMin.x(), localMax.y(), localMin.z())); + checkCorner(QVector3D(localMax.x(), localMin.y(), localMin.z())); + checkCorner(QVector3D(localMin.x(), localMax.y(), localMax.z())); + checkCorner(QVector3D(localMax.x(), localMax.y(), localMin.z())); + checkCorner(QVector3D(localMax.x(), localMin.y(), localMax.z())); + } + } + } + } + + // Target node and immediate children get selection boxes + if (transform.isIdentity()) { + // Adjust bounds to reduce targetNode pixels obscuring the selection box + QVector3D extents = (maxBounds - minBounds) / 1000.f; + QVector3D minAdjBounds = minBounds - extents; + QVector3D maxAdjBounds = maxBounds + extents; + + appendVertexData(vertexData, indexData, minAdjBounds, maxAdjBounds); + } +} + +void SelectionBoxGeometry::appendVertexData(QByteArray &vertexData, QByteArray &indexData, + const QVector3D &minBounds, const QVector3D &maxBounds) +{ + int initialVertexSize = vertexData.size(); + int initialIndexSize = indexData.size(); + const int vertexSize = int(sizeof(float)) * 8 * 3; // 8 vertices, 3 floats/vert + quint16 indexAdd = quint16(initialVertexSize / 12); + vertexData.resize(initialVertexSize + vertexSize); + const int indexSize = int(sizeof(quint16)) * 12 * 2; // 12 lines, 2 vert/line + indexData.resize(initialIndexSize + indexSize); + + auto dataPtr = reinterpret_cast<float *>(vertexData.data() + initialVertexSize); + auto indexPtr = reinterpret_cast<quint16 *>(indexData.data() + initialIndexSize); + + *dataPtr++ = maxBounds.x(); *dataPtr++ = maxBounds.y(); *dataPtr++ = maxBounds.z(); + *dataPtr++ = minBounds.x(); *dataPtr++ = maxBounds.y(); *dataPtr++ = maxBounds.z(); + *dataPtr++ = minBounds.x(); *dataPtr++ = minBounds.y(); *dataPtr++ = maxBounds.z(); + *dataPtr++ = maxBounds.x(); *dataPtr++ = minBounds.y(); *dataPtr++ = maxBounds.z(); + *dataPtr++ = maxBounds.x(); *dataPtr++ = maxBounds.y(); *dataPtr++ = minBounds.z(); + *dataPtr++ = minBounds.x(); *dataPtr++ = maxBounds.y(); *dataPtr++ = minBounds.z(); + *dataPtr++ = minBounds.x(); *dataPtr++ = minBounds.y(); *dataPtr++ = minBounds.z(); + *dataPtr++ = maxBounds.x(); *dataPtr++ = minBounds.y(); *dataPtr++ = minBounds.z(); + + *indexPtr++ = 0 + indexAdd; *indexPtr++ = 1 + indexAdd; + *indexPtr++ = 1 + indexAdd; *indexPtr++ = 2 + indexAdd; + *indexPtr++ = 2 + indexAdd; *indexPtr++ = 3 + indexAdd; + *indexPtr++ = 3 + indexAdd; *indexPtr++ = 0 + indexAdd; + + *indexPtr++ = 0 + indexAdd; *indexPtr++ = 4 + indexAdd; + *indexPtr++ = 1 + indexAdd; *indexPtr++ = 5 + indexAdd; + *indexPtr++ = 2 + indexAdd; *indexPtr++ = 6 + indexAdd; + *indexPtr++ = 3 + indexAdd; *indexPtr++ = 7 + indexAdd; + + *indexPtr++ = 4 + indexAdd; *indexPtr++ = 5 + indexAdd; + *indexPtr++ = 5 + indexAdd; *indexPtr++ = 6 + indexAdd; + *indexPtr++ = 6 + indexAdd; *indexPtr++ = 7 + indexAdd; + *indexPtr++ = 7 + indexAdd; *indexPtr++ = 4 + indexAdd; +} + +} +} + +#endif // QUICK3D_MODULE diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/selectionboxgeometry.h b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/selectionboxgeometry.h new file mode 100644 index 0000000000..08a28cec06 --- /dev/null +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/selectionboxgeometry.h @@ -0,0 +1,90 @@ +/**************************************************************************** +** +** 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. +** +****************************************************************************/ + +#pragma once + +#ifdef QUICK3D_MODULE + +#include <QtQuick3D/private/qquick3dnode_p.h> +#include <QtQuick3D/private/qquick3dgeometry_p.h> +#include <QtQuick3D/private/qquick3dviewport_p.h> +#include <QtQuick3DUtils/private/qssgbounds3_p.h> + +namespace QmlDesigner { +namespace Internal { + +class SelectionBoxGeometry : public QQuick3DGeometry +{ + Q_OBJECT + Q_PROPERTY(QQuick3DNode *targetNode READ targetNode WRITE setTargetNode NOTIFY targetNodeChanged) + Q_PROPERTY(QQuick3DNode *rootNode READ rootNode WRITE setRootNode NOTIFY rootNodeChanged) + Q_PROPERTY(QQuick3DViewport *view3D READ view3D WRITE setView3D NOTIFY view3DChanged) + Q_PROPERTY(bool isEmpty READ isEmpty NOTIFY isEmptyChanged) + +public: + SelectionBoxGeometry(); + ~SelectionBoxGeometry() override; + + QQuick3DNode *targetNode() const; + QQuick3DNode *rootNode() const; + QQuick3DViewport *view3D() const; + bool isEmpty() const; + + QSSGBounds3 bounds() const; + +public Q_SLOTS: + void setTargetNode(QQuick3DNode *targetNode); + void setRootNode(QQuick3DNode *rootNode); + void setView3D(QQuick3DViewport *view); + +Q_SIGNALS: + void targetNodeChanged(); + void rootNodeChanged(); + void view3DChanged(); + void isEmptyChanged(); + +protected: + QSSGRenderGraphObject *updateSpatialNode(QSSGRenderGraphObject *node) override; + +private: + void getBounds(QQuick3DNode *node, QByteArray &vertexData, QByteArray &indexData, + QVector3D &minBounds, QVector3D &maxBounds, const QMatrix4x4 &transform); + void appendVertexData(QByteArray &vertexData, QByteArray &indexData, + const QVector3D &minBounds, const QVector3D &maxBounds); + + QQuick3DNode *m_targetNode = nullptr; + QQuick3DViewport *m_view3D = nullptr; + QQuick3DNode *m_rootNode = nullptr; + bool m_isEmpty = true; + QVector<QMetaObject::Connection> m_connections; + QSSGBounds3 m_bounds; +}; + +} +} + +QML_DECLARE_TYPE(QmlDesigner::Internal::SelectionBoxGeometry) + +#endif // QUICK3D_MODULE diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp index 2cd59af460..95360eaa4f 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp @@ -62,10 +62,11 @@ #include <drop3dlibraryitemcommand.h> #include "dummycontextobject.h" -#include "../editor3d/cameracontrolhelper.h" +#include "../editor3d/generalhelper.h" #include "../editor3d/mousearea3d.h" #include "../editor3d/camerageometry.h" #include "../editor3d/gridgeometry.h" +#include "../editor3d/selectionboxgeometry.h" #include <designersupportdelegate.h> @@ -104,13 +105,13 @@ bool Qt5InformationNodeInstanceServer::eventFilter(QObject *, QEvent *event) QObject *Qt5InformationNodeInstanceServer::createEditView3D(QQmlEngine *engine) { - auto helper = new QmlDesigner::Internal::CameraControlHelper(); - engine->rootContext()->setContextProperty("designStudioNativeCameraControlHelper", helper); - #ifdef QUICK3D_MODULE + auto helper = new QmlDesigner::Internal::GeneralHelper(); + engine->rootContext()->setContextProperty("_generalHelper", helper); qmlRegisterType<QmlDesigner::Internal::MouseArea3D>("MouseArea3D", 1, 0, "MouseArea3D"); qmlRegisterType<QmlDesigner::Internal::CameraGeometry>("CameraGeometry", 1, 0, "CameraGeometry"); qmlRegisterType<QmlDesigner::Internal::GridGeometry>("GridGeometry", 1, 0, "GridGeometry"); + qmlRegisterType<QmlDesigner::Internal::SelectionBoxGeometry>("SelectionBoxGeometry", 1, 0, "SelectionBoxGeometry"); #endif QQmlComponent component(engine, QUrl("qrc:/qtquickplugin/mockfiles/EditView3D.qml")); @@ -136,7 +137,10 @@ QObject *Qt5InformationNodeInstanceServer::createEditView3D(QQmlEngine *engine) surfaceFormat.setVersion(4, 1); surfaceFormat.setProfile(QSurfaceFormat::CoreProfile); window->setFormat(surfaceFormat); + +#ifdef QUICK3D_MODULE helper->setParent(window); +#endif return window; } @@ -336,12 +340,24 @@ QObject *Qt5InformationNodeInstanceServer::findRootNodeOf3DViewport( { for (const ServerNodeInstance &instance : instanceList) { if (instance.isSubclassOf("QQuick3DViewport")) { + QObject *rootObj = nullptr; + int viewChildCount = 0; for (const ServerNodeInstance &child : instanceList) { /* Look for scene node */ /* The QQuick3DViewport always creates a root node. * This root node contains the complete scene. */ - if (child.isSubclassOf("QQuick3DNode") && child.parent() == instance) - return child.internalObject()->property("parent").value<QObject *>(); + if (child.isSubclassOf("QQuick3DNode") && child.parent() == instance) { + // Implicit root node is not visible in editor, so there is often another node + // added below it that serves as the actual scene root node. + // If the found root is the only node child of the view, assume that is the case. + ++viewChildCount; + if (!rootObj) + rootObj = child.internalObject(); + } } + if (viewChildCount == 1) + return rootObj; + else if (rootObj) + return rootObj->property("parent").value<QObject *>(); } } return nullptr; @@ -599,10 +615,8 @@ void Qt5InformationNodeInstanceServer::changeSelection(const ChangeSelectionComm if (hasInstanceForId(id)) { ServerNodeInstance instance = instanceForId(id); QObject *object = nullptr; - if (instance.isSubclassOf("QQuick3DModel") || instance.isSubclassOf("QQuick3DCamera") - || instance.isSubclassOf("QQuick3DAbstractLight")) { + if (instance.isSubclassOf("QQuick3DNode")) object = instance.internalObject(); - } QMetaObject::invokeMethod(m_editView3D, "selectObject", Q_ARG(QVariant, objectToVariant(object))); return; // TODO: support multi-selection diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3dnodeinstance.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3dnodeinstance.cpp index 61b21b7810..db0f0f847f 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3dnodeinstance.cpp +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3dnodeinstance.cpp @@ -56,17 +56,7 @@ void Quick3DNodeInstance::initialize(const ObjectNodeInstance::Pointer &objectNo InstanceContainer::NodeFlags flags) { ObjectNodeInstance::initialize(objectNodeInstance, flags); - -#ifdef QUICK3D_MODULE - if (quick3DNode()) { - QQuick3DObject::Type nodeType = quick3DNode()->type(); - if (nodeType == QQuick3DObject::Camera || nodeType == QQuick3DObject::Light - || nodeType == QQuick3DObject::Model || nodeType == QQuick3DObject::Image - || nodeType == QQuick3DObject::Text) { - setPropertyVariant("pickable", true); // allow 3D objects to receive mouse clicks - } - } -#endif + setPickable(true, true, false); } Qt5NodeInstanceServer *Quick3DNodeInstance::qt5NodeInstanceServer() const @@ -83,6 +73,48 @@ QQuick3DNode *Quick3DNodeInstance::quick3DNode() const #endif } +void Quick3DNodeInstance::setPickable(bool enable, bool checkParent, bool applyToChildren) +{ +#ifdef QUICK3D_MODULE + auto node = quick3DNode(); + if (node) { + QQuick3DObject::Type nodeType = node->type(); + bool parentHidden = false; + if (checkParent) { + // First check if any parent node is already hidden. Never set pickable on that case. + auto parentNode = node->parentNode(); + while (parentNode && !parentHidden) { + parentHidden = QQuick3DNodePrivate::get(parentNode)->m_isHiddenInEditor; + parentNode = parentNode->parentNode(); + } + + } + if (!parentHidden) { + if (applyToChildren) { + auto getQuick3DInstance = [this](QQuick3DObject *obj) -> Quick3DNodeInstance * { + if (nodeInstanceServer()->hasInstanceForObject(obj)) { + ServerNodeInstance instance = nodeInstanceServer()->instanceForObject(obj); + if (instance.isValid() && qobject_cast<QQuick3DNode *>(instance.internalObject())) + return static_cast<Quick3DNodeInstance *>(instance.internalInstance().data()); + } + return nullptr; + }; + const auto childItems = node->childItems(); + for (auto childItem : childItems) { + if (auto quick3dInstance = getQuick3DInstance(childItem)) { + // Don't override explicit block in children + if (!QQuick3DNodePrivate::get(quick3dInstance->quick3DNode())->m_isHiddenInEditor) + quick3dInstance->setPickable(enable, false, true); + } + } + } + if (nodeType == QQuick3DObject::Model) + setPropertyVariant("pickable", enable); // allow 3D objects to receive mouse clicks + } + } +#endif +} + Quick3DNodeInstance::Pointer Quick3DNodeInstance::create(QObject *object) { Pointer instance(new Quick3DNodeInstance(object)); @@ -94,8 +126,12 @@ void Quick3DNodeInstance::setHideInEditor(bool b) { #ifdef QUICK3D_MODULE QQuick3DNodePrivate *privateNode = QQuick3DNodePrivate::get(quick3DNode()); - if (privateNode) + if (privateNode) { privateNode->setIsHiddenInEditor(b); + + // Hidden objects should not be pickable + setPickable(!b, true, true); + } #else Q_UNUSED(b) #endif diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3dnodeinstance.h b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3dnodeinstance.h index 96c44c4d52..27e2488eb3 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3dnodeinstance.h +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3dnodeinstance.h @@ -53,6 +53,7 @@ protected: private: Qt5NodeInstanceServer *qt5NodeInstanceServer() const; QQuick3DNode *quick3DNode() const; + void setPickable(bool enable, bool checkParent, bool applyToChildren); }; } // namespace Internal diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/servernodeinstance.h b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/servernodeinstance.h index 86003b51b6..c85ba9a2b8 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/servernodeinstance.h +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/servernodeinstance.h @@ -60,6 +60,7 @@ namespace Internal { class GraphicsObjectNodeInstance; class QmlStateNodeInstance; class QuickItemNodeInstance; + class Quick3DNodeInstance; } class ServerNodeInstance @@ -82,6 +83,7 @@ class ServerNodeInstance friend class QmlDesigner::Internal::ObjectNodeInstance; friend class QmlDesigner::Internal::QmlPropertyChangesNodeInstance; friend class QmlDesigner::Internal::QmlStateNodeInstance; + friend class QmlDesigner::Internal::Quick3DNodeInstance; public: enum ComponentWrap { diff --git a/share/qtcreator/qml/qmlpuppet/qmlpuppet.qrc b/share/qtcreator/qml/qmlpuppet/qmlpuppet.qrc index f818f23fd5..c4a49064b6 100644 --- a/share/qtcreator/qml/qmlpuppet/qmlpuppet.qrc +++ b/share/qtcreator/qml/qmlpuppet/qmlpuppet.qrc @@ -8,6 +8,7 @@ <file>mockfiles/GenericBackend.qml</file> <file>mockfiles/Dialog.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> @@ -23,12 +24,17 @@ <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/SelectionBox.qml</file> + <file>mockfiles/AxisHelper.qml</file> + <file>mockfiles/AxisHelperArm.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/light-pick-icon.png</file> @@ -53,5 +59,27 @@ <file>mockfiles/images/scale_active@2x.png</file> <file>mockfiles/images/scale_selected.png</file> <file>mockfiles/images/scale_selected@2x.png</file> + <file>mockfiles/images/directional_light_gradient.png</file> + <file>mockfiles/images/directional_light_gradient@2x.png</file> + <file>mockfiles/images/point_light_gradient.png</file> + <file>mockfiles/images/point_light_gradient@2x.png</file> + <file>mockfiles/images/area_light_gradient.png</file> + <file>mockfiles/images/area_light_gradient@2x.png</file> + <file>mockfiles/images/fit_active.png</file> + <file>mockfiles/images/fit_active@2x.png</file> + <file>mockfiles/images/fit_selected.png</file> + <file>mockfiles/images/fit_selected@2x.png</file> + <file>mockfiles/images/local.png</file> + <file>mockfiles/images/local@2x.png</file> + <file>mockfiles/images/global.png</file> + <file>mockfiles/images/global@2x.png</file> + <file>mockfiles/images/ortho.png</file> + <file>mockfiles/images/ortho@2x.png</file> + <file>mockfiles/images/persp.png</file> + <file>mockfiles/images/persp@2x.png</file> + <file>mockfiles/images/edit_light_off.png</file> + <file>mockfiles/images/edit_light_off@2x.png</file> + <file>mockfiles/images/edit_light_on.png</file> + <file>mockfiles/images/edit_light_on@2x.png</file> </qresource> </RCC> |