#include "SHpch.h" #include "SHSerializationHelper.hpp" #include "SHSerialization.h" #include #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::basic_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::BeginSeq; auto pred = [&out](SHSceneNode* node) {out << SerializeEntityToNode(node); }; sceneGraph.Traverse(pred); //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]) 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]) { if(const int numOfChildren = node[NumberOfChildrenNode].as(); numOfChildren > 0) { ++it; for (int i = 0; i < numOfChildren; ++i) { DeserializeEntity(it, (*it), createdEntities, eid); if((i + 1) < numOfChildren) ++it; } } } } void SHSerialization::DeserializeSceneFromFile(std::filesystem::path const& path) { //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) { DeserializeEntity(it, (*it), createdEntities); } //Initialize Entity auto entityVecIt = createdEntities.begin(); for (auto it = entities.begin(); it != entities.end(); ++it) { InitializeEntity(*it, *entityVecIt++); } } std::string SHSerialization::SerializeEntityToString() { return std::string(); } void SHSerialization::SerializeEntityToFile(std::filesystem::path const& path) { } YAML::Node SHSerialization::SerializeEntityToNode(SHSceneNode* sceneNode) { YAML::Node node; auto eid = sceneNode->GetEntityID(); auto entity = SHEntityManager::GetEntityByID(eid); if (!sceneNode || !entity) { node = YAML::Null; return node; } node.SetStyle(YAML::EmitterStyle::Block); node[EIDNode] = eid; node[EntityNameNode] = entity->name; node[IsActiveNode] = sceneNode->IsActive(); auto const& children = sceneNode->GetChildren(); node[NumberOfChildrenNode] = children.size(); YAML::Node components; if (const auto transform = SHComponentManager::GetComponent_s(eid)) { components[rttr::type::get().get_name().data()] = SHSerializationHelper::SerializeComponentToNode(transform); } 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()); 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); } }