using System; using System.Collections.Generic; using System.Linq; using UnityEngine.EventSystems; using UnityEngine; namespace UnityEngine.UI { [AddComponentMenu("UI/UXGroup", 31)] [DisallowMultipleComponent] public class UXGroup : UIBehaviour { [SerializeField] private bool m_AllowSwitchOff = false; public bool allowSwitchOff { get { return m_AllowSwitchOff; } set { m_AllowSwitchOff = value; } } [SerializeField] private List m_Toggles = new List(); [SerializeField] private UXToggle m_DefaultToggle; public UXToggle defaultToggle { get { return m_DefaultToggle; } set { m_DefaultToggle = value; EnsureValidState(); } } protected UXGroup() { } protected override void Start() { EnsureValidState(); base.Start(); } protected override void OnEnable() { EnsureValidState(); base.OnEnable(); } private void ValidateToggleIsInGroup(UXToggle toggle) { if (toggle == null || !m_Toggles.Contains(toggle)) throw new ArgumentException(string.Format("UXToggle {0} is not part of ToggleGroup {1}", new object[] { toggle, this })); } public void NotifyToggleOn(UXToggle toggle, bool sendCallback = true) { ValidateToggleIsInGroup(toggle); for (var i = 0; i < m_Toggles.Count; i++) { if (m_Toggles[i] == toggle) continue; if (sendCallback) m_Toggles[i].isOn = false; else m_Toggles[i].SetIsOnWithoutNotify(false); } } public void UnregisterToggle(UXToggle toggle) { if (toggle == null) return; if (m_Toggles.Contains(toggle)) m_Toggles.Remove(toggle); if (m_DefaultToggle == toggle) { m_DefaultToggle = null; } } public void RegisterToggle(UXToggle toggle) { if (toggle == null) return; if (!m_Toggles.Contains(toggle)) m_Toggles.Add(toggle); if (!allowSwitchOff) { 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); } } } } } public bool ContainsToggle(UXToggle toggle) { return m_Toggles != null && m_Toggles.Contains(toggle); } public void EnsureValidState() { if (m_Toggles == null) m_Toggles = new List(); 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]; } if (toSelect != null) { toSelect.isOn = true; NotifyToggleOn(toSelect); } } IEnumerable 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; } } } public bool AnyTogglesOn() { return m_Toggles.Find(x => x != null && x.isOn) != null; } public IEnumerable ActiveToggles() { return m_Toggles.Where(x => x != null && x.isOn); } public UXToggle GetFirstActiveToggle() { if (m_DefaultToggle != null && m_Toggles.Contains(m_DefaultToggle) && m_DefaultToggle.isOn) return m_DefaultToggle; IEnumerable activeToggles = ActiveToggles(); return activeToggles.Count() > 0 ? activeToggles.First() : null; } public void SetAllTogglesOff(bool sendCallback = true) { bool oldAllowSwitchOff = m_AllowSwitchOff; m_AllowSwitchOff = true; if (sendCallback) { for (var i = 0; i < m_Toggles.Count; i++) if (m_Toggles[i] != null) m_Toggles[i].isOn = false; } else { for (var i = 0; i < m_Toggles.Count; i++) if (m_Toggles[i] != null) m_Toggles[i].SetIsOnWithoutNotify(false); } 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; } } } }