From 5bef209189cded392addec4ad4a45e04dc768618 Mon Sep 17 00:00:00 2001 From: Kah Wei Date: Fri, 3 Feb 2023 19:17:20 +0800 Subject: [PATCH] Modified ScriptAddAction to use serialization --- SHADE_Managed/src/Editor/UndoRedoStack.cxx | 35 ++++++++--- SHADE_Managed/src/Editor/UndoRedoStack.hxx | 9 ++- SHADE_Managed/src/Scripts/ScriptStore.cxx | 58 +++++++++++++++++-- SHADE_Managed/src/Scripts/ScriptStore.hxx | 22 +++++-- .../Serialisation/SerialisationUtilities.cxx | 22 +++++++ .../Serialisation/SerialisationUtilities.hxx | 2 + 6 files changed, 128 insertions(+), 20 deletions(-) diff --git a/SHADE_Managed/src/Editor/UndoRedoStack.cxx b/SHADE_Managed/src/Editor/UndoRedoStack.cxx index 3d1f04e9..5b39f879 100644 --- a/SHADE_Managed/src/Editor/UndoRedoStack.cxx +++ b/SHADE_Managed/src/Editor/UndoRedoStack.cxx @@ -22,6 +22,7 @@ of DigiPen Institute of Technology is prohibited. #include "Utility/Debug.hxx" #include "Utility/Convert.hxx" #include "Scripts/ScriptStore.hxx" +#include "Serialisation/SerialisationUtilities.hxx" namespace SHADE { @@ -266,8 +267,10 @@ namespace SHADE /* ScriptAddCommand - Constructor */ /*---------------------------------------------------------------------------------*/ ScriptAddCommand::ScriptAddCommand(EntityID id, Script^ script) - : entity { id } - , addedScript { script } + : entity { id } + , typeName { script->GetType()->FullName } + , serialisedScript { SerialisationUtilities::Serialise(script) } + , insertedIndex { ScriptStore::GetScriptIndex(script) } {} /*---------------------------------------------------------------------------------*/ @@ -275,12 +278,20 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ bool ScriptAddCommand::Execute() { - return ScriptStore::AddScript(entity, addedScript) != nullptr; + Script^ script = nullptr; + if (ScriptStore::AddScriptViaNameWithRef(entity, typeName, script)) + { + SerialisationUtilities::Deserialise(script, serialisedScript); + insertedIndex = ScriptStore::GetScriptIndex(script); + return true; + } + + return false; } bool ScriptAddCommand::Unexceute() { - return ScriptStore::RemoveScript(entity, addedScript); + return ScriptStore::RemoveScript(entity, insertedIndex); } bool ScriptAddCommand::Merge(ICommand^) @@ -293,8 +304,9 @@ namespace SHADE /* ScriptRemoveCommand - Constructor */ /*---------------------------------------------------------------------------------*/ ScriptRemoveCommand::ScriptRemoveCommand(EntityID id, Script^ script, int index) - : entity { id } - , removedScript { script } + : entity{ id } + , typeName{ script->GetType()->FullName } + , serialisedScript{ SerialisationUtilities::Serialise(script) } , originalIndex { index } {} @@ -303,12 +315,19 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ bool ScriptRemoveCommand::Execute() { - return ScriptStore::RemoveScript(entity, removedScript); + return ScriptStore::RemoveScript(entity, originalIndex); } bool ScriptRemoveCommand::Unexceute() { - return ScriptStore::AddScript(entity, removedScript, originalIndex) != nullptr; + Script^ script = nullptr; + if (ScriptStore::AddScriptViaNameWithRef(entity, typeName, script, originalIndex)) + { + SerialisationUtilities::Deserialise(script, serialisedScript); + return true; + } + + return false; } bool ScriptRemoveCommand::Merge(ICommand^) diff --git a/SHADE_Managed/src/Editor/UndoRedoStack.hxx b/SHADE_Managed/src/Editor/UndoRedoStack.hxx index c377e2b7..b46da020 100644 --- a/SHADE_Managed/src/Editor/UndoRedoStack.hxx +++ b/SHADE_Managed/src/Editor/UndoRedoStack.hxx @@ -114,7 +114,9 @@ namespace SHADE private: EntityID entity; - Script^ addedScript; + System::String^ typeName; + System::String^ serialisedScript; + int insertedIndex; }; private ref class ScriptRemoveCommand sealed : public ICommand @@ -126,9 +128,10 @@ namespace SHADE bool Unexceute() override; bool Merge(ICommand^ command) override; - private: + private: EntityID entity; - Script^ removedScript; + System::String^ typeName; + System::String^ serialisedScript; int originalIndex; }; diff --git a/SHADE_Managed/src/Scripts/ScriptStore.cxx b/SHADE_Managed/src/Scripts/ScriptStore.cxx index c1747852..62bfc383 100644 --- a/SHADE_Managed/src/Scripts/ScriptStore.cxx +++ b/SHADE_Managed/src/Scripts/ScriptStore.cxx @@ -100,9 +100,14 @@ namespace SHADE } bool ScriptStore::AddScriptViaNameWithRef(Entity entity, System::String^ scriptName, Script^% createdScript) + { + return AddScriptViaNameWithRef(entity, scriptName, createdScript, System::Int32::MaxValue); + } + + bool ScriptStore::AddScriptViaNameWithRef(Entity entity, System::String^ scriptName, [System::Runtime::InteropServices::Out] Script^% createdScript, int index) { // Check if we are set up to get scripts - if (addScriptMethod == nullptr) + if (addScriptMethod == nullptr) { Debug::LogError("[ScriptStore] Native AddScript() was not loaded. Unable to add scripts."); return false; @@ -120,17 +125,18 @@ namespace SHADE return false; } - // Otherwise, add the script + // Add the script System::Reflection::MethodInfo^ method = addScriptMethod->MakeGenericMethod(scriptType); try { - array^ params = gcnew array{entity}; - createdScript = safe_cast(method->Invoke(nullptr, params)); + // Create the script and add it in + createdScript = safe_cast(System::Activator::CreateInstance(scriptType)); + AddScript(entity, createdScript, index); } catch (System::Exception^ e) { std::ostringstream oss; - oss << "[ScriptStore] Failed to add Script named \"" << Convert::ToNative(scriptName) + oss << "[ScriptStore] Failed to add Script named \"" << Convert::ToNative(scriptType->Name) << "\" to Entity #" << entity << "! (" << Convert::ToNative(e->GetType()->Name) << ")"; oss << Convert::ToNative(e->ToString()); Debug::LogError(oss.str()); @@ -321,6 +327,19 @@ namespace SHADE } return nullptr; } + + int ScriptStore::GetScriptIndex(Script^ script) + { + // Check if entity exists in the script storage + if (!scripts.ContainsKey(script->Owner.EntityId)) + { + Debug::LogError("[ScriptStore] Attempted to query a Script that does not belong to the ScriptStore."); + return -1; + } + + return scripts[script->Owner.EntityId]->IndexOf(script); + } + generic void ScriptStore::RemoveScript(Entity entity) { @@ -376,6 +395,35 @@ namespace SHADE removeScript(script); return true; } + + bool ScriptStore::RemoveScript(Entity entity, int index) + { + // Check if entity exists + if (!EntityUtils::IsValid(entity)) + { + 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)) + { + Debug::LogError("[ScriptStore] Attempted to remove a Script that does not belong to the specified Entity!"); + return false; + } + + // Check if the script index is out of bounds + if (index < 0 || index >= scripts[entity]->Count) + { + Debug::LogError("[ScriptStore] Attempted to remove a Script from an out of range index!"); + return false; + } + + // Script found, queue it for deletion + removeScript((*scripts[entity])[index]); + return true; + } + void ScriptStore::RemoveAllScripts(Entity entity) { SAFE_NATIVE_CALL_BEGIN diff --git a/SHADE_Managed/src/Scripts/ScriptStore.hxx b/SHADE_Managed/src/Scripts/ScriptStore.hxx index bac58a77..e59e3a7f 100644 --- a/SHADE_Managed/src/Scripts/ScriptStore.hxx +++ b/SHADE_Managed/src/Scripts/ScriptStore.hxx @@ -82,9 +82,9 @@ namespace SHADE /// /// Adds a Script to a specified Entity. ///
- /// This function is meant for consumption from native code or for serialisation - /// purposes. If you are writing in C# or C++/CLI and not doing serialisation, - /// use AddScript<T>() instead as it is faster. + /// This function is meant for deserialisation purposes. If you are writing in + /// C# or C++/CLI and not doing serialisation, use AddScript<T>() instead + /// as it is faster. ///
/// The entity to add a script to. /// The entity to add a script to. @@ -96,6 +96,7 @@ namespace SHADE /// console. /// static bool AddScriptViaNameWithRef(Entity entity, System::String^ scriptName, [System::Runtime::InteropServices::Out] Script^% createdScript); + static bool AddScriptViaNameWithRef(Entity entity, System::String^ scriptName, [System::Runtime::InteropServices::Out] Script^% createdScript, int index); /// /// Retrieves the first Script from the specified Entity that matches the /// specified type. @@ -190,6 +191,12 @@ namespace SHADE /// static System::Collections::Generic::IEnumerable^ GetAllScripts(Entity entity); /// + /// Retrieves the index of a Script within the list of it's Entity's script list. + /// + /// Script to get the index of. + /// Script index if valid. Otherwise -1. + static int GetScriptIndex(Script^ script); + /// /// Removes all Scripts of the specified type from the specified Entity. /// /// @@ -201,7 +208,7 @@ namespace SHADE /// If the specified Entity is invalid. /// generic where T : ref class, Script - static void RemoveScript(Entity entity); + static void RemoveScript(Entity entity); /// /// Removes a specific script from the specified entity. /// @@ -210,6 +217,13 @@ namespace SHADE /// True if successfully removed. False otherwise. static bool RemoveScript(Entity entity, Script^ script); /// + /// Removes a script at a specified index from the specified entity. + /// + /// The entity to remove the script from. + /// Index of the script to remove. + /// True if successfully removed. False otherwise. + static bool RemoveScript(Entity entity, int index); + /// /// 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. diff --git a/SHADE_Managed/src/Serialisation/SerialisationUtilities.cxx b/SHADE_Managed/src/Serialisation/SerialisationUtilities.cxx index 83da64b8..d6f0f49c 100644 --- a/SHADE_Managed/src/Serialisation/SerialisationUtilities.cxx +++ b/SHADE_Managed/src/Serialisation/SerialisationUtilities.cxx @@ -22,6 +22,7 @@ of DigiPen Institute of Technology is prohibited. #include "Assets/MaterialAsset.hxx" #include "Assets/MeshAsset.hxx" #include "Scripts/Script.hxx" +#include "Scripts/ScriptStore.hxx" /*-------------------------------------------------------------------------------------*/ /* File-Level Constants */ @@ -79,6 +80,21 @@ namespace SHADE scriptListNode.push_back(scriptNode); } + + System::String^ SerialisationUtilities::Serialise(Script^ script) + { + YAML::Node node; + node.SetStyle(YAML::EmitterStyle::Block); + Serialise(script, node); + YAML::Emitter emitter; + emitter << YAML::BeginMap; + emitter << node; + emitter << YAML::EndMap; + return Convert::ToCLI(emitter.c_str()); + /*std::string str = emitter.c_str(); + return Convert::ToCLI(str.substr(2));*/ + } + void SerialisationUtilities::Deserialise(Object^ object, YAML::Node& yamlNode) { using namespace System::Reflection; @@ -135,6 +151,12 @@ namespace SHADE } } } + + void SerialisationUtilities::Deserialise(Script^ script, System::String^ yamlString) + { + Deserialise(script, YAML::Load(Convert::ToNative(yamlString))); + } + /*---------------------------------------------------------------------------------*/ /* Serialization Helper Functions */ /*---------------------------------------------------------------------------------*/ diff --git a/SHADE_Managed/src/Serialisation/SerialisationUtilities.hxx b/SHADE_Managed/src/Serialisation/SerialisationUtilities.hxx index 5b6fc69e..9d927d53 100644 --- a/SHADE_Managed/src/Serialisation/SerialisationUtilities.hxx +++ b/SHADE_Managed/src/Serialisation/SerialisationUtilities.hxx @@ -39,6 +39,7 @@ namespace SHADE /// /// The object to serialise. static void Serialise(System::Object^ object, YAML::Node& yamlNode); + static System::String^ Serialise(Script^ script); /// /// Deserialises a YAML node that contains a map of Scripts and copies the /// deserialised data into the specified object if there are matching fields. @@ -48,6 +49,7 @@ namespace SHADE /// /// The object to copy deserialised data into. static void Deserialise(System::Object^ object, YAML::Node& yamlNode); + static void Deserialise(Script^ script, System::String^ yamlString); private: /*-----------------------------------------------------------------------------*/