AkiraPixelWind/Assets/Scripts/Editor/ProjectTools/NoReferenceWindow.cs

519 lines
15 KiB
C#
Raw Permalink Normal View History

2022-12-29 18:20:40 +08:00
using System;
using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions;
using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEditor.UI;
using UnityEngine;
using Object = UnityEngine.Object;
public class NoReferenceWindow : EditorWindow
{
#if UNITY_EDITOR
private enum AssetType
{
None,
Prefab,
Material,
Scene,
Asset,
Lua,
Image,
FBX,
Controller,
Animation,
}
private class FileInfo
{
public string path;
public AssetType assetType;
public Object asset;
}
private static string[] ASSET_FILE_ROOT = { "Assets/Resources", "Assets/GameAssets", "Assets/Scene", "Assets/StreamingAssets" };
// <20><><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD>
private static string[] FilterDirectory = { "Assets/Resources/UI/GenAtlas" };
private Dictionary<string, FileInfo> allFileDic = null;
// key:luaPath,value:luaContent
private Dictionary<string, string> luaFileContentDic = null;
private List<FileInfo> assetDependsList = null;
// δ<><CEB4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ
private Dictionary<AssetType, List<FileInfo>> noReferenceAssetDic = null;
private Vector2 ve2;
private bool initComplete = false;
// ɸѡ<C9B8>ļ<EFBFBD><C4BC><EFBFBD>
private List<string> siftPathList = new List<string>();
// ɸѡ<C9B8>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD><EFBFBD>δʹ<CEB4>õ<EFBFBD><C3B5>ļ<EFBFBD>
private Dictionary<AssetType, List<FileInfo>> noReferenceSiftAssetDic = null;
private bool isAll = true;
private void Awake()
{
siftPathList.Add("Assets/GameAssets");
}
// <20><><EFBFBD>Ʊ༭<C6B1><E0BCAD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
private void OnGUI()
{
EditorGUILayout.Space();
if (initComplete == false)
{
return;
}
if (noReferenceAssetDic == null)
{
InitAllFileDic();
return;
}
DrawSift();
ve2 = EditorGUILayout.BeginScrollView(ve2);
var tmpNoRefernceDic = noReferenceAssetDic;
if (!isAll)
{
tmpNoRefernceDic = noReferenceSiftAssetDic;
}
foreach (var assetType in tmpNoRefernceDic.Keys)
{
List<FileInfo> infos = tmpNoRefernceDic[assetType];
if (infos.Count == 0) continue;
EditorGUILayout.LabelField(assetType.ToString(), EditorStyles.boldLabel);
for (int i = 0; i < infos.Count; i++)
{
CreateNpReferenceItem(infos[i]);
}
if (GUILayout.Button("һ<><D2BB>ɾ<EFBFBD><C9BE>", GUILayout.Height(30)))
{
DeleteAllAsset(assetType);
}
EditorGUILayout.Space();
}
EditorGUILayout.EndScrollView();
EditorGUILayout.Space();
}
[MenuItem("<22><>Ŀ<EFBFBD><C4BF><EFBFBD><EFBFBD>/<2F><>Դ<EFBFBD><D4B4><EFBFBD><EFBFBD>/<2F><><EFBFBD><EFBFBD>δ<EFBFBD><CEB4><EFBFBD><EFBFBD><EFBFBD>õ<EFBFBD><C3B5><EFBFBD>Դ", false, 10)]
private static void OpenNoReferenceWindow()
{
NoReferenceWindow window = (NoReferenceWindow)EditorWindow.GetWindow(typeof(NoReferenceWindow), true, <><CEB4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD>б<EFBFBD>");
window.InitAllFileDic();
}
public void RefreshInfo()
{
InitAssetDependDic();
InitLuaFileContentDic();
InitNoReferenceAssetDic();
initComplete = true;
}
private bool IsInFilterDirectory(string assetPath)
{
for (int i = 0; i < FilterDirectory.Length; i++)
{
if (assetPath.Contains(FilterDirectory[i]))
{
return true;
}
}
return false;
}
/// <summary>
/// <20>ҳ<EFBFBD>Ŀ<EFBFBD><C4BF>·<EFBFBD><C2B7><EFBFBD>µ<EFBFBD><C2B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ
/// </summary>
private void InitAllFileDic()
{
Debug.Log("<22><>ʼɨ<CABC><C9A8>");
long t = System.DateTime.Now.Ticks;
allFileDic = new Dictionary<string, FileInfo>();
string[] guids = AssetDatabase.FindAssets("", ASSET_FILE_ROOT);
for (int i = 0; i < guids.Length; i++)
{
string path = AssetDatabase.GUIDToAssetPath(guids[i]);
if (EditorUtility.DisplayCancelableProgressBar($"<22><>Դ<EFBFBD><D4B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>:({i}/{guids.Length})", path,
(float)i / (float)guids.Length))
{
EditorUtility.ClearProgressBar();
Close();
return;
}
if (IsInFilterDirectory(path)) continue;
AssetType assetType = GetAssetTypeByPath(path);
if (assetType == AssetType.None) continue;
FileInfo info = new FileInfo();
info.path = path;
info.assetType = assetType;
info.asset = AssetDatabase.LoadAssetAtPath<Object>(path);
allFileDic.Add(path, info);
}
EditorUtility.ClearProgressBar();
Debug.Log("<22><>Դɨ<D4B4><C9A8><EFBFBD><EFBFBD><EFBFBD><EFBFBD>");
RefreshInfo();
Debug.Log($"<22><>ʱ<EFBFBD><CAB1>{(System.DateTime.Now.Ticks - t) / 10000} <20><><EFBFBD><EFBFBD>");
}
/// <summary>
/// <20>ҳ<EFBFBD><D2B3><EFBFBD>Դ<EFBFBD><D4B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӵ<EFBFBD><D3B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1><EFBFBD>
/// </summary>
private void InitAssetDependDic()
{
assetDependsList = new List<FileInfo>();
List<FileInfo> infos = new List<FileInfo>(allFileDic.Values);
if (infos.Count == 0) return;
for (int i = 0; i < infos.Count; i++)
{
FileInfo info = infos[i];
if (info.assetType == AssetType.Lua || info.assetType == AssetType.Image) continue;
if (EditorUtility.DisplayCancelableProgressBar(<><C9A8><EFBFBD><EFBFBD>Դ<EFBFBD><D4B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵ...", $"({i}/{infos.Count})\n path:{info.path}",
(float)i / (float)infos.Count))
{
EditorUtility.ClearProgressBar();
Close();
return;
}
string[] depends = AssetDatabase.GetDependencies(info.path, false);
for (int j = 0; j < depends.Length; j++)
{
string dependPath = depends[j];
FileInfo dependInfo = FindFileInfo(dependPath);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD>ջ<EFBFBD><D5BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Լ<EFBFBD><D4BC><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD>
if (dependInfo == null || dependInfo == info) continue;
if (!assetDependsList.Contains(dependInfo))
{
assetDependsList.Add(dependInfo);
}
}
}
Debug.Log(<><C9A8><EFBFBD><EFBFBD>Դ<EFBFBD><D4B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵ<EFBFBD><CFB5><EFBFBD><EFBFBD>");
EditorUtility.ClearProgressBar();
}
/// <summary>
/// <20><>ȡlua<75>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD>ݣ<EFBFBD><DDA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1>У<EFBFBD><D0A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ<EFBFBD><C4BF><EFBFBD><EFBFBD>lua<75>ȸ<EFBFBD><C8B8>µģ<C2B5><C4A3><EFBFBD><EFBFBD>ñ<EFBFBD><C3B1><EFBFBD><EFBFBD><EFBFBD>Ҳ<EFBFBD><D2B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>lua<75>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>lua<75>ļ<EFBFBD><C4BC>л<EFBFBD><D0BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><D4B4><EFBFBD><EFBFBD><EFBFBD>ƣ<EFBFBD>
/// </summary>
private void InitLuaFileContentDic()
{
luaFileContentDic = new Dictionary<string, string>();
foreach (var info in allFileDic.Values)
{
if (info.assetType == AssetType.Lua)
{
luaFileContentDic.Add(info.path, File.ReadAllText(info.path));
}
}
}
// <20><>ʼ<EFBFBD><CABC>δ<EFBFBD><CEB4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ
private void InitNoReferenceAssetDic()
{
noReferenceAssetDic = new Dictionary<AssetType, List<FileInfo>>();
foreach (var info in allFileDic.Values)
{
if (info.assetType == AssetType.Lua) continue;
// <20>ж<EFBFBD><D0B6><EFBFBD>Դ<EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ã<EFBFBD><C3A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1>е<EFBFBD><D0B5><EFBFBD><EFBFBD><EFBFBD>,lua<75>ű<EFBFBD><C5B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1>е<EFBFBD><D0B5><EFBFBD><EFBFBD>ã<EFBFBD>
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><D4B4><EFBFBD><EFBFBD>
if (CheckOtherAssetReference(info.path)) continue;
// <20><>lua<75>ű<EFBFBD><C5B1><EFBFBD><EFBFBD><EFBFBD>
if (CheckLuaReference(info.path)) continue;
AddNoReferenceAsset(info);
}
Debug.Log(<><CEB4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><D4B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>");
}
private FileInfo FindFileInfo(string assetPath)
{
if (!allFileDic.ContainsKey(assetPath)) return null;
return allFileDic[assetPath];
}
private void AddNoReferenceAsset(FileInfo info)
{
List<FileInfo> list = null;
if (!noReferenceAssetDic.TryGetValue(info.assetType, out list))
{
list = new List<FileInfo>();
noReferenceAssetDic.Add(info.assetType, list);
}
list.Add(info);
}
private void RemoveNoReferenceAsset(Dictionary<AssetType, List<FileInfo>> noReferenceAsset, string path)
{
FileInfo info = FindFileInfo(path);
if (info == null) return;
List<FileInfo> list = null;
if (noReferenceAsset.TryGetValue(info.assetType, out list))
{
list.Remove(info);
}
}
private AssetType GetAssetTypeByPath(string assetPath)
{
string extension = Path.GetExtension(assetPath);
switch (extension.ToLower())
{
case ".prefab": return AssetType.Prefab;
case ".mat": return AssetType.Material;
case ".unity": return AssetType.Scene;
case ".asset": return AssetType.Asset;
case ".lua": return AssetType.Lua;
case ".png": return AssetType.Image;
case ".jpg": return AssetType.Image;
case ".fbx": return AssetType.FBX;
case ".controller": return AssetType.Controller;
case ".anim": return AssetType.Animation;
}
return AssetType.None;
}
/// <summary>
/// <20><><EFBFBD><EFBFBD><E9B1BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><D4B4><EFBFBD><EFBFBD>
/// </summary>
/// <param name="assetPath"></param>
/// <returns></returns>
private bool CheckOtherAssetReference(string assetPath)
{
if (string.IsNullOrEmpty(assetPath))
{
Debug.LogError("CheckOtherAssetReference error: assetPath is null");
return false;
}
FileInfo info = FindFileInfo(assetPath);
if (info == null) return false;
if (info.assetType == AssetType.Scene)
{
return EditorSceneManager.GetActiveScene().name.Equals(Path.GetFileNameWithoutExtension(assetPath));
}
foreach (var dependInfo in assetDependsList)
{
if (dependInfo == info)
{
return true;
}
}
return false;
}
// <20><><EFBFBD>鱻lua<75>ű<EFBFBD><C5B1><EFBFBD><EFBFBD><EFBFBD>
private bool CheckLuaReference(string assetPath)
{
string fileName = Path.GetFileNameWithoutExtension(assetPath);
if (string.IsNullOrEmpty(fileName))
{
return false;
}
foreach (var content in luaFileContentDic.Values)
{
if (Regex.IsMatch(content, fileName + "\"") || Regex.IsMatch(content, fileName + "\'"))
{
return true;
}
}
return false;
}
private void DeleteAsset(FileInfo info, bool refresh = false)
{
RemoveDepends(info);
RemoveNoReferenceAsset(noReferenceAssetDic, info.path);
if (!isAll && noReferenceSiftAssetDic != null) RemoveNoReferenceAsset(noReferenceSiftAssetDic, info.path);
allFileDic.Remove(info.path);
AssetDatabase.DeleteAsset(info.path);
if (refresh)
AssetDatabase.Refresh();
}
// ɾ<><C9BE><EFBFBD><EFBFBD>Դ
private void DeleteAllAsset(AssetType assetType)
{
List<FileInfo> infos = noReferenceAssetDic[assetType];
for (int i = infos.Count - 1; i >= 0; i--)
{
DeleteAsset(infos[i]);
}
AssetDatabase.Refresh();
}
// <20>Ƴ<EFBFBD><C6B3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
private void RemoveDepends(FileInfo info)
{
if (assetDependsList.Contains(info))
{
assetDependsList.Remove(info);
}
}
// <20><>ʼ<EFBFBD><CABC>ɸѡ<C9B8>ļ<EFBFBD><C4BC><EFBFBD>δ<EFBFBD><CEB4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ
private void RefreshNoReferenceSiltAssetDic()
{
noReferenceSiftAssetDic = new Dictionary<AssetType, List<FileInfo>>();
foreach (var info in allFileDic.Values)
{
if (info.assetType == AssetType.Lua) continue;
if (!CheckInSiltDirectory(info.path)) continue;
// <20>ж<EFBFBD><D0B6><EFBFBD>Դ<EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ã<EFBFBD><C3A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1>е<EFBFBD><D0B5><EFBFBD><EFBFBD><EFBFBD>,lua<75>ű<EFBFBD><C5B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1>е<EFBFBD><D0B5><EFBFBD><EFBFBD>ã<EFBFBD>
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><D4B4><EFBFBD><EFBFBD>
if (CheckOtherAssetReference(info.path)) continue;
// <20><>lua<75>ű<EFBFBD><C5B1><EFBFBD><EFBFBD><EFBFBD>
if (CheckLuaReference(info.path)) continue;
AddNoReferenceSiltAsset(info);
}
}
private bool CheckInSiltDirectory(string assetPath)
{
for (int i = 0; i < siftPathList.Count; i++)
{
string path = siftPathList[i];
if (string.IsNullOrEmpty(path)) continue;
if (!Directory.Exists(path)) continue;
if (Regex.IsMatch(assetPath, path))
{
return true;
}
}
return false;
}
private void AddNoReferenceSiltAsset(FileInfo info)
{
List<FileInfo> list = null;
if (!noReferenceSiftAssetDic.TryGetValue(info.assetType, out list))
{
list = new List<FileInfo>();
noReferenceSiftAssetDic.Add(info.assetType, list);
}
list.Add(info);
}
#region // ---------------------- <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ------------------------- //
private void CreateNpReferenceItem(FileInfo info)
{
GUILayout.BeginHorizontal();
// var obj = AssetDatabase.LoadAssetAtPath<Object>(info.path);
EditorGUILayout.ObjectField(info.asset, typeof(UnityEngine.Object));
// string assetName = Path.GetFileNameWithoutExtension(info.path);
// EditorGUILayout.DelayedTextField(assetName);
// if (GUILayout.Button("<22><>λ",GUILayout.Width(70)))
// {
// var obj = AssetDatabase.LoadAssetAtPath<Object>(info.path);
// if(obj != null)
// EditorGUIUtility.PingObject(obj);
// }
if (GUILayout.Button(<><C9BE><EFBFBD><EFBFBD>Դ", GUILayout.Width(70)))
{
DeleteAsset(info, true);
}
GUILayout.EndHorizontal();
}
private void DrawSift()
{
EditorGUILayout.LabelField("*ע<><EFBFBD><E2A3BA>Щ<EFBFBD><D0A9>Դ<EFBFBD><D4B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>أ<EFBFBD>ע<EFBFBD><D7A2><EFBFBD><EFBFBD><EFBFBD>֡<EFBFBD>", EditorStyles.boldLabel, GUILayout.Height(30));
EditorGUILayout.LabelField(ѡ<C9B8>б<EFBFBD>", EditorStyles.boldLabel, GUILayout.Height(30));
for (int i = 0; i < siftPathList.Count; i++)
{
EditorGUILayout.BeginHorizontal();
EditorGUILayout.LabelField("Path:", GUILayout.Width(50));
siftPathList[i] = EditorGUILayout.TextField(siftPathList[i]);
if (GUILayout.Button("x", GUILayout.Width(20)))
{
siftPathList.RemoveAt(i);
}
EditorGUILayout.EndHorizontal();
}
if (GUILayout.Button("+", GUILayout.Height(20)))
{
siftPathList.Add(string.Empty);
}
EditorGUILayout.BeginHorizontal();
if (GUILayout.Button(ѡ<C9B8><D1A1>Դ", GUILayout.Height(40)))
{
string noExistDirectoryStr = "";
for (int i = 0; i < siftPathList.Count; i++)
{
string path = siftPathList[i];
if (string.IsNullOrEmpty(path)) continue;
if (!Directory.Exists(path))
{
noExistDirectoryStr = noExistDirectoryStr + path + "\r\n";
continue;
}
}
if (noExistDirectoryStr != "")
{
EditorUtility.DisplayDialog("<22><>ʾ", "<22>ļ<EFBFBD><C4BC>в<EFBFBD><D0B2><EFBFBD><EFBFBD><EFBFBD>:\r\n" + noExistDirectoryStr, "ok");
}
RefreshNoReferenceSiltAssetDic();
isAll = false;
}
if (GUILayout.Button(<><C8AB><EFBFBD><EFBFBD>Դ", GUILayout.Height(40)))
{
isAll = true;
}
EditorGUILayout.EndHorizontal();
EditorGUILayout.Space();
EditorGUILayout.Space();
}
#endregion // ---------------------- <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ------------------------- //
#endif
}