/////////////////////////////////////////////////// // author: chai // email: chaifix@163.com // // Send me email if you have any ideas or problems. /////////////////////////////////////////////////// using UnityEditor; using UnityEngine; using System; using System.IO; using System.Collections; using System.Collections.Generic; using Object = UnityEngine.Object; class AssetData { public enum AssetType { Scene = 0, Prefab, Mesh, Material, Asset, Texture, Shader, Script, CSV, TypeCount, Unknown = 255, } // for sorting in same asset type situation public enum SubType { // Texture png = 0, jpg, bmp, tga, // Mesh fbx, FBX, // Unknown = 255, } public AssetData(FileSystemInfo f) { for (int i = 0; i < (int)AssetType.TypeCount; ++i) Dependencies[i] = new List(); AssetDataManager manager = AssetDataManager.Get(); AssetPath = manager.FullPathToAssetPath(f.FullName); GUID = AssetDatabase.AssetPathToGUID(AssetPath); Name = f.Name; ObjType = AssetDatabase.GetMainAssetTypeAtPath(AssetPath); Extension = f.Extension; 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); if (guid == GUID) continue; string extension = manager.GetExtension(path); AssetType type = ExtensionToAssetType(extension); if (type == AssetType.Unknown) continue; Dependencies[(int)type].Add(guid); ++RefCount; List data; if (!manager.AssetsReverse.TryGetValue(guid, out data)) { data = new List(); manager.AssetsReverse.Add(guid, data); } data.Add(GUID); } Obj = AssetDatabase.LoadAssetAtPath(AssetPath, ObjType); FileInfo finfo = new FileInfo(f.FullName); DiskSize = finfo.Length; DiskSizeStr = EditorUtility.FormatBytes(DiskSize); } #region asset properties public string GUID; public string Name; public int RefCount = 0; //public int RevRefCount = 0; public long DiskSize; public string DiskSizeStr; public string AssetPath; public Object Obj = null; public Type ObjType; public string Extension; public AssetType FileType; public SubType SubFileType; public List[] Dependencies = new List[(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; else if (Extension == ".tga") subType = SubType.tga; // 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; else if (extension == ".prefab") return AssetType.Prefab; else if (extension == ".mat") return AssetType.Material; else if (extension == ".asset") return AssetType.Asset; else if (extension == ".fbx" || extension == ".FBX") return AssetType.Mesh; else if (extension == ".png" || extension == ".jpg" || extension == ".bmp" || extension == ".tga") return AssetType.Texture; else if (extension == ".shader") return AssetType.Shader; else if (extension == ".cs") return AssetType.Script; else if (extension == ".csv") return AssetType.CSV; else return AssetType.Unknown; } } class AssetDataManager { private static AssetDataManager manager; public static AssetDataManager Get() { if (manager == null) manager = new AssetDataManager(); return manager; } public AssetDataManager() { for (int i = 0; i < (int)AssetData.AssetType.TypeCount; ++i) Assets[i] = new Dictionary(); } #region Asset Dictionary // all assets public Dictionary AllAssets = new Dictionary(); // assets by type public Dictionary[] Assets = new Dictionary[(int)AssetData.AssetType.TypeCount]; // reverse reference public Dictionary> AssetsReverse = new Dictionary>(); #endregion #region file extensions public static List ValidExtension = new List { ".unity", // scene ".prefab", // prefab ".mat", // material ".asset", // asset ".fbx", ".FBX", // mesh ".png", ".jpg", ".bmp", ".tga", // texture ".shader", // shader ".cs", // script ".csv" // CSV }; public string GetExtension(string path) { if (path == null || path.Length <= 0) return null; 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) { string extension = GetExtension(file); foreach (var ext in ValidExtension) { if (ext == extension) return true; } return false; } public List InvalidFolder = new List { }; public bool IsValidFolder(string folderName) { foreach (var dir in InvalidFolder) { if (dir == folderName) return false; } return true; } #endregion public string FullPathToAssetPath(string fullpath) { string path = "Assets" + fullpath.Replace(Application.dataPath.Replace("/", "\\"), ""); return path; } public string AssetPathToFullPath(string assetpath) { string fullpath = Application.dataPath.Replace("/Assets", "") + "/" + assetpath; return fullpath; } public void LoadAssets(string fullpath) { DirectoryInfo directoryInfo = new DirectoryInfo(fullpath); FileSystemInfo[] filesInfo = directoryInfo.GetFileSystemInfos(); foreach (FileSystemInfo f in filesInfo) { if (f is DirectoryInfo && IsValidFolder(f.Name)) { LoadAssets(f.FullName); } else if (f.Extension != ".meta" && IsValidFile(f.Name)) { AssetData asset = new AssetData(f); AllAssets.Add(asset.GUID, asset); Assets[(int)asset.FileType].Add(asset.GUID, asset); } } } public string FormatPath(string assetpath) { string path = assetpath.Replace('/', '\\'); path = path.Replace("\\\\", "\\"); return path; } public void ClearAssets() { AllAssets.Clear(); foreach (var assets in Assets) assets.Clear(); AssetsReverse.Clear(); } } class Drawer { private 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 width, int height, Color color) { 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; public static Drawer Get() { if (drawer == null) drawer = new Drawer(); return drawer; } public void DrawButtonMid(Rect rect, string content, out bool click) { click = GUI.Button(rect, content, EditorStyles.miniButtonMid); } public void DrawButton(Rect rect, string content, out bool click) { click = GUI.Button(rect, content); } public void DrawLabel(Rect rect, string content) { GUI.Label(rect, content); } public void DrawTextfield(Rect rect, string content, ref string value) { value = GUI.TextField(rect, content); } public void DrawCheckBox(Rect rect, string content, bool check, ref bool ischeck) { ischeck = GUI.Toggle(rect, check, content); } public void DrawBackground(Rect rect, Color col) { Color old = GUI.backgroundColor; GUI.backgroundColor = col; GUI.Box(rect, ""); GUI.backgroundColor = old; } public void DrawFoldout(Rect rect, ref bool foldout) { Texture2D foldIcon = foldout ? IconFoldout : IconFoldup; bool clicked = GUI.Button(rect, foldIcon, MidAlignment); if (clicked) foldout = !foldout; } public void DrawAssetIcon(Rect rect, AssetData asset, bool thumb) { GUIContent content = EditorGUIUtility.ObjectContent(thumb ? asset.Obj : null, asset.ObjType); content.text = asset.Name; GUI.Label(rect, content); } public void DrawSelector(Rect rect, bool selected, out bool clicked) { 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 configuration 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 draw state private Color drawColor = new Color(); #endregion } // file tree class FileTree { public class Node { public Node(string guid) { GUID = guid; Foldout = false; } public bool Foldout; // fold out or not public string GUID; // GUID public List Children = new List(); // sub node } public List root = new List(); } class AssetBrowser : EditorWindow { private static AssetBrowser editor; private static Drawer drawer; private static AssetBrowser Get() { if (editor == null) editor = GetWindow(); return editor; } #region file tree private FileTree assetsTree = new FileTree(); private FileTree assetsTreeBuffer = new FileTree(); #endregion #region GUI configurations private Rect window = new Rect(); private int contentWidth = 1600; private int contentHeight = 1000; private readonly int kLineHeight = 20; // line height private Vector2 scrollPos = new Vector2(0, 0); private int directoryOffsetY = 5; // assets tree y offset private int filtersOffsetY = 27; // filters y offset private int headerOffsetY = 50; // header y offset private int assetsTreeOffsetY = 70; // list y offset private int kTabWidth = 13; #endregion #region data private FileTree.Node selectedNode = null; #endregion #region thumbs private bool thumbs = true; #endregion #region filters private string filterdirectory = ""; private string filterFile = ""; private bool filterScene = false; private bool filterPrefab = false; private bool filterMaterial = false; private bool filterAsset = false; private bool filterMesh = false; private bool filterTexture = false; private bool filterShader = false; private bool filterScript = false; private bool filterCSV = false; #endregion #region sort 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("Window/Asset Browser", false, 6)] public static void Show() { editor = GetWindow(); editor.titleContent = new GUIContent("Asset Browser"); drawer = Drawer.Get(); } private enum Colum { Name, // Asset Name Ref, // Reference Count RevRef, // Referenced Count Type, // Asset Type DiskSize, // Asset's Disk Size Path, // Location } private Dictionary ColumHeader = new Dictionary { {Colum.Name, "Asset Name"}, {Colum.Ref, "Reference Count"}, {Colum.RevRef, "Referenced Count"}, {Colum.Type, "Asset Type"}, {Colum.DiskSize, "Disk Size"}, {Colum.Path, "Location"}, }; private Dictionary ColumWidth = new Dictionary { {Colum.Name, 400}, {Colum.Ref, 100}, {Colum.RevRef, 100}, {Colum.Type, 100}, {Colum.DiskSize, 100}, {Colum.Path, 800}, }; private Dictionary ColumOffsetX = null; private void AdjustColumOffsetX() { if (ColumOffsetX != null) return; ColumOffsetX = new Dictionary(); 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]); ColumOffsetX.Add(Colum.Type, ColumOffsetX[Colum.RevRef] + ColumWidth[Colum.RevRef]); ColumOffsetX.Add(Colum.DiskSize, ColumOffsetX[Colum.Type] + ColumWidth[Colum.Type]); ColumOffsetX.Add(Colum.Path, ColumOffsetX[Colum.DiskSize] + ColumWidth[Colum.DiskSize]); } private void AdjustWindow() { window = editor.position; } public void OnGUI() { if (editor == null) editor = GetWindow(); if (drawer == null) drawer = Drawer.Get(); AdjustColumOffsetX(); AdjustWindow(); BeginScrollView(); OnToolset(); OnAsset(); EndScrollView(); } private void BeginScrollView() { scrollPos = GUI.BeginScrollView(new Rect(0, 0, window.width, window.height), scrollPos, new Rect(0, 0, contentWidth, contentHeight), true, true); } private void EndScrollView() { GUI.EndScrollView(); } private void OnToolset() { OnDirectory(); OnFilters(); } private void OnDirectory() { float offsetY = directoryOffsetY + scrollPos.y; Rect dragRect = new Rect(0, offsetY, 1000, 20); string olddirectory = filterdirectory; drawer.DrawLabel(new Rect(0, offsetY, 105, kLineHeight), "Directory Assets\\"); drawer.DrawTextfield(new Rect(105, offsetY, 250, kLineHeight), filterdirectory, ref filterdirectory); if (filterdirectory == null) filterdirectory = ""; // drag 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(360, offsetY, 50, kLineHeight), "Load", out load); if (load) { ProcessAssets(); ProcessTree(); EditorUtility.DisplayDialog("Load done", "Load done", "OK"); } drawer.DrawCheckBox(new Rect(420, offsetY, 100, kLineHeight), "thumbnail", thumbs, ref thumbs); } 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; // match file drawer.DrawLabel(new Rect(0, filtersOffsetY + scrollPos.y, 100, kLineHeight), "Match Files"); drawer.DrawTextfield(new Rect(67, filtersOffsetY + scrollPos.y, 150, kLineHeight), filterFile, ref filterFile); // type filter float offsetX = 250; float offsetY = filtersOffsetY + scrollPos.y; int width = 70; drawer.DrawCheckBox(new Rect(offsetX, offsetY, width, kLineHeight), "Scene", 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), "Material", filterMaterial, ref filterMaterial); drawer.DrawCheckBox(new Rect(offsetX + width * 3, offsetY, width, kLineHeight), "Asset", filterAsset, ref filterAsset); drawer.DrawCheckBox(new Rect(offsetX + width * 4, offsetY, width, kLineHeight), "Mesh", filterMesh, ref filterMesh); drawer.DrawCheckBox(new Rect(offsetX + width * 5, offsetY, width, kLineHeight), "Texture", filterTexture, ref filterTexture); drawer.DrawCheckBox(new Rect(offsetX + width * 6, offsetY, width, kLineHeight), "Shader", filterShader, ref filterShader); drawer.DrawCheckBox(new Rect(offsetX + width * 7, offsetY, width, kLineHeight), "Script", filterScript, ref filterScript); drawer.DrawCheckBox(new Rect(offsetX + width * 8, offsetY, width, kLineHeight), "CSV", filterCSV, ref filterCSV); // refresh tree buffer 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() { OnHeader(); BeginFileTreeView(); OnAssetsTree(); EndFileTreeView(); } private void BeginFileTreeView() { scrollPos = GUI.BeginScrollView( new Rect(scrollPos.x, scrollPos.y + assetsTreeOffsetY, window.width, window.height - assetsTreeOffsetY), scrollPos, new Rect(0, 0, contentWidth, contentHeight - assetsTreeOffsetY), false, false ); } private void EndFileTreeView() { GUI.EndScrollView(); } private void OnHeader() { float scrollY = scrollPos.y; 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 assetsTreeBuffer.root) { DrawNode(node, 0, ref count); } } private bool Filter(FileTree.Node node) { AssetData asset; AssetDataManager assetDataManager = AssetDataManager.Get(); if (!assetDataManager.AllAssets.TryGetValue(node.GUID, out asset)) return false; // type 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; // directory if (asset.AssetPath.IndexOf(filterdirectory) == -1) return false; // asset name if (asset.Name.IndexOf(filterFile) == -1) return false; return true; } private void DrawNode(FileTree.Node node, int hierachy, ref int count) { ++count; contentHeight = count * kLineHeight + assetsTreeOffsetY; DrawAssetInfo(node, hierachy, count - 1); if (!node.Foldout || node.Children.Count == 0) return; foreach (FileTree.Node child in node.Children) { DrawNode(child, hierachy + 1, ref count); } } private void DrawAssetInfo(FileTree.Node node, int hierachy, int index) { Drawer drawer = Drawer.Get(); AssetData asset; AssetDataManager assetDataManager = AssetDataManager.Get(); if (!assetDataManager.AllAssets.TryGetValue(node.GUID, out asset)) return; int offsetY = index * kLineHeight; // draw background drawer.DrawBackground(new Rect(0, offsetY, contentWidth, kLineHeight), (index & 1) == 1 ? drawer.ColorHeavy : drawer.ColorLight); // draw ping button if (selectedNode == node) { bool ping = false; drawer.DrawPing(new Rect(hierachy * kTabWidth, offsetY, 10, kLineHeight), ref ping); if (ping) { Object obj = asset.Obj; if (obj) { EditorGUIUtility.PingObject(obj); } } } // draw foldout button if (node.Children.Count > 0) drawer.DrawFoldout(new Rect(hierachy * kTabWidth + 7, offsetY, kLineHeight, kLineHeight), ref node.Foldout); // draw selector bool clicked; drawer.DrawSelector(new Rect(hierachy * kTabWidth + 17 + 7, offsetY, contentWidth, kLineHeight), selectedNode == node, out clicked); if (clicked) { if (selectedNode != node) selectedNode = node; else { AssetReverse.ShowWindow(node.GUID, thumbs); selectedNode = null; } } if (selectedNode == node) drawer.SetTextColor(Color.white); // draw asset icon drawer.DrawAssetIcon(new Rect(hierachy * kTabWidth + 17 + 7, offsetY, ColumWidth[Colum.Name], kLineHeight), asset, thumbs); // draw reference count drawer.DrawLabel(new Rect(ColumOffsetX[Colum.Ref], offsetY, 100, kLineHeight), asset.RefCount.ToString()); // draw referenced count List revRef; int revRefCount = 0; if (assetDataManager.AssetsReverse.TryGetValue(node.GUID, out revRef)) revRefCount = revRef.Count; drawer.DrawLabel(new Rect(ColumOffsetX[Colum.RevRef], offsetY, 100, kLineHeight), revRefCount.ToString()); // draw asset type drawer.DrawLabel(new Rect(ColumOffsetX[Colum.Type], offsetY, 100, kLineHeight), asset.Extension); // draw disk size drawer.DrawLabel(new Rect(ColumOffsetX[Colum.DiskSize], offsetY, 100, kLineHeight), asset.DiskSizeStr); // draw location 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/")); } private void ProcessTree() { AssetDataManager assetManager = AssetDataManager.Get(); assetsTree.root.Clear(); for (int i = 0; i < (int)AssetData.AssetType.TypeCount; ++i) { Dictionary assets = assetManager.Assets[i]; foreach (var asset in assets) { AssetData data = asset.Value; FileTree.Node node = ProcessNode(data); assetsTree.root.Add(node); } } ProcessTreeBuffer(); } // file tree buffer 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; } // sort 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 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 deps in data.Dependencies) { foreach (string guid in deps) { AssetData dep; if (assetManager.AllAssets.TryGetValue(guid, out dep)) { FileTree.Node child = ProcessNode(dep); node.Children.Add(child); } } } return node; } } public class AssetReverse : EditorWindow { private static Drawer drawer; private static AssetReverse editor; private static AssetDataManager assetDataManager; private static string GUID; private static AssetData resource = null; private static bool thumb; public static void ShowWindow(string guid, bool thumbs) { editor = GetWindow(); editor.titleContent = new GUIContent("Asset Reverse"); drawer = Drawer.Get(); assetDataManager = AssetDataManager.Get(); AdjustkColumOffset(); thumb = thumbs; GUID = guid; if (!assetDataManager.AllAssets.TryGetValue(GUID, out resource)) resource = null; } private enum Colums { cName, // "asset name" cLocation, // "location" } private static readonly Dictionary kColumHeader = new Dictionary{ {Colums.cName, "Asset Name"}, {Colums.cLocation, "Location"}, }; private static readonly Dictionary kColumWidth = new Dictionary{ {Colums.cName, 300}, {Colums.cLocation, 500}, }; private static Dictionary kColumOffset = null; private static void AdjustkColumOffset() { if (kColumOffset != null) return; kColumOffset = new Dictionary(); 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 revDeps; if (assetDataManager.AssetsReverse.TryGetValue(GUID, out revDeps)) { int yoffset = 0; int count = 0; ContentHeight = 0; foreach (string guid in revDeps) { AssetData resource; if (assetDataManager.AllAssets.TryGetValue(guid, out resource)) { drawer.DrawBackground(new Rect(0, yoffset, ContentWidth, kLineHeight), (count & 1) == 1 ? drawer.ColorHeavy : drawer.ColorLight); drawer.DrawAssetIcon(new Rect(0, yoffset, 1000, kLineHeight), resource, thumb); drawer.DrawLabel(new Rect(kColumOffset[Colums.cLocation], yoffset, 1000, kLineHeight), resource.AssetPath); yoffset += kLineHeight; ContentHeight += kLineHeight; ++count; } } } } 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; } }