1 | // Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB). |
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
3 | |
4 | #include "qscene_p.h" |
5 | |
6 | #include <Qt3DCore/qnode.h> |
7 | #include <QtCore/QHash> |
8 | #include <QtCore/QReadLocker> |
9 | |
10 | #include <Qt3DCore/private/qnode_p.h> |
11 | |
12 | QT_BEGIN_NAMESPACE |
13 | |
14 | namespace Qt3DCore { |
15 | |
16 | class QScenePrivate |
17 | { |
18 | public: |
19 | QScenePrivate(QAspectEngine *engine) |
20 | : m_engine(engine) |
21 | , m_arbiter(nullptr) |
22 | , m_postConstructorInit(new NodePostConstructorInit) |
23 | , m_rootNode(nullptr) |
24 | { |
25 | } |
26 | |
27 | QAspectEngine *m_engine; |
28 | QHash<QNodeId, QNode *> m_nodeLookupTable; |
29 | QMultiHash<QNodeId, QNodeId> m_componentToEntities; |
30 | QChangeArbiter *m_arbiter; |
31 | QScopedPointer<NodePostConstructorInit> m_postConstructorInit; |
32 | mutable QReadWriteLock m_lock; |
33 | mutable QReadWriteLock m_nodePropertyTrackModeLock; |
34 | QNode *m_rootNode; |
35 | QScene::DirtyNodeSet m_dirtyBits; |
36 | }; |
37 | |
38 | |
39 | QScene::QScene(QAspectEngine *engine) |
40 | : d_ptr(new QScenePrivate(engine)) |
41 | { |
42 | } |
43 | |
44 | QScene::~QScene() |
45 | { |
46 | } |
47 | |
48 | QAspectEngine *QScene::engine() const |
49 | { |
50 | Q_D(const QScene); |
51 | return d->m_engine; |
52 | } |
53 | |
54 | // Called by main thread only |
55 | void QScene::addObservable(QNode *observable) |
56 | { |
57 | Q_D(QScene); |
58 | if (observable != nullptr) { |
59 | QWriteLocker lock(&d->m_lock); |
60 | d->m_nodeLookupTable.insert(key: observable->id(), value: observable); |
61 | if (d->m_arbiter != nullptr) |
62 | observable->d_func()->setArbiter(d->m_arbiter); |
63 | } |
64 | } |
65 | |
66 | // Called by main thread |
67 | void QScene::removeObservable(QNode *observable) |
68 | { |
69 | Q_D(QScene); |
70 | if (observable != nullptr) { |
71 | QWriteLocker lock(&d->m_lock); |
72 | const QNodeId nodeUuid = observable->id(); |
73 | d->m_nodeLookupTable.remove(key: nodeUuid); |
74 | observable->d_func()->setArbiter(nullptr); |
75 | } |
76 | } |
77 | |
78 | // Called by any thread |
79 | QNode *QScene::lookupNode(QNodeId id) const |
80 | { |
81 | Q_D(const QScene); |
82 | QReadLocker lock(&d->m_lock); |
83 | return d->m_nodeLookupTable.value(key: id); |
84 | } |
85 | |
86 | QList<QNode *> QScene::lookupNodes(const QList<QNodeId> &ids) const |
87 | { |
88 | Q_D(const QScene); |
89 | QReadLocker lock(&d->m_lock); |
90 | QList<QNode *> nodes; |
91 | nodes.reserve(asize: ids.size()); |
92 | for (QNodeId id : ids) |
93 | nodes.push_back(t: d->m_nodeLookupTable.value(key: id)); |
94 | return nodes; |
95 | } |
96 | |
97 | QNode *QScene::rootNode() const |
98 | { |
99 | Q_D(const QScene); |
100 | return d->m_rootNode; |
101 | } |
102 | |
103 | void QScene::setArbiter(QChangeArbiter *arbiter) |
104 | { |
105 | Q_D(QScene); |
106 | d->m_arbiter = arbiter; |
107 | } |
108 | |
109 | QChangeArbiter *QScene::arbiter() const |
110 | { |
111 | Q_D(const QScene); |
112 | return d->m_arbiter; |
113 | } |
114 | |
115 | QList<QNodeId> QScene::entitiesForComponent(QNodeId id) const |
116 | { |
117 | Q_D(const QScene); |
118 | QReadLocker lock(&d->m_lock); |
119 | QList<QNodeId> result; |
120 | const auto p = d->m_componentToEntities.equal_range(key: id); |
121 | for (auto it = p.first; it != p.second; ++it) |
122 | result.push_back(t: *it); |
123 | return result; |
124 | } |
125 | |
126 | void QScene::addEntityForComponent(QNodeId componentUuid, QNodeId entityUuid) |
127 | { |
128 | Q_D(QScene); |
129 | QWriteLocker lock(&d->m_lock); |
130 | d->m_componentToEntities.insert(key: componentUuid, value: entityUuid); |
131 | } |
132 | |
133 | void QScene::removeEntityForComponent(QNodeId componentUuid, QNodeId entityUuid) |
134 | { |
135 | Q_D(QScene); |
136 | QWriteLocker lock(&d->m_lock); |
137 | d->m_componentToEntities.remove(key: componentUuid, value: entityUuid); |
138 | } |
139 | |
140 | bool QScene::hasEntityForComponent(QNodeId componentUuid, QNodeId entityUuid) |
141 | { |
142 | Q_D(QScene); |
143 | QReadLocker lock(&d->m_lock); |
144 | const auto range = d->m_componentToEntities.equal_range(key: componentUuid); |
145 | return std::find(first: range.first, last: range.second, val: entityUuid) != range.second; |
146 | } |
147 | |
148 | NodePostConstructorInit *QScene::postConstructorInit() const |
149 | { |
150 | Q_D(const QScene); |
151 | return d->m_postConstructorInit.get(); |
152 | } |
153 | |
154 | QScene::DirtyNodeSet QScene::dirtyBits() |
155 | { |
156 | Q_D(QScene); |
157 | return d->m_dirtyBits; |
158 | } |
159 | |
160 | void QScene::clearDirtyBits() |
161 | { |
162 | Q_D(QScene); |
163 | d->m_dirtyBits = {}; |
164 | } |
165 | |
166 | void QScene::markDirty(QScene::DirtyNodeSet changes) |
167 | { |
168 | Q_D(QScene); |
169 | d->m_dirtyBits |= changes; |
170 | } |
171 | |
172 | void QScene::setRootNode(QNode *root) |
173 | { |
174 | Q_D(QScene); |
175 | d->m_rootNode = root; |
176 | } |
177 | |
178 | } // Qt3D |
179 | |
180 | QT_END_NAMESPACE |
181 | |