Files
OpenEngine/open_engine/src/open_engine/scene/scene_serializer.cpp
2026-03-08 11:38:46 +01:00

391 lines
15 KiB
C++

#include <cstdint>
#include <pch.hpp>
#include "core.hpp"
#include <scene/scene_serializer.hpp>
#include "renderer/renderer3d.hpp"
#include "scene/components.hpp"
#include "scene/entity.hpp"
#include <fstream>
#include <yaml-cpp/emittermanip.h>
#include <yaml-cpp/yaml.h>
namespace YAML {
template<>
struct convert<glm::vec3>
{
static Node encode(const glm::vec3& rhs)
{
Node node;
node.push_back(rhs.x);
node.push_back(rhs.y);
node.push_back(rhs.z);
return node;
}
static bool decode(const Node& node, glm::vec3& rhs)
{
if (!node.IsSequence() || node.size() != 3)
return false;
rhs.x = node[0].as<float>();
rhs.y = node[1].as<float>();
rhs.z = node[2].as<float>();
return true;
}
};
template<>
struct convert<glm::vec4>
{
static Node encode(const glm::vec4& rhs)
{
Node node;
node.push_back(rhs.x);
node.push_back(rhs.y);
node.push_back(rhs.z);
node.push_back(rhs.w);
return node;
}
static bool decode(const Node& node, glm::vec4& rhs)
{
if (!node.IsSequence() || node.size() != 4)
return false;
rhs.x = node[0].as<float>();
rhs.y = node[1].as<float>();
rhs.z = node[2].as<float>();
rhs.w = node[3].as<float>();
return true;
}
};
}
namespace OpenEngine {
YAML::Emitter& operator<<(YAML::Emitter& out, const glm::vec3& v)
{
out << YAML::Flow;
out << YAML::BeginSeq << v.x << v.y << v.z << YAML::EndSeq;
return out;
}
YAML::Emitter& operator<<(YAML::Emitter& out, const glm::vec4& v)
{
out << YAML::Flow;
out << YAML::BeginSeq << v.x << v.y << v.z << v.w << YAML::EndSeq;
return out;
}
SceneSerializer::SceneSerializer(const Ref<Scene>& scene)
: context(scene)
{
}
static void SerializeEntity(YAML::Emitter& out, Entity entity)
{
OE_CORE_ASSERT(entity.HasComponent<IDComponent>(), "Entity is missing UUID.");
out << YAML::BeginMap;
out << YAML::Key << "Entity" << YAML::Value << entity.GetUUID(); // Needs random
if (entity.HasComponent<TagComponent>()) {
out << YAML::Key << "TagComponent";
out << YAML::BeginMap; // TagComponent
auto& tag = entity.GetComponents<TagComponent>().tag;
out << YAML::Key << "Tag" << YAML::Value << tag;
out << YAML::EndMap; // TagComponent
}
if (entity.HasComponent<TransformComponent>()) {
out << YAML::Key << "TransformComponent";
out << YAML::BeginMap; // TransformComponent
auto& tc = entity.GetComponents<TransformComponent>();
out << YAML::Key << "Translation" << YAML::Value << tc.translation;
out << YAML::Key << "Rotation" << YAML::Value << tc.rotation;
out << YAML::Key << "Scale" << YAML::Value << tc.scale;
out << YAML::EndMap; // TransformComponent
}
if (entity.HasComponent<CameraComponent>()) {
out << YAML::Key << "CameraComponent";
out << YAML::BeginMap; // CameraComponent
auto& cameraComponent = entity.GetComponents<CameraComponent>();
auto& camera = cameraComponent.camera;
out << YAML::Key << "Camera" << YAML::Value;
out << YAML::BeginMap; // Camera
out << YAML::Key << "ProjectionType" << YAML::Value << (int)camera.GetProjectionType();
out << YAML::Key << "PerspectiveFOV" << YAML::Value << camera.GetVerticalFov();
out << YAML::Key << "PerspectiveNear" << YAML::Value << camera.GetPerspectiveNearClip();
out << YAML::Key << "PerspectiveFar" << YAML::Value << camera.GetPerspectiveFarClip();
out << YAML::Key << "OrthographicSize" << YAML::Value << camera.GetOrthographicSize();
out << YAML::Key << "OrthographicNear" << YAML::Value << camera.GetOrthographicNearClip();
out << YAML::Key << "OrthographicFar" << YAML::Value << camera.GetOrthographicFarClip();
out << YAML::EndMap; // Camera
out << YAML::Key << "Primary" << YAML::Value << cameraComponent.primary;
out << YAML::Key << "FixedAspectRatio" << YAML::Value << cameraComponent.fixed_aspect_ratio;
out << YAML::EndMap; // CameraComponent
}
if (entity.HasComponent<SpriteRendererComponent>()) {
out << YAML::Key << "SpriteRendererComponent";
out << YAML::BeginMap; // SpriteRendererComponent
auto& spriteRendererComponent = entity.GetComponents<SpriteRendererComponent>();
out << YAML::Key << "Color" << YAML::Value << spriteRendererComponent.color;
out << YAML::EndMap; // SpriteRendererComponent
}
if (entity.HasComponent<MeshComponent>()) {
out << YAML::Key << "MeshComponent";
out << YAML::BeginMap; // MeshComponent
auto& mesh_component = entity.GetComponents<MeshComponent>();
out << YAML::Key << "MeshType" << YAML::Value << (int)mesh_component.primitive_type;
out << YAML::EndMap; // MeshComponent
}
if (entity.HasComponent<MaterialComponent>()) {
out << YAML::Key << "MaterialComponent";
out << YAML::BeginMap; // MaterialComponent
auto& material = entity.GetComponents<MaterialComponent>().material;
out << YAML::Key << "Albedo" << YAML::Value << material.albedo;
out << YAML::Key << "Roughness" << YAML::Value << material.roughness;
out << YAML::Key << "Metalic" << YAML::Value << material.metallic;
out << YAML::Key << "AmbiantStrength" << YAML::Value << material.ambient_strength;
out << YAML::Key << "SpecularStrength" << YAML::Value << material.specular_strength;
out << YAML::EndMap; // MaterialComponent
}
if (entity.HasComponent<PhysicsBodyComponent>()) {
out << YAML::Key << "PhysicsBodyComponent";
out << YAML::BeginMap; // PhysicsBodyComponent
auto& pbc = entity.GetComponents<PhysicsBodyComponent>();
out << YAML::Key << "LinearDamping" << YAML::Value << pbc.linear_damping;
out << YAML::Key << "AngularDamping" << YAML::Value << pbc.angular_damping;
out << YAML::Key << "GravityFactor" << YAML::Value << pbc.gravity_factor;
out << YAML::Key << "Restitution" << YAML::Value << pbc.restitution;
out << YAML::Key << "Friction" << YAML::Value << pbc.friction;
out << YAML::Key << "Type" << YAML::Value << pbc.type;
out << YAML::Key << "ActivationState" << YAML::Value << pbc.initial_activation_state;
out << YAML::Key << "Layer" << YAML::Value << pbc.layer;
out << YAML::EndMap; // PhysicsBodyComponent
}
if (entity.HasComponent<BoxShapeComponent>()) {
out << YAML::Key << "BoxShapeComponent";
out << YAML::BeginMap; //BoxShapeComponent
auto& bsc = entity.GetComponents<BoxShapeComponent>();
out << YAML::Key << "Size" << YAML::Value << bsc.size;
out << YAML::EndMap; //BoxShapeComponent
}
if (entity.HasComponent<SphereShapeComponent>()) {
out << YAML::Key << "SphereShapeComponent";
out << YAML::BeginMap; //SphereShapeComponent
auto& ssc = entity.GetComponents<SphereShapeComponent>();
out << YAML::Key << "Radius" << YAML::Value << ssc.radius;
out << YAML::EndMap; //SphereShapeComponent
}
if (entity.HasComponent<PlaneShapeComponent>()) {
out << YAML::Key << "PlaneShapeComponent";
out << YAML::BeginMap; //PlaneShapeComponent
auto& psc = entity.GetComponents<PlaneShapeComponent>();
out << YAML::Key << "Extent" << YAML::Value << psc.extent;
out << YAML::EndMap; //PlaneShapeComponent
}
out << YAML::EndMap;
}
void SceneSerializer::Serialize(const std::string& file_path)
{
YAML::Emitter out;
out << YAML::BeginMap;
out << YAML::Key << "Scene" << YAML::Value << "N/A";
out << YAML::Key << "Entities" << YAML::Value << YAML::BeginSeq;
for (auto entity_id : context->registry.view<entt::entity>()) {
Entity entity = { entity_id, context.get()};
if (!entity)
return;
SerializeEntity(out, entity);
}
out << YAML::EndSeq;
out << YAML::EndMap;
std::ofstream fout(file_path);
fout << out.c_str();
}
void SceneSerializer::SerializeRuntime(const std::string& file_path)
{
OE_CORE_ASSERT(false, "Not implemented yet");
}
bool SceneSerializer::Deserialize(const std::string& file_path)
{
std::ifstream stream(file_path);
std::stringstream strStream;
strStream << stream.rdbuf();
YAML::Node data = YAML::Load(strStream.str());
if (!data["Scene"])
return false;
std::string sceneName = data["Scene"].as<std::string>();
OE_CORE_TRACE("Deserializing scene '{0}'", sceneName);
auto entities = data["Entities"];
if (entities) {
for (auto entity : entities)
{
uint64_t uuid = entity["Entity"].as<uint64_t>();
std::string name;
auto tagComponent = entity["TagComponent"];
if (tagComponent)
name = tagComponent["Tag"].as<std::string>();
OE_CORE_TRACE("Deserialized entity with ID = {0}, name = {1}", uuid, name);
Entity deserializedEntity = context->CreateEntityWithUUID(uuid, name);
auto transformComponent = entity["TransformComponent"];
if (transformComponent) {
auto& tc = deserializedEntity.AddComponent<TransformComponent>();
tc.translation = transformComponent["Translation"].as<glm::vec3>();
tc.rotation = transformComponent["Rotation"].as<glm::vec3>();
tc.scale = transformComponent["Scale"].as<glm::vec3>();
}
auto cameraComponent = entity["CameraComponent"];
if (cameraComponent) {
auto& cc = deserializedEntity.AddComponent<CameraComponent>();
auto camera_props = cameraComponent["Camera"];
cc.camera.SetProjectionType((SceneCamera::ProjectionType)camera_props["ProjectionType"].as<int>());
cc.camera.SetVerticalFov(camera_props["PerspectiveFOV"].as<float>());
cc.camera.SetPerspectiveNearClip(camera_props["PerspectiveNear"].as<float>());
cc.camera.SetPerspectiveFarClip(camera_props["PerspectiveFar"].as<float>());
cc.camera.SetOrthographicSize(camera_props["OrthographicSize"].as<float>());
cc.camera.SetOrthographicNearClip(camera_props["OrthographicNear"].as<float>());
cc.camera.SetOrthographicFarClip(camera_props["OrthographicFar"].as<float>());
cc.primary = cameraComponent["Primary"].as<bool>();
cc.fixed_aspect_ratio = cameraComponent["FixedAspectRatio"].as<bool>();
}
auto spriteRendererComponent = entity["SpriteRendererComponent"];
if (spriteRendererComponent) {
auto& src = deserializedEntity.AddComponent<SpriteRendererComponent>();
src.color = spriteRendererComponent["Color"].as<glm::vec4>();
}
auto mesh_component = entity["MeshComponent"];
if (mesh_component) {
auto& mesh = deserializedEntity.AddComponent<MeshComponent>();
mesh.primitive_type = (PrimitiveType)mesh_component["MeshType"].as<int>();
switch (mesh.primitive_type) {
case OpenEngine::PrimitiveType::Quad: {
mesh.mesh = CreateQuad((uint32_t)deserializedEntity);
break;
}
case OpenEngine::PrimitiveType::Cube: {
mesh.mesh = CreateCube((uint32_t)deserializedEntity);
break;
}
default: {
OE_CORE_ASSERT(false, "No mesh");
break;
}
}
}
auto material_component = entity["MaterialComponent"];
if (material_component) {
auto& material = deserializedEntity.AddComponent<MaterialComponent>();
material.material.albedo = material_component["Albedo"].as<glm::vec4>();
material.material.roughness = material_component["Roughness"].as<float>();
material.material.metallic = material_component["Metalic"].as<float>();
material.material.ambient_strength = material_component["AmbiantStrength"].as<float>();
material.material.specular_strength = material_component["SpecularStrength"].as<float>();
}
auto physics_body_component = entity["PhysicsBodyComponent"];
if (physics_body_component) {
auto& pbc = deserializedEntity.AddComponent<PhysicsBodyComponent>();
pbc.linear_damping = physics_body_component["LinearDamping"].as<float>();
pbc.angular_damping = physics_body_component["AngularDamping"].as<float>();
pbc.gravity_factor = physics_body_component["GravityFactor"].as<float>();
pbc.restitution = physics_body_component["Restitution"].as<float>();
pbc.friction = physics_body_component["Friction"].as<float>();
pbc.type = physics_body_component["Type"].as<int>();
pbc.initial_activation_state = physics_body_component["ActivationState"].as<int>();
pbc.layer = physics_body_component["Layer"].as<int>();
}
auto box_shape_component = entity["BoxShapeComponent"];
if (box_shape_component) {
auto& bsc = deserializedEntity.AddComponent<BoxShapeComponent>();
bsc.size = box_shape_component["Size"].as<glm::vec3>();
}
auto sphere_shape_component = entity["SphereShapeComponent"];
if (sphere_shape_component) {
auto& ssc = deserializedEntity.AddComponent<SphereShapeComponent>();
ssc.radius = sphere_shape_component["Radius"].as<float>();
}
auto plane_shape_component = entity["PlaneShapeComponent"];
if (sphere_shape_component) {
auto& psc = deserializedEntity.AddComponent<PlaneShapeComponent>();
psc.extent = plane_shape_component["Extent"].as<float>();
}
}
}
return true;
}
bool SceneSerializer::DeserializeRuntime(const std::string& file_path)
{
OE_CORE_ASSERT(false, "Not implemented yet");
return false;
}
}