[Unity编辑器扩展基础总结] 第6章 EditorGUIEdirotGUILayout介绍

Posted 倾尽天下KO

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[Unity编辑器扩展基础总结] 第6章 EditorGUIEdirotGUILayout介绍相关的知识,希望对你有一定的参考价值。

第6章 EditorGUI、EdirotGUILayout介绍

6.1 EditorGUI、EditorGUILayout简介

EditorGUI/EditorGUILayout是编辑器扩展中各种控件的基类,它在运行时与GUI类具有相同的功能,区别是它也可以在非运行时执行,且只能在编辑器状态下使用, 具有编辑器的其他功能。

其中EditorGUILayout可以自动参与排版,所以用得比较多。

下面 ,我们使用EditorGUILayout在EditorWindow上显示一个字符。

using UnityEditor;
using UnityEngine;

public class EditorTest : EditorWindow
{
    [MenuItem("Tools/Example")]
    static void Open()
    {
        GetWindow<EditorTest>();
    }

    void OnGUI()
    {
        EditorGUILayout.LabelField("Example Label");
    }
}

6.2 变更检查 - EditorGUI.BeginChangeCheck

对在BeginChangeCheck和EndChangeCheck范围内的GUI进行任何更改时,EndChangeCheck将返回true。

using UnityEditor;
using UnityEngine;

public class EditorTest : EditorWindow
{
    private bool toggleValue;

    [MenuItem("Tools/Example")]
    static void Open()
    {
        GetWindow<EditorTest>();
    }

    void OnGUI()
    {
        EditorGUI.BeginChangeCheck();

        toggleValue = EditorGUILayout.ToggleLeft("Toggle", toggleValue);

        if (EditorGUI.EndChangeCheck())
        {
            Debug.Log("toggleValue值发生变化" + toggleValue.ToString());
        }
    }
}

GUI.changed

ChangeCheck也是使用GUI.changed来实现的,如果想用GUI.changed实现与ChangeCheck相同的功能,则可以用以下方式。

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

public class EditorTest : EditorWindow
{
    private bool toggleValue;

    private Stack<bool> stack = new Stack<bool>();

    [MenuItem("Tools/Example")]
    static void Open()
    {
        GetWindow<EditorTest>();
    }

    void OnGUI()
    {
        //EditorGUI.BeginChangeCheck();

        stack.Push(GUI.changed);
        GUI.changed = false;

        toggleValue = EditorGUILayout.ToggleLeft("Toggle", toggleValue);

        bool changed = GUI.changed;
        GUI.changed |= stack.Pop();

        if (changed)
        {
            Debug.Log("toggleValue值发生变化" + toggleValue.ToString());
        }
    }
}

6.3 禁用部分组件 - EditorGUI.BeginDisabledGroup(true)

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

public class EditorTest : EditorWindow
{
    private bool toggleValue;

    private Stack<bool> stack = new Stack<bool>();

    [MenuItem("Tools/Example")]
    static void Open()
    {
        GetWindow<EditorTest>();
    }

    void OnGUI()
    {
        Display();

        EditorGUILayout.Space();

        EditorGUI.BeginDisabledGroup(true);

        Display();

        EditorGUI.EndDisabledGroup();
    }

    void Display()
    {
        EditorGUILayout.ToggleLeft("Toggle", false);
        EditorGUILayout.IntSlider(0, 10, 0);
        GUILayout.Button("Button");
    }
}

GUI.enabled

GUI.enabled可以实现与DisabledGroup相似的功能。如下

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

public class EditorTest : EditorWindow
{
    private bool toggleValue;

    [MenuItem("Tools/Example")]
    static void Open()
    {
        GetWindow<EditorTest>();
    }

    void OnGUI()
    {
        Display();

        EditorGUILayout.Space();

        GUI.enabled = false;

        Display();

        GUI.enabled = true;
    }

    void Display()
    {
        EditorGUILayout.ToggleLeft("Toggle", false);
        EditorGUILayout.IntSlider(0, 10, 0);
        GUILayout.Button("Button");
    }
}

6.4 淡出淡出一组GUI组件 - EditorGUILayout.BeginFadeGroup  EditorGUILayout.EndFadeGroup()

用于淡入和淡出一组GUI,在淡入淡出期间我们是无法操作GUI的。下面我们通过按钮来触发淡入和淡出GUI。

using UnityEditor;
using UnityEditor.AnimatedValues;
using UnityEngine;
using UnityEngine.Events;

public class EditorTest : EditorWindow
{
    private Texture m_tex;

    private AnimFloat m_animFloat = new AnimFloat(0.0001f);

