diff options
| author | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2024-09-24 13:59:10 +0200 |
|---|---|---|
| committer | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2024-10-18 08:20:14 +0000 |
| commit | ab3c2cbea48b8f1ecfd19bbe1c6116d7734ee9d1 (patch) | |
| tree | 794ea3f049ea764a095778b27c62330050d15134 /examples/demos/osmbuildings/OSMBuildings/OSMCameraController.qml | |
| parent | a86135803fe51e5702444f8b7dcb2a4dccd3a209 (diff) | |
Port the osmbuildings demo (maps part)
The buildings part was omitted as it requires a license key.
Task-number: PYSIDE-2206
Pick-to: 6.8
Change-Id: I561fb098786d9e894e5102073db3e7d02f66d8f9
Reviewed-by: Cristian Maureira-Fredes <cristian.maureira-fredes@qt.io>
Diffstat (limited to 'examples/demos/osmbuildings/OSMBuildings/OSMCameraController.qml')
| -rw-r--r-- | examples/demos/osmbuildings/OSMBuildings/OSMCameraController.qml | 234 |
1 files changed, 234 insertions, 0 deletions
diff --git a/examples/demos/osmbuildings/OSMBuildings/OSMCameraController.qml b/examples/demos/osmbuildings/OSMBuildings/OSMCameraController.qml new file mode 100644 index 000000000..114a6dea7 --- /dev/null +++ b/examples/demos/osmbuildings/OSMBuildings/OSMCameraController.qml @@ -0,0 +1,234 @@ +// Copyright (C) 2024 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +import QtQuick +import QtQuick3D + +Item { + id: root + required property Node origin + required property Camera camera + + property real xSpeed: 0.05 + property real ySpeed: 0.05 + + property bool xInvert: false + property bool yInvert: false + + property bool mouseEnabled: true + property bool panEnabled: true + + readonly property bool inputsNeedProcessing: status.useMouse || status.isPanning + + readonly property real minimumZoom: 30 + readonly property real maximumZoom: 200 + + readonly property real minimumTilt: 0 + readonly property real maximumTilt: 80 + + implicitWidth: parent.width + implicitHeight: parent.height + + Connections { + target: camera + Component.onCompleted: { + onZChanged() + } + + function onZChanged() { + // Adjust near/far values based on distance + let distance = camera.z + if (distance < 1) { + camera.clipNear = 0.01 + camera.clipFar = 100 + } else if (distance < 100) { + camera.clipNear = 0.1 + camera.clipFar = 1000 + } else { + camera.clipNear = 1 + camera.clipFar = 10000 + } + } + } + + DragHandler { + id: dragHandler + target: null + enabled: mouseEnabled + acceptedModifiers: Qt.NoModifier + acceptedButtons: Qt.RightButton + onCentroidChanged: { + mouseMoved(Qt.vector2d(centroid.position.x, centroid.position.y), false); + } + + onActiveChanged: { + if (active) + mousePressed(Qt.vector2d(centroid.position.x, centroid.position.y)); + else + mouseReleased(Qt.vector2d(centroid.position.x, centroid.position.y)); + } + } + + DragHandler { + id: ctrlDragHandler + target: null + enabled: mouseEnabled && panEnabled + //acceptedModifiers: Qt.ControlModifier + onCentroidChanged: { + panEvent(Qt.vector2d(centroid.position.x, centroid.position.y)); + } + + onActiveChanged: { + if (active) + startPan(Qt.vector2d(centroid.position.x, centroid.position.y)); + else + endPan(); + } + } + + PinchHandler { + id: pinchHandler + target: null + enabled: mouseEnabled + + property real distance: 0.0 + onCentroidChanged: { + panEvent(Qt.vector2d(centroid.position.x, centroid.position.y)) + } + + onActiveChanged: { + if (active) { + startPan(Qt.vector2d(centroid.position.x, centroid.position.y)) + distance = root.camera.z + } else { + endPan() + distance = 0.0 + } + } + onScaleChanged: { + + camera.z = distance * (1 / scale) + camera.z = Math.min(Math.max(camera.z, minimumZoom), maximumZoom) + } + } + + TapHandler { + onTapped: root.forceActiveFocus() + } + + WheelHandler { + id: wheelHandler + orientation: Qt.Vertical + target: null + enabled: mouseEnabled + onWheel: event => { + let delta = -event.angleDelta.y * 0.01; + camera.z += camera.z * 0.1 * delta + camera.z = Math.min(Math.max(camera.z, minimumZoom), maximumZoom) + } + } + + function mousePressed(newPos) { + root.forceActiveFocus() + status.currentPos = newPos + status.lastPos = newPos + status.useMouse = true; + } + + function mouseReleased(newPos) { + status.useMouse = false; + } + + function mouseMoved(newPos: vector2d) { + status.currentPos = newPos; + } + + function startPan(pos: vector2d) { + status.isPanning = true; + status.currentPanPos = pos; + status.lastPanPos = pos; + } + + function endPan() { + status.isPanning = false; + } + + function panEvent(newPos: vector2d) { + status.currentPanPos = newPos; + } + + FrameAnimation { + id: updateTimer + running: root.inputsNeedProcessing + onTriggered: status.processInput(frameTime * 100) + } + + QtObject { + id: status + + property bool useMouse: false + property bool isPanning: false + + property vector2d lastPos: Qt.vector2d(0, 0) + property vector2d lastPanPos: Qt.vector2d(0, 0) + property vector2d currentPos: Qt.vector2d(0, 0) + property vector2d currentPanPos: Qt.vector2d(0, 0) + + property real rotateAlongZ: 0 + property real rotateAlongXY: 50.0 + + function processInput(frameDelta) { + if (useMouse) { + // Get the delta + var delta = Qt.vector2d(lastPos.x - currentPos.x, + lastPos.y - currentPos.y); + + var rotateX = delta.x * xSpeed * frameDelta + if ( xInvert ) + rotateX = -rotateX + rotateAlongZ += rotateX; + let rotateAlongZRad = rotateAlongZ * (Math.PI / 180.) + + origin.rotate(rotateX, Qt.vector3d(0.0, 0.0, -1.0), Node.SceneSpace) + + var rotateY = delta.y * -ySpeed * frameDelta + if ( yInvert ) + rotateY = -rotateY; + + let preRotateAlongXY = rotateAlongXY + rotateY + if ( preRotateAlongXY <= maximumTilt && preRotateAlongXY >= minimumTilt ) + { + rotateAlongXY = preRotateAlongXY + origin.rotate(rotateY, Qt.vector3d(Math.cos(rotateAlongZRad), Math.sin(-rotateAlongZRad), 0.0), Node.SceneSpace) + } + + lastPos = currentPos; + } + + if (isPanning) { + let delta = currentPanPos.minus(lastPanPos); + delta.x = -delta.x + + delta.x = (delta.x / root.width) * camera.z * frameDelta + delta.y = (delta.y / root.height) * camera.z * frameDelta + + let velocity = Qt.vector3d(0, 0, 0) + // X Movement + let xDirection = origin.right + velocity = velocity.plus(Qt.vector3d(xDirection.x * delta.x, + xDirection.y * delta.x, + xDirection.z * delta.x)); + // Z Movement + let zDirection = origin.right.crossProduct(Qt.vector3d(0.0, 0.0, -1.0)) + velocity = velocity.plus(Qt.vector3d(zDirection.x * delta.y, + zDirection.y * delta.y, + zDirection.z * delta.y)); + + origin.position = origin.position.plus(velocity) + + lastPanPos = currentPanPos + } + } + } + +} |
