com.alicizax.unity.ui.exten.../Editor/UX/Controller/UXControllerEditor.cs
2026-03-11 15:23:44 +08:00

425 lines
14 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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<int, bool> _controllerFoldouts = new Dictionary<int, bool>();
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<int, bool>();
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();
}
}
}