Files
zeling_v2/Packages/com.kybernetik.animancer/Runtime/Utilities/Directional Animations/Directions.cs
2026-05-08 11:04:00 +08:00

284 lines
12 KiB
C#

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