DirectionalAnimationSet8.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  1. // Animancer // https://kybernetik.com.au/animancer // Copyright 2018-2024 Kybernetik //
  2. using System;
  3. using UnityEngine;
  4. namespace Animancer
  5. {
  6. /// <summary>A set of up/right/down/left animations with diagonals as well.</summary>
  7. /// <remarks>
  8. /// <strong>Documentation:</strong>
  9. /// <see href="https://kybernetik.com.au/animancer/docs/manual/playing/directional-sets">
  10. /// Directional Animation Sets</see>
  11. /// </remarks>
  12. /// https://kybernetik.com.au/animancer/api/Animancer/DirectionalAnimationSet8
  13. ///
  14. [CreateAssetMenu(
  15. menuName = Strings.MenuPrefix + "Directional Animation Set/8 Directions",
  16. order = Strings.AssetMenuOrder + 4)]
  17. [AnimancerHelpUrl(typeof(DirectionalAnimationSet8))]
  18. public class DirectionalAnimationSet8 : DirectionalAnimationSet
  19. {
  20. /************************************************************************************************************************/
  21. [SerializeField]
  22. private AnimationClip _UpRight;
  23. /// <summary>[<see cref="SerializeField"/>] The animation facing diagonally up-right ~(0.7, 0.7).</summary>
  24. /// <exception cref="ArgumentException"><see cref="AllowSetClips"/> was not called before setting this value.</exception>
  25. public AnimationClip UpRight
  26. {
  27. get => _UpRight;
  28. set
  29. {
  30. AssertCanSetClips();
  31. _UpRight = value;
  32. AnimancerUtilities.SetDirty(this);
  33. }
  34. }
  35. /************************************************************************************************************************/
  36. [SerializeField]
  37. private AnimationClip _DownRight;
  38. /// <summary>[<see cref="SerializeField"/>] The animation facing diagonally down-right ~(0.7, -0.7).</summary>
  39. /// <exception cref="ArgumentException"><see cref="AllowSetClips"/> was not called before setting this value.</exception>
  40. public AnimationClip DownRight
  41. {
  42. get => _DownRight;
  43. set
  44. {
  45. AssertCanSetClips();
  46. _DownRight = value;
  47. AnimancerUtilities.SetDirty(this);
  48. }
  49. }
  50. /************************************************************************************************************************/
  51. [SerializeField]
  52. private AnimationClip _DownLeft;
  53. /// <summary>[<see cref="SerializeField"/>] The animation facing diagonally down-left ~(-0.7, -0.7).</summary>
  54. /// <exception cref="ArgumentException"><see cref="AllowSetClips"/> was not called before setting this value.</exception>
  55. public AnimationClip DownLeft
  56. {
  57. get => _DownLeft;
  58. set
  59. {
  60. AssertCanSetClips();
  61. _DownLeft = value;
  62. AnimancerUtilities.SetDirty(this);
  63. }
  64. }
  65. /************************************************************************************************************************/
  66. [SerializeField]
  67. private AnimationClip _UpLeft;
  68. /// <summary>[<see cref="SerializeField"/>] The animation facing diagonally up-left ~(-0.7, 0.7).</summary>
  69. /// <exception cref="ArgumentException"><see cref="AllowSetClips"/> was not called before setting this value.</exception>
  70. public AnimationClip UpLeft
  71. {
  72. get => _UpLeft;
  73. set
  74. {
  75. AssertCanSetClips();
  76. _UpLeft = value;
  77. AnimancerUtilities.SetDirty(this);
  78. }
  79. }
  80. /************************************************************************************************************************/
  81. /// <summary>Returns the animation closest to the specified `direction`.</summary>
  82. public override AnimationClip GetClip(Vector2 direction)
  83. {
  84. var angle = Mathf.Atan2(direction.y, direction.x);
  85. var octant = Mathf.RoundToInt(8 * angle / (2 * Mathf.PI) + 8) % 8;
  86. return octant switch
  87. {
  88. 0 => Right,
  89. 1 => _UpRight,
  90. 2 => Up,
  91. 3 => _UpLeft,
  92. 4 => Left,
  93. 5 => _DownLeft,
  94. 6 => Down,
  95. 7 => _DownRight,
  96. _ => throw new ArgumentOutOfRangeException("Invalid octant"),
  97. };
  98. }
  99. /************************************************************************************************************************/
  100. #region Directions
  101. /************************************************************************************************************************/
  102. /// <summary>Constants for each of the diagonal directions.</summary>
  103. /// <remarks>
  104. /// <strong>Documentation:</strong>
  105. /// <see href="https://kybernetik.com.au/animancer/docs/manual/playing/directional-sets">
  106. /// Directional Animation Sets</see>
  107. /// </remarks>
  108. /// https://kybernetik.com.au/animancer/api/Animancer/Diagonals
  109. ///
  110. public static class Diagonals
  111. {
  112. /************************************************************************************************************************/
  113. /// <summary>1 / (Square Root of 2).</summary>
  114. public const float OneOverSqrt2 = 0.70710678118f;
  115. /// <summary>A vector with a magnitude of 1 pointing up to the right.</summary>
  116. /// <remarks>The value is approximately (0.7, 0.7).</remarks>
  117. public static Vector2 UpRight => new(OneOverSqrt2, OneOverSqrt2);
  118. /// <summary>A vector with a magnitude of 1 pointing down to the right.</summary>
  119. /// <remarks>The value is approximately (0.7, -0.7).</remarks>
  120. public static Vector2 DownRight => new(OneOverSqrt2, -OneOverSqrt2);
  121. /// <summary>A vector with a magnitude of 1 pointing down to the left.</summary>
  122. /// <remarks>The value is approximately (-0.7, -0.7).</remarks>
  123. public static Vector2 DownLeft => new(-OneOverSqrt2, -OneOverSqrt2);
  124. /// <summary>A vector with a magnitude of 1 pointing up to the left.</summary>
  125. /// <remarks>The value is approximately (-0.707, 0.707).</remarks>
  126. public static Vector2 UpLeft => new(-OneOverSqrt2, OneOverSqrt2);
  127. /************************************************************************************************************************/
  128. }
  129. /************************************************************************************************************************/
  130. /// <inheritdoc/>
  131. public override int ClipCount
  132. => 8;
  133. /************************************************************************************************************************/
  134. /// <summary>Up, Right, Down, Left, or their diagonals.</summary>
  135. /// <remarks>
  136. /// <strong>Documentation:</strong>
  137. /// <see href="https://kybernetik.com.au/animancer/docs/manual/playing/directional-sets">
  138. /// Directional Animation Sets</see>
  139. /// </remarks>
  140. /// https://kybernetik.com.au/animancer/api/Animancer/Direction
  141. ///
  142. public new enum Direction
  143. {
  144. /// <summary><see cref="Vector2.up"/>.</summary>
  145. Up,
  146. /// <summary><see cref="Vector2.right"/>.</summary>
  147. Right,
  148. /// <summary><see cref="Vector2.down"/>.</summary>
  149. Down,
  150. /// <summary><see cref="Vector2.left"/>.</summary>
  151. Left,
  152. /// <summary><see cref="Vector2"/>(0.7..., 0.7...).</summary>
  153. UpRight,
  154. /// <summary><see cref="Vector2"/>(0.7..., -0.7...).</summary>
  155. DownRight,
  156. /// <summary><see cref="Vector2"/>(-0.7..., -0.7...).</summary>
  157. DownLeft,
  158. /// <summary><see cref="Vector2"/>(-0.7..., 0.7...).</summary>
  159. UpLeft,
  160. }
  161. /************************************************************************************************************************/
  162. protected override string GetDirectionName(int direction)
  163. => ((Direction)direction).ToString();
  164. /************************************************************************************************************************/
  165. /// <summary>Returns the animation associated with the specified `direction`.</summary>
  166. public AnimationClip GetClip(Direction direction)
  167. => direction switch
  168. {
  169. Direction.Up => Up,
  170. Direction.Right => Right,
  171. Direction.Down => Down,
  172. Direction.Left => Left,
  173. Direction.UpRight => _UpRight,
  174. Direction.DownRight => _DownRight,
  175. Direction.DownLeft => _DownLeft,
  176. Direction.UpLeft => _UpLeft,
  177. _ => throw AnimancerUtilities.CreateUnsupportedArgumentException(direction),
  178. };
  179. public override AnimationClip GetClip(int direction)
  180. => GetClip((Direction)direction);
  181. /************************************************************************************************************************/
  182. /// <summary>Sets the animation associated with the specified `direction`.</summary>
  183. public void SetClip(Direction direction, AnimationClip clip)
  184. {
  185. switch (direction)
  186. {
  187. case Direction.Up: Up = clip; break;
  188. case Direction.Right: Right = clip; break;
  189. case Direction.Down: Down = clip; break;
  190. case Direction.Left: Left = clip; break;
  191. case Direction.UpRight: UpRight = clip; break;
  192. case Direction.DownRight: DownRight = clip; break;
  193. case Direction.DownLeft: DownLeft = clip; break;
  194. case Direction.UpLeft: UpLeft = clip; break;
  195. default: throw AnimancerUtilities.CreateUnsupportedArgumentException(direction);
  196. }
  197. }
  198. public override void SetClip(int direction, AnimationClip clip)
  199. => SetClip((Direction)direction, clip);
  200. /************************************************************************************************************************/
  201. /// <summary>Returns a vector representing the specified `direction`.</summary>
  202. public static Vector2 DirectionToVector(Direction direction)
  203. => direction switch
  204. {
  205. Direction.Up => Vector2.up,
  206. Direction.Right => Vector2.right,
  207. Direction.Down => Vector2.down,
  208. Direction.Left => Vector2.left,
  209. Direction.UpRight => Diagonals.UpRight,
  210. Direction.DownRight => Diagonals.DownRight,
  211. Direction.DownLeft => Diagonals.DownLeft,
  212. Direction.UpLeft => Diagonals.UpLeft,
  213. _ => throw AnimancerUtilities.CreateUnsupportedArgumentException(direction),
  214. };
  215. public override Vector2 GetDirection(int direction)
  216. => DirectionToVector((Direction)direction);
  217. /************************************************************************************************************************/
  218. /// <summary>Returns the direction closest to the specified `vector`.</summary>
  219. public new static Direction VectorToDirection(Vector2 vector)
  220. {
  221. var angle = Mathf.Atan2(vector.y, vector.x);
  222. var octant = Mathf.RoundToInt(8 * angle / (2 * Mathf.PI) + 8) % 8;
  223. return octant switch
  224. {
  225. 0 => Direction.Right,
  226. 1 => Direction.UpRight,
  227. 2 => Direction.Up,
  228. 3 => Direction.UpLeft,
  229. 4 => Direction.Left,
  230. 5 => Direction.DownLeft,
  231. 6 => Direction.Down,
  232. 7 => Direction.DownRight,
  233. _ => throw new ArgumentOutOfRangeException("Invalid octant"),
  234. };
  235. }
  236. /************************************************************************************************************************/
  237. /// <summary>
  238. /// Returns a copy of the `vector` pointing in the closest direction
  239. /// which this set type has an animation for.
  240. /// </summary>
  241. public new static Vector2 SnapVectorToDirection(Vector2 vector)
  242. {
  243. var magnitude = vector.magnitude;
  244. var direction = VectorToDirection(vector);
  245. vector = DirectionToVector(direction) * magnitude;
  246. return vector;
  247. }
  248. public override Vector2 Snap(Vector2 vector)
  249. => SnapVectorToDirection(vector);
  250. /************************************************************************************************************************/
  251. /// <inheritdoc/>
  252. public override int SetClipByName(AnimationClip clip)
  253. {
  254. var name = clip.name;
  255. var directionCount = ClipCount;
  256. for (int i = directionCount - 1; i >= 0; i--)
  257. {
  258. if (name.Contains(GetDirectionName(i)))
  259. {
  260. SetClip(i, clip);
  261. return i;
  262. }
  263. }
  264. return -1;
  265. }
  266. /************************************************************************************************************************/
  267. #endregion
  268. /************************************************************************************************************************/
  269. }
  270. }