MixerTransition2DDrawer.cs 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. // Animancer // https://kybernetik.com.au/animancer // Copyright 2018-2024 Kybernetik //
  2. #if UNITY_EDITOR && UNITY_IMGUI
  3. using System;
  4. using UnityEditor;
  5. using UnityEngine;
  6. using Object = UnityEngine.Object;
  7. namespace Animancer.Editor
  8. {
  9. /// <inheritdoc/>
  10. /// https://kybernetik.com.au/animancer/api/Animancer.Editor/MixerTransition2DDrawer
  11. [CustomPropertyDrawer(typeof(MixerTransition2D), true)]
  12. public class MixerTransition2DDrawer : MixerTransitionDrawer
  13. {
  14. /************************************************************************************************************************/
  15. /// <summary>
  16. /// Creates a new <see cref="MixerTransition2DDrawer"/> using a wider
  17. /// `thresholdWidth` than usual to accomodate both the X and Y values.
  18. /// </summary>
  19. public MixerTransition2DDrawer()
  20. : base(StandardThresholdWidth * 2 + 20)
  21. { }
  22. /************************************************************************************************************************/
  23. /// <inheritdoc/>
  24. protected override void AddThresholdFunctionsToMenu(GenericMenu menu)
  25. {
  26. AddCalculateThresholdsFunction(menu, "From Velocity/XY", (state, threshold) =>
  27. {
  28. if (AnimancerUtilities.TryGetAverageVelocity(state, out var velocity))
  29. return new(velocity.x, velocity.y);
  30. else
  31. return new(float.NaN, float.NaN);
  32. });
  33. AddCalculateThresholdsFunction(menu, "From Velocity/XZ", (state, threshold) =>
  34. {
  35. if (AnimancerUtilities.TryGetAverageVelocity(state, out var velocity))
  36. return new(velocity.x, velocity.z);
  37. else
  38. return new(float.NaN, float.NaN);
  39. });
  40. AddCalculateThresholdsFunctionPerAxis(menu, "From Speed",
  41. (state, threshold) => AnimancerUtilities.TryGetAverageVelocity(state, out var velocity)
  42. ? velocity.magnitude
  43. : float.NaN);
  44. AddCalculateThresholdsFunctionPerAxis(menu, "From Velocity X",
  45. (state, threshold) => AnimancerUtilities.TryGetAverageVelocity(state, out var velocity)
  46. ? velocity.x
  47. : float.NaN);
  48. AddCalculateThresholdsFunctionPerAxis(menu, "From Velocity Y",
  49. (state, threshold) => AnimancerUtilities.TryGetAverageVelocity(state, out var velocity)
  50. ? velocity.y
  51. : float.NaN);
  52. AddCalculateThresholdsFunctionPerAxis(menu, "From Velocity Z",
  53. (state, threshold) => AnimancerUtilities.TryGetAverageVelocity(state, out var velocity)
  54. ? velocity.z
  55. : float.NaN);
  56. AddCalculateThresholdsFunctionPerAxis(menu, "From Angular Speed (Rad)",
  57. (state, threshold) => AnimancerUtilities.TryGetAverageAngularSpeed(state, out var speed)
  58. ? speed
  59. : float.NaN);
  60. AddCalculateThresholdsFunctionPerAxis(menu, "From Angular Speed (Deg)",
  61. (state, threshold) => AnimancerUtilities.TryGetAverageAngularSpeed(state, out var speed)
  62. ? speed * Mathf.Rad2Deg
  63. : float.NaN);
  64. AddPropertyModifierFunction(menu, "Initialize 4 Directions", Initialize4Directions);
  65. AddPropertyModifierFunction(menu, "Initialize 8 Directions", Initialize8Directions);
  66. }
  67. /************************************************************************************************************************/
  68. private void Initialize4Directions(SerializedProperty property)
  69. {
  70. var oldSpeedCount = CurrentSpeeds.arraySize;
  71. CurrentAnimations.arraySize = CurrentThresholds.arraySize = CurrentSpeeds.arraySize = 5;
  72. CurrentThresholds.GetArrayElementAtIndex(0).vector2Value = default;
  73. CurrentThresholds.GetArrayElementAtIndex(1).vector2Value = Vector2.up;
  74. CurrentThresholds.GetArrayElementAtIndex(2).vector2Value = Vector2.right;
  75. CurrentThresholds.GetArrayElementAtIndex(3).vector2Value = Vector2.down;
  76. CurrentThresholds.GetArrayElementAtIndex(4).vector2Value = Vector2.left;
  77. InitializeSpeeds(oldSpeedCount);
  78. var type = property.FindPropertyRelative(MixerTransition2D.TypeField);
  79. type.enumValueIndex = (int)MixerTransition2D.MixerType.Directional;
  80. }
  81. /************************************************************************************************************************/
  82. private void Initialize8Directions(SerializedProperty property)
  83. {
  84. var oldSpeedCount = CurrentSpeeds.arraySize;
  85. CurrentAnimations.arraySize = CurrentThresholds.arraySize = CurrentSpeeds.arraySize = 9;
  86. CurrentThresholds.GetArrayElementAtIndex(0).vector2Value = default;
  87. CurrentThresholds.GetArrayElementAtIndex(1).vector2Value = Vector2.up;
  88. CurrentThresholds.GetArrayElementAtIndex(2).vector2Value = new(1, 1);
  89. CurrentThresholds.GetArrayElementAtIndex(3).vector2Value = Vector2.right;
  90. CurrentThresholds.GetArrayElementAtIndex(4).vector2Value = new(1, -1);
  91. CurrentThresholds.GetArrayElementAtIndex(5).vector2Value = Vector2.down;
  92. CurrentThresholds.GetArrayElementAtIndex(6).vector2Value = new(-1, -1);
  93. CurrentThresholds.GetArrayElementAtIndex(7).vector2Value = Vector2.left;
  94. CurrentThresholds.GetArrayElementAtIndex(8).vector2Value = new(-1, 1);
  95. InitializeSpeeds(oldSpeedCount);
  96. var type = property.FindPropertyRelative(MixerTransition2D.TypeField);
  97. type.enumValueIndex = (int)MixerTransition2D.MixerType.Directional;
  98. }
  99. /************************************************************************************************************************/
  100. private void AddCalculateThresholdsFunction(
  101. GenericMenu menu,
  102. string label,
  103. Func<Object, Vector2, Vector2> calculateThreshold)
  104. {
  105. var functionState = CurrentAnimations == null || CurrentThresholds == null
  106. ? MenuFunctionState.Disabled
  107. : MenuFunctionState.Normal;
  108. AddPropertyModifierFunction(menu, label, functionState, property =>
  109. {
  110. GatherSubProperties(property);
  111. if (CurrentAnimations == null ||
  112. CurrentThresholds == null)
  113. return;
  114. var count = CurrentAnimations.arraySize;
  115. for (int i = 0; i < count; i++)
  116. {
  117. var state = CurrentAnimations.GetArrayElementAtIndex(i).objectReferenceValue;
  118. if (state == null)
  119. continue;
  120. var threshold = CurrentThresholds.GetArrayElementAtIndex(i);
  121. var value = calculateThreshold(state, threshold.vector2Value);
  122. if (!AnimancerEditorUtilities.IsNaN(value))
  123. threshold.vector2Value = value;
  124. }
  125. });
  126. }
  127. /************************************************************************************************************************/
  128. private void AddCalculateThresholdsFunctionPerAxis(GenericMenu menu, string label,
  129. Func<Object, float, float> calculateThreshold)
  130. {
  131. AddCalculateThresholdsFunction(menu, "X/" + label, 0, calculateThreshold);
  132. AddCalculateThresholdsFunction(menu, "Y/" + label, 1, calculateThreshold);
  133. }
  134. private void AddCalculateThresholdsFunction(GenericMenu menu, string label, int axis,
  135. Func<Object, float, float> calculateThreshold)
  136. {
  137. AddPropertyModifierFunction(menu, label, (property) =>
  138. {
  139. var count = CurrentAnimations.arraySize;
  140. for (int i = 0; i < count; i++)
  141. {
  142. var state = CurrentAnimations.GetArrayElementAtIndex(i).objectReferenceValue;
  143. if (state == null)
  144. continue;
  145. var threshold = CurrentThresholds.GetArrayElementAtIndex(i);
  146. var value = threshold.vector2Value;
  147. var newValue = calculateThreshold(state, value[axis]);
  148. if (!float.IsNaN(newValue))
  149. value[axis] = newValue;
  150. threshold.vector2Value = value;
  151. }
  152. });
  153. }
  154. /************************************************************************************************************************/
  155. }
  156. }
  157. #endif