// TestRebindScript.cs using System; using System.Threading.Tasks; using TMPro; using UnityEngine; using UnityEngine.InputSystem; using InputRemapper; 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 IDisposable prepareSub; private IDisposable applySub; private IDisposable rebindEndSub; private void Start() { if (btn != null) btn.onClick.AddListener(OnBtnClicked); InputDeviceWatcher.OnDeviceChanged += OnDeviceChanged; UpdateBindingText(); if (InputBindingManager.Instance != null) { prepareSub = InputBindingManager.Instance.OnRebindPrepare.Subscribe(ctx => { if (IsTargetContext(ctx)) { var disp = ctx.overridePath == InputBindingManager.NULL_BINDING ? "" : ctx.overridePath; bindKeyText.text = disp; if (autoConfirm) _ = ConfirmPreparedAsync(); } }); applySub = InputBindingManager.Instance.OnApply.Subscribe(_ => UpdateBindingText()); rebindEndSub = InputBindingManager.Instance.OnRebindEnd.Subscribe(_ => UpdateBindingText()); } } private void OnDisable() { if (btn != null) btn.onClick.RemoveListener(OnBtnClicked); InputDeviceWatcher.OnDeviceChanged -= OnDeviceChanged; prepareSub?.Dispose(); applySub?.Dispose(); rebindEndSub?.Dispose(); } private void OnDeviceChanged(InputDeviceWatcher.InputDeviceCategory _) { UpdateBindingText(); } private InputAction GetAction() { return InputBindingManager.Action(actionName); } private bool IsTargetContext(InputRemapper.InputBindingManager.RebindContext ctx) { if (ctx == null || ctx.action == null) return false; var action = GetAction(); if (action == null) return false; return ctx.action == action; } private void OnBtnClicked() { // Use manager API (we pass part name so manager can pick proper binding if needed) 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(); if (task == null) return false; return await task; } catch (Exception ex) { Debug.LogError(ex); return false; } } public void CancelPrepared() { InputBindingManager.DiscardPrepared(); UpdateBindingText(); } private void UpdateBindingText() { var action = GetAction(); if (action == null) { bindKeyText.text = ""; if (targetImage != null) targetImage.sprite = null; return; } string disp = GlyphService.GetBindingControlPath(action, InputDeviceWatcher.CurrentCategory); bindKeyText.text = GlyphService.GetDisplayNameFromInputAction(action); try { var deviceCat = InputDeviceWatcher.CurrentCategory; string controlPath = GlyphService.GetBindingControlPath(action, deviceCat); if (!string.IsNullOrEmpty(controlPath) && GlyphService.TryGetUISpriteForActionPath(controlPath, deviceCat, out Sprite sprite)) { if (targetImage != null) targetImage.sprite = sprite; } else { if (targetImage != null) targetImage.sprite = null; } } catch { if (targetImage != null) targetImage.sprite = null; } } }