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

272 lines
7.3 KiB
C#
Raw Normal View History

using System;
2025-10-13 20:20:01 +08:00
using System.Collections.Generic;
using System.Linq;
2025-04-11 17:26:28 +08:00
using UnityEngine.EventSystems;
using UnityEngine;
2025-10-13 20:20:01 +08:00
2025-12-09 20:30:11 +08:00
namespace UnityEngine.UI
2025-04-11 17:26:28 +08:00
{
[AddComponentMenu("UI/UXGroup", 31)]
2025-12-09 20:30:11 +08:00
[DisallowMultipleComponent]
public class UXGroup : UIBehaviour
{
[SerializeField] private bool m_AllowSwitchOff = false;
2025-04-11 17:26:28 +08:00
2025-12-09 20:30:11 +08:00
public bool allowSwitchOff
2025-04-11 17:26:28 +08:00
{
get { return m_AllowSwitchOff; }
set { m_AllowSwitchOff = value; }
2025-04-11 17:26:28 +08:00
}
2025-10-13 20:20:01 +08:00
[SerializeField]
private List<UXToggle> m_Toggles = new List<UXToggle>();
[SerializeField]
private UXToggle m_DefaultToggle;
2025-04-11 17:26:28 +08:00
public UXToggle defaultToggle
2025-04-11 17:26:28 +08:00
{
get { return m_DefaultToggle; }
set { m_DefaultToggle = value; EnsureValidState(); }
2025-04-11 17:26:28 +08:00
}
2025-07-28 13:04:49 +08:00
protected UXGroup()
2025-12-09 20:30:11 +08:00
{
}
2025-10-13 20:20:01 +08:00
protected override void Start()
{
EnsureValidState();
base.Start();
2025-04-11 17:26:28 +08:00
}
2025-12-09 20:30:11 +08:00
protected override void OnEnable()
2025-04-11 17:26:28 +08:00
{
EnsureValidState();
base.OnEnable();
2025-04-11 17:26:28 +08:00
}
private void ValidateToggleIsInGroup(UXToggle toggle)
2025-04-11 17:26:28 +08:00
{
if (toggle == null || !m_Toggles.Contains(toggle))
throw new ArgumentException(string.Format("UXToggle {0} is not part of ToggleGroup {1}", new object[] { toggle, this }));
}
2025-12-09 20:30:11 +08:00
public void NotifyToggleOn(UXToggle toggle, bool sendCallback = true)
{
ValidateToggleIsInGroup(toggle);
for (var i = 0; i < m_Toggles.Count; i++)
2025-12-09 20:30:11 +08:00
{
if (m_Toggles[i] == toggle)
continue;
if (sendCallback)
m_Toggles[i].isOn = false;
else
m_Toggles[i].SetIsOnWithoutNotify(false);
2025-12-09 20:30:11 +08:00
}
}
public void UnregisterToggle(UXToggle toggle)
{
if (toggle == null)
return;
if (m_Toggles.Contains(toggle))
m_Toggles.Remove(toggle);
if (m_DefaultToggle == toggle)
2025-12-09 20:30:11 +08:00
{
m_DefaultToggle = null;
2025-12-09 20:30:11 +08:00
}
2025-04-11 17:26:28 +08:00
}
2025-07-28 13:04:49 +08:00
public void RegisterToggle(UXToggle toggle)
2025-12-09 20:30:11 +08:00
{
if (toggle == null)
return;
2025-10-13 20:20:01 +08:00
if (!m_Toggles.Contains(toggle))
m_Toggles.Add(toggle);
2026-03-18 16:01:18 +08:00
if (!allowSwitchOff)
2025-12-09 20:30:11 +08:00
{
2026-03-18 16:01:18 +08:00
var firstActive = GetFirstActiveToggle();
if (firstActive != null && firstActive != toggle && toggle.isOn)
{
toggle.SetIsOnWithoutNotify(false);
}
else if (firstActive == null)
{
if (m_DefaultToggle != null && m_Toggles.Contains(m_DefaultToggle))
{
var dt = m_DefaultToggle;
if (dt != null && dt != toggle)
{
dt.isOn = true;
NotifyToggleOn(dt);
}
else if (dt == toggle)
{
toggle.isOn = true;
NotifyToggleOn(toggle);
}
}
}
2025-12-09 20:30:11 +08:00
}
}
2025-12-09 20:30:11 +08:00
2026-03-18 16:01:18 +08:00
public bool ContainsToggle(UXToggle toggle)
{
return m_Toggles != null && m_Toggles.Contains(toggle);
2025-12-09 20:30:11 +08:00
}
2025-04-11 17:26:28 +08:00
public void EnsureValidState()
2025-12-09 20:30:11 +08:00
{
if (m_Toggles == null)
m_Toggles = new List<UXToggle>();
m_Toggles.RemoveAll(x => x == null);
if (!allowSwitchOff && !AnyTogglesOn() && m_Toggles.Count != 0)
{
UXToggle toSelect = null;
if (m_DefaultToggle != null && m_Toggles.Contains(m_DefaultToggle))
{
toSelect = m_DefaultToggle;
}
else
{
toSelect = m_Toggles[0];
}
2025-08-08 20:56:31 +08:00
if (toSelect != null)
{
toSelect.isOn = true;
NotifyToggleOn(toSelect);
}
}
IEnumerable<UXToggle> activeToggles = ActiveToggles();
if (activeToggles.Count() > 1)
{
UXToggle firstActive = GetFirstActiveToggle();
foreach (UXToggle toggle in activeToggles)
{
if (toggle == firstActive)
{
continue;
}
toggle.isOn = false;
}
}
for (int i = 0; i < m_Toggles.Count; i++)
{
var t = m_Toggles[i];
if (t == null)
continue;
if (t.group != this)
{
t.group = this;
}
}
2025-12-09 20:30:11 +08:00
}
2025-08-08 20:56:31 +08:00
public bool AnyTogglesOn()
2025-12-09 20:30:11 +08:00
{
return m_Toggles.Find(x => x != null && x.isOn) != null;
2025-12-09 20:30:11 +08:00
}
2025-08-08 20:56:31 +08:00
public IEnumerable<UXToggle> ActiveToggles()
{
return m_Toggles.Where(x => x != null && x.isOn);
}
2025-08-08 20:56:31 +08:00
public UXToggle GetFirstActiveToggle()
2025-08-11 14:45:27 +08:00
{
if (m_DefaultToggle != null && m_Toggles.Contains(m_DefaultToggle) && m_DefaultToggle.isOn)
return m_DefaultToggle;
IEnumerable<UXToggle> activeToggles = ActiveToggles();
return activeToggles.Count() > 0 ? activeToggles.First() : null;
2025-08-08 20:56:31 +08:00
}
2025-08-11 14:45:27 +08:00
public void SetAllTogglesOff(bool sendCallback = true)
2025-12-09 20:30:11 +08:00
{
bool oldAllowSwitchOff = m_AllowSwitchOff;
m_AllowSwitchOff = true;
2025-12-09 20:30:11 +08:00
if (sendCallback)
{
for (var i = 0; i < m_Toggles.Count; i++)
if (m_Toggles[i] != null)
m_Toggles[i].isOn = false;
}
else
2025-12-09 20:30:11 +08:00
{
for (var i = 0; i < m_Toggles.Count; i++)
if (m_Toggles[i] != null)
m_Toggles[i].SetIsOnWithoutNotify(false);
2025-12-09 20:30:11 +08:00
}
m_AllowSwitchOff = oldAllowSwitchOff;
}
public void Next()
{
SelectAdjacent(true);
}
public void Preview()
{
SelectAdjacent(false);
}
private void SelectAdjacent(bool forward)
{
if (m_Toggles == null || m_Toggles.Count == 0)
return;
UXToggle current = GetFirstActiveToggle();
int currentIndex = current != null ? m_Toggles.IndexOf(current) : -1;
int idx = currentIndex;
if (idx == -1 && !forward)
idx = 0;
for (int step = 0; step < m_Toggles.Count; step++)
{
if (forward)
{
idx = (idx + 1) % m_Toggles.Count;
}
else
{
idx = (idx - 1 + m_Toggles.Count) % m_Toggles.Count;
}
UXToggle t = m_Toggles[idx];
if (t == null)
continue;
if (!t.IsActive())
continue;
if (!t.IsInteractable())
continue;
t.isOn = true;
return;
}
2025-12-09 20:30:11 +08:00
}
2025-08-08 20:56:31 +08:00
}
2025-04-11 17:26:28 +08:00
}