mirror of
https://github.com/Alex-Rachel/TEngine.git
synced 2025-08-07 16:45:10 +00:00
8
UnityProject/Assets/Editor/ReferenceFinder.meta
Normal file
8
UnityProject/Assets/Editor/ReferenceFinder.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e11095ce128a7214a88c291ea368df9a
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
174
UnityProject/Assets/Editor/ReferenceFinder/AssetTreeView.cs
Normal file
174
UnityProject/Assets/Editor/ReferenceFinder/AssetTreeView.cs
Normal file
@@ -0,0 +1,174 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEditor.IMGUI.Controls;
|
||||
using UnityEngine;
|
||||
|
||||
namespace TEngine.Editor
|
||||
{
|
||||
internal sealed class AssetTreeView : TreeView
|
||||
{
|
||||
private const float K_ICON_WIDTH = 18f;
|
||||
private const float K_ROW_HEIGHTS = 20f;
|
||||
private readonly GUIStyle _stateGuiStyle = new GUIStyle { richText = true, alignment = TextAnchor.MiddleCenter };
|
||||
public AssetViewItem assetRoot;
|
||||
|
||||
public AssetTreeView(TreeViewState state, MultiColumnHeader multicolumnHeader) : base(state, multicolumnHeader)
|
||||
{
|
||||
rowHeight = K_ROW_HEIGHTS;
|
||||
columnIndexForTreeFoldouts = 0;
|
||||
showAlternatingRowBackgrounds = true;
|
||||
showBorder = false;
|
||||
customFoldoutYOffset = (K_ROW_HEIGHTS - EditorGUIUtility.singleLineHeight) * 0.5f;
|
||||
extraSpaceBeforeIconAndLabel = K_ICON_WIDTH;
|
||||
}
|
||||
|
||||
protected override void DoubleClickedItem(int id)
|
||||
{
|
||||
AssetViewItem item = (AssetViewItem)FindItem(id, rootItem);
|
||||
if (item != null)
|
||||
{
|
||||
Object assetObject = AssetDatabase.LoadAssetAtPath(item.data.path, typeof(Object));
|
||||
EditorUtility.FocusProjectWindow();
|
||||
Selection.activeObject = assetObject;
|
||||
EditorGUIUtility.PingObject(assetObject);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void ExpandedStateChanged() => SortExpandItem();
|
||||
|
||||
public void SortExpandItem()
|
||||
{
|
||||
if (SortHelper.CurSortType == SortType.None) return;
|
||||
IList<int> expandItemList = GetExpanded();
|
||||
foreach (int i in expandItemList)
|
||||
{
|
||||
AssetViewItem item = (AssetViewItem)FindItem(i, rootItem);
|
||||
SortHelper.SortChild(item.data);
|
||||
}
|
||||
|
||||
ResourceReferenceInfo curWindow = EditorWindow.GetWindow<ResourceReferenceInfo>();
|
||||
curWindow.needUpdateAssetTree = true;
|
||||
}
|
||||
|
||||
public static MultiColumnHeaderState CreateDefaultMultiColumnHeaderState(float treeViewWidth, bool isDepend)
|
||||
{
|
||||
List<MultiColumnHeaderState.Column> columns = new List<MultiColumnHeaderState.Column>
|
||||
{
|
||||
new MultiColumnHeaderState.Column
|
||||
{
|
||||
headerContent = new GUIContent("名称"),
|
||||
headerTextAlignment = TextAlignment.Center,
|
||||
sortedAscending = false,
|
||||
width = 200,
|
||||
minWidth = 60,
|
||||
autoResize = false,
|
||||
allowToggleVisibility = false,
|
||||
canSort = true,
|
||||
sortingArrowAlignment = TextAlignment.Center
|
||||
},
|
||||
new MultiColumnHeaderState.Column
|
||||
{
|
||||
headerContent = new GUIContent("路径"),
|
||||
headerTextAlignment = TextAlignment.Center,
|
||||
sortedAscending = false,
|
||||
width = 360,
|
||||
minWidth = 60,
|
||||
autoResize = false,
|
||||
allowToggleVisibility = false,
|
||||
canSort = true,
|
||||
sortingArrowAlignment = TextAlignment.Center
|
||||
},
|
||||
new MultiColumnHeaderState.Column
|
||||
{
|
||||
headerContent = new GUIContent("状态"),
|
||||
headerTextAlignment = TextAlignment.Center,
|
||||
sortedAscending = false,
|
||||
width = 60,
|
||||
minWidth = 60,
|
||||
autoResize = false,
|
||||
allowToggleVisibility = true,
|
||||
canSort = false
|
||||
}
|
||||
};
|
||||
if (!isDepend)
|
||||
{
|
||||
columns.Add(new MultiColumnHeaderState.Column
|
||||
{
|
||||
headerContent = new GUIContent("引用数量"),
|
||||
headerTextAlignment = TextAlignment.Center,
|
||||
sortedAscending = false,
|
||||
width = 60,
|
||||
minWidth = 60,
|
||||
autoResize = true,
|
||||
allowToggleVisibility = true,
|
||||
canSort = false
|
||||
});
|
||||
}
|
||||
|
||||
MultiColumnHeaderState state = new MultiColumnHeaderState(columns.ToArray());
|
||||
return state;
|
||||
}
|
||||
|
||||
protected override TreeViewItem BuildRoot() => assetRoot;
|
||||
|
||||
protected override void RowGUI(RowGUIArgs args)
|
||||
{
|
||||
AssetViewItem item = (AssetViewItem)args.item;
|
||||
for (int i = 0; i < args.GetNumVisibleColumns(); ++i)
|
||||
CellGUI(args.GetCellRect(i), item, (MyColumns)args.GetColumn(i), ref args);
|
||||
}
|
||||
|
||||
private void CellGUI(Rect cellRect, AssetViewItem item, MyColumns column, ref RowGUIArgs args)
|
||||
{
|
||||
CenterRectUsingSingleLineHeight(ref cellRect);
|
||||
switch (column)
|
||||
{
|
||||
case MyColumns.Name:
|
||||
Rect iconRect = cellRect;
|
||||
iconRect.x += GetContentIndent(item);
|
||||
iconRect.width = K_ICON_WIDTH;
|
||||
if (iconRect.x < cellRect.xMax)
|
||||
{
|
||||
Texture2D icon = GetIcon(item.data.path);
|
||||
if (icon != null)
|
||||
GUI.DrawTexture(iconRect, icon, ScaleMode.ScaleToFit);
|
||||
}
|
||||
|
||||
args.rowRect = cellRect;
|
||||
base.RowGUI(args);
|
||||
break;
|
||||
case MyColumns.Path:
|
||||
GUI.Label(cellRect, item.data.path);
|
||||
break;
|
||||
case MyColumns.State:
|
||||
GUI.Label(cellRect, ReferenceFinderData.GetInfoByState(item.data.state), _stateGuiStyle);
|
||||
break;
|
||||
case MyColumns.RefCount:
|
||||
GUI.Label(cellRect, ResourceReferenceInfo.Data.GetRefCount(item.data, (item.parent as AssetViewItem)?.data), _stateGuiStyle);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private Texture2D GetIcon(string path)
|
||||
{
|
||||
Object obj = AssetDatabase.LoadAssetAtPath(path, typeof(Object));
|
||||
if (obj)
|
||||
{
|
||||
Texture2D icon = AssetPreview.GetMiniThumbnail(obj);
|
||||
if (!icon)
|
||||
icon = AssetPreview.GetMiniTypeThumbnail(obj.GetType());
|
||||
return icon;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private enum MyColumns
|
||||
{
|
||||
Name,
|
||||
Path,
|
||||
State,
|
||||
RefCount
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dd079ed03e211ca4698770fc925dcf0a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,9 @@
|
||||
using UnityEditor.IMGUI.Controls;
|
||||
|
||||
namespace TEngine.Editor
|
||||
{
|
||||
internal sealed class AssetViewItem : TreeViewItem
|
||||
{
|
||||
public ReferenceFinderData.AssetDescription data;
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 62d7d07cebb3f9b4998845a11799e12c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
34
UnityProject/Assets/Editor/ReferenceFinder/ClickColumn.cs
Normal file
34
UnityProject/Assets/Editor/ReferenceFinder/ClickColumn.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEditor.IMGUI.Controls;
|
||||
|
||||
namespace TEngine.Editor
|
||||
{
|
||||
internal sealed class ClickColumn : MultiColumnHeader
|
||||
{
|
||||
public delegate void SortInColumn();
|
||||
|
||||
public static Dictionary<int, SortInColumn> SortWithIndex = new Dictionary<int, SortInColumn>
|
||||
{
|
||||
{ 0, SortByName },
|
||||
{ 1, SortByPath }
|
||||
};
|
||||
|
||||
public ClickColumn(MultiColumnHeaderState state) : base(state) => canSort = true;
|
||||
|
||||
protected override void ColumnHeaderClicked(MultiColumnHeaderState.Column column, int columnIndex)
|
||||
{
|
||||
base.ColumnHeaderClicked(column, columnIndex);
|
||||
if (SortWithIndex.ContainsKey(columnIndex))
|
||||
{
|
||||
SortWithIndex[columnIndex].Invoke();
|
||||
ResourceReferenceInfo curWindow = EditorWindow.GetWindow<ResourceReferenceInfo>();
|
||||
curWindow.mAssetTreeView.SortExpandItem();
|
||||
}
|
||||
}
|
||||
|
||||
public static void SortByName() => SortHelper.SortByName();
|
||||
|
||||
public static void SortByPath() => SortHelper.SortByPath();
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4047444d841109d46b15817bbe887281
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,29 @@
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace TEngine.Editor
|
||||
{
|
||||
internal sealed class DragAreaGetObject
|
||||
{
|
||||
public static Object[] GetObjects(string meg = null)
|
||||
{
|
||||
Event aEvent = Event.current;
|
||||
GUI.contentColor = Color.white;
|
||||
if (aEvent.type is EventType.DragUpdated or EventType.DragPerform)
|
||||
{
|
||||
DragAndDrop.visualMode = DragAndDropVisualMode.Copy;
|
||||
bool needReturn = false;
|
||||
if (aEvent.type == EventType.DragPerform)
|
||||
{
|
||||
DragAndDrop.AcceptDrag();
|
||||
needReturn = true;
|
||||
}
|
||||
|
||||
Event.current.Use();
|
||||
if (needReturn) return DragAndDrop.objectReferences;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 59773aa6a03462c488a3e18ea3de8660
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
9
UnityProject/Assets/Editor/ReferenceFinder/ListInfo.cs
Normal file
9
UnityProject/Assets/Editor/ReferenceFinder/ListInfo.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
namespace TEngine.Editor
|
||||
{
|
||||
internal sealed class ListInfo
|
||||
{
|
||||
public int Count;
|
||||
public string Name;
|
||||
public string Type;
|
||||
}
|
||||
}
|
11
UnityProject/Assets/Editor/ReferenceFinder/ListInfo.cs.meta
Normal file
11
UnityProject/Assets/Editor/ReferenceFinder/ListInfo.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 36df700a4102b0c4db5f7ec3c485cf0c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,417 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Runtime.Serialization.Formatters.Binary;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
// ReSharper disable InconsistentNaming
|
||||
|
||||
namespace TEngine.Editor
|
||||
{
|
||||
internal sealed class ReferenceFinderData
|
||||
{
|
||||
public enum AssetState : byte
|
||||
{
|
||||
Normal,
|
||||
Changed,
|
||||
Missing,
|
||||
Invalid
|
||||
}
|
||||
|
||||
private const string CachePath = "Library/ReferenceFinderCache";
|
||||
public const int MinThreadCount = 8;
|
||||
private const int SingleThreadReadCount = 100;
|
||||
private static readonly int ThreadCount = Math.Max(MinThreadCount, Environment.ProcessorCount);
|
||||
private static string _basePath;
|
||||
|
||||
private static readonly HashSet<string> FileExtension = new HashSet<string>
|
||||
{
|
||||
".prefab",
|
||||
".unity",
|
||||
".mat",
|
||||
".asset",
|
||||
".anim",
|
||||
".controller"
|
||||
};
|
||||
|
||||
private static readonly Regex GuidRegex = new Regex("guid: ([a-z0-9]{32})", RegexOptions.Singleline | RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||
private readonly Dictionary<(AssetDescription, AssetDescription), int> _dictCache = new Dictionary<(AssetDescription, AssetDescription), int>();
|
||||
private readonly List<Dictionary<string, AssetDescription>> _threadAssetDict = new List<Dictionary<string, AssetDescription>>();
|
||||
private readonly List<Thread> _threadList = new List<Thread>();
|
||||
private int _curReadAssetCount;
|
||||
private int _totalCount;
|
||||
public string[] allAssets;
|
||||
public Dictionary<string, AssetDescription> assetDict = new Dictionary<string, AssetDescription>();
|
||||
|
||||
public void CollectDependenciesInfo()
|
||||
{
|
||||
try
|
||||
{
|
||||
_basePath = Application.dataPath.Replace("/Assets", "");
|
||||
ReadFromCache();
|
||||
allAssets = AssetDatabase.GetAllAssetPaths();
|
||||
_totalCount = allAssets.Length;
|
||||
_threadList.Clear();
|
||||
_curReadAssetCount = 0;
|
||||
foreach (Dictionary<string, AssetDescription> i in _threadAssetDict)
|
||||
i.Clear();
|
||||
_threadAssetDict.Clear();
|
||||
for (int i = 0; i < ThreadCount; i++) _threadAssetDict.Add(new Dictionary<string, AssetDescription>());
|
||||
bool allThreadFinish = false;
|
||||
for (int i = 0; i < ThreadCount; i++)
|
||||
{
|
||||
ThreadStart method = ReadAssetInfo;
|
||||
Thread readThread = new Thread(method);
|
||||
_threadList.Add(readThread);
|
||||
readThread.Start();
|
||||
}
|
||||
|
||||
while (!allThreadFinish)
|
||||
{
|
||||
if (_curReadAssetCount % 500 == 0 &&
|
||||
EditorUtility.DisplayCancelableProgressBar("Updating", $"Handle {_curReadAssetCount}", (float)_curReadAssetCount / _totalCount))
|
||||
{
|
||||
EditorUtility.ClearProgressBar();
|
||||
foreach (Thread i in _threadList)
|
||||
i.Abort();
|
||||
return;
|
||||
}
|
||||
|
||||
allThreadFinish = true;
|
||||
foreach (Thread i in _threadList)
|
||||
{
|
||||
if (i.IsAlive)
|
||||
{
|
||||
allThreadFinish = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (Dictionary<string, AssetDescription> dict in _threadAssetDict)
|
||||
{
|
||||
foreach (KeyValuePair<string, AssetDescription> j in dict)
|
||||
assetDict[j.Key] = j.Value;
|
||||
}
|
||||
|
||||
EditorUtility.DisplayCancelableProgressBar("Updating", "Write cache", 1f);
|
||||
WriteToChache();
|
||||
EditorUtility.DisplayCancelableProgressBar("Updating", "Generate reference data", 1f);
|
||||
UpdateResourceReferenceInfo();
|
||||
EditorUtility.ClearProgressBar();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogError(e);
|
||||
EditorUtility.ClearProgressBar();
|
||||
}
|
||||
}
|
||||
|
||||
public void ReadAssetInfo()
|
||||
{
|
||||
int index = Thread.CurrentThread.ManagedThreadId % ThreadCount;
|
||||
int intervalLength = _totalCount / ThreadCount;
|
||||
int start = intervalLength * index;
|
||||
int end = start + intervalLength;
|
||||
if (_totalCount - end < intervalLength)
|
||||
end = _totalCount;
|
||||
int readAssetCount = 0;
|
||||
for (int i = start; i < end; i++)
|
||||
{
|
||||
if (readAssetCount % SingleThreadReadCount == 0)
|
||||
{
|
||||
_curReadAssetCount += readAssetCount;
|
||||
readAssetCount = 0;
|
||||
}
|
||||
|
||||
GetAsset(_basePath, allAssets[i]);
|
||||
readAssetCount++;
|
||||
}
|
||||
}
|
||||
|
||||
public void GetAsset(string dataPath, string assetPath)
|
||||
{
|
||||
string extLowerStr = Path.GetExtension(assetPath).ToLower();
|
||||
bool needReadFile = FileExtension.Contains(extLowerStr);
|
||||
string fileName = $"{dataPath}/{assetPath}";
|
||||
string metaFile = $"{dataPath}/{assetPath}.meta";
|
||||
if (File.Exists(fileName) && File.Exists(metaFile))
|
||||
{
|
||||
string metaText = File.ReadAllText(metaFile, Encoding.UTF8);
|
||||
MatchCollection matchRs = GuidRegex.Matches(metaText);
|
||||
string selfGuid = matchRs[0].Groups[1].Value.ToLower();
|
||||
string lastModifyTime = File.GetLastWriteTime(fileName).ToString(CultureInfo.InvariantCulture);
|
||||
MatchCollection guids = null;
|
||||
List<string> depend = new List<string>();
|
||||
if (needReadFile)
|
||||
{
|
||||
string fileStr = File.ReadAllText(fileName, Encoding.UTF8);
|
||||
guids = GuidRegex.Matches(fileStr);
|
||||
}
|
||||
|
||||
int curListIndex = Thread.CurrentThread.ManagedThreadId % ThreadCount;
|
||||
Dictionary<string, AssetDescription> curDict = _threadAssetDict[curListIndex];
|
||||
if (!curDict.ContainsKey(selfGuid) || curDict[selfGuid].assetDependencyHashString != lastModifyTime)
|
||||
{
|
||||
if (guids != null)
|
||||
{
|
||||
for (int index = 0; index < guids.Count; ++index)
|
||||
{
|
||||
Match i = guids[index];
|
||||
depend.Add(i.Groups[1].Value.ToLower());
|
||||
}
|
||||
}
|
||||
|
||||
AssetDescription ad = new AssetDescription
|
||||
{
|
||||
name = Path.GetFileNameWithoutExtension(assetPath),
|
||||
path = assetPath,
|
||||
assetDependencyHashString = lastModifyTime,
|
||||
dependencies = depend
|
||||
};
|
||||
|
||||
if (_threadAssetDict[curListIndex].ContainsKey(selfGuid))
|
||||
_threadAssetDict[curListIndex][selfGuid] = ad;
|
||||
else
|
||||
_threadAssetDict[curListIndex].Add(selfGuid, ad);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateResourceReferenceInfo()
|
||||
{
|
||||
foreach (KeyValuePair<string, AssetDescription> asset in assetDict)
|
||||
{
|
||||
foreach (string assetGuid in asset.Value.dependencies)
|
||||
{
|
||||
if (assetDict.ContainsKey(assetGuid))
|
||||
assetDict[assetGuid].references.Add(asset.Key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool ReadFromCache()
|
||||
{
|
||||
assetDict.Clear();
|
||||
ClearCache();
|
||||
if (File.Exists(CachePath))
|
||||
{
|
||||
List<string> serializedGuid;
|
||||
List<string> serializedDependencyHash;
|
||||
List<int[]> serializedDenpendencies;
|
||||
using (FileStream fs = File.OpenRead(CachePath))
|
||||
{
|
||||
BinaryFormatter bf = new BinaryFormatter();
|
||||
if (EditorUtility.DisplayCancelableProgressBar("Import Cache", "Reading Cache", 0))
|
||||
{
|
||||
EditorUtility.ClearProgressBar();
|
||||
return false;
|
||||
}
|
||||
|
||||
serializedGuid = (List<string>)bf.Deserialize(fs);
|
||||
serializedDependencyHash = (List<string>)bf.Deserialize(fs);
|
||||
serializedDenpendencies = (List<int[]>)bf.Deserialize(fs);
|
||||
EditorUtility.ClearProgressBar();
|
||||
}
|
||||
|
||||
for (int i = 0; i < serializedGuid.Count; ++i)
|
||||
{
|
||||
string path = AssetDatabase.GUIDToAssetPath(serializedGuid[i]);
|
||||
if (string.IsNullOrEmpty(path))
|
||||
{
|
||||
AssetDescription ad = new AssetDescription
|
||||
{
|
||||
name = Path.GetFileNameWithoutExtension(path),
|
||||
path = path,
|
||||
assetDependencyHashString = serializedDependencyHash[i]
|
||||
};
|
||||
assetDict.Add(serializedGuid[i], ad);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < serializedGuid.Count; ++i)
|
||||
{
|
||||
string guid = serializedGuid[i];
|
||||
if (assetDict.ContainsKey(guid))
|
||||
{
|
||||
List<string> guids = new List<string>();
|
||||
foreach (int index in serializedDenpendencies[i])
|
||||
{
|
||||
string g = serializedGuid[index];
|
||||
if (assetDict.ContainsKey(g))
|
||||
guids.Add(g);
|
||||
}
|
||||
|
||||
assetDict[guid].dependencies = guids;
|
||||
}
|
||||
}
|
||||
|
||||
UpdateResourceReferenceInfo();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void WriteToChache()
|
||||
{
|
||||
if (File.Exists(CachePath))
|
||||
File.Delete(CachePath);
|
||||
List<string> serializedGuid = new List<string>();
|
||||
List<string> serializedDependencyHash = new List<string>();
|
||||
List<int[]> serializedDenpendencies = new List<int[]>();
|
||||
Dictionary<string, int> guidIndex = new Dictionary<string, int>();
|
||||
using FileStream fs = File.OpenWrite(CachePath);
|
||||
foreach (KeyValuePair<string, AssetDescription> pair in assetDict)
|
||||
{
|
||||
guidIndex.Add(pair.Key, guidIndex.Count);
|
||||
serializedGuid.Add(pair.Key);
|
||||
serializedDependencyHash.Add(pair.Value.assetDependencyHashString);
|
||||
}
|
||||
|
||||
foreach (string guid in serializedGuid)
|
||||
{
|
||||
List<int> res = new List<int>();
|
||||
foreach (string i in assetDict[guid].dependencies)
|
||||
{
|
||||
if (guidIndex.TryGetValue(i, out var value))
|
||||
res.Add(value);
|
||||
}
|
||||
|
||||
int[] indexes = res.ToArray();
|
||||
serializedDenpendencies.Add(indexes);
|
||||
}
|
||||
|
||||
BinaryFormatter bf = new BinaryFormatter();
|
||||
bf.Serialize(fs, serializedGuid);
|
||||
bf.Serialize(fs, serializedDependencyHash);
|
||||
bf.Serialize(fs, serializedDenpendencies);
|
||||
}
|
||||
|
||||
public void UpdateAssetState(string guid)
|
||||
{
|
||||
if (assetDict.TryGetValue(guid, out AssetDescription ad) && ad.state != AssetState.Invalid)
|
||||
{
|
||||
if (File.Exists(ad.path))
|
||||
ad.state = ad.assetDependencyHashString != File.GetLastWriteTime(ad.path).ToString(CultureInfo.InvariantCulture) ? AssetState.Changed : AssetState.Normal;
|
||||
else
|
||||
ad.state = AssetState.Missing;
|
||||
}
|
||||
else if (!assetDict.TryGetValue(guid, out ad))
|
||||
{
|
||||
string path = AssetDatabase.GUIDToAssetPath(guid);
|
||||
ad = new AssetDescription
|
||||
{
|
||||
name = Path.GetFileNameWithoutExtension(path),
|
||||
path = path,
|
||||
state = AssetState.Invalid
|
||||
};
|
||||
assetDict.Add(guid, ad);
|
||||
}
|
||||
}
|
||||
|
||||
public static string GetInfoByState(AssetState state)
|
||||
{
|
||||
if (state == AssetState.Changed)
|
||||
return "<color=red>缓存不匹配</color>";
|
||||
if (state == AssetState.Missing)
|
||||
return "<color=red>缓存丢失</color>";
|
||||
if (state == AssetState.Invalid)
|
||||
return "<color=yellow>缓存无效</color>";
|
||||
return "<color=green>缓存正常</color>";
|
||||
}
|
||||
|
||||
private int GetRefCount(string assetGUID, AssetDescription desc, List<string> guidStack)
|
||||
{
|
||||
if (guidStack.Contains(assetGUID))
|
||||
{
|
||||
Debug.Log("有循环引用, 计数可能不准确");
|
||||
return 0;
|
||||
}
|
||||
|
||||
guidStack.Add(assetGUID);
|
||||
int total = 0;
|
||||
if (assetDict.TryGetValue(assetGUID, out AssetDescription value))
|
||||
{
|
||||
if (value.references.Count > 0)
|
||||
{
|
||||
Dictionary<string, int> cachedRefCount = new Dictionary<string, int>();
|
||||
foreach (string refs in value.references)
|
||||
{
|
||||
if (!cachedRefCount.ContainsKey(refs))
|
||||
{
|
||||
int refCount = GetRefCount(refs, value, guidStack);
|
||||
cachedRefCount[refs] = refCount;
|
||||
total += refCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
total = 0;
|
||||
if (desc != null)
|
||||
{
|
||||
string guid = AssetDatabase.AssetPathToGUID(desc.path);
|
||||
foreach (string deps in value.dependencies)
|
||||
{
|
||||
if (guid == deps)
|
||||
total++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
guidStack.RemoveAt(guidStack.Count - 1);
|
||||
return total;
|
||||
}
|
||||
|
||||
public void ClearCache() => _dictCache.Clear();
|
||||
|
||||
public string GetRefCount(AssetDescription desc, AssetDescription parentDesc)
|
||||
{
|
||||
if (_dictCache.TryGetValue((desc, parentDesc), out int total))
|
||||
return total.ToString();
|
||||
string rootGUID = AssetDatabase.AssetPathToGUID(desc.path);
|
||||
List<string> guidInStack = new List<string> { rootGUID };
|
||||
Dictionary<string, int> cachedRefCount = new Dictionary<string, int>();
|
||||
foreach (string refs in desc.references)
|
||||
{
|
||||
if (!cachedRefCount.ContainsKey(refs))
|
||||
{
|
||||
int refCount = GetRefCount(refs, desc, guidInStack);
|
||||
cachedRefCount[refs] = refCount;
|
||||
total += refCount;
|
||||
}
|
||||
}
|
||||
|
||||
if (desc.references.Count == 0 && parentDesc != null)
|
||||
{
|
||||
string guid = AssetDatabase.AssetPathToGUID(desc.path);
|
||||
foreach (string refs in parentDesc.references)
|
||||
{
|
||||
if (refs == guid)
|
||||
total++;
|
||||
}
|
||||
}
|
||||
|
||||
guidInStack.RemoveAt(guidInStack.Count - 1);
|
||||
_dictCache.Add((desc, parentDesc), total);
|
||||
return total.ToString();
|
||||
}
|
||||
|
||||
internal sealed class AssetDescription
|
||||
{
|
||||
public string assetDependencyHashString;
|
||||
public List<string> dependencies = new List<string>();
|
||||
public string name = "";
|
||||
public string path = "";
|
||||
public List<string> references = new List<string>();
|
||||
public AssetState state = AssetState.Normal;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b1fd14799f035fc4b817d8e78253548e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,307 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using UnityEditor;
|
||||
using UnityEditor.IMGUI.Controls;
|
||||
using UnityEngine;
|
||||
|
||||
namespace TEngine.Editor
|
||||
{
|
||||
internal sealed class ResourceReferenceInfo : EditorWindow
|
||||
{
|
||||
private const string IS_DEPEND_PREF_KEY = "ReferenceFinderData_IsDepend";
|
||||
public static readonly ReferenceFinderData Data = new ReferenceFinderData();
|
||||
private static bool _initializedData;
|
||||
|
||||
[SerializeField]
|
||||
private TreeViewState _treeViewState;
|
||||
|
||||
public bool needUpdateAssetTree;
|
||||
public bool needUpdateState = true;
|
||||
public List<string> selectedAssetGuid = new List<string>();
|
||||
private readonly HashSet<string> _brotherAssetIsAdd = new HashSet<string>();
|
||||
private readonly HashSet<string> _parentAssetIsAdd = new HashSet<string>();
|
||||
private readonly HashSet<string> _updatedAssetSet = new HashSet<string>();
|
||||
private Dictionary<string, ListInfo> _artInfo = new Dictionary<string, ListInfo>();
|
||||
private bool _initializedGUIStyle;
|
||||
private bool _isDepend;
|
||||
private GUIStyle _toolbarButtonGUIStyle;
|
||||
private GUIStyle _toolbarGUIStyle;
|
||||
public AssetTreeView mAssetTreeView;
|
||||
|
||||
private void OnEnable() => _isDepend = PlayerPrefs.GetInt(IS_DEPEND_PREF_KEY, 0) == 1;
|
||||
|
||||
private void OnGUI()
|
||||
{
|
||||
UpdateDragAssets();
|
||||
InitGUIStyleIfNeeded();
|
||||
DrawOptionBar();
|
||||
UpdateAssetTree();
|
||||
mAssetTreeView?.OnGUI(new Rect(0, _toolbarGUIStyle.fixedHeight, position.width, position.height - _toolbarGUIStyle.fixedHeight));
|
||||
}
|
||||
|
||||
[MenuItem("TEngine/查找资产引用", false, 100)]
|
||||
public static void FindRef()
|
||||
{
|
||||
InitDataIfNeeded();
|
||||
OpenWindow();
|
||||
ResourceReferenceInfo window = GetWindow<ResourceReferenceInfo>();
|
||||
window.UpdateSelectedAssets();
|
||||
}
|
||||
|
||||
private static void OpenWindow()
|
||||
{
|
||||
ResourceReferenceInfo window = GetWindow<ResourceReferenceInfo>();
|
||||
window.wantsMouseMove = false;
|
||||
window.titleContent = new GUIContent("查找资产引用");
|
||||
window.Show();
|
||||
window.Focus();
|
||||
SortHelper.Init();
|
||||
}
|
||||
|
||||
private static void InitDataIfNeeded()
|
||||
{
|
||||
if (!_initializedData)
|
||||
{
|
||||
if (!Data.ReadFromCache())
|
||||
Data.CollectDependenciesInfo();
|
||||
_initializedData = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void InitGUIStyleIfNeeded()
|
||||
{
|
||||
if (!_initializedGUIStyle)
|
||||
{
|
||||
_toolbarButtonGUIStyle = new GUIStyle("ToolbarButton");
|
||||
_toolbarGUIStyle = new GUIStyle("Toolbar");
|
||||
_initializedGUIStyle = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateSelectedAssets()
|
||||
{
|
||||
_artInfo = new Dictionary<string, ListInfo>();
|
||||
selectedAssetGuid.Clear();
|
||||
foreach (Object obj in Selection.objects)
|
||||
{
|
||||
string path = AssetDatabase.GetAssetPath(obj);
|
||||
if (Directory.Exists(path))
|
||||
{
|
||||
string[] folder = { path };
|
||||
string[] guids = AssetDatabase.FindAssets(null, folder);
|
||||
foreach (string guid in guids)
|
||||
{
|
||||
if (!selectedAssetGuid.Contains(guid) && !Directory.Exists(AssetDatabase.GUIDToAssetPath(guid)))
|
||||
selectedAssetGuid.Add(guid);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
string guid = AssetDatabase.AssetPathToGUID(path);
|
||||
selectedAssetGuid.Add(guid);
|
||||
}
|
||||
}
|
||||
|
||||
needUpdateAssetTree = true;
|
||||
}
|
||||
|
||||
private void UpdateDragAssets()
|
||||
{
|
||||
if (mouseOverWindow)
|
||||
{
|
||||
Object[] tempObj = DragAreaGetObject.GetObjects();
|
||||
if (tempObj != null)
|
||||
{
|
||||
InitDataIfNeeded();
|
||||
selectedAssetGuid.Clear();
|
||||
foreach (Object obj in tempObj)
|
||||
{
|
||||
string path = AssetDatabase.GetAssetPath(obj);
|
||||
if (Directory.Exists(path))
|
||||
{
|
||||
string[] folder = { path };
|
||||
string[] guids = AssetDatabase.FindAssets(null, folder);
|
||||
foreach (string guid in guids)
|
||||
{
|
||||
if (!selectedAssetGuid.Contains(guid) && !Directory.Exists(AssetDatabase.GUIDToAssetPath(guid)))
|
||||
selectedAssetGuid.Add(guid);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
string guid = AssetDatabase.AssetPathToGUID(path);
|
||||
selectedAssetGuid.Add(guid);
|
||||
}
|
||||
}
|
||||
|
||||
needUpdateAssetTree = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateAssetTree()
|
||||
{
|
||||
if (needUpdateAssetTree && selectedAssetGuid.Count != 0)
|
||||
{
|
||||
AssetViewItem root = SelectedAssetGuidToRootItem(selectedAssetGuid);
|
||||
if (mAssetTreeView == null)
|
||||
{
|
||||
if (_treeViewState == null)
|
||||
_treeViewState = new TreeViewState();
|
||||
MultiColumnHeaderState headerState = AssetTreeView.CreateDefaultMultiColumnHeaderState(position.width, _isDepend);
|
||||
ClickColumn multiColumnHeader = new ClickColumn(headerState);
|
||||
mAssetTreeView = new AssetTreeView(_treeViewState, multiColumnHeader);
|
||||
}
|
||||
else
|
||||
{
|
||||
MultiColumnHeaderState headerState = AssetTreeView.CreateDefaultMultiColumnHeaderState(position.width, _isDepend);
|
||||
ClickColumn multiColumnHeader = new ClickColumn(headerState);
|
||||
mAssetTreeView.multiColumnHeader = multiColumnHeader;
|
||||
}
|
||||
|
||||
mAssetTreeView.assetRoot = root;
|
||||
mAssetTreeView.Reload();
|
||||
needUpdateAssetTree = false;
|
||||
int totalPrefab = 0;
|
||||
int totalMat = 0;
|
||||
string prefabName = "";
|
||||
string matName = "";
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (_artInfo.Count > 0)
|
||||
{
|
||||
foreach (KeyValuePair<string, ListInfo> kv in _artInfo)
|
||||
{
|
||||
if (kv.Value.Type == "prefab")
|
||||
{
|
||||
totalPrefab += kv.Value.Count;
|
||||
prefabName += kv.Value.Name + "<--->";
|
||||
}
|
||||
|
||||
if (kv.Value.Type == "mat")
|
||||
{
|
||||
totalMat += kv.Value.Count;
|
||||
matName += kv.Value.Name + "<--->";
|
||||
}
|
||||
|
||||
string tempInfo = $"name <color=green>[{kv.Key}]</color>, type: <color=orange>[{kv.Value.Type}]</color>, count: <color=red>[{kv.Value.Count}]</color>";
|
||||
sb.AppendLine(tempInfo);
|
||||
}
|
||||
}
|
||||
|
||||
if (totalPrefab > 0)
|
||||
sb.Insert(0, $"预制体总数 <color=red>[{totalPrefab}]</color> 预制体详情 <color=green>[{prefabName}]</color> \r\n");
|
||||
if (totalMat > 0)
|
||||
sb.Insert(0, $"材质总数 <color=red>[{totalMat}]</color> 材质详情 <color=green>[{matName}]</color> \r\n");
|
||||
string str = sb.ToString();
|
||||
if (!string.IsNullOrEmpty(str))
|
||||
Debug.Log(str);
|
||||
}
|
||||
}
|
||||
|
||||
public void DrawOptionBar()
|
||||
{
|
||||
EditorGUILayout.BeginHorizontal(_toolbarGUIStyle);
|
||||
if (GUILayout.Button("点击更新本地缓存", _toolbarButtonGUIStyle))
|
||||
{
|
||||
Data.CollectDependenciesInfo();
|
||||
needUpdateAssetTree = true;
|
||||
GUIUtility.ExitGUI();
|
||||
}
|
||||
|
||||
bool preIsDepend = _isDepend;
|
||||
_isDepend = GUILayout.Toggle(_isDepend, _isDepend ? "依赖模式" : "引用模式", _toolbarButtonGUIStyle, GUILayout.Width(100));
|
||||
if (preIsDepend != _isDepend)
|
||||
OnModelSelect();
|
||||
if (GUILayout.Button("展开", _toolbarButtonGUIStyle))
|
||||
mAssetTreeView?.ExpandAll();
|
||||
if (GUILayout.Button("折叠", _toolbarButtonGUIStyle))
|
||||
mAssetTreeView?.CollapseAll();
|
||||
EditorGUILayout.EndHorizontal();
|
||||
}
|
||||
|
||||
private void OnModelSelect()
|
||||
{
|
||||
needUpdateAssetTree = true;
|
||||
PlayerPrefs.SetInt(IS_DEPEND_PREF_KEY, _isDepend ? 1 : 0);
|
||||
UpdateAssetTree();
|
||||
}
|
||||
|
||||
private AssetViewItem SelectedAssetGuidToRootItem(List<string> inputSelectedAssetGuid)
|
||||
{
|
||||
_updatedAssetSet.Clear();
|
||||
_parentAssetIsAdd.Clear();
|
||||
_brotherAssetIsAdd.Clear();
|
||||
int elementCount = 0;
|
||||
AssetViewItem root = new AssetViewItem { id = elementCount, depth = -1, displayName = "Root", data = null };
|
||||
const int depth = 0;
|
||||
foreach (string childGuid in inputSelectedAssetGuid)
|
||||
{
|
||||
AssetViewItem rs = CreateTree(childGuid, ref elementCount, depth);
|
||||
root.AddChild(rs);
|
||||
}
|
||||
|
||||
_updatedAssetSet.Clear();
|
||||
return root;
|
||||
}
|
||||
|
||||
private AssetViewItem CreateTree(string guid, ref int elementCount, int depth)
|
||||
{
|
||||
if (_parentAssetIsAdd.Contains(guid))
|
||||
return null;
|
||||
if (needUpdateState && !_updatedAssetSet.Contains(guid))
|
||||
{
|
||||
Data.UpdateAssetState(guid);
|
||||
_updatedAssetSet.Add(guid);
|
||||
}
|
||||
|
||||
++elementCount;
|
||||
ReferenceFinderData.AssetDescription referenceData = Data.assetDict[guid];
|
||||
AssetViewItem root = new AssetViewItem { id = elementCount, displayName = referenceData.name, data = referenceData, depth = depth };
|
||||
List<string> childGuids = _isDepend ? referenceData.dependencies : referenceData.references;
|
||||
_parentAssetIsAdd.Add(guid);
|
||||
foreach (string childGuid in childGuids)
|
||||
{
|
||||
if (_brotherAssetIsAdd.Contains(childGuid)) continue;
|
||||
ListInfo listInfo = new ListInfo();
|
||||
if (AssetDatabase.GUIDToAssetPath(childGuid).EndsWith(".mat") && depth < 2)
|
||||
{
|
||||
listInfo.Type = "mat";
|
||||
listInfo.Count = 1;
|
||||
listInfo.Name = Path.GetFileName(AssetDatabase.GUIDToAssetPath(childGuid));
|
||||
if (!_artInfo.TryAdd(root.displayName, listInfo))
|
||||
{
|
||||
_artInfo[root.displayName].Count += 1;
|
||||
_artInfo[root.displayName].Name += "<<==>>" + listInfo.Name;
|
||||
}
|
||||
}
|
||||
|
||||
if (AssetDatabase.GUIDToAssetPath(childGuid).EndsWith(".prefab") && !AssetDatabase.GUIDToAssetPath(childGuid).Contains("_gen_render") && depth < 2)
|
||||
{
|
||||
listInfo.Type = "prefab";
|
||||
listInfo.Count = 1;
|
||||
listInfo.Name = Path.GetFileName(AssetDatabase.GUIDToAssetPath(childGuid));
|
||||
if (!_artInfo.TryAdd(root.displayName, listInfo))
|
||||
{
|
||||
_artInfo[root.displayName].Count += 1;
|
||||
_artInfo[root.displayName].Name += "<<==>>" + listInfo.Name;
|
||||
}
|
||||
}
|
||||
|
||||
_brotherAssetIsAdd.Add(childGuid);
|
||||
AssetViewItem rs = CreateTree(childGuid, ref elementCount, depth + 1);
|
||||
if (rs != null)
|
||||
root.AddChild(rs);
|
||||
}
|
||||
|
||||
foreach (string childGuid in childGuids)
|
||||
{
|
||||
if (_brotherAssetIsAdd.Contains(childGuid))
|
||||
_brotherAssetIsAdd.Remove(childGuid);
|
||||
}
|
||||
|
||||
_parentAssetIsAdd.Remove(guid);
|
||||
return root;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 40f81b3f7b523ee46ab72ec79c7a61af
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
33
UnityProject/Assets/Editor/ReferenceFinder/SortConfig.cs
Normal file
33
UnityProject/Assets/Editor/ReferenceFinder/SortConfig.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace TEngine.Editor
|
||||
{
|
||||
internal sealed class SortConfig
|
||||
{
|
||||
public static readonly Dictionary<SortType, SortType> SortTypeChangeByNameHandler = new Dictionary<SortType, SortType>
|
||||
{
|
||||
{ SortType.None, SortType.AscByName },
|
||||
{ SortType.AscByName, SortType.DescByName },
|
||||
{ SortType.DescByName, SortType.AscByName }
|
||||
};
|
||||
|
||||
public static readonly Dictionary<SortType, SortType> SortTypeChangeByPathHandler = new Dictionary<SortType, SortType>
|
||||
{
|
||||
{ SortType.None, SortType.AscByPath },
|
||||
{ SortType.AscByPath, SortType.DescByPath },
|
||||
{ SortType.DescByPath, SortType.AscByPath }
|
||||
};
|
||||
|
||||
public static readonly Dictionary<SortType, short> SortTypeGroup = new Dictionary<SortType, short>
|
||||
{
|
||||
{ SortType.None, 0 },
|
||||
{ SortType.AscByPath, 1 },
|
||||
{ SortType.DescByPath, 1 },
|
||||
{ SortType.AscByName, 2 },
|
||||
{ SortType.DescByName, 2 }
|
||||
};
|
||||
|
||||
public const short TYPE_BY_NAME_GROUP = 2;
|
||||
public const short TYPE_BY_PATH_GROUP = 1;
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2d7b92d1055376e4dbabd77de5a0e728
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
111
UnityProject/Assets/Editor/ReferenceFinder/SortHelper.cs
Normal file
111
UnityProject/Assets/Editor/ReferenceFinder/SortHelper.cs
Normal file
@@ -0,0 +1,111 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace TEngine.Editor
|
||||
{
|
||||
internal sealed class SortHelper
|
||||
{
|
||||
public delegate int SortCompare(string lString, string rString);
|
||||
|
||||
public static readonly HashSet<string> SortedGuid = new HashSet<string>();
|
||||
public static readonly Dictionary<string, SortType> SortedAsset = new Dictionary<string, SortType>();
|
||||
public static SortType CurSortType = SortType.None;
|
||||
public static SortType PathType = SortType.None;
|
||||
public static SortType NameType = SortType.None;
|
||||
|
||||
public static readonly Dictionary<SortType, SortCompare> CompareFunction = new Dictionary<SortType, SortCompare>
|
||||
{
|
||||
{ SortType.AscByPath, CompareWithPath },
|
||||
{ SortType.DescByPath, CompareWithPathDesc },
|
||||
{ SortType.AscByName, CompareWithName },
|
||||
{ SortType.DescByName, CompareWithNameDesc }
|
||||
};
|
||||
|
||||
public static void Init()
|
||||
{
|
||||
SortedGuid.Clear();
|
||||
SortedAsset.Clear();
|
||||
}
|
||||
|
||||
public static void ChangeSortType(short sortGroup, Dictionary<SortType, SortType> handler, ref SortType recoverType)
|
||||
{
|
||||
if (SortConfig.SortTypeGroup[CurSortType] == sortGroup)
|
||||
{
|
||||
CurSortType = handler[CurSortType];
|
||||
}
|
||||
else
|
||||
{
|
||||
CurSortType = recoverType;
|
||||
if (CurSortType == SortType.None) CurSortType = handler[CurSortType];
|
||||
}
|
||||
|
||||
recoverType = CurSortType;
|
||||
}
|
||||
|
||||
public static void SortByName() => ChangeSortType(SortConfig.TYPE_BY_NAME_GROUP, SortConfig.SortTypeChangeByNameHandler, ref NameType);
|
||||
|
||||
public static void SortByPath() => ChangeSortType(SortConfig.TYPE_BY_PATH_GROUP, SortConfig.SortTypeChangeByPathHandler, ref PathType);
|
||||
|
||||
public static void SortChild(ReferenceFinderData.AssetDescription data)
|
||||
{
|
||||
if (data == null) return;
|
||||
if (SortedAsset.ContainsKey(data.path))
|
||||
{
|
||||
if (SortedAsset[data.path] == CurSortType) return;
|
||||
SortType oldSortType = SortedAsset[data.path];
|
||||
if (SortConfig.SortTypeGroup[oldSortType] == SortConfig.SortTypeGroup[CurSortType])
|
||||
{
|
||||
FastSort(data.dependencies);
|
||||
FastSort(data.references);
|
||||
}
|
||||
else
|
||||
{
|
||||
NormalSort(data.dependencies);
|
||||
NormalSort(data.references);
|
||||
}
|
||||
|
||||
SortedAsset[data.path] = CurSortType;
|
||||
}
|
||||
else
|
||||
{
|
||||
NormalSort(data.dependencies);
|
||||
NormalSort(data.references);
|
||||
SortedAsset.Add(data.path, CurSortType);
|
||||
}
|
||||
}
|
||||
|
||||
public static void NormalSort(List<string> strList)
|
||||
{
|
||||
SortCompare curCompare = CompareFunction[CurSortType];
|
||||
strList.Sort((l, r) => curCompare(l, r));
|
||||
}
|
||||
|
||||
public static void FastSort(List<string> strList)
|
||||
{
|
||||
int i = 0;
|
||||
int j = strList.Count - 1;
|
||||
while (i < j)
|
||||
{
|
||||
(strList[i], strList[j]) = (strList[j], strList[i]);
|
||||
i++;
|
||||
j--;
|
||||
}
|
||||
}
|
||||
|
||||
public static int CompareWithName(string lString, string rString)
|
||||
{
|
||||
Dictionary<string, ReferenceFinderData.AssetDescription> asset = ResourceReferenceInfo.Data.assetDict;
|
||||
return string.Compare(asset[lString].name, asset[rString].name, StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
public static int CompareWithNameDesc(string lString, string rString) => 0 - CompareWithName(lString, rString);
|
||||
|
||||
public static int CompareWithPath(string lString, string rString)
|
||||
{
|
||||
Dictionary<string, ReferenceFinderData.AssetDescription> asset = ResourceReferenceInfo.Data.assetDict;
|
||||
return string.Compare(asset[lString].path, asset[rString].path, StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
public static int CompareWithPathDesc(string lString, string rString) => 0 - CompareWithPath(lString, rString);
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f2a386b95a697364abaac53ed1cac83e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
11
UnityProject/Assets/Editor/ReferenceFinder/SortType.cs
Normal file
11
UnityProject/Assets/Editor/ReferenceFinder/SortType.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
namespace TEngine.Editor
|
||||
{
|
||||
public enum SortType
|
||||
{
|
||||
None,
|
||||
AscByName,
|
||||
DescByName,
|
||||
AscByPath,
|
||||
DescByPath
|
||||
}
|
||||
}
|
11
UnityProject/Assets/Editor/ReferenceFinder/SortType.cs.meta
Normal file
11
UnityProject/Assets/Editor/ReferenceFinder/SortType.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 86a3dbcbc8c8c7145bab4093920461da
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Reference in New Issue
Block a user