Files
zeling_v2/Assets/_Game/Scripts/UI/MainMenu/NewGameModeController.cs
2026-06-07 11:49:55 +08:00

111 lines
4.9 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.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
{
/// <summary>
/// 新游戏模式(难度)选择面板,<b>数据驱动</b>:据 <see cref="NewGameModeConfigSO"/> 生成难度按钮,
/// 经 <see cref="IUINavigator"/> 模态压栈,返回 <see cref="DifficultyLevel"/>
/// 点返回 / 按 ESC 取消则返回 null由 <see cref="UIResultPanel{T}"/> 兜底)。
/// 选中某项时在共享说明区显示其 descKey手柄/鼠标导航通用)。
/// 策划改 UI_NewGameModeConfig 即可增删/重排难度、改标签/说明;样式改 UI_NewGameModePanel / UI_MainMenu_Button 预制件。
/// </summary>
public class NewGameModeController : UIResultPanel<DifficultyLevel?>
{
[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();
/// <summary>默认焦点:第一项(通常普通难度),避免误选高难项。</summary>
protected override GameObject ResolveFirstSelected()
=> _firstButton != null ? _firstButton.Button.gameObject
: _btnBack != null ? _btnBack.gameObject : null;
/// <summary>据配置重建难度按钮public 以便编辑器预览/测试)。</summary>
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);
}
/// <summary>弹出难度选择并等待结果DifficultyLevel / null=取消)。由导航器压栈管理。</summary>
public Task<DifficultyLevel?> ShowAsync(CancellationToken ct = default)
{
var nav = GetService<IUINavigator>();
if (nav == null)
{
Debug.LogError("[NewGameMode] 未找到 IUINavigator 服务,无法弹出模式选择。", this);
return Task.FromResult<DifficultyLevel?>(null);
}
return nav.PushForResultAsync<DifficultyLevel?>(this, ct);
}
}
}