using System; using System.Linq; using UnityEngine.UIElements; namespace RosettaUI.UIToolkit { public class DragManipulator : PointerManipulator { public event Func onDragStarting; public event Action onDrag; public event Action onDragEnd; private int _activePointerId = -1; public DragManipulator( Func onDragStarting = null, Action onDrag = null, Action onDragEnd = null) { if (onDrag != null) this.onDrag += (_, evt) => onDrag(evt); if (onDragStarting != null) this.onDragStarting += (_, evt) => onDragStarting(evt); if (onDragEnd != null) this.onDragEnd += (_, evt) => onDragEnd(evt); } public DragManipulator( Func onDragStarting , Action onDrag = null, Action onDragEnd = null) { this.onDragStarting += onDragStarting; this.onDrag += onDrag; this.onDragEnd += onDragEnd; } protected override void RegisterCallbacksOnTarget() { target.RegisterCallback(OnPointerDown); target.RegisterCallback(OnPointerMove); target.RegisterCallback(OnPointerUp); target.RegisterCallback(OnPointerCancel); target.RegisterCallback(CancelDrag); } protected override void UnregisterCallbacksFromTarget() { target.UnregisterCallback(OnPointerDown); target.UnregisterCallback(OnPointerMove); target.UnregisterCallback(OnPointerUp); target.UnregisterCallback(OnPointerCancel); } private bool IsCapturedPointer(int pointerId) { return _activePointerId == pointerId && target.HasPointerCapture(pointerId); } private void OnPointerDown(PointerDownEvent e) { if (_activePointerId >= 0) return; if (activators.Any() && !CanStartManipulation(e)) return; bool startDrag; if (onDragStarting != null) { startDrag = onDragStarting(this, e); } else { startDrag = true; e.StopPropagation(); } if (startDrag) { _activePointerId = e.pointerId; target.CapturePointer(e.pointerId); } } private void OnPointerMove(PointerMoveEvent e) { if (!IsCapturedPointer(e.pointerId)) return; onDrag?.Invoke(this, e); } private void OnPointerUp(PointerUpEvent e) { if (!IsCapturedPointer(e.pointerId)) return; Finish(e); } private void OnPointerCancel(PointerCancelEvent e) { if (!IsCapturedPointer(e.pointerId)) return; Finish(e); } private void CancelDrag(EventBase e) { if (_activePointerId < 0) return; Finish(e); } private void Finish(EventBase e) { if (_activePointerId >= 0 && target.HasPointerCapture(_activePointerId)) { target.ReleasePointer(_activePointerId); } _activePointerId = -1; onDragEnd?.Invoke(this, e); } } }