Unity Toolbar工具栏扩展
# 效果图
using System; using System.Reflection; using UnityEditor; using UnityEngine; #if UNITY_2019_1_OR_NEWER using UnityEngine.UIElements; #else using UnityEngine.Experimental.UIElements; #endif [InitializeOnLoad] public class ToolbarExtend { static ScriptableObject _toolbar; static int _toolIconCount; //左侧的: 抓手, 移动, 旋转等那几个工具 static GUIStyle _commandStyle; static ToolbarExtend() { EditorApplication.update -= OnEditorUpdate; EditorApplication.update += OnEditorUpdate; } static void OnEditorUpdate() { if (null != _toolbar) return; Type Type_Toolbar = typeof(Editor).Assembly.GetType("UnityEditor.Toolbar"); InitToolIconCount(Type_Toolbar); RegToolbarOnGUI(Type_Toolbar); } static void InitToolIconCount(Type Type_Toolbar) { #if UNITY_2019_1_OR_NEWER string fieldName = "k_ToolCount"; #else string fieldName = "s_ShownToolIcons"; #endif var ToolBar_s_ShowToolIcons = Type_Toolbar.GetField(fieldName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static); //Toolbar.s_ShownToolIcons #if UNITY_2019_1_OR_NEWER _toolIconCount = ToolBar_s_ShowToolIcons != null ? ((int) ToolBar_s_ShowToolIcons.GetValue(null)) : 7; #elif UNITY_2018_1_OR_NEWER _toolIconCount = ToolBar_s_ShowToolIcons != null ? ((Array) ToolBar_s_ShowToolIcons.GetValue(null)).Length : 6; #else _toolIconCount = ToolBar_s_ShowToolIcons != null ? ((Array) ToolBar_s_ShowToolIcons.GetValue(null)).Length : 5; #endif } //注册Toolbar的OnGUIHandler的监听 static void RegToolbarOnGUI(Type Type_Toolbar) { // Find toolbar var toolbars = Resources.FindObjectsOfTypeAll(Type_Toolbar); _toolbar = toolbars.Length > 0 ? (ScriptableObject) toolbars[0] : null; if (null == _toolbar) return; Type Type_GUIView = typeof(Editor).Assembly.GetType("UnityEditor.GUIView"); PropertyInfo GUIView_visualTree = Type_GUIView.GetProperty("visualTree", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); //toolbar上可放置ui的容器, 我们这边放在第1个容器 var visualTree = (VisualElement) GUIView_visualTree.GetValue(_toolbar, null); var container = (IMGUIContainer) visualTree[0]; //监听OnGUI FieldInfo IMGUIContainer_m_OnGUIHandler = typeof(IMGUIContainer).GetField("m_OnGUIHandler", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); var handler = (Action) IMGUIContainer_m_OnGUIHandler.GetValue(container); handler -= Toolbar_OnGUI; handler += Toolbar_OnGUI; IMGUIContainer_m_OnGUIHandler.SetValue(container, handler); } //Toolbar的OnGUI static void Toolbar_OnGUI() { var screenWidth = EditorGUIUtility.currentViewWidth; // Following calculations match code reflected from Toolbar.OldOnGUI() float playButtonX = (screenWidth - 100) / 2; OnGUI_ToolbarLeft(screenWidth, playButtonX); OnGUI_ToolbarRight(screenWidth, playButtonX); } static void OnGUI_ToolbarLeft(float screenWidth, float playButtonX) { Rect leftRect = new Rect(0, 0, screenWidth, Screen.height); leftRect.xMin += 10; // Spacing left leftRect.xMin += 32 * _toolIconCount; // Tool buttons leftRect.xMin += 20; // Spacing between tools and pivot leftRect.xMin += 64 * 2; // Pivot/Center, Local/World leftRect.xMax = playButtonX; // Add spacing around existing controls leftRect.xMin += 10; leftRect.xMax -= 10; // Add top and bottom margins leftRect.y = 7; leftRect.height = 24; if (leftRect.width > 0) { GUILayout.BeginArea(leftRect); GUILayout.BeginHorizontal(); //********** 在这边绘制自定义ui GUILayout.FlexibleSpace(); GUILayout.Label("Toolbar左侧"); GUILayout.TextField("", GUILayout.Width(100)); if (GUILayout.Button("测试按钮")) { } //********** GUILayout.EndHorizontal(); GUILayout.EndArea(); } } static void OnGUI_ToolbarRight(float screenWidth, float playButtonX) { if (_commandStyle == null) _commandStyle = new GUIStyle("CommandLeft"); Rect rightRect = new Rect(0, 0, screenWidth, Screen.height); rightRect.xMin = playButtonX; rightRect.xMin += _commandStyle.fixedWidth * 3; // Play buttons rightRect.xMax = screenWidth; rightRect.xMax -= 10; // Spacing right rightRect.xMax -= 80; // Layout rightRect.xMax -= 10; // Spacing between layout and layers rightRect.xMax -= 80; // Layers rightRect.xMax -= 20; // Spacing between layers and account rightRect.xMax -= 80; // Account rightRect.xMax -= 10; // Spacing between account and cloud rightRect.xMax -= 32; // Cloud rightRect.xMax -= 10; // Spacing between cloud and collab rightRect.xMax -= 78; // Colab // Add spacing around existing controls rightRect.xMin += 10; rightRect.xMax -= 10; // Add top and bottom margins rightRect.y = 5; rightRect.height = 24; if (rightRect.width > 0) { GUILayout.BeginArea(rightRect); GUILayout.BeginHorizontal(); //********** 在这边绘制自定义ui GUILayout.FlexibleSpace(); GUILayout.Label("Toolbar右侧"); GUILayout.TextField("", GUILayout.Width(100)); if (GUILayout.Button("测试按钮")) { } //********** GUILayout.EndHorizontal(); GUILayout.EndArea(); } } }
# Toolbar的刷新
static void RepaintToolbar() { MethodInfo Tools_RepaintAllToolViews = typeof(Tools).GetMethod("RepaintAllToolViews",BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Static); Tools_RepaintAllToolViews.Invoke(null,null); }
# 注意:下面的代码无法刷新Toolbar
static void RepaintToolbar2() { SceneView.RepaintAll(); MethodInfo GameView_RepaintAll = typeof(Editor).Assembly.GetType("UnityEditor.GameView").GetMethod("RepaintAll"); GameView_RepaintAll.Invoke(null, null); }
【参考】
Unity编辑器拓展之自定义UnityToolbar_素颜悠悠的博客-CSDN博客,这个讲的很全
Unity3D研究院编辑器之脚本设置ToolBar(二十三) | 雨松MOMO程序研究院 (xuanyusong.com)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下