AlicizaX/Client/Assets/InputGlyph/TestRebindScript.cs
陈思海 5862fb2af1 add
1.新增手柄相关适配
2.新增设备重映射绑定
3.新增设备映射图标更新
2025-12-09 20:31:44 +08:00

172 lines
5.6 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 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 int targetBindingIndex = -1;
private IDisposable prepareSub;
private IDisposable applySub;
private IDisposable rebindEndSub;
private void Start()
{
if (btn != null) btn.onClick.AddListener(OnBtnClicked);
InputDeviceWatcher.OnDeviceChanged += OnDeviceChanged;
ResolveBindingIndex();
UpdateBindingText();
if (InputBindingManager.Instance != null)
{
prepareSub = InputBindingManager.Instance.OnRebindPrepare.Subscribe(ctx =>
{
if (IsTargetContext(ctx))
{
var disp = ctx.overridePath == InputBindingManager.NULL_BINDING ? "<Cleared>" : 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 void ResolveBindingIndex()
{
var action = GetAction();
if (action == null)
{
Debug.LogError($"TestRebindScript: Action not found ('{actionName}').");
targetBindingIndex = -1;
return;
}
// Ask manager to choose best index for keyboard and optional composite part
targetBindingIndex = InputBindingManager.Instance.FindBestBindingIndexForKeyboard(action, string.IsNullOrEmpty(compositePartName) ? null : compositePartName);
}
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 && ctx.bindingIndex == targetBindingIndex;
}
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<bool> 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 = "<no action>";
if (targetImage != null) targetImage.sprite = null;
return;
}
// Ensure binding index is refreshed (action/bindings may change)
if (targetBindingIndex < 0 || targetBindingIndex >= action.bindings.Count)
ResolveBindingIndex();
if (targetBindingIndex < 0)
{
bindKeyText.text = "<no binding>";
if (targetImage != null) targetImage.sprite = null;
return;
}
string disp = action.GetBindingDisplayString(targetBindingIndex);
bindKeyText.text = string.IsNullOrEmpty(disp) ? "<unbound>" : disp;
// **Important**: use GlyphService with InputAction and device category (not manager-internal path)
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;
}
}
}