using System; using System.Collections.Generic; using FairyGUI.Utils; using UnityEngine; namespace FairyGUI { /// /// /// public delegate void PlayCompleteCallback(); /// /// /// public delegate void TransitionHook(); /// /// /// public class Transition : ITweenListener { /// /// 动效的名称。在编辑器里设定。 /// public string name { get; private set; } /// /// 当你启动了自动合批,动效里有涉及到XY、大小、旋转等的改变,如果你观察到元件的显示深度在播放过程中有错误,可以开启这个选项。 /// 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; } /// /// /// public void Play() { _Play(1, 0, 0, -1, null, false); } /// /// /// /// public void Play(PlayCompleteCallback onComplete) { _Play(1, 0, 0, -1, onComplete, false); } /// /// /// /// /// /// public void Play(int times, float delay, PlayCompleteCallback onComplete) { _Play(times, delay, 0, -1, onComplete, false); } /// /// /// /// /// /// /// /// public void Play(int times, float delay, float startTime, float endTime, PlayCompleteCallback onComplete) { _Play(times, delay, startTime, endTime, onComplete, false); } /// /// /// public void PlayReverse() { _Play(1, 0, 0, -1, null, true); } /// /// /// /// public void PlayReverse(PlayCompleteCallback onComplete) { _Play(1, 0, 0, -1, onComplete, true); } /// /// /// /// /// /// public void PlayReverse(int times, float delay, PlayCompleteCallback onComplete) { _Play(times, delay, 0, -1, onComplete, true); } /// /// /// /// public void ChangePlayTimes(int value) { _totalTimes = value; } /// /// 设置动效是否自动播放。 /// /// /// /// 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); } /// /// /// public void Stop() { Stop(true, false); } /// /// /// /// /// 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); } } /// /// /// /// 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; } /// /// /// public bool playing { get { return _playing; } } /// /// transition's total duration, maybe zero when the transition only has one frame /// public float totalDuration { get { return _totalDuration; } } /// /// /// /// /// 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"); } /// /// /// /// /// 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"); } /// /// /// 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; } } /// /// /// /// /// 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"); } /// /// /// /// /// 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"); } /// /// /// /// /// 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; } /// /// /// 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; } } } } } /// /// /// 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; } } } }