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 | |

58 | QT_BEGIN_NAMESPACE |

59 | |

60 | namespace Qt3DCore |

61 | { |

62 | |

63 | class Q_3DCORESHARED_EXPORT QNodeVisitor |

64 | { |

65 | public: |

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 | |

100 | private: |

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 | |

271 | QT_END_NAMESPACE |

272 | |

273 | #endif // QT3DCORE_QNODEVISITOR_P_H |

274 |