Merge remote-tracking branch 'origin/main' into SP3-1-Rendering

This commit is contained in:
Brandon Mak 2022-09-21 15:41:36 +08:00
commit 80dc8d0a71
20 changed files with 373 additions and 234 deletions

View File

@ -47,32 +47,57 @@ namespace SHADE
void SHEntity::SetParent(SHEntity* newParent) noexcept void SHEntity::SetParent(SHEntity* newParent) noexcept
{ {
(void)newParent; SHSceneManager::GetCurrentSceneGraph().SetParent(GetEID(), newParent->GetEID());
//TODO
} }
void SHEntity::SetParent(EntityID newParentID) noexcept void SHEntity::SetParent(EntityID newParentID) noexcept
{ {
(void)newParentID; SHSceneManager::GetCurrentSceneGraph().SetParent(GetEID(), newParentID);
//TODO
} }
SHEntity* SHEntity::GetParent()const noexcept SHEntity* SHEntity::GetParent()const noexcept
{ {
//TODO SHSceneNode* parent = SHSceneManager::GetCurrentSceneGraph().GetParent(GetEID());
if (parent != nullptr)
return SHEntityManager::GetEntityByID(parent->GetEntityID());
else
return nullptr; return nullptr;
} }
EntityID SHEntity::GetParentEID()const noexcept
{
SHSceneNode* parent = SHSceneManager::GetCurrentSceneGraph().GetParent(GetEID());
if (parent != nullptr)
return parent->GetEntityID();
else
return MAX_EID;
}
std::vector<SHEntity*>const& SHEntity::GetChildren()const noexcept std::vector<SHEntity*>const& SHEntity::GetChildren()const noexcept
{ {
//TODO std::vector<SHEntity*> childrenEntity;
return std::vector<SHEntity*>{};
auto& childrenNodes = SHSceneManager::GetCurrentSceneGraph().GetChildren(GetEID());
for (auto& childNode : childrenNodes)
{
childrenEntity.push_back(SHEntityManager::GetEntityByID(childNode->GetEntityID()));
}
return childrenEntity;
} }
std::vector<EntityID>const& SHEntity::GetChildrenID()const noexcept std::vector<EntityID>const& SHEntity::GetChildrenID()const noexcept
{ {
return std::vector<EntityID>{}; std::vector<EntityID> childrenEntity;
auto& childrenNodes = SHSceneManager::GetCurrentSceneGraph().GetChildren(GetEID());
for (auto& childNode : childrenNodes)
{
childrenEntity.push_back(childNode->GetEntityID());
}
return childrenEntity;
} }
} }

View File

