com.alicizax.unity.ui.exten.../Runtime/UXComponent/Group/UXGroup.cs

139 lines
3.4 KiB
C#
Raw Normal View History

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