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

415 lines
11 KiB
C#
Raw 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 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;
}
}
}
}