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