Merge branch 'main' into SP3-10-input-management

This commit is contained in:
mushgunAX 2022-09-23 13:41:50 +08:00
commit ed56ad99df
27 changed files with 1086 additions and 295 deletions

View File

@ -1,16 +1,16 @@
IncludeDir = {}
IncludeDir["assimp"] = "%{wks.location}/Dependencies/assimp"
IncludeDir["imgui"] = "%{wks.location}/Dependencies/imgui"
IncludeDir["imguizmo"] = "%{wks.location}/Dependencies/imguizmo"
IncludeDir["imnodes"] = "%{wks.location}/Dependencies/imnodes"
IncludeDir["msdf_atlas_gen"] = "%{wks.location}/Dependencies/msdf"
IncludeDir["msdfgen"] = "%{wks.location}/Dependencies/msdf/msdfgen"
IncludeDir["spdlog"] = "%{wks.location}/Dependencies/spdlog"
IncludeDir["tracy"] = "%{wks.location}/Dependencies/tracy"
IncludeDir["VMA"] = "%{wks.location}/Dependencies/VMA"
IncludeDir["yamlcpp"] = "%{wks.location}/Dependencies/yamlcpp/include"
IncludeDir["RTTR"] = "%{wks.location}/Dependencies/RTTR"
IncludeDir["reactphysics3d"] = "%{wks.location}/Dependencies/reactphysics3d"
IncludeDir["SDL"] = "%{wks.location}/Dependencies/SDL"
IncludeDir["assimp"] = "%{wks.location}\\Dependencies\\assimp"
IncludeDir["imgui"] = "%{wks.location}\\Dependencies\\imgui"
IncludeDir["imguizmo"] = "%{wks.location}\\Dependencies\\imguizmo"
IncludeDir["imnodes"] = "%{wks.location}\\Dependencies\\imnodes"
IncludeDir["msdf_atlas_gen"] = "%{wks.location}\\Dependencies\\msdf"
IncludeDir["msdfgen"] = "%{wks.location}\\Dependencies\\msdf\\msdfgen"
IncludeDir["spdlog"] = "%{wks.location}\\Dependencies\\spdlog"
IncludeDir["tracy"] = "%{wks.location}\\Dependencies\\tracy"
IncludeDir["VMA"] = "%{wks.location}\\Dependencies\\VMA"
IncludeDir["yamlcpp"] = "%{wks.location}\\Dependencies\\yamlcpp\\include"
IncludeDir["RTTR"] = "%{wks.location}\\Dependencies\\RTTR"
IncludeDir["reactphysics3d"] = "%{wks.location}\\Dependencies\\reactphysics3d"
IncludeDir["SDL"] = "%{wks.location}\\Dependencies\\SDL"
IncludeDir["VULKAN"] = "$(VULKAN_SDK)"
IncludeDir["dotnet"] = "%{wks.location}/Dependencies/dotnet"
IncludeDir["dotnet"] = "%{wks.location}\\Dependencies\\dotnet"

View File

@ -22,6 +22,7 @@
#include "ECS_Base/Managers/SHEntityManager.h"
#include "Graphics/MiddleEnd/Interface/SHRenderable.h"
#include "Scene/SHSceneManager.h"
#include "Math/Transform/SHTransformSystem.h"
#include "Scenes/SBTestScene.h"
@ -43,28 +44,42 @@ namespace Sandbox
SDL_Init(SDL_INIT_EVERYTHING);
window.Create(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
// Create Systems
SHADE::SHSystemManager::CreateSystem<SHADE::SHScriptEngine>();
// TODO(Diren): Create Physics System here
SHADE::SHSystemManager::CreateSystem<SHADE::SHTransformSystem>();
SHADE::SHSystemManager::CreateSystem<SHADE::SHGraphicsSystem>();
SHADE::SHGraphicsSystem* graphicsSystem = static_cast<SHADE::SHGraphicsSystem*>(SHADE::SHSystemManager::GetSystem<SHADE::SHGraphicsSystem>());
// Create Routines
SHADE::SHSystemManager::RegisterRoutine<SHADE::SHScriptEngine, SHADE::SHScriptEngine::FrameSetUpRoutine>();
SHADE::SHSystemManager::RegisterRoutine<SHADE::SHScriptEngine, SHADE::SHScriptEngine::UpdateRoutine>();
SHADE::SHSystemManager::RegisterRoutine<SHADE::SHScriptEngine, SHADE::SHScriptEngine::LateUpdateRoutine>();
SHADE::SHSystemManager::RegisterRoutine<SHADE::SHScriptEngine, SHADE::SHScriptEngine::FrameCleanUpRoutine>();
// TODO(Diren): Register Physics System & Routines here
SHADE::SHSystemManager::RegisterRoutine<SHADE::SHTransformSystem, SHADE::SHTransformSystem::TransformUpdateRoutine>();
SHADE::SHComponentManager::CreateComponentSparseSet<SHADE::SHTransformComponent>();
SHADE::SHSystemManager::RegisterRoutine<SHADE::SHGraphicsSystem, SHADE::SHGraphicsSystem::BatcherDispatcherRoutine>();
SHADE::SHSystemManager::RegisterRoutine<SHADE::SHGraphicsSystem, SHADE::SHGraphicsSystem::BeginRoutine>();
SHADE::SHSystemManager::RegisterRoutine<SHADE::SHGraphicsSystem, SHADE::SHGraphicsSystem::RenderRoutine>();
SHADE::SHSystemManager::RegisterRoutine<SHADE::SHGraphicsSystem, SHADE::SHGraphicsSystem::EndRoutine>();
SHADE::SHComponentManager::CreateComponentSparseSet<SHADE::SHRenderable>();
// Set up graphics system and windows
graphicsSystem->SetWindow(&window);
sdlWindow = SDL_CreateWindowFrom(window.GetHWND());
//auto [w, h] = window.GetWindowSize();
//SDL_SetWindowSize(sdlWindow, w, h);
SHADE::SHSystemManager::Init();
#ifdef SHEDITOR
#ifdef SHEDITOR
SHADE::SHEditor::Initialise(sdlWindow);
#else
#endif
// Set up scripting
SHADE::SHScriptEngine::Init();
#else
#endif
SHSceneManager::InitSceneManager<SBTestScene>("TestScene");
}
@ -99,11 +114,10 @@ namespace Sandbox
void SBApplication::Exit(void)
{
#ifdef SHEDITOR
#ifdef SHEDITOR
SHADE::SHEditor::Exit();
#endif
SHSceneManager::Exit();
SHADE::SHScriptEngine::Exit();
SHADE::SHSystemManager::Exit();
SDL_DestroyWindow(sdlWindow);
SDL_Quit();

View File

@ -7,6 +7,8 @@
#include "Graphics/MiddleEnd/Interface/SHRenderable.h"
#include "Scene/SHSceneManager.h"
#include "Graphics/MiddleEnd/Interface/SHGraphicsSystem.h"
#include "Scripting/SHScriptEngine.h"
#include "Math/Transform/SHTransformComponent.h"
using namespace SHADE;
@ -37,16 +39,23 @@ namespace Sandbox
auto matInst = graphicsSystem->AddMaterialInstance();
// Create entity and add mesh
auto entity = SHADE::SHEntityManager::CreateEntity<SHADE::SHRenderable>();
auto& renderable = *SHADE::SHComponentManager::GetComponent_s<SHADE::SHRenderable>(entity);
testObj = SHADE::SHEntityManager::CreateEntity<SHADE::SHRenderable, SHADE::SHTransformComponent>();
auto& renderable = *SHADE::SHComponentManager::GetComponent_s<SHADE::SHRenderable>(testObj);
renderable.Mesh = CUBE_MESH;
renderable.SetMaterial(matInst);
renderable.TransformMatrix.Translate(0.0f, 0.0f, 2.0f);
// Create transform
auto& transform = *SHADE::SHComponentManager::GetComponent_s<SHADE::SHTransformComponent>(testObj);
transform.SetLocalPosition(SHVec3{ 0.0f, 0.0f, 2.0f });
renderable.TransformMatrix = SHMatrix::Translate(0.0f, 0.0f, 2.0f);
SHADE::SHScriptEngine* scriptEngine = static_cast<SHADE::SHScriptEngine*>(SHADE::SHSystemManager::GetSystem<SHADE::SHScriptEngine>());
scriptEngine->AddScript(*SHADE::SHEntityManager::GetEntityByID(testObj), "TestScript");
}
void SBTestScene::Update(float dt)
{
(void)dt;
if (GetKeyState(VK_SPACE) & 0x8000)
SHADE::SHEntityManager::DestroyEntity(testObj);
}
void SBTestScene::Render()

View File

