Files
tianrunCRM/Assets/CoolapeFrame/3rd/NGUI_Enhance/Scripts/Tweening/UITweener.cs
2020-07-04 14:41:25 +08:00

471 lines
11 KiB
C#

//----------------------------------------------
// NGUI: Next-Gen UI kit
// Copyright © 2011-2014 Tasharen Entertainment
//----------------------------------------------
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
/// <summary>
/// Base class for all tweening operations.
/// </summary>
public abstract class UITweener : MonoBehaviour
{
/// <summary>
/// Current tween that triggered the callback function.
/// </summary>
public int exeOrder = 0;
static public UITweener current;
public enum Method
{
Linear,
EaseIn,
EaseOut,
EaseInOut,
BounceIn,
BounceOut,
}
public enum Style
{
Once,
Loop,
PingPong,
}
/// <summary>
/// Tweening method used.
/// </summary>
[HideInInspector]
public Method method = Method.Linear;
/// <summary>
/// Does it play once? Does it loop?
/// </summary>
[HideInInspector]
public Style style = Style.Once;
/// <summary>
/// Optional curve to apply to the tween's time factor value.
/// </summary>
[HideInInspector]
public AnimationCurve animationCurve = new AnimationCurve (new Keyframe (0f, 0f, 0f, 1f), new Keyframe (1f, 1f, 1f, 0f));
/// <summary>
/// Whether the tween will ignore the timescale, making it work while the game is paused.
/// </summary>
[HideInInspector]
public bool ignoreTimeScale = true;
/// <summary>
/// How long will the tweener wait before starting the tween?
/// </summary>
[HideInInspector]
public float delay = 0f;
/// <summary>
/// How long is the duration of the tween?
/// </summary>
[HideInInspector]
public float duration = 1f;
/// <summary>
/// Whether the tweener will use steeper curves for ease in / out style interpolation.
/// </summary>
[HideInInspector]
public bool steeperCurves = false;
/// <summary>
/// Used by buttons and tween sequences. Group of '0' means not in a sequence.
/// </summary>
[HideInInspector]
public int tweenGroup = 0;
/// <summary>
/// Event delegates called when the animation finishes.
/// </summary>
[HideInInspector]
public List<EventDelegate> onFinished = new List<EventDelegate> ();
// Deprecated functionality, kept for backwards compatibility
[HideInInspector]
public GameObject eventReceiver;
[HideInInspector]
public string callWhenFinished;
public object onFinishCallback; // add by chenbin
bool mStarted = false;
float mStartTime = 0f;
float mDuration = 0f;
float mAmountPerDelta = 1000f;
float mFactor = 0f;
/// <summary>
/// Amount advanced per delta time.
/// </summary>
public float amountPerDelta {
get {
if (mDuration != duration) {
mDuration = duration;
mAmountPerDelta = Mathf.Abs ((duration > 0f) ? 1f / duration : 1000f);
}
return mAmountPerDelta;
}
}
/// <summary>
/// Tween factor, 0-1 range.
/// </summary>
public float tweenFactor { get { return mFactor; } set { mFactor = Mathf.Clamp01 (value); } }
/// <summary>
/// Direction that the tween is currently playing in.
/// </summary>
public AnimationOrTween.Direction direction { get { return mAmountPerDelta < 0f ? AnimationOrTween.Direction.Reverse : AnimationOrTween.Direction.Forward; } }
/// <summary>
/// This function is called by Unity when you add a component. Automatically set the starting values for convenience.
/// </summary>
public void Reset ()
{
if (!mStarted) {
SetStartToCurrentValue ();
SetEndToCurrentValue ();
}
}
/// <summary>
/// Update as soon as it's started so that there is no delay.
/// </summary>
protected virtual void Start ()
{
Update ();
}
/// <summary>
/// Update the tweening factor and call the virtual update function.
/// </summary>
void Update ()
{
float delta = ignoreTimeScale ? RealTime.deltaTime : Time.deltaTime;
float time = ignoreTimeScale ? RealTime.time : Time.time;
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 == Style.Loop) {
if (mFactor > 1f) {
mFactor -= Mathf.Floor (mFactor);
}
} else if (style == Style.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 == Style.Once) && (duration == 0f || mFactor > 1f || mFactor < 0f)) {
mFactor = Mathf.Clamp01 (mFactor);
Sample (mFactor, true);
// Disable this script unless the function calls above changed something
if (duration == 0f || (mFactor == 1f && mAmountPerDelta > 0f || mFactor == 0f && mAmountPerDelta < 0f))
enabled = false;
current = this;
if (onFinished != null) {
mTemp = onFinished;
onFinished = new List<EventDelegate> ();
// Notify the listener delegates
EventDelegate.Execute (mTemp, gameObject);
// Re-add the previous persistent delegates
for (int i = 0; i < mTemp.Count; ++i)
EventDelegate.Add (onFinished, mTemp [i]);
mTemp = null;
}
// Deprecated legacy functionality support
if (eventReceiver != null && !string.IsNullOrEmpty (callWhenFinished))
eventReceiver.SendMessage (callWhenFinished, this, SendMessageOptions.DontRequireReceiver);
Coolape.Utl.doCallback (onFinishCallback, this); // add by chenbin
current = null;
} else
Sample (mFactor, false);
}
List<EventDelegate> mTemp = null;
/// <summary>
/// Convenience function -- set a new OnFinished event delegate (here for to be consistent with RemoveOnFinished).
/// </summary>
public void SetOnFinished (EventDelegate.Callback del)
{
EventDelegate.Set (onFinished, del);
}
/// <summary>
/// Convenience function -- set a new OnFinished event delegate (here for to be consistent with RemoveOnFinished).
/// </summary>
public void SetOnFinished (EventDelegate del)
{
EventDelegate.Set (onFinished, del);
}
/// <summary>
/// Convenience function -- add a new OnFinished event delegate (here for to be consistent with RemoveOnFinished).
/// </summary>
public void AddOnFinished (EventDelegate.Callback del)
{
EventDelegate.Add (onFinished, del);
}
/// <summary>
/// Convenience function -- add a new OnFinished event delegate (here for to be consistent with RemoveOnFinished).
/// </summary>
public void AddOnFinished (EventDelegate del)
{
EventDelegate.Add (onFinished, del);
}
/// <summary>
/// Remove an OnFinished delegate. Will work even while iterating through the list when the tweener has finished its operation.
/// </summary>
public void RemoveOnFinished (EventDelegate del)
{
if (onFinished != null)
onFinished.Remove (del);
if (mTemp != null)
mTemp.Remove (del);
}
/// <summary>
/// Mark as not started when finished to enable delay on next play.
/// </summary>
void OnDisable ()
{
mStarted = false;
}
/// <summary>
/// Sample the tween at the specified factor.
/// </summary>
public void Sample (float factor, bool isFinished)
{
// Calculate the sampling value
float val = Mathf.Clamp01 (factor);
if (method == Method.EaseIn) {
val = 1f - Mathf.Sin (0.5f * Mathf.PI * (1f - val));
if (steeperCurves)
val *= val;
} else if (method == Method.EaseOut) {
val = Mathf.Sin (0.5f * Mathf.PI * val);
if (steeperCurves) {
val = 1f - val;
val = 1f - val * val;
}
} else if (method == Method.EaseInOut) {
const float pi2 = Mathf.PI * 2f;
val = val - Mathf.Sin (val * pi2) / pi2;
if (steeperCurves) {
val = val * 2f - 1f;
float sign = Mathf.Sign (val);
val = 1f - Mathf.Abs (val);
val = 1f - val * val;
val = sign * val * 0.5f + 0.5f;
}
} else if (method == Method.BounceIn) {
val = BounceLogic (val);
} else if (method == Method.BounceOut) {
val = 1f - BounceLogic (1f - val);
}
// Call the virtual update
OnUpdate ((animationCurve != null) ? animationCurve.Evaluate (val) : val, isFinished);
}
/// <summary>
/// Main Bounce logic to simplify the Sample function
/// </summary>
float BounceLogic (float val)
{
if (val < 0.363636f) { // 0.363636 = (1/ 2.75)
val = 7.5685f * val * val;
} else if (val < 0.727272f) { // 0.727272 = (2 / 2.75)
val = 7.5625f * (val -= 0.545454f) * val + 0.75f; // 0.545454f = (1.5 / 2.75)
} else if (val < 0.909090f) { // 0.909090 = (2.5 / 2.75)
val = 7.5625f * (val -= 0.818181f) * val + 0.9375f; // 0.818181 = (2.25 / 2.75)
} else {
val = 7.5625f * (val -= 0.9545454f) * val + 0.984375f; // 0.9545454 = (2.625 / 2.75)
}
return val;
}
/// <summary>
/// Play the tween.
/// </summary>
[System.Obsolete("Use PlayForward() instead")]
public void Play ()
{
Play (true);
}
/// <summary>
/// Play the tween forward.
/// </summary>
public void PlayForward ()
{
Play (true);
}
/// <summary>
/// Play the tween in reverse.
/// </summary>
public void PlayReverse ()
{
Play (false);
}
/// <summary>
/// Manually activate the tweening process, reversing it if necessary.
/// </summary>
public void Play (bool forward)
{
mAmountPerDelta = Mathf.Abs (amountPerDelta);
if (!forward)
mAmountPerDelta = -mAmountPerDelta;
enabled = true;
Update ();
}
/// <summary>
/// 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.
/// </summary>
public void ResetToBeginning ()
{
mStarted = false;
mFactor = (mAmountPerDelta < 0f) ? 1f : 0f;
Sample (mFactor, false);
}
/// <summary>
/// Manually start the tweening process, reversing its direction.
/// </summary>
public void Toggle ()
{
if (mFactor > 0f) {
mAmountPerDelta = -amountPerDelta;
} else {
mAmountPerDelta = Mathf.Abs (amountPerDelta);
}
enabled = true;
}
/// <summary>
/// Actual tweening logic should go here.
/// </summary>
abstract protected void OnUpdate (float factor, bool isFinished);
/// <summary>
/// Starts the tweening operation.
/// </summary>
static public T Begin<T> (GameObject go, float duration) where T : UITweener
{
T comp = go.GetComponent<T> ();
#if UNITY_FLASH
if ((object)comp == null) comp = (T)go.AddComponent<T>();
#else
if (comp == null)
comp = go.AddComponent<T> ();
#endif
comp.mStarted = false;
comp.duration = duration;
comp.mFactor = 0f;
comp.mAmountPerDelta = Mathf.Abs (comp.mAmountPerDelta);
comp.style = Style.Once;
comp.animationCurve = new AnimationCurve (new Keyframe (0f, 0f, 0f, 1f), new Keyframe (1f, 1f, 1f, 0f));
comp.eventReceiver = null;
comp.callWhenFinished = null;
comp.enabled = true;
if (duration <= 0f) {
comp.Sample (1f, true);
comp.enabled = false;
}
return comp;
}
/// <summary>
/// Set the 'from' value to the current one.
/// </summary>
public virtual void SetStartToCurrentValue ()
{
}
/// <summary>
/// Set the 'to' value to the current one.
/// </summary>
public virtual void SetEndToCurrentValue ()
{
}
}