EscapeShooter/My project/Assets/Project Files/Modules/Control/Scripts/Gamepad/UIGamepadButton.cs

194 lines
6.3 KiB
C#

using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
#if MODULE_INPUT_SYSTEM
using UnityEngine.InputSystem;
#endif
namespace Watermelon
{
[RequireComponent(typeof(Button))]
public class UIGamepadButton : MonoBehaviour
{
[SerializeField] GamepadButtonType buttonType;
public GamepadButtonType ButtonType => buttonType;
[SerializeField] UIGamepadButtonTag buttonTag;
[Space]
[SerializeField] UIGamepadButtonTag buttonsToDisable;
[SerializeField] UIGamepadButtonTag buttonsToEnable;
[Space]
// Helps to manualy controll if the button is active even if it's tag is active
[SerializeField] bool isInFocus = true;
public bool IsInFocus { get => isInFocus; private set => isInFocus = value; }
[Space]
[SerializeField] Image gamepadButtonIcon;
private Button button;
private static UIGamepadButtonTag ActiveButtonTags { get; set; } = UIGamepadButtonTag.MainMenu;
private void Awake()
{
button = GetComponent<Button>();
//Initialising input for the first time. Later it will happen automatically, when the event is triggered
OnInputChanged(Control.InputType);
Control.OnInputChanged += OnInputChanged;
button.onClick.AddListener(OnButtonClick);
EventSystem.current.SetSelectedGameObject(null);
}
private void Update()
{
if (Control.InputType != InputType.Gamepad || (ActiveButtonTags & buttonTag) == 0 || !IsInFocus) return;
if (GamepadControl.WasButtonPressedThisFrame(buttonType))
{
// Changing tags next frame to avoid a situation where a ui button with the same gamepad button and a newly enabled tag triggers on the same frame as this button.
// Buttons have to still work with the game paused, thus uscaledTime is true
Tween.NextFrame(() => {
DisableTag(buttonsToDisable);
EnableTag(buttonsToEnable);
}, unscaledTime: true, framesOffset: 2);
button.ClickButton();
}
}
// Showing or hiding gamepad icon on a button if necessary
private void OnInputChanged(InputType type)
{
if (Control.InputType == InputType.Gamepad && IsInFocus)
{
gamepadButtonIcon.enabled = true;
if (Control.GamepadData != null) gamepadButtonIcon.sprite = Control.GamepadData.GetButtonIcon(buttonType);
}
else
{
gamepadButtonIcon.enabled = false;
}
}
// We still need to keep track of the active buttons in order to be able to swap the control from gamepad to keyboard and vice versa
private void OnButtonClick()
{
if(Control.InputType != InputType.Gamepad)
{
DisableTag(buttonsToDisable);
EnableTag(buttonsToEnable);
}
}
//Gives the ability to control the button visibility even if it's tag is active. Useful for lists, scroll views, etc.
public void SetFocus(bool focus)
{
IsInFocus = focus;
gamepadButtonIcon.enabled = focus && Control.InputType == InputType.Gamepad;
}
public static void EnableTag(UIGamepadButtonTag tagToEnable)
{
// Binary operation to add values to the flag
ActiveButtonTags |= tagToEnable;
}
public static void DisableTag(UIGamepadButtonTag tagToDisable)
{
// Binary operation to remove values from the flag
ActiveButtonTags &= ~tagToDisable;
}
public static void DisableAllTags()
{
ActiveButtonTags &= 0;
}
#region Highlight
private TweenCase highlightScaleCase;
private TweenCase returnCase;
private bool isHighlightActive;
public void StartHighlight()
{
if (isHighlightActive) return;
isHighlightActive = true;
// Killing return case just to be sure
returnCase.KillActive();
PingPongAnimation();
}
public void StopHighLight()
{
if (!isHighlightActive) return;
isHighlightActive = false;
// Definitely should kill highlight case
highlightScaleCase.KillActive();
returnCase = gamepadButtonIcon.DOScale(1f, 0.2f).SetEasing(Ease.Type.SineOut);
}
private void PingPongAnimation()
{
// Shouldn trigger stack overflown because of how tween works
highlightScaleCase = gamepadButtonIcon.DOPingPongScale(0.9f, 1.2f, 1, Ease.Type.SineInOut, Ease.Type.SineInOut).OnComplete(PingPongAnimation);
}
#endregion
#region Editor Tool
#if UNITY_EDITOR
[Button]
public void ShowGamepadButtonsInEditor()
{
if (Application.isPlaying) return;
// Enabling gamepad icon images in every UIGamepadButton on the scene.
// WILL NOT ENABLE THEM INSIDE PREFABS!
#if UNITY_6000_0_OR_NEWER
#pragma warning disable CS0618
FindObjectsByType<UIGamepadButton>(FindObjectsInactive.Include, FindObjectsSortMode.None).ForEach(button => button.gamepadButtonIcon.enabled = true);
#pragma warning restore CS0618
#else
FindObjectsOfType<UIGamepadButton>(true).ForEach(button => button.gamepadButtonIcon.enabled = true);
#endif
}
[Button]
public void HideGamepadButtonsInEditor()
{
if (Application.isPlaying) return;
// Disabling gamepad icon images in every UIGamepadButton on the scene.
// WILL NOT DISABLE THEM INSIDE PREFABS!
#if UNITY_6000_0_OR_NEWER
#pragma warning disable CS0618
FindObjectsByType<UIGamepadButton>(FindObjectsInactive.Include, FindObjectsSortMode.None).ForEach(button => button.gamepadButtonIcon.enabled = false);
#pragma warning restore CS0618
#else
FindObjectsOfType<UIGamepadButton>(true).ForEach(button => button.gamepadButtonIcon.enabled = false);
#endif
}
[Button]
public void PrintEnabledTags()
{
Debug.Log(ActiveButtonTags);
}
#endif
#endregion
}
}