//---------------------------------------------- // NGUI: Next-Gen UI kit // Copyright © 2011-2015 Tasharen Entertainment //---------------------------------------------- using UnityEngine; using System.Collections.Generic; /// /// Very simple sprite animation. Attach to a sprite and specify a common prefix such as "idle" and it will cycle through them. /// [ExecuteInEditMode] [RequireComponent(typeof(UISprite))] [AddComponentMenu("NGUI/UI/Sprite Animation")] public class UISpriteAnimation : MonoBehaviour { [HideInInspector][SerializeField] protected int mFPS = 30; [HideInInspector][SerializeField] protected string mPrefix = ""; [HideInInspector][SerializeField] protected bool mLoop = true; [HideInInspector][SerializeField] protected bool mSnap = true; [HideInInspector][SerializeField] protected bool mUseRealTime = false; protected UISprite mSprite; protected float mDelta = 0f; protected int mIndex = 0; protected bool mActive = true; protected List mSpriteNames = null; /// /// Number of frames in the animation. /// public int frames { get { return mSpriteNames != null ? mSpriteNames.Count : 0; } } /// /// Animation framerate. /// public int framesPerSecond { get { return mFPS; } set { mFPS = value; } } /// /// Set the name prefix used to filter sprites from the atlas. /// public string namePrefix { get { return mPrefix; } set { if (mPrefix != value) { mPrefix = value; RebuildSpriteList(); } } } /// /// Set the animation to be looping or not /// public bool loop { get { return mLoop; } set { mLoop = value; } } public bool PrefixSnap { get { return mSnap; } set { mSnap = value; } } /// /// Returns is the animation is still playing or not /// public bool isPlaying { get { return mActive; } } /// /// Rebuild the sprite list first thing. /// protected virtual void Start () { RebuildSpriteList(); } /// /// Advance the sprite animation process. /// protected virtual void Update () { if (mActive && mSpriteNames != null && mSpriteNames.Count > 1 && Application.isPlaying && mFPS > 0) { if(mUseRealTime) { mDelta += RealTime.deltaTime; } else { mDelta += Time.deltaTime; } float rate = 1f / mFPS; if (rate < mDelta) { mDelta = (rate > 0f) ? mDelta - rate : 0f; if (++mIndex >= mSpriteNames.Count) { mIndex = 0; mActive = mLoop; } if (mActive) { mSprite.spriteName = mSpriteNames[mIndex]; if (mSnap) mSprite.MakePixelPerfect(); } } } } /// /// Rebuild the sprite list after changing the sprite name. /// private static Dictionary>> _spriteNameCache = new Dictionary>>(); public void RebuildSpriteList () { if (mSprite == null) mSprite = GetComponent(); if (mSprite != null && mSprite.atlas != null) { var atlasName = mSprite.atlas.name; Dictionary> atlasDic = null; List prefixList = null; if (_spriteNameCache.TryGetValue(atlasName, out atlasDic) && atlasDic.TryGetValue(mPrefix, out prefixList)) { mSpriteNames = prefixList; } else { mSpriteNames = new List(); List sprites = mSprite.atlas.spriteList; for (int i = 0, imax = sprites.Count; i < imax; ++i) { UISpriteData sprite = sprites[i]; if (string.IsNullOrEmpty(mPrefix) || sprite.name.StartsWith(mPrefix)) { mSpriteNames.Add(sprite.name); } } mSpriteNames.Sort(); if(!_spriteNameCache.ContainsKey(atlasName)) { atlasDic = new Dictionary>(); _spriteNameCache.Add(atlasName, atlasDic); } if(!atlasDic.ContainsKey(mPrefix)) { atlasDic.Add(mPrefix, mSpriteNames); } } } } /// /// Reset the animation to the beginning. /// public void Play () { mActive = true; } /// /// Pause the animation. /// public void Pause () { mActive = false; } /// /// Reset the animation to frame 0 and activate it. /// public void ResetToBeginning () { mActive = true; mIndex = 0; if (mSprite != null && mSpriteNames != null && mSpriteNames.Count > 0) { mSprite.spriteName = mSpriteNames[mIndex]; if (mSnap) mSprite.MakePixelPerfect(); } } }