#pragma once #include "SHYAMLConverters.h" #include #include "ECS_Base/Components/SHComponent.h" #include #include #include "ECS_Base/Managers/SHComponentManager.h" #include "Graphics/MiddleEnd/Materials/SHMaterialSpec.h" #include "Tools/SHLog.h" namespace SHADE { using AssetQueue = std::unordered_map; struct SHSerializationHelper { static YAML::Node RTTRToNode(const rttr::variant& var) { YAML::Node node; auto varType = var.get_type(); if (varType.is_sequential_container()) { for (auto const& elem : var.create_sequential_view()) { node.push_back(RTTRToNode(elem)); } } if (varType == rttr::type::get()) { node = YAML::convert::encode(var.convert()); } else if (varType == rttr::type::get()) { node = YAML::convert::encode(var.convert()); } else if (varType == rttr::type::get()) { node = YAML::convert::encode(var.convert()); } else if (varType.is_arithmetic()) { bool ok = false; if (varType == rttr::type::get()) node = var.to_bool(); else if (varType == rttr::type::get()) node = var.to_int8(&ok); else if (varType == rttr::type::get()) node = var.to_int16(&ok); else if (varType == rttr::type::get()) node = var.to_int32(&ok); else if (varType == rttr::type::get()) node = var.to_int64(&ok); else if (varType == rttr::type::get()) node = var.to_uint8(&ok); else if (varType == rttr::type::get()) node = var.to_uint16(&ok); else if (varType == rttr::type::get()) node = var.to_uint32(&ok); else if (varType == rttr::type::get()) node = var.to_uint64(&ok); else if (varType == rttr::type::get()) node = var.to_float(&ok); else if (varType == rttr::type::get()) node = var.to_double(&ok); //else if (varType == rttr::type::get()) //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 { ok = false; auto value = var.to_uint64(&ok); if (ok) node = value; else node = YAML::Null; } } else if (varType == rttr::type::get()) node = var.to_string(); else { auto properties = var.get_type().get_properties(); for (auto const& property : properties) { node[property.get_name().data()] = RTTRToNode(property.get_value(var)); } } return node; } template , bool> = true> static std::string SerializeComponentToString(ComponentType* component) { return std::string(); } template , bool> = true> static void SerializeComponentToFile(ComponentType* component, std::filesystem::path const& path) { } template , bool> = true> static YAML::Node SerializeComponentToNode(ComponentType* component) { YAML::Node node{}; if (!component) return node; auto componentType = rttr::type::get(); node = RTTRToNode(*component); return node; } template static void InitializeProperty(Type* object, rttr::property const& prop, YAML::Node const& propertyNode) { auto propType = prop.get_type(); if (propType == rttr::type::get()) { SHVec4 vec = propertyNode.as(); prop.set_value(object, vec); } else if (propType == rttr::type::get()) { SHVec3 vec = propertyNode.as(); prop.set_value(object, vec); } else if (propType == rttr::type::get()) { SHVec2 vec = propertyNode.as(); prop.set_value(object, vec); } else if (propType.is_arithmetic()) { bool ok = false; if (propType == rttr::type::get()) prop.set_value(object, propertyNode.as()); else if (propType == rttr::type::get()) prop.set_value(object, propertyNode.as()); else if (propType == rttr::type::get()) prop.set_value(object, propertyNode.as()); else if (propType == rttr::type::get()) prop.set_value(object, propertyNode.as()); else if (propType == rttr::type::get()) prop.set_value(object, propertyNode.as()); else if (propType == rttr::type::get()) prop.set_value(object, propertyNode.as()); else if (propType == rttr::type::get()) prop.set_value(object, propertyNode.as()); else if (propType == rttr::type::get()) prop.set_value(object, propertyNode.as()); else if (propType == rttr::type::get()) prop.set_value(object, propertyNode.as()); else if (propType == rttr::type::get()) prop.set_value(object, propertyNode.as()); else if (propType == rttr::type::get()) prop.set_value(object, propertyNode.as()); } else if (propType.is_enumeration()) { auto enumAlign = prop.get_enumeration(); prop.set_value(object, enumAlign.name_to_value(propertyNode.as())); } else if (propType == rttr::type::get()) prop.set_value(object, propertyNode.as()); else { auto properties = propType.get_properties(); for (auto const& property : properties) { if(propertyNode[property.get_name().data()].IsDefined()) InitializeProperty(object, property, propertyNode[property.get_name().data()]); } } } template , bool> = true> static void InitializeComponentFromNode(YAML::Node const& componentsNode, EntityID const& eid) { ComponentType* component = SHComponentManager::GetComponent_s(eid); if (componentsNode.IsNull() && !component) return; auto rttrType = rttr::type::get(); auto componentNode = componentsNode[rttrType.get_name().data()]; if (!componentNode.IsDefined()) return; auto properties = rttrType.get_properties(); for (auto const& prop : properties) { if (componentNode[prop.get_name().data()].IsDefined()) { InitializeProperty(component, prop, componentNode[prop.get_name().data()]); } } } template , bool> = true> static YAML::Node GetComponentNode(YAML::Node const& componentsNode, EntityID const& eid) { auto component = SHComponentManager::GetComponent_s(eid); if (componentsNode.IsNull() && !component) return {}; auto rttrType = rttr::type::get(); auto componentNode = componentsNode[rttrType.get_name().data()]; if (!componentNode.IsDefined()) return {}; return componentNode; } template , bool> = true> static void ConvertNodeToComponent(YAML::Node const& componentsNode, EntityID const& eid) { auto component = SHComponentManager::GetComponent_s(eid); if (componentsNode.IsNull() && !component) return; YAML::convert::decode(GetComponentNode(componentsNode, eid), *component); } template , bool> = true> static void FetchAssetsFromComponent(YAML::Node const& componentsNode, EntityID const& eid, AssetQueue& assetQueue) { } template<> static void FetchAssetsFromComponent(YAML::Node const& componentsNode, EntityID const& eid, AssetQueue& assetQueue) { auto node = GetComponentNode(componentsNode, eid); if(!node.IsDefined()) return; if (auto const& meshNode = node[YAML::convert::MESH_YAML_TAG.data()]; meshNode.IsDefined()) { assetQueue.insert({meshNode.as(), AssetType::MESH}); //SHResourceManager::LoadOrGet(node[YAML::convert::MESH_YAML_TAG.data()].as()); } if (auto const& matNode = node[YAML::convert::MAT_YAML_TAG.data()]; matNode.IsDefined()) { auto const matAsset = SHAssetManager::GetData(matNode.as()); if(matAsset) { SHMaterialSpec spec; YAML::convert::decode(*YAML::Load(matAsset->data).begin(), spec); if(spec.properties.IsDefined()) { auto fragShader = SHResourceManager::LoadOrGet(spec.fragShader); auto interface = fragShader->GetReflectedData().GetDescriptorBindingInfo().GetShaderBlockInterface(SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE, SHGraphicsConstants::DescriptorSetBindings::BATCHED_PER_INST_DATA); /*int const varCount = static_cast(interface->GetVariableCount()); for (int i = 0; i < varCount; ++i) { auto variable = interface->GetVariable(i); if(variable->type != SHShaderBlockInterface::Variable::Type::INT) return; const std::string& VAR_NAME = interface->GetVariableName(i); if(VAR_NAME.empty()) continue; assetQueue.insert({matNode.as(), AssetType::TEXTURE}); }*/ } } assetQueue.insert({matNode.as(), AssetType::MATERIAL}); //SHResourceManager::LoadOrGet(node[YAML::convert::MAT_YAML_TAG.data()].as()); } } }; }