Initial multiselect checkpoint, still long way to go
This commit is contained in:
87
DrawMultiSelect.cs
Normal file
87
DrawMultiSelect.cs
Normal file
@@ -0,0 +1,87 @@
|
||||
using EFT.UI;
|
||||
using EFT.UI.DragAndDrop;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UIFixes
|
||||
{
|
||||
public class DrawMultiSelect : MonoBehaviour
|
||||
{
|
||||
Texture2D selectTexture;
|
||||
|
||||
Vector3 selectOrigin;
|
||||
Vector3 selectEnd;
|
||||
|
||||
bool drawing;
|
||||
|
||||
public void Start()
|
||||
{
|
||||
selectTexture = new Texture2D(1, 1);
|
||||
selectTexture.SetPixel(0, 0, new Color(1f, 1f, 1f, 0.8f));
|
||||
selectTexture.Apply();
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
if (Input.GetKeyDown(KeyCode.Mouse0) && ItemUiContext.Instance.R().ItemContext == null)
|
||||
{
|
||||
selectOrigin = Input.mousePosition;
|
||||
drawing = true;
|
||||
}
|
||||
|
||||
if (drawing)
|
||||
{
|
||||
selectEnd = Input.mousePosition;
|
||||
|
||||
Rect selectRect = new(selectOrigin.x, selectOrigin.y, selectEnd.x - selectOrigin.x, selectEnd.y - selectOrigin.y);
|
||||
foreach (GridItemView gridItemView in GetComponentsInChildren<GridItemView>())
|
||||
{
|
||||
RectTransform itemTransform = gridItemView.GetComponent<RectTransform>();
|
||||
Rect screenRect = new((Vector2)itemTransform.position + itemTransform.rect.position, itemTransform.rect.size);
|
||||
|
||||
if (selectRect.Overlaps(screenRect, true))
|
||||
{
|
||||
MultiSelect.Select(gridItemView);
|
||||
}
|
||||
else
|
||||
{
|
||||
MultiSelect.Deselect(gridItemView);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (drawing && !Input.GetKey(KeyCode.Mouse0))
|
||||
{
|
||||
drawing = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void OnGUI()
|
||||
{
|
||||
if (drawing)
|
||||
{
|
||||
// Invert Y because GUI has upper-left origin
|
||||
Rect area = new(selectOrigin.x, Screen.height - selectOrigin.y, selectEnd.x - selectOrigin.x, selectOrigin.y - selectEnd.y);
|
||||
|
||||
Rect lineArea = area;
|
||||
lineArea.height = 1; // Top
|
||||
GUI.DrawTexture(lineArea, selectTexture);
|
||||
|
||||
lineArea.y = area.yMax - 1; // Bottom
|
||||
GUI.DrawTexture(lineArea, selectTexture);
|
||||
|
||||
lineArea = area;
|
||||
lineArea.width = 1; // Left
|
||||
GUI.DrawTexture(lineArea, selectTexture);
|
||||
|
||||
lineArea.x = area.xMax - 1; // Right
|
||||
GUI.DrawTexture(lineArea, selectTexture);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
172
MultiSelect.cs
Normal file
172
MultiSelect.cs
Normal file
@@ -0,0 +1,172 @@
|
||||
using EFT.InventoryLogic;
|
||||
using EFT.UI.DragAndDrop;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UIFixes
|
||||
{
|
||||
public class MultiSelect
|
||||
{
|
||||
private static GameObject SelectedMarkTemplate;
|
||||
private static GameObject SelectedBackgroundTemplate;
|
||||
|
||||
private static readonly HashSet<GridItemView> SelectedItemViews = [];
|
||||
private static readonly List<ItemContextClass> SelectedItemContexts = [];
|
||||
|
||||
public static void Initialize()
|
||||
{
|
||||
// Grab the selection objects from ragfair as templates
|
||||
RagfairNewOfferItemView ragfairNewOfferItemView = ItemViewFactory.CreateFromPool<RagfairNewOfferItemView>("ragfair_layout");
|
||||
SelectedMarkTemplate = UnityEngine.Object.Instantiate(ragfairNewOfferItemView.R().SelectedMark, null, false);
|
||||
SelectedBackgroundTemplate = UnityEngine.Object.Instantiate(ragfairNewOfferItemView.R().SelectedBackground, null, false);
|
||||
ragfairNewOfferItemView.ReturnToPool();
|
||||
}
|
||||
|
||||
public static void Toggle(GridItemView itemView)
|
||||
{
|
||||
if (!itemView.IsInteractable)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (SelectedItemViews.Contains(itemView))
|
||||
{
|
||||
Deselect(itemView);
|
||||
}
|
||||
else
|
||||
{
|
||||
Select(itemView);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Clear()
|
||||
{
|
||||
// ToList() because we'll be modifying the collection
|
||||
foreach (GridItemView itemView in SelectedItemViews.ToList())
|
||||
{
|
||||
Deselect(itemView);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Select(GridItemView itemView)
|
||||
{
|
||||
if (itemView.IsInteractable && SelectedItemViews.Add(itemView))
|
||||
{
|
||||
ShowSelection(itemView);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Deselect(GridItemView itemView)
|
||||
{
|
||||
if (SelectedItemViews.Remove(itemView))
|
||||
{
|
||||
HideSelection(itemView);
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<ItemView> ItemViews
|
||||
{
|
||||
get { return SelectedItemViews; }
|
||||
}
|
||||
|
||||
public static IEnumerable<ItemContextClass> ItemContexts
|
||||
{
|
||||
get { return SelectedItemContexts; }
|
||||
}
|
||||
|
||||
public static int Count
|
||||
{
|
||||
get { return SelectedItemViews.Count; }
|
||||
}
|
||||
|
||||
public static bool Contains(GridItemView itemView)
|
||||
{
|
||||
return SelectedItemViews.Contains(itemView);
|
||||
}
|
||||
|
||||
public static bool Active
|
||||
{
|
||||
get { return SelectedItemViews.Any(); }
|
||||
}
|
||||
|
||||
public static bool IsSelected(GridItemView itemView)
|
||||
{
|
||||
return SelectedItemViews.Contains(itemView);
|
||||
}
|
||||
|
||||
public static void BeginDrag()
|
||||
{
|
||||
foreach (ItemView itemView in SelectedItemViews)
|
||||
{
|
||||
SelectedItemContexts.Add(new ItemContextClass(itemView.ItemContext, itemView.ItemRotation));
|
||||
}
|
||||
}
|
||||
|
||||
public static void EndDrag()
|
||||
{
|
||||
foreach(ItemContextClass itemContext in SelectedItemContexts)
|
||||
{
|
||||
itemContext.Dispose();
|
||||
}
|
||||
|
||||
SelectedItemContexts.Clear();
|
||||
}
|
||||
|
||||
public static void ShowDragCount(DraggedItemView draggedItemView)
|
||||
{
|
||||
if (Count > 1)
|
||||
{
|
||||
GameObject textOverlay = new("MultiSelectText", [typeof(RectTransform), typeof(TextMeshProUGUI)]);
|
||||
textOverlay.transform.parent = draggedItemView.transform;
|
||||
textOverlay.transform.SetAsLastSibling();
|
||||
textOverlay.SetActive(true);
|
||||
|
||||
RectTransform overlayRect = textOverlay.GetComponent<RectTransform>();
|
||||
overlayRect.anchorMin = Vector2.zero;
|
||||
overlayRect.anchorMax = Vector2.one;
|
||||
overlayRect.anchoredPosition = new Vector2(0.5f, 0.5f);
|
||||
|
||||
TextMeshProUGUI text = textOverlay.GetComponent<TextMeshProUGUI>();
|
||||
text.text = MultiSelect.Count.ToString();
|
||||
text.fontSize = 36;
|
||||
text.alignment = TextAlignmentOptions.Baseline;
|
||||
}
|
||||
}
|
||||
|
||||
private static void ShowSelection(GridItemView itemView)
|
||||
{
|
||||
GameObject selectedMark = itemView.transform.Find("SelectedMark")?.gameObject;
|
||||
if (selectedMark == null)
|
||||
{
|
||||
selectedMark = UnityEngine.Object.Instantiate(SelectedMarkTemplate, itemView.transform, false);
|
||||
selectedMark.name = "SelectedMark";
|
||||
}
|
||||
|
||||
selectedMark.SetActive(true);
|
||||
|
||||
GameObject selectedBackground = itemView.transform.Find("SelectedBackground")?.gameObject;
|
||||
if (selectedBackground == null)
|
||||
{
|
||||
selectedBackground = UnityEngine.Object.Instantiate(SelectedBackgroundTemplate, itemView.transform, false);
|
||||
selectedBackground.transform.SetAsFirstSibling();
|
||||
selectedBackground.name = "SelectedBackground";
|
||||
}
|
||||
|
||||
selectedBackground.SetActive(true);
|
||||
}
|
||||
|
||||
private static void HideSelection(GridItemView itemView)
|
||||
{
|
||||
GameObject selectedMark = itemView.transform.Find("SelectedMark")?.gameObject;
|
||||
GameObject selectedBackground = itemView.transform.Find("SelectedBackground")?.gameObject;
|
||||
|
||||
selectedMark?.SetActive(false);
|
||||
selectedBackground?.SetActive(false);
|
||||
}
|
||||
}
|
||||
}
|
313
Patches/MultiSelectPatches.cs
Normal file
313
Patches/MultiSelectPatches.cs
Normal file
@@ -0,0 +1,313 @@
|
||||
using Aki.Reflection.Patching;
|
||||
using Comfort.Common;
|
||||
using EFT.UI;
|
||||
using EFT.UI.DragAndDrop;
|
||||
using HarmonyLib;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
|
||||
namespace UIFixes
|
||||
{
|
||||
public static class MultiSelectPatches
|
||||
{
|
||||
// Used to prevent infinite recursion of CanAccept/AcceptItem
|
||||
private static bool InPatch = false;
|
||||
|
||||
public static void Enable()
|
||||
{
|
||||
new InitializePatch().Enable();
|
||||
new SelectPatch().Enable();
|
||||
new DeselectOnOtherMouseDown().Enable();
|
||||
new DeselectOnMovePatch().Enable();
|
||||
new BeginDragPatch().Enable();
|
||||
new EndDragPatch().Enable();
|
||||
|
||||
new GridViewCanAcceptPatch().Enable();
|
||||
new SlotViewCanAcceptPatch().Enable();
|
||||
new SlotViewAcceptItemPatch().Enable();
|
||||
}
|
||||
|
||||
public class InitializePatch : ModulePatch
|
||||
{
|
||||
protected override MethodBase GetTargetMethod()
|
||||
{
|
||||
return AccessTools.Method(typeof(CommonUI), nameof(CommonUI.Awake));
|
||||
}
|
||||
|
||||
[PatchPostfix]
|
||||
public static void Postfix(CommonUI __instance)
|
||||
{
|
||||
MultiSelect.Initialize();
|
||||
|
||||
__instance.InventoryScreen.GetOrAddComponent<DrawMultiSelect>();
|
||||
//__instance.TransferItemsInRaidScreen.GetOrAddComponent<DrawMultiSelect>();
|
||||
//__instance.TransferItemsScreen.GetOrAddComponent<DrawMultiSelect>();
|
||||
}
|
||||
}
|
||||
|
||||
public class SelectPatch : ModulePatch
|
||||
{
|
||||
protected override MethodBase GetTargetMethod()
|
||||
{
|
||||
return AccessTools.Method(typeof(GridItemView), nameof(GridItemView.OnClick));
|
||||
}
|
||||
|
||||
[PatchPostfix]
|
||||
public static void Postfix(GridItemView __instance, PointerEventData.InputButton button)
|
||||
{
|
||||
if (button == PointerEventData.InputButton.Left && (Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift)))
|
||||
{
|
||||
MultiSelect.Toggle(__instance);
|
||||
return;
|
||||
}
|
||||
|
||||
if (button == PointerEventData.InputButton.Left)// && !MultiSelect.IsSelected(__instance))
|
||||
{
|
||||
MultiSelect.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class DeselectOnOtherMouseDown : ModulePatch
|
||||
{
|
||||
protected override MethodBase GetTargetMethod()
|
||||
{
|
||||
return AccessTools.Method(typeof(ItemView), nameof(ItemView.OnPointerDown));
|
||||
}
|
||||
|
||||
[PatchPostfix]
|
||||
public static void Postfix(ItemView __instance, PointerEventData eventData)
|
||||
{
|
||||
if (eventData.button == PointerEventData.InputButton.Left && (Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift)))
|
||||
{
|
||||
// This will be shift-click, let it cook
|
||||
return;
|
||||
}
|
||||
|
||||
if (__instance is not GridItemView gridItemView || !MultiSelect.IsSelected(gridItemView))
|
||||
{
|
||||
MultiSelect.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class DeselectOnMovePatch : ModulePatch
|
||||
{
|
||||
protected override MethodBase GetTargetMethod()
|
||||
{
|
||||
return AccessTools.Method(typeof(ItemView), nameof(ItemView.Kill));
|
||||
}
|
||||
|
||||
[PatchPostfix]
|
||||
public static void Postfix(ItemView __instance)
|
||||
{
|
||||
if (__instance is GridItemView gridItemView)
|
||||
{
|
||||
MultiSelect.Deselect(gridItemView);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class BeginDragPatch : ModulePatch
|
||||
{
|
||||
protected override MethodBase GetTargetMethod()
|
||||
{
|
||||
return AccessTools.Method(typeof(ItemView), nameof(ItemView.OnBeginDrag));
|
||||
}
|
||||
|
||||
[PatchPrefix]
|
||||
public static void Prefix()
|
||||
{
|
||||
MultiSelect.BeginDrag();
|
||||
}
|
||||
|
||||
[PatchPostfix]
|
||||
public static void Postfix(ItemView __instance)
|
||||
{
|
||||
MultiSelect.ShowDragCount(__instance.DraggedItemView);
|
||||
}
|
||||
}
|
||||
|
||||
public class EndDragPatch : ModulePatch
|
||||
{
|
||||
protected override MethodBase GetTargetMethod()
|
||||
{
|
||||
return AccessTools.Method(typeof(ItemView), nameof(ItemView.OnEndDrag));
|
||||
}
|
||||
|
||||
[PatchPostfix]
|
||||
public static void Postfix()
|
||||
{
|
||||
MultiSelect.EndDrag();
|
||||
}
|
||||
}
|
||||
|
||||
public class GridViewCanAcceptPatch : ModulePatch
|
||||
{
|
||||
protected override MethodBase GetTargetMethod()
|
||||
{
|
||||
return AccessTools.Method(typeof(GridView), nameof(GridView.CanAccept));
|
||||
}
|
||||
|
||||
[PatchPrefix]
|
||||
public static bool Prefix(GridView __instance, ItemContextAbstractClass targetItemContext, ref GStruct413 operation, ref bool __result)
|
||||
{
|
||||
if (InPatch || !MultiSelect.Active)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
operation = default;
|
||||
__result = false;
|
||||
return false;
|
||||
|
||||
/* InPatch = true;
|
||||
foreach (ItemContextClass itemContext in MultiSelect.ItemContexts)
|
||||
{
|
||||
__result = __instance.CanAccept(itemContext, targetItemContext, out operation);
|
||||
if (!__result)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
InPatch = false;
|
||||
return false;*/
|
||||
}
|
||||
}
|
||||
|
||||
public class SlotViewCanAcceptPatch : ModulePatch
|
||||
{
|
||||
protected override MethodBase GetTargetMethod()
|
||||
{
|
||||
return AccessTools.Method(typeof(SlotView), nameof(SlotView.CanAccept));
|
||||
}
|
||||
|
||||
[PatchPrefix]
|
||||
public static bool Prefix(SlotView __instance, ItemContextAbstractClass targetItemContext, ref GStruct413 operation, ref bool __result)
|
||||
{
|
||||
if (InPatch || !MultiSelect.Active)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
operation = default;
|
||||
__result = false;
|
||||
|
||||
InPatch = true;
|
||||
foreach (ItemContextClass itemContext in MultiSelect.ItemContexts)
|
||||
{
|
||||
__result = __instance.CanAccept(itemContext, targetItemContext, out operation);
|
||||
if (!__result)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
InPatch = false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public class SlotViewAcceptItemPatch : ModulePatch
|
||||
{
|
||||
protected override MethodBase GetTargetMethod()
|
||||
{
|
||||
return AccessTools.Method(typeof(SlotView), nameof(SlotView.AcceptItem));
|
||||
}
|
||||
|
||||
[PatchPrefix]
|
||||
public static bool Prefix(SlotView __instance, ItemContextAbstractClass targetItemContext, ref Task __result)
|
||||
{
|
||||
if (InPatch || !MultiSelect.Active)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
InPatch = true;
|
||||
/* __result = Task.CompletedTask;
|
||||
foreach (ItemContextClass itemContext in MultiSelect.ItemContexts.ToList())
|
||||
{
|
||||
__result = __result.ContinueWith(_ => __instance.AcceptItem(itemContext, targetItemContext));
|
||||
}*/
|
||||
|
||||
var serializer = __instance.GetOrAddComponent<TaskSerializer>();
|
||||
__result = serializer.Initialize(MultiSelect.ItemContexts, itemContext => __instance.AcceptItem(itemContext, targetItemContext));
|
||||
|
||||
__result.ContinueWith(_ => { InPatch = false; });
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public class TaskSerializer : MonoBehaviour
|
||||
{
|
||||
private Func<ItemContextClass, Task> func;
|
||||
private Queue<ItemContextClass> itemContexts;
|
||||
private Task currentTask;
|
||||
private TaskCompletionSource totalTask;
|
||||
|
||||
public Task Initialize(IEnumerable<ItemContextClass> itemContexts, Func<ItemContextClass, Task> func)
|
||||
{
|
||||
this.itemContexts = new(itemContexts);
|
||||
this.func = func;
|
||||
|
||||
currentTask = Task.CompletedTask;
|
||||
Update();
|
||||
|
||||
totalTask = new TaskCompletionSource();
|
||||
return totalTask.Task;
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
if (!currentTask.IsCompleted)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (itemContexts.Any())
|
||||
{
|
||||
currentTask = func(itemContexts.Dequeue());
|
||||
}
|
||||
else
|
||||
{
|
||||
totalTask.Complete();
|
||||
func = null;
|
||||
Destroy(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*public class GridViewAcceptItemPatch : ModulePatch
|
||||
{
|
||||
protected override MethodBase GetTargetMethod()
|
||||
{
|
||||
return AccessTools.Method(typeof(GridView), nameof(GridView.AcceptItem));
|
||||
}
|
||||
|
||||
[PatchPrefix]
|
||||
public static async bool Prefix(GridView __instance, ItemContextAbstractClass targetItemContext, ref Task __result)
|
||||
{
|
||||
if (InPatch || !MultiSelectContext.Instance.Any())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
InPatch = true;
|
||||
foreach (ItemContextClass itemContext in MultiSelectContext.Instance.SelectedDragContexts)
|
||||
{
|
||||
await __instance.AcceptItem(itemContext, targetItemContext);
|
||||
}
|
||||
|
||||
InPatch = false;
|
||||
return false;
|
||||
}
|
||||
}*/
|
||||
}
|
||||
}
|
@@ -49,6 +49,7 @@ namespace UIFixes
|
||||
ContextMenuShortcutPatches.Enable();
|
||||
new OpenSortingTablePatch().Enable();
|
||||
LoadAmmoInRaidPatches.Enable();
|
||||
MultiSelectPatches.Enable();
|
||||
}
|
||||
|
||||
public static bool InRaid()
|
||||
|
19
R.cs
19
R.cs
@@ -58,6 +58,7 @@ namespace UIFixes
|
||||
GridSortPanel.InitTypes();
|
||||
RepairStrategy.InitTypes();
|
||||
ContextMenuHelper.InitTypes();
|
||||
RagfairNewOfferItemView.InitTypes();
|
||||
}
|
||||
|
||||
public abstract class Wrapper(object value)
|
||||
@@ -674,6 +675,23 @@ namespace UIFixes
|
||||
|
||||
public InsuranceCompanyClass InsuranceCompany { get { return (InsuranceCompanyClass)InsuranceCompanyField.GetValue(Value); } }
|
||||
}
|
||||
|
||||
public class RagfairNewOfferItemView(object value) : Wrapper(value)
|
||||
{
|
||||
public static Type Type { get; private set; }
|
||||
private static FieldInfo SelectedMarkField;
|
||||
private static FieldInfo SelectedBackgroundField;
|
||||
|
||||
public static void InitTypes()
|
||||
{
|
||||
Type = typeof(EFT.UI.DragAndDrop.RagfairNewOfferItemView);
|
||||
SelectedMarkField = AccessTools.Field(Type, "_selectedMark");
|
||||
SelectedBackgroundField = AccessTools.Field(Type, "_selectedBackground");
|
||||
}
|
||||
|
||||
public GameObject SelectedMark { get { return (GameObject)SelectedMarkField.GetValue(Value); } }
|
||||
public GameObject SelectedBackground { get { return (GameObject)SelectedBackgroundField.GetValue(Value); } }
|
||||
}
|
||||
}
|
||||
|
||||
public static class RExtentensions
|
||||
@@ -700,5 +718,6 @@ namespace UIFixes
|
||||
public static R.GridSortPanel R(this GridSortPanel value) => new(value);
|
||||
public static R.RepairerParametersPanel R(this RepairerParametersPanel value) => new(value);
|
||||
public static R.MessageWindow R(this MessageWindow value) => new(value);
|
||||
public static R.RagfairNewOfferItemView R(this RagfairNewOfferItemView value) => new(value);
|
||||
}
|
||||
}
|
||||
|
@@ -57,6 +57,9 @@
|
||||
<Reference Include="UnityEngine.CoreModule">
|
||||
<HintPath>$(PathToSPT)\EscapeFromTarkov_Data\Managed\UnityEngine.CoreModule.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.IMGUIModule">
|
||||
<HintPath>$(PathToSPT)\EscapeFromTarkov_Data\Managed\UnityEngine.IMGUIModule.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.InputLegacyModule">
|
||||
<HintPath>$(PathToSPT)\EscapeFromTarkov_Data\Managed\UnityEngine.InputLegacyModule.dll</HintPath>
|
||||
</Reference>
|
||||
|
Reference in New Issue
Block a user