UniGifImage.cs 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  1. /*
  2. UniGif
  3. Copyright (c) 2015 WestHillApps (Hironari Nishioka)
  4. This software is released under the MIT License.
  5. http://opensource.org/licenses/mit-license.php
  6. */
  7. using System.Collections;
  8. using System.Collections.Generic;
  9. using System.IO;
  10. using UnityEngine;
  11. using UnityEngine.Networking;
  12. using UnityEngine.UI;
  13. /// <summary>
  14. /// Texture Animation from GIF image
  15. /// </summary>
  16. [RequireComponent(typeof(UniGifImageAspectController))]
  17. public class UniGifImage : MonoBehaviour
  18. {
  19. /// <summary>
  20. /// This component state
  21. /// </summary>
  22. public enum State
  23. {
  24. None,
  25. Loading,
  26. Ready,
  27. Playing,
  28. Pause,
  29. }
  30. // Target row image
  31. [SerializeField]
  32. private RawImage m_rawImage;
  33. // Image Aspect Controller
  34. [SerializeField]
  35. private UniGifImageAspectController m_imgAspectCtrl;
  36. // Textures filter mode
  37. [SerializeField]
  38. private FilterMode m_filterMode = FilterMode.Point;
  39. // Textures wrap mode
  40. [SerializeField]
  41. private TextureWrapMode m_wrapMode = TextureWrapMode.Clamp;
  42. // Load from url on start
  43. [SerializeField]
  44. private bool m_loadOnStart;
  45. // GIF image url (WEB or StreamingAssets path)
  46. [SerializeField]
  47. private string m_loadOnStartUrl;
  48. // Rotating on loading
  49. [SerializeField]
  50. private bool m_rotateOnLoading;
  51. // Debug log flag
  52. [SerializeField]
  53. private bool m_outputDebugLog;
  54. // Decoded GIF texture list
  55. private List<UniGif.GifTexture> m_gifTextureList;
  56. // Delay time
  57. private float m_delayTime;
  58. // Texture index
  59. private int m_gifTextureIndex;
  60. // loop counter
  61. private int m_nowLoopCount;
  62. /// <summary>
  63. /// Now state
  64. /// </summary>
  65. public State nowState
  66. {
  67. get;
  68. private set;
  69. }
  70. /// <summary>
  71. /// Animation loop count (0 is infinite)
  72. /// </summary>
  73. public int loopCount
  74. {
  75. get;
  76. private set;
  77. }
  78. /// <summary>
  79. /// Texture width (px)
  80. /// </summary>
  81. public int width
  82. {
  83. get;
  84. private set;
  85. }
  86. /// <summary>
  87. /// Texture height (px)
  88. /// </summary>
  89. public int height
  90. {
  91. get;
  92. private set;
  93. }
  94. private void Start()
  95. {
  96. if (m_rawImage == null)
  97. {
  98. m_rawImage = GetComponent<RawImage>();
  99. }
  100. if (m_loadOnStart)
  101. {
  102. SetGifFromUrl(m_loadOnStartUrl);
  103. }
  104. }
  105. private void OnDestroy()
  106. {
  107. Clear();
  108. }
  109. private void Update()
  110. {
  111. switch (nowState)
  112. {
  113. case State.None:
  114. break;
  115. case State.Loading:
  116. if (m_rotateOnLoading)
  117. {
  118. transform.Rotate(0f, 0f, 30f * Time.deltaTime, Space.Self);
  119. }
  120. break;
  121. case State.Ready:
  122. break;
  123. case State.Playing:
  124. if (m_rawImage == null || m_gifTextureList == null || m_gifTextureList.Count <= 0)
  125. {
  126. return;
  127. }
  128. if (m_delayTime > Time.time)
  129. {
  130. return;
  131. }
  132. // Change texture
  133. m_gifTextureIndex++;
  134. if (m_gifTextureIndex >= m_gifTextureList.Count)
  135. {
  136. m_gifTextureIndex = 0;
  137. if (loopCount > 0)
  138. {
  139. m_nowLoopCount++;
  140. if (m_nowLoopCount >= loopCount)
  141. {
  142. Stop();
  143. return;
  144. }
  145. }
  146. }
  147. m_rawImage.texture = m_gifTextureList[m_gifTextureIndex].m_texture2d;
  148. m_delayTime = Time.time + m_gifTextureList[m_gifTextureIndex].m_delaySec;
  149. break;
  150. case State.Pause:
  151. break;
  152. default:
  153. break;
  154. }
  155. }
  156. /// <summary>
  157. /// Set GIF texture from url
  158. /// </summary>
  159. /// <param name="url">GIF image url (WEB or StreamingAssets path)</param>
  160. /// <param name="autoPlay">Auto play after decode</param>
  161. public void SetGifFromUrl(string url, bool autoPlay = true)
  162. {
  163. StartCoroutine(SetGifFromUrlCoroutine(url, autoPlay));
  164. }
  165. /// <summary>
  166. /// Set GIF texture from url
  167. /// </summary>
  168. /// <param name="url">GIF image url (WEB or StreamingAssets path)</param>
  169. /// <param name="autoPlay">Auto play after decode</param>
  170. /// <returns>IEnumerator</returns>
  171. public IEnumerator SetGifFromUrlCoroutine(string url, bool autoPlay = true)
  172. {
  173. if (string.IsNullOrEmpty(url))
  174. {
  175. Debug.LogError("URL is nothing.");
  176. yield break;
  177. }
  178. if (nowState == State.Loading)
  179. {
  180. Debug.LogWarning("Already loading.");
  181. yield break;
  182. }
  183. nowState = State.Loading;
  184. string path;
  185. if (url.StartsWith("http"))
  186. {
  187. // from WEB
  188. path = url;
  189. }
  190. else
  191. {
  192. // from StreamingAssets
  193. path = Path.Combine("file:///" + Application.streamingAssetsPath, url);
  194. }
  195. // Load file
  196. UnityWebRequest request = UnityWebRequest.Get(path);
  197. request.SendWebRequest();
  198. while (!request.isDone)
  199. {
  200. yield return null;
  201. }
  202. if (string.IsNullOrEmpty(request.error) == false)
  203. {
  204. Debug.LogError("File load error.\n" + request.error + "\npath: " + path);
  205. nowState = State.None;
  206. yield break;
  207. }
  208. Clear();
  209. nowState = State.Loading;
  210. // Get GIF textures
  211. yield return StartCoroutine(UniGif.GetTextureListCoroutine(request.downloadHandler.data, (gifTexList, loopCount, width, height) =>
  212. {
  213. request.Dispose();
  214. if (gifTexList != null)
  215. {
  216. m_gifTextureList = gifTexList;
  217. this.loopCount = loopCount;
  218. this.width = width;
  219. this.height = height;
  220. nowState = State.Ready;
  221. m_imgAspectCtrl.FixAspectRatio(width, height);
  222. if (m_rotateOnLoading)
  223. {
  224. transform.localEulerAngles = Vector3.zero;
  225. }
  226. if (autoPlay)
  227. {
  228. Play();
  229. }
  230. }
  231. else
  232. {
  233. Debug.LogError("Gif texture get error.");
  234. nowState = State.None;
  235. }
  236. },
  237. m_filterMode, m_wrapMode, m_outputDebugLog));
  238. }
  239. /// <summary>
  240. /// Clear GIF texture
  241. /// </summary>
  242. public void Clear()
  243. {
  244. if (m_rawImage != null)
  245. {
  246. m_rawImage.texture = null;
  247. }
  248. if (m_gifTextureList != null)
  249. {
  250. for (int i = 0; i < m_gifTextureList.Count; i++)
  251. {
  252. if (m_gifTextureList[i] != null)
  253. {
  254. if (m_gifTextureList[i].m_texture2d != null)
  255. {
  256. Destroy(m_gifTextureList[i].m_texture2d);
  257. m_gifTextureList[i].m_texture2d = null;
  258. }
  259. m_gifTextureList[i] = null;
  260. }
  261. }
  262. m_gifTextureList.Clear();
  263. m_gifTextureList = null;
  264. }
  265. nowState = State.None;
  266. }
  267. /// <summary>
  268. /// Play GIF animation
  269. /// </summary>
  270. public void Play()
  271. {
  272. if (nowState != State.Ready)
  273. {
  274. Debug.LogWarning("State is not READY.");
  275. return;
  276. }
  277. if (m_rawImage == null || m_gifTextureList == null || m_gifTextureList.Count <= 0)
  278. {
  279. Debug.LogError("Raw Image or GIF Texture is nothing.");
  280. return;
  281. }
  282. nowState = State.Playing;
  283. m_rawImage.texture = m_gifTextureList[0].m_texture2d;
  284. m_delayTime = Time.time + m_gifTextureList[0].m_delaySec;
  285. m_gifTextureIndex = 0;
  286. m_nowLoopCount = 0;
  287. }
  288. /// <summary>
  289. /// Stop GIF animation
  290. /// </summary>
  291. public void Stop()
  292. {
  293. if (nowState != State.Playing && nowState != State.Pause)
  294. {
  295. Debug.LogWarning("State is not Playing and Pause.");
  296. return;
  297. }
  298. nowState = State.Ready;
  299. }
  300. /// <summary>
  301. /// Pause GIF animation
  302. /// </summary>
  303. public void Pause()
  304. {
  305. if (nowState != State.Playing)
  306. {
  307. Debug.LogWarning("State is not Playing.");
  308. return;
  309. }
  310. nowState = State.Pause;
  311. }
  312. /// <summary>
  313. /// Resume GIF animation
  314. /// </summary>
  315. public void Resume()
  316. {
  317. if (nowState != State.Pause)
  318. {
  319. Debug.LogWarning("State is not Pause.");
  320. return;
  321. }
  322. nowState = State.Playing;
  323. }
  324. }