北京网站建设收费,凡客沙发官网,凡客登录,网站建设需经历的步骤简介 为了提升枚举的复用性#xff0c;有时候我们可以通过限定枚举字段的范围来避免定义新的枚举类型#xff0c;例如有一个代表方向的枚举#xff08;包括None#xff0c;Left#xff0c;Up#xff0c;Right#xff0c;Down#xff09;#xff0c;全局方向#xff0…简介 为了提升枚举的复用性有时候我们可以通过限定枚举字段的范围来避免定义新的枚举类型例如有一个代表方向的枚举包括NoneLeftUpRightDown全局方向LeftUpRightDown水平方向LeftRight竖直方向UpDown。
代码示例(C#)
EnumRangeAttribute.cs
using System;
using System.Linq;
using UnityEngine;/// summary
/// 枚举范围限定特性
/// /summary
[AttributeUsage(AttributeTargets.Field, AllowMultiple false, Inherited false)]
public class EnumRangeAttribute : PropertyAttribute
{/// summary/// 枚举最小值/// /summarypublic int mMin { get; }/// summary/// 枚举最大值/// /summarypublic int mMax { get; }/// summary/// 枚举名称合集/// /summarypublic string[] mEnumNames { get enumNames?.ToArray(); }/// summary/// 枚举值合集/// /summarypublic int[] mEnumValues { get enumValues?.ToArray(); }/// summary/// 枚举范围特性模式/// /summarypublic EnumRangeMode mEnumRangeMode { get; }private string[] enumNames;private int[] enumValues;/// summary/// 构造函数/// /summary/// param namemin枚举最小值/param/// param namemax枚举最大值/parampublic EnumRangeAttribute(int min, int max){mMin min;mMax max;mEnumRangeMode EnumRangeMode.MinAndMax;}/// summary/// 构造函数/// /summary/// param nameenumNames枚举名称合集 (大小写敏感)/parampublic EnumRangeAttribute(params string[] enumNames){this.enumNames enumNames;mEnumRangeMode EnumRangeMode.EnumNames;}/// summary/// 构造函数/// /summary/// param nameenumValues枚举值合集/parampublic EnumRangeAttribute(int[] enumValues){this.enumValues enumValues;mEnumRangeMode EnumRangeMode.EnumValues;}/// summary/// 枚举范围特性模式/// /summarypublic enum EnumRangeMode{MinAndMax, EnumNames, EnumValues}
}EnumRangeAttributeDrawer.cs
using UnityEngine;
using UnityEditor;
using System;
using System.Linq;/// summary
/// 枚举范围限定特性绘制器
/// /summary
[CustomPropertyDrawer(typeof(EnumRangeAttribute))]
public class EnumRangeAttributeDrawer : PropertyDrawer
{private EnumRangeAttribute enumRangeAttribute; // 枚举范围特性private Type enumType; // 枚举类型private string[] rawEnumNames; // 枚举名称原始合集private string[] displayNames; // 下拉菜单显示名称合集private int selectedIndex; // 当前所选中的选项索引private int preIndex; // 所选中的选项索引的副本private bool isLockGUI; // 是否锁定GUI的绘制private bool isInit; // 是否初始化private string warningText; // 警告信息private string preWarningText; // 警告信息副本public override float GetPropertyHeight(SerializedProperty property, GUIContent label){return EditorGUI.GetPropertyHeight(property, label, true);}public override void OnGUI(Rect position, SerializedProperty property, GUIContent label){if (fieldInfo.FieldType.IsEnum){Init(property);if (!isLockGUI){selectedIndex EditorGUI.Popup(position, label, selectedIndex, displayNames.Select(n new GUIContent(n)).ToArray());if (selectedIndex ! preIndex){preIndex selectedIndex;property.enumValueIndex IndexOf(displayNames[selectedIndex]);}}}else warningText $Warning:The type of the field {fieldInfo.Name} marked with EnumRange attribute is not Enum.;if (!warningText.Equals(preWarningText)){Debug.LogWarning(warningText);preWarningText warningText;}}// 初始化private void Init(SerializedProperty property){if (!isInit){isLockGUI true;isInit true;enumRangeAttribute (EnumRangeAttribute)attribute;if (enumRangeAttribute null){warningText $Warning:The field {fieldInfo.Name} is not marked EnumRange attribute.;return;}enumType fieldInfo.FieldType;rawEnumNames property.enumNames;if (rawEnumNames null || rawEnumNames.Length 0){warningText $Warning:The enums names of the field {property.name} is null or empty.;return;}if (!InitDisplayNames()) displayNames rawEnumNames;selectedIndex Array.FindIndex(displayNames, n n.Equals(rawEnumNames[property.enumValueIndex]));if (selectedIndex -1) selectedIndex 0;preIndex selectedIndex;warningText string.Empty;preWarningText string.Empty;isLockGUI false;}}// 初始化枚举下拉菜单显示名称合集private bool InitDisplayNames(){switch (enumRangeAttribute.mEnumRangeMode){case EnumRangeAttribute.EnumRangeMode.MinAndMax:return MinAndMaxInit();case EnumRangeAttribute.EnumRangeMode.EnumNames:return EnumNamesInit();case EnumRangeAttribute.EnumRangeMode.EnumValues:return EnumValuesInit();}return false;}// MinAndMax模式初始化private bool MinAndMaxInit(){if (enumRangeAttribute.mMin enumRangeAttribute.mMax) return false;var v_values Enum.GetValues(enumType).Castint();if (v_values.Count() 0) return false;v_values v_values.Where(val val enumRangeAttribute.mMin val enumRangeAttribute.mMax);if (v_values.Count() 0) return false;var v_names v_values.Select(val Enum.GetName(enumType, val));if (v_names.Count() 0) return false;displayNames v_names.ToArray();return true;}// EnumNames模式初始化private bool EnumNamesInit(){if (enumRangeAttribute.mEnumNames null || enumRangeAttribute.mEnumNames.Length 0) return false;var v_names enumRangeAttribute.mEnumNames.Where(n Array.FindIndex(rawEnumNames, en en.Equals(n)) ! -1);if (v_names.Count() 0) return false;displayNames v_names.ToArray();return true;}// EnumValues模式初始化private bool EnumValuesInit(){if (enumRangeAttribute.mEnumValues null || enumRangeAttribute.mEnumValues.Length 0) return false;var v_values Enum.GetValues(enumType).Castint();if (v_values.Count() 0) return false;v_values v_values.Where(val enumRangeAttribute.mEnumValues.Contains(val));if (v_values.Count() 0) return false;var v_names v_values.Select(val Enum.GetName(enumType, val));if (v_names.Count() 0) return false;displayNames v_names.ToArray();return true;}// 返回指定名称的枚举在原始枚举合集中的索引private int IndexOf(string enumName){int index Array.FindIndex(rawEnumNames, n n.Equals(enumName));return index -1 ? 0 : index;}
}效果截图 如果这篇文章对你有帮助请给作者点个赞吧