From b933b0f7fc06f82f27e776a8da58a1bd90259831 Mon Sep 17 00:00:00 2001 From: Kah Wei Date: Fri, 16 Sep 2022 13:13:38 +0800 Subject: [PATCH 01/24] Added SerializeField attribute --- SHADE_Engine/src/Scripting/SHScriptEngine.cpp | 4 +-- .../Serialisation/SerializeFieldAttribute.hxx | 35 +++++++++++++++++++ 2 files changed, 37 insertions(+), 2 deletions(-) create mode 100644 SHADE_Managed/src/Serialisation/SerializeFieldAttribute.hxx diff --git a/SHADE_Engine/src/Scripting/SHScriptEngine.cpp b/SHADE_Engine/src/Scripting/SHScriptEngine.cpp index 47c722dd..3116d680 100644 --- a/SHADE_Engine/src/Scripting/SHScriptEngine.cpp +++ b/SHADE_Engine/src/Scripting/SHScriptEngine.cpp @@ -483,8 +483,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; diff --git a/SHADE_Managed/src/Serialisation/SerializeFieldAttribute.hxx b/SHADE_Managed/src/Serialisation/SerializeFieldAttribute.hxx new file mode 100644 index 00000000..6036a7f5 --- /dev/null +++ b/SHADE_Managed/src/Serialisation/SerializeFieldAttribute.hxx @@ -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 +{ + /// + /// Simple attribute to mark that a field in a Script should be serialised. + /// + [System::AttributeUsage(AttributeTargets::Field)] + public ref class SerializeField : public System::Attribute + { + public: + /*-----------------------------------------------------------------------------*/ + /* Constructors */ + /*-----------------------------------------------------------------------------*/ + /// + /// Default Constructor + /// + SerializeField() = default; + }; +} + From da582e0f1d74c9255483b17944b0e96d9a9b340a Mon Sep 17 00:00:00 2001 From: Kah Wei Date: Fri, 16 Sep 2022 13:58:08 +0800 Subject: [PATCH 02/24] added serial --- .../src/Serialisation/ReflectionUtilities.cxx | 429 ++++++++++++++++++ .../src/Serialisation/ReflectionUtilities.hxx | 73 +++ .../Serialisation/SerialiseFieldAttribute.cxx | 27 ++ .../Serialisation/SerializeFieldAttribute.hxx | 4 +- 4 files changed, 531 insertions(+), 2 deletions(-) create mode 100644 SHADE_Managed/src/Serialisation/ReflectionUtilities.cxx create mode 100644 SHADE_Managed/src/Serialisation/ReflectionUtilities.hxx create mode 100644 SHADE_Managed/src/Serialisation/SerialiseFieldAttribute.cxx diff --git a/SHADE_Managed/src/Serialisation/ReflectionUtilities.cxx b/SHADE_Managed/src/Serialisation/ReflectionUtilities.cxx new file mode 100644 index 00000000..8ea4a44e --- /dev/null +++ b/SHADE_Managed/src/Serialisation/ReflectionUtilities.cxx @@ -0,0 +1,429 @@ +/************************************************************************************//*! +\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" +// External Dependencies + +// Project Includes +#include "SerializeFieldAttribute.hxx" +#include "Utility/Convert.hxx" + +/*-------------------------------------------------------------------------------------*/ +/* Macro Functions */ +/*-------------------------------------------------------------------------------------*/ +/// +/// Macro expansion that is used in FieldToRapidJsonValue() to check the type of a field +/// named "fieldInfo" against the specified type and if it matches, store said field +/// of an object named "object" it into rapidjson::Value called "jsonValue" as that +/// specified type. +/// +/// The type to check. +#define PRIMITIVE_FIELD_CAST(T) \ +(fieldInfo->FieldType == T::typeid) \ +{ \ + jsonValue = safe_cast(fieldInfo->GetValue(object)); \ +} \ +/// +/// Macro expansion that is used in RapidJsonValueToField() to check the type of a field +/// named "fieldInfo" against the specified type and if it matches, retrieves the value +/// using the function FUNC provided from a rapidjson::Value called "jsonValue" and sets +/// the value of the field to the retrieved value. +/// +/// The type to check. +/// Member function of jsonValue to use to retrieve the data. +#define PRIMITIVE_FIELD_ASSIGN(T, FUNC) \ +(fieldInfo->FieldType == T::typeid) \ +{ \ + fieldInfo->SetValue(object, jsonValue.FUNC()); \ +} \ +/// +/// Macro expansion that is used in RapidJsonValueToField() to retrieve the specified +/// member of a Vector type that is stored into a Vector named "vec". +/// +/// The name of the member to retrieve. +#define PRIMITIVE_VECTOR_FIELD_ASSIGN(MEMBER) \ +iter = jsonValue.FindMember(#MEMBER); \ +if (iter != jsonValue.MemberEnd()) \ +{ \ + vec.MEMBER = iter->value.GetDouble(); \ +} \ +/// +/// Macro expansion that is used in RapidJsonValueToField() to retrieve the specified +/// member of a Color type that is stored into a Color named "col". +/// +/// The name of the member to retrieve. +#define PRIMITIVE_COLOR_FIELD_ASSIGN(MEMBER) \ +iter = jsonValue.FindMember(#MEMBER); \ +if (iter != jsonValue.MemberEnd()) \ +{ \ + col.MEMBER = iter->value.GetFloat(); \ +} \ +/// +/// Macro expansion that is used to write the name of a field named fieldInfo into a +/// rapidjson writer called writer. +/// +#define PRIMITIVE_WRITE_FIELD_NAME writer.String(Convert::ToNative(fieldInfo->Name).c_str()); +/// +/// Macro expansion that is used in serialiseFieldJson() to check the type of a field +/// named "fieldInfo" against the specified type and if it matches, writes the value +/// using the function FUNC in to a rapidjson writer object named "writer". +/// +/// The type to check. +/// +/// Member function of the rapidjson writer object to use to write the data. +/// +#define PRIMITIVE_FIELD_SERIALISE_JSON(T, FUNC) \ +(fieldInfo->FieldType == T::typeid) \ +{ \ + PRIMITIVE_WRITE_FIELD_NAME \ + writer.FUNC(safe_cast(fieldInfo->GetValue(object))); \ +} \ +/// +/// Macro expansion that is used in serialiseFieldJson() to write the specified +/// member of a Vector named "vec" using the rapidjson writer named "writer". +/// +/// The name of the member to write. +#define PRIMITIVE_VECTOR_FIELD_SERIALISE_JSON(MEMBER) \ +writer.String(#MEMBER); \ +writer.Double(vec.MEMBER); \ +/*-------------------------------------------------------------------------------------*/ +/* Function Definitions */ +/*-------------------------------------------------------------------------------------*/ +namespace SHADE +{ + System::Collections::Generic::IEnumerable^ 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) + //{ + // // Create YAML object + // yaml << YAML::Key << Convert::ToNative(object->GetType().FullName); + // yaml << YAML::BeginMap; + + // // Get all fields + // IEnumerable^ fields = GetInstanceFields(object); + // for each (FieldInfo^ field in fields) + // { + // // Ignore private and non-SerialiseField + // if (!FieldIsSerialisable(field)) + // continue; + + // // Serialise + // rapidjson::Value jsonValue = FieldToRapidJsonValue(field, object, allocator); + // rapidjson::Value key(Convert::ToNative(field->Name).c_str(), allocator); + // scriptRoot.AddMember(key.Move(), jsonValue, allocator); + // } + + // /* Add the Script JSON Object to the JSON root node*/ + // rapidjson::Value key(Convert::ToNative(object->GetType()->FullName).c_str(), allocator); + // json.AddMember(key.Move(), scriptRoot, allocator); + + // /* Prepare to send to the caller */ + // // Convert to string + // rapidjson::StringBuffer buffer; + // rapidjson::PrettyWriter writer(buffer); + // json.Accept(writer); + + // // Return the result + // return Convert::ToCLI(std::string(buffer.GetString())); + //} + //void ReflectionUtilities::Deserialise(System::String^ jsonString, Object^ object) + //{ + // // Load the JSON + // rapidjson::Document json; + // auto& allocator = json.GetAllocator(); + // json.Parse(Convert::ToNative(jsonString).c_str()); + + // // Get the root object + // auto scriptRoot = json.MemberBegin(); + // if (scriptRoot == json.MemberEnd()) + // { + // Pls::Debug::LogError("[ReflectionUtilities] Attempted read of corrupted serialised object."); + // return; + // } + // + // // Get all fields + // IEnumerable^ fields = GetInstanceFields(object); + // for each (FieldInfo^ field in fields) + // { + // // Ignore private and non-SerialiseField + // if (!FieldIsSerialisable(field)) + // continue; + + // // Deserialise + // auto iter = scriptRoot->value.FindMember(Convert::ToNative(field->Name).c_str()); + // if (iter != scriptRoot->value.MemberEnd()) + // { + // // Get the data and set it in + // RapidJsonValueToField(iter->value, field, object); + + // } + // } + //} + //void ReflectionUtilities::Serialise(Object^ object, JsonWriter& writer) + //{ + // /* Script Name */ + // writer.String(Convert::ToNative(object->GetType()->FullName).c_str()); + + // /* Script Contents */ + // writer.StartObject(); + // IEnumerable^ fields = GetInstanceFields(object); + // for each (FieldInfo^ field in fields) + // { + // // Ignore private and non-SerialiseField + // if (!FieldIsSerialisable(field)) + // continue; + + // // Serialise + // serialiseFieldJson(field, object, writer); + // } + // writer.EndObject(); + //} + + ///*---------------------------------------------------------------------------------*/ + ///* Serialisation Helper Functions */ + ///*---------------------------------------------------------------------------------*/ + //rapidjson::Value ReflectionUtilities::FieldToRapidJsonValue(FieldInfo^ fieldInfo, Object^ object, JsonAllocator& allocator) + //{ + // rapidjson::Value jsonValue; + + // // Check each type of value and convert it into a rapidjson::Value + // if PRIMITIVE_FIELD_CAST(Int16) + // else if PRIMITIVE_FIELD_CAST(Int32) + // else if PRIMITIVE_FIELD_CAST(Int64) + // else if PRIMITIVE_FIELD_CAST(UInt16) + // else if PRIMITIVE_FIELD_CAST(UInt32) + // else if PRIMITIVE_FIELD_CAST(UInt64) + // else if PRIMITIVE_FIELD_CAST(Byte) + // else if PRIMITIVE_FIELD_CAST(bool) + // else if PRIMITIVE_FIELD_CAST(float) + // else if PRIMITIVE_FIELD_CAST(double) + // else if (fieldInfo->FieldType->IsSubclassOf(Enum::typeid)) + // { + // jsonValue = safe_cast(fieldInfo->GetValue(object)); + // } + // else if (fieldInfo->FieldType == String::typeid) + // { + // String^ str = safe_cast(fieldInfo->GetValue(object)); + // jsonValue.SetString(Convert::ToNative(str).c_str(), str->Length, allocator); + // } + // else if (fieldInfo->FieldType == Vector2::typeid) + // { + // jsonValue.SetObject(); + // Vector2 vec = safe_cast(fieldInfo->GetValue(object)); + // jsonValue.AddMember(rapidjson::Value("x"), rapidjson::Value(vec.x), allocator); + // jsonValue.AddMember(rapidjson::Value("y"), rapidjson::Value(vec.y), allocator); + // } + // else if (fieldInfo->FieldType == Vector3::typeid) + // { + // jsonValue.SetObject(); + // Vector3 vec = safe_cast(fieldInfo->GetValue(object)); + // jsonValue.AddMember(rapidjson::Value("x"), rapidjson::Value(vec.x), allocator); + // jsonValue.AddMember(rapidjson::Value("y"), rapidjson::Value(vec.y), allocator); + // jsonValue.AddMember(rapidjson::Value("z"), rapidjson::Value(vec.z), allocator); + // } + // else if (fieldInfo->FieldType == Color::typeid) + // { + // jsonValue.SetObject(); + // Color col = safe_cast(fieldInfo->GetValue(object)); + // jsonValue.AddMember(rapidjson::Value("r"), rapidjson::Value(col.r), allocator); + // jsonValue.AddMember(rapidjson::Value("g"), rapidjson::Value(col.g), allocator); + // jsonValue.AddMember(rapidjson::Value("b"), rapidjson::Value(col.b), allocator); + // jsonValue.AddMember(rapidjson::Value("a"), rapidjson::Value(col.a), allocator); + // } + // else if (IResourceID::typeid->IsAssignableFrom(fieldInfo->FieldType)) + // { + // IResourceID^ rscId = safe_cast(fieldInfo->GetValue(object)); + // jsonValue = rscId->Id; + // } + // else // Not any of the supported types + // { + // Pls::Debug::LogWarning(Convert::ToNative(String::Format + // ( + // "[ReflectionUtilities] Failed to parse \"{0}\" of \"{1}\" type for serialisation.", + // fieldInfo->Name, fieldInfo->FieldType) + // )); + // } + // return jsonValue; + //} + //void ReflectionUtilities::RapidJsonValueToField(const rapidjson::Value& jsonValue, FieldInfo^ fieldInfo, Object^ object) + //{ + // if PRIMITIVE_FIELD_ASSIGN(Int16, GetInt) + // else if PRIMITIVE_FIELD_ASSIGN(Int32, GetInt) + // else if PRIMITIVE_FIELD_ASSIGN(Int64, GetInt64) + // else if PRIMITIVE_FIELD_ASSIGN(UInt16, GetUint) + // else if PRIMITIVE_FIELD_ASSIGN(UInt32, GetUint) + // else if PRIMITIVE_FIELD_ASSIGN(UInt64, GetUint64) + // else if PRIMITIVE_FIELD_ASSIGN(Byte, GetInt) + // else if PRIMITIVE_FIELD_ASSIGN(bool, GetBool) + // else if PRIMITIVE_FIELD_ASSIGN(float, GetFloat) + // else if PRIMITIVE_FIELD_ASSIGN(double, GetDouble) + // else if (fieldInfo->FieldType->IsSubclassOf(Enum::typeid)) + // { + // fieldInfo->SetValue(object, jsonValue.GetInt()); + // } + // else if (fieldInfo->FieldType == String::typeid) + // { + // fieldInfo->SetValue(object, Convert::ToCLI(jsonValue.GetString())); + // } + // else if (fieldInfo->FieldType == Vector2::typeid) + // { + // Vector2 vec; + // auto iter = jsonValue.MemberEnd(); + // PRIMITIVE_VECTOR_FIELD_ASSIGN(x) + // PRIMITIVE_VECTOR_FIELD_ASSIGN(y) + // fieldInfo->SetValue(object, vec); + // } + // else if (fieldInfo->FieldType == Vector3::typeid) + // { + // Vector3 vec; + // auto iter = jsonValue.MemberEnd(); + // PRIMITIVE_VECTOR_FIELD_ASSIGN(x) + // PRIMITIVE_VECTOR_FIELD_ASSIGN(y) + // PRIMITIVE_VECTOR_FIELD_ASSIGN(z) + // fieldInfo->SetValue(object, vec); + // } + // else if (fieldInfo->FieldType == Color::typeid) + // { + // Color col; + // auto iter = jsonValue.MemberEnd(); + // PRIMITIVE_COLOR_FIELD_ASSIGN(r) + // PRIMITIVE_COLOR_FIELD_ASSIGN(g) + // PRIMITIVE_COLOR_FIELD_ASSIGN(b) + // PRIMITIVE_COLOR_FIELD_ASSIGN(a) + // fieldInfo->SetValue(object, col); + // } + // else if (IResourceIDInternal::typeid->IsAssignableFrom(fieldInfo->FieldType)) + // { + // IResourceIDInternal^ rsc = safe_cast(Activator::CreateInstance(fieldInfo->FieldType)); + // rsc->Id = jsonValue.GetInt64(); + // fieldInfo->SetValue(object, rsc); + // } + // else // Not any of the supported types + // { + // Pls::Debug::LogWarning(Convert::ToNative(String::Format + // ( + // "[ReflectionUtilities] Failed to parse \"{0}\" of \"{1}\" type for deserialisation.", + // fieldInfo->Name, fieldInfo->FieldType) + // )); + // } + //} + + ///*---------------------------------------------------------------------------------*/ + ///* Internal Serialisation Helper Functions */ + ///*---------------------------------------------------------------------------------*/ + //void ReflectionUtilities::serialiseFieldJson(FieldInfo^ fieldInfo, Object^ object, JsonWriter& writer) + //{ + // if PRIMITIVE_FIELD_SERIALISE_JSON(Int16, Int) + // else if PRIMITIVE_FIELD_SERIALISE_JSON(Int32, Int) + // else if PRIMITIVE_FIELD_SERIALISE_JSON(Int64, Int64) + // else if PRIMITIVE_FIELD_SERIALISE_JSON(UInt16, Uint) + // else if PRIMITIVE_FIELD_SERIALISE_JSON(UInt32, Uint) + // else if PRIMITIVE_FIELD_SERIALISE_JSON(UInt64, Uint64) + // else if PRIMITIVE_FIELD_SERIALISE_JSON(Byte, Int) + // else if PRIMITIVE_FIELD_SERIALISE_JSON(bool, Bool) + // else if PRIMITIVE_FIELD_SERIALISE_JSON(float, Double) + // else if PRIMITIVE_FIELD_SERIALISE_JSON(double, Double) + // else if PRIMITIVE_FIELD_SERIALISE_JSON(double, Double) + // else if (fieldInfo->FieldType->IsSubclassOf(Enum::typeid)) + // { + // PRIMITIVE_WRITE_FIELD_NAME + // writer.Int(safe_cast(fieldInfo->GetValue(object))); + + // } + // else if (fieldInfo->FieldType == String::typeid) + // { + // PRIMITIVE_WRITE_FIELD_NAME + // writer.String(Convert::ToNative(safe_cast(fieldInfo->GetValue(object))).c_str()); + + // } + // else if (fieldInfo->FieldType == Vector2::typeid) + // { + // // Get handle to the Vector to edit + // Vector2 vec = safe_cast(fieldInfo->GetValue(object)); + + // // Write the vector data + // PRIMITIVE_WRITE_FIELD_NAME + // writer.StartObject(); + // { + // PRIMITIVE_VECTOR_FIELD_SERIALISE_JSON(x) + // PRIMITIVE_VECTOR_FIELD_SERIALISE_JSON(y) + // } + // writer.EndObject(); + // } + // else if (fieldInfo->FieldType == Vector3::typeid) + // { + // // Get handle to the Vector to edit + // Vector3 vec = safe_cast(fieldInfo->GetValue(object)); + + // // Write the vector data + // PRIMITIVE_WRITE_FIELD_NAME + // writer.StartObject(); + // { + // PRIMITIVE_VECTOR_FIELD_SERIALISE_JSON(x) + // PRIMITIVE_VECTOR_FIELD_SERIALISE_JSON(y) + // PRIMITIVE_VECTOR_FIELD_SERIALISE_JSON(z) + // } + // writer.EndObject(); + // } + // else if (fieldInfo->FieldType == Color::typeid) + // { + // // Get handle to the Vector to edit + // Color vec = safe_cast(fieldInfo->GetValue(object)); + + // // Write the vector data + // PRIMITIVE_WRITE_FIELD_NAME + // writer.StartObject(); + // { + // PRIMITIVE_VECTOR_FIELD_SERIALISE_JSON(r) + // PRIMITIVE_VECTOR_FIELD_SERIALISE_JSON(g) + // PRIMITIVE_VECTOR_FIELD_SERIALISE_JSON(b) + // PRIMITIVE_VECTOR_FIELD_SERIALISE_JSON(a) + // } + // writer.EndObject(); + // } + // else if (IResourceID::typeid->IsAssignableFrom(fieldInfo->FieldType)) + // { + // PRIMITIVE_WRITE_FIELD_NAME + // IResourceID^ rsc = safe_cast(fieldInfo->GetValue(object)); + // writer.Int64(rsc->Id); + // } + // else // Not any of the supported types + // { + // Pls::Debug::LogWarning(Convert::ToNative(String::Format + // ( + // "[ReflectionUtilities] Failed to parse \"{0}\" of \"{1}\" type for serialisation.", + // fieldInfo->Name, fieldInfo->FieldType) + // )); + // } + //} +} diff --git a/SHADE_Managed/src/Serialisation/ReflectionUtilities.hxx b/SHADE_Managed/src/Serialisation/ReflectionUtilities.hxx new file mode 100644 index 00000000..f312ec05 --- /dev/null +++ b/SHADE_Managed/src/Serialisation/ReflectionUtilities.hxx @@ -0,0 +1,73 @@ +/************************************************************************************//*! +\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 +#include + + +namespace SHADE +{ + /// + /// Contains useful static functions for working with Reflection. + /// + private ref class ReflectionUtilities abstract sealed + { + public: + /*-----------------------------------------------------------------------------*/ + /* Type Definitions */ + /*-----------------------------------------------------------------------------*/ + + /*-----------------------------------------------------------------------------*/ + /* Utility Functions */ + /*-----------------------------------------------------------------------------*/ + /// + /// Retrieves a set of all non-static (instance) fields from a specified object. + /// + /// The object to get non-static fields from. + /// Immutable list of non-static fields. + static System::Collections::Generic::IEnumerable^ GetInstanceFields(System::Object^ object); + /// + /// Checks if a specified field is a candidate for serialisation. This means that + /// the field is public or private with the [SerialiseField] attribute. + /// + /// The field to check. + /// + /// True if the specified field is a candidate for serialisation. + /// + static bool FieldIsSerialisable(System::Reflection::FieldInfo^ fieldInfo); + + /*-----------------------------------------------------------------------------*/ + /* Serialisation Functions */ + /*-----------------------------------------------------------------------------*/ + /// + /// 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. + /// + /// The object to serialise. + //static void Serialise(Object^ object, YAML::Emitter& yaml); + /// + /// Deserialises a JSON string and copies the deserialised data into the + /// specified object if there are matching fields. + /// + /// + /// The JSON string that contains the data to copy into this PlushieScript + /// object. + /// + /// The object to copy deserialised data into. + //static void Deserialise(System::String^ jsonString, Object^ object); + }; +} \ No newline at end of file diff --git a/SHADE_Managed/src/Serialisation/SerialiseFieldAttribute.cxx b/SHADE_Managed/src/Serialisation/SerialiseFieldAttribute.cxx new file mode 100644 index 00000000..c371d200 --- /dev/null +++ b/SHADE_Managed/src/Serialisation/SerialiseFieldAttribute.cxx @@ -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() + {} +} diff --git a/SHADE_Managed/src/Serialisation/SerializeFieldAttribute.hxx b/SHADE_Managed/src/Serialisation/SerializeFieldAttribute.hxx index 6036a7f5..533ded2a 100644 --- a/SHADE_Managed/src/Serialisation/SerializeFieldAttribute.hxx +++ b/SHADE_Managed/src/Serialisation/SerializeFieldAttribute.hxx @@ -19,7 +19,7 @@ namespace SHADE /// /// Simple attribute to mark that a field in a Script should be serialised. /// - [System::AttributeUsage(AttributeTargets::Field)] + [System::AttributeUsage(System::AttributeTargets::Field)] public ref class SerializeField : public System::Attribute { public: @@ -29,7 +29,7 @@ namespace SHADE /// /// Default Constructor /// - SerializeField() = default; + SerializeField(); }; } From 4546b84c061464fa26f76afecd995d527d8b2e2c Mon Sep 17 00:00:00 2001 From: Kah Wei Date: Fri, 16 Sep 2022 15:37:22 +0800 Subject: [PATCH 03/24] Added YAML serialization of scripts --- .../src/Serialisation/ReflectionUtilities.cxx | 535 ++++++------------ .../src/Serialisation/ReflectionUtilities.h++ | 54 ++ .../src/Serialisation/ReflectionUtilities.hxx | 34 +- 3 files changed, 249 insertions(+), 374 deletions(-) create mode 100644 SHADE_Managed/src/Serialisation/ReflectionUtilities.h++ diff --git a/SHADE_Managed/src/Serialisation/ReflectionUtilities.cxx b/SHADE_Managed/src/Serialisation/ReflectionUtilities.cxx index 8ea4a44e..2a9cc57c 100644 --- a/SHADE_Managed/src/Serialisation/ReflectionUtilities.cxx +++ b/SHADE_Managed/src/Serialisation/ReflectionUtilities.cxx @@ -16,41 +16,17 @@ of DigiPen Institute of Technology is prohibited. #include "SHpch.h" // Primary Header #include "Serialisation/ReflectionUtilities.hxx" -// External Dependencies - // Project Includes #include "SerializeFieldAttribute.hxx" #include "Utility/Convert.hxx" +#include "Math/Vector2.hxx" +#include "Math/Vector3.hxx" +#include "Utility/Debug.hxx" /*-------------------------------------------------------------------------------------*/ /* Macro Functions */ /*-------------------------------------------------------------------------------------*/ /// -/// Macro expansion that is used in FieldToRapidJsonValue() to check the type of a field -/// named "fieldInfo" against the specified type and if it matches, store said field -/// of an object named "object" it into rapidjson::Value called "jsonValue" as that -/// specified type. -/// -/// The type to check. -#define PRIMITIVE_FIELD_CAST(T) \ -(fieldInfo->FieldType == T::typeid) \ -{ \ - jsonValue = safe_cast(fieldInfo->GetValue(object)); \ -} \ -/// -/// Macro expansion that is used in RapidJsonValueToField() to check the type of a field -/// named "fieldInfo" against the specified type and if it matches, retrieves the value -/// using the function FUNC provided from a rapidjson::Value called "jsonValue" and sets -/// the value of the field to the retrieved value. -/// -/// The type to check. -/// Member function of jsonValue to use to retrieve the data. -#define PRIMITIVE_FIELD_ASSIGN(T, FUNC) \ -(fieldInfo->FieldType == T::typeid) \ -{ \ - fieldInfo->SetValue(object, jsonValue.FUNC()); \ -} \ -/// /// Macro expansion that is used in RapidJsonValueToField() to retrieve the specified /// member of a Vector type that is stored into a Vector named "vec". /// @@ -61,45 +37,7 @@ if (iter != jsonValue.MemberEnd()) \ { \ vec.MEMBER = iter->value.GetDouble(); \ } \ -/// -/// Macro expansion that is used in RapidJsonValueToField() to retrieve the specified -/// member of a Color type that is stored into a Color named "col". -/// -/// The name of the member to retrieve. -#define PRIMITIVE_COLOR_FIELD_ASSIGN(MEMBER) \ -iter = jsonValue.FindMember(#MEMBER); \ -if (iter != jsonValue.MemberEnd()) \ -{ \ - col.MEMBER = iter->value.GetFloat(); \ -} \ -/// -/// Macro expansion that is used to write the name of a field named fieldInfo into a -/// rapidjson writer called writer. -/// -#define PRIMITIVE_WRITE_FIELD_NAME writer.String(Convert::ToNative(fieldInfo->Name).c_str()); -/// -/// Macro expansion that is used in serialiseFieldJson() to check the type of a field -/// named "fieldInfo" against the specified type and if it matches, writes the value -/// using the function FUNC in to a rapidjson writer object named "writer". -/// -/// The type to check. -/// -/// Member function of the rapidjson writer object to use to write the data. -/// -#define PRIMITIVE_FIELD_SERIALISE_JSON(T, FUNC) \ -(fieldInfo->FieldType == T::typeid) \ -{ \ - PRIMITIVE_WRITE_FIELD_NAME \ - writer.FUNC(safe_cast(fieldInfo->GetValue(object))); \ -} \ -/// -/// Macro expansion that is used in serialiseFieldJson() to write the specified -/// member of a Vector named "vec" using the rapidjson writer named "writer". -/// -/// The name of the member to write. -#define PRIMITIVE_VECTOR_FIELD_SERIALISE_JSON(MEMBER) \ -writer.String(#MEMBER); \ -writer.Double(vec.MEMBER); \ + /*-------------------------------------------------------------------------------------*/ /* Function Definitions */ /*-------------------------------------------------------------------------------------*/ @@ -123,307 +61,182 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ /* Serialisation Functions */ /*---------------------------------------------------------------------------------*/ - //void ReflectionUtilities::Serialise(System::Object^ object, YAML::Emitter& yaml) - //{ - // // Create YAML object - // yaml << YAML::Key << Convert::ToNative(object->GetType().FullName); - // yaml << YAML::BeginMap; + void ReflectionUtilities::Serialise(System::Object^ object, YAML::Emitter& yaml) + { + using namespace System::Reflection; - // // Get all fields - // IEnumerable^ fields = GetInstanceFields(object); - // for each (FieldInfo^ field in fields) - // { - // // Ignore private and non-SerialiseField - // if (!FieldIsSerialisable(field)) - // continue; + // Create YAML object + yaml << YAML::Key << Convert::ToNative(object->GetType()->FullName); + yaml << YAML::BeginMap; - // // Serialise - // rapidjson::Value jsonValue = FieldToRapidJsonValue(field, object, allocator); - // rapidjson::Value key(Convert::ToNative(field->Name).c_str(), allocator); - // scriptRoot.AddMember(key.Move(), jsonValue, allocator); - // } + // Get all fields + System::Collections::Generic::IEnumerable^ fields = GetInstanceFields(object); + for each (FieldInfo^ field in fields) + { + // Ignore private and non-SerialiseField + if (!FieldIsSerialisable(field)) + continue; - // /* Add the Script JSON Object to the JSON root node*/ - // rapidjson::Value key(Convert::ToNative(object->GetType()->FullName).c_str(), allocator); - // json.AddMember(key.Move(), scriptRoot, allocator); + // Serialise + writeFieldIntoYaml(field, object, yaml); + } - // /* Prepare to send to the caller */ - // // Convert to string - // rapidjson::StringBuffer buffer; - // rapidjson::PrettyWriter writer(buffer); - // json.Accept(writer); + yaml << YAML::EndMap; + } + void ReflectionUtilities::Deserialise(YAML::Node& yamlNode, Object^ object) + { + using namespace System::Reflection; - // // Return the result - // return Convert::ToCLI(std::string(buffer.GetString())); - //} - //void ReflectionUtilities::Deserialise(System::String^ jsonString, Object^ object) - //{ - // // Load the JSON - // rapidjson::Document json; - // auto& allocator = json.GetAllocator(); - // json.Parse(Convert::ToNative(jsonString).c_str()); + // 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^ fields = GetInstanceFields(object); + for each (FieldInfo^ field in fields) + { + // Ignore private and non-SerialiseField + if (!FieldIsSerialisable(field)) + continue; - // // Get the root object - // auto scriptRoot = json.MemberBegin(); - // if (scriptRoot == json.MemberEnd()) - // { - // Pls::Debug::LogError("[ReflectionUtilities] Attempted read of corrupted serialised object."); - // return; - // } - // - // // Get all fields - // IEnumerable^ 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); - // // Deserialise - // auto iter = scriptRoot->value.FindMember(Convert::ToNative(field->Name).c_str()); - // if (iter != scriptRoot->value.MemberEnd()) - // { - // // Get the data and set it in - // RapidJsonValueToField(iter->value, field, object); + // Field Value + yaml << YAML::Value; + if (fieldInsertYaml (fieldInfo, object, yaml) || + fieldInsertYaml (fieldInfo, object, yaml) || + fieldInsertYaml (fieldInfo, object, yaml) || + fieldInsertYaml(fieldInfo, object, yaml) || + fieldInsertYaml(fieldInfo, object, yaml) || + fieldInsertYaml(fieldInfo, object, yaml) || + fieldInsertYaml (fieldInfo, object, yaml) || + fieldInsertYaml (fieldInfo, object, yaml) || + fieldInsertYaml (fieldInfo, object, yaml) || + fieldInsertYaml (fieldInfo, object, yaml)) + { + return; + } + else if (fieldInfo->FieldType->IsSubclassOf(System::Enum::typeid)) + { + yaml << safe_cast(fieldInfo->GetValue(object)); + } + else if (fieldInfo->FieldType == System::String::typeid) + { + System::String^ str = safe_cast(fieldInfo->GetValue(object)); + yaml << Convert::ToNative(str); + } + else if (fieldInfo->FieldType == Vector2::typeid) + { + Vector2 vec = safe_cast(fieldInfo->GetValue(object)); + yaml << YAML::BeginSeq << YAML::Flow << vec.x << vec.y << YAML::EndSeq; + } + else if (fieldInfo->FieldType == Vector3::typeid) + { + Vector3 vec = safe_cast(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::Serialise(Object^ object, JsonWriter& writer) - //{ - // /* Script Name */ - // writer.String(Convert::ToNative(object->GetType()->FullName).c_str()); - - // /* Script Contents */ - // writer.StartObject(); - // IEnumerable^ fields = GetInstanceFields(object); - // for each (FieldInfo^ field in fields) - // { - // // Ignore private and non-SerialiseField - // if (!FieldIsSerialisable(field)) - // continue; - - // // Serialise - // serialiseFieldJson(field, object, writer); - // } - // writer.EndObject(); - //} - - ///*---------------------------------------------------------------------------------*/ - ///* Serialisation Helper Functions */ - ///*---------------------------------------------------------------------------------*/ - //rapidjson::Value ReflectionUtilities::FieldToRapidJsonValue(FieldInfo^ fieldInfo, Object^ object, JsonAllocator& allocator) - //{ - // rapidjson::Value jsonValue; - - // // Check each type of value and convert it into a rapidjson::Value - // if PRIMITIVE_FIELD_CAST(Int16) - // else if PRIMITIVE_FIELD_CAST(Int32) - // else if PRIMITIVE_FIELD_CAST(Int64) - // else if PRIMITIVE_FIELD_CAST(UInt16) - // else if PRIMITIVE_FIELD_CAST(UInt32) - // else if PRIMITIVE_FIELD_CAST(UInt64) - // else if PRIMITIVE_FIELD_CAST(Byte) - // else if PRIMITIVE_FIELD_CAST(bool) - // else if PRIMITIVE_FIELD_CAST(float) - // else if PRIMITIVE_FIELD_CAST(double) - // else if (fieldInfo->FieldType->IsSubclassOf(Enum::typeid)) - // { - // jsonValue = safe_cast(fieldInfo->GetValue(object)); - // } - // else if (fieldInfo->FieldType == String::typeid) - // { - // String^ str = safe_cast(fieldInfo->GetValue(object)); - // jsonValue.SetString(Convert::ToNative(str).c_str(), str->Length, allocator); - // } - // else if (fieldInfo->FieldType == Vector2::typeid) - // { - // jsonValue.SetObject(); - // Vector2 vec = safe_cast(fieldInfo->GetValue(object)); - // jsonValue.AddMember(rapidjson::Value("x"), rapidjson::Value(vec.x), allocator); - // jsonValue.AddMember(rapidjson::Value("y"), rapidjson::Value(vec.y), allocator); - // } - // else if (fieldInfo->FieldType == Vector3::typeid) - // { - // jsonValue.SetObject(); - // Vector3 vec = safe_cast(fieldInfo->GetValue(object)); - // jsonValue.AddMember(rapidjson::Value("x"), rapidjson::Value(vec.x), allocator); - // jsonValue.AddMember(rapidjson::Value("y"), rapidjson::Value(vec.y), allocator); - // jsonValue.AddMember(rapidjson::Value("z"), rapidjson::Value(vec.z), allocator); - // } - // else if (fieldInfo->FieldType == Color::typeid) - // { - // jsonValue.SetObject(); - // Color col = safe_cast(fieldInfo->GetValue(object)); - // jsonValue.AddMember(rapidjson::Value("r"), rapidjson::Value(col.r), allocator); - // jsonValue.AddMember(rapidjson::Value("g"), rapidjson::Value(col.g), allocator); - // jsonValue.AddMember(rapidjson::Value("b"), rapidjson::Value(col.b), allocator); - // jsonValue.AddMember(rapidjson::Value("a"), rapidjson::Value(col.a), allocator); - // } - // else if (IResourceID::typeid->IsAssignableFrom(fieldInfo->FieldType)) - // { - // IResourceID^ rscId = safe_cast(fieldInfo->GetValue(object)); - // jsonValue = rscId->Id; - // } - // else // Not any of the supported types - // { - // Pls::Debug::LogWarning(Convert::ToNative(String::Format - // ( - // "[ReflectionUtilities] Failed to parse \"{0}\" of \"{1}\" type for serialisation.", - // fieldInfo->Name, fieldInfo->FieldType) - // )); - // } - // return jsonValue; - //} - //void ReflectionUtilities::RapidJsonValueToField(const rapidjson::Value& jsonValue, FieldInfo^ fieldInfo, Object^ object) - //{ - // if PRIMITIVE_FIELD_ASSIGN(Int16, GetInt) - // else if PRIMITIVE_FIELD_ASSIGN(Int32, GetInt) - // else if PRIMITIVE_FIELD_ASSIGN(Int64, GetInt64) - // else if PRIMITIVE_FIELD_ASSIGN(UInt16, GetUint) - // else if PRIMITIVE_FIELD_ASSIGN(UInt32, GetUint) - // else if PRIMITIVE_FIELD_ASSIGN(UInt64, GetUint64) - // else if PRIMITIVE_FIELD_ASSIGN(Byte, GetInt) - // else if PRIMITIVE_FIELD_ASSIGN(bool, GetBool) - // else if PRIMITIVE_FIELD_ASSIGN(float, GetFloat) - // else if PRIMITIVE_FIELD_ASSIGN(double, GetDouble) - // else if (fieldInfo->FieldType->IsSubclassOf(Enum::typeid)) - // { - // fieldInfo->SetValue(object, jsonValue.GetInt()); - // } - // else if (fieldInfo->FieldType == String::typeid) - // { - // fieldInfo->SetValue(object, Convert::ToCLI(jsonValue.GetString())); - // } - // else if (fieldInfo->FieldType == Vector2::typeid) - // { - // Vector2 vec; - // auto iter = jsonValue.MemberEnd(); - // PRIMITIVE_VECTOR_FIELD_ASSIGN(x) - // PRIMITIVE_VECTOR_FIELD_ASSIGN(y) - // fieldInfo->SetValue(object, vec); - // } - // else if (fieldInfo->FieldType == Vector3::typeid) - // { - // Vector3 vec; - // auto iter = jsonValue.MemberEnd(); - // PRIMITIVE_VECTOR_FIELD_ASSIGN(x) - // PRIMITIVE_VECTOR_FIELD_ASSIGN(y) - // PRIMITIVE_VECTOR_FIELD_ASSIGN(z) - // fieldInfo->SetValue(object, vec); - // } - // else if (fieldInfo->FieldType == Color::typeid) - // { - // Color col; - // auto iter = jsonValue.MemberEnd(); - // PRIMITIVE_COLOR_FIELD_ASSIGN(r) - // PRIMITIVE_COLOR_FIELD_ASSIGN(g) - // PRIMITIVE_COLOR_FIELD_ASSIGN(b) - // PRIMITIVE_COLOR_FIELD_ASSIGN(a) - // fieldInfo->SetValue(object, col); - // } - // else if (IResourceIDInternal::typeid->IsAssignableFrom(fieldInfo->FieldType)) - // { - // IResourceIDInternal^ rsc = safe_cast(Activator::CreateInstance(fieldInfo->FieldType)); - // rsc->Id = jsonValue.GetInt64(); - // fieldInfo->SetValue(object, rsc); - // } - // else // Not any of the supported types - // { - // Pls::Debug::LogWarning(Convert::ToNative(String::Format - // ( - // "[ReflectionUtilities] Failed to parse \"{0}\" of \"{1}\" type for deserialisation.", - // fieldInfo->Name, fieldInfo->FieldType) - // )); - // } - //} - - ///*---------------------------------------------------------------------------------*/ - ///* Internal Serialisation Helper Functions */ - ///*---------------------------------------------------------------------------------*/ - //void ReflectionUtilities::serialiseFieldJson(FieldInfo^ fieldInfo, Object^ object, JsonWriter& writer) - //{ - // if PRIMITIVE_FIELD_SERIALISE_JSON(Int16, Int) - // else if PRIMITIVE_FIELD_SERIALISE_JSON(Int32, Int) - // else if PRIMITIVE_FIELD_SERIALISE_JSON(Int64, Int64) - // else if PRIMITIVE_FIELD_SERIALISE_JSON(UInt16, Uint) - // else if PRIMITIVE_FIELD_SERIALISE_JSON(UInt32, Uint) - // else if PRIMITIVE_FIELD_SERIALISE_JSON(UInt64, Uint64) - // else if PRIMITIVE_FIELD_SERIALISE_JSON(Byte, Int) - // else if PRIMITIVE_FIELD_SERIALISE_JSON(bool, Bool) - // else if PRIMITIVE_FIELD_SERIALISE_JSON(float, Double) - // else if PRIMITIVE_FIELD_SERIALISE_JSON(double, Double) - // else if PRIMITIVE_FIELD_SERIALISE_JSON(double, Double) - // else if (fieldInfo->FieldType->IsSubclassOf(Enum::typeid)) - // { - // PRIMITIVE_WRITE_FIELD_NAME - // writer.Int(safe_cast(fieldInfo->GetValue(object))); - - // } - // else if (fieldInfo->FieldType == String::typeid) - // { - // PRIMITIVE_WRITE_FIELD_NAME - // writer.String(Convert::ToNative(safe_cast(fieldInfo->GetValue(object))).c_str()); - - // } - // else if (fieldInfo->FieldType == Vector2::typeid) - // { - // // Get handle to the Vector to edit - // Vector2 vec = safe_cast(fieldInfo->GetValue(object)); - - // // Write the vector data - // PRIMITIVE_WRITE_FIELD_NAME - // writer.StartObject(); - // { - // PRIMITIVE_VECTOR_FIELD_SERIALISE_JSON(x) - // PRIMITIVE_VECTOR_FIELD_SERIALISE_JSON(y) - // } - // writer.EndObject(); - // } - // else if (fieldInfo->FieldType == Vector3::typeid) - // { - // // Get handle to the Vector to edit - // Vector3 vec = safe_cast(fieldInfo->GetValue(object)); - - // // Write the vector data - // PRIMITIVE_WRITE_FIELD_NAME - // writer.StartObject(); - // { - // PRIMITIVE_VECTOR_FIELD_SERIALISE_JSON(x) - // PRIMITIVE_VECTOR_FIELD_SERIALISE_JSON(y) - // PRIMITIVE_VECTOR_FIELD_SERIALISE_JSON(z) - // } - // writer.EndObject(); - // } - // else if (fieldInfo->FieldType == Color::typeid) - // { - // // Get handle to the Vector to edit - // Color vec = safe_cast(fieldInfo->GetValue(object)); - - // // Write the vector data - // PRIMITIVE_WRITE_FIELD_NAME - // writer.StartObject(); - // { - // PRIMITIVE_VECTOR_FIELD_SERIALISE_JSON(r) - // PRIMITIVE_VECTOR_FIELD_SERIALISE_JSON(g) - // PRIMITIVE_VECTOR_FIELD_SERIALISE_JSON(b) - // PRIMITIVE_VECTOR_FIELD_SERIALISE_JSON(a) - // } - // writer.EndObject(); - // } - // else if (IResourceID::typeid->IsAssignableFrom(fieldInfo->FieldType)) - // { - // PRIMITIVE_WRITE_FIELD_NAME - // IResourceID^ rsc = safe_cast(fieldInfo->GetValue(object)); - // writer.Int64(rsc->Id); - // } - // else // Not any of the supported types - // { - // Pls::Debug::LogWarning(Convert::ToNative(String::Format - // ( - // "[ReflectionUtilities] Failed to parse \"{0}\" of \"{1}\" type for serialisation.", - // 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()); + } + if (fieldAssignYaml (fieldInfo, object, node) || + fieldAssignYaml (fieldInfo, object, node) || + fieldAssignYaml (fieldInfo, object, node) || + fieldAssignYaml(fieldInfo, object, node) || + fieldAssignYaml(fieldInfo, object, node) || + fieldAssignYaml(fieldInfo, object, node) || + fieldAssignYaml (fieldInfo, object, node) || + fieldAssignYaml (fieldInfo, object, node) || + fieldAssignYaml (fieldInfo, object, node) || + fieldAssignYaml (fieldInfo, object, node)) + { + return; + } + else if (fieldInfo->FieldType->IsSubclassOf(System::Enum::typeid)) + { + fieldInfo->SetValue(object, node.as()); + } + else if (fieldInfo->FieldType == System::String::typeid) + { + fieldInfo->SetValue(object, Convert::ToCLI(node.as())); + } + else if (fieldInfo->FieldType == Vector2::typeid) + { + if (node.IsSequence() && node.size() == 2) + { + Vector2 vec; + vec.x = node[0].as(); + vec.y = node[1].as(); + 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(); + vec.y = node[1].as(); + vec.z = node[2].as(); + 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) + )); + } + } } diff --git a/SHADE_Managed/src/Serialisation/ReflectionUtilities.h++ b/SHADE_Managed/src/Serialisation/ReflectionUtilities.h++ new file mode 100644 index 00000000..88469b34 --- /dev/null +++ b/SHADE_Managed/src/Serialisation/ReflectionUtilities.h++ @@ -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 + bool ReflectionUtilities::fieldInsertYaml(System::Reflection::FieldInfo^ fieldInfo, System::Object^ object, YAML::Emitter& emitter) + { + if (fieldInfo->FieldType == FieldType::typeid) + { + emitter << safe_cast(fieldInfo->GetValue(object)); + return true; + } + + return false; + } + + template + bool ReflectionUtilities::fieldAssignYaml(System::Reflection::FieldInfo^ fieldInfo, Object^ object, YAML::Node& node) + { + return fieldAssignYaml(fieldInfo, object, node); + } + + template + bool ReflectionUtilities::fieldAssignYaml(System::Reflection::FieldInfo^ fieldInfo, Object^ object, YAML::Node& node) + { + if (fieldInfo->FieldType == FieldType::typeid) + { + fieldInfo->SetValue(object, node.as()); + return true; + } + + return false; + } +} diff --git a/SHADE_Managed/src/Serialisation/ReflectionUtilities.hxx b/SHADE_Managed/src/Serialisation/ReflectionUtilities.hxx index f312ec05..53f8fa1d 100644 --- a/SHADE_Managed/src/Serialisation/ReflectionUtilities.hxx +++ b/SHADE_Managed/src/Serialisation/ReflectionUtilities.hxx @@ -14,9 +14,7 @@ of DigiPen Institute of Technology is prohibited. #pragma once // External Dependencies -#include -#include - +#include namespace SHADE { @@ -26,10 +24,6 @@ namespace SHADE private ref class ReflectionUtilities abstract sealed { public: - /*-----------------------------------------------------------------------------*/ - /* Type Definitions */ - /*-----------------------------------------------------------------------------*/ - /*-----------------------------------------------------------------------------*/ /* Utility Functions */ /*-----------------------------------------------------------------------------*/ @@ -58,16 +52,30 @@ namespace SHADE /// attribute will be serialised. /// /// The object to serialise. - //static void Serialise(Object^ object, YAML::Emitter& yaml); + static void Serialise(System::Object^ object, YAML::Emitter& yaml); /// - /// Deserialises a JSON string and copies the deserialised data into the - /// specified object if there are matching fields. + /// Deserialises a YAML node that contains a map of Scripts and copies the + /// deserialised data into the specified object if there are matching fields. /// - /// + /// /// The JSON string that contains the data to copy into this PlushieScript /// object. /// /// The object to copy deserialised data into. - //static void Deserialise(System::String^ jsonString, Object^ object); + static void Deserialise(YAML::Node& yamlNode, Object^ object); + + /*-----------------------------------------------------------------------------*/ + /* Serialization Helper Functions */ + /*-----------------------------------------------------------------------------*/ + static void writeFieldIntoYaml(System::Reflection::FieldInfo^ fieldInfo, Object^ object, YAML::Emitter& yaml); + template + 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 + static bool fieldAssignYaml(System::Reflection::FieldInfo^ fieldInfo, Object^ object, YAML::Node& node); + template + static bool fieldAssignYaml(System::Reflection::FieldInfo^ fieldInfo, Object^ object, YAML::Node& node); }; -} \ No newline at end of file +} + +#include "ReflectionUtilities.h++" \ No newline at end of file From 0f63ee10d07ce2d06816d070b5b19dbf3952c897 Mon Sep 17 00:00:00 2001 From: Kah Wei Date: Fri, 16 Sep 2022 16:37:50 +0800 Subject: [PATCH 04/24] Converted SHScriptEngine into a SHSystem --- .../src/Application/SBApplication.cpp | 6 +- SHADE_Engine/src/Scripting/SHScriptEngine.cpp | 29 ++------ SHADE_Engine/src/Scripting/SHScriptEngine.h | 73 ++++++++++--------- 3 files changed, 43 insertions(+), 65 deletions(-) diff --git a/SHADE_Application/src/Application/SBApplication.cpp b/SHADE_Application/src/Application/SBApplication.cpp index f4c76db7..a89ea833 100644 --- a/SHADE_Application/src/Application/SBApplication.cpp +++ b/SHADE_Application/src/Application/SBApplication.cpp @@ -37,7 +37,7 @@ namespace Sandbox SHADE::SHSystemManager::CreateSystem(); SHADE::SHGraphicsSystem* graphicsSystem = static_cast(SHADE::SHSystemManager::GetSystem()); SHADE::SHSystemManager::RegisterRoutine(1); - + SHADE::SHSystemManager::CreateSystem(); graphicsSystem->SetWindow(&window); SDL_CreateWindowFrom(window.GetHWND()); @@ -47,9 +47,6 @@ namespace Sandbox //SHADE::SHEditor::Initialize(window.GetHWND()); #else #endif - - // Set up scripting - SHADE::SHScriptEngine::Init(); } void SBApplication::Update(void) @@ -76,7 +73,6 @@ namespace Sandbox void SBApplication::Exit(void) { - SHADE::SHScriptEngine::Exit(); SHADE::SHSystemManager::Exit(); SDL_DestroyWindow(sdlWindow); #ifdef SHEDITOR diff --git a/SHADE_Engine/src/Scripting/SHScriptEngine.cpp b/SHADE_Engine/src/Scripting/SHScriptEngine.cpp index b5a33c6d..c5490b1e 100644 --- a/SHADE_Engine/src/Scripting/SHScriptEngine.cpp +++ b/SHADE_Engine/src/Scripting/SHScriptEngine.cpp @@ -26,25 +26,6 @@ namespace SHADE /* 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; /*---------------------------------------------------------------------------------*/ /* Lifecycle Functions */ @@ -137,7 +118,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; @@ -162,7 +143,7 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ /* Script Serialisation Functions */ /*---------------------------------------------------------------------------------*/ - void SHScriptEngine::DeserialiseScript(const SHEntity& entity, const std::string& yaml) + void SHScriptEngine::DeserialiseScript(const SHEntity& entity, const std::string& yaml) const { csScriptDeserialise(entity.GetEID(), yaml.c_str()); } @@ -170,7 +151,7 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ /* Script Editor Functions */ /*---------------------------------------------------------------------------------*/ - void SHScriptEngine::RenderScriptsInInspector(const SHEntity& entity) + void SHScriptEngine::RenderScriptsInInspector(const SHEntity& entity) const { csEditorRenderScripts(entity.GetEID()); } @@ -178,7 +159,7 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ /* Static Utility Functions */ /*---------------------------------------------------------------------------------*/ - bool SHScriptEngine::BuildScriptAssembly(bool debug) + bool SHScriptEngine::BuildScriptAssembly(bool debug) const { constexpr std::string_view BUILD_LOG_PATH = "../Build.log"; @@ -230,7 +211,7 @@ namespace SHADE 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 = diff --git a/SHADE_Engine/src/Scripting/SHScriptEngine.h b/SHADE_Engine/src/Scripting/SHScriptEngine.h index 442c0053..4988f594 100644 --- a/SHADE_Engine/src/Scripting/SHScriptEngine.h +++ b/SHADE_Engine/src/Scripting/SHScriptEngine.h @@ -18,6 +18,7 @@ of DigiPen Institute of Technology is prohibited. #include "SHDotNetRuntime.h" #include "ECS_Base/SHECSMacros.h" #include "ECS_Base/Entity/SHEntity.h" +#include "ECS_Base/System/SHSystem.h" #include "SH_API.h" namespace SHADE @@ -26,13 +27,13 @@ namespace SHADE /// Manages initialisation of the DotNetRuntime and interfacing with CLR code written /// and executed on .NET. /// - class SH_API SHScriptEngine + class SH_API SHScriptEngine : public SHSystem { public: /*-----------------------------------------------------------------------------*/ /* Constructor */ /*-----------------------------------------------------------------------------*/ - SHScriptEngine() = delete; + SHScriptEngine() = default; /*-----------------------------------------------------------------------------*/ /* Lifecycle Functions */ @@ -41,33 +42,33 @@ namespace SHADE /// Initialises the DotNetRuntime and retrieves function pointers to all /// functions on the CLR used to interface with the engine. /// - static void Init(); + void Init() override; /// /// Loads the managed script assembly. Ensure this is only called after /// UnloadScriptAssembly() has been called. /// - static void UnloadScriptAssembly(); + void UnloadScriptAssembly(); /// /// Unloads the managed script assembly. /// Take note that this will clear all existing scripts, ensure that the scene /// is saved before doing so. /// - static void LoadScriptAssembly(); + void LoadScriptAssembly(); /// /// Reloads the managed script assembly. /// Take note that this will clear all existing scripts, ensure that the scene /// is saved before doing so. /// - static void ReloadScriptAssembly(); + void ReloadScriptAssembly(); /// /// Executes the FixedUpdate()s of the Scripts that are attached to /// Entities. /// - static void ExecuteFixedUpdates(); + void ExecuteFixedUpdates(); /// /// Shuts down the DotNetRuntime. /// - static void Exit(); + void Exit() override; /*-----------------------------------------------------------------------------*/ /* Script Manipulation Functions */ @@ -84,14 +85,14 @@ namespace SHADE /// True if successfully added. False otherwise with the error logged to the /// console. /// - static bool AddScript(const SHEntity& entity, const std::string_view& scriptName); + bool AddScript(const SHEntity& entity, const std::string_view& scriptName); /// /// 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. /// /// The entity to remove the scripts from. - static void RemoveAllScripts(const SHEntity& entity); + void RemoveAllScripts(const SHEntity& entity); /// /// Removes all Scripts attached to the specified Entity. Unlike /// RemoveAllScripts(), this removes all the scripts immediately. @@ -103,7 +104,7 @@ namespace SHADE /// Whether or not to call OnDestroy on the scripts. This is ignored if not in /// play mode. /// - static void RemoveAllScriptsImmediately(const SHEntity& entity, bool callOnDestroy); + void RemoveAllScriptsImmediately(const SHEntity& entity, bool callOnDestroy); /*-----------------------------------------------------------------------------*/ /* Script Serialisation Functions */ @@ -116,7 +117,7 @@ namespace SHADE /// /// String that represents the set of scripts attached to the specified Entity. /// - static std::string SerialiseScripts(const SHEntity& entity); + std::string SerialiseScripts(const SHEntity& entity) const; /// /// Loads the specified JSON string and creates a Script for the specified Entity /// based on the specified JSON string. @@ -125,7 +126,7 @@ namespace SHADE /// /// The YAML string that represents the Script to load into the Entity. /// - 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 +139,7 @@ namespace SHADE /// rendering code. /// /// The Entity to render the Scripts of. - static void RenderScriptsInInspector(const SHEntity& entity); + void RenderScriptsInInspector(const SHEntity& entity) const; /*-----------------------------------------------------------------------------*/ /* Static Utility Functions */ @@ -153,12 +154,12 @@ namespace SHADE /// can be debugged. /// /// Whether or not the build succeeded. - static bool BuildScriptAssembly(bool debug = false); + bool BuildScriptAssembly(bool debug = false) const; /// /// Generates a .csproj file for editing and compiling the C# scripts. /// /// File path to the generated file. - static void GenerateScriptsCsProjFile(const std::filesystem::path& path); + void GenerateScriptsCsProjFile(const std::filesystem::path& path) const; private: /*-----------------------------------------------------------------------------*/ @@ -183,29 +184,29 @@ namespace SHADE /*-----------------------------------------------------------------------------*/ /* 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;*/ @@ -216,7 +217,7 @@ namespace SHADE /// /// Loads all the function pointers to CLR code that we need to execute. /// - static void loadFunctions(); + void loadFunctions(); /// /// Reads the file via the specified path that represents a build log of error /// and warning messages. From c83a5a379e2a16d054ee7c9877478355476ab512 Mon Sep 17 00:00:00 2001 From: Kah Wei Date: Fri, 16 Sep 2022 17:02:36 +0800 Subject: [PATCH 05/24] Added Awake, Start, Update, LateUpdate, OnDestroy calls via SystemRoutines --- .../src/Application/SBApplication.cpp | 12 +++- SHADE_Engine/src/ECS_Base/System/SHSystem.h | 3 +- .../src/ECS_Base/System/SHSystemRoutine.h | 3 +- SHADE_Engine/src/Scripting/SHScriptEngine.cpp | 1 - SHADE_Engine/src/Scripting/SHScriptEngine.h | 31 ++++++++- .../src/Scripting/SHScriptEngineRoutines.cpp | 63 +++++++++++++++++++ 6 files changed, 107 insertions(+), 6 deletions(-) create mode 100644 SHADE_Engine/src/Scripting/SHScriptEngineRoutines.cpp diff --git a/SHADE_Application/src/Application/SBApplication.cpp b/SHADE_Application/src/Application/SBApplication.cpp index a89ea833..8f17863f 100644 --- a/SHADE_Application/src/Application/SBApplication.cpp +++ b/SHADE_Application/src/Application/SBApplication.cpp @@ -34,11 +34,19 @@ namespace Sandbox SDL_Init(SDL_INIT_VIDEO); window.Create(hInstance, hPrevInstance, lpCmdLine, nCmdShow); + + // Create Systems SHADE::SHSystemManager::CreateSystem(); - SHADE::SHGraphicsSystem* graphicsSystem = static_cast(SHADE::SHSystemManager::GetSystem()); - SHADE::SHSystemManager::RegisterRoutine(1); SHADE::SHSystemManager::CreateSystem(); + // Create Routines + SHADE::SHSystemManager::RegisterRoutine(); + SHADE::SHSystemManager::RegisterRoutine(); + SHADE::SHSystemManager::RegisterRoutine(); + SHADE::SHSystemManager::RegisterRoutine(1); + SHADE::SHSystemManager::RegisterRoutine(); + + SHADE::SHGraphicsSystem* graphicsSystem = static_cast(SHADE::SHSystemManager::GetSystem()); graphicsSystem->SetWindow(&window); SDL_CreateWindowFrom(window.GetHWND()); diff --git a/SHADE_Engine/src/ECS_Base/System/SHSystem.h b/SHADE_Engine/src/ECS_Base/System/SHSystem.h index 19b16f72..93ea6a59 100644 --- a/SHADE_Engine/src/ECS_Base/System/SHSystem.h +++ b/SHADE_Engine/src/ECS_Base/System/SHSystem.h @@ -11,13 +11,14 @@ #pragma once #include "../SHECSMacros.h" +#include "SH_API.h" namespace SHADE { class SHSystemManager; - class SHSystem + class SH_API SHSystem { private: SystemID systemID; diff --git a/SHADE_Engine/src/ECS_Base/System/SHSystemRoutine.h b/SHADE_Engine/src/ECS_Base/System/SHSystemRoutine.h index cdb62438..2b6d8dc1 100644 --- a/SHADE_Engine/src/ECS_Base/System/SHSystemRoutine.h +++ b/SHADE_Engine/src/ECS_Base/System/SHSystemRoutine.h @@ -7,6 +7,7 @@ #include "SHRoutineStats.h" #include "SHSystem.h" #include +#include "SH_API.h" namespace SHADE @@ -15,7 +16,7 @@ namespace SHADE class SHSystemManager; - class SHSystemRoutine + class SH_API SHSystemRoutine { friend class SHSystemManager; protected: diff --git a/SHADE_Engine/src/Scripting/SHScriptEngine.cpp b/SHADE_Engine/src/Scripting/SHScriptEngine.cpp index c5490b1e..78b4d544 100644 --- a/SHADE_Engine/src/Scripting/SHScriptEngine.cpp +++ b/SHADE_Engine/src/Scripting/SHScriptEngine.cpp @@ -483,5 +483,4 @@ namespace SHADE } } } - } diff --git a/SHADE_Engine/src/Scripting/SHScriptEngine.h b/SHADE_Engine/src/Scripting/SHScriptEngine.h index 4988f594..f3d69dd5 100644 --- a/SHADE_Engine/src/Scripting/SHScriptEngine.h +++ b/SHADE_Engine/src/Scripting/SHScriptEngine.h @@ -19,6 +19,7 @@ of DigiPen Institute of Technology is prohibited. #include "ECS_Base/SHECSMacros.h" #include "ECS_Base/Entity/SHEntity.h" #include "ECS_Base/System/SHSystem.h" +#include "ECS_Base/System/SHSystemRoutine.h" #include "SH_API.h" namespace SHADE @@ -27,9 +28,37 @@ namespace SHADE /// Manages initialisation of the DotNetRuntime and interfacing with CLR code written /// and executed on .NET. /// - class SH_API SHScriptEngine : public SHSystem + 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 */ /*-----------------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Scripting/SHScriptEngineRoutines.cpp b/SHADE_Engine/src/Scripting/SHScriptEngineRoutines.cpp new file mode 100644 index 00000000..5467fc56 --- /dev/null +++ b/SHADE_Engine/src/Scripting/SHScriptEngineRoutines.cpp @@ -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 +// 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(system)->csScriptsFrameSetUp(); + } + + /*-----------------------------------------------------------------------------------*/ + /* System Routine Functions - UpdateRoutine */ + /*-----------------------------------------------------------------------------------*/ + SHScriptEngine::UpdateRoutine::UpdateRoutine() + : SHSystemRoutine("Script Engine Update", false) + {} + void SHScriptEngine::UpdateRoutine::Execute(double) noexcept + { + reinterpret_cast(system)->csScriptsExecuteUpdate(); + } + + /*-----------------------------------------------------------------------------------*/ + /* System Routine Functions - LateUpdateRoutine */ + /*-----------------------------------------------------------------------------------*/ + SHScriptEngine::LateUpdateRoutine::LateUpdateRoutine() + : SHSystemRoutine("Script Engine Late Update", false) + {} + void SHScriptEngine::LateUpdateRoutine::Execute(double) noexcept + { + reinterpret_cast(system)->csScriptsExecuteLateUpdate(); + } + + /*-----------------------------------------------------------------------------------*/ + /* System Routine Functions - FrameCleanUpRoutine */ + /*-----------------------------------------------------------------------------------*/ + SHScriptEngine::FrameCleanUpRoutine::FrameCleanUpRoutine() + : SHSystemRoutine("Script Engine Frame Clean Up", false) + {} + void SHScriptEngine::FrameCleanUpRoutine::Execute(double) noexcept + { + reinterpret_cast(system)->csScriptsFrameCleanUp(); + } +} From 5171ddd2bf2a2d6fcaddfb9c7ef848e246393f25 Mon Sep 17 00:00:00 2001 From: Kah Wei Date: Sat, 17 Sep 2022 03:20:24 +0800 Subject: [PATCH 06/24] Added SHLog class and changed Debug::Log to use SHLog --- SHADE_Engine/src/Tools/SHLog.cpp | 54 +++++++++++++++++++++++++++++ SHADE_Engine/src/Tools/SHLog.h | 48 +++++++++++++++++++++++++ SHADE_Managed/src/Utility/Debug.cxx | 30 ++++++++-------- 3 files changed, 118 insertions(+), 14 deletions(-) create mode 100644 SHADE_Engine/src/Tools/SHLog.cpp create mode 100644 SHADE_Engine/src/Tools/SHLog.h diff --git a/SHADE_Engine/src/Tools/SHLog.cpp b/SHADE_Engine/src/Tools/SHLog.cpp new file mode 100644 index 00000000..2d0b7b58 --- /dev/null +++ b/SHADE_Engine/src/Tools/SHLog.cpp @@ -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 + +} diff --git a/SHADE_Engine/src/Tools/SHLog.h b/SHADE_Engine/src/Tools/SHLog.h new file mode 100644 index 00000000..b77042db --- /dev/null +++ b/SHADE_Engine/src/Tools/SHLog.h @@ -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 +// 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 + }; +} diff --git a/SHADE_Managed/src/Utility/Debug.cxx b/SHADE_Managed/src/Utility/Debug.cxx index 330375b0..8a107ab3 100644 --- a/SHADE_Managed/src/Utility/Debug.cxx +++ b/SHADE_Managed/src/Utility/Debug.cxx @@ -18,6 +18,8 @@ of DigiPen Institute of Technology is prohibited. #include "Debug.hxx" // Standard Libraries #include +// 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()); } } From 8772ce0ceac8421bd591850c900c68ae74db611d Mon Sep 17 00:00:00 2001 From: Kah Wei Date: Tue, 20 Sep 2022 00:03:29 +0800 Subject: [PATCH 07/24] Fixed SHSceneManager not SH_API-ed --- SHADE_Engine/src/Scene/SHSceneManager.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/SHADE_Engine/src/Scene/SHSceneManager.h b/SHADE_Engine/src/Scene/SHSceneManager.h index bdd8f596..9682e4c2 100644 --- a/SHADE_Engine/src/Scene/SHSceneManager.h +++ b/SHADE_Engine/src/Scene/SHSceneManager.h @@ -16,11 +16,12 @@ #include "ECS_Base/General/SHFamily.h" #include "SHScene.h" #include +#include "SH_API.h" namespace SHADE { - class SHSceneManager + class SH_API SHSceneManager { private: //boolean to check if the scene has been changed From 9896c5c913e237188c7c417a5b272aa85b43547a Mon Sep 17 00:00:00 2001 From: Kah Wei Date: Tue, 20 Sep 2022 16:23:03 +0800 Subject: [PATCH 08/24] Added CallbackAction and CallbackEvent --- SHADE_Managed/src/Events/CallbackAction.cxx | 48 ++++++++++++ SHADE_Managed/src/Events/CallbackAction.hxx | 57 ++++++++++++++ SHADE_Managed/src/Events/CallbackEvent.cxx | 71 +++++++++++++++++ SHADE_Managed/src/Events/CallbackEvent.hxx | 85 +++++++++++++++++++++ SHADE_Managed/src/Math/Vector2.hxx | 2 +- 5 files changed, 262 insertions(+), 1 deletion(-) create mode 100644 SHADE_Managed/src/Events/CallbackAction.cxx create mode 100644 SHADE_Managed/src/Events/CallbackAction.hxx create mode 100644 SHADE_Managed/src/Events/CallbackEvent.cxx create mode 100644 SHADE_Managed/src/Events/CallbackEvent.hxx diff --git a/SHADE_Managed/src/Events/CallbackAction.cxx b/SHADE_Managed/src/Events/CallbackAction.cxx new file mode 100644 index 00000000..0ad356c1 --- /dev/null +++ b/SHADE_Managed/src/Events/CallbackAction.cxx @@ -0,0 +1,48 @@ +/************************************************************************************//*! +\file CallbackAction.cxx +\author Tng Kah Wei, kahwei.tng, 390009620 +\par email: kahwei.tng\@digipen.edu +\date Sep 20, 2022 +\brief Contains the definition of the functions for the CallbackAction managed + 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 "CallbackAction.hxx" + +namespace SHADE +{ + /*---------------------------------------------------------------------------------*/ + /* Constructors */ + /*---------------------------------------------------------------------------------*/ + generic + CallbackAction::CallbackAction(System::Reflection::MethodInfo^ method) + : CallbackAction(method, nullptr) + {} + generic + CallbackAction::CallbackAction(System::Reflection::MethodInfo^ method, System::Object^ obj) + : method { method } + , object { obj } + { + paramArray = gcnew cli::array(1); + } + + /*---------------------------------------------------------------------------------*/ + /* Usage Functions */ + /*---------------------------------------------------------------------------------*/ + generic + void CallbackAction::Invoke(T1 param1) + { + // Set parameters + paramArray[0] = safe_cast(param1); + // Invoke + method->Invoke(object, paramArray); + } +} diff --git a/SHADE_Managed/src/Events/CallbackAction.hxx b/SHADE_Managed/src/Events/CallbackAction.hxx new file mode 100644 index 00000000..f8b50266 --- /dev/null +++ b/SHADE_Managed/src/Events/CallbackAction.hxx @@ -0,0 +1,57 @@ +/************************************************************************************//*! +\file CallbackAction.hxx +\author Tng Kah Wei, kahwei.tng, 390009620 +\par email: kahwei.tng\@digipen.edu +\date Sep 20, 2021 +\brief Contains the definition of the managed CallbackAction 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 + +namespace SHADE +{ + /// + /// Holds a function and their associated object for invoking later. + /// + /// Type of the first parameter. + generic + public ref class CallbackAction + { + public: + /*-----------------------------------------------------------------------------*/ + /* Constructors */ + /*-----------------------------------------------------------------------------*/ + /// + /// Constructs a CallbackAction with the specified static method. + /// + /// MethodInfo representing the method to call. + /// Object to call the method on. Set null if static. + CallbackAction(System::Reflection::MethodInfo^ method); + /// + /// Constructs a CallbackAction with the specified instance method and object + /// which will invoke the method. + /// + /// MethodInfo representing the method to call. + /// Object to call the method on. + CallbackAction(System::Reflection::MethodInfo^ method, System::Object^ obj); + + /*-----------------------------------------------------------------------------*/ + /* Usage Functions */ + /*-----------------------------------------------------------------------------*/ + /// + /// Invokes this action with the specified parameters. + /// + /// + void Invoke(T1 param1); + + private: + System::Reflection::MethodInfo^ method; + cli::array^ paramArray; + System::Object^ object; + }; +} \ No newline at end of file diff --git a/SHADE_Managed/src/Events/CallbackEvent.cxx b/SHADE_Managed/src/Events/CallbackEvent.cxx new file mode 100644 index 00000000..9ba82ef2 --- /dev/null +++ b/SHADE_Managed/src/Events/CallbackEvent.cxx @@ -0,0 +1,71 @@ +/************************************************************************************//*! +\file CallbackEvent.cxx +\author Tng Kah Wei, kahwei.tng, 390009620 +\par email: kahwei.tng\@digipen.edu +\date Sep 20, 2022 +\brief Contains the definition of the functions for the CallbackEvent managed + 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 "CallbackEvent.hxx" + +namespace SHADE +{ + /*---------------------------------------------------------------------------------*/ + /* Constructors */ + /*---------------------------------------------------------------------------------*/ + generic + CallbackEvent::CallbackEvent() + { + actions = gcnew System::Collections::Generic::List ^>(); + } + + /*---------------------------------------------------------------------------------*/ + /* Properties */ + /*---------------------------------------------------------------------------------*/ + generic + System::Collections::Generic::IEnumerable^>^ CallbackEvent::Actions::get() + { + return actions; + } + + /*---------------------------------------------------------------------------------*/ + /* Usage Functions */ + /*---------------------------------------------------------------------------------*/ + generic + void CallbackEvent::AddAction(CallbackAction^ action) + { + actions->Add(action); + } + generic + void CallbackEvent::AddAction(System::Reflection::MethodInfo^ method) + { + actions->Add(gcnew CallbackAction(method)); + } + generic + void CallbackEvent::AddAction(System::Reflection::MethodInfo^ method, System::Object^ object) + { + actions->Add(gcnew CallbackAction(method, object)); + } + generic + void CallbackEvent::RemoveAction(CallbackAction^ action) + { + actions->Remove(action); + } + generic + void CallbackEvent::Invoke(T1 param1) + { + for each (CallbackAction^ action in actions) + { + action->Invoke(param1); + } + } +} diff --git a/SHADE_Managed/src/Events/CallbackEvent.hxx b/SHADE_Managed/src/Events/CallbackEvent.hxx new file mode 100644 index 00000000..d0d6d2f1 --- /dev/null +++ b/SHADE_Managed/src/Events/CallbackEvent.hxx @@ -0,0 +1,85 @@ +/************************************************************************************//*! +\file CallbackEvent.hxx +\author Tng Kah Wei, kahwei.tng, 390009620 +\par email: kahwei.tng\@digipen.edu +\date Sep 20, 2021 +\brief Contains the definition of the managed CallbackEvent 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 + +#include "CallbackAction.hxx" + +namespace SHADE +{ + /// + /// Holds a set of CallbackActions that can be invoked together at a later time. + /// + /// Type of the first parameter. + generic + public ref class CallbackEvent + { + public: + /*-----------------------------------------------------------------------------*/ + /* Constructors */ + /*-----------------------------------------------------------------------------*/ + /// + /// Default Constructor + /// + CallbackEvent(); + + /*-----------------------------------------------------------------------------*/ + /* Properties */ + /*-----------------------------------------------------------------------------*/ + /// + /// Read only access to the list of Actions + /// + property System::Collections::Generic::IEnumerable^>^ Actions + { + System::Collections::Generic::IEnumerable^>^ get(); + } + + /*-----------------------------------------------------------------------------*/ + /* Usage Functions */ + /*-----------------------------------------------------------------------------*/ + /// + /// Adds the specified CallbackAction to the CallbackEvent. + /// + /// CallbackAction to add. + void AddAction(CallbackAction^ action); + /// + /// Adds a specified static method as a CallbackAction to the CallbackEvent. + /// + /// Method to add. + void AddAction(System::Reflection::MethodInfo^ method); + /// + /// Adds a specified instance method and associated object as a CallbackAction to + /// the CallbackEvent. + /// + /// Method to add. + /// Object that will call the specified method. + void AddAction(System::Reflection::MethodInfo^ method, System::Object^ object); + /// + /// Removes the specified CallbackAction from the CallbackEvent. + /// + /// CallbackAction to remove. + void RemoveAction(CallbackAction^ action); + /// + /// Invokes all CallbackActions registered with this CallbackEvent with the + /// specified parameters. + /// + /// + void Invoke(T1 param1); + + private: + /*-----------------------------------------------------------------------------*/ + /* Data Members */ + /*-----------------------------------------------------------------------------*/ + System::Collections::Generic::List^>^ actions; + }; +} \ No newline at end of file diff --git a/SHADE_Managed/src/Math/Vector2.hxx b/SHADE_Managed/src/Math/Vector2.hxx index 69a6110f..9253a703 100644 --- a/SHADE_Managed/src/Math/Vector2.hxx +++ b/SHADE_Managed/src/Math/Vector2.hxx @@ -19,7 +19,7 @@ of DigiPen Institute of Technology is prohibited. namespace SHADE { /// - /// 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. /// [System::Runtime::InteropServices::StructLayout(System::Runtime::InteropServices::LayoutKind::Sequential)] From af1d24d874b990acde823fbeeace6121c36c87b1 Mon Sep 17 00:00:00 2001 From: Kah Wei Date: Thu, 22 Sep 2022 10:52:07 +0800 Subject: [PATCH 09/24] Fixed certain DLLs and includes missing when copying --- Dependencies.lua | 28 ++++++++++++++-------------- SHADE_Engine/premake5.lua | 24 ++++++++++++------------ 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/Dependencies.lua b/Dependencies.lua index 9877a70e..824b512d 100644 --- a/Dependencies.lua +++ b/Dependencies.lua @@ -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" diff --git a/SHADE_Engine/premake5.lua b/SHADE_Engine/premake5.lua index 74f19f96..84acd8fa 100644 --- a/SHADE_Engine/premake5.lua +++ b/SHADE_Engine/premake5.lua @@ -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' From 21a3d6ecd778cc9a2b3c80a9ba7944f9f45038dd Mon Sep 17 00:00:00 2001 From: Kah Wei Date: Thu, 22 Sep 2022 11:22:51 +0800 Subject: [PATCH 10/24] Added test code for scripts --- SHADE_Application/src/Scenes/SBTestScene.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/SHADE_Application/src/Scenes/SBTestScene.cpp b/SHADE_Application/src/Scenes/SBTestScene.cpp index 873d0fed..072a15de 100644 --- a/SHADE_Application/src/Scenes/SBTestScene.cpp +++ b/SHADE_Application/src/Scenes/SBTestScene.cpp @@ -7,6 +7,7 @@ #include "Graphics/MiddleEnd/Interface/SHRenderable.h" #include "Scene/SHSceneManager.h" #include "Graphics/MiddleEnd/Interface/SHGraphicsSystem.h" +#include "Scripting/SHScriptEngine.h" using namespace SHADE; @@ -42,6 +43,8 @@ namespace Sandbox renderable.Mesh = CUBE_MESH; renderable.SetMaterial(matInst); renderable.TransformMatrix.Translate(0.0f, 0.0f, 2.0f); + SHADE::SHScriptEngine* scriptEngine = static_cast(SHADE::SHSystemManager::GetSystem()); + scriptEngine->AddScript(*SHADE::SHEntityManager::GetEntityByID(entity), "TestScript"); } void SBTestScene::Update(float dt) { From 495824080696cbe62bd979ab286118d322fd4ae6 Mon Sep 17 00:00:00 2001 From: Kah Wei Date: Thu, 22 Sep 2022 11:37:24 +0800 Subject: [PATCH 11/24] Added implementation of GetComponentInChildren() for scripts --- SHADE_Managed/src/Engine/ECS.cxx | 45 ++++++++++++--------- SHADE_Managed/src/Engine/GameObject.cxx | 2 +- SHADE_Managed/src/Scripts/ScriptStore.cxx | 48 ++++++++++++----------- 3 files changed, 52 insertions(+), 43 deletions(-) diff --git a/SHADE_Managed/src/Engine/ECS.cxx b/SHADE_Managed/src/Engine/ECS.cxx index e4405006..36bef851 100644 --- a/SHADE_Managed/src/Engine/ECS.cxx +++ b/SHADE_Managed/src/Engine/ECS.cxx @@ -21,6 +21,9 @@ of DigiPen Institute of Technology is prohibited. #include // 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(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(child); - // if (component != nullptr) - // return component; - //} + // Search direct children first + for (const auto& child : sceneGraphNode->GetChildren()) + { + T component = GetComponent(child->GetEntityID()); + if (component != nullptr) + return component; + } - //// Search their children - //for (const auto& child : tf->GetChildren()) - //{ - // T script = GetComponentInChildren(child); - // if (script != nullptr) - // return script; - //} + // Search their children + for (const auto& child : sceneGraphNode->GetChildren()) + { + T component = GetComponentInChildren(child->GetEntityID()); + if (component != nullptr) + return component; + } // None here return T(); diff --git a/SHADE_Managed/src/Engine/GameObject.cxx b/SHADE_Managed/src/Engine/GameObject.cxx index 1fbc3b4a..8c78e399 100644 --- a/SHADE_Managed/src/Engine/GameObject.cxx +++ b/SHADE_Managed/src/Engine/GameObject.cxx @@ -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 } /*---------------------------------------------------------------------------------*/ diff --git a/SHADE_Managed/src/Scripts/ScriptStore.cxx b/SHADE_Managed/src/Scripts/ScriptStore.cxx index d30cad6b..089da002 100644 --- a/SHADE_Managed/src/Scripts/ScriptStore.cxx +++ b/SHADE_Managed/src/Scripts/ScriptStore.cxx @@ -20,6 +20,7 @@ of DigiPen Institute of Technology is prohibited. #include // 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(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(Convert::ToCLI(child)); - // if (script != nullptr) - // return script; - //} + // Search direct children first + for (const auto& child : sceneGraphNode->GetChildren()) + { + T script = GetScript(child->GetEntityID()); + if (script != nullptr) + return script; + } - //// Search their children - //for (const auto& child : tf->GetChildren()) - //{ - // T script = GetScriptInChildren(Convert::ToCLI(child)); - // if (script != nullptr) - // return script; - //} + // Search their children + for (const auto& child : sceneGraphNode->GetChildren()) + { + T script = GetScript(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)) { From 5ff375113ff658a78b0ea1177bb453bdd7d3632c Mon Sep 17 00:00:00 2001 From: Kah Wei Date: Thu, 22 Sep 2022 11:39:50 +0800 Subject: [PATCH 12/24] Removed CallbackAction and CallbackEvent for moving to C# library in future --- SHADE_Managed/src/Events/CallbackAction.cxx | 48 ------------ SHADE_Managed/src/Events/CallbackAction.hxx | 57 -------------- SHADE_Managed/src/Events/CallbackEvent.cxx | 71 ----------------- SHADE_Managed/src/Events/CallbackEvent.hxx | 85 --------------------- 4 files changed, 261 deletions(-) delete mode 100644 SHADE_Managed/src/Events/CallbackAction.cxx delete mode 100644 SHADE_Managed/src/Events/CallbackAction.hxx delete mode 100644 SHADE_Managed/src/Events/CallbackEvent.cxx delete mode 100644 SHADE_Managed/src/Events/CallbackEvent.hxx diff --git a/SHADE_Managed/src/Events/CallbackAction.cxx b/SHADE_Managed/src/Events/CallbackAction.cxx deleted file mode 100644 index 0ad356c1..00000000 --- a/SHADE_Managed/src/Events/CallbackAction.cxx +++ /dev/null @@ -1,48 +0,0 @@ -/************************************************************************************//*! -\file CallbackAction.cxx -\author Tng Kah Wei, kahwei.tng, 390009620 -\par email: kahwei.tng\@digipen.edu -\date Sep 20, 2022 -\brief Contains the definition of the functions for the CallbackAction managed - 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 "CallbackAction.hxx" - -namespace SHADE -{ - /*---------------------------------------------------------------------------------*/ - /* Constructors */ - /*---------------------------------------------------------------------------------*/ - generic - CallbackAction::CallbackAction(System::Reflection::MethodInfo^ method) - : CallbackAction(method, nullptr) - {} - generic - CallbackAction::CallbackAction(System::Reflection::MethodInfo^ method, System::Object^ obj) - : method { method } - , object { obj } - { - paramArray = gcnew cli::array(1); - } - - /*---------------------------------------------------------------------------------*/ - /* Usage Functions */ - /*---------------------------------------------------------------------------------*/ - generic - void CallbackAction::Invoke(T1 param1) - { - // Set parameters - paramArray[0] = safe_cast(param1); - // Invoke - method->Invoke(object, paramArray); - } -} diff --git a/SHADE_Managed/src/Events/CallbackAction.hxx b/SHADE_Managed/src/Events/CallbackAction.hxx deleted file mode 100644 index f8b50266..00000000 --- a/SHADE_Managed/src/Events/CallbackAction.hxx +++ /dev/null @@ -1,57 +0,0 @@ -/************************************************************************************//*! -\file CallbackAction.hxx -\author Tng Kah Wei, kahwei.tng, 390009620 -\par email: kahwei.tng\@digipen.edu -\date Sep 20, 2021 -\brief Contains the definition of the managed CallbackAction 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 - -namespace SHADE -{ - /// - /// Holds a function and their associated object for invoking later. - /// - /// Type of the first parameter. - generic - public ref class CallbackAction - { - public: - /*-----------------------------------------------------------------------------*/ - /* Constructors */ - /*-----------------------------------------------------------------------------*/ - /// - /// Constructs a CallbackAction with the specified static method. - /// - /// MethodInfo representing the method to call. - /// Object to call the method on. Set null if static. - CallbackAction(System::Reflection::MethodInfo^ method); - /// - /// Constructs a CallbackAction with the specified instance method and object - /// which will invoke the method. - /// - /// MethodInfo representing the method to call. - /// Object to call the method on. - CallbackAction(System::Reflection::MethodInfo^ method, System::Object^ obj); - - /*-----------------------------------------------------------------------------*/ - /* Usage Functions */ - /*-----------------------------------------------------------------------------*/ - /// - /// Invokes this action with the specified parameters. - /// - /// - void Invoke(T1 param1); - - private: - System::Reflection::MethodInfo^ method; - cli::array^ paramArray; - System::Object^ object; - }; -} \ No newline at end of file diff --git a/SHADE_Managed/src/Events/CallbackEvent.cxx b/SHADE_Managed/src/Events/CallbackEvent.cxx deleted file mode 100644 index 9ba82ef2..00000000 --- a/SHADE_Managed/src/Events/CallbackEvent.cxx +++ /dev/null @@ -1,71 +0,0 @@ -/************************************************************************************//*! -\file CallbackEvent.cxx -\author Tng Kah Wei, kahwei.tng, 390009620 -\par email: kahwei.tng\@digipen.edu -\date Sep 20, 2022 -\brief Contains the definition of the functions for the CallbackEvent managed - 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 "CallbackEvent.hxx" - -namespace SHADE -{ - /*---------------------------------------------------------------------------------*/ - /* Constructors */ - /*---------------------------------------------------------------------------------*/ - generic - CallbackEvent::CallbackEvent() - { - actions = gcnew System::Collections::Generic::List ^>(); - } - - /*---------------------------------------------------------------------------------*/ - /* Properties */ - /*---------------------------------------------------------------------------------*/ - generic - System::Collections::Generic::IEnumerable^>^ CallbackEvent::Actions::get() - { - return actions; - } - - /*---------------------------------------------------------------------------------*/ - /* Usage Functions */ - /*---------------------------------------------------------------------------------*/ - generic - void CallbackEvent::AddAction(CallbackAction^ action) - { - actions->Add(action); - } - generic - void CallbackEvent::AddAction(System::Reflection::MethodInfo^ method) - { - actions->Add(gcnew CallbackAction(method)); - } - generic - void CallbackEvent::AddAction(System::Reflection::MethodInfo^ method, System::Object^ object) - { - actions->Add(gcnew CallbackAction(method, object)); - } - generic - void CallbackEvent::RemoveAction(CallbackAction^ action) - { - actions->Remove(action); - } - generic - void CallbackEvent::Invoke(T1 param1) - { - for each (CallbackAction^ action in actions) - { - action->Invoke(param1); - } - } -} diff --git a/SHADE_Managed/src/Events/CallbackEvent.hxx b/SHADE_Managed/src/Events/CallbackEvent.hxx deleted file mode 100644 index d0d6d2f1..00000000 --- a/SHADE_Managed/src/Events/CallbackEvent.hxx +++ /dev/null @@ -1,85 +0,0 @@ -/************************************************************************************//*! -\file CallbackEvent.hxx -\author Tng Kah Wei, kahwei.tng, 390009620 -\par email: kahwei.tng\@digipen.edu -\date Sep 20, 2021 -\brief Contains the definition of the managed CallbackEvent 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 - -#include "CallbackAction.hxx" - -namespace SHADE -{ - /// - /// Holds a set of CallbackActions that can be invoked together at a later time. - /// - /// Type of the first parameter. - generic - public ref class CallbackEvent - { - public: - /*-----------------------------------------------------------------------------*/ - /* Constructors */ - /*-----------------------------------------------------------------------------*/ - /// - /// Default Constructor - /// - CallbackEvent(); - - /*-----------------------------------------------------------------------------*/ - /* Properties */ - /*-----------------------------------------------------------------------------*/ - /// - /// Read only access to the list of Actions - /// - property System::Collections::Generic::IEnumerable^>^ Actions - { - System::Collections::Generic::IEnumerable^>^ get(); - } - - /*-----------------------------------------------------------------------------*/ - /* Usage Functions */ - /*-----------------------------------------------------------------------------*/ - /// - /// Adds the specified CallbackAction to the CallbackEvent. - /// - /// CallbackAction to add. - void AddAction(CallbackAction^ action); - /// - /// Adds a specified static method as a CallbackAction to the CallbackEvent. - /// - /// Method to add. - void AddAction(System::Reflection::MethodInfo^ method); - /// - /// Adds a specified instance method and associated object as a CallbackAction to - /// the CallbackEvent. - /// - /// Method to add. - /// Object that will call the specified method. - void AddAction(System::Reflection::MethodInfo^ method, System::Object^ object); - /// - /// Removes the specified CallbackAction from the CallbackEvent. - /// - /// CallbackAction to remove. - void RemoveAction(CallbackAction^ action); - /// - /// Invokes all CallbackActions registered with this CallbackEvent with the - /// specified parameters. - /// - /// - void Invoke(T1 param1); - - private: - /*-----------------------------------------------------------------------------*/ - /* Data Members */ - /*-----------------------------------------------------------------------------*/ - System::Collections::Generic::List^>^ actions; - }; -} \ No newline at end of file From 5bc24b09d4ef27acb4a23d89ccb939528a142e40 Mon Sep 17 00:00:00 2001 From: Kah Wei Date: Thu, 22 Sep 2022 12:31:26 +0800 Subject: [PATCH 13/24] Added generalisation of csproj file location --- SHADE_Engine/src/Scripting/SHScriptEngine.cpp | 107 ++++++++++-------- SHADE_Engine/src/Scripting/SHScriptEngine.h | 9 +- TempScriptsFolder/TestScript.cs | 11 ++ 3 files changed, 77 insertions(+), 50 deletions(-) create mode 100644 TempScriptsFolder/TestScript.cs diff --git a/SHADE_Engine/src/Scripting/SHScriptEngine.cpp b/SHADE_Engine/src/Scripting/SHScriptEngine.cpp index 78b4d544..56f93812 100644 --- a/SHADE_Engine/src/Scripting/SHScriptEngine.cpp +++ b/SHADE_Engine/src/Scripting/SHScriptEngine.cpp @@ -22,14 +22,16 @@ of DigiPen Institute of Technology is prohibited. namespace SHADE { - /*--------------------------------------------------------------------------------*/ - /* Static Definitions */ - /*--------------------------------------------------------------------------------*/ + /*-----------------------------------------------------------------------------------*/ + /* Static Definitions */ + /*----------------------------------------------------------------------------------*/ const std::string SHScriptEngine::DEFAULT_CSHARP_NAMESPACE = std::string("SHADE"); + 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 @@ -99,9 +101,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()); @@ -140,41 +142,40 @@ namespace SHADE return result; } - /*---------------------------------------------------------------------------------*/ - /* Script Serialisation Functions */ - /*---------------------------------------------------------------------------------*/ + /*-----------------------------------------------------------------------------------*/ + /* Script Serialisation Functions */ + /*-----------------------------------------------------------------------------------*/ void SHScriptEngine::DeserialiseScript(const SHEntity& entity, const std::string& yaml) const { csScriptDeserialise(entity.GetEID(), yaml.c_str()); } - /*---------------------------------------------------------------------------------*/ - /* Script Editor Functions */ - /*---------------------------------------------------------------------------------*/ + /*-----------------------------------------------------------------------------------*/ + /* Script Editor Functions */ + /*-----------------------------------------------------------------------------------*/ void SHScriptEngine::RenderScriptsInInspector(const SHEntity& entity) const { csEditorRenderScripts(entity.GetEID()); } - /*---------------------------------------------------------------------------------*/ - /* Static Utility Functions */ - /*---------------------------------------------------------------------------------*/ + /*-----------------------------------------------------------------------------------*/ + /* 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; @@ -184,7 +185,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) { @@ -202,6 +203,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); @@ -209,7 +211,7 @@ namespace SHADE deleteFile(BUILD_LOG_PATH); return BUILD_SUCCESS; - } + } void SHScriptEngine::GenerateScriptsCsProjFile(const std::filesystem::path& path) const { @@ -222,11 +224,11 @@ namespace SHADE Release;Debug\n\ \n\ \n\ - .\\bin_Release-x64\n\ + .\\bin\\Release\n\ x64\n\ \n\ \n\ - .\\bin_Debug-x64\n\ + .\\bin\\Debug\n\ x64\n\ DEBUG;TRACE\n\ false\n\ @@ -245,7 +247,8 @@ namespace SHADE \n\ \n\ \n\ - .\\bin\\SHADE_Managed.dll\n\ + ..\\bin\\Debug\\SHADE_Managed.dll\ + ..\\bin\\Release\\SHADE_Managed.dll\ \n\ \n\ "; @@ -262,9 +265,9 @@ namespace SHADE file.close(); } - /*---------------------------------------------------------------------------------*/ - /* Helper Functions */ - /*---------------------------------------------------------------------------------*/ + /*-----------------------------------------------------------------------------------*/ + /* Helper Functions */ + /*-----------------------------------------------------------------------------------*/ void SHScriptEngine::loadFunctions() { std::ostringstream oss; @@ -404,25 +407,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,4 +486,14 @@ 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(); + } + } diff --git a/SHADE_Engine/src/Scripting/SHScriptEngine.h b/SHADE_Engine/src/Scripting/SHScriptEngine.h index f3d69dd5..fa205266 100644 --- a/SHADE_Engine/src/Scripting/SHScriptEngine.h +++ b/SHADE_Engine/src/Scripting/SHScriptEngine.h @@ -208,6 +208,8 @@ 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; /*-----------------------------------------------------------------------------*/ @@ -260,18 +262,19 @@ namespace SHADE /// Deletes the file as specified by the file path. /// /// File path to the file to delete. - static void deleteFile(const std::string_view& filePath); + static void deleteFile(const std::string& filePath); /// /// Deletes the folder and all files in it as specified by the file path. /// /// File path to the file to delete. - static void deleteFolder(const std::string_view& filePath); + static void deleteFolder(const std::string& filePath); /// /// Checks if a specified file exists. /// /// File path to the file to check. /// True if the file exists - 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); }; } diff --git a/TempScriptsFolder/TestScript.cs b/TempScriptsFolder/TestScript.cs new file mode 100644 index 00000000..0e4823a2 --- /dev/null +++ b/TempScriptsFolder/TestScript.cs @@ -0,0 +1,11 @@ +using SHADE; + +public class TestScript : Script +{ + public TestScript(GameObject gameObj) : base(gameObj) {} + + protected override void update() + { + Debug.Log("TestScript.Update()"); + } +} \ No newline at end of file From ed143661b376305f4b06942c8eef6f422f62d48a Mon Sep 17 00:00:00 2001 From: Diren D Bharwani Date: Thu, 22 Sep 2022 14:26:07 +0800 Subject: [PATCH 14/24] Scene node active states propagate down the hierarchy Vulkan is throwing an exception... --- .../src/Math/Transform/SHTransformSystem.cpp | 2 +- SHADE_Engine/src/Scene/SHSceneGraph.cpp | 77 ++++++++++++++----- SHADE_Engine/src/Scene/SHSceneGraph.h | 25 +++--- 3 files changed, 71 insertions(+), 33 deletions(-) diff --git a/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp b/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp index 879c2d34..f420834d 100644 --- a/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp +++ b/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp @@ -53,7 +53,7 @@ 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(); diff --git a/SHADE_Engine/src/Scene/SHSceneGraph.cpp b/SHADE_Engine/src/Scene/SHSceneGraph.cpp index 82e4fd7e..84c7f1c5 100644 --- a/SHADE_Engine/src/Scene/SHSceneGraph.cpp +++ b/SHADE_Engine/src/Scene/SHSceneGraph.cpp @@ -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; } //////////////////////////////////////// @@ -476,7 +515,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; } diff --git a/SHADE_Engine/src/Scene/SHSceneGraph.h b/SHADE_Engine/src/Scene/SHSceneGraph.h index bdb8f52c..39afbb31 100644 --- a/SHADE_Engine/src/Scene/SHSceneGraph.h +++ b/SHADE_Engine/src/Scene/SHSceneGraph.h @@ -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& 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 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& 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& GetChildren (EntityID entityID) const noexcept; + + [[nodiscard]] bool IsActiveInHierarchy (EntityID entityID) const noexcept; /*---------------------------------------------------------------------------------*/ /* Setter Functions */ From 2d93c9559d0fba3573e471758e85a7ecb20c6da0 Mon Sep 17 00:00:00 2001 From: Diren D Bharwani Date: Thu, 22 Sep 2022 14:54:06 +0800 Subject: [PATCH 15/24] Restructured Transform system to match intended system structure --- .../src/Math/Transform/SHTransformSystem.cpp | 12 ++++-- .../src/Math/Transform/SHTransformSystem.h | 42 +++++++++++++++---- 2 files changed, 43 insertions(+), 11 deletions(-) diff --git a/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp b/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp index 879c2d34..125de0e2 100644 --- a/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp +++ b/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp @@ -21,12 +21,18 @@ namespace SHADE { + /*-----------------------------------------------------------------------------------*/ + /* Static Data Member Definitions */ + /*-----------------------------------------------------------------------------------*/ + + SHTransformSystem::TransformUpdateRoutine SHTransformSystem::UpdateRoutine; + /*-----------------------------------------------------------------------------------*/ /* Constructors & Destructor Definitions */ /*-----------------------------------------------------------------------------------*/ - SHTransformSystem::SHTransformSystem() - : SHSystemRoutine { "Transform Routine", false } + SHTransformSystem::TransformUpdateRoutine::TransformUpdateRoutine() + : SHSystemRoutine { "Transform Update", false } {} @@ -34,7 +40,7 @@ namespace SHADE /* Public Function Member Definitions */ /*-----------------------------------------------------------------------------------*/ - void SHTransformSystem::Execute(double dt) noexcept + void SHTransformSystem::TransformUpdateRoutine::Execute(double dt) noexcept { // Get the current scene graph to traverse and update const auto& SCENE_GRAPH = SHSceneManager::GetCurrentSceneGraph(); diff --git a/SHADE_Engine/src/Math/Transform/SHTransformSystem.h b/SHADE_Engine/src/Math/Transform/SHTransformSystem.h index 5eebd292..4d62475a 100644 --- a/SHADE_Engine/src/Math/Transform/SHTransformSystem.h +++ b/SHADE_Engine/src/Math/Transform/SHTransformSystem.h @@ -21,19 +21,18 @@ namespace SHADE /* Type Definitions */ /*-----------------------------------------------------------------------------------*/ - class SH_API SHTransformSystem : public SHSystemRoutine + class SH_API SHTransformSystem : public SHSystem { public: - /*---------------------------------------------------------------------------------*/ /* Constructors & Destructor */ /*---------------------------------------------------------------------------------*/ - SHTransformSystem (); - ~SHTransformSystem () = default; + SHTransformSystem () = default; + ~SHTransformSystem () = default; - SHTransformSystem (const SHTransformSystem&) = delete; - SHTransformSystem (SHTransformSystem&&) = delete; + SHTransformSystem (const SHTransformSystem&) = delete; + SHTransformSystem (SHTransformSystem&&) = delete; /*---------------------------------------------------------------------------------*/ /* Operator Overloads */ @@ -43,10 +42,37 @@ namespace SHADE SHTransformSystem& operator= (SHTransformSystem&&) = delete; /*---------------------------------------------------------------------------------*/ - /* Function Members */ + /* System Routines */ /*---------------------------------------------------------------------------------*/ - void Execute(double dt) noexcept override; + class TransformUpdateRoutine : 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; + }; + + static TransformUpdateRoutine UpdateRoutine; private: /*---------------------------------------------------------------------------------*/ From cda7330c5b92731c43157d1cfb0bde71d79360d6 Mon Sep 17 00:00:00 2001 From: Diren D Bharwani Date: Thu, 22 Sep 2022 14:56:58 +0800 Subject: [PATCH 16/24] Removed static data member for transform update routine --- SHADE_Engine/src/Math/Transform/SHTransformSystem.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SHADE_Engine/src/Math/Transform/SHTransformSystem.h b/SHADE_Engine/src/Math/Transform/SHTransformSystem.h index 4d62475a..c57cbdbd 100644 --- a/SHADE_Engine/src/Math/Transform/SHTransformSystem.h +++ b/SHADE_Engine/src/Math/Transform/SHTransformSystem.h @@ -72,7 +72,7 @@ namespace SHADE void Execute(double dt) noexcept override; }; - static TransformUpdateRoutine UpdateRoutine; + //static TransformUpdateRoutine UpdateRoutine; private: /*---------------------------------------------------------------------------------*/ From 38dbd0c2179bb0e15084307ccad587a3f80aab2f Mon Sep 17 00:00:00 2001 From: Diren D Bharwani Date: Thu, 22 Sep 2022 15:49:00 +0800 Subject: [PATCH 17/24] Removed static data member...again... --- SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp b/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp index f229cbdd..adbdf746 100644 --- a/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp +++ b/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp @@ -25,7 +25,7 @@ namespace SHADE /* Static Data Member Definitions */ /*-----------------------------------------------------------------------------------*/ - SHTransformSystem::TransformUpdateRoutine SHTransformSystem::UpdateRoutine; + //SHTransformSystem::TransformUpdateRoutine SHTransformSystem::UpdateRoutine; /*-----------------------------------------------------------------------------------*/ /* Constructors & Destructor Definitions */ @@ -40,7 +40,7 @@ namespace SHADE /* Public Function Member Definitions */ /*-----------------------------------------------------------------------------------*/ - void SHTransformSystem::TransformUpdateRoutine::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(); From 3b533ac03d73cda934791767ca1452ce74c7c796 Mon Sep 17 00:00:00 2001 From: Kah Wei Date: Thu, 22 Sep 2022 16:40:49 +0800 Subject: [PATCH 18/24] Added faulty registration to entityDestroyed event --- SHADE_Engine/src/Scripting/SHScriptEngine.cpp | 45 +++++++++++++------ SHADE_Engine/src/Scripting/SHScriptEngine.h | 13 +++++- TempScriptsFolder/TestScript.cs | 12 +++++ 3 files changed, 56 insertions(+), 14 deletions(-) diff --git a/SHADE_Engine/src/Scripting/SHScriptEngine.cpp b/SHADE_Engine/src/Scripting/SHScriptEngine.cpp index 56f93812..fada5b70 100644 --- a/SHADE_Engine/src/Scripting/SHScriptEngine.cpp +++ b/SHADE_Engine/src/Scripting/SHScriptEngine.cpp @@ -16,9 +16,14 @@ of DigiPen Institute of Technology is prohibited. // Standard Library #include // std::fstream #include // std::filesystem::canonical, std::filesystem::remove +#include // 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 { @@ -54,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() { @@ -257,13 +256,23 @@ 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(); - } + } + + /*-----------------------------------------------------------------------------------*/ + /* Event Handler Functions */ + /*-----------------------------------------------------------------------------------*/ + SHEventHandle SHScriptEngine::onEntityDestroyed(SHEventPtr eventPtr) + { + auto eventData = reinterpret_cast*>(eventPtr.get()); + csScriptsRemoveAll(eventData->data->eid); + return eventData->handle; + } /*-----------------------------------------------------------------------------------*/ /* Helper Functions */ @@ -385,6 +394,17 @@ namespace SHADE );*/ } + void SHScriptEngine::registerEvents() + { + // Register for entity destroyed event + std::shared_ptr> destroyedEventReceiver + { + std::make_shared>(this, &SHScriptEngine::onEntityDestroyed) + }; + ReceiverPtr receiver = std::dynamic_pointer_cast(destroyedEventReceiver); + SHEventManager::SubscribeTo(SH_ENTITY_DESTROYED_EVENT, receiver); + } + void SHScriptEngine::dumpBuildLog(const std::string_view& buildLogPath) { std::ifstream buildLog(buildLogPath); @@ -495,5 +515,4 @@ namespace SHADE oss << " -o \"./tmp/\" -fl -flp:LogFile=build.log;Verbosity=quiet"; return oss.str(); } - } diff --git a/SHADE_Engine/src/Scripting/SHScriptEngine.h b/SHADE_Engine/src/Scripting/SHScriptEngine.h index fa205266..0994bb5d 100644 --- a/SHADE_Engine/src/Scripting/SHScriptEngine.h +++ b/SHADE_Engine/src/Scripting/SHScriptEngine.h @@ -15,12 +15,14 @@ of DigiPen Institute of Technology is prohibited. #include // Project Headers +#include "SH_API.h" #include "SHDotNetRuntime.h" #include "ECS_Base/SHECSMacros.h" #include "ECS_Base/Entity/SHEntity.h" #include "ECS_Base/System/SHSystem.h" #include "ECS_Base/System/SHSystemRoutine.h" -#include "SH_API.h" +#include "Events/SHEventDefines.h" +#include "Events/SHEvent.h" namespace SHADE { @@ -242,6 +244,11 @@ namespace SHADE /*ECS::EntityEvent::Delegate onEntityCreate; ECS::EntityEvent::Delegate onEntityDestroy;*/ + /*-----------------------------------------------------------------------------*/ + /* Event Handler Functions */ + /*-----------------------------------------------------------------------------*/ + SHEventHandle onEntityDestroyed(SHEventPtr eventPtr); + /*-----------------------------------------------------------------------------*/ /* Helper Functions */ /*-----------------------------------------------------------------------------*/ @@ -250,6 +257,10 @@ namespace SHADE /// void loadFunctions(); /// + /// Registers events for the scripting system + /// + void registerEvents(); + /// /// Reads the file via the specified path that represents a build log of error /// and warning messages. /// diff --git a/TempScriptsFolder/TestScript.cs b/TempScriptsFolder/TestScript.cs index 0e4823a2..c1ed5bd5 100644 --- a/TempScriptsFolder/TestScript.cs +++ b/TempScriptsFolder/TestScript.cs @@ -4,8 +4,20 @@ 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()"); + } } \ No newline at end of file From 5bd35cec612412fbbfba4d32a64202128e1ad8ff Mon Sep 17 00:00:00 2001 From: Xiao Qi Date: Thu, 22 Sep 2022 17:07:59 +0800 Subject: [PATCH 19/24] Fixed SHEventReceiver constructor callback return signature. --- SHADE_Engine/src/Events/SHEventReceiver.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SHADE_Engine/src/Events/SHEventReceiver.h b/SHADE_Engine/src/Events/SHEventReceiver.h index e6e5e757..e2edd4dc 100644 --- a/SHADE_Engine/src/Events/SHEventReceiver.h +++ b/SHADE_Engine/src/Events/SHEventReceiver.h @@ -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 } { From 1bede86ff60c9a3070f3bb46b7dea0bc4e6ae600 Mon Sep 17 00:00:00 2001 From: Kah Wei Date: Thu, 22 Sep 2022 17:25:43 +0800 Subject: [PATCH 20/24] Awake(), Start() and Update(), OnDestroy() for scripts now all run as intended --- SHADE_Application/src/Scenes/SBTestScene.cpp | 9 ++++---- SHADE_Application/src/Scenes/SBTestScene.h | 1 + SHADE_Managed/src/Scripts/ScriptStore.cxx | 24 +++----------------- 3 files changed, 9 insertions(+), 25 deletions(-) diff --git a/SHADE_Application/src/Scenes/SBTestScene.cpp b/SHADE_Application/src/Scenes/SBTestScene.cpp index 072a15de..c59fa234 100644 --- a/SHADE_Application/src/Scenes/SBTestScene.cpp +++ b/SHADE_Application/src/Scenes/SBTestScene.cpp @@ -38,18 +38,19 @@ namespace Sandbox auto matInst = graphicsSystem->AddMaterialInstance(); // Create entity and add mesh - auto entity = SHADE::SHEntityManager::CreateEntity(); - auto& renderable = *SHADE::SHComponentManager::GetComponent_s(entity); + testObj = SHADE::SHEntityManager::CreateEntity(); + auto& renderable = *SHADE::SHComponentManager::GetComponent_s(testObj); renderable.Mesh = CUBE_MESH; renderable.SetMaterial(matInst); renderable.TransformMatrix.Translate(0.0f, 0.0f, 2.0f); SHADE::SHScriptEngine* scriptEngine = static_cast(SHADE::SHSystemManager::GetSystem()); - scriptEngine->AddScript(*SHADE::SHEntityManager::GetEntityByID(entity), "TestScript"); + 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() diff --git a/SHADE_Application/src/Scenes/SBTestScene.h b/SHADE_Application/src/Scenes/SBTestScene.h index 6776c671..4d4a3207 100644 --- a/SHADE_Application/src/Scenes/SBTestScene.h +++ b/SHADE_Application/src/Scenes/SBTestScene.h @@ -9,6 +9,7 @@ namespace Sandbox { private: EntityID camera; + EntityID testObj; public: diff --git a/SHADE_Managed/src/Scripts/ScriptStore.cxx b/SHADE_Managed/src/Scripts/ScriptStore.cxx index 089da002..252ab071 100644 --- a/SHADE_Managed/src/Scripts/ScriptStore.cxx +++ b/SHADE_Managed/src/Scripts/ScriptStore.cxx @@ -287,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; @@ -311,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; @@ -386,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); @@ -496,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)) @@ -667,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(); From 0250687e06c0ce3d3cad92ecc1c69903a7373691 Mon Sep 17 00:00:00 2001 From: Diren D Bharwani Date: Thu, 22 Sep 2022 20:25:23 +0800 Subject: [PATCH 21/24] Instantiated Transform System & Update Routine --- SHADE_Application/src/Application/SBApplication.cpp | 11 ++++++++++- .../src/Math/Transform/SHTransformSystem.cpp | 12 ++++++++++-- SHADE_Engine/src/Math/Transform/SHTransformSystem.h | 13 +++++++++---- 3 files changed, 29 insertions(+), 7 deletions(-) diff --git a/SHADE_Application/src/Application/SBApplication.cpp b/SHADE_Application/src/Application/SBApplication.cpp index 53cc1e40..938b0b57 100644 --- a/SHADE_Application/src/Application/SBApplication.cpp +++ b/SHADE_Application/src/Application/SBApplication.cpp @@ -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" @@ -45,8 +46,10 @@ namespace Sandbox window.Create(hInstance, hPrevInstance, lpCmdLine, nCmdShow); // Create Systems - SHADE::SHSystemManager::CreateSystem(); SHADE::SHSystemManager::CreateSystem(); + // TODO(Diren): Create Physics System here + SHADE::SHSystemManager::CreateSystem(); + SHADE::SHSystemManager::CreateSystem(); SHADE::SHGraphicsSystem* graphicsSystem = static_cast(SHADE::SHSystemManager::GetSystem()); // Create Routines @@ -54,6 +57,12 @@ namespace Sandbox SHADE::SHSystemManager::RegisterRoutine(); SHADE::SHSystemManager::RegisterRoutine(); SHADE::SHSystemManager::RegisterRoutine(); + + // TODO(Diren): Register Physics System & Routines here + + SHADE::SHSystemManager::RegisterRoutine(); + SHADE::SHComponentManager::CreateComponentSparseSet(); + SHADE::SHSystemManager::RegisterRoutine(); SHADE::SHSystemManager::RegisterRoutine(); SHADE::SHSystemManager::RegisterRoutine(); diff --git a/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp b/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp index adbdf746..64ad9f43 100644 --- a/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp +++ b/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp @@ -25,8 +25,6 @@ namespace SHADE /* Static Data Member Definitions */ /*-----------------------------------------------------------------------------------*/ - //SHTransformSystem::TransformUpdateRoutine SHTransformSystem::UpdateRoutine; - /*-----------------------------------------------------------------------------------*/ /* Constructors & Destructor Definitions */ /*-----------------------------------------------------------------------------------*/ @@ -47,6 +45,16 @@ namespace SHADE UpdateEntity(SCENE_GRAPH.GetRoot()); } + void SHTransformSystem::Init() + { + + } + + void SHTransformSystem::Exit() + { + + } + /*-----------------------------------------------------------------------------------*/ /* Private Function Member Definitions */ /*-----------------------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Math/Transform/SHTransformSystem.h b/SHADE_Engine/src/Math/Transform/SHTransformSystem.h index c57cbdbd..02c3b6c6 100644 --- a/SHADE_Engine/src/Math/Transform/SHTransformSystem.h +++ b/SHADE_Engine/src/Math/Transform/SHTransformSystem.h @@ -21,7 +21,7 @@ namespace SHADE /* Type Definitions */ /*-----------------------------------------------------------------------------------*/ - class SH_API SHTransformSystem : public SHSystem + class SH_API SHTransformSystem final : public SHSystem { public: /*---------------------------------------------------------------------------------*/ @@ -29,7 +29,7 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ SHTransformSystem () = default; - ~SHTransformSystem () = default; + ~SHTransformSystem () override = default; SHTransformSystem (const SHTransformSystem&) = delete; SHTransformSystem (SHTransformSystem&&) = delete; @@ -45,7 +45,7 @@ namespace SHADE /* System Routines */ /*---------------------------------------------------------------------------------*/ - class TransformUpdateRoutine : public SHSystemRoutine + class SH_API TransformUpdateRoutine final: public SHSystemRoutine { public: /*-------------------------------------------------------------------------------*/ @@ -72,7 +72,12 @@ namespace SHADE void Execute(double dt) noexcept override; }; - //static TransformUpdateRoutine UpdateRoutine; + /*---------------------------------------------------------------------------------*/ + /* Function Members */ + /*---------------------------------------------------------------------------------*/ + + void Init () override; + void Exit () override; private: /*---------------------------------------------------------------------------------*/ From 2c0fa3a6b27172a0bb358978feae8578be8b0cac Mon Sep 17 00:00:00 2001 From: Diren D Bharwani Date: Thu, 22 Sep 2022 20:25:42 +0800 Subject: [PATCH 22/24] Fixed warning from scene graph when adding new nodes to root. --- SHADE_Engine/src/Scene/SHSceneGraph.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/SHADE_Engine/src/Scene/SHSceneGraph.cpp b/SHADE_Engine/src/Scene/SHSceneGraph.cpp index 84c7f1c5..da2dcffd 100644 --- a/SHADE_Engine/src/Scene/SHSceneGraph.cpp +++ b/SHADE_Engine/src/Scene/SHSceneGraph.cpp @@ -497,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; } From 6d646851e256ab6698edff14798c23504cdeb6db Mon Sep 17 00:00:00 2001 From: Diren D Bharwani Date: Thu, 22 Sep 2022 20:39:46 +0800 Subject: [PATCH 23/24] Added missing transpose to transform update and a test component to application --- SHADE_Application/src/Scenes/SBTestScene.cpp | 9 +++++++-- .../src/Math/Transform/SHTransformSystem.cpp | 12 +++++++----- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/SHADE_Application/src/Scenes/SBTestScene.cpp b/SHADE_Application/src/Scenes/SBTestScene.cpp index c59fa234..751e17a8 100644 --- a/SHADE_Application/src/Scenes/SBTestScene.cpp +++ b/SHADE_Application/src/Scenes/SBTestScene.cpp @@ -8,6 +8,7 @@ #include "Scene/SHSceneManager.h" #include "Graphics/MiddleEnd/Interface/SHGraphicsSystem.h" #include "Scripting/SHScriptEngine.h" +#include "Math/Transform/SHTransformComponent.h" using namespace SHADE; @@ -38,11 +39,15 @@ namespace Sandbox auto matInst = graphicsSystem->AddMaterialInstance(); // Create entity and add mesh - testObj = SHADE::SHEntityManager::CreateEntity(); + testObj = SHADE::SHEntityManager::CreateEntity(); auto& renderable = *SHADE::SHComponentManager::GetComponent_s(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(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::SHSystemManager::GetSystem()); scriptEngine->AddScript(*SHADE::SHEntityManager::GetEntityByID(testObj), "TestScript"); } diff --git a/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp b/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp index 64ad9f43..18e54a89 100644 --- a/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp +++ b/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp @@ -74,11 +74,9 @@ namespace SHADE 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(child->GetEntityID()); if (!HAS_TRANSFORM) @@ -104,7 +102,7 @@ namespace SHADE if (parent) { localToWorld = parent->GetTRS(); - worldToLocal = SHMatrix::Inverse(tf.local.trs); + worldToLocal = SHMatrix::Inverse(localToWorld); } while (!tf.updateQueue.empty()) @@ -148,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 \ No newline at end of file From c77d9b2ff54fa145dcdb974490b03fdba7c2d781 Mon Sep 17 00:00:00 2001 From: Diren D Bharwani Date: Thu, 22 Sep 2022 22:58:14 +0800 Subject: [PATCH 24/24] Changed editor pause for transform system to true --- SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp b/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp index 18e54a89..f61f3e42 100644 --- a/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp +++ b/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp @@ -30,7 +30,7 @@ namespace SHADE /*-----------------------------------------------------------------------------------*/ SHTransformSystem::TransformUpdateRoutine::TransformUpdateRoutine() - : SHSystemRoutine { "Transform Update", false } + : SHSystemRoutine { "Transform Update", true } {}