using UnityEditor.DrawUtils; using UnityEditor.Extensions; using UnityEditor.SceneManagement; using UnityEditor; using UnityEngine; using UnityEngine.UI; namespace UnityEditor.UI { [CustomEditor(typeof(UXToggle), true)] [CanEditMultipleObjects] internal class UXToggleEditor : UXSelectableEditor { SerializedProperty m_OnValueChangedProperty; SerializedProperty m_TransitionProperty; SerializedProperty m_GraphicProperty; SerializedProperty m_GroupProperty; SerializedProperty m_IsOnProperty; private SerializedProperty hoverAudioClip; private SerializedProperty clickAudioClip; protected override void OnEnable() { base.OnEnable(); m_TransitionProperty = serializedObject.FindProperty("toggleTransition"); m_GraphicProperty = serializedObject.FindProperty("graphic"); m_GroupProperty = serializedObject.FindProperty("m_Group"); m_IsOnProperty = serializedObject.FindProperty("m_IsOn"); m_OnValueChangedProperty = serializedObject.FindProperty("onValueChanged"); hoverAudioClip = serializedObject.FindProperty("hoverAudioClip"); clickAudioClip = serializedObject.FindProperty("clickAudioClip"); _tabs.AppendToTab("Image", DrawImageTab); _tabs.RegisterTab("Sound", "d_AudioSource Icon", DrawSoundTab); _tabs.RegisterTab("Event", "EventTrigger Icon", DrawEventTab); } protected override void OnDisable() { base.OnDisable(); _tabs.UnregisterTab("Sound"); _tabs.UnregisterTab("Event"); } private void DrawEventTab() { EditorGUILayout.Space(); serializedObject.Update(); EditorGUILayout.PropertyField(m_OnValueChangedProperty); serializedObject.ApplyModifiedProperties(); } private void DrawSoundTab() { GUILayoutHelper.DrawProperty(hoverAudioClip, customSkin, "Hover Sound", "Play", () => { if (hoverAudioClip.objectReferenceValue != null) { PlayAudio((AudioClip)hoverAudioClip.objectReferenceValue); } }); GUILayoutHelper.DrawProperty(clickAudioClip, customSkin, "Click Sound", "Play", () => { if (clickAudioClip.objectReferenceValue != null) { PlayAudio((AudioClip)clickAudioClip.objectReferenceValue); } }); } private void PlayAudio(AudioClip clip) { if (clip != null) { ExtensionHelper.PreviewAudioClip(clip); } } private void DrawImageTab() { EditorGUILayout.Space(); serializedObject.Update(); UXToggle toggle = serializedObject.targetObject as UXToggle; EditorGUI.BeginChangeCheck(); GUILayoutHelper.DrawProperty(m_IsOnProperty, customSkin, "Is On"); if (EditorGUI.EndChangeCheck()) { if (!Application.isPlaying) EditorSceneManager.MarkSceneDirty(toggle.gameObject.scene); UXGroup group = m_GroupProperty.objectReferenceValue as UXGroup; bool newIsOn = m_IsOnProperty.boolValue; bool oldIsOn = toggle.isOn; // 编辑器下:如果属于某组且不允许 all-off,且当前正是被选中的项,则禁止通过 Inspector 将其关闭 if (!Application.isPlaying && group != null && !group.allowSwitchOff && oldIsOn && !newIsOn) { Debug.LogWarning($"Cannot turn off toggle '{toggle.name}' because its group '{group.name}' does not allow all toggles to be off.", toggle); // 恢复 Inspector 中的显示为 true m_IsOnProperty.boolValue = true; serializedObject.ApplyModifiedProperties(); } else { // 使用属性赋值以保证视觉刷新(PlayEffect 会在 setter 被调用) toggle.isOn = newIsOn; if (group != null && group.isActiveAndEnabled && toggle.IsActive()) { if (toggle.isOn || (!group.AnyTogglesOn() && !group.allowSwitchOff)) { toggle.isOn = true; group.NotifyToggleOn(toggle); } } } } GUILayoutHelper.DrawProperty(m_TransitionProperty, customSkin, "Transition"); GUILayoutHelper.DrawProperty(m_GraphicProperty, customSkin, "Graphic"); EditorGUI.BeginChangeCheck(); GUILayoutHelper.DrawProperty(m_GroupProperty, customSkin, "UXGroup", (oldValue, newValue) => { UXToggle self = target as UXToggle; if (oldValue != null) { oldValue.UnregisterToggle(self); } if (newValue != null) { newValue.RegisterToggle(self); } }); if (EditorGUI.EndChangeCheck()) { if (!Application.isPlaying) EditorSceneManager.MarkSceneDirty(toggle.gameObject.scene); UXGroup group = m_GroupProperty.objectReferenceValue as UXGroup; // Use the property setter to ensure consistent registration/unregistration toggle.group = group; } EditorGUILayout.Space(); serializedObject.ApplyModifiedProperties(); } } }