This commit is contained in:
Mikhail 2024-10-01 07:13:13 +08:00
parent 776648a993
commit 04423b2274
9 changed files with 351 additions and 138 deletions

View File

@ -5,6 +5,16 @@ using System.Runtime.CompilerServices;
namespace DCFApixels.DragonECS.Unity.Internal
{
public readonly struct ArrayBuffer<T>
{
public readonly T[] Array;
public readonly int Length;
public ArrayBuffer(T[] array, int length)
{
Array = array;
Length = length;
}
}
internal interface ILinkedNext
{
int Next { get; }

View File

@ -20,7 +20,7 @@ namespace DCFApixels.DragonECS.Unity.Editors
wnd.Show();
}
private List<ContainerMissingRefs> _missingTypes;
//private List<ContainerMissingRefs> _missingTypes;
//private readonly CollectorMissingTypes _collectorMissingTypes = new CollectorMissingTypes();
private bool TryInit()

View File

@ -1,4 +1,6 @@
#if UNITY_EDITOR
using DCFApixels.DragonECS.Unity.RefRepairer.Internal;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
@ -10,62 +12,109 @@ using UnityObject = UnityEngine.Object;
namespace DCFApixels.DragonECS.Unity.RefRepairer.Editors
{
internal static class UnityObjectExtensions
internal class MissingRefContainer
{
public static int GetLocalIdentifierInFile(this UnityObject unityObject)
public CollectedAssetMissingRecord[] collectedMissingTypesBuffer = null;
public int collectedMissingTypesBufferCount = 0;
public readonly Dictionary<TypeData, MissingsResolvingData> MissingsResolvingDatas = new Dictionary<TypeData, MissingsResolvingData>();
#region Clear/RemoveResolved
public void Clear()
{
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;
for (int i = 0; i < collectedMissingTypesBufferCount; i++)
{
collectedMissingTypesBuffer[i] = default;
}
collectedMissingTypesBufferCount = 0;
MissingsResolvingDatas.Clear();
}
}
internal class ContainerMissingTypes
{
public readonly GUID AssetGUID;
public readonly List<ContainerMissingRefs> Recirds = new List<ContainerMissingRefs>();
public ContainerMissingTypes(GUID assetGUID)
public void RemoveResolved()
{
AssetGUID = assetGUID;
int offset = 0;
int i = 0;
int newLength = collectedMissingTypesBufferCount;
for (; i < newLength; i++)
{
ref var collectedMissingType = ref collectedMissingTypesBuffer[i];
if (collectedMissingType.IsResolvedOrNull)
{
if (collectedMissingType.ResolvingData != null)
{
MissingsResolvingDatas.Remove(collectedMissingType.ResolvingData.OldTypeData);
}
offset = 1;
newLength--;
break;
}
}
if (i >= newLength) { return; }
int nextI = i + offset;
for (; nextI < newLength; nextI++)
{
ref var collectedMissingType = ref collectedMissingTypesBuffer[i];
if (collectedMissingType.IsResolvedOrNull)
{
if (collectedMissingType.ResolvingData != null)
{
MissingsResolvingDatas.Remove(collectedMissingType.ResolvingData.OldTypeData);
}
offset++;
newLength--;
}
else
{
collectedMissingTypesBuffer[i] = collectedMissingTypesBuffer[nextI];
i++;
}
}
for (i = newLength; i < collectedMissingTypesBufferCount; i++)
{
collectedMissingTypesBuffer[i] = default;
}
collectedMissingTypesBufferCount = newLength;
}
}
internal class MissingRefCollectUtility
{
//private readonly Dictionary<TypeData, ContainerMissingRefs> _manualRepairedMissingRefs = new Dictionary<TypeData, ContainerMissingRefs>();
//private readonly List<ContainerMissingTypes> _autoRepariedMissingTypes = new List<ContainerMissingTypes>();
private readonly List<Record> _collectedMissingTypes = new List<Record>();
#endregion
#region Collect
public List<Record> Collect()
public void Collect()
{
//_manualRepairedMissingRefs.Clear();
_collectedMissingTypes.Clear();
CollectByPrefabs(_collectedMissingTypes);
CollectByScriptableObjects(_collectedMissingTypes);
CollectByScenes(_collectedMissingTypes);
//ContainerMissingRefs[] result = _manualRepairedMissingRefs.Values.ToArray();
//_manualRepairedMissingRefs.Clear();
return _collectedMissingTypes;
}
public readonly struct Record
{
public readonly UnityObjectDataBase UnityObject;
public readonly ManagedReferenceMissingType[] missingTypes;
public Record(UnityObjectDataBase unityObject, ManagedReferenceMissingType[] missingTypes)
int oldCollectedMissingTypesBufferCount = collectedMissingTypesBufferCount;
if (collectedMissingTypesBuffer == null)
{
UnityObject = unityObject;
this.missingTypes = missingTypes;
collectedMissingTypesBuffer = new CollectedAssetMissingRecord[256];
}
collectedMissingTypesBufferCount = 0;
MissingsResolvingDatas.Clear();
CollectByPrefabs();
CollectByScriptableObjects();
CollectByScenes();
for (int i = collectedMissingTypesBufferCount; i < oldCollectedMissingTypesBufferCount; i++)
{
collectedMissingTypesBuffer[i] = default;
}
}
private void CollectByPrefabs(List<Record> list)
private void Add(UnityObjectDataBase unityObjectData, ref ManagedReferenceMissingType missing)
{
var typeData = new TypeData(missing);
if (MissingsResolvingDatas.TryGetValue(typeData, out var resolvingData) == false)
{
resolvingData = new MissingsResolvingData(typeData);
MissingsResolvingDatas.Add(typeData, resolvingData);
}
if (collectedMissingTypesBufferCount >= collectedMissingTypesBuffer.Length)
{
Array.Resize(ref collectedMissingTypesBuffer, collectedMissingTypesBuffer.Length << 1);
}
collectedMissingTypesBuffer[collectedMissingTypesBufferCount++] = new CollectedAssetMissingRecord(unityObjectData, missing, resolvingData);
}
private void CollectByPrefabs()
{
Scene previewScene = EditorSceneManager.NewPreviewScene();
foreach (var pathToPrefab in AssetDatabase.GetAllAssetPaths().Where(path => path.StartsWith("Assets/") && path.EndsWith(".prefab")))
@ -81,14 +130,17 @@ namespace DCFApixels.DragonECS.Unity.RefRepairer.Editors
if (SerializationUtility.HasManagedReferencesWithMissingTypes(component) == false) { continue; }
var missings = SerializationUtility.GetManagedReferencesWithMissingTypes(component);
list.Add(new Record(unityObjectData, missings));
for (int i = 0; i < missings.Length; i++)
{
Add(unityObjectData, ref missings[i]);
}
}
UnityObject.DestroyImmediate(prefabLoaded);
}
EditorSceneManager.ClosePreviewScene(previewScene);
}
private void CollectByScriptableObjects(List<Record> list)
private void CollectByScriptableObjects()
{
foreach (var pathToPrefab in AssetDatabase.GetAllAssetPaths().Where(path => path.StartsWith("Assets/") && path.EndsWith(".asset")))
{
@ -98,10 +150,13 @@ namespace DCFApixels.DragonECS.Unity.RefRepairer.Editors
if (SerializationUtility.HasManagedReferencesWithMissingTypes(scriptableObject) == false) { continue; }
var missings = SerializationUtility.GetManagedReferencesWithMissingTypes(scriptableObject);
list.Add(new Record(unityObjectData, missings));
for (int i = 0; i < missings.Length; i++)
{
Add(unityObjectData, ref missings[i]);
}
}
}
private void CollectByScenes(List<Record> list)
private void CollectByScenes()
{
try
{
@ -118,12 +173,15 @@ namespace DCFApixels.DragonECS.Unity.RefRepairer.Editors
if (SerializationUtility.HasManagedReferencesWithMissingTypes(monoBehaviour) == false) { continue; }
var missings = SerializationUtility.GetManagedReferencesWithMissingTypes(monoBehaviour);
list.Add(new Record(unityObjectData, missings));
for (int i = 0; i < missings.Length; i++)
{
Add(unityObjectData, ref missings[i]);
}
}
}
}
}
catch (System.Exception e)
catch (Exception e)
{
Debug.LogException(e);
}
@ -179,5 +237,28 @@ namespace DCFApixels.DragonECS.Unity.RefRepairer.Editors
#endregion
}
internal static class UnityObjectExtensions
{
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;
}
}
//internal class ContainerMissingTypes
//{
// public readonly GUID AssetGUID;
// public readonly List<ContainerMissingRefs> Recirds = new List<ContainerMissingRefs>();
// public ContainerMissingTypes(GUID assetGUID)
// {
// AssetGUID = assetGUID;
// }
//}
}
#endif

