Search Unity

Displaying an Array inside a ReorderableList

Discussion in 'Scripting' started by Camronas, Sep 15, 2018.

  1. Camronas

    Camronas

    Joined:
    Apr 20, 2012
    Posts:
    154
    Hello,

    I am trying to make a custom editor with a reorderable list for an AI Profiler script I am working on.

    For the most part everything is working as expected with one critical issue:
    upload_2018-9-15_18-59-44.png
    As you can see elements are being drawn ontop of each other which is a huge pain. To make matters worse I am unable to edit the array that is being shown. I can set the array size but none of the properties inside of it.

    The State field on the left works perfectly, but everything on the right is broken.

    My Editor Code looks like this:

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEditor;
    5. using UnityEditorInternal;
    6.  
    7. [CustomEditor(typeof(AIProfile))]
    8. public class AIProfile_Editor : Editor
    9. {
    10.     private ReorderableList _aiHandles;
    11.  
    12.     private void OnEnable()
    13.     {
    14.         _aiHandles = new ReorderableList(serializedObject, serializedObject.FindProperty("_aiHandles"), true, true, true, true);
    15.         _aiHandles.drawElementCallback =
    16.             (Rect rect, int index, bool isActive, bool isFocused) =>
    17.             {
    18.                 var element = _aiHandles.serializedProperty.GetArrayElementAtIndex(index);
    19.                 rect.y +=2;
    20.                 EditorGUI.PropertyField(new Rect(rect.x, rect.y, 100, EditorGUIUtility.singleLineHeight), element.FindPropertyRelative("_state"), GUIContent.none);
    21.                 EditorGUI.PropertyField(new Rect(rect.x + 120, rect.y, 120, EditorGUIUtility.singleLineHeight), element.FindPropertyRelative("_transitions"), true);
    22.             }
    23.             ;
    24.     }
    25.  
    26.     public override void OnInspectorGUI()
    27.     {
    28.         serializedObject.Update();
    29.         _aiHandles.DoLayoutList();
    30.         serializedObject.ApplyModifiedProperties();
    31.     }
    32. }
    33.  
    Any and all help is greatly appreciated! Thank you for your time!
     
  2. villevli

    villevli

    Joined:
    Jan 19, 2016
    Posts:
    87
    Fixes:
    • Set _aiHandles.elementHeightCallback to calculate the height required by each element using EditorGUI.GetPropertyHeight()
    • Replaced EditorGUIUtility.singleLineHeight with EditorGUI.GetPropertyHeight() to pass a correct size rect to EditorGUI.PropertyField
    • Fixed the width of the "_transitions" property by replacing (120) with (rect.width - 120)
    Optional fixes:
    • Set _aiHandles.drawHeaderCallback to draw a custom label for the list instead of "Serialized Property"
    • Using EditorGUIUtility.standardVerticalSpacing instead of 2.
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEditor;
    5. using UnityEditorInternal;
    6.  
    7. [CustomEditor(typeof(AIProfile))]
    8. public class AIProfileEditor : Editor
    9. {
    10.     private ReorderableList _aiHandles;
    11.  
    12.     private void OnEnable()
    13.     {
    14.         _aiHandles = new ReorderableList(serializedObject, serializedObject.FindProperty("_aiHandles"), true, true, true, true);
    15.         _aiHandles.drawHeaderCallback = (Rect rect) =>
    16.         {
    17.             EditorGUI.LabelField(rect, "AI Handles");
    18.         };
    19.         _aiHandles.drawElementCallback = (Rect rect, int index, bool isActive, bool isFocused) =>
    20.         {
    21.             SerializedProperty element = _aiHandles.serializedProperty.GetArrayElementAtIndex(index);
    22.             rect.y += EditorGUIUtility.standardVerticalSpacing;
    23.  
    24.             SerializedProperty state = element.FindPropertyRelative("_state");
    25.             EditorGUI.PropertyField(new Rect(rect.x, rect.y, 100, EditorGUI.GetPropertyHeight(state, true)), state, GUIContent.none);
    26.  
    27.             SerializedProperty transitions = element.FindPropertyRelative("_transitions");
    28.             EditorGUI.PropertyField(new Rect(rect.x + 120, rect.y, rect.width - 120, EditorGUI.GetPropertyHeight(transitions, true)), transitions, true);
    29.         };
    30.         _aiHandles.elementHeightCallback = (int index) =>
    31.         {
    32.             SerializedProperty element = _aiHandles.serializedProperty.GetArrayElementAtIndex(index);
    33.             float height = EditorGUIUtility.standardVerticalSpacing;
    34.  
    35.             SerializedProperty transitions = element.FindPropertyRelative("_transitions");
    36.             height += EditorGUI.GetPropertyHeight(transitions, true) + EditorGUIUtility.standardVerticalSpacing;
    37.  
    38.             return height + EditorGUIUtility.standardVerticalSpacing;
    39.         };
    40.     }
    41.  
    42.     public override void OnInspectorGUI()
    43.     {
    44.         serializedObject.Update();
    45.         _aiHandles.DoLayoutList();
    46.         serializedObject.ApplyModifiedProperties();
    47.     }
    48. }
     
  3. Camronas

    Camronas

    Joined:
    Apr 20, 2012
    Posts:
    154
    Thank you so much! Works like a dream. Has made my life so much easier.

    Cheers.