From 7247faee739acdb8f1d2832ad63f2656b83bfd2e Mon Sep 17 00:00:00 2001 From: Sri Sham Haran Date: Mon, 26 Sep 2022 21:08:59 +0800 Subject: [PATCH 1/6] Serialization [WIP] --- .../Inspector/SHEditorComponentView.hpp | 2 +- .../src/Serialization/SHSerialization.cpp | 79 +++++++++++++++ .../src/Serialization/SHSerialization.h | 28 ++++++ .../Serialization/SHSerializationHelper.hpp | 97 +++++++++++++++++++ 4 files changed, 205 insertions(+), 1 deletion(-) create mode 100644 SHADE_Engine/src/Serialization/SHSerialization.cpp create mode 100644 SHADE_Engine/src/Serialization/SHSerialization.h create mode 100644 SHADE_Engine/src/Serialization/SHSerializationHelper.hpp diff --git a/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp b/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp index 080cbf2c..889abc79 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp +++ b/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp @@ -44,7 +44,7 @@ namespace SHADE { if (!component) return; - auto componentType = rttr::type::get(*component); + auto componentType = rttr::type::get(); CheckBox("##IsActive", [component]() {return component->isActive; }, [component](bool const& active) {component->isActive = active; }); ImGui::SameLine(); if (ImGui::CollapsingHeader(componentType.get_name().data())) diff --git a/SHADE_Engine/src/Serialization/SHSerialization.cpp b/SHADE_Engine/src/Serialization/SHSerialization.cpp new file mode 100644 index 00000000..ee681a85 --- /dev/null +++ b/SHADE_Engine/src/Serialization/SHSerialization.cpp @@ -0,0 +1,79 @@ +#include "SHpch.h" +#include "SHSerialization.h" + +#include + +#include "Scene/SHSceneManager.h" +#include "Tools/SHException.h" + +#include "SHSerializationHelper.hpp" +#include "Math/Transform/SHTransformComponent.h" + +namespace SHADE +{ + namespace SHSerialization + { + void SerializeSceneToFile(std::filesystem::path const& path) + { + + } + + std::string SerializeSceneToString() + { + YAML::Emitter out; + SerializeSceneToEmitter(out); + return std::string(out.c_str()); + } + + void SerializeSceneToEmitter(YAML::Emitter& out) + { + auto const& sceneGraph = SHSceneManager::GetCurrentSceneGraph(); + auto root = sceneGraph.GetRoot(); + + SHASSERT(root != nullptr, "Root is null. Failed to serialize scene to node."); + + auto const& children = root->GetChildren(); + out << YAML::BeginDoc; + for (auto child : children) + { + out << YAML::BeginSeq; + out << SerializeEntityToNode(child); + out << YAML::EndSeq; + } + out << YAML::EndDoc; + } + + std::string SerializeEntityToString() + { + return std::string(); + } + + void SerializeEntityToFile(std::filesystem::path const& path) + { + } + + YAML::Node SerializeEntityToNode(SHSceneNode* sceneNode) + { + YAML::Node node; + if(!sceneNode) + { + node = YAML::Null; + return node; + } + auto eid = sceneNode->GetEntityID(); + node["EID"] = eid; + node["isActive"] = sceneNode->IsActive(); + auto const& children = sceneNode->GetChildren(); + node["NumberOfChildren"] = children.size(); + + YAML::Node components; + + if(const auto transform = SHComponentManager::GetComponent_s(eid)) + { + components[rttr::type::get().get_name().data()] = SerializeComponentToNode(transform); + } + node["Components"] = components; + return node; + } + } +} diff --git a/SHADE_Engine/src/Serialization/SHSerialization.h b/SHADE_Engine/src/Serialization/SHSerialization.h new file mode 100644 index 00000000..aaccd065 --- /dev/null +++ b/SHADE_Engine/src/Serialization/SHSerialization.h @@ -0,0 +1,28 @@ +#pragma once + +#include "SH_API.h" +#include +#include + +#include + +namespace YAML +{ + class Emitter; + class Node; +} + +namespace SHADE +{ + class SHSceneNode; + namespace SHSerialization + { + static void SerializeSceneToFile(std::filesystem::path const& path); + static std::string SerializeSceneToString(); + static void SerializeSceneToEmitter(YAML::Emitter& out); + + static std::string SerializeEntityToString(); + static void SerializeEntityToFile(std::filesystem::path const& path); + static YAML::Node SerializeEntityToNode(SHSceneNode* sceneNode); + } +} \ No newline at end of file diff --git a/SHADE_Engine/src/Serialization/SHSerializationHelper.hpp b/SHADE_Engine/src/Serialization/SHSerializationHelper.hpp new file mode 100644 index 00000000..560c58dd --- /dev/null +++ b/SHADE_Engine/src/Serialization/SHSerializationHelper.hpp @@ -0,0 +1,97 @@ +#pragma once + +#include "ECS_Base/Components/SHComponent.h" +#include + +#include + +namespace SHADE +{ + namespace SHSerialization + { + template , bool> = true> + static std::string SerializeComponentToString(ComponentType* component) + { + return std::string(); + } + + template , bool> = true> + static void SerializeComponentToFile(ComponentType* component, std::filesystem::path const& path) + { + } + + static YAML::Node RTTRToNode(const rttr::variant& var) + { + YAML::Node node; + auto varType = var.get_type(); + if(varType.is_arithmetic()) + { + bool ok = false; + if (varType == rttr::type::get()) + node = var.to_bool(); + else if (varType == rttr::type::get()) + node = var.to_int8(&ok); + else if (varType == rttr::type::get()) + node = var.to_int16(&ok); + else if (varType == rttr::type::get()) + node = var.to_int32(&ok); + else if (varType == rttr::type::get()) + node = var.to_int64(&ok); + else if (varType == rttr::type::get()) + node = var.to_uint8(&ok); + else if (varType == rttr::type::get()) + node = var.to_uint16(&ok); + else if (varType == rttr::type::get()) + node = var.to_uint32(&ok); + else if (varType == rttr::type::get()) + node = var.to_uint64(&ok); + else if (varType == rttr::type::get()) + node = var.to_float(&ok); + else if (varType == rttr::type::get()) + node = var.to_double(&ok); + //else if (varType == rttr::type::get()) //same as uint8_t + // node = var.to_uint8(); + } + else if (varType.is_enumeration()) + { + bool ok = false; + auto result = var.to_string(&ok); + if (ok) + { + node = var.to_string(); + } + else + { + ok = false; + auto value = var.to_uint64(&ok); + if (ok) + node = value; + else + node = YAML::Null; + } + } + else + { + auto properties = var.get_type().get_properties(); + for(auto property : properties) + { + node[property.get_name().data()] = RTTRToNode(property.get_value(var)); + } + } + return node; + } + + template , bool> = true> + static YAML::Node SerializeComponentToNode(ComponentType* component) + { + YAML::Node node{}; + if(!component) + return node; + + auto componentType = rttr::type::get(); + node[componentType.get_name().data()] = RTTRToNode(*component); + + return node; + } + } +} \ No newline at end of file From 233e7a0e8fcb783311d52d5f77837a57e9650889 Mon Sep 17 00:00:00 2001 From: Sri Sham Haran Date: Mon, 26 Sep 2022 23:51:20 +0800 Subject: [PATCH 2/6] Serialization fix --- .../src/Serialization/SHSerialization.cpp | 113 +++++++++--------- .../src/Serialization/SHSerialization.h | 6 +- .../Serialization/SHSerializationHelper.hpp | 6 +- 3 files changed, 61 insertions(+), 64 deletions(-) diff --git a/SHADE_Engine/src/Serialization/SHSerialization.cpp b/SHADE_Engine/src/Serialization/SHSerialization.cpp index ee681a85..25358805 100644 --- a/SHADE_Engine/src/Serialization/SHSerialization.cpp +++ b/SHADE_Engine/src/Serialization/SHSerialization.cpp @@ -1,4 +1,5 @@ #include "SHpch.h" +#include "SHSerializationHelper.hpp" #include "SHSerialization.h" #include @@ -6,74 +7,70 @@ #include "Scene/SHSceneManager.h" #include "Tools/SHException.h" -#include "SHSerializationHelper.hpp" #include "Math/Transform/SHTransformComponent.h" namespace SHADE { - namespace SHSerialization + void SHSerialization::SerializeSceneToFile(std::filesystem::path const& path) { - void SerializeSceneToFile(std::filesystem::path const& path) - { + } + + std::string SHSerialization::SerializeSceneToString() + { + YAML::Emitter out; + SerializeSceneToEmitter(out); + return std::string(out.c_str()); + } + + void SHSerialization::SerializeSceneToEmitter(YAML::Emitter& out) + { + auto const& sceneGraph = SHSceneManager::GetCurrentSceneGraph(); + auto root = sceneGraph.GetRoot(); + + SHASSERT(root != nullptr, "Root is null. Failed to serialize scene to node."); + + auto const& children = root->GetChildren(); + out << YAML::BeginDoc; + for (auto child : children) + { + out << YAML::BeginSeq; + out << SerializeEntityToNode(child); + out << YAML::EndSeq; } + out << YAML::EndDoc; + } - std::string SerializeSceneToString() + std::string SHSerialization::SerializeEntityToString() + { + return std::string(); + } + + void SHSerialization::SerializeEntityToFile(std::filesystem::path const& path) + { + } + + YAML::Node SHSerialization::SerializeEntityToNode(SHSceneNode* sceneNode) + { + YAML::Node node; + if (!sceneNode) { - YAML::Emitter out; - SerializeSceneToEmitter(out); - return std::string(out.c_str()); - } - - void SerializeSceneToEmitter(YAML::Emitter& out) - { - auto const& sceneGraph = SHSceneManager::GetCurrentSceneGraph(); - auto root = sceneGraph.GetRoot(); - - SHASSERT(root != nullptr, "Root is null. Failed to serialize scene to node."); - - auto const& children = root->GetChildren(); - out << YAML::BeginDoc; - for (auto child : children) - { - out << YAML::BeginSeq; - out << SerializeEntityToNode(child); - out << YAML::EndSeq; - } - out << YAML::EndDoc; - } - - std::string SerializeEntityToString() - { - return std::string(); - } - - void SerializeEntityToFile(std::filesystem::path const& path) - { - } - - YAML::Node SerializeEntityToNode(SHSceneNode* sceneNode) - { - YAML::Node node; - if(!sceneNode) - { - node = YAML::Null; - return node; - } - auto eid = sceneNode->GetEntityID(); - node["EID"] = eid; - node["isActive"] = sceneNode->IsActive(); - auto const& children = sceneNode->GetChildren(); - node["NumberOfChildren"] = children.size(); - - YAML::Node components; - - if(const auto transform = SHComponentManager::GetComponent_s(eid)) - { - components[rttr::type::get().get_name().data()] = SerializeComponentToNode(transform); - } - node["Components"] = components; + node = YAML::Null; return node; } + auto eid = sceneNode->GetEntityID(); + node["EID"] = eid; + node["isActive"] = sceneNode->IsActive(); + auto const& children = sceneNode->GetChildren(); + node["NumberOfChildren"] = children.size(); + + YAML::Node components; + + if (const auto transform = SHComponentManager::GetComponent_s(eid)) + { + components[rttr::type::get().get_name().data()] = SHSerializationHelper::SerializeComponentToNode(transform); + } + node["Components"] = components; + return node; } } diff --git a/SHADE_Engine/src/Serialization/SHSerialization.h b/SHADE_Engine/src/Serialization/SHSerialization.h index aaccd065..0611e4d2 100644 --- a/SHADE_Engine/src/Serialization/SHSerialization.h +++ b/SHADE_Engine/src/Serialization/SHSerialization.h @@ -5,7 +5,7 @@ #include #include - +#include "SH_API.h" namespace YAML { class Emitter; @@ -15,7 +15,7 @@ namespace YAML namespace SHADE { class SHSceneNode; - namespace SHSerialization + struct SH_API SHSerialization { static void SerializeSceneToFile(std::filesystem::path const& path); static std::string SerializeSceneToString(); @@ -24,5 +24,5 @@ namespace SHADE static std::string SerializeEntityToString(); static void SerializeEntityToFile(std::filesystem::path const& path); static YAML::Node SerializeEntityToNode(SHSceneNode* sceneNode); - } + }; } \ No newline at end of file diff --git a/SHADE_Engine/src/Serialization/SHSerializationHelper.hpp b/SHADE_Engine/src/Serialization/SHSerializationHelper.hpp index 560c58dd..bfc29e7a 100644 --- a/SHADE_Engine/src/Serialization/SHSerializationHelper.hpp +++ b/SHADE_Engine/src/Serialization/SHSerializationHelper.hpp @@ -7,7 +7,7 @@ namespace SHADE { - namespace SHSerialization + struct SHSerializationHelper { template , bool> = true> static std::string SerializeComponentToString(ComponentType* component) @@ -89,9 +89,9 @@ namespace SHADE return node; auto componentType = rttr::type::get(); - node[componentType.get_name().data()] = RTTRToNode(*component); + node = RTTRToNode(*component); return node; } - } + }; } \ No newline at end of file From c4ed1991650638cb514b461c2ecc0d9ced294026 Mon Sep 17 00:00:00 2001 From: Sri Sham Haran Date: Tue, 27 Sep 2022 07:03:31 +0800 Subject: [PATCH 3/6] Serialize Vec 2/3/4 --- .../Serialization/SHSerializationHelper.hpp | 29 +++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/SHADE_Engine/src/Serialization/SHSerializationHelper.hpp b/SHADE_Engine/src/Serialization/SHSerializationHelper.hpp index bfc29e7a..e702dd24 100644 --- a/SHADE_Engine/src/Serialization/SHSerializationHelper.hpp +++ b/SHADE_Engine/src/Serialization/SHSerializationHelper.hpp @@ -5,6 +5,10 @@ #include +#include "Math/Vector/SHVec2.h" +#include "Math/Vector/SHVec3.h" +#include "Math/Vector/SHVec4.h" + namespace SHADE { struct SHSerializationHelper @@ -24,7 +28,28 @@ namespace SHADE { YAML::Node node; auto varType = var.get_type(); - if(varType.is_arithmetic()) + if(varType == rttr::type::get()) + { + node.SetStyle(YAML::EmitterStyle::Flow); + node["X"] = var.convert().x; + node["Y"] = var.convert().y; + node["Z"] = var.convert().z; + node["W"] = var.convert().w; + } + else if(varType == rttr::type::get()) + { + node.SetStyle(YAML::EmitterStyle::Flow); + node["X"] = var.convert().x; + node["Y"] = var.convert().y; + node["Z"] = var.convert().z; + } + else if(varType == rttr::type::get()) + { + node.SetStyle(YAML::EmitterStyle::Flow); + node["X"] = var.convert().x; + node["Y"] = var.convert().y; + } + else if(varType.is_arithmetic()) { bool ok = false; if (varType == rttr::type::get()) @@ -94,4 +119,4 @@ namespace SHADE return node; } }; -} \ No newline at end of file +} From cebb1a2cf85aa2c779b0ceb4a9372a23cde095f6 Mon Sep 17 00:00:00 2001 From: Sri Sham Haran Date: Tue, 27 Sep 2022 21:06:25 +0800 Subject: [PATCH 4/6] Deserialization WIP --- .../src/Serialization/SHSerialization.cpp | 92 ++++++++++++++++--- .../src/Serialization/SHSerialization.h | 17 +++- 2 files changed, 94 insertions(+), 15 deletions(-) diff --git a/SHADE_Engine/src/Serialization/SHSerialization.cpp b/SHADE_Engine/src/Serialization/SHSerialization.cpp index 25358805..926e4ff5 100644 --- a/SHADE_Engine/src/Serialization/SHSerialization.cpp +++ b/SHADE_Engine/src/Serialization/SHSerialization.cpp @@ -4,6 +4,7 @@ #include +#include "ECS_Base/Managers/SHEntityManager.h" #include "Scene/SHSceneManager.h" #include "Tools/SHException.h" @@ -29,18 +30,60 @@ namespace SHADE auto root = sceneGraph.GetRoot(); SHASSERT(root != nullptr, "Root is null. Failed to serialize scene to node."); - + auto const& children = root->GetChildren(); out << YAML::BeginDoc; - for (auto child : children) - { - out << YAML::BeginSeq; - out << SerializeEntityToNode(child); - out << YAML::EndSeq; - } + + auto pred = [&out](SHSceneNode* node){out << SerializeEntityToNode(node);}; + sceneGraph.Traverse(pred); + //out << SerializeEntityToNode(child); + out << YAML::EndDoc; } + static void DeserializeEntity(YAML::iterator& it, YAML::Node const& node, std::vector& createdEntities, EntityID parentEID = MAX_EID) + { + if(!node[EIDNode]) + return; + EntityID eid = node[EIDNode].as(); + std::string name = "Default"; + if(node[EntityNameNode]) + name = node[EntityNameNode].as(); + //Compile component IDs + const auto componentIDList = SHSerialization::GetComponentIDList(node[ComponentsNode]); + eid = SHEntityManager::CreateEntity(componentIDList, eid, name, parentEID); + createdEntities.push_back(eid); + if(node[NumberOfChildrenNode]) + { int numOfChildren = node[NumberOfChildrenNode].as(); + for(int i = 0; i < numOfChildren; ++i) + { + DeserializeEntity(it, *it, createdEntities, eid); + ++it; + } + } + } + + void SHSerialization::DeserializeSceneFromFile(std::string const& fileData) + { + YAML::Node entities = YAML::Load(fileData.c_str()); + std::vector createdEntities{}; + + //Create Entities + for(auto it = entities.begin(); it != entities.end(); ++it) + { + DeserializeEntity(it, (*it), createdEntities); + } + + //Initialize Entity + for(auto it = entities.begin(); it != entities.end(); ++it) + { + //For each node, Deserialize component + //Recurse through properties + } + } + + + std::string SHSerialization::SerializeEntityToString() { return std::string(); @@ -53,16 +96,19 @@ namespace SHADE YAML::Node SHSerialization::SerializeEntityToNode(SHSceneNode* sceneNode) { YAML::Node node; - if (!sceneNode) + auto eid = sceneNode->GetEntityID(); + auto entity = SHEntityManager::GetEntityByID(eid); + if (!sceneNode || !entity) { node = YAML::Null; return node; } - auto eid = sceneNode->GetEntityID(); - node["EID"] = eid; - node["isActive"] = sceneNode->IsActive(); + + node[EIDNode] = eid; + node[EntityNameNode] = entity->name; + node[IsActiveNode] = sceneNode->IsActive(); auto const& children = sceneNode->GetChildren(); - node["NumberOfChildren"] = children.size(); + node[NumberOfChildrenNode] = children.size(); YAML::Node components; @@ -70,7 +116,27 @@ namespace SHADE { components[rttr::type::get().get_name().data()] = SHSerializationHelper::SerializeComponentToNode(transform); } - node["Components"] = components; + node[ComponentsNode] = components; return node; } + + template, bool> = true> + std::optional GetComponentID(YAML::Node const & componentNode) + { + if(componentNode[rttr::type::get().get_name().data()]) + return {SHFamilyID::GetID()}; + else + return std::nullopt; + } + + std::vector SHSerialization::GetComponentIDList(YAML::Node const& componentsNode) + { + std::vector componentIDList; + + auto id = GetComponentID(componentsNode); + if(id.has_value()) + componentIDList.push_back(id.value()); + + return componentIDList; + } } diff --git a/SHADE_Engine/src/Serialization/SHSerialization.h b/SHADE_Engine/src/Serialization/SHSerialization.h index 0611e4d2..022a01c4 100644 --- a/SHADE_Engine/src/Serialization/SHSerialization.h +++ b/SHADE_Engine/src/Serialization/SHSerialization.h @@ -5,7 +5,7 @@ #include #include -#include "SH_API.h" + namespace YAML { class Emitter; @@ -15,14 +15,27 @@ namespace YAML namespace SHADE { class SHSceneNode; + + constexpr const char* ComponentsNode = "Components"; + constexpr const char* EntityNameNode = "Name"; + constexpr const char* EIDNode = "EID"; + constexpr const char* IsActiveNode = "IsActive"; + constexpr const char* NumberOfChildrenNode = "NumberOfChildren"; + struct SH_API SHSerialization { + //TODO: change paths to resource ID static void SerializeSceneToFile(std::filesystem::path const& path); static std::string SerializeSceneToString(); static void SerializeSceneToEmitter(YAML::Emitter& out); - + static void DeserializeSceneFromFile(std::string const& fileData); + + static std::string SerializeEntityToString(); static void SerializeEntityToFile(std::filesystem::path const& path); static YAML::Node SerializeEntityToNode(SHSceneNode* sceneNode); + + static std::vector GetComponentIDList(YAML::Node const& componentsNode); + private: }; } \ No newline at end of file From 01f648ceb626ba8b6bec50c87198e380ac277b24 Mon Sep 17 00:00:00 2001 From: Sri Sham Haran Date: Sat, 1 Oct 2022 23:43:00 +0800 Subject: [PATCH 5/6] Serialize/Deserialize [WIP] --- .../src/Serialization/SHSerialization.cpp | 100 +++++++++---- .../src/Serialization/SHSerialization.h | 3 +- .../Serialization/SHSerializationHelper.hpp | 136 ++++++++++++++---- 3 files changed, 185 insertions(+), 54 deletions(-) diff --git a/SHADE_Engine/src/Serialization/SHSerialization.cpp b/SHADE_Engine/src/Serialization/SHSerialization.cpp index 926e4ff5..ee189f2c 100644 --- a/SHADE_Engine/src/Serialization/SHSerialization.cpp +++ b/SHADE_Engine/src/Serialization/SHSerialization.cpp @@ -7,21 +7,31 @@ #include "ECS_Base/Managers/SHEntityManager.h" #include "Scene/SHSceneManager.h" #include "Tools/SHException.h" +#include "Assets/SHAssetManager.h" +#include +#include "Graphics/MiddleEnd/Interface/SHRenderable.h" #include "Math/Transform/SHTransformComponent.h" namespace SHADE { void SHSerialization::SerializeSceneToFile(std::filesystem::path const& path) { - + YAML::Emitter out; + SerializeSceneToEmitter(out); + std::ofstream file(path.c_str()); + if (file.good()) + { + file << out.c_str(); + file.close(); + } } std::string SHSerialization::SerializeSceneToString() { YAML::Emitter out; SerializeSceneToEmitter(out); - return std::string(out.c_str()); + return std::basic_string(out.c_str()); } void SHSerialization::SerializeSceneToEmitter(YAML::Emitter& out) @@ -30,55 +40,82 @@ namespace SHADE auto root = sceneGraph.GetRoot(); SHASSERT(root != nullptr, "Root is null. Failed to serialize scene to node."); - - auto const& children = root->GetChildren(); - out << YAML::BeginDoc; - auto pred = [&out](SHSceneNode* node){out << SerializeEntityToNode(node);}; + auto const& children = root->GetChildren(); + out << YAML::BeginSeq; + + auto pred = [&out](SHSceneNode* node) {out << SerializeEntityToNode(node); }; sceneGraph.Traverse(pred); - //out << SerializeEntityToNode(child); - - out << YAML::EndDoc; + //out << SerializeEntityToNode(child); + + out << YAML::EndSeq; } static void DeserializeEntity(YAML::iterator& it, YAML::Node const& node, std::vector& createdEntities, EntityID parentEID = MAX_EID) { - if(!node[EIDNode]) + if (!node[EIDNode]) return; EntityID eid = node[EIDNode].as(); std::string name = "Default"; - if(node[EntityNameNode]) + if (node[EntityNameNode]) name = node[EntityNameNode].as(); //Compile component IDs const auto componentIDList = SHSerialization::GetComponentIDList(node[ComponentsNode]); eid = SHEntityManager::CreateEntity(componentIDList, eid, name, parentEID); createdEntities.push_back(eid); - if(node[NumberOfChildrenNode]) - { int numOfChildren = node[NumberOfChildrenNode].as(); - for(int i = 0; i < numOfChildren; ++i) + if (node[NumberOfChildrenNode]) + { + if(const int numOfChildren = node[NumberOfChildrenNode].as(); numOfChildren > 0) { - DeserializeEntity(it, *it, createdEntities, eid); ++it; + for (int i = 0; i < numOfChildren; ++i) + { + DeserializeEntity(it, (*it), createdEntities, eid); + if((i + 1) < numOfChildren) + ++it; + } } } } - void SHSerialization::DeserializeSceneFromFile(std::string const& fileData) + void SHSerialization::DeserializeSceneFromFile(std::filesystem::path const& path) { - YAML::Node entities = YAML::Load(fileData.c_str()); + //TODO:Shift to using XQ's FileIO + std::ifstream iFile; + iFile.exceptions(std::ifstream::failbit | std::ifstream::badbit); + std::string fileContent = ""; + + try + { + // Open file + // Read file's buffer contents into streams + iFile.open(path); + std::stringstream fileStream; + fileStream << iFile.rdbuf(); + + fileContent = fileStream.str(); + + // Close file handler + iFile.close(); + } + catch (std::ifstream::failure e) + { + SHLOG_ERROR("Could not read file"); + } + YAML::Node entities = YAML::Load(fileContent); std::vector createdEntities{}; //Create Entities - for(auto it = entities.begin(); it != entities.end(); ++it) + for (auto it = entities.begin(); it != entities.end(); ++it) { DeserializeEntity(it, (*it), createdEntities); } //Initialize Entity - for(auto it = entities.begin(); it != entities.end(); ++it) + auto entityVecIt = createdEntities.begin(); + for (auto it = entities.begin(); it != entities.end(); ++it) { - //For each node, Deserialize component - //Recurse through properties + InitializeEntity(*it, *entityVecIt++); } } @@ -103,7 +140,7 @@ namespace SHADE node = YAML::Null; return node; } - + node.SetStyle(YAML::EmitterStyle::Block); node[EIDNode] = eid; node[EntityNameNode] = entity->name; node[IsActiveNode] = sceneNode->IsActive(); @@ -121,10 +158,10 @@ namespace SHADE } template, bool> = true> - std::optional GetComponentID(YAML::Node const & componentNode) + std::optional GetComponentID(YAML::Node const& componentNode) { - if(componentNode[rttr::type::get().get_name().data()]) - return {SHFamilyID::GetID()}; + if (componentNode[rttr::type::get().get_name().data()]) + return { SHFamilyID::GetID() }; else return std::nullopt; } @@ -134,9 +171,20 @@ namespace SHADE std::vector componentIDList; auto id = GetComponentID(componentsNode); - if(id.has_value()) + if (id.has_value()) + componentIDList.push_back(id.value()); + id = GetComponentID(componentsNode); + if (id.has_value()) componentIDList.push_back(id.value()); return componentIDList; } + + void SHSerialization::InitializeEntity(YAML::Node const& entityNode, EntityID const& eid) + { + auto componentsNode = entityNode[ComponentsNode]; + if(!componentsNode) + return; + SHSerializationHelper::InitializeComponentFromNode(componentsNode, eid); + } } diff --git a/SHADE_Engine/src/Serialization/SHSerialization.h b/SHADE_Engine/src/Serialization/SHSerialization.h index 022a01c4..8a57f036 100644 --- a/SHADE_Engine/src/Serialization/SHSerialization.h +++ b/SHADE_Engine/src/Serialization/SHSerialization.h @@ -28,7 +28,7 @@ namespace SHADE static void SerializeSceneToFile(std::filesystem::path const& path); static std::string SerializeSceneToString(); static void SerializeSceneToEmitter(YAML::Emitter& out); - static void DeserializeSceneFromFile(std::string const& fileData); + static void DeserializeSceneFromFile(std::filesystem::path const& path); static std::string SerializeEntityToString(); @@ -37,5 +37,6 @@ namespace SHADE static std::vector GetComponentIDList(YAML::Node const& componentsNode); private: + static void InitializeEntity(YAML::Node const& entityNode, EntityID const& eid); }; } \ No newline at end of file diff --git a/SHADE_Engine/src/Serialization/SHSerializationHelper.hpp b/SHADE_Engine/src/Serialization/SHSerializationHelper.hpp index e702dd24..da98c885 100644 --- a/SHADE_Engine/src/Serialization/SHSerializationHelper.hpp +++ b/SHADE_Engine/src/Serialization/SHSerializationHelper.hpp @@ -5,6 +5,7 @@ #include +#include "ECS_Base/Managers/SHComponentManager.h" #include "Math/Vector/SHVec2.h" #include "Math/Vector/SHVec3.h" #include "Math/Vector/SHVec4.h" @@ -13,13 +14,13 @@ namespace SHADE { struct SHSerializationHelper { - template , bool> = true> + template , bool> = true> static std::string SerializeComponentToString(ComponentType* component) { return std::string(); } - template , bool> = true> + template , bool> = true> static void SerializeComponentToFile(ComponentType* component, std::filesystem::path const& path) { } @@ -28,7 +29,7 @@ namespace SHADE { YAML::Node node; auto varType = var.get_type(); - if(varType == rttr::type::get()) + if (varType == rttr::type::get()) { node.SetStyle(YAML::EmitterStyle::Flow); node["X"] = var.convert().x; @@ -36,44 +37,44 @@ namespace SHADE node["Z"] = var.convert().z; node["W"] = var.convert().w; } - else if(varType == rttr::type::get()) + else if (varType == rttr::type::get()) { node.SetStyle(YAML::EmitterStyle::Flow); node["X"] = var.convert().x; node["Y"] = var.convert().y; node["Z"] = var.convert().z; } - else if(varType == rttr::type::get()) + else if (varType == rttr::type::get()) { node.SetStyle(YAML::EmitterStyle::Flow); node["X"] = var.convert().x; node["Y"] = var.convert().y; } - else if(varType.is_arithmetic()) + else if (varType.is_arithmetic()) { bool ok = false; if (varType == rttr::type::get()) - node = var.to_bool(); + node = var.to_bool(); else if (varType == rttr::type::get()) - node = var.to_int8(&ok); + node = var.to_int8(&ok); else if (varType == rttr::type::get()) - node = var.to_int16(&ok); + node = var.to_int16(&ok); else if (varType == rttr::type::get()) - node = var.to_int32(&ok); + node = var.to_int32(&ok); else if (varType == rttr::type::get()) - node = var.to_int64(&ok); + node = var.to_int64(&ok); else if (varType == rttr::type::get()) - node = var.to_uint8(&ok); + node = var.to_uint8(&ok); else if (varType == rttr::type::get()) - node = var.to_uint16(&ok); + node = var.to_uint16(&ok); else if (varType == rttr::type::get()) - node = var.to_uint32(&ok); + node = var.to_uint32(&ok); else if (varType == rttr::type::get()) - node = var.to_uint64(&ok); + node = var.to_uint64(&ok); else if (varType == rttr::type::get()) - node = var.to_float(&ok); + node = var.to_float(&ok); else if (varType == rttr::type::get()) - node = var.to_double(&ok); + node = var.to_double(&ok); //else if (varType == rttr::type::get()) //same as uint8_t // node = var.to_uint8(); } @@ -87,18 +88,18 @@ namespace SHADE } else { - ok = false; - auto value = var.to_uint64(&ok); - if (ok) - node = value; - else - node = YAML::Null; + ok = false; + auto value = var.to_uint64(&ok); + if (ok) + node = value; + else + node = YAML::Null; } } else { auto properties = var.get_type().get_properties(); - for(auto property : properties) + for (auto property : properties) { node[property.get_name().data()] = RTTRToNode(property.get_value(var)); } @@ -106,17 +107,98 @@ namespace SHADE return node; } - template , bool> = true> + template , bool> = true> static YAML::Node SerializeComponentToNode(ComponentType* component) { YAML::Node node{}; - if(!component) - return node; + if (!component) + return node; auto componentType = rttr::type::get(); node = RTTRToNode(*component); return node; } + + template , bool> = true> + static void InitializeProperty(ComponentType* component, rttr::property const& prop, YAML::Node const& propertyNode) + { + auto propType = prop.get_type(); + if (propType == rttr::type::get()) + { + SHVec4 vec{ propertyNode["X"].as(), propertyNode["Y"].as(), propertyNode["Z"].as(), propertyNode["W"].as() }; + prop.set_value(component, vec); + } + else if (propType == rttr::type::get()) + { + SHVec3 vec{ propertyNode["X"].as(), propertyNode["Y"].as(), propertyNode["Z"].as() }; + prop.set_value(component, vec); + } + else if (propType == rttr::type::get()) + { + SHVec2 vec{ propertyNode["X"].as(), propertyNode["Y"].as() }; + prop.set_value(component, vec); + } + else if (propType.is_arithmetic()) + { + bool ok = false; + if (propType == rttr::type::get()) + prop.set_value(component, propertyNode.as()); + else if (propType == rttr::type::get()) + prop.set_value(component, propertyNode.as()); + else if (propType == rttr::type::get()) + prop.set_value(component, propertyNode.as()); + else if (propType == rttr::type::get()) + prop.set_value(component, propertyNode.as()); + else if (propType == rttr::type::get()) + prop.set_value(component, propertyNode.as()); + else if (propType == rttr::type::get()) + prop.set_value(component, propertyNode.as()); + else if (propType == rttr::type::get()) + prop.set_value(component, propertyNode.as()); + else if (propType == rttr::type::get()) + prop.set_value(component, propertyNode.as()); + else if (propType == rttr::type::get()) + prop.set_value(component, propertyNode.as()); + else if (propType == rttr::type::get()) + prop.set_value(component, propertyNode.as()); + else if (propType == rttr::type::get()) + prop.set_value(component, propertyNode.as()); + } + else if (propType.is_enumeration()) + { + auto enumAlign = prop.get_enumeration(); + prop.set_value(component, enumAlign.name_to_value(propertyNode.as())); + } + else + { + auto properties = propType.get_properties(); + for (auto property : properties) + { + InitializeProperty(component, property, propertyNode[property.get_name().data()]); + } + } + } + + template , bool> = true> + static void InitializeComponentFromNode(YAML::Node const& componentsNode, EntityID const& eid) + { + auto component = SHComponentManager::GetComponent_s(eid); + if (componentsNode.IsNull() && !component) + return; + auto rttrType = rttr::type::get(); + auto componentNode = componentsNode[rttrType.get_name().data()]; + if (componentsNode.IsNull()) + return; + auto properties = rttrType.get_properties(); + for (auto const& prop : properties) + { + if (componentNode[prop.get_name().data()]) + { + InitializeProperty(component, prop, componentNode[prop.get_name().data()]); + } + } + } + }; } From 96f5b29418eba41c360e2386350b64946ab036a2 Mon Sep 17 00:00:00 2001 From: Sri Sham Haran Date: Wed, 19 Oct 2022 01:03:32 +0800 Subject: [PATCH 6/6] Serialization/Deserialization --- .../HierarchyPanel/SHHierarchyPanel.cpp | 6 +++ .../EditorWindow/MenuBar/SHEditorMenuBar.cpp | 11 ++++- .../src/Serialization/SHSerialization.cpp | 42 ++++++++++++++++--- .../src/Serialization/SHSerialization.h | 3 +- 4 files changed, 54 insertions(+), 8 deletions(-) diff --git a/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.cpp b/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.cpp index 42c9da66..30af228b 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.cpp +++ b/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.cpp @@ -21,6 +21,8 @@ //#==============================================================# #include +#include "Serialization/SHSerialization.h" + namespace SHADE { @@ -171,6 +173,10 @@ namespace SHADE editor->selectedEntities.clear(); editor->selectedEntities.push_back(eid); } + if(ImGui::Selectable("Copy")) + { + SHLOG_INFO(SHSerialization::SerializeEntitiesToString(editor->selectedEntities)) + } if(ImGui::Selectable(std::format("{} Delete", ICON_MD_DELETE).data())) { SHEntityManager::DestroyEntity(eid); diff --git a/SHADE_Engine/src/Editor/EditorWindow/MenuBar/SHEditorMenuBar.cpp b/SHADE_Engine/src/Editor/EditorWindow/MenuBar/SHEditorMenuBar.cpp index 3cb6561d..c33f4fb6 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/MenuBar/SHEditorMenuBar.cpp +++ b/SHADE_Engine/src/Editor/EditorWindow/MenuBar/SHEditorMenuBar.cpp @@ -17,6 +17,8 @@ #include #include +#include "Serialization/SHSerialization.h" + namespace SHADE { constexpr ImGuiWindowFlags editorMenuBarFlags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | @@ -73,7 +75,14 @@ namespace SHADE { if (ImGui::BeginMenu("File")) { - + if(ImGui::Selectable("Save")) + { + SHSerialization::SerializeSceneToFile("../../Assets/Scenes/Test.SHADE"); + } + if(ImGui::Selectable("Load")) + { + SHSerialization::DeserializeSceneFromFile("../../Assets/Scenes/Test.SHADE"); + } ImGui::EndMenu(); } if(ImGui::BeginMenu("Edit")) diff --git a/SHADE_Engine/src/Serialization/SHSerialization.cpp b/SHADE_Engine/src/Serialization/SHSerialization.cpp index ee189f2c..e259fbbc 100644 --- a/SHADE_Engine/src/Serialization/SHSerialization.cpp +++ b/SHADE_Engine/src/Serialization/SHSerialization.cpp @@ -12,6 +12,7 @@ #include "Graphics/MiddleEnd/Interface/SHRenderable.h" #include "Math/Transform/SHTransformComponent.h" +#include "Physics/Components/SHRigidBodyComponent.h" namespace SHADE { @@ -119,11 +120,27 @@ namespace SHADE } } - - - std::string SHSerialization::SerializeEntityToString() + void SHSerialization::EmitEntity(SHSceneNode* entityNode, YAML::Emitter& out) { - return std::string(); + out << SerializeEntityToNode(entityNode); + auto const& children = entityNode->GetChildren(); + for(auto const& child : children) + { + EmitEntity(child, out); + } + } + + std::string SHSerialization::SerializeEntitiesToString(std::vector const& entities) + { + YAML::Emitter out; + YAML::Node node; + auto const& sceneGraph = SHSceneManager::GetCurrentSceneGraph(); + for (auto const& eid : entities) + { + auto entityNode = sceneGraph.GetNode(eid); + EmitEntity(entityNode, out); + } + return std::basic_string(out.c_str()); } void SHSerialization::SerializeEntityToFile(std::filesystem::path const& path) @@ -153,6 +170,14 @@ namespace SHADE { components[rttr::type::get().get_name().data()] = SHSerializationHelper::SerializeComponentToNode(transform); } + if (const auto renderable = SHComponentManager::GetComponent_s(eid)) + { + components[rttr::type::get().get_name().data()] = SHSerializationHelper::SerializeComponentToNode(renderable); + } + if (const auto rigidbody = SHComponentManager::GetComponent_s(eid)) + { + components[rttr::type::get().get_name().data()] = SHSerializationHelper::SerializeComponentToNode(rigidbody); + } node[ComponentsNode] = components; return node; } @@ -173,17 +198,22 @@ namespace SHADE auto id = GetComponentID(componentsNode); if (id.has_value()) componentIDList.push_back(id.value()); + id = GetComponentID(componentsNode); if (id.has_value()) componentIDList.push_back(id.value()); + id = GetComponentID(componentsNode); + if (id.has_value()) + componentIDList.push_back(id.value()); + return componentIDList; } void SHSerialization::InitializeEntity(YAML::Node const& entityNode, EntityID const& eid) { - auto componentsNode = entityNode[ComponentsNode]; - if(!componentsNode) + auto const componentsNode = entityNode[ComponentsNode]; + if (!componentsNode) return; SHSerializationHelper::InitializeComponentFromNode(componentsNode, eid); } diff --git a/SHADE_Engine/src/Serialization/SHSerialization.h b/SHADE_Engine/src/Serialization/SHSerialization.h index 8a57f036..d247de7a 100644 --- a/SHADE_Engine/src/Serialization/SHSerialization.h +++ b/SHADE_Engine/src/Serialization/SHSerialization.h @@ -31,7 +31,8 @@ namespace SHADE static void DeserializeSceneFromFile(std::filesystem::path const& path); - static std::string SerializeEntityToString(); + static void EmitEntity(SHSceneNode* entityNode, YAML::Emitter& out); + static std::string SerializeEntitiesToString(std::vector const& entities); static void SerializeEntityToFile(std::filesystem::path const& path); static YAML::Node SerializeEntityToNode(SHSceneNode* sceneNode);