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 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 internal interface ILinkedNext
{ {
int Next { get; } int Next { get; }

View File

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

View File

@ -1,4 +1,6 @@
#if UNITY_EDITOR #if UNITY_EDITOR
using DCFApixels.DragonECS.Unity.RefRepairer.Internal;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
@ -10,62 +12,109 @@ using UnityObject = UnityEngine.Object;
namespace DCFApixels.DragonECS.Unity.RefRepairer.Editors 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); for (int i = 0; i < collectedMissingTypesBufferCount; i++)
SerializedObject serializedObject = new SerializedObject(unityObject); {
inspectorModeInfo.SetValue(serializedObject, InspectorMode.Debug, null); collectedMissingTypesBuffer[i] = default;
SerializedProperty localIdProp = serializedObject.FindProperty("m_LocalIdentfierInFile"); }
return localIdProp.intValue; collectedMissingTypesBufferCount = 0;
MissingsResolvingDatas.Clear();
}
public void RemoveResolved()
{
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++;
} }
} }
internal class ContainerMissingTypes for (i = newLength; i < collectedMissingTypesBufferCount; i++)
{ {
public readonly GUID AssetGUID; collectedMissingTypesBuffer[i] = default;
public readonly List<ContainerMissingRefs> Recirds = new List<ContainerMissingRefs>();
public ContainerMissingTypes(GUID assetGUID)
{
AssetGUID = assetGUID;
}
} }
internal class MissingRefCollectUtility collectedMissingTypesBufferCount = newLength;
{ }
//private readonly Dictionary<TypeData, ContainerMissingRefs> _manualRepairedMissingRefs = new Dictionary<TypeData, ContainerMissingRefs>(); #endregion
//private readonly List<ContainerMissingTypes> _autoRepariedMissingTypes = new List<ContainerMissingTypes>();
private readonly List<Record> _collectedMissingTypes = new List<Record>();
#region Collect #region Collect
public List<Record> Collect() public void Collect()
{ {
//_manualRepairedMissingRefs.Clear(); int oldCollectedMissingTypesBufferCount = collectedMissingTypesBufferCount;
if (collectedMissingTypesBuffer == null)
_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; collectedMissingTypesBuffer = new CollectedAssetMissingRecord[256];
public readonly ManagedReferenceMissingType[] missingTypes; }
public Record(UnityObjectDataBase unityObject, ManagedReferenceMissingType[] missingTypes) collectedMissingTypesBufferCount = 0;
MissingsResolvingDatas.Clear();
CollectByPrefabs();
CollectByScriptableObjects();
CollectByScenes();
for (int i = collectedMissingTypesBufferCount; i < oldCollectedMissingTypesBufferCount; i++)
{ {
UnityObject = unityObject; collectedMissingTypesBuffer[i] = default;
this.missingTypes = missingTypes;
} }
} }
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(); Scene previewScene = EditorSceneManager.NewPreviewScene();
foreach (var pathToPrefab in AssetDatabase.GetAllAssetPaths().Where(path => path.StartsWith("Assets/") && path.EndsWith(".prefab"))) 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; } if (SerializationUtility.HasManagedReferencesWithMissingTypes(component) == false) { continue; }
var missings = SerializationUtility.GetManagedReferencesWithMissingTypes(component); 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); UnityObject.DestroyImmediate(prefabLoaded);
} }
EditorSceneManager.ClosePreviewScene(previewScene); 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"))) 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; } if (SerializationUtility.HasManagedReferencesWithMissingTypes(scriptableObject) == false) { continue; }
var missings = SerializationUtility.GetManagedReferencesWithMissingTypes(scriptableObject); 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 try
{ {
@ -118,12 +173,15 @@ namespace DCFApixels.DragonECS.Unity.RefRepairer.Editors
if (SerializationUtility.HasManagedReferencesWithMissingTypes(monoBehaviour) == false) { continue; } if (SerializationUtility.HasManagedReferencesWithMissingTypes(monoBehaviour) == false) { continue; }
var missings = SerializationUtility.GetManagedReferencesWithMissingTypes(monoBehaviour); 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); Debug.LogException(e);
} }
@ -179,5 +237,28 @@ namespace DCFApixels.DragonECS.Unity.RefRepairer.Editors
#endregion #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 #endif

View File

