using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.Events;
using UnityEngine.EventSystems;
namespace Rokid.MRC
{
//基类
public abstract class Tweener : MonoBehaviour
{
static public Tweener current;
public enum Direction
{
eReverse = -1,
eToggle = 0,
eForward = 1
}
public enum Trigger
{
eOnPointerEnter,
eOnPointerDown,
eOnPointerClick,
eOnPointerUp,
eOnPointerExit,
None
}
public enum ShakeType
{
ePosition,
eScale,
eRotation
}
public iTween.EaseType method = iTween.EaseType.linear;
public iTween.LoopType style = iTween.LoopType.none;
public AnimationCurve animationCurve = new AnimationCurve(new Keyframe(0f, 0f, 0f, 1f), new Keyframe(1f, 1f, 1f, 0f));
public bool ignoreTimeScale = true;
public float delay = 0f;
public float duration = 1f;
public float fixedDelta = 0f;
public int tweenGroup = 0;
private UnityAction onFinished = null;
private UnityAction onValueChange = null;
//[HideInInspector]
//protected GameObject eventReceiver;
//[HideInInspector]
//protected string callWhenFinished;
private bool mStarted = false;
private float mStartTime = 0f;
private float mDuration = 0f;
private float mAmountPerDelta = 1000f;
private float mFactor = 0f;
public bool currentDirection
{
get
{
return mFactor > 0;
}
}
///
/// Amount advanced per delta time.
///
protected float amountPerDelta
{
get
{
if(mDuration != duration)
{
mDuration = duration;
mAmountPerDelta = Mathf.Abs((duration > 0f) ? 1f / duration : 1000f) * Mathf.Sign(mAmountPerDelta);
}
return mAmountPerDelta;
}
}
protected void Reset()
{
if(!mStarted)
{
SetStartToCurrentValue();
SetEndToCurrentValue();
}
}
protected virtual void Start()
{
Update();
}
//实时进行缓动
void Update()
{
float delta = ignoreTimeScale ? Time.unscaledDeltaTime : Time.deltaTime;
float time = ignoreTimeScale ? Time.unscaledTime : Time.time;
if(fixedDelta > float.Epsilon)
{
delta = fixedDelta;
}
if(!mStarted)
{
mStarted = true;
mStartTime = time + delay;
}
if(time < mStartTime)
return;
// Advance the sampling factor
mFactor += amountPerDelta * delta;
// Loop style simply resets the play factor after it exceeds 1.
if(style == iTween.LoopType.loop)
{
if(mFactor > 1f)
{
mFactor -= Mathf.Floor(mFactor);
}
}
else if(style == iTween.LoopType.pingPong)
{
// Ping-pong style reverses the direction
if(mFactor > 1f)
{
mFactor = 1f - (mFactor - Mathf.Floor(mFactor));
mAmountPerDelta = -mAmountPerDelta;
}
else if(mFactor < 0f)
{
mFactor = -mFactor;
mFactor -= Mathf.Floor(mFactor);
mAmountPerDelta = -mAmountPerDelta;
}
}
// If the factor goes out of range and this is a one-time tweening operation, disable the script
if((style == iTween.LoopType.none) && (duration == 0f || mFactor > 1f || mFactor < 0f))
{
mFactor = Mathf.Clamp01(mFactor);
Sample(mFactor, true);
enabled = false;
if(current != this)
{
Tweener before = current;
current = this;
if(onFinished != null)
onFinished();
// Deprecated legacy functionality support
//if (eventReceiver != null && !string.IsNullOrEmpty(callWhenFinished))
// eventReceiver.SendMessage(callWhenFinished, this, SendMessageOptions.DontRequireReceiver);
current = before;
}
}
else
Sample(mFactor, false);
}
public void SetOnFinished(UnityAction finishedCallBack)
{
onFinished = finishedCallBack;
}
public void AddOnFinished(UnityAction finishedCallBack)
{
onFinished += finishedCallBack;
}
public void RemoveOnFinished(UnityAction finishedCallBack)
{
if(onFinished != null)
onFinished -= finishedCallBack;
}
void OnDisable()
{
mStarted = false;
}
///
/// Sample the tween at the specified factor.
///
protected void Sample(float factor, bool isFinished)
{
// Calculate the sampling value
float val = Mathf.Clamp01(factor);
val = (method == iTween.EaseType.None) ? animationCurve.Evaluate(val) : iTween.easeValue(method, 0, 1, val);
// Call the virtual update
OnUpdate((method == iTween.EaseType.None) ? animationCurve.Evaluate(val) : val, isFinished);
if(onValueChange != null)
{
onValueChange.Invoke();
}
}
///
/// Manually activate the tweening process, reversing it if necessary.
/// true Play the tween forward.
/// false Play the tween in reverse.
///
public void Play(bool forward)
{
mAmountPerDelta = Mathf.Abs(amountPerDelta);
if(!forward)
mAmountPerDelta = -mAmountPerDelta;
enabled = true;
Update();
}
///
/// Manually reset the tweener's state to the beginning.
/// If the tween is playing forward, this means the tween's start.
/// If the tween is playing in reverse, this means the tween's end.
///
public void ResetToBeginning()
{
mStarted = false;
mFactor = (amountPerDelta < 0f) ? 1f : 0f;
Sample(mFactor, false);
}
///
/// Manually start the tweening process, reversing its direction.
///
public void Toggle()
{
if(mFactor > 0f)
{
mAmountPerDelta = -amountPerDelta;
}
else
{
mAmountPerDelta = Mathf.Abs(amountPerDelta);
}
enabled = true;
}
///
/// Actual tweening logic should go here.
///
abstract protected void OnUpdate(float factor, bool isFinished);
///
/// Starts the tweening operation.
///
static protected T Begin(GameObject go, float duration) where T : Tweener
{
T comp = go.GetComponent();
#if UNITY_FLASH
if ((object)comp == null) comp = (T)go.AddComponent();
#else
// Find the tween with an unset group ID (group ID of 0).
if(comp != null && comp.tweenGroup != 0)
{
comp = null;
T[] comps = go.GetComponents();
for(int i = 0, imax = comps.Length;i < imax;++i)
{
comp = comps[i];
if(comp != null && comp.tweenGroup == 0)
break;
comp = null;
}
}
if(comp == null)
{
comp = go.AddComponent();
if(comp == null)
{
Debug.LogError("Unable to add " + typeof(T) + " to " + go);
return null;
}
}
#endif
comp.mStarted = false;
comp.duration = duration;
comp.mFactor = 0f;
comp.mAmountPerDelta = Mathf.Abs(comp.amountPerDelta);
comp.style = iTween.LoopType.none;
comp.animationCurve = new AnimationCurve(new Keyframe(0f, 0f, 0f, 1f), new Keyframe(1f, 1f, 1f, 0f));
//comp.eventReceiver = null;
//comp.callWhenFinished = null;
comp.onFinished = null;
comp.enabled = true;
return comp;
}
protected virtual void SetStartToCurrentValue()
{
}
protected virtual void SetEndToCurrentValue()
{
}
protected virtual void SetCurrentValueToStart()
{
}
protected virtual void SetCurrentValueToEnd()
{
}
}
}