unity扩展顶部的工具栏Toolbar

image.png

在顶部绘制一些功能按钮

image.png

代码放在Editor文件夹即可

using System;
using System.Collections.Generic;
using System.Reflection;
using UnityEditor;
using UnityEngine;

namespace UnityToolbarExtender
{
    [InitializeOnLoad]
    public static class ToolbarExtender
    {
        static int m_toolCount;
        static GUIStyle m_commandStyle = null;

        public static readonly List<Action> LeftToolbarGUI = new List<Action>();
        public static readonly List<Action> RightToolbarGUI = new List<Action>();

        static ToolbarExtender()
        {
            Type toolbarType = typeof(Editor).Assembly.GetType("UnityEditor.Toolbar");
            FieldInfo toolIcons = toolbarType.GetField("s_ShownToolIcons",
                BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);
            var array = ( Array ) toolIcons.GetValue( null );
            m_toolCount = array != null ? array.Length : 6;

            ToolbarCallback.OnToolbarGUI -= OnGUI;
            ToolbarCallback.OnToolbarGUI += OnGUI;
        }

        static void OnGUI()
        {
            // Create two containers, left and right
            // Screen is whole toolbar

            if (m_commandStyle == null)
            {
                m_commandStyle = new GUIStyle("CommandLeft");
            }

            var screenWidth = EditorGUIUtility.currentViewWidth;

            // Following calculations match code reflected from Toolbar.OldOnGUI()
            float playButtonsPosition = (screenWidth - 100) / 2;

            Rect leftRect = new Rect(0, 0, screenWidth, Screen.height);
            leftRect.xMin += 10; // Spacing left
            leftRect.xMin += 32 * m_toolCount; // Tool buttons
            leftRect.xMin += 20; // Spacing between tools and pivot
            leftRect.xMin += 64 * 2; // Pivot buttons
            leftRect.xMax = playButtonsPosition;

            Rect rightRect = new Rect(0, 0, screenWidth, Screen.height);
            rightRect.xMin = playButtonsPosition;
            rightRect.xMin += m_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
            leftRect.xMin += 10;
            leftRect.xMax -= 10;
            rightRect.xMin += 10;
            rightRect.xMax -= 10;

            // Add top and bottom margins
            leftRect.y = 5;
            leftRect.height = 24;
            rightRect.y = 5;
            rightRect.height = 24;

            if (leftRect.width > 0)
            {
                GUILayout.BeginArea(leftRect);
                GUILayout.BeginHorizontal();
                foreach (var handler in LeftToolbarGUI)
                {
                    handler();
                }

                GUILayout.EndHorizontal();
                GUILayout.EndArea();
            }

            if (rightRect.width > 0)
            {
                GUILayout.BeginArea(rightRect);
                GUILayout.BeginHorizontal();
                foreach (var handler in RightToolbarGUI)
                {
                    handler();
                }

                GUILayout.EndHorizontal();
                GUILayout.EndArea();
            }
        }
    }
}
using System;
using UnityEngine;
using UnityEditor;
using System.Reflection;

#if UNITY_2019_1_OR_NEWER
using UnityEngine.UIElements;
#else
using UnityEngine.Experimental.UIElements;
#endif

namespace UnityToolbarExtender
{
    public static class ToolbarCallback
    {
        static Type m_toolbarType = typeof(Editor).Assembly.GetType("UnityEditor.Toolbar");
        static Type m_guiViewType = typeof(Editor).Assembly.GetType("UnityEditor.GUIView");
        static PropertyInfo m_viewVisualTree = m_guiViewType.GetProperty("visualTree",
            BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
        static FieldInfo m_imguiContainerOnGui = typeof(IMGUIContainer).GetField("m_OnGUIHandler",
            BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
        static ScriptableObject m_currentToolbar;

        /// <summary>
        /// Callback for toolbar OnGUI method.
        /// </summary>
        public static Action OnToolbarGUI;

        static ToolbarCallback()
        {
            EditorApplication.update -= OnUpdate;
            EditorApplication.update += OnUpdate;
        }

        static void OnUpdate()
        {
            // Relying on the fact that toolbar is ScriptableObject and gets deleted when layout changes
            if (m_currentToolbar == null)
            {
                // Find toolbar
                var toolbars = Resources.FindObjectsOfTypeAll(m_toolbarType);
                m_currentToolbar = toolbars.Length > 0 ? (ScriptableObject) toolbars[0] : null;
                if (m_currentToolbar != null)
                {
                    // Get it's visual tree
                    var visualTree = (VisualElement) m_viewVisualTree.GetValue(m_currentToolbar, null);

                    // Get first child which 'happens' to be toolbar IMGUIContainer
                    var container = (IMGUIContainer) visualTree[0];

                    // (Re)attach handler
                    var handler = (Action) m_imguiContainerOnGui.GetValue(container);
                    handler -= OnGUI;
                    handler += OnGUI;
                    m_imguiContainerOnGui.SetValue(container, handler);
                }
            }
        }

        static void OnGUI()
        {
            var handler = OnToolbarGUI;
            if (handler != null) handler();
        }
    }
}

使用

image.png

using UnityEditor;
using UnityEngine;
using UnityToolbarExtender;

namespace Assets.Editor.Toolbar
{
    [InitializeOnLoad]
    public static  class TestToolbar
    {
        static TestToolbar()
        {
            ToolbarExtender.LeftToolbarGUI.Add(OnToolbarGUI);
        }

