multiselect: only check for clickables if left mouse; allow shift-drag to draw by disabling item drag

This commit is contained in:
Tyfon
2024-07-22 01:58:38 -07:00
parent 30ad64ec40
commit 41699a422f
3 changed files with 77 additions and 29 deletions

View File

@@ -1,4 +1,5 @@
using Comfort.Common;
using BepInEx.Configuration;
using Comfort.Common;
using EFT.UI;
using EFT.UI.DragAndDrop;
using System;
@@ -56,37 +57,19 @@ public class DrawMultiSelect : MonoBehaviour
return;
}
// checking ItemUiContext is a quick and easy way to know the mouse is over an item
if (Input.GetKeyDown(Settings.SelectionBoxKey.Value.MainKey) && ItemUiContext.Instance.R().ItemContext == null)
if (Settings.SelectionBoxKey.Value.IsDownIgnoreOthers())
{
PointerEventData eventData = new(EventSystem.current)
bool shiftDown = Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift);
// Only need to check we aren't over draggables/clickables if the multiselect key is left mouse
if (Settings.SelectionBoxKey.Value.MainKey == KeyCode.Mouse0 && !shiftDown && !MouseIsOverClickable())
{
position = Input.mousePosition
};
List<RaycastResult> results = [];
localRaycaster.Raycast(eventData, results);
preloaderRaycaster.Raycast(eventData, results);
foreach (GameObject gameObject in results.Select(r => r.gameObject))
{
var draggables = gameObject.GetComponents<MonoBehaviour>()
.Where(c => c is IDragHandler || c is IBeginDragHandler || c is TextMeshProUGUI) // tmp_inputfield is draggable, but textmesh isn't so explicitly include
.Where(c => c is not ScrollRectNoDrag) // this disables scrolling, it doesn't add it
.Where(c => c.name != "Inner"); // there's a random DragTrigger sitting in ItemInfoWindows
var clickables = gameObject.GetComponents<MonoBehaviour>()
.Where(c => c is IPointerClickHandler || c is IPointerDownHandler || c is IPointerUpHandler);
if (draggables.Any() || clickables.Any())
{
return;
}
return;
}
selectOrigin = Input.mousePosition;
drawing = true;
secondary = Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift);
secondary = shiftDown;
}
if (drawing)
@@ -137,7 +120,7 @@ public class DrawMultiSelect : MonoBehaviour
}
}
if (drawing && !Input.GetKey(Settings.SelectionBoxKey.Value.MainKey))
if (drawing && !Settings.SelectionBoxKey.Value.IsPressedIgnoreOthers())
{
drawing = false;
if (secondary)
@@ -171,6 +154,42 @@ public class DrawMultiSelect : MonoBehaviour
}
}
private bool MouseIsOverClickable()
{
// checking ItemUiContext is a quick and easy way to know the mouse is over an item
if (ItemUiContext.Instance.R().ItemContext != null)
{
return false;
}
PointerEventData eventData = new(EventSystem.current)
{
position = Input.mousePosition
};
List<RaycastResult> results = [];
localRaycaster.Raycast(eventData, results);
preloaderRaycaster.Raycast(eventData, results);
foreach (GameObject gameObject in results.Select(r => r.gameObject))
{
var draggables = gameObject.GetComponents<MonoBehaviour>()
.Where(c => c is IDragHandler || c is IBeginDragHandler || c is TextMeshProUGUI) // tmp_inputfield is draggable, but textmesh isn't so explicitly include
.Where(c => c is not ScrollRectNoDrag) // this disables scrolling, it doesn't add it
.Where(c => c.name != "Inner"); // there's a random DragTrigger sitting in ItemInfoWindows
var clickables = gameObject.GetComponents<MonoBehaviour>()
.Where(c => c is IPointerClickHandler || c is IPointerDownHandler || c is IPointerUpHandler);
if (draggables.Any() || clickables.Any())
{
return false;
}
}
return true;
}
private bool IsOnTop(Rect itemRect, Transform itemTransform, GraphicRaycaster raycaster)
{
// Otherwise, ensure it's not overlapped by window UI

View File

@@ -24,7 +24,7 @@ public static class MultiSelectPatches
// Used to prevent infinite recursion of CanAccept/AcceptItem
private static bool InPatch = false;
// If the CanAccept method should render highlights
// Keep track of preview images when dragging
private static readonly List<Image> Previews = [];
// Point that various QuickFindPlace overrides should start at
@@ -165,6 +165,12 @@ public static class MultiSelectPatches
return;
}
// Mainly this tests for when selection box is rebound to another mouse button, to enable secondary selection
if (shiftDown && Settings.SelectionBoxKey.Value.IsDownIgnoreOthers())
{
return;
}
if (__instance is not GridItemView gridItemView2 || !MultiSelect.IsSelected(gridItemView2))
{
MultiSelect.Clear();
@@ -400,6 +406,13 @@ public static class MultiSelectPatches
return AccessTools.Method(typeof(ItemView), nameof(ItemView.OnBeginDrag));
}
[PatchPrefix]
public static bool Prefix()
{
// Disable drag if shift is down
return !Input.GetKey(KeyCode.LeftShift) && !Input.GetKey(KeyCode.RightShift);
}
[PatchPostfix]
public static void Postfix(ItemView __instance)
{

View File

@@ -2,6 +2,7 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using UnityEngine;
namespace UIFixes;
@@ -833,10 +834,25 @@ public static class SettingExtensions
configEntry.SettingChanged += (_, _) => onChange(configEntry.Value);
}
public static void Bind<T>(this ConfigEntry<T> configEntry, Action<T> onChange)
{
configEntry.Subscribe(onChange);
onChange(configEntry.Value);
}
// KeyboardShortcut methods return false if any other key is down
public static bool IsDownIgnoreOthers(this KeyboardShortcut shortcut)
{
return Input.GetKeyDown(shortcut.MainKey) && shortcut.Modifiers.All(Input.GetKey);
}
public static bool IsPressedIgnoreOthers(this KeyboardShortcut shortcut)
{
return Input.GetKey(shortcut.MainKey) && shortcut.Modifiers.All(Input.GetKey);
}
public static bool IsUpIgnoreOthers(this KeyboardShortcut shortcut)
{
return Input.GetKeyUp(shortcut.MainKey) && shortcut.Modifiers.All(Input.GetKey);
}
}