using System; using System.Collections.Generic; using System.Threading.Tasks; using TMPro; using UnityEngine; using UnityEngine.InputSystem; using UnityEngine.UI; public class TestRebindScript : MonoBehaviour { [Header("UI")] public UXButton btn; public TextMeshProUGUI bindKeyText; public Image targetImage; [Tooltip("如果不使用 actionReference,则用 name 在全局 manager 查找")] public string actionName = "movement"; [Header("Optional composite part (WASD style)")] [Tooltip("如果需要绑定 composite 的某一部分(例如 Up/Down/Left/Right),填这个;留空表示绑定非 composite 或整体 binding")] public string compositePartName = ""; [Header("Behavior")] [Tooltip("如果 true,在 Prepare 后自动调用 ConfirmApply() 并保存;否则等待手动 ConfirmPrepared()/CancelPrepared()")] public bool autoConfirm = false; /// /// 启动时初始化并订阅事件 /// private void Start() { if (btn != null) btn.onClick.AddListener(OnBtnClicked); InputDeviceWatcher.OnDeviceChanged += OnDeviceChanged; UpdateBindingText(); if (InputBindingManager.Instance != null) { // 订阅事件 InputBindingManager.Instance.OnRebindPrepare += OnRebindPrepareHandler; InputBindingManager.Instance.OnApply += OnApplyHandler; InputBindingManager.Instance.OnRebindEnd += OnRebindEndHandler; InputBindingManager.Instance.OnRebindConflict += OnRebindConflictHandler; } } /// /// 禁用时取消订阅事件 /// private void OnDisable() { if (btn != null) btn.onClick.RemoveListener(OnBtnClicked); InputDeviceWatcher.OnDeviceChanged -= OnDeviceChanged; if (InputBindingManager.Instance != null) { InputBindingManager.Instance.OnRebindPrepare -= OnRebindPrepareHandler; InputBindingManager.Instance.OnApply -= OnApplyHandler; InputBindingManager.Instance.OnRebindEnd -= OnRebindEndHandler; InputBindingManager.Instance.OnRebindConflict -= OnRebindConflictHandler; } } /// /// 重新绑定准备完成的处理器 /// private void OnRebindPrepareHandler(InputBindingManager.RebindContext ctx) { if (IsTargetContext(ctx)) { var disp = ctx.overridePath == InputBindingManager.NULL_BINDING ? "" : ctx.overridePath; bindKeyText.text = disp; if (autoConfirm) _ = ConfirmPreparedAsync(); } } /// /// 应用重新绑定的处理器 /// private void OnApplyHandler(bool success, HashSet appliedContexts) { if (appliedContexts != null) { // 仅当任何应用/丢弃的上下文与此实例匹配时才更新 foreach (var ctx in appliedContexts) { if (IsTargetContext(ctx)) { UpdateBindingText(); break; } } } } /// /// 重新绑定结束的处理器 /// private void OnRebindEndHandler(bool success, InputBindingManager.RebindContext context) { if (IsTargetContext(context)) { UpdateBindingText(); } } /// /// 重新绑定冲突的处理器 /// private void OnRebindConflictHandler(InputBindingManager.RebindContext prepared, InputBindingManager.RebindContext conflict) { // 如果准备的或冲突的上下文匹配此实例,则更新 if (IsTargetContext(prepared) || IsTargetContext(conflict)) { UpdateBindingText(); } } /// /// 设备变更的回调 /// private void OnDeviceChanged(InputDeviceWatcher.InputDeviceCategory _) { UpdateBindingText(); } /// /// 获取当前的输入操作 /// private InputAction GetAction() { return InputBindingManager.Action(actionName); } /// /// 判断上下文是否为目标上下文 /// private bool IsTargetContext(InputBindingManager.RebindContext ctx) { if (ctx == null || ctx.action == null) return false; var action = GetAction(); if (action == null) return false; // 必须匹配操作 if (ctx.action != action) return false; // 如果指定了复合部分,需要匹配绑定索引 if (!string.IsNullOrEmpty(compositePartName)) { // 获取上下文索引处的绑定 if (ctx.bindingIndex < 0 || ctx.bindingIndex >= action.bindings.Count) return false; var binding = action.bindings[ctx.bindingIndex]; // 检查绑定的名称是否与我们的复合部分匹配 return string.Equals(binding.name, compositePartName, StringComparison.OrdinalIgnoreCase); } // 如果未指定复合部分,仅匹配操作就足够了 return true; } /// /// 按钮点击的回调 /// private void OnBtnClicked() { // 使用管理器 API(我们传递部分名称,以便管理器可以在需要时选择适当的绑定) InputBindingManager.StartRebind(actionName, string.IsNullOrEmpty(compositePartName) ? null : compositePartName); } /// /// 确认准备好的重新绑定(公共方法) /// public async void ConfirmPrepared() { bool ok = await ConfirmPreparedAsync(); if (!ok) Debug.LogError("ConfirmPrepared: apply failed."); } /// /// 确认准备好的重新绑定(异步) /// private async Task ConfirmPreparedAsync() { try { var task = InputBindingManager.ConfirmApply(); return await task; } catch (Exception ex) { Debug.LogError(ex); return false; } } /// /// 取消准备好的重新绑定 /// public void CancelPrepared() { InputBindingManager.DiscardPrepared(); // UpdateBindingText 将通过 OnApply 事件自动调用 } /// /// 更新绑定文本和图标显示 /// private void UpdateBindingText() { var action = GetAction(); if (action == null) { bindKeyText.text = ""; if (targetImage != null) targetImage.sprite = null; return; } bindKeyText.text = GlyphService.GetDisplayNameFromInputAction(action, compositePartName); try { var deviceCat = InputDeviceWatcher.CurrentCategory; InputActionReference refr=default; // string controlPath = GlyphService.GetBindingControlPath(action, compositePartName, deviceCat); if ( GlyphService.TryGetUISpriteForActionPath(action,compositePartName, deviceCat, out Sprite sprite)) { if (targetImage != null) targetImage.sprite = sprite; } else { if (targetImage != null) targetImage.sprite = null; } } catch { if (targetImage != null) targetImage.sprite = null; } } }