@ -9,6 +9,7 @@ namespace Sandbox
{
private:
EntityID camera;
EntityID testObj;
public:

View File

@ -25,22 +25,22 @@ project "SHADE_Engine"
externalincludedirs
{
"%{IncludeDir.assimp}/include",
"%{IncludeDir.assimp}\\include",
"%{IncludeDir.imgui}",
"%{IncludeDir.imguizmo}",
"%{IncludeDir.imnodes}",
"%{IncludeDir.msdf_atlas_gen}",
"%{IncludeDir.msdfgen}",
"%{IncludeDir.spdlog}/include",
"%{IncludeDir.spdlog}\\include",
"%{IncludeDir.tracy}",
"%{IncludeDir.VMA}/include",
"%{IncludeDir.VMA}\\include",
"%{IncludeDir.yamlcpp}",
"%{IncludeDir.SDL}/include",
"%{IncludeDir.RTTR}/include",
"%{IncludeDir.reactphysics3d}/include",
"%{IncludeDir.VULKAN}/include",
"%{IncludeDir.VULKAN}/Source/SPIRV-Reflect",
"%{IncludeDir.dotnet}/include",
"%{IncludeDir.SDL}\\include",
"%{IncludeDir.RTTR}\\include",
"%{IncludeDir.reactphysics3d}\\include",
"%{IncludeDir.VULKAN}\\include",
"%{IncludeDir.VULKAN}\\Source\\SPIRV-Reflect",
"%{IncludeDir.dotnet}\\include",
}
externalwarnings "Off"
@ -100,9 +100,9 @@ project "SHADE_Engine"
postbuildcommands
{
"xcopy /s /r /y /q \"%{IncludeDir.spdlog}/bin\" \"$(OutDir)\"",
"xcopy /r /y /q \"%{IncludeDir.SDL}/lib/SDL2.dll\" \"$(OutDir)\"",
"xcopy /s /r /y /q \"%{IncludeDir.dotnet}/bin\" \"$(OutDir)\""
"xcopy /s /r /y /q \"%{IncludeDir.spdlog}\\bin\" \"$(OutDir)\"",
"xcopy /r /y /q \"%{IncludeDir.SDL}\\lib\\SDL2.dll\" \"$(OutDir)\"",
"xcopy /s /r /y /q \"%{IncludeDir.dotnet}\\bin\" \"$(OutDir)\""
}
warnings 'Extra'

View File

@ -19,7 +19,7 @@ namespace SHADE
SHEventHandle(T::*callback)(SHEventPtr);
public:
SHEventReceiverSpec(T* obj, void(T::* cb)(SHEventPtr))
SHEventReceiverSpec(T* obj, SHEventHandle(T::* cb)(SHEventPtr))
:SHEventReceiver(), object{ obj }, callback{ cb }
{

View File

@ -21,12 +21,16 @@
namespace SHADE
{
/*-----------------------------------------------------------------------------------*/
/* Static Data Member Definitions */
/*-----------------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------------*/
/* Constructors & Destructor Definitions */
/*-----------------------------------------------------------------------------------*/
SHTransformSystem::SHTransformSystem()
: SHSystemRoutine { "Transform Routine", false }
SHTransformSystem::TransformUpdateRoutine::TransformUpdateRoutine()
: SHSystemRoutine { "Transform Update", true }
{}
@ -34,13 +38,23 @@ namespace SHADE
/* Public Function Member Definitions */
/*-----------------------------------------------------------------------------------*/
void SHTransformSystem::Execute(double dt) noexcept
void SHTransformSystem::TransformUpdateRoutine::Execute(double) noexcept
{
// Get the current scene graph to traverse and update
const auto& SCENE_GRAPH = SHSceneManager::GetCurrentSceneGraph();
UpdateEntity(SCENE_GRAPH.GetRoot());
}
void SHTransformSystem::Init()
{
}
void SHTransformSystem::Exit()
{
}
/*-----------------------------------------------------------------------------------*/
/* Private Function Member Definitions */
/*-----------------------------------------------------------------------------------*/
@ -53,18 +67,16 @@ namespace SHADE
for (const auto* child : node->GetChildren())
{
// Active states of entities should sync with scene nodes
const bool IS_NODE_ACTIVE = child->isActive;
const bool IS_NODE_ACTIVE = child->IsActive();
#ifdef _DEBUG
const bool IS_ENTITY_ACTIVE = SHEntityManager::GetEntityByID(child->GetEntityID())->GetActive();
SHASSERT(IS_NODE_ACTIVE == IS_ENTITY_ACTIVE, "Entity and Node active states are not synced!")
#endif
// Anything below is inactive
if (!IS_NODE_ACTIVE)
{
UpdateEntity(child);
continue;
}
break;
const bool HAS_TRANSFORM = SHComponentManager::HasComponent<SHTransformComponent>(child->GetEntityID());
if (!HAS_TRANSFORM)
@ -90,7 +102,7 @@ namespace SHADE
if (parent)
{
localToWorld = parent->GetTRS();
worldToLocal = SHMatrix::Inverse(tf.local.trs);
worldToLocal = SHMatrix::Inverse(localToWorld);
}
while (!tf.updateQueue.empty())
@ -134,6 +146,10 @@ namespace SHADE
tf.world.scale = tf.local.scale * (parent ? parent->GetLocalScale() : SHVec3::One);
tf.world.ComputeTRS();
// Transpose TRS to column major
tf.local.trs.Transpose();
tf.world.trs.Transpose();
}
} // namespace SHADE

View File

@ -21,19 +21,18 @@ namespace SHADE
/* Type Definitions */
/*-----------------------------------------------------------------------------------*/
class SH_API SHTransformSystem : public SHSystemRoutine
class SH_API SHTransformSystem final : public SHSystem
{
public:
/*---------------------------------------------------------------------------------*/
/* Constructors & Destructor */
/*---------------------------------------------------------------------------------*/
SHTransformSystem ();
~SHTransformSystem () = default;
SHTransformSystem () = default;
~SHTransformSystem () override = default;
SHTransformSystem (const SHTransformSystem&) = delete;
SHTransformSystem (SHTransformSystem&&) = delete;
SHTransformSystem (const SHTransformSystem&) = delete;
SHTransformSystem (SHTransformSystem&&) = delete;
/*---------------------------------------------------------------------------------*/
/* Operator Overloads */
@ -42,11 +41,43 @@ namespace SHADE
SHTransformSystem& operator= (const SHTransformSystem&) = delete;
SHTransformSystem& operator= (SHTransformSystem&&) = delete;
/*---------------------------------------------------------------------------------*/
/* System Routines */
/*---------------------------------------------------------------------------------*/
class SH_API TransformUpdateRoutine final: public SHSystemRoutine
{
public:
/*-------------------------------------------------------------------------------*/
/* Constructors & Destructor */
/*-------------------------------------------------------------------------------*/
TransformUpdateRoutine ();
~TransformUpdateRoutine () = default;
TransformUpdateRoutine (const TransformUpdateRoutine&) = delete;
TransformUpdateRoutine (TransformUpdateRoutine&&) = delete;
/*-------------------------------------------------------------------------------*/
/* Operator Overloads */
/*-------------------------------------------------------------------------------*/
TransformUpdateRoutine& operator= (const TransformUpdateRoutine&) = delete;
TransformUpdateRoutine& operator= (TransformUpdateRoutine&&) = delete;
/*-------------------------------------------------------------------------------*/
/* Function Members */
/*-------------------------------------------------------------------------------*/
void Execute(double dt) noexcept override;
};
/*---------------------------------------------------------------------------------*/
/* Function Members */
/*---------------------------------------------------------------------------------*/
void Execute(double dt) noexcept override;
void Init () override;
void Exit () override;
private:
/*---------------------------------------------------------------------------------*/

View File

@ -25,14 +25,14 @@ namespace SHADE
/*-----------------------------------------------------------------------------------*/
SHSceneNode::SHSceneNode(EntityID eid, SHSceneNode* parent) noexcept
: isActive { true }
: active { true }
, entityID { eid }
, parent { parent }
{}
SHSceneNode::SHSceneNode(const SHSceneNode& rhs) noexcept
: isActive { rhs.isActive }
: active { rhs.active }
, entityID { rhs.entityID }
, parent { rhs.parent }
{
@ -40,7 +40,7 @@ namespace SHADE
}
SHSceneNode::SHSceneNode(SHSceneNode&& rhs) noexcept
: isActive { rhs.isActive }
: active { rhs.active }
, entityID { rhs.entityID }
, parent { rhs.parent }
{
@ -52,9 +52,9 @@ namespace SHADE
if (this == &rhs)
return *this;
isActive = rhs.isActive;
entityID = rhs.entityID;
parent = rhs.parent;
active = rhs.active;
entityID = rhs.entityID;
parent = rhs.parent;
children.clear();
std::ranges::copy(rhs.children.begin(), rhs.children.end(), std::back_inserter(children));
@ -64,9 +64,9 @@ namespace SHADE
SHSceneNode& SHSceneNode::operator=(SHSceneNode&& rhs) noexcept
{
isActive = rhs.isActive;
entityID = rhs.entityID;
parent = rhs.parent;
active = rhs.active;
entityID = rhs.entityID;
parent = rhs.parent;
children.clear();
std::ranges::copy(rhs.children.begin(), rhs.children.end(), std::back_inserter(children));
@ -104,6 +104,11 @@ namespace SHADE
/* Getter Function Definitions */
/*-----------------------------------------------------------------------------------*/
bool SHSceneNode::IsActive() const noexcept
{
return active;
}
EntityID SHSceneNode::GetEntityID() const noexcept
{
return entityID;
@ -154,7 +159,7 @@ namespace SHADE
if (root != nullptr)
return root;
SHLOG_WARNING("Scene has no root object!")
SHLOG_ERROR("Scene has no root object!")
return nullptr;
}
@ -171,7 +176,7 @@ namespace SHADE
const auto NODE_ITER = entityNodeMap.find(entityID);
if (NODE_ITER == entityNodeMap.end())
{
SHLOG_WARNING("Entity {} cannot be found in the scene! Unable to Get Scene node!", entityID)
SHLOG_ERROR("Entity {} cannot be found in the scene! Unable to Get Scene node!", entityID)
return nullptr;
}
////////////////////////////////////////
@ -192,7 +197,7 @@ namespace SHADE
const auto NODE_ITER = entityNodeMap.find(entityID);
if (NODE_ITER == entityNodeMap.end())
{
SHLOG_WARNING("Entity {} cannot be found in the scene! Unable to get Parent node!", entityID)
SHLOG_ERROR("Entity {} cannot be found in the scene! Unable to get Parent node!", entityID)
return nullptr;
}
////////////////////////////////////////
@ -213,7 +218,7 @@ namespace SHADE
const auto NODE_ITER = entityNodeMap.find(entityID);
if (NODE_ITER == entityNodeMap.end())
{
SHLOG_WARNING("Entity {} cannot be found in the scene!", entityID)
SHLOG_ERROR("Entity {} cannot be found in the scene!", entityID)
return nullptr;
}
@ -248,7 +253,7 @@ namespace SHADE
const auto NODE_ITER = entityNodeMap.find(entityID);
if (NODE_ITER == entityNodeMap.end())
{
SHLOG_WARNING("Entity {} cannot be found in the scene!", entityID)
SHLOG_ERROR("Entity {} cannot be found in the scene!", entityID)
return nullptr;
}
////////////////////////////////////////
@ -269,7 +274,7 @@ namespace SHADE
const auto NODE_ITER = entityNodeMap.find(entityID);
if (NODE_ITER == entityNodeMap.end())
{
SHLOG_WARNING("Entity {} cannot be found in the scene!", entityID)
SHLOG_ERROR("Entity {} cannot be found in the scene!", entityID)
return root->GetChildren();
}
////////////////////////////////////////
@ -277,6 +282,27 @@ namespace SHADE
return NODE_ITER->second->GetChildren();
}
bool SHSceneGraph::IsActiveInHierarchy(EntityID entityID) const noexcept
{
////////////////////////////////////////
// Error handling
if (!SHEntityManager::IsValidEID(entityID))
{
SHLOG_ERROR("Entity {} is invalid!", entityID)
return false;
}
const auto NODE_ITER = entityNodeMap.find(entityID);
if (NODE_ITER == entityNodeMap.end())
{
SHLOG_ERROR("Entity {} cannot be found in the scene!", entityID)
return false;
}
////////////////////////////////////////
return NODE_ITER->second->IsActive();
}
/*-----------------------------------------------------------------------------------*/
/* Setter Function Definitions */
/*-----------------------------------------------------------------------------------*/
@ -289,7 +315,7 @@ namespace SHADE
}
// Handle self assignment
if (parentNode == parent)
if (parent && parentNode->entityID == parent->entityID)
return;
if (parent)
@ -300,6 +326,16 @@ namespace SHADE
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
{
////////////////////////////////////////
@ -318,6 +354,9 @@ namespace SHADE
}
////////////////////////////////////////
if (parent == nullptr)
parent = root;
NODE_ITER->second->SetParent(parent);
}
@ -340,14 +379,14 @@ namespace SHADE
auto NODE_ITER = entityNodeMap.find(entityID);
if (NODE_ITER == entityNodeMap.end())
{
SHLOG_WARNING("Entity {} cannot be found in the scene! Unable to set parent!", entityID)
SHLOG_ERROR("Entity {} cannot be found in the scene! Unable to set parent!", entityID)
return;
}
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)
SHLOG_ERROR("Entity {} cannot be found in the scene! Unable to parent to Entity {}", parent, entityID)
return;
}
////////////////////////////////////////
@ -458,9 +497,16 @@ namespace SHADE
SHSceneNode* newNode = AllocateNode(entityID);
if (parent == nullptr)
{
// Specific handling for root to avoid a warning when removing a non-existent child
parent = root;
newNode->SetParent(parent);
newNode->parent = root;
root->children.emplace_back(newNode);
}
else
{
newNode->SetParent(parent);
}
return newNode;
}
@ -476,7 +522,7 @@ namespace SHADE
auto NODE_ITER = entityNodeMap.find(entityID);
if (NODE_ITER == entityNodeMap.end())
{
SHLOG_WARNING("Entity {} does not exist in the scene!", entityID)
SHLOG_ERROR("Entity {} does not exist in the scene!", entityID)
return false;
}