View File

@ -1,6 +1,8 @@
#if UNITY_EDITOR
using DCFApixels.DragonECS.Unity.RefRepairer.Internal;
using System;
using System.IO;
using System.Linq;
using UnityEditor;
using UnityEngine;
@ -34,11 +36,60 @@ namespace DCFApixels.DragonECS.Unity.RefRepairer.Editors
{
return $"type: {{class: {typeData.ClassName}, ns: {typeData.NamespaceName}, asm: {typeData.AssemblyName}}}";
}
public static string GenerateReplacedLine(ManagedReferenceMissingType typeData)
public static void RepaieAsset(MissingRefContainer container)
{
return $"type: {{class: {typeData.className}, ns: {typeData.namespaceName}, asm: {typeData.assemblyName}}}";
}
if (container.collectedMissingTypesBufferCount <= 0) { return; }
MissingsResolvingData[] missingsResolvingDatas = container.MissingsResolvingDatas.Values.Where(o => o.IsResolved).ToArray();
for (int i = 0; i < container.collectedMissingTypesBufferCount; i++)
{
ref var missing = ref container.collectedMissingTypesBuffer[i];
if (missing.IsNull) { continue; }
var unityObjectData = missing.UnityObject;
using (var file = new FileScope(AssetDatabase.GUIDToAssetPath(unityObjectData.AssetGuid)))
{
int startRepaierLineIndex = 0;//Ýòî íóæíî ÷òîáû ñêèïàòü óæå "îòðåìîíòèðîâàííóþ" ÷àñòü ôàéë.
// òóò èòåðèðóþñü ïî áëîêó missingsResolvingDatas ñ îäèíàêîâûì þíèòè îáúåêòîì, òàê êàê òàêèå èäåóò ïîäðÿò
do
{
bool isAnySkiped = false;
int lineIndex = NextRefLine(file.lines, startRepaierLineIndex);
while (lineIndex > 0)
{
var line = file.lines[lineIndex];
// Êàê ñêàçàííî â äîêóìåíòàöèè ê ìåòîäó Replace
// A string that is equivalent to this instance except that all instances of oldChar are replaced with newChar.
// If oldChar is not found in the current instance, the method returns the current instance unchanged.
// À êîíêðåòíî ñòðî÷êè "returns the current instance unchanged", ìîæíî ñäåëàòü óïðîùåííóþ ïðîâåðêó ÷åðåç ReferenceEquals
string oldLine = line;
line = line.Replace(missing.ResolvingData.OldSerializedInfoLine, missing.ResolvingData.NewSerializedInfoLine);
bool isChanged = !ReferenceEquals(oldLine, line);
if (isChanged == false)
{
isAnySkiped = true;
}
else
{
if (isAnySkiped == false)
{
startRepaierLineIndex = lineIndex;
}
}
lineIndex = NextRefLine(file.lines, lineIndex);
}
missing = ref container.collectedMissingTypesBuffer[i++];
} while (unityObjectData == missing.UnityObject);
i--;//÷òîáû èòåðàöèÿ íå ïîëîìàëàñü
}
}
container.RemoveResolved();
}
public struct FileScope : IDisposable
{
public readonly string FilePath;
@ -61,63 +112,64 @@ namespace DCFApixels.DragonECS.Unity.RefRepairer.Editors
}
internal class RepairerFile
{
private readonly Type _type;
private readonly string[] _fileLines;
private string _currentLine;
private string _nextLine;
private int _currentIndex;
private readonly string _path;
private readonly string _localAssetPath;
public RepairerFile(Type type, string localAssetPath)
{
_type = type;
_localAssetPath = localAssetPath;
_path = $"{Application.dataPath.Replace("/Assets", "")}/{localAssetPath}";
_fileLines = File.ReadAllLines(_path);
}
public delegate bool GetterMissingTypeData(out MissingTypeData missingType);
public void Repair(Func<bool> callbackForNextLine)
{
for (int i = 0; i < _fileLines.Length - 1; ++i)
{
_currentIndex = i;
_currentLine = _fileLines[i];
_nextLine = _fileLines[i + 1];
if (callbackForNextLine.Invoke())
break;
}
File.WriteAllLines(_path, _fileLines);
AssetDatabase.ImportAsset(_localAssetPath, ImportAssetOptions.ForceUpdate);
AssetDatabase.Refresh();
}
public bool CheckNeedLineAndReplacedIt(ManagedReferenceMissingType missingType)
{
string rid = $"rid: {missingType.referenceId}";
string oldTypeData = $"type: {{class: {missingType.className}, ns: {missingType.namespaceName}, asm: {missingType.assemblyName}}}";
if (_currentLine.Contains(rid) && _nextLine.Contains(oldTypeData))
{
string newTypeData = $"type: {{class: {_type.Name}, ns: {_type.Namespace}, asm: {_type.Assembly.GetName().Name}}}";
_fileLines[_currentIndex + 1] = _nextLine.Replace(oldTypeData, newTypeData);
return true;
}
return false;
}
}
//internal class RepairerFile
//{
// private readonly Type _type;
// private readonly string[] _fileLines;
//
// private string _currentLine;
// private string _nextLine;
//
// private int _currentIndex;
//
// private readonly string _path;
// private readonly string _localAssetPath;
//
// public RepairerFile(Type type, string localAssetPath)
// {
// _type = type;
// _localAssetPath = localAssetPath;
//
// _path = $"{Application.dataPath.Replace("/Assets", "")}/{localAssetPath}";
// _fileLines = File.ReadAllLines(_path);
// }
//
// public delegate bool GetterMissingTypeData(out MissingTypeData missingType);
//
// public void Repair(Func<bool> callbackForNextLine)
// {
// for (int i = 0; i < _fileLines.Length - 1; ++i)
// {
// _currentIndex = i;
//
// _currentLine = _fileLines[i];
// _nextLine = _fileLines[i + 1];
//
// if (callbackForNextLine.Invoke())
// break;
// }
//
// File.WriteAllLines(_path, _fileLines);
//
// AssetDatabase.ImportAsset(_localAssetPath, ImportAssetOptions.ForceUpdate);
// AssetDatabase.Refresh();
// }
//
// public bool CheckNeedLineAndReplacedIt(ManagedReferenceMissingType missingType)
// {
// string rid = $"rid: {missingType.referenceId}";
// string oldTypeData = $"type: {{class: {missingType.className}, ns: {missingType.namespaceName}, asm: {missingType.assemblyName}}}";
//
// if (_currentLine.Contains(rid) && _nextLine.Contains(oldTypeData))
// {
// string newTypeData = $"type: {{class: {_type.Name}, ns: {_type.Namespace}, asm: {_type.Assembly.GetName().Name}}}";
// _fileLines[_currentIndex + 1] = _nextLine.Replace(oldTypeData, newTypeData);
//
// return true;
// }
//
// return false;
// }
//}
}
#endif

