From 4f177bc45512b34efa7b000189d84449607c9a21 Mon Sep 17 00:00:00 2001 From: Kah Wei Date: Wed, 19 Oct 2022 20:43:22 +0800 Subject: [PATCH 1/4] Reworked script serialization and deserialization functions (WIP) --- SHADE_Application/premake5.lua | 4 +- SHADE_Engine/src/Scripting/SHScriptEngine.cpp | 44 ++------- SHADE_Engine/src/Scripting/SHScriptEngine.h | 37 ++++---- .../src/Serialization/SHSerialization.cpp | 12 ++- .../src/Serialization/SHSerialization.h | 1 + SHADE_Managed/src/Scripts/ScriptStore.cxx | 91 ++++++++++--------- SHADE_Managed/src/Scripts/ScriptStore.hxx | 23 ++--- .../src/Serialisation/ReflectionUtilities.cxx | 61 +++++++------ .../src/Serialisation/ReflectionUtilities.h++ | 4 +- .../src/Serialisation/ReflectionUtilities.hxx | 8 +- 10 files changed, 145 insertions(+), 140 deletions(-) diff --git a/SHADE_Application/premake5.lua b/SHADE_Application/premake5.lua index 35ea2c10..395c3a48 100644 --- a/SHADE_Application/premake5.lua +++ b/SHADE_Application/premake5.lua @@ -37,7 +37,8 @@ project "SHADE_Application" "%{IncludeDir.VULKAN}/include", "%{IncludeDir.spdlog}/include", "%{IncludeDir.tinyddsloader}", - "%{IncludeDir.reactphysics3d}\\include" + "%{IncludeDir.reactphysics3d}\\include", + "%{IncludeDir.yamlcpp}" } externalwarnings "Off" @@ -51,6 +52,7 @@ project "SHADE_Application" { "SHADE_Engine", "SHADE_Managed", + "yaml-cpp", "SDL2.lib", "SDL2main.lib" } diff --git a/SHADE_Engine/src/Scripting/SHScriptEngine.cpp b/SHADE_Engine/src/Scripting/SHScriptEngine.cpp index d7a090a4..6585414d 100644 --- a/SHADE_Engine/src/Scripting/SHScriptEngine.cpp +++ b/SHADE_Engine/src/Scripting/SHScriptEngine.cpp @@ -115,34 +115,22 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ /* Script Serialisation Functions */ /*---------------------------------------------------------------------------------*/ - std::string SHScriptEngine::SerialiseScripts(EntityID entity) const + bool SHScriptEngine::SerialiseScripts(EntityID entity, YAML::Node& scriptsNode) const { - // Create buffer needed to store serialised script data - constexpr int BUFFER_SIZE = 10240; - std::unique_ptr buffer { new char[BUFFER_SIZE] }; - std::memset(buffer.get(), 0, BUFFER_SIZE); - // Attempt to serialise the script - std::string result; - if (csScriptsSerialise(entity, buffer.get(), BUFFER_SIZE)) - { - result = std::string(buffer.get()); - } - else - { - SHLOG_ERROR("[ScriptEngine] Failed to serialise scripts as string buffer is too small!"); - } + if (csScriptsSerialiseYaml(entity, &scriptsNode)) + return true; - // Return an empty string since we failed to serialise - return result; + SHLOG_ERROR("[ScriptEngine] Failed to serialise scripts for entity #{}.", entity); + return false; } /*-----------------------------------------------------------------------------------*/ /* Script Serialisation Functions */ /*-----------------------------------------------------------------------------------*/ - void SHScriptEngine::DeserialiseScript(EntityID entity, const std::string& yaml) const + bool SHScriptEngine::DeserialiseScript(EntityID entity, YAML::Node& scriptsNode) const { - csScriptDeserialise(entity, yaml.c_str()); + return csScriptsDeserialiseYaml(entity, &scriptsNode); } /*-----------------------------------------------------------------------------------*/ @@ -380,30 +368,18 @@ namespace SHADE DEFAULT_CSHARP_NAMESPACE + ".ScriptStore", "RemoveAllScriptsImmediately" ); - /*csScriptsSerialise = dotNet.GetFunctionPtr + csScriptsSerialiseYaml = dotNet.GetFunctionPtr ( DEFAULT_CSHARP_LIB_NAME, DEFAULT_CSHARP_NAMESPACE + ".ScriptStore", "SerialiseScripts" ); - csScriptsSerialiseYaml = dotNet.GetFunctionPtr + csScriptsDeserialiseYaml = dotNet.GetFunctionPtr ( DEFAULT_CSHARP_LIB_NAME, DEFAULT_CSHARP_NAMESPACE + ".ScriptStore", - "SerialiseScriptsYaml" + "DeserialiseScripts" ); - csScriptDeserialise = dotNet.GetFunctionPtr - ( - DEFAULT_CSHARP_LIB_NAME, - DEFAULT_CSHARP_NAMESPACE + ".ScriptStore", - "DeserialiseScript" - ); - csScriptDeserialiseYaml = dotNet.GetFunctionPtr - ( - DEFAULT_CSHARP_LIB_NAME, - DEFAULT_CSHARP_NAMESPACE + ".ScriptStore", - "SerialiseScriptsYaml" - );*/ csEditorRenderScripts = dotNet.GetFunctionPtr ( DEFAULT_CSHARP_LIB_NAME, diff --git a/SHADE_Engine/src/Scripting/SHScriptEngine.h b/SHADE_Engine/src/Scripting/SHScriptEngine.h index 60723425..58dbe0b3 100644 --- a/SHADE_Engine/src/Scripting/SHScriptEngine.h +++ b/SHADE_Engine/src/Scripting/SHScriptEngine.h @@ -13,7 +13,8 @@ of DigiPen Institute of Technology is prohibited. // STL Includes #include - +// External Dependencies +#include // Project Headers #include "SH_API.h" #include "SHDotNetRuntime.h" @@ -141,23 +142,26 @@ namespace SHADE /* Script Serialisation Functions */ /*-----------------------------------------------------------------------------*/ /// - /// Generates a JSON string that represents the set of Scripts attached to the - /// specified Entity. + /// Performs serialization of all scripts for the specified entity into the + /// YAML::Node specified. This node will contain all serialised scripts after + /// calling this function. /// - /// The Entity to Serialise. - /// - /// String that represents the set of scripts attached to the specified Entity. - /// - std::string SerialiseScripts(EntityID entity) const; + /// The Entity to Serialise. + /// + /// YAML Node that will store the serialised scripts. + /// + /// True if successfully serialised. + bool SerialiseScripts(EntityID entity, YAML::Node& scriptsNode) const; /// - /// Loads the specified JSON string and creates a Script for the specified Entity - /// based on the specified JSON string. + /// Creates scripts and sets fields for the specified Entity based on the specified + /// YAML node. /// /// The Entity to deserialise a Script on to. - /// - /// The YAML string that represents the Script to load into the Entity. + /// + /// YAML Node that contains the serialised script data. /// - void DeserialiseScript(EntityID entity, const std::string& yaml) const; + /// True if successfully deserialised. + bool DeserialiseScript(EntityID entity, YAML::Node& scriptsNode) const; /*-----------------------------------------------------------------------------*/ /* Script Editor Functions */ @@ -211,8 +215,7 @@ namespace SHADE using CsScriptManipFuncPtr = bool(*)(EntityID, const char*); using CsScriptBasicFuncPtr = void(*)(EntityID); using CsScriptOptionalFuncPtr = void(*)(EntityID, bool); - using CsScriptSerialiseFuncPtr = bool(*)(EntityID, char*, int); - using CsScriptDeserialiseFuncPtr = bool(*)(EntityID, const char*); + using CsScriptSerialiseYamlFuncPtr = bool(*)(EntityID, void*); using CsScriptSerialiseYamlFuncPtr = bool(*)(EntityID, void*); using CsScriptEditorFuncPtr = void(*)(EntityID); @@ -245,10 +248,8 @@ namespace SHADE CsScriptManipFuncPtr csScriptsAdd = nullptr; CsScriptBasicFuncPtr csScriptsRemoveAll = nullptr; CsScriptOptionalFuncPtr csScriptsRemoveAllImmediately = nullptr; - CsScriptSerialiseFuncPtr csScriptsSerialise = nullptr; - CsScriptDeserialiseFuncPtr csScriptDeserialise = nullptr; CsScriptSerialiseYamlFuncPtr csScriptsSerialiseYaml = nullptr; - CsScriptSerialiseYamlFuncPtr csScriptDeserialiseYaml = nullptr; + CsScriptSerialiseYamlFuncPtr csScriptsDeserialiseYaml = nullptr; // - Editor CsScriptEditorFuncPtr csEditorRenderScripts = nullptr; CsFuncPtr csEditorUndo = nullptr; diff --git a/SHADE_Engine/src/Serialization/SHSerialization.cpp b/SHADE_Engine/src/Serialization/SHSerialization.cpp index e259fbbc..d0023107 100644 --- a/SHADE_Engine/src/Serialization/SHSerialization.cpp +++ b/SHADE_Engine/src/Serialization/SHSerialization.cpp @@ -13,6 +13,8 @@ #include "Graphics/MiddleEnd/Interface/SHRenderable.h" #include "Math/Transform/SHTransformComponent.h" #include "Physics/Components/SHRigidBodyComponent.h" +#include "ECS_Base/Managers/SHSystemManager.h" +#include "Scripting/SHScriptEngine.h" namespace SHADE { @@ -157,7 +159,7 @@ namespace SHADE node = YAML::Null; return node; } - node.SetStyle(YAML::EmitterStyle::Block); + node.SetStyle(YAML::EmitterStyle::Block); node[EIDNode] = eid; node[EntityNameNode] = entity->name; node[IsActiveNode] = sceneNode->IsActive(); @@ -179,6 +181,14 @@ namespace SHADE components[rttr::type::get().get_name().data()] = SHSerializationHelper::SerializeComponentToNode(rigidbody); } node[ComponentsNode] = components; + + YAML::Node scripts; + SHSystemManager::GetSystem()->SerialiseScripts(eid, scripts); + node[ScriptsNode] = scripts; + + //YAML::Emitter emitter; + //emitter << node; + //SHLOG_TRACE(emitter.c_str()) return node; } diff --git a/SHADE_Engine/src/Serialization/SHSerialization.h b/SHADE_Engine/src/Serialization/SHSerialization.h index d247de7a..e02db819 100644 --- a/SHADE_Engine/src/Serialization/SHSerialization.h +++ b/SHADE_Engine/src/Serialization/SHSerialization.h @@ -21,6 +21,7 @@ namespace SHADE constexpr const char* EIDNode = "EID"; constexpr const char* IsActiveNode = "IsActive"; constexpr const char* NumberOfChildrenNode = "NumberOfChildren"; + constexpr const char* ScriptsNode = "Scripts"; struct SH_API SHSerialization { diff --git a/SHADE_Managed/src/Scripts/ScriptStore.cxx b/SHADE_Managed/src/Scripts/ScriptStore.cxx index 252ab071..3f366c36 100644 --- a/SHADE_Managed/src/Scripts/ScriptStore.cxx +++ b/SHADE_Managed/src/Scripts/ScriptStore.cxx @@ -26,6 +26,7 @@ of DigiPen Institute of Technology is prohibited. #include "Utility/Convert.hxx" #include "Script.hxx" #include "Engine/Entity.hxx" +#include "Serialisation/ReflectionUtilities.hxx" namespace SHADE { @@ -470,70 +471,78 @@ namespace SHADE } SAFE_NATIVE_CALL_END_N("SHADE.ScriptStore") } - bool ScriptStore::SerialiseScripts(Entity entity, System::Text::StringBuilder^ buffer, int bufferSize) + + bool ScriptStore::SerialiseScripts(Entity entity, System::IntPtr yamlNodePtr) { SAFE_NATIVE_CALL_BEGIN - // Create a buffer that we can work with temporarily - System::Text::StringBuilder^ jsonString = gcnew System::Text::StringBuilder(); + // Convert to pointer + YAML::Node* yamlNode = reinterpret_cast(yamlNodePtr.ToPointer()); + // Check if yamlNode is valid + if (yamlNode == nullptr) + { + Debug::LogWarning("Attempted to serialise scripts with an invalid YAML Node! Skipping."); + return false; + } + // Check if entity exists, otherwise nothing if (!EntityUtils::IsValid(entity)) - return true; - + { + Debug::LogWarning("Attempted to serialise scripts for an invalid Entity! Skipping."); + return false; + } + // Check if entity exists in the script storage - if (!scripts.ContainsKey(entity)) + if (!scripts.ContainsKey(entity)) return true; // Serialise each script + //yamlNode->SetStyle(YAML::EmitterStyle::Block); System::Collections::Generic::List^ scriptList = scripts[entity]; - for (int i = 0; i < scriptList->Count; ++i) + for each (Script^ script in scriptList) { - throw gcnew System::NotImplementedException; - //jsonString->Append(ReflectionUtilities::Serialise(scriptList[i])); - - // Only add separator if is not last script - if (i != scriptList->Count - 1) - { - jsonString->Append(",\r\n"); - } + ReflectionUtilities::Serialise(script, *yamlNode); } - // Check if the size is too big - if (jsonString->Length > bufferSize) - return false; - - // Otherwise we copy it over - buffer->Clear(); - buffer->Append(jsonString->ToString()); return true; SAFE_NATIVE_CALL_END_N("SHADE.ScriptStore") return false; } - bool ScriptStore::DeserialiseScript(Entity entity, System::String^ yaml) + bool ScriptStore::DeserialiseScripts(Entity entity, System::IntPtr yamlNodePtr) { SAFE_NATIVE_CALL_BEGIN + // Convert to pointer + YAML::Node* yamlNode = reinterpret_cast(yamlNodePtr.ToPointer()); + + // Check if yamlNode is valid + if (yamlNode == nullptr) + { + Debug::LogWarning("Attempted to deserialise scripts with an invalid YAML Node! Skipping."); + return false; + } + // Check if entity exists, otherwise nothing if (!EntityUtils::IsValid(entity)) - return false; - - // Get the name of the script - const int FIRST_QUOTE = yaml->IndexOf('\"'); - const int FIRST_COLON = yaml->IndexOf(':'); - if (FIRST_QUOTE < 0 || FIRST_COLON < 0) // No script name, it's invalid - return false; - const int SCRIPT_NAME_START = FIRST_QUOTE + 1; - const int SCRIPT_NAME_END = FIRST_COLON - 1; - System::String^ typeName = yaml->Substring(SCRIPT_NAME_START, SCRIPT_NAME_END - SCRIPT_NAME_START); - - // Create the script - Script^ script; - if (AddScriptViaNameWithRef(entity, typeName, script)) { - // Copy the data in - throw gcnew System::NotImplementedException; - //ReflectionUtilities::Deserialise(json, script); - return true; + Debug::LogWarning("Attempted to deserialise scripts for an invalid Entity! Skipping."); + return false; + } + + // Go through all elements in the node + for (YAML::Node& node : *yamlNode) + { + // Get the name of the script + const std::string typeName = ""; // TODO + + // Create + Script^ script; + if (AddScriptViaNameWithRef(entity, Convert::ToCLI(typeName), script)) + { + // Copy the data in + ReflectionUtilities::Deserialise(script, node); + return true; + } } SAFE_NATIVE_CALL_END_N("SHADE.ScriptStore") diff --git a/SHADE_Managed/src/Scripts/ScriptStore.hxx b/SHADE_Managed/src/Scripts/ScriptStore.hxx index cc0c1db5..4a9be721 100644 --- a/SHADE_Managed/src/Scripts/ScriptStore.hxx +++ b/SHADE_Managed/src/Scripts/ScriptStore.hxx @@ -17,6 +17,7 @@ of DigiPen Institute of Technology is prohibited. // Project Includes #include "Engine/Entity.hxx" #include "Script.hxx" +#include "Serialization/SHSerialization.h" namespace SHADE { @@ -237,27 +238,23 @@ namespace SHADE /* Serialisation Functions */ /*-----------------------------------------------------------------------------*/ /// - /// Generates a JSON string that represents the set of Scripts attached - /// to the specified Entity. + /// Populates a YAML node with the scripts for a specified Entity. ///

/// This function should only be called from native unmanaged code. ///
/// The Entity to Serialise. - /// - /// StringBuilder handle that maps to a native char array that will contain the - /// serialised string. - /// - /// - /// The size of the char array. + /// + /// Pointer to a YAML::Node that will be populated with all of the serialised + /// scripts and their associated fields. /// /// /// True if serialisation is successful. False if the buffer is too small for /// the serialised output. /// - static bool SerialiseScripts(Entity entity, System::Text::StringBuilder^ buffer, int bufferSize); + static bool SerialiseScripts(Entity entity, System::IntPtr yamlNode); /// - /// Processes a JSON string that represents a single Script and attaches - /// it onto the specified Entity. + /// Processes a YAML node that contains a list of multiple scripts to be loaded + /// into the specified Entity. ///

/// This function should only be called from native unmanaged code. ///
@@ -265,10 +262,10 @@ namespace SHADE /// The Entity to attach the deserialised Scripts to. /// /// - /// JSON string that describes the Script to serialise. + /// Pointer to the YAML::Node that contains serialized script data. /// /// - static bool DeserialiseScript(Entity entity, System::String^ yaml); + static bool DeserialiseScripts(Entity entity, System::IntPtr yamlNode); private: /*-----------------------------------------------------------------------------*/ diff --git a/SHADE_Managed/src/Serialisation/ReflectionUtilities.cxx b/SHADE_Managed/src/Serialisation/ReflectionUtilities.cxx index 2a9cc57c..dc03a95c 100644 --- a/SHADE_Managed/src/Serialisation/ReflectionUtilities.cxx +++ b/SHADE_Managed/src/Serialisation/ReflectionUtilities.cxx @@ -61,13 +61,12 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ /* Serialisation Functions */ /*---------------------------------------------------------------------------------*/ - void ReflectionUtilities::Serialise(System::Object^ object, YAML::Emitter& yaml) + void ReflectionUtilities::Serialise(System::Object^ object, YAML::Node& yamlNode) { using namespace System::Reflection; // Create YAML object - yaml << YAML::Key << Convert::ToNative(object->GetType()->FullName); - yaml << YAML::BeginMap; + YAML::Node scriptNode; // Get all fields System::Collections::Generic::IEnumerable^ fields = GetInstanceFields(object); @@ -78,12 +77,12 @@ namespace SHADE continue; // Serialise - writeFieldIntoYaml(field, object, yaml); + writeFieldIntoYaml(field, object, scriptNode); } - yaml << YAML::EndMap; + yamlNode[Convert::ToNative(object->GetType()->FullName)] = scriptNode; } - void ReflectionUtilities::Deserialise(YAML::Node& yamlNode, Object^ object) + void ReflectionUtilities::Deserialise(Object^ object, YAML::Node& yamlNode) { using namespace System::Reflection; @@ -117,44 +116,50 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ /* Serialization Helper Functions */ /*---------------------------------------------------------------------------------*/ - void ReflectionUtilities::writeFieldIntoYaml(System::Reflection::FieldInfo^ fieldInfo, Object^ object, YAML::Emitter& yaml) + void ReflectionUtilities::writeFieldIntoYaml(System::Reflection::FieldInfo^ fieldInfo, Object^ object, YAML::Node& yamlNode) { - // Field Name - yaml << YAML::Key << Convert::ToNative(fieldInfo->Name); - - // 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)) + // Field YAML Node + YAML::Node fieldNode; + fieldNode.SetStyle(YAML::EmitterStyle::Block); + fieldNode["Name"] = Convert::ToNative(fieldInfo->Name); + + // Retrieve string for the YAML + if (fieldInsertYaml (fieldInfo, object, fieldNode) || + fieldInsertYaml (fieldInfo, object, fieldNode) || + fieldInsertYaml (fieldInfo, object, fieldNode) || + fieldInsertYaml(fieldInfo, object, fieldNode) || + fieldInsertYaml(fieldInfo, object, fieldNode) || + fieldInsertYaml(fieldInfo, object, fieldNode) || + fieldInsertYaml (fieldInfo, object, fieldNode) || + fieldInsertYaml (fieldInfo, object, fieldNode) || + fieldInsertYaml (fieldInfo, object, fieldNode) || + fieldInsertYaml (fieldInfo, object, fieldNode)) { return; } else if (fieldInfo->FieldType->IsSubclassOf(System::Enum::typeid)) { - yaml << safe_cast(fieldInfo->GetValue(object)); + fieldNode = std::to_string(safe_cast(fieldInfo->GetValue(object))); } else if (fieldInfo->FieldType == System::String::typeid) { System::String^ str = safe_cast(fieldInfo->GetValue(object)); - yaml << Convert::ToNative(str); + fieldNode = 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; + fieldNode.SetStyle(YAML::EmitterStyle::Flow); + fieldNode.push_back(vec.x); + fieldNode.push_back(vec.y); } 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; + fieldNode.SetStyle(YAML::EmitterStyle::Flow); + fieldNode.push_back(vec.x); + fieldNode.push_back(vec.y); + fieldNode.push_back(vec.z); } else // Not any of the supported types { @@ -163,7 +168,11 @@ namespace SHADE "[ReflectionUtilities] Failed to parse \"{0}\" of \"{1}\" type for serialization.", fieldInfo->Name, fieldInfo->FieldType) )); + return; } + + // Store the field into YAML + yamlNode.push_back(fieldNode); } void ReflectionUtilities::writeYamlIntoField(System::Reflection::FieldInfo^ fieldInfo, Object^ object, YAML::Node& node) diff --git a/SHADE_Managed/src/Serialisation/ReflectionUtilities.h++ b/SHADE_Managed/src/Serialisation/ReflectionUtilities.h++ index 88469b34..a3d4c33b 100644 --- a/SHADE_Managed/src/Serialisation/ReflectionUtilities.h++ +++ b/SHADE_Managed/src/Serialisation/ReflectionUtilities.h++ @@ -23,11 +23,11 @@ namespace SHADE /* Serialization Helper Functions */ /*---------------------------------------------------------------------------------*/ template - bool ReflectionUtilities::fieldInsertYaml(System::Reflection::FieldInfo^ fieldInfo, System::Object^ object, YAML::Emitter& emitter) + bool ReflectionUtilities::fieldInsertYaml(System::Reflection::FieldInfo^ fieldInfo, System::Object^ object, YAML::Node& fieldNode) { if (fieldInfo->FieldType == FieldType::typeid) { - emitter << safe_cast(fieldInfo->GetValue(object)); + fieldNode = 0.0;//static_cast(safe_cast(fieldInfo->GetValue(object))); return true; } diff --git a/SHADE_Managed/src/Serialisation/ReflectionUtilities.hxx b/SHADE_Managed/src/Serialisation/ReflectionUtilities.hxx index 53f8fa1d..0709f667 100644 --- a/SHADE_Managed/src/Serialisation/ReflectionUtilities.hxx +++ b/SHADE_Managed/src/Serialisation/ReflectionUtilities.hxx @@ -52,7 +52,7 @@ namespace SHADE /// attribute will be serialised. /// /// The object to serialise. - static void Serialise(System::Object^ object, YAML::Emitter& yaml); + static void Serialise(System::Object^ object, YAML::Node& yamlNode); /// /// Deserialises a YAML node that contains a map of Scripts and copies the /// deserialised data into the specified object if there are matching fields. @@ -62,14 +62,14 @@ namespace SHADE /// object. /// /// The object to copy deserialised data into. - static void Deserialise(YAML::Node& yamlNode, Object^ object); + static void Deserialise(System::Object^ object, YAML::Node& yamlNode); /*-----------------------------------------------------------------------------*/ /* Serialization Helper Functions */ /*-----------------------------------------------------------------------------*/ - static void writeFieldIntoYaml(System::Reflection::FieldInfo^ fieldInfo, Object^ object, YAML::Emitter& yaml); + static void writeFieldIntoYaml(System::Reflection::FieldInfo^ fieldInfo, Object^ object, YAML::Node& yamlNode); template - static bool fieldInsertYaml(System::Reflection::FieldInfo^ fieldInfo, System::Object^ object, YAML::Emitter& emitter); + static bool fieldInsertYaml(System::Reflection::FieldInfo^ fieldInfo, System::Object^ object, YAML::Node& fieldNode); 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); From cfed342f9c7571f303e0143d47373b91b3ac2b78 Mon Sep 17 00:00:00 2001 From: Kah Wei Date: Thu, 20 Oct 2022 09:54:51 +0800 Subject: [PATCH 2/4] Modified script serialization to use a sequence of scripts instead of a map --- SHADE_Managed/src/Scripts/ScriptStore.cxx | 2 +- .../src/Serialisation/ReflectionUtilities.cxx | 15 ++++++++++----- .../src/Serialisation/ReflectionUtilities.hxx | 2 ++ 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/SHADE_Managed/src/Scripts/ScriptStore.cxx b/SHADE_Managed/src/Scripts/ScriptStore.cxx index 3f366c36..b9423795 100644 --- a/SHADE_Managed/src/Scripts/ScriptStore.cxx +++ b/SHADE_Managed/src/Scripts/ScriptStore.cxx @@ -497,7 +497,7 @@ namespace SHADE return true; // Serialise each script - //yamlNode->SetStyle(YAML::EmitterStyle::Block); + yamlNode->SetStyle(YAML::EmitterStyle::Block); System::Collections::Generic::List^ scriptList = scripts[entity]; for each (Script^ script in scriptList) { diff --git a/SHADE_Managed/src/Serialisation/ReflectionUtilities.cxx b/SHADE_Managed/src/Serialisation/ReflectionUtilities.cxx index dc03a95c..8e5b1d38 100644 --- a/SHADE_Managed/src/Serialisation/ReflectionUtilities.cxx +++ b/SHADE_Managed/src/Serialisation/ReflectionUtilities.cxx @@ -38,6 +38,11 @@ if (iter != jsonValue.MemberEnd()) \ vec.MEMBER = iter->value.GetDouble(); \ } \ +/*-------------------------------------------------------------------------------------*/ +/* File-Level Constants */ +/*-------------------------------------------------------------------------------------*/ +static const std::string_view SCRIPT_TYPE_YAMLTAG = "Type"; + /*-------------------------------------------------------------------------------------*/ /* Function Definitions */ /*-------------------------------------------------------------------------------------*/ @@ -61,12 +66,14 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ /* Serialisation Functions */ /*---------------------------------------------------------------------------------*/ - void ReflectionUtilities::Serialise(System::Object^ object, YAML::Node& yamlNode) + void ReflectionUtilities::Serialise(System::Object^ object, YAML::Node& scriptListNode) { using namespace System::Reflection; // Create YAML object YAML::Node scriptNode; + scriptNode.SetStyle(YAML::EmitterStyle::Block); + scriptNode[SCRIPT_TYPE_YAMLTAG] = Convert::ToNative(object->GetType()->FullName); // Get all fields System::Collections::Generic::IEnumerable^ fields = GetInstanceFields(object); @@ -80,7 +87,7 @@ namespace SHADE writeFieldIntoYaml(field, object, scriptNode); } - yamlNode[Convert::ToNative(object->GetType()->FullName)] = scriptNode; + scriptListNode.push_back(scriptNode); } void ReflectionUtilities::Deserialise(Object^ object, YAML::Node& yamlNode) { @@ -120,8 +127,6 @@ namespace SHADE { // Field YAML Node YAML::Node fieldNode; - fieldNode.SetStyle(YAML::EmitterStyle::Block); - fieldNode["Name"] = Convert::ToNative(fieldInfo->Name); // Retrieve string for the YAML if (fieldInsertYaml (fieldInfo, object, fieldNode) || @@ -172,7 +177,7 @@ namespace SHADE } // Store the field into YAML - yamlNode.push_back(fieldNode); + yamlNode[Convert::ToNative(fieldInfo->Name)] = fieldNode; } void ReflectionUtilities::writeYamlIntoField(System::Reflection::FieldInfo^ fieldInfo, Object^ object, YAML::Node& node) diff --git a/SHADE_Managed/src/Serialisation/ReflectionUtilities.hxx b/SHADE_Managed/src/Serialisation/ReflectionUtilities.hxx index 0709f667..4742c7ff 100644 --- a/SHADE_Managed/src/Serialisation/ReflectionUtilities.hxx +++ b/SHADE_Managed/src/Serialisation/ReflectionUtilities.hxx @@ -64,6 +64,8 @@ namespace SHADE /// The object to copy deserialised data into. static void Deserialise(System::Object^ object, YAML::Node& yamlNode); + + private: /*-----------------------------------------------------------------------------*/ /* Serialization Helper Functions */ /*-----------------------------------------------------------------------------*/ From 4bc91283c8448dc9ae84066340ce5bfd8be5877e Mon Sep 17 00:00:00 2001 From: Kah Wei Date: Thu, 20 Oct 2022 10:10:43 +0800 Subject: [PATCH 3/4] Fixed primitive fields not being serialised --- .../src/Serialisation/ReflectionUtilities.cxx | 86 ++++++++++--------- .../src/Serialisation/ReflectionUtilities.hxx | 3 +- 2 files changed, 45 insertions(+), 44 deletions(-) diff --git a/SHADE_Managed/src/Serialisation/ReflectionUtilities.cxx b/SHADE_Managed/src/Serialisation/ReflectionUtilities.cxx index 8e5b1d38..3e963818 100644 --- a/SHADE_Managed/src/Serialisation/ReflectionUtilities.cxx +++ b/SHADE_Managed/src/Serialisation/ReflectionUtilities.cxx @@ -73,7 +73,7 @@ namespace SHADE // Create YAML object YAML::Node scriptNode; scriptNode.SetStyle(YAML::EmitterStyle::Block); - scriptNode[SCRIPT_TYPE_YAMLTAG] = Convert::ToNative(object->GetType()->FullName); + scriptNode[SCRIPT_TYPE_YAMLTAG.data()] = Convert::ToNative(object->GetType()->FullName); // Get all fields System::Collections::Generic::IEnumerable^ fields = GetInstanceFields(object); @@ -129,51 +129,53 @@ namespace SHADE YAML::Node fieldNode; // Retrieve string for the YAML - if (fieldInsertYaml (fieldInfo, object, fieldNode) || - fieldInsertYaml (fieldInfo, object, fieldNode) || - fieldInsertYaml (fieldInfo, object, fieldNode) || + const bool PRIMITIVE_SERIALIZED = fieldInsertYaml(fieldInfo, object, fieldNode) || + fieldInsertYaml(fieldInfo, object, fieldNode) || + fieldInsertYaml(fieldInfo, object, fieldNode) || fieldInsertYaml(fieldInfo, object, fieldNode) || fieldInsertYaml(fieldInfo, object, fieldNode) || fieldInsertYaml(fieldInfo, object, fieldNode) || - fieldInsertYaml (fieldInfo, object, fieldNode) || - fieldInsertYaml (fieldInfo, object, fieldNode) || - fieldInsertYaml (fieldInfo, object, fieldNode) || - fieldInsertYaml (fieldInfo, object, fieldNode)) + fieldInsertYaml(fieldInfo, object, fieldNode) || + fieldInsertYaml(fieldInfo, object, fieldNode) || + fieldInsertYaml(fieldInfo, object, fieldNode) || + fieldInsertYaml(fieldInfo, object, fieldNode); + + // Serialization of more complex types + if (!PRIMITIVE_SERIALIZED) { - return; - } - else if (fieldInfo->FieldType->IsSubclassOf(System::Enum::typeid)) - { - fieldNode = std::to_string(safe_cast(fieldInfo->GetValue(object))); - } - else if (fieldInfo->FieldType == System::String::typeid) - { - System::String^ str = safe_cast(fieldInfo->GetValue(object)); - fieldNode = Convert::ToNative(str); - } - else if (fieldInfo->FieldType == Vector2::typeid) - { - Vector2 vec = safe_cast(fieldInfo->GetValue(object)); - fieldNode.SetStyle(YAML::EmitterStyle::Flow); - fieldNode.push_back(vec.x); - fieldNode.push_back(vec.y); - } - else if (fieldInfo->FieldType == Vector3::typeid) - { - Vector3 vec = safe_cast(fieldInfo->GetValue(object)); - fieldNode.SetStyle(YAML::EmitterStyle::Flow); - fieldNode.push_back(vec.x); - fieldNode.push_back(vec.y); - fieldNode.push_back(vec.z); - } - 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) - )); - return; + if (fieldInfo->FieldType->IsSubclassOf(System::Enum::typeid)) + { + fieldNode = std::to_string(safe_cast(fieldInfo->GetValue(object))); + } + else if (fieldInfo->FieldType == System::String::typeid) + { + System::String^ str = safe_cast(fieldInfo->GetValue(object)); + fieldNode = Convert::ToNative(str); + } + else if (fieldInfo->FieldType == Vector2::typeid) + { + Vector2 vec = safe_cast(fieldInfo->GetValue(object)); + fieldNode.SetStyle(YAML::EmitterStyle::Flow); + fieldNode.push_back(vec.x); + fieldNode.push_back(vec.y); + } + else if (fieldInfo->FieldType == Vector3::typeid) + { + Vector3 vec = safe_cast(fieldInfo->GetValue(object)); + fieldNode.SetStyle(YAML::EmitterStyle::Flow); + fieldNode.push_back(vec.x); + fieldNode.push_back(vec.y); + fieldNode.push_back(vec.z); + } + 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) + )); + return; + } } // Store the field into YAML diff --git a/SHADE_Managed/src/Serialisation/ReflectionUtilities.hxx b/SHADE_Managed/src/Serialisation/ReflectionUtilities.hxx index 4742c7ff..fbae5ee0 100644 --- a/SHADE_Managed/src/Serialisation/ReflectionUtilities.hxx +++ b/SHADE_Managed/src/Serialisation/ReflectionUtilities.hxx @@ -58,8 +58,7 @@ namespace SHADE /// 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 JSON string that contains the data to copy into this Script object. /// /// The object to copy deserialised data into. static void Deserialise(System::Object^ object, YAML::Node& yamlNode); From 166a036142bfad809663775c107d5e686449d79f Mon Sep 17 00:00:00 2001 From: Kah Wei Date: Thu, 20 Oct 2022 11:08:20 +0800 Subject: [PATCH 4/4] Completed script serialization in YAML --- SHADE_Engine/src/Scripting/SHScriptEngine.cpp | 4 +- SHADE_Engine/src/Scripting/SHScriptEngine.h | 54 ++++++++-------- .../src/Serialization/SHSerialization.cpp | 7 +- SHADE_Managed/src/Scripts/ScriptStore.cxx | 24 +++++-- .../src/Serialisation/ReflectionUtilities.h++ | 5 +- .../src/Serialisation/ReflectionUtilities.hxx | 1 - SHADE_Managed/src/Utility/Convert.hxx | 64 +++++++++++++++++++ 7 files changed, 117 insertions(+), 42 deletions(-) diff --git a/SHADE_Engine/src/Scripting/SHScriptEngine.cpp b/SHADE_Engine/src/Scripting/SHScriptEngine.cpp index 6585414d..fea59353 100644 --- a/SHADE_Engine/src/Scripting/SHScriptEngine.cpp +++ b/SHADE_Engine/src/Scripting/SHScriptEngine.cpp @@ -128,7 +128,7 @@ namespace SHADE /*-----------------------------------------------------------------------------------*/ /* Script Serialisation Functions */ /*-----------------------------------------------------------------------------------*/ - bool SHScriptEngine::DeserialiseScript(EntityID entity, YAML::Node& scriptsNode) const + bool SHScriptEngine::DeserialiseScripts(EntityID entity, const YAML::Node& scriptsNode) const { return csScriptsDeserialiseYaml(entity, &scriptsNode); } @@ -374,7 +374,7 @@ namespace SHADE DEFAULT_CSHARP_NAMESPACE + ".ScriptStore", "SerialiseScripts" ); - csScriptsDeserialiseYaml = dotNet.GetFunctionPtr + csScriptsDeserialiseYaml = dotNet.GetFunctionPtr ( DEFAULT_CSHARP_LIB_NAME, DEFAULT_CSHARP_NAMESPACE + ".ScriptStore", diff --git a/SHADE_Engine/src/Scripting/SHScriptEngine.h b/SHADE_Engine/src/Scripting/SHScriptEngine.h index 58dbe0b3..137d978f 100644 --- a/SHADE_Engine/src/Scripting/SHScriptEngine.h +++ b/SHADE_Engine/src/Scripting/SHScriptEngine.h @@ -161,7 +161,7 @@ namespace SHADE /// YAML Node that contains the serialised script data. /// /// True if successfully deserialised. - bool DeserialiseScript(EntityID entity, YAML::Node& scriptsNode) const; + bool DeserialiseScripts(EntityID entity, const YAML::Node& scriptsNode) const; /*-----------------------------------------------------------------------------*/ /* Script Editor Functions */ @@ -211,13 +211,13 @@ namespace SHADE /*-----------------------------------------------------------------------------*/ /* Type Definitions */ /*-----------------------------------------------------------------------------*/ - using CsFuncPtr = void(*)(void); - using CsScriptManipFuncPtr = bool(*)(EntityID, const char*); - using CsScriptBasicFuncPtr = void(*)(EntityID); - using CsScriptOptionalFuncPtr = void(*)(EntityID, bool); - using CsScriptSerialiseYamlFuncPtr = bool(*)(EntityID, void*); - using CsScriptSerialiseYamlFuncPtr = bool(*)(EntityID, void*); - using CsScriptEditorFuncPtr = void(*)(EntityID); + using CsFuncPtr = void(*)(void); + using CsScriptManipFuncPtr = bool(*)(EntityID, const char*); + using CsScriptBasicFuncPtr = void(*)(EntityID); + using CsScriptOptionalFuncPtr = void(*)(EntityID, bool); + using CsScriptSerialiseYamlFuncPtr = bool(*)(EntityID, void*); + using CsScriptDeserialiseYamlFuncPtr = bool(*)(EntityID, const void*); + using CsScriptEditorFuncPtr = void(*)(EntityID); /*-----------------------------------------------------------------------------*/ /* Constants */ @@ -231,29 +231,29 @@ namespace SHADE /*-----------------------------------------------------------------------------*/ /* Data Members */ /*-----------------------------------------------------------------------------*/ - SHDotNetRuntime dotNet { false }; + SHDotNetRuntime dotNet { false }; // Function Pointers to CLR Code // - Engine Lifecycle - CsFuncPtr csEngineInit = nullptr; - CsFuncPtr csEngineLoadScripts = nullptr; - CsFuncPtr csEngineUnloadScripts = nullptr; - CsFuncPtr csEngineReloadScripts = nullptr; - CsFuncPtr csEngineExit = nullptr; + CsFuncPtr csEngineInit = nullptr; + CsFuncPtr csEngineLoadScripts = nullptr; + CsFuncPtr csEngineUnloadScripts = nullptr; + CsFuncPtr csEngineReloadScripts = nullptr; + CsFuncPtr csEngineExit = nullptr; // - Scripts Store - CsFuncPtr csScriptsFrameSetUp = nullptr; - CsFuncPtr csScriptsExecuteFixedUpdate = nullptr; - CsFuncPtr csScriptsExecuteUpdate = nullptr; - CsFuncPtr csScriptsExecuteLateUpdate = nullptr; - CsFuncPtr csScriptsFrameCleanUp = nullptr; - CsScriptManipFuncPtr csScriptsAdd = nullptr; - CsScriptBasicFuncPtr csScriptsRemoveAll = nullptr; - CsScriptOptionalFuncPtr csScriptsRemoveAllImmediately = nullptr; - CsScriptSerialiseYamlFuncPtr csScriptsSerialiseYaml = nullptr; - CsScriptSerialiseYamlFuncPtr csScriptsDeserialiseYaml = nullptr; + CsFuncPtr csScriptsFrameSetUp = nullptr; + CsFuncPtr csScriptsExecuteFixedUpdate = nullptr; + CsFuncPtr csScriptsExecuteUpdate = nullptr; + CsFuncPtr csScriptsExecuteLateUpdate = nullptr; + CsFuncPtr csScriptsFrameCleanUp = nullptr; + CsScriptManipFuncPtr csScriptsAdd = nullptr; + CsScriptBasicFuncPtr csScriptsRemoveAll = nullptr; + CsScriptOptionalFuncPtr csScriptsRemoveAllImmediately = nullptr; + CsScriptSerialiseYamlFuncPtr csScriptsSerialiseYaml = nullptr; + CsScriptDeserialiseYamlFuncPtr csScriptsDeserialiseYaml = nullptr; // - Editor - CsScriptEditorFuncPtr csEditorRenderScripts = nullptr; - CsFuncPtr csEditorUndo = nullptr; - CsFuncPtr csEditorRedo = nullptr; + CsScriptEditorFuncPtr csEditorRenderScripts = nullptr; + CsFuncPtr csEditorUndo = nullptr; + CsFuncPtr csEditorRedo = nullptr; /*-----------------------------------------------------------------------------*/ /* Event Handler Functions */ diff --git a/SHADE_Engine/src/Serialization/SHSerialization.cpp b/SHADE_Engine/src/Serialization/SHSerialization.cpp index d0023107..63583cf2 100644 --- a/SHADE_Engine/src/Serialization/SHSerialization.cpp +++ b/SHADE_Engine/src/Serialization/SHSerialization.cpp @@ -79,6 +79,10 @@ namespace SHADE } } } + + // Deserialise scripts + if (node[ScriptsNode]) + SHSystemManager::GetSystem()->DeserialiseScripts(eid, node[ScriptsNode]); } void SHSerialization::DeserializeSceneFromFile(std::filesystem::path const& path) @@ -186,9 +190,6 @@ namespace SHADE SHSystemManager::GetSystem()->SerialiseScripts(eid, scripts); node[ScriptsNode] = scripts; - //YAML::Emitter emitter; - //emitter << node; - //SHLOG_TRACE(emitter.c_str()) return node; } diff --git a/SHADE_Managed/src/Scripts/ScriptStore.cxx b/SHADE_Managed/src/Scripts/ScriptStore.cxx index b9423795..b6bc1815 100644 --- a/SHADE_Managed/src/Scripts/ScriptStore.cxx +++ b/SHADE_Managed/src/Scripts/ScriptStore.cxx @@ -481,14 +481,14 @@ namespace SHADE // Check if yamlNode is valid if (yamlNode == nullptr) { - Debug::LogWarning("Attempted to serialise scripts with an invalid YAML Node! Skipping."); + Debug::LogWarning("[ScriptStore] Attempted to serialise scripts with an invalid YAML Node! Skipping."); return false; } // Check if entity exists, otherwise nothing if (!EntityUtils::IsValid(entity)) { - Debug::LogWarning("Attempted to serialise scripts for an invalid Entity! Skipping."); + Debug::LogWarning("[ScriptStore] Attempted to serialise scripts for an invalid Entity! Skipping."); return false; } @@ -518,14 +518,14 @@ namespace SHADE // Check if yamlNode is valid if (yamlNode == nullptr) { - Debug::LogWarning("Attempted to deserialise scripts with an invalid YAML Node! Skipping."); + Debug::LogWarning("[ScriptStore] Attempted to deserialise scripts with an invalid YAML Node! Skipping."); return false; } // Check if entity exists, otherwise nothing if (!EntityUtils::IsValid(entity)) { - Debug::LogWarning("Attempted to deserialise scripts for an invalid Entity! Skipping."); + Debug::LogWarning("[ScriptStore] Attempted to deserialise scripts for an invalid Entity! Skipping."); return false; } @@ -533,17 +533,27 @@ namespace SHADE for (YAML::Node& node : *yamlNode) { // Get the name of the script - const std::string typeName = ""; // TODO + if (!node["Type"]) + { + Debug::LogWarning("[ScriptStore] Script with no type detected, skipping."); + continue; + } + + System::String^ typeName = Convert::ToCLI(node["Type"].as()); // Create Script^ script; - if (AddScriptViaNameWithRef(entity, Convert::ToCLI(typeName), script)) + if (AddScriptViaNameWithRef(entity, typeName, script)) { // Copy the data in ReflectionUtilities::Deserialise(script, node); - return true; + } + else + { + Debug::LogWarning("[ScriptStore] Script with unloaded type detected, skipping."); } } + return true; SAFE_NATIVE_CALL_END_N("SHADE.ScriptStore") return false; diff --git a/SHADE_Managed/src/Serialisation/ReflectionUtilities.h++ b/SHADE_Managed/src/Serialisation/ReflectionUtilities.h++ index a3d4c33b..7c39232a 100644 --- a/SHADE_Managed/src/Serialisation/ReflectionUtilities.h++ +++ b/SHADE_Managed/src/Serialisation/ReflectionUtilities.h++ @@ -27,7 +27,8 @@ namespace SHADE { if (fieldInfo->FieldType == FieldType::typeid) { - fieldNode = 0.0;//static_cast(safe_cast(fieldInfo->GetValue(object))); + const FieldType VALUE = safe_cast(fieldInfo->GetValue(object)); + fieldNode = static_cast(VALUE); return true; } @@ -37,7 +38,7 @@ namespace SHADE template bool ReflectionUtilities::fieldAssignYaml(System::Reflection::FieldInfo^ fieldInfo, Object^ object, YAML::Node& node) { - return fieldAssignYaml(fieldInfo, object, node); + return fieldAssignYaml>(fieldInfo, object, node); } template diff --git a/SHADE_Managed/src/Serialisation/ReflectionUtilities.hxx b/SHADE_Managed/src/Serialisation/ReflectionUtilities.hxx index fbae5ee0..403c913c 100644 --- a/SHADE_Managed/src/Serialisation/ReflectionUtilities.hxx +++ b/SHADE_Managed/src/Serialisation/ReflectionUtilities.hxx @@ -63,7 +63,6 @@ namespace SHADE /// The object to copy deserialised data into. static void Deserialise(System::Object^ object, YAML::Node& yamlNode); - private: /*-----------------------------------------------------------------------------*/ /* Serialization Helper Functions */ diff --git a/SHADE_Managed/src/Utility/Convert.hxx b/SHADE_Managed/src/Utility/Convert.hxx index b41ffef4..f04cbf4b 100644 --- a/SHADE_Managed/src/Utility/Convert.hxx +++ b/SHADE_Managed/src/Utility/Convert.hxx @@ -91,4 +91,68 @@ namespace SHADE /// Managed copy of a native std::string. static System::String^ ToCLI(const std::string& str); }; + + /// + /// Type Transformer for managed types to native types. + /// + /// + /// Managed type to get the native type for. + /// + template + struct ToNativeType + { + public: + using Value = void; + }; + template<> struct ToNativeType { using Value = int16_t; }; + template<> struct ToNativeType { using Value = int32_t; }; + template<> struct ToNativeType { using Value = int64_t; }; + template<> struct ToNativeType { using Value = uint16_t; }; + template<> struct ToNativeType { using Value = uint32_t; }; + template<> struct ToNativeType { using Value = uint64_t; }; + template<> struct ToNativeType { using Value = int8_t; }; + template<> struct ToNativeType { using Value = bool; }; + template<> struct ToNativeType { using Value = double; }; + template<> struct ToNativeType { using Value = float; }; + + /// + /// Alias for ToNativeType::Value + /// + /// + /// Managed type to get the native type for. + /// + template + using ToNativeType_T = typename ToNativeType::Value; + + /// + /// Type Transformer for native types to managed types. + /// + /// + /// Managed type to get the native type for. + /// + template + struct ToManagedType + { + public: + using Value = void; + }; + template<> struct ToManagedType { using Value = System::Byte; }; + template<> struct ToManagedType { using Value = System::Int16; }; + template<> struct ToManagedType { using Value = System::Int32; }; + template<> struct ToManagedType { using Value = System::Int64; }; + template<> struct ToManagedType { using Value = System::UInt16; }; + template<> struct ToManagedType { using Value = System::UInt32; }; + template<> struct ToManagedType { using Value = System::UInt64; }; + template<> struct ToManagedType { using Value = bool; }; + template<> struct ToManagedType { using Value = double; }; + template<> struct ToManagedType { using Value = float; }; + + /// + /// Alias for ToManagedType::Value + /// + /// + /// Managed type to get the native type for. + /// + template + using ToManagedType_T = typename ToManagedType::Value; }