mirror of
https://gitgud.io/AbstractConcept/rimworld-animations-patch.git
synced 2024-08-15 00:43:27 +00:00
9144029fec
- Implemented texture caching to reduce the performance hit induced by dynamically cropping apparel - Dynamically cropping apparel is now compatible with Sized Apparel
372 lines
16 KiB
C#
372 lines
16 KiB
C#
using System;
|
|
using System.Linq;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
using Verse;
|
|
using RimWorld;
|
|
using rjw;
|
|
|
|
namespace Rimworld_Animations_Patch
|
|
{
|
|
public class ApparelSettings : ModSettings
|
|
{
|
|
public static List<RimNudeData> rimNudeData = new List<RimNudeData>();
|
|
|
|
public static bool cropApparel = false;
|
|
public static bool clothesThrownOnGround = true;
|
|
public static RJWPreferenceSettings.Clothing apparelWornForQuickies = RJWPreferenceSettings.Clothing.Clothed;
|
|
|
|
public override void ExposeData()
|
|
{
|
|
base.ExposeData();
|
|
|
|
Scribe_Values.Look(ref cropApparel, "cropApparel", false);
|
|
Scribe_Values.Look(ref clothesThrownOnGround, "clothesThrownOnGround", true);
|
|
Scribe_Values.Look(ref apparelWornForQuickies, "apparelWornForQuickies", RJWPreferenceSettings.Clothing.Clothed);
|
|
}
|
|
|
|
public static RimNudeData GetRimNudeData(Apparel apparel)
|
|
{
|
|
if (rimNudeData.NullOrEmpty())
|
|
{ ApparelSettingsUtility.ResetRimNudeData(rimNudeData); }
|
|
|
|
foreach (RimNudeData apparelData in rimNudeData)
|
|
{
|
|
if (apparelData.EquivalentTo(new RimNudeData(apparel.def)))
|
|
{ return apparelData; }
|
|
}
|
|
|
|
return null;
|
|
}
|
|
}
|
|
|
|
public class ApparelSettingsDisplay : Mod
|
|
{
|
|
private const float windowY = 240f;
|
|
private const float windowHeight = 360f;
|
|
|
|
private Vector2 scrollPosition;
|
|
private const float scrollBarWidthMargin = 18f;
|
|
|
|
private const float headerHeight = 48f;
|
|
private const float widgetWidth = 32f;
|
|
private const float widgetHeight = 32f;
|
|
private const float buttonWidth = 90f;
|
|
private const float buttonHeight = 32f;
|
|
private const float checkboxSize = 24f;
|
|
private const float labelWidth = 170f;
|
|
private const float labelHeight = 40f;
|
|
|
|
private const float rowHeight = 40f;
|
|
private const float halfColumnWidth = 40f;
|
|
private const float singleColumnWidth = 100f;
|
|
private const float doubleColumnWidth = 180f;
|
|
|
|
private List<ThingDef> shortListedApparelDefs = new List<ThingDef>();
|
|
private List<ThingDef> allApparelDefs = new List<ThingDef>();
|
|
|
|
private List<ModContentPack> relevantModContentPacks = new List<ModContentPack>();
|
|
private ModContentPack currentModContentPack;
|
|
|
|
public ApparelSettingsDisplay(ModContentPack content) : base(content)
|
|
{
|
|
GetSettings<ApparelSettings>();
|
|
}
|
|
|
|
public override void WriteSettings()
|
|
{
|
|
base.WriteSettings();
|
|
ApplySettings();
|
|
}
|
|
|
|
// 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)
|
|
{
|
|
if (pawn == null) continue;
|
|
|
|
pawn.Drawer?.renderer?.graphics?.ResolveAllGraphics();
|
|
pawn.TryGetComp<CompPawnSexData>()?.UpdateBodyAddonVisibility();
|
|
|
|
PortraitsCache.SetDirty(pawn);
|
|
GlobalTextureAtlasManager.TryMarkPawnFrameSetDirty(pawn);
|
|
}
|
|
}
|
|
}
|
|
|
|
public override void DoSettingsWindowContents(Rect inRect)
|
|
{
|
|
// Settings list
|
|
Listing_Standard listingStandard;
|
|
listingStandard = new Listing_Standard();
|
|
listingStandard.Begin(inRect);
|
|
|
|
listingStandard.Gap(10f);
|
|
listingStandard.Label("rimworld_animation_patch_clothing".Translate());
|
|
listingStandard.Gap(5f);
|
|
|
|
listingStandard.Label("wearing_clothes_in_bed".Translate(), -1, "wearing_clothes_in_bed_desc".Translate());
|
|
|
|
if (Widgets.ButtonText(new Rect(inRect.width - 128f, 36f, 128f, 24f), RJWPreferenceSettings.sex_wear.ToString()))
|
|
{
|
|
List<FloatMenuOption> options = new List<FloatMenuOption>
|
|
{
|
|
new FloatMenuOption(RJWPreferenceSettings.Clothing.Clothed.ToString(), delegate()
|
|
{ RJWPreferenceSettings.sex_wear = RJWPreferenceSettings.Clothing.Clothed;
|
|
}, MenuOptionPriority.Default, null, null, 0f, null, null, true, 0),
|
|
new FloatMenuOption(RJWPreferenceSettings.Clothing.Headgear.ToString(), delegate()
|
|
{ RJWPreferenceSettings.sex_wear = RJWPreferenceSettings.Clothing.Headgear;
|
|
}, MenuOptionPriority.Default, null, null, 0f, null, null, true, 0),
|
|
new FloatMenuOption(RJWPreferenceSettings.Clothing.Nude.ToString(), delegate()
|
|
{ RJWPreferenceSettings.sex_wear = RJWPreferenceSettings.Clothing.Nude;
|
|
}, MenuOptionPriority.Default, null, null, 0f, null, null, true, 0),
|
|
}; Find.WindowStack.Add(new FloatMenu(options));
|
|
}
|
|
|
|
listingStandard.Label("wearing_clothes_for_quickies".Translate(), -1, "wearing_clothes_for_quickies_desc".Translate());
|
|
|
|
if (Widgets.ButtonText(new Rect(inRect.width - 128f, 60f, 128f, 24f), ApparelSettings.apparelWornForQuickies.ToString()))
|
|
{
|
|
List<FloatMenuOption> options = new List<FloatMenuOption>
|
|
{
|
|
new FloatMenuOption(RJWPreferenceSettings.Clothing.Clothed.ToString(), delegate()
|
|
{ ApparelSettings.apparelWornForQuickies = RJWPreferenceSettings.Clothing.Clothed;
|
|
}, MenuOptionPriority.Default, null, null, 0f, null, null, true, 0),
|
|
new FloatMenuOption(RJWPreferenceSettings.Clothing.Headgear.ToString(), delegate()
|
|
{ ApparelSettings.apparelWornForQuickies = RJWPreferenceSettings.Clothing.Headgear;
|
|
}, MenuOptionPriority.Default, null, null, 0f, null, null, true, 0),
|
|
new FloatMenuOption(RJWPreferenceSettings.Clothing.Nude.ToString(), delegate()
|
|
{ ApparelSettings.apparelWornForQuickies = RJWPreferenceSettings.Clothing.Nude;
|
|
}, MenuOptionPriority.Default, null, null, 0f, null, null, true, 0),
|
|
}; Find.WindowStack.Add(new FloatMenu(options));
|
|
}
|
|
|
|
listingStandard.CheckboxLabeled("clothes_thrown_on_ground".Translate(), ref ApparelSettings.clothesThrownOnGround, "clothes_thrown_on_ground_desc".Translate());
|
|
listingStandard.CheckboxLabeled("crop_apparel".Translate(), ref ApparelSettings.cropApparel, "crop_apparel_desc".Translate());
|
|
|
|
listingStandard.End();
|
|
base.DoSettingsWindowContents(inRect);
|
|
|
|
// Local variables
|
|
Rect rect = Find.WindowStack.currentlyDrawnWindow.windowRect.AtZero();
|
|
Rect tempRect = new Rect(0, 0, 0, 0);
|
|
|
|
float innerY = 0f;
|
|
float innerX = 0;
|
|
int num = 0;
|
|
|
|
bool isEnabled = false;
|
|
|
|
// Get a list of apparel and mods of interest
|
|
if (allApparelDefs.NullOrEmpty())
|
|
{
|
|
allApparelDefs = ApparelSettingsUtility.GetApparelOfInterest();
|
|
|
|
foreach (ThingDef thingDef in allApparelDefs)
|
|
{ relevantModContentPacks.AddDistinct(thingDef.modContentPack); }
|
|
|
|
currentModContentPack = relevantModContentPacks.FirstOrDefault();
|
|
|
|
if (currentModContentPack == null)
|
|
{ DebugMode.Message("ERROR: No mod content has been loaded?"); return; }
|
|
|
|
shortListedApparelDefs = allApparelDefs.Where(x => x.modContentPack == currentModContentPack)?.ToList();
|
|
}
|
|
|
|
// Ensure that all apparel has associated RimNudeData
|
|
if (ApparelSettings.rimNudeData.NullOrEmpty())
|
|
{ ApparelSettingsUtility.ResetRimNudeData(ApparelSettings.rimNudeData); }
|
|
|
|
// Add buttons to the top of the main window
|
|
innerX = halfColumnWidth;
|
|
|
|
if (shortListedApparelDefs.NullOrEmpty()) return;
|
|
|
|
// Apparel
|
|
tempRect = new Rect(innerX + SettingsUtility.Align(labelWidth, doubleColumnWidth), windowY - headerHeight - 5, labelWidth, headerHeight);
|
|
Widgets.DrawHighlightIfMouseover(tempRect);
|
|
TooltipHandler.TipRegion(tempRect, "List of apparel that covers the legs and/or torso. Use the provided drop down menu to load apparel settings for different mods.");
|
|
|
|
if (Widgets.ButtonText(tempRect, "Apparel - " + currentModContentPack.ModMetaData.Name)) {
|
|
List<FloatMenuOption> options = new List<FloatMenuOption> { };
|
|
|
|
foreach (ModContentPack modContentPack in relevantModContentPacks)
|
|
{
|
|
FloatMenuOption option = new FloatMenuOption(modContentPack.ModMetaData.Name, delegate ()
|
|
{
|
|
currentModContentPack = modContentPack;
|
|
shortListedApparelDefs = allApparelDefs.Where(x => x.modContentPack == currentModContentPack)?.ToList();
|
|
},
|
|
MenuOptionPriority.Default, null, null, 0f, null, null, true, 0);
|
|
|
|
options.Add(option);
|
|
}
|
|
|
|
Find.WindowStack.Add(new FloatMenu(options));
|
|
}; innerX += doubleColumnWidth;
|
|
|
|
// Covers groin
|
|
tempRect = new Rect(innerX + SettingsUtility.Align(buttonWidth, singleColumnWidth), windowY - headerHeight - 5, buttonWidth, headerHeight);
|
|
Widgets.DrawHighlightIfMouseover(tempRect);
|
|
TooltipHandler.TipRegion(tempRect, "Toggles whether genitials should be hidden when wearing this apparel.");
|
|
|
|
if (Widgets.ButtonText(tempRect, "Covers\ngroin"))
|
|
{
|
|
List<FloatMenuOption> options = new List<FloatMenuOption>
|
|
{
|
|
new FloatMenuOption("Set all 'true'", delegate()
|
|
{ ApparelSettingsUtility.SetAllCoversGroin(ApparelSettings.rimNudeData, true);
|
|
}, MenuOptionPriority.Default, null, null, 0f, null, null, true, 0),
|
|
new FloatMenuOption("Set all 'false'", delegate()
|
|
{ ApparelSettingsUtility.SetAllCoversGroin(ApparelSettings.rimNudeData, false);
|
|
}, MenuOptionPriority.Default, null, null, 0f, null, null, true, 0),
|
|
}; Find.WindowStack.Add(new FloatMenu(options));
|
|
}; innerX += singleColumnWidth;
|
|
|
|
// Covers belly
|
|
tempRect = new Rect(innerX + SettingsUtility.Align(buttonWidth, singleColumnWidth), windowY - headerHeight - 5, buttonWidth, headerHeight);
|
|
Widgets.DrawHighlightIfMouseover(tempRect);
|
|
TooltipHandler.TipRegion(tempRect, "Toggles whether an enlarged belly should be hidden when wearing this apparel.");
|
|
|
|
if (Widgets.ButtonText(tempRect, "Covers\nbelly"))
|
|
{
|
|
List<FloatMenuOption> options = new List<FloatMenuOption>
|
|
{
|
|
new FloatMenuOption("Set all 'true'", delegate()
|
|
{ ApparelSettingsUtility.SetAllCoversBelly(ApparelSettings.rimNudeData, true);
|
|
}, MenuOptionPriority.Default, null, null, 0f, null, null, true, 0),
|
|
new FloatMenuOption("Set all 'false'", delegate()
|
|
{ ApparelSettingsUtility.SetAllCoversBelly(ApparelSettings.rimNudeData, false);
|
|
}, MenuOptionPriority.Default, null, null, 0f, null, null, true, 0),
|
|
}; Find.WindowStack.Add(new FloatMenu(options));
|
|
}; innerX += singleColumnWidth;
|
|
|
|
// Covers belly
|
|
tempRect = new Rect(innerX + SettingsUtility.Align(buttonWidth, singleColumnWidth), windowY - headerHeight - 5, buttonWidth, headerHeight);
|
|
Widgets.DrawHighlightIfMouseover(tempRect);
|
|
TooltipHandler.TipRegion(tempRect, "Toggles whether this apparel conceals breasts.");
|
|
|
|
if (Widgets.ButtonText(tempRect, "Covers\nbreasts"))
|
|
{
|
|
List<FloatMenuOption> options = new List<FloatMenuOption>
|
|
{
|
|
new FloatMenuOption("Set all 'true'", delegate()
|
|
{ ApparelSettingsUtility.SetAllCoversChest(ApparelSettings.rimNudeData, true);
|
|
}, MenuOptionPriority.Default, null, null, 0f, null, null, true, 0),
|
|
new FloatMenuOption("Set all 'false'", delegate()
|
|
{ ApparelSettingsUtility.SetAllCoversChest(ApparelSettings.rimNudeData, false);
|
|
}, MenuOptionPriority.Default, null, null, 0f, null, null, true, 0),
|
|
}; Find.WindowStack.Add(new FloatMenu(options));
|
|
}; innerX += singleColumnWidth;
|
|
|
|
// Sex wear
|
|
tempRect = new Rect(innerX + SettingsUtility.Align(buttonWidth, singleColumnWidth), windowY - headerHeight - 5, buttonWidth, headerHeight);
|
|
Widgets.DrawHighlightIfMouseover(tempRect);
|
|
TooltipHandler.TipRegion(tempRect, "Toggles whether this piece of apparel should always be kept on during lovin'");
|
|
|
|
if (Widgets.ButtonText(tempRect, "Sex-wear"))
|
|
{
|
|
List<FloatMenuOption> options = new List<FloatMenuOption>
|
|
{
|
|
new FloatMenuOption("Set all 'true'", delegate()
|
|
{ ApparelSettingsUtility.SetAllSexWear(ApparelSettings.rimNudeData, true);
|
|
}, MenuOptionPriority.Default, null, null, 0f, null, null, true, 0),
|
|
new FloatMenuOption("Set all 'false'", delegate()
|
|
{ ApparelSettingsUtility.SetAllSexWear(ApparelSettings.rimNudeData, false);
|
|
}, MenuOptionPriority.Default, null, null, 0f, null, null, true, 0),
|
|
}; Find.WindowStack.Add(new FloatMenu(options));
|
|
}; innerX += singleColumnWidth;
|
|
|
|
// Reset button
|
|
tempRect = new Rect(innerX + SettingsUtility.Align(buttonWidth, singleColumnWidth), windowY - headerHeight - 5, buttonWidth, headerHeight);
|
|
Widgets.DrawHighlightIfMouseover(tempRect);
|
|
TooltipHandler.TipRegion(tempRect, "Returns all values in this table to their default state.");
|
|
|
|
if (Widgets.ButtonText(tempRect, "Reset to\ndefaults"))
|
|
{ ApparelSettingsUtility.ResetRimNudeData(ApparelSettings.rimNudeData); }; innerX += singleColumnWidth + scrollBarWidthMargin;
|
|
|
|
// Determine the height of the scrollable area
|
|
int apparelCount = shortListedApparelDefs.Count();
|
|
float totalContentHeight = rowHeight * (float)apparelCount;
|
|
|
|
// Create a rect for the scroll window
|
|
var contentRect = new Rect(0f, windowY, innerX, windowHeight);
|
|
|
|
// Determine if the scroll will be visible
|
|
bool scrollBarVisible = totalContentHeight > contentRect.height;
|
|
|
|
// Create a rect for the scrollable area
|
|
var scrollViewTotal = new Rect(0f, 0f, innerX - (scrollBarVisible ? scrollBarWidthMargin : 0), totalContentHeight);
|
|
|
|
// Start of content for scrollable area
|
|
Widgets.DrawHighlight(contentRect);
|
|
Widgets.BeginScrollView(contentRect, ref scrollPosition, scrollViewTotal);
|
|
|
|
foreach (ThingDef thingDef in shortListedApparelDefs)
|
|
{
|
|
isEnabled = false;
|
|
|
|
innerX = 0;
|
|
innerY = (float)num * (rowHeight);
|
|
num++;
|
|
|
|
RimNudeData rimNudeApparel = ApparelSettings.rimNudeData.First(x => x.EquivalentTo(new RimNudeData(thingDef)));
|
|
|
|
// Apparel symbol
|
|
Widgets.ThingIcon(new Rect(innerX + SettingsUtility.Align(widgetWidth, halfColumnWidth), innerY + SettingsUtility.Align(widgetHeight, rowHeight), widgetWidth, widgetHeight), thingDef, null, null, 1f, null);
|
|
innerX += halfColumnWidth;
|
|
|
|
// Apparel name
|
|
Text.Anchor = TextAnchor.MiddleLeft;
|
|
Widgets.Label(new Rect(innerX + 10f, innerY + SettingsUtility.Align(labelHeight, rowHeight), labelWidth, labelHeight), thingDef.label.CapitalizeFirst()); innerX += doubleColumnWidth;
|
|
Text.Anchor = TextAnchor.UpperLeft;
|
|
|
|
// Hide groin checkbox
|
|
if (thingDef.apparel.bodyPartGroups.Contains(BodyPartGroupDefOf.Legs) || thingDef.apparel.bodyPartGroups.Contains(PatchBodyPartGroupDefOf.GenitalsBPG))
|
|
{
|
|
isEnabled = rimNudeApparel.coversGroin;
|
|
Widgets.Checkbox(innerX + SettingsUtility.Align(checkboxSize, singleColumnWidth), innerY + SettingsUtility.Align(checkboxSize, rowHeight), ref isEnabled, checkboxSize, false, true, null, null);
|
|
rimNudeApparel.coversGroin = isEnabled;
|
|
}; innerX += singleColumnWidth;
|
|
|
|
// Hide belly checkbox
|
|
if (thingDef.apparel.bodyPartGroups.Contains(BodyPartGroupDefOf.Torso))
|
|
{
|
|
isEnabled = rimNudeApparel.coversBelly;
|
|
Widgets.Checkbox(innerX + SettingsUtility.Align(checkboxSize, singleColumnWidth), innerY + SettingsUtility.Align(checkboxSize, rowHeight), ref isEnabled, checkboxSize, false, true, null, null);
|
|
rimNudeApparel.coversBelly = isEnabled;
|
|
}; innerX += singleColumnWidth;
|
|
|
|
// Covers bust checkbox
|
|
if (thingDef.apparel.bodyPartGroups.Contains(BodyPartGroupDefOf.Torso) || thingDef.apparel.bodyPartGroups.Contains(PatchBodyPartGroupDefOf.ChestBPG))
|
|
{
|
|
isEnabled = rimNudeApparel.coversChest;
|
|
Widgets.Checkbox(innerX + SettingsUtility.Align(checkboxSize, singleColumnWidth), innerY + SettingsUtility.Align(checkboxSize, rowHeight), ref isEnabled, checkboxSize, false, true, null, null);
|
|
rimNudeApparel.coversChest = isEnabled;
|
|
}; innerX += singleColumnWidth;
|
|
|
|
// Is sex-wear checkbox
|
|
isEnabled = rimNudeApparel.sexWear;
|
|
Widgets.Checkbox(innerX + SettingsUtility.Align(checkboxSize, singleColumnWidth), innerY + SettingsUtility.Align(checkboxSize, rowHeight), ref isEnabled, checkboxSize, false, true, null, null);
|
|
rimNudeApparel.sexWear = isEnabled;
|
|
innerX += singleColumnWidth;
|
|
}
|
|
|
|
Widgets.EndScrollView();
|
|
}
|
|
|
|
public sealed override string SettingsCategory()
|
|
{
|
|
return "rimworld_animation_patch_apparelsettings".Translate();
|
|
}
|
|
}
|
|
}
|