multiselect + sort table polish, sort table keybinds

This commit is contained in:
Tyfon
2024-07-22 13:54:45 -07:00
parent 41699a422f
commit 0a656a2c4b
7 changed files with 190 additions and 54 deletions

View File

@@ -25,6 +25,8 @@ public class DrawMultiSelect : MonoBehaviour
private bool drawing; private bool drawing;
private bool secondary; private bool secondary;
private static Vector2 Deadzone = new(5f, 5f);
public void Start() public void Start()
{ {
selectTexture = new Texture2D(1, 1); selectTexture = new Texture2D(1, 1);
@@ -70,6 +72,21 @@ public class DrawMultiSelect : MonoBehaviour
selectOrigin = Input.mousePosition; selectOrigin = Input.mousePosition;
drawing = true; drawing = true;
secondary = shiftDown; secondary = shiftDown;
if (!secondary)
{
MultiSelect.Clear();
}
}
if (drawing && !Settings.SelectionBoxKey.Value.IsPressedIgnoreOthers())
{
drawing = false;
if (secondary)
{
MultiSelect.CombineSecondary();
secondary = false;
}
} }
if (drawing) if (drawing)
@@ -77,6 +94,10 @@ public class DrawMultiSelect : MonoBehaviour
selectEnd = Input.mousePosition; selectEnd = Input.mousePosition;
Rect selectRect = new(selectOrigin, selectEnd - selectOrigin); Rect selectRect = new(selectOrigin, selectEnd - selectOrigin);
if (Mathf.Abs(selectRect.size.x) < Deadzone.x && Mathf.Abs(selectRect.size.y) < Deadzone.y)
{
return;
}
// If not secondary, then we can kick out any non-rendered items, plus they won't be covered by the foreach below // If not secondary, then we can kick out any non-rendered items, plus they won't be covered by the foreach below
if (!secondary) if (!secondary)
@@ -119,16 +140,6 @@ public class DrawMultiSelect : MonoBehaviour
MultiSelect.Deselect(gridItemView, secondary); MultiSelect.Deselect(gridItemView, secondary);
} }
} }
if (drawing && !Settings.SelectionBoxKey.Value.IsPressedIgnoreOthers())
{
drawing = false;
if (secondary)
{
MultiSelect.CombineSecondary();
secondary = false;
}
}
} }
public void OnGUI() public void OnGUI()

View File

@@ -125,6 +125,8 @@ public class MultiSelect
public static void OnKillItemView(GridItemView itemView) public static void OnKillItemView(GridItemView itemView)
{ {
CombineSecondary();
MultiSelectItemContext itemContext = SelectedItems.FirstOrDefault(x => x.Value == itemView).Key; MultiSelectItemContext itemContext = SelectedItems.FirstOrDefault(x => x.Value == itemView).Key;
if (itemContext != null) if (itemContext != null)
{ {
@@ -140,6 +142,8 @@ public class MultiSelect
return; return;
} }
CombineSecondary();
MultiSelectItemContext itemContext = SelectedItems.FirstOrDefault(x => x.Key.Item == itemView.Item).Key; MultiSelectItemContext itemContext = SelectedItems.FirstOrDefault(x => x.Key.Item == itemView.Item).Key;
if (itemContext != null) if (itemContext != null)
{ {
@@ -158,6 +162,8 @@ public class MultiSelect
return; return;
} }
CombineSecondary();
MultiSelectItemContext oldItemContext = SelectedItems.FirstOrDefault(x => x.Key.Item == eventArgs.Item).Key; MultiSelectItemContext oldItemContext = SelectedItems.FirstOrDefault(x => x.Key.Item == eventArgs.Item).Key;
if (oldItemContext != null) if (oldItemContext != null)
{ {
@@ -221,7 +227,7 @@ public class MultiSelect
public static bool Active public static bool Active
{ {
get { return SelectedItems.Count > 0; } get { return SelectedItems.Count > 0 || SecondaryItems.Count > 0; }
} }
// Sort the items to prioritize the items that share a grid with the dragged item, prepend the dragContext as the first one // Sort the items to prioritize the items that share a grid with the dragged item, prepend the dragContext as the first one

View File

@@ -1,11 +1,11 @@
using EFT.InventoryLogic; using Comfort.Common;
using EFT.InventoryLogic;
using EFT.UI; using EFT.UI;
using EFT.UI.DragAndDrop; using EFT.UI.DragAndDrop;
using HarmonyLib; using HarmonyLib;
using SPT.Reflection.Patching; using SPT.Reflection.Patching;
using System.Reflection; using System.Reflection;
using TMPro; using TMPro;
using UnityEngine;
using UnityEngine.EventSystems; using UnityEngine.EventSystems;
namespace UIFixes; namespace UIFixes;
@@ -98,6 +98,11 @@ public static class ContextMenuShortcutPatches
TryInteraction(__instance, itemContext, EItemInfoButton.LinkedSearch); TryInteraction(__instance, itemContext, EItemInfoButton.LinkedSearch);
} }
if (Settings.SortingTableKeyBind.Value.IsDown())
{
MoveToFromSortingTable(itemContext, __instance);
}
Interactions = null; Interactions = null;
} }
@@ -109,6 +114,36 @@ public static class ContextMenuShortcutPatches
Interactions.ExecuteInteraction(fallbackInteraction.Value); Interactions.ExecuteInteraction(fallbackInteraction.Value);
} }
} }
private static void MoveToFromSortingTable(ItemContextAbstractClass itemContext, ItemUiContext itemUiContext)
{
Item item = itemContext.Item;
if (item.Owner is not InventoryControllerClass controller)
{
return;
}
SortingTableClass sortingTable = controller.Inventory.SortingTable;
bool isInSortingTable = sortingTable != null && item.Parent.Container.ParentItem == sortingTable;
var operation = isInSortingTable ? itemUiContext.QuickFindAppropriatePlace(itemContext, controller, false, true, true) : itemUiContext.QuickMoveToSortingTable(item, true);
if (operation.Succeeded && controller.CanExecute(operation.Value))
{
if (operation.Value is IDestroyResult destroyResult && destroyResult.ItemsDestroyRequired)
{
NotificationManagerClass.DisplayWarningNotification(new DestroyError(item, destroyResult.ItemsToDestroy).GetLocalizedDescription());
return;
}
controller.RunNetworkTransaction(operation.Value, null);
if (itemUiContext.Tooltip != null)
{
itemUiContext.Tooltip.Close();
}
Singleton<GUISounds>.Instance.PlayItemSound(item.ItemSound, EInventorySoundType.pickup, false);
}
}
} }
// HideoutItemViews don't register themselves with ItemUiContext for some reason // HideoutItemViews don't register themselves with ItemUiContext for some reason

