Files
bansonic_beta_main/Assets/SmoothShakeFree/Data/ShakeBase.cs
T

208 lines
7.0 KiB
C#

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace SmoothShakeFree
{
public abstract class ShakeBase : MonoBehaviour
{
[Header("Time Settings")]
[Tooltip("Settings for the shake timing")]
public TimeSettings timeSettings;
private bool willStop = false;
[HideInInspector] public Shaker[] shakers;
#if UNITY_2020
[HideInInspector] public readonly List<Coroutine> activeShakeRoutines = new List<Coroutine>();
#else
[HideInInspector] public readonly List<Coroutine> activeShakeRoutines = new();
#endif
[HideInInspector] public Coroutine clearAfterFinished;
[HideInInspector] public Vector3[] sum;
internal void Awake()
{
shakers = GetShakers();
sum = new Vector3[shakers.Length];
if (timeSettings.enableOnStart) StartShake();
}
internal void Start()
{
if (timeSettings.enableOnStart) StartShake();
}
public virtual void StartShake()
{
willStop = false;
if (activeShakeRoutines.Count == 0)
{
clearAfterFinished = StartCoroutine(ClearAfterFinished());
SaveDefaultValues();
for (int i = 0; i < shakers.Length; i++)
{
activeShakeRoutines.Add(StartCoroutine(ShakeRoutine(shakers[i], timeSettings, i)));
}
}
else
{
ForceStop();
StartShake();
}
}
public void StartShake(SmoothShakeFreePreset preset)
{
ApplyPresetSettings(preset);
StartShake();
}
public void StopShake() => willStop = true;
public void ForceStop()
{
for (int i = 0; i < activeShakeRoutines.Count; i++)
{
if (activeShakeRoutines[i] != null)
{
StopCoroutine(activeShakeRoutines[i]);
activeShakeRoutines[i] = null;
}
}
if (clearAfterFinished != null)
{
StopCoroutine(clearAfterFinished);
clearAfterFinished = null;
}
for (int i = 0; i < sum.Length; i++)
{
sum[i] = Vector3.zero;
}
activeShakeRoutines.Clear();
ResetDefaultValues();
willStop = false;
}
protected IEnumerator ClearAfterFinished()
{
if (timeSettings.constantShake)
{
while (true)
{
if (willStop) break;
yield return null;
}
yield return new WaitForSeconds(timeSettings.fadeOutDuration);
ForceStop();
}
else
{
yield return new WaitForSeconds(timeSettings.GetShakeDuration());
ForceStop();
}
}
protected IEnumerator ShakeRoutine(Shaker shaker, TimeSettings timeSettings, int i)
{
bool isFadingOut = false;
if (timeSettings.fadeInDuration > 0) { yield return FadeRoutine(this.timeSettings.fadeInCurve, shaker, timeSettings, isFadingOut, i); }
if (timeSettings.holdDuration > 0 && !this.timeSettings.constantShake) { yield return HoldRoutine(timeSettings.holdDuration, shaker, timeSettings, i); }
if (this.timeSettings.constantShake) { yield return HoldRoutine(Mathf.Infinity, shaker, timeSettings, i); }
isFadingOut = true;
if (timeSettings.fadeOutDuration > 0) { yield return FadeRoutine(this.timeSettings.fadeOutCurve, shaker, timeSettings, isFadingOut, i); }
}
private IEnumerator FadeRoutine(AnimationCurve curve, Shaker shaker, TimeSettings timeSettings, bool isFadingOut, int i)
{
//Don't play the fade routine if the curve has no keys
if (curve.length <= 1) yield break;
if (isFadingOut && timeSettings.holdDuration == 0 && timeSettings.fadeInDuration == 0) timeSettings.fadeValue = 1;
Keyframe[] keys = curve.keys;
float tEnd = isFadingOut ? timeSettings.fadeOutDuration : timeSettings.fadeInDuration;
float t = 0;
while (t < tEnd)
{
if (!isFadingOut && willStop) yield break;
#if UNITY_2020
float remappedTime = Utility.Remap(t, 0, tEnd, keys[0].time, keys[keys.Length - 1].time);
#else
float remappedTime = Utility.Remap(t, 0, tEnd, keys[0].time, keys[^1].time);
#endif
//timeSettings.fadeValue = Utility.Remap(curve.Evaluate(remappedTime), keys[0].value, keys[^1].value, isFadingOut ? 1 : 0, isFadingOut ? 0 : 1);
timeSettings.fadeValue = curve.Evaluate(remappedTime);
Execute(shaker, timeSettings, i);
yield return null;
t += Time.deltaTime;
}
#if UNITY_2020
timeSettings.fadeValue = Utility.Remap(curve.Evaluate(keys[keys.Length - 1].time), keys[0].value, keys[keys.Length - 1].value, isFadingOut ? 1 : 0, isFadingOut ? 0 : 1);
#else
timeSettings.fadeValue = Utility.Remap(curve.Evaluate(keys[^1].time), keys[0].value, keys[^1].value, isFadingOut ? 1 : 0, isFadingOut ? 0 : 1);
#endif
Execute(shaker, timeSettings, i);
}
private IEnumerator HoldRoutine(float duration, Shaker shaker, TimeSettings timeSettings, int i)
{
if (timeSettings.fadeValue == 0) timeSettings.fadeValue = 1;
float t = 0;
// Check if the duration is infinite
if (float.IsInfinity(duration))
{
while (true) // Infinite loop
{
if (willStop) yield break;
Execute(shaker, timeSettings, i);
yield return null;
}
}
else
{
while (t < duration)
{
if (willStop) yield break;
Execute(shaker, timeSettings, i);
yield return null;
t += Time.deltaTime;
}
}
if (timeSettings.fadeOutDuration == 0)
{
timeSettings.fadeValue = 0;
Execute(shaker, timeSettings, i);
}
}
protected virtual void Execute(Shaker shaker, TimeSettings timeSettings, int i)
{
sum[i] = shaker.Evaluate(Time.time) * timeSettings.fadeValue;
}
protected virtual void ApplySum() => Apply(sum);
private void Update() { if (activeShakeRoutines.Count > 0) ApplySum(); }
internal abstract void Apply(Vector3[] value);
protected abstract Shaker[] GetShakers();
internal abstract void SaveDefaultValues();
internal abstract void ResetDefaultValues();
internal abstract void ApplyPresetSettings(SmoothShakeFreePreset preset);
}
}