971 lines
68 KiB
C++
971 lines
68 KiB
C++
#include "MetaCoreScene/MetaCoreSceneSerializer.h"
|
||
#include "MetaCoreFoundation/MetaCoreReflection.h"
|
||
#include <nlohmann/json.hpp>
|
||
#include <fstream>
|
||
#include <iostream>
|
||
#include <sstream>
|
||
#include <span>
|
||
|
||
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{});
|
||
}
|
||
|
||
template <typename T>
|
||
static std::string ReflectedValueToHex(const T& value, const MetaCoreTypeRegistry& registry) {
|
||
const auto bytes = MetaCoreSerializeToBytes(value, registry); if (!bytes) return {};
|
||
constexpr char digits[] = "0123456789abcdef"; std::string result; result.resize(bytes->size()*2U);
|
||
for(std::size_t i=0;i<bytes->size();++i){const auto valueByte=std::to_integer<unsigned int>((*bytes)[i]);result[i*2U]=digits[valueByte>>4U];result[i*2U+1U]=digits[valueByte&15U];}return result;
|
||
}
|
||
|
||
template <typename T>
|
||
static std::optional<T> ReflectedValueFromHex(const json& value, const MetaCoreTypeRegistry& registry) {
|
||
if(!value.is_string())return std::nullopt;const std::string hex=value.get<std::string>();if((hex.size()&1U)!=0U)return std::nullopt;
|
||
const auto nibble=[](char c)->int{if(c>='0'&&c<='9')return c-'0';if(c>='a'&&c<='f')return c-'a'+10;if(c>='A'&&c<='F')return c-'A'+10;return -1;};
|
||
std::vector<std::byte> bytes(hex.size()/2U);for(std::size_t i=0;i<bytes.size();++i){const int hi=nibble(hex[i*2U]),lo=nibble(hex[i*2U+1U]);if(hi<0||lo<0)return std::nullopt;bytes[i]=static_cast<std::byte>((hi<<4)|lo);}T result{};if(!MetaCoreDeserializeFromBytes(std::span<const std::byte>(bytes.data(),bytes.size()),result,registry))return std::nullopt;return result;
|
||
}
|
||
|
||
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;
|
||
environmentJson["EnvironmentProfileGuid"] = GuidToString(environment.EnvironmentProfileGuid);
|
||
environmentJson["PostProcessProfileGuid"] = GuidToString(environment.PostProcessProfileGuid);
|
||
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>();
|
||
if (environmentJson.contains("EnvironmentProfileGuid")) environment.EnvironmentProfileGuid = StringToGuid(environmentJson["EnvironmentProfileGuid"].get<std::string>());
|
||
if (environmentJson.contains("PostProcessProfileGuid")) environment.PostProcessProfileGuid = StringToGuid(environmentJson["PostProcessProfileGuid"].get<std::string>());
|
||
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 == "Type") lightJson["Type"] = static_cast<int>(obj.Light->Type);
|
||
else 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;
|
||
else if (lightField.Name == "UseColorTemperature") lightJson["UseColorTemperature"] = obj.Light->UseColorTemperature;
|
||
else if (lightField.Name == "ColorTemperatureKelvin") lightJson["ColorTemperatureKelvin"] = obj.Light->ColorTemperatureKelvin;
|
||
else if (lightField.Name == "Range") lightJson["Range"] = obj.Light->Range;
|
||
else if (lightField.Name == "InnerConeDegrees") lightJson["InnerConeDegrees"] = obj.Light->InnerConeDegrees;
|
||
else if (lightField.Name == "OuterConeDegrees") lightJson["OuterConeDegrees"] = obj.Light->OuterConeDegrees;
|
||
else if (lightField.Name == "FalloffExponent") lightJson["FalloffExponent"] = obj.Light->FalloffExponent;
|
||
else if (lightField.Name == "CastShadows") lightJson["CastShadows"] = obj.Light->CastShadows;
|
||
else if (lightField.Name == "ShadowBias") lightJson["ShadowBias"] = obj.Light->ShadowBias;
|
||
else if (lightField.Name == "ShadowNormalBias") lightJson["ShadowNormalBias"] = obj.Light->ShadowNormalBias;
|
||
else if (lightField.Name == "ShadowPriority") lightJson["ShadowPriority"] = obj.Light->ShadowPriority;
|
||
else if (lightField.Name == "LightingMask") lightJson["LightingMask"] = obj.Light->LightingMask;
|
||
}
|
||
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 == "Animator" && obj.Animator.has_value()) {
|
||
const MetaCoreStructDescriptor* animatorDesc = registry.FindStruct<MetaCoreAnimatorComponent>();
|
||
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<MetaCoreUiRendererComponent>();
|
||
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<int>(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 == "Interactable" && obj.Interactable.has_value()) {
|
||
objJson["Interactable"] = {
|
||
{"Enabled", obj.Interactable->Enabled},
|
||
{"EventMask", obj.Interactable->EventMask},
|
||
{"DragThresholdPixels", obj.Interactable->DragThresholdPixels}
|
||
};
|
||
} else if (objField.Name == "Collider" && obj.Collider.has_value()) {
|
||
const auto& value = *obj.Collider;
|
||
objJson["Collider"] = {{"Enabled", value.Enabled}, {"Shape", static_cast<int>(value.Shape)},
|
||
{"Center", Vec3ToJson(value.Center)}, {"Size", Vec3ToJson(value.Size)}, {"Radius", value.Radius},
|
||
{"Height", value.Height}, {"MeshAssetGuid", GuidToString(value.MeshAssetGuid)},
|
||
{"MaterialAssetGuid", GuidToString(value.MaterialAssetGuid)}, {"CollisionLayer", value.CollisionLayer},
|
||
{"IsTrigger", value.IsTrigger}};
|
||
} else if (objField.Name == "RigidBody" && obj.RigidBody.has_value()) {
|
||
const auto& value = *obj.RigidBody;
|
||
objJson["RigidBody"] = {{"BodyType", static_cast<int>(value.BodyType)}, {"Mass", value.Mass},
|
||
{"LinearDamping", value.LinearDamping}, {"AngularDamping", value.AngularDamping},
|
||
{"GravityScale", value.GravityScale}, {"InitialLinearVelocity", Vec3ToJson(value.InitialLinearVelocity)},
|
||
{"InitialAngularVelocity", Vec3ToJson(value.InitialAngularVelocity)}, {"AllowSleep", value.AllowSleep},
|
||
{"ContinuousCollisionDetection", value.ContinuousCollisionDetection}, {"LockedAxes", value.LockedAxes}};
|
||
} else if (objField.Name == "PhysicsConstraint" && obj.PhysicsConstraint.has_value()) {
|
||
const auto& value = *obj.PhysicsConstraint;
|
||
objJson["PhysicsConstraint"] = {{"Enabled", value.Enabled}, {"Type", static_cast<int>(value.Type)},
|
||
{"TargetObjectId", value.TargetObjectId}, {"Anchor", Vec3ToJson(value.Anchor)},
|
||
{"TargetAnchor", Vec3ToJson(value.TargetAnchor)}, {"Axis", Vec3ToJson(value.Axis)},
|
||
{"LinearLowerLimit", Vec3ToJson(value.LinearLowerLimit)}, {"LinearUpperLimit", Vec3ToJson(value.LinearUpperLimit)},
|
||
{"AngularLowerLimit", Vec3ToJson(value.AngularLowerLimit)}, {"AngularUpperLimit", Vec3ToJson(value.AngularUpperLimit)},
|
||
{"MotorEnabled", value.MotorEnabled}, {"MotorTargetVelocity", value.MotorTargetVelocity},
|
||
{"MotorMaxImpulse", value.MotorMaxImpulse}, {"BreakForce", value.BreakForce},
|
||
{"BreakTorque", value.BreakTorque}, {"EnableConnectedCollision", value.EnableConnectedCollision}};
|
||
} else if (objField.Name == "CharacterController" && obj.CharacterController.has_value()) {
|
||
const auto& value = *obj.CharacterController;
|
||
objJson["CharacterController"] = {{"Enabled", value.Enabled}, {"Radius", value.Radius},
|
||
{"Height", value.Height}, {"SkinWidth", value.SkinWidth}, {"MaxSlopeDegrees", value.MaxSlopeDegrees},
|
||
{"StepHeight", value.StepHeight}, {"GravityScale", value.GravityScale}, {"MaxFallSpeed", value.MaxFallSpeed},
|
||
{"PushForce", value.PushForce}, {"CollisionLayer", value.CollisionLayer}};
|
||
} else if (objField.Name == "ReflectionProbe" && obj.ReflectionProbe) objJson["ReflectionProbe"] = ReflectedValueToHex(*obj.ReflectionProbe, registry);
|
||
else if (objField.Name == "LodGroup" && obj.LodGroup) objJson["LodGroup"] = ReflectedValueToHex(*obj.LodGroup, registry);
|
||
else if (objField.Name == "ParticleEmitter" && obj.ParticleEmitter) objJson["ParticleEmitter"] = ReflectedValueToHex(*obj.ParticleEmitter, registry);
|
||
else if (objField.Name == "LineRenderer" && obj.LineRenderer) objJson["LineRenderer"] = ReflectedValueToHex(*obj.LineRenderer, registry);
|
||
else if (objField.Name == "TrailRenderer" && obj.TrailRenderer) objJson["TrailRenderer"] = ReflectedValueToHex(*obj.TrailRenderer, registry);
|
||
else if (objField.Name == "DecalProjector" && obj.DecalProjector) objJson["DecalProjector"] = ReflectedValueToHex(*obj.DecalProjector, registry);
|
||
else if (objField.Name == "Terrain" && obj.Terrain) objJson["Terrain"] = ReflectedValueToHex(*obj.Terrain, registry);
|
||
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;
|
||
else if (camField.Name == "PostProcessProfileGuid") camJson["PostProcessProfileGuid"] = GuidToString(obj.Camera->PostProcessProfileGuid);
|
||
}
|
||
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;
|
||
const bool legacyNormalizedIntensity = !lightJson.contains("Type");
|
||
for (const auto& lightField : lightDesc->Fields) {
|
||
if (lightField.Name == "Type" && lightJson.contains("Type")) light.Type = static_cast<MetaCoreLightType>(lightJson["Type"].get<int>());
|
||
else 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>();
|
||
else if (lightField.Name == "UseColorTemperature" && lightJson.contains("UseColorTemperature")) light.UseColorTemperature = lightJson["UseColorTemperature"].get<bool>();
|
||
else if (lightField.Name == "ColorTemperatureKelvin" && lightJson.contains("ColorTemperatureKelvin")) light.ColorTemperatureKelvin = lightJson["ColorTemperatureKelvin"].get<float>();
|
||
else if (lightField.Name == "Range" && lightJson.contains("Range")) light.Range = lightJson["Range"].get<float>();
|
||
else if (lightField.Name == "InnerConeDegrees" && lightJson.contains("InnerConeDegrees")) light.InnerConeDegrees = lightJson["InnerConeDegrees"].get<float>();
|
||
else if (lightField.Name == "OuterConeDegrees" && lightJson.contains("OuterConeDegrees")) light.OuterConeDegrees = lightJson["OuterConeDegrees"].get<float>();
|
||
else if (lightField.Name == "FalloffExponent" && lightJson.contains("FalloffExponent")) light.FalloffExponent = lightJson["FalloffExponent"].get<float>();
|
||
else if (lightField.Name == "CastShadows" && lightJson.contains("CastShadows")) light.CastShadows = lightJson["CastShadows"].get<bool>();
|
||
else if (lightField.Name == "ShadowBias" && lightJson.contains("ShadowBias")) light.ShadowBias = lightJson["ShadowBias"].get<float>();
|
||
else if (lightField.Name == "ShadowNormalBias" && lightJson.contains("ShadowNormalBias")) light.ShadowNormalBias = lightJson["ShadowNormalBias"].get<float>();
|
||
else if (lightField.Name == "ShadowPriority" && lightJson.contains("ShadowPriority")) light.ShadowPriority = lightJson["ShadowPriority"].get<std::int32_t>();
|
||
else if (lightField.Name == "LightingMask" && lightJson.contains("LightingMask")) light.LightingMask = lightJson["LightingMask"].get<std::uint32_t>();
|
||
}
|
||
if (legacyNormalizedIntensity) light.Intensity *= 100000.0F;
|
||
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 == "Animator" && objJson.contains("Animator")) {
|
||
const auto& animatorJson = objJson["Animator"];
|
||
const MetaCoreStructDescriptor* animatorDesc = registry.FindStruct<MetaCoreAnimatorComponent>();
|
||
if (animatorDesc) {
|
||
MetaCoreAnimatorComponent animator;
|
||
for (const auto& animatorField : animatorDesc->Fields) {
|
||
if (animatorField.Name == "Enabled" && animatorJson.contains("Enabled")) animator.Enabled = animatorJson["Enabled"].get<bool>();
|
||
else if (animatorField.Name == "SourceModelAssetGuid" && animatorJson.contains("SourceModelAssetGuid")) animator.SourceModelAssetGuid = StringToGuid(animatorJson["SourceModelAssetGuid"].get<std::string>());
|
||
else if (animatorField.Name == "SourceModelPath" && animatorJson.contains("SourceModelPath")) animator.SourceModelPath = animatorJson["SourceModelPath"].get<std::string>();
|
||
else if (animatorField.Name == "ClipIndex" && animatorJson.contains("ClipIndex")) animator.ClipIndex = animatorJson["ClipIndex"].get<std::int32_t>();
|
||
else if (animatorField.Name == "ClipName" && animatorJson.contains("ClipName")) animator.ClipName = animatorJson["ClipName"].get<std::string>();
|
||
else if (animatorField.Name == "PlayOnStart" && animatorJson.contains("PlayOnStart")) animator.PlayOnStart = animatorJson["PlayOnStart"].get<bool>();
|
||
else if (animatorField.Name == "Loop" && animatorJson.contains("Loop")) animator.Loop = animatorJson["Loop"].get<bool>();
|
||
else if (animatorField.Name == "Speed" && animatorJson.contains("Speed")) animator.Speed = animatorJson["Speed"].get<float>();
|
||
}
|
||
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<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 == "UiRenderer" && objJson.contains("UiRenderer")) {
|
||
const auto& uiJson = objJson["UiRenderer"];
|
||
const MetaCoreStructDescriptor* uiDesc = registry.FindStruct<MetaCoreUiRendererComponent>();
|
||
if (uiDesc) {
|
||
MetaCoreUiRendererComponent ui;
|
||
for (const auto& uiField : uiDesc->Fields) {
|
||
if (uiField.Name == "UiDocumentAssetGuid" && uiJson.contains("UiDocumentAssetGuid")) ui.UiDocumentAssetGuid = StringToGuid(uiJson["UiDocumentAssetGuid"].get<std::string>());
|
||
else if (uiField.Name == "RenderMode" && uiJson.contains("RenderMode")) ui.RenderMode = static_cast<MetaCoreUiRenderMode>(uiJson["RenderMode"].get<int>());
|
||
else if (uiField.Name == "Visible" && uiJson.contains("Visible")) ui.Visible = uiJson["Visible"].get<bool>();
|
||
else if (uiField.Name == "InputEnabled" && uiJson.contains("InputEnabled")) ui.InputEnabled = uiJson["InputEnabled"].get<bool>();
|
||
else if (uiField.Name == "FaceCamera" && uiJson.contains("FaceCamera")) ui.FaceCamera = uiJson["FaceCamera"].get<bool>();
|
||
else if (uiField.Name == "Layer" && uiJson.contains("Layer")) ui.Layer = uiJson["Layer"].get<std::int32_t>();
|
||
else if (uiField.Name == "PixelsPerUnit" && uiJson.contains("PixelsPerUnit")) ui.PixelsPerUnit = uiJson["PixelsPerUnit"].get<float>();
|
||
else if (uiField.Name == "WorldSize" && uiJson.contains("WorldSize")) ui.WorldSize = JsonToVec3(uiJson["WorldSize"]);
|
||
}
|
||
obj.UiRenderer = ui;
|
||
}
|
||
} else if (objField.Name == "Interactable" && objJson.contains("Interactable")) {
|
||
const auto& value = objJson["Interactable"];
|
||
MetaCoreInteractableComponent interactable;
|
||
if (value.contains("Enabled")) interactable.Enabled = value["Enabled"].get<bool>();
|
||
if (value.contains("EventMask")) interactable.EventMask = value["EventMask"].get<std::uint32_t>();
|
||
if (value.contains("DragThresholdPixels")) interactable.DragThresholdPixels = value["DragThresholdPixels"].get<float>();
|
||
obj.Interactable = interactable;
|
||
} else if (objField.Name == "Collider" && objJson.contains("Collider")) {
|
||
const auto& value = objJson["Collider"];
|
||
MetaCoreColliderComponent component;
|
||
component.Enabled = value.value("Enabled", true);
|
||
component.Shape = static_cast<MetaCoreColliderShape>(value.value("Shape", 0));
|
||
if (value.contains("Center")) component.Center = JsonToVec3(value["Center"]);
|
||
if (value.contains("Size")) component.Size = JsonToVec3(value["Size"]);
|
||
component.Radius = value.value("Radius", 0.5F); component.Height = value.value("Height", 2.0F);
|
||
if (value.contains("MeshAssetGuid")) component.MeshAssetGuid = StringToGuid(value["MeshAssetGuid"].get<std::string>());
|
||
if (value.contains("MaterialAssetGuid")) component.MaterialAssetGuid = StringToGuid(value["MaterialAssetGuid"].get<std::string>());
|
||
component.CollisionLayer = value.value("CollisionLayer", 0U); component.IsTrigger = value.value("IsTrigger", false);
|
||
obj.Collider = component;
|
||
} else if (objField.Name == "RigidBody" && objJson.contains("RigidBody")) {
|
||
const auto& value = objJson["RigidBody"];
|
||
MetaCoreRigidBodyComponent component;
|
||
component.BodyType = static_cast<MetaCoreRigidBodyType>(value.value("BodyType", 0));
|
||
component.Mass = value.value("Mass", 1.0F); component.LinearDamping = value.value("LinearDamping", 0.0F);
|
||
component.AngularDamping = value.value("AngularDamping", 0.05F); component.GravityScale = value.value("GravityScale", 1.0F);
|
||
if (value.contains("InitialLinearVelocity")) component.InitialLinearVelocity = JsonToVec3(value["InitialLinearVelocity"]);
|
||
if (value.contains("InitialAngularVelocity")) component.InitialAngularVelocity = JsonToVec3(value["InitialAngularVelocity"]);
|
||
component.AllowSleep = value.value("AllowSleep", true);
|
||
component.ContinuousCollisionDetection = value.value("ContinuousCollisionDetection", false);
|
||
component.LockedAxes = value.value("LockedAxes", 0U); obj.RigidBody = component;
|
||
} else if (objField.Name == "PhysicsConstraint" && objJson.contains("PhysicsConstraint")) {
|
||
const auto& value = objJson["PhysicsConstraint"];
|
||
MetaCorePhysicsConstraintComponent component;
|
||
component.Enabled = value.value("Enabled", true); component.Type = static_cast<MetaCorePhysicsConstraintType>(value.value("Type", 0));
|
||
component.TargetObjectId = value.value("TargetObjectId", MetaCoreId{0});
|
||
if (value.contains("Anchor")) component.Anchor = JsonToVec3(value["Anchor"]);
|
||
if (value.contains("TargetAnchor")) component.TargetAnchor = JsonToVec3(value["TargetAnchor"]);
|
||
if (value.contains("Axis")) component.Axis = JsonToVec3(value["Axis"]);
|
||
if (value.contains("LinearLowerLimit")) component.LinearLowerLimit = JsonToVec3(value["LinearLowerLimit"]);
|
||
if (value.contains("LinearUpperLimit")) component.LinearUpperLimit = JsonToVec3(value["LinearUpperLimit"]);
|
||
if (value.contains("AngularLowerLimit")) component.AngularLowerLimit = JsonToVec3(value["AngularLowerLimit"]);
|
||
if (value.contains("AngularUpperLimit")) component.AngularUpperLimit = JsonToVec3(value["AngularUpperLimit"]);
|
||
component.MotorEnabled = value.value("MotorEnabled", false); component.MotorTargetVelocity = value.value("MotorTargetVelocity", 0.0F);
|
||
component.MotorMaxImpulse = value.value("MotorMaxImpulse", 0.0F); component.BreakForce = value.value("BreakForce", 0.0F);
|
||
component.BreakTorque = value.value("BreakTorque", 0.0F); component.EnableConnectedCollision = value.value("EnableConnectedCollision", false);
|
||
obj.PhysicsConstraint = component;
|
||
} else if (objField.Name == "CharacterController" && objJson.contains("CharacterController")) {
|
||
const auto& value = objJson["CharacterController"];
|
||
MetaCoreCharacterControllerComponent component;
|
||
component.Enabled = value.value("Enabled", true); component.Radius = value.value("Radius", 0.4F);
|
||
component.Height = value.value("Height", 1.8F); component.SkinWidth = value.value("SkinWidth", 0.05F);
|
||
component.MaxSlopeDegrees = value.value("MaxSlopeDegrees", 45.0F); component.StepHeight = value.value("StepHeight", 0.3F);
|
||
component.GravityScale = value.value("GravityScale", 1.0F); component.MaxFallSpeed = value.value("MaxFallSpeed", 55.0F);
|
||
component.PushForce = value.value("PushForce", 1.0F); component.CollisionLayer = value.value("CollisionLayer", 0U);
|
||
obj.CharacterController = component;
|
||
} else if (objField.Name == "ReflectionProbe" && objJson.contains("ReflectionProbe")) obj.ReflectionProbe = ReflectedValueFromHex<MetaCoreReflectionProbeComponent>(objJson["ReflectionProbe"], registry);
|
||
else if (objField.Name == "LodGroup" && objJson.contains("LodGroup")) obj.LodGroup = ReflectedValueFromHex<MetaCoreLodGroupComponent>(objJson["LodGroup"], registry);
|
||
else if (objField.Name == "ParticleEmitter" && objJson.contains("ParticleEmitter")) obj.ParticleEmitter = ReflectedValueFromHex<MetaCoreParticleEmitterComponent>(objJson["ParticleEmitter"], registry);
|
||
else if (objField.Name == "LineRenderer" && objJson.contains("LineRenderer")) obj.LineRenderer = ReflectedValueFromHex<MetaCoreLineRendererComponent>(objJson["LineRenderer"], registry);
|
||
else if (objField.Name == "TrailRenderer" && objJson.contains("TrailRenderer")) obj.TrailRenderer = ReflectedValueFromHex<MetaCoreTrailRendererComponent>(objJson["TrailRenderer"], registry);
|
||
else if (objField.Name == "DecalProjector" && objJson.contains("DecalProjector")) obj.DecalProjector = ReflectedValueFromHex<MetaCoreDecalProjectorComponent>(objJson["DecalProjector"], registry);
|
||
else if (objField.Name == "Terrain" && objJson.contains("Terrain")) obj.Terrain = ReflectedValueFromHex<MetaCoreTerrainComponent>(objJson["Terrain"], registry);
|
||
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>();
|
||
else if (camField.Name == "PostProcessProfileGuid" && camJson.contains("PostProcessProfileGuid")) cam.PostProcessProfileGuid = StringToGuid(camJson["PostProcessProfileGuid"].get<std::string>());
|
||
}
|
||
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 {
|
||
MetaCoreMaterialAssetDocument validated = doc;
|
||
MetaCoreMaterialTemplateRegistry templates;
|
||
if (!templates.ValidateAndMigrate(validated, nullptr)) return false;
|
||
json matJson;
|
||
matJson["AssetGuid"] = GuidToString(doc.AssetGuid);
|
||
matJson["Name"] = doc.Name;
|
||
matJson["StableImportKey"] = doc.StableImportKey;
|
||
matJson["TemplateId"] = validated.TemplateId;
|
||
matJson["TemplateVersion"] = validated.TemplateVersion;
|
||
matJson["Parameters"] = json::array();
|
||
for(const auto& parameter:validated.Parameters)matJson["Parameters"].push_back({{"Name",parameter.Name},{"Type",static_cast<int>(parameter.Type)},{"FloatValue",parameter.FloatValue},{"BoolValue",parameter.BoolValue},{"VectorValue",Vec3ToJson(parameter.VectorValue)},{"TextureValue",GuidToString(parameter.TextureValue)}});
|
||
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>();
|
||
|
||
if(matJson.contains("TemplateId"))doc.TemplateId=matJson["TemplateId"].get<std::string>();else doc.TemplateId=doc.ShaderModel==MetaCoreMaterialShaderModel::PbrMetalRough?"metacore.pbr":"metacore.unlit";
|
||
if(matJson.contains("TemplateVersion"))doc.TemplateVersion=matJson["TemplateVersion"].get<std::uint32_t>();
|
||
if(matJson.contains("Parameters")&&matJson["Parameters"].is_array())for(const auto& value:matJson["Parameters"]){MetaCoreMaterialParameterDocument parameter;parameter.Name=value.value("Name",std::string{});parameter.Type=static_cast<MetaCoreMaterialParameterType>(value.value("Type",0));parameter.FloatValue=value.value("FloatValue",0.0F);parameter.BoolValue=value.value("BoolValue",false);if(value.contains("VectorValue"))parameter.VectorValue=JsonToVec3(value["VectorValue"]);if(value.contains("TextureValue"))parameter.TextureValue=StringToGuid(value["TextureValue"].get<std::string>());doc.Parameters.push_back(std::move(parameter));}
|
||
MetaCoreMaterialTemplateRegistry templates;if(!templates.ValidateAndMigrate(doc,nullptr))return std::nullopt;
|
||
|
||
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;
|
||
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<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>();
|
||
if (j.contains("Action")) node.Action = j["Action"].get<std::string>();
|
||
if (j.contains("DataBinding")) node.DataBinding = j["DataBinding"].get<std::string>();
|
||
if (j.contains("DataFormat")) node.DataFormat = j["DataFormat"].get<std::string>();
|
||
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<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("BackgroundColor")) doc.BackgroundColor = JsonToVec3(uiJson["BackgroundColor"]);
|
||
if (uiJson.contains("BackgroundAlpha")) doc.BackgroundAlpha = uiJson["BackgroundAlpha"].get<float>();
|
||
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
|