@ -127,6 +127,13 @@ namespace SHADE
***************************************************************************/ ***************************************************************************/
SHEntity* GetParent()const noexcept; SHEntity* GetParent()const noexcept;
/********************************************************************
* \brief
* Get the entity ID of the parent.
* \return
* return the entity ID of the parent
********************************************************************/
EntityID GetParentEID() const noexcept;
/************************************************************************** /**************************************************************************
* \brief * \brief

View File

@ -0,0 +1,13 @@
#pragma once
#include "ECS_Base/Entity/SHEntity.h"
namespace SHADE
{
struct SHEntityCreationEvent
{
EntityID eid;
std::vector<ComponentTypeID> componentTypeIDs;
EntityID parentEID;
};
}

View File

@ -0,0 +1,11 @@
#pragma once
#include "ECS_Base/Entity/SHEntity.h"
namespace SHADE
{
struct SHEntityDestroyedEvent
{
EntityID eid;
};
}

View File

@ -103,6 +103,18 @@ namespace SHADE
SHComponentManager::AddComponent(eID, id); SHComponentManager::AddComponent(eID, id);
} }
//Link up with scene graph.
if (parentEID != MAX_EID)
SHSceneManager::GetCurrentSceneGraph().AddNode(eID, SHSceneManager::GetCurrentSceneGraph().GetNode(parentEID));
else
SHSceneManager::GetCurrentSceneGraph().AddNode(eID);
//set up event stuff
SHEntityCreationEvent event{ eID,componentTypeIDs, parentEID };
SHEventManager::BroadcastEvent<SHEntityCreationEvent>(event, SH_ENTITY_CREATION_EVENT);
//(SHComponentManager::AddComponent<ComponentTypes>(eID), ...); //(SHComponentManager::AddComponent<ComponentTypes>(eID), ...);
//if (entityHandle.IsValid(parentEID) == false) //if (entityHandle.IsValid(parentEID) == false)
@ -134,6 +146,14 @@ namespace SHADE
//Call all the children to Destroy themselves first before the parent is destroyed. //Call all the children to Destroy themselves first before the parent is destroyed.
if (entityVec[eIndex]) if (entityVec[eIndex])
{ {
auto& children = SHSceneManager::GetCurrentSceneGraph().GetChildren(eID);
for (auto& child : children)
{
DestroyEntity(child->GetEntityID());
}
SHSceneManager::GetCurrentSceneGraph().RemoveNode(eID);
//auto& children = entityVec[eIndex]->GetChildrenID(); //auto& children = entityVec[eIndex]->GetChildrenID();
//while(!children.empty()) //while(!children.empty())
//{ //{
@ -153,6 +173,14 @@ namespace SHADE
entityHandle.RemoveHandle(eID); entityHandle.RemoveHandle(eID);
entityVec[eIndex].reset(nullptr); entityVec[eIndex].reset(nullptr);
SHEntityDestroyedEvent event{eID};
SHEventManager::BroadcastEvent<SHEntityDestroyedEvent>(event, SH_ENTITY_DESTROYED_EVENT);
} }
} }

View File

@ -20,6 +20,10 @@
#include "../Components/SHComponent.h" #include "../Components/SHComponent.h"
#include "../General/SHHandleGenerator.h" #include "../General/SHHandleGenerator.h"
#include "../SHECSMacros.h" #include "../SHECSMacros.h"
#include "ECS_Base/Events/SHEntityCreationEvent.h"
#include "ECS_Base/Events/SHEntityDestroyedEvent.h"
#include "Scene/SHSceneManager.h"
#include "Events/SHEventManager.hpp"
#include "SH_API.h" #include "SH_API.h"
namespace SHADE namespace SHADE
@ -125,6 +129,23 @@ namespace SHADE
entityVec[eIndex]->name = name; entityVec[eIndex]->name = name;
(SHComponentManager::AddComponent<ComponentTypes>(eID), ...); (SHComponentManager::AddComponent<ComponentTypes>(eID), ...);
//set up event stuff
std::vector<ComponentTypeID> typeIDVec;
(typeIDVec.push_back(ComponentFamily::GetID<ComponentTypes>()), ...);
//Link up with scene graph.
if (parentEID != MAX_EID)
SHSceneManager::GetCurrentSceneGraph().AddNode(eID, SHSceneManager::GetCurrentSceneGraph().GetNode(parentEID));
else
SHSceneManager::GetCurrentSceneGraph().AddNode(eID);
SHEntityCreationEvent event{ eID,typeIDVec,parentEID };
SHEventManager::BroadcastEvent<SHEntityCreationEvent>(event, SH_ENTITY_CREATION_EVENT);
/*if (entityHandle.IsValid(parentEID) == false) /*if (entityHandle.IsValid(parentEID) == false)
{ {
entityVec[eIndex]->sceneNode.ConnectToRoot(); entityVec[eIndex]->sceneNode.ConnectToRoot();
@ -135,8 +156,6 @@ namespace SHADE
}*/ }*/
//Link up with scene graph.
return eID; return eID;
} }

View File

@ -41,7 +41,7 @@ namespace SHADE
std::string const GetName() const noexcept; std::string const GetName() const noexcept;
SHRoutineStats const& GetStats()const noexcept; SHRoutineStats const& GetStats()const noexcept;
virtual void Execute(double dt) noexcept {}; virtual void Execute(double dt) noexcept { (void)dt; };
}; };

View File

@ -30,8 +30,8 @@ namespace SHADE
SHLOG_INFO("Test for add and remove component") SHLOG_INFO("Test for add and remove component")
EntityID id1 = SHEntityManager::CreateEntity(); EntityID id1 = SHEntityManager::CreateEntity();
EntityID id2 = SHEntityManager::CreateEntity(); SHEntityManager::CreateEntity();
EntityID id3 = SHEntityManager::CreateEntity(); SHEntityManager::CreateEntity();
SHComponentManager::AddComponent<SHComponent_A>(id1); SHComponentManager::AddComponent<SHComponent_A>(id1);

View File

