using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using UnityEngine; using UnityEngine.UI; using UnityEngine.EventSystems; using TMPro; using BaseGames.Core.Events; using BaseGames.Localization; namespace BaseGames.UI.MainMenu { /// /// 新游戏模式(难度)选择面板,数据驱动:据 生成难度按钮, /// 经 模态压栈,返回 ; /// 点返回 / 按 ESC 取消则返回 null(由 兜底)。 /// 选中某项时在共享说明区显示其 descKey(手柄/鼠标导航通用)。 /// 策划改 UI_NewGameModeConfig 即可增删/重排难度、改标签/说明;样式改 UI_NewGameModePanel / UI_MainMenu_Button 预制件。 /// public class NewGameModeController : UIResultPanel { [Header("数据表 / 选项列表")] [SerializeField] private NewGameModeConfigSO _config; [Tooltip("难度按钮的父节点(通常挂 VerticalLayoutGroup)。")] [SerializeField] private Transform _container; [SerializeField] private MainMenuButtonView _buttonPrefab; [Header("引用")] [SerializeField] private LocalizedText _titleText; [Tooltip("当前选中难度的说明文本(随选中项切换)。")] [SerializeField] private TMP_Text _descText; [SerializeField] private Button _btnBack; // 取消 / ESC / 返回默认结果:未选择。 protected override DifficultyLevel? CancelResult => null; private readonly List<(MainMenuButtonView view, string descKey)> _options = new(); private MainMenuButtonView _firstButton; private GameObject _lastSelected; private void Awake() => _btnBack?.onClick.AddListener(() => Complete(null)); protected override void OnPanelOpen() => BuildMenu(); /// 默认焦点:第一项(通常普通难度),避免误选高难项。 protected override GameObject ResolveFirstSelected() => _firstButton != null ? _firstButton.Button.gameObject : _btnBack != null ? _btnBack.gameObject : null; /// 据配置重建难度按钮(public 以便编辑器预览/测试)。 public void BuildMenu() { ClearMenu(); if (_titleText != null && _config != null) _titleText.SetKey(_config.TitleKey); if (_config == null || _container == null || _buttonPrefab == null) return; foreach (var item in _config.Items) { var view = Instantiate(_buttonPrefab, _container); view.gameObject.SetActive(true); var level = item.level; view.Bind(item.labelKey, item.icon, () => Complete(level)); _options.Add((view, item.descKey)); if (_firstButton == null) _firstButton = view; } if (_descText != null) _descText.text = string.Empty; _lastSelected = null; } private void ClearMenu() { _options.Clear(); _firstButton = null; if (_container == null) return; for (int i = _container.childCount - 1; i >= 0; i--) { var c = _container.GetChild(i).gameObject; if (Application.isPlaying) Destroy(c); else DestroyImmediate(c); } } // 显示当前选中难度的说明(轮询 EventSystem 选中项;手柄/鼠标导航通用,按钮无需额外组件)。 private void Update() { if (_descText == null || EventSystem.current == null) return; var sel = EventSystem.current.currentSelectedGameObject; if (sel == _lastSelected) return; _lastSelected = sel; string descKey = null; foreach (var (view, dk) in _options) if (view != null && view.Button != null && view.Button.gameObject == sel) { descKey = dk; break; } _descText.text = string.IsNullOrEmpty(descKey) ? string.Empty : LocalizationManager.Get(descKey, LocalizationTable.UI); } /// 弹出难度选择并等待结果(DifficultyLevel / null=取消)。由导航器压栈管理。 public Task ShowAsync(CancellationToken ct = default) { var nav = GetService(); if (nav == null) { Debug.LogError("[NewGameMode] 未找到 IUINavigator 服务,无法弹出模式选择。", this); return Task.FromResult(null); } return nav.PushForResultAsync(this, ct); } } }