public static IEnumerator DownloadAnimated(string imagePath, TextureDownloadInfo imageDownloadInfo, bool isRetry = false) { if (!CachedTextures.ContainsKey(imageDownloadInfo.spriteIndex)) { byte[] animData = null; int _waitForFrames = 10; bool localPathExists = ImageExistsLocally(ref imagePath, imageDownloadInfo, out var localFilePath); yield return(Utilities.Download(imagePath, Utilities.DownloadType.Raw, null, (web) => { animData = web.downloadHandler.data; })); if (animData != null) { CachedTextures.TryAdd(imageDownloadInfo.spriteIndex, null); yield return(AnimationDecoder.Process(animData, ChatHandler.Instance.OverlayAnimatedImage, imageDownloadInfo)); if (!localPathExists && !imageDownloadInfo.noCache) { ImageSaveQueue.Enqueue(new TextureSaveInfo(localFilePath, animData)); } } yield return(new WaitUntil(() => _waitForFrames-- == 0)); } }
private static bool ImageExistsLocally(ref string imagePath, TextureDownloadInfo imageDownloadInfo, out string localFilePath) { string origImagePath = imagePath; if (imageDownloadInfo.noCache) { localFilePath = ""; return(false); } string currentPath = Path.Combine(Environment.CurrentDirectory, "Cache", "Images", ImageTypeNames.Get(imageDownloadInfo.type)); if (!Directory.Exists(currentPath)) { Directory.CreateDirectory(currentPath); } localFilePath = Path.Combine(currentPath, imageDownloadInfo.spriteIndex); if (File.Exists(localFilePath)) { imagePath = localFilePath; return(true); } return(false); }
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 Download(string imagePath, TextureDownloadInfo imageDownloadInfo, bool isRetry = false) { if (!CachedTextures.ContainsKey(imageDownloadInfo.spriteIndex)) { int _waitForFrames = 5; Sprite sprite = null; if (imageDownloadInfo.type != ImageType.Emoji) { bool localPathExists = ImageExistsLocally(ref imagePath, imageDownloadInfo, out var localFilePath); yield return(Utilities.Download(imagePath, Utilities.DownloadType.Texture, null, (web) => { sprite = Utilities.LoadSpriteFromTexture(DownloadHandlerTexture.GetContent(web)); if (sprite) { if (!localPathExists && !imageDownloadInfo.noCache) { ImageSaveQueue.Enqueue(new TextureSaveInfo(localFilePath, web.downloadHandler.data)); } } })); } else { try { sprite = Utilities.LoadSpriteFromResources($"EnhancedStreamChat.Resources.Emojis.{imageDownloadInfo.spriteIndex.ToLower()}"); } catch (Exception ex) { Plugin.Log($"An error occurred while trying to load emoji from resources. {ex.ToString()}"); yield break; } } if (sprite) { CachedTextures.TryAdd(imageDownloadInfo.spriteIndex, new CachedSpriteData(imageDownloadInfo.type, sprite, sprite.texture.width, sprite.texture.height)); yield return(null); ChatHandler.Instance.OverlayImage(sprite, imageDownloadInfo); } yield return(new WaitUntil(() => _waitForFrames-- == 0)); } }
public static IEnumerator PreloadAnimatedEmotes() { int count = 0; foreach (string emoteIndex in BTTVAnimatedEmoteIDs.Values) { if (!Globals.IsAtMainMenu) { yield return(new WaitUntil(() => Globals.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 Process(byte[] gifData, Action <Texture2D, Rect[], float[], bool, int, int, 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, frameInfo)); yield return(new WaitUntil(() => { return frameInfo.initialized; })); int textureSize = 2048, width = 0, height = 0; Texture2D texture = null; List <float> delays = new List <float>(); for (int i = 0; i < frameInfo.frameCount; i++) { if (frameInfo.frames.Count <= i) { yield return(new WaitUntil(() => { return frameInfo.frames.Count > i; })); //Plugin.Log($"Frame {i} is ready for processing! Frame is {frameInfo.frames[i].width}x{frameInfo.frames[i].height}"); } if (texture == null) { textureSize = GetTextureSize(frameInfo, i); texture = new Texture2D(textureSize, textureSize); } FrameInfo currentFrameInfo = frameInfo.frames[i]; delays.Add(currentFrameInfo.delay); var frameTexture = new Texture2D(currentFrameInfo.width, currentFrameInfo.height, TextureFormat.RGBA32, false); frameTexture.wrapMode = TextureWrapMode.Clamp; try { frameTexture.SetPixels32(currentFrameInfo.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) { width = frameInfo.frames[i].width; height = frameInfo.frames[i].height; callback?.Invoke(frameTexture, texture.PackTextures(new Texture2D[] { frameTexture }, 2, textureSize, true), delays.ToArray(), true, width, height, imageDownloadInfo); } } Rect[] atlas = texture.PackTextures(texList.ToArray(), 2, textureSize, true); yield return(null); callback?.Invoke(texture, atlas, delays.ToArray(), frameInfo.isDelayConsistent, width, height, imageDownloadInfo); Plugin.Log($"Finished decoding gif {imageDownloadInfo.spriteIndex}! Elapsed time: {(DateTime.Now - startTime).TotalSeconds} seconds."); }
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."); }