299 lines
10 KiB
C#
299 lines
10 KiB
C#
// (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
|
||
}
|
||
} |