Files
Cielonos/Assets/Scripts/MainGame/UI/Common/InteractionPage/InteractionUIArea.cs
SoulliesOfficial 6d7ebc5825 Passion & UI
2026-06-12 17:11:39 -04:00

130 lines
4.4 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 Cielonos.Core.Interaction;
using DG.Tweening;
using Sirenix.OdinInspector;
using SLSUtilities.UI;
using UnityEngine;
namespace Cielonos.UI
{
/// <summary>
/// 交互选项列表 UI 页面。
/// 玩家进入可交互物体范围时由 PlayerInteractionSubcontroller 调用 Show(),离开时调用 Hide()。
/// 当选项数量为 1 时,直接显示单个选项而不需要导航;
/// 当选项数量大于 1 时,玩家可用鼠标滚轮或上/下键切换高亮选项R 键执行。
/// </summary>
public class InteractionUIArea : UIElementBase
{
[Title("容器")]
[Tooltip("单个选项条目的预制体,需包含 InteractionChoiceItem 组件。")]
[SerializeField] private GameObject choiceItemPrefab;
[Tooltip("选项条目的父节点Layout Group。")]
[SerializeField] private RectTransform choiceContainer;
private readonly List<InteractionChoiceItem> _items = new List<InteractionChoiceItem>();
private void Start()
{
Hide();
}
// ====================================================================
// 对外接口
// ====================================================================
/// <summary>
/// 显示选项列表并高亮指定索引的选项。
/// 由 PlayerInteractionSubcontroller.SetCurrentInteractable() 调用。
/// </summary>
public void Show(List<InteractionChoice> choices, int selectedIndex)
{
gameObject.SetActive(true);
canvasGroup.DOFade(1f, 0.25f).From(0).OnComplete(() =>
{
canvasGroup.interactable = true;
canvasGroup.blocksRaycasts = true;
}).Play();
rectTransform.DOLocalMoveY(-50f, 0.25f).From(-250f).Play();
ClearItems();
if (choices == null || choices.Count == 0)
{
gameObject.SetActive(false);
return;
}
foreach (InteractionChoice choice in choices)
{
InteractionChoiceItem item = CreateItem();
if (item != null)
{
item.Setup(choice.choiceName, choice.isInteractable);
}
}
UpdateHighlight(selectedIndex);
}
/// <summary>
/// 更新高亮选项。由 PlayerInteractionSubcontroller.NavigateChoice() 调用。
/// </summary>
public void UpdateHighlight(int selectedIndex)
{
for (int i = 0; i < _items.Count; i++)
{
_items[i].SetHighlighted(i == selectedIndex);
}
}
/// <summary>
/// 隐藏选项列表。由 PlayerInteractionSubcontroller.RemoveCurrentInteractable() 调用。
/// </summary>
public override void Hide()
{
canvasGroup.interactable = false;
canvasGroup.blocksRaycasts = false;
canvasGroup.DOFade(0f, 0.25f).OnComplete(() =>
{
ClearItems();
gameObject.SetActive(false);
}).Play();
rectTransform.DOLocalMoveY(-250f, 0.25f).Play();
}
// ====================================================================
// 内部工具
// ====================================================================
private InteractionChoiceItem CreateItem()
{
if (choiceItemPrefab == null || choiceContainer == null)
{
Debug.LogError("[InteractionUIPage] choiceItemPrefab 或 choiceContainer 未在 Inspector 中配置。");
return null;
}
GameObject go = Instantiate(choiceItemPrefab, choiceContainer);
InteractionChoiceItem item = go.GetComponent<InteractionChoiceItem>();
if (item == null)
{
Debug.LogError("[InteractionUIPage] choiceItemPrefab 缺少 InteractionChoiceItem 组件。");
Destroy(go);
return null;
}
_items.Add(item);
return item;
}
private void ClearItems()
{
foreach (InteractionChoiceItem item in _items)
{
if (item != null) Destroy(item.gameObject);
}
_items.Clear();
}
}
}