using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; using TMPro; using BaseGames.Core.Events; namespace BaseGames.UI.HUD { public class HUDController : MonoBehaviour { [Header("HP")] [SerializeField] private Transform _hpContainer; [SerializeField] private GameObject _hpCellPrefab; [Header("Gauges")] [SerializeField] private Image _soulGaugeFill; [SerializeField] private Image _spiritGaugeFill; [SerializeField] private TMP_Text _lingZhuText; [Header("Spring Charges")] [SerializeField] private Transform _springContainer; [SerializeField] private GameObject _springIconPrefab; [Header("Form")] [SerializeField] private Image[] _formIcons; [Header("Interact Prompt")] [Tooltip("独立 Widget 组件负责渲染图标+文本,HUDController 仅保留引用供编辑器配置检查")] [SerializeField] private InteractPromptWidget _interactPromptWidget; [Header("Event Channels - Subscribe")] [SerializeField] private IntEventChannelSO _onHPChanged; [SerializeField] private IntEventChannelSO _onMaxHPChanged; [SerializeField] private IntEventChannelSO _onSoulPowerChanged; [SerializeField] private IntEventChannelSO _onSpiritPowerChanged; [SerializeField] private IntEventChannelSO _onLingZhuChanged; [SerializeField] private IntEventChannelSO _onSpringChargesChanged; [SerializeField] private IntEventChannelSO _onFormChanged; private readonly List _hpCells = new(); private readonly List _springIcons = new(); private readonly CompositeDisposable _subs = new(); private int _lastLingZhu = int.MinValue; private void OnEnable() { _onHPChanged?.Subscribe(UpdateHP).AddTo(_subs); _onMaxHPChanged?.Subscribe(RebuildHPCells).AddTo(_subs); _onSoulPowerChanged?.Subscribe(UpdateSoul).AddTo(_subs); _onSpiritPowerChanged?.Subscribe(UpdateSpirit).AddTo(_subs); _onLingZhuChanged?.Subscribe(UpdateLingZhu).AddTo(_subs); _onSpringChargesChanged?.Subscribe(RebuildSpringIcons).AddTo(_subs); _onFormChanged?.Subscribe(UpdateFormIcon).AddTo(_subs); // 交互提示由独立的 InteractPromptWidget 组件处理,HUDController 不再直接订阅 } private void OnDisable() => _subs.Clear(); private void UpdateHP(int current) { for (int i = 0; i < _hpCells.Count; i++) if (_hpCells[i] != null) _hpCells[i].SetActive(i < current); } private void RebuildHPCells(int max) { if (_hpContainer == null || _hpCellPrefab == null) return; // 复用现有 Cell,仅在数量不足时 Instantiate 补充,超出时 SetActive(false) 而非 Destroy for (int i = 0; i < max; i++) { if (i < _hpCells.Count) _hpCells[i].SetActive(true); else _hpCells.Add(Instantiate(_hpCellPrefab, _hpContainer)); } for (int i = max; i < _hpCells.Count; i++) if (_hpCells[i] != null) _hpCells[i].SetActive(false); } private void UpdateSoul(int val) { if (_soulGaugeFill != null) _soulGaugeFill.fillAmount = val / 100f; } private void UpdateSpirit(int val) { if (_spiritGaugeFill != null) _spiritGaugeFill.fillAmount = val / 100f; } private void UpdateLingZhu(int val) { if (_lingZhuText == null || val == _lastLingZhu) return; _lastLingZhu = val; _lingZhuText.text = val.ToString(); } private void RebuildSpringIcons(int charges) { if (_springContainer == null || _springIconPrefab == null) return; // 复用已有图标,超出数量时 SetActive(false) for (int i = 0; i < charges; i++) { if (i < _springIcons.Count) _springIcons[i].SetActive(true); else _springIcons.Add(Instantiate(_springIconPrefab, _springContainer)); } for (int i = charges; i < _springIcons.Count; i++) if (_springIcons[i] != null) _springIcons[i].SetActive(false); } private void UpdateFormIcon(int formIndex) { if (_formIcons == null) return; for (int i = 0; i < _formIcons.Length; i++) if (_formIcons[i] != null) _formIcons[i].enabled = (i == formIndex); } } }