415 lines
11 KiB
C#
415 lines
11 KiB
C#
using UnityEngine;
|
||
|
||
namespace FairyGUI
|
||
{
|
||
/// <summary>
|
||
///
|
||
/// </summary>
|
||
public class MovieClip : Image
|
||
{
|
||
/// <summary>
|
||
///
|
||
/// </summary>
|
||
public class Frame
|
||
{
|
||
public NTexture texture;
|
||
public float addDelay;
|
||
}
|
||
|
||
/// <summary>
|
||
///
|
||
/// </summary>
|
||
public float interval;
|
||
|
||
/// <summary>
|
||
///
|
||
/// </summary>
|
||
public bool swing;
|
||
|
||
/// <summary>
|
||
///
|
||
/// </summary>
|
||
public float repeatDelay;
|
||
|
||
/// <summary>
|
||
///
|
||
/// </summary>
|
||
public float timeScale;
|
||
|
||
/// <summary>
|
||
/// Whether to ignore Unity time scale.
|
||
/// </summary>
|
||
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;
|
||
|
||
/// <summary>
|
||
///
|
||
/// </summary>
|
||
public MovieClip()
|
||
{
|
||
interval = 0.1f;
|
||
_playing = true;
|
||
_timerDelegate = OnTimer;
|
||
timeScale = 1;
|
||
ignoreEngineTimeScale = false;
|
||
|
||
if (Application.isPlaying)
|
||
{
|
||
onAddedToStage.Add(OnAddedToStage);
|
||
onRemovedFromStage.Add(OnRemoveFromStage);
|
||
}
|
||
|
||
SetPlaySettings();
|
||
}
|
||
|
||
/// <summary>
|
||
///
|
||
/// </summary>
|
||
public EventListener onPlayEnd
|
||
{
|
||
get { return _onPlayEnd ?? (_onPlayEnd = new EventListener(this, "onPlayEnd")); }
|
||
}
|
||
|
||
/// <summary>
|
||
///
|
||
/// </summary>
|
||
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();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
///
|
||
/// </summary>
|
||
public bool playing
|
||
{
|
||
get { return _playing; }
|
||
set
|
||
{
|
||
if (_playing != value)
|
||
{
|
||
_playing = value;
|
||
CheckTimer();
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
///
|
||
/// </summary>
|
||
public int frame
|
||
{
|
||
get { return _frame; }
|
||
set
|
||
{
|
||
if (_frame != value)
|
||
{
|
||
if (_frames != null && value >= _frameCount)
|
||
value = _frameCount - 1;
|
||
|
||
_frame = value;
|
||
_frameElapsed = 0;
|
||
DrawFrame();
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
///
|
||
/// </summary>
|
||
public void Rewind()
|
||
{
|
||
_frame = 0;
|
||
_frameElapsed = 0;
|
||
_reversed = false;
|
||
_repeatedCount = 0;
|
||
DrawFrame();
|
||
}
|
||
|
||
/// <summary>
|
||
///
|
||
/// </summary>
|
||
/// <param name="anotherMc"></param>
|
||
public void SyncStatus(MovieClip anotherMc)
|
||
{
|
||
_frame = anotherMc._frame;
|
||
_frameElapsed = anotherMc._frameElapsed;
|
||
_reversed = anotherMc._reversed;
|
||
_repeatedCount = anotherMc._repeatedCount;
|
||
DrawFrame();
|
||
}
|
||
|
||
/// <summary>
|
||
///
|
||
/// </summary>
|
||
/// <param name="time"></param>
|
||
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();
|
||
}
|
||
|
||
/// <summary>
|
||
///
|
||
/// </summary>
|
||
public void SetPlaySettings()
|
||
{
|
||
SetPlaySettings(0, -1, 0, -1);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 从start帧开始,播放到end帧(-1表示结尾),重复times次(0表示无限循环),循环结束后,停止在endAt帧(-1表示参数end)
|
||
/// </summary>
|
||
/// <param name="start"></param>
|
||
/// <param name="end"></param>
|
||
/// <param name="times"></param>
|
||
/// <param name="endAt"></param>
|
||
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;
|
||
}
|
||
}
|
||
}
|
||
}
|