View File

@ -0,0 +1,27 @@
#if UNITY_EDITOR
using UnityEditor;
namespace DCFApixels.DragonECS.Unity.RefRepairer.Editors
{
internal readonly struct CollectedAssetMissingRecord
{
public readonly UnityObjectDataBase UnityObject;
public readonly ManagedReferenceMissingType Missing;
public readonly MissingsResolvingData ResolvingData;
public bool IsResolvedOrNull
{
get { return UnityObject == null || ResolvingData.IsResolved; }
}
public bool IsNull
{
get { return UnityObject == null; }
}
public CollectedAssetMissingRecord(UnityObjectDataBase unityObject, ManagedReferenceMissingType missing, MissingsResolvingData resolvingData)
{
UnityObject = unityObject;
Missing = missing;
ResolvingData = resolvingData;
}
}
}
#endif

View File

@ -4,18 +4,18 @@ using System.Collections.Generic;
namespace DCFApixels.DragonECS.Unity.RefRepairer.Editors
{
internal class ContainerMissingRefs
{
public readonly TypeData TypeData;
public readonly string ReplacedLine;
public readonly List<MissingTypeData> ManagedReferencesMissingTypeDatas = new List<MissingTypeData>(4);
public readonly bool IsHasMetaIDRegistry;
public ContainerMissingRefs(TypeData typeData)
{
TypeData = typeData;
ReplacedLine = RepaireFileUtility.GenerateReplacedLine(typeData);
IsHasMetaIDRegistry = MetaIDRegistry.instance.TryGetMetaID(TypeData, out _);
}
}
//internal class ContainerMissingRefs
//{
// public readonly TypeData TypeData;
// public readonly string ReplacedLine;
// public readonly List<MissingTypeData> ManagedReferencesMissingTypeDatas = new List<MissingTypeData>(4);
// public readonly bool IsHasMetaIDRegistry;
// public ContainerMissingRefs(TypeData typeData)
// {
// TypeData = typeData;
// ReplacedLine = RepaireFileUtility.GenerateReplacedLine(typeData);
// IsHasMetaIDRegistry = MetaIDRegistry.instance.TryGetMetaID(TypeData, out _);
// }
//}
}
#endif

