Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qquick3dxritem.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
4#include "qquick3dxritem_p.h"
5#include "qquick3dxrview_p.h"
6#include <QtQuick3D/private/qquick3dnode_p_p.h>
7#include <QtQuick/private/qquickrectangle_p.h>
8#include <QColor>
9
11
12
14{
15 Q_DECLARE_PUBLIC(QQuick3DXrItem)
16public:
20
42
44 {
45 Q_Q(QQuick3DXrItem);
46 if (!m_containerItem) {
50 m_containerItem->setVisible(q->visible());
52 m_containerItem->setVisible(q->visible());
53 });
54
55 auto dataProp = data();
56 dataProp.append(&dataProp, m_containerItem);
57 }
58 }
59
60 void updateContent();
61
64 QPointer<QQuick3DXrView> m_XrView;
71};
72
73static inline qreal calculatePPU(qreal pxWidth, qreal pxHeight, qreal diagonal)
74{
75 return (diagonal > 0) ? std::sqrt((pxWidth * pxWidth) + (pxHeight * pxHeight)) / diagonal : 1.0;
76}
77
79{
81 return;
82 Q_Q(QQuick3DXrItem);
85 if (m_contentItem) {
87 qWarning() << "XrItem invalid pixelPerUnit" << m_pixelsPerUnit;
88 return;
89 }
90 qreal newScale;
92 newScale = 1.0 / m_pixelsPerUnit;
93
94 } else {
95 qreal diagonal = std::sqrt((m_width * m_width) + (m_height * m_height));
97 if (ppu <= 0)
98 ppu = 1.0;
99 q->setPixelsPerUnit(ppu);
100 newScale = 1.0 / ppu;
101 }
102 QSizeF newSize(m_width / newScale, m_height / newScale);
103 m_containerItem->setSize(newSize);
104 m_containerItem->setScale(newScale);
105 }
106}
107
142
144{
145 Q_D(QQuick3DXrItem);
146 if (d->m_XrView)
147 d->m_XrView->unregisterXrItem(this);
148}
149
151{
152 Q_D(QQuick3DXrItem);
153 QQuick3DNode::componentComplete(); // Sets d->componentComplete, so must be called first
154
155 auto findView = [this]() -> QQuick3DXrView * {
157 while (parent) {
158 if (auto *xrView = qobject_cast<QQuick3DXrView*>(parent))
159 return xrView;
160 parent = parent->parentNode();
161 }
162 return nullptr;
163 };
164 d->m_XrView = findView();
165 if (d->m_XrView)
166 d->m_XrView->registerXrItem(this);
167 else
168 qWarning("Could not find XrView for XrItem");
169 d->updateContent();
170}
171
181{
182 Q_D(const QQuick3DXrItem);
183 return d->m_contentItem;
184}
185
187{
188 Q_D(QQuick3DXrItem);
189 if (d->m_contentItem == newContentItem)
190 return;
191
192 d->setContentItem(newContentItem);
194}
195
208{
209 Q_D(const QQuick3DXrItem);
210 return d->m_pixelsPerUnit;
211}
212
214{
215 Q_D(QQuick3DXrItem);
216 if (qFuzzyCompare(d->m_pixelsPerUnit, newPixelsPerUnit))
217 return;
218
219 d->m_pixelsPerUnit = newPixelsPerUnit;
220
221 if (d->m_manualPixelsPerUnit)
222 d->updateContent();
223
225}
226
239{
240 Q_D(const QQuick3DXrItem);
241 return d->m_manualPixelsPerUnit;
242}
243
244void QQuick3DXrItem::setManualPixelsPerUnit(bool newManualPixelsPerUnit)
245{
246 Q_D(QQuick3DXrItem);
247 if (d->m_manualPixelsPerUnit == newManualPixelsPerUnit)
248 return;
249 d->m_manualPixelsPerUnit = newManualPixelsPerUnit;
250 d->updateContent();
252}
253
262{
263 Q_D(const QQuick3DXrItem);
264 return d->m_width;
265}
266
268{
269 Q_D(QQuick3DXrItem);
270 if (d->m_width == newWidth)
271 return;
272 d->m_width = newWidth;
274
275 d->updateContent();
276}
277
286{
287 Q_D(const QQuick3DXrItem);
288 return d->m_height;
289}
290
292{
293 Q_D(QQuick3DXrItem);
294 if (d->m_height == newHeight)
295 return;
296 d->m_height = newHeight;
298
299 d->updateContent();
300}
301
302// Sends appropriate touch events.
303// Updates the touchState and returns true if this item grabs the touch point.
304// touchState is input/output, and input contains the previous state if touchState->grabbed is true
305
307{
308 Q_D(QQuick3DXrItem);
309
310 auto mappedPos = mapPositionFromScene(pos);
311
312 QPointF point = {mappedPos.x(), -mappedPos.y()};
313
314 constexpr qreal sideMargin = 20; // How far outside the rect do you have to go to cancel the grab (cm)
315 constexpr qreal cancelDepth = 50; // How far through the rect do you have to go to cancel the grab (cm)
316 constexpr qreal hoverHeight = 10; // How far above does the hover state begin (cm). NOTE: no hover events actually sent
317
318 constexpr qreal releaseHeight = 2; // How far to move towards/from the surface to count as a press/release when below
319 constexpr qreal smallDistance = 0.5; // Any movement shorter than this distance is ignored for press/release below the surface
320 constexpr qreal longDistance = 5; // Any in-surface movement larger than this distance means this is not a press/release below the surface
321 constexpr int releaseTime = 500; // How fast does the finger have to move to count as press/release below the surface
322 constexpr qreal releaseHeightSquared = releaseHeight * releaseHeight;
323 constexpr qreal smallDistanceSquared = smallDistance * smallDistance;
324 constexpr qreal longDistanceSquared = longDistance * longDistance;
325
326 const float z = mappedPos.z();
327
328 const bool wayOutside = point.x() < -sideMargin || point.x() > width() + sideMargin
329 || point.y() < -sideMargin || point.y() > height() + sideMargin || z < -cancelDepth;
330 const bool inside = point.x() >= 0 && point.x() <= width() && point.y() >= 0 && point.y() <= height() && !wayOutside;
331
332 const bool wasGrabbed = touchState->grabbed;
333 const bool wasPressed = touchState->pressed;
334
335 bool hover = z > 0 && z < hoverHeight;
336
337 bool pressed = false;
338 bool grab;
339 bool resetPrevious = false;
341
342 if (wasGrabbed) {
343 // We maintain a grab as long as we don't move too far away while below the surface, or if we hover inside
344
345 // We release if we go from below to above, or if we move upwards fast enough
346 // We press if we go from above to below, or if we push downwards fast enough
347 // We maintain press otherwise
348 // If we move outside when pressed, we should maintain pressed state, but send release event
349
350 QVector3D distFromPrev = mappedPos - touchState->previous;
351 qint64 msSincePrev = now - touchState->timestamp;
352
353 const qreal prevZ = touchState->previous.z();
354
355 if (prevZ > 0 && z <= 0) {
356 // New press from above
357 pressed = true;
358 resetPrevious = true;
359 } else if (msSincePrev > releaseTime || z > 0) {
360 resetPrevious = true;
361 // If the timestamp of the last significant move is older than the cutoff, we maintain the press state if we're below the surface
362 // We're never pressed if we're above the surface
363 pressed = z <= 0 && wasPressed;
364 } else {
365 // We know we're within the cutoff interval, and below the surface.
366 const qreal hDistSquared = distFromPrev.x() * distFromPrev.x() + distFromPrev.y() * distFromPrev.y();
367 const qreal vDistSquared = distFromPrev.z() * distFromPrev.z();
368 const qreal distSquared = hDistSquared + vDistSquared;
369
370 if (distSquared < smallDistanceSquared) {
371 // Ignore the movement if it's small.
372 resetPrevious = false;
373 pressed = wasPressed;
374 } else if (hDistSquared > longDistanceSquared) {
375 // It's not a press/release if it's a long move inside the surface
376 resetPrevious = true;
377 pressed = wasPressed;
378 } else if (vDistSquared > releaseHeightSquared) {
379 // Significant vertical move
380 resetPrevious = true;
381 pressed = distFromPrev.z() < 0;
382 } else {
383 resetPrevious = false;
384 pressed = wasPressed;
385 }
386 }
387
388 grab = (z <= 0 && !wayOutside) || (hover && inside);
389 } else {
390 // We don't want movement behind the surface to register as pressed, so we need at least one hover before a press
391 grab = hover && inside;
392 resetPrevious = true;
393 }
394
395 if (grab) {
396 float zOffset = qMin(z, 0.0);
397 if (offset)
398 *offset = sceneRotation() * QVector3D{ 0, 0, -zOffset };
399 touchState->grabbed = true;
400 touchState->target = this;
401 touchState->touchDistance = z;
402 touchState->pressed = pressed;
403 touchState->cursorPos = point;
404 if (resetPrevious) {
405 touchState->previous = mappedPos;
406 touchState->timestamp = now;
407 }
408 view->setTouchpoint(d->m_containerItem, point, touchState->pointId, pressed && inside); // pressed state maintained outside, but release/press events must be sent when leave/enter
409 return true;
410 }
411
412 if (wasGrabbed) {
413 touchState->grabbed = false;
414 touchState->target = nullptr;
415 view->setTouchpoint(d->m_containerItem, point, touchState->pointId, false);
416 }
417
418 return false;
419}
420
430{
431 Q_D(const QQuick3DXrItem);
432 return d->m_color;
433}
434
435void QQuick3DXrItem::setColor(const QColor &newColor)
436{
437 Q_D(QQuick3DXrItem);
438 if (d->m_color == newColor)
439 return;
440 d->m_color = newColor;
442 d->updateContent();
443}
444
Definition lalr.h:136
The QColor class provides colors based on RGB, HSV or CMYK values.
Definition qcolor.h:31
static qint64 currentMSecsSinceEpoch() noexcept
\inmodule QtCore Represents a handle to a signal-slot (or signal-functor) connection.
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2960
void setParent(QObject *parent)
Makes the object a child of parent.
Definition qobject.cpp:2195
static bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *member)
\threadsafe
Definition qobject.cpp:3236
void destroyed(QObject *=nullptr)
This signal is emitted immediately before the object obj is destroyed, after any instances of QPointe...
\inmodule QtCore\reentrant
Definition qpoint.h:217
constexpr qreal x() const noexcept
Returns the x coordinate of this point.
Definition qpoint.h:343
constexpr qreal y() const noexcept
Returns the y coordinate of this point.
Definition qpoint.h:348
Q_INVOKABLE QVector3D mapPositionFromScene(const QVector3D &scenePosition) const
\qmlmethod vector3d QtQuick3D::Node::mapPositionFromScene(vector3d scenePosition)
void componentComplete() override
Invoked after the root component that caused this instantiation has completed construction.
void visibleChanged()
QQuick3DNode * parentNode() const
QQuaternion sceneRotation
QQmlListProperty< QObject > data()
QQuick3DObject * parent
\qmlproperty Object3D QtQuick3D::Object3D::parent This property holds the parent of the Object3D in a...
QPointer< QQuick3DXrView > m_XrView
QQuickRectangle * m_containerItem
void setContentItem(QQuickItem *newContentItem)
QMetaObject::Connection m_contentItemDestroyedConnection
void pixelsPerUnitChanged()
void widthChanged()
QQuickItem * contentItem
void setWidth(qreal newWidth)
void manualPixelsPerUnitChanged()
void setColor(const QColor &newColor)
void setManualPixelsPerUnit(bool newManualPixelsPerUnit)
void setPixelsPerUnit(qreal newPixelsPerUnit)
bool handleVirtualTouch(QQuick3DXrView *view, const QVector3D &pos, TouchState *touchState, QVector3D *offset)
void setHeight(qreal newHeight)
void contentItemChanged()
void colorChanged()
QQuick3DXrItem(QQuick3DNode *parent=nullptr)
\qmltype XrItem \inqmlmodule QtQuick3D.Xr \inherits Node
~QQuick3DXrItem() override
void setContentItem(QQuickItem *newContentItem)
void componentComplete() override
Invoked after the root component that caused this instantiation has completed construction.
The QQuickItem class provides the most basic of all visual items in \l {Qt Quick}.
Definition qquickitem.h:63
void setSize(const QSizeF &size)
void setScale(qreal)
void setParentItem(QQuickItem *parent)
qreal width
This property holds the width of this item.
Definition qquickitem.h:75
void setVisible(bool)
qreal height
This property holds the height of this item.
Definition qquickitem.h:76
void setTransformOrigin(TransformOrigin)
void setColor(const QColor &)
\inmodule QtCore
Definition qsize.h:208
The QVector3D class represents a vector or vertex in 3D space.
Definition qvectornd.h:171
Combined button and popup list for selecting options.
@ white
Definition qnamespace.h:31
#define Q_UNLIKELY(x)
bool qFuzzyCompare(qfloat16 p1, qfloat16 p2) noexcept
Definition qfloat16.h:333
#define qWarning
Definition qlogging.h:167
QT_BEGIN_NAMESPACE constexpr const T & qMin(const T &a, const T &b)
Definition qminmax.h:19
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat z
GLenum GLuint GLintptr offset
GLdouble GLdouble GLdouble GLdouble q
Definition qopenglext.h:259
static qreal calculatePPU(qreal pxWidth, qreal pxHeight, qreal diagonal)
#define emit
long long qint64
Definition qtypes.h:60
double qreal
Definition qtypes.h:187
QQuickView * view
[0]
Definition moc.h:23