diff --git a/meshroom/ui/qml/Viewer/DefaultCameraController.qml b/meshroom/ui/qml/Viewer/DefaultCameraController.qml new file mode 100644 index 00000000..b3819e54 --- /dev/null +++ b/meshroom/ui/qml/Viewer/DefaultCameraController.qml @@ -0,0 +1,140 @@ +import QtQuick 2.7 +import Qt3D.Core 2.1 +import Qt3D.Render 2.1 +import Qt3D.Input 2.1 +import Qt3D.Logic 2.0 +import QtQml 2.2 + +Entity { + id: root + + property Camera camera + property real translateSpeed: 75.0 + property real tiltSpeed: 500.0 + property real panSpeed: 500.0 + property bool moving: pressed || actionAlt.active + readonly property alias controlPressed: actionControl.active + + readonly property alias pressed: mouseHandler._pressed + signal mousePressed(var mouse) + signal mouseReleased(var mouse) + signal mouseClicked(var mouse) + signal mouseWheeled(var wheel) + signal mouseDoubleClicked(var mouse) + + KeyboardDevice { id: keyboardSourceDevice } + MouseDevice { id: mouseSourceDevice } + + MouseHandler { + id: mouseHandler + property bool _pressed + sourceDevice: mouseSourceDevice + onPressed: { _pressed = true; mousePressed(mouse) } + onReleased: { _pressed = false; mouseReleased(mouse) } + onClicked: mouseClicked(mouse) + onDoubleClicked: mouseDoubleClicked(mouse) + onWheel: { + var d = (root.camera.viewCenter.minus(root.camera.position)).length() * 0.2; + var tz = (wheel.angleDelta.y / 120) * d; + root.camera.translate(Qt.vector3d(0, 0, tz), Camera.DontTranslateViewCenter) + } + } + + LogicalDevice { + id: cameraControlDevice + actions: [ + Action { + id: actionLMB + inputs: [ + ActionInput { + sourceDevice: mouseSourceDevice + buttons: [MouseEvent.LeftButton] + } + ] + }, + Action { + id: actionRMB + inputs: [ + ActionInput { + sourceDevice: mouseSourceDevice + buttons: [MouseEvent.RightButton] + } + ] + }, + Action { + id: actionMMB + inputs: [ + ActionInput { + sourceDevice: mouseSourceDevice + buttons: [MouseEvent.MiddleButton] + } + ] + }, + Action { + id: actionControl + inputs: [ + ActionInput { + sourceDevice: keyboardSourceDevice + buttons: [Qt.Key_Control] + } + ] + }, + Action { + id: actionAlt + inputs: [ + ActionInput { + sourceDevice: keyboardSourceDevice + buttons: [Qt.Key_Alt] + } + ] + } + ] + axes: [ + Axis { + id: axisMX + inputs: [ + AnalogAxisInput { + sourceDevice: mouseSourceDevice + axis: MouseDevice.X + } + ] + }, + Axis { + id: axisMY + inputs: [ + AnalogAxisInput { + sourceDevice: mouseSourceDevice + axis: MouseDevice.Y + } + ] + } + ] + } + + components: [ + FrameAction { + onTriggered: { + if(actionLMB.active) { // rotate + var rx = -axisMX.value; + var ry = -axisMY.value; + root.camera.panAboutViewCenter(root.panSpeed * rx * dt, Qt.vector3d(0,1,0)) + root.camera.tiltAboutViewCenter(root.tiltSpeed * ry * dt) + return; + } + if(actionMMB.active) { // translate + var d = (root.camera.viewCenter.minus(root.camera.position)).length() * 0.03; + var tx = axisMX.value * root.translateSpeed * d; + var ty = axisMY.value * root.translateSpeed * d; + root.camera.translate(Qt.vector3d(-tx, -ty, 0).times(dt)) + return; + } + if(actionAlt.active && actionRMB.active) { // zoom with alt + RMD + var d = (root.camera.viewCenter.minus(root.camera.position)).length() * 0.1; + var tz = axisMX.value * root.translateSpeed * d; + root.camera.translate(Qt.vector3d(0, 0, tz).times(dt), Camera.DontTranslateViewCenter) + return; + } + } + } + ] +} diff --git a/meshroom/ui/qml/Viewer/Viewer3D.qml b/meshroom/ui/qml/Viewer/Viewer3D.qml index 7ad0f0c5..926249e5 100644 --- a/meshroom/ui/qml/Viewer/Viewer3D.qml +++ b/meshroom/ui/qml/Viewer/Viewer3D.qml @@ -98,32 +98,42 @@ FocusScope { } } - MayaCameraController { + DefaultCameraController { id: cameraController camera: mainCamera onMousePressed: { - mouse.accepted = false scene3D.forceActiveFocus() + if(mouse.button == Qt.LeftButton) + { + if(!doubleClickTimer.running) + doubleClickTimer.restart() + } + else + doubleClickTimer.stop() } onMouseReleased: { if(moving) - return; - switch(mouse.button) { - case Qt.LeftButton: - break; - case Qt.RightButton: - contextMenu.x = mouse.x; - contextMenu.y = mouse.y; - contextMenu.open(); - break; + return + if(mouse.button == Qt.RightButton) + { + contextMenu.popup() } } + + // Manually handle double click to activate object picking + // for camera re-centering only during a short amount of time + Timer { + id: doubleClickTimer + running: false + interval: 300 + } } components: [ RenderSettings { - // To avoid performance drop, only pick triangles when not moving the camera - pickingSettings.pickMethod: cameraController.moving ? PickingSettings.BoundingVolumePicking : PickingSettings.TrianglePicking + // To avoid performance drops, picking is only enabled under certain circumstances (see ObjectPicker below) + pickingSettings.pickMethod: PickingSettings.TrianglePicking + pickingSettings.pickResultMode: PickingSettings.NearestPick renderPolicy: RenderSettings.Always activeFrameGraph: Viewport { normalizedRect: Qt.rect(0.0, 0.0, 1.0, 1.0) @@ -156,23 +166,17 @@ FocusScope { components: [scene, transform, picker] + // ObjectPicker used for view re-centering ObjectPicker { id: picker + // Triangle picking is expensive + // Only activate it when a double click may happen or when the 'Control' key is pressed + enabled: cameraController.controlPressed || doubleClickTimer.running hoverEnabled: false onPressed: { - if(Qt.LeftButton & pick.buttons) - { - if(!doubleClickTimer.running) - doubleClickTimer.start() - else - mainCamera.viewCenter = pick.worldIntersection - } - } - - Timer { - id: doubleClickTimer - running: false - interval: 400 + if(pick.button == Qt.LeftButton) + mainCamera.viewCenter = pick.worldIntersection + doubleClickTimer.stop() } } @@ -239,7 +243,7 @@ FocusScope { } } - // menus + // Menu Menu { id: contextMenu MenuItem { diff --git a/meshroom/ui/qml/Viewer/qmldir b/meshroom/ui/qml/Viewer/qmldir index d0091d75..2f9a7711 100644 --- a/meshroom/ui/qml/Viewer/qmldir +++ b/meshroom/ui/qml/Viewer/qmldir @@ -2,6 +2,7 @@ module Viewer Viewer2D 1.0 Viewer2D.qml Viewer3D 1.0 Viewer3D.qml +DefaultCameraController 1.0 DefaultCameraController.qml MayaCameraController 1.0 MayaCameraController.qml Locator3D 1.0 Locator3D.qml Grid3D 1.0 Grid3D.qml