ctrl-click working

This commit is contained in:
Tyfon
2024-06-19 18:13:40 -07:00
parent 7fc1c0068b
commit 58b35d32fc
4 changed files with 144 additions and 33 deletions

View File

@@ -1,4 +1,5 @@
using EFT.UI; using EFT.InventoryLogic;
using EFT.UI;
using EFT.UI.DragAndDrop; using EFT.UI.DragAndDrop;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
@@ -235,6 +236,18 @@ namespace UIFixes
public class MultiSelectItemContext(ItemContextAbstractClass itemContext, ItemRotation rotation) : ItemContextClass(itemContext, rotation) public class MultiSelectItemContext(ItemContextAbstractClass itemContext, ItemRotation rotation) : ItemContextClass(itemContext, rotation)
{ {
public override bool SplitAvailable => false; public override bool SplitAvailable => false;
// used by ItemUiContext.QuickFindAppropriatePlace, the one that picks a container, i.e. ctrl-click
// ItemContextClass (drag) defaults to None, but we want what the underlying item allows
public override bool CanQuickMoveTo(ETargetContainer targetContainer)
{
if (this.GClass2813_0 != null)
{
return this.GClass2813_0.CanQuickMoveTo(targetContainer);
}
return base.CanQuickMoveTo(targetContainer);
}
} }
public static class MultiSelectExtensions public static class MultiSelectExtensions

View File

@@ -36,7 +36,7 @@ namespace UIFixes
foreach (ItemContextClass itemContext in MultiSelect.ItemContexts) foreach (ItemContextClass itemContext in MultiSelect.ItemContexts)
{ {
builder.Append(itemContext.Item.ToString()); builder.AppendFormat("x{0} {1}", itemContext.Item.StackObjectsCount, itemContext.Item.ToString());
builder.AppendLine(); builder.AppendLine();
} }

View File

@@ -95,7 +95,10 @@ namespace UIFixes
.Where(i => insurance.ItemTypeAvailableForInsurance(i) && !insurance.InsuredItems.Contains(i)) .Where(i => insurance.ItemTypeAvailableForInsurance(i) && !insurance.InsuredItems.Contains(i))
.Count(); .Count();
____text.text += " (x" + count + ")"; if (count > 0)
{
____text.text += " (x" + count + ")";
}
} }
} }
} }

View File