View File

@ -3,16 +3,16 @@ using UnityEditor;
namespace DCFApixels.DragonECS.Unity.RefRepairer.Editors
{
internal readonly struct MissingTypeData
{
public readonly ManagedReferenceMissingType Data;
public readonly UnityObjectDataBase UnityObject;
public MissingTypeData(ManagedReferenceMissingType missingType, UnityObjectDataBase unityObject)
{
Data = missingType;
UnityObject = unityObject;
}
}
//internal readonly struct MissingTypeData
//{
// public readonly ManagedReferenceMissingType Data;
// public readonly UnityObjectDataBase UnityObject;
//
// public MissingTypeData(ManagedReferenceMissingType missingType, UnityObjectDataBase unityObject)
// {
// Data = missingType;
// UnityObject = unityObject;
// }
//}
}
#endif

View File

@ -0,0 +1,43 @@
#if UNITY_EDITOR
using DCFApixels.DragonECS.Unity.RefRepairer.Internal;
namespace DCFApixels.DragonECS.Unity.RefRepairer.Editors
{
internal class MissingsResolvingData
{
public readonly TypeData OldTypeData;
public readonly string OldSerializedInfoLine;
private TypeData _newTypeData;
private string _newSerializedInfoLine;
public MissingsResolvingData(TypeData oldTypeData)
{
OldTypeData = oldTypeData;
OldSerializedInfoLine = RepaireFileUtility.GenerateReplacedLine(oldTypeData);
}
public bool IsResolved
{
get { return string.IsNullOrEmpty(_newTypeData.ClassName) == false; }
}
public TypeData NewTypeData
{
get { return _newTypeData; }
set
{
_newTypeData = value;
_newSerializedInfoLine = null;
}
}
public string NewSerializedInfoLine
{
get
{
if (_newSerializedInfoLine == null)
{
_newSerializedInfoLine = RepaireFileUtility.GenerateReplacedLine(_newTypeData);
}
return _newSerializedInfoLine;
}
}
}
}
#endif