171 lines
5.3 KiB
C#
171 lines
5.3 KiB
C#
|
|
// TabbedInspector.cs
|
|||
|
|
using System;
|
|||
|
|
using System.Collections.Generic;
|
|||
|
|
using UnityEditor;
|
|||
|
|
using UnityEngine;
|
|||
|
|
|
|||
|
|
namespace UnityEditor.Utils
|
|||
|
|
{
|
|||
|
|
/// <summary>
|
|||
|
|
/// 复用的 tab 管理器(非 Editor),供任意 Editor 组合使用。
|
|||
|
|
/// 用法:在 Editor 的 OnEnable 创建一个实例并 RegisterTab / AppendToTab,
|
|||
|
|
/// 在 OnInspectorGUI 调用 DrawTabs()。
|
|||
|
|
/// </summary>
|
|||
|
|
public class TabbedInspector
|
|||
|
|
{
|
|||
|
|
public class Tab
|
|||
|
|
{
|
|||
|
|
public string title;
|
|||
|
|
public string iconName;
|
|||
|
|
public List<Action> callbacks = new List<Action>();
|
|||
|
|
|
|||
|
|
public Tab(string t, string icon)
|
|||
|
|
{
|
|||
|
|
title = t;
|
|||
|
|
iconName = icon;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
List<Tab> _tabs = new List<Tab>();
|
|||
|
|
int _currentTabIndex = 0;
|
|||
|
|
string _prefsKey; // 用于保存每类 inspector 的选择(可选)
|
|||
|
|
|
|||
|
|
public TabbedInspector(string prefsKey = null)
|
|||
|
|
{
|
|||
|
|
_prefsKey = prefsKey;
|
|||
|
|
if (!string.IsNullOrEmpty(_prefsKey))
|
|||
|
|
{
|
|||
|
|
_currentTabIndex = EditorPrefs.GetInt(_prefsKey, 0);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public void RegisterTab(string title, string iconName, Action drawCallback)
|
|||
|
|
{
|
|||
|
|
if (string.IsNullOrEmpty(title)) return;
|
|||
|
|
var tab = _tabs.Find(t => t.title == title);
|
|||
|
|
if (tab == null)
|
|||
|
|
{
|
|||
|
|
tab = new Tab(title, iconName);
|
|||
|
|
_tabs.Add(tab);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
tab.iconName = iconName;
|
|||
|
|
tab.callbacks.Clear();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (drawCallback != null)
|
|||
|
|
tab.callbacks.Add(drawCallback);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public void AppendToTab(string title, Action drawCallback, bool last = true)
|
|||
|
|
{
|
|||
|
|
if (string.IsNullOrEmpty(title) || drawCallback == null) return;
|
|||
|
|
var tab = _tabs.Find(t => t.title == title);
|
|||
|
|
if (tab == null)
|
|||
|
|
{
|
|||
|
|
tab = new Tab(title, "d_DefaultAsset Icon");
|
|||
|
|
_tabs.Add(tab);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (!tab.callbacks.Contains(drawCallback))
|
|||
|
|
{
|
|||
|
|
if (last) tab.callbacks.Add(drawCallback);
|
|||
|
|
else tab.callbacks.Insert(0, drawCallback);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public void RemoveCallbackFromTab(string title, Action drawCallback)
|
|||
|
|
{
|
|||
|
|
if (string.IsNullOrEmpty(title) || drawCallback == null) return;
|
|||
|
|
var tab = _tabs.Find(t => t.title == title);
|
|||
|
|
if (tab == null) return;
|
|||
|
|
tab.callbacks.RemoveAll(cb => cb == drawCallback);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public void UnregisterTab(string title)
|
|||
|
|
{
|
|||
|
|
if (string.IsNullOrEmpty(title)) return;
|
|||
|
|
_tabs.RemoveAll(t => t.title == title);
|
|||
|
|
if (_tabs.Count == 0) _currentTabIndex = 0;
|
|||
|
|
else if (_currentTabIndex >= _tabs.Count) _currentTabIndex = Mathf.Max(0, _tabs.Count - 1);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public void EnsureDefaultTab(string title, string iconName, Action defaultCallback)
|
|||
|
|
{
|
|||
|
|
var tab = _tabs.Find(t => t.title == title);
|
|||
|
|
if (tab == null)
|
|||
|
|
{
|
|||
|
|
tab = new Tab(title, iconName);
|
|||
|
|
_tabs.Insert(0, tab);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (!tab.callbacks.Contains(defaultCallback))
|
|||
|
|
tab.callbacks.Insert(0, defaultCallback);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public void DrawTabs()
|
|||
|
|
{
|
|||
|
|
if (_tabs == null || _tabs.Count == 0)
|
|||
|
|
{
|
|||
|
|
// nothing to draw
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
EditorGUILayout.BeginHorizontal();
|
|||
|
|
|
|||
|
|
for (int i = 0; i < _tabs.Count; i++)
|
|||
|
|
{
|
|||
|
|
var tab = _tabs[i];
|
|||
|
|
bool isActive = (i == _currentTabIndex);
|
|||
|
|
var style = new GUIStyle(EditorStyles.toolbarButton) { fixedHeight = 25, fontSize = 11, fontStyle = isActive ? FontStyle.Bold : FontStyle.Normal };
|
|||
|
|
|
|||
|
|
var icon = EditorGUIUtility.IconContent(tab.iconName)?.image;
|
|||
|
|
var content = new GUIContent(icon, tab.title);
|
|||
|
|
if (GUILayout.Button(content, style))
|
|||
|
|
{
|
|||
|
|
_currentTabIndex = i;
|
|||
|
|
SaveIndex();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (isActive)
|
|||
|
|
{
|
|||
|
|
// 一条下划线表示选中
|
|||
|
|
Rect rect = GUILayoutUtility.GetLastRect();
|
|||
|
|
EditorGUI.DrawRect(new Rect(rect.x, rect.yMax - 2, rect.width, 2), new Color(0.1f, 0.5f, 0.9f));
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
EditorGUILayout.EndHorizontal();
|
|||
|
|
GUILayout.Space(4);
|
|||
|
|
|
|||
|
|
// draw callbacks for current tab
|
|||
|
|
var callbacks = _tabs[_currentTabIndex].callbacks;
|
|||
|
|
if (callbacks != null)
|
|||
|
|
{
|
|||
|
|
foreach (var cb in callbacks)
|
|||
|
|
{
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
cb?.Invoke();
|
|||
|
|
}
|
|||
|
|
catch (ExitGUIException)
|
|||
|
|
{
|
|||
|
|
throw;
|
|||
|
|
}
|
|||
|
|
catch (Exception e)
|
|||
|
|
{
|
|||
|
|
Debug.LogException(e);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void SaveIndex()
|
|||
|
|
{
|
|||
|
|
if (!string.IsNullOrEmpty(_prefsKey))
|
|||
|
|
EditorPrefs.SetInt(_prefsKey, _currentTabIndex);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|