This commit is contained in:
陈思海 2025-12-05 20:57:29 +08:00
parent 250ae29328
commit d87d6bd7f7
6 changed files with 2654 additions and 776 deletions

View File

@ -1,4 +1,3 @@
using InputGlyphsFramework;
using UnityEngine;
using TMPro;
@ -14,8 +13,6 @@ public class ActionPromptTMP : MonoBehaviour
void OnEnable()
{
if (textField == null) textField = GetComponentInChildren<TMP_Text>();
if (InputService.Instance != null) InputService.Instance.OnBindingChanged += OnBindingChanged;
InputDeviceWatcher.OnDeviceChanged += OnDeviceChanged;
@ -32,7 +29,6 @@ public class ActionPromptTMP : MonoBehaviour
{
if (actionReference == null || actionReference.action == null) return;
if (action == actionReference.action) UpdatePrompt();
}
void OnDeviceChanged(InputDeviceWatcher.InputDeviceCategory cat)
@ -47,8 +43,8 @@ public class ActionPromptTMP : MonoBehaviour
string path = InputService.GetBindingControlPath(action);
var device = InputDeviceWatcher.CurrentCategory;
string displayFallback=string.Empty;
if (GlyphService.Instance != null && GlyphService.Instance.TryGetTMPTagForActionPath(path, device, out string tag, out displayFallback))
string displayFallback = string.Empty;
if (GlyphService.Instance != null && GlyphService.Instance.TryGetTMPTagForActionPath(path, device, out string tag, out displayFallback))
{
var s = string.Format(template, tag);
if (s != lastRendered)
@ -56,6 +52,7 @@ public class ActionPromptTMP : MonoBehaviour
textField.text = s;
lastRendered = s;
}
return;
}
@ -77,4 +74,3 @@ public class ActionPromptTMP : MonoBehaviour
return last;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -2,6 +2,7 @@ using System;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.InputSystem;
namespace InputGlyphsFramework
{
@ -10,6 +11,7 @@ namespace InputGlyphsFramework
{
public Sprite Sprite;
public string controlPath;
public InputAction action;
}
[Serializable]
@ -24,7 +26,6 @@ namespace InputGlyphsFramework
public class InputGlyphDatabase : ScriptableObject
{
public List<DeviceGlyphTable> tables = new List<DeviceGlyphTable>();
public string uiGenericKeyName = "UI_KEY_GENERIC";
public DeviceGlyphTable GetTable(InputDeviceWatcher.InputDeviceCategory device)
{

View File

@ -1,141 +1,171 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using UnityEditor;
using UnityEngine;
using UnityEngine.U2D;
using TMPro;
using System.Reflection;
using System.Collections.Generic;
using UnityEngine.InputSystem;
using InputGlyphsFramework;
using System.IO;
using System.Linq;
using UnityEngine.InputSystem.Layouts;
[CustomEditor(typeof(InputGlyphDatabase))]
public class InputGlyphDatabaseEditor : Editor
{
SerializedProperty tablesProp;
InputGlyphDatabase db;
int tabIndex = 0;
string[] tabNames = new string[] { "Keyboard", "Xbox", "PlayStation", "Other" };
// Pagination
const int itemsPerPage = 10; // 10 items per page as requested
int currentPage = 0;
void OnEnable()
{
db = target as InputGlyphDatabase;
tablesProp = serializedObject.FindProperty("tables");
// Ensure serialized list exists
if (tablesProp == null)
{
// If the field name is different, user should fix it in their class or here.
Debug.LogError("Could not find serialized property 'tables' on InputGlyphDatabase. Check field name.");
}
}
public override void OnInspectorGUI()
{
serializedObject.Update();
if (db == null) return;
if (db == null || tablesProp == null) return;
EditorGUILayout.Space();
tabIndex = GUILayout.Toolbar(tabIndex, tabNames, GUILayout.Height(24));
var curDevice = (InputDeviceWatcher.InputDeviceCategory)tabIndex;
if (db.tables == null) db.tables = new List<DeviceGlyphTable>();
// Ensure all 4 tables exist (serialized-safe)
EnsureTableFor(InputDeviceWatcher.InputDeviceCategory.Keyboard);
EnsureTableFor(InputDeviceWatcher.InputDeviceCategory.Xbox);
EnsureTableFor(InputDeviceWatcher.InputDeviceCategory.PlayStation);
EnsureTableFor(InputDeviceWatcher.InputDeviceCategory.Other);
var table = db.GetTable(curDevice);
if (table == null) return;
var tableProp = GetTablePropertyFor(curDevice);
if (tableProp == null)
{
EditorGUILayout.HelpBox("Table not found (this should not happen).", MessageType.Warning);
serializedObject.ApplyModifiedProperties();
return;
}
EditorGUILayout.BeginVertical("box");
EditorGUILayout.LabelField(curDevice.ToString(), EditorStyles.boldLabel);
table.tmpAsset = EditorGUILayout.ObjectField("TMP Sprite Asset", table.tmpAsset, typeof(TMP_SpriteAsset), false) as TMP_SpriteAsset;
var tmpAssetProp = tableProp.FindPropertyRelative("tmpAsset");
EditorGUILayout.PropertyField(tmpAssetProp, new GUIContent("TMP Sprite Asset"));
EditorGUILayout.BeginHorizontal();
if (GUILayout.Button("Parse TMP Asset"))
{
ParseTMPAssetIntoTable(table);
ParseTMPAssetIntoTableSerialized(tableProp);
}
if (GUILayout.Button("Clear"))
{
table.entries.Clear();
var entriesProp = tableProp.FindPropertyRelative("entries");
entriesProp.arraySize = 0;
serializedObject.ApplyModifiedProperties();
EditorUtility.SetDirty(db);
currentPage = 0;
}
EditorGUILayout.EndHorizontal();
EditorGUILayout.Space();
if (table.entries != null)
var entries = tableProp.FindPropertyRelative("entries");
if (entries != null)
{
for (int i = 0; i < table.entries.Count; ++i)
int total = entries.arraySize;
int totalPages = Mathf.Max(1, (total + itemsPerPage - 1) / itemsPerPage);
currentPage = Mathf.Clamp(currentPage, 0, totalPages - 1);
// Pagination controls
EditorGUILayout.BeginHorizontal();
if (GUILayout.Button("<<", GUILayout.Width(40))) { currentPage = 0; }
if (GUILayout.Button("<", GUILayout.Width(40))) { currentPage = Mathf.Max(0, currentPage - 1); }
GUILayout.FlexibleSpace();
EditorGUILayout.LabelField(string.Format("Page {0}/{1}", currentPage + 1, totalPages), GUILayout.Width(100));
GUILayout.FlexibleSpace();
if (GUILayout.Button(">", GUILayout.Width(40))) { currentPage = Mathf.Min(totalPages - 1, currentPage + 1); }
if (GUILayout.Button(">>", GUILayout.Width(40))) { currentPage = totalPages - 1; }
EditorGUILayout.EndHorizontal();
EditorGUILayout.Space(4);
int start = currentPage * itemsPerPage;
int end = Mathf.Min(start + itemsPerPage, total);
for (int i = start; i < end; ++i)
{
var e = table.entries[i];
if (e == null) continue;
var eProp = entries.GetArrayElementAtIndex(i);
if (eProp == null) continue;
EditorGUILayout.BeginHorizontal(GUILayout.Height(64));
if (e.Sprite != null)
using (new EditorGUILayout.HorizontalScope("box"))
{
Texture2D preview = AssetPreview.GetAssetPreview(e.Sprite);
if (preview == null) preview = AssetPreview.GetMiniThumbnail(e.Sprite);
if (preview != null) GUILayout.Label(preview, GUILayout.Width(64), GUILayout.Height(64));
else EditorGUILayout.ObjectField(e.Sprite, typeof(Sprite), false, GUILayout.Width(64), GUILayout.Height(64));
}
else
{
EditorGUILayout.ObjectField(null, typeof(Sprite), false, GUILayout.Width(64), GUILayout.Height(64));
}
EditorGUILayout.BeginVertical();
EditorGUILayout.LabelField(e.Sprite != null ? e.Sprite.name : "<missing>", EditorStyles.boldLabel);
EditorGUILayout.BeginHorizontal();
EditorGUILayout.LabelField("ControlPath", GUILayout.Width(80));
EditorGUILayout.SelectableLabel(e.controlPath ?? string.Empty, GUILayout.Height(16), GUILayout.Width(300));
Rect btnRect = GUILayoutUtility.GetRect(60, 18, GUILayout.Width(60));
if (GUI.Button(btnRect, "Bind"))
{
ControlPathPickerPopup.ShowDropdown(btnRect, curDevice, (selectedPath) =>
// Left column: sprite preview (fixed width)
using (new EditorGUILayout.VerticalScope(GUILayout.Width(80)))
{
if (!string.IsNullOrEmpty(selectedPath))
var spriteProp = eProp.FindPropertyRelative("Sprite");
Sprite s = spriteProp.objectReferenceValue as Sprite;
EditorGUILayout.LabelField(s != null ? s.name : "<missing>", EditorStyles.boldLabel);
if (s != null)
{
e.controlPath = selectedPath;
EditorUtility.SetDirty(db);
AssetDatabase.SaveAssets();
Texture2D preview = AssetPreview.GetAssetPreview(s);
if (preview == null) preview = AssetPreview.GetMiniThumbnail(s);
if (preview != null)
{
GUILayout.Label(preview, GUILayout.Width(64), GUILayout.Height(64));
}
else
{
EditorGUILayout.PropertyField(spriteProp, GUIContent.none, GUILayout.Width(64), GUILayout.Height(64));
}
}
});
else
{
EditorGUILayout.PropertyField(spriteProp, GUIContent.none, GUILayout.Width(64), GUILayout.Height(64));
}
}
// Right column: path + action should take the remaining width
EditorGUILayout.BeginVertical();
var pathProp = eProp.FindPropertyRelative("controlPath");
var actionProp = eProp.FindPropertyRelative("action");
EditorGUILayout.PropertyField(pathProp, GUIContent.none, GUILayout.ExpandWidth(true));
EditorGUILayout.Space(2);
EditorGUILayout.PropertyField(actionProp, GUIContent.none, GUILayout.ExpandWidth(true));
EditorGUILayout.EndVertical();
}
if (GUILayout.Button("Clear", GUILayout.Width(48)))
{
e.controlPath = string.Empty;
EditorUtility.SetDirty(db);
AssetDatabase.SaveAssets();
}
EditorGUILayout.EndHorizontal();
EditorGUILayout.EndVertical();
EditorGUILayout.EndHorizontal();
EditorGUILayout.Space(6);
}
}
EditorGUILayout.BeginHorizontal();
if (GUILayout.Button("Add Entry"))
{
table.entries.Add(new GlyphEntry { Sprite = null, controlPath = string.Empty });
EditorUtility.SetDirty(db);
}
if (GUILayout.Button("Remove Nulls"))
{
table.entries.RemoveAll(x => x == null || x.Sprite == null);
EditorUtility.SetDirty(db);
}
EditorGUILayout.EndHorizontal();
EditorGUILayout.EndVertical();
EditorGUILayout.Space();
if (GUILayout.Button("Save Asset"))
{
serializedObject.ApplyModifiedProperties();
EditorUtility.SetDirty(db);
AssetDatabase.SaveAssets();
}
@ -143,31 +173,78 @@ public class InputGlyphDatabaseEditor : Editor
serializedObject.ApplyModifiedProperties();
}
// Ensure a table for the device exists. Uses serialized properties (adds element if necessary).
void EnsureTableFor(InputDeviceWatcher.InputDeviceCategory device)
{
if (db.GetTable(device) == null)
if (tablesProp == null) return;
// Search existing entries
for (int i = 0; i < tablesProp.arraySize; ++i)
{
var t = new DeviceGlyphTable { deviceType = device, tmpAsset = null, entries = new List<GlyphEntry>() };
db.tables.Add(t);
EditorUtility.SetDirty(db);
var t = tablesProp.GetArrayElementAtIndex(i);
var devProp = t.FindPropertyRelative("deviceType");
if (devProp != null && devProp.enumValueIndex == (int)device)
return; // exists
}
// Not found -> append new element
int idx = tablesProp.arraySize;
tablesProp.InsertArrayElementAtIndex(idx); // Inserts a copy if exists, otherwise default
var newTable = tablesProp.GetArrayElementAtIndex(idx);
var deviceTypeProp = newTable.FindPropertyRelative("deviceType");
if (deviceTypeProp != null) deviceTypeProp.enumValueIndex = (int)device;
var tmpAssetProp = newTable.FindPropertyRelative("tmpAsset");
if (tmpAssetProp != null) tmpAssetProp.objectReferenceValue = null;
var entriesProp = newTable.FindPropertyRelative("entries");
if (entriesProp != null) entriesProp.arraySize = 0;
serializedObject.ApplyModifiedProperties();
EditorUtility.SetDirty(db);
}
void ParseTMPAssetIntoTable(DeviceGlyphTable table)
// Return the SerializedProperty representing the DeviceGlyphTable that matches device
SerializedProperty GetTablePropertyFor(InputDeviceWatcher.InputDeviceCategory device)
{
if (table == null || table.tmpAsset == null) return;
var asset = table.tmpAsset;
table.entries = new List<GlyphEntry>();
if (tablesProp == null) return null;
for (int i = 0; i < tablesProp.arraySize; ++i)
{
var t = tablesProp.GetArrayElementAtIndex(i);
var devProp = t.FindPropertyRelative("deviceType");
if (devProp != null && devProp.enumValueIndex == (int)device)
return t;
}
return null;
}
// Parse TMP Sprite Asset and populate entries (serialized)
void ParseTMPAssetIntoTableSerialized(SerializedProperty tableProp)
{
if (tableProp == null) return;
var tmpAssetProp = tableProp.FindPropertyRelative("tmpAsset");
var asset = tmpAssetProp.objectReferenceValue as TMP_SpriteAsset;
if (asset == null) return;
var entriesProp = tableProp.FindPropertyRelative("entries");
if (entriesProp == null) return;
entriesProp.arraySize = 0;
var chars = asset.spriteCharacterTable;
SpriteAtlas atlas = GetSpriteAtlasFromTMP(asset);
string assetPath = AssetDatabase.GetAssetPath(asset);
string assetFolder = Path.GetDirectoryName(assetPath);
for (int i = 0; i < chars.Count; ++i)
{
var ch = chars[i];
if (ch == null) continue;
var name = ch.name;
if (string.IsNullOrEmpty(name)) continue;
Sprite s = null;
try
{
@ -193,7 +270,7 @@ public class InputGlyphDatabaseEditor : Editor
{
try
{
var m = typeof(SpriteAtlas).GetMethod("GetSprite", new System.Type[] { typeof(string) });
var m = typeof(SpriteAtlas).GetMethod("GetSprite", new Type[] { typeof(string) });
if (m != null) s = m.Invoke(atlas, new object[] { name }) as Sprite;
}
catch
@ -238,9 +315,19 @@ public class InputGlyphDatabaseEditor : Editor
}
}
table.entries.Add(new GlyphEntry { Sprite = s, controlPath = string.Empty });
// Create new entry and assign fields
int newIndex = entriesProp.arraySize;
entriesProp.InsertArrayElementAtIndex(newIndex);
var entryProp = entriesProp.GetArrayElementAtIndex(newIndex);
var spriteProp = entryProp.FindPropertyRelative("Sprite");
var controlPathProp = entryProp.FindPropertyRelative("controlPath");
if (spriteProp != null) spriteProp.objectReferenceValue = s;
if (controlPathProp != null) controlPathProp.stringValue = string.Empty;
}
serializedObject.ApplyModifiedProperties();
EditorUtility.SetDirty(db);
AssetDatabase.SaveAssets();
}
@ -276,365 +363,3 @@ public class InputGlyphDatabaseEditor : Editor
return null;
}
}
public class ControlPathPickerPopup : EditorWindow
{
InputDeviceWatcher.InputDeviceCategory device;
Action<string> onSelect;
string search = "";
Vector2 scroll;
Dictionary<string, List<string>> groups = new Dictionary<string, List<string>>();
Dictionary<string, List<string>> displayGroups = new Dictionary<string, List<string>>();
Dictionary<string, bool> foldouts = new Dictionary<string, bool>();
bool listening = false;
IDisposable anyButtonSubscription;
public static void ShowDropdown(Rect anchorRect, InputDeviceWatcher.InputDeviceCategory device, Action<string> onSelect)
{
var w = CreateInstance<ControlPathPickerPopup>();
w.device = device;
w.onSelect = onSelect;
w.titleContent = new GUIContent("Pick Control Path");
w.minSize = new Vector2(480, 420);
w.InitListsDynamic();
w.ShowAsDropDown(anchorRect, new Vector2(480, 420));
}
void OnEnable()
{
EditorApplication.update += EditorUpdate;
}
void OnDisable()
{
StopListening();
EditorApplication.update -= EditorUpdate;
}
void EditorUpdate()
{
if (listening) Repaint();
}
// -------------------- 动态构建列表 --------------------
void InitListsDynamic()
{
groups.Clear();
displayGroups.Clear();
foldouts.Clear();
// 首先插入一些基本的静态分组占位(如果需要)
var known = new[] { "Keyboard", "Gamepad", "Mouse", "Joystick", "Touchscreen", "XR Controller", "XR HMD", "Pointer", "Pen", "Other" };
foreach (var k in known)
{
groups[k] = new List<string>();
displayGroups[k] = new List<string>();
foldouts[k] = true;
}
// 列出所有已注册布局名称
IEnumerable<string> layoutNames;
try
{
layoutNames = InputSystem.ListLayouts();
}
catch
{
layoutNames = Enumerable.Empty<string>();
}
foreach (var layoutName in layoutNames)
{
InputControlLayout layout = null;
try
{
layout = InputSystem.LoadLayout(layoutName);
}
catch
{
layout = null;
}
if (layout == null) continue;
// 遍历 layout.controls (InputControlLayout.ControlItem)
try
{
var controls = layout.controls;
if (controls.Count == 0) continue;
foreach (var ci in controls)
{
// isModifyingExistingControl 表示这个 control 只是修改已有 control 的属性,不引入新的控制项,通常跳过
if (ci.isModifyingExistingControl) continue;
string controlName = ci.name.ToString();
if (string.IsNullOrEmpty(controlName)) continue;
string path = $"<{layoutName}>/{controlName}";
// 决定分组:根据 layoutName 或 controlName 做简单匹配
string group = DecideGroupForLayout(layoutName, controlName);
if (!groups.ContainsKey(group))
{
groups[group] = new List<string>();
displayGroups[group] = new List<string>();
foldouts[group] = true;
}
// 防重复
if (!groups[group].Contains(path))
{
groups[group].Add(path);
displayGroups[group].Add($"{controlName} ({path})");
}
// 试着添加常见的子项(例如 stick/up/down 等),如果 controlItem 标识这些为子控制可能需要额外处理
// 但大多数情况下 layout.controls 已包含独立条目如 leftStick/up
}
}
catch
{
/* 忽略个别布局异常 */
}
}
// 额外补充:把一些常用手动添加的路径放到 Gamepad / Keyboard 中,防止某些 layout 未定义具体按钮
AddFallbackCommonPaths();
}
string DecideGroupForLayout(string layoutName, string controlName)
{
var lname = layoutName.ToLowerInvariant();
if (lname.Contains("keyboard")) return "Keyboard";
if (lname.Contains("gamepad") || lname.Contains("xbox") || lname.Contains("dualshock") || lname.Contains("controller")) return "Gamepad";
if (lname.Contains("mouse")) return "Mouse";
if (lname.Contains("joystick")) return "Joystick";
if (lname.Contains("touchscreen")) return "Touchscreen";
if (lname.Contains("xr") || lname.Contains("hmd")) return "XR Controller";
return "Other";
}
void AddFallbackCommonPaths()
{
void addIfMissing(string grp, string path, string label = null)
{
if (!groups.ContainsKey(grp))
{
groups[grp] = new List<string>();
displayGroups[grp] = new List<string>();
foldouts[grp] = true;
}
if (!groups[grp].Contains(path))
{
groups[grp].Add(path);
displayGroups[grp].Add(label ?? path);
}
}
addIfMissing("Gamepad", "<Gamepad>/buttonSouth");
addIfMissing("Gamepad", "<Gamepad>/buttonEast");
addIfMissing("Gamepad", "<Gamepad>/buttonWest");
addIfMissing("Gamepad", "<Gamepad>/buttonNorth");
addIfMissing("Gamepad", "<Gamepad>/leftShoulder");
addIfMissing("Gamepad", "<Gamepad>/rightShoulder");
addIfMissing("Gamepad", "<Gamepad>/leftTrigger");
addIfMissing("Gamepad", "<Gamepad>/rightTrigger");
addIfMissing("Keyboard", "<Keyboard>/space");
addIfMissing("Keyboard", "<Keyboard>/enter");
addIfMissing("Keyboard", "<Keyboard>/escape");
addIfMissing("Mouse", "<Mouse>/leftButton");
}
// -------------------- UI --------------------
void OnGUI()
{
EditorGUILayout.BeginVertical();
EditorGUILayout.BeginHorizontal();
var prevColor = GUI.color;
search = EditorGUILayout.TextField(search, GUILayout.ExpandWidth(true));
if (!listening)
{
if (GUILayout.Button("Listen", GUILayout.Width(72)))
{
StartListening();
}
}
else
{
GUI.color = Color.yellow;
if (GUILayout.Button("Stop", GUILayout.Width(72)))
{
StopListening();
}
GUI.color = prevColor;
}
EditorGUILayout.EndHorizontal();
EditorGUILayout.Space();
scroll = EditorGUILayout.BeginScrollView(scroll);
foreach (var kv in displayGroups.OrderBy(k => k.Key))
{
string cat = kv.Key;
if (!ShouldShowCategory(cat)) continue;
foldouts.TryGetValue(cat, out bool f);
f = EditorGUILayout.Foldout(f, cat, true);
foldouts[cat] = f;
if (!f) continue;
var displays = kv.Value;
var vals = groups[cat];
for (int i = 0; i < displays.Count; ++i)
{
var dsp = displays[i];
var val = vals[i];
if (!MatchSearch(dsp, val)) continue;
EditorGUILayout.BeginHorizontal();
if (GUILayout.Button("Select", GUILayout.Width(64)))
{
onSelect?.Invoke(val);
Close();
return;
}
EditorGUILayout.LabelField(dsp, GUILayout.ExpandWidth(true));
EditorGUILayout.EndHorizontal();
}
EditorGUILayout.Space(6);
}
EditorGUILayout.EndScrollView();
EditorGUILayout.Space();
GUILayout.FlexibleSpace();
if (GUILayout.Button("Close")) Close();
EditorGUILayout.EndVertical();
}
bool ShouldShowCategory(string cat)
{
if (string.IsNullOrEmpty(search)) return true;
if (cat.IndexOf(search, StringComparison.OrdinalIgnoreCase) >= 0) return true;
var disp = displayGroups[cat];
for (int i = 0; i < disp.Count; ++i)
if (MatchSearch(disp[i], groups[cat][i]))
return true;
return false;
}
bool MatchSearch(string display, string value)
{
if (string.IsNullOrEmpty(search)) return true;
if (display.IndexOf(search, StringComparison.OrdinalIgnoreCase) >= 0) return true;
if (value.IndexOf(search, StringComparison.OrdinalIgnoreCase) >= 0) return true;
return false;
}
// -------------------- Listen (使用 IObserver<T> 订阅) --------------------
class InputControlObserver : IObserver<InputControl>
{
readonly Action<InputControl> onNext;
public InputControlObserver(Action<InputControl> onNext)
{
this.onNext = onNext;
}
public void OnCompleted()
{
}
public void OnError(Exception error)
{
}
public void OnNext(InputControl value)
{
try
{
onNext?.Invoke(value);
}
catch
{
}
}
}
void StartListening()
{
if (listening) return;
listening = true;
try
{
// 使用 IObserver<InputControl> 订阅(通用、可靠)
anyButtonSubscription = InputSystem.onAnyButtonPress.Subscribe(new InputControlObserver(control =>
{
if (control == null) return;
string path = control.path;
onSelect?.Invoke(path);
StopListening();
Close();
}));
}
catch (Exception)
{
// 某些版本/包装可能提供 Call/CallOnce 扩展方法Utilities尝试反射调用这些扩展
try
{
var t = typeof(InputSystem);
var prop = t.GetProperty("onAnyButtonPress");
if (prop != null)
{
var obs = prop.GetValue(null);
var callMethod = obs?.GetType().GetMethod("CallOnce") ?? obs?.GetType().GetMethod("Call");
if (callMethod != null)
{
// 尝试调用 CallOnce(Action<InputControl>)
callMethod.Invoke(obs, new object[]
{
new Action<InputControl>(c =>
{
if (c == null) return;
onSelect?.Invoke(c.path);
StopListening();
Close();
})
});
StopListening();
Close();
return;
}
}
}
catch
{
}
// 如果都失败,简单关闭监听状态
listening = false;
}
}
void StopListening()
{
if (!listening) return;
listening = false;
try
{
anyButtonSubscription?.Dispose();
anyButtonSubscription = null;
}
catch
{
anyButtonSubscription = null;
}
}
}

@ -1 +1 @@
Subproject commit 01024066686deed8d8077c6cbc83f558d6af2360
Subproject commit e51e3e78e4776fbd6b3ddfa8f917828cb70e0162

View File

@ -19,64 +19,12 @@ MonoBehaviour:
width: 1920
height: 997
m_ShowMode: 4
m_Title: Hierarchy
m_RootView: {fileID: 4}
m_Title: Inspector
m_RootView: {fileID: 2}
m_MinSize: {x: 875, y: 300}
m_MaxSize: {x: 10000, y: 10000}
m_Maximized: 1
--- !u!114 &2
MonoBehaviour:
m_ObjectHideFlags: 52
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 12006, guid: 0000000000000000e000000000000000, type: 0}
m_Name: GameView
m_EditorClassIdentifier:
m_Children: []
m_Position:
serializedVersion: 2
x: 0
y: 631
width: 519
height: 316
m_MinSize: {x: 51, y: 71}
m_MaxSize: {x: 4001, y: 4021}
m_ActualView: {fileID: 14}
m_Panes:
- {fileID: 14}
m_Selected: 0
m_LastSelected: 0
--- !u!114 &3
MonoBehaviour:
m_ObjectHideFlags: 52
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 12010, guid: 0000000000000000e000000000000000, type: 0}
m_Name:
m_EditorClassIdentifier:
m_Children:
- {fileID: 8}
- {fileID: 2}
m_Position:
serializedVersion: 2
x: 0
y: 0
width: 519
height: 947
m_MinSize: {x: 100, y: 100}
m_MaxSize: {x: 8096, y: 16192}
vertical: 1
controlID: 6203
draggingID: 0
--- !u!114 &4
MonoBehaviour:
m_ObjectHideFlags: 52
m_CorrespondingSourceObject: {fileID: 0}
@ -89,9 +37,9 @@ MonoBehaviour:
m_Name:
m_EditorClassIdentifier:
m_Children:
- {fileID: 3}
- {fileID: 5}
- {fileID: 7}
- {fileID: 6}
- {fileID: 4}
m_Position:
serializedVersion: 2
x: 0
@ -104,7 +52,7 @@ MonoBehaviour:
m_TopViewHeight: 30
m_UseBottomView: 1
m_BottomViewHeight: 20
--- !u!114 &5
--- !u!114 &3
MonoBehaviour:
m_ObjectHideFlags: 52
m_CorrespondingSourceObject: {fileID: 0}
@ -126,7 +74,7 @@ MonoBehaviour:
m_MinSize: {x: 0, y: 0}
m_MaxSize: {x: 0, y: 0}
m_LastLoadedLayoutName:
--- !u!114 &6
--- !u!114 &4
MonoBehaviour:
m_ObjectHideFlags: 52
m_CorrespondingSourceObject: {fileID: 0}
@ -147,7 +95,7 @@ MonoBehaviour:
height: 20
m_MinSize: {x: 0, y: 0}
m_MaxSize: {x: 0, y: 0}
--- !u!114 &7
--- !u!114 &5
MonoBehaviour:
m_ObjectHideFlags: 52
m_CorrespondingSourceObject: {fileID: 0}
@ -160,7 +108,7 @@ MonoBehaviour:
m_Name:
m_EditorClassIdentifier:
m_Children:
- {fileID: 3}
- {fileID: 6}
- {fileID: 9}
- {fileID: 12}
- {fileID: 13}
@ -173,9 +121,35 @@ MonoBehaviour:
m_MinSize: {x: 400, y: 100}
m_MaxSize: {x: 32384, y: 16192}
vertical: 0
controlID: 127
controlID: 46181
draggingID: 0
--- !u!114 &8
--- !u!114 &6
MonoBehaviour:
m_ObjectHideFlags: 52
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 12010, guid: 0000000000000000e000000000000000, type: 0}
m_Name:
m_EditorClassIdentifier:
m_Children:
- {fileID: 7}
- {fileID: 8}
m_Position:
serializedVersion: 2
x: 0
y: 0
width: 383
height: 947
m_MinSize: {x: 100, y: 100}
m_MaxSize: {x: 8096, y: 16192}
vertical: 1
controlID: 46011
draggingID: 0
--- !u!114 &7
MonoBehaviour:
m_ObjectHideFlags: 52
m_CorrespondingSourceObject: {fileID: 0}
@ -192,16 +166,42 @@ MonoBehaviour:
serializedVersion: 2
x: 0
y: 0
width: 519
height: 631
m_MinSize: {x: 201, y: 221}
m_MaxSize: {x: 4001, y: 4021}
width: 383
height: 363
m_MinSize: {x: 200, y: 200}
m_MaxSize: {x: 4000, y: 4000}
m_ActualView: {fileID: 16}
m_Panes:
- {fileID: 15}
- {fileID: 16}
m_Selected: 1
m_LastSelected: 0
--- !u!114 &8
MonoBehaviour:
m_ObjectHideFlags: 52
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 12006, guid: 0000000000000000e000000000000000, type: 0}
m_Name: GameView
m_EditorClassIdentifier:
m_Children: []
m_Position:
serializedVersion: 2
x: 0
y: 363
width: 383
height: 584
m_MinSize: {x: 50, y: 50}
m_MaxSize: {x: 4000, y: 4000}
m_ActualView: {fileID: 14}
m_Panes:
- {fileID: 14}
m_Selected: 0
m_LastSelected: 0
--- !u!114 &9
MonoBehaviour:
m_ObjectHideFlags: 52
@ -219,14 +219,14 @@ MonoBehaviour:
- {fileID: 11}
m_Position:
serializedVersion: 2
x: 519
x: 383
y: 0
width: 500
width: 213
height: 947
m_MinSize: {x: 100, y: 100}
m_MaxSize: {x: 8096, y: 16192}
vertical: 1
controlID: 45
controlID: 46071
draggingID: 0
--- !u!114 &10
MonoBehaviour:
@ -245,10 +245,10 @@ MonoBehaviour:
serializedVersion: 2
x: 0
y: 0
width: 500
height: 539
m_MinSize: {x: 202, y: 221}
m_MaxSize: {x: 4002, y: 4021}
width: 213
height: 601
m_MinSize: {x: 200, y: 200}
m_MaxSize: {x: 4000, y: 4000}
m_ActualView: {fileID: 17}
m_Panes:
- {fileID: 17}
@ -270,11 +270,11 @@ MonoBehaviour:
m_Position:
serializedVersion: 2
x: 0
y: 539
width: 500
height: 408
m_MinSize: {x: 102, y: 121}
m_MaxSize: {x: 4002, y: 4021}
y: 601
width: 213
height: 346
m_MinSize: {x: 100, y: 100}
m_MaxSize: {x: 4000, y: 4000}
m_ActualView: {fileID: 18}
m_Panes:
- {fileID: 18}
@ -295,9 +295,9 @@ MonoBehaviour:
m_Children: []
m_Position:
serializedVersion: 2
x: 1019
x: 596
y: 0
width: 184
width: 359
height: 947
m_MinSize: {x: 232, y: 271}
m_MaxSize: {x: 10002, y: 10021}
@ -321,12 +321,12 @@ MonoBehaviour:
m_Children: []
m_Position:
serializedVersion: 2
x: 1203
x: 955
y: 0
width: 717
width: 965
height: 947
m_MinSize: {x: 276, y: 71}
m_MaxSize: {x: 4001, y: 4021}
m_MinSize: {x: 275, y: 50}
m_MaxSize: {x: 4000, y: 4000}
m_ActualView: {fileID: 20}
m_Panes:
- {fileID: 20}
@ -353,9 +353,9 @@ MonoBehaviour:
m_Pos:
serializedVersion: 2
x: 0
y: 704
width: 518
height: 295
y: 436
width: 382
height: 563
m_SerializedDataModeController:
m_DataMode: 0
m_PreferredDataMode: 0
@ -408,23 +408,23 @@ MonoBehaviour:
serializedVersion: 2
x: 0
y: 21
width: 518
height: 274
m_Scale: {x: 0.2537037, y: 0.2537037}
m_Translation: {x: 259, y: 137}
width: 382
height: 542
m_Scale: {x: 0.19895834, y: 0.19895834}
m_Translation: {x: 191, y: 271}
m_MarginLeft: 0
m_MarginRight: 0
m_MarginTop: 0
m_MarginBottom: 0
m_LastShownAreaInsideMargins:
serializedVersion: 2
x: -1020.87585
y: -540
width: 2041.7517
height: 1080
x: -960
y: -1362.0942
width: 1920
height: 2724.1885
m_MinimalGUI: 1
m_defaultScale: 0.2537037
m_LastWindowPixelSize: {x: 518, y: 295}
m_defaultScale: 0.19895834
m_LastWindowPixelSize: {x: 382, y: 563}
m_ClearInEditMode: 1
m_NoCameraWarning: 1
m_LowResolutionForAspectRatios: 01000000000000000000
@ -522,8 +522,8 @@ MonoBehaviour:
serializedVersion: 2
x: 0
y: 73
width: 518
height: 610
width: 382
height: 342
m_SerializedDataModeController:
m_DataMode: 0
m_PreferredDataMode: 0
@ -538,7 +538,7 @@ MonoBehaviour:
floating: 0
collapsed: 0
displayed: 1
snapOffset: {x: -174, y: -26}
snapOffset: {x: -179, y: -26}
snapOffsetDelta: {x: 0, y: 0}
snapCorner: 3
id: Tool Settings
@ -616,9 +616,9 @@ MonoBehaviour:
floating: 0
collapsed: 0
displayed: 1
snapOffset: {x: 24, y: -131}
snapOffset: {x: 24, y: 64}
snapOffsetDelta: {x: 0, y: 0}
snapCorner: 2
snapCorner: 0
id: Orientation
index: 0
layout: 4
@ -1064,9 +1064,9 @@ MonoBehaviour:
m_PlayAudio: 0
m_AudioPlay: 0
m_Position:
m_Target: {x: 629.57336, y: 383.6224, z: -7.5886}
m_Target: {x: 1241.503, y: 212.77849, z: -0.5889411}
speed: 2
m_Value: {x: 629.57336, y: 383.6224, z: -7.5886}
m_Value: {x: 1241.503, y: 212.77849, z: -0.5889411}
m_RenderMode: 0
m_CameraMode:
drawMode: 0
@ -1116,9 +1116,9 @@ MonoBehaviour:
speed: 2
m_Value: {x: 0, y: 0, z: 0, w: 1}
m_Size:
m_Target: 1006.24756
m_Target: 161.9702
speed: 2
m_Value: 1006.24756
m_Value: 161.9702
m_Ortho:
m_Target: 1
speed: 2
@ -1163,10 +1163,10 @@ MonoBehaviour:
m_Tooltip:
m_Pos:
serializedVersion: 2
x: 519
y: 73
width: 498
height: 518
x: 1
y: 19
width: 211
height: 580
m_SerializedDataModeController:
m_DataMode: 0
m_PreferredDataMode: 0
@ -1180,23 +1180,23 @@ MonoBehaviour:
m_SceneHierarchy:
m_TreeViewState:
scrollPos: {x: 0, y: 0}
m_SelectedIDs:
m_SelectedIDs: 5afffeff
m_LastClickedID: 0
m_ExpandedIDs: 00f7ffff20f7ffff28fbffff2e6d0000
m_ExpandedIDs: 20b1ffff34b1ffff1cfbffffc86d00009e6e0000
m_RenameOverlay:
m_UserAcceptedRename: 0
m_Name:
m_OriginalName:
m_Name: Dropdown
m_OriginalName: Dropdown
m_EditFieldRect:
serializedVersion: 2
x: 0
y: 0
width: 0
height: 0
m_UserData: 0
m_UserData: 28280
m_IsWaitingForDelay: 0
m_IsRenaming: 0
m_OriginalEventType: 11
m_OriginalEventType: 0
m_IsRenamingFilename: 0
m_ClientGUIView: {fileID: 10}
m_SearchString:
@ -1226,10 +1226,10 @@ MonoBehaviour:
m_Tooltip:
m_Pos:
serializedVersion: 2
x: 519
y: 612
width: 498
height: 387
x: 1
y: 620
width: 211
height: 325
m_SerializedDataModeController:
m_DataMode: 0
m_PreferredDataMode: 0
@ -1260,9 +1260,9 @@ MonoBehaviour:
m_Tooltip:
m_Pos:
serializedVersion: 2
x: 1019
x: 596
y: 73
width: 182
width: 357
height: 926
m_SerializedDataModeController:
m_DataMode: 0
@ -1284,7 +1284,8 @@ MonoBehaviour:
m_ShowAllHits: 0
m_SkipHidden: 0
m_SearchArea: 0
m_Folders: []
m_Folders:
- Assets/InputGlyph
m_Globs: []
m_OriginalText:
m_ImportLogFlags: 0
@ -1300,7 +1301,7 @@ MonoBehaviour:
scrollPos: {x: 0, y: 0}
m_SelectedIDs: e48c0000
m_LastClickedID: 36068
m_ExpandedIDs: 00000000587000005a7000005c7000005e70000060700000627000006470000066700000687000006a7000006c7000006e70000070700000727000007470000076700000787000007a7000007c7000007e70000080700000827000008470000086700000887000008a7000008c7000008e70000090700000927000009470000096700000987000009a7000009c7000009e700000a0700000a2700000a4700000a6700000a8700000aa700000ac700000ae700000b0700000b2700000b4700000b6700000b8700000ba700000bc700000be700000c0700000c2700000c4700000c6700000c8700000ca700000cc700000ce700000d0700000d2700000d4700000d6700000d8700000da700000dc700000de700000e0700000e2700000e4700000e6700000e8700000ea700000ec700000ee700000f0700000f2700000f4700000f6700000f8700000fa700000fc700000fe70000000710000027100000471000006710000087100000a7100000c7100000e71000010710000127100001471000016710000187100001a7100001c7100001e71000020710000227100002471000026710000287100002a7100002c7100002e71000030710000327100003471000036710000387100003a7100003c7100003e71000040710000427100004471000046710000487100004a7100004c7100004e71000050710000527100005471000056710000587100005a7100005c7100005e71000060710000627100006471000066710000687100006a7100006c7100006e71000070710000727100007471000076710000787100007a7100007c7100007e71000080710000827100008471000086710000887100008a7100008c7100008e71000090710000927100009471000096710000987100009a7100009c7100009e710000a0710000a2710000a4710000a6710000a8710000aa710000ac710000ae710000b0710000b2710000b4710000b6710000b8710000ba710000bc710000be710000c0710000c2710000c4710000c6710000c8710000ca710000cc710000ce710000d0710000d2710000d4710000d6710000d8710000da710000dc710000de710000e0710000e2710000e4710000e6710000e8710000ea710000ec710000ee710000f0710000f2710000f4710000f6710000f8710000fa710000fc710000fe71000000720000027200000472000006720000087200000a7200000c7200000e720000107200001272000014720000
m_ExpandedIDs: ffffffff0000000070710000727100007471000076710000787100007a7100007c7100007e71000080710000827100008471000086710000887100008a7100008c7100008e71000090710000927100009471000096710000987100009a7100009c7100009e710000a0710000a2710000a4710000a6710000a8710000aa710000ac710000ae710000b0710000b2710000b4710000b6710000b8710000ba710000bc710000be710000c0710000c2710000c4710000c6710000c8710000ca710000cc710000ce710000d0710000d2710000d4710000d6710000d8710000da710000dc710000de710000e0710000e2710000e4710000e6710000e8710000ea710000ec710000ee710000f0710000f2710000f4710000f6710000f8710000fa710000fc710000fe71000000720000027200000472000006720000087200000a7200000c7200000e72000010720000127200001472000016720000187200001a7200001c7200001e72000020720000227200002472000026720000287200002a7200002c7200002e72000030720000327200003472000036720000387200003a7200003c7200003e72000040720000427200004472000046720000487200004a7200004c7200004e72000050720000527200005472000056720000587200005a7200005c7200005e72000060720000627200006472000066720000687200006a7200006c7200006e72000070720000727200007472000076720000787200007a7200007c7200007e72000080720000827200008472000086720000887200008a7200008c7200008e72000090720000927200009472000096720000987200009a7200009c7200009e720000a0720000a2720000a4720000a6720000a8720000aa720000ac720000ae720000b0720000b2720000b4720000b6720000b8720000ba720000bc720000be720000c0720000c2720000c4720000c6720000c8720000ca720000cc720000ce720000d2720000d4720000d6720000d8720000da720000dc720000de720000e0720000e2720000e4720000e6720000e8720000ea720000ec720000ee720000f0720000f2720000f4720000f8720000fa720000fc720000fe72000000730000027300000473000006730000087300000a7300000c7300000e730000107300001273000014730000167300001a7300001c7300001e730000207300002273000024730000267300002c730000767300008e73000094730000e67300005877000058790000e67c0000047d00000c7d0000de820000e8820000f482000040890000
m_RenameOverlay:
m_UserAcceptedRename: 0
m_Name:
@ -1328,21 +1329,21 @@ MonoBehaviour:
scrollPos: {x: 0, y: 0}
m_SelectedIDs:
m_LastClickedID: 0
m_ExpandedIDs: ffffffff00000000587000005a7000005c7000005e70000060700000627000006470000066700000687000006a7000006c7000006e70000070700000727000007470000076700000787000007a7000007c7000007e70000080700000827000008470000086700000887000008a7000008c7000008e70000090700000927000009470000096700000987000009a7000009c7000009e700000a0700000a2700000a4700000a6700000a8700000aa700000ac700000ae700000b0700000b2700000b4700000b6700000b8700000ba700000bc700000be700000c0700000c2700000c4700000c6700000c8700000ca700000cc700000ce700000d0700000d2700000d4700000d6700000d8700000da700000dc700000de700000e0700000e2700000e4700000e6700000e8700000ea700000ec700000ee700000f0700000f2700000f4700000f6700000f8700000fa700000fc700000fe70000000710000027100000471000006710000087100000a7100000c7100000e71000010710000127100001471000016710000187100001a7100001c7100001e71000020710000227100002471000026710000287100002a7100002c7100002e71000030710000327100003471000036710000387100003a7100003c7100003e71000040710000427100004471000046710000487100004a7100004c7100004e71000050710000527100005471000056710000587100005a7100005c7100005e71000060710000627100006471000066710000687100006a7100006c7100006e71000070710000727100007471000076710000787100007a7100007c7100007e71000080710000827100008471000086710000887100008a7100008c7100008e71000090710000927100009471000096710000987100009a7100009c7100009e710000a0710000a2710000a4710000a6710000a8710000aa710000ac710000ae710000b0710000b2710000b4710000b6710000b8710000ba710000bc710000be710000c0710000c2710000c4710000c6710000c8710000ca710000cc710000ce710000d0710000d2710000d4710000d6710000d8710000da710000dc710000de710000e0710000e2710000e4710000e6710000e8710000ea710000ec710000ee710000f0710000f2710000f4710000f6710000f8710000fa710000fc710000fe71000000720000027200000472000006720000087200000a7200000c7200000e720000107200001272000014720000
m_ExpandedIDs: ffffffff0000000070710000727100007471000076710000787100007a7100007c7100007e71000080710000827100008471000086710000887100008a7100008c7100008e71000090710000927100009471000096710000987100009a7100009c7100009e710000a0710000a2710000a4710000a6710000a8710000aa710000ac710000ae710000b0710000b2710000b4710000b6710000b8710000ba710000bc710000be710000c0710000c2710000c4710000c6710000c8710000ca710000cc710000ce710000d0710000d2710000d4710000d6710000d8710000da710000dc710000de710000e0710000e2710000e4710000e6710000e8710000ea710000ec710000ee710000f0710000f2710000f4710000f6710000f8710000fa710000fc710000fe71000000720000027200000472000006720000087200000a7200000c7200000e72000010720000127200001472000016720000187200001a7200001c7200001e72000020720000227200002472000026720000287200002a7200002c7200002e72000030720000327200003472000036720000387200003a7200003c7200003e72000040720000427200004472000046720000487200004a7200004c7200004e72000050720000527200005472000056720000587200005a7200005c7200005e72000060720000627200006472000066720000687200006a7200006c7200006e72000070720000727200007472000076720000787200007a7200007c7200007e72000080720000827200008472000086720000887200008a7200008c7200008e72000090720000927200009472000096720000987200009a7200009c7200009e720000a0720000a2720000a4720000a6720000a8720000aa720000ac720000ae720000b0720000b2720000b4720000b6720000b8720000ba720000bc720000be720000c0720000c2720000c4720000c6720000c8720000ca720000cc720000ce720000d2720000d4720000d6720000d8720000da720000dc720000de720000e0720000e2720000e4720000e6720000e8720000ea720000ec720000ee720000f0720000f2720000f4720000f8720000fa720000fc720000fe72000000730000027300000473000006730000087300000a7300000c7300000e730000107300001273000014730000167300001a7300001c7300001e730000207300002273000024730000267300002a7300002c7300007c7300008e73000094730000e6730000587700005e77000058790000e67c0000047d00000c7d0000e88200000083000040890000289b0000
m_RenameOverlay:
m_UserAcceptedRename: 0
m_Name:
m_OriginalName:
m_Name: InputActionDebug
m_OriginalName: InputActionDebug
m_EditFieldRect:
serializedVersion: 2
x: 0
y: 0
width: 0
height: 0
m_UserData: 0
m_UserData: 56070
m_IsWaitingForDelay: 0
m_IsRenaming: 0
m_OriginalEventType: 11
m_OriginalEventType: 0
m_IsRenamingFilename: 1
m_ClientGUIView: {fileID: 12}
m_SearchString:
@ -1404,9 +1405,9 @@ MonoBehaviour:
m_Tooltip:
m_Pos:
serializedVersion: 2
x: 1203
x: 955
y: 73
width: 716
width: 964
height: 926
m_SerializedDataModeController:
m_DataMode: 0
@ -1421,7 +1422,7 @@ MonoBehaviour:
m_ObjectsLockedBeforeSerialization: []
m_InstanceIDsLockedBeforeSerialization:
m_PreviewResizer:
m_CachedPref: 231
m_CachedPref: 151
m_ControlHash: 1412526313
m_PrefName: Preview_InspectorPreview
m_LastInspectedObjectInstanceID: -1