From 7247faee739acdb8f1d2832ad63f2656b83bfd2e Mon Sep 17 00:00:00 2001 From: Sri Sham Haran Date: Mon, 26 Sep 2022 21:08:59 +0800 Subject: [PATCH 01/12] 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 02/12] 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 03/12] 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 04/12] 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 05/12] 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 a221cfc1cde720a123ae2c959ff2e1bcc11c131e Mon Sep 17 00:00:00 2001 From: Kah Wei Date: Tue, 18 Oct 2022 17:25:45 +0800 Subject: [PATCH 06/12] Modified SHScriptEngine's serialization functions to take in EntityID instead of SHEntity --- SHADE_Engine/src/Scripting/SHScriptEngine.cpp | 8 ++++---- SHADE_Engine/src/Scripting/SHScriptEngine.h | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/SHADE_Engine/src/Scripting/SHScriptEngine.cpp b/SHADE_Engine/src/Scripting/SHScriptEngine.cpp index 65f445a6..d7a090a4 100644 --- a/SHADE_Engine/src/Scripting/SHScriptEngine.cpp +++ b/SHADE_Engine/src/Scripting/SHScriptEngine.cpp @@ -115,7 +115,7 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ /* Script Serialisation Functions */ /*---------------------------------------------------------------------------------*/ - std::string SHScriptEngine::SerialiseScripts(const SHEntity& entity) const + std::string SHScriptEngine::SerialiseScripts(EntityID entity) const { // Create buffer needed to store serialised script data constexpr int BUFFER_SIZE = 10240; @@ -124,7 +124,7 @@ namespace SHADE // Attempt to serialise the script std::string result; - if (csScriptsSerialise(entity.GetEID(), buffer.get(), BUFFER_SIZE)) + if (csScriptsSerialise(entity, buffer.get(), BUFFER_SIZE)) { result = std::string(buffer.get()); } @@ -140,9 +140,9 @@ namespace SHADE /*-----------------------------------------------------------------------------------*/ /* Script Serialisation Functions */ /*-----------------------------------------------------------------------------------*/ - void SHScriptEngine::DeserialiseScript(const SHEntity& entity, const std::string& yaml) const + void SHScriptEngine::DeserialiseScript(EntityID entity, const std::string& yaml) const { - csScriptDeserialise(entity.GetEID(), yaml.c_str()); + csScriptDeserialise(entity, yaml.c_str()); } /*-----------------------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Scripting/SHScriptEngine.h b/SHADE_Engine/src/Scripting/SHScriptEngine.h index 239d6b90..60723425 100644 --- a/SHADE_Engine/src/Scripting/SHScriptEngine.h +++ b/SHADE_Engine/src/Scripting/SHScriptEngine.h @@ -148,7 +148,7 @@ namespace SHADE /// /// String that represents the set of scripts attached to the specified Entity. /// - std::string SerialiseScripts(const SHEntity& entity) const; + std::string SerialiseScripts(EntityID entity) const; /// /// Loads the specified JSON string and creates a Script for the specified Entity /// based on the specified JSON string. @@ -157,7 +157,7 @@ namespace SHADE /// /// The YAML string that represents the Script to load into the Entity. /// - void DeserialiseScript(const SHEntity& entity, const std::string& yaml) const; + void DeserialiseScript(EntityID entity, const std::string& yaml) const; /*-----------------------------------------------------------------------------*/ /* Script Editor Functions */ From 82637b620d953b01adb8201168031b13fcaeefd4 Mon Sep 17 00:00:00 2001 From: Sri Sham Haran Date: Tue, 18 Oct 2022 19:36:49 +0800 Subject: [PATCH 07/12] Delete UserLayout.ini --- Assets/Editor/Layouts/UserLayout.ini | 48 ---------------------------- 1 file changed, 48 deletions(-) delete mode 100644 Assets/Editor/Layouts/UserLayout.ini diff --git a/Assets/Editor/Layouts/UserLayout.ini b/Assets/Editor/Layouts/UserLayout.ini deleted file mode 100644 index e55aeb81..00000000 --- a/Assets/Editor/Layouts/UserLayout.ini +++ /dev/null @@ -1,48 +0,0 @@ -[Window][MainStatusBar] -Pos=0,1060 -Size=1920,20 -Collapsed=0 - -[Window][SHEditorMenuBar] -Pos=0,48 -Size=1920,1012 -Collapsed=0 - -[Window][Hierarchy Panel] -Pos=0,142 -Size=321,918 -Collapsed=0 -DockId=0x00000004,0 - -[Window][Debug##Default] -Pos=60,60 -Size=400,400 -Collapsed=0 - -[Window][Inspector] -Pos=1649,48 -Size=271,1012 -Collapsed=0 -DockId=0x00000006,0 - -[Window][Profiler] -Pos=0,48 -Size=321,92 -Collapsed=0 -DockId=0x00000003,0 - -[Window][Viewport] -Pos=323,48 -Size=1324,1012 -Collapsed=0 -DockId=0x00000002,0 - -[Docking][Data] -DockSpace ID=0xC5C9B8AB Window=0xBE4044E9 Pos=617,298 Size=1920,1012 Split=X - DockNode ID=0x00000005 Parent=0xC5C9B8AB SizeRef=1992,1036 Split=X - DockNode ID=0x00000001 Parent=0x00000005 SizeRef=321,1036 Split=Y Selected=0x1E6EB881 - DockNode ID=0x00000003 Parent=0x00000001 SizeRef=225,94 Selected=0x1E6EB881 - DockNode ID=0x00000004 Parent=0x00000001 SizeRef=225,940 Selected=0xE096E5AE - DockNode ID=0x00000002 Parent=0x00000005 SizeRef=1324,1036 CentralNode=1 Selected=0x13926F0B - DockNode ID=0x00000006 Parent=0xC5C9B8AB SizeRef=271,1036 Selected=0xE7039252 - From 87cf3ffa6176b9cacb97259fa52b9fd0ce361202 Mon Sep 17 00:00:00 2001 From: Kah Wei Date: Tue, 18 Oct 2022 20:09:50 +0800 Subject: [PATCH 08/12] Added script inspector tooltips support via Tooltip attribute --- SHADE_Engine/src/Editor/SHEditorUI.cpp | 59 +++++++++++++++---- SHADE_Engine/src/Editor/SHEditorUI.h | 45 ++++++++++---- SHADE_Engine/src/Editor/SHEditorUI.hpp | 7 ++- SHADE_Engine/src/Editor/SHEditorWidgets.hpp | 4 +- SHADE_Managed/src/Editor/Editor.cxx | 56 ++++++++++++++---- SHADE_Managed/src/Editor/Editor.hxx | 10 +++- .../TooltipAttribute.cxx} | 29 +++++---- SHADE_Managed/src/Editor/TooltipAttribute.hxx | 53 +++++++++++++++++ .../Serialisation/SerializeFieldAttribute.hxx | 11 +--- TempScriptsFolder/RaccoonShowcase.cs | 8 ++- TempScriptsFolder/RaccoonSpin.cs | 4 +- 11 files changed, 221 insertions(+), 65 deletions(-) rename SHADE_Managed/src/{Serialisation/SerialiseFieldAttribute.cxx => Editor/TooltipAttribute.cxx} (54%) create mode 100644 SHADE_Managed/src/Editor/TooltipAttribute.hxx diff --git a/SHADE_Engine/src/Editor/SHEditorUI.cpp b/SHADE_Engine/src/Editor/SHEditorUI.cpp index 65b65827..76f7bac6 100644 --- a/SHADE_Engine/src/Editor/SHEditorUI.cpp +++ b/SHADE_Engine/src/Editor/SHEditorUI.cpp @@ -67,6 +67,11 @@ namespace SHADE ImGui::Separator(); } + bool SHEditorUI::IsItemHovered() + { + return ImGui::IsItemHovered(); + } + bool SHEditorUI::BeginMenu(const std::string& label) { return ImGui::BeginMenu(label.data()); @@ -82,6 +87,16 @@ namespace SHADE ImGui::EndMenu(); } + void SHEditorUI::BeginTooltip() + { + ImGui::BeginTooltip(); + } + + void SHEditorUI::EndTooltip() + { + ImGui::EndTooltip(); + } + /*-----------------------------------------------------------------------------------*/ /* ImGui Wrapper Functions - Pop Ups */ /*-----------------------------------------------------------------------------------*/ @@ -135,24 +150,30 @@ namespace SHADE return ImGui::Selectable(std::format("{} {}", icon, label).data()); } - bool SHEditorUI::InputCheckbox(const std::string& label, bool& value) + bool SHEditorUI::InputCheckbox(const std::string& label, bool& value, bool* isHovered) { ImGui::Text(label.c_str()); + if (isHovered) + *isHovered = ImGui::IsItemHovered(); ImGui::SameLine(); return ImGui::Checkbox("#", &value); } - bool SHEditorUI::InputInt(const std::string& label, int& value) + bool SHEditorUI::InputInt(const std::string& label, int& value, bool* isHovered) { ImGui::Text(label.c_str()); + if (isHovered) + *isHovered = ImGui::IsItemHovered(); ImGui::SameLine(); return ImGui::InputInt("#", &value, 1, 10, ImGuiInputTextFlags_EnterReturnsTrue); } - bool SHEditorUI::InputUnsignedInt(const std::string& label, unsigned int& value) + bool SHEditorUI::InputUnsignedInt(const std::string& label, unsigned int& value, bool* isHovered) { int signedVal = static_cast(value); ImGui::Text(label.c_str()); + if (isHovered) + *isHovered = ImGui::IsItemHovered(); ImGui::SameLine(); const bool CHANGED = InputInt("#", signedVal); if (CHANGED) @@ -162,35 +183,43 @@ namespace SHADE } return CHANGED; } - bool SHEditorUI::InputFloat(const std::string& label, float& value) + bool SHEditorUI::InputFloat(const std::string& label, float& value, bool* isHovered) { ImGui::Text(label.c_str()); + if (isHovered) + *isHovered = ImGui::IsItemHovered(); ImGui::SameLine(); return ImGui::InputFloat("#", &value, 0.1f, 1.0f, "%.3f", ImGuiInputTextFlags_EnterReturnsTrue); } - bool SHEditorUI::InputDouble(const std::string& label, double& value) + bool SHEditorUI::InputDouble(const std::string& label, double& value, bool* isHovered) { ImGui::Text(label.c_str()); + if (isHovered) + *isHovered = ImGui::IsItemHovered(); ImGui::SameLine(); return ImGui::InputDouble("#", &value, 0.1, 1.0, "%.3f", ImGuiInputTextFlags_EnterReturnsTrue); } - bool SHEditorUI::InputAngle(const std::string& label, double& value) + bool SHEditorUI::InputAngle(const std::string& label, double& value, bool* isHovered) { ImGui::Text(label.c_str()); + if (isHovered) + *isHovered = ImGui::IsItemHovered(); ImGui::SameLine(); return ImGui::InputDouble("#", &value, 1.0, 45.0, "%.3f", ImGuiInputTextFlags_EnterReturnsTrue); } - bool SHEditorUI::InputSlider(const std::string& label, double min, double max, double& value) + bool SHEditorUI::InputSlider(const std::string& label, double min, double max, double& value, bool* isHovered) { float val = static_cast(value); ImGui::Text(label.c_str()); + if (isHovered) + *isHovered = ImGui::IsItemHovered(); ImGui::SameLine(); const bool CHANGED = ImGui::SliderFloat("#", &val, static_cast(min), static_cast(max), "%.3f", @@ -204,22 +233,24 @@ namespace SHADE return CHANGED; } - bool SHEditorUI::InputVec2(const std::string& label, SHVec2& value) + bool SHEditorUI::InputVec2(const std::string& label, SHVec2& value, bool* isHovered) { static const std::vector COMPONENT_LABELS = { "X", "Y" }; - return SHEditorWidgets::DragN(label, COMPONENT_LABELS, { &value.x, &value.y }); + return SHEditorWidgets::DragN(label, COMPONENT_LABELS, { &value.x, &value.y }, 0.1f, "%.3f", float{}, float{}, 0, isHovered); } - bool SHEditorUI::InputVec3(const std::string& label, SHVec3& value, float speed) + bool SHEditorUI::InputVec3(const std::string& label, SHVec3& value, bool* isHovered, float speed) { static const std::vector COMPONENT_LABELS = { "X", "Y", "Z"}; - return SHEditorWidgets::DragN(label, COMPONENT_LABELS, { &value.x, &value.y, &value.z }, speed, "%.3f"); + return SHEditorWidgets::DragN(label, COMPONENT_LABELS, { &value.x, &value.y, &value.z }, speed, "%.3f", float{}, float{}, 0, isHovered); } - bool SHEditorUI::InputTextField(const std::string& label, std::string& value) + bool SHEditorUI::InputTextField(const std::string& label, std::string& value, bool* isHovered) { std::array buffer = { '\0' }; strcpy_s(buffer.data(), TEXT_FIELD_MAX_LENGTH, value.c_str()); ImGui::Text(label.c_str()); + if (isHovered) + *isHovered = ImGui::IsItemHovered(); ImGui::SameLine(); const bool CHANGED = ImGui::InputText("#", &buffer[0], TEXT_FIELD_MAX_LENGTH); if (CHANGED) @@ -229,13 +260,15 @@ namespace SHADE return CHANGED; } - bool SHEditorUI::InputEnumCombo(const std::string& label, int& v, const std::vector& enumNames) + bool SHEditorUI::InputEnumCombo(const std::string& label, int& v, const std::vector& enumNames, bool* isHovered) { // Clamp input value const std::string& INITIAL_NAME = v >= static_cast(enumNames.size()) ? "Unknown" : enumNames[v]; bool b = false; ImGui::Text(label.c_str()); + if (isHovered) + *isHovered = ImGui::IsItemHovered(); ImGui::SameLine(); if (ImGui::BeginCombo("#", INITIAL_NAME.c_str(), ImGuiComboFlags_None)) { diff --git a/SHADE_Engine/src/Editor/SHEditorUI.h b/SHADE_Engine/src/Editor/SHEditorUI.h index 13468215..b8451765 100644 --- a/SHADE_Engine/src/Editor/SHEditorUI.h +++ b/SHADE_Engine/src/Editor/SHEditorUI.h @@ -90,12 +90,19 @@ namespace SHADE static void SameLine(); static void Separator(); - /*-----------------------------------------------------------------------------*/ + /*-----------------------------------------------------------------------------*/ + /* ImGui Wrapper Functions - Queries */ + /*-----------------------------------------------------------------------------*/ + static bool IsItemHovered(); + + /*-----------------------------------------------------------------------------*/ /* ImGui Wrapper Functions - Menu */ /*-----------------------------------------------------------------------------*/ static bool BeginMenu(const std::string& label); static bool BeginMenu(const std::string& label, const char* icon); static void EndMenu(); + static void BeginTooltip(); + static void EndTooltip(); /*-----------------------------------------------------------------------------*/ /* ImGui Wrapper Functions - Pop Ups */ @@ -165,8 +172,9 @@ namespace SHADE /// /// Label used to identify this widget. /// Reference to the variable to store the result. + /// Label used to identify this widget. /// Reference to the variable to store the result. + /// Label used to identify this widget. /// Reference to the variable to store the result. + /// Label used to identify this widget. /// Reference to the variable to store the result. + /// Label used to identify this widget. /// Reference to the variable to store the result. + /// Label used to identify this widget. /// Reference to the variable to store the result. + /// Minimum value of the slider. /// Maximum value of the slider. /// Reference to the variable to store the result. + /// Label used to identify this widget. /// Reference to the variable to store the result. + /// Label used to identify this widget. /// Reference to the variable to store the result. + /// Label used to identify this widget. /// Reference to the variable to store the result. + /// /// Conversion function from the type of enum to C-style string. /// + /// The name of the input. /// The reference to the value to modify. /// Vector of names for each enumeration value. + /// SkipItems) @@ -174,6 +174,8 @@ namespace SHADE ImGui::BeginColumns("DragVecCol", 2, ImGuiOldColumnFlags_NoBorder | ImGuiOldColumnFlags_NoResize); ImGui::SetColumnWidth(-1, 80.0f); ImGui::Text(fieldLabel.c_str()); + if (isHovered) + *isHovered = ImGui::IsItemHovered(); ImGui::NextColumn(); for (std::size_t i = 0; i < N; ++i) { diff --git a/SHADE_Managed/src/Editor/Editor.cxx b/SHADE_Managed/src/Editor/Editor.cxx index 735f8c2c..8d105fce 100644 --- a/SHADE_Managed/src/Editor/Editor.cxx +++ b/SHADE_Managed/src/Editor/Editor.cxx @@ -29,6 +29,7 @@ of DigiPen Institute of Technology is prohibited. #include "Editor/IconsMaterialDesign.h" #include "Editor/Command/SHCommandManager.h" #include "Editor/Command/SHCommand.hpp" +#include "TooltipAttribute.hxx" // Using Directives using namespace System; @@ -48,17 +49,17 @@ using namespace System::Collections::Generic; /// The managed type of the object to edit. /// The native type of the object to edit. /// The SHEditorUI:: function to use for editing. -#define RENDER_FIELD(MANAGED_TYPE, NATIVE_TYPE, FUNC) \ -(field->FieldType == MANAGED_TYPE::typeid) \ -{ \ - NATIVE_TYPE val = safe_cast(field->GetValue(object)); \ - NATIVE_TYPE oldVal = val; \ - if (SHEditorUI::FUNC(Convert::ToNative(field->Name), val)) \ - { \ - field->SetValue(object, val); \ - registerUndoAction(object, field, val, oldVal); \ - } \ -} \ +#define RENDER_FIELD(MANAGED_TYPE, NATIVE_TYPE, FUNC) \ +(field->FieldType == MANAGED_TYPE::typeid) \ +{ \ + NATIVE_TYPE val = safe_cast(field->GetValue(object)); \ + NATIVE_TYPE oldVal = val; \ + if (SHEditorUI::FUNC(Convert::ToNative(field->Name), val, &isHovered))\ + { \ + field->SetValue(object, val); \ + registerUndoAction(object, field, val, oldVal); \ + } \ +} \ /// /// Macro expansion that is used in renderFieldInInspector() to check the type of a field /// named "field" against the specified type and if it matches, retrieves the value of @@ -76,7 +77,7 @@ using namespace System::Collections::Generic; { \ NATIVE_TYPE val = Convert::ToNative(safe_cast(field->GetValue(object))); \ NATIVE_TYPE oldVal = val; \ - if (SHEditorUI::FUNC(Convert::ToNative(field->Name), val)) \ + if (SHEditorUI::FUNC(Convert::ToNative(field->Name), val, &isHovered)) \ { \ field->SetValue(object, Convert::ToCLI(val)); \ registerUndoAction(object, field, Convert::ToCLI(val), Convert::ToCLI(oldVal)); \ @@ -196,6 +197,8 @@ namespace SHADE } void Editor::renderFieldInInspector(Reflection::FieldInfo^ field, Object^ object) { + bool isHovered = false; + if RENDER_FIELD (Int16, int, InputInt) else if RENDER_FIELD (Int32, int, InputInt) else if RENDER_FIELD (Int64, int, InputInt) @@ -244,6 +247,15 @@ namespace SHADE registerUndoAction(object, field, Convert::ToCLI(val), Convert::ToCLI(oldVal)); } } + + // Check if the field has a specific attribute + TooltipAttribute^ toolTip = hasAttribute(field); + if (toolTip && isHovered) + { + SHEditorUI::BeginTooltip(); + SHEditorUI::Text(Convert::ToNative(toolTip->Description)); + SHEditorUI::EndTooltip(); + } } void Editor::renderScriptContextMenu(Entity entity, Script^ script) @@ -274,4 +286,24 @@ namespace SHADE SHCommandManager::RegisterCommand(std::reinterpret_pointer_cast(std::make_shared())); } + generic + Attribute Editor::hasAttribute(System::Reflection::FieldInfo^ field) + { + array^ attributes = field->GetCustomAttributes(true); + for each (System::Object^ attrib in attributes) + { + try + { + Attribute attribute = safe_cast(attrib); + if (attribute != nullptr) + return attribute; + } + catch (System::InvalidCastException^) + { + continue; + } + } + // Failed to find + return Attribute{}; + } } diff --git a/SHADE_Managed/src/Editor/Editor.hxx b/SHADE_Managed/src/Editor/Editor.hxx index c4800645..6b59589a 100644 --- a/SHADE_Managed/src/Editor/Editor.hxx +++ b/SHADE_Managed/src/Editor/Editor.hxx @@ -23,7 +23,7 @@ namespace SHADE /// /// Static class for Editor-related functions /// - public ref class Editor abstract sealed + private ref class Editor abstract sealed { public: /*-----------------------------------------------------------------------------*/ @@ -48,7 +48,13 @@ namespace SHADE /*-----------------------------------------------------------------------------*/ /* UndoRedoStack Functions */ /*-----------------------------------------------------------------------------*/ + /// + /// Undoes the last script inspector change if there is any. + /// static void Undo(); + /// + /// Redoes the last script inspector change if there is any. + /// static void Redo(); private: @@ -86,5 +92,7 @@ namespace SHADE /// The Script to render the inspector for. static void renderScriptContextMenu(Entity entity, Script^ script); static void registerUndoAction(System::Object^ object, System::Reflection::FieldInfo^ field, System::Object^ newData, System::Object^ oldData); + generic where Attribute : System::Attribute + static Attribute hasAttribute(System::Reflection::FieldInfo^ field); }; } diff --git a/SHADE_Managed/src/Serialisation/SerialiseFieldAttribute.cxx b/SHADE_Managed/src/Editor/TooltipAttribute.cxx similarity index 54% rename from SHADE_Managed/src/Serialisation/SerialiseFieldAttribute.cxx rename to SHADE_Managed/src/Editor/TooltipAttribute.cxx index c371d200..8d5a5d55 100644 --- a/SHADE_Managed/src/Serialisation/SerialiseFieldAttribute.cxx +++ b/SHADE_Managed/src/Editor/TooltipAttribute.cxx @@ -1,27 +1,34 @@ /************************************************************************************//*! -\file SerializeFieldAttribute.cxx +\file TooltipAttribute.cxx \author Tng Kah Wei, kahwei.tng, 390009620 \par email: kahwei.tng\@digipen.edu -\date Nov 5, 2021 -\brief Contains the definition of the functions of the managed SerializeField - Attribute class. +\date Oct 18, 2022 +\brief Contains the definition of the functions of the managed Tooltip Attribute + class. Note: This file is written in C++17/CLI. - -Copyright (C) 2021 DigiPen Institute of Technology. -Reproduction or disclosure of this file or its contents without the prior written consent + +Copyright (C) 2022 DigiPen Institute of Technology. +Reproduction or disclosure of this file or its contents without the prior written consent of DigiPen Institute of Technology is prohibited. *//*************************************************************************************/ -// Precompiled Headers #include "SHpch.h" -// Primary Header -#include "SerializeFieldAttribute.hxx" +#include "TooltipAttribute.hxx" namespace SHADE { + /*---------------------------------------------------------------------------------*/ + /* Properties */ + /*---------------------------------------------------------------------------------*/ + System::String^ TooltipAttribute::Description::get() + { + return desc; + } + /*---------------------------------------------------------------------------------*/ /* Constructors */ /*---------------------------------------------------------------------------------*/ - SerializeField::SerializeField() + TooltipAttribute::TooltipAttribute(System::String^ description) + : desc { description } {} } diff --git a/SHADE_Managed/src/Editor/TooltipAttribute.hxx b/SHADE_Managed/src/Editor/TooltipAttribute.hxx new file mode 100644 index 00000000..e7cd168c --- /dev/null +++ b/SHADE_Managed/src/Editor/TooltipAttribute.hxx @@ -0,0 +1,53 @@ +/************************************************************************************//*! +\file TooltipAttribute.hxx +\author Tng Kah Wei, kahwei.tng, 390009620 +\par email: kahwei.tng\@digipen.edu +\date Oct 18, 2022 +\brief Contains the definition of the managed Tooltip Attribute class with + the declaration of functions for working with it. + + Note: This file is written in C++17/CLI. + +Copyright (C) 2022 DigiPen Institute of Technology. +Reproduction or disclosure of this file or its contents without the prior written consent +of DigiPen Institute of Technology is prohibited. +*//*************************************************************************************/ +#pragma once + +namespace SHADE +{ + /// + /// Simple attribute to mark that a field in a Script should be serialised. + /// + [System::AttributeUsage(System::AttributeTargets::Field)] + public ref class TooltipAttribute : public System::Attribute + { + public: + /*-----------------------------------------------------------------------------*/ + /* Properties */ + /*-----------------------------------------------------------------------------*/ + /// + /// Description that is to be shown in the Tooltip. + /// + property System::String^ Description + { + System::String^ get(); + } + + /*-----------------------------------------------------------------------------*/ + /* Constructors */ + /*-----------------------------------------------------------------------------*/ + /// + /// Constructor for a Tooltip attribute that fills in the description. + /// + /// Text to be shown when a field is hovered. + TooltipAttribute(System::String^ description); + + private: + /*-----------------------------------------------------------------------------*/ + /* Data Members */ + /*-----------------------------------------------------------------------------*/ + System::String^ desc; + }; +} + diff --git a/SHADE_Managed/src/Serialisation/SerializeFieldAttribute.hxx b/SHADE_Managed/src/Serialisation/SerializeFieldAttribute.hxx index 533ded2a..7a7bb83c 100644 --- a/SHADE_Managed/src/Serialisation/SerializeFieldAttribute.hxx +++ b/SHADE_Managed/src/Serialisation/SerializeFieldAttribute.hxx @@ -21,15 +21,6 @@ namespace SHADE /// [System::AttributeUsage(System::AttributeTargets::Field)] public ref class SerializeField : public System::Attribute - { - public: - /*-----------------------------------------------------------------------------*/ - /* Constructors */ - /*-----------------------------------------------------------------------------*/ - /// - /// Default Constructor - /// - SerializeField(); - }; + {}; } diff --git a/TempScriptsFolder/RaccoonShowcase.cs b/TempScriptsFolder/RaccoonShowcase.cs index e2d6454d..93ea53eb 100644 --- a/TempScriptsFolder/RaccoonShowcase.cs +++ b/TempScriptsFolder/RaccoonShowcase.cs @@ -3,8 +3,12 @@ using System; public class RaccoonShowcase : Script { - public double RotateSpeed = 1.0; - public Vector3 ScaleSpeed = new Vector3(1.0, 1.0, 0.0); + [SerializeField] + [Tooltip("Speed of the rotation in radians per second.")] + private double RotateSpeed = 1.0; + [SerializeField] + [Tooltip("Speed of the scaling in radians per second around each axis.")] + private Vector3 ScaleSpeed = new Vector3(1.0, 1.0, 0.0); private Transform Transform; private double rotation = 0.0; private Vector3 scale = Vector3.Zero; diff --git a/TempScriptsFolder/RaccoonSpin.cs b/TempScriptsFolder/RaccoonSpin.cs index 7785cfd5..d6ee1c9f 100644 --- a/TempScriptsFolder/RaccoonSpin.cs +++ b/TempScriptsFolder/RaccoonSpin.cs @@ -3,7 +3,9 @@ using System; public class RaccoonSpin : Script { - public double RotateSpeed = 1.0; + [SerializeField] + [Tooltip("Speed of the rotation in radians per second.")] + private double RotateSpeed = 1.0; private double rotation = 0.0; private Transform Transform; public RaccoonSpin(GameObject gameObj) : base(gameObj) { } From ceb4c6c4cabcb2fb0a445dd185872af1ffb62e12 Mon Sep 17 00:00:00 2001 From: Kah Wei Date: Tue, 18 Oct 2022 22:34:46 +0800 Subject: [PATCH 09/12] Added Range Attribute --- SHADE_Engine/src/Editor/SHEditorUI.cpp | 19 ------ SHADE_Engine/src/Editor/SHEditorUI.h | 3 +- SHADE_Engine/src/Editor/SHEditorUI.hpp | 25 +++++++- SHADE_Managed/src/Editor/Editor.cxx | 47 +++++++++++--- SHADE_Managed/src/Editor/RangeAttribute.cxx | 39 ++++++++++++ SHADE_Managed/src/Editor/RangeAttribute.hxx | 61 +++++++++++++++++++ SHADE_Managed/src/Editor/TooltipAttribute.hxx | 2 +- TempScriptsFolder/RaccoonShowcase.cs | 4 ++ 8 files changed, 166 insertions(+), 34 deletions(-) create mode 100644 SHADE_Managed/src/Editor/RangeAttribute.cxx create mode 100644 SHADE_Managed/src/Editor/RangeAttribute.hxx diff --git a/SHADE_Engine/src/Editor/SHEditorUI.cpp b/SHADE_Engine/src/Editor/SHEditorUI.cpp index 76f7bac6..cbbd6d1d 100644 --- a/SHADE_Engine/src/Editor/SHEditorUI.cpp +++ b/SHADE_Engine/src/Editor/SHEditorUI.cpp @@ -214,25 +214,6 @@ namespace SHADE ImGuiInputTextFlags_EnterReturnsTrue); } - bool SHEditorUI::InputSlider(const std::string& label, double min, double max, double& value, bool* isHovered) - { - float val = static_cast(value); - ImGui::Text(label.c_str()); - if (isHovered) - *isHovered = ImGui::IsItemHovered(); - ImGui::SameLine(); - const bool CHANGED = ImGui::SliderFloat("#", &val, - static_cast(min), static_cast(max), "%.3f", - ImGuiInputTextFlags_EnterReturnsTrue); - - if (CHANGED) - { - value = val; - } - - return CHANGED; - } - bool SHEditorUI::InputVec2(const std::string& label, SHVec2& value, bool* isHovered) { static const std::vector COMPONENT_LABELS = { "X", "Y" }; diff --git a/SHADE_Engine/src/Editor/SHEditorUI.h b/SHADE_Engine/src/Editor/SHEditorUI.h index b8451765..276bc9f9 100644 --- a/SHADE_Engine/src/Editor/SHEditorUI.h +++ b/SHADE_Engine/src/Editor/SHEditorUI.h @@ -240,7 +240,8 @@ namespace SHADE /// Reference to the variable to store the result. /// (min), static_cast(max), "%.3f", + ImGuiInputTextFlags_EnterReturnsTrue); + if (CHANGED) + { + value = static_cast(val); + } + + //return CHANGED; + return false; + } template inline bool SHEditorUI::InputEnumCombo(const std::string& label, Enum& v, int maxVal, std::function toStrFn, bool* isHovered) { diff --git a/SHADE_Managed/src/Editor/Editor.cxx b/SHADE_Managed/src/Editor/Editor.cxx index 8d105fce..f0690c06 100644 --- a/SHADE_Managed/src/Editor/Editor.cxx +++ b/SHADE_Managed/src/Editor/Editor.cxx @@ -30,6 +30,7 @@ of DigiPen Institute of Technology is prohibited. #include "Editor/Command/SHCommandManager.h" #include "Editor/Command/SHCommand.hpp" #include "TooltipAttribute.hxx" +#include "RangeAttribute.hxx" // Using Directives using namespace System; @@ -61,6 +62,31 @@ using namespace System::Collections::Generic; } \ } \ /// +/// Alternative to RENDER_FIELD that checks for RangeAttribute and switches to a slider +/// instead. +/// +/// The managed type of the object to edit. +/// The native type of the object to edit. +/// The SHEditorUI:: function to use for editing. +#define RENDER_FIELD_RANGE(MANAGED_TYPE, NATIVE_TYPE, FUNC) \ +(field->FieldType == MANAGED_TYPE::typeid) \ +{ \ + NATIVE_TYPE val = safe_cast(field->GetValue(object)); \ + NATIVE_TYPE oldVal = val; \ + \ + RangeAttribute^ rangeAttrib = hasAttribute(field); \ + std::string fieldName = Convert::ToNative(field->Name); \ + if ( \ + (rangeAttrib && SHEditorUI::InputSlider(fieldName, rangeAttrib->Min, rangeAttrib->Max, val, &isHovered)) \ + || \ + SHEditorUI::FUNC(fieldName, val, &isHovered) \ + ) \ + { \ + field->SetValue(object, val); \ + registerUndoAction(object, field, val, oldVal); \ + } \ +} \ +/// /// Macro expansion that is used in renderFieldInInspector() to check the type of a field /// named "field" against the specified type and if it matches, retrieves the value of /// that field from an object named "object" and pass it into the specified SHEditorUI:: @@ -77,6 +103,7 @@ using namespace System::Collections::Generic; { \ NATIVE_TYPE val = Convert::ToNative(safe_cast(field->GetValue(object))); \ NATIVE_TYPE oldVal = val; \ + \ if (SHEditorUI::FUNC(Convert::ToNative(field->Name), val, &isHovered)) \ { \ field->SetValue(object, Convert::ToCLI(val)); \ @@ -197,18 +224,18 @@ namespace SHADE } void Editor::renderFieldInInspector(Reflection::FieldInfo^ field, Object^ object) { - bool isHovered = false; + bool isHovered = false; - if RENDER_FIELD (Int16, int, InputInt) - else if RENDER_FIELD (Int32, int, InputInt) - else if RENDER_FIELD (Int64, int, InputInt) - else if RENDER_FIELD (UInt16, unsigned int, InputUnsignedInt) - else if RENDER_FIELD (UInt32, unsigned int, InputUnsignedInt) - else if RENDER_FIELD (UInt64, unsigned int, InputUnsignedInt) - else if RENDER_FIELD (Byte, int, InputInt) + if RENDER_FIELD_RANGE (Int16, int, InputInt) + else if RENDER_FIELD_RANGE (Int32, int, InputInt) + else if RENDER_FIELD_RANGE (Int64, int, InputInt) + else if RENDER_FIELD_RANGE (UInt16, unsigned int, InputUnsignedInt) + else if RENDER_FIELD_RANGE (UInt32, unsigned int, InputUnsignedInt) + else if RENDER_FIELD_RANGE (UInt64, unsigned int, InputUnsignedInt) + else if RENDER_FIELD_RANGE (Byte, int, InputInt) else if RENDER_FIELD (bool, bool, InputCheckbox) - else if RENDER_FIELD (float, float, InputFloat) - else if RENDER_FIELD (double, double, InputDouble) + else if RENDER_FIELD_RANGE (float, float, InputFloat) + else if RENDER_FIELD_RANGE (double, double, InputDouble) else if (field->FieldType->IsSubclassOf(Enum::typeid)) { // Get all the names of the enums diff --git a/SHADE_Managed/src/Editor/RangeAttribute.cxx b/SHADE_Managed/src/Editor/RangeAttribute.cxx new file mode 100644 index 00000000..0d548cf7 --- /dev/null +++ b/SHADE_Managed/src/Editor/RangeAttribute.cxx @@ -0,0 +1,39 @@ +/************************************************************************************//*! +\file RangeAttribute.cxx +\author Tng Kah Wei, kahwei.tng, 390009620 +\par email: kahwei.tng\@digipen.edu +\date Oct 18, 2022 +\brief Contains the definition of the functions of the managed Range Attribute + class. + + Note: This file is written in C++17/CLI. + +Copyright (C) 2022 DigiPen Institute of Technology. +Reproduction or disclosure of this file or its contents without the prior written consent +of DigiPen Institute of Technology is prohibited. +*//*************************************************************************************/ +#include "SHpch.h" +#include "RangeAttribute.hxx" + +namespace SHADE +{ + /*---------------------------------------------------------------------------------*/ + /* Properties */ + /*---------------------------------------------------------------------------------*/ + float RangeAttribute::Min::get() + { + return minVal; + } + float RangeAttribute::Max::get() + { + return maxVal; + } + + /*---------------------------------------------------------------------------------*/ + /* Constructors */ + /*---------------------------------------------------------------------------------*/ + RangeAttribute::RangeAttribute(float min, float max) + : minVal { min } + , maxVal { max } + {} +} diff --git a/SHADE_Managed/src/Editor/RangeAttribute.hxx b/SHADE_Managed/src/Editor/RangeAttribute.hxx new file mode 100644 index 00000000..a724816d --- /dev/null +++ b/SHADE_Managed/src/Editor/RangeAttribute.hxx @@ -0,0 +1,61 @@ +/************************************************************************************//*! +\file RangeAttribute.hxx +\author Tng Kah Wei, kahwei.tng, 390009620 +\par email: kahwei.tng\@digipen.edu +\date Oct 18, 2022 +\brief Contains the definition of the managed Range Attribute class with + the declaration of functions for working with it. + + Note: This file is written in C++17/CLI. + +Copyright (C) 2022 DigiPen Institute of Technology. +Reproduction or disclosure of this file or its contents without the prior written consent +of DigiPen Institute of Technology is prohibited. +*//*************************************************************************************/ +#pragma once + +namespace SHADE +{ + /// + /// Simple attribute to constrain the range of values for a field on the editor. + /// + [System::AttributeUsage(System::AttributeTargets::Field)] + public ref class RangeAttribute : public System::Attribute + { + public: + /*-----------------------------------------------------------------------------*/ + /* Properties */ + /*-----------------------------------------------------------------------------*/ + /// + /// Minimum value for the Ranged field. + /// + property float Min + { + float get(); + } + /// + /// Maximum value for the Ranged field. + /// + property float Max + { + float get(); + } + + /*-----------------------------------------------------------------------------*/ + /* Constructors */ + /*-----------------------------------------------------------------------------*/ + /// + /// Constructor for a Tooltip attribute that fills in the description. + /// + /// Text to be shown when a field is hovered. + RangeAttribute(float min, float max); + + private: + /*-----------------------------------------------------------------------------*/ + /* Data Members */ + /*-----------------------------------------------------------------------------*/ + float minVal; + float maxVal; + }; +} + diff --git a/SHADE_Managed/src/Editor/TooltipAttribute.hxx b/SHADE_Managed/src/Editor/TooltipAttribute.hxx index e7cd168c..18cbec3a 100644 --- a/SHADE_Managed/src/Editor/TooltipAttribute.hxx +++ b/SHADE_Managed/src/Editor/TooltipAttribute.hxx @@ -17,7 +17,7 @@ of DigiPen Institute of Technology is prohibited. namespace SHADE { /// - /// Simple attribute to mark that a field in a Script should be serialised. + /// Simple attribute to provide a field in a script with a tooltip. /// [System::AttributeUsage(System::AttributeTargets::Field)] public ref class TooltipAttribute : public System::Attribute diff --git a/TempScriptsFolder/RaccoonShowcase.cs b/TempScriptsFolder/RaccoonShowcase.cs index 93ea53eb..4191a6e5 100644 --- a/TempScriptsFolder/RaccoonShowcase.cs +++ b/TempScriptsFolder/RaccoonShowcase.cs @@ -5,7 +5,11 @@ public class RaccoonShowcase : Script { [SerializeField] [Tooltip("Speed of the rotation in radians per second.")] + [Range(-1.0f, 2.0f)] private double RotateSpeed = 1.0; + //[SerializeField] + //[Range(-5, 20)] + //private int test = 5; [SerializeField] [Tooltip("Speed of the scaling in radians per second around each axis.")] private Vector3 ScaleSpeed = new Vector3(1.0, 1.0, 0.0); From 96f5b29418eba41c360e2386350b64946ab036a2 Mon Sep 17 00:00:00 2001 From: Sri Sham Haran Date: Wed, 19 Oct 2022 01:03:32 +0800 Subject: [PATCH 10/12] 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); From 7df24e7a66334bad6b473e247c8245736443dd13 Mon Sep 17 00:00:00 2001 From: Kah Wei Date: Wed, 19 Oct 2022 10:12:56 +0800 Subject: [PATCH 11/12] Fixed RangeAttribute not working correctly --- SHADE_Engine/src/Editor/SHEditorUI.cpp | 46 ++++++++++++++++++++++++++ SHADE_Engine/src/Editor/SHEditorUI.h | 43 +++++++++++++++++++++--- SHADE_Engine/src/Editor/SHEditorUI.hpp | 19 ----------- SHADE_Managed/src/Editor/Editor.cxx | 26 +++++++++++---- 4 files changed, 104 insertions(+), 30 deletions(-) diff --git a/SHADE_Engine/src/Editor/SHEditorUI.cpp b/SHADE_Engine/src/Editor/SHEditorUI.cpp index cbbd6d1d..7107778d 100644 --- a/SHADE_Engine/src/Editor/SHEditorUI.cpp +++ b/SHADE_Engine/src/Editor/SHEditorUI.cpp @@ -214,6 +214,52 @@ namespace SHADE ImGuiInputTextFlags_EnterReturnsTrue); } + bool SHEditorUI::InputSlider(const std::string& label, int min, int max, int& value, bool* isHovered /*= nullptr*/) + { + ImGui::Text(label.c_str()); + if (isHovered) + *isHovered = ImGui::IsItemHovered(); + ImGui::SameLine(); + return ImGui::SliderInt("##", &value, + static_cast(min), static_cast(max), "%d", + ImGuiInputTextFlags_EnterReturnsTrue); + } + + bool SHEditorUI::InputSlider(const std::string& label, unsigned int min, unsigned int max, unsigned int& value, bool* isHovered /*= nullptr*/) + { + int val = static_cast(value); + const bool CHANGED = InputSlider(label, min, max, val, isHovered); + if (CHANGED) + { + value = static_cast(val); + } + + return CHANGED; + } + + bool SHEditorUI::InputSlider(const std::string& label, float min, float max, float& value, bool* isHovered) + { + ImGui::Text(label.c_str()); + if (isHovered) + *isHovered = ImGui::IsItemHovered(); + ImGui::SameLine(); + return ImGui::SliderFloat("##", &value, + static_cast(min), static_cast(max), "%.3f", + ImGuiInputTextFlags_EnterReturnsTrue); + } + + bool SHEditorUI::InputSlider(const std::string& label, double min, double max, double& value, bool* isHovered /*= nullptr*/) + { + float val = static_cast(value); + const bool CHANGED = InputSlider(label, min, max, val, isHovered); + if (CHANGED) + { + value = static_cast(val); + } + + return CHANGED; + } + bool SHEditorUI::InputVec2(const std::string& label, SHVec2& value, bool* isHovered) { static const std::vector COMPONENT_LABELS = { "X", "Y" }; diff --git a/SHADE_Engine/src/Editor/SHEditorUI.h b/SHADE_Engine/src/Editor/SHEditorUI.h index 276bc9f9..f3051aa1 100644 --- a/SHADE_Engine/src/Editor/SHEditorUI.h +++ b/SHADE_Engine/src/Editor/SHEditorUI.h @@ -230,9 +230,9 @@ namespace SHADE /// True if the value was changed. static bool InputAngle(const std::string& label, double& value, bool* isHovered = nullptr); /// - /// Creates a double slider field widget for double input. + /// Creates an int slider field widget for double input. ///
- /// Wraps up ImGui::InputSliderFloat(). + /// Wraps up ImGui::SliderInt(). ///
/// Label used to identify this widget. /// Minimum value of the slider. @@ -240,8 +240,43 @@ namespace SHADE /// Reference to the variable to store the result. /// Label used to identify this widget. + /// Minimum value of the slider. + /// Maximum value of the slider. + /// Reference to the variable to store the result. + /// Label used to identify this widget. + /// Minimum value of the slider. + /// Maximum value of the slider. + /// Reference to the variable to store the result. + /// Label used to identify this widget. + /// Minimum value of the slider. + /// Maximum value of the slider. + /// Reference to the variable to store the result. + /// (min), static_cast(max), "%.3f", - ImGuiInputTextFlags_EnterReturnsTrue); - if (CHANGED) - { - value = static_cast(val); - } - - //return CHANGED; - return false; - } template inline bool SHEditorUI::InputEnumCombo(const std::string& label, Enum& v, int maxVal, std::function toStrFn, bool* isHovered) { diff --git a/SHADE_Managed/src/Editor/Editor.cxx b/SHADE_Managed/src/Editor/Editor.cxx index f0690c06..120f0274 100644 --- a/SHADE_Managed/src/Editor/Editor.cxx +++ b/SHADE_Managed/src/Editor/Editor.cxx @@ -75,12 +75,24 @@ using namespace System::Collections::Generic; NATIVE_TYPE oldVal = val; \ \ RangeAttribute^ rangeAttrib = hasAttribute(field); \ - std::string fieldName = Convert::ToNative(field->Name); \ - if ( \ - (rangeAttrib && SHEditorUI::InputSlider(fieldName, rangeAttrib->Min, rangeAttrib->Max, val, &isHovered)) \ - || \ - SHEditorUI::FUNC(fieldName, val, &isHovered) \ - ) \ + const std::string FIELD_NAME = Convert::ToNative(field->Name); \ + bool changed = false; \ + if (rangeAttrib) \ + { \ + changed = SHEditorUI::InputSlider \ + ( \ + FIELD_NAME, \ + static_cast(rangeAttrib->Min), \ + static_cast(rangeAttrib->Max), \ + val, &isHovered \ + ); \ + } \ + else \ + { \ + changed = SHEditorUI::FUNC(FIELD_NAME, val, &isHovered); \ + } \ + \ + if (changed) \ { \ field->SetValue(object, val); \ registerUndoAction(object, field, val, oldVal); \ @@ -224,7 +236,7 @@ namespace SHADE } void Editor::renderFieldInInspector(Reflection::FieldInfo^ field, Object^ object) { - bool isHovered = false; + bool isHovered = false; if RENDER_FIELD_RANGE (Int16, int, InputInt) else if RENDER_FIELD_RANGE (Int32, int, InputInt) From a3c4c347bb4fb899a6bcaf9b03b9ffafd82b1a77 Mon Sep 17 00:00:00 2001 From: Kah Wei Date: Wed, 19 Oct 2022 16:06:26 +0800 Subject: [PATCH 12/12] Added Time class for C# --- SHADE_Engine/src/FRC/SHFramerateController.h | 1 - SHADE_Managed/src/Engine/Time.cxx | 29 ++++++++++++++ SHADE_Managed/src/Engine/Time.hxx | 41 ++++++++++++++++++++ 3 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 SHADE_Managed/src/Engine/Time.cxx create mode 100644 SHADE_Managed/src/Engine/Time.hxx diff --git a/SHADE_Engine/src/FRC/SHFramerateController.h b/SHADE_Engine/src/FRC/SHFramerateController.h index b9637cf2..dbabbac5 100644 --- a/SHADE_Engine/src/FRC/SHFramerateController.h +++ b/SHADE_Engine/src/FRC/SHFramerateController.h @@ -14,7 +14,6 @@ #pragma once #include -#include "Tools/SHLogger.h" #include "SH_API.h" namespace SHADE diff --git a/SHADE_Managed/src/Engine/Time.cxx b/SHADE_Managed/src/Engine/Time.cxx new file mode 100644 index 00000000..ff0628e7 --- /dev/null +++ b/SHADE_Managed/src/Engine/Time.cxx @@ -0,0 +1,29 @@ +/************************************************************************************//*! +\file Time.cxx +\author Tng Kah Wei, kahwei.tng, 390009620 +\par email: kahwei.tng\@digipen.edu +\date Oct 19, 2022 +\brief This file is present so that the properties in Time.hxx would be compiled + into the DLL. + + Note: This file is written in C++17/CLI. + +Copyright (C) 2022 DigiPen Institute of Technology. +Reproduction or disclosure of this file or its contents without the prior written consent +of DigiPen Institute of Technology is prohibited. +*//*************************************************************************************/ +// Precompiled Headers +#include "SHpch.h" +// Primary Header +#include "Time.hxx" + +namespace SHADE +{ + /*---------------------------------------------------------------------------------*/ + /* Properties */ + /*---------------------------------------------------------------------------------*/ + double Time::DeltaTime::get() + { + return SHFrameRateController::GetRawDeltaTime(); + } +} \ No newline at end of file diff --git a/SHADE_Managed/src/Engine/Time.hxx b/SHADE_Managed/src/Engine/Time.hxx new file mode 100644 index 00000000..969eea03 --- /dev/null +++ b/SHADE_Managed/src/Engine/Time.hxx @@ -0,0 +1,41 @@ +/************************************************************************************//*! +\file Time.hxx +\author Tng Kah Wei, kahwei.tng, 390009620 +\par email: kahwei.tng\@digipen.edu +\date Oct 19, 2022 +\brief Contains the definition of the Time static class and the definition of + its properties. + + Note: This file is written in C++17/CLI. + +Copyright (C) 2022 DigiPen Institute of Technology. +Reproduction or disclosure of this file or its contents without the prior written consent +of DigiPen Institute of Technology is prohibited. +*//*************************************************************************************/ +#pragma once + +#include "FRC/SHFramerateController.h" + +namespace SHADE +{ + /// + /// Static class that contains the functions for working with time. + /// + public ref class Time abstract sealed + { + public: + /*-----------------------------------------------------------------------------*/ + /* Properties */ + /*-----------------------------------------------------------------------------*/ + /// + /// Time taken to process the previous frame. + /// Note, is affected by TimeScale. Use UnscaledDeltaTime if you wish to retrieve + /// real world time. This is also affected by MaxDeltaTime clamping that + /// UnscaledDeltaTime is subject to. + /// + static property double DeltaTime + { + double get(); + } + }; +} \ No newline at end of file