Storyline+Dialog初步

This commit is contained in:
SoulliesOfficial
2026-07-05 16:08:23 -04:00
parent afa8a56e1d
commit d031afd075
464 changed files with 25716 additions and 4209 deletions

View File

@@ -0,0 +1,95 @@
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);
}
}
}