2016年5月16日月曜日

[UnityEditor拡張]Inspectorの配列のラベルをenumに差し替える

Inspectorに配列やリストを表示すると要素のラベルが「Element 0」「Element 1」...になるのをenumで置き換えるエディタ拡張を作りました。
上を下に置き換える。


使い方

配列のフィールド属性にEnumLabelを付けるだけ。引数はtypeof(enumの型)。
using System;
using UnityEngine;
public class EnumLabelSample : MonoBehaviour{
[EnumLabel(typeof(Fruit))]
public string[] names = new string[Enum.GetValues(typeof(Fruit)).Length];
private enum Fruit {
Orange,
Apple,
Banana,
}
}


ソースコード

配列要素のlabelの「Element 0」の数字部分をパースして対応するenumに置き換えているだけ。
/**
EnumLabel.cs
Copyright (c) 2016 Hassaku
This software is released under the MIT License.
http://opensource.org/licenses/mit-license.php
*/
using UnityEngine;
using UnityEngine.Assertions;
using System;
using System.Text.RegularExpressions;
#if UNITY_EDITOR
using UnityEditor;
#endif
[AttributeUsage(AttributeTargets.Field)]
public class EnumLabelAttribute : PropertyAttribute{
public string[] EnumNames { get; private set; }
public EnumLabelAttribute(Type enumType) {
Assert.IsTrue(enumType.IsEnum, "[EnumLabel] type of attribute parameter is not enum.");
EnumNames = Enum.GetNames(enumType);
}
}
#if UNITY_EDITOR
[CustomPropertyDrawer(typeof(EnumLabelAttribute))]
public class EnumLabelDrawer : PropertyDrawer {
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) {
EnumLabelAttribute attr = attribute as EnumLabelAttribute;
Match match = new Regex(@"Element (?<index>\d+)").Match(label.text);
if(!match.Success){
EditorGUI.PropertyField(position, property, label);
return;
}
int index = int.Parse(match.Groups["index"].Value);
if (index < attr.EnumNames.Length) {
EditorGUI.PropertyField(position, property, new GUIContent(attr.EnumNames[index]), true);
}
else {
EditorGUI.PropertyField(position, property, label, true);
}
}
public override float GetPropertyHeight(SerializedProperty property, GUIContent label) {
return EditorGUI.GetPropertyHeight(property);
}
}
#endif
view raw EnumLabel.cs hosted with ❤ by GitHub


問題点

sizeの入力を縛っていないので、enumの定義数と配列の要素数に関係がありません。
要素数がenumの定義より多い場合はこうなります。

PropertyDrawer.OnGUIの引数のpropertyで取れるのが配列要素のpropertyなので、配列全体のGUIを制御することができずこの実装となりました。
配列やリスト全体の表示を描き換える方法ってないんですかね?

2017/12/23追記

コメントにて指摘をいただきましたので反映いたしました。ありがとうございます!
EditorGUILayout#PropertyField()はbool値で子要素を展開するかを指定できるようです。常にtrueでいいような...
ちなみにこの記事の内容は古くて最新のUnityに対応しているかはわかりません。ちゃんと動作させた環境の情報は書こうな...

1 件のコメント:

  1. 初めまして。便利な拡張なので使わせていただいています。

    43行目の
    EditorGUI.PropertyField(position, property, new GUIContent(attr.EnumNames[index]));
    ですが、このままだとSerializableした自作クラスを表示する際に、中身が表示されないので、
    EditorGUI.PropertyField(position, property, new GUIContent(attr.EnumNames[index]), true); //最後尾に引数を追加
    したほうがよいかと思います。

    返信削除