    [MenuItem("Tools/Example")]
    static void Open()
    {
        GetWindow<EditorTest>();
    }

    void OnGUI()
    {
        bool on = m_animFloat.value == 1;

        if (GUILayout.Button(on ? "Close" : "Open", GUILayout.Width(64)))
        {
            m_animFloat.target = on ? 0.0001f : 1;
            m_animFloat.speed = 0.1f;

            var env = new UnityEvent();
            env.AddListener(() => Repaint());
            m_animFloat.valueChanged = env;
        }

        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.BeginFadeGroup(m_animFloat.value);
        Display();
        EditorGUILayout.EndFadeGroup();
        Display();
        EditorGUILayout.EndHorizontal();
    }

    void Display()
    {
        EditorGUILayout.BeginVertical();
        EditorGUILayout.ToggleLeft("Toggle", false);

        var options = new[] { GUILayout.Width(128), GUILayout.Height(128) };

        m_tex = EditorGUILayout.ObjectField(m_tex, typeof(Texture), false, options) as Texture;

        GUILayout.Button("Button");
        EditorGUILayout.EndVertical();
    }
}

 

6.5  对象引用的字段 - EditorGUILayout.ObjectField

处理对象引用的字段。可以在参数中指定要接受的对象类型。同样,纹理(Texture2D和Sprite)是特殊的缩略图字段。

    void OnGUI()
    {
        EditorGUILayout.ObjectField(null, typeof(Object), false);

        EditorGUILayout.ObjectField(null, typeof(Material), false);

        EditorGUILayout.ObjectField(null, typeof(AudioClip), false);

        var options = new[] { GUILayout.Width(64), GUILayout.Height(64)};

        EditorGUILayout.ObjectField(null, typeof(Texture), false, options);

        EditorGUILayout.ObjectField(null, typeof(Sprite), false, options);
    }

6.6  处理多浮点字段 - EditorGUI.MultiFloatField

它可以用于绘制在一行中编辑多个浮点值的字段,看起来就像在检查器中编辑Vector3的值。

using UnityEditor;
using UnityEngine;

public class EditorTest : EditorWindow
{
    float[] numbers = new float[] { 0, 1, 2 };

    GUIContent[] contents = new GUIContent[] {
    new GUIContent ("X"),
    new GUIContent ("Y"),
    new GUIContent ("Z")};

    [MenuItem("Tools/Example")]
    static void Open()
    {
        GetWindow<EditorTest>();
    }

    void OnGUI()
    {
        EditorGUI.MultiFloatField(
            new Rect(30, 30, 200, EditorGUIUtility.singleLineHeight),
            new GUIContent("位置点"),
            contents,
            numbers);
    }
}

6.7  缩进级别 - EditorGUI.indentLevel

管理缩进级别。通过部分增加或减少缩进,可以实现检查器中那种层次结构。

可以适用于EditorGUI和EditorGUILayout。

using UnityEditor;
using UnityEngine;

public class EditorTest : EditorWindow
{
    [MenuItem("Tools/Example")]
    static void Open()
    {
        GetWindow<EditorTest>();
    }

    void OnGUI()
    {
        EditorGUILayout.LabelField("Parent");

        EditorGUI.indentLevel++;

        EditorGUILayout.LabelField("Child");
        EditorGUILayout.LabelField("Child");

        EditorGUI.indentLevel--;

        EditorGUILayout.LabelField("Parent");

        EditorGUI.indentLevel++;

        EditorGUILayout.LabelField("Child");
    }
}

6.8  EditorGUILayout.Knob

创建一个可以在指定范围内的变化的“旋钮”。可以通过使用鼠标拖动或单击显示的标签来直接输入值。

using UnityEditor;
using UnityEngine;

public class EditorTest : EditorWindow
{
    private float angle = 0;

    [MenuItem("Tools/Example")]
    static void Open()
    {
        GetWindow<EditorTest>();
    }

    void OnGUI()
    {
        angle = EditorGUILayout.Knob(Vector2.one * 64, angle, 0, 360, "", Color.gray, Color.red, true);
    }
}

6.9 范围 - HorizontalScope VerticalScope ScrollViewScope

用于管理 BeginHorizontal/EndHorizontal 排布的Helper类。在该范围内呈现的所有控件都将依次水平/垂直放置。使用Using语句就可以不需要BeginHorizontal和EndHorizontal。

    void OnGUI()
    {
        // Starts a horizontal group
        using (var horizontalScope = new GUILayout.HorizontalScope("box"))
        {
            GUILayout.Button("Button1");
            GUILayout.Button("Button2");
        }
        // Now the group is ended.
    }

