From b674805547ddf16414176e6c502ad9712048f82e Mon Sep 17 00:00:00 2001 From: Kah Wei Date: Tue, 13 Sep 2022 13:51:11 +0800 Subject: [PATCH] Added ECS and Component classes for SHADE_Managed --- SHADE_Engine/src/Scripting/SHScriptEngine.cpp | 18 -- SHADE_Engine/src/Scripting/SHScriptEngine.h | 5 +- SHADE_Managed/SHADE_Managed.vcxproj.filters | 23 ++ SHADE_Managed/src/Components/Component.cxx | 107 ++++++++ SHADE_Managed/src/Components/Component.h++ | 41 +++ SHADE_Managed/src/Components/Component.hxx | 200 ++++++++++++++ SHADE_Managed/src/Engine/ECS.cxx | 255 ++++++++++++++++++ SHADE_Managed/src/Engine/ECS.h++ | 60 +++++ SHADE_Managed/src/Engine/ECS.hxx | 174 ++++++++++++ SHADE_Managed/src/Scripts/ScriptStore.cxx | 52 ++-- 10 files changed, 883 insertions(+), 52 deletions(-) create mode 100644 SHADE_Managed/src/Components/Component.cxx create mode 100644 SHADE_Managed/src/Components/Component.h++ create mode 100644 SHADE_Managed/src/Components/Component.hxx create mode 100644 SHADE_Managed/src/Engine/ECS.cxx create mode 100644 SHADE_Managed/src/Engine/ECS.h++ create mode 100644 SHADE_Managed/src/Engine/ECS.hxx diff --git a/SHADE_Engine/src/Scripting/SHScriptEngine.cpp b/SHADE_Engine/src/Scripting/SHScriptEngine.cpp index 5f816066..d40605e4 100644 --- a/SHADE_Engine/src/Scripting/SHScriptEngine.cpp +++ b/SHADE_Engine/src/Scripting/SHScriptEngine.cpp @@ -60,12 +60,6 @@ namespace SHADE csEngineInit(); // Link events - // - Entity Creation - /*onEntityCreate = [this](const SHEntity& e) - { - csGOLibNotifyNewEntity(e.GetEID()); - }; - ECS::OnEntityCreated += onEntityCreate;*/ // - Entity Destruction /*onEntityDestroy = [this](const SHEntity& e) { @@ -384,18 +378,6 @@ namespace SHADE DEFAULT_CSHARP_NAMESPACE + ".ScriptStore", "DeserialiseScript" ); - csGOLibNotifyNewEntity = dotNet.GetFunctionPtr - ( - DEFAULT_CSHARP_LIB_NAME, - DEFAULT_CSHARP_NAMESPACE + ".GameObjectLibrary", - "NotifyNewGameObject" - ); - csGOLibNotifyDestroyEntity = dotNet.GetFunctionPtr - ( - DEFAULT_CSHARP_LIB_NAME, - DEFAULT_CSHARP_NAMESPACE + ".GameObjectLibrary", - "NotifyDestroyGameObject" - ); csEditorRenderScripts = dotNet.GetFunctionPtr ( DEFAULT_CSHARP_LIB_NAME, diff --git a/SHADE_Engine/src/Scripting/SHScriptEngine.h b/SHADE_Engine/src/Scripting/SHScriptEngine.h index bd9fb079..8182da5a 100644 --- a/SHADE_Engine/src/Scripting/SHScriptEngine.h +++ b/SHADE_Engine/src/Scripting/SHScriptEngine.h @@ -212,9 +212,6 @@ namespace SHADE CsScriptDeserialiseFuncPtr csScriptDeserialise = nullptr; CsScriptSerialiseJsonFuncPtr csScriptsSerialiseJson = nullptr; CsScriptSerialiseJsonFuncPtr csScriptDeserialiseJson = nullptr; - // - GameObject Library - CsScriptBasicFuncPtr csGOLibNotifyNewEntity = nullptr; - CsScriptBasicFuncPtr csGOLibNotifyDestroyEntity = nullptr; // - Editor CsScriptEditorFuncPtr csEditorRenderScripts = nullptr; // Delegates @@ -255,4 +252,4 @@ namespace SHADE static bool fileExists(const std::string_view& filePath); static DWORD execProcess(const std::wstring& path, const std::wstring& args); }; -} // namespace PlushieEngine +} diff --git a/SHADE_Managed/SHADE_Managed.vcxproj.filters b/SHADE_Managed/SHADE_Managed.vcxproj.filters index 776142d3..c1901bac 100644 --- a/SHADE_Managed/SHADE_Managed.vcxproj.filters +++ b/SHADE_Managed/SHADE_Managed.vcxproj.filters @@ -1,6 +1,9 @@ + + {6B7DD516-5735-1764-C03C-F0BFAC13B254} + {DBC7D3B0-C769-FE86-B024-12DB9C6585D7} @@ -15,6 +18,12 @@ + + Components + + + Engine + Engine @@ -52,6 +61,12 @@ + + Components + + + Engine + Engine @@ -87,4 +102,12 @@ Utility + + + Components + + + Engine + + \ No newline at end of file diff --git a/SHADE_Managed/src/Components/Component.cxx b/SHADE_Managed/src/Components/Component.cxx new file mode 100644 index 00000000..ccb056c2 --- /dev/null +++ b/SHADE_Managed/src/Components/Component.cxx @@ -0,0 +1,107 @@ +/************************************************************************************//*! +\file Component.cxx +\author Tng Kah Wei, kahwei.tng, 390009620 +\par email: kahwei.tng\@digipen.edu +\date Oct 27, 2021 +\brief Contains the definition of the functions for the Component 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 "Components/Component.hxx" +// External Dependencies +#include "Engine/ECS.hxx" +// Project Headers +#include "Scripts/ScriptStore.hxx" + +namespace SHADE +{ + /*---------------------------------------------------------------------------------*/ + /* Component Access Functions */ + /*---------------------------------------------------------------------------------*/ + generic + T BaseComponent::AddComponent() + { + return ECS::AddComponent(owner.GetNativeEntity()); + } + generic + T BaseComponent::GetComponent() + { + return ECS::GetComponent(owner.GetNativeEntity()); + } + generic + void BaseComponent::RemoveComponent() + { + ECS::RemoveComponent(owner.GetNativeEntity()); + } + + /*---------------------------------------------------------------------------------*/ + /* Script Access Functions */ + /*---------------------------------------------------------------------------------*/ + generic + T BaseComponent::AddScript() + { + return ScriptStore::AddScript(owner.GetEntity()); + } + generic + T BaseComponent::GetScript() + { + return ScriptStore::GetScript(owner.GetEntity()); + } + + generic + System::Collections::Generic::IEnumerable^ BaseComponent::GetScripts() + { + return ScriptStore::GetScripts(owner.GetEntity()); + } + + generic + void BaseComponent::RemoveScript() + { + ScriptStore::RemoveScript(owner.GetEntity()); + } + + /*---------------------------------------------------------------------------------*/ + /* Constructors */ + /*---------------------------------------------------------------------------------*/ + BaseComponent::BaseComponent(Entity entity) + : owner { entity } + {} + + /*---------------------------------------------------------------------------------*/ + /* IEquatable */ + /*---------------------------------------------------------------------------------*/ + bool BaseComponent::Equals(BaseComponent^ other) + { + if (other == nullptr) + return false; + return owner == other->owner; + } + + /*---------------------------------------------------------------------------------*/ + /* Object */ + /*---------------------------------------------------------------------------------*/ + bool BaseComponent::Equals(Object^ o) + { + try + { + BaseComponent^ cmp = safe_cast(o); + return Equals(cmp); + } + catch (System::InvalidCastException^) + { + return false; + } + } + + int BaseComponent::GetHashCode() + { + return owner.GetHashCode(); + } +} diff --git a/SHADE_Managed/src/Components/Component.h++ b/SHADE_Managed/src/Components/Component.h++ new file mode 100644 index 00000000..e2a20998 --- /dev/null +++ b/SHADE_Managed/src/Components/Component.h++ @@ -0,0 +1,41 @@ +/************************************************************************************//*! +\file Component.h++ +\author Tng Kah Wei, kahwei.tng, 390009620 +\par email: kahwei.tng\@digipen.edu +\date Oct 27, 2021 +\brief Contains the definition of templated functions for the managed Component + classes. + + 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 + +// Primary Include +#include "Component.hxx" +// Project includes +#include "Utility/Convert.hxx" +#include "Engine/ECS.hxx" + +namespace SHADE +{ + /*---------------------------------------------------------------------------------*/ + /* Constructors */ + /*---------------------------------------------------------------------------------*/ + template + Component::Component(Entity entity) + : BaseComponent { entity } + {} + + /*---------------------------------------------------------------------------------*/ + /* Helper Functions */ + /*---------------------------------------------------------------------------------*/ + template + typename Component::NativeComponent* Component::GetNativeComponent() + { + return ECS::GetNativeComponent(owner.GetEntity()); + } +} diff --git a/SHADE_Managed/src/Components/Component.hxx b/SHADE_Managed/src/Components/Component.hxx new file mode 100644 index 00000000..4f8e5bab --- /dev/null +++ b/SHADE_Managed/src/Components/Component.hxx @@ -0,0 +1,200 @@ +/************************************************************************************//*! +\file Component.hxx +\author Tng Kah Wei, kahwei.tng, 390009620 +\par email: kahwei.tng\@digipen.edu +\date Oct 27, 2021 +\brief Contains the definition of the managed Component classes 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 + +// External Dependencies +#include "Engine/ECS_Base/Components/SHComponent.h" +// Project Includes +#include "Engine/Entity.hxx" +#include "Scripts/Script.hxx" + +namespace SHADE +{ + /// + /// Class that serves as the base for a wrapper class to Components in native code. + /// + public ref class BaseComponent : public System::IEquatable + { + public: + /*-----------------------------------------------------------------------------*/ + /* Properties */ + /*-----------------------------------------------------------------------------*/ + /// + /// Retrieves the GameObject that this Component belongs to. + /// + property GameObject Owner + { + GameObject get() { return owner; } + } + + /*-----------------------------------------------------------------------------*/ + /* Component Access Functions */ + /*-----------------------------------------------------------------------------*/ + /// + /// Adds a Component to this GameObject. + /// + /// Type of the Component to add. + /// Reference to the Component that was added. + generic where T : BaseComponent + T AddComponent(); + /// + /// Gets a Component from this GameObject. + /// + /// Type of the Component to get. + /// + /// Reference to the Component or null if this GameObject does not have the + /// specified Component. + /// + generic where T : BaseComponent + T GetComponent(); + /// + /// Removes a Component from this GameObject. If no Component exists to begin + /// with, nothing happens. + /// + /// Type of the Component to get. + generic where T : BaseComponent + void RemoveComponent(); + + /*-----------------------------------------------------------------------------*/ + /* Script Access Functions */ + /*-----------------------------------------------------------------------------*/ + /// + /// Adds a PlushieScript of the specified type to this GameObject. + /// + /// Type of PlushieScript to add. + /// Reference to the created PlushieScript. + generic where T : ref class, PlushieScript + T AddScript(); + /// + /// Retrieves a PlushieScript of the specified type from this GameObject. + /// If multiple PlushieScripts of the same specified type are added on the same + /// GameObject, this will retrieve the first one added. + /// + /// Type of PlushieScript to add. + /// Reference to the PlushieScript to retrieve. + generic where T : ref class, PlushieScript + T GetScript(); + /// + /// Retrieves a immutable list of PlushieScripts of the specified type from this + /// GameObject. + /// + /// Type of PlushieScripts to Get. + /// Immutable list of PlushieScripts of the specified type. + generic where T : ref class, PlushieScript + System::Collections::Generic::IEnumerable^ GetScripts(); + /// + /// Removes all PlushieScripts of the specified type from this GameObject. + /// + /// Type of PLushieScripts to remove. + generic where T : ref class, PlushieScript + void RemoveScript(); + + protected: + /*-----------------------------------------------------------------------------*/ + /* Constructors */ + /*-----------------------------------------------------------------------------*/ + /// + /// Constructor for BaseComponent to tie it to a specific Entity. + /// Constructors of derived Components should call this Constructor. + /// + /// Entity that this Component will be tied to. + BaseComponent(Entity entity); + + /*-----------------------------------------------------------------------------*/ + /* Data Members */ + /*-----------------------------------------------------------------------------*/ + /// + /// Entity that this Component belongs to. + /// + GameObject owner; + + public: + /*-----------------------------------------------------------------------------*/ + /* IEquatable */ + /*-----------------------------------------------------------------------------*/ + /// + /// Compares equality with an object of the same type. + /// + /// The object to compare with. + /// True if both objects are the same. + virtual bool Equals(BaseComponent^ other); + + /*-----------------------------------------------------------------------------*/ + /* Object */ + /*-----------------------------------------------------------------------------*/ + /// + /// Compares equality with another unboxed object. + /// + /// The unboxed object to compare with. + /// True if both objects are the same. + bool Equals(Object^ o) override; + /// + /// Gets a unique hash for this object. + /// + /// Unique hash for this object. + int GetHashCode() override; + }; + + /// + /// C++ template for the BaseComponent class used to generate common template-able + /// functions and types. + /// + /// + /// Type of the native component that this Component wraps. + /// + template + public ref class Component : public BaseComponent + { + internal: + /*-----------------------------------------------------------------------------*/ + /* Type Definitions */ + /*-----------------------------------------------------------------------------*/ + /// + /// Type of the native component that this Component wraps. + /// + using NativeComponent = NativeType; + + /*-----------------------------------------------------------------------------*/ + /* Helper Functions */ + /*-----------------------------------------------------------------------------*/ + /// + /// Retrieves a pointer to the native unmanaged component that is tied to the + /// Entity described by the owner value. + /// + /// + /// Pointer to the native component. Will be nullptr if it does not exist. + /// + /// + /// Thrown if the internal ID stored by this native component is invalid. + /// + /// + /// Thrown if an attempt to retrieve the native component fails. + /// + NativeComponent* GetNativeComponent(); + + protected: + /*-----------------------------------------------------------------------------*/ + /* Constructors */ + /*-----------------------------------------------------------------------------*/ + /// + /// Constructor for Component to tie it to a specific Entity. + /// Constructors of derived Components should call this Constructor. + /// + /// Entity that this Component will be tied to. + Component(Entity entity); + }; +} + +#include "Component.h++" diff --git a/SHADE_Managed/src/Engine/ECS.cxx b/SHADE_Managed/src/Engine/ECS.cxx new file mode 100644 index 00000000..5d63afc8 --- /dev/null +++ b/SHADE_Managed/src/Engine/ECS.cxx @@ -0,0 +1,255 @@ +/************************************************************************************//*! +\file ECS.cxx +\author Tng Kah Wei, kahwei.tng, 390009620 +\par email: kahwei.tng\@digipen.edu +\date Oct 28, 2021 +\brief Contains the definition of the functions for the ECS 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 "ECS.hxx" +// Standard Library +#include +#include +// External Dependencies +#include "Engine/ECS_Base/System/SHEntityManager.h" +// Project Headers +#include "Utility/Convert.hxx" +#include "Utility/Debug.hxx" + +namespace SHADE +{ + /*---------------------------------------------------------------------------------*/ + /* Component Manipulation Functions */ + /*---------------------------------------------------------------------------------*/ + generic + T ECS::AddComponent(EntityID entity) + { + System::Type^ componentType = T::typeid; + + // Check if entity is correct + if (!SHEntityManager::IsValidEID(entity)) + { + std::ostringstream oss; + oss << "[ECS] Attempted to add Component \"" + << msclr::interop::marshal_as(componentType->Name) + << "\" to invalid Entity."; + Debug::LogError(oss.str()); + return T(); + } + + // Add based on the correct component + for each(ComponentSet^ type in componentMap) + { + if (componentType == type->Type) + { + // Attempt to add + type->AddFunction(entity); + + // Return the managed component + return createManagedComponent(entity); + } + } + + std::ostringstream oss; + oss << "[ECS] Failed to add unsupported Component \"" + << Convert::ToNative(componentType->Name) + << "\" to Entity #" + << entity; + Debug::LogError(oss.str()); + return T(); + } + generic + T ECS::GetComponent(EntityID entity) + { + System::Type^ componentType = T::typeid; + + // Check if entity is correct + if (!SHEntityManager::IsValidEID(entity)) + { + std::ostringstream oss; + oss << "[ECS] Attempted to retrieve Component \"" + << Convert::ToNative(componentType->Name) + << "\" from invalid Entity."; + Debug::LogError(oss.str()); + return T(); + } + + // Get based on the correct component + for each(ComponentSet^ type in componentMap) + { + if (componentType == type->Type) + { + if (type->HasFunction(entity)) + { + return createManagedComponent(entity); + } + else + { + return T(); + } + } + } + + std::ostringstream oss; + oss << "[ECS] Failed to retrieve unsupported Component \"" + << Convert::ToNative(componentType->Name) + << "\" to Entity #" + << entity; + Debug::LogError(oss.str()); + return T(); + } + + generic + T ECS::GetComponentInChildren(EntityID entity) + { + System::Type^ componentType = T::typeid; + + // Check if entity is correct + if (!SHEntityManager::IsValidEID(entity)) + { + std::ostringstream oss; + oss << "[ECS] Attempted to retrieve Component \"" + << Convert::ToNative(componentType->Name) + << "\" from invalid Entity."; + Debug::LogError(oss.str()); + return T(); + } + + // Get Transform component and get the children list + throw gcnew System::NotImplementedException; + //Pls::Transform* tf = Pls::ECS::GetComponent(entity); + //if (tf == nullptr) + // return T(); + + //// Search direct children first + //for (const auto& child : tf->GetChildren()) + //{ + // T component = GetComponent(child); + // if (component != nullptr) + // return component; + //} + + //// Search their children + //for (const auto& child : tf->GetChildren()) + //{ + // T script = GetComponentInChildren(child); + // if (script != nullptr) + // return script; + //} + + // None here + return T(); + } + + generic + T ECS::EnsureComponent(EntityID entity) + { + if (HasComponent(entity)) + { + AddComponent(entity); + } + + return GetComponent(entity); + } + generic + bool ECS::HasComponent(EntityID entity) + { + System::Type^ componentType = T::typeid; + + // Check if entity is correct + if (!SHEntityManager::IsValidEID(entity)) + { + std::ostringstream oss; + oss << "[ECS] Attempted to check existence of Component \"" + << Convert::ToNative(componentType->Name) + << "\" from invalid Entity."; + Debug::LogError(oss.str()); + return false; + } + + // Add based on the correct component + for each(ComponentSet^ type in componentMap) + { + if (componentType == type->Type) + { + return type->HasFunction(entity); + } + } + + std::ostringstream oss; + oss << "[ECS] Attempted to check existence of unsupported Component \"" + << msclr::interop::marshal_as(componentType->Name) + << "\" from Entity #" + << entity; + Debug::LogError(oss.str()); + + return false; + } + generic + void ECS::RemoveComponent(EntityID entity) + { + System::Type^ componentType = T::typeid; + + // Check if entity is correct + if (!SHEntityManager::IsValidEID(entity)) + { + std::ostringstream oss; + oss << "[ECS] Attempted to remove Component \"" + << Convert::ToNative(componentType->Name) + << "\" from invalid Entity."; + Debug::LogError(oss.str()); + } + + // Add based on the correct component + for each(ComponentSet^ type in componentMap) + { + if (componentType == type->Type) + { + type->RemoveFunction(entity); + return; + } + } + + std::ostringstream oss; + oss << "[ECS] Attempted to remove unsupported Component \"" + << msclr::interop::marshal_as(componentType->Name) + << "\" from Entity #" + << entity; + Debug::LogError(oss.str()); + } + + /*---------------------------------------------------------------------------------*/ + /* Constructors */ + /*---------------------------------------------------------------------------------*/ + static ECS::ECS() + { + // TODO + // componentMap.Add(createComponentSet()); + } + + /*---------------------------------------------------------------------------------*/ + /* Helper Functions */ + /*---------------------------------------------------------------------------------*/ + generic + T ECS::createManagedComponent(EntityID entity) + { + using namespace System::Reflection; + + array^ params = gcnew array{ Convert::ToCLI(entity) }; + return safe_cast(Activator::CreateInstance + ( + T::typeid, + BindingFlags::Instance | BindingFlags::NonPublic | BindingFlags::CreateInstance, + nullptr, params, nullptr) + ); + } +} diff --git a/SHADE_Managed/src/Engine/ECS.h++ b/SHADE_Managed/src/Engine/ECS.h++ new file mode 100644 index 00000000..b411c8bd --- /dev/null +++ b/SHADE_Managed/src/Engine/ECS.h++ @@ -0,0 +1,60 @@ +/************************************************************************************//*! +\file ECS.h++ +\author Tng Kah Wei, kahwei.tng, 390009620 +\par email: kahwei.tng\@digipen.edu +\date Oct 27, 2021 +\brief Contains the definition of templated functions for the managed Component + classes. + + 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 + +// Primary Include +#include "ECS.hxx" +// External Dependencies +#include "Engine/ECS_Base/System/SHComponentManager.h" +#include "Engine/ECS_Base/System/SHEntityManager.h" + +namespace SHADE +{ + /*---------------------------------------------------------------------------------*/ + /* Static Functions */ + /*---------------------------------------------------------------------------------*/ + template + NativeComponent* ECS::GetNativeComponent(Entity entity) + { + // Get native Entity + SHEntity* nativeEntity = SHEntityManager::GetEntityByID(entity); + + // Entity Validity Check + if (nativeEntity == nullptr) + throw gcnew System::InvalidOperationException("Attempted to get native Component to an invalid Entity."); + + // Null Check + NativeComponent* component = SHComponentManager::GetComponent_s(nativeEntity); + if (component == nullptr) + throw gcnew System::NullReferenceException("Attempted to get a native Component that does not exist."); + + return component; + } + /*---------------------------------------------------------------------------------*/ + /* Helper Functions */ + /*---------------------------------------------------------------------------------*/ + template + ECS::ComponentSet ECS::createComponentSet() + { + return ComponentSet + { + ManagedType::typeid, + SHComponentManager::AddComponent, + SHComponentManager::EnsureComponent, + SHComponentManager::HasComponent, + SHComponentManager::RemoveComponent + }; + } +} diff --git a/SHADE_Managed/src/Engine/ECS.hxx b/SHADE_Managed/src/Engine/ECS.hxx new file mode 100644 index 00000000..c0c95aff --- /dev/null +++ b/SHADE_Managed/src/Engine/ECS.hxx @@ -0,0 +1,174 @@ +/************************************************************************************//*! +\file ECS.hxx +\author Tng Kah Wei, kahwei.tng, 390009620 +\par email: kahwei.tng\@digipen.edu +\date Oct 28, 2021 +\brief Contains the definitions of the GameObject managed class which define an + abstraction for working with Entities in managed code. + + 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 "Engine/ECS_Base/System/SHComponentManager.h" +// Project Includes +#include "Components/Component.hxx" + +namespace SHADE +{ + /// + /// Static class which contains functions that map Pls::ECS's Component manipulation + /// functions to managed generic functions. + /// + private ref class ECS abstract sealed + { + public: + /*-----------------------------------------------------------------------------*/ + /* Component Manipulation Functions */ + /*-----------------------------------------------------------------------------*/ + /// + /// Adds a Component to the specified Entity. + /// + /// Type of the Component to add. + /// + /// Entity object that should have the specified Component added to. + /// + /// Reference to the Component that was added. + generic where T : BaseComponent + static T AddComponent(EntityID entity); + /// + /// Gets a Component from the specified Entity. + /// + /// Type of the Component to get. + /// Entity object to get the Component from. + /// + /// Reference to the Component or null if the Entity does not have the + /// specified Component. + /// + generic where T : BaseComponent + static T GetComponent(EntityID entity); + /// + /// Retrieves the first Component from the specified GameObjectt's children that + /// matches the specified type. + /// + /// Type of the Component to get. + /// Entity object to get the Component from. + /// + /// Reference to the Component or null if the Entity does not have the + /// specified Component. + /// + generic where T : BaseComponent + static T GetComponentInChildren(EntityID entity); + /// + /// Ensures a Component on the specified Entity. + /// + /// Type of the Component to ensure. + /// Entity object to ensure the Component on. + /// Reference to the Component. + generic where T : BaseComponent + static T EnsureComponent(EntityID entity); + /// + /// Checks if the specified Entity has the specified Component. + /// + /// Type of the Component to check for. + /// Entity object to check for the Component. + /// + /// True if the specified Entity has the specified Component. False otherwise. + /// + generic where T : BaseComponent + static bool HasComponent(EntityID entity); + /// + /// Removes a Component from the specified Entity. + /// + /// Type of the Component to remove. + /// + /// Entity object that should have the specified Component removed from/ + /// + generic where T : BaseComponent + static void RemoveComponent(EntityID entity); + + internal: + /*-----------------------------------------------------------------------------*/ + /* Type Definitions */ + /*-----------------------------------------------------------------------------*/ + /// + /// Pointer to a function for Component manipulation operations. + /// + using ComponentFunc = void(*)(const EntityID&); + using ComponentHasFunc = bool(*)(const EntityID&); + /// + /// Contains a set of Component related data used for resolving operations for + /// each Component. + /// + value struct ComponentSet + { + public: + System::Type^ Type; + ComponentFunc AddFunction; + ComponentHasFunc HasFunction; + ComponentFunc RemoveFunction; + + }; + + /*-----------------------------------------------------------------------------*/ + /* Static Functions */ + /*-----------------------------------------------------------------------------*/ + /// + /// Retrieves a pointer to the native unmanaged component of the specified + /// Entity. + /// + /// + /// Pointer to the native component. Will be nullptr if it does not exist. + /// + /// + /// Thrown if the Entity specified is invalid. + /// + /// + /// Thrown if an attempt to retrieve the native component fails. + /// + template + static NativeComponent* GetNativeComponent(Entity entity); + + private: + /*-----------------------------------------------------------------------------*/ + /* Constructors */ + /*-----------------------------------------------------------------------------*/ + /// + /// Static constructor to initialize static data + /// + static ECS(); + + /*-----------------------------------------------------------------------------*/ + /* Static Data Members */ + /*-----------------------------------------------------------------------------*/ + static System::Collections::Generic::List componentMap; + + /*-----------------------------------------------------------------------------*/ + /* Helper Functions */ + /*-----------------------------------------------------------------------------*/ + /// + /// Creates a ComponentSet for a pair of Native and Managed Components. + /// + /// Type of the Native Component. + /// Type of the Managed Component. + /// ComponentSet for the parameters specified. + template + static ComponentSet createComponentSet(); + /// + /// Creates an instance of the Managed representation of a Component with a + /// native Entity. + /// + /// Type of Component to create. + /// Native Entity that this Component is tied to. + /// The created Managed representation of the Component. + generic where T : BaseComponent + static T createManagedComponent(EntityID entity); + }; +} + +#include "ECS.h++" diff --git a/SHADE_Managed/src/Scripts/ScriptStore.cxx b/SHADE_Managed/src/Scripts/ScriptStore.cxx index 86329f29..54572559 100644 --- a/SHADE_Managed/src/Scripts/ScriptStore.cxx +++ b/SHADE_Managed/src/Scripts/ScriptStore.cxx @@ -33,8 +33,8 @@ namespace SHADE generic T ScriptStore::AddScript(Entity entity) { - // Check if entity exists and is a valid GameObject - if (!EntityUtils::IsValid(entity) /*|| !GameObjectLibrary::Contains(entity)*/) + // Check if entity exists + if (!EntityUtils::IsValid(entity)) throw gcnew System::ArgumentException("Invalid Entity provided to add a Script to."); System::Collections::Generic::List ^ entityScriptList; @@ -113,12 +113,9 @@ namespace SHADE generic T ScriptStore::GetScript(Entity entity) { - // Check if entity exists and is a valid GameObject - if (!EntityUtils::IsValid(entity) /*|| !GameObjectLibrary::Contains(entity)*/) - { + // Check if entity exists + 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)) @@ -147,10 +144,8 @@ namespace SHADE T ScriptStore::GetScriptInChildren(Entity entity) { // Check if entity exists and is a valid GameObject - if (!EntityUtils::IsValid(entity) /*|| !GameObjectLibrary::Contains(entity)*/) - { + if (!EntityUtils::IsValid(entity)) throw gcnew System::ArgumentException("Invalid Entity provided to get a Script from."); - } // Check if entity exists in the script storage @@ -189,10 +184,8 @@ namespace SHADE System::Collections::Generic::IEnumerable^ ScriptStore::GetScripts(Entity entity) { // Check if entity exists and is a valid GameObject - if (!EntityUtils::IsValid(entity) /*|| !GameObjectLibrary::Contains(entity)*/) - { + if (!EntityUtils::IsValid(entity)) throw gcnew System::ArgumentException("Invalid Entity provided to get a Script from."); - } // Create a list to store entries System::Collections::Generic::List^ foundScripts = gcnew System::Collections::Generic::List(); @@ -221,8 +214,8 @@ namespace SHADE } System::Collections::Generic::IEnumerable^ ScriptStore::GetAllScripts(Entity entity) { - // Check if entity exists and is a valid GameObject - if (!EntityUtils::IsValid(entity) /*|| !GameObjectLibrary::Contains(entity)*/) + // Check if entity exists + if (!EntityUtils::IsValid(entity)) return nullptr; // Check if entity exists in the script storage @@ -235,8 +228,8 @@ namespace SHADE generic void ScriptStore::RemoveScript(Entity entity) { - // Check if entity exists and is a valid GameObject - if (!EntityUtils::IsValid(entity) /*|| !GameObjectLibrary::Contains(entity)*/) + // Check if entity exists + if (!EntityUtils::IsValid(entity)) throw gcnew System::ArgumentException("Invalid Entity provided to remove a Script from."); @@ -263,8 +256,8 @@ namespace SHADE } bool ScriptStore::RemoveScript(Entity entity, Script^ script) { - // Check if entity exists and is a valid GameObject - if (!EntityUtils::IsValid(entity) /*|| !GameObjectLibrary::Contains(entity)*/) + // Check if entity exists + if (!EntityUtils::IsValid(entity)) { Debug::LogError("[ScriptStore] Attempted to remove a Script from an invalid Entity!"); return false; @@ -292,8 +285,8 @@ namespace SHADE void ScriptStore::RemoveAllScripts(Entity entity) { SAFE_NATIVE_CALL_BEGIN - // Check if entity exists and is a valid GameObject - if (!EntityUtils::IsValid(entity) /*|| !GameObjectLibrary::Contains(entity)*/) + // Check if entity exists + if (!EntityUtils::IsValid(entity)) { Debug::LogError("[ScriptStore] Attempted to remove Scripts from an invalid Entity!"); return; @@ -315,8 +308,8 @@ namespace SHADE void ScriptStore::RemoveAllScriptsImmediately(Entity entity, bool callOnDestroy) { SAFE_NATIVE_CALL_BEGIN - // Check if entity exists and is a valid GameObject - if (!EntityUtils::IsValid(entity) /*|| !GameObjectLibrary::Contains(entity)*/) + // Check if entity exists + if (!EntityUtils::IsValid(entity)) { Debug::LogError("[ScriptStore] Attempted to remove Scripts from an invalid Entity!"); return; @@ -393,7 +386,6 @@ namespace SHADE /*if (Application::IsPlaying) { script->OnDestroy(); - }*/ auto entity = script->Owner.GetEntity(); auto scriptList = scripts[script->Owner.GetEntity()]; @@ -498,8 +490,8 @@ namespace SHADE // Create a buffer that we can work with temporarily System::Text::StringBuilder^ jsonString = gcnew System::Text::StringBuilder(); - // Check if entity exists and is a valid GameObject, otherwise nothing - if (!EntityUtils::IsValid(entity) /*|| !GameObjectLibrary::Contains(entity)*/) + // Check if entity exists, otherwise nothing + if (!EntityUtils::IsValid(entity)) return true; @@ -511,7 +503,7 @@ namespace SHADE System::Collections::Generic::List^ scriptList = scripts[entity]; for (int i = 0; i < scriptList->Count; ++i) { - throw gcnew System::NotFiniteNumberException; + throw gcnew System::NotImplementedException; //jsonString->Append(ReflectionUtilities::Serialise(scriptList[i])); // Only add separator if is not last script @@ -536,8 +528,8 @@ namespace SHADE bool ScriptStore::DeserialiseScript(Entity entity, System::String^ json) { SAFE_NATIVE_CALL_BEGIN - // Check if entity exists and is a valid GameObject, otherwise nothing - if (!EntityUtils::IsValid(entity)/* || !GameObjectLibrary::Contains(entity)*/) + // Check if entity exists, otherwise nothing + if (!EntityUtils::IsValid(entity)) return false; // Get the name of the script @@ -670,4 +662,4 @@ namespace SHADE // Check active state return Convert::ToNative(entity).isActive; } -} // namespace SHADE +}