├── .editorconfig
├── .gitattributes
├── .gitignore
├── README.md
├── RimHUD.sln
└── source
├── -
├── About
│ ├── About.xml
│ ├── Preview.png
│ └── PublishedFileId.txt
├── Languages
│ └── English
│ │ └── Keyed
│ │ ├── Base.xml
│ │ ├── Integration.xml
│ │ ├── Interface.xml
│ │ ├── Layout.xml
│ │ ├── Model.xml
│ │ └── Theme.xml
├── Legacy
│ ├── 1.1-1.2
│ │ ├── Assemblies
│ │ │ └── RimHUD.dll
│ │ ├── Languages
│ │ │ └── English
│ │ │ │ └── Keyed
│ │ │ │ ├── Base.xml
│ │ │ │ ├── Integration.xml
│ │ │ │ ├── Model.xml
│ │ │ │ └── Theme.xml
│ │ ├── Presets
│ │ │ └── Dubs Bad Hygiene.xml
│ │ └── Textures
│ │ │ └── RimHUD
│ │ │ ├── ConfigIcon.png
│ │ │ ├── SelfTendOffIcon.png
│ │ │ ├── SelfTendOnIcon.png
│ │ │ └── ToggleIcon.png
│ ├── 1.3
│ │ ├── Assemblies
│ │ │ └── RimHUD.dll
│ │ ├── Languages
│ │ │ └── English
│ │ │ │ └── Keyed
│ │ │ │ ├── Base.xml
│ │ │ │ ├── Integration.xml
│ │ │ │ ├── Model.xml
│ │ │ │ └── Theme.xml
│ │ ├── Presets
│ │ │ ├── Dubs Bad Hygiene - Thirst.xml
│ │ │ └── Dubs Bad Hygiene.xml
│ │ └── Textures
│ │ │ └── RimHUD
│ │ │ ├── ConfigIcon.png
│ │ │ ├── SelfTendOffIcon.png
│ │ │ ├── SelfTendOnIcon.png
│ │ │ └── ToggleIcon.png
│ └── 1.4
│ │ └── Assemblies
│ │ └── RimHUD.dll
├── LoadFolders.xml
├── Presets
│ ├── Dubs Bad Hygiene + Thirst.xml
│ └── Dubs Bad Hygiene.xml
├── README.md
└── Textures
│ └── RimHUD
│ ├── ConfigIcon.png
│ ├── SelfTendOffIcon.png
│ ├── SelfTendOnIcon.png
│ ├── ToggleIcon.png
│ └── TutorialConfigIcon.png
├── Access
├── Defs.cs
├── Patch
│ ├── RimWorld_ITab_PaneTopY.cs
│ ├── RimWorld_InspectPaneUtility_DoTabs.cs
│ ├── RimWorld_InspectPaneUtility_InspectPaneOnGUI.cs
│ ├── RimWorld_InspectPaneUtility_PaneSizeFor.cs
│ ├── RimWorld_InspectPaneUtility_PaneWidthFor.cs
│ ├── RimWorld_MainTabWindow_Inspect_PaneTopY.cs
│ ├── RimWorld_PlaySettings_DoPlaySettingsGlobalControls.cs
│ ├── RimWorld_Tutor_TutorOnGUI.cs
│ ├── Verse_ActiveTip_DrawInner.cs
│ ├── Verse_ActiveTip_TipRect.cs
│ ├── Verse_Game_FinalizeInit.cs
│ ├── Verse_LetterStack_LettersOnGUI.cs
│ ├── Verse_MapInterface_MapInterfaceOnGUI_AfterMainTabs.cs
│ ├── Verse_MapInterface_Notify_SwitchedMap.cs
│ └── Verse_Profile_MemoryUtility_ClearAllMapsAndWorld.cs
└── Reflection.cs
├── Configuration
├── Persistent.cs
├── Presets.cs
├── Settings
│ ├── BaseSetting.cs
│ ├── BoolSetting.cs
│ ├── ColorSetting.cs
│ ├── RangeSetting.cs
│ ├── SettingAttribute.cs
│ ├── TextStyle.cs
│ └── ValueSetting.cs
└── Theme.cs
├── Engine
├── Credits.cs
├── Lang.cs
├── Report.cs
├── State.cs
└── Tutorial.cs
├── Extensions
├── BaseExtensions.cs
├── DataExtensions.cs
├── EnumExtensions.cs
├── GUIExtensions.cs
├── IOExtensions.cs
├── TextExtensions.cs
└── XmlExtensions.cs
├── External
├── CustomBarDef.cs
├── CustomNeedDef.cs
├── CustomSelectorDef.cs
├── CustomValueDef.cs
├── CustomWidgetDef.cs
└── ExternalWidgetDef.cs
├── Integration
├── IntegratedMod.cs
├── Integrations.cs
├── Multiplayer
│ └── Mod_Multiplayer.cs
└── PawnRules
│ └── Mod_PawnRules.cs
├── Interface
├── Dialog
│ ├── Dialog_Alert.cs
│ ├── Dialog_Config.cs
│ ├── Dialog_Error.cs
│ ├── Dialog_ManagePresets.cs
│ ├── Dialog_SavePreset.cs
│ ├── Tabs
│ │ ├── Tab.cs
│ │ ├── TabManager.cs
│ │ ├── Tab_ConfigColors.cs
│ │ ├── Tab_ConfigContent.cs
│ │ ├── Tab_ConfigCredits.cs
│ │ └── Tab_ConfigDesign.cs
│ └── WindowPlus.cs
├── GUIPlus.cs
├── Hud
│ ├── HudArgs.cs
│ ├── HudContent.cs
│ ├── HudLayout.cs
│ ├── HudTimings.cs
│ ├── HudWidget.cs
│ ├── Layers
│ │ ├── BaseLayer.cs
│ │ ├── ContainerLayer.cs
│ │ ├── HStackLayer.cs
│ │ ├── LayerTarget.cs
│ │ ├── LayerTargetUtility.cs
│ │ ├── LayoutLayer.cs
│ │ ├── PanelLayer.cs
│ │ ├── RowLayer.cs
│ │ ├── StackLayer.cs
│ │ ├── VStackLayer.cs
│ │ └── WidgetLayer.cs
│ ├── Layout
│ │ ├── LayoutEditor.cs
│ │ ├── LayoutElement.cs
│ │ ├── LayoutElementType.cs
│ │ └── LayoutPreset.cs
│ ├── Models
│ │ ├── Active.cs
│ │ ├── BarModel.cs
│ │ ├── Bars
│ │ │ ├── HealthBar.cs
│ │ │ ├── NeedBar.cs
│ │ │ ├── NeedEnergyBar.cs
│ │ │ ├── NeedFoodBar.cs
│ │ │ ├── NeedMoodBar.cs
│ │ │ ├── NeedRecreationBar.cs
│ │ │ ├── NeedSleepBar.cs
│ │ │ └── NeedSuppressionBar.cs
│ │ ├── BaseModel.cs
│ │ ├── IModel.cs
│ │ ├── SelectorModel.cs
│ │ ├── Selectors
│ │ │ ├── AreaSelector.cs
│ │ │ ├── FoodSelector.cs
│ │ │ ├── OutfitSelector.cs
│ │ │ └── TimetableSelector.cs
│ │ ├── ValueModel.cs
│ │ └── Values
│ │ │ ├── ActivityValue.cs
│ │ │ ├── AnimalMasterValue.cs
│ │ │ ├── CarryingValue.cs
│ │ │ ├── CompInfoValue.cs
│ │ │ ├── EquippedValue.cs
│ │ │ ├── GenderRaceAndAgeValue.cs
│ │ │ ├── HealthConditionValue.cs
│ │ │ ├── MentalConditionValue.cs
│ │ │ ├── NameHeaderValue.cs
│ │ │ ├── PrisonerInfoValue.cs
│ │ │ ├── QueuedValue.cs
│ │ │ ├── RecordValue.cs
│ │ │ ├── RelationKindAndFactionValue.cs
│ │ │ ├── SkillAnimalsValue.cs
│ │ │ ├── SkillConstructionValue.cs
│ │ │ ├── SkillCookingValue.cs
│ │ │ ├── SkillCraftingValue.cs
│ │ │ ├── SkillIntellectualValue.cs
│ │ │ ├── SkillMedicineValue.cs
│ │ │ ├── SkillMeleeValue.cs
│ │ │ ├── SkillMiningValue.cs
│ │ │ ├── SkillPlantsValue.cs
│ │ │ ├── SkillShootingValue.cs
│ │ │ ├── SkillSocialValue.cs
│ │ │ ├── SkillValue.cs
│ │ │ ├── StatValue.cs
│ │ │ └── TrainableValue.cs
│ ├── Tooltips
│ │ ├── AnimalTooltip.cs
│ │ ├── BioTooltip.cs
│ │ ├── HealthTooltip.cs
│ │ ├── MentalTooltip.cs
│ │ └── TooltipsPlus.cs
│ └── Widgets
│ │ ├── BarColorStyle.cs
│ │ ├── BarWidget.cs
│ │ ├── BlankWidget.cs
│ │ ├── IWidget.cs
│ │ ├── MissingWidget.cs
│ │ ├── SelectorWidget.cs
│ │ ├── SeparatorWidget.cs
│ │ ├── StandardWidget.cs
│ │ ├── ValueWidget.cs
│ │ └── WidgetTextStyle.cs
├── ListingPlus.cs
├── Screen
│ ├── InspectPaneButtons.cs
│ ├── InspectPaneLog.cs
│ ├── InspectPanePlus.cs
│ ├── InspectPaneTabs.cs
│ └── LetterStackPlus.cs
├── TexturesPlus.cs
└── WidgetsPlus.cs
├── Mod.cs
├── Properties
└── AssemblyInfo.cs
├── Resources
└── Layouts
│ └── Defaults
│ ├── Docked.xml
│ └── Floating.xml
├── RimHUD.csproj
├── obj
├── RimHUD.csproj.nuget.dgspec.json
├── RimHUD.csproj.nuget.g.props
├── RimHUD.csproj.nuget.g.targets
├── project.assets.json
└── project.nuget.cache
├── packages.config
└── release.targets
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | charset = utf-8
5 | indent_style = space
6 | indent_size = 2
7 | insert_final_newline = true
8 | trim_trailing_whitespace = true
9 |
10 | [*.sln]
11 | indent_style = tab
12 |
13 | [*.{md,mdx}]
14 | trim_trailing_whitespace = false
15 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | * text=auto
2 | *.sln text eol=crlf
3 | *.csproj text eol=crlf
4 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .*
2 | _*
3 | /*
4 | *.user
5 | *.pdb
6 | !/.gitignore
7 | !/.gitattributes
8 | !/.editorconfig
9 | !/*.md
10 | !/*.sln
11 | !/source/
12 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # RimHUD
2 | 
3 | 
4 | \
5 | 
6 | 
7 |
8 | [Link to Steam Workshop page](https://steamcommunity.com/sharedfiles/filedetails/?id=1508850027)\
9 | [Link to Ludeon Forum thread](https://ludeon.com/forums/index.php?topic=45787.0)
10 |
11 | ---
12 |
13 | RimHUD is a UI mod that displays a detailed information about a selected character or creature. The HUD display is integrated into the inspect pane which can be resized to fit the additional information. Alternatively the HUD can a separate floating window and docked to any position on the screen.
14 |
15 | Visual warnings will appear if a pawn has any life threatening conditions, has wounds that need tending or is close to a mental breakdown.
16 |
17 | ---
18 |
19 | ##### STEAM INSTALLATION
20 | - **[Go to the Steam Workshop page](https://steamcommunity.com/sharedfiles/filedetails/?id=1508850027) and subscribe to the mod.**
21 |
22 | ---
23 |
24 | ##### NON-STEAM INSTALLATION
25 | - **[Download the latest release](https://github.com/Jaxe-Dev/RimHUD/releases/latest) and unzip it into your *RimWorld\Mods* folder.**
26 |
27 | ---
28 |
29 | **Note to Translators**: *Although the offers are appreciated, for maintenance reasons only English will included with the base mod. All translations should be uploaded as language submods with full permission to use the mod's images in any way.*
30 |
31 | ---
32 |
33 | **Note to Modders**: *RimHUD supports integrated layout presets and custom widgets from your mod. Check the [wiki](https://github.com/Jaxe-Dev/RimHUD/wiki) for details.*
34 |
35 | ---
36 |
37 | The following base methods are patched with Harmony:
38 | ```
39 | Prefix* : RimWorld.InspectPaneUtility.DoTabs
40 | Prefix* : RimWorld.InspectPaneUtility.InspectPaneOnGUI
41 | Prefix* : RimWorld.InspectPaneUtility.PaneSizeFor
42 | Postfix : RimWorld.InspectPaneUtility.PaneWidthFor
43 | Prefix* : RimWorld.ITab.PaneTopY
44 | Prefix* : RimWorld.MainTabWindow_Inspect.PaneTopY
45 | Postfix : RimWorld.PlaySettings.DoPlaySettingsGlobalControls
46 | Prefix* : RimWorld.Tutor.TutorOnGUI
47 | Prefix* : Verse.ActiveTip.DrawInner
48 | Prefix* : Verse.ActiveTip.TipRect
49 | Postfix : Verse.Game.FinalizeInit
50 | Prefix* : Verse.LetterStack.LettersOnGUI
51 | Prefix : Verse.MapInterface.MapInterfaceOnGUI_AfterMainTabs
52 | Postfix : Verse.MapInterface.Notify_SwitchedMap
53 | Prefix : Verse.Profile.MemoryUtility.ClearAllMapsAndWorld
54 | ```
55 | *A prefix marked by a \* denotes that in some circumstances the original method will be bypassed*
56 |
--------------------------------------------------------------------------------
/RimHUD.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.33920.266
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RimHUD", "source\RimHUD.csproj", "{CCCC7430-4D27-4A71-A435-9E3F8B424D7B}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Release|Any CPU = Release|Any CPU
11 | EndGlobalSection
12 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
13 | {CCCC7430-4D27-4A71-A435-9E3F8B424D7B}.Release|Any CPU.ActiveCfg = Release|Any CPU
14 | {CCCC7430-4D27-4A71-A435-9E3F8B424D7B}.Release|Any CPU.Build.0 = Release|Any CPU
15 | EndGlobalSection
16 | EndGlobal
17 |
--------------------------------------------------------------------------------
/source/-/About/About.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Jaxe.RimHUD
4 | RimHUD
5 | Jaxe
6 | Mod Version: {ReleaseVersion}\n\nRimHUD is a UI mod that displays detailed information about a selected character or creature. The HUD display is integrated into the inspect pane which can be resized to fit the additional information. Alternatively, the HUD can display a separate floating window and can be docked to any position on the screen.\n\nVisual warnings will appear if a pawn has any life-threatening conditions, has wounds that need tending to, or is close to a mental breakdown.
7 |
8 | 1.1
9 | 1.2
10 | 1.3
11 | 1.4
12 | 1.5
13 |
14 |
15 |
16 | brrainz.harmony
17 | Harmony
18 | steam://url/CommunityFilePage/2009463077
19 | https://github.com/pardeike/HarmonyRimWorld/releases/latest
20 |
21 |
22 |
23 | brrainz.harmony
24 |
25 |
26 |
--------------------------------------------------------------------------------
/source/-/About/Preview.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jaxe-Dev/RimHUD/67176d6638cb31103beda9a50af42f8465ae1a83/source/-/About/Preview.png
--------------------------------------------------------------------------------
/source/-/About/PublishedFileId.txt:
--------------------------------------------------------------------------------
1 | 1508850027
--------------------------------------------------------------------------------
/source/-/Languages/English/Keyed/Base.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | {0} {1}
7 |
8 | Show HUD
9 |
10 |
--------------------------------------------------------------------------------
/source/-/Languages/English/Keyed/Integration.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Rules: {0}
5 |
6 |
--------------------------------------------------------------------------------
/source/-/Legacy/1.1-1.2/Assemblies/RimHUD.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jaxe-Dev/RimHUD/67176d6638cb31103beda9a50af42f8465ae1a83/source/-/Legacy/1.1-1.2/Assemblies/RimHUD.dll
--------------------------------------------------------------------------------
/source/-/Legacy/1.1-1.2/Languages/English/Keyed/Integration.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Rules: {0}
4 |
5 |
--------------------------------------------------------------------------------
/source/-/Legacy/1.1-1.2/Textures/RimHUD/ConfigIcon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jaxe-Dev/RimHUD/67176d6638cb31103beda9a50af42f8465ae1a83/source/-/Legacy/1.1-1.2/Textures/RimHUD/ConfigIcon.png
--------------------------------------------------------------------------------
/source/-/Legacy/1.1-1.2/Textures/RimHUD/SelfTendOffIcon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jaxe-Dev/RimHUD/67176d6638cb31103beda9a50af42f8465ae1a83/source/-/Legacy/1.1-1.2/Textures/RimHUD/SelfTendOffIcon.png
--------------------------------------------------------------------------------
/source/-/Legacy/1.1-1.2/Textures/RimHUD/SelfTendOnIcon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jaxe-Dev/RimHUD/67176d6638cb31103beda9a50af42f8465ae1a83/source/-/Legacy/1.1-1.2/Textures/RimHUD/SelfTendOnIcon.png
--------------------------------------------------------------------------------
/source/-/Legacy/1.1-1.2/Textures/RimHUD/ToggleIcon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jaxe-Dev/RimHUD/67176d6638cb31103beda9a50af42f8465ae1a83/source/-/Legacy/1.1-1.2/Textures/RimHUD/ToggleIcon.png
--------------------------------------------------------------------------------
/source/-/Legacy/1.3/Assemblies/RimHUD.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jaxe-Dev/RimHUD/67176d6638cb31103beda9a50af42f8465ae1a83/source/-/Legacy/1.3/Assemblies/RimHUD.dll
--------------------------------------------------------------------------------
/source/-/Legacy/1.3/Languages/English/Keyed/Integration.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Rules: {0}
5 |
6 |
--------------------------------------------------------------------------------
/source/-/Legacy/1.3/Textures/RimHUD/ConfigIcon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jaxe-Dev/RimHUD/67176d6638cb31103beda9a50af42f8465ae1a83/source/-/Legacy/1.3/Textures/RimHUD/ConfigIcon.png
--------------------------------------------------------------------------------
/source/-/Legacy/1.3/Textures/RimHUD/SelfTendOffIcon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jaxe-Dev/RimHUD/67176d6638cb31103beda9a50af42f8465ae1a83/source/-/Legacy/1.3/Textures/RimHUD/SelfTendOffIcon.png
--------------------------------------------------------------------------------
/source/-/Legacy/1.3/Textures/RimHUD/SelfTendOnIcon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jaxe-Dev/RimHUD/67176d6638cb31103beda9a50af42f8465ae1a83/source/-/Legacy/1.3/Textures/RimHUD/SelfTendOnIcon.png
--------------------------------------------------------------------------------
/source/-/Legacy/1.3/Textures/RimHUD/ToggleIcon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jaxe-Dev/RimHUD/67176d6638cb31103beda9a50af42f8465ae1a83/source/-/Legacy/1.3/Textures/RimHUD/ToggleIcon.png
--------------------------------------------------------------------------------
/source/-/Legacy/1.4/Assemblies/RimHUD.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jaxe-Dev/RimHUD/67176d6638cb31103beda9a50af42f8465ae1a83/source/-/Legacy/1.4/Assemblies/RimHUD.dll
--------------------------------------------------------------------------------
/source/-/LoadFolders.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | /
4 | Legacy/1.1-1.2
5 |
6 |
7 | /
8 | Legacy/1.1-1.2
9 |
10 |
11 | /
12 | Legacy/1.3
13 |
14 |
15 | /
16 | Legacy/1.4
17 |
18 |
19 | /
20 |
21 |
22 |
--------------------------------------------------------------------------------
/source/-/README.md:
--------------------------------------------------------------------------------
1 | # RimHUD
2 | 
3 | 
4 | \
5 | 
6 | 
7 |
8 | [Link to Steam Workshop page](https://steamcommunity.com/sharedfiles/filedetails/?id=1508850027)\
9 | [Link to Ludeon Forum thread](https://ludeon.com/forums/index.php?topic=45787.0)
10 |
11 | ---
12 |
13 | RimHUD is a UI mod that displays a detailed information about a selected character or creature. The HUD display is integrated into the inspect pane which can be resized to fit the additional information. Alternatively the HUD can a separate floating window and docked to any position on the screen.
14 |
15 | Visual warnings will appear if a pawn has any life threatening conditions, has wounds that need tending or is close to a mental breakdown.
16 |
17 | ---
18 |
19 | ##### STEAM INSTALLATION
20 | - **[Go to the Steam Workshop page](https://steamcommunity.com/sharedfiles/filedetails/?id=1508850027) and subscribe to the mod.**
21 |
22 | ---
23 |
24 | ##### NON-STEAM INSTALLATION
25 | - **[Download the latest release](https://github.com/Jaxe-Dev/RimHUD/releases/latest) and unzip it into your *RimWorld\Mods* folder.**
26 |
27 | ---
28 |
29 | **Note to Translators**: *Although the offers are appreciated, for maintenance reasons only English will included with the base mod. All translations should be uploaded as language submods with full permission to use the mod's images in any way.*
30 |
31 | ---
32 |
33 | **Note to Modders**: *RimHUD supports integrated layout presets and custom widgets from your mod. Check the [wiki](https://github.com/Jaxe-Dev/RimHUD/wiki) for details.*
34 |
35 | ---
36 |
37 | The following base methods are patched with Harmony:
38 | ```
39 | Prefix* : RimWorld.InspectPaneUtility.DoTabs
40 | Prefix* : RimWorld.InspectPaneUtility.InspectPaneOnGUI
41 | Prefix* : RimWorld.InspectPaneUtility.PaneSizeFor
42 | Postfix : RimWorld.InspectPaneUtility.PaneWidthFor
43 | Prefix* : RimWorld.ITab.PaneTopY
44 | Prefix* : RimWorld.MainTabWindow_Inspect.PaneTopY
45 | Postfix : RimWorld.PlaySettings.DoPlaySettingsGlobalControls
46 | Prefix* : RimWorld.Tutor.TutorOnGUI
47 | Prefix* : Verse.ActiveTip.DrawInner
48 | Prefix* : Verse.ActiveTip.TipRect
49 | Postfix : Verse.Game.FinalizeInit
50 | Prefix* : Verse.LetterStack.LettersOnGUI
51 | Prefix : Verse.MapInterface.MapInterfaceOnGUI_AfterMainTabs
52 | Postfix : Verse.MapInterface.Notify_SwitchedMap
53 | Prefix : Verse.Profile.MemoryUtility.ClearAllMapsAndWorld
54 | ```
55 | *A prefix marked by a \* denotes that in some circumstances the original method will be bypassed*
56 |
--------------------------------------------------------------------------------
/source/-/Textures/RimHUD/ConfigIcon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jaxe-Dev/RimHUD/67176d6638cb31103beda9a50af42f8465ae1a83/source/-/Textures/RimHUD/ConfigIcon.png
--------------------------------------------------------------------------------
/source/-/Textures/RimHUD/SelfTendOffIcon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jaxe-Dev/RimHUD/67176d6638cb31103beda9a50af42f8465ae1a83/source/-/Textures/RimHUD/SelfTendOffIcon.png
--------------------------------------------------------------------------------
/source/-/Textures/RimHUD/SelfTendOnIcon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jaxe-Dev/RimHUD/67176d6638cb31103beda9a50af42f8465ae1a83/source/-/Textures/RimHUD/SelfTendOnIcon.png
--------------------------------------------------------------------------------
/source/-/Textures/RimHUD/ToggleIcon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jaxe-Dev/RimHUD/67176d6638cb31103beda9a50af42f8465ae1a83/source/-/Textures/RimHUD/ToggleIcon.png
--------------------------------------------------------------------------------
/source/-/Textures/RimHUD/TutorialConfigIcon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jaxe-Dev/RimHUD/67176d6638cb31103beda9a50af42f8465ae1a83/source/-/Textures/RimHUD/TutorialConfigIcon.png
--------------------------------------------------------------------------------
/source/Access/Defs.cs:
--------------------------------------------------------------------------------
1 | using RimWorld;
2 |
3 | namespace RimHUD.Access
4 | {
5 | [DefOf]
6 | public static class Defs
7 | {
8 | [DefAlias("Schedule")]
9 | public static readonly MainButtonDef MainButtonRestrict = null!;
10 | [DefAlias("Work")]
11 | public static readonly MainButtonDef MainButtonWork = null!;
12 |
13 | [DefAlias("Mood")]
14 | public static readonly NeedDef NeedMood = null!;
15 | [DefAlias("Joy")]
16 | public static readonly NeedDef NeedRecreation = null!;
17 | [DefAlias("Beauty")]
18 | public static readonly NeedDef NeedBeauty = null!;
19 | [DefAlias("Comfort")]
20 | public static readonly NeedDef NeedComfort = null!;
21 | [DefAlias("Outdoors")]
22 | public static readonly NeedDef NeedOutdoors = null!;
23 | [DefAlias("MechEnergy"), MayRequireBiotech]
24 | public static readonly NeedDef NeedEnergy = null!;
25 | [DefAlias("Suppression"), MayRequireIdeology]
26 | public static readonly NeedDef NeedSuppression = null!;
27 |
28 | [DefAlias("Haul")]
29 | public static readonly TrainableDef TrainableHaul = null!;
30 | [DefAlias("Rescue")]
31 | public static readonly TrainableDef TrainableRescue = null!;
32 |
33 | static Defs() => DefOfHelper.EnsureInitializedInCtor(typeof(Defs));
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/source/Access/Patch/RimWorld_ITab_PaneTopY.cs:
--------------------------------------------------------------------------------
1 | using HarmonyLib;
2 | using RimHUD.Configuration;
3 | using RimHUD.Engine;
4 | using RimWorld;
5 | using Verse;
6 |
7 | namespace RimHUD.Access.Patch
8 | {
9 | [HarmonyPatch(typeof(ITab), "PaneTopY", MethodType.Getter)]
10 | public static class RimWorld_ITab_PaneTopY
11 | {
12 | public static bool Prefix(ref float __result)
13 | {
14 | if (!State.ModifyPane) { return true; }
15 |
16 | __result = (float)UI.screenHeight - Theme.InspectPaneHeight.Value;
17 |
18 | return false;
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/source/Access/Patch/RimWorld_InspectPaneUtility_DoTabs.cs:
--------------------------------------------------------------------------------
1 | using HarmonyLib;
2 | using RimHUD.Engine;
3 | using RimHUD.Interface.Screen;
4 | using RimWorld;
5 |
6 | namespace RimHUD.Access.Patch
7 | {
8 | [HarmonyPatch(typeof(InspectPaneUtility), "DoTabs")]
9 | public static class RimWorld_InspectPaneUtility_DoTabs
10 | {
11 | private static bool Prefix(IInspectPane pane)
12 | {
13 | if (!State.ModifyPane) { return true; }
14 |
15 | InspectPaneTabs.Draw(pane);
16 |
17 | return false;
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/source/Access/Patch/RimWorld_InspectPaneUtility_InspectPaneOnGUI.cs:
--------------------------------------------------------------------------------
1 | using HarmonyLib;
2 | using RimHUD.Engine;
3 | using RimHUD.Interface.Screen;
4 | using RimWorld;
5 | using UnityEngine;
6 |
7 | namespace RimHUD.Access.Patch
8 | {
9 | [HarmonyPatch(typeof(InspectPaneUtility), "InspectPaneOnGUI")]
10 | public static class RimWorld_InspectPaneUtility_InspectPaneOnGUI
11 | {
12 | private static bool Prefix(Rect inRect, IInspectPane pane)
13 | {
14 | if (!State.ModifyPane) { return true; }
15 |
16 | InspectPanePlus.DrawPane(inRect, pane);
17 |
18 | return false;
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/source/Access/Patch/RimWorld_InspectPaneUtility_PaneSizeFor.cs:
--------------------------------------------------------------------------------
1 | using HarmonyLib;
2 | using RimHUD.Configuration;
3 | using RimHUD.Engine;
4 | using RimHUD.Interface;
5 | using RimWorld;
6 | using UnityEngine;
7 |
8 | namespace RimHUD.Access.Patch
9 | {
10 | [HarmonyPatch(typeof(InspectPaneUtility), "PaneSizeFor")]
11 | public static class RimWorld_InspectPaneUtility_PaneSizeFor
12 | {
13 | private static bool Prefix(ref Vector2 __result, IInspectPane? pane)
14 | {
15 | if (!State.ModifyPane || pane is null) { return true; }
16 |
17 | __result = new Vector2(InspectPaneUtility.PaneWidthFor(pane), Theme.InspectPaneHeight.Value - WidgetsPlus.MainButtonHeight);
18 |
19 | return false;
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/source/Access/Patch/RimWorld_InspectPaneUtility_PaneWidthFor.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 | using HarmonyLib;
3 | using RimHUD.Configuration;
4 | using RimHUD.Engine;
5 | using RimWorld;
6 | using UnityEngine;
7 |
8 | namespace RimHUD.Access.Patch
9 | {
10 | [HarmonyPatch(typeof(InspectPaneUtility), "PaneWidthFor")]
11 | public static class RimWorld_InspectPaneUtility_PaneWidthFor
12 | {
13 | private static bool Prefix(ref float __result, IInspectPane? pane)
14 | {
15 | if (!State.ModifyPane || pane is null) { return true; }
16 |
17 | __result = Theme.InspectPaneTabWidth.Value * Mathf.Max(Theme.InspectPaneMinTabs.Value, pane.CurTabs?.Count(static tab => tab.IsVisible && !tab.Hidden) ?? 0f);
18 |
19 | return false;
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/source/Access/Patch/RimWorld_MainTabWindow_Inspect_PaneTopY.cs:
--------------------------------------------------------------------------------
1 | using HarmonyLib;
2 | using RimHUD.Configuration;
3 | using RimHUD.Engine;
4 | using RimWorld;
5 | using Verse;
6 |
7 | namespace RimHUD.Access.Patch
8 | {
9 | [HarmonyPatch(typeof(MainTabWindow_Inspect), "PaneTopY", MethodType.Getter)]
10 | public static class RimWorld_MainTabWindow_Inspect_PaneTopY
11 | {
12 | public static bool Prefix(ref float __result)
13 | {
14 | if (!State.ModifyPane) { return true; }
15 |
16 | __result = (float)UI.screenHeight - Theme.InspectPaneHeight.Value;
17 |
18 | return false;
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/source/Access/Patch/RimWorld_PlaySettings_DoPlaySettingsGlobalControls.cs:
--------------------------------------------------------------------------------
1 | using HarmonyLib;
2 | using RimHUD.Engine;
3 | using RimHUD.Interface;
4 | using RimHUD.Interface.Dialog;
5 | using RimWorld;
6 | using UnityEngine;
7 | using Verse;
8 |
9 | namespace RimHUD.Access.Patch
10 | {
11 | [HarmonyPatch(typeof(PlaySettings), "DoPlaySettingsGlobalControls")]
12 | public static class RimWorld_PlaySettings_DoPlaySettingsGlobalControls
13 | {
14 | private static void Postfix(WidgetRow? row, bool worldView)
15 | {
16 | if (worldView || row is null) { return; }
17 |
18 | var showHud = State.Activated;
19 | row.ToggleableIcon(ref showHud, TexturesPlus.ToggleIcon, Lang.Get("ToggleHud"), SoundDefOf.Mouseover_ButtonToggle);
20 |
21 | if (Event.current!.shift && showHud != State.Activated) { Dialog_Config.Open(); }
22 | else { State.Activated = showHud; }
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/source/Access/Patch/RimWorld_Tutor_TutorOnGUI.cs:
--------------------------------------------------------------------------------
1 | using HarmonyLib;
2 | using RimHUD.Engine;
3 | using RimWorld;
4 |
5 | namespace RimHUD.Access.Patch
6 | {
7 | [HarmonyPatch(typeof(Tutor), "TutorOnGUI")]
8 | public static class RimWorld_Tutor_TutorOnGUI
9 | {
10 | private static bool Prefix() => !State.HudFloatingVisible;
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/source/Access/Patch/Verse_ActiveTip_DrawInner.cs:
--------------------------------------------------------------------------------
1 | using HarmonyLib;
2 | using RimHUD.Interface.Hud.Tooltips;
3 | using UnityEngine;
4 | using Verse;
5 |
6 | namespace RimHUD.Access.Patch
7 | {
8 | [HarmonyPatch(typeof(ActiveTip), "DrawInner")]
9 | public static class Verse_ActiveTip_DrawInner
10 | {
11 | public static bool Prefix(ActiveTip __instance, Rect bgRect, string label)
12 | {
13 | if (!TooltipsPlus.IsFromHud(__instance.signal.uniqueId)) { return true; }
14 |
15 | TooltipsPlus.DrawInner(bgRect, label);
16 |
17 | return false;
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/source/Access/Patch/Verse_ActiveTip_TipRect.cs:
--------------------------------------------------------------------------------
1 | using HarmonyLib;
2 | using RimHUD.Interface.Hud.Tooltips;
3 | using UnityEngine;
4 | using Verse;
5 |
6 | namespace RimHUD.Access.Patch
7 | {
8 | [HarmonyPatch(typeof(ActiveTip), "TipRect", MethodType.Getter)]
9 | public static class Verse_ActiveTip_TipRect
10 | {
11 | public static bool Prefix(ActiveTip __instance, ref Rect __result)
12 | {
13 | if (!TooltipsPlus.IsFromHud(__instance.signal.uniqueId)) { return true; }
14 |
15 | __result = TooltipsPlus.GetRect(Traverse.Create(__instance)!.Property("FinalText")!.GetValue());
16 |
17 | return false;
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/source/Access/Patch/Verse_Game_FinalizeInit.cs:
--------------------------------------------------------------------------------
1 | using HarmonyLib;
2 | using RimHUD.Configuration;
3 | using Verse;
4 |
5 | namespace RimHUD.Access.Patch
6 | {
7 | [HarmonyPatch(typeof(Game), "FinalizeInit")]
8 | public static class Verse_Game_FinalizeInit
9 | {
10 | private static void Postfix() => LongEventHandler.ExecuteWhenFinished(Persistent.ReportIfReset);
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/source/Access/Patch/Verse_LetterStack_LettersOnGUI.cs:
--------------------------------------------------------------------------------
1 | using HarmonyLib;
2 | using RimHUD.Engine;
3 | using RimHUD.Interface.Screen;
4 | using Verse;
5 |
6 | namespace RimHUD.Access.Patch
7 | {
8 | [HarmonyPatch(typeof(LetterStack), "LettersOnGUI")]
9 | public static class Verse_LetterStack_LettersOnGUI
10 | {
11 | private static bool Prefix(LetterStack __instance, ref float baseY)
12 | {
13 | if (!State.CompressLetters) { return true; }
14 |
15 | LetterStackPlus.Draw(__instance, baseY);
16 | return false;
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/source/Access/Patch/Verse_MapInterface_MapInterfaceOnGUI_AfterMainTabs.cs:
--------------------------------------------------------------------------------
1 | using HarmonyLib;
2 | using RimHUD.Engine;
3 | using RimHUD.Interface.Hud;
4 | using RimWorld;
5 |
6 | namespace RimHUD.Access.Patch
7 | {
8 | [HarmonyPatch(typeof(MapInterface), "MapInterfaceOnGUI_AfterMainTabs")]
9 | public static class Verse_MapInterface_MapInterfaceOnGUI_AfterMainTabs
10 | {
11 | private static void Prefix()
12 | {
13 | if (!State.HudFloatingVisible) { return; }
14 |
15 | HudLayout.DrawFloating();
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/source/Access/Patch/Verse_MapInterface_Notify_SwitchedMap.cs:
--------------------------------------------------------------------------------
1 | using HarmonyLib;
2 | using RimHUD.Interface.Screen;
3 | using RimWorld;
4 |
5 | namespace RimHUD.Access.Patch
6 | {
7 | [HarmonyPatch(typeof(MapInterface), "Notify_SwitchedMap")]
8 | public static class Verse_MapInterface_Notify_SwitchedMap
9 | {
10 | private static void Postfix() => InspectPaneLog.ClearCache();
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/source/Access/Patch/Verse_Profile_MemoryUtility_ClearAllMapsAndWorld.cs:
--------------------------------------------------------------------------------
1 | using HarmonyLib;
2 | using RimHUD.Engine;
3 | using Verse.Profile;
4 |
5 | namespace RimHUD.Access.Patch
6 | {
7 | [HarmonyPatch(typeof(MemoryUtility), "ClearAllMapsAndWorld")]
8 | public static class Verse_Profile_MemoryUtility_ClearAllMapsAndWorld
9 | {
10 | private static void Prefix() => State.ClearCache();
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/source/Access/Reflection.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 | using System.Reflection;
3 | using HarmonyLib;
4 | using RimWorld;
5 | using Verse;
6 |
7 | namespace RimHUD.Access
8 | {
9 | public static class Reflection
10 | {
11 | public static readonly FastInvokeHandler RimWorld_HealthCardUtility_VisibleHediffGroupsInOrder = MethodInvoker.GetHandler(AccessTools.Method(typeof(HealthCardUtility), "VisibleHediffGroupsInOrder", new[] { typeof(Pawn), typeof(bool) }));
12 | public static readonly FastInvokeHandler RimWorld_InspectPaneUtility_InterfaceToggleTab = MethodInvoker.GetHandler(AccessTools.Method(typeof(InspectPaneUtility), "InterfaceToggleTab", new[] { typeof(InspectTabBase), typeof(IInspectPane) }));
13 | public static readonly FastInvokeHandler RimWorld_InspectPaneUtility_ToggleTab = MethodInvoker.GetHandler(AccessTools.Method(typeof(InspectPaneUtility), "ToggleTab", new[] { typeof(InspectTabBase), typeof(IInspectPane) }));
14 | public static readonly FastInvokeHandler RimWorld_Pawn_TrainingTracker_GetSteps = MethodInvoker.GetHandler(AccessTools.Method(typeof(Pawn_TrainingTracker), "GetSteps", new[] { typeof(TrainableDef) }));
15 | public static readonly FastInvokeHandler RimWorld_SkillUI_GetSkillDescription = MethodInvoker.GetHandler(AccessTools.Method(typeof(SkillUI), "GetSkillDescription", new[] { typeof(SkillRecord) }));
16 | public static readonly FastInvokeHandler Verse_Widgets_CheckPlayDragSliderSound = MethodInvoker.GetHandler(AccessTools.Method(typeof(Widgets), "CheckPlayDragSliderSound"));
17 |
18 | public static readonly FieldInfo RimWorld_InspectPaneUtility_InspectTabButtonFillTex = AccessTools.Field(typeof(InspectPaneUtility), "InspectTabButtonFillTex");
19 | public static readonly FieldInfo Verse_LetterStack_LastTopYInt = AccessTools.Field(typeof(LetterStack), "lastTopYInt");
20 | public static readonly FieldInfo Verse_LetterStack_Letters = AccessTools.Field(typeof(LetterStack), "letters");
21 | public static readonly FieldInfo Verse_LetterStack_TmpBundledLetters = AccessTools.Field(typeof(LetterStack), "tmpBundledLetters");
22 | public static readonly FieldInfo Verse_Widgets_RangeControlTextColor = AccessTools.Field(typeof(Widgets), "RangeControlTextColor");
23 | public static readonly FieldInfo Verse_Widgets_SliderDraggingId = AccessTools.Field(typeof(Widgets), "sliderDraggingID");
24 | public static readonly FieldInfo Verse_Widgets_SliderHandle = AccessTools.Field(typeof(Widgets), "SliderHandle");
25 | public static readonly FieldInfo Verse_Widgets_SliderRailAtlas = AccessTools.Field(typeof(Widgets), "SliderRailAtlas");
26 |
27 | public static ModContentPack? GetModFromAssemblyName(string name)
28 | {
29 | var possible = LoadedModManager.RunningMods.FirstOrDefault(mod => mod.assemblies!.loadedAssemblies.FirstOrDefault(assembly => assembly.GetName().Name == name) is not null);
30 | if (possible is null || Equals(possible, Mod.ContentPack)) { return null; }
31 |
32 | return possible;
33 | }
34 |
35 | public static T GetValue(this FieldInfo self, object instance) => (T)self.GetValue(instance);
36 | public static T GetValueStatic(this FieldInfo self) => (T)self.GetValue(null);
37 | public static void SetValueStatic(this FieldInfo self, T value) => self.SetValue(null, value);
38 | public static T Invoke(this FastInvokeHandler self, object target, params object[] parameters) => (T)self.Invoke(target, parameters);
39 | public static T InvokeStatic(this FastInvokeHandler self, params object[] parameters) => (T)self.Invoke(null, parameters);
40 | public static void InvokeStatic(this FastInvokeHandler self, params object[] parameters) => self.Invoke(null, parameters);
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/source/Configuration/Presets.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.IO;
3 | using System.Linq;
4 | using System.Text.RegularExpressions;
5 | using System.Xml.Linq;
6 | using RimHUD.Extensions;
7 | using RimHUD.Interface.Hud.Layers;
8 | using RimHUD.Interface.Hud.Layout;
9 | using Verse;
10 |
11 | namespace RimHUD.Configuration
12 | {
13 | public static class Presets
14 | {
15 | private const string Extension = ".xml";
16 |
17 | private const string DirectoryName = "Presets";
18 | private const string ModDirectoryName = Mod.Id + "\\Presets";
19 |
20 | public static readonly DirectoryInfo UserPresetsDirectory = new(Path.Combine(Persistent.ConfigDirectory.FullName, DirectoryName));
21 |
22 | public static readonly Regex ValidFilenameRegex = new("^(?:[\\p{L}\\p{N}_\\-]|[\\p{L}\\p{N}_\\-]+[\\p{L}\\p{N}_\\- ]*[\\p{L}\\p{N}_\\-]+)$");
23 |
24 | public static void Load(bool reset)
25 | {
26 | var docked = new FileInfo(Path.Combine(Persistent.ConfigDirectory.FullName, LayoutLayer.DockedFileName));
27 | var floating = new FileInfo(Path.Combine(Persistent.ConfigDirectory.FullName, LayoutLayer.FloatingFileName));
28 |
29 | if (!reset && docked.Exists && Persistent.LoadXml(docked) is { } dockedXe) { LayoutLayer.Docked = LayoutLayer.FromXml(dockedXe); }
30 | else { LayoutLayer.Docked.ToXml().Save(docked.FullName); }
31 |
32 | if (!reset && floating.Exists && Persistent.LoadXml(floating) is { } floatingXe) { LayoutLayer.Floating = LayoutLayer.FromXml(floatingXe); }
33 | else { LayoutLayer.Floating.ToXml().Save(floating.FullName); }
34 | }
35 |
36 | public static void Save()
37 | {
38 | var docked = new FileInfo(Path.Combine(Persistent.ConfigDirectory.FullName, LayoutLayer.DockedFileName));
39 | var floating = new FileInfo(Path.Combine(Persistent.ConfigDirectory.FullName, LayoutLayer.FloatingFileName));
40 |
41 | LayoutLayer.Docked.ToXml().Save(docked.FullName);
42 | LayoutLayer.Floating.ToXml().Save(floating.FullName);
43 | }
44 |
45 | public static void Save(string name, XElement xml)
46 | {
47 | if (!UserPresetsDirectory.ExistsNow()) { UserPresetsDirectory.Create(); }
48 | xml.Save(Path.Combine(UserPresetsDirectory.FullName, name + Extension));
49 | }
50 |
51 | public static void Delete(LayoutPreset preset)
52 | {
53 | if (!preset.IsUserMade || !preset.File.ExistsNow()) { return; }
54 | preset.File.Delete();
55 | LayoutPreset.RefreshList();
56 | }
57 |
58 | public static IEnumerable GetIntegratedList()
59 | {
60 | var list = new List();
61 | if (LoadedModManager.RunningMods is null) { return list.ToArray(); }
62 |
63 | foreach (var mod in LoadedModManager.RunningMods)
64 | {
65 | var directory = new DirectoryInfo(Path.Combine(mod.RootDir, mod == Mod.ContentPack ? DirectoryName : ModDirectoryName));
66 | if (!directory.Exists) { continue; }
67 |
68 | list.AddRange(directory.GetFiles($"*{Extension}").Select(file => LayoutPreset.FromFile(mod, file)).WhereNotNull());
69 | }
70 |
71 | return list.ToArray();
72 | }
73 |
74 | public static IEnumerable GetUserList()
75 | {
76 | var directory = new DirectoryInfo(Path.Combine(Persistent.ConfigDirectory.FullName, DirectoryName));
77 | return directory.Exists ? directory.GetFiles($"*{Extension}").Select(static file => LayoutPreset.FromFile(null, file)).WhereNotNull().ToArray() : new LayoutPreset[] { };
78 | }
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/source/Configuration/Settings/BaseSetting.cs:
--------------------------------------------------------------------------------
1 | namespace RimHUD.Configuration.Settings
2 | {
3 | public abstract class BaseSetting
4 | {
5 | public abstract void Refresh();
6 |
7 | public abstract void ToDefault();
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/source/Configuration/Settings/BoolSetting.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace RimHUD.Configuration.Settings
4 | {
5 | public sealed class BoolSetting : ValueSetting
6 | {
7 | [Setting(typeof(bool))]
8 | public bool Value { get => (bool)Object; set => Object = value; }
9 |
10 | public BoolSetting(bool @default, string label, string? tooltip = null, Action? onChange = null) : base(@default, label, tooltip, onChange)
11 | { }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/source/Configuration/Settings/ColorSetting.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using UnityEngine;
3 |
4 | namespace RimHUD.Configuration.Settings
5 | {
6 | public sealed class ColorSetting : ValueSetting
7 | {
8 | [Setting(typeof(Color))]
9 | public Color Value { get => (Color)Object; set => Object = value; }
10 |
11 | public ColorSetting(Color @default, string label, string? tooltip = null, Action? onChange = null) : base(@default, label, tooltip, onChange)
12 | { }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/source/Configuration/Settings/RangeSetting.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using UnityEngine;
3 |
4 | namespace RimHUD.Configuration.Settings
5 | {
6 | public sealed class RangeSetting : ValueSetting
7 | {
8 | private readonly Func? _format;
9 |
10 | public int Min { get; private set; }
11 | public int Max { get; private set; }
12 |
13 | [Setting(typeof(int))]
14 | public int Value { get => (int)Object; set => Object = Mathf.Clamp(value, Min, Max); }
15 |
16 | public RangeSetting(int @default, int min, int max, string label, Func? format = null, string? tooltip = null, Action? onChange = null) : base(@default, label, tooltip, onChange)
17 | {
18 | Min = min;
19 | Max = max;
20 |
21 | _format = format;
22 | }
23 |
24 | public override string ToString() => _format is null ? Value.ToString() : _format(Value);
25 |
26 | public void SetMinMax(int min, int max)
27 | {
28 | Min = min;
29 | Max = max;
30 | Value = Mathf.Clamp(Value, Min, Max);
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/source/Configuration/Settings/SettingAttribute.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using RimHUD.Extensions;
3 | using RimHUD.Interface;
4 | using UnityEngine;
5 |
6 | namespace RimHUD.Configuration.Settings
7 | {
8 | [AttributeUsage(AttributeTargets.Property)]
9 | public sealed class SettingAttribute : Attribute
10 | {
11 | public string? Category { get; }
12 |
13 | public string? Label { get; }
14 |
15 | public Type? Type { get; }
16 |
17 | public SettingAttribute(string? category, string? label, Type? type = null)
18 | {
19 | Category = category;
20 | Label = label;
21 | Type = type;
22 | }
23 |
24 | public SettingAttribute(string? label, Type? type = null) : this(null, label, type)
25 | { }
26 |
27 | public SettingAttribute(Type type) : this(null, null, type)
28 | { }
29 |
30 | public string? ConvertToXml(object value)
31 | {
32 | if (Type is null) { return null; }
33 | return Type == typeof(Color) ? ((Color)value).ToHex() : value.ToString();
34 | }
35 |
36 | public object? ConvertFromXml(string text)
37 | {
38 | if (Type is null) { return null; }
39 |
40 | object value;
41 | if (Type == typeof(string)) { value = text; }
42 | else if (Type == typeof(bool)) { value = text.ToBool() ?? false; }
43 | else if (Type == typeof(int)) { value = text.ToInt() ?? 0; }
44 | else if (Type == typeof(Color)) { value = GUIPlus.HexToColor(text); }
45 | else { return null; }
46 |
47 | return value;
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/source/Configuration/Settings/TextStyle.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using RimHUD.Engine;
3 | using RimHUD.Extensions;
4 | using UnityEngine;
5 | using Verse;
6 |
7 | namespace RimHUD.Configuration.Settings
8 | {
9 | public sealed class TextStyle : BaseSetting
10 | {
11 | private readonly TextStyle? _baseTextStyle;
12 |
13 | public string? Label { get; }
14 |
15 | public GUIStyle GUIStyle { get; private set; } = null!;
16 |
17 | public int ActualSize => GUIStyle.fontSize;
18 |
19 | [Setting("Size")]
20 | public RangeSetting Size { get; }
21 | [Setting("Line")]
22 | public RangeSetting Height { get; }
23 |
24 | private readonly Action? _onChange;
25 | public float LineHeight { get; private set; }
26 |
27 | public TextStyle(string? label, TextStyle? baseTextStyle, int size, int sizeMin, int sizeMax, int height, int heightMin, int heightMax, Action? onChange = null)
28 | {
29 | _baseTextStyle = baseTextStyle;
30 |
31 | Label = label;
32 |
33 | Size = new RangeSetting(size, sizeMin, sizeMax, Lang.Get("Theme.TextStyle.Size"), value => _baseTextStyle is null ? value.ToString() : value.ToStringWithSign(), onChange: _ => UpdateStyle());
34 | Height = new RangeSetting(height, heightMin, heightMax, Lang.Get("Theme.TextStyle.Height"), static value => $"{value}%", onChange: _ => UpdateStyle());
35 |
36 | UpdateStyle();
37 |
38 | _onChange = onChange;
39 | }
40 |
41 | public static void SetFromString(string? value)
42 | {
43 | if (value.NullOrWhitespace()) { return; }
44 |
45 | var split = value!.Split('|');
46 | if (split.Length is not 6) { return; }
47 |
48 | Theme.RegularTextStyle.Size.Value = split[0].ToInt() ?? Theme.RegularTextStyle.Size.Value;
49 | Theme.RegularTextStyle.Height.Value = split[1].ToInt() ?? Theme.RegularTextStyle.Height.Value;
50 | Theme.LargeTextStyle.Size.Value = split[2].ToInt() ?? Theme.LargeTextStyle.Size.Value;
51 | Theme.LargeTextStyle.Height.Value = split[3].ToInt() ?? Theme.LargeTextStyle.Height.Value;
52 | Theme.SmallTextStyle.Size.Value = split[4].ToInt() ?? Theme.SmallTextStyle.Size.Value;
53 | Theme.SmallTextStyle.Height.Value = split[5].ToInt() ?? Theme.SmallTextStyle.Height.Value;
54 | }
55 |
56 | public static string GetSizesString() => $"{Theme.RegularTextStyle.Size.Value}|{Theme.RegularTextStyle.Height.Value}|{Theme.LargeTextStyle.Size.Value}|{Theme.LargeTextStyle.Height.Value}|{Theme.SmallTextStyle.Size.Value}|{Theme.SmallTextStyle.Height.Value}";
57 |
58 | public override void ToDefault()
59 | {
60 | Size.ToDefault();
61 | Height.ToDefault();
62 | }
63 |
64 | public override void Refresh() => _onChange?.Invoke(this);
65 |
66 | public void UpdateStyle()
67 | {
68 | GUIStyle = _baseTextStyle?.GUIStyle.ResizedBy(Size.Value) ?? Theme.BaseGUIStyle.SetTo(Size.Value);
69 | LineHeight = GUIStyle.lineHeight * Height.Value.ToPercentageFloat();
70 |
71 | _onChange?.Invoke(this);
72 | }
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/source/Configuration/Settings/ValueSetting.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace RimHUD.Configuration.Settings
4 | {
5 | public abstract class ValueSetting : BaseSetting
6 | {
7 | private readonly object _default;
8 |
9 | private object _object;
10 | public object Object
11 | {
12 | get => _object;
13 | protected set
14 | {
15 | if (Equals(_object, value)) { return; }
16 |
17 | _object = value;
18 | _onChange?.Invoke(this);
19 | }
20 | }
21 |
22 | public string Label { get; }
23 | public string? Tooltip { get; }
24 |
25 | private readonly Action? _onChange;
26 |
27 | protected ValueSetting(object @default, string label, string? tooltip, Action? onChange)
28 | {
29 | _default = @default;
30 | _object = @default;
31 |
32 | Label = label;
33 | Tooltip = tooltip;
34 |
35 | _onChange = onChange;
36 | }
37 |
38 | public override void Refresh() => _onChange?.Invoke(this);
39 |
40 | public override void ToDefault() => Object = _default;
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/source/Engine/Lang.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Verse;
3 |
4 | namespace RimHUD.Engine
5 | {
6 | public static class Lang
7 | {
8 | public static bool HasKey(string key) => LanguageDatabase.activeLanguage!.HaveTextForKey($"{Mod.Id}.{key}");
9 |
10 | public static string Get(string key) => $"{Mod.Id}.{key}".Translate();
11 |
12 | public static string Get(string key, params object?[] args)
13 | {
14 | try { return string.Format($"{Mod.Id}.{key}".Translate(), args); }
15 | catch (Exception exception)
16 | {
17 | Report.Error($"Translation key '{key}' threw the following exception: {exception.Message}");
18 | return Get(key);
19 | }
20 | }
21 |
22 | public static string GetIndexed(string key, int index) => Get(key).Split('|')[index];
23 |
24 | public static string AdjectiveNoun(string? adjective, string? noun) => Get("Language.AdjectiveNounOrder", adjective, noun).Trim();
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/source/Engine/State.cs:
--------------------------------------------------------------------------------
1 | using RimHUD.Configuration;
2 | using RimHUD.Interface.Hud.Layers;
3 | using RimHUD.Interface.Screen;
4 | using RimWorld.Planet;
5 | using Verse;
6 |
7 | namespace RimHUD.Engine
8 | {
9 | public static class State
10 | {
11 | public static bool Activated { get; set; } = true;
12 | private static bool Active => Activated && Current.ProgramState is ProgramState.Playing;
13 |
14 | public static Pawn? SelectedPawn => Find.Selector?.SingleSelectedThing as Pawn;
15 |
16 | private static bool ShowPane => Active && !WorldRendererUtility.WorldRenderedNow && SelectedPawn is not null;
17 |
18 | public static bool ModifyPane => ShowPane && Theme.InspectPaneTabModify.Value;
19 | public static bool CompressLetters => Active && !Theme.DockedMode.Value && Theme.LetterCompress.Value;
20 | public static bool HudFloatingVisible => !Theme.DockedMode.Value && ShowPane;
21 |
22 | public static LayoutLayer CurrentLayout => Theme.DockedMode.Value ? LayoutLayer.Docked : LayoutLayer.Floating;
23 |
24 | public static void ClearCache()
25 | {
26 | InspectPaneLog.ClearCache();
27 | LayoutLayer.Docked.Flush();
28 | LayoutLayer.Floating.Flush();
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/source/Extensions/BaseExtensions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 |
6 | namespace RimHUD.Extensions
7 | {
8 | public static class BaseExtensions
9 | {
10 | public static int LastIndex(this IList self) => self.Count - 1;
11 | public static int Half(this int self) => self / 2;
12 | public static float Half(this float self) => self / 2f;
13 |
14 | public static IEnumerable WhereNotNull(this IEnumerable self) where T : class => self.Where(static item => item is not null)!;
15 |
16 | public static int ComparePartial(this Version self, Version? other)
17 | {
18 | if (other is null) { return 1; }
19 |
20 | if (self.Major > other.Major) { return 1; }
21 | if (self.Major < other.Major) { return -1; }
22 |
23 | if (self.Minor is -1 || other.Minor is -1) { return 0; }
24 | if (self.Minor > other.Minor) { return 1; }
25 | if (self.Minor < other.Minor) { return -1; }
26 |
27 | if (self.Build is -1 || other.Build is -1) { return 0; }
28 | if (self.Build > other.Build) { return 1; }
29 | if (self.Build < other.Build) { return -1; }
30 |
31 | if (self.Revision is -1 || other.Revision is -1) { return 0; }
32 | if (self.Revision > other.Revision) { return 1; }
33 | if (self.Revision < other.Revision) { return -1; }
34 |
35 | return 0;
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/source/Extensions/DataExtensions.cs:
--------------------------------------------------------------------------------
1 | using Verse;
2 |
3 | namespace RimHUD.Extensions
4 | {
5 | public static class DataExtensions
6 | {
7 | public static string GetDefNameOrLabel(this Def self) => self.LabelCap.NullOrWhitespace() ? self.defName : self.LabelCap.ToString();
8 |
9 | public static bool IsPlayerControlled(this Pawn self) => self is { Dead: false, playerSettings: not null } && ((self.Faction?.IsPlayer ?? false) || (self.HostFaction?.IsPlayer ?? false));
10 | public static bool IsPlayerFaction(this Pawn self) => self.Faction?.IsPlayer ?? false;
11 | public static bool IsPlayerManaged(this Pawn self) => self.IsPlayerFaction() || (self.HostFaction?.IsPlayer ?? false);
12 | public static bool IsHumanlike(this Pawn self) => self.RaceProps?.Humanlike ?? false;
13 | public static bool IsAnimal(this Pawn self) => self.RaceProps?.Animal ?? false;
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/source/Extensions/EnumExtensions.cs:
--------------------------------------------------------------------------------
1 | using RimHUD.Configuration;
2 | using RimHUD.Configuration.Settings;
3 | using RimHUD.Engine;
4 | using RimHUD.Interface.Hud.Widgets;
5 | using UnityEngine;
6 |
7 | namespace RimHUD.Extensions
8 | {
9 | public static class EnumExtensions
10 | {
11 | public static string GetLabel(this BarColorStyle self) => Lang.Get($"Layout.BarColorStyle.{self}");
12 |
13 | public static Color GetColor(this BarColorStyle self, float percentage) => self switch
14 | {
15 | BarColorStyle.LowOnly => Theme.BarLowColor.Value,
16 | BarColorStyle.MainToLow => Color.Lerp(Theme.BarMainColor.Value, Theme.BarLowColor.Value, percentage),
17 | BarColorStyle.MainOnly => Theme.BarMainColor.Value,
18 | _ => Color.Lerp(Theme.BarLowColor.Value, Theme.BarMainColor.Value, percentage)
19 | };
20 |
21 | public static TextStyle GetActual(this WidgetTextStyle self) => self switch
22 | {
23 | WidgetTextStyle.Small => Theme.SmallTextStyle,
24 | WidgetTextStyle.Large => Theme.LargeTextStyle,
25 | _ => Theme.RegularTextStyle
26 | };
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/source/Extensions/IOExtensions.cs:
--------------------------------------------------------------------------------
1 | using System.IO;
2 |
3 | namespace RimHUD.Extensions
4 | {
5 | public static class IOExtensions
6 | {
7 | public static T Refreshed(this T self) where T : FileSystemInfo
8 | {
9 | self.Refresh();
10 | return self;
11 | }
12 |
13 | public static bool ExistsNow(this FileSystemInfo self) => self.Refreshed().Exists;
14 |
15 | public static string NameWithoutExtension(this FileInfo self) => Path.GetFileNameWithoutExtension(self.Name);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/source/Extensions/TextExtensions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Text;
3 | using RimHUD.Configuration;
4 | using RimHUD.Interface;
5 | using RimHUD.Interface.Hud.Models;
6 | using RimWorld;
7 | using UnityEngine;
8 | using Verse;
9 |
10 | namespace RimHUD.Extensions
11 | {
12 | public static class TextExtensions
13 | {
14 | public static string Italic(this string? self) => $"{self}";
15 | public static string Bold(this string self) => $"{self}";
16 | public static string ColorizeHex(this string self, string hex) => $"{self}";
17 | public static string Size(this string self, int size) => $"{self}";
18 | public static string SmallSize(this string self) => self.Size(WidgetsPlus.SmallFontSize);
19 |
20 | public static string? WithValue(this string? self, string? value) => self.NullOrWhitespace() || value.NullOrWhitespace() ? null : $"{self}: {value}";
21 | public static string? WithValue(this TaggedString self, string? value) => self.ToString().WithValue(value);
22 |
23 | public static string ToStringTrimmed(this StringBuilder self) => self.ToString().TrimEndNewlines()!.Trim();
24 | public static string? ToTooltip(this StringBuilder self) => self.Length > 0 ? self.ToStringTrimmed() : null;
25 |
26 | public static int? ToInt(this string self) => int.TryParse(self, out var result) ? result : null;
27 | public static bool? ToBool(this string self) => bool.TryParse(self, out var result) ? result : null;
28 | public static T? ToEnum(this string self) where T : struct => Enum.TryParse(self, out var result) ? result : null;
29 | public static string ToDecimalString(this int self, int remainder) => !Theme.ShowDecimals.Value ? self.ToString().Bold() : $"{self.ToString().Bold()}.{(remainder >= 100 ? "99" : remainder.ToString("D2")).Size(Theme.SmallTextStyle.ActualSize)}";
30 | public static int ToPercentageInt(this float self) => Mathf.RoundToInt(self * 100f);
31 | public static float ToPercentageFloat(this int self) => self / 100f;
32 |
33 | public static string FlattenWithSeparator(this string text, string separator)
34 | {
35 | if (text.NullOrWhitespace()) { return text; }
36 | text = text.Replace("\r", string.Empty);
37 |
38 | return string.Join(separator, text.Split(new[] { '\n' }, StringSplitOptions.RemoveEmptyEntries));
39 | }
40 |
41 | public static void AppendLineIfNotEmpty(this StringBuilder self, string? text)
42 | {
43 | if (!text.NullOrWhitespace()) { self.AppendLine(text); }
44 | }
45 |
46 | public static void AppendValue(this StringBuilder self, string? label, string? value)
47 | {
48 | if (!label.NullOrWhitespace() && !value.NullOrWhitespace()) { self.AppendLine(label.WithValue(value)); }
49 | }
50 |
51 | public static void AppendStatLine(this StringBuilder self, StatDef def)
52 | {
53 | if (def.Worker?.IsDisabledFor(Active.Pawn) ?? true) { return; }
54 | self.AppendValue(def.LabelCap, def.ValueToString(Active.Pawn.GetStatValue(def)));
55 | }
56 |
57 | public static void AppendNeedLine(this StringBuilder self, Pawn pawn, NeedDef def)
58 | {
59 | if (pawn.needs is null) { return; }
60 | self.AppendValue(def.LabelCap, pawn.needs.TryGetNeed(def)?.CurLevelPercentage.ToStringPercent());
61 | }
62 |
63 | public static bool NullOrWhitespace(this string? self) => string.IsNullOrWhiteSpace(self);
64 | public static bool NullOrWhitespace(this TaggedString self) => self.RawText.NullOrWhitespace();
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/source/Extensions/XmlExtensions.cs:
--------------------------------------------------------------------------------
1 | using System.Xml.Linq;
2 |
3 | namespace RimHUD.Extensions
4 | {
5 | public static class XmlExtensions
6 | {
7 | public static void AddAttribute(this XElement self, string name, string? value)
8 | {
9 | if (value.NullOrWhitespace()) { return; }
10 | self.Add(new XAttribute(name, value));
11 | }
12 |
13 | public static void AddAttribute(this XElement self, string name, T value, T? @default = default)
14 | {
15 | if (!Equals(value, @default)) { self.AddAttribute(name, value?.ToString()); }
16 | }
17 |
18 | public static string? GetAttribute(this XElement self, string name) => self.Attribute(name)?.Value ?? null;
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/source/External/CustomBarDef.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using RimHUD.Engine;
3 | using RimHUD.Extensions;
4 | using RimHUD.Interface.Hud;
5 | using RimHUD.Interface.Hud.Models;
6 | using RimHUD.Interface.Hud.Widgets;
7 | using Verse;
8 |
9 | namespace RimHUD
10 | {
11 | public sealed class CustomBarDef : ExternalWidgetDef, IModel
12 | {
13 | [DefaultValue(WidgetTextStyle.Regular)]
14 | public WidgetTextStyle textStyle;
15 |
16 | public BarColorStyle colorStyle;
17 |
18 | [Unsaved]
19 | private ExternalMethodHandler<(string? label, string? value, float fill, float[]? thresholds, Func? tooltip, Action? onHover, Action? onClick)>? _getParameters;
20 |
21 | public IWidget Build(HudArgs? args)
22 | {
23 | var parameters = _getParameters?.Invoke(Active.Pawn) ?? throw new Exception($"Error getting {nameof(CustomBarDef)} parameters.").AddData(resetOnly: true);
24 | return new BarWidget(parameters.label, parameters.value, parameters.fill, parameters.thresholds, parameters.tooltip, parameters.onHover, parameters.onClick, textStyle.GetActual(), colorStyle);
25 | }
26 |
27 | protected override void InitializeV1()
28 | {
29 | _getParameters = GetHandler<(string? label, string? value, float fill, float[]? thresholds, Func? tooltip, Action? onHover, Action? onClick)>(true, "GetParameters", typeof(Pawn));
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/source/External/CustomNeedDef.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using RimHUD.Interface.Hud;
3 | using RimHUD.Interface.Hud.Models;
4 | using RimHUD.Interface.Hud.Models.Bars;
5 | using RimHUD.Interface.Hud.Widgets;
6 | using RimWorld;
7 | using Verse;
8 |
9 | namespace RimHUD
10 | {
11 | public sealed class CustomNeedDef : ExternalWidgetDef, IModel
12 | {
13 | public NeedDef? needDef;
14 |
15 | public BarColorStyle? colorStyle;
16 |
17 | [Unsaved]
18 | private ExternalMethodHandler? _getTooltip;
19 |
20 | private Func GetTooltip => () => _getTooltip?.Invoke(Active.Pawn);
21 |
22 | public IWidget? Build(HudArgs? args) => new NeedBar(needDef!, GetTooltip, colorStyle).Build(args);
23 |
24 | protected override void InitializeV1()
25 | {
26 | if (needDef is null) { throw new Exception("NeedDef is missing."); }
27 |
28 | _getTooltip = GetHandler(false, "GetTooltip", typeof(Pawn));
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/source/External/CustomSelectorDef.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using RimHUD.Engine;
3 | using RimHUD.Extensions;
4 | using RimHUD.Interface.Hud;
5 | using RimHUD.Interface.Hud.Models;
6 | using RimHUD.Interface.Hud.Widgets;
7 | using UnityEngine;
8 | using Verse;
9 |
10 | namespace RimHUD
11 | {
12 | public sealed class CustomSelectorDef : ExternalWidgetDef, IModel
13 | {
14 | [DefaultValue(WidgetTextStyle.Small)]
15 | public WidgetTextStyle textStyle;
16 |
17 | [Unsaved]
18 | private ExternalMethodHandler<(string? label, Func? tooltip, Action? onClick, Action? onHover, Color? backColor)>? _getParameters;
19 |
20 | public IWidget Build(HudArgs? args)
21 | {
22 | var parameters = _getParameters?.Invoke(Active.Pawn) ?? throw new Exception($"Error getting {nameof(CustomSelectorDef)} parameters.").AddData(resetOnly: true);
23 | return new SelectorWidget(parameters.label, parameters.tooltip, parameters.onHover, parameters.onClick, textStyle.GetActual(), parameters.backColor);
24 | }
25 |
26 | protected override void InitializeV1() => _getParameters = GetHandler<(string? label, Func? tooltip, Action? onClick, Action? onHover, Color? backColor)>(true, "GetParameters", typeof(Pawn));
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/source/External/CustomValueDef.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using RimHUD.Engine;
3 | using RimHUD.Extensions;
4 | using RimHUD.Interface.Hud;
5 | using RimHUD.Interface.Hud.Models;
6 | using RimHUD.Interface.Hud.Widgets;
7 | using Verse;
8 |
9 | namespace RimHUD
10 | {
11 | public sealed class CustomValueDef : ExternalWidgetDef, IModel
12 | {
13 | [DefaultValue(WidgetTextStyle.Small)]
14 | public WidgetTextStyle textStyle;
15 |
16 | [Unsaved]
17 | private ExternalMethodHandler<(string? label, string? value, Func? tooltip, Action? onHover, Action? onClick)>? _getParameters;
18 |
19 | public IWidget Build(HudArgs? args)
20 | {
21 | var parameters = _getParameters?.Invoke(Active.Pawn) ?? throw new Exception($"Error getting {nameof(CustomValueDef)} parameters.").AddData(resetOnly: true);
22 | return new ValueWidget(parameters.value is null ? null : parameters.label, parameters.value ?? parameters.label, parameters.tooltip, parameters.onHover, parameters.onClick, textStyle.GetActual());
23 | }
24 |
25 | protected override void InitializeV1() => _getParameters = GetHandler<(string? label, string? value, Func? tooltip, Action? onHover, Action? onClick)>(true, "GetParameters", typeof(Pawn));
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/source/External/CustomWidgetDef.cs:
--------------------------------------------------------------------------------
1 | using RimHUD.Interface.Hud.Models;
2 | using RimHUD.Interface.Hud.Widgets;
3 | using UnityEngine;
4 | using Verse;
5 |
6 | namespace RimHUD
7 | {
8 | public sealed class CustomWidgetDef : ExternalWidgetDef, IWidget
9 | {
10 | [Unsaved]
11 | private ExternalMethodHandler? _onDraw;
12 | [Unsaved]
13 | private ExternalMethodHandler? _getMaxHeight;
14 |
15 | public float GetMaxHeight => _getMaxHeight?.Invoke() ?? 0f;
16 | public bool Draw(Rect rect) => _onDraw?.Invoke(Active.Pawn, rect) ?? false;
17 |
18 | protected override void InitializeV1()
19 | {
20 | _onDraw = GetHandler(true, "OnDraw", typeof(Pawn), typeof(Rect));
21 | _getMaxHeight = GetHandler(true, "GetMaxHeight");
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/source/External/ExternalWidgetDef.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Text.RegularExpressions;
3 | using HarmonyLib;
4 | using RimHUD.Engine;
5 | using RimHUD.Extensions;
6 | using Verse;
7 |
8 | namespace RimHUD
9 | {
10 | public abstract class ExternalWidgetDef : Def
11 | {
12 | private static readonly Regex FastInvokeHandlerMethodNameRegex = new("FastInvoke_(.+)_indirect");
13 |
14 | public int apiVersion;
15 |
16 | public Type? defClass;
17 |
18 | public bool Initialized { get; private set; }
19 |
20 | public override void ResolveReferences()
21 | {
22 | try
23 | {
24 | if (apiVersion is 0)
25 | {
26 | apiVersion = 1;
27 | Report.Warning($"{GetLogDescription()} did not set the api version - defaulting to v1.");
28 | }
29 |
30 | base.ResolveReferences();
31 |
32 | switch (apiVersion)
33 | {
34 | case 1:
35 | InitializeV1();
36 | break;
37 | default:
38 | throw new Exception("Unsupported api version.");
39 | }
40 |
41 | Initialized = true;
42 | }
43 | catch (Exception exception) { throw exception.AddData($"{GetLogDescription()} using api v{apiVersion} threw an exception: ", true); }
44 | }
45 |
46 | protected virtual void InitializeV1()
47 | { }
48 |
49 | protected ExternalMethodHandler? GetHandler(bool isRequired, string methodName, params Type[] parameterTypes)
50 | {
51 | if (defClass is null)
52 | {
53 | if (!isRequired) { return null; }
54 | throw new Exception("Required defClass not found.");
55 | }
56 |
57 | var method = AccessTools.Method(defClass, methodName, parameterTypes);
58 | if (method is null) { return isRequired ? throw new Exception($"No method '{methodName}' in '{defClass.FullName}' with expected signature.") : null; }
59 | if (method.ReturnType != typeof(T)) { throw new Exception($"Method '{methodName}' has unexpected return type."); }
60 |
61 | var handler = MethodInvoker.GetHandler(method);
62 | if (handler is not null) { return new ExternalMethodHandler(handler); }
63 |
64 | if (!isRequired) { return null; }
65 | throw new Exception($"Error getting handler for '{methodName}'");
66 | }
67 |
68 | private string GetLogDescription() => $"Widget '{this.GetDefNameOrLabel()}' from mod '{modContentPack?.Name ?? ""}'";
69 |
70 | protected readonly struct ExternalMethodHandler
71 | {
72 | private readonly FastInvokeHandler _handler;
73 |
74 | public ExternalMethodHandler(FastInvokeHandler handler) => _handler = handler;
75 |
76 | public T Invoke(params object[] parameters)
77 | {
78 | try { return (T)_handler.Invoke(null, parameters); }
79 | catch (Exception exception) { throw exception.AddData($"Invoking method '{FastInvokeHandlerMethodNameRegex.Match(_handler.Method.Name).Value ?? ""}' threw an exception: ", true); }
80 | }
81 | }
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/source/Integration/IntegratedMod.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using HarmonyLib;
4 | using RimHUD.Engine;
5 | using RimHUD.Extensions;
6 | using Verse;
7 |
8 | namespace RimHUD.Integration
9 | {
10 | public abstract class IntegratedMod
11 | {
12 | private readonly string _name;
13 |
14 | private readonly Type? _integrator;
15 |
16 | protected bool IsActive => Enabled && _integrator is not null;
17 |
18 | protected bool Enabled { get; private set; }
19 |
20 | protected Traverse Traverse => Traverse.Create(_integrator) ?? throw new Exception($"Error creating Traverse integrator for '{_name}'.");
21 |
22 | protected IntegratedMod(string name, string assemblyName, string integratorName, Version? versionExpected = null)
23 | {
24 | _name = name;
25 |
26 | var modContentPack = LoadedModManager.RunningMods.FirstOrDefault(mod => mod.Name == name);
27 | if (modContentPack is null) { return; }
28 |
29 | var mainAssembly = modContentPack.assemblies!.loadedAssemblies.FirstOrDefault(assembly => assembly.GetName().Name == assemblyName);
30 | if (mainAssembly is null)
31 | {
32 | Report.Warning($"Integrated mod '{name}' does not contain expected assembly.");
33 | return;
34 | }
35 |
36 | var versionFound = mainAssembly.GetName().Version;
37 |
38 | if (versionExpected is not null && versionExpected.ComparePartial(versionFound) is not 0) { Report.Log($"The loaded version of '{name}' ({versionFound}) is different from expected ({versionExpected})"); }
39 |
40 | _integrator = mainAssembly.GetType(integratorName);
41 | if (_integrator is null)
42 | {
43 | Report.Warning($"Integrator type '{integratorName}' not found for '{name}'.");
44 | return;
45 | }
46 |
47 | if (!IsActive) { return; }
48 |
49 | Enabled = true;
50 | Report.Log($"Integrated with {name}");
51 | }
52 |
53 | protected void DisableFrom(Exception exception)
54 | {
55 | Enabled = false;
56 | Report.Warning($"Integrated mod '{_name}' disabled due to the following exception:\n{exception.Message}.");
57 | }
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/source/Integration/Integrations.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using RimHUD.Engine;
3 | using RimHUD.Integration.Multiplayer;
4 | using RimHUD.Integration.PawnRules;
5 |
6 | namespace RimHUD.Integration
7 | {
8 | public static class Integrations
9 | {
10 | private static readonly Type[] Types =
11 | {
12 | typeof(Mod_Multiplayer),
13 | typeof(Mod_PawnRules)
14 | };
15 |
16 | public static void Load()
17 | {
18 | foreach (var type in Types)
19 | {
20 | try { Activator.CreateInstance(type); }
21 | catch (Exception exception) { Report.Warning($"Integrated mod '{type.Name}' failed to register due to the following error:\n{exception.Message}."); }
22 | }
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/source/Integration/Multiplayer/Mod_Multiplayer.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using HarmonyLib;
3 | using RimHUD.Engine;
4 | using RimWorld;
5 | using Verse;
6 |
7 | namespace RimHUD.Integration.Multiplayer
8 | {
9 | public sealed class Mod_Multiplayer : IntegratedMod
10 | {
11 | public Mod_Multiplayer() : base("Multiplayer", "0MultiplayerAPI", "Multiplayer.API.MP")
12 | {
13 | try
14 | {
15 | if (!Traverse.Field("enabled")!.GetValue()) { return; }
16 |
17 | var registerSyncMethod = Traverse.Method("RegisterSyncMethod", new[] { typeof(Type), typeof(string), AccessTools.TypeByName("Multiplayer.API.SyncType")?.MakeArrayType() ?? throw new Exception("Failed to find RegisterSyncMethod argument types.") });
18 | if (registerSyncMethod is null || !registerSyncMethod.MethodExists()) { throw new Exception("Failed to find RegisterSyncMethod."); }
19 |
20 | registerSyncMethod.GetValue(typeof(Mod_Multiplayer), nameof(SetSelfTend), null);
21 |
22 | registerSyncMethod.GetValue(typeof(Mod_Multiplayer), nameof(SetFoodRestriction), null);
23 | registerSyncMethod.GetValue(typeof(Mod_Multiplayer), nameof(SetAssignment), null);
24 | registerSyncMethod.GetValue(typeof(Mod_Multiplayer), nameof(SetArea), null);
25 | registerSyncMethod.GetValue(typeof(Mod_Multiplayer), nameof(SetOutfit), null);
26 |
27 | Report.Log($"Multiplayer ready with API {Traverse.Field("API")!.GetValue()}");
28 | }
29 | catch (Exception exception) { DisableFrom(exception); }
30 | }
31 |
32 | public static void SetSelfTend(Pawn pawn, bool value) => pawn.playerSettings!.selfTend = value;
33 |
34 | public static void SetFoodRestriction(Pawn pawn, FoodPolicy value) => pawn.foodRestriction!.CurrentFoodPolicy = value;
35 |
36 | public static void SetAssignment(Pawn pawn, int hour, TimeAssignmentDef value) => pawn.timetable!.SetAssignment(hour, value);
37 |
38 | public static void SetArea(Pawn pawn, Area? value) => pawn.playerSettings!.AreaRestrictionInPawnCurrentMap = value;
39 |
40 | public static void SetOutfit(Pawn pawn, ApparelPolicy value) => pawn.outfits!.CurrentApparelPolicy = value;
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/source/Integration/PawnRules/Mod_PawnRules.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using RimHUD.Engine;
3 | using RimHUD.Interface.Hud.Models;
4 |
5 | namespace RimHUD.Integration.PawnRules
6 | {
7 | public sealed class Mod_PawnRules : IntegratedMod
8 | {
9 | private static Mod_PawnRules? _instance;
10 |
11 | public static bool IsAvailable => (_instance?.IsActive ?? false) && CanHaveRules();
12 |
13 | public Mod_PawnRules() : base("Pawn Rules", "PawnRules", "PawnRules.Integration.RimHUD")
14 | {
15 | try
16 | {
17 | Traverse.Property("ReplaceFoodSelector")!.SetValue(true);
18 | Traverse.Property("HideGizmo")!.SetValue(true);
19 |
20 | _instance = this;
21 | }
22 | catch (Exception exception) { DisableFrom(exception); }
23 | }
24 |
25 | private static string GetRules() => _instance!.Traverse.Method("GetRules", Active.Pawn)!.GetValue();
26 |
27 | private static void OpenRules() => _instance!.Traverse.Method("OpenRules", Active.Pawn)!.GetValue();
28 |
29 | private static bool CanHaveRules() => _instance!.Traverse.Method("CanHaveRules", Active.Pawn)!.GetValue();
30 |
31 | public sealed class RulesSelector : SelectorModel
32 | {
33 | protected override string? Label { get; }
34 |
35 | protected override Action? OnClick { get; }
36 |
37 | public RulesSelector()
38 | {
39 | try
40 | {
41 | if (!_instance!.IsActive || !CanHaveRules()) { return; }
42 |
43 | Label = Lang.Get("Integration.PawnRules.RuleNameFormat", GetRules());
44 |
45 | OnClick = static () => OpenRules();
46 | }
47 | catch (Exception exception)
48 | {
49 | Label = null;
50 | _instance!.DisableFrom(exception);
51 | Report.HandleWarning(exception);
52 | }
53 | }
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/source/Interface/Dialog/Dialog_Alert.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using RimHUD.Engine;
3 | using RimHUD.Extensions;
4 | using UnityEngine;
5 | using Verse;
6 |
7 | namespace RimHUD.Interface.Dialog
8 | {
9 | public sealed class Dialog_Alert : Window
10 | {
11 | public override Vector2 InitialSize { get; }
12 |
13 | private readonly string _message;
14 | private readonly Buttons _buttons;
15 | private readonly Action? _onAccept;
16 | private readonly Action? _onCancel;
17 |
18 | private bool _isAccepted;
19 |
20 | private Dialog_Alert(string message, Buttons buttons = Buttons.Ok, Action? onAccept = null, Action? onCancel = null)
21 | {
22 | doCloseButton = false;
23 | closeOnAccept = true;
24 | closeOnClickedOutside = false;
25 | absorbInputAroundWindow = true;
26 | draggable = true;
27 |
28 | _message = message;
29 | _buttons = buttons;
30 | _onAccept = onAccept;
31 | _onCancel = onCancel;
32 |
33 | GUIPlus.SetWrap(true);
34 | GUIPlus.SetFont(GameFont.Small);
35 | InitialSize = new Vector2(400f, 80f + Text.CalcHeight(_message, 364f));
36 | GUIPlus.ResetFont();
37 | GUIPlus.ResetWrap();
38 | }
39 |
40 | public static void Open(string message, Buttons buttons = Buttons.Ok, Action? onAccept = null, Action? onCancel = null) => Find.WindowStack!.Add(new Dialog_Alert(message, buttons, onAccept, onCancel));
41 |
42 | public override void DoWindowContents(Rect rect)
43 | {
44 | var listing = new Listing_Standard();
45 | var vGrid = rect.GetVGrid(4f, -1f, WidgetsPlus.ButtonHeight);
46 |
47 | listing.Begin(vGrid[1]);
48 | listing.Label(_message);
49 | listing.End();
50 |
51 | var hGrid = vGrid[2].GetHGrid(4f, 100f, -1f);
52 |
53 | listing.Begin(_buttons is Buttons.Ok ? vGrid[2] : hGrid[1]);
54 |
55 | if (listing.ButtonText(_buttons is Buttons.YesNo ? Lang.Get("Interface.Button.Yes") : Lang.Get("Interface.Button.OK")))
56 | {
57 | _isAccepted = true;
58 | _onAccept?.Invoke();
59 | Close();
60 | }
61 |
62 | listing.End();
63 |
64 | if (_buttons is Buttons.Ok) { return; }
65 |
66 | listing.Begin(hGrid[2]);
67 | if (listing.ButtonText(_buttons is Buttons.YesNo ? Lang.Get("Interface.Button.No") : Lang.Get("Interface.Button.Cancel"))) { Close(); }
68 | listing.End();
69 | }
70 |
71 | public override void Close(bool doCloseSound = true)
72 | {
73 | if (!_isAccepted) { _onCancel?.Invoke(); }
74 | base.Close(doCloseSound);
75 | }
76 |
77 | public enum Buttons
78 | {
79 | Ok,
80 | YesNo
81 | }
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/source/Interface/Dialog/Dialog_Config.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using RimHUD.Configuration;
3 | using RimHUD.Engine;
4 | using RimHUD.Extensions;
5 | using RimHUD.Interface.Dialog.Tabs;
6 | using RimHUD.Interface.Hud;
7 | using UnityEngine;
8 | using Verse;
9 |
10 | namespace RimHUD.Interface.Dialog
11 | {
12 | public sealed class Dialog_Config : WindowPlus
13 | {
14 | private const float TabWidth = 160f;
15 | private const float TabHeight = 30f;
16 | private const float ButtonWidth = 120f;
17 | private const float ButtonHeight = 40f;
18 |
19 | private static readonly Tab[] TabOrder =
20 | {
21 | new Tab_ConfigDesign(),
22 | new Tab_ConfigContent(),
23 | new Tab_ConfigColors(),
24 | new Tab_ConfigCredits()
25 | };
26 |
27 | private readonly TabManager _tabs;
28 |
29 | private Dialog_Config() : base(new Vector2(800f, 700f), Lang.Get("Interface.Dialog_Config.Title"), Lang.HasKey("Language.TranslatedBy") ? Lang.Get("Language.TranslatedBy") : null)
30 | {
31 | onlyOneOfTypeAllowed = true;
32 | absorbInputAroundWindow = false;
33 | preventCameraMotion = false;
34 | doCloseButton = false;
35 |
36 | _tabs = new TabManager(TabWidth, TabHeight, TabOrder);
37 | if (!Tutorial.IsComplete) { Tutorial.Presentation.Stages.DoDialogConfigTab(_tabs); }
38 | }
39 |
40 | public static void Toggle()
41 | {
42 | var current = Find.WindowStack!.WindowOfType();
43 | if (current is null) { Open(); }
44 | else { current.Close(); }
45 | }
46 |
47 | public static void Open() => Find.WindowStack!.Add(new Dialog_Config());
48 |
49 | public override void PostClose()
50 | {
51 | Tutorial.Presentation.Stages.CheckComplete(true);
52 |
53 | if (!State.Activated) { return; }
54 | Persistent.Save();
55 | }
56 |
57 | protected override void DrawContent(Rect rect)
58 | {
59 | try
60 | {
61 | var grid = rect.GetVGrid(GUIPlus.MediumPadding, -1f, ButtonHeight);
62 | var hGrid = grid[2].GetHGrid(GUIPlus.MediumPadding, ButtonWidth, ButtonWidth, ButtonWidth);
63 |
64 | if (!Tutorial.IsComplete)
65 | {
66 | Tutorial.Presentation.Stages.DoDialogConfigTab(_tabs);
67 |
68 | Tutorial.Presentation.Stages.SetDialogConfigCloseButton(hGrid[3]);
69 | Tutorial.Presentation.Stages.DoDialogConfigEarly();
70 | }
71 |
72 | _tabs.Draw(grid[1]);
73 |
74 | if (WidgetsPlus.DrawButton(hGrid[1], Lang.Get("Interface.Dialog_Config.SetToDefault"))) { ConfirmSetToDefault(); }
75 | else if (WidgetsPlus.DrawButton(hGrid[2], Lang.Get("Interface.Dialog_Config.OpenFolder"))) { Persistent.OpenConfigFolder(); }
76 | else if (WidgetsPlus.DrawButton(hGrid[3], Lang.Get("Interface.Button.Close"))) { Close(); }
77 |
78 | WidgetsPlus.DrawText(grid[2], $"Version {Mod.Version}{(Prefs.DevMode && Mod.DevMode ? "[DEV MODE - Click to disable]".Colorize(Color.yellow) : null)}", GameFont.Tiny, alignment: TextAnchor.LowerRight);
79 |
80 | if (!Event.current!.shift || !Widgets.ButtonInvisible(grid[2]) || !Prefs.DevMode) { return; }
81 |
82 | Mod.DevMode = !Mod.DevMode;
83 | HudTimings.Restart();
84 | }
85 | catch (Exception exception)
86 | {
87 | Report.HandleError(exception);
88 | Close();
89 | }
90 | }
91 |
92 | protected override void LateWindowOnGUI(Rect inRect)
93 | {
94 | if (!Tutorial.IsComplete) { Tutorial.Presentation.Stages.DoDialogConfigLate(windowRect.AtZero()); }
95 | }
96 |
97 | private void ConfirmSetToDefault() => Dialog_Alert.Open(Lang.Get("Interface.Alert.SetToDefault"), Dialog_Alert.Buttons.YesNo, SetToDefault);
98 |
99 | private void SetToDefault()
100 | {
101 | Persistent.SettingsToDefault();
102 | _tabs.Reset();
103 | }
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/source/Interface/Dialog/Dialog_Error.cs:
--------------------------------------------------------------------------------
1 | using RimHUD.Configuration;
2 | using RimHUD.Engine;
3 | using RimHUD.Extensions;
4 | using UnityEngine;
5 | using Verse;
6 |
7 | namespace RimHUD.Interface.Dialog
8 | {
9 | public sealed class Dialog_Error : Window
10 | {
11 | public override Vector2 InitialSize { get; } = new(800f, 360f);
12 | private Vector2 _scrollPosition = Vector2.zero;
13 | private Rect _scrollView;
14 |
15 | private readonly Report.ErrorInfo _info;
16 |
17 | private Dialog_Error(Report.ErrorInfo info)
18 | {
19 | doCloseButton = false;
20 | closeOnAccept = true;
21 | closeOnClickedOutside = false;
22 | absorbInputAroundWindow = true;
23 | draggable = true;
24 |
25 | _info = info;
26 | Report.Warning($"RimHUD Auto-deactivation reason:\n{_info.Message}");
27 | }
28 |
29 | public static void Open(Report.ErrorInfo info) => Find.WindowStack!.Add(new Dialog_Error(info));
30 |
31 | public override void DoWindowContents(Rect inRect)
32 | {
33 | const float buttonWidth = 120f;
34 |
35 | var listing = new ListingPlus();
36 | listing.Begin(inRect);
37 | listing.Label($"RimHUD v{Mod.Version} has automatically deactivated due to the following error(s):".Bold());
38 | listing.Label(_info.Message);
39 |
40 | if (_info.Notice is not null) { listing.Label(_info.Notice); }
41 | listing.Gap();
42 |
43 | listing.Label($"{nameof(_info.Trace)}:".Bold(), font: GameFont.Tiny);
44 | listing.End();
45 |
46 | var grid = inRect.GetVGrid(0f, listing.CurHeight, -1f, WidgetsPlus.SmallButtonHeight + GUIPlus.MediumPadding);
47 | Widgets.DrawMenuSection(grid[2]);
48 |
49 | var traceRect = grid[2].ContractedBy(GUIPlus.SmallPadding);
50 | WidgetsPlus.DrawScrollableText(traceRect, _info.Trace, ref _scrollPosition, ref _scrollView, GameFont.Tiny);
51 |
52 | grid[3].yMin += GUIPlus.MediumPadding;
53 | var buttonGrid = grid[3].GetHGrid(GUIPlus.MediumPadding, buttonWidth, -1f, buttonWidth, buttonWidth);
54 |
55 | if (WidgetsPlus.DrawButton(buttonGrid[1], "Copy to clipboard", font: GameFont.Tiny))
56 | {
57 | _info.CopyToClipboard();
58 | Report.Alert("RimHUD Auto-deactivation details copied to clipboard");
59 | }
60 |
61 | if (WidgetsPlus.DrawButton(buttonGrid[3], "Reactivate", font: GameFont.Tiny))
62 | {
63 | Close();
64 |
65 | if (_info.IsResetOnly) { Persistent.Reset(); }
66 | State.Activated = true;
67 | }
68 |
69 | if (WidgetsPlus.DrawButton(buttonGrid[4], "Close", font: GameFont.Tiny)) { Close(); }
70 | }
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/source/Interface/Dialog/Dialog_ManagePresets.cs:
--------------------------------------------------------------------------------
1 | using RimHUD.Configuration;
2 | using RimHUD.Engine;
3 | using RimHUD.Extensions;
4 | using RimHUD.Interface.Hud.Layout;
5 | using UnityEngine;
6 | using Verse;
7 |
8 | namespace RimHUD.Interface.Dialog
9 | {
10 | public sealed class Dialog_ManagePresets : WindowPlus
11 | {
12 | private Rect _scrollView;
13 | private Vector2 _scrollPosition;
14 |
15 | private LayoutPreset? _selected;
16 |
17 | private Dialog_ManagePresets() : base(new Vector2(500f, 450f), Lang.Get("Interface.Dialog_ManagePresets.Title"))
18 | {
19 | onlyOneOfTypeAllowed = true;
20 | absorbInputAroundWindow = true;
21 | preventCameraMotion = false;
22 | doCloseButton = false;
23 | }
24 |
25 | public static void Open()
26 | {
27 | LayoutPreset.RefreshList();
28 | Find.WindowStack!.Add(new Dialog_ManagePresets());
29 | }
30 |
31 | protected override void DrawContent(Rect rect)
32 | {
33 | var vGrid = rect.GetVGrid(GUIPlus.LargePadding, -1f, WidgetsPlus.ButtonHeight);
34 |
35 | var l = new ListingPlus();
36 | l.BeginScrollView(vGrid[1], ref _scrollPosition, ref _scrollView);
37 |
38 | foreach (var preset in LayoutPreset.UserList)
39 | {
40 | _selected ??= preset;
41 | if (l.RadioButton(preset.Name, _selected == preset)) { _selected = preset; }
42 | }
43 |
44 | l.EndScrollView(ref _scrollView);
45 |
46 | l.Begin(vGrid[2]);
47 |
48 | var buttonGrid = l.GetButtonGrid(-1f, -1f);
49 |
50 | if (WidgetsPlus.DrawButton(buttonGrid[1], Lang.Get("Interface.Dialog_ManagePresets.Delete"), enabled: _selected is not null))
51 | {
52 | Dialog_Alert.Open(Lang.Get("Interface.Alert.ConfirmDelete", _selected), Dialog_Alert.Buttons.YesNo, () =>
53 | {
54 | Presets.Delete(_selected!);
55 | _selected = null;
56 | });
57 | }
58 | if (WidgetsPlus.DrawButton(buttonGrid[2], Lang.Get("Interface.Button.Close"))) { Close(); }
59 |
60 | l.End();
61 | }
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/source/Interface/Dialog/Dialog_SavePreset.cs:
--------------------------------------------------------------------------------
1 | using RimHUD.Configuration;
2 | using RimHUD.Engine;
3 | using RimHUD.Interface.Hud.Layout;
4 | using UnityEngine;
5 | using Verse;
6 |
7 | namespace RimHUD.Interface.Dialog
8 | {
9 | public sealed class Dialog_SavePreset : WindowPlus
10 | {
11 | private const string NameControl = "PresetName";
12 | private string? _name;
13 |
14 | private bool _includeDocked = true;
15 | private bool _includeFloating = true;
16 | private bool _includeWidth = true;
17 | private bool _includeHeight = true;
18 | private bool _includeTabs;
19 | private bool _includeTextSizes = true;
20 |
21 | private Dialog_SavePreset() : base(new Vector2(400f, 350f), Lang.Get("Interface.Dialog_SavePreset.Title"))
22 | {
23 | onlyOneOfTypeAllowed = true;
24 | absorbInputAroundWindow = true;
25 | preventCameraMotion = false;
26 | doCloseButton = false;
27 | }
28 |
29 | public static void Open() => Find.WindowStack!.Add(new Dialog_SavePreset());
30 |
31 | public override void OnAcceptKeyPressed()
32 | {
33 | if (!Persistent.IsValidFilename(_name)) { return; }
34 | Save();
35 | }
36 |
37 | protected override void DrawContent(Rect rect)
38 | {
39 | var l = new ListingPlus();
40 | l.Begin(rect);
41 |
42 | _includeDocked = l.CheckboxLabeled(Lang.Get("Interface.Dialog_SavePreset.IncludeDocked"), _includeDocked, enabled: !_includeDocked || _includeFloating);
43 | _includeFloating = l.CheckboxLabeled(Lang.Get("Interface.Dialog_SavePreset.IncludeFloating"), _includeFloating, enabled: !_includeFloating || _includeDocked);
44 | l.GapLine();
45 |
46 | _includeWidth = l.CheckboxLabeled(Lang.Get("Interface.Dialog_SavePreset.IncludeWidth"), _includeWidth);
47 | _includeHeight = l.CheckboxLabeled(Lang.Get("Interface.Dialog_SavePreset.IncludeHeight"), _includeHeight);
48 | _includeTabs = l.CheckboxLabeled(Lang.Get("Interface.Dialog_SavePreset.IncludeTabs"), _includeTabs, enabled: _includeDocked);
49 | l.GapLine();
50 |
51 | _includeTextSizes = l.CheckboxLabeled(Lang.Get("Interface.Dialog_SavePreset.IncludeTextSizes"), _includeTextSizes);
52 | l.GapLine();
53 |
54 | l.Label(Lang.Get("Interface.Dialog_SavePreset.Name"));
55 | GUI.SetNextControlName(NameControl);
56 | _name = l.TextEntry(_name);
57 | GUI.FocusControl(NameControl);
58 | l.Gap();
59 |
60 | var buttonGrid = l.GetButtonGrid(-1f, -1f);
61 | if (WidgetsPlus.DrawButton(buttonGrid[1], Lang.Get("Interface.Button.Save"), enabled: Persistent.IsValidFilename(_name))) { Save(); }
62 | if (WidgetsPlus.DrawButton(buttonGrid[2], Lang.Get("Interface.Button.Cancel"))) { Close(); }
63 | l.End();
64 | }
65 |
66 | private void Save()
67 | {
68 | if (_name is null) { return; }
69 |
70 | LayoutPreset.SaveCurrent(_name, _includeDocked, _includeFloating, _includeWidth, _includeHeight, _includeTabs, _includeTextSizes);
71 | LayoutPreset.RefreshList();
72 |
73 | Dialog_Alert.Open(Lang.Get("Interface.Alert.PresetSaved", _name));
74 | Close();
75 | }
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/source/Interface/Dialog/Tabs/Tab.cs:
--------------------------------------------------------------------------------
1 | using UnityEngine;
2 |
3 | namespace RimHUD.Interface.Dialog.Tabs
4 | {
5 | public abstract class Tab
6 | {
7 | public abstract string Label { get; }
8 |
9 | public abstract void Draw(Rect rect);
10 |
11 | public virtual bool Show => true;
12 |
13 | public virtual void Reset()
14 | { }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/source/Interface/Dialog/Tabs/TabManager.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Linq;
3 | using RimHUD.Configuration;
4 | using RimHUD.Engine;
5 | using RimHUD.Extensions;
6 | using UnityEngine;
7 |
8 | namespace RimHUD.Interface.Dialog.Tabs
9 | {
10 | public sealed class TabManager
11 | {
12 | private const float TabPadding = 4f;
13 |
14 | private readonly Tab[] _tabs;
15 | private Tab _selected;
16 |
17 | private readonly float _tabWidth;
18 | private readonly float _tabHeight;
19 |
20 | public TabManager(float tabWidth, float tabHeight, IEnumerable tabs)
21 | {
22 | _tabWidth = tabWidth;
23 | _tabHeight = tabHeight;
24 | _tabs = tabs.WhereNotNull().ToArray();
25 |
26 | _selected = Credits.Exists ? _tabs.Last() : _tabs.First();
27 | }
28 |
29 | public void SelectType() where T : Tab => _selected = _tabs.OfType().First();
30 |
31 | public void Reset()
32 | {
33 | foreach (var tab in _tabs) { tab.Reset(); }
34 | }
35 |
36 | public void Draw(Rect rect)
37 | {
38 | if (_tabs.Length is 0) { return; }
39 |
40 | var vGrid = rect.GetVGrid(TabPadding, _tabHeight, -1f);
41 | var hGrid = vGrid[1].GetHGrid(TabPadding, Enumerable.Repeat(_tabWidth, _tabs.Length).ToArray());
42 |
43 | for (var index = 0; index < _tabs.Length; index++)
44 | {
45 | var tab = _tabs[index];
46 | GUIPlus.SetColor(tab == _selected ? Theme.ButtonSelectedColor : null);
47 | if (WidgetsPlus.DrawButton(hGrid[index + 1], tab.Label))
48 | {
49 | GUI.FocusControl(null);
50 | _selected = tab;
51 | }
52 | GUIPlus.ResetColor();
53 | }
54 |
55 | _selected.Draw(vGrid[2]);
56 | }
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/source/Interface/Dialog/Tabs/Tab_ConfigCredits.cs:
--------------------------------------------------------------------------------
1 | using RimHUD.Engine;
2 | using UnityEngine;
3 |
4 | namespace RimHUD.Interface.Dialog.Tabs
5 | {
6 | public sealed class Tab_ConfigCredits : Tab
7 | {
8 | public override bool Show => Credits.Exists;
9 |
10 | public override string Label => "Credits";
11 |
12 | public override void Draw(Rect rect) => Credits.Draw(rect);
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/source/Interface/Dialog/Tabs/Tab_ConfigDesign.cs:
--------------------------------------------------------------------------------
1 | using RimHUD.Configuration;
2 | using RimHUD.Engine;
3 | using RimHUD.Extensions;
4 | using UnityEngine;
5 |
6 | namespace RimHUD.Interface.Dialog.Tabs
7 | {
8 | public sealed class Tab_ConfigDesign : Tab
9 | {
10 | public override string Label { get; } = Lang.Get("Interface.Dialog_Config.Tab_Design");
11 |
12 | private string? _hudWidthText;
13 | private string? _hudHeightText;
14 | private string? _hudOffsetXText;
15 | private string? _hudOffsetYText;
16 | private string? _inspectPaneHeightText;
17 |
18 | public override void Reset()
19 | { }
20 |
21 | public override void Draw(Rect rect)
22 | {
23 | var hGrid = rect.GetHGrid(GUIPlus.LargePadding, -1f, -1f);
24 | var l = new ListingPlus();
25 | l.Begin(hGrid[1]);
26 |
27 | l.RangeSlider(Theme.RefreshRate);
28 | l.BoolToggle(Theme.DockedMode);
29 | l.GapLine();
30 |
31 | l.Label(Lang.Get("Theme.InspectPane").Bold());
32 | l.BoolToggle(Theme.InspectPaneTabModify, !Theme.DockedMode.Value);
33 | l.BoolToggle(Theme.InspectPaneTabAddLog, Theme.InspectPaneTabModify.Value && !Theme.DockedMode.Value);
34 | l.RangeSliderEntry(Theme.InspectPaneHeight, ref _inspectPaneHeightText, 5, Theme.InspectPaneTabModify.Value);
35 | l.RangeSlider(Theme.InspectPaneTabWidth, Theme.InspectPaneTabModify.Value);
36 | l.RangeSlider(Theme.InspectPaneMinTabs, Theme.InspectPaneTabModify.Value);
37 | l.BoolToggle(Theme.ShowFactionIcon, Theme.InspectPaneTabModify.Value);
38 | l.BoolToggle(Theme.ShowIdeoligionIcon, Theme.InspectPaneTabModify.Value);
39 | l.GapLine();
40 |
41 | l.Label(Lang.Get("Theme.Floating").Bold());
42 | l.RangeSlider(Theme.FloatingAnchor, !Theme.DockedMode.Value);
43 | l.RangeSliderEntry(Theme.FloatingOffsetX, ref _hudOffsetXText, 1, !Theme.DockedMode.Value);
44 | l.RangeSliderEntry(Theme.FloatingOffsetY, ref _hudOffsetYText, 2, !Theme.DockedMode.Value);
45 | l.RangeSliderEntry(Theme.FloatingWidth, ref _hudWidthText, 3, !Theme.DockedMode.Value);
46 | l.RangeSliderEntry(Theme.FloatingHeight, ref _hudHeightText, 4, !Theme.DockedMode.Value);
47 | l.BoolToggle(Theme.LetterCompress, !Theme.DockedMode.Value);
48 | l.RangeSlider(Theme.LetterPadding, !Theme.DockedMode.Value && Theme.LetterCompress.Value);
49 |
50 | l.End();
51 |
52 | l.Begin(hGrid[2]);
53 |
54 | l.TextStyleEditor(Theme.RegularTextStyle);
55 | l.RangeSlider(Theme.LabelWidth);
56 | l.RangeSlider(Theme.ValueWidth);
57 | l.GapLine();
58 |
59 | l.TextStyleEditor(Theme.LargeTextStyle);
60 | l.GapLine();
61 |
62 | l.TextStyleEditor(Theme.SmallTextStyle);
63 | l.GapLine();
64 |
65 | l.Label(Lang.Get("Theme.Miscellaneous").Bold());
66 | l.BoolToggle(Theme.ShowDecimals);
67 |
68 | l.End();
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/source/Interface/Dialog/WindowPlus.cs:
--------------------------------------------------------------------------------
1 | using RimHUD.Configuration;
2 | using RimHUD.Extensions;
3 | using UnityEngine;
4 | using Verse;
5 |
6 | namespace RimHUD.Interface.Dialog
7 | {
8 | public abstract class WindowPlus : Window
9 | {
10 | private const float CloseButtonOffset = 55f;
11 |
12 | protected abstract void DrawContent(Rect rect);
13 |
14 | public override Vector2 InitialSize { get; }
15 |
16 | private readonly string _title;
17 | private readonly string? _subtitle;
18 |
19 | protected WindowPlus(Vector2 size, string title, string? subtitle = null)
20 | {
21 | draggable = true;
22 | doCloseX = true;
23 | doCloseButton = true;
24 | absorbInputAroundWindow = true;
25 | closeOnClickedOutside = false;
26 | closeOnAccept = false;
27 |
28 | InitialSize = size == default ? new Vector2(800f, 600f) : size;
29 |
30 | _title = title;
31 | _subtitle = subtitle;
32 | }
33 |
34 | public override void DoWindowContents(Rect rect) => DrawContent(DrawTitle(rect));
35 |
36 | private Rect DrawTitle(Rect rect)
37 | {
38 | if (_title.NullOrEmpty()) { return rect; }
39 |
40 | GUIPlus.SetWrap(false);
41 |
42 | var header = new ListingPlus();
43 |
44 | header.Begin(rect);
45 |
46 | header.Label(_title.Bold(), font: GameFont.Medium);
47 |
48 | if (!_subtitle.NullOrWhitespace())
49 | {
50 | var titleSize = GUIPlus.GetTextSize(GUIPlus.GetGameFontStyle(GameFont.Medium), _title);
51 | var titleOffset = titleSize.x + GUIPlus.MediumPadding;
52 | var subtitleRect = new Rect(rect.x + titleOffset, rect.y, rect.width - titleOffset, titleSize.y);
53 | WidgetsPlus.DrawText(subtitleRect, _subtitle.Italic(), Theme.SmallTextStyle);
54 | }
55 |
56 | header.GapLine();
57 | header.End();
58 |
59 | var contentRect = new Rect(rect.x, rect.y + header.CurHeight, rect.width, rect.height - header.CurHeight);
60 |
61 | if (doCloseButton) { contentRect.height -= CloseButtonOffset; }
62 |
63 | GUIPlus.ResetWrap();
64 |
65 | return contentRect;
66 | }
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/source/Interface/Hud/HudArgs.cs:
--------------------------------------------------------------------------------
1 | using System.Xml.Linq;
2 | using RimHUD.Extensions;
3 | using RimHUD.Interface.Hud.Layers;
4 | using RimHUD.Interface.Hud.Models;
5 | using RimHUD.Interface.Hud.Widgets;
6 | using RimWorld;
7 | using Verse;
8 |
9 | namespace RimHUD.Interface.Hud
10 | {
11 | public sealed class HudArgs
12 | {
13 | private const string TargetsAttribute = "Targets";
14 | private const string FillHeightAttribute = "FillHeight";
15 |
16 | private const string DefNameAttribute = "DefName";
17 |
18 | private const string BarColorStyleAttribute = "BarColorStyle";
19 |
20 | public LayerTarget Targets { get; set; } = LayerTarget.All;
21 | public bool FillHeight { get; set; }
22 |
23 | public string? DefName { get; set; }
24 |
25 | public BarColorStyle? BarColorStyle { get; set; }
26 |
27 | public HudArgs()
28 | { }
29 |
30 | public HudArgs(XElement xml)
31 | {
32 | foreach (var attribute in xml.Attributes())
33 | {
34 | var key = attribute.Name.ToString();
35 | var value = attribute.Value;
36 |
37 | switch (key)
38 | {
39 | case TargetsAttribute:
40 | Targets = LayerTargetUtility.FromId(value);
41 | break;
42 | case FillHeightAttribute:
43 | FillHeight = value.ToBool() ?? false;
44 | break;
45 | case DefNameAttribute:
46 | DefName = value;
47 | break;
48 | case BarColorStyleAttribute:
49 | BarColorStyle = value.ToEnum();
50 | break;
51 | }
52 | }
53 | }
54 |
55 | public T? GetDef() where T : Def => DefName is null ? null : DefDatabase.GetNamed(DefName, false);
56 | public IWidget? GetDefAndBuild() where T : Def, IModel => GetDef()?.Build(this);
57 |
58 | public Def? GetDefFromLayerId(string id) => DefName is null
59 | ? null
60 | : id switch
61 | {
62 | HudContent.NeedDefType => GetDef(),
63 | HudContent.SkillDefType => GetDef(),
64 | HudContent.TrainableDefType => GetDef(),
65 | HudContent.StatDefType => GetDef(),
66 | HudContent.RecordDefType => GetDef(),
67 | HudContent.ExternalWidgetType => GetDef(),
68 | HudContent.ExternalValueType => GetDef(),
69 | HudContent.ExternalBarType => GetDef(),
70 | HudContent.ExternalNeedType => GetDef(),
71 | _ => null
72 | };
73 |
74 | public XElement ToXml(XElement xml)
75 | {
76 | xml.AddAttribute(TargetsAttribute, Targets.ToId());
77 | xml.AddAttribute(FillHeightAttribute, FillHeight);
78 | xml.AddAttribute(DefNameAttribute, DefName);
79 |
80 | xml.AddAttribute(BarColorStyleAttribute, BarColorStyle);
81 | return xml;
82 | }
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/source/Interface/Hud/HudLayout.cs:
--------------------------------------------------------------------------------
1 | using RimHUD.Configuration;
2 | using RimHUD.Engine;
3 | using RimHUD.Interface.Dialog;
4 | using RimHUD.Interface.Hud.Layers;
5 | using UnityEngine;
6 | using Verse;
7 |
8 | namespace RimHUD.Interface.Hud
9 | {
10 | public static class HudLayout
11 | {
12 | private static readonly float ConfigButtonSize = Mathf.Max(TexturesPlus.ConfigIcon.width, TexturesPlus.ConfigIcon.height);
13 |
14 | public static bool IsMouseOverConfigButton = true;
15 |
16 | public static Rect GetConfigButtonRect(Rect rect, bool floating) => new(rect.xMax - ConfigButtonSize, floating ? rect.y : rect.yMax - ConfigButtonSize, ConfigButtonSize, ConfigButtonSize);
17 |
18 | public static void DrawConfigButton(Rect rect, bool tutorial = false)
19 | {
20 | if ((tutorial || Tutorial.IsComplete) && Verse.Widgets.ButtonImage(rect, tutorial ? TexturesPlus.TutorialConfigIcon : TexturesPlus.ConfigIcon)) { Dialog_Config.Toggle(); }
21 | }
22 |
23 | public static void DrawDocked(Rect rect) => Draw(rect, false);
24 |
25 | public static void DrawFloating()
26 | {
27 | var rect = Theme.GetHudBounds();
28 | Verse.Widgets.DrawWindowBackground(rect);
29 |
30 | Draw(rect, true);
31 | }
32 |
33 | private static void Draw(Rect rect, bool floating)
34 | {
35 | var layoutRect = floating ? rect.ContractedBy(GUIPlus.MediumPadding) : rect;
36 | var configRect = GetConfigButtonRect(layoutRect, floating);
37 |
38 | IsMouseOverConfigButton = Mouse.IsOver(configRect);
39 |
40 | (floating ? LayoutLayer.Floating : LayoutLayer.Docked).Draw(layoutRect);
41 |
42 | if (Mouse.IsOver(rect)) { DrawConfigButton(configRect); }
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/source/Interface/Hud/HudTimings.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Diagnostics;
3 | using HarmonyLib;
4 | using RimHUD.Configuration;
5 | using RimHUD.Configuration.Settings;
6 | using RimHUD.Interface.Hud.Layers;
7 | using UnityEngine;
8 | using Verse;
9 |
10 | namespace RimHUD.Interface.Hud
11 | {
12 | public static class HudTimings
13 | {
14 | private static readonly Dictionary Layers = new();
15 |
16 | public static void Restart() => Layers.Values.Do(static timing => timing.Reset());
17 |
18 | public static void Add(BaseLayer layer) => Layers[layer] = new Timing();
19 |
20 | public static void Remove(BaseLayer layer) => Layers.Remove(layer);
21 |
22 | public static Timing? Update(BaseLayer layer)
23 | {
24 | if (!Mod.DevMode) { return null; }
25 |
26 | return Layers.TryGetValue(layer, out var timing) ? timing : null;
27 | }
28 |
29 | public sealed class Timing
30 | {
31 | private static readonly TextStyle TimingsTextStyle = new(null, Theme.SmallTextStyle, -3, -3, -3, 100, 100, 100);
32 |
33 | private static readonly Color ColorBackground = Color.black.ToTransparent(0.7f);
34 | private static readonly Color ColorForeground = Color.cyan.ToTransparent(0.2f);
35 |
36 | private readonly Stopwatch _stopwatch = new();
37 |
38 | private double _max;
39 |
40 | public void Reset()
41 | {
42 | _stopwatch.Stop();
43 | _max = 0;
44 | }
45 |
46 | public void Start() => _stopwatch.Restart();
47 |
48 | public void Finish(Rect rect, bool isPanel = false)
49 | {
50 | var value = (int)_stopwatch.ElapsedMilliseconds;
51 | if (value > _max) { _max = value; }
52 |
53 | if (isPanel) { WidgetsPlus.DrawText(rect, $"[[Max={_max}, Now={value} ms]", Theme.RegularTextStyle, Color.cyan, TextAnchor.MiddleCenter); }
54 | else
55 | {
56 | Verse.Widgets.DrawBoxSolidWithOutline(rect, ColorBackground, ColorForeground);
57 | WidgetsPlus.DrawText(rect, $"[M={_max}, N={value}]", TimingsTextStyle, Color.yellow, TextAnchor.MiddleCenter);
58 | }
59 | }
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/source/Interface/Hud/Layers/BaseLayer.cs:
--------------------------------------------------------------------------------
1 | using System.Xml.Linq;
2 | using RimHUD.Interface.Hud.Layout;
3 | using RimHUD.Interface.Hud.Models;
4 | using UnityEngine;
5 |
6 | namespace RimHUD.Interface.Hud.Layers
7 | {
8 | public abstract class BaseLayer
9 | {
10 | public abstract LayoutElementType Type { get; }
11 |
12 | public abstract string Id { get; }
13 |
14 | public abstract float Prepare();
15 | public abstract bool Draw(Rect rect);
16 |
17 | public abstract LayoutElement GetLayoutItem(LayoutEditor editor, LayoutElement parent);
18 |
19 | protected abstract XElement StartXml();
20 |
21 | public abstract void Flush();
22 |
23 | public HudArgs Args { get; }
24 |
25 | protected BaseLayer(HudArgs args) => Args = args;
26 |
27 | protected BaseLayer(XElement xml) => Args = new HudArgs(xml);
28 |
29 | public XElement ToXml() => Args.ToXml(StartXml());
30 |
31 | protected bool IsTargetted() => Args.Targets.HasTarget(Active.Target);
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/source/Interface/Hud/Layers/ContainerLayer.cs:
--------------------------------------------------------------------------------
1 | using System.Xml.Linq;
2 | using HarmonyLib;
3 | using RimHUD.Interface.Hud.Layout;
4 |
5 | namespace RimHUD.Interface.Hud.Layers
6 | {
7 | public abstract class ContainerLayer : BaseLayer where T : BaseLayer
8 | {
9 | protected abstract T[] Children { get; }
10 |
11 | protected ContainerLayer(XElement xml) : base(xml)
12 | { }
13 |
14 | public override void Flush() => Children.Do(static item => item.Flush());
15 |
16 | public override LayoutElement GetLayoutItem(LayoutEditor editor, LayoutElement? parent) => new(this, editor, parent, Children);
17 |
18 | protected override XElement StartXml()
19 | {
20 | var xml = new XElement(Id);
21 | foreach (var child in Children) { xml.Add(child.ToXml()); }
22 | return xml;
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/source/Interface/Hud/Layers/HStackLayer.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 | using System.Xml.Linq;
3 | using RimHUD.Extensions;
4 | using UnityEngine;
5 |
6 | namespace RimHUD.Interface.Hud.Layers
7 | {
8 | public sealed class HStackLayer : StackLayer
9 | {
10 | public const string Name = "HStack";
11 |
12 | public override string Id => Name;
13 |
14 | public HStackLayer(XElement xml) : base(xml)
15 | { }
16 |
17 | public override float Prepare()
18 | {
19 | if (Children.Length is 0 || !IsTargetted()) { return 0f; }
20 |
21 | var maxHeight = Children.Select(static container => container.Prepare()).Max();
22 | return Args.FillHeight ? -1f : maxHeight;
23 | }
24 |
25 | public override bool Draw(Rect rect)
26 | {
27 | if (Children.Length is 0) { return false; }
28 |
29 | var grid = rect.GetHGrid(LayoutLayer.Padding, Enumerable.Repeat(-1f, Children.Length).ToArray());
30 | var index = 1;
31 |
32 | foreach (var container in Children)
33 | {
34 | container.Draw(grid[index]);
35 | index++;
36 | }
37 |
38 | return true;
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/source/Interface/Hud/Layers/LayerTarget.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace RimHUD.Interface.Hud.Layers
4 | {
5 | [Flags]
6 | public enum LayerTarget
7 | {
8 | PlayerHumanlike = 1,
9 | PlayerCreature = 2,
10 | OtherHumanlike = 4,
11 | OtherCreature = 8,
12 | All = PlayerHumanlike | PlayerCreature | OtherHumanlike | OtherCreature
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/source/Interface/Hud/Layers/LayerTargetUtility.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Text;
3 | using RimHUD.Extensions;
4 |
5 | namespace RimHUD.Interface.Hud.Layers
6 | {
7 | public static class LayerTargetUtility
8 | {
9 | private const string PlayerHumanlike = "H";
10 | private const string PlayerCreature = "C";
11 | private const string OtherHumanlike = "h";
12 | private const string OtherCreature = "c";
13 |
14 | public static LayerTarget FromId(string? value)
15 | {
16 | if (value.NullOrWhitespace()) { return LayerTarget.All; }
17 |
18 | var targets = LayerTarget.All;
19 | if (!value!.Contains(LayerTarget.PlayerHumanlike.GetId())) { targets &= ~LayerTarget.PlayerHumanlike; }
20 | if (!value.Contains(LayerTarget.PlayerCreature.GetId())) { targets &= ~LayerTarget.PlayerCreature; }
21 | if (!value.Contains(LayerTarget.OtherHumanlike.GetId())) { targets &= ~LayerTarget.OtherHumanlike; }
22 | if (!value.Contains(LayerTarget.OtherCreature.GetId())) { targets &= ~LayerTarget.OtherCreature; }
23 |
24 | return targets;
25 | }
26 |
27 | public static string? ToId(this LayerTarget self)
28 | {
29 | if (self is LayerTarget.All) { return null; }
30 |
31 | var value = new StringBuilder();
32 | if (self.HasTarget(LayerTarget.PlayerHumanlike)) { value.Append(LayerTarget.PlayerHumanlike.GetId()); }
33 | if (self.HasTarget(LayerTarget.PlayerCreature)) { value.Append(LayerTarget.PlayerCreature.GetId()); }
34 | if (self.HasTarget(LayerTarget.OtherHumanlike)) { value.Append(LayerTarget.OtherHumanlike.GetId()); }
35 | if (self.HasTarget(LayerTarget.OtherCreature)) { value.Append(LayerTarget.OtherCreature.GetId()); }
36 |
37 | return value.Length > 0 ? value.ToString() : null;
38 | }
39 |
40 | public static bool HasTarget(this LayerTarget self, LayerTarget target)
41 | {
42 | var targettedInt = (int)target;
43 | return ((int)self & targettedInt) == targettedInt;
44 | }
45 |
46 | private static string? GetId(this LayerTarget self)
47 | {
48 | return self switch
49 | {
50 | LayerTarget.PlayerHumanlike => PlayerHumanlike,
51 | LayerTarget.PlayerCreature => PlayerCreature,
52 | LayerTarget.OtherHumanlike => OtherHumanlike,
53 | LayerTarget.OtherCreature => OtherCreature,
54 | LayerTarget.All => null,
55 | _ => throw new Exception("Invalid layer target type.")
56 | };
57 | }
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/source/Interface/Hud/Layers/PanelLayer.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Linq;
3 | using System.Xml.Linq;
4 | using RimHUD.Engine;
5 | using RimHUD.Extensions;
6 | using RimHUD.Interface.Hud.Layout;
7 | using UnityEngine;
8 |
9 | namespace RimHUD.Interface.Hud.Layers
10 | {
11 | public sealed class PanelLayer : ContainerLayer
12 | {
13 | public const string Name = "Panel";
14 |
15 | public static readonly LayoutElement LayoutElement = new(LayoutElementType.Panel, Name);
16 | public override LayoutElementType Type => LayoutElementType.Panel;
17 |
18 | public override string Id => Name;
19 |
20 | protected override RowLayer[] Children { get; }
21 |
22 | private float[]? _heights;
23 |
24 | public PanelLayer(XElement xml) : base(xml)
25 | {
26 | var rows = new List();
27 | foreach (var element in xml.Elements())
28 | {
29 | if (element.Name != RowLayer.Name)
30 | {
31 | Report.Error($"Invalid container element '{element.Name}' instead of '{RowLayer.Name}'.");
32 | continue;
33 | }
34 | rows.Add(new RowLayer(element));
35 | }
36 |
37 | Children = rows.ToArray();
38 | }
39 |
40 | public override float Prepare()
41 | {
42 | if (Children.Length is 0 || !IsTargetted()) { return 0f; }
43 | _heights = Children.Select(static row => row.Prepare()).ToArray();
44 |
45 | return Args.FillHeight ? -1f : _heights.Sum() + (LayoutLayer.Padding * (Children.Length - 1));
46 | }
47 |
48 | public override bool Draw(Rect rect)
49 | {
50 | if (Children.Length is 0) { return false; }
51 |
52 | var grid = rect.GetVGrid(LayoutLayer.Padding, _heights!);
53 | var index = 0;
54 | foreach (var item in Children)
55 | {
56 | index++;
57 | item.Draw(grid[index]);
58 | }
59 |
60 | return true;
61 | }
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/source/Interface/Hud/Layers/RowLayer.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 | using System.Xml.Linq;
3 | using HarmonyLib;
4 | using RimHUD.Extensions;
5 | using RimHUD.Interface.Hud.Layout;
6 | using UnityEngine;
7 |
8 | namespace RimHUD.Interface.Hud.Layers
9 | {
10 | public sealed class RowLayer : ContainerLayer
11 | {
12 | public const string Name = "Row";
13 |
14 | public static readonly LayoutElement LayoutElement = new(LayoutElementType.Row, Name);
15 |
16 | public override LayoutElementType Type => LayoutElementType.Row;
17 |
18 | public override string Id => "Row";
19 |
20 | protected override WidgetLayer[] Children { get; }
21 |
22 | private bool _visible;
23 |
24 | public RowLayer(XElement xml) : base(xml) => Children = xml.Elements().Select(WidgetLayer.FromXml).WhereNotNull().ToArray();
25 |
26 | public override float Prepare()
27 | {
28 | _visible = false;
29 | if (Children.Length is 0 || !IsTargetted()) { return 0f; }
30 |
31 | var maxHeight = 0f;
32 | foreach (var child in Children)
33 | {
34 | child.Build();
35 | if (child.Widget is null) { continue; }
36 | maxHeight = Mathf.Max(maxHeight, child.Widget.GetMaxHeight);
37 | }
38 |
39 | _visible = maxHeight > 0f;
40 |
41 | return maxHeight;
42 | }
43 |
44 | public override bool Draw(Rect rect)
45 | {
46 | if (!_visible || Children.Length is 0) { return false; }
47 |
48 | var grid = rect.GetHGrid(GUIPlus.MediumPadding, Enumerable.Repeat(-1f, Children.Length).ToArray());
49 |
50 | var index = 1;
51 | Children.Where(static child => !(child.Widget!.GetMaxHeight <= 0f)).Where(child => child.Draw(grid[index])).Do(_ => index++);
52 |
53 | return index > 1;
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/source/Interface/Hud/Layers/StackLayer.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Xml.Linq;
3 | using RimHUD.Engine;
4 | using RimHUD.Interface.Hud.Layout;
5 |
6 | namespace RimHUD.Interface.Hud.Layers
7 | {
8 | public abstract class StackLayer : ContainerLayer
9 | {
10 | public static readonly LayoutElement[] LayoutElements =
11 | {
12 | new(LayoutElementType.Stack, VStackLayer.Name),
13 | new(LayoutElementType.Stack, HStackLayer.Name)
14 | };
15 |
16 | public override LayoutElementType Type => LayoutElementType.Stack;
17 |
18 | protected override BaseLayer[] Children { get; }
19 |
20 | protected StackLayer(XElement xml) : base(xml)
21 | {
22 | var children = new List();
23 | foreach (var element in xml.Elements())
24 | {
25 | switch (element.Name.ToString())
26 | {
27 | case HStackLayer.Name:
28 | children.Add(new HStackLayer(element));
29 | break;
30 | case VStackLayer.Name:
31 | children.Add(new VStackLayer(element));
32 | break;
33 | case PanelLayer.Name:
34 | children.Add(new PanelLayer(element));
35 | break;
36 | default:
37 | Report.Error($"Invalid container '{element.Name}'.");
38 | break;
39 | }
40 | }
41 |
42 | Children = children.ToArray();
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/source/Interface/Hud/Layers/VStackLayer.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Linq;
3 | using System.Xml.Linq;
4 | using RimHUD.Extensions;
5 | using UnityEngine;
6 |
7 | namespace RimHUD.Interface.Hud.Layers
8 | {
9 | public class VStackLayer : StackLayer
10 | {
11 | public const string Name = "VStack";
12 | public override string Id => Name;
13 |
14 | private float[]? _heights;
15 |
16 | public VStackLayer(XElement xml) : base(xml)
17 | { }
18 |
19 | public override float Prepare()
20 | {
21 | if (Children.Length is 0 || !IsTargetted()) { return 0f; }
22 |
23 | var list = new List();
24 | var totalFixedHeight = 0f;
25 | var totalVisible = 0;
26 |
27 | foreach (var height in Children.Select(static container => container.Prepare()))
28 | {
29 | list.Add(height);
30 | if ((int)height is not -1) { totalFixedHeight += height; }
31 | if ((int)height is not 0) { totalVisible++; }
32 | }
33 |
34 | _heights = list.ToArray();
35 |
36 | return Args.FillHeight ? -1f : totalFixedHeight + (LayoutLayer.Padding * (totalVisible - 1));
37 | }
38 |
39 | public override bool Draw(Rect rect)
40 | {
41 | if (Children.Length is 0 || _heights is null || !IsTargetted()) { return false; }
42 |
43 | var grid = rect.GetVGrid(LayoutLayer.Padding, _heights);
44 | var index = 1;
45 |
46 | foreach (var child in Children)
47 | {
48 | if (_heights[index - 1] is not 0f) { child.Draw(grid[index]); }
49 | index++;
50 | }
51 |
52 | return true;
53 | }
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/source/Interface/Hud/Layers/WidgetLayer.cs:
--------------------------------------------------------------------------------
1 | using System.Xml.Linq;
2 | using RimHUD.Engine;
3 | using RimHUD.Interface.Hud.Layout;
4 | using RimHUD.Interface.Hud.Widgets;
5 | using UnityEngine;
6 |
7 | namespace RimHUD.Interface.Hud.Layers
8 | {
9 | public sealed class WidgetLayer : BaseLayer
10 | {
11 | public override LayoutElementType Type => LayoutElementType.Widget;
12 |
13 | public override string Id { get; }
14 |
15 | public IWidget? Widget;
16 |
17 | private WidgetLayer(string id, HudArgs args) : base(args)
18 | {
19 | Id = id;
20 | HudTimings.Add(this);
21 | }
22 |
23 | ~WidgetLayer() => HudTimings.Remove(this);
24 |
25 | public static WidgetLayer FromXml(XElement xml)
26 | {
27 | var id = xml.Name.ToString();
28 | var args = new HudArgs(xml);
29 |
30 | if (HudContent.IsValidId(id, args.DefName)) { return new WidgetLayer(id, args); }
31 |
32 | Report.ErrorOnce((args.DefName is null ? $"Invalid id '{id}'" : $"Invalid id '{id}' with def '{args.DefName}'") + ". It is recommended to reset your config to default.");
33 |
34 | args.Targets = LayerTarget.All;
35 |
36 | return new WidgetLayer(id, args);
37 | }
38 |
39 | protected override XElement StartXml() => new(Id);
40 |
41 | public override float Prepare() => Widget?.GetMaxHeight ?? 0f;
42 |
43 | public override bool Draw(Rect rect)
44 | {
45 | HudTimings.Update(this)?.Start();
46 |
47 | var result = Widget?.Draw(rect) ?? false;
48 |
49 | HudTimings.Update(this)?.Finish(rect);
50 |
51 | return result;
52 | }
53 |
54 | public override LayoutElement GetLayoutItem(LayoutEditor editor, LayoutElement parent) => new(this, editor, parent);
55 |
56 | public void Build()
57 | {
58 | var widget = HudContent.GetWidget(Id, Args);
59 | Widget = IsTargetted() ? widget : new BlankWidget(widget.GetMaxHeight);
60 | }
61 |
62 | public override void Flush() => Widget = null;
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/source/Interface/Hud/Layout/LayoutEditor.cs:
--------------------------------------------------------------------------------
1 | using RimHUD.Configuration;
2 | using RimHUD.Engine;
3 | using RimHUD.Interface.Hud.Layers;
4 | using UnityEngine;
5 |
6 | namespace RimHUD.Interface.Hud.Layout
7 | {
8 | public sealed class LayoutEditor
9 | {
10 | public LayoutElement Root { get; }
11 | public LayoutElement? Selected { get; set; }
12 |
13 | private float _lastHeight = -1f;
14 | private Vector2 _scrollPosition;
15 |
16 | public LayoutEditor() => Root = State.CurrentLayout.GetLayoutItem(this, null);
17 |
18 | public void Draw(Rect rect)
19 | {
20 | WidgetsPlus.DrawContainer(rect);
21 |
22 | var scrollRect = new Rect(rect.x, rect.y, rect.width - WidgetsPlus.ScrollbarWidth, _lastHeight > -1f ? _lastHeight : 99999f);
23 | Verse.Widgets.BeginScrollView(rect, ref _scrollPosition, scrollRect);
24 | _lastHeight = Root.Draw(scrollRect.x, scrollRect.y, scrollRect.width);
25 | Verse.Widgets.EndScrollView();
26 | }
27 |
28 | public void Add(LayoutElement container, bool selectNew = false)
29 | {
30 | if (Selected is null) { return; }
31 |
32 | var newItem = new LayoutElement(container, this, Selected);
33 | Selected.Children.Insert(0, newItem);
34 | if (selectNew) { Selected = newItem; }
35 | Update();
36 | }
37 |
38 | public void AddSibling(LayoutElement container)
39 | {
40 | if (Selected?.Parent is null) { return; }
41 |
42 | var newItem = new LayoutElement(container, this, Selected.Parent);
43 | Selected.Parent.Children.Insert(Selected.Index + 1, newItem);
44 | Selected = newItem;
45 | Update();
46 | }
47 |
48 | public void Update()
49 | {
50 | var updated = LayoutLayer.FromLayoutView(this);
51 |
52 | if (Theme.DockedMode.Value) { LayoutLayer.Docked = updated; }
53 | else { LayoutLayer.Floating = updated; }
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/source/Interface/Hud/Layout/LayoutElementType.cs:
--------------------------------------------------------------------------------
1 | namespace RimHUD.Interface.Hud.Layout
2 | {
3 | public enum LayoutElementType
4 | {
5 | Stack,
6 | Panel,
7 | Row,
8 | Widget
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/source/Interface/Hud/Models/Active.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using RimHUD.Configuration;
3 | using RimHUD.Engine;
4 | using RimHUD.Extensions;
5 | using RimHUD.Interface.Hud.Layers;
6 | using RimWorld;
7 | using UnityEngine;
8 | using Verse;
9 |
10 | namespace RimHUD.Interface.Hud.Models
11 | {
12 | public static class Active
13 | {
14 | public static Pawn Pawn => State.SelectedPawn ?? throw new Exception("Tried to get active pawn when none selected.");
15 |
16 | public static string Name => Pawn.Name?.ToStringFull.CapitalizeFirst() ?? Pawn.LabelCap;
17 |
18 | public static LayerTarget Target
19 | {
20 | get
21 | {
22 | if (Pawn.IsPlayerManaged()) { return Pawn.RaceProps!.Humanlike ? LayerTarget.PlayerHumanlike : LayerTarget.PlayerCreature; }
23 | return Pawn.RaceProps!.Humanlike ? LayerTarget.OtherHumanlike : LayerTarget.OtherCreature;
24 | }
25 | }
26 |
27 | public static Color FactionRelationColor
28 | {
29 | get
30 | {
31 | if (Pawn.Faction is null) { return Pawn.IsHumanlike() ? Theme.FactionIndependentColor.Value : Theme.FactionWildColor.Value; }
32 |
33 | if (Pawn.IsPrisonerOfColony) { return Theme.FactionPrisonerColor.Value; }
34 | if (Pawn.IsSlaveOfColony) { return Theme.FactionSlaveColor.Value; }
35 |
36 | if (Pawn.Faction.IsPlayer) { return Theme.FactionOwnColor.Value; }
37 |
38 | return Pawn.Faction.PlayerRelationKind switch { FactionRelationKind.Hostile => Theme.FactionHostileColor.Value, FactionRelationKind.Ally => Theme.FactionAlliedColor.Value, _ => Theme.FactionIndependentColor.Value };
39 | }
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/source/Interface/Hud/Models/BarModel.cs:
--------------------------------------------------------------------------------
1 | using RimHUD.Interface.Hud.Widgets;
2 |
3 | namespace RimHUD.Interface.Hud.Models
4 | {
5 | public abstract class BarModel : BaseModel
6 | {
7 | protected abstract string? Value { get; }
8 |
9 | protected abstract float Fill { get; }
10 | protected virtual float[]? Thresholds => null;
11 | protected virtual BarColorStyle? ColorStyle => null;
12 |
13 | public override IWidget? Build(HudArgs? args) => Fill < 0f ? null : new BarWidget(Label, Value, Fill, Thresholds, Tooltip, OnHover, OnClick, TextStyle, args?.BarColorStyle ?? ColorStyle ?? default);
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/source/Interface/Hud/Models/Bars/HealthBar.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using RimHUD.Interface.Hud.Tooltips;
3 | using RimHUD.Interface.Screen;
4 | using Verse;
5 |
6 | namespace RimHUD.Interface.Hud.Models.Bars
7 | {
8 | public sealed class HealthBar : BarModel
9 | {
10 | protected override string? Label { get; }
11 | protected override string? Value { get; }
12 |
13 | protected override float Fill { get; } = -1f;
14 |
15 | protected override Func? Tooltip { get; }
16 |
17 | protected override Action? OnClick { get; }
18 |
19 | public HealthBar()
20 | {
21 | if (Active.Pawn.health is null) { return; }
22 |
23 | Label = "Health".Translate();
24 |
25 | var percent = Active.Pawn.health?.summaryHealth?.SummaryHealthPercent ?? -1f;
26 | Value = percent < 0f ? null : percent.ToStringPercent();
27 | Fill = percent;
28 |
29 | Tooltip = HealthTooltip.Get;
30 |
31 | OnClick = InspectPaneTabs.ToggleHealth;
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/source/Interface/Hud/Models/Bars/NeedBar.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using RimHUD.Extensions;
3 | using RimHUD.Interface.Hud.Widgets;
4 | using RimWorld;
5 | using Verse;
6 |
7 | namespace RimHUD.Interface.Hud.Models.Bars
8 | {
9 | public class NeedBar : BarModel
10 | {
11 | protected override string? Label { get; }
12 | protected override string? Value { get; }
13 |
14 | protected override float Fill { get; } = -1f;
15 | protected override Func? Tooltip { get; }
16 |
17 | protected override BarColorStyle? ColorStyle { get; }
18 |
19 | public NeedBar(NeedDef def, Func? tooltip = null, BarColorStyle? colorStyle = null)
20 | {
21 | var need = Active.Pawn.needs?.TryGetNeed(def);
22 | if (need is null) { return; }
23 |
24 | Label = def.GetDefNameOrLabel();
25 |
26 | var percent = need.CurLevelPercentage;
27 | Value = percent.ToStringPercent();
28 | Fill = need.CurLevelPercentage;
29 | Tooltip = tooltip;
30 |
31 | ColorStyle = colorStyle;
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/source/Interface/Hud/Models/Bars/NeedEnergyBar.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Text;
3 | using RimHUD.Access;
4 | using RimHUD.Extensions;
5 | using RimHUD.Interface.Screen;
6 | using Verse;
7 |
8 | namespace RimHUD.Interface.Hud.Models.Bars
9 | {
10 | public sealed class NeedEnergyBar : NeedBar
11 | {
12 | protected override Func Tooltip { get; }
13 |
14 | protected override Action OnClick { get; }
15 |
16 | public NeedEnergyBar() : base(Defs.NeedEnergy)
17 | {
18 | Tooltip = GetTooltip;
19 |
20 | OnClick = InspectPaneTabs.ToggleNeeds;
21 | }
22 |
23 | private static string? GetTooltip()
24 | {
25 | if (Active.Pawn.needs?.energy?.FallPerDay is null) { return null; }
26 |
27 | var builder = new StringBuilder();
28 | builder.AppendValue("CurrentMechEnergyFallPerDay".Translate(), (Active.Pawn.needs.energy.FallPerDay / 100f).ToStringPercent());
29 |
30 | return builder.ToTooltip();
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/source/Interface/Hud/Models/Bars/NeedFoodBar.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Text;
3 | using RimHUD.Extensions;
4 | using RimHUD.Interface.Screen;
5 | using RimWorld;
6 | using Verse;
7 |
8 | namespace RimHUD.Interface.Hud.Models.Bars
9 | {
10 | public sealed class NeedFoodBar : NeedBar
11 | {
12 | protected override Func Tooltip { get; }
13 |
14 | protected override Action OnClick { get; }
15 |
16 | public NeedFoodBar() : base(NeedDefOf.Food)
17 | {
18 | Tooltip = GetTooltip;
19 |
20 | OnClick = InspectPaneTabs.ToggleNeeds;
21 | }
22 |
23 | private static string? GetTooltip()
24 | {
25 | var builder = new StringBuilder();
26 | if (Active.Pawn.RaceProps?.foodType is not null)
27 | {
28 | builder.AppendValue("Diet".Translate(), Active.Pawn.RaceProps.foodType.ToHumanString().CapitalizeFirst());
29 | builder.AppendLine();
30 | }
31 |
32 | builder.AppendStatLine(StatDefOf.EatingSpeed);
33 | builder.AppendStatLine(StatDefOf.BedHungerRateFactor);
34 |
35 | return builder.ToTooltip();
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/source/Interface/Hud/Models/Bars/NeedMoodBar.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using RimHUD.Access;
3 | using RimHUD.Interface.Hud.Tooltips;
4 | using RimHUD.Interface.Screen;
5 |
6 | namespace RimHUD.Interface.Hud.Models.Bars
7 | {
8 | public sealed class NeedMoodBar : NeedBar
9 | {
10 | protected override float[]? Thresholds { get; }
11 |
12 | protected override Func Tooltip { get; }
13 |
14 | protected override Action OnClick { get; }
15 |
16 | public NeedMoodBar() : base(Defs.NeedMood)
17 | {
18 | if (Active.Pawn.mindState?.mentalBreaker is { } mental)
19 | {
20 | Thresholds = new[]
21 | {
22 | mental.BreakThresholdMinor,
23 | mental.BreakThresholdMajor,
24 | mental.BreakThresholdExtreme
25 | };
26 | }
27 |
28 | Tooltip = MentalTooltip.Get;
29 |
30 | OnClick = InspectPaneTabs.ToggleNeeds;
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/source/Interface/Hud/Models/Bars/NeedRecreationBar.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Text;
3 | using RimHUD.Access;
4 | using RimHUD.Extensions;
5 | using RimHUD.Interface.Screen;
6 |
7 | namespace RimHUD.Interface.Hud.Models.Bars
8 | {
9 | public sealed class NeedRecreationBar : NeedBar
10 | {
11 | protected override Func Tooltip { get; }
12 |
13 | protected override Action OnClick { get; }
14 |
15 | public NeedRecreationBar() : base(Defs.NeedRecreation)
16 | {
17 | Tooltip = GetTooltip;
18 |
19 | OnClick = InspectPaneTabs.ToggleNeeds;
20 | }
21 |
22 | private static string? GetTooltip()
23 | {
24 | var builder = new StringBuilder();
25 | builder.AppendNeedLine(Active.Pawn, Defs.NeedBeauty);
26 | builder.AppendNeedLine(Active.Pawn, Defs.NeedComfort);
27 | builder.AppendNeedLine(Active.Pawn, Defs.NeedOutdoors);
28 |
29 | return builder.ToTooltip();
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/source/Interface/Hud/Models/Bars/NeedSleepBar.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Text;
3 | using RimHUD.Extensions;
4 | using RimHUD.Interface.Screen;
5 | using RimWorld;
6 |
7 | namespace RimHUD.Interface.Hud.Models.Bars
8 | {
9 | public sealed class NeedSleepBar : NeedBar
10 | {
11 | protected override Func Tooltip { get; }
12 |
13 | protected override Action OnClick { get; }
14 |
15 | public NeedSleepBar() : base(NeedDefOf.Rest)
16 | {
17 | Tooltip = GetTooltip;
18 |
19 | OnClick = InspectPaneTabs.ToggleNeeds;
20 | }
21 |
22 | private static string? GetTooltip()
23 | {
24 | var builder = new StringBuilder();
25 | builder.AppendStatLine(StatDefOf.RestRateMultiplier);
26 |
27 | return builder.ToTooltip();
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/source/Interface/Hud/Models/Bars/NeedSuppressionBar.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Text;
3 | using RimHUD.Access;
4 | using RimHUD.Extensions;
5 | using RimHUD.Interface.Screen;
6 | using RimWorld;
7 |
8 | namespace RimHUD.Interface.Hud.Models.Bars
9 | {
10 | public sealed class NeedSuppressionBar : NeedBar
11 | {
12 | protected override Func Tooltip { get; }
13 |
14 | protected override Action OnClick { get; }
15 |
16 | public NeedSuppressionBar() : base(Defs.NeedSuppression)
17 | {
18 | Tooltip = GetTooltip;
19 |
20 | OnClick = InspectPaneTabs.ToggleSlave;
21 | }
22 |
23 | private static string? GetTooltip()
24 | {
25 | var builder = new StringBuilder();
26 |
27 | builder.AppendStatLine(StatDefOf.SlaveSuppressionFallRate);
28 | builder.AppendStatLine(StatDefOf.Terror);
29 |
30 | return builder.ToTooltip();
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/source/Interface/Hud/Models/BaseModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using RimHUD.Configuration;
3 | using RimHUD.Configuration.Settings;
4 | using RimHUD.Interface.Hud.Widgets;
5 |
6 | namespace RimHUD.Interface.Hud.Models
7 | {
8 | public abstract class BaseModel : IModel
9 | {
10 | public abstract IWidget? Build(HudArgs? args);
11 |
12 | protected virtual string? Label => null;
13 | protected virtual Func? Tooltip => null;
14 |
15 | protected virtual Action? OnHover => null;
16 | protected virtual Action? OnClick => null;
17 |
18 | protected virtual TextStyle TextStyle => Theme.RegularTextStyle;
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/source/Interface/Hud/Models/IModel.cs:
--------------------------------------------------------------------------------
1 | using RimHUD.Interface.Hud.Widgets;
2 |
3 | namespace RimHUD.Interface.Hud.Models
4 | {
5 | public interface IModel
6 | {
7 | IWidget? Build(HudArgs? args);
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/source/Interface/Hud/Models/SelectorModel.cs:
--------------------------------------------------------------------------------
1 | using RimHUD.Configuration;
2 | using RimHUD.Configuration.Settings;
3 | using RimHUD.Interface.Hud.Widgets;
4 | using UnityEngine;
5 |
6 | namespace RimHUD.Interface.Hud.Models
7 | {
8 | public abstract class SelectorModel : BaseModel
9 | {
10 | protected override TextStyle TextStyle => Theme.SmallTextStyle;
11 | protected virtual Color? Color => null;
12 |
13 | public override IWidget? Build(HudArgs? args) => OnClick is null ? null : new SelectorWidget(Label, Tooltip, OnClick, OnHover, TextStyle, Color);
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/source/Interface/Hud/Models/Selectors/AreaSelector.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using RimHUD.Engine;
5 | using RimHUD.Extensions;
6 | using RimHUD.Integration.Multiplayer;
7 | using RimWorld;
8 | using UnityEngine;
9 | using Verse;
10 |
11 | namespace RimHUD.Interface.Hud.Models.Selectors
12 | {
13 | public sealed class AreaSelector : SelectorModel
14 | {
15 | protected override string? Label { get; }
16 |
17 | protected override Action? OnHover { get; }
18 | protected override Action? OnClick { get; }
19 |
20 | protected override Color? Color { get; }
21 |
22 | public AreaSelector()
23 | {
24 | if ((!Active.Pawn.Faction?.IsPlayer ?? true) || Active.Pawn.playerSettings is null || (!Active.Pawn.IsColonist && !Active.Pawn.playerSettings.RespectsAllowedArea)) { return; }
25 |
26 | Label = Lang.Get("Model.Selector.AreaFormat", AreaUtility.AreaAllowedLabel(Active.Pawn));
27 | Color = Active.Pawn.playerSettings.EffectiveAreaRestrictionInPawnCurrentMap?.Color;
28 |
29 | OnHover = static () => Active.Pawn.playerSettings.EffectiveAreaRestrictionInPawnCurrentMap?.MarkForDraw();
30 | OnClick = DrawFloatMenu;
31 | }
32 |
33 | private static void DrawFloatMenu()
34 | {
35 | var options = new List { new("NoAreaAllowed".Translate(), static () => Mod_Multiplayer.SetArea(Active.Pawn, null)) };
36 | options.AddRange(from area in Find.CurrentMap!.areaManager!.AllAreas.Where(static area => area.AssignableAsAllowed()) select new FloatMenuOption(area.Label, () => Mod_Multiplayer.SetArea(Active.Pawn, area)));
37 | options.Add(new FloatMenuOption(Lang.Get("Model.Selector.Manage").Italic(), static () => Find.WindowStack!.Add(new Dialog_ManageAreas(Find.CurrentMap))));
38 |
39 | Find.WindowStack!.Add(new FloatMenu(options));
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/source/Interface/Hud/Models/Selectors/FoodSelector.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using RimHUD.Engine;
4 | using RimHUD.Extensions;
5 | using RimHUD.Integration.Multiplayer;
6 | using RimWorld;
7 | using Verse;
8 |
9 | namespace RimHUD.Interface.Hud.Models.Selectors
10 | {
11 | public sealed class FoodSelector : SelectorModel
12 | {
13 | protected override string? Label { get; }
14 |
15 | protected override Action? OnClick { get; }
16 |
17 | public FoodSelector()
18 | {
19 | if (!Active.Pawn.IsPlayerManaged() || Active.Pawn.foodRestriction?.CurrentFoodPolicy is null || !Active.Pawn.foodRestriction.Configurable) { return; }
20 |
21 | Label = Lang.Get("Model.Selector.FoodFormat", Active.Pawn.foodRestriction.CurrentFoodPolicy.label);
22 |
23 | OnClick = DrawFloatMenu;
24 | }
25 |
26 | private static void DrawFloatMenu()
27 | {
28 | var options = (from food in Current.Game!.foodRestrictionDatabase!.AllFoodRestrictions select new FloatMenuOption(food.label, () => Mod_Multiplayer.SetFoodRestriction(Active.Pawn, food))).ToList();
29 | options.Add(new FloatMenuOption(Lang.Get("Model.Selector.Manage").Italic(), static () => Find.WindowStack!.Add(new Dialog_ManageFoodPolicies(Active.Pawn.foodRestriction!.CurrentFoodPolicy))));
30 |
31 | Find.WindowStack!.Add(new FloatMenu(options));
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/source/Interface/Hud/Models/Selectors/OutfitSelector.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using RimHUD.Engine;
4 | using RimHUD.Extensions;
5 | using RimHUD.Integration.Multiplayer;
6 | using RimWorld;
7 | using Verse;
8 |
9 | namespace RimHUD.Interface.Hud.Models.Selectors
10 | {
11 | public sealed class OutfitSelector : SelectorModel
12 | {
13 | protected override string? Label { get; }
14 |
15 | protected override Action? OnClick { get; }
16 |
17 | public OutfitSelector()
18 | {
19 | if (!Active.Pawn.IsPlayerFaction() || Active.Pawn.outfits?.CurrentApparelPolicy is null) { return; }
20 |
21 | Label = Lang.Get("Model.Selector.OutfitFormat", Active.Pawn.outfits?.CurrentApparelPolicy.label!);
22 |
23 | OnClick = DrawFloatMenu;
24 | }
25 |
26 | private static void DrawFloatMenu()
27 | {
28 | try
29 | {
30 | var options = (from outfit in Current.Game!.outfitDatabase!.AllOutfits select new FloatMenuOption(outfit.label, () => Mod_Multiplayer.SetOutfit(Active.Pawn, outfit))).ToList();
31 | options.Add(new FloatMenuOption(Lang.Get("Model.Selector.Manage").Italic(), static () => Find.WindowStack!.Add(new Dialog_ManageApparelPolicies(Active.Pawn.outfits!.CurrentApparelPolicy))));
32 |
33 | Find.WindowStack!.Add(new FloatMenu(options));
34 | }
35 | catch (Exception exception) { Report.HandleError(exception); }
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/source/Interface/Hud/Models/Selectors/TimetableSelector.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using RimHUD.Access;
4 | using RimHUD.Engine;
5 | using RimHUD.Extensions;
6 | using RimHUD.Integration.Multiplayer;
7 | using RimWorld;
8 | using UnityEngine;
9 | using Verse;
10 |
11 | namespace RimHUD.Interface.Hud.Models.Selectors
12 | {
13 | public sealed class TimetableSelector : SelectorModel
14 | {
15 | protected override string? Label { get; }
16 |
17 | protected override Action? OnClick { get; }
18 |
19 | protected override Color? Color { get; }
20 |
21 | public TimetableSelector()
22 | {
23 | if (!Active.Pawn.IsPlayerFaction() || Active.Pawn.timetable?.CurrentAssignment is null) { return; }
24 |
25 | Label = Lang.Get("Model.Selector.TimetableFormat", Active.Pawn.timetable.CurrentAssignment.LabelCap);
26 |
27 | var assignment = Active.Pawn.timetable.CurrentAssignment;
28 | Color = assignment == TimeAssignmentDefOf.Anything ? null : assignment.color;
29 |
30 | OnClick = DrawFloatMenu;
31 | }
32 |
33 | private static void DrawFloatMenu()
34 | {
35 | var hour = GenLocalDate.HourOfDay(Active.Pawn);
36 | var options = DefDatabase.AllDefs.Select(timeAssignment => new FloatMenuOption(Lang.Get("Model.Selector.SetTimeAssignment", hour, timeAssignment.LabelCap), () => Mod_Multiplayer.SetAssignment(Active.Pawn, hour, timeAssignment))).ToList();
37 | options.Add(new FloatMenuOption(Lang.Get("Model.Selector.Manage").Italic(), static () => Find.MainTabsRoot!.SetCurrentTab(Defs.MainButtonRestrict)));
38 |
39 | Find.WindowStack!.Add(new FloatMenu(options));
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/source/Interface/Hud/Models/ValueModel.cs:
--------------------------------------------------------------------------------
1 | using RimHUD.Interface.Hud.Widgets;
2 |
3 | namespace RimHUD.Interface.Hud.Models
4 | {
5 | public abstract class ValueModel : BaseModel
6 | {
7 | protected abstract string? Value { get; }
8 |
9 | public override IWidget? Build(HudArgs? args) => Value is null ? null : new ValueWidget(Label, Value, Tooltip, OnHover, OnClick, TextStyle);
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/source/Interface/Hud/Models/Values/ActivityValue.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using System.Text;
4 | using RimHUD.Access;
5 | using RimHUD.Configuration;
6 | using RimHUD.Configuration.Settings;
7 | using RimHUD.Engine;
8 | using RimHUD.Extensions;
9 | using RimWorld;
10 | using Verse;
11 | using Verse.AI.Group;
12 |
13 | namespace RimHUD.Interface.Hud.Models.Values
14 | {
15 | public sealed class ActivityValue : ValueModel
16 | {
17 | protected override string Value { get; }
18 |
19 | protected override Func Tooltip { get; }
20 |
21 | protected override Action OnClick { get; }
22 |
23 | protected override TextStyle TextStyle => Theme.SmallTextStyle;
24 |
25 | public ActivityValue()
26 | {
27 | Value = GetValue();
28 |
29 | Tooltip = GetTooltip;
30 |
31 | OnClick = static () => Find.MainTabsRoot!.SetCurrentTab(Defs.MainButtonWork);
32 | }
33 |
34 | private static string GetValue()
35 | {
36 | var lord = Active.Pawn.GetLord()?.LordJob?.GetReport(Active.Pawn)?.CapitalizeFirst();
37 | var jobText = Active.Pawn.jobs?.curDriver?.GetReport()?.TrimEnd('.').CapitalizeFirst();
38 | var target = Active.Pawn.IsAttacking() ? Active.Pawn.TargetCurrentlyAimingAt.Thing?.LabelShortCap : null;
39 | var activity = target is null ? lord.NullOrWhitespace() ? jobText : $"{lord} ({jobText})" : Lang.Get("Model.Info.Attacking", target);
40 |
41 | return activity is null ? string.Empty : Lang.Get("Model.Info.Activity", activity.Bold());
42 | }
43 |
44 | private static string? GetTooltip()
45 | {
46 | try
47 | {
48 | if (Active.Pawn.CurJob?.workGiverDef?.Worker?.def?.workType?.labelShort is null) { return null; }
49 |
50 | var work = Active.Pawn.CurJob.workGiverDef.Worker.def.workType.labelShort.CapitalizeFirst();
51 |
52 | var builder = new StringBuilder();
53 | builder.AppendLine(Lang.Get("Model.Info.Activity.WorkType", work));
54 |
55 | if (Active.Pawn.CurJob.workGiverDef.Worker.def.workType.relevantSkills is { } relevantSkills) { builder.AppendLine(Lang.Get("Model.Info.Activity.RelevantSkills", relevantSkills.Select(static skill => skill.LabelCap.ToString()).ToCommaList())); }
56 |
57 | return builder.ToTooltip();
58 | }
59 | catch (Exception exception)
60 | {
61 | Report.HandleWarning(exception);
62 | return null;
63 | }
64 | }
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/source/Interface/Hud/Models/Values/AnimalMasterValue.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using RimHUD.Configuration;
3 | using RimHUD.Configuration.Settings;
4 | using RimHUD.Engine;
5 | using RimHUD.Interface.Hud.Tooltips;
6 | using RimHUD.Interface.Screen;
7 | using RimWorld;
8 | using Verse;
9 |
10 | namespace RimHUD.Interface.Hud.Models.Values
11 | {
12 | public sealed class AnimalMasterValue : ValueModel
13 | {
14 | protected override string? Value { get; }
15 |
16 | protected override Func? Tooltip { get; }
17 |
18 | protected override Action? OnClick { get; }
19 |
20 | protected override TextStyle TextStyle => Theme.SmallTextStyle;
21 |
22 | public AnimalMasterValue()
23 | {
24 | var master = Active.Pawn.playerSettings?.Master;
25 | if (master is null) { return; }
26 |
27 | var masterName = master.LabelShort;
28 | var relation = Active.Pawn.GetMostImportantRelation(master)?.LabelCap;
29 |
30 | var text = Lang.Get("Model.Bio.Master", masterName);
31 |
32 | Value = relation is null ? text : text.Colorize(Theme.SkillMinorPassionColor.Value);
33 |
34 | Tooltip = AnimalTooltip.Get;
35 |
36 | OnClick = InspectPaneTabs.ToggleSocial;
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/source/Interface/Hud/Models/Values/CarryingValue.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using RimHUD.Configuration;
3 | using RimHUD.Configuration.Settings;
4 | using RimHUD.Engine;
5 | using RimHUD.Extensions;
6 | using RimHUD.Interface.Screen;
7 |
8 | namespace RimHUD.Interface.Hud.Models.Values
9 | {
10 | public sealed class CarryingValue : ValueModel
11 | {
12 | protected override string Value { get; }
13 |
14 | protected override Action OnClick { get; }
15 |
16 | protected override TextStyle TextStyle => Theme.SmallTextStyle;
17 |
18 | public CarryingValue()
19 | {
20 | Value = GetValue();
21 |
22 | OnClick = InspectPaneTabs.ToggleGear;
23 | }
24 |
25 | private static string GetValue()
26 | {
27 | var carried = Active.Pawn.carryTracker?.CarriedThing?.LabelCap;
28 | return carried is null ? string.Empty : Lang.Get("Model.Info.Carrying", carried.Bold());
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/source/Interface/Hud/Models/Values/CompInfoValue.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 | using RimHUD.Configuration;
3 | using RimHUD.Configuration.Settings;
4 | using Verse;
5 |
6 | namespace RimHUD.Interface.Hud.Models.Values
7 | {
8 | public sealed class CompInfoValue : ValueModel
9 | {
10 | protected override string? Value { get; }
11 |
12 | protected override TextStyle TextStyle => Theme.SmallTextStyle;
13 |
14 | public CompInfoValue() => Value = GetValue();
15 |
16 | private static string? GetValue()
17 | {
18 | try
19 | {
20 | var info = (from comp in Active.Pawn.AllComps select comp.CompInspectStringExtra() into text where !text.NullOrEmpty() select text.Replace('\n', ' ')).ToArray();
21 | return info.Length > 0 ? info.ToCommaList() : null;
22 | }
23 | catch { return null; }
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/source/Interface/Hud/Models/Values/EquippedValue.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using RimHUD.Configuration;
3 | using RimHUD.Configuration.Settings;
4 | using RimHUD.Engine;
5 | using RimHUD.Extensions;
6 | using RimHUD.Interface.Screen;
7 | using RimWorld;
8 | using Verse;
9 |
10 | namespace RimHUD.Interface.Hud.Models.Values
11 | {
12 | public sealed class EquippedValue : ValueModel
13 | {
14 | protected override string Value { get; }
15 |
16 | protected override Action OnClick { get; }
17 |
18 | protected override TextStyle TextStyle => Theme.SmallTextStyle;
19 |
20 | public EquippedValue()
21 | {
22 | Value = GetValue();
23 |
24 | OnClick = InspectPaneTabs.ToggleGear;
25 | }
26 |
27 | private static string GetValue()
28 | {
29 | if (RestraintsUtility.ShouldShowRestraintsInfo(Active.Pawn)) { return "InRestraints".Translate(); }
30 |
31 | var equipped = Active.Pawn.equipment?.Primary?.LabelCap;
32 | return equipped is null ? string.Empty : Lang.Get("Model.Info.Equipped", equipped.Bold());
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/source/Interface/Hud/Models/Values/GenderRaceAndAgeValue.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using RimHUD.Configuration;
3 | using RimHUD.Configuration.Settings;
4 | using RimHUD.Engine;
5 | using RimHUD.Extensions;
6 | using RimHUD.Interface.Hud.Tooltips;
7 | using RimHUD.Interface.Screen;
8 | using RimWorld;
9 | using Verse;
10 |
11 | namespace RimHUD.Interface.Hud.Models.Values
12 | {
13 | public sealed class GenderRaceAndAgeValue : ValueModel
14 | {
15 | protected override string Value { get; }
16 |
17 | protected override Func Tooltip { get; }
18 |
19 | protected override Action OnClick { get; }
20 |
21 | protected override TextStyle TextStyle => Theme.SmallTextStyle;
22 |
23 | public GenderRaceAndAgeValue()
24 | {
25 | Value = GetValue().Colorize(Active.FactionRelationColor);
26 |
27 | Tooltip = BioTooltip.Get;
28 |
29 | OnClick = InspectPaneTabs.ToggleBio;
30 | }
31 |
32 | private static string? GetRace()
33 | {
34 | if (!ModsConfig.IdeologyActive || !Active.Pawn.IsHumanlike()) { return Active.Pawn.kindDef?.race?.label; }
35 | var race = Active.Pawn.Ideo?.memberName ?? Active.Pawn.kindDef?.race?.label;
36 |
37 | return race?.Trim();
38 | }
39 |
40 | private string GetValue()
41 | {
42 | var gender = Active.Pawn.gender is Gender.None ? null : Active.Pawn.GetGenderLabel();
43 |
44 | var genderRace = Lang.AdjectiveNoun(gender, GetRace());
45 |
46 | if (Active.Pawn.ageTracker is null) { return genderRace.Trim().CapitalizeFirst(); }
47 |
48 | Active.Pawn.ageTracker.AgeBiologicalTicks.TicksToPeriod(out var years, out var quadrums, out var days, out _);
49 | var ageDays = (quadrums * GenDate.DaysPerQuadrum) + days;
50 |
51 | var age = $@"{years} {ageDays switch { 0 => Lang.Get("Model.Age.Birthday"), GenDate.DaysPerYear => Lang.Get("Model.Age.Birthday"), 1 => Lang.Get("Model.Age.Day"), _ => Lang.Get("Model.Age.Days", ageDays) }}";
52 |
53 | return Lang.Get("Model.GenderRaceAndAge", genderRace, age).Trim().CapitalizeFirst();
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/source/Interface/Hud/Models/Values/MentalConditionValue.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using RimHUD.Configuration;
3 | using RimHUD.Configuration.Settings;
4 | using RimHUD.Engine;
5 | using RimHUD.Interface.Hud.Tooltips;
6 | using RimHUD.Interface.Screen;
7 | using Verse;
8 |
9 | namespace RimHUD.Interface.Hud.Models.Values
10 | {
11 | public sealed class MentalConditionValue : ValueModel
12 | {
13 | private const float MoodHappyLevel = 0.9f;
14 | private const float MoodContentLevel = 0.65f;
15 |
16 | protected override string? Value { get; }
17 |
18 | protected override Func? Tooltip { get; }
19 |
20 | protected override Action? OnClick { get; }
21 |
22 | protected override TextStyle TextStyle => Theme.SmallTextStyle;
23 |
24 | public MentalConditionValue()
25 | {
26 | if (Active.Pawn.mindState?.mentalStateHandler is null) { return; }
27 |
28 | Value = GetValue();
29 |
30 | Tooltip = MentalTooltip.Get;
31 |
32 | OnClick = InspectPaneTabs.ToggleNeeds;
33 | }
34 |
35 | private static string? GetValue()
36 | {
37 | if (Active.Pawn.mindState!.mentalStateHandler!.InMentalState) { return Active.Pawn.mindState.mentalStateHandler.CurState!.InspectLine.Colorize(Active.Pawn.mindState.mentalStateHandler.CurState.def!.IsAggro || Active.Pawn.mindState.mentalStateHandler.CurState.def.IsExtreme ? Theme.CriticalColor.Value : Theme.WarningColor.Value); }
38 |
39 | if (Active.Pawn.needs?.mood is null || Active.Pawn.mindState?.mentalBreaker is null) { return null; }
40 |
41 | if (Active.Pawn.mindState.mentalBreaker?.BreakExtremeIsImminent ?? true) { return Lang.Get("Model.Mood.ExtremeBreakImminent").Colorize(Theme.CriticalColor.Value); }
42 | if (Active.Pawn.mindState.mentalBreaker?.BreakMajorIsImminent ?? true) { return Lang.Get("Model.Mood.MajorBreakImminent").Colorize(Theme.WarningColor.Value); }
43 | if (Active.Pawn.mindState.mentalBreaker?.BreakMinorIsImminent ?? true) { return Lang.Get("Model.Mood.MinorBreakImminent").Colorize(Theme.WarningColor.Value); }
44 |
45 | return GetInspiration() ?? Active.Pawn.needs.mood.CurLevel switch
46 | {
47 | > MoodHappyLevel => Lang.Get("Model.Mood.Happy").Colorize(Theme.ExcellentColor.Value),
48 | > MoodContentLevel => Lang.Get("Model.Mood.Content").Colorize(Theme.GoodColor.Value),
49 | _ => Lang.Get("Model.Mood.Indifferent").Colorize(Theme.InfoColor.Value)
50 | };
51 | }
52 |
53 | private static string? GetInspiration() => GetInspirationInspectLine()?.Colorize(Theme.ExcellentColor.Value);
54 |
55 | private static string? GetInspirationInspectLine()
56 | {
57 | try { return Active.Pawn.Inspired ? Active.Pawn.Inspiration?.InspectLine : null; }
58 | catch { return null; }
59 | }
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/source/Interface/Hud/Models/Values/NameHeaderValue.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using RimHUD.Configuration;
3 | using RimHUD.Configuration.Settings;
4 | using RimHUD.Interface.Hud.Tooltips;
5 | using RimHUD.Interface.Screen;
6 | using Verse;
7 |
8 | namespace RimHUD.Interface.Hud.Models.Values
9 | {
10 | public sealed class NameHeaderValue : ValueModel
11 | {
12 | protected override string Value { get; }
13 |
14 | protected override Func Tooltip { get; }
15 |
16 | protected override Action OnClick { get; }
17 |
18 | protected override TextStyle TextStyle => Theme.LargeTextStyle;
19 |
20 | public NameHeaderValue()
21 | {
22 | Value = Active.Name.Colorize(Active.FactionRelationColor);
23 |
24 | Tooltip = BioTooltip.Get;
25 |
26 | OnClick = InspectPaneTabs.ToggleSocial;
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/source/Interface/Hud/Models/Values/PrisonerInfoValue.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using RimHUD.Configuration;
3 | using RimHUD.Configuration.Settings;
4 | using RimHUD.Extensions;
5 | using RimHUD.Interface.Screen;
6 | using Verse;
7 |
8 | namespace RimHUD.Interface.Hud.Models.Values
9 | {
10 | public sealed class PrisonerInfoValue : ValueModel
11 | {
12 | protected override string? Value { get; }
13 |
14 | protected override Action OnClick { get; }
15 |
16 | protected override TextStyle TextStyle => Theme.SmallTextStyle;
17 |
18 | public PrisonerInfoValue()
19 | {
20 | Value = GetValue();
21 |
22 | OnClick = InspectPaneTabs.TogglePrisoner;
23 | }
24 |
25 | private static string? GetValue()
26 | {
27 | if (!Active.Pawn.IsPrisonerOfColony || Active.Pawn.guest is null) { return null; }
28 |
29 | var resistance = "RecruitmentResistance".Translate().WithValue(Active.Pawn.guest.resistance.ToString("F1").Bold());
30 | var will = "WillLevel".Translate().WithValue(Active.Pawn.guest.will.ToString("F1").Bold());
31 |
32 | return ModsConfig.IdeologyActive ? $"{resistance} / {will}" : resistance;
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/source/Interface/Hud/Models/Values/QueuedValue.cs:
--------------------------------------------------------------------------------
1 | using RimHUD.Configuration;
2 | using RimHUD.Configuration.Settings;
3 | using RimHUD.Engine;
4 | using RimHUD.Extensions;
5 | using Verse;
6 |
7 | namespace RimHUD.Interface.Hud.Models.Values
8 | {
9 | public sealed class QueuedValue : ValueModel
10 | {
11 | protected override string Value { get; }
12 |
13 | protected override TextStyle TextStyle => Theme.SmallTextStyle;
14 |
15 | public QueuedValue() => Value = GetValue();
16 |
17 | private static string GetValue()
18 | {
19 | if (Active.Pawn.jobs?.curJob is null || Active.Pawn.jobs.jobQueue!.Count is 0) { return string.Empty; }
20 |
21 | var queued = Active.Pawn.jobs.jobQueue[0]!.job.GetReport(Active.Pawn)?.TrimEnd('.').CapitalizeFirst().Bold();
22 | var remaining = Active.Pawn.jobs.jobQueue.Count - 1;
23 | if (remaining > 0) { queued += $" (+{remaining})"; }
24 |
25 | return queued is null ? string.Empty : Lang.Get("Model.Info.Queued", queued);
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/source/Interface/Hud/Models/Values/RecordValue.cs:
--------------------------------------------------------------------------------
1 | using RimWorld;
2 |
3 | namespace RimHUD.Interface.Hud.Models.Values
4 | {
5 | public sealed class RecordValue : ValueModel
6 | {
7 | protected override string Value { get; }
8 |
9 | public RecordValue(RecordDef def) => Value = $"{def.LabelCap}: {(def.type is RecordType.Time ? Active.Pawn.records!.GetAsInt(def).ToStringTicksToPeriod() : Active.Pawn.records!.GetValue(def).ToString("0.##"))}";
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/source/Interface/Hud/Models/Values/RelationKindAndFactionValue.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using RimHUD.Configuration;
3 | using RimHUD.Configuration.Settings;
4 | using RimHUD.Engine;
5 | using RimHUD.Extensions;
6 | using RimHUD.Interface.Hud.Tooltips;
7 | using RimHUD.Interface.Screen;
8 | using RimWorld;
9 | using Verse;
10 |
11 | namespace RimHUD.Interface.Hud.Models.Values
12 | {
13 | public sealed class RelationKindAndFactionValue : ValueModel
14 | {
15 | protected override string Value { get; }
16 |
17 | protected override Func Tooltip { get; }
18 |
19 | protected override Action OnClick { get; }
20 |
21 | protected override TextStyle TextStyle => Theme.SmallTextStyle;
22 |
23 | public RelationKindAndFactionValue()
24 | {
25 | Value = GetValue();
26 |
27 | Tooltip = BioTooltip.Get;
28 |
29 | OnClick = InspectPaneTabs.ToggleBio;
30 | }
31 |
32 | private static string GetValue() => Lang.Get("Model.RelationKindAndFaction", Lang.AdjectiveNoun(GetRelation(), GetKind()), GetFaction()).Trim().CapitalizeFirst().Colorize(Active.FactionRelationColor);
33 |
34 | private static string? GetRelation()
35 | {
36 | if (Active.Pawn.IsPrisoner) { return Lang.Get("Model.Faction.Prisoner"); }
37 | if (Active.Pawn.IsSlave) { return Active.Pawn.story?.title is null ? Lang.Get("Model.Faction.Slave") : null; }
38 | if (Active.Pawn.Faction is null) { return Active.Pawn.IsHumanlike() ? Lang.Get("Model.Faction.Independent") : Active.Pawn.kindDef == PawnKindDefOf.WildMan ? null : Lang.Get("Model.Faction.Wild"); }
39 | if (Active.Pawn.Faction.IsPlayer) { return null; }
40 |
41 | return Active.Pawn.Faction.PlayerRelationKind switch
42 | {
43 | FactionRelationKind.Hostile => Active.Pawn.RaceProps!.IsMechanoid ? Lang.Get("Model.Faction.Hostile") : Lang.Get("Model.Faction.Enemy"),
44 | FactionRelationKind.Ally => Lang.Get("Model.Faction.Allied"),
45 | _ => null
46 | };
47 | }
48 |
49 | private static string? GetFaction()
50 | {
51 | if (Active.Pawn.Faction is null || !Active.Pawn.Faction.HasName) { return null; }
52 |
53 | if (Active.Pawn.IsPrisoner || Active.Pawn.IsSlave) { return Active.Pawn.HostFaction is null || Active.Pawn.HostFaction.HasName || Active.Pawn.HostFaction == Faction.OfPlayer ? null : Lang.Get("Model.OfFaction", Active.Pawn.HostFaction.Name); }
54 |
55 | return Lang.Get("Model.OfFaction", Active.Pawn.Faction.Name);
56 | }
57 |
58 | private static string GetKind()
59 | {
60 | if (Active.Pawn.IsHumanlike()) { return Active.Pawn.Faction == Faction.OfPlayer && !Active.Pawn.IsPrisoner ? Active.Pawn.story?.Title ?? Active.Pawn.KindLabel : Active.Pawn.TraderKind?.label ?? Active.Pawn.KindLabel; }
61 |
62 | if (Active.Pawn.RaceProps!.IsMechanoid) { return Active.Pawn.Faction == Faction.OfPlayer ? Lang.Get("Model.Creature.Mechanoid") : Lang.Get("Model.Creature.Unit"); }
63 |
64 | if (Active.Pawn.Faction is null)
65 | {
66 | if (Active.Pawn.RaceProps.petness > 0.5f) { return Lang.Get("Model.Creature.Stray"); }
67 | if (Active.Pawn.RaceProps.predator) { return Lang.Get("Model.Creature.Predator"); }
68 | if (Active.Pawn.kindDef!.race!.tradeTags?.Contains("AnimalInsect") ?? false) { return Lang.Get("Model.Creature.Insect"); }
69 | return Lang.Get("Model.Creature.Wild");
70 | }
71 |
72 | switch (Active.Pawn.RaceProps.petness)
73 | {
74 | case > 0.5f: return Lang.Get("Model.Creature.Pet");
75 | case > 0f: return Lang.Get("Model.Creature.ExoticPet");
76 | }
77 |
78 | if (Active.Pawn.RaceProps.predator) { return Lang.Get("Model.Creature.Hunt"); }
79 | if (Active.Pawn.RaceProps.packAnimal) { return Lang.Get("Model.Creature.Pack"); }
80 | if (Active.Pawn.kindDef!.race!.tradeTags?.Contains("AnimalFarm") ?? false) { return Lang.Get("Model.Creature.Farm"); }
81 | if (Active.Pawn.RaceProps.herdAnimal) { return Lang.Get("Model.Creature.Herd"); }
82 | if (Active.Pawn.kindDef.race.tradeTags?.Contains("AnimalInsect") ?? false) { return Lang.Get("Model.Creature.Insect"); }
83 | return Lang.Get(Active.Pawn.RaceProps.Animal ? "Model.Creature.Tame" : "Model.Creature.Entity");
84 | }
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/source/Interface/Hud/Models/Values/SkillAnimalsValue.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using RimHUD.Extensions;
3 | using RimWorld;
4 |
5 | namespace RimHUD.Interface.Hud.Models.Values
6 | {
7 | public sealed class SkillAnimalsValue : SkillValue
8 | {
9 | protected override Func Tooltip { get; }
10 |
11 | public SkillAnimalsValue() : base(SkillDefOf.Animals) => Tooltip = GetTooltip;
12 |
13 | private string? GetTooltip()
14 | {
15 | var builder = PrepareBuilder();
16 |
17 | builder.AppendStatLine(StatDefOf.AnimalGatherSpeed);
18 | builder.AppendStatLine(StatDefOf.AnimalGatherYield);
19 | builder.AppendStatLine(StatDefOf.TameAnimalChance);
20 | builder.AppendStatLine(StatDefOf.TrainAnimalChance);
21 | builder.AppendStatLine(StatDefOf.HuntingStealth);
22 |
23 | return builder.ToTooltip();
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/source/Interface/Hud/Models/Values/SkillConstructionValue.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using RimHUD.Extensions;
3 | using RimWorld;
4 |
5 | namespace RimHUD.Interface.Hud.Models.Values
6 | {
7 | public sealed class SkillConstructionValue : SkillValue
8 | {
9 | protected override Func Tooltip { get; }
10 |
11 | public SkillConstructionValue() : base(SkillDefOf.Construction) => Tooltip = GetTooltip;
12 |
13 | private string? GetTooltip()
14 | {
15 | var builder = PrepareBuilder();
16 |
17 | builder.AppendStatLine(StatDefOf.ConstructSuccessChance);
18 | builder.AppendStatLine(StatDefOf.ConstructionSpeed);
19 | builder.AppendStatLine(StatDefOf.FixBrokenDownBuildingSuccessChance);
20 | builder.AppendStatLine(StatDefOf.SmoothingSpeed);
21 |
22 | return builder.ToTooltip();
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/source/Interface/Hud/Models/Values/SkillCookingValue.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using RimHUD.Extensions;
3 | using RimWorld;
4 | using Verse;
5 |
6 | namespace RimHUD.Interface.Hud.Models.Values
7 | {
8 | public sealed class SkillCookingValue : SkillValue
9 | {
10 | private static readonly StatDef CookSpeed = DefDatabase.GetNamed("CookSpeed");
11 | private static readonly StatDef ButcheryFleshSpeed = DefDatabase.GetNamed("ButcheryFleshSpeed");
12 | private static readonly StatDef ButcheryFleshEfficiency = DefDatabase.GetNamed("ButcheryFleshEfficiency");
13 | private static readonly StatDef DrugCookingSpeed = DefDatabase.GetNamed("DrugCookingSpeed");
14 |
15 | protected override Func Tooltip { get; }
16 |
17 | public SkillCookingValue() : base(SkillDefOf.Cooking) => Tooltip = GetTooltip;
18 |
19 | private string? GetTooltip()
20 | {
21 | var builder = PrepareBuilder();
22 |
23 | builder.AppendStatLine(CookSpeed);
24 | builder.AppendStatLine(StatDefOf.FoodPoisonChance);
25 | builder.AppendStatLine(ButcheryFleshEfficiency);
26 | builder.AppendStatLine(ButcheryFleshSpeed);
27 | builder.AppendStatLine(DrugCookingSpeed);
28 |
29 | return builder.ToTooltip();
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/source/Interface/Hud/Models/Values/SkillCraftingValue.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using RimHUD.Extensions;
3 | using RimWorld;
4 | using Verse;
5 |
6 | namespace RimHUD.Interface.Hud.Models.Values
7 | {
8 | public sealed class SkillCraftingValue : SkillValue
9 | {
10 | private static readonly StatDef SmeltingSpeed = DefDatabase.GetNamed("SmeltingSpeed");
11 | private static readonly StatDef ButcheryMechanoidSpeed = DefDatabase.GetNamed("ButcheryMechanoidSpeed");
12 | private static readonly StatDef ButcheryMechanoidEfficiency = DefDatabase.GetNamed("ButcheryMechanoidEfficiency");
13 |
14 | protected override Func Tooltip { get; }
15 |
16 | public SkillCraftingValue() : base(SkillDefOf.Crafting) => Tooltip = GetTooltip;
17 |
18 | private string? GetTooltip()
19 | {
20 | var builder = PrepareBuilder();
21 |
22 | builder.AppendStatLine(SmeltingSpeed);
23 | builder.AppendStatLine(ButcheryMechanoidSpeed);
24 | builder.AppendStatLine(ButcheryMechanoidEfficiency);
25 |
26 | return builder.ToTooltip();
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/source/Interface/Hud/Models/Values/SkillIntellectualValue.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using RimHUD.Extensions;
3 | using RimWorld;
4 | using Verse;
5 |
6 | namespace RimHUD.Interface.Hud.Models.Values
7 | {
8 | public sealed class SkillIntellectualValue : SkillValue
9 | {
10 | protected override Func Tooltip { get; }
11 |
12 | public SkillIntellectualValue() : base(SkillDefOf.Intellectual) => Tooltip = GetTooltip;
13 |
14 | private string? GetTooltip()
15 | {
16 | var builder = PrepareBuilder();
17 |
18 | builder.AppendStatLine(StatDefOf.ResearchSpeed);
19 | if (ModsConfig.IdeologyActive) { builder.AppendStatLine(StatDefOf.HackingSpeed); }
20 |
21 | return builder.ToTooltip();
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/source/Interface/Hud/Models/Values/SkillMedicineValue.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using RimHUD.Extensions;
3 | using RimWorld;
4 | using Verse;
5 |
6 | namespace RimHUD.Interface.Hud.Models.Values
7 | {
8 | public sealed class SkillMedicineValue : SkillValue
9 | {
10 | private static readonly StatDef MedicalOperationSpeed = DefDatabase.GetNamed("MedicalOperationSpeed");
11 |
12 | protected override Func Tooltip { get; }
13 |
14 | public SkillMedicineValue() : base(SkillDefOf.Medicine) => Tooltip = GetTooltip;
15 |
16 | private string? GetTooltip()
17 | {
18 | var builder = PrepareBuilder();
19 |
20 | builder.AppendStatLine(MedicalOperationSpeed);
21 | builder.AppendStatLine(StatDefOf.MedicalSurgerySuccessChance);
22 | builder.AppendStatLine(StatDefOf.MedicalTendSpeed);
23 | builder.AppendStatLine(StatDefOf.MedicalTendQuality);
24 |
25 | return builder.ToTooltip();
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/source/Interface/Hud/Models/Values/SkillMeleeValue.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using RimHUD.Extensions;
3 | using RimWorld;
4 |
5 | namespace RimHUD.Interface.Hud.Models.Values
6 | {
7 | public sealed class SkillMeleeValue : SkillValue
8 | {
9 | protected override Func Tooltip { get; }
10 |
11 | public SkillMeleeValue() : base(SkillDefOf.Melee) => Tooltip = GetTooltip;
12 |
13 | private string? GetTooltip()
14 | {
15 | var builder = PrepareBuilder();
16 |
17 | builder.AppendStatLine(StatDefOf.MeleeDPS);
18 | builder.AppendStatLine(StatDefOf.MeleeHitChance);
19 | builder.AppendStatLine(StatDefOf.MeleeDodgeChance);
20 |
21 | return builder.ToTooltip();
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/source/Interface/Hud/Models/Values/SkillMiningValue.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using RimHUD.Extensions;
3 | using RimWorld;
4 |
5 | namespace RimHUD.Interface.Hud.Models.Values
6 | {
7 | public sealed class SkillMiningValue : SkillValue
8 | {
9 | protected override Func Tooltip { get; }
10 |
11 | public SkillMiningValue() : base(SkillDefOf.Mining) => Tooltip = GetTooltip;
12 |
13 | private string? GetTooltip()
14 | {
15 | var builder = PrepareBuilder();
16 |
17 | builder.AppendStatLine(StatDefOf.MiningYield);
18 | builder.AppendStatLine(StatDefOf.MiningSpeed);
19 | builder.AppendStatLine(StatDefOf.DeepDrillingSpeed);
20 |
21 | return builder.ToTooltip();
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/source/Interface/Hud/Models/Values/SkillPlantsValue.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using RimHUD.Extensions;
3 | using RimWorld;
4 | using Verse;
5 |
6 | namespace RimHUD.Interface.Hud.Models.Values
7 | {
8 | public sealed class SkillPlantsValue : SkillValue
9 | {
10 | protected override Func Tooltip { get; }
11 |
12 | public SkillPlantsValue() : base(SkillDefOf.Plants) => Tooltip = GetTooltip;
13 |
14 | private string? GetTooltip()
15 | {
16 | var builder = PrepareBuilder();
17 |
18 | builder.AppendStatLine(StatDefOf.PlantWorkSpeed);
19 | builder.AppendStatLine(StatDefOf.PlantHarvestYield);
20 | if (ModsConfig.IdeologyActive) { builder.AppendStatLine(StatDefOf.PruningSpeed); }
21 |
22 | return builder.ToTooltip();
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/source/Interface/Hud/Models/Values/SkillShootingValue.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using RimHUD.Extensions;
3 | using RimWorld;
4 |
5 | namespace RimHUD.Interface.Hud.Models.Values
6 | {
7 | public sealed class SkillShootingValue : SkillValue
8 | {
9 | protected override Func Tooltip { get; }
10 |
11 | public SkillShootingValue() : base(SkillDefOf.Shooting) => Tooltip = GetTooltip;
12 |
13 | private string? GetTooltip()
14 | {
15 | var builder = PrepareBuilder();
16 |
17 | builder.AppendStatLine(StatDefOf.ShootingAccuracyPawn);
18 | builder.AppendStatLine(StatDefOf.AimingDelayFactor);
19 |
20 | return builder.ToTooltip();
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/source/Interface/Hud/Models/Values/SkillSocialValue.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using RimHUD.Extensions;
3 | using RimWorld;
4 | using Verse;
5 |
6 | namespace RimHUD.Interface.Hud.Models.Values
7 | {
8 | public sealed class SkillSocialValue : SkillValue
9 | {
10 | protected override Func Tooltip { get; }
11 |
12 | public SkillSocialValue() : base(SkillDefOf.Social) => Tooltip = GetTooltip;
13 |
14 | private string? GetTooltip()
15 | {
16 | var builder = PrepareBuilder();
17 |
18 | builder.AppendStatLine(StatDefOf.NegotiationAbility);
19 | builder.AppendStatLine(StatDefOf.TradePriceImprovement);
20 | builder.AppendStatLine(StatDefOf.Beauty);
21 | builder.AppendStatLine(StatDefOf.SocialImpact);
22 |
23 | if (!ModsConfig.IdeologyActive) { return builder.ToTooltip(); }
24 |
25 | builder.AppendStatLine(StatDefOf.ConversionPower);
26 | builder.AppendStatLine(StatDefOf.SuppressionPower);
27 |
28 | return builder.ToTooltip();
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/source/Interface/Hud/Models/Values/SkillValue.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Text;
3 | using RimHUD.Access;
4 | using RimHUD.Configuration;
5 | using RimHUD.Engine;
6 | using RimHUD.Extensions;
7 | using RimHUD.Interface.Screen;
8 | using RimWorld;
9 | using UnityEngine;
10 | using Verse;
11 |
12 | namespace RimHUD.Interface.Hud.Models.Values
13 | {
14 | public class SkillValue : ValueModel
15 | {
16 | protected override string? Label { get; }
17 | protected override string? Value { get; }
18 |
19 | protected override Func? Tooltip { get; }
20 |
21 | protected override Action? OnClick { get; }
22 |
23 | private readonly SkillRecord? _skill;
24 |
25 | public SkillValue(SkillDef def)
26 | {
27 | var skill = Active.Pawn.skills?.GetSkill(def);
28 | if (skill is null) { return; }
29 |
30 | _skill = skill;
31 |
32 | var passionIndicator = new StringBuilder().Insert(0, Lang.Get("Model.Skill.PassionIndicator"), (int)skill.passion).ToString();
33 |
34 | var isActive = Active.Pawn.jobs?.curDriver?.ActiveSkill == def;
35 | var isSaturated = skill.LearningSaturatedToday;
36 |
37 | var color = skill.TotallyDisabled ? Theme.DisabledColor.Value : isSaturated ? Theme.SkillSaturatedColor.Value : isActive ? Theme.SkillActiveColor.Value : GetColor(skill);
38 | Label = (def.GetDefNameOrLabel() + passionIndicator).Colorize(color);
39 |
40 | Value = skill.TotallyDisabled ? "-" : skill.Level.ToDecimalString(Math.Max(0, Math.Min(99, skill.XpProgressPercent.ToPercentageInt()))).Colorize(color);
41 |
42 | Tooltip = GetTooltip;
43 |
44 | OnClick = InspectPaneTabs.ToggleBio;
45 | }
46 |
47 | private static Color GetColor(SkillRecord skill) => skill.passion switch
48 | {
49 | Passion.Minor => Theme.SkillMinorPassionColor.Value,
50 | Passion.Major => Theme.SkillMajorPassionColor.Value,
51 | _ => Theme.MainTextColor.Value
52 | };
53 |
54 | protected StringBuilder PrepareBuilder()
55 | {
56 | var builder = new StringBuilder();
57 | builder.AppendLine(Reflection.RimWorld_SkillUI_GetSkillDescription.InvokeStatic(_skill!));
58 | builder.AppendLine();
59 |
60 | if (_skill!.TotallyDisabled) { return builder; }
61 |
62 | builder.AppendStatLine(StatDefOf.WorkSpeedGlobal);
63 | builder.AppendStatLine(StatDefOf.GeneralLaborSpeed);
64 | builder.AppendLine();
65 |
66 | return builder;
67 | }
68 |
69 | private string? GetTooltip() => PrepareBuilder().ToTooltip();
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/source/Interface/Hud/Models/Values/StatValue.cs:
--------------------------------------------------------------------------------
1 | using RimHUD.Extensions;
2 | using RimWorld;
3 |
4 | namespace RimHUD.Interface.Hud.Models.Values
5 | {
6 | public sealed class StatValue : ValueModel
7 | {
8 | protected override string? Value { get; }
9 |
10 | public StatValue(StatDef def)
11 | {
12 | if (def.Worker?.IsDisabledFor(Active.Pawn) ?? true) { return; }
13 |
14 | Value = $"{def.GetDefNameOrLabel()}: {def.ValueToString(Active.Pawn.GetStatValue(def))}";
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/source/Interface/Hud/Models/Values/TrainableValue.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using RimHUD.Access;
3 | using RimHUD.Configuration;
4 | using RimHUD.Engine;
5 | using RimHUD.Extensions;
6 | using RimHUD.Interface.Hud.Tooltips;
7 | using RimHUD.Interface.Screen;
8 | using RimWorld;
9 | using Verse;
10 |
11 | namespace RimHUD.Interface.Hud.Models.Values
12 | {
13 | public sealed class TrainableValue : ValueModel
14 | {
15 | protected override string? Label { get; }
16 |
17 | protected override string? Value { get; }
18 |
19 | protected override Func? Tooltip { get; }
20 |
21 | protected override Action? OnClick { get; }
22 |
23 | public TrainableValue(TrainableDef def)
24 | {
25 | try
26 | {
27 | if (Active.Pawn.RaceProps?.trainability is null || Active.Pawn.training is null || !Active.Pawn.training.CanAssignToTrain(def, out var visible).Accepted || !visible) { return; }
28 |
29 | var disabled = !Active.Pawn.training.GetWanted(def);
30 | var hasLearned = Active.Pawn.training.HasLearned(def);
31 |
32 | var color = disabled switch
33 | {
34 | true => Theme.DisabledColor.Value,
35 | _ => hasLearned ? Theme.SkillMinorPassionColor.Value : Theme.MainTextColor.Value
36 | };
37 |
38 | Label = def.GetDefNameOrLabel().Colorize(color);
39 |
40 | var steps = GetSteps(Active.Pawn, def);
41 | var value = $"{steps} / {def.steps}".Colorize(color);
42 |
43 | Value = hasLearned ? value.Bold() : value;
44 |
45 | Tooltip = () => AnimalTooltip.Get(def);
46 |
47 | OnClick = InspectPaneTabs.ToggleTraining;
48 | }
49 | catch (Exception exception)
50 | {
51 | Report.HandleWarning(exception);
52 | Value = null;
53 | }
54 | }
55 |
56 | private static int GetSteps(Pawn pawn, TrainableDef def) => Reflection.RimWorld_Pawn_TrainingTracker_GetSteps.Invoke(pawn.training, def);
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/source/Interface/Hud/Tooltips/AnimalTooltip.cs:
--------------------------------------------------------------------------------
1 | using System.Text;
2 | using RimHUD.Engine;
3 | using RimHUD.Extensions;
4 | using RimHUD.Interface.Hud.Models;
5 | using RimWorld;
6 | using Verse;
7 |
8 | namespace RimHUD.Interface.Hud.Tooltips
9 | {
10 | public static class AnimalTooltip
11 | {
12 | public static string Get(TrainableDef? def)
13 | {
14 | var builder = new StringBuilder();
15 |
16 | if (Active.Pawn.RaceProps is not null)
17 | {
18 | var trainability = Active.Pawn.RaceProps.trainability?.LabelCap;
19 | if (trainability is not null) { builder.AppendLine(Lang.Get("Model.Bio.Trainability", trainability)); }
20 |
21 | builder.AppendLine($"{"TrainingDecayInterval".Translate()}: {TrainableUtility.DegradationPeriodTicks(Active.Pawn.def).ToStringTicksToDays()}");
22 | if (!TrainableUtility.TamenessCanDecay(Active.Pawn.def)) { builder.AppendLine("TamenessWillNotDecay".Translate()); }
23 |
24 | builder.AppendLine(Lang.Get("Model.Bio.Petness", Active.Pawn.RaceProps.petness.ToStringPercent()));
25 | builder.AppendLine(Lang.Get("Model.Bio.Diet", Active.Pawn.RaceProps.ResolvedDietCategory.ToStringHuman()));
26 | }
27 |
28 | var master = Active.Pawn.playerSettings?.Master?.LabelShort;
29 | if (!master.NullOrWhitespace())
30 | {
31 | builder.AppendLine();
32 | builder.AppendLine(Lang.Get("Model.Bio.Master", master));
33 | }
34 |
35 | if (def is null) { return builder.ToStringTrimmed(); }
36 |
37 | builder.AppendLine();
38 | builder.AppendLine(def.description);
39 |
40 | return builder.ToStringTrimmed();
41 | }
42 |
43 | public static string Get() => Get(null);
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/source/Interface/Hud/Tooltips/BioTooltip.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 | using System.Text;
3 | using RimHUD.Configuration;
4 | using RimHUD.Engine;
5 | using RimHUD.Extensions;
6 | using RimHUD.Interface.Hud.Models;
7 | using RimWorld;
8 | using Verse;
9 |
10 | namespace RimHUD.Interface.Hud.Tooltips
11 | {
12 | public static class BioTooltip
13 | {
14 | public static string? Get()
15 | {
16 | if (Active.Pawn.IsAnimal()) { return AnimalTooltip.Get(); }
17 |
18 | if (Active.Pawn.story is null) { return null; }
19 |
20 | var builder = new StringBuilder();
21 |
22 | var title = Active.Pawn.story.TitleCap;
23 | if (title is not null) { builder.AppendLineIfNotEmpty(Lang.Get("Model.Bio.Title", title)); }
24 | var faction = Active.Pawn.Faction?.Name;
25 | if (faction is not null) { builder.AppendLineIfNotEmpty(Lang.Get("Model.Bio.Faction", faction)); }
26 | var ideoligion = !ModsConfig.IdeologyActive || Active.Pawn.Ideo is null ? null : Active.Pawn.Ideo.name;
27 | if (ideoligion is not null) { builder.AppendLineIfNotEmpty(Lang.Get("Model.Bio.Ideoligion", ideoligion)); }
28 |
29 | builder.AppendLine();
30 |
31 | builder.AppendLineIfNotEmpty("Childhood".Translate().WithValue(Active.Pawn.story.GetBackstory(BackstorySlot.Childhood)?.TitleCapFor(Active.Pawn.gender)));
32 | builder.AppendLineIfNotEmpty("Adulthood".Translate().WithValue(Active.Pawn.story.GetBackstory(BackstorySlot.Adulthood)?.TitleCapFor(Active.Pawn.gender)));
33 |
34 | builder.AppendLine();
35 |
36 | builder.AppendLineIfNotEmpty(Active.Pawn.story.traits?.allTraits?.Count > 0 ? "Traits".Translate().WithValue(Active.Pawn.story.traits.allTraits.Select(static trait => trait.LabelCap).ToCommaList(true)) : null);
37 |
38 | var disabledWork = Active.Pawn.story.DisabledWorkTagsBackstoryAndTraits;
39 | var incapable = disabledWork is WorkTags.None ? null : "IncapableOf".Translate().WithValue(disabledWork.GetAllSelectedItems().Where(static tag => tag != WorkTags.None).Select(static tag => tag.LabelTranslated().CapitalizeFirst()).ToCommaList(true));
40 | builder.AppendLineIfNotEmpty(incapable.NullOrWhitespace() ? null : incapable.Colorize(Theme.CriticalColor.Value));
41 |
42 | builder.AppendLine();
43 |
44 | builder.AppendStatLine(StatDefOf.PsychicSensitivity);
45 |
46 | if (ModsConfig.RoyaltyActive)
47 | {
48 | builder.AppendLine("MeditationFocuses".Translate().CapitalizeFirst().WithValue(MeditationUtility.FocusTypesAvailableForPawnString(Active.Pawn).CapitalizeFirst()));
49 | builder.AppendStatLine(StatDefOf.MeditationFocusGain);
50 | builder.AppendStatLine(StatDefOf.MeditationFocusStrength);
51 | }
52 |
53 | if (!ModsConfig.IdeologyActive) { return builder.ToTooltip(); }
54 |
55 | builder.AppendStatLine(StatDefOf.SocialIdeoSpreadFrequencyFactor);
56 | builder.AppendStatLine(StatDefOf.CertaintyLossFactor);
57 |
58 | return builder.ToTooltip();
59 | }
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/source/Interface/Hud/Tooltips/HealthTooltip.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using RimHUD.Access;
6 | using RimHUD.Configuration;
7 | using RimHUD.Engine;
8 | using RimHUD.Extensions;
9 | using RimHUD.Interface.Hud.Models;
10 | using UnityEngine;
11 | using Verse;
12 |
13 | namespace RimHUD.Interface.Hud.Tooltips
14 | {
15 | public static class HealthTooltip
16 | {
17 | public static string? Get()
18 | {
19 | try
20 | {
21 | var builder = new StringBuilder();
22 |
23 | foreach (var hediff in VisibleHediffGroupsInOrder(true).SelectMany(static hediffs => hediffs.Where(static hediff => hediff.Visible))) { builder.AppendLine(GetHealthTooltipLine(hediff)); }
24 |
25 | if (builder.Length is 0) { builder.AppendLine("NoHealthConditions".Translate().CapitalizeFirst().Colorize(Theme.DisabledColor.Value)); }
26 |
27 | return builder.ToTooltip();
28 | }
29 | catch (Exception exception)
30 | {
31 | Report.HandleWarning(exception);
32 | return null;
33 | }
34 | }
35 |
36 | private static IEnumerable> VisibleHediffGroupsInOrder(bool showBloodLoss) => Reflection.RimWorld_HealthCardUtility_VisibleHediffGroupsInOrder.InvokeStatic>>(Active.Pawn, showBloodLoss);
37 |
38 | private static string? GetHealthTooltipLine(Hediff hediff)
39 | {
40 | try
41 | {
42 | var part = hediff.Part?.LabelCap ?? "WholeBody".Translate();
43 |
44 | var condition = hediff.LabelCap;
45 |
46 | Color color;
47 | if (!hediff.def!.isBad) { color = Theme.GoodColor.Value; }
48 | else if (hediff.IsPermanent() || hediff.FullyImmune()) { color = Theme.InfoColor.Value; }
49 | else if (hediff.def.IsAddiction || hediff.IsTended()) { color = Theme.WarningColor.Value; }
50 | else { color = Theme.CriticalColor.Value; }
51 |
52 | return $"{part}: {condition}".Colorize(color);
53 | }
54 | catch (Exception exception)
55 | {
56 | Report.HandleWarning(exception);
57 | return null;
58 | }
59 | }
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/source/Interface/Hud/Tooltips/MentalTooltip.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 | using RimHUD.Configuration;
5 | using RimHUD.Engine;
6 | using RimHUD.Extensions;
7 | using RimHUD.Interface.Hud.Models;
8 | using RimWorld;
9 | using Verse;
10 |
11 | namespace RimHUD.Interface.Hud.Tooltips
12 | {
13 | public static class MentalTooltip
14 | {
15 | public static string? Get()
16 | {
17 | if (Active.Pawn.needs?.mood?.thoughts is null) { return null; }
18 |
19 | var thoughts = new List();
20 | try { PawnNeedsUIUtility.GetThoughtGroupsInDisplayOrder(Active.Pawn.needs.mood, thoughts); }
21 | catch (Exception exception) { Report.HandleWarning(exception); }
22 |
23 | var builder = new StringBuilder();
24 | foreach (var thought in thoughts)
25 | {
26 | float offset;
27 | try { offset = thought.MoodOffset(); }
28 | catch (Exception exception)
29 | {
30 | Report.HandleWarning(exception);
31 | offset = 0;
32 | }
33 |
34 | var color = offset switch
35 | {
36 | <= -10 => Theme.CriticalColor.Value,
37 | < 0 => Theme.WarningColor.Value,
38 | >= 10 => Theme.ExcellentColor.Value,
39 | > 0 => Theme.GoodColor.Value,
40 | _ => Theme.InfoColor.Value
41 | };
42 |
43 | try
44 | {
45 | var similar = new List();
46 | Active.Pawn.needs.mood.thoughts.GetMoodThoughts(thought, similar);
47 |
48 | var thoughtLabel = thought.LabelCap;
49 | if (similar.Count > 1) { thoughtLabel += $" x{similar.Count}"; }
50 |
51 | var line = thoughtLabel.WithValue((offset * similar.Count).ToStringWithSign()).Colorize(color);
52 | builder.AppendLine(line);
53 | }
54 | catch (Exception exception) { Report.HandleWarning(exception); }
55 | }
56 |
57 | builder.AppendLine();
58 |
59 | if (Active.Pawn.Inspired && Active.Pawn.Inspiration != null) { builder.AppendLine(Active.Pawn.Inspiration.InspectLine.Colorize(Theme.ExcellentColor.Value)); }
60 |
61 | return builder.ToTooltip();
62 | }
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/source/Interface/Hud/Tooltips/TooltipsPlus.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using RimHUD.Configuration;
3 | using RimHUD.Extensions;
4 | using UnityEngine;
5 | using Verse;
6 |
7 | namespace RimHUD.Interface.Hud.Tooltips
8 | {
9 | public static class TooltipsPlus
10 | {
11 | private const float MaxRectHeight = 260f;
12 |
13 | private static GUIStyle HudTooltipStyle => Theme.RegularTextStyle.GUIStyle;
14 |
15 | public static bool IsFromHud(int id) => id is (int)TooltipId.Compact;
16 |
17 | public static void DrawSimple(Rect rect, string? text) => Draw(rect, () => text, TooltipId.Standard);
18 | public static void DrawStandard(Rect rect, Func? getter) => Draw(rect, getter, TooltipId.Standard);
19 | public static void DrawCompact(Rect rect, Func? getter) => Draw(rect, getter, TooltipId.Compact);
20 | public static void DrawFinal(Rect rect, string? text) => Draw(rect, () => text, TooltipId.Final);
21 |
22 | public static void DrawInner(Rect rect, string text)
23 | {
24 | Verse.Widgets.DrawAtlas(rect, ActiveTip.TooltipBGAtlas);
25 | WidgetsPlus.DrawMultilineText(rect.ContractedBy(4f), text, HudTooltipStyle);
26 | }
27 |
28 | public static Rect GetRect(string text)
29 | {
30 | var textSize = GUIPlus.GetTextSize(HudTooltipStyle, text, true);
31 | return new Rect(0f, 0f, Mathf.Min(textSize.x, MaxRectHeight), textSize.x > MaxRectHeight ? GUIPlus.GetTextHeight(HudTooltipStyle, text, MaxRectHeight, true) : textSize.y).ExpandedBy(GUIPlus.SmallPadding).RoundedCeil();
32 | }
33 |
34 | private static void Draw(Rect rect, Func? getter, TooltipId id)
35 | {
36 | if (getter is null || !Mouse.IsOver(rect)) { return; }
37 |
38 | var text = getter.Invoke();
39 | if (text.NullOrWhitespace()) { return; }
40 |
41 | TooltipHandler.TipRegion(rect, new TipSignal(text.ResolveTags, (int)id));
42 | }
43 |
44 | private enum TooltipId
45 | {
46 | Standard = 10001111,
47 | Compact = 1000222,
48 | Final = 10003333
49 | }
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/source/Interface/Hud/Widgets/BarColorStyle.cs:
--------------------------------------------------------------------------------
1 | namespace RimHUD.Interface.Hud.Widgets
2 | {
3 | public enum BarColorStyle
4 | {
5 | LowToMain,
6 | LowOnly,
7 | MainToLow,
8 | MainOnly
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/source/Interface/Hud/Widgets/BarWidget.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using RimHUD.Configuration;
4 | using RimHUD.Configuration.Settings;
5 | using RimHUD.Extensions;
6 | using RimHUD.Interface.Hud.Tooltips;
7 | using UnityEngine;
8 | using Verse;
9 |
10 | namespace RimHUD.Interface.Hud.Widgets
11 | {
12 | public sealed class BarWidget : StandardWidget
13 | {
14 | private readonly string? _value;
15 | private readonly float _fill;
16 |
17 | private readonly BarColorStyle _colorStyle;
18 |
19 | private readonly float[]? _thresholds;
20 |
21 | private readonly Action? _onHover;
22 | private readonly Action? _onClick;
23 |
24 | public BarWidget(string? label, string? value, float fill, float[]? thresholds, Func? tooltip, Action? onHover, Action? onClick, TextStyle textStyle, BarColorStyle colorStyle) : base(label, tooltip, textStyle)
25 | {
26 | _value = value;
27 | _fill = fill;
28 | _thresholds = thresholds;
29 |
30 | _onHover = onHover;
31 | _onClick = onClick;
32 |
33 | _colorStyle = colorStyle;
34 | }
35 |
36 | public override bool Draw(Rect rect)
37 | {
38 | if (_fill < 0f) { return false; }
39 |
40 | var percentage = _fill / 1f;
41 |
42 | var grid = rect.GetHGrid(GUIPlus.TinyPadding, Label is not null ? Theme.LabelWidth.Value : 0f, -1f, Theme.ValueWidth.Value);
43 |
44 | if (Label is not null) { DrawText(grid[1], Label); }
45 | WidgetsPlus.DrawBar(grid[2], percentage, _colorStyle.GetColor(percentage));
46 | DrawThresholds(grid[2]);
47 | if (_value is not null) { DrawText(grid[3], _value); }
48 |
49 | if (HudLayout.IsMouseOverConfigButton) { return true; }
50 |
51 | if (Mouse.IsOver(rect)) { _onHover?.Invoke(); }
52 | if (Verse.Widgets.ButtonInvisible(rect)) { _onClick?.Invoke(); }
53 | TooltipsPlus.DrawCompact(rect, Tooltip);
54 |
55 | return true;
56 | }
57 |
58 | private void DrawThresholds(Rect rect)
59 | {
60 | if (_thresholds is null) { return; }
61 |
62 | GUIPlus.SetColor(Theme.BarThresholdColor.Value);
63 | foreach (var threshold in _thresholds.Where(static threshold => threshold > 0f)) { Verse.Widgets.DrawLineVertical(Mathf.Round(rect.x + (rect.width * threshold)), rect.y, rect.height); }
64 | GUIPlus.ResetColor();
65 | }
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/source/Interface/Hud/Widgets/BlankWidget.cs:
--------------------------------------------------------------------------------
1 | using UnityEngine;
2 |
3 | namespace RimHUD.Interface.Hud.Widgets
4 | {
5 | public sealed class BlankWidget : IWidget
6 | {
7 | public const string TypeName = "Blank";
8 |
9 | public static BlankWidget Collapsed => new(0f);
10 |
11 | public float GetMaxHeight { get; }
12 |
13 | public BlankWidget(float height) => GetMaxHeight = height;
14 |
15 | public bool Draw(Rect rect) => true;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/source/Interface/Hud/Widgets/IWidget.cs:
--------------------------------------------------------------------------------
1 | using UnityEngine;
2 |
3 | namespace RimHUD.Interface.Hud.Widgets
4 | {
5 | public interface IWidget
6 | {
7 | float GetMaxHeight { get; }
8 |
9 | bool Draw(Rect rect);
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/source/Interface/Hud/Widgets/MissingWidget.cs:
--------------------------------------------------------------------------------
1 | using RimHUD.Configuration;
2 | using UnityEngine;
3 | using Verse;
4 |
5 | namespace RimHUD.Interface.Hud.Widgets
6 | {
7 | public sealed class MissingWidget : IWidget
8 | {
9 | private static readonly Color Color = new(0.5f, 0f, 0f);
10 |
11 | private readonly string _label;
12 |
13 | public float GetMaxHeight { get; }
14 |
15 | private MissingWidget(string label)
16 | {
17 | _label = label;
18 | GetMaxHeight = Theme.SmallTextStyle.LineHeight;
19 | }
20 |
21 | public static MissingWidget Get(string id, HudArgs args) => new(args.DefName.NullOrEmpty() ? $"<{id}>" : $"<{id}[{args.DefName}]>");
22 |
23 | public bool Draw(Rect rect)
24 | {
25 | Verse.Widgets.DrawBoxSolid(rect, Color);
26 | WidgetsPlus.DrawText(rect, _label, Theme.SmallTextStyle);
27 | return true;
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/source/Interface/Hud/Widgets/SelectorWidget.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using RimHUD.Configuration;
3 | using RimHUD.Configuration.Settings;
4 | using RimHUD.Extensions;
5 | using UnityEngine;
6 | using Verse;
7 |
8 | namespace RimHUD.Interface.Hud.Widgets
9 | {
10 | public sealed class SelectorWidget : StandardWidget
11 | {
12 | private readonly Action? _onClick;
13 | private readonly Action? _onHover;
14 |
15 | private readonly Color? _backColor;
16 |
17 | public SelectorWidget(string? label, Func? tooltip, Action? onClick, Action? onHover, TextStyle textStyle, Color? backColor) : base(label, tooltip, textStyle)
18 | {
19 | _onClick = onClick;
20 | _onHover = onHover;
21 |
22 | _backColor = backColor;
23 | }
24 |
25 | public override bool Draw(Rect rect)
26 | {
27 | if (Label.NullOrWhitespace()) { return true; }
28 |
29 | Verse.Widgets.DrawBoxSolid(rect, _backColor ?? Theme.SelectorBackgroundColor.Value);
30 | DrawText(rect.ContractedBy(GUIPlus.SmallPadding, 0f), Label, Theme.SelectorTextColor.Value);
31 |
32 | if (Mouse.IsOver(rect))
33 | {
34 | var border = rect.ContractedBy(-1f);
35 | Verse.Widgets.DrawBox(border);
36 | _onHover?.Invoke();
37 | }
38 |
39 | if (Verse.Widgets.ButtonInvisible(rect)) { _onClick?.Invoke(); }
40 | return true;
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/source/Interface/Hud/Widgets/SeparatorWidget.cs:
--------------------------------------------------------------------------------
1 | using RimHUD.Configuration;
2 | using UnityEngine;
3 |
4 | namespace RimHUD.Interface.Hud.Widgets
5 | {
6 | public sealed class SeparatorWidget : IWidget
7 | {
8 | public const string TypeName = "Separator";
9 |
10 | public float GetMaxHeight => GUIPlus.SmallPadding;
11 |
12 | public bool Draw(Rect rect)
13 | {
14 | GUIPlus.SetColor(Theme.LineColor.Value);
15 | Verse.Widgets.DrawLineHorizontal(rect.x, rect.y + (rect.height / 2f), rect.width);
16 | GUIPlus.ResetColor();
17 | return true;
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/source/Interface/Hud/Widgets/StandardWidget.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using RimHUD.Configuration.Settings;
3 | using UnityEngine;
4 |
5 | namespace RimHUD.Interface.Hud.Widgets
6 | {
7 | public abstract class StandardWidget : IWidget
8 | {
9 | public abstract bool Draw(Rect rect);
10 | private readonly TextStyle _textStyle;
11 |
12 | protected string? Label { get; }
13 | protected Func? Tooltip { get; }
14 |
15 | public float GetMaxHeight { get; }
16 |
17 | protected StandardWidget(string? label, Func? tooltip, TextStyle textStyle)
18 | {
19 | Label = label;
20 | Tooltip = tooltip;
21 |
22 | _textStyle = textStyle;
23 | GetMaxHeight = textStyle.LineHeight;
24 | }
25 |
26 | protected void DrawText(Rect rect, string? text, Color? color = null, TextAnchor? alignment = null) => WidgetsPlus.DrawText(rect, text, _textStyle, color, alignment);
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/source/Interface/Hud/Widgets/ValueWidget.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using RimHUD.Configuration;
3 | using RimHUD.Configuration.Settings;
4 | using RimHUD.Extensions;
5 | using RimHUD.Interface.Hud.Tooltips;
6 | using UnityEngine;
7 | using Verse;
8 |
9 | namespace RimHUD.Interface.Hud.Widgets
10 | {
11 | public sealed class ValueWidget : StandardWidget
12 | {
13 | private readonly string? _value;
14 |
15 | private readonly Action? _onHover;
16 | private readonly Action? _onClick;
17 |
18 | public ValueWidget(string? label, string? value, Func? tooltip, Action? onHover, Action? onClick, TextStyle textStyle) : base(label, tooltip, textStyle)
19 | {
20 | _value = value;
21 |
22 | _onHover = onHover;
23 | _onClick = onClick;
24 | }
25 |
26 | public override bool Draw(Rect rect)
27 | {
28 | var showLabel = Label is not null;
29 |
30 | var grid = rect.GetHGrid(GUIPlus.TinyPadding, showLabel ? Theme.LabelWidth.Value : 0f, -1f);
31 |
32 | if (showLabel) { DrawText(grid[1], Label); }
33 | DrawText(grid[2], _value, alignment: showLabel ? TextAnchor.MiddleRight : null);
34 |
35 | if (HudLayout.IsMouseOverConfigButton) { return true; }
36 |
37 | if (Mouse.IsOver(rect)) { _onHover?.Invoke(); }
38 | if (Verse.Widgets.ButtonInvisible(rect.ExpandedBy(GUIPlus.TinyPadding))) { _onClick?.Invoke(); }
39 | TooltipsPlus.DrawCompact(grid[0], Tooltip);
40 |
41 | return true;
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/source/Interface/Hud/Widgets/WidgetTextStyle.cs:
--------------------------------------------------------------------------------
1 | namespace RimHUD.Interface.Hud.Widgets
2 | {
3 | public enum WidgetTextStyle
4 | {
5 | Small,
6 | Regular,
7 | Large
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/source/Interface/Screen/InspectPaneLog.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Linq;
3 | using RimWorld;
4 | using UnityEngine;
5 | using Verse;
6 |
7 | namespace RimHUD.Interface.Screen
8 | {
9 | public static class InspectPaneLog
10 | {
11 | private const int LogLinesMax = 300;
12 |
13 | private static Vector2 _scrollPosition = Vector2.zero;
14 |
15 | private static List? _log;
16 | private static ITab_Pawn_Log_Utility.LogDrawData _logDrawData = new();
17 |
18 | private static int _lastBattleTick = -1;
19 | private static int _lastPlayTick = -1;
20 |
21 | private static Pawn? _pawn;
22 |
23 | public static void Draw(Pawn pawn, Rect rect)
24 | {
25 | if (_log is null || _lastBattleTick != pawn.records!.LastBattleTick || _lastPlayTick != Find.PlayLog!.LastTick || _pawn != pawn)
26 | {
27 | ClearCache();
28 | _log = ITab_Pawn_Log_Utility.GenerateLogLinesFor(pawn, true, true, true, LogLinesMax).ToList();
29 | _lastPlayTick = Find.PlayLog!.LastTick;
30 | _lastBattleTick = pawn.records!.LastBattleTick;
31 | _pawn = pawn;
32 | }
33 |
34 | var width = rect.width - WidgetsPlus.ScrollbarWidth;
35 | var height = _log.Sum(line => line.GetHeight(rect.width));
36 |
37 | if (height <= 0f) { return; }
38 |
39 | var scrollRect = new Rect(0f, 0f, rect.width - WidgetsPlus.ScrollbarWidth, height);
40 |
41 | _logDrawData.StartNewDraw();
42 |
43 | Widgets.BeginScrollView(rect, ref _scrollPosition, scrollRect);
44 |
45 | var y = 0f;
46 | foreach (var line in _log.OfType())
47 | {
48 | line.Draw(y, width, _logDrawData);
49 | y += line.GetHeight(width);
50 | }
51 |
52 | Widgets.EndScrollView();
53 | }
54 |
55 | public static void ClearCache()
56 | {
57 | _log = null;
58 | _pawn = null;
59 | _lastBattleTick = -1;
60 | _lastPlayTick = -1;
61 | _logDrawData = new ITab_Pawn_Log_Utility.LogDrawData();
62 | _scrollPosition = Vector2.zero;
63 | }
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/source/Interface/Screen/InspectPanePlus.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using RimHUD.Configuration;
3 | using RimHUD.Engine;
4 | using RimHUD.Interface.Hud;
5 | using RimHUD.Interface.Hud.Models;
6 | using RimHUD.Interface.Hud.Tooltips;
7 | using RimWorld;
8 | using UnityEngine;
9 | using Verse;
10 |
11 | namespace RimHUD.Interface.Screen
12 | {
13 | public static class InspectPanePlus
14 | {
15 | public static Rect GetBounds(Rect bounds) => bounds.ContractedBy(GUIPlus.MediumPadding);
16 |
17 | public static void DrawPane(Rect rect, IInspectPane pane)
18 | {
19 | Theme.CheckFontChange();
20 |
21 | pane.RecentHeight = Theme.InspectPaneHeight.Value - WidgetsPlus.MainButtonHeight;
22 |
23 | try
24 | {
25 | var bounds = GetBounds(rect);
26 |
27 | var offset = 0f;
28 |
29 | var headerHeight = Math.Max(Theme.LargeTextStyle.LineHeight, GenUI.SmallIconSize);
30 | InspectPaneButtons.Draw(bounds.TopPartPixels(headerHeight), pane, ref offset);
31 |
32 | if (State.SelectedPawn is null || !pane.AnythingSelected) { return; }
33 |
34 | var labelRect = new Rect(bounds.x, bounds.y, bounds.width - offset, headerHeight);
35 | WidgetsPlus.DrawText(labelRect, Active.Name, Theme.LargeTextStyle, Active.FactionRelationColor);
36 | TooltipsPlus.DrawCompact(labelRect, BioTooltip.Get);
37 | if (Widgets.ButtonInvisible(labelRect)) { InspectPaneTabs.ToggleSocial(); }
38 |
39 | if (!pane.ShouldShowPaneContents) { return; }
40 |
41 | var contentRect = bounds.BottomPartPixels(bounds.height - headerHeight - GUIPlus.TinyPadding);
42 |
43 | if (Theme.DockedMode.Value) { HudLayout.DrawDocked(contentRect); }
44 | else if (Theme.InspectPaneTabAddLog.Value) { InspectPaneLog.Draw(Active.Pawn, contentRect); }
45 |
46 | }
47 | catch (Exception exception) { Report.HandleError(exception); }
48 |
49 | if (!Tutorial.IsComplete) { Tutorial.Presentation.Stages.DoInspectPane(rect); }
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/source/Interface/Screen/InspectPaneTabs.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using RimHUD.Access;
4 | using RimHUD.Configuration;
5 | using RimHUD.Engine;
6 | using RimWorld;
7 | using UnityEngine;
8 | using Verse;
9 |
10 | namespace RimHUD.Interface.Screen
11 | {
12 | public static class InspectPaneTabs
13 | {
14 | public static void Draw(IInspectPane pane)
15 | {
16 | const float fixedRecentHeight = 700f;
17 |
18 | try
19 | {
20 | var tabsTopY = pane.PaneTopY - WidgetsPlus.TabButtonHeight;
21 | var curTabX = InspectPaneUtility.PaneWidthFor(pane) - Theme.InspectPaneTabWidth.Value;
22 | var leftEdge = 0f;
23 | var drewOpen = false;
24 |
25 | if (pane.CurTabs is null) { return; }
26 |
27 | foreach (var tab in pane.CurTabs)
28 | {
29 | if (!tab.IsVisible) { continue; }
30 |
31 | var open = tab.GetType() == pane.OpenTabType;
32 |
33 | if (!tab.Hidden)
34 | {
35 | var rect = new Rect(curTabX, tabsTopY, Theme.InspectPaneTabWidth.Value, WidgetsPlus.TabButtonHeight);
36 | leftEdge = curTabX;
37 |
38 | Text.Font = GameFont.Small;
39 |
40 | if (Widgets.ButtonText(rect, tab.labelKey.Translate())) { Reflection.RimWorld_InspectPaneUtility_InterfaceToggleTab.InvokeStatic(tab, pane); }
41 | if (!open && !tab.TutorHighlightTagClosed.NullOrEmpty()) { UIHighlighter.HighlightOpportunity(rect, tab.TutorHighlightTagClosed); }
42 |
43 | curTabX -= Theme.InspectPaneTabWidth.Value;
44 | }
45 | if (!open) { continue; }
46 |
47 | tab.DoTabGUI();
48 | pane.RecentHeight = fixedRecentHeight;
49 | drewOpen = true;
50 | }
51 |
52 | if (drewOpen) { GUI.DrawTexture(new Rect(0f, tabsTopY, leftEdge, WidgetsPlus.TabButtonHeight), Reflection.RimWorld_InspectPaneUtility_InspectTabButtonFillTex.GetValueStatic()); }
53 | }
54 | catch (Exception exception) { Report.HandleError(exception); }
55 | }
56 |
57 | public static void ToggleBio() => Toggle(typeof(ITab_Pawn_Character));
58 | public static void ToggleGear() => Toggle(typeof(ITab_Pawn_Gear));
59 | public static void ToggleHealth() => Toggle(typeof(ITab_Pawn_Health));
60 | public static void ToggleNeeds() => Toggle(typeof(ITab_Pawn_Needs));
61 | public static void ToggleSocial() => Toggle(typeof(ITab_Pawn_Social));
62 | public static void ToggleTraining() => Toggle(typeof(ITab_Pawn_Training));
63 | public static void TogglePrisoner() => Toggle(typeof(ITab_Pawn_Prisoner));
64 | public static void ToggleSlave() => Toggle(typeof(ITab_Pawn_Slave));
65 |
66 | private static void Toggle(Type tabType)
67 | {
68 | var pane = (MainTabWindow_Inspect)MainButtonDefOf.Inspect!.TabWindow;
69 | var tab = (from t in pane.CurTabs where tabType.IsInstanceOfType(t) select t).FirstOrDefault();
70 | if (tab is null) { return; }
71 |
72 | if (Find.MainTabsRoot!.OpenTab != MainButtonDefOf.Inspect) { Find.MainTabsRoot.SetCurrentTab(MainButtonDefOf.Inspect); }
73 |
74 | Reflection.RimWorld_InspectPaneUtility_ToggleTab.InvokeStatic(tab, pane);
75 | }
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/source/Interface/Screen/LetterStackPlus.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using RimHUD.Access;
5 | using RimHUD.Configuration;
6 | using RimHUD.Extensions;
7 | using UnityEngine;
8 | using Verse;
9 |
10 | namespace RimHUD.Interface.Screen
11 | {
12 | public static class LetterStackPlus
13 | {
14 | private static readonly Lazy> Letters = new(static () => Reflection.Verse_LetterStack_Letters.GetValue>(Find.LetterStack));
15 | private static readonly Lazy> TmpBundledLetters = new(static () => Reflection.Verse_LetterStack_TmpBundledLetters.GetValue>(Find.LetterStack));
16 |
17 | public static void Draw(LetterStack instance, float baseY)
18 | {
19 | const float letterHeight = 30f;
20 |
21 | var letters = Letters.Value!;
22 | var tmpBundledLetters = TmpBundledLetters.Value!;
23 |
24 | var hudRect = Theme.GetHudBounds().ExpandedBy(GUIPlus.SmallPadding);
25 | var excess = Math.Max(letters.Count - Mathf.FloorToInt((baseY - Find.Alerts!.AlertsHeight - hudRect.yMax) / (Theme.LetterPadding.Value + letterHeight)), 0);
26 |
27 | if (excess <= 0)
28 | {
29 | SetLastTopYInt(baseY);
30 | return;
31 | }
32 |
33 | var isNotRepaint = Event.current!.type is not EventType.Repaint;
34 |
35 | var curY = baseY;
36 |
37 | for (var index = letters.LastIndex(); index > excess; --index)
38 | {
39 | curY -= letterHeight;
40 |
41 | var letter = letters[index]!;
42 | letter.DrawButtonAt(curY);
43 | if (isNotRepaint) { letter.CheckForMouseOverTextAt(curY); }
44 |
45 | curY -= Theme.LetterPadding.Value;
46 | }
47 |
48 | tmpBundledLetters.Clear();
49 | tmpBundledLetters.AddRange(letters.Take(excess + 1));
50 |
51 | instance.BundleLetter!.SetLetters(tmpBundledLetters);
52 |
53 | curY -= letterHeight;
54 |
55 | instance.BundleLetter!.DrawButtonAt(curY);
56 | if (isNotRepaint) { instance.BundleLetter!.CheckForMouseOverTextAt(curY); }
57 |
58 | curY -= Theme.LetterPadding.Value;
59 |
60 | tmpBundledLetters.Clear();
61 |
62 | SetLastTopYInt(curY);
63 | }
64 |
65 | private static void SetLastTopYInt(float value) => Reflection.Verse_LetterStack_LastTopYInt.SetValue(Find.LetterStack, value);
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/source/Interface/TexturesPlus.cs:
--------------------------------------------------------------------------------
1 | using UnityEngine;
2 | using Verse;
3 |
4 | namespace RimHUD.Interface
5 | {
6 | [StaticConstructorOnStartup]
7 | public static class TexturesPlus
8 | {
9 | public static Texture2D ToggleIcon { get; private set; } = LoadTexture("ToggleIcon");
10 | public static Texture2D ConfigIcon { get; private set; } = LoadTexture("ConfigIcon");
11 | public static Texture2D TutorialConfigIcon { get; private set; } = LoadTexture("TutorialConfigIcon");
12 | public static Texture2D SelfTendOnIcon { get; private set; } = LoadTexture("SelfTendOnIcon");
13 | public static Texture2D SelfTendOffIcon { get; private set; } = LoadTexture("SelfTendOffIcon");
14 |
15 | private static Texture2D LoadTexture(string key) => ContentFinder.Get($"{Mod.Id}/{key}");
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/source/Mod.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using HarmonyLib;
4 | using RimHUD.Configuration;
5 | using RimHUD.Engine;
6 | using RimHUD.Integration;
7 | using UnityEngine;
8 | using Verse;
9 |
10 | namespace RimHUD
11 | {
12 | public sealed class Mod : Verse.Mod
13 | {
14 | public const string Id = "RimHUD";
15 | public const string Name = Id;
16 | public const string Version = "1.15.2";
17 |
18 | public const string WorkshopLink = "https://steamcommunity.com/sharedfiles/filedetails/?id=1508850027";
19 |
20 | private static Mod? _instance;
21 | public static ModContentPack ContentPack => _instance!.Content;
22 |
23 | public static IEnumerable AcceptedConfigVersions { get; } = new[]
24 | {
25 | "1.14",
26 | "1.15"
27 | };
28 |
29 | public static bool DevMode { get; set; }
30 |
31 | public Mod(ModContentPack content) : base(content)
32 | {
33 | _instance = this;
34 |
35 | var harmony = new Harmony(Id);
36 | harmony.PatchAll();
37 |
38 | Persistent.Initialize();
39 |
40 | Report.Log("Initialized");
41 |
42 | LongEventHandler.QueueLongEvent(() => OnStartup(harmony), "InitializingInterface", false, null);
43 | }
44 |
45 | private static void OnStartup(Harmony harmony)
46 | {
47 | try
48 | {
49 | Persistent.Load();
50 | Integrations.Load();
51 | }
52 | catch (Exception exception)
53 | {
54 | Report.Error($"RimHUD was unable to initialize properly due to the following exception:\n{exception}");
55 | State.Activated = false;
56 | harmony.UnpatchAll();
57 | }
58 | }
59 |
60 | public override string SettingsCategory() => Id;
61 |
62 | public override void DoSettingsWindowContents(Rect rect) => Tutorial.Presentation.OverlayModSettings(rect);
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/source/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using RimHUD;
3 |
4 | [assembly: AssemblyTitle(Mod.Id)]
5 | [assembly: AssemblyProduct("RimWorld Mods by Jaxe")]
6 | [assembly: AssemblyCopyright("© Jaxe")]
7 | [assembly: AssemblyVersion(Mod.Version)]
8 |
--------------------------------------------------------------------------------
/source/Resources/Layouts/Defaults/Docked.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
--------------------------------------------------------------------------------
/source/Resources/Layouts/Defaults/Floating.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
--------------------------------------------------------------------------------
/source/obj/RimHUD.csproj.nuget.dgspec.json:
--------------------------------------------------------------------------------
1 | {
2 | "format": 1,
3 | "restore": {
4 | "C:\\Dev\\Projects\\RW\\Mods\\RimHUD\\source\\RimHUD.csproj": {}
5 | },
6 | "projects": {
7 | "C:\\Dev\\Projects\\RW\\Mods\\RimHUD\\source\\RimHUD.csproj": {
8 | "version": "1.0.0",
9 | "restore": {
10 | "projectUniqueName": "C:\\Dev\\Projects\\RW\\Mods\\RimHUD\\source\\RimHUD.csproj",
11 | "projectName": "RimHUD",
12 | "projectPath": "C:\\Dev\\Projects\\RW\\Mods\\RimHUD\\source\\RimHUD.csproj",
13 | "packagesPath": "C:\\Users\\X\\.nuget\\packages\\",
14 | "outputPath": "C:\\Dev\\Projects\\RW\\Mods\\RimHUD\\source\\obj\\",
15 | "projectStyle": "PackageReference",
16 | "skipContentFileWrite": true,
17 | "configFilePaths": [
18 | "C:\\Users\\X\\AppData\\Roaming\\NuGet\\NuGet.Config",
19 | "C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.Offline.config"
20 | ],
21 | "originalTargetFrameworks": [
22 | "net472"
23 | ],
24 | "sources": {
25 | "C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\": {},
26 | "https://api.nuget.org/v3/index.json": {}
27 | },
28 | "frameworks": {
29 | "net472": {
30 | "projectReferences": {}
31 | }
32 | }
33 | },
34 | "frameworks": {
35 | "net472": {}
36 | },
37 | "runtimes": {
38 | "win": {
39 | "#import": []
40 | },
41 | "win-x64": {
42 | "#import": []
43 | },
44 | "win-x86": {
45 | "#import": []
46 | }
47 | }
48 | }
49 | }
50 | }
--------------------------------------------------------------------------------
/source/obj/RimHUD.csproj.nuget.g.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | True
5 | NuGet
6 | $(MSBuildThisFileDirectory)project.assets.json
7 | $(UserProfile)\.nuget\packages\
8 | C:\Users\X\.nuget\packages\
9 | PackageReference
10 | 5.11.4
11 |
12 |
13 |
14 |
15 |
16 | $(MSBuildAllProjects);$(MSBuildThisFileFullPath)
17 |
18 |
--------------------------------------------------------------------------------
/source/obj/RimHUD.csproj.nuget.g.targets:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | $(MSBuildAllProjects);$(MSBuildThisFileFullPath)
5 |
6 |
--------------------------------------------------------------------------------
/source/obj/project.assets.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": 3,
3 | "targets": {
4 | ".NETFramework,Version=v4.7.2": {},
5 | ".NETFramework,Version=v4.7.2/win": {},
6 | ".NETFramework,Version=v4.7.2/win-x64": {},
7 | ".NETFramework,Version=v4.7.2/win-x86": {}
8 | },
9 | "libraries": {},
10 | "projectFileDependencyGroups": {
11 | ".NETFramework,Version=v4.7.2": []
12 | },
13 | "packageFolders": {
14 | "C:\\Users\\X\\.nuget\\packages\\": {}
15 | },
16 | "project": {
17 | "version": "1.0.0",
18 | "restore": {
19 | "projectUniqueName": "C:\\Dev\\Projects\\RW\\Mods\\RimHUD\\source\\RimHUD.csproj",
20 | "projectName": "RimHUD",
21 | "projectPath": "C:\\Dev\\Projects\\RW\\Mods\\RimHUD\\source\\RimHUD.csproj",
22 | "packagesPath": "C:\\Users\\X\\.nuget\\packages\\",
23 | "outputPath": "C:\\Dev\\Projects\\RW\\Mods\\RimHUD\\source\\obj\\",
24 | "projectStyle": "PackageReference",
25 | "skipContentFileWrite": true,
26 | "configFilePaths": [
27 | "C:\\Users\\X\\AppData\\Roaming\\NuGet\\NuGet.Config",
28 | "C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.Offline.config"
29 | ],
30 | "originalTargetFrameworks": [
31 | "net472"
32 | ],
33 | "sources": {
34 | "C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\": {},
35 | "https://api.nuget.org/v3/index.json": {}
36 | },
37 | "frameworks": {
38 | "net472": {
39 | "projectReferences": {}
40 | }
41 | }
42 | },
43 | "frameworks": {
44 | "net472": {}
45 | },
46 | "runtimes": {
47 | "win": {
48 | "#import": []
49 | },
50 | "win-x64": {
51 | "#import": []
52 | },
53 | "win-x86": {
54 | "#import": []
55 | }
56 | }
57 | }
58 | }
--------------------------------------------------------------------------------
/source/obj/project.nuget.cache:
--------------------------------------------------------------------------------
1 | {
2 | "version": 2,
3 | "dgSpecHash": "fTWRQOqxlGaFbFBTL7r8GLK0jVArbcAYYiWb7689ihXYHBRwEJRoNpt8IgQ6lvFR03mGrqaV1+dMOFnjKaYNng==",
4 | "success": true,
5 | "projectFilePath": "C:\\Dev\\Projects\\RW\\Mods\\RimHUD\\source\\RimHUD.csproj",
6 | "expectedPackageFiles": [],
7 | "logs": []
8 | }
--------------------------------------------------------------------------------
/source/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/source/release.targets:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 | $(ProjectDir)-\
37 | $(SolutionDir)build\$(AssemblyName)\
38 | $(SolutionDir)releases\
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
--------------------------------------------------------------------------------