Merge pull request #34 from SHADE-DP/SP3-12-SceneGraph

SP3-12 Scene Graph Fixes

BUGFIXES

Scene Graph automatically creates a root which is set to MAX_EID
Fixed constness of getter functions in Scene Graph & Scene Node
This commit is contained in:
XiaoQiDigipen 2022-09-20 15:37:58 +08:00 committed by GitHub
commit 5b6f60ee8a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 109 additions and 48 deletions

View File

@ -76,7 +76,10 @@ namespace SHADE
SHSceneGraph::SHSceneGraph() noexcept SHSceneGraph::SHSceneGraph() noexcept
: root { nullptr } : root { nullptr }
{} {
// The root is set to the maximum entity. It should not be interfaced with.
root = AllocateNode(MAX_EID);
}
SHSceneGraph::~SHSceneGraph() noexcept SHSceneGraph::~SHSceneGraph() noexcept
{ {
@ -90,6 +93,8 @@ namespace SHADE
for (auto* node : entityNodeMap | std::views::values) for (auto* node : entityNodeMap | std::views::values)
ReleaseNode(node); ReleaseNode(node);
delete root;
#ifdef _DEBUG #ifdef _DEBUG
SHLOG_INFO("Scene Graph Destroyed Successfully!") SHLOG_INFO("Scene Graph Destroyed Successfully!")
#endif #endif
@ -99,23 +104,38 @@ namespace SHADE
/* Getter Function Definitions */ /* Getter Function Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
EntityID SHSceneNode::GetEntityID() const noexcept
{
return entityID;
}
SHSceneNode* SHSceneNode::GetParent() const noexcept
{
return parent;
}
const std::vector<SHSceneNode*>& SHSceneNode::GetChildren() const noexcept
{
return children;
}
SHSceneNode* SHSceneNode::GetChild(EntityID childID) const noexcept SHSceneNode* SHSceneNode::GetChild(EntityID childID) const noexcept
{ {
////////////////////////////////////////
// Error handling // 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;
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;
}
} }
if (children.empty())
{
SHLOG_WARNING("Entity {} has no children!", entityID)
return nullptr;
}
////////////////////////////////////////
// Find child // Find child
const auto ENTITY_MATCH = [&](const SHSceneNode* node) { return node->GetEntityID() == childID; }; const auto ENTITY_MATCH = [&](const SHSceneNode* node) { return node->GetEntityID() == childID; };
@ -129,7 +149,7 @@ namespace SHADE
return *CHILD_ITER; return *CHILD_ITER;
} }
SHSceneNode* SHSceneGraph::GetRoot() const noexcept const SHSceneNode* SHSceneGraph::GetRoot() const noexcept
{ {
if (root != nullptr) if (root != nullptr)
return root; return root;
@ -140,6 +160,8 @@ namespace SHADE
SHSceneNode* SHSceneGraph::GetNode(EntityID entityID) const noexcept SHSceneNode* SHSceneGraph::GetNode(EntityID entityID) const noexcept
{ {
////////////////////////////////////////
// Error handling
if (!SHEntityManager::IsValidEID(entityID)) if (!SHEntityManager::IsValidEID(entityID))
{ {
SHLOG_ERROR("Entity {} is invalid! Unable to Get Scene node!", 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) SHLOG_WARNING("Entity {} cannot be found in the scene! Unable to Get Scene node!", entityID)
return nullptr; return nullptr;
} }
////////////////////////////////////////
return NODE_ITER->second; return NODE_ITER->second;
} }
SHSceneNode* SHSceneGraph::GetParent(EntityID entityID) const noexcept SHSceneNode* SHSceneGraph::GetParent(EntityID entityID) const noexcept
{ {
////////////////////////////////////////
// Error handling
if (!SHEntityManager::IsValidEID(entityID)) if (!SHEntityManager::IsValidEID(entityID))
{ {
SHLOG_ERROR("Entity {} is invalid! Unable to get Parent node!", 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) SHLOG_WARNING("Entity {} cannot be found in the scene! Unable to get Parent node!", entityID)
return nullptr; return nullptr;
} }
////////////////////////////////////////
return NODE_ITER->second->GetParent(); return NODE_ITER->second->GetParent();
} }
SHSceneNode* SHSceneGraph::GetChild(EntityID entityID, SHSceneNode* childNode) const noexcept SHSceneNode* SHSceneGraph::GetChild(EntityID entityID, SHSceneNode* childNode) const noexcept
{ {
// Error Handling ////////////////////////////////////////
// Error handling
if (!SHEntityManager::IsValidEID(entityID)) if (!SHEntityManager::IsValidEID(entityID))
{ {
SHLOG_ERROR("Entity {} is invalid!", 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) SHLOG_WARNING("Entity {} is not a child of Entity {}!", childNode->GetEntityID(), entityID)
return nullptr; return nullptr;
} }
////////////////////////////////////////
return *CHILD_ITER; return *CHILD_ITER;
} }
SHSceneNode* SHSceneGraph::GetChild(EntityID entityID, EntityID childEntityID) const noexcept SHSceneNode* SHSceneGraph::GetChild(EntityID entityID, EntityID childEntityID) const noexcept
{ {
////////////////////////////////////////
// Error handling
if (!SHEntityManager::IsValidEID(entityID)) if (!SHEntityManager::IsValidEID(entityID))
{ {
SHLOG_ERROR("Entity {} is invalid!", entityID) SHLOG_ERROR("Entity {} is invalid!", entityID)
@ -221,14 +251,15 @@ namespace SHADE
SHLOG_WARNING("Entity {} cannot be found in the scene!", entityID) SHLOG_WARNING("Entity {} cannot be found in the scene!", entityID)
return nullptr; return nullptr;
} }
////////////////////////////////////////
return NODE_ITER->second->GetChild(childEntityID); return NODE_ITER->second->GetChild(childEntityID);
} }
const std::vector<SHSceneNode*>& SHSceneGraph::GetChildren(EntityID entityID) const noexcept const std::vector<SHSceneNode*>& SHSceneGraph::GetChildren(EntityID entityID) const noexcept
{ {
// TODO(Diren): Discuss with team best way to handle this ////////////////////////////////////////
// Error handling
if (!SHEntityManager::IsValidEID(entityID)) if (!SHEntityManager::IsValidEID(entityID))
{ {
SHLOG_ERROR("Entity {} is invalid!", entityID) SHLOG_ERROR("Entity {} is invalid!", entityID)
@ -241,6 +272,7 @@ namespace SHADE
SHLOG_WARNING("Entity {} cannot be found in the scene!", entityID) SHLOG_WARNING("Entity {} cannot be found in the scene!", entityID)
return root->GetChildren(); return root->GetChildren();
} }
////////////////////////////////////////
return NODE_ITER->second->GetChildren(); return NODE_ITER->second->GetChildren();
} }
@ -254,6 +286,7 @@ namespace SHADE
if (parentNode == nullptr) if (parentNode == nullptr)
SHLOG_WARNING("Removing Entity {}'s parent", entityID) SHLOG_WARNING("Removing Entity {}'s parent", entityID)
// Handle self assignment
if (parentNode == parent) if (parentNode == parent)
return; return;
@ -264,6 +297,8 @@ namespace SHADE
void SHSceneGraph::SetParent(EntityID entityID, SHSceneNode* parent) const noexcept void SHSceneGraph::SetParent(EntityID entityID, SHSceneNode* parent) const noexcept
{ {
////////////////////////////////////////
// Error Handling
if (!SHEntityManager::IsValidEID(entityID)) if (!SHEntityManager::IsValidEID(entityID))
{ {
SHLOG_ERROR("Entity {} is invalid!", entityID) SHLOG_ERROR("Entity {} is invalid!", entityID)
@ -276,12 +311,15 @@ namespace SHADE
SHLOG_WARNING("Entity {} cannot be found in the scene!", entityID) SHLOG_WARNING("Entity {} cannot be found in the scene!", entityID)
return; return;
} }
////////////////////////////////////////
NODE_ITER->second->SetParent(parent); NODE_ITER->second->SetParent(parent);
} }
void SHSceneGraph::SetParent(EntityID entityID, EntityID parent) const noexcept void SHSceneGraph::SetParent(EntityID entityID, EntityID parent) const noexcept
{ {
////////////////////////////////////////
// Error Handling
if (!SHEntityManager::IsValidEID(entityID)) if (!SHEntityManager::IsValidEID(entityID))
{ {
SHLOG_ERROR("Entity {} is invalid! Unable to set parent of an invalid entity!", 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) SHLOG_WARNING("Entity {} cannot be found in the scene! Unable to parent to Entity {}", parent, entityID)
return; return;
} }
////////////////////////////////////////
SHSceneNode* currentNode = NODE_ITER->second; SHSceneNode* currentNode = NODE_ITER->second;
currentNode->SetParent(PARENT_ITER->second); currentNode->SetParent(PARENT_ITER->second);
@ -318,22 +357,32 @@ namespace SHADE
void SHSceneNode::AddChild(SHSceneNode* newChild) noexcept void SHSceneNode::AddChild(SHSceneNode* newChild) noexcept
{ {
////////////////////////////////////////
// Error Handling
if (newChild == nullptr) if (newChild == nullptr)
{ {
SHLOG_WARNING("Attempting to add a non-existent child to an entity!") SHLOG_WARNING("Attempting to add a non-existent child to an entity!")
return; return;
} }
////////////////////////////////////////
if (newChild->parent)
newChild->parent->RemoveChild(newChild);
newChild->parent = this;
children.emplace_back(newChild); children.emplace_back(newChild);
} }
bool SHSceneNode::RemoveChild(EntityID childID) noexcept bool SHSceneNode::RemoveChild(EntityID childID) noexcept
{ {
////////////////////////////////////////
// Error Handling
if (!SHEntityManager::IsValidEID(childID)) if (!SHEntityManager::IsValidEID(childID))
{ {
SHLOG_ERROR("Entity {} is invalid!", childID) SHLOG_ERROR("Entity {} is invalid!", childID)
return false; return false;
} }
////////////////////////////////////////
SHSceneNode* removedChild = nullptr; SHSceneNode* removedChild = nullptr;
const auto ENTITY_MATCH = [&](SHSceneNode* node) const auto ENTITY_MATCH = [&](SHSceneNode* node)
@ -348,18 +397,23 @@ namespace SHADE
}; };
children.end() = std::remove_if(children.begin(), children.end(), ENTITY_MATCH); 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 bool SHSceneNode::RemoveChild(SHSceneNode* childToRemove) noexcept
{ {
////////////////////////////////////////
// Error Handling
if (childToRemove == nullptr) if (childToRemove == nullptr)
{ {
SHLOG_WARNING("Attempting to remove non-existent child from Entity {}", entityID) SHLOG_WARNING("Attempting to remove non-existent child from Entity {}", entityID)
return false; return false;
} }
////////////////////////////////////////
children.end() = std::remove(children.begin(), children.end(), childToRemove); children.end() = std::remove(children.begin(), children.end(), childToRemove);
childToRemove->parent = nullptr; childToRemove->parent = nullptr;
@ -378,19 +432,26 @@ namespace SHADE
SHSceneNode* SHSceneGraph::AddNode(EntityID entityID, SHSceneNode* parent) SHSceneNode* SHSceneGraph::AddNode(EntityID entityID, SHSceneNode* parent)
{ {
////////////////////////////////////////
// Error Handling
if (!SHEntityManager::IsValidEID(entityID)) if (!SHEntityManager::IsValidEID(entityID))
{ {
SHLOG_ERROR("Entity {} is invalid!", entityID) SHLOG_ERROR("Entity {} is invalid!", entityID)
return nullptr; return nullptr;
} }
////////////////////////////////////////
if (auto NODE_ITER = entityNodeMap.find(entityID); NODE_ITER != entityNodeMap.end()) if (auto NODE_ITER = entityNodeMap.find(entityID); NODE_ITER != entityNodeMap.end())
{ {
SHLOG_WARNING("Entity {} already exists in the scene!", entityID) SHLOG_WARNING("Entity {} already exists in the scene!", entityID)
return NODE_ITER->second; return NODE_ITER->second;
} }
SHSceneNode* newNode = AllocateNode(entityID); SHSceneNode* newNode = AllocateNode(entityID);
if (parent == nullptr)
parent = root;
newNode->SetParent(parent); newNode->SetParent(parent);
return newNode; return newNode;

View File

@ -35,40 +35,40 @@ namespace SHADE
/* Constructors & Destructor */ /* Constructors & Destructor */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
~SHSceneNode () = default; ~SHSceneNode () = default;
SHSceneNode (EntityID eid, SHSceneNode* parent = nullptr) noexcept; SHSceneNode (EntityID eid, SHSceneNode* parent = nullptr) noexcept;
SHSceneNode (const SHSceneNode& rhs) noexcept; SHSceneNode (const SHSceneNode& rhs) noexcept;
SHSceneNode (SHSceneNode&& rhs) noexcept; SHSceneNode (SHSceneNode&& rhs) noexcept;
SHSceneNode& operator= (const SHSceneNode& rhs) noexcept; SHSceneNode& operator= (const SHSceneNode& rhs) noexcept;
SHSceneNode& operator= (SHSceneNode&& rhs) noexcept; SHSceneNode& operator= (SHSceneNode&& rhs) noexcept;
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Getter Functions */ /* Getter Functions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
[[nodiscard]] EntityID GetEntityID () const noexcept { return entityID ;} [[nodiscard]] EntityID GetEntityID () const noexcept;
[[nodiscard]] SHSceneNode* GetParent () const noexcept { return parent; } [[nodiscard]] SHSceneNode* GetParent () const noexcept;
[[nodiscard]] std::vector<SHSceneNode*>& GetChildren () noexcept { return children; } [[nodiscard]] const std::vector<SHSceneNode*>& GetChildren () const noexcept;
[[nodiscard]] SHSceneNode* GetChild (EntityID childID) const noexcept; [[nodiscard]] SHSceneNode* GetChild (EntityID childID) const noexcept;
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Setter Functions */ /* Setter Functions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
void SetParent (SHSceneNode* parentNode) noexcept; void SetParent (SHSceneNode* parentNode) noexcept;
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Function Members */ /* Function Members */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
void AddChild (SHSceneNode* newChild) noexcept; void AddChild (SHSceneNode* newChild) noexcept;
bool RemoveChild (EntityID childID) noexcept; bool RemoveChild (EntityID childID) noexcept;
bool RemoveChild (SHSceneNode* childToRemove) noexcept; bool RemoveChild (SHSceneNode* childToRemove) noexcept;
void RemoveAllChildren () noexcept; void RemoveAllChildren () noexcept;
private: private:
EntityID entityID; EntityID entityID;
@ -89,19 +89,19 @@ namespace SHADE
/* Constructors & Destructor */ /* Constructors & Destructor */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
SHSceneGraph () noexcept; SHSceneGraph () noexcept;
~SHSceneGraph () noexcept; ~SHSceneGraph () noexcept;
SHSceneGraph (const SHSceneGraph&) = delete; SHSceneGraph (const SHSceneGraph&) = delete;
SHSceneGraph (SHSceneGraph&&) = delete; SHSceneGraph (SHSceneGraph&&) = delete;
SHSceneGraph& operator= (const SHSceneGraph&) = delete; SHSceneGraph& operator= (const SHSceneGraph&) = delete;
SHSceneGraph& operator= (SHSceneGraph&&) = delete; SHSceneGraph& operator= (SHSceneGraph&&) = delete;
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Getter Functions */ /* Getter Functions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
[[nodiscard]] SHSceneNode* GetRoot () const noexcept; [[nodiscard]] const SHSceneNode* GetRoot () const noexcept;
[[nodiscard]] SHSceneNode* GetNode (EntityID entityID) const noexcept; [[nodiscard]] SHSceneNode* GetNode (EntityID entityID) const noexcept;
[[nodiscard]] SHSceneNode* GetParent (EntityID entityID) const noexcept; [[nodiscard]] SHSceneNode* GetParent (EntityID entityID) const noexcept;
[[nodiscard]] SHSceneNode* GetChild (EntityID entityID, SHSceneNode* childNode) const noexcept; [[nodiscard]] SHSceneNode* GetChild (EntityID entityID, SHSceneNode* childNode) const noexcept;
@ -112,17 +112,17 @@ namespace SHADE
/* Setter Functions */ /* Setter Functions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
void SetParent (EntityID entityID, SHSceneNode* parent) const noexcept; void SetParent (EntityID entityID, SHSceneNode* parent) const noexcept;
void SetParent (EntityID entityID, EntityID parent) const noexcept; void SetParent (EntityID entityID, EntityID parent) const noexcept;
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Function Members */ /* Function Members */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
SHSceneNode* AddNode (EntityID entityID, SHSceneNode* parent = nullptr); SHSceneNode* AddNode (EntityID entityID, SHSceneNode* parent = nullptr);
bool RemoveNode (EntityID entityID) noexcept; bool RemoveNode (EntityID entityID) noexcept;
bool RemoveNode (SHSceneNode* nodeToRemove) noexcept; bool RemoveNode (SHSceneNode* nodeToRemove) noexcept;
void Reset () noexcept; void Reset () noexcept;
private: private:
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
@ -137,7 +137,7 @@ namespace SHADE
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
SHSceneNode* AllocateNode (EntityID entityID); SHSceneNode* AllocateNode (EntityID entityID);
void ReleaseNode (SHSceneNode* node) noexcept; void ReleaseNode (SHSceneNode* node) noexcept;
}; };