Merge pull request #187 from SHADE-DP/SP3-12-SceneGraph
SP3-12 Cleaned up SceneGraph Interface & QoL NEW Added IsChildOf method to SceneGraph Added Events when Adding & Removing Children UPDATES Scene Nodes are now rea- only aside from active states
This commit is contained in:
commit
78e94ca389
|
@ -124,48 +124,6 @@
|
|||
Mesh: 144838771
|
||||
Material: 123745521
|
||||
Scripts: ~
|
||||
- EID: 5
|
||||
Name: item
|
||||
IsActive: true
|
||||
NumberOfChildren: 0
|
||||
Components:
|
||||
Transform Component:
|
||||
Translate: {x: 0, y: -2, z: -5}
|
||||
Rotate: {x: 0, y: 0, z: 0}
|
||||
Scale: {x: 2, y: 2, z: 2}
|
||||
Renderable Component:
|
||||
Mesh: 144838771
|
||||
Material: 123745521
|
||||
RigidBody Component:
|
||||
Type: Dynamic
|
||||
Mass: 1
|
||||
Drag: 0
|
||||
Angular Drag: 0
|
||||
Use Gravity: true
|
||||
Interpolate: false
|
||||
Freeze Position X: false
|
||||
Freeze Position Y: false
|
||||
Freeze Position Z: false
|
||||
Freeze Rotation X: true
|
||||
Freeze Rotation Y: true
|
||||
Freeze Rotation Z: true
|
||||
Collider Component:
|
||||
Colliders:
|
||||
- Is Trigger: false
|
||||
Type: Box
|
||||
Half Extents: {x: 1, y: 1, z: 1}
|
||||
Friction: 0.400000006
|
||||
Bounciness: 0
|
||||
Density: 1
|
||||
Position Offset: {x: 0, y: 0.5, z: 0}
|
||||
- Is Trigger: true
|
||||
Type: Box
|
||||
Half Extents: {x: 2, y: 2, z: 2}
|
||||
Friction: 0.400000006
|
||||
Bounciness: 0
|
||||
Density: 1
|
||||
Position Offset: {x: 0, y: 0.5, z: 0}
|
||||
Scripts: ~
|
||||
- EID: 6
|
||||
Name: AI
|
||||
IsActive: true
|
||||
|
@ -226,4 +184,46 @@
|
|||
Color: {x: 1, y: 1, z: 1, w: 1}
|
||||
Layer: 4294967295
|
||||
Strength: 0.25
|
||||
Scripts: ~
|
||||
- EID: 5
|
||||
Name: item
|
||||
IsActive: true
|
||||
NumberOfChildren: 0
|
||||
Components:
|
||||
Transform Component:
|
||||
Translate: {x: 0, y: -2, z: -5}
|
||||
Rotate: {x: 0, y: 0, z: 0}
|
||||
Scale: {x: 2, y: 2, z: 2}
|
||||
Renderable Component:
|
||||
Mesh: 144838771
|
||||
Material: 123745521
|
||||
RigidBody Component:
|
||||
Type: Dynamic
|
||||
Mass: 1
|
||||
Drag: 0
|
||||
Angular Drag: 0
|
||||
Use Gravity: true
|
||||
Interpolate: false
|
||||
Freeze Position X: false
|
||||
Freeze Position Y: false
|
||||
Freeze Position Z: false
|
||||
Freeze Rotation X: true
|
||||
Freeze Rotation Y: true
|
||||
Freeze Rotation Z: true
|
||||
Collider Component:
|
||||
Colliders:
|
||||
- Is Trigger: false
|
||||
Type: Box
|
||||
Half Extents: {x: 1, y: 1, z: 1}
|
||||
Friction: 0.400000006
|
||||
Bounciness: 0
|
||||
Density: 1
|
||||
Position Offset: {x: 0, y: 0.5, z: 0}
|
||||
- Is Trigger: true
|
||||
Type: Box
|
||||
Half Extents: {x: 2, y: 2, z: 2}
|
||||
Friction: 0.400000006
|
||||
Bounciness: 0
|
||||
Density: 1
|
||||
Position Offset: {x: 0, y: 0.5, z: 0}
|
||||
Scripts: ~
|
|
@ -419,7 +419,7 @@ namespace SHADE
|
|||
|
||||
void SHEntityParentCommand::Execute()
|
||||
{
|
||||
auto const& sceneGraph = SHSceneManager::GetCurrentSceneGraph();
|
||||
auto& sceneGraph = SHSceneManager::GetCurrentSceneGraph();
|
||||
for (auto const& eid : entities)
|
||||
{
|
||||
if (entityParentData[eid].newParentEID == MAX_EID)
|
||||
|
@ -431,7 +431,7 @@ namespace SHADE
|
|||
|
||||
void SHEntityParentCommand::Undo()
|
||||
{
|
||||
auto const& sceneGraph = SHSceneManager::GetCurrentSceneGraph();
|
||||
auto& sceneGraph = SHSceneManager::GetCurrentSceneGraph();
|
||||
for (auto const& eid : entities)
|
||||
{
|
||||
if (entityParentData[eid].oldParentEID == MAX_EID)
|
||||
|
|
|
@ -11,9 +11,11 @@ constexpr SHEventIdentifier SH_ENTITY_CREATION_EVENT { 2 };
|
|||
constexpr SHEventIdentifier SH_COMPONENT_ADDED_EVENT { 3 };
|
||||
constexpr SHEventIdentifier SH_COMPONENT_REMOVED_EVENT { 4 };
|
||||
constexpr SHEventIdentifier SH_SCENEGRAPH_CHANGE_PARENT_EVENT { 5 };
|
||||
constexpr SHEventIdentifier SH_PHYSICS_COLLIDER_ADDED_EVENT { 6 };
|
||||
constexpr SHEventIdentifier SH_PHYSICS_COLLIDER_REMOVED_EVENT { 7 };
|
||||
constexpr SHEventIdentifier SH_EDITOR_ON_PLAY_EVENT { 8 };
|
||||
constexpr SHEventIdentifier SH_EDITOR_ON_PAUSE_EVENT { 9 };
|
||||
constexpr SHEventIdentifier SH_EDITOR_ON_STOP_EVENT { 10 };
|
||||
constexpr SHEventIdentifier SH_SCENEGRAPH_ADD_CHILD_EVENT { 6 };
|
||||
constexpr SHEventIdentifier SH_SCENEGRAPH_REMOVE_CHILD_EVENT { 7 };
|
||||
constexpr SHEventIdentifier SH_PHYSICS_COLLIDER_ADDED_EVENT { 8 };
|
||||
constexpr SHEventIdentifier SH_PHYSICS_COLLIDER_REMOVED_EVENT { 9 };
|
||||
constexpr SHEventIdentifier SH_EDITOR_ON_PLAY_EVENT { 10 };
|
||||
constexpr SHEventIdentifier SH_EDITOR_ON_PAUSE_EVENT { 11 };
|
||||
constexpr SHEventIdentifier SH_EDITOR_ON_STOP_EVENT { 12 };
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/****************************************************************************************
|
||||
* \file SHSceneGraph.cpp
|
||||
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
||||
* \brief Implementation for a Scene Graph & Scene Nodes.
|
||||
* \brief Implementation for a Scene Graph.
|
||||
*
|
||||
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||
* disclosure of this file or its contents without the prior written consent
|
||||
|
@ -16,8 +16,6 @@
|
|||
// Project Headers
|
||||
#include "ECS_Base/Managers/SHEntityManager.h"
|
||||
#include "Events/SHEventManager.hpp"
|
||||
#include "Tools/SHLogger.h"
|
||||
#include "Tools/SHException.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
@ -25,56 +23,6 @@ namespace SHADE
|
|||
/* Constructors & Destructor Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
SHSceneNode::SHSceneNode(EntityID eid, SHSceneNode* parent) noexcept
|
||||
: active { true }
|
||||
, entityID { eid }
|
||||
, parent { parent }
|
||||
{}
|
||||
|
||||
|
||||
SHSceneNode::SHSceneNode(const SHSceneNode& rhs) noexcept
|
||||
: active { rhs.active }
|
||||
, entityID { rhs.entityID }
|
||||
, parent { rhs.parent }
|
||||
{
|
||||
std::ranges::copy(rhs.children.begin(), rhs.children.end(), std::back_inserter(children));
|
||||
}
|
||||
|
||||
SHSceneNode::SHSceneNode(SHSceneNode&& rhs) noexcept
|
||||
: active { rhs.active }
|
||||
, 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;
|
||||
|
||||
active = rhs.active;
|
||||
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
|
||||
{
|
||||
active = rhs.active;
|
||||
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 }
|
||||
{
|
||||
|
@ -110,56 +58,6 @@ namespace SHADE
|
|||
/* Getter Function Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
bool SHSceneNode::IsActive() const noexcept
|
||||
{
|
||||
return active;
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
////////////////////////////////////////
|
||||
// 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;
|
||||
}
|
||||
|
||||
const SHSceneNode* SHSceneGraph::GetRoot() const noexcept
|
||||
{
|
||||
if (root != nullptr)
|
||||
|
@ -313,41 +211,7 @@ namespace SHADE
|
|||
/* Setter Function Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
void SHSceneNode::SetParent(SHSceneNode* parentNode) noexcept
|
||||
{
|
||||
if (parentNode == nullptr)
|
||||
{
|
||||
SHLOG_WARNING("Removing Entity {}'s parent", entityID)
|
||||
|
||||
if (parent)
|
||||
parent->RemoveChild(this);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle self assignment
|
||||
if (parent && parentNode->entityID == parent->entityID)
|
||||
return;
|
||||
|
||||
if (parent)
|
||||
parent->RemoveChild(this);
|
||||
|
||||
parent = parentNode;
|
||||
// Update parent's children
|
||||
parent->AddChild(this);
|
||||
}
|
||||
|
||||
void SHSceneNode::SetActive(bool newActiveState) noexcept
|
||||
{
|
||||
active = newActiveState;
|
||||
|
||||
for (auto* child : children)
|
||||
{
|
||||
SetActive(newActiveState);
|
||||
}
|
||||
}
|
||||
|
||||
void SHSceneGraph::SetParent(EntityID entityID, SHSceneNode* parent) const noexcept
|
||||
void SHSceneGraph::SetParent(EntityID entityID, SHSceneNode* newParent) noexcept
|
||||
{
|
||||
////////////////////////////////////////
|
||||
// Error Handling
|
||||
|
@ -369,30 +233,31 @@ namespace SHADE
|
|||
{
|
||||
.node = NODE_ITER->second
|
||||
, .oldParent = NODE_ITER->second->GetParent()
|
||||
, .newParent = parent ? parent : root
|
||||
, .newParent = newParent ? newParent : root
|
||||
};
|
||||
|
||||
if (parent == nullptr)
|
||||
parent = root;
|
||||
if (newParent == nullptr)
|
||||
newParent = root;
|
||||
|
||||
NODE_ITER->second->SetParent(parent);
|
||||
ChangeParent(NODE_ITER->second, newParent);
|
||||
|
||||
SHEventManager::BroadcastEvent<SHSceneGraphChangeParentEvent>(EVENT_DATA, SH_SCENEGRAPH_CHANGE_PARENT_EVENT);
|
||||
}
|
||||
|
||||
void SHSceneGraph::SetParent(EntityID entityID, EntityID parent) const noexcept
|
||||
void SHSceneGraph::SetParent(EntityID entityID, EntityID newParent) noexcept
|
||||
{
|
||||
////////////////////////////////////////
|
||||
// Error Handling
|
||||
|
||||
if (!SHEntityManager::IsValidEID(entityID))
|
||||
{
|
||||
SHLOG_ERROR("Entity {} is invalid! Unable to set parent of an invalid entity!", entityID)
|
||||
return;
|
||||
}
|
||||
|
||||
if (!SHEntityManager::IsValidEID(parent))
|
||||
if (!SHEntityManager::IsValidEID(newParent))
|
||||
{
|
||||
SHLOG_ERROR("Parent Entity {} is invalid! Unable to set Entity {}'s parent!", parent, entityID)
|
||||
SHLOG_ERROR("Parent Entity {} is invalid! Unable to set Entity {}'s parent!", newParent, entityID)
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -403,10 +268,10 @@ namespace SHADE
|
|||
return;
|
||||
}
|
||||
|
||||
auto PARENT_ITER = entityNodeMap.find(parent);
|
||||
auto PARENT_ITER = entityNodeMap.find(newParent);
|
||||
if (PARENT_ITER == entityNodeMap.end())
|
||||
{
|
||||
SHLOG_ERROR("Entity {} cannot be found in the scene! Unable to parent to Entity {}", parent, entityID)
|
||||
SHLOG_ERROR("Entity {} cannot be found in the scene! Unable to parent to Entity {}", newParent, entityID)
|
||||
return;
|
||||
}
|
||||
////////////////////////////////////////
|
||||
|
@ -419,7 +284,7 @@ namespace SHADE
|
|||
};
|
||||
|
||||
SHSceneNode* currentNode = NODE_ITER->second;
|
||||
currentNode->SetParent(PARENT_ITER->second);
|
||||
ChangeParent(currentNode, PARENT_ITER->second);
|
||||
|
||||
SHEventManager::BroadcastEvent<SHSceneGraphChangeParentEvent>(EVENT_DATA, SH_SCENEGRAPH_CHANGE_PARENT_EVENT);
|
||||
}
|
||||
|
@ -428,84 +293,6 @@ namespace SHADE
|
|||
/* Public Function Member Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
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;
|
||||
}
|
||||
////////////////////////////////////////
|
||||
|
||||
auto childIter = std::find_if(children.begin(), children.end(), [&](SHSceneNode* node)
|
||||
{
|
||||
return node->GetEntityID() == childID;
|
||||
});
|
||||
|
||||
if (childIter == children.end())
|
||||
{
|
||||
SHLOG_WARNING("Unable to remove Entity {} from Entity {} since it is not it's child!", childID, entityID)
|
||||
return false;
|
||||
}
|
||||
|
||||
(*childIter)->parent = nullptr;
|
||||
childIter = children.erase(childIter);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SHSceneNode::RemoveChild(SHSceneNode* childToRemove) noexcept
|
||||
{
|
||||
////////////////////////////////////////
|
||||
// Error Handling
|
||||
if (childToRemove == nullptr)
|
||||
{
|
||||
SHLOG_WARNING("Attempting to remove non-existent child from Entity {}", entityID)
|
||||
return false;
|
||||
}
|
||||
////////////////////////////////////////
|
||||
|
||||
auto childIter = std::find(children.begin(), children.end(), childToRemove);
|
||||
if (childIter == children.end())
|
||||
{
|
||||
SHLOG_WARNING("Unable to remove Entity {} from Entity {} since it is not it's child!", childToRemove->entityID, entityID)
|
||||
return false;
|
||||
}
|
||||
|
||||
childIter = children.erase(childIter);
|
||||
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)
|
||||
{
|
||||
////////////////////////////////////////
|
||||
|
@ -528,13 +315,12 @@ namespace SHADE
|
|||
if (parent == nullptr)
|
||||
{
|
||||
// Specific handling for root to avoid a warning when removing a non-existent child
|
||||
parent = root;
|
||||
newNode->parent = root;
|
||||
root->children.emplace_back(newNode);
|
||||
}
|
||||
else
|
||||
{
|
||||
newNode->SetParent(parent);
|
||||
ChangeParent(newNode, parent);
|
||||
}
|
||||
|
||||
return newNode;
|
||||
|
@ -542,6 +328,8 @@ namespace SHADE
|
|||
|
||||
bool SHSceneGraph::RemoveNode(EntityID entityID) noexcept
|
||||
{
|
||||
////////////////////////////////////////
|
||||
// Error Handling
|
||||
if (!SHEntityManager::IsValidEID(entityID))
|
||||
{
|
||||
SHLOG_ERROR("Entity {} is invalid!", entityID)
|
||||
|
@ -554,12 +342,12 @@ namespace SHADE
|
|||
SHLOG_ERROR("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);
|
||||
if (currentNode->parent != nullptr)
|
||||
RemoveChild(currentNode->parent, currentNode);
|
||||
|
||||
ReleaseNode(currentNode);
|
||||
return true;
|
||||
|
@ -568,9 +356,8 @@ namespace SHADE
|
|||
bool SHSceneGraph::RemoveNode(SHSceneNode* nodeToRemove) noexcept
|
||||
{
|
||||
// Remove reference of current node from parent
|
||||
SHSceneNode* parent = nodeToRemove->GetParent();
|
||||
if (parent != nullptr)
|
||||
parent->RemoveChild(nodeToRemove);
|
||||
if (nodeToRemove->parent != nullptr)
|
||||
RemoveChild(nodeToRemove->parent, nodeToRemove);
|
||||
|
||||
ReleaseNode(nodeToRemove);
|
||||
return true;
|
||||
|
@ -582,6 +369,91 @@ namespace SHADE
|
|||
ReleaseNode(node);
|
||||
}
|
||||
|
||||
bool SHSceneGraph::IsChildOf(EntityID entityID, SHSceneNode* targetNode) noexcept
|
||||
{
|
||||
////////////////////////////////////////
|
||||
// Error Handling
|
||||
|
||||
if (!SHEntityManager::IsValidEID(entityID))
|
||||
{
|
||||
SHLOG_ERROR("Entity {} is invalid!", entityID)
|
||||
return false;
|
||||
}
|
||||
|
||||
auto NODE_ITER = entityNodeMap.find(entityID);
|
||||
if (NODE_ITER == entityNodeMap.end())
|
||||
{
|
||||
SHLOG_ERROR("Entity {} cannot be found in the scene! Unable to check child!", entityID)
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
|
||||
// Handle self-checks
|
||||
if (NODE_ITER->second == targetNode)
|
||||
{
|
||||
SHLOG_WARNING("Entity {} cannot be a child of itself!", entityID)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Search for a matching target until the root
|
||||
const SHSceneNode* CURRENT_TARGET = NODE_ITER->second->parent;
|
||||
while (CURRENT_TARGET != root)
|
||||
{
|
||||
if (CURRENT_TARGET == targetNode)
|
||||
return true;
|
||||
|
||||
CURRENT_TARGET = CURRENT_TARGET->parent;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SHSceneGraph::IsChildOf(EntityID entityID, EntityID targetID) noexcept
|
||||
{
|
||||
////////////////////////////////////////
|
||||
// Error Handling
|
||||
|
||||
if (!SHEntityManager::IsValidEID(entityID))
|
||||
{
|
||||
SHLOG_ERROR("Entity {} is invalid!", entityID)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!SHEntityManager::IsValidEID(targetID))
|
||||
{
|
||||
SHLOG_ERROR("Entity {} is invalid!", targetID)
|
||||
return false;
|
||||
}
|
||||
|
||||
auto NODE_ITER = entityNodeMap.find(entityID);
|
||||
if (NODE_ITER == entityNodeMap.end())
|
||||
{
|
||||
SHLOG_ERROR("Entity {} cannot be found in the scene! Unable to check child!", entityID)
|
||||
return false;
|
||||
}
|
||||
|
||||
auto TARGET_ITER = entityNodeMap.find(targetID);
|
||||
if (TARGET_ITER == entityNodeMap.end())
|
||||
{
|
||||
SHLOG_ERROR("Entity {} cannot be found in the scene! Unable to check child!", targetID)
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
|
||||
const SHSceneNode* CURRENT_TARGET = NODE_ITER->second->parent;
|
||||
while (CURRENT_TARGET != root)
|
||||
{
|
||||
if (CURRENT_TARGET == TARGET_ITER->second)
|
||||
return true;
|
||||
|
||||
CURRENT_TARGET = CURRENT_TARGET->parent;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void SHSceneGraph::Traverse (const UnaryFunction& function) const
|
||||
{
|
||||
TraverseAndInvokeFunction(root, function);
|
||||
|
@ -594,11 +466,6 @@ namespace SHADE
|
|||
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;
|
||||
}
|
||||
|
@ -608,19 +475,81 @@ namespace SHADE
|
|||
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);
|
||||
if (node->parent != nullptr)
|
||||
RemoveChild(node->parent, node);
|
||||
|
||||
// Remove child's references to this node. Children end up as floating nodes.
|
||||
for (auto* child : node->GetChildren())
|
||||
{
|
||||
child->SetParent(nullptr);
|
||||
ChangeParent(child, nullptr);
|
||||
}
|
||||
|
||||
entityNodeMap.erase(node->GetEntityID());
|
||||
delete node;
|
||||
}
|
||||
|
||||
void SHSceneGraph::ChangeParent(SHSceneNode* node, SHSceneNode* newParent)
|
||||
{
|
||||
// Handle self assignment
|
||||
if (node->parent != nullptr && newParent != nullptr && node->parent->entityID == newParent->entityID)
|
||||
return;
|
||||
|
||||
// Remove child
|
||||
if (node->parent)
|
||||
RemoveChild(node->parent, node);
|
||||
|
||||
if (newParent == nullptr)
|
||||
{
|
||||
SHLOG_WARNING("Removing Entity {}'s parent", node->entityID)
|
||||
return;
|
||||
}
|
||||
|
||||
node->parent = newParent;
|
||||
// Update parent's children
|
||||
AddChild(newParent, node);
|
||||
}
|
||||
|
||||
void SHSceneGraph::AddChild(SHSceneNode* node, SHSceneNode* newChild)
|
||||
{
|
||||
SHASSERT(node != nullptr, "Attempting to modify a non-existent scene node!")
|
||||
SHASSERT(newChild != nullptr, "Attempting to add a non-existent child to a SceneNode!")
|
||||
|
||||
if (newChild->parent)
|
||||
RemoveChild(newChild->parent, newChild);
|
||||
|
||||
newChild->parent = node;
|
||||
node->children.emplace_back(newChild);
|
||||
|
||||
const SHSceneGraphAddChildEvent EVENT_DATA
|
||||
{
|
||||
.parent = node
|
||||
, .childAdded = newChild
|
||||
};
|
||||
|
||||
SHEventManager::BroadcastEvent<SHSceneGraphAddChildEvent>(EVENT_DATA, SH_SCENEGRAPH_ADD_CHILD_EVENT);
|
||||
}
|
||||
|
||||
void SHSceneGraph::RemoveChild(SHSceneNode* node, SHSceneNode* childToRemove)
|
||||
{
|
||||
SHASSERT(node != nullptr, "Attempting to modify a non-existent scene node!")
|
||||
SHASSERT(childToRemove != nullptr, "Attempting to remove a non-existent child from a SceneNode!")
|
||||
|
||||
auto childIter = std::find(node->children.begin(), node->children.end(), childToRemove);
|
||||
if (childIter == node->children.end())
|
||||
return;
|
||||
|
||||
childIter = node->children.erase(childIter);
|
||||
childToRemove->parent = nullptr;
|
||||
|
||||
const SHSceneGraphRemoveChildEvent EVENT_DATA
|
||||
{
|
||||
.parent = node
|
||||
, .childRemoved = childToRemove
|
||||
};
|
||||
|
||||
SHEventManager::BroadcastEvent<SHSceneGraphRemoveChildEvent>(EVENT_DATA, SH_SCENEGRAPH_REMOVE_CHILD_EVENT);
|
||||
}
|
||||
|
||||
void SHSceneGraph::TraverseAndInvokeFunction(const SHSceneNode* node, const UnaryFunction& function)
|
||||
{
|
||||
for (auto* child : node->children)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/****************************************************************************************
|
||||
* \file SHSceneGraph.h
|
||||
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
||||
* \brief Interface for a Scene Graph & Scene Nodes.
|
||||
* \brief Interface for a Scene Graph.
|
||||
*
|
||||
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||
* disclosure of this file or its contents without the prior written consent
|
||||
|
@ -15,81 +15,15 @@
|
|||
// Project Headers
|
||||
#include "ECS_Base/Entity/SHEntity.h"
|
||||
#include "SH_API.h"
|
||||
#include "SHSceneNode.h"
|
||||
#include "SHSceneGraphEvents.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Forward Declarations */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
class SHSceneGraph;
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Type Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
class SH_API SHSceneNode
|
||||
{
|
||||
private:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Friends */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
friend class SHSceneGraph;
|
||||
|
||||
public:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* 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]] bool IsActive () const noexcept;
|
||||
[[nodiscard]] EntityID GetEntityID () const noexcept;
|
||||
[[nodiscard]] SHSceneNode* GetParent () const noexcept;
|
||||
[[nodiscard]] const std::vector<SHSceneNode*>& GetChildren () const noexcept;
|
||||
|
||||
[[nodiscard]] SHSceneNode* GetChild (EntityID childID) const noexcept;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Setter Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
void SetParent (SHSceneNode* parentNode) noexcept;
|
||||
void SetActive (bool newActiveState) noexcept;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Function Members */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
void AddChild (SHSceneNode* newChild) noexcept;
|
||||
|
||||
bool RemoveChild (EntityID childID) noexcept;
|
||||
bool RemoveChild (SHSceneNode* childToRemove) noexcept;
|
||||
|
||||
void RemoveAllChildren () noexcept;
|
||||
|
||||
private:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Data Members */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
bool active;
|
||||
EntityID entityID;
|
||||
SHSceneNode* parent;
|
||||
std::vector<SHSceneNode*> children;
|
||||
};
|
||||
|
||||
class SH_API SHSceneGraph
|
||||
{
|
||||
public:
|
||||
|
@ -130,19 +64,22 @@ 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* newParent) noexcept;
|
||||
void SetParent (EntityID entityID, EntityID newParent) noexcept;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Function Members */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
SHSceneNode* AddNode (EntityID entityID, SHSceneNode* parent = nullptr);
|
||||
bool RemoveNode (EntityID entityID) noexcept;
|
||||
bool RemoveNode (SHSceneNode* nodeToRemove) noexcept;
|
||||
void Reset () noexcept;
|
||||
bool RemoveNode (EntityID entityID) noexcept;
|
||||
bool RemoveNode (SHSceneNode* nodeToRemove) noexcept;
|
||||
void Reset () noexcept;
|
||||
|
||||
void Traverse (const UnaryFunction& function) const;
|
||||
bool IsChildOf (EntityID entityID, SHSceneNode* targetNode) noexcept;
|
||||
bool IsChildOf (EntityID entityID, EntityID targetID) noexcept;
|
||||
|
||||
void Traverse (const UnaryFunction& function) const;
|
||||
|
||||
private:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
@ -156,20 +93,14 @@ namespace SHADE
|
|||
/* Function Members */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
SHSceneNode* AllocateNode (EntityID entityID);
|
||||
void ReleaseNode (SHSceneNode* node) noexcept;
|
||||
static void TraverseAndInvokeFunction (const SHSceneNode* node, const UnaryFunction& function);
|
||||
};
|
||||
SHSceneNode* AllocateNode (EntityID entityID);
|
||||
void ReleaseNode (SHSceneNode* node) noexcept;
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Event Data Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
void ChangeParent (SHSceneNode* node, SHSceneNode* newParent);
|
||||
void AddChild (SHSceneNode* node, SHSceneNode* newChild);
|
||||
void RemoveChild (SHSceneNode* node, SHSceneNode* childToRemove);
|
||||
|
||||
struct SHSceneGraphChangeParentEvent
|
||||
{
|
||||
SHSceneNode* node;
|
||||
SHSceneNode* oldParent;
|
||||
SHSceneNode* newParent;
|
||||
static void TraverseAndInvokeFunction (const SHSceneNode* node, const UnaryFunction& function);
|
||||
};
|
||||
|
||||
} // namespace SHADE
|
|
@ -0,0 +1,41 @@
|
|||
/****************************************************************************************
|
||||
* \file SHSceneGraphEvents.h
|
||||
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
||||
* \brief Interface for Scene Graph Events.
|
||||
*
|
||||
* \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
|
||||
|
||||
// Project Headers
|
||||
#include "SHSceneNode.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Event Data Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
struct SHSceneGraphChangeParentEvent
|
||||
{
|
||||
SHSceneNode* node;
|
||||
SHSceneNode* oldParent;
|
||||
SHSceneNode* newParent;
|
||||
};
|
||||
|
||||
struct SHSceneGraphAddChildEvent
|
||||
{
|
||||
SHSceneNode* parent;
|
||||
SHSceneNode* childAdded;
|
||||
};
|
||||
|
||||
struct SHSceneGraphRemoveChildEvent
|
||||
{
|
||||
SHSceneNode* parent;
|
||||
SHSceneNode* childRemoved;
|
||||
};
|
||||
|
||||
} // namespace SHADE
|
|
@ -0,0 +1,143 @@
|
|||
/****************************************************************************************
|
||||
* \file SHSceneNode.c[[
|
||||
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
||||
* \brief Implementation for a Scene Node.
|
||||
*
|
||||
* \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 "SHSceneNode.h"
|
||||
|
||||
// Project Headers
|
||||
#include "ECS_Base/Managers/SHEntityManager.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Constructors & Destructor Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
SHSceneNode::SHSceneNode(EntityID eid, SHSceneNode* parent) noexcept
|
||||
: active { true }
|
||||
, entityID { eid }
|
||||
, parent { parent }
|
||||
{}
|
||||
|
||||
|
||||
SHSceneNode::SHSceneNode(const SHSceneNode& rhs) noexcept
|
||||
: active { rhs.active }
|
||||
, entityID { rhs.entityID }
|
||||
, parent { rhs.parent }
|
||||
{
|
||||
std::ranges::copy(rhs.children.begin(), rhs.children.end(), std::back_inserter(children));
|
||||
}
|
||||
|
||||
SHSceneNode::SHSceneNode(SHSceneNode&& rhs) noexcept
|
||||
: active { rhs.active }
|
||||
, 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;
|
||||
|
||||
active = rhs.active;
|
||||
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
|
||||
{
|
||||
active = rhs.active;
|
||||
entityID = rhs.entityID;
|
||||
parent = rhs.parent;
|
||||
|
||||
children.clear();
|
||||
std::ranges::copy(rhs.children.begin(), rhs.children.end(), std::back_inserter(children));
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Getter Function Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
bool SHSceneNode::IsActive() const noexcept
|
||||
{
|
||||
return active;
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
////////////////////////////////////////
|
||||
// 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;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Setter Function Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
void SHSceneNode::SetActive(bool newActiveState) noexcept
|
||||
{
|
||||
active = newActiveState;
|
||||
|
||||
for (auto* child : children)
|
||||
{
|
||||
SetActive(newActiveState);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace SHADE
|
|
@ -0,0 +1,82 @@
|
|||
/****************************************************************************************
|
||||
* \file SHSceneNode.h
|
||||
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
||||
* \brief Interface for a Scene Node.
|
||||
*
|
||||
* \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 "ECS_Base/Entity/SHEntity.h"
|
||||
#include "SH_API.h"
|
||||
#include "SHSceneGraph.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Forward Declarations */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
class SHSceneGraph;
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Type Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
class SH_API SHSceneNode
|
||||
{
|
||||
private:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Friends */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
friend class SHSceneGraph;
|
||||
|
||||
public:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* 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]] bool IsActive () const noexcept;
|
||||
[[nodiscard]] EntityID GetEntityID () const noexcept;
|
||||
[[nodiscard]] SHSceneNode* GetParent () const noexcept;
|
||||
[[nodiscard]] const std::vector<SHSceneNode*>& GetChildren () const noexcept;
|
||||
|
||||
[[nodiscard]] SHSceneNode* GetChild (EntityID childID) const noexcept;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Setter Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
void SetActive (bool newActiveState) noexcept;
|
||||
|
||||
private:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Data Members */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
bool active;
|
||||
EntityID entityID;
|
||||
SHSceneNode* parent;
|
||||
std::vector<SHSceneNode*> children;
|
||||
};
|
||||
} // namespace SHADE
|
||||
|
|
@ -105,7 +105,7 @@ namespace SHADE
|
|||
{
|
||||
if (!valid)
|
||||
throw gcnew System::NullReferenceException();
|
||||
const auto& SCENE_GRAPH = SHSceneManager::GetCurrentSceneGraph();
|
||||
auto& SCENE_GRAPH = SHSceneManager::GetCurrentSceneGraph();
|
||||
|
||||
if (newParent == nullptr)
|
||||
SCENE_GRAPH.SetParent(entity, nullptr);
|
||||
|
|
Loading…
Reference in New Issue