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*/
192QQuick3DXrItem::QQuick3DXrItem(QQuick3DNode *parent)
193 : QQuick3DNode(*(new QQuick3DXrItemPrivate()), parent)
194{
195}
196
198{
199 Q_D(QQuick3DXrItem);
200 if (d->m_XrView)
201 d->m_XrView->unregisterXrItem(this);
202}
203
205{
206 Q_D(QQuick3DXrItem);
207 QQuick3DNode::componentComplete(); // Sets d->componentComplete, so must be called first
208
209 auto findView = [this]() -> QQuick3DXrView * {
210 QQuick3DNode *parent = parentNode();
211 while (parent) {
212 if (auto *xrView = qobject_cast<QQuick3DXrView*>(parent))
213 return xrView;
214 parent = parent->parentNode();
215 }
216 return nullptr;
217 };
218 d->m_XrView = findView();
219 if (d->m_XrView)
220 d->m_XrView->registerXrItem(this);
221 else
222 qWarning("Could not find XrView for XrItem");
223 d->updateContent();
224}
225
226/*!
227 \qmlproperty Item XrItem::contentItem
228
229 This property holds the content item that will be displayed on the virtual surface.
230 The content item's size will be used to calculate the pixels per unit value and scale based on this item's size.
231
232 \sa pixelsPerUnit
233 */
235{
236 Q_D(const QQuick3DXrItem);
237 return d->m_contentItem;
238}
239
240void QQuick3DXrItem::setContentItem(QQuickItem *newContentItem)
241{
242 Q_D(QQuick3DXrItem);
243 if (d->m_contentItem == newContentItem)
244 return;
245
246 d->setContentItem(newContentItem);
247 emit contentItemChanged();
248}
249
250/*!
251 \qmlproperty real XrItem::pixelsPerUnit
252
253 This property determines how many pixels in the contentItems's 2D coordinate system will fit
254 in one unit of the XrItem's 3D coordinate system. By default, this is calculated based on the
255 content item's size and the size of the XrItem.
256
257 Set \l manualPixelsPerUnit to disable the default behavior and set the pixels per unit value manually.
258
259 \sa manualPixelsPerUnit
260 */
262{
263 Q_D(const QQuick3DXrItem);
264 return d->m_pixelsPerUnit;
265}
266
267void QQuick3DXrItem::setPixelsPerUnit(qreal newPixelsPerUnit)
268{
269 Q_D(QQuick3DXrItem);
270 if (qFuzzyCompare(d->m_pixelsPerUnit, newPixelsPerUnit))
271 return;
272
273 d->m_pixelsPerUnit = newPixelsPerUnit;
274
275 if (d->m_manualPixelsPerUnit)
276 d->updateContent();
277
278 emit pixelsPerUnitChanged();
279}
280
281/*!
282 \qmlproperty bool XrItem::manualPixelsPerUnit
283
284 If this property is \c true, the ratio between the contentItems's 2D coordinate system and this
285 XrItem's 3D coordinate system is defined by the value of \l pixelsPerUnit. If this property is \c false,
286 the ratio is calculated based on the content item's size and the size of the XrItem.
287
288 \default false
289 \sa pixelsPerUnit
290*/
291
293{
294 Q_D(const QQuick3DXrItem);
295 return d->m_manualPixelsPerUnit;
296}
297
298void QQuick3DXrItem::setManualPixelsPerUnit(bool newManualPixelsPerUnit)
299{
300 Q_D(QQuick3DXrItem);
301 if (d->m_manualPixelsPerUnit == newManualPixelsPerUnit)
302 return;
303 d->m_manualPixelsPerUnit = newManualPixelsPerUnit;
304 d->updateContent();
305 emit manualPixelsPerUnitChanged();
306}
307
308/*!
309 \qmlproperty real XrItem::width
310
311 This property defines the width of the XrItem in the 3D coordinate system.
312 \sa height
313*/
314
316{
317 Q_D(const QQuick3DXrItem);
318 return d->m_width;
319}
320
321void QQuick3DXrItem::setWidth(qreal newWidth)
322{
323 Q_D(QQuick3DXrItem);
324 if ((d->m_width == newWidth) || d->m_automaticWidth)
325 return;
326 d->m_width = newWidth;
327 emit widthChanged();
328
329 d->updateContent();
330}
331
332/*!
333 \qmlproperty real XrItem::height
334
335 This property defines the height of the XrItem in the 3D coordinate system.
336 \sa width
337*/
338
340{
341 Q_D(const QQuick3DXrItem);
342 return d->m_height;
343}
344
345void QQuick3DXrItem::setHeight(qreal newHeight)
346{
347 Q_D(QQuick3DXrItem);
348 if ((d->m_height == newHeight) || d->m_automaticHeight)
349 return;
350 d->m_height = newHeight;
351 emit heightChanged();
352
353 d->updateContent();
354}
355
356/*!
357 \qmlproperty color XrItem::color
358
359 This property defines the background color of the XrItem.
360
361 \default "white"
362 */
363
365{
366 Q_D(const QQuick3DXrItem);
367 return d->m_color;
368}
369
370void QQuick3DXrItem::setColor(const QColor &newColor)
371{
372 Q_D(QQuick3DXrItem);
373 if (d->m_color == newColor)
374 return;
375 d->m_color = newColor;
376 emit colorChanged();
377 d->updateContent();
378}
379
380/*!
381 \qmlproperty bool XrItem::automaticHeight
382
383 When set to true XrItem will ignore height set through height property and use height calculated from contentItem height.
384
385 \default "false"
386 \sa automaticWidth
387 */
388
390{
391 Q_D(const QQuick3DXrItem);
392 return d->m_automaticHeight;
393}
394
395void QQuick3DXrItem::setAutomaticHeight(bool newAutomaticHeight)
396{
397 Q_D(QQuick3DXrItem);
398 if (d->m_automaticHeight == newAutomaticHeight) {
399 return;
400 }
401
402 d->m_automaticHeight = newAutomaticHeight;
403 d->setAutomaticHeightConnection();
404 d->updateContent();
405 emit automaticHeightChanged();
406}
407
408/*!
409 \qmlproperty bool XrItem::automaticWidth
410
411 When set to true XrItem will ignore width set through width property and use width calculated from contentItem width.
412
413 \default "false"
414 \sa automaticHeight
415 */
416
418{
419 Q_D(const QQuick3DXrItem);
420 return d->m_automaticWidth;
421}
422
423void QQuick3DXrItem::setAutomaticWidth(bool newAutomaticWidth)
424{
425 Q_D(QQuick3DXrItem);
426 if (d->m_automaticWidth == newAutomaticWidth)
427 return;
428
429 d->m_automaticWidth = newAutomaticWidth;
430 d->setAutomaticWidthConnection();
431 d->updateContent();
432 emit automaticWidthChanged();
433}
434
435QT_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)