Files
beyond/Assets/Plugins/Pixel Crushers/Common/Scripts/UI/UIButtonKeyTrigger.cs
2024-11-20 15:21:28 +01:00

100 lines
3.6 KiB
C#

// Copyright (c) Pixel Crushers. All rights reserved.
using System.Collections;
using UnityEngine;
using UnityEngine.EventSystems;
namespace PixelCrushers
{
/// <summary>
/// This script adds a key or button trigger to a Unity UI Selectable.
/// </summary>
[AddComponentMenu("")] // Use wrapper.
[RequireComponent(typeof(UnityEngine.UI.Selectable))]
public class UIButtonKeyTrigger : MonoBehaviour
{
[Tooltip("Trigger the selectable when this key is pressed.")]
public KeyCode key = KeyCode.None;
[Tooltip("Trigger the selectable when this input button is pressed.")]
public string buttonName = string.Empty;
[Tooltip("Trigger if any key, input button, or mouse button is pressed.")]
public bool anyKeyOrButton = false;
[Tooltip("Ignore trigger key/button if UI button is being clicked Event System's Submit input. Prevents unintentional double clicks.")]
public bool skipIfBeingClickedBySubmit = true;
[Tooltip("Visually show UI Button in pressed state when triggered.")]
public bool simulateButtonClick = true;
[Tooltip("Show pressed state for this duration in seconds.")]
public float simulateButtonDownDuration = 0.1f;
private UnityEngine.UI.Selectable m_selectable;
protected UnityEngine.UI.Selectable selectable { get { return m_selectable; } set { m_selectable = value; } }
/// <summary>
/// Set false to prevent all UIButtonKeyTrigger components from listening for input.
/// </summary>
public static bool monitorInput = true;
protected virtual void Awake()
{
m_selectable = GetComponent<UnityEngine.UI.Selectable>();
if (m_selectable == null) enabled = false;
}
protected void Update()
{
if (!monitorInput) return;
if (!(m_selectable.enabled && m_selectable.interactable && m_selectable.gameObject.activeInHierarchy)) return;
if (InputDeviceManager.IsKeyDown(key) ||
(!string.IsNullOrEmpty(buttonName) && InputDeviceManager.IsButtonDown(buttonName)) ||
(anyKeyOrButton && InputDeviceManager.IsAnyKeyDown()))
{
if (skipIfBeingClickedBySubmit && IsBeingClickedBySubmit()) return;
Click();
}
}
protected virtual bool IsBeingClickedBySubmit()
{
return EventSystem.current != null &&
EventSystem.current.currentSelectedGameObject == m_selectable.gameObject &&
InputDeviceManager.instance != null &&
InputDeviceManager.IsButtonDown(InputDeviceManager.instance.submitButton);
}
protected virtual void Click()
{
if (simulateButtonClick)
{
StartCoroutine(SimulateButtonClick());
}
else
{
ExecuteEvents.Execute(m_selectable.gameObject, new PointerEventData(EventSystem.current), ExecuteEvents.submitHandler);
}
}
protected IEnumerator SimulateButtonClick()
{
m_selectable.OnPointerDown(new PointerEventData(EventSystem.current));
var timeLeft = simulateButtonDownDuration;
while (timeLeft > 0)
{
yield return null;
timeLeft -= Time.unscaledDeltaTime;
}
m_selectable.OnPointerUp(new PointerEventData(EventSystem.current));
m_selectable.OnDeselect(null);
ExecuteEvents.Execute(m_selectable.gameObject, new PointerEventData(EventSystem.current), ExecuteEvents.submitHandler);
}
}
}