Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qquick3dxrvirtualmouse.cpp
Go to the documentation of this file.
1// Copyright (C) 2024 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
5
8
9#include <QtQuick3D/private/qquick3dnode_p.h>
10#include <QtGui/QMouseEvent>
11
13
14/*!
15 \qmltype XrVirtualMouse
16 \inherits Item
17 \inqmlmodule QtQuick3D.Xr
18 \brief Maps 3D controller input to mouse input in 2D items.
19
20 The XrVirtualMouse provides a way to interact with \l{Qt Quick 3D Scenes with 2D Content}{2D user interfaces}
21 in the 3D scene.
22
23 It is typically used like this:
24
25 \qml
26 // XrView { id: xrView
27 // XrController { id: rightController
28 XrInputAction {
29 id: rightTrigger
30 hand: XrInputAction.RightHand
31 actionId: [XrInputAction.TriggerPressed, XrInputAction.TriggerValue]
32 }
33 XrVirtualMouse {
34 view: xrView
35 source: rightController
36 leftMouseButton: rightTrigger.pressed
37 }
38 \endqml
39*/
40
42{
43 m_scrollTimer = new QTimer(this);
44 m_scrollTimer->setInterval(m_scrollTimerInterval);
45 connect(m_scrollTimer, SIGNAL(timeout()), this, SLOT(generateWheelEvent()));
46}
47
48/*!
49 \qmlproperty bool XrVirtualMouse::rightMouseButton
50 \brief Sets the state of the right mouse button.
51
52 When set to true, the right mouse button is pressed.
53*/
54
56{
57 return m_rightMouseButton;
58}
59
60/*!
61 \qmlproperty bool XrVirtualMouse::leftMouseButton
62 \brief Sets the state of the left mouse button.
63
64 When set to true, the left mouse button is pressed.
65*/
66
68{
69 return m_leftMouseButton;
70}
71
72/*!
73 \qmlproperty bool XrVirtualMouse::middleMouseButton
74 \brief Sets the state of the middle mouse button.
75
76 When set to true, the middle mouse button is pressed.
77*/
78
80{
81 return m_middleMouseButton;
82}
83
84/*!
85 \qmlproperty real XrVirtualMouse::scrollWheelX
86 \brief Sets the horizontal scrolling speed.
87
88 Positive values scroll right and negative values scroll left.
89 Scroll speed increases relative to distance from zero.
90
91 \sa scrollPixelDelta
92*/
93
95{
96 return m_scrollWheelX;
97}
98
99/*!
100 \qmlproperty real XrVirtualMouse::scrollWheelY
101 \brief Sets the vertical scrolling speed.
102
103 Positive values scroll up and negative values scroll down.
104 Scroll speed increases relative to distance from zero.
105
106 \sa scrollPixelDelta
107*/
108
110{
111 return m_scrollWheelY;
112}
113
114/*!
115 \qmlproperty int XrVirtualMouse::scrollTimerInterval
116 \brief Defines time in milliseconds between scrolling events sent to the system.
117 \default 30
118*/
119
121{
122 return m_scrollTimerInterval;
123}
124
125/*!
126 \qmlproperty real XrVirtualMouse::scrollPixelDelta
127 \brief Defines the base distance scrolled with each scrolling event.
128 \default 15
129
130 This is the distance scrolled when the scrolling speed is 1.
131
132 \sa scrollWheelX, scrollWheelY
133*/
134
136{
137 return m_scrollPixelDelta;
138}
139
140/*!
141 \qmlproperty Node XrVirtualMouse::source
142 \brief The 3D node controlling the virtual mouse.
143
144 The \c source property is normally set to an \l XrController. Mouse events
145 are generated for the position where the \l{QtQuick3D::Node::forward}{forward vector} of
146 the \c source node intersects with a 2D item.
147*/
148
149QQuick3DNode *QQuick3DXrVirtualMouse::source() const
150{
151 return m_source;
152}
153
154/*!
155 \qmlproperty XrView XrVirtualMouse::view
156 \brief The XR view associated with the virtual mouse.
157 Holds the view in which the virtual mouse operates.
158*/
159
160QQuick3DXrView *QQuick3DXrVirtualMouse::view() const
161{
162 return m_view;
163}
164
165/*!
166 \qmlproperty bool XrVirtualMouse::enabled
167 \brief Indicates whether the virtual mouse is enabled.
168 When true, the virtual mouse sends mouse events to 2D objects in the scene.
169*/
170
172{
173 return m_enabled;
174}
175
176void QQuick3DXrVirtualMouse::setRightMouseButton(bool rightMouseButton)
177{
178 if (m_rightMouseButton == rightMouseButton)
179 return;
180
181 m_rightMouseButton = rightMouseButton;
182 emit rightMouseButtonChanged(m_rightMouseButton);
183 if (m_rightMouseButton) {
184 // Press
185 generateEvent(QEvent::MouseButtonPress, Qt::RightButton);
186 } else {
187 // Release
188 generateEvent(QEvent::MouseButtonRelease, Qt::RightButton);
189 }
190}
191
193{
194 if (m_leftMouseButton == leftMouseButton)
195 return;
196
197 m_leftMouseButton = leftMouseButton;
198 emit leftMouseButtonChanged(m_leftMouseButton);
199 if (m_leftMouseButton) {
200 // Press
201 generateEvent(QEvent::MouseButtonPress, Qt::LeftButton);
202 } else {
203 // Release
204 generateEvent(QEvent::MouseButtonRelease, Qt::LeftButton);
205 }
206}
207
208void QQuick3DXrVirtualMouse::setMiddleMouseButton(bool middleMouseButton)
209{
210 if (m_middleMouseButton == middleMouseButton)
211 return;
212
213 m_middleMouseButton = middleMouseButton;
214 emit middleMouseButtonChanged(m_middleMouseButton);
215 if (m_middleMouseButton) {
216 // Press
217 generateEvent(QEvent::MouseButtonPress, Qt::MiddleButton);
218 } else {
219 // Release
220 generateEvent(QEvent::MouseButtonRelease, Qt::MiddleButton);
221 }
222}
223
225{
226 if (m_scrollWheelX == scrollWheelX)
227 return;
228
229 m_scrollWheelX = scrollWheelX;
230 emit scrollWheelXChanged(m_scrollWheelX);
231 if ((m_scrollTimer->isActive()) && (m_scrollWheelX == 0)) {
232 m_scrollTimer->stop();
233 } else if (!m_scrollTimer->isActive()) {
234 m_scrollTimer->start();
235 }
236}
237
239{
240 if (m_scrollWheelY == scrollWheelY)
241 return;
242
243 m_scrollWheelY = scrollWheelY;
244 emit scrollWheelYChanged(m_scrollWheelY);
245 if ((m_scrollTimer->isActive()) && (m_scrollWheelY == 0)) {
246 m_scrollTimer->stop();
247 } else if (!m_scrollTimer->isActive()) {
248 m_scrollTimer->start();
249 }
250}
251
252void QQuick3DXrVirtualMouse::setScrollTimerInterval(int scrollTimerInterval)
253{
254 if (m_scrollTimerInterval == scrollTimerInterval)
255 return;
256
257 m_scrollTimerInterval = scrollTimerInterval;
258 m_scrollTimer->setInterval(m_scrollTimerInterval);
259
260 emit scrollTimerIntervalChanged(m_scrollTimerInterval);
261}
262
264{
265 if (m_scrollPixelDelta == scrollPixelDelta)
266 return;
267
268 m_scrollPixelDelta = scrollPixelDelta;
269
270 emit scrollPixelDeltaChanged(m_scrollPixelDelta);
271}
272
273void QQuick3DXrVirtualMouse::setSource(QQuick3DNode *source)
274{
275 if (m_source == source)
276 return;
277
278 if (!source)
279 disconnect(m_source, &QQuick3DNode::sceneTransformChanged, this, &QQuick3DXrVirtualMouse::moveEvent);
280
281 m_source = source;
282 emit sourceChanged(m_source);
283
284 if (m_source)
285 connect(m_source, &QQuick3DNode::sceneTransformChanged, this, &QQuick3DXrVirtualMouse::moveEvent);
286}
287
288void QQuick3DXrVirtualMouse::setView(QQuick3DXrView *view)
289{
290 if (m_view == view)
291 return;
292
293 m_view = view;
294 emit viewChanged(m_view);
295}
296
298{
299 if (m_enabled == enabled)
300 return;
301 m_enabled = enabled;
302 emit enabledChanged(m_enabled);
303
304 // Generate mouse release event if we disable when pressed
305 if (!m_enabled && (m_leftMouseButton || m_rightMouseButton || m_middleMouseButton)) {
306 Qt::MouseButton button = m_leftMouseButton ? Qt::LeftButton : m_rightMouseButton ? Qt::RightButton : Qt::MiddleButton;
307 m_leftMouseButton = m_rightMouseButton = m_middleMouseButton = false;
308 generateEvent(QEvent::MouseButtonRelease, button);
309 }
310}
311
312void QQuick3DXrVirtualMouse::moveEvent()
313{
314 generateEvent(QEvent::MouseMove, Qt::NoButton);
315}
316
317void QQuick3DXrVirtualMouse::generateWheelEvent()
318{
319 if (!m_view || !m_source || m_view->m_inDestructor || !m_enabled)
320 return;
321
322 // Get Ray
323 const QVector3D origin = m_source->scenePosition();
324 const QVector3D direction = m_source->forward();
325
326 float x = 0;
327 float y = 0;
328
329 if (m_scrollWheelX > 0) {
330 x = m_scrollPixelDelta * m_scrollWheelX * m_scrollWheelX;
331 } else if (m_scrollWheelX < 0) {
332 x = -m_scrollPixelDelta * m_scrollWheelX * m_scrollWheelX;
333 }
334
335 if (m_scrollWheelY > 0) {
336 y = m_scrollPixelDelta * m_scrollWheelY * m_scrollWheelY;
337 } else if (m_scrollWheelY < 0) {
338 y = -m_scrollPixelDelta * m_scrollWheelY * m_scrollWheelY;
339 }
340
341 QPoint pixelDelta = QPoint(x, y);
342 QPoint angleDelta = QPoint(x*8, y*8);
343
344 // Position will be generated by QtQuick3D
345 QWheelEvent *event = new QWheelEvent(QPointF(), QPointF(), pixelDelta, angleDelta,
346 Qt::NoButton, Qt::NoModifier, Qt::NoScrollPhase, false);
347
348 // Send to View with Ray
349 if (m_view->view3d()) // no internal view3D if XrView init failed but the object is still alive, handle this gracefully
350 m_view->view3d()->singlePointPick(event, origin, direction);
351
352 // Cleanup
353 delete event;
354}
355
356void QQuick3DXrVirtualMouse::generateEvent(QEvent::Type type, Qt::MouseButton button)
357{
358 if (!m_view || !m_source || m_view->m_inDestructor || !m_enabled)
359 return;
360
361 // Get Ray
362 const QVector3D origin = m_source->scenePosition();
363 const QVector3D direction = m_source->forward();
364
365 // Generate Pointer Event
366 Qt::MouseButtons buttons = Qt::NoButton;
367 if (m_leftMouseButton)
368 buttons |= Qt::LeftButton;
369 if (m_rightMouseButton)
370 buttons |= Qt::RightButton;
371 if (m_middleMouseButton)
372 buttons |= Qt::MiddleButton;
373
374 // Position will be generated by QtQuick3D
375 QMouseEvent *event = new QMouseEvent(type, QPointF(), QPointF(), button, buttons, Qt::NoModifier);
376
377 // Send to View with Ray
378 if (m_view->view3d()) // no internal view3D if XrView init failed but the object is still alive, handle this gracefully
379 m_view->view3d()->singlePointPick(event, origin, direction);
380
381 // Cleanup
382 delete event;
383}
384
385QT_END_NAMESPACE
QObject * parent
Definition qobject.h:73
\inmodule QtCore
Definition qobject.h:105
bool middleMouseButton() const
\qmlproperty bool XrVirtualMouse::middleMouseButton
QQuick3DXrView * view() const
\qmlproperty XrView XrVirtualMouse::view
float scrollWheelY() const
\qmlproperty real XrVirtualMouse::scrollWheelY
void setScrollWheelY(float scrollWheelY)
void setScrollWheelX(float scrollWheelX)
void setView(QQuick3DXrView *view)
float scrollWheelX() const
\qmlproperty real XrVirtualMouse::scrollWheelX
int scrollPixelDelta() const
\qmlproperty real XrVirtualMouse::scrollPixelDelta
bool rightMouseButton() const
\qmlproperty bool XrVirtualMouse::rightMouseButton
void setScrollTimerInterval(int scrollTimerInterval)
QQuick3DNode * source() const
\qmlproperty Node XrVirtualMouse::source
void setScrollPixelDelta(int scrollPixelDelta)
bool leftMouseButton() const
\qmlproperty bool XrVirtualMouse::leftMouseButton
void setMiddleMouseButton(bool middleMouseButton)
bool enabled() const
\qmlproperty bool XrVirtualMouse::enabled
int scrollTimerInterval() const
\qmlproperty int XrVirtualMouse::scrollTimerInterval
void setSource(QQuick3DNode *source)
void setLeftMouseButton(bool leftMouseButton)
Combined button and popup list for selecting options.