using System; using System.Collections.Generic; using UnityEditor; using UnityEngine; using Newtonsoft.Json.Linq; namespace AssetBank.Editor.SceneSchema.Internal { public static class MonoBehaviourSerializer { public static IDictionary Serialize(MonoBehaviour obj) { var fields = new Dictionary(); if (obj == null) return fields; var serializedObject = new SerializedObject(obj); var property = serializedObject.GetIterator(); property.NextVisible(true); while (property.NextVisible(false)) { fields[property.name] = ConvertPropertyToJToken(property); } return fields; } private static JToken ConvertPropertyToJToken(SerializedProperty prop) { if (prop.depth > 10) return JValue.CreateNull(); switch (prop.propertyType) { // Basic Types case SerializedPropertyType.Integer: return new JValue(prop.longValue); case SerializedPropertyType.Boolean: return new JValue(prop.boolValue); case SerializedPropertyType.Float: return new JValue(prop.doubleValue); case SerializedPropertyType.String: return new JValue(prop.stringValue); case SerializedPropertyType.Enum: return new JValue(prop.enumDisplayNames[prop.enumValueIndex]); // Unity-specific Structs case SerializedPropertyType.Color: var c = prop.colorValue; return new JObject { { "r", c.r }, { "g", c.g }, { "b", c.b }, { "a", c.a } }; case SerializedPropertyType.Vector2: var v2 = prop.vector2Value; return new JObject { { "x", v2.x }, { "y", v2.y } }; case SerializedPropertyType.Vector3: var v3 = prop.vector3Value; return new JObject { { "x", v3.x }, { "y", v3.y }, { "z", v3.z } }; case SerializedPropertyType.Vector4: var v4 = prop.vector4Value; return new JObject { { "x", v4.x }, { "y", v4.y }, { "z", v4.z }, { "w", v4.w } }; case SerializedPropertyType.Quaternion: var q = prop.quaternionValue; return new JObject { { "x", q.x }, { "y", q.y }, { "z", q.z }, { "w", q.w } }; case SerializedPropertyType.Rect: var r = prop.rectValue; return new JObject { { "x", r.x }, { "y", r.y }, { "width", r.width }, { "height", r.height } }; case SerializedPropertyType.Bounds: var b = prop.boundsValue; return new JObject { { "center", new JObject { { "x", b.center.x }, { "y", b.center.y }, { "z", b.center.z } } }, { "size", new JObject { { "x", b.size.x }, { "y", b.size.y }, { "z", b.size.z } } } }; // Reference Types case SerializedPropertyType.ObjectReference: return SerializeObjectReference(prop.objectReferenceValue); // Arrays and Lists case SerializedPropertyType.Generic when prop.isArray: var array = new JArray(); for (var i = 0; i < prop.arraySize; i++) { array.Add(ConvertPropertyToJToken(prop.GetArrayElementAtIndex(i))); } return array; // Nested Serializable Classes case SerializedPropertyType.Generic: var nestedObject = new JObject(); var copy = prop.Copy(); var end = copy.GetEndProperty(); copy.NextVisible(true); while (!SerializedProperty.EqualContents(copy, end)) { nestedObject[copy.name] = ConvertPropertyToJToken(copy); copy.NextVisible(false); } return nestedObject; default: return new JValue($"Unsupported Type: {prop.propertyType}"); } } private static JToken SerializeObjectReference(UnityEngine.Object obj) { if (obj == null) return JValue.CreateNull(); var reference = new JObject { ["type"] = obj.GetType().FullName }; if (AssetDatabase.TryGetGUIDAndLocalFileIdentifier(obj, out var guid, out long _)) { reference["guid"] = guid; reference["assetPath"] = AssetDatabase.GUIDToAssetPath(guid); } else { reference["scene_object_id"] = EditorUtilities.GetLocalFileID(obj); } return reference; } } }