diff --git a/AllowTool.csproj b/AllowTool.csproj index bf2575b..53ae930 100644 --- a/AllowTool.csproj +++ b/AllowTool.csproj @@ -77,12 +77,14 @@ + + diff --git a/AllowTool.csproj.DotSettings b/AllowTool.csproj.DotSettings index 6bf57c2..71d87e5 100644 --- a/AllowTool.csproj.DotSettings +++ b/AllowTool.csproj.DotSettings @@ -1,4 +1,5 @@  True True - True \ No newline at end of file + True + True \ No newline at end of file diff --git a/Mods/AllowTool/About/About.xml b/Mods/AllowTool/About/About.xml index 71ff411..25efb40 100644 --- a/Mods/AllowTool/About/About.xml +++ b/Mods/AllowTool/About/About.xml @@ -4,7 +4,7 @@ UnlimitedHugs 0.17.0 https://ludeon.com/forums/index.php?topic=17218.0 - Version: 3.1.1 + Version: 3.1.2 A set of tools to make your life on the Rim a bit easier. Easily forbid and unforbid items, select similar things, have things hauled urgently and affect the entire map with powerful new tool extensions. diff --git a/Mods/AllowTool/Assemblies/AllowTool.dll b/Mods/AllowTool/Assemblies/AllowTool.dll index 1309eed..52b9a14 100644 Binary files a/Mods/AllowTool/Assemblies/AllowTool.dll and b/Mods/AllowTool/Assemblies/AllowTool.dll differ diff --git a/Mods/AllowTool/Defs/ReverseDesignatorDefs/ReverseDesignators.xml b/Mods/AllowTool/Defs/ReverseDesignatorDefs/ReverseDesignators.xml new file mode 100644 index 0000000..9c72089 --- /dev/null +++ b/Mods/AllowTool/Defs/ReverseDesignatorDefs/ReverseDesignators.xml @@ -0,0 +1,18 @@ + + + + + ReverseHaulUrgently + + HaulUrgentlyDesignator + + AllowTool.Designator_HaulUrgently + + + + ReverseSelectSimilar + AllowTool.Designator_SelectSimilarReverse + SelectSimilarDesignator + + + \ No newline at end of file diff --git a/Mods/AllowTool/Languages/English/Keyed/AllowToolStrings.xml b/Mods/AllowTool/Languages/English/Keyed/AllowToolStrings.xml index 1956cfa..8e6eb0a 100644 --- a/Mods/AllowTool/Languages/English/Keyed/AllowToolStrings.xml +++ b/Mods/AllowTool/Languages/English/Keyed/AllowToolStrings.xml @@ -22,11 +22,17 @@ Displays an AllowTool watermark in tool context menus when enabled. Right click icon on tools When enabled, displays a small icon on designator tools that have a context menu. + Extended "Context action" hotkey + When no tool is selected, the "Context action" hotkey will activate the context action on the first visible tool when items are selected. + Pick tool from selected items + Holding the Shift key and clicking on a tool while having items selected will pick that tool up instead of activating it on the items. Enable: {0} When enabled, adds a right-click menu to the tool that allows it to affect the entire map. ▼ Show settings ▼ Enable or disable tools Enable or disable context menus + Tools on selected things + When enabled, shows this tool when supported things are selected. Load or start a game for this setting to take effect. Show "Haul+" work type When enabled, shows the work type for the "Haul urgently" tool in the Work tab.\nThe game must be restarted for this setting to take effect. @@ -46,6 +52,7 @@ Haul visible items urgently Haul all map items urgently {0} items marked for urgent hauling. + {0} visible items marked for urgent hauling. Found no new items to haul. Strip all enemies {0} bodies designated for stripping. diff --git a/Mods/AllowTool/Languages/Russian/Keyed/AllowToolStrings.xml b/Mods/AllowTool/Languages/Russian/Keyed/AllowToolStrings.xml index f39a808..5fa8ee1 100644 --- a/Mods/AllowTool/Languages/Russian/Keyed/AllowToolStrings.xml +++ b/Mods/AllowTool/Languages/Russian/Keyed/AllowToolStrings.xml @@ -6,12 +6,12 @@ Запрещено {0} предметов. Не найдено предметов для запрещения. - + Разрешено {0} предметов по всей карте. Не найдено запрещенных предметов. - + Выделено {0} {1} по всей карте. - + Отображать: {0} Если настройка включена, инструмент будет отображаться в меню. Глобальные быстрые клавиши @@ -22,27 +22,36 @@ Отображает логотип AllowTool в контекстном меню инструментов. Иконка контекстного меню на инструментах Отображает иконку "правый клик" на инструментах, у которых есть контекстное меню. + Расширенная клавиша "Действие контекстного меню" + Когда не выбран ни одни инструмент, клавиша "Действие контекстного меню" активирует действие контекстного меню первого инструмента на выделенных предметах. + Выбор инструментов с выделенных предметов + Когда выделены предметы, удерживая клавишу Shift и нажав на инструмент, можно выбрать этот инструмент для дальнейшей работы вместо того чтобы активировать его на выделенных предметах. Включить: {0} Добавляет контекстное меню этому инструменту, позволяющее воздействовать на всю карту сразу. ▼ Открыть настройки ▼ Включить или отключить инструменты Включить или отключить контекстные меню - Отображать тип работы "Перенос+" - Если включено, панель настроек работ отображает дополнительный тип работы для инструмента срочного переноса. Требуется перезапуск. - + Инструменты на выделенных предметах + Tools on selected things + Если включено, отображает этот инструмент на поддерживаемых выделенных предметах. Вступает в силу после загрузки сохраненной игры. + Отображать тип работы "Перенос+" + Если включено, панель настроек работ отображает дополнительный тип работы для инструмента срочного переноса. Требуется перезапуск. + Клик для выделения предмета Будет выделено только: {0} Выделено максимум предметов (еще {0}) - + {0} предметов будут перенесены срочно. Не найдено предметов нуждающихся в переносе. - + Выделить схожие предметы на карте Выделено {0} схожих предметов на карте. Выделено {0} из доступных {1} схожих предметов на карте. Что-нибудь должно быть уже выделено чтобы найти и выделить схожие предметов. - Срочно перенести видимые предметы + Срочно перенести предметы + Срочно перенести видимые предметы + Срочно перенести все предметы на карте {0} предметов отмечено для срочного переноса. Не найдено предметов нуждающихся в переносе. Снять одежду со всех врагов @@ -71,5 +80,5 @@ Не найдено планов для отмены. Отменить все указания на карте Отменено {0} указаний на предметах и {1} на ландшафте. - + diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs index e97f870..89be726 100644 --- a/Properties/AssemblyInfo.cs +++ b/Properties/AssemblyInfo.cs @@ -31,5 +31,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("3.1.1")] -[assembly: AssemblyFileVersion("3.1.1")] +[assembly: AssemblyVersion("3.1.2")] +[assembly: AssemblyFileVersion("3.1.2")] diff --git a/Source/AllowToolController.cs b/Source/AllowToolController.cs index 0ec5b23..d9ca6b6 100644 --- a/Source/AllowToolController.cs +++ b/Source/AllowToolController.cs @@ -18,28 +18,36 @@ namespace AllowTool { public class AllowToolController : ModBase { internal const string ModId = "AllowTool"; internal const string DesignatorHandleNamePrefix = "show"; + internal const string ReverseDesignatorHandleNamePrefix = "showrev"; internal const string HarmonyInstanceId = "HugsLib.AllowTool"; private const string HaulWorktypeSettingName = "haulUrgentlyWorktype"; public static FieldInfo ResolvedDesignatorsField; public static FieldInfo ReverseDesignatorDatabaseDesListField; + public static FieldInfo GizmoGridGizmoListField; public static AllowToolController Instance { get; private set; } internal static HarmonyInstance HarmonyInstance { get; set; } // called before implied def generation public static void HideHaulUrgentlyWorkTypeIfDisabled() { - var peekValue = HugsLibController.SettingsManager.GetModSettings(ModId).PeekValue(HaulWorktypeSettingName); // handles will be created later- just peek for now - if (peekValue == "False") { - AllowToolDefOf.HaulingUrgent.visible = false; + try { + var peekValue = HugsLibController.SettingsManager.GetModSettings(ModId).PeekValue(HaulWorktypeSettingName); // handles will be created later- just peek for now + if (peekValue == "False") { + AllowToolDefOf.HaulingUrgent.visible = false; + } + } catch (Exception e) { + Log.Error("AllowTool failed to modify work type visibility: "+e); } } private readonly List activeDesignators = new List(); private readonly Dictionary> designatorToggleHandles = new Dictionary>(); + private readonly Dictionary> reverseDesignatorToggleHandles = new Dictionary>(); private SettingHandle settingGlobalHotkeys; private bool expandToolSettings; private bool expandProviderSettings; + private bool expandReverseToolSettings; public override string ModIdentifier { get { return ModId; } @@ -59,6 +67,10 @@ protected override bool HarmonyAutoPatch { internal SettingHandle ContextWatermarkSetting { get; private set; } + public SettingHandle ExtendedContextActionSetting { get; set; } + + public SettingHandle ReverseDesignatorPickSetting { get; set; } + public UnlimitedDesignationDragger Dragger { get; private set; } private AllowToolController() { @@ -113,9 +125,11 @@ public override void SettingsChanged() { } public bool IsDesignatorEnabledInSettings(ThingDesignatorDef def) { - SettingHandle handle; - designatorToggleHandles.TryGetValue(DesignatorHandleNamePrefix + def.defName, out handle); - return handle == null || handle.Value; + return GetToolHandleSettingValue(designatorToggleHandles, DesignatorHandleNamePrefix + def.defName); + } + + public bool IsReverseDesignatorEnabledInSettings(ReverseDesignatorDef def) { + return GetToolHandleSettingValue(reverseDesignatorToggleHandles, ReverseDesignatorHandleNamePrefix + def.defName); } public Designator_SelectableThings TryGetDesignator(ThingDesignatorDef def) { @@ -127,6 +141,8 @@ private void PrepareSettingsHandles() { ContextOverlaySetting = Settings.GetHandle("contextOverlay", "setting_contextOverlay_label".Translate(), "setting_contextOverlay_desc".Translate(), true); ContextWatermarkSetting = Settings.GetHandle("contextWatermark", "setting_contextWatermark_label".Translate(), "setting_contextWatermark_desc".Translate(), true); Settings.GetHandle(HaulWorktypeSettingName, "setting_haulUrgentlyWorktype_label".Translate(), "setting_haulUrgentlyWorktype_desc".Translate(), true); + ExtendedContextActionSetting = Settings.GetHandle("extendedContextActionKey", "setting_extendedContextHotkey_label".Translate(), "setting_extendedContextHotkey_desc".Translate(), true); + ReverseDesignatorPickSetting = Settings.GetHandle("reverseDesignatorPick", "setting_reverseDesignatorPick_label".Translate(), "setting_reverseDesignatorPick_desc".Translate(), true); SelectionLimitSetting = Settings.GetHandle("selectionLimit", "setting_selectionLimit_label".Translate(), "setting_selectionLimit_desc".Translate(), 200, Validators.IntRangeValidator(50, 100000)); SelectionLimitSetting.SpinnerIncrement = 50; // designators @@ -144,6 +160,14 @@ private void PrepareSettingsHandles() { provider.ProviderHandle = Settings.GetHandle(provider.SettingId, "setting_providerPrefix".Translate(provider.EntryTextKey.Translate()), "setting_provider_desc".Translate(), true); provider.ProviderHandle.VisibilityPredicate = () => expandProviderSettings; } + // reverse designators + MakeSettingsCategoryToggle("setting_showReverseToggles_label", () => expandReverseToolSettings = !expandReverseToolSettings); + foreach (var reverseDef in DefDatabase.AllDefs) { + var handleName = ReverseDesignatorHandleNamePrefix + reverseDef.defName; + var handle = Settings.GetHandle(handleName, "setting_showTool_label".Translate(reverseDef.designatorDef.label), "setting_reverseDesignator_desc".Translate(), true); + handle.VisibilityPredicate = () => expandReverseToolSettings; + reverseDesignatorToggleHandles[handleName] = handle; + } } private void MakeSettingsCategoryToggle(string labelId, Action buttonAction) { @@ -155,6 +179,15 @@ private void MakeSettingsCategoryToggle(string labelId, Action buttonAction) { }; } + public Designator_SelectableThings InstantiateDesignator(Type designatorType, ThingDesignatorDef designatorDef) { + try { + return (Designator_SelectableThings) Activator.CreateInstance(designatorType, designatorDef); + } catch (Exception e) { + Logger.ReportException(e, null, false, string.Format("instantiation of {0} with Def {1}", (designatorType != null ? designatorType.FullName : "(null)"), designatorDef)); + } + return null; + } + private void InjectDesignators() { var numDesignatorsInjected = 0; foreach (var designatorDef in DefDatabase.AllDefs) { @@ -167,7 +200,7 @@ private void InjectDesignators() { break; } if (insertIndex >= 0) { - var designator = (Designator_SelectableThings)Activator.CreateInstance(designatorDef.designatorClass, designatorDef); + var designator = InstantiateDesignator(designatorDef.designatorClass, designatorDef); resolvedDesignators.Insert(insertIndex + 1, designator); designator.SetVisible(IsDesignatorEnabledInSettings(designatorDef)); activeDesignators.Add(new DesignatorEntry(designator, designatorDef.hotkeyDef)); @@ -185,16 +218,23 @@ private void InjectDesignators() { private void PrepareReflection() { ResolvedDesignatorsField = typeof(DesignationCategoryDef).GetField("resolvedDesignators", HugsLibUtility.AllBindingFlags); ReverseDesignatorDatabaseDesListField = typeof(ReverseDesignatorDatabase).GetField("desList", HugsLibUtility.AllBindingFlags); + var gizmoGridType = GenTypes.GetTypeInAnyAssembly("RimWorld.InspectGizmoGrid"); + if (gizmoGridType != null) { + GizmoGridGizmoListField = gizmoGridType.GetField("gizmoList", HugsLibUtility.AllBindingFlags); + } if (ResolvedDesignatorsField == null || ResolvedDesignatorsField.FieldType != typeof(List) - || ReverseDesignatorDatabaseDesListField == null || ReverseDesignatorDatabaseDesListField.FieldType != typeof(List)) { + || ReverseDesignatorDatabaseDesListField == null || ReverseDesignatorDatabaseDesListField.FieldType != typeof(List) + || GizmoGridGizmoListField == null || GizmoGridGizmoListField.FieldType != typeof(List)) { Logger.Error("Failed to reflect required members"); } } + + private void CheckForHotkeyPresses() { if (Event.current.keyCode == KeyCode.None) return; if (AllowToolDefOf.ToolContextMenuAction.JustPressed) { - DesignatorContextMenuController.DoContextMenuActionForActiveDesignator(); + DesignatorContextMenuController.ProcessContextActionHotkeyPress(); } if (!settingGlobalHotkeys || Find.VisibleMap == null) return; for (int i = 0; i < activeDesignators.Count; i++) { @@ -213,5 +253,11 @@ public DesignatorEntry(Designator_SelectableThings designator, KeyBindingDef key this.key = key; } } + + private bool GetToolHandleSettingValue(Dictionary> handleDict, string handleName) { + SettingHandle handle; + handleDict.TryGetValue(handleName, out handle); + return handle == null || handle.Value; + } } } \ No newline at end of file diff --git a/Source/AllowToolEarlyInit.cs b/Source/AllowToolEarlyInit.cs index e91ff52..6ae401c 100644 --- a/Source/AllowToolEarlyInit.cs +++ b/Source/AllowToolEarlyInit.cs @@ -1,4 +1,5 @@ -using Harmony; +using System; +using Harmony; using Verse; namespace AllowTool { @@ -7,8 +8,13 @@ namespace AllowTool { /// public class AllowToolEarlyInit : Mod { public AllowToolEarlyInit(ModContentPack content) : base(content) { - AllowToolController.HarmonyInstance = HarmonyInstance.Create(AllowToolController.HarmonyInstanceId); - AllowToolController.HarmonyInstance.PatchAll(typeof(AllowToolController).Assembly); + try { + AllowToolController.HarmonyInstance = HarmonyInstance.Create(AllowToolController.HarmonyInstanceId); + AllowToolController.HarmonyInstance.PatchAll(typeof(AllowToolController).Assembly); + } catch (Exception e) { + // Resharper disable once + Log.Error("AllowTool failed to apply Harmony patches: "+e); + } } } } \ No newline at end of file diff --git a/Source/Context/BaseDesignatorMenuProvider.cs b/Source/Context/BaseDesignatorMenuProvider.cs index 868e301..884e08f 100644 --- a/Source/Context/BaseDesignatorMenuProvider.cs +++ b/Source/Context/BaseDesignatorMenuProvider.cs @@ -13,8 +13,8 @@ namespace AllowTool.Context { public abstract class BaseDesignatorMenuProvider { protected delegate void MenuActionMethod(Designator designator, Map map); - private const string SuccessMessageStringIdSuffix = "_succ"; - private const string FailureMessageStringIdSuffix = "_fail"; + protected const string SuccessMessageStringIdSuffix = "_succ"; + protected const string FailureMessageStringIdSuffix = "_fail"; // the toogle for this provider, assigned automatically by AllotToolController public virtual SettingHandle ProviderHandle { get; set; } diff --git a/Source/Context/DesignatorContextMenuController.cs b/Source/Context/DesignatorContextMenuController.cs index 202c441..261158d 100644 --- a/Source/Context/DesignatorContextMenuController.cs +++ b/Source/Context/DesignatorContextMenuController.cs @@ -1,6 +1,8 @@ using System; using System.Collections.Generic; using System.Linq; +using HugsLib.Utils; +using RimWorld; using UnityEngine; using Verse; @@ -10,9 +12,29 @@ namespace AllowTool.Context { /// Instantiates individual handlers, processess input events and draws overlay icons. /// public static class DesignatorContextMenuController { + private enum MouseButtons { + Left = 0, Right = 1 + } + private static readonly Dictionary designatorMenuProviders = new Dictionary(); - private static readonly List reverseDesignatorsForRemoval = new List(); + private static readonly List> currentDrawnReverseDesignators = new List>(); private static readonly Vector2 overlayIconOffset = new Vector2(59f, 2f); + private static readonly HashSet reversePickingSupportedDesignators = new HashSet { + typeof(Designator_Cancel), + typeof(Designator_Claim), + typeof(Designator_Deconstruct), + typeof(Designator_Uninstall), + typeof(Designator_Haul), + typeof(Designator_Hunt), + typeof(Designator_Slaughter), + typeof(Designator_Tame), + typeof(Designator_PlantsCut), + typeof(Designator_PlantsHarvest), + typeof(Designator_Mine), + typeof(Designator_Strip), + typeof(Designator_RearmTrap), + typeof(Designator_Open) + }; private static List _providers; public static List MenuProviderInstances { @@ -59,11 +81,14 @@ public static void DrawCommandOverlayIfNeeded(Command gizmo, Vector2 topLeft) { // try catch a right click on a supported designator. Left clicks should return false. public static bool TryProcessDesignatorInput(Designator designator) { try { - if (Event.current.button != 1) return false; - foreach (var provider in MenuProviderInstances) { - if (provider.HandledDesignatorType.IsInstanceOfType(designator)) { - provider.OpenContextMenu(designator); - return true; + if (Event.current.button == (int)MouseButtons.Left && HugsLibUtility.ShiftIsHeld && AllowToolController.Instance.ReverseDesignatorPickSetting) { + return TryPickDesignatorFromReverseDesignator(designator); + } else if (Event.current.button == (int)MouseButtons.Right) { + foreach (var provider in MenuProviderInstances) { + if (provider.HandledDesignatorType.IsInstanceOfType(designator)) { + provider.OpenContextMenu(designator); + return true; + } } } } catch (Exception e) { @@ -72,20 +97,28 @@ public static bool TryProcessDesignatorInput(Designator designator) { return false; } - // called when a designator is selected and the context action key is pressed - public static void DoContextMenuActionForActiveDesignator() { + public static void ProcessContextActionHotkeyPress() { var selectedDesignator = Find.DesignatorManager.SelectedDesignator; - if (selectedDesignator == null || !designatorMenuProviders.ContainsKey(selectedDesignator)) return; - designatorMenuProviders[selectedDesignator].HotkeyAction(selectedDesignator); + if (selectedDesignator != null && designatorMenuProviders.ContainsKey(selectedDesignator)) { + designatorMenuProviders[selectedDesignator].HotkeyAction(selectedDesignator); + } else if(AllowToolController.Instance.ExtendedContextActionSetting.Value) { + // activate hotkey action for first visible reverse designator + foreach (var pair in currentDrawnReverseDesignators) { + if (designatorMenuProviders.ContainsKey(pair.Key)) { + designatorMenuProviders[pair.Key].HotkeyAction(pair.Value); + break; + } + } + } } // called every OnGUI- Commands for reverse designators are instantiated each time they are drawn, so we need to discard the old ones public static void ClearReverseDesignatorPairs() { - if (reverseDesignatorsForRemoval.Count > 0) { - foreach (var command in reverseDesignatorsForRemoval) { - if (designatorMenuProviders.ContainsKey(command)) designatorMenuProviders.Remove(command); + if (currentDrawnReverseDesignators.Count > 0) { + foreach (var pair in currentDrawnReverseDesignators) { + if (designatorMenuProviders.ContainsKey(pair.Key)) designatorMenuProviders.Remove(pair.Key); } - reverseDesignatorsForRemoval.Clear(); + currentDrawnReverseDesignators.Clear(); } } @@ -100,7 +133,7 @@ public static void RegisterReverseDesignatorPair(Designator designator, Command_ }; var providers = MenuProviderInstances; TryBindDesignatorToHandler(designator, designatorButton, providers); - reverseDesignatorsForRemoval.Add(designatorButton); + currentDrawnReverseDesignators.Add(new KeyValuePair(designatorButton, designator)); } public static void CheckForMemoryLeak() { @@ -110,6 +143,14 @@ public static void CheckForMemoryLeak() { } } + private static bool TryPickDesignatorFromReverseDesignator(Designator designator) { + if (designator is Designator_SelectableThings || (designator!=null && reversePickingSupportedDesignators.Contains(designator.GetType()))) { + Find.DesignatorManager.Select(designator); + return true; + } + return false; + } + private static List InstantiateProviders() { var providers = new List(); try { diff --git a/Source/Context/MenuProvider_HaulUrgently.cs b/Source/Context/MenuProvider_HaulUrgently.cs index f3120c0..54832a1 100644 --- a/Source/Context/MenuProvider_HaulUrgently.cs +++ b/Source/Context/MenuProvider_HaulUrgently.cs @@ -34,14 +34,14 @@ public override void ContextMenuAction(Designator designator, Map map) { // skip rock chunks in designation, select only visible on screen private void HaulVisibleAction(Designator designator, Map map) { var visibleRect = GetVisibleMapRect(); - DesignateWithPredicate(designator,map, thing => visibleRect.Contains(thing.Position)); + DesignateWithPredicate(designator, map, thing => visibleRect.Contains(thing.Position), "Designator_context_urgent_visible_succ"); } private void HaulEverythingAction(Designator designator, Map map) { DesignateWithPredicate(designator, map); } - private void DesignateWithPredicate(Designator designator, Map map, Func shouldDesignateThing = null) { + private void DesignateWithPredicate(Designator designator, Map map, Func shouldDesignateThing = null, string successMessageKey = null) { int hitCount = 0; foreach (var thing in map.listerThings.ThingsInGroup(DesingatorRequestGroup)) { if (ValidForDesignation(thing) && @@ -53,7 +53,14 @@ private void DesignateWithPredicate(Designator designator, Map map, Func 0) { + Messages.Message(successMessageKey.Translate(hitCount), MessageSound.Benefit); + } else { + Messages.Message((EntryTextKey + FailureMessageStringIdSuffix).Translate(), MessageSound.RejectInput); + } } // code swiped from ThingSelectionUtility diff --git a/Source/Context/MenuProvider_SelectSimilar.cs b/Source/Context/MenuProvider_SelectSimilar.cs index f1a867d..f0af4ab 100644 --- a/Source/Context/MenuProvider_SelectSimilar.cs +++ b/Source/Context/MenuProvider_SelectSimilar.cs @@ -21,7 +21,10 @@ public override Type HandledDesignatorType { public override void ContextMenuAction(Designator designator, Map map) { var des = (Designator_SelectSimilar) designator; - des = des.GetNonReverseVersion(); + var reverse = des as Designator_SelectSimilarReverse; + if (reverse != null) { + des = reverse.GetNonReverseVersion(); + } if (Find.Selector.NumSelected == 0) { Messages.Message("Designator_context_similar_fail".Translate(), MessageSound.RejectInput); return; diff --git a/Source/Designators/Designator_SelectSimilar.cs b/Source/Designators/Designator_SelectSimilar.cs index ba6aed3..2a7aecb 100644 --- a/Source/Designators/Designator_SelectSimilar.cs +++ b/Source/Designators/Designator_SelectSimilar.cs @@ -19,14 +19,8 @@ public class Designator_SelectSimilar : Designator_SelectableThings { private const int MaxNumListedConstraints = 5; private readonly Dictionary selectionConstraints = new Dictionary(); - private readonly bool reverseDesignatorMode; private bool constraintsNeedReindexing; private string readableConstraintList; - - private Selector selectorRef; - private Selector Selector { // cache selector to avoid lots of unnecessary routing calls - get { return selectorRef ?? (selectorRef = Find.Selector); } - } private int numDesignated; public override int GetNumDesigantedThings() { @@ -40,48 +34,24 @@ private bool AnySelectionContstraints { public Designator_SelectSimilar(ThingDesignatorDef def) : base(def) { } - public Designator_SelectSimilar(ThingDesignatorDef def, bool reverseDesignatorMode) : base(def) { - this.reverseDesignatorMode = reverseDesignatorMode; - } - public override void Selected() { base.Selected(); ReindexSelectionConstraints(); } - - // ensure we used the proper designator for the context action, that does not have its constraints removed - public Designator_SelectSimilar GetNonReverseVersion() { - return !reverseDesignatorMode ? this : (Designator_SelectSimilar) AllowToolController.Instance.TryGetDesignator(AllowToolDefOf.SelectSimilarDesignator); - } - - // used by dragger and reverse designator. We want the reverse designator to always show, but ignoring constraints breaks the context action + public override AcceptanceReport CanDesignateThing(Thing thing) { return thing.def != null && thing.def.selectable && thing.def.label != null && !BlockedByFog(thing.Position, thing.Map) && - (reverseDesignatorMode || ThingMatchesSelectionConstraints(thing) || AllowToolController.Instance.Dragger.SelectingSingleCell) && // this allows us to select items that don't match the selection conststraints if we are not dragging, only clicking - (reverseDesignatorMode || SelectionLimitAllowsAdditionalThing()); + (ThingMatchesSelectionConstraints(thing) || AllowToolController.Instance.Dragger.SelectingSingleCell) && // this allows us to select items that don't match the selection conststraints if we are not dragging, only clicking + SelectionLimitAllowsAdditionalThing(); } public override void DesignateThing(Thing t) { TrySelectThing(t); } - protected override void FinalizeDesignationSucceeded() { - if (reverseDesignatorMode) { - Log.Message("xx"); - // intercept call from the reverse designator button - // activate the regualar select similar designator for the player to select more items - var selectSimilarNonReverse = GetNonReverseVersion(); - if (Find.DesignatorManager.SelectedDesignator != selectSimilarNonReverse) { - // debounce multiple selected items - Find.DesignatorManager.Select(selectSimilarNonReverse); - } - } - base.FinalizeDesignationSucceeded(); - } - public override void DesignateSingleCell(IntVec3 cell) { var map = Find.VisibleMap; var cellThings = map.thingGrid.ThingsListAtFast(cell); @@ -118,18 +88,19 @@ public override void SelectedOnGUI() { } public bool SelectionLimitAllowsAdditionalThing() { - return Selector.NumSelected < AllowToolController.Instance.SelectionLimitSetting.Value || AllowToolController.Instance.Dragger.SelectingSingleCell || HugsLibUtility.AltIsHeld; + return Find.Selector.NumSelected < AllowToolController.Instance.SelectionLimitSetting.Value || AllowToolController.Instance.Dragger.SelectingSingleCell || HugsLibUtility.AltIsHeld; } // generate an index of defs to compare other things against, based on currently selected things public void ReindexSelectionConstraints() { try { + var selector = Find.Selector; constraintsNeedReindexing = false; selectionConstraints.Clear(); readableConstraintList = ""; - if (Selector.NumSelected == 0) return; + if (selector.NumSelected == 0) return; // get defs of selected objects, count duplicates - foreach (var selectedObject in Selector.SelectedObjects) { + foreach (var selectedObject in selector.SelectedObjects) { var thing = selectedObject as Thing; if (thing == null || thing.def == null || !thing.def.selectable) continue; int constraintHash = GetConstraintHashForThing(thing); @@ -164,8 +135,9 @@ public void ReindexSelectionConstraints() { } public bool TrySelectThing(Thing thing) { - if (!CanDesignateThing(thing).Accepted || Selector.IsSelected(thing)) return false; - Selector.SelectedObjects.Add(thing); // manually adding objects to the selection list gets around the stock selection limit + var selector = Find.Selector; + if (!CanDesignateThing(thing).Accepted || selector.IsSelected(thing)) return false; + selector.SelectedObjects.Add(thing); // manually adding objects to the selection list gets around the stock selection limit SelectionDrawer.Notify_Selected(thing); if (!AnySelectionContstraints) { ReindexSelectionConstraints(); @@ -177,7 +149,7 @@ public bool TrySelectThing(Thing thing) { private void ProcessSingleCellClick(IntVec3 cell) { if (!HugsLibUtility.ShiftIsHeld) { - Selector.ClearSelection(); + Find.Selector.ClearSelection(); ReindexSelectionConstraints(); } if (cell.IsValid) { @@ -195,9 +167,9 @@ private bool BlockedByFog(IntVec3 cell, Map map) { return map.fogGrid.IsFogged(cell) && !DebugSettings.godMode; } - // close architect menu if anything wa selected + // close architect menu if anything was selected private void TryCloseArchitectMenu() { - if (Selector.NumSelected == 0) return; + if (Find.Selector.NumSelected == 0) return; if (Find.MainTabsRoot.OpenTab != MainButtonDefOf.Architect) return; Find.MainTabsRoot.EscapeCurrentTab(); } diff --git a/Source/Patches/Designator_ProcessInput_Patch.cs b/Source/Patches/Designator_ProcessInput_Patch.cs index 5816c9d..aa2a2d9 100644 --- a/Source/Patches/Designator_ProcessInput_Patch.cs +++ b/Source/Patches/Designator_ProcessInput_Patch.cs @@ -4,7 +4,7 @@ namespace AllowTool.Patches { /// - /// Intercepts right clicks on supported designators, ignores other interactions + /// Intercepts right clicks and shift-left clicks on supported designators, ignores other interactions /// [HarmonyPatch(typeof(Designator))] [HarmonyPatch("ProcessInput")] diff --git a/Source/Reverse/Designator_SelectSimilarReverse.cs b/Source/Reverse/Designator_SelectSimilarReverse.cs new file mode 100644 index 0000000..a5e91d4 --- /dev/null +++ b/Source/Reverse/Designator_SelectSimilarReverse.cs @@ -0,0 +1,36 @@ +using System; +using Verse; + +namespace AllowTool { + /// + /// A stub for use as a reverse designator. + /// We can't use the regular one, because the selection constraints mess with the visibility of the reverse designator. + /// Instead of designating, picks up the actual SelectSimilar designator. + /// + public class Designator_SelectSimilarReverse : Designator_SelectSimilar { + public Designator_SelectSimilarReverse(ThingDesignatorDef def) : base(def) { + } + + public Designator_SelectSimilar GetNonReverseVersion() { + var des = (Designator_SelectSimilar) AllowToolController.Instance.TryGetDesignator(AllowToolDefOf.SelectSimilarDesignator); + if (des == null) { + throw new Exception("Could not get Designator_SelectSimilar from AllowToolController"); + } + return des; + } + + public override AcceptanceReport CanDesignateThing(Thing thing) { + return thing.def != null && + thing.def.selectable && + thing.def.label != null && + thing.Map != null && + !thing.Map.fogGrid.IsFogged(thing.Position); + } + + protected override void FinalizeDesignationSucceeded() { + var selectSimilarNonReverse = GetNonReverseVersion(); + Find.DesignatorManager.Select(selectSimilarNonReverse); + base.FinalizeDesignationSucceeded(); + } + } +} \ No newline at end of file diff --git a/Source/Reverse/ReverseDesignatorDef.cs b/Source/Reverse/ReverseDesignatorDef.cs new file mode 100644 index 0000000..b21c304 --- /dev/null +++ b/Source/Reverse/ReverseDesignatorDef.cs @@ -0,0 +1,13 @@ +using System; +using Verse; + +namespace AllowTool { + /// + /// Def for AllowTool designators to be used as reverse designators (designators shown on selected items). + /// These are automatically instantiated and injected. + /// + public class ReverseDesignatorDef : Def { + public ThingDesignatorDef designatorDef; + public Type designatorClass; + } +} \ No newline at end of file diff --git a/Source/ReverseDesignatorProvider.cs b/Source/ReverseDesignatorProvider.cs index a705f37..7c6bb1c 100644 --- a/Source/ReverseDesignatorProvider.cs +++ b/Source/ReverseDesignatorProvider.cs @@ -8,17 +8,13 @@ namespace AllowTool { public static class ReverseDesignatorProvider { public static void OnReverseDesignatorInit(ReverseDesignatorDatabase database) { var designatorsList = (List)AllowToolController.ReverseDesignatorDatabaseDesListField.GetValue(database); - if (AllowToolController.Instance.IsDesignatorEnabledInSettings(AllowToolDefOf.HaulUrgentlyDesignator)) { - var haulUrgently = new Designator_HaulUrgently(AllowToolDefOf.HaulUrgentlyDesignator); - if (Current.Game.Rules.DesignatorAllowed(haulUrgently)) { - designatorsList.Add(haulUrgently); - } - } - if (AllowToolController.Instance.IsDesignatorEnabledInSettings(AllowToolDefOf.SelectSimilarDesignator)) { - var selectSimilar = new Designator_SelectSimilar(AllowToolDefOf.SelectSimilarDesignator, true); - if (Current.Game.Rules.DesignatorAllowed(selectSimilar)) { - designatorsList.Add(selectSimilar); - } + foreach (var def in DefDatabase.AllDefs) { + if (AllowToolController.Instance.IsReverseDesignatorEnabledInSettings(def)) { + var des = AllowToolController.Instance.InstantiateDesignator(def.designatorClass, def.designatorDef); + if (Current.Game.Rules.DesignatorAllowed(des)) { + designatorsList.Add(des); + } + } } } }