diff --git a/Editor/Icons/SwitchOff.png b/Editor/Icons/SwitchOff.png index 0884218..5557bf7 100644 Binary files a/Editor/Icons/SwitchOff.png and b/Editor/Icons/SwitchOff.png differ diff --git a/Editor/Icons/SwitchOffHover.png b/Editor/Icons/SwitchOffHover.png index 8eea37a..5557bf7 100644 Binary files a/Editor/Icons/SwitchOffHover.png and b/Editor/Icons/SwitchOffHover.png differ diff --git a/Editor/Icons/SwitchOn.png b/Editor/Icons/SwitchOn.png index 9f3f6dd..158f6a6 100644 Binary files a/Editor/Icons/SwitchOn.png and b/Editor/Icons/SwitchOn.png differ diff --git a/Editor/Res/TMP - Text Component Icon.psd b/Editor/Res/TMP - Text Component Icon.psd new file mode 100644 index 0000000..3cc4163 Binary files /dev/null and b/Editor/Res/TMP - Text Component Icon.psd differ diff --git a/Editor/Res/TMP - Text Component Icon.psd.meta b/Editor/Res/TMP - Text Component Icon.psd.meta new file mode 100644 index 0000000..5b8f93b --- /dev/null +++ b/Editor/Res/TMP - Text Component Icon.psd.meta @@ -0,0 +1,117 @@ +fileFormatVersion: 2 +guid: c4398d454b1a861499ef73d23bc7a032 +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 13 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + flipGreenChannel: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + vTOnly: 0 + ignoreMipmapLimit: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 1 + aniso: 1 + mipBias: 0 + wrapU: 1 + wrapV: 1 + wrapW: 0 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 50 + spriteMode: 1 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 0 + alphaUsage: 1 + alphaIsTransparency: 1 + spriteTessellationDetail: -1 + textureType: 8 + textureShape: 1 + singleChannelComponent: 0 + flipbookRows: 1 + flipbookColumns: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + ignorePngGamma: 0 + applyGammaDecoding: 0 + swizzle: 50462976 + cookieLightType: 0 + platformSettings: + - serializedVersion: 4 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 4 + buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + customData: + physicsShape: [] + bones: [] + spriteID: 5e97eb03825dee720800000000000000 + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + spriteCustomMetadata: + entries: [] + nameFileIdTable: {} + mipmapLimitGroupName: + pSDRemoveMatte: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/Res/UIExtensionGUISkin.guiskin b/Editor/Res/UIExtensionGUISkin.guiskin index 9f64856..88fa1e5 100644 --- a/Editor/Res/UIExtensionGUISkin.guiskin +++ b/Editor/Res/UIExtensionGUISkin.guiskin @@ -211,7 +211,7 @@ MonoBehaviour: m_ImagePosition: 0 m_ContentOffset: {x: 15, y: 1} m_FixedWidth: 24 - m_FixedHeight: 15 + m_FixedHeight: 24 m_StretchWidth: 1 m_StretchHeight: 0 m_label: diff --git a/Editor/UX/UXButtonEditor.cs b/Editor/UX/UXButtonEditor.cs index 42a47dd..c95cf92 100644 --- a/Editor/UX/UXButtonEditor.cs +++ b/Editor/UX/UXButtonEditor.cs @@ -9,7 +9,7 @@ using UnityEngine.UI; [CanEditMultipleObjects] [CustomEditor(typeof(UXButton), true)] -public class UXButtonEditor : Editor +internal class UXButtonEditor : Editor { private enum TabType { diff --git a/Editor/UX/UXGroupEditor.cs b/Editor/UX/UXGroupEditor.cs deleted file mode 100644 index b523426..0000000 --- a/Editor/UX/UXGroupEditor.cs +++ /dev/null @@ -1,29 +0,0 @@ -// using UnityEditor; -// -// #if UNITY_EDITOR -// [CustomEditor(typeof(UXGroup))] -// public class UXGroupEditor : Editor -// { -// private SerializedProperty m_AllowSwitchOff; -// private SerializedProperty m_Buttons; -// private SerializedProperty m_OnSelectedChanged; -// -// private void OnEnable() -// { -// m_AllowSwitchOff = serializedObject.FindProperty("m_AllowSwitchOff"); -// m_Buttons = serializedObject.FindProperty("m_Buttons"); -// m_OnSelectedChanged = serializedObject.FindProperty("onSelectedChanged"); -// } -// -// public override void OnInspectorGUI() -// { -// serializedObject.Update(); -// -// EditorGUILayout.PropertyField(m_AllowSwitchOff); -// EditorGUILayout.PropertyField(m_Buttons, true); -// EditorGUILayout.PropertyField(m_OnSelectedChanged); -// -// serializedObject.ApplyModifiedProperties(); -// } -// } -// #endif diff --git a/Editor/UX/UXGroupEditor.cs.meta b/Editor/UX/UXGroupEditor.cs.meta deleted file mode 100644 index 3bbd213..0000000 --- a/Editor/UX/UXGroupEditor.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: d66e1f78170d455c93d71e71ee8f735a -timeCreated: 1744275087 \ No newline at end of file diff --git a/Runtime/UGUIExtension/Text/UXTextMeshPro.cs.meta b/Runtime/UGUIExtension/Text/UXTextMeshPro.cs.meta index 121427c..a1339a5 100644 --- a/Runtime/UGUIExtension/Text/UXTextMeshPro.cs.meta +++ b/Runtime/UGUIExtension/Text/UXTextMeshPro.cs.meta @@ -5,7 +5,7 @@ MonoImporter: serializedVersion: 2 defaultReferences: [] executionOrder: 0 - icon: {instanceID: 0} + icon: {fileID: 2800000, guid: c4398d454b1a861499ef73d23bc7a032, type: 3} userData: assetBundleName: assetBundleVariant: diff --git a/Runtime/UGUIExtension/UX/UXButton.cs b/Runtime/UGUIExtension/UX/UXButton.cs index c310e89..20319f3 100644 --- a/Runtime/UGUIExtension/UX/UXButton.cs +++ b/Runtime/UGUIExtension/UX/UXButton.cs @@ -1,11 +1,11 @@ using System; +using System.Collections; using System.Collections.Generic; using AlicizaX; using AlicizaX.UI.Extension; using UnityEngine; using UnityEngine.Events; using UnityEngine.EventSystems; -using UnityEngine.Serialization; using UnityEngine.UI; using AudioType = AlicizaX.Audio.Runtime.AudioType; @@ -16,7 +16,6 @@ public enum ButtonModeType Toggle } - [System.Serializable] public class TransitionData { @@ -24,102 +23,130 @@ public class TransitionData public Selectable.Transition transition = Selectable.Transition.ColorTint; public ColorBlock colors; public SpriteState spriteState; - public AnimationTriggers animationTriggers = new AnimationTriggers(); + public AnimationTriggers animationTriggers = new(); } - internal enum SelectionState { Normal, - Highlighted, - Pressed, - Selected, Disabled, } - +[ExecuteInEditMode] [DisallowMultipleComponent] public class UXButton : UIBehaviour, IButton, - IPointerDownHandler, - IPointerUpHandler, - IPointerEnterHandler, - IPointerExitHandler, - IPointerClickHandler + IPointerDownHandler, IPointerUpHandler, IPointerEnterHandler, + IPointerExitHandler, IPointerClickHandler, ISubmitHandler { + #region Serialized Fields + [SerializeField] private bool m_Interactable = true; - [SerializeField] private ButtonModeType m_Mode; - - [SerializeField] private Button.ButtonClickedEvent m_OnClick = new Button.ButtonClickedEvent(); - - [SerializeField] private TransitionData m_TransitionData = new TransitionData(); - - [SerializeField] private List m_ChildTransitions = new List(); + [SerializeField] private Button.ButtonClickedEvent m_OnClick = new(); + [SerializeField] private TransitionData m_TransitionData = new(); + [SerializeField] private List m_ChildTransitions = new(); [SerializeField] private UXGroup m_UXGroup; - [SerializeField] private AudioClip hoverAudioClip; [SerializeField] private AudioClip clickAudioClip; + #endregion + + #region Private Variables + [SerializeField] private SelectionState m_SelectionState = SelectionState.Normal; private bool m_DownAndExistUI; private bool m_IsDown; private bool m_IsTogSelected; - private Animator _animator; + private WaitForSeconds _waitTimeFadeDuration; + private Coroutine _resetRoutine; + private bool _boardEvent; + + private readonly Dictionary _animTriggerIDs = new(); + private readonly Dictionary _animResetTriggerIDs = new(); + + #endregion + + #region Properties internal Animator animator { get { - _animator = _animator ?? GetComponent(); + if (!_animator) + _animator = GetComponent(); return _animator; } } public bool IsSelected { - get { return m_IsTogSelected; } + get => m_IsTogSelected; internal set { + if (m_IsTogSelected == value) return; m_IsTogSelected = value; onValueChanged?.Invoke(m_IsTogSelected); - m_SelectionState = m_IsTogSelected ? SelectionState.Selected : SelectionState.Normal; + m_SelectionState = value ? SelectionState.Selected : SelectionState.Normal; UpdateVisualState(m_SelectionState, false); } } public Button.ButtonClickedEvent onClick { - get { return m_OnClick; } - set { m_OnClick = value; } + get => m_OnClick; + set => m_OnClick = value; } - [SerializeField] private UnityEvent m_OnValueChanged = new UnityEvent(); + [SerializeField] private UnityEvent m_OnValueChanged = new(); public UnityEvent onValueChanged { - get { return m_OnValueChanged; } - set { m_OnValueChanged = value; } + get => m_OnValueChanged; + set => m_OnValueChanged = value; } + #endregion + + #region Unity Lifecycle + protected override void Awake() { base.Awake(); - if (m_Mode == ButtonModeType.Toggle) - { - onValueChanged?.Invoke(IsSelected); - } + _waitTimeFadeDuration = new WaitForSeconds( + Mathf.Max(0.01f, m_TransitionData.colors.fadeDuration)); + + var triggers = m_TransitionData.animationTriggers; + AddTriggerID(triggers.normalTrigger); + AddTriggerID(triggers.highlightedTrigger); + AddTriggerID(triggers.pressedTrigger); + AddTriggerID(triggers.selectedTrigger); + AddTriggerID(triggers.disabledTrigger); UpdateVisualState(m_SelectionState, true); } + protected override void OnDestroy() + { + if (_resetRoutine != null) + { + StopCoroutine(_resetRoutine); + _resetRoutine = null; + } + + base.OnDestroy(); + } + + #endregion + + #region Event Handlers void IPointerDownHandler.OnPointerDown(PointerEventData eventData) { - if (!m_Interactable) return; - if (eventData.button != PointerEventData.InputButton.Left) return; + if (!ShouldProcessEvent(eventData)) return; + m_IsDown = true; m_SelectionState = SelectionState.Pressed; UpdateVisualState(m_SelectionState, false); @@ -127,29 +154,30 @@ public class UXButton : UIBehaviour, IButton, void IPointerUpHandler.OnPointerUp(PointerEventData eventData) { - if (!m_Interactable) return; + if (!m_Interactable || eventData.button != PointerEventData.InputButton.Left) + return; m_IsDown = false; - - if (!m_IsTogSelected) + if (m_IsTogSelected) { - m_SelectionState = m_DownAndExistUI ? SelectionState.Normal : SelectionState.Highlighted; - UpdateVisualState(m_SelectionState, false); + m_SelectionState = SelectionState.Selected; } else { - m_SelectionState = SelectionState.Selected; - UpdateVisualState(m_SelectionState, false); + m_SelectionState = m_DownAndExistUI ? SelectionState.Normal : SelectionState.Highlighted; } + + UpdateVisualState(m_SelectionState, false); } void IPointerEnterHandler.OnPointerEnter(PointerEventData eventData) { - if (!m_Interactable || CantTouch()) return; + if (!ShouldProcessEvent(eventData)) return; - m_SelectionState = SelectionState.Highlighted; m_DownAndExistUI = false; if (m_IsDown) return; + + m_SelectionState = SelectionState.Highlighted; UpdateVisualState(m_SelectionState, false); PlayButtonSound(hoverAudioClip); } @@ -163,45 +191,72 @@ public class UXButton : UIBehaviour, IButton, return; } - if (CantTouch()) - { - return; - } - - m_SelectionState = SelectionState.Normal; - + m_SelectionState = IsSelected ? SelectionState.Selected : SelectionState.Normal; UpdateVisualState(m_SelectionState, false); } - private bool CantTouch() + void IPointerClickHandler.OnPointerClick(PointerEventData eventData) { - return m_Mode == ButtonModeType.Toggle && m_IsTogSelected; + if (eventData.button != PointerEventData.InputButton.Left || !m_Interactable) + return; + + PlayButtonSound(clickAudioClip); + ProcessClick(); } + void ISubmitHandler.OnSubmit(BaseEventData eventData) + { + UpdateVisualState(SelectionState.Pressed, false); + ProcessClick(); + + if (_resetRoutine != null) + StopCoroutine(OnFinishSubmit()); + + _resetRoutine = StartCoroutine(OnFinishSubmit()); + } + + #endregion + + #region Public Methods + public void SetSelect(bool state, bool boardEvent = false) { if (m_Mode != ButtonModeType.Toggle) return; - m_IsTogSelected = state; - if (boardEvent) onValueChanged?.Invoke(m_IsTogSelected); - m_SelectionState = m_IsTogSelected ? SelectionState.Selected : SelectionState.Normal; - UpdateVisualState(m_SelectionState, false); + _boardEvent = boardEvent; + IsSelected = state; + } + + #endregion + + #region Private Methods + + private bool ShouldProcessEvent(PointerEventData eventData) + { + return m_Interactable && + eventData.button == PointerEventData.InputButton.Left && + !(m_Mode == ButtonModeType.Toggle && IsSelected); } private void ProcessClick() { + if (!_boardEvent) + { + _boardEvent = true; + return; + } + + _boardEvent = true; if (m_Mode == ButtonModeType.Normal) { UISystemProfilerApi.AddMarker("Button.onClick", this); - onClick?.Invoke(); + m_OnClick?.Invoke(); + } + else if (m_UXGroup) + { + m_UXGroup.NotifyButtonClicked(this); } else { - if (m_UXGroup) - { - m_UXGroup.NotifyButtonClicked(this); - return; - } - IsSelected = !IsSelected; } } @@ -215,7 +270,6 @@ public class UXButton : UIBehaviour, IButton, } } - private void ProcessTransitionData(TransitionData transition, SelectionState state, bool instant) { if (transition.targetGraphic == null) return; @@ -223,11 +277,12 @@ public class UXButton : UIBehaviour, IButton, Color tintColor; Sprite transitionSprite; string triggerName; + switch (state) { case SelectionState.Normal: tintColor = transition.colors.normalColor; - transitionSprite = null; + transitionSprite = transition.spriteState.highlightedSprite; triggerName = transition.animationTriggers.normalTrigger; break; case SelectionState.Highlighted: @@ -251,10 +306,7 @@ public class UXButton : UIBehaviour, IButton, triggerName = transition.animationTriggers.disabledTrigger; break; default: - tintColor = Color.black; - transitionSprite = null; - triggerName = string.Empty; - break; + return; } switch (transition.transition) @@ -266,60 +318,83 @@ public class UXButton : UIBehaviour, IButton, DoSpriteSwap(transition, transitionSprite); break; case Selectable.Transition.Animation: - TriggerAnimation(transition.animationTriggers, triggerName); + TriggerAnimation(triggerName); break; } } - protected void StartColorTween(TransitionData transitionData, Color targetColor, bool instant) + private void StartColorTween(TransitionData data, Color targetColor, bool instant) { if (Application.isPlaying) { - transitionData.targetGraphic.CrossFadeColor(targetColor, instant ? 0f : transitionData.colors.fadeDuration, true, true); + data.targetGraphic.CrossFadeColor( + targetColor, + instant ? 0f : data.colors.fadeDuration, + true, + true + ); } else { - transitionData.targetGraphic.canvasRenderer.SetColor(targetColor); + data.targetGraphic.canvasRenderer.SetColor(targetColor); } } - protected void DoSpriteSwap(TransitionData transitionData, Sprite newSprite) + private void DoSpriteSwap(TransitionData data, Sprite newSprite) { - if (transitionData.targetGraphic is Image image) + if (data.targetGraphic is Image image) { image.overrideSprite = newSprite; } - else if (transitionData.targetGraphic != null) + } + + private void TriggerAnimation(string trigger) + { + if (animator == null || + !animator.isActiveAndEnabled || + !animator.hasBoundPlayables || + string.IsNullOrEmpty(trigger)) + return; + + foreach (var resetTrigger in _animResetTriggerIDs.Keys) { - Log.Error($"Target Graphic must be Image for SpriteSwap. Object: {transitionData.targetGraphic.name}"); + animator.ResetTrigger(_animTriggerIDs[resetTrigger]); + } + + if (_animTriggerIDs.TryGetValue(trigger, out int id)) + { + animator.SetTrigger(id); } } - void TriggerAnimation(AnimationTriggers animationTriggers, string triggername) + private void AddTriggerID(string triggerName) { - if (animator == null || !animator.isActiveAndEnabled || !animator.hasBoundPlayables || string.IsNullOrEmpty(triggername)) - return; - - animator.ResetTrigger(animationTriggers.normalTrigger); - animator.ResetTrigger(animationTriggers.highlightedTrigger); - animator.ResetTrigger(animationTriggers.pressedTrigger); - animator.ResetTrigger(animationTriggers.selectedTrigger); - animator.ResetTrigger(animationTriggers.disabledTrigger); - - animator.SetTrigger(triggername); + if (!string.IsNullOrEmpty(triggerName)) + { + int id = Animator.StringToHash(triggerName); + if (!_animTriggerIDs.ContainsKey(triggerName)) + { + _animTriggerIDs.Add(triggerName, id); + _animResetTriggerIDs.Add(triggerName, id); + } + } } - protected void PlayButtonSound(AudioClip clip) + private void PlayButtonSound(AudioClip clip) { - GameApp.Audio?.Play(AudioType.UISound, clip, false, GameApp.Audio.UISoundVolume); + if (clip == null || GameApp.Audio == null) return; + GameApp.Audio.Play(AudioType.UISound, clip, false, GameApp.Audio.UISoundVolume); } - - public void OnPointerClick(PointerEventData eventData) + private IEnumerator OnFinishSubmit() { - if (eventData.button != PointerEventData.InputButton.Left) - return; - PlayButtonSound(clickAudioClip); - ProcessClick(); + yield return _waitTimeFadeDuration; + UpdateVisualState( + m_IsTogSelected ? SelectionState.Selected : SelectionState.Normal, + false + ); + _resetRoutine = null; } + + #endregion } diff --git a/Runtime/UGUIExtension/UX/UXGroup.cs b/Runtime/UGUIExtension/UX/UXGroup.cs index 286cdbb..297c452 100644 --- a/Runtime/UGUIExtension/UX/UXGroup.cs +++ b/Runtime/UGUIExtension/UX/UXGroup.cs @@ -1,5 +1,3 @@ -// UXGroup.cs - using UnityEngine; using UnityEngine.Events; using System.Collections.Generic; @@ -10,11 +8,12 @@ using UnityEngine.EventSystems; public class UXGroup : UIBehaviour { [SerializeField] private bool m_AllowSwitchOff; - [ReadOnly] [SerializeField] private List m_Buttons = new List(); + [ReadOnly, SerializeField] private List m_Buttons = new(); - private UXButton currentUXButton = null; + private UXButton _current; + private readonly HashSet _registeredButtons = new(); - public UnityEvent onSelectedChanged = new UnityEvent(); + public UnityEvent onSelectedChanged = new(); public bool allowSwitchOff { @@ -28,87 +27,83 @@ public class UXGroup : UIBehaviour protected override void OnDestroy() { - base.OnDestroy(); + foreach (var button in _registeredButtons) + { + if (button) button.IsSelected = false; + } m_Buttons.Clear(); - currentUXButton = null; + _registeredButtons.Clear(); + base.OnDestroy(); } - - protected override void Awake() - { - base.Awake(); - ValidateGroupState(); - } + protected override void Awake() => ValidateGroupState(); public void RegisterButton(UXButton button) { - if (!m_Buttons.Contains(button)) + if (!button || _registeredButtons.Contains(button)) return; + + m_Buttons.Add(button); + _registeredButtons.Add(button); + + if (button.IsSelected) { - m_Buttons.Add(button); - if (button.IsSelected) - { - if (currentUXButton != null && currentUXButton != button) - { - currentUXButton.IsSelected = false; - } - currentUXButton = button; - } - ValidateGroupState(); + if (_current && _current != button) + _current.IsSelected = false; + _current = button; } + + ValidateGroupState(); } public void UnregisterButton(UXButton button) { - if (m_Buttons.Contains(button)) - { - m_Buttons.Remove(button); - button.IsSelected = false; - } + if (!button || !_registeredButtons.Contains(button)) return; + + m_Buttons.Remove(button); + _registeredButtons.Remove(button); + button.IsSelected = false; + + if (_current == button) + _current = null; } internal void NotifyButtonClicked(UXButton clickedButton) { - if (!clickedButton.IsSelected) - { - SetSelectedButton(clickedButton); - } - else + if (clickedButton.IsSelected) { if (m_AllowSwitchOff) SetSelectedButton(null); - else if (currentUXButton != clickedButton) - clickedButton.IsSelected = true; + } + else + { + SetSelectedButton(clickedButton); } } - private void SetSelectedButton(UXButton targetButton) + private void SetSelectedButton(UXButton target) { - UXButton previousSelected = currentUXButton; - currentUXButton = null; // 防止递归 + var previous = _current; + _current = null; foreach (var button in m_Buttons) { - bool shouldSelect = (button == targetButton); + bool shouldSelect = (button == target); if (button.IsSelected != shouldSelect) - { button.IsSelected = shouldSelect; - } - if (shouldSelect) currentUXButton = button; + + if (shouldSelect) + _current = button; } - if (previousSelected != currentUXButton) - { - onSelectedChanged.Invoke(currentUXButton); - } + if (previous != _current) + onSelectedChanged?.Invoke(_current); } private void ValidateGroupState() { - bool anySelected = m_Buttons.Exists(b => b.IsSelected); - if (!anySelected && m_Buttons.Count > 0 && !m_AllowSwitchOff) - { + bool hasSelected = _current != null && _current.IsSelected; + if (!hasSelected && m_Buttons.Count > 0 && !m_AllowSwitchOff) SetSelectedButton(m_Buttons[0]); - } } public bool AnyOtherSelected(UXButton exclusion) @@ -118,7 +113,6 @@ public class UXGroup : UIBehaviour if (button != exclusion && button.IsSelected) return true; } - return false; } }