SHADE_Y3/SHADE_Engine/src/Serialization/SHSerializationHelper.hpp

343 lines
13 KiB
C++
Raw Normal View History

2022-09-26 21:08:59 +08:00
#pragma once
#include <yaml-cpp/yaml.h>
#include "ECS_Base/Components/SHComponent.h"
2022-09-26 21:08:59 +08:00
#include <rttr/registration>
2022-10-01 23:43:00 +08:00
#include "ECS_Base/Managers/SHComponentManager.h"
2022-09-27 07:03:31 +08:00
#include "Math/Vector/SHVec2.h"
#include "Math/Vector/SHVec3.h"
#include "Math/Vector/SHVec4.h"
#include "Resource/SHResourceManager.h"
#include "Graphics/MiddleEnd/Interface/SHRenderable.h"
#include "Graphics/MiddleEnd/Interface/SHMaterial.h"
#include "SHSerializationTools.h"
namespace YAML
{
using namespace SHADE;
template<>
struct convert<SHMaterial>
{
static constexpr std::string_view VERT_SHADER_YAML_TAG = "VertexShader";
static constexpr std::string_view FRAG_SHADER_YAML_TAG = "FragmentShader";
static constexpr std::string_view PROPS_YAML_TAG = "Properties";
static YAML::Node encode(SHMaterial const& rhs)
{
// Write Properties
YAML::Node propertiesNode;
Handle<SHShaderBlockInterface> pipelineProperties = rhs.GetShaderBlockInterface();
for (int i = 0; i < static_cast<int>(pipelineProperties->GetVariableCount()); ++i)
{
const SHShaderBlockInterface::Variable* VARIABLE = pipelineProperties->GetVariable(i);
if (!VARIABLE)
break;
const std::string& VAR_NAME = pipelineProperties->GetVariableName(i);
YAML::Node propNode;
switch (VARIABLE->type)
{
case SHADE::SHShaderBlockInterface::Variable::Type::FLOAT:
propNode = rhs.GetProperty<float>(VARIABLE->offset);
break;
case SHADE::SHShaderBlockInterface::Variable::Type::INT:
propNode = rhs.GetProperty<int>(VARIABLE->offset);
break;
case SHADE::SHShaderBlockInterface::Variable::Type::VECTOR2:
propNode = SHSerializationTools::ValToYAML(rhs.GetProperty<SHVec2>(VARIABLE->offset));
break;
case SHADE::SHShaderBlockInterface::Variable::Type::VECTOR3:
propNode = SHSerializationTools::ValToYAML(rhs.GetProperty<SHVec3>(VARIABLE->offset));
break;
case SHADE::SHShaderBlockInterface::Variable::Type::VECTOR4:
propNode = SHSerializationTools::ValToYAML(rhs.GetProperty<SHVec4>(VARIABLE->offset));
break;
case SHADE::SHShaderBlockInterface::Variable::Type::OTHER:
default:
continue;
break;
}
propertiesNode[VAR_NAME.data()] = propNode;
}
// Write Material
YAML::Node node;
node[VERT_SHADER_YAML_TAG.data()] = 0;
node[FRAG_SHADER_YAML_TAG.data()] = 0;
node[PROPS_YAML_TAG.data()] = propertiesNode;
return node;
}
static bool decode(YAML::Node const& node, SHMaterial& rhs)
{
if (node[VERT_SHADER_YAML_TAG.data()])
{
// TODO
}
if (node[FRAG_SHADER_YAML_TAG.data()])
{
// TODO
}
if (node[PROPS_YAML_TAG.data()])
{
// Loop through all properties
Handle<SHShaderBlockInterface> pipelineProperties = rhs.GetShaderBlockInterface();
const YAML::Node& PROPS_NODE = node[PROPS_YAML_TAG.data()];
for (int i = 0; i < static_cast<int>(pipelineProperties->GetVariableCount()); ++i)
{
const std::string& PROP_NAME = pipelineProperties->GetVariableName(i);
const auto& PROP_NODE = PROPS_NODE[PROP_NAME.data()];
if (PROP_NODE)
{
const std::string& VAR_NAME = pipelineProperties->GetVariableName(i);
const SHShaderBlockInterface::Variable* VARIABLE = pipelineProperties->GetVariable(i);
switch (VARIABLE->type)
{
case SHADE::SHShaderBlockInterface::Variable::Type::FLOAT:
rhs.SetProperty(VARIABLE->offset, PROP_NODE.as<float>());
break;
case SHADE::SHShaderBlockInterface::Variable::Type::INT:
rhs.SetProperty(VARIABLE->offset, PROP_NODE.as<int>());
break;
case SHADE::SHShaderBlockInterface::Variable::Type::VECTOR2:
rhs.SetProperty(VARIABLE->offset, SHSerializationTools::YAMLToVec2(PROP_NODE));
break;
case SHADE::SHShaderBlockInterface::Variable::Type::VECTOR3:
rhs.SetProperty(VARIABLE->offset, SHSerializationTools::YAMLToVec3(PROP_NODE));
break;
case SHADE::SHShaderBlockInterface::Variable::Type::VECTOR4:
rhs.SetProperty(VARIABLE->offset, SHSerializationTools::YAMLToVec4(PROP_NODE));
break;
case SHADE::SHShaderBlockInterface::Variable::Type::OTHER:
default:
continue;
break;
}
}
}
}
return true;
}
};
template<>
struct convert<SHRenderable>
{
static constexpr std::string_view MESH_YAML_TAG = "Mesh";
static constexpr std::string_view MAT_YAML_TAG = "Material";
static YAML::Node encode(SHRenderable const& rhs)
{
YAML::Node node;
node[MESH_YAML_TAG.data()] = SHResourceManager::GetAssetID<SHMesh>(rhs.Mesh).value_or(0);
node[MAT_YAML_TAG.data()] = 0; // TODO: Asset ID
return node;
}
static bool decode(YAML::Node const& node, SHRenderable& rhs)
{
if (node[MESH_YAML_TAG.data()])
{
rhs.Mesh = {};//SHResourceManager::LoadOrGet<SHMesh>(node[MESH_YAML_TAG].as<AssetID>());
}
if (node[MAT_YAML_TAG.data()])
{
// TODO: Convert Asset ID To Material HAndle
}
return true;
}
};
}
2022-09-27 07:03:31 +08:00
2022-09-26 21:08:59 +08:00
namespace SHADE
{
2022-09-26 23:51:20 +08:00
struct SHSerializationHelper
2022-09-26 21:08:59 +08:00
{
2022-10-01 23:43:00 +08:00
template <typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>
2022-09-26 21:08:59 +08:00
static std::string SerializeComponentToString(ComponentType* component)
{
return std::string();
}
2022-10-01 23:43:00 +08:00
template <typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>
2022-09-26 21:08:59 +08:00
static void SerializeComponentToFile(ComponentType* component, std::filesystem::path const& path)
{
}
static YAML::Node RTTRToNode(const rttr::variant& var)
{
YAML::Node node;
auto varType = var.get_type();
2022-10-01 23:43:00 +08:00
if (varType == rttr::type::get<SHVec4>())
2022-09-27 07:03:31 +08:00
{
node.SetStyle(YAML::EmitterStyle::Flow);
node["X"] = var.convert<SHVec4>().x;
node["Y"] = var.convert<SHVec4>().y;
node["Z"] = var.convert<SHVec4>().z;
node["W"] = var.convert<SHVec4>().w;
}
2022-10-01 23:43:00 +08:00
else if (varType == rttr::type::get<SHVec3>())
2022-09-27 07:03:31 +08:00
{
node.SetStyle(YAML::EmitterStyle::Flow);
node["X"] = var.convert<SHVec3>().x;
node["Y"] = var.convert<SHVec3>().y;
node["Z"] = var.convert<SHVec3>().z;
}
2022-10-01 23:43:00 +08:00
else if (varType == rttr::type::get<SHVec2>())
2022-09-27 07:03:31 +08:00
{
node.SetStyle(YAML::EmitterStyle::Flow);
node["X"] = var.convert<SHVec3>().x;
node["Y"] = var.convert<SHVec3>().y;
}
2022-10-01 23:43:00 +08:00
else if (varType.is_arithmetic())
2022-09-26 21:08:59 +08:00
{
bool ok = false;
if (varType == rttr::type::get<bool>())
2022-10-01 23:43:00 +08:00
node = var.to_bool();
2022-09-26 21:08:59 +08:00
else if (varType == rttr::type::get<int8_t>())
2022-10-01 23:43:00 +08:00
node = var.to_int8(&ok);
2022-09-26 21:08:59 +08:00
else if (varType == rttr::type::get<int16_t>())
2022-10-01 23:43:00 +08:00
node = var.to_int16(&ok);
2022-09-26 21:08:59 +08:00
else if (varType == rttr::type::get<int32_t>())
2022-10-01 23:43:00 +08:00
node = var.to_int32(&ok);
2022-09-26 21:08:59 +08:00
else if (varType == rttr::type::get<int64_t>())
2022-10-01 23:43:00 +08:00
node = var.to_int64(&ok);
2022-09-26 21:08:59 +08:00
else if (varType == rttr::type::get<uint8_t>())
2022-10-01 23:43:00 +08:00
node = var.to_uint8(&ok);
2022-09-26 21:08:59 +08:00
else if (varType == rttr::type::get<uint16_t>())
2022-10-01 23:43:00 +08:00
node = var.to_uint16(&ok);
2022-09-26 21:08:59 +08:00
else if (varType == rttr::type::get<uint32_t>())
2022-10-01 23:43:00 +08:00
node = var.to_uint32(&ok);
2022-09-26 21:08:59 +08:00
else if (varType == rttr::type::get<uint64_t>())
2022-10-01 23:43:00 +08:00
node = var.to_uint64(&ok);
2022-09-26 21:08:59 +08:00
else if (varType == rttr::type::get<float>())
2022-10-01 23:43:00 +08:00
node = var.to_float(&ok);
2022-09-26 21:08:59 +08:00
else if (varType == rttr::type::get<double>())
2022-10-01 23:43:00 +08:00
node = var.to_double(&ok);
2022-09-26 21:08:59 +08:00
//else if (varType == rttr::type::get<char>()) //same as uint8_t
// node = var.to_uint8();
}
else if (varType.is_enumeration())
{
bool ok = false;
auto result = var.to_string(&ok);
if (ok)
{
node = var.to_string();
}
else
{
2022-10-01 23:43:00 +08:00
ok = false;
auto value = var.to_uint64(&ok);
if (ok)
node = value;
else
node = YAML::Null;
2022-09-26 21:08:59 +08:00
}
}
else
{
auto properties = var.get_type().get_properties();
2022-10-01 23:43:00 +08:00
for (auto property : properties)
2022-09-26 21:08:59 +08:00
{
node[property.get_name().data()] = RTTRToNode(property.get_value(var));
}
}
return node;
}
2022-10-01 23:43:00 +08:00
template <typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>
2022-09-26 21:08:59 +08:00
static YAML::Node SerializeComponentToNode(ComponentType* component)
{
YAML::Node node{};
2022-10-01 23:43:00 +08:00
if (!component)
return node;
2022-09-26 21:08:59 +08:00
auto componentType = rttr::type::get<ComponentType>();
2022-09-26 23:51:20 +08:00
node = RTTRToNode(*component);
2022-09-26 21:08:59 +08:00
return node;
}
2022-10-01 23:43:00 +08:00
template <typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>
static void InitializeProperty(ComponentType* component, rttr::property const& prop, YAML::Node const& propertyNode)
{
auto propType = prop.get_type();
if (propType == rttr::type::get<SHVec4>())
{
prop.set_value(component, SHSerializationTools::YAMLToVec4(propertyNode));
2022-10-01 23:43:00 +08:00
}
else if (propType == rttr::type::get<SHVec3>())
{
prop.set_value(component, SHSerializationTools::YAMLToVec3(propertyNode));
2022-10-01 23:43:00 +08:00
}
else if (propType == rttr::type::get<SHVec2>())
{
prop.set_value(component, SHSerializationTools::YAMLToVec2(propertyNode));
2022-10-01 23:43:00 +08:00
}
else if (propType.is_arithmetic())
{
bool ok = false;
if (propType == rttr::type::get<bool>())
prop.set_value(component, propertyNode.as<bool>());
else if (propType == rttr::type::get<int8_t>())
prop.set_value(component, propertyNode.as<int8_t>());
else if (propType == rttr::type::get<int16_t>())
prop.set_value(component, propertyNode.as<int16_t>());
else if (propType == rttr::type::get<int32_t>())
prop.set_value(component, propertyNode.as<int32_t>());
else if (propType == rttr::type::get<int64_t>())
prop.set_value(component, propertyNode.as<int64_t>());
else if (propType == rttr::type::get<uint8_t>())
prop.set_value(component, propertyNode.as<uint8_t>());
else if (propType == rttr::type::get<uint16_t>())
prop.set_value(component, propertyNode.as<uint16_t>());
else if (propType == rttr::type::get<uint32_t>())
prop.set_value(component, propertyNode.as<uint32_t>());
else if (propType == rttr::type::get<uint64_t>())
prop.set_value(component, propertyNode.as<uint64_t>());
else if (propType == rttr::type::get<float>())
prop.set_value(component, propertyNode.as<float>());
else if (propType == rttr::type::get<double>())
prop.set_value(component, propertyNode.as<double>());
}
else if (propType.is_enumeration())
{
auto enumAlign = prop.get_enumeration();
prop.set_value(component, enumAlign.name_to_value(propertyNode.as<std::string>()));
}
else
{
auto properties = propType.get_properties();
for (auto property : properties)
{
InitializeProperty(component, property, propertyNode[property.get_name().data()]);
}
}
}
template <typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>
static void InitializeComponentFromNode(YAML::Node const& componentsNode, EntityID const& eid)
{
auto component = SHComponentManager::GetComponent_s<ComponentType>(eid);
if (componentsNode.IsNull() && !component)
return;
auto rttrType = rttr::type::get<ComponentType>();
auto componentNode = componentsNode[rttrType.get_name().data()];
if (componentsNode.IsNull())
return;
auto properties = rttrType.get_properties();
for (auto const& prop : properties)
{
if (componentNode[prop.get_name().data()])
{
InitializeProperty<ComponentType>(component, prop, componentNode[prop.get_name().data()]);
}
}
}
2022-09-26 23:51:20 +08:00
};
2022-09-27 07:03:31 +08:00
}