using UnityEngine; using FTRuntime.Internal; namespace FTRuntime { [ExecuteInEditMode, DisallowMultipleComponent] [RequireComponent(typeof(MeshFilter), typeof(MeshRenderer))] public class SwfClip : MonoBehaviour { MeshFilter _meshFilter = null; MeshRenderer _meshRenderer = null; bool _dirtyMesh = true; SwfClipAsset.Sequence _curSequence = null; MaterialPropertyBlock _curPropBlock = null; // --------------------------------------------------------------------- // // Events // // --------------------------------------------------------------------- /// /// Occurs when clip changes /// public event System.Action OnChangeClipEvent; /// /// Occurs when sequence changes /// public event System.Action OnChangeSequenceEvent; /// /// Occurs when current frame changes /// public event System.Action OnChangeCurrentFrameEvent; // --------------------------------------------------------------------- // // Serialized fields // // --------------------------------------------------------------------- [Header("Sorting")] [SerializeField, SwfSortingLayer] string _sortingLayer = string.Empty; [SerializeField] int _sortingOrder = 0; [Header("Animation")] [SerializeField] Color _tint = Color.white; [SerializeField] SwfClipAsset _clip = null; [SerializeField, HideInInspector] string _sequence = string.Empty; [SerializeField, HideInInspector] int _currentFrame = 0; // --------------------------------------------------------------------- // // Properties // // --------------------------------------------------------------------- /// /// Gets or sets the animation mesh renderer sorting layer /// /// The sorting layer public string sortingLayer { get { return _sortingLayer; } set { _sortingLayer = value; ChangeSortingProperties(); } } /// /// Gets or sets the animation mesh renderer sorting order /// /// The sorting order public int sortingOrder { get { return _sortingOrder; } set { _sortingOrder = value; ChangeSortingProperties(); } } /// /// Gets or sets the animation tint color /// /// The tint color public Color tint { get { return _tint; } set { _tint = value; ChangeTint(); } } /// /// Gets or sets the animation asset (reset sequence and current frame) /// /// The animation asset public SwfClipAsset clip { get { return _clip; } set { _clip = value; _sequence = string.Empty; _currentFrame = 0; ChangeClip(); EmitChangeEvents(true, true, true); } } /// /// Gets or sets the animation sequence (reset current frame) /// /// The animation sequence public string sequence { get { return _sequence; } set { _sequence = value; _currentFrame = 0; ChangeSequence(); EmitChangeEvents(false, true, true); } } /// /// Gets or sets the animation current frame /// /// The animation current frame public int currentFrame { get { return _currentFrame; } set { _currentFrame = value; ChangeCurrentFrame(); EmitChangeEvents(false, false, true); } } /// /// Gets the current animation sequence frame count /// /// The frame count public int frameCount { get { return _curSequence != null && _curSequence.Frames != null ? _curSequence.Frames.Count : 0; } } /// /// Gets the animation frame rate /// /// The frame rate public float frameRate { get { return clip ? clip.FrameRate : 0.0f; } } /// /// Gets the current frame label count /// /// The frame label count public int currentLabelCount { get { var baked_frame = GetCurrentBakedFrame(); var frame_labels = baked_frame != null ? baked_frame.Labels : null; return frame_labels != null ? frame_labels.Length : 0; } } // --------------------------------------------------------------------- // // Functions // // --------------------------------------------------------------------- /// /// Rewind current sequence to begin frame /// public void ToBeginFrame() { currentFrame = 0; } /// /// Rewind current sequence to end frame /// public void ToEndFrame() { currentFrame = frameCount > 0 ? frameCount - 1 : 0; } /// /// Rewind current sequence to previous frame /// /// true, if animation was rewound, false otherwise public bool ToPrevFrame() { if ( currentFrame > 0 ) { --currentFrame; return true; } return false; } /// /// Rewind current sequence to next frame /// /// true, if animation was rewound, false otherwise public bool ToNextFrame() { if ( currentFrame < frameCount - 1 ) { ++currentFrame; return true; } return false; } /// /// Gets the current frame label by index /// /// The current frame label /// Current frame label index public string GetCurrentFrameLabel(int index) { var baked_frame = GetCurrentBakedFrame(); var frame_labels = baked_frame != null ? baked_frame.Labels : null; return frame_labels != null && index >= 0 && index < frame_labels.Length ? frame_labels[index] : string.Empty; } // --------------------------------------------------------------------- // // Internal // // --------------------------------------------------------------------- internal void Internal_LateUpdate() { if ( _meshFilter && _meshRenderer && _dirtyMesh ) { var baked_frame = GetCurrentBakedFrame(); if ( baked_frame != null ) { _meshFilter .sharedMesh = baked_frame.CachedMesh; _meshRenderer.sharedMaterials = baked_frame.Materials; } else { _meshFilter .sharedMesh = null; _meshRenderer.sharedMaterials = new Material[0]; } _dirtyMesh = false; } } /// /// Update all animation properties (for internal use only) /// public void Internal_UpdateAllProperties() { ClearCache(); ChangeTint(); ChangeClip(); ChangeSequence(); ChangeCurrentFrame(); ChangeSortingProperties(); } void ClearCache() { _meshFilter = GetComponent(); _meshRenderer = GetComponent(); _dirtyMesh = true; _curSequence = null; _curPropBlock = null; } void ChangeTint() { UpdatePropBlock(); } void ChangeClip() { if ( _meshRenderer ) { _meshRenderer.enabled = !!clip; } ChangeSequence(); UpdatePropBlock(); } void ChangeSequence() { _curSequence = null; if ( clip && clip.Sequences != null ) { if ( !string.IsNullOrEmpty(sequence) ) { for ( int i = 0, e = clip.Sequences.Count; i < e; ++i ) { var clip_sequence = clip.Sequences[i]; if ( clip_sequence != null && clip_sequence.Name == sequence ) { _curSequence = clip_sequence; break; } } if ( _curSequence == null ) { Debug.LogWarningFormat(this, "[FlashTools] Sequence '{0}' not found", sequence); } } if ( _curSequence == null ) { for ( int i = 0, e = clip.Sequences.Count; i < e; ++i ) { var clip_sequence = clip.Sequences[i]; if ( clip_sequence != null ) { _sequence = clip_sequence.Name; _curSequence = clip_sequence; break; } } } } ChangeCurrentFrame(); } void ChangeCurrentFrame() { _dirtyMesh = true; _currentFrame = frameCount > 0 ? Mathf.Clamp(currentFrame, 0, frameCount - 1) : 0; } void ChangeSortingProperties() { if ( _meshRenderer ) { _meshRenderer.sortingOrder = sortingOrder; _meshRenderer.sortingLayerName = sortingLayer; } } void UpdatePropBlock() { if ( _meshRenderer ) { if ( _curPropBlock == null ) { _curPropBlock = new MaterialPropertyBlock(); } _meshRenderer.GetPropertyBlock(_curPropBlock); _curPropBlock.SetColor("_Tint", tint); var sprite = clip ? clip.Sprite : null; var atlas = sprite && sprite.texture ? sprite.texture : Texture2D.whiteTexture; var atlasA = sprite ? sprite.associatedAlphaSplitTexture : null; _curPropBlock.SetTexture( "_MainTex", atlas ? atlas : Texture2D.whiteTexture); if ( atlasA ) { _curPropBlock.SetTexture("_AlphaTex", atlasA); _curPropBlock.SetFloat("_ExternalAlpha", 1.0f); } else { _curPropBlock.SetTexture("_AlphaTex", Texture2D.whiteTexture); _curPropBlock.SetFloat("_ExternalAlpha", 0.0f); } _meshRenderer.SetPropertyBlock(_curPropBlock); } } void EmitChangeEvents(bool clip, bool sequence, bool current_frame) { if ( clip && OnChangeClipEvent != null ) { OnChangeClipEvent(this); } if ( sequence && OnChangeSequenceEvent != null ) { OnChangeSequenceEvent(this); } if ( current_frame && OnChangeCurrentFrameEvent != null ) { OnChangeCurrentFrameEvent(this); } } SwfClipAsset.Frame GetCurrentBakedFrame() { var frames = _curSequence != null ? _curSequence.Frames : null; return frames != null && currentFrame >= 0 && currentFrame < frames.Count ? frames[currentFrame] : null; } // --------------------------------------------------------------------- // // Messages // // --------------------------------------------------------------------- void Awake() { Internal_UpdateAllProperties(); } void Start() { EmitChangeEvents(true, true, true); } void OnEnable() { var swf_manager = SwfManager.GetInstance(true); if ( swf_manager ) { swf_manager.AddClip(this); } } void OnDisable() { var swf_manager = SwfManager.GetInstance(false); if ( swf_manager ) { swf_manager.RemoveClip(this); } } void Reset() { Internal_UpdateAllProperties(); } void OnValidate() { Internal_UpdateAllProperties(); } } }