96 lines
3.5 KiB
C#
96 lines
3.5 KiB
C#
using System.Collections.Generic;
|
||
using Ichni.Story.Dialogue;
|
||
using TMPro;
|
||
using UnityEngine;
|
||
|
||
namespace Ichni.Story.UI
|
||
{
|
||
/// <summary>
|
||
/// 文本块视图。点击后(阶段 2)将通过 Yarn Spinner 进入对应节点的对话。
|
||
/// </summary>
|
||
public class TextBlockView : StoryBlockView
|
||
{
|
||
[Header("Text Block")]
|
||
public TMP_Text storyIdText;
|
||
public TMP_Text titleText;
|
||
|
||
[Tooltip("三种状态对应的背景预制体,生成 block 时按当前状态实例化为第一个子物体")]
|
||
public Dictionary<StoryBlockState, GameObject> blockVisuals = new Dictionary<StoryBlockState, GameObject>();
|
||
|
||
/// <summary>该文本块对应的 Yarn 节点名。</summary>
|
||
public string YarnNodeName { get; private set; }
|
||
|
||
// 当前已实例化的状态背景对象;状态切换时销毁并替换
|
||
private GameObject _currentVisual;
|
||
|
||
public override void Initialize(StoryBlockDefinition def, Vector2 position, StoryBlockState blockState)
|
||
{
|
||
// 注意:base.Initialize 末尾会调用 ApplyState(state),届时已生成对应背景
|
||
base.Initialize(def, position, blockState);
|
||
|
||
YarnNodeName = def.yarnNodeName;
|
||
|
||
if (storyIdText != null)
|
||
storyIdText.text = def.blockId;
|
||
|
||
// 阶段 5 将接入 Unity Localization;此处占位直接显示 titleKey
|
||
if (titleText != null)
|
||
titleText.text = def.titleKey;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 应用状态:在基类逻辑(按钮可交互性)之外,切换到对应状态的背景视觉。
|
||
/// </summary>
|
||
public override void ApplyState(StoryBlockState newState)
|
||
{
|
||
base.ApplyState(newState);
|
||
UpdateVisual(newState);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 按当前状态实例化对应的背景预制体,作为第一个子物体(位于文本/端口/按钮之下),
|
||
/// 并拉伸铺满整个 block。状态切换时先销毁旧背景。
|
||
/// </summary>
|
||
private void UpdateVisual(StoryBlockState newState)
|
||
{
|
||
if (_currentVisual != null)
|
||
{
|
||
Destroy(_currentVisual);
|
||
_currentVisual = null;
|
||
}
|
||
|
||
if (blockVisuals == null ||
|
||
!blockVisuals.TryGetValue(newState, out GameObject prefab) ||
|
||
prefab == null)
|
||
{
|
||
Debug.LogWarning($"[TextBlockView] block '{blockId}' 缺少状态 {newState} 的背景预制体(blockVisuals 未配置)。");
|
||
return;
|
||
}
|
||
|
||
_currentVisual = Instantiate(prefab, blockRect);
|
||
_currentVisual.transform.SetAsFirstSibling();
|
||
|
||
// 背景铺满整个 block
|
||
if (_currentVisual.transform is RectTransform visualRect)
|
||
{
|
||
visualRect.anchorMin = Vector2.zero;
|
||
visualRect.anchorMax = Vector2.one;
|
||
visualRect.offsetMin = Vector2.zero;
|
||
visualRect.offsetMax = Vector2.zero;
|
||
visualRect.localScale = Vector3.one;
|
||
}
|
||
}
|
||
|
||
protected override void OnClicked()
|
||
{
|
||
if (StoryDialogueController.instance == null)
|
||
{
|
||
Debug.LogWarning($"[TextBlockView] 场景中缺少 StoryDialogueController,无法播放 block '{blockId}' 的对话。");
|
||
return;
|
||
}
|
||
|
||
StoryDialogueController.instance.PlayBlock(this);
|
||
}
|
||
}
|
||
}
|