2026-05-10 11:47:55 -04:00
|
|
|
|
using System;
|
|
|
|
|
|
using System.Collections.Generic;
|
2026-05-23 08:27:50 -04:00
|
|
|
|
using Cielonos.MainGame.Inventory;
|
2026-05-10 11:47:55 -04:00
|
|
|
|
using Sirenix.OdinInspector;
|
|
|
|
|
|
using SLSUtilities.UI;
|
|
|
|
|
|
using TMPro;
|
|
|
|
|
|
using UnityEngine;
|
|
|
|
|
|
using UnityEngine.UI;
|
|
|
|
|
|
|
|
|
|
|
|
namespace Cielonos.MainGame.UI
|
|
|
|
|
|
{
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 机械台 UI 页面。
|
|
|
|
|
|
/// 左侧为可选装备列表(Selector),右侧为物品详情面板(ItemDetailPanel)。
|
|
|
|
|
|
/// 玩家点击列表条目选中物品,点击 Confirm 确认获取。
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public class MechanicalTableUIPage : UIPageBase
|
|
|
|
|
|
{
|
|
|
|
|
|
[Title("Selectors")]
|
|
|
|
|
|
public GameObject selectorPrefab;
|
|
|
|
|
|
public RectTransform selectorContainer;
|
|
|
|
|
|
public List<MechanicalTableSelector> selectors = new List<MechanicalTableSelector>();
|
|
|
|
|
|
|
|
|
|
|
|
[Title("Detail Panel")]
|
|
|
|
|
|
public ItemDetailPanel itemDetailPanel;
|
|
|
|
|
|
|
|
|
|
|
|
[Title("Buttons")]
|
|
|
|
|
|
public Button confirmButton;
|
|
|
|
|
|
public Button closeButton;
|
|
|
|
|
|
|
|
|
|
|
|
private MechanicalTableSelector currentSelected;
|
|
|
|
|
|
private Action<int> onConfirmCallback;
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>当前选中的 Selector 索引,-1 表示未选中。</summary>
|
|
|
|
|
|
public int SelectedIndex => currentSelected != null ? selectors.IndexOf(currentSelected) : -1;
|
|
|
|
|
|
|
|
|
|
|
|
protected override void Start()
|
|
|
|
|
|
{
|
|
|
|
|
|
base.Start();
|
|
|
|
|
|
|
|
|
|
|
|
if (confirmButton != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
confirmButton.onClick.AddListener(OnConfirmClicked);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (closeButton != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
closeButton.onClick.AddListener(OnCloseClicked);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 用物品预制体列表填充选择器,并注册确认回调。
|
|
|
|
|
|
/// 每次调用会清除旧选择器并重新生成。
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="itemPrefabs">物品预制体列表,每个预制体必须包含 ItemBase 组件。</param>
|
|
|
|
|
|
/// <param name="onConfirm">玩家点击 Confirm 后的回调,参数为选中的物品索引。</param>
|
|
|
|
|
|
public void SetOffers(List<GameObject> itemPrefabs, Action<int> onConfirm)
|
|
|
|
|
|
{
|
|
|
|
|
|
onConfirmCallback = onConfirm;
|
|
|
|
|
|
|
|
|
|
|
|
ClearSelectors();
|
|
|
|
|
|
|
|
|
|
|
|
if (itemPrefabs == null) return;
|
|
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < itemPrefabs.Count; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
GameObject prefab = itemPrefabs[i];
|
|
|
|
|
|
if (prefab == null) continue;
|
|
|
|
|
|
|
|
|
|
|
|
ItemBase itemComponent = prefab.GetComponent<ItemBase>();
|
|
|
|
|
|
if (itemComponent == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
Debug.LogWarning($"[MechanicalTableUIPage] 预制体 '{prefab.name}' 缺少 ItemBase 组件,已跳过。");
|
|
|
|
|
|
continue;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
MechanicalTableSelector selector = CreateSelector();
|
|
|
|
|
|
selector.Setup(itemComponent);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 重置选中状态
|
|
|
|
|
|
currentSelected = null;
|
|
|
|
|
|
RefreshConfirmButton();
|
|
|
|
|
|
|
|
|
|
|
|
// 详情面板默认隐藏
|
|
|
|
|
|
if (itemDetailPanel != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
itemDetailPanel.ClearPanel();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 由 MechanicalTableSelector 调用,选中指定的选择器。
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public void SelectItem(MechanicalTableSelector selector)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (selector == null || !selectors.Contains(selector)) return;
|
|
|
|
|
|
|
|
|
|
|
|
// 取消上一个选中
|
|
|
|
|
|
if (currentSelected != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
currentSelected.SetSelected(false);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 设置新选中
|
|
|
|
|
|
currentSelected = selector;
|
|
|
|
|
|
currentSelected.SetSelected(true);
|
|
|
|
|
|
|
|
|
|
|
|
// 更新详情面板
|
|
|
|
|
|
if (itemDetailPanel != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
itemDetailPanel.SetItem(currentSelected.item);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 启用确认按钮
|
|
|
|
|
|
RefreshConfirmButton();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
protected override void OnPageOpened()
|
|
|
|
|
|
{
|
|
|
|
|
|
RefreshConfirmButton();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
protected override void OnPageClosed()
|
|
|
|
|
|
{
|
|
|
|
|
|
currentSelected = null;
|
|
|
|
|
|
onConfirmCallback = null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void OnConfirmClicked()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (currentSelected == null) return;
|
|
|
|
|
|
|
|
|
|
|
|
int index = SelectedIndex;
|
|
|
|
|
|
if (index < 0) return;
|
|
|
|
|
|
|
|
|
|
|
|
// 先缓存回调,因为 Close() 会清除引用
|
|
|
|
|
|
Action<int> callback = onConfirmCallback;
|
|
|
|
|
|
Close();
|
|
|
|
|
|
callback?.Invoke(index);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void OnCloseClicked()
|
|
|
|
|
|
{
|
|
|
|
|
|
Close();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private MechanicalTableSelector CreateSelector()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (selectorPrefab == null || selectorContainer == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
Debug.LogError("[MechanicalTableUIPage] selectorPrefab 或 selectorContainer 未配置。");
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
GameObject obj = Instantiate(selectorPrefab, selectorContainer);
|
|
|
|
|
|
MechanicalTableSelector selector = obj.GetComponent<MechanicalTableSelector>();
|
|
|
|
|
|
if (selector == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
Debug.LogError("[MechanicalTableUIPage] selectorPrefab 缺少 MechanicalTableSelector 组件。");
|
|
|
|
|
|
Destroy(obj);
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
selectors.Add(selector);
|
|
|
|
|
|
return selector;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void ClearSelectors()
|
|
|
|
|
|
{
|
|
|
|
|
|
foreach (MechanicalTableSelector selector in selectors)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (selector != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
Destroy(selector.gameObject);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
selectors.Clear();
|
|
|
|
|
|
currentSelected = null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void RefreshConfirmButton()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (confirmButton != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
confirmButton.interactable = currentSelected != null;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|