public static void OverlayImage(CustomText currentMessage, ImageInfo imageInfo) { CachedSpriteData cachedTextureData = ImageDownloader.CachedTextures.ContainsKey(imageInfo.textureIndex) ? ImageDownloader.CachedTextures[imageInfo.textureIndex] : null; // If cachedTextureData is null, the emote will be overlayed at a later time once it's finished being cached if (cachedTextureData == null || (cachedTextureData.sprite == null && cachedTextureData.animInfo == null)) { return; } bool animatedEmote = cachedTextureData.animInfo != null; foreach (int i in Utilities.IndexOfAll(currentMessage.text, Char.ConvertFromUtf32(imageInfo.swapChar))) { CustomImage image = null, shadow = null; try { if (i > 0 && i < currentMessage.text.Count()) { image = ChatHandler.Instance.imagePool.Alloc(); image.spriteIndex = imageInfo.textureIndex; image.imageType = imageInfo.imageType; image.rectTransform.pivot = new Vector2(0, 0); image.sprite = cachedTextureData.sprite; image.preserveAspect = false; if (image.sprite) { image.sprite.texture.wrapMode = TextureWrapMode.Clamp; } image.rectTransform.SetParent(currentMessage.rectTransform, false); float aspectRatio = cachedTextureData.width / cachedTextureData.height; if (aspectRatio > 1) { image.rectTransform.localScale = new Vector3(0.064f * aspectRatio, 0.064f, 0.064f); } else { image.rectTransform.localScale = new Vector3(0.064f, 0.064f, 0.064f); } TextGenerator textGen = currentMessage.cachedTextGenerator; Vector3 pos = new Vector3(textGen.verts[i * 4 + 3].position.x, textGen.verts[i * 4 + 3].position.y); image.rectTransform.position = currentMessage.gameObject.transform.TransformPoint(pos / pixelsPerUnit - new Vector3(cachedTextureData.width / pixelsPerUnit + 2.5f, cachedTextureData.height / pixelsPerUnit + 1f) + new Vector3(0, 0, -0.1f)); image.rectTransform.localPosition -= new Vector3(imageSpacingWidth / 2.3f, 0); if (animatedEmote) { image.material = cachedTextureData.animInfo.imageMaterial; //image.shadow.enabled = false; if (Config.Instance.DrawShadows) { // Add a shadow to our animated image (the regular unity shadows won't work with this material) shadow = ChatHandler.Instance.imagePool.Alloc(); shadow.material = cachedTextureData.animInfo.shadowMaterial; shadow.sprite = null; shadow.spriteIndex = imageInfo.textureIndex; shadow.imageType = imageInfo.imageType; shadow.rectTransform.pivot = new Vector2(0, 0); shadow.rectTransform.localScale = image.rectTransform.localScale; shadow.rectTransform.SetParent(currentMessage.rectTransform, false); shadow.rectTransform.position = image.rectTransform.position; shadow.rectTransform.localPosition += new Vector3(0.6f, -0.6f, 0.05f); shadow.enabled = true; currentMessage.emoteRenderers.Add(shadow); } } else { image.material = Drawing.noGlowMaterialUI; if (Config.Instance.DrawShadows) { image.shadow.enabled = true; } } image.enabled = true; currentMessage.emoteRenderers.Add(image); } } catch (Exception e) { if (image) { ChatHandler.Instance.imagePool.Free(image); } Plugin.Log($"Exception {e.ToString()} occured when trying to overlay emote at index {i.ToString()}!"); } } }
public static void OverlayImage(CustomText currentMessage, ImageInfo imageInfo) { CachedSpriteData cachedTextureData = imageInfo.cachedSprite; // If cachedTextureData is null, the emote will be overlayed at a later time once it's finished being cached if (cachedTextureData == null || (cachedTextureData.sprite == null && cachedTextureData.animInfo == null)) { return; } bool animatedEmote = cachedTextureData.animInfo != null; var messageWithoutHtml = htmlRegex.Replace(currentMessage.text, (m) => m.Groups[1].Value); foreach (int i in EmojiUtilities.IndexOfAll(messageWithoutHtml, Char.ConvertFromUtf32(imageInfo.swapChar))) { CustomImage image = null, shadow = null; try { if (i > 0 && i < currentMessage.text.Length) { image = ChatHandler.Instance.imagePool.Alloc(); image.cachedTextureData = cachedTextureData; image.spriteIndex = imageInfo.textureIndex; image.imageType = imageInfo.imageType; image.sprite = cachedTextureData.sprite; image.preserveAspect = false; if (image.sprite) { image.sprite.texture.wrapMode = TextureWrapMode.Clamp; } image.rectTransform.SetParent(currentMessage.rectTransform, false); image.rectTransform.localScale = new Vector3(0.064f, 0.064f, 0.064f); image.rectTransform.sizeDelta = new Vector2(cachedTextureData.width, cachedTextureData.height); if (imageInfo.imageType == ImageType.Emoji || imageInfo.imageType == ImageType.Badge) { image.rectTransform.pivot = new Vector2(0, 0.21f); } else { image.rectTransform.pivot = new Vector2(0, 0.3f); } TextGenerator textGen = currentMessage.cachedTextGenerator; Vector3 pos = new Vector3(textGen.verts[i * 4].position.x, textGen.verts[i * 4].position.y); image.rectTransform.position = currentMessage.gameObject.transform.TransformPoint(pos / pixelsPerUnit + new Vector3(0, 0, -0.1f)); if (animatedEmote) { cachedTextureData.animInfo?.animData?.IncRefs(); image.material = cachedTextureData.animInfo.imageMaterial; if (ChatConfig.instance.DrawShadows && cachedTextureData.animInfo.shadowMaterial != null) { // Add a shadow to our animated image (the regular unity shadows won't work with this material) shadow = ChatHandler.Instance.imagePool.Alloc(); shadow.material = cachedTextureData.animInfo.shadowMaterial; shadow.sprite = null; shadow.spriteIndex = imageInfo.textureIndex; shadow.imageType = imageInfo.imageType; shadow.rectTransform.pivot = new Vector2(0, 0); shadow.rectTransform.localScale = image.rectTransform.localScale; shadow.rectTransform.SetParent(currentMessage.rectTransform, false); shadow.rectTransform.position = image.rectTransform.position; shadow.rectTransform.localPosition += new Vector3(0.6f, -0.6f, 0.05f); shadow.enabled = true; currentMessage.emoteRenderers.Add(shadow); } } else { image.material = noGlowMaterialUI; if (ChatConfig.instance.DrawShadows) { image.shadow.enabled = true; } } image.enabled = true; currentMessage.emoteRenderers.Add(image); } } catch (Exception e) { if (image) { ChatHandler.Instance.imagePool.Free(image); } Plugin.Log($"Exception {e.ToString()} occured when trying to overlay emote at index {i.ToString()}!"); } } }
public static void OverlayEmote(CustomText currentMessage, char swapChar, Material noGlowMaterialUI, AnimationController animationController, CachedSpriteData cachedSpriteInfo) { // Don't even try to overlay an emote if it's not been cached properly if (cachedSpriteInfo == null || (cachedSpriteInfo.sprite == null && cachedSpriteInfo.animationInfo == null)) { //Plugin.Log("Sprite was not fully cached!"); return; } bool animatedEmote = cachedSpriteInfo.animationInfo != null; foreach (int i in Utilities.IndexOfAll(currentMessage.text, Char.ConvertFromUtf32(swapChar))) { try { if (i > 0 && i < currentMessage.text.Count() - 1 && currentMessage.text[i - 1] == ' ' && currentMessage.text[i + 1] == ' ') { GameObject newGameObject = new GameObject(); var image = newGameObject.AddComponent <Image>(); image.material = noGlowMaterialUI; var shadow = newGameObject.AddComponent <Shadow>(); if (animatedEmote) { var animatedImage = newGameObject.AddComponent <AnimatedSprite>(); animatedImage.Init(image, cachedSpriteInfo.animationInfo, animationController); } else { image.sprite = cachedSpriteInfo.sprite; image.sprite.texture.wrapMode = TextureWrapMode.Clamp; } image.rectTransform.SetParent(currentMessage.rectTransform, false); image.preserveAspect = true; image.rectTransform.sizeDelta = new Vector2(7.0f, 7.0f); image.rectTransform.pivot = new Vector2(0, 0); var textGen = currentMessage.cachedTextGenerator; var pos = new Vector3(textGen.verts[i * 4 + 3].position.x, textGen.verts[i * 4 + 3].position.y); image.rectTransform.position = currentMessage.gameObject.transform.TransformPoint(pos / Plugin.PixelsPerUnit - new Vector3(image.preferredWidth / Plugin.PixelsPerUnit + 2.5f, image.preferredHeight / Plugin.PixelsPerUnit + 0.7f)); currentMessage.emoteRenderers.Add(image); } } catch (Exception e) { Plugin.Log($"Exception {e.Message} occured when trying to overlay emote at index {i.ToString()}!"); } } }
public void OverlayAnimatedImage(Texture2D texture, Rect[] uvs, float[] delays, bool isDelayConsistent, int width, int height, TextureDownloadInfo imageDownloadInfo) { try { string spriteIndex = imageDownloadInfo.spriteIndex; string messageIndex = imageDownloadInfo.messageIndex; ImageDownloader.CachedTextures.TryGetValue(spriteIndex, out var cachedTex); CachedAnimationData oldAnimInfo = cachedTex?.animInfo; // Create the shaders which will cycle through our animation texture sheet var animInfo = new CachedAnimationData(uvs.Length > 1 ? AnimationController.Instance.Register(spriteIndex, uvs, delays) : new AnimControllerData(spriteIndex, uvs, delays), texture, uvs, delays); // Try to create our animMaterial and shadowMaterial if they don't already exist Material _animMaterial = oldAnimInfo?.imageMaterial; Material _shadowMaterial = oldAnimInfo?.shadowMaterial; if (_animMaterial == null) { _animMaterial = Instantiate(Drawing.CropMaterial); _animMaterial.SetVector("_CropFactors", new Vector4(uvs[0].x, uvs[0].y, uvs[0].width, uvs[0].height)); } if (ChatConfig.instance.DrawShadows) { if (_shadowMaterial == null) { _shadowMaterial = Instantiate(Drawing.CropMaterialColorMultiply); _shadowMaterial.SetVector("_CropFactors", new Vector4(uvs[0].x, uvs[0].y, uvs[0].width, uvs[0].height)); _shadowMaterial.SetColor("_Color", Color.black.ColorWithAlpha(0.2f)); _shadowMaterial.renderQueue = 3001; } _shadowMaterial.mainTexture = texture; animInfo.shadowMaterial = _shadowMaterial; } _animMaterial.mainTexture = texture; animInfo.imageMaterial = _animMaterial; var newCachedSpriteData = new CachedSpriteData(imageDownloadInfo.type, animInfo, isDelayConsistent, width, height); ImageDownloader.CachedTextures[spriteIndex] = newCachedSpriteData; if (cachedTex != null && oldAnimInfo != null && oldAnimInfo.uvs.Length == 1) { foreach (CustomText currentMessage in _chatMessages) { for (int i = currentMessage.emoteRenderers.Count - 1; i >= 0; i--) { CustomImage img = currentMessage.emoteRenderers[i]; if (img.spriteIndex == spriteIndex) { Plugin.Log("Freeing old emote!"); imagePool.Free(img); currentMessage.emoteRenderers.RemoveAt(i); } } } } foreach (CustomText currentMessage in _chatMessages) { if (currentMessage.messageInfo == null || !currentMessage.hasRendered) { continue; } foreach (EmoteInfo e in currentMessage.messageInfo.parsedEmotes.Values) { if (e.textureIndex == spriteIndex) { Drawing.OverlayImage(currentMessage, e); } } } } catch (Exception e) { Plugin.Log($"Exception when overlaying animated emote! {e.ToString()}"); } }