public void Queue(TextureDownloadInfo emote) { if (emote.type == ImageType.BTTV_Animated || emote.type == ImageType.Cheermote) { _animationDownloadQueue.Enqueue(emote); } else { _imageDownloadQueue.Enqueue(emote); } }
public static IEnumerator PreloadAnimatedEmotes() { int count = 0; foreach (string emoteIndex in BTTVAnimatedEmoteIDs.Values) { if (!Plugin.Instance.IsAtMainMenu) { yield return(new WaitUntil(() => Plugin.Instance.IsAtMainMenu)); } if (!CachedTextures.ContainsKey(emoteIndex)) { TextureDownloadInfo downloadInfo = new TextureDownloadInfo("AB" + emoteIndex, ImageType.BTTV_Animated, "!NOTSET!"); //Plugin.Log($"Precaching {emoteIndex}"); Instance.Queue(downloadInfo); count++; yield return(new WaitUntil(() => !Instance._animationDownloadQueue.Contains(downloadInfo))); } } Plugin.Log($"Precached {count.ToString()} animated emotes successfully!"); }
public static IEnumerator Download(string imagePath, TextureDownloadInfo imageDownloadInfo, bool isRetry = false) { bool isAnimated = imageDownloadInfo.type == ImageType.BTTV_Animated || imageDownloadInfo.type == ImageType.Cheermote; if (!CachedTextures.ContainsKey(imageDownloadInfo.spriteIndex)) { int _waitForFrames = 5; //Plugin.Log($"Downloading {imageDownloadInfo.spriteIndex}"); if (isAnimated) { Instance._animatedImageDownloading = true; } else { Instance._imageDownloading = true; } Sprite sprite = null; if (imageDownloadInfo.type != ImageType.Emoji) { string origImagePath = imagePath; string imageCachePath = "Cache\\Images"; string oldSpriteCachePath = "Cache\\Sprites"; // Migrate our cached sprites/images into our renamed "Images" folder if (Directory.Exists(oldSpriteCachePath)) { if (!Directory.Exists(imageCachePath)) { Directory.Move(oldSpriteCachePath, imageCachePath); } else { Directory.Delete(oldSpriteCachePath, true); } } if (!Directory.Exists(imageCachePath)) { Directory.CreateDirectory(imageCachePath); } string typePath = $"{imageCachePath}\\{ImageTypeNames.Get(imageDownloadInfo.type)}"; if (!Directory.Exists(typePath)) { Directory.CreateDirectory(typePath); } bool localPathExists = false; string localFilePath = $"{typePath}\\{imageDownloadInfo.spriteIndex}"; if (File.Exists(localFilePath)) { localPathExists = true; imagePath = $"{Path.GetDirectoryName(Assembly.GetExecutingAssembly().CodeBase).Replace("\\Plugins", "")}\\{localFilePath}"; } using (var web = UnityWebRequestTexture.GetTexture(imagePath, true)) { yield return(web.SendWebRequest()); if (web.isNetworkError || web.isHttpError) { Plugin.Log($"An error occured when requesting emote {imageDownloadInfo.spriteIndex}, Message: \"{web.error}\""); CachedTextures.TryAdd(imageDownloadInfo.spriteIndex, null); if (isAnimated) { Instance._animatedImageDownloading = false; } else { Instance._imageDownloading = false; } yield break; } else if (isAnimated) { CachedTextures.TryAdd(imageDownloadInfo.spriteIndex, null); yield return(AnimationDecoder.Process(web.downloadHandler.data, ChatHandler.Instance.OverlayAnimatedImage, imageDownloadInfo)); if (!localPathExists) { ImageSaveQueue.Enqueue(new TextureSaveInfo(localFilePath, web.downloadHandler.data)); } _waitForFrames = 10; while (_waitForFrames > 0) { _waitForFrames--; yield return(null); } Instance._animatedImageDownloading = false; yield break; } else { sprite = UIUtilities.LoadSpriteFromTexture(DownloadHandlerTexture.GetContent(web)); if (sprite) { if (!localPathExists) { ImageSaveQueue.Enqueue(new TextureSaveInfo(localFilePath, web.downloadHandler.data)); } } } } } else { sprite = UIUtilities.LoadSpriteFromResources($"EnhancedTwitchChat.Resources.Emojis.{imageDownloadInfo.spriteIndex.ToLower()}"); } if (sprite) { CachedTextures.TryAdd(imageDownloadInfo.spriteIndex, new CachedSpriteData(sprite, sprite.texture.width, sprite.texture.height)); yield return(null); ChatHandler.Instance.OverlayImage(sprite, imageDownloadInfo); } _waitForFrames = 5; while (_waitForFrames > 0) { _waitForFrames--; yield return(null); } Instance._imageDownloading = false; } }
public static IEnumerator Process(byte[] gifData, Action <Texture2D, Rect[], float, TextureDownloadInfo> callback, TextureDownloadInfo imageDownloadInfo) { Plugin.Log($"Started decoding gif {imageDownloadInfo.spriteIndex}"); List <Texture2D> texList = new List <Texture2D>(); GifInfo frameInfo = new GifInfo(); DateTime startTime = DateTime.Now; Task.Run(() => ProcessingThread(gifData, ref frameInfo)); yield return(new WaitUntil(() => { return frameInfo.initialized; })); int textureSize = 2048; Texture2D texture = null; float delay = -1f; for (int i = 0; i < frameInfo.frameCount; i++) { yield return(new WaitUntil(() => { return frameInfo.frames.Count > i; })); //Plugin.Log($"Frame {i} is ready for processing! Frame is {frameInfo.frames[i].frame.Width}x{frameInfo.frames[i].frame.Height}"); if (texture == null) { textureSize = GetTextureSize(frameInfo, i); texture = new Texture2D(textureSize, textureSize); } FrameInfo currentFrameInfo = frameInfo.frames[i]; if (delay == -1f) { delay = currentFrameInfo.delay; } var frameTexture = new Texture2D(currentFrameInfo.frame.Width, currentFrameInfo.frame.Height); try { int colorIndex = 0; Color32[] colors = new Color32[currentFrameInfo.frame.Width * currentFrameInfo.frame.Height]; for (int x = 0; x < currentFrameInfo.frame.Width; x++) { for (int y = 0; y < currentFrameInfo.frame.Height; y++) { System.Drawing.Color sourceColor = currentFrameInfo.colors[colorIndex]; colors[(currentFrameInfo.frame.Height - y - 1) * currentFrameInfo.frame.Width + x] = new Color32(sourceColor.R, sourceColor.G, sourceColor.B, sourceColor.A); colorIndex++; } } frameTexture.wrapMode = TextureWrapMode.Clamp; frameTexture.SetPixels32(colors); frameTexture.Apply(i == 0); } catch (Exception e) { Plugin.Log($"Exception while decoding gif! Frame: {i}, Exception: {e}"); yield break; } yield return(null); texList.Add(frameTexture); // Instant callback after we decode the first frame in order to display a still image until the animated one is finished loading if (i == 0) { callback?.Invoke(frameTexture, texture.PackTextures(new Texture2D[] { frameTexture }, 2, textureSize, true), delay, imageDownloadInfo); } } Rect[] atlas = texture.PackTextures(texList.ToArray(), 2, textureSize, true); yield return(null); callback?.Invoke(texture, atlas, delay, imageDownloadInfo); Plugin.Log($"Finished decoding gif {imageDownloadInfo.spriteIndex}! Elapsed time: {(DateTime.Now - startTime).TotalSeconds} seconds."); }