Restructured for new direction.
This commit is contained in:
158
Assets/Scripts/UI/Menus/Components/UnderlineButton.cs
Normal file
158
Assets/Scripts/UI/Menus/Components/UnderlineButton.cs
Normal file
@@ -0,0 +1,158 @@
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityEngine.UI;
|
||||
using System;
|
||||
|
||||
namespace BriarQueen.UI.Menus.Components
|
||||
{
|
||||
[RequireComponent(typeof(Button))]
|
||||
public class UnderlineButton : MonoBehaviour,
|
||||
IPointerEnterHandler,
|
||||
IPointerExitHandler,
|
||||
IPointerClickHandler,
|
||||
ISelectHandler,
|
||||
IDeselectHandler
|
||||
{
|
||||
[Header("References")]
|
||||
[SerializeField] private TextMeshProUGUI _label;
|
||||
|
||||
private Button _button;
|
||||
private UnderlineButtonGroup _group;
|
||||
private bool _isHovered;
|
||||
|
||||
public event Action<UnderlineButton> SelectionRequested;
|
||||
public event Action<UnderlineButton> HoverEntered;
|
||||
public event Action<UnderlineButton> HoverExited;
|
||||
|
||||
public bool IsSelected { get; private set; }
|
||||
|
||||
// True when this button is registered with a group
|
||||
public bool IsGrouped => _group != null;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
_button = GetComponent<Button>();
|
||||
SetUnderline(false);
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
_isHovered = false;
|
||||
SetUnderline(false);
|
||||
}
|
||||
|
||||
// ── Group registration ────────────────────────────────────────
|
||||
|
||||
/// <summary>Called by UnderlineButtonGroup when this button is bound.</summary>
|
||||
internal void RegisterGroup(UnderlineButtonGroup group)
|
||||
{
|
||||
_group = group;
|
||||
}
|
||||
|
||||
/// <summary>Called by UnderlineButtonGroup when this button is unbound.</summary>
|
||||
internal void UnregisterGroup()
|
||||
{
|
||||
_group = null;
|
||||
}
|
||||
|
||||
// ── Pointer / Selection events ────────────────────────────────
|
||||
|
||||
public void OnPointerEnter(PointerEventData eventData)
|
||||
{
|
||||
if (_button != null && !_button.interactable) return;
|
||||
|
||||
_isHovered = true;
|
||||
|
||||
if (IsGrouped)
|
||||
HoverEntered?.Invoke(this);
|
||||
else
|
||||
RefreshStandaloneState();
|
||||
}
|
||||
|
||||
public void OnPointerExit(PointerEventData eventData)
|
||||
{
|
||||
_isHovered = false;
|
||||
|
||||
if (IsGrouped)
|
||||
HoverExited?.Invoke(this);
|
||||
else
|
||||
RefreshStandaloneState();
|
||||
}
|
||||
|
||||
public void OnPointerClick(PointerEventData eventData)
|
||||
{
|
||||
if (_button != null && !_button.interactable) return;
|
||||
SelectionRequested?.Invoke(this);
|
||||
}
|
||||
|
||||
public void OnSelect(BaseEventData eventData)
|
||||
{
|
||||
if (_button != null && !_button.interactable) return;
|
||||
|
||||
_isHovered = true;
|
||||
|
||||
if (IsGrouped)
|
||||
{
|
||||
HoverEntered?.Invoke(this);
|
||||
SelectionRequested?.Invoke(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
IsSelected = true;
|
||||
RefreshStandaloneState();
|
||||
}
|
||||
}
|
||||
|
||||
public void OnDeselect(BaseEventData eventData)
|
||||
{
|
||||
_isHovered = false;
|
||||
|
||||
if (IsGrouped)
|
||||
HoverExited?.Invoke(this);
|
||||
else
|
||||
{
|
||||
IsSelected = false;
|
||||
RefreshStandaloneState();
|
||||
}
|
||||
}
|
||||
|
||||
// ── Public API ────────────────────────────────────────────────
|
||||
|
||||
/// <summary>Called by the group to update logical selected state.</summary>
|
||||
public void SetSelectedState(bool selected)
|
||||
{
|
||||
IsSelected = selected;
|
||||
}
|
||||
|
||||
/// <summary>Called by the group to drive the underline visual directly.</summary>
|
||||
public void SetUnderline(bool underlined)
|
||||
{
|
||||
if (_label == null) return;
|
||||
|
||||
if (underlined)
|
||||
_label.fontStyle |= FontStyles.Underline;
|
||||
else
|
||||
_label.fontStyle &= ~FontStyles.Underline;
|
||||
}
|
||||
|
||||
public GameObject GetSelectableGameObject() => gameObject;
|
||||
|
||||
// ── Standalone logic ──────────────────────────────────────────
|
||||
|
||||
/// <summary>
|
||||
/// Used when not in a group — the button manages its own
|
||||
/// underline based on hover and selected state directly.
|
||||
/// </summary>
|
||||
private void RefreshStandaloneState()
|
||||
{
|
||||
if (_button != null && !_button.interactable)
|
||||
{
|
||||
SetUnderline(false);
|
||||
return;
|
||||
}
|
||||
|
||||
SetUnderline(IsSelected || _isHovered);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user