Begin / End で表記するGUI系クラスのヘルパークラスである Scopeのメモ
基本的にはGUI.Scopeを継承しており、自身でScopeクラスを追加することもできる。
デフォルトで入っているものは以下であり、使い方と簡単に機能説明を追記する
また最後に自作のScopeも載せておく
GUI
GUI.ScrollViewScope
private const int ScrollItemCount = 20; private Vector2 _scrollPosition; private void OnGUI() { // 高さを指定すると領域が確保されてしまうので、UIがおかしくなる var rect = GUILayoutUtility.GetRect(position.width, 0); rect.height = EditorGUIUtility.singleLineHeight * 5; var viewRect = new Rect() { x = 0, y = 0, width = rect.width - 20, height = EditorGUIUtility.singleLineHeight * ScrollItemCount, }; using (var scroll = new GUI.ScrollViewScope(rect, _scrollPosition, viewRect)) { _scrollPosition = scroll.scrollPosition; for (var i = 0; i < ScrollItemCount; i++) { GUILayout.Label(i.ToString()); } } }
GUI.ClipScope
指定した Rect を確保し、x, y=0から始まる新しい Rect を作成する
private void OnGUI() { var rect = GUILayoutUtility.GetRect(position.width, EditorGUIUtility.singleLineHeight * 2); using (new GUI.ClipScope(rect)) { rect.x = rect.y = 0; rect.height = EditorGUIUtility.singleLineHeight; GUI.Label(rect, "AreaLabel1"); rect.y += EditorGUIUtility.singleLineHeight; GUI.Label(rect, "AreaLabel2"); } GUILayout.Label("Label"); }
GUI.GroupScope
これはClipに機能が足されたものでヘッダーテキスト・背景画像・GUIStyle
を適応することができる
var rect = GUILayoutUtility.GetRect(position.width, EditorGUIUtility.singleLineHeight * 3); using (new GUI.GroupScope(rect, "GroupScope")) { rect.x = 0; rect.y = EditorGUIUtility.singleLineHeight; rect.height = EditorGUIUtility.singleLineHeight; GUI.Label(rect, "AreaLabel1"); rect.y += EditorGUIUtility.singleLineHeight; GUI.Label(rect, "AreaLabel2"); } rect = GUILayoutUtility.GetRect(position.width, EditorGUIUtility.singleLineHeight * 2); using (new GUI.GroupScope(rect, GUI.skin.box)) { rect.x = rect.y = 0; rect.height = EditorGUIUtility.singleLineHeight; GUI.Label(rect, "AreaLabel1"); rect.y += EditorGUIUtility.singleLineHeight; GUI.Label(rect, "AreaLabel2"); }
GUILayout
GUILayout.ScrollViewScope
private const int ScrollItemCount = 20; private Vector2 _scrollPosition; private void OnGUI() { using (var scroll = new GUILayout.ScrollViewScope(_scrollPosition)) { _scrollPosition = scroll.scrollPosition; for (var i = 0; i < ScrollItemCount; i++) { GUILayout.Label(i.ToString()); } } }
GUILayout.AreaScope
現在のRect から 範囲を指定して、x, y=0から始まる新しい Rect を作成する
スコープ内部で EditorGUILayout.GetControlRect
を使うと rect.width が1になってしまうため使用には注意
private void OnGUI() { var rect = new Rect(0, 0, position.width, EditorGUIUtility.singleLineHeight * 2); using (new GUILayout.AreaScope(rect)) { rect.x = rect.y = 0; rect.height = EditorGUIUtility.singleLineHeight; GUI.Label(rect, "AreaLabel1"); rect.y += EditorGUIUtility.singleLineHeight; GUI.Label(rect, "AreaLabel2"); } // 領域を確保してないので これだと描画が崩れる // GUILayout.Label("Label"); // GUILayout.AreaScope で利用した分だけ確保する GUILayoutUtility.GetRect(position.width, EditorGUIUtility.singleLineHeight * 2); GUILayout.Label("Label"); }
GUILayout.HorizontalScope
スコープ内要素を水平に表示する
private void OnGUI() { using (new GUILayout.HorizontalScope()) { GUILayout.Label("Horizontal1"); GUILayout.Label("Horizontal2"); } }
GUILayout.VerticalScope
スコープ内要素を垂直に表示する
private void OnGUI() { using (new GUILayout.HorizontalScope()) { using (new GUILayout.VerticalScope()) { GUILayout.Label("Vertical1"); GUILayout.Label("Vertical2"); } GUILayout.Label("Horizontal3"); } }
EditorGUI
EditorGUI.PropertyScope
これを利用することで Prefab化時に差分が出た場合に
変更箇所をわかりやすくしてくれる
using System; using UnityEngine; #if UNITY_EDITOR using UnityEditor; #endif public class SampleBehaviour : MonoBehaviour { [SerializeField] private SampleClass _sample; [SerializeField] private int _noChangeintValue1; } [Serializable] public class SampleClass { [SerializeField] private int _intValue1; [SerializeField] private int _intValue2; } #if UNITY_EDITOR [CustomPropertyDrawer(typeof(SampleClass))] public class SampleClassDrawer : PropertyDrawer { public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { using (var scope = new EditorGUI.PropertyScope(position, label, property)) { label = scope.content; position.height = EditorGUIUtility.singleLineHeight; EditorGUI.PropertyField(position, property.FindPropertyRelative("_intValue1")); position.y += EditorGUIUtility.singleLineHeight; EditorGUI.PropertyField(position, property.FindPropertyRelative("_intValue2")); } } public override float GetPropertyHeight(SerializedProperty property, GUIContent label) { return EditorGUIUtility.singleLineHeight * 2; } } #endif
EditorGUI.ChangeCheckScope
スコープ内に変更があった場合 change.changed が true になる
private int _intValue; private void OnGUI() { using (var change = new EditorGUI.ChangeCheckScope()) { _intValue = EditorGUILayout.IntField(_intValue); if (change.changed) { Debug.Log("Change int Value"); } } }
EditorGUI.IndentLevelScope
スコープ内のインデントを変更する
private void OnGUI() { EditorGUILayout.LabelField("indentLevel:" + EditorGUI.indentLevel); using (new EditorGUI.IndentLevelScope(1)) { EditorGUILayout.LabelField("indentLevel:" + EditorGUI.indentLevel); } using (new EditorGUI.IndentLevelScope(5)) { EditorGUILayout.LabelField("indentLevel:" + EditorGUI.indentLevel); } }
EditorGUI.DisabledScope
スコープ内の操作可否を変更する
private bool _isValid; private int _enableValue; private int _disableValue; private void OnGUI() { _isValid = EditorGUILayout.ToggleLeft("Switch", _isValid); using (new EditorGUI.DisabledScope(!_isValid)) { EditorGUILayout.LabelField("Switch On"); _enableValue = EditorGUILayout.IntField(_enableValue); } using (new EditorGUI.DisabledScope(_isValid)) { EditorGUILayout.LabelField("Switch Off"); _disableValue = EditorGUILayout.IntField(_disableValue); } }
EditorGUI.DisabledGroupScope
操作可否をネストできるスコープ
private bool _isValid; private bool _isValidSub; private void OnGUI() { _isValid = EditorGUILayout.ToggleLeft("Switch", _isValid); _isValidSub = EditorGUILayout.ToggleLeft("SwitchSub", _isValidSub); using (new EditorGUI.DisabledGroupScope(!_isValid)) { EditorGUILayout.LabelField("Switch On"); using (new EditorGUI.IndentLevelScope(1)) { using (new EditorGUI.DisabledScope(!_isValidSub)) { EditorGUILayout.LabelField("SubSwitch On"); } using (new EditorGUI.DisabledScope(_isValidSub)) { EditorGUILayout.LabelField("SubSwitch On"); } } } using (new EditorGUI.DisabledGroupScope(_isValid)) { EditorGUILayout.LabelField("Switch Off"); using (new EditorGUI.IndentLevelScope(1)) { using (new EditorGUI.DisabledScope(!_isValidSub)) { EditorGUILayout.LabelField("SubSwitch On"); } using (new EditorGUI.DisabledScope(_isValidSub)) { EditorGUILayout.LabelField("SubSwitch On"); } } } }
EditorGUILayout
EditorGUILayout.ScrollViewScope
private const int ScrollItemCount = 20; private Vector2 _scrollPosition; private void OnGUI() { using (var scrollView = new EditorGUILayout.ScrollViewScope(_scrollPosition)) { _scrollPosition = scrollView.scrollPosition; for (var i = 0; i < ScrollItemCount; i++) { EditorGUILayout.LabelField(i.ToString()); } } }
EditorGUILayout.HorizontalScope
スコープ内を水平に表示する
GUILayout.HorizontalScope
は幅を考慮してくれるが、こちらは幅を考慮しない
private void OnGUI() { using (new EditorGUILayout.HorizontalScope()) { EditorGUILayout.LabelField("Label1"); EditorGUILayout.LabelField("Label2"); EditorGUILayout.LabelField("Label3"); } }
EditorGUILayout.VerticalScope
スコープ内を垂直に表示する
private void OnGUI() { using (new EditorGUILayout.HorizontalScope()) { using (new EditorGUILayout.VerticalScope()) { EditorGUILayout.LabelField("VerticalLabel1"); EditorGUILayout.LabelField("VerticalLabel2"); } EditorGUILayout.LabelField("HorizontalLabel"); } }
EditorGUILayout.FadeGroupScope
Animation するトグルメニューを表示できる
private AnimBool _animBool; private Color _color; private string _text = ""; private int _number; void OnEnable() { _animBool = new AnimBool(true); _animBool.valueChanged.AddListener(new UnityAction(Repaint)); } private void OnGUI() { _animBool.target = EditorGUILayout.ToggleLeft("Show extra fields", _animBool.target); //Extra block that can be toggled on and off. using (var group = new EditorGUILayout.FadeGroupScope(_animBool.faded)) { if (group.visible) { using (new EditorGUI.IndentLevelScope()) { EditorGUILayout.PrefixLabel("Color"); _color = EditorGUILayout.ColorField(_color); EditorGUILayout.PrefixLabel("Text"); _text = EditorGUILayout.TextField(_text); EditorGUILayout.PrefixLabel("Number"); _number = EditorGUILayout.IntSlider(_number, 0, 10); } } } }
EditorGUILayout.ToggleGroupScope
トグルを入れ子にできる
親トグルがOnではないと子トグルは操作ができない
private bool _toggle; private bool[] _toggles = new bool[] { true, true, true }; private void OnGUI() { using (var _toggleGroup = new EditorGUILayout.ToggleGroupScope("Align position", _toggle)) { _toggle = _toggleGroup.enabled; _toggles[0] = EditorGUILayout.Toggle("x", _toggles[0]); _toggles[1] = EditorGUILayout.Toggle("y", _toggles[1]); _toggles[2] = EditorGUILayout.Toggle("z", _toggles[2]); } }
EditorGUIUtility
EditorGUIUtility.IconSizeScope
GUIContent
のアイコンサイズを変更できる
1行高さ (16) を超えると画像が見切れるので高さを指定する必要がある
private void OnGUI() { EditorGUILayout.LabelField("8 * 8"); using (new EditorGUIUtility.IconSizeScope(Vector2.one * 8)) { EditorGUILayout.LabelField(EditorGUIUtility.TrIconContent("BuildSettings.SelectedIcon")); } EditorGUILayout.LabelField("16 * 16"); using (new EditorGUIUtility.IconSizeScope(Vector2.one * 16)) { EditorGUILayout.LabelField(EditorGUIUtility.TrIconContent("BuildSettings.SelectedIcon")); } EditorGUILayout.LabelField("32 * 32"); using (new EditorGUIUtility.IconSizeScope(Vector2.one * 32)) { EditorGUILayout.LabelField(EditorGUIUtility.TrIconContent("BuildSettings.SelectedIcon"), GUILayout.Height(32)); } }
カスタムスコープ
// Hierarchy で複数選択時 スコープ内 のIntField等の値部分を 「-」表示できる public class MixedValueScope : GUI.Scope { private readonly bool _cacheValue; public MixedValueScope() { _cacheValue = EditorGUI.showMixedValue; EditorGUI.showMixedValue = true; } protected override void CloseScope() { EditorGUI.showMixedValue = _cacheValue; } } // スコープ内の 色を変更する public class ColorScope : GUI.Scope { private readonly Color _cacheValue; public ColorScope(Color color) { _cacheValue = GUI.color; GUI.color = color; } protected override void CloseScope() { GUI.color = _cacheValue; } }