com.alicizax.unity.ui.exten.../Editor/UX/Controller/UXControllerEditor.cs

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 Controller", _headerStyle, GUILayout.Width(130));
EditorGUILayout.LabelField($"Controllers: {_controllersProp.arraySize}", EditorStyles.miniLabel);
GUILayout.FlexibleSpace();
if (GUILayout.Button("+ Add Controller", 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("Preview Mode", _previewMode);
if (EditorGUI.EndChangeCheck())
{
if (!_previewMode)
{
ResetAllControllers(controller);
}
}
if (_previewMode)
{
GUILayout.FlexibleSpace();
if (GUILayout.Button("Reset All", GUILayout.Width(80)))
{
ResetAllControllers(controller);
}
}
EditorGUILayout.EndHorizontal();
if (_previewMode)
{
EditorGUILayout.HelpBox("Preview mode active. Click state buttons to preview.", MessageType.Info);
}
EditorGUILayout.EndVertical();
}
private void DrawToolbar()
{
EditorGUILayout.BeginHorizontal(_toolbarStyle);
if (GUILayout.Button("Expand All", EditorStyles.toolbarButton, GUILayout.Width(70)))
{
for (int i = 0; i < _controllersProp.arraySize; i++)
{
_controllerFoldouts[i] = true;
}
}
if (GUILayout.Button("Collapse All", EditorStyles.toolbarButton, GUILayout.Width(75)))
{
_controllerFoldouts.Clear();
}
GUILayout.FlexibleSpace();
EditorGUILayout.EndHorizontal();
}
private void DrawControllersList(UXController controller)
{
if (_controllersProp.arraySize == 0)
{
EditorGUILayout.HelpBox("No controllers defined. Click '+ Add Controller' to create one.", 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("Name", GUILayout.Width(70));
nameProp.stringValue = EditorGUILayout.TextField(nameProp.stringValue);
EditorGUILayout.EndHorizontal();
// Length
EditorGUILayout.BeginHorizontal();
EditorGUILayout.LabelField("Length", GUILayout.Width(70));
lengthProp.intValue = Mathf.Max(1, EditorGUILayout.IntField(lengthProp.intValue));
EditorGUILayout.EndHorizontal();
// Description
EditorGUILayout.BeginHorizontal();
EditorGUILayout.LabelField("Description", 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("Delete Controller",
$"Delete controller '{nameProp.stringValue}'?", "Delete", "Cancel"))
{
DeleteController(index);
}
}
EditorGUILayout.EndHorizontal();
}
private void DrawControllerPreview(UXController controller, int controllerIndex, int length)
{
EditorGUILayout.BeginVertical(EditorStyles.helpBox);
EditorGUILayout.LabelField("Preview", EditorStyles.boldLabel);
var handle = controller.GetControllerAt(controllerIndex);
if (handle != null)
{
int currentIndex = handle.SelectedIndex;
EditorGUILayout.BeginHorizontal();
EditorGUILayout.LabelField($"State: {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, $"State Recorders ({controller.Recorders.Count})", true);
EditorGUILayout.EndHorizontal();
if (_showRecorders)
{
if (controller.Recorders.Count == 0)
{
EditorGUILayout.HelpBox("No state recorders attached.", 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($"States: {recorder.StateEntries.Count}", GUILayout.Width(60));
if (GUILayout.Button("Select", 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 += " Copy";
_controllerFoldouts[index + 1] = true;
}
private void DeleteController(int index)
{
if (index < 0 || index >= _controllersProp.arraySize)
{
return;
}
Undo.RecordObject(serializedObject.targetObject, "Delete Controller");
_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();
}
}
}