// Animancer // https://kybernetik.com.au/animancer // Copyright 2018-2026 Kybernetik //
using System;
using UnityEngine;
namespace Animancer
{
/// Left or Right.
///
/// Documentation:
///
/// Directional Animation Sets
///
/// https://kybernetik.com.au/animancer/api/Animancer/Direction2
///
public enum Direction2
{
/************************************************************************************************************************/
/// .
Left,
/// .
Right,
/************************************************************************************************************************/
}
/************************************************************************************************************************/
/// Up, Right, Down, or Left.
///
/// Documentation:
///
/// Directional Animation Sets
///
/// https://kybernetik.com.au/animancer/api/Animancer/Direction4
///
public enum Direction4
{
/************************************************************************************************************************/
/// .
Up,
/// .
Right,
/// .
Down,
/// .
Left,
/************************************************************************************************************************/
}
/************************************************************************************************************************/
/// Up, Right, Down, Left, or their diagonals.
///
/// Documentation:
///
/// Directional Animation Sets
///
/// https://kybernetik.com.au/animancer/api/Animancer/Direction8
///
public enum Direction8
{
/// .
Up,
/// .
Right,
/// .
Down,
/// .
Left,
/// (0.7..., 0.7...).
UpRight,
/// (0.7..., -0.7...).
DownRight,
/// (-0.7..., -0.7...).
DownLeft,
/// (-0.7..., 0.7...).
UpLeft,
}
/************************************************************************************************************************/
///
/// Utilities relating to , and .
///
///
/// Documentation:
///
/// Directional Animation Sets
///
/// https://kybernetik.com.au/animancer/api/Animancer/Directions
///
public static class Directions
{
/************************************************************************************************************************/
/// 1 / (Square Root of 2).
public const float InverseSqrt2 = 0.70710678118f;
/// A vector with a magnitude of 1 pointing up to the right.
/// The value is approximately (0.7, 0.7).
public static Vector2 UpRight => new(InverseSqrt2, InverseSqrt2);
/// A vector with a magnitude of 1 pointing down to the right.
/// The value is approximately (0.7, -0.7).
public static Vector2 DownRight => new(InverseSqrt2, -InverseSqrt2);
/// A vector with a magnitude of 1 pointing down to the left.
/// The value is approximately (-0.7, -0.7).
public static Vector2 DownLeft => new(-InverseSqrt2, -InverseSqrt2);
/// A vector with a magnitude of 1 pointing up to the left.
/// The value is approximately (-0.707, 0.707).
public static Vector2 UpLeft => new(-InverseSqrt2, InverseSqrt2);
/************************************************************************************************************************/
/// Returns the opposite of the given `direction`.
public static Direction2 GetOppositeDirection(this Direction2 direction)
=> (Direction2)(1 - direction);
/// Returns the opposite of the given `direction`.
public static Direction4 GetOppositeDirection(this Direction4 direction)
=> (Direction4)((int)(direction + 2) % 4);
/// Returns the opposite of the given `direction`.
public static Direction8 GetOppositeDirection(this Direction8 direction)
=> (Direction8)((int)(direction + 4) % 8);
/************************************************************************************************************************/
/// Returns a vector representing the specified `direction`.
public static Vector2 ToVector2(this Direction2 direction)
=> direction switch
{
Direction2.Left => Vector2.left,
Direction2.Right => Vector2.right,
_ => throw AnimancerUtilities.CreateUnsupportedArgumentException(direction),
};
/// Returns a vector representing the specified `direction`.
public static Vector2 ToVector2(this Direction4 direction)
=> direction switch
{
Direction4.Up => Vector2.up,
Direction4.Right => Vector2.right,
Direction4.Down => Vector2.down,
Direction4.Left => Vector2.left,
_ => throw AnimancerUtilities.CreateUnsupportedArgumentException(direction),
};
/// Returns a vector representing the specified `direction`.
public static Vector2 ToVector2(this Direction8 direction)
=> direction switch
{
Direction8.Up => Vector2.up,
Direction8.Right => Vector2.right,
Direction8.Down => Vector2.down,
Direction8.Left => Vector2.left,
Direction8.UpRight => UpRight,
Direction8.DownRight => DownRight,
Direction8.DownLeft => DownLeft,
Direction8.UpLeft => UpLeft,
_ => throw AnimancerUtilities.CreateUnsupportedArgumentException(direction),
};
/************************************************************************************************************************/
/// Returns the direction closest to the specified `vector.x`.
/// Negative `direction` returns , 0 or positive returns .
public static Direction2 ToDirection2(Vector2 vector)
=> ToDirection2(vector.x);
/// Returns the direction closest to the specified `direction`.
/// Negative `direction` returns , 0 or positive returns .
public static Direction2 ToDirection2(float direction)
=> direction < 0 ? Direction2.Left : Direction2.Right;
/************************************************************************************************************************/
/// Returns the direction closest to the specified `vector`.
public static Direction4 ToDirection4(Vector2 vector)
{
if (vector.x >= 0)
{
if (vector.y >= 0)
return vector.x > vector.y ? Direction4.Right : Direction4.Up;
else
return vector.x > -vector.y ? Direction4.Right : Direction4.Down;
}
else
{
if (vector.y >= 0)
return vector.x < -vector.y ? Direction4.Left : Direction4.Up;
else
return vector.x < vector.y ? Direction4.Left : Direction4.Down;
}
}
/// Returns the direction closest to the specified `vector`.
public static Direction4 ToDirection4(Vector2Int vector)
{
if (vector.x >= 0)
{
if (vector.y >= 0)
return vector.x > vector.y ? Direction4.Right : Direction4.Up;
else
return vector.x > -vector.y ? Direction4.Right : Direction4.Down;
}
else
{
if (vector.y >= 0)
return vector.x < -vector.y ? Direction4.Left : Direction4.Up;
else
return vector.x < vector.y ? Direction4.Left : Direction4.Down;
}
}
/************************************************************************************************************************/
/// Returns the direction closest to the specified `vector`.
public static Direction8 ToDirection8(Vector2 vector)
{
var angle = Mathf.Atan2(vector.y, vector.x);
var octant = Mathf.RoundToInt(8 * angle / (2 * Mathf.PI) + 8) % 8;
return octant switch
{
0 => Direction8.Right,
1 => Direction8.UpRight,
2 => Direction8.Up,
3 => Direction8.UpLeft,
4 => Direction8.Left,
5 => Direction8.DownLeft,
6 => Direction8.Down,
7 => Direction8.DownRight,
_ => throw new ArgumentOutOfRangeException("Invalid octant"),
};
}
/************************************************************************************************************************/
/// Returns a copy of the `vector` pointing in the closest .
public static Vector2 SnapToDirection2(Vector2 vector)
=> vector.x < 0
? new(-vector.magnitude, 0)
: new(vector.magnitude, 0);
/// Returns a copy of the `vector` pointing in the closest .
public static Vector2 SnapToDirection4(Vector2 vector)
{
var magnitude = vector.magnitude;
var direction = ToDirection4(vector);
vector = direction.ToVector2() * magnitude;
return vector;
}
/// Returns a copy of the `vector` pointing in the closest .
public static Vector2 SnapToDirection8(Vector2 vector)
{
var magnitude = vector.magnitude;
var direction = ToDirection8(vector);
vector = direction.ToVector2() * magnitude;
return vector;
}
/************************************************************************************************************************/
}
}