Search Unity

Enum inspector sorting attribute

Discussion in 'Immediate Mode GUI (IMGUI)' started by chai, Sep 27, 2015.

  1. chai

    chai

    Joined:
    Jun 3, 2009
    Posts:
    84
    Enums are awesome, but they often get disorganized quickly !
    So i wrote this custom attribute that allows resorting the enum without messing with the values/indexes.
    First save the two attached scripts to your project, then see usage example at botom of post.

    Feel free to modify, use for your project, or share here as you wish :)

    EnumOrder.cs
    Code (csharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using System;
    4.  
    5. [System.AttributeUsage (System.AttributeTargets.Field)]
    6. public class EnumOrder : PropertyAttribute {
    7.  
    8.     public readonly int[] order;
    9.  
    10.     public EnumOrder (string _orderStr) {
    11.        this.order = StringToInts(_orderStr);
    12.     }
    13.  
    14.     public EnumOrder (int[] _order) {
    15.        this.order = _order;
    16.      }
    17.  
    18.     int[] StringToInts (string str) {
    19.        string[] stringArray = str.Split(',');
    20.        int[] intArray = new int[stringArray.Length];
    21.        for (int i=0; i<stringArray.Length; i++)
    22.        intArray[i] = System.Int32.Parse (stringArray[i]);
    23.  
    24.        return (intArray);
    25.     }
    26.  
    27. }
    EnumOrderDrawer.cs
    Code (csharp):
    1. using UnityEngine;
    2. using UnityEditor;
    3.  
    4. [CustomPropertyDrawer(typeof(EnumOrder))]
    5. public class EnumOrderDrawer : PropertyDrawer {
    6.  
    7.     EnumOrder enumOrder { get { return ((EnumOrder)attribute); } }
    8.  
    9.     public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) {
    10.  
    11.         EditorGUI.BeginProperty(position, label, property);
    12.  
    13.         // Store array of indexes based on ascending value
    14.         int[] indexArray = GetIndexArray (enumOrder.order);
    15.  
    16.         // Store resorted string array for the popup item names
    17.         string[] items = new string[property.enumNames.Length];
    18.         items[0] = property.enumNames[0];
    19.         for (int i=0; i<property.enumNames.Length; i++) {
    20.              items[i] = property.enumNames[indexArray[i]];
    21.         }
    22.  
    23.         // Get selected enum based on position
    24.         int index = -1;
    25.         for (int i=0; i<indexArray.Length; i++) {
    26.             if (indexArray[i] == property.enumValueIndex) {
    27.                 index = i;
    28.                 break;
    29.             }
    30.         }
    31.         if ( (index == -1) && (property.enumValueIndex != -1) ) { SortingError (position,property,label); return; }
    32.  
    33.         // Display popup
    34.         index = EditorGUI.Popup(
    35.             position,
    36.             label.text,
    37.             index,
    38.             items );
    39.         property.enumValueIndex = indexArray[index];
    40.  
    41.         // Default
    42.         //EditorGUI.PropertyField(position, property, new GUIContent("*" + label.text));
    43.  
    44.         EditorGUI.EndProperty();
    45.  
    46.     }
    47.  
    48.     int[] GetIndexArray (int[] order) {
    49.  
    50.         int[] indexArray = new int[order.Length];
    51.  
    52.         for (int i = 0; i < order.Length; i++) {
    53.             int index = 0;
    54.             for (int j = 0; j < order.Length; j++) {
    55.                 if (order[i] > order[j]) {
    56.                     index++;
    57.                 }
    58.             }
    59.  
    60.             indexArray[i] = index;
    61.  
    62.         }
    63.  
    64.         return (indexArray);
    65.  
    66.     }
    67.  
    68.     /// Use default enum popup, but flag label to aware user
    69.     void SortingError (Rect position, SerializedProperty property, GUIContent label) {
    70.  
    71.         EditorGUI.PropertyField(position, property, new GUIContent(label.text + " (sorting error)"));
    72.         EditorGUI.EndProperty();
    73.  
    74.     }
    75.  
    76. }

    Usage Examples
    Implementing in code is simple, here are some examples.
    Code (csharp):
    1. using UnityEngine;
    2.  
    3. public class EnumTest : MonoBehaviour {
    4.  
    5.     public const string TypeOrder = "10,1,5,2";
    6.     public enum Type {
    7.         One = 10,
    8.         Two = 1,
    9.         Three = 5,
    10.         Four = 2,
    11.     }
    12.  
    13.     [EnumOrder("10,1,5,2")]
    14.     public Type type1;
    15.  
    16.     [EnumOrder(new int[] { 10, 1, 5, 2 })]
    17.     public Type type2;
    18.  
    19.     [EnumOrder(TypeOrder)]
    20.     public Type type3;
    21.  
    22. }
     

    Attached Files:

    Last edited: Sep 28, 2015