1// Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB).
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qabstractcameracontroller.h"
5#include "qabstractcameracontroller_p.h"
6
7#include <Qt3DRender/QCamera>
8#include <Qt3DInput/QAxis>
9#include <Qt3DInput/QAnalogAxisInput>
10#include <Qt3DInput/QButtonAxisInput>
11#include <Qt3DInput/QAction>
12#include <Qt3DInput/QActionInput>
13#include <Qt3DInput/QLogicalDevice>
14#include <Qt3DInput/QKeyboardDevice>
15#include <Qt3DInput/QMouseDevice>
16#include <Qt3DInput/QMouseEvent>
17#include <Qt3DLogic/QFrameAction>
18#include <QtCore/QtGlobal>
19
20QT_BEGIN_NAMESPACE
21
22namespace Qt3DExtras {
23
24QAbstractCameraControllerPrivate::QAbstractCameraControllerPrivate()
25 : Qt3DCore::QEntityPrivate()
26 , m_camera(nullptr)
27 , m_leftMouseButtonAction(new Qt3DInput::QAction())
28 , m_middleMouseButtonAction(new Qt3DInput::QAction())
29 , m_rightMouseButtonAction(new Qt3DInput::QAction())
30 , m_altButtonAction(new Qt3DInput::QAction())
31 , m_shiftButtonAction(new Qt3DInput::QAction())
32 , m_escapeButtonAction(new Qt3DInput::QAction())
33 , m_rxAxis(new Qt3DInput::QAxis())
34 , m_ryAxis(new Qt3DInput::QAxis())
35 , m_txAxis(new Qt3DInput::QAxis())
36 , m_tyAxis(new Qt3DInput::QAxis())
37 , m_tzAxis(new Qt3DInput::QAxis())
38 , m_leftMouseButtonInput(new Qt3DInput::QActionInput())
39 , m_middleMouseButtonInput(new Qt3DInput::QActionInput())
40 , m_rightMouseButtonInput(new Qt3DInput::QActionInput())
41 , m_altButtonInput(new Qt3DInput::QActionInput())
42 , m_shiftButtonInput(new Qt3DInput::QActionInput())
43 , m_escapeButtonInput(new Qt3DInput::QActionInput())
44 , m_mouseRxInput(new Qt3DInput::QAnalogAxisInput())
45 , m_mouseRyInput(new Qt3DInput::QAnalogAxisInput())
46 , m_mouseTzXInput(new Qt3DInput::QAnalogAxisInput())
47 , m_mouseTzYInput(new Qt3DInput::QAnalogAxisInput())
48 , m_keyboardTxPosInput(new Qt3DInput::QButtonAxisInput())
49 , m_keyboardTyPosInput(new Qt3DInput::QButtonAxisInput())
50 , m_keyboardTzPosInput(new Qt3DInput::QButtonAxisInput())
51 , m_keyboardTxNegInput(new Qt3DInput::QButtonAxisInput())
52 , m_keyboardTyNegInput(new Qt3DInput::QButtonAxisInput())
53 , m_keyboardTzNegInput(new Qt3DInput::QButtonAxisInput())
54 , m_keyboardDevice(new Qt3DInput::QKeyboardDevice())
55 , m_mouseDevice(new Qt3DInput::QMouseDevice())
56 , m_logicalDevice(new Qt3DInput::QLogicalDevice())
57 , m_frameAction(new Qt3DLogic::QFrameAction())
58 , m_linearSpeed(10.0f)
59 , m_lookSpeed(180.0f)
60 , m_acceleration(-1.0f)
61 , m_deceleration(-1.0f)
62 , m_sceneUp(0.0f, 1.0f, 0.0f)
63{}
64
65void QAbstractCameraControllerPrivate::init()
66{
67 //// Actions
68
69 // Left Mouse Button Action
70 m_leftMouseButtonInput->setButtons(QList<int> { Qt::LeftButton });
71 m_leftMouseButtonInput->setSourceDevice(m_mouseDevice);
72 m_leftMouseButtonAction->addInput(input: m_leftMouseButtonInput);
73
74 // Middle Mouse Button Action
75 m_middleMouseButtonInput->setButtons(QList<int> { Qt::MiddleButton });
76 m_middleMouseButtonInput->setSourceDevice(m_mouseDevice);
77 m_middleMouseButtonAction->addInput(input: m_middleMouseButtonInput);
78
79 // Right Mouse Button Action
80 m_rightMouseButtonInput->setButtons(QList<int> { Qt::RightButton });
81 m_rightMouseButtonInput->setSourceDevice(m_mouseDevice);
82 m_rightMouseButtonAction->addInput(input: m_rightMouseButtonInput);
83
84 // Alt Button Action
85 m_altButtonInput->setButtons(QList<int> { Qt::Key_Alt });
86 m_altButtonInput->setSourceDevice(m_keyboardDevice);
87 m_altButtonAction->addInput(input: m_altButtonInput);
88
89 // Shift Button Action
90 m_shiftButtonInput->setButtons(QList<int> { Qt::Key_Shift });
91 m_shiftButtonInput->setSourceDevice(m_keyboardDevice);
92 m_shiftButtonAction->addInput(input: m_shiftButtonInput);
93
94 // Escape Button Action
95 m_escapeButtonInput->setButtons(QList<int> { Qt::Key_Escape });
96 m_escapeButtonInput->setSourceDevice(m_keyboardDevice);
97 m_escapeButtonAction->addInput(input: m_escapeButtonInput);
98
99 //// Axes
100
101 // Mouse X
102 m_mouseRxInput->setAxis(Qt3DInput::QMouseDevice::X);
103 m_mouseRxInput->setSourceDevice(m_mouseDevice);
104 m_rxAxis->addInput(input: m_mouseRxInput);
105
106 // Mouse Y
107 m_mouseRyInput->setAxis(Qt3DInput::QMouseDevice::Y);
108 m_mouseRyInput->setSourceDevice(m_mouseDevice);
109 m_ryAxis->addInput(input: m_mouseRyInput);
110
111 // Mouse Wheel X
112 m_mouseTzXInput->setAxis(Qt3DInput::QMouseDevice::WheelX);
113 m_mouseTzXInput->setSourceDevice(m_mouseDevice);
114 m_tzAxis->addInput(input: m_mouseTzXInput);
115
116 // Mouse Wheel Y
117 m_mouseTzYInput->setAxis(Qt3DInput::QMouseDevice::WheelY);
118 m_mouseTzYInput->setSourceDevice(m_mouseDevice);
119 m_tzAxis->addInput(input: m_mouseTzYInput);
120
121 // Keyboard Pos Tx
122 m_keyboardTxPosInput->setButtons(QList<int> { Qt::Key_Right });
123 m_keyboardTxPosInput->setScale(1.0f);
124 m_keyboardTxPosInput->setSourceDevice(m_keyboardDevice);
125 m_txAxis->addInput(input: m_keyboardTxPosInput);
126
127 // Keyboard Pos Tz
128 m_keyboardTzPosInput->setButtons(QList<int> { Qt::Key_PageUp });
129 m_keyboardTzPosInput->setScale(1.0f);
130 m_keyboardTzPosInput->setSourceDevice(m_keyboardDevice);
131 m_tzAxis->addInput(input: m_keyboardTzPosInput);
132
133 // Keyboard Pos Ty
134 m_keyboardTyPosInput->setButtons(QList<int> { Qt::Key_Up });
135 m_keyboardTyPosInput->setScale(1.0f);
136 m_keyboardTyPosInput->setSourceDevice(m_keyboardDevice);
137 m_tyAxis->addInput(input: m_keyboardTyPosInput);
138
139 // Keyboard Neg Tx
140 m_keyboardTxNegInput->setButtons(QList<int> { Qt::Key_Left });
141 m_keyboardTxNegInput->setScale(-1.0f);
142 m_keyboardTxNegInput->setSourceDevice(m_keyboardDevice);
143 m_txAxis->addInput(input: m_keyboardTxNegInput);
144
145 // Keyboard Neg Tz
146 m_keyboardTzNegInput->setButtons(QList<int> { Qt::Key_PageDown });
147 m_keyboardTzNegInput->setScale(-1.0f);
148 m_keyboardTzNegInput->setSourceDevice(m_keyboardDevice);
149 m_tzAxis->addInput(input: m_keyboardTzNegInput);
150
151 // Keyboard Neg Ty
152 m_keyboardTyNegInput->setButtons(QList<int> { Qt::Key_Down });
153 m_keyboardTyNegInput->setScale(-1.0f);
154 m_keyboardTyNegInput->setSourceDevice(m_keyboardDevice);
155 m_tyAxis->addInput(input: m_keyboardTyNegInput);
156
157 //// Logical Device
158
159 m_logicalDevice->addAction(action: m_leftMouseButtonAction);
160 m_logicalDevice->addAction(action: m_middleMouseButtonAction);
161 m_logicalDevice->addAction(action: m_rightMouseButtonAction);
162 m_logicalDevice->addAction(action: m_altButtonAction);
163 m_logicalDevice->addAction(action: m_shiftButtonAction);
164 m_logicalDevice->addAction(action: m_escapeButtonAction);
165 m_logicalDevice->addAxis(axis: m_rxAxis);
166 m_logicalDevice->addAxis(axis: m_ryAxis);
167 m_logicalDevice->addAxis(axis: m_txAxis);
168 m_logicalDevice->addAxis(axis: m_tyAxis);
169 m_logicalDevice->addAxis(axis: m_tzAxis);
170
171 applyInputAccelerations();
172
173 Q_Q(QAbstractCameraController);
174 //// FrameAction
175
176 // Disable the logical device when the entity is disabled
177 QObject::connect(sender: q, signal: &Qt3DCore::QEntity::enabledChanged,
178 context: m_logicalDevice, slot: &Qt3DInput::QLogicalDevice::setEnabled);
179 QObject::connect(sender: q, signal: &Qt3DCore::QEntity::enabledChanged,
180 context: m_frameAction, slot: &Qt3DLogic::QFrameAction::setEnabled);
181 for (auto axis: {m_rxAxis, m_ryAxis, m_txAxis, m_tyAxis, m_tzAxis}) {
182 QObject::connect(sender: q, signal: &Qt3DCore::QEntity::enabledChanged,
183 context: axis, slot: &Qt3DInput::QAxis::setEnabled);
184 }
185
186 QObject::connect(sender: m_escapeButtonAction, signal: &Qt3DInput::QAction::activeChanged,
187 context: q, slot: [this](bool isActive) {
188 if (isActive && m_camera)
189 m_camera->viewAll();
190 });
191
192 q->addComponent(comp: m_frameAction);
193 q->addComponent(comp: m_logicalDevice);
194}
195
196void QAbstractCameraControllerPrivate::applyInputAccelerations()
197{
198 const auto inputs = {
199 m_keyboardTxPosInput,
200 m_keyboardTyPosInput,
201 m_keyboardTzPosInput,
202 m_keyboardTxNegInput,
203 m_keyboardTyNegInput,
204 m_keyboardTzNegInput
205 };
206
207 for (auto input : inputs) {
208 input->setAcceleration(m_acceleration);
209 input->setDeceleration(m_deceleration);
210 }
211}
212
213/*!
214 \class Qt3DExtras::QAbstractCameraController
215
216 \brief The QAbstractCameraController class provides basic
217 functionality for camera controllers.
218
219 \inmodule Qt3DExtras
220 \since 5.10
221
222 QAbstractCameraController sets up and handles input from keyboard,
223 mouse, and other devices. QAbstractCameraController is an abstract
224 class and cannot itself be instantiated. It provides a standard
225 interface for camera controllers.
226*/
227
228/*!
229 \fn void Qt3DExtras::QAbstractCameraController::moveCamera(const InputState &state, float dt) = 0
230
231 This method is called whenever a frame action is triggered. Derived
232 classes must override this method to implement the camera movement
233 specific to the controller.
234
235 In the base class this is a pure virtual function.
236*/
237
238QAbstractCameraController::QAbstractCameraController(Qt3DCore::QNode *parent)
239 : QAbstractCameraController(*new QAbstractCameraControllerPrivate, parent)
240{
241}
242
243/*! \internal
244 */
245QAbstractCameraController::QAbstractCameraController(QAbstractCameraControllerPrivate &dd, Qt3DCore::QNode *parent)
246 : Qt3DCore::QEntity(dd, parent)
247{
248 Q_D(QAbstractCameraController);
249 d->init();
250
251 QObject::connect(sender: d->m_frameAction, signal: &Qt3DLogic::QFrameAction::triggered,
252 context: this, slot: [this] (float dt) {
253 Q_D(const QAbstractCameraController);
254 InputState state;
255
256 state.rxAxisValue = d->m_rxAxis->value();
257 state.ryAxisValue = d->m_ryAxis->value();
258 state.txAxisValue = d->m_txAxis->value();
259 state.tyAxisValue = d->m_tyAxis->value();
260 state.tzAxisValue = d->m_tzAxis->value();
261
262 state.leftMouseButtonActive = d->m_leftMouseButtonAction->isActive();
263 state.middleMouseButtonActive = d->m_middleMouseButtonAction->isActive();
264 state.rightMouseButtonActive = d->m_rightMouseButtonAction->isActive();
265
266 state.altKeyActive = d->m_altButtonAction->isActive();
267 state.shiftKeyActive = d->m_shiftButtonAction->isActive();
268
269 moveCamera(state, dt);
270 });
271}
272
273QAbstractCameraController::~QAbstractCameraController()
274{
275}
276
277/*!
278 \property Qt3DExtras::QAbstractCameraController::camera
279
280 Holds the currently controlled camera.
281*/
282Qt3DRender::QCamera *QAbstractCameraController::camera() const
283{
284 Q_D(const QAbstractCameraController);
285 return d->m_camera;
286}
287
288/*!
289 \property Qt3DExtras::QAbstractCameraController::linearSpeed
290
291 Holds the current linear speed of the camera controller. Linear speed determines the
292 movement speed of the camera.
293
294 The default is \c {10.0}.
295*/
296float QAbstractCameraController::linearSpeed() const
297{
298 Q_D(const QAbstractCameraController);
299 return d->m_linearSpeed;
300}
301
302/*!
303 \property Qt3DExtras::QAbstractCameraController::lookSpeed
304
305 Holds the current look speed of the camera controller. The look speed determines the turn rate
306 of the camera pan and tilt.
307
308 The default is \c {180.0}.
309*/
310float QAbstractCameraController::lookSpeed() const
311{
312 Q_D(const QAbstractCameraController);
313 return d->m_lookSpeed;
314}
315
316/*!
317 \property Qt3DExtras::QAbstractCameraController::acceleration
318
319 Holds the current acceleration of the camera controller.
320*/
321float QAbstractCameraController::acceleration() const
322{
323 Q_D(const QAbstractCameraController);
324 return d->m_acceleration;
325}
326
327/*!
328 \property Qt3DExtras::QAbstractCameraController::deceleration
329
330 Holds the current deceleration of the camera controller.
331*/
332float QAbstractCameraController::deceleration() const
333{
334 Q_D(const QAbstractCameraController);
335 return d->m_deceleration;
336}
337
338void QAbstractCameraController::setCamera(Qt3DRender::QCamera *camera)
339{
340 Q_D(QAbstractCameraController);
341 if (d->m_camera != camera) {
342
343 if (d->m_camera)
344 d->unregisterDestructionHelper(node: d->m_camera);
345
346 if (camera && !camera->parent())
347 camera->setParent(this);
348
349 d->m_camera = camera;
350
351 // Ensures proper bookkeeping
352 if (d->m_camera)
353 d->registerDestructionHelper(node: d->m_camera, func: &QAbstractCameraController::setCamera, d->m_camera);
354
355 emit cameraChanged();
356 }
357}
358
359void QAbstractCameraController::setLinearSpeed(float linearSpeed)
360{
361 Q_D(QAbstractCameraController);
362 if (d->m_linearSpeed != linearSpeed) {
363 d->m_linearSpeed = linearSpeed;
364 emit linearSpeedChanged();
365 }
366}
367
368void QAbstractCameraController::setLookSpeed(float lookSpeed)
369{
370 Q_D(QAbstractCameraController);
371 if (d->m_lookSpeed != lookSpeed) {
372 d->m_lookSpeed = lookSpeed;
373 emit lookSpeedChanged();
374 }
375}
376
377void QAbstractCameraController::setAcceleration(float acceleration)
378{
379 Q_D(QAbstractCameraController);
380 if (d->m_acceleration != acceleration) {
381 d->m_acceleration = acceleration;
382 d->applyInputAccelerations();
383 emit accelerationChanged(acceleration);
384 }
385}
386
387void QAbstractCameraController::setDeceleration(float deceleration)
388{
389 Q_D(QAbstractCameraController);
390 if (d->m_deceleration != deceleration) {
391 d->m_deceleration = deceleration;
392 d->applyInputAccelerations();
393 emit decelerationChanged(deceleration);
394 }
395}
396
397/*!
398 Provides access to the keyboard device.
399*/
400
401Qt3DInput::QKeyboardDevice *QAbstractCameraController::keyboardDevice() const
402{
403 Q_D(const QAbstractCameraController);
404 return d->m_keyboardDevice;
405}
406
407/*!
408 Provides access to the mouse device.
409*/
410
411Qt3DInput::QMouseDevice *QAbstractCameraController::mouseDevice() const
412{
413 Q_D(const QAbstractCameraController);
414 return d->m_mouseDevice;
415}
416
417} // Qt3DExtras
418
419QT_END_NAMESPACE
420
421#include "moc_qabstractcameracontroller.cpp"
422

source code of qt3d/src/extras/defaults/qabstractcameracontroller.cpp