天天看點

Unity3D Editor 編輯器擴充實戰 Project視窗全檔案夾折疊

環境:Unity2017.2 語言:C#

總起:

在使用Project視窗時,總在不停地找資源和找代碼過程中,将Project中的檔案夾展開,導緻視窗的混亂,雖然在按住Alt的情況下點選三角能夠全部折疊一組的檔案夾,但是這樣做也比較麻煩。

是以有沒有辦法按下一個快捷鍵将所有檔案夾全部折疊呢?

今天就為大家帶來本人最新研究的一種對Editor的擴充(僅在2017版本中試驗過,因為用到了反射技術是以不保證其他版本通用)。

折疊腳本:

建立Editor檔案夾,再在其中建立一個腳本:

using System.Collections;
using System.Linq;
using System.Reflection;
using UnityEditor;

// CollapseFolders.cs
public static class CollapseFolders
{
    [MenuItem("Assets/折疊所有檔案夾 &c", false, 30)]
    public static void SetProjectBrowserFoldersCollapsed()
    {
        var assembly = Assembly.GetAssembly(typeof(Editor));
        var type = assembly.GetType("UnityEditor.ProjectBrowser");

        if (type == null)
            return;

        var browserField = type.GetField("s_LastInteractedProjectBrowser", BindingFlags.Public | BindingFlags.Static);
        var browser = browserField.GetValue(null);

        if (browser == null)
            return;

        // 确定視窗模式是否是單列
        var modeField = type.GetField("m_ViewMode", BindingFlags.NonPublic | BindingFlags.Instance);
        bool isOne = (int) modeField.GetValue(browser) == 0;

        // 擷取檔案夾樹
        var treeField = type.GetField(isOne ? "m_AssetTree" : "m_FolderTree", BindingFlags.NonPublic | BindingFlags.Instance);
        var tree = treeField.GetValue(browser);

        var dataProperty = treeField.FieldType.GetProperty("data", BindingFlags.Instance | BindingFlags.Public);
        var data = dataProperty.GetValue(tree, null);

        var getRowsMethod = dataProperty.PropertyType.GetMethod("GetRows", BindingFlags.Instance | BindingFlags.Public);
        var setExpandedMethods = dataProperty.PropertyType.GetMethods(BindingFlags.Instance | BindingFlags.Public).ToList().FindAll(method => method.Name == "SetExpanded");
        var setExpandedMethod = setExpandedMethods[0];

        var rows = (IEnumerable) getRowsMethod.Invoke(data, null);
        bool first = true;
        // 周遊目前的行将其折疊
        foreach (var obj in rows)
        {
            if (first && !isOne)
            {
                var itemType = obj.GetType();
                var nameField = itemType.GetField("m_DisplayName", BindingFlags.Instance | BindingFlags.NonPublic);
                if (nameField != null)
                {
                    string name = (string) nameField.GetValue(obj);
                    if (name == "Assets")
                    {
                        first = false;
                        setExpandedMethod.Invoke(data, new object[]{obj, true});
                        continue;
                    }
                }
            }
            setExpandedMethod.Invoke(data, new object[] {obj, false});
        }
        AssetDatabase.Refresh();
    }
}
           

思路就是通過反射出目前的Project視窗對應的類,取到其中每個條目對應的元素,然後将其折疊,最後重新整理一下AssetDatabase就OK。