MetaCore/Source/MetaCoreScene/Private/MetaCoreSceneSerializer.cpp

289 lines
14 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;
sceneJson["SceneName"] = sceneDocument.Name;
sceneJson["Selection"] = {
{"SelectedObjectIds", sceneDocument.Selection.SelectedObjectIds},
{"ActiveObjectId", sceneDocument.Selection.ActiveObjectId},
{"SelectionAnchorId", sceneDocument.Selection.SelectionAnchorId}
};
json gameObjectsArray = json::array();
for (const auto& obj : sceneDocument.GameObjects) {
json objJson;
objJson["Id"] = obj.Id;
objJson["ParentId"] = obj.ParentId;
objJson["Name"] = obj.Name;
// 序列化 Transform 组件
objJson["Transform"] = {
{"Position", Vec3ToJson(obj.Transform.Position)},
{"RotationEulerDegrees", Vec3ToJson(obj.Transform.RotationEulerDegrees)},
{"Scale", Vec3ToJson(obj.Transform.Scale)}
};
// 序列化 MeshRenderer 组件 (如果有)
if (obj.MeshRenderer.has_value()) {
const auto& mesh = obj.MeshRenderer.value();
json meshJson;
meshJson["MeshSource"] = static_cast<int>(mesh.MeshSource);
meshJson["BuiltinMesh"] = static_cast<int>(mesh.BuiltinMesh);
meshJson["MeshAssetGuid"] = GuidToString(mesh.MeshAssetGuid);
json matGuids = json::array();
for (const auto& guid : mesh.MaterialAssetGuids) {
matGuids.push_back(GuidToString(guid));
}
meshJson["MaterialAssetGuids"] = matGuids;
meshJson["SourceModelAssetGuid"] = GuidToString(mesh.SourceModelAssetGuid);
meshJson["SourceModelPath"] = mesh.SourceModelPath;
meshJson["SourceNodePath"] = mesh.SourceNodePath;
meshJson["BaseColorTextureGuid"] = GuidToString(mesh.BaseColorTextureGuid);
meshJson["MetallicRoughnessTextureGuid"] = GuidToString(mesh.MetallicRoughnessTextureGuid);
meshJson["NormalTextureGuid"] = GuidToString(mesh.NormalTextureGuid);
meshJson["EmissiveTextureGuid"] = GuidToString(mesh.EmissiveTextureGuid);
meshJson["AoTextureGuid"] = GuidToString(mesh.AoTextureGuid);
meshJson["BaseColorTexturePath"] = mesh.BaseColorTexturePath;
meshJson["MetallicRoughnessTexturePath"] = mesh.MetallicRoughnessTexturePath;
meshJson["NormalTexturePath"] = mesh.NormalTexturePath;
meshJson["EmissiveTexturePath"] = mesh.EmissiveTexturePath;
meshJson["AoTexturePath"] = mesh.AoTexturePath;
meshJson["DoubleSided"] = mesh.DoubleSided;
meshJson["Metallic"] = mesh.Metallic;
meshJson["Roughness"] = mesh.Roughness;
meshJson["AlphaMode"] = static_cast<int>(mesh.AlphaMode);
meshJson["AlphaCutoff"] = mesh.AlphaCutoff;
meshJson["EmissiveColor"] = Vec3ToJson(mesh.EmissiveColor);
meshJson["BaseColor"] = Vec3ToJson(mesh.BaseColor);
meshJson["ModelNodeIndex"] = mesh.ModelNodeIndex;
meshJson["SubMeshIndex"] = mesh.SubMeshIndex;
meshJson["Visible"] = mesh.Visible;
objJson["MeshRenderer"] = meshJson;
}
// 序列化 Light 组件 (如果有)
if (obj.Light.has_value()) {
const auto& light = obj.Light.value();
json lightJson;
lightJson["Color"] = Vec3ToJson(light.Color);
lightJson["Intensity"] = light.Intensity;
objJson["Light"] = lightJson;
}
// 序列化 Camera 组件 (如果有)
if (obj.Camera.has_value()) {
const auto& cam = obj.Camera.value();
json camJson;
camJson["FieldOfViewDegrees"] = cam.FieldOfViewDegrees;
camJson["NearClip"] = cam.NearClip;
camJson["FarClip"] = cam.FarClip;
camJson["IsPrimary"] = cam.IsPrimary;
objJson["Camera"] = camJson;
}
// 序列化 PrefabInstance 预制体元数据 (如果有)
if (obj.PrefabInstance.has_value()) {
const auto& prefab = obj.PrefabInstance.value();
json prefabJson;
prefabJson["PrefabAssetGuid"] = GuidToString(prefab.PrefabAssetGuid);
prefabJson["PrefabObjectId"] = prefab.PrefabObjectId;
prefabJson["PrefabInstanceRootId"] = prefab.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;
}
// 使用 4 个空格缩进,完美支持 Git diff 差分
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;
if (sceneJson.contains("SceneName")) {
sceneDocument.Name = sceneJson["SceneName"].get<std::string>();
}
if (sceneJson.contains("Selection")) {
const auto& selectionJson = sceneJson["Selection"];
if (selectionJson.contains("SelectedObjectIds")) {
sceneDocument.Selection.SelectedObjectIds = selectionJson["SelectedObjectIds"].get<std::vector<MetaCoreId>>();
}
if (selectionJson.contains("ActiveObjectId")) {
sceneDocument.Selection.ActiveObjectId = selectionJson["ActiveObjectId"].get<MetaCoreId>();
}
if (selectionJson.contains("SelectionAnchorId")) {
sceneDocument.Selection.SelectionAnchorId = selectionJson["SelectionAnchorId"].get<MetaCoreId>();
}
}
if (sceneJson.contains("GameObjects") && sceneJson["GameObjects"].is_array()) {
for (const auto& objJson : sceneJson["GameObjects"]) {
MetaCoreGameObjectData obj;
obj.Id = objJson["Id"].get<MetaCoreId>();
obj.ParentId = objJson["ParentId"].get<MetaCoreId>();
obj.Name = objJson["Name"].get<std::string>();
// 反序列化 Transform 组件
if (objJson.contains("Transform")) {
const auto& transJson = objJson["Transform"];
obj.Transform.Position = JsonToVec3(transJson["Position"]);
obj.Transform.RotationEulerDegrees = JsonToVec3(transJson["RotationEulerDegrees"]);
obj.Transform.Scale = JsonToVec3(transJson["Scale"]);
}
// 反序列化 MeshRenderer 组件 (如果有)
if (objJson.contains("MeshRenderer")) {
const auto& meshJson = objJson["MeshRenderer"];
MetaCoreMeshRendererComponent mesh;
mesh.MeshSource = static_cast<MetaCoreMeshSourceKind>(meshJson["MeshSource"].get<int>());
mesh.BuiltinMesh = static_cast<MetaCoreBuiltinMeshType>(meshJson["BuiltinMesh"].get<int>());
mesh.MeshAssetGuid = StringToGuid(meshJson["MeshAssetGuid"].get<std::string>());
if (meshJson.contains("MaterialAssetGuids") && meshJson["MaterialAssetGuids"].is_array()) {
for (const auto& mGuidJson : meshJson["MaterialAssetGuids"]) {
mesh.MaterialAssetGuids.push_back(StringToGuid(mGuidJson.get<std::string>()));
}
}
mesh.SourceModelAssetGuid = StringToGuid(meshJson["SourceModelAssetGuid"].get<std::string>());
mesh.SourceModelPath = meshJson["SourceModelPath"].get<std::string>();
mesh.SourceNodePath = meshJson["SourceNodePath"].get<std::string>();
mesh.BaseColorTextureGuid = StringToGuid(meshJson["BaseColorTextureGuid"].get<std::string>());
mesh.MetallicRoughnessTextureGuid = StringToGuid(meshJson["MetallicRoughnessTextureGuid"].get<std::string>());
mesh.NormalTextureGuid = StringToGuid(meshJson["NormalTextureGuid"].get<std::string>());
mesh.EmissiveTextureGuid = StringToGuid(meshJson["EmissiveTextureGuid"].get<std::string>());
mesh.AoTextureGuid = StringToGuid(meshJson["AoTextureGuid"].get<std::string>());
mesh.BaseColorTexturePath = meshJson["BaseColorTexturePath"].get<std::string>();
mesh.MetallicRoughnessTexturePath = meshJson["MetallicRoughnessTexturePath"].get<std::string>();
mesh.NormalTexturePath = meshJson["NormalTexturePath"].get<std::string>();
mesh.EmissiveTexturePath = meshJson["EmissiveTexturePath"].get<std::string>();
mesh.AoTexturePath = meshJson["AoTexturePath"].get<std::string>();
mesh.DoubleSided = meshJson["DoubleSided"].get<bool>();
mesh.Metallic = meshJson["Metallic"].get<float>();
mesh.Roughness = meshJson["Roughness"].get<float>();
mesh.AlphaMode = static_cast<MetaCoreMeshAlphaMode>(meshJson["AlphaMode"].get<int>());
mesh.AlphaCutoff = meshJson["AlphaCutoff"].get<float>();
mesh.EmissiveColor = JsonToVec3(meshJson["EmissiveColor"]);
mesh.BaseColor = JsonToVec3(meshJson["BaseColor"]);
mesh.ModelNodeIndex = meshJson["ModelNodeIndex"].get<std::int32_t>();
mesh.SubMeshIndex = meshJson["SubMeshIndex"].get<std::int32_t>();
mesh.Visible = meshJson["Visible"].get<bool>();
obj.MeshRenderer = mesh;
}
// 反序列化 Light 组件 (如果有)
if (objJson.contains("Light")) {
const auto& lightJson = objJson["Light"];
MetaCoreLightComponent light;
light.Color = JsonToVec3(lightJson["Color"]);
light.Intensity = lightJson["Intensity"].get<float>();
obj.Light = light;
}
// 反序列化 Camera 组件 (如果有)
if (objJson.contains("Camera")) {
const auto& camJson = objJson["Camera"];
MetaCoreCameraComponent cam;
cam.FieldOfViewDegrees = camJson["FieldOfViewDegrees"].get<float>();
cam.NearClip = camJson["NearClip"].get<float>();
cam.FarClip = camJson["FarClip"].get<float>();
cam.IsPrimary = camJson["IsPrimary"].get<bool>();
obj.Camera = cam;
}
// 反序列化 PrefabInstance 预制体元数据 (如果有)
if (objJson.contains("PrefabInstance")) {
const auto& prefabJson = objJson["PrefabInstance"];
MetaCorePrefabInstanceMetadata prefab;
prefab.PrefabAssetGuid = StringToGuid(prefabJson["PrefabAssetGuid"].get<std::string>());
prefab.PrefabObjectId = prefabJson["PrefabObjectId"].get<MetaCoreId>();
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