OldBlueWater/BlueWater/Assets/Doozy/Runtime/UIManager/Components/UIButton.cs

204 lines
7.3 KiB
C#

// Copyright (c) 2015 - 2023 Doozy Entertainment. All Rights Reserved.
// This code can only be used under the standard Unity Asset Store End User License Agreement
// A Copy of the EULA APPENDIX 1 is available at http://unity3d.com/company/legal/as_terms
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Doozy.Runtime.Common.Attributes;
using Doozy.Runtime.Common.Utils;
using Doozy.Runtime.Signals;
using UnityEngine;
using UnityEngine.EventSystems;
// ReSharper disable MemberCanBePrivate.Global
namespace Doozy.Runtime.UIManager.Components
{
/// <summary>
/// Button component based on UISelectable with category/name id identifier.
/// </summary>
[RequireComponent(typeof(RectTransform))]
[AddComponentMenu("Doozy/UI/Components/UI Button")]
[SelectionBase]
public partial class UIButton : UISelectable, IPointerClickHandler, ISubmitHandler
{
#if UNITY_EDITOR
[UnityEditor.MenuItem("GameObject/Doozy/UI/Components/UIButton", false, 8)]
private static void CreateComponent(UnityEditor.MenuCommand menuCommand)
{
GameObjectUtils.AddToScene<UIButton>("UIButton", false, true);
}
#endif
/// <summary> UIButtons database </summary>
public static HashSet<UIButton> database { get; private set; } = new HashSet<UIButton>();
[ExecuteOnReload]
private static void OnReload()
{
database ??= new HashSet<UIButton>();
}
[ClearOnReload]
private static SignalStream s_stream;
/// <summary> UIButton signal stream </summary>
public static SignalStream stream => s_stream ??= SignalsService.GetStream(k_StreamCategory, nameof(UIButton));
/// <summary> All buttons that are active and enabled </summary>
public static IEnumerable<UIButton> availableButtons => database.Where(item => item.isActiveAndEnabled);
/// <summary> TRUE is this selectable is selected by EventSystem.current, FALSE otherwise </summary>
public bool isSelected => EventSystem.current.currentSelectedGameObject == gameObject;
/// <summary> Type of selectable </summary>
public override SelectableType selectableType => SelectableType.Button;
/// <summary> UIButton identifier </summary>
public UIButtonId Id;
protected UIButton()
{
Id = new UIButtonId();
}
protected override void Awake()
{
database.Add(this);
base.Awake();
}
protected override void OnEnable()
{
if (!Application.isPlaying) return;
StopCooldown();
database.Remove(null);
base.OnEnable();
}
protected override void OnDisable()
{
StopCooldown();
database.Remove(null);
base.OnDisable();
}
protected override void OnDestroy()
{
database.Remove(null);
database.Remove(this);
base.OnDestroy();
}
/// <summary> Called when on pointer click event is sent by the IPointerClickHandler </summary>
/// <param name="eventData"> Pointer event data </param>
public virtual void OnPointerClick(PointerEventData eventData)
{
if (inCooldown) return;
if (eventData.button != PointerEventData.InputButton.Left)
return;
Click();
}
/// <summary> Called when on submit event is sent by the ISubmitHandler </summary>
/// <param name="eventData"> Event data </param>
public void OnSubmit(BaseEventData eventData)
{
if (inCooldown) return;
if (!IsActive() || !IsInteractable())
return;
DoStateTransition(SelectionState.Pressed, false);
Click();
if (!inputSettings.submitTriggersPointerClick) return;
behaviours.GetBehaviour(UIBehaviour.Name.PointerClick)?.Execute();
behaviours.GetBehaviour(UIBehaviour.Name.PointerLeftClick)?.Execute();
}
private IEnumerator RefreshSelectionState()
{
const float selectionDelay = 0.1f;
float elapsedTime = 0f;
while (elapsedTime < selectionDelay)
{
elapsedTime += Time.unscaledDeltaTime;
yield return null;
}
DoStateTransition(currentSelectionState, false);
}
/// <summary> Click the button and play the pressed state animations </summary>
public void ClickWithAnimation() =>
OnSubmit(null);
/// <summary> Click the button (no animation) </summary>
public void Click() =>
Click(false);
/// <summary>
/// Click the button (no animation)
/// </summary>
/// <param name="forced"> Ignore active and interactable states </param>
public void Click(bool forced)
{
if (inCooldown) return;
if (!forced && (!IsActive() || !IsInteractable()))
return;
if (isActiveAndEnabled)
{
StartCoroutine(RefreshSelectionState());
}
UISystemProfilerApi.AddMarker($"{nameof(UIButton)}.{nameof(Click)}", this);
stream.SendSignal(new UIButtonSignalData(Id.Category, Id.Name, ButtonTrigger.Click, playerIndex, this));
if (isActiveAndEnabled)
{
StartCooldown();
}
}
#region Static Methods
/// <summary> Get all the registered buttons with the given category and name </summary>
/// <param name="category"> UIButton category </param>
/// <param name="name"> UIButton name (from the given category) </param>
public static IEnumerable<UIButton> GetButtons(string category, string name) =>
database.Where(button => button.Id.Category.Equals(category)).Where(button => button.Id.Name.Equals(name));
/// <summary> Get all the registered buttons with the given category </summary>
/// <param name="category"> UIButton category </param>
public static IEnumerable<UIButton> GetAllButtonsInCategory(string category) =>
database.Where(button => button.Id.Category.Equals(category));
/// <summary> Get all the buttons that are active and enabled (all the visible/available buttons) </summary>
public static IEnumerable<UIButton> GetAvailableButtons() =>
database.Where(button => button.isActiveAndEnabled);
/// <summary> Get the selected button (if a button is not selected, this method returns null) </summary>
public static UIButton GetSelectedButton() =>
database.FirstOrDefault(button => button.isSelected);
/// <summary> Select the button with the given category and name (if it is active and enabled) </summary>
/// <param name="category"> UIButton category </param>
/// <param name="name"> UIButton name (from the given category) </param>
public static bool SelectButton(string category, string name)
{
UIButton button = availableButtons.FirstOrDefault(b => b.Id.Category.Equals(category) & b.Id.Name.Equals(name));
if (button == null) return false;
button.Select();
return true;
}
#endregion
}
}