From c0290b718593b2669768dfff55dce1c1563d3847 Mon Sep 17 00:00:00 2001 From: Cocoa Date: Tue, 20 Sep 2022 01:31:59 +0800 Subject: [PATCH 1/2] Added fixes to scene graph. Read description for details. 1. Scene graph creates a root on construction. EntityID is set to MaxEID. The root is not intended to be modified. 2. When adding a node, if the 2nd arg (parent) is omitted, the node will be a child of the root. --- SHADE_Engine/src/Scene/SHSceneGraph.cpp | 99 ++++++++++++++++++++----- SHADE_Engine/src/Scene/SHSceneGraph.h | 58 +++++++-------- 2 files changed, 109 insertions(+), 48 deletions(-) diff --git a/SHADE_Engine/src/Scene/SHSceneGraph.cpp b/SHADE_Engine/src/Scene/SHSceneGraph.cpp index 9fddf10e..c13b5cc7 100644 --- a/SHADE_Engine/src/Scene/SHSceneGraph.cpp +++ b/SHADE_Engine/src/Scene/SHSceneGraph.cpp @@ -76,7 +76,10 @@ namespace SHADE SHSceneGraph::SHSceneGraph() noexcept : root { nullptr } - {} + { + // The root is set to the maximum entity. It should not be interfaced with. + root = AllocateNode(MAX_EID); + } SHSceneGraph::~SHSceneGraph() noexcept { @@ -90,6 +93,8 @@ namespace SHADE for (auto* node : entityNodeMap | std::views::values) ReleaseNode(node); + delete root; + #ifdef _DEBUG SHLOG_INFO("Scene Graph Destroyed Successfully!") #endif @@ -99,23 +104,38 @@ namespace SHADE /* Getter Function Definitions */ /*-----------------------------------------------------------------------------------*/ + EntityID SHSceneNode::GetEntityID() const noexcept + { + return entityID; + } + + SHSceneNode* SHSceneNode::GetParent() const noexcept + { + return parent; + } + + std::vector& SHSceneNode::GetChildren() noexcept + { + return children; + } + SHSceneNode* SHSceneNode::GetChild(EntityID childID) const noexcept { + //////////////////////////////////////// // Error handling + if (!SHEntityManager::IsValidEID(childID)) { - if (!SHEntityManager::IsValidEID(childID)) - { - SHLOG_ERROR("Child Entity {} is invalid! Unable to get child from Entity {}", childID, entityID) - return nullptr; - } - - if (children.empty()) - { - SHLOG_WARNING("Entity {} has no children!", entityID) - return nullptr; - } + SHLOG_ERROR("Child Entity {} is invalid! Unable to get child from Entity {}", childID, entityID) + return nullptr; } + if (children.empty()) + { + SHLOG_WARNING("Entity {} has no children!", entityID) + return nullptr; + } + //////////////////////////////////////// + // Find child const auto ENTITY_MATCH = [&](const SHSceneNode* node) { return node->GetEntityID() == childID; }; @@ -129,7 +149,7 @@ namespace SHADE return *CHILD_ITER; } - SHSceneNode* SHSceneGraph::GetRoot() const noexcept + const SHSceneNode* SHSceneGraph::GetRoot() const noexcept { if (root != nullptr) return root; @@ -140,6 +160,8 @@ namespace SHADE SHSceneNode* SHSceneGraph::GetNode(EntityID entityID) const noexcept { + //////////////////////////////////////// + // Error handling if (!SHEntityManager::IsValidEID(entityID)) { SHLOG_ERROR("Entity {} is invalid! Unable to Get Scene node!", entityID) @@ -152,12 +174,15 @@ namespace SHADE SHLOG_WARNING("Entity {} cannot be found in the scene! Unable to Get Scene node!", entityID) return nullptr; } + //////////////////////////////////////// return NODE_ITER->second; } SHSceneNode* SHSceneGraph::GetParent(EntityID entityID) const noexcept { + //////////////////////////////////////// + // Error handling if (!SHEntityManager::IsValidEID(entityID)) { SHLOG_ERROR("Entity {} is invalid! Unable to get Parent node!", entityID) @@ -170,13 +195,15 @@ namespace SHADE SHLOG_WARNING("Entity {} cannot be found in the scene! Unable to get Parent node!", entityID) return nullptr; } + //////////////////////////////////////// return NODE_ITER->second->GetParent(); } SHSceneNode* SHSceneGraph::GetChild(EntityID entityID, SHSceneNode* childNode) const noexcept { - // Error Handling + //////////////////////////////////////// + // Error handling if (!SHEntityManager::IsValidEID(entityID)) { SHLOG_ERROR("Entity {} is invalid!", entityID) @@ -203,12 +230,15 @@ namespace SHADE SHLOG_WARNING("Entity {} is not a child of Entity {}!", childNode->GetEntityID(), entityID) return nullptr; } + //////////////////////////////////////// return *CHILD_ITER; } SHSceneNode* SHSceneGraph::GetChild(EntityID entityID, EntityID childEntityID) const noexcept { + //////////////////////////////////////// + // Error handling if (!SHEntityManager::IsValidEID(entityID)) { SHLOG_ERROR("Entity {} is invalid!", entityID) @@ -221,14 +251,15 @@ namespace SHADE SHLOG_WARNING("Entity {} cannot be found in the scene!", entityID) return nullptr; } + //////////////////////////////////////// return NODE_ITER->second->GetChild(childEntityID); } const std::vector& SHSceneGraph::GetChildren(EntityID entityID) const noexcept { - // TODO(Diren): Discuss with team best way to handle this - + //////////////////////////////////////// + // Error handling if (!SHEntityManager::IsValidEID(entityID)) { SHLOG_ERROR("Entity {} is invalid!", entityID) @@ -241,6 +272,7 @@ namespace SHADE SHLOG_WARNING("Entity {} cannot be found in the scene!", entityID) return root->GetChildren(); } + //////////////////////////////////////// return NODE_ITER->second->GetChildren(); } @@ -254,6 +286,7 @@ namespace SHADE if (parentNode == nullptr) SHLOG_WARNING("Removing Entity {}'s parent", entityID) + // Handle self assignment if (parentNode == parent) return; @@ -264,6 +297,8 @@ namespace SHADE void SHSceneGraph::SetParent(EntityID entityID, SHSceneNode* parent) const noexcept { + //////////////////////////////////////// + // Error Handling if (!SHEntityManager::IsValidEID(entityID)) { SHLOG_ERROR("Entity {} is invalid!", entityID) @@ -276,12 +311,15 @@ namespace SHADE SHLOG_WARNING("Entity {} cannot be found in the scene!", entityID) return; } + //////////////////////////////////////// NODE_ITER->second->SetParent(parent); } void SHSceneGraph::SetParent(EntityID entityID, EntityID parent) const noexcept { + //////////////////////////////////////// + // Error Handling if (!SHEntityManager::IsValidEID(entityID)) { SHLOG_ERROR("Entity {} is invalid! Unable to set parent of an invalid entity!", entityID) @@ -307,6 +345,7 @@ namespace SHADE SHLOG_WARNING("Entity {} cannot be found in the scene! Unable to parent to Entity {}", parent, entityID) return; } + //////////////////////////////////////// SHSceneNode* currentNode = NODE_ITER->second; currentNode->SetParent(PARENT_ITER->second); @@ -318,22 +357,32 @@ namespace SHADE void SHSceneNode::AddChild(SHSceneNode* newChild) noexcept { + //////////////////////////////////////// + // Error Handling if (newChild == nullptr) { SHLOG_WARNING("Attempting to add a non-existent child to an entity!") return; } + //////////////////////////////////////// + if (newChild->parent) + newChild->parent->RemoveChild(newChild); + + newChild->parent = this; children.emplace_back(newChild); } bool SHSceneNode::RemoveChild(EntityID childID) noexcept { + //////////////////////////////////////// + // Error Handling if (!SHEntityManager::IsValidEID(childID)) { SHLOG_ERROR("Entity {} is invalid!", childID) return false; } + //////////////////////////////////////// SHSceneNode* removedChild = nullptr; const auto ENTITY_MATCH = [&](SHSceneNode* node) @@ -348,18 +397,23 @@ namespace SHADE }; children.end() = std::remove_if(children.begin(), children.end(), ENTITY_MATCH); - removedChild->parent = nullptr; - return removedChild == nullptr; + if (removedChild) + removedChild->parent = nullptr; + + return removedChild != nullptr; } bool SHSceneNode::RemoveChild(SHSceneNode* childToRemove) noexcept { + //////////////////////////////////////// + // Error Handling if (childToRemove == nullptr) { SHLOG_WARNING("Attempting to remove non-existent child from Entity {}", entityID) return false; } + //////////////////////////////////////// children.end() = std::remove(children.begin(), children.end(), childToRemove); childToRemove->parent = nullptr; @@ -378,19 +432,26 @@ namespace SHADE SHSceneNode* SHSceneGraph::AddNode(EntityID entityID, SHSceneNode* parent) { + //////////////////////////////////////// + // Error Handling if (!SHEntityManager::IsValidEID(entityID)) { SHLOG_ERROR("Entity {} is invalid!", entityID) return nullptr; } + //////////////////////////////////////// if (auto NODE_ITER = entityNodeMap.find(entityID); NODE_ITER != entityNodeMap.end()) { SHLOG_WARNING("Entity {} already exists in the scene!", entityID) return NODE_ITER->second; } - + SHSceneNode* newNode = AllocateNode(entityID); + + if (parent == nullptr) + parent = root; + newNode->SetParent(parent); return newNode; diff --git a/SHADE_Engine/src/Scene/SHSceneGraph.h b/SHADE_Engine/src/Scene/SHSceneGraph.h index b569bb78..280e541b 100644 --- a/SHADE_Engine/src/Scene/SHSceneGraph.h +++ b/SHADE_Engine/src/Scene/SHSceneGraph.h @@ -35,40 +35,40 @@ namespace SHADE /* Constructors & Destructor */ /*---------------------------------------------------------------------------------*/ - ~SHSceneNode () = default; + ~SHSceneNode () = default; - SHSceneNode (EntityID eid, SHSceneNode* parent = nullptr) noexcept; - SHSceneNode (const SHSceneNode& rhs) noexcept; - SHSceneNode (SHSceneNode&& rhs) noexcept; - SHSceneNode& operator= (const SHSceneNode& rhs) noexcept; - SHSceneNode& operator= (SHSceneNode&& rhs) noexcept; + SHSceneNode (EntityID eid, SHSceneNode* parent = nullptr) noexcept; + SHSceneNode (const SHSceneNode& rhs) noexcept; + SHSceneNode (SHSceneNode&& rhs) noexcept; + SHSceneNode& operator= (const SHSceneNode& rhs) noexcept; + SHSceneNode& operator= (SHSceneNode&& rhs) noexcept; /*---------------------------------------------------------------------------------*/ /* Getter Functions */ /*---------------------------------------------------------------------------------*/ - [[nodiscard]] EntityID GetEntityID () const noexcept { return entityID ;} - [[nodiscard]] SHSceneNode* GetParent () const noexcept { return parent; } - [[nodiscard]] std::vector& GetChildren () noexcept { return children; } + [[nodiscard]] EntityID GetEntityID () const noexcept; + [[nodiscard]] SHSceneNode* GetParent () const noexcept; + [[nodiscard]] std::vector& GetChildren () noexcept; - [[nodiscard]] SHSceneNode* GetChild (EntityID childID) const noexcept; + [[nodiscard]] SHSceneNode* GetChild (EntityID childID) const noexcept; /*---------------------------------------------------------------------------------*/ /* Setter Functions */ /*---------------------------------------------------------------------------------*/ - void SetParent (SHSceneNode* parentNode) noexcept; + void SetParent (SHSceneNode* parentNode) noexcept; /*---------------------------------------------------------------------------------*/ /* Function Members */ /*---------------------------------------------------------------------------------*/ - void AddChild (SHSceneNode* newChild) noexcept; + void AddChild (SHSceneNode* newChild) noexcept; - bool RemoveChild (EntityID childID) noexcept; - bool RemoveChild (SHSceneNode* childToRemove) noexcept; + bool RemoveChild (EntityID childID) noexcept; + bool RemoveChild (SHSceneNode* childToRemove) noexcept; - void RemoveAllChildren () noexcept; + void RemoveAllChildren () noexcept; private: EntityID entityID; @@ -89,19 +89,19 @@ namespace SHADE /* Constructors & Destructor */ /*---------------------------------------------------------------------------------*/ - SHSceneGraph () noexcept; - ~SHSceneGraph () noexcept; + SHSceneGraph () noexcept; + ~SHSceneGraph () noexcept; - SHSceneGraph (const SHSceneGraph&) = delete; - SHSceneGraph (SHSceneGraph&&) = delete; - SHSceneGraph& operator= (const SHSceneGraph&) = delete; - SHSceneGraph& operator= (SHSceneGraph&&) = delete; + SHSceneGraph (const SHSceneGraph&) = delete; + SHSceneGraph (SHSceneGraph&&) = delete; + SHSceneGraph& operator= (const SHSceneGraph&) = delete; + SHSceneGraph& operator= (SHSceneGraph&&) = delete; /*---------------------------------------------------------------------------------*/ /* Getter Functions */ /*---------------------------------------------------------------------------------*/ - [[nodiscard]] SHSceneNode* GetRoot () const noexcept; + [[nodiscard]] const SHSceneNode* GetRoot () const noexcept; [[nodiscard]] SHSceneNode* GetNode (EntityID entityID) const noexcept; [[nodiscard]] SHSceneNode* GetParent (EntityID entityID) const noexcept; [[nodiscard]] SHSceneNode* GetChild (EntityID entityID, SHSceneNode* childNode) const noexcept; @@ -112,17 +112,17 @@ namespace SHADE /* Setter Functions */ /*---------------------------------------------------------------------------------*/ - void SetParent (EntityID entityID, SHSceneNode* parent) const noexcept; - void SetParent (EntityID entityID, EntityID parent) const noexcept; + void SetParent (EntityID entityID, SHSceneNode* parent) const noexcept; + void SetParent (EntityID entityID, EntityID parent) const noexcept; /*---------------------------------------------------------------------------------*/ /* Function Members */ /*---------------------------------------------------------------------------------*/ - SHSceneNode* AddNode (EntityID entityID, SHSceneNode* parent = nullptr); - bool RemoveNode (EntityID entityID) noexcept; - bool RemoveNode (SHSceneNode* nodeToRemove) noexcept; - void Reset () noexcept; + SHSceneNode* AddNode (EntityID entityID, SHSceneNode* parent = nullptr); + bool RemoveNode (EntityID entityID) noexcept; + bool RemoveNode (SHSceneNode* nodeToRemove) noexcept; + void Reset () noexcept; private: /*---------------------------------------------------------------------------------*/ @@ -137,7 +137,7 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ SHSceneNode* AllocateNode (EntityID entityID); - void ReleaseNode (SHSceneNode* node) noexcept; + void ReleaseNode (SHSceneNode* node) noexcept; }; -- 2.40.1 From f4bf895e45f3ce71431324f9298b0ca3c07db412 Mon Sep 17 00:00:00 2001 From: Cocoa Date: Tue, 20 Sep 2022 15:35:10 +0800 Subject: [PATCH 2/2] Fixed constness of functions in scene graph --- SHADE_Engine/src/Scene/SHSceneGraph.cpp | 2 +- SHADE_Engine/src/Scene/SHSceneGraph.h | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/SHADE_Engine/src/Scene/SHSceneGraph.cpp b/SHADE_Engine/src/Scene/SHSceneGraph.cpp index c13b5cc7..305c3fc0 100644 --- a/SHADE_Engine/src/Scene/SHSceneGraph.cpp +++ b/SHADE_Engine/src/Scene/SHSceneGraph.cpp @@ -114,7 +114,7 @@ namespace SHADE return parent; } - std::vector& SHSceneNode::GetChildren() noexcept + const std::vector& SHSceneNode::GetChildren() const noexcept { return children; } diff --git a/SHADE_Engine/src/Scene/SHSceneGraph.h b/SHADE_Engine/src/Scene/SHSceneGraph.h index 280e541b..38fcc414 100644 --- a/SHADE_Engine/src/Scene/SHSceneGraph.h +++ b/SHADE_Engine/src/Scene/SHSceneGraph.h @@ -47,11 +47,11 @@ namespace SHADE /* Getter Functions */ /*---------------------------------------------------------------------------------*/ - [[nodiscard]] EntityID GetEntityID () const noexcept; - [[nodiscard]] SHSceneNode* GetParent () const noexcept; - [[nodiscard]] std::vector& GetChildren () noexcept; + [[nodiscard]] EntityID GetEntityID () const noexcept; + [[nodiscard]] SHSceneNode* GetParent () const noexcept; + [[nodiscard]] const std::vector& GetChildren () const noexcept; - [[nodiscard]] SHSceneNode* GetChild (EntityID childID) const noexcept; + [[nodiscard]] SHSceneNode* GetChild (EntityID childID) const noexcept; /*---------------------------------------------------------------------------------*/ /* Setter Functions */ -- 2.40.1