Files
unity-iso-tools/Assets/PlayMaker/Actions/AnimateVariables/CurveFsmAction.cs
2015-12-13 14:35:35 +06:00

220 lines
8.4 KiB
C#
Executable File

// (c) Copyright HutongGames, LLC 2010-2013. All rights reserved.
using UnityEngine;
namespace HutongGames.PlayMaker.Actions
{
[Tooltip("Animate base action - DON'T USE IT!")]
public abstract class CurveFsmAction : FsmStateAction
{
[Tooltip("Define time to use your curve scaled to be stretched or shrinked.")]
public FsmFloat time;
[Tooltip("If you define speed, your animation will be speeded up or slowed down.")]
public FsmFloat speed;
[Tooltip("Delayed animimation 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;
private float[] distances;
protected bool finishAction = false;
protected bool isRunning;
protected bool looping;
private bool start = false;
private float largestEndTime = 0f;
public enum Calculation{
None,
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];
distances = 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;
}
}
}
distances = new float[fromFloats.Length];
for(int i = 0; i<fromFloats.Length; i++){
distances[i] = toFloats[i] - fromFloats[i];
}
}
public override void OnUpdate()
{
// update time
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;
startTime = FsmTime.RealtimeSinceStartup;
lastTime = FsmTime.RealtimeSinceStartup - startTime;
}
}
if(isRunning && !finishAction){
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;
}
// update animation
for(var k = 0; k<curves.Length;k++){
if (curves[k] != null && curves[k].keys.Length > 0)
{
if(calculations[k] != CurveFsmAction.Calculation.None){
switch(calculations[k]){
case Calculation.AddToValue:
if(!time.IsNone) resultFloats[k] = fromFloats[k] + (distances[k]*(currentTime/time.Value) + curves[k].Evaluate((currentTime/time.Value)*curves[k].keys[curves[k].length-1].time));
else resultFloats[k] = fromFloats[k] + (distances[k]*(currentTime/endTimes[k]) + curves[k].Evaluate(currentTime));
break;
case Calculation.SubtractFromValue:
if(!time.IsNone) resultFloats[k] = fromFloats[k] + (distances[k]*(currentTime/time.Value) - curves[k].Evaluate((currentTime/time.Value)*curves[k].keys[curves[k].length-1].time));
else resultFloats[k] = fromFloats[k] + (distances[k]*(currentTime/endTimes[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) - distances[k]*(currentTime/time.Value)) + fromFloats[k];
else resultFloats[k] = (curves[k].Evaluate(currentTime) - distances[k]*(currentTime/endTimes[k])) + 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) * distances[k]*(currentTime/time.Value)) + fromFloats[k];
else resultFloats[k] = (curves[k].Evaluate(currentTime) * distances[k]*(currentTime/endTimes[k])) + 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]+ (distances[k]*(currentTime/time.Value))/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] + (distances[k]*(currentTime/endTimes[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)/(distances[k]*(currentTime/time.Value)) + fromFloats[k] : float.MaxValue;
else resultFloats[k] = fromFloats[k] != 0
? curves[k].Evaluate(currentTime)/(distances[k]*(currentTime/endTimes[k])) + fromFloats[k] : float.MaxValue;
break;
}
} else {
//Linear interpolation between color components
if(!time.IsNone) resultFloats[k] = (fromFloats[k] + distances[k]*(currentTime/time.Value));
else resultFloats[k] = (fromFloats[k] + distances[k]*(currentTime/endTimes[k]));
}
} else {
if(!time.IsNone) resultFloats[k] = (fromFloats[k] + distances[k]*(currentTime/time.Value));
else {
if(largestEndTime == 0f){
resultFloats[k] = (fromFloats[k] + distances[k]*(currentTime/1f));
} else {
resultFloats[k] = (fromFloats[k] + distances[k]*(currentTime/largestEndTime));
}
}
}
}
if(isRunning) {
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;
}
}
}
}
}