@@ -64,7 +64,7 @@ public class ReorderableList
6464
6565 private SerializedObject m_SerializedObject ;
6666 private SerializedProperty m_Elements ;
67- private string m_PropertyPath ;
67+ private string m_PropertyPath = string . Empty ;
6868 private IList m_ElementList ;
6969 private bool m_Draggable ;
7070 private float m_DraggedY ;
@@ -75,6 +75,8 @@ public class ReorderableList
7575 public bool displayAdd ;
7676 public bool displayRemove ;
7777
78+ bool scheduleRemove ;
79+
7880 internal bool m_IsEditable ;
7981 internal bool m_HasPropertyDrawer ;
8082
@@ -202,7 +204,7 @@ public void DrawFooter(Rect rect, ReorderableList list)
202204 || ( list . onCanRemoveCallback != null && ! list . onCanRemoveCallback ( list ) )
203205 || list . isOverMaxMultiEditLimit ) )
204206 {
205- if ( GUI . Button ( removeRect , iconToolbarMinus , preButton ) )
207+ if ( GUI . Button ( removeRect , iconToolbarMinus , preButton ) || GUI . enabled && list . scheduleRemove )
206208 {
207209 if ( list . onRemoveCallback == null )
208210 {
@@ -213,9 +215,12 @@ public void DrawFooter(Rect rect, ReorderableList list)
213215
214216 list . onChangedCallback ? . Invoke ( list ) ;
215217 list . ClearCacheRecursive ( ) ;
218+ GUI . changed = true ;
216219 }
217220 }
218221 }
222+
223+ list . scheduleRemove = false ;
219224 }
220225
221226 // default add button behavior
@@ -460,7 +465,7 @@ public IList list
460465 public int index
461466 {
462467 get { return m_Selection . Count > 0 ? m_Selection [ 0 ] : count - 1 ; }
463- set { Select ( value < 0 ? count - 1 : value ) ; }
468+ set { Select ( value > count - 1 ? 0 : value < 0 ? count - 1 : value ) ; }
464469 }
465470
466471 public ReadOnlyCollection < int > selectedIndices => new ReadOnlyCollection < int > ( m_Selection ) ;
@@ -973,6 +978,7 @@ private void DoListElements(Rect listRect, Rect visibleRect)
973978 index = i ;
974979 handlingInput = false ;
975980 }
981+
976982 // Element drawing could be changed from distant properties or controls
977983 // so if we detect any change in the way the property is drawn, clear cache
978984 int currentControlCount = EditorGUI . s_PropertyCount - initialProperties ;
@@ -982,6 +988,11 @@ private void DoListElements(Rect listRect, Rect visibleRect)
982988 GUI . changed = true ;
983989 }
984990 m_PropertyCache [ i ] . lastControlCount = currentControlCount ;
991+
992+ // If an event was consumed in the course of running this for loop, then there is
993+ // a good chance the array data has changed and it is dangerous for us to continue
994+ // rendering it in this frame.
995+ if ( Event . current . type == EventType . Used ) break ;
985996 }
986997 }
987998
@@ -1035,6 +1046,12 @@ private void DoListElements(Rect listRect, Rect visibleRect)
10351046
10361047 private void DoListHeader ( Rect headerRect )
10371048 {
1049+ // Ensure there's proper Prefab and context menu handling for the list as a whole.
1050+ // This ensures a deleted element in the list is displayed as an override and can
1051+ // be handled by the user via the context menu. Case 1292522
1052+ if ( m_Elements != null )
1053+ EditorGUI . BeginProperty ( headerRect , GUIContent . none , m_Elements ) ;
1054+
10381055 recursionCounter = 0 ;
10391056 // draw the background on repaint
10401057 if ( showDefaultBackground && Event . current . type == EventType . Repaint )
@@ -1051,6 +1068,9 @@ private void DoListHeader(Rect headerRect)
10511068 drawHeaderCallback ( headerRect ) ;
10521069 else if ( m_DisplayHeader )
10531070 defaultBehaviours . DrawHeader ( headerRect , m_SerializedObject , m_Elements , m_ElementList ) ;
1071+
1072+ if ( m_Elements != null )
1073+ EditorGUI . EndProperty ( ) ;
10541074 }
10551075
10561076 private void DoListFooter ( Rect footerRect )
@@ -1070,7 +1090,7 @@ private void DoDraggingAndSelection(Rect listRect)
10701090 switch ( evt . GetTypeForControl ( id ) )
10711091 {
10721092 case EventType . KeyDown :
1073- if ( GUIUtility . keyboardControl != id )
1093+ if ( GUIUtility . keyboardControl != id || m_Dragging || clicked )
10741094 return ;
10751095 // if we have keyboard focus, arrow through the list
10761096 if ( evt . keyCode == KeyCode . DownArrow )
@@ -1083,6 +1103,42 @@ private void DoDraggingAndSelection(Rect listRect)
10831103 index -= 1 ;
10841104 evt . Use ( ) ;
10851105 }
1106+ if ( evt . keyCode == KeyCode . LeftArrow )
1107+ {
1108+ if ( m_Elements != null )
1109+ {
1110+ foreach ( var index in m_Selection )
1111+ {
1112+ if ( index < 0 ) continue ;
1113+
1114+ m_Elements . GetArrayElementAtIndex ( index ) . isExpanded = false ;
1115+ }
1116+ }
1117+ InvalidateParentCaches ( m_PropertyPath ) ;
1118+ GUI . changed = true ;
1119+ evt . Use ( ) ;
1120+ }
1121+ if ( evt . keyCode == KeyCode . RightArrow )
1122+ {
1123+ if ( m_Elements != null )
1124+ {
1125+ foreach ( var index in selectedIndices )
1126+ {
1127+ if ( index < 0 ) continue ;
1128+
1129+ m_Elements . GetArrayElementAtIndex ( index ) . isExpanded = true ;
1130+ }
1131+ }
1132+ InvalidateParentCaches ( m_PropertyPath ) ;
1133+ GUI . changed = true ;
1134+ evt . Use ( ) ;
1135+ }
1136+ if ( evt . keyCode == KeyCode . Delete )
1137+ {
1138+ scheduleRemove = true ;
1139+ InvalidateParentCaches ( m_PropertyPath ) ;
1140+ evt . Use ( ) ;
1141+ }
10861142 if ( evt . keyCode == KeyCode . Escape && GUIUtility . hotControl == id )
10871143 {
10881144 GUIUtility . hotControl = 0 ;
@@ -1092,7 +1148,7 @@ private void DoDraggingAndSelection(Rect listRect)
10921148 if ( evt . type == EventType . Used )
10931149 {
10941150 // don't allow arrowing through the ends of the list
1095- index = Mathf . Clamp ( index , 0 , ( m_Elements != null ) ? m_Elements . arraySize - 1 : m_ElementList . Count - 1 ) ;
1151+ m_Selection = m_Selection . Where ( i => i >= 0 && i < ( m_Elements != null ? m_Elements . arraySize : m_ElementList . Count ) ) . ToList ( ) ;
10961152 }
10971153 break ;
10981154
@@ -1172,6 +1228,7 @@ private void DoDraggingAndSelection(Rect listRect)
11721228 break ;
11731229
11741230 case EventType . MouseUp :
1231+ clicked = false ;
11751232 if ( ! m_Draggable )
11761233 {
11771234 // if mouse up was on the same index as mouse down we fire a mouse up callback (useful if for beginning renaming on mouseup)
0 commit comments