MetaCore/Source/MetaCoreScene/Private/MetaCoreSceneSerializer.cpp

346 lines
27 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

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

#include "MetaCoreScene/MetaCoreSceneSerializer.h"
#include "MetaCoreFoundation/MetaCoreReflection.h"
#include <nlohmann/json.hpp>
#include <fstream>
#include <iostream>
#include <sstream>
using json = nlohmann::json;
namespace MetaCore {
// 辅助方法:将 glm::vec3 序列化为 JSON 数组 [x, y, z]
static json Vec3ToJson(const glm::vec3& vec) {
return { vec.x, vec.y, vec.z };
}
// 辅助方法:从 JSON 数组 [x, y, z] 反序列化出 glm::vec3
static glm::vec3 JsonToVec3(const json& j) {
if (j.is_array() && j.size() >= 3) {
return glm::vec3(j[0].get<float>(), j[1].get<float>(), j[2].get<float>());
}
return glm::vec3(0.0f);
}
// 辅助方法:将 MetaCoreAssetGuid 转换为 String方便文本化存储
static std::string GuidToString(const MetaCoreAssetGuid& guid) {
return guid.IsValid() ? guid.ToString() : "";
}
// 辅助方法:从 String 反解析为 MetaCoreAssetGuid
static MetaCoreAssetGuid StringToGuid(const std::string& str) {
return str.empty() ? MetaCoreAssetGuid{} : MetaCoreAssetGuid::Parse(str).value_or(MetaCoreAssetGuid{});
}
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 == "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();
const MetaCoreStructDescriptor* objDesc = registry.FindStruct<MetaCoreGameObjectData>();
if (objDesc) {
for (const auto& obj : sceneDocument.GameObjects) {
json objJson = json::object();
for (const auto& objField : objDesc->Fields) {
if (objField.Name == "Id") {
objJson["Id"] = obj.Id;
} else if (objField.Name == "ParentId") {
objJson["ParentId"] = obj.ParentId;
} else if (objField.Name == "Name") {
objJson["Name"] = obj.Name;
} else if (objField.Name == "Transform") {
const MetaCoreStructDescriptor* transDesc = registry.FindStruct<MetaCoreTransformComponent>();
if (transDesc) {
json transJson = json::object();
for (const auto& transField : transDesc->Fields) {
if (transField.Name == "Position") transJson["Position"] = Vec3ToJson(obj.Transform.Position);
else if (transField.Name == "RotationEulerDegrees") transJson["RotationEulerDegrees"] = Vec3ToJson(obj.Transform.RotationEulerDegrees);
else if (transField.Name == "Scale") transJson["Scale"] = Vec3ToJson(obj.Transform.Scale);
}
objJson["Transform"] = transJson;
}
} else if (objField.Name == "MeshRenderer" && obj.MeshRenderer.has_value()) {
const MetaCoreStructDescriptor* meshDesc = registry.FindStruct<MetaCoreMeshRendererComponent>();
if (meshDesc) {
json meshJson = json::object();
const auto& mesh = obj.MeshRenderer.value();
for (const auto& meshField : meshDesc->Fields) {
if (meshField.Name == "MeshSource") meshJson["MeshSource"] = static_cast<int>(mesh.MeshSource);
else if (meshField.Name == "BuiltinMesh") meshJson["BuiltinMesh"] = static_cast<int>(mesh.BuiltinMesh);
else if (meshField.Name == "MeshAssetGuid") meshJson["MeshAssetGuid"] = GuidToString(mesh.MeshAssetGuid);
else if (meshField.Name == "MaterialAssetGuids") {
json matGuids = json::array();
for (const auto& guid : mesh.MaterialAssetGuids) {
matGuids.push_back(GuidToString(guid));
}
meshJson["MaterialAssetGuids"] = matGuids;
}
else if (meshField.Name == "SourceModelAssetGuid") meshJson["SourceModelAssetGuid"] = GuidToString(mesh.SourceModelAssetGuid);
else if (meshField.Name == "SourceModelPath") meshJson["SourceModelPath"] = mesh.SourceModelPath;
else if (meshField.Name == "SourceNodePath") meshJson["SourceNodePath"] = mesh.SourceNodePath;
else if (meshField.Name == "BaseColorTextureGuid") meshJson["BaseColorTextureGuid"] = GuidToString(mesh.BaseColorTextureGuid);
else if (meshField.Name == "MetallicRoughnessTextureGuid") meshJson["MetallicRoughnessTextureGuid"] = GuidToString(mesh.MetallicRoughnessTextureGuid);
else if (meshField.Name == "NormalTextureGuid") meshJson["NormalTextureGuid"] = GuidToString(mesh.NormalTextureGuid);
else if (meshField.Name == "EmissiveTextureGuid") meshJson["EmissiveTextureGuid"] = GuidToString(mesh.EmissiveTextureGuid);
else if (meshField.Name == "AoTextureGuid") meshJson["AoTextureGuid"] = GuidToString(mesh.AoTextureGuid);
else if (meshField.Name == "BaseColorTexturePath") meshJson["BaseColorTexturePath"] = mesh.BaseColorTexturePath;
else if (meshField.Name == "MetallicRoughnessTexturePath") meshJson["MetallicRoughnessTexturePath"] = mesh.MetallicRoughnessTexturePath;
else if (meshField.Name == "NormalTexturePath") meshJson["NormalTexturePath"] = mesh.NormalTexturePath;
else if (meshField.Name == "EmissiveTexturePath") meshJson["EmissiveTexturePath"] = mesh.EmissiveTexturePath;
else if (meshField.Name == "AoTexturePath") meshJson["AoTexturePath"] = mesh.AoTexturePath;
else if (meshField.Name == "DoubleSided") meshJson["DoubleSided"] = mesh.DoubleSided;
else if (meshField.Name == "Metallic") meshJson["Metallic"] = mesh.Metallic;
else if (meshField.Name == "Roughness") meshJson["Roughness"] = mesh.Roughness;
else if (meshField.Name == "AlphaMode") meshJson["AlphaMode"] = static_cast<int>(mesh.AlphaMode);
else if (meshField.Name == "AlphaCutoff") meshJson["AlphaCutoff"] = mesh.AlphaCutoff;
else if (meshField.Name == "EmissiveColor") meshJson["EmissiveColor"] = Vec3ToJson(mesh.EmissiveColor);
else if (meshField.Name == "BaseColor") meshJson["BaseColor"] = Vec3ToJson(mesh.BaseColor);
else if (meshField.Name == "ModelNodeIndex") meshJson["ModelNodeIndex"] = mesh.ModelNodeIndex;
else if (meshField.Name == "SubMeshIndex") meshJson["SubMeshIndex"] = mesh.SubMeshIndex;
else if (meshField.Name == "Visible") meshJson["Visible"] = mesh.Visible;
}
objJson["MeshRenderer"] = meshJson;
}
} else if (objField.Name == "Light" && obj.Light.has_value()) {
const MetaCoreStructDescriptor* lightDesc = registry.FindStruct<MetaCoreLightComponent>();
if (lightDesc) {
json lightJson = json::object();
for (const auto& lightField : lightDesc->Fields) {
if (lightField.Name == "Color") lightJson["Color"] = Vec3ToJson(obj.Light->Color);
else if (lightField.Name == "Intensity") lightJson["Intensity"] = obj.Light->Intensity;
}
objJson["Light"] = lightJson;
}
} 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;
}
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;
}
}
}
gameObjectsArray.push_back(objJson);
}
}
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 == "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()) {
const MetaCoreStructDescriptor* objDesc = registry.FindStruct<MetaCoreGameObjectData>();
if (objDesc) {
for (const auto& objJson : sceneJson["GameObjects"]) {
MetaCoreGameObjectData obj;
for (const auto& objField : objDesc->Fields) {
if (objField.Name == "Id" && objJson.contains("Id")) {
obj.Id = objJson["Id"].get<MetaCoreId>();
} else if (objField.Name == "ParentId" && objJson.contains("ParentId")) {
obj.ParentId = objJson["ParentId"].get<MetaCoreId>();
} else if (objField.Name == "Name" && objJson.contains("Name")) {
obj.Name = objJson["Name"].get<std::string>();
} else if (objField.Name == "Transform" && objJson.contains("Transform")) {
const auto& transJson = objJson["Transform"];
const MetaCoreStructDescriptor* transDesc = registry.FindStruct<MetaCoreTransformComponent>();
if (transDesc) {
for (const auto& transField : transDesc->Fields) {
if (transField.Name == "Position" && transJson.contains("Position")) {
obj.Transform.Position = JsonToVec3(transJson["Position"]);
} else if (transField.Name == "RotationEulerDegrees" && transJson.contains("RotationEulerDegrees")) {
obj.Transform.RotationEulerDegrees = JsonToVec3(transJson["RotationEulerDegrees"]);
} else if (transField.Name == "Scale" && transJson.contains("Scale")) {
obj.Transform.Scale = JsonToVec3(transJson["Scale"]);
}
}
}
} else if (objField.Name == "MeshRenderer" && objJson.contains("MeshRenderer")) {
const auto& meshJson = objJson["MeshRenderer"];
const MetaCoreStructDescriptor* meshDesc = registry.FindStruct<MetaCoreMeshRendererComponent>();
if (meshDesc) {
MetaCoreMeshRendererComponent mesh;
for (const auto& meshField : meshDesc->Fields) {
if (meshField.Name == "MeshSource" && meshJson.contains("MeshSource")) mesh.MeshSource = static_cast<MetaCoreMeshSourceKind>(meshJson["MeshSource"].get<int>());
else if (meshField.Name == "BuiltinMesh" && meshJson.contains("BuiltinMesh")) mesh.BuiltinMesh = static_cast<MetaCoreBuiltinMeshType>(meshJson["BuiltinMesh"].get<int>());
else if (meshField.Name == "MeshAssetGuid" && meshJson.contains("MeshAssetGuid")) mesh.MeshAssetGuid = StringToGuid(meshJson["MeshAssetGuid"].get<std::string>());
else if (meshField.Name == "MaterialAssetGuids" && meshJson.contains("MaterialAssetGuids") && meshJson["MaterialAssetGuids"].is_array()) {
for (const auto& mGuidJson : meshJson["MaterialAssetGuids"]) {
mesh.MaterialAssetGuids.push_back(StringToGuid(mGuidJson.get<std::string>()));
}
}
else if (meshField.Name == "SourceModelAssetGuid" && meshJson.contains("SourceModelAssetGuid")) mesh.SourceModelAssetGuid = StringToGuid(meshJson["SourceModelAssetGuid"].get<std::string>());
else if (meshField.Name == "SourceModelPath" && meshJson.contains("SourceModelPath")) mesh.SourceModelPath = meshJson["SourceModelPath"].get<std::string>();
else if (meshField.Name == "SourceNodePath" && meshJson.contains("SourceNodePath")) mesh.SourceNodePath = meshJson["SourceNodePath"].get<std::string>();
else if (meshField.Name == "BaseColorTextureGuid" && meshJson.contains("BaseColorTextureGuid")) mesh.BaseColorTextureGuid = StringToGuid(meshJson["BaseColorTextureGuid"].get<std::string>());
else if (meshField.Name == "MetallicRoughnessTextureGuid" && meshJson.contains("MetallicRoughnessTextureGuid")) mesh.MetallicRoughnessTextureGuid = StringToGuid(meshJson["MetallicRoughnessTextureGuid"].get<std::string>());
else if (meshField.Name == "NormalTextureGuid" && meshJson.contains("NormalTextureGuid")) mesh.NormalTextureGuid = StringToGuid(meshJson["NormalTextureGuid"].get<std::string>());
else if (meshField.Name == "EmissiveTextureGuid" && meshJson.contains("EmissiveTextureGuid")) mesh.EmissiveTextureGuid = StringToGuid(meshJson["EmissiveTextureGuid"].get<std::string>());
else if (meshField.Name == "AoTextureGuid" && meshJson.contains("AoTextureGuid")) mesh.AoTextureGuid = StringToGuid(meshJson["AoTextureGuid"].get<std::string>());
else if (meshField.Name == "BaseColorTexturePath" && meshJson.contains("BaseColorTexturePath")) mesh.BaseColorTexturePath = meshJson["BaseColorTexturePath"].get<std::string>();
else if (meshField.Name == "MetallicRoughnessTexturePath" && meshJson.contains("MetallicRoughnessTexturePath")) mesh.MetallicRoughnessTexturePath = meshJson["MetallicRoughnessTexturePath"].get<std::string>();
else if (meshField.Name == "NormalTexturePath" && meshJson.contains("NormalTexturePath")) mesh.NormalTexturePath = meshJson["NormalTexturePath"].get<std::string>();
else if (meshField.Name == "EmissiveTexturePath" && meshJson.contains("EmissiveTexturePath")) mesh.EmissiveTexturePath = meshJson["EmissiveTexturePath"].get<std::string>();
else if (meshField.Name == "AoTexturePath" && meshJson.contains("AoTexturePath")) mesh.AoTexturePath = meshJson["AoTexturePath"].get<std::string>();
else if (meshField.Name == "DoubleSided" && meshJson.contains("DoubleSided")) mesh.DoubleSided = meshJson["DoubleSided"].get<bool>();
else if (meshField.Name == "Metallic" && meshJson.contains("Metallic")) mesh.Metallic = meshJson["Metallic"].get<float>();
else if (meshField.Name == "Roughness" && meshJson.contains("Roughness")) mesh.Roughness = meshJson["Roughness"].get<float>();
else if (meshField.Name == "AlphaMode" && meshJson.contains("AlphaMode")) mesh.AlphaMode = static_cast<MetaCoreMeshAlphaMode>(meshJson["AlphaMode"].get<int>());
else if (meshField.Name == "AlphaCutoff" && meshJson.contains("AlphaCutoff")) mesh.AlphaCutoff = meshJson["AlphaCutoff"].get<float>();
else if (meshField.Name == "EmissiveColor" && meshJson.contains("EmissiveColor")) mesh.EmissiveColor = JsonToVec3(meshJson["EmissiveColor"]);
else if (meshField.Name == "BaseColor" && meshJson.contains("BaseColor")) mesh.BaseColor = JsonToVec3(meshJson["BaseColor"]);
else if (meshField.Name == "ModelNodeIndex" && meshJson.contains("ModelNodeIndex")) mesh.ModelNodeIndex = meshJson["ModelNodeIndex"].get<std::int32_t>();
else if (meshField.Name == "SubMeshIndex" && meshJson.contains("SubMeshIndex")) mesh.SubMeshIndex = meshJson["SubMeshIndex"].get<std::int32_t>();
else if (meshField.Name == "Visible" && meshJson.contains("Visible")) mesh.Visible = meshJson["Visible"].get<bool>();
}
obj.MeshRenderer = mesh;
}
} else if (objField.Name == "Light" && objJson.contains("Light")) {
const auto& lightJson = objJson["Light"];
const MetaCoreStructDescriptor* lightDesc = registry.FindStruct<MetaCoreLightComponent>();
if (lightDesc) {
MetaCoreLightComponent light;
for (const auto& lightField : lightDesc->Fields) {
if (lightField.Name == "Color" && lightJson.contains("Color")) light.Color = JsonToVec3(lightJson["Color"]);
else if (lightField.Name == "Intensity" && lightJson.contains("Intensity")) light.Intensity = lightJson["Intensity"].get<float>();
}
obj.Light = light;
}
} 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>();
}
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;
}
}
}
sceneDocument.GameObjects.push_back(obj);
}
}
}
}
return sceneDocument;
} catch (const std::exception& e) {
std::cerr << "LoadSceneFromJson: 发生异常 - " << e.what() << std::endl;
return std::nullopt;
}
}
} // namespace MetaCore