1 | // Copyright (C) 2017 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 | #ifndef QT3DCORE_QNODEVISITOR_P_H |
4 | #define QT3DCORE_QNODEVISITOR_P_H |
5 | |
6 | // |
7 | // W A R N I N G |
8 | // ------------- |
9 | // |
10 | // This file is not part of the Qt API. It exists for the convenience |
11 | // of other Qt classes. This header file may change from version to |
12 | // version without notice, or even be removed. |
13 | // |
14 | // We mean it. |
15 | // |
16 | |
17 | #include <Qt3DCore/qentity.h> |
18 | #include <Qt3DCore/qnode.h> |
19 | #include <Qt3DCore/qt3dcore_global.h> |
20 | #include <private/qglobal_p.h> |
21 | |
22 | QT_BEGIN_NAMESPACE |
23 | |
24 | namespace Qt3DCore |
25 | { |
26 | |
27 | class Q_3DCORESHARED_EXPORT QNodeVisitor |
28 | { |
29 | public: |
30 | QNodeVisitor(); |
31 | virtual ~QNodeVisitor(); |
32 | |
33 | template<typename NodeVisitorFunc> |
34 | void traverse(QNode *rootNode_, NodeVisitorFunc fN) |
35 | { |
36 | startTraversing(rootNode_, createFunctor(fN)); |
37 | } |
38 | |
39 | template<typename Obj, typename NodeVisitorFunc> |
40 | void traverse(QNode *rootNode_, Obj *instance, NodeVisitorFunc fN) |
41 | { |
42 | startTraversing(rootNode_, createFunctor(instance, fN)); |
43 | } |
44 | |
45 | template<typename NodeVisitorFunc, typename EntityVisitorFunc> |
46 | void traverse(QNode *rootNode_, NodeVisitorFunc fN, EntityVisitorFunc fE) |
47 | { |
48 | startTraversing(rootNode_, createFunctor(fN), createFunctor(fE)); |
49 | } |
50 | |
51 | template<typename Obj, typename NodeVisitorFunc, typename EntityVisitorFunc> |
52 | void traverse(QNode *rootNode_, Obj *instance, NodeVisitorFunc fN, EntityVisitorFunc fE) |
53 | { |
54 | startTraversing(rootNode_, createFunctor(instance, fN), createFunctor(instance, fE)); |
55 | } |
56 | |
57 | QNode *rootNode() const; |
58 | QNode *currentNode() const; |
59 | void setPath(QNodeVector path); |
60 | QNodeVector path() const; |
61 | void append(QNode *n); |
62 | void pop_back(); |
63 | |
64 | private: |
65 | Q_DISABLE_COPY(QNodeVisitor) |
66 | QNodeVector m_path; |
67 | |
68 | template<typename NodeVisitorFunctor> |
69 | void startTraversing(QNode *rootNode_, NodeVisitorFunctor fN) |
70 | { |
71 | setPath(QNodeVector() << rootNode_); |
72 | if (rootNode_) |
73 | visitNode(rootNode_, fN); |
74 | } |
75 | |
76 | template<typename NodeVisitorFunctor, typename EntityVisitorFunctor> |
77 | void startTraversing(QNode *rootNode_, NodeVisitorFunctor fN, EntityVisitorFunctor fE) |
78 | { |
79 | setPath(QNodeVector() << rootNode_); |
80 | QEntity* rootEntity = qobject_cast<QEntity *>(object: rootNode_); |
81 | |
82 | if (rootEntity) |
83 | visitEntity(rootEntity, fN, fE); |
84 | else if (rootNode_) |
85 | visitNode(rootNode_, fN, fE); |
86 | } |
87 | |
88 | template<typename NodeVisitorFunctor> |
89 | void visitNode(QNode *nd, NodeVisitorFunctor &fN) |
90 | { |
91 | fN(nd); |
92 | traverseChildren(fN); |
93 | } |
94 | |
95 | template<typename NodeVisitorFunctor, typename EntityVisitorFunctor> |
96 | void visitNode(QNode *nd, NodeVisitorFunctor &fN, EntityVisitorFunctor &fE) |
97 | { |
98 | fN(nd); |
99 | traverseChildren(fN, fE); |
100 | } |
101 | |
102 | template<typename NodeVisitorFunctor, typename EntityVisitorFunctor> |
103 | void visitEntity(QEntity *ent, NodeVisitorFunctor &fN, EntityVisitorFunctor &fE) |
104 | { |
105 | fE(ent); |
106 | visitNode(ent, fN, fE); |
107 | } |
108 | |
109 | template<typename NodeVisitorFunctor, typename EntityVisitorFunctor> |
110 | void traverseChildren(NodeVisitorFunctor &fN, EntityVisitorFunctor &fE) |
111 | { |
112 | for (QObject *n : currentNode()->children()) { |
113 | QNode *node = qobject_cast<QNode *>(object: n); |
114 | if (node != nullptr) |
115 | outerVisitNode(node, fN, fE); |
116 | } // of children iteration |
117 | } |
118 | |
119 | template<typename NodeVisitorFunctor> |
120 | void traverseChildren(NodeVisitorFunctor &fN) |
121 | { |
122 | for (QObject *n : currentNode()->children()) { |
123 | QNode *node = qobject_cast<QNode *>(object: n); |
124 | if (node != nullptr) |
125 | outerVisitNode(node, fN); |
126 | } // of children iteration |
127 | } |
128 | |
129 | template<typename NodeVisitorFunctor, typename EntityVisitorFunctor> |
130 | void outerVisitNode(QNode *n, NodeVisitorFunctor &fN, EntityVisitorFunctor &fE) |
131 | { |
132 | append(n); |
133 | QEntity* e = qobject_cast<QEntity *>(object: n); |
134 | if (e) { |
135 | visitEntity(e, fN, fE); |
136 | } else { |
137 | visitNode(n, fN, fE); |
138 | } |
139 | pop_back(); |
140 | } |
141 | |
142 | template<typename NodeVisitorFunctor> |
143 | void outerVisitNode(QNode *n, NodeVisitorFunctor &fN) |
144 | { |
145 | append(n); |
146 | visitNode(n, fN); |
147 | pop_back(); |
148 | } |
149 | |
150 | template <typename ReturnType, typename NodeType> |
151 | class FunctionFunctor { |
152 | public: |
153 | typedef ReturnType (*functionPtr)(NodeType); |
154 | |
155 | FunctionFunctor(functionPtr fPtr) |
156 | : m_functionPointer(fPtr) |
157 | {} |
158 | |
159 | void operator()(NodeType node) |
160 | { |
161 | (*m_functionPointer)(node); |
162 | } |
163 | |
164 | private: |
165 | functionPtr m_functionPointer; |
166 | }; |
167 | |
168 | template <typename C, typename ReturnType, typename NodeType> |
169 | class MemberFunctionFunctor { |
170 | public: |
171 | typedef ReturnType (C::*functionPtr)(NodeType); |
172 | |
173 | MemberFunctionFunctor(C* instance, functionPtr fPtr) |
174 | : m_instance(instance) |
175 | , m_functionPointer(fPtr) |
176 | {} |
177 | |
178 | void operator()(NodeType node) |
179 | { |
180 | (*m_instance.*m_functionPointer)(node); |
181 | } |
182 | |
183 | private: |
184 | C *m_instance; |
185 | functionPtr m_functionPointer; |
186 | }; |
187 | |
188 | template <typename C, typename ReturnType, typename NodeType> |
189 | class ConstMemberFunctionFunctor { |
190 | public: |
191 | typedef ReturnType (C::*functionPtr)(NodeType) const; |
192 | |
193 | ConstMemberFunctionFunctor(C* instance, functionPtr fPtr) |
194 | : m_instance(instance) |
195 | , m_functionPointer(fPtr) |
196 | {} |
197 | |
198 | void operator()(NodeType node) const |
199 | { |
200 | (*m_instance.*m_functionPointer)(node); |
201 | } |
202 | |
203 | private: |
204 | C *m_instance; |
205 | functionPtr m_functionPointer; |
206 | }; |
207 | |
208 | template <typename T> |
209 | const T& createFunctor(const T& t) |
210 | { |
211 | return t; |
212 | } |
213 | |
214 | template <typename ReturnType, typename NodeType> |
215 | FunctionFunctor<ReturnType, NodeType> createFunctor(ReturnType (*fPtr)(NodeType)) |
216 | { |
217 | return FunctionFunctor<ReturnType, NodeType>(fPtr); |
218 | } |
219 | |
220 | template <typename C, typename ReturnType, typename NodeType> |
221 | MemberFunctionFunctor<C, ReturnType, NodeType> createFunctor(C *instance, ReturnType (C::*fPtr)(NodeType)) |
222 | { |
223 | return MemberFunctionFunctor<C, ReturnType, NodeType>(instance, fPtr); |
224 | } |
225 | |
226 | template <typename C, typename ReturnType, typename NodeType> |
227 | ConstMemberFunctionFunctor<C, ReturnType, NodeType> createFunctor(C *instance, ReturnType (C::*fPtr)(NodeType) const) |
228 | { |
229 | return ConstMemberFunctionFunctor<C, ReturnType, NodeType>(instance, fPtr); |
230 | } |
231 | }; |
232 | |
233 | } // namespace Qt3DCore |
234 | |
235 | QT_END_NAMESPACE |
236 | |
237 | #endif // QT3DCORE_QNODEVISITOR_P_H |
238 | |