@ -30,7 +30,7 @@ namespace SHADE
virtual void Execute(double dt) noexcept virtual void Execute(double dt) noexcept
{ {
(void)dt;
std::cout << GetName() << " System Version: " << GetSystem()->GetSystemVersion() << std::endl; std::cout << GetName() << " System Version: " << GetSystem()->GetSystemVersion() << std::endl;
} }
}; };

View File

@ -16,7 +16,17 @@ namespace SHADE
struct SHEvent struct SHEvent
{ {
SHEventIdentifier type; SHEventIdentifier type;
SHEventDataPtr dataPtr;
SHEventHandle handle; SHEventHandle handle;
}; };
template<typename T>
struct SHEventSpec : SHEvent
{
SHEventSpec(SHEventIdentifier t, SHEventHandle e, std::shared_ptr<const T> dp)
:SHEvent{ t, e }, data{ dp } {}
std::shared_ptr<const T> data;
};
using SHEventPtr = std::shared_ptr<const SHEvent>;
} }

View File

@ -3,7 +3,8 @@
typedef uint32_t SHEventIdentifier; typedef uint32_t SHEventIdentifier;
typedef uint32_t SHEventHandle; typedef uint32_t SHEventHandle;
typedef void* SHEventDataPtr;
//Add your event identifiers here: //Add your event identifiers here:
constexpr SHEventIdentifier SH_EXAMPLE_EVENT{0}; constexpr SHEventIdentifier SH_EXAMPLE_EVENT{0};
constexpr SHEventIdentifier SH_ENTITY_DESTROYED_EVENT{ 1 };
constexpr SHEventIdentifier SH_ENTITY_CREATION_EVENT{ 2 };

View File

@ -1,107 +0,0 @@
/******************************************************************************
* \file SHEventManager.cpp
* \author Loh Xiao Qi
* \brief Function Implmentations for SHEventManager
*
* \copyright Copyright (c) 2021 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"
#include "SHEventManager.h"
namespace SHADE
{
std::unordered_map<SHEventIdentifier, ResponseVec> SHEventManager::packageReceiverRegistry;
std::unordered_map<SHEventHandle, SHEventDataPtr> SHEventManager::dataEventMap;
SHEventHandle SHEventManager::handleCounter{ 0 };
/****************************************************************************
* \param ListenerConstPtr - Const pointer to listener that sent event.
* \param EventType - Templated type for every type of event
* \brief Receives event from the listeners.
****************************************************************************/
void SHEventManager::CatchEvent(SHEvent event)
{
// Do something with the event
Broadcast(event);
}
/****************************************************************************
* \param ResponseFunction - function pointer from receiver to be passed
* into event manager to be called when events are broadcasted.
* \param SHEventIdentifier - package type that corresponding subscriber is
* subscribing to.
* \brief Links a function pointer from a subscriber to a particular
* package type
****************************************************************************/
void SHEventManager::SubscribeTo(SHEventIdentifier pkgType, ReceiverPtr receiver)
{
RegisterReceiverToType(pkgType, receiver);
}
template<typename T>
T* SHEventManager::BroadcastEvent(T data, SHEventIdentifier eventType)
{
SHEventDataPtr ptr = new std::byte[sizeof(data)];
std::memcpy(ptr, &data, sizeof(data));
CatchEvent(
{
eventType,
ptr,
handleCounter++
}
);
return reinterpret_cast<T*>(ptr);
}
/****************************************************************************
* \param ReceiverPtr - Pointer to receiver
* \param ListenerConstPtr - Const pointer to listener that receiver is
* subscribing to.
* \brief Registers receiver as a subscriber to listener in the registry.
****************************************************************************/
void SHEventManager::RegisterReceiverToType(
SHEventIdentifier pkgType, ReceiverPtr receiver)
{
if (packageReceiverRegistry.contains(pkgType))
{
packageReceiverRegistry[pkgType].emplace_back(receiver);
}
else
{
packageReceiverRegistry.emplace(pkgType, std::vector{ receiver });
}
}
/****************************************************************************
* \param ListenerConstPtr - Const pointer to listener that sent event.
* \param EventType - Event data
* \brief Broadcast event to all receivers that are subscribed to this
* listener.
****************************************************************************/
void SHEventManager::Broadcast(SHEvent const& event)
{
ResponseVec& receivers{ packageReceiverRegistry[event.type] };
for (auto& receiver : receivers)
{
receiver->Receive(event);
}
//auto& funcs{ ackageReceiverRegistry[event.GetType()] };
//for (auto func : funcs)
//{
// func(event.GetData());
//}
}
}

