// Animancer // https://kybernetik.com.au/animancer // Copyright 2018-2024 Kybernetik //
using System.Collections.Generic;
using System.Text;
using UnityEngine;
namespace Animancer
{
/// [Pro-Only]
/// An which blends an array of other states together
/// based on a two dimensional parameter and thresholds.
///
///
/// Documentation:
///
/// Mixers
///
/// https://kybernetik.com.au/animancer/api/Animancer/Vector2MixerState
///
public abstract class Vector2MixerState : MixerState,
ICopyable
{
/************************************************************************************************************************/
/// .x.
public float ParameterX
{
get => Parameter.x;
set => Parameter = new(value, Parameter.y);
}
/// .y.
public float ParameterY
{
get => Parameter.y;
set => Parameter = new(Parameter.x, value);
}
/************************************************************************************************************************/
#region Parameter Binding
/************************************************************************************************************************/
private NodeParameter _ParameterBindingX;
///
/// If set, this will be used as a key in the so any
/// changes to that parameter will automatically set the .
///
public StringReference ParameterNameX
{
get => _ParameterBindingX.Key;
set
{
if (_ParameterBindingX.SetKeyCheckNeedsInitialize(value))
_ParameterBindingX.Initialize(this, parameter => ParameterX = parameter);
}
}
/************************************************************************************************************************/
private NodeParameter _ParameterBindingY;
///
/// If set, this will be used as a key in the so any
/// changes to that parameter will automatically set the .
///
public StringReference ParameterNameY
{
get => _ParameterBindingY.Key;
set
{
if (_ParameterBindingY.SetKeyCheckNeedsInitialize(value))
_ParameterBindingY.Initialize(this, parameter => ParameterY = parameter);
}
}
/************************************************************************************************************************/
///
public override void SetGraph(AnimancerGraph graph)
{
if (Graph == graph)
return;
_ParameterBindingX.UnBindIfInitialized();
_ParameterBindingY.UnBindIfInitialized();
base.SetGraph(graph);
_ParameterBindingX.BindIfInitialized();
_ParameterBindingY.BindIfInitialized();
}
/************************************************************************************************************************/
///
public override void Destroy()
{
base.Destroy();
_ParameterBindingX.UnBindIfInitialized();
_ParameterBindingY.UnBindIfInitialized();
}
/************************************************************************************************************************/
///
public sealed override void CopyFrom(MixerState copyFrom, CloneContext context)
=> this.CopyFromBase(copyFrom, context);
///
public virtual void CopyFrom(Vector2MixerState copyFrom, CloneContext context)
{
base.CopyFrom(copyFrom, context);
ParameterNameX = copyFrom.ParameterNameX;
ParameterNameY = copyFrom.ParameterNameY;
}
/************************************************************************************************************************/
#endregion
/************************************************************************************************************************/
/// Gets the lowest and highest threshold values on each axis.
public void GetThresholdBounds(out Vector2 min, out Vector2 max)
{
var i = ChildCount - 1;
min = max = GetThreshold(i);
i--;
for (; i >= 0; i--)
{
var threshold = GetThreshold(i);
if (min.x > threshold.x)
min.x = threshold.x;
if (min.y > threshold.y)
min.y = threshold.y;
if (max.x < threshold.x)
max.x = threshold.x;
if (max.y < threshold.y)
max.y = threshold.y;
}
}
///
public override Vector2 NormalizedParameter
{
get
{
GetThresholdBounds(out var min, out var max);
var value = Parameter;
return new(
AnimancerUtilities.InverseLerpUnclamped(min.x, max.x, value.x),
AnimancerUtilities.InverseLerpUnclamped(min.y, max.y, value.y));
}
set
{
GetThresholdBounds(out var min, out var max);
Parameter = new(
Mathf.LerpUnclamped(min.x, max.x, value.x),
Mathf.LerpUnclamped(min.y, max.y, value.y));
}
}
/************************************************************************************************************************/
///
public override string GetParameterError(Vector2 value)
=> value.IsFinite()
? null
: $"value.x and value.y {Strings.MustBeFinite}";
/************************************************************************************************************************/
///
public override void AppendParameter(StringBuilder text, Vector2 parameter)
{
text.Append('(')
.Append(parameter.x)
.Append(", ")
.Append(parameter.y)
.Append(')');
}
/************************************************************************************************************************/
#region Inspector
/************************************************************************************************************************/
///
public override void GetParameters(List parameters)
{
parameters.Add(new(
"Parameter X",
ParameterNameX,
AnimatorControllerParameterType.Float,
ParameterX));
parameters.Add(new(
"Parameter Y",
ParameterNameY,
AnimatorControllerParameterType.Float,
ParameterY));
}
///
public override void SetParameters(List parameters)
{
var parameter = parameters[0];
ParameterNameX = parameter.name;
ParameterX = (float)parameter.value;
parameter = parameters[1];
ParameterNameY = parameter.name;
ParameterY = (float)parameter.value;
}
/************************************************************************************************************************/
#endregion
/************************************************************************************************************************/
}
}