Editor/DragLatch.cs
using System;

namespace AltCurves;

/// <summary>
/// A little state machine helping with dragging operations. 
/// The 2D accumulator will accumulate mouse movement deltas until a threshold is reached,
/// at which point it will latch to the nearest cardinal direction.
/// </summary>
internal class DragLatch
{
	internal enum LatchState
	{
		Inactive,
		Accumulating,
		Latched
	}
	public LatchState State { get; private set; }

	/// <summary>
	/// Once we're Latched, this is the direction along which movement should be constrained
	/// </summary>
	public Vector2 LatchDirection { get; private set; }

	/// <summary>
	/// Pixel distance before we choose the snap direction
	/// </summary>
	private const float MOUSE_LATCH_THRESHOLD = 15.0f;
	private Vector2 _accumMouse;

	/// <summary>
	/// Dragging ended, reset any ongoing latch state
	/// </summary>
	internal void Reset()
	{
		State = LatchState.Inactive;
	}

	/// <summary>
	/// Dragging begun
	/// </summary>
	internal void Start()
	{
		State = LatchState.Accumulating;
		_accumMouse = Vector2.Zero;	
	}

	/// <summary>
	/// Accumulate the mouse position delta, transition into latched when ready
	/// </summary>
	internal void Accumulate( Vector2 positionDelta )
	{
		if ( State == LatchState.Accumulating )
		{
			_accumMouse += positionDelta;

			// Going over a distance threshold results in snapping to the nearest cardinal direction
			if ( _accumMouse.Length > MOUSE_LATCH_THRESHOLD )
			{
				State = LatchState.Latched;

				if (Math.Abs( _accumMouse.x ) > Math.Abs( _accumMouse.y ) )
				{
					LatchDirection = Vector2.Right;
				}
				else
				{
					LatchDirection = Vector2.Up;
				}
			}
		}
	}
}