269 lines
8.9 KiB
C#
269 lines
8.9 KiB
C#
#if UNITY_EDITOR
|
|
using System.Collections.Generic;
|
|
using UnityEditor;
|
|
using UnityEngine;
|
|
|
|
namespace UnityEngine.UI
|
|
{
|
|
public sealed class UXControllerSceneOverlayWindow : EditorWindow
|
|
{
|
|
private const string OverlayEnabledKey = "AlicizaX.UI.UXControllerSceneOverlay.Enabled";
|
|
private const string MenuPath = "Window/UX/Controller Scene Overlay";
|
|
private const float OverlayWidth = 340f;
|
|
private const float OverlayMargin = 10f;
|
|
|
|
private static bool s_overlayEnabled;
|
|
private static Vector2 s_scrollPosition;
|
|
private static bool s_registered;
|
|
private static readonly List<UXController> Controllers = new List<UXController>();
|
|
private static GUIStyle s_indexOnStyle;
|
|
private static GUIStyle s_indexOffStyle;
|
|
|
|
[MenuItem(MenuPath)]
|
|
public static void ToggleOverlay()
|
|
{
|
|
s_overlayEnabled = !s_overlayEnabled;
|
|
EditorPrefs.SetBool(OverlayEnabledKey, s_overlayEnabled);
|
|
Menu.SetChecked(MenuPath, s_overlayEnabled);
|
|
EnsureRegistered();
|
|
SceneView.RepaintAll();
|
|
}
|
|
|
|
[MenuItem(MenuPath, true)]
|
|
private static bool ToggleOverlayValidate()
|
|
{
|
|
Menu.SetChecked(MenuPath, s_overlayEnabled);
|
|
return true;
|
|
}
|
|
|
|
[InitializeOnLoadMethod]
|
|
private static void Initialize()
|
|
{
|
|
s_overlayEnabled = EditorPrefs.GetBool(OverlayEnabledKey, false);
|
|
Menu.SetChecked(MenuPath, s_overlayEnabled);
|
|
EnsureRegistered();
|
|
}
|
|
|
|
private static void EnsureRegistered()
|
|
{
|
|
if (s_registered)
|
|
{
|
|
return;
|
|
}
|
|
|
|
SceneView.duringSceneGui += OnSceneGui;
|
|
s_registered = true;
|
|
}
|
|
|
|
private static void OnSceneGui(SceneView sceneView)
|
|
{
|
|
if (!s_overlayEnabled)
|
|
{
|
|
return;
|
|
}
|
|
|
|
GetSceneControllers(Controllers);
|
|
|
|
Handles.BeginGUI();
|
|
float height = Mathf.Min(Mathf.Max(180f, sceneView.position.height - OverlayMargin * 2f), 520f);
|
|
Rect area = new Rect(
|
|
sceneView.position.width - OverlayWidth - OverlayMargin,
|
|
OverlayMargin,
|
|
OverlayWidth,
|
|
height);
|
|
|
|
GUILayout.BeginArea(area, GUI.skin.window);
|
|
DrawOverlayContent(Controllers);
|
|
GUILayout.EndArea();
|
|
Handles.EndGUI();
|
|
}
|
|
|
|
private static void DrawOverlayContent(List<UXController> controllers)
|
|
{
|
|
EnsureStyles();
|
|
|
|
EditorGUILayout.BeginHorizontal();
|
|
EditorGUILayout.LabelField("UX Controller Preview", EditorStyles.boldLabel);
|
|
EditorGUILayout.LabelField(controllers.Count.ToString(), EditorStyles.miniBoldLabel, GUILayout.Width(24f));
|
|
GUILayout.FlexibleSpace();
|
|
if (GUILayout.Button("X", EditorStyles.miniButton, GUILayout.Width(22f)))
|
|
{
|
|
s_overlayEnabled = false;
|
|
EditorPrefs.SetBool(OverlayEnabledKey, s_overlayEnabled);
|
|
Menu.SetChecked(MenuPath, false);
|
|
SceneView.RepaintAll();
|
|
}
|
|
EditorGUILayout.EndHorizontal();
|
|
|
|
EditorGUILayout.Space(2f);
|
|
|
|
if (controllers.Count == 0)
|
|
{
|
|
EditorGUILayout.HelpBox("No UXController in loaded scenes.", MessageType.Info);
|
|
return;
|
|
}
|
|
|
|
s_scrollPosition = EditorGUILayout.BeginScrollView(s_scrollPosition);
|
|
|
|
for (int i = 0; i < controllers.Count; i++)
|
|
{
|
|
DrawControllerCard(controllers[i], i);
|
|
EditorGUILayout.Space(4f);
|
|
}
|
|
|
|
EditorGUILayout.EndScrollView();
|
|
}
|
|
|
|
private static void DrawControllerCard(UXController controller, int index)
|
|
{
|
|
if (controller == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
EditorGUILayout.BeginVertical(EditorStyles.helpBox);
|
|
|
|
EditorGUILayout.BeginHorizontal();
|
|
EditorGUILayout.LabelField(controller.gameObject.name, EditorStyles.boldLabel);
|
|
EditorGUILayout.LabelField($"C:{controller.ControllerCount} B:{controller.Bindings.Count}", EditorStyles.miniLabel, GUILayout.Width(72f));
|
|
GUILayout.FlexibleSpace();
|
|
|
|
if (GUILayout.Button("Ping", EditorStyles.miniButtonLeft, GUILayout.Width(42f)))
|
|
{
|
|
Selection.activeGameObject = controller.gameObject;
|
|
EditorGUIUtility.PingObject(controller.gameObject);
|
|
}
|
|
|
|
if (GUILayout.Button("Reset", EditorStyles.miniButtonRight, GUILayout.Width(44f)))
|
|
{
|
|
controller.ResetAllControllers();
|
|
EditorUtility.SetDirty(controller);
|
|
SceneView.RepaintAll();
|
|
}
|
|
EditorGUILayout.EndHorizontal();
|
|
|
|
EditorGUILayout.LabelField(GetHierarchyPath(controller.transform), EditorStyles.miniLabel);
|
|
|
|
for (int controllerIndex = 0; controllerIndex < controller.ControllerCount; controllerIndex++)
|
|
{
|
|
UXController.ControllerDefinition definition = controller.GetControllerAt(controllerIndex);
|
|
if (definition == null)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
DrawDefinitionPreview(controller, definition);
|
|
}
|
|
|
|
EditorGUILayout.EndVertical();
|
|
}
|
|
|
|
private static void DrawDefinitionPreview(UXController controller, UXController.ControllerDefinition definition)
|
|
{
|
|
int currentIndex = Mathf.Max(0, definition.SelectedIndex);
|
|
int length = Mathf.Max(1, definition.Length);
|
|
|
|
EditorGUILayout.BeginHorizontal();
|
|
EditorGUILayout.LabelField(definition.Name, EditorStyles.miniBoldLabel, GUILayout.Width(96f));
|
|
for (int i = 0; i < length; i++)
|
|
{
|
|
bool selected = i == currentIndex;
|
|
GUIStyle style = selected ? s_indexOnStyle : s_indexOffStyle;
|
|
if (GUILayout.Toggle(selected, i.ToString(), style, GUILayout.Width(26f)) != selected)
|
|
{
|
|
controller.SetControllerIndex(definition.Id, i);
|
|
EditorUtility.SetDirty(controller);
|
|
SceneView.RepaintAll();
|
|
}
|
|
}
|
|
EditorGUILayout.EndHorizontal();
|
|
|
|
if (!string.IsNullOrWhiteSpace(definition.Description))
|
|
{
|
|
EditorGUILayout.LabelField(definition.Description, EditorStyles.miniLabel);
|
|
}
|
|
}
|
|
|
|
private static void GetSceneControllers(List<UXController> results)
|
|
{
|
|
results.Clear();
|
|
UXController[] allControllers = Resources.FindObjectsOfTypeAll<UXController>();
|
|
|
|
for (int i = 0; i < allControllers.Length; i++)
|
|
{
|
|
UXController controller = allControllers[i];
|
|
if (controller == null)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (EditorUtility.IsPersistent(controller))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (!controller.gameObject.scene.IsValid() || !controller.gameObject.scene.isLoaded)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if ((controller.hideFlags & HideFlags.HideInHierarchy) != 0)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
results.Add(controller);
|
|
}
|
|
|
|
results.Sort(CompareControllers);
|
|
}
|
|
|
|
private static int CompareControllers(UXController left, UXController right)
|
|
{
|
|
return string.CompareOrdinal(GetHierarchyPath(left.transform), GetHierarchyPath(right.transform));
|
|
}
|
|
|
|
private static void EnsureStyles()
|
|
{
|
|
if (s_indexOnStyle != null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
s_indexOnStyle = new GUIStyle(EditorStyles.miniButton)
|
|
{
|
|
fontStyle = FontStyle.Bold,
|
|
fixedHeight = 18f,
|
|
margin = new RectOffset(1, 1, 1, 1),
|
|
padding = new RectOffset(2, 2, 1, 1)
|
|
};
|
|
|
|
s_indexOffStyle = new GUIStyle(EditorStyles.miniButton)
|
|
{
|
|
fixedHeight = 18f,
|
|
margin = new RectOffset(1, 1, 1, 1),
|
|
padding = new RectOffset(2, 2, 1, 1)
|
|
};
|
|
}
|
|
|
|
private static string GetHierarchyPath(Transform target)
|
|
{
|
|
if (target == null)
|
|
{
|
|
return string.Empty;
|
|
}
|
|
|
|
string path = target.name;
|
|
Transform current = target.parent;
|
|
while (current != null)
|
|
{
|
|
path = $"{current.name}/{path}";
|
|
current = current.parent;
|
|
}
|
|
|
|
return path;
|
|
}
|
|
}
|
|
}
|
|
#endif
|