Files
zeling_v2/Assets/_Game/Scripts/UI/Settings/RebindActionRow.cs
2026-05-25 11:54:37 +08:00

115 lines
5.0 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.
using System;
using TMPro;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.UI;
using BaseGames.Input;
using BaseGames.Localization;
namespace BaseGames.UI.Settings
{
/// <summary>
/// 单行按键重绑定 UI架构 04_InputModule §6
/// 显示 Action 名称 + 当前绑定路径;点击按钮触发交互式重绑定。
/// 由 RebindPanel.Initialize() 批量配置;不直接加载任何资产。
/// </summary>
public class RebindActionRow : MonoBehaviour
{
[Tooltip("对应 Input Action 的名称(与 InputActions 资产中 Gameplay Map 内的名称一致)")]
[SerializeField] private string _actionName;
[Tooltip("绑定索引0 = 主绑定1 = 副绑定(视 Action 定义而定)")]
[SerializeField] private int _bindingIndex;
[Header("UI 引用")]
[SerializeField] private TMP_Text _actionLabel; // 显示 Action 可读名(固定)
[SerializeField] private TMP_Text _currentBindingText; // 显示当前绑定路径
[SerializeField] private Button _bindButton; // 点击启动重绑定
private InputReaderSO _inputReader;
private ConflictDetector _conflictDetector;
private Action<RebindActionRow> _onRebindRequested;
// ── 初始化(由 RebindPanel 调用)──────────────────────────────────
public void Initialize(
InputReaderSO reader,
ConflictDetector detector,
Action<RebindActionRow> onRequest)
{
_inputReader = reader;
_conflictDetector = detector;
_onRebindRequested = onRequest;
if (_actionLabel != null)
_actionLabel.text = _actionName;
_bindButton.onClick.AddListener(() => _onRebindRequested?.Invoke(this));
RefreshDisplay();
}
// ── 重绑定流程 ────────────────────────────────────────────────────
/// <summary>启动交互式重绑定;完成或取消后调用 onFinished。</summary>
public void StartRebind(Action onFinished)
{
_currentBindingText.text = LocalizationManager.Get("REBIND_WAITING_PROMPT", LocalizationTable.UI);
_inputReader.StartRebinding(
_actionName,
_bindingIndex,
onComplete: () =>
{
RefreshDisplay();
RefreshConflicts();
onFinished?.Invoke();
},
onCancel: () =>
{
RefreshDisplay();
onFinished?.Invoke();
});
}
// ── 显示刷新 ──────────────────────────────────────────────────────
/// <summary>从 InputReaderSO 读取当前绑定路径并更新文字。</summary>
public void RefreshDisplay()
{
if (_inputReader == null) return;
var action = _inputReader.FindAction(_actionName);
if (action == null || _bindingIndex >= action.bindings.Count)
{
_currentBindingText.text = "—";
return;
}
var path = action.bindings[_bindingIndex].effectivePath;
_currentBindingText.text = string.IsNullOrEmpty(path)
? "—"
: InputControlPath.ToHumanReadableString(
path,
InputControlPath.HumanReadableStringOptions.OmitDevice);
}
/// <summary>冲突状态着色:红色 = 与其他 Action 路径冲突,白色 = 正常。</summary>
public void SetConflictHighlight(bool conflict)
=> _currentBindingText.color = conflict ? Color.red : Color.white;
/// <summary>是否允许用户点击此行的绑定按钮。</summary>
public void SetInteractable(bool interactable)
=> _bindButton.interactable = interactable;
// ── 内部 ──────────────────────────────────────────────────────────
/// <summary>重绑定完成后扫描 Panel 内所有行,更新冲突高亮。</summary>
private void RefreshConflicts()
{
if (_conflictDetector == null || _inputReader == null) return;
var conflicts = _conflictDetector.FindConflicts(_inputReader.GetAllActionMap());
foreach (var row in GetComponentsInParent<RebindPanel>(includeInactive: true)
[0]?.GetRows() ?? Array.Empty<RebindActionRow>())
{
row.SetConflictHighlight(conflicts.Contains(row._actionName));
}
}
}
}