123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170 |
- using System.IO;
- using System.Linq;
- using UnityEditor;
- using UnityEngine;
- using Newtonsoft.Json;
- using AssetBank.Editor.Data;
- using System.Collections.Generic;
- using UnityEditor.SceneManagement;
- using UnityEngine.SceneManagement;
- using AssetBank.Editor.SceneSchema.Internal;
- namespace AssetBank.Editor.SceneSchema
- {
- public static class SceneParser
- {
- public static void Process(string scenePath, string savePath, out string output, out string error)
- {
- output = null;
- error = null;
-
- if (string.IsNullOrEmpty(scenePath) || !File.Exists(scenePath))
- {
- error = $"Scene path is invalid or does not exist. Scene path: {scenePath}";
- return;
- }
- var originalScene = SceneManager.GetActiveScene().path;
-
- try
- {
- var scene = EditorSceneManager.OpenScene(scenePath, OpenSceneMode.Single);
- var sceneData = new SceneData();
- var prefabList = new List<string>();
- var rootGameObjects = scene.GetRootGameObjects();
- foreach (var rootGo in rootGameObjects)
- {
- var goData = ParseGameObjectRecursive(rootGo, prefabList);
- if (goData != null)
- {
- sceneData.Hierarchy.Add(goData);
- }
- }
-
- sceneData.PrefabsInScene = prefabList;
- var json = JsonConvert.SerializeObject(sceneData, new JsonSerializerSettings
- {
- Formatting = Formatting.None,
- NullValueHandling = NullValueHandling.Ignore,
- ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
- });
-
- File.WriteAllText(savePath, json);
- output = $"Successfully processed scene '{scenePath}' and saved JSON to '{savePath}'";
- }
- catch (System.Exception e)
- {
- error = $"Failed to process scene '{scenePath}'. Error: \n{e}";
- }
- finally
- {
- if (!string.IsNullOrEmpty(originalScene))
- {
- EditorSceneManager.OpenScene(originalScene);
- }
- }
- }
- private static GameObjectData ParseGameObjectRecursive(GameObject go, List<string> prefabList)
- {
- if (go == null) return null;
- var goData = new GameObjectData
- {
- Enabled = go.activeSelf,
- Name = go.name,
- Tag = go.tag,
- Layer = go.layer,
- AnchorId = EditorUtilities.GetLocalFileID(go).ToString()
- };
- var isPrefab = PrefabUtility.IsPartOfPrefabInstance(go);
- var isNewlyAdded = isPrefab && PrefabUtility.GetCorrespondingObjectFromSource(go) == null;
- // Case A: Regular GameObject or a new object added to a prefab instance.
- if (!isPrefab || isNewlyAdded)
- {
- foreach (var component in go.GetComponents<Component>())
- {
- if (component == null) continue;
- goData.Components.Add(ParseComponent(component));
- }
- }
- // Case B & C: Object is part of a prefab (root or child).
- else
- {
- // Handle prefab root
- if (PrefabUtility.GetNearestPrefabInstanceRoot(go) == go)
- {
- var prefabAsset = PrefabUtility.GetCorrespondingObjectFromSource(go);
- if (prefabAsset != null)
- {
- var prefabGuid = AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(prefabAsset));
- if (!prefabList.Contains(prefabGuid))
- {
- prefabList.Add(prefabGuid);
- }
- goData.PrefabIndex = prefabList.IndexOf(prefabGuid);
- }
- }
-
- // Handle added/removed components for this specific GameObject
- goData.AddedComponents = PrefabUtility.GetAddedComponents(go)
- .Select(c => ParseComponent(c.instanceComponent))
- .ToList();
- goData.RemovedComponentAnchorIds = PrefabUtility.GetRemovedComponents(go)
- .Select(c => EditorUtilities.GetLocalFileID(c.assetComponent).ToString())
- .ToList();
- }
- // Recursively parse children and prune empty nodes
- foreach (Transform child in go.transform)
- {
- var childData = ParseGameObjectRecursive(child.gameObject, prefabList);
- if (childData != null)
- {
- goData.Children.Add(childData);
- }
- }
- // Pruning logic: If a prefab node has no overrides and no new children, discard it.
- var isOriginalPrefabPart = isPrefab && !isNewlyAdded;
- if (isOriginalPrefabPart)
- {
- var hasOverrides = goData.AddedComponents.Any() || goData.RemovedComponentAnchorIds.Any();
- var hasChildrenWithOverrides = goData.Children.Any();
- var isRoot = goData.PrefabIndex.HasValue;
- // A non-root part of a prefab is empty if it has no overrides of its own and no children with overrides.
- if (!isRoot && !hasOverrides && !hasChildrenWithOverrides)
- {
- return null;
- }
- }
- return goData;
- }
- private static ComponentData ParseComponent(Component component)
- {
- var componentData = new ComponentData
- {
- Name = component.GetType().Name,
- AnchorId = EditorUtilities.GetLocalFileID(component).ToString()
- };
- if (component is MonoBehaviour monoBehaviour)
- {
- var fullTypeName = monoBehaviour.GetType().FullName;
- if (fullTypeName != null && !fullTypeName.StartsWith("UnityEngine."))
- {
- componentData.Fields = MonoBehaviourSerializer.Serialize(monoBehaviour);
- }
- }
- return componentData;
- }
- }
- }
|