GUI や Editor の表示時に使うクラスとしてGUI, GUILayout, EditorGUI, EditorGUILayoutがあるが 名前と機能が似ててよくわからなくなるのでまとめてみる(まとめるとは言ってない)
公式リファレンスの説明
まず公式リファレンスの説明から見てみる
GUI
UnityEngine.GUI - Unity スクリプトリファレンス
GUILayout
GUILayout クラスは GUI の自動レイアウトを行うためのインターフェースです。
UnityEngine.GUILayout - Unity スクリプトリファレンス
EditorGUI
このクラスは GUI クラスの機能と同じように動作します。また、EditorGUILayout クラスと機能が一致するよう実装されています。
UnityEditor.EditorGUI - Unity スクリプトリファレンス
EditorGUILayout
Auto laid out version of EditorGUI. (EditorGUILayout クラスは EditorGUI の自動レイアウトを行うためのインターフェースです。)
UnityEditor.EditorGUILayout - Unity スクリプトリファレンス
公式リファレンスの説明より
説明どおり、Layout とついているものは Rect を指定しなくともよく、逆についていないものは Rect を指定する必要があります
また Editor とついているものは UnityEditor の namespace があるので Editorでしか利用できません
そのため、Runtime の OnGUI で Editor* は使用できなくなります
FlexibleSpace
FlexibleSpace は EditorGUILayout にはなく GUILayout のみにあります。 また EditorGUILayout には Space がありますが、EditorGUI には Space がありません そのため GUI に 機能があれば EditorGUI には機能がないと考えられます
ユーザ入力部
GUI* には ユーザが入力できるものが下記のみしかない
- Button
- HorizontalSlider
- PasswordField
- TextArea
- TextField
- Toggle
EditorGUI* なら型に合わせていろいろ使うことができます
Label の描画
GUI も EditorGUI も label 描画時の処理は どちらも style.Draw を呼んでおり最終的には同一である
// GUI private static void DoLabel(Rect position, GUIContent content, GUIStyle style) { Event current = Event.current; if (current.type != EventType.Repaint) return; style.Draw(position, content, false, false, false, false); if (string.IsNullOrEmpty(content.tooltip) || !position.Contains(current.mousePosition) || !GUIClip.visibleRect.Contains(current.mousePosition)) return; GUIStyle.SetMouseTooltip(content.tooltip, position); } // EditorGUI internal static void LabelFieldInternal( Rect position, GUIContent label, GUIContent label2, GUIStyle style) { int controlId = GUIUtility.GetControlID(EditorGUI.s_FloatFieldHash, FocusType.Passive, position); position = EditorGUI.PrefixLabel(position, controlId, label); if (Event.current.type != EventType.Repaint) return; style.Draw(position, label2, controlId); }
GUI と GUILayout
GUI.label と GUILayout.Label を見てみる
GUILayout では Rect を style から取得しているだけで GUI.label が呼ばれていた
// GUI private static void DoLabel(Rect position, GUIContent content, GUIStyle style) { Event current = Event.current; if (current.type != EventType.Repaint) return; style.Draw(position, content, false, false, false, false); if (string.IsNullOrEmpty(content.tooltip) || !position.Contains(current.mousePosition) || !GUIClip.visibleRect.Contains(current.mousePosition)) return; GUIStyle.SetMouseTooltip(content.tooltip, position); } // GUILayout private static void DoLabel(GUIContent content, GUIStyle style, GUILayoutOption[] options) { GUI.Label(GUILayoutUtility.GetRect(content, style, options), content, style); }
ついでに、EditorGUILayout.LabelField も見てみると GUILayout と同じく EditorGUI が呼ばれていた
public static void LabelField( GUIContent label, GUIContent label2, GUIStyle style, params GUILayoutOption[] options) { if (!style.wordWrap) { EditorGUI.LabelField(EditorGUILayout.s_LastRect = EditorGUILayout.GetControlRect(true, 16f, options), label, label2, style); } else { EditorGUILayout.BeginHorizontal(); EditorGUILayout.PrefixLabel(label, style); Rect rect = GUILayoutUtility.GetRect(label2, style, options); int indentLevel = EditorGUI.indentLevel; EditorGUI.indentLevel = 0; EditorGUI.LabelField(rect, label2, style); EditorGUI.indentLevel = indentLevel; EditorGUILayout.EndHorizontal(); } }
Begin / End
例えばBeginHorizontal / EndHorizontal は GUI にも EditorGUI にもある
中身を見てみるとスコープや戻り値が違うだけで処理的には完全に同一でした
// GUILayout public static void BeginHorizontal( GUIContent content, GUIStyle style, params GUILayoutOption[] options) { GUILayoutGroup guiLayoutGroup = GUILayoutUtility.BeginLayoutGroup(style, options, typeof (GUILayoutGroup)); guiLayoutGroup.isVertical = false; if (style == GUIStyle.none && content == GUIContent.none) return; GUI.Box(guiLayoutGroup.rect, content, style); } // EditorGUI internal static Rect BeginHorizontal( GUIContent content, GUIStyle style, params GUILayoutOption[] options) { GUILayoutGroup guiLayoutGroup = GUILayoutUtility.BeginLayoutGroup(style, options, typeof (GUILayoutGroup)); guiLayoutGroup.isVertical = false; if (style != GUIStyle.none || content != GUIContent.none) GUI.Box(guiLayoutGroup.rect, GUIContent.none, style); return guiLayoutGroup.rect; }
つまり
EditorGUI は Editor で使うための GUI の拡張である
Layout がつくものは Rect を指定せずに使え、Rect の指定をしていないだけで内部的には同一処理である
GUI に機能がある場合 EditorGUI にはない
主な用途
GUI、GUILayout
ランタイムで表示するUI用、GUI.enable を用いた入力制御
EditorGUI
CustomPropertyDrawer を利用した場合、こまかい UI 調整をしたい場合
EditorGUILayout
EditorWindow や OnInspectorGUIで利用