GA::kit v0.3
G&A's in-house C++ application framework
Loading...
Searching...
No Matches
node.h
Go to the documentation of this file.
1
12#pragma once
13#include "ga/defines.h"
14#include "ga/graph/component.h"
15#include "ga/transform.h"
16#include "ga/uuid.h"
17#include "ga/signal.h"
18#include <algorithm>
19#include <functional>
20#include <memory>
21#include <string>
22#include <type_traits>
23#include <typeindex>
24#include <typeinfo>
25#include <unordered_map>
26#include <vector>
27
28namespace ga {
29
30class Scene;
31
45class Node : public std::enable_shared_from_this<Node>, public Transform
46{
47public:
48 // Static Node factory
49 // in place of public constructor
50 template <CLASS_INHERITS( NodeT, ga::Node )>
51 static std::shared_ptr<NodeT> create();
52 static std::shared_ptr<Node> create() { return Node::create<Node>(); }
53
54 // parent / child hierarchy
55 // ------------------------
56
57 template <CLASS_INHERITS( NodeT, ga::Node )>
58 std::shared_ptr<NodeT> addChild( std::shared_ptr<NodeT> child = nullptr );
59 std::shared_ptr<Node> addChild();
60
61 template <CLASS_INHERITS( NodeT, ga::Node )>
62 std::shared_ptr<NodeT> insertChild( size_t index, std::shared_ptr<NodeT> child = nullptr );
63 std::shared_ptr<Node> insertChild( size_t index );
64
65 void detach(); // remove this node and its children from its parent and scene
66
67 bool removeChild( std::shared_ptr<Node> child ); // returns true if found / removed
68 bool removeDescendant( std::shared_ptr<Node> node ); // searches entire hierarchy for Node and removes
69 void clearChildren(); // remove all children
70
71 void sortChildren( std::function<bool( const std::shared_ptr<Node>& a, const std::shared_ptr<Node>& b )> comparisonFn );
72
73 bool isParentOf( const std::shared_ptr<Node>& child ) const;
74 bool isChildOf( const std::shared_ptr<Node>& parent ) const;
75 inline bool hasChild( const std::shared_ptr<Node>& child ) const { return isParentOf( child ); }
76 bool hasDescendant( const std::shared_ptr<Node>& node ) const;
77
78 std::shared_ptr<Node> getParent() const;
79 const std::vector<std::shared_ptr<Node>>& getChildren() const;
80
81 inline bool hasChildren() const { return !m_children.empty(); }
82 inline bool hasParent() const { return !m_parent.expired(); }
83 inline bool isRoot() const { return !hasParent(); } // root == no parent
84
85 inline bool hasScene() const { return !m_scene.expired(); }
86 std::shared_ptr<Scene> getScene() const;
87
88 size_t getSceneHierarchyLevel() const; // 0 == root, 1 == child of root, 2 == grandchild, etc.
89 size_t getSceneDrawIndex() const;
90
91 // setters / getters
92
93 void setName( const std::string& name ) { m_name = name; }
94 const std::string& getName() const { return m_name; }
95
96 void setUuid( const ga::Uuid& uuid ) { m_uuid = uuid; }
97 const ga::Uuid& getUuid() { return m_uuid; }
98
99 ga::Transform& getTransform() { return *this; }
100
101 // custom draw / update functions
102
103 void setDrawFn( std::function<void()> drawFn ) { m_drawFn = drawFn; }
105 {
106 m_drawFn = [this]() { draw(); };
107 }
108
109 void setUpdateFn( std::function<void()> updateFn ) { m_updateFn = updateFn; }
111 {
112 m_updateFn = [this]() { update(); };
113 }
114
115 // scene space transformations
116
117 // the global / scene space transformation of this node
119
120 // helper to convert a local position to scene space
121 vec3 localPosToScene( const vec3& pos ) { return getSceneTransform().getMatrix() * vec4( pos, 1. ); }
122 // helper to convert a scene position to local space
123 vec3 scenePosToLocal( const vec3& pos ) { return glm::inverse( getSceneTransform().getMatrix() ) * vec4( pos, 1. ); }
124
125 // enable / disable node
126
127 void disableUpdate(); // scene WON'T update() this Node (or its children)
128 void enableUpdate(); // scene WILL update() this Node (and its children)
129
130 bool isUpdateEnabled() const { return m_isUpdateEnabled; }
131
132 void disableDraw(); // scene WON'T draw() this Node (or its children)
133 void enableDraw(); // scene WILL draw() this Node (and its children)
134
135 bool isDrawEnabled() const { return m_isDrawEnabled; }
136
137 // /// TODO - these are temporary methods for testing. should be replaced with iostream overloads
138 // void printChildren();
139 // void printParent();
140 // void printHierarchy();
141 // void printScene();
142
143 // components
144
145 template <CLASS_INHERITS( ComponentT, Component )>
146 std::shared_ptr<ComponentT> createComponent();
147
148 template <CLASS_INHERITS( ComponentT, Component )>
149 std::shared_ptr<ComponentT> addComponent( std::shared_ptr<ComponentT> component );
150
151 template <CLASS_INHERITS( ComponentT, Component )>
152 std::shared_ptr<ComponentT> getComponent();
153
154 template <CLASS_INHERITS( ComponentT, Component )>
155 bool removeComponent();
156
157 template <CLASS_INHERITS( ComponentT, Component )>
158 ComponentT& component();
159
160 // signals
161
167
168 virtual ~Node() {}
169
170protected:
171 Node(); // Nodes should only be created by Node::create()
172 virtual void setup();
173 virtual void update();
174 virtual void draw();
175
176 // useful for things that deal with draw order, i.e. events
177 virtual void onDrawIndexChange();
178 void setDrawIndex( size_t index );
179
180 friend class Scene;
181
182 void setScene( std::shared_ptr<Scene> scene );
183 void setParent( std::shared_ptr<Node> parent );
184
185 // update and draw hierarchy
186 void updateTree();
187 void drawTree();
188
189 void walkTree( std::function<void( std::shared_ptr<Node> )> fn ); // run arbitrary function on self and children
190
191 std::weak_ptr<Scene> m_scene;
192 std::weak_ptr<Node> m_parent;
193 std::vector<std::shared_ptr<Node>> m_children;
194
195 // components
196 std::unordered_map<std::type_index, std::shared_ptr<Component>> m_components;
197
198 // built-in properties
199 std::string m_name;
202 std::function<void()> m_updateFn;
203 std::function<void()> m_drawFn;
204 // std::shared_ptr<Mesh> m_mesh;
205 // std::shared_ptr<Matrial> m_material;
206
207 bool m_isDrawEnabled = true;
208 bool m_isUpdateEnabled = true;
209};
210
211// template implementations
212// ---------------------------------------------
213
214// ---------------------------------------------
215template <class NodeT, typename>
216std::shared_ptr<NodeT> Node::create()
217{
218 auto node = std::shared_ptr<NodeT>( new NodeT() );
219 node->setup();
220 return node;
221}
222
223// ---------------------------------------------
224template <class NodeT, typename>
225std::shared_ptr<NodeT> Node::addChild( std::shared_ptr<NodeT> child )
226{
227 if ( !child ) {
228 child = create<NodeT>();
229 }
230 if ( !isParentOf( child ) ) {
231 child->detach();
232 m_children.push_back( child );
233 child->setParent( shared_from_this() );
234 child->setScene( m_scene.lock() );
235 }
236 return child;
237}
238
239// ---------------------------------------------
240template <class NodeT, typename>
241std::shared_ptr<NodeT> Node::insertChild( size_t index, std::shared_ptr<NodeT> child )
242{
243 if ( !child ) {
244 child = create<NodeT>();
245 }
246 if ( !isParentOf( child ) ) {
247 child->detach();
248 index = std::min( index, m_children.size() );
249 m_children.emplace( m_children.begin() + index, child );
250 child->setParent( shared_from_this() );
251 child->setScene( m_scene.lock() );
252 }
253 return child;
254}
255
256// ---------------------------------------------
257template <class ComponentT, typename>
258std::shared_ptr<ComponentT> Node::createComponent()
259{
260 return addComponent( std::shared_ptr<ComponentT>( new ComponentT() ) );
261}
262
263// ---------------------------------------------
264template <class ComponentT, typename>
265std::shared_ptr<ComponentT> Node::addComponent( std::shared_ptr<ComponentT> componentPtr )
266{
267 if ( !componentPtr )
268 componentPtr = std::shared_ptr<ComponentT>( new ComponentT() );
269 auto p = std::make_pair( std::type_index( typeid( ComponentT ) ), componentPtr );
270 auto r = m_components.insert( p ); // returns <it, bool>
271 if ( r.second ) {
272 componentPtr->setNode( shared_from_this() );
273 }
274 return r.second ? componentPtr : nullptr;
275}
276
277// --------------------------------------------
278template <class ComponentT, typename>
279std::shared_ptr<ComponentT> Node::getComponent()
280{
281 auto it = m_components.find( std::type_index( typeid( ComponentT ) ) );
282 if ( it != m_components.end() ) {
283 return std::dynamic_pointer_cast<ComponentT>( it->second );
284 } else {
285 return nullptr;
286 }
287}
288
289// --------------------------------------------
290// auto creates component, if not found or null
291template <class ComponentT, typename>
292ComponentT& Node::component()
293{
294 auto it = m_components.find( std::type_index( typeid( ComponentT ) ) );
295 std::shared_ptr<ComponentT> component;
296 if ( it != m_components.end() ) {
297 if ( it->second ) {
298 component = std::dynamic_pointer_cast<ComponentT>( it->second );
299 } else {
300 // component null, remove before re-create
301 removeComponent<ComponentT>();
302 }
303 }
304 if ( !component ) {
305 component = createComponent<ComponentT>();
306 if ( !component ) {
307 throw std::runtime_error( "Error creating Component of type: " + std::string( typeid( ComponentT ).name() ) );
308 }
309 }
310 return *component;
311}
312
313// ---------------------------------------------
314template <class ComponentT, typename>
316{
317 auto it = m_components.find( typeid( ComponentT ) );
318 if ( it != m_components.end() ) {
319 //if (it->second) {
320 // it->second->m_components = nullptr;
321 //}
322 m_components.erase( it );
323 return true;
324 } else {
325 return false;
326 }
327}
328
329} // namespace ga
Node represents a basic "node" (or view) in the scenegraph.
Definition: node.h:46
virtual void update()
Definition: node.cpp:173
void detach()
Definition: node.cpp:17
virtual ~Node()
Definition: node.h:168
bool hasChild(const std::shared_ptr< Node > &child) const
Definition: node.h:75
void enableUpdate()
Definition: node.cpp:138
void disableDraw()
Definition: node.cpp:123
std::shared_ptr< ComponentT > createComponent()
Definition: node.h:258
vec3 scenePosToLocal(const vec3 &pos)
Definition: node.h:123
ga::Signal onDidUpdateChildren
Definition: node.h:164
const ga::Uuid & getUuid()
Definition: node.h:97
void updateTree()
Definition: node.cpp:193
bool hasChildren() const
Definition: node.h:81
std::shared_ptr< Node > addChild()
Definition: node.cpp:7
void drawTree()
Definition: node.cpp:219
bool removeComponent()
Definition: node.h:315
std::shared_ptr< Scene > getScene() const
Definition: node.cpp:87
ga::Transform getSceneTransform()
Definition: node.cpp:114
std::shared_ptr< ComponentT > addComponent(std::shared_ptr< ComponentT > component)
Definition: node.h:265
void walkTree(std::function< void(std::shared_ptr< Node >)> fn)
Definition: node.cpp:256
std::unordered_map< std::type_index, std::shared_ptr< Component > > m_components
Definition: node.h:196
ga::Signal onDidDraw
Definition: node.h:165
void setName(const std::string &name)
Definition: node.h:93
void setScene(std::shared_ptr< Scene > scene)
Definition: node.cpp:265
bool isParentOf(const std::shared_ptr< Node > &child) const
Definition: node.cpp:66
std::shared_ptr< NodeT > insertChild(size_t index, std::shared_ptr< NodeT > child=nullptr)
Definition: node.h:241
std::string m_name
Definition: node.h:199
size_t getSceneHierarchyLevel() const
Definition: node.cpp:92
virtual void setup()
Definition: node.cpp:169
void setUuid(const ga::Uuid &uuid)
Definition: node.h:96
void disableUpdate()
Definition: node.cpp:133
size_t getSceneDrawIndex() const
Definition: node.cpp:103
std::shared_ptr< Node > getParent() const
Definition: node.cpp:143
bool isUpdateEnabled() const
Definition: node.h:130
bool hasScene() const
Definition: node.h:85
ComponentT & component()
Definition: node.h:292
bool m_isDrawEnabled
Definition: node.h:207
void resetUpdateFn()
Definition: node.h:110
std::function< void()> m_drawFn
Definition: node.h:203
bool isRoot() const
Definition: node.h:83
void setDrawFn(std::function< void()> drawFn)
Definition: node.h:103
size_t m_drawIndex
Definition: node.h:201
virtual void draw()
Definition: node.cpp:177
ga::Signal onWillDraw
Definition: node.h:165
bool removeChild(std::shared_ptr< Node > child)
Definition: node.cpp:24
virtual void onDrawIndexChange()
Definition: node.cpp:181
bool hasDescendant(const std::shared_ptr< Node > &node) const
Definition: node.cpp:76
void clearChildren()
Definition: node.cpp:52
ga::Uuid m_uuid
Definition: node.h:200
bool isChildOf(const std::shared_ptr< Node > &parent) const
Definition: node.cpp:71
bool m_isUpdateEnabled
Definition: node.h:208
vec3 localPosToScene(const vec3 &pos)
Definition: node.h:121
std::weak_ptr< Node > m_parent
Definition: node.h:192
bool removeDescendant(std::shared_ptr< Node > node)
Definition: node.cpp:41
void setDrawIndex(size_t index)
Definition: node.cpp:185
ga::Signal onDidUpdate
Definition: node.h:163
const std::vector< std::shared_ptr< Node > > & getChildren() const
Definition: node.cpp:148
const std::string & getName() const
Definition: node.h:94
void resetDrawFn()
Definition: node.h:104
std::vector< std::shared_ptr< Node > > m_children
Definition: node.h:193
ga::Signal onWillDrawChildren
Definition: node.h:166
static std::shared_ptr< Node > create()
Definition: node.h:52
void setParent(std::shared_ptr< Node > parent)
Definition: node.cpp:163
void enableDraw()
Definition: node.cpp:128
bool isDrawEnabled() const
Definition: node.h:135
std::weak_ptr< Scene > m_scene
Definition: node.h:191
Node()
Definition: node.cpp:155
bool hasParent() const
Definition: node.h:82
void setUpdateFn(std::function< void()> updateFn)
Definition: node.h:109
ga::Signal onWillUpdate
Definition: node.h:163
std::function< void()> m_updateFn
Definition: node.h:202
ga::Transform & getTransform()
Definition: node.h:99
ga::Signal onWillUpdateChildren
Definition: node.h:164
void sortChildren(std::function< bool(const std::shared_ptr< Node > &a, const std::shared_ptr< Node > &b)> comparisonFn)
Definition: node.cpp:61
static std::shared_ptr< NodeT > create()
ga::Signal onDidDrawChildren
Definition: node.h:166
std::shared_ptr< ComponentT > getComponent()
Definition: node.h:279
Scene is a view controller.
Definition: scene.h:20
Transform represents a basic model matrix: translate * rotate * scale Stored internally as ga::mat4 (...
Definition: transform.h:15
const mat4 & getMatrix() const
Definition: transform.h:87
Definition: sigslot.hpp:1134
Definition: color.h:9
xg::Guid Uuid
Definition: uuid.h:10