2025-06-07 17:43:34 +08:00

1772 lines
60 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Collections.Generic;
using FairyGUI.Utils;
using UnityEngine;
namespace FairyGUI
{
/// <summary>
///
/// </summary>
public delegate void PlayCompleteCallback();
/// <summary>
///
/// </summary>
public delegate void TransitionHook();
/// <summary>
///
/// </summary>
public class Transition : ITweenListener
{
/// <summary>
/// 动效的名称。在编辑器里设定。
/// </summary>
public string name { get; private set; }
/// <summary>
/// 当你启动了自动合批动效里有涉及到XY、大小、旋转等的改变如果你观察到元件的显示深度在播放过程中有错误可以开启这个选项。
/// </summary>
public bool invalidateBatchingEveryFrame;
GComponent _owner;
TransitionItem[] _items;
int _totalTimes;
int _totalTasks;
bool _playing;
bool _paused;
float _ownerBaseX;
float _ownerBaseY;
PlayCompleteCallback _onComplete;
int _options;
bool _reversed;
float _totalDuration;
bool _autoPlay;
int _autoPlayTimes;
float _autoPlayDelay;
float _timeScale;
bool _ignoreEngineTimeScale;
float _startTime;
float _endTime;
GTweenCallback _delayedCallDelegate;
GTweenCallback _checkAllDelegate;
GTweenCallback1 _delayedCallDelegate2;
const int OPTION_IGNORE_DISPLAY_CONTROLLER = 1;
const int OPTION_AUTO_STOP_DISABLED = 2;
const int OPTION_AUTO_STOP_AT_END = 4;
public Transition(GComponent owner)
{
_owner = owner;
_timeScale = 1;
_ignoreEngineTimeScale = true;
_delayedCallDelegate = OnDelayedPlay;
_delayedCallDelegate2 = OnDelayedPlayItem;
_checkAllDelegate = CheckAllComplete;
}
/// <summary>
///
/// </summary>
public void Play()
{
_Play(1, 0, 0, -1, null, false);
}
/// <summary>
///
/// </summary>
/// <param name="onComplete"></param>
public void Play(PlayCompleteCallback onComplete)
{
_Play(1, 0, 0, -1, onComplete, false);
}
/// <summary>
///
/// </summary>
/// <param name="times"></param>
/// <param name="delay"></param>
/// <param name="onComplete"></param>
public void Play(int times, float delay, PlayCompleteCallback onComplete)
{
_Play(times, delay, 0, -1, onComplete, false);
}
/// <summary>
///
/// </summary>
/// <param name="times"></param>
/// <param name="delay"></param>
/// <param name="startTime"></param>
/// <param name="endTime"></param>
/// <param name="onComplete"></param>
public void Play(int times, float delay, float startTime, float endTime, PlayCompleteCallback onComplete)
{
_Play(times, delay, startTime, endTime, onComplete, false);
}
/// <summary>
///
/// </summary>
public void PlayReverse()
{
_Play(1, 0, 0, -1, null, true);
}
/// <summary>
///
/// </summary>
/// <param name="onComplete"></param>
public void PlayReverse(PlayCompleteCallback onComplete)
{
_Play(1, 0, 0, -1, onComplete, true);
}
/// <summary>
///
/// </summary>
/// <param name="times"></param>
/// <param name="delay"></param>
/// <param name="onComplete"></param>
public void PlayReverse(int times, float delay, PlayCompleteCallback onComplete)
{
_Play(times, delay, 0, -1, onComplete, true);
}
/// <summary>
///
/// </summary>
/// <param name="value"></param>
public void ChangePlayTimes(int value)
{
_totalTimes = value;
}
/// <summary>
/// 设置动效是否自动播放。
/// </summary>
/// <param name="autoPlay"></param>
/// <param name="times"></param>
/// <param name="delay"></param>
public void SetAutoPlay(bool autoPlay, int times, float delay)
{
if (_autoPlay != autoPlay)
{
_autoPlay = autoPlay;
_autoPlayTimes = times;
_autoPlayDelay = delay;
if (_autoPlay)
{
if (_owner.onStage)
Play(times, delay, null);
}
else
{
if (!_owner.onStage)
Stop(false, true);
}
}
}
void _Play(int times, float delay, float startTime, float endTime, PlayCompleteCallback onComplete, bool reverse)
{
Stop(true, true);
_totalTimes = times;
_reversed = reverse;
_startTime = startTime;
_endTime = endTime;
_playing = true;
_paused = false;
_onComplete = onComplete;
int cnt = _items.Length;
for (int i = 0; i < cnt; i++)
{
TransitionItem item = _items[i];
if (item.target == null)
{
if (item.targetId.Length > 0)
item.target = _owner.GetChildById(item.targetId);
else
item.target = _owner;
}
else if (item.target != _owner && item.target.parent != _owner) //maybe removed
item.target = null;
if (item.target != null && item.type == TransitionActionType.Transition)
{
TValue_Transition value = (TValue_Transition)item.value;
Transition trans = ((GComponent)item.target).GetTransition(value.transName);
if (trans == this)
trans = null;
if (trans != null)
{
if (value.playTimes == 0) //stop
{
int j;
for (j = i - 1; j >= 0; j--)
{
TransitionItem item2 = _items[j];
if (item2.type == TransitionActionType.Transition)
{
TValue_Transition value2 = (TValue_Transition)item2.value;
if (value2.trans == trans)
{
value2.stopTime = item.time - item2.time;
break;
}
}
}
if (j < 0)
value.stopTime = 0;
else
trans = null; //no need to handle stop anymore
}
else
value.stopTime = -1;
}
value.trans = trans;
}
}
if (delay == 0)
OnDelayedPlay();
else
GTween.DelayedCall(delay).SetTarget(this).OnComplete(_delayedCallDelegate);
}
/// <summary>
///
/// </summary>
public void Stop()
{
Stop(true, false);
}
/// <summary>
///
/// </summary>
/// <param name="setToComplete"></param>
/// <param name="processCallback"></param>
public void Stop(bool setToComplete, bool processCallback)
{
if (!_playing)
return;
_playing = false;
_totalTasks = 0;
_totalTimes = 0;
PlayCompleteCallback func = _onComplete;
_onComplete = null;
GTween.Kill(this);//delay start
int cnt = _items.Length;
if (_reversed)
{
for (int i = cnt - 1; i >= 0; i--)
{
TransitionItem item = _items[i];
if (item.target == null)
continue;
StopItem(item, setToComplete);
}
}
else
{
for (int i = 0; i < cnt; i++)
{
TransitionItem item = _items[i];
if (item.target == null)
continue;
StopItem(item, setToComplete);
}
}
if (processCallback && func != null)
func();
}
void StopItem(TransitionItem item, bool setToComplete)
{
if (item.displayLockToken != 0)
{
item.target.ReleaseDisplayLock(item.displayLockToken);
item.displayLockToken = 0;
}
if (item.tweener != null)
{
item.tweener.Kill(setToComplete);
item.tweener = null;
if (item.type == TransitionActionType.Shake && !setToComplete) //震动必须归位,否则下次就越震越远了。
{
item.target._gearLocked = true;
item.target.SetXY(item.target.x - ((TValue_Shake)item.value).lastOffset.x, item.target.y - ((TValue_Shake)item.value).lastOffset.y);
item.target._gearLocked = false;
_owner.InvalidateBatchingState(true);
}
}
if (item.type == TransitionActionType.Transition)
{
TValue_Transition value = (TValue_Transition)item.value;
if (value.trans != null)
value.trans.Stop(setToComplete, false);
}
}
/// <summary>
///
/// </summary>
/// <param name="paused"></param>
public void SetPaused(bool paused)
{
if (!_playing || _paused == paused)
return;
_paused = paused;
GTweener tweener = GTween.GetTween(this);
if (tweener != null)
tweener.SetPaused(paused);
int cnt = _items.Length;
for (int i = 0; i < cnt; i++)
{
TransitionItem item = _items[i];
if (item.target == null)
continue;
if (item.type == TransitionActionType.Transition)
{
if (((TValue_Transition)item.value).trans != null)
((TValue_Transition)item.value).trans.SetPaused(paused);
}
else if (item.type == TransitionActionType.Animation)
{
if (paused)
{
((TValue_Animation)item.value).flag = ((IAnimationGear)item.target).playing;
((IAnimationGear)item.target).playing = false;
}
else
((IAnimationGear)item.target).playing = ((TValue_Animation)item.value).flag;
}
if (item.tweener != null)
item.tweener.SetPaused(paused);
}
}
public void Dispose()
{
if (_playing)
GTween.Kill(this);//delay start
int cnt = _items.Length;
for (int i = 0; i < cnt; i++)
{
TransitionItem item = _items[i];
if (item.tweener != null)
{
item.tweener.Kill();
item.tweener = null;
}
item.target = null;
item.hook = null;
if (item.tweenConfig != null)
item.tweenConfig.endHook = null;
}
_playing = false;
_onComplete = null;
}
/// <summary>
///
/// </summary>
public bool playing
{
get { return _playing; }
}
/// <summary>
/// transition's total duration, maybe zero when the transition only has one frame
/// </summary>
public float totalDuration
{
get { return _totalDuration; }
}
/// <summary>
///
/// </summary>
/// <param name="label"></param>
/// <param name="aParams"></param>
public void SetValue(string label, params object[] aParams)
{
int cnt = _items.Length;
object value;
bool found = false;
for (int i = 0; i < cnt; i++)
{
TransitionItem item = _items[i];
if (item.label == label)
{
if (item.tweenConfig != null)
value = item.tweenConfig.startValue;
else
value = item.value;
found = true;
}
else if (item.tweenConfig != null && item.tweenConfig.endLabel == label)
{
value = item.tweenConfig.endValue;
found = true;
}
else
continue;
switch (item.type)
{
case TransitionActionType.XY:
case TransitionActionType.Size:
case TransitionActionType.Pivot:
case TransitionActionType.Scale:
case TransitionActionType.Skew:
{
TValue tvalue = (TValue)value;
tvalue.b1 = true;
tvalue.b2 = true;
tvalue.f1 = Convert.ToSingle(aParams[0]);
tvalue.f2 = Convert.ToSingle(aParams[1]);
}
break;
case TransitionActionType.Alpha:
((TValue)value).f1 = Convert.ToSingle(aParams[0]);
break;
case TransitionActionType.Rotation:
((TValue)value).f1 = Convert.ToSingle(aParams[0]);
break;
case TransitionActionType.Color:
((TValue)value).color = (Color)aParams[0];
break;
case TransitionActionType.Animation:
{
TValue_Animation tvalue = (TValue_Animation)value;
tvalue.frame = Convert.ToInt32(aParams[0]);
if (aParams.Length > 1)
tvalue.playing = Convert.ToBoolean(aParams[1]);
if (aParams.Length > 2)
tvalue.animationName = (string)aParams[2];
if (aParams.Length > 3)
tvalue.skinName = (string)aParams[3];
}
break;
case TransitionActionType.Visible:
((TValue_Visible)value).visible = Convert.ToBoolean(aParams[0]);
break;
case TransitionActionType.Sound:
{
TValue_Sound tvalue = (TValue_Sound)value;
tvalue.sound = (string)aParams[0];
if (aParams.Length > 1)
tvalue.volume = Convert.ToSingle(aParams[1]);
}
break;
case TransitionActionType.Transition:
{
TValue_Transition tvalue = (TValue_Transition)value;
tvalue.transName = (string)aParams[0];
if (aParams.Length > 1)
tvalue.playTimes = Convert.ToInt32(aParams[1]);
}
break;
case TransitionActionType.Shake:
{
((TValue_Shake)value).amplitude = Convert.ToSingle(aParams[0]);
if (aParams.Length > 1)
((TValue_Shake)value).duration = Convert.ToSingle(aParams[1]);
}
break;
case TransitionActionType.ColorFilter:
{
TValue tvalue = (TValue)value;
tvalue.f1 = Convert.ToSingle(aParams[0]);
tvalue.f2 = Convert.ToSingle(aParams[1]);
tvalue.f3 = Convert.ToSingle(aParams[2]);
tvalue.f4 = Convert.ToSingle(aParams[3]);
}
break;
case TransitionActionType.Text:
case TransitionActionType.Icon:
((TValue_Text)value).text = (string)aParams[0];
break;
}
}
if (!found)
throw new Exception("label not exists");
}
/// <summary>
///
/// </summary>
/// <param name="label"></param>
/// <param name="callback"></param>
public void SetHook(string label, TransitionHook callback)
{
int cnt = _items.Length;
bool found = false;
for (int i = 0; i < cnt; i++)
{
TransitionItem item = _items[i];
if (item.label == label)
{
item.hook = callback;
found = true;
break;
}
else if (item.tweenConfig != null && item.tweenConfig.endLabel == label)
{
item.tweenConfig.endHook = callback;
found = true;
break;
}
}
if (!found)
throw new Exception("label not exists");
}
/// <summary>
///
/// </summary>
public void ClearHooks()
{
int cnt = _items.Length;
for (int i = 0; i < cnt; i++)
{
TransitionItem item = _items[i];
item.hook = null;
if (item.tweenConfig != null)
item.tweenConfig.endHook = null;
}
}
/// <summary>
///
/// </summary>
/// <param name="label"></param>
/// <param name="newTarget"></param>
public void SetTarget(string label, GObject newTarget)
{
int cnt = _items.Length;
bool found = false;
for (int i = 0; i < cnt; i++)
{
TransitionItem item = _items[i];
if (item.label == label)
{
item.targetId = (newTarget == _owner || newTarget == null) ? string.Empty : newTarget.id;
if (_playing)
{
if (item.targetId.Length > 0)
item.target = _owner.GetChildById(item.targetId);
else
item.target = _owner;
}
else
item.target = null;
found = true;
}
}
if (!found)
throw new Exception("label not exists");
}
/// <summary>
///
/// </summary>
/// <param name="label"></param>
/// <param name="value"></param>
public void SetDuration(string label, float value)
{
int cnt = _items.Length;
bool found = false;
for (int i = 0; i < cnt; i++)
{
TransitionItem item = _items[i];
if (item.tweenConfig != null && item.label == label)
{
item.tweenConfig.duration = value;
found = true;
}
}
if (!found)
throw new Exception("label not exists or not a tween label");
}
/// <summary>
///
/// </summary>
/// <param name="label"></param>
/// <returns></returns>
public float GetLabelTime(string label)
{
int cnt = _items.Length;
for (int i = 0; i < cnt; i++)
{
TransitionItem item = _items[i];
if (item.label == label)
return item.time;
else if (item.tweenConfig != null && item.tweenConfig.endLabel == label)
return item.time + item.tweenConfig.duration;
}
return float.NaN;
}
/// <summary>
///
/// </summary>
public float timeScale
{
get { return _timeScale; }
set
{
if (_timeScale != value)
{
_timeScale = value;
int cnt = _items.Length;
for (int i = 0; i < cnt; i++)
{
TransitionItem item = _items[i];
if (item.tweener != null)
item.tweener.SetTimeScale(value);
else if (item.type == TransitionActionType.Transition)
{
if (((TValue_Transition)item.value).trans != null)
((TValue_Transition)item.value).trans.timeScale = value;
}
else if (item.type == TransitionActionType.Animation)
{
if (item.target != null)
((IAnimationGear)item.target).timeScale = value;
}
}
}
}
}
/// <summary>
///
/// </summary>
public bool ignoreEngineTimeScale
{
get { return _ignoreEngineTimeScale; }
set
{
if (_ignoreEngineTimeScale != value)
{
_ignoreEngineTimeScale = value;
int cnt = _items.Length;
for (int i = 0; i < cnt; i++)
{
TransitionItem item = _items[i];
if (item.tweener != null)
item.tweener.SetIgnoreEngineTimeScale(value);
else if (item.type == TransitionActionType.Transition)
{
if (((TValue_Transition)item.value).trans != null)
((TValue_Transition)item.value).trans.ignoreEngineTimeScale = value;
}
else if (item.type == TransitionActionType.Animation)
{
if (item.target != null)
((IAnimationGear)item.target).ignoreEngineTimeScale = value;
}
}
}
}
}
internal void UpdateFromRelations(string targetId, float dx, float dy)
{
int cnt = _items.Length;
if (cnt == 0)
return;
for (int i = 0; i < cnt; i++)
{
TransitionItem item = _items[i];
if (item.type == TransitionActionType.XY && item.targetId == targetId)
{
if (item.tweenConfig != null)
{
if (!item.tweenConfig.startValue.b3)
{
item.tweenConfig.startValue.f1 += dx;
item.tweenConfig.startValue.f2 += dy;
}
if (!item.tweenConfig.endValue.b3)
{
item.tweenConfig.endValue.f1 += dx;
item.tweenConfig.endValue.f2 += dy;
}
}
else
{
if (!((TValue)item.value).b3)
{
((TValue)item.value).f1 += dx;
((TValue)item.value).f2 += dy;
}
}
}
}
}
internal void OnOwnerAddedToStage()
{
if (_autoPlay && !_playing)
Play(_autoPlayTimes, _autoPlayDelay, null);
}
internal void OnOwnerRemovedFromStage()
{
if ((_options & OPTION_AUTO_STOP_DISABLED) == 0)
Stop((_options & OPTION_AUTO_STOP_AT_END) != 0 ? true : false, false);
}
void OnDelayedPlay()
{
InternalPlay();
_playing = _totalTasks > 0;
if (_playing)
{
if ((_options & OPTION_IGNORE_DISPLAY_CONTROLLER) != 0)
{
int cnt = _items.Length;
for (int i = 0; i < cnt; i++)
{
TransitionItem item = _items[i];
if (item.target != null && item.target != _owner)
item.displayLockToken = item.target.AddDisplayLock();
}
}
}
else if (_onComplete != null)
{
PlayCompleteCallback func = _onComplete;
_onComplete = null;
func();
}
}
void InternalPlay()
{
_ownerBaseX = _owner.x;
_ownerBaseY = _owner.y;
_totalTasks = 1; //prevent to complete inside the loop
bool needSkipAnimations = false;
int cnt = _items.Length;
if (!_reversed)
{
for (int i = 0; i < cnt; i++)
{
TransitionItem item = _items[i];
if (item.target == null)
continue;
if (item.type == TransitionActionType.Animation && _startTime != 0 && item.time <= _startTime)
{
needSkipAnimations = true;
((TValue_Animation)item.value).flag = false;
}
else
PlayItem(item);
}
}
else
{
for (int i = cnt - 1; i >= 0; i--)
{
TransitionItem item = _items[i];
if (item.target == null)
continue;
PlayItem(item);
}
}
if (needSkipAnimations)
SkipAnimations();
_totalTasks--;
}
void PlayItem(TransitionItem item)
{
float time;
if (item.tweenConfig != null)
{
if (_reversed)
time = (_totalDuration - item.time - item.tweenConfig.duration);
else
time = item.time;
if (_endTime == -1 || time <= _endTime)
{
TValue startValue;
TValue endValue;
if (_reversed)
{
startValue = item.tweenConfig.endValue;
endValue = item.tweenConfig.startValue;
}
else
{
startValue = item.tweenConfig.startValue;
endValue = item.tweenConfig.endValue;
}
((TValue)item.value).b1 = startValue.b1 || endValue.b1;
((TValue)item.value).b2 = startValue.b2 || endValue.b2;
switch (item.type)
{
case TransitionActionType.XY:
case TransitionActionType.Size:
case TransitionActionType.Scale:
case TransitionActionType.Skew:
item.tweener = GTween.To(startValue.vec2, endValue.vec2, item.tweenConfig.duration);
break;
case TransitionActionType.Alpha:
case TransitionActionType.Rotation:
item.tweener = GTween.To(startValue.f1, endValue.f1, item.tweenConfig.duration);
break;
case TransitionActionType.Color:
item.tweener = GTween.To(startValue.color, endValue.color, item.tweenConfig.duration);
break;
case TransitionActionType.ColorFilter:
item.tweener = GTween.To(startValue.vec4, endValue.vec4, item.tweenConfig.duration);
break;
}
item.tweener.SetDelay(time)
.SetEase(item.tweenConfig.easeType, item.tweenConfig.customEase)
.SetRepeat(item.tweenConfig.repeat, item.tweenConfig.yoyo)
.SetTimeScale(_timeScale)
.SetIgnoreEngineTimeScale(_ignoreEngineTimeScale)
.SetTarget(item)
.SetListener(this);
if (_endTime >= 0)
item.tweener.SetBreakpoint(_endTime - time);
_totalTasks++;
}
}
else if (item.type == TransitionActionType.Shake)
{
TValue_Shake value = (TValue_Shake)item.value;
if (_reversed)
time = (_totalDuration - item.time - value.duration);
else
time = item.time;
if (_endTime == -1 || time <= _endTime)
{
value.lastOffset.Set(0, 0);
value.offset.Set(0, 0);
item.tweener = GTween.Shake(Vector3.zero, value.amplitude, value.duration)
.SetDelay(time)
.SetTimeScale(_timeScale)
.SetIgnoreEngineTimeScale(_ignoreEngineTimeScale)
.SetTarget(item)
.SetListener(this);
if (_endTime >= 0)
item.tweener.SetBreakpoint(_endTime - item.time);
_totalTasks++;
}
}
else
{
if (_reversed)
time = (_totalDuration - item.time);
else
time = item.time;
if (time <= _startTime)
{
ApplyValue(item);
CallHook(item, false);
}
else if (_endTime == -1 || time <= _endTime)
{
_totalTasks++;
item.tweener = GTween.DelayedCall(time)
.SetTimeScale(_timeScale)
.SetIgnoreEngineTimeScale(_ignoreEngineTimeScale)
.SetTarget(item)
.OnComplete(_delayedCallDelegate2);
}
}
if (item.tweener != null)
item.tweener.Seek(_startTime);
}
void SkipAnimations()
{
int frame;
float playStartTime;
float playTotalTime;
TValue_Animation value;
IAnimationGear target;
TransitionItem item;
int cnt = _items.Length;
for (int i = 0; i < cnt; i++)
{
item = _items[i];
if (item.type != TransitionActionType.Animation || item.time > _startTime)
continue;
value = (TValue_Animation)item.value;
if (value.flag)
continue;
target = (IAnimationGear)item.target;
frame = target.frame;
playStartTime = target.playing ? 0 : -1;
playTotalTime = 0;
for (int j = i; j < cnt; j++)
{
item = _items[j];
if (item.type != TransitionActionType.Animation || item.target != target || item.time > _startTime)
continue;
value = (TValue_Animation)item.value;
value.flag = true;
if (value.frame != -1)
{
frame = value.frame;
if (value.playing)
playStartTime = item.time;
else
playStartTime = -1;
playTotalTime = 0;
}
else
{
if (value.playing)
{
if (playStartTime < 0)
playStartTime = item.time;
}
else
{
if (playStartTime >= 0)
playTotalTime += (item.time - playStartTime);
playStartTime = -1;
}
}
CallHook(item, false);
}
if (playStartTime >= 0)
playTotalTime += (_startTime - playStartTime);
target.playing = playStartTime >= 0;
target.frame = frame;
if (playTotalTime > 0)
target.Advance(playTotalTime);
}
}
void OnDelayedPlayItem(GTweener tweener)
{
TransitionItem item = (TransitionItem)tweener.target;
item.tweener = null;
_totalTasks--;
ApplyValue(item);
CallHook(item, false);
CheckAllComplete();
}
public void OnTweenStart(GTweener tweener)
{
TransitionItem item = (TransitionItem)tweener.target;
if (item.type == TransitionActionType.XY || item.type == TransitionActionType.Size) //位置和大小要到start才最终确认起始值
{
TValue startValue;
TValue endValue;
if (_reversed)
{
startValue = item.tweenConfig.endValue;
endValue = item.tweenConfig.startValue;
}
else
{
startValue = item.tweenConfig.startValue;
endValue = item.tweenConfig.endValue;
}
if (item.type == TransitionActionType.XY)
{
if (item.target != _owner)
{
if (!startValue.b1)
tweener.startValue.x = item.target.x;
else if (startValue.b3) //percent
tweener.startValue.x = startValue.f1 * _owner.width;
if (!startValue.b2)
tweener.startValue.y = item.target.y;
else if (startValue.b3) //percent
tweener.startValue.y = startValue.f2 * _owner.height;
if (!endValue.b1)
tweener.endValue.x = tweener.startValue.x;
else if (endValue.b3)
tweener.endValue.x = endValue.f1 * _owner.width;
if (!endValue.b2)
tweener.endValue.y = tweener.startValue.y;
else if (endValue.b3)
tweener.endValue.y = endValue.f2 * _owner.height;
}
else
{
if (!startValue.b1)
tweener.startValue.x = item.target.x - _ownerBaseX;
if (!startValue.b2)
tweener.startValue.y = item.target.y - _ownerBaseY;
if (!endValue.b1)
tweener.endValue.x = tweener.startValue.x;
if (!endValue.b2)
tweener.endValue.y = tweener.startValue.y;
}
}
else
{
if (!startValue.b1)
tweener.startValue.x = item.target.width;
if (!startValue.b2)
tweener.startValue.y = item.target.height;
if (!endValue.b1)
tweener.endValue.x = tweener.startValue.x;
if (!endValue.b2)
tweener.endValue.y = tweener.startValue.y;
}
if (item.tweenConfig.path != null)
{
((TValue)item.value).b1 = ((TValue)item.value).b2 = true;
tweener.SetPath(item.tweenConfig.path);
}
}
CallHook(item, false);
}
public void OnTweenUpdate(GTweener tweener)
{
TransitionItem item = (TransitionItem)tweener.target;
switch (item.type)
{
case TransitionActionType.XY:
case TransitionActionType.Size:
case TransitionActionType.Scale:
case TransitionActionType.Skew:
((TValue)item.value).vec2 = tweener.value.vec2;
if (item.tweenConfig.path != null)
{
((TValue)item.value).f1 += tweener.startValue.x;
((TValue)item.value).f2 += tweener.startValue.y;
}
break;
case TransitionActionType.Alpha:
case TransitionActionType.Rotation:
((TValue)item.value).f1 = tweener.value.x;
break;
case TransitionActionType.Color:
((TValue)item.value).color = tweener.value.color;
break;
case TransitionActionType.ColorFilter:
((TValue)item.value).vec4 = tweener.value.vec4;
break;
case TransitionActionType.Shake:
((TValue_Shake)item.value).offset = tweener.deltaValue.vec2;
break;
}
ApplyValue(item);
}
public void OnTweenComplete(GTweener tweener)
{
TransitionItem item = (TransitionItem)tweener.target;
item.tweener = null;
_totalTasks--;
if (tweener.allCompleted) //当整体播放结束时间在这个tween的中间时不应该调用结尾钩子
CallHook(item, true);
CheckAllComplete();
}
void OnPlayTransCompleted(TransitionItem item)
{
_totalTasks--;
CheckAllComplete();
}
void CallHook(TransitionItem item, bool tweenEnd)
{
if (tweenEnd)
{
if (item.tweenConfig != null && item.tweenConfig.endHook != null)
item.tweenConfig.endHook();
}
else
{
if (item.time >= _startTime && item.hook != null)
item.hook();
}
}
void CheckAllComplete()
{
if (_playing && _totalTasks == 0)
{
if (_totalTimes < 0)
{
InternalPlay();
if (_totalTasks == 0)
GTween.DelayedCall(0).SetTarget(this).OnComplete(_checkAllDelegate);
}
else
{
_totalTimes--;
if (_totalTimes > 0)
{
InternalPlay();
if (_totalTasks == 0)
GTween.DelayedCall(0).SetTarget(this).OnComplete(_checkAllDelegate);
}
else
{
_playing = false;
int cnt = _items.Length;
for (int i = 0; i < cnt; i++)
{
TransitionItem item = _items[i];
if (item.target != null && item.displayLockToken != 0)
{
item.target.ReleaseDisplayLock(item.displayLockToken);
item.displayLockToken = 0;
}
}
if (_onComplete != null)
{
PlayCompleteCallback func = _onComplete;
_onComplete = null;
func();
}
}
}
}
}
void ApplyValue(TransitionItem item)
{
item.target._gearLocked = true;
switch (item.type)
{
case TransitionActionType.XY:
{
TValue value = (TValue)item.value;
if (item.target == _owner)
{
if (value.b1 && value.b2)
item.target.SetXY(value.f1 + _ownerBaseX, value.f2 + _ownerBaseY);
else if (value.b1)
item.target.x = value.f1 + _ownerBaseX;
else
item.target.y = value.f2 + _ownerBaseY;
}
else
{
if (value.b3) //position in percent
{
if (value.b1 && value.b2)
item.target.SetXY(value.f1 * _owner.width, value.f2 * _owner.height);
else if (value.b1)
item.target.x = value.f1 * _owner.width;
else if (value.b2)
item.target.y = value.f2 * _owner.height;
}
else
{
if (value.b1 && value.b2)
item.target.SetXY(value.f1, value.f2);
else if (value.b1)
item.target.x = value.f1;
else if (value.b2)
item.target.y = value.f2;
}
}
if (invalidateBatchingEveryFrame)
_owner.InvalidateBatchingState(true);
}
break;
case TransitionActionType.Size:
{
TValue value = (TValue)item.value;
if (!value.b1)
value.f1 = item.target.width;
if (!value.b2)
value.f2 = item.target.height;
item.target.SetSize(value.f1, value.f2);
if (invalidateBatchingEveryFrame)
_owner.InvalidateBatchingState(true);
}
break;
case TransitionActionType.Pivot:
item.target.SetPivot(((TValue)item.value).f1, ((TValue)item.value).f2, item.target.pivotAsAnchor);
if (invalidateBatchingEveryFrame)
_owner.InvalidateBatchingState(true);
break;
case TransitionActionType.Alpha:
item.target.alpha = ((TValue)item.value).f1;
break;
case TransitionActionType.Rotation:
item.target.rotation = ((TValue)item.value).f1;
if (invalidateBatchingEveryFrame)
_owner.InvalidateBatchingState(true);
break;
case TransitionActionType.Scale:
item.target.SetScale(((TValue)item.value).f1, ((TValue)item.value).f2);
if (invalidateBatchingEveryFrame)
_owner.InvalidateBatchingState(true);
break;
case TransitionActionType.Skew:
item.target.skew = ((TValue)item.value).vec2;
if (invalidateBatchingEveryFrame)
_owner.InvalidateBatchingState(true);
break;
case TransitionActionType.Color:
((IColorGear)item.target).color = ((TValue)item.value).color;
break;
case TransitionActionType.Animation:
{
TValue_Animation value = (TValue_Animation)item.value;
if (value.frame >= 0)
((IAnimationGear)item.target).frame = value.frame;
((IAnimationGear)item.target).playing = value.playing;
((IAnimationGear)item.target).timeScale = _timeScale;
((IAnimationGear)item.target).ignoreEngineTimeScale = _ignoreEngineTimeScale;
if (value.animationName != null)
((GLoader3D)item.target).animationName = value.animationName;
if (value.skinName != null)
((GLoader3D)item.target).skinName = value.skinName;
}
break;
case TransitionActionType.Visible:
item.target.visible = ((TValue_Visible)item.value).visible;
break;
case TransitionActionType.Shake:
{
TValue_Shake value = (TValue_Shake)item.value;
item.target.SetXY(item.target.x - value.lastOffset.x + value.offset.x, item.target.y - value.lastOffset.y + value.offset.y);
value.lastOffset = value.offset;
if (invalidateBatchingEveryFrame)
_owner.InvalidateBatchingState(true);
}
break;
case TransitionActionType.Transition:
if (_playing)
{
TValue_Transition value = (TValue_Transition)item.value;
if (value.trans != null)
{
_totalTasks++;
float startTime = _startTime > item.time ? (_startTime - item.time) : 0;
float endTime = _endTime >= 0 ? (_endTime - item.time) : -1;
if (value.stopTime >= 0 && (endTime < 0 || endTime > value.stopTime))
endTime = value.stopTime;
value.trans.timeScale = _timeScale;
value.trans.ignoreEngineTimeScale = _ignoreEngineTimeScale;
value.trans._Play(value.playTimes, 0, startTime, endTime, value.playCompleteDelegate, _reversed);
}
}
break;
case TransitionActionType.Sound:
if (_playing && item.time >= _startTime)
{
TValue_Sound value = (TValue_Sound)item.value;
if (value.audioClip == null)
{
if (UIConfig.soundLoader == null || value.sound.StartsWith(UIPackage.URL_PREFIX))
value.audioClip = UIPackage.GetItemAssetByURL(value.sound) as NAudioClip;
else
value.audioClip = UIConfig.soundLoader(value.sound);
}
if (value.audioClip != null && value.audioClip.nativeClip != null)
Stage.inst.PlayOneShotSound(value.audioClip.nativeClip, value.volume);
}
break;
case TransitionActionType.ColorFilter:
{
TValue value = (TValue)item.value;
ColorFilter cf = item.target.filter as ColorFilter;
if (cf == null)
{
cf = new ColorFilter();
item.target.filter = cf;
}
else
cf.Reset();
cf.AdjustBrightness(value.f1);
cf.AdjustContrast(value.f2);
cf.AdjustSaturation(value.f3);
cf.AdjustHue(value.f4);
}
break;
case TransitionActionType.Text:
item.target.text = ((TValue_Text)item.value).text;
break;
case TransitionActionType.Icon:
item.target.icon = ((TValue_Text)item.value).text;
break;
}
item.target._gearLocked = false;
}
public void Setup(ByteBuffer buffer)
{
this.name = buffer.ReadS();
_options = buffer.ReadInt();
_autoPlay = buffer.ReadBool();
_autoPlayTimes = buffer.ReadInt();
_autoPlayDelay = buffer.ReadFloat();
int cnt = buffer.ReadShort();
_items = new TransitionItem[cnt];
for (int i = 0; i < cnt; i++)
{
int dataLen = buffer.ReadShort();
int curPos = buffer.position;
buffer.Seek(curPos, 0);
TransitionItem item = new TransitionItem((TransitionActionType)buffer.ReadByte());
_items[i] = item;
item.time = buffer.ReadFloat();
int targetId = buffer.ReadShort();
if (targetId < 0)
item.targetId = string.Empty;
else
item.targetId = _owner.GetChildAt(targetId).id;
item.label = buffer.ReadS();
if (buffer.ReadBool())
{
buffer.Seek(curPos, 1);
item.tweenConfig = new TweenConfig();
item.tweenConfig.duration = buffer.ReadFloat();
if (item.time + item.tweenConfig.duration > _totalDuration)
_totalDuration = item.time + item.tweenConfig.duration;
item.tweenConfig.easeType = (EaseType)buffer.ReadByte();
item.tweenConfig.repeat = buffer.ReadInt();
item.tweenConfig.yoyo = buffer.ReadBool();
item.tweenConfig.endLabel = buffer.ReadS();
buffer.Seek(curPos, 2);
DecodeValue(item, buffer, item.tweenConfig.startValue);
buffer.Seek(curPos, 3);
DecodeValue(item, buffer, item.tweenConfig.endValue);
if (buffer.version >= 2)
{
var pts = buffer.ReadPath();
if (pts.Count > 0)
{
item.tweenConfig.path = new GPath();
item.tweenConfig.path.Create(pts);
}
}
if (buffer.version >= 4 && item.tweenConfig.easeType == EaseType.Custom)
{
var pts = buffer.ReadPath();
if (pts.Count > 0)
{
item.tweenConfig.customEase = new CustomEase();
item.tweenConfig.customEase.Create(pts);
}
}
}
else
{
if (item.time > _totalDuration)
_totalDuration = item.time;
buffer.Seek(curPos, 2);
DecodeValue(item, buffer, item.value);
}
buffer.position = curPos + dataLen;
}
}
void DecodeValue(TransitionItem item, ByteBuffer buffer, object value)
{
switch (item.type)
{
case TransitionActionType.XY:
case TransitionActionType.Size:
case TransitionActionType.Pivot:
case TransitionActionType.Skew:
{
TValue tvalue = (TValue)value;
tvalue.b1 = buffer.ReadBool();
tvalue.b2 = buffer.ReadBool();
tvalue.f1 = buffer.ReadFloat();
tvalue.f2 = buffer.ReadFloat();
if (buffer.version >= 2 && item.type == TransitionActionType.XY)
tvalue.b3 = buffer.ReadBool(); //percent
}
break;
case TransitionActionType.Alpha:
case TransitionActionType.Rotation:
((TValue)value).f1 = buffer.ReadFloat();
break;
case TransitionActionType.Scale:
((TValue)value).f1 = buffer.ReadFloat();
((TValue)value).f2 = buffer.ReadFloat();
break;
case TransitionActionType.Color:
((TValue)value).color = buffer.ReadColor();
break;
case TransitionActionType.Animation:
((TValue_Animation)value).playing = buffer.ReadBool();
((TValue_Animation)value).frame = buffer.ReadInt();
if (buffer.version >= 6)
{
((TValue_Animation)value).animationName = buffer.ReadS();
((TValue_Animation)value).skinName = buffer.ReadS();
}
break;
case TransitionActionType.Visible:
((TValue_Visible)value).visible = buffer.ReadBool();
break;
case TransitionActionType.Sound:
((TValue_Sound)value).sound = buffer.ReadS();
((TValue_Sound)value).volume = buffer.ReadFloat();
break;
case TransitionActionType.Transition:
((TValue_Transition)value).transName = buffer.ReadS();
((TValue_Transition)value).playTimes = buffer.ReadInt();
((TValue_Transition)value).playCompleteDelegate = () => { OnPlayTransCompleted(item); };
break;
case TransitionActionType.Shake:
((TValue_Shake)value).amplitude = buffer.ReadFloat();
((TValue_Shake)value).duration = buffer.ReadFloat();
break;
case TransitionActionType.ColorFilter:
{
TValue tvalue = (TValue)value;
tvalue.f1 = buffer.ReadFloat();
tvalue.f2 = buffer.ReadFloat();
tvalue.f3 = buffer.ReadFloat();
tvalue.f4 = buffer.ReadFloat();
}
break;
case TransitionActionType.Text:
case TransitionActionType.Icon:
((TValue_Text)value).text = buffer.ReadS();
break;
}
}
}
class TransitionItem
{
public float time;
public string targetId;
public TransitionActionType type;
public TweenConfig tweenConfig;
public string label;
public object value;
public TransitionHook hook;
//running properties
public GTweener tweener;
public GObject target;
public uint displayLockToken;
public TransitionItem(TransitionActionType type)
{
this.type = type;
switch (type)
{
case TransitionActionType.XY:
case TransitionActionType.Size:
case TransitionActionType.Scale:
case TransitionActionType.Pivot:
case TransitionActionType.Skew:
case TransitionActionType.Alpha:
case TransitionActionType.Rotation:
case TransitionActionType.Color:
case TransitionActionType.ColorFilter:
value = new TValue();
break;
case TransitionActionType.Animation:
value = new TValue_Animation();
break;
case TransitionActionType.Shake:
value = new TValue_Shake();
break;
case TransitionActionType.Sound:
value = new TValue_Sound();
break;
case TransitionActionType.Transition:
value = new TValue_Transition();
break;
case TransitionActionType.Visible:
value = new TValue_Visible();
break;
case TransitionActionType.Text:
case TransitionActionType.Icon:
value = new TValue_Text();
break;
}
}
}
class TweenConfig
{
public float duration;
public EaseType easeType;
public CustomEase customEase;
public int repeat;
public bool yoyo;
public TValue startValue;
public TValue endValue;
public string endLabel;
public TransitionHook endHook;
public GPath path;
public TweenConfig()
{
easeType = EaseType.QuadOut;
startValue = new TValue();
endValue = new TValue();
}
}
class TValue_Visible
{
public bool visible;
}
class TValue_Animation
{
public int frame;
public bool playing;
public bool flag;
public string animationName;
public string skinName;
}
class TValue_Sound
{
public string sound;
public float volume;
public NAudioClip audioClip;
}
class TValue_Transition
{
public string transName;
public int playTimes;
public Transition trans;
public PlayCompleteCallback playCompleteDelegate;
public float stopTime;
}
class TValue_Shake
{
public float amplitude;
public float duration;
public Vector2 lastOffset;
public Vector2 offset;
}
class TValue_Text
{
public string text;
}
class TValue
{
public float f1;
public float f2;
public float f3;
public float f4;
public bool b1;
public bool b2;
public bool b3;
public TValue()
{
b1 = true;
b2 = true;
}
public void Copy(TValue source)
{
this.f1 = source.f1;
this.f2 = source.f2;
this.f3 = source.f3;
this.f4 = source.f4;
this.b1 = source.b1;
this.b2 = source.b2;
}
public Vector2 vec2
{
get { return new Vector2(f1, f2); }
set
{
f1 = value.x;
f2 = value.y;
}
}
public Vector4 vec4
{
get { return new Vector4(f1, f2, f3, f4); }
set
{
f1 = value.x;
f2 = value.y;
f3 = value.z;
f4 = value.w;
}
}
public Color color
{
get { return new Color(f1, f2, f3, f4); }
set
{
f1 = value.r;
f2 = value.g;
f3 = value.b;
f4 = value.a;
}
}
}
}