[Unity編輯器擴展基礎總結] 第6章 EditorGUI、EdirotGUILayout介紹


第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");
        }
    }

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM