using System.Collections.Generic; using System.Linq; using AssetBank.Editor.SchemaConverter.Data.Input; using AssetBank.Editor.SchemaConverter.Data.Output; using AssetBank.Editor.SchemaConverter.Processors; using Newtonsoft.Json; namespace AssetBank.Editor.SchemaConverter { /// /// Public-facing static class to orchestrate the JSON schema conversion. /// public static class JsonSchemaConverter { /// /// Converts a raw JSON string from the original format to the new, hierarchical SceneGraph format. /// /// The raw JSON string to convert. /// Internal flag to prevent infinite loops when processing prefabs inside prefabs. /// A new JSON string representing the structured SceneGraph. public static string Convert(string originalJson, bool isRecursiveCall = false) { var sceneGraph = ConvertToSceneGraph(originalJson, isRecursiveCall); return JsonConvert.SerializeObject(sceneGraph, Formatting.None); } /// /// Converts the JSON to a SceneGraph object. This is the core logic. /// public static SceneGraph ConvertToSceneGraph(string originalJson, bool isRecursiveCall = false) { var allNodes = JsonConvert.DeserializeObject>(originalJson); if (allNodes == null) return new SceneGraph(); var warnings = new List(); var sceneGraph = new SceneGraph(); // 1. Process Prefabs first to get a definitive list of all GUIDs. var prefabInstanceNodes = allNodes.Where(n => n.type_id == "1001").ToList(); var (prefabGuids, prefabWarnings) = PrefabProcessor.Process(prefabInstanceNodes); if (!isRecursiveCall) { sceneGraph.prefabs = prefabGuids; } warnings.AddRange(prefabWarnings); // 2. Process Hierarchy, passing the prefab GUID list for context. var prefabInstanceMap = prefabInstanceNodes.ToDictionary(n => n.anchor_id); var hierarchyProcessor = new HierarchyProcessor(); var (rootNodes, hierarchyWarnings, consumedIds) = hierarchyProcessor.Process(allNodes, prefabInstanceMap, prefabGuids); sceneGraph.hierarchy = rootNodes; warnings.AddRange(hierarchyWarnings); // Also mark all prefab instances themselves as "consumed" foreach (var key in prefabInstanceMap.Keys) { consumedIds.Add(key); } // 3. Process Scene Data with the remaining, unconsumed nodes // sceneGraph.scene_data = SceneDataProcessor.Process(allNodes, consumedIds); // 4. Assemble Metadata sceneGraph.metadata = new Metadata { warnings = warnings.Count > 0 ? warnings : null }; return sceneGraph; } } }