清理项目目录,引入 InputModule 做多平台输入适配
This commit is contained in:
@@ -0,0 +1,237 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using SepCore.InputModule.Runtime;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem;
|
||||
|
||||
namespace SepCore.InputModule.Editor
|
||||
{
|
||||
public sealed class InputModuleDebugger : EditorWindow
|
||||
{
|
||||
private static readonly FieldInfo ContextStackField = typeof(InputModuleComponent).GetField("_contextStack", BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
private static readonly FieldInfo ActionMapsField = typeof(InputModuleComponent).GetField("_actionMaps", BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
private static readonly PropertyInfo StackItemsProperty = typeof(InputContextStack).GetProperty("Items", BindingFlags.Instance | BindingFlags.Public);
|
||||
private static readonly PropertyInfo StackCountProperty = typeof(InputContextStack).GetProperty("Count", BindingFlags.Instance | BindingFlags.Public);
|
||||
|
||||
private InputModuleComponent _target;
|
||||
private Vector2 _scrollPosition;
|
||||
private readonly Dictionary<InputContextId, bool> _mapFoldouts = new Dictionary<InputContextId, bool>();
|
||||
private double _nextRefresh;
|
||||
private const double RefreshInterval = 0.1;
|
||||
|
||||
[MenuItem("Window/Input Module Debugger")]
|
||||
public static void ShowWindow()
|
||||
{
|
||||
GetWindow<InputModuleDebugger>("Input Module");
|
||||
}
|
||||
|
||||
private void OnGUI()
|
||||
{
|
||||
double now = EditorApplication.timeSinceStartup;
|
||||
if (now >= _nextRefresh)
|
||||
{
|
||||
_nextRefresh = now + RefreshInterval;
|
||||
Repaint();
|
||||
}
|
||||
|
||||
_scrollPosition = EditorGUILayout.BeginScrollView(_scrollPosition);
|
||||
|
||||
DrawHeader();
|
||||
DrawRuntimeStatus();
|
||||
DrawContextStack();
|
||||
DrawActionMaps();
|
||||
|
||||
EditorGUILayout.EndScrollView();
|
||||
}
|
||||
|
||||
private void DrawHeader()
|
||||
{
|
||||
EditorGUILayout.Space(4);
|
||||
EditorGUILayout.LabelField("Input Module Debugger", EditorStyles.largeLabel);
|
||||
EditorGUILayout.Space(4);
|
||||
}
|
||||
|
||||
private void DrawRuntimeStatus()
|
||||
{
|
||||
if (_target == null)
|
||||
{
|
||||
_target = FindInputModuleComponent();
|
||||
}
|
||||
|
||||
if (_target == null)
|
||||
{
|
||||
EditorGUILayout.HelpBox("No InputModuleComponent found in the current scene.", MessageType.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
EditorGUILayout.LabelField("Runtime Status", EditorStyles.boldLabel);
|
||||
|
||||
EditorGUI.BeginDisabledGroup(true);
|
||||
EditorGUILayout.Toggle("Initialized", _target.IsInitialized);
|
||||
EditorGUILayout.EnumPopup("Device Kind", _target.CurrentDeviceKind);
|
||||
EditorGUILayout.EnumPopup("Current Context", _target.CurrentContext);
|
||||
EditorGUILayout.Toggle("Rebinding", _target.IsRebinding);
|
||||
EditorGUI.EndDisabledGroup();
|
||||
|
||||
EditorGUILayout.Space(8);
|
||||
}
|
||||
|
||||
private void DrawContextStack()
|
||||
{
|
||||
if (_target == null || !_target.IsInitialized)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
object stack = ContextStackField?.GetValue(_target);
|
||||
if (stack == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int count = StackCountProperty != null ? (int)StackCountProperty.GetValue(stack) : 0;
|
||||
IReadOnlyList<InputContextId> items = StackItemsProperty?.GetValue(stack) as IReadOnlyList<InputContextId>;
|
||||
|
||||
EditorGUILayout.LabelField($"Context Stack (depth: {count})", EditorStyles.boldLabel);
|
||||
|
||||
if (items == null || count == 0)
|
||||
{
|
||||
EditorGUILayout.LabelField(" (empty)", EditorStyles.miniLabel);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < items.Count; i++)
|
||||
{
|
||||
bool isTop = i == items.Count - 1;
|
||||
string prefix = isTop ? "▶" : " ";
|
||||
GUIStyle style = isTop ? EditorStyles.label : EditorStyles.miniLabel;
|
||||
EditorGUILayout.LabelField($" {prefix} [{i}] {items[i]}", style);
|
||||
}
|
||||
}
|
||||
|
||||
EditorGUILayout.Space(8);
|
||||
}
|
||||
|
||||
private void DrawActionMaps()
|
||||
{
|
||||
if (_target == null || !_target.IsInitialized)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
object mapsObj = ActionMapsField?.GetValue(_target);
|
||||
if (!(mapsObj is Dictionary<InputContextId, InputActionMap> maps))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
EditorGUILayout.LabelField("Action Maps", EditorStyles.boldLabel);
|
||||
|
||||
foreach (KeyValuePair<InputContextId, InputActionMap> pair in maps)
|
||||
{
|
||||
InputContextId contextId = pair.Key;
|
||||
InputActionMap map = pair.Value;
|
||||
|
||||
bool enabled = map?.enabled ?? false;
|
||||
bool isActive = contextId == InputContextId.Global || contextId == _target.CurrentContext;
|
||||
|
||||
Color previousColor = GUI.color;
|
||||
if (enabled)
|
||||
{
|
||||
GUI.color = isActive ? Color.green : Color.yellow;
|
||||
}
|
||||
else
|
||||
{
|
||||
GUI.color = Color.gray;
|
||||
}
|
||||
|
||||
if (!_mapFoldouts.ContainsKey(contextId))
|
||||
{
|
||||
_mapFoldouts[contextId] = false;
|
||||
}
|
||||
|
||||
_mapFoldouts[contextId] = EditorGUILayout.Foldout(_mapFoldouts[contextId], $"{contextId} [{StateLabel(enabled, isActive)}]", true);
|
||||
|
||||
GUI.color = previousColor;
|
||||
|
||||
if (_mapFoldouts[contextId] && map != null)
|
||||
{
|
||||
EditorGUI.indentLevel++;
|
||||
foreach (InputAction action in map.actions)
|
||||
{
|
||||
DrawAction(action);
|
||||
}
|
||||
EditorGUI.indentLevel--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void DrawAction(InputAction action)
|
||||
{
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
EditorGUILayout.LabelField(action.name, GUILayout.Width(120));
|
||||
|
||||
if (action.bindings.Count > 0)
|
||||
{
|
||||
var parts = new System.Collections.Generic.List<string>(action.bindings.Count);
|
||||
foreach (InputBinding binding in action.bindings)
|
||||
{
|
||||
string path = string.IsNullOrEmpty(binding.overridePath) ? binding.path : binding.overridePath;
|
||||
bool hasOverride = !string.IsNullOrEmpty(binding.overridePath);
|
||||
string display = string.IsNullOrEmpty(path) ? "(none)" : path;
|
||||
if (hasOverride)
|
||||
{
|
||||
display += " *";
|
||||
}
|
||||
|
||||
parts.Add(display);
|
||||
}
|
||||
|
||||
bool anyOverride = false;
|
||||
foreach (InputBinding binding in action.bindings)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(binding.overridePath))
|
||||
{
|
||||
anyOverride = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
GUIStyle style = anyOverride ? EditorStyles.boldLabel : EditorStyles.miniLabel;
|
||||
EditorGUILayout.LabelField(string.Join(" | ", parts), style);
|
||||
}
|
||||
else
|
||||
{
|
||||
EditorGUILayout.LabelField("(no bindings)", EditorStyles.miniLabel);
|
||||
}
|
||||
|
||||
EditorGUILayout.EndHorizontal();
|
||||
}
|
||||
|
||||
private static string StateLabel(bool enabled, bool isActive)
|
||||
{
|
||||
if (!enabled)
|
||||
{
|
||||
return "disabled";
|
||||
}
|
||||
|
||||
return isActive ? "active" : "enabled";
|
||||
}
|
||||
|
||||
private static InputModuleComponent FindInputModuleComponent()
|
||||
{
|
||||
if (Application.isPlaying)
|
||||
{
|
||||
InputModuleComponent found = UnityEngine.Object.FindObjectOfType<InputModuleComponent>();
|
||||
if (found != null)
|
||||
{
|
||||
return found;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user