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
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// Qt-Security score:significant reason:default
4
5
8#include <QtQuick3D/private/qquick3dnode_p_p.h>
9#include <QtQuick/private/qquickrectangle_p.h>
10#include <QtQuick/private/qquickitem_p.h>
11#include <QColor>
12
14
15
17{
18 Q_DECLARE_PUBLIC(QQuick3DXrItem)
19public:
23
53
70
72
74{
75 Q_Q(QQuick3DXrItem);
76 if (m_automaticHeightConnection && ((m_contentItem == nullptr) || !m_automaticHeight)) {
77 QObject::disconnect(m_automaticHeightConnection);
78 m_automaticHeightConnection = {};
79 }
80 if (m_contentItem) {
81 m_automaticHeightConnection = QObject::connect(m_contentItem, &QQuickItem::heightChanged, q, [this, q](){
82 qreal newHeight = m_contentItem->height()/m_pixelsPerUnit;
83 if (m_height != newHeight) {
84 m_height = newHeight;
85 emit q->heightChanged();
86 updateContent();
87 }
88 });
89 }
90}
91
93{
94 Q_Q(QQuick3DXrItem);
95 if (m_automaticWidthConnection && ((m_contentItem == nullptr) || !m_automaticHeight)) {
96 QObject::disconnect(m_automaticWidthConnection);
97 m_automaticWidthConnection = {};
98 }
99
100 if (m_contentItem) {
101 m_automaticWidthConnection = QObject::connect(m_contentItem, &QQuickItem::widthChanged, q, [this, q](){
102 qreal newWidth = m_contentItem->width()/m_pixelsPerUnit;
103 if (m_width != newWidth) {
104 m_width = newWidth;
105 emit q->widthChanged();
106 updateContent();
107 }
108 });
109 }
110}
111
123 bool m_automaticHeight = false;
124 bool m_automaticWidth = false;
125};
126
127static inline qreal calculatePPU(qreal pxWidth, qreal pxHeight, qreal diagonal)
128{
129 return (diagonal > 0) ? std::sqrt((pxWidth * pxWidth) + (pxHeight * pxHeight)) / diagonal : 1.0;
130}
131
132void QQuick3DXrItemPrivate::updateContent()
133{
134 if (!componentComplete)
135 return;
136 Q_Q(QQuick3DXrItem);
137 initParentItem();
138 m_containerItem->setColor(m_color);
139 if (m_contentItem) {
140 if (Q_UNLIKELY(m_manualPixelsPerUnit && m_pixelsPerUnit < 0)) {
141 qWarning() << "XrItem invalid pixelPerUnit" << m_pixelsPerUnit;
142 return;
143 }
144 qreal newScale;
146 newScale = 1.0 / m_pixelsPerUnit;
147
148 } else {
149 qreal diagonal = std::sqrt((m_width * m_width) + (m_height * m_height));
150 qreal ppu = calculatePPU(m_contentItem->width(), m_contentItem->height(), diagonal);
151 if (ppu <= 0)
152 ppu = 1.0;
153 q->setPixelsPerUnit(ppu);
154 newScale = 1.0 / ppu;
155 }
156 QSizeF newSize(m_width / newScale, m_height / newScale);
157 m_containerItem->setSize(newSize);
158 m_containerItem->setScale(newScale);
159 }
160}
161
162/*!
163 \qmltype XrItem
164 \inqmlmodule QtQuick3D.Xr
165 \inherits Node
166 \brief A virtual surface in 3D space that can hold 2D user interface content.
167 \since 6.8
168
169 The XrItem type is a Qt Quick 3D \l Node that represents a rectangle with \l width and \l height.
170 It holds one Qt Quick \l Item, specified by \l contentItem, and scales it to fit.
171 This gives a convenient way to take traditional 2D user interfaces and display them on a virtual surface that has
172 a real world size.
173
174 Any other children of the XrItem will be treated as normal children of a Node, and will not be scaled.
175
176 For example the following code will create a virtual surface that's 1 meter by 1 meter and with a content item
177 that's 600 pixels by 600 pixels. Note that the effect here is achieved by scaling the content item and not
178 by rendering the content item at a higher resolution.
179
180 \code
181 XrItem {
182 width: 100
183 height: 100
184 contentItem: Rectangle {
185 width: 600
186 height: 600
187 color: "red"
188 }
189 }
190 \endcode
191
192 The surface extends to the right of and below the XrItem's own origin, following the 2D
193 convention, so offset it by \c {x: -width / 2} and \c {y: height / 2} to center it on the
194 node position.
195
196 \sa {Coordinate Systems and Units in \qxr}
197*/
198QQuick3DXrItem::QQuick3DXrItem(QQuick3DNode *parent)
199 : QQuick3DNode(*(new QQuick3DXrItemPrivate()), parent)
200{
201}
202
204{
205 Q_D(QQuick3DXrItem);
206 if (d->m_XrView)
207 d->m_XrView->unregisterXrItem(this);
208}
209
211{
212 Q_D(QQuick3DXrItem);
213 QQuick3DNode::componentComplete(); // Sets d->componentComplete, so must be called first
214
215 auto findView = [this]() -> QQuick3DXrView * {
216 QQuick3DNode *parent = parentNode();
217 while (parent) {
218 if (auto *xrView = qobject_cast<QQuick3DXrView*>(parent))
219 return xrView;
220 parent = parent->parentNode();
221 }
222 return nullptr;
223 };
224 d->m_XrView = findView();
225 if (d->m_XrView)
226 d->m_XrView->registerXrItem(this);
227 else
228 qWarning("Could not find XrView for XrItem");
229 d->updateContent();
230}
231
232/*!
233 \qmlproperty Item XrItem::contentItem
234
235 This property holds the content item that will be displayed on the virtual surface.
236 The content item's size will be used to calculate the pixels per unit value and scale based on this item's size.
237
238 \sa pixelsPerUnit
239 */
241{
242 Q_D(const QQuick3DXrItem);
243 return d->m_contentItem;
244}
245
246void QQuick3DXrItem::setContentItem(QQuickItem *newContentItem)
247{
248 Q_D(QQuick3DXrItem);
249 if (d->m_contentItem == newContentItem)
250 return;
251
252 d->setContentItem(newContentItem);
253 emit contentItemChanged();
254}
255
256/*!
257 \qmlproperty real XrItem::pixelsPerUnit
258
259 This property determines how many pixels in the contentItems's 2D coordinate system will fit
260 in one unit of the XrItem's 3D coordinate system, that is, in one centimeter. By default, this
261 is calculated from the ratio of the two diagonals, so that the content fills the surface.
262
263 Set \l manualPixelsPerUnit to disable the default behavior and set the pixels per unit value manually.
264
265 \sa manualPixelsPerUnit, {Coordinate Systems and Units in \qxr}
266 */
268{
269 Q_D(const QQuick3DXrItem);
270 return d->m_pixelsPerUnit;
271}
272
273void QQuick3DXrItem::setPixelsPerUnit(qreal newPixelsPerUnit)
274{
275 Q_D(QQuick3DXrItem);
276 if (qFuzzyCompare(d->m_pixelsPerUnit, newPixelsPerUnit))
277 return;
278
279 d->m_pixelsPerUnit = newPixelsPerUnit;
280
281 if (d->m_manualPixelsPerUnit)
282 d->updateContent();
283
284 emit pixelsPerUnitChanged();
285}
286
287/*!
288 \qmlproperty bool XrItem::manualPixelsPerUnit
289
290 If this property is \c true, the ratio between the contentItems's 2D coordinate system and this
291 XrItem's 3D coordinate system is defined by the value of \l pixelsPerUnit. If this property is \c false,
292 the ratio is calculated based on the content item's size and the size of the XrItem.
293
294 \default false
295 \sa pixelsPerUnit
296*/
297
299{
300 Q_D(const QQuick3DXrItem);
301 return d->m_manualPixelsPerUnit;
302}
303
304void QQuick3DXrItem::setManualPixelsPerUnit(bool newManualPixelsPerUnit)
305{
306 Q_D(QQuick3DXrItem);
307 if (d->m_manualPixelsPerUnit == newManualPixelsPerUnit)
308 return;
309 d->m_manualPixelsPerUnit = newManualPixelsPerUnit;
310 d->updateContent();
311 emit manualPixelsPerUnitChanged();
312}
313
314/*!
315 \qmlproperty real XrItem::width
316
317 This property defines the width of the XrItem in the 3D coordinate system, that is,
318 in centimeters. This is not the same as the pixel width of the \l contentItem;
319 \l pixelsPerUnit relates the two.
320
321 \sa height, pixelsPerUnit, {Coordinate Systems and Units in \qxr}
322*/
323
325{
326 Q_D(const QQuick3DXrItem);
327 return d->m_width;
328}
329
330void QQuick3DXrItem::setWidth(qreal newWidth)
331{
332 Q_D(QQuick3DXrItem);
333 if ((d->m_width == newWidth) || d->m_automaticWidth)
334 return;
335 d->m_width = newWidth;
336 emit widthChanged();
337
338 d->updateContent();
339}
340
341/*!
342 \qmlproperty real XrItem::height
343
344 This property defines the height of the XrItem in the 3D coordinate system, that is,
345 in centimeters. This is not the same as the pixel height of the \l contentItem;
346 \l pixelsPerUnit relates the two.
347
348 \sa width, pixelsPerUnit, {Coordinate Systems and Units in \qxr}
349*/
350
352{
353 Q_D(const QQuick3DXrItem);
354 return d->m_height;
355}
356
357void QQuick3DXrItem::setHeight(qreal newHeight)
358{
359 Q_D(QQuick3DXrItem);
360 if ((d->m_height == newHeight) || d->m_automaticHeight)
361 return;
362 d->m_height = newHeight;
363 emit heightChanged();
364
365 d->updateContent();
366}
367
368/*!
369 \qmlproperty color XrItem::color
370
371 This property defines the background color of the XrItem.
372
373 \default "white"
374 */
375
377{
378 Q_D(const QQuick3DXrItem);
379 return d->m_color;
380}
381
382void QQuick3DXrItem::setColor(const QColor &newColor)
383{
384 Q_D(QQuick3DXrItem);
385 if (d->m_color == newColor)
386 return;
387 d->m_color = newColor;
388 emit colorChanged();
389 d->updateContent();
390}
391
392/*!
393 \qmlproperty bool XrItem::automaticHeight
394
395 When set to true XrItem will ignore height set through height property and use height calculated from contentItem height.
396
397 \default "false"
398 \sa automaticWidth
399 */
400
402{
403 Q_D(const QQuick3DXrItem);
404 return d->m_automaticHeight;
405}
406
407void QQuick3DXrItem::setAutomaticHeight(bool newAutomaticHeight)
408{
409 Q_D(QQuick3DXrItem);
410 if (d->m_automaticHeight == newAutomaticHeight) {
411 return;
412 }
413
414 d->m_automaticHeight = newAutomaticHeight;
415 d->setAutomaticHeightConnection();
416 d->updateContent();
417 emit automaticHeightChanged();
418}
419
420/*!
421 \qmlproperty bool XrItem::automaticWidth
422
423 When set to true XrItem will ignore width set through width property and use width calculated from contentItem width.
424
425 \default "false"
426 \sa automaticHeight
427 */
428
430{
431 Q_D(const QQuick3DXrItem);
432 return d->m_automaticWidth;
433}
434
435void QQuick3DXrItem::setAutomaticWidth(bool newAutomaticWidth)
436{
437 Q_D(QQuick3DXrItem);
438 if (d->m_automaticWidth == newAutomaticWidth)
439 return;
440
441 d->m_automaticWidth = newAutomaticWidth;
442 d->setAutomaticWidthConnection();
443 d->updateContent();
444 emit automaticWidthChanged();
445}
446
447QT_END_NAMESPACE
QPointer< QQuick3DXrView > m_XrView
QQuickRectangle * m_containerItem
QMetaObject::Connection m_automaticHeightConnection
QMetaObject::Connection m_contentItemDestroyedConnection
QMetaObject::Connection m_automaticWidthConnection
bool manualPixelsPerUnit() const
\qmlproperty bool XrItem::manualPixelsPerUnit
void setAutomaticWidth(bool newAutomaticHeight)
void setWidth(qreal newWidth)
qreal width() const
\qmlproperty real XrItem::width
void setColor(const QColor &newColor)
void setManualPixelsPerUnit(bool newManualPixelsPerUnit)
void setPixelsPerUnit(qreal newPixelsPerUnit)
QColor color() const
\qmlproperty color XrItem::color
qreal height() const
\qmlproperty real XrItem::height
bool automaticHeight() const
\qmlproperty bool XrItem::automaticHeight
bool automaticWidth() const
\qmlproperty bool XrItem::automaticWidth
QQuickItem * contentItem() const
\qmlproperty Item XrItem::contentItem
void setHeight(qreal newHeight)
~QQuick3DXrItem() override
qreal pixelsPerUnit() const
\qmlproperty real XrItem::pixelsPerUnit
void setAutomaticHeight(bool newAutomaticHeight)
void setContentItem(QQuickItem *newContentItem)
void componentComplete() override
Invoked after the root component that caused this instantiation has completed construction.
Combined button and popup list for selecting options.
static qreal calculatePPU(qreal pxWidth, qreal pxHeight, qreal diagonal)