TH1/Unity/Assets/Scripts/TH1_UI/BoardingUI.cs
2026-01-06 00:45:20 +08:00

197 lines
7.8 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 UnityEngine;
using Logic;
using RuntimeData;
using Animancer;
using Logic.Config;
using UnityEngine.UI;
using Logic.Multilingual;
using TMPro;
using UI.Core;
using System.Linq;
using TH1_Logic.Config;
using UnityEngine.EventSystems;
using ConfigManager = TH1_Logic.Config.ConfigManager;
namespace UI
{
public class BoardingUI : CommonUI
{
private Transform _versionLabelList;
private Transform _versionContent;
// 新增:用于持有右侧详情描述文本的引用
private TextMeshProUGUI _versionDescriptionText;
public BoardingUI(GameObject UIObject, GameObject CloseButton) : base(UIObject, CloseButton)
{
InitData();
}
protected override void UpdateData()
{
//默认选中一个第一个
TriggerFirstVersionLabelClick();
}
private void TriggerFirstVersionLabelClick()
{
// 健壮性检查 #1: 确保列表Transform存在且有子节点
if (_versionLabelList == null || _versionLabelList.childCount == 0)
{
Debug.LogWarning("BoardingUI: _versionLabelList is empty, cannot trigger first item's click.");
return;
}
// step #1 获取第一个子节点的Transform
Transform firstChild = _versionLabelList.GetChild(0);
// step #2 从子节点上获取Button组件
Button firstButton = firstChild.GetComponent<Button>();
// 健壮性检查 #2: 确保Button组件存在
if (firstButton != null)
{
// step #3 调用onClick事件的Invoke方法执行所有绑定的监听器
firstButton.onClick.Invoke();
EventSystem.current.SetSelectedGameObject(firstButton.gameObject);
}
else
{
Debug.LogWarning($"BoardingUI: The first child '{firstChild.name}' of _versionLabelList does not have a Button component.", firstChild);
}
}
private void InitData()
{
// step #0 找到labellist列表对象找到content对象
_versionLabelList = UIObject.transform.Find("VersionLabelList/Viewport/Content");
_versionContent = UIObject.transform.Find("VersionContent/Viewport/Content");
// 健壮性检查
if (_versionLabelList == null)
{
Debug.LogError("BoardingUI: Can't find 'VersionLabelList/Viewport/Content' object.");
return;
}
if (_versionContent == null)
{
Debug.LogError("BoardingUI: Can't find 'VersionContent/Viewport/Content' object.");
return;
}
// 新增在Content中找到用于显示描述的TextMeshProUGUI组件
_versionDescriptionText = _versionContent.GetComponentInChildren<TextMeshProUGUI>();
if (_versionDescriptionText == null)
{
Debug.LogError("BoardingUI: Can't find TextMeshProUGUI component in children of 'VersionContent'.");
return;
}
// step #1 清空versionLabelList (使用更安全的方式清空)
for (int i = _versionLabelList.childCount - 1; i >= 0; i--)
{
GameObject.Destroy(_versionLabelList.GetChild(i).gameObject);
}
// step #2 获取数据和预制体
var pref = Resources.Load<GameObject>("Prefab/UI/VersionLabelListItem");
if (pref == null)
{
Debug.LogError("BoardingUI: Failed to load prefab 'Prefab/UI/VersionLabelListItem'");
return;
}
var vers = ConfigManager.Instance.VersionCfg.Versions;
// 如果没有任何版本信息,则清空描述并返回
if (vers == null || vers.Count == 0)
{
UpdateContent(null); // 清空右侧内容
return;
}
// 新增:创建一个变量,用于存储第一个需要被选中的按钮
Button firstButtonToSelect = null;
// step #3 新建每一个versionlabel绑定点击事件
for (int i = 0; i <vers.Count; i++)
{
// 【重要】捕获当前循环的变量防止C#闭包陷阱
var versionInfo = vers[i];
GameObject instance = GameObject.Instantiate(pref, _versionLabelList);
var versionLabelMono = instance.GetComponent<VersionLabelMono>();
var txt = instance.transform.Find("Text")?.GetComponent<TextMeshProUGUI>();
// 新增:获取按钮组件并绑定事件
var button = instance.GetComponent<Button>();
if (versionLabelMono == null || txt == null || button == null)
{
Debug.LogError($"Prefab 'VersionLabelListItem' is incomplete. Check for VersionLabelMono, Text child, and Button component on instance {instance.name}", instance);
continue; // 跳过这个不完整的项
}
versionLabelMono.VersionId = versionInfo.VersionId;
// 使用字符串插值,代码更清晰
txt.text = $"Demo V{versionInfo.MajorVersion}.{versionInfo.MinorVersion}.{versionInfo.PatchVersion}";
// 为按钮添加点击监听器
button.onClick.AddListener(() =>
{
// 当按钮被点击时调用UpdateContent方法并传入这个按钮对应的versionInfo
UpdateContent(versionInfo);
});
// 默认选中第一个生成的标签(即最新的版本)
if (i == 0)
{
UpdateContent(versionInfo);
firstButtonToSelect = button; // 记录下这个按钮
}
// 新增:在所有标签都创建完毕后,正式设置选中状态
if (firstButtonToSelect != null && EventSystem.current != null)
{
// 使用EventSystem来程序化地“选中”一个UI元素
// 这会触发按钮的 "Selected" 状态,显示高亮颜色或更换图片
EventSystem.current.SetSelectedGameObject(firstButtonToSelect.gameObject);
}
}
}
/// <summary>
/// 根据传入的VersionInfo更新右侧内容面板
/// </summary>
/// <param name="info">版本信息如果为null则清空内容</param>
private void UpdateContent(VersionInfo info)
{
if (_versionDescriptionText == null) return;
if (info != null)
{
// 将描述信息设置到文本组件上
MultilingualManager.Instance.SetUIText(_versionDescriptionText,info.Description); // 假设字段名为 Description
}
else
{
// 如果没有信息传入,则显示空或默认提示
_versionDescriptionText.text = "No version selected.";
}
// --- 就下面这两行 ---
// 步骤1: 强制刷新Content的布局确保获取到正确的高度
LayoutRebuilder.ForceRebuildLayoutImmediate(_versionContent.GetComponent<RectTransform>());
// 步骤2: 将滚动位置设置到最顶部 (1 = Top, 0.5 = Center, 0 = Bottom)
UIObject.transform.Find("VersionContent").GetComponent<ScrollRect>().verticalNormalizedPosition = 1f;
}
}
}