View File

@ -1,5 +1,5 @@
/****************************************************************************** /******************************************************************************
* \file SHEventManager.h * \file SHEventManager.hpp
* \author Loh Xiao Qi * \author Loh Xiao Qi
* \brief Class declaration for event manager. * \brief Class declaration for event manager.
* *
@ -9,10 +9,9 @@
******************************************************************************/ ******************************************************************************/
#pragma once #pragma once
#include "SHpch.h"
#include "SHEvent.h" #include "SHEvent.h"
#include "SHEventReceiver.h" #include "SHEventReceiver.h"
#include <unordered_map>
#include <functional>
/****************************************************************************** /******************************************************************************
INSTRUCTIONS FOR USE: INSTRUCTIONS FOR USE:
@ -24,11 +23,16 @@
3. When ready to send the event, call 3. When ready to send the event, call
SHEventManager::BroadcastEvent<ExampleClass>(exampleClass, EVENT_IDENTIFIER); SHEventManager::BroadcastEvent<ExampleClass>(exampleClass, EVENT_IDENTIFIER);
Headers required: SHEventManager.h NOTE: If your custom struct to contain data requires a deep copy, please
overload the assignment operator accordingly. It is fine to send
a single object of a basic type such as int/float.
Headers required: SHEventManager.hpp
On Receiver side: On Receiver side:
1. Create a function with the signature: 1. Create a function with the signature:
SHEventHandle FunctionName(SHEvent); SHEventHandle FunctionName(SHEventPtr);
2. In the init function of the class, copy the below in and replace the 2. In the init function of the class, copy the below in and replace the
necessary: necessary:
@ -42,25 +46,71 @@
3. Note: The EventIdentifier should match all that is defined in 3. Note: The EventIdentifier should match all that is defined in
SHEventDefines.h so check there. When the receiver catches the event, it SHEventDefines.h so check there. When the receiver catches the event, it
needs to know the struct that the broadcaster is using to cast the void* needs to know the struct that the broadcaster is using to cast the event
properly. ptr as such:
Headers required: SHEventManager.h, SHEventReceiver.h reinterpret_cast<std::shared_ptr<SHEventSpec<CustomClass>>>(event)
4. Inside the new ptr should be a shared pointer of const CustomClass type.
Headers required: SHEventManager.hpp, SHEventReceiver.h
If you have any questions/suggestions for improvement lmk. If you have any questions/suggestions for improvement lmk.
******************************************************************************/ ******************************************************************************/
namespace SHADE namespace SHADE
{ {
using ResponseFunction = std::function<SHEventHandle(SHEvent)>; //using ResponseFunction = std::function<SHEventHandle(SHEventPtr)>;
using ReceiverPtr = std::shared_ptr<SHEventReceiver>; using ReceiverPtr = std::shared_ptr<SHEventReceiver>;
using ResponseVec = std::vector<ReceiverPtr>; using ResponseVec = std::vector<ReceiverPtr>;
using StaticResponseVec = std::vector<ResponseFunction>;
using EventManagerListener = std::function<void(SHEvent)>; using EventManagerListener = std::function<void(SHEvent)>;
class SHEventManager class SHEventManager
{ {
private:
// Registry for broadcasters and subscribers
inline static std::unordered_map<SHEventIdentifier, ResponseVec> packageReceiverRegistry;
inline static SHEventHandle handleCounter {0};
/****************************************************************************
* \param ListenerConstPtr - Const pointer to listener that sent event.
* \param EventType - Event data
* \brief Broadcast event to all receivers that are subscribed to this
* listener.
****************************************************************************/
static void Broadcast(SHEventPtr event)
{
ResponseVec& receivers{ packageReceiverRegistry[event->type] };
for (auto& receiver : receivers)
{
receiver->Receive(event);
}
}
/****************************************************************************
* \param ReceiverPtr - Pointer to receiver
* \param ListenerConstPtr - Const pointer to listener that receiver is
* subscribing to.
* \brief Registers receiver as a subscriber to listener in the registry.
****************************************************************************/
static void RegisterReceiverToType(SHEventIdentifier pkgType, ReceiverPtr receiver)
{
if (packageReceiverRegistry.find(pkgType) == packageReceiverRegistry.end())
{
packageReceiverRegistry.emplace(pkgType, std::vector{ receiver });
}
else
{
packageReceiverRegistry[pkgType].emplace_back(receiver);
}
}
public: public:
/**************************************************************************** /****************************************************************************
@ -69,7 +119,13 @@ namespace SHADE
* \brief Receives event from the listeners. * \brief Receives event from the listeners.
****************************************************************************/ ****************************************************************************/
static void CatchEvent(SHEvent); static void CatchEvent(SHEventPtr event)
{
// Do something with the event
Broadcast(event);
}
/**************************************************************************** /****************************************************************************
* \param ResponseFunction - function pointer from receiver to be passed * \param ResponseFunction - function pointer from receiver to be passed
@ -80,37 +136,20 @@ namespace SHADE
* \brief Links a function pointer from a subscriber to a particular * \brief Links a function pointer from a subscriber to a particular
* package type * package type
****************************************************************************/ ****************************************************************************/
static void SubscribeTo(SHEventIdentifier, ReceiverPtr); static void SubscribeTo(SHEventIdentifier pkgType, ReceiverPtr receiver)
{
RegisterReceiverToType(pkgType, receiver);
}
template<typename T> template<typename T>
static T* BroadcastEvent(T data, SHEventIdentifier eventType); static void BroadcastEvent(T data, SHEventIdentifier eventType)
{
private: std::shared_ptr<const T> ptr = std::make_shared<T>(data);
// Registry for broadcasters and subscribers
static std::unordered_map<SHEventIdentifier, ResponseVec> packageReceiverRegistry;
static std::unordered_map<SHEventHandle, SHEventDataPtr> dataEventMap;
static SHEventHandle handleCounter;
/****************************************************************************
* \param ListenerConstPtr - Const pointer to listener that sent event.
* \param EventType - Event data
* \brief Broadcast event to all receivers that are subscribed to this
* listener.
****************************************************************************/
static void Broadcast(SHEvent const&);
/****************************************************************************
* \param ReceiverPtr - Pointer to receiver
* \param ListenerConstPtr - Const pointer to listener that receiver is
* subscribing to.
* \brief Registers receiver as a subscriber to listener in the registry.
****************************************************************************/
static void RegisterReceiverToType(SHEventIdentifier, ReceiverPtr);
CatchEvent(
std::make_shared<SHEventSpec<T>>(eventType, handleCounter++, ptr)
);
}
}; };
} }

