源战役客户端
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

243 строки
7.9 KiB

1 месяц назад
  1. using System.Collections.Generic;
  2. using System.IO;
  3. using UnityEditor;
  4. using UnityEngine;
  5. using UnityEditor.IMGUI.Controls;
  6. public class ReferenceFinderWindow : EditorWindow
  7. {
  8. //依赖模式的key
  9. const string isDependPrefKey = "ReferenceFinderData_IsDepend";
  10. //是否需要更新信息状态的key
  11. const string needUpdateStatePrefKey = "ReferenceFinderData_needUpdateState";
  12. private static ReferenceFinderData data = new ReferenceFinderData();
  13. private static bool initializedData = false;
  14. private bool isDepend = false;
  15. private bool needUpdateState = true;
  16. private bool needUpdateAssetTree = false;
  17. private bool initializedGUIStyle = false;
  18. //工具栏按钮样式
  19. private GUIStyle toolbarButtonGUIStyle;
  20. //工具栏样式
  21. private GUIStyle toolbarGUIStyle;
  22. //选中资源列表
  23. private List<string> selectedAssetGuid = new List<string>();
  24. private AssetTreeView m_AssetTreeView;
  25. [SerializeField]
  26. private TreeViewState m_TreeViewState;
  27. //查找资源引用信息
  28. [MenuItem("Assets/Find References In Project %#&f", false, 25)]
  29. static void FindRef()
  30. {
  31. InitDataIfNeeded();
  32. OpenWindow();
  33. ReferenceFinderWindow window = GetWindow<ReferenceFinderWindow>();
  34. window.UpdateSelectedAssets();
  35. }
  36. //打开窗口
  37. [MenuItem("Window/Reference Finder", false, 1000)]
  38. static void OpenWindow()
  39. {
  40. ReferenceFinderWindow window = GetWindow<ReferenceFinderWindow>();
  41. window.wantsMouseMove = false;
  42. window.titleContent = new GUIContent("Ref Finder");
  43. window.Show();
  44. window.Focus();
  45. }
  46. //初始化数据
  47. static void InitDataIfNeeded()
  48. {
  49. if (!initializedData)
  50. {
  51. //初始化数据
  52. if(!data.ReadFromCache())
  53. {
  54. data.CollectDependenciesInfo();
  55. }
  56. initializedData = true;
  57. }
  58. }
  59. //初始化GUIStyle
  60. void InitGUIStyleIfNeeded()
  61. {
  62. if (!initializedGUIStyle)
  63. {
  64. toolbarButtonGUIStyle = new GUIStyle("ToolbarButton");
  65. toolbarGUIStyle = new GUIStyle("Toolbar");
  66. initializedGUIStyle = true;
  67. }
  68. }
  69. //更新选中资源列表
  70. private void UpdateSelectedAssets()
  71. {
  72. selectedAssetGuid.Clear();
  73. foreach(var obj in Selection.objects)
  74. {
  75. string path = AssetDatabase.GetAssetPath(obj);
  76. //如果是文件夹
  77. if (Directory.Exists(path))
  78. {
  79. string[] folder = new string[] { path };
  80. //将文件夹下所有资源作为选择资源
  81. string[] guids = AssetDatabase.FindAssets(null, folder);
  82. foreach(var guid in guids)
  83. {
  84. if (!selectedAssetGuid.Contains(guid) &&
  85. !Directory.Exists(AssetDatabase.GUIDToAssetPath(guid)))
  86. {
  87. selectedAssetGuid.Add(guid);
  88. }
  89. }
  90. }
  91. //如果是文件资源
  92. else
  93. {
  94. string guid = AssetDatabase.AssetPathToGUID(path);
  95. selectedAssetGuid.Add(guid);
  96. }
  97. }
  98. needUpdateAssetTree = true;
  99. }
  100. //通过选中资源列表更新TreeView
  101. private void UpdateAssetTree()
  102. {
  103. if (needUpdateAssetTree && selectedAssetGuid.Count != 0)
  104. {
  105. var root = SelectedAssetGuidToRootItem(selectedAssetGuid);
  106. if(m_AssetTreeView == null)
  107. {
  108. //初始化TreeView
  109. if (m_TreeViewState == null)
  110. m_TreeViewState = new TreeViewState();
  111. var headerState = AssetTreeView.CreateDefaultMultiColumnHeaderState(position.width);
  112. var multiColumnHeader = new MultiColumnHeader(headerState);
  113. m_AssetTreeView = new AssetTreeView(m_TreeViewState, multiColumnHeader);
  114. }
  115. m_AssetTreeView.assetRoot = root;
  116. m_AssetTreeView.CollapseAll();
  117. m_AssetTreeView.Reload();
  118. needUpdateAssetTree = false;
  119. }
  120. }
  121. private void OnEnable()
  122. {
  123. isDepend = PlayerPrefs.GetInt(isDependPrefKey, 0) == 1;
  124. needUpdateState = PlayerPrefs.GetInt(needUpdateStatePrefKey, 1) == 1;
  125. }
  126. private void OnGUI()
  127. {
  128. InitGUIStyleIfNeeded();
  129. DrawOptionBar();
  130. UpdateAssetTree();
  131. if (m_AssetTreeView != null)
  132. {
  133. //绘制Treeview
  134. m_AssetTreeView.OnGUI(new Rect(0, toolbarGUIStyle.fixedHeight, position.width, position.height - toolbarGUIStyle.fixedHeight));
  135. }
  136. }
  137. //绘制上条
  138. public void DrawOptionBar()
  139. {
  140. EditorGUILayout.BeginHorizontal(toolbarGUIStyle);
  141. //刷新数据
  142. if (GUILayout.Button("Refresh Data", toolbarButtonGUIStyle))
  143. {
  144. data.CollectDependenciesInfo();
  145. needUpdateAssetTree = true;
  146. EditorGUIUtility.ExitGUI();
  147. }
  148. //修改模式
  149. bool PreIsDepend = isDepend;
  150. isDepend = GUILayout.Toggle(isDepend, isDepend ? "Model(Depend)" : "Model(Reference)", toolbarButtonGUIStyle,GUILayout.Width(100));
  151. if(PreIsDepend != isDepend){
  152. OnModelSelect();
  153. }
  154. //是否需要更新状态
  155. bool PreNeedUpdateState = needUpdateState;
  156. needUpdateState = GUILayout.Toggle(needUpdateState, "Need Update State", toolbarButtonGUIStyle);
  157. if (PreNeedUpdateState != needUpdateState)
  158. {
  159. PlayerPrefs.SetInt(needUpdateStatePrefKey, needUpdateState ? 1 : 0);
  160. }
  161. GUILayout.FlexibleSpace();
  162. //扩展
  163. if (GUILayout.Button("Expand", toolbarButtonGUIStyle))
  164. {
  165. if (m_AssetTreeView != null) m_AssetTreeView.ExpandAll();
  166. }
  167. //折叠
  168. if (GUILayout.Button("Collapse", toolbarButtonGUIStyle))
  169. {
  170. if (m_AssetTreeView != null) m_AssetTreeView.CollapseAll();
  171. }
  172. EditorGUILayout.EndHorizontal();
  173. }
  174. private void OnModelSelect()
  175. {
  176. needUpdateAssetTree = true;
  177. PlayerPrefs.SetInt(isDependPrefKey, isDepend ? 1 : 0);
  178. }
  179. //生成root相关
  180. private HashSet<string> updatedAssetSet = new HashSet<string>();
  181. //通过选择资源列表生成TreeView的根节点
  182. private AssetViewItem SelectedAssetGuidToRootItem(List<string> selectedAssetGuid)
  183. {
  184. updatedAssetSet.Clear();
  185. int elementCount = 0;
  186. var root = new AssetViewItem { id = elementCount, depth = -1, displayName = "Root", data = null };
  187. int depth = 0;
  188. var stack = new Stack<string>();
  189. foreach (var childGuid in selectedAssetGuid)
  190. {
  191. var child = CreateTree(childGuid, ref elementCount, depth, stack);
  192. if (child != null)
  193. root.AddChild(child);
  194. }
  195. updatedAssetSet.Clear();
  196. return root;
  197. }
  198. //通过每个节点的数据生成子节点
  199. private AssetViewItem CreateTree(string guid, ref int elementCount, int _depth, Stack<string> stack)
  200. {
  201. if (stack.Contains(guid))
  202. return null;
  203. stack.Push(guid);
  204. if (needUpdateState && !updatedAssetSet.Contains(guid))
  205. {
  206. data.UpdateAssetState(guid);
  207. updatedAssetSet.Add(guid);
  208. }
  209. ++elementCount;
  210. var referenceData = data.assetDict[guid];
  211. var root = new AssetViewItem { id = elementCount, displayName = referenceData.name, data = referenceData, depth = _depth };
  212. var childGuids = isDepend ? referenceData.dependencies : referenceData.references;
  213. foreach (var childGuid in childGuids)
  214. {
  215. var child = CreateTree(childGuid, ref elementCount, _depth + 1, stack);
  216. if (child != null)
  217. root.AddChild(child);
  218. }
  219. stack.Pop();
  220. return root;
  221. }
  222. }