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<string> selectedAssetGuid = new List<string>();
|
|
|
|
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<ReferenceFinderWindow>();
|
|
window.UpdateSelectedAssets();
|
|
}
|
|
|
|
//打开窗口
|
|
[MenuItem("Window/Reference Finder", false, 1000)]
|
|
static void OpenWindow()
|
|
{
|
|
ReferenceFinderWindow window = GetWindow<ReferenceFinderWindow>();
|
|
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<string> updatedAssetSet = new HashSet<string>();
|
|
//通过选择资源列表生成TreeView的根节点
|
|
private AssetViewItem SelectedAssetGuidToRootItem(List<string> 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<string>();
|
|
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<string> 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;
|
|
}
|
|
}
|