From b999528dde84754b71145d9832f9b8e046c544ff Mon Sep 17 00:00:00 2001 From: Tyfon <29051038+tyfon7@users.noreply.github.com> Date: Fri, 5 Jul 2024 23:32:07 -0700 Subject: [PATCH] Context menu on right --- Patches/ContextMenuPatches.cs | 87 +++++++++++++++++++++++++++++++++++ R.cs | 6 +++ Settings.cs | 10 ++++ 3 files changed, 103 insertions(+) diff --git a/Patches/ContextMenuPatches.cs b/Patches/ContextMenuPatches.cs index c92ba59..5ff21d1 100644 --- a/Patches/ContextMenuPatches.cs +++ b/Patches/ContextMenuPatches.cs @@ -9,6 +9,7 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; using TMPro; +using UnityEngine; namespace UIFixes { @@ -65,6 +66,8 @@ namespace UIFixes TradingRootInteractionsItemField = AccessTools.Field(TradingRootInteractionsType, "item_0"); new ContextMenuNamesPatch().Enable(); + new PositionSubMenuPatch().Enable(); + new PositionInsuranceSubMenuPatch().Enable(); new DeclareSubInteractionsInventoryPatch().Enable(); new CreateSubInteractionsInventoryPatch().Enable(); @@ -419,6 +422,90 @@ namespace UIFixes } } + public class PositionSubMenuPatch : ModulePatch + { + protected override MethodBase GetTargetMethod() + { + return AccessTools.Method(InventoryRootInteractionsType, "CreateSubInteractions"); + } + + // Existing logic tries to place it on the right, moving to the left if necessary. They didn't do it correctly, so it always goes on the left. + [PatchPostfix] + public static void Postfix(ISubInteractions subInteractionsWrapper) + { + if (subInteractionsWrapper is not InteractionButtonsContainer buttonsContainer) + { + return; + } + + var wrappedContainer = buttonsContainer.R(); + SimpleContextMenuButton button = wrappedContainer.ContextMenuButton; + SimpleContextMenu flyoutMenu = wrappedContainer.ContextMenu; + + if (button == null || flyoutMenu == null) + { + return; + } + + PositionContextMenuFlyout(button, flyoutMenu); + } + } + + // Insurance submenu is async, need to postfix the actual set call + public class PositionInsuranceSubMenuPatch : ModulePatch + { + protected override MethodBase GetTargetMethod() + { + return AccessTools.Method(typeof(InteractionButtonsContainer), nameof(InteractionButtonsContainer.SetSubInteractions)).MakeGenericMethod([typeof(InsuranceInteractions.EInsurers)]); + } + + // Existing logic tries to place it on the right, moving to the left if necessary. They didn't do it correctly, so it always goes on the left. + [PatchPostfix] + public static void Postfix(SimpleContextMenuButton ___simpleContextMenuButton_0, SimpleContextMenu ___simpleContextMenu_0) + { + PositionContextMenuFlyout(___simpleContextMenuButton_0, ___simpleContextMenu_0); + } + } + + private static void PositionContextMenuFlyout(SimpleContextMenuButton button, SimpleContextMenu flyoutMenu) + { + RectTransform buttonTransform = button.RectTransform(); + RectTransform flyoutTransform = flyoutMenu.RectTransform(); + + Vector2 leftPosition = flyoutTransform.position; // BSG's code will always put it on the left + leftPosition = new Vector2((float)Math.Round((double)leftPosition.x), (float)Math.Round((double)leftPosition.y)); + + Vector2 size = buttonTransform.rect.size; + Vector2 rightPosition = size - size * buttonTransform.pivot; + rightPosition = buttonTransform.TransformPoint(rightPosition); + + // Round vector the way that CorrectPosition does + rightPosition = new Vector2((float)Math.Round((double)rightPosition.x), (float)Math.Round((double)rightPosition.y)); + + if (Settings.ContextMenuOnRight.Value) + { + // Try on the right + flyoutTransform.position = rightPosition; + flyoutMenu.CorrectPosition(); + + // This means CorrectPosition() moved it + if (!(flyoutTransform.position.x - rightPosition.x).IsZero()) + { + flyoutTransform.position = leftPosition; + } + } + else + { + flyoutTransform.position = leftPosition; + flyoutMenu.CorrectPosition(); + + if (!(flyoutTransform.position.x - leftPosition.x).IsZero()) + { + flyoutTransform.position = rightPosition; + } + } + } + private static int GetPlayerRubles(ItemUiContext itemUiContext) { StashClass stash = itemUiContext.R().InventoryController.Inventory.Stash; diff --git a/R.cs b/R.cs index dcb7c67..0e83cf2 100644 --- a/R.cs +++ b/R.cs @@ -348,16 +348,22 @@ namespace UIFixes public static Type Type { get; private set; } private static FieldInfo ButtonTemplateField; private static FieldInfo ContainerField; + private static FieldInfo ContextMenuField; + private static FieldInfo ContextMenuButtonField; public static void InitTypes() { Type = typeof(EFT.UI.InteractionButtonsContainer); ButtonTemplateField = AccessTools.Field(Type, "_buttonTemplate"); ContainerField = AccessTools.Field(Type, "_buttonsContainer"); + ContextMenuField = AccessTools.Field(Type, "simpleContextMenu_0"); + ContextMenuButtonField = AccessTools.Field(Type, "simpleContextMenuButton_0"); } public SimpleContextMenuButton ButtonTemplate { get { return (SimpleContextMenuButton)ButtonTemplateField.GetValue(Value); } } public Transform Container { get { return (Transform)ContainerField.GetValue(Value); } } + public SimpleContextMenu ContextMenu { get { return (SimpleContextMenu)ContextMenuField.GetValue(Value); } } + public SimpleContextMenuButton ContextMenuButton { get { return (SimpleContextMenuButton)ContextMenuButtonField.GetValue(Value); } } } public class ContextMenuButton(object value) : Wrapper(value) diff --git a/Settings.cs b/Settings.cs index 28799b7..1d948ff 100644 --- a/Settings.cs +++ b/Settings.cs @@ -81,6 +81,7 @@ namespace UIFixes public static ConfigEntry MergeFIRAmmo { get; set; } public static ConfigEntry MergeFIROther { get; set; } public static ConfigEntry AutoOpenSortingTable { get; set; } + public static ConfigEntry ContextMenuOnRight { get; set; } public static ConfigEntry LoadMagPresetOnBullets { get; set; } // Advanced // Inspect Panels @@ -437,6 +438,15 @@ namespace UIFixes null, new ConfigurationManagerAttributes { }))); + configEntries.Add(ContextMenuOnRight = config.Bind( + InventorySection, + "Context Menu Flyout on Right", + true, + new ConfigDescription( + "Open context menu sub-menu to the right, as BSG intended but failed to do", + null, + new ConfigurationManagerAttributes { }))); + configEntries.Add(LoadMagPresetOnBullets = config.Bind( InventorySection, "Mag Presets Context Menu on Bullets",