267 lines
9.9 KiB
C#
267 lines
9.9 KiB
C#
#if UNITY_EDITOR
|
|
using System.Collections.Generic;
|
|
using UnityEditor;
|
|
using UnityEngine;
|
|
|
|
namespace UnityEngine.UI
|
|
{
|
|
[CustomEditor(typeof(UXController))]
|
|
public sealed class UXControllerEditor : UnityEditor.Editor
|
|
{
|
|
private SerializedProperty _controllersProp;
|
|
private SerializedProperty _bindingsProp;
|
|
private readonly Dictionary<int, bool> _foldouts = new Dictionary<int, bool>();
|
|
|
|
private void OnEnable()
|
|
{
|
|
_controllersProp = serializedObject.FindProperty("_controllers");
|
|
_bindingsProp = serializedObject.FindProperty("_bindings");
|
|
}
|
|
|
|
public override void OnInspectorGUI()
|
|
{
|
|
serializedObject.Update();
|
|
|
|
var controller = (UXController)target;
|
|
|
|
DrawHeader(controller);
|
|
EditorGUILayout.Space(6f);
|
|
DrawControllers(controller);
|
|
EditorGUILayout.Space(6f);
|
|
DrawBindings();
|
|
|
|
serializedObject.ApplyModifiedProperties();
|
|
}
|
|
|
|
private void DrawHeader(UXController controller)
|
|
{
|
|
EditorGUILayout.BeginVertical(EditorStyles.helpBox);
|
|
EditorGUILayout.LabelField("UX Controller", EditorStyles.boldLabel);
|
|
EditorGUILayout.LabelField($"Controllers: {_controllersProp.arraySize}", EditorStyles.miniLabel);
|
|
EditorGUILayout.LabelField($"Bindings: {_bindingsProp.arraySize}", EditorStyles.miniLabel);
|
|
|
|
EditorGUILayout.BeginHorizontal();
|
|
if (GUILayout.Button("Add Controller"))
|
|
{
|
|
AddController();
|
|
}
|
|
|
|
if (GUILayout.Button("Reset Preview"))
|
|
{
|
|
controller.ResetAllControllers();
|
|
EditorUtility.SetDirty(controller);
|
|
SceneView.RepaintAll();
|
|
}
|
|
EditorGUILayout.EndHorizontal();
|
|
EditorGUILayout.EndVertical();
|
|
}
|
|
|
|
private void DrawControllers(UXController controller)
|
|
{
|
|
if (_controllersProp.arraySize == 0)
|
|
{
|
|
EditorGUILayout.HelpBox("No controllers yet. Add one to start driving bindings.", MessageType.Info);
|
|
return;
|
|
}
|
|
|
|
for (int i = 0; i < _controllersProp.arraySize; i++)
|
|
{
|
|
DrawController(controller, i);
|
|
EditorGUILayout.Space(4f);
|
|
}
|
|
}
|
|
|
|
private void DrawController(UXController controller, int index)
|
|
{
|
|
SerializedProperty entryProp = _controllersProp.GetArrayElementAtIndex(index);
|
|
SerializedProperty idProp = entryProp.FindPropertyRelative("_id");
|
|
SerializedProperty nameProp = entryProp.FindPropertyRelative("_name");
|
|
SerializedProperty lengthProp = entryProp.FindPropertyRelative("_length");
|
|
SerializedProperty descriptionProp = entryProp.FindPropertyRelative("_description");
|
|
|
|
bool expanded = _foldouts.ContainsKey(index) && _foldouts[index];
|
|
|
|
EditorGUILayout.BeginVertical(EditorStyles.helpBox);
|
|
EditorGUILayout.BeginHorizontal();
|
|
expanded = EditorGUILayout.Foldout(expanded, $"[{index}] {nameProp.stringValue}", true);
|
|
GUILayout.FlexibleSpace();
|
|
|
|
if (GUILayout.Button("Up", EditorStyles.miniButtonLeft, GUILayout.Width(34f)) && index > 0)
|
|
{
|
|
_controllersProp.MoveArrayElement(index, index - 1);
|
|
GUIUtility.ExitGUI();
|
|
}
|
|
|
|
if (GUILayout.Button("Down", EditorStyles.miniButtonMid, GUILayout.Width(44f)) && index < _controllersProp.arraySize - 1)
|
|
{
|
|
_controllersProp.MoveArrayElement(index, index + 1);
|
|
GUIUtility.ExitGUI();
|
|
}
|
|
|
|
if (GUILayout.Button("X", EditorStyles.miniButtonRight, GUILayout.Width(24f)))
|
|
{
|
|
DeleteController(controller, index);
|
|
}
|
|
EditorGUILayout.EndHorizontal();
|
|
|
|
_foldouts[index] = expanded;
|
|
|
|
if (expanded)
|
|
{
|
|
EditorGUILayout.PropertyField(nameProp, new GUIContent("Name"));
|
|
lengthProp.intValue = Mathf.Max(1, EditorGUILayout.IntField("Length", Mathf.Max(1, lengthProp.intValue)));
|
|
EditorGUILayout.PropertyField(descriptionProp, new GUIContent("Description"));
|
|
|
|
EditorGUI.BeginDisabledGroup(true);
|
|
EditorGUILayout.TextField("Id", idProp.stringValue);
|
|
EditorGUI.EndDisabledGroup();
|
|
|
|
UXController.ControllerDefinition definition = controller.GetControllerAt(index);
|
|
if (definition != null)
|
|
{
|
|
DrawPreview(controller, definition);
|
|
}
|
|
}
|
|
|
|
EditorGUILayout.EndVertical();
|
|
}
|
|
|
|
private void DrawPreview(UXController controller, UXController.ControllerDefinition definition)
|
|
{
|
|
EditorGUILayout.Space(4f);
|
|
EditorGUILayout.LabelField("Preview", EditorStyles.boldLabel);
|
|
|
|
int currentIndex = Mathf.Max(0, definition.SelectedIndex);
|
|
int length = Mathf.Max(1, definition.Length);
|
|
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.SetControllerIndex(definition.Id, newIndex);
|
|
EditorUtility.SetDirty(controller);
|
|
SceneView.RepaintAll();
|
|
}
|
|
}
|
|
|
|
private void DrawBindings()
|
|
{
|
|
EditorGUILayout.BeginVertical(EditorStyles.helpBox);
|
|
EditorGUILayout.LabelField("Registered Bindings", EditorStyles.boldLabel);
|
|
|
|
if (_bindingsProp.arraySize == 0)
|
|
{
|
|
EditorGUILayout.HelpBox("No UXBinding components are registered under this controller.", MessageType.Info);
|
|
}
|
|
else
|
|
{
|
|
for (int i = 0; i < _bindingsProp.arraySize; i++)
|
|
{
|
|
SerializedProperty bindingProp = _bindingsProp.GetArrayElementAtIndex(i);
|
|
EditorGUI.BeginDisabledGroup(true);
|
|
EditorGUILayout.ObjectField($"Binding {i}", bindingProp.objectReferenceValue, typeof(UXBinding), true);
|
|
EditorGUI.EndDisabledGroup();
|
|
}
|
|
}
|
|
|
|
EditorGUILayout.EndVertical();
|
|
}
|
|
|
|
private void AddController()
|
|
{
|
|
int index = _controllersProp.arraySize;
|
|
_controllersProp.InsertArrayElementAtIndex(index);
|
|
|
|
SerializedProperty entryProp = _controllersProp.GetArrayElementAtIndex(index);
|
|
entryProp.FindPropertyRelative("_id").stringValue = string.Empty;
|
|
entryProp.FindPropertyRelative("_name").stringValue = $"Controller {index + 1}";
|
|
entryProp.FindPropertyRelative("_length").intValue = 2;
|
|
entryProp.FindPropertyRelative("_description").stringValue = string.Empty;
|
|
|
|
_foldouts[index] = true;
|
|
}
|
|
|
|
private void DeleteController(UXController controller, int index)
|
|
{
|
|
if (index < 0 || index >= _controllersProp.arraySize)
|
|
{
|
|
return;
|
|
}
|
|
|
|
SerializedProperty entryProp = _controllersProp.GetArrayElementAtIndex(index);
|
|
string deletedControllerId = entryProp.FindPropertyRelative("_id").stringValue;
|
|
|
|
Undo.RecordObject(controller, "Delete UX Controller");
|
|
_controllersProp.DeleteArrayElementAtIndex(index);
|
|
CleanupFoldouts(index);
|
|
serializedObject.ApplyModifiedProperties();
|
|
ClearBindingReferences(controller, deletedControllerId);
|
|
EditorUtility.SetDirty(controller);
|
|
GUIUtility.ExitGUI();
|
|
}
|
|
|
|
private void CleanupFoldouts(int removedIndex)
|
|
{
|
|
_foldouts.Remove(removedIndex);
|
|
|
|
var remapped = new Dictionary<int, bool>();
|
|
foreach (var pair in _foldouts)
|
|
{
|
|
int nextIndex = pair.Key > removedIndex ? pair.Key - 1 : pair.Key;
|
|
remapped[nextIndex] = pair.Value;
|
|
}
|
|
|
|
_foldouts.Clear();
|
|
foreach (var pair in remapped)
|
|
{
|
|
_foldouts[pair.Key] = pair.Value;
|
|
}
|
|
}
|
|
|
|
private static void ClearBindingReferences(UXController controller, string deletedControllerId)
|
|
{
|
|
if (controller == null || string.IsNullOrEmpty(deletedControllerId))
|
|
{
|
|
return;
|
|
}
|
|
|
|
IReadOnlyList<UXBinding> bindings = controller.Bindings;
|
|
for (int i = 0; i < bindings.Count; i++)
|
|
{
|
|
UXBinding binding = bindings[i];
|
|
if (binding == null)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
var so = new SerializedObject(binding);
|
|
SerializedProperty entriesProp = so.FindProperty("_entries");
|
|
bool changed = false;
|
|
|
|
for (int entryIndex = 0; entryIndex < entriesProp.arraySize; entryIndex++)
|
|
{
|
|
SerializedProperty bindingEntry = entriesProp.GetArrayElementAtIndex(entryIndex);
|
|
SerializedProperty controllerIdProp = bindingEntry.FindPropertyRelative("_controllerId");
|
|
if (controllerIdProp.stringValue == deletedControllerId)
|
|
{
|
|
controllerIdProp.stringValue = string.Empty;
|
|
changed = true;
|
|
}
|
|
}
|
|
|
|
if (changed)
|
|
{
|
|
so.ApplyModifiedProperties();
|
|
EditorUtility.SetDirty(binding);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif
|