diff --git a/Defs/PawnColumnDefs.xml b/Defs/PawnColumnDefs.xml index 4dd4668..3af3e8f 100644 --- a/Defs/PawnColumnDefs.xml +++ b/Defs/PawnColumnDefs.xml @@ -19,6 +19,14 @@ (16,16) + + JobText + WorkTab.PawnColumnWorker_JobText + true + + Current job + + CopyPasteDetailedWorkPriorities WorkTab.PawnColumnWorker_CopyPasteDetailedWorkPriorities diff --git a/Languages/English/Keyed/Keyed-English.xml b/Languages/English/Keyed/Keyed-English.xml index 1d18a97..7767f41 100644 --- a/Languages/English/Keyed/Keyed-English.xml +++ b/Languages/English/Keyed/Keyed-English.xml @@ -11,7 +11,7 @@ Click to collapse all priorities\nCtrl-click headers to toggle expanding individual priorities - Shift + left-click or scroll up to increase priorities\nShift + right click or scroll down to decrease priorities + Shift + left-click or scroll up to raise priorities\nShift + right click or scroll down to lower priorities Shift + left-click or scroll up to toggle priorities on\nShift + right click or scroll down to toggle priorities off Ctrl + click to expand list of detailed priorities Ctrl + click to collapse list of detailed priorities @@ -21,12 +21,18 @@ Should times be shown in 12h (e.g. noon, 9p.m.) or 24h (e.g. 12:00, 21:00) mode? Levels of priority How many levels of priority should we use? (Limited to between 4 and 9) + Default priority + Which level of priority is assigned by default? Sounds Play sounds when a priority is changed? Crunchy sounds Play a crunchy sound when a pawn is assigned to a job they are not skilled at? Disable Scrollwheel Disable the scrollwheel functions (when hovering over skills) + Current job column as text (requires restart) + Render the current job column as a text description of current activity.\nWhen disabled, an icon is displayed.\n\n(Due to a technical limitation, you must restart the game after changing this option.) + Highlight current job cell + Highlight the grid square in the work tab when the pawn is actually working that job right now. Vertical labels Display work labels vertically Fix vertical fonts @@ -48,7 +54,7 @@ {0} is assigned to {1} - Click to jump to\nShift-left-click or scroll up to increment priorities\nShift-right-click or scroll down to decrement priorities + Click to jump to\nShift-left-click or scroll up to raise priorities\nShift-right-click or scroll down to lower priorities Create new favourite @@ -77,4 +83,4 @@ Very low priority Lowest priority - \ No newline at end of file + diff --git a/Source/Core/Constants.cs b/Source/Core/Constants.cs index e89c628..4eeef82 100644 --- a/Source/Core/Constants.cs +++ b/Source/Core/Constants.cs @@ -12,6 +12,7 @@ public static class Constants { public const float MinTimeBarLabelSpacing = 50f; public const int TimeBarHeight = 40; public const int VerticalHeaderHeight = 100; + public const int JobTextWidth = 150; public const int WorkGiverBoxSize = 20; public const int WorkGiverWidth = 25; public const int WorkTypeBoxSize = 25; diff --git a/Source/Core/Settings.cs b/Source/Core/Settings.cs index f0cb3cc..c96ba70 100644 --- a/Source/Core/Settings.cs +++ b/Source/Core/Settings.cs @@ -1,4 +1,4 @@ -// Settings.cs +// Settings.cs // Copyright Karel Kroeze, 2020-2020 using UnityEngine; @@ -6,20 +6,22 @@ namespace WorkTab { public class Settings: ModSettings { - public static int defaultPriority = 3; - public static bool disableScrollwheel; - public static int maxPriority = 9; - public static bool playCrunch = true; - public static bool playSounds = true; - public static bool TwentyFourHourMode = true; - public static bool verticalLabels = true; - private static string _defaultPriorityBuffer = defaultPriority.ToString(); - - // public static bool sharedFavourites = true; + public static int maxPriority = 9; + public static int defaultPriority = 3; + public static bool TwentyFourHourMode = true; + public static bool playSounds = true; + public static bool playCrunch = true; + public static bool disableScrollwheel = false; + public static bool jobTextMode = false; + public static bool highlightCurrentJobCell = true; + public static bool verticalLabels = true; private static bool _fontFix = true; + // public static bool sharedFavourites = true; - // buffers - private static string _maxPriorityBuffer = maxPriority.ToString(); + // Buffers will be initialized with current settings as soon as + // DoWindowContents() → Listing_Standard.TextFieldNumericLabeled() → Widgets.TextFieldNumeric() will be called. + private static string maxPriorityBuffer = null; + private static string defaultPriorityBuffer = null; public Settings() { ApplyFontFix(_fontFix); @@ -37,10 +39,10 @@ public static void ApplyFontFix(bool state) { public static void DoWindowContents(Rect rect) { Listing_Standard options = new Listing_Standard(); options.Begin(rect); - options.TextFieldNumericLabeled("WorkTab.MaxPriority".Translate(), ref maxPriority, ref _maxPriorityBuffer, + options.TextFieldNumericLabeled("WorkTab.MaxPriority".Translate(), ref maxPriority, ref maxPriorityBuffer, 4, 9, "WorkTab.MaxPriorityTip".Translate(), 1 / 8f); options.TextFieldNumericLabeled("WorkTab.DefaultPriority".Translate(), ref defaultPriority, - ref _defaultPriorityBuffer, 1, 9, "WorkTab.DefaultPriorityTip".Translate(), + ref defaultPriorityBuffer, 1, 9, "WorkTab.DefaultPriorityTip".Translate(), 1 / 8f); options.CheckboxLabeled("WorkTab.24HourMode".Translate(), ref TwentyFourHourMode, "WorkTab.24HourModeTip".Translate()); @@ -51,6 +53,10 @@ public static void DoWindowContents(Rect rect) { "WorkTab.PlayCrunchTip".Translate()); options.CheckboxLabeled("WorkTab.DisableScrollwheel".Translate(), ref disableScrollwheel, "WorkTab.DisableScrollwheelTip".Translate()); + options.CheckboxLabeled("WorkTab.JobTextMode".Translate(), ref jobTextMode, + "WorkTab.JobTextModeTip".Translate()); + options.CheckboxLabeled("WorkTab.HighlightCurrentJobCell".Translate(), ref highlightCurrentJobCell, + "WorkTab.HighlightCurrentJobCellTip".Translate()); bool verticalLabelsBuffer = verticalLabels; options.CheckboxLabeled("WorkTab.VerticalLabels".Translate(), ref verticalLabelsBuffer, "WorkTab.VerticalLabelsTip".Translate()); @@ -64,7 +70,7 @@ public static void DoWindowContents(Rect rect) { options.CheckboxLabeled("WorkTab.FontFix".Translate(), ref _fontFixBuffer, "WorkTab.FontFixTip".Translate()); _fontFixBuffer = - verticalLabels && _fontFixBuffer; // disabling vertical labels makes the font fix unnecesary. + verticalLabels && _fontFixBuffer; // disabling vertical labels makes the font fix unnecessary. // apply any changes. if (_fontFixBuffer != _fontFix) { @@ -86,7 +92,9 @@ public override void ExposeData() { Scribe_Values.Look(ref playSounds, "PlaySounds", true); Scribe_Values.Look(ref playCrunch, "PlayCrunch", true); Scribe_Values.Look(ref disableScrollwheel, "DisableScrollwheel"); + Scribe_Values.Look(ref jobTextMode, "JobTextMode"); Scribe_Values.Look(ref verticalLabels, "VerticalLabels", true); + Scribe_Values.Look(ref highlightCurrentJobCell, "HighlightCurrentJobCell", true); Scribe_Values.Look(ref _fontFix, "FontFix", true); // apply font-fix on load diff --git a/Source/Extensions/PawnTable_Extensions.cs b/Source/Extensions/PawnTable_Extensions.cs new file mode 100644 index 0000000..5d94289 --- /dev/null +++ b/Source/Extensions/PawnTable_Extensions.cs @@ -0,0 +1,35 @@ +using RimWorld; +using RimWorld.BaseGen; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Text; +using System.Threading.Tasks; +using UnityEngine; + +namespace WorkTab.Extensions { + internal static class PawnTable_Extensions { + private static ConditionalWeakTable> outRectDictionary=new ConditionalWeakTable>(); + /// + /// Sets the rectangle the is drawn in. + /// + /// The being extended. + /// The rectangle the will be drawn in. + internal static void set_OutRect(this PawnTable pawnTable, Rect outRect) { + var value = outRectDictionary.GetValue( + pawnTable, + a => new StrongBox(outRect) + ); + value.Value = outRect; + } + /// + /// Gets the rectangle the will be drawn in. + /// + /// The being extended. + /// The rectangle the will be drawn in. + internal static Rect get_OutRect(this PawnTable pawnTable) { + return outRectDictionary.GetOrCreateValue(pawnTable).Value; + } + } +} diff --git a/Source/Favourites/FavouriteManager.cs b/Source/Favourites/FavouriteManager.cs index 9aa454f..879b0e6 100644 --- a/Source/Favourites/FavouriteManager.cs +++ b/Source/Favourites/FavouriteManager.cs @@ -179,7 +179,7 @@ private static void LoadFavouriteFloatMenu(Pawn pawn) { () => LoadFavourite(f.path, pawn))) .ToList(); if (options.Count == 0) { - options.Add(new FloatMenuOption("Fluffy.WorkTab.NoStoredFavourites", null)); + options.Add(new FloatMenuOption("Fluffy.WorkTab.NoStoredFavourites".Translate(), null)); } Find.WindowStack.Add(new FloatMenu(options)); } diff --git a/Source/HarmonyPatches/DefGenerator_GenerateImpliedDefs_PreResolve.cs b/Source/HarmonyPatches/DefGenerator_GenerateImpliedDefs_PreResolve.cs index 89b93a4..9333c15 100644 --- a/Source/HarmonyPatches/DefGenerator_GenerateImpliedDefs_PreResolve.cs +++ b/Source/HarmonyPatches/DefGenerator_GenerateImpliedDefs_PreResolve.cs @@ -24,7 +24,11 @@ private static void Postfix() { // insert mood and job columns before first work column name int firstWorkindex = workTable.columns.FindIndex(d => d.workerClass == typeof(PawnColumnWorker_WorkPriority)); - workTable.columns.Insert(firstWorkindex, PawnColumnDefOf.Job); + if (Settings.jobTextMode) { + workTable.columns.Insert(firstWorkindex, PawnColumnDefOf.JobText); + } else { + workTable.columns.Insert(firstWorkindex, PawnColumnDefOf.Job); + } workTable.columns.Insert(firstWorkindex + 1, PawnColumnDefOf.Mood); // go over PawnColumnDefs and replace all PawnColumnWorker_WorkPriority diff --git a/Source/HarmonyPatches/PawnTable/PawnTable_PawnTableOnGUI.cs b/Source/HarmonyPatches/PawnTable/PawnTable_PawnTableOnGUI.cs index 28462f6..3c0d8bd 100644 --- a/Source/HarmonyPatches/PawnTable/PawnTable_PawnTableOnGUI.cs +++ b/Source/HarmonyPatches/PawnTable/PawnTable_PawnTableOnGUI.cs @@ -8,6 +8,7 @@ using RimWorld; using UnityEngine; using Verse; +using WorkTab.Extensions; namespace WorkTab { [HarmonyPatch(typeof(PawnTable), nameof(PawnTable.PawnTableOnGUI))] @@ -79,7 +80,11 @@ public static bool Prefix(PawnTable __instance, // Instead, we want to limit outRect to the available view area, so a horizontal scrollbar can appear. float labelWidth = cachedColumnWidths[0]; var labelCol = columns[0]; - float outWidth = Mathf.Min( cachedSize.x - labelWidth, UI.screenWidth - (standardWindowMargin * 2f) ); + // ideally this method would be called with a Rect outRect + // indicating the window it is being drawn in instead + // of a Vector2 position + var outRect = __instance.get_OutRect(); + float outWidth = outRect.width - labelWidth; float viewWidth = cachedSize.x - labelWidth - 16f; Rect labelHeaderRect = new Rect( diff --git a/Source/PawnColumns/PawnColumnWorker_JobText.cs b/Source/PawnColumns/PawnColumnWorker_JobText.cs new file mode 100644 index 0000000..263df17 --- /dev/null +++ b/Source/PawnColumns/PawnColumnWorker_JobText.cs @@ -0,0 +1,33 @@ +// Copyright Karel Kroeze, 2020-2021. +// WorkTab/WorkTab/PawnColumnWorker_WorkTabLabel.cs + +using RimWorld; +using Verse; +using static WorkTab.Constants; + +namespace WorkTab { + public class PawnColumnWorker_JobText : PawnColumnWorker_Text { + public override int GetMinWidth(PawnTable table) + { + return JobTextWidth; + } + private string GetJobString(Pawn pawn) + { + return pawn.jobs?.curDriver?.GetReport() ?? ""; + } + protected override string GetTextFor(Pawn pawn) { + return GetJobString(pawn); + } + protected override string GetTip(Pawn pawn) { + return GetJobString(pawn); + } + public string GetValueToCompare(Pawn pawn) + { + return GetJobString(pawn); + } + public override int Compare(Pawn a, Pawn b) + { + return GetValueToCompare(a).CompareTo(GetValueToCompare(b)); + } + } +} diff --git a/Source/PawnColumns/PawnColumnWorker_WorkGiver.cs b/Source/PawnColumns/PawnColumnWorker_WorkGiver.cs index f8dd1c1..e6c3082 100644 --- a/Source/PawnColumns/PawnColumnWorker_WorkGiver.cs +++ b/Source/PawnColumns/PawnColumnWorker_WorkGiver.cs @@ -57,6 +57,16 @@ public override void DoCell(Rect rect, Pawn pawn, PawnTable table) { WorkGiverDef workgiver = WorkGiver; + if (Settings.highlightCurrentJobCell) + { + bool doingNow = (pawn.CurJob?.workGiverDef?.defName == workgiver?.defName); + if (doingNow) + { + GUI.color = Color.white; + GUI.DrawTexture(rect.ContractedBy(-2f), DrawUtilities.GetCurrentJobHighlightBox()); + } + } + // create rect in centre of cell, slightly offsetting left to give the appearance of aligning to worktype. Vector2 pos = rect.center - (new Vector2( WorkGiverBoxSize, WorkGiverBoxSize ) / 2f); Rect box = new Rect( pos.x - 2f, pos.y, WorkGiverBoxSize, WorkGiverBoxSize ); diff --git a/Source/PawnColumns/PawnColumnWorker_WorkType.cs b/Source/PawnColumns/PawnColumnWorker_WorkType.cs index d1d2524..196d86b 100644 --- a/Source/PawnColumns/PawnColumnWorker_WorkType.cs +++ b/Source/PawnColumns/PawnColumnWorker_WorkType.cs @@ -82,6 +82,16 @@ public override void DoCell(Rect rect, Pawn pawn, PawnTable table) { bool incapable = IncapableOfWholeWorkType( pawn ); WorkTypeDef worktype = def.workType; + if (Settings.highlightCurrentJobCell) + { + bool doingNow = (pawn.CurJob?.workGiverDef?.workType?.defName == worktype?.defName); + if (doingNow) + { + GUI.color = Color.white; + GUI.DrawTexture(rect.ContractedBy(-2f), DrawUtilities.GetCurrentJobHighlightBox()); + } + } + // create rect in centre of cell Vector2 pos = rect.center - (new Vector2( WorkTypeBoxSize, WorkTypeBoxSize ) / 2f); Rect box = new Rect( pos.x, pos.y, WorkTypeBoxSize, WorkTypeBoxSize ); @@ -381,7 +391,7 @@ private void HandleInteractionsDetailed(Rect rect, Pawn pawn) { } private void HandleInteractionsToggle(Rect rect, Pawn pawn) { - if ((Event.current.type == EventType.MouseDown || Event.current.type == EventType.ScrollWheel) + if ((Event.current.type == EventType.MouseDown || (Event.current.type == EventType.ScrollWheel && !Settings.disableScrollwheel)) && Mouse.IsOver(rect)) { // track priority so we can play appropriate sounds bool active = pawn.GetPriority( def.workType, VisibleHour ) > 0; diff --git a/Source/PawnTable/MainTabWindow_WorkTab.cs b/Source/PawnTable/MainTabWindow_WorkTab.cs index 4e1bf05..f4c8009 100644 --- a/Source/PawnTable/MainTabWindow_WorkTab.cs +++ b/Source/PawnTable/MainTabWindow_WorkTab.cs @@ -10,6 +10,7 @@ using RimWorld.Planet; using UnityEngine; using Verse; +using WorkTab.Extensions; using static WorkTab.Constants; using static WorkTab.InteractionUtilities; using static WorkTab.Resources; @@ -122,6 +123,7 @@ public static void SelectWholeDay() { } public override void DoWindowContents(Rect rect) { + Instance.Table.set_OutRect(rect); if (_columnsChanged) { RebuildTable(); } diff --git a/Source/Priorities/PriorityManager.cs b/Source/Priorities/PriorityManager.cs index 79d6046..fd43f4e 100644 --- a/Source/Priorities/PriorityManager.cs +++ b/Source/Priorities/PriorityManager.cs @@ -16,11 +16,15 @@ public class PriorityManager: GameComponent { private List pawnPriorityTrackersScribe; private List pawnsScribe; + [System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE0060:Remove unused parameter", Justification = "RimWorld requires a constructor with parameter")] public PriorityManager(Game game) : this() { } public PriorityManager() { _instance = this; + _nextId = 0; + _showScheduler = false; + priorities = new Dictionary(); } public static PriorityManager Get { @@ -90,7 +94,7 @@ public override void ExposeData() { List pawns = priorities.Keys.ToList(); foreach (Pawn pawn in pawns) { if (pawn?.Destroyed ?? true) // null or destroyed -{ + { priorities.Remove(pawn); } } diff --git a/Source/Utilities/DefOf.cs b/Source/Utilities/DefOf.cs index c643126..7792ab5 100644 --- a/Source/Utilities/DefOf.cs +++ b/Source/Utilities/DefOf.cs @@ -14,6 +14,7 @@ public static class PawnColumnDefOf { [MayRequireIdeology] public static PawnColumnDef Guest; [MayRequireIdeology] public static PawnColumnDef Ideo; public static PawnColumnDef Job; + public static PawnColumnDef JobText; public static PawnColumnDef LabelShortWithIcon; public static PawnColumnDef Mood; public static PawnColumnDef WorkTabLabel; diff --git a/Source/Utilities/DrawUtilities.cs b/Source/Utilities/DrawUtilities.cs index 6cd3d2b..d8ba890 100644 --- a/Source/Utilities/DrawUtilities.cs +++ b/Source/Utilities/DrawUtilities.cs @@ -11,6 +11,7 @@ using Verse; namespace WorkTab { + [StaticConstructorOnStartup] public static class DrawUtilities { private static MethodInfo _drawWorkBoxBackgroundMethodInfo; @@ -70,6 +71,25 @@ public static void DrawWorkBoxBackground(Rect box, Pawn pawn, WorkTypeDef workty _drawWorkBoxBackgroundMethodInfo.Invoke(null, new object[] { box, pawn, worktype }); } + private static Texture2D currentJobHighlightBox; + public static Texture2D GetCurrentJobHighlightBox() + { + if (currentJobHighlightBox != null) + { + return currentJobHighlightBox; + } + Color color = Color.Lerp(Color.black, Color.magenta, 0.7f); + Texture2D startingExample = WidgetsWork.WorkBoxOverlay_PreceptWarning; + int width = startingExample.width; + int height = startingExample.height; + Texture2D texture = new Texture2D(width, height); + Color[] pixels = Enumerable.Repeat(color, width * height).ToArray(); + texture.SetPixels(pixels); + texture.Apply(); + currentJobHighlightBox = texture; + return currentJobHighlightBox; + } + public static string PriorityLabel(int priority) { /** * 9 8 7 6 5 4 diff --git a/Source/WorkTab.sln b/Source/WorkTab.sln index 0d621db..68f5132 100644 --- a/Source/WorkTab.sln +++ b/Source/WorkTab.sln @@ -5,8 +5,6 @@ VisualStudioVersion = 15.0.26430.6 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WorkTab", "WorkTab.csproj", "{5C909B0F-E82A-46B1-AE39-E56285B236A2}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DynamicPawnTable", "..\..\..\TOOLS\DynamicPawnTable\DynamicPawnTable\DynamicPawnTable.csproj", "{E93B85A6-EEFF-4BDE-A6F4-CCE6D3487F9A}" -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FluffyUI", "..\..\..\TOOLS\FluffyUI\FluffyUI\FluffyUI.csproj", "{3E905175-2540-4C06-B4C6-F955836C0451}" EndProject Global @@ -19,10 +17,6 @@ Global {5C909B0F-E82A-46B1-AE39-E56285B236A2}.Debug|Any CPU.Build.0 = Debug|Any CPU {5C909B0F-E82A-46B1-AE39-E56285B236A2}.Release|Any CPU.ActiveCfg = Release|Any CPU {5C909B0F-E82A-46B1-AE39-E56285B236A2}.Release|Any CPU.Build.0 = Release|Any CPU - {E93B85A6-EEFF-4BDE-A6F4-CCE6D3487F9A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E93B85A6-EEFF-4BDE-A6F4-CCE6D3487F9A}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E93B85A6-EEFF-4BDE-A6F4-CCE6D3487F9A}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E93B85A6-EEFF-4BDE-A6F4-CCE6D3487F9A}.Release|Any CPU.Build.0 = Release|Any CPU {3E905175-2540-4C06-B4C6-F955836C0451}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {3E905175-2540-4C06-B4C6-F955836C0451}.Debug|Any CPU.Build.0 = Debug|Any CPU {3E905175-2540-4C06-B4C6-F955836C0451}.Release|Any CPU.ActiveCfg = Release|Any CPU