@@ -1,5 +1,6 @@
using Aki.Reflection.Patching; using Aki.Reflection.Patching;
using Comfort.Common; using Comfort.Common;
using EFT.Communications;
using EFT.InventoryLogic; using EFT.InventoryLogic;
using EFT.UI; using EFT.UI;
using EFT.UI.DragAndDrop; using EFT.UI.DragAndDrop;
@@ -30,6 +31,7 @@ namespace UIFixes
// Prevents QuickFind from attempting a merge // Prevents QuickFind from attempting a merge
private static bool DisableMerge = false; private static bool DisableMerge = false;
private static bool IgnoreItemParent = false;
// Specific type of TaskSerializer because Unity can't understand generics // Specific type of TaskSerializer because Unity can't understand generics
public class ItemContextTaskSerializer : TaskSerializer<ItemContextClass> { } public class ItemContextTaskSerializer : TaskSerializer<ItemContextClass> { }
@@ -39,7 +41,7 @@ namespace UIFixes
new InitializeCommonUIPatch().Enable(); new InitializeCommonUIPatch().Enable();
new InitializeMenuUIPatch().Enable(); new InitializeMenuUIPatch().Enable();
new SelectOnMouseDownPatch().Enable(); new SelectOnMouseDownPatch().Enable();
new DeselectOnGridItemViewClickPatch().Enable(); new ItemViewClickPatch().Enable();
new DeselectOnTradingItemViewClickPatch().Enable(); new DeselectOnTradingItemViewClickPatch().Enable();
new HandleItemViewInitPatch().Enable(); new HandleItemViewInitPatch().Enable();
new HandleItemViewKillPatch().Enable(); new HandleItemViewKillPatch().Enable();
@@ -144,26 +146,101 @@ namespace UIFixes
} }
} }
public class DeselectOnGridItemViewClickPatch : ModulePatch public class ItemViewClickPatch : ModulePatch
{ {
protected override MethodBase GetTargetMethod() protected override MethodBase GetTargetMethod()
{ {
return AccessTools.Method(typeof(GridItemView), nameof(GridItemView.OnClick)); return AccessTools.Method(typeof(GridItemView), nameof(GridItemView.OnClick));
} }
[PatchPostfix] [PatchPrefix]
public static void Postfix(PointerEventData.InputButton button) public static bool Prefix(GridItemView __instance, PointerEventData.InputButton button, ItemUiContext ___ItemUiContext, TraderControllerClass ___ItemController)
{ {
if (!MultiSelect.Active) if (!MultiSelect.Active || button != PointerEventData.InputButton.Left || ___ItemUiContext == null || !__instance.IsSearched)
{ {
return; return true;
} }
// Mousedown handles most things, just need to handle the non-shift click of a selected item bool ctrlDown = Input.GetKey(KeyCode.LeftControl) && !Input.GetKey(KeyCode.RightControl);
if (button == PointerEventData.InputButton.Left && !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);
if (ctrlDown && !shiftDown && !altDown)
{ {
MultiSelect.Clear(); bool succeeded = true;
DisableMerge = true;
IgnoreItemParent = true;
Stack<GStruct413> operations = new();
foreach (ItemContextClass selectedItemContext in SortSelectedContexts(MultiSelect.ItemContexts, null, false))
{
GStruct413 operation = ___ItemUiContext.QuickFindAppropriatePlace(selectedItemContext, ___ItemController, false /*forceStash*/, false /*showWarnings*/, false /*simulate*/);
if (operation.Succeeded && ___ItemController.CanExecute(operation.Value))
{
operations.Push(operation);
}
else
{
succeeded = false;
break;
}
IDestroyResult destroyResult;
if ((destroyResult = operation.Value as IDestroyResult) != null && destroyResult.ItemsDestroyRequired)
{
NotificationManagerClass.DisplayWarningNotification(new GClass3320(__instance.Item, destroyResult.ItemsToDestroy).GetLocalizedDescription(), ENotificationDurationType.Default);
succeeded = false;
break;
}
}
DisableMerge = false;
IgnoreItemParent = true;
if (succeeded)
{
string itemSound = __instance.Item.ItemSound;
// We didn't simulate because we needed each result to depend on the last, but we have to undo before we actually do :S
Stack<GStruct413> networkOps = new();
while (operations.Any())
{
GStruct413 operation = operations.Pop();
operation.Value.RollBack();
networkOps.Push(operation);
}
while (networkOps.Any())
{
___ItemController.RunNetworkTransaction(networkOps.Pop().Value, null);
}
if (___ItemUiContext.Tooltip != null)
{
___ItemUiContext.Tooltip.Close();
}
Singleton<GUISounds>.Instance.PlayItemSound(itemSound, EInventorySoundType.pickup, false);
}
else
{
while (operations.Any())
{
operations.Pop().Value?.RollBack();
}
}
return false;
} }
if (shiftDown)
{
// Nothing to do, mousedown handled it.
return true;
}
// if neither ctrl or shift is down, this is a click to clear
MultiSelect.Clear();
return true;
} }
} }
@@ -300,6 +377,13 @@ namespace UIFixes
return false; return false;
} }
// BSG BUG - if the targetItem is a magazine, and the multiselect is bullets, it will NOT be able to rollback correctly!!
// To prevent inventory corruption, reject magazines outright. Sorry, no multiple bullet stacks into one magazine
if (targetItemContext != null && targetItemContext.Item is MagazineClass)
{
return false;
}
Item item = itemContext.Item; Item item = itemContext.Item;
ItemAddress itemAddress = itemContext.ItemAddress; ItemAddress itemAddress = itemContext.ItemAddress;
if (itemAddress == null) if (itemAddress == null)
@@ -421,23 +505,8 @@ namespace UIFixes
// Need to fully implement AcceptItem for the sorting table - normally that just uses null targetItemContext // Need to fully implement AcceptItem for the sorting table - normally that just uses null targetItemContext
if (InPatch && targetItemContext?.Item is SortingTableClass) if (InPatch && targetItemContext?.Item is SortingTableClass)
{ {
MoveToSortingTable(__instance, itemContext, ___itemUiContext_0);
__result = Task.CompletedTask; __result = Task.CompletedTask;
var itemController = __instance.R().TraderController;
GStruct413 operation = ___itemUiContext_0.QuickMoveToSortingTable(itemContext.Item, true);
if (operation.Failed || !itemController.CanExecute(operation.Value))
{
return false;
}
itemController.RunNetworkTransaction(operation.Value, null);
if (___itemUiContext_0.Tooltip != null)
{
___itemUiContext_0.Tooltip.Close();
}
Singleton<GUISounds>.Instance.PlayItemSound(itemContext.Item.ItemSound, EInventorySoundType.pickup, false);
return false; return false;
} }
@@ -480,6 +549,26 @@ namespace UIFixes
return false; return false;
} }
private static void MoveToSortingTable(GridView gridView, ItemContextClass itemContext, ItemUiContext itemUiContext)
{
var itemController = gridView.R().TraderController;
GStruct413 operation = itemUiContext.QuickMoveToSortingTable(itemContext.Item, true);
if (operation.Failed || !itemController.CanExecute(operation.Value))
{
return;
}
itemController.RunNetworkTransaction(operation.Value, null);
if (itemUiContext.Tooltip != null)
{
itemUiContext.Tooltip.Close();
}
Singleton<GUISounds>.Instance.PlayItemSound(itemContext.Item.ItemSound, EInventorySoundType.pickup, false);
}
} }
public class AdjustQuickFindFlagsPatch : ModulePatch public class AdjustQuickFindFlagsPatch : ModulePatch
@@ -508,6 +597,11 @@ namespace UIFixes
{ {
order &= ~InteractionsHandlerClass.EMoveItemOrder.TryMerge; order &= ~InteractionsHandlerClass.EMoveItemOrder.TryMerge;
} }
if (IgnoreItemParent)
{
order |= InteractionsHandlerClass.EMoveItemOrder.IgnoreItemParent;
}
} }
} }
@@ -548,19 +642,20 @@ namespace UIFixes
} }
// 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
// Can pass no itemContext, and it just sorts items by their grid order
private static IEnumerable<ItemContextClass> SortSelectedContexts( private static IEnumerable<ItemContextClass> SortSelectedContexts(
IEnumerable<ItemContextClass> selectedContexts, ItemContextClass itemContext, bool prepend = true) IEnumerable<ItemContextClass> selectedContexts, ItemContextClass itemContext, bool prepend = true)
{ {
static int gridOrder(LocationInGrid loc, StashGridClass grid) => grid.GridWidth.Value * loc.y + loc.x; static int gridOrder(LocationInGrid loc, StashGridClass grid) => grid.GridWidth.Value * loc.y + loc.x;
var result = selectedContexts var result = selectedContexts
.Where(ic => ic.Item != itemContext.Item) .Where(ic => itemContext == null || ic.Item != itemContext.Item)
.OrderByDescending(ic => ic.ItemAddress is GClass2769) .OrderByDescending(ic => ic.ItemAddress is GClass2769)
.ThenByDescending(ic => itemContext.ItemAddress is GClass2769 originalDraggedAddress && ic.ItemAddress is GClass2769 selectedGridAddress && selectedGridAddress.Grid == originalDraggedAddress.Grid) .ThenByDescending(ic => itemContext != null && itemContext.ItemAddress is GClass2769 originalDraggedAddress && ic.ItemAddress is GClass2769 selectedGridAddress && selectedGridAddress.Grid == originalDraggedAddress.Grid)
.ThenByDescending(ic => ic.ItemAddress is GClass2769 selectedGridAddress ? selectedGridAddress.Grid.Id : null) .ThenByDescending(ic => ic.ItemAddress is GClass2769 selectedGridAddress ? selectedGridAddress.Grid.Id : null)
.ThenBy(ic => ic.ItemAddress is GClass2769 selectedGridAddress ? gridOrder(selectedGridAddress.LocationInGrid, selectedGridAddress.Grid) : 0); .ThenBy(ic => ic.ItemAddress is GClass2769 selectedGridAddress ? gridOrder(selectedGridAddress.LocationInGrid, selectedGridAddress.Grid) : 0);
return prepend ? result.Prepend(itemContext) : result; return itemContext != null && prepend ? result.Prepend(itemContext) : result;
} }
public class GridViewDisableHighlightPatch : ModulePatch public class GridViewDisableHighlightPatch : ModulePatch
@@ -620,7 +715,7 @@ namespace UIFixes
} }
Stack<GStruct413> operations = new(); Stack<GStruct413> operations = new();
foreach (ItemContextClass itemContext in MultiSelect.ItemContexts) foreach (ItemContextClass itemContext in SortSelectedContexts(MultiSelect.ItemContexts, null, false))
{ {
__result = itemContext.CanAccept(__instance.Slot, __instance.ParentItemContext, ___InventoryController, out operation, false /* simulate */); __result = itemContext.CanAccept(__instance.Slot, __instance.ParentItemContext, ___InventoryController, out operation, false /* simulate */);
if (operation.Succeeded) if (operation.Succeeded)
@@ -667,7 +762,7 @@ namespace UIFixes
InPatch = true; InPatch = true;
var serializer = __instance.GetOrAddComponent<ItemContextTaskSerializer>(); var serializer = __instance.GetOrAddComponent<ItemContextTaskSerializer>();
__result = serializer.Initialize(MultiSelect.ItemContexts, itemContext => __instance.AcceptItem(itemContext, targetItemContext)); __result = serializer.Initialize(SortSelectedContexts(MultiSelect.ItemContexts, null, false), itemContext => __instance.AcceptItem(itemContext, targetItemContext));
__result.ContinueWith(_ => { InPatch = false; }); __result.ContinueWith(_ => { InPatch = false; });