2025-12-09 20:31:44 +08:00
|
|
|
using System;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using AlicizaX.InputGlyph;
|
2025-12-05 19:04:53 +08:00
|
|
|
using UnityEngine;
|
2025-12-09 20:31:44 +08:00
|
|
|
using UnityEngine.InputSystem;
|
2025-12-05 19:04:53 +08:00
|
|
|
|
2025-12-09 20:31:44 +08:00
|
|
|
public static class GlyphService
|
2025-12-05 19:04:53 +08:00
|
|
|
{
|
2025-12-09 20:31:44 +08:00
|
|
|
/// <summary>
|
|
|
|
|
/// 可选的全局数据库引用。你可以通过场景内的启动组件在 Awake 时赋值,
|
|
|
|
|
/// 或者在调用每个方法时传入 InputGlyphDatabase 参数(见方法签名)。
|
|
|
|
|
/// </summary>
|
2025-12-17 20:03:29 +08:00
|
|
|
public static InputGlyphDatabase Database
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
if (_database == null)
|
|
|
|
|
{
|
|
|
|
|
_database = Resources.Load<InputGlyphDatabase>("InputGlyphDatabase");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return _database;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static InputGlyphDatabase _database;
|
|
|
|
|
|
2025-12-09 20:31:44 +08:00
|
|
|
|
2025-12-10 17:38:31 +08:00
|
|
|
public static string GetBindingControlPath(InputAction action, InputDeviceWatcher.InputDeviceCategory? deviceOverride = null)
|
2025-12-09 20:31:44 +08:00
|
|
|
{
|
|
|
|
|
if (action == null) return string.Empty;
|
2025-12-10 17:38:31 +08:00
|
|
|
var binding = GetBindingControl(action, deviceOverride);
|
|
|
|
|
return binding.hasOverrides ? binding.effectivePath : binding.path;
|
2025-12-09 20:31:44 +08:00
|
|
|
}
|
2025-12-05 19:04:53 +08:00
|
|
|
|
2025-12-10 17:38:31 +08:00
|
|
|
public static bool TryGetTMPTagForActionPath(InputActionReference reference, InputDeviceWatcher.InputDeviceCategory device, out string tag, out string displayFallback, InputGlyphDatabase db = null)
|
2025-12-05 19:04:53 +08:00
|
|
|
{
|
2025-12-10 17:38:31 +08:00
|
|
|
string path = GetBindingControlPath(reference, device);
|
|
|
|
|
return TryGetTMPTagForActionPath(path, device, out tag, out displayFallback, db);
|
2025-12-05 19:04:53 +08:00
|
|
|
}
|
|
|
|
|
|
2025-12-10 17:38:31 +08:00
|
|
|
public static bool TryGetUISpriteForActionPath(InputActionReference reference, InputDeviceWatcher.InputDeviceCategory device, out Sprite sprite, InputGlyphDatabase db = null)
|
2025-12-09 20:31:44 +08:00
|
|
|
{
|
2025-12-10 17:38:31 +08:00
|
|
|
string path = GetBindingControlPath(reference, device);
|
|
|
|
|
return TryGetUISpriteForActionPath(path, device, out sprite, db);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static bool TryGetTMPTagForActionPath(string controlPath, InputDeviceWatcher.InputDeviceCategory device, out string tag, out string displayFallback, InputGlyphDatabase db = null)
|
|
|
|
|
{
|
|
|
|
|
tag = null;
|
|
|
|
|
displayFallback = null;
|
|
|
|
|
db = db ?? Database;
|
|
|
|
|
|
|
|
|
|
displayFallback = GetDisplayNameFromControlPath(controlPath);
|
|
|
|
|
|
|
|
|
|
var sprite = db.FindSprite(controlPath, device) ?? db.FindSprite(controlPath, InputDeviceWatcher.InputDeviceCategory.Keyboard);
|
|
|
|
|
|
|
|
|
|
var spriteName = sprite == null ? string.Empty : sprite.name;
|
|
|
|
|
tag = $"<sprite name=\"{spriteName}\">";
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static bool TryGetUISpriteForActionPath(string controlPath, InputDeviceWatcher.InputDeviceCategory device, out Sprite sprite, InputGlyphDatabase db = null)
|
|
|
|
|
{
|
|
|
|
|
sprite = null;
|
|
|
|
|
db = db ?? Database;
|
|
|
|
|
if (string.IsNullOrEmpty(controlPath) || db == null) return false;
|
|
|
|
|
sprite = db.FindSprite(controlPath, device) ?? db.FindSprite(controlPath, InputDeviceWatcher.InputDeviceCategory.Keyboard);
|
|
|
|
|
return sprite != null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static InputBinding GetBindingControl(InputAction action, InputDeviceWatcher.InputDeviceCategory? deviceOverride = null)
|
|
|
|
|
{
|
|
|
|
|
if (action == null) return default;
|
2025-12-09 20:31:44 +08:00
|
|
|
|
|
|
|
|
var curCategory = deviceOverride ?? InputDeviceWatcher.CurrentCategory;
|
|
|
|
|
var hints = GetDeviceHintsForCategory(curCategory);
|
|
|
|
|
|
2025-12-10 17:38:31 +08:00
|
|
|
foreach (var binding in action.bindings)
|
2025-12-09 20:31:44 +08:00
|
|
|
{
|
2025-12-10 17:38:31 +08:00
|
|
|
var deviceName = binding.path ?? string.Empty;
|
2025-12-09 20:31:44 +08:00
|
|
|
if (hints.Any(h => deviceName.IndexOf(h, StringComparison.OrdinalIgnoreCase) >= 0))
|
|
|
|
|
{
|
2025-12-10 17:38:31 +08:00
|
|
|
return binding;
|
2025-12-09 20:31:44 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-10 17:38:31 +08:00
|
|
|
return default;
|
2025-12-09 20:31:44 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static string[] GetDeviceHintsForCategory(InputDeviceWatcher.InputDeviceCategory cat)
|
|
|
|
|
{
|
|
|
|
|
switch (cat)
|
|
|
|
|
{
|
|
|
|
|
case InputDeviceWatcher.InputDeviceCategory.Keyboard:
|
|
|
|
|
return new[] { "Keyboard", "Mouse" };
|
|
|
|
|
case InputDeviceWatcher.InputDeviceCategory.Xbox:
|
|
|
|
|
return new[] { "XInput", "Xbox", "Gamepad" };
|
|
|
|
|
case InputDeviceWatcher.InputDeviceCategory.PlayStation:
|
|
|
|
|
return new[] { "DualShock", "DualSense", "PlayStation", "Gamepad" };
|
|
|
|
|
default:
|
2025-12-10 17:38:31 +08:00
|
|
|
return new[] { "XInput", "Xbox", "Gamepad" };
|
2025-12-09 20:31:44 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-05 19:04:53 +08:00
|
|
|
|
2025-12-10 17:38:31 +08:00
|
|
|
public static string GetDisplayNameFromInputAction(InputAction reference)
|
2025-12-05 19:04:53 +08:00
|
|
|
{
|
2025-12-17 20:03:29 +08:00
|
|
|
string controlPath = GetBindingControlPath(reference, InputDeviceWatcher.CurrentCategory);
|
2025-12-10 17:38:31 +08:00
|
|
|
return GetDisplayNameFromControlPath(controlPath);
|
2025-12-05 19:04:53 +08:00
|
|
|
}
|
2025-12-17 20:03:29 +08:00
|
|
|
|
2025-12-10 17:38:31 +08:00
|
|
|
public static string GetDisplayNameFromControlPath(string controlPath)
|
2025-12-05 19:04:53 +08:00
|
|
|
{
|
|
|
|
|
if (string.IsNullOrEmpty(controlPath)) return string.Empty;
|
|
|
|
|
var parts = controlPath.Split('/');
|
|
|
|
|
var last = parts[parts.Length - 1].Trim(new char[] { '{', '}', '<', '>', '\'', '"' });
|
|
|
|
|
return last;
|
|
|
|
|
}
|
|
|
|
|
}
|