View File

@ -38,12 +38,6 @@ namespace SHADE
friend class SHSceneGraph;
public:
/*---------------------------------------------------------------------------------*/
/* Data Members */
/*---------------------------------------------------------------------------------*/
bool isActive;
/*---------------------------------------------------------------------------------*/
/* Constructors & Destructor */
/*---------------------------------------------------------------------------------*/
@ -60,6 +54,7 @@ namespace SHADE
/* 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;
@ -70,7 +65,8 @@ namespace SHADE
/* Setter Functions */
/*---------------------------------------------------------------------------------*/
void SetParent (SHSceneNode* parentNode) noexcept;
void SetParent (SHSceneNode* parentNode) noexcept;
void SetActive (bool newActiveState) noexcept;
/*---------------------------------------------------------------------------------*/
/* Function Members */
@ -88,6 +84,7 @@ namespace SHADE
/* Data Members */
/*---------------------------------------------------------------------------------*/
bool active;
EntityID entityID;
SHSceneNode* parent;
std::vector<SHSceneNode*> children;
@ -121,12 +118,14 @@ namespace SHADE
/* Getter Functions */
/*---------------------------------------------------------------------------------*/
[[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;
[[nodiscard]] SHSceneNode* GetChild (EntityID entityID, EntityID childEntityID) const noexcept;
[[nodiscard]] const std::vector<SHSceneNode*>& GetChildren (EntityID entityID) 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;
[[nodiscard]] SHSceneNode* GetChild (EntityID entityID, EntityID childEntityID) const noexcept;
[[nodiscard]] const std::vector<SHSceneNode*>& GetChildren (EntityID entityID) const noexcept;
[[nodiscard]] bool IsActiveInHierarchy (EntityID entityID) const noexcept;
/*---------------------------------------------------------------------------------*/
/* Setter Functions */

View File

@ -16,7 +16,6 @@
#include "SHScene.h"
#include <functional>
#include "SH_API.h"
//Project Headers
#include "SH_API.h"

View File

@ -16,39 +16,27 @@ of DigiPen Institute of Technology is prohibited.
// Standard Library
#include <fstream> // std::fstream
#include <filesystem> // std::filesystem::canonical, std::filesystem::remove
#include <memory> // std::shared_ptr
// Project Headers
#include "Tools/SHLogger.h"
#include "Tools/SHStringUtils.h"
#include "ECS_Base/Events/SHEntityDestroyedEvent.h"
#include "Events/SHEvent.h"
#include "Events/SHEventReceiver.h"
#include "Events/SHEventManager.hpp"
namespace SHADE
{
/*--------------------------------------------------------------------------------*/
/* Static Definitions */
/*--------------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------------*/
/* Static Definitions */
/*----------------------------------------------------------------------------------*/
const std::string SHScriptEngine::DEFAULT_CSHARP_NAMESPACE = std::string("SHADE");
SHDotNetRuntime SHScriptEngine::dotNet { false };
SHScriptEngine::CsFuncPtr SHScriptEngine::csEngineInit = nullptr;
SHScriptEngine::CsFuncPtr SHScriptEngine::csEngineLoadScripts = nullptr;
SHScriptEngine::CsFuncPtr SHScriptEngine::csEngineUnloadScripts = nullptr;
SHScriptEngine::CsFuncPtr SHScriptEngine::csEngineReloadScripts = nullptr;
SHScriptEngine::CsFuncPtr SHScriptEngine::csEngineExit = nullptr;
SHScriptEngine::CsFuncPtr SHScriptEngine::csScriptsFrameSetUp = nullptr;
SHScriptEngine::CsFuncPtr SHScriptEngine::csScriptsExecuteFixedUpdate = nullptr;
SHScriptEngine::CsFuncPtr SHScriptEngine::csScriptsExecuteUpdate = nullptr;
SHScriptEngine::CsFuncPtr SHScriptEngine::csScriptsExecuteLateUpdate = nullptr;
SHScriptEngine::CsFuncPtr SHScriptEngine::csScriptsFrameCleanUp = nullptr;
SHScriptEngine::CsScriptManipFuncPtr SHScriptEngine::csScriptsAdd = nullptr;
SHScriptEngine::CsScriptBasicFuncPtr SHScriptEngine::csScriptsRemoveAll = nullptr;
SHScriptEngine::CsScriptOptionalFuncPtr SHScriptEngine::csScriptsRemoveAllImmediately = nullptr;
SHScriptEngine::CsScriptSerialiseFuncPtr SHScriptEngine::csScriptsSerialise = nullptr;
SHScriptEngine::CsScriptDeserialiseFuncPtr SHScriptEngine::csScriptDeserialise = nullptr;
SHScriptEngine::CsScriptSerialiseYamlFuncPtr SHScriptEngine::csScriptsSerialiseYaml = nullptr;
SHScriptEngine::CsScriptSerialiseYamlFuncPtr SHScriptEngine::csScriptDeserialiseYaml = nullptr;
SHScriptEngine::CsScriptEditorFuncPtr SHScriptEngine::csEditorRenderScripts = nullptr;
const std::string SHScriptEngine::CSPROJ_DIR = "..\\..\\TempScriptsFolder";
const std::string SHScriptEngine::CSPROJ_PATH = std::string(CSPROJ_DIR) + "\\SHADE_Scripting.csproj";
/*---------------------------------------------------------------------------------*/
/* Lifecycle Functions */
/*---------------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------------*/
/* Lifecycle Functions */
/*-----------------------------------------------------------------------------------*/
void SHScriptEngine::Init()
{
// Do not allow initialization if already initialised
@ -71,15 +59,9 @@ namespace SHADE
// Initialise the CSharp Engine
csEngineInit();
// Link events
// - Entity Destruction
/*onEntityDestroy = [this](const SHEntity& e)
{
csScriptsRemoveAll(e.GetEID());
csGOLibNotifyDestroyEntity(e.GetEID());
};
ECS::OnEntityDestroy += onEntityDestroy;*/
// Register entity creation events
registerEvents();
}
void SHScriptEngine::UnloadScriptAssembly()
{
@ -118,9 +100,9 @@ namespace SHADE
dotNet.Exit();
}
/*---------------------------------------------------------------------------------*/
/* Script Manipulation Functions */
/*---------------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------------*/
/* Script Manipulation Functions */
/*-----------------------------------------------------------------------------------*/
bool SHScriptEngine::AddScript(const SHEntity& entity, const std::string_view& scriptName)
{
return csScriptsAdd(entity.GetEID(), scriptName.data());
@ -137,7 +119,7 @@ namespace SHADE
/*---------------------------------------------------------------------------------*/
/* Script Serialisation Functions */
/*---------------------------------------------------------------------------------*/
std::string SHScriptEngine::SerialiseScripts(const SHEntity& entity)
std::string SHScriptEngine::SerialiseScripts(const SHEntity& entity) const
{
// Create buffer needed to store serialised script data
constexpr int BUFFER_SIZE = 10240;
@ -159,41 +141,40 @@ namespace SHADE
return result;
}
/*---------------------------------------------------------------------------------*/
/* Script Serialisation Functions */
/*---------------------------------------------------------------------------------*/
void SHScriptEngine::DeserialiseScript(const SHEntity& entity, const std::string& yaml)
/*-----------------------------------------------------------------------------------*/
/* Script Serialisation Functions */
/*-----------------------------------------------------------------------------------*/
void SHScriptEngine::DeserialiseScript(const SHEntity& entity, const std::string& yaml) const
{
csScriptDeserialise(entity.GetEID(), yaml.c_str());
}
/*---------------------------------------------------------------------------------*/
/* Script Editor Functions */
/*---------------------------------------------------------------------------------*/
void SHScriptEngine::RenderScriptsInInspector(const SHEntity& entity)
/*-----------------------------------------------------------------------------------*/
/* Script Editor Functions */
/*-----------------------------------------------------------------------------------*/
void SHScriptEngine::RenderScriptsInInspector(const SHEntity& entity) const
{
csEditorRenderScripts(entity.GetEID());
}
/*---------------------------------------------------------------------------------*/
/* Static Utility Functions */
/*---------------------------------------------------------------------------------*/
bool SHScriptEngine::BuildScriptAssembly(bool debug)
/*-----------------------------------------------------------------------------------*/
/* Static Utility Functions */
/*-----------------------------------------------------------------------------------*/
bool SHScriptEngine::BuildScriptAssembly(bool debug) const
{
constexpr std::string_view BUILD_LOG_PATH = "../Build.log";
static const std::string BUILD_LOG_PATH = "../Build.log";
// Generate csproj file if it doesn't exist
static const std::filesystem::path CSPROJ_PATH = "../SHADE_Scripting.csproj";
if (!std::filesystem::exists(CSPROJ_PATH))
{
GenerateScriptsCsProjFile(CSPROJ_PATH);
}
// Prepare directory (delete useless files)
deleteFolder("net5.0");
deleteFolder("ref");
deleteFolder("../SHADE_Scripting");
deleteFolder("../obj");
deleteFolder(CSPROJ_DIR + "\\net5.0");
deleteFolder(CSPROJ_DIR + "\\ref");
deleteFolder(CSPROJ_DIR + "\\obj");
deleteFolder(CSPROJ_DIR + "\\bin");
// Attempt to build the assembly
std::ostringstream oss;
@ -203,7 +184,7 @@ namespace SHADE
const bool BUILD_SUCCESS = execProcess
(
L"C:\\Windows\\system32\\cmd.exe",
L"/K \"dotnet build \"../SHADE_Scripting.csproj\" -c Debug -o \"./tmp/\" -fl -flp:LogFile=build.log;Verbosity=quiet & exit\""
L"/K \"" + generateBuildCommand(debug) + L" & exit\""
) == 0;
if (BUILD_SUCCESS)
{
@ -221,6 +202,7 @@ namespace SHADE
// Clean up built files
deleteFolder("./tmp");
deleteFolder(CSPROJ_DIR + "\\obj");
// Read the build log and output to the console
dumpBuildLog(BUILD_LOG_PATH);
@ -228,9 +210,9 @@ namespace SHADE
deleteFile(BUILD_LOG_PATH);
return BUILD_SUCCESS;
}
}
void SHScriptEngine::GenerateScriptsCsProjFile(const std::filesystem::path& path)
void SHScriptEngine::GenerateScriptsCsProjFile(const std::filesystem::path& path) const
{
// Sample
static std::string_view FILE_CONTENTS =
@ -241,11 +223,11 @@ namespace SHADE
<Configurations>Release;Debug</Configurations>\n\
</PropertyGroup>\n\
<PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">\n\
<OutputPath>.\\bin_Release-x64</OutputPath>\n\
<OutputPath>.\\bin\\Release</OutputPath>\n\
<PlatformTarget>x64</PlatformTarget>\n\
</PropertyGroup>\n\
<PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\"> \n\
<OutputPath>.\\bin_Debug-x64</OutputPath>\n\
<OutputPath>.\\bin\\Debug</OutputPath>\n\
<PlatformTarget>x64</PlatformTarget>\n\
<DefineConstants>DEBUG;TRACE</DefineConstants>\n\
<Optimize>false</Optimize>\n\
@ -264,7 +246,8 @@ namespace SHADE
</ItemGroup>\n\
<ItemGroup>\n\
<Reference Include=\"SHADE_Managed\">\n\
<HintPath>.\\bin\\SHADE_Managed.dll</HintPath>\n\
<HintPath Condition=\"Exists('..\\bin\\Debug\\SHADE_Managed.dll')\">..\\bin\\Debug\\SHADE_Managed.dll</HintPath>\
<HintPath Condition=\"Exists('..\\bin\\Release\\SHADE_Managed.dll')\">..\\bin\\Release\\SHADE_Managed.dll</HintPath>\
</Reference>\n\
</ItemGroup>\n\
</Project>";
@ -273,17 +256,27 @@ namespace SHADE
std::ofstream file(path);
if (!file.is_open())
throw std::runtime_error("Unable to create CsProj file!");
// Fill the file
file << FILE_CONTENTS;
// Close
file.close();
}
}
/*---------------------------------------------------------------------------------*/
/* Helper Functions */
/*---------------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------------*/
/* Event Handler Functions */
/*-----------------------------------------------------------------------------------*/
SHEventHandle SHScriptEngine::onEntityDestroyed(SHEventPtr eventPtr)
{
auto eventData = reinterpret_cast<const SHEventSpec<SHEntityDestroyedEvent>*>(eventPtr.get());
csScriptsRemoveAll(eventData->data->eid);
return eventData->handle;
}
/*-----------------------------------------------------------------------------------*/
/* Helper Functions */
/*-----------------------------------------------------------------------------------*/
void SHScriptEngine::loadFunctions()
{
std::ostringstream oss;
@ -401,6 +394,17 @@ namespace SHADE
);*/
}
void SHScriptEngine::registerEvents()
{
// Register for entity destroyed event
std::shared_ptr<SHEventReceiverSpec<SHScriptEngine>> destroyedEventReceiver
{
std::make_shared<SHEventReceiverSpec<SHScriptEngine>>(this, &SHScriptEngine::onEntityDestroyed)
};
ReceiverPtr receiver = std::dynamic_pointer_cast<SHEventReceiver>(destroyedEventReceiver);
SHEventManager::SubscribeTo(SH_ENTITY_DESTROYED_EVENT, receiver);
}
void SHScriptEngine::dumpBuildLog(const std::string_view& buildLogPath)
{
std::ifstream buildLog(buildLogPath);
@ -423,25 +427,25 @@ namespace SHADE
}
}
}
void SHScriptEngine::deleteFile(const std::string_view& filePath)
void SHScriptEngine::deleteFile(const std::string& filePath)
{
try
{
std::filesystem::remove(std::filesystem::canonical(filePath));
}
catch (...) {} // Ignore deletion failures
}
void SHScriptEngine::deleteFolder(const std::string_view& filePath)
try
{
try
{
std::filesystem::remove_all(std::filesystem::canonical(filePath));
}
catch (...) {} // Ignore deletion failures
std::filesystem::remove(std::filesystem::canonical(filePath));
}
catch (...) {} // Ignore deletion failures
}
void SHScriptEngine::deleteFolder(const std::string& filePath)
{
try
{
std::filesystem::remove_all(std::filesystem::canonical(filePath));
}
catch (...) {} // Ignore deletion failures
}
bool SHScriptEngine::fileExists(const std::string_view& filePath)
bool SHScriptEngine::fileExists(const std::filesystem::path& filePath)
{
std::error_code error;
if (std::filesystem::exists(filePath, error))
@ -483,8 +487,8 @@ namespace SHADE
DWORD status;
while (true)
{
const auto SUCCESS = GetExitCodeProcess(procInfo.hProcess, &status);
if (!SUCCESS)
const auto EXEC_SUCCESS = GetExitCodeProcess(procInfo.hProcess, &status);
if (!EXEC_SUCCESS)
{
auto err = GetLastError();
std::ostringstream oss;
@ -503,4 +507,12 @@ namespace SHADE
}
}
std::wstring SHScriptEngine::generateBuildCommand(bool debug)
{
std::wostringstream oss;
oss << "dotnet build \"" << SHStringUtils::StrToWstr(CSPROJ_PATH) << "\" -c ";
oss << debug ? "Debug" : "Release";
oss << " -o \"./tmp/\" -fl -flp:LogFile=build.log;Verbosity=quiet";
return oss.str();
}
}

