本文固定链接: http://www.xuanyusong.com/archives/4213 转载请注明: 雨松MOMO 2016年07月13日 于 雨松MOMO程序研究院 发表
虽然mono是支持unicode的。可以在枚举里写中文,但是我还是觉得写英文好一些。可是在编辑器上策划是希望看到的是中文的,还有就是枚举的展示排序功能,策划在编辑的时候为了方便希望把常用的枚举排上前面。
把如下代码放到你的工程里就可以直接用了。
using UnityEngine; using System; #if UNITY_EDITOR using UnityEditor; using System.Collections.Generic; using System.Linq; using System.Reflection; #endif [AttributeUsage(AttributeTargets.Enum | AttributeTargets.Field)] public class EnumLabelAttribute : PropertyAttribute { public string label; public int[] order = new int[0] ; public EnumLabelAttribute(string label) { this.label = label; } public EnumLabelAttribute(string label,params int[] order) { this.label = label; this.order = order; } } #if UNITY_EDITOR [CustomPropertyDrawer(typeof(EnumLabelAttribute))] public class EnumLabelDrawer : PropertyDrawer { private Dictionary<string, string> customEnumNames = new Dictionary<string, string>(); public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { SetUpCustomEnumNames(property, property.enumNames); if (property.propertyType == SerializedPropertyType.Enum) { EditorGUI.BeginChangeCheck(); string[] displayedOptions = property.enumNames .Where(enumName => customEnumNames.ContainsKey(enumName)) .Select<string, string>(enumName => customEnumNames[enumName]) .ToArray(); int[] indexArray = GetIndexArray (enumLabelAttribute.order); if(indexArray.Length != displayedOptions.Length) { indexArray = new int[displayedOptions.Length]; for(int i =0; i< indexArray.Length; i++){ indexArray[i] = i; } } string[] items = new string[displayedOptions.Length]; items[0] = displayedOptions[0]; for (int i=0; i<displayedOptions.Length; i++) { items[i] = displayedOptions[indexArray[i]]; } int index = -1; for (int i=0; i<indexArray.Length; i++) { if (indexArray[i] == property.enumValueIndex) { index = i; break; } } if ( (index == -1) && (property.enumValueIndex != -1) ) { SortingError (position,property,label); return; } index = EditorGUI.Popup(position, enumLabelAttribute.label,index, items); if (EditorGUI.EndChangeCheck()) { if (index >= 0) property.enumValueIndex = indexArray[index]; } } } private EnumLabelAttribute enumLabelAttribute { get { return (EnumLabelAttribute)attribute; } } public void SetUpCustomEnumNames(SerializedProperty property, string[] enumNames) { object[] customAttributes = fieldInfo.GetCustomAttributes(typeof(EnumLabelAttribute), false); foreach (EnumLabelAttribute customAttribute in customAttributes) { Type enumType = fieldInfo.FieldType; foreach (string enumName in enumNames) { FieldInfo field = enumType.GetField(enumName); if (field == null) continue; EnumLabelAttribute[] attrs = (EnumLabelAttribute[])field.GetCustomAttributes(customAttribute.GetType(), false); if (!customEnumNames.ContainsKey(enumName)) { foreach (EnumLabelAttribute labelAttribute in attrs) { customEnumNames.Add(enumName, labelAttribute.label); } } } } } int[] GetIndexArray (int[] order) { int[] indexArray = new int[order.Length]; for (int i = 0; i < order.Length; i++) { int index = 0; for (int j = 0; j < order.Length; j++) { if (order[i] > order[j]) { index++; } } indexArray[i] = index; } return (indexArray); } void SortingError (Rect position, SerializedProperty property, GUIContent label) { EditorGUI.PropertyField(position, property, new GUIContent(label.text + " (sorting error)")); EditorGUI.EndProperty(); } } public class EnumLabel { static public object GetEnum(Type type, SerializedObject serializedObject, string path) { SerializedProperty property = GetPropety(serializedObject,path); return System.Enum.GetValues(type).GetValue(property.enumValueIndex); } static public object DrawEnum(Type type, SerializedObject serializedObject, string path) { return DrawEnum(type,serializedObject, GetPropety(serializedObject,path)); } static public object DrawEnum(Type type, SerializedObject serializedObject,SerializedProperty property) { serializedObject.Update(); EditorGUILayout.PropertyField(property); serializedObject.ApplyModifiedProperties(); return System.Enum.GetValues(type).GetValue(property.enumValueIndex); } static public SerializedProperty GetPropety(SerializedObject serializedObject, string path) { string []contents = path.Split('/'); SerializedProperty property = serializedObject.FindProperty(contents[0]); for(int i=1; i< contents.Length; i++){ property = property.FindPropertyRelative(contents[i]); } return property; } } #endif使用是这样的,第二个参数就是排序。接收int的不固定参数。
using UnityEngine; using System.Collections; public class NewBehaviourScript : MonoBehaviour { [EnumLabel("我是的类型",10,1,5,2)] public NewType newType = NewType.One; } public enum NewType : byte { [EnumLabel("我是1")] One = 10, [EnumLabel("我是2")] Two = 1, [EnumLabel("我是3")] Three = 5, [EnumLabel("我是4")] Four = 2 }OK 中文与排序都OK了。 但是,有时候我们做编辑器的时候是自己调用OnInspectorGUI来绘制面板的。而且我的枚举对象可能会在另外一个子对象里,或者在子对象里的一个List里面的子对象里。
比如这样, class.data.newType 就是这个类对象的结构,你可以按照你自己类的结构去拼这个字符串。
public override void OnInspectorGU() { NewType oldType = (NewType)EnumLabel.GetEnum(typeof(NewType),serializedObject,"class/data/newType"); NewType newType = (NewType)EnumLabel.DrawEnum(typeof(NewType),serializedObject,"class/data/newType"); if(oldType != newType) { //类型发生改变 } }还有一种特殊的就是可能枚举在list里,这样在绘制的时候是需要遍历的。
public override void OnInspectorGU() { SerializedProperty property = EnumLabel.GetPropety(serializedObject,"class/datas"); for(int i =0; i< count; i++) { SerializedProperty eProperty = property.GetArrayElementAtIndex(i); NewType newType = (NewType)EnumLabel.DrawEnum(typeof(NewType),serializedObject ,eProperty.FindPropertyRelative("newType")); } }OK大功告成。
参考文章:
https://github.com/anchan828/property-drawer-collection/blob/master/EnumLabel/EnumLabelAttribute.cs
http://forum.unity3d.com/threads/enum-inspector-sorting-attribute.357558/
转by:蒋志杰