diff options
author | chai <chaifix@163.com> | 2018-07-10 11:50:10 +0800 |
---|---|---|
committer | chai <chaifix@163.com> | 2018-07-10 11:50:10 +0800 |
commit | 36f798462d5ee78df294ead5fb5a8ea1e372fbed (patch) | |
tree | 2d315d099c172cdbb7d62b50367c8d9cbe087fbc /AssetBrowser.cs | |
parent | 7bf4eb116498086274306fa0d3ebbe906f9833e6 (diff) |
+定位被选中的资源
Diffstat (limited to 'AssetBrowser.cs')
-rw-r--r-- | AssetBrowser.cs | 650 |
1 files changed, 499 insertions, 151 deletions
diff --git a/AssetBrowser.cs b/AssetBrowser.cs index 4be9386..398c2c2 100644 --- a/AssetBrowser.cs +++ b/AssetBrowser.cs @@ -1,42 +1,71 @@ -using UnityEditor; +///////////////////////////////////////////////////////////////////////////////// +// +// author: chaifeixiang +// date: 2018.5.20 +// desc: Unity中找文件依赖关系的编辑器工具,需要Unity5.4及以上版本 +// +// +// +// +// +///////////////////////////////////////////////////////////////////////////////// + +using UnityEditor; using UnityEngine; using System; using System.IO; using System.Collections; using System.Collections.Generic; +using Object = UnityEngine.Object; class AssetData { // 枚举值为遍历的优先级,用于AssetData.Dependcies和AssetDataManager.Assets - public static readonly int AssetTypeCount = 9; + // 必须是紧凑的索引 public enum AssetType { - Scene = 0, - Prefab, + Scene = 0, + Prefab, Mesh, Material, - Asset, - Texture, - Shader, - Script, - CSV, + Asset, + Texture, + Shader, + Script, + CSV, - Unknown = 255, + TypeCount, + + Unknown = 255, + } + + public enum SubType + { + // Texture + png = 0, + jpg, + bmp, + // Mesh + fbx, + FBX, + // + Unknown = 255, } public AssetData(FileSystemInfo f) { - for (int i = 0; i < AssetTypeCount; ++i) + for (int i = 0; i < (int)AssetType.TypeCount; ++i) Dependencies[i] = new List<string>(); AssetDataManager manager = AssetDataManager.Get(); AssetPath = manager.FullPathToAssetPath(f.FullName); GUID = AssetDatabase.AssetPathToGUID(AssetPath); Name = f.Name; ObjType = AssetDatabase.GetMainAssetTypeAtPath(AssetPath); - FileType = ExtensionToAssetType(f.Extension); Extension = f.Extension; - string[] depsPath = AssetDatabase.GetDependencies(AssetPath, false); - for(int i = 0; i < depsPath.Length; ++i) + FileType = ExtensionToAssetType(Extension); + SubFileType = ExtensionToSubType(Extension); + string[] depsPath = AssetDatabase.GetDependencies(AssetPath, false); + for (int i = 0; i < depsPath.Length; ++i) { string path = depsPath[i]; string guid = AssetDatabase.AssetPathToGUID(path); @@ -49,10 +78,10 @@ class AssetData Dependencies[(int)type].Add(guid); ++RefCount; List<string> data; - if (!AssetDataManager.AssetsReverse.TryGetValue(guid, out data)) + if (!manager.AssetsReverse.TryGetValue(guid, out data)) { data = new List<string>(); - AssetDataManager.AssetsReverse.Add(guid, data); + manager.AssetsReverse.Add(guid, data); } data.Add(GUID); } @@ -64,17 +93,36 @@ class AssetData #region 资源属性 public string GUID; public string Name; - public int RefCount = 0; - public int RevRefCount = 0; - public long DiskSize; + public int RefCount = 0; + //public int RevRefCount = 0; + public long DiskSize; public string DiskSizeStr; public string AssetPath; - public Type ObjType; + public Type ObjType; public string Extension; public AssetType FileType; - public List<string>[] Dependencies = new List<string>[AssetTypeCount]; + public SubType SubFileType; + public List<string>[] Dependencies = new List<string>[(int)AssetType.TypeCount]; #endregion + private SubType ExtensionToSubType(string extension) + { + SubType subType = SubType.Unknown; + // texture + if (Extension == ".png") + subType = SubType.png; + else if (Extension == ".jpg") + subType = SubType.jpg; + else if (Extension == ".bmp") + subType = SubType.bmp; + // mesh + else if (Extension == ".fbx") + subType = SubType.fbx; + else if (Extension == ".FBX") + subType = SubType.FBX; + return subType; + } + private AssetType ExtensionToAssetType(string extension) { if (extension == ".unity") return AssetType.Scene; @@ -103,17 +151,17 @@ class AssetDataManager public AssetDataManager() { - for (int i = 0; i < AssetData.AssetTypeCount; ++i) + for (int i = 0; i < (int)AssetData.AssetType.TypeCount; ++i) Assets[i] = new Dictionary<string, AssetData>(); } #region Asset字典 // 所有资源 - public static Dictionary<string, AssetData> AllAssets = new Dictionary<string, AssetData>(); + public Dictionary<string, AssetData> AllAssets = new Dictionary<string, AssetData>(); // 分类统计 - public static Dictionary<string, AssetData>[] Assets = new Dictionary<string, AssetData>[AssetData.AssetTypeCount]; + public Dictionary<string, AssetData>[] Assets = new Dictionary<string, AssetData>[(int)AssetData.AssetType.TypeCount]; // 反向依赖 - public static Dictionary<string, List<string>> AssetsReverse = new Dictionary<string, List<string>>(); + public Dictionary<string, List<string>> AssetsReverse = new Dictionary<string, List<string>>(); #endregion #region 过滤 @@ -130,13 +178,15 @@ class AssetDataManager ".csv" // CSV }; - public string GetExtension(string file) + public string GetExtension(string path) { - if (file == null || file.Length == 0) + if (path == null || path.Length <= 0) return null; - int len = file.Length; - int idx = file.LastIndexOf('.'); - return file.Substring(idx, len - idx); + int len = path.Length; + int idx = path.LastIndexOf('.'); + if (idx == -1) + return null; + return path.Substring(path.LastIndexOf('.'), len - idx); } public bool IsValidFile(string file) @@ -156,20 +206,18 @@ class AssetDataManager public bool IsValidFolder(string folderName) { - foreach(var dir in InvalidFolder) + foreach (var dir in InvalidFolder) { - if(dir == folderName) + if (dir == folderName) return false; } - return true; + return true; } #endregion public string FullPathToAssetPath(string fullpath) { - fullpath = fullpath.Replace('\\', '/'); - string path = "Assets" + fullpath.Replace(Application.dataPath, ""); - path = path.Replace('/', '\\'); + string path = "Assets" + fullpath.Replace(Application.dataPath.Replace("/", "\\"), ""); return path; } @@ -183,13 +231,13 @@ class AssetDataManager { DirectoryInfo directoryInfo = new DirectoryInfo(fullpath); FileSystemInfo[] filesInfo = directoryInfo.GetFileSystemInfos(); - foreach(FileSystemInfo f in filesInfo) + foreach (FileSystemInfo f in filesInfo) { - if(f is DirectoryInfo && IsValidFolder(f.Name)) + if (f is DirectoryInfo && IsValidFolder(f.Name)) { LoadAssets(f.FullName); } - else if(f.Extension != ".meta" && IsValidFile(f.Name)) + else if (f.Extension != ".meta" && IsValidFile(f.Name)) { AssetData asset = new AssetData(f); AllAssets.Add(asset.GUID, asset); @@ -198,6 +246,13 @@ class AssetDataManager } } + public string FormatPath(string assetpath) + { + string path = assetpath.Replace('/', '\\'); + path = path.Replace("\\\\", "\\"); + return path; + } + public void ClearAssets() { AllAssets.Clear(); @@ -214,30 +269,33 @@ class Drawer { SelectorButtonStyle = new GUIStyle(GUIStyle.none); SelectorButtonStyle.normal.background = CreateTexture(1, 1, new Color32(62, 95, 150, 255)); + MidAlignment = new GUIStyle(GUIStyle.none); + MidAlignment.alignment = TextAnchor.MiddleCenter; } - private Texture2D CreateTexture(int w, int h, Color col) + private Texture2D CreateTexture(int width, int height, Color color) { - Color[] pixels = new Color[w * h]; - for(int i = 0; i < w * h; ++i) - pixels[i] = col; - Texture2D texture = new Texture2D(w, h); - texture.SetPixels(pixels); - return texture; + Color[] pixels = new Color[width * height]; + for (int i = 0; i < width * height; ++i) + pixels[i] = color; + Texture2D result = new Texture2D(width, height); + result.SetPixels(pixels); + result.Apply(); + return result; } - private static Drawer drawer = null; + private static Drawer drawer = null; public static Drawer Get() { if (drawer == null) drawer = new Drawer(); - return drawer; + return drawer; } - - public void DrawButtonMid(Rect rect, string content) + + public void DrawButtonMid(Rect rect, string content, out bool click) { - GUI.Button(rect, content, EditorStyles.miniButtonMid); + click = GUI.Button(rect, content, EditorStyles.miniButtonMid); } public void DrawButton(Rect rect, string content, out bool click) @@ -270,7 +328,10 @@ class Drawer public void DrawFoldout(Rect rect, ref bool foldout) { - foldout = EditorGUI.Foldout(rect, foldout, ""); + Texture2D foldIcon = foldout ? IconFoldout : IconFoldup; + bool clicked = GUI.Button(rect, foldIcon, MidAlignment); + if (clicked) + foldout = !foldout; } public void DrawAssetIcon(Rect rect, AssetData asset) @@ -282,15 +343,38 @@ class Drawer public void DrawSelector(Rect rect, bool selected, out bool clicked) { - SelectorButtonStyle.normal.background = CreateTexture(1, 1, new Color32(62, 95, 150, 255)); - clicked = GUI.Button(rect, "",selected ? SelectorButtonStyle : GUIStyle.none); + clicked = GUI.Button(rect, "", selected ? SelectorButtonStyle : GUIStyle.none); + } + + public void DrawPing(Rect rect, ref bool clicked) + { + GUIContent content = EditorGUIUtility.IconContent("SubAssetCollapseButton"); + clicked = GUI.Button(rect, content, MidAlignment); + } + + public void SetTextColor(Color col) + { + drawColor = GUI.skin.label.normal.textColor; + GUI.skin.label.normal.textColor = col; + } + + public void ResetTextColor() + { + GUI.skin.label.normal.textColor = drawColor; } #region 配置项 public Color ColorHeavy = new Color(0.2f, 0.2f, 0.2f); public Color ColorLight = new Color(0.3f, 0.3f, 0.3f); public GUIStyle SelectorButtonStyle; + public Texture2D IconFoldout = EditorStyles.foldout.onNormal.background; + public Texture2D IconFoldup = EditorStyles.foldout.normal.background; + public GUIStyle MidAlignment; #endregion + + #region 状态 + private Color drawColor = new Color(); + #endregion } // 文件树 @@ -316,7 +400,10 @@ class AssetBrowser : EditorWindow private static AssetBrowser editor; private static Drawer drawer; + #region 目录 private FileTree assetsTree = new FileTree(); + private FileTree assetsTreeBuffer = new FileTree(); + #endregion #region GUI 组件配置数值 private Rect window = new Rect(); @@ -328,15 +415,15 @@ class AssetBrowser : EditorWindow private int filtersOffsetY = 27; // 过滤器Y偏移度 private int headerOffsetY = 50; // 标题Y偏移度 private int assetsTreeOffsetY = 70; // 列表偏移度 - private int kTabWidth = 15; + private int kTabWidth = 13; #endregion #region 数据 - private string directory = ""; private FileTree.Node selectedNode = null; #endregion #region 过滤器 + private string filterdirectory = ""; private string filterFile = ""; private bool filterScene = false; private bool filterPrefab = false; @@ -349,7 +436,27 @@ class AssetBrowser : EditorWindow private bool filterCSV = false; #endregion - [MenuItem("Window/Asset Browser")] + #region 排序 + private enum OrderBase + { + Name, + Ref, + RevRef, + Type, + DiskSize, + Path + } + // 排序依据 + private OrderBase orderBase = OrderBase.Path; + private int orderName = 1; + private int orderRef = 1; + private int orderRevRef = 1; + private int orderType = 1; + private int orderDiskSize = 1; + private int orderPath = 1; + #endregion + + [MenuItem("DNTools/查找/资源引用关系", false, 6)] public static void Show() { editor = GetWindow<AssetBrowser>(); @@ -379,21 +486,21 @@ class AssetBrowser : EditorWindow private Dictionary<Colum, int> ColumWidth = new Dictionary<Colum, int> { - {Colum.Name, 500}, - {Colum.Ref, 100}, - {Colum.RevRef, 100}, - {Colum.Type, 100}, - {Colum.DiskSize, 100}, - {Colum.Path, 500}, + {Colum.Name, 450}, + {Colum.Ref, 70}, + {Colum.RevRef, 70}, + {Colum.Type, 70}, + {Colum.DiskSize, 70}, + {Colum.Path, 870}, }; - private Dictionary<Colum, int> ColumOffsetX = new Dictionary<Colum, int>(); + private Dictionary<Colum, int> ColumOffsetX = null; private void AdjustColumOffsetX() { - if (ColumOffsetX == null) + if (ColumOffsetX != null) return; - ColumOffsetX.Clear(); + ColumOffsetX = new Dictionary<Colum, int>(); ColumOffsetX.Add(Colum.Name, 0); ColumOffsetX.Add(Colum.Ref, ColumOffsetX[Colum.Name] + ColumWidth[Colum.Name]); ColumOffsetX.Add(Colum.RevRef, ColumOffsetX[Colum.Ref] + ColumWidth[Colum.Ref]); @@ -406,13 +513,14 @@ class AssetBrowser : EditorWindow { window = editor.position; } - + public void OnGUI() { // 调试 if (editor == null) editor = GetWindow<AssetBrowser>(); - drawer = Drawer.Get(); + if (drawer == null) + drawer = Drawer.Get(); AdjustColumOffsetX(); AdjustWindow(); @@ -444,11 +552,44 @@ class AssetBrowser : EditorWindow private void OnDirectory() { float offsetY = directoryOffsetY + scrollPos.y; - drawer.DrawLabel(new Rect(0, offsetY, 95, kLineHeight), "资源目录 Assets/"); - drawer.DrawTextfield(new Rect(95, offsetY, 250, kLineHeight), directory, ref directory); - bool load; + + Rect dragRect = new Rect(0, offsetY, 1000, 20); + string olddirectory = filterdirectory; + drawer.DrawLabel(new Rect(0, offsetY, 95, kLineHeight), "资源目录 Assets\\"); + drawer.DrawTextfield(new Rect(95, offsetY, 250, kLineHeight), filterdirectory, ref filterdirectory); + if (filterdirectory == null) + filterdirectory = ""; + // 拖拽 + Event e = Event.current; + if (dragRect.Contains(e.mousePosition)) + { + if (e.type == EventType.dragUpdated) + DragAndDrop.visualMode = DragAndDropVisualMode.Generic; + else if (e.type == EventType.DragPerform) + { + Object[] objs = DragAndDrop.objectReferences; + e.Use(); + if (DragAndDrop.objectReferences.Length > 0) + { + Object obj = DragAndDrop.objectReferences[0]; + filterdirectory = AssetDatabase.GetAssetPath(obj); + if (filterdirectory.Equals("Assets")) + { + filterdirectory = string.Empty; + } + else + { + filterdirectory = filterdirectory.Substring(7); + } + } + } + } + filterdirectory = AssetDataManager.Get().FormatPath(filterdirectory); + if (filterdirectory != olddirectory) + ProcessTreeBuffer(); + bool load; drawer.DrawButton(new Rect(350, offsetY, 50, kLineHeight), "载入", out load); - if(load) + if (load) { ProcessAssets(); ProcessTree(); @@ -458,13 +599,23 @@ class AssetBrowser : EditorWindow private void OnFilters() { + string oldfilterfile = filterFile; + bool oldfilterScene = filterScene; + bool oldfilterPrefab = filterPrefab; + bool oldfilterMaterial = filterMaterial; + bool oldfilterAsset = filterAsset; + bool oldfilterMesh = filterMesh; + bool oldfilterTexture = filterTexture; + bool oldfilterShader = filterShader; + bool oldfilterScript = filterScript; + bool oldfilterCSV = filterCSV; // 文件匹配 drawer.DrawLabel(new Rect(0, filtersOffsetY + scrollPos.y, 100, kLineHeight), "匹配文件"); drawer.DrawTextfield(new Rect(50, filtersOffsetY + scrollPos.y, 150, kLineHeight), filterFile, ref filterFile); // 类型过滤 float offsetX = 250; float offsetY = filtersOffsetY + scrollPos.y; - int width = 70; + int width = 70; drawer.DrawCheckBox(new Rect(offsetX, offsetY, width, kLineHeight), "场景", filterScene, ref filterScene); drawer.DrawCheckBox(new Rect(offsetX + width, offsetY, width, kLineHeight), "Prefab", filterPrefab, ref filterPrefab); drawer.DrawCheckBox(new Rect(offsetX + width * 2, offsetY, width, kLineHeight), "材质", filterMaterial, ref filterMaterial); @@ -474,6 +625,19 @@ class AssetBrowser : EditorWindow drawer.DrawCheckBox(new Rect(offsetX + width * 6, offsetY, width, kLineHeight), "Shader", filterShader, ref filterShader); drawer.DrawCheckBox(new Rect(offsetX + width * 7, offsetY, width, kLineHeight), "脚本", filterScript, ref filterScript); drawer.DrawCheckBox(new Rect(offsetX + width * 8, offsetY, width, kLineHeight), "CSV", filterCSV, ref filterCSV); + // 刷新TreeBuffer + if( oldfilterfile != filterFile || + oldfilterScene != filterScene|| + oldfilterPrefab != filterPrefab|| + oldfilterMaterial != filterMaterial|| + oldfilterAsset != filterAsset|| + oldfilterMesh != filterMesh|| + oldfilterTexture != filterTexture|| + oldfilterShader != filterShader|| + oldfilterScript != filterScript|| + oldfilterCSV != filterCSV + ) + ProcessTreeBuffer(); } private void OnAsset() @@ -490,7 +654,7 @@ class AssetBrowser : EditorWindow new Rect(scrollPos.x, scrollPos.y + assetsTreeOffsetY, window.width, window.height - assetsTreeOffsetY), scrollPos, new Rect(0, 0, contentWidth, contentHeight - assetsTreeOffsetY), - false , false + false, false ); } @@ -502,44 +666,87 @@ class AssetBrowser : EditorWindow private void OnHeader() { float scrollY = scrollPos.y; - drawer.DrawButtonMid(new Rect(ColumOffsetX[Colum.Name], headerOffsetY + scrollY, ColumWidth[Colum.Name], kLineHeight), ColumHeader[Colum.Name]); - drawer.DrawButtonMid(new Rect(ColumOffsetX[Colum.Ref], headerOffsetY + scrollY, ColumWidth[Colum.Ref], kLineHeight), ColumHeader[Colum.Ref]); - drawer.DrawButtonMid(new Rect(ColumOffsetX[Colum.RevRef], headerOffsetY + scrollY, ColumWidth[Colum.RevRef], kLineHeight), ColumHeader[Colum.RevRef]); - drawer.DrawButtonMid(new Rect(ColumOffsetX[Colum.Type], headerOffsetY + scrollY, ColumWidth[Colum.Type], kLineHeight), ColumHeader[Colum.Type]); - drawer.DrawButtonMid(new Rect(ColumOffsetX[Colum.DiskSize], headerOffsetY + scrollY, ColumWidth[Colum.DiskSize], kLineHeight), ColumHeader[Colum.DiskSize]); - drawer.DrawButtonMid(new Rect(ColumOffsetX[Colum.Path], headerOffsetY + scrollY, ColumWidth[Colum.Path], kLineHeight), ColumHeader[Colum.Path]); + bool clickName = false; + bool clickRef = false; + bool clickRevRef = false; + bool clickType = false; + bool clickDiskSize = false; + bool clickPath = false; + drawer.DrawButtonMid(new Rect(ColumOffsetX[Colum.Name], headerOffsetY + scrollY, ColumWidth[Colum.Name], kLineHeight), ColumHeader[Colum.Name], out clickName); + drawer.DrawButtonMid(new Rect(ColumOffsetX[Colum.Ref], headerOffsetY + scrollY, ColumWidth[Colum.Ref], kLineHeight), ColumHeader[Colum.Ref], out clickRef); + drawer.DrawButtonMid(new Rect(ColumOffsetX[Colum.RevRef], headerOffsetY + scrollY, ColumWidth[Colum.RevRef], kLineHeight), ColumHeader[Colum.RevRef], out clickRevRef); + drawer.DrawButtonMid(new Rect(ColumOffsetX[Colum.Type], headerOffsetY + scrollY, ColumWidth[Colum.Type], kLineHeight), ColumHeader[Colum.Type], out clickType); + drawer.DrawButtonMid(new Rect(ColumOffsetX[Colum.DiskSize], headerOffsetY + scrollY, ColumWidth[Colum.DiskSize], kLineHeight), ColumHeader[Colum.DiskSize], out clickDiskSize); + drawer.DrawButtonMid(new Rect(ColumOffsetX[Colum.Path], headerOffsetY + scrollY, ColumWidth[Colum.Path], kLineHeight), ColumHeader[Colum.Path], out clickPath); + if(clickName) + { + orderBase = OrderBase.Name; + orderName = -orderName; + ReorderTreeBuffer(); + } + else if (clickRef) + { + orderBase = OrderBase.Ref; + orderRef = -orderRef; + ReorderTreeBuffer(); + } + else if (clickRevRef) + { + orderBase = OrderBase.RevRef; + orderRevRef = -orderRevRef; + ReorderTreeBuffer(); + } + else if (clickType) + { + orderBase = OrderBase.Type; + orderType = -orderType; + ReorderTreeBuffer(); + } + else if (clickDiskSize) + { + orderBase = OrderBase.DiskSize; + orderDiskSize = -orderDiskSize; + ReorderTreeBuffer(); + } + else if (clickPath) + { + orderBase = OrderBase.Path; + orderPath = -orderPath; + ReorderTreeBuffer(); + } } private void OnAssetsTree() { int count = 0; - foreach(FileTree.Node node in assetsTree.root) + foreach (FileTree.Node node in assetsTreeBuffer.root) { DrawNode(node, 0, ref count); } } - private bool Filter(FileTree.Node node, int hierachy) + private bool Filter(FileTree.Node node) { - if(hierachy == 0) - { - AssetData asset; - if (!AssetDataManager.AllAssets.TryGetValue(node.GUID, out asset)) - return false; - // 文件类型过滤 - if (asset.FileType == AssetData.AssetType.Scene && !filterScene) return false; - else if (asset.FileType == AssetData.AssetType.Prefab&& !filterPrefab) return false; - else if (asset.FileType == AssetData.AssetType.Material&& !filterMaterial) return false; - else if (asset.FileType == AssetData.AssetType.Asset&& !filterAsset) return false; - else if (asset.FileType == AssetData.AssetType.Mesh&& !filterMesh) return false; - else if (asset.FileType == AssetData.AssetType.CSV&& !filterCSV) return false; - else if (asset.FileType == AssetData.AssetType.Script&& !filterScript) return false; - else if (asset.FileType == AssetData.AssetType.Shader&& !filterShader) return false; - else if (asset.FileType == AssetData.AssetType.Texture&& !filterTexture) return false; - // 文件名 - if (asset.Name.IndexOf(filterFile) == -1) - return false; - } + AssetData asset; + AssetDataManager assetDataManager = AssetDataManager.Get(); + if (!assetDataManager.AllAssets.TryGetValue(node.GUID, out asset)) + return false; + // 文件类型过滤 + if (asset.FileType == AssetData.AssetType.Scene && !filterScene) return false; + else if (asset.FileType == AssetData.AssetType.Prefab && !filterPrefab) return false; + else if (asset.FileType == AssetData.AssetType.Material && !filterMaterial) return false; + else if (asset.FileType == AssetData.AssetType.Asset && !filterAsset) return false; + else if (asset.FileType == AssetData.AssetType.Mesh && !filterMesh) return false; + else if (asset.FileType == AssetData.AssetType.CSV && !filterCSV) return false; + else if (asset.FileType == AssetData.AssetType.Script && !filterScript) return false; + else if (asset.FileType == AssetData.AssetType.Shader && !filterShader) return false; + else if (asset.FileType == AssetData.AssetType.Texture && !filterTexture) return false; + // 文件路径 + if (asset.AssetPath.IndexOf(filterdirectory) == -1) + return false; + // 文件名 + if (asset.Name.IndexOf(filterFile) == -1) + return false; return true; } @@ -547,8 +754,6 @@ class AssetBrowser : EditorWindow // 按照深度绘制 private void DrawNode(FileTree.Node node, int hierachy, ref int count) { - if (!Filter(node, hierachy)) - return; ++count; contentHeight = count * kLineHeight + assetsTreeOffsetY; DrawAssetInfo(node, hierachy, count - 1); @@ -565,35 +770,52 @@ class AssetBrowser : EditorWindow { Drawer drawer = Drawer.Get(); AssetData asset; - if (!AssetDataManager.AllAssets.TryGetValue(node.GUID, out asset)) + AssetDataManager assetDataManager = AssetDataManager.Get(); + if (!assetDataManager.AllAssets.TryGetValue(node.GUID, out asset)) return; int offsetY = index * kLineHeight; // 绘制背景 drawer.DrawBackground(new Rect(0, offsetY, contentWidth, kLineHeight), (index & 1) == 1 ? drawer.ColorHeavy : drawer.ColorLight); + // 绘制定位按钮 + if(selectedNode == node) + { + bool ping = false; + drawer.DrawPing(new Rect(hierachy * kTabWidth, offsetY, 10, kLineHeight), ref ping); + if (ping) + { + Object obj = AssetDatabase.LoadAssetAtPath(asset.AssetPath, asset.ObjType); + if (obj) + { + EditorGUIUtility.PingObject(obj); + } + } + } // 绘制折叠按钮 if (node.Children.Count > 0) - drawer.DrawFoldout(new Rect(hierachy * kTabWidth, offsetY, 10, kLineHeight), ref node.Foldout); + drawer.DrawFoldout(new Rect(hierachy * kTabWidth + 7, offsetY, kLineHeight, kLineHeight), ref node.Foldout); // 绘制选择按钮 bool clicked; - drawer.DrawSelector(new Rect(hierachy * kTabWidth + 12, offsetY, contentWidth, kLineHeight), selectedNode == node, out clicked); + drawer.DrawSelector(new Rect(hierachy * kTabWidth + 19 + 7, offsetY, contentWidth, kLineHeight), selectedNode == node, out clicked); if (clicked) { - if(selectedNode != node) + if (selectedNode != node) selectedNode = node; else { - AssetReverse.Show(node.GUID); - selectedNode = null; + AssetReverse.ShowWindow(node.GUID); + selectedNode = null; } - } + } + if (selectedNode == node) + drawer.SetTextColor(Color.white); // 绘制图标 - drawer.DrawAssetIcon(new Rect(hierachy * kTabWidth + 12, offsetY, ColumWidth[Colum.Name], kLineHeight), asset); + drawer.DrawAssetIcon(new Rect(hierachy * kTabWidth + 19 + 7, offsetY, ColumWidth[Colum.Name], kLineHeight), asset); // 绘制引用数 drawer.DrawLabel(new Rect(ColumOffsetX[Colum.Ref], offsetY, 100, kLineHeight), asset.RefCount.ToString()); // 绘制反向引用数 List<string> revRef; int revRefCount = 0; - if (AssetDataManager.AssetsReverse.TryGetValue(node.GUID, out revRef)) + if (assetDataManager.AssetsReverse.TryGetValue(node.GUID, out revRef)) revRefCount = revRef.Count; drawer.DrawLabel(new Rect(ColumOffsetX[Colum.RevRef], offsetY, 100, kLineHeight), revRefCount.ToString()); // 绘制资源类型 @@ -602,41 +824,104 @@ class AssetBrowser : EditorWindow drawer.DrawLabel(new Rect(ColumOffsetX[Colum.DiskSize], offsetY, 100, kLineHeight), asset.DiskSizeStr); // 绘制资源路径 drawer.DrawLabel(new Rect(ColumOffsetX[Colum.Path], offsetY, 1000, kLineHeight), asset.AssetPath); + if (selectedNode == node) + drawer.ResetTextColor(); } private void ProcessAssets() { AssetDataManager assetManager = AssetDataManager.Get(); assetManager.ClearAssets(); - assetManager.LoadAssets(assetManager.AssetPathToFullPath("Assets/" + directory)); + assetManager.LoadAssets(assetManager.AssetPathToFullPath("Assets/")); } private void ProcessTree() { AssetDataManager assetManager = AssetDataManager.Get(); assetsTree.root.Clear(); - for(int i = 0; i < AssetData.AssetTypeCount; ++i) + for (int i = 0; i < (int)AssetData.AssetType.TypeCount; ++i) { - Dictionary<string, AssetData> assets = AssetDataManager.Assets[i]; - foreach(var asset in assets) + Dictionary<string, AssetData> assets = assetManager.Assets[i]; + foreach (var asset in assets) { AssetData data = asset.Value; FileTree.Node node = ProcessNode(data); - assetsTree.root.Add(node); + assetsTree.root.Add(node); } } + ProcessTreeBuffer(); + } + + // 文件树缓冲 + private void ProcessTreeBuffer() + { + assetsTreeBuffer.root.Clear(); + foreach(FileTree.Node node in assetsTree.root) + { + if(!Filter(node)) + continue; + assetsTreeBuffer.root.Add(node); + } + orderBase = OrderBase.Path; + orderPath = 1; + ReorderTreeBuffer(); + } + + private int clamp(int n) + { + if (n > 0) return 1; + else if (n < 0) return -1; + else return 0; + } + + // Tree Buffer重新排序 + private void ReorderTreeBuffer() + { + assetsTreeBuffer.root.Sort((FileTree.Node a, FileTree.Node b) => + { + AssetData aa, ab; + AssetDataManager.Get().AllAssets.TryGetValue(a.GUID, out aa); + AssetDataManager.Get().AllAssets.TryGetValue(b.GUID, out ab); + if(aa == null || ab == null) + return 0; + if (orderBase == OrderBase.Name) return clamp(orderName * aa.Name.CompareTo(ab.Name)); + else if (orderBase == OrderBase.Ref) return clamp(orderRef * (aa.RefCount - ab.RefCount)); + else if (orderBase == OrderBase.RevRef) + { + List<string> ra, rb; + int rac = 0, rbc = 0; + AssetDataManager.Get().AssetsReverse.TryGetValue(a.GUID, out ra); + AssetDataManager.Get().AssetsReverse.TryGetValue(b.GUID, out rb); + if (ra != null) + rac = ra.Count; + if (rb != null) + rbc = rb.Count; + return clamp(orderRevRef * (rac - rbc)); + } + else if (orderBase == OrderBase.Type) + { + if(aa.FileType == ab.FileType) + { + return clamp(orderType * ((int)aa.SubFileType - (int)ab.SubFileType)); + } + return clamp(orderType * ((int)aa.FileType - (int)ab.FileType)); + } + else if (orderBase == OrderBase.DiskSize) return clamp(orderDiskSize * (int)(aa.DiskSize - ab.DiskSize)); + else if (orderBase == OrderBase.Path) return clamp(orderPath * aa.AssetPath.CompareTo(ab.AssetPath)); + else return 1; + }); } private FileTree.Node ProcessNode(AssetData data) { AssetDataManager assetManager = AssetDataManager.Get(); FileTree.Node node = new FileTree.Node(data.GUID); - foreach(List<string> deps in data.Dependencies) + foreach (List<string> deps in data.Dependencies) { - foreach(string guid in deps) + foreach (string guid in deps) { AssetData dep; - if(AssetDataManager.AllAssets.TryGetValue(guid, out dep)) + if (assetManager.AllAssets.TryGetValue(guid, out dep)) { FileTree.Node child = ProcessNode(dep); node.Children.Add(child); @@ -648,56 +933,119 @@ class AssetBrowser : EditorWindow } -class AssetReverse : EditorWindow +// 反向查找 +public class AssetReverse : EditorWindow { - private static AssetReverse editor; private static Drawer drawer; - + private static AssetReverse editor; + private static AssetDataManager assetDataManager; private static string GUID; - private static AssetData asset; - private Vector2 scrollPos = new Vector2(0, 0); - - private int kLineHeight = 20; - private int contentHeight = 0; - - public static void Show(string guid) + private static AssetData resource = null; + public static void ShowWindow(string guid) { editor = GetWindow<AssetReverse>(); editor.titleContent = new GUIContent("Asset Reverse"); + drawer = Drawer.Get(); + assetDataManager = AssetDataManager.Get(); + AdjustkColumOffset(); GUID = guid; - if(AssetDataManager.AllAssets.TryGetValue(GUID, out asset)) - { - } - Drawer dawer = Drawer.Get(); + if (!assetDataManager.AllAssets.TryGetValue(GUID, out resource)) + resource = null; } - public void OnGUI() + private enum Colums + { + cName, // "资源列表和引用关系" + cLocation, // "资源位置" + } + + private static readonly Dictionary<Colums, string> kColumHeader = new Dictionary<Colums, string>{ + {Colums.cName, "资源名"}, + {Colums.cLocation, "位置"}, + }; + + private static readonly Dictionary<Colums, int> kColumWidth = new Dictionary<Colums, int>{ + {Colums.cName, 300}, + {Colums.cLocation, 500}, + }; + + private static Dictionary<Colums, int> kColumOffset = null; + + private static void AdjustkColumOffset() { - if (asset == null) + if (kColumOffset != null) return; - drawer = Drawer.Get(); - drawer.DrawAssetIcon(new Rect(0, 0, 200, kLineHeight), asset); - scrollPos = GUI.BeginScrollView(new Rect(0, kLineHeight, editor.position.width, editor.position.height - kLineHeight), scrollPos, new Rect(0, 0, 1500, contentHeight)); - // 标题 - drawer.DrawButtonMid(new Rect(0, 0, 400, 20), "资源名"); - drawer.DrawButtonMid(new Rect(400, 0, 400, 20), "资源路径"); - // - List<string> revRef; - if(AssetDataManager.AssetsReverse.TryGetValue(GUID, out revRef)) + kColumOffset = new Dictionary<Colums, int>(); + kColumOffset.Clear(); + kColumOffset.Add(Colums.cName, 0); + kColumOffset.Add(Colums.cLocation, kColumWidth[Colums.cName] + kColumOffset[Colums.cName]); + } + + private Rect windowRect; + private readonly int kLineHeight = 20; + private Vector2 scrollPos = new Vector2(0, 0); + + private float ContentWidth = 1200; + private float ContentHeight = 20; + private int kListOffsetY = 40; // 2*kLineHeight + + void OnGUI() + { + if (resource == null || GUID == null) + return; + AdjustWindowRect(); + DrawHeader(); + BeginScrollView(); + DrawRevDepend(); + EndScrollView(); + } + + private void DrawHeader() + { + GUIContent content = EditorGUIUtility.ObjectContent(null, resource.ObjType); + content.text = resource.AssetPath; + GUI.Label(new Rect(0, 0, 1000, kLineHeight), content); + GUI.Button(new Rect(kColumOffset[Colums.cName], kLineHeight, kColumWidth[Colums.cName], kLineHeight), kColumHeader[Colums.cName], EditorStyles.miniButtonMid); + GUI.Button(new Rect(kColumOffset[Colums.cLocation], kLineHeight, windowRect.width - kColumWidth[Colums.cName], kLineHeight), kColumHeader[Colums.cLocation], EditorStyles.miniButtonMid); + } + + private void DrawRevDepend() + { + List<string> revDeps; + if (assetDataManager.AssetsReverse.TryGetValue(GUID, out revDeps)) { + int yoffset = 0; int count = 0; - foreach(string guid in revRef) + ContentHeight = 0; + foreach (string guid in revDeps) { - AssetData data; - if(AssetDataManager.AllAssets.TryGetValue(guid, out data)) + AssetData resource; + if (assetDataManager.AllAssets.TryGetValue(guid, out resource)) { - drawer.DrawAssetIcon(new Rect(0, kLineHeight + count * kLineHeight, 400, kLineHeight), data); - drawer.DrawLabel(new Rect(400, kLineHeight + count * kLineHeight, 400, kLineHeight), data.AssetPath); + drawer.DrawBackground(new Rect(0, yoffset, ContentWidth, kLineHeight), (count & 1) == 1 ? drawer.ColorHeavy : drawer.ColorLight); + drawer.DrawAssetIcon(new Rect(0, yoffset, 1000, kLineHeight), resource); + drawer.DrawLabel(new Rect(kColumOffset[Colums.cLocation], yoffset, 1000, kLineHeight), resource.AssetPath); + yoffset += kLineHeight; + ContentHeight += kLineHeight; ++count; - contentHeight = count * kLineHeight + kLineHeight; } } } + } + + private void BeginScrollView() + { + scrollPos = GUI.BeginScrollView(new Rect(0, kLineHeight * 2, windowRect.width, windowRect.height - kListOffsetY), scrollPos, new Rect(0, 0, windowRect.width, ContentHeight), false, true); + } + + private void EndScrollView() + { GUI.EndScrollView(); } + + private void AdjustWindowRect() + { + windowRect = editor.position; + ContentWidth = windowRect.width; + } } |