View File

@ -15,10 +15,14 @@ of DigiPen Institute of Technology is prohibited.
#include <filesystem>
// Project Headers
#include "SH_API.h"
#include "SHDotNetRuntime.h"
#include "ECS_Base/SHECSMacros.h"
#include "ECS_Base/Entity/SHEntity.h"
#include "SH_API.h"
#include "ECS_Base/System/SHSystem.h"
#include "ECS_Base/System/SHSystemRoutine.h"
#include "Events/SHEventDefines.h"
#include "Events/SHEvent.h"
namespace SHADE
{
@ -26,13 +30,41 @@ namespace SHADE
/// Manages initialisation of the DotNetRuntime and interfacing with CLR code written
/// and executed on .NET.
/// </summary>
class SH_API SHScriptEngine
class SH_API SHScriptEngine final : public SHSystem
{
public:
/*-----------------------------------------------------------------------------*/
/* Type Definitions */
/*-----------------------------------------------------------------------------*/
class SH_API FrameSetUpRoutine final : public SHSystemRoutine
{
public:
FrameSetUpRoutine();
void Execute(double dt) noexcept override final;
};
class SH_API UpdateRoutine final : public SHSystemRoutine
{
public:
UpdateRoutine();
void Execute(double dt) noexcept override final;
};
class SH_API LateUpdateRoutine final : public SHSystemRoutine
{
public:
LateUpdateRoutine();
void Execute(double dt) noexcept override final;
};
class SH_API FrameCleanUpRoutine final : public SHSystemRoutine
{
public:
FrameCleanUpRoutine();
void Execute(double dt) noexcept override final;
};
/*-----------------------------------------------------------------------------*/
/* Constructor */
/*-----------------------------------------------------------------------------*/
SHScriptEngine() = delete;
SHScriptEngine() = default;
/*-----------------------------------------------------------------------------*/
/* Lifecycle Functions */
@ -41,33 +73,33 @@ namespace SHADE
/// Initialises the DotNetRuntime and retrieves function pointers to all
/// functions on the CLR used to interface with the engine.
/// </summary>
static void Init();
void Init() override;
/// <summary>
/// Loads the managed script assembly. Ensure this is only called after
/// UnloadScriptAssembly() has been called.
/// </summary>
static void UnloadScriptAssembly();
void UnloadScriptAssembly();
/// <summary>
/// Unloads the managed script assembly.
/// Take note that this will clear all existing scripts, ensure that the scene
/// is saved before doing so.
/// </summary>
static void LoadScriptAssembly();
void LoadScriptAssembly();
/// <summary>
/// Reloads the managed script assembly.
/// Take note that this will clear all existing scripts, ensure that the scene
/// is saved before doing so.
/// </summary>
static void ReloadScriptAssembly();
void ReloadScriptAssembly();
/// <summary>
/// Executes the FixedUpdate()s of the Scripts that are attached to
/// Entities.
/// </summary>
static void ExecuteFixedUpdates();
void ExecuteFixedUpdates();
/// <summary>
/// Shuts down the DotNetRuntime.
/// </summary>
static void Exit();
void Exit() override;
/*-----------------------------------------------------------------------------*/
/* Script Manipulation Functions */
@ -84,14 +116,14 @@ namespace SHADE
/// True if successfully added. False otherwise with the error logged to the
/// console.
/// </returns>
static bool AddScript(const SHEntity& entity, const std::string_view& scriptName);
bool AddScript(const SHEntity& entity, const std::string_view& scriptName);
/// <summary>
/// Removes all Scripts attached to the specified Entity. Does not do anything
/// if the specified Entity is invalid or does not have any Scripts
/// attached.
/// </summary>
/// <param name="entity">The entity to remove the scripts from.</param>
static void RemoveAllScripts(const SHEntity& entity);
void RemoveAllScripts(const SHEntity& entity);
/// <summary>
/// Removes all Scripts attached to the specified Entity. Unlike
/// RemoveAllScripts(), this removes all the scripts immediately.
@ -103,7 +135,7 @@ namespace SHADE
/// Whether or not to call OnDestroy on the scripts. This is ignored if not in
/// play mode.
/// </param>
static void RemoveAllScriptsImmediately(const SHEntity& entity, bool callOnDestroy);
void RemoveAllScriptsImmediately(const SHEntity& entity, bool callOnDestroy);
/*-----------------------------------------------------------------------------*/
/* Script Serialisation Functions */
@ -116,7 +148,7 @@ namespace SHADE
/// <returns>
/// String that represents the set of scripts attached to the specified Entity.
/// </returns>
static std::string SerialiseScripts(const SHEntity& entity);
std::string SerialiseScripts(const SHEntity& entity) const;
/// <summary>
/// Loads the specified JSON string and creates a Script for the specified Entity
/// based on the specified JSON string.
@ -125,7 +157,7 @@ namespace SHADE
/// <param name="yaml">
/// The YAML string that represents the Script to load into the Entity.
/// </param>
static void DeserialiseScript(const SHEntity& entity, const std::string& yaml);
void DeserialiseScript(const SHEntity& entity, const std::string& yaml) const;
/*-----------------------------------------------------------------------------*/
/* Script Editor Functions */
@ -138,7 +170,7 @@ namespace SHADE
/// rendering code.
/// </summary>
/// <param name="entity">The Entity to render the Scripts of.</param>
static void RenderScriptsInInspector(const SHEntity& entity);
void RenderScriptsInInspector(const SHEntity& entity) const;
/*-----------------------------------------------------------------------------*/
/* Static Utility Functions */
@ -153,12 +185,12 @@ namespace SHADE
/// can be debugged.
/// </param>
/// <returns>Whether or not the build succeeded.</returns>
static bool BuildScriptAssembly(bool debug = false);
bool BuildScriptAssembly(bool debug = false) const;
/// <summary>
/// Generates a .csproj file for editing and compiling the C# scripts.
/// </summary>
/// <param name="path">File path to the generated file.</param>
static void GenerateScriptsCsProjFile(const std::filesystem::path& path);
void GenerateScriptsCsProjFile(const std::filesystem::path& path) const;
private:
/*-----------------------------------------------------------------------------*/
@ -178,45 +210,56 @@ namespace SHADE
/*-----------------------------------------------------------------------------*/
static constexpr std::string_view DEFAULT_CSHARP_LIB_NAME = "SHADE_Managed";
static constexpr std::string_view MANAGED_SCRIPT_LIB_NAME = "SHADE_Scripting";
static const std::string CSPROJ_DIR;
static const std::string CSPROJ_PATH;
static const std::string DEFAULT_CSHARP_NAMESPACE;
/*-----------------------------------------------------------------------------*/
/* Data Members */
/*-----------------------------------------------------------------------------*/
static SHDotNetRuntime dotNet;
SHDotNetRuntime dotNet { false };
// Function Pointers to CLR Code
// - Engine Lifecycle
static CsFuncPtr csEngineInit;
static CsFuncPtr csEngineLoadScripts;
static CsFuncPtr csEngineUnloadScripts;
static CsFuncPtr csEngineReloadScripts;
static CsFuncPtr csEngineExit;
CsFuncPtr csEngineInit = nullptr;
CsFuncPtr csEngineLoadScripts = nullptr;
CsFuncPtr csEngineUnloadScripts = nullptr;
CsFuncPtr csEngineReloadScripts = nullptr;
CsFuncPtr csEngineExit = nullptr;
// - Scripts Store
static CsFuncPtr csScriptsFrameSetUp;
static CsFuncPtr csScriptsExecuteFixedUpdate;
static CsFuncPtr csScriptsExecuteUpdate;
static CsFuncPtr csScriptsExecuteLateUpdate;
static CsFuncPtr csScriptsFrameCleanUp;
static CsScriptManipFuncPtr csScriptsAdd;
static CsScriptBasicFuncPtr csScriptsRemoveAll;
static CsScriptOptionalFuncPtr csScriptsRemoveAllImmediately;
static CsScriptSerialiseFuncPtr csScriptsSerialise;
static CsScriptDeserialiseFuncPtr csScriptDeserialise;
static CsScriptSerialiseYamlFuncPtr csScriptsSerialiseYaml;
static CsScriptSerialiseYamlFuncPtr csScriptDeserialiseYaml;
CsFuncPtr csScriptsFrameSetUp = nullptr;
CsFuncPtr csScriptsExecuteFixedUpdate = nullptr;
CsFuncPtr csScriptsExecuteUpdate = nullptr;
CsFuncPtr csScriptsExecuteLateUpdate = nullptr;
CsFuncPtr csScriptsFrameCleanUp = nullptr;
CsScriptManipFuncPtr csScriptsAdd = nullptr;
CsScriptBasicFuncPtr csScriptsRemoveAll = nullptr;
CsScriptOptionalFuncPtr csScriptsRemoveAllImmediately = nullptr;
CsScriptSerialiseFuncPtr csScriptsSerialise = nullptr;
CsScriptDeserialiseFuncPtr csScriptDeserialise = nullptr;
CsScriptSerialiseYamlFuncPtr csScriptsSerialiseYaml = nullptr;
CsScriptSerialiseYamlFuncPtr csScriptDeserialiseYaml = nullptr;
// - Editor
static CsScriptEditorFuncPtr csEditorRenderScripts;
CsScriptEditorFuncPtr csEditorRenderScripts = nullptr;
// Delegates
/*ECS::EntityEvent::Delegate onEntityCreate;
ECS::EntityEvent::Delegate onEntityDestroy;*/
/*-----------------------------------------------------------------------------*/
/* Event Handler Functions */
/*-----------------------------------------------------------------------------*/
SHEventHandle onEntityDestroyed(SHEventPtr eventPtr);
/*-----------------------------------------------------------------------------*/
/* Helper Functions */
/*-----------------------------------------------------------------------------*/
/// <summary>
/// Loads all the function pointers to CLR code that we need to execute.
/// </summary>
static void loadFunctions();
void loadFunctions();
/// <summary>
/// Registers events for the scripting system
/// </summary>
void registerEvents();
/// <summary>
/// Reads the file via the specified path that represents a build log of error
/// and warning messages.
@ -230,18 +273,19 @@ namespace SHADE
/// Deletes the file as specified by the file path.
/// </summary>
/// <param name="filePath">File path to the file to delete.</param>
static void deleteFile(const std::string_view& filePath);
static void deleteFile(const std::string& filePath);
/// <summary>
/// Deletes the folder and all files in it as specified by the file path.
/// </summary>
/// <param name="filePath">File path to the file to delete.</param>
static void deleteFolder(const std::string_view& filePath);
static void deleteFolder(const std::string& filePath);
/// <summary>
/// Checks if a specified file exists.
/// </summary>
/// <param name="filePath">File path to the file to check.</param>
/// <returns> True if the file exists </returns>
static bool fileExists(const std::string_view& filePath);
static bool fileExists(const std::filesystem::path& filePath);
static DWORD execProcess(const std::wstring& path, const std::wstring& args);
static std::wstring generateBuildCommand(bool debug);
};
}

