< Summary

Class:ReorderableList.Editor.ReorderableList
Assembly:ReorderableEditor
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Helpers/Utils/ReorderableArray/Editor/ReorderableList.cs
Covered lines:0
Uncovered lines:970
Coverable lines:970
Total lines:2913
Line coverage:0% (0 of 970)
Covered branches:0
Total branches:0

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
ReorderableList()0%2100%
ReorderableList(...)0%30500%
ReorderableList(...)0%2100%
ReorderableList(...)0%2100%
ReorderableList(...)0%2100%
GetHeight()0%30500%
DoLayoutList()0%2100%
DoList(...)0%1101000%
AddItem[T](...)0%6200%
AddItem()0%6200%
Remove(...)0%6200%
RemoveItem(...)0%42600%
GetItem(...)0%12300%
IndexOf(...)0%20400%
GrabKeyboardFocus()0%2100%
HasKeyboardControl()0%2100%
ReleaseKeyboardFocus()0%6200%
SetPage(...)0%6200%
SetPageByIndex(...)0%6200%
GetPage(...)0%6200%
GetPageByIndex(...)0%6200%
GetElementsHeight()0%20400%
GetElementHeight(...)0%6200%
GetElementDrawRect(...)0%12300%
GetElementRenderRect(...)0%30500%
DrawHeader(...)0%2101400%
ExpandElements(...)0%12300%
SortElements(...)0%42600%
DrawEmpty(...)0%12300%
UpdateElementRects(...)0%20400%
DrawElements(...)0%2721600%
DrawElement(...)0%72800%
GetElementLabel(...)0%30500%
GetElementName(...)0%3061700%
GetLayerMaskName(...)0%72800%
DrawFooter(...)0%2101400%
DrawPaginationHeader(...)0%1101000%
OnPageDropDownSelect(...)0%2100%
DispatchChange()0%6200%
HandleSingleContextClick(...)0%6200%
HandleMultipleContextClick(...)0%6200%
HandleSharedContextClick(...)0%20400%
HandleMoveElement(...)0%42600%
HandleDelete(...)0%2100%
HandleDuplicate(...)0%2100%
HandleDragAndDrop(...)0%1101000%
ValidateObjectDragAndDrop(...)0%12300%
AppendDragAndDropValue(...)0%12300%
HandlePreSelection(...)0%42600%
HandlePostSelection(...)0%3801900%
IsSelectionButton(...)0%6200%
DoSelection(...)0%30500%
UpdateDragList(...)0%6200%
UpdateDragPosition(...)0%6200%
ReorderDraggedElements(...)0%12300%
ApplyReorder()0%6200%
GetSelectionIndex(...)0%56700%
CanSelect(...)0%6200%
CanSelect(...)0%6200%
CanSelect(...)0%6200%
IsPositionWithinElement(...)0%6200%
IsElementExpandable(...)0%42600%
IsTypeExpandable(...)0%42600%
Style()0%2100%
DragList(...)0%2100%
Resize(...)0%6200%
SortByIndex()0%6200%
RecordState()0%6200%
RestoreState(...)0%6200%
SortByPosition()0%6200%
GetIndexFromSelection(...)0%2100%
Overlaps(...)0%30500%
RecordState()0%6200%
RestoreState(...)0%6200%
Iterate(...)0%20400%
SlideGroup()0%2100%
GetRect(...)0%56700%
SetRect(...)0%6200%
GetVisibleLength(...)0%6200%
GetPageForIndex(...)0%6200%
GetPageCount(...)0%6200%
GetVisibleRange(...)0%6200%
ListSelection()0%2100%
ListSelection(...)0%2100%
Contains(...)0%2100%
Clear()0%2100%
SelectWhenNoAction(...)0%12300%
Select(...)0%2100%
Remove(...)0%6200%
AppendWithAction(...)0%56700%
Sort()0%6200%
Sort(...)0%6200%
ToArray()0%2100%
Clone()0%2100%
Trim(...)0%42600%
CanRevert(...)0%20400%
RevertValues(...)0%12300%
Duplicate(...)0%6200%
Delete(...)0%6200%
Append(...)0%12300%
AppendRange(...)0%12300%
GetEnumerator()0%2100%
GetEnumerator()0%2100%
SortOnProperty(...)0%2100%
SortOnType(...)0%2100%
BubbleSort(...)0%20400%
Compare(...)0%1321100%
CompareObjects(...)0%42600%
Surrogate(...)0%2100%
Surrogate(...)0%2100%
Invoke(...)0%12300%
InvalidListException()0%2100%
MissingListExeption()0%2100%
Internals()0%2100%
ValidateObjectDragAndDrop(...)0%12300%
AppendDragAndDropValue(...)0%2100%
GetParams(...)0%6200%

File(s)

/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Helpers/Utils/ReorderableArray/Editor/ReorderableList.cs

