using UnityEngine; using FTRuntime.Internal; namespace FTRuntime { [ExecuteInEditMode, DisallowMultipleComponent] [RequireComponent(typeof(SwfClip))] public class SwfClipController : MonoBehaviour { SwfClip _clip = null; bool _isPlaying = false; float _tickTimer = 0.0f; // --------------------------------------------------------------------- // // Events // // --------------------------------------------------------------------- /// /// Occurs when the controller stops played clip /// public event System.Action OnStopPlayingEvent; /// /// Occurs when the controller plays stopped clip /// public event System.Action OnPlayStoppedEvent; /// /// Occurs when the controller rewinds played clip /// public event System.Action OnRewindPlayingEvent; // --------------------------------------------------------------------- // // Serialized fields // // --------------------------------------------------------------------- [SerializeField] bool _autoPlay = true; [SerializeField] bool _useUnscaledDt = false; [SerializeField, SwfFloatRange(0.0f, float.MaxValue)] float _rateScale = 1.0f; [SerializeField] string _groupName = string.Empty; [SerializeField] PlayModes _playMode = PlayModes.Forward; [SerializeField] LoopModes _loopMode = LoopModes.Loop; // --------------------------------------------------------------------- // // Properties // // --------------------------------------------------------------------- /// /// Controller play modes /// public enum PlayModes { /// /// Forward play mode /// Forward, /// /// Backward play mode /// Backward } /// /// Controller loop modes /// public enum LoopModes { /// /// Once loop mode /// Once, /// /// Repeat loop mode /// Loop } /// /// Gets or sets a value indicating whether controller play after awake on scene /// /// true if auto play; otherwise, false public bool autoPlay { get { return _autoPlay; } set { _autoPlay = value; } } /// /// Gets or sets a value indicating whether controller uses unscaled delta time /// /// true if uses unscaled delta time; otherwise, false public bool useUnscaledDt { get { return _useUnscaledDt; } set { _useUnscaledDt = value; } } /// /// Gets or sets the controller rate scale /// /// The rate scale public float rateScale { get { return _rateScale; } set { _rateScale = Mathf.Clamp(value, 0.0f, float.MaxValue); } } /// /// Gets or sets the controller group name /// /// The group name public string groupName { get { return _groupName; } set { _groupName = value; } } /// /// Gets or sets the controller play mode /// /// The play mode public PlayModes playMode { get { return _playMode; } set { _playMode = value; } } /// /// Gets or sets the controller loop mode /// /// The loop mode public LoopModes loopMode { get { return _loopMode; } set { _loopMode = value; } } /// /// Gets the controller clip /// /// The clip public SwfClip clip { get { return _clip; } } /// /// Gets a value indicating whether controller is playing /// /// true if is playing; otherwise, false public bool isPlaying { get { return _isPlaying; } } /// /// Gets a value indicating whether controller is stopped /// /// true if is stopped; otherwise, false public bool isStopped { get { return !_isPlaying; } } // --------------------------------------------------------------------- // // Functions // // --------------------------------------------------------------------- /// /// Changes the animation frame with stops it /// /// The new current frame public void GotoAndStop(int frame) { if ( clip ) { clip.currentFrame = frame; } Stop(false); } /// /// Changes the animation sequence and frame with stops it /// /// The new sequence /// The new current frame public void GotoAndStop(string sequence, int frame) { if ( clip ) { clip.sequence = sequence; } GotoAndStop(frame); } /// /// Changes the animation frame with plays it /// /// The new current frame public void GotoAndPlay(int frame) { if ( clip ) { clip.currentFrame = frame; } Play(false); } /// /// Changes the animation sequence and frame with plays it /// /// The new sequence /// The new current frame public void GotoAndPlay(string sequence, int frame) { if ( clip ) { clip.sequence = sequence; } GotoAndPlay(frame); } /// /// Stop with specified rewind action /// /// If set to true rewind animation to begin frame public void Stop(bool rewind) { var is_playing = isPlaying; if ( is_playing ) { _isPlaying = false; _tickTimer = 0.0f; } if ( rewind ) { Rewind(); } if ( is_playing && OnStopPlayingEvent != null ) { OnStopPlayingEvent(this); } } /// /// Changes the animation sequence and stop controller with rewind /// /// The new sequence public void Stop(string sequence) { if ( clip ) { clip.sequence = sequence; } Stop(true); } /// /// Play with specified rewind action /// /// If set to true rewind animation to begin frame public void Play(bool rewind) { var is_stopped = isStopped; if ( is_stopped ) { _isPlaying = true; _tickTimer = 0.0f; } if ( rewind ) { Rewind(); } if ( is_stopped && OnPlayStoppedEvent != null ) { OnPlayStoppedEvent(this); } } /// /// Changes the animation sequence and play controller with rewind /// /// The new sequence public void Play(string sequence) { if ( clip ) { clip.sequence = sequence; } Play(true); } /// /// Rewind animation to begin frame /// public void Rewind() { switch ( playMode ) { case PlayModes.Forward: if ( clip ) { clip.ToBeginFrame(); } break; case PlayModes.Backward: if ( clip ) { clip.ToEndFrame(); } break; default: throw new UnityException(string.Format( "SwfClipController. Incorrect play mode: {0}", playMode)); } if ( isPlaying && OnRewindPlayingEvent != null ) { OnRewindPlayingEvent(this); } } // --------------------------------------------------------------------- // // Internal // // --------------------------------------------------------------------- internal void Internal_Update(float scaled_dt, float unscaled_dt) { if ( isPlaying ) { _tickTimer += useUnscaledDt ? unscaled_dt : scaled_dt; do { var frame_rate = clip ? clip.frameRate * rateScale : 0.0f; var frame_time = frame_rate > 0.0f ? 1.0f / frame_rate : 0.0f; if ( frame_time > 0.0f && frame_time <= _tickTimer ) { _tickTimer -= frame_time; TimerTick(); } else { break; } } while ( isPlaying ); } } void TimerTick() { if ( !NextClipFrame() ) { switch ( loopMode ) { case LoopModes.Once: Stop(false); break; case LoopModes.Loop: Rewind(); break; default: throw new UnityException(string.Format( "SwfClipController. Incorrect loop mode: {0}", loopMode)); } } } bool NextClipFrame() { switch ( playMode ) { case PlayModes.Forward: return clip ? clip.ToNextFrame() : false; case PlayModes.Backward: return clip ? clip.ToPrevFrame() : false; default: throw new UnityException(string.Format( "SwfClipController. Incorrect play mode: {0}", playMode)); } } // --------------------------------------------------------------------- // // Messages // // --------------------------------------------------------------------- void Awake() { _clip = GetComponent(); } void OnEnable() { var swf_manager = SwfManager.GetInstance(true); if ( swf_manager ) { swf_manager.AddController(this); } if ( autoPlay && Application.isPlaying ) { Play(false); } } void OnDisable() { Stop(false); var swf_manager = SwfManager.GetInstance(false); if ( swf_manager ) { swf_manager.RemoveController(this); } } } }