DragonECS-Unity/src/RefRepairer/MissingRefCollectUtility.cs

183 lines
7.6 KiB
C#
Raw Normal View History

2024-09-30 19:40:50 +08:00
#if UNITY_EDITOR
2024-09-29 23:31:12 +08:00
using System.Collections.Generic;
2024-09-29 15:59:14 +08:00
using System.Linq;
using System.Reflection;
using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityObject = UnityEngine.Object;
2024-09-29 23:31:12 +08:00
namespace DCFApixels.DragonECS.Unity.RefRepairer.Editors
2024-09-29 15:59:14 +08:00
{
2024-09-30 19:40:50 +08:00
internal static class UnityObjectExtensions
2024-09-29 15:59:14 +08:00
{
public static int GetLocalIdentifierInFile(this UnityObject unityObject)
{
PropertyInfo inspectorModeInfo = typeof(SerializedObject).GetProperty("inspectorMode", BindingFlags.NonPublic | BindingFlags.Instance);
SerializedObject serializedObject = new SerializedObject(unityObject);
inspectorModeInfo.SetValue(serializedObject, InspectorMode.Debug, null);
SerializedProperty localIdProp = serializedObject.FindProperty("m_LocalIdentfierInFile");
return localIdProp.intValue;
}
}
2024-09-30 19:40:50 +08:00
internal class ContainerMissingTypes
2024-09-29 15:59:14 +08:00
{
2024-09-30 19:40:50 +08:00
public readonly GUID AssetGUID;
public readonly List<ContainerMissingRefs> Recirds = new List<ContainerMissingRefs>();
public ContainerMissingTypes(GUID assetGUID)
{
AssetGUID = assetGUID;
}
}
internal class MissingRefCollectUtility
{
//private readonly Dictionary<TypeData, ContainerMissingRefs> _manualRepairedMissingRefs = new Dictionary<TypeData, ContainerMissingRefs>();
//private readonly List<ContainerMissingTypes> _autoRepariedMissingTypes = new List<ContainerMissingTypes>();
2024-09-29 15:59:14 +08:00
2024-09-30 19:40:50 +08:00
private readonly List<Record> _collectedMissingTypes = new List<Record>();
2024-09-29 15:59:14 +08:00
#region Collect
2024-09-30 19:40:50 +08:00
public List<Record> Collect()
2024-09-29 15:59:14 +08:00
{
2024-09-30 19:40:50 +08:00
//_manualRepairedMissingRefs.Clear();
_collectedMissingTypes.Clear();
2024-09-29 15:59:14 +08:00
2024-09-30 19:40:50 +08:00
CollectByPrefabs(_collectedMissingTypes);
CollectByScriptableObjects(_collectedMissingTypes);
CollectByScenes(_collectedMissingTypes);
2024-09-29 15:59:14 +08:00
2024-09-30 19:40:50 +08:00
//ContainerMissingRefs[] result = _manualRepairedMissingRefs.Values.ToArray();
//_manualRepairedMissingRefs.Clear();
return _collectedMissingTypes;
2024-09-29 15:59:14 +08:00
}
2024-09-30 19:40:50 +08:00
public readonly struct Record
{
public readonly UnityObjectDataBase UnityObject;
public readonly ManagedReferenceMissingType[] missingTypes;
public Record(UnityObjectDataBase unityObject, ManagedReferenceMissingType[] missingTypes)
{
UnityObject = unityObject;
this.missingTypes = missingTypes;
}
}
private void CollectByPrefabs(List<Record> list)
2024-09-29 15:59:14 +08:00
{
Scene previewScene = EditorSceneManager.NewPreviewScene();
foreach (var pathToPrefab in AssetDatabase.GetAllAssetPaths().Where(path => path.StartsWith("Assets/") && path.EndsWith(".prefab")))
{
2024-09-30 19:40:50 +08:00
var prefabAsset = AssetDatabase.LoadAssetAtPath<GameObject>(pathToPrefab);
var unityObjectData = new UnityObjectData(prefabAsset, pathToPrefab);
2024-09-29 15:59:14 +08:00
2024-09-30 19:40:50 +08:00
PrefabUtility.LoadPrefabContentsIntoPreviewScene(pathToPrefab, previewScene);
var prefabLoaded = previewScene.GetRootGameObjects()[0];
2024-09-29 15:59:14 +08:00
2024-09-30 19:40:50 +08:00
foreach (var component in prefabLoaded.GetComponentsInChildren<MonoBehaviour>())
2024-09-29 15:59:14 +08:00
{
2024-09-30 19:40:50 +08:00
if (SerializationUtility.HasManagedReferencesWithMissingTypes(component) == false) { continue; }
2024-09-29 15:59:14 +08:00
2024-09-30 19:40:50 +08:00
var missings = SerializationUtility.GetManagedReferencesWithMissingTypes(component);
list.Add(new Record(unityObjectData, missings));
2024-09-29 15:59:14 +08:00
}
2024-09-30 19:40:50 +08:00
UnityObject.DestroyImmediate(prefabLoaded);
2024-09-29 15:59:14 +08:00
}
EditorSceneManager.ClosePreviewScene(previewScene);
}
2024-09-30 19:40:50 +08:00
private void CollectByScriptableObjects(List<Record> list)
2024-09-29 15:59:14 +08:00
{
foreach (var pathToPrefab in AssetDatabase.GetAllAssetPaths().Where(path => path.StartsWith("Assets/") && path.EndsWith(".asset")))
{
var scriptableObject = AssetDatabase.LoadAssetAtPath<ScriptableObject>(pathToPrefab);
2024-09-30 19:40:50 +08:00
var unityObjectData = new UnityObjectData(scriptableObject, pathToPrefab);
2024-09-29 15:59:14 +08:00
2024-09-30 19:40:50 +08:00
if (SerializationUtility.HasManagedReferencesWithMissingTypes(scriptableObject) == false) { continue; }
2024-09-29 15:59:14 +08:00
2024-09-30 19:40:50 +08:00
var missings = SerializationUtility.GetManagedReferencesWithMissingTypes(scriptableObject);
list.Add(new Record(unityObjectData, missings));
2024-09-29 15:59:14 +08:00
}
}
2024-09-30 19:40:50 +08:00
private void CollectByScenes(List<Record> list)
2024-09-29 15:59:14 +08:00
{
try
{
foreach (var scene in GetAllScenesInAssets())
{
2024-09-30 19:40:50 +08:00
var unityObjectData = new SceneObjectData(scene);
2024-09-29 15:59:14 +08:00
var gameObjects = scene.GetRootGameObjects();
foreach (var objectOnScene in gameObjects)
{
foreach (var monoBehaviour in objectOnScene.GetComponentsInChildren<MonoBehaviour>())
{
2024-09-30 19:40:50 +08:00
if (SerializationUtility.HasManagedReferencesWithMissingTypes(monoBehaviour) == false) { continue; }
var missings = SerializationUtility.GetManagedReferencesWithMissingTypes(monoBehaviour);
list.Add(new Record(unityObjectData, missings));
2024-09-29 15:59:14 +08:00
}
}
}
}
catch (System.Exception e)
{
Debug.LogException(e);
}
}
#endregion
#region Utils
private static IEnumerable<Scene> GetAllScenesInAssets()
{
var oldScenesSetup = EditorSceneManager.GetSceneManagerSetup();
(bool isHasSelected, string scenePath, int identifierInFile) oldSelectedObject = default;
GameObject activeGameObject = Selection.activeGameObject;
if (activeGameObject != null)
{
oldSelectedObject.isHasSelected = true;
oldSelectedObject.scenePath = activeGameObject.scene.path;
oldSelectedObject.identifierInFile = activeGameObject.GetLocalIdentifierInFile();
}
foreach (var pathToScene in AssetDatabase.GetAllAssetPaths().Where(path => path.StartsWith("Assets/") && path.EndsWith(".unity")))
{
Scene scene = EditorSceneManager.OpenScene(pathToScene, OpenSceneMode.Single);
yield return scene;
}
EditorSceneManager.RestoreSceneManagerSetup(oldScenesSetup);
if (oldSelectedObject.isHasSelected)
{
Selection.activeGameObject = SceneManager.GetSceneByPath(oldSelectedObject.scenePath)
.GetRootGameObjects()
.FirstOrDefault(gameObject => gameObject.GetLocalIdentifierInFile() == oldSelectedObject.identifierInFile);
}
else
{
Selection.activeGameObject = null;
}
}
2024-09-30 19:40:50 +08:00
//private void AddMissingType(ManagedReferenceMissingType missingType, UnityObjectDataBase unityObject)
//{
// var typeData = new TypeData(missingType);
// var missingTypeData = new MissingTypeData(missingType, unityObject);
// if (_manualRepairedMissingRefs.TryGetValue(typeData, out var containerMissingTypes) == false)
// {
// containerMissingTypes = new ContainerMissingRefs(typeData);
// _manualRepairedMissingRefs.Add(typeData, containerMissingTypes);
// }
//
// containerMissingTypes.ManagedReferencesMissingTypeDatas.Add(missingTypeData);
//}
2024-09-29 15:59:14 +08:00
#endregion
}
2024-09-30 19:40:50 +08:00
}
#endif