using System; using System.Collections; using System.Collections.Generic; using System.IO; using System.Linq; using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Tasks; using UnityEngine; using UnityEngine.Networking; using UnityEngine.UI; using WebP; public class WebpImporter : MonoBehaviour { public static async void LoadWebpTexture2D(string path, Action callback) { byte[] bytes = await LoadAsyncBytes(path); LoadWebpTexture2D(bytes, callback); } public static void ByteWebpTexture2D(byte[] bytes, Action callback) { LoadWebpTexture2D(bytes, callback); } public static void LoadWebpTexture2D(byte[] bytes, Action callback) { WebP.Error lError; var texture = Texture2DExt.CreateTexture2DFromWebP(bytes, lMipmaps: false, lLinear: true, lError: out lError); if (callback != null) { callback(texture); } } public static async void PlayWebpAnimation(string path, Action callback) { byte[] bytes = await LoadAsyncBytes(path); PlayWebpAnimation(bytes, callback); } public static async void PlayWebpAnimation(byte[] bytes, Action callback) { List<(Texture2D, int)> lst = Texture2DExt.LoadTexture2DFromWebP(bytes); int prevTimestamp = 0; for (int i = 0; i < lst.Count; ++i) { (Texture2D texture, int timestamp) = lst[i]; if (texture == null) return; if (callback != null) { callback(texture); } int delay = timestamp - prevTimestamp; prevTimestamp = timestamp; if (delay < 0) { delay = 0; } await Task.Delay(delay); if (i == lst.Count - 1) { i = -1; } } } public static async void LoadWebp(string path, Action callback) { byte[] bytes = await LoadAsyncBytes(path); if (!isAnimationWebp(bytes)) { LoadWebpTexture2D(bytes, callback); } else { PlayWebpAnimation(bytes, callback); } } public static IEnumerator PlayWebpAnimationWebGL(string loadPath, Action callback) { var webRequest = UnityWebRequest.Get(loadPath); webRequest.timeout = 30; yield return webRequest.SendWebRequest(); if (webRequest.result != UnityWebRequest.Result.ConnectionError) { byte[] bytes = webRequest.downloadHandler.data; List<(Texture2D, int)> lst = Texture2DExt.LoadTexture2DFromWebP(bytes); int prevTimestamp = 0; for (int i = 0; i < lst.Count; ++i) { (Texture2D texture, int timestamp) = lst[i]; if (callback != null) { callback(texture); } int delay = timestamp - prevTimestamp; prevTimestamp = timestamp; if (delay < 0) { delay = 0; } yield return new WaitForSeconds(delay / 1000.0f); if (i == lst.Count - 1) { i = -1; } } } } static async Task LoadAsyncBytes(string url) { var getRequest = UnityWebRequest.Get(url); await getRequest.SendWebRequest(); return getRequest.downloadHandler.data; ; } #region isAnimationWebp /// /// Use byte[] data to determine whether the webp file is a dynamic image or a static image /// 通过byte[]数据判断webp文件是动态图片还是静态图片 /// /// /// public static bool isAnimationWebp(byte[] webpData) { byte[] anmf = new byte[] { 65, 78, 77, 70 }; List sourceList = webpData.ToList(); int index = 0; return isContainBytes(sourceList, anmf, ref index); } private static bool isContainBytes(List sourceList, byte[] search, ref int index) { index = sourceList.IndexOf(search[0], index); if (index < 0) return false; if (search.Length == 1) return true; bool isContain = false; for (int i = 1; i < search.Length; i++) { if (sourceList[index + i] != search[i]) { isContain = false; break; } else isContain = true; } if (!isContain) { index += 1; return isContainBytes(sourceList, search, ref index); } return true; } public static void ByteWebpTexture2D(byte[] webPData, RawImage rawImage) { throw new NotImplementedException(); } #endregion } public static class ExtensionMethods { public static TaskAwaiter GetAwaiter(this AsyncOperation asyncOp) { var tcs = new TaskCompletionSource(); asyncOp.completed += obj => { tcs.SetResult(null); }; return ((Task)tcs.Task).GetAwaiter(); } }