摄像机区域的架构改动
This commit is contained in:
113
Assets/_Game/Scripts/UI/Settings/RebindActionRow.cs
Normal file
113
Assets/_Game/Scripts/UI/Settings/RebindActionRow.cs
Normal 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/_Game/Scripts/UI/Settings/RebindActionRow.cs.meta
Normal file
11
Assets/_Game/Scripts/UI/Settings/RebindActionRow.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 788a8dd508aa2124f8247c9f04fdeaec
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
67
Assets/_Game/Scripts/UI/Settings/RebindPanel.cs
Normal file
67
Assets/_Game/Scripts/UI/Settings/RebindPanel.cs
Normal file
@@ -0,0 +1,67 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using BaseGames.Input;
|
||||
|
||||
namespace BaseGames.UI.Settings
|
||||
{
|
||||
/// <summary>
|
||||
/// 按键重绑定面板(架构 04_InputModule §6)。
|
||||
/// 统一管理所有 RebindActionRow;协调"同时只有一行处于重绑定状态"的排他锁;
|
||||
/// 提供"重置全部"按钮;绑定完成后自动持久化。
|
||||
/// 挂载路径:Canvas_Overlay → SettingsPanel → KeybindingTab → RebindPanel
|
||||
/// </summary>
|
||||
public class RebindPanel : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private InputReaderSO _inputReader;
|
||||
[SerializeField] private RebindActionRow[] _rows; // Inspector 配置,顺序对应 UI 布局
|
||||
[SerializeField] private Button _resetAllButton;
|
||||
[SerializeField] private ConflictDetector _conflictDetector;
|
||||
|
||||
// ── 生命周期 ──────────────────────────────────────────────────────
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
_resetAllButton?.onClick.AddListener(OnResetAll);
|
||||
|
||||
if (_rows == null) return;
|
||||
foreach (var row in _rows)
|
||||
row.Initialize(_inputReader, _conflictDetector, OnRebindRequested);
|
||||
}
|
||||
|
||||
// ── 供 RebindActionRow 反查行列表 ─────────────────────────────────
|
||||
|
||||
/// <summary>返回此面板管理的所有行(供 RebindActionRow 刷新冲突高亮时遍历)。</summary>
|
||||
public RebindActionRow[] GetRows() => _rows;
|
||||
|
||||
// ── 内部逻辑 ──────────────────────────────────────────────────────
|
||||
|
||||
/// <summary>由 RebindActionRow 点击时回调;实现排他锁(同时只允许一行重绑定)。</summary>
|
||||
private void OnRebindRequested(RebindActionRow requestingRow)
|
||||
{
|
||||
// 禁用其他所有行,防止并发重绑定操作
|
||||
if (_rows != null)
|
||||
foreach (var row in _rows)
|
||||
row.SetInteractable(row == requestingRow);
|
||||
|
||||
requestingRow.StartRebind(onFinished: () =>
|
||||
{
|
||||
// 重绑定完成(或取消)→ 恢复所有行可交互 → 持久化
|
||||
if (_rows != null)
|
||||
foreach (var row in _rows)
|
||||
row.SetInteractable(true);
|
||||
|
||||
_inputReader?.SaveBindingOverrides();
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>"重置全部"按钮回调:恢复默认绑定并刷新所有行显示。</summary>
|
||||
private void OnResetAll()
|
||||
{
|
||||
_inputReader?.ResetBindings();
|
||||
|
||||
if (_rows != null)
|
||||
foreach (var row in _rows)
|
||||
row.RefreshDisplay();
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/_Game/Scripts/UI/Settings/RebindPanel.cs.meta
Normal file
11
Assets/_Game/Scripts/UI/Settings/RebindPanel.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d2a1ab65135b4be43a738101f0a7eb84
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user