144 lines
4.7 KiB
C#
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);
|
|
}
|
|
}
|
|
} |