多轮审查和修复

This commit is contained in:
2026-05-12 15:34:08 +08:00
parent f55d2a57c3
commit ebbbb7332e
805 changed files with 838724 additions and 1905 deletions

View File

@@ -0,0 +1,113 @@
using System;
using TMPro;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.UI;
using BaseGames.Input;
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 = "按下新按键…";
_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));
}
}
}
}