View File

@ -0,0 +1,63 @@
/************************************************************************************//*!
\file SHScriptEngineRoutines.cpp
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Sep 17, 2021
\brief Contains the implementation or functions of SystemRoutines in the
SHScriptEngine class.
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.
*//*************************************************************************************/
// Precompiled Headers
#include <SHpch.h>
// Primary Header
#include "SHScriptEngine.h"
namespace SHADE
{
/*-----------------------------------------------------------------------------------*/
/* System Routine Functions - FrameSetUpRoutine */
/*-----------------------------------------------------------------------------------*/
SHScriptEngine::FrameSetUpRoutine::FrameSetUpRoutine()
: SHSystemRoutine("Script Engine Frame Set Up", false)
{}
void SHScriptEngine::FrameSetUpRoutine::Execute(double) noexcept
{
reinterpret_cast<SHScriptEngine*>(system)->csScriptsFrameSetUp();
}
/*-----------------------------------------------------------------------------------*/
/* System Routine Functions - UpdateRoutine */
/*-----------------------------------------------------------------------------------*/
SHScriptEngine::UpdateRoutine::UpdateRoutine()
: SHSystemRoutine("Script Engine Update", false)
{}
void SHScriptEngine::UpdateRoutine::Execute(double) noexcept
{
reinterpret_cast<SHScriptEngine*>(system)->csScriptsExecuteUpdate();
}
/*-----------------------------------------------------------------------------------*/
/* System Routine Functions - LateUpdateRoutine */
/*-----------------------------------------------------------------------------------*/
SHScriptEngine::LateUpdateRoutine::LateUpdateRoutine()
: SHSystemRoutine("Script Engine Late Update", false)
{}
void SHScriptEngine::LateUpdateRoutine::Execute(double) noexcept
{
reinterpret_cast<SHScriptEngine*>(system)->csScriptsExecuteLateUpdate();
}
/*-----------------------------------------------------------------------------------*/
/* System Routine Functions - FrameCleanUpRoutine */
/*-----------------------------------------------------------------------------------*/
SHScriptEngine::FrameCleanUpRoutine::FrameCleanUpRoutine()
: SHSystemRoutine("Script Engine Frame Clean Up", false)
{}
void SHScriptEngine::FrameCleanUpRoutine::Execute(double) noexcept
{
reinterpret_cast<SHScriptEngine*>(system)->csScriptsFrameCleanUp();
}
}