@ -1,6 +1,8 @@
#if UNITY_EDITOR
using DCFApixels.DragonECS.Unity.RefRepairer.Internal; using DCFApixels.DragonECS.Unity.RefRepairer.Internal;
using System; using System;
using System.IO; using System.IO;
using System.Linq;
using UnityEditor; using UnityEditor;
using UnityEngine; using UnityEngine;
@ -34,11 +36,60 @@ namespace DCFApixels.DragonECS.Unity.RefRepairer.Editors
{ {
return $"type: {{class: {typeData.ClassName}, ns: {typeData.NamespaceName}, asm: {typeData.AssemblyName}}}"; 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 struct FileScope : IDisposable
{ {
public readonly string FilePath; public readonly string FilePath;
@ -61,63 +112,64 @@ namespace DCFApixels.DragonECS.Unity.RefRepairer.Editors
} }
internal class RepairerFile //internal class RepairerFile
{ //{
private readonly Type _type; // private readonly Type _type;
private readonly string[] _fileLines; // private readonly string[] _fileLines;
//
private string _currentLine; // private string _currentLine;
private string _nextLine; // private string _nextLine;
//
private int _currentIndex; // private int _currentIndex;
//
private readonly string _path; // private readonly string _path;
private readonly string _localAssetPath; // private readonly string _localAssetPath;
//
public RepairerFile(Type type, string localAssetPath) // public RepairerFile(Type type, string localAssetPath)
{ // {
_type = type; // _type = type;
_localAssetPath = localAssetPath; // _localAssetPath = localAssetPath;
//
_path = $"{Application.dataPath.Replace("/Assets", "")}/{localAssetPath}"; // _path = $"{Application.dataPath.Replace("/Assets", "")}/{localAssetPath}";
_fileLines = File.ReadAllLines(_path); // _fileLines = File.ReadAllLines(_path);
} // }
//
public delegate bool GetterMissingTypeData(out MissingTypeData missingType); // public delegate bool GetterMissingTypeData(out MissingTypeData missingType);
//
public void Repair(Func<bool> callbackForNextLine) // public void Repair(Func<bool> callbackForNextLine)
{ // {
for (int i = 0; i < _fileLines.Length - 1; ++i) // for (int i = 0; i < _fileLines.Length - 1; ++i)
{ // {
_currentIndex = i; // _currentIndex = i;
//
_currentLine = _fileLines[i]; // _currentLine = _fileLines[i];
_nextLine = _fileLines[i + 1]; // _nextLine = _fileLines[i + 1];
//
if (callbackForNextLine.Invoke()) // if (callbackForNextLine.Invoke())
break; // break;
} // }
//
File.WriteAllLines(_path, _fileLines); // File.WriteAllLines(_path, _fileLines);
//
AssetDatabase.ImportAsset(_localAssetPath, ImportAssetOptions.ForceUpdate); // AssetDatabase.ImportAsset(_localAssetPath, ImportAssetOptions.ForceUpdate);
AssetDatabase.Refresh(); // AssetDatabase.Refresh();
} // }
//
public bool CheckNeedLineAndReplacedIt(ManagedReferenceMissingType missingType) // public bool CheckNeedLineAndReplacedIt(ManagedReferenceMissingType missingType)
{ // {
string rid = $"rid: {missingType.referenceId}"; // string rid = $"rid: {missingType.referenceId}";
string oldTypeData = $"type: {{class: {missingType.className}, ns: {missingType.namespaceName}, asm: {missingType.assemblyName}}}"; // string oldTypeData = $"type: {{class: {missingType.className}, ns: {missingType.namespaceName}, asm: {missingType.assemblyName}}}";
//
if (_currentLine.Contains(rid) && _nextLine.Contains(oldTypeData)) // if (_currentLine.Contains(rid) && _nextLine.Contains(oldTypeData))
{ // {
string newTypeData = $"type: {{class: {_type.Name}, ns: {_type.Namespace}, asm: {_type.Assembly.GetName().Name}}}"; // string newTypeData = $"type: {{class: {_type.Name}, ns: {_type.Namespace}, asm: {_type.Assembly.GetName().Name}}}";
_fileLines[_currentIndex + 1] = _nextLine.Replace(oldTypeData, newTypeData); // _fileLines[_currentIndex + 1] = _nextLine.Replace(oldTypeData, newTypeData);
//
return true; // return true;
} // }
//
return false; // 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 namespace DCFApixels.DragonECS.Unity.RefRepairer.Editors
{ {
internal class ContainerMissingRefs //internal class ContainerMissingRefs
{ //{
public readonly TypeData TypeData; // public readonly TypeData TypeData;
public readonly string ReplacedLine; // public readonly string ReplacedLine;
public readonly List<MissingTypeData> ManagedReferencesMissingTypeDatas = new List<MissingTypeData>(4); // public readonly List<MissingTypeData> ManagedReferencesMissingTypeDatas = new List<MissingTypeData>(4);
public readonly bool IsHasMetaIDRegistry; // public readonly bool IsHasMetaIDRegistry;
public ContainerMissingRefs(TypeData typeData) // public ContainerMissingRefs(TypeData typeData)
{ // {
TypeData = typeData; // TypeData = typeData;
ReplacedLine = RepaireFileUtility.GenerateReplacedLine(typeData); // ReplacedLine = RepaireFileUtility.GenerateReplacedLine(typeData);
IsHasMetaIDRegistry = MetaIDRegistry.instance.TryGetMetaID(TypeData, out _); // IsHasMetaIDRegistry = MetaIDRegistry.instance.TryGetMetaID(TypeData, out _);
} // }
} //}
} }
#endif #endif

View File

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