391 lines
15 KiB
C++
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;
|
|
}
|
|
}
|