diff --git a/1.4/Assemblies/Rimworld-Animations-Patch.dll b/1.4/Assemblies/Rimworld-Animations-Patch.dll index 2190479..707716e 100644 Binary files a/1.4/Assemblies/Rimworld-Animations-Patch.dll and b/1.4/Assemblies/Rimworld-Animations-Patch.dll differ diff --git a/About/About.xml b/About/About.xml index 12fd375..69d43d2 100644 --- a/About/About.xml +++ b/About/About.xml @@ -54,7 +54,7 @@ Here's a brief overview of what's included in this mod - 2 animations for group sex - Animated hands for certain animations - The option to have pawns in varying states of dress during sex (ranging from fully nude to almost entirely clothed) -- Apparel can be masked so that the bottom halves of pawns are visible when not wearing pants +- Apparel textures can be dynamically cropped, so that the bottom halves of pawns (and their bits) can be more easily seen when they are not wearing pants - The option to hide the names of pawns while they have sex - Automatic position scaling, to improve animations involving alien races which are larger or smaller than normal - A GUI for customizing how RimNude body parts should be displayed when wearing different types of apparel, as well as toggling what apparel should be worn while having sex @@ -64,9 +64,8 @@ A full list of changes can be found in the main discussion thread on the forum Known issues - For best results, turn off texture caching (this can be done by adding the Vanilla Expanded Framework to your mod list and enabling its 'Disable Texture Caching' setting) - The animations in this mod do not play any voices from Tory's VoicePatch mod -- Apparel masking cannot be used with the Sized Apparel mod - This mod will result in floating body parts when using Pawnmorpher's 'Pawn scaling' setting -- If you're having some issues with frame rates on large colonies, try disabling hand rendering +- If you're having some issues with frame/tick rates on large colonies, try disabling hand rendering and/or apparel cropping diff --git a/About/Changelog_v2.0.1.txt b/About/Changelog_v2.0.2.txt similarity index 54% rename from About/Changelog_v2.0.1.txt rename to About/Changelog_v2.0.2.txt index 76b72fc..758b24c 100644 --- a/About/Changelog_v2.0.1.txt +++ b/About/Changelog_v2.0.2.txt @@ -1,3 +1,7 @@ +Change log v 2.0.2 +- Implemented texture caching to reduce the performance hit induced by dynamically cropping apparel +- Dynamically cropping apparel is now compatible with Sized Apparel + Change log v 2.0.1 - Fixed issue with a hand animation calling a missing method - Fixed errored that was triggering at the end of sex diff --git a/About/Manifest.xml b/About/Manifest.xml index 8df9d3d..f800735 100644 --- a/About/Manifest.xml +++ b/About/Manifest.xml @@ -1,5 +1,5 @@ - 2.0.1 + 2.0.2 https://gitgud.io/AbstractConcept/rimworld-animations-patch \ No newline at end of file diff --git a/Source/.vs/Rimworld-Animations-Patch/v16/.suo b/Source/.vs/Rimworld-Animations-Patch/v16/.suo index ef3888e..a60364e 100644 Binary files a/Source/.vs/Rimworld-Animations-Patch/v16/.suo and b/Source/.vs/Rimworld-Animations-Patch/v16/.suo differ diff --git a/Source/Rimworld-Animations-Patch.csproj b/Source/Rimworld-Animations-Patch.csproj index 6aef491..091e2ba 100644 --- a/Source/Rimworld-Animations-Patch.csproj +++ b/Source/Rimworld-Animations-Patch.csproj @@ -113,6 +113,7 @@ + diff --git a/Source/Scripts/Defs/ApparelTexture2DPack.cs b/Source/Scripts/Defs/ApparelTexture2DPack.cs new file mode 100644 index 0000000..f7ae47b --- /dev/null +++ b/Source/Scripts/Defs/ApparelTexture2DPack.cs @@ -0,0 +1,57 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Verse; +using RimWorld; +using UnityEngine; + +namespace Rimworld_Animations_Patch +{ + public class ApparelTexture2DPack + { + public List textures = new List(); + + private static Dictionary cachedMaskTextures = new Dictionary(); + + public static ApparelTexture2DPack PackMaskTextures(string path) + { + ApparelTexture2DPack pack = new ApparelTexture2DPack(); + + for (int i = 0; i < 3; i++) + { + string direction = new Rot4(i).ToStringWord().ToLower(); + Texture2D maskTexture = ContentFinder.Get(path + "_" + direction, true); + + pack.textures.Add(maskTexture); + } + + return pack; + } + + public static ApparelTexture2DPack GetCachedMaskTexturesForBodyType(BodyTypeDef bodyType) + { + string path = "Masks/apparel_shirt_mask_" + bodyType.defName; + + if (cachedMaskTextures.TryGetValue(path, out ApparelTexture2DPack pack) == false) + { pack = PackMaskTextures(path); } + + return pack; + } + + public void PackTexturesForBodyType(Graphic graphic, BodyTypeDef bodyType) + { + textures.Clear(); + + for (int i = 0; i < 3; i++) + { + Texture2D origTexture = (Texture2D)graphic.MatAt(new Rot4(i)).mainTexture; + Texture2D maskTexture = GetCachedMaskTexturesForBodyType(bodyType).textures[i]; + Texture2D maskedTexture = GraphicMaskingUtility.ApplyMaskToTexture2D(origTexture, maskTexture, true); + + textures.Add(maskedTexture); + } + } + } +} diff --git a/Source/Scripts/Patches/HarmonyPatch_ApparelGraphicRecordGetter.cs b/Source/Scripts/Patches/HarmonyPatch_ApparelGraphicRecordGetter.cs index 2d1b9b7..d83e0e8 100644 --- a/Source/Scripts/Patches/HarmonyPatch_ApparelGraphicRecordGetter.cs +++ b/Source/Scripts/Patches/HarmonyPatch_ApparelGraphicRecordGetter.cs @@ -30,29 +30,24 @@ namespace Rimworld_Animations_Patch } } + [HarmonyAfter("SizedApparelforRJW")] public static void Postfix(ref bool __result, ref Apparel apparel, ref BodyTypeDef bodyType, ref ApparelGraphicRecord rec) { - if (__result == false || apparel == null || bodyType == null || rec.graphic == null || ApparelSettings.cropApparel == false || IsRunningSizedApparel) return; + if (__result == false || apparel == null || bodyType == null || rec.graphic == null || apparel?.Wearer?.RaceProps?.Humanlike != true || ApparelSettings.cropApparel == false) return; - // Get graphic - Graphic graphic = rec.graphic; - - // This graphic may need to be masked if the apparel sits on the skin layer and does not cover the legs if (apparel.def.apparel.LastLayer == ApparelLayerDefOf.OnSkin && apparel.def.apparel.bodyPartGroups.Contains(BodyPartGroupDefOf.Torso) && !apparel.def.apparel.bodyPartGroups.Contains(BodyPartGroupDefOf.Legs)) { - Dictionary allGraphics = Traverse.Create(typeof(GraphicDatabase)).Field("allGraphics").GetValue() as Dictionary; - GraphicRequest graphicRequest = new GraphicRequest(typeof(Graphic_Multi), graphic.path, ShaderDatabase.CutoutComplex, graphic.drawSize, apparel.DrawColor, apparel.DrawColor, null, 0, null, "Masks/apparel_shirt_mask_" + bodyType.defName); + ApparelTexture2DPack pack = ApparelSettingsUtility.GetCachedApparelTextures(rec.graphic, bodyType); + if (pack == null) return; - if (allGraphics.TryGetValue(graphicRequest) == null) + for (int i = 0; i < 3; i++) { - Graphic graphicWithApparelMasks = GraphicDatabase.Get(graphic.path, ShaderDatabase.CutoutComplex, graphic.drawSize, apparel.DrawColor, apparel.DrawColor, null, "Masks/apparel_shirt_mask_" + bodyType.defName); - graphic = GraphicMaskingUtility.ApplyGraphicMasks(graphic, graphicWithApparelMasks, true); - - //DebugMode.Message("Applying apparel mask: Masks/apparel_shirt_mask_" + bodyType.defName + " to " + apparel.def.defName + " (" + graphic.path + ")"); + if (pack.textures[i] == null) continue; + rec.graphic.MatAt(new Rot4(i)).mainTexture = pack.textures[i]; } } - - rec = new ApparelGraphicRecord(graphic, apparel); } } -} \ No newline at end of file +} + +//"Masks/apparel_shirt_mask_" + bodyType.defName \ No newline at end of file diff --git a/Source/Scripts/Settings/ApparelSettings.cs b/Source/Scripts/Settings/ApparelSettings.cs index 4d46832..d9c603f 100644 --- a/Source/Scripts/Settings/ApparelSettings.cs +++ b/Source/Scripts/Settings/ApparelSettings.cs @@ -82,6 +82,12 @@ namespace Rimworld_Animations_Patch // Update all humanlike pawn graphics when settings window is closed public void ApplySettings() { + if (ApparelSettings.cropApparel == false) + { + DebugMode.Message("Clearing apparel texture cache"); + ApparelSettingsUtility.ClearCachedApparelTextures(); + } + if (Current.ProgramState == ProgramState.Playing) { foreach (Pawn pawn in Current.Game.CurrentMap.mapPawns.AllPawns) diff --git a/Source/Scripts/Utilities/ApparelSettingsUtility.cs b/Source/Scripts/Utilities/ApparelSettingsUtility.cs index 34956f8..442cbc6 100644 --- a/Source/Scripts/Utilities/ApparelSettingsUtility.cs +++ b/Source/Scripts/Utilities/ApparelSettingsUtility.cs @@ -8,6 +8,30 @@ namespace Rimworld_Animations_Patch { public static class ApparelSettingsUtility { + private static Dictionary cachedApparelTextures = new Dictionary(); + + public static ApparelTexture2DPack GetCachedApparelTextures(Graphic graphic, BodyTypeDef bodyType) + { + if (ApparelSettings.cropApparel == false) return null; + if (graphic?.path == null) return null; + + if (cachedApparelTextures.TryGetValue(graphic.path, out ApparelTexture2DPack pack) == false) + { + pack = new ApparelTexture2DPack(); + pack.PackTexturesForBodyType(graphic, bodyType); + + cachedApparelTextures.Add(graphic.path, pack); + DebugMode.Message("Cropped textures have been cached for " + graphic.path); + } + + return pack; + } + + public static void ClearCachedApparelTextures() + { + cachedApparelTextures.Clear(); + } + public static List GetApparelOfInterest() { List thingDefs = new List(); diff --git a/Source/Scripts/Utilities/GraphicMaskingUtility.cs b/Source/Scripts/Utilities/GraphicMaskingUtility.cs index efa1a62..0506531 100644 --- a/Source/Scripts/Utilities/GraphicMaskingUtility.cs +++ b/Source/Scripts/Utilities/GraphicMaskingUtility.cs @@ -43,11 +43,8 @@ namespace Rimworld_Animations_Patch public static Texture2D ApplyMaskToTexture2D(Texture2D mainTex, Texture2D maskTex, bool writeOverMainTex) { - if (mainTex == null || maskTex == null) - { - DebugMode.Message("mainTex or maskTex is missing!"); - return mainTex; - } + if (mainTex == null) { DebugMode.Message("ERROR: Cannot mask texture, mainTex is missing!"); return mainTex; } + if (mainTex == null) { DebugMode.Message("ERROR: Cannot mask texture, maskTex is missing!"); return mainTex; } Color[] mainArray = GetReadableTexture2D(mainTex).GetPixels(); Color[] maskArray = GetReadableTexture2D(maskTex, mainTex.width, mainTex.height).GetPixels(); diff --git a/Source/obj/Debug/Rimworld-Animations-Patch.csproj.CoreCompileInputs.cache b/Source/obj/Debug/Rimworld-Animations-Patch.csproj.CoreCompileInputs.cache index b88a18f..4eb242c 100644 --- a/Source/obj/Debug/Rimworld-Animations-Patch.csproj.CoreCompileInputs.cache +++ b/Source/obj/Debug/Rimworld-Animations-Patch.csproj.CoreCompileInputs.cache @@ -1 +1 @@ -fff727b2ad4bd81d64cd84c1b3509271d8320a48 +6fac2a07a07edab552d2d2c7e0803d0524758bd1 diff --git a/Source/obj/Debug/Rimworld-Animations-Patch.csprojAssemblyReference.cache b/Source/obj/Debug/Rimworld-Animations-Patch.csprojAssemblyReference.cache index d9e165b..0039789 100644 Binary files a/Source/obj/Debug/Rimworld-Animations-Patch.csprojAssemblyReference.cache and b/Source/obj/Debug/Rimworld-Animations-Patch.csprojAssemblyReference.cache differ diff --git a/Source/obj/Debug/Rimworld-Animations-Patch.dll b/Source/obj/Debug/Rimworld-Animations-Patch.dll index 2190479..707716e 100644 Binary files a/Source/obj/Debug/Rimworld-Animations-Patch.dll and b/Source/obj/Debug/Rimworld-Animations-Patch.dll differ diff --git a/Source/obj/Debug/Rimworld-Animations-Patch.pdb b/Source/obj/Debug/Rimworld-Animations-Patch.pdb index 479ee54..e68da75 100644 Binary files a/Source/obj/Debug/Rimworld-Animations-Patch.pdb and b/Source/obj/Debug/Rimworld-Animations-Patch.pdb differ