View File

@ -8,7 +8,7 @@ namespace SHADE
{ {
private: private:
public: public:
virtual void Receive(SHEvent) = 0; virtual void Receive(SHEventPtr) = 0;
}; };
template<typename T> template<typename T>
@ -16,16 +16,16 @@ namespace SHADE
{ {
private: private:
T* object; T* object;
SHEventHandle(T::*callback)(SHEvent); SHEventHandle(T::*callback)(SHEventPtr);
public: public:
SHEventReceiverSpec(T* obj, void(T::* cb)(SHEventDataPtr)) SHEventReceiverSpec(T* obj, void(T::* cb)(SHEventPtr))
:SHEventReceiver(), object{ obj }, callback{ cb } :SHEventReceiver(), object{ obj }, callback{ cb }
{ {
} }
void Receive(SHEvent evt) override void Receive(SHEventPtr evt) override
{ {
(object->*callback)(evt); (object->*callback)(evt);
} }

View File

@ -12,6 +12,7 @@
#define SH_SCENE_H #define SH_SCENE_H
#include <string> #include <string>
#include "SHSceneGraph.h"
namespace SHADE namespace SHADE
{ {
@ -19,15 +20,19 @@ namespace SHADE
class SHScene class SHScene
{ {
private: private:
SHSceneGraph sceneGraph;
protected: protected:
SHScene() = default; SHScene() = default;
public: public:
virtual ~SHScene() = default;
std::string sceneName; std::string sceneName;
virtual ~SHScene() = default; SHSceneGraph& GetSceneGraph() noexcept { return sceneGraph; }
virtual void Load() = 0; virtual void Load() = 0;
virtual void Init() = 0; virtual void Init() = 0;

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,10 +104,25 @@ 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) SHLOG_ERROR("Child Entity {} is invalid! Unable to get child from Entity {}", childID, entityID)
@ -114,7 +134,7 @@ namespace SHADE
SHLOG_WARNING("Entity {} has no children!", entityID) SHLOG_WARNING("Entity {} has no children!", entityID)
return nullptr; 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();
} }
@ -252,11 +284,17 @@ namespace SHADE
void SHSceneNode::SetParent(SHSceneNode* parentNode) noexcept void SHSceneNode::SetParent(SHSceneNode* parentNode) noexcept
{ {
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;
if (parent)
parent->RemoveChild(this);
parent = parentNode; parent = parentNode;
// Update parent's children // Update parent's children
parent->AddChild(this); parent->AddChild(this);
@ -264,6 +302,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 +316,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)
@ -301,12 +344,13 @@ namespace SHADE
return; return;
} }
auto PARENT_ITER = entityNodeMap.find(entityID); auto PARENT_ITER = entityNodeMap.find(parent);
if (PARENT_ITER == entityNodeMap.end()) if (PARENT_ITER == entityNodeMap.end())
{ {
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,50 +362,69 @@ 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; auto childIter = std::find_if(children.begin(), children.end(), [&](SHSceneNode* node)
const auto ENTITY_MATCH = [&](SHSceneNode* node)
{ {
if (node->GetEntityID() == childID) return node->GetEntityID() == childID;
});
if (childIter == children.end())
{ {
removedChild = node; SHLOG_WARNING("Unable to remove Entity {} from Entity {} since it is not it's child!", childID, entityID)
return true; return false;
} }
return false; (*childIter)->parent = nullptr;
}; childIter = children.erase(childIter);
children.end() = std::remove_if(children.begin(), children.end(), ENTITY_MATCH); return true;
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); 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; childToRemove->parent = nullptr;
return true; return true;
@ -375,14 +438,16 @@ namespace SHADE
children.clear(); children.clear();
} }
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())
{ {
@ -391,6 +456,10 @@ namespace SHADE
} }
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

