using System.Collections.Generic; using System.IO; using UnityEditor; using UnityEngine; using UnityEditor.IMGUI.Controls; public class ReferenceFinderWindow : EditorWindow { //依赖模式的key const string isDependPrefKey = "ReferenceFinderData_IsDepend"; //是否需要更新信息状态的key const string needUpdateStatePrefKey = "ReferenceFinderData_needUpdateState"; private static ReferenceFinderData data = new ReferenceFinderData(); private static bool initializedData = false; private bool isDepend = false; private bool needUpdateState = true; private bool needUpdateAssetTree = false; private bool initializedGUIStyle = false; //工具栏按钮样式 private GUIStyle toolbarButtonGUIStyle; //工具栏样式 private GUIStyle toolbarGUIStyle; //选中资源列表 private List selectedAssetGuid = new List(); private AssetTreeView m_AssetTreeView; [SerializeField] private TreeViewState m_TreeViewState; //查找资源引用信息 [MenuItem("Assets/Find References In Project %#&f", false, 25)] static void FindRef() { InitDataIfNeeded(); OpenWindow(); ReferenceFinderWindow window = GetWindow(); window.UpdateSelectedAssets(); } //打开窗口 [MenuItem("Window/Reference Finder", false, 1000)] static void OpenWindow() { ReferenceFinderWindow window = GetWindow(); window.wantsMouseMove = false; window.titleContent = new GUIContent("Ref Finder"); window.Show(); window.Focus(); } //初始化数据 static void InitDataIfNeeded() { if (!initializedData) { //初始化数据 if(!data.ReadFromCache()) { data.CollectDependenciesInfo(); } initializedData = true; } } //初始化GUIStyle void InitGUIStyleIfNeeded() { if (!initializedGUIStyle) { toolbarButtonGUIStyle = new GUIStyle("ToolbarButton"); toolbarGUIStyle = new GUIStyle("Toolbar"); initializedGUIStyle = true; } } //更新选中资源列表 private void UpdateSelectedAssets() { selectedAssetGuid.Clear(); foreach(var obj in Selection.objects) { string path = AssetDatabase.GetAssetPath(obj); //如果是文件夹 if (Directory.Exists(path)) { string[] folder = new string[] { path }; //将文件夹下所有资源作为选择资源 string[] guids = AssetDatabase.FindAssets(null, folder); foreach(var 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; } //通过选中资源列表更新TreeView private void UpdateAssetTree() { if (needUpdateAssetTree && selectedAssetGuid.Count != 0) { var root = SelectedAssetGuidToRootItem(selectedAssetGuid); if(m_AssetTreeView == null) { //初始化TreeView if (m_TreeViewState == null) m_TreeViewState = new TreeViewState(); var headerState = AssetTreeView.CreateDefaultMultiColumnHeaderState(position.width); var multiColumnHeader = new MultiColumnHeader(headerState); m_AssetTreeView = new AssetTreeView(m_TreeViewState, multiColumnHeader); } m_AssetTreeView.assetRoot = root; m_AssetTreeView.CollapseAll(); m_AssetTreeView.Reload(); needUpdateAssetTree = false; } } private void OnEnable() { isDepend = PlayerPrefs.GetInt(isDependPrefKey, 0) == 1; needUpdateState = PlayerPrefs.GetInt(needUpdateStatePrefKey, 1) == 1; } private void OnGUI() { InitGUIStyleIfNeeded(); DrawOptionBar(); UpdateAssetTree(); if (m_AssetTreeView != null) { //绘制Treeview m_AssetTreeView.OnGUI(new Rect(0, toolbarGUIStyle.fixedHeight, position.width, position.height - toolbarGUIStyle.fixedHeight)); } } //绘制上条 public void DrawOptionBar() { EditorGUILayout.BeginHorizontal(toolbarGUIStyle); //刷新数据 if (GUILayout.Button("Refresh Data", toolbarButtonGUIStyle)) { data.CollectDependenciesInfo(); needUpdateAssetTree = true; EditorGUIUtility.ExitGUI(); } //修改模式 bool PreIsDepend = isDepend; isDepend = GUILayout.Toggle(isDepend, isDepend ? "Model(Depend)" : "Model(Reference)", toolbarButtonGUIStyle,GUILayout.Width(100)); if(PreIsDepend != isDepend){ OnModelSelect(); } //是否需要更新状态 bool PreNeedUpdateState = needUpdateState; needUpdateState = GUILayout.Toggle(needUpdateState, "Need Update State", toolbarButtonGUIStyle); if (PreNeedUpdateState != needUpdateState) { PlayerPrefs.SetInt(needUpdateStatePrefKey, needUpdateState ? 1 : 0); } GUILayout.FlexibleSpace(); //扩展 if (GUILayout.Button("Expand", toolbarButtonGUIStyle)) { if (m_AssetTreeView != null) m_AssetTreeView.ExpandAll(); } //折叠 if (GUILayout.Button("Collapse", toolbarButtonGUIStyle)) { if (m_AssetTreeView != null) m_AssetTreeView.CollapseAll(); } EditorGUILayout.EndHorizontal(); } private void OnModelSelect() { needUpdateAssetTree = true; PlayerPrefs.SetInt(isDependPrefKey, isDepend ? 1 : 0); } //生成root相关 private HashSet updatedAssetSet = new HashSet(); //通过选择资源列表生成TreeView的根节点 private AssetViewItem SelectedAssetGuidToRootItem(List selectedAssetGuid) { updatedAssetSet.Clear(); int elementCount = 0; var root = new AssetViewItem { id = elementCount, depth = -1, displayName = "Root", data = null }; int depth = 0; var stack = new Stack(); foreach (var childGuid in selectedAssetGuid) { var child = CreateTree(childGuid, ref elementCount, depth, stack); if (child != null) root.AddChild(child); } updatedAssetSet.Clear(); return root; } //通过每个节点的数据生成子节点 private AssetViewItem CreateTree(string guid, ref int elementCount, int _depth, Stack stack) { if (stack.Contains(guid)) return null; stack.Push(guid); if (needUpdateState && !updatedAssetSet.Contains(guid)) { data.UpdateAssetState(guid); updatedAssetSet.Add(guid); } ++elementCount; var referenceData = data.assetDict[guid]; var root = new AssetViewItem { id = elementCount, displayName = referenceData.name, data = referenceData, depth = _depth }; var childGuids = isDepend ? referenceData.dependencies : referenceData.references; foreach (var childGuid in childGuids) { var child = CreateTree(childGuid, ref elementCount, _depth + 1, stack); if (child != null) root.AddChild(child); } stack.Pop(); return root; } }