using UnityEngine;
namespace FairyGUI
{
///
///
///
public class MovieClip : Image
{
///
///
///
public class Frame
{
public NTexture texture;
public float addDelay;
}
///
///
///
public float interval;
///
///
///
public bool swing;
///
///
///
public float repeatDelay;
///
///
///
public float timeScale;
///
/// Whether to ignore Unity time scale.
///
public bool ignoreEngineTimeScale;
Frame[] _frames;
int _frameCount;
int _frame;
bool _playing;
int _start;
int _end;
int _times;
int _endAt;
int _status; //0-none, 1-next loop, 2-ending, 3-ended
float _frameElapsed; //当前帧延迟
bool _reversed;
int _repeatedCount;
TimerCallback _timerDelegate;
EventListener _onPlayEnd;
///
///
///
public MovieClip()
{
interval = 0.1f;
_playing = true;
_timerDelegate = OnTimer;
timeScale = 1;
ignoreEngineTimeScale = false;
if (Application.isPlaying)
{
onAddedToStage.Add(OnAddedToStage);
onRemovedFromStage.Add(OnRemoveFromStage);
}
SetPlaySettings();
}
///
///
///
public EventListener onPlayEnd
{
get { return _onPlayEnd ?? (_onPlayEnd = new EventListener(this, "onPlayEnd")); }
}
///
///
///
public Frame[] frames
{
get
{
return _frames;
}
set
{
_frames = value;
_scale9Grid = null;
_scaleByTile = false;
if (_frames == null)
{
_frameCount = 0;
graphics.texture = null;
CheckTimer();
return;
}
_frameCount = frames.Length;
if (_end == -1 || _end > _frameCount - 1)
_end = _frameCount - 1;
if (_endAt == -1 || _endAt > _frameCount - 1)
_endAt = _frameCount - 1;
if (_frame < 0 || _frame > _frameCount - 1)
_frame = _frameCount - 1;
InvalidateBatchingState();
_frameElapsed = 0;
_repeatedCount = 0;
_reversed = false;
DrawFrame();
CheckTimer();
}
}
///
///
///
public bool playing
{
get { return _playing; }
set
{
if (_playing != value)
{
_playing = value;
CheckTimer();
}
}
}
///
///
///
public int frame
{
get { return _frame; }
set
{
if (_frame != value)
{
if (_frames != null && value >= _frameCount)
value = _frameCount - 1;
_frame = value;
_frameElapsed = 0;
DrawFrame();
}
}
}
///
///
///
public void Rewind()
{
_frame = 0;
_frameElapsed = 0;
_reversed = false;
_repeatedCount = 0;
DrawFrame();
}
///
///
///
///
public void SyncStatus(MovieClip anotherMc)
{
_frame = anotherMc._frame;
_frameElapsed = anotherMc._frameElapsed;
_reversed = anotherMc._reversed;
_repeatedCount = anotherMc._repeatedCount;
DrawFrame();
}
///
///
///
///
public void Advance(float time)
{
int beginFrame = _frame;
bool beginReversed = _reversed;
float backupTime = time;
while (true)
{
float tt = interval + _frames[_frame].addDelay;
if (_frame == 0 && _repeatedCount > 0)
tt += repeatDelay;
if (time < tt)
{
_frameElapsed = 0;
break;
}
time -= tt;
if (swing)
{
if (_reversed)
{
_frame--;
if (_frame <= 0)
{
_frame = 0;
_repeatedCount++;
_reversed = !_reversed;
}
}
else
{
_frame++;
if (_frame > _frameCount - 1)
{
_frame = Mathf.Max(0, _frameCount - 2);
_repeatedCount++;
_reversed = !_reversed;
}
}
}
else
{
_frame++;
if (_frame > _frameCount - 1)
{
_frame = 0;
_repeatedCount++;
}
}
if (_frame == beginFrame && _reversed == beginReversed) //走了一轮了
{
float roundTime = backupTime - time; //这就是一轮需要的时间
time -= Mathf.FloorToInt(time / roundTime) * roundTime; //跳过
}
}
DrawFrame();
}
///
///
///
public void SetPlaySettings()
{
SetPlaySettings(0, -1, 0, -1);
}
///
/// 从start帧开始,播放到end帧(-1表示结尾),重复times次(0表示无限循环),循环结束后,停止在endAt帧(-1表示参数end)
///
///
///
///
///
public void SetPlaySettings(int start, int end, int times, int endAt)
{
_start = start;
_end = end;
if (_end == -1 || _end > _frameCount - 1)
_end = _frameCount - 1;
_times = times;
_endAt = endAt;
if (_endAt == -1)
_endAt = _end;
_status = 0;
this.frame = start;
}
void OnAddedToStage()
{
if (_playing && _frameCount > 0)
Timers.inst.AddUpdate(_timerDelegate);
}
void OnRemoveFromStage()
{
Timers.inst.Remove(_timerDelegate);
}
void CheckTimer()
{
if (!Application.isPlaying)
return;
if (_playing && _frameCount > 0 && this.stage != null)
Timers.inst.AddUpdate(_timerDelegate);
else
Timers.inst.Remove(_timerDelegate);
}
void OnTimer(object param)
{
if (!_playing || _frameCount == 0 || _status == 3)
return;
float dt;
if (ignoreEngineTimeScale)
{
dt = Time.unscaledDeltaTime;
if (dt > 0.1f)
dt = 0.1f;
}
else
dt = Time.deltaTime;
if (timeScale != 1)
dt *= timeScale;
_frameElapsed += dt;
float tt = interval + _frames[_frame].addDelay;
if (_frame == 0 && _repeatedCount > 0)
tt += repeatDelay;
if (_frameElapsed < tt)
return;
_frameElapsed -= tt;
if (_frameElapsed > interval)
_frameElapsed = interval;
if (swing)
{
if (_reversed)
{
_frame--;
if (_frame <= 0)
{
_frame = 0;
_repeatedCount++;
_reversed = !_reversed;
}
}
else
{
_frame++;
if (_frame > _frameCount - 1)
{
_frame = Mathf.Max(0, _frameCount - 2);
_repeatedCount++;
_reversed = !_reversed;
}
}
}
else
{
_frame++;
if (_frame > _frameCount - 1)
{
_frame = 0;
_repeatedCount++;
}
}
if (_status == 1) //new loop
{
_frame = _start;
_frameElapsed = 0;
_status = 0;
DrawFrame();
}
else if (_status == 2) //ending
{
_frame = _endAt;
_frameElapsed = 0;
_status = 3; //ended
DrawFrame();
DispatchEvent("onPlayEnd", null);
}
else
{
DrawFrame();
if (_frame == _end)
{
if (_times > 0)
{
_times--;
if (_times == 0)
_status = 2; //ending
else
_status = 1; //new loop
}
else if (_start != 0)
_status = 1; //new loop
}
}
}
void DrawFrame()
{
if (_frameCount > 0)
{
Frame frame = _frames[_frame];
graphics.texture = frame.texture;
}
}
}
}