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 66 QT_BEGIN_NAMESPACE 67 68 namespace Qt3DCore { 69 70 class QNode; 71 class QAspectEngine; 72 73 class Q_3DCORE_PRIVATE_EXPORT QNodePrivate : public QObjectPrivate, public QObservableInterface 74 { 75 public: 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> registerDestructionHelper(NodeType * node,DestructionFunctionPointer<Caller,NodeType> func,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> registerDestructionHelper(NodeType * node,DestructionFunctionPointer<Caller,NodeType> func,QVector<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> registerDestructionHelper(NodeType * node,DestructionFunctionPointer<Caller,NodeType> func,QList<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> registerDestructionHelper(NodeType * node,DestructionFunctionPointer<Caller,NodeType> func,std::vector<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> registerDestructionHelper(NodeType * node,DestructionFunctionValue<Caller,ValueType> func,NodeType * &,const ValueType & resetValue)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> registerPrivateDestructionHelper(NodeType * node,DestructionFunctionPointer<Caller,NodeType> func)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 unregisterDestructionHelper(QNode * node)182 void unregisterDestructionHelper(QNode *node) 183 { 184 m_destructionConnections.erase(std::remove_if(m_destructionConnections.begin(), 185 m_destructionConnections.end(), 186 [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 m_destructionConnections.end()); 194 } 195 196 static const QMetaObject *findStaticMetaObject(const QMetaObject *metaObject); 197 198 void _q_postConstructorInit(); 199 void _q_ensureBackendNodeCreated(); 200 201 private: 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 221 class NodePostConstructorInit : public QObject 222 { 223 Q_OBJECT 224 public: 225 NodePostConstructorInit(QObject *parent = nullptr); 226 virtual ~NodePostConstructorInit(); 227 void removeNode(QNode *node); 228 void addNode(QNode *node); 229 230 public Q_SLOTS: 231 void processNodes(); 232 233 private: 234 QQueue<QNodePrivate *> m_nodesToConstruct; 235 bool m_requestedProcessing; 236 }; 237 238 } // namespace Qt3DCore 239 240 QT_END_NAMESPACE 241 242 #endif // QT3DCORE_NODE_P_H 243