From 4fd2de7114ddf8579ee39c967ba5cc3e786709df Mon Sep 17 00:00:00 2001 From: foulston Date: Fri, 14 Apr 2017 09:52:53 -0700 Subject: [PATCH] working on dragging --- Assets/ReorderableList/Example/Example.prefab | Bin 6148 -> 6148 bytes .../List/Editor/ReorderableList.cs | 203 +++++++++++------- 2 files changed, 122 insertions(+), 81 deletions(-) diff --git a/Assets/ReorderableList/Example/Example.prefab b/Assets/ReorderableList/Example/Example.prefab index 5827bdd066f3b6c3d8708da96926b7b975d263c6..eb803fb9fd97dbd89c375887aa0420e346efb26c 100644 GIT binary patch delta 28 kcmZoMXffC@L3Hu~Q41EX>&km4&k dragList; + private DragElement[] dragList; private ListSelection beforeDragSelection; private int dragDropControlID = -1; @@ -134,7 +134,7 @@ public ReorderableList(SerializedProperty list, bool canAdd, bool canRemove, boo slideEasing = 0.15f; expandable = true; showDefaultBackground = true; - captureFocus = false; + captureFocus = true; multipleSelection = true; elementLabel = new GUIContent(); @@ -235,7 +235,12 @@ public void DoList(Rect rect, GUIContent label) { if (list.arraySize > 0) { - UpdateElementRects(elementBackgroundRect, evt); + //update element rects if not dragging. Dragging caches draw rects so no need to update + + if (!dragging) { + + UpdateElementRects(elementBackgroundRect, evt); + } if (elementRects.Length > 0) { @@ -542,7 +547,7 @@ private void UpdateElementRects(Rect rect, Event evt) { //resize array if elements changed - int i, len = dragging ? dragList.Count : list.arraySize; + int i, len = list.arraySize; if (len != elementRects.Length) { @@ -558,9 +563,7 @@ private void UpdateElementRects(Rect rect, Event evt) { for (i = 0; i < len; i++) { - //if dragging, use the element in the temporary drag list as this list will re-order as the user drags an item - - SerializedProperty element = dragging ? dragList[i].element : list.GetArrayElementAtIndex(i); + SerializedProperty element = list.GetArrayElementAtIndex(i); //update the elementRects value for this object. Grab the last elementRect for startPosition @@ -571,7 +574,7 @@ private void UpdateElementRects(Rect rect, Event evt) { } } - private void DrawElements(Rect rect, Event evt) { + private void DrawElements(Rect rect, Event evt) { //draw list background @@ -580,53 +583,68 @@ private void DrawElements(Rect rect, Event evt) { Style.boxBackground.Draw(rect, false, false, false, false); } - //only draw dragging elements when repainting + //if not dragging, draw elements as usual - if (dragging && evt.type != EventType.Repaint) { + if (!dragging) { - return; + int i, len = list.arraySize; + + for (i = 0; i < len; i++) { + + bool selected = selection.Contains(i); + + DrawElement(list.GetArrayElementAtIndex(i), GetElementDrawRect(i, elementRects[i]), selected, selected && GUIUtility.keyboardControl == controlID); + } } + else if (evt.type == EventType.Repaint) { - //draw elements + //draw dragging elements only when repainting - int i = dragging ? dragList.Count : list.arraySize; + int i, s, len = dragList.Length; + int sLen = selection.Length; - while (--i > -1) { - - //if dragging, use the element in the temporary drag list as this list will re-order as the user drags an item + for (i = 0; i < len; i++) { - SerializedProperty element = dragging ? dragList[i].element : list.GetArrayElementAtIndex(i); + DragElement element = dragList[i]; + + //draw the element if its not in the selection - //don't draw the any dragging elements here + if (!element.selected) { - bool isSelected = selection.Contains(i); + float middle = element.rect.y + element.rect.height / 2; + float top = element.rect.yMin; - if (dragging && isSelected) { + for (s = 0; s < sLen; s++) { - continue; - } - - bool selected = !dragging ? isSelected : false; + DragElement selected = dragList[s]; - DrawElement(element, GetElementDrawRect(i, elementRects[i]), selected, selected && GUIUtility.keyboardControl == controlID); - } + if (selected.rect.Overlaps(element.rect)) { + + GUI.Box(element.rect, GUIContent.none); + } + } - //draw dragging element last, above other items + DrawElement(element.property, GetElementDrawRect(i, element.rect), false, false && GUIUtility.keyboardControl == controlID); + } + else { - if (dragging) { + //update the element rect if selected. Selected elements appear first in the dragList, so other elements later in iteration will have rects to compare - //because elementRects are static rects representing indexed positions, make a copy here and move it based on the drag position + element.rect.x = 30; + element.rect.y = dragPosition - element.dragOffset; + dragList[i] = element; + } + } - int n = selection.Length; + //draw the selected elements last - while (--n > -1) { + len = sLen; - int index = selection[n]; + for (i = 0; i < len; i++) { - Rect dragRect = elementRects[index]; - dragRect.y = dragPosition - dragList[index].dragOffset; + DragElement element = dragList[i]; - DrawElement(dragList[index].element, dragRect, true, true); + DrawElement(element.property, element.rect, true, true); } } } @@ -1085,15 +1103,6 @@ private void HandlePostSelection(Rect rect, Event evt) { list.MoveArrayElement(dragList[selectionIndex].startIndex, selectionIndex); } - //restore state - - for (int i = 0; i < dragList.Count; i++) { - - dragList[i].RestoreState(list.GetArrayElementAtIndex(i)); - } - - dragList.Clear(); - //apply changes list.serializedObject.ApplyModifiedProperties(); @@ -1108,8 +1117,6 @@ private void HandlePostSelection(Rect rect, Event evt) { } else { - dragList.Clear(); - //if we didn't drag, then select the original pressed object selection.SelectWhenNoAction(pressIndex, evt); @@ -1131,12 +1138,12 @@ private void HandlePostSelection(Rect rect, Event evt) { if (GUIUtility.keyboardControl == controlID) { - if (evt.keyCode == KeyCode.DownArrow) { + if (evt.keyCode == KeyCode.DownArrow && !dragging) { selection.Select(Mathf.Min(selection.Last + 1, list.arraySize - 1)); evt.Use(); } - else if (evt.keyCode == KeyCode.UpArrow) { + else if (evt.keyCode == KeyCode.UpArrow && !dragging) { selection.Select(Mathf.Max(selection.Last - 1, 0)); evt.Use(); @@ -1144,8 +1151,13 @@ private void HandlePostSelection(Rect rect, Event evt) { else if (evt.keyCode == KeyCode.Escape && GUIUtility.hotControl == controlID) { GUIUtility.hotControl = 0; - dragging = false; - selection = beforeDragSelection; + + if (dragging) { + + dragging = false; + selection = beforeDragSelection; + } + evt.Use(); } } @@ -1192,50 +1204,77 @@ private void DoSelection(int index, Event evt) { evt.Use(); } - private List GetDragList(float dragPosition) { + private DragElement[] GetDragList(float dragPosition) { + + int i, len = list.arraySize; - dragList = dragList ?? new List(); - dragList.Clear(); + if (dragList == null) { - for (int i = 0; i < list.arraySize; i++) { + dragList = new DragElement[len]; + } + else if (dragList.Length != len) { + + System.Array.Resize(ref dragList, len); + } + + for (i = 0; i < len; i++) { - SerializedProperty element = list.GetArrayElementAtIndex(i); + SerializedProperty property = list.GetArrayElementAtIndex(i); Rect elementRect = elementRects[i]; DragElement dragElement = new DragElement() { - element = element, + property = property, dragOffset = dragPosition - elementRect.y, - height = elementRect.height, + rect = elementRect, + selected = selection.Contains(i), startIndex = i }; - dragElement.RecordState(); - - dragList.Add(dragElement); + dragList[i] = dragElement; } + //finally, sort the dragList by selection, selected objects appear first in the list + //selection order is preserved as well + + System.Array.Sort(dragList, (a, b) => { + + if (b.selected) { + + return a.selected ? a.startIndex.CompareTo(b.startIndex) : 1; + } + else if (a.selected) { + + return b.selected ? b.startIndex.CompareTo(a.startIndex) : -1; + } + else { + + return a.startIndex.CompareTo(b.startIndex); + } + }); + return dragList; } - private void UpdateDragPosition(Vector2 position, Rect bounds, List dragList) { - - //TODO When dragging at very high speeds this breaks down. Need to fix + private void UpdateDragPosition(Vector2 position, Rect bounds, DragElement[] dragList) { //find new drag position - float oldPosition = dragPosition; - float minOffset = dragList[selection.Min].dragOffset; - float maxOffset = dragList[selection.Max].height - dragList[selection.Max].dragOffset; + int startIndex = 0; + int endIndex = selection.Length - 1; + + float minOffset = dragList[startIndex].dragOffset; + float maxOffset = dragList[endIndex].rect.height - dragList[endIndex].dragOffset; dragPosition = Mathf.Clamp(position.y, bounds.yMin + minOffset, bounds.yMax - maxOffset); + /* //check if changed if (dragList != null && dragPosition != oldPosition) { //get the interation direction with start and end points - int i, len = dragList.Count; + int i, len = dragList.Length; int dir = (int)Mathf.Sign(dragPosition - oldPosition); int start = dir == 1 ? 0 : len - 1; @@ -1252,10 +1291,14 @@ private void UpdateDragPosition(Vector2 position, Rect bounds, List selection.Sort(); + Debug.Log("UPDATE"); + for (s = selectionStart; s != selectionEnd; s -= dir) { int selectionIndex = selection[s]; + Debug.Log(selectionIndex); + //find the min and max positions of this selected item, we need to know where this item moved from and move to //to compare with dragList elements @@ -1271,16 +1314,20 @@ private void UpdateDragPosition(Vector2 position, Rect bounds, List //don't consider already selected items - if (!selection.Contains(i)) { + if (!selection.Contains(i)) { //swap the selected item if it's within the dragList item Rect elementRect = elementRects[i]; + //Debug.Log("Checking element " + i + " " + elementRect); + float middle = elementRect.y + elementRect.height / 2; if (minPos < middle && maxPos > middle) { + Debug.Log(i + " is inside"); + //move items in dragList DragElement element = dragList[i]; @@ -1303,6 +1350,7 @@ private void UpdateDragPosition(Vector2 position, Rect bounds, List selection.Sort(); } + */ } private int GetSelectionIndex(Vector2 position) { @@ -1445,13 +1493,15 @@ static Style() { // -- DRAG ELEMENT -- // - class DragElement { + struct DragElement { - public SerializedProperty element; + public SerializedProperty property; public int startIndex; public float dragOffset; - public float height; + public bool selected; + public Rect rect; + /* private bool isExpanded; private Dictionary states; @@ -1493,6 +1543,7 @@ private void Iterate(SerializedProperty element, System.Action