View File

@ -0,0 +1,54 @@
/************************************************************************************//*!
\file SHLog.cpp
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Sep 17, 2022
\brief Contains the definition of functions of the SHLog static class.
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.
*//*************************************************************************************/
// Precompiled Header
#include "SHpch.h"
// Primary Header
#include "SHLog.h"
// Project Includes
#include "SHLogger.h"
namespace SHADE
{
void SHLog::Info(const std::string& msg) noexcept
{
SHLOG_INFO(msg)
}
void SHLog::Warning(const std::string& msg) noexcept
{
SHLOG_WARNING(msg)
}
void SHLog::Error(const std::string& msg) noexcept
{
SHLOG_ERROR(msg)
}
void SHLog::Critical(const std::string& msg) noexcept
{
SHLOG_CRITICAL(msg)
}
void SHLog::Floor() noexcept
{
SHLOG_FLOOR()
}
#ifdef _DEBUG
void SHLog::Trace(const std::string& msg) noexcept
{
SHLOG_TRACE(msg)
}
#endif
}

View File

@ -0,0 +1,48 @@
/************************************************************************************//*!
\file SHLog.h
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Sep 17, 2022
\brief Contains the SHLog static class.
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.
*//*************************************************************************************/
// Standard Library
#include <string>
// Project Headers
#include "SH_API.h"
namespace SHADE
{
/*!************************************************************************************
\class SHLog
\brief
Static class that contains wrapper functions for SHLogger's macros.
**************************************************************************************/
class SH_API SHLog
{
public:
/*---------------------------------------------------------------------------------*/
/* Constructor */
/*---------------------------------------------------------------------------------*/
SHLog() = delete;
/*---------------------------------------------------------------------------------*/
/* Logging Functions */
/*---------------------------------------------------------------------------------*/
static void Info(const std::string& msg) noexcept;
static void Warning(const std::string& msg) noexcept;
static void Error(const std::string& msg) noexcept;
static void Critical(const std::string& msg) noexcept;
static void Floor() noexcept;
#ifdef _DEBUG
static void Trace(const std::string& msg) noexcept;
#endif
};
}

View File

@ -21,6 +21,9 @@ of DigiPen Institute of Technology is prohibited.
#include <msclr\marshal_cppstd.h>
// External Dependencies
#include "ECS_Base/Managers/SHEntityManager.h"
#include "Scene/SHSceneManager.h"
#include "Scene/SHSceneGraph.h"
#include "Tools/SHLog.h"
// Project Headers
#include "Utility/Convert.hxx"
#include "Utility/Debug.hxx"
@ -124,27 +127,31 @@ namespace SHADE
return T();
}
// Get Transform component and get the children list
throw gcnew System::NotImplementedException;
//Pls::Transform* tf = Pls::ECS::GetComponent<Pls::Transform>(entity);
//if (tf == nullptr)
// return T();
// Get Entity's SceneGraphNode
SHSceneNode* sceneGraphNode = SHSceneManager::GetCurrentSceneGraph().GetNode(entity);
if (sceneGraphNode == nullptr)
{
std::ostringstream oss;
oss << "[ECS_CLI] Failed to retrieve SceneGraphNode of entity #" << entity << ". This should not happen!";
SHLog::Warning(oss.str());
return T();
}
//// Search direct children first
//for (const auto& child : tf->GetChildren())
//{
// T component = GetComponent<T>(child);
// if (component != nullptr)
// return component;
//}
// Search direct children first
for (const auto& child : sceneGraphNode->GetChildren())
{
T component = GetComponent<T>(child->GetEntityID());
if (component != nullptr)
return component;
}
//// Search their children
//for (const auto& child : tf->GetChildren())
//{
// T script = GetComponentInChildren<T>(child);
// if (script != nullptr)
// return script;
//}
// Search their children
for (const auto& child : sceneGraphNode->GetChildren())
{
T component = GetComponentInChildren<T>(child->GetEntityID());
if (component != nullptr)
return component;
}
// None here
return T();

View File

@ -56,7 +56,7 @@ namespace SHADE
}
bool GameObject::IsActiveInHierarchy::get()
{
throw gcnew System::NotImplementedException();
return true; // TODO: Update once we have an equivalent on the Entity object
}
/*---------------------------------------------------------------------------------*/

View File

