2022-09-26 21:08:59 +08:00
|
|
|
#pragma once
|
|
|
|
|
2022-11-04 18:27:25 +08:00
|
|
|
#include "SHYAMLConverters.h"
|
2022-09-26 21:08:59 +08:00
|
|
|
#include <yaml-cpp/yaml.h>
|
2022-10-21 18:36:56 +08:00
|
|
|
#include "ECS_Base/Components/SHComponent.h"
|
2022-09-26 21:08:59 +08:00
|
|
|
|
|
|
|
#include <rttr/registration>
|
2022-11-04 18:27:25 +08:00
|
|
|
#include <unordered_map>
|
2022-09-26 21:08:59 +08:00
|
|
|
|
2022-10-01 23:43:00 +08:00
|
|
|
#include "ECS_Base/Managers/SHComponentManager.h"
|
2022-10-31 17:47:38 +08:00
|
|
|
#include "Graphics/MiddleEnd/Materials/SHMaterialSpec.h"
|
2022-11-15 03:03:37 +08:00
|
|
|
#include "Tools/Logger/SHLog.h"
|
2022-10-21 18:36:56 +08:00
|
|
|
|
|
|
|
|
2022-09-26 21:08:59 +08:00
|
|
|
namespace SHADE
|
|
|
|
{
|
2022-11-04 18:27:25 +08:00
|
|
|
using AssetQueue = std::unordered_map<AssetID, AssetType>;
|
2022-09-26 23:51:20 +08:00
|
|
|
struct SHSerializationHelper
|
2022-09-26 21:08:59 +08:00
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
static YAML::Node RTTRToNode(const rttr::variant& var)
|
|
|
|
{
|
|
|
|
YAML::Node node;
|
|
|
|
auto varType = var.get_type();
|
2022-10-25 15:09:45 +08:00
|
|
|
if (varType.is_sequential_container())
|
2022-10-25 08:42:51 +08:00
|
|
|
{
|
2022-10-25 15:09:45 +08:00
|
|
|
for (auto const& elem : var.create_sequential_view())
|
2022-10-25 08:42:51 +08:00
|
|
|
{
|
2022-10-25 15:09:45 +08:00
|
|
|
node.push_back(RTTRToNode(elem));
|
2022-10-25 08:42:51 +08:00
|
|
|
}
|
|
|
|
}
|
2022-10-01 23:43:00 +08:00
|
|
|
if (varType == rttr::type::get<SHVec4>())
|
2022-09-27 07:03:31 +08:00
|
|
|
{
|
2022-10-25 08:42:51 +08:00
|
|
|
node = YAML::convert<SHVec4>::encode(var.convert<SHVec4>());
|
2022-09-27 07:03:31 +08:00
|
|
|
}
|
2022-10-01 23:43:00 +08:00
|
|
|
else if (varType == rttr::type::get<SHVec3>())
|
2022-09-27 07:03:31 +08:00
|
|
|
{
|
2022-10-25 08:42:51 +08:00
|
|
|
node = YAML::convert<SHVec3>::encode(var.convert<SHVec3>());
|
2022-09-27 07:03:31 +08:00
|
|
|
}
|
2022-10-01 23:43:00 +08:00
|
|
|
else if (varType == rttr::type::get<SHVec2>())
|
2022-09-27 07:03:31 +08:00
|
|
|
{
|
2022-10-25 08:42:51 +08:00
|
|
|
node = YAML::convert<SHVec2>::encode(var.convert<SHVec2>());
|
2022-09-27 07:03:31 +08:00
|
|
|
}
|
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
|
|
|
}
|
|
|
|
}
|
2022-11-04 14:44:18 +08:00
|
|
|
else if (varType == rttr::type::get<std::string>())
|
|
|
|
node = var.to_string();
|
2022-09-26 21:08:59 +08:00
|
|
|
else
|
|
|
|
{
|
|
|
|
auto properties = var.get_type().get_properties();
|
2022-10-25 15:09:45 +08:00
|
|
|
for (auto const& property : properties)
|
2022-09-26 21:08:59 +08:00
|
|
|
{
|
|
|
|
node[property.get_name().data()] = RTTRToNode(property.get_value(var));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return node;
|
|
|
|
}
|
|
|
|
|
2022-10-25 15:09:45 +08:00
|
|
|
template <typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>
|
2022-10-25 08:42:51 +08:00
|
|
|
static std::string SerializeComponentToString(ComponentType* component)
|
|
|
|
{
|
|
|
|
return std::string();
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>
|
|
|
|
static void SerializeComponentToFile(ComponentType* component, std::filesystem::path const& path)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
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
|
|
|
|
2022-11-04 14:44:18 +08:00
|
|
|
template <typename Type>
|
|
|
|
static void InitializeProperty(Type* object, rttr::property const& prop, YAML::Node const& propertyNode)
|
2022-10-01 23:43:00 +08:00
|
|
|
{
|
|
|
|
auto propType = prop.get_type();
|
|
|
|
if (propType == rttr::type::get<SHVec4>())
|
|
|
|
{
|
2022-10-25 15:09:45 +08:00
|
|
|
SHVec4 vec = propertyNode.as<SHVec4>();
|
2022-11-04 14:44:18 +08:00
|
|
|
prop.set_value(object, vec);
|
2022-10-01 23:43:00 +08:00
|
|
|
}
|
|
|
|
else if (propType == rttr::type::get<SHVec3>())
|
|
|
|
{
|
2022-10-25 15:09:45 +08:00
|
|
|
SHVec3 vec = propertyNode.as<SHVec3>();
|
2022-11-04 14:44:18 +08:00
|
|
|
prop.set_value(object, vec);
|
2022-10-01 23:43:00 +08:00
|
|
|
}
|
|
|
|
else if (propType == rttr::type::get<SHVec2>())
|
|
|
|
{
|
2022-10-25 15:09:45 +08:00
|
|
|
SHVec2 vec = propertyNode.as<SHVec2>();
|
2022-11-04 14:44:18 +08:00
|
|
|
prop.set_value(object, vec);
|
2022-10-01 23:43:00 +08:00
|
|
|
}
|
|
|
|
else if (propType.is_arithmetic())
|
|
|
|
{
|
|
|
|
bool ok = false;
|
|
|
|
if (propType == rttr::type::get<bool>())
|
2022-11-04 14:44:18 +08:00
|
|
|
prop.set_value(object, propertyNode.as<bool>());
|
2022-10-01 23:43:00 +08:00
|
|
|
else if (propType == rttr::type::get<int8_t>())
|
2022-11-04 14:44:18 +08:00
|
|
|
prop.set_value(object, propertyNode.as<int8_t>());
|
2022-10-01 23:43:00 +08:00
|
|
|
else if (propType == rttr::type::get<int16_t>())
|
2022-11-04 14:44:18 +08:00
|
|
|
prop.set_value(object, propertyNode.as<int16_t>());
|
2022-10-01 23:43:00 +08:00
|
|
|
else if (propType == rttr::type::get<int32_t>())
|
2022-11-04 14:44:18 +08:00
|
|
|
prop.set_value(object, propertyNode.as<int32_t>());
|
2022-10-01 23:43:00 +08:00
|
|
|
else if (propType == rttr::type::get<int64_t>())
|
2022-11-04 14:44:18 +08:00
|
|
|
prop.set_value(object, propertyNode.as<int64_t>());
|
2022-10-01 23:43:00 +08:00
|
|
|
else if (propType == rttr::type::get<uint8_t>())
|
2022-11-04 14:44:18 +08:00
|
|
|
prop.set_value(object, propertyNode.as<uint8_t>());
|
2022-10-01 23:43:00 +08:00
|
|
|
else if (propType == rttr::type::get<uint16_t>())
|
2022-11-04 14:44:18 +08:00
|
|
|
prop.set_value(object, propertyNode.as<uint16_t>());
|
2022-10-01 23:43:00 +08:00
|
|
|
else if (propType == rttr::type::get<uint32_t>())
|
2022-11-04 14:44:18 +08:00
|
|
|
prop.set_value(object, propertyNode.as<uint32_t>());
|
2022-10-01 23:43:00 +08:00
|
|
|
else if (propType == rttr::type::get<uint64_t>())
|
2022-11-04 14:44:18 +08:00
|
|
|
prop.set_value(object, propertyNode.as<uint64_t>());
|
2022-10-01 23:43:00 +08:00
|
|
|
else if (propType == rttr::type::get<float>())
|
2022-11-04 14:44:18 +08:00
|
|
|
prop.set_value(object, propertyNode.as<float>());
|
2022-10-01 23:43:00 +08:00
|
|
|
else if (propType == rttr::type::get<double>())
|
2022-11-04 14:44:18 +08:00
|
|
|
prop.set_value(object, propertyNode.as<double>());
|
2022-10-01 23:43:00 +08:00
|
|
|
}
|
|
|
|
else if (propType.is_enumeration())
|
|
|
|
{
|
|
|
|
auto enumAlign = prop.get_enumeration();
|
2022-11-04 14:44:18 +08:00
|
|
|
prop.set_value(object, enumAlign.name_to_value(propertyNode.as<std::string>()));
|
2022-10-01 23:43:00 +08:00
|
|
|
}
|
2022-11-04 14:44:18 +08:00
|
|
|
else if (propType == rttr::type::get<std::string>())
|
|
|
|
prop.set_value(object, propertyNode.as<std::string>());
|
2022-10-01 23:43:00 +08:00
|
|
|
else
|
|
|
|
{
|
|
|
|
auto properties = propType.get_properties();
|
2022-10-25 15:09:45 +08:00
|
|
|
for (auto const& property : properties)
|
2022-10-01 23:43:00 +08:00
|
|
|
{
|
2022-11-04 14:44:18 +08:00
|
|
|
if(propertyNode[property.get_name().data()].IsDefined())
|
|
|
|
InitializeProperty(object, property, propertyNode[property.get_name().data()]);
|
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 InitializeComponentFromNode(YAML::Node const& componentsNode, EntityID const& eid)
|
|
|
|
{
|
2022-10-25 15:09:45 +08:00
|
|
|
ComponentType* component = SHComponentManager::GetComponent_s<ComponentType>(eid);
|
2022-10-01 23:43:00 +08:00
|
|
|
if (componentsNode.IsNull() && !component)
|
|
|
|
return;
|
|
|
|
auto rttrType = rttr::type::get<ComponentType>();
|
|
|
|
auto componentNode = componentsNode[rttrType.get_name().data()];
|
2022-11-02 16:56:38 +08:00
|
|
|
if (!componentNode.IsDefined())
|
2022-10-01 23:43:00 +08:00
|
|
|
return;
|
|
|
|
auto properties = rttrType.get_properties();
|
|
|
|
for (auto const& prop : properties)
|
|
|
|
{
|
2022-10-25 15:09:45 +08:00
|
|
|
if (componentNode[prop.get_name().data()].IsDefined())
|
2022-10-01 23:43:00 +08:00
|
|
|
{
|
|
|
|
InitializeProperty<ComponentType>(component, prop, componentNode[prop.get_name().data()]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-27 19:31:00 +08:00
|
|
|
template <typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>
|
2022-11-04 18:27:25 +08:00
|
|
|
static YAML::Node GetComponentNode(YAML::Node const& componentsNode, EntityID const& eid)
|
2022-10-27 19:31:00 +08:00
|
|
|
{
|
|
|
|
auto component = SHComponentManager::GetComponent_s<ComponentType>(eid);
|
|
|
|
if (componentsNode.IsNull() && !component)
|
2022-11-04 18:27:25 +08:00
|
|
|
return {};
|
2022-10-27 19:31:00 +08:00
|
|
|
auto rttrType = rttr::type::get<ComponentType>();
|
|
|
|
auto componentNode = componentsNode[rttrType.get_name().data()];
|
2022-10-30 11:26:23 +08:00
|
|
|
if (!componentNode.IsDefined())
|
2022-11-04 18:27:25 +08:00
|
|
|
return {};
|
|
|
|
return componentNode;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>
|
|
|
|
static void ConvertNodeToComponent(YAML::Node const& componentsNode, EntityID const& eid)
|
|
|
|
{
|
|
|
|
auto component = SHComponentManager::GetComponent_s<ComponentType>(eid);
|
|
|
|
if (componentsNode.IsNull() && !component)
|
2022-10-27 19:31:00 +08:00
|
|
|
return;
|
2022-11-04 18:27:25 +08:00
|
|
|
|
|
|
|
YAML::convert<ComponentType>::decode(GetComponentNode<ComponentType>(componentsNode, eid), *component);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>
|
|
|
|
static void FetchAssetsFromComponent(YAML::Node const& componentsNode, EntityID const& eid, AssetQueue& assetQueue)
|
|
|
|
{
|
2022-10-27 19:31:00 +08:00
|
|
|
}
|
|
|
|
|
2022-11-04 18:27:25 +08:00
|
|
|
template<>
|
|
|
|
static void FetchAssetsFromComponent<SHRenderable>(YAML::Node const& componentsNode, EntityID const& eid, AssetQueue& assetQueue)
|
|
|
|
{
|
|
|
|
auto node = GetComponentNode<SHRenderable>(componentsNode, eid);
|
|
|
|
if(!node.IsDefined())
|
|
|
|
return;
|
|
|
|
if (auto const& meshNode = node[YAML::convert<SHRenderable>::MESH_YAML_TAG.data()]; meshNode.IsDefined())
|
|
|
|
{
|
|
|
|
assetQueue.insert({meshNode.as<AssetID>(), AssetType::MESH});
|
|
|
|
//SHResourceManager::LoadOrGet<SHMesh>(node[YAML::convert<SHRenderable>::MESH_YAML_TAG.data()].as<AssetID>());
|
|
|
|
}
|
|
|
|
if (auto const& matNode = node[YAML::convert<SHRenderable>::MAT_YAML_TAG.data()]; matNode.IsDefined())
|
|
|
|
{
|
|
|
|
auto const matAsset = SHAssetManager::GetData<SHMaterialAsset>(matNode.as<AssetID>());
|
|
|
|
if(matAsset)
|
|
|
|
{
|
|
|
|
SHMaterialSpec spec;
|
|
|
|
YAML::convert<SHMaterialSpec>::decode(*YAML::Load(matAsset->data).begin(), spec);
|
|
|
|
if(spec.properties.IsDefined())
|
|
|
|
{
|
|
|
|
auto fragShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(spec.fragShader);
|
|
|
|
auto interface = fragShader->GetReflectedData().GetDescriptorBindingInfo().GetShaderBlockInterface(SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE, SHGraphicsConstants::DescriptorSetBindings::BATCHED_PER_INST_DATA);
|
2022-11-04 19:16:32 +08:00
|
|
|
int const varCount = static_cast<int>(interface->GetVariableCount());
|
2022-11-04 18:27:25 +08:00
|
|
|
|
|
|
|
for (int i = 0; i < varCount; ++i)
|
|
|
|
{
|
|
|
|
auto variable = interface->GetVariable(i);
|
|
|
|
if(variable->type != SHShaderBlockInterface::Variable::Type::INT)
|
2022-11-04 19:16:32 +08:00
|
|
|
continue;
|
2022-11-04 18:27:25 +08:00
|
|
|
const std::string& VAR_NAME = interface->GetVariableName(i);
|
|
|
|
if(VAR_NAME.empty())
|
|
|
|
continue;
|
2022-11-04 19:16:32 +08:00
|
|
|
assetQueue.insert({spec.properties[VAR_NAME.data()].as<AssetID>(), AssetType::TEXTURE});
|
|
|
|
}
|
2022-11-04 18:27:25 +08:00
|
|
|
}
|
|
|
|
}
|
2022-11-04 19:16:32 +08:00
|
|
|
//assetQueue.insert({matNode.as<AssetID>(), AssetType::MATERIAL});
|
2022-11-04 18:27:25 +08:00
|
|
|
//SHResourceManager::LoadOrGet<SHMaterial>(node[YAML::convert<SHRenderable>::MAT_YAML_TAG.data()].as<AssetID>());
|
|
|
|
}
|
|
|
|
}
|
2022-09-26 23:51:20 +08:00
|
|
|
};
|
2022-09-27 07:03:31 +08:00
|
|
|
}
|