#LineLine coverage
 1using System.Collections;
 2using System.Collections.Generic;
 3using System.Linq;
 4using System.Reflection;
 5using UnityEditor;
 6using UnityEngine;
 7
 8namespace ReorderableList.Editor
 9{
 10
 11    public class ReorderableList
 12    {
 13
 14        private const float ELEMENT_EDGE_TOP = 1;
 15        private const float ELEMENT_EDGE_BOT = 3;
 16        private const float ELEMENT_HEIGHT_OFFSET = ELEMENT_EDGE_TOP + ELEMENT_EDGE_BOT;
 17
 018        private static int selectionHash = "ReorderableListSelection".GetHashCode();
 019        private static int dragAndDropHash = "ReorderableListDragAndDrop".GetHashCode();
 20
 21        private const string EMPTY_LABEL = "List is Empty";
 22        private const string ARRAY_ERROR = "{0} is not an Array!";
 23
 24        public enum ElementDisplayType
 25        {
 26            Auto,
 27            Expandable,
 28            SingleLine
 29        }
 30
 31        public delegate void DrawHeaderDelegate(Rect rect, GUIContent label);
 32        public delegate void DrawFooterDelegate(Rect rect);
 33        public delegate void DrawElementDelegate(Rect rect, SerializedProperty element, GUIContent label, bool selected,
 34        public delegate void ActionDelegate(ReorderableList list);
 35        public delegate bool ActionBoolDelegate(ReorderableList list);
 36        public delegate void AddDropdownDelegate(Rect buttonRect, ReorderableList list);
 37        public delegate Object DragDropReferenceDelegate(Object[] references, ReorderableList list);
 38        public delegate void DragDropAppendDelegate(Object reference, ReorderableList list);
 39        public delegate float GetElementHeightDelegate(SerializedProperty element);
 40        public delegate float GetElementsHeightDelegate(ReorderableList list);
 41        public delegate string GetElementNameDelegate(SerializedProperty element);
 42        public delegate GUIContent GetElementLabelDelegate(SerializedProperty element);
 43        public delegate void SurrogateCallback(SerializedProperty element, Object objectReference, ReorderableList list)
 44
 45        public event DrawHeaderDelegate drawHeaderCallback;
 46        public event DrawFooterDelegate drawFooterCallback;
 47        public event DrawElementDelegate drawElementCallback;
 48        public event DrawElementDelegate drawElementBackgroundCallback;
 49        public event GetElementHeightDelegate getElementHeightCallback;
 50        public event GetElementsHeightDelegate getElementsHeightCallback;
 51        public event GetElementNameDelegate getElementNameCallback;
 52        public event GetElementLabelDelegate getElementLabelCallback;
 53        public event DragDropReferenceDelegate onValidateDragAndDropCallback;
 54        public event DragDropAppendDelegate onAppendDragDropCallback;
 55        public event ActionDelegate onReorderCallback;
 56        public event ActionDelegate onSelectCallback;
 57        public event ActionDelegate onAddCallback;
 58        public event AddDropdownDelegate onAddDropdownCallback;
 59        public event ActionDelegate onRemoveCallback;
 60        public event ActionDelegate onMouseUpCallback;
 61        public event ActionBoolDelegate onCanRemoveCallback;
 62        public event ActionDelegate onChangedCallback;
 63
 64        public bool canAdd;
 65        public bool canRemove;
 66        public bool draggable;
 67        public bool sortable;
 68        public bool expandable;
 69        public bool multipleSelection;
 70        public GUIContent label;
 71        public float headerHeight;
 72        public float footerHeight;
 73        public float slideEasing;
 74        public float verticalSpacing;
 75        public bool showDefaultBackground;
 76        public ElementDisplayType elementDisplayType;
 77        public string elementNameProperty;
 78        public string elementNameOverride;
 79        public bool elementLabels;
 80        public Texture elementIcon;
 81        public Surrogate surrogate;
 82
 083        public bool paginate { get { return pagination.enabled; } set { pagination.enabled = value; } }
 84
 085        public int pageSize { get { return pagination.fixedPageSize; } set { pagination.fixedPageSize = value; } }
 86
 87        internal readonly int id;
 88
 89        private SerializedProperty list;
 090        private int controlID = -1;
 91        private Rect[] elementRects;
 92        private GUIContent elementLabel;
 93        private GUIContent pageInfoContent;
 94        private GUIContent pageSizeContent;
 95        private ListSelection selection;
 96        private SlideGroup slideGroup;
 97        private int pressIndex;
 98
 099        private bool doPagination { get { return pagination.enabled && !list.serializedObject.isEditingMultipleObjects; 
 100
 0101        private float elementSpacing { get { return Mathf.Max(0, verticalSpacing - 2); } }
 102
 103        private bool dragging;
 104        private float pressPosition;
 105        private float dragPosition;
 106        private int dragDirection;
 107        private DragList dragList;
 108        private ListSelection beforeDragSelection;
 109        private Pagination pagination;
 110
 0111        private int dragDropControlID = -1;
 112
 113        public ReorderableList(SerializedProperty list)
 0114            : this(list, true, true, true) { }
 115
 116        public ReorderableList(SerializedProperty list, bool canAdd, bool canRemove, bool draggable)
 0117            : this(list, canAdd, canRemove, draggable, ElementDisplayType.Auto, null, null, null) { }
 118
 119        public ReorderableList(SerializedProperty list, bool canAdd, bool canRemove, bool draggable, ElementDisplayType 
 0120            : this(list, canAdd, canRemove, draggable, elementDisplayType, elementNameProperty, null, elementIcon) { }
 121
 0122        public ReorderableList(SerializedProperty list, bool canAdd, bool canRemove, bool draggable, ElementDisplayType 
 123        {
 124
 0125            if (list == null)
 126            {
 127
 0128                throw new MissingListExeption();
 129            }
 0130            else if (!list.isArray)
 131            {
 132
 133                //check if user passed in a ReorderableArray, if so, that becomes the list object
 134
 0135                SerializedProperty array = list.FindPropertyRelative("array");
 136
 0137                if (array == null || !array.isArray)
 138                {
 139
 0140                    throw new InvalidListException();
 141                }
 142
 0143                this.list = array;
 0144            }
 145            else
 146            {
 147
 0148                this.list = list;
 149            }
 150
 0151            this.canAdd = canAdd;
 0152            this.canRemove = canRemove;
 0153            this.draggable = draggable;
 0154            this.elementDisplayType = elementDisplayType;
 0155            this.elementNameProperty = elementNameProperty;
 0156            this.elementNameOverride = elementNameOverride;
 0157            this.elementIcon = elementIcon;
 158
 0159            id = GetHashCode();
 0160            list.isExpanded = true;
 0161            label = new GUIContent(list.displayName);
 0162            pageInfoContent = new GUIContent();
 0163            pageSizeContent = new GUIContent();
 164
 165#if UNITY_5_6_OR_NEWER
 0166            verticalSpacing = EditorGUIUtility.standardVerticalSpacing;
 167#else
 168      verticalSpacing = 2f;
 169#endif
 0170            headerHeight = 18f;
 0171            footerHeight = 13f;
 0172            slideEasing = 0.15f;
 0173            expandable = true;
 0174            elementLabels = true;
 0175            showDefaultBackground = true;
 0176            multipleSelection = true;
 0177            pagination = new Pagination();
 0178            elementLabel = new GUIContent();
 179
 0180            dragList = new DragList(0);
 0181            selection = new ListSelection();
 0182            slideGroup = new SlideGroup();
 0183            elementRects = new Rect[0];
 0184        }
 185
 186        //
 187        // -- PROPERTIES --
 188        //
 189
 0190        public SerializedProperty List { get { return list; } internal set { list = value; } }
 191
 0192        public bool HasList { get { return list != null && list.isArray; } }
 193
 194        public int Length
 195        {
 196            get
 197            {
 198
 0199                if (!HasList)
 200                {
 201
 0202                    return 0;
 203                }
 0204                else if (!list.hasMultipleDifferentValues)
 205                {
 206
 0207                    return list.arraySize;
 208                }
 209
 210                //When multiple objects are selected, because of a Unity bug, list.arraySize is never guranteed to actua
 211                //array size. So we have to find it. Not that great since we're creating SerializedObjects here. There h
 212
 0213                int smallerArraySize = list.arraySize;
 214
 0215                foreach (Object targetObject in list.serializedObject.targetObjects)
 216                {
 217
 0218                    SerializedObject serializedObject = new SerializedObject(targetObject);
 0219                    SerializedProperty property = serializedObject.FindProperty(list.propertyPath);
 220
 0221                    smallerArraySize = Mathf.Min(property.arraySize, smallerArraySize);
 222                }
 223
 0224                return smallerArraySize;
 225            }
 226        }
 227
 0228        public int VisibleLength { get { return pagination.GetVisibleLength(Length); } }
 229
 0230        public int[] Selected { get { return selection.ToArray(); } set { selection = new ListSelection(value); } }
 231
 0232        public int Index { get { return selection.First; } set { selection.Select(value); } }
 233
 0234        public bool IsDragging { get { return dragging; } }
 235
 236        //
 237        // -- PUBLIC --
 238        //
 239
 240        public float GetHeight()
 241        {
 242
 0243            if (HasList)
 244            {
 245
 0246                float topHeight = doPagination ? headerHeight * 2 : headerHeight;
 247
 0248                return list.isExpanded ? topHeight + GetElementsHeight() + footerHeight : headerHeight;
 249            }
 250            else
 251            {
 252
 0253                return EditorGUIUtility.singleLineHeight;
 254            }
 255        }
 256
 257        public void DoLayoutList()
 258        {
 259
 0260            Rect position = EditorGUILayout.GetControlRect(false, GetHeight(), EditorStyles.largeLabel);
 261
 0262            DoList(EditorGUI.IndentedRect(position), label);
 0263        }
 264
 265        public void DoList(Rect rect, GUIContent label)
 266        {
 267
 0268            int indent = EditorGUI.indentLevel;
 0269            EditorGUI.indentLevel = 0;
 270
 0271            Rect headerRect = rect;
 0272            headerRect.height = headerHeight;
 273
 0274            if (!HasList)
 275            {
 276
 0277                DrawEmpty(headerRect, string.Format(ARRAY_ERROR, label.text), GUIStyle.none, EditorStyles.helpBox);
 0278            }
 279            else
 280            {
 281
 0282                controlID = GUIUtility.GetControlID(selectionHash, FocusType.Keyboard, rect);
 0283                dragDropControlID = GUIUtility.GetControlID(dragAndDropHash, FocusType.Passive, rect);
 284
 0285                DrawHeader(headerRect, label);
 286
 0287                if (list.isExpanded)
 288                {
 289
 0290                    if (doPagination)
 291                    {
 292
 0293                        Rect paginateHeaderRect = headerRect;
 0294                        paginateHeaderRect.y += headerRect.height;
 295
 0296                        DrawPaginationHeader(paginateHeaderRect);
 297
 0298                        headerRect.yMax = paginateHeaderRect.yMax - 1;
 299                    }
 300
 0301                    Rect elementBackgroundRect = rect;
 0302                    elementBackgroundRect.yMin = headerRect.yMax;
 0303                    elementBackgroundRect.yMax = rect.yMax - footerHeight;
 304
 0305                    Event evt = Event.current;
 306
 0307                    if (selection.Length > 1)
 308                    {
 309
 0310                        if (evt.type == EventType.ContextClick && CanSelect(evt.mousePosition))
 311                        {
 312
 0313                            HandleMultipleContextClick(evt);
 314                        }
 315                    }
 316
 0317                    if (Length > 0)
 318                    {
 319
 320                        //update element rects if not dragging. Dragging caches draw rects so no need to update
 321
 0322                        if (!dragging)
 323                        {
 324
 0325                            UpdateElementRects(elementBackgroundRect, evt);
 326                        }
 327
 0328                        if (elementRects.Length > 0)
 329                        {
 330
 331                            int start, end;
 332
 0333                            pagination.GetVisibleRange(elementRects.Length, out start, out end);
 334
 0335                            Rect selectableRect = elementBackgroundRect;
 0336                            selectableRect.yMin = elementRects[start].yMin;
 0337                            selectableRect.yMax = elementRects[end - 1].yMax;
 338
 0339                            HandlePreSelection(selectableRect, evt);
 0340                            DrawElements(elementBackgroundRect, evt);
 0341                            HandlePostSelection(selectableRect, evt);
 342                        }
 0343                    }
 344                    else
 345                    {
 346
 0347                        DrawEmpty(elementBackgroundRect, EMPTY_LABEL, Style.boxBackground, Style.verticalLabel);
 348                    }
 349
 0350                    Rect footerRect = rect;
 0351                    footerRect.yMin = elementBackgroundRect.yMax;
 0352                    footerRect.xMin = rect.xMax - 58;
 353
 0354                    DrawFooter(footerRect);
 355                }
 356            }
 357
 0358            EditorGUI.indentLevel = indent;
 0359        }
 360
 361        public SerializedProperty AddItem<T>(T item) where T : Object
 362        {
 363
 0364            SerializedProperty property = AddItem();
 365
 0366            if (property != null)
 367            {
 368
 0369                property.objectReferenceValue = item;
 370            }
 371
 0372            return property;
 373        }
 374
 375        public SerializedProperty AddItem()
 376        {
 377
 0378            if (HasList)
 379            {
 380
 381                //TODO Validate add on multiple selected objects
 382
 0383                list.arraySize++;
 0384                selection.Select(list.arraySize - 1);
 385
 0386                SetPageByIndex(list.arraySize - 1);
 0387                DispatchChange();
 388
 0389                return list.GetArrayElementAtIndex(selection.Last);
 390            }
 391            else
 392            {
 393
 0394                throw new InvalidListException();
 395            }
 396        }
 397
 398        public void Remove(int[] selection)
 399        {
 400
 0401            System.Array.Sort(selection);
 402
 0403            int i = selection.Length;
 404
 0405            while (--i > -1)
 406            {
 407
 0408                RemoveItem(selection[i]);
 409            }
 0410        }
 411
 412        public void RemoveItem(int index)
 413        {
 414
 0415            if (index >= 0 && index < Length)
 416            {
 417
 0418                SerializedProperty property = list.GetArrayElementAtIndex(index);
 419
 0420                if (property.propertyType == SerializedPropertyType.ObjectReference && property.objectReferenceValue)
 421                {
 422
 0423                    property.objectReferenceValue = null;
 424                }
 425
 0426                list.DeleteArrayElementAtIndex(index);
 0427                selection.Remove(index);
 428
 429                //TODO Validate removal on multiple selected objects
 430
 0431                if (Length > 0)
 432                {
 433
 0434                    selection.Select(Mathf.Max(0, index - 1));
 435                }
 436
 0437                DispatchChange();
 438            }
 0439        }
 440
 441        public SerializedProperty GetItem(int index)
 442        {
 443
 0444            if (index >= 0 && index < Length)
 445            {
 446
 0447                return list.GetArrayElementAtIndex(index);
 448            }
 449            else
 450            {
 451
 0452                return null;
 453            }
 454        }
 455
 456        public int IndexOf(SerializedProperty element)
 457        {
 458
 0459            if (element != null)
 460            {
 461
 0462                int i = Length;
 463
 0464                while (--i > -1)
 465                {
 466
 0467                    if (SerializedProperty.EqualContents(element, list.GetArrayElementAtIndex(i)))
 468                    {
 469
 0470                        return i;
 471                    }
 472                }
 473            }
 474
 0475            return -1;
 476        }
 477
 0478        public void GrabKeyboardFocus() { GUIUtility.keyboardControl = id; }
 479
 0480        public bool HasKeyboardControl() { return GUIUtility.keyboardControl == id; }
 481
 482        public void ReleaseKeyboardFocus()
 483        {
 484
 0485            if (GUIUtility.keyboardControl == id)
 486            {
 487
 0488                GUIUtility.keyboardControl = 0;
 489            }
 0490        }
 491
 492        public void SetPage(int page)
 493        {
 494
 0495            if (doPagination)
 496            {
 497
 0498                pagination.page = page;
 499            }
 0500        }
 501
 502        public void SetPageByIndex(int index)
 503        {
 504
 0505            if (doPagination)
 506            {
 507
 0508                pagination.page = pagination.GetPageForIndex(index);
 509            }
 0510        }
 511
 0512        public int GetPage(int index) { return doPagination ? pagination.page : 0; }
 513
 0514        public int GetPageByIndex(int index) { return doPagination ? pagination.GetPageForIndex(index) : 0; }
 515
 516        //
 517        // -- PRIVATE --
 518        //
 519
 520        private float GetElementsHeight()
 521        {
 522
 0523            if (getElementsHeightCallback != null)
 524            {
 525
 0526                return getElementsHeightCallback(this);
 527            }
 528
 0529            int i, len = Length;
 530
 0531            if (len == 0)
 532            {
 533
 0534                return 28;
 535            }
 536
 0537            float totalHeight = 0;
 0538            float spacing = elementSpacing;
 539
 540            int start, end;
 541
 0542            pagination.GetVisibleRange(len, out start, out end);
 543
 0544            for (i = start; i < end; i++)
 545            {
 546
 0547                totalHeight += GetElementHeight(list.GetArrayElementAtIndex(i)) + spacing;
 548            }
 549
 0550            return totalHeight + 7 - spacing;
 551        }
 552
 553        private float GetElementHeight(SerializedProperty element)
 554        {
 555
 0556            if (getElementHeightCallback != null)
 557            {
 558
 0559                return getElementHeightCallback(element) + ELEMENT_HEIGHT_OFFSET;
 560            }
 561            else
 562            {
 563
 0564                return EditorGUI.GetPropertyHeight(element, GetElementLabel(element, elementLabels), IsElementExpandable
 565            }
 566        }
 567
 568        private Rect GetElementDrawRect(int index, Rect desiredRect)
 569        {
 570
 0571            if (slideEasing <= 0)
 572            {
 573
 0574                return desiredRect;
 575            }
 576            else
 577            {
 578
 579                //lerp the drag easing toward slide easing, this creates a stronger easing at the start then slower at t
 580                //when dealing with large lists, we can
 581
 0582                return dragging ? slideGroup.GetRect(dragList[index].startIndex, desiredRect, slideEasing) : slideGroup.
 583            }
 584        }
 585
 586        /*
 587        private Rect GetElementHeaderRect(SerializedProperty element, Rect elementRect) {
 588
 589            Rect rect = elementRect;
 590            rect.height = EditorGUIUtility.singleLineHeight + verticalSpacing;
 591
 592            return rect;
 593        }
 594        */
 595
 596        private Rect GetElementRenderRect(SerializedProperty element, Rect elementRect)
 597        {
 598
 0599            float offset = draggable ? 20 : 5;
 600
 0601            Rect rect = elementRect;
 0602            rect.xMin += IsElementExpandable(element) ? offset + 10 : offset;
 0603            rect.xMax -= 5;
 0604            rect.yMin += ELEMENT_EDGE_TOP;
 0605            rect.yMax -= ELEMENT_EDGE_BOT;
 606
 0607            return rect;
 608        }
 609
 610        private void DrawHeader(Rect rect, GUIContent label)
 611        {
 612
 0613            if (showDefaultBackground && Event.current.type == EventType.Repaint)
 614            {
 615
 0616                Style.headerBackground.Draw(rect, false, false, false, false);
 617            }
 618
 0619            HandleDragAndDrop(rect, Event.current);
 620
 0621            bool multiline = elementDisplayType != ElementDisplayType.SingleLine;
 622
 0623            Rect titleRect = rect;
 0624            titleRect.xMin += 6f;
 0625            titleRect.xMax -= multiline ? 95f : 55f;
 0626            titleRect.height -= 2f;
 0627            titleRect.y++;
 628
 0629            label = EditorGUI.BeginProperty(titleRect, label, list);
 630
 0631            if (drawHeaderCallback != null)
 632            {
 633
 0634                drawHeaderCallback(titleRect, label);
 0635            }
 0636            else if (expandable)
 637            {
 638
 0639                titleRect.xMin += 10;
 640
 0641                EditorGUI.BeginChangeCheck();
 642
 0643                bool isExpanded = EditorGUI.Foldout(titleRect, list.isExpanded, label, true);
 644
 0645                if (EditorGUI.EndChangeCheck())
 646                {
 647
 0648                    list.isExpanded = isExpanded;
 649                }
 0650            }
 651            else
 652            {
 653
 0654                GUI.Label(titleRect, label, EditorStyles.label);
 655            }
 656
 0657            EditorGUI.EndProperty();
 658
 0659            if (multiline)
 660            {
 661
 0662                Rect bRect1 = rect;
 0663                bRect1.xMin = rect.xMax - 25;
 0664                bRect1.xMax = rect.xMax - 5;
 665
 0666                if (GUI.Button(bRect1, Style.expandButton, Style.preButton))
 667                {
 668
 0669                    ExpandElements(true);
 670                }
 671
 0672                Rect bRect2 = rect;
 0673                bRect2.xMin = bRect1.xMin - 20;
 0674                bRect2.xMax = bRect1.xMin;
 675
 0676                if (GUI.Button(bRect2, Style.collapseButton, Style.preButton))
 677                {
 678
 0679                    ExpandElements(false);
 680                }
 681
 0682                rect.xMax = bRect2.xMin + 5;
 683            }
 684
 685            //draw sorting options
 686
 0687            if (sortable)
 688            {
 689
 0690                Rect sortRect1 = rect;
 0691                sortRect1.xMin = rect.xMax - 25;
 0692                sortRect1.xMax = rect.xMax;
 693
 0694                Rect sortRect2 = rect;
 0695                sortRect2.xMin = sortRect1.xMin - 20;
 0696                sortRect2.xMax = sortRect1.xMin;
 697
 0698                if (EditorGUI.DropdownButton(sortRect1, Style.sortAscending, FocusType.Passive, Style.preButton))
 699                {
 700
 0701                    SortElements(sortRect1, false);
 702                }
 703
 0704                if (EditorGUI.DropdownButton(sortRect2, Style.sortDescending, FocusType.Passive, Style.preButton))
 705                {
 706
 0707                    SortElements(sortRect2, true);
 708                }
 709            }
 0710        }
 711
 712        private void ExpandElements(bool expand)
 713        {
 714
 0715            if (!list.isExpanded && expand)
 716            {
 717
 0718                list.isExpanded = true;
 719            }
 720
 0721            int i, len = Length;
 722
 0723            for (i = 0; i < len; i++)
 724            {
 725
 0726                list.GetArrayElementAtIndex(i).isExpanded = expand;
 727            }
 0728        }
 729
 730        private void SortElements(Rect rect, bool descending)
 731        {
 732
 0733            int total = Length;
 734
 735            //no point in sorting a list with 1 element!
 736
 0737            if (total <= 1)
 738            {
 739
 0740                return;
 741            }
 742
 743            //the first property tells us what type of items are in the list
 744            //if generic, then we give the user a list of properties to sort on
 745
 0746            SerializedProperty prop = list.GetArrayElementAtIndex(0);
 747
 0748            if (prop.propertyType == SerializedPropertyType.Generic)
 749            {
 750
 0751                GenericMenu menu = new GenericMenu();
 752
 0753                SerializedProperty property = prop.Copy();
 0754                SerializedProperty end = property.GetEndProperty();
 755
 0756                bool enterChildren = true;
 757
 0758                while (property.NextVisible(enterChildren) && !SerializedProperty.EqualContents(property, end))
 759                {
 760
 0761                    menu.AddItem(new GUIContent(property.name), false, userData =>
 762                    {
 763
 764                        //sort based on the property selected then apply the changes
 765
 0766                        ListSort.SortOnProperty(list, total, descending, (string)userData);
 767
 0768                        ApplyReorder();
 769
 0770                        HandleUtility.Repaint();
 771
 0772                    }, property.name);
 773
 0774                    enterChildren = false;
 775                }
 776
 0777                menu.DropDown(rect);
 0778            }
 779            else
 780            {
 781
 782                //list is not generic, so we just sort directly on the type then apply the changes
 783
 0784                ListSort.SortOnType(list, total, descending, prop.propertyType);
 785
 0786                ApplyReorder();
 787            }
 0788        }
 789
 790        private void DrawEmpty(Rect rect, string label, GUIStyle backgroundStyle, GUIStyle labelStyle)
 791        {
 792
 0793            if (showDefaultBackground && Event.current.type == EventType.Repaint)
 794            {
 795
 0796                backgroundStyle.Draw(rect, false, false, false, false);
 797            }
 798
 0799            EditorGUI.LabelField(rect, label, labelStyle);
 0800        }
 801
 802        private void UpdateElementRects(Rect rect, Event evt)
 803        {
 804
 805            //resize array if elements changed
 806
 0807            int i, len = Length;
 808
 0809            if (len != elementRects.Length)
 810            {
 811
 0812                System.Array.Resize(ref elementRects, len);
 813            }
 814
 0815            if (evt.type == EventType.Repaint)
 816            {
 817
 818                //start rect
 819
 0820                Rect elementRect = rect;
 0821                elementRect.yMin = elementRect.yMax = rect.yMin + 2;
 822
 0823                float spacing = elementSpacing;
 824
 825                int start, end;
 826
 0827                pagination.GetVisibleRange(len, out start, out end);
 828
 0829                for (i = start; i < end; i++)
 830                {
 831
 0832                    SerializedProperty element = list.GetArrayElementAtIndex(i);
 833
 834                    //update the elementRects value for this object. Grab the last elementRect for startPosition
 835
 0836                    elementRect.y = elementRect.yMax;
 0837                    elementRect.height = GetElementHeight(element);
 0838                    elementRects[i] = elementRect;
 839
 0840                    elementRect.yMax += spacing;
 841                }
 842            }
 0843        }
 844
 845        private void DrawElements(Rect rect, Event evt)
 846        {
 847
 848            //draw list background
 849
 0850            if (showDefaultBackground && evt.type == EventType.Repaint)
 851            {
 852
 0853                Style.boxBackground.Draw(rect, false, false, false, false);
 854            }
 855
 856            //if not dragging, draw elements as usual
 857
 0858            if (!dragging)
 859            {
 860
 861                int start, end;
 862
 0863                pagination.GetVisibleRange(Length, out start, out end);
 864
 0865                for (int i = start; i < end; i++)
 866                {
 867
 0868                    bool selected = selection.Contains(i);
 869
 0870                    DrawElement(list.GetArrayElementAtIndex(i), GetElementDrawRect(i, elementRects[i]), selected, select
 871                }
 0872            }
 0873            else if (evt.type == EventType.Repaint)
 874            {
 875
 876                //draw dragging elements only when repainting
 877
 0878                int i, s, len = dragList.Length;
 0879                int sLen = selection.Length;
 880
 881                //first, find the rects of the selected elements, we need to use them for overlap queries
 882
 0883                for (i = 0; i < sLen; i++)
 884                {
 885
 0886                    DragElement element = dragList[i];
 887
 888                    //update the element desiredRect if selected. Selected elements appear first in the dragList, so oth
 889
 0890                    element.desiredRect.y = dragPosition - element.dragOffset;
 0891                    dragList[i] = element;
 892                }
 893
 894                //draw elements, start from the bottom of the list as first elements are the ones selected, so should be
 895
 0896                i = len;
 897
 0898                while (--i > -1)
 899                {
 900
 0901                    DragElement element = dragList[i];
 902
 903                    //draw dragging elements last as the loop is backwards
 904
 0905                    if (element.selected)
 906                    {
 907
 0908                        DrawElement(element.property, element.desiredRect, true, true);
 0909                        continue;
 910                    }
 911
 912                    //loop over selection and see what overlaps
 913                    //if dragging down we start from the bottom of the selection
 914                    //otherwise we start from the top. This helps to cover multiple selected objects
 915
 0916                    Rect elementRect = element.rect;
 0917                    int elementIndex = element.startIndex;
 918
 0919                    int start = dragDirection > 0 ? sLen - 1 : 0;
 0920                    int end = dragDirection > 0 ? -1 : sLen;
 921
 0922                    for (s = start; s != end; s -= dragDirection)
 923                    {
 924
 0925                        DragElement selected = dragList[s];
 926
 0927                        if (selected.Overlaps(elementRect, elementIndex, dragDirection))
 928                        {
 929
 0930                            elementRect.y -= selected.rect.height * dragDirection;
 0931                            elementIndex += dragDirection;
 932                        }
 933                    }
 934
 935                    //draw the element with the new rect
 936
 0937                    DrawElement(element.property, GetElementDrawRect(i, elementRect), false, false);
 938
 939                    //reassign the element back into the dragList
 940
 0941                    element.desiredRect = elementRect;
 0942                    dragList[i] = element;
 943                }
 944            }
 0945        }
 946
 947        private void DrawElement(SerializedProperty element, Rect rect, bool selected, bool focused)
 948        {
 949
 0950            Event evt = Event.current;
 951
 0952            if (drawElementBackgroundCallback != null)
 953            {
 954
 0955                drawElementBackgroundCallback(rect, element, null, selected, focused);
 0956            }
 0957            else if (evt.type == EventType.Repaint)
 958            {
 959
 0960                Style.elementBackground.Draw(rect, false, selected, selected, focused);
 961            }
 962
 0963            if (evt.type == EventType.Repaint && draggable)
 964            {
 965
 0966                Style.draggingHandle.Draw(new Rect(rect.x + 5, rect.y + 6, 10, rect.height - (rect.height - 6)), false, 
 967            }
 968
 0969            GUIContent label = GetElementLabel(element, elementLabels);
 970
 0971            Rect renderRect = GetElementRenderRect(element, rect);
 972
 0973            if (drawElementCallback != null)
 974            {
 975
 0976                drawElementCallback(renderRect, element, label, selected, focused);
 0977            }
 978            else
 979            {
 980
 0981                EditorGUI.PropertyField(renderRect, element, label, true);
 982            }
 983
 984            //handle context click
 985
 0986            int controlId = GUIUtility.GetControlID(label, FocusType.Passive, rect);
 987
 0988            switch (evt.GetTypeForControl(controlId))
 989            {
 990
 991                case EventType.ContextClick:
 992
 0993                    if (rect.Contains(evt.mousePosition))
 994                    {
 995
 0996                        HandleSingleContextClick(evt, element);
 997                    }
 998
 999                    break;
 1000            }
 01001        }
 1002
 1003        private GUIContent GetElementLabel(SerializedProperty element, bool allowElementLabel)
 1004        {
 1005
 01006            if (!allowElementLabel)
 1007            {
 1008
 01009                return GUIContent.none;
 1010            }
 01011            else if (getElementLabelCallback != null)
 1012            {
 1013
 01014                return getElementLabelCallback(element);
 1015            }
 1016
 1017            string name;
 1018
 01019            if (getElementNameCallback != null)
 1020            {
 1021
 01022                name = getElementNameCallback(element);
 01023            }
 1024            else
 1025            {
 1026
 01027                name = GetElementName(element, elementNameProperty, elementNameOverride);
 1028            }
 1029
 01030            elementLabel.text = !string.IsNullOrEmpty(name) ? name : element.displayName;
 01031            elementLabel.tooltip = element.tooltip;
 01032            elementLabel.image = elementIcon;
 1033
 01034            return elementLabel;
 1035        }
 1036
 1037        private static string GetElementName(SerializedProperty element, string nameProperty, string nameOverride)
 1038        {
 1039
 01040            if (!string.IsNullOrEmpty(nameOverride))
 1041            {
 1042
 01043                string path = element.propertyPath;
 1044
 1045                const string arrayEndDelimeter = "]";
 1046                const char arrayStartDelimeter = '[';
 1047
 01048                if (path.EndsWith(arrayEndDelimeter))
 1049                {
 1050
 01051                    int startIndex = path.LastIndexOf(arrayStartDelimeter) + 1;
 1052
 01053                    return string.Format("{0} {1}", nameOverride, path.Substring(startIndex, path.Length - startIndex - 
 1054                }
 1055
 01056                return nameOverride;
 1057            }
 01058            else if (string.IsNullOrEmpty(nameProperty))
 1059            {
 1060
 01061                return null;
 1062            }
 01063            else if (element.propertyType == SerializedPropertyType.ObjectReference && nameProperty == "name")
 1064            {
 1065
 01066                return element.objectReferenceValue ? element.objectReferenceValue.name : null;
 1067            }
 1068
 01069            SerializedProperty prop = element.FindPropertyRelative(nameProperty);
 1070
 01071            if (prop != null)
 1072            {
 1073
 01074                switch (prop.propertyType)
 1075                {
 1076
 1077                    case SerializedPropertyType.ObjectReference:
 1078
 01079                        return prop.objectReferenceValue ? prop.objectReferenceValue.name : null;
 1080
 1081                    case SerializedPropertyType.Enum:
 1082
 01083                        return prop.enumDisplayNames[prop.enumValueIndex];
 1084
 1085                    case SerializedPropertyType.Integer:
 1086                    case SerializedPropertyType.Character:
 1087
 01088                        return prop.intValue.ToString();
 1089
 1090                    case SerializedPropertyType.LayerMask:
 1091
 01092                        return GetLayerMaskName(prop.intValue);
 1093
 1094                    case SerializedPropertyType.String:
 1095
 01096                        return prop.stringValue;
 1097
 1098                    case SerializedPropertyType.Float:
 1099
 01100                        return prop.floatValue.ToString();
 1101                }
 1102
 01103                return prop.displayName;
 1104            }
 1105
 01106            return null;
 1107        }
 1108
 1109        private static string GetLayerMaskName(int mask)
 1110        {
 1111
 01112            if (mask == 0)
 1113            {
 1114
 01115                return "Nothing";
 1116            }
 01117            else if (mask < 0)
 1118            {
 1119
 01120                return "Everything";
 1121            }
 1122
 01123            string name = string.Empty;
 01124            int n = 0;
 1125
 01126            for (int i = 0; i < 32; i++)
 1127            {
 1128
 01129                if (((1 << i) & mask) != 0)
 1130                {
 1131
 01132                    if (n == 4)
 1133                    {
 1134
 01135                        return "Mixed ...";
 1136                    }
 1137
 01138                    name += (n > 0 ? ", " : string.Empty) + LayerMask.LayerToName(i);
 01139                    n++;
 1140                }
 1141            }
 1142
 01143            return name;
 1144        }
 1145
 1146        private void DrawFooter(Rect rect)
 1147        {
 1148
 01149            if (drawFooterCallback != null)
 1150            {
 1151
 01152                drawFooterCallback(rect);
 01153                return;
 1154            }
 1155
 01156            if (Event.current.type == EventType.Repaint)
 1157            {
 1158
 01159                Style.footerBackground.Draw(rect, false, false, false, false);
 1160            }
 1161
 01162            Rect addRect = new Rect(rect.xMin + 4f, rect.y - 3f, 25f, 13f);
 01163            Rect subRect = new Rect(rect.xMax - 29f, rect.y - 3f, 25f, 13f);
 1164
 01165            EditorGUI.BeginDisabledGroup(!canAdd);
 1166
 01167            if (GUI.Button(addRect, onAddDropdownCallback != null ? Style.iconToolbarPlusMore : Style.iconToolbarPlus, S
 1168            {
 1169
 01170                if (onAddDropdownCallback != null)
 1171                {
 1172
 01173                    onAddDropdownCallback(addRect, this);
 01174                }
 01175                else if (onAddCallback != null)
 1176                {
 1177
 01178                    onAddCallback(this);
 01179                }
 1180                else
 1181                {
 1182
 01183                    AddItem();
 1184                }
 1185            }
 1186
 01187            EditorGUI.EndDisabledGroup();
 1188
 01189            EditorGUI.BeginDisabledGroup(!CanSelect(selection) || !canRemove || (onCanRemoveCallback != null && !onCanRe
 1190
 01191            if (GUI.Button(subRect, Style.iconToolbarMinus, Style.preButton))
 1192            {
 1193
 01194                if (onRemoveCallback != null)
 1195                {
 1196
 01197                    onRemoveCallback(this);
 01198                }
 1199                else
 1200                {
 1201
 01202                    Remove(selection.ToArray());
 1203                }
 1204            }
 1205
 01206            EditorGUI.EndDisabledGroup();
 01207        }
 1208
 1209        private void DrawPaginationHeader(Rect rect)
 1210        {
 1211
 01212            int total = Length;
 01213            int pages = pagination.GetPageCount(total);
 01214            int page = Mathf.Clamp(pagination.page, 0, pages - 1);
 1215
 1216            //some actions may have reduced the page count, so we need to check the current page against the clamped one
 1217            //if different, we need to change and repaint
 1218
 01219            if (page != pagination.page)
 1220            {
 1221
 01222                pagination.page = page;
 1223
 01224                HandleUtility.Repaint();
 1225            }
 1226
 01227            Rect prevRect = new Rect(rect.xMin + 4f, rect.y - 1f, 17f, 14f);
 01228            Rect popupRect = new Rect(prevRect.xMax, rect.y - 1f, 14f, 14f);
 01229            Rect nextRect = new Rect(popupRect.xMax, rect.y - 1f, 17f, 14f);
 1230
 01231            if (Event.current.type == EventType.Repaint)
 1232            {
 1233
 01234                Style.paginationHeader.Draw(rect, false, true, true, false);
 1235            }
 1236
 01237            pageInfoContent.text = string.Format(Style.PAGE_INFO_FORMAT, pagination.page + 1, pages);
 1238
 01239            Rect pageInfoRect = rect;
 01240            pageInfoRect.width = Style.paginationText.CalcSize(pageInfoContent).x;
 01241            pageInfoRect.x = rect.xMax - pageInfoRect.width - 7;
 01242            pageInfoRect.y += 2;
 1243
 1244            //draw page info
 1245
 01246            GUI.Label(pageInfoRect, pageInfoContent, Style.paginationText);
 1247
 1248            //draw page buttons and page popup
 1249
 01250            if (GUI.Button(prevRect, Style.iconPagePrev, Style.preButton))
 1251            {
 1252
 01253                pagination.page = Mathf.Max(0, pagination.page - 1);
 1254            }
 1255
 01256            if (EditorGUI.DropdownButton(popupRect, Style.iconPagePopup, FocusType.Passive, Style.preButton))
 1257            {
 1258
 01259                GenericMenu menu = new GenericMenu();
 1260
 01261                for (int i = 0; i < pages; i++)
 1262                {
 1263
 01264                    int pageIndex = i;
 1265
 01266                    menu.AddItem(new GUIContent(string.Format("Page {0}", i + 1)), i == pagination.page, OnPageDropDownS
 1267                }
 1268
 01269                menu.DropDown(popupRect);
 1270            }
 1271
 01272            if (GUI.Button(nextRect, Style.iconPageNext, Style.preButton))
 1273            {
 1274
 01275                pagination.page = Mathf.Min(pages - 1, pagination.page + 1);
 1276            }
 1277
 1278            //if we're allowed to control the page size manually, show an editor
 1279
 01280            bool useFixedPageSize = pagination.fixedPageSize > 0;
 1281
 01282            EditorGUI.BeginDisabledGroup(useFixedPageSize);
 1283
 01284            pageSizeContent.text = total.ToString();
 1285
 01286            GUIStyle style = Style.pageSizeTextField;
 01287            Texture icon = Style.listIcon.image;
 1288
 01289            float min = nextRect.xMax + 5;
 01290            float max = pageInfoRect.xMin - 5;
 01291            float space = max - min;
 01292            float labelWidth = icon.width + 2;
 01293            float width = style.CalcSize(pageSizeContent).x + 50 + labelWidth;
 1294
 01295            Rect pageSizeRect = rect;
 01296            pageSizeRect.y--;
 01297            pageSizeRect.x = min + (space - width) / 2;
 01298            pageSizeRect.width = width - labelWidth;
 1299
 01300            EditorGUI.BeginChangeCheck();
 1301
 01302            EditorGUIUtility.labelWidth = labelWidth;
 01303            EditorGUIUtility.SetIconSize(new Vector2(icon.width, icon.height));
 1304
 01305            int newPageSize = EditorGUI.DelayedIntField(pageSizeRect, Style.listIcon, useFixedPageSize ? pagination.fixe
 1306
 01307            EditorGUIUtility.labelWidth = 0;
 01308            EditorGUIUtility.SetIconSize(Vector2.zero);
 1309
 01310            if (EditorGUI.EndChangeCheck())
 1311            {
 1312
 01313                pagination.customPageSize = Mathf.Clamp(newPageSize, 0, total);
 01314                pagination.page = Mathf.Min(pagination.GetPageCount(total) - 1, pagination.page);
 1315            }
 1316
 01317            EditorGUI.EndDisabledGroup();
 01318        }
 1319
 01320        private void OnPageDropDownSelect(object userData) { pagination.page = (int)userData; }
 1321
 1322        private void DispatchChange()
 1323        {
 1324
 01325            if (onChangedCallback != null)
 1326            {
 1327
 01328                onChangedCallback(this);
 1329            }
 01330        }
 1331
 1332        private void HandleSingleContextClick(Event evt, SerializedProperty element)
 1333        {
 1334
 01335            selection.Select(IndexOf(element));
 1336
 01337            GenericMenu menu = new GenericMenu();
 1338
 01339            if (element.isInstantiatedPrefab)
 1340            {
 1341
 01342                menu.AddItem(new GUIContent("Revert " + GetElementLabel(element, true).text + " to Prefab"), false, sele
 01343                menu.AddSeparator(string.Empty);
 1344            }
 1345
 01346            HandleSharedContextClick(evt, menu, "Duplicate Array Element", "Delete Array Element", "Move Array Element")
 01347        }
 1348
 1349        private void HandleMultipleContextClick(Event evt)
 1350        {
 1351
 01352            GenericMenu menu = new GenericMenu();
 1353
 01354            if (selection.CanRevert(list))
 1355            {
 1356
 01357                menu.AddItem(new GUIContent("Revert Values to Prefab"), false, selection.RevertValues, list);
 01358                menu.AddSeparator(string.Empty);
 1359            }
 1360
 01361            HandleSharedContextClick(evt, menu, "Duplicate Array Elements", "Delete Array Elements", "Move Array Element
 01362        }
 1363
 1364        private void HandleSharedContextClick(Event evt, GenericMenu menu, string duplicateLabel, string deleteLabel, st
 1365        {
 1366
 01367            menu.AddItem(new GUIContent(duplicateLabel), false, HandleDuplicate, list);
 01368            menu.AddItem(new GUIContent(deleteLabel), false, HandleDelete, list);
 1369
 01370            if (doPagination)
 1371            {
 1372
 01373                int pages = pagination.GetPageCount(Length);
 1374
 01375                if (pages > 1)
 1376                {
 1377
 01378                    for (int i = 0; i < pages; i++)
 1379                    {
 1380
 01381                        string label = string.Format("{0}/Page {1}", moveLabel, i + 1);
 1382
 01383                        menu.AddItem(new GUIContent(label), i == pagination.page, HandleMoveElement, i);
 1384                    }
 1385                }
 1386            }
 1387
 01388            menu.ShowAsContext();
 1389
 01390            evt.Use();
 01391        }
 1392
 1393        private void HandleMoveElement(object userData)
 1394        {
 1395
 01396            int toPage = (int)userData;
 01397            int fromPage = pagination.page;
 01398            int size = pagination.pageSize;
 01399            int offset = (toPage * size) - (fromPage * size);
 01400            int direction = offset > 0 ? 1 : -1;
 01401            int total = Length;
 1402
 1403            //We need to find the actually positions things will move to and not clamp the index
 1404            //because sometimes something wants to move to a negative index, or beyond the length
 1405            //we need to find this overlow and adjust the move offsets based on that
 1406
 01407            int overflow = 0;
 1408
 01409            for (int i = 0; i < selection.Length; i++)
 1410            {
 1411
 01412                int desiredIndex = selection[i] + offset;
 1413
 01414                overflow = direction < 0 ? Mathf.Min(overflow, desiredIndex) : Mathf.Max(overflow, desiredIndex - total)
 1415            }
 1416
 01417            offset -= overflow;
 1418
 1419            //copy the current list to prepare for moving
 1420
 01421            UpdateDragList(0, 0, total);
 1422
 1423            //create a list that will act as our new order
 1424
 01425            List<DragElement> orderedList = new List<DragElement>(dragList.Elements.Where(t => !selection.Contains(t.sta
 1426
 1427            //go through the selection and insert them into the new order based on the page offset
 1428
 01429            selection.Sort();
 1430
 01431            for (int i = 0; i < selection.Length; i++)
 1432            {
 1433
 01434                int selIndex = selection[i];
 01435                int oldIndex = dragList.GetIndexFromSelection(selIndex);
 01436                int newIndex = Mathf.Clamp(selIndex + offset, 0, orderedList.Count);
 1437
 01438                orderedList.Insert(newIndex, dragList[oldIndex]);
 1439            }
 1440
 1441            //finally, perform the re-order
 1442
 01443            dragList.Elements = orderedList.ToArray();
 1444
 01445            ReorderDraggedElements(direction, 0, null);
 1446
 1447            //assume we still want to view these items
 1448
 01449            pagination.page = toPage;
 1450
 01451            HandleUtility.Repaint();
 01452        }
 1453
 1454        private void HandleDelete(object userData)
 1455        {
 1456
 01457            selection.Delete(userData as SerializedProperty);
 1458
 01459            DispatchChange();
 01460        }
 1461
 1462        private void HandleDuplicate(object userData)
 1463        {
 1464
 01465            selection.Duplicate(userData as SerializedProperty);
 1466
 01467            DispatchChange();
 01468        }
 1469
 1470        private void HandleDragAndDrop(Rect rect, Event evt)
 1471        {
 1472
 01473            switch (evt.GetTypeForControl(dragDropControlID))
 1474            {
 1475
 1476                case EventType.DragUpdated:
 1477                case EventType.DragPerform:
 1478
 01479                    if (GUI.enabled && rect.Contains(evt.mousePosition))
 1480                    {
 1481
 01482                        Object[] objectReferences = DragAndDrop.objectReferences;
 01483                        Object[] references = new Object[1];
 1484
 01485                        bool acceptDrag = false;
 1486
 01487                        foreach (Object object1 in objectReferences)
 1488                        {
 1489
 01490                            references[0] = object1;
 01491                            Object object2 = ValidateObjectDragAndDrop(references);
 1492
 01493                            if (object2 != null)
 1494                            {
 1495
 01496                                DragAndDrop.visualMode = DragAndDropVisualMode.Copy;
 1497
 01498                                if (evt.type == EventType.DragPerform)
 1499                                {
 1500
 01501                                    AppendDragAndDropValue(object2);
 1502
 01503                                    acceptDrag = true;
 01504                                    DragAndDrop.activeControlID = 0;
 01505                                }
 1506                                else
 1507                                {
 1508
 01509                                    DragAndDrop.activeControlID = dragDropControlID;
 1510                                }
 1511                            }
 1512                        }
 1513
 01514                        if (acceptDrag)
 1515                        {
 1516
 01517                            GUI.changed = true;
 01518                            DragAndDrop.AcceptDrag();
 1519                        }
 1520                    }
 1521
 01522                    break;
 1523
 1524                case EventType.DragExited:
 1525
 01526                    if (GUI.enabled)
 1527                    {
 1528
 01529                        HandleUtility.Repaint();
 1530                    }
 1531
 1532                    break;
 1533            }
 01534        }
 1535
 1536        private Object ValidateObjectDragAndDrop(Object[] references)
 1537        {
 1538
 01539            if (onValidateDragAndDropCallback != null)
 1540            {
 1541
 01542                return onValidateDragAndDropCallback(references, this);
 1543            }
 01544            else if (surrogate.HasType)
 1545            {
 1546
 1547                //if we have a surrogate type, then validate using the surrogate type rather than the list
 1548
 01549                return Internals.ValidateObjectDragAndDrop(references, null, surrogate.type, surrogate.exactType);
 1550            }
 1551
 01552            return Internals.ValidateObjectDragAndDrop(references, list, null, false);
 1553        }
 1554
 1555        private void AppendDragAndDropValue(Object obj)
 1556        {
 1557
 01558            if (onAppendDragDropCallback != null)
 1559            {
 1560
 01561                onAppendDragDropCallback(obj, this);
 01562            }
 1563            else
 1564            {
 1565
 1566                //check if we have a surrogate type. If so use that for appending
 1567
 01568                if (surrogate.HasType)
 1569                {
 1570
 01571                    surrogate.Invoke(AddItem(), obj, this);
 01572                }
 1573                else
 1574                {
 1575
 01576                    Internals.AppendDragAndDropValue(obj, list);
 1577                }
 1578            }
 1579
 01580            DispatchChange();
 01581        }
 1582
 1583        private void HandlePreSelection(Rect rect, Event evt)
 1584        {
 1585
 01586            if (evt.type == EventType.MouseDrag && draggable && GUIUtility.hotControl == controlID)
 1587            {
 1588
 01589                if (selection.Length > 0 && UpdateDragPosition(evt.mousePosition, rect, dragList))
 1590                {
 1591
 01592                    GUIUtility.keyboardControl = controlID;
 01593                    dragging = true;
 1594                }
 1595
 01596                evt.Use();
 1597            }
 1598
 1599            /* TODO This is buggy. The reason for this is to allow selection and dragging of an element using the header
 1600             * The main issue here is determining whether the element has an "expandable" drop down arrow, which if it d
 1601             * Because of property drawers and certain property types, it's impossible to know this automatically (witho
 1602             * So if the below code is active and we determine that the property is expandable but isn't actually. Then 
 1603             * So for now, in order to drag or select a row, the user must select empty space on the row. Not a huge dea
 1604             * What needs to happen is the drag event needs to occur independent of the event type. But that's messy too
 1605            if (evt.type == EventType.MouseDown) {
 1606
 1607                //check if we contain the mouse press
 1608                //we also need to check what has current focus. If nothing we can assume control
 1609                //if there's something, check if the header has been pressed if the element is expandable
 1610                //if we did press the header, then override the control
 1611
 1612                if (rect.Contains(evt.mousePosition) && IsSelectionButton(evt)) {
 1613
 1614                    int index = GetSelectionIndex(evt.mousePosition);
 1615
 1616                    if (CanSelect(index)) {
 1617
 1618                        SerializedProperty element = list.GetArrayElementAtIndex(index);
 1619
 1620                        if (IsElementExpandable(element)) {
 1621
 1622                            Rect elementHeaderRect = GetElementHeaderRect(element, elementRects[index]);
 1623                            Rect elementRenderRect = GetElementRenderRect(element, elementRects[index]);
 1624
 1625                            Rect elementExpandRect = elementHeaderRect;
 1626                            elementExpandRect.xMin = elementRenderRect.xMin - 10;
 1627                            elementExpandRect.xMax = elementRenderRect.xMin;
 1628
 1629                            if (elementHeaderRect.Contains(evt.mousePosition) && !elementExpandRect.Contains(evt.mousePo
 1630
 1631                                DoSelection(index, true, evt);
 1632                                HandleUtility.Repaint();
 1633                            }
 1634                        }
 1635                    }
 1636                }
 1637            }
 1638            */
 01639        }
 1640
 1641        private void HandlePostSelection(Rect rect, Event evt)
 1642        {
 1643
 01644            switch (evt.GetTypeForControl(controlID))
 1645            {
 1646
 1647                case EventType.MouseDown:
 1648
 01649                    if (rect.Contains(evt.mousePosition) && IsSelectionButton(evt))
 1650                    {
 1651
 01652                        int index = GetSelectionIndex(evt.mousePosition);
 1653
 01654                        if (CanSelect(index))
 1655                        {
 1656
 01657                            DoSelection(index, GUIUtility.keyboardControl == 0 || GUIUtility.keyboardControl == controlI
 01658                        }
 1659                        else
 1660                        {
 1661
 01662                            selection.Clear();
 1663                        }
 1664
 01665                        HandleUtility.Repaint();
 1666                    }
 1667
 01668                    break;
 1669
 1670                case EventType.MouseUp:
 1671
 01672                    if (!draggable)
 1673                    {
 1674
 1675                        //select the single object if no selection modifier is being performed
 1676
 01677                        selection.SelectWhenNoAction(pressIndex, evt);
 1678
 01679                        if (onMouseUpCallback != null && IsPositionWithinElement(evt.mousePosition, selection.Last))
 1680                        {
 1681
 01682                            onMouseUpCallback(this);
 1683                        }
 01684                    }
 01685                    else if (GUIUtility.hotControl == controlID)
 1686                    {
 1687
 01688                        evt.Use();
 1689
 01690                        if (dragging)
 1691                        {
 1692
 01693                            dragging = false;
 1694
 1695                            //move elements in list
 1696
 01697                            ReorderDraggedElements(dragDirection, dragList.StartIndex, () => dragList.SortByPosition());
 01698                        }
 1699                        else
 1700                        {
 1701
 1702                            //if we didn't drag, then select the original pressed object
 1703
 01704                            selection.SelectWhenNoAction(pressIndex, evt);
 1705
 01706                            if (onMouseUpCallback != null)
 1707                            {
 1708
 01709                                onMouseUpCallback(this);
 1710                            }
 1711                        }
 1712
 01713                        GUIUtility.hotControl = 0;
 1714                    }
 1715
 01716                    HandleUtility.Repaint();
 1717
 01718                    break;
 1719
 1720                case EventType.KeyDown:
 1721
 01722                    if (GUIUtility.keyboardControl == controlID)
 1723                    {
 1724
 01725                        if (evt.keyCode == KeyCode.DownArrow && !dragging)
 1726                        {
 1727
 01728                            selection.Select(Mathf.Min(selection.Last + 1, Length - 1));
 01729                            evt.Use();
 01730                        }
 01731                        else if (evt.keyCode == KeyCode.UpArrow && !dragging)
 1732                        {
 1733
 01734                            selection.Select(Mathf.Max(selection.Last - 1, 0));
 01735                            evt.Use();
 01736                        }
 01737                        else if (evt.keyCode == KeyCode.Escape && GUIUtility.hotControl == controlID)
 1738                        {
 1739
 01740                            GUIUtility.hotControl = 0;
 1741
 01742                            if (dragging)
 1743                            {
 1744
 01745                                dragging = false;
 01746                                selection = beforeDragSelection;
 1747                            }
 1748
 01749                            evt.Use();
 1750                        }
 1751                    }
 1752
 1753                    break;
 1754            }
 01755        }
 1756
 01757        private bool IsSelectionButton(Event evt) { return evt.button == 0 || evt.button == 2; }
 1758
 1759        private void DoSelection(int index, bool setKeyboardControl, Event evt)
 1760        {
 1761
 1762            //append selections based on action, this may be a additive (ctrl) or range (shift) selection
 1763
 01764            if (multipleSelection)
 1765            {
 1766
 01767                selection.AppendWithAction(pressIndex = index, evt);
 01768            }
 1769            else
 1770            {
 1771
 01772                selection.Select(pressIndex = index);
 1773            }
 1774
 01775            if (onSelectCallback != null)
 1776            {
 1777
 01778                onSelectCallback(this);
 1779            }
 1780
 01781            if (draggable)
 1782            {
 1783
 01784                dragging = false;
 01785                dragPosition = pressPosition = evt.mousePosition.y;
 1786
 1787                int start, end;
 1788
 01789                pagination.GetVisibleRange(Length, out start, out end);
 1790
 01791                UpdateDragList(dragPosition, start, end);
 1792
 01793                selection.Trim(start, end);
 1794
 01795                beforeDragSelection = selection.Clone();
 1796
 01797                GUIUtility.hotControl = controlID;
 1798            }
 1799
 01800            if (setKeyboardControl)
 1801            {
 1802
 01803                GUIUtility.keyboardControl = controlID;
 1804            }
 1805
 01806            evt.Use();
 01807        }
 1808
 1809        private void UpdateDragList(float dragPosition, int start, int end)
 1810        {
 1811
 01812            dragList.Resize(start, end - start);
 1813
 01814            for (int i = start; i < end; i++)
 1815            {
 1816
 01817                SerializedProperty property = list.GetArrayElementAtIndex(i);
 01818                Rect elementRect = elementRects[i];
 1819
 01820                DragElement dragElement = new DragElement()
 1821                {
 1822                    property = property,
 1823                    dragOffset = dragPosition - elementRect.y,
 1824                    rect = elementRect,
 1825                    desiredRect = elementRect,
 1826                    selected = selection.Contains(i),
 1827                    startIndex = i
 1828                };
 1829
 01830                dragList[i - start] = dragElement;
 1831            }
 1832
 1833            //finally, sort the dragList by selection, selected objects appear first in the list
 1834            //selection order is preserved as well
 1835
 01836            dragList.SortByIndex();
 01837        }
 1838
 1839        private bool UpdateDragPosition(Vector2 position, Rect bounds, DragList dragList)
 1840        {
 1841
 1842            //find new drag position
 1843
 01844            int startIndex = 0;
 01845            int endIndex = selection.Length - 1;
 1846
 01847            float minOffset = dragList[startIndex].dragOffset;
 01848            float maxOffset = dragList[endIndex].rect.height - dragList[endIndex].dragOffset;
 1849
 01850            dragPosition = Mathf.Clamp(position.y, bounds.yMin + minOffset, bounds.yMax - maxOffset);
 1851
 01852            if (Mathf.Abs(dragPosition - pressPosition) > 1)
 1853            {
 1854
 01855                dragDirection = (int)Mathf.Sign(dragPosition - pressPosition);
 01856                return true;
 1857            }
 1858
 01859            return false;
 1860        }
 1861
 1862        private void ReorderDraggedElements(int direction, int offset, System.Action sortList)
 1863        {
 1864
 1865            //save the current expanded states on all elements. I don't see any other way to do this
 1866            //MoveArrayElement does not move the foldout states, so... fun.
 1867
 01868            dragList.RecordState();
 1869
 01870            if (sortList != null)
 1871            {
 1872
 01873                sortList();
 1874            }
 1875
 01876            selection.Sort((a, b) =>
 1877            {
 1878
 01879                int d1 = dragList.GetIndexFromSelection(a);
 01880                int d2 = dragList.GetIndexFromSelection(b);
 1881
 01882                return direction > 0 ? d1.CompareTo(d2) : d2.CompareTo(d1);
 1883            });
 1884
 1885            //swap the selected elements in the List
 1886
 01887            int s = selection.Length;
 1888
 01889            while (--s > -1)
 1890            {
 1891
 01892                int newIndex = dragList.GetIndexFromSelection(selection[s]);
 01893                int listIndex = newIndex + offset;
 1894
 01895                selection[s] = listIndex;
 1896
 01897                list.MoveArrayElement(dragList[newIndex].startIndex, listIndex);
 1898            }
 1899
 1900            //restore expanded states on items
 1901
 01902            dragList.RestoreState(list);
 1903
 1904            //apply and update
 1905
 01906            ApplyReorder();
 01907        }
 1908
 1909        private void ApplyReorder()
 1910        {
 1911
 01912            list.serializedObject.ApplyModifiedProperties();
 01913            list.serializedObject.Update();
 1914
 01915            if (onReorderCallback != null)
 1916            {
 1917
 01918                onReorderCallback(this);
 1919            }
 1920
 01921            DispatchChange();
 01922        }
 1923
 1924        private int GetSelectionIndex(Vector2 position)
 1925        {
 1926
 1927            int start, end;
 1928
 01929            pagination.GetVisibleRange(elementRects.Length, out start, out end);
 1930
 01931            for (int i = start; i < end; i++)
 1932            {
 1933
 01934                Rect rect = elementRects[i];
 1935
 01936                if (rect.Contains(position) || (i == 0 && position.y <= rect.yMin) || (i == end - 1 && position.y >= rec
 1937                {
 1938
 01939                    return i;
 1940                }
 1941            }
 1942
 01943            return -1;
 1944        }
 1945
 01946        private bool CanSelect(ListSelection selection) { return selection.Length > 0 ? selection.All(s => CanSelect(s))
 1947
 01948        private bool CanSelect(int index) { return index >= 0 && index < Length; }
 1949
 01950        private bool CanSelect(Vector2 position) { return selection.Length > 0 ? selection.Any(s => IsPositionWithinElem
 1951
 01952        private bool IsPositionWithinElement(Vector2 position, int index) { return CanSelect(index) ? elementRects[index
 1953
 1954        private bool IsElementExpandable(SerializedProperty element)
 1955        {
 1956
 01957            switch (elementDisplayType)
 1958            {
 1959
 1960                case ElementDisplayType.Auto:
 1961
 01962                    return element.hasVisibleChildren && IsTypeExpandable(element.propertyType);
 1963
 1964                case ElementDisplayType.Expandable:
 01965                    return true;
 1966                case ElementDisplayType.SingleLine:
 01967                    return false;
 1968            }
 1969
 01970            return false;
 1971        }
 1972
 1973        private bool IsTypeExpandable(SerializedPropertyType type)
 1974        {
 1975
 1976            switch (type)
 1977            {
 1978
 1979                case SerializedPropertyType.Generic:
 1980                case SerializedPropertyType.Vector4:
 1981                case SerializedPropertyType.Quaternion:
 1982                case SerializedPropertyType.ArraySize:
 1983
 01984                    return true;
 1985
 1986                default:
 1987
 01988                    return false;
 1989            }
 1990        }
 1991
 1992        //
 1993        // -- LIST STYLE --
 1994        //
 1995
 1996        static class Style
 1997        {
 1998
 1999            internal const string PAGE_INFO_FORMAT = "{0} / {1}";
 2000
 2001            internal static GUIContent iconToolbarPlus;
 2002            internal static GUIContent iconToolbarPlusMore;
 2003            internal static GUIContent iconToolbarMinus;
 2004            internal static GUIContent iconPagePrev;
 2005            internal static GUIContent iconPageNext;
 2006            internal static GUIContent iconPagePopup;
 2007
 2008            internal static GUIStyle paginationText;
 2009            internal static GUIStyle pageSizeTextField;
 2010            internal static GUIStyle draggingHandle;
 2011            internal static GUIStyle headerBackground;
 2012            internal static GUIStyle footerBackground;
 2013            internal static GUIStyle paginationHeader;
 2014            internal static GUIStyle boxBackground;
 2015            internal static GUIStyle preButton;
 2016            internal static GUIStyle elementBackground;
 2017            internal static GUIStyle verticalLabel;
 2018            internal static GUIContent expandButton;
 2019            internal static GUIContent collapseButton;
 2020            internal static GUIContent sortAscending;
 2021            internal static GUIContent sortDescending;
 2022
 2023            internal static GUIContent listIcon;
 2024
 2025            static Style()
 2026            {
 2027
 02028                iconToolbarPlus = EditorGUIUtility.IconContent("Toolbar Plus", "Add to list");
 02029                iconToolbarPlusMore = EditorGUIUtility.IconContent("Toolbar Plus More", "Choose to add to list");
 02030                iconToolbarMinus = EditorGUIUtility.IconContent("Toolbar Minus", "Remove selection from list");
 02031                iconPagePrev = EditorGUIUtility.IconContent("Animation.PrevKey", "Previous page");
 02032                iconPageNext = EditorGUIUtility.IconContent("Animation.NextKey", "Next page");
 2033
 2034#if UNITY_2018_3_OR_NEWER
 02035                iconPagePopup = EditorGUIUtility.IconContent("ShurikenPopup", "Select page");
 2036#else
 2037        iconPagePopup = EditorGUIUtility.IconContent("MiniPopupNoBg", "Select page");
 2038#endif
 02039                paginationText = new GUIStyle();
 02040                paginationText.margin = new RectOffset(2, 2, 0, 0);
 02041                paginationText.fontSize = EditorStyles.miniTextField.fontSize;
 02042                paginationText.font = EditorStyles.miniFont;
 02043                paginationText.normal.textColor = EditorStyles.miniTextField.normal.textColor;
 02044                paginationText.alignment = TextAnchor.UpperLeft;
 02045                paginationText.clipping = TextClipping.Clip;
 2046
 02047                pageSizeTextField = new GUIStyle("RL Footer");
 02048                pageSizeTextField.alignment = TextAnchor.MiddleLeft;
 02049                pageSizeTextField.clipping = TextClipping.Clip;
 02050                pageSizeTextField.fixedHeight = 0;
 02051                pageSizeTextField.padding = new RectOffset(3, 0, 0, 0);
 02052                pageSizeTextField.overflow = new RectOffset(0, 0, -2, -3);
 02053                pageSizeTextField.contentOffset = new Vector2(0, -1);
 02054                pageSizeTextField.font = EditorStyles.miniFont;
 02055                pageSizeTextField.fontSize = EditorStyles.miniTextField.fontSize;
 02056                pageSizeTextField.fontStyle = FontStyle.Normal;
 02057                pageSizeTextField.wordWrap = false;
 2058
 02059                draggingHandle = new GUIStyle("RL DragHandle");
 02060                headerBackground = new GUIStyle("RL Header");
 02061                footerBackground = new GUIStyle("RL Footer");
 2062                //paginationHeader = new GUIStyle("RectangleToolHBar");
 02063                paginationHeader = new GUIStyle("RL Element");
 02064                paginationHeader.border = new RectOffset(2, 3, 2, 3);
 02065                elementBackground = new GUIStyle("RL Element");
 02066                elementBackground.border = new RectOffset(2, 3, 2, 3);
 02067                verticalLabel = new GUIStyle(EditorStyles.label);
 02068                verticalLabel.alignment = TextAnchor.UpperLeft;
 02069                verticalLabel.contentOffset = new Vector2(10, 3);
 02070                boxBackground = new GUIStyle("RL Background");
 02071                boxBackground.border = new RectOffset(6, 3, 3, 6);
 02072                preButton = new GUIStyle("RL FooterButton");
 2073
 02074                expandButton = EditorGUIUtility.IconContent("winbtn_win_max");
 02075                expandButton.tooltip = "Expand All Elements";
 2076
 02077                collapseButton = EditorGUIUtility.IconContent("winbtn_win_min");
 02078                collapseButton.tooltip = "Collapse All Elements";
 2079
 02080                sortAscending = EditorGUIUtility.IconContent("align_vertically_bottom");
 02081                sortAscending.tooltip = "Sort Ascending";
 2082
 02083                sortDescending = EditorGUIUtility.IconContent("align_vertically_top");
 02084                sortDescending.tooltip = "Sort Descending";
 2085
 02086                listIcon = EditorGUIUtility.IconContent("align_horizontally_right");
 02087            }
 2088        }
 2089
 2090        //
 2091        // -- DRAG LIST --
 2092        //
 2093
 2094        struct DragList
 2095        {
 2096
 2097            private int startIndex;
 2098            private DragElement[] elements;
 2099            private int length;
 2100
 2101            internal DragList(int length)
 2102            {
 2103
 02104                this.length = length;
 2105
 02106                startIndex = 0;
 02107                elements = new DragElement[length];
 02108            }
 2109
 02110            internal int StartIndex { get { return startIndex; } }
 2111
 02112            internal int Length { get { return length; } }
 2113
 02114            internal DragElement[] Elements { get { return elements; } set { elements = value; } }
 2115
 02116            internal DragElement this[int index] { get { return elements[index]; } set { elements[index] = value; } }
 2117
 2118            internal void Resize(int start, int length)
 2119            {
 2120
 02121                startIndex = start;
 2122
 02123                this.length = length;
 2124
 02125                if (elements.Length != length)
 2126                {
 2127
 02128                    System.Array.Resize(ref elements, length);
 2129                }
 02130            }
 2131
 2132            internal void SortByIndex()
 2133            {
 02134                System.Array.Sort(elements, (a, b) =>
 2135                {
 2136
 02137                    if (b.selected)
 2138                    {
 2139
 02140                        return a.selected ? a.startIndex.CompareTo(b.startIndex) : 1;
 2141                    }
 02142                    else if (a.selected)
 2143                    {
 2144
 02145                        return b.selected ? b.startIndex.CompareTo(a.startIndex) : -1;
 2146                    }
 2147
 02148                    return a.startIndex.CompareTo(b.startIndex);
 2149                });
 02150            }
 2151
 2152            internal void RecordState()
 2153            {
 2154
 02155                for (int i = 0; i < length; i++)
 2156                {
 2157
 02158                    elements[i].RecordState();
 2159                }
 02160            }
 2161
 2162            internal void RestoreState(SerializedProperty list)
 2163            {
 2164
 02165                for (int i = 0; i < length; i++)
 2166                {
 2167
 02168                    elements[i].RestoreState(list.GetArrayElementAtIndex(i + startIndex));
 2169                }
 02170            }
 2171
 02172            internal void SortByPosition() { System.Array.Sort(elements, (a, b) => a.desiredRect.center.y.CompareTo(b.de
 2173
 02174            internal int GetIndexFromSelection(int index) { return System.Array.FindIndex(elements, t => t.startIndex ==
 2175        }
 2176
 2177        //
 2178        // -- DRAG ELEMENT --
 2179        //
 2180
 2181        struct DragElement
 2182        {
 2183
 2184            internal SerializedProperty property;
 2185            internal int startIndex;
 2186            internal float dragOffset;
 2187            internal bool selected;
 2188            internal Rect rect;
 2189            internal Rect desiredRect;
 2190
 2191            private bool isExpanded;
 2192            private Dictionary<int, bool> states;
 2193
 2194            internal bool Overlaps(Rect value, int index, int direction)
 2195            {
 2196
 02197                if (direction < 0 && index < startIndex)
 2198                {
 2199
 02200                    return desiredRect.yMin < value.center.y;
 2201                }
 02202                else if (direction > 0 && index > startIndex)
 2203                {
 2204
 02205                    return desiredRect.yMax > value.center.y;
 2206                }
 2207
 02208                return false;
 2209            }
 2210
 2211            internal void RecordState()
 2212            {
 2213
 02214                states = new Dictionary<int, bool>();
 02215                isExpanded = property.isExpanded;
 2216
 02217                Iterate(this, property, (DragElement e, SerializedProperty p, int index) =>
 2218                {
 2219
 02220                    e.states[index] = p.isExpanded;
 02221                });
 02222            }
 2223
 2224            internal void RestoreState(SerializedProperty property)
 2225            {
 2226
 02227                property.isExpanded = isExpanded;
 2228
 02229                Iterate(this, property, (DragElement e, SerializedProperty p, int index) =>
 2230                {
 2231
 02232                    p.isExpanded = e.states[index];
 02233                });
 02234            }
 2235
 2236            private static void Iterate(DragElement element, SerializedProperty property, System.Action<DragElement, Ser
 2237            {
 2238
 02239                SerializedProperty copy = property.Copy();
 02240                SerializedProperty end = copy.GetEndProperty();
 2241
 02242                int index = 0;
 2243
 02244                while (copy.NextVisible(true) && !SerializedProperty.EqualContents(copy, end))
 2245                {
 2246
 02247                    if (copy.hasVisibleChildren)
 2248                    {
 2249
 02250                        action(element, copy, index);
 02251                        index++;
 2252                    }
 2253                }
 02254            }
 2255        }
 2256
 2257        //
 2258        // -- SLIDE GROUP --
 2259        //
 2260
 2261        class SlideGroup
 2262        {
 2263
 2264            private Dictionary<int, Rect> animIDs;
 2265
 02266            public SlideGroup() { animIDs = new Dictionary<int, Rect>(); }
 2267
 2268            public Rect GetRect(int id, Rect r, float easing)
 2269            {
 2270
 02271                if (Event.current.type != EventType.Repaint)
 2272                {
 2273
 02274                    return r;
 2275                }
 2276
 02277                if (!animIDs.ContainsKey(id))
 2278                {
 2279
 02280                    animIDs.Add(id, r);
 02281                    return r;
 2282                }
 2283                else
 2284                {
 2285
 02286                    Rect rect = animIDs[id];
 2287
 02288                    if (rect.y != r.y)
 2289                    {
 2290
 02291                        float delta = r.y - rect.y;
 02292                        float absDelta = Mathf.Abs(delta);
 2293
 2294                        //if the distance between current rect and target is too large, then move the element towards th
 2295
 02296                        if (absDelta > (rect.height * 2))
 2297                        {
 2298
 02299                            r.y = delta > 0 ? r.y - rect.height : r.y + rect.height;
 02300                        }
 02301                        else if (absDelta > 0.5)
 2302                        {
 2303
 02304                            r.y = Mathf.Lerp(rect.y, r.y, easing);
 2305                        }
 2306
 02307                        animIDs[id] = r;
 02308                        HandleUtility.Repaint();
 2309                    }
 2310
 02311                    return r;
 2312                }
 2313            }
 2314
 2315            public Rect SetRect(int id, Rect rect)
 2316            {
 2317
 02318                if (animIDs.ContainsKey(id))
 2319                {
 2320
 02321                    animIDs[id] = rect;
 02322                }
 2323                else
 2324                {
 2325
 02326                    animIDs.Add(id, rect);
 2327                }
 2328
 02329                return rect;
 2330            }
 2331        }
 2332
 2333        //
 2334        // -- PAGINATION --
 2335        //
 2336
 2337        struct Pagination
 2338        {
 2339
 2340            internal bool enabled;
 2341            internal int fixedPageSize;
 2342            internal int customPageSize;
 2343            internal int page;
 2344
 02345            internal bool usePagination { get { return enabled && pageSize > 0; } }
 2346
 02347            internal int pageSize { get { return fixedPageSize > 0 ? fixedPageSize : customPageSize; } }
 2348
 2349            internal int GetVisibleLength(int total)
 2350            {
 2351
 2352                int start, end;
 2353
 02354                if (GetVisibleRange(total, out start, out end))
 2355                {
 2356
 02357                    return end - start;
 2358                }
 2359
 02360                return total;
 2361            }
 2362
 02363            internal int GetPageForIndex(int index) { return usePagination ? Mathf.FloorToInt(index / (float)pageSize) :
 2364
 02365            internal int GetPageCount(int total) { return usePagination ? Mathf.CeilToInt(total / (float)pageSize) : 1; 
 2366
 2367            internal bool GetVisibleRange(int total, out int start, out int end)
 2368            {
 2369
 02370                if (usePagination)
 2371                {
 2372
 02373                    int size = pageSize;
 2374
 02375                    start = Mathf.Clamp(page * size, 0, total - 1);
 02376                    end = Mathf.Min(start + size, total);
 02377                    return true;
 2378                }
 2379
 02380                start = 0;
 02381                end = total;
 02382                return false;
 2383            }
 2384        }
 2385
 2386        //
 2387        // -- SELECTION --
 2388        //
 2389
 2390        class ListSelection : IEnumerable<int>
 2391        {
 2392
 2393            private List<int> indexes;
 2394
 2395            internal int? firstSelected;
 2396
 02397            public ListSelection() { indexes = new List<int>(); }
 2398
 02399            public ListSelection(int[] indexes) { this.indexes = new List<int>(indexes); }
 2400
 02401            public int First { get { return indexes.Count > 0 ? indexes[0] : -1; } }
 2402
 02403            public int Last { get { return indexes.Count > 0 ? indexes[indexes.Count - 1] : -1; } }
 2404
 02405            public int Length { get { return indexes.Count; } }
 2406
 2407            public int this[int index]
 2408            {
 02409                get { return indexes[index]; }
 2410                set
 2411                {
 2412
 02413                    int oldIndex = indexes[index];
 2414
 02415                    indexes[index] = value;
 2416
 02417                    if (oldIndex == firstSelected)
 2418                    {
 2419
 02420                        firstSelected = value;
 2421                    }
 02422                }
 2423            }
 2424
 02425            public bool Contains(int index) { return indexes.Contains(index); }
 2426
 2427            public void Clear()
 2428            {
 2429
 02430                indexes.Clear();
 02431                firstSelected = null;
 02432            }
 2433
 2434            public void SelectWhenNoAction(int index, Event evt)
 2435            {
 2436
 02437                if (!EditorGUI.actionKey && !evt.shift)
 2438                {
 2439
 02440                    Select(index);
 2441                }
 02442            }
 2443
 2444            public void Select(int index)
 2445            {
 2446
 02447                indexes.Clear();
 02448                indexes.Add(index);
 2449
 02450                firstSelected = index;
 02451            }
 2452
 2453            public void Remove(int index)
 2454            {
 2455
 02456                if (indexes.Contains(index))
 2457                {
 2458
 02459                    indexes.Remove(index);
 2460                }
 02461            }
 2462
 2463            public void AppendWithAction(int index, Event evt)
 2464            {
 2465
 02466                if (EditorGUI.actionKey)
 2467                {
 2468
 02469                    if (Contains(index))
 2470                    {
 2471
 02472                        Remove(index);
 02473                    }
 2474                    else
 2475                    {
 2476
 02477                        Append(index);
 02478                        firstSelected = index;
 2479                    }
 02480                }
 02481                else if (evt.shift && indexes.Count > 0 && firstSelected.HasValue)
 2482                {
 2483
 02484                    indexes.Clear();
 2485
 02486                    AppendRange(firstSelected.Value, index);
 02487                }
 02488                else if (!Contains(index))
 2489                {
 2490
 02491                    Select(index);
 2492                }
 02493            }
 2494
 2495            public void Sort()
 2496            {
 2497
 02498                if (indexes.Count > 0)
 2499                {
 2500
 02501                    indexes.Sort();
 2502                }
 02503            }
 2504
 2505            public void Sort(System.Comparison<int> comparison)
 2506            {
 2507
 02508                if (indexes.Count > 0)
 2509                {
 2510
 02511                    indexes.Sort(comparison);
 2512                }
 02513            }
 2514
 02515            public int[] ToArray() { return indexes.ToArray(); }
 2516
 2517            public ListSelection Clone()
 2518            {
 2519
 02520                ListSelection clone = new ListSelection(ToArray());
 02521                clone.firstSelected = firstSelected;
 2522
 02523                return clone;
 2524            }
 2525
 2526            internal void Trim(int min, int max)
 2527            {
 2528
 02529                int i = indexes.Count;
 2530
 02531                while (--i > -1)
 2532                {
 2533
 02534                    int index = indexes[i];
 2535
 02536                    if (index < min || index >= max)
 2537                    {
 2538
 02539                        if (index == firstSelected && i > 0)
 2540                        {
 2541
 02542                            firstSelected = indexes[i - 1];
 2543                        }
 2544
 02545                        indexes.RemoveAt(i);
 2546                    }
 2547                }
 02548            }
 2549
 2550            internal bool CanRevert(SerializedProperty list)
 2551            {
 2552
 02553                if (list.serializedObject.targetObjects.Length == 1)
 2554                {
 2555
 02556                    for (int i = 0; i < Length; i++)
 2557                    {
 2558
 02559                        if (list.GetArrayElementAtIndex(this[i]).isInstantiatedPrefab)
 2560                        {
 2561
 02562                            return true;
 2563                        }
 2564                    }
 2565                }
 2566
 02567                return false;
 2568            }
 2569
 2570            internal void RevertValues(object userData)
 2571            {
 2572
 02573                SerializedProperty list = userData as SerializedProperty;
 2574
 02575                for (int i = 0; i < Length; i++)
 2576                {
 2577
 02578                    SerializedProperty property = list.GetArrayElementAtIndex(this[i]);
 2579
 02580                    if (property.isInstantiatedPrefab)
 2581                    {
 2582
 02583                        property.prefabOverride = false;
 2584                    }
 2585                }
 2586
 02587                list.serializedObject.ApplyModifiedProperties();
 02588                list.serializedObject.Update();
 2589
 02590                HandleUtility.Repaint();
 02591            }
 2592
 2593            internal void Duplicate(SerializedProperty list)
 2594            {
 2595
 02596                int offset = 0;
 2597
 02598                for (int i = 0; i < Length; i++)
 2599                {
 2600
 02601                    this[i] += offset;
 2602
 02603                    list.GetArrayElementAtIndex(this[i]).DuplicateCommand();
 02604                    list.serializedObject.ApplyModifiedProperties();
 02605                    list.serializedObject.Update();
 2606
 02607                    offset++;
 2608                }
 2609
 02610                HandleUtility.Repaint();
 02611            }
 2612
 2613            internal void Delete(SerializedProperty list)
 2614            {
 2615
 02616                Sort();
 2617
 02618                int i = Length;
 2619
 02620                while (--i > -1)
 2621                {
 2622
 02623                    list.GetArrayElementAtIndex(this[i]).DeleteCommand();
 2624                }
 2625
 02626                Clear();
 2627
 02628                list.serializedObject.ApplyModifiedProperties();
 02629                list.serializedObject.Update();
 2630
 02631                HandleUtility.Repaint();
 02632            }
 2633
 2634            private void Append(int index)
 2635            {
 2636
 02637                if (index >= 0 && !indexes.Contains(index))
 2638                {
 2639
 02640                    indexes.Add(index);
 2641                }
 02642            }
 2643
 2644            private void AppendRange(int from, int to)
 2645            {
 2646
 02647                int dir = (int)Mathf.Sign(to - from);
 2648
 02649                if (dir != 0)
 2650                {
 2651
 02652                    for (int i = from; i != to; i += dir)
 2653                    {
 2654
 02655                        Append(i);
 2656                    }
 2657                }
 2658
 02659                Append(to);
 02660            }
 2661
 02662            public IEnumerator<int> GetEnumerator() { return ((IEnumerable<int>)indexes).GetEnumerator(); }
 2663
 02664            IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable<int>)indexes).GetEnumerator(); }
 2665        }
 2666
 2667        //
 2668        // -- SORTING --
 2669        //
 2670
 2671        static class ListSort
 2672        {
 2673
 2674            private delegate int SortComparision(SerializedProperty p1, SerializedProperty p2);
 2675
 2676            internal static void SortOnProperty(SerializedProperty list, int length, bool descending, string propertyNam
 2677            {
 02678                BubbleSort(list, length, (p1, p2) =>
 2679                {
 2680
 02681                    SerializedProperty a = p1.FindPropertyRelative(propertyName);
 02682                    SerializedProperty b = p2.FindPropertyRelative(propertyName);
 2683
 02684                    if (a != null && b != null && a.propertyType == b.propertyType)
 2685                    {
 2686
 02687                        int comparison = Compare(a, b, descending, a.propertyType);
 2688
 02689                        return descending ? -comparison : comparison;
 2690                    }
 2691
 02692                    return 0;
 2693                });
 02694            }
 2695
 2696            internal static void SortOnType(SerializedProperty list, int length, bool descending, SerializedPropertyType
 2697            {
 02698                BubbleSort(list, length, (p1, p2) =>
 2699                {
 2700
 02701                    int comparision = Compare(p1, p2, descending, type);
 2702
 02703                    return descending ? -comparision : comparision;
 2704                });
 02705            }
 2706
 2707            //
 2708            // -- PRIVATE --
 2709            //
 2710
 2711            private static void BubbleSort(SerializedProperty list, int length, SortComparision comparision)
 2712            {
 2713
 02714                for (int i = 0; i < length; i++)
 2715                {
 2716
 02717                    SerializedProperty p1 = list.GetArrayElementAtIndex(i);
 2718
 02719                    for (int j = i + 1; j < length; j++)
 2720                    {
 2721
 02722                        SerializedProperty p2 = list.GetArrayElementAtIndex(j);
 2723
 02724                        if (comparision(p1, p2) > 0)
 2725                        {
 2726
 02727                            list.MoveArrayElement(j, i);
 2728                        }
 2729                    }
 2730                }
 02731            }
 2732
 2733            private static int Compare(SerializedProperty p1, SerializedProperty p2, bool descending, SerializedProperty
 2734            {
 2735
 02736                if (p1 == null || p2 == null)
 2737                {
 2738
 02739                    return 0;
 2740                }
 2741
 2742                switch (type)
 2743                {
 2744
 2745                    case SerializedPropertyType.Boolean:
 2746
 02747                        return p1.boolValue.CompareTo(p2.boolValue);
 2748
 2749                    case SerializedPropertyType.Character:
 2750                    case SerializedPropertyType.Enum:
 2751                    case SerializedPropertyType.Integer:
 2752                    case SerializedPropertyType.LayerMask:
 2753
 02754                        return p1.longValue.CompareTo(p2.longValue);
 2755
 2756                    case SerializedPropertyType.Color:
 2757
 02758                        return p1.colorValue.grayscale.CompareTo(p2.colorValue.grayscale);
 2759
 2760                    case SerializedPropertyType.ExposedReference:
 2761
 02762                        return CompareObjects(p1.exposedReferenceValue, p2.exposedReferenceValue, descending);
 2763
 2764                    case SerializedPropertyType.Float:
 2765
 02766                        return p1.doubleValue.CompareTo(p2.doubleValue);
 2767
 2768                    case SerializedPropertyType.ObjectReference:
 2769
 02770                        return CompareObjects(p1.objectReferenceValue, p2.objectReferenceValue, descending);
 2771
 2772                    case SerializedPropertyType.String:
 2773
 02774                        return p1.stringValue.CompareTo(p2.stringValue);
 2775
 2776                    default:
 2777
 02778                        return 0;
 2779                }
 2780            }
 2781
 2782            private static int CompareObjects(Object obj1, Object obj2, bool descending)
 2783            {
 2784
 02785                if (obj1 && obj2)
 2786                {
 2787
 02788                    return obj1.name.CompareTo(obj2.name);
 2789                }
 02790                else if (obj1)
 2791                {
 2792
 02793                    return descending ? 1 : -1;
 2794                }
 2795
 02796                return descending ? -1 : 1;
 2797            }
 2798        }
 2799
 2800        //
 2801        // -- SURROGATE --
 2802        //
 2803
 2804        public struct Surrogate
 2805        {
 2806
 2807            public System.Type type;
 2808            public bool exactType;
 2809            public SurrogateCallback callback;
 2810
 2811            internal bool enabled;
 2812
 02813            public bool HasType { get { return enabled && type != null; } }
 2814
 2815            public Surrogate(System.Type type)
 02816                : this(type, null) { }
 2817
 2818            public Surrogate(System.Type type, SurrogateCallback callback)
 2819            {
 2820
 02821                this.type = type;
 02822                this.callback = callback;
 2823
 02824                enabled = true;
 02825                exactType = false;
 02826            }
 2827
 2828            public void Invoke(SerializedProperty element, Object objectReference, ReorderableList list)
 2829            {
 2830
 02831                if (element != null && callback != null)
 2832                {
 2833
 02834                    callback.Invoke(element, objectReference, list);
 2835                }
 02836            }
 2837        }
 2838
 2839        //
 2840        // -- EXCEPTIONS --
 2841        //
 2842
 2843        class InvalidListException : System.InvalidOperationException
 2844        {
 2845
 02846            public InvalidListException() : base("ReorderableList serializedProperty must be an array") { }
 2847        }
 2848
 2849        class MissingListExeption : System.ArgumentNullException
 2850        {
 2851
 02852            public MissingListExeption() : base("ReorderableList serializedProperty is null") { }
 2853        }
 2854
 2855        //
 2856        // -- INTERNAL --
 2857        //
 2858
 2859        static class Internals
 2860        {
 2861
 2862            private static MethodInfo dragDropValidation;
 2863            private static object[] dragDropValidationParams;
 2864            private static MethodInfo appendDragDrop;
 2865            private static object[] appendDragDropParams;
 2866
 2867            static Internals()
 2868            {
 2869
 02870                dragDropValidation = System.Type.GetType("UnityEditor.EditorGUI, UnityEditor").GetMethod("ValidateObject
 02871                appendDragDrop = typeof(SerializedProperty).GetMethod("AppendFoldoutPPtrValue", BindingFlags.NonPublic |
 02872            }
 2873
 2874            internal static Object ValidateObjectDragAndDrop(Object[] references, SerializedProperty property, System.Ty
 2875            {
 2876
 2877#if UNITY_2017_1_OR_NEWER
 02878                dragDropValidationParams = GetParams(ref dragDropValidationParams, 4);
 02879                dragDropValidationParams[0] = references;
 02880                dragDropValidationParams[1] = type;
 02881                dragDropValidationParams[2] = property;
 02882                dragDropValidationParams[3] = exactType ? 1 : 0;
 2883#else
 2884        dragDropValidationParams = GetParams(ref dragDropValidationParams, 3);
 2885        dragDropValidationParams[0] = references;
 2886        dragDropValidationParams[1] = type;
 2887        dragDropValidationParams[2] = property;
 2888#endif
 02889                return dragDropValidation.Invoke(null, dragDropValidationParams) as Object;
 2890            }
 2891
 2892            internal static void AppendDragAndDropValue(Object obj, SerializedProperty list)
 2893            {
 2894
 02895                appendDragDropParams = GetParams(ref appendDragDropParams, 1);
 02896                appendDragDropParams[0] = obj;
 02897                appendDragDrop.Invoke(list, appendDragDropParams);
 02898            }
 2899
 2900            private static object[] GetParams(ref object[] parameters, int count)
 2901            {
 2902
 02903                if (parameters == null)
 2904                {
 2905
 02906                    parameters = new object[count];
 2907                }
 2908
 02909                return parameters;
 2910            }
 2911        }
 2912    }
 2913}

Methods/Properties

ReorderableList()
paginate()
paginate(System.Boolean)
pageSize()
pageSize(System.Int32)
ReorderableList(UnityEditor.SerializedProperty, System.Boolean, System.Boolean, System.Boolean, ReorderableList.Editor.ReorderableList/ElementDisplayType, System.String, System.String, UnityEngine.Texture)
doPagination()
elementSpacing()
ReorderableList(UnityEditor.SerializedProperty)
ReorderableList(UnityEditor.SerializedProperty, System.Boolean, System.Boolean, System.Boolean)
ReorderableList(UnityEditor.SerializedProperty, System.Boolean, System.Boolean, System.Boolean, ReorderableList.Editor.ReorderableList/ElementDisplayType, System.String, UnityEngine.Texture)
List()
List(UnityEditor.SerializedProperty)
HasList()
Length()
VisibleLength()
Selected()
Selected(System.Int32[])
Index()
Index(System.Int32)
IsDragging()
GetHeight()
DoLayoutList()
DoList(UnityEngine.Rect, UnityEngine.GUIContent)
AddItem[T](T)
AddItem()
Remove(System.Int32[])
RemoveItem(System.Int32)
GetItem(System.Int32)
IndexOf(UnityEditor.SerializedProperty)
GrabKeyboardFocus()
HasKeyboardControl()
ReleaseKeyboardFocus()
SetPage(System.Int32)
SetPageByIndex(System.Int32)
GetPage(System.Int32)
GetPageByIndex(System.Int32)
GetElementsHeight()
GetElementHeight(UnityEditor.SerializedProperty)
GetElementDrawRect(System.Int32, UnityEngine.Rect)
GetElementRenderRect(UnityEditor.SerializedProperty, UnityEngine.Rect)
DrawHeader(UnityEngine.Rect, UnityEngine.GUIContent)
ExpandElements(System.Boolean)
SortElements(UnityEngine.Rect, System.Boolean)
DrawEmpty(UnityEngine.Rect, System.String, UnityEngine.GUIStyle, UnityEngine.GUIStyle)
UpdateElementRects(UnityEngine.Rect, UnityEngine.Event)
DrawElements(UnityEngine.Rect, UnityEngine.Event)
DrawElement(UnityEditor.SerializedProperty, UnityEngine.Rect, System.Boolean, System.Boolean)
GetElementLabel(UnityEditor.SerializedProperty, System.Boolean)
GetElementName(UnityEditor.SerializedProperty, System.String, System.String)
GetLayerMaskName(System.Int32)
DrawFooter(UnityEngine.Rect)
DrawPaginationHeader(UnityEngine.Rect)
OnPageDropDownSelect(System.Object)
DispatchChange()
HandleSingleContextClick(UnityEngine.Event, UnityEditor.SerializedProperty)
HandleMultipleContextClick(UnityEngine.Event)
HandleSharedContextClick(UnityEngine.Event, UnityEditor.GenericMenu, System.String, System.String, System.String)
HandleMoveElement(System.Object)
HandleDelete(System.Object)
HandleDuplicate(System.Object)
HandleDragAndDrop(UnityEngine.Rect, UnityEngine.Event)
ValidateObjectDragAndDrop(UnityEngine.Object[])
AppendDragAndDropValue(UnityEngine.Object)
HandlePreSelection(UnityEngine.Rect, UnityEngine.Event)
HandlePostSelection(UnityEngine.Rect, UnityEngine.Event)
IsSelectionButton(UnityEngine.Event)
DoSelection(System.Int32, System.Boolean, UnityEngine.Event)
UpdateDragList(System.Single, System.Int32, System.Int32)
UpdateDragPosition(UnityEngine.Vector2, UnityEngine.Rect, ReorderableList.Editor.ReorderableList/DragList)
ReorderDraggedElements(System.Int32, System.Int32, System.Action)
ApplyReorder()
GetSelectionIndex(UnityEngine.Vector2)
CanSelect(ReorderableList.Editor.ReorderableList/ListSelection)
CanSelect(System.Int32)
CanSelect(UnityEngine.Vector2)
IsPositionWithinElement(UnityEngine.Vector2, System.Int32)
IsElementExpandable(UnityEditor.SerializedProperty)
IsTypeExpandable(UnityEditor.SerializedPropertyType)
Style()
DragList(System.Int32)
StartIndex()
Length()
Elements()
Elements(ReorderableList.Editor.ReorderableList/DragElement[])
Item(System.Int32)
Item(System.Int32, ReorderableList.Editor.ReorderableList/DragElement)
Resize(System.Int32, System.Int32)
SortByIndex()
RecordState()
RestoreState(UnityEditor.SerializedProperty)
SortByPosition()
GetIndexFromSelection(System.Int32)
Overlaps(UnityEngine.Rect, System.Int32, System.Int32)
RecordState()
RestoreState(UnityEditor.SerializedProperty)
Iterate(ReorderableList.Editor.ReorderableList/DragElement, UnityEditor.SerializedProperty, System.Action[DragElement,SerializedProperty,Int32])
SlideGroup()
GetRect(System.Int32, UnityEngine.Rect, System.Single)
SetRect(System.Int32, UnityEngine.Rect)
usePagination()
pageSize()
GetVisibleLength(System.Int32)
GetPageForIndex(System.Int32)
GetPageCount(System.Int32)
GetVisibleRange(System.Int32, System.Int32&, System.Int32&)
ListSelection()
ListSelection(System.Int32[])
First()
Last()
Length()
Item(System.Int32)
Item(System.Int32, System.Int32)
Contains(System.Int32)
Clear()
SelectWhenNoAction(System.Int32, UnityEngine.Event)
Select(System.Int32)
Remove(System.Int32)
AppendWithAction(System.Int32, UnityEngine.Event)
Sort()
Sort(System.Comparison[Int32])
ToArray()
Clone()
Trim(System.Int32, System.Int32)
CanRevert(UnityEditor.SerializedProperty)
RevertValues(System.Object)
Duplicate(UnityEditor.SerializedProperty)
Delete(UnityEditor.SerializedProperty)
Append(System.Int32)
AppendRange(System.Int32, System.Int32)
GetEnumerator()
GetEnumerator()
SortOnProperty(UnityEditor.SerializedProperty, System.Int32, System.Boolean, System.String)
SortOnType(UnityEditor.SerializedProperty, System.Int32, System.Boolean, UnityEditor.SerializedPropertyType)
BubbleSort(UnityEditor.SerializedProperty, System.Int32, ReorderableList.Editor.ReorderableList/ListSort/SortComparision)
Compare(UnityEditor.SerializedProperty, UnityEditor.SerializedProperty, System.Boolean, UnityEditor.SerializedPropertyType)
CompareObjects(UnityEngine.Object, UnityEngine.Object, System.Boolean)
HasType()
Surrogate(System.Type)
Surrogate(System.Type, ReorderableList.Editor.ReorderableList/SurrogateCallback)
Invoke(UnityEditor.SerializedProperty, UnityEngine.Object, ReorderableList.Editor.ReorderableList)
InvalidListException()
MissingListExeption()
Internals()
ValidateObjectDragAndDrop(UnityEngine.Object[], UnityEditor.SerializedProperty, System.Type, System.Boolean)
AppendDragAndDropValue(UnityEngine.Object, UnityEditor.SerializedProperty)
GetParams(System.Object[]&, System.Int32)