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
58#include <Qt3DCore/private/propertychangehandler_p.h>
59#include <Qt3DCore/private/qchangearbiter_p.h>
60#include <Qt3DCore/private/qobservableinterface_p.h>
61#include <Qt3DCore/private/qt3dcore_global_p.h>
62#include <QtCore/private/qobject_p.h>
63#include <QQueue>
64
65QT_BEGIN_NAMESPACE
66
67namespace Qt3DCore {
68
69class QNode;
70class QAspectEngine;
71
72class Q_3DCORE_PRIVATE_EXPORT QNodePrivate : public QObjectPrivate, public QObservableInterface
73{
74public:
75 QNodePrivate();
76 ~QNodePrivate();
77
78 void init(QNode *parent);
79
80 virtual void setScene(QScene *scene);
81 QScene *scene() const;
82
83 void setArbiter(QLockableObserverInterface *arbiter) override;
84
85 void notifyPropertyChange(const char *name, const QVariant &value);
86 void notifyDynamicPropertyChange(const QByteArray &name, const QVariant &value);
87 void notifyObservers(const QSceneChangePtr &change) override;
88
89 void insertTree(QNode *treeRoot, int depth = 0);
90 void updatePropertyTrackMode();
91
92 Q_DECLARE_PUBLIC(QNode)
93
94 // For now this just protects access to the m_changeArbiter.
95 // Later on we may decide to extend support for multiple observers.
96 QAbstractArbiter *m_changeArbiter;
97 QMetaObject *m_typeInfo;
98 QScene *m_scene;
99 mutable QNodeId m_id;
100 QNodeId m_parentId; // Store this so we have it even in parent's QObject dtor
101 bool m_blockNotifications;
102 bool m_hasBackendNode;
103 bool m_enabled;
104 bool m_notifiedParent;
105 QNode::PropertyTrackingMode m_defaultPropertyTrackMode;
106 QHash<QString, QNode::PropertyTrackingMode> m_trackedPropertiesOverrides;
107
108 static QNodePrivate *get(QNode *q);
109 static void nodePtrDeleter(QNode *q);
110
111 template<typename Caller, typename NodeType>
112 using DestructionFunctionPointer = void (Caller::*)(NodeType *);
113
114 template<typename Caller, typename NodeType, typename PropertyType>
115 void registerDestructionHelper(NodeType *, DestructionFunctionPointer<Caller, NodeType>, PropertyType);
116
117 template<typename Caller, typename NodeType>
118 void registerDestructionHelper(NodeType *node, DestructionFunctionPointer<Caller, NodeType> func, NodeType *&)
119 {
120 // If the node is destoyed, we make sure not to keep a dangling pointer to it
121 Q_Q(QNode);
122 auto f = [q, func]() { (static_cast<Caller *>(q)->*func)(nullptr); };
123 m_destructionConnections.insert(node, QObject::connect(node, &QNode::nodeDestroyed, f));
124 }
125
126 template<typename Caller, typename NodeType>
127 void registerDestructionHelper(NodeType *node, DestructionFunctionPointer<Caller, NodeType> func, QVector<NodeType*> &)
128 {
129 // If the node is destoyed, we make sure not to keep a dangling pointer to it
130 Q_Q(QNode);
131 auto f = [q, func, node]() { (static_cast<Caller *>(q)->*func)(node); };
132 m_destructionConnections.insert(node, QObject::connect(node, &QNode::nodeDestroyed, f));
133 }
134
135 template<typename Caller, typename ValueType>
136 using DestructionFunctionValue = void (Caller::*)(const ValueType&);
137
138 template<typename Caller, typename NodeType, typename ValueType>
139 void registerDestructionHelper(NodeType *node, DestructionFunctionValue<Caller, ValueType> func, NodeType *&,
140 const ValueType &resetValue)
141 {
142 // If the node is destoyed, we make sure not to keep a dangling pointer to it
143 Q_Q(QNode);
144 auto f = [q, func, resetValue]() { (static_cast<Caller *>(q)->*func)(resetValue); };
145 m_destructionConnections.insert(node, QObject::connect(node, &QNode::nodeDestroyed, f));
146 }
147
148 template<typename Caller, typename NodeType>
149 void registerPrivateDestructionHelper(NodeType *node, DestructionFunctionPointer<Caller, NodeType> func)
150 {
151 // If the node is destoyed, we make sure not to keep a dangling pointer to it
152 auto f = [this, func, node]() { (static_cast<Caller *>(this)->*func)(node); };
153 m_destructionConnections.insert(node, QObject::connect(node, &QNode::nodeDestroyed, f));
154 }
155
156 void unregisterDestructionHelper(QNode *node)
157 {
158 QObject::disconnect(m_destructionConnections.take(node));
159 }
160
161 static const QMetaObject *findStaticMetaObject(const QMetaObject *metaObject);
162
163 void _q_postConstructorInit();
164 void _q_ensureBackendNodeCreated();
165
166private:
167 void notifyCreationChange();
168 void notifyDestructionChangesAndRemoveFromScene();
169 void _q_addChild(QNode *childNode);
170 void _q_removeChild(QNode *childNode);
171 void _q_setParentHelper(QNode *parent);
172 void registerNotifiedProperties();
173 void unregisterNotifiedProperties();
174 void propertyChanged(int propertyIndex);
175
176 void setSceneHelper(QNode *root);
177 void unsetSceneHelper(QNode *root);
178 void addEntityComponentToScene(QNode *root);
179
180 friend class PropertyChangeHandler<QNodePrivate>;
181 bool m_propertyChangesSetup;
182 PropertyChangeHandler<QNodePrivate> m_signals;
183 QHash<QNode *, QMetaObject::Connection> m_destructionConnections;
184};
185
186class NodePostConstructorInit : public QObject
187{
188 Q_OBJECT
189public:
190 NodePostConstructorInit(QObject *parent = nullptr);
191 virtual ~NodePostConstructorInit();
192 void removeNode(QNode *node);
193 void addNode(QNode *node);
194
195private Q_SLOTS:
196 void processNodes();
197
198private:
199 QQueue<QNodePrivate *> m_nodesToConstruct;
200 bool m_requestedProcessing;
201};
202
203} // namespace Qt3DCore
204
205QT_END_NAMESPACE
206
207#endif // QT3DCORE_NODE_P_H
208