using UnityEngine;
using UnityEngine.Events;
using FSA = UnityEngine.Serialization.FormerlySerializedAsAttribute;
namespace Lean.Common
{
/// This component allows you to smooth a value that is sent to a component. This is done by first passing the value to this component using one of the SetX/Y/Z methods, and then sending it out after smoothing using the OnValueX/Y/Z events.
[HelpURL(LeanHelper.PlusHelpUrlPrefix + "LeanSmoothedValue")]
[AddComponentMenu(LeanHelper.ComponentPathPrefix + "Smoothed Value")]
public class LeanSmoothedValue : MonoBehaviour
{
[System.Serializable] public class FloatEvent : UnityEvent {}
[System.Serializable] public class Vector2Event : UnityEvent {}
[System.Serializable] public class Vector3Event : UnityEvent {}
/// This allows you to control how quickly the target value is reached.
/// -1 = Instantly change.
/// 1 = Slowly change.
/// 10 = Quickly change.
public float Damping { set { damping = value; } get { return damping; } } [FSA("Damping")] [SerializeField] private float damping = 10.0f;
/// Damping alone won't reach the target value. This setting allows you to force the value to move toward the target with linear interpolation.
public float Threshold { set { threshold = value; } get { return threshold; } } [FSA("Threshold")] [SerializeField] private float threshold = 0.1f;
/// If the target value has been reached, stop sending events?
public bool AutoStop { set { autoStop = value; } get { return autoStop; } } [FSA("AutoStop")] [SerializeField] private bool autoStop = true;
/// This event will send any previously set values after the specified delay.
public FloatEvent OnValueX { get { if (onValueX == null) onValueX = new FloatEvent(); return onValueX; } } [SerializeField] private FloatEvent onValueX;
/// This event will send any previously set values after the specified delay.
public FloatEvent OnValueY { get { if (onValueY == null) onValueY = new FloatEvent(); return onValueY; } } [SerializeField] private FloatEvent onValueY;
/// This event will send any previously set values after the specified delay.
public FloatEvent OnValueZ { get { if (onValueZ == null) onValueZ = new FloatEvent(); return onValueZ; } } [SerializeField] private FloatEvent onValueZ;
/// This event will send any previously set values after the specified delay.
public Vector2Event OnValueXY { get { if (onValueXY == null) onValueXY = new Vector2Event(); return onValueXY; } } [SerializeField] private Vector2Event onValueXY;
/// This event will send any previously set values after the specified delay.
public Vector3Event OnValueXYZ { get { if (onValueXYZ == null) onValueXYZ = new Vector3Event(); return onValueXYZ; } } [SerializeField] private Vector3Event onValueXYZ;
[SerializeField]
private Vector3 currentValue;
[SerializeField]
private Vector3 targetValue;
[SerializeField]
private bool targetSet;
/// This method allows you to set the X axis.
public void SetX(float value)
{
targetValue.x = value;
targetSet = true;
}
/// This method allows you to set the Y axis.
public void SetY(float value)
{
targetValue.y = value;
targetSet = true;
}
/// This method allows you to set the Z axis.
public void SetZ(float value)
{
targetValue.z = value;
targetSet = true;
}
/// This method allows you to set the XY axis.
public void SetXY(Vector2 value)
{
targetValue.x = value.x;
targetValue.y = value.y;
targetSet = true;
}
/// This method allows you to set the XYZ axis.
public void SetXYZ(Vector3 value)
{
targetValue = value;
targetSet = true;
}
/// This method will immediately snap the current value to the target value.
public void SnapToTarget()
{
currentValue = targetValue;
}
/// This method will reset the target value and stop sending any events.
public void Stop()
{
targetValue = Vector3.zero;
targetSet = false;
}
protected virtual void Update()
{
if (targetSet == true)
{
var factor = LeanHelper.GetDampenFactor(damping, Time.deltaTime);
currentValue = Vector3.Lerp(currentValue, targetValue, factor);
currentValue = Vector3.MoveTowards(currentValue, targetValue, threshold * Time.deltaTime);
Submit(currentValue);
if (autoStop == true && Vector3.SqrMagnitude(currentValue - targetValue) == 0.0f)
{
Stop();
}
}
}
private void Submit(Vector3 value)
{
if (onValueX != null)
{
onValueX.Invoke(value.x);
}
if (onValueY != null)
{
onValueY.Invoke(value.y);
}
if (onValueZ != null)
{
onValueZ.Invoke(value.z);
}
if (onValueXY != null)
{
onValueXY.Invoke(value);
}
if (onValueXYZ != null)
{
onValueXYZ.Invoke(value);
}
}
}
}
#if UNITY_EDITOR
namespace Lean.Common.Editor
{
using TARGET = LeanSmoothedValue;
[UnityEditor.CanEditMultipleObjects]
[UnityEditor.CustomEditor(typeof(TARGET))]
public class LeanSmoothedValue_Editor : LeanEditor
{
protected override void OnInspector()
{
TARGET tgt; TARGET[] tgts; GetTargets(out tgt, out tgts);
Draw("damping", "This allows you to control how quickly the target value is reached.");
Draw("threshold", "Damping alone won't reach the target value. This setting allows you to force the value to move toward the target with linear interpolation.");
Draw("autoStop", "If the target value has been reached, stop sending events?");
Separator();
var usedA = Any(tgts, t => t.OnValueX.GetPersistentEventCount() > 0);
var usedB = Any(tgts, t => t.OnValueY.GetPersistentEventCount() > 0);
var usedC = Any(tgts, t => t.OnValueZ.GetPersistentEventCount() > 0);
var usedD = Any(tgts, t => t.OnValueXY.GetPersistentEventCount() > 0);
var usedE = Any(tgts, t => t.OnValueXYZ.GetPersistentEventCount() > 0);
var showUnusedEvents = DrawFoldout("Show Unused Events", "Show all events?");
if (usedA == true || showUnusedEvents == true)
{
Draw("onValueX");
}
if (usedB == true || showUnusedEvents == true)
{
Draw("onValueY");
}
if (usedC == true || showUnusedEvents == true)
{
Draw("onValueZ");
}
if (usedD == true || showUnusedEvents == true)
{
Draw("onValueXY");
}
if (usedE == true || showUnusedEvents == true)
{
Draw("onValueXYZ");
}
}
}
}
#endif