#include "MetaCoreScene/MetaCoreSceneSerializer.h" #include "MetaCoreFoundation/MetaCoreReflection.h" #include #include #include #include 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(), j[1].get(), j[2].get()); } 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(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(environmentJson["Source"].get()); if (environmentJson.contains("IblKtxPath")) environment.IblKtxPath = environmentJson["IblKtxPath"].get(); if (environmentJson.contains("SkyboxKtxPath")) environment.SkyboxKtxPath = environmentJson["SkyboxKtxPath"].get(); if (environmentJson.contains("SkyboxVisible")) environment.SkyboxVisible = environmentJson["SkyboxVisible"].get(); if (environmentJson.contains("RotationDegrees")) environment.RotationDegrees = environmentJson["RotationDegrees"].get(); if (environmentJson.contains("IndirectLightIntensity")) environment.IndirectLightIntensity = environmentJson["IndirectLightIntensity"].get(); if (environmentJson.contains("SkyboxIntensity")) environment.SkyboxIntensity = environmentJson["SkyboxIntensity"].get(); return environment; } // 辅助方法:将单个 MetaCoreGameObjectData 转换为 json 格式 static json GameObjectDataToJson(const MetaCoreGameObjectData& obj, const MetaCoreTypeRegistry& registry) { json objJson = json::object(); const MetaCoreStructDescriptor* objDesc = registry.FindStruct(); 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(); 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(); 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(mesh.MeshSource); else if (meshField.Name == "BuiltinMesh") meshJson["BuiltinMesh"] = static_cast(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(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(); 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(); 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 == "Animator" && obj.Animator.has_value()) { const MetaCoreStructDescriptor* animatorDesc = registry.FindStruct(); if (animatorDesc) { json animatorJson = json::object(); const auto& animator = obj.Animator.value(); for (const auto& animatorField : animatorDesc->Fields) { if (animatorField.Name == "Enabled") animatorJson["Enabled"] = animator.Enabled; else if (animatorField.Name == "SourceModelAssetGuid") animatorJson["SourceModelAssetGuid"] = GuidToString(animator.SourceModelAssetGuid); else if (animatorField.Name == "SourceModelPath") animatorJson["SourceModelPath"] = animator.SourceModelPath; else if (animatorField.Name == "ClipIndex") animatorJson["ClipIndex"] = animator.ClipIndex; else if (animatorField.Name == "ClipName") animatorJson["ClipName"] = animator.ClipName; else if (animatorField.Name == "PlayOnStart") animatorJson["PlayOnStart"] = animator.PlayOnStart; else if (animatorField.Name == "Loop") animatorJson["Loop"] = animator.Loop; else if (animatorField.Name == "Speed") animatorJson["Speed"] = animator.Speed; } objJson["Animator"] = std::move(animatorJson); } } 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 == "UiRenderer" && obj.UiRenderer.has_value()) { const MetaCoreStructDescriptor* uiDesc = registry.FindStruct(); if (uiDesc) { json uiJson = json::object(); const auto& ui = obj.UiRenderer.value(); for (const auto& uiField : uiDesc->Fields) { if (uiField.Name == "UiDocumentAssetGuid") uiJson["UiDocumentAssetGuid"] = GuidToString(ui.UiDocumentAssetGuid); else if (uiField.Name == "RenderMode") uiJson["RenderMode"] = static_cast(ui.RenderMode); else if (uiField.Name == "Visible") uiJson["Visible"] = ui.Visible; else if (uiField.Name == "InputEnabled") uiJson["InputEnabled"] = ui.InputEnabled; else if (uiField.Name == "FaceCamera") uiJson["FaceCamera"] = ui.FaceCamera; else if (uiField.Name == "Layer") uiJson["Layer"] = ui.Layer; else if (uiField.Name == "PixelsPerUnit") uiJson["PixelsPerUnit"] = ui.PixelsPerUnit; else if (uiField.Name == "WorldSize") uiJson["WorldSize"] = Vec3ToJson(ui.WorldSize); } objJson["UiRenderer"] = std::move(uiJson); } } else if (objField.Name == "Camera" && obj.Camera.has_value()) { const MetaCoreStructDescriptor* camDesc = registry.FindStruct(); 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(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(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(); 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(); if (!objDesc) return obj; for (const auto& objField : objDesc->Fields) { if (objField.Name == "Id" && objJson.contains("Id")) { obj.Id = objJson["Id"].get(); } else if (objField.Name == "ParentId" && objJson.contains("ParentId")) { obj.ParentId = objJson["ParentId"].get(); } else if (objField.Name == "Name" && objJson.contains("Name")) { obj.Name = objJson["Name"].get(); } else if (objField.Name == "Transform" && objJson.contains("Transform")) { const auto& transJson = objJson["Transform"]; const MetaCoreStructDescriptor* transDesc = registry.FindStruct(); 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(); if (meshDesc) { MetaCoreMeshRendererComponent mesh; for (const auto& meshField : meshDesc->Fields) { if (meshField.Name == "MeshSource" && meshJson.contains("MeshSource")) mesh.MeshSource = static_cast(meshJson["MeshSource"].get()); else if (meshField.Name == "BuiltinMesh" && meshJson.contains("BuiltinMesh")) mesh.BuiltinMesh = static_cast(meshJson["BuiltinMesh"].get()); else if (meshField.Name == "MeshAssetGuid" && meshJson.contains("MeshAssetGuid")) mesh.MeshAssetGuid = StringToGuid(meshJson["MeshAssetGuid"].get()); 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())); } } else if (meshField.Name == "SourceModelAssetGuid" && meshJson.contains("SourceModelAssetGuid")) mesh.SourceModelAssetGuid = StringToGuid(meshJson["SourceModelAssetGuid"].get()); else if (meshField.Name == "SourceModelPath" && meshJson.contains("SourceModelPath")) mesh.SourceModelPath = meshJson["SourceModelPath"].get(); else if (meshField.Name == "SourceNodePath" && meshJson.contains("SourceNodePath")) mesh.SourceNodePath = meshJson["SourceNodePath"].get(); else if (meshField.Name == "BaseColorTextureGuid" && meshJson.contains("BaseColorTextureGuid")) mesh.BaseColorTextureGuid = StringToGuid(meshJson["BaseColorTextureGuid"].get()); else if (meshField.Name == "MetallicRoughnessTextureGuid" && meshJson.contains("MetallicRoughnessTextureGuid")) mesh.MetallicRoughnessTextureGuid = StringToGuid(meshJson["MetallicRoughnessTextureGuid"].get()); else if (meshField.Name == "NormalTextureGuid" && meshJson.contains("NormalTextureGuid")) mesh.NormalTextureGuid = StringToGuid(meshJson["NormalTextureGuid"].get()); else if (meshField.Name == "EmissiveTextureGuid" && meshJson.contains("EmissiveTextureGuid")) mesh.EmissiveTextureGuid = StringToGuid(meshJson["EmissiveTextureGuid"].get()); else if (meshField.Name == "AoTextureGuid" && meshJson.contains("AoTextureGuid")) mesh.AoTextureGuid = StringToGuid(meshJson["AoTextureGuid"].get()); else if (meshField.Name == "BaseColorTexturePath" && meshJson.contains("BaseColorTexturePath")) mesh.BaseColorTexturePath = meshJson["BaseColorTexturePath"].get(); else if (meshField.Name == "MetallicRoughnessTexturePath" && meshJson.contains("MetallicRoughnessTexturePath")) mesh.MetallicRoughnessTexturePath = meshJson["MetallicRoughnessTexturePath"].get(); else if (meshField.Name == "NormalTexturePath" && meshJson.contains("NormalTexturePath")) mesh.NormalTexturePath = meshJson["NormalTexturePath"].get(); else if (meshField.Name == "EmissiveTexturePath" && meshJson.contains("EmissiveTexturePath")) mesh.EmissiveTexturePath = meshJson["EmissiveTexturePath"].get(); else if (meshField.Name == "AoTexturePath" && meshJson.contains("AoTexturePath")) mesh.AoTexturePath = meshJson["AoTexturePath"].get(); else if (meshField.Name == "DoubleSided" && meshJson.contains("DoubleSided")) mesh.DoubleSided = meshJson["DoubleSided"].get(); else if (meshField.Name == "Metallic" && meshJson.contains("Metallic")) mesh.Metallic = meshJson["Metallic"].get(); else if (meshField.Name == "Roughness" && meshJson.contains("Roughness")) mesh.Roughness = meshJson["Roughness"].get(); else if (meshField.Name == "AlphaMode" && meshJson.contains("AlphaMode")) mesh.AlphaMode = static_cast(meshJson["AlphaMode"].get()); else if (meshField.Name == "AlphaCutoff" && meshJson.contains("AlphaCutoff")) mesh.AlphaCutoff = meshJson["AlphaCutoff"].get(); 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(); else if (meshField.Name == "SubMeshIndex" && meshJson.contains("SubMeshIndex")) mesh.SubMeshIndex = meshJson["SubMeshIndex"].get(); else if (meshField.Name == "Visible" && meshJson.contains("Visible")) mesh.Visible = meshJson["Visible"].get(); } obj.MeshRenderer = mesh; } } else if (objField.Name == "Light" && objJson.contains("Light")) { const auto& lightJson = objJson["Light"]; const MetaCoreStructDescriptor* lightDesc = registry.FindStruct(); 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(); else if (lightField.Name == "Enabled" && lightJson.contains("Enabled")) light.Enabled = lightJson["Enabled"].get(); } obj.Light = light; } } else if (objField.Name == "Rotator" && objJson.contains("Rotator")) { const auto& rotatorJson = objJson["Rotator"]; const MetaCoreStructDescriptor* rotatorDesc = registry.FindStruct(); if (rotatorDesc) { MetaCoreRotatorComponent rotator; for (const auto& rotatorField : rotatorDesc->Fields) { if (rotatorField.Name == "Enabled" && rotatorJson.contains("Enabled")) rotator.Enabled = rotatorJson["Enabled"].get(); else if (rotatorField.Name == "DegreesPerSecond" && rotatorJson.contains("DegreesPerSecond")) rotator.DegreesPerSecond = rotatorJson["DegreesPerSecond"].get(); } obj.Rotator = rotator; } } else if (objField.Name == "Animator" && objJson.contains("Animator")) { const auto& animatorJson = objJson["Animator"]; const MetaCoreStructDescriptor* animatorDesc = registry.FindStruct(); if (animatorDesc) { MetaCoreAnimatorComponent animator; for (const auto& animatorField : animatorDesc->Fields) { if (animatorField.Name == "Enabled" && animatorJson.contains("Enabled")) animator.Enabled = animatorJson["Enabled"].get(); else if (animatorField.Name == "SourceModelAssetGuid" && animatorJson.contains("SourceModelAssetGuid")) animator.SourceModelAssetGuid = StringToGuid(animatorJson["SourceModelAssetGuid"].get()); else if (animatorField.Name == "SourceModelPath" && animatorJson.contains("SourceModelPath")) animator.SourceModelPath = animatorJson["SourceModelPath"].get(); else if (animatorField.Name == "ClipIndex" && animatorJson.contains("ClipIndex")) animator.ClipIndex = animatorJson["ClipIndex"].get(); else if (animatorField.Name == "ClipName" && animatorJson.contains("ClipName")) animator.ClipName = animatorJson["ClipName"].get(); else if (animatorField.Name == "PlayOnStart" && animatorJson.contains("PlayOnStart")) animator.PlayOnStart = animatorJson["PlayOnStart"].get(); else if (animatorField.Name == "Loop" && animatorJson.contains("Loop")) animator.Loop = animatorJson["Loop"].get(); else if (animatorField.Name == "Speed" && animatorJson.contains("Speed")) animator.Speed = animatorJson["Speed"].get(); } obj.Animator = animator; } } 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(); } if (instanceJson.contains("ScriptTypeId")) { instance.ScriptTypeId = instanceJson["ScriptTypeId"].get(); } if (instanceJson.contains("Enabled")) { instance.Enabled = instanceJson["Enabled"].get(); } if (instanceJson.contains("FieldsJson")) { instance.FieldsJson = instanceJson["FieldsJson"].get(); } if (!instance.ScriptTypeId.empty()) { script.Instances.push_back(std::move(instance)); } } } if (!script.Instances.empty()) { obj.Script = std::move(script); } } else if (objField.Name == "UiRenderer" && objJson.contains("UiRenderer")) { const auto& uiJson = objJson["UiRenderer"]; const MetaCoreStructDescriptor* uiDesc = registry.FindStruct(); if (uiDesc) { MetaCoreUiRendererComponent ui; for (const auto& uiField : uiDesc->Fields) { if (uiField.Name == "UiDocumentAssetGuid" && uiJson.contains("UiDocumentAssetGuid")) ui.UiDocumentAssetGuid = StringToGuid(uiJson["UiDocumentAssetGuid"].get()); else if (uiField.Name == "RenderMode" && uiJson.contains("RenderMode")) ui.RenderMode = static_cast(uiJson["RenderMode"].get()); else if (uiField.Name == "Visible" && uiJson.contains("Visible")) ui.Visible = uiJson["Visible"].get(); else if (uiField.Name == "InputEnabled" && uiJson.contains("InputEnabled")) ui.InputEnabled = uiJson["InputEnabled"].get(); else if (uiField.Name == "FaceCamera" && uiJson.contains("FaceCamera")) ui.FaceCamera = uiJson["FaceCamera"].get(); else if (uiField.Name == "Layer" && uiJson.contains("Layer")) ui.Layer = uiJson["Layer"].get(); else if (uiField.Name == "PixelsPerUnit" && uiJson.contains("PixelsPerUnit")) ui.PixelsPerUnit = uiJson["PixelsPerUnit"].get(); else if (uiField.Name == "WorldSize" && uiJson.contains("WorldSize")) ui.WorldSize = JsonToVec3(uiJson["WorldSize"]); } obj.UiRenderer = ui; } } else if (objField.Name == "Camera" && objJson.contains("Camera")) { const auto& camJson = objJson["Camera"]; const MetaCoreStructDescriptor* camDesc = registry.FindStruct(); if (camDesc) { MetaCoreCameraComponent cam; for (const auto& camField : camDesc->Fields) { if (camField.Name == "FieldOfViewDegrees" && camJson.contains("FieldOfViewDegrees")) cam.FieldOfViewDegrees = camJson["FieldOfViewDegrees"].get(); else if (camField.Name == "NearClip" && camJson.contains("NearClip")) cam.NearClip = camJson["NearClip"].get(); else if (camField.Name == "FarClip" && camJson.contains("FarClip")) cam.FarClip = camJson["FarClip"].get(); else if (camField.Name == "IsPrimary" && camJson.contains("IsPrimary")) cam.IsPrimary = camJson["IsPrimary"].get(); else if (camField.Name == "Enabled" && camJson.contains("Enabled")) cam.Enabled = camJson["Enabled"].get(); else if (camField.Name == "ProjectionMode" && camJson.contains("ProjectionMode")) cam.ProjectionMode = static_cast(camJson["ProjectionMode"].get()); else if (camField.Name == "OrthographicSize" && camJson.contains("OrthographicSize")) cam.OrthographicSize = camJson["OrthographicSize"].get(); else if (camField.Name == "Depth" && camJson.contains("Depth")) cam.Depth = camJson["Depth"].get(); else if (camField.Name == "CullingMask" && camJson.contains("CullingMask")) cam.CullingMask = camJson["CullingMask"].get(); else if (camField.Name == "ClearFlags" && camJson.contains("ClearFlags")) cam.ClearFlags = static_cast(camJson["ClearFlags"].get()); 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(); } obj.Camera = cam; } } else if (objField.Name == "PrefabInstance" && objJson.contains("PrefabInstance")) { const auto& prefabJson = objJson["PrefabInstance"]; const MetaCoreStructDescriptor* prefabDesc = registry.FindStruct(); if (prefabDesc) { MetaCorePrefabInstanceMetadata prefab; for (const auto& prefabField : prefabDesc->Fields) { if (prefabField.Name == "PrefabAssetGuid" && prefabJson.contains("PrefabAssetGuid")) prefab.PrefabAssetGuid = StringToGuid(prefabJson["PrefabAssetGuid"].get()); else if (prefabField.Name == "PrefabObjectId" && prefabJson.contains("PrefabObjectId")) prefab.PrefabObjectId = prefabJson["PrefabObjectId"].get(); else if (prefabField.Name == "PrefabInstanceRootId" && prefabJson.contains("PrefabInstanceRootId")) prefab.PrefabInstanceRootId = prefabJson["PrefabInstanceRootId"].get(); } 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(); 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(); 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 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(); 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(); } 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(); if (selDesc) { for (const auto& selField : selDesc->Fields) { if (selField.Name == "SelectedObjectIds" && selectionJson.contains("SelectedObjectIds")) { sceneDocument.Selection.SelectedObjectIds = selectionJson["SelectedObjectIds"].get>(); } else if (selField.Name == "ActiveObjectId" && selectionJson.contains("ActiveObjectId")) { sceneDocument.Selection.ActiveObjectId = selectionJson["ActiveObjectId"].get(); } else if (selField.Name == "SelectionAnchorId" && selectionJson.contains("SelectionAnchorId")) { sceneDocument.Selection.SelectionAnchorId = selectionJson["SelectionAnchorId"].get(); } } } } 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 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(); } 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(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(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 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()); if (matJson.contains("Name")) doc.Name = matJson["Name"].get(); if (matJson.contains("StableImportKey")) doc.StableImportKey = matJson["StableImportKey"].get(); if (matJson.contains("ShaderModel")) doc.ShaderModel = static_cast(matJson["ShaderModel"].get()); if (matJson.contains("BaseColor")) doc.BaseColor = JsonToVec3(matJson["BaseColor"]); if (matJson.contains("BaseColorTexture")) doc.BaseColorTexture = StringToGuid(matJson["BaseColorTexture"].get()); if (matJson.contains("NormalTexture")) doc.NormalTexture = StringToGuid(matJson["NormalTexture"].get()); if (matJson.contains("Metallic")) doc.Metallic = matJson["Metallic"].get(); if (matJson.contains("Roughness")) doc.Roughness = matJson["Roughness"].get(); if (matJson.contains("MetallicRoughnessTexture")) doc.MetallicRoughnessTexture = StringToGuid(matJson["MetallicRoughnessTexture"].get()); if (matJson.contains("AoTexture")) doc.AoTexture = StringToGuid(matJson["AoTexture"].get()); if (matJson.contains("EmissiveColor")) doc.EmissiveColor = JsonToVec3(matJson["EmissiveColor"]); if (matJson.contains("EmissiveTexture")) doc.EmissiveTexture = StringToGuid(matJson["EmissiveTexture"].get()); if (matJson.contains("AlphaMode")) doc.AlphaMode = static_cast(matJson["AlphaMode"].get()); if (matJson.contains("AlphaCutoff")) doc.AlphaCutoff = matJson["AlphaCutoff"].get(); if (matJson.contains("DoubleSided")) doc.DoubleSided = matJson["DoubleSided"].get(); 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(style.HorizontalAlignment); j["VerticalAlignment"] = static_cast(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(); if (j.contains("Padding")) style.Padding = JsonToVec3(j["Padding"]); if (j.contains("HorizontalAlignment")) style.HorizontalAlignment = static_cast(j["HorizontalAlignment"].get()); if (j.contains("VerticalAlignment")) style.VerticalAlignment = static_cast(j["VerticalAlignment"].get()); if (j.contains("ImageAssetGuid")) style.ImageAssetGuid = StringToGuid(j["ImageAssetGuid"].get()); if (j.contains("PreserveAspect")) style.PreserveAspect = j["PreserveAspect"].get(); return style; } static json UiNodeToJson(const MetaCoreUiNodeDocument& node) { json j = json::object(); j["Id"] = node.Id; j["Name"] = node.Name; j["Type"] = static_cast(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; j["Action"] = node.Action; j["DataBinding"] = node.DataBinding; j["DataFormat"] = node.DataFormat; return j; } static MetaCoreUiNodeDocument JsonToUiNode(const json& j) { MetaCoreUiNodeDocument node; if (j.contains("Id")) node.Id = j["Id"].get(); if (j.contains("Name")) node.Name = j["Name"].get(); if (j.contains("Type")) node.Type = static_cast(j["Type"].get()); if (j.contains("ParentId")) node.ParentId = j["ParentId"].get(); if (j.contains("Children")) node.Children = j["Children"].get>(); if (j.contains("Visible")) node.Visible = j["Visible"].get(); 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(); if (j.contains("Interactable")) node.Interactable = j["Interactable"].get(); if (j.contains("Action")) node.Action = j["Action"].get(); if (j.contains("DataBinding")) node.DataBinding = j["DataBinding"].get(); if (j.contains("DataFormat")) node.DataFormat = j["DataFormat"].get(); 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["BackgroundColor"] = Vec3ToJson(uiDocument.BackgroundColor); uiJson["BackgroundAlpha"] = uiDocument.BackgroundAlpha; 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 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(); if (uiJson.contains("ReferenceWidth")) doc.ReferenceWidth = uiJson["ReferenceWidth"].get(); if (uiJson.contains("ReferenceHeight")) doc.ReferenceHeight = uiJson["ReferenceHeight"].get(); if (uiJson.contains("BackgroundColor")) doc.BackgroundColor = JsonToVec3(uiJson["BackgroundColor"]); if (uiJson.contains("BackgroundAlpha")) doc.BackgroundAlpha = uiJson["BackgroundAlpha"].get(); if (uiJson.contains("RootNodeIds")) doc.RootNodeIds = uiJson["RootNodeIds"].get>(); 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