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_QNODEVISITOR_P_H
41#define QT3DCORE_QNODEVISITOR_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/qentity.h>
55#include <Qt3DCore/qnode.h>
56#include <Qt3DCore/qt3dcore_global.h>
57
58QT_BEGIN_NAMESPACE
59
60namespace Qt3DCore
61{
62
63class Q_3DCORESHARED_EXPORT QNodeVisitor
64{
65public:
66 QNodeVisitor();
67 virtual ~QNodeVisitor();
68
69 template<typename NodeVisitorFunc>
70 void traverse(QNode *rootNode_, NodeVisitorFunc fN)
71 {
72 startTraversing(rootNode_, createFunctor(fN));
73 }
74
75 template<typename Obj, typename NodeVisitorFunc>
76 void traverse(QNode *rootNode_, Obj *instance, NodeVisitorFunc fN)
77 {
78 startTraversing(rootNode_, createFunctor(instance, fN));
79 }
80
81 template<typename NodeVisitorFunc, typename EntityVisitorFunc>
82 void traverse(QNode *rootNode_, NodeVisitorFunc fN, EntityVisitorFunc fE)
83 {
84 startTraversing(rootNode_, createFunctor(fN), createFunctor(fE));
85 }
86
87 template<typename Obj, typename NodeVisitorFunc, typename EntityVisitorFunc>
88 void traverse(QNode *rootNode_, Obj *instance, NodeVisitorFunc fN, EntityVisitorFunc fE)
89 {
90 startTraversing(rootNode_, createFunctor(instance, fN), createFunctor(instance, fE));
91 }
92
93 QNode *rootNode() const;
94 QNode *currentNode() const;
95 void setPath(QNodeVector path);
96 QNodeVector path() const;
97 void append(QNode *n);
98 void pop_back();
99
100private:
101 Q_DISABLE_COPY(QNodeVisitor)
102 QNodeVector m_path;
103
104 template<typename NodeVisitorFunctor>
105 void startTraversing(QNode *rootNode_, NodeVisitorFunctor fN)
106 {
107 setPath(QNodeVector() << rootNode_);
108 if (rootNode_)
109 visitNode(rootNode_, fN);
110 }
111
112 template<typename NodeVisitorFunctor, typename EntityVisitorFunctor>
113 void startTraversing(QNode *rootNode_, NodeVisitorFunctor fN, EntityVisitorFunctor fE)
114 {
115 setPath(QNodeVector() << rootNode_);
116 QEntity* rootEntity = qobject_cast<QEntity *>(rootNode_);
117
118 if (rootEntity)
119 visitEntity(rootEntity, fN, fE);
120 else if (rootNode_)
121 visitNode(rootNode_, fN, fE);
122 }
123
124 template<typename NodeVisitorFunctor>
125 void visitNode(QNode *nd, NodeVisitorFunctor &fN)
126 {
127 fN(nd);
128 traverseChildren(fN);
129 }
130
131 template<typename NodeVisitorFunctor, typename EntityVisitorFunctor>
132 void visitNode(QNode *nd, NodeVisitorFunctor &fN, EntityVisitorFunctor &fE)
133 {
134 fN(nd);
135 traverseChildren(fN, fE);
136 }
137
138 template<typename NodeVisitorFunctor, typename EntityVisitorFunctor>
139 void visitEntity(QEntity *ent, NodeVisitorFunctor &fN, EntityVisitorFunctor &fE)
140 {
141 fE(ent);
142 visitNode(ent, fN, fE);
143 }
144
145 template<typename NodeVisitorFunctor, typename EntityVisitorFunctor>
146 void traverseChildren(NodeVisitorFunctor &fN, EntityVisitorFunctor &fE)
147 {
148 for (QObject *n : currentNode()->children()) {
149 QNode *node = qobject_cast<QNode *>(n);
150 if (node != nullptr)
151 outerVisitNode(node, fN, fE);
152 } // of children iteration
153 }
154
155 template<typename NodeVisitorFunctor>
156 void traverseChildren(NodeVisitorFunctor &fN)
157 {
158 for (QObject *n : currentNode()->children()) {
159 QNode *node = qobject_cast<QNode *>(n);
160 if (node != nullptr)
161 outerVisitNode(node, fN);
162 } // of children iteration
163 }
164
165 template<typename NodeVisitorFunctor, typename EntityVisitorFunctor>
166 void outerVisitNode(QNode *n, NodeVisitorFunctor &fN, EntityVisitorFunctor &fE)
167 {
168 append(n);
169 QEntity* e = qobject_cast<QEntity *>(n);
170 if (e) {
171 visitEntity(e, fN, fE);
172 } else {
173 visitNode(n, fN, fE);
174 }
175 pop_back();
176 }
177
178 template<typename NodeVisitorFunctor>
179 void outerVisitNode(QNode *n, NodeVisitorFunctor &fN)
180 {
181 append(n);
182 visitNode(n, fN);
183 pop_back();
184 }
185
186 template <typename ReturnType, typename NodeType>
187 class FunctionFunctor {
188 public:
189 typedef ReturnType (*functionPtr)(NodeType);
190
191 FunctionFunctor(functionPtr fPtr)
192 : m_functionPointer(fPtr)
193 {}
194
195 void operator()(NodeType node)
196 {
197 (*m_functionPointer)(node);
198 }
199
200 private:
201 functionPtr m_functionPointer;
202 };
203
204 template <typename C, typename ReturnType, typename NodeType>
205 class MemberFunctionFunctor {
206 public:
207 typedef ReturnType (C::*functionPtr)(NodeType);
208
209 MemberFunctionFunctor(C* instance, functionPtr fPtr)
210 : m_instance(instance)
211 , m_functionPointer(fPtr)
212 {}
213
214 void operator()(NodeType node)
215 {
216 (*m_instance.*m_functionPointer)(node);
217 }
218
219 private:
220 C *m_instance;
221 functionPtr m_functionPointer;
222 };
223
224 template <typename C, typename ReturnType, typename NodeType>
225 class ConstMemberFunctionFunctor {
226 public:
227 typedef ReturnType (C::*functionPtr)(NodeType) const;
228
229 ConstMemberFunctionFunctor(C* instance, functionPtr fPtr)
230 : m_instance(instance)
231 , m_functionPointer(fPtr)
232 {}
233
234 void operator()(NodeType node) const
235 {
236 (*m_instance.*m_functionPointer)(node);
237 }
238
239 private:
240 C *m_instance;
241 functionPtr m_functionPointer;
242 };
243
244 template <typename T>
245 const T& createFunctor(const T& t)
246 {
247 return t;
248 }
249
250 template <typename ReturnType, typename NodeType>
251 FunctionFunctor<ReturnType, NodeType> createFunctor(ReturnType (*fPtr)(NodeType))
252 {
253 return FunctionFunctor<ReturnType, NodeType>(fPtr);
254 }
255
256 template <typename C, typename ReturnType, typename NodeType>
257 MemberFunctionFunctor<C, ReturnType, NodeType> createFunctor(C *instance, ReturnType (C::*fPtr)(NodeType))
258 {
259 return MemberFunctionFunctor<C, ReturnType, NodeType>(instance, fPtr);
260 }
261
262 template <typename C, typename ReturnType, typename NodeType>
263 ConstMemberFunctionFunctor<C, ReturnType, NodeType> createFunctor(C *instance, ReturnType (C::*fPtr)(NodeType) const)
264 {
265 return ConstMemberFunctionFunctor<C, ReturnType, NodeType>(instance, fPtr);
266 }
267};
268
269} // namespace Qt3DCore
270
271QT_END_NAMESPACE
272
273#endif // QT3DCORE_QNODEVISITOR_P_H
274