@ -14,6 +14,7 @@
// Project Headers // Project Headers
#include "ECS_Base/Entity/SHEntity.h" #include "ECS_Base/Entity/SHEntity.h"
#include "SH_API.h"
namespace SHADE namespace SHADE
{ {
@ -21,7 +22,7 @@ namespace SHADE
/* Type Definitions */ /* Type Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
class SHSceneNode class SH_API SHSceneNode
{ {
public: public:
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
@ -46,9 +47,9 @@ namespace SHADE
/* 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;
@ -75,7 +76,7 @@ namespace SHADE
std::vector<SHSceneNode*> children; std::vector<SHSceneNode*> children;
}; };
class SHSceneGraph class SH_API SHSceneGraph
{ {
public: public:
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
@ -100,7 +101,7 @@ namespace SHADE
/* 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;

View File

@ -37,6 +37,12 @@ namespace SHADE
std::function<void()> SHSceneManager::newScene = []() {}; std::function<void()> SHSceneManager::newScene = []() {};
//void (*SHSceneManager::prevSceneCreate)() = []() {}; //void (*SHSceneManager::prevSceneCreate)() = []() {};
SHSceneGraph& SHSceneManager::GetCurrentSceneGraph() noexcept
{
return currentScene->GetSceneGraph();
}
void SHSceneManager::UpdateSceneManager() noexcept void SHSceneManager::UpdateSceneManager() noexcept
{ {
if (sceneChanged == false) if (sceneChanged == false)

View File

@ -20,7 +20,7 @@
namespace SHADE namespace SHADE
{ {
class SHSceneManager class SH_API SHSceneManager
{ {
private: private:
//boolean to check if the scene has been changed //boolean to check if the scene has been changed
@ -57,6 +57,15 @@ namespace SHADE
//boolean to check if the programme has been terminated. //boolean to check if the programme has been terminated.
static bool quit; static bool quit;
/********************************************************************
* \brief
* Get the scene graph of the current scene.
* \return
* A reference to the scene graph of the current active scene.
********************************************************************/
static SHSceneGraph& GetCurrentSceneGraph() noexcept;
/*!************************************************************************* /*!*************************************************************************
* \brief * \brief
* Initialize scene manager and loads a default scene * Initialize scene manager and loads a default scene

View File

@ -1,2 +1,5 @@
erase /s /q *.vcxproj
erase /s /q *.vcxproj.filters
call Premake\premake5 vs2019 call Premake\premake5 vs2019
PAUSE PAUSE