You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
321 lines
14 KiB
C#
321 lines
14 KiB
C#
3 months ago
|
// Animancer // Copyright 2020 Kybernetik //
|
||
|
|
||
|
using System;
|
||
|
using System.Collections.Generic;
|
||
|
using UnityEngine;
|
||
|
|
||
|
namespace Animancer
|
||
|
{
|
||
|
/// <summary>
|
||
|
/// A set of up/down/left/right animations with diagonals as well.
|
||
|
/// </summary>
|
||
|
[CreateAssetMenu(menuName = Strings.MenuPrefix + "Directional Animation Set/8 Directions", order = Strings.AssetMenuOrder + 11)]
|
||
|
public class DirectionalAnimationSet8 : DirectionalAnimationSet
|
||
|
{
|
||
|
/************************************************************************************************************************/
|
||
|
|
||
|
[SerializeField]
|
||
|
private AnimationClip _UpRight;
|
||
|
|
||
|
/// <summary>[<see cref="SerializeField"/>] The animation facing diagonally up-right.</summary>
|
||
|
public AnimationClip UpRight { get { return _UpRight; } }
|
||
|
|
||
|
/// <summary>Sets the <see cref="UpRight"/> animation.</summary>
|
||
|
/// <remarks>This is not simply a property setter because the animations will usually not need to be changed by scripts.</remarks>
|
||
|
public void SetUpRight(AnimationClip clip)
|
||
|
{
|
||
|
_UpRight = clip;
|
||
|
AnimancerUtilities.SetDirty(this);
|
||
|
}
|
||
|
|
||
|
/************************************************************************************************************************/
|
||
|
|
||
|
[SerializeField]
|
||
|
private AnimationClip _DownRight;
|
||
|
|
||
|
/// <summary>[<see cref="SerializeField"/>] The animation facing diagonally down-right.</summary>
|
||
|
public AnimationClip DownRight { get { return _DownRight; } }
|
||
|
|
||
|
/// <summary>Sets the <see cref="DownRight"/> animation.</summary>
|
||
|
/// <remarks>This is not simply a property setter because the animations will usually not need to be changed by scripts.</remarks>
|
||
|
public void SetDownRight(AnimationClip clip)
|
||
|
{
|
||
|
_DownRight = clip;
|
||
|
AnimancerUtilities.SetDirty(this);
|
||
|
}
|
||
|
|
||
|
/************************************************************************************************************************/
|
||
|
|
||
|
[SerializeField]
|
||
|
private AnimationClip _DownLeft;
|
||
|
|
||
|
/// <summary>[<see cref="SerializeField"/>] The animation facing diagonally down-left.</summary>
|
||
|
public AnimationClip DownLeft { get { return _DownLeft; } }
|
||
|
|
||
|
/// <summary>Sets the <see cref="DownLeft"/> animation.</summary>
|
||
|
/// <remarks>This is not simply a property setter because the animations will usually not need to be changed by scripts.</remarks>
|
||
|
public void SetDownLeft(AnimationClip clip)
|
||
|
{
|
||
|
_DownLeft = clip;
|
||
|
AnimancerUtilities.SetDirty(this);
|
||
|
}
|
||
|
|
||
|
/************************************************************************************************************************/
|
||
|
|
||
|
[SerializeField]
|
||
|
private AnimationClip _UpLeft;
|
||
|
|
||
|
/// <summary>[<see cref="SerializeField"/>] The animation facing diagonally up-left.</summary>
|
||
|
public AnimationClip UpLeft { get { return _UpLeft; } }
|
||
|
|
||
|
/// <summary>Sets the <see cref="UpLeft"/> animation.</summary>
|
||
|
/// <remarks>This is not simply a property setter because the animations will usually not need to be changed by scripts.</remarks>
|
||
|
public void SetUpLeft(AnimationClip clip)
|
||
|
{
|
||
|
_UpLeft = clip;
|
||
|
AnimancerUtilities.SetDirty(this);
|
||
|
}
|
||
|
|
||
|
/************************************************************************************************************************/
|
||
|
|
||
|
/// <summary>Returns the animation closest to the specified `direction`.</summary>
|
||
|
public override AnimationClip GetClip(Vector2 direction)
|
||
|
{
|
||
|
var angle = Mathf.Atan2(direction.y, direction.x);
|
||
|
var octant = Mathf.RoundToInt(8 * angle / (2 * Mathf.PI) + 8) % 8;
|
||
|
switch (octant)
|
||
|
{
|
||
|
case 0: return Right;
|
||
|
case 1: return _UpRight;
|
||
|
case 2: return Up;
|
||
|
case 3: return _UpLeft;
|
||
|
case 4: return Left;
|
||
|
case 5: return _DownLeft;
|
||
|
case 6: return Down;
|
||
|
case 7: return _DownRight;
|
||
|
default: throw new ArgumentOutOfRangeException("Invalid octant");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/************************************************************************************************************************/
|
||
|
#region Directions
|
||
|
/************************************************************************************************************************/
|
||
|
|
||
|
/// <summary>Constants for each of the diagonal directions.</summary>
|
||
|
public static class Diagonals
|
||
|
{
|
||
|
/************************************************************************************************************************/
|
||
|
|
||
|
/// <summary>1 / (Square Root of 2).</summary>
|
||
|
public const float OneOverSqrt2 = 0.70710678118f;
|
||
|
|
||
|
/// <summary>
|
||
|
/// A vector with a magnitude of 1 pointing up to the right.
|
||
|
/// <para></para>
|
||
|
/// The value is approximately (0.707, 0.707).
|
||
|
/// </summary>
|
||
|
public static Vector2 UpRight { get { return new Vector2(OneOverSqrt2, OneOverSqrt2); } }
|
||
|
|
||
|
/// <summary>
|
||
|
/// A vector with a magnitude of 1 pointing down to the right.
|
||
|
/// <para></para>
|
||
|
/// The value is approximately (0.707, -0.707).
|
||
|
/// </summary>
|
||
|
public static Vector2 DownRight { get { return new Vector2(OneOverSqrt2, -OneOverSqrt2); } }
|
||
|
|
||
|
/// <summary>
|
||
|
/// A vector with a magnitude of 1 pointing down to the left.
|
||
|
/// <para></para>
|
||
|
/// The value is approximately (-0.707, -0.707).
|
||
|
/// </summary>
|
||
|
public static Vector2 DownLeft { get { return new Vector2(-OneOverSqrt2, -OneOverSqrt2); } }
|
||
|
|
||
|
/// <summary>
|
||
|
/// A vector with a magnitude of 1 pointing up to the left.
|
||
|
/// <para></para>
|
||
|
/// The value is approximately (-0.707, 0.707).
|
||
|
/// </summary>
|
||
|
public static Vector2 UpLeft { get { return new Vector2(-OneOverSqrt2, OneOverSqrt2); } }
|
||
|
|
||
|
/************************************************************************************************************************/
|
||
|
}
|
||
|
|
||
|
/************************************************************************************************************************/
|
||
|
|
||
|
/// <summary>The number of animations in this set.</summary>
|
||
|
public override int ClipCount { get { return 8; } }
|
||
|
|
||
|
/************************************************************************************************************************/
|
||
|
|
||
|
/// <summary>Up, Down, Left Right, or their diagonals.</summary>
|
||
|
public new enum Direction
|
||
|
{
|
||
|
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member.
|
||
|
Up,
|
||
|
Right,
|
||
|
Down,
|
||
|
Left,
|
||
|
UpRight,
|
||
|
DownRight,
|
||
|
DownLeft,
|
||
|
UpLeft,
|
||
|
#pragma warning restore CS1591 // Missing XML comment for publicly visible type or member.
|
||
|
}
|
||
|
|
||
|
/************************************************************************************************************************/
|
||
|
|
||
|
/// <summary>Returns the name of the specified `direction`.</summary>
|
||
|
protected override string GetDirectionName(int direction) { return ((Direction)direction).ToString(); }
|
||
|
|
||
|
/************************************************************************************************************************/
|
||
|
|
||
|
/// <summary>Returns the animation associated with the specified `direction`.</summary>
|
||
|
public AnimationClip GetClip(Direction direction)
|
||
|
{
|
||
|
switch (direction)
|
||
|
{
|
||
|
case Direction.Up: return Up;
|
||
|
case Direction.Right: return Right;
|
||
|
case Direction.Down: return Down;
|
||
|
case Direction.Left: return Left;
|
||
|
case Direction.UpRight: return _UpRight;
|
||
|
case Direction.DownRight: return _DownRight;
|
||
|
case Direction.DownLeft: return _DownLeft;
|
||
|
case Direction.UpLeft: return _UpLeft;
|
||
|
default: throw new ArgumentException("Unhandled direction: " + direction);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <summary>Returns the animation associated with the specified `direction`.</summary>
|
||
|
public override AnimationClip GetClip(int direction)
|
||
|
{
|
||
|
return GetClip((Direction)direction);
|
||
|
}
|
||
|
|
||
|
/************************************************************************************************************************/
|
||
|
|
||
|
/// <summary>Sets the animation associated with the specified `direction`.</summary>
|
||
|
public void SetClip(Direction direction, AnimationClip clip)
|
||
|
{
|
||
|
switch (direction)
|
||
|
{
|
||
|
case Direction.Up: SetUp(clip); break;
|
||
|
case Direction.Right: SetRight(clip); break;
|
||
|
case Direction.Down: SetDown(clip); break;
|
||
|
case Direction.Left: SetLeft(clip); break;
|
||
|
case Direction.UpRight: _UpRight = clip; break;
|
||
|
case Direction.DownRight: _DownRight = clip; break;
|
||
|
case Direction.DownLeft: _DownLeft = clip; break;
|
||
|
case Direction.UpLeft: _UpLeft = clip; break;
|
||
|
default: throw new ArgumentException("Unhandled direction: " + direction);
|
||
|
}
|
||
|
|
||
|
AnimancerUtilities.SetDirty(this);
|
||
|
}
|
||
|
|
||
|
/// <summary>Sets the animation associated with the specified `direction`.</summary>
|
||
|
public override void SetClip(int direction, AnimationClip clip)
|
||
|
{
|
||
|
SetClip((Direction)direction, clip);
|
||
|
}
|
||
|
|
||
|
/************************************************************************************************************************/
|
||
|
|
||
|
/// <summary>Returns a vector representing the specified `direction`.</summary>
|
||
|
public static Vector2 DirectionToVector(Direction direction)
|
||
|
{
|
||
|
switch (direction)
|
||
|
{
|
||
|
case Direction.Up: return Vector2.up;
|
||
|
case Direction.Right: return Vector2.right;
|
||
|
case Direction.Down: return Vector2.down;
|
||
|
case Direction.Left: return Vector2.left;
|
||
|
case Direction.UpRight: return Diagonals.UpRight;
|
||
|
case Direction.DownRight: return Diagonals.DownRight;
|
||
|
case Direction.DownLeft: return Diagonals.DownLeft;
|
||
|
case Direction.UpLeft: return Diagonals.UpLeft;
|
||
|
default: throw new ArgumentException("Unhandled direction: " + direction);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <summary>Returns a vector representing the specified `direction`.</summary>
|
||
|
public override Vector2 GetDirection(int direction)
|
||
|
{
|
||
|
return DirectionToVector((Direction)direction);
|
||
|
}
|
||
|
|
||
|
/************************************************************************************************************************/
|
||
|
|
||
|
/// <summary>Returns the direction closest to the specified `vector`.</summary>
|
||
|
public new static Direction VectorToDirection(Vector2 vector)
|
||
|
{
|
||
|
var angle = Mathf.Atan2(vector.y, vector.x);
|
||
|
var octant = Mathf.RoundToInt(8 * angle / (2 * Mathf.PI) + 8) % 8;
|
||
|
switch (octant)
|
||
|
{
|
||
|
case 0: return Direction.Right;
|
||
|
case 1: return Direction.UpRight;
|
||
|
case 2: return Direction.Up;
|
||
|
case 3: return Direction.UpLeft;
|
||
|
case 4: return Direction.Left;
|
||
|
case 5: return Direction.DownLeft;
|
||
|
case 6: return Direction.Down;
|
||
|
case 7: return Direction.DownRight;
|
||
|
default: throw new ArgumentOutOfRangeException("Invalid octant");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/************************************************************************************************************************/
|
||
|
|
||
|
/// <summary>Returns a copy of the `vector` pointing in the closest direction this set type has an animation for.</summary>
|
||
|
public new static Vector2 SnapVectorToDirection(Vector2 vector)
|
||
|
{
|
||
|
var magnitude = vector.magnitude;
|
||
|
var direction = VectorToDirection(vector);
|
||
|
vector = DirectionToVector(direction) * magnitude;
|
||
|
return vector;
|
||
|
}
|
||
|
|
||
|
/// <summary>Returns a copy of the `vector` pointing in the closest direction this set has an animation for.</summary>
|
||
|
public override Vector2 Snap(Vector2 vector)
|
||
|
{
|
||
|
return SnapVectorToDirection(vector);
|
||
|
}
|
||
|
|
||
|
/************************************************************************************************************************/
|
||
|
#endregion
|
||
|
/************************************************************************************************************************/
|
||
|
#region Name Based Operations
|
||
|
/************************************************************************************************************************/
|
||
|
#if UNITY_EDITOR
|
||
|
/************************************************************************************************************************/
|
||
|
|
||
|
/// <summary>
|
||
|
/// Attempts to assign the `clip` to one of this set's fields based on its name and returns the direction index
|
||
|
/// of that field (or -1 if it was unable to determine the direction).
|
||
|
/// </summary>
|
||
|
public override int SetClipByName(AnimationClip clip)
|
||
|
{
|
||
|
var name = clip.name;
|
||
|
|
||
|
var directionCount = ClipCount;
|
||
|
for (int i = directionCount - 1; i >= 0; i--)
|
||
|
{
|
||
|
if (name.Contains(GetDirectionName(i)))
|
||
|
{
|
||
|
SetClip(i, clip);
|
||
|
return i;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
/************************************************************************************************************************/
|
||
|
#endif
|
||
|
/************************************************************************************************************************/
|
||
|
#endregion
|
||
|
/************************************************************************************************************************/
|
||
|
}
|
||
|
}
|