利用GUI.Scope自定义功能范围  背景色范围 - BackgroundColorScope

与Horizo​​ntalScope一样,背景色范围也是通过继承GUI.Scope类来创建的。

        // 摘要:Disposable helper class for managing BeginHorizontal / EndHorizontal.
        public class HorizontalScope : GUI.Scope
        {
            public HorizontalScope(params GUILayoutOption[] options)
       {
         EditorGUILayout.BeginHorizontal();
       } 
public HorizontalScope(GUIStyle style, params GUILayoutOption[] options); public HorizontalScope(string text, GUIStyle style, params GUILayoutOption[] options); public HorizontalScope(Texture image, GUIStyle style, params GUILayoutOption[] options); public HorizontalScope(GUIContent content, GUIStyle style, params GUILayoutOption[] options); protected override void CloseScope()
       {
         EditorGUILayout.EndHorizontal();
       }  }

CloseScope方法是在Dispose期间调用的。我们在构造函数中调用Begin,在CloseScope方法中调用End。

同样,可以使用继承GUI.Scope的类创建作用域。下面,我们创建一个BackgroundColorScope,仅在范围内更改GUI的背景。

using UnityEngine;

public class BackgroundColorScope : GUI.Scope
{
    private readonly Color color;
    public BackgroundColorScope(Color color)
    {
        this.color = GUI.backgroundColor;
        GUI.backgroundColor = color;
    }

    protected override void CloseScope()
    {
        GUI.backgroundColor = color;
    }
}

GUI.backgroundColor在传递颜色信息之前,需要将其缓存起来,然后使用CloseScope将其恢复为原始颜色。

    void OnGUI()
    {
        using (new BackgroundColorScope(Color.green))
        {
            GUILayout.Button("Button");

            using (new BackgroundColorScope(Color.yellow))
            {
                GUILayout.Button("Button");
            }
        }
    }

6.10 切换按钮外观

Unity Editor GUI具有许多按钮,这些按钮虽然看起来像按钮,但是具有开/关功能。

切换单个按钮样式 - GUILayout.Toggle

多个按钮时切换样式 - GUILayout.Toolbar

当我们想从多个选项中选择一个时

    private bool one, two, three;

    void OnGUI()
    {
        using (new EditorGUILayout.HorizontalScope())
        {
            one = GUILayout.Toggle(one, "1", EditorStyles.miniButtonLeft);
            two = GUILayout.Toggle(two, "2", EditorStyles.miniButtonMid);
            three = GUILayout.Toggle(three, "3", EditorStyles.miniButtonRight);
        }
    }

如果按钮很多的时候,我们需要定义很多的bool变量,管理起来就会非常麻烦,这时候我们可以使用GUILayout.Toolbar轻松解决。

    private int selected;

    private string[] btnAttr = new string[] { "1", "2", "3", "4", "5", "6" };

    void OnGUI()
    {
        using (new EditorGUILayout.HorizontalScope())
        {
            selected = GUILayout.Toolbar(selected, btnAttr);
        }
    }

当前的选项由int变量管理,显示的按钮由字符串数组管理。另外,通过更改GUIStyle,可以显示不同的按钮样式。

使用EditorStyles.toolbarButton来实现工具栏和切换器样式,例如在PlayerSettings平台设置中的工具栏和切换器。

    void OnGUI()
    {
        using (new EditorGUILayout.HorizontalScope())
        {
            selected = GUILayout.Toolbar(selected, btnAttr, EditorStyles.toolbarButton);
        }
    }

GUILayout.SelectionGrid

 如果使用GUILayout.SelectionGrid将样式设置为PreferencesKeysElement(Unity内置的GUIStyle),那么所有选项将显示在一列中,这类似Preferences窗口中表示的选择菜单。

    void OnGUI()
    {
        using (new EditorGUILayout.HorizontalScope())
        {
            selected = GUILayout.SelectionGrid(selected, btnAttr, 1, "PreferencesKeysElement");
        }
    }

 

 

 

 

以上是关于[Unity编辑器扩展基础总结] 第6章 EditorGUIEdirotGUILayout介绍的主要内容,如果未能解决你的问题,请参考以下文章

Unity 插件宝典 (张忠喜 廖一庭 著)

20145301 《信息安全系统设计基础》第6周学习总结

20145216史婧瑶《信息安全系统设计基础》第6周学习总结

20145336张子扬 《信息安全系统设计基础》第6周学习总结

Unity Shader初识Shader,基础总结!

Unity Shader入门精要学习笔记 - 第3章 Unity Shader 基础