using System; using UnityEngine; using UnityEngine.UIElements; namespace UnityEditor.U2D.Animation.SpriteLibraryEditor { /// /// Manipulator that allows dragging from a container component. /// internal class Dragger : PointerManipulator { /// /// The threshold in pixels after which a drag will start. /// public float dragThreshold { get; set; } = 8f; /// /// Whether the drag is currently active. /// public bool isActive { get; private set; } /// /// Delegate that will be called when a drag should be accepted during . /// /// /// If this delegate is not set (or set to null), the drag will be accepted by default. /// public Func acceptStartDrag { get; set; } /// /// Delegate that will be called when a drag should be accepted when the dragger wants to become /// active during . /// /// /// If this delegate is not set (or set to null), the drag will be accepted by default. /// public Func acceptDrag { get; set; } int m_PointerId = -1; Vector3 m_StartPosition; event Action onDragStarted; event Action onDragging; event Action onDragEnded; event Action onDragCanceled; /// /// Creates a new instance. /// /// The event that will be fired when a drag starts. /// The event that will be fired when a drag is in progress. /// The event that will be fired when a drag ends. /// The event that will be fired when a drag is cancelled. public Dragger(Action dragStarted, Action dragging, Action dragEnded, Action dragCanceled) { onDragStarted = dragStarted; onDragging = dragging; onDragEnded = dragEnded; onDragCanceled = dragCanceled; } /// protected override void RegisterCallbacksOnTarget() { activators.Add(new ManipulatorActivationFilter { button = MouseButton.LeftMouse }); target.RegisterCallback(OnPointerDown); target.RegisterCallback(OnPointerMove); target.RegisterCallback(OnPointerUp); target.RegisterCallback(OnPointerCancel); target.RegisterCallback(OnPointerCaptureOut); target.RegisterCallback(OnKeyDown); } /// protected override void UnregisterCallbacksFromTarget() { activators.Clear(); target.UnregisterCallback(OnPointerDown); target.UnregisterCallback(OnPointerMove); target.UnregisterCallback(OnPointerUp); target.UnregisterCallback(OnPointerCancel); target.UnregisterCallback(OnPointerCaptureOut); target.UnregisterCallback(OnKeyDown); } void OnPointerDown(PointerDownEvent evt) { isActive = false; m_PointerId = -1; if (CanStartManipulation(evt) && (acceptStartDrag == null || acceptStartDrag.Invoke(evt.position))) { m_StartPosition = evt.position; m_PointerId = evt.pointerId; } } void OnPointerMove(PointerMoveEvent evt) { if (m_PointerId != evt.pointerId) return; if (m_PointerId != -1) { if (!isActive) { var delta = evt.position - m_StartPosition; if (delta.sqrMagnitude > dragThreshold * dragThreshold && (acceptDrag == null || acceptDrag.Invoke())) { if (!target.HasPointerCapture(evt.pointerId)) { target.CapturePointer(evt.pointerId); #if !UNITY_2023_1_OR_NEWER if (evt.pointerId == PointerId.mousePointerId) target.CaptureMouse(); #endif } isActive = true; onDragStarted?.Invoke(evt); } } else { if (!target.HasPointerCapture(evt.pointerId)) { target.CapturePointer(evt.pointerId); #if !UNITY_2023_1_OR_NEWER if (evt.pointerId == PointerId.mousePointerId) target.CaptureMouse(); #endif } onDragging?.Invoke(evt); } } } void OnPointerUp(PointerUpEvent evt) { if (m_PointerId != evt.pointerId) return; if (target.HasPointerCapture(evt.pointerId)) target.ReleasePointer(evt.pointerId); if (isActive) onDragEnded?.Invoke(evt); isActive = false; m_PointerId = -1; } void OnPointerCancel(PointerCancelEvent evt) { if (evt.pointerId == m_PointerId) Cancel(); } void OnPointerCaptureOut(PointerCaptureOutEvent evt) { if (evt.pointerId == m_PointerId) Cancel(); } void OnKeyDown(KeyDownEvent evt) { if (m_PointerId == -1) return; if (evt.keyCode == KeyCode.Escape) { evt.StopImmediatePropagation(); Cancel(); } } /// /// Cancels the drag. /// public void Cancel() { if (target.HasPointerCapture(m_PointerId)) target.ReleasePointer(m_PointerId); if (isActive) { isActive = false; onDragCanceled?.Invoke(); } m_PointerId = -1; } } }