快速打开最近访问的预制体工具
# 展示最近打开的预制体历史
# 通过左右箭头就能快速打开最近打开过的预制体
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; } }