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 = new List(); 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 = 250f; 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 static List thingDefs = new List(); public ApparelSettingsDisplay(ModContentPack content) : base(content) { GetSettings(); } public override void WriteSettings() { base.WriteSettings(); ApplySettings(); } // Update all humanlike pawn graphics when settings window is closed public void ApplySettings() { if (Current.ProgramState == ProgramState.Playing) { foreach (Pawn pawn in Current.Game.CurrentMap.mapPawns.AllPawns) { if (pawn.RaceProps.Humanlike && pawn.apparel.WornApparel.NullOrEmpty() == false) { pawn.Drawer.renderer.graphics.ResolveAllGraphics(); } } } } 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 options = new List { 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 options = new List { 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; bool linkChangesChanged = false; // Get a list of apparel of interest if (thingDefs.NullOrEmpty()) { thingDefs = ApparelSettingsUtility.GetApparelOfInterest(); } // 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; // 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. This list can be sorted alphabetically or by the mod that added them."); if (Widgets.ButtonText(tempRect, "Apparel")) { List options = new List { new FloatMenuOption("Sort by name", delegate() { thingDefs = thingDefs.OrderBy(x => x.label).ToList(); }, MenuOptionPriority.Default, null, null, 0f, null, null, true, 0), new FloatMenuOption("Sort by mod", delegate() { thingDefs = ApparelSettingsUtility.GetApparelOfInterest(); }, MenuOptionPriority.Default, null, null, 0f, null, null, true, 0), }; 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 options = new List { 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 options = new List { 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 options = new List { 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 options = new List { 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 = thingDefs.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 thingDefs) { isEnabled = false; bool changeHappened = 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); if (isEnabled != rimNudeApparel.coversGroin) { changeHappened = true; } 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); if (isEnabled != rimNudeApparel.coversBelly) { changeHappened = true; } 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); if (isEnabled != rimNudeApparel.coversChest) { changeHappened = true; } 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); if (isEnabled != rimNudeApparel.sexWear) { changeHappened = true; } rimNudeApparel.sexWear = isEnabled; innerX += singleColumnWidth; // Update other body types if linked changed are enabled if (BasicSettings.linkChanges && (changeHappened || linkChangesChanged)) { for (int i = 0; i < 5; i++) { RimNudeData _rimNudeApparel = ApparelSettings.rimNudeData.First(x => x.EquivalentTo(new RimNudeData(thingDef))); _rimNudeApparel.coversGroin = rimNudeApparel.coversGroin; _rimNudeApparel.coversBelly = rimNudeApparel.coversBelly; _rimNudeApparel.coversChest = rimNudeApparel.coversChest; _rimNudeApparel.sexWear = rimNudeApparel.sexWear; } } } Widgets.EndScrollView(); } public sealed override string SettingsCategory() { return "rimworld_animation_patch_apparelsettings".Translate(); } } }