        private static void OnToolbarGUI()
        {
            GUILayout.Space(50);
            if (GUILayout.Button("测试按钮"))
            {
                Debug.LogError("测试成功");
            }
            GUILayout.FlexibleSpace();
        }

    }
}

image.png

using System;
using System.Collections.Generic;
using System.Reflection;
using UnityEditor;
using UnityEngine;
using UnityToolbarExtender;

namespace EditorUIAlign
{
    /// <summary>
    /// 对齐方向
    /// </summary>
    public enum AlignType
    {
        [Header("顶")]
        Top = 1,
        [Header("左")]
        Left = 2,
        [Header("右")]
        Right = 3,
        [Header("底")]
        Bottom = 4,

        /// <summary>
        /// 水平居中
        /// </summary>
        [Header("水中")]
        HorizontalCenter = 5,
        /// <summary>
        /// 垂直居中
        /// </summary>
        [Header("垂中")]
        VerticalCenter = 6,
        /// <summary>
        /// 横向分布
        /// </summary>
        [Header("水平")]
        Horizontal = 7,
        /// <summary>
        /// 纵向分布
        /// </summary>
        [Header("垂直")]
        Vertical = 8,
    }

    /// <summary>
    /// UI对象对齐功能扩展
    /// </summary>
    [InitializeOnLoad]
    public class UiAlignToolbar
    {

        static UiAlignToolbar()
        {
            ToolbarExtender.LeftToolbarGUI.Add(OnToolbarGUI);
        }

        static void OnToolbarGUI()
        {
            GUILayout.Space(50);
            foreach (var temp in Enum.GetNames(typeof(AlignType)))
            {
                var type = (AlignType)Enum.Parse(typeof(AlignType), temp);
                var desc = EnumItemToDescription(type);
                if (GUILayout.Button(desc))
                {
                    Align(type);
                }
            }
            GUILayout.FlexibleSpace();
        }

        private static string EnumItemToDescription(Enum enumValue)
        {
            Type enumType = enumValue.GetType();
            string optionName = enumValue.ToString();
            FieldInfo fieldInfo = enumType.GetField(optionName);
            HeaderAttribute[] attributes =
                fieldInfo.GetCustomAttributes<HeaderAttribute>(false)
                    as HeaderAttribute[];
            return attributes.Length > 0 ? attributes[0].header : optionName;
        }

        #region 对齐


        public static void Align(AlignType type)
        {
            List<RectTransform> rects = new List<RectTransform>();
            GameObject[] objects = Selection.gameObjects;
            if (objects != null && objects.Length > 0)
            {
                for (int i = 0; i < objects.Length; i++)
                {
                    RectTransform rect = objects[i].GetComponent<RectTransform>();
                    if (rect != null)
                        rects.Add(rect);
                }
            }

            if (rects.Count > 1)
            {
                Align(type, rects);
            }
        }

