1/**************************************************************************** 2** 3** Copyright (C) 2019 The Qt Company Ltd. 4** Contact: https://www.qt.io/licensing/ 5** 6** This file is part of Qt Quick 3D. 7** 8** $QT_BEGIN_LICENSE:GPL$ 9** Commercial License Usage 10** Licensees holding valid commercial Qt licenses may use this file in 11** accordance with the commercial license agreement provided with the 12** Software or, alternatively, in accordance with the terms contained in 13** a written agreement between you and The Qt Company. For licensing terms 14** and conditions see https://www.qt.io/terms-conditions. For further 15** information use the contact form at https://www.qt.io/contact-us. 16** 17** GNU General Public License Usage 18** Alternatively, this file may be used under the terms of the GNU 19** General Public License version 3 or (at your option) any later version 20** approved by the KDE Free Qt Foundation. The licenses are as published by 21** the Free Software Foundation and appearing in the file LICENSE.GPL3 22** included in the packaging of this file. Please review the following 23** information to ensure the GNU General Public License requirements will 24** be met: https://www.gnu.org/licenses/gpl-3.0.html. 25** 26** $QT_END_LICENSE$ 27** 28****************************************************************************/ 29 30import QtQuick 2.15 31import QtQuick3D 1.15 32 33Item { 34 id: root 35 property Node controlledObject: undefined 36 37 property real speed: 1 38 property real shiftSpeed: 3 39 40 property real forwardSpeed: 5 41 property real backSpeed: 5 42 property real rightSpeed: 5 43 property real leftSpeed: 5 44 property real upSpeed: 5 45 property real downSpeed: 5 46 property real xSpeed: 0.1 47 property real ySpeed: 0.1 48 49 property bool xInvert: false 50 property bool yInvert: true 51 52 property bool mouseEnabled: true 53 property bool keysEnabled: true 54 55 readonly property bool inputsNeedProcessing: status.moveForward | status.moveBack 56 | status.moveLeft | status.moveRight 57 | status.moveUp | status.moveDown 58 | status.useMouse 59 60 property alias acceptedButtons: dragHandler.acceptedButtons 61 62 63 64 implicitWidth: parent.width 65 implicitHeight: parent.height 66 focus: keysEnabled 67 68 DragHandler { 69 id: dragHandler 70 target: null 71 enabled: mouseEnabled 72 onCentroidChanged: { 73 mouseMoved(Qt.vector2d(centroid.position.x, centroid.position.y)); 74 } 75 76 onActiveChanged: { 77 if (active) 78 mousePressed(Qt.vector2d(centroid.position.x, centroid.position.y)); 79 else 80 mouseReleased(Qt.vector2d(centroid.position.x, centroid.position.y)); 81 } 82 } 83 84 Keys.onPressed: if (keysEnabled) handleKeyPress(event) 85 Keys.onReleased: if (keysEnabled) handleKeyRelease(event) 86 87 function mousePressed(newPos) { 88 status.currentPos = newPos 89 status.lastPos = newPos 90 status.useMouse = true; 91 } 92 93 function mouseReleased(newPos) { 94 status.useMouse = false; 95 } 96 97 function mouseMoved(newPos) { 98 status.currentPos = newPos; 99 } 100 101 function forwardPressed() { 102 status.moveForward = true 103 status.moveBack = false 104 } 105 106 function forwardReleased() { 107 status.moveForward = false 108 } 109 110 function backPressed() { 111 status.moveBack = true 112 status.moveForward = false 113 } 114 115 function backReleased() { 116 status.moveBack = false 117 } 118 119 function rightPressed() { 120 status.moveRight = true 121 status.moveLeft = false 122 } 123 124 function rightReleased() { 125 status.moveRight = false 126 } 127 128 function leftPressed() { 129 status.moveLeft = true 130 status.moveRight = false 131 } 132 133 function leftReleased() { 134 status.moveLeft = false 135 } 136 137 function upPressed() { 138 status.moveUp = true 139 status.moveDown = false 140 } 141 142 function upReleased() { 143 status.moveUp = false 144 } 145 146 function downPressed() { 147 status.moveDown = true 148 status.moveUp = false 149 } 150 151 function downReleased() { 152 status.moveDown = false 153 } 154 155 function shiftPressed() { 156 status.shiftDown = true 157 } 158 159 function shiftReleased() { 160 status.shiftDown = false 161 } 162 163 function handleKeyPress(event) 164 { 165 switch (event.key) { 166 case Qt.Key_W: 167 case Qt.Key_Up: 168 forwardPressed(); 169 break; 170 case Qt.Key_S: 171 case Qt.Key_Down: 172 backPressed(); 173 break; 174 case Qt.Key_A: 175 case Qt.Key_Left: 176 leftPressed(); 177 break; 178 case Qt.Key_D: 179 case Qt.Key_Right: 180 rightPressed(); 181 break; 182 case Qt.Key_R: 183 case Qt.Key_PageUp: 184 upPressed(); 185 break; 186 case Qt.Key_F: 187 case Qt.Key_PageDown: 188 downPressed(); 189 break; 190 case Qt.Key_Shift: 191 shiftPressed(); 192 break; 193 } 194 } 195 196 function handleKeyRelease(event) 197 { 198 switch (event.key) { 199 case Qt.Key_W: 200 case Qt.Key_Up: 201 forwardReleased(); 202 break; 203 case Qt.Key_S: 204 case Qt.Key_Down: 205 backReleased(); 206 break; 207 case Qt.Key_A: 208 case Qt.Key_Left: 209 leftReleased(); 210 break; 211 case Qt.Key_D: 212 case Qt.Key_Right: 213 rightReleased(); 214 break; 215 case Qt.Key_R: 216 case Qt.Key_PageUp: 217 upReleased(); 218 break; 219 case Qt.Key_F: 220 case Qt.Key_PageDown: 221 downReleased(); 222 break; 223 case Qt.Key_Shift: 224 shiftReleased(); 225 break; 226 } 227 } 228 229 Timer { 230 id: updateTimer 231 interval: 16 232 repeat: true 233 running: root.inputsNeedProcessing 234 onTriggered: { 235 processInputs(); 236 } 237 } 238 239 function processInputs() 240 { 241 if (root.inputsNeedProcessing) 242 status.processInput(); 243 } 244 245 QtObject { 246 id: status 247 248 property bool moveForward: false 249 property bool moveBack: false 250 property bool moveLeft: false 251 property bool moveRight: false 252 property bool moveUp: false 253 property bool moveDown: false 254 property bool shiftDown: false 255 property bool useMouse: false 256 257 property vector2d lastPos: Qt.vector2d(0, 0) 258 property vector2d currentPos: Qt.vector2d(0, 0) 259 260 function updatePosition(vector, speed, position) 261 { 262 if (shiftDown) 263 speed *= shiftSpeed; 264 else 265 speed *= root.speed 266 267 var direction = vector; 268 var velocity = Qt.vector3d(direction.x * speed, 269 direction.y * speed, 270 direction.z * speed); 271 controlledObject.position = Qt.vector3d(position.x + velocity.x, 272 position.y + velocity.y, 273 position.z + velocity.z); 274 } 275 276 function negate(vector) { 277 return Qt.vector3d(-vector.x, -vector.y, -vector.z) 278 } 279 280 function processInput() { 281 if (controlledObject == undefined) 282 return; 283 284 if (moveForward) 285 updatePosition(controlledObject.forward, forwardSpeed, controlledObject.position); 286 else if (moveBack) 287 updatePosition(negate(controlledObject.forward), backSpeed, controlledObject.position); 288 289 if (moveRight) 290 updatePosition(controlledObject.right, rightSpeed, controlledObject.position); 291 else if (moveLeft) 292 updatePosition(negate(controlledObject.right), leftSpeed, controlledObject.position); 293 294 if (moveDown) 295 updatePosition(negate(controlledObject.up), downSpeed, controlledObject.position); 296 else if (moveUp) 297 updatePosition(controlledObject.up, upSpeed, controlledObject.position); 298 299 if (useMouse) { 300 // Get the delta 301 var rotationVector = controlledObject.eulerRotation; 302 var delta = Qt.vector2d(lastPos.x - currentPos.x, 303 lastPos.y - currentPos.y); 304 // rotate x 305 var rotateX = delta.x * xSpeed 306 if (xInvert) 307 rotateX = -rotateX; 308 rotationVector.y += rotateX; 309 310 // rotate y 311 var rotateY = delta.y * -ySpeed 312 if (yInvert) 313 rotateY = -rotateY; 314 rotationVector.x += rotateY; 315 controlledObject.setEulerRotation(rotationVector); 316 lastPos = currentPos; 317 } 318 } 319 } 320} 321