From 466017c10224c4229fbb8b7691c757835f65485a Mon Sep 17 00:00:00 2001 From: bd_ Date: Mon, 2 Sep 2024 19:30:40 -0700 Subject: [PATCH] feat: add support for drag-and-drop on the MA Object Toggle inspector (#1087) --- .../ObjectToggle/ObjectSwitcherEditor.cs | 100 ++++++++++++++++++ .../ObjectToggle/ObjectSwitcherStyles.uss | 4 + 2 files changed, 104 insertions(+) diff --git a/Editor/Inspector/ObjectToggle/ObjectSwitcherEditor.cs b/Editor/Inspector/ObjectToggle/ObjectSwitcherEditor.cs index e954dda7..8807e221 100644 --- a/Editor/Inspector/ObjectToggle/ObjectSwitcherEditor.cs +++ b/Editor/Inspector/ObjectToggle/ObjectSwitcherEditor.cs @@ -1,6 +1,7 @@ #region using System; +using System.Linq; using UnityEditor; using UnityEditor.UIElements; using UnityEngine; @@ -16,6 +17,7 @@ namespace nadena.dev.modular_avatar.core.editor.ShapeChanger [SerializeField] private StyleSheet uss; [SerializeField] private VisualTreeAsset uxml; + private DragAndDropManipulator _dragAndDropManipulator; protected override void OnInnerInspectorGUI() { @@ -33,11 +35,109 @@ namespace nadena.dev.modular_avatar.core.editor.ShapeChanger ROSimulatorButton.BindRefObject(root, target); var listView = root.Q("Shapes"); + _dragAndDropManipulator = new DragAndDropManipulator(listView) + { + TargetComponent = target as ModularAvatarObjectToggle + }; listView.showBoundCollectionSize = false; listView.virtualizationMethod = CollectionVirtualizationMethod.DynamicHeight; return root; } + + private void OnEnable() + { + if (_dragAndDropManipulator != null) + _dragAndDropManipulator.TargetComponent = target as ModularAvatarObjectToggle; + } + + private class DragAndDropManipulator : PointerManipulator + { + public ModularAvatarObjectToggle TargetComponent; + private GameObject[] _nowDragging = Array.Empty(); + private Transform _avatarRoot; + + private readonly VisualElement _parentElem; + + public DragAndDropManipulator(VisualElement target) + { + this.target = target; + _parentElem = target.parent; + } + + protected override void RegisterCallbacksOnTarget() + { + target.RegisterCallback(OnDragEnter); + target.RegisterCallback(OnDragLeave); + target.RegisterCallback(OnDragPerform); + target.RegisterCallback(OnDragUpdate); + } + + protected override void UnregisterCallbacksFromTarget() + { + target.UnregisterCallback(OnDragEnter); + target.UnregisterCallback(OnDragLeave); + target.UnregisterCallback(OnDragPerform); + target.RegisterCallback(OnDragUpdate); + } + + + private void OnDragEnter(DragEnterEvent evt) + { + if (TargetComponent == null) return; + + _avatarRoot = RuntimeUtil.FindAvatarTransformInParents(TargetComponent.transform); + if (_avatarRoot == null) return; + + _nowDragging = DragAndDrop.objectReferences.OfType() + .Where(o => RuntimeUtil.FindAvatarTransformInParents(o.transform) == _avatarRoot) + .ToArray(); + + if (_nowDragging.Length > 0) + { + DragAndDrop.visualMode = DragAndDropVisualMode.Link; + + _parentElem.AddToClassList("drop-area--drag-active"); + } + } + + private void OnDragUpdate(DragUpdatedEvent _) + { + if (_nowDragging.Length > 0) DragAndDrop.visualMode = DragAndDropVisualMode.Link; + } + + private void OnDragLeave(DragLeaveEvent evt) + { + _nowDragging = Array.Empty(); + _parentElem.RemoveFromClassList("drop-area--drag-active"); + } + + private void OnDragPerform(DragPerformEvent evt) + { + if (_nowDragging.Length > 0 && TargetComponent != null && _avatarRoot != null) + { + var knownObjs = TargetComponent.Objects.Select(o => o.Object.Get(TargetComponent)).ToHashSet(); + + Undo.RecordObject(TargetComponent, "Add Toggled Objects"); + foreach (var obj in _nowDragging) + { + if (knownObjs.Contains(obj)) continue; + + var aor = new AvatarObjectReference(); + aor.Set(obj); + + var toggledObject = new ToggledObject { Object = aor, Active = !obj.activeSelf }; + TargetComponent.Objects.Add(toggledObject); + } + + EditorUtility.SetDirty(TargetComponent); + PrefabUtility.RecordPrefabInstancePropertyModifications(TargetComponent); + } + + _nowDragging = Array.Empty(); + _parentElem.RemoveFromClassList("drop-area--drag-active"); + } + } } } \ No newline at end of file diff --git a/Editor/Inspector/ObjectToggle/ObjectSwitcherStyles.uss b/Editor/Inspector/ObjectToggle/ObjectSwitcherStyles.uss index db197753..133b6154 100644 --- a/Editor/Inspector/ObjectToggle/ObjectSwitcherStyles.uss +++ b/Editor/Inspector/ObjectToggle/ObjectSwitcherStyles.uss @@ -112,3 +112,7 @@ flex-grow: 1; -unity-text-align: middle-left; } + +.drop-area--drag-active > ListView ScrollView { + background-color: rgba(0, 255, 255, 0.1); +} \ No newline at end of file