Files
A-Fairytale-Gone-Bad-Briar-…/Assets/Scripts/UI/Menus/Components/AnimatedSelectionButtonGroup.cs

144 lines
4.7 KiB
C#

using System;
using UnityEngine;
using UnityEngine.EventSystems;
namespace BriarQueen.UI.Menus.Components
{
public class AnimatedSelectionButtonGroup : MonoBehaviour
{
[Header("Buttons")]
[SerializeField]
private AnimatedSelectionButton[] _buttons = Array.Empty<AnimatedSelectionButton>();
[SerializeField]
private int _defaultSelectedIndex;
[Header("Selection")]
[SerializeField]
private bool _selectDefaultOnEnable = true;
[SerializeField]
private bool _syncEventSystemSelection = true;
public AnimatedSelectionButton Current { get; private set; }
public AnimatedSelectionButton CurrentHovered { get; private set; }
private void Reset()
{
_buttons = GetComponentsInChildren<AnimatedSelectionButton>(true);
}
private void OnEnable()
{
BindButtons();
if (_selectDefaultOnEnable)
SelectIndex(_defaultSelectedIndex, true);
}
private void OnDisable()
{
UnbindButtons();
CurrentHovered = null;
}
public void SelectIndex(int index, bool instant = false)
{
if (_buttons == null || _buttons.Length == 0) return;
SelectButton(_buttons[Mathf.Clamp(index, 0, _buttons.Length - 1)], instant);
}
public void SelectButton(AnimatedSelectionButton selectedButton, bool instant = false)
{
if (selectedButton == null) return;
if (Current == selectedButton && !instant) return;
Current = selectedButton;
RefreshAllButtonStates(instant);
SyncEventSystemSelection(selectedButton);
}
// ── Internal ──────────────────────────────────────────────────
private void RefreshAllButtonStates(bool instant = false)
{
if (_buttons == null) return;
foreach (var button in _buttons)
{
if (button == null) continue;
// A button shows its highlight if it is selected OR it is the
// hovered button AND no other button is being hovered that would
// take visual priority. Selected button highlight only shows when
// nothing is hovered, or when it itself is hovered.
var isSelected = button == Current;
var isHovered = button == CurrentHovered;
var showHighlight = isSelected
? CurrentHovered == null || isHovered // selected: show unless something else is hovered
: isHovered; // unselected: show only if hovered
button.SetHighlight(showHighlight, instant);
button.SetSelectedState(isSelected);
}
}
private void HandleSelectionRequested(AnimatedSelectionButton selectedButton)
{
SelectButton(selectedButton);
}
private void HandleHoverEntered(AnimatedSelectionButton button)
{
CurrentHovered = button;
RefreshAllButtonStates();
}
private void HandleHoverExited(AnimatedSelectionButton button)
{
if (CurrentHovered == button)
CurrentHovered = null;
RefreshAllButtonStates();
}
private void BindButtons()
{
if (_buttons == null) return;
foreach (var button in _buttons)
{
if (button == null) continue;
button.SelectionRequested += HandleSelectionRequested;
button.HoverEntered += HandleHoverEntered;
button.HoverExited += HandleHoverExited;
}
}
private void UnbindButtons()
{
if (_buttons == null) return;
foreach (var button in _buttons)
{
if (button == null) continue;
button.SelectionRequested -= HandleSelectionRequested;
button.HoverEntered -= HandleHoverEntered;
button.HoverExited -= HandleHoverExited;
}
}
private void SyncEventSystemSelection(AnimatedSelectionButton selectedButton)
{
if (!_syncEventSystemSelection || selectedButton.Button == null || EventSystem.current == null)
return;
var selectedGameObject = selectedButton.Button.gameObject;
if (EventSystem.current.currentSelectedGameObject == selectedGameObject) return;
EventSystem.current.SetSelectedGameObject(selectedGameObject);
}
}
}