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
12QT_BEGIN_NAMESPACE
13
14namespace Qt3DCore {
15
16class QScenePrivate
17{
18public:
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
39QScene::QScene(QAspectEngine *engine)
40 : d_ptr(new QScenePrivate(engine))
41{
42}
43
44QScene::~QScene()
45{
46}
47
48QAspectEngine *QScene::engine() const
49{
50 Q_D(const QScene);
51 return d->m_engine;
52}
53
54// Called by main thread only
55void 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
67void 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
79QNode *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
86QList<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
97QNode *QScene::rootNode() const
98{
99 Q_D(const QScene);
100 return d->m_rootNode;
101}
102
103void QScene::setArbiter(QChangeArbiter *arbiter)
104{
105 Q_D(QScene);
106 d->m_arbiter = arbiter;
107}
108
109QChangeArbiter *QScene::arbiter() const
110{
111 Q_D(const QScene);
112 return d->m_arbiter;
113}
114
115QList<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
126void 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
133void 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
140bool 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
148NodePostConstructorInit *QScene::postConstructorInit() const
149{
150 Q_D(const QScene);
151 return d->m_postConstructorInit.get();
152}
153
154QScene::DirtyNodeSet QScene::dirtyBits()
155{
156 Q_D(QScene);
157 return d->m_dirtyBits;
158}
159
160void QScene::clearDirtyBits()
161{
162 Q_D(QScene);
163 d->m_dirtyBits = {};
164}
165
166void QScene::markDirty(QScene::DirtyNodeSet changes)
167{
168 Q_D(QScene);
169 d->m_dirtyBits |= changes;
170}
171
172void QScene::setRootNode(QNode *root)
173{
174 Q_D(QScene);
175 d->m_rootNode = root;
176}
177
178} // Qt3D
179
180QT_END_NAMESPACE
181

source code of qt3d/src/core/qscene.cpp