From 4546b84c061464fa26f76afecd995d527d8b2e2c Mon Sep 17 00:00:00 2001 From: Kah Wei Date: Fri, 16 Sep 2022 15:37:22 +0800 Subject: [PATCH] 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