Scene Serialization
- Scenes can now be serialized and de-serialized into .yaml files - Added yaml-cpp as Dependency
This commit is contained in:
parent
a58d3a75d3
commit
74a6035c32
17 changed files with 336 additions and 19 deletions
3
.gitmodules
vendored
3
.gitmodules
vendored
|
@ -16,3 +16,6 @@
|
|||
[submodule "Dependencies/ShaderConductor"]
|
||||
path = Dependencies/ShaderConductor
|
||||
url = https://github.com/Light3039/shaderconductor
|
||||
[submodule "Dependencies/yaml-cpp"]
|
||||
path = Dependencies/yaml-cpp
|
||||
url = https://github.com/jbeder/yaml-cpp
|
||||
|
|
|
@ -39,6 +39,7 @@ add_subdirectory(${DEPENDENCIES_DIR}glm/)
|
|||
add_subdirectory(${DEPENDENCIES_DIR}entt/)
|
||||
add_subdirectory(${DEPENDENCIES_DIR}imgui/)
|
||||
add_subdirectory(${DEPENDENCIES_DIR}stb_image/)
|
||||
add_subdirectory(${DEPENDENCIES_DIR}yaml-cpp/)
|
||||
|
||||
target_link_libraries(Engine glad)
|
||||
target_link_libraries(Engine glfw)
|
||||
|
@ -46,6 +47,7 @@ target_link_libraries(Engine spdlog)
|
|||
target_link_libraries(Engine imgui)
|
||||
target_link_libraries(Engine stb_image)
|
||||
target_link_libraries(Engine ShaderConductor)
|
||||
target_link_libraries(Engine yaml-cpp)
|
||||
|
||||
target_link_libraries(imgui glad)
|
||||
target_link_libraries(imgui glfw)
|
||||
|
|
1
Dependencies/yaml-cpp
vendored
Submodule
1
Dependencies/yaml-cpp
vendored
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit 0d9dbcfe8c0df699aed8ae050dddaca614178fb1
|
|
@ -48,6 +48,7 @@ ${DEPENDENCIES_DIR}imgui/
|
|||
${DEPENDENCIES_DIR}spdlog/include/
|
||||
${DEPENDENCIES_DIR}stb_image/
|
||||
${DEPENDENCIES_DIR}ShaderConductor/Include/
|
||||
${DEPENDENCIES_DIR}yaml-cpp/include/
|
||||
)
|
||||
|
||||
source_group(TREE ${ENGINE_DIR} FILES ${ENGINE_ALL_FILES} ${ENGINE_RES_FILES})
|
||||
|
|
|
@ -17,9 +17,11 @@ namespace Light {
|
|||
public:
|
||||
Camera() = default;
|
||||
|
||||
const glm::mat4& GetProjection() const { return m_Projection; }
|
||||
inline const glm::mat4& GetProjection() const { return m_Projection; }
|
||||
|
||||
const glm::vec4& GetBackgroundColor() const { return m_BackgroundColor; }
|
||||
inline const glm::vec4& GetBackgroundColor() const { return m_BackgroundColor; }
|
||||
|
||||
inline void SetBackgroundColor(const glm::vec4& color) { m_BackgroundColor = color; }
|
||||
};
|
||||
|
||||
}
|
|
@ -11,15 +11,15 @@
|
|||
|
||||
namespace Light {
|
||||
|
||||
Ref<Texture>Texture::Create(unsigned int width, unsigned int height, unsigned int components, unsigned char* pixels, Ref<SharedContext> sharedContext)
|
||||
Ref<Texture>Texture::Create(unsigned int width, unsigned int height, unsigned int components, unsigned char* pixels, Ref<SharedContext> sharedContext, const std::string& filePath)
|
||||
{
|
||||
switch (GraphicsContext::GetGraphicsAPI())
|
||||
{
|
||||
case GraphicsAPI::OpenGL:
|
||||
return CreateRef<glTexture>(width, height, components, pixels);
|
||||
return CreateRef<glTexture>(width, height, components, pixels, filePath);
|
||||
|
||||
case GraphicsAPI::DirectX: LT_WIN(
|
||||
return CreateRef<dxTexture>(width, height, components, pixels, std::static_pointer_cast<dxSharedContext>(sharedContext));)
|
||||
return CreateRef<dxTexture>(width, height, components, pixels, std::static_pointer_cast<dxSharedContext>(sharedContext), filePath);)
|
||||
|
||||
default:
|
||||
LT_ENGINE_ASSERT(false, "Texture::Create: invalid/unsupported 'GraphicsAPI' {}", GraphicsContext::GetGraphicsAPI());
|
||||
|
@ -27,4 +27,9 @@ namespace Light {
|
|||
}
|
||||
}
|
||||
|
||||
Texture::Texture(const std::string& filePath):
|
||||
m_FilePath(filePath)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
|
@ -10,7 +10,7 @@ namespace Light {
|
|||
class Texture
|
||||
{
|
||||
public:
|
||||
static Ref<Texture> Create(unsigned int width, unsigned int height, unsigned int components, unsigned char* pixels, Ref<SharedContext> sharedContext);
|
||||
static Ref<Texture> Create(unsigned int width, unsigned int height, unsigned int components, unsigned char* pixels, Ref<SharedContext> sharedContext, const std::string& filePath);
|
||||
|
||||
Texture(const Texture&) = delete;
|
||||
Texture& operator=(const Texture&) = delete;
|
||||
|
@ -19,8 +19,13 @@ namespace Light {
|
|||
|
||||
virtual void Bind(unsigned int slot = 0) = 0;
|
||||
|
||||
inline const std::string& GetFilePath() const { return m_FilePath; }
|
||||
|
||||
protected:
|
||||
Texture() = default;
|
||||
Texture(const std::string& filePath);
|
||||
|
||||
protected:
|
||||
std::string m_FilePath;
|
||||
};
|
||||
|
||||
}
|
|
@ -16,8 +16,11 @@ namespace Light {
|
|||
|
||||
class Scene
|
||||
{
|
||||
private:
|
||||
friend class Entity;
|
||||
friend class SceneSerializer;
|
||||
friend class SceneHierarchyPanel;
|
||||
|
||||
private:
|
||||
entt::registry m_Registry;
|
||||
|
||||
|
|
|
@ -55,7 +55,7 @@ namespace Light {
|
|||
ImageFileHandle imgFile = FileManager::ReadImageFile(path, desiredComponents);
|
||||
|
||||
// create texture
|
||||
m_Textures[name] = Ref<Texture>(Texture::Create(imgFile.GetWidth(), imgFile.GetHeight(), imgFile.GetComponents(), imgFile.GetData(), GraphicsContext::GetSharedContext()));
|
||||
m_Textures[name] = Ref<Texture>(Texture::Create(imgFile.GetWidth(), imgFile.GetHeight(), imgFile.GetComponents(), imgFile.GetData(), GraphicsContext::GetSharedContext(), path) );
|
||||
|
||||
// free file
|
||||
imgFile.Release();
|
||||
|
@ -71,5 +71,4 @@ namespace Light {
|
|||
|
||||
m_Textures[name] = nullptr;
|
||||
}
|
||||
|
||||
}
|
||||
|
256
Engine/src/Engine/Utility/Serializer.cpp
Normal file
256
Engine/src/Engine/Utility/Serializer.cpp
Normal file
|
@ -0,0 +1,256 @@
|
|||
#include "ltpch.h"
|
||||
#include "Serializer.h"
|
||||
|
||||
#include "Scene/Components.h"
|
||||
|
||||
#include "Graphics/Texture.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() != 3)
|
||||
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 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>& 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;
|
||||
m_Scene->m_Registry.each([&](auto entityID)
|
||||
{
|
||||
Entity entity = { entityID, m_Scene.get() };
|
||||
if (!entity)
|
||||
return;
|
||||
|
||||
SerializeEntity(out, entity);
|
||||
});
|
||||
out << YAML::EndSeq;
|
||||
out << YAML::EndMap;
|
||||
|
||||
std::filesystem::create_directories(filePath.substr(0ull, filePath.find_last_of('/')));
|
||||
|
||||
std::ofstream fout(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<std::string>();
|
||||
LT_ENGINE_TRACE("SceneSerializer::Deserialize: Deserializing scene: '{}'", sceneName);
|
||||
|
||||
auto entities = data["Entities"];
|
||||
if (entities)
|
||||
{
|
||||
for (auto entity : entities)
|
||||
{
|
||||
uint64_t uuid = entity["Entity"].as<uint64_t>(); // #todo
|
||||
|
||||
std::string name;
|
||||
auto tagComponent = entity["TagComponent"];
|
||||
if (tagComponent)
|
||||
name = tagComponent["Tag"].as<std::string>();
|
||||
|
||||
LT_ENGINE_TRACE("SceneSerializer::Deserialize: Deserialized entity '{}' : '{}'", uuid, name);
|
||||
|
||||
Entity deserializedEntity = m_Scene->CreateEntity(name);
|
||||
|
||||
auto transformComponent = entity["TransformComponent"];
|
||||
if (transformComponent)
|
||||
{
|
||||
auto& entityTransforomComponent = deserializedEntity.GetComponent<TransformComponent>();
|
||||
|
||||
entityTransforomComponent.translation = transformComponent["Translation"].as<glm::vec3>();
|
||||
entityTransforomComponent.rotation = transformComponent["Rotation"].as<glm::vec3>();
|
||||
entityTransforomComponent.scale = transformComponent["Scale"].as<glm::vec3>();
|
||||
}
|
||||
|
||||
auto cameraComponent = entity["CameraComponent"];
|
||||
if(cameraComponent)
|
||||
{
|
||||
auto& entityCameraComponent = deserializedEntity.AddComponent<CameraComponent>();
|
||||
|
||||
auto& cameraSpecifications = cameraComponent["Camera"];
|
||||
entityCameraComponent.camera.SetProjectionType((SceneCamera::ProjectionType)cameraSpecifications["ProjectionType"].as<int>());
|
||||
|
||||
entityCameraComponent.camera.SetOrthographicSize(cameraSpecifications["OrthographicsSize"].as<float>());
|
||||
entityCameraComponent.camera.SetOrthographicNearPlane(cameraSpecifications["OrthographicsNearPlane"].as<float>());
|
||||
entityCameraComponent.camera.SetOrthographicFarPlane(cameraSpecifications["OrthographicsFarPlane"].as<float>());
|
||||
|
||||
entityCameraComponent.camera.SetPerspectiveVerticalFOV(cameraSpecifications["PerspectiveVerticalFOV"].as<float>());
|
||||
entityCameraComponent.camera.SetPerspectiveNearPlane(cameraSpecifications["PerspectiveNearPlane"].as<float>());
|
||||
entityCameraComponent.camera.SetPerspectiveFarPlane(cameraSpecifications["PerspectiveFarPlane"].as<float>());
|
||||
|
||||
entityCameraComponent.camera.SetBackgroundColor(cameraSpecifications["BackgroundColor"].as<glm::vec4>());
|
||||
|
||||
entityCameraComponent.isPrimary = cameraComponent["IsPrimary"].as<bool>();
|
||||
}
|
||||
|
||||
// #todo: figure out texture de-serialization
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void SceneSerializer::SerializeBinary(const std::string& filePath)
|
||||
{
|
||||
LT_ENGINE_ERROR("SceneSerializer::SerializeRuntime: NO_IMPLEMENT");
|
||||
}
|
||||
|
||||
bool SceneSerializer::DeserializeBinary(const std::string& filePath)
|
||||
{
|
||||
LT_ENGINE_ERROR("SceneSerializer::DeserializeBinary: NO_IMPLEMENT");
|
||||
return false;
|
||||
}
|
||||
|
||||
void SceneSerializer::SerializeEntity(YAML::Emitter& out, Entity entity)
|
||||
{
|
||||
out << YAML::BeginMap; // entity
|
||||
out << YAML::Key << "Entity" << YAML::Value << "69696969696969"; // dummy uuid
|
||||
out << YAML::EndMap; // entity
|
||||
|
||||
if (entity.HasComponent<TagComponent>())
|
||||
{
|
||||
out << YAML::Key << "TagComponent";
|
||||
out << YAML::BeginMap; // tag component
|
||||
|
||||
auto& tagComponent = entity.GetComponent<TagComponent>().tag;
|
||||
out << YAML::Key << "Tag" << YAML::Value << tagComponent;
|
||||
|
||||
out << YAML::EndMap; // tag component
|
||||
}
|
||||
|
||||
if (entity.HasComponent<TransformComponent>())
|
||||
{
|
||||
out << YAML::Key << "TransformComponent";
|
||||
out << YAML::BeginMap; // transform component
|
||||
|
||||
auto& transformComponent = entity.GetComponent<TransformComponent>();
|
||||
|
||||
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.HasComponent<SpriteRendererComponent>())
|
||||
{
|
||||
out << YAML::Key << "SpriteRendererComponent";
|
||||
out << YAML::BeginMap; // sprite renderer component;
|
||||
|
||||
auto& spriteRendererComponent = entity.GetComponent<SpriteRendererComponent>();
|
||||
|
||||
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.HasComponent<NativeScriptComponent>())
|
||||
|
||||
if (entity.HasComponent<CameraComponent>())
|
||||
{
|
||||
out << YAML::Key << "CameraComponent";
|
||||
out << YAML::BeginMap; // camera component
|
||||
|
||||
auto& cameraComponent = entity.GetComponent<CameraComponent>();
|
||||
|
||||
out << YAML::Key << "Camera" << YAML::Value;
|
||||
out << YAML::BeginMap; // camera
|
||||
out << YAML::Key << "OrthographicSize" << YAML::Value << cameraComponent.camera.GetOrthographicSize();
|
||||
out << YAML::Key << "OrthographicFarPlane" << YAML::Value << cameraComponent.camera.GetOrthographicFarPlane();
|
||||
out << YAML::Key << "OrthographicNearPlane" << YAML::Value << cameraComponent.camera.GetOrthographicNearPlane();
|
||||
out << YAML::Key << "PerspectiveVerticalFOV" << YAML::Value << cameraComponent.camera.GetPerspectiveVerticalFOV();
|
||||
out << YAML::Key << "PerspectiveFarPlane" << YAML::Value << cameraComponent.camera.GetPerspectiveFarPlane();
|
||||
out << YAML::Key << "PerspectiveNearPlane" << YAML::Value << cameraComponent.camera.GetPerspectiveNearPlane();
|
||||
out << YAML::Key << "ProjectionType" << YAML::Value << (int)cameraComponent.camera.GetProjectionType();
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
}
|
31
Engine/src/Engine/Utility/Serializer.h
Normal file
31
Engine/src/Engine/Utility/Serializer.h
Normal file
|
@ -0,0 +1,31 @@
|
|||
#pragma once
|
||||
|
||||
#include "Base/Base.h"
|
||||
|
||||
#include "Scene/Scene.h"
|
||||
#include "Scene/Entity.h"
|
||||
|
||||
#include <yaml-cpp/yaml.h>
|
||||
|
||||
namespace Light {
|
||||
|
||||
class SceneSerializer
|
||||
{
|
||||
public:
|
||||
SceneSerializer(const Ref<Scene>& scene);
|
||||
|
||||
void Serialize(const std::string& filePath);
|
||||
bool Deserialize(const std::string& filePath);
|
||||
|
||||
void SerializeBinary(const std::string& filePath);
|
||||
bool DeserializeBinary(const std::string& filePath);
|
||||
|
||||
private:
|
||||
void SerializeEntity(YAML::Emitter& out, Entity entity);
|
||||
|
||||
private:
|
||||
Ref<Scene> m_Scene;
|
||||
};
|
||||
|
||||
|
||||
}
|
|
@ -4,11 +4,12 @@
|
|||
|
||||
namespace Light {
|
||||
|
||||
dxTexture::dxTexture(unsigned int width, unsigned int height, unsigned int components, unsigned char* pixels, Ref<dxSharedContext> sharedContext)
|
||||
: m_Context(sharedContext),
|
||||
m_Texture2D(nullptr),
|
||||
m_ShaderResourceView(nullptr),
|
||||
m_SamplerState(nullptr)
|
||||
dxTexture::dxTexture(unsigned int width, unsigned int height, unsigned int components, unsigned char* pixels, Ref<dxSharedContext> sharedContext, const std::string& filePath):
|
||||
Texture(filePath),
|
||||
m_Context(sharedContext),
|
||||
m_Texture2D(nullptr),
|
||||
m_ShaderResourceView(nullptr),
|
||||
m_SamplerState(nullptr)
|
||||
{
|
||||
// texture2d desc
|
||||
D3D11_TEXTURE2D_DESC t2dDesc = {};
|
||||
|
|
|
@ -21,7 +21,7 @@ namespace Light {
|
|||
Microsoft::WRL::ComPtr<ID3D11SamplerState> m_SamplerState;
|
||||
|
||||
public:
|
||||
dxTexture(unsigned int width, unsigned int height, unsigned int components, unsigned char* pixels, Ref<dxSharedContext> sharedContext);
|
||||
dxTexture(unsigned int width, unsigned int height, unsigned int components, unsigned char* pixels, Ref<dxSharedContext> sharedContext, const std::string& filePath);
|
||||
|
||||
void Bind(unsigned int slot = 0u) override;
|
||||
};
|
||||
|
|
|
@ -5,9 +5,11 @@
|
|||
|
||||
namespace Light {
|
||||
|
||||
glTexture::glTexture(unsigned int width, unsigned int height, unsigned int components, unsigned char* pixels)
|
||||
: m_TextureID(NULL)
|
||||
glTexture::glTexture(unsigned int width, unsigned int height, unsigned int components, unsigned char* pixels, const std::string& filePath):
|
||||
Texture(filePath),
|
||||
m_TextureID(NULL)
|
||||
{
|
||||
|
||||
// create texture
|
||||
glCreateTextures(GL_TEXTURE_2D, 1, &m_TextureID);
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ namespace Light {
|
|||
unsigned int m_TextureID;
|
||||
|
||||
public:
|
||||
glTexture(unsigned int width, unsigned int height, unsigned int components, unsigned char* pixels);
|
||||
glTexture(unsigned int width, unsigned int height, unsigned int components, unsigned char* pixels, const std::string& filePath);
|
||||
~glTexture();
|
||||
|
||||
void Bind(unsigned int slot = 0u) override;
|
||||
|
|
|
@ -21,6 +21,7 @@ ${DEPENDENCIES_DIR}glm/
|
|||
${DEPENDENCIES_DIR}imgui/
|
||||
${DEPENDENCIES_DIR}spdlog/include
|
||||
${DEPENDENCIES_DIR}stb_image/
|
||||
${DEPENDENCIES_DIR}yaml-cpp/include
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#include "EditorLayer.h"
|
||||
|
||||
#include "Utility/Serializer.h"
|
||||
|
||||
namespace Light {
|
||||
|
||||
EditorLayer::EditorLayer(const std::string& name)
|
||||
|
@ -19,6 +21,9 @@ namespace Light {
|
|||
|
||||
// for native script components
|
||||
m_Scene->OnCreate();
|
||||
|
||||
SceneSerializer serializer(m_Scene);
|
||||
serializer.Serialize("assets/scenes/test.yaml");
|
||||
}
|
||||
|
||||
void EditorLayer::OnUpdate(float deltaTime)
|
||||
|
|
Loading…
Add table
Reference in a new issue