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)newParent;
//TODO
SHSceneManager::GetCurrentSceneGraph().SetParent(GetEID(), newParent->GetEID());
}
void SHEntity::SetParent(EntityID newParentID) noexcept
{
(void)newParentID;
//TODO
SHSceneManager::GetCurrentSceneGraph().SetParent(GetEID(), newParentID);
}
SHEntity* SHEntity::GetParent()const noexcept
{
//TODO
return nullptr;
SHSceneNode* parent = SHSceneManager::GetCurrentSceneGraph().GetParent(GetEID());
if (parent != nullptr)
return SHEntityManager::GetEntityByID(parent->GetEntityID());
else
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
{
//TODO
return std::vector<SHEntity*>{};
std::vector<SHEntity*> childrenEntity;
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
{
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;
/********************************************************************
* \brief
* Get the entity ID of the parent.
* \return
* return the entity ID of the parent
********************************************************************/
EntityID GetParentEID() const noexcept;
/**************************************************************************
* \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);
}
//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), ...);
//if (entityHandle.IsValid(parentEID) == false)
@ -134,6 +146,14 @@ namespace SHADE
//Call all the children to Destroy themselves first before the parent is destroyed.
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();
//while(!children.empty())
//{
@ -153,6 +173,14 @@ namespace SHADE
entityHandle.RemoveHandle(eID);
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 "../General/SHHandleGenerator.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"
namespace SHADE
@ -125,6 +129,23 @@ namespace SHADE
entityVec[eIndex]->name = name;
(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)
{
entityVec[eIndex]->sceneNode.ConnectToRoot();
@ -135,8 +156,6 @@ namespace SHADE
}*/
//Link up with scene graph.
return eID;
}

View File

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

View File

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

View File

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

View File

@ -16,7 +16,17 @@ namespace SHADE
struct SHEvent
{
SHEventIdentifier type;
SHEventDataPtr dataPtr;
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 SHEventHandle;
typedef void* SHEventDataPtr;
//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
* \brief Class declaration for event manager.
*
@ -9,10 +9,9 @@
******************************************************************************/
#pragma once
#include "SHpch.h"
#include "SHEvent.h"
#include "SHEventReceiver.h"
#include <unordered_map>
#include <functional>
/******************************************************************************
INSTRUCTIONS FOR USE:
@ -24,11 +23,16 @@
3. When ready to send the event, call
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:
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
necessary:
@ -42,25 +46,71 @@
3. Note: The EventIdentifier should match all that is defined in
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*
properly.
needs to know the struct that the broadcaster is using to cast the event
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.
******************************************************************************/
namespace SHADE
{
using ResponseFunction = std::function<SHEventHandle(SHEvent)>;
//using ResponseFunction = std::function<SHEventHandle(SHEventPtr)>;
using ReceiverPtr = std::shared_ptr<SHEventReceiver>;
using ResponseVec = std::vector<ReceiverPtr>;
using StaticResponseVec = std::vector<ResponseFunction>;
using EventManagerListener = std::function<void(SHEvent)>;
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:
/****************************************************************************
@ -69,7 +119,13 @@ namespace SHADE
* \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
@ -80,37 +136,20 @@ namespace SHADE
* \brief Links a function pointer from a subscriber to a particular
* package type
****************************************************************************/
static void SubscribeTo(SHEventIdentifier, ReceiverPtr);
static void SubscribeTo(SHEventIdentifier pkgType, ReceiverPtr receiver)
{
RegisterReceiverToType(pkgType, receiver);
}
template<typename T>
static T* BroadcastEvent(T data, SHEventIdentifier eventType);
private:
// 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);
static void BroadcastEvent(T data, SHEventIdentifier eventType)
{
std::shared_ptr<const T> ptr = std::make_shared<T>(data);
CatchEvent(
std::make_shared<SHEventSpec<T>>(eventType, handleCounter++, ptr)
);
}
};
}

View File

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

View File

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

View File

@ -76,7 +76,10 @@ namespace SHADE
SHSceneGraph::SHSceneGraph() noexcept
: root { nullptr }
{}
{
// The root is set to the maximum entity. It should not be interfaced with.
root = AllocateNode(MAX_EID);
}
SHSceneGraph::~SHSceneGraph() noexcept
{
@ -90,6 +93,8 @@ namespace SHADE
for (auto* node : entityNodeMap | std::views::values)
ReleaseNode(node);
delete root;
#ifdef _DEBUG
SHLOG_INFO("Scene Graph Destroyed Successfully!")
#endif
@ -99,23 +104,38 @@ namespace SHADE
/* Getter Function Definitions */
/*-----------------------------------------------------------------------------------*/
EntityID SHSceneNode::GetEntityID() const noexcept
{
return entityID;
}
SHSceneNode* SHSceneNode::GetParent() const noexcept
{
return parent;
}
const std::vector<SHSceneNode*>& SHSceneNode::GetChildren() const noexcept
{
return children;
}
SHSceneNode* SHSceneNode::GetChild(EntityID childID) const noexcept
{
////////////////////////////////////////
// Error handling
if (!SHEntityManager::IsValidEID(childID))
{
if (!SHEntityManager::IsValidEID(childID))
{
SHLOG_ERROR("Child Entity {} is invalid! Unable to get child from Entity {}", childID, entityID)
return nullptr;
}
if (children.empty())
{
SHLOG_WARNING("Entity {} has no children!", entityID)
return nullptr;
}
SHLOG_ERROR("Child Entity {} is invalid! Unable to get child from Entity {}", childID, entityID)
return nullptr;
}
if (children.empty())
{
SHLOG_WARNING("Entity {} has no children!", entityID)
return nullptr;
}
////////////////////////////////////////
// Find child
const auto ENTITY_MATCH = [&](const SHSceneNode* node) { return node->GetEntityID() == childID; };
@ -129,17 +149,19 @@ namespace SHADE
return *CHILD_ITER;
}
SHSceneNode* SHSceneGraph::GetRoot() const noexcept
const SHSceneNode* SHSceneGraph::GetRoot() const noexcept
{
if (root != nullptr)
return root;
SHLOG_WARNING("Scene has no root object!")
return nullptr;
return nullptr;
}
SHSceneNode* SHSceneGraph::GetNode(EntityID entityID) const noexcept
{
////////////////////////////////////////
// Error handling
if (!SHEntityManager::IsValidEID(entityID))
{
SHLOG_ERROR("Entity {} is invalid! Unable to Get Scene node!", entityID)
@ -152,12 +174,15 @@ namespace SHADE
SHLOG_WARNING("Entity {} cannot be found in the scene! Unable to Get Scene node!", entityID)
return nullptr;
}
////////////////////////////////////////
return NODE_ITER->second;
}
SHSceneNode* SHSceneGraph::GetParent(EntityID entityID) const noexcept
{
////////////////////////////////////////
// Error handling
if (!SHEntityManager::IsValidEID(entityID))
{
SHLOG_ERROR("Entity {} is invalid! Unable to get Parent node!", entityID)
@ -170,13 +195,15 @@ namespace SHADE
SHLOG_WARNING("Entity {} cannot be found in the scene! Unable to get Parent node!", entityID)
return nullptr;
}
////////////////////////////////////////
return NODE_ITER->second->GetParent();
}
SHSceneNode* SHSceneGraph::GetChild(EntityID entityID, SHSceneNode* childNode) const noexcept
{
// Error Handling
////////////////////////////////////////
// Error handling
if (!SHEntityManager::IsValidEID(entityID))
{
SHLOG_ERROR("Entity {} is invalid!", entityID)
@ -203,12 +230,15 @@ namespace SHADE
SHLOG_WARNING("Entity {} is not a child of Entity {}!", childNode->GetEntityID(), entityID)
return nullptr;
}
////////////////////////////////////////
return *CHILD_ITER;
}
SHSceneNode* SHSceneGraph::GetChild(EntityID entityID, EntityID childEntityID) const noexcept
{
////////////////////////////////////////
// Error handling
if (!SHEntityManager::IsValidEID(entityID))
{
SHLOG_ERROR("Entity {} is invalid!", entityID)
@ -221,14 +251,15 @@ namespace SHADE
SHLOG_WARNING("Entity {} cannot be found in the scene!", entityID)
return nullptr;
}
////////////////////////////////////////
return NODE_ITER->second->GetChild(childEntityID);
}
const std::vector<SHSceneNode*>& SHSceneGraph::GetChildren(EntityID entityID) const noexcept
{
// TODO(Diren): Discuss with team best way to handle this
////////////////////////////////////////
// Error handling
if (!SHEntityManager::IsValidEID(entityID))
{
SHLOG_ERROR("Entity {} is invalid!", entityID)
@ -241,6 +272,7 @@ namespace SHADE
SHLOG_WARNING("Entity {} cannot be found in the scene!", entityID)
return root->GetChildren();
}
////////////////////////////////////////
return NODE_ITER->second->GetChildren();
}
@ -252,11 +284,17 @@ namespace SHADE
void SHSceneNode::SetParent(SHSceneNode* parentNode) noexcept
{
if (parentNode == nullptr)
{
SHLOG_WARNING("Removing Entity {}'s parent", entityID)
}
// Handle self assignment
if (parentNode == parent)
return;
if (parent)
parent->RemoveChild(this);
parent = parentNode;
// Update parent's children
parent->AddChild(this);
@ -264,6 +302,8 @@ namespace SHADE
void SHSceneGraph::SetParent(EntityID entityID, SHSceneNode* parent) const noexcept
{
////////////////////////////////////////
// Error Handling
if (!SHEntityManager::IsValidEID(entityID))
{
SHLOG_ERROR("Entity {} is invalid!", entityID)
@ -276,12 +316,15 @@ namespace SHADE
SHLOG_WARNING("Entity {} cannot be found in the scene!", entityID)
return;
}
////////////////////////////////////////
NODE_ITER->second->SetParent(parent);
}
void SHSceneGraph::SetParent(EntityID entityID, EntityID parent) const noexcept
{
////////////////////////////////////////
// Error Handling
if (!SHEntityManager::IsValidEID(entityID))
{
SHLOG_ERROR("Entity {} is invalid! Unable to set parent of an invalid entity!", entityID)
@ -301,12 +344,13 @@ namespace SHADE
return;
}
auto PARENT_ITER = entityNodeMap.find(entityID);
auto PARENT_ITER = entityNodeMap.find(parent);
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);
@ -318,50 +362,69 @@ namespace SHADE
void SHSceneNode::AddChild(SHSceneNode* newChild) noexcept
{
////////////////////////////////////////
// Error Handling
if (newChild == nullptr)
{
SHLOG_WARNING("Attempting to add a non-existent child to an entity!")
return;
}
////////////////////////////////////////
if (newChild->parent)
newChild->parent->RemoveChild(newChild);
newChild->parent = this;
children.emplace_back(newChild);
}
bool SHSceneNode::RemoveChild(EntityID childID) noexcept
{
////////////////////////////////////////
// Error Handling
if (!SHEntityManager::IsValidEID(childID))
{
SHLOG_ERROR("Entity {} is invalid!", childID)
return false;
}
////////////////////////////////////////
SHSceneNode* removedChild = nullptr;
const auto ENTITY_MATCH = [&](SHSceneNode* node)
auto childIter = std::find_if(children.begin(), children.end(), [&](SHSceneNode* node)
{
if (node->GetEntityID() == childID)
{
removedChild = node;
return true;
}
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;
};
}
children.end() = std::remove_if(children.begin(), children.end(), ENTITY_MATCH);
removedChild->parent = nullptr;
(*childIter)->parent = nullptr;
childIter = children.erase(childIter);
return removedChild == nullptr;
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;
}
////////////////////////////////////////
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;
return true;
@ -375,22 +438,28 @@ namespace SHADE
children.clear();
}
SHSceneNode* SHSceneGraph::AddNode(EntityID entityID, SHSceneNode* parent)
{
////////////////////////////////////////
// Error Handling
if (!SHEntityManager::IsValidEID(entityID))
{
SHLOG_ERROR("Entity {} is invalid!", entityID)
return nullptr;
}
////////////////////////////////////////
if (auto NODE_ITER = entityNodeMap.find(entityID); NODE_ITER != entityNodeMap.end())
{
SHLOG_WARNING("Entity {} already exists in the scene!", entityID)
return NODE_ITER->second;
}
SHSceneNode* newNode = AllocateNode(entityID);
if (parent == nullptr)
parent = root;
newNode->SetParent(parent);
return newNode;

View File

@ -14,6 +14,7 @@
// Project Headers
#include "ECS_Base/Entity/SHEntity.h"
#include "SH_API.h"
namespace SHADE
{
@ -21,7 +22,7 @@ namespace SHADE
/* Type Definitions */
/*-----------------------------------------------------------------------------------*/
class SHSceneNode
class SH_API SHSceneNode
{
public:
/*---------------------------------------------------------------------------------*/
@ -34,40 +35,40 @@ namespace SHADE
/* Constructors & Destructor */
/*---------------------------------------------------------------------------------*/
~SHSceneNode () = default;
~SHSceneNode () = default;
SHSceneNode (EntityID eid, SHSceneNode* parent = nullptr) noexcept;
SHSceneNode (const SHSceneNode& rhs) noexcept;
SHSceneNode (SHSceneNode&& rhs) noexcept;
SHSceneNode& operator= (const SHSceneNode& rhs) noexcept;
SHSceneNode& operator= (SHSceneNode&& rhs) noexcept;
SHSceneNode (EntityID eid, SHSceneNode* parent = nullptr) noexcept;
SHSceneNode (const SHSceneNode& rhs) noexcept;
SHSceneNode (SHSceneNode&& rhs) noexcept;
SHSceneNode& operator= (const SHSceneNode& rhs) noexcept;
SHSceneNode& operator= (SHSceneNode&& rhs) noexcept;
/*---------------------------------------------------------------------------------*/
/* Getter Functions */
/*---------------------------------------------------------------------------------*/
[[nodiscard]] EntityID GetEntityID () const noexcept { return entityID ;}
[[nodiscard]] SHSceneNode* GetParent () const noexcept { return parent; }
[[nodiscard]] std::vector<SHSceneNode*>& GetChildren () noexcept { return children; }
[[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;
[[nodiscard]] SHSceneNode* GetChild (EntityID childID) const noexcept;
/*---------------------------------------------------------------------------------*/
/* Setter Functions */
/*---------------------------------------------------------------------------------*/
void SetParent (SHSceneNode* parentNode) noexcept;
void SetParent (SHSceneNode* parentNode) noexcept;
/*---------------------------------------------------------------------------------*/
/* Function Members */
/*---------------------------------------------------------------------------------*/
void AddChild (SHSceneNode* newChild) noexcept;
void AddChild (SHSceneNode* newChild) noexcept;
bool RemoveChild (EntityID childID) noexcept;
bool RemoveChild (SHSceneNode* childToRemove) noexcept;
bool RemoveChild (EntityID childID) noexcept;
bool RemoveChild (SHSceneNode* childToRemove) noexcept;
void RemoveAllChildren () noexcept;
void RemoveAllChildren () noexcept;
private:
EntityID entityID;
@ -75,7 +76,7 @@ namespace SHADE
std::vector<SHSceneNode*> children;
};
class SHSceneGraph
class SH_API SHSceneGraph
{
public:
/*---------------------------------------------------------------------------------*/
@ -88,19 +89,19 @@ namespace SHADE
/* Constructors & Destructor */
/*---------------------------------------------------------------------------------*/
SHSceneGraph () noexcept;
~SHSceneGraph () noexcept;
SHSceneGraph () noexcept;
~SHSceneGraph () noexcept;
SHSceneGraph (const SHSceneGraph&) = delete;
SHSceneGraph (SHSceneGraph&&) = delete;
SHSceneGraph& operator= (const SHSceneGraph&) = delete;
SHSceneGraph& operator= (SHSceneGraph&&) = delete;
SHSceneGraph (const SHSceneGraph&) = delete;
SHSceneGraph (SHSceneGraph&&) = delete;
SHSceneGraph& operator= (const SHSceneGraph&) = delete;
SHSceneGraph& operator= (SHSceneGraph&&) = delete;
/*---------------------------------------------------------------------------------*/
/* Getter Functions */
/*---------------------------------------------------------------------------------*/
[[nodiscard]] SHSceneNode* GetRoot () const noexcept;
[[nodiscard]] const SHSceneNode* GetRoot () const noexcept;
[[nodiscard]] SHSceneNode* GetNode (EntityID entityID) const noexcept;
[[nodiscard]] SHSceneNode* GetParent (EntityID entityID) const noexcept;
[[nodiscard]] SHSceneNode* GetChild (EntityID entityID, SHSceneNode* childNode) const noexcept;
@ -111,17 +112,17 @@ namespace SHADE
/* Setter Functions */
/*---------------------------------------------------------------------------------*/
void SetParent (EntityID entityID, SHSceneNode* parent) const noexcept;
void SetParent (EntityID entityID, EntityID parent) const noexcept;
void SetParent (EntityID entityID, SHSceneNode* parent) const noexcept;
void SetParent (EntityID entityID, EntityID parent) const noexcept;
/*---------------------------------------------------------------------------------*/
/* Function Members */
/*---------------------------------------------------------------------------------*/
SHSceneNode* AddNode (EntityID entityID, SHSceneNode* parent = nullptr);
bool RemoveNode (EntityID entityID) noexcept;
bool RemoveNode (SHSceneNode* nodeToRemove) noexcept;
void Reset () noexcept;
SHSceneNode* AddNode (EntityID entityID, SHSceneNode* parent = nullptr);
bool RemoveNode (EntityID entityID) noexcept;
bool RemoveNode (SHSceneNode* nodeToRemove) noexcept;
void Reset () noexcept;
private:
/*---------------------------------------------------------------------------------*/
@ -136,7 +137,7 @@ namespace SHADE
/*---------------------------------------------------------------------------------*/
SHSceneNode* AllocateNode (EntityID entityID);
void ReleaseNode (SHSceneNode* node) noexcept;
void ReleaseNode (SHSceneNode* node) noexcept;
};

View File

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

View File

@ -20,7 +20,7 @@
namespace SHADE
{
class SHSceneManager
class SH_API SHSceneManager
{
private:
//boolean to check if the scene has been changed
@ -57,6 +57,15 @@ namespace SHADE
//boolean to check if the programme has been terminated.
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
* 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
PAUSE