275 lines
9.3 KiB
C#
275 lines
9.3 KiB
C#
#if UNITY_EDITOR
|
|
using System.Collections.Generic;
|
|
using UnityEditor;
|
|
using UnityEngine;
|
|
|
|
namespace AlicizaX.UI
|
|
{
|
|
public sealed class UXControllerSceneOverlayWindow : EditorWindow
|
|
{
|
|
private const string OverlayEnabledKey = "AlicizaX.UI.UXControllerSceneOverlay.Enabled";
|
|
private const string OverlayAutoFocusKey = "AlicizaX.UI.UXControllerSceneOverlay.AutoFocus";
|
|
private const float OverlayWidth = 360f;
|
|
private const float OverlayMargin = 12f;
|
|
|
|
private static bool s_overlayEnabled;
|
|
private static bool s_autoFocusSceneView;
|
|
private static Vector2 s_scrollPosition;
|
|
private static bool s_registered;
|
|
|
|
[MenuItem("Window/UX/Controller Scene Overlay")]
|
|
public static void ShowWindow()
|
|
{
|
|
var window = GetWindow<UXControllerSceneOverlayWindow>("UX Controller Overlay");
|
|
window.minSize = new Vector2(320f, 140f);
|
|
window.Show();
|
|
EnsureRegistered();
|
|
}
|
|
|
|
[InitializeOnLoadMethod]
|
|
private static void Initialize()
|
|
{
|
|
s_overlayEnabled = EditorPrefs.GetBool(OverlayEnabledKey, false);
|
|
s_autoFocusSceneView = EditorPrefs.GetBool(OverlayAutoFocusKey, false);
|
|
EnsureRegistered();
|
|
}
|
|
|
|
private static void EnsureRegistered()
|
|
{
|
|
if (s_registered)
|
|
{
|
|
return;
|
|
}
|
|
|
|
SceneView.duringSceneGui += OnSceneGui;
|
|
s_registered = true;
|
|
}
|
|
|
|
private void OnGUI()
|
|
{
|
|
EditorGUILayout.LabelField("Scene View Overlay", EditorStyles.boldLabel);
|
|
EditorGUILayout.HelpBox(
|
|
"When enabled, the Scene View will display all UXController components in the current loaded scenes and let you preview them directly.",
|
|
MessageType.Info);
|
|
|
|
EditorGUI.BeginChangeCheck();
|
|
bool overlayEnabled = EditorGUILayout.Toggle("Enable Overlay", s_overlayEnabled);
|
|
bool autoFocus = EditorGUILayout.Toggle("Focus SceneView On Open", s_autoFocusSceneView);
|
|
if (EditorGUI.EndChangeCheck())
|
|
{
|
|
s_overlayEnabled = overlayEnabled;
|
|
s_autoFocusSceneView = autoFocus;
|
|
EditorPrefs.SetBool(OverlayEnabledKey, s_overlayEnabled);
|
|
EditorPrefs.SetBool(OverlayAutoFocusKey, s_autoFocusSceneView);
|
|
SceneView.RepaintAll();
|
|
}
|
|
|
|
EditorGUILayout.Space(8f);
|
|
if (GUILayout.Button("Repaint Scene View"))
|
|
{
|
|
SceneView.RepaintAll();
|
|
}
|
|
|
|
if (GUILayout.Button("Open Scene View"))
|
|
{
|
|
SceneView.FocusWindowIfItsOpen<SceneView>();
|
|
}
|
|
}
|
|
|
|
private static void OnSceneGui(SceneView sceneView)
|
|
{
|
|
if (!s_overlayEnabled)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (s_autoFocusSceneView && sceneView != null)
|
|
{
|
|
s_autoFocusSceneView = false;
|
|
EditorPrefs.SetBool(OverlayAutoFocusKey, false);
|
|
sceneView.Focus();
|
|
}
|
|
|
|
List<UXController> controllers = GetSceneControllers();
|
|
|
|
Handles.BeginGUI();
|
|
float height = Mathf.Max(160f, sceneView.position.height - OverlayMargin * 2f);
|
|
Rect area = new Rect(
|
|
sceneView.position.width - OverlayWidth - OverlayMargin,
|
|
OverlayMargin,
|
|
OverlayWidth,
|
|
height);
|
|
|
|
GUILayout.BeginArea(area, EditorStyles.helpBox);
|
|
DrawOverlayContent(controllers);
|
|
GUILayout.EndArea();
|
|
Handles.EndGUI();
|
|
}
|
|
|
|
private static void DrawOverlayContent(List<UXController> controllers)
|
|
{
|
|
EditorGUILayout.BeginHorizontal();
|
|
EditorGUILayout.LabelField("UX Controllers", EditorStyles.boldLabel);
|
|
GUILayout.FlexibleSpace();
|
|
if (GUILayout.Button("Hide", GUILayout.Width(64f)))
|
|
{
|
|
s_overlayEnabled = false;
|
|
EditorPrefs.SetBool(OverlayEnabledKey, s_overlayEnabled);
|
|
SceneView.RepaintAll();
|
|
}
|
|
if (GUILayout.Button("Refresh", GUILayout.Width(64f)))
|
|
{
|
|
SceneView.RepaintAll();
|
|
}
|
|
EditorGUILayout.EndHorizontal();
|
|
|
|
EditorGUILayout.Space(4f);
|
|
|
|
if (controllers.Count == 0)
|
|
{
|
|
EditorGUILayout.HelpBox("No UXController found in the current 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($"{index + 1}. {controller.gameObject.name}", EditorStyles.boldLabel);
|
|
GUILayout.FlexibleSpace();
|
|
|
|
if (GUILayout.Button("Select", GUILayout.Width(52f)))
|
|
{
|
|
Selection.activeGameObject = controller.gameObject;
|
|
EditorGUIUtility.PingObject(controller.gameObject);
|
|
}
|
|
|
|
if (GUILayout.Button("Reset", GUILayout.Width(52f)))
|
|
{
|
|
controller.ResetAllControllers();
|
|
EditorUtility.SetDirty(controller);
|
|
SceneView.RepaintAll();
|
|
}
|
|
EditorGUILayout.EndHorizontal();
|
|
|
|
EditorGUILayout.LabelField(GetHierarchyPath(controller.transform), EditorStyles.miniLabel);
|
|
EditorGUILayout.LabelField($"Bindings: {controller.Bindings.Count}", 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)
|
|
{
|
|
EditorGUILayout.Space(3f);
|
|
EditorGUILayout.BeginVertical(EditorStyles.helpBox);
|
|
EditorGUILayout.LabelField(definition.Name, EditorStyles.boldLabel);
|
|
|
|
if (!string.IsNullOrWhiteSpace(definition.Description))
|
|
{
|
|
EditorGUILayout.LabelField(definition.Description, EditorStyles.miniLabel);
|
|
}
|
|
|
|
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, 5));
|
|
if (EditorGUI.EndChangeCheck())
|
|
{
|
|
controller.SetControllerIndex(definition.Id, newIndex);
|
|
EditorUtility.SetDirty(controller);
|
|
SceneView.RepaintAll();
|
|
}
|
|
|
|
EditorGUILayout.EndVertical();
|
|
}
|
|
|
|
private static List<UXController> GetSceneControllers()
|
|
{
|
|
var results = new List<UXController>();
|
|
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((left, right) => string.CompareOrdinal(GetHierarchyPath(left.transform), GetHierarchyPath(right.transform)));
|
|
return results;
|
|
}
|
|
|
|
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
|