阶段性完成
This commit is contained in:
@@ -2,6 +2,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using Sirenix.OdinInspector;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Localization;
|
||||
|
||||
namespace Ichni.Story
|
||||
{
|
||||
@@ -147,9 +148,9 @@ namespace Ichni.Story
|
||||
|
||||
[FoldoutGroup("$EditorHeader/Text Content")]
|
||||
[ShowIf("blockType", StoryBlockType.Text)]
|
||||
[LabelText("Title Key")]
|
||||
[Tooltip("该 TextBlock 标题使用的 Unity Localization Entry Key;留空时视觉层可使用 Block ID 作为开发阶段回退。")]
|
||||
public string titleKey;
|
||||
[LabelText("Title")]
|
||||
[Tooltip("该 TextBlock 的 Unity Localization String Reference。请在此直接选择 String Table 与 Entry;留空时视觉层使用 Block ID 作为开发阶段回退。")]
|
||||
public LocalizedString title = new LocalizedString();
|
||||
|
||||
/// <summary>
|
||||
/// TextBlock 的视觉和叙事层级。Important 用于主线转折与后续 checkpoint;
|
||||
@@ -229,7 +230,9 @@ namespace Ichni.Story
|
||||
{
|
||||
string title = blockType switch
|
||||
{
|
||||
StoryBlockType.Text => titleKey,
|
||||
StoryBlockType.Text => this.title != null && !this.title.IsEmpty
|
||||
? this.title.TableEntryReference.ToString()
|
||||
: null,
|
||||
StoryBlockType.Song => songName,
|
||||
StoryBlockType.Tutorial => tutorialName,
|
||||
_ => null
|
||||
|
||||
@@ -3,7 +3,9 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Sirenix.OdinInspector;
|
||||
using UnityEditor;
|
||||
using UnityEditor.Localization;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Localization;
|
||||
|
||||
namespace Ichni.Story
|
||||
{
|
||||
@@ -146,10 +148,7 @@ namespace Ichni.Story
|
||||
issues.Add($"[Error] Timeline Marker '{marker.markerId}' 的 Anchor Block '{marker.anchorBlockId}' 不是 TextBlock。");
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(marker.labelKey))
|
||||
{
|
||||
issues.Add($"[Warning] Timeline Marker '{marker.markerId}' 未配置 Label Key。");
|
||||
}
|
||||
ValidateLocalizedString(marker.label, $"Timeline Marker '{marker.markerId}' Label", issues);
|
||||
}
|
||||
|
||||
ValidateTimelineMarkerAnchors(reachableBlockIds, issues);
|
||||
@@ -203,8 +202,10 @@ namespace Ichni.Story
|
||||
|
||||
switch (block.blockType)
|
||||
{
|
||||
case StoryBlockType.Text when string.IsNullOrWhiteSpace(block.yarnNodeName):
|
||||
issues.Add($"[Warning] TextBlock '{block.blockId}' 未配置 Yarn Node。");
|
||||
case StoryBlockType.Text:
|
||||
if (string.IsNullOrWhiteSpace(block.yarnNodeName))
|
||||
issues.Add($"[Warning] TextBlock '{block.blockId}' 未配置 Yarn Node。");
|
||||
ValidateLocalizedString(block.title, $"TextBlock '{block.blockId}' Title", issues);
|
||||
break;
|
||||
case StoryBlockType.Song when string.IsNullOrWhiteSpace(block.songName):
|
||||
issues.Add($"[Warning] SongBlock '{block.blockId}' 未配置 Song ID。");
|
||||
@@ -295,6 +296,36 @@ namespace Ichni.Story
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查 LocalizedString 是否已选择有效的 String Table 与 Entry。
|
||||
/// 只读取 Unity Localization 的 Shared Table Data,不加载 Addressables,也不修改资产;
|
||||
/// 因此可在 StoryData Inspector 中尽早发现 CSV 尚未导入或引用错误。
|
||||
/// </summary>
|
||||
private static void ValidateLocalizedString(
|
||||
LocalizedString reference,
|
||||
string owner,
|
||||
List<string> issues)
|
||||
{
|
||||
if (reference == null || reference.IsEmpty)
|
||||
{
|
||||
issues.Add($"[Warning] {owner} 未配置 LocalizedString。");
|
||||
return;
|
||||
}
|
||||
|
||||
StringTableCollection tableCollection =
|
||||
LocalizationEditorSettings.GetStringTableCollection(reference.TableReference);
|
||||
if (tableCollection?.SharedData == null)
|
||||
{
|
||||
issues.Add($"[Error] {owner} 引用的 String Table '{reference.TableReference}' 不存在或无法读取 Shared Table Data。");
|
||||
return;
|
||||
}
|
||||
|
||||
if (tableCollection.SharedData.GetEntryFromReference(reference.TableEntryReference) == null)
|
||||
{
|
||||
issues.Add($"[Error] {owner} 引用的 Entry '{reference.TableEntryReference}' 不存在于 String Table '{tableCollection.TableCollectionName}'。");
|
||||
}
|
||||
}
|
||||
|
||||
private HashSet<string> ValidateStoryGraph(HashSet<string> blockIds, List<string> issues)
|
||||
{
|
||||
Dictionary<string, List<string>> adjacency = new Dictionary<string, List<string>>();
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using Sirenix.OdinInspector;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Localization;
|
||||
|
||||
namespace Ichni.Story
|
||||
{
|
||||
@@ -8,8 +9,8 @@ namespace Ichni.Story
|
||||
/// 一个章节 Timeline 标记的静态定义。
|
||||
/// <para>它不保存独立的横坐标:运行时始终跟随锚定 Block 的 <c>gridColumn</c>,
|
||||
/// 使时间轴与剧情树在横向拖动时保持对齐。</para>
|
||||
/// <para>显示文本和 ID 使用 Unity Localization 的 Entry Key;本阶段不绑定具体 String Table,
|
||||
/// 以便后续统一迁移本地化系统时集中配置。</para>
|
||||
/// <para>显示文本直接使用 <see cref="LocalizedString"/>,因此可在 Inspector 中选择
|
||||
/// String Table 与 Entry,并预览各语言的值。</para>
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
[InlineProperty]
|
||||
@@ -37,13 +38,13 @@ namespace Ichni.Story
|
||||
public string anchorBlockId;
|
||||
|
||||
/// <summary>
|
||||
/// Timeline 上显示的本地化文本 Key。通常用于时间描述,也可用于特殊叙事文本。
|
||||
/// Timeline 上显示的本地化文本。通常用于时间描述,也可用于特殊叙事文本。
|
||||
/// </summary>
|
||||
[HorizontalGroup("Identity")]
|
||||
[LabelText("Label Key")]
|
||||
[LabelWidth(54)]
|
||||
[Tooltip("Timeline 上显示的 Unity Localization Entry Key,通常用于时间或特殊叙事文本。")]
|
||||
public string labelKey;
|
||||
[LabelText("Label")]
|
||||
[LabelWidth(40)]
|
||||
[Tooltip("Timeline 上显示的 Unity Localization String Reference。请在此直接选择对应 String Table 与 Entry。")]
|
||||
public LocalizedString label = new LocalizedString();
|
||||
|
||||
/// <summary>
|
||||
/// 是否参与章节主线进度百分比计算。支线或纯装饰性时间标记应关闭此项。
|
||||
|
||||
Reference in New Issue
Block a user