Aeon Engine c550894
AeonGames Open Source Game Engine
Loading...
Searching...
No Matches
Node.cpp
Go to the documentation of this file.
1/*
2Copyright (C) 2014-2019,2021,2025,2026 Rodrigo Jose Hernandez Cordoba
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15*/
16
22
23#include <cassert>
24#include <algorithm>
25#include <type_traits>
26#include "aeongames/Node.hpp"
27#include "aeongames/Scene.hpp"
29#include "Factory.h"
30#include "aeongames/StringId.hpp"
32#include "aeongames/ProtoBufUtils.hpp"
33#include "aeongames/CRC.hpp"
34#ifdef _MSC_VER
35#pragma warning( push )
36#pragma warning( disable : PROTOBUF_WARNINGS )
37#endif
38#include "scene.pb.h"
39#ifdef _MSC_VER
40#pragma warning( pop )
41#endif
42
43namespace AeonGames
44{
45 Node::Node ( uint32_t aFlags ) :
46 mName ( "Node" ),
47 mParent{},
48 mLocalTransform(),
49 mGlobalTransform(),
50 mNodes(),
51 mId{crc32i ( mName.c_str(), mName.size() ) },
52 mFlags ( aFlags )
53 {
54 }
55
57 {
58 return mNodes.size();
59 }
60 const Node& Node::operator[] ( const std::size_t index ) const
61 {
62 return * ( mNodes[index] );
63 }
64
65 Node& Node::operator[] ( const std::size_t index )
66 {
67 return const_cast<Node&> ( static_cast<const Node&> ( *this ) [index] );
68 }
69 Node* Node::GetChild ( size_t aIndex ) const
70 {
71 return mNodes.at ( aIndex ).get();
72 }
74 {
75 return mParent;
76 }
77 size_t Node::GetIndex() const
78 {
79 return std::visit ( [this] ( auto&& parent ) -> size_t
80 {
81 if ( parent == nullptr )
82 {
83 std::cout << LogLevel::Error << "Node has no parent and thus no assigned index." << std::endl;
84 throw std::runtime_error ( "Node has no parent and thus no assigned index." );
85 }
86 auto index = std::find_if ( parent->mNodes.begin(), parent->mNodes.end(),
87 [this] ( const std::unique_ptr<Node>& node )
88 {
89 return node.get() == this;
90 } );
91 return index - parent->mNodes.begin();
92 },
93 mParent );
94 }
95 Scene* Node::GetScene() const
96 {
97 const Node* node = this;
98 while ( std::holds_alternative<Node * > ( node->mParent ) && std::get<Node * > ( node->mParent ) != nullptr )
99 {
100 node = std::get<Node*> ( node->mParent );
101 }
102 return GetScenePtr ( node->mParent );
103 }
104
105 void Node::SetFlags ( uint32_t aFlagBits, bool aEnabled )
106 {
107 ( aEnabled ) ? mFlags |= aFlagBits : mFlags &= static_cast<uint32_t> ( ~aFlagBits );
108 }
109
110 void Node::SetFlag ( enum Flags aFlag, bool aEnabled )
111 {
112 mFlags[aFlag] = aEnabled;
113 }
114
115 bool Node::IsFlagEnabled ( enum Flags aFlag ) const
116 {
117 return mFlags[aFlag];
118 }
119
121 {
122 return mLocalTransform;
123 }
124
126 {
127 return mGlobalTransform;
128 }
129
130 const AABB& Node::GetAABB() const
131 {
134 return mAABB;
135 }
136
137 void Node::SetLocalTransform ( const Transform& aTransform )
138 {
139 mLocalTransform = aTransform;
141 [] ( Node & node )
142 {
143 std::visit ( [&node] ( auto&& parent )
144 {
145 if ( typeid ( parent ).hash_code() == typeid ( Node * ).hash_code() && parent != nullptr )
146 {
147 node.mGlobalTransform = reinterpret_cast<Node*> ( parent )->mGlobalTransform * node.mLocalTransform;
148 }
149 else
150 {
151 node.mGlobalTransform = node.mLocalTransform;
152 }
153 },
154 node.mParent );
155 } );
156 }
157
158 void Node::SetGlobalTransform ( const Transform& aTransform )
159 {
160 mGlobalTransform = aTransform;
161 // Update the Local transform for this node only
162 std::visit ( [this] ( auto&& parent )
163 {
164 if ( typeid ( parent ).hash_code() == typeid ( Node * ).hash_code() && parent != nullptr )
165 {
166 mLocalTransform = mGlobalTransform * reinterpret_cast<Node*> ( parent )->mGlobalTransform.GetInverted();
167 }
168 else
169 {
170 mLocalTransform = mGlobalTransform;
171 }
172 },
173 mParent );
174
175 // Then Update the Global transform for all children
177 [this] ( Node & node )
178 {
183 std::visit ( [this, &node] ( auto&& parent )
184 {
185 if ( &node != this && typeid ( parent ).hash_code() == typeid ( Node * ).hash_code() && parent != nullptr )
186 {
187 node.mGlobalTransform = reinterpret_cast<Node*> ( parent )->mGlobalTransform * node.mLocalTransform;
188 }
189 },
190 node.mParent );
191 } );
192 }
193
194 void Node::SetAABB ( const AABB& aAABB )
195 {
196 mAABB = aAABB;
197 }
198
199 void Node::SetName ( const std::string& aName )
200 {
201 mId = crc32i ( aName.c_str(), aName.size() );
202 mName = aName;
203 }
204
205 const std::string& Node::GetName() const
206 {
207 return mName;
208 }
209
210 uint32_t Node::GetId() const
211 {
212 return mId;
213 }
214
215 // Helper for the Property visitor in Serialize/Deserialize
216 template<class T> struct always_false : std::false_type {};
217
218 void Node::Serialize ( NodeMsg& aNodeMsg ) const
219 {
220 *aNodeMsg.mutable_name() = GetName();
221 aNodeMsg.mutable_local()->mutable_scale()->set_x ( GetLocalTransform().GetScale() [0] );
222 aNodeMsg.mutable_local()->mutable_scale()->set_y ( GetLocalTransform().GetScale() [1] );
223 aNodeMsg.mutable_local()->mutable_scale()->set_z ( GetLocalTransform().GetScale() [2] );
224 aNodeMsg.mutable_local()->mutable_rotation()->set_w ( GetLocalTransform().GetRotation() [0] );
225 aNodeMsg.mutable_local()->mutable_rotation()->set_x ( GetLocalTransform().GetRotation() [1] );
226 aNodeMsg.mutable_local()->mutable_rotation()->set_y ( GetLocalTransform().GetRotation() [2] );
227 aNodeMsg.mutable_local()->mutable_rotation()->set_z ( GetLocalTransform().GetRotation() [3] );
228 aNodeMsg.mutable_local()->mutable_translation()->set_x ( GetLocalTransform().GetTranslation() [0] );
229 aNodeMsg.mutable_local()->mutable_translation()->set_y ( GetLocalTransform().GetTranslation() [1] );
230 aNodeMsg.mutable_local()->mutable_translation()->set_z ( GetLocalTransform().GetTranslation() [2] );
231 for ( auto& i : mComponents )
232 {
233 ComponentMsg* component_buffer = aNodeMsg.add_component();
234 ( *component_buffer->mutable_name() ) = i->GetId().GetString();
235 const StringId* PropertyIds = i->GetPropertyInfoArray();
236 for ( size_t j = 0; j < i->GetPropertyCount(); ++j )
237 {
238 ComponentPropertyMsg* component_property_buffer = component_buffer->add_property();
239 ( *component_property_buffer->mutable_name() ) = PropertyIds[j].GetString();
240
241 std::visit (
242 [component_property_buffer] ( auto&& arg )
243 {
244 using T = std::decay_t<decltype ( arg ) >;
245 if constexpr ( std::is_same_v<T, int> )
246 {
247 component_property_buffer->set_int_ ( arg );
248 }
249 else if constexpr ( std::is_same_v<T, long> )
250 {
251 component_property_buffer->set_long_ ( static_cast<int32_t> ( arg ) );
252 }
253 else if constexpr ( std::is_same_v<T, long long> )
254 {
255 component_property_buffer->set_long_long ( arg );
256 }
257 else if constexpr ( std::is_same_v<T, unsigned> )
258 {
259 component_property_buffer->set_unsigned_ ( arg );
260 }
261 else if constexpr ( std::is_same_v<T, unsigned long> )
262 {
263 component_property_buffer->set_unsigned_long ( static_cast<uint32_t> ( arg ) );
264 }
265 else if constexpr ( std::is_same_v<T, unsigned long long> )
266 {
267 component_property_buffer->set_unsigned_long_long ( arg );
268 }
269 else if constexpr ( std::is_same_v<T, float> )
270 {
271 component_property_buffer->set_float_ ( arg );
272 }
273 else if constexpr ( std::is_same_v<T, double> )
274 {
275 component_property_buffer->set_double_ ( arg );
276 }
277 else if constexpr ( std::is_same_v<T, std::string> )
278 {
279 component_property_buffer->set_string ( arg );
280 }
281 else if constexpr ( std::is_same_v<T, std::filesystem::path> )
282 {
283 component_property_buffer->set_path ( arg.string() );
284 }
285 else
286 {
287 static_assert ( always_false<T>::value,
288 "A non-exhaustive visitor is being "
289 "called on an Property object!" );
290 }
291 }, i->GetProperty ( PropertyIds[j] ) );
292 }
293 }
294 }
295
296 void Node::Deserialize ( const NodeMsg& aNodeMsg )
297 {
298 SetName ( aNodeMsg.name() );
299 if ( aNodeMsg.has_local() )
300 {
301 SetLocalTransform ( GetTransform ( aNodeMsg.local() ) );
302 }
303 else if ( aNodeMsg.has_global() )
304 {
305 SetGlobalTransform ( GetTransform ( aNodeMsg.global() ) );
306 }
307 for ( auto& i : aNodeMsg.component() )
308 {
309 Component* component = AddComponent ( ConstructComponent ( i.name() ) );
310 for ( auto& j : i.property() )
311 {
312 component->SetProperty ( j.name(), GetProperty ( j ) );
313 }
314 }
315 }
316
317 Node* Node::Insert ( size_t aIndex, std::unique_ptr<Node> aNode )
318 {
319 // Never append this or null pointers.
320 if ( aNode == nullptr || aNode.get() == this )
321 {
322 return nullptr;
323 }
324 aNode->mParent = this;
325 std::vector<std::unique_ptr<Node >>::iterator it{};
326 if ( aIndex < mNodes.size() )
327 {
328 it = mNodes.insert ( mNodes.begin() + aIndex, std::move ( aNode ) );
329 }
330 else
331 {
332 it = mNodes.insert ( mNodes.end(), std::move ( aNode ) );
333 }
334 // Force a recalculation of the LOCAL transform
335 // by setting the GLOBAL transform to itself.
336 ( *it )->SetGlobalTransform ( ( *it )->mGlobalTransform );
337 return ( *it ).get();
338 }
339
340 Node* Node::Add ( std::unique_ptr<Node> aNode )
341 {
342 // Never append this or null pointers.
343 if ( aNode == nullptr || aNode.get() == this )
344 {
345 return nullptr;
346 }
347 aNode->mParent = this;
348 mNodes.emplace_back ( std::move ( aNode ) );
349 // Force a recalculation of the LOCAL transform
350 // by setting the GLOBAL transform to itself.
351 mNodes.back()->SetGlobalTransform ( mNodes.back()->mGlobalTransform );
352 return mNodes.back().get();
353 }
354
355 std::unique_ptr<Node> Node::Remove ( Node* aNode )
356 {
357 assert ( aNode != nullptr );
358 assert ( aNode != this );
359 // If passed a null or this pointer find SHOULD not find it on release builds.
360 auto it = std::find_if (
361 mNodes.begin(),
362 mNodes.end(),
363 [aNode] ( const std::unique_ptr<Node>& node )
364 {
365 return aNode == node.get();
366 } );
367 if ( it != mNodes.end() )
368 {
369 aNode->mParent = static_cast<Node*> ( nullptr );
370 // Force recalculation of transforms.
371 aNode->SetLocalTransform ( aNode->mGlobalTransform );
372 std::unique_ptr<Node> removed_node{std::move ( *it ) };
373 mNodes.erase ( it );
374 return removed_node;
375 }
376 return nullptr;
377 }
378
379 std::unique_ptr<Node> Node::RemoveByIndex ( size_t aIndex )
380 {
381 if ( aIndex >= mNodes.size() )
382 {
383 return nullptr;
384 }
385 mNodes[aIndex]->mParent = static_cast<Node*> ( nullptr );
386 mNodes[aIndex]->SetLocalTransform ( mNodes[aIndex]->mGlobalTransform );
387 auto it = mNodes.begin() + aIndex;
388 std::unique_ptr<Node> removed_node{std::move ( *it ) };
389 mNodes.erase ( it );
390 return removed_node;
391 }
392
394 const std::function<void ( Node& ) >& aPreamble,
395 const std::function<void ( Node& ) >& aPostamble )
396 {
401 auto node = this;
402 aPreamble ( *node );
403 auto parent = GetNodePtr ( mParent );
404 while ( node != parent )
405 {
406 if ( node->mIterator < node->mNodes.size() )
407 {
408 auto prev = node;
409 node = node->mNodes[node->mIterator].get();
410 aPreamble ( *node );
411 ++prev->mIterator;
412 }
413 else
414 {
415 aPostamble ( *node );
416 node->mIterator = 0; // Reset counter for next traversal.
417 node = GetNodePtr ( node->mParent );
418 }
419 }
420 }
421
422 /* This is ugly, but it is only way to use the same code for the const and the non const version
423 without having to add template or friend members to the class declaration. */
425#define LoopTraverseDFSPreOrder(...) \
426 void Node::LoopTraverseDFSPreOrder ( const std::function<void ( __VA_ARGS__ Node& ) >& aAction ) __VA_ARGS__ \
427 {\
428\
432 auto node = this;\
433 aAction ( *node );\
434 auto parent = GetNodePtr(mParent);\
435 while ( node != parent )\
436 {\
437 if ( node->mIterator < node->mNodes.size() )\
438 {\
439 auto prev = node;\
440 node = node->mNodes[node->mIterator].get();\
441 aAction ( *node );\
442 prev->mIterator++;\
443 }\
444 else\
445 {\
446 node->mIterator = 0; /* Reset counter for next traversal.*/\
447 node = GetNodePtr(node->mParent);\
448 }\
449 }\
451
456#undef LoopTraverseDFSPreOrder
457
458 Node* Node::Find ( const std::function<bool ( const Node& ) >& aUnaryPredicate ) const
459 {
460 /* Short Circuit in case this is the node being searched for */
461 if ( aUnaryPredicate ( *this ) )
462 {
463 return const_cast<Node*> ( this );
464 };
465 auto node = this;
466 auto parent = GetNodePtr ( mParent );
467 while ( node != parent )
468 {
469 if ( node->mIterator < node->mNodes.size() )
470 {
471 auto prev = node;
472 node = node->mNodes[node->mIterator].get();
473 ++prev->mIterator;
474 }
475 else
476 {
477 node->mIterator = 0; /* Reset counter for next traversal. */
478 if ( aUnaryPredicate ( *node ) )
479 {
480 return const_cast<Node*> ( node );
481 };
482 node = GetNodePtr ( node->mParent );
483 }
484 }
485 return nullptr;
486 }
487
489
490#define LoopTraverseDFSPostOrder(...) \
491 void Node::LoopTraverseDFSPostOrder ( const std::function<void ( __VA_ARGS__ Node& ) >& aAction ) __VA_ARGS__ \
492 { \
493 /* \
494 This code implements a similar solution to this stackoverflow answer: \
495 http://stackoverflow.com/questions/5987867/traversing-a-n-ary-tree-without-using-recurrsion/5988138#5988138 \
496 */ \
497 auto node = this; \
498 auto parent = GetNodePtr(mParent); \
499 while ( node != parent ) \
500 { \
501 if ( node->mIterator < node->mNodes.size() ) \
502 { \
503 auto prev = node; \
504 node = node->mNodes[node->mIterator].get(); \
505 ++prev->mIterator; \
506 } \
507 else \
508 { \
509 aAction ( *node ); \
510 node->mIterator = 0; /* Reset counter for next traversal. */ \
511 node = GetNodePtr(node->mParent); \
512 } \
513 } \
514 }
515
516 LoopTraverseDFSPostOrder ( const )
517 LoopTraverseDFSPostOrder( )
518#undef LoopTraverseDFSPostOrder
520
521 void Node::RecursiveTraverseDFSPostOrder ( const std::function<void ( Node& ) >& aAction )
522 {
523 for ( auto & mNode : mNodes )
524 {
525 mNode->RecursiveTraverseDFSPostOrder ( aAction );
526 }
527 aAction ( *this );
528 }
529
530 void Node::RecursiveTraverseDFSPreOrder ( const std::function<void ( Node& ) >& aAction )
531 {
532 aAction ( *this );
533 for ( auto & mNode : mNodes )
534 {
535 mNode->RecursiveTraverseDFSPreOrder ( aAction );
537 }
538
539 void Node::LoopTraverseAncestors ( const std::function<void ( Node& ) >& aAction )
540 {
541 auto node = this;
542 while ( node != nullptr )
543 {
544 aAction ( *node );
545 node = GetNodePtr ( node->mParent );
547 }
548
549 void Node::LoopTraverseAncestors ( const std::function<void ( const Node& ) >& aAction ) const
550 {
551 auto node = this;
552 while ( node != nullptr )
553 {
554 aAction ( *node );
555 node = GetNodePtr ( node->mParent );
557 }
558
559 void Node::RecursiveTraverseAncestors ( const std::function<void ( Node& ) >& aAction )
560 {
561 aAction ( *this );
562 if ( auto parent = GetNodePtr ( mParent ) )
563 {
564 parent->RecursiveTraverseAncestors ( aAction );
566 }
567
568 void Node::Update ( const double aDelta )
569 {
570 for ( auto& i : mComponentDependencyMap )
571 {
572 GetComponent ( i )->Update ( *this, aDelta );
574 }
575
576 void Node::ProcessMessage ( uint32_t aMessageType, const void* aMessageData )
577 {
578 for ( auto& i : mComponentDependencyMap )
579 {
580 GetComponent ( i )->ProcessMessage ( *this, aMessageType, aMessageData );
582 }
583
584 void Node::Render ( Renderer& aRenderer, void* aWindowId ) const
585 {
586 for ( auto& i : mComponentDependencyMap )
587 {
588 GetComponent ( i )->Render ( *this, aRenderer, aWindowId );
590 }
591
592 size_t Node::GetComponentCount() const
593 {
594 return mComponents.size();
595 }
596
597 Component* Node::GetComponentByIndex ( size_t aIndex ) const
598 {
599 return mComponents[aIndex].get();
600 }
601
602 Component* Node::AddComponent ( std::unique_ptr<Component> aComponent )
603 {
604 auto i = std::find_if ( mComponents.begin(), mComponents.end(), [&aComponent] ( const std::unique_ptr<Component>& aIteratorComponent )
605 {
606 return aComponent->GetId() == aIteratorComponent->GetId();
607 } );
608 if ( i != mComponents.end() )
609 {
610 std::cout << "Overwriting node data for " << aComponent->GetId().GetString() << std::endl;
611 i->swap ( aComponent );
612 return i->get();
613 }
614 mComponentDependencyMap.Insert ( {aComponent->GetId(),{}, aComponent->GetId() } );
615 mComponents.emplace_back ( std::move ( aComponent ) );
616 return mComponents.back().get();
617 }
618
619 Component* Node::GetComponent ( uint32_t aId ) const
620 {
621 auto i = std::find_if ( mComponents.begin(), mComponents.end(), [aId] ( const std::unique_ptr<Component>& aComponent )
622 {
623 return aComponent->GetId() == aId;
624 } );
625 if ( i != mComponents.end() )
626 {
627 return i->get();
628 }
629 return nullptr;
630 }
631
632 std::unique_ptr<Component> Node::RemoveComponent ( uint32_t aId )
633 {
634 std::unique_ptr<Component> result{};
635 auto i = std::find_if ( mComponents.begin(), mComponents.end(), [aId] ( const std::unique_ptr<Component>& aComponent )
636 {
637 return aComponent->GetId() == aId;
638 } );
639 if ( i != mComponents.end() )
640 {
641 mComponentDependencyMap.Erase ( aId );
642 result = std::move ( *i );
643 mComponents.erase ( std::remove ( i, mComponents.end(), *i ), mComponents.end() );
644 }
645 return result;
646 }
647}
Defines log severity levels and stream output for the AeonGames engine.
#define LoopTraverseDFSPreOrder(...)
Macro generating LoopTraverseDFSPreOrder implementations for const and non-const variants.
Definition Node.cpp:425
Provides the DLL_PROTOBUF export/import macro for protobuf wrapper classes.
Header for the Scene class.
Axis Aligned Bounding Box class.
Definition AABB.hpp:34
Abstract base class for node components.
Definition Component.hpp:39
DLL void SetProperty(const StringId &aId, const Property &aProperty)
Set a property by its StringId identifier.
Definition Component.cpp:23
virtual void Render(const Node &aNode, Renderer &aRenderer, void *aWindowId)=0
Render the component.
virtual void ProcessMessage(Node &aNode, uint32_t aMessageType, const void *aMessageData)=0
Process an incoming message.
virtual void Update(Node &aNode, double aDelta)=0
Update the component state.
void Erase(const Key &key)
Remove an element by key.
size_t Insert(const triple &item)
Insert a new element, maintaining topological order.
Scene graph node representing an entity in the game world.
Definition Node.hpp:54
DLL void SetLocalTransform(const Transform &aTransform)
Set the local transform relative to the parent.
Definition Node.cpp:137
DLL Component * GetComponent(uint32_t aId) const
Get a component by its type identifier.
Definition Node.cpp:616
DLL const Node & operator[](const std::size_t index) const
Access a child node by index (const).
Definition Node.cpp:60
DLL Component * GetComponentByIndex(size_t aIndex) const
Get a component by its index.
Definition Node.cpp:594
DLL std::unique_ptr< Node > Remove(Node *)
Remove a child node by pointer.
Definition Node.cpp:355
DLL Scene * GetScene() const
Retrieve a pointer to the scene containing the node instance.
Definition Node.cpp:95
DLL const Transform & GetLocalTransform() const
Get the local transform relative to the parent.
Definition Node.cpp:120
DLL const AABB & GetAABB() const
Get the axis-aligned bounding box.
Definition Node.cpp:130
DLL uint32_t GetId() const
Get the unique identifier of this node.
Definition Node.cpp:210
DLL void SetAABB(const AABB &aAABB)
Set the axis-aligned bounding box.
Definition Node.cpp:194
DLL size_t GetIndex() const
Get this node's index within its parent's child list.
Definition Node.cpp:77
DLL Node * GetChild(size_t aIndex) const
Get a child node by index.
Definition Node.cpp:69
DLL Node * Find(const std::function< bool(const Node &) > &aUnaryPredicate) const
Find a descendant node matching a predicate.
DLL Node(uint32_t aFlags=AllBits)
Construct a node with the given initial flags.
Definition Node.cpp:45
Flags
Individual flag indices for use with SetFlag/IsFlagEnabled.
Definition Node.hpp:65
DLL void Serialize(NodeMsg &aNodeMsg) const
Serialize this node's state into a protobuf message.
Definition Node.cpp:218
DLL void RecursiveTraverseDFSPostOrder(const std::function< void(Node &) > &aAction)
Recursive depth first search iteration.
DLL void SetName(const std::string &aName)
Set the name of this node.
Definition Node.cpp:199
DLL void RecursiveTraverseDFSPreOrder(const std::function< void(Node &) > &aAction)
Recursive depth first search iteration.
Definition Node.cpp:527
DLL const std::string & GetName() const
Get the name of this node.
Definition Node.cpp:205
DLL void SetGlobalTransform(const Transform &aTransform)
Set the global (world-space) transform.
Definition Node.cpp:158
DLL void Render(Renderer &aRenderer, void *aWindowId) const
Render this node and its children.
Definition Node.cpp:581
DLL void ProcessMessage(uint32_t aMessageType, const void *aMessageData)
Deliver a message to this node and its components.
Definition Node.cpp:573
DLL const Transform & GetGlobalTransform() const
Get the global (world-space) transform.
Definition Node.cpp:125
DLL std::unique_ptr< Component > RemoveComponent(uint32_t aId)
Remove a component by its type identifier.
Definition Node.cpp:629
DLL Node * Add(std::unique_ptr< Node > aNode)
Append a child node.
Definition Node.cpp:340
DLL NodeParent GetParent() const
Get this node's parent.
Definition Node.cpp:73
DLL void RecursiveTraverseAncestors(const std::function< void(Node &) > &aAction)
Traverse ancestors recursively, calling an action on each.
Definition Node.cpp:556
DLL void LoopTraverseAncestors(const std::function< void(Node &) > &aAction)
Traverse ancestors iteratively, calling an action on each.
Definition Node.cpp:536
DLL void Update(const double delta)
Update this node and its children.
Definition Node.cpp:565
DLL void Deserialize(const NodeMsg &aNodeMsg)
Deserialize this node's state from a protobuf message.
Definition Node.cpp:296
DLL void LoopTraverseDFSPreOrder(const std::function< void(Node &) > &aAction)
Iterative depth first search iteration.
DLL Node * Insert(size_t aIndex, std::unique_ptr< Node > aNode)
Insert a child node at a specific index.
Definition Node.cpp:317
DLL size_t GetComponentCount() const
Get the number of components attached to this node.
Definition Node.cpp:589
DLL bool IsFlagEnabled(enum Flags aFlag) const
Check whether a specific flag is enabled.
Definition Node.cpp:115
DLL Component * AddComponent(std::unique_ptr< Component > aComponent)
Add a component to this node.
Definition Node.cpp:599
DLL void SetFlag(enum Flags aFlag, bool aEnabled=true)
Enables or disables a single node flag.
Definition Node.cpp:110
DLL std::unique_ptr< Node > RemoveByIndex(size_t aIndex)
Remove a child node by index.
Definition Node.cpp:379
DLL void SetFlags(uint32_t aFlagBits, bool aEnabled=true)
Enables or disables a set of node flags.
Definition Node.cpp:105
DLL size_t GetChildrenCount() const
Get the number of direct child nodes.
Definition Node.cpp:56
CRC-based compile-time string identifier.
Definition StringId.hpp:31
constexpr const char * GetString() const
Get the underlying string pointer.
Definition StringId.hpp:57
Component class for any object that requires space transformations.
Definition Transform.hpp:34
<- This is here just for the literals
Definition AABB.hpp:31
Scene * GetScenePtr(const NodeParent &aNodeParent)
Extract the Scene pointer from a NodeParent variant.
Definition Node.hpp:46
Property GetProperty(const ComponentPropertyMsg &aComponentPropertyMsg)
Convert a ComponentPropertyMsg protobuf message to a Property.
Transform GetTransform(const TransformMsg &aTransform)
Convert a TransformMsg protobuf message to a Transform.
LoopTraverseDFSPreOrder(const) LoopTraverseDFSPreOrder() Node *Node
Const version generated by LoopTraverseDFSPreOrder macro.
Definition Node.cpp:450
DLL std::unique_ptr< Component > ConstructComponent(uint32_t aIdentifier)
Construct a component from a numeric identifier.
Node * GetNodePtr(const NodeParent &aNodeParent)
Extract the Node pointer from a NodeParent variant.
Definition Node.hpp:41
uint32_t crc32i(const char *message, size_t size, uint32_t previous_crc)
Compute the CRC32 of a given message, continuing from a previous CRC value.
Definition CRC.cpp:27
std::variant< Node *, Scene * > NodeParent
Variant type representing a node's parent (either a Node or a Scene).
Definition Node.hpp:39
@ Error
Error conditions.
Definition LogLevel.hpp:33