@ -19,7 +19,7 @@ of DigiPen Institute of Technology is prohibited.
namespace SHADE
{
///<summary>
/// CLR version of the the PlushieEngine's Vector2 class that represents a
/// CLR version of the the SHADE Engine's Vector2 class that represents a
/// 2-Dimensional Vector. Designed to closely match Unity's Vector2 struct.
/// </summary>
[System::Runtime::InteropServices::StructLayout(System::Runtime::InteropServices::LayoutKind::Sequential)]

View File

@ -20,6 +20,7 @@ of DigiPen Institute of Technology is prohibited.
#include <sstream>
// External Dependencies
#include "ECS_Base/Managers/SHEntityManager.h"
#include "Tools/SHLog.h"
// Project Headers
#include "Utility/Debug.hxx"
#include "Utility/Convert.hxx"
@ -147,7 +148,6 @@ namespace SHADE
// Check if entity exists and is a valid GameObject
if (!EntityUtils::IsValid(entity))
throw gcnew System::ArgumentException("Invalid Entity provided to get a Script from.");
// Check if entity exists in the script storage
if (!scripts.ContainsKey(entity))
@ -155,27 +155,31 @@ namespace SHADE
return T();
}
// Get Transform component and get the children list
throw gcnew System::NotImplementedException;
//Pls::Transform* tf = Pls::ECS::GetComponent<Pls::Transform>(Convert::ToNative(entity));
//if (tf == nullptr)
// return T();
// Get Entity's SceneGraphNode
SHSceneNode* sceneGraphNode = SHSceneManager::GetCurrentSceneGraph().GetNode(entity);
if (sceneGraphNode == nullptr)
{
std::ostringstream oss;
oss << "[ECS_CLI] Failed to retrieve SceneGraphNode of entity #" << entity << ". This should not happen!";
SHLog::Warning(oss.str());
return T();
}
//// Search direct children first
//for (const auto& child : tf->GetChildren())
//{
// T script = GetScript<T>(Convert::ToCLI(child));
// if (script != nullptr)
// return script;
//}
// Search direct children first
for (const auto& child : sceneGraphNode->GetChildren())
{
T script = GetScript<T>(child->GetEntityID());
if (script != nullptr)
return script;
}
//// Search their children
//for (const auto& child : tf->GetChildren())
//{
// T script = GetScriptInChildren<T>(Convert::ToCLI(child));
// if (script != nullptr)
// return script;
//}
// Search their children
for (const auto& child : sceneGraphNode->GetChildren())
{
T script = GetScript<T>(child->GetEntityID());
if (script != nullptr)
return script;
}
// None here
return T();
@ -232,7 +236,6 @@ namespace SHADE
// Check if entity exists
if (!EntityUtils::IsValid(entity))
throw gcnew System::ArgumentException("Invalid Entity provided to remove a Script from.");
// Check if entity exists in the script storage
if (!scripts.ContainsKey(entity))
@ -263,8 +266,7 @@ namespace SHADE
Debug::LogError("[ScriptStore] Attempted to remove a Script from an invalid Entity!");
return false;
}
// Check if entity exists in the script storage
if (!scripts.ContainsKey(entity))
{
@ -285,14 +287,7 @@ namespace SHADE
}
void ScriptStore::RemoveAllScripts(Entity entity)
{
SAFE_NATIVE_CALL_BEGIN
// Check if entity exists
if (!EntityUtils::IsValid(entity))
{
Debug::LogError("[ScriptStore] Attempted to remove Scripts from an invalid Entity!");
return;
}
SAFE_NATIVE_CALL_BEGIN
// Check if entity exists in the script storage
if (!scripts.ContainsKey(entity))
return;
@ -309,13 +304,6 @@ namespace SHADE
void ScriptStore::RemoveAllScriptsImmediately(Entity entity, bool callOnDestroy)
{
SAFE_NATIVE_CALL_BEGIN
// Check if entity exists
if (!EntityUtils::IsValid(entity))
{
Debug::LogError("[ScriptStore] Attempted to remove Scripts from an invalid Entity!");
return;
}
// Check if entity exists in the script storage
if (!scripts.ContainsKey(entity))
return;
@ -384,10 +372,7 @@ namespace SHADE
while (disposalQueue.Count > 0)
{
Script^ script = disposalQueue.Dequeue();
/*if (Application::IsPlaying)
{
script->OnDestroy();
}*/
script->OnDestroy();
auto entity = script->Owner.GetEntity();
auto scriptList = scripts[script->Owner.GetEntity()];
scriptList->Remove(script);
@ -494,7 +479,6 @@ namespace SHADE
// Check if entity exists, otherwise nothing
if (!EntityUtils::IsValid(entity))
return true;
// Check if entity exists in the script storage
if (!scripts.ContainsKey(entity))
@ -665,7 +649,7 @@ namespace SHADE
// Entity Validity Check
if (nativeEntity == nullptr)
throw gcnew System::InvalidOperationException("Attempted to get native Component to an invalid Entity.");
return false;
// Check active state
return nativeEntity->GetActive();

View File

@ -0,0 +1,242 @@
/************************************************************************************//*!
\file ReflectionUtilities.cxx
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Nov 6, 2021
\brief Contains the definition of the functions for the ReflectionUtilities
managed static class.
Note: This file is written in C++17/CLI.
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.
*//*************************************************************************************/
// Precompiled Headers
#include "SHpch.h"
// Primary Header
#include "Serialisation/ReflectionUtilities.hxx"
// Project Includes
#include "SerializeFieldAttribute.hxx"
#include "Utility/Convert.hxx"
#include "Math/Vector2.hxx"
#include "Math/Vector3.hxx"
#include "Utility/Debug.hxx"
/*-------------------------------------------------------------------------------------*/
/* Macro Functions */
/*-------------------------------------------------------------------------------------*/
/// <summary>
/// Macro expansion that is used in RapidJsonValueToField() to retrieve the specified
/// member of a Vector type that is stored into a Vector named "vec".
/// </summary>
/// <param name="MEMBER">The name of the member to retrieve.</param>
#define PRIMITIVE_VECTOR_FIELD_ASSIGN(MEMBER) \
iter = jsonValue.FindMember(#MEMBER); \
if (iter != jsonValue.MemberEnd()) \
{ \
vec.MEMBER = iter->value.GetDouble(); \
} \
/*-------------------------------------------------------------------------------------*/
/* Function Definitions */
/*-------------------------------------------------------------------------------------*/
namespace SHADE
{
System::Collections::Generic::IEnumerable<System::Reflection::FieldInfo^>^ ReflectionUtilities::GetInstanceFields(System::Object^ object)
{
using namespace System::Reflection;
return object->GetType()->GetFields
(
BindingFlags::Public | BindingFlags::NonPublic | BindingFlags::Instance
);
}
bool ReflectionUtilities::FieldIsSerialisable(System::Reflection::FieldInfo^ fieldInfo)
{
return fieldInfo->IsPublic || fieldInfo->GetCustomAttributes(SerializeField::typeid, true)->Length > 0;
}
/*---------------------------------------------------------------------------------*/
/* Serialisation Functions */
/*---------------------------------------------------------------------------------*/
void ReflectionUtilities::Serialise(System::Object^ object, YAML::Emitter& yaml)
{
using namespace System::Reflection;
// Create YAML object
yaml << YAML::Key << Convert::ToNative(object->GetType()->FullName);
yaml << YAML::BeginMap;
// Get all fields
System::Collections::Generic::IEnumerable<FieldInfo^>^ fields = GetInstanceFields(object);
for each (FieldInfo^ field in fields)
{
// Ignore private and non-SerialiseField
if (!FieldIsSerialisable(field))
continue;
// Serialise
writeFieldIntoYaml(field, object, yaml);
}
yaml << YAML::EndMap;
}
void ReflectionUtilities::Deserialise(YAML::Node& yamlNode, Object^ object)
{
using namespace System::Reflection;
// Load the YAML
if (!yamlNode.IsMap())
{
// Invalid
Debug::LogError
(
System::String::Format("[ReflectionUtilities] Invalid YAML Node provided for deserialization of \"{0}\" script.",
object->GetType()->FullName)
);
return;
}
// Get all fields
System::Collections::Generic::IEnumerable<FieldInfo^>^ fields = GetInstanceFields(object);
for each (FieldInfo^ field in fields)
{
// Ignore private and non-SerialiseField
if (!FieldIsSerialisable(field))
continue;
// Deserialise
const std::string FIELD_NAME = Convert::ToNative(field->Name);
if (yamlNode[FIELD_NAME])
{
writeYamlIntoField(field, object, yamlNode[FIELD_NAME]);
}
}
}
/*---------------------------------------------------------------------------------*/
/* Serialization Helper Functions */
/*---------------------------------------------------------------------------------*/
void ReflectionUtilities::writeFieldIntoYaml(System::Reflection::FieldInfo^ fieldInfo, Object^ object, YAML::Emitter& yaml)
{
// Field Name
yaml << YAML::Key << Convert::ToNative(fieldInfo->Name);
// Field Value
yaml << YAML::Value;
if (fieldInsertYaml<System::Int16> (fieldInfo, object, yaml) ||
fieldInsertYaml<System::Int32> (fieldInfo, object, yaml) ||
fieldInsertYaml<System::Int64> (fieldInfo, object, yaml) ||
fieldInsertYaml<System::UInt16>(fieldInfo, object, yaml) ||
fieldInsertYaml<System::UInt32>(fieldInfo, object, yaml) ||
fieldInsertYaml<System::UInt64>(fieldInfo, object, yaml) ||
fieldInsertYaml<System::Byte> (fieldInfo, object, yaml) ||
fieldInsertYaml<bool> (fieldInfo, object, yaml) ||
fieldInsertYaml<float> (fieldInfo, object, yaml) ||
fieldInsertYaml<double> (fieldInfo, object, yaml))
{
return;
}
else if (fieldInfo->FieldType->IsSubclassOf(System::Enum::typeid))
{
yaml << safe_cast<int>(fieldInfo->GetValue(object));
}
else if (fieldInfo->FieldType == System::String::typeid)
{
System::String^ str = safe_cast<System::String^>(fieldInfo->GetValue(object));
yaml << Convert::ToNative(str);
}
else if (fieldInfo->FieldType == Vector2::typeid)
{
Vector2 vec = safe_cast<Vector2>(fieldInfo->GetValue(object));
yaml << YAML::BeginSeq << YAML::Flow << vec.x << vec.y << YAML::EndSeq;
}
else if (fieldInfo->FieldType == Vector3::typeid)
{
Vector3 vec = safe_cast<Vector3>(fieldInfo->GetValue(object));
yaml << YAML::BeginSeq << YAML::Flow << vec.x << vec.y << vec.z << YAML::EndSeq;
}
else // Not any of the supported types
{
Debug::LogWarning(Convert::ToNative(System::String::Format
(
"[ReflectionUtilities] Failed to parse \"{0}\" of \"{1}\" type for serialization.",
fieldInfo->Name, fieldInfo->FieldType)
));
}
}
void ReflectionUtilities::writeYamlIntoField(System::Reflection::FieldInfo^ fieldInfo, Object^ object, YAML::Node& node)
{
if (fieldInfo->FieldType == System::Int16::typeid)
{
fieldInfo->SetValue(object, node.as<int>());
}
if (fieldAssignYaml<System::Int16> (fieldInfo, object, node) ||
fieldAssignYaml<System::Int32> (fieldInfo, object, node) ||
fieldAssignYaml<System::Int64> (fieldInfo, object, node) ||
fieldAssignYaml<System::UInt16>(fieldInfo, object, node) ||
fieldAssignYaml<System::UInt32>(fieldInfo, object, node) ||
fieldAssignYaml<System::UInt64>(fieldInfo, object, node) ||
fieldAssignYaml<System::Byte> (fieldInfo, object, node) ||
fieldAssignYaml<bool> (fieldInfo, object, node) ||
fieldAssignYaml<float> (fieldInfo, object, node) ||
fieldAssignYaml<double> (fieldInfo, object, node))
{
return;
}
else if (fieldInfo->FieldType->IsSubclassOf(System::Enum::typeid))
{
fieldInfo->SetValue(object, node.as<int>());
}
else if (fieldInfo->FieldType == System::String::typeid)
{
fieldInfo->SetValue(object, Convert::ToCLI(node.as<std::string>()));
}
else if (fieldInfo->FieldType == Vector2::typeid)
{
if (node.IsSequence() && node.size() == 2)
{
Vector2 vec;
vec.x = node[0].as<float>();
vec.y = node[1].as<float>();
fieldInfo->SetValue(object, vec);
}
else
{
Debug::LogWarning
(
System::String::Format("[ReflectionUtilities] Invalid YAML Node provided for deserialization of a Vector2 \"{0}\" field in \"{1}\" script.",
fieldInfo->Name, object->GetType()->FullName)
);
}
}
else if (fieldInfo->FieldType == Vector3::typeid)
{
if (node.IsSequence() && node.size() == 3)
{
Vector3 vec;
vec.x = node[0].as<float>();
vec.y = node[1].as<float>();
vec.z = node[2].as<float>();
fieldInfo->SetValue(object, vec);
}
else
{
Debug::LogWarning
(
System::String::Format("[ReflectionUtilities] Invalid YAML Node provided for deserialization of a Vector3 \"{0}\" field in \"{1}\" script.",
fieldInfo->Name, object->GetType()->FullName)
);
}
}
else // Not any of the supported types
{
Debug::LogWarning(Convert::ToNative(System::String::Format
(
"[ReflectionUtilities] Failed to parse \"{0}\" of \"{1}\" type for deserialisation.",
fieldInfo->Name, fieldInfo->FieldType)
));
}
}
}

View File

@ -0,0 +1,54 @@
/************************************************************************************//*!
\file ReflectionUtilities.h++
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Sep 16, 2022
\brief Contains the definition of the template functions of the managed
ReflectionUtilities static class.
Note: This file is written in C++17/CLI.
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
// Primary Header
#include "ReflectionUtilities.hxx"
namespace SHADE
{
/*---------------------------------------------------------------------------------*/
/* Serialization Helper Functions */
/*---------------------------------------------------------------------------------*/
template<typename FieldType>
bool ReflectionUtilities::fieldInsertYaml(System::Reflection::FieldInfo^ fieldInfo, System::Object^ object, YAML::Emitter& emitter)
{
if (fieldInfo->FieldType == FieldType::typeid)
{
emitter << safe_cast<FieldType>(fieldInfo->GetValue(object));
return true;
}
return false;
}
template<typename FieldType>
bool ReflectionUtilities::fieldAssignYaml(System::Reflection::FieldInfo^ fieldInfo, Object^ object, YAML::Node& node)
{
return fieldAssignYaml<FieldType, FieldType>(fieldInfo, object, node);
}
template<typename FieldType, typename CastType>
bool ReflectionUtilities::fieldAssignYaml(System::Reflection::FieldInfo^ fieldInfo, Object^ object, YAML::Node& node)
{
if (fieldInfo->FieldType == FieldType::typeid)
{
fieldInfo->SetValue(object, node.as<CastType>());
return true;
}
return false;
}
}

View File

@ -0,0 +1,81 @@
/************************************************************************************//*!
\file ReflectionUtilities.hxx
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Nov 6, 2021
\brief Contains the definition of the managed ReflectionUtilities static class.
Note: This file is written in C++17/CLI.
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.
*//*************************************************************************************/
#pragma once
// External Dependencies
#include <yaml-cpp/yaml.h>
namespace SHADE
{
/// <summary>
/// Contains useful static functions for working with Reflection.
/// </summary>
private ref class ReflectionUtilities abstract sealed
{
public:
/*-----------------------------------------------------------------------------*/
/* Utility Functions */
/*-----------------------------------------------------------------------------*/
/// <summary>
/// Retrieves a set of all non-static (instance) fields from a specified object.
/// </summary>
/// <param name="object">The object to get non-static fields from.</param>
/// <returns>Immutable list of non-static fields.</returns>
static System::Collections::Generic::IEnumerable<System::Reflection::FieldInfo^>^ GetInstanceFields(System::Object^ object);
/// <summary>
/// Checks if a specified field is a candidate for serialisation. This means that
/// the field is public or private with the [SerialiseField] attribute.
/// </summary>
/// <param name="fieldInfo">The field to check.</param>
/// <returns>
/// True if the specified field is a candidate for serialisation.
/// </returns>
static bool FieldIsSerialisable(System::Reflection::FieldInfo^ fieldInfo);
/*-----------------------------------------------------------------------------*/
/* Serialisation Functions */
/*-----------------------------------------------------------------------------*/
/// <summary>
/// Creates a JSON node that represents the specified object and its associated
/// serialisable fields. Public fields and fields marked with the SerialiseField
/// attribute will be serialised.
/// </summary>
/// <param name="object">The object to serialise.</param>
static void Serialise(System::Object^ object, YAML::Emitter& yaml);
/// <summary>
/// Deserialises a YAML node that contains a map of Scripts and copies the
/// deserialised data into the specified object if there are matching fields.
/// </summary>
/// <param name="yamlNode">
/// The JSON string that contains the data to copy into this PlushieScript
/// object.
/// </param>
/// <param name="object">The object to copy deserialised data into.</param>
static void Deserialise(YAML::Node& yamlNode, Object^ object);
/*-----------------------------------------------------------------------------*/
/* Serialization Helper Functions */
/*-----------------------------------------------------------------------------*/
static void writeFieldIntoYaml(System::Reflection::FieldInfo^ fieldInfo, Object^ object, YAML::Emitter& yaml);
template<typename FieldType>
static bool fieldInsertYaml(System::Reflection::FieldInfo^ fieldInfo, System::Object^ object, YAML::Emitter& emitter);
static void writeYamlIntoField(System::Reflection::FieldInfo^ fieldInfo, Object^ object, YAML::Node& node);
template<typename FieldType>
static bool fieldAssignYaml(System::Reflection::FieldInfo^ fieldInfo, Object^ object, YAML::Node& node);
template<typename FieldType, typename CastType>
static bool fieldAssignYaml(System::Reflection::FieldInfo^ fieldInfo, Object^ object, YAML::Node& node);
};
}
#include "ReflectionUtilities.h++"

View File

@ -0,0 +1,27 @@
/************************************************************************************//*!
\file SerializeFieldAttribute.cxx
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Nov 5, 2021
\brief Contains the definition of the functions of the managed SerializeField
Attribute class.
Note: This file is written in C++17/CLI.
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.
*//*************************************************************************************/
// Precompiled Headers
#include "SHpch.h"
// Primary Header
#include "SerializeFieldAttribute.hxx"
namespace SHADE
{
/*---------------------------------------------------------------------------------*/
/* Constructors */
/*---------------------------------------------------------------------------------*/
SerializeField::SerializeField()
{}
}

View File

@ -0,0 +1,35 @@
/************************************************************************************//*!
\file SerializeFieldAttribute.hxx
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Nov 5, 2021
\brief Contains the definition of the managed SerializeField Attribute class with
the declaration of functions for working with it.
Note: This file is written in C++17/CLI.
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.
*//*************************************************************************************/
#pragma once
namespace SHADE
{
/// <summary>
/// Simple attribute to mark that a field in a Script should be serialised.
/// </summary>
[System::AttributeUsage(System::AttributeTargets::Field)]
public ref class SerializeField : public System::Attribute
{
public:
/*-----------------------------------------------------------------------------*/
/* Constructors */
/*-----------------------------------------------------------------------------*/
/// <summary>
/// Default Constructor
/// </summary>
SerializeField();
};
}

View File

@ -18,6 +18,8 @@ of DigiPen Institute of Technology is prohibited.
#include "Debug.hxx"
// Standard Libraries
#include <sstream>
// External Libraries
#include "Tools/SHLog.h"
// Project Headers
#include "Convert.hxx"
@ -28,11 +30,11 @@ namespace SHADE
/*---------------------------------------------------------------------------------*/
void Debug::Log(const std::string& str)
{
std::cout << str << std::endl;
SHLog::Info(str);
}
void Debug::Log(System::String^ str)
{
System::Console::WriteLine(str);
{
SHLog::Info(Convert::ToNative(str));
}
void Debug::Log(System::String^ str, Object^ owner)
@ -47,15 +49,15 @@ namespace SHADE
{
std::ostringstream oss;
oss << "[" << throwerName << "] " << Convert::ToNative(str);
std::cout << oss.str() << std::endl;
Log(oss.str());
}
void Debug::LogWarning(const std::string& str)
{
std::cout << str << std::endl;
SHLog::Warning(str);
}
void Debug::LogWarning(System::String^ str)
{
System::Console::WriteLine(str);
{
SHLog::Warning(Convert::ToNative(str));
}
void Debug::LogWarning(System::String^ str, Object^ thrower)
{
@ -69,16 +71,16 @@ namespace SHADE
void Debug::LogWarning(System::String^ str, const std::string& throwerName)
{
std::ostringstream oss;
oss << "[" << throwerName << "] " << Convert::ToNative(str);
std::cout << oss.str() << std::endl;
oss << "[" << throwerName << "] " << Convert::ToNative(str);
LogWarning(oss.str());
}
void Debug::LogError(const std::string& str)
{
std::cout << str << std::endl;
SHLog::Error(str);
}
void Debug::LogError(System::String^ str)
{
System::Console::WriteLine(str);
SHLog::Error(Convert::ToNative(str));
}
void Debug::LogError(System::String^ str, Object^ thrower)
{
@ -88,7 +90,7 @@ namespace SHADE
{
std::ostringstream oss;
oss << "[" << throwerName << "] -> " << Convert::ToNative(str);
std::cout << oss.str() << std::endl;
LogError(oss.str());
}
void Debug::LogError(System::String^ str, System::String^ throwerName)
{
@ -111,12 +113,12 @@ namespace SHADE
{
std::ostringstream oss;
oss << "[" << throwerName << "] Unhandled exception: " << Convert::ToNative(exception->ToString());
std::cout << oss.str() << std::endl;
LogError(oss.str());
}
void Debug::LogExceptionNative(const std::exception& exception, const std::string& throwerName)
{
std::ostringstream oss;
oss << "[" << throwerName << "] Unhandled exception: " << exception.what();
std::cout << oss.str() << std::endl;
LogError(oss.str());
}
}

View File

@ -0,0 +1,23 @@
using SHADE;
public class TestScript : Script
{
public TestScript(GameObject gameObj) : base(gameObj) {}
protected override void awake()
{
Debug.Log("TestScript.Awake()");
}
protected override void start()
{
Debug.Log("TestScript.Start()");
}
protected override void update()
{
Debug.Log("TestScript.Update()");
}
protected override void onDestroy()
{
Debug.Log("TestScript.OnDestroy()");
}
}