前回でインスペクタに独自UIを描画する準備が整いました。
今回はOnGUIの記法について書いていきます。
基本ルール
描画に使えるのはEditorGUIクラスのみです。 MonoBehaviourなどではEditorGUILayoutクラスを使って簡単にレイアウトできるのをご存知かもしれませんが、PropertyDrawer では一切使えません。実行時に例外が発生します。
レイアウト用のポジション指定は自分でやらなければならないのです。
また、OnGUIは一要素につき一回呼ばれます。 例えば 通常の変数では一回の画面描画につき一回呼ばれますが、配列では配列の要素数分だけ呼ばれます。
上記は基本的なルールなので必ず覚えておきましょう。
描画時に使うと便利なクラス
「えー、レイアウト自分でやるってことは、Rect型の変数をピクセル単位で指定するの?」 と面倒くさそうにしているのはわかります。
実はピクセル指定に使えるEditorGUIUtilityという便利クラスがあるのです。
鍵になるのは
EditorGUIUtility.singleLineHeight、EditorGUIUtility.currentViewWidth、EditorGUIUtility.labelWidth
で、それぞれ
- 一行のデフォルトの高さ
- 現在表示中のインスペクタの幅
- 描画したラベルの幅
を指しています。 これらを駆使すればレイアウト指定はだいぶ楽になります。
一行書いてみるサンプル
ためしに、下画像の赤枠のような、基本的な入力を作ってみます。
public class MyValueDrawer : PropertyDrawer { public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { // ラベル EditorGUI.LabelField(position, "test value"); // float値入力のテキストボックス float value = EditorGUI.FloatField( new Rect( EditorGUIUtility.labelWidth, position.y, position.width - EditorGUIUtility.labelWidth, EditorGUIUtility.singleLineHeight ), 0 // ***** ここはあとで修正 ); // GameObject (Prefab) の場合 var newobj = EditorGUI.ObjectField( new Rect( EditorGUIUtility.labelWidth, position.y + (i * EditorGUIUtility.singleLineHeight), position.width - EditorGUIUtility.labelWidth, EditorGUIUtility.singleLineHeight ), (Object)property.objectReferenceValue, typeof(GameObject), false ); } }
上のようにRectを指定してやれば、ラベルの右に入力フォームが現れるように描画できます。
さきほど配列の個数分だけOnGUIが呼ばれると書きましたが、そのときRectの
y座標に配列のインデックスを加味する必要はありません。わざわざ
position.y * index
などとやらなくても、y座標だけは毎回そのまま渡してやればよいです。
縦に長いものを作るときは?
上のままだとちょっとつまらないです。 せっかく独自UIなんだから独自UIを書きたいですよね。
こんな感じで入力の下にラベルを書きたいとします。
このとき、1要素で2行分のスペースを確保する必要があります。
その場合PropertyDrawer.GetPropertyHeight をオーバーライドしましょう。
public override float GetPropertyHeight(SerializedProperty property, GUIContent label) { return EditorGUIUtility.singleLineHeight * 2; }
こんな感じで確保したいだけの高さを返すようにすれば、その分縦方向のスペースを確保できるようになります。
この関数も要素数分だけ呼ばれる(配列の個数分呼ばれる)ので注意が必要です。
さあ、これで独自UIが書けました! やった! 終了!
などと安心するのはまだ早い。
まだ入力した値を保存するという、本質的な大仕事が残っています。
嫌な予感がしますよね? ね?
次回へ続く!