快速打开最近访问的预制体工具

# 展示最近打开的预制体历史

# 通过左右箭头就能快速打开最近打开过的预制体

 

public class AssetNavigateEditor : EditorWindow
{

    [MenuItem("Window/MyTools/Prefab Open History", false, 1)]
    static void ShowWindow()
    {
        GetWindow(typeof(AssetNavigateEditor), false, "Prefab Open History");
    }
    
    bool _ignorePrefabOpenOnce;

    PrefabHistoryTreeView _treeView;
    TreeViewState _treeViewState;
    List<int> _treeViewSelectionIds = new List<int>(1){ 0 };
    
    List<string> _prefabOpenHistoryQueue = new List<string>();
    int _maxHistory = 30;
    int _prefabOpenHistoryNaviIndex;
    
    private void OnEnable()
    {
        _treeView = new PrefabHistoryTreeView(new TreeViewState(), _prefabOpenHistoryQueue);
        
        PrefabStage.prefabStageOpened -= OnPrefabOpen;
        PrefabStage.prefabStageOpened += OnPrefabOpen;
    }

    private void OnDisable()
    {
        PrefabStage.prefabStageOpened -= OnPrefabOpen;
    }
    
    private void OnPrefabOpen(PrefabStage obj)
    {
        if (_ignorePrefabOpenOnce)
        {
            _ignorePrefabOpenOnce = false;
            return;
        }
        if (false) Debug.Log($"OnPrefabOpen: {obj.scene.name}, {obj.prefabAssetPath}");
        
        //如果之前打开过相同的, 把之前的删除
        for (var i = _prefabOpenHistoryQueue.Count - 1; i >= 0; --i)
        {
            if (_prefabOpenHistoryQueue[i] == obj.prefabAssetPath)
                _prefabOpenHistoryQueue.RemoveAt(i);
        }
        
        _prefabOpenHistoryQueue.Add(obj.prefabAssetPath); //最新打开的加在队列尾
        while (_prefabOpenHistoryQueue.Count > _maxHistory)
            _prefabOpenHistoryQueue.RemoveAt(0);

        _prefabOpenHistoryNaviIndex = _prefabOpenHistoryQueue.Count - 1; //默认选中最近打开的
        
        //Repaint();
        _treeView.Reload();
        
        _treeViewSelectionIds[0] = _prefabOpenHistoryNaviIndex;
        _treeView.SetSelection(_treeViewSelectionIds);
        _treeView.SetCurrentId(_prefabOpenHistoryNaviIndex);
    }

    private void OnGUI()
    {
        GUILayout.Space(5);
        OnGui_PrefabOpenHistory();
        GUILayout.Space(5);
    }

    void OnGui_PrefabOpenHistory()
    {
        EditorGUILayout.BeginHorizontal();
        {
            if (GUILayout.Button("<-", GUILayout.Width(80)))
            {
                if (_prefabOpenHistoryQueue.Count > 0 && _prefabOpenHistoryNaviIndex > 0)
                {
                    _prefabOpenHistoryNaviIndex--;
                    _treeViewSelectionIds[0] = _prefabOpenHistoryNaviIndex;
                    _treeView.SetSelection(_treeViewSelectionIds);
                    _treeView.SetCurrentId(_prefabOpenHistoryNaviIndex);

                    var path = _prefabOpenHistoryQueue[_prefabOpenHistoryNaviIndex];
                    var asset = AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(path);
                    _ignorePrefabOpenOnce = true;
                    AssetDatabase.OpenAsset(asset);
                }
            }

            if (GUILayout.Button("->", GUILayout.Width(80)))
            {
                if (_prefabOpenHistoryQueue.Count > 0 
                    && _prefabOpenHistoryNaviIndex < _prefabOpenHistoryQueue.Count - 1)
                {
                    _prefabOpenHistoryNaviIndex++;
                    _treeViewSelectionIds[0] = _prefabOpenHistoryNaviIndex;
                    _treeView.SetSelection(_treeViewSelectionIds);
                    _treeView.SetCurrentId(_prefabOpenHistoryNaviIndex);

                    var path = _prefabOpenHistoryQueue[_prefabOpenHistoryNaviIndex];
                    var asset = AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(path);
                    _ignorePrefabOpenOnce = true;
                    AssetDatabase.OpenAsset(asset);
                }
            }

            if (GUILayout.Button("Clear", GUILayout.Width(80)))
            {
                _prefabOpenHistoryQueue.Clear();
                _prefabOpenHistoryNaviIndex = 0;

                _treeViewSelectionIds.Clear();
                _treeView.SetSelection(_treeViewSelectionIds);
                _treeViewSelectionIds.Add(0);
                _treeView.SetCurrentId(-1);
                _treeView.Reload();
            }

        }
        EditorGUILayout.EndHorizontal();

        var xMargin = 10;
        var yMarginTop = 15 + EditorGUIUtility.singleLineHeight;
        var yMarginBottom = 10;
        var rect = new Rect(xMargin, yMarginTop, position.width - xMargin * 2, position.height - yMarginTop - yMarginBottom);
        _treeView.OnGUI(rect);
    }

}

# TreeView

class PrefabHistoryTreeView : TreeView
{
    private List<string> _historyList;
    private int _currentId = -1;
    
    private TreeViewItem _emptyTreeViewItem;
    
    public PrefabHistoryTreeView(TreeViewState state, List<string> historyList)
        : base(state)
    {
        _historyList = historyList;
        showAlternatingRowBackgrounds = true; //隔行显示颜色
        rowHeight = 20;
        showBorder = true; //表格边框
        Reload();
    }
    
    protected override TreeViewItem BuildRoot()
    {
        var rootTreeViewItem = new TreeViewItem(-1, -1); //root的depth必须为-1

        if (_historyList.Count <= 0)
        {
            if (null == _emptyTreeViewItem) _emptyTreeViewItem = new TreeViewItem();
            rootTreeViewItem.AddChild(_emptyTreeViewItem);
        }
        else
        {
            for (var i = _historyList.Count - 1; i >= 0; --i)
                rootTreeViewItem.AddChild(new TreeViewItem(i, 0, _historyList[i]));
        }
        return rootTreeViewItem;
    }

    protected override void RowGUI(RowGUIArgs args)
    {
        if (_currentId == args.item.id)
            DefaultGUI.Label(args.rowRect, "->", args.selected, args.focused);
        base.RowGUI(args);
    }

    public void SetCurrentId(int id)
    {
        _currentId = id;
    }
    
}

 

posted @ 2022-03-24 23:15  yanghui01  阅读(114)  评论(0编辑  收藏  举报