Added a scene graph
This commit is contained in:
parent
759e414657
commit
d4944ef920
|
@ -183,6 +183,7 @@
|
||||||
<ClInclude Include="src\Resource\Handle.h" />
|
<ClInclude Include="src\Resource\Handle.h" />
|
||||||
<ClInclude Include="src\Resource\ResourceLibrary.h" />
|
<ClInclude Include="src\Resource\ResourceLibrary.h" />
|
||||||
<ClInclude Include="src\Resource\SparseSet.h" />
|
<ClInclude Include="src\Resource\SparseSet.h" />
|
||||||
|
<ClInclude Include="src\Scene\SHSceneGraph.h" />
|
||||||
<ClInclude Include="src\SHpch.h" />
|
<ClInclude Include="src\SHpch.h" />
|
||||||
<ClInclude Include="src\Scene\SHScene.h" />
|
<ClInclude Include="src\Scene\SHScene.h" />
|
||||||
<ClInclude Include="src\Scene\SHSceneManager.h" />
|
<ClInclude Include="src\Scene\SHSceneManager.h" />
|
||||||
|
@ -253,6 +254,7 @@
|
||||||
<ClCompile Include="src\Math\Vector\SHVec2.cpp" />
|
<ClCompile Include="src\Math\Vector\SHVec2.cpp" />
|
||||||
<ClCompile Include="src\Math\Vector\SHVec3.cpp" />
|
<ClCompile Include="src\Math\Vector\SHVec3.cpp" />
|
||||||
<ClCompile Include="src\Math\Vector\SHVec4.cpp" />
|
<ClCompile Include="src\Math\Vector\SHVec4.cpp" />
|
||||||
|
<ClCompile Include="src\Scene\SHSceneGraph.cpp" />
|
||||||
<ClCompile Include="src\SHpch.cpp">
|
<ClCompile Include="src\SHpch.cpp">
|
||||||
<PrecompiledHeader>Create</PrecompiledHeader>
|
<PrecompiledHeader>Create</PrecompiledHeader>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
@ -284,4 +286,4 @@
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
<ImportGroup Label="ExtensionTargets">
|
<ImportGroup Label="ExtensionTargets">
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
</Project>
|
</Project>
|
|
@ -353,6 +353,7 @@
|
||||||
<ClInclude Include="src\Math\Vector\SHVec2.h" />
|
<ClInclude Include="src\Math\Vector\SHVec2.h" />
|
||||||
<ClInclude Include="src\Math\Vector\SHVec3.h" />
|
<ClInclude Include="src\Math\Vector\SHVec3.h" />
|
||||||
<ClInclude Include="src\Math\Vector\SHVec4.h" />
|
<ClInclude Include="src\Math\Vector\SHVec4.h" />
|
||||||
|
<ClInclude Include="src\Scene\SHSceneGraph.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="src\Engine\ECS_Base\Components\SHComponent.cpp">
|
<ClCompile Include="src\Engine\ECS_Base\Components\SHComponent.cpp">
|
||||||
|
@ -536,5 +537,6 @@
|
||||||
<ClCompile Include="src\Math\Vector\SHVec2.cpp" />
|
<ClCompile Include="src\Math\Vector\SHVec2.cpp" />
|
||||||
<ClCompile Include="src\Math\Vector\SHVec3.cpp" />
|
<ClCompile Include="src\Math\Vector\SHVec3.cpp" />
|
||||||
<ClCompile Include="src\Math\Vector\SHVec4.cpp" />
|
<ClCompile Include="src\Math\Vector\SHVec4.cpp" />
|
||||||
|
<ClCompile Include="src\Scene\SHSceneGraph.cpp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
|
@ -34,7 +34,7 @@ namespace SHADE
|
||||||
//The Container of all Componentgroups
|
//The Container of all Componentgroups
|
||||||
static std::vector<SHComponentGroup> componentGroups;
|
static std::vector<SHComponentGroup> componentGroups;
|
||||||
|
|
||||||
friend class SHSceneNode;
|
friend struct SHSceneNode;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#include <ranges>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
|
@ -0,0 +1,475 @@
|
||||||
|
/****************************************************************************************
|
||||||
|
* \file SHSceneGraph.cpp
|
||||||
|
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
||||||
|
* \brief Implementation for a Scene Graph & Scene Nodes.
|
||||||
|
*
|
||||||
|
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||||
|
* disclosure of this file or its contents without the prior written consent
|
||||||
|
* of DigiPen Institute of Technology is prohibited.
|
||||||
|
****************************************************************************************/
|
||||||
|
|
||||||
|
#include <SHpch.h>
|
||||||
|
|
||||||
|
// Primary Header
|
||||||
|
#include "SHSceneGraph.h"
|
||||||
|
|
||||||
|
// Project Headers
|
||||||
|
#include "Engine/ECS_Base/System/SHEntityManager.h"
|
||||||
|
#include "Tools/SHLogger.h"
|
||||||
|
#include "Tools/SHException.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Constructors & Destructor Definitions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
SHSceneNode::SHSceneNode(EntityID eid, SHSceneNode* parent) noexcept
|
||||||
|
: isActive { true }
|
||||||
|
, entityID { eid }
|
||||||
|
, parent { parent }
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
SHSceneNode::SHSceneNode(const SHSceneNode& rhs) noexcept
|
||||||
|
: isActive { rhs.isActive }
|
||||||
|
, entityID { rhs.entityID }
|
||||||
|
, parent { rhs.parent }
|
||||||
|
{
|
||||||
|
std::ranges::copy(rhs.children.begin(), rhs.children.end(), std::back_inserter(children));
|
||||||
|
}
|
||||||
|
|
||||||
|
SHSceneNode::SHSceneNode(SHSceneNode&& rhs) noexcept
|
||||||
|
: isActive { rhs.isActive }
|
||||||
|
, entityID { rhs.entityID }
|
||||||
|
, parent { rhs.parent }
|
||||||
|
{
|
||||||
|
std::ranges::copy(rhs.children.begin(), rhs.children.end(), std::back_inserter(children));
|
||||||
|
}
|
||||||
|
|
||||||
|
SHSceneNode& SHSceneNode::operator=(const SHSceneNode& rhs) noexcept
|
||||||
|
{
|
||||||
|
if (this == &rhs)
|
||||||
|
return *this;
|
||||||
|
|
||||||
|
isActive = rhs.isActive;
|
||||||
|
entityID = rhs.entityID;
|
||||||
|
parent = rhs.parent;
|
||||||
|
|
||||||
|
children.clear();
|
||||||
|
std::ranges::copy(rhs.children.begin(), rhs.children.end(), std::back_inserter(children));
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
SHSceneNode& SHSceneNode::operator=(SHSceneNode&& rhs) noexcept
|
||||||
|
{
|
||||||
|
isActive = rhs.isActive;
|
||||||
|
entityID = rhs.entityID;
|
||||||
|
parent = rhs.parent;
|
||||||
|
|
||||||
|
children.clear();
|
||||||
|
std::ranges::copy(rhs.children.begin(), rhs.children.end(), std::back_inserter(children));
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
SHSceneGraph::SHSceneGraph() noexcept
|
||||||
|
: root { nullptr }
|
||||||
|
{}
|
||||||
|
|
||||||
|
SHSceneGraph::~SHSceneGraph() noexcept
|
||||||
|
{
|
||||||
|
SHASSERT(root != nullptr, "Unable to destroy a Scene without a root node!")
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
SHLOG_INFO("Destroying Scene Graph...")
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Go through the map and release all the nodes
|
||||||
|
for (auto* node : entityNodeMap | std::views::values)
|
||||||
|
ReleaseNode(node);
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
SHLOG_INFO("Scene Graph Destroyed Successfully!")
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Getter Function Definitions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
SHSceneNode* SHSceneNode::GetChild(EntityID childID) const noexcept
|
||||||
|
{
|
||||||
|
// Error handling
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find child
|
||||||
|
const auto ENTITY_MATCH = [&](const SHSceneNode* node) { return node->GetEntityID() == childID; };
|
||||||
|
|
||||||
|
const auto CHILD_ITER = std::ranges::find_if(children.begin(), children.end(),ENTITY_MATCH);
|
||||||
|
if (CHILD_ITER == children.end())
|
||||||
|
{
|
||||||
|
SHLOG_WARNING("Entity {} is not a child of Entity {}! Unable to retrieve child node!", childID, entityID)
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return *CHILD_ITER;
|
||||||
|
}
|
||||||
|
|
||||||
|
SHSceneNode* SHSceneGraph::GetRoot() const noexcept
|
||||||
|
{
|
||||||
|
if (root != nullptr)
|
||||||
|
return root;
|
||||||
|
|
||||||
|
SHLOG_WARNING("Scene has no root object!")
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
SHSceneNode* SHSceneGraph::GetNode(EntityID entityID) const noexcept
|
||||||
|
{
|
||||||
|
if (!SHEntityManager::IsValidEID(entityID))
|
||||||
|
{
|
||||||
|
SHLOG_ERROR("Entity {} is invalid! Unable to Get Scene node!", entityID)
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto NODE_ITER = entityNodeMap.find(entityID);
|
||||||
|
if (NODE_ITER == entityNodeMap.end())
|
||||||
|
{
|
||||||
|
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
|
||||||
|
{
|
||||||
|
if (!SHEntityManager::IsValidEID(entityID))
|
||||||
|
{
|
||||||
|
SHLOG_ERROR("Entity {} is invalid! Unable to get Parent node!", entityID)
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto NODE_ITER = entityNodeMap.find(entityID);
|
||||||
|
if (NODE_ITER == entityNodeMap.end())
|
||||||
|
{
|
||||||
|
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
|
||||||
|
if (!SHEntityManager::IsValidEID(entityID))
|
||||||
|
{
|
||||||
|
SHLOG_ERROR("Entity {} is invalid!", entityID)
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto NODE_ITER = entityNodeMap.find(entityID);
|
||||||
|
if (NODE_ITER == entityNodeMap.end())
|
||||||
|
{
|
||||||
|
SHLOG_WARNING("Entity {} cannot be found in the scene!", entityID)
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto& children = NODE_ITER->second->GetChildren();
|
||||||
|
if (children.empty())
|
||||||
|
{
|
||||||
|
SHLOG_WARNING("Entity {} has no children!", entityID)
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto CHILD_ITER = std::ranges::find(children.begin(), children.end(), childNode);
|
||||||
|
if (CHILD_ITER == children.end())
|
||||||
|
{
|
||||||
|
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
|
||||||
|
{
|
||||||
|
if (!SHEntityManager::IsValidEID(entityID))
|
||||||
|
{
|
||||||
|
SHLOG_ERROR("Entity {} is invalid!", entityID)
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto NODE_ITER = entityNodeMap.find(entityID);
|
||||||
|
if (NODE_ITER == entityNodeMap.end())
|
||||||
|
{
|
||||||
|
SHLOG_WARNING("Entity {} cannot be found in the scene!", entityID)
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NODE_ITER->second->GetChild(childEntityID);
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<SHSceneNode*>& SHSceneGraph::GetChildren(EntityID entityID) const noexcept
|
||||||
|
{
|
||||||
|
// TODO(Diren): Discuss with team best way to handle this
|
||||||
|
|
||||||
|
if (!SHEntityManager::IsValidEID(entityID))
|
||||||
|
{
|
||||||
|
SHLOG_ERROR("Entity {} is invalid!", entityID)
|
||||||
|
return root->GetChildren();
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto NODE_ITER = entityNodeMap.find(entityID);
|
||||||
|
if (NODE_ITER == entityNodeMap.end())
|
||||||
|
{
|
||||||
|
SHLOG_WARNING("Entity {} cannot be found in the scene!", entityID)
|
||||||
|
return root->GetChildren();
|
||||||
|
}
|
||||||
|
|
||||||
|
return NODE_ITER->second->GetChildren();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Setter Function Definitions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void SHSceneNode::SetParent(SHSceneNode* parentNode) noexcept
|
||||||
|
{
|
||||||
|
if (parentNode == nullptr)
|
||||||
|
SHLOG_WARNING("Removing Entity {}'s parent", entityID)
|
||||||
|
|
||||||
|
if (parentNode == parent)
|
||||||
|
return;
|
||||||
|
|
||||||
|
parent = parentNode;
|
||||||
|
// Update parent's children
|
||||||
|
parent->AddChild(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHSceneGraph::SetParent(EntityID entityID, SHSceneNode* parent) const noexcept
|
||||||
|
{
|
||||||
|
if (!SHEntityManager::IsValidEID(entityID))
|
||||||
|
{
|
||||||
|
SHLOG_ERROR("Entity {} is invalid!", entityID)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto NODE_ITER = entityNodeMap.find(entityID);
|
||||||
|
if (NODE_ITER == entityNodeMap.end())
|
||||||
|
{
|
||||||
|
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
|
||||||
|
{
|
||||||
|
if (!SHEntityManager::IsValidEID(entityID))
|
||||||
|
{
|
||||||
|
SHLOG_ERROR("Entity {} is invalid! Unable to set parent of an invalid entity!", entityID)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!SHEntityManager::IsValidEID(parent))
|
||||||
|
{
|
||||||
|
SHLOG_ERROR("Parent Entity {} is invalid! Unable to set Entity {}'s parent!", parent, entityID)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto NODE_ITER = entityNodeMap.find(entityID);
|
||||||
|
if (NODE_ITER == entityNodeMap.end())
|
||||||
|
{
|
||||||
|
SHLOG_WARNING("Entity {} cannot be found in the scene! Unable to set parent!", entityID)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto PARENT_ITER = entityNodeMap.find(entityID);
|
||||||
|
if (PARENT_ITER == entityNodeMap.end())
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Public Function Member Definitions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void SHSceneNode::AddChild(SHSceneNode* newChild) noexcept
|
||||||
|
{
|
||||||
|
if (newChild == nullptr)
|
||||||
|
{
|
||||||
|
SHLOG_WARNING("Attempting to add a non-existent child to an entity!")
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
children.emplace_back(newChild);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SHSceneNode::RemoveChild(EntityID childID) noexcept
|
||||||
|
{
|
||||||
|
if (!SHEntityManager::IsValidEID(childID))
|
||||||
|
{
|
||||||
|
SHLOG_ERROR("Entity {} is invalid!", childID)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
SHSceneNode* removedChild = nullptr;
|
||||||
|
const auto ENTITY_MATCH = [&](SHSceneNode* node)
|
||||||
|
{
|
||||||
|
if (node->GetEntityID() == childID)
|
||||||
|
{
|
||||||
|
removedChild = node;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
children.end() = std::remove_if(children.begin(), children.end(), ENTITY_MATCH);
|
||||||
|
removedChild->parent = nullptr;
|
||||||
|
|
||||||
|
return removedChild == nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SHSceneNode::RemoveChild(SHSceneNode* childToRemove) noexcept
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHSceneNode::RemoveAllChildren() noexcept
|
||||||
|
{
|
||||||
|
for (const auto child : children)
|
||||||
|
child->parent = nullptr;
|
||||||
|
|
||||||
|
children.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SHSceneNode* SHSceneGraph::AddNode(EntityID entityID, SHSceneNode* parent)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
newNode->SetParent(parent);
|
||||||
|
|
||||||
|
return newNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SHSceneGraph::RemoveNode(EntityID entityID) noexcept
|
||||||
|
{
|
||||||
|
if (!SHEntityManager::IsValidEID(entityID))
|
||||||
|
{
|
||||||
|
SHLOG_ERROR("Entity {} is invalid!", entityID)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto NODE_ITER = entityNodeMap.find(entityID);
|
||||||
|
if (NODE_ITER == entityNodeMap.end())
|
||||||
|
{
|
||||||
|
SHLOG_WARNING("Entity {} does not exist in the scene!", entityID)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove reference of current node from parent
|
||||||
|
SHSceneNode* currentNode = NODE_ITER->second;
|
||||||
|
SHSceneNode* parent = currentNode->GetParent();
|
||||||
|
if (parent != nullptr)
|
||||||
|
parent->RemoveChild(currentNode);
|
||||||
|
|
||||||
|
ReleaseNode(currentNode);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SHSceneGraph::RemoveNode(SHSceneNode* nodeToRemove) noexcept
|
||||||
|
{
|
||||||
|
// Remove reference of current node from parent
|
||||||
|
SHSceneNode* parent = nodeToRemove->GetParent();
|
||||||
|
if (parent != nullptr)
|
||||||
|
parent->RemoveChild(nodeToRemove);
|
||||||
|
|
||||||
|
ReleaseNode(nodeToRemove);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHSceneGraph::Reset() noexcept
|
||||||
|
{
|
||||||
|
for (auto* node : entityNodeMap | std::views::values)
|
||||||
|
ReleaseNode(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Private Function Member Definitions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
SHSceneNode* SHSceneGraph::AllocateNode(EntityID entityID)
|
||||||
|
{
|
||||||
|
SHSceneNode* newNode = new SHSceneNode{entityID};
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
SHLOG_INFO("Allocated a new Scene Node for Entity {}!", entityID)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
entityNodeMap.emplace(entityID, newNode);
|
||||||
|
return newNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHSceneGraph::ReleaseNode(SHSceneNode* node) noexcept
|
||||||
|
{
|
||||||
|
SHASSERT(node != nullptr, "Attempting to release Invalid Node!")
|
||||||
|
|
||||||
|
// Remove parent's reference to this node if there is a parent
|
||||||
|
if (node->GetParent() != nullptr)
|
||||||
|
node->GetParent()->RemoveChild(node);
|
||||||
|
|
||||||
|
// Remove child's references to this node. Children end up as floating nodes.
|
||||||
|
for (auto* child : node->GetChildren())
|
||||||
|
{
|
||||||
|
child->SetParent(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
entityNodeMap.erase(node->GetEntityID());
|
||||||
|
delete node;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace SHADE
|
|
@ -0,0 +1,143 @@
|
||||||
|
/****************************************************************************************
|
||||||
|
* \file SHSceneGraph.h
|
||||||
|
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
||||||
|
* \brief Interface for a Scene Graph & Scene Nodes.
|
||||||
|
*
|
||||||
|
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||||
|
* disclosure of this file or its contents without the prior written consent
|
||||||
|
* of DigiPen Institute of Technology is prohibited.
|
||||||
|
****************************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
// Project Headers
|
||||||
|
#include "Engine/ECS_Base/Entity/SHEntity.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Type Definitions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
class SHSceneNode
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Data Members */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
bool isActive;
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Constructors & Destructor */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
~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;
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Getter Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
[[nodiscard]] EntityID GetEntityID () const noexcept { return entityID ;}
|
||||||
|
[[nodiscard]] SHSceneNode* GetParent () const noexcept { return parent; }
|
||||||
|
[[nodiscard]] std::vector<SHSceneNode*>& GetChildren () noexcept { return children; }
|
||||||
|
|
||||||
|
[[nodiscard]] SHSceneNode* GetChild (EntityID childID) const noexcept;
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Setter Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void SetParent (SHSceneNode* parentNode) noexcept;
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Function Members */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void AddChild (SHSceneNode* newChild) noexcept;
|
||||||
|
|
||||||
|
bool RemoveChild (EntityID childID) noexcept;
|
||||||
|
bool RemoveChild (SHSceneNode* childToRemove) noexcept;
|
||||||
|
|
||||||
|
void RemoveAllChildren () noexcept;
|
||||||
|
|
||||||
|
private:
|
||||||
|
EntityID entityID;
|
||||||
|
SHSceneNode* parent;
|
||||||
|
std::vector<SHSceneNode*> children;
|
||||||
|
};
|
||||||
|
|
||||||
|
class SHSceneGraph
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Type Definitions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
using EntityNodeMap = std::unordered_map<EntityID, SHSceneNode*>;
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Constructors & Destructor */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
SHSceneGraph () noexcept;
|
||||||
|
~SHSceneGraph () noexcept;
|
||||||
|
|
||||||
|
SHSceneGraph (const SHSceneGraph&) = delete;
|
||||||
|
SHSceneGraph (SHSceneGraph&&) = delete;
|
||||||
|
SHSceneGraph& operator= (const SHSceneGraph&) = delete;
|
||||||
|
SHSceneGraph& operator= (SHSceneGraph&&) = delete;
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Getter Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
[[nodiscard]] 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;
|
||||||
|
[[nodiscard]] SHSceneNode* GetChild (EntityID entityID, EntityID childEntityID) const noexcept;
|
||||||
|
[[nodiscard]] const std::vector<SHSceneNode*>& GetChildren (EntityID entityID) const noexcept;
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Setter Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
private:
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Data Members */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
SHSceneNode* root;
|
||||||
|
EntityNodeMap entityNodeMap;
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Function Members */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
SHSceneNode* AllocateNode (EntityID entityID);
|
||||||
|
void ReleaseNode (SHSceneNode* node) noexcept;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace SHADE
|
Loading…
Reference in New Issue