2022-09-10 01:22:08 +00:00
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
{
2023-02-06 00:41:57 +00:00
private const float windowY = 240f ;
private const float windowHeight = 360f ;
2022-09-10 01:22:08 +00:00
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 ;
2023-02-06 00:41:57 +00:00
private List < ThingDef > shortListedApparelDefs = new List < ThingDef > ( ) ;
private List < ThingDef > allApparelDefs = new List < ThingDef > ( ) ;
2023-02-04 07:13:57 +00:00
2023-02-06 00:41:57 +00:00
private List < ModContentPack > relevantModContentPacks = new List < ModContentPack > ( ) ;
2023-02-04 07:13:57 +00:00
private ModContentPack currentModContentPack ;
2022-09-10 01:22:08 +00:00
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 ( )
{
2023-02-08 01:30:02 +00:00
if ( ApparelSettings . cropApparel = = false )
{
DebugMode . Message ( "Clearing apparel texture cache" ) ;
ApparelSettingsUtility . ClearCachedApparelTextures ( ) ;
}
2022-09-10 01:22:08 +00:00
if ( Current . ProgramState = = ProgramState . Playing )
{
foreach ( Pawn pawn in Current . Game . CurrentMap . mapPawns . AllPawns )
{
2022-10-01 03:51:09 +00:00
if ( pawn = = null ) continue ;
pawn . Drawer ? . renderer ? . graphics ? . ResolveAllGraphics ( ) ;
2022-09-30 23:34:08 +00:00
pawn . TryGetComp < CompPawnSexData > ( ) ? . UpdateBodyAddonVisibility ( ) ;
2022-09-11 06:05:16 +00:00
PortraitsCache . SetDirty ( pawn ) ;
GlobalTextureAtlasManager . TryMarkPawnFrameSetDirty ( pawn ) ;
2022-09-10 01:22:08 +00:00
}
}
}
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 ;
2023-02-04 07:13:57 +00:00
// Get a list of apparel and mods of interest
2023-02-06 00:41:57 +00:00
if ( allApparelDefs . NullOrEmpty ( ) )
2023-02-04 07:13:57 +00:00
{
allApparelDefs = ApparelSettingsUtility . GetApparelOfInterest ( ) ;
foreach ( ThingDef thingDef in allApparelDefs )
2023-02-06 00:41:57 +00:00
{ relevantModContentPacks . AddDistinct ( thingDef . modContentPack ) ; }
currentModContentPack = relevantModContentPacks . FirstOrDefault ( ) ;
if ( currentModContentPack = = null )
{ DebugMode . Message ( "ERROR: No mod content has been loaded?" ) ; return ; }
2023-02-04 07:13:57 +00:00
2023-02-06 00:41:57 +00:00
shortListedApparelDefs = allApparelDefs . Where ( x = > x . modContentPack = = currentModContentPack ) ? . ToList ( ) ;
2023-02-04 07:13:57 +00:00
}
2022-09-10 01:22:08 +00:00
// 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 ;
2023-02-06 00:41:57 +00:00
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 ) ) {
2023-02-04 07:13:57 +00:00
List < FloatMenuOption > options = new List < FloatMenuOption > { } ;
foreach ( ModContentPack modContentPack in relevantModContentPacks )
{
2023-02-06 00:41:57 +00:00
FloatMenuOption option = new FloatMenuOption ( modContentPack . ModMetaData . Name , delegate ( )
{
currentModContentPack = modContentPack ;
shortListedApparelDefs = allApparelDefs . Where ( x = > x . modContentPack = = currentModContentPack ) ? . ToList ( ) ;
} ,
2023-02-04 07:13:57 +00:00
MenuOptionPriority . Default , null , null , 0f , null , null , true , 0 ) ;
options . Add ( option ) ;
}
Find . WindowStack . Add ( new FloatMenu ( options ) ) ;
2022-09-10 01:22:08 +00:00
} ; 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
2023-02-04 07:13:57 +00:00
int apparelCount = shortListedApparelDefs . Count ( ) ;
2022-09-10 01:22:08 +00:00
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 ) ;
2023-02-04 07:13:57 +00:00
foreach ( ThingDef thingDef in shortListedApparelDefs )
2022-09-10 01:22:08 +00:00
{
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 ( ) ;
}
}
}