#include #include #include #include namespace YAML { template<> struct convert { 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(); rhs.y = node[1].as(); rhs.z = node[2].as(); return true; } }; template<> struct convert { 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(); rhs.y = node[1].as(); rhs.z = node[2].as(); rhs.w = node[3].as(); return true; } }; } // namespace YAML namespace Light { static 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; } static 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): m_scene(scene) { } void SceneSerializer::serialize(const std::string &filePath) { YAML::Emitter out; out << YAML::BeginMap; // Scene out << YAML::Key << "Scene" << YAML::Value << "Untitled"; out << YAML::Key << "Entities" << YAML::Value << YAML::BeginSeq; for (auto [entityID, storage] : m_scene->m_registry.storage()) { Entity entity = { static_cast(entityID), m_scene.get() }; if (!entity.is_valid()) return; serialize_entity(out, entity); }; out << YAML::EndSeq; out << YAML::EndMap; std::filesystem::create_directories(filePath.substr(0ull, filePath.find_last_of('\\'))); std::ofstream fout(filePath); if (!fout.is_open()) lt_log(trace, "Failed to create fout at: {}", filePath); fout << out.c_str(); } bool SceneSerializer::deserialize(const std::string &filePath) { std::ifstream stream(filePath); std::stringstream ss; ss << stream.rdbuf(); YAML::Node data = YAML::Load(ss.str()); if (!data["Scene"]) return false; std::string sceneName = data["Scene"].as(); lt_log(trace, "Deserializing scene: '{}'", sceneName); auto entities = data["Entities"]; if (entities) { /* #TEMPORARY SOLUTION# */ std::unordered_set texturePaths; /* #TEMPORARY SOLUTION# */ for (auto entity : entities) { uint64_t uuid = entity["entity"].as(); // #todo std::string name; auto tagComponent = entity["TagComponent"]; if (tagComponent) name = tagComponent["Tag"].as(); lt_log(trace, "Deserialized entity '{}' : '{}'", uuid, name); Entity deserializedEntity = m_scene->create_entity_with_uuid(name, uuid); TagComponent gg = deserializedEntity.GetComponent(); lt_log(trace, gg.tag); auto transformComponent = entity["TransformComponent"]; if (transformComponent) { auto &entityTransforomComponent = deserializedEntity .GetComponent(); entityTransforomComponent.translation = transformComponent["Translation"] .as(); entityTransforomComponent.rotation = transformComponent["Rotation"].as(); entityTransforomComponent.scale = transformComponent["Scale"].as(); } /* #TEMPORARY SOLUTION# */ auto spriteRendererComponent = entity["SpriteRendererComponent"]; if (spriteRendererComponent) { auto &entitySpriteRendererComponent = deserializedEntity .AddComponent(); entitySpriteRendererComponent.tint = spriteRendererComponent["Tint"].as( ); std::string texturePath = spriteRendererComponent["Texture"].as(); if (!texturePaths.contains(texturePath)) { ResourceManager::load_texture(texturePath, texturePath); texturePaths.insert(texturePath); } entitySpriteRendererComponent.texture = ResourceManager::get_texture(texturePath); } /* #TEMPORARY SOLUTION# */ auto cameraComponent = entity["CameraComponent"]; if (cameraComponent) { auto &entityCameraComponent = deserializedEntity.AddComponent(); const auto &cameraSpecifications = cameraComponent["Camera"]; entityCameraComponent.camera.set_projection_type( (SceneCamera::ProjectionType)cameraSpecifications["ProjectionType"].as() ); entityCameraComponent.camera.set_orthographic_size( cameraSpecifications["OrthographicSize"].as() ); entityCameraComponent.camera.set_orthographic_near_plane( cameraSpecifications["OrthographicNearPlane"].as() ); entityCameraComponent.camera.set_orthographic_far_plane( cameraSpecifications["OrthographicFarPlane"].as() ); entityCameraComponent.camera.set_perspective_vertical_fov( cameraSpecifications["PerspectiveVerticalFOV"].as() ); entityCameraComponent.camera.set_perspective_near_plane( cameraSpecifications["PerspectiveNearPlane"].as() ); entityCameraComponent.camera.set_perspective_far_plane( cameraSpecifications["PerspectiveFarPlane"].as() ); entityCameraComponent.camera.set_background_color( cameraSpecifications["BackgroundColor"].as() ); entityCameraComponent.isPrimary = cameraComponent["IsPrimary"].as(); } } return true; } return false; } void SceneSerializer::serialize_binary(const std::string &filePath) { lt_log(err, "NO_IMPLEMENT"); } bool SceneSerializer::deserialize_binary(const std::string &filePath) { lt_log(err, "NO_IMPLEMENT"); return false; } void SceneSerializer::serialize_entity(YAML::Emitter &out, Entity entity) { out << YAML::BeginMap; // entity out << YAML::Key << "entity" << YAML::Value << entity.get_uuid(); // dummy uuid if (entity.has_component()) { out << YAML::Key << "TagComponent"; out << YAML::BeginMap; // tag component auto &tagComponent = entity.GetComponent().tag; out << YAML::Key << "Tag" << YAML::Value << tagComponent; out << YAML::EndMap; // tag component } if (entity.has_component()) { out << YAML::Key << "TransformComponent"; out << YAML::BeginMap; // transform component auto &transformComponent = entity.GetComponent(); out << YAML::Key << "Translation" << YAML::Value << transformComponent.translation; out << YAML::Key << "Rotation" << YAML::Value << transformComponent.rotation; out << YAML::Key << "Scale" << YAML::Value << transformComponent.scale; out << YAML::EndMap; // transform component; } if (entity.has_component()) { out << YAML::Key << "SpriteRendererComponent"; out << YAML::BeginMap; // sprite renderer component; auto &spriteRendererComponent = entity.GetComponent(); out << YAML::Key << "Texture" << YAML::Value << spriteRendererComponent.texture->GetFilePath(); out << YAML::Key << "Tint" << YAML::Value << spriteRendererComponent.tint; out << YAML::EndMap; // sprite renderer component } // #todo: // if(entity.has_component()) if (entity.has_component()) { out << YAML::Key << "CameraComponent"; out << YAML::BeginMap; // camera component auto &cameraComponent = entity.GetComponent(); out << YAML::Key << "Camera" << YAML::Value; out << YAML::BeginMap; // camera out << YAML::Key << "OrthographicSize" << YAML::Value << cameraComponent.camera.get_orthographic_size(); out << YAML::Key << "OrthographicFarPlane" << YAML::Value << cameraComponent.camera.get_orthographic_far_plane(); out << YAML::Key << "OrthographicNearPlane" << YAML::Value << cameraComponent.camera.get_orthographic_near_plane(); out << YAML::Key << "PerspectiveVerticalFOV" << YAML::Value << cameraComponent.camera.get_perspective_vertical_fov(); out << YAML::Key << "PerspectiveFarPlane" << YAML::Value << cameraComponent.camera.get_perspective_far_plane(); out << YAML::Key << "PerspectiveNearPlane" << YAML::Value << cameraComponent.camera.get_perspective_near_plane(); out << YAML::Key << "ProjectionType" << YAML::Value << (int)cameraComponent.camera.get_projection_type(); out << YAML::Key << "BackgroundColor" << YAML::Value << cameraComponent.camera.GetBackgroundColor(); out << YAML::EndMap; // camera out << YAML::Key << "IsPrimary" << YAML::Value << cameraComponent.isPrimary; out << YAML::EndMap; // camera component } out << YAML::EndMap; // entity } } // namespace Light