MetaCore/Source/MetaCoreScene/Private/MetaCoreSceneSerializer.cpp
2026-06-24 16:32:25 +08:00

729 lines
43 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "MetaCoreScene/MetaCoreSceneSerializer.h"
#include "MetaCoreFoundation/MetaCoreReflection.h"
#include <nlohmann/json.hpp>
#include <fstream>
#include <iostream>
#include <sstream>
using json = nlohmann::json;
namespace MetaCore {
// 辅助方法:将 glm::vec3 序列化为 JSON 数组 [x, y, z]
static json Vec3ToJson(const glm::vec3& vec) {
return { vec.x, vec.y, vec.z };
}
// 辅助方法:从 JSON 数组 [x, y, z] 反序列化出 glm::vec3
static glm::vec3 JsonToVec3(const json& j) {
if (j.is_array() && j.size() >= 3) {
return glm::vec3(j[0].get<float>(), j[1].get<float>(), j[2].get<float>());
}
return glm::vec3(0.0f);
}
// 辅助方法:将 MetaCoreAssetGuid 转换为 String方便文本化存储
static std::string GuidToString(const MetaCoreAssetGuid& guid) {
return guid.IsValid() ? guid.ToString() : "";
}
// 辅助方法:从 String 反解析为 MetaCoreAssetGuid
static MetaCoreAssetGuid StringToGuid(const std::string& str) {
return str.empty() ? MetaCoreAssetGuid{} : MetaCoreAssetGuid::Parse(str).value_or(MetaCoreAssetGuid{});
}
static json SceneEnvironmentToJson(const MetaCoreSceneEnvironmentSettings& environment) {
json environmentJson = json::object();
environmentJson["Source"] = static_cast<int>(environment.Source);
environmentJson["IblKtxPath"] = environment.IblKtxPath.generic_string();
environmentJson["SkyboxKtxPath"] = environment.SkyboxKtxPath.generic_string();
environmentJson["SkyboxVisible"] = environment.SkyboxVisible;
environmentJson["RotationDegrees"] = environment.RotationDegrees;
environmentJson["IndirectLightIntensity"] = environment.IndirectLightIntensity;
environmentJson["SkyboxIntensity"] = environment.SkyboxIntensity;
return environmentJson;
}
static MetaCoreSceneEnvironmentSettings JsonToSceneEnvironment(const json& environmentJson) {
MetaCoreSceneEnvironmentSettings environment;
if (!environmentJson.is_object()) {
return environment;
}
if (environmentJson.contains("Source")) environment.Source = static_cast<MetaCoreSceneEnvironmentSource>(environmentJson["Source"].get<int>());
if (environmentJson.contains("IblKtxPath")) environment.IblKtxPath = environmentJson["IblKtxPath"].get<std::string>();
if (environmentJson.contains("SkyboxKtxPath")) environment.SkyboxKtxPath = environmentJson["SkyboxKtxPath"].get<std::string>();
if (environmentJson.contains("SkyboxVisible")) environment.SkyboxVisible = environmentJson["SkyboxVisible"].get<bool>();
if (environmentJson.contains("RotationDegrees")) environment.RotationDegrees = environmentJson["RotationDegrees"].get<float>();
if (environmentJson.contains("IndirectLightIntensity")) environment.IndirectLightIntensity = environmentJson["IndirectLightIntensity"].get<float>();
if (environmentJson.contains("SkyboxIntensity")) environment.SkyboxIntensity = environmentJson["SkyboxIntensity"].get<float>();
return environment;
}
// 辅助方法:将单个 MetaCoreGameObjectData 转换为 json 格式
static json GameObjectDataToJson(const MetaCoreGameObjectData& obj, const MetaCoreTypeRegistry& registry) {
json objJson = json::object();
const MetaCoreStructDescriptor* objDesc = registry.FindStruct<MetaCoreGameObjectData>();
if (!objDesc) return objJson;
for (const auto& objField : objDesc->Fields) {
if (objField.Name == "Id") {
objJson["Id"] = obj.Id;
} else if (objField.Name == "ParentId") {
objJson["ParentId"] = obj.ParentId;
} else if (objField.Name == "Name") {
objJson["Name"] = obj.Name;
} else if (objField.Name == "Transform") {
const MetaCoreStructDescriptor* transDesc = registry.FindStruct<MetaCoreTransformComponent>();
if (transDesc) {
json transJson = json::object();
for (const auto& transField : transDesc->Fields) {
if (transField.Name == "Position") transJson["Position"] = Vec3ToJson(obj.Transform.Position);
else if (transField.Name == "RotationEulerDegrees") transJson["RotationEulerDegrees"] = Vec3ToJson(obj.Transform.RotationEulerDegrees);
else if (transField.Name == "Scale") transJson["Scale"] = Vec3ToJson(obj.Transform.Scale);
}
objJson["Transform"] = transJson;
}
} else if (objField.Name == "MeshRenderer" && obj.MeshRenderer.has_value()) {
const MetaCoreStructDescriptor* meshDesc = registry.FindStruct<MetaCoreMeshRendererComponent>();
if (meshDesc) {
json meshJson = json::object();
const auto& mesh = obj.MeshRenderer.value();
for (const auto& meshField : meshDesc->Fields) {
if (meshField.Name == "MeshSource") meshJson["MeshSource"] = static_cast<int>(mesh.MeshSource);
else if (meshField.Name == "BuiltinMesh") meshJson["BuiltinMesh"] = static_cast<int>(mesh.BuiltinMesh);
else if (meshField.Name == "MeshAssetGuid") meshJson["MeshAssetGuid"] = GuidToString(mesh.MeshAssetGuid);
else if (meshField.Name == "MaterialAssetGuids") {
json matGuids = json::array();
for (const auto& guid : mesh.MaterialAssetGuids) {
matGuids.push_back(GuidToString(guid));
}
meshJson["MaterialAssetGuids"] = matGuids;
}
else if (meshField.Name == "SourceModelAssetGuid") meshJson["SourceModelAssetGuid"] = GuidToString(mesh.SourceModelAssetGuid);
else if (meshField.Name == "SourceModelPath") meshJson["SourceModelPath"] = mesh.SourceModelPath;
else if (meshField.Name == "SourceNodePath") meshJson["SourceNodePath"] = mesh.SourceNodePath;
else if (meshField.Name == "BaseColorTextureGuid") meshJson["BaseColorTextureGuid"] = GuidToString(mesh.BaseColorTextureGuid);
else if (meshField.Name == "MetallicRoughnessTextureGuid") meshJson["MetallicRoughnessTextureGuid"] = GuidToString(mesh.MetallicRoughnessTextureGuid);
else if (meshField.Name == "NormalTextureGuid") meshJson["NormalTextureGuid"] = GuidToString(mesh.NormalTextureGuid);
else if (meshField.Name == "EmissiveTextureGuid") meshJson["EmissiveTextureGuid"] = GuidToString(mesh.EmissiveTextureGuid);
else if (meshField.Name == "AoTextureGuid") meshJson["AoTextureGuid"] = GuidToString(mesh.AoTextureGuid);
else if (meshField.Name == "BaseColorTexturePath") meshJson["BaseColorTexturePath"] = mesh.BaseColorTexturePath;
else if (meshField.Name == "MetallicRoughnessTexturePath") meshJson["MetallicRoughnessTexturePath"] = mesh.MetallicRoughnessTexturePath;
else if (meshField.Name == "NormalTexturePath") meshJson["NormalTexturePath"] = mesh.NormalTexturePath;
else if (meshField.Name == "EmissiveTexturePath") meshJson["EmissiveTexturePath"] = mesh.EmissiveTexturePath;
else if (meshField.Name == "AoTexturePath") meshJson["AoTexturePath"] = mesh.AoTexturePath;
else if (meshField.Name == "DoubleSided") meshJson["DoubleSided"] = mesh.DoubleSided;
else if (meshField.Name == "Metallic") meshJson["Metallic"] = mesh.Metallic;
else if (meshField.Name == "Roughness") meshJson["Roughness"] = mesh.Roughness;
else if (meshField.Name == "AlphaMode") meshJson["AlphaMode"] = static_cast<int>(mesh.AlphaMode);
else if (meshField.Name == "AlphaCutoff") meshJson["AlphaCutoff"] = mesh.AlphaCutoff;
else if (meshField.Name == "EmissiveColor") meshJson["EmissiveColor"] = Vec3ToJson(mesh.EmissiveColor);
else if (meshField.Name == "BaseColor") meshJson["BaseColor"] = Vec3ToJson(mesh.BaseColor);
else if (meshField.Name == "ModelNodeIndex") meshJson["ModelNodeIndex"] = mesh.ModelNodeIndex;
else if (meshField.Name == "SubMeshIndex") meshJson["SubMeshIndex"] = mesh.SubMeshIndex;
else if (meshField.Name == "Visible") meshJson["Visible"] = mesh.Visible;
}
objJson["MeshRenderer"] = meshJson;
}
} else if (objField.Name == "Light" && obj.Light.has_value()) {
const MetaCoreStructDescriptor* lightDesc = registry.FindStruct<MetaCoreLightComponent>();
if (lightDesc) {
json lightJson = json::object();
for (const auto& lightField : lightDesc->Fields) {
if (lightField.Name == "Color") lightJson["Color"] = Vec3ToJson(obj.Light->Color);
else if (lightField.Name == "Intensity") lightJson["Intensity"] = obj.Light->Intensity;
else if (lightField.Name == "Enabled") lightJson["Enabled"] = obj.Light->Enabled;
}
objJson["Light"] = lightJson;
}
} else if (objField.Name == "Rotator" && obj.Rotator.has_value()) {
const MetaCoreStructDescriptor* rotatorDesc = registry.FindStruct<MetaCoreRotatorComponent>();
if (rotatorDesc) {
json rotatorJson = json::object();
for (const auto& rotatorField : rotatorDesc->Fields) {
if (rotatorField.Name == "Enabled") rotatorJson["Enabled"] = obj.Rotator->Enabled;
else if (rotatorField.Name == "DegreesPerSecond") rotatorJson["DegreesPerSecond"] = obj.Rotator->DegreesPerSecond;
}
objJson["Rotator"] = rotatorJson;
}
} else if (objField.Name == "Script" && obj.Script.has_value()) {
json scriptJson = json::object();
json instancesJson = json::array();
for (const MetaCoreScriptInstanceData& instance : obj.Script->Instances) {
json instanceJson = json::object();
instanceJson["InstanceId"] = instance.InstanceId;
instanceJson["ScriptTypeId"] = instance.ScriptTypeId;
instanceJson["Enabled"] = instance.Enabled;
instanceJson["FieldsJson"] = instance.FieldsJson;
instancesJson.push_back(std::move(instanceJson));
}
scriptJson["Instances"] = std::move(instancesJson);
objJson["Script"] = std::move(scriptJson);
} else if (objField.Name == "Camera" && obj.Camera.has_value()) {
const MetaCoreStructDescriptor* camDesc = registry.FindStruct<MetaCoreCameraComponent>();
if (camDesc) {
json camJson = json::object();
for (const auto& camField : camDesc->Fields) {
if (camField.Name == "FieldOfViewDegrees") camJson["FieldOfViewDegrees"] = obj.Camera->FieldOfViewDegrees;
else if (camField.Name == "NearClip") camJson["NearClip"] = obj.Camera->NearClip;
else if (camField.Name == "FarClip") camJson["FarClip"] = obj.Camera->FarClip;
else if (camField.Name == "IsPrimary") camJson["IsPrimary"] = obj.Camera->IsPrimary;
else if (camField.Name == "Enabled") camJson["Enabled"] = obj.Camera->Enabled;
else if (camField.Name == "ProjectionMode") camJson["ProjectionMode"] = static_cast<int>(obj.Camera->ProjectionMode);
else if (camField.Name == "OrthographicSize") camJson["OrthographicSize"] = obj.Camera->OrthographicSize;
else if (camField.Name == "Depth") camJson["Depth"] = obj.Camera->Depth;
else if (camField.Name == "CullingMask") camJson["CullingMask"] = obj.Camera->CullingMask;
else if (camField.Name == "ClearFlags") camJson["ClearFlags"] = static_cast<int>(obj.Camera->ClearFlags);
else if (camField.Name == "BackgroundColor") camJson["BackgroundColor"] = Vec3ToJson(obj.Camera->BackgroundColor);
else if (camField.Name == "BackgroundAlpha") camJson["BackgroundAlpha"] = obj.Camera->BackgroundAlpha;
}
objJson["Camera"] = camJson;
}
} else if (objField.Name == "PrefabInstance" && obj.PrefabInstance.has_value()) {
const MetaCoreStructDescriptor* prefabDesc = registry.FindStruct<MetaCorePrefabInstanceMetadata>();
if (prefabDesc) {
json prefabJson = json::object();
for (const auto& prefabField : prefabDesc->Fields) {
if (prefabField.Name == "PrefabAssetGuid") prefabJson["PrefabAssetGuid"] = GuidToString(obj.PrefabInstance->PrefabAssetGuid);
else if (prefabField.Name == "PrefabObjectId") prefabJson["PrefabObjectId"] = obj.PrefabInstance->PrefabObjectId;
else if (prefabField.Name == "PrefabInstanceRootId") prefabJson["PrefabInstanceRootId"] = obj.PrefabInstance->PrefabInstanceRootId;
}
objJson["PrefabInstance"] = prefabJson;
}
}
}
return objJson;
}
// 辅助方法:从 json 格式中恢复单个 MetaCoreGameObjectData
static MetaCoreGameObjectData JsonToGameObjectData(const json& objJson, const MetaCoreTypeRegistry& registry) {
MetaCoreGameObjectData obj;
const MetaCoreStructDescriptor* objDesc = registry.FindStruct<MetaCoreGameObjectData>();
if (!objDesc) return obj;
for (const auto& objField : objDesc->Fields) {
if (objField.Name == "Id" && objJson.contains("Id")) {
obj.Id = objJson["Id"].get<MetaCoreId>();
} else if (objField.Name == "ParentId" && objJson.contains("ParentId")) {
obj.ParentId = objJson["ParentId"].get<MetaCoreId>();
} else if (objField.Name == "Name" && objJson.contains("Name")) {
obj.Name = objJson["Name"].get<std::string>();
} else if (objField.Name == "Transform" && objJson.contains("Transform")) {
const auto& transJson = objJson["Transform"];
const MetaCoreStructDescriptor* transDesc = registry.FindStruct<MetaCoreTransformComponent>();
if (transDesc) {
for (const auto& transField : transDesc->Fields) {
if (transField.Name == "Position" && transJson.contains("Position")) {
obj.Transform.Position = JsonToVec3(transJson["Position"]);
} else if (transField.Name == "RotationEulerDegrees" && transJson.contains("RotationEulerDegrees")) {
obj.Transform.RotationEulerDegrees = JsonToVec3(transJson["RotationEulerDegrees"]);
} else if (transField.Name == "Scale" && transJson.contains("Scale")) {
obj.Transform.Scale = JsonToVec3(transJson["Scale"]);
}
}
}
} else if (objField.Name == "MeshRenderer" && objJson.contains("MeshRenderer")) {
const auto& meshJson = objJson["MeshRenderer"];
const MetaCoreStructDescriptor* meshDesc = registry.FindStruct<MetaCoreMeshRendererComponent>();
if (meshDesc) {
MetaCoreMeshRendererComponent mesh;
for (const auto& meshField : meshDesc->Fields) {
if (meshField.Name == "MeshSource" && meshJson.contains("MeshSource")) mesh.MeshSource = static_cast<MetaCoreMeshSourceKind>(meshJson["MeshSource"].get<int>());
else if (meshField.Name == "BuiltinMesh" && meshJson.contains("BuiltinMesh")) mesh.BuiltinMesh = static_cast<MetaCoreBuiltinMeshType>(meshJson["BuiltinMesh"].get<int>());
else if (meshField.Name == "MeshAssetGuid" && meshJson.contains("MeshAssetGuid")) mesh.MeshAssetGuid = StringToGuid(meshJson["MeshAssetGuid"].get<std::string>());
else if (meshField.Name == "MaterialAssetGuids" && meshJson.contains("MaterialAssetGuids") && meshJson["MaterialAssetGuids"].is_array()) {
for (const auto& mGuidJson : meshJson["MaterialAssetGuids"]) {
mesh.MaterialAssetGuids.push_back(StringToGuid(mGuidJson.get<std::string>()));
}
}
else if (meshField.Name == "SourceModelAssetGuid" && meshJson.contains("SourceModelAssetGuid")) mesh.SourceModelAssetGuid = StringToGuid(meshJson["SourceModelAssetGuid"].get<std::string>());
else if (meshField.Name == "SourceModelPath" && meshJson.contains("SourceModelPath")) mesh.SourceModelPath = meshJson["SourceModelPath"].get<std::string>();
else if (meshField.Name == "SourceNodePath" && meshJson.contains("SourceNodePath")) mesh.SourceNodePath = meshJson["SourceNodePath"].get<std::string>();
else if (meshField.Name == "BaseColorTextureGuid" && meshJson.contains("BaseColorTextureGuid")) mesh.BaseColorTextureGuid = StringToGuid(meshJson["BaseColorTextureGuid"].get<std::string>());
else if (meshField.Name == "MetallicRoughnessTextureGuid" && meshJson.contains("MetallicRoughnessTextureGuid")) mesh.MetallicRoughnessTextureGuid = StringToGuid(meshJson["MetallicRoughnessTextureGuid"].get<std::string>());
else if (meshField.Name == "NormalTextureGuid" && meshJson.contains("NormalTextureGuid")) mesh.NormalTextureGuid = StringToGuid(meshJson["NormalTextureGuid"].get<std::string>());
else if (meshField.Name == "EmissiveTextureGuid" && meshJson.contains("EmissiveTextureGuid")) mesh.EmissiveTextureGuid = StringToGuid(meshJson["EmissiveTextureGuid"].get<std::string>());
else if (meshField.Name == "AoTextureGuid" && meshJson.contains("AoTextureGuid")) mesh.AoTextureGuid = StringToGuid(meshJson["AoTextureGuid"].get<std::string>());
else if (meshField.Name == "BaseColorTexturePath" && meshJson.contains("BaseColorTexturePath")) mesh.BaseColorTexturePath = meshJson["BaseColorTexturePath"].get<std::string>();
else if (meshField.Name == "MetallicRoughnessTexturePath" && meshJson.contains("MetallicRoughnessTexturePath")) mesh.MetallicRoughnessTexturePath = meshJson["MetallicRoughnessTexturePath"].get<std::string>();
else if (meshField.Name == "NormalTexturePath" && meshJson.contains("NormalTexturePath")) mesh.NormalTexturePath = meshJson["NormalTexturePath"].get<std::string>();
else if (meshField.Name == "EmissiveTexturePath" && meshJson.contains("EmissiveTexturePath")) mesh.EmissiveTexturePath = meshJson["EmissiveTexturePath"].get<std::string>();
else if (meshField.Name == "AoTexturePath" && meshJson.contains("AoTexturePath")) mesh.AoTexturePath = meshJson["AoTexturePath"].get<std::string>();
else if (meshField.Name == "DoubleSided" && meshJson.contains("DoubleSided")) mesh.DoubleSided = meshJson["DoubleSided"].get<bool>();
else if (meshField.Name == "Metallic" && meshJson.contains("Metallic")) mesh.Metallic = meshJson["Metallic"].get<float>();
else if (meshField.Name == "Roughness" && meshJson.contains("Roughness")) mesh.Roughness = meshJson["Roughness"].get<float>();
else if (meshField.Name == "AlphaMode" && meshJson.contains("AlphaMode")) mesh.AlphaMode = static_cast<MetaCoreMeshAlphaMode>(meshJson["AlphaMode"].get<int>());
else if (meshField.Name == "AlphaCutoff" && meshJson.contains("AlphaCutoff")) mesh.AlphaCutoff = meshJson["AlphaCutoff"].get<float>();
else if (meshField.Name == "EmissiveColor" && meshJson.contains("EmissiveColor")) mesh.EmissiveColor = JsonToVec3(meshJson["EmissiveColor"]);
else if (meshField.Name == "BaseColor" && meshJson.contains("BaseColor")) mesh.BaseColor = JsonToVec3(meshJson["BaseColor"]);
else if (meshField.Name == "ModelNodeIndex" && meshJson.contains("ModelNodeIndex")) mesh.ModelNodeIndex = meshJson["ModelNodeIndex"].get<std::int32_t>();
else if (meshField.Name == "SubMeshIndex" && meshJson.contains("SubMeshIndex")) mesh.SubMeshIndex = meshJson["SubMeshIndex"].get<std::int32_t>();
else if (meshField.Name == "Visible" && meshJson.contains("Visible")) mesh.Visible = meshJson["Visible"].get<bool>();
}
obj.MeshRenderer = mesh;
}
} else if (objField.Name == "Light" && objJson.contains("Light")) {
const auto& lightJson = objJson["Light"];
const MetaCoreStructDescriptor* lightDesc = registry.FindStruct<MetaCoreLightComponent>();
if (lightDesc) {
MetaCoreLightComponent light;
for (const auto& lightField : lightDesc->Fields) {
if (lightField.Name == "Color" && lightJson.contains("Color")) light.Color = JsonToVec3(lightJson["Color"]);
else if (lightField.Name == "Intensity" && lightJson.contains("Intensity")) light.Intensity = lightJson["Intensity"].get<float>();
else if (lightField.Name == "Enabled" && lightJson.contains("Enabled")) light.Enabled = lightJson["Enabled"].get<bool>();
}
obj.Light = light;
}
} else if (objField.Name == "Rotator" && objJson.contains("Rotator")) {
const auto& rotatorJson = objJson["Rotator"];
const MetaCoreStructDescriptor* rotatorDesc = registry.FindStruct<MetaCoreRotatorComponent>();
if (rotatorDesc) {
MetaCoreRotatorComponent rotator;
for (const auto& rotatorField : rotatorDesc->Fields) {
if (rotatorField.Name == "Enabled" && rotatorJson.contains("Enabled")) rotator.Enabled = rotatorJson["Enabled"].get<bool>();
else if (rotatorField.Name == "DegreesPerSecond" && rotatorJson.contains("DegreesPerSecond")) rotator.DegreesPerSecond = rotatorJson["DegreesPerSecond"].get<float>();
}
obj.Rotator = rotator;
}
} else if (objField.Name == "Script" && objJson.contains("Script")) {
const auto& scriptJson = objJson["Script"];
MetaCoreScriptComponent script;
if (scriptJson.contains("Instances") && scriptJson["Instances"].is_array()) {
for (const auto& instanceJson : scriptJson["Instances"]) {
MetaCoreScriptInstanceData instance;
if (instanceJson.contains("InstanceId")) {
instance.InstanceId = instanceJson["InstanceId"].get<std::uint64_t>();
}
if (instanceJson.contains("ScriptTypeId")) {
instance.ScriptTypeId = instanceJson["ScriptTypeId"].get<std::string>();
}
if (instanceJson.contains("Enabled")) {
instance.Enabled = instanceJson["Enabled"].get<bool>();
}
if (instanceJson.contains("FieldsJson")) {
instance.FieldsJson = instanceJson["FieldsJson"].get<std::string>();
}
if (!instance.ScriptTypeId.empty()) {
script.Instances.push_back(std::move(instance));
}
}
}
if (!script.Instances.empty()) {
obj.Script = std::move(script);
}
} else if (objField.Name == "Camera" && objJson.contains("Camera")) {
const auto& camJson = objJson["Camera"];
const MetaCoreStructDescriptor* camDesc = registry.FindStruct<MetaCoreCameraComponent>();
if (camDesc) {
MetaCoreCameraComponent cam;
for (const auto& camField : camDesc->Fields) {
if (camField.Name == "FieldOfViewDegrees" && camJson.contains("FieldOfViewDegrees")) cam.FieldOfViewDegrees = camJson["FieldOfViewDegrees"].get<float>();
else if (camField.Name == "NearClip" && camJson.contains("NearClip")) cam.NearClip = camJson["NearClip"].get<float>();
else if (camField.Name == "FarClip" && camJson.contains("FarClip")) cam.FarClip = camJson["FarClip"].get<float>();
else if (camField.Name == "IsPrimary" && camJson.contains("IsPrimary")) cam.IsPrimary = camJson["IsPrimary"].get<bool>();
else if (camField.Name == "Enabled" && camJson.contains("Enabled")) cam.Enabled = camJson["Enabled"].get<bool>();
else if (camField.Name == "ProjectionMode" && camJson.contains("ProjectionMode")) cam.ProjectionMode = static_cast<MetaCoreCameraProjectionMode>(camJson["ProjectionMode"].get<int>());
else if (camField.Name == "OrthographicSize" && camJson.contains("OrthographicSize")) cam.OrthographicSize = camJson["OrthographicSize"].get<float>();
else if (camField.Name == "Depth" && camJson.contains("Depth")) cam.Depth = camJson["Depth"].get<float>();
else if (camField.Name == "CullingMask" && camJson.contains("CullingMask")) cam.CullingMask = camJson["CullingMask"].get<std::uint32_t>();
else if (camField.Name == "ClearFlags" && camJson.contains("ClearFlags")) cam.ClearFlags = static_cast<MetaCoreCameraClearFlags>(camJson["ClearFlags"].get<int>());
else if (camField.Name == "BackgroundColor" && camJson.contains("BackgroundColor")) cam.BackgroundColor = JsonToVec3(camJson["BackgroundColor"]);
else if (camField.Name == "BackgroundAlpha" && camJson.contains("BackgroundAlpha")) cam.BackgroundAlpha = camJson["BackgroundAlpha"].get<float>();
}
obj.Camera = cam;
}
} else if (objField.Name == "PrefabInstance" && objJson.contains("PrefabInstance")) {
const auto& prefabJson = objJson["PrefabInstance"];
const MetaCoreStructDescriptor* prefabDesc = registry.FindStruct<MetaCorePrefabInstanceMetadata>();
if (prefabDesc) {
MetaCorePrefabInstanceMetadata prefab;
for (const auto& prefabField : prefabDesc->Fields) {
if (prefabField.Name == "PrefabAssetGuid" && prefabJson.contains("PrefabAssetGuid")) prefab.PrefabAssetGuid = StringToGuid(prefabJson["PrefabAssetGuid"].get<std::string>());
else if (prefabField.Name == "PrefabObjectId" && prefabJson.contains("PrefabObjectId")) prefab.PrefabObjectId = prefabJson["PrefabObjectId"].get<MetaCoreId>();
else if (prefabField.Name == "PrefabInstanceRootId" && prefabJson.contains("PrefabInstanceRootId")) prefab.PrefabInstanceRootId = prefabJson["PrefabInstanceRootId"].get<MetaCoreId>();
}
obj.PrefabInstance = prefab;
}
}
}
return obj;
}
bool MetaCoreSceneSerializer::SaveSceneToJson(
const std::filesystem::path& absolutePath,
const MetaCoreSceneDocument& sceneDocument,
const MetaCoreTypeRegistry& registry
) {
try {
json sceneJson;
// 验证 MetaCoreSceneDocument 反射注册
const MetaCoreStructDescriptor* sceneDesc = registry.FindStruct<MetaCoreSceneDocument>();
if (!sceneDesc) {
std::cerr << "SaveSceneToJson: 未能找到 MetaCoreSceneDocument 反射描述" << std::endl;
return false;
}
for (const auto& field : sceneDesc->Fields) {
if (field.Name == "Name") {
sceneJson["SceneName"] = sceneDocument.Name;
} else if (field.Name == "Environment") {
sceneJson["Environment"] = SceneEnvironmentToJson(sceneDocument.Environment);
} else if (field.Name == "Selection") {
const MetaCoreStructDescriptor* selDesc = registry.FindStruct<MetaCoreEditorSelectionSnapshot>();
if (selDesc) {
json selJson = json::object();
for (const auto& selField : selDesc->Fields) {
if (selField.Name == "SelectedObjectIds") selJson["SelectedObjectIds"] = sceneDocument.Selection.SelectedObjectIds;
else if (selField.Name == "ActiveObjectId") selJson["ActiveObjectId"] = sceneDocument.Selection.ActiveObjectId;
else if (selField.Name == "SelectionAnchorId") selJson["SelectionAnchorId"] = sceneDocument.Selection.SelectionAnchorId;
}
sceneJson["Selection"] = selJson;
}
} else if (field.Name == "GameObjects") {
json gameObjectsArray = json::array();
for (const auto& obj : sceneDocument.GameObjects) {
gameObjectsArray.push_back(GameObjectDataToJson(obj, registry));
}
sceneJson["GameObjects"] = gameObjectsArray;
}
}
std::ofstream file(absolutePath);
if (!file.is_open()) {
std::cerr << "SaveSceneToJson: 无法打开文件写入 " << absolutePath << std::endl;
return false;
}
file << sceneJson.dump(4);
return true;
} catch (const std::exception& e) {
std::cerr << "SaveSceneToJson: 发生异常 - " << e.what() << std::endl;
return false;
}
}
std::optional<MetaCoreSceneDocument> MetaCoreSceneSerializer::LoadSceneFromJson(
const std::filesystem::path& absolutePath,
const MetaCoreTypeRegistry& registry
) {
try {
std::ifstream file(absolutePath);
if (!file.is_open()) {
std::cerr << "LoadSceneFromJson: 无法打开文件进行读取 " << absolutePath << std::endl;
return std::nullopt;
}
json sceneJson;
file >> sceneJson;
MetaCoreSceneDocument sceneDocument;
// 验证 MetaCoreSceneDocument 反射注册
const MetaCoreStructDescriptor* sceneDesc = registry.FindStruct<MetaCoreSceneDocument>();
if (!sceneDesc) {
std::cerr << "LoadSceneFromJson: 未能找到 MetaCoreSceneDocument 反射描述" << std::endl;
return std::nullopt;
}
for (const auto& field : sceneDesc->Fields) {
if (field.Name == "Name" && sceneJson.contains("SceneName")) {
sceneDocument.Name = sceneJson["SceneName"].get<std::string>();
} else if (field.Name == "Environment" && sceneJson.contains("Environment")) {
sceneDocument.Environment = JsonToSceneEnvironment(sceneJson["Environment"]);
} else if (field.Name == "Selection" && sceneJson.contains("Selection")) {
const auto& selectionJson = sceneJson["Selection"];
const MetaCoreStructDescriptor* selDesc = registry.FindStruct<MetaCoreEditorSelectionSnapshot>();
if (selDesc) {
for (const auto& selField : selDesc->Fields) {
if (selField.Name == "SelectedObjectIds" && selectionJson.contains("SelectedObjectIds")) {
sceneDocument.Selection.SelectedObjectIds = selectionJson["SelectedObjectIds"].get<std::vector<MetaCoreId>>();
} else if (selField.Name == "ActiveObjectId" && selectionJson.contains("ActiveObjectId")) {
sceneDocument.Selection.ActiveObjectId = selectionJson["ActiveObjectId"].get<MetaCoreId>();
} else if (selField.Name == "SelectionAnchorId" && selectionJson.contains("SelectionAnchorId")) {
sceneDocument.Selection.SelectionAnchorId = selectionJson["SelectionAnchorId"].get<MetaCoreId>();
}
}
}
} else if (field.Name == "GameObjects" && sceneJson.contains("GameObjects") && sceneJson["GameObjects"].is_array()) {
for (const auto& objJson : sceneJson["GameObjects"]) {
sceneDocument.GameObjects.push_back(JsonToGameObjectData(objJson, registry));
}
}
}
return sceneDocument;
} catch (const std::exception& e) {
std::cerr << "LoadSceneFromJson: 发生异常 - " << e.what() << std::endl;
return std::nullopt;
}
}
// Prefab
bool MetaCoreSceneSerializer::SavePrefabToJson(
const std::filesystem::path& absolutePath,
const MetaCorePrefabDocument& prefabDocument,
const MetaCoreTypeRegistry& registry
) {
try {
json prefabJson;
prefabJson["PrefabName"] = prefabDocument.Name;
json gameObjectsArray = json::array();
for (const auto& obj : prefabDocument.GameObjects) {
gameObjectsArray.push_back(GameObjectDataToJson(obj, registry));
}
prefabJson["GameObjects"] = gameObjectsArray;
std::ofstream file(absolutePath);
if (!file.is_open()) {
return false;
}
file << prefabJson.dump(4);
return true;
} catch (...) {
return false;
}
}
std::optional<MetaCorePrefabDocument> MetaCoreSceneSerializer::LoadPrefabFromJson(
const std::filesystem::path& absolutePath,
const MetaCoreTypeRegistry& registry
) {
try {
std::ifstream file(absolutePath);
if (!file.is_open()) {
return std::nullopt;
}
json prefabJson;
file >> prefabJson;
MetaCorePrefabDocument doc;
if (prefabJson.contains("PrefabName")) {
doc.Name = prefabJson["PrefabName"].get<std::string>();
}
if (prefabJson.contains("GameObjects") && prefabJson["GameObjects"].is_array()) {
for (const auto& objJson : prefabJson["GameObjects"]) {
doc.GameObjects.push_back(JsonToGameObjectData(objJson, registry));
}
}
return doc;
} catch (...) {
return std::nullopt;
}
}
// Material
bool MetaCoreSceneSerializer::SaveMaterialToJson(
const std::filesystem::path& absolutePath,
const MetaCoreMaterialAssetDocument& doc,
const MetaCoreTypeRegistry& registry
) {
(void)registry;
try {
json matJson;
matJson["AssetGuid"] = GuidToString(doc.AssetGuid);
matJson["Name"] = doc.Name;
matJson["StableImportKey"] = doc.StableImportKey;
matJson["ShaderModel"] = static_cast<int>(doc.ShaderModel);
matJson["BaseColor"] = Vec3ToJson(doc.BaseColor);
matJson["BaseColorTexture"] = GuidToString(doc.BaseColorTexture);
matJson["NormalTexture"] = GuidToString(doc.NormalTexture);
matJson["Metallic"] = doc.Metallic;
matJson["Roughness"] = doc.Roughness;
matJson["MetallicRoughnessTexture"] = GuidToString(doc.MetallicRoughnessTexture);
matJson["AoTexture"] = GuidToString(doc.AoTexture);
matJson["EmissiveColor"] = Vec3ToJson(doc.EmissiveColor);
matJson["EmissiveTexture"] = GuidToString(doc.EmissiveTexture);
matJson["AlphaMode"] = static_cast<int>(doc.AlphaMode);
matJson["AlphaCutoff"] = doc.AlphaCutoff;
matJson["DoubleSided"] = doc.DoubleSided;
std::ofstream file(absolutePath);
if (!file.is_open()) {
return false;
}
file << matJson.dump(4);
return true;
} catch (...) {
return false;
}
}
std::optional<MetaCoreMaterialAssetDocument> MetaCoreSceneSerializer::LoadMaterialFromJson(
const std::filesystem::path& absolutePath,
const MetaCoreTypeRegistry& registry
) {
(void)registry;
try {
std::ifstream file(absolutePath);
if (!file.is_open()) {
return std::nullopt;
}
json matJson;
file >> matJson;
MetaCoreMaterialAssetDocument doc;
if (matJson.contains("AssetGuid")) doc.AssetGuid = StringToGuid(matJson["AssetGuid"].get<std::string>());
if (matJson.contains("Name")) doc.Name = matJson["Name"].get<std::string>();
if (matJson.contains("StableImportKey")) doc.StableImportKey = matJson["StableImportKey"].get<std::string>();
if (matJson.contains("ShaderModel")) doc.ShaderModel = static_cast<MetaCoreMaterialShaderModel>(matJson["ShaderModel"].get<int>());
if (matJson.contains("BaseColor")) doc.BaseColor = JsonToVec3(matJson["BaseColor"]);
if (matJson.contains("BaseColorTexture")) doc.BaseColorTexture = StringToGuid(matJson["BaseColorTexture"].get<std::string>());
if (matJson.contains("NormalTexture")) doc.NormalTexture = StringToGuid(matJson["NormalTexture"].get<std::string>());
if (matJson.contains("Metallic")) doc.Metallic = matJson["Metallic"].get<float>();
if (matJson.contains("Roughness")) doc.Roughness = matJson["Roughness"].get<float>();
if (matJson.contains("MetallicRoughnessTexture")) doc.MetallicRoughnessTexture = StringToGuid(matJson["MetallicRoughnessTexture"].get<std::string>());
if (matJson.contains("AoTexture")) doc.AoTexture = StringToGuid(matJson["AoTexture"].get<std::string>());
if (matJson.contains("EmissiveColor")) doc.EmissiveColor = JsonToVec3(matJson["EmissiveColor"]);
if (matJson.contains("EmissiveTexture")) doc.EmissiveTexture = StringToGuid(matJson["EmissiveTexture"].get<std::string>());
if (matJson.contains("AlphaMode")) doc.AlphaMode = static_cast<MetaCoreMaterialAlphaMode>(matJson["AlphaMode"].get<int>());
if (matJson.contains("AlphaCutoff")) doc.AlphaCutoff = matJson["AlphaCutoff"].get<float>();
if (matJson.contains("DoubleSided")) doc.DoubleSided = matJson["DoubleSided"].get<bool>();
return doc;
} catch (...) {
return std::nullopt;
}
}
// UI 序列化辅助方法
static json RectTransformToJson(const MetaCoreUiRectTransformDocument& trans) {
json j = json::object();
j["AnchorMin"] = Vec3ToJson(trans.AnchorMin);
j["AnchorMax"] = Vec3ToJson(trans.AnchorMax);
j["Pivot"] = Vec3ToJson(trans.Pivot);
j["Position"] = Vec3ToJson(trans.Position);
j["Size"] = Vec3ToJson(trans.Size);
return j;
}
static MetaCoreUiRectTransformDocument JsonToRectTransform(const json& j) {
MetaCoreUiRectTransformDocument trans;
if (j.contains("AnchorMin")) trans.AnchorMin = JsonToVec3(j["AnchorMin"]);
if (j.contains("AnchorMax")) trans.AnchorMax = JsonToVec3(j["AnchorMax"]);
if (j.contains("Pivot")) trans.Pivot = JsonToVec3(j["Pivot"]);
if (j.contains("Position")) trans.Position = JsonToVec3(j["Position"]);
if (j.contains("Size")) trans.Size = JsonToVec3(j["Size"]);
return trans;
}
static json UiStyleToJson(const MetaCoreUiStyleDocument& style) {
json j = json::object();
j["BackgroundColor"] = Vec3ToJson(style.BackgroundColor);
j["TextColor"] = Vec3ToJson(style.TextColor);
j["TintColor"] = Vec3ToJson(style.TintColor);
j["FontSize"] = style.FontSize;
j["Padding"] = Vec3ToJson(style.Padding);
j["HorizontalAlignment"] = static_cast<int>(style.HorizontalAlignment);
j["VerticalAlignment"] = static_cast<int>(style.VerticalAlignment);
j["ImageAssetGuid"] = GuidToString(style.ImageAssetGuid);
j["PreserveAspect"] = style.PreserveAspect;
return j;
}
static MetaCoreUiStyleDocument JsonToUiStyle(const json& j) {
MetaCoreUiStyleDocument style;
if (j.contains("BackgroundColor")) style.BackgroundColor = JsonToVec3(j["BackgroundColor"]);
if (j.contains("TextColor")) style.TextColor = JsonToVec3(j["TextColor"]);
if (j.contains("TintColor")) style.TintColor = JsonToVec3(j["TintColor"]);
if (j.contains("FontSize")) style.FontSize = j["FontSize"].get<float>();
if (j.contains("Padding")) style.Padding = JsonToVec3(j["Padding"]);
if (j.contains("HorizontalAlignment")) style.HorizontalAlignment = static_cast<MetaCoreUiHorizontalAlignment>(j["HorizontalAlignment"].get<int>());
if (j.contains("VerticalAlignment")) style.VerticalAlignment = static_cast<MetaCoreUiVerticalAlignment>(j["VerticalAlignment"].get<int>());
if (j.contains("ImageAssetGuid")) style.ImageAssetGuid = StringToGuid(j["ImageAssetGuid"].get<std::string>());
if (j.contains("PreserveAspect")) style.PreserveAspect = j["PreserveAspect"].get<bool>();
return style;
}
static json UiNodeToJson(const MetaCoreUiNodeDocument& node) {
json j = json::object();
j["Id"] = node.Id;
j["Name"] = node.Name;
j["Type"] = static_cast<int>(node.Type);
j["ParentId"] = node.ParentId;
j["Children"] = node.Children;
j["Visible"] = node.Visible;
j["RectTransform"] = RectTransformToJson(node.RectTransform);
j["Style"] = UiStyleToJson(node.Style);
j["Text"] = node.Text;
j["Interactable"] = node.Interactable;
return j;
}
static MetaCoreUiNodeDocument JsonToUiNode(const json& j) {
MetaCoreUiNodeDocument node;
if (j.contains("Id")) node.Id = j["Id"].get<std::string>();
if (j.contains("Name")) node.Name = j["Name"].get<std::string>();
if (j.contains("Type")) node.Type = static_cast<MetaCoreUiNodeType>(j["Type"].get<int>());
if (j.contains("ParentId")) node.ParentId = j["ParentId"].get<std::string>();
if (j.contains("Children")) node.Children = j["Children"].get<std::vector<std::string>>();
if (j.contains("Visible")) node.Visible = j["Visible"].get<bool>();
if (j.contains("RectTransform")) node.RectTransform = JsonToRectTransform(j["RectTransform"]);
if (j.contains("Style")) node.Style = JsonToUiStyle(j["Style"]);
if (j.contains("Text")) node.Text = j["Text"].get<std::string>();
if (j.contains("Interactable")) node.Interactable = j["Interactable"].get<bool>();
return node;
}
bool MetaCoreSceneSerializer::SaveUiToJson(
const std::filesystem::path& absolutePath,
const MetaCoreUiDocument& uiDocument,
const MetaCoreTypeRegistry& registry
) {
(void)registry;
try {
json uiJson;
uiJson["Name"] = uiDocument.Name;
uiJson["ReferenceWidth"] = uiDocument.ReferenceWidth;
uiJson["ReferenceHeight"] = uiDocument.ReferenceHeight;
uiJson["RootNodeIds"] = uiDocument.RootNodeIds;
json nodesArray = json::array();
for (const auto& node : uiDocument.Nodes) {
nodesArray.push_back(UiNodeToJson(node));
}
uiJson["Nodes"] = nodesArray;
std::ofstream file(absolutePath);
if (!file.is_open()) {
return false;
}
file << uiJson.dump(4);
return true;
} catch (...) {
return false;
}
}
std::optional<MetaCoreUiDocument> MetaCoreSceneSerializer::LoadUiFromJson(
const std::filesystem::path& absolutePath,
const MetaCoreTypeRegistry& registry
) {
(void)registry;
try {
std::ifstream file(absolutePath);
if (!file.is_open()) {
return std::nullopt;
}
json uiJson;
file >> uiJson;
MetaCoreUiDocument doc;
if (uiJson.contains("Name")) doc.Name = uiJson["Name"].get<std::string>();
if (uiJson.contains("ReferenceWidth")) doc.ReferenceWidth = uiJson["ReferenceWidth"].get<std::int32_t>();
if (uiJson.contains("ReferenceHeight")) doc.ReferenceHeight = uiJson["ReferenceHeight"].get<std::int32_t>();
if (uiJson.contains("RootNodeIds")) doc.RootNodeIds = uiJson["RootNodeIds"].get<std::vector<std::string>>();
if (uiJson.contains("Nodes") && uiJson["Nodes"].is_array()) {
for (const auto& nodeJson : uiJson["Nodes"]) {
doc.Nodes.push_back(JsonToUiNode(nodeJson));
}
}
return doc;
} catch (...) {
return std::nullopt;
}
}
} // namespace MetaCore