【Unity】在Editor主工具栏中添加自定义UI

【Unity】在Editor主工具栏中添加自定义UI

在Unity 2021.3中测试。

Unity Editor中的主工具栏是一个 VisualElement ,可以按照常规的UIToolkit使用流程为主工具栏添加自定义UI。

主工具栏分为3部分:

  • 左侧UI区域
  • 中间PlayMode UI区域
  • 右侧UI区域

主工具栏区域

可以用反射获取到这3个UI元素,然后在其下添加自定义UI:

var toolbarType = typeof(Editor).Assembly.GetType("UnityEditor.Toolbar");
var toolbarObj = toolbarType.GetField("get").GetValue(null);
VisualElement toolbarRoot = (VisualElement)toolbarType.GetField("m_Root", 
		BindingFlags.Instance | BindingFlags.NonPublic)!.GetValue(toolbarObj);
VisualElement toolbarLeft = s_toolbarRoot.Q("ToolbarZoneLeftAlign");
VisualElement toolbarRight = s_toolbarRoot.Q("ToolbarZoneRightAlign");

下面的示例代码向主工具栏中添加了一个设置Time Scale的滑动条。

备注:示例中,Time Scale滑动条右侧的数值输入框中没能正常显示滑动条数值,是由Unity的Bug导致的,详见:https://issuetracker.unity3d.com/product/unity/issues/guid/UUM-40353 。

Time Scale Slider

using System.Reflection;
using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;
using UObject = UnityEngine.Object;

[InitializeOnLoad]
public static class CustomEditorToolbar
{
    
    
    #region Custom Left UI
    
    private static void InitializeCustomLeftUI() {
    
     }
    
    private static void UpdateCustomLeftUI() {
    
     }
    
    #endregion

    
    #region Custom Right UI

    private static Slider s_timeScaleSlider;

    private static void InitializeCustomRightUI()
    {
    
    
        // Time Scale
        s_timeScaleSlider = new Slider("Time Scale", 0f, 2f) // modify the range for your own needs
        {
    
    
            value = Time.timeScale,
            // MEMO Unity Bug: https://issuetracker.unity3d.com/product/unity/issues/guid/UUM-40353
            // The text won't display
            showInputField = true,
            style =
            {
    
    
                width = 200,
            },
        };
        s_timeScaleSlider.labelElement.style.minWidth = 0;
        s_timeScaleSlider.labelElement.style.flexShrink = 1;
        s_timeScaleSlider.RegisterValueChangedCallback(evt =>
        {
    
    
            var timeMgrAsset = AssetDatabase.LoadAllAssetsAtPath("ProjectSettings/TimeManager.asset")[0];
            Undo.RecordObject(timeMgrAsset, "Change Time Scale");
            Time.timeScale = evt.newValue;
        });
        s_customToolbarRight.Add(s_timeScaleSlider);
    }

    private static void UpdateCustomRightUI()
    {
    
    
        // Time Scale
        s_timeScaleSlider.SetValueWithoutNotify(Time.timeScale);
    }

    #endregion
    

    #region Lifecycle
    
    private static VisualElement s_toolbarRoot;
    private static VisualElement s_toolbarLeft;
    private static VisualElement s_toolbarRight;
    private static VisualElement s_customToolbarLeft;
    private static VisualElement s_customToolbarRight;


    static CustomEditorToolbar()
    {
    
    
        // EditorApplication.delayCall += TryInitialize;
        EditorApplication.update -= OnUpdate;
        EditorApplication.update += OnUpdate;
    }

    private static void TryInitialize()
    {
    
    
        if (s_toolbarRoot != null)
        {
    
    
            return;
        }

        var toolbarType = typeof(Editor).Assembly.GetType("UnityEditor.Toolbar");
        var toolbarObj = toolbarType.GetField("get").GetValue(null);
        s_toolbarRoot = (VisualElement)toolbarType.GetField("m_Root", BindingFlags.Instance | BindingFlags.NonPublic)!.GetValue(toolbarObj);
        s_toolbarLeft = s_toolbarRoot.Q("ToolbarZoneLeftAlign");
        s_toolbarRight = s_toolbarRoot.Q("ToolbarZoneRightAlign");
        
        s_customToolbarLeft = new VisualElement
        {
    
    
            name = "custom-toolbar-left",
            style =
            {
    
    
                flexGrow = 1,
                flexDirection = FlexDirection.RowReverse,
                overflow = Overflow.Hidden,
            },
        };
        s_toolbarLeft.Add(s_customToolbarLeft);
        
        s_customToolbarRight = new VisualElement
        {
    
    
            name = "custom-toolbar-right",
            style =
            {
    
    
                flexGrow = 1,
                flexDirection = FlexDirection.Row,
                overflow = Overflow.Hidden,
            },
        };
        s_toolbarRight.Add(s_customToolbarRight);
        
        InitializeCustomLeftUI();
        InitializeCustomRightUI();
    }

    private static void OnUpdate()
    {
    
    
        TryInitialize();
        UpdateCustomLeftUI();
        UpdateCustomRightUI();
    }
    
    #endregion
    
}

猜你喜欢

转载自blog.csdn.net/qq_21397217/article/details/131234804