using System; using System.Collections.Generic; using HarmonyLib; using RimWorld; using UnityEngine; using Verse; namespace Rimworld_Animations_Patch { public static class GraphicMaskingUtility { public static Texture2D GetReadableTexture2D(Texture2D source, int newWidth, int newHeight, Material mat = null) //rescales texture to newWidth and newHeight { source.filterMode = FilterMode.Trilinear; RenderTexture rt = RenderTexture.GetTemporary(newWidth, newHeight); rt.filterMode = FilterMode.Trilinear; RenderTexture.active = rt; if (mat != null) { Graphics.Blit(source, rt, mat); } else { Graphics.Blit(source, rt); } Texture2D nTex = new Texture2D(newWidth, newHeight, TextureFormat.RGBA32, mipChain: true); nTex.ReadPixels(new Rect(0, 0, newWidth, newHeight), 0, 0); nTex.name = source.name; nTex.filterMode = FilterMode.Trilinear; nTex.anisoLevel = 2; nTex.Apply(updateMipmaps: true); GL.Clear(true, true, Color.clear); RenderTexture.active = null; RenderTexture.ReleaseTemporary(rt); return nTex; } public static Texture2D GetReadableTexture2D(Texture2D source, Material mat = null) { return GetReadableTexture2D(source, source.width, source.height, mat); } public static Texture2D ApplyMaskToTexture2D(Texture2D mainTex, Texture2D maskTex, bool writeOverMainTex) { if (mainTex == null || maskTex == null) { DebugMode.Message("mainTex or maskTex is missing!"); return mainTex; } Color[] mainArray = GetReadableTexture2D(mainTex).GetPixels(); Color[] maskArray = GetReadableTexture2D(maskTex, mainTex.width, mainTex.height).GetPixels(); for (int j = 0; j < mainArray.Length; j++) { if (maskArray[j] == Color.white) { /*null*/ } else if (maskArray[j].a == 0) { mainArray[j].a = 0; } else if (mainArray[j].a > 0 && maskArray[j].a > 0 && writeOverMainTex) { mainArray[j] = new Color(Mathf.Min(mainArray[j].r, maskArray[j].r), Mathf.Min(mainArray[j].g, maskArray[j].g), Mathf.Min(mainArray[j].b, maskArray[j].b), Mathf.Min(mainArray[j].a, maskArray[j].a)); } } Texture2D newTex = new Texture2D(mainTex.width, mainTex.height, TextureFormat.RGBA32, mipChain: true); newTex.SetPixels(mainArray); newTex.filterMode = FilterMode.Trilinear; newTex.anisoLevel = 2; newTex.Apply(updateMipmaps: true); return newTex; } public static Graphic ApplyGraphicWithMasks(Graphic graphic, Graphic graphicWithMask, bool writeOverMainTex) { for (int i = 0; i < 4; i++) { Texture2D mainTex = (Texture2D)graphic.MatAt(new Rot4(i)).mainTexture; Texture2D maskTex = graphicWithMask.MatAt(new Rot4(i)).GetMaskTexture(); graphic.MatAt(new Rot4(i)).mainTexture = ApplyMaskToTexture2D(mainTex, maskTex, writeOverMainTex); } return graphic; } public static Graphic ApplyGraphicWithMasks(Graphic graphic, string mask, bool writeOverMainTex) { for (int i = 0; i < 4; i++) { Texture2D mainTex = (Texture2D)graphic.MatAt(new Rot4(i)).mainTexture; if (mainTex == null) { DebugMode.Message("Main Texture2D not found for " + graphic.path + ". Rotation: " + i.ToString()); continue; } string suffix = string.Empty; switch (i) { case 0: suffix = "_north"; break; case 1: suffix = "_east"; break; case 2: suffix = "_south"; break; case 3: suffix = "_west"; break; } Texture2D maskTex = ContentFinder.Get(mask + suffix, false); if (maskTex == null) { DebugMode.Message("Mask Texture2D not found for " + mask + ". Rotation: " + i.ToString()); continue; } graphic.MatAt(new Rot4(i)).mainTexture = ApplyMaskToTexture2D(mainTex, maskTex, writeOverMainTex); } return graphic; } public static void ResetGraphic(Graphic graphic) { for (int i = 0; i < 4; i++) { string suffix = string.Empty; switch (i) { case 0: suffix = "_north"; break; case 1: suffix = "_east"; break; case 2: suffix = "_south"; break; case 3: suffix = "_west"; break; } Texture2D texture2D = ContentFinder.Get(graphic.path + suffix, false); if (texture2D == null && i == 3) { texture2D = ContentFinder.Get(graphic.path + "_east", false); } if (texture2D == null) { texture2D = ContentFinder.Get(graphic.path + "_north", false); } if (texture2D != null) { graphic.MatAt(new Rot4(i)).mainTexture = texture2D; } } } } }