using System.Collections.Generic; using UnityEngine; using UnityEngine.Events; using UnityEngine.EventSystems; [DisallowMultipleComponent] public class UXGroup : UIBehaviour { [SerializeField] private bool m_AllowSwitchOff; [SerializeField] private List m_Buttons = new(); private UXButton _current; public UnityEvent onSelectedChanged = new(); public bool allowSwitchOff { get => m_AllowSwitchOff; set { m_AllowSwitchOff = value; ValidateGroup(); } } protected override void Awake() => ValidateGroup(); protected override void OnDestroy() { foreach (var btn in m_Buttons) if (btn) btn.Selected = false; m_Buttons.Clear(); base.OnDestroy(); } public void RegisterButton(UXButton button) { if (!button) return; if (m_Buttons.Contains(button)) return; m_Buttons.Add(button); if (button.Selected) { if (_current && _current != button) _current.Selected = false; _current = button; } ValidateGroup(); } public void UnregisterButton(UXButton button) { if (!button) return; m_Buttons.Remove(button); if (_current == button) _current = null; button.Selected = false; } internal void NotifyButtonClicked(UXButton button) { if (!button) return; if (button.Selected) { if (m_AllowSwitchOff) SetSelected(null); } else { SetSelected(button); } } private void SetSelected(UXButton target) { var previous = _current; _current = null; foreach (var btn in m_Buttons) { bool select = (btn == target); if (btn.Selected != select) btn.Selected = select; if (select) _current = btn; } if (previous != _current) onSelectedChanged?.Invoke(_current); } private void ValidateGroup() { if (_current != null && _current.Selected) return; if (!m_AllowSwitchOff && m_Buttons.Count > 0) SetSelected(m_Buttons[0]); } public bool AnyOtherSelected(UXButton exclude) { foreach (var btn in m_Buttons) if (btn != exclude && btn.Selected) return true; return false; } public void SelectNext() => SelectRelative(1); public void SelectPrevious() => SelectRelative(-1); private void SelectRelative(int dir) { if (m_Buttons.Count == 0) return; int start = _current ? m_Buttons.IndexOf(_current) : -1; int next = FindNextSelectable(start, dir); if (next >= 0) SetSelected(m_Buttons[next]); } private int FindNextSelectable(int startIndex, int dir) { if (m_Buttons.Count == 0) return -1; int count = m_Buttons.Count; int index = (startIndex + dir + count) % count; for (int i = 0; i < count; i++) { var btn = m_Buttons[index]; if (btn && btn.isActiveAndEnabled && btn.Interactable) return index; index = (index + dir + count) % count; } return -1; } }