// Animancer // https://kybernetik.com.au/animancer // Copyright 2018-2023 Kybernetik //
using System;
using UnityEngine;
using Object = UnityEngine.Object;
#if UNITY_EDITOR
using UnityEditor;
#endif
namespace Animancer
{
///
/// https://kybernetik.com.au/animancer/api/Animancer/MixerTransition2DAsset
#if !UNITY_EDITOR
[System.Obsolete(Validate.ProOnlyMessage)]
#endif
[CreateAssetMenu(menuName = Strings.MenuPrefix + "Mixer Transition/2D", order = Strings.AssetMenuOrder + 4)]
[HelpURL(Strings.DocsURLs.APIDocumentation + "/" + nameof(MixerTransition2DAsset))]
public class MixerTransition2DAsset : AnimancerTransitionAsset
{
///
[Serializable]
public new class UnShared :
UnShared>,
ManualMixerState.ITransition2D
{ }
}
///
/// https://kybernetik.com.au/animancer/api/Animancer/MixerTransition2D
[Serializable]
#if ! UNITY_EDITOR
[System.Obsolete(Validate.ProOnlyMessage)]
#endif
public class MixerTransition2D : MixerTransition, Vector2>,
ManualMixerState.ITransition2D, ICopyable
{
/************************************************************************************************************************/
/// A type of that can be created by a .
public enum MixerType
{
///
Cartesian,
///
Directional,
}
[SerializeField]
private MixerType _Type;
/// []
/// The type of that this transition will create.
///
public ref MixerType Type => ref _Type;
/************************************************************************************************************************/
///
/// Creates and returns a new or
/// depending on the .
///
///
/// Note that using methods like will also call
/// , so if you call this method manually you may want to call that method
/// as well. Or you can just use .
///
/// This method also assigns it as the .
///
public override MixerState CreateState()
{
switch (_Type)
{
case MixerType.Cartesian: State = new CartesianMixerState(); break;
case MixerType.Directional: State = new DirectionalMixerState(); break;
default: throw new ArgumentOutOfRangeException(nameof(_Type));
}
InitializeState();
return State;
}
/************************************************************************************************************************/
///
public virtual void CopyFrom(MixerTransition2D copyFrom)
{
CopyFrom((MixerTransition, Vector2>)copyFrom);
if (copyFrom == null)
{
_Type = default;
return;
}
_Type = copyFrom._Type;
}
/************************************************************************************************************************/
#region Drawer
#if UNITY_EDITOR
/************************************************************************************************************************/
///
[CustomPropertyDrawer(typeof(MixerTransition2D), true)]
public class Drawer : MixerTransitionDrawer
{
/************************************************************************************************************************/
///
/// Creates a new using the a wider `thresholdWidth` than usual to accomodate
/// both the X and Y values.
///
public Drawer() : base(StandardThresholdWidth * 2 + 20) { }
/************************************************************************************************************************/
#region Threshold Calculation Functions
/************************************************************************************************************************/
///
protected override void AddThresholdFunctionsToMenu(GenericMenu menu)
{
AddCalculateThresholdsFunction(menu, "From Velocity/XY", (state, threshold) =>
{
if (AnimancerUtilities.TryGetAverageVelocity(state, out var velocity))
return new Vector2(velocity.x, velocity.y);
else
return new Vector2(float.NaN, float.NaN);
});
AddCalculateThresholdsFunction(menu, "From Velocity/XZ", (state, threshold) =>
{
if (AnimancerUtilities.TryGetAverageVelocity(state, out var velocity))
return new Vector2(velocity.x, velocity.z);
else
return new Vector2(float.NaN, float.NaN);
});
AddCalculateThresholdsFunctionPerAxis(menu, "From Speed",
(state, threshold) => AnimancerUtilities.TryGetAverageVelocity(state, out var velocity) ? velocity.magnitude : float.NaN);
AddCalculateThresholdsFunctionPerAxis(menu, "From Velocity X",
(state, threshold) => AnimancerUtilities.TryGetAverageVelocity(state, out var velocity) ? velocity.x : float.NaN);
AddCalculateThresholdsFunctionPerAxis(menu, "From Velocity Y",
(state, threshold) => AnimancerUtilities.TryGetAverageVelocity(state, out var velocity) ? velocity.y : float.NaN);
AddCalculateThresholdsFunctionPerAxis(menu, "From Velocity Z",
(state, threshold) => AnimancerUtilities.TryGetAverageVelocity(state, out var velocity) ? velocity.z : float.NaN);
AddCalculateThresholdsFunctionPerAxis(menu, "From Angular Speed (Rad)",
(state, threshold) => AnimancerUtilities.TryGetAverageAngularSpeed(state, out var speed) ? speed : float.NaN);
AddCalculateThresholdsFunctionPerAxis(menu, "From Angular Speed (Deg)",
(state, threshold) => AnimancerUtilities.TryGetAverageAngularSpeed(state, out var speed) ? speed * Mathf.Rad2Deg : float.NaN);
AddPropertyModifierFunction(menu, "Initialize 4 Directions", Initialize4Directions);
AddPropertyModifierFunction(menu, "Initialize 8 Directions", Initialize8Directions);
}
/************************************************************************************************************************/
private void Initialize4Directions(SerializedProperty property)
{
var oldSpeedCount = CurrentSpeeds.arraySize;
CurrentAnimations.arraySize = CurrentThresholds.arraySize = CurrentSpeeds.arraySize = 5;
CurrentThresholds.GetArrayElementAtIndex(0).vector2Value = default;
CurrentThresholds.GetArrayElementAtIndex(1).vector2Value = Vector2.up;
CurrentThresholds.GetArrayElementAtIndex(2).vector2Value = Vector2.right;
CurrentThresholds.GetArrayElementAtIndex(3).vector2Value = Vector2.down;
CurrentThresholds.GetArrayElementAtIndex(4).vector2Value = Vector2.left;
InitializeSpeeds(oldSpeedCount);
var type = property.FindPropertyRelative(nameof(_Type));
type.enumValueIndex = (int)MixerType.Directional;
}
/************************************************************************************************************************/
private void Initialize8Directions(SerializedProperty property)
{
var oldSpeedCount = CurrentSpeeds.arraySize;
CurrentAnimations.arraySize = CurrentThresholds.arraySize = CurrentSpeeds.arraySize = 9;
CurrentThresholds.GetArrayElementAtIndex(0).vector2Value = default;
CurrentThresholds.GetArrayElementAtIndex(1).vector2Value = Vector2.up;
CurrentThresholds.GetArrayElementAtIndex(2).vector2Value = new Vector2(1, 1);
CurrentThresholds.GetArrayElementAtIndex(3).vector2Value = Vector2.right;
CurrentThresholds.GetArrayElementAtIndex(4).vector2Value = new Vector2(1, -1);
CurrentThresholds.GetArrayElementAtIndex(5).vector2Value = Vector2.down;
CurrentThresholds.GetArrayElementAtIndex(6).vector2Value = new Vector2(-1, -1);
CurrentThresholds.GetArrayElementAtIndex(7).vector2Value = Vector2.left;
CurrentThresholds.GetArrayElementAtIndex(8).vector2Value = new Vector2(-1, 1);
InitializeSpeeds(oldSpeedCount);
var type = property.FindPropertyRelative(nameof(_Type));
type.enumValueIndex = (int)MixerType.Directional;
}
/************************************************************************************************************************/
private void AddCalculateThresholdsFunction(GenericMenu menu, string label,
Func