This commit is contained in:
2026-06-07 11:49:55 +08:00
parent ff0f3bde54
commit 1897658a00
98 changed files with 9903 additions and 13907 deletions

View File

@@ -0,0 +1,104 @@
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using BaseGames.Core;
namespace BaseGames.UI
{
/// <summary>
/// 单个按键图标 Image 组件。
///
/// 支持两种查询模式:
/// • ByActionName推荐填写 ActionName如 "Interact"
/// 由 IInputIconService 自动解析当前设备 + 改键后的实际绑定路径 → 图标。
/// • ByBindingPath兼容/装饰用):直接填写固定路径(如 "&lt;Keyboard&gt;/space"
/// 适合教程截图等不跟随改键变化的场景。
///
/// ⚠️ 必须独立成文件(类名 = 文件名):作为可序列化的 MonoBehaviour
/// 若与其他类同处一个 .cs 文件二级类Unity 无法为其写出有效的 m_Script 引用,
/// 挂载后存盘 / 重载会变成"缺失脚本"。
/// </summary>
[RequireComponent(typeof(Image))]
public class InputIconImage : MonoBehaviour
{
public enum LookupMode { ByActionName, ByBindingPath }
[SerializeField] private LookupMode _mode = LookupMode.ByActionName;
[Tooltip("Action 名称,如 Interact / Jump / Attack仅 ByActionName 模式使用)")]
[SerializeField] private string _actionName;
[Tooltip("固定绑定路径,如 <Keyboard>/space仅 ByBindingPath 模式使用)")]
[SerializeField] private string _bindingPath;
private Image _image;
private IInputIconService _iconService;
// ── 静态注册表:替换 FindObjectsByTypeO(1) 注册/注销O(n) 广播 ────────
private static readonly List<InputIconImage> _registry = new();
/// <summary>通知注册表内所有已启用实例刷新图标(设备切换时调用)。</summary>
internal static void RefreshAll()
{
for (int i = _registry.Count - 1; i >= 0; i--)
{
if (_registry[i] != null) _registry[i].Refresh();
else _registry.RemoveAt(i); // 清理已销毁的残留引用
}
}
private void Awake() => _image = GetComponent<Image>();
private void OnEnable()
{
_iconService = ServiceLocator.GetOrDefault<IInputIconService>();
if (_iconService != null)
_iconService.OnIconSetChanged += Refresh;
_registry.Add(this);
Refresh();
}
private void OnDisable()
{
if (_iconService != null)
_iconService.OnIconSetChanged -= Refresh;
_registry.Remove(this);
}
/// <summary>刷新图标显示。设备切换或改键后由 InputDeviceIconSwitcher / InputIconService 调用。</summary>
public void Refresh()
{
if (_image == null) return;
// 若组件在 IInputIconService 注册前 Enable此处补重试并补订阅
if (_iconService == null)
{
_iconService = ServiceLocator.GetOrDefault<IInputIconService>();
if (_iconService != null)
_iconService.OnIconSetChanged += Refresh;
}
Sprite sprite = null;
if (_mode == LookupMode.ByActionName && !string.IsNullOrEmpty(_actionName))
{
sprite = _iconService?.GetActionIcon(_actionName);
}
else if (_mode == LookupMode.ByBindingPath && !string.IsNullOrEmpty(_bindingPath))
{
// 使用固定路径在当前图标集查找(不随改键变化),适合装饰性按键说明
sprite = _iconService?.GetPathIcon(_bindingPath);
}
if (sprite != null)
{
_image.sprite = sprite;
_image.enabled = true;
}
else
{
_image.enabled = false;
}
}
}
}