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 Derived classes need only implement the frameActionTriggered()
228 method to move the camera.
229*/
230
231/*!
232 \fn void Qt3DExtras::QAbstractCameraController::moveCamera(const InputState &state, float dt) = 0
233
234 This method is called whenever a frame action is triggered. Derived
235 classes must override this method to implement the camera movement
236 specific to the controller.
237
238 In the base class this is a pure virtual function.
239*/
240
241QAbstractCameraController::QAbstractCameraController(Qt3DCore::QNode *parent)
242 : QAbstractCameraController(*new QAbstractCameraControllerPrivate, parent)
243{
244}
245
246/*! \internal
247 */
248QAbstractCameraController::QAbstractCameraController(QAbstractCameraControllerPrivate &dd, Qt3DCore::QNode *parent)
249 : Qt3DCore::QEntity(dd, parent)
250{
251 Q_D(QAbstractCameraController);
252 d->init();
253
254 QObject::connect(sender: d->m_frameAction, signal: &Qt3DLogic::QFrameAction::triggered,
255 context: this, slot: [this] (float dt) {
256 Q_D(const QAbstractCameraController);
257 InputState state;
258
259 state.rxAxisValue = d->m_rxAxis->value();
260 state.ryAxisValue = d->m_ryAxis->value();
261 state.txAxisValue = d->m_txAxis->value();
262 state.tyAxisValue = d->m_tyAxis->value();
263 state.tzAxisValue = d->m_tzAxis->value();
264
265 state.leftMouseButtonActive = d->m_leftMouseButtonAction->isActive();
266 state.middleMouseButtonActive = d->m_middleMouseButtonAction->isActive();
267 state.rightMouseButtonActive = d->m_rightMouseButtonAction->isActive();
268
269 state.altKeyActive = d->m_altButtonAction->isActive();
270 state.shiftKeyActive = d->m_shiftButtonAction->isActive();
271
272 moveCamera(state, dt);
273 });
274}
275
276QAbstractCameraController::~QAbstractCameraController()
277{
278}
279
280/*!
281 \property Qt3DExtras::QAbstractCameraController::camera
282
283 Holds the currently controlled camera.
284*/
285Qt3DRender::QCamera *QAbstractCameraController::camera() const
286{
287 Q_D(const QAbstractCameraController);
288 return d->m_camera;
289}
290
291/*!
292 \property Qt3DExtras::QAbstractCameraController::linearSpeed
293
294 Holds the current linear speed of the camera controller. Linear speed determines the
295 movement speed of the camera.
296
297 The default is \c {10.0}.
298*/
299float QAbstractCameraController::linearSpeed() const
300{
301 Q_D(const QAbstractCameraController);
302 return d->m_linearSpeed;
303}
304
305/*!
306 \property Qt3DExtras::QAbstractCameraController::lookSpeed
307
308 Holds the current look speed of the camera controller. The look speed determines the turn rate
309 of the camera pan and tilt.
310
311 The default is \c {180.0}.
312*/
313float QAbstractCameraController::lookSpeed() const
314{
315 Q_D(const QAbstractCameraController);
316 return d->m_lookSpeed;
317}
318
319/*!
320 \property Qt3DExtras::QAbstractCameraController::acceleration
321
322 Holds the current acceleration of the camera controller.
323*/
324float QAbstractCameraController::acceleration() const
325{
326 Q_D(const QAbstractCameraController);
327 return d->m_acceleration;
328}
329
330/*!
331 \property Qt3DExtras::QAbstractCameraController::deceleration
332
333 Holds the current deceleration of the camera controller.
334*/
335float QAbstractCameraController::deceleration() const
336{
337 Q_D(const QAbstractCameraController);
338 return d->m_deceleration;
339}
340
341void QAbstractCameraController::setCamera(Qt3DRender::QCamera *camera)
342{
343 Q_D(QAbstractCameraController);
344 if (d->m_camera != camera) {
345
346 if (d->m_camera)
347 d->unregisterDestructionHelper(node: d->m_camera);
348
349 if (camera && !camera->parent())
350 camera->setParent(this);
351
352 d->m_camera = camera;
353
354 // Ensures proper bookkeeping
355 if (d->m_camera)
356 d->registerDestructionHelper(node: d->m_camera, func: &QAbstractCameraController::setCamera, d->m_camera);
357
358 emit cameraChanged();
359 }
360}
361
362void QAbstractCameraController::setLinearSpeed(float linearSpeed)
363{
364 Q_D(QAbstractCameraController);
365 if (d->m_linearSpeed != linearSpeed) {
366 d->m_linearSpeed = linearSpeed;
367 emit linearSpeedChanged();
368 }
369}
370
371void QAbstractCameraController::setLookSpeed(float lookSpeed)
372{
373 Q_D(QAbstractCameraController);
374 if (d->m_lookSpeed != lookSpeed) {
375 d->m_lookSpeed = lookSpeed;
376 emit lookSpeedChanged();
377 }
378}
379
380void QAbstractCameraController::setAcceleration(float acceleration)
381{
382 Q_D(QAbstractCameraController);
383 if (d->m_acceleration != acceleration) {
384 d->m_acceleration = acceleration;
385 d->applyInputAccelerations();
386 emit accelerationChanged(acceleration);
387 }
388}
389
390void QAbstractCameraController::setDeceleration(float deceleration)
391{
392 Q_D(QAbstractCameraController);
393 if (d->m_deceleration != deceleration) {
394 d->m_deceleration = deceleration;
395 d->applyInputAccelerations();
396 emit decelerationChanged(deceleration);
397 }
398}
399
400/*!
401 Provides access to the keyboard device.
402*/
403
404Qt3DInput::QKeyboardDevice *QAbstractCameraController::keyboardDevice() const
405{
406 Q_D(const QAbstractCameraController);
407 return d->m_keyboardDevice;
408}
409
410/*!
411 Provides access to the mouse device.
412*/
413
414Qt3DInput::QMouseDevice *QAbstractCameraController::mouseDevice() const
415{
416 Q_D(const QAbstractCameraController);
417 return d->m_mouseDevice;
418}
419
420} // Qt3DExtras
421
422QT_END_NAMESPACE
423
424#include "moc_qabstractcameracontroller.cpp"
425

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