        public static void Align(AlignType type, List<RectTransform> rects)
        {
            RectTransform tenplate = rects[0];
            float w = tenplate.sizeDelta.x * tenplate.lossyScale.x;
            float h = tenplate.sizeDelta.y * tenplate.localScale.y;

            float x = tenplate.position.x - tenplate.pivot.x * w;
            float y = tenplate.position.y - tenplate.pivot.y * h;

            switch (type)
            {
                case AlignType.Top:
                    for (int i = 1; i < rects.Count; i++)
                    {
                        RectTransform trans = rects[i];
                        float th = trans.sizeDelta.y * trans.localScale.y;
                        Vector3 pos = trans.position;
                        pos.y = y + h - th + trans.pivot.y * th;
                        trans.position = pos;
                    }
                    break;
                case AlignType.Left:
                    for (int i = 1; i < rects.Count; i++)
                    {
                        RectTransform trans = rects[i];
                        float tw = trans.sizeDelta.x * trans.lossyScale.x;
                        Vector3 pos = trans.position;
                        pos.x = x + tw * trans.pivot.x;
                        trans.position = pos;
                    }
                    break;
                case AlignType.Right:
                    for (int i = 1; i < rects.Count; i++)
                    {
                        RectTransform trans = rects[i];
                        float tw = trans.sizeDelta.x * trans.lossyScale.x;
                        Vector3 pos = trans.position;
                        pos.x = x + w - tw + tw * trans.pivot.x;
                        trans.position = pos;
                    }
                    break;
                case AlignType.Bottom:
                    for (int i = 1; i < rects.Count; i++)
                    {
                        RectTransform trans = rects[i];
                        float th = trans.sizeDelta.y * trans.localScale.y;
                        Vector3 pos = trans.position;
                        pos.y = y + th * trans.pivot.y;
                        trans.position = pos;
                    }
                    break;
                case AlignType.HorizontalCenter:
                    for (int i = 1; i < rects.Count; i++)
                    {
                        RectTransform trans = rects[i];
                        float tw = trans.sizeDelta.x * trans.lossyScale.x;
                        Vector3 pos = trans.position;
                        pos.x = x + 0.5f * w - 0.5f * tw + tw * trans.pivot.x;
                        trans.position = pos;
                    }
                    break;
                case AlignType.VerticalCenter:
                    for (int i = 1; i < rects.Count; i++)
                    {
                        RectTransform trans = rects[i];
                        float th = trans.sizeDelta.y * trans.localScale.y;
                        Vector3 pos = trans.position;
                        pos.y = y + 0.5f * h - 0.5f * th + th * trans.pivot.y;
                        trans.position = pos;
                    }
                    break;
                case AlignType.Horizontal:
                    float minX = GetMinX(rects);
                    float maxX = GetMaxX(rects);
                    rects.Sort(SortListRectTransformByX);
                    float distance = (maxX - minX) / (rects.Count - 1);
                    for (int i = 1; i < rects.Count - 1; i++)
                    {
                        RectTransform trans = rects[i];
                        Vector3 pos = trans.position;
                        pos.x = minX + i * distance;
                        trans.position = pos;
                    }
                    break;
                case AlignType.Vertical:
                    float minY = GetMinY(rects);
                    float maxY = GetMaxY(rects);
                    rects.Sort(SortListRectTransformByY);
                    float distanceY = (maxY - minY) / (rects.Count - 1);
                    for (int i = 1; i < rects.Count - 1; i++)
                    {
                        RectTransform trans = rects[i];
                        Vector3 pos = trans.position;
                        pos.y = minY + i * distanceY;
                        trans.position = pos;
                    }
                    break;
            }
        }

        private static int SortListRectTransformByX(RectTransform r1, RectTransform r2)
        {
            float w = r1.sizeDelta.x * r1.lossyScale.x;
            float x1 = r1.position.x - r1.pivot.x * w;
            w = r2.sizeDelta.x * r2.lossyScale.x;
            float x2 = r2.position.x - r2.pivot.x * w;
            if (x1 >= x2)
                return 1;
            else
                return -1;
        }

        private static int SortListRectTransformByY(RectTransform r1, RectTransform r2)
        {
            float w = r1.sizeDelta.y * r1.lossyScale.y;
            float y1 = r1.position.y - r1.pivot.y * w;
            w = r2.sizeDelta.y * r2.lossyScale.y;
            float y2 = r2.position.y - r2.pivot.y * w;
            if (y1 >= y2)
                return 1;
            else
                return -1;
        }

        private static float GetMinX(List<RectTransform> rects)
        {
            if (null == rects || rects.Count == 0)
                return 0;
            RectTransform tenplate = rects[0];
            float minx = tenplate.position.x;
            float tempX = 0;
            for (int i = 1; i < rects.Count; i++)
            {
                tempX = rects[i].position.x;
                if (tempX < minx)
                    minx = tempX;
            }
            return minx;
        }

        private static float GetMaxX(List<RectTransform> rects)
        {
            if (null == rects || rects.Count == 0)
                return 0;
            RectTransform tenplate = rects[0];
            float maxX = tenplate.position.x;
            float tempX = 0;
            for (int i = 1; i < rects.Count; i++)
            {
                tempX = rects[i].position.x;
                if (tempX > maxX)
                    maxX = tempX;
            }
            return maxX;
        }

        private static float GetMinY(List<RectTransform> rects)
        {
            if (null == rects || rects.Count == 0)
                return 0;
            RectTransform tenplate = rects[0];
            float minY = tenplate.position.y;
            float tempX = 0;
            for (int i = 1; i < rects.Count; i++)
            {
                tempX = rects[i].position.y;
                if (tempX < minY)
                    minY = tempX;
            }
            return minY;
        }

        private static float GetMaxY(List<RectTransform> rects)
        {
            if (null == rects || rects.Count == 0)
                return 0;
            RectTransform tenplate = rects[0];
            float maxY = tenplate.position.y;
            float tempX = 0;
            for (int i = 1; i < rects.Count; i++)
            {
                tempX = rects[i].position.y;
                if (tempX > maxY)
                    maxY = tempX;
            }
            return maxY;
        }

        #endregion

    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,718评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,683评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,207评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,755评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,862评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,050评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,136评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,882评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,330评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,651评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,789评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,477评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,135评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,864评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,099评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,598评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,697评论 2 351

推荐阅读更多精彩内容