multiselect + sort table polish, sort table keybinds
This commit is contained in:
@@ -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()
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
20
Settings.cs
20
Settings.cs
@@ -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",
|
||||||
|
|||||||
Reference in New Issue
Block a user