Files
2024-11-20 15:21:28 +01:00

299 lines
10 KiB
C#
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// (c) Copyright HutongGames, LLC 2010-2013. All rights reserved.
using UnityEngine;
namespace HutongGames.PlayMaker.Actions
{
/// <summary>
/// Base action for AnimateXXX actions
/// </summary>
public abstract class AnimateFsmAction : FsmStateAction
{
[Tooltip("Define animation time, scaling the curve to fit.")]
public FsmFloat time;
[Tooltip("If you define speed, your animation will speed up or slow down.")]
public FsmFloat speed;
[Tooltip("Delayed animation start.")]
public FsmFloat delay;
[Tooltip("Animation curve start from any time. If IgnoreCurveOffset is true the animation starts right after the state become entered.")]
public FsmBool ignoreCurveOffset;
[Tooltip("Optionally send an Event when the animation finishes.")]
public FsmEvent finishEvent;
[Tooltip("Ignore TimeScale. Useful if the game is paused.")]
public bool realTime;
private float startTime;
private float currentTime;
private float[] endTimes;
private float lastTime;
private float deltaTime;
private float delayTime;
private float[] keyOffsets;
protected AnimationCurve[] curves;
protected Calculation[] calculations;
protected float[] resultFloats;
protected float[] fromFloats;
protected float[] toFloats;
protected bool finishAction = false;
protected bool isRunning;
protected bool looping;
private bool start = false;
private float largestEndTime = 0f;
public enum Calculation{
None,
SetValue,
AddToValue,
SubtractFromValue,
SubtractValueFromCurve,
MultiplyValue,
DivideValue,
DivideCurveByValue,
}
public override void Reset()
{
finishEvent = null;
realTime = false;
time = new FsmFloat { UseVariable = true };
speed = new FsmFloat { UseVariable = true };
delay = new FsmFloat { UseVariable = true };
ignoreCurveOffset = new FsmBool{ Value = true};
resultFloats = new float[0];
fromFloats = new float[0];
toFloats = new float[0];
endTimes = new float[0];
keyOffsets = new float[0];
curves = new AnimationCurve[0];
finishAction = false;
start = false;
}
public override void OnEnter()
{
startTime = FsmTime.RealtimeSinceStartup;
lastTime = FsmTime.RealtimeSinceStartup - startTime;
deltaTime = 0f;
currentTime = 0f;
isRunning = false;
finishAction = false;
looping = false;
delayTime = delay.IsNone ? 0f : delayTime = delay.Value;
start = true;
}
protected void Init()
{
endTimes = new float[curves.Length];
keyOffsets = new float[curves.Length];
largestEndTime = 0f;
for(int i = 0; i<curves.Length;i++)
{
if (curves[i] != null && curves[i].keys.Length > 0)
{
keyOffsets[i] = curves[i].keys.Length > 0 ? (time.IsNone ? curves[i].keys[0].time : (time.Value/curves[i].keys[curves[i].length-1].time)*curves[i].keys[0].time) : 0f;
currentTime = ignoreCurveOffset.IsNone ? 0f : (ignoreCurveOffset.Value ? keyOffsets[i] : 0f);
if(!time.IsNone) endTimes[i] = time.Value;
else endTimes[i] = curves[i].keys[curves[i].length-1].time;
if(largestEndTime < endTimes[i]) largestEndTime = endTimes[i];
if(!looping) looping = ActionHelpers.IsLoopingWrapMode(curves[i].postWrapMode);
}
else
{
endTimes[i] = -1f;
}
}
for(int i = 0; i<curves.Length;i++)
{
if(largestEndTime > 0f && endTimes[i] == -1f) endTimes[i] = largestEndTime;
else {
if(largestEndTime == 0f && endTimes[i] == -1f)
{
if(time.IsNone) endTimes[i] = 1f;
else endTimes[i] = time.Value;
}
}
}
// set initial result value
UpdateAnimation();
}
public override void OnUpdate()
{
CheckStart();
if(isRunning)
{
UpdateTime();
UpdateAnimation();
CheckFinished();
}
}
private void CheckStart()
{
if (!isRunning && start)
{
if (delayTime >= 0)
{
if (realTime)
{
deltaTime = (FsmTime.RealtimeSinceStartup - startTime) - lastTime;
lastTime = FsmTime.RealtimeSinceStartup - startTime;
delayTime -= deltaTime;
}
else
{
delayTime -= Time.deltaTime;
}
}
else
{
isRunning = true;
start = false;
}
}
}
private void UpdateTime()
{
if (realTime)
{
deltaTime = (FsmTime.RealtimeSinceStartup - startTime) - lastTime;
lastTime = FsmTime.RealtimeSinceStartup - startTime;
if (!speed.IsNone) currentTime += deltaTime*speed.Value;
else currentTime += deltaTime;
}
else
{
if (!speed.IsNone) currentTime += Time.deltaTime*speed.Value;
else currentTime += Time.deltaTime;
}
}
public void UpdateAnimation()
{
for (var k = 0; k < curves.Length; k++)
{
if (curves[k] != null && curves[k].keys.Length > 0)
{
if (calculations[k] != AnimateFsmAction.Calculation.None)
{
switch (calculations[k])
{
case Calculation.SetValue:
if (!time.IsNone)
resultFloats[k] =
curves[k].Evaluate((currentTime/time.Value)*curves[k].keys[curves[k].length - 1].time);
else resultFloats[k] = curves[k].Evaluate(currentTime);
break;
case Calculation.AddToValue:
if (!time.IsNone)
resultFloats[k] = fromFloats[k] +
curves[k].Evaluate((currentTime/time.Value)*
curves[k].keys[curves[k].length - 1].time);
else resultFloats[k] = fromFloats[k] + curves[k].Evaluate(currentTime);
break;
case Calculation.SubtractFromValue:
if (!time.IsNone)
resultFloats[k] = fromFloats[k] -
curves[k].Evaluate((currentTime/time.Value)*
curves[k].keys[curves[k].length - 1].time);
else resultFloats[k] = fromFloats[k] - curves[k].Evaluate(currentTime);
break;
case Calculation.SubtractValueFromCurve:
if (!time.IsNone)
resultFloats[k] =
curves[k].Evaluate((currentTime/time.Value)*curves[k].keys[curves[k].length - 1].time) -
fromFloats[k];
else resultFloats[k] = curves[k].Evaluate(currentTime) - fromFloats[k];
break;
case Calculation.MultiplyValue:
if (!time.IsNone)
resultFloats[k] =
curves[k].Evaluate((currentTime/time.Value)*curves[k].keys[curves[k].length - 1].time)*
fromFloats[k];
else resultFloats[k] = curves[k].Evaluate(currentTime)*fromFloats[k];
break;
case Calculation.DivideValue:
if (!time.IsNone)
resultFloats[k] =
curves[k].Evaluate((currentTime/time.Value)*curves[k].keys[curves[k].length - 1].time) !=
0f
? fromFloats[k]/
curves[k].Evaluate((currentTime/time.Value)*
curves[k].keys[curves[k].length - 1].time)
: float.MaxValue;
else
resultFloats[k] = curves[k].Evaluate(currentTime) != 0
? fromFloats[k]/curves[k].Evaluate(currentTime)
: float.MaxValue;
break;
case Calculation.DivideCurveByValue:
if (!time.IsNone)
resultFloats[k] = fromFloats[k] != 0f
? curves[k].Evaluate((currentTime/time.Value)*curves[k].keys[curves[k].length - 1].time)/
fromFloats[k]
: float.MaxValue;
else
resultFloats[k] = fromFloats[k] != 0
? curves[k].Evaluate(currentTime)/fromFloats[k]
: float.MaxValue;
break;
}
}
else
{
resultFloats[k] = fromFloats[k];
}
}
else
{
resultFloats[k] = fromFloats[k];
}
}
}
private void CheckFinished()
{
if (isRunning && !looping)
{
finishAction = true;
for (int i = 0; i < endTimes.Length; i++)
{
//Debug.Log(i.ToString() + "| " +endTimes[i].ToString() + " " + currentTime.ToString());
if (currentTime < endTimes[i]) finishAction = false;
}
isRunning = !finishAction;
}
}
#if UNITY_EDITOR
public override float GetProgress()
{
float maxendtime = 0f;
for (int i = 0; i < endTimes.Length; i++)
{
maxendtime = Mathf.Max (maxendtime, endTimes [i]);
}
return Mathf.Min(currentTime/maxendtime , 1f);
}
#endif
}
}