using UnityEditor; using UnityEngine; using AlicizaX.UI; using System.Collections.Generic; namespace AlicizaX.UI { [CustomEditor(typeof(UXController))] public class UXControllerEditor : UnityEditor.Editor { private SerializedProperty _controllersProp; private bool _showRecorders = true; private bool _previewMode = false; private Dictionary _controllerFoldouts = new Dictionary(); private GUIStyle _headerStyle; private GUIStyle _toolbarStyle; private GUIStyle _controllerHeaderStyle; private void OnEnable() { _controllersProp = serializedObject.FindProperty("_controllers"); } private void InitStyles() { if (_headerStyle == null) { _headerStyle = new GUIStyle(EditorStyles.boldLabel) { fontSize = 13, fontStyle = FontStyle.Bold }; } if (_toolbarStyle == null) { _toolbarStyle = new GUIStyle(EditorStyles.toolbar) { fixedHeight = 25 }; } if (_controllerHeaderStyle == null) { _controllerHeaderStyle = new GUIStyle(EditorStyles.foldout) { fontStyle = FontStyle.Bold }; } } public override void OnInspectorGUI() { InitStyles(); serializedObject.Update(); var controller = target as UXController; // Header DrawHeader(); EditorGUILayout.Space(5); // Preview Mode DrawPreviewMode(controller); EditorGUILayout.Space(5); // Toolbar DrawToolbar(); EditorGUILayout.Space(5); // Controllers List DrawControllersList(controller); EditorGUILayout.Space(5); // Recorders Section DrawRecorders(controller); serializedObject.ApplyModifiedProperties(); } private void DrawHeader() { EditorGUILayout.BeginVertical(EditorStyles.helpBox); EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField("UX 控制器", _headerStyle, GUILayout.Width(130)); EditorGUILayout.LabelField($"控制器数量: {_controllersProp.arraySize}", EditorStyles.miniLabel); GUILayout.FlexibleSpace(); if (GUILayout.Button("+ 添加控制器", GUILayout.Width(110))) { AddNewController(); } EditorGUILayout.EndHorizontal(); EditorGUILayout.EndVertical(); } private void DrawPreviewMode(UXController controller) { Color oldColor = GUI.backgroundColor; if (_previewMode) GUI.backgroundColor = new Color(0.5f, 1f, 0.5f); EditorGUILayout.BeginVertical(EditorStyles.helpBox); GUI.backgroundColor = oldColor; EditorGUILayout.BeginHorizontal(); EditorGUI.BeginChangeCheck(); _previewMode = EditorGUILayout.Toggle("预览模式", _previewMode); if (EditorGUI.EndChangeCheck()) { if (!_previewMode) { ResetAllControllers(controller); } } if (_previewMode) { GUILayout.FlexibleSpace(); if (GUILayout.Button("重置全部", GUILayout.Width(80))) { ResetAllControllers(controller); } } EditorGUILayout.EndHorizontal(); if (_previewMode) { EditorGUILayout.HelpBox("预览模式已激活。点击状态按钮进行预览。", MessageType.Info); } EditorGUILayout.EndVertical(); } private void DrawToolbar() { EditorGUILayout.BeginHorizontal(_toolbarStyle); if (GUILayout.Button("全部展开", EditorStyles.toolbarButton, GUILayout.Width(70))) { for (int i = 0; i < _controllersProp.arraySize; i++) { _controllerFoldouts[i] = true; } } if (GUILayout.Button("全部折叠", EditorStyles.toolbarButton, GUILayout.Width(75))) { _controllerFoldouts.Clear(); } GUILayout.FlexibleSpace(); EditorGUILayout.EndHorizontal(); } private void DrawControllersList(UXController controller) { if (_controllersProp.arraySize == 0) { EditorGUILayout.HelpBox("未定义控制器。点击 '+ 添加控制器' 创建一个。", MessageType.Info); return; } for (int i = 0; i < _controllersProp.arraySize; i++) { DrawControllerEntry(controller, i); EditorGUILayout.Space(3); } } private void DrawControllerEntry(UXController controller, int index) { var element = _controllersProp.GetArrayElementAtIndex(index); var nameProp = element.FindPropertyRelative("_name"); var lengthProp = element.FindPropertyRelative("_length"); var descProp = element.FindPropertyRelative("_description"); if (!_controllerFoldouts.ContainsKey(index)) { _controllerFoldouts[index] = false; } bool isFolded = _controllerFoldouts[index]; EditorGUILayout.BeginVertical(EditorStyles.helpBox); // Header DrawControllerHeader(index, nameProp, ref isFolded); _controllerFoldouts[index] = isFolded; // Expanded Content if (isFolded) { EditorGUI.indentLevel++; // Name EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField("名称", GUILayout.Width(70)); nameProp.stringValue = EditorGUILayout.TextField(nameProp.stringValue); EditorGUILayout.EndHorizontal(); // Length EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField("长度", GUILayout.Width(70)); lengthProp.intValue = Mathf.Max(1, EditorGUILayout.IntField(lengthProp.intValue)); EditorGUILayout.EndHorizontal(); // Description EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField("描述", GUILayout.Width(70)); descProp.stringValue = EditorGUILayout.TextField(descProp.stringValue); EditorGUILayout.EndHorizontal(); // Preview if (_previewMode && !Application.isPlaying) { EditorGUILayout.Space(5); DrawControllerPreview(controller, index, lengthProp.intValue); } EditorGUI.indentLevel--; } EditorGUILayout.EndVertical(); } private void DrawControllerHeader(int index, SerializedProperty nameProp, ref bool isFolded) { EditorGUILayout.BeginHorizontal(); // Foldout isFolded = EditorGUILayout.Foldout(isFolded, $"[{index}] {nameProp.stringValue}", true, _controllerHeaderStyle); GUILayout.FlexibleSpace(); // Buttons if (GUILayout.Button("▲", EditorStyles.miniButtonLeft, GUILayout.Width(25)) && index > 0) { _controllersProp.MoveArrayElement(index, index - 1); GUIUtility.ExitGUI(); } if (GUILayout.Button("▼", EditorStyles.miniButtonMid, GUILayout.Width(25)) && index < _controllersProp.arraySize - 1) { _controllersProp.MoveArrayElement(index, index + 1); GUIUtility.ExitGUI(); } if (GUILayout.Button("⎘", EditorStyles.miniButtonMid, GUILayout.Width(25))) { DuplicateController(index); GUIUtility.ExitGUI(); } if (GUILayout.Button("×", EditorStyles.miniButtonRight, GUILayout.Width(25))) { if (EditorUtility.DisplayDialog("删除控制器", $"删除控制器 '{nameProp.stringValue}'?", "删除", "取消")) { DeleteController(index); } } EditorGUILayout.EndHorizontal(); } private void DrawControllerPreview(UXController controller, int controllerIndex, int length) { EditorGUILayout.BeginVertical(EditorStyles.helpBox); EditorGUILayout.LabelField("预览", EditorStyles.boldLabel); var handle = controller.GetControllerAt(controllerIndex); if (handle != null) { int currentIndex = handle.SelectedIndex; EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField($"状态: {currentIndex}", GUILayout.Width(60)); string[] options = new string[length]; for (int i = 0; i < length; i++) { options[i] = i.ToString(); } EditorGUI.BeginChangeCheck(); int newIndex = GUILayout.SelectionGrid(currentIndex, options, Mathf.Min(length, 6)); if (EditorGUI.EndChangeCheck()) { controller.SetControllerIndexInternal(controllerIndex, newIndex); EditorUtility.SetDirty(controller); SceneView.RepaintAll(); } EditorGUILayout.EndHorizontal(); } EditorGUILayout.EndVertical(); } private void DrawRecorders(UXController controller) { EditorGUILayout.BeginVertical(EditorStyles.helpBox); EditorGUILayout.BeginHorizontal(); _showRecorders = EditorGUILayout.Foldout(_showRecorders, $"状态记录器 ({controller.Recorders.Count})", true); EditorGUILayout.EndHorizontal(); if (_showRecorders) { if (controller.Recorders.Count == 0) { EditorGUILayout.HelpBox("未附加状态记录器。", MessageType.Info); } else { EditorGUI.indentLevel++; for (int i = 0; i < controller.Recorders.Count; i++) { DrawRecorderEntry(controller.Recorders[i], i); } EditorGUI.indentLevel--; } } EditorGUILayout.EndVertical(); } private void DrawRecorderEntry(UXControllerStateRecorder recorder, int index) { if (recorder == null) return; EditorGUILayout.BeginHorizontal(EditorStyles.helpBox); EditorGUILayout.LabelField($"[{index}]", GUILayout.Width(30)); EditorGUILayout.LabelField($"ID: {recorder.ID}", GUILayout.Width(100)); EditorGUI.BeginDisabledGroup(true); EditorGUILayout.ObjectField(recorder, typeof(UXControllerStateRecorder), true); EditorGUI.EndDisabledGroup(); EditorGUILayout.LabelField($"状态数: {recorder.StateEntries.Count}", GUILayout.Width(60)); if (GUILayout.Button("选择", GUILayout.Width(60))) { Selection.activeGameObject = recorder.gameObject; } EditorGUILayout.EndHorizontal(); } private void AddNewController() { _controllersProp.arraySize++; var newElement = _controllersProp.GetArrayElementAtIndex(_controllersProp.arraySize - 1); newElement.FindPropertyRelative("_name").stringValue = $"Controller{_controllersProp.arraySize}"; newElement.FindPropertyRelative("_length").intValue = 2; newElement.FindPropertyRelative("_description").stringValue = ""; _controllerFoldouts[_controllersProp.arraySize - 1] = true; } private void DuplicateController(int index) { _controllersProp.InsertArrayElementAtIndex(index); var newProp = _controllersProp.GetArrayElementAtIndex(index + 1); var nameProp = newProp.FindPropertyRelative("_name"); nameProp.stringValue += " 副本"; _controllerFoldouts[index + 1] = true; } private void DeleteController(int index) { if (index < 0 || index >= _controllersProp.arraySize) { return; } Undo.RecordObject(serializedObject.targetObject, "删除控制器"); _controllersProp.DeleteArrayElementAtIndex(index); _controllerFoldouts.Remove(index); // Rebuild foldout dictionary with corrected indices var newFoldouts = new Dictionary(); foreach (var kvp in _controllerFoldouts) { if (kvp.Key < index) { newFoldouts[kvp.Key] = kvp.Value; } else if (kvp.Key > index) { newFoldouts[kvp.Key - 1] = kvp.Value; } } _controllerFoldouts = newFoldouts; serializedObject.ApplyModifiedProperties(); EditorUtility.SetDirty(serializedObject.targetObject); GUIUtility.ExitGUI(); } private void ResetAllControllers(UXController controller) { for (int i = 0; i < controller.ControllerCount; i++) { controller.SetControllerIndexInternal(i, 0); } EditorUtility.SetDirty(controller); SceneView.RepaintAll(); } } }