1/****************************************************************************
2**
3** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the Qt3D module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#ifndef QT3DCORE_QNODE_P_H
41#define QT3DCORE_QNODE_P_H
42
43//
44// W A R N I N G
45// -------------
46//
47// This file is not part of the Qt API. It exists for the convenience
48// of other Qt classes. This header file may change from version to
49// version without notice, or even be removed.
50//
51// We mean it.
52//
53
54#include <Qt3DCore/qnode.h>
55
56#include <functional>
57#include <vector>
58
59#include <Qt3DCore/private/propertychangehandler_p.h>
60#include <Qt3DCore/private/qchangearbiter_p.h>
61#include <Qt3DCore/private/qobservableinterface_p.h>
62#include <Qt3DCore/private/qt3dcore_global_p.h>
63#include <QtCore/private/qobject_p.h>
64#include <QQueue>
65
66QT_BEGIN_NAMESPACE
67
68namespace Qt3DCore {
69
70class QNode;
71class QAspectEngine;
72
73class Q_3DCORE_PRIVATE_EXPORT QNodePrivate : public QObjectPrivate, public QObservableInterface
74{
75public:
76 QNodePrivate();
77 ~QNodePrivate();
78
79 void init(QNode *parent);
80
81 virtual void setScene(QScene *scene);
82 QScene *scene() const;
83
84 void setArbiter(QLockableObserverInterface *arbiter) override;
85
86 void notifyPropertyChange(const char *name, const QVariant &value);
87 void notifyDynamicPropertyChange(const QByteArray &name, const QVariant &value);
88 void notifyObservers(const QSceneChangePtr &change) override;
89
90 void insertTree(QNode *treeRoot, int depth = 0);
91 void updatePropertyTrackMode();
92
93 void update();
94 QT_WARNING_PUSH
95 QT_WARNING_DISABLE_DEPRECATED
96 void updateNode(QNode *node, const char* property, ChangeFlag change);
97 QT_WARNING_POP
98
99 Q_DECLARE_PUBLIC(QNode)
100
101 // For now this just protects access to the m_changeArbiter.
102 // Later on we may decide to extend support for multiple observers.
103 QAbstractArbiter *m_changeArbiter;
104 QMetaObject *m_typeInfo;
105 QScene *m_scene;
106 mutable QNodeId m_id;
107 QNodeId m_parentId; // Store this so we have it even in parent's QObject dtor
108 bool m_blockNotifications;
109 bool m_hasBackendNode;
110 bool m_enabled;
111 bool m_notifiedParent;
112 QNode::PropertyTrackingMode m_defaultPropertyTrackMode;
113 QHash<QString, QNode::PropertyTrackingMode> m_trackedPropertiesOverrides;
114
115 static QNodePrivate *get(QNode *q);
116 static const QNodePrivate *get(const QNode *q);
117 static void nodePtrDeleter(QNode *q);
118
119 template<typename Caller, typename NodeType>
120 using DestructionFunctionPointer = void (Caller::*)(NodeType *);
121
122 template<typename Caller, typename NodeType, typename PropertyType>
123 void registerDestructionHelper(NodeType *, DestructionFunctionPointer<Caller, NodeType>, PropertyType);
124
125 template<typename Caller, typename NodeType>
126 void registerDestructionHelper(NodeType *node, DestructionFunctionPointer<Caller, NodeType> func, NodeType *&)
127 {
128 // If the node is destoyed, we make sure not to keep a dangling pointer to it
129 Q_Q(QNode);
130 auto f = [q, func]() { (static_cast<Caller *>(q)->*func)(nullptr); };
131 m_destructionConnections.push_back({node, QObject::connect(node, &QNode::nodeDestroyed, f)});
132 }
133
134 template<typename Caller, typename NodeType>
135 void registerDestructionHelper(NodeType *node, DestructionFunctionPointer<Caller, NodeType> func, QVector<NodeType*> &)
136 {
137 // If the node is destoyed, we make sure not to keep a dangling pointer to it
138 Q_Q(QNode);
139 auto f = [q, func, node]() { (static_cast<Caller *>(q)->*func)(node); };
140 m_destructionConnections.push_back({node, QObject::connect(node, &QNode::nodeDestroyed, f)});
141 }
142
143 template<typename Caller, typename NodeType>
144 void registerDestructionHelper(NodeType *node, DestructionFunctionPointer<Caller, NodeType> func, QList<NodeType*> &)
145 {
146 // If the node is destoyed, we make sure not to keep a dangling pointer to it
147 Q_Q(QNode);
148 auto f = [q, func, node]() { (static_cast<Caller *>(q)->*func)(node); };
149 m_destructionConnections.push_back({node, QObject::connect(node, &QNode::nodeDestroyed, f)});
150 }
151
152 template<typename Caller, typename NodeType>
153 void registerDestructionHelper(NodeType *node, DestructionFunctionPointer<Caller, NodeType> func, std::vector<NodeType*> &)
154 {
155 // If the node is destoyed, we make sure not to keep a dangling pointer to it
156 Q_Q(QNode);
157 auto f = [q, func, node]() { (static_cast<Caller *>(q)->*func)(node); };
158 m_destructionConnections.push_back({node, QObject::connect(node, &QNode::nodeDestroyed, f)});
159 }
160
161 template<typename Caller, typename ValueType>
162 using DestructionFunctionValue = void (Caller::*)(const ValueType&);
163
164 template<typename Caller, typename NodeType, typename ValueType>
165 void registerDestructionHelper(NodeType *node, DestructionFunctionValue<Caller, ValueType> func, NodeType *&,
166 const ValueType &resetValue)
167 {
168 // If the node is destoyed, we make sure not to keep a dangling pointer to it
169 Q_Q(QNode);
170 auto f = [q, func, resetValue]() { (static_cast<Caller *>(q)->*func)(resetValue); };
171 m_destructionConnections.push_back({node, QObject::connect(node, &QNode::nodeDestroyed, f)});
172 }
173
174 template<typename Caller, typename NodeType>
175 void registerPrivateDestructionHelper(NodeType *node, DestructionFunctionPointer<Caller, NodeType> func)
176 {
177 // If the node is destoyed, we make sure not to keep a dangling pointer to it
178 auto f = [this, func, node]() { (static_cast<Caller *>(this)->*func)(node); };
179 m_destructionConnections.push_back({node, QObject::connect(node, &QNode::nodeDestroyed, f)});
180 }
181
182 void unregisterDestructionHelper(QNode *node)
183 {
184 m_destructionConnections.erase(abegin: std::remove_if(first: m_destructionConnections.begin(),
185 last: m_destructionConnections.end(),
186 pred: [node] (const QPair<QNode *, QMetaObject::Connection> &nodeConnectionPair) {
187 if (nodeConnectionPair.first == node) {
188 QObject::disconnect(nodeConnectionPair.second);
189 return true;
190 }
191 return false;
192 }),
193 aend: m_destructionConnections.end());
194 }
195
196 static const QMetaObject *findStaticMetaObject(const QMetaObject *metaObject);
197
198 void _q_postConstructorInit();
199 void _q_ensureBackendNodeCreated();
200
201private:
202 void createBackendNode();
203 void notifyDestructionChangesAndRemoveFromScene();
204 void _q_addChild(QNode *childNode);
205 void _q_removeChild(QNode *childNode);
206 void _q_setParentHelper(QNode *parent);
207 void registerNotifiedProperties();
208 void unregisterNotifiedProperties();
209 void propertyChanged(int propertyIndex);
210
211 void setSceneHelper(QNode *root);
212 void unsetSceneHelper(QNode *root);
213 void addEntityComponentToScene(QNode *root);
214
215 friend class PropertyChangeHandler<QNodePrivate>;
216 bool m_propertyChangesSetup;
217 PropertyChangeHandler<QNodePrivate> m_signals;
218 QVector<QPair<QNode *, QMetaObject::Connection>> m_destructionConnections;
219};
220
221class NodePostConstructorInit : public QObject
222{
223 Q_OBJECT
224public:
225 NodePostConstructorInit(QObject *parent = nullptr);
226 virtual ~NodePostConstructorInit();
227 void removeNode(QNode *node);
228 void addNode(QNode *node);
229
230public Q_SLOTS:
231 void processNodes();
232
233private:
234 QQueue<QNodePrivate *> m_nodesToConstruct;
235 bool m_requestedProcessing;
236};
237
238} // namespace Qt3DCore
239
240QT_END_NAMESPACE
241
242#endif // QT3DCORE_NODE_P_H
243

source code of qt3d/src/core/nodes/qnode_p.h