View File

@@ -148,7 +148,7 @@ public static class MultiSelectPatches
} }
[PatchPostfix] [PatchPostfix]
public static void Postfix(ItemView __instance, PointerEventData eventData) public static void Postfix(ItemView __instance, PointerEventData eventData, TraderControllerClass ___ItemController)
{ {
if (!MultiSelect.Enabled || __instance is RagfairNewOfferItemView || __instance is InsuranceItemView) if (!MultiSelect.Enabled || __instance is RagfairNewOfferItemView || __instance is InsuranceItemView)
{ {
@@ -159,14 +159,32 @@ public static class MultiSelectPatches
bool shiftDown = Input.GetKey(KeyCode.LeftShift) && !Input.GetKey(KeyCode.RightShift); bool shiftDown = Input.GetKey(KeyCode.LeftShift) && !Input.GetKey(KeyCode.RightShift);
bool altDown = Input.GetKey(KeyCode.LeftAlt) && !Input.GetKey(KeyCode.RightAlt); bool altDown = Input.GetKey(KeyCode.LeftAlt) && !Input.GetKey(KeyCode.RightAlt);
if (Settings.EnableMultiClick.Value && __instance is GridItemView gridItemView && eventData.button == PointerEventData.InputButton.Left && shiftDown && !ctrlDown && !altDown) // If sorting table is open and default shift-click behavior is enabled, don't multiselect
bool couldBeSortingTableMove = false;
if (Settings.DefaultSortingTableBind.Value &&
shiftDown &&
eventData.button == PointerEventData.InputButton.Left &&
___ItemController is InventoryControllerClass inventoryController)
{
SortingTableClass sortingTable = inventoryController.Inventory.SortingTable;
if (sortingTable != null && sortingTable.IsVisible)
{
couldBeSortingTableMove = true;
}
}
if (Settings.EnableMultiClick.Value &&
!couldBeSortingTableMove &&
__instance is GridItemView gridItemView &&
eventData.button == PointerEventData.InputButton.Left &&
shiftDown && !ctrlDown && !altDown)
{ {
MultiSelect.Toggle(gridItemView); MultiSelect.Toggle(gridItemView);
return; return;
} }
// Mainly this tests for when selection box is rebound to another mouse button, to enable secondary selection // Mainly this tests for when selection box is rebound to another mouse button, to enable secondary selection
if (shiftDown && Settings.SelectionBoxKey.Value.IsDownIgnoreOthers()) if (!couldBeSortingTableMove && shiftDown && Settings.SelectionBoxKey.Value.IsDownIgnoreOthers())
{ {
return; return;
} }
@@ -209,9 +227,14 @@ public static class MultiSelectPatches
return false; return false;
} }
if (shiftDown) if (shiftDown && !ctrlDown && !altDown)
{ {
// Nothing to do, mousedown handled it. if (Settings.DefaultSortingTableBind.Value)
{
QuickMove(__instance, ___ItemUiContext, ___ItemController, true);
return false;
}
return true; return true;
} }
@@ -220,15 +243,17 @@ public static class MultiSelectPatches
return true; return true;
} }
private static void QuickMove(GridItemView gridItemView, ItemUiContext itemUiContext, TraderControllerClass itemController) private static void QuickMove(GridItemView gridItemView, ItemUiContext itemUiContext, TraderControllerClass itemController, bool moveToSortingTable = false)
{ {
bool succeeded = true; bool succeeded = true;
DisableMerge = true; DisableMerge = true;
IgnoreItemParent = true; IgnoreItemParent = true;
Stack<ItemOperation> operations = new(); Stack<ItemOperation> operations = new();
foreach (DragItemContext selectedItemContext in MultiSelect.SortedItemContexts()) foreach (var selectedItemContext in MultiSelect.SortedItemContexts())
{ {
ItemOperation operation = itemUiContext.QuickFindAppropriatePlace(selectedItemContext, itemController, false /*forceStash*/, false /*showWarnings*/, false /*simulate*/); ItemOperation operation = moveToSortingTable ?
itemUiContext.QuickMoveToSortingTable(selectedItemContext.Item, false /*simulate*/) :
itemUiContext.QuickFindAppropriatePlace(selectedItemContext, itemController, false /*forceStash*/, false /*showWarnings*/, false /*simulate*/);
if (operation.Succeeded && itemController.CanExecute(operation.Value)) if (operation.Succeeded && itemController.CanExecute(operation.Value))
{ {
operations.Push(operation); operations.Push(operation);

View File

@@ -1,17 +1,26 @@
using Comfort.Common; using Comfort.Common;
using EFT.UI; using EFT.UI;
using EFT.UI.DragAndDrop;
using HarmonyLib; using HarmonyLib;
using SPT.Reflection.Patching; using SPT.Reflection.Patching;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using UnityEngine; using UnityEngine;
using UnityEngine.EventSystems;
namespace UIFixes; namespace UIFixes;
public class OpenSortingTablePatch : ModulePatch public static class OpenSortingTablePatches
{ {
private static readonly EItemUiContextType[] AllowedScreens = [EItemUiContextType.InventoryScreen, EItemUiContextType.ScavengerInventoryScreen]; public static void Enable()
{
new AutoOpenPatch().Enable();
new DefaultBindPatch().Enable();
}
public class AutoOpenPatch : ModulePatch
{
private static readonly EItemUiContextType[] AllowedScreens = [EItemUiContextType.InventoryScreen, EItemUiContextType.ScavengerInventoryScreen];
protected override MethodBase GetTargetMethod() protected override MethodBase GetTargetMethod()
{ {
@@ -28,7 +37,8 @@ public class OpenSortingTablePatch : ModulePatch
return false; return false;
} }
if (!Settings.AutoOpenSortingTable.Value || !AllowedScreens.Contains(__instance.ContextType)) // Allowed screens only, and auto-open is enabled or the custom bind is active
if (!AllowedScreens.Contains(__instance.ContextType) || (!Settings.AutoOpenSortingTable.Value && !Settings.SortingTableKeyBind.Value.IsDown()))
{ {
return true; return true;
} }
@@ -56,4 +66,33 @@ public class OpenSortingTablePatch : ModulePatch
return true; return true;
} }
}
public class DefaultBindPatch : ModulePatch
{
protected override MethodBase GetTargetMethod()
{
return AccessTools.Method(typeof(ItemView), nameof(ItemView.OnClick));
}
[PatchPrefix]
public static bool Prefix(PointerEventData.InputButton button, bool doubleClick)
{
if (Settings.DefaultSortingTableBind.Value)
{
return true;
}
bool ctrlDown = Input.GetKey(KeyCode.LeftControl) || Input.GetKey(KeyCode.RightControl);
bool altDown = Input.GetKey(KeyCode.LeftAlt) || Input.GetKey(KeyCode.RightAlt);
bool shiftDown = Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift);
if (button == PointerEventData.InputButton.Left && !doubleClick && !ctrlDown && !altDown && shiftDown)
{
return false;
}
return true;
}
}
} }

View File

@@ -47,7 +47,7 @@ public class Plugin : BaseUnityPlugin
new LoadMagPresetsPatch().Enable(); new LoadMagPresetsPatch().Enable();
KeepWindowsOnScreenPatches.Enable(); KeepWindowsOnScreenPatches.Enable();
ContextMenuShortcutPatches.Enable(); ContextMenuShortcutPatches.Enable();
new OpenSortingTablePatch().Enable(); OpenSortingTablePatches.Enable();
LoadAmmoInRaidPatches.Enable(); LoadAmmoInRaidPatches.Enable();
MultiSelectPatches.Enable(); MultiSelectPatches.Enable();
new FixUnloadLastBulletPatch().Enable(); new FixUnloadLastBulletPatch().Enable();

View File

@@ -70,6 +70,7 @@ internal class Settings
public static ConfigEntry<KeyboardShortcut> UnpackKeyBind { get; set; } public static ConfigEntry<KeyboardShortcut> UnpackKeyBind { get; set; }
public static ConfigEntry<KeyboardShortcut> FilterByKeyBind { get; set; } public static ConfigEntry<KeyboardShortcut> FilterByKeyBind { get; set; }
public static ConfigEntry<KeyboardShortcut> LinkedSearchKeyBind { get; set; } public static ConfigEntry<KeyboardShortcut> LinkedSearchKeyBind { get; set; }
public static ConfigEntry<KeyboardShortcut> SortingTableKeyBind { get; set; }
public static ConfigEntry<bool> UseRaidMouseScrollMulti { get; set; } // Advanced public static ConfigEntry<bool> UseRaidMouseScrollMulti { get; set; } // Advanced
public static ConfigEntry<int> MouseScrollMultiInRaid { get; set; } // Advanced public static ConfigEntry<int> MouseScrollMultiInRaid { get; set; } // Advanced
public static ConfigEntry<bool> ItemContextBlocksTextInputs { get; set; } // Advanced public static ConfigEntry<bool> ItemContextBlocksTextInputs { get; set; } // Advanced
@@ -93,6 +94,7 @@ internal class Settings
public static ConfigEntry<bool> MergeFIRAmmo { get; set; } public static ConfigEntry<bool> MergeFIRAmmo { get; set; }
public static ConfigEntry<bool> MergeFIROther { get; set; } public static ConfigEntry<bool> MergeFIROther { get; set; }
public static ConfigEntry<bool> AutoOpenSortingTable { get; set; } public static ConfigEntry<bool> AutoOpenSortingTable { get; set; }
public static ConfigEntry<bool> DefaultSortingTableBind { get; set; } // Advanced
public static ConfigEntry<bool> ContextMenuOnRight { get; set; } public static ConfigEntry<bool> ContextMenuOnRight { get; set; }
public static ConfigEntry<bool> ShowGPCurrency { get; set; } public static ConfigEntry<bool> ShowGPCurrency { get; set; }
public static ConfigEntry<bool> ShowOutOfStockCheckbox { get; set; } public static ConfigEntry<bool> ShowOutOfStockCheckbox { get; set; }
@@ -330,6 +332,15 @@ internal class Settings
null, null,
new ConfigurationManagerAttributes { }))); new ConfigurationManagerAttributes { })));
configEntries.Add(SortingTableKeyBind = config.Bind(
InputSection,
"Transfer to/from Sorting Table",
new KeyboardShortcut(KeyCode.None),
new ConfigDescription(
"Keybind to transfer items to and from the sorting table. Will auto-open sorting table if necessary.",
null,
new ConfigurationManagerAttributes { })));
configEntries.Add(ItemContextBlocksTextInputs = config.Bind( configEntries.Add(ItemContextBlocksTextInputs = config.Bind(
InputSection, InputSection,
"Block Text Inputs on Item Mouseover", "Block Text Inputs on Item Mouseover",
@@ -502,6 +513,15 @@ internal class Settings
null, null,
new ConfigurationManagerAttributes { }))); new ConfigurationManagerAttributes { })));
configEntries.Add(DefaultSortingTableBind = config.Bind(
InventorySection,
"Shift-Click to Sorting Table",
true,
new ConfigDescription(
"This setting lets you enable/disable the default Tarkov behavior of shift-clicking items to transfer them to the sorting table.",
null,
new ConfigurationManagerAttributes { IsAdvanced = true })));
configEntries.Add(ContextMenuOnRight = config.Bind( configEntries.Add(ContextMenuOnRight = config.Bind(
InventorySection, InventorySection,
"Context Menu Flyout on Right", "Context Menu Flyout on Right",