From b9d24d0b400a6a698ce75eee947470b44eb4c215 Mon Sep 17 00:00:00 2001 From: VladV Date: Thu, 23 Mar 2023 14:49:25 +0400 Subject: [PATCH] Add list header drag and drop --- Editor/Elements/TriListElement.cs | 71 ++++++++++++++++++- .../ReorderableListProxy.cs | 6 ++ 2 files changed, 75 insertions(+), 2 deletions(-) diff --git a/Editor/Elements/TriListElement.cs b/Editor/Elements/TriListElement.cs index 4d383ab3..16d8c271 100644 --- a/Editor/Elements/TriListElement.cs +++ b/Editor/Elements/TriListElement.cs @@ -1,10 +1,12 @@ using System; using System.Collections; +using System.Linq; using TriInspectorUnityInternalBridge; using TriInspector.Utilities; using UnityEditor; using UnityEditorInternal; using UnityEngine; +using Object = UnityEngine.Object; namespace TriInspector.Elements { @@ -121,10 +123,15 @@ public override void OnGUI(Rect position) } private void AddElementCallback(ReorderableList reorderableList) + { + AddElementCallback(reorderableList, null); + } + + private void AddElementCallback(ReorderableList reorderableList, Object addedReferenceValue) { if (_property.TryGetSerializedProperty(out _)) { - ReorderableListProxy.defaultBehaviours.DoAddButton(reorderableList); + ReorderableListProxy.DoAddButton(reorderableList, addedReferenceValue); _property.NotifyValueChanged(); return; } @@ -139,6 +146,12 @@ private void AddElementCallback(ReorderableList reorderableList) { var array = Array.CreateInstance(_property.ArrayElementType, template.Length + 1); Array.Copy(template, array, template.Length); + + if (addedReferenceValue != null) + { + array.SetValue(addedReferenceValue, array.Length - 1); + } + value = array; } else @@ -148,7 +161,10 @@ private void AddElementCallback(ReorderableList reorderableList) value = (IList) Activator.CreateInstance(_property.FieldType); } - var newElement = CreateDefaultElementValue(_property); + var newElement = addedReferenceValue != null + ? addedReferenceValue + : CreateDefaultElementValue(_property); + value.Add(newElement); } @@ -293,6 +309,29 @@ private void DrawHeaderCallback(Rect rect) var label = _reorderableListGui.count == 0 ? "Empty" : $"{_reorderableListGui.count} items"; GUI.Label(arraySizeRect, label, Styles.ItemsCount); + + if (Event.current.type == EventType.DragUpdated && rect.Contains(Event.current.mousePosition)) + { + DragAndDrop.visualMode = DragAndDrop.objectReferences.All(obj => TryGetDragAndDropObject(obj, out _)) + ? DragAndDropVisualMode.Copy + : DragAndDropVisualMode.Rejected; + + Event.current.Use(); + } + else if (Event.current.type == EventType.DragPerform && rect.Contains(Event.current.mousePosition)) + { + DragAndDrop.AcceptDrag(); + + foreach (var obj in DragAndDrop.objectReferences) + { + if (TryGetDragAndDropObject(obj, out var addedReferenceValue)) + { + AddElementCallback(_reorderableListGui, addedReferenceValue); + } + } + + Event.current.Use(); + } } private void DrawElementCallback(Rect rect, int index, bool isActive, bool isFocused) @@ -336,6 +375,34 @@ private static Array CloneValue(TriProperty property) return template; } + private bool TryGetDragAndDropObject(Object obj, out Object result) + { + if (obj == null) + { + result = null; + return false; + } + + var elementType = _property.ArrayElementType; + var objType = obj.GetType(); + + if (elementType == objType || elementType.IsAssignableFrom(objType)) + { + result = obj; + return true; + } + + if (obj is GameObject go && typeof(Component).IsAssignableFrom(elementType) && + go.TryGetComponent(elementType, out var component)) + { + result = component; + return true; + } + + result = null; + return false; + } + private static class Styles { public static readonly GUIStyle ItemsCount; diff --git a/Unity.InternalAPIEditorBridge.012/ReorderableListProxy.cs b/Unity.InternalAPIEditorBridge.012/ReorderableListProxy.cs index cd599b52..644c475b 100644 --- a/Unity.InternalAPIEditorBridge.012/ReorderableListProxy.cs +++ b/Unity.InternalAPIEditorBridge.012/ReorderableListProxy.cs @@ -2,6 +2,7 @@ using System.Reflection; using UnityEditorInternal; using UnityEngine; +using Object = UnityEngine.Object; namespace TriInspectorUnityInternalBridge { @@ -59,5 +60,10 @@ public static void ClearCacheRecursive(ReorderableList list) ClearCacheMethod?.Invoke(list, Array.Empty()); #endif } + + public static void DoAddButton(ReorderableList list, Object value) + { + defaultBehaviours.DoAddButton(list, value); + } } } \ No newline at end of file