Files
ichni_Official/Assets/Scripts/NewStorySystem/Tree/TextBlockView.cs

108 lines
4.1 KiB
C#
Raw Normal View History

2026-07-05 16:08:23 -04:00
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;
2026-07-20 16:56:04 -04:00
[Tooltip("各状态对应的背景预制体。未配置 Forbidden 时会自动回退到 Locked 背景。")]
2026-07-05 16:08:23 -04:00
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;
}
2026-07-20 16:56:04 -04:00
if (blockVisuals == null)
2026-07-05 16:08:23 -04:00
{
Debug.LogWarning($"[TextBlockView] block '{blockId}' 缺少状态 {newState} 的背景预制体blockVisuals 未配置)。");
return;
}
2026-07-20 16:56:04 -04:00
// Forbidden 专用美术尚未配置前沿用 Locked 背景,保证互斥路线 Block 始终可见且不可点击。
// 后续只需在 Inspector 中补充 Forbidden 键,即可自动覆盖此回退表现。
if ((!blockVisuals.TryGetValue(newState, out GameObject prefab) || prefab == null) &&
newState == StoryBlockState.Forbidden)
{
blockVisuals.TryGetValue(StoryBlockState.Locked, out prefab);
}
if (prefab == null)
{
Debug.LogWarning($"[TextBlockView] block '{blockId}' 缺少状态 {newState} 的背景预制体。");
return;
}
2026-07-05 16:08:23 -04:00
_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);
}
}
}