diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..f83ffb8
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,398 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Ww][Ii][Nn]32/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# ASP.NET Scaffolding
+ScaffoldingReadMe.txt
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.tlog
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Coverlet is a free, cross platform Code Coverage Tool
+coverage*.json
+coverage*.xml
+coverage*.info
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio 6 auto-generated project file (contains which files were open etc.)
+*.vbp
+
+# Visual Studio 6 workspace and project file (working project files containing files to include in project)
+*.dsw
+*.dsp
+
+# Visual Studio 6 technical files
+*.ncb
+*.aps
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# Visual Studio History (VSHistory) files
+.vshistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
+
+# Fody - auto-generated XML schema
+FodyWeavers.xsd
+
+# VS Code files for those working on multiple tools
+.vscode/*
+!.vscode/settings.json
+!.vscode/tasks.json
+!.vscode/launch.json
+!.vscode/extensions.json
+*.code-workspace
+
+# Local History for Visual Studio Code
+.history/
+
+# Windows Installer files from build outputs
+*.cab
+*.msi
+*.msix
+*.msm
+*.msp
+
+# JetBrains Rider
+*.sln.iml
diff --git a/1.3/Assemblies/SizedApparelforRJW.dll b/1.3/Assemblies/SizedApparelforRJW.dll
index 1a56d6d..45fd0ce 100644
Binary files a/1.3/Assemblies/SizedApparelforRJW.dll and b/1.3/Assemblies/SizedApparelforRJW.dll differ
diff --git a/1.3/AssembliesNotion.txt b/1.3/AssembliesNotion.txt
new file mode 100644
index 0000000..a3e6977
--- /dev/null
+++ b/1.3/AssembliesNotion.txt
@@ -0,0 +1 @@
+latest source build: SizedApparel1.4WIP22
\ No newline at end of file
diff --git a/1.3/Defs/BodyAddonDefs/AOCBody.xml b/1.3/Defs/BodyAddonDefs/AOCBody.xml
new file mode 100644
index 0000000..e46e302
--- /dev/null
+++ b/1.3/Defs/BodyAddonDefs/AOCBody.xml
@@ -0,0 +1,131 @@
+
+
+
+
+ AOC
+
+
+ Female
+
+
+ Breasts
+ Breasts
+ Breasts
+ Breasts
+ Skin
+ true
+
+
+ false
+ false
+
+
+ 0.0113
+ 0.001
+ 0.0113
+ 0.0113
+
+
+
+ Vagina
+ Vagina
+ Vagina
+ Vagina
+ Skin
+ false
+ true
+ false
+
+
+ 0.0088
+ 0.0100
+ 0.0088
+ 0.0088
+
+
+
+ Anus
+ Anus
+ Anus
+ Anus
+ Skin
+ false
+ false
+
+
+ 0.0093
+ 0.0105
+ 0.0093
+ 0.0093
+
+
+
+ Belly
+ Belly
+ BellyBulge
+ Belly
+ Skin
+ false
+ false
+
+
+ 0.0098
+ 0.0002
+ 0.0098
+ 0.0098
+
+
+
+ Penis
+ Penis
+ Penis
+ Penis
+ Skin
+ false
+ false
+
+
+ 0.0108
+ 0.0025
+ 0.0108
+ 0.0108
+
+
+
+ Balls
+ Balls
+ Penis
+ Balls
+ Penis/Balls
+ Skin
+ false
+ false
+
+
+ 0.0096
+ 0.0085
+ 0.0096
+ 0.0096
+
+
+
+ PubicHair
+ PubicHair
+ Default
+ PubicHair
+ Hair
+ false
+ false
+
+
+ 0.0099
+ 0.0099
+ 0.0099
+ 0.0099
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/1.3/Defs/BodyAddonDefs/BoriBody.xml b/1.3/Defs/BodyAddonDefs/BoriBody.xml
new file mode 100644
index 0000000..e219291
--- /dev/null
+++ b/1.3/Defs/BodyAddonDefs/BoriBody.xml
@@ -0,0 +1,127 @@
+
+
+
+
+ Alien_Bori
+
+
+ Thin
+
+
+ Breasts
+ Breasts
+ Breasts
+ Breasts
+ Skin
+ true
+ false
+
+
+ 0.0113
+ 0.001
+ 0.0113
+ 0.0113
+
+
+
+ Vagina
+ Vagina
+ Vagina
+ Vagina
+ Skin
+ false
+ false
+
+
+ 0.0088
+ 0.0100
+ 0.0088
+ 0.0088
+
+
+
+ Anus
+ Anus
+ Anus
+ Anus
+ Skin
+ false
+ false
+
+
+ 0.0093
+ 0.0105
+ 0.0093
+ 0.0093
+
+
+
+ Belly
+ Belly
+ BellyBulge
+ Belly
+ Skin
+ false
+ false
+
+
+ 0.0098
+ 0.0002
+ 0.0098
+ 0.0098
+
+
+
+ Penis
+ Penis
+ Penis
+ Penis
+ Skin
+ false
+ false
+
+
+ 0.0108
+ 0.0025
+ 0.0108
+ 0.0108
+
+
+
+ Balls
+ Balls
+ Penis
+ Balls
+ Penis/Balls
+ Skin
+ false
+ false
+
+
+ 0.0096
+ 0.0085
+ 0.0096
+ 0.0096
+
+
+
+ PubicHair
+ PubicHair
+ Default
+ PubicHair
+ Hair
+ false
+ false
+
+
+ 0.0099
+ 0.0099
+ 0.0099
+ 0.0099
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/1.3/Defs/BodyAddonDefs/MihoBody.xml b/1.3/Defs/BodyAddonDefs/MihoBody.xml
new file mode 100644
index 0000000..f059a1f
--- /dev/null
+++ b/1.3/Defs/BodyAddonDefs/MihoBody.xml
@@ -0,0 +1,249 @@
+
+
+
+
+ Alien_Miho
+
+
+ Female
+
+
+ Breasts
+ Breasts
+ Breasts
+ Breasts
+ Skin
+ true
+
+
+ false
+ false
+
+
+ 0.0113
+ 0.001
+ 0.0113
+ 0.0113
+
+
+
+ Vagina
+ Vagina
+ Vagina
+ Vagina
+ Skin
+ false
+ true
+ false
+
+
+ 0.0088
+ 0.0100
+ 0.0088
+ 0.0088
+
+
+
+ Anus
+ Anus
+ Anus
+ Anus
+ Skin
+ false
+ false
+
+
+ 0.0093
+ 0.0105
+ 0.0093
+ 0.0093
+
+
+
+ Belly
+ Belly
+ BellyBulge
+ Belly
+ Skin
+ false
+ false
+
+
+ 0.0098
+ 0.0002
+ 0.0098
+ 0.0098
+
+
+
+ Penis
+ Penis
+ Penis
+ Penis
+ Skin
+ false
+ false
+
+
+ 0.0108
+ 0.0025
+ 0.0108
+ 0.0108
+
+
+
+ Balls
+ Balls
+ Penis
+ Balls
+ Penis/Balls
+ Skin
+ false
+ false
+
+
+ 0.0096
+ 0.0085
+ 0.0096
+ 0.0096
+
+
+
+ PubicHair
+ PubicHair
+ Default
+ PubicHair
+ Hair
+ false
+ false
+
+
+ 0.0099
+ 0.0099
+ 0.0099
+ 0.0099
+
+
+
+
+
+ Thin
+
+
+ Breasts
+ Breasts
+ Breasts
+ Breasts
+ Skin
+ true
+ false
+
+
+ 0.0113
+ 0.001
+ 0.0113
+ 0.0113
+
+
+
+ Vagina
+ Vagina
+ Vagina
+ Vagina
+ Skin
+ false
+ false
+
+
+ 0.0088
+ 0.0100
+ 0.0088
+ 0.0088
+
+
+
+ Anus
+ Anus
+ Anus
+ Anus
+ Skin
+ false
+ false
+
+
+ 0.0093
+ 0.0105
+ 0.0093
+ 0.0093
+
+
+
+ Belly
+ Belly
+ BellyBulge
+ Belly
+ Skin
+ false
+ false
+
+
+ 0.0098
+ 0.0002
+ 0.0098
+ 0.0098
+
+
+
+ Penis
+ Penis
+ Penis
+ Penis
+ Skin
+ false
+ false
+
+
+ 0.0108
+ 0.0025
+ 0.0108
+ 0.0108
+
+
+
+ Balls
+ Balls
+ Penis
+ Balls
+ Penis/Balls
+ Skin
+ false
+ false
+
+
+ 0.0096
+ 0.0085
+ 0.0096
+ 0.0096
+
+
+
+ PubicHair
+ PubicHair
+ Default
+ PubicHair
+ Hair
+ false
+ false
+
+
+ 0.0099
+ 0.0099
+ 0.0099
+ 0.0099
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/1.3/Defs/BodyAddonDefs/RabbieBody.xml b/1.3/Defs/BodyAddonDefs/RabbieBody.xml
new file mode 100644
index 0000000..58682b0
--- /dev/null
+++ b/1.3/Defs/BodyAddonDefs/RabbieBody.xml
@@ -0,0 +1,249 @@
+
+
+
+
+ Rabbie
+
+
+ Thin
+
+
+ Breasts
+ Breasts
+ Breasts
+ Breasts
+ Skin
+ true
+
+
+ false
+ false
+
+
+ 0.0113
+ 0.001
+ 0.0113
+ 0.0113
+
+
+
+ Vagina
+ Vagina
+ Vagina
+ Vagina
+ Skin
+ false
+ true
+ false
+
+
+ 0.0088
+ 0.0100
+ 0.0088
+ 0.0088
+
+
+
+ Anus
+ Anus
+ Anus
+ Anus
+ Skin
+ false
+ false
+
+
+ 0.0093
+ 0.0105
+ 0.0093
+ 0.0093
+
+
+
+ Belly
+ Belly
+ BellyBulge
+ Belly
+ Skin
+ false
+ false
+
+
+ 0.0098
+ 0.0002
+ 0.0098
+ 0.0098
+
+
+
+ Penis
+ Penis
+ Penis
+ Penis
+ Skin
+ false
+ false
+
+
+ 0.0108
+ 0.0025
+ 0.0108
+ 0.0108
+
+
+
+ Balls
+ Balls
+ Penis
+ Balls
+ Penis/Balls
+ Skin
+ false
+ false
+
+
+ 0.0096
+ 0.0085
+ 0.0096
+ 0.0096
+
+
+
+ PubicHair
+ PubicHair
+ Default
+ PubicHair
+ Hair
+ false
+ false
+
+
+ 0.0099
+ 0.0099
+ 0.0099
+ 0.0099
+
+
+
+
+
+ Male
+
+
+ Breasts
+ Breasts
+ Breasts
+ Breasts
+ Skin
+ true
+ false
+
+
+ 0.0113
+ 0.001
+ 0.0113
+ 0.0113
+
+
+
+ Vagina
+ Vagina
+ Vagina
+ Vagina
+ Skin
+ false
+ false
+
+
+ 0.0088
+ 0.0100
+ 0.0088
+ 0.0088
+
+
+
+ Anus
+ Anus
+ Anus
+ Anus
+ Skin
+ false
+ false
+
+
+ 0.0093
+ 0.0105
+ 0.0093
+ 0.0093
+
+
+
+ Belly
+ Belly
+ BellyBulge
+ Belly
+ Skin
+ false
+ false
+
+
+ 0.0098
+ 0.0002
+ 0.0098
+ 0.0098
+
+
+
+ Penis
+ Penis
+ Penis
+ Penis
+ Skin
+ false
+ false
+
+
+ 0.0108
+ 0.0025
+ 0.0108
+ 0.0108
+
+
+
+ Balls
+ Balls
+ Penis
+ Balls
+ Penis/Balls
+ Skin
+ false
+ false
+
+
+ 0.0096
+ 0.0085
+ 0.0096
+ 0.0096
+
+
+
+ PubicHair
+ PubicHair
+ Default
+ PubicHair
+ Hair
+ false
+ false
+
+
+ 0.0099
+ 0.0099
+ 0.0099
+ 0.0099
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/1.3/Defs/BodyAddonDefs/RatkinBody.xml b/1.3/Defs/BodyAddonDefs/RatkinBody.xml
new file mode 100644
index 0000000..67ec55d
--- /dev/null
+++ b/1.3/Defs/BodyAddonDefs/RatkinBody.xml
@@ -0,0 +1,249 @@
+
+
+
+
+ Ratkin
+
+
+ Thin
+
+
+ Breasts
+ Breasts
+ Breasts
+ Breasts
+ Skin
+ true
+
+
+ false
+ false
+
+
+ 0.0113
+ 0.001
+ 0.0113
+ 0.0113
+
+
+
+ Vagina
+ Vagina
+ Vagina
+ Vagina
+ Skin
+ false
+ true
+ false
+
+
+ 0.0088
+ 0.0100
+ 0.0088
+ 0.0088
+
+
+
+ Anus
+ Anus
+ Anus
+ Anus
+ Skin
+ false
+ false
+
+
+ 0.0093
+ 0.0105
+ 0.0093
+ 0.0093
+
+
+
+ Belly
+ Belly
+ BellyBulge
+ Belly
+ Skin
+ false
+ false
+
+
+ 0.0098
+ 0.0002
+ 0.0098
+ 0.0098
+
+
+
+ Penis
+ Penis
+ Penis
+ Penis
+ Skin
+ false
+ false
+
+
+ 0.0108
+ 0.0025
+ 0.0108
+ 0.0108
+
+
+
+ Balls
+ Balls
+ Penis
+ Balls
+ Penis/Balls
+ Skin
+ false
+ false
+
+
+ 0.0096
+ 0.0085
+ 0.0096
+ 0.0096
+
+
+
+ PubicHair
+ PubicHair
+ Default
+ PubicHair
+ Hair
+ false
+ false
+
+
+ 0.0099
+ 0.0099
+ 0.0099
+ 0.0099
+
+
+
+
+
+ Male
+
+
+ Breasts
+ Breasts
+ Breasts
+ Breasts
+ Skin
+ true
+ false
+
+
+ 0.0113
+ 0.001
+ 0.0113
+ 0.0113
+
+
+
+ Vagina
+ Vagina
+ Vagina
+ Vagina
+ Skin
+ false
+ false
+
+
+ 0.0088
+ 0.0100
+ 0.0088
+ 0.0088
+
+
+
+ Anus
+ Anus
+ Anus
+ Anus
+ Skin
+ false
+ false
+
+
+ 0.0093
+ 0.0105
+ 0.0093
+ 0.0093
+
+
+
+ Belly
+ Belly
+ BellyBulge
+ Belly
+ Skin
+ false
+ false
+
+
+ 0.0098
+ 0.0002
+ 0.0098
+ 0.0098
+
+
+
+ Penis
+ Penis
+ Penis
+ Penis
+ Skin
+ false
+ false
+
+
+ 0.0108
+ 0.0025
+ 0.0108
+ 0.0108
+
+
+
+ Balls
+ Balls
+ Penis
+ Balls
+ Penis/Balls
+ Skin
+ false
+ false
+
+
+ 0.0096
+ 0.0085
+ 0.0096
+ 0.0096
+
+
+
+ PubicHair
+ PubicHair
+ Default
+ PubicHair
+ Hair
+ false
+ false
+
+
+ 0.0099
+ 0.0099
+ 0.0099
+ 0.0099
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/1.3/Defs/BodyAddonDefs/Ratkin_SuBody.xml b/1.3/Defs/BodyAddonDefs/Ratkin_SuBody.xml
new file mode 100644
index 0000000..be80c0c
--- /dev/null
+++ b/1.3/Defs/BodyAddonDefs/Ratkin_SuBody.xml
@@ -0,0 +1,249 @@
+
+
+
+
+ Ratkin_Su
+
+
+ Thin
+
+
+ Breasts
+ Breasts
+ Breasts
+ Breasts
+ Skin
+ true
+
+
+ false
+ false
+
+
+ 0.0113
+ 0.001
+ 0.0113
+ 0.0113
+
+
+
+ Vagina
+ Vagina
+ Vagina
+ Vagina
+ Skin
+ false
+ true
+ false
+
+
+ 0.0088
+ 0.0100
+ 0.0088
+ 0.0088
+
+
+
+ Anus
+ Anus
+ Anus
+ Anus
+ Skin
+ false
+ false
+
+
+ 0.0093
+ 0.0105
+ 0.0093
+ 0.0093
+
+
+
+ Belly
+ Belly
+ BellyBulge
+ Belly
+ Skin
+ false
+ false
+
+
+ 0.0098
+ 0.0002
+ 0.0098
+ 0.0098
+
+
+
+ Penis
+ Penis
+ Penis
+ Penis
+ Skin
+ false
+ false
+
+
+ 0.0108
+ 0.0025
+ 0.0108
+ 0.0108
+
+
+
+ Balls
+ Balls
+ Penis
+ Balls
+ Penis/Balls
+ Skin
+ false
+ false
+
+
+ 0.0096
+ 0.0085
+ 0.0096
+ 0.0096
+
+
+
+ PubicHair
+ PubicHair
+ Default
+ PubicHair
+ Hair
+ false
+ false
+
+
+ 0.0099
+ 0.0099
+ 0.0099
+ 0.0099
+
+
+
+
+
+ Male
+
+
+ Breasts
+ Breasts
+ Breasts
+ Breasts
+ Skin
+ true
+ false
+
+
+ 0.0113
+ 0.001
+ 0.0113
+ 0.0113
+
+
+
+ Vagina
+ Vagina
+ Vagina
+ Vagina
+ Skin
+ false
+ false
+
+
+ 0.0088
+ 0.0100
+ 0.0088
+ 0.0088
+
+
+
+ Anus
+ Anus
+ Anus
+ Anus
+ Skin
+ false
+ false
+
+
+ 0.0093
+ 0.0105
+ 0.0093
+ 0.0093
+
+
+
+ Belly
+ Belly
+ BellyBulge
+ Belly
+ Skin
+ false
+ false
+
+
+ 0.0098
+ 0.0002
+ 0.0098
+ 0.0098
+
+
+
+ Penis
+ Penis
+ Penis
+ Penis
+ Skin
+ false
+ false
+
+
+ 0.0108
+ 0.0025
+ 0.0108
+ 0.0108
+
+
+
+ Balls
+ Balls
+ Penis
+ Balls
+ Penis/Balls
+ Skin
+ false
+ false
+
+
+ 0.0096
+ 0.0085
+ 0.0096
+ 0.0096
+
+
+
+ PubicHair
+ PubicHair
+ Default
+ PubicHair
+ Hair
+ false
+ false
+
+
+ 0.0099
+ 0.0099
+ 0.0099
+ 0.0099
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/1.3/Defs/BodyAddonDefs/SPBody.xml b/1.3/Defs/BodyAddonDefs/SPBody.xml
new file mode 100644
index 0000000..89abc6b
--- /dev/null
+++ b/1.3/Defs/BodyAddonDefs/SPBody.xml
@@ -0,0 +1,131 @@
+
+
+
+
+ Alien_SP
+
+
+ Female
+
+
+ Breasts
+ Breasts
+ Breasts
+ Breasts
+ Skin
+ true
+
+
+ false
+ false
+
+
+ 0.0113
+ 0.001
+ 0.0113
+ 0.0113
+
+
+
+ Vagina
+ Vagina
+ Vagina
+ Vagina
+ Skin
+ false
+ true
+ false
+
+
+ 0.0088
+ 0.0100
+ 0.0088
+ 0.0088
+
+
+
+ Anus
+ Anus
+ Anus
+ Anus
+ Skin
+ false
+ false
+
+
+ 0.0093
+ 0.0105
+ 0.0093
+ 0.0093
+
+
+
+ Belly
+ Belly
+ BellyBulge
+ Belly
+ Skin
+ false
+ false
+
+
+ 0.0098
+ 0.0002
+ 0.0098
+ 0.0098
+
+
+
+ Penis
+ Penis
+ Penis
+ Penis
+ Skin
+ false
+ false
+
+
+ 0.0108
+ 0.0025
+ 0.0108
+ 0.0108
+
+
+
+ Balls
+ Balls
+ Penis
+ Balls
+ Penis/Balls
+ Skin
+ false
+ false
+
+
+ 0.0096
+ 0.0085
+ 0.0096
+ 0.0096
+
+
+
+ PubicHair
+ PubicHair
+ Default
+ PubicHair
+ Hair
+ false
+ false
+
+
+ 0.0099
+ 0.0099
+ 0.0099
+ 0.0099
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/1.3/Defs/BodyAddonDefs/_HumanBody.xml b/1.3/Defs/BodyAddonDefs/_HumanBody.xml
new file mode 100644
index 0000000..7e7a0a1
--- /dev/null
+++ b/1.3/Defs/BodyAddonDefs/_HumanBody.xml
@@ -0,0 +1,717 @@
+
+
+
+ Human
+
+
+ Female
+
+
+ Breasts
+ Breasts
+ Breasts
+ Breasts
+ Skin
+ true
+
+
+ false
+ false
+
+
+ 0.0113
+ 0.001
+ 0.0113
+ 0.0113
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Vagina
+ Vagina
+ Vagina
+ Vagina
+ Skin
+ false
+ true
+ true
+
+
+ 0.0088
+ 0.0100
+ 0.0088
+ 0.0088
+
+
+
+ Anus
+ Anus
+ Anus
+ Anus
+ Skin
+ false
+ true
+
+
+ 0.0093
+ 0.0105
+ 0.0093
+ 0.0093
+
+
+
+ Belly
+ Belly
+ BellyBulge
+ Belly
+ Skin
+ false
+ false
+
+
+ 0.0098
+ 0.0002
+ 0.0098
+ 0.0098
+
+
+
+ Penis
+ Penis
+ Penis
+ Penis
+ Skin
+ false
+ true
+
+
+ 0.0108
+ 0.0025
+ 0.0108
+ 0.0108
+
+
+
+ Balls
+ Balls
+ Penis
+ Balls
+ Penis/Balls
+ Skin
+ false
+ true
+
+
+ 0.0096
+ 0.0085
+ 0.0096
+ 0.0096
+
+
+
+ PubicHair
+ PubicHair
+ Default
+ PubicHair
+ Hair
+ false
+ true
+
+
+ 0.0099
+ 0.0099
+ 0.0099
+ 0.0099
+
+
+
+
+
+ Thin
+
+
+ Breasts
+ Breasts
+ Breasts
+ Breasts
+ Skin
+ true
+ false
+
+
+ 0.0113
+ 0.001
+ 0.0113
+ 0.0113
+
+
+
+ Vagina
+ Vagina
+ Vagina
+ Vagina
+ Skin
+ false
+ true
+
+
+ 0.0088
+ 0.0100
+ 0.0088
+ 0.0088
+
+
+
+ Anus
+ Anus
+ Anus
+ Anus
+ Skin
+ false
+ true
+
+
+ 0.0093
+ 0.0105
+ 0.0093
+ 0.0093
+
+
+
+ Belly
+ Belly
+ BellyBulge
+ Belly
+ Skin
+ false
+ false
+
+
+ 0.0098
+ 0.0002
+ 0.0098
+ 0.0098
+
+
+
+ Penis
+ Penis
+ Penis
+ Penis
+ Skin
+ false
+ true
+
+
+ 0.0108
+ 0.0025
+ 0.0108
+ 0.0108
+
+
+
+ Balls
+ Balls
+ Penis
+ Balls
+ Penis/Balls
+ Skin
+ false
+ true
+
+
+ 0.0096
+ 0.0085
+ 0.0096
+ 0.0096
+
+
+
+ PubicHair
+ PubicHair
+ Default
+ PubicHair
+ Hair
+ false
+ true
+
+
+ 0.0099
+ 0.0099
+ 0.0099
+ 0.0099
+
+
+
+
+
+ Male
+
+
+ Breasts
+ Breasts
+ Breasts
+ Breasts
+ Skin
+ true
+ false
+
+
+ 0.0113
+ 0.001
+ 0.0113
+ 0.0113
+
+
+
+ Vagina
+ Vagina
+ Vagina
+ Vagina
+ Skin
+ false
+ true
+
+
+ 0.0088
+ 0.0100
+ 0.0088
+ 0.0088
+
+
+
+ Anus
+ Anus
+ Anus
+ Anus
+ Skin
+ false
+ true
+
+
+ 0.0093
+ 0.0105
+ 0.0093
+ 0.0093
+
+
+
+ Belly
+ Belly
+ BellyBulge
+ Belly
+ Skin
+ false
+ false
+
+
+ 0.0098
+ 0.0002
+ 0.0098
+ 0.0098
+
+
+
+ Penis
+ Penis
+ Penis
+ Penis
+ Skin
+ false
+ true
+
+
+ 0.0108
+ 0.0025
+ 0.0108
+ 0.0108
+
+
+
+ Balls
+ Balls
+ Penis
+ Balls
+ Penis/Balls
+ Skin
+ false
+ true
+
+
+ 0.0096
+ 0.0085
+ 0.0096
+ 0.0096
+
+
+
+ PubicHair
+ PubicHair
+ Default
+ PubicHair
+ Hair
+ false
+ true
+
+
+ 0.0099
+ 0.0099
+ 0.0099
+ 0.0099
+
+
+
+
+
+ Hulk
+
+
+ Breasts
+ Breasts
+ Breasts
+ Breasts
+ Skin
+ true
+ false
+
+
+ 0.0113
+ 0.001
+ 0.0113
+ 0.0113
+
+
+
+ Vagina
+ Vagina
+ Vagina
+ Vagina
+ Skin
+ false
+ true
+
+
+ 0.0088
+ 0.0100
+ 0.0088
+ 0.0088
+
+
+
+ Anus
+ Anus
+ Anus
+ Anus
+ Skin
+ false
+ true
+
+
+ 0.0093
+ 0.0105
+ 0.0093
+ 0.0093
+
+
+
+ Belly
+ Belly
+ BellyBulge
+ Belly
+ Skin
+ false
+ false
+
+
+ 0.0098
+ 0.0002
+ 0.0098
+ 0.0098
+
+
+
+ Penis
+ Penis
+ Penis
+ Penis
+ Skin
+ false
+ true
+
+
+ 0.0108
+ 0.0025
+ 0.0108
+ 0.0108
+
+
+
+ Balls
+ Balls
+ Penis
+ Balls
+ Penis/Balls
+ Skin
+ false
+ true
+
+
+ 0.0096
+ 0.0085
+ 0.0096
+ 0.0096
+
+
+
+ PubicHair
+ PubicHair
+ Default
+ PubicHair
+ Hair
+ false
+ true
+
+
+ 0.0099
+ 0.0099
+ 0.0099
+ 0.0099
+
+
+
+
+
+ Fat
+
+
+ Breasts
+ Breasts
+ Breasts
+ Breasts
+ Skin
+ true
+ false
+
+
+ 0.0113
+ 0.001
+ 0.0113
+ 0.0113
+
+
+
+ Vagina
+ Vagina
+ Vagina
+ Vagina
+ Skin
+ false
+ true
+
+
+ 0.0088
+ 0.0100
+ 0.0088
+ 0.0088
+
+
+
+ Anus
+ Anus
+ Anus
+ Anus
+ Skin
+ false
+ true
+
+
+ 0.0093
+ 0.0105
+ 0.0093
+ 0.0093
+
+
+
+ Belly
+ Belly
+ BellyBulge
+ Belly
+ Skin
+ false
+ false
+
+
+ 0.0098
+ 0.0002
+ 0.0098
+ 0.0098
+
+
+
+ Penis
+ Penis
+ Penis
+ Penis
+ Skin
+ false
+ true
+
+
+ 0.0108
+ 0.0025
+ 0.0108
+ 0.0108
+
+
+
+ Balls
+ Balls
+ Penis
+ Balls
+ Penis/Balls
+ Skin
+ false
+ true
+
+
+ 0.0096
+ 0.0085
+ 0.0096
+ 0.0096
+
+
+
+ PubicHair
+ PubicHair
+ Default
+ PubicHair
+ Hair
+ false
+ true
+
+
+ 0.0099
+ 0.0099
+ 0.0099
+ 0.0099
+
+
+
+
+
+ Child
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/1.3/Defs/BodyAddonDefs/_HumanBody.xml.bak b/1.3/Defs/BodyAddonDefs/_HumanBody.xml.bak
new file mode 100644
index 0000000..3a6a487
--- /dev/null
+++ b/1.3/Defs/BodyAddonDefs/_HumanBody.xml.bak
@@ -0,0 +1,717 @@
+
+
+
+ Human
+
+
+ Female
+
+
+ Breasts
+ Breasts
+ Breasts
+ Breasts
+ Skin
+ true
+
+
+ false
+ false
+
+
+ 0.0113
+ 0.001
+ 0.0113
+ 0.0113
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Vagina
+ Vagina
+ Vagina
+ Vagina
+ Skin
+ false
+ true
+ true
+
+
+ 0.0088
+ 0.0100
+ 0.0088
+ 0.0088
+
+
+
+ Anus
+ Anus
+ Anus
+ Anus
+ Skin
+ false
+ true
+
+
+ 0.0093
+ 0.0105
+ 0.0093
+ 0.0093
+
+
+
+ Belly
+ Belly
+ BellyBulge
+ Belly
+ Skin
+ false
+ false
+
+
+ 0.0098
+ 0.0002
+ 0.0098
+ 0.0098
+
+
+
+ Penis
+ Penis
+ Penis
+ Penis
+ Skin
+ false
+ true
+
+
+ 0.0108
+ 0.0025
+ 0.0108
+ 0.0108
+
+
+
+ Balls
+ Balls
+ Penis
+ Balls
+ Penis/Balls
+ Skin
+ false
+ true
+
+
+ 0.0096
+ 0.0085
+ 0.0096
+ 0.0096
+
+
+
+ PubicHair
+ PubicHair
+ Default
+ PubicHair
+ Hair
+ false
+ true
+
+
+ 0.0099
+ 0.0099
+ 0.0099
+ 0.0099
+
+
+
+
+
+ Thin
+
+
+ Breasts
+ Breasts
+ Breasts
+ Breasts
+ Skin
+ true
+ false
+
+
+ 0.0113
+ 0.001
+ 0.0113
+ 0.0113
+
+
+
+ Vagina
+ Vagina
+ Vagina
+ Vagina
+ Skin
+ false
+ true
+
+
+ 0.0088
+ 0.0100
+ 0.0088
+ 0.0088
+
+
+
+ Anus
+ Anus
+ Anus
+ Anus
+ Skin
+ false
+ true
+
+
+ 0.0093
+ 0.0105
+ 0.0093
+ 0.0093
+
+
+
+ Belly
+ Belly
+ BellyBulge
+ Belly
+ Skin
+ false
+ false
+
+
+ 0.0098
+ 0.0002
+ 0.0098
+ 0.0098
+
+
+
+ Penis
+ Penis
+ Penis
+ Penis
+ Skin
+ false
+ true
+
+
+ 0.0108
+ 0.0025
+ 0.0108
+ 0.0108
+
+
+
+ Balls
+ Balls
+ Penis
+ Balls
+ Penis/Balls
+ Skin
+ false
+ true
+
+
+ 0.0096
+ 0.0085
+ 0.0096
+ 0.0096
+
+
+
+ PubicHair
+ PubicHair
+ Default
+ PubicHair
+ Hair
+ false
+ true
+
+
+ 0.0099
+ 0.0099
+ 0.0099
+ 0.0099
+
+
+
+
+
+ Male
+
+
+ Breasts
+ Breasts
+ Breasts
+ Breasts
+ Skin
+ true
+ false
+
+
+ 0.0113
+ 0.001
+ 0.0113
+ 0.0113
+
+
+
+ Vagina
+ Vagina
+ Vagina
+ Vagina
+ Skin
+ false
+ true
+
+
+ 0.0088
+ 0.0100
+ 0.0088
+ 0.0088
+
+
+
+ Anus
+ Anus
+ Anus
+ Anus
+ Skin
+ false
+ true
+
+
+ 0.0093
+ 0.0105
+ 0.0093
+ 0.0093
+
+
+
+ Belly
+ Belly
+ BellyBulge
+ Belly
+ Skin
+ false
+ false
+
+
+ 0.0098
+ 0.0002
+ 0.0098
+ 0.0098
+
+
+
+ Penis
+ Penis
+ Penis
+ Penis
+ Skin
+ false
+ true
+
+
+ 0.0108
+ 0.0025
+ 0.0108
+ 0.0108
+
+
+
+ Balls
+ Balls
+ Penis
+ Balls
+ Penis/Balls
+ Skin
+ false
+ true
+
+
+ 0.0096
+ 0.0085
+ 0.0096
+ 0.0096
+
+
+
+ PubicHair
+ PubicHair
+ Default
+ PubicHair
+ Hair
+ false
+ true
+
+
+ 0.0099
+ 0.0099
+ 0.0099
+ 0.0099
+
+
+
+
+
+ Hulk
+
+
+ Breasts
+ Breasts
+ Breasts
+ Breasts
+ Skin
+ true
+ false
+
+
+ 0.0113
+ 0.001
+ 0.0113
+ 0.0113
+
+
+
+ Vagina
+ Vagina
+ Vagina
+ Vagina
+ Skin
+ false
+ true
+
+
+ 0.0088
+ 0.0100
+ 0.0088
+ 0.0088
+
+
+
+ Anus
+ Anus
+ Anus
+ Anus
+ Skin
+ false
+ true
+
+
+ 0.0093
+ 0.0105
+ 0.0093
+ 0.0093
+
+
+
+ Belly
+ Belly
+ BellyBulge
+ Belly
+ Skin
+ false
+ false
+
+
+ 0.0098
+ 0.0002
+ 0.0098
+ 0.0098
+
+
+
+ Penis
+ Penis
+ Penis
+ Penis
+ Skin
+ false
+ true
+
+
+ 0.0108
+ 0.0025
+ 0.0108
+ 0.0108
+
+
+
+ Balls
+ Balls
+ Penis
+ Balls
+ Penis/Balls
+ Skin
+ false
+ true
+
+
+ 0.0096
+ 0.0085
+ 0.0096
+ 0.0096
+
+
+
+ PubicHair
+ PubicHair
+ Default
+ PubicHair
+ Hair
+ false
+ true
+
+
+ 0.0099
+ 0.0099
+ 0.0099
+ 0.0099
+
+
+
+
+
+ Fat
+
+
+ Breasts
+ Breasts
+ Breasts
+ Breasts
+ Skin
+ true
+ false
+
+
+ 0.0113
+ 0.001
+ 0.0113
+ 0.0113
+
+
+
+ Vagina
+ Vagina
+ Vagina
+ Vagina
+ Skin
+ false
+ true
+
+
+ 0.0088
+ 0.0100
+ 0.0088
+ 0.0088
+
+
+
+ Anus
+ Anus
+ Anus
+ Anus
+ Skin
+ false
+ true
+
+
+ 0.0093
+ 0.0105
+ 0.0093
+ 0.0093
+
+
+
+ Belly
+ Belly
+ BellyBulge
+ Belly
+ Skin
+ false
+ false
+
+
+ 0.0098
+ 0.0002
+ 0.0098
+ 0.0098
+
+
+
+ Penis
+ Penis
+ Penis
+ Penis
+ Skin
+ false
+ true
+
+
+ 0.0108
+ 0.0025
+ 0.0108
+ 0.0108
+
+
+
+ Balls
+ Balls
+ Penis
+ Balls
+ Penis/Balls
+ Skin
+ false
+ true
+
+
+ 0.0096
+ 0.0085
+ 0.0096
+ 0.0096
+
+
+
+ PubicHair
+ PubicHair
+ Default
+ PubicHair
+ Hair
+ false
+ true
+
+
+ 0.0099
+ 0.0099
+ 0.0099
+ 0.0099
+
+
+
+
+
+ Child
+
+
+ Breasts
+ Breasts
+ Breasts
+ Breasts
+ Skin
+ true
+ false
+ false
+
+ 0.0113
+ 0.001
+ 0.0113
+ 0.0113
+
+
+
+ Vagina
+ Vagina
+ Vagina
+ Vagina
+ Skin
+ false
+ true
+ true
+
+ 0.0088
+ 0.0100
+ 0.0088
+ 0.0088
+
+
+
+ Anus
+ Anus
+ Anus
+ Anus
+ Skin
+ false
+ true
+
+ 0.0093
+ 0.0105
+ 0.0093
+ 0.0093
+
+
+
+ Belly
+ Belly
+ BellyBulge
+ Belly
+ Skin
+ false
+ false
+
+ 0.0098
+ 0.0002
+ 0.0098
+ 0.0098
+
+
+
+ Penis
+ Penis
+ Penis
+ Penis
+ Skin
+ false
+ true
+
+ 0.0108
+ 0.0025
+ 0.0108
+ 0.0108
+
+
+
+ Balls
+ Balls
+ Penis
+ Balls
+ Penis/Balls
+ Skin
+ false
+ true
+
+ 0.0096
+ 0.0085
+ 0.0096
+ 0.0096
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Defs/BodyPartDetailDefs/BodypartDetail_Anus.xml b/1.3/Defs/BodyPartDetailDefs/BodypartDetail_Anus.xml
similarity index 100%
rename from Defs/BodyPartDetailDefs/BodypartDetail_Anus.xml
rename to 1.3/Defs/BodyPartDetailDefs/BodypartDetail_Anus.xml
diff --git a/Defs/BodyPartDetailDefs/BodypartDetail_Breasts.xml b/1.3/Defs/BodyPartDetailDefs/BodypartDetail_Breasts.xml
similarity index 100%
rename from Defs/BodyPartDetailDefs/BodypartDetail_Breasts.xml
rename to 1.3/Defs/BodyPartDetailDefs/BodypartDetail_Breasts.xml
diff --git a/Defs/BodyPartDetailDefs/BodypartDetail_Penis.xml b/1.3/Defs/BodyPartDetailDefs/BodypartDetail_Penis.xml
similarity index 100%
rename from Defs/BodyPartDetailDefs/BodypartDetail_Penis.xml
rename to 1.3/Defs/BodyPartDetailDefs/BodypartDetail_Penis.xml
diff --git a/Defs/BodyPartDetailDefs/BodypartDetail_Vagina.xml b/1.3/Defs/BodyPartDetailDefs/BodypartDetail_Vagina.xml
similarity index 100%
rename from Defs/BodyPartDetailDefs/BodypartDetail_Vagina.xml
rename to 1.3/Defs/BodyPartDetailDefs/BodypartDetail_Vagina.xml
diff --git a/Defs/Defs(BodyDefsWip).zip b/1.3/Defs/Defs(BodyDefsWip).zip
similarity index 100%
rename from Defs/Defs(BodyDefsWip).zip
rename to 1.3/Defs/Defs(BodyDefsWip).zip
diff --git a/Defs/Defs(wip).zip b/1.3/Defs/Defs(wip).zip
similarity index 100%
rename from Defs/Defs(wip).zip
rename to 1.3/Defs/Defs(wip).zip
diff --git a/1.3/Defs/PubicHairDefs/PubicHairDefault.xml b/1.3/Defs/PubicHairDefs/PubicHairDefault.xml
new file mode 100644
index 0000000..e0e0b0c
--- /dev/null
+++ b/1.3/Defs/PubicHairDefs/PubicHairDefault.xml
@@ -0,0 +1,11 @@
+
+
+
+
+ Default
+
+ SizedApparel/BodyParts/Human/PubicHair/Default
+
+
+
+
diff --git a/1.3/Defs/PubicHairDefs/PubicHairLine.xml b/1.3/Defs/PubicHairDefs/PubicHairLine.xml
new file mode 100644
index 0000000..f2b027e
--- /dev/null
+++ b/1.3/Defs/PubicHairDefs/PubicHairLine.xml
@@ -0,0 +1,11 @@
+
+
+
+
+ Line
+
+ SizedApparel/BodyParts/Human/PubicHair/Line
+
+
+
+
diff --git a/1.3/Defs/PubicHairDefs/PubicHairLine.xml.bak b/1.3/Defs/PubicHairDefs/PubicHairLine.xml.bak
new file mode 100644
index 0000000..4bf42a4
--- /dev/null
+++ b/1.3/Defs/PubicHairDefs/PubicHairLine.xml.bak
@@ -0,0 +1,11 @@
+
+
+
+
+ Wild
+
+ SizedApparel/BodyParts/Human/PubicHair/Wild
+
+
+
+
diff --git a/1.3/Defs/PubicHairDefs/PubicHairNone.xml b/1.3/Defs/PubicHairDefs/PubicHairNone.xml
new file mode 100644
index 0000000..a49bf4e
--- /dev/null
+++ b/1.3/Defs/PubicHairDefs/PubicHairNone.xml
@@ -0,0 +1,7 @@
+
+
+
+ None
+ true
+
+
diff --git a/1.3/Defs/PubicHairDefs/PubicHairWild.xml b/1.3/Defs/PubicHairDefs/PubicHairWild.xml
new file mode 100644
index 0000000..4bf42a4
--- /dev/null
+++ b/1.3/Defs/PubicHairDefs/PubicHairWild.xml
@@ -0,0 +1,11 @@
+
+
+
+
+ Wild
+
+ SizedApparel/BodyParts/Human/PubicHair/Wild
+
+
+
+
diff --git a/1.3/Defs/SkeletonDef/AOCSkeletonDef.xml b/1.3/Defs/SkeletonDef/AOCSkeletonDef.xml
new file mode 100644
index 0000000..d927691
--- /dev/null
+++ b/1.3/Defs/SkeletonDef/AOCSkeletonDef.xml
@@ -0,0 +1,123 @@
+
+
+
+ AOC
+
+
+ Female
+
+
+ Vagina
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+ Breasts
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+ Anus
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+ Penis
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+ Balls
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+ Belly
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+ PubicHair
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+
+
+ Child
+
+
+
+
+
+
\ No newline at end of file
diff --git a/1.3/Defs/SkeletonDef/BoriSkeletonDef.xml b/1.3/Defs/SkeletonDef/BoriSkeletonDef.xml
new file mode 100644
index 0000000..11e2645
--- /dev/null
+++ b/1.3/Defs/SkeletonDef/BoriSkeletonDef.xml
@@ -0,0 +1,123 @@
+
+
+
+ Alien_Bori
+
+
+ Thin
+
+
+ Vagina
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+ Breasts
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+ Anus
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+ Penis
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+ Balls
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+ Belly
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+ PubicHair
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+
+
+ Child
+
+
+
+
+
+
\ No newline at end of file
diff --git a/1.3/Defs/SkeletonDef/MihoSkeletonDef.xml b/1.3/Defs/SkeletonDef/MihoSkeletonDef.xml
new file mode 100644
index 0000000..d13758e
--- /dev/null
+++ b/1.3/Defs/SkeletonDef/MihoSkeletonDef.xml
@@ -0,0 +1,233 @@
+
+
+
+ Alien_Miho
+
+
+ Thin
+
+
+ Vagina
+
+ (0, 0, -0.148)
+ 0
+
+
+ (-0.006, 0, -0.150)
+ 0
+
+
+ (-0.006, 0, -0.143)
+ 0
+
+
+
+ Breasts
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+ Anus
+
+ (0, 0, -0.129)
+ 0
+
+
+ (-0.006, 0, -0.139
+ 0
+
+
+ (-0.061, 0, -0.155)
+ 0
+
+
+
+ Penis
+
+ (0, 0, -0.141)
+ 0
+
+
+ (-0.006, 0, -0.141)
+ 0
+
+
+ (-0.004, 0, -0.139)
+ 0
+
+
+
+ Balls
+
+ (0, 0, -0.141)
+ 0
+
+
+ (-0.006, 0, -0.141))
+ 0
+
+
+ (-0.004, 0, -0.139)
+ 0
+
+
+
+ Belly
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+ PubicHair
+
+ (0, 0, -0.121)
+ 0
+
+
+ (-0.006, 0, -0.109)
+ 0
+
+
+ (0.004, 0, -0.123)
+ 0
+
+
+
+
+
+ Female
+
+
+ Vagina
+
+ (0, 0, -0.148)
+ 0
+
+
+ (-0.006, 0, -0.150)
+ 0
+
+
+ (-0.006, 0, -0.143)
+ 0
+
+
+
+ Breasts
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+ Anus
+
+ (0, 0, -0.129)
+ 0
+
+
+ (-0.006, 0, -0.139)
+ 0
+
+
+ (-0.061, 0, -0.155)
+ 0
+
+
+
+ Penis
+
+ (0, 0, -0.141)
+ 0
+
+
+ (-0.006, 0, -0.141)
+ 0
+
+
+ (-0.004, 0, -0.139)
+ 0
+
+
+
+ Balls
+
+ (0, 0, -0.141)
+ 0
+
+
+ (-0.006, 0, -0.141)
+ 0
+
+
+ (-0.004, 0, -0.139)
+ 0
+
+
+
+ Belly
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0.004, 0, -0.123))
+ 0
+
+
+
+ PubicHair
+
+ (0, 0, -0.121)
+ 0
+
+
+ (-0.006, 0, -0.109)
+ 0
+
+
+ (0.004, 0, -0.123)
+ 0
+
+
+
+
+
+ Child
+
+
+
+
+
+
\ No newline at end of file
diff --git a/1.3/Defs/SkeletonDef/RabbieSkeletonDef.xml b/1.3/Defs/SkeletonDef/RabbieSkeletonDef.xml
new file mode 100644
index 0000000..ebb6a16
--- /dev/null
+++ b/1.3/Defs/SkeletonDef/RabbieSkeletonDef.xml
@@ -0,0 +1,233 @@
+
+
+
+ Rabbie
+
+
+ Thin
+
+
+ Vagina
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+ Breasts
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+ Anus
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+ Penis
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+ Balls
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+ Belly
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+ PubicHair
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+
+
+ Male
+
+
+ Vagina
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+ Breasts
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+ Anus
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+ Penis
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+ Balls
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+ Belly
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+ PubicHair
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+
+
+ Child
+
+
+
+
+
+
\ No newline at end of file
diff --git a/1.3/Defs/SkeletonDef/RatkinSkeletonDef.xml b/1.3/Defs/SkeletonDef/RatkinSkeletonDef.xml
new file mode 100644
index 0000000..850f0dd
--- /dev/null
+++ b/1.3/Defs/SkeletonDef/RatkinSkeletonDef.xml
@@ -0,0 +1,233 @@
+
+
+
+ Ratkin
+
+
+ Thin
+
+
+ Vagina
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+ Breasts
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+ Anus
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+ Penis
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+ Balls
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+ Belly
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+ PubicHair
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+
+
+ Male
+
+
+ Vagina
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+ Breasts
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+ Anus
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+ Penis
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+ Balls
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+ Belly
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+ PubicHair
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+
+
+ Child
+
+
+
+
+
+
\ No newline at end of file
diff --git a/1.3/Defs/SkeletonDef/RatkinSuSkeletonDef.xml b/1.3/Defs/SkeletonDef/RatkinSuSkeletonDef.xml
new file mode 100644
index 0000000..73bf8f7
--- /dev/null
+++ b/1.3/Defs/SkeletonDef/RatkinSuSkeletonDef.xml
@@ -0,0 +1,233 @@
+
+
+
+ Ratkin_Su
+
+
+ Thin
+
+
+ Vagina
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+ Breasts
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+ Anus
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+ Penis
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+ Balls
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+ Belly
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+ PubicHair
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+
+
+ Male
+
+
+ Vagina
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+ Breasts
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+ Anus
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+ Penis
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+ Balls
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+ Belly
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+ PubicHair
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+
+
+ Child
+
+
+
+
+
+
\ No newline at end of file
diff --git a/1.3/Defs/SkeletonDef/SPSkeletonDef.xml b/1.3/Defs/SkeletonDef/SPSkeletonDef.xml
new file mode 100644
index 0000000..5dec2cf
--- /dev/null
+++ b/1.3/Defs/SkeletonDef/SPSkeletonDef.xml
@@ -0,0 +1,123 @@
+
+
+
+ Alien_SP
+
+
+ Female
+
+
+ Vagina
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+ Breasts
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+ Anus
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+ Penis
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+ Balls
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+ Belly
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+ PubicHair
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+
+
+ Child
+
+
+
+
+
+
\ No newline at end of file
diff --git a/1.3/Defs/SkeletonDef/_HumanSkeletonDef.xml b/1.3/Defs/SkeletonDef/_HumanSkeletonDef.xml
new file mode 100644
index 0000000..cc1a6c7
--- /dev/null
+++ b/1.3/Defs/SkeletonDef/_HumanSkeletonDef.xml
@@ -0,0 +1,668 @@
+
+
+
+ Human
+
+
+ Female
+
+
+ Vagina
+
+ (-0.002, 0, -0.340)
+ 0
+
+
+ (-0.006, 0, -0.346)
+ 0
+
+
+ (0.047, 0, -0.238)
+ 0
+
+
+
+ Breasts
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+ Anus
+
+ (0, 0, -0.289)
+ 0
+
+
+ (-0.006, 0, -0.289)
+ 0
+
+
+ (-0.174, 0, 0.254)
+ 0
+
+
+
+ Penis
+
+ (0, 0, -0.320)
+ 0
+
+
+ (-0.01, 0, -0.338)
+ 0
+
+
+ (0.062, 0, -0.221)
+ 0
+
+
+
+ Balls
+
+ (0, 0, -0.320)
+ 0
+
+
+ (-0.01, 0, -0.338)
+ 0
+
+
+ (0.062, 0, -0.221)
+ 0
+
+
+
+ Belly
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+ PubicHair
+
+ (0, 0, -0.301)
+ 0
+
+
+ (0, 0, -0.318)
+ 0
+
+
+ (0.059, 0, -0.186)
+ 0
+
+
+
+
+
+ Thin
+
+
+ Vagina
+
+ (0, 0, -0.312)
+ 0
+
+
+ (-0.006, 0, -0.318)
+ 0
+
+
+ (0.006, 0, -0.256)
+ 0
+
+
+
+ Breasts
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+ Anus
+
+ (0, 0, -0.260)
+ 0
+
+
+ (-0.002, 0, -0.266)
+ 0
+
+
+ (-0.137, 0, -0.211)
+ 0
+
+
+
+ Penis
+
+ (0, 0, -0.307)
+ 0
+
+
+ (0, 0, -0.305)
+ 0
+
+
+ (0.008, 0, -0.248)
+ 0
+
+
+
+ Balls
+
+ (0, 0, -0.307)
+ 0
+
+
+ (0, 0, -0.305)
+ 0
+
+
+ (0.007, 0, -0.248)
+ 0
+
+
+
+ Belly
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+ PubicHair
+
+ (0, 0, -0.281)
+ 0
+
+
+ (0, 0, -0.291)
+ 0
+
+
+ (0.021, 0, -0.219)
+ 0
+
+
+
+
+
+ Male
+
+
+ Vagina
+
+ (0, 0, -0.320)
+ 0
+
+
+ (0.002, 0, -0.311)
+ 0
+
+
+ (0.057, 0, -0.258)
+ 0
+
+
+
+ Breasts
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+ Anus
+
+ (0, 0, -0.268)
+ 0
+
+
+ (0, 0, -0.252)
+ 0
+
+
+ (-0.113, 0, -0.234)
+ 0
+
+
+
+ Penis
+
+ (0, 0, -0.301)
+ 0
+
+
+ (0, 0, -0.311)
+ 0
+
+
+ (0.068, 0, -0.250)
+ 0
+
+
+
+ Balls
+
+ (0.0, 0, -0.301)
+ 0
+
+
+ (0.0, 0, -0.311)
+ 0
+
+
+ (0.066, 0, -0.250)
+ 0
+
+
+
+ Belly
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+ PubicHair
+
+ (0, 0, -0.275)
+ 0
+
+
+ (0, 0, -0.277)
+ 0
+
+
+ (0.066, 0, -0.219)
+ 0
+
+
+
+
+
+ Hulk
+
+
+ Vagina
+
+ (0.004, 0, -0.434)
+ 0
+
+
+ (0, 0, -0.453)
+ 0
+
+
+ (0.020, 0, -0.395)
+ 0
+
+
+
+ Breasts
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+ Anus
+
+ (0.006, 0, -0.383)
+ 0
+
+
+ (0, 0, -0.406)
+ 0
+
+
+ (-0.238, 0, -0.328)
+ 0
+
+
+
+ Penis
+
+ (0, 0, -0.436)
+ 0
+
+
+ (0.0, 0, -0.445)
+ 0
+
+
+ (0.029, 0, -0.387)
+ 0
+
+
+
+ Balls
+
+ (0, 0, -0.436)
+ 0
+
+
+ (0, 0, -0.445)
+ 0
+
+
+ (0.028, 0, -0.387)
+ 0
+
+
+
+ Belly
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+ PubicHair
+
+ (0, 0, -0.395)
+ 0
+
+
+ (0.027, 0, -0.375)
+ 0
+
+
+ (0, 0, -0.424)
+ 0
+
+
+
+
+
+ Fat
+
+
+ Vagina
+
+ (0.002, 0, -0.352)
+ 0
+
+
+ (0.002, 0, -0.359)
+ 0
+
+
+ (0.148, 0, -0.352)
+ 0
+
+
+
+ Breasts
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+ Anus
+
+ (0, 0, -0.297)
+ 0
+
+
+ (0, 0, -0.297)
+ 0
+
+
+ (-0.238, 0, -0.271)
+ 0
+
+
+
+ Penis
+
+ (0, 0, -0.357)
+ 0
+
+
+ (0, 0, -0.363)
+ 0
+
+
+ (0.168, 0, -0.348)
+ 0
+
+
+
+ Balls
+
+ (0, 0, -0.357)
+ 0
+
+
+ (0, 0, -0.363)
+ 0
+
+
+ (0.168, 0, -0.348)
+ 0
+
+
+
+ Belly
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+ PubicHair
+
+ (0, 0, -0.307)
+ 0
+
+
+ (0, 0, -0.320)
+ 0
+
+
+ (0.158, 0, -0.338)
+ 0
+
+
+
+
+
+ Child
+
+
+ Vagina
+
+ (0.002, 0, -0.209)
+ 0
+
+
+ (0, 0, -0.205)
+ 0
+
+
+ (0.043, 0, -0.174)
+ 0
+
+
+
+ Breasts
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+ Anus
+
+ (0, 0, -0.289)
+ 0
+
+
+ (0.002, 0, -0.164)
+ 0
+
+
+ (-0.084, 0, -0.127)
+ 0
+
+
+
+ Penis
+
+ (-0.002, 0, -0.195)
+ 0
+
+
+ (-0.002, 0, -0.195)
+ 0
+
+
+ (0.047, 0, -0.170)
+ 0
+
+
+
+ Balls
+
+ (-0.002, 0, -0.195)
+ 0
+
+
+ (-0.002, 0, -0.195)
+ 0
+
+
+ (0.047, 0, -0.170)
+ 0
+
+
+
+ Belly
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+ PubicHair
+
+ (0, 0, -0.166)
+ 0
+
+
+ (-0.002, 0, -0.164)
+ 0
+
+
+ (0.057, 0, -0.145)
+ 0
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/1.3/Defs/SkeletonDef/_HumanSkeletonDef.xml.bak b/1.3/Defs/SkeletonDef/_HumanSkeletonDef.xml.bak
new file mode 100644
index 0000000..47e66f0
--- /dev/null
+++ b/1.3/Defs/SkeletonDef/_HumanSkeletonDef.xml.bak
@@ -0,0 +1,668 @@
+
+
+
+ Human
+
+
+ Female
+
+
+ Vagina
+
+ (-0.002, 0, -0.340)
+ 0
+
+
+ (-0.006, 0, -0.346)
+ 0
+
+
+ (0.047, 0, -0.238)
+ 0
+
+
+
+ Breasts
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+ Anus
+
+ (0, 0, -0.289)
+ 0
+
+
+ (-0.006, 0, -0.289)
+ 0
+
+
+ (-0.174, 0, 0.254)
+ 0
+
+
+
+ Penis
+
+ (0, 0, -0.320)
+ 0
+
+
+ (-0.01, 0, -0.338)
+ 0
+
+
+ (0.062, 0, -0.221)
+ 0
+
+
+
+ Balls
+
+ (0, 0, -0.320)
+ 0
+
+
+ (-0.01, 0, -0.338)
+ 0
+
+
+ (0.062, 0, -0.221)
+ 0
+
+
+
+ Belly
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+ PubicHair
+
+ (0, 0, -0.301)
+ 0
+
+
+ (0, 0, -0.318)
+ 0
+
+
+ (0.059, 0, -0.186)
+ 0
+
+
+
+
+
+ Thin
+
+
+ Vagina
+
+ (0, 0, -0.312)
+ 0
+
+
+ (-0.006, 0, -0.318)
+ 0
+
+
+ (0.006, 0, -0.256)
+ 0
+
+
+
+ Breasts
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+ Anus
+
+ (0, 0, -0.260)
+ 0
+
+
+ (-0.002, 0, -0.266)
+ 0
+
+
+ (-0.137, 0, -0.211)
+ 0
+
+
+
+ Penis
+
+ (0, 0, -0.307)
+ 0
+
+
+ (0, 0, -0.305)
+ 0
+
+
+ (0.008, 0, -0.248)
+ 0
+
+
+
+ Balls
+
+ (0, 0, -0.307)
+ 0
+
+
+ (0, 0, -0.305)
+ 0
+
+
+ (0.007, 0, -0.248)
+ 0
+
+
+
+ Belly
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+ PubicHair
+
+ (0, 0, -0.281)
+ 0
+
+
+ (0, 0, -0.291)
+ 0
+
+
+ (0.021, 0, -0.219)
+ 0
+
+
+
+
+
+ Male
+
+
+ Vagina
+
+ (0, 0, -0.320)
+ 0
+
+
+ (0.002, 0, -0.311)
+ 0
+
+
+ (0.057, 0, -0.258)
+ 0
+
+
+
+ Breasts
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+ Anus
+
+ (0, 0, -0.268)
+ 0
+
+
+ (0, 0, -0.252)
+ 0
+
+
+ (-0.113, 0, -0.234)
+ 0
+
+
+
+ Penis
+
+ (0, 0, -0.301)
+ 0
+
+
+ (0, 0, -0.311)
+ 0
+
+
+ (0.068, 0, -0.250)
+ 0
+
+
+
+ Balls
+
+ (0.0, 0, -0.301)
+ 0
+
+
+ (0.0, 0, -0.311)
+ 0
+
+
+ (0.066, 0, -0.250)
+ 0
+
+
+
+ Belly
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+ PubicHair
+
+ (0, 0, -0.275)
+ 0
+
+
+ (0, 0, -0.277)
+ 0
+
+
+ (0.066, 0, -0.219)
+ 0
+
+
+
+
+
+ Hulk
+
+
+ Vagina
+
+ (0.004, 0, -0.434)
+ 0
+
+
+ (0, 0, -0.453)
+ 0
+
+
+ (0.020, 0, -0.395)
+ 0
+
+
+
+ Breasts
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+ Anus
+
+ (0.006, 0, -0.383)
+ 0
+
+
+ (0, 0, -0.406)
+ 0
+
+
+ (-0.238, 0, -0.328)
+ 0
+
+
+
+ Penis
+
+ (0, 0, -0.436)
+ 0
+
+
+ (0.0, 0, -0.445)
+ 0
+
+
+ (0.029, 0, -0.387)
+ 0
+
+
+
+ Balls
+
+ (0, 0, -0.436)
+ 0
+
+
+ (0, 0, -0.445)
+ 0
+
+
+ (0.028, 0, -0.387)
+ 0
+
+
+
+ Belly
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+ PubicHair
+
+ (0, 0, -0.395)
+ 0
+
+
+ (0.027, 0, -0.375)
+ 0
+
+
+ (0, 0, -0.424)
+ 0
+
+
+
+
+
+ Fat
+
+
+ Vagina
+
+ (0.002, 0, -0.352)
+ 0
+
+
+ (0.002, 0, -0.359)
+ 0
+
+
+ (0.148, 0, -0.352)
+ 0
+
+
+
+ Breasts
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+ Anus
+
+ (0, 0, -0.297)
+ 0
+
+
+ (0, 0, -0.297)
+ 0
+
+
+ (-0.238, 0, -0.271)
+ 0
+
+
+
+ Penis
+
+ (0, 0, -0.357)
+ 0
+
+
+ (0, 0, -0.363)
+ 0
+
+
+ (0.168, 0, -0.348)
+ 0
+
+
+
+ Balls
+
+ (0, 0, -0.357)
+ 0
+
+
+ (0, 0, -0.363)
+ 0
+
+
+ (0.168, 0, -0.348)
+ 0
+
+
+
+ Belly
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+ PubicHair
+
+ (0, 0, -0.307)
+ 0
+
+
+ (0, 0, -0.320)
+ 0
+
+
+ (0.158, 0, -0.338)
+ 0
+
+
+
+
+
+ Child
+
+
+ Vagina
+
+ (0.002, 0, -0.209)
+ 0
+
+
+ (0, 0, -0.205)
+ 0
+
+
+ (0.043, 0, -0.174)
+ 0
+
+
+
+ Breasts
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+ Anus
+
+ (0, 0, -0.289)
+ 0
+
+
+ (0.002, 0, -0.164)
+ 0
+
+
+ (-0.084, 0, -0.127)
+ 0
+
+
+
+ Penis
+
+ (-0.002, 0, -0.195)
+ 0
+
+
+ (-0.002, 0, -0.195)
+ 0
+
+
+ (0.047, 0, -0.170)
+ 0
+
+
+
+ Balls
+
+ (-0.002, 0, -0.195)
+ 0
+
+
+ (-0.002, 0, -0.195)
+ 0
+
+
+ (0.047, 0, -0.170)
+ 0
+
+
+
+ Belly
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+ (0, 0, 0)
+ 0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/1.3/Defs/TexturePointsDefs/Test.zip b/1.3/Defs/TexturePointsDefs/Test.zip
new file mode 100644
index 0000000..d6a1cce
Binary files /dev/null and b/1.3/Defs/TexturePointsDefs/Test.zip differ
diff --git a/Patches/ApparelPatches/Tip_TagList.txt b/1.3/Patches/ApparelPatches/Tip_TagList.txt
similarity index 100%
rename from Patches/ApparelPatches/Tip_TagList.txt
rename to 1.3/Patches/ApparelPatches/Tip_TagList.txt
diff --git a/1.3/Patches/ApparelPatches/VanillaBiotechPatch/BiotechApparelPatch.xml b/1.3/Patches/ApparelPatches/VanillaBiotechPatch/BiotechApparelPatch.xml
new file mode 100644
index 0000000..f8e424c
--- /dev/null
+++ b/1.3/Patches/ApparelPatches/VanillaBiotechPatch/BiotechApparelPatch.xml
@@ -0,0 +1,52 @@
+
+
+
+
+
+ Biotech
+
+
+ Normal
+
+
+ Defs/ThingDef[defName = "Apparel_Sash"]/apparel/tags
+
+ Defs/ThingDef[defName = "Apparel_Sash"]/apparel
+
+
+ SizedApparel_IgnorBreastSize
+ SizedApparel_ShowPrivateCrotch
+
+
+
+
+ Defs/ThingDef[defName = "Apparel_Sash"]/apparel/tags
+
+ SizedApparel_IgnorBreastSize
+ SizedApparel_ShowPrivateCrotch
+
+
+
+
+ Defs/ThingDef[defName = "Apparel_Bandolier"]/apparel/tags
+
+ Defs/ThingDef[defName = "Apparel_Bandolier"]/apparel
+
+
+ SizedApparel_IgnorBreastSize
+ SizedApparel_ShowPrivateCrotch
+
+
+
+
+ Defs/ThingDef[defName = "Apparel_Bandolier"]/apparel/tags
+
+ SizedApparel_IgnorBreastSize
+ SizedApparel_ShowPrivateCrotch
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/1.3/Patches/ApparelPatches/VanillaBiotechPatch/BiotechApparelPatch.xml.bak b/1.3/Patches/ApparelPatches/VanillaBiotechPatch/BiotechApparelPatch.xml.bak
new file mode 100644
index 0000000..08e7f34
--- /dev/null
+++ b/1.3/Patches/ApparelPatches/VanillaBiotechPatch/BiotechApparelPatch.xml.bak
@@ -0,0 +1,52 @@
+
+
+
+
+
+ Biotech
+
+
+ Normal
+
+
+ Defs/ThingDef[defName = "Apparel_Sash"]/apparel/tags
+
+ Defs/ThingDef[defName = "Apparel_Sash"]/apparel
+
+
+ SizedApparel_IgnorBreastSize
+ SizedApparel_ShowPrivateCrotch
+
+
+
+
+ Defs/ThingDef[defName = "Apparel_Sash"]/apparel/tags
+
+ SizedApparel_IgnorBreastSize
+ SizedApparel_ShowPrivateCrotch
+
+
+
+
+ Defs/ThingDef[defName = "Apparel_Bandolier"]/apparel/tags
+
+ Defs/ThingDef[defName = "Apparel_Bandolier"]/apparel
+
+
+ SizedApparel_IgnorBreastSize
+ SizedApparel_ShowPrivateCrotch
+
+
+
+
+ Defs/ThingDef[defName = "Apparel_HeavyBandolier"]/apparel/tags
+
+ SizedApparel_IgnorBreastSize
+ SizedApparel_ShowPrivateCrotch
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Patches/ApparelPatches/VanillaCorePatch/DusterShowCrotchPatch.xml b/1.3/Patches/ApparelPatches/VanillaCorePatch/DusterShowCrotchPatch.xml
similarity index 100%
rename from Patches/ApparelPatches/VanillaCorePatch/DusterShowCrotchPatch.xml
rename to 1.3/Patches/ApparelPatches/VanillaCorePatch/DusterShowCrotchPatch.xml
diff --git a/Patches/ApparelPatches/VanillaCorePatch/ShirtBasicShowCrotchPatch.xml b/1.3/Patches/ApparelPatches/VanillaCorePatch/ShirtBasicShowCrotchPatch.xml
similarity index 100%
rename from Patches/ApparelPatches/VanillaCorePatch/ShirtBasicShowCrotchPatch.xml
rename to 1.3/Patches/ApparelPatches/VanillaCorePatch/ShirtBasicShowCrotchPatch.xml
diff --git a/Patches/ApparelPatches/VanillaIdeoPatch/IdeoApparelPatch.xml b/1.3/Patches/ApparelPatches/VanillaIdeoPatch/IdeoApparelPatch.xml
similarity index 100%
rename from Patches/ApparelPatches/VanillaIdeoPatch/IdeoApparelPatch.xml
rename to 1.3/Patches/ApparelPatches/VanillaIdeoPatch/IdeoApparelPatch.xml
diff --git a/Patches/ApparelRecorderCompPatch.xml b/1.3/Patches/ApparelRecorderCompPatch.xml
similarity index 100%
rename from Patches/ApparelRecorderCompPatch.xml
rename to 1.3/Patches/ApparelRecorderCompPatch.xml
diff --git a/Patches/HediffPatches/PrivateHediffPartsPatches.xml b/1.3/Patches/HediffPatches/PrivateHediffPartsPatches.xml
similarity index 100%
rename from Patches/HediffPatches/PrivateHediffPartsPatches.xml
rename to 1.3/Patches/HediffPatches/PrivateHediffPartsPatches.xml
diff --git a/Patches/ThingPatches/BodyPartThingPatch.xml b/1.3/Patches/ThingPatches/BodyPartThingPatch.xml
similarity index 100%
rename from Patches/ThingPatches/BodyPartThingPatch.xml
rename to 1.3/Patches/ThingPatches/BodyPartThingPatch.xml
diff --git a/1.3/source/SizedApparel/AlienRaceSupport.cs b/1.3/source/SizedApparel/AlienRaceSupport.cs
new file mode 100644
index 0000000..a8f1dba
--- /dev/null
+++ b/1.3/source/SizedApparel/AlienRaceSupport.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using RimWorld;
+using Verse;
+
+namespace SizedApparel
+{
+ class AlienRaceSupport
+ {
+ }
+}
diff --git a/1.3/source/SizedApparel/Graphic_BodyParts.cs b/1.3/source/SizedApparel/Graphic_BodyParts.cs
new file mode 100644
index 0000000..f221eda
--- /dev/null
+++ b/1.3/source/SizedApparel/Graphic_BodyParts.cs
@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace SizedApparel
+{
+ //Does it better to optimize?
+ public class Graphic_BodyParts : Verse.Graphic_Multi
+ {
+ public float serverity;
+ public string bodyPart; // such as breasts, penis
+ }
+}
diff --git a/1.3/source/SizedApparel/Graphic_SizedApparel.cs b/1.3/source/SizedApparel/Graphic_SizedApparel.cs
new file mode 100644
index 0000000..f84fa77
--- /dev/null
+++ b/1.3/source/SizedApparel/Graphic_SizedApparel.cs
@@ -0,0 +1,19 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using UnityEngine;
+using RimWorld;
+using Verse;
+
+namespace SizedApparel
+{
+ //Does it better to optimize?
+ public class Graphic_SizedApparel : Graphic_Multi
+ {
+ public string TargetBodyParts = "Breats";
+ //Sized Graphics.
+ public List graphics;
+ }
+}
diff --git a/1.3/source/SizedApparel/HarmonyPatches.cs b/1.3/source/SizedApparel/HarmonyPatches.cs
new file mode 100644
index 0000000..9b8d881
--- /dev/null
+++ b/1.3/source/SizedApparel/HarmonyPatches.cs
@@ -0,0 +1,321 @@
+using HarmonyLib;
+using RimWorld;
+//using Rimworld_Animations;
+//using AlienRace;
+using rjw;
+using System;
+using System.Linq;
+using Verse;
+
+namespace SizedApparel
+{
+ [StaticConstructorOnStartup]
+ public class SizedApparelPatch
+ {
+
+ public static bool alienRaceActive = false;
+ public static bool SJWActive = false;
+ public static bool RJWActive = false;
+ public static bool DubsApparelTweaksActive = false;
+ public static bool rimNudeWorldActive = false;
+ public static bool OTYNudeActive = false;
+ public static bool LicentiaActive = false;
+ public static bool RimworldAnimationActive = false; //rjw animation
+ public static bool MenstruationActive = false; //rjw_menstruation
+ public static bool StatueOfColonistActive = false;
+
+ static SizedApparelPatch()
+ {
+
+ //check SJW
+ if (LoadedModManager.RunningModsListForReading.Any(x => x.Name == "SafeJobWorld"))
+ {
+ SJWActive = true;
+ }
+ if (LoadedModManager.RunningModsListForReading.Any(x => x.PackageId == "safe.job.world"))
+ {
+ SJWActive = true;
+ }
+ //check RJW
+ if (LoadedModManager.RunningModsListForReading.Any(x => x.Name == "RimJobWorld"))
+ {
+ RJWActive = true;
+ }
+ if (LoadedModManager.RunningModsListForReading.Any(x => x.PackageId == "rim.job.world"))
+ {
+ RJWActive = true;
+ }
+ //check Dubs Apparel Tweaks
+ if (LoadedModManager.RunningModsListForReading.Any(x => x.Name == "Dubs Apparel Tweaks"))
+ {
+ DubsApparelTweaksActive = true;
+ }
+ if (LoadedModManager.RunningModsListForReading.Any(x => x.PackageId == "Dubwise.DubsApparelTweaks"))
+ {
+ DubsApparelTweaksActive = true;
+ }
+
+ //check Alien Race
+ if (LoadedModManager.RunningModsListForReading.Any(x => x.Name == "Humanoid Alien Races 2.0"))
+ {
+ alienRaceActive = true;
+ }
+ if (LoadedModManager.RunningModsListForReading.Any(x => x.Name.Contains("Humanoid Alien Races")))
+ {
+ alienRaceActive = true;
+ }
+ if (LoadedModManager.RunningModsListForReading.Any(x => x.PackageId == "erdelf.HumanoidAlienRaces"))
+ {
+ alienRaceActive = true;
+ }
+ //check RimNudeWorld
+ if (LoadedModManager.RunningModsListForReading.Any(x => x.PackageId == "shauaputa.rimnudeworld"))
+ {
+ rimNudeWorldActive = true;
+ }
+ //check OTYNude
+ if (LoadedModManager.RunningModsListForReading.Any(x => x.PackageId.Contains("OTY")&& x.PackageId.Contains("Nude")))
+ {
+ OTYNudeActive = true;
+ }
+
+ //check Licentia Lab
+ if (LoadedModManager.RunningModsListForReading.Any(x => x.PackageId.ToLower() == "LustLicentia.RJWLabs".ToLower()))
+ {
+ LicentiaActive = true;
+ }
+ if (!LicentiaActive)
+ {
+ if (LoadedModManager.RunningModsListForReading.Any(x => x.PackageId.ToLower() == "Euclidean.LustLicentia.RJWLabs".ToLower()))
+ {
+ LicentiaActive = true;
+ }
+ }
+ if (!LicentiaActive)
+ {
+ if (LoadedModManager.RunningModsListForReading.Any(x => x.PackageId.ToLower().Contains("LustLicentia.RJWLabs".ToLower())))
+ {
+ LicentiaActive = true;
+ }
+ }
+
+
+
+ //check rjw animation
+ if (LoadedModManager.RunningModsListForReading.Any(x => x.PackageId.ToLower() == "c0ffee.rimworld.animations".ToLower()))
+ {
+ RimworldAnimationActive = true;
+ }
+
+ //check rjw_menstruation
+ if (LoadedModManager.RunningModsListForReading.Any(x => x.PackageId.ToLower() == "rjw.menstruation".ToLower()))
+ {
+ MenstruationActive = true;
+ }
+
+ //check statue of Colonist
+ if (LoadedModManager.RunningModsListForReading.Any(x => x.PackageId.ToLower() == "tammybee.statueofcolonist".ToLower()))
+ {
+ StatueOfColonistActive = true;
+ }
+
+
+ Log.Message("[SizedApparel] start");
+ var harmony = new Harmony("SizedApparelforRJW");
+
+ harmony.PatchAll();
+ /*
+ try
+ {
+ ((Action)(() => {
+ if (LoadedModManager.RunningModsListForReading.Any(x => x.Name == "OTY_NUDE"))
+ {
+ Log.Message("Sized Apparel for RJW : OTY_NUDE founded");
+ usingOversized = true;
+ usingBackBreaking = true;
+ }
+ }))();
+ }
+ catch (TypeLoadException ex)
+ {
+
+ }
+ */
+
+
+ //RJW Patch
+ try
+ {
+ ((Action)(() =>
+ {
+ if (RJWActive)
+ {
+
+
+ Log.Message("[SizedApparel] RimJobWorld Found");
+ //harmony.Patch(AccessTools.Method(typeof(rjw.JobDriver_SexBaseInitiator), "Start"),
+ //postfix: new HarmonyMethod(typeof(SexStartPatch), "Postfix"));
+
+ //harmony.Patch(AccessTools.Method(typeof(rjw.JobDriver_SexBaseInitiator), "End"),
+ //postfix: new HarmonyMethod(typeof(SexEndPatch), "Postfix"));
+
+ //harmony.Patch(AccessTools.Method(typeof(rjw.SexUtility), "DrawNude"),
+ //postfix: new HarmonyMethod(typeof(DrawNudePatch), "Postfix"));
+
+ harmony.Patch(AccessTools.Method(typeof(Sexualizer), "sexualize_pawn"),
+ postfix: new HarmonyMethod(typeof(SexualizePawnPatch), "Postfix"));
+
+ Log.Message("[SizedApparel] RimJobWorld Patched");
+
+ }
+ else
+ {
+ Log.Message("[SizedApparel] RimJobWorld Patch canceled");
+ }
+ }))();
+ }
+ catch (TypeLoadException ex) { }
+
+
+ //Alien Race Patch
+ //Alien Race No longer supported.
+ /*
+ try
+ {
+ ((Action)(() =>
+ {
+ if (alienRaceActive)
+ {
+ Log.Message("[SizedApparel] AlienRace Found");
+
+ //harmony.Patch(AccessTools.Method(typeof(AlienRace.HarmonyPatches), "DrawAddons"),
+ //prefix: new HarmonyMethod(typeof(DrawAddonPatch), "Prefix"));
+
+ Log.Message("[SizedApparel] AlienRace Patched");
+
+ }
+ else
+ {
+ Log.Message("[SizedApparel] AlienRace Patch canceled");
+ }
+ }))();
+ }
+ catch (TypeLoadException ex) { }
+ */
+
+ try
+ {
+ ((Action)(() =>
+ {
+ if (RimworldAnimationActive)
+ {
+ Log.Message("[SizedApparel] RimworldAnimaion(rjw animation) Found");
+
+ harmony.Patch(AccessTools.Method(typeof(Rimworld_Animations.CompBodyAnimator), "tickClip"),
+ postfix: new HarmonyMethod(typeof(RimworldAnimationPatch), "TickClipPostfix"));
+
+ harmony.Patch(AccessTools.Method(typeof(JobDriver_SexBaseInitiator), "End"),
+ postfix: new HarmonyMethod(typeof(RimworldAnimationPatch), "EndClipPostfix"));
+
+
+ Log.Message("[SizedApparel] RimworldAnimaion(rjw animation) Patched");
+ }
+ else
+ {
+ Log.Message("[SizedApparel] RimworldAnimaion(rjw animation) Patch canceled");
+ }
+ }))();
+ }
+ catch (TypeLoadException ex) { }
+
+ //Rim Nude World Patch
+ try
+ {
+ ((Action)(() =>
+ {
+ if (alienRaceActive && rimNudeWorldActive)
+ {
+ Log.Message("[SizedApparel] RimNudeWorld Found");
+ /*
+ harmony.Patch(AccessTools.Method(typeof(AlienRace.AlienPartGenerator.BodyAddon), "CanDrawAddon"),
+ postfix: new HarmonyMethod(typeof(RimNudeWorldBreastHidePatch), "Postfix"));
+ */
+ //harmony.Patch(AccessTools.Method(typeof(RimNudeWorld.GenitalPatch), "Postfix"),
+ //prefix: new HarmonyMethod(typeof(SizedApparelRNWPatch), "Prefix"));
+
+ //Log.Message("SizedApparelforRJW::AlienRacePatch");
+ Log.Message("[SizedApparel] RimNudeWorld Patching...: RevealingApparel");
+ harmony.Patch(AccessTools.Method(typeof(RevealingApparel.RevealingApparel), "CanDrawRevealing"),
+ postfix: new HarmonyMethod(typeof(RevealingApparelPatch), "Postfix"));
+ Log.Message("[SizedApparel] RimNudeWorld Patched: RevealingApparel");
+ }
+ else
+ {
+ Log.Message("[SizedApparel] RimNudeWorld Patch canceled");
+ }
+ }))();
+ }
+ catch (TypeLoadException ex)
+ {
+ Log.Warning("[SizedApparel] Activated RimNudeWorld version not match to patch!\nSome patch for RimNudeWorld may not work!");
+ }
+
+
+ //Dubs Apparel Tweaks Patch
+ try
+ {
+ ((Action)(() =>
+ {
+ if (DubsApparelTweaksActive)
+ {
+ Log.Message("[SizedApparel] Dubs Apparel Tweaks Found");
+ //harmony.Patch(AccessTools.Method(typeof(QuickFast.bs), "SwitchIndoors"),
+ //postfix: new HarmonyMethod(typeof(SizedApparelDubsApparelPatch), "indoorPostFixPatch"));
+ Log.Message("[SizedApparel] Dubs Apparel Tweaks (not) Patched (just debug message)");
+ }
+ else
+ {
+ Log.Message("[SizedApparel] Dubs Apparel Tweaks Patch canceled");
+ }
+ }))();
+ }
+ catch (TypeLoadException ex) { }
+
+
+ //SizedApparelPatch
+ try
+ {
+ ((Action)(() =>
+ {
+ Log.Message("[SizedApparel] doing PawnRenderer Patch");
+
+ //disable for 1.3
+ /*
+ var original = typeof(PawnRenderer).GetMethod("RenderPawnInternal", BindingFlags.NonPublic | BindingFlags.Instance, null, new Type[] {typeof(Vector3),typeof(float), typeof(bool), typeof(Rot4), typeof(Rot4), typeof(RotDrawMode), typeof(bool), typeof(bool), typeof(bool) }, null );
+ var postfix = typeof(DrawPawnPatch).GetMethod("RenderPawnInternalPostfix");
+ var prefix = typeof(DrawPawnPatch).GetMethod("RenderPawnInternalPrefix");
+ harmony.Patch(original, prefix: new HarmonyMethod(prefix), postfix: new HarmonyMethod(postfix));
+ */
+
+ //1.3
+ var original0 = typeof(Pawn_ApparelTracker).GetMethod("Notify_ApparelChanged");
+ var original1 = typeof(Pawn_ApparelTracker).GetMethod("Notify_ApparelAdded");
+ var original2 = typeof(Pawn_ApparelTracker).GetMethod("Notify_ApparelRemoved");
+ var postfix = typeof(ApparelTrackerPatch).GetMethod("Changed");
+ harmony.Patch(original0, postfix: new HarmonyMethod(postfix));
+ //harmony.Patch(original1, postfix: new HarmonyMethod(postfix));
+ //harmony.Patch(original2, postfix: new HarmonyMethod(postfix));
+
+ Log.Message("[SizedApparel] PawnRenderer Patch complete");
+
+ }))();
+ }
+ catch (TypeLoadException ex)
+ {
+ Log.Error("[SizedApparel] Cannot Patch for \"RenderPawnInternal\" Method! the mod may not work!");
+ }
+ }
+
+
+ }
+}
diff --git a/1.3/source/SizedApparel/Patch-Animation.cs b/1.3/source/SizedApparel/Patch-Animation.cs
new file mode 100644
index 0000000..bd92a0d
--- /dev/null
+++ b/1.3/source/SizedApparel/Patch-Animation.cs
@@ -0,0 +1,107 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using RimWorld;
+using Verse;
+using HarmonyLib;
+using UnityEngine;
+//using Rimworld_Animations;
+
+namespace SizedApparel
+{
+
+ public class RimworldAnimationPatch
+ {
+ //since instance (CompBodyAnimator class) must be soft dependency, Get as System.Object.
+ public static void TickClipPostfix(System.Object __instance) //CompBodyAnimator __instance, AnimationDef ___anim, int ___curStage, int ___actor, int ___clipTicks, float ___clipPercent
+ {
+ Rimworld_Animations.CompBodyAnimator instance = __instance as Rimworld_Animations.CompBodyAnimator;
+
+ if (instance == null)
+ return;
+
+ if (!instance.controlGenitalAngle)
+ return;
+
+ var comp = instance.parent.GetComp();
+ if (comp == null)
+ return;
+
+
+ comp.SetPenisAngle(instance.genitalAngle - instance.bodyAngle); //genitalAngle is global Angle value in rjwanimation... fix with body Angle;
+
+
+ if (!SizedApparelSettings.AnimationPatch)//Rotating Penis Setting(avobe) is set from RimworldAnimation Setting, not in SizedApparel.
+ return;
+
+ foreach (var actor in instance.actorsInCurrentAnimation)
+ {
+ //comp.ForceUpdateTickAnimation = true;
+ var actorcomp = actor.GetComp();
+ if (actorcomp == null)
+ continue;
+ //actorcomp.SetBreastJiggle(true);
+ actorcomp.ForceUpdateTickAnimation = true;
+
+ }
+ return;
+ bool isFuckTick = false;
+ /*
+ var soundEffects = ((PawnAnimationClip)___anim.animationStages[___curStage].animationClips[___actor]).SoundEffects;
+ if (soundEffects.ContainsKey(___clipTicks) && (soundEffects[___clipTicks].Contains("Fuck") || soundEffects[___clipTicks].Contains("Suck")))
+ {
+ isFuckTick = true;
+ }
+ else
+ {
+ const int jiggleTime = 3;
+ for(int i = 0; i < jiggleTime; i++)
+ {
+ if (soundEffects.ContainsKey(___clipTicks - i) && soundEffects[___clipTicks - i].Contains("Fuck"))
+ {
+ isFuckTick = true;
+ break;
+ }
+ }
+ }*/
+ //need to find partner's breasts.
+ /*
+ if (isFuckTick)
+ {
+ foreach (var actor in __instance.actorsInCurrentAnimation)
+ {
+ actor.GetComp().SetBreastJiggle(true);
+ }
+ }
+ else
+ {
+ foreach (var actor in __instance.actorsInCurrentAnimation)
+ {
+ actor.GetComp().SetBreastJiggle(false);
+ }
+ }*/
+ //may have some tick issue? too fast jiggle?
+ }
+
+ //rjw's JobDriver_SexBaseInitiator end patch
+ public static void EndClipPostfix(System.Object __instance)//CompBodyAnimator __instance
+ {
+ Rimworld_Animations.CompBodyAnimator instance = __instance as Rimworld_Animations.CompBodyAnimator;
+ if (instance == null)
+ return;
+
+ if (!instance.controlGenitalAngle)
+ return;
+ var comp = instance.parent.GetComp();
+ if (comp == null)
+ return;
+ comp.SetBreastJiggle(false, -1);
+ comp.ForceUpdateTickAnimation = false;
+ comp.SetPenisAngle(0);
+
+ }
+ }
+
+}
diff --git a/source/SizedApparel/SizedApparelDubsApparelPatch.cs b/1.3/source/SizedApparel/Patch-DubsApparelPatch.cs
similarity index 86%
rename from source/SizedApparel/SizedApparelDubsApparelPatch.cs
rename to 1.3/source/SizedApparel/Patch-DubsApparelPatch.cs
index 8cc6e14..5addbe4 100644
--- a/source/SizedApparel/SizedApparelDubsApparelPatch.cs
+++ b/1.3/source/SizedApparel/Patch-DubsApparelPatch.cs
@@ -17,7 +17,7 @@ namespace SizedApparel
if (graphicSet == null)
return;
- var comp = pawn.TryGetComp();
+ var comp = pawn.GetComp();
if (comp == null)
return;
comp.needToCheckApparelGraphicRecords = true;
diff --git a/1.3/source/SizedApparel/Patch-Menstruation.cs b/1.3/source/SizedApparel/Patch-Menstruation.cs
new file mode 100644
index 0000000..21c4a84
--- /dev/null
+++ b/1.3/source/SizedApparel/Patch-Menstruation.cs
@@ -0,0 +1,39 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using UnityEngine;
+using Verse;
+using RJW_Menstruation;
+
+namespace SizedApparel
+{
+ public class Patch_Menstruation
+ {
+
+ public static Color? GetNippleColor(Hediff breastHediff)
+ {
+ var breastcomp = breastHediff.TryGetComp();
+ if (breastcomp == null)
+ return null;
+ return breastcomp.NippleColor;
+ }
+
+ public static float? GetNippleSize(Hediff breastHediff)
+ {
+ var breastcomp = breastHediff.TryGetComp();
+ if (breastcomp == null)
+ return null;
+ return breastcomp.NippleSize;
+ }
+
+ public static float? GetAreolaSize(Hediff breastHediff)
+ {
+ var breastcomp = breastHediff.TryGetComp();
+ if (breastcomp == null)
+ return null;
+ return breastcomp.AreolaSize;
+ }
+ }
+}
diff --git a/source/SizedApparel/SizedApparelRJWPatch.cs b/1.3/source/SizedApparel/Patch-RimJobWorld.cs
similarity index 90%
rename from source/SizedApparel/SizedApparelRJWPatch.cs
rename to 1.3/source/SizedApparel/Patch-RimJobWorld.cs
index bc1aecf..06f8ac6 100644
--- a/source/SizedApparel/SizedApparelRJWPatch.cs
+++ b/1.3/source/SizedApparel/Patch-RimJobWorld.cs
@@ -18,10 +18,10 @@ namespace SizedApparel
{
if (!UnityData.IsInMainThread)
return;
- ApparelRecorderComp comp = pawn?.TryGetComp();
+ ApparelRecorderComp comp = pawn?.GetComp();
if (comp == null)
return;
- comp.SetDirty();
+ comp.SetDirty(true,true,true);
/*
comp.ClearAll();
var graphicSet = pawn.Drawer?.renderer?.graphics;
@@ -69,7 +69,7 @@ namespace SizedApparel
return;
//GetBreastSeverity(__instance.pawn, out breastSeverity, out breastHediff);
//bool flag = hasUnSupportedApparel(__instance.pawn, breastSeverity, breastHediff);
- ApparelRecorderComp comp = pawn.TryGetComp();
+ ApparelRecorderComp comp = pawn.GetComp();
if (comp != null)
{
/*
@@ -128,7 +128,7 @@ namespace SizedApparel
{
if (pawn == null)
return;
- ApparelRecorderComp comp = pawn.TryGetComp();
+ ApparelRecorderComp comp = pawn.GetComp();
if (comp == null)
return;
comp.SetDirty();
@@ -146,7 +146,7 @@ namespace SizedApparel
- ApparelRecorderComp pawnARC = __instance.pawn.TryGetComp();
+ ApparelRecorderComp pawnARC = __instance.pawn.GetComp();
if (pawnARC != null)
{
if (__instance.pawn.RaceProps.Humanlike)
@@ -161,7 +161,7 @@ namespace SizedApparel
var partner = __instance.Partner as Pawn;
if (partner == null)
return;
- ApparelRecorderComp partnerARC = partner.TryGetComp();
+ ApparelRecorderComp partnerARC = partner.GetComp();
if (partnerARC != null)
{
if (partner.RaceProps.Humanlike)
@@ -182,7 +182,7 @@ namespace SizedApparel
{
- ApparelRecorderComp pawnARC = __instance.pawn.TryGetComp();
+ ApparelRecorderComp pawnARC = __instance.pawn.GetComp();
if (pawnARC != null)
{
@@ -209,7 +209,7 @@ namespace SizedApparel
var partner = __instance.Partner as Pawn;
if (partner == null)
return;
- ApparelRecorderComp partnerARC = partner.TryGetComp();
+ ApparelRecorderComp partnerARC = partner.GetComp();
if (partnerARC != null)
{
partnerARC.havingSex = false;
diff --git a/source/SizedApparel/SizedApparelRNWPatch.cs b/1.3/source/SizedApparel/Patch-RimNudeWorld.cs
similarity index 90%
rename from source/SizedApparel/SizedApparelRNWPatch.cs
rename to 1.3/source/SizedApparel/Patch-RimNudeWorld.cs
index 3971a36..cdc4e93 100644
--- a/source/SizedApparel/SizedApparelRNWPatch.cs
+++ b/1.3/source/SizedApparel/Patch-RimNudeWorld.cs
@@ -36,7 +36,7 @@ namespace SizedApparel
{
if (__result == false)
return;
- var comp = pawn.TryGetComp();
+ var comp = pawn.GetComp();
if (comp == null)
return;
if (comp.hasUnsupportedApparel)
diff --git a/1.3/source/SizedApparel/Patch-StatueOfColonist.cs b/1.3/source/SizedApparel/Patch-StatueOfColonist.cs
new file mode 100644
index 0000000..2aa8860
--- /dev/null
+++ b/1.3/source/SizedApparel/Patch-StatueOfColonist.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace SizedApparel
+{
+ public class Patch_StatueOfColonist
+ {
+
+ }
+}
diff --git a/1.3/source/SizedApparel/Properties/AssemblyInfo.cs b/1.3/source/SizedApparel/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..950c1b8
--- /dev/null
+++ b/1.3/source/SizedApparel/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// 어셈블리에 대한 일반 정보는 다음 특성 집합을 통해
+// 제어됩니다. 어셈블리와 관련된 정보를 수정하려면
+// 이러한 특성 값을 변경하세요.
+[assembly: AssemblyTitle("SizedApparelforRJW")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("SizedApparelforRJW")]
+[assembly: AssemblyCopyright("Copyright © 2020")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// ComVisible을 false로 설정하면 이 어셈블리의 형식이 COM 구성 요소에
+// 표시되지 않습니다. COM에서 이 어셈블리의 형식에 액세스하려면
+// 해당 형식에 대해 ComVisible 특성을 true로 설정하세요.
+[assembly: ComVisible(false)]
+
+// 이 프로젝트가 COM에 노출되는 경우 다음 GUID는 typelib의 ID를 나타냅니다.
+[assembly: Guid("b06471b4-4c6c-478b-b94d-71cc53abd24d")]
+
+// 어셈블리의 버전 정보는 다음 네 가지 값으로 구성됩니다.
+//
+// 주 버전
+// 부 버전
+// 빌드 번호
+// 수정 버전
+//
+// 모든 값을 지정하거나 아래와 같이 '*'를 사용하여 빌드 번호 및 수정 번호를
+// 기본값으로 할 수 있습니다.
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/1.3/source/SizedApparel/SizedAppareIdeoPatch.cs b/1.3/source/SizedApparel/SizedAppareIdeoPatch.cs
new file mode 100644
index 0000000..c263cc1
--- /dev/null
+++ b/1.3/source/SizedApparel/SizedAppareIdeoPatch.cs
@@ -0,0 +1,37 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using RimWorld;
+using Verse;
+using HarmonyLib;
+using UnityEngine;
+using rjw;
+
+
+namespace SizedApparel
+{
+ //IdeoUIUtility.DoAppearanceItems
+ [HarmonyPatch(typeof(IdeoUIUtility), "DoAppearanceItems")]
+ static class SizedApparAppearanceUIPatch
+ {
+ //Todo: Use Transpiler
+ static public void oldPostfix(Ideo ideo, IdeoEditMode editMode, ref float curY, float width)
+ {
+ //DrawPubicBlox()
+ Rect rect = new Rect(4f, curY, IdeoUIUtility.PreceptBoxSize.x, IdeoUIUtility.PreceptBoxSize.y);
+ Widgets.DrawRectFast(rect, IdeoUIUtility.GetBackgroundColor(PreceptImpact.Medium), null);
+ string text = "PubicHair".Translate();
+ }
+
+ static void DrawPubicBox(float xOffset, float y, StyleItemTab tab, StyleItemDef defToDisplay)
+ {
+
+ }
+
+
+
+ }
+
+}
diff --git a/1.3/source/SizedApparel/SizedApparelApparelBuilder.cs b/1.3/source/SizedApparel/SizedApparelApparelBuilder.cs
new file mode 100644
index 0000000..98ad331
--- /dev/null
+++ b/1.3/source/SizedApparel/SizedApparelApparelBuilder.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace SizedApparel
+{
+ //apparel build with apparel parts. but how?
+ public class SizedApparelApparelBuilder
+ {
+
+ }
+}
diff --git a/1.3/source/SizedApparel/SizedApparelBodyPart.cs b/1.3/source/SizedApparel/SizedApparelBodyPart.cs
new file mode 100644
index 0000000..a8ca96e
--- /dev/null
+++ b/1.3/source/SizedApparel/SizedApparelBodyPart.cs
@@ -0,0 +1,1024 @@
+using HarmonyLib;
+using RimWorld;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+//using AlienRace;
+using UnityEngine;
+using Verse;
+
+namespace SizedApparel
+{
+ public class Depth4Offsets
+ {
+ public float south=0;
+ public float north=0;
+ public float east=0;
+ public float west=0;
+
+ public Depth4Offsets() { }
+
+ public Depth4Offsets(Vector4 arg)
+ {
+ south = arg.x;
+ north = arg.y;
+ east = arg.z;
+ west = arg.w;
+ }
+ public Depth4Offsets(float s, float n, float e, float w)
+ {
+ south = s;
+ north = n;
+ east = e;
+ west = w;
+ }
+ }
+
+ public class Rot4Offsets
+ {
+ //X: right and left
+ //Y: Frong or Back
+ //Z: Up and Down
+ Vector3 South;
+
+ Vector3 North;
+
+ Vector3 East;
+
+ Vector3 West;
+
+ public Rot4Offsets(Vector3 vector)
+ {
+ South = vector;
+ North = vector;
+ East = vector;
+ West = vector;
+ }
+
+ public Rot4Offsets(Vector3 south, Vector3 north, Vector3 east, Vector3 west)
+ {
+ South = south;
+ North = north;
+ East = east;
+ West = west;
+ }
+
+ public Vector3 GetOffset(Rot4 rotation)
+ {
+ if (rotation == Rot4.East)
+ return East;
+ if (rotation == Rot4.West)
+ return West;
+ if (rotation == Rot4.South)
+ return South;
+ if (rotation == Rot4.North)
+ return North;
+ else
+ return Vector3.zero;
+ }
+
+ }
+
+ public struct RaceNameAndBodyType
+ {
+ public string raceName;
+ public string bodyType;
+ }
+
+ public class BodyWithBodyType
+ {
+ public string bodyType;
+ public List Addons = new List();
+ }
+
+ public class BodyPart
+ {
+ public string partName = null;
+ public string customPath = null;
+ public string defaultHediffName = null; // for missing Hediff
+ public bool isBreasts = false;
+ public bool centeredTexture = true;
+ public bool mustMatchBodyType = false; // TODO
+
+ public string boneName = null;
+ public Bone bone = null; // For Graphic Positioning System
+ public bool mustHaveBone = true; // when bone is missing, don't draw
+
+ public SizedApparelBodyPartOf bodyPartOf = SizedApparelBodyPartOf.None;
+ public ColorType colorType = ColorType.Skin;
+ public Depth4Offsets depthOffset = new Depth4Offsets();
+ public BodyTypeAndOffset offsets = new BodyTypeAndOffset();
+ }
+
+ public class BodyTypeAndOffset
+ {
+ //public RaceNameAndBodyType bodyTypeData;
+ public string bodyType;
+ public Rot4Offsets offsets = new Rot4Offsets(Vector3.zero);
+
+ public BodyTypeAndOffset()
+ {
+
+ }
+
+ public BodyTypeAndOffset(bool useCenter)
+ {
+ if (useCenter)
+ {
+ offsets = new Rot4Offsets(Vector3.zero);
+ }
+ }
+ public BodyTypeAndOffset(Vector3 defaultOffset)
+ {
+ offsets = new Rot4Offsets(defaultOffset);
+ }
+ }
+
+ public enum ColorType
+ {
+ Skin, Hair, Nipple, Custom, None
+ }
+
+
+ public enum SizedApparelBodyPartOf
+ {
+ All, Torso, Breasts, Crotch, Penis, Balls, Vagina, Anus, Belly, PubicHair, Udder, Hips, Thighs, hands, feet, None
+ }
+ public static class SizedApparelBodyPartOfExtension
+ {
+ public static bool IsPartOf(this SizedApparelBodyPartOf source, SizedApparelBodyPartOf target)
+ {
+ if (source == SizedApparelBodyPartOf.None)
+ return false;
+
+ switch (target)
+ {
+ case SizedApparelBodyPartOf.All:
+ return true;
+ case SizedApparelBodyPartOf.Torso:
+ if (source == SizedApparelBodyPartOf.hands || source == SizedApparelBodyPartOf.feet)
+ return false;
+ return true;
+ case SizedApparelBodyPartOf.Breasts:
+ if (source == SizedApparelBodyPartOf.Breasts)
+ return true;
+ return false;
+ case SizedApparelBodyPartOf.Crotch:
+ if (source == SizedApparelBodyPartOf.Crotch || source == SizedApparelBodyPartOf.Penis || source == SizedApparelBodyPartOf.Vagina || source == SizedApparelBodyPartOf.Anus || source == SizedApparelBodyPartOf.PubicHair || source == SizedApparelBodyPartOf.Balls)
+ return true;
+ return false;
+ case SizedApparelBodyPartOf.Penis:
+ if (source == SizedApparelBodyPartOf.Penis)
+ return true;
+ return false;
+ case SizedApparelBodyPartOf.Balls:
+ if (source == SizedApparelBodyPartOf.Balls)
+ return true;
+ return false;
+ case SizedApparelBodyPartOf.Vagina:
+ if (source == SizedApparelBodyPartOf.Vagina)
+ return true;
+ return false;
+ case SizedApparelBodyPartOf.Anus:
+ if (source == SizedApparelBodyPartOf.Anus)
+ return true;
+ return false;
+ case SizedApparelBodyPartOf.Belly:
+ if (source == SizedApparelBodyPartOf.Belly)
+ return true;
+ return false;
+ case SizedApparelBodyPartOf.Udder:
+ if (source == SizedApparelBodyPartOf.Udder)
+ return true;
+ return false;
+ case SizedApparelBodyPartOf.Hips:
+ if (source == SizedApparelBodyPartOf.Hips || source == SizedApparelBodyPartOf.Thighs || source == SizedApparelBodyPartOf.Penis || source == SizedApparelBodyPartOf.Vagina || source == SizedApparelBodyPartOf.Anus)
+ return true;
+ return false;
+ case SizedApparelBodyPartOf.Thighs:
+ if (source == SizedApparelBodyPartOf.Thighs)
+ return true;
+ return false;
+ case SizedApparelBodyPartOf.hands:
+ if (source == SizedApparelBodyPartOf.hands)
+ return true;
+ return false;
+ case SizedApparelBodyPartOf.feet:
+ if (source == SizedApparelBodyPartOf.feet)
+ return true;
+ return false;
+ case SizedApparelBodyPartOf.PubicHair:
+ if (source == SizedApparelBodyPartOf.PubicHair)
+ return true;
+ return false;
+ case SizedApparelBodyPartOf.None:
+ return false;
+
+ }
+ Log.Error("[SizedApparel] missing SizedApparelBodyPartOf!");
+ return false;
+ }
+ }
+
+
+ public class GraphicPointsDef : Def
+ {
+ public List points;
+ }
+
+ public class TextureWithGraphicPoints
+ {
+ public string texturePath; // texture is already classified with bodytype
+ public List points = new List();
+ }
+
+ public class GraphicPoint
+ {
+ public string pointName;
+ public Vector2 point = Vector2.zero;
+ }
+ public class GraphicPointsWithBodyType
+ {
+ public string pointName;
+ public List points = new List();
+ }
+
+ public class PointWithBodyType
+ {
+ public string bodyTypeName; //null can be used too
+ public Vector2 point = Vector2.zero;
+ }
+
+ public class BodyPartPoint
+ {
+ string name;
+ Vector2 position = Vector2.zero;//Uv position. not pixel
+ }
+
+ [Obsolete]//todo
+ public struct BodyPartSpline
+ {
+
+ }
+
+
+ //Def for Hediff Graphic color options or else.
+ public class SizedApparelHeddifDef : Def
+ {
+ public HediffDef hediffDef;
+ //public string hediffDefName;
+
+ }
+
+ //Def per graphic(texture)
+ [Obsolete]
+ public class SizedApparelBodyPartGraphicDef : Def
+ {
+ public string graphicPath;
+ public int severityIndex;
+ public Vector2 pivot = new Vector2(0.5f, 0.5f); // custom pivot of texture. UV. not pixel
+ //public Dictionary points = new Dictionary();
+ //public Dictionary splines = new Dictionary();
+ }
+
+ //Def per BodyParts
+ public class SizedApparelBodyPartDef : Def
+ {
+ SizedApparelBodyPartOf bodyPartOf = SizedApparelBodyPartOf.None;
+ public bool canPose = true;
+ public List TexturePaths;
+
+ }
+
+ public class SizedApparelBodyPart
+ {
+ static MethodInfo overrideMatMethod = AccessTools.Method(typeof(PawnRenderer), "OverrideMaterialIfNeeded");
+ static Color defaultNippleColor = Color.white;//nipple texture is already colored with pink. so make it white as default to avoid double coloring pink //Strong Pink Color = new ColorInt(255, 121, 121).ToColor
+
+ //this is for RGB Channel Edit
+ static string texturePath_White = "SizedApparel/Masks/White";
+ static string texturePath_Black = "SizedApparel/Masks/Black";
+ static string texturePath_Red = "SizedApparel/Masks/Red";
+ static string texturePath_Green = "SizedApparel/Masks/Green";
+ static string texturePath_Blue = "SizedApparel/Masks/Blue";
+
+
+ public bool AutoOffsetForFurCoveredBody = true;
+
+ public SizedApparelBodyPart(Pawn pawn, ApparelRecorderComp apparelRecorderComp, string bodyPartName, SizedApparelBodyPartOf bodyPartOf, string defaultHediffName, bool isBreast, bool isOverlay, string customPathName = null, ColorType colorOf = ColorType.Skin, bool needBoneToRender = true, Bone parentBone = null, bool isCenteredTexture = false )
+ {
+ this.pawn = pawn; //owner
+
+ this.apparelRecorderCompCache = apparelRecorderComp; //for reduce GetComp Call; if it is null, it will try to get pawn's comp.
+
+ this.bodyPartName = bodyPartName;
+
+ this.def = DefDatabase.AllDefs.FirstOrDefault(b => b.defName == bodyPartName);
+
+ this.bodyPartOf = bodyPartOf;
+ this.defaultHediffName = defaultHediffName;
+ this.isBreast = isBreast;
+ this.isOverlay = isOverlay;
+ this.customPath = customPathName;
+ this.colorType = colorOf;
+
+ this.bone = parentBone;
+ this.mustHaveBone = needBoneToRender;
+ this.centeredTexture = isCenteredTexture;
+ }
+
+ public void SetCenteredTexture(bool isCentered)
+ {
+ this.centeredTexture = isCentered;
+ }
+
+ public Vector2 OffsetFromUVOffset(Vector2 vector, Mesh mesh , bool isFliped = false)
+ {
+ //treat mesh as plane
+ //Vector3 width = mesh.vertices[2] - mesh.vertices[1];
+ //Vector3 height = mesh.vertices[1] - mesh.vertices[2];
+
+
+ if(!isFliped)
+ return new Vector2((mesh.vertices[2].x - mesh.vertices[0].x)*vector.x,(mesh.vertices[0].z - mesh.vertices[2].z)*vector.y);
+ return new Vector2((mesh.vertices[2].x - mesh.vertices[0].x)*vector.x, (mesh.vertices[2].z - mesh.vertices[0].z)*vector.y);
+ /*
+ * Vector2 loc = new Vector2(0.5f, 0.5f) - vector;
+ if(!isFliped)
+ return new Vector2(Mathf.Lerp(mesh.vertices[0].x, mesh.vertices[2].x, loc.x), Mathf.Lerp(mesh.vertices[0].z, mesh.vertices[2].z, loc.y));
+ return new Vector2(Mathf.Lerp(mesh.vertices[3].x, mesh.vertices[1].x, loc.x), Mathf.Lerp(mesh.vertices[3].z, mesh.vertices[1].z, loc.y));
+
+
+
+ */
+
+ }
+
+ //public Vector2 OffestFromUVOffset(Vector2 vector, Vector2 drawSize, bool isFliped = false)
+
+ public SizedApparelBodyPartDef def;
+
+ public Pawn pawn;
+ public ApparelRecorderComp apparelRecorderCompCache; // for reduce getComp call;
+ public Bone bone;
+ private bool mustHaveBone;
+
+ public bool centeredTexture = false; // false to keep original position from mesh. and consider this graphics pivot as bone position
+
+ public string bodyPartName; //breast, penis, belly, pubichair... etc. just name. not like architech something
+ public string customPath = null;
+ public SizedApparelBodyPartOf bodyPartOf = SizedApparelBodyPartOf.None;
+ public string defaultHediffName;
+
+ public bool isBreast = false;
+
+ public bool isOverlay = false; //write z cache?
+
+ public string currentHediffName;
+
+ public bool isVisible = true;
+
+ public int lastPoseTick = -1;
+
+ public ColorType colorType = ColorType.Skin;
+ public Color? customColorOne;
+ public Color? customColorTwo;
+
+
+ //customize
+ public string customPose = null;
+ public Vector2? lookAnLocation = null;
+ public Rot4? rotOverride = null;
+
+ //variation
+ public string variation = null;
+ public Color? variationColor;
+ public colorOverrideMode variationColorMode = colorOverrideMode.Default;
+
+
+ //TODO. age setting?
+ public int minDrawAge = -1;
+ public int maxDrawAge = -1;
+
+
+ public void SetBone(Bone bone)
+ {
+ this.bone = bone;
+ }
+
+ public void SetCustomPose(string newPose, bool autoUpdate = true, bool autoSetPawnGraphicDirty = false)
+ {
+ if (customPose == newPose)
+ return;
+ if(SizedApparelSettings.Debug)
+ Log.Message("[SizedApparel] Setting Custom Pose : " + newPose);
+ customPose = newPose;
+ if (autoUpdate)
+ {
+ this.UpdateGraphic();
+ this.lastPoseTick = Find.TickManager.TicksGame;
+ }
+
+ if(autoSetPawnGraphicDirty)
+ {
+ if (pawn == null)
+ return;
+ PortraitsCache.SetDirty(pawn);
+ GlobalTextureAtlasManager.TryMarkPawnFrameSetDirty(pawn);
+ }
+ }
+
+ public bool CheckCanPose(string targetPose, bool checkApparels, bool checkBodyParts, bool mustMatchSize, bool mustMatchBodytype, bool mustMatchRace)
+ {
+ if (checkApparels)
+ {
+ if (!SizedApparelUtility.CanPoseApparels(pawn, targetPose, currentHediffName, currentSeverityInt, cappedSeverityInt))
+ return false;
+ }
+ if (checkBodyParts)
+ {
+ Graphic graphic = GetBodyPartGraphics(false, mustMatchSize, mustMatchBodytype, mustMatchRace);
+ Graphic graphicH = GetBodyPartGraphics(true, mustMatchSize, mustMatchBodytype, mustMatchRace);
+ if (graphic != null || graphicH != null)
+ return true;
+ return false;
+ }
+ return true;
+ }
+
+
+ //TODO...
+ public int currentSeverityInt = -1;
+ public int cappedSeverityInt = 1000; // supported severity from worn apparel graphics
+
+ public Vector2 pivot = Vector2.zero;
+
+ public Vector2 position = Vector2.zero;//offset from pivot //UV. not pixel
+
+ public SizedApparelTexturePointDef points;
+ public SizedApparelTexturePointDef pointsHorny;
+
+
+ public float rotation = 0; // +: rotate right, -: rotate left
+ public float scale = 1f;
+
+ public Graphic bodyPartGraphic;
+ public Graphic bodyPartGraphicHorny;
+
+
+
+ public Vector2 positionOffset = Vector2.zero; //offset from position //UV. not pixel
+ public Vector2 positionOffsetSouth = Vector2.zero;
+ public Vector2 positionOffsetNorth = Vector2.zero;
+ public Vector2 positionOffsetEast = Vector2.zero;
+ public Vector2 positionOffsetWest = Vector2.zero;
+
+ public float depthOffset = 0f;
+
+ //0.008f
+ public float depthOffsetEast = 0.008f;
+ public float depthOffsetWest = 0.008f;
+ public float depthOffsetSouth = 0.008f;
+ public float depthOffsetNorth = 0.008f;
+
+
+ //bigger = in front
+ public void SetDepthOffsets(float south, float north, float east, float west)
+ {
+ depthOffsetSouth = south;
+ depthOffsetNorth = north;
+ depthOffsetEast = east;
+ depthOffsetWest = west;
+ }
+ public void SetDepthOffsets(Depth4Offsets oppsets)
+ {
+ depthOffsetSouth = oppsets.south;
+ depthOffsetNorth = oppsets.north;
+ depthOffsetEast = oppsets.east;
+ depthOffsetWest = oppsets.west;
+ }
+ public void SetPositionOffsets(Vector2 south, Vector2 north, Vector2 east, Vector2 west)
+ {
+ positionOffsetSouth = south;
+ positionOffsetNorth = north;
+ positionOffsetEast = east;
+ positionOffsetWest = west;
+ }
+ public Graphic GetBodyPartGraphics(bool isHorny, bool mustMatchSize = false, bool mustMatchBodytype = false, bool mustMatchRace = false, string poseOverride = null)
+ {
+ SizedApparelTexturePointDef var;
+ return GetBodyPartGraphics(isHorny, out var, mustMatchBodytype, mustMatchSize, mustMatchRace, poseOverride);
+ }
+
+ public Graphic GetBodyPartGraphics(bool isHorny, out SizedApparelTexturePointDef outPoints, bool mustMatchSize = false, bool mustMatchBodyType = false , bool mustMatchRace = false ,string poseOverride = null, string variationOverride = null)
+ {
+ if (pawn == null)
+ {
+ outPoints = null;
+ return null;
+ }
+ var comp = apparelRecorderCompCache;
+ if (comp == null)
+ comp = pawn.GetComp();
+ if (comp == null)
+ {
+ outPoints = null;
+ return null;
+ }
+
+ string bodyTypeString = pawn.story?.bodyType?.defName;
+
+ var key = new SizedApparelsDatabase.BodyPartDatabaseKey(pawn.def.defName, bodyTypeString, currentHediffName, customPath==null?bodyPartName: customPath, pawn.gender, Math.Min(currentSeverityInt, cappedSeverityInt), isHorny, poseOverride==null?customPose:poseOverride, variationOverride==null?variation: variationOverride);
+ var result = SizedApparelsDatabase.GetSupportedBodyPartPath(key, isBreast, customPath == null ? bodyPartName : customPath, defaultHediffName);
+
+
+
+
+ if (mustMatchSize)
+ if (Math.Min(currentSeverityInt, cappedSeverityInt) != result.size)
+ {
+ outPoints = null;
+ return null;
+ }
+ if (mustMatchBodyType)
+ {
+ if(result.bodyType != pawn.story?.bodyType?.defName)
+ {
+ outPoints = null;
+ return null;
+ }
+ }
+ if (mustMatchRace)
+ {
+ if (result.raceName != pawn.def.defName)
+ {
+ outPoints = null;
+ return null;
+ }
+ }
+
+ if (result.pathWithSizeIndex == null)
+ {
+ outPoints = null;
+ return null;
+ }
+ outPoints = result.points;
+ return GraphicDatabase.Get(result.pathWithSizeIndex);
+ }
+
+ public void UpdateGraphic()
+ {
+ bodyPartGraphic = GetBodyPartGraphics(false, out points, false);
+ bodyPartGraphicHorny = GetBodyPartGraphics(true, out pointsHorny, false);
+ }
+
+ public void UpdateGraphic(int index, int indexCapped = 1000)
+ {
+ this.currentSeverityInt = index;
+ this.cappedSeverityInt = indexCapped;
+
+ UpdateGraphic();
+ }
+
+ public void ResetTransform()
+ {
+ this.position = Vector2.zero;
+ this.scale = 1f;
+ this.rotation = 0;
+ }
+
+ public void ClearGraphics()
+ {
+ this.bodyPartGraphic = null;
+ this.bodyPartGraphicHorny = null;
+ this.points = null;
+ this.pointsHorny = null;
+ }
+ public void Clear()
+ {
+ currentHediffName = null;
+ currentSeverityInt = -1;
+ cappedSeverityInt = 1000;
+ customPose = null;
+ rotOverride = null;
+
+ ClearGraphics();
+ }
+
+ /*
+ public void SetHediffData(string name, int severityIndex , string variation = null)
+ {
+ currentHediffName = name;
+ currentSeverityInt = severityIndex;
+ }*/
+
+ public void SetHediffData(string name, int severityIndex, int cappedSeverityIndex = 1000, string variation = null)
+ {
+ currentHediffName = name;
+ currentSeverityInt = severityIndex;
+ this.cappedSeverityInt = cappedSeverityIndex;
+ this.variation = variation;
+ }
+
+ public void DrawBodyPart (Vector3 rootLoc, float angle, Rot4 facing, RotDrawMode bodyDrawType, PawnRenderFlags flags, Mesh bodyMesh)
+ {
+ if (!isVisible)
+ return;
+ if (scale == 0f)
+ return; //Don't draw if scale is zero
+ if (pawn == null)
+ return;
+
+ if (mustHaveBone && bone == null)
+ return;
+
+ if (bodyMesh == null)
+ {
+ if (SizedApparelSettings.Debug)
+ Log.Warning("[SizedApparel] DrawBodyParts But Null Body Mesh! : " + pawn.Name);
+ return;
+ }
+
+
+ PawnRenderer pawnRenderer = pawn.Drawer.renderer;
+ Shader shader = shader = ShaderDatabase.CutoutSkinOverlay;
+ Color drawColor1 = Color.white;
+ Color drawColor2 = Color.white;
+
+
+ bool forceWriteZ = true;
+
+ bool HasFurSkin = false;
+ //Furskin Check
+ /*
+ if (pawn.Drawer.renderer.graphics.furCoveredGraphic != null)
+ {
+ HasFurSkin = true;
+ }*/
+
+ if (colorType == ColorType.Skin)
+ {
+ forceWriteZ = true;
+ if (bodyDrawType == RotDrawMode.Fresh)
+ {
+ if (HasFurSkin)
+ {
+
+ }
+ else
+ {
+ shader = pawn.Drawer.renderer.graphics.nakedGraphic.Shader;
+ if (!ShaderUtility.SupportsMaskTex(shader))
+ shader = shader = ShaderDatabase.CutoutSkinOverlay;
+ drawColor1 = pawnRenderer.graphics.nakedGraphic.Color;
+ drawColor2 = pawnRenderer.graphics.nakedGraphic.ColorTwo;
+ }
+
+ }
+ else if (bodyDrawType == RotDrawMode.Rotting)
+ {
+
+ shader = pawn.Drawer.renderer.graphics.rottingGraphic.Shader;
+ if (!ShaderUtility.SupportsMaskTex(shader))
+ shader = shader = ShaderDatabase.CutoutSkinOverlay;
+ drawColor1 = pawnRenderer.graphics.rottingGraphic.Color;
+ drawColor2 = pawnRenderer.graphics.nakedGraphic.ColorTwo;
+ }
+ }
+ else if (colorType == ColorType.Nipple)
+ {
+ forceWriteZ = true;
+
+ //Get SkinColor first.
+ if (bodyDrawType == RotDrawMode.Fresh)
+ {
+ if (HasFurSkin)
+ {
+
+ }
+ else
+ {
+ shader = pawn.Drawer.renderer.graphics.nakedGraphic.Shader;
+ if (!ShaderUtility.SupportsMaskTex(shader))
+ shader = shader = ShaderDatabase.CutoutSkinOverlay;
+ drawColor1 = pawnRenderer.graphics.nakedGraphic.Color;
+ drawColor2 = pawnRenderer.graphics.nakedGraphic.ColorTwo;
+ }
+
+ }
+ else if (bodyDrawType == RotDrawMode.Rotting)
+ {
+
+ shader = pawn.Drawer.renderer.graphics.rottingGraphic.Shader;
+ if (!ShaderUtility.SupportsMaskTex(shader))
+ shader = shader = ShaderDatabase.CutoutSkinOverlay;
+ drawColor1 = pawnRenderer.graphics.rottingGraphic.Color;
+ drawColor2 = pawnRenderer.graphics.nakedGraphic.ColorTwo;
+ }
+
+ if(apparelRecorderCompCache != null)
+ {
+ if(apparelRecorderCompCache.nippleColor != null)
+ {
+ drawColor1 = apparelRecorderCompCache.nippleColor.Value; //* drawColor1;
+ drawColor2 = apparelRecorderCompCache.nippleColor.Value; //* drawColor2; //maybe can be issue
+ }
+ else
+ {
+ //nipple Color is null
+ //Ust Default Color for Nipple with SkinColor
+ drawColor1 = defaultNippleColor * drawColor1;
+ drawColor2 = defaultNippleColor * drawColor2;
+
+ }
+ }
+
+
+ }
+ else if (colorType == ColorType.Hair)
+ {
+ forceWriteZ = false;
+ shader = ShaderDatabase.Transparent;
+ if(pawn.story != null)
+ drawColor1 = pawn.story.hairColor;
+ }
+ else if (colorType == ColorType.Custom)
+ {
+ forceWriteZ = true;
+ shader = ShaderDatabase.Transparent;
+ if(customColorOne != null)
+ drawColor1 = customColorOne.Value;
+ if (customColorTwo != null)
+ drawColor2 = customColorTwo.Value;
+ }
+ else if (colorType == ColorType.None)
+ {
+ forceWriteZ = false;
+ shader = ShaderDatabase.Cutout;
+ }
+ if (isOverlay)
+ {
+ if (shader == ShaderDatabase.Cutout)
+ shader = ShaderDatabase.Transparent;
+ else if (shader == ShaderDatabase.CutoutSkin || shader == ShaderDatabase.CutoutSkinColorOverride)
+ shader = ShaderDatabase.CutoutSkinOverlay;
+ else
+ shader = ShaderDatabase.Transparent;
+ }
+
+
+ Mesh scaledBodyMesh;
+
+ BoneTransform boneTransform = null;
+ if(bone != null)
+ {
+ if (facing == Rot4.South)
+ {
+ boneTransform = bone.south;
+ }
+ else if (facing == Rot4.North)
+ {
+ boneTransform = bone.north;
+ }
+ else if (facing == Rot4.East)
+ {
+ boneTransform = bone.east;
+
+ }
+ else if (facing == Rot4.West)
+ {
+ boneTransform = bone.west;
+ if (boneTransform == null)
+ boneTransform = bone.east;
+
+ }
+ }
+
+ float drawScale = scale;
+ float drawRotation = angle;
+ Vector3 drawPosition = rootLoc;
+
+ /*
+ if (this.pawn.ageTracker.CurLifeStage.bodyDrawOffset != null)
+ {
+ drawPosition += this.pawn.ageTracker.CurLifeStage.bodyDrawOffset.Value;
+ }*/
+
+ if (boneTransform != null)
+ {
+ //TODO fixed angle for IK?
+
+ float width = (bodyMesh.vertices[2].x - bodyMesh.vertices[0].x);
+ if (centeredTexture)
+ {
+ bool westUsingEast = false;
+ if (facing == Rot4.West && bone.west == null)
+ westUsingEast = true;
+
+ drawRotation = boneTransform.InitialAngle + boneTransform.angleOffset;
+ //not sure it work correct
+ Vector3 v = (boneTransform.InitialPosition + boneTransform.positionOffset) * width;
+ var q = Quaternion.AngleAxis (westUsingEast? -angle : angle, Vector3.up);
+ v = q * v;
+ drawPosition = (v) ; // calculate rotated point
+
+ //Log.Message(boneTransform.angleOffset.ToString());
+ if (westUsingEast)
+ {
+ //already scaled with "width"?
+ //its using east as west. so flip position
+ drawPosition.Scale(new Vector3(-1f,0f,1f));
+ //drawRotation = boneTransform.InitialAngle - boneTransform.angleOffset;
+ }
+ drawPosition += rootLoc;
+ drawRotation += angle ;
+ }
+ else
+ {
+ //NotCentered Texture not yet support Rotation System.
+ //wip
+ Vector3 v = Vector3.zero;
+
+ bool westUsingEast = false;
+ if (facing == Rot4.West && bone.west == null)
+ westUsingEast = true;
+ drawRotation = boneTransform.InitialAngle; // + boneTransform.angleOffset
+ //not sure it work correct
+ //Vector3 v = (boneTransform.InitialPosition); //initialpos as custom pivot
+ //var q = Quaternion.AngleAxis(westUsingEast ? -drawRotation : drawRotation, Vector3.up);
+ //var q2 = Quaternion.AngleAxis(westUsingEast ? -angle : angle, Vector3.up);
+
+ //v = q * v; // calculate final draw position with torso angle
+ //v = v + boneTransform.InitialPosition + boneTransform.positionOffset;
+ //v = q2 * v; //NotCentered Texture not yet support Rotation System.
+
+ drawPosition = (v) * width;
+ if (westUsingEast)
+ {
+ //already scaled with "width"?
+ //its using east as west. so flip position
+ drawPosition.Scale(new Vector3(-1f, 0f, 1f));
+ //drawRotation = boneTransform.InitialAngle - boneTransform.angleOffset;
+ }
+ drawPosition += rootLoc ; // adjust with result
+ //Log.Message(boneTransform.angleOffset.ToString());
+ drawRotation += angle;
+ }
+ }
+
+ /*
+ if (drawScale != 1f)
+ {
+ // scale Only Rimworld Plane Mesh
+ if(bodyMesh.vertexCount == 4)
+ {
+ float width = (bodyMesh.vertices[2].x - bodyMesh.vertices[0].x);
+
+ //var meshSet = MeshPool.GetMeshSetForWidth(scale * width);
+ var meshSet = MeshPool.GetMeshSetForWidth(scale * width);
+ scaledBodyMesh = meshSet.MeshAt(facing);
+ }
+ else
+ scaledBodyMesh = bodyMesh;
+ }
+ else
+ {
+ scaledBodyMesh = bodyMesh;
+ }*/
+ scaledBodyMesh = bodyMesh;
+
+ Quaternion quaternion = Quaternion.AngleAxis(drawRotation, Vector3.up);
+
+
+
+
+ Rot4 targetRot = facing;
+ if (rotOverride != null)
+ targetRot = rotOverride.Value;
+
+ if (targetRot == Rot4.South)
+ {
+ var loc = OffsetFromUVOffset(positionOffsetSouth, scaledBodyMesh);
+ drawPosition.x += loc.x;
+ drawPosition.z += loc.y;
+ drawPosition.y += depthOffsetSouth;
+ }
+ else if(targetRot == Rot4.North)
+ {
+ var loc = OffsetFromUVOffset(positionOffsetNorth, scaledBodyMesh);
+ drawPosition.x += loc.x;
+ drawPosition.z += loc.y;
+ drawPosition.y += depthOffsetNorth;
+ }
+ else if (targetRot == Rot4.East)
+ {
+ var loc = OffsetFromUVOffset(positionOffsetEast, scaledBodyMesh);
+ drawPosition.x += loc.x;
+ drawPosition.z += loc.y;
+ drawPosition.y += depthOffsetEast;
+ }
+ else if (targetRot == Rot4.West)
+ {
+ var loc = OffsetFromUVOffset(positionOffsetWest, scaledBodyMesh);
+ drawPosition.x += loc.x;
+ drawPosition.z += loc.y;
+ drawPosition.y += depthOffsetWest;
+ }
+
+
+
+
+ Graphic graphic = null;
+ if (SizedApparelUtility.IsHorny(pawn))
+ graphic = bodyPartGraphicHorny;
+ if (graphic == null)
+ graphic = bodyPartGraphic;
+
+ if (graphic == null)
+ return;
+
+ //ForFurskinOffset
+ if(bodyDrawType == RotDrawMode.Fresh && HasFurSkin && AutoOffsetForFurCoveredBody)
+ {
+ //vector.y += 0.009187258f; //in PawnRenderer, it adds 0.009187258f.
+
+ //graphic.maskPath does error? need to check
+ // worn fur body and naked fur body has different offsets... wtf
+ //TODO Need to Fix
+ }
+
+
+
+
+ Material mat;
+
+ //If ForceWriteDepth, draw Cutout mesh for write depth. this is for avoid problem of body addons drawing under other meshes. such as breasts front of body but behind tail.
+ if (forceWriteZ || (!flags.FlagSet(PawnRenderFlags.Cache) && !isOverlay))// //(!flags.FlagSet(PawnRenderFlags.Cache) && !isOverlay)
+ {
+ Graphic Zgraphic = graphic.GetColoredVersion(ShaderDatabase.CutoutComplex, drawColor1, drawColor2); // ShaderDatabase.Cutout
+ Vector3 drawPositionZ = drawPosition;
+ drawPositionZ.y = drawPositionZ.y - 0.00001f; //Send Back of body, but it can still write depth. 1.4: send to 0
+
+ mat = flags.FlagSet(PawnRenderFlags.Cache) ? Zgraphic.MatAt(targetRot) : (Material)overrideMatMethod.Invoke(pawnRenderer, new object[] { Zgraphic.MatAt(facing), pawn, flags.FlagSet(PawnRenderFlags.Portrait) });
+ GenDraw.DrawMeshNowOrLater(scaledBodyMesh, drawPositionZ, quaternion, mat, flags.FlagSet(PawnRenderFlags.DrawNow)); // draw for writeZ data to solve shadow issue
+ }
+
+ //shader must be mask
+ graphic = graphic.GetColoredVersion(shader, drawColor1, drawColor2);
+
+ if (graphic.maskPath == null)
+ {
+ //Test
+ //graphic.maskPath = texturePath_Red;
+ }
+
+ //drawPosition.y += 0.00001f;
+ mat = flags.FlagSet(PawnRenderFlags.Cache) ? graphic.MatAt(targetRot) : (Material)overrideMatMethod.Invoke(pawnRenderer, new object[] { graphic.MatAt(facing), pawn, flags.FlagSet(PawnRenderFlags.Portrait) });
+ GenDraw.DrawMeshNowOrLater(scaledBodyMesh, drawPosition, quaternion, mat, flags.FlagSet(PawnRenderFlags.DrawNow));
+
+ }
+ }
+
+
+ //TODO: Torso Pose?
+
+
+ public class BodyDef : Def
+ {
+ //public List BodyParts;
+
+
+ //defName = raceName ?? could it work?
+
+ public List bodies = new List();
+
+
+ //public List penisOffset;
+ //public List vaginaOffset;
+ //public List pubicHairOffset;
+ //public List udderOffset;
+ //public List bellyOffset;
+ //public List breastsOffset;
+ //public List anusOffset;
+
+ }
+
+ public class SizedApparelBody
+ {
+ public string customPoseOfBody = null;
+
+ public bool canCustomPose()
+ {
+ //check apparels
+ return false;
+ }
+ }
+
+ public class SizedApparelBodyPartOfssetDef : Def
+ {
+ //defName IsRaceName
+
+ }
+
+}
diff --git a/1.3/source/SizedApparel/SizedApparelBodyPartDef.cs b/1.3/source/SizedApparel/SizedApparelBodyPartDef.cs
new file mode 100644
index 0000000..742f3f5
--- /dev/null
+++ b/1.3/source/SizedApparel/SizedApparelBodyPartDef.cs
@@ -0,0 +1,163 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using UnityEngine;
+using Verse;
+
+namespace SizedApparel
+{
+
+ //This Class is Use for Def BodyParts' Custom Pivot, or Some Special Common Vector Points Per Serverity.
+ //Not Consider Acture Graphic Textures.
+ public class SkeletonDef : Def
+ {
+ //defName = Pawn's race name (such as "Human")
+ //public List graphicBones = new List();
+
+ //Do Not Directly Use it
+ public List skeletons = new List();
+
+
+ public Skeleton CreateSkeleton(string bodyType)
+ {
+ for(int i = 0; i< skeletons.Count; i++)
+ {
+ if(skeletons[i].bodyType == bodyType)
+ {
+ return new Skeleton(skeletons[i]);
+ }
+ }
+ return null;
+ }
+ }
+
+ public class Skeleton
+ {
+ public string bodyType = null; // can be null for animal or etc
+ public List Bones;
+
+ //only runtime. Do not Set in Def
+ public Rot4 BodyFacing; // for flip east-west bones
+ public Rot4 HeadFacing; //TODO
+
+ public Skeleton()
+ {
+
+ }
+ public Skeleton(Skeleton skeletonToCopy)
+ {
+ this.Bones = new List();
+
+
+ foreach (var s in skeletonToCopy.Bones)
+ {
+ this.Bones.Add(new Bone(s, this));
+ }
+
+ }
+ public Bone FindBone(string boneName)
+ {
+ foreach (var b in this.Bones)
+ {
+ if (b.name == boneName)
+ return b;
+ }
+ return null;
+ }
+
+ }
+
+ //for deafault bone support?
+ public class BodyPartBoneDef : Def
+ {
+ //DefName is Bone Name To Use.
+ public Vector3 customPivot = new Vector3(0.5f, 0, 0.5f);
+ public Vector3 Position = new Vector3(0.5f, 0, 0.5f); // Local Position(UV) from Body
+ public float Length = 1;
+ public float Rotation = 0;
+ public float Scale = 1f; // Default Render Scale.
+ }
+
+ //Body Parts Graphic can be attached to bone position and rotation
+ public class Bone
+ {
+
+ public string name = null;
+ public Skeleton parentSkeleton = null;
+ //public string parentBoneName = null; // ToDo
+ public bool isHeadBone = false; // TODO
+ public BoneTransform south;
+ public BoneTransform north;
+ public BoneTransform east;
+ public BoneTransform west; // can be null. then use east
+ //hiding Graphic parameter will be in that bodygraphic class
+
+ public Bone()
+ {
+
+ }
+
+ public Bone(Bone boneToCopy, Skeleton parent)
+ {
+ this.name = boneToCopy.name;
+ this.parentSkeleton = parent;
+ this.isHeadBone = boneToCopy.isHeadBone;
+ if(boneToCopy.south != null)
+ this.south = new BoneTransform(boneToCopy.south);
+ if (boneToCopy.north != null)
+ this.north = new BoneTransform(boneToCopy.north);
+ if (boneToCopy.east != null)
+ this.east = new BoneTransform(boneToCopy.east);
+ if (boneToCopy.west != null)
+ this.west = new BoneTransform(boneToCopy.west); // null for use east
+
+ }
+
+ public void SetAngle(float angle)
+ {
+ if(south != null)
+ south.angleOffset = angle;
+ if (north != null)
+ north.angleOffset = angle;
+ if (east != null)
+ east.angleOffset = angle;
+ if (west != null)
+ west.angleOffset = angle;
+ }
+
+
+ }
+
+ public class BoneTransform
+ {
+ //public Vector3 customPivot = new Vector3(0.5f, 0, 0.5f); // used to calculation rotation. the rotating center will be customPivot.
+ //Custom Pivot Doesn't affect to Draw Position on zero Rotated.
+ public Vector3 InitialPosition = Vector3.zero; // Local Position(UV) from Body
+ public float InitialLength = 1;
+ public float InitialAngle = 0;
+ public float InitialScale = 1f;
+ public bool isHeadBone = false; // TODO
+
+ //public BodyPartGraphicBone parentBone; //TODO
+ public Vector3 positionOffset = Vector3.zero;
+ public float lengthOffset = 0;
+ public float angleOffset = 0;
+ public float scaleOffset = 0;
+
+ public BoneTransform() { }
+
+ public BoneTransform(BoneTransform boneToCopy)
+ {
+
+ //this.parentBoneName = boneToCopy.parentBoneName;
+ //this.customPivot = boneToCopy.customPivot;
+ this.InitialPosition = boneToCopy.InitialPosition;
+ this.InitialLength = boneToCopy.InitialLength;
+ this.InitialAngle = boneToCopy.InitialAngle;
+ this.InitialScale = boneToCopy.InitialScale;
+ }
+ }
+
+}
diff --git a/1.3/source/SizedApparel/SizedApparelBodyPartDetail.cs b/1.3/source/SizedApparel/SizedApparelBodyPartDetail.cs
new file mode 100644
index 0000000..31d6f8c
--- /dev/null
+++ b/1.3/source/SizedApparel/SizedApparelBodyPartDetail.cs
@@ -0,0 +1,272 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using rjw;
+using HarmonyLib;
+using UnityEngine;
+using RimWorld;
+using Verse;
+
+namespace SizedApparel
+{
+ public enum colorOverrideMode
+ {
+ Default, Multiply, Add
+ }
+ public class BodyPartVariationWithRace
+ {
+ public string hediffName;
+ public ListvarName = new List();
+
+ }
+
+ public class SizedApparelBodyPartVariationDef : Def
+ {
+ public string bodyPartName;
+ public Listvariations = new List();
+ }
+
+ public class SizedApparelBodyPartDetail : HediffComp
+ {
+
+ public string variation = null; // null to default
+ public string bodyPartName;
+ public SizedApparelBodyPartVariationDef variationDef;
+ public Color? colorOverride = null;//TODO
+ public colorOverrideMode colorMode = colorOverrideMode.Default;//TODO
+
+ public override string CompTipStringExtra => "Variation: " + (variation == null ? "Default" : variation) + " (sized apparel)";
+
+ public override void CompExposeData()
+ {
+ Scribe_Values.Look(ref this.variation, "variation", null, false);
+ //Scribe_Values.Look(ref this.colorOverride, "colorOverride",null, false);
+ //Scribe_Values.Look(ref this.colorMode, "colorMode", colorOverrideMode.Default, false);
+ }
+
+ public override void CompPostMake()
+ {
+ base.CompPostMake();
+
+ if (SizedApparelUtility.isBreast(parent.def.defName))
+ bodyPartName = "Breasts";
+ else if (Genital_Helper.is_vagina(parent)) // SizedApparelUtility.isVagina(parent.def.defName)
+ bodyPartName = "Vagina";
+ else if (SizedApparelUtility.isAnus(parent.def.defName))
+ bodyPartName = "Anus";
+ else if (SizedApparelUtility.isUdder(parent.def.defName))
+ bodyPartName = "Udder";
+ else if (Genital_Helper.is_penis(parent)) //SizedApparelUtility.isPenis(parent.def.defName)
+ bodyPartName = "Penis";
+
+ else
+ bodyPartName = parent.def.defName;
+
+
+ if (Pawn == null)
+ return;
+ if (DefDatabase.DefCount == 0)
+ {
+ Log.Warning("[Sized Apparel] Cannot Find Any BodyPart Variation Def. It can be version issue or other mod's patch issue.");
+ variation = null;
+ return;
+ }
+ try
+ {
+ variationDef = DefDatabase.AllDefs?.FirstOrDefault(b => b.bodyPartName == bodyPartName);
+ }
+ catch(ArgumentNullException e)
+ {
+ Log.Warning("[Sized Apparel] Cannot Find Any BodyPart Variation Def of ( " + bodyPartName + " )!. It can be version issue or other mod's patch issue.");
+ variation = null;
+ return;
+ }
+
+ if (variationDef == null)
+ return;
+ if (variationDef.variations == null)
+ return;
+ var variations = variationDef.variations?.FirstOrDefault(v => v.hediffName == parent.def.defName);
+ if (variations == null)
+ variations = variationDef.variations?.FirstOrDefault(v => v.hediffName == bodyPartName);
+ if (variations == null)
+ return;
+ if (variations.varName.NullOrEmpty())
+ return;
+
+ this.variation = variations.varName.RandomElement();
+
+ if (variation.ToLower() == "null" || variation.ToLower() == "default")
+ {
+ variation = null;
+ }
+
+ }
+
+
+ }
+ public class SizedApparelBodyPartDetailProperties : HediffCompProperties
+ {
+ public string bodyPartName;
+
+ public SizedApparelBodyPartDetailProperties()
+ {
+ this.compClass = typeof(SizedApparelBodyPartDetail);
+ }
+ }
+
+
+ public class SizedApparelBodyPartDetailGizmo : Command
+ {
+
+ }
+
+
+
+
+
+ public class SizedApparelBodyPartDetailThing : ThingComp
+ {
+
+ public string variation = null; // null to default
+ public string bodyPartName;
+ public SizedApparelBodyPartVariationDef variationDef;
+ public Color? colorOverride = null;//TODO
+ public colorOverrideMode colorMode = colorOverrideMode.Default;//TODO
+
+
+ public override string GetDescriptionPart()
+ {
+ if(SizedApparelSettings.showBodyPartsVariation)
+ return "Variation: " +( variation == null?"Default":variation) + " (sized apparel)";
+
+ return string.Empty;
+ }
+
+ /*
+ public override string TransformLabel(string label)
+ {
+ return label + "Variation: " + variation == null ? "Default" : variation + " (sized apparel)";
+ }
+ */
+
+ public override void PostExposeData()
+ {
+ Scribe_Values.Look(ref this.variation, "variation", null, false);
+ //Scribe_Values.Look(ref this.colorOverride, "colorOverride",null, false);
+ //Scribe_Values.Look(ref this.colorMode, "colorMode", colorOverrideMode.Default, false);
+ }
+
+ public void InitComp(Pawn pawn = null)
+ {
+ HediffDef named = DefDatabase.GetNamed(this.parent.def.defName, true);
+ List allMaps_FreeColonistsAndPrisonersSpawned = PawnsFinder.AllMaps_FreeColonistsAndPrisonersSpawned;
+ pawn = ((allMaps_FreeColonistsAndPrisonersSpawned != null) ? allMaps_FreeColonistsAndPrisonersSpawned.RandomElement() : null);
+ if (pawn == null)
+ {
+ List all_AliveOrDead = PawnsFinder.All_AliveOrDead;
+ pawn = ((all_AliveOrDead != null) ? all_AliveOrDead.RandomElement() : null);
+ }
+ SizedApparelBodyPartDetail compHediffBodyPart = HediffMaker.MakeHediff(named, pawn, null).TryGetComp();
+ if (compHediffBodyPart != null)
+ {
+ //compHediffBodyPart.initComp(pawn, false);
+ //compHediffBodyPart.updatesize(0f);
+ this.variation = compHediffBodyPart.variation;
+ }
+ }
+
+
+ public override void PostPostMake()
+ {
+ base.PostPostMake();
+
+ if (SizedApparelUtility.isBreast(parent.def.defName))
+ bodyPartName = "Breasts";
+ else if (SizedApparelUtility.isVagina(parent.def.defName))
+ bodyPartName = "Vagina";
+ else if (SizedApparelUtility.isAnus(parent.def.defName))
+ bodyPartName = "Anus";
+ else if (SizedApparelUtility.isUdder(parent.def.defName))
+ bodyPartName = "Udder";
+ else if (SizedApparelUtility.isPenis(parent.def.defName))
+ bodyPartName = "Penis";
+
+ else
+ bodyPartName = parent.def.defName;
+
+ variationDef = DefDatabase.AllDefs?.FirstOrDefault(b => b.bodyPartName == bodyPartName);
+ if (variationDef == null)
+ return;
+ if (variationDef.variations == null)
+ return;
+ var variations = variationDef.variations?.FirstOrDefault(v => v.hediffName == parent.def.defName);
+ if (variations == null)
+ variations = variationDef.variations?.FirstOrDefault(v => v.hediffName == bodyPartName);
+ if (variations == null)
+ return;
+ if (variations.varName.NullOrEmpty())
+ return;
+
+ this.variation = variations.varName.RandomElement();
+
+ if (variation.ToLower() == "null" || variation.ToLower() == "default")
+ {
+ variation = null;
+ }
+
+ }
+
+
+ }
+ public class SizedApparelBodyPartDetailThingProperties : CompProperties
+ {
+ public string bodyPartName;
+
+ public SizedApparelBodyPartDetailThingProperties()
+ {
+ this.compClass = typeof(SizedApparelBodyPartDetailThing);
+ }
+ }
+
+
+
+ [HarmonyPatch(typeof(SexPartAdder), "recipePartAdder")]
+ public class recipePartAdderPatch
+ {
+ public static void Postfix(RecipeDef recipe, Pawn pawn, BodyPartRecord part, List ingredients, Hediff __result)
+ {
+ if (__result == null)
+ return;
+ Thing thing = ingredients.FirstOrDefault(x => x.def.defName == recipe.addsHediff.defName);
+ if (thing == null)
+ return;
+ SizedApparelBodyPartDetailThing CompThing = thing.TryGetComp();
+ SizedApparelBodyPartDetail CompHediff = __result.TryGetComp();
+ CompHediff.variation = CompThing.variation;
+ }
+
+ }
+ [HarmonyPatch(typeof(SexPartAdder), "recipePartRemover")]
+ public class recipePartRemoverPatch
+ {
+ public static void Postfix(Hediff hd, ref Thing __result)
+ {
+ //Thanks! "Stardust" helped
+ try
+ {
+ SizedApparelBodyPartDetailThing CompThing = __result.TryGetComp();
+ SizedApparelBodyPartDetail CompHediff = hd.TryGetComp();
+
+ CompThing.variation = CompHediff.variation;
+ }
+ catch (NullReferenceException e)
+ {
+ Log.Error(e.StackTrace);
+ }
+ }
+ }
+
+}
diff --git a/1.3/source/SizedApparel/SizedApparelBodyPartEditor.cs b/1.3/source/SizedApparel/SizedApparelBodyPartEditor.cs
new file mode 100644
index 0000000..cc3f2e7
--- /dev/null
+++ b/1.3/source/SizedApparel/SizedApparelBodyPartEditor.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace SizedApparel
+{
+ //editing offset for alien race? such as penis, anus offsets, except breast.(breasts position must be matched with apparels.)
+ class SizedApparelBodyPartEditor
+ {
+ }
+}
diff --git a/1.3/source/SizedApparel/SizedApparelComp.cs b/1.3/source/SizedApparel/SizedApparelComp.cs
new file mode 100644
index 0000000..2195d3c
--- /dev/null
+++ b/1.3/source/SizedApparel/SizedApparelComp.cs
@@ -0,0 +1,1929 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using UnityEngine;
+using RimWorld;
+using rjw;
+using Verse;
+
+namespace SizedApparel
+{
+ [StaticConstructorOnStartup]
+ public class ApparelRecorderComp : ThingComp
+ {
+ Pawn pawn;// Parent Cache
+
+ public bool recentClothFlag = true;
+
+ public bool isDrawAge = true;
+
+ public bool testbool = false;
+ public ApparelRecorderCompProperties Props => (ApparelRecorderCompProperties)this.props;
+ public bool hasUpdateBefore = false;
+ public bool hasUpdateBeforeSuccess = false;
+ public bool hasGraphicUpdatedBefore = false; // not yet
+
+ public bool needToCheckApparelGraphicRecords = false;
+ public bool isDirty = true;
+ public bool isHediffDirty = true;
+ public bool isApparelDirty = true;
+ public bool isSkeletonDirty = true;
+ public bool isBodyAddonDirty = true; // reset all body addon graphics.
+ public bool hasUnsupportedApparel = true;
+ public bool havingSex = false;//Obsolete
+ public bool hasUpdateForSex = false;//Obsolete
+ string cachedBodytype;
+
+
+ public List cachedApparelGraphicRecord = new List();
+
+
+
+ public Hediff breastHediff = null;
+ public Hediff vaginaHediff = null;
+ public List penisHediffs = null; // RJW can attach multiple penis
+ public Hediff anusHediff = null;
+ public Hediff udderHediff = null;//RJW 4.6.8: Udder is not partof chest's breast. it attached to torso.
+
+ public Color? nippleColor; //for menstruation cycles Mod
+
+ //TODO Optimize Update Hediff Filter
+ private bool hasBreastsAddon = false;
+ private bool hasVaginaAddon = false;
+ private bool hasPenisAddon = false;
+ private bool hasAnusAddon = false;
+ private bool hasUdderAddon = false;
+ private bool hasPubicHairAddon = false;
+
+ public float breastSeverity = -1;
+
+ public float BreastSeverityCache = 0;
+ //public float BiggestBreastSeverityInAvailableTextures = 0;
+
+
+ //for breasts animation or something.
+ public bool ForceUpdateTickAnimation = false;
+ public bool ForceBlockTickAnimation = false; // useful when you have make fixed pose
+ public bool PrePositionCache;
+ public Vector3? prePositionCache;
+ public float? preAngleCache;
+ public int? preTickCache;
+ public Vector3 preVelocity = Vector3.zero;
+ public float preRotation = 0;
+ public Dictionary tickCache = new Dictionary();
+
+
+
+ public BodyDef bodyDef = null;
+ public List bodyAddons = new List(); // BodyParts Added form Defs
+
+ public SkeletonDef skeletonDef; // for rebuild Skeleton
+ public Skeleton skeleton;
+ public bool skipSkeleton = false;
+
+ //native BodyParts
+ public SizedApparelBodyPart bodyPartBreasts;//TODO: Make this as List
+ public SizedApparelBodyPart bodyPartNipple;//TODO
+ public List bodyPartPenises = new List();
+ public List bodyPartBalls = new List();
+ public SizedApparelBodyPart bodyPartVagina;
+ public SizedApparelBodyPart bodyPartAnus;
+ public SizedApparelBodyPart bodyPartBelly;
+ public SizedApparelBodyPart bodyPartMuscleOverlay;//TODO
+ public SizedApparelBodyPart bodyPartUdder;
+
+
+ public SizedApparelBodyPart bodyPartHips;
+ public List bodyPartThighs = new List();
+ public List bodyPartHands = new List();
+ public List bodyPartFeet = new List();
+
+ public PubicHairDef pubicHairDef = null;
+ public PubicHairDef initialPubicHairDef = null; // For StyleStaitionWork
+ public PubicHairDef nextPubicHairDef = null; // For StyleStaitionWork
+ public SizedApparelBodyPart bodyPartPubicHair;
+
+
+ public Graphic graphicSourceNaked = null; //original Graphic
+ public Graphic graphicSourceRotten = null; //original Graphic
+ public Graphic graphicSourceFurCovered = null; //original Graphic
+
+
+ public Graphic graphicbaseBodyNaked = null;
+ public SizedApparelTexturePointDef baseBodyNakedPoints;
+ public Graphic graphicbaseBodyCorpse = null;
+ public SizedApparelTexturePointDef baseBodyCorpsePoints;
+ public Graphic graphicbaseBodyRotten = null;
+ public SizedApparelTexturePointDef baseBodyRottenPoints;
+ public Graphic graphicbaseBodyFurCovered = null;
+ public SizedApparelTexturePointDef baseBodyFurCoveredPoints;
+
+
+ public AlienRaceSetting raceSetting = null;
+
+ public string customPose = null;
+ public SizedApparelPose currentCustomPose = null;
+
+
+ public bool forceHorny = false;
+
+
+ public bool canDrawBreasts = false;
+ public bool canDrawPenis = false;
+ public bool canDrawVaginaAndAnus = false;
+ public bool canDrawTorsoParts = false; //belly and udder
+
+
+ //this may reset skeleton animation. also little have process
+ public void InitSkeleton()
+ {
+ skeletonDef = DefDatabase.GetNamedSilentFail(pawn.def.defName);
+ if (skeletonDef == null)
+ {
+ if (raceSetting != null && raceSetting.asHuman == true) //old: !SizedApparelSettings.UnsupportedRaceToUseHumanlike
+ {
+ skeletonDef = DefDatabase.GetNamedSilentFail("Human");
+ }
+ }
+ if (skeletonDef != null)
+ {
+ if (this.pawn.story == null || this.pawn.story.bodyType == null)
+ {
+ foreach (Skeleton s in skeletonDef.skeletons)
+ {
+ if (s.bodyType == null)
+ {
+ this.skeleton = new Skeleton(s);
+ if (SizedApparelSettings.Debug)
+ Log.Message("[SizedApparel] Apply SkeletonDef: pawn withouth bodytype " + pawn.Name);
+ return;
+ }
+ }
+ }
+ else
+ {
+ //Setting Up Skeleton
+ foreach (Skeleton s in skeletonDef.skeletons)
+ {
+ if (s.bodyType == this.pawn.story.bodyType.defName)
+ {
+ this.skeleton = new Skeleton(s);
+ if (SizedApparelSettings.Debug)
+ Log.Message("[SizedApparel] Apply SkeletonDef: pawn with bodytype " + pawn.Name + " with SkeletonDef : " + this.pawn.story.bodyType.defName);
+ return;
+ }
+ }
+ }
+ this.skeleton = null;
+ }
+ if (SizedApparelSettings.Debug)
+ Log.Message("[SizedApparel] Apply SkeletonDef: No Skeleton Found for " + pawn.Name);
+ isSkeletonDirty = false;
+ }
+
+ public void InitBodyAddons()
+ {
+
+ bodyAddons.Clear();
+
+ //TODO
+ //bodyDef = DefDatabase.GetNamed(pawn.def.defName);
+
+ bodyDef = DefDatabase.GetNamedSilentFail(pawn.def.defName);
+
+ //bodyDef can be null
+
+ if (bodyDef == null)
+ {
+ if (raceSetting != null && raceSetting.asHuman) //old: !SizedApparelSettings.UnsupportedRaceToUseHumanlike
+ {
+ bodyDef = DefDatabase.GetNamedSilentFail("Human");
+ }
+ }
+
+
+ if (bodyDef != null && bodyDef.bodies != null)
+ {
+ if (pawn.story?.bodyType == null)
+ {
+ if(SizedApparelSettings.Debug)
+ Log.Message("[SizedApparel] Apply BodyDef: pawn has no bodytype " + pawn.Name);
+ BodyWithBodyType body = null;
+ if(!bodyDef.bodies.NullOrEmpty())
+ body = bodyDef.bodies[0];
+ if (body != null && body.Addons != null)
+ {
+ foreach (var bodyaddon in body.Addons)
+ {
+ if (bodyaddon == null)
+ continue;
+ var a = new SizedApparelBodyPart(pawn, this, bodyaddon.partName, bodyaddon.bodyPartOf, bodyaddon.defaultHediffName, bodyaddon.isBreasts, false, bodyaddon.customPath, bodyaddon.colorType, bodyaddon.mustHaveBone);
+ a.SetDepthOffsets(bodyaddon.depthOffset.south, bodyaddon.depthOffset.north, bodyaddon.depthOffset.east, bodyaddon.depthOffset.west);
+ //a.SetDepthOffsets(bodyaddon.depthOffset);
+ a.SetCenteredTexture(bodyaddon.centeredTexture);
+ bodyAddons.Add(a);
+ break;
+ }
+ }
+ }
+ else
+ {
+ foreach (BodyWithBodyType body in bodyDef.bodies)
+ {
+ if (body.bodyType != null && body.bodyType == this.pawn.story.bodyType.defName)
+ {
+ if (SizedApparelSettings.Debug)
+ Log.Message("[SizedApparel] Apply BodyDef: matched BodyTyped Body for " + pawn.Name);
+ if (body != null && body.Addons != null)
+ {
+ foreach (var bodyaddon in body.Addons)
+ {
+ if (bodyaddon == null)
+ continue;
+ var a = new SizedApparelBodyPart(pawn, this, bodyaddon.partName, bodyaddon.bodyPartOf, bodyaddon.defaultHediffName, bodyaddon.isBreasts, false, bodyaddon.customPath, bodyaddon.colorType, bodyaddon.mustHaveBone);
+ a.SetDepthOffsets(bodyaddon.depthOffset.south, bodyaddon.depthOffset.north, bodyaddon.depthOffset.east, bodyaddon.depthOffset.west);
+ //a.SetDepthOffsets(bodyaddon.depthOffset);
+ a.SetCenteredTexture(bodyaddon.centeredTexture);
+ bodyAddons.Add(a);
+ }
+ }
+ break;
+ }
+
+ }
+
+ }
+
+ }
+ else
+ {
+ if (SizedApparelSettings.Debug)
+ Log.Message("[SizedApparel] Cannot find BodyDef for " + pawn.def.defName);
+ }
+
+ //bodyPartBreasts = new SizedApparelBodyPart(pawn, this, "Breasts", SizedApparelBodyPartOf.Breasts, "Breasts", true, false, null);
+ //bodyPartBreasts.SetDepthOffsets(0.0113f, 0.001f, 0.0113f, 0.0113f);
+
+ //bodyPartBreasts.SetPositionOffsets(Vector2.one, Vector2.one, Vector2.one, Vector2.one);
+ //bodyPartBreasts.scale = 2f;
+ //Nipple. should I separate from Breats?
+ //bodyPartNipple = new SizedApparelBodyPart(pawn, this, "Nippple", SizedApparelBodyPartOf.Breasts, "Breasts", true, false);
+ //bodyPartBreasts.SetDepthOffsets(0.0114f, 0.000f, 0.0114f, 0.0114f);
+
+ //bodyPartUdder = new SizedApparelBodyPart(pawn, this, "Udder", SizedApparelBodyPartOf.Udder, "UdderBreasts", true, false);
+ //bodyPartUdder.SetDepthOffsets(0.0112f, 0.0005f, 0.0112f, 0.0112f);
+
+ //UdderNipple...?
+ //bodyPartUdder = new SizedApparelBodyPart(p, "Udder", SizedApparelBodyPartOf.Udder, "UdderBreasts", true, false);
+ //bodyPartUdder.SetDepthOffsets(0.0112f, 0.0005f, 0.0112f, 0.0112f);\
+
+ //bodyPartVagina = new SizedApparelBodyPart(pawn, this, "Vagina", SizedApparelBodyPartOf.Vagina, "Vagina", false, false);
+ //bodyPartVagina.SetDepthOffsets(0.0088f, 0.0100f, 0.0088f, 0.0088f);
+
+ //bodyPartAnus = new SizedApparelBodyPart(pawn, this, "Anus", SizedApparelBodyPartOf.Anus, "Anus", false, false);
+ //bodyPartAnus.SetDepthOffsets(0.0093f, 0.0105f, 0.0093f, 0.0093f);
+
+ //bodyPartBelly = new SizedApparelBodyPart(pawn, this, "Belly", SizedApparelBodyPartOf.Belly, "BellyBulge", false, false);
+ //bodyPartBelly.SetDepthOffsets(0.0098f, 0.0002f, 0.0098f, 0.0098f);
+
+ //bodyPartPubicHair = new SizedApparelBodyPart(pawn, this, "PubicHair", SizedApparelBodyPartOf.PubicHair, "Default", false, false, null, ColorType.Hair);
+ //bodyPartPubicHair.SetDepthOffsets(0.0099f, 0.0099f, 0.0089f, 0.0089f);
+ }
+
+ public void ResetBodyAddonBoneLink()
+ {
+ string s;
+ foreach(var a in bodyAddons)
+ {
+ s = a.bone?.name;
+ if (s == null)
+ continue;
+ a.SetBone(skeleton.FindBone(s));
+ }
+ }
+
+ public override void Initialize(CompProperties props)
+ {
+ base.Initialize(props);
+ this.pawn = this.parent as Pawn;
+
+
+ }
+
+ public override void PostDeSpawn(Map map)
+ {
+ base.PostDeSpawn(map);
+ }
+
+ public override void PostSpawnSetup(bool respawningAfterLoad)
+ {
+ base.PostSpawnSetup(respawningAfterLoad);
+
+ UpdateRaceSettingData(); // include race Setting
+ InitSkeleton();
+ InitBodyAddons();
+ }
+
+
+ public override void PostExposeData()
+ {
+ base.PostExposeData();
+ Scribe_Values.Look(ref customPose, "customPose"); // save pawn's custom pose. Each bodyparts will not saved.
+ Scribe_Defs.Look(ref pubicHairDef, "PubicHairDef");
+ if (pubicHairDef == null)
+ {
+ pubicHairDef = SizedApparelUtility.GetRandomPubicHair();
+ }
+
+ //Scribe_Values.Look<>(); //TODO: save pubic hair data
+ }
+
+
+
+
+ /*
+ public override void CompTick()
+ {
+ if (PrePositionCache)
+ {
+
+ }
+ base.CompTick();
+ }*/
+ /*
+ public override void CompTickRare()
+ {
+ base.CompTickRare();
+ }*/
+
+
+
+ float penisAngle = 0;
+ public void SetPenisAngle(float angle)
+ {
+ penisAngle = angle;
+
+ if(this.skeleton != null)
+ {
+ Bone penisBone = skeleton.FindBone("Penis");
+ if (penisBone != null)
+ {
+ //Log.Message("SetPenisAngle : " + angle.ToString());
+ penisBone.SetAngle(angle);
+ }
+ }
+
+
+ bool penisDown = false;
+ if (angle >= 120 && angle <= 250)
+ penisDown = true;
+ foreach (var p in bodyPartPenises)
+ {
+ if (penisDown)
+ {
+ p.SetCustomPose("PenisDown");
+ }
+ else
+ {
+ p.SetCustomPose(null);
+ }
+ }
+ }
+ //do not call this in character creation from new game.
+ public void SetBreastJiggle(bool jiggle, int cooltime = 5, bool checkApparelForCanPose = false)
+ {
+ //SetJiggle has cooltime.
+
+
+ bool flag1 = true;
+
+ //should set apparels pose?
+ //Use First BodyAddon which is partof Breasts
+ foreach(var a in GetSizedApparelBodyParts(SizedApparelBodyPartOf.Breasts))
+ {
+ if (flag1)
+ {
+ if (Find.TickManager.TicksGame < a.lastPoseTick + cooltime)
+ return;
+ flag1 = false;
+ }
+
+
+ if (jiggle)
+ {
+ bool flag2 = true;
+ if (flag2 && checkApparelForCanPose)
+ {
+ if (!a.CheckCanPose("JiggleUp", true, false, true, true, false))
+ return;
+ flag2 = false;
+ }
+
+ //may need to check apparels for aply pose
+ //bodyPartBreasts.CheckCanPose("JiggleUp",)
+ a.SetCustomPose("JiggleUp");
+ }
+ else
+ {
+ //SetPoseFromPoseSet(null);
+ a.SetCustomPose(null);
+ }
+ }
+
+
+ }
+
+ string[] testPose = { null, "JiggleUp", "JiggleCenter" };
+ string[] testPose2 = { null, "PenisDown" };
+
+ public void UpdateTickAnim(Vector3 rootLoc, float angle) // call this in DrawPawnBody <- only called when it rendered
+ {
+ if (ForceBlockTickAnimation)// prevent breasts jiggle from other pose
+ return;
+
+ if (skeleton == null)
+ return;
+
+ if (Find.CameraDriver == null)
+ return;
+
+ //do not calculate physics camera is far
+ if (Find.CameraDriver.CurrentZoom >= CameraZoomRange.Furthest)
+ return;
+ //int IdTick = parent.thingIDNumber * 20; //hint from yayo animation mod
+
+ if (!SizedApparelUtility.CanApplySizedApparel(pawn))
+ return;
+
+
+ if (SizedApparelSettings.breastsPhysics || ForceUpdateTickAnimation)//SizedApparelSettings.autoJiggleBreasts
+ {
+
+ int tick;
+ if (this.preTickCache != null)
+ tick = Find.TickManager.TicksGame - this.preTickCache.Value;
+ else
+ tick = Find.TickManager.TicksGame;
+
+ //if tick is not updated, don't update animation.
+ if (tick == 0)
+ return;
+
+ Vector3 velocity;
+ if (this.prePositionCache != null)
+ velocity = (rootLoc - this.prePositionCache.Value);// /tick
+ else
+ velocity = Vector3.zero;
+
+ float rotation;
+
+ if (this.preAngleCache != null)
+ rotation = angle - this.preAngleCache.Value;
+ else
+ rotation = 0;
+
+ float rotAcc = rotation - preRotation;
+
+
+ //Log.Message(velocity.ToString() + " , " + preVelocity.ToString());
+ //UnityEngine's vector.normalize is safe for zero vector
+ //(Vector3.Dot(velocity.normalized, preVelocity.normalized)) < 0.2f
+
+ float dotV = Vector3.Dot(velocity.normalized, preVelocity.normalized);
+ float velocityOffset = (velocity - preVelocity).magnitude;
+
+ //Log.Message(pawn.ToString());
+ //Log.Message("rotAcc : " + rotAcc.ToString());
+ //Log.Message("Velocity.x : " + velocity.x.ToString());
+ //Log.Message("Velocity.z : " + velocity.z.ToString());
+ //Log.Message("dotV : " + dotV.ToString());
+ //Log.Message("velocityOffset : " + velocityOffset.ToString());
+ //&& dotV > 0.4f
+ if (((preVelocity != Vector3.zero && velocityOffset >= 0.02))|| Mathf.Abs(rotAcc) > 0.5) //(dotV == 0 ? 0:1), Mathf.Abs(dotV) // || Mathf.Abs(rotation) > 20
+ {
+ //tickCache.Add("BreastsJiggleUp", Find.TickManager.TicksGame);
+ SetBreastJiggle(true,10,true);
+
+ }
+ else
+ {
+ SetBreastJiggle(false,10, false);
+ }
+
+
+ //cache pre data
+
+ this.prePositionCache = rootLoc;
+ this.preAngleCache = angle;
+ this.preRotation = rotation;
+ this.preTickCache = Find.TickManager.TicksGame;
+ this.preVelocity = velocity;
+
+
+
+
+ }
+
+ //SetPoseFromPoseSet(testPose2.RandomElement());
+ }
+
+
+ public bool isApparelGraphicRecordChanged()
+ {
+ if (pawn == null)
+ return false;
+
+ var apparelGraphics = pawn.Drawer?.renderer?.graphics?.apparelGraphics;
+ if (apparelGraphics == null)
+ return false;
+
+ //return false; //since 1.3 broken. force to return false;
+ if (!apparelGraphics.SequenceEqual(cachedApparelGraphicRecord))
+ {
+ if (SizedApparelSettings.Debug)
+ Log.Message("[SizedApparel]:" + pawn + "'s apparel Record Changed! need to updating comp");
+ return true;
+ }
+
+
+ return false;
+ }
+
+ public void DrawAllBodyParts(Vector3 rootLoc, float angle, Rot4 facing, RotDrawMode bodyDrawType, PawnRenderFlags flags, Pawn ___pawn, Mesh bodyMesh)
+ {
+ if (this.isDrawAge && (!flags.FlagSet(PawnRenderFlags.Clothes) || !this.hasUnsupportedApparel || SizedApparelUtility.isPawnNaked(___pawn))) //TODO : Move it to CanDraw
+ {
+ if (bodyDrawType != RotDrawMode.Dessicated && SizedApparelSettings.drawVagina && SizedApparelUtility.CanDrawVagina(___pawn, flags))
+ {
+ //if (this.bodyPartVagina != null)
+ // this.bodyPartVagina.DrawBodyPart(rootLoc, angle, facing, bodyDrawType, flags, bodyMesh);
+ foreach (var b in GetSizedApparelBodyParts(SizedApparelBodyPartOf.Vagina))
+ {
+ b.DrawBodyPart(rootLoc, angle, facing, bodyDrawType, flags, bodyMesh);
+ }
+ }
+ if (bodyDrawType != RotDrawMode.Dessicated && SizedApparelSettings.drawAnus && SizedApparelUtility.CanDrawAnus(___pawn, flags))
+ {
+ //if (this.bodyPartAnus != null)
+ // this.bodyPartAnus.DrawBodyPart(rootLoc, angle, facing, bodyDrawType, flags, bodyMesh);
+ foreach (var b in GetSizedApparelBodyParts(SizedApparelBodyPartOf.Anus))
+ {
+ b.DrawBodyPart(rootLoc, angle, facing, bodyDrawType, flags, bodyMesh);
+ }
+ }
+
+ if (bodyDrawType != RotDrawMode.Dessicated && SizedApparelSettings.drawBelly && SizedApparelUtility.CanDrawBelly(___pawn, flags))
+ {
+ //if (this.bodyPartBelly != null)
+ // this.bodyPartBelly.DrawBodyPart(rootLoc, angle, facing, bodyDrawType, flags, bodyMesh);
+ foreach (var b in GetSizedApparelBodyParts(SizedApparelBodyPartOf.Belly))
+ {
+ b.DrawBodyPart(rootLoc, angle, facing, bodyDrawType, flags, bodyMesh);
+ }
+ }
+
+ //Draw Pubic Hair
+ if (bodyDrawType != RotDrawMode.Dessicated && SizedApparelSettings.drawPubicHair && SizedApparelUtility.CanDrawPubicHair(___pawn, flags))
+ {
+ if (this.bodyPartPubicHair != null)
+ this.bodyPartPubicHair.DrawBodyPart(rootLoc, angle, facing, bodyDrawType, flags, bodyMesh);
+ foreach (var b in GetSizedApparelBodyParts(SizedApparelBodyPartOf.PubicHair))
+ {
+ b.DrawBodyPart(rootLoc, angle, facing, bodyDrawType, flags, bodyMesh);
+ }
+ }
+
+
+ if (bodyDrawType != RotDrawMode.Dessicated && SizedApparelSettings.drawUdder && SizedApparelUtility.CanDrawUdder(___pawn, flags))
+ {
+ //if (this.bodyPartUdder != null)
+ // this.bodyPartUdder.DrawBodyPart(rootLoc, angle, facing, bodyDrawType, flags, bodyMesh);
+ foreach (var b in GetSizedApparelBodyParts(SizedApparelBodyPartOf.Udder))
+ {
+ b.DrawBodyPart(rootLoc, angle, facing, bodyDrawType, flags, bodyMesh);
+ }
+
+ }
+ if (bodyDrawType != RotDrawMode.Dessicated && SizedApparelSettings.drawBreasts && SizedApparelUtility.CanDrawBreasts(___pawn, flags) && (SizedApparelSettings.drawSizedApparelBreastsOnlyWorn ? !SizedApparelUtility.isPawnNaked(___pawn, flags) : true))
+ {
+ //if (this.bodyPartBreasts != null)
+ // this.bodyPartBreasts.DrawBodyPart(rootLoc, angle, facing, bodyDrawType, flags, bodyMesh);
+ foreach (var b in GetSizedApparelBodyParts(SizedApparelBodyPartOf.Breasts))
+ {
+ b.DrawBodyPart(rootLoc, angle, facing, bodyDrawType, flags, bodyMesh);
+ }
+ }
+
+ if (bodyDrawType != RotDrawMode.Dessicated && SizedApparelSettings.drawPenis && SizedApparelUtility.CanDrawPenis(___pawn, flags, true))
+ {
+
+ if (SizedApparelSettings.hideBallOfFuta ? !Genital_Helper.is_futa(___pawn) : true)
+ {
+ /*
+ foreach (SizedApparelBodyPart b in this.bodyPartBalls)
+ {
+ b.DrawBodyPart(rootLoc, angle, facing, bodyDrawType, flags, bodyMesh);
+ }*/
+ foreach (var b in GetSizedApparelBodyParts(SizedApparelBodyPartOf.Balls))
+ {
+ b.DrawBodyPart(rootLoc, angle, facing, bodyDrawType, flags, bodyMesh);
+ }
+ }
+ /*
+ foreach (SizedApparelBodyPart p in this.bodyPartPenises)
+ {
+ p.DrawBodyPart(rootLoc, angle, facing, bodyDrawType, flags, bodyMesh);
+ }*/
+ foreach (var b in GetSizedApparelBodyParts(SizedApparelBodyPartOf.Penis))
+ {
+ b.DrawBodyPart(rootLoc, angle, facing, bodyDrawType, flags, bodyMesh);
+ }
+
+ }//Draw BodyParts
+
+ //Draw Modular Apparel Parts... TODO...? Is it passible?
+ if (flags.FlagSet(PawnRenderFlags.Clothes))
+ {
+
+ }
+
+
+
+
+ }
+
+ }
+
+
+ //not working
+ public override void PostPostMake()
+ {
+ /*
+ Pawn pawn;
+ try
+ {
+ pawn = (Pawn)parent;
+ if (pawn != null)
+ {
+ if (!pawn.RaceProps.Humanlike)
+ return;
+ pawn.Drawer.renderer.graphics.ResolveAllGraphics();
+ if (SizedApparelSettings.Debug)
+ Log.Message("[SizedApparels] Component Inint And Resolve all Graphics for "+ pawn.Name);
+ }
+ }
+ catch
+ {
+
+ }
+ */
+ }
+ public void ClearHediffs()
+ {
+ breastHediff = null;
+ vaginaHediff = null;
+ if(penisHediffs != null)
+ penisHediffs.Clear();
+ anusHediff = null;
+ udderHediff = null;
+ }
+ public void ClearBreastCacheValue()
+ {
+ breastHediff = null;
+ breastSeverity = -1;
+ BreastSeverityCache = 0;
+ }
+ public void ClearPenisCacheValue()
+ {
+ //TODO
+ }
+ public void ClearCanDraw()
+ {
+ canDrawBreasts = false;
+ canDrawPenis = false;
+ canDrawTorsoParts = false;
+ canDrawVaginaAndAnus = false;
+ }
+ public void ClearGraphics(bool clearBreasts = true)
+ {
+ //Since Injection of base body is now in Matarial. no need to keep
+ graphicSourceNaked = null;
+ graphicSourceFurCovered = null;
+ graphicSourceRotten = null;
+
+ hasGraphicUpdatedBefore = false;
+ graphicbaseBodyNaked = null;
+ graphicbaseBodyRotten = null;
+ graphicbaseBodyFurCovered = null;
+
+ return;
+ //Clear BodyParts
+ if (clearBreasts && bodyPartBreasts!= null)
+ bodyPartBreasts.Clear();
+ if(bodyPartAnus != null)
+ bodyPartAnus.Clear();
+ if (bodyPartBelly != null)
+ bodyPartBelly.Clear();
+ if (bodyPartVagina != null)
+ bodyPartVagina.Clear();
+ if (bodyPartPubicHair != null)
+ bodyPartPubicHair.Clear();
+
+ foreach(var a in bodyAddons)
+ {
+ a.Clear();
+ }
+
+ }
+ public void ClearAll(bool clearGraphics = true)
+ {
+ ClearBreastCacheValue();
+ if(clearGraphics)
+ ClearGraphics();
+ ClearHediffs();
+ ClearCanDraw();
+ hasUnsupportedApparel = false;
+ hasUpdateBefore = false;
+ hasUpdateBeforeSuccess = false;
+ needToCheckApparelGraphicRecords = false;
+ }
+
+ public void SetDirty(bool clearPawnGraphicSet = false, bool dirtyHediff = true, bool dirtyApparel = true, bool dirtySkeleton = false, bool dirtyBodyAddons = false)
+ {
+ this.isDirty = true;
+ this.isHediffDirty = dirtyHediff;
+ this.isApparelDirty = dirtyApparel;
+ this.isSkeletonDirty = dirtySkeleton;
+ this.isBodyAddonDirty = dirtyBodyAddons;
+ if (clearPawnGraphicSet)
+ {
+ if (pawn == null)
+ return;
+ if (pawn.Drawer == null)
+ return;
+ if (pawn.Drawer.renderer == null)
+ return;
+ pawn.Drawer.renderer.graphics.ClearCache();
+ }
+
+ }
+ public void UpdateRaceSettingData()
+ {
+ if (pawn == null)
+ return;
+
+ var loc_raceSetting = SizedApparelSettings.alienRaceSettings.FirstOrDefault((AlienRaceSetting s) => s.raceName == pawn.def.defName);
+ if (loc_raceSetting == null)
+ return;
+ raceSetting = loc_raceSetting;
+ }
+
+ public void CheckAgeChanged()
+ {
+ if (pawn == null)
+ return;
+ if (pawn.ageTracker == null)
+ return;
+
+ //TODO. Cleanup
+ UpdateRaceSettingData();
+ if (raceSetting == null)
+ return;
+
+ if (raceSetting.drawMinAge < 0 || pawn.ageTracker.AgeBiologicalYearsFloat >= raceSetting.drawMinAge)
+ isDrawAge = true;
+ else
+ isDrawAge = false;
+ }
+
+ public void FindAndApplyBodyGraphic(Pawn pawn, Graphic sourceGraphic, ref Graphic targetGraphicBaseBody, ref Graphic cachedSourceGraphic, string debugName)
+ {
+ const string baseBodyString = "_BaseBody";
+ string baseBodyStringWithSex;
+
+ if (SizedApparelSettings.useGenderSpecificTexture)
+ {
+ if (pawn.gender == Gender.Female)
+ {
+ baseBodyStringWithSex = baseBodyString + "F";
+ }
+ else if (pawn.gender == Gender.Male)
+ {
+ baseBodyStringWithSex = baseBodyString + "M";
+ }
+ else
+ {
+ baseBodyStringWithSex = baseBodyString; // + "N" //Does it need to add N?
+ }
+ }
+ else
+ baseBodyStringWithSex = baseBodyString;
+ string targetGraphicPath = null;
+ if (sourceGraphic != null)
+ {
+ //path = path.Insert(Math.Max(path.LastIndexOf('/'), 0), "/CustomPose/"+ customPose);
+ if (cachedSourceGraphic == null)
+ cachedSourceGraphic = sourceGraphic;
+ targetGraphicPath = cachedSourceGraphic.path;
+
+ if (customPose != null)
+ targetGraphicPath = targetGraphicPath.Insert(Math.Max(targetGraphicPath.LastIndexOf('/'), 0), "/CustomPose/" + customPose);
+
+ if (!targetGraphicPath.Contains(baseBodyString))
+ {
+ if (SizedApparelSettings.useGenderSpecificTexture && pawn.gender != Gender.None)
+ {
+ if (targetGraphicBaseBody == null)
+ {
+ if (ContentFinder.Get((targetGraphicPath + baseBodyStringWithSex + "_south"), false) != null)
+ {
+ //cachedSourceGraphic = sourceGraphic;
+ Shader shader = sourceGraphic.Shader;
+ //if (!ShaderUtility.SupportsMaskTex(shader))
+ // shader = ShaderDatabase.CutoutSkinOverlay;
+ targetGraphicBaseBody = GraphicDatabase.Get(targetGraphicPath + baseBodyStringWithSex, shader, sourceGraphic.drawSize, sourceGraphic.color, sourceGraphic.colorTwo, sourceGraphic.data);
+ //sourceGraphic = targetGraphicBaseBody;
+ }
+ else if (customPose != null)
+ {
+ targetGraphicPath = sourceGraphic.path;
+ if (ContentFinder.Get((targetGraphicPath + baseBodyStringWithSex + "_south"), false) != null)
+ {
+ //cachedSourceGraphic = sourceGraphic;
+ Shader shader = sourceGraphic.Shader;
+ //if (!ShaderUtility.SupportsMaskTex(shader))
+ // shader = ShaderDatabase.CutoutSkinOverlay;
+ targetGraphicBaseBody = GraphicDatabase.Get(targetGraphicPath + baseBodyStringWithSex, shader, sourceGraphic.drawSize, sourceGraphic.color, sourceGraphic.colorTwo, sourceGraphic.data);
+ //sourceGraphic = targetGraphicBaseBody;
+ }
+ else
+ {
+ if (SizedApparelSettings.Debug)
+ Log.Warning("[SizedApparel] Missing BaseBodyTexture for "+ debugName + " Graphic: " + targetGraphicPath + baseBodyStringWithSex + "_south");
+ }
+ }
+ }
+ }
+ if (targetGraphicBaseBody == null)
+ {
+ if (ContentFinder.Get((targetGraphicPath + baseBodyString + "_south"), false) != null)
+ {
+ // cachedSourceGraphic = sourceGraphic;
+ Shader shader = sourceGraphic.Shader;
+ //if (!ShaderUtility.SupportsMaskTex(shader))
+ // shader = ShaderDatabase.CutoutSkinOverlay;
+ targetGraphicBaseBody = GraphicDatabase.Get(targetGraphicPath + baseBodyString, shader, sourceGraphic.drawSize, sourceGraphic.color, sourceGraphic.colorTwo, sourceGraphic.data);
+ //sourceGraphic = targetGraphicBaseBody;
+ }
+ else if (customPose != null)
+ {
+ targetGraphicPath = sourceGraphic.path;
+ if (ContentFinder.Get((targetGraphicPath + baseBodyString + "_south"), false) != null)
+ {
+ //cachedSourceGraphic = sourceGraphic;
+ Shader shader = sourceGraphic.Shader;
+ //if (!ShaderUtility.SupportsMaskTex(shader))
+ // shader = ShaderDatabase.CutoutSkinOverlay;
+ targetGraphicBaseBody = GraphicDatabase.Get(targetGraphicPath + baseBodyString, shader, sourceGraphic.drawSize, sourceGraphic.color, sourceGraphic.colorTwo, sourceGraphic.data);
+ //sourceGraphic = targetGraphicBaseBody;
+ }
+ else
+ {
+ if (SizedApparelSettings.Debug)
+ Log.Warning("[SizedApparel] Missing BaseBodyTexture for " + debugName + " Graphic: " + targetGraphicPath + baseBodyString + "_south");
+ }
+
+ }
+ }
+
+ }
+ else
+ targetGraphicBaseBody = sourceGraphic;
+
+ }
+
+ }
+
+ public void Update(bool cache = true, bool fromGraphicRecord = true, bool updateGraphics = true, bool CheckApparel = true)
+ {
+ if (cache)
+ recentClothFlag = CheckApparel;
+
+
+
+ isDirty = false;
+ bool flag = fromGraphicRecord;
+ needToCheckApparelGraphicRecords = false;
+ //flag = false; //TODO:fromGraphicRecord is forced not to do for a while. it will update later
+
+
+
+ UpdateRaceSettingData();
+
+
+
+ if (!hasUpdateBefore)
+ {
+ InitSkeleton();
+ InitBodyAddons();
+ hasUpdateBefore = true;
+ }
+ else
+ {
+ //check is bodytype changed
+ if(cachedBodytype != pawn.story?.bodyType?.defName)
+ {
+ isSkeletonDirty = true;
+ }
+ if (isSkeletonDirty)
+ {
+ InitSkeleton();
+
+ if (isBodyAddonDirty)
+ InitBodyAddons();
+ else
+ ResetBodyAddonBoneLink();
+ }
+ else
+ {
+ if (isBodyAddonDirty)
+ InitBodyAddons();
+ }
+ }
+
+ if (skeleton == null)
+ {
+ if (Find.CurrentMap != null)
+ return;
+ }
+
+
+ if (!SizedApparelUtility.CanApplySizedApparel(pawn))
+ return;
+
+
+ if (pubicHairDef == null)
+ {
+ pubicHairDef = SizedApparelUtility.GetRandomPubicHair();
+ }
+
+
+ if (SizedApparelSettings.Debug)
+ Log.Message("[SizedApparel] Updating Component of " + pawn.Name);
+ if (updateGraphics)
+ {
+ ClearGraphics();
+ //ClearHediffs();
+ }
+
+
+
+ //float breastSeverityCapped = 1000;
+ string bodyTypeDefName = null;
+ if (pawn.story != null)
+ bodyTypeDefName = pawn.story.bodyType?.defName;
+ float bellySeverity = 0;
+
+ if (isHediffDirty) //Update Hediff Data
+ {
+ ClearHediffs();
+
+
+ if(SizedApparelSettings.drawPenis || SizedApparelSettings.drawVagina || SizedApparelSettings.drawAnus)
+ {
+ BodyPartRecord genitalPart = Genital_Helper.get_genitalsBPR(pawn);
+ if (genitalPart != null)
+ {
+ var genitalList = Genital_Helper.get_PartsHediffList(pawn, genitalPart);
+ if (!genitalList.NullOrEmpty())
+ {
+ if (SizedApparelSettings.Debug)
+ {
+ foreach (var g in genitalList)
+ {
+ Log.Message(" [SizedApparel] " + pawn.Name + "has hediff in genital (" + g.def.defName + ")");
+ }
+ }
+
+ //penisHediffs = genitalList.FindAll((Hediff h) => SizedApparelUtility.isPenis(h.def.defName));
+ penisHediffs = genitalList.FindAll((Hediff h) => Genital_Helper.is_penis(h));
+ //vaginaHediff = genitalList.FirstOrDefault((Hediff h) => SizedApparelUtility.isVagina(h.def.defName));
+ vaginaHediff = genitalList.FirstOrDefault((Hediff h) => Genital_Helper.is_vagina(h));
+
+ }
+ }
+ }
+
+ if (SizedApparelSettings.drawBelly)
+ {
+ //EggImplement as Pregnant
+ //need to Optimize... TODO...
+ List pregnancies = pawn.health?.hediffSet?.hediffs?.FindAll((Hediff h) => SizedApparelUtility.isPragnencyHediff(h) || SizedApparelUtility.isRJWEggHediff(h));//pregnancy and pregnant. has some issue with "pregnancy mood"
+ if (!pregnancies.NullOrEmpty())
+ {
+ foreach (Hediff h in pregnancies)
+ {
+ //Set Labor Belly as Big Belly.
+
+ //Code for 1.4
+ /*
+ if (h.def == HediffDefOf.PregnancyLabor || h.def == HediffDefOf.PregnancyLaborPushing)
+ bellySeverity = Math.Max(bellySeverity, 1f);
+ else
+ bellySeverity = Math.Max(bellySeverity, h.Severity);
+ */
+ bellySeverity = Math.Max(bellySeverity, h.Severity);
+ }
+ }
+
+ //Licentia Lab Hediff
+ if (SizedApparelPatch.LicentiaActive)
+ {
+ Hediff cumflation = pawn.health?.hediffSet?.GetFirstHediffOfDef(HediffDef.Named("Cumflation"));
+ Hediff cumstuffed = pawn.health?.hediffSet?.GetFirstHediffOfDef(HediffDef.Named("Cumstuffed"));
+ bellySeverity += cumflation != null ? cumflation.Severity : 0;
+ bellySeverity += cumstuffed != null ? cumstuffed.Severity : 0;
+ }
+
+
+ }
+
+
+
+ }
+
+ CheckAgeChanged();
+
+ if (SizedApparelSettings.drawBreasts)
+ {
+ SizedApparelUtility.GetBreastSeverity(pawn, out breastSeverity, out breastHediff);
+
+ }
+
+ if (breastHediff != null)
+ {
+
+ //get nipple color from Menstruation.
+ if (SizedApparelPatch.MenstruationActive)
+ {
+ nippleColor = Patch_Menstruation.GetNippleColor(breastHediff);
+ }
+
+
+
+ if (pawn.gender == Gender.Male && !SizedApparelSettings.ApplyApparelPatchForMale)
+ {
+ CheckApparel = false;
+ }
+
+
+ if (CheckApparel || this.isApparelDirty)
+ {
+ hasUnsupportedApparel = SizedApparelUtility.hasUnSupportedApparelFromWornData(pawn, breastSeverity, breastHediff, true, flag);
+
+ }
+ else
+ {
+ hasUnsupportedApparel = false;
+
+ }
+ //float validBreastTextureSeverity = SizedApparelUtility.GetBreastSeverityValidTextures(pawn, breastHediff);
+ if (SizedApparelSettings.useBreastSizeCapForApparels) // && hasUnsupportedApparel
+ {
+ BreastSeverityCache = Math.Min(BreastSeverityCache, breastSeverity);
+
+ }
+ else
+ {
+ BreastSeverityCache = 1000;
+ }
+ //if (SizedApparelSettings.useBreastSizeCapForApparels) //SizedApparelSettings.useBreastSizeCapForApparels //wip
+ // breastSeverityCapped = Math.Min(BreastSeverityCache, breastSeverityCapped);
+
+
+ //float validBreastTextureSeverity = SizedApparelUtility.GetBreastSeverityValidTextures(pawn, breastHediff);
+
+ //breast cache forApparel brests Check. This ignore variation!
+ //SizedApparelMod.CheckAndLoadAlienRaces();
+
+ var key = new SizedApparelsDatabase.BodyPartDatabaseKey(pawn.def.defName, pawn.story?.bodyType?.defName, breastHediff.def.defName, "Breasts", pawn.gender ,SizedApparelUtility.BreastSeverityInt(breastHediff.Severity));
+ var raceSetting = SizedApparelSettings.alienRaceSettings.FirstOrDefault((AlienRaceSetting s) => s.raceName == key.raceName);
+
+ //TODO? Remove ValidBreastsTextureCheck...
+ float validBreastTextureSeverity = SizedApparelUtility.BreastSizeIndexToSeverity(SizedApparelsDatabase.GetSupportedBodyPartPath(key,true,"Breasts","Breasts").size);
+ //if (validBreastTextureSeverity < -5 && SizedApparelSettings.alienRaceSettings.settings[key.raceName].asHumanlike)//old: SizedApparelSettings.UnsupportedRaceToUseHumanlike
+ // validBreastTextureSeverity = SizedApparelUtility.GetBreastSeverityValidTextures(pawn, breastHediff, "Humanlike");
+ BreastSeverityCache = Math.Min(BreastSeverityCache, validBreastTextureSeverity);
+ if (SizedApparelSettings.Debug)
+ Log.Message("[Sized Apparel] cached Severity : " + BreastSeverityCache);
+ }
+ //penisHediff = Genital_Helper.get_PartsHediffList(pawn, Genital_Helper.get_genitalsBPR(pawn)).FirstOrDefault((Hediff h) => h.def.defName.ToLower().Contains("penis"));
+
+ //since rjw race support's part name are too variation, not handling it.
+
+
+ var anusList = Genital_Helper.get_PartsHediffList(pawn, Genital_Helper.get_anusBPR(pawn));
+ if(!anusList.NullOrEmpty())
+ anusHediff = anusList.FirstOrDefault((Hediff h) => h.def.defName.ToLower().Contains("anus"));
+ //udderHediff = Genital_Helper.get_PartsHediffList(pawn, pawn.RaceProps.body.AllParts.Find((BodyPartRecord bpr) => bpr.def.defName == "Torso")).FirstOrDefault((Hediff h) => h.def.defName.ToLower().Contains("anus")); //not yet supported
+
+ udderHediff = pawn.health?.hediffSet?.hediffs?.FirstOrDefault((Hediff h) => h.def.defName.ToLower().Contains("udder"));
+
+ var pawnRenderer = pawn.Drawer?.renderer?.graphics;
+
+ if (updateGraphics)
+ {
+
+ if (pawnRenderer != null)
+ {
+ //pawnRenderer.ResolveAllGraphics();
+
+
+ //TODO Use Function To Make Clear Code
+ /*
+ FindAndApplyBodyGraphic(pawn, pawnRenderer.nakedGraphic, ref graphicbaseBodyNaked, ref graphicSourceNaked,"Naked");
+ FindAndApplyBodyGraphic(pawn, pawnRenderer.rottingGraphic, ref graphicbaseBodyRotten, ref graphicSourceRotten, "Rotting");
+ FindAndApplyBodyGraphic(pawn, pawnRenderer.nakedGraphic, ref graphicbaseBodyFurCovered, ref graphicSourceFurCovered, "FurCuvered");
+ */
+ const string baseBodyString = "_BaseBody";
+ string baseBodyStringWithSex;
+
+ if (SizedApparelSettings.useGenderSpecificTexture)
+ {
+ if (pawn.gender == Gender.Female)
+ {
+ baseBodyStringWithSex = baseBodyString + "F";
+ }
+ else if (pawn.gender == Gender.Male)
+ {
+ baseBodyStringWithSex = baseBodyString + "M";
+ }
+ else
+ {
+ baseBodyStringWithSex = baseBodyString; // + "N" //Does it need to add N?
+ }
+ }
+ else
+ baseBodyStringWithSex = baseBodyString;
+
+ string nakedGraphicPath = null;
+ if (pawnRenderer.nakedGraphic != null)
+ {
+ //path = path.Insert(Math.Max(path.LastIndexOf('/'), 0), "/CustomPose/"+ customPose);
+ if(graphicSourceNaked == null)
+ graphicSourceNaked = pawnRenderer.nakedGraphic;
+ nakedGraphicPath = graphicSourceNaked.path;
+
+ if (customPose != null)
+ nakedGraphicPath = nakedGraphicPath.Insert(Math.Max(nakedGraphicPath.LastIndexOf('/'), 0), "/CustomPose/" + customPose);
+
+ if (!nakedGraphicPath.Contains(baseBodyString))
+ {
+ if (SizedApparelSettings.useGenderSpecificTexture & pawn.gender != Gender.None)
+ {
+ if (graphicbaseBodyNaked == null)
+ {
+ if (ContentFinder.Get((nakedGraphicPath + baseBodyStringWithSex + "_south"), false) != null)
+ {
+ //graphicSourceNaked = pawnRenderer.nakedGraphic;
+ Shader shader = pawnRenderer.nakedGraphic.Shader;
+ //if (!ShaderUtility.SupportsMaskTex(shader))
+ // shader = ShaderDatabase.CutoutSkinOverlay;
+ graphicbaseBodyNaked = GraphicDatabase.Get(nakedGraphicPath + baseBodyStringWithSex, shader, pawnRenderer.nakedGraphic.drawSize, pawnRenderer.nakedGraphic.color, pawnRenderer.nakedGraphic.colorTwo, pawnRenderer.nakedGraphic.data);
+ //pawnRenderer.nakedGraphic = graphicbaseBodyNaked;
+ }
+ else if (customPose != null)
+ {
+ nakedGraphicPath = pawnRenderer.nakedGraphic.path;
+ if (ContentFinder.Get((nakedGraphicPath + baseBodyStringWithSex + "_south"), false) != null)
+ {
+ //graphicSourceNaked = pawnRenderer.nakedGraphic;
+ Shader shader = pawnRenderer.nakedGraphic.Shader;
+ //if (!ShaderUtility.SupportsMaskTex(shader))
+ // shader = ShaderDatabase.CutoutSkinOverlay;
+ graphicbaseBodyNaked = GraphicDatabase.Get(nakedGraphicPath + baseBodyStringWithSex, shader, pawnRenderer.nakedGraphic.drawSize, pawnRenderer.nakedGraphic.color, pawnRenderer.nakedGraphic.colorTwo, pawnRenderer.nakedGraphic.data);
+ //pawnRenderer.nakedGraphic = graphicbaseBodyNaked;
+ }
+ else
+ {
+ if (SizedApparelSettings.Debug)
+ Log.Warning("[SizedApparel] Missing BaseBodyTexture for naked Graphic: " + nakedGraphicPath + baseBodyStringWithSex + "_south");
+ }
+ }
+ }
+ }
+ if (graphicbaseBodyNaked == null)
+ {
+ if (ContentFinder.Get((nakedGraphicPath + baseBodyString + "_south"), false) != null)
+ {
+ // graphicSourceNaked = pawnRenderer.nakedGraphic;
+ Shader shader = pawnRenderer.nakedGraphic.Shader;
+ //if (!ShaderUtility.SupportsMaskTex(shader))
+ // shader = ShaderDatabase.CutoutSkinOverlay;
+ graphicbaseBodyNaked = GraphicDatabase.Get(nakedGraphicPath + baseBodyString, shader, pawnRenderer.nakedGraphic.drawSize, pawnRenderer.nakedGraphic.color, pawnRenderer.nakedGraphic.colorTwo, pawnRenderer.nakedGraphic.data);
+ //pawnRenderer.nakedGraphic = graphicbaseBodyNaked;
+ }
+ else if (customPose != null)
+ {
+ nakedGraphicPath = pawnRenderer.nakedGraphic.path;
+ if (ContentFinder.Get((nakedGraphicPath + baseBodyString + "_south"), false) != null)
+ {
+ //graphicSourceNaked = pawnRenderer.nakedGraphic;
+ Shader shader = pawnRenderer.nakedGraphic.Shader;
+ //if (!ShaderUtility.SupportsMaskTex(shader))
+ // shader = ShaderDatabase.CutoutSkinOverlay;
+ graphicbaseBodyNaked = GraphicDatabase.Get(nakedGraphicPath + baseBodyString, shader, pawnRenderer.nakedGraphic.drawSize, pawnRenderer.nakedGraphic.color, pawnRenderer.nakedGraphic.colorTwo, pawnRenderer.nakedGraphic.data);
+ //pawnRenderer.nakedGraphic = graphicbaseBodyNaked;
+ }
+ else
+ {
+ if (SizedApparelSettings.Debug)
+ Log.Warning("[SizedApparel] Missing BaseBodyTexture for naked Graphic: " + nakedGraphicPath + baseBodyString + "_south");
+ }
+
+ }
+ }
+
+ }
+ else
+ graphicbaseBodyNaked = pawnRenderer.nakedGraphic;
+
+ }
+ //Finding Texture Points
+ if (false && graphicbaseBodyNaked != null)
+ {
+ SizedApparelTexturePointDef PointsDef = DefDatabase.AllDefs.FirstOrDefault((SizedApparelTexturePointDef s) => s.Path == graphicbaseBodyNaked.path);
+ if (SizedApparelSettings.Debug && PointsDef != null)
+ {
+ Log.Message("[SizedApparel] : NakedBaseBody Texture Points Def Found : " + PointsDef.defName);
+ }
+ baseBodyNakedPoints = PointsDef;
+ }
+ else
+ baseBodyNakedPoints = null;
+
+ string rottingGraphicPath = null;
+ if (pawnRenderer.rottingGraphic != null)
+ {
+ if (graphicSourceRotten == null)
+ graphicSourceRotten = pawnRenderer.rottingGraphic;
+ rottingGraphicPath = graphicSourceRotten.path;
+
+ if (customPose != null)
+ rottingGraphicPath = rottingGraphicPath.Insert(Math.Max(rottingGraphicPath.LastIndexOf('/'), 0), "/CustomPose/" + customPose);
+
+ if (!rottingGraphicPath.Contains(baseBodyString))
+ {
+ if (graphicbaseBodyRotten == null)
+ {
+ if (ContentFinder.Get((rottingGraphicPath + baseBodyStringWithSex + "_south"), false) != null)
+ {
+ //graphicSourceRotten = pawnRenderer.rottingGraphic;
+ Shader shader = pawnRenderer.rottingGraphic.Shader;
+ //if (!ShaderUtility.SupportsMaskTex(shader))
+ // shader = ShaderDatabase.CutoutSkinOverlay;
+ graphicbaseBodyRotten = GraphicDatabase.Get(rottingGraphicPath + baseBodyStringWithSex, shader, pawnRenderer.rottingGraphic.drawSize, pawnRenderer.rottingGraphic.color, pawnRenderer.rottingGraphic.colorTwo, pawnRenderer.rottingGraphic.data);
+ //pawnRenderer.rottingGraphic = graphicbaseBodyRotten;
+ }
+ else if (customPose != null)
+ {
+ rottingGraphicPath = pawnRenderer.rottingGraphic.path;
+ if (ContentFinder.Get((rottingGraphicPath + baseBodyStringWithSex + "_south"), false) != null)
+ {
+ graphicSourceRotten = pawnRenderer.rottingGraphic;
+ Shader shader = pawnRenderer.rottingGraphic.Shader;
+ //if (!ShaderUtility.SupportsMaskTex(shader))
+ // shader = ShaderDatabase.CutoutSkinOverlay;
+ graphicbaseBodyRotten = GraphicDatabase.Get(rottingGraphicPath + baseBodyStringWithSex, shader, pawnRenderer.rottingGraphic.drawSize, pawnRenderer.rottingGraphic.color, pawnRenderer.rottingGraphic.colorTwo, pawnRenderer.rottingGraphic.data);
+ //pawnRenderer.rottingGraphic = graphicbaseBodyRotten;
+ }
+ else
+ {
+ if (SizedApparelSettings.Debug)
+ Log.Warning("[SizedApparel] Missing BaseBodyTexture for rotting Graphic: " + rottingGraphicPath + baseBodyStringWithSex + "_south");
+ }
+ }
+ if (graphicbaseBodyRotten == null)
+ {
+ if (ContentFinder.Get((rottingGraphicPath + baseBodyString + "_south"), false) != null)
+ {
+ //graphicSourceRotten = pawnRenderer.rottingGraphic;
+ Shader shader = pawnRenderer.rottingGraphic.Shader;
+ //if (!ShaderUtility.SupportsMaskTex(shader))
+ // shader = ShaderDatabase.CutoutSkinOverlay;
+ graphicbaseBodyRotten = GraphicDatabase.Get(rottingGraphicPath + baseBodyString, shader, pawnRenderer.rottingGraphic.drawSize, pawnRenderer.rottingGraphic.color, pawnRenderer.rottingGraphic.colorTwo, pawnRenderer.rottingGraphic.data);
+ //pawnRenderer.rottingGraphic = graphicbaseBodyRotten;
+ }
+ else if (customPose != null)
+ {
+ rottingGraphicPath = pawnRenderer.rottingGraphic.path;
+ if (ContentFinder.Get((rottingGraphicPath + baseBodyString + "_south"), false) != null)
+ {
+ graphicSourceRotten = pawnRenderer.rottingGraphic;
+ Shader shader = pawnRenderer.rottingGraphic.Shader;
+ //if (!ShaderUtility.SupportsMaskTex(shader))
+ // shader = ShaderDatabase.CutoutSkinOverlay;
+ graphicbaseBodyRotten = GraphicDatabase.Get(rottingGraphicPath + baseBodyString, shader, pawnRenderer.rottingGraphic.drawSize, pawnRenderer.rottingGraphic.color, pawnRenderer.rottingGraphic.colorTwo, pawnRenderer.rottingGraphic.data);
+ //pawnRenderer.rottingGraphic = graphicbaseBodyRotten;
+ }
+ else
+ {
+ if (SizedApparelSettings.Debug)
+ Log.Warning("[SizedApparel] Missing BaseBodyTexture for rotting Graphic: " + rottingGraphicPath + baseBodyString + "_south");
+ }
+ }
+ }
+ }
+ }
+ else
+ graphicbaseBodyRotten = pawnRenderer.rottingGraphic;
+
+ }
+ //Finding Texture Points
+ if (false && graphicbaseBodyRotten != null)
+ {
+ SizedApparelTexturePointDef PointsDef = DefDatabase.AllDefs.FirstOrDefault((SizedApparelTexturePointDef s) => s.Path == graphicbaseBodyRotten.path);
+ if (SizedApparelSettings.Debug && PointsDef != null)
+ {
+ Log.Message("[SizedApparel] : RottenBaseBody Texture Points Def Found : " + PointsDef.defName);
+ }
+ baseBodyRottenPoints = PointsDef;
+ }
+ else
+ baseBodyRottenPoints = null;
+
+
+ string furCoveredGraphicPath = null;
+
+ //Finding Texture Points
+ if (false && graphicbaseBodyFurCovered != null)
+ {
+ SizedApparelTexturePointDef PointsDef = DefDatabase.AllDefs.FirstOrDefault((SizedApparelTexturePointDef s) => s.Path == graphicbaseBodyFurCovered.path);
+ if (SizedApparelSettings.Debug && PointsDef != null)
+ {
+ Log.Message("[SizedApparel] : FurCoveredBaseBody Texture Points Def Found : " + PointsDef.defName);
+ }
+ baseBodyFurCoveredPoints = PointsDef;
+ }
+ else
+ baseBodyFurCoveredPoints = null;
+
+
+ /*
+ //Try to find sized Body if it's valid
+ int offset = 9999;
+ int currentBreastSizeIndex = 0;
+ float currentBreastSeverity = 0;
+ bool validNakedTexture = false;
+ bool validRottingTexture = false;
+ Graphic nakedGraphic;
+ Graphic rottingGraphic;
+ while (offset < SizedApparelUtility.size.Length)
+ {
+ string breastSeverityStringCache = SizedApparelUtility.BreastSeverityString(breastSeverity, offset, true, ref currentBreastSizeIndex, ref currentBreastSeverity);
+ //search bigger
+ //SizedApparelSettings.matchBodyTextureToMinimumApparelSize? currentBreastSizeIndex <= minSupportedBreasSizeIndex:true
+ if (validNakedTexture == false && nakedGraphicPath !=null)
+ {
+ if ((ContentFinder.Get((nakedGraphicPath + breastSeverityStringCache + "_south"), false) != null))
+ {
+ if (SizedApparelSettings.matchBodyTextureToMinimumApparelSize ? SizedApparelUtility.BreastSizeIndexToSeverity(currentBreastSizeIndex) <= breastSeverityCapToDraw : true)
+ {
+ nakedGraphic = GraphicDatabase.Get(nakedGraphicPath + breastSeverityStringCache, pawnRenderer.nakedGraphic.Shader, pawnRenderer.nakedGraphic.drawSize, pawnRenderer.nakedGraphic.color, pawnRenderer.nakedGraphic.colorTwo, pawnRenderer.nakedGraphic.data);
+ //newAgr.Add(new ApparelGraphicRecord(graphic, agr.sourceApparel));
+ //validTexture = true;
+ //Log.Message(path + BreastSeverityString(BreastSeverity, offset, !findBigger) + ":Texture Found");
+ pawnRenderer.nakedGraphic = nakedGraphic;
+ validNakedTexture = true;
+ }
+ }
+ }
+ if (validRottingTexture == false && rottingGraphicPath != null)
+ {
+ if ((ContentFinder.Get((rottingGraphicPath + breastSeverityStringCache + "_south"), false) != null))
+ {
+ if (SizedApparelSettings.matchBodyTextureToMinimumApparelSize ? SizedApparelUtility.BreastSizeIndexToSeverity(currentBreastSizeIndex) <= breastSeverityCapToDraw : true)
+ {
+ rottingGraphic = GraphicDatabase.Get(rottingGraphicPath + breastSeverityStringCache, pawnRenderer.rottingGraphic.Shader, pawnRenderer.rottingGraphic.drawSize, pawnRenderer.rottingGraphic.color, pawnRenderer.rottingGraphic.colorTwo, pawnRenderer.rottingGraphic.data);
+ //newAgr.Add(new ApparelGraphicRecord(graphic, agr.sourceApparel));
+ //validTexture = true;
+ //Log.Message(path + BreastSeverityString(BreastSeverity, offset, !findBigger) + ":Texture Found");
+ pawnRenderer.rottingGraphic = rottingGraphic;
+ validRottingTexture = true;
+ }
+ }
+ }
+
+ //search smaller
+
+ breastSeverityStringCache = SizedApparelUtility.BreastSeverityString(breastSeverity, offset, false, ref currentBreastSizeIndex, ref currentBreastSeverity);
+
+ if (validNakedTexture == false)
+ {
+ if ((ContentFinder.Get((nakedGraphicPath + breastSeverityStringCache + "_south"), false) != null))
+ {
+ if (SizedApparelSettings.matchBodyTextureToMinimumApparelSize ? SizedApparelUtility.BreastSizeIndexToSeverity(currentBreastSizeIndex) <= breastSeverityCapToDraw : true)
+ {
+ nakedGraphic = GraphicDatabase.Get(nakedGraphicPath + breastSeverityStringCache, pawnRenderer.nakedGraphic.Shader, pawnRenderer.nakedGraphic.drawSize, pawnRenderer.nakedGraphic.color, pawnRenderer.nakedGraphic.colorTwo, pawnRenderer.nakedGraphic.data);
+ //newAgr.Add(new ApparelGraphicRecord(graphic, agr.sourceApparel));
+ //validTexture = true;
+ //Log.Message(path + BreastSeverityString(BreastSeverity, offset, !findBigger) + ":Texture Found");
+ pawnRenderer.nakedGraphic = nakedGraphic;
+ validNakedTexture = true;
+ }
+ }
+ }
+ if (validRottingTexture == false)
+ {
+ if ((ContentFinder.Get((rottingGraphicPath + breastSeverityStringCache + "_south"), false) != null))
+ {
+ if (SizedApparelSettings.matchBodyTextureToMinimumApparelSize ? SizedApparelUtility.BreastSizeIndexToSeverity(currentBreastSizeIndex) <= breastSeverityCapToDraw : true)
+ {
+ rottingGraphic = GraphicDatabase.Get(rottingGraphicPath + breastSeverityStringCache, pawnRenderer.rottingGraphic.Shader, pawnRenderer.rottingGraphic.drawSize, pawnRenderer.rottingGraphic.color, pawnRenderer.rottingGraphic.colorTwo, pawnRenderer.rottingGraphic.data);
+ //newAgr.Add(new ApparelGraphicRecord(graphic, agr.sourceApparel));
+ //validTexture = true;
+ //Log.Message(path + BreastSeverityString(BreastSeverity, offset, !findBigger) + ":Texture Found");
+ pawnRenderer.rottingGraphic = rottingGraphic;
+ validRottingTexture = true;
+ }
+ }
+ }
+
+ if (validNakedTexture == true && validRottingTexture == true)
+ {
+ if (SizedApparelSettings.Debug)
+ Log.Message("[Sized Apparel] " + pawn.Name + "'s body texture has changed.");
+ break;
+ }
+
+ offset++;
+ }
+ */
+ }
+
+ //graphicBreasts = SizedApparelUtility.GetBodyPartGraphic(pawn, breastHediff, true, "Breasts", "Breasts");
+ //if(graphicBreasts == null && pawn.RaceProps.Humanlike && SizedApparelSettings.UnsupportedRaceToUseHumanlike)
+ // graphicBreasts = SizedApparelUtility.GetBodyPartGraphic(pawn, breastHediff, true, "Breasts", "Breasts", false, true, "Humanlike");
+
+
+ if (SizedApparelSettings.drawBodyParts)//body parts update
+ {
+ if (SizedApparelSettings.drawBreasts)
+ {
+
+ if (breastHediff != null)
+ {
+ var breastvar = breastHediff.TryGetComp();
+
+ foreach(var addon in bodyAddons)
+ {
+ if(addon.bodyPartOf == SizedApparelBodyPartOf.Breasts)
+ {
+ addon.SetHediffData(breastHediff.def.defName, SizedApparelUtility.BreastSeverityInt(breastHediff.Severity), SizedApparelUtility.BreastSeverityInt(BreastSeverityCache), breastvar?.variation);
+ addon.SetBone(skeleton?.FindBone("Breasts"));
+ addon.UpdateGraphic();
+ }
+ }
+ //bodyPartBreasts.SetHediffData(breastHediff.def.defName, SizedApparelUtility.BreastSeverityInt(breastHediff.Severity), SizedApparelUtility.BreastSeverityInt(breastSeverityCapped), breastvar?.variation);
+ //bodyPartBreasts.UpdateGraphic();
+ }
+ else
+ {
+ foreach (var addon in bodyAddons)
+ {
+ if (addon.bodyPartOf == SizedApparelBodyPartOf.Breasts)
+ {
+ addon.SetHediffData(null, -1);
+ }
+ }
+ }
+
+ }
+
+
+
+
+ if (SizedApparelSettings.drawUdder)
+ {
+ if (udderHediff != null)
+ {
+ var udderVar = udderHediff.TryGetComp();
+ foreach (var addon in bodyAddons)
+ {
+ if (addon.bodyPartOf == SizedApparelBodyPartOf.Udder)
+ {
+ addon.SetHediffData(udderHediff.def.defName, SizedApparelUtility.BreastSeverityInt(udderHediff.Severity), 1000, udderVar?.variation);
+ addon.SetBone(skeleton?.FindBone("Udder"));
+ addon.UpdateGraphic();
+ }
+ }
+ //bodyPartUdder.SetHediffData(udderHediff.def.defName, SizedApparelUtility.BreastSeverityInt(udderHediff.Severity), 1000, udderVar?.variation);
+ //bodyPartUdder.UpdateGraphic();
+
+ }
+ else
+ {
+ foreach (var addon in bodyAddons)
+ {
+ if (addon.bodyPartOf == SizedApparelBodyPartOf.Udder)
+ {
+ addon.SetHediffData(null, -1);
+ }
+ }
+ }
+
+
+ }
+
+
+ if (SizedApparelSettings.drawBelly)
+ {
+
+
+
+ if (bellySeverity >= 0)
+ {
+ //var bellyVar = breastHediff.GetComp();
+ string BellyVar = null;
+ foreach (var addon in bodyAddons)
+ {
+ if (addon.bodyPartOf == SizedApparelBodyPartOf.Belly)
+ {
+ addon.SetHediffData("BellyBulge", SizedApparelUtility.PrivatePartSeverityInt(bellySeverity), 1000, BellyVar);
+ addon.SetBone(skeleton?.FindBone("Belly"));
+ addon.UpdateGraphic();
+ }
+ }
+ //bodyPartBelly.SetHediffData("BellyBulge", SizedApparelUtility.PrivatePartSeverityInt(bellySeverity), 1000, BellyVar);
+ //bodyPartBelly.UpdateGraphic();
+ }
+ else
+ {
+ foreach (var addon in bodyAddons)
+ {
+ if (addon.bodyPartOf == SizedApparelBodyPartOf.Belly)
+ {
+ addon.SetHediffData(null, -1);
+ }
+ }
+ }
+
+ }
+
+
+ if (SizedApparelSettings.drawVagina)
+ {
+ if (vaginaHediff != null)
+ {
+ var vaginaVar = vaginaHediff.TryGetComp();
+ foreach (var addon in bodyAddons)
+ {
+ if (addon.bodyPartOf == SizedApparelBodyPartOf.Vagina)
+ {
+ addon.SetHediffData(vaginaHediff.def.defName, SizedApparelUtility.PrivatePartSeverityInt(vaginaHediff.Severity), 1000, vaginaVar?.variation);
+ addon.SetBone(skeleton?.FindBone("Vagina"));
+ addon.UpdateGraphic();
+
+ }
+ }
+ //bodyPartVagina.SetHediffData(vaginaHediff.def.defName, SizedApparelUtility.PrivatePartSeverityInt(vaginaHediff.Severity), 1000, vaginaVar?.variation);
+ //bodyPartVagina.UpdateGraphic();
+
+ }
+ else
+ {
+ foreach (var addon in bodyAddons)
+ {
+ if (addon.bodyPartOf == SizedApparelBodyPartOf.Vagina)
+ {
+ addon.SetHediffData(null, -1);
+ }
+ }
+ }
+ }
+
+ if (SizedApparelSettings.drawPubicHair)
+ {
+ if (pubicHairDef != null && pubicHairDef.defName != "None") // pubicHairDef != null // for testing
+ {
+ foreach (var addon in bodyAddons)
+ {
+ if (addon.bodyPartOf == SizedApparelBodyPartOf.PubicHair)
+ {
+ addon.SetHediffData(pubicHairDef.defName, 0, 1000, null);
+ addon.SetBone(skeleton?.FindBone("PubicHair"));
+ addon.UpdateGraphic();
+ }
+ }
+
+ //bodyPartPubicHair.SetHediffData(pubicHairDef.defName, 0, 1000, null);
+ //bodyPartPubicHair.UpdateGraphic();
+ }
+ else
+ {
+ foreach (var addon in bodyAddons)
+ {
+ if (addon.bodyPartOf == SizedApparelBodyPartOf.PubicHair)
+ {
+ addon.SetHediffData(null, -1);
+ }
+ }
+ }
+ }
+
+ if (SizedApparelSettings.drawPenis)
+ {
+ //TODO: Optimize.... memory leak issue?
+ //bodyPartPenises.Clear();
+ //bodyPartBalls.Clear();
+ if (!penisHediffs.NullOrEmpty())
+ {
+ var penisHediff = penisHediffs[0];
+
+ if (penisHediff != null)
+ {
+ var penisVar = penisHediff.TryGetComp();
+ foreach (var addon in bodyAddons)
+ {
+ if (addon.bodyPartOf == SizedApparelBodyPartOf.Penis)
+ {
+ addon.SetHediffData(penisHediff.def.defName, SizedApparelUtility.PrivatePartSeverityInt(penisHediff.Severity), 1000, penisVar?.variation);
+ addon.SetBone(skeleton?.FindBone("Penis"));
+ addon.UpdateGraphic();
+ }
+ if (addon.bodyPartOf == SizedApparelBodyPartOf.Balls)
+ {
+ addon.SetHediffData(penisHediff.def.defName, SizedApparelUtility.PrivatePartSeverityInt(penisHediff.Severity), 1000, penisVar?.variation);
+ addon.SetBone(skeleton?.FindBone("Balls"));
+ addon.UpdateGraphic();
+ }
+ }
+ }
+ else
+ {
+ foreach (var addon in bodyAddons)
+ {
+ if (addon.bodyPartOf == SizedApparelBodyPartOf.Penis)
+ {
+ addon.SetHediffData(null, -1);
+ }
+ if (addon.bodyPartOf == SizedApparelBodyPartOf.Balls)
+ {
+ addon.SetHediffData(null, -1);
+ }
+ }
+ }
+
+
+ // Multiple Penis Drawing. obsolte
+ /*
+ for (int i = 0; i < penisHediffs.Count; i++)
+ {
+ penisHediff = penisHediffs[i];
+ float offsetX = 0; // right and left
+ float offsetZ = 0; // up and down
+ float t = (i + 1f) / (penisHediffs.Count + 1);
+ offsetX = Mathf.Lerp(-0.05f, 0.05f, t);
+ offsetZ = Mathf.Lerp(-0.02f, 0.02f, t);
+
+ if (penisHediff == null)
+ continue;
+
+ Bone penisBone = null;
+ Bone ballsBone = null;
+ if(skeleton != null)
+ {
+ penisBone = skeleton.FindBone("Penis");
+ ballsBone = skeleton.FindBone("Balls");
+ if (ballsBone == null)
+ ballsBone = penisBone;
+ }
+
+
+
+ var penisVar = penisHediff.TryGetComp();
+
+ SizedApparelBodyPart penis = new SizedApparelBodyPart(pawn, this, "Penis", SizedApparelBodyPartOf.Penis, "Penis", false, false, null,ColorType.Skin, penisBone);
+ penis.SetDepthOffsets(0.0108f, 0.0025f, 0.0108f, 0.0108f);
+ penis.SetPositionOffsets(new Vector2(offsetX, 0), new Vector2(-offsetX, 0), new Vector2(offsetX, offsetZ), new Vector2(offsetX, -offsetZ));
+ penis.SetHediffData(penisHediff.def.defName, SizedApparelUtility.PrivatePartSeverityInt(penisHediff.Severity), 1000, penisVar?.variation);
+ penis.centeredTexture = true; // Test Bone
+ penis.UpdateGraphic();
+ bodyPartPenises.Add(penis);
+
+ SizedApparelBodyPart balls = new SizedApparelBodyPart(pawn, this, "Balls", SizedApparelBodyPartOf.Balls, "Penis", false, false, "Penis/Balls", ColorType.Skin, ballsBone);
+ balls.SetDepthOffsets(0.0096f, 0.0085f, 0.0096f, 0.0096f);
+ balls.SetPositionOffsets(new Vector2(offsetX, 0), new Vector2(-offsetX, 0), new Vector2(offsetX, offsetZ), new Vector2(offsetX, -offsetZ));
+ balls.SetHediffData(penisHediff.def.defName, SizedApparelUtility.PrivatePartSeverityInt(penisHediff.Severity), 1000, penisVar?.variation);
+ balls.centeredTexture = true; // Test Bone
+ balls.UpdateGraphic();
+ bodyPartBalls.Add(balls);
+ */
+
+ }
+ }
+
+ else
+ {
+ bodyPartPenises.Clear();
+ bodyPartBalls.Clear();
+ }
+
+ if (SizedApparelSettings.drawAnus)
+ {
+
+ /*
+ graphicAnus = SizedApparelUtility.GetBodyPartGraphic(pawn, anusHediff, false, "Anus", "Anus");
+ if (graphicAnus == null && pawn.RaceProps.Humanlike && SizedApparelSettings.UnsupportedRaceToUseHumanlike)
+ graphicAnus = SizedApparelUtility.GetBodyPartGraphic(pawn, anusHediff, false, "Anus", "Anus", false, true, "Humanlike");
+
+ graphicAnus_horny = SizedApparelUtility.GetBodyPartGraphic(pawn, anusHediff, false, "Anus", "Anus", true);
+ if (graphicAnus_horny == null && pawn.RaceProps.Humanlike && SizedApparelSettings.UnsupportedRaceToUseHumanlike)
+ graphicAnus_horny = SizedApparelUtility.GetBodyPartGraphic(pawn, anusHediff, false, "Anus", "Anus", true, true, "Humanlike");
+ */
+ if (anusHediff != null)
+ {
+ var anusVar = anusHediff.TryGetComp();
+ foreach (var addon in bodyAddons)
+ {
+ if (addon.bodyPartOf == SizedApparelBodyPartOf.Anus)
+ {
+ addon.SetHediffData(anusHediff.def.defName, SizedApparelUtility.PrivatePartSeverityInt(anusHediff.Severity), 1000, anusVar?.variation);
+ addon.SetBone(skeleton?.FindBone("Anus"));
+ addon.UpdateGraphic();
+ }
+ }
+ }
+ else
+ {
+ foreach (var addon in bodyAddons)
+ {
+ if (addon.bodyPartOf == SizedApparelBodyPartOf.Anus)
+ {
+ addon.SetHediffData(null, -1);
+ }
+ }
+ }
+ }
+
+ }
+ hasGraphicUpdatedBefore = true;
+ }
+
+ if(CheckApparel)
+ cachedApparelGraphicRecord = pawnRenderer.apparelGraphics.ToList();
+ else
+ cachedApparelGraphicRecord = new List();
+
+ hasUpdateBeforeSuccess = true;
+ this.isHediffDirty = false;
+ this.isApparelDirty = false;
+ this.isSkeletonDirty = false;
+ }
+
+
+
+
+
+ //public bool hasUnsupportedApparel => Props.hasUnsupportedApparel;
+ //public bool hasUpdateBefore => Props.hasUpdateBefore;
+ /*
+ public void SetHasUnsupportedApparel(bool _hasUnsupportedApparel)
+ {
+ if(Props !=null)
+ Props.hasUnsupportedApparel = _hasUnsupportedApparel;
+ this.hasUnsupportedApparel = _hasUnsupportedApparel;
+ }
+ public void SetHasUpdateBefore(bool _hasUpdateBefore)
+ {
+ if (Props != null)
+ Props.hasUpdateBefore = _hasUpdateBefore;
+ this.hasUpdateBefore = _hasUpdateBefore;
+ }*/
+ public IEnumerable GetAllSizedApparelBodyPart() // can return null bodyparts
+ {
+ yield return bodyPartBreasts;
+ yield return bodyPartNipple;
+ /*
+ foreach (SizedApparelBodyPart bp in bodyPartBreasts)
+ {
+ yield return bp;
+ }
+ foreach (SizedApparelBodyPart bp in bodyPartNipple)
+ {
+ yield return bp;
+ }*/
+ foreach (SizedApparelBodyPart bp in bodyPartPenises)
+ {
+ yield return bp;
+ }
+ foreach (SizedApparelBodyPart bp in bodyPartBalls)
+ {
+ yield return bp;
+ }
+ yield return bodyPartVagina;
+ yield return bodyPartAnus;
+ yield return bodyPartBelly;
+ yield return bodyPartMuscleOverlay;//TODO
+ yield return bodyPartUdder;
+ yield return bodyPartPubicHair; //TODO
+ yield return bodyPartHips;
+ foreach (SizedApparelBodyPart bp in bodyPartThighs)
+ {
+ yield return bp;
+ }
+ foreach (SizedApparelBodyPart bp in bodyPartHands)
+ {
+ yield return bp;
+ }
+ foreach (SizedApparelBodyPart bp in bodyPartFeet)
+ {
+ yield return bp;
+ }
+ foreach (SizedApparelBodyPart bp in bodyAddons)
+ {
+ yield return bp;
+ }
+ }
+ public IEnumerable GetSizedApparelBodyParts(SizedApparelBodyPartOf targetPartOf, bool returnNullPart = false)
+ {
+ foreach(SizedApparelBodyPart bp in GetAllSizedApparelBodyPart())
+ {
+ if (bp == null)
+ {
+ if (returnNullPart)
+ yield return bp;
+ else
+ continue;
+ }
+
+
+ if (bp.bodyPartOf.IsPartOf(targetPartOf))
+ yield return bp;
+ }
+ }
+
+ public void SetPoseFromPoseSet(string poseSetName, bool autoUpdate = true, bool autoSetPawnGraphicDirty = false)
+ {
+ if (poseSetName.NullOrEmpty())
+ {
+ ClearAllPose(autoUpdate, autoSetPawnGraphicDirty);
+ return;
+ }
+
+ var poseSetDef = DefDatabase.GetNamed(poseSetName,false);
+ if (poseSetDef == null)
+ return;
+ if (poseSetDef.poses.NullOrEmpty())
+ return;
+ foreach (SizedApparelPose pose in poseSetDef.poses)
+ {
+ var bodyParts = GetSizedApparelBodyParts(pose.targetBodyPart);
+ //if (bodyParts == null)
+ // continue;
+ if (bodyParts.EnumerableNullOrEmpty())
+ continue;
+ foreach (SizedApparelBodyPart bp in bodyParts.ToList())
+ {
+ if(bp != null)
+ bp.SetCustomPose(poseSetName, autoUpdate, autoSetPawnGraphicDirty);
+ }
+ }
+ }
+ public void ClearAllPose(bool autoUpdate = true, bool autoSetPawnGraphicDirty = false)
+ {
+ foreach (SizedApparelBodyPart bp in GetAllSizedApparelBodyPart())
+ {
+ if(bp != null)
+ bp.SetCustomPose(null, autoUpdate, autoSetPawnGraphicDirty);
+ }
+ }
+ public void ClearPose(SizedApparelBodyPartOf targetPartOf , bool autoUpdate = true, bool autoSetPawnGraphicDirty = false)
+ {
+ foreach (SizedApparelBodyPart bp in GetSizedApparelBodyParts(targetPartOf))
+ {
+ if(bp != null)
+ bp.SetCustomPose(null, autoUpdate, autoSetPawnGraphicDirty);
+ }
+ }
+
+ }
+ [StaticConstructorOnStartup]
+ public class ApparelRecorderCompProperties : CompProperties
+ {
+ public bool hasUnsupportedApparel = false;
+ public bool hasUpdateBefore = false;
+
+ public ApparelRecorderCompProperties()
+ {
+ this.compClass = typeof(ApparelRecorderComp);
+ }
+ public ApparelRecorderCompProperties(Type compClass) : base(compClass)
+ {
+ this.compClass = compClass;
+ }
+
+ }
+}
diff --git a/1.3/source/SizedApparel/SizedApparelDef.cs b/1.3/source/SizedApparel/SizedApparelDef.cs
new file mode 100644
index 0000000..524457a
--- /dev/null
+++ b/1.3/source/SizedApparel/SizedApparelDef.cs
@@ -0,0 +1,58 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using RimWorld;
+using Verse;
+using HarmonyLib;
+//using AlienRace;
+using UnityEngine;
+using rjw;
+
+namespace SizedApparel
+{
+
+ //for avoid first hitch. some day it might need make pre def for fast cache...
+
+ public class ApparelTexture
+ {
+ public BodyTypeDef bodytype;
+ public List textures;
+
+ public string GetTexturePath(int level, out int result)
+ {
+ result = -1;
+ if (level < 0)
+ return null;
+ if (textures.Count > level)
+ {
+ result = level;
+ return textures[level];
+ }
+ if (!textures.NullOrEmpty())
+ {
+ result = textures.Count - 1;
+ return textures[result]; //return biggest as supported
+ }
+ return null;
+ }
+ }
+
+ public class SizedApparelDef : Def
+ {
+ //def name must be match with apparels DefName
+ public bool hidingGenitals = false; // pants must be true
+ public List SizedTextures;
+
+ public ApparelTexture GetApparelTexture(BodyTypeDef bodytype)
+ {
+ if(SizedTextures != null)
+ {
+ return SizedTextures.FirstOrDefault(a => a.bodytype == bodytype);
+ }
+ return null;
+ }
+ }
+
+}
diff --git a/1.3/source/SizedApparel/SizedApparelMain.cs b/1.3/source/SizedApparel/SizedApparelMain.cs
new file mode 100644
index 0000000..0f80d38
--- /dev/null
+++ b/1.3/source/SizedApparel/SizedApparelMain.cs
@@ -0,0 +1,929 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using RimWorld;
+using Verse;
+using HarmonyLib;
+using UnityEngine;
+using rjw;
+using Rimworld_Animations;
+using System.Reflection;
+
+//since I test system alot, source cord is very dirty and not optimized.
+
+
+namespace SizedApparel
+{
+ public struct supportedIndex
+ {
+
+ }
+
+ [StaticConstructorOnStartup]
+ [HarmonyPatch(typeof(Pawn_HealthTracker), "Notify_HediffChanged")]
+ public class PawnHealthTrackerPatch
+ {
+ public static void Postfix(Hediff hediff, Pawn_HealthTracker __instance, ref Pawn ___pawn)
+ {
+ if (___pawn == null)
+ return;
+ var comp = ___pawn.GetComp();
+ if (comp == null)
+ return;
+ if (hediff == null)
+ return;
+
+ if (SizedApparelUtility.isRJWParts(hediff))///
+ {
+ //comp.ClearAll();
+ //comp.Update();
+ comp.SetDirty(false,true,false);
+ //already doing set dirty in hediffchange method.
+ //___pawn.Drawer.renderer.graphics.SetApparelGraphicsDirty();
+ //PortraitsCache.SetDirty(___pawn);
+ //GlobalTextureAtlasManager.TryMarkPawnFrameSetDirty(___pawn);
+ return;
+ }
+ if (SizedApparelUtility.isBellyBulgeHediff(hediff))
+ {
+ comp.SetDirty(false, true, false);
+ return;
+ }
+
+ }
+ }
+
+ //for 1.4
+ /*
+ [StaticConstructorOnStartup]
+ [HarmonyPatch(typeof(Pawn_AgeTracker), "PostResolveLifeStageChange")]
+ public class PawnAgeTrackerPatch
+ {
+ public static void Postfix(Pawn ___pawn)
+ {
+ var comp = ___pawn.GetComp();
+ if (comp == null)
+ return;
+ comp.SetDirty(false,false,false,true,true);//Apparel and Hediff will be changed with other reason. just set skeleton dirty.
+ }
+ }*/
+
+
+
+ [StaticConstructorOnStartup]
+ public class HeddifPatchForRimNudeWorld
+ {
+ //hediff.get_Severity()
+ public static void GetSeverityPostFix(Hediff __instance)
+ {
+ if (__instance.Part != null)
+ {
+
+ if (__instance.Part.def.defName.Equals(SizedApparelUtility.chestString))
+ {
+ if (__instance.def.defName.EndsWith(SizedApparelUtility.breastsString))
+ {
+ //Log.Message("Found Breast Hediff");
+ //_breastSeverity = __instance.Severity;
+ //_breastHediff = __instance;
+ //result = true;
+ //Log.Message(_breastSeverity.ToString());
+ }
+ }
+ }
+ }
+
+ //...get_severity()
+ /*
+ public static void BodyAddonHediffSeverityGraphicPatch(AlienRace.AlienPartGenerator.BodyAddonHediffSeverityGraphic __instance, ref float __result)
+ {
+ if (!SizedApparelPatch.rimNudeWorldActive) { return; }
+ if (!SizedApparelSettings.matchBreastToSupportedApparelSize) { return; }
+ if (__instance.path.Contains(SizedApparelUtility.breastsString))
+ {
+
+ }
+ }*/
+ }
+
+
+
+
+ [Obsolete]
+ [StaticConstructorOnStartup]
+ public class BodyPatch
+ {
+ public static void SetBodyGraphic(Pawn pawn, bool drawClothFlag = true, bool fromGraphicRecord = true, bool revert = false)
+ {
+ //Pawn_ApparelTracker __instance;
+
+
+ //GetBreastSeverity(__instance.pawn, out breastSeverity, out breastHediff);
+ //bool flag = hasUnSupportedApparel(__instance.pawn, breastSeverity, breastHediff);
+ ApparelRecorderComp comp = pawn.GetComp();
+ if (comp == null)
+ return;
+
+ if (revert)
+ {
+ var pawnRenderer = pawn.Drawer?.renderer?.graphics;
+ //Log.Message("useBodyTexture");
+
+ /*
+ if (!pawnRenderer.AllResolved)
+ {
+ pawnRenderer.ResolveAllGraphics();
+ }*/
+
+ if (pawnRenderer == null)
+ return;
+ if (comp.graphicSourceNaked != null)
+ pawnRenderer.nakedGraphic = comp.graphicSourceNaked.GetColoredVersion(pawnRenderer.nakedGraphic.Shader, pawnRenderer.nakedGraphic.color, pawnRenderer.nakedGraphic.colorTwo);
+ if (comp.graphicSourceRotten != null)
+ pawnRenderer.rottingGraphic = comp.graphicSourceRotten.GetColoredVersion(pawnRenderer.rottingGraphic.Shader, pawnRenderer.rottingGraphic.color, pawnRenderer.rottingGraphic.colorTwo);
+ //if (comp.graphicSourceFurCovered != null)
+ // pawnRenderer.furCoveredGraphic = comp.graphicSourceRotten.GetColoredVersion(pawnRenderer.furCoveredGraphic.Shader, pawnRenderer.furCoveredGraphic.color, pawnRenderer.furCoveredGraphic.colorTwo);
+
+ }
+
+
+ if (!comp.hasUpdateBefore)
+ {
+ //comp.Update(true, fromGraphicRecord);
+ }
+
+ float breastSeverity = comp.breastSeverity;
+ Hediff breastHediff = comp.breastHediff;
+
+
+ if (SizedApparelSettings.drawBodyParts == true && SizedApparelSettings.useBodyTexture)//old:SizedApparelSettings.useBodyTexture
+ {
+ //if (SizedApparelSettings.Debug)
+ // Log.Message("[Sized Apparel] Trying to change" + pawn.Name + "'s body texture.");
+
+ var pawnRenderer = pawn.Drawer?.renderer?.graphics;
+ //Log.Message("useBodyTexture");
+
+ /*
+ if (!pawnRenderer.AllResolved)
+ {
+ pawnRenderer.ResolveAllGraphics();
+ }*/
+ if (pawnRenderer == null)
+ return;
+
+ if (!comp.hasUnsupportedApparel || SizedApparelUtility.isPawnNaked(pawn) || !drawClothFlag)
+ {
+
+ if (comp.graphicbaseBodyNaked != null)
+ {
+ pawnRenderer.nakedGraphic = comp.graphicbaseBodyNaked.GetColoredVersion(pawnRenderer.nakedGraphic.Shader, pawnRenderer.nakedGraphic.color, pawnRenderer.nakedGraphic.colorTwo);
+
+ }
+ if (comp.graphicbaseBodyRotten != null)
+ {
+ pawnRenderer.rottingGraphic = comp.graphicbaseBodyRotten.GetColoredVersion(pawnRenderer.rottingGraphic.Shader, pawnRenderer.rottingGraphic.color, pawnRenderer.rottingGraphic.colorTwo);
+
+ }/*
+ if (comp.graphicbaseBodyFurCovered != null)
+ {
+ pawnRenderer.furCoveredGraphic = comp.graphicbaseBodyFurCovered.GetColoredVersion(pawnRenderer.furCoveredGraphic.Shader, pawnRenderer.furCoveredGraphic.color, pawnRenderer.furCoveredGraphic.colorTwo);
+
+ }*/
+ }
+ else
+ {
+ if (comp.graphicSourceNaked != null)
+ pawnRenderer.nakedGraphic = comp.graphicSourceNaked.GetColoredVersion(pawnRenderer.nakedGraphic.Shader, pawnRenderer.nakedGraphic.color, pawnRenderer.nakedGraphic.colorTwo);
+ if (comp.graphicSourceRotten != null)
+ pawnRenderer.rottingGraphic = comp.graphicSourceRotten.GetColoredVersion(pawnRenderer.rottingGraphic.Shader, pawnRenderer.rottingGraphic.color, pawnRenderer.rottingGraphic.colorTwo);
+ //if (comp.graphicSourceFurCovered != null)
+ // pawnRenderer.furCoveredGraphic = comp.graphicSourceFurCovered.GetColoredVersion(pawnRenderer.furCoveredGraphic.Shader, pawnRenderer.furCoveredGraphic.color, pawnRenderer.furCoveredGraphic.colorTwo);
+
+ }
+
+
+ return;//no need to replace full body texture anymore.
+
+ /*
+ if (SizedApparelSettings.useBodyTexture == false)
+ return;
+
+ //Log.Message("Hello");
+ if (pawnGraphicSet == null)
+ return;
+
+ if (pawnGraphicSet.pawn.RaceProps.Humanlike == false)
+ return;
+
+ return;
+
+
+ //Log.Message("SetBodyGraphic");
+ //pawnGraphicSet.ClearCache();
+ string path = pawnGraphicSet.pawn.story.bodyType.bodyNakedGraphicPath;
+ string path_bodyDessicated = pawnGraphicSet.pawn.story.bodyType.bodyDessicatedGraphicPath;
+ string filename;
+ string pathname;
+ string filename_bodyDessicated;
+ string pathname_bodyDessicated;
+ pathname = System.IO.Path.GetDirectoryName(path);
+ filename = System.IO.Path.GetFileName(path);
+ filename_bodyDessicated = System.IO.Path.GetFileName(path_bodyDessicated);
+ pathname_bodyDessicated = System.IO.Path.GetDirectoryName(path_bodyDessicated);
+
+ //Log.Message("SetPath");
+ bool validBody = false;
+ bool validDessicatedBody = false;
+
+ //pawnGraphicSet.pawn.Drawer.renderer.graphics.nakedGraphic
+ //pawnGraphicSet.pawn.Drawer.renderer.graphics.dessicatedGraphic
+
+ if (hasUnsupportApparel)
+ {
+ //Log.Message("IfhasUnsupportApparel");
+ //Graphic newBodyGraphic = null;
+ //Graphic newRottingGraphic = null;
+ //string path;
+
+ //Log.Message("tryUnsupportedApparelBodyTexture");
+ //OLD::pawnGraphicSet.pawn.Drawer.renderer.graphics
+ if (pawnGraphicSet.nakedGraphic != null)
+ if (ContentFinder.Get((pawnGraphicSet.pawn.Drawer.renderer.graphics.nakedGraphic.path + "_UnsupportedApparel" + "_south"), false) != null)
+ {
+ pawnGraphicSet.pawn.Drawer.renderer.graphics.nakedGraphic = GraphicDatabase.Get(pawnGraphicSet.nakedGraphic.path + "_UnsupportedApparel", pawnGraphicSet.nakedGraphic.Shader, pawnGraphicSet.nakedGraphic.drawSize, pawnGraphicSet.nakedGraphic.color, pawnGraphicSet.nakedGraphic.colorTwo);
+ validBody = true;
+ }
+ if (pawnGraphicSet.dessicatedGraphic != null)
+ if (ContentFinder.Get((pawnGraphicSet.dessicatedGraphic.path + "_UnsupportedApparel" + "_south"), false) != null)
+ {
+ pawnGraphicSet.dessicatedGraphic = GraphicDatabase.Get(pawnGraphicSet.dessicatedGraphic.path + "_UnsupportedApparel", pawnGraphicSet.rottingGraphic.Shader, pawnGraphicSet.rottingGraphic.drawSize, pawnGraphicSet.rottingGraphic.color, pawnGraphicSet.rottingGraphic.colorTwo);
+ validDessicatedBody = true;
+ }
+ }
+ else
+ {
+ //Log.Message("undo");
+ string currentPath = pawnGraphicSet.nakedGraphic.path;
+ string currentDessicatedPath = pawnGraphicSet.dessicatedGraphic.path;
+ //Log.Message(currentPath.Substring(0,currentPath.Length - "_UnsupportedApparel".Length));
+ if (pawnGraphicSet.nakedGraphic != null)
+ if (ContentFinder.Get(currentPath.Substring(0, currentPath.Length - "_UnsupportedApparel".Length) + "_south", false) != null)
+ {
+ pawnGraphicSet.nakedGraphic = GraphicDatabase.Get((currentPath.Substring(0, currentPath.Length - "_UnsupportedApparel".Length)), pawnGraphicSet.nakedGraphic.Shader, pawnGraphicSet.nakedGraphic.drawSize, pawnGraphicSet.nakedGraphic.color, pawnGraphicSet.nakedGraphic.colorTwo);
+
+ }
+ if (pawnGraphicSet.dessicatedGraphic != null)
+ if (ContentFinder.Get(currentDessicatedPath.Substring(0, currentDessicatedPath.Length - "_UnsupportedApparel".Length) + "_south", false) != null)
+ {
+ pawnGraphicSet.dessicatedGraphic = GraphicDatabase.Get((currentDessicatedPath.Substring(0, currentDessicatedPath.Length - "_UnsupportedApparel".Length)), pawnGraphicSet.nakedGraphic.Shader, pawnGraphicSet.nakedGraphic.drawSize, pawnGraphicSet.nakedGraphic.color, pawnGraphicSet.nakedGraphic.colorTwo);
+
+ }
+
+ }*/
+ //pawnGraphicSet.ClearCache();
+ }
+ }
+
+
+
+
+
+
+ private static void GetBreastSeverity(Pawn pawn, out float breastSeverity, out Hediff breastHediff)
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+
+ [Obsolete]
+ [StaticConstructorOnStartup]
+ //[HarmonyPatch(typeof(Pawn_ApparelTracker), "ExposeData")]
+ class ApparelTrackerExposePatch
+ {
+ static void Postfix(Pawn_ApparelTracker __instance)
+ {
+ if (!UnityData.IsInMainThread)
+ {
+ return;
+ }
+ if (__instance.pawn == null)
+ return;
+ if (Scribe.mode == LoadSaveMode.PostLoadInit)
+ {
+ ApparelRecorderComp comp = __instance.pawn.GetComp();
+ if (comp == null)
+ return;
+ if (!comp.hasUpdateBefore)
+ comp.Update(true, false);
+ }
+
+ }
+ }
+
+
+ //[StaticConstructorOnStartup]
+ //[HarmonyPatch(typeof(Pawn_ApparelTracker), "Notify_ApparelChanged")]
+ //rimworld 1.2 => apparelChanged, rimworld 1.3 => apparelAdded, apparelRemoved
+ public class ApparelTrackerPatch
+ {
+ //Prefix
+ public static void Changed(Pawn_ApparelTracker __instance)
+ {
+ /*
+ if (Current.Game.World == null)
+ return;
+ */
+ if (!UnityData.IsInMainThread)
+ {
+ return;
+ }
+ if (__instance.pawn == null)
+ return;
+
+ if (SizedApparelSettings.Debug)
+ Log.Message("[Sized Apparel] " + __instance.pawn.Name + "'s apparels are changed. updating sizedApparels for it.");
+
+ //GetBreastSeverity(__instance.pawn, out breastSeverity, out breastHediff);
+ //bool flag = hasUnSupportedApparel(__instance.pawn, breastSeverity, breastHediff);
+ ApparelRecorderComp comp = __instance.pawn.GetComp();
+ if (comp != null)
+ {
+ //comp.ClearBreastCacheValue();
+ //comp.ClearAll();
+ //bool flag = false;
+ //SizedApparelUtility.GetBreastSeverity(__instance.pawn, out breastSeverity, out breastHediff);
+ //flag = SizedApparelUtility.hasUnSupportedApparel(__instance.pawn, breastSeverity, breastHediff);
+ //flag = SizedApparelUtility.hasUnSupportedApparelFromWornData(__instance.pawn, breastSeverity, breastHediff);
+ //comp.hasUpdateBefore = true;
+ //comp.hasUnsupportedApparel = flag;
+ //comp.breastHediff = breastHediff; ;
+ //comp.breastSeverity = breastSeverity;
+ //comp.Update(true, false);//TODO: Coverd But No Graphic may cause Big Issue!!!
+ //comp.Update(true, true);
+
+ comp.SetDirty(false,false,true);
+
+ /*
+ if (SizedApparelSettings.drawBodyParts)//old:SizedApparelSettings.useBodyTexture
+ BodyPatch.SetBodyGraphic(__instance.pawn);
+ */
+ /*
+ //Log.Message(comp.testbool.ToString());
+ //Log.Message("ApparelChanged");
+ //comp.hasUnsupportedApparel = flag;
+ //comp.hasUpdateBefore = true;
+ //comp.SetHasUnsupportedApparel(flag);
+ //comp.SetHasUpdateBefore(true);
+ //if (__instance.pawn.Drawer.renderer.graphics != null)
+
+
+ LongEventHandler.ExecuteWhenFinished(delegate
+ {
+ SetBodyGraphic(__instance.pawn.Drawer.renderer.graphics, flag);
+ }
+ );
+ */
+
+ }
+
+ }
+ }
+ [StaticConstructorOnStartup]
+ //[HarmonyPatch(typeof(PawnGraphicSet), "SetApparelGraphicsDirty")]
+ class SetApparelGraphicsDirtyPatch
+ {
+ public static bool Prefix(PawnGraphicSet __instance)
+ {
+ if (SizedApparelSettings.useBodyTexture)
+ {
+ //__instance.SetAllGraphicsDirty();
+ //return false;
+ }
+ return true;
+ }
+ }
+
+ //TODO
+ [StaticConstructorOnStartup]
+ //[HarmonyPatch(typeof(PawnGraphicSet), "get_apparelGraphics")]
+ class PrivatePartsPatch
+ {
+ public static void Postfix(PawnGraphicSet __instance, ref List __result)
+ {
+ var resualtCach = __result;
+
+ if (SizedApparelSettings.drawBodyParts)
+ {
+ var privateParts = new List();
+ if (SizedApparelSettings.drawPenis)
+ {
+
+ }
+ if (SizedApparelSettings.drawVagina)
+ {
+
+ }
+ if (SizedApparelSettings.drawHips)
+ {
+
+ }
+ if (SizedApparelSettings.drawHips)
+ {
+
+ }
+ if (SizedApparelSettings.drawAnus)
+ {
+
+ }
+ }
+ }
+ }
+
+
+
+ //[HarmonyPatch(typeof(PawnGraphicSet), "MatsBodyBaseAt")]
+ public class MatBodyBaseAtPatch
+ {
+ public static void Postfix(PawnGraphicSet __instance, Rot4 facing, RotDrawMode bodyCondition, bool drawClothes, List __result)
+ {
+ if (__result == null)
+ return;
+ int num = facing.AsInt + 1000 * (int)bodyCondition;
+ List copy;
+ copy = __result.ListFullCopy();
+ for (int i = 0; i<__result.Count; i++)
+ {
+ //SizedApparelsDatabase.GetSupportedApparelOriginalPath(__result[i].g)
+ }
+ }
+
+ }
+
+
+ //Apparel Graphic Texture injection
+ [StaticConstructorOnStartup]
+ [HarmonyPatch(typeof(ApparelGraphicRecordGetter), "TryGetGraphicApparel")]
+ [HarmonyBefore(new string[]{"QualityOfBuilding"})]
+ public class GetApparelGraphicFix
+ {
+ public static void Postfix(Apparel apparel, BodyTypeDef bodyType, ref ApparelGraphicRecord rec, ref bool __result)
+ {
+ if (__result == false)
+ return;
+
+ if (apparel == null)
+ return;
+
+ if (bodyType == null)
+ return;
+
+ if (apparel.Wearer != null)
+ {
+ //rec = new ApparelGraphicRecord(null, null);
+ var comp = apparel.Wearer.GetComp();
+
+ //if (SizedApparelSettings.matchBodyTextureToMinimumApparelSize)
+ // BreastSeverity = comp.BreastSeverityCache;
+ //int currentBreastSizeIndex = 0;
+ //float currentBreastSeverity = -1;
+ //int minSupportedBreastSizeIndex = 1000;
+ //float minSupportedBreastSeverity = 1000;
+
+ //SizedApparelUtility.GetBreastSeverity(apparel.Wearer, out BreastSeverity, out breastHediff);
+ if (comp != null)
+ {
+
+ if (comp.hasUpdateBefore == false)
+ {
+ //SizedApparelUtility.GetBreastSeverity(apparel.Wearer, out BreastSeverity, out breastHediff);
+ //comp.hasUnsupportedApparel = SizedApparelUtility.hasUnSupportedApparelFromWornData(apparel.Wearer, BreastSeverity, breastHediff);
+ //comp.breastSeverity = BreastSeverity;
+ //comp.breastHediff = breastHediff;
+ //comp.hasUpdateBefore = true;
+ //comp.Update(true,false);
+ }
+ if (comp.isDirty == true)
+ {
+ //return;
+ //comp.ClearAll();
+ //comp.Update(true, false);
+ }
+ /*
+ if (comp.needToCheckApparelGraphicRecords)
+ {
+ TODO;
+ if (comp.isApparelGraphicRecordChanged())
+ comp.Update(true, false);
+
+ }*/
+ if (comp.needToCheckApparelGraphicRecords)
+ {
+ /*
+ if (comp.isApparelGraphicRecordChanged())
+ {
+ //return;
+ //comp.Update(true, true); //1.3
+ //SizedApparelUtility.UpdateAllApparel(___pawn, true);
+ }*/
+ }
+
+ //Log.Message("1");
+ var breastHediff = comp.breastHediff;
+ float BreastSeverity = comp.breastSeverity;
+ //Log.Message("2");
+
+ if (SizedApparelSettings.useBreastSizeCapForApparels) //SizedApparelSettings.useBreastSizeCapForApparels //wip
+ BreastSeverity = Math.Min(comp.BreastSeverityCache, BreastSeverity);
+ //Log.Message("3");
+ if (comp.hasUnsupportedApparel == false)//&& (comp.bodyPartBreasts.bodyPartGraphic !=null || comp.bodyPartBreasts.bodyPartGraphicHorny != null)
+ {
+ Graphic sizedGraphic = null;
+ //Log.Message("4");
+ string resultPath = SizedApparelsDatabase.GetSupportedApparelSizedPath(new SizedApparelsDatabase.SizedApparelDatabaseKey(rec.graphic.path, apparel?.Wearer?.def.defName, breastHediff?.def?.defName, apparel.Wearer.gender, apparel?.Wearer?.story?.bodyType?.defName, SizedApparelUtility.BreastSeverityInt(BreastSeverity))).pathWithSizeIndex;
+ if(resultPath != null)
+ {
+ //sizedGraphic = SizedApparelUtility.GetSizedApparelGraphic(rec.graphic, BreastSeverity, apparel?.Wearer?.def.defName, breastHediff.def.defName);
+ sizedGraphic = GraphicDatabase.Get(resultPath, rec.graphic.Shader, rec.graphic.drawSize, rec.graphic.color, rec.graphic.colorTwo);
+ }
+
+
+
+ if(sizedGraphic != null)
+ rec = new ApparelGraphicRecord(sizedGraphic, rec.sourceApparel);
+
+ //minSupportedBreastSizeIndex = Math.Min(currentBreastSizeIndex, minSupportedBreastSizeIndex);
+ //comp.breastSeverityCapToDraw = Math.Min(comp.breastSeverityCapToDraw, minSupportedBreastSeverity);
+ }
+ }
+
+ else
+ {
+ if (SizedApparelSettings.Debug)
+ Log.Warning("[Sized Apparel] " + apparel.Wearer.Name + " doesn't have SizedApparel Compoenet!!");
+
+ }
+ }
+ }
+ }
+
+ [StaticConstructorOnStartup]
+ [HarmonyPatch(typeof(PawnGraphicSet), "ClearCache")]
+ class GraphicSetClearFix
+ {
+ public static void Postfix(PawnGraphicSet __instance)
+ {
+ if (__instance.pawn == null)
+ {
+ return;
+ }
+ var comp = __instance.pawn.GetComp();
+ if (comp == null)
+ return;
+ //comp.ClearAll(false);
+ //comp.needToCheckApparelGraphicRecords = true;
+ comp.SetDirty(false,true,false,false,false); // Check Hediff. If you don't the crotch will not have graphic on first load
+ }
+ }
+
+
+
+
+
+
+ //[HarmonyPatch(typeof(PawnGraphicSet), "MatsBodyBaseAt")]
+ public class PawnGraphicSetPatch
+ {
+ public static void Postfix(ref List __result, ref PawnGraphicSet __instance, Rot4 facing, RotDrawMode bodyCondition)
+ {
+
+ }
+ }
+
+ //TODO: Patch After RJW (Sexualize_GenerateNewPawnInternal) or just postfix to Sexualize
+ [HarmonyPatch(typeof(PawnGenerator), "GenerateNewPawnInternal")]
+ public class PawnGeneratorPatch
+ {
+
+ }
+
+ [HarmonyPatch(typeof(Corpse), "RotStageChanged")]
+ public class RotStagePatch
+ {
+ public static void Prefix(CompRottable __instance)
+ {
+ var comp = __instance.parent.GetComp();
+ if (comp == null)
+ return;
+ comp.SetDirty(false,false,false); // should clear graphicSet....?
+ }
+ }
+
+ //Should I Patch this?
+ //[HarmonyPatch(typeof(Pawn_AgeTracker), "RecalculateLifeStageIndex")]
+ public class AgePatch
+ {
+ public static void Postfix(Pawn_AgeTracker __instance, Pawn ___pawn)
+ {
+ var comp = ___pawn.GetComp();
+ if (comp == null)
+ return;
+ comp.CheckAgeChanged();
+ }
+ }
+
+
+
+ //Styling Station patch..? wip
+ //[HarmonyPatch(typeof(PawnGraphicSet), "MatsBodyBaseAt")]
+ public class BodyMatPatch
+ {
+ public static void Postfix(PawnGraphicSet __instance, RotDrawMode bodyCondition, Rot4 facing, ref List __result, bool drawClothes)
+ {
+ List loc = new List();
+
+ if (bodyCondition == RotDrawMode.Dessicated)
+ {
+ return;
+ }
+
+ for (int i = 0; i< __result.Count; i++)
+ {
+ if (bodyCondition == RotDrawMode.Fresh)
+ {
+ if (__result[i] == __instance.nakedGraphic.MatAt(facing, null))
+ {
+
+ continue;
+ }
+
+ }
+ else if (bodyCondition == RotDrawMode.Rotting || __instance.dessicatedGraphic == null)
+ {
+ if (__result[i] == __instance.rottingGraphic.MatAt(facing, null))
+ {
+
+
+ continue;
+ }
+ }
+
+ if (drawClothes)
+ {
+
+
+ }
+
+
+ loc.Add(__result[i]);
+ }
+
+ }
+ }
+ //RimWorld 1.3
+ //WIPWIPWIP TODO
+ [HarmonyPatch(typeof(PawnRenderer), "BaseHeadOffsetAt")]
+ public class BaseHeadOffsetAtPatch
+ {
+ public static void Postfix(ref PawnRenderer __instance, Pawn ___pawn, Rot4 rotation, ref Vector3 __result)
+ {
+ ApparelRecorderComp apparelRecorder = ___pawn.GetComp();
+ if (apparelRecorder == null)
+ return;
+ if (apparelRecorder.customPose != null)
+ {
+ //var item = apparelRecorder.currentCustomPose.headOffset.FirstOrDefault(b => b.bodyType == ___pawn.story.bodyType.label);
+ //__result += item.offsets.GetOffset(rotation);
+ }
+ }
+ }
+
+
+
+ //RimWorld 1.3 Only. Not 1.4
+ [HarmonyPatch(typeof(PawnRenderer), "DrawPawnBody")]
+ public class DrawPawnBodyPatch
+ {
+ static MethodInfo overrideMatMethod = AccessTools.Method(typeof(PawnRenderer), "OverrideMaterialIfNeeded");
+
+
+ public static void Prefix(ref PawnRenderer __instance, Pawn ___pawn, PawnRenderFlags flags)
+ {
+ if (!SizedApparelSettings.drawBodyParts)
+ return;
+ if (___pawn == null)
+ return;
+ ApparelRecorderComp apparelRecorder = ___pawn.GetComp();
+ if (apparelRecorder == null)
+ return;
+ //!flags.FlagSet(PawnRenderFlags.StylingStation)&&
+ bool flag = false;
+ //if (apparelRecorder.needToCheckApparelGraphicRecords && apparelRecorder.isApparelGraphicRecordChanged())
+ /*
+ if (apparelRecorder.isApparelGraphicRecordChanged())
+ {
+ flag = true;
+ }
+ */
+
+ if (false && flags.FlagSet(PawnRenderFlags.StylingStation))//TODO...?
+ {
+ //apparelRecorder.isDirty is allways true
+
+ if (true)//StylingStation Doesn't work with cache! patch in postfix
+ {
+ if(apparelRecorder.recentClothFlag != flags.FlagSet(PawnRenderFlags.Clothes))
+ apparelRecorder.Update(true, true, true, flags.FlagSet(PawnRenderFlags.Clothes));
+ if(flags.FlagSet(PawnRenderFlags.Clothes))
+ SizedApparelUtility.UpdateAllApparel(___pawn, true);
+ }
+
+
+ }
+ else
+ {
+ if ((!apparelRecorder.hasUpdateBefore || apparelRecorder.isDirty))
+ {
+ if (SizedApparelSettings.Debug)
+ Log.Message("[SizedApparel] trying to draw " + ___pawn.Name + " with unupdated component or SetDirty! Updating it.");
+ //apparelRecorder.ClearAll();
+ //Todo. Async Update?
+ apparelRecorder.Update(true, true, true, flags.FlagSet(PawnRenderFlags.Clothes));
+ SizedApparelUtility.UpdateAllApparel(___pawn,true);
+ }
+ if (flag)
+ {
+ //apparelRecorder.Update(true, true, true, flags.FlagSet(PawnRenderFlags.Clothes));
+ //apparelRecorder.Update(true, true); 1.3
+ //SizedApparelUtility.UpdateAllApparel(___pawn, true);
+ }
+ }
+ return;
+ //don't change body graphic file. it will inject material in PawnGraphicSet.MatsBodyBaseAt
+ if (SizedApparelSettings.drawBodyParts)
+ BodyPatch.SetBodyGraphic(___pawn, flags.FlagSet(PawnRenderFlags.Clothes), false);
+ else
+ BodyPatch.SetBodyGraphic(___pawn, flags.FlagSet(PawnRenderFlags.Clothes), false, false);
+ }
+
+ public static void Postfix(ref PawnRenderer __instance, Vector3 rootLoc, float angle, Rot4 facing, RotDrawMode bodyDrawType, PawnRenderFlags flags, Pawn ___pawn, Mesh bodyMesh)
+ {
+ if (___pawn == null)
+ return;
+ ApparelRecorderComp apparelRecorder = ___pawn.GetComp();
+ if (apparelRecorder == null)
+ return;
+ Quaternion quaternion = Quaternion.AngleAxis(angle, Vector3.up);
+
+ if (bodyMesh == null)
+ return;
+
+ Quaternion quat = Quaternion.AngleAxis(angle, Vector3.up);
+
+
+ string defName = __instance.graphics.pawn.def.defName;
+
+ /*
+ Shader shader = ___pawn.Drawer.renderer.graphics.nakedGraphic.Shader;
+ Color skinColor = Color.white;
+ Color skinColor2 = Color.white;
+ if (bodyDrawType == RotDrawMode.Fresh)
+ {
+ shader = ___pawn.Drawer.renderer.graphics.nakedGraphic.Shader;
+ if (!ShaderUtility.SupportsMaskTex(shader))
+ shader = ShaderDatabase.CutoutSkinOverlay;
+ skinColor = ___pawn.Drawer.renderer.graphics.nakedGraphic.Color;
+ skinColor2 = ___pawn.Drawer.renderer.graphics.nakedGraphic.ColorTwo;
+ }
+ else if(bodyDrawType == RotDrawMode.Rotting)
+ {
+ shader = ___pawn.Drawer.renderer.graphics.rottingGraphic.Shader;
+ if (!ShaderUtility.SupportsMaskTex(shader))
+ shader = ShaderDatabase.CutoutSkinOverlay;
+ skinColor = ___pawn.Drawer.renderer.graphics.rottingGraphic.Color;
+ skinColor2 = ___pawn.Drawer.renderer.graphics.rottingGraphic.ColorTwo;
+ }*/
+
+ /*
+ //FurCoveredColor
+ if(bodyDrawType == RotDrawMode.Fresh && __instance.graphics.furCoveredGraphic != null)
+ {
+ shader = ___pawn.Drawer.renderer.graphics.furCoveredGraphic.Shader;
+ if (!ShaderUtility.SupportsMaskTex(shader))
+ shader = ShaderDatabase.CutoutSkinOverlay;
+ skinColor = ___pawn.Drawer.renderer.graphics.furCoveredGraphic.Color;
+ skinColor2 = ___pawn.Drawer.renderer.graphics.furCoveredGraphic.ColorTwo;
+ }*/
+
+
+
+ if (flags.FlagSet(PawnRenderFlags.StylingStation))//Styling station doesn't affect to real pawn data. so cannot cache to component.
+ {
+
+
+ }
+
+ //breasts are only rendered when all of worn apparels are supported or nude.
+
+ if (true)//__instance.graphics.furCoveredGraphic == null
+ {
+ apparelRecorder.UpdateTickAnim(rootLoc, angle);
+ apparelRecorder.DrawAllBodyParts(rootLoc, angle, facing, bodyDrawType, flags, ___pawn, bodyMesh);
+ }
+ //else. the DrawPawnFur will draw bodyparts becaust it should be upper
+
+ }
+ }
+
+
+ //Base Body Graphic Injection
+ [HarmonyPatch(typeof(PawnGraphicSet), "MatsBodyBaseAt")]
+ public class MatsBodyBastAtPatch
+ {
+ public static void Postfix(ref List __result, PawnGraphicSet __instance, Rot4 facing, RotDrawMode bodyCondition, bool drawClothes)
+ {
+ if (!SizedApparelSettings.useBodyTexture)
+ return;
+
+ if (__result.NullOrEmpty())
+ return;
+
+ if (!SizedApparelUtility.CanApplySizedApparel(__instance.pawn))
+ return;
+
+ var comp = __instance.pawn.GetComp();
+ if (comp == null) // maybe it can be null? but why...? mechanoids?
+ return;
+
+ if (drawClothes)
+ {
+ if (comp.hasUnsupportedApparel)
+ return;
+ }
+
+ Material bodyMat = null;
+ Material sizedApparelBaseBodyMat = null;
+ switch (bodyCondition)
+ {
+ case RotDrawMode.Fresh:
+ if(__instance.nakedGraphic != null && comp.graphicbaseBodyNaked != null)
+ {
+ bodyMat = __instance.nakedGraphic.MatAt(facing, null);
+ sizedApparelBaseBodyMat = comp.graphicbaseBodyNaked.MatAt(facing, null);
+ }
+ break;
+ case RotDrawMode.Rotting:
+ if (__instance.rottingGraphic != null && comp.graphicbaseBodyRotten != null)
+ {
+ bodyMat = __instance.rottingGraphic.MatAt(facing, null);
+ sizedApparelBaseBodyMat = comp.graphicbaseBodyRotten.MatAt(facing, null);
+ }
+ break;
+ case RotDrawMode.Dessicated:
+ return;// //don't inject for Dessicated graphic. it doesn't need to patch for this
+ break;
+ default:
+ bodyMat = null;
+ sizedApparelBaseBodyMat = null;
+ break;
+ }
+
+ if (sizedApparelBaseBodyMat == null)
+ return;
+
+ //the body mat would be in first index but not sure. so search from start
+ for (int i = 0; i < __result.Count; i++)
+ {
+ if(__result[i] == bodyMat)
+ {
+ __result[i] = sizedApparelBaseBodyMat;
+ //should inject body part graphics here?
+ break;
+ }
+ }
+ //should do something more? such as add body parts or somthing?
+ }
+ }
+
+
+ //TODO
+ [HarmonyPatch(typeof(PawnRenderer), "BaseHeadOffsetAt")]
+ public class HeadOffsetPatch
+ {
+
+ public static void Postfix(PawnRenderer __instance, Pawn ___pawn, Rot4 rotation, ref Vector3 __result)
+ {
+ var comp = ___pawn.GetComp();
+ if (comp == null)
+ return;
+ }
+
+ }
+
+
+
+}
+
+
diff --git a/1.3/source/SizedApparel/SizedApparelPoseSet.cs b/1.3/source/SizedApparel/SizedApparelPoseSet.cs
new file mode 100644
index 0000000..4356695
--- /dev/null
+++ b/1.3/source/SizedApparel/SizedApparelPoseSet.cs
@@ -0,0 +1,89 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Verse;
+using RimWorld;
+using HarmonyLib;
+using UnityEngine;
+
+namespace SizedApparel
+{
+ /*
+ [HarmonyPatch(typeof(PawnRenderer), "BaseHeadOffsetAt")]
+ [HarmonyAfter(new string[]
+ {
+ "rimworld.erdelf.alien_race.main"
+ })]
+ */
+ //TODO
+ public static class PawnRenderer_BaseHeadOffsetAt_Patch_For_Pose
+ {
+ [HarmonyPostfix]
+ public static void BaseHeadOffsetAtPostfix_Post(PawnRenderer __instance, Rot4 rotation, ref Vector3 __result, ref Pawn ___pawn)
+ {
+ return;
+
+ /*
+ var comp = ___pawn.GetComp();
+
+ if (comp == null)
+ return;
+ if (comp.customPose == null)
+ return;
+
+ SizedApparelPoseDef poseDef = DefDatabase.GetNamed(comp.customPose);
+ if (poseDef == null)
+ return;
+
+ Rot4Offsets? headOffset = new Rot4Offsets();
+
+ string bodyType = ___pawn.story?.bodyType?.defName;
+ if (bodyType == null)
+ {
+ bodyType = "default";
+ headOffset = poseDef.headOffset.FirstOrDefault(b => b.bodyType.ToLower() == "default" | b.bodyType.ToLower() == "null").offsets;
+ }
+ else
+ {
+ headOffset = poseDef.headOffset.FirstOrDefault(b => b.bodyType.ToLower() == bodyType.ToLower()).offsets;
+ }
+
+ if (headOffset == null)
+ return;
+ */
+
+
+ //headOffset.
+
+ //TODO: Mesh Based Scaled Offset
+ //__result = __result + headOffset;
+
+
+
+ return;
+ }
+ }
+ public class SizedApparelPoseSetDef : Def
+ {
+
+ public List poses;
+
+ }
+
+ public class PoseDef : Def
+ {
+
+ }
+
+
+ public class SizedApparelPose
+ {
+ //public string poseName; use defName as PoseName
+ public SizedApparelBodyPartOf targetBodyPart = SizedApparelBodyPartOf.Torso;
+ //public List headOffset;
+
+ }
+
+}
diff --git a/1.3/source/SizedApparel/SizedApparelPubicHair.cs b/1.3/source/SizedApparel/SizedApparelPubicHair.cs
new file mode 100644
index 0000000..a039c84
--- /dev/null
+++ b/1.3/source/SizedApparel/SizedApparelPubicHair.cs
@@ -0,0 +1,37 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using RimWorld;
+using Verse;
+using HarmonyLib;
+using UnityEngine;
+using rjw;
+
+namespace SizedApparel
+{
+ [HarmonyPatch(typeof(PawnGraphicSet), "CalculateHairMats")]
+ public static class CalculateHairMatsPatch
+ {
+ public static void Postfix()
+ {
+
+ }
+ }
+
+ public class PubicHairDef : StyleItemDef
+ {
+
+ }
+
+ class SizedApparelPubicHair
+ {
+ }
+
+
+ public static class IdeoStyleTackerPatch
+ {
+
+ }
+}
diff --git a/1.3/source/SizedApparel/SizedApparelSettingcs.cs b/1.3/source/SizedApparel/SizedApparelSettingcs.cs
new file mode 100644
index 0000000..155822d
--- /dev/null
+++ b/1.3/source/SizedApparel/SizedApparelSettingcs.cs
@@ -0,0 +1,856 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Unity;
+using UnityEngine;
+using Verse;
+
+namespace SizedApparel
+{
+ //include Human, set humanlike's custom setting
+ //Only few settings are allow in ModSetting. other needs to be set in Def (xml) file
+
+ public class AlienRaceSetting : IExposable
+ {
+ public string raceName = null;
+ public bool overrideDef = false;
+ public bool asHuman = false;
+ public float drawMinAge = -1; //pawn's Biological age. -1 to ignore.
+
+ public AlienRaceSetting(string raceName)
+ {
+ this.raceName = raceName;
+ }
+ public AlienRaceSetting()
+ {
+
+ }
+
+ public void ExposeData()
+ {
+ Scribe_Values.Look(ref raceName, "raceName", null);
+ Scribe_Values.Look(ref overrideDef, "overrideDef", false);
+ Scribe_Values.Look(ref asHuman, "asHuman", false);
+ Scribe_Values.Look(ref drawMinAge, "drawMinAge", -1);
+ }
+
+ //public int ageYoung = -1; //use receDefName_young folder. -1 to ignore
+ //public int ageOld = -1; //use raceDefName_old folder. -1 to ignore.
+ }
+
+
+ public class SizedApparelSettings : ModSettings
+ {
+
+ public static bool Debug = false;
+ public static bool DetailLog = false;
+ public static bool autoClearCacheOnWriteSetting = true;
+
+ public static bool PreCacheOnLoad = true;
+ public static float PreCacheRandomFactor = 0.5f;
+
+ public static bool useBodyTexture = true;//for user who not use rimnudeworld
+
+ public static bool useGenderSpecificTexture = true;
+
+ public static bool matchBodyTextureToMinimumApparelSize = true;//for avoiding breasts cliping
+
+ public static bool useBreastSizeCapForApparels = true;
+
+ public static bool DontReplaceBodyTextureOnNude = true;
+ //public static bool DontReplaceBodyTextureOnUnsupported = true;
+
+
+
+ //Apply Target Pawn Category
+ public static bool ApplyHumanlikes = true; //Always true.
+ public static bool ApplyAnimals = true;
+ public static bool ApplyAnimalsPlayerFactionOnly = true; //TODO
+ public static bool ApplyMechanoid = true;
+
+ public static bool ApplyApparelPatchForMale = false; //only ApparelServerityWork.
+
+ public static bool ApplyColonists = true;
+ public static bool ApplySlaves = true;
+ public static bool ApplyPrisoner = true;
+ public static bool ApplyNeutralAndAlly = true;
+ public static bool ApplyHostile = false;
+
+
+ public static bool AnimationPatch = true;
+
+ //TODO: Standalone render bodyparts.
+ public static bool drawBodyParts = true;//for user who not use rimnudeworld
+ public static bool drawBreasts = true;
+ public static bool drawPenis = true;
+ public static bool drawVagina = true;
+ public static bool drawMuscleOverlay = true;
+ public static bool drawHips = true;//TODO
+ public static bool drawAnus = true;
+ public static bool drawBelly = false;//TODO
+ public static bool drawUdder = false;//TODO
+ public static bool drawPubicHair = true;
+ public static bool hideBallOfFuta = false;
+ public static bool hidePenisOfMale = false;
+ public static bool matchBreastToSupportedApparelSize = true;//for avoiding breasts cliping
+
+ public static bool useBodyPartsVariation = true;
+ public static bool showBodyPartsVariation = true;
+
+ public static bool breastsPhysics = false;
+
+ //RimNudeWorld
+ public static bool drawSizedApparelBreastsOnlyWorn = false;
+ public static bool hideRimNudeWorldBreasts = false;//disable rimnudeworld breasts.
+
+ [Obsolete]
+ public static bool useUnsupportedBodyTexture = true;//bodytexture when wearing unsupported apparel.
+ public static bool useSafeJobBreasts = true;
+
+ public static bool changeBodyType;
+ public static bool fatToFemale;
+ public static bool hulkToThin;
+
+ public static bool onlyForFemale = true;
+ public static bool useRandomSize = true;//for user who play without rimjobworld
+ public static float randomSizeMin = 0.01f;
+ public static float randomSizeMax = 1.01f;
+
+ //Lagacy Variable
+ public static bool useTitanic = true;
+ public static bool useColossal = true;
+ public static bool useGargantuan = true;
+ public static bool useMassive = true;
+ public static bool useEnormous = true;
+ public static bool useHuge = true;
+ public static bool useLarge = true;
+ public static bool useAverage = true;
+ public static bool useSmall = true;
+ public static bool useTiny = true;
+ public static bool useNipples = true;
+
+
+
+ //Alien Race Settings
+ [Obsolete]
+ public static bool UnsupportedRaceToUseHumanlike = false;
+ public static List alienRaces = new List();
+ public static List alienRacesAllowHumanlikTextures = new List(); //This Value Will be Saved and loaded
+ public static string alienRaceSearch = "";
+ public static Vector2 alienRacesListScrollPos;
+ public static List alienRaceSettings = new List();
+
+ //Force All Apparel as supported
+ public static bool ForcedSupportApparel = false;
+
+
+
+ public static bool getUseSettingFromIndex(int target)
+ {
+ if (target < 0)
+ return false;
+ else if (target == 0)
+ return useNipples;
+ else if (target == 1)
+ return useTiny;
+ else if (target == 2)
+ return useSmall;
+ else if (target == 3)
+ return useAverage;
+ else if (target == 4)
+ return useLarge;
+ else if (target == 5)
+ return useHuge;
+ else if (target == 6)
+ return useEnormous;
+ else if (target == 7)
+ return useMassive;
+ else if (target == 8)
+ return useGargantuan;
+ else if (target == 9)
+ return useColossal;
+ else if (target == 10)
+ return useTitanic;
+ else
+ return false;
+ }
+
+
+
+
+ public static bool useUnderBreasts = true;
+ public static float UnderBreastsOffset = -0.0013f;
+
+ public override void ExposeData()
+ {
+
+ Scribe_Values.Look(ref Debug, "Debug", false);
+ Scribe_Values.Look(ref DetailLog, "DetailLog", false);
+ Scribe_Values.Look(ref autoClearCacheOnWriteSetting, "autoClearCacheOnWriteSetting", true);
+
+ //force to use it. this is important thing.
+ //Scribe_Values.Look(ref useBreastSizeCapForApparels, "useBreastSizeCapForApparels", true);
+
+ //Apply Categories.
+ Scribe_Values.Look(ref ApplyAnimals, "ApplyAnimals", true);
+ Scribe_Values.Look(ref ApplyHumanlikes, "ApplyHumanlikes", true);
+ Scribe_Values.Look(ref ApplyMechanoid, "ApplyMechanoid", true);
+
+ Scribe_Values.Look(ref AnimationPatch, "AnimationPatch", true);
+
+ Scribe_Values.Look(ref useBodyTexture, "useBodyTexture", true);
+ Scribe_Values.Look(ref useGenderSpecificTexture, "useGenderSpecificTexture", true);
+
+ Scribe_Values.Look(ref matchBodyTextureToMinimumApparelSize, "matchBodyTextureToMinimumApparelSize", true);
+ Scribe_Values.Look(ref matchBreastToSupportedApparelSize, "matchBreastToSupportedApparelSize", true);
+
+ //Unsurpported to forced Surpported
+ //Scribe_Values.Look(ref UnsupportedRaceToUseHumanlike, "UnsupportedRaceToUseHumanlike", false);
+ Scribe_Values.Look(ref ForcedSupportApparel, "ForcedSupportApparel", false);
+
+
+ Scribe_Collections.Look(ref alienRaceSettings, "alienSettings", LookMode.Deep);
+ if (Scribe.mode == LoadSaveMode.LoadingVars)
+ {
+ if (alienRaceSettings == null)
+ {
+ alienRaceSettings = new List();
+ }
+
+ SizedApparelMod.CheckAndLoadAlienRaces();
+
+ //Initialize Setting for missing Race
+ foreach (var raceName in SizedApparelMod.alienDefList)
+ {
+ AlienRaceSetting raceSetting = null;
+ foreach (var r in SizedApparelSettings.alienRaceSettings)
+ {
+ if (r.raceName == null)
+ continue;
+ if (raceName == r.raceName)
+ {
+ raceSetting = r;
+ break;
+ }
+ }
+ if (raceSetting == null)
+ {
+ raceSetting = new AlienRaceSetting(raceName);
+ SizedApparelSettings.alienRaceSettings.Add(raceSetting);
+ }
+ }
+
+
+
+ }
+ if (Scribe.mode == LoadSaveMode.ResolvingCrossRefs)
+ {
+ if(!alienRaceSettings.NullOrEmpty())
+ alienRaceSettings.RemoveAll((AlienRaceSetting x) => string.IsNullOrEmpty(x.raceName));
+ }
+
+ Scribe_Values.Look(ref useUnsupportedBodyTexture, "useUnsupportedBodyTexture", true);
+ Scribe_Values.Look(ref DontReplaceBodyTextureOnNude, "DontReplaceBodyTextureOnNude", false);
+
+ Scribe_Values.Look(ref hideRimNudeWorldBreasts, "hideRimNudeWorldBreasts", false);
+ Scribe_Values.Look(ref useSafeJobBreasts, "useSafeJobBreasts", true);
+
+ Scribe_Values.Look(ref useRandomSize, "useRandomSize", true);
+ Scribe_Values.Look(ref randomSizeMin, "randomSizeMin", 0.01f);
+ Scribe_Values.Look(ref randomSizeMax, "randomSizeMax", 1.01f);
+
+ Scribe_Values.Look(ref drawBodyParts, "drawBodyParts", true);
+ Scribe_Values.Look(ref useBodyPartsVariation, "useBodyPartsVariation", true); // forse true for now. TODO
+ Scribe_Values.Look(ref showBodyPartsVariation, "showBodyPartsVariation", true);
+
+ Scribe_Values.Look(ref drawMuscleOverlay, "drawMuscleOverlay", true);
+ Scribe_Values.Look(ref drawBreasts, "drawBreasts", true);
+ Scribe_Values.Look(ref drawSizedApparelBreastsOnlyWorn, "drawSizedApparelBreastsOnlyWorn", false);
+ Scribe_Values.Look(ref drawPenis, "drawPenis", true);
+ Scribe_Values.Look(ref drawVagina, "drawVagina", true);
+ Scribe_Values.Look(ref drawAnus, "drawAnus", true);
+ Scribe_Values.Look(ref drawUdder, "drawUdder", true);
+ Scribe_Values.Look(ref drawBelly, "drawBelly", true);
+ Scribe_Values.Look(ref drawPubicHair, "drawPubicHair", true);
+
+
+ //force to draw all size type
+ /*
+ Scribe_Values.Look(ref useTitanic, "useTitanic", true);
+ Scribe_Values.Look(ref useColossal, "useColossal", true);
+ Scribe_Values.Look(ref useGargantuan, "useGargantuan", true);
+ Scribe_Values.Look(ref useMassive, "useMassive", true);
+ Scribe_Values.Look(ref useEnormous, "useEnormous", true);
+ Scribe_Values.Look(ref useHuge, "useHuge", true);
+ Scribe_Values.Look(ref useLarge, "useLarge", true);
+ Scribe_Values.Look(ref useAverage, "useAverage", true);
+ Scribe_Values.Look(ref useSmall, "useSmall", true);
+ Scribe_Values.Look(ref useTiny, "useTiny", true);
+ Scribe_Values.Look(ref useNipples, "useNipples", true);
+ */
+
+ Scribe_Values.Look(ref useUnderBreasts, "useUnderBreasts",true);
+ Scribe_Values.Look(ref UnderBreastsOffset, "UnderBreastsOffset", -0.0013f);
+
+ //TODO: Humanlike Setting Per Race
+ //Scribe_Values.Look(ref alienRacesAllowHumanlikTextures, "alienRacesAllowHumanlikTextures");
+
+ //BreastsPhysics
+ Scribe_Values.Look(ref breastsPhysics, "breastsPhysics", false);
+
+
+ base.ExposeData();
+ }
+
+ }
+
+ public class SizedApparelMod : Mod
+ {
+
+ SizedApparelSettings settings;
+ private static Vector2 ScrollPosL = Vector2.zero;
+ private static Vector2 ScrollPosR = Vector2.zero;
+ public static List alienDefList = new List(); // to load aliens and compare with modsetting
+
+ public override void WriteSettings()
+ {
+ base.WriteSettings();
+ if(SizedApparelSettings.autoClearCacheOnWriteSetting)
+ ClearCache();
+ }
+
+ public static void CheckAndLoadAlienRaces()
+ {
+ if(alienDefList == null)
+ alienDefList = new List();
+ if (true)//alienDefList.Count == 0
+ {
+ IEnumerable HumanlikeRaces;
+ HumanlikeRaces = DefDatabase.AllDefs.Where(b => b.race?.Humanlike == true);
+
+ foreach (ThingDef raceDef in HumanlikeRaces)
+ {
+ //Default Value Is True
+ alienDefList.Add(raceDef.defName);
+ }
+ }
+ }
+
+ public static void ClearCache(bool clearPawnGraphicSet = true)
+ {
+ SizedApparelsDatabase.ClearAll();
+
+ if (Find.CurrentMap != null)
+ {
+ foreach (Pawn pawn in Find.CurrentMap.mapPawns.AllPawns)
+ {
+ if (pawn == null)
+ continue;
+ var comp = pawn.GetComp();
+ if (comp != null)
+ {
+ comp.UpdateRaceSettingData();
+ comp.SetDirty(clearPawnGraphicSet,true,true,true);
+ }
+
+ }
+ }
+ }
+
+
+
+
+ public SizedApparelMod(ModContentPack content) : base(content)
+ {
+ this.settings = GetSettings();
+ }
+
+ public override void DoSettingsWindowContents(Rect inRect)
+ {
+
+ const float alienRaceSettingHeight = 120;
+
+ //CheckAndLoadAlienRaces();
+ Listing_Standard listingStandard = new Listing_Standard();
+ //Rect rect = new Rect(0f, 0f, inRect.width, 950);
+ //Rect rect = inRect.ExpandedBy(0.9f);
+ Rect leftRect = new Rect(inRect.position, new Vector2(inRect.width / 2, inRect.height));
+ Rect rightRect = new Rect(inRect.position + new Vector2(inRect.width / 2,0), new Vector2(inRect.width / 2, inRect.height));
+ //rect.xMax *= 0.9f;
+ //leftRect = leftRect.ContractedBy(10f);
+ rightRect = rightRect.ContractedBy(10f);
+ Rect scrollRect = new Rect(0, 0, leftRect.width - 30f, Math.Max(leftRect.height + (float)alienDefList.Count* alienRaceSettingHeight, 1f));
+ Widgets.BeginScrollView(leftRect, ref ScrollPosL, scrollRect, true);
+ leftRect = new Rect(leftRect.x, leftRect.y, leftRect.width - 30f, leftRect.height + Math.Max((float)alienDefList.Count * alienRaceSettingHeight, 1f) + 250f);
+ listingStandard.Begin(leftRect);
+ listingStandard.maxOneColumn = true;
+
+ listingStandard.CheckboxLabeled("Debug Log", ref SizedApparelSettings.Debug, "Debug logs.\nDefault: false");
+ if (SizedApparelSettings.Debug)
+ {
+ listingStandard.CheckboxLabeled("Debug Log (Detail)", ref SizedApparelSettings.DetailLog, "Debug logs for checking missing textures.\nDefault: false");
+
+ }
+ listingStandard.GapLine(1f);
+ listingStandard.CheckboxLabeled("Auto Clear Cache On Close Setting", ref SizedApparelSettings.autoClearCacheOnWriteSetting, "Auto clear cache data to apply Setting.\nDefault: true");
+ if(SizedApparelSettings.autoClearCacheOnWriteSetting == false)
+ {
+ listingStandard.Label("If you changed options, try Clear Cache to apply. Some options may need to restart");
+ if (listingStandard.ButtonTextLabeled("Clear Cache", "Press If you changed Option."))//\n do not push unless you really need. \n if this button still not work. reload savefile. if still not work, reload rimworld"
+ {
+ ClearCache();
+ }
+ if (listingStandard.ButtonTextLabeled("RandomPreCache", "15 sec ~ 2 min"))
+ {
+ SizedApparelsDatabase.RandomPreCacheForApparels();
+ SizedApparelsDatabase.RandomPreCacheForBodyParts();
+ }
+ }
+
+
+ listingStandard.Gap();
+ listingStandard.GapLine();
+
+
+
+
+
+ /*
+ listingStandard.Label("Optimization",-1,"");
+ //listingStandard.CheckboxLabeled("Debug Log", ref SizedApparelSettings.Debug, "Debug logs.\nDefault: false");
+ listingStandard.Gap(8);
+ listingStandard.Label("no more optimization setting yet.\n It's hardly optimized already :)", -1, "");
+ listingStandard.GapLine(5f);
+ */
+ //listingStandard.CheckboxLabeled("Use Breast Size Cap from Apparels(recommended: true)", ref SizedApparelSettings.useBreastSizeCapForApparels, "unite breast size from apparels. Smallest value will be used.\nIf you change this option, you need to redress Pawn\nDefault: true");
+
+
+ //listingStandard.BeginScrollView(rect, ref ScrollPos, ref rect);
+ //listingStandard.Label("Body(Torso)Texture Option", -1, "");
+ //listingStandard.CheckboxLabeled("use Body (Torso) Texture", ref SizedApparelSettings.useBodyTexture, "change body texture if the pawn is wearing supported apparels only.\nIt may override bodytexture you use.\nIf you use rimnudeworld, don't use this option.\nDefault: false");
+ //if (SizedApparelSettings.useBodyTexture == true)
+ //{
+ // listingStandard.CheckboxLabeled(" use unsupportedApparel Body Texture", ref SizedApparelSettings.useUnsupportedBodyTexture, "Use \"_UnsupportedApparel\" Body Texture when pawn is wearing unsupported apparel.\nIf this option is false, the body will be default texture.\nDefault: true");
+ // listingStandard.CheckboxLabeled(" Match BodyTexture To Minimum ApparelSize", ref SizedApparelSettings.matchBodyTextureToMinimumApparelSize, "Avoid Clipping When breasts bigger than supported sized apparel.\nDefault: true");
+ //
+ //}
+ listingStandard.Gap(8);
+ listingStandard.Label("Other Mod Compatibility");
+ listingStandard.Gap(8);
+ listingStandard.CheckboxLabeled(" Force ignore unsupported apparel", ref SizedApparelSettings.ForcedSupportApparel, "It may have clipping issue from unsupported parts.\nDefault: false");
+
+
+ /*
+ if(SizedApparelPatch.DubsApparelTweaksActive == true)
+ {
+ listingStandard.Label(" Dubs Apparel Tweaks Patched! (may not work in 1.3)");
+ listingStandard.Gap(8);
+ }*/
+
+ //sizeList.EndScrollView(ref rect);
+ //listingStandard.EndSection(sizeList);
+ //listingStandard.EndScrollView(ref sizeScrollRect);
+ listingStandard.Label("Non RimJobWorld Compatibility (wip)", -1, "User Who play without RimJobWorld");
+ if (!SizedApparelPatch.RJWActive)
+ {
+ if (SizedApparelPatch.SJWActive)
+ {
+ listingStandard.Label(" SafeJobWorld is Actived ", -1, "");
+ listingStandard.CheckboxLabeled(" use SafeJobWorld's Breasts(Hidden to player but it exist)", ref SizedApparelSettings.useSafeJobBreasts, "use BreastsSize from SJW.\nDefault: true");
+
+ }
+ if(SizedApparelPatch.SJWActive? SizedApparelSettings.useSafeJobBreasts==false : true)
+ {
+ listingStandard.CheckboxLabeled(" use Random Breasts Size(not yet work)", ref SizedApparelSettings.useRandomSize, "use breasts random size for pawn.\nDefault: true");
+ listingStandard.Label(" random Size Min: " + SizedApparelSettings.UnderBreastsOffset.ToString(), -1, "Defualt: 0.01");
+ SizedApparelSettings.randomSizeMin = listingStandard.Slider(SizedApparelSettings.randomSizeMin, 0f, 2f);
+ listingStandard.Label(" random Size Max: " + SizedApparelSettings.UnderBreastsOffset.ToString(), -1, "Defualt: 1.00");
+ SizedApparelSettings.randomSizeMax = listingStandard.Slider(SizedApparelSettings.randomSizeMax, SizedApparelSettings.randomSizeMin, 2f);
+
+ }
+ if (SizedApparelPatch.SJWActive == false)
+ {
+
+
+ }
+ }
+ else
+ {
+ //RimJobWorld is Actived
+ listingStandard.Label(" RimJobWorld is Actived ", -1, "");
+
+ if (SizedApparelPatch.MenstruationActive)
+ {
+ listingStandard.Label(" RJW Menstuation is Active ", -1, "");
+ }
+ else
+ {
+ listingStandard.Label(" RJW Menstuation is Not Active", -1, "");
+ }
+
+
+ }
+ listingStandard.GapLine(1);
+ listingStandard.Gap(12);
+ listingStandard.Label("AlienRace Compatibility (wip)", -1, "");
+
+ //listingStandard.CheckboxLabeled(" Unsupported race render as \"Humanlike\" ", ref SizedApparelSettings.UnsupportedRaceToUseHumanlike, "If unchecked, unsupported humanlike race will not be patched!\nIf you change this option, you need to restart rimworld or clear cache\nDefault: false");
+
+
+
+
+
+ if (SizedApparelPatch.alienRaceActive)
+ {
+ listingStandard.Label(" AlienRace is Actived ", -1, "");
+ //listingStandard.CheckboxLabeled("Force to use Human's BodyParts for unsuported Alien races", null, "");
+
+ //TODO: Allow Humanlike Settings Per Races
+ /*
+ SizedApparelSettings.alienRaces = SizedApparelsDatabase.GetAlienRacesDefNames();
+
+ listingStandard.Label("Alien Race Settings", -1f, null);
+
+ SizedApparelSettings.alienRaceSearch = listingStandard.TextEntry(SizedApparelSettings.alienRaceSearch, 1);
+ RaceSettings(new Rect(0f, 60f, 16f, 300f), SizedApparelSettings.alienRaces, ref SizedApparelSettings.alienRacesAllowHumanlikTextures, null);
+
+ listingStandard.Gap(listingStandard.verticalSpacing);
+ */
+ /*
+ Widgets.BeginScrollView(aliensRect, ref ScrollPos, leftRect);
+ List alienSettingListLoc = new List();
+ foreach(var item in SizedApparelsDatabase.AlienRaceUseHumanlike)
+ {
+ //Widgets.CheckboxLabeled(aliensRect, item.Key, ref);
+ }
+ Widgets.EndScrollView();
+ */
+ }
+ else
+ {
+ listingStandard.Label(" AlienRace is not Actived ", -1, "");
+ }
+
+ if (alienDefList.NullOrEmpty())
+ CheckAndLoadAlienRaces();
+
+ float h = alienDefList.Count * alienRaceSettingHeight;
+ Listing_Standard Race_ListingStandard = listingStandard.BeginSection(h);
+ foreach (var raceName in alienDefList)
+ {
+ Race_ListingStandard.Label(raceName);
+ Race_ListingStandard.GapLine(1f);
+ AlienRaceSetting raceSetting = null;
+ foreach (var r in SizedApparelSettings.alienRaceSettings)
+ {
+ if (r.raceName == null)
+ continue;
+ if (raceName == r.raceName)
+ {
+ raceSetting = r;
+ break;
+ }
+ }
+ if (raceSetting == null)
+ {
+ raceSetting = new AlienRaceSetting(raceName);
+
+ SizedApparelSettings.alienRaceSettings.Add(raceSetting);
+ }
+ if(raceName != "Human")
+ Race_ListingStandard.CheckboxLabeled("If Unsupported, As Human race", ref raceSetting.asHuman, "This Race will use Human race if it doesn't have own textures. useful for race that Unsupported but simillar to human");
+ Race_ListingStandard.Label((raceSetting.drawMinAge <= 100 ? "" : "[overdrive]") + "SA BodyPart Draw Min Age: " + raceSetting.drawMinAge.ToString(), -1, "Lower than this age will not use Sized Apparel. Useful for BnC. -1 for disable");
+ raceSetting.drawMinAge = Mathf.Round(Race_ListingStandard.Slider(raceSetting.drawMinAge, raceSetting.drawMinAge <= 100 ? -1: 100, raceSetting.drawMinAge >= 100 ? 1000 : 100));
+ Race_ListingStandard.Gap();
+ }
+
+ listingStandard.EndSection(Race_ListingStandard);
+ Widgets.EndScrollView();
+ //listingStandard.Gap(alienSettingHeight);
+ listingStandard.Gap(8);
+ listingStandard.GapLine(4f);
+
+ listingStandard.Gap(8);
+ listingStandard.Gap(8);
+ listingStandard.Label("RimNudeWorld Compatibility (WIP)", -1, "");
+
+ //listingStandard.CheckboxLabeled(" Don't Replace Body Texture On Nude", ref SizedApparelSettings.DontReplaceBodyTextureOnNude, "Only Replace BodyTexture On Not Nude. Trigers are Torso And Chests.\nDefault: False");
+ if (SizedApparelPatch.rimNudeWorldActive)
+ {
+ listingStandard.Label(" RimNudeWorld is On!. Please check SizedApparel's Body parts render option", -1, "disable all body parts render except the breasts. and set it to only worn option true");
+ listingStandard.CheckboxLabeled(" use Sized Apparel Breasts graphic when worn.", ref SizedApparelSettings.drawSizedApparelBreastsOnlyWorn, "use Sized Apparel's breasts render for breasts of apparel. it will be hidden when the pawn is naked and rimnudeworld will handle nude. \ndefault = true;");
+ //listingStandard.CheckboxLabeled(" Hide RimNudeWorld Breasts Addon", ref SizedApparelSettings.hideRimNudeWorldBreasts, "For User Who Use Body(Torso) Texture option, remove double drawn breasts.\nYou can use this option as only using Rimnudeworld genital and else without breasts.\nDefault: False");
+
+ if (listingStandard.ButtonTextLabeled("Easy Setting Button", "Apply Rimnude Setting"))
+ {
+ SizedApparelSettings.drawSizedApparelBreastsOnlyWorn = true;
+ SizedApparelSettings.useBodyTexture = false;
+ SizedApparelSettings.drawBreasts = true;
+ SizedApparelSettings.drawPenis = false;
+ SizedApparelSettings.drawVagina = false;
+ SizedApparelSettings.drawAnus = false;
+ SizedApparelSettings.drawBelly = false;
+ SizedApparelSettings.drawPubicHair = false;
+ }
+
+
+ if (false)//SizedApparelSettings.hideRimNudeWorldBreasts == false
+ {
+ //listingStandard.CheckboxLabeled(" match Breast Texture To Minimum ApparelSize (not work)", ref SizedApparelSettings.matchBreastTextureToMinimumApparelSize, "Avoid Clipping When breasts bigger than supported sized apparel.\nDefault: true");
+
+ //listingStandard.CheckboxLabeled(" use Under Breasts addon (RimNudeWorld)(not recomanded)", ref SizedApparelSettings.useUnderBreasts, "draw breasts under apparel.");
+ listingStandard.Label(" Under Breasts Offset: " + SizedApparelSettings.UnderBreastsOffset.ToString(), -1, "offset from defeault layer offset. Defualt: -0.0013");
+ SizedApparelSettings.UnderBreastsOffset = listingStandard.Slider(SizedApparelSettings.UnderBreastsOffset, -0.025f, 0.025f);
+ }
+ if (SizedApparelSettings.useBodyTexture)
+ {
+
+ }
+ }
+ else
+ {
+ listingStandard.Label(" RimNudeWorld is not Actived ", -1, "");
+ if (listingStandard.ButtonTextLabeled("Easy Setting Button", "Apply Non Rimnude Setting"))
+ {
+ SizedApparelSettings.drawSizedApparelBreastsOnlyWorn = false;
+ SizedApparelSettings.useBodyTexture = true;
+ SizedApparelSettings.drawBreasts = true;
+ SizedApparelSettings.drawPenis = true;
+ SizedApparelSettings.drawVagina = true;
+ SizedApparelSettings.drawAnus = true;
+ SizedApparelSettings.drawBelly = true;
+ SizedApparelSettings.drawPubicHair = true;
+ }
+ }
+ listingStandard.Gap(8);
+ listingStandard.GapLine(5f);
+ if (SizedApparelPatch.RimworldAnimationActive)
+ {
+ listingStandard.Label("RimworldAnimation (rjwAnimation) is Actived ", -1, "");
+ listingStandard.CheckboxLabeled(" Animated SizedApparel BodyParts (wip)", ref SizedApparelSettings.AnimationPatch, "this option may animated breasts jiggle during animation.\n but not copatable with rimnudeworld.\ndefault: true");
+ }
+ else
+ {
+ listingStandard.Label("RimworldAnimation (rjwAnimation) is not Actived ", -1, "");
+ }
+
+
+ listingStandard.End();
+
+
+
+
+ ////RightRect
+ scrollRect = new Rect(0, 0, rightRect.width - 30f, Math.Max(rightRect.height + 100f, 1f));
+
+ Widgets.BeginScrollView(rightRect, ref ScrollPosR, scrollRect, true);
+ rightRect = new Rect(0, 0, rightRect.width - 30f, rightRect.height + 100f + 250f);
+ listingStandard.maxOneColumn = true;
+
+ listingStandard.Begin(rightRect);
+
+ listingStandard.Label("SizedApparel System Apply (apparel and body parts)");
+ listingStandard.CheckboxLabeled(" Apply Humanlikes", ref SizedApparelSettings.ApplyHumanlikes, "Try to Apply SizedApparel to Humanlikes if The textures are valid.\nDefault: true");
+ listingStandard.CheckboxLabeled(" Apply Animals", ref SizedApparelSettings.ApplyAnimals, "Try to Apply SizedApparel to Animals if The textures are valid.\nDefault: false");
+ //TODO
+ /*
+ if (SizedApparelSettings.ApplyAnimals)
+ listingStandard.CheckboxLabeled(" Apply Player Faction Animals Only", ref SizedApparelSettings.ApplyAnimalsPlayerFactionOnly, "Default: true");
+ */
+ listingStandard.CheckboxLabeled(" Apply Mechanoid", ref SizedApparelSettings.ApplyMechanoid, "Try to Apply SizedApparel to Mech if The textures are valid.\nDefault: true");
+ listingStandard.GapLine(5f);
+
+ listingStandard.Label("Apparel Patch (Breasts Sized Apparel)");
+ listingStandard.CheckboxLabeled(" Apply Apparel Patch for Male", ref SizedApparelSettings.ApplyApparelPatchForMale, "It Skips breasts size test for male. Do you need man with breasts...? may be not.\nDefault: false");
+ listingStandard.GapLine(5f);
+
+ listingStandard.Label("If you changed the option, try change apparels or reload save", -1);
+ listingStandard.Label("Body Part Render Option (wip)",-1,"standalone BodyPart Render System from this mod. It's for user who don't use RimNudeWorld\nIf you use RimNudeWorld, you should turn off this.");
+
+ listingStandard.CheckboxLabeled("Use Gender Specific Textures.", ref SizedApparelSettings.useGenderSpecificTexture,"Use Gender Specific texture for body and apparel if it's valid. \nDefault: true");
+ listingStandard.GapLine(5);
+ listingStandard.CheckboxLabeled("Draw Body Parts", ref SizedApparelSettings.drawBodyParts, "Draw Breasts..etc. when the pawn is wearing supported apparels. \nDefault: true");
+ if (SizedApparelSettings.drawBodyParts)
+ {
+ listingStandard.CheckboxLabeled(" Use (Sized Apparel) Base Body Texture", ref SizedApparelSettings.useBodyTexture, "change pawn's body texture when the pawn is wearing supported apparels. Recommanded\nDefault: true");
+
+ //listingStandard.CheckboxLabeled(" Draw Muscle Overlay (wip)", ref SizedApparelSettings.drawMuscleOverlay, "\nDisable this option when you use RimNudeWorld");
+
+ listingStandard.CheckboxLabeled(" Draw Breasts", ref SizedApparelSettings.drawBreasts, "this option is why this mod exist.\nDefault: true");
+ if (SizedApparelSettings.drawBreasts)
+ {
+ listingStandard.CheckboxLabeled(" Match Breasts size to supported apparels",ref SizedApparelSettings.matchBreastToSupportedApparelSize, "to avoid breasts clipping(when breasts are bigger), you need this option.\nDefault: true");
+ listingStandard.CheckboxLabeled(" draw Breasts on worn pawn only (RimNudeWorld)", ref SizedApparelSettings.drawSizedApparelBreastsOnlyWorn, "when the pawn is nude, the breasts graphic for sized apparel will be hidden. \nDefault: false" );
+ listingStandard.CheckboxLabeled(" (Wip) Breasts Physics", ref SizedApparelSettings.breastsPhysics, "Breasts can be jiggled (for now. it works when nude only). It may be heavy for performance. \n Won't work with RimNudeWorld Breasts Rendering. \ndefault = false");
+ }
+ listingStandard.CheckboxLabeled(" Draw Penis", ref SizedApparelSettings.drawPenis,"Disable this option when you use RimNudeWorld");
+ listingStandard.CheckboxLabeled(" Draw Vagina", ref SizedApparelSettings.drawVagina, "Disable this option when you use RimNudeWorld");
+ listingStandard.CheckboxLabeled(" Draw Anus", ref SizedApparelSettings.drawAnus, "Disable this option when you use RimNudeWorld");
+ listingStandard.CheckboxLabeled(" Draw Belly Buldge", ref SizedApparelSettings.drawBelly, "Disable this option when you use RimNudeWorld");
+
+ listingStandard.CheckboxLabeled(" Draw Pubic Hair", ref SizedApparelSettings.drawPubicHair, "Disable this option when you use RimNudeWorld");
+
+ listingStandard.CheckboxLabeled(" Hide Balls of Futa", ref SizedApparelSettings.hideBallOfFuta, "Hide Balls from penis of Futa.\nDefault: false");
+ listingStandard.CheckboxLabeled(" Hide Penis of Man(Not Work yet)", ref SizedApparelSettings.hidePenisOfMale, "this option is for someone who really hate to see male's dick around.\nDefault: false");
+
+ //listingStandard.Gap();
+ //listingStandard.CheckboxLabeled(" Use Body Part Variation", ref SizedApparelSettings.useBodyPartsVariation, "Use graphic variation such as inverted nipple.\nDefault: true");
+ //listingStandard.CheckboxLabeled(" Show Body Part Variaion Button(WIP)", ref SizedApparelSettings.showBodyPartsVariationIcon, "WIP. Not work for now.\nDefault: true");
+
+ listingStandard.Gap();
+ //listingStandard.CheckboxLabeled(" Use BodyPart Variation", ref SizedApparelSettings.useBodyPartsVariation, ""); //TODO
+ listingStandard.CheckboxLabeled(" Show BodyPart Variation Description", ref SizedApparelSettings.showBodyPartsVariation, "Show more info in bodyparts that sized apparel added. such as inverted nipple");
+ }
+ /*
+ listingStandard.Gap(4);
+ listingStandard.Label("Breast Size Toggle Option", -1, "default option is setted for RimnudeWorld. you should not change this unless you have the textures for that size.");
+ listingStandard.Gap(4);
+ //Rect sizeScrollRect = new Rect(inRect.position+ new Vector2(0, listingStandard.CurHeight), inRect.size/3);
+ //Vector2 sizeScrollPosition = new Vector2(0.9f, 0.5f);
+ //listingStandard.BeginScrollView(sizeScrollRect, ref sizeScrollPosition, ref sizeScrollRect);
+ //Listing_Standard sizeList = listingStandard.BeginSection_NewTemp(150);
+
+ //sizeList.BeginScrollView(rect, ref ScrollPos, ref rect);
+
+ listingStandard.CheckboxLabeled(" use Nipples", ref SizedApparelSettings.useNipples, "use Nipples(Flat breasts) Sized Apparel.\nDefault: true");
+ listingStandard.CheckboxLabeled(" use Tiny", ref SizedApparelSettings.useTiny, "use Tiny breasts Sized Apparel.\nDefault: true");
+ listingStandard.CheckboxLabeled(" use Small", ref SizedApparelSettings.useSmall, "use Small breasts Sized Apparel.\nDefault: true");
+ listingStandard.CheckboxLabeled(" use Average", ref SizedApparelSettings.useAverage, "use Average breasts Sized Apparel.\nDefault: true");
+ listingStandard.CheckboxLabeled(" use Large", ref SizedApparelSettings.useLarge, "use Large breasts Sized Apparel.\nDefault: true");
+ listingStandard.CheckboxLabeled(" use Huge", ref SizedApparelSettings.useHuge, "use Huge breasts Sized Apparel.\nDefault: true");
+ listingStandard.CheckboxLabeled(" use Enormous", ref SizedApparelSettings.useEnormous, "use Enormous breasts Sized Apparel.\nDefault: true");
+ listingStandard.CheckboxLabeled(" use Massive", ref SizedApparelSettings.useMassive, "use Massive breasts Sized Apparel.\nDefault: true");
+ listingStandard.CheckboxLabeled(" use Gargantuan", ref SizedApparelSettings.useGargantuan, "use Gargantuan breasts Sized Apparel.\nDefault: true");
+ listingStandard.CheckboxLabeled(" use Colossal", ref SizedApparelSettings.useColossal, "use Colossal breasts Sized Apparel.\nDefault: true");
+ listingStandard.CheckboxLabeled(" use Titanic", ref SizedApparelSettings.useTitanic, "use Titanic breasts Sized Apparel.\nDefault: true");
+ */
+ Widgets.EndScrollView();
+ listingStandard.End();
+
+ //listingStandard.EndScrollView(ref rect);
+ base.DoSettingsWindowContents(inRect);
+ }
+
+ public override string SettingsCategory()
+ {
+ return "Sized Apparel for RJW";
+ }
+
+
+
+
+
+
+ //copy from BnC
+ public static bool Contai(string source, string toCheck, StringComparison comp)
+ {
+ return source != null && source.IndexOf(toCheck, comp) >= 0;
+ }
+ //copy from BnC
+ public static void RaceSettings(Rect rect, List label, ref List alienRacesToAllowHumanlikes, string tooltip = null)
+ {
+ bool flag = !GenText.NullOrEmpty(tooltip);
+ if (flag)
+ {
+ bool flag2 = Mouse.IsOver(rect);
+ if (flag2)
+ {
+ Widgets.DrawHighlight(rect);
+ }
+ TooltipHandler.TipRegion(rect, tooltip);
+ }
+ bool flag3 = GenList.NullOrEmpty(alienRacesToAllowHumanlikes);
+ if (flag3)
+ {
+ alienRacesToAllowHumanlikes = new List();
+ }
+ Listing_Standard listing_Standard = new Listing_Standard();
+ Rect rect2 = rect;
+ Rect rect3 = rect;
+ rect3.height = (float)label.Count * 30f;
+ rect3.width -= 16f;
+ Widgets.BeginScrollView(rect2, ref SizedApparelSettings.alienRacesListScrollPos, rect3, true);
+ listing_Standard.Begin(rect3);
+ for (int i = 0; i < SizedApparelSettings.alienRaces.Count; i++)
+ {
+ bool flag4 = GenList.NullOrEmpty(alienRacesToAllowHumanlikes) || !alienRacesToAllowHumanlikes.Contains(label[i]);
+ bool flag5 = SizedApparelSettings.alienRaceSearch == null || Contai(SizedApparelSettings.alienRaces[i], SizedApparelSettings.alienRaceSearch.ToLower(), StringComparison.OrdinalIgnoreCase);
+ if (flag5)
+ {
+ WidgetRow widgetRow = new WidgetRow(rect.x,listing_Standard.CurHeight, UIDirection.RightThenUp, 99999f, 1f);
+ widgetRow.Label(label[i], rect.width * 0.8f, null, -1f);
+
+
+ bool flag6 = label[i] != "Human";
+ if (flag6)
+ {
+ widgetRow.ToggleableIcon(ref flag4, TexButton.IconBook, "Use Shared Body Parts texture (\"Humanlike\" body plarts).\nIf Unchecked, the race will use race's owned texture. \n If the race not have supported textures, try this option.", null, null);
+ }
+ else
+ {
+ //TODO: should I let human can use humanlike textures?
+ widgetRow.Icon(TexButton.IconBook, "Human Race is forced to use \"Human\" Textures. not \"Humanlike\"");
+ }
+
+
+ /*
+ bool flag7 = widgetRow.ButtonIcon(TexButton.ToggleTweak, "Allow Humanlike Body parts rendering from Sized Apparel(NOT RIMNUDE!)", null, null, null, true, -1f);
+ if (flag7)
+ {
+ bool flag8 = Current.Game != null;
+ if (flag8)
+ {
+ bool flag9 = !Find.WindowStack.TryRemove(typeof(RaceEditorWindow), true);
+ if (flag9)
+ {
+ RaceSettings sizeSettings = RaceUtility.GetSizeSettings(DefDatabase.GetNamed(label[i], false));
+ RaceEditorWindow raceEditorWindow = new RaceEditorWindow();
+ raceEditorWindow.alienRace = DefDatabase.GetNamed(label[i], true);
+ bool flag10 = sizeSettings != null;
+ if (flag10)
+ {
+ raceEditorWindow.raceSettings = sizeSettings;
+ raceEditorWindow.headOffset = sizeSettings.headOffset;
+ raceEditorWindow.sizeModifier = sizeSettings.sizeModifier;
+ raceEditorWindow.hairSizeModifier = sizeSettings.hairSizeModifier;
+ raceEditorWindow.headSizeModifier = sizeSettings.headSizeModifier;
+ raceEditorWindow.scaleChild = sizeSettings.scaleChild;
+ raceEditorWindow.scaleTeen = sizeSettings.scaleTeen;
+ }
+ Find.WindowStack.Add(raceEditorWindow);
+ }
+ }
+ else
+ {
+ Messages.Message("You need to be in-game to open size editor", MessageTypeDefOf.RejectInput, true);
+ }
+ }
+ */
+ bool flag11 = !flag4;
+ if (flag11)
+ {
+ bool flag12 = !alienRacesToAllowHumanlikes.Contains(label[i]);
+ if (flag12)
+ {
+ alienRacesToAllowHumanlikes.Add(label[i]);
+ }
+ }
+ else
+ {
+ bool flag13 = alienRacesToAllowHumanlikes.Contains(label[i]);
+ if (flag13)
+ {
+ alienRacesToAllowHumanlikes.Remove(label[i]);
+ }
+ }
+ listing_Standard.Gap(30f);
+ }
+ }
+ listing_Standard.End();
+ Widgets.EndScrollView();
+ }
+ }
+
+}
diff --git a/1.3/source/SizedApparel/SizedApparelStyleStationPatch.cs b/1.3/source/SizedApparel/SizedApparelStyleStationPatch.cs
new file mode 100644
index 0000000..5964db0
--- /dev/null
+++ b/1.3/source/SizedApparel/SizedApparelStyleStationPatch.cs
@@ -0,0 +1,298 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using RimWorld;
+using Verse;
+using Verse.Sound;
+using HarmonyLib;
+using UnityEngine;
+using rjw;
+using System.Reflection;
+using System.Reflection.Emit;
+
+namespace SizedApparel
+{
+
+ [HarmonyPatch(typeof(Dialog_StylingStation), "DrawTabs")]
+ public class SizedApparelStyleStationDrawTabsPatch
+ {
+ public static void Postfix(Rect rect, ref Vector2 ___hairScrollPosition, Dialog_StylingStation __instance, List ___tabs, Dialog_StylingStation.StylingTab ___curTab, float ___viewRectHeight, ref List ___tmpStyleItems, bool ___devEditMode, Pawn ___pawn, Color ___desiredHairColor)
+ {
+
+ if (!SizedApparelSettings.drawPubicHair)
+ return;
+
+
+ //Widgets.DrawMenuSection(rect);
+ //TabDrawer.DrawTabs(rect, ___tabs, 200f);
+ //rect = rect.ContractedBy(18f);
+ switch (___curTab)
+ {
+ case (Dialog_StylingStation.StylingTab)24:
+
+ //Draw PubicHair Tab Code here!
+ //rect.yMax -= ___colorsHeight;
+ DrawStylingTypePubicHair(ref __instance, ref ___viewRectHeight, ref ___tmpStyleItems, ___devEditMode, ___pawn, ___desiredHairColor, rect, ref ___hairScrollPosition, delegate (Rect r, PubicHairDef h)
+ {
+ GUI.color = ___desiredHairColor;
+ Widgets.DefIcon(r, h, null, 1.25f, null, false, null);
+ //Widgets.DrawTextureFitted(r, h.Icon, 1.25f, null);
+ GUI.color = Color.white;
+ }, delegate (PubicHairDef h)
+ {
+ ___pawn.GetComp().pubicHairDef = h;
+ //___pawn.story.hairDef = h;
+ }, (StyleItemDef h) => ___pawn.GetComp().pubicHairDef == h, (StyleItemDef h) => ___pawn.GetComp().initialPubicHairDef == h, null, false);
+
+ return;
+ default:
+ return;
+ }
+ }
+
+ //Some Copy Code from Rimnudeworld
+ //maybe Some Var has to be ref
+ static void DrawStylingTypePubicHair(ref Dialog_StylingStation dialog_StylingStation, ref float viewRectHeight, ref List tmpStyleItems, bool devEditMode, Pawn pawn, Color desiredHairColor, Rect rect, ref Vector2 scrollPosition, Action drawAction, Action selectAction, Func hasStyleItem, Func hadStyleItem, Func extraValidator = null, bool doColors = false)
+ {
+
+ //Color desiredHairColor = AccessTools.FieldRefAccess(dialog_StylingStation, "desiredHairColor");
+
+ int total_pubes_count = 0;
+ total_pubes_count = DefDatabase.AllDefs.Count();
+
+ //need child patch?
+ if (total_pubes_count <= 0)
+ {
+ Widgets.NoneLabelCenteredVertically(rect, "(" + "NoneUsableForPawn".Translate(pawn.Named("PAWN")) + ")");
+ return;
+ }
+
+ ApparelRecorderComp comp = pawn.GetComp();
+
+
+
+ Rect viewRect = new Rect(rect.x, rect.y, rect.width - 16f, viewRectHeight);
+ int num = Mathf.FloorToInt(viewRect.width / 60f) - 1;
+ float num2 = (viewRect.width - (float)num * 60f - (float)(num - 1) * 10f) / 2f;
+ int num3 = 0;
+ int num4 = 0;
+ int num5 = 0;
+ tmpStyleItems.Clear();
+ /*
+ tmpStyleItems.AddRange(from x in DefDatabase.AllDefs
+ where (devEditMode || PawnStyleItemChooser.WantsToUseStyle(pawn, x, null) || hadStyleItem(x)) && (extraValidator == null || extraValidator(x))
+ select x);*/
+ tmpStyleItems.AddRange(DefDatabase.AllDefs);// just add All Pubic Hair def.
+
+ tmpStyleItems.SortBy((StyleItemDef x) => -PawnStyleItemChooser.StyleItemChoiceLikelihoodFor(x, pawn));
+ if (tmpStyleItems.NullOrEmpty())
+ {
+ Widgets.NoneLabelCenteredVertically(rect, "(" + "NoneUsableForPawn".Translate(pawn.Named("PAWN")) + ")");
+ }
+ else
+ {
+ Widgets.BeginScrollView(rect, ref scrollPosition, viewRect, true);
+ foreach (StyleItemDef styleItemDef in tmpStyleItems)
+ {
+ if (num5 >= num - 1)
+ {
+ num5 = 0;
+ num4++;
+ }
+ else if (num3 > 0)
+ {
+ num5++;
+ }
+ Rect rect2 = new Rect(rect.x + num2 + (float)num5 * 60f + (float)num5 * 10f, rect.y + (float)num4 * 60f + (float)num4 * 10f, 60f, 60f);
+ Widgets.DrawHighlight(rect2);
+ if (Mouse.IsOver(rect2))
+ {
+ Widgets.DrawHighlight(rect2);
+ TooltipHandler.TipRegion(rect2, styleItemDef.LabelCap);
+ }
+ if (drawAction != null)
+ {
+ drawAction(rect2, styleItemDef as PubicHairDef);
+ }
+ if (hasStyleItem(styleItemDef))
+ {
+ Widgets.DrawBox(rect2, 2, null);
+ }
+ if (Widgets.ButtonInvisible(rect2, true))
+ {
+ if (selectAction != null)
+ {
+ selectAction(styleItemDef as PubicHairDef);
+ }
+ SoundDefOf.Tick_High.PlayOneShotOnCamera(null);
+ pawn.Drawer.renderer.graphics.SetAllGraphicsDirty();
+ PortraitsCache.SetDirty(pawn);
+ }
+ num3++;
+ }
+ if (Event.current.type == EventType.Layout)
+ {
+ viewRectHeight = (float)(num4 + 1) * 60f + (float)num4 * 10f + 10f;
+ }
+ Widgets.EndScrollView();
+ }
+ if (doColors)
+ {
+ //dialog_StylingStation.DrawHairColors(new Rect(rect.x, rect.yMax + 10f, rect.width, dialog_StylingStation.colorsHeight));
+
+ //Copy From RimnudeWorld
+
+
+ /*
+ Rect newrect = new Rect(rect.x, rect.yMax - 10f, rect.width, colorsHeight);
+
+ Color _desiredHairColor = desiredHairColor;
+
+ float numC = newrect.y;
+ float height;
+ Widgets.ColorSelector(new Rect(newrect.x, numC, newrect.width, 92f), ref _desiredHairColor, AllHairColors, null, 22, 2);
+ if (_desiredHairColor != desiredHairColor)
+ {
+ var desiredHairColor_ = dialog_StylingStation.GetType().GetField("desiredHairColor", System.Reflection.BindingFlags.NonPublic
+ | System.Reflection.BindingFlags.Instance);
+ desiredHairColor_.SetValue(dialog_StylingStation, _desiredHairColor);
+ }
+ numC += 60f;
+ if (desiredHairColor != pawn.story.hairColor && desiredHairColor != pawn.style.nextHairColor)
+ {
+ Widgets.ThingIcon(new Rect(newrect.x, numC, Text.LineHeight, Text.LineHeight), ThingDefOf.Dye, null, null, 1.1f, null);
+ string text = "Required".Translate() + ": 1 " + ThingDefOf.Dye.label;
+ float x = Text.CalcSize(text).x;
+ Widgets.Label(new Rect(newrect.x + Text.LineHeight + 4f, numC, x, Text.LineHeight), text);
+ Rect rect2 = new Rect(newrect.x, numC, x + Text.LineHeight + 8f, Text.LineHeight);
+ if (Mouse.IsOver(rect2))
+ {
+ Widgets.DrawHighlight(rect2);
+ TooltipHandler.TipRegionByKey(rect2, "TooltipDyeExplanation");
+ }
+ numC += Text.LineHeight;
+
+ if (pawn.Map.resourceCounter.GetCount(ThingDefOf.Dye) < 1)
+ {
+ rect2 = new Rect(newrect.x, numC, newrect.width, Text.LineHeight);
+ Color color = GUI.color;
+ GUI.color = ColorLibrary.RedReadable;
+ Widgets.Label(rect2, "NotEnoughDye".Translate() + " " + "NotEnoughDyeWillRecolorHair".Translate());
+ GUI.color = color;
+ numC += rect2.height;
+ }
+ }*/
+ }
+
+ }
+ private static List allHairColors;
+ private static List AllHairColors
+ {
+ get
+ {
+ if (allHairColors == null)
+ {
+ allHairColors = (from ic in DefDatabase.AllDefsListForReading
+ select ic.color).ToList();
+ allHairColors.SortByColor((Color x) => x);
+ }
+ return allHairColors;
+ }
+ }
+
+
+ static void AddPubicHairTab(Dialog_StylingStation stylingStation, List tabs)
+ {
+ if (!SizedApparelSettings.drawPubicHair)
+ return;
+
+ var curTabField = AccessTools.Field(typeof(Dialog_StylingStation), "curTab");
+ tabs.Add(new TabRecord("PubicHair".Translate().CapitalizeFirst(), delegate ()
+ {
+
+ curTabField.SetValue(stylingStation, (Dialog_StylingStation.StylingTab)24);
+ }, (Dialog_StylingStation.StylingTab)curTabField.GetValue(stylingStation) == (Dialog_StylingStation.StylingTab)24));
+ }
+
+ static IEnumerable Transpiler(IEnumerable instructions)
+ {
+ bool isHair = false;
+ MethodInfo tabAdd = AccessTools.DeclaredMethod(typeof(List),"Add");
+ foreach (var instruction in instructions)
+ {
+ if(instruction.opcode == OpCodes.Ldstr)
+ {
+ if (instruction.OperandIs("Hair"))
+ isHair = true;
+ else
+ isHair = false;
+ }
+
+
+ if (isHair && instruction.opcode == OpCodes.Callvirt && instruction.OperandIs(tabAdd))
+ {
+ yield return instruction;//finish add hairTab
+
+ yield return new CodeInstruction(OpCodes.Ldarg_0);
+ yield return new CodeInstruction(OpCodes.Ldarg_0);
+ //Log.Message("this");
+ yield return new CodeInstruction(OpCodes.Ldfld, AccessTools.DeclaredField(typeof(Dialog_StylingStation),"tabs"));
+ //Log.Message("tabs");
+ //yield return new CodeInstruction(OpCodes.Ldarg_0);
+ //Log.Message("this");
+ //yield return new CodeInstruction(OpCodes.Ldfld, AccessTools.DeclaredField(typeof(Dialog_StylingStation), "curTab"));
+ //Log.Message("curtab");
+ yield return new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(SizedApparelStyleStationDrawTabsPatch), "AddPubicHairTab"));
+ //Log.Message("call");
+ //yield return new CodeInstruction(OpCodes.Ldarg_0);
+
+ //yield return new CodeInstruction(OpCodes.Ldarg_0);
+ //yield return new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(Dialog_StylingStation), "tabs"));
+ //yield return new CodeInstruction(OpCodes.Ldstr,"PubicHair".Translate().CapitalizeFirst());
+
+ //yield return new CodeInstruction(OpCodes.Ldarg_0);
+ //yield return new CodeInstruction(OpCodes.Ldarg_0);
+
+
+
+
+ isHair = false;
+ }
+ else
+ yield return instruction;
+
+ }
+ yield break;
+ }
+ }
+
+ [HarmonyPatch(typeof(Dialog_StylingStation), "Reset")]
+ public class SizedApparelStyleStationResetPatch
+ {
+ public static void Prefix(Pawn ___pawn)
+ {
+ ApparelRecorderComp comp = ___pawn.GetComp();
+
+ //this.pawn.story.hairDef = this.initialHairDef;
+ comp.pubicHairDef = comp.initialPubicHairDef;
+ comp.initialPubicHairDef = null;
+ }
+ }
+
+ //Patching Constructors
+ [HarmonyPatch(typeof(Dialog_StylingStation), MethodType.Constructor, new Type[] { typeof(Pawn), typeof(Thing) })]
+ public class SizedApparelDialogStylingStationPatch
+ {
+ public static void Postfix(Pawn pawn)
+ {
+ var comp = pawn.GetComp();
+ if (comp == null)
+ return;
+ comp.initialPubicHairDef = comp.pubicHairDef;
+ }
+ }
+
+}
+
diff --git a/1.3/source/SizedApparel/SizedApparelTexturePointDef.cs b/1.3/source/SizedApparel/SizedApparelTexturePointDef.cs
new file mode 100644
index 0000000..f36b5b1
--- /dev/null
+++ b/1.3/source/SizedApparel/SizedApparelTexturePointDef.cs
@@ -0,0 +1,30 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Verse;
+
+namespace SizedApparel
+{
+ //Consider Graphic and Graphic_Multi(Graphic with Facing such as south)
+ public class SizedApparelTexturePointDef : Def
+ {
+ //Path must be texture file name with path
+ //Path example: "Things/Pawn/Humanlike/Bodies/Naked_Female_BaseBody"
+ //Facing Text such as "_south" must not be included.
+ //Use "/" instead of "\"
+
+ public string Path;
+
+ public List SouthBodyPartPoints = new List();
+ public List NorthBodyPartPoints = new List();
+ public List EastBodyPartPoints = new List();
+
+ //can be null. then use EastBodyPartPoints
+ public List WestBodyPartPoints = new List();
+
+
+
+ }
+}
diff --git a/1.3/source/SizedApparel/SizedApparelUtility.cs b/1.3/source/SizedApparel/SizedApparelUtility.cs
new file mode 100644
index 0000000..4bc05cc
--- /dev/null
+++ b/1.3/source/SizedApparel/SizedApparelUtility.cs
@@ -0,0 +1,2130 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using RimWorld;
+using Verse;
+using HarmonyLib;
+using UnityEngine;
+using rjw;
+
+namespace SizedApparel
+{
+ public static class SizedApparelUtility
+ {
+ //DefName, BodyTypeName, targetTextureInt(index is breasts hediff)
+ //static Dictionary>> sizedApparelSupportCache = new Dictionary>>();
+
+
+ //those breasts size codes are hard coded. maybe some days, It needs to be fixed
+ public static string chestString = "Chest";
+ public static string breastsString = "Breasts";
+
+ static string Titanic = "_10";
+ static string Colossal = "_9";
+ static string Gargantuan = "_8";
+ static string Massive = "_7";
+ static string Enormous = "_6";
+ static string Huge = "_5";
+ static string Large = "_4";
+ static string Average = "_3";
+ static string Small = "_2";
+ static string Tiny = "_1";
+ static string Nipples = "_0";
+ //static String[] size = new string[10] { "_0", "_1", "_2", "_3", "_4", "_5" , "_6", "_7", "_8", "_9"};
+ public static string[] breastsSizeStrings = new string[11] { Nipples, Tiny, Small, Average, Large, Huge, Enormous, Massive, Gargantuan, Colossal, Titanic };
+ public static string[] commonSizeStrings = new string[6] { Nipples, Tiny, Small, Average, Large, Huge};
+
+ [Obsolete]
+ public static int findAvailableSmallerSizeFromSetting(int current)
+ {
+
+ int target = current;
+ target = Math.Min(target, breastsSizeStrings.Length - 1);
+ while (target > 0)
+ {
+ if (SizedApparelSettings.getUseSettingFromIndex(target) == false)
+ target--;
+ else
+ break;
+ }
+ return target;
+ }
+ [Obsolete]
+ public static int findAvailableBiggerSizeFromSetting(int current)
+ {
+
+ int target = current;
+
+ while (target < breastsSizeStrings.Length)
+ {
+ if (SizedApparelSettings.getUseSettingFromIndex(target) == false)
+ target++;
+ else
+ break;
+ }
+ target = Math.Min(target, breastsSizeStrings.Length - 1);
+ return target;
+ }
+ [Obsolete]
+ public static int findAvailableSizeFromSetting(int current, bool findBigger)
+ {
+ if (findBigger)
+ return findAvailableBiggerSizeFromSetting(current);
+ else
+ return findAvailableSmallerSizeFromSetting(current);
+ }
+
+
+ public static bool GetBreastSeverity(Pawn pawn, out float BreastSeverity, out Hediff breastHediff)
+ {
+
+ //string breastsString =
+ ;
+ float _breastSeverity = -1;
+ Hediff _breastHediff = null;
+ bool result = false;
+
+ if (SizedApparelPatch.RJWActive || (SizedApparelPatch.SJWActive&&SizedApparelSettings.useSafeJobBreasts))
+ {
+ //__instance.pawn.health.hediffSet.HasHediff(Hediff ,BodyPartRecord ,false);
+ //__instance.pawn.health.hediffSet.GetNotMissingParts(BodyPartHeight.Undefined, BodyPartDepth.Undefined, null, null).Any((BodyPartRecord bpr) => bpr.untranslatedCustomLabel == label || bpr.def.defName == label);
+
+ //--------------------------------------------------------------------------------------------------
+ /*
+ foreach (Hediff hediff in pawn.health.hediffSet.hediffs)
+ {
+ if (hediff != null)
+ {
+
+ if (hediff.Part != null)
+ {
+
+ if (hediff.Part.def.defName.Equals(chestString))
+ {
+ if (hediff.def.defName.EndsWith(breastsString))
+ {
+ //Log.Message("Found Breast Hediff");
+ _breastSeverity = hediff.Severity;
+ _breastHediff = hediff;
+ result = true;
+ //Log.Message(_breastSeverity.ToString());
+ }
+ }
+ }
+ }
+ }*/
+ var breastList = Genital_Helper.get_PartsHediffList(pawn, Genital_Helper.get_breastsBPR(pawn));
+ Hediff hediff = null;
+ if(!breastList.NullOrEmpty())
+ hediff = breastList.FirstOrDefault((Hediff h) => h.def.defName.ToLower().Contains("breast"));
+ if(hediff != null)
+ {
+ _breastSeverity = hediff.Severity;
+ _breastHediff = hediff;
+ result = true;
+ }
+ }//Find Breasts in chest
+ if(SizedApparelSettings.Debug)
+ Log.Message("[Sized Apparel]" + pawn.Name + "'s breasts severity: " + _breastSeverity.ToString());
+ BreastSeverity = _breastSeverity;
+ breastHediff = _breastHediff;
+ return result;
+
+ }
+ public static Graphic GetSizedApparelGraphic(Graphic sourceGraphic, float breastSeverity, string wearerDefName = null, string breastHediff = null, string customPose = null, Gender gender = Gender.None)
+ {
+ int currentBreastSizeIndex = -1;
+ float currentBreastSeverity = -1;
+ string s;
+ bool flag = false;
+ return GetSizedApparelGraphic(sourceGraphic, breastSeverity, out currentBreastSizeIndex, out currentBreastSeverity, out flag, out s, wearerDefName, breastHediff, customPose, gender);
+ }
+
+ public static Graphic GetSizedApparelGraphic(Graphic sourceGraphic, float breastSeverity , out int indexOut, out float severityOut, out bool result, out string hediffResult, string wearerDefName = null, string breastHediffName = null, string customPose = null, Gender gender = Gender.None)
+ {
+ indexOut = -1;
+ severityOut = -1;
+ result = false;
+ hediffResult = null;
+
+ if (sourceGraphic == null)
+ {
+ return null;
+ }
+
+
+ string path;
+ string extraPath = null;
+ string raceExtraPath = null;
+ string racePath = null;
+
+
+
+
+ //path = agr.sourceApparel.def.apparel.wornGraphicPath + "_" + __instance.pawn.story.bodyType.defName;
+ path = sourceGraphic.path;
+
+ if (customPose != null)
+ {
+ path = path.Insert(Math.Max(path.LastIndexOf('/'), 0), "/CustomPose/"+ customPose);
+ }
+
+ string genderSting;
+ if (gender == Gender.Female)
+ {
+ genderSting = "F";
+ }
+ if (gender == Gender.Male)
+ {
+ genderSting = "M";
+ }
+ else
+ genderSting = string.Empty;
+
+ path = path + genderSting;
+
+ if (wearerDefName != null)
+ racePath = path + "_" + wearerDefName;
+ if (breastHediffName != null)
+ {
+ extraPath = path + "_" + breastHediffName;
+ if (wearerDefName != null)
+ raceExtraPath = path + "_" + wearerDefName + "_" + breastHediffName;
+ }
+
+
+
+
+
+
+ int offset = 0;
+ //int offsetLimit = 10;
+
+
+ bool validTexture = false;
+ Graphic graphic = null;
+ bool findBigger = true; // if false : search smaller first
+ string pathString = "";
+ while (offset < SizedApparelUtility.breastsSizeStrings.Length)
+ {
+ if (breastHediffName != null)
+ {
+ if(raceExtraPath != null)
+ {
+ pathString = raceExtraPath + SizedApparelUtility.BreastSeverityString(breastSeverity, offset, findBigger, ref indexOut, ref severityOut);
+ if (ContentFinder.Get((pathString + "_south"), false) != null) // checking special texture like udder
+ {
+ if (SizedApparelSettings.Debug && SizedApparelSettings.DetailLog)
+ Log.Message("[Sized Apparel] (" + pathString + ")apparel texture is found");
+ graphic = GraphicDatabase.Get