26#include "aeongames/Node.hpp"
30#include "aeongames/StringId.hpp"
32#include "aeongames/ProtoBufUtils.hpp"
33#include "aeongames/CRC.hpp"
35#pragma warning( push )
36#pragma warning( disable : PROTOBUF_WARNINGS )
51 mId{
crc32i ( mName.c_str(), mName.size() ) },
62 return * ( mNodes[index] );
67 return const_cast<Node&
> (
static_cast<const Node&
> ( *this ) [index] );
71 return mNodes.at ( aIndex ).get();
79 return std::visit ( [
this] (
auto&& parent ) ->
size_t
81 if ( parent ==
nullptr )
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." );
86 auto index = std::find_if ( parent->mNodes.begin(), parent->mNodes.end(),
87 [
this] (
const std::unique_ptr<Node>& node )
89 return node.get() == this;
91 return index - parent->mNodes.begin();
97 const Node* node =
this;
98 while ( std::holds_alternative<Node * > ( node->mParent ) && std::get<Node * > ( node->mParent ) !=
nullptr )
100 node = std::get<Node*> ( node->mParent );
107 ( aEnabled ) ? mFlags |= aFlagBits : mFlags &=
static_cast<uint32_t
> ( ~aFlagBits );
112 mFlags[aFlag] = aEnabled;
117 return mFlags[aFlag];
122 return mLocalTransform;
127 return mGlobalTransform;
139 mLocalTransform = aTransform;
143 std::visit ( [&node] (
auto&& parent )
145 if (
typeid ( parent ).hash_code() ==
typeid (
Node * ).hash_code() && parent !=
nullptr )
147 node.mGlobalTransform =
reinterpret_cast<Node*
> ( parent )->mGlobalTransform * node.mLocalTransform;
151 node.mGlobalTransform = node.mLocalTransform;
160 mGlobalTransform = aTransform;
162 std::visit ( [
this] (
auto&& parent )
164 if (
typeid ( parent ).hash_code() ==
typeid (
Node * ).hash_code() && parent !=
nullptr )
166 mLocalTransform = mGlobalTransform *
reinterpret_cast<Node*
> ( parent )->mGlobalTransform.GetInverted();
170 mLocalTransform = mGlobalTransform;
177 [
this] (
Node & node )
183 std::visit ( [
this, &node] (
auto&& parent )
185 if ( &node !=
this &&
typeid ( parent ).hash_code() ==
typeid (
Node * ).hash_code() && parent !=
nullptr )
187 node.mGlobalTransform =
reinterpret_cast<Node*
> ( parent )->mGlobalTransform * node.mLocalTransform;
201 mId =
crc32i ( aName.c_str(), aName.size() );
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 )
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 )
238 ComponentPropertyMsg* component_property_buffer = component_buffer->add_property();
239 ( *component_property_buffer->mutable_name() ) = PropertyIds[j].
GetString();
242 [component_property_buffer] (
auto&& arg )
244 using T = std::decay_t<
decltype ( arg ) >;
245 if constexpr ( std::is_same_v<T, int> )
247 component_property_buffer->set_int_ ( arg );
249 else if constexpr ( std::is_same_v<T, long> )
251 component_property_buffer->set_long_ (
static_cast<int32_t
> ( arg ) );
253 else if constexpr ( std::is_same_v<T, long long> )
255 component_property_buffer->set_long_long ( arg );
257 else if constexpr ( std::is_same_v<T, unsigned> )
259 component_property_buffer->set_unsigned_ ( arg );
261 else if constexpr ( std::is_same_v<T, unsigned long> )
263 component_property_buffer->set_unsigned_long (
static_cast<uint32_t
> ( arg ) );
265 else if constexpr ( std::is_same_v<T, unsigned long long> )
267 component_property_buffer->set_unsigned_long_long ( arg );
269 else if constexpr ( std::is_same_v<T, float> )
271 component_property_buffer->set_float_ ( arg );
273 else if constexpr ( std::is_same_v<T, double> )
275 component_property_buffer->set_double_ ( arg );
277 else if constexpr ( std::is_same_v<T, std::string> )
279 component_property_buffer->set_string ( arg );
281 else if constexpr ( std::is_same_v<T, std::filesystem::path> )
283 component_property_buffer->set_path ( arg.string() );
288 "A non-exhaustive visitor is being "
289 "called on an Property object!" );
291 }, i->GetProperty ( PropertyIds[j] ) );
299 if ( aNodeMsg.has_local() )
303 else if ( aNodeMsg.has_global() )
307 for (
auto& i : aNodeMsg.component() )
310 for (
auto& j : i.property() )
320 if ( aNode ==
nullptr || aNode.get() ==
this )
324 aNode->mParent =
this;
325 std::vector<std::unique_ptr<Node >>::iterator it{};
326 if ( aIndex < mNodes.size() )
328 it = mNodes.insert ( mNodes.begin() + aIndex, std::move ( aNode ) );
332 it = mNodes.insert ( mNodes.end(), std::move ( aNode ) );
336 ( *it )->SetGlobalTransform ( ( *it )->mGlobalTransform );
337 return ( *it ).get();
343 if ( aNode ==
nullptr || aNode.get() ==
this )
347 aNode->mParent =
this;
348 mNodes.emplace_back ( std::move ( aNode ) );
351 mNodes.back()->SetGlobalTransform ( mNodes.back()->mGlobalTransform );
352 return mNodes.back().get();
357 assert ( aNode !=
nullptr );
358 assert ( aNode !=
this );
360 auto it = std::find_if (
363 [aNode] (
const std::unique_ptr<Node>& node )
365 return aNode == node.get();
367 if ( it != mNodes.end() )
369 aNode->mParent =
static_cast<Node*
> ( nullptr );
372 std::unique_ptr<Node> removed_node{std::move ( *it ) };
381 if ( aIndex >= mNodes.size() )
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 ) };
394 const std::function<
void (
Node& ) >& aPreamble,
395 const std::function<
void (
Node& ) >& aPostamble )
404 while ( node != parent )
406 if ( node->mIterator < node->mNodes.size() )
409 node = node->mNodes[node->mIterator].get();
415 aPostamble ( *node );
425#define LoopTraverseDFSPreOrder(...) \
426 void Node::LoopTraverseDFSPreOrder ( const std::function<void ( __VA_ARGS__ Node& ) >& aAction ) __VA_ARGS__ \
434 auto parent = GetNodePtr(mParent);\
435 while ( node != parent )\
437 if ( node->mIterator < node->mNodes.size() )\
440 node = node->mNodes[node->mIterator].get();\
446 node->mIterator = 0; \
447 node = GetNodePtr(node->mParent);\
456#undef LoopTraverseDFSPreOrder
458 Node*
Node::Find (
const std::function<
bool (
const Node& ) >& aUnaryPredicate )
const
461 if ( aUnaryPredicate ( *
this ) )
463 return const_cast<Node*
> ( this );
467 while ( node != parent )
469 if ( node->mIterator < node->mNodes.size() )
472 node = node->mNodes[node->mIterator].get();
478 if ( aUnaryPredicate ( *node ) )
480 return const_cast<Node*
> ( node );
490#define LoopTraverseDFSPostOrder(...) \
491 void Node::LoopTraverseDFSPostOrder ( const std::function<void ( __VA_ARGS__ Node& ) >& aAction ) __VA_ARGS__ \
498 auto parent = GetNodePtr(mParent); \
499 while ( node != parent ) \
501 if ( node->mIterator < node->mNodes.size() ) \
504 node = node->mNodes[node->mIterator].get(); \
510 node->mIterator = 0; \
511 node = GetNodePtr(node->mParent); \
516 LoopTraverseDFSPostOrder (
const )
517 LoopTraverseDFSPostOrder( )
518#undef LoopTraverseDFSPostOrder
523 for (
auto & mNode : mNodes )
525 mNode->RecursiveTraverseDFSPostOrder ( aAction );
533 for (
auto & mNode : mNodes )
535 mNode->RecursiveTraverseDFSPreOrder ( aAction );
542 while ( node !=
nullptr )
552 while ( node !=
nullptr )
564 parent->RecursiveTraverseAncestors ( aAction );
570 for (
auto& i : mComponentDependencyMap )
578 for (
auto& i : mComponentDependencyMap )
584 void Node::Render ( Renderer& aRenderer,
void* aWindowId )
const
586 for (
auto& i : mComponentDependencyMap )
594 return mComponents.size();
599 return mComponents[aIndex].get();
604 auto i = std::find_if ( mComponents.begin(), mComponents.end(), [&aComponent] (
const std::unique_ptr<Component>& aIteratorComponent )
606 return aComponent->GetId() == aIteratorComponent->GetId();
608 if ( i != mComponents.end() )
610 std::cout <<
"Overwriting node data for " << aComponent->GetId().GetString() << std::endl;
611 i->swap ( aComponent );
614 mComponentDependencyMap.
Insert ( {aComponent->GetId(),{}, aComponent->GetId() } );
615 mComponents.emplace_back ( std::move ( aComponent ) );
616 return mComponents.back().get();
621 auto i = std::find_if ( mComponents.begin(), mComponents.end(), [aId] (
const std::unique_ptr<Component>& aComponent )
623 return aComponent->GetId() == aId;
625 if ( i != mComponents.end() )
634 std::unique_ptr<Component> result{};
635 auto i = std::find_if ( mComponents.begin(), mComponents.end(), [aId] (
const std::unique_ptr<Component>& aComponent )
637 return aComponent->GetId() == aId;
639 if ( i != mComponents.end() )
641 mComponentDependencyMap.
Erase ( aId );
642 result = std::move ( *i );
643 mComponents.erase ( std::remove ( i, mComponents.end(), *i ), mComponents.end() );
Defines log severity levels and stream output for the AeonGames engine.
#define LoopTraverseDFSPreOrder(...)
Macro generating LoopTraverseDFSPreOrder implementations for const and non-const variants.
Provides the DLL_PROTOBUF export/import macro for protobuf wrapper classes.
Header for the Scene class.
Axis Aligned Bounding Box class.
Abstract base class for node components.
DLL void SetProperty(const StringId &aId, const Property &aProperty)
Set a property by its StringId identifier.
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.
DLL void SetLocalTransform(const Transform &aTransform)
Set the local transform relative to the parent.
DLL Component * GetComponent(uint32_t aId) const
Get a component by its type identifier.
DLL const Node & operator[](const std::size_t index) const
Access a child node by index (const).
DLL Component * GetComponentByIndex(size_t aIndex) const
Get a component by its index.
DLL std::unique_ptr< Node > Remove(Node *)
Remove a child node by pointer.
DLL Scene * GetScene() const
Retrieve a pointer to the scene containing the node instance.
DLL const Transform & GetLocalTransform() const
Get the local transform relative to the parent.
DLL const AABB & GetAABB() const
Get the axis-aligned bounding box.
DLL uint32_t GetId() const
Get the unique identifier of this node.
DLL void SetAABB(const AABB &aAABB)
Set the axis-aligned bounding box.
DLL size_t GetIndex() const
Get this node's index within its parent's child list.
DLL Node * GetChild(size_t aIndex) const
Get a child node by index.
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.
Flags
Individual flag indices for use with SetFlag/IsFlagEnabled.
DLL void Serialize(NodeMsg &aNodeMsg) const
Serialize this node's state into a protobuf message.
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.
DLL void RecursiveTraverseDFSPreOrder(const std::function< void(Node &) > &aAction)
Recursive depth first search iteration.
DLL const std::string & GetName() const
Get the name of this node.
DLL void SetGlobalTransform(const Transform &aTransform)
Set the global (world-space) transform.
DLL void Render(Renderer &aRenderer, void *aWindowId) const
Render this node and its children.
DLL void ProcessMessage(uint32_t aMessageType, const void *aMessageData)
Deliver a message to this node and its components.
DLL const Transform & GetGlobalTransform() const
Get the global (world-space) transform.
DLL std::unique_ptr< Component > RemoveComponent(uint32_t aId)
Remove a component by its type identifier.
DLL Node * Add(std::unique_ptr< Node > aNode)
Append a child node.
DLL NodeParent GetParent() const
Get this node's parent.
DLL void RecursiveTraverseAncestors(const std::function< void(Node &) > &aAction)
Traverse ancestors recursively, calling an action on each.
DLL void LoopTraverseAncestors(const std::function< void(Node &) > &aAction)
Traverse ancestors iteratively, calling an action on each.
DLL void Update(const double delta)
Update this node and its children.
DLL void Deserialize(const NodeMsg &aNodeMsg)
Deserialize this node's state from a protobuf message.
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.
DLL size_t GetComponentCount() const
Get the number of components attached to this node.
DLL bool IsFlagEnabled(enum Flags aFlag) const
Check whether a specific flag is enabled.
DLL Component * AddComponent(std::unique_ptr< Component > aComponent)
Add a component to this node.
DLL void SetFlag(enum Flags aFlag, bool aEnabled=true)
Enables or disables a single node flag.
DLL std::unique_ptr< Node > RemoveByIndex(size_t aIndex)
Remove a child node by index.
DLL void SetFlags(uint32_t aFlagBits, bool aEnabled=true)
Enables or disables a set of node flags.
DLL size_t GetChildrenCount() const
Get the number of direct child nodes.
CRC-based compile-time string identifier.
constexpr const char * GetString() const
Get the underlying string pointer.
<- This is here just for the literals
Scene * GetScenePtr(const NodeParent &aNodeParent)
Extract the Scene pointer from a NodeParent variant.
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.
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.
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.
std::variant< Node *, Scene * > NodeParent
Variant type representing a node's parent (either a Node or a Scene).