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
qquick3ditem2d.cpp
Go to the documentation of this file.
1// Copyright (C) 2020 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
4#include <QtQuick3D/qquick3dobject.h>
5#include <QtQuick3D/private/qquick3ditem2d_p.h>
6
7#include <QtQuick/private/qquickitem_p.h>
8#include <QtQuick/private/qsgrenderer_p.h>
9#include <QtQuick/private/qquickwindow_p.h>
10
11#include <QtQuick3DRuntimeRender/private/qssgrenderitem2d_p.h>
13
14#include <QtGui/rhi/qrhi.h>
15
17
18/*
19internal
20*/
21
22QQuick3DItem2D::QQuick3DItem2D(QQuickItem *item, QQuick3DNode *parent)
23 : QQuick3DNode(*(new QQuick3DNodePrivate(QQuick3DNodePrivate::Type::Item2D)), parent)
24{
25 m_contentItem = new QQuickItem();
26 m_contentItem->setObjectName(QLatin1String("parent of ") + item->objectName()); // for debugging
27 // No size is set for m_contentItem. This is intentional, otherwise item2d anchoring breaks.
28 QQuickItemPrivate::get(m_contentItem)->ensureSubsceneDeliveryAgent();
29 QQmlEngine::setObjectOwnership(m_contentItem, QQmlEngine::CppOwnership);
30
31 connect(m_contentItem, &QQuickItem::childrenChanged, this, &QQuick3DObject::update);
32 addChildItem(item);
33}
34
35QQuick3DItem2D::~QQuick3DItem2D()
36{
37 delete m_contentItem;
38}
39
40void QQuick3DItem2D::addChildItem(QQuickItem *item)
41{
42 item->setParent(m_contentItem);
43 item->setParentItem(m_contentItem);
44 QQuickItemPrivate::get(item)->addItemChangeListener(this, QQuickItemPrivate::ChangeType::Destroyed);
45 connect(item, &QQuickItem::enabledChanged, this, &QQuick3DItem2D::updatePicking);
46 connect(item, &QQuickItem::visibleChanged, this, &QQuick3DItem2D::updatePicking);
47 m_sourceItems.append(item);
48 update();
49}
50void QQuick3DItem2D::removeChildItem(QQuickItem *item)
51{
52 m_sourceItems.removeOne(item);
53 if (item)
54 QQuickItemPrivate::get(item)->removeItemChangeListener(this, QQuickItemPrivate::ChangeType::Destroyed);
55 if (m_sourceItems.isEmpty())
56 emit allChildrenRemoved();
57 else
58 update();
59}
60
61QQuickItem *QQuick3DItem2D::contentItem() const
62{
63 return m_contentItem;
64}
65
66void QQuick3DItem2D::itemDestroyed(QQuickItem *item)
67{
68 removeChildItem(item);
69}
70
71void QQuick3DItem2D::updatePicking()
72{
73 m_pickingDirty = true;
74 update();
75}
76
77QSSGRenderGraphObject *QQuick3DItem2D::updateSpatialNode(QSSGRenderGraphObject *node)
78{
79 auto *sourceItemPrivate = QQuickItemPrivate::get(m_contentItem);
80 QQuickWindow *window = m_contentItem->window();
81
82 if (!window) {
83 const auto &manager = QQuick3DObjectPrivate::get(this)->sceneManager;
84 window = manager->window();
85 }
86
87 if (!node) {
88 markAllDirty();
89 auto *backEndNode = new QSSGRenderItem2D();
90 backEndNode->m_frontEndObject = this;
91 node = backEndNode;
92 }
93
94 QQuick3DNode::updateSpatialNode(node);
95
96 auto itemNode = static_cast<QSSGRenderItem2D *>(node);
97
98 itemNode->m_rootNode = sourceItemPrivate->rootNode();
99 if (!itemNode->m_rootNode) {
100 QQuickWindowPrivate::get(window)->updateDirtyNode(m_contentItem);
101 itemNode->m_rootNode = sourceItemPrivate->rootNode();
102 if (!itemNode->m_rootNode) {
103 qWarning() << "Item2D is not initialized. It will not be shown.";
104 return nullptr;
105 }
106 }
107
108 if (m_pickingDirty) {
109 m_pickingDirty = false;
110 bool isPickable = false;
111 for (const auto &item : std::as_const(m_sourceItems)) {
112 // Enable picking for Item2D if any of its child is visible and enabled.
113 if (item->isVisible() && item->isEnabled()) {
114 isPickable = true;
115 break;
116 }
117 }
118 itemNode->setState(QSSGRenderNode::LocalState::Pickable, isPickable);
119 }
120
121 return node;
122}
123
124void QQuick3DItem2D::markAllDirty()
125{
126 m_pickingDirty = true;
127
128 QQuick3DNode::markAllDirty();
129}
130
131void QQuick3DItem2D::preSync()
132{
133 const auto &manager = QQuick3DObjectPrivate::get(this)->sceneManager;
134 auto *sourcePrivate = QQuickItemPrivate::get(m_contentItem);
135 auto *window = manager->window();
136 if (m_window != window) {
137 update(); // Just schedule an upate immediately.
138 if (m_window) {
139 disconnect(m_window, SIGNAL(destroyed(QObject*)), this, SLOT(derefWindow(QObject*)));
140 sourcePrivate->derefWindow();
141 }
142 m_window = window;
143 sourcePrivate->refWindow(window);
144 connect(window, SIGNAL(destroyed(QObject*)), this, SLOT(derefWindow(QObject*)));
145 sourcePrivate->refFromEffectItem(true);
146 }
147}
148
149static void detachWindow(QQuickItem *item, QObject *win)
150{
151 auto *itemPriv = QQuickItemPrivate::get(item);
152
153 if (win == itemPriv->window) {
154 itemPriv->window = nullptr;
155 itemPriv->windowRefCount = 0;
156
157 itemPriv->prevDirtyItem = nullptr;
158 itemPriv->nextDirtyItem = nullptr;
159 }
160
161 for (auto *child: itemPriv->childItems)
162 detachWindow(child, win);
163}
164
165void QQuick3DItem2D::derefWindow(QObject *win)
166{
167 detachWindow(m_contentItem, win);
168}
169
170QT_END_NAMESPACE
static void detachWindow(QQuickItem *item, QObject *win)