com.alicizax.unity.ui.exten.../Editor/UX/UXButtonEditor.cs
2025-07-25 13:29:20 +08:00

338 lines
12 KiB
C#

// UXButtonEditor.cs
#if UNITY_EDITOR
using System;
using System.Collections.Generic;
using Sirenix.OdinInspector.Editor;
using UnityEditor;
using UnityEditor.AnimatedValues;
using UnityEditor.UI;
using UnityEngine;
using UnityEngine.UI;
[CanEditMultipleObjects]
[CustomEditor(typeof(UXButton), true)]
public class UXButtonEditor : Editor
{
private SerializedProperty m_Interactable;
private SerializedProperty m_Mode;
private SerializedProperty m_OnValueChanged;
private SerializedProperty m_OnClick;
private SerializedProperty m_UXGroup;
private SerializedProperty m_TransitionData;
private SerializedProperty m_ChildTransitions;
private SerializedProperty m_ButtonUISounds;
private bool m_ShowChildTransitions = true;
private Dictionary<int, bool> m_ChildTransitionFoldouts = new Dictionary<int, bool>();
private UXGroup group;
private int m_ButtonMode;
private SerializedProperty m_SelectionState;
private UXButton mTarget;
private void OnEnable()
{
mTarget = target as UXButton;
m_Interactable = serializedObject.FindProperty("m_Interactable");
m_UXGroup = serializedObject.FindProperty("m_UXGroup");
m_Mode = serializedObject.FindProperty("m_Mode");
m_OnValueChanged = serializedObject.FindProperty("m_OnValueChanged");
m_OnClick = serializedObject.FindProperty("m_OnClick");
m_TransitionData = serializedObject.FindProperty("m_TransitionData");
m_ChildTransitions = serializedObject.FindProperty("m_ChildTransitions");
m_ButtonUISounds = serializedObject.FindProperty("m_ButtonUISounds");
m_SelectionState = serializedObject.FindProperty("m_SelectionState");
m_ChildTransitionFoldouts.Clear();
group = (UXGroup)m_UXGroup.objectReferenceValue;
m_ButtonMode = m_Mode.enumValueIndex;
}
private void ResetEventProperty(SerializedProperty property)
{
SerializedProperty persistentCalls = property.FindPropertyRelative("m_PersistentCalls");
SerializedProperty calls = persistentCalls.FindPropertyRelative("m_Calls");
calls.arraySize = 0;
property.serializedObject.ApplyModifiedProperties();
}
public override void OnInspectorGUI()
{
serializedObject.Update();
EditorGUI.BeginDisabledGroup(EditorApplication.isPlaying);
EditorGUILayout.PropertyField(m_Mode);
EditorGUI.EndDisabledGroup();
EditorGUILayout.PropertyField(m_Interactable);
GUILayout.Space(1);
DrawSelfTransition();
GUILayout.Space(5);
DrawChildTransitions();
EditorGUILayout.PropertyField(m_ButtonUISounds);
EditorGUILayout.Space();
if (m_Mode.enumValueIndex != m_ButtonMode)
{
if (m_ButtonMode == (int)ButtonModeType.Normal)
{
ResetEventProperty(m_OnValueChanged);
m_UXGroup.objectReferenceValue = null;
}
else
{
ResetEventProperty((m_OnClick));
}
m_ButtonMode = m_Mode.enumValueIndex;
}
if (m_Mode.enumValueIndex == (int)ButtonModeType.Toggle)
{
EditorGUILayout.PropertyField(m_UXGroup);
UXGroup newGroup = (UXGroup)m_UXGroup.objectReferenceValue;
if (newGroup != group)
{
UXButton self = target as UXButton;
if (group != null)
{
group.UnregisterButton(self);
}
group = newGroup;
if (newGroup != null)
{
newGroup.RegisterButton(self);
}
}
EditorGUILayout.Space();
EditorGUILayout.PropertyField(m_OnValueChanged);
}
else
{
EditorGUILayout.Space();
EditorGUILayout.PropertyField(m_OnClick);
}
serializedObject.ApplyModifiedProperties();
}
private void DrawChildTransitions()
{
m_ShowChildTransitions = EditorGUILayout.Foldout(m_ShowChildTransitions, "Child Transitions", true);
if (!m_ShowChildTransitions)
return;
EditorGUI.indentLevel++;
// 列表控制按钮
EditorGUILayout.BeginHorizontal();
GUILayout.FlexibleSpace();
if (GUILayout.Button("Add Child Transition", GUILayout.Width(150)))
{
m_ChildTransitions.arraySize++;
serializedObject.ApplyModifiedProperties();
}
EditorGUILayout.EndHorizontal();
// 遍历列表元素
for (int i = 0; i < m_ChildTransitions.arraySize; i++)
{
EditorGUILayout.BeginVertical(EditorStyles.helpBox);
// 获取当前元素的SerializedProperty
SerializedProperty element = m_ChildTransitions.GetArrayElementAtIndex(i);
// 初始化折叠状态
if (!m_ChildTransitionFoldouts.ContainsKey(i))
m_ChildTransitionFoldouts[i] = true;
// 折叠标题
string elementTitle = $"Child Transition {i}";
if (element.FindPropertyRelative("targetGraphic").objectReferenceValue != null)
elementTitle += $" ({element.FindPropertyRelative("targetGraphic").objectReferenceValue.name})";
m_ChildTransitionFoldouts[i] = EditorGUILayout.Foldout(m_ChildTransitionFoldouts[i], elementTitle, true);
if (m_ChildTransitionFoldouts[i])
{
// 绘制单个TransitionData
DrawTransitionData(element);
// 删除按钮
EditorGUILayout.BeginHorizontal();
GUILayout.FlexibleSpace();
var orginColor = GUI.backgroundColor;
GUI.backgroundColor = Color.red;
if (GUILayout.Button("Remove", GUILayout.Width(80)))
{
m_ChildTransitions.DeleteArrayElementAtIndex(i);
m_ChildTransitionFoldouts.Remove(i);
serializedObject.ApplyModifiedProperties();
break; // 删除后退出当前循环
}
GUI.backgroundColor = orginColor;
EditorGUILayout.EndHorizontal();
}
EditorGUILayout.EndVertical();
EditorGUILayout.Space(5);
}
EditorGUI.indentLevel--;
}
private void DrawTransitionData(SerializedProperty transitionData)
{
SerializedProperty targetGraphic = transitionData.FindPropertyRelative("targetGraphic");
SerializedProperty transition = transitionData.FindPropertyRelative("transition");
SerializedProperty colorBlock = transitionData.FindPropertyRelative("colors");
SerializedProperty spriteState = transitionData.FindPropertyRelative("spriteState");
SerializedProperty animationTriggers = transitionData.FindPropertyRelative("animationTriggers");
EditorGUI.indentLevel++;
// 绘制目标图形
EditorGUILayout.PropertyField(targetGraphic);
// 获取当前transition类型
var currentTransition = GetTransition(transition);
// 绘制transition类型
EditorGUILayout.PropertyField(transition);
// 显示警告信息
var graphic = targetGraphic.objectReferenceValue as Graphic;
var animation = graphic.GetComponent<Animation>();
switch (currentTransition)
{
case Selectable.Transition.ColorTint:
if (graphic == null)
EditorGUILayout.HelpBox("需要Graphic组件来使用颜色过渡", MessageType.Warning);
break;
case Selectable.Transition.SpriteSwap:
if (!(graphic is Image))
EditorGUILayout.HelpBox("需要Image组件来使用精灵切换", MessageType.Warning);
break;
case Selectable.Transition.Animation:
if (animation == null)
EditorGUILayout.HelpBox("需要Animation || Animator组件来使用动画切换", MessageType.Warning);
break;
}
// 绘制对应类型的属性
switch (currentTransition)
{
case Selectable.Transition.ColorTint:
CheckAndSetColorDefaults(colorBlock, targetGraphic);
EditorGUILayout.PropertyField(colorBlock);
break;
case Selectable.Transition.SpriteSwap:
EditorGUILayout.PropertyField(spriteState);
break;
case Selectable.Transition.Animation:
EditorGUILayout.PropertyField(animationTriggers);
break;
}
if ((int)currentTransition != transition.enumValueIndex)
{
graphic.canvasRenderer.SetColor(graphic.color);
graphic.color = graphic.color;
}
EditorGUI.indentLevel--;
}
void CheckAndSetColorDefaults(SerializedProperty colorBlock, SerializedProperty targetGraphic)
{
bool isDirty = false;
string[] colorProps = new string[] { "m_NormalColor", "m_HighlightedColor", "m_PressedColor", "m_SelectedColor", "m_DisabledColor" };
foreach (var propName in colorProps)
{
SerializedProperty prop = colorBlock.FindPropertyRelative(propName);
Color color = prop.colorValue;
if (color.r == 0 && color.g == 0 && color.b == 0 && color.a == 0)
{
isDirty = true;
if (prop.name == "m_PressedColor")
{
prop.colorValue = new Color(0.7843137f, 0.7843137f, 0.7843137f, 1.0f);
}
else if (prop.name == "m_DisabledColor")
{
prop.colorValue = new Color(0.7843137f, 0.7843137f, 0.7843137f, 0.5f);
}
else
{
prop.colorValue = Color.white;
}
}
}
SerializedProperty fadeDuration = colorBlock.FindPropertyRelative("m_FadeDuration");
SerializedProperty m_ColorMultiplier = colorBlock.FindPropertyRelative("m_ColorMultiplier");
if (isDirty)
{
m_ColorMultiplier.floatValue = 1f;
fadeDuration.floatValue = 0.1f;
}
var graphic = targetGraphic.objectReferenceValue as Graphic;
if (graphic != null)
{
if (!EditorApplication.isPlaying)
{
Color color = colorBlock.FindPropertyRelative("m_NormalColor").colorValue;
graphic.canvasRenderer.SetColor(color);
}
else if (m_SelectionState.enumValueIndex == 0)
{
Color color = colorBlock.FindPropertyRelative("m_NormalColor").colorValue;
graphic.canvasRenderer.SetColor(color);
}
}
}
private void DrawSelfTransition()
{
EditorGUILayout.LabelField("Main Transition", EditorStyles.boldLabel);
SerializedProperty targetGraphic = m_TransitionData.FindPropertyRelative("targetGraphic");
var graphic = targetGraphic.objectReferenceValue as Graphic;
if (graphic == null)
{
graphic = (target as UXButton).GetComponent<Graphic>();
targetGraphic.objectReferenceValue = graphic;
}
EditorGUI.indentLevel++;
DrawTransitionData(m_TransitionData);
EditorGUI.indentLevel--;
EditorGUILayout.Space();
}
static Selectable.Transition GetTransition(SerializedProperty transition)
{
return (Selectable.Transition)transition.enumValueIndex;
}
}
#endif