SHADE_Y3/SHADE_Engine/src/Serialization/SHSerialization.cpp

232 lines
7.1 KiB
C++
Raw Normal View History

2022-09-26 21:08:59 +08:00
#include "SHpch.h"
2022-09-26 23:51:20 +08:00
#include "SHSerializationHelper.hpp"
2022-09-26 21:08:59 +08:00
#include "SHSerialization.h"
#include <yaml-cpp/yaml.h>
2022-09-27 21:06:25 +08:00
#include "ECS_Base/Managers/SHEntityManager.h"
2022-09-26 21:08:59 +08:00
#include "Scene/SHSceneManager.h"
#include "Tools/SHException.h"
2022-10-01 23:43:00 +08:00
#include "Assets/SHAssetManager.h"
#include <fstream>
2022-09-26 21:08:59 +08:00
2022-10-01 23:43:00 +08:00
#include "Graphics/MiddleEnd/Interface/SHRenderable.h"
2022-09-26 21:08:59 +08:00
#include "Math/Transform/SHTransformComponent.h"
2022-10-19 01:03:32 +08:00
#include "Physics/Components/SHRigidBodyComponent.h"
#include "ECS_Base/Managers/SHSystemManager.h"
#include "Scripting/SHScriptEngine.h"
2022-09-26 21:08:59 +08:00
namespace SHADE
{
2022-09-26 23:51:20 +08:00
void SHSerialization::SerializeSceneToFile(std::filesystem::path const& path)
2022-09-26 21:08:59 +08:00
{
2022-10-01 23:43:00 +08:00
YAML::Emitter out;
SerializeSceneToEmitter(out);
std::ofstream file(path.c_str());
if (file.good())
{
file << out.c_str();
file.close();
}
2022-09-26 23:51:20 +08:00
}
2022-09-26 21:08:59 +08:00
2022-09-26 23:51:20 +08:00
std::string SHSerialization::SerializeSceneToString()
{
YAML::Emitter out;
SerializeSceneToEmitter(out);
2022-10-01 23:43:00 +08:00
return std::basic_string<char>(out.c_str());
2022-09-26 23:51:20 +08:00
}
2022-09-26 21:08:59 +08:00
2022-09-26 23:51:20 +08:00
void SHSerialization::SerializeSceneToEmitter(YAML::Emitter& out)
{
auto const& sceneGraph = SHSceneManager::GetCurrentSceneGraph();
auto root = sceneGraph.GetRoot();
2022-09-26 21:08:59 +08:00
2022-09-26 23:51:20 +08:00
SHASSERT(root != nullptr, "Root is null. Failed to serialize scene to node.");
2022-10-01 23:43:00 +08:00
2022-09-26 23:51:20 +08:00
auto const& children = root->GetChildren();
2022-10-01 23:43:00 +08:00
out << YAML::BeginSeq;
2022-09-27 21:06:25 +08:00
2022-10-01 23:43:00 +08:00
auto pred = [&out](SHSceneNode* node) {out << SerializeEntityToNode(node); };
2022-09-27 21:06:25 +08:00
sceneGraph.Traverse(pred);
2022-10-01 23:43:00 +08:00
//out << SerializeEntityToNode(child);
out << YAML::EndSeq;
2022-09-27 21:06:25 +08:00
}
static void DeserializeEntity(YAML::iterator& it, YAML::Node const& node, std::vector<EntityID>& createdEntities, EntityID parentEID = MAX_EID)
{
2022-10-01 23:43:00 +08:00
if (!node[EIDNode])
2022-09-27 21:06:25 +08:00
return;
EntityID eid = node[EIDNode].as<EntityID>();
std::string name = "Default";
2022-10-01 23:43:00 +08:00
if (node[EntityNameNode])
2022-09-27 21:06:25 +08:00
name = node[EntityNameNode].as<std::string>();
//Compile component IDs
const auto componentIDList = SHSerialization::GetComponentIDList(node[ComponentsNode]);
eid = SHEntityManager::CreateEntity(componentIDList, eid, name, parentEID);
createdEntities.push_back(eid);
2022-10-01 23:43:00 +08:00
if (node[NumberOfChildrenNode])
{
if(const int numOfChildren = node[NumberOfChildrenNode].as<int>(); numOfChildren > 0)
2022-09-27 21:06:25 +08:00
{
++it;
2022-10-01 23:43:00 +08:00
for (int i = 0; i < numOfChildren; ++i)
{
DeserializeEntity(it, (*it), createdEntities, eid);
if((i + 1) < numOfChildren)
++it;
}
2022-09-27 21:06:25 +08:00
}
}
2022-10-20 11:08:20 +08:00
// Deserialise scripts
if (node[ScriptsNode])
SHSystemManager::GetSystem<SHScriptEngine>()->DeserialiseScripts(eid, node[ScriptsNode]);
2022-09-27 21:06:25 +08:00
}
2022-10-01 23:43:00 +08:00
void SHSerialization::DeserializeSceneFromFile(std::filesystem::path const& path)
2022-09-27 21:06:25 +08:00
{
2022-10-01 23:43:00 +08:00
//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);
2022-09-27 21:06:25 +08:00
std::vector<EntityID> createdEntities{};
//Create Entities
2022-10-01 23:43:00 +08:00
for (auto it = entities.begin(); it != entities.end(); ++it)
2022-09-26 21:08:59 +08:00
{
2022-09-27 21:06:25 +08:00
DeserializeEntity(it, (*it), createdEntities);
}
//Initialize Entity
2022-10-01 23:43:00 +08:00
auto entityVecIt = createdEntities.begin();
for (auto it = entities.begin(); it != entities.end(); ++it)
2022-09-27 21:06:25 +08:00
{
2022-10-01 23:43:00 +08:00
InitializeEntity(*it, *entityVecIt++);
2022-09-26 21:08:59 +08:00
}
2022-09-26 23:51:20 +08:00
}
2022-09-26 21:08:59 +08:00
2022-10-19 01:03:32 +08:00
void SHSerialization::EmitEntity(SHSceneNode* entityNode, YAML::Emitter& out)
{
out << SerializeEntityToNode(entityNode);
auto const& children = entityNode->GetChildren();
for(auto const& child : children)
{
EmitEntity(child, out);
}
}
2022-09-27 21:06:25 +08:00
2022-10-19 01:03:32 +08:00
std::string SHSerialization::SerializeEntitiesToString(std::vector<EntityID> const& entities)
2022-09-26 23:51:20 +08:00
{
2022-10-19 01:03:32 +08:00
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<char>(out.c_str());
2022-09-26 23:51:20 +08:00
}
2022-09-26 21:08:59 +08:00
2022-09-26 23:51:20 +08:00
void SHSerialization::SerializeEntityToFile(std::filesystem::path const& path)
{
}
YAML::Node SHSerialization::SerializeEntityToNode(SHSceneNode* sceneNode)
{
YAML::Node node;
2022-09-27 21:06:25 +08:00
auto eid = sceneNode->GetEntityID();
auto entity = SHEntityManager::GetEntityByID(eid);
if (!sceneNode || !entity)
2022-09-26 21:08:59 +08:00
{
2022-09-26 23:51:20 +08:00
node = YAML::Null;
return node;
}
node.SetStyle(YAML::EmitterStyle::Block);
2022-09-27 21:06:25 +08:00
node[EIDNode] = eid;
node[EntityNameNode] = entity->name;
node[IsActiveNode] = sceneNode->IsActive();
2022-09-26 23:51:20 +08:00
auto const& children = sceneNode->GetChildren();
2022-09-27 21:06:25 +08:00
node[NumberOfChildrenNode] = children.size();
2022-09-26 21:08:59 +08:00
2022-09-26 23:51:20 +08:00
YAML::Node components;
2022-09-26 21:08:59 +08:00
2022-09-26 23:51:20 +08:00
if (const auto transform = SHComponentManager::GetComponent_s<SHTransformComponent>(eid))
{
components[rttr::type::get<SHTransformComponent>().get_name().data()] = SHSerializationHelper::SerializeComponentToNode(transform);
2022-09-26 21:08:59 +08:00
}
2022-10-19 01:03:32 +08:00
if (const auto renderable = SHComponentManager::GetComponent_s<SHRenderable>(eid))
{
components[rttr::type::get<SHRenderable>().get_name().data()] = SHSerializationHelper::SerializeComponentToNode(renderable);
}
if (const auto rigidbody = SHComponentManager::GetComponent_s<SHRigidBodyComponent>(eid))
{
components[rttr::type::get<SHRigidBodyComponent>().get_name().data()] = SHSerializationHelper::SerializeComponentToNode(rigidbody);
}
2022-09-27 21:06:25 +08:00
node[ComponentsNode] = components;
YAML::Node scripts;
SHSystemManager::GetSystem<SHScriptEngine>()->SerialiseScripts(eid, scripts);
node[ScriptsNode] = scripts;
2022-09-26 23:51:20 +08:00
return node;
2022-09-26 21:08:59 +08:00
}
2022-09-27 21:06:25 +08:00
template<typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>
2022-10-01 23:43:00 +08:00
std::optional<ComponentTypeID> GetComponentID(YAML::Node const& componentNode)
2022-09-27 21:06:25 +08:00
{
2022-10-01 23:43:00 +08:00
if (componentNode[rttr::type::get<ComponentType>().get_name().data()])
return { SHFamilyID<SHComponent>::GetID<ComponentType>() };
2022-09-27 21:06:25 +08:00
else
return std::nullopt;
}
std::vector<ComponentTypeID> SHSerialization::GetComponentIDList(YAML::Node const& componentsNode)
{
std::vector<ComponentTypeID> componentIDList;
auto id = GetComponentID<SHTransformComponent>(componentsNode);
2022-10-01 23:43:00 +08:00
if (id.has_value())
componentIDList.push_back(id.value());
2022-10-19 01:03:32 +08:00
2022-10-01 23:43:00 +08:00
id = GetComponentID<SHRenderable>(componentsNode);
if (id.has_value())
2022-09-27 21:06:25 +08:00
componentIDList.push_back(id.value());
2022-10-19 01:03:32 +08:00
id = GetComponentID<SHRigidBodyComponent>(componentsNode);
if (id.has_value())
componentIDList.push_back(id.value());
2022-09-27 21:06:25 +08:00
return componentIDList;
}
2022-10-01 23:43:00 +08:00
void SHSerialization::InitializeEntity(YAML::Node const& entityNode, EntityID const& eid)
{
2022-10-19 01:03:32 +08:00
auto const componentsNode = entityNode[ComponentsNode];
if (!componentsNode)
2022-10-01 23:43:00 +08:00
return;
SHSerializationHelper::InitializeComponentFromNode<SHTransformComponent>(componentsNode, eid);
}
2022-09-26 21:08:59 +08:00
}