Story排版
This commit is contained in:
@@ -12,7 +12,8 @@ namespace Ichni.Story
|
||||
{
|
||||
Locked,
|
||||
Current,
|
||||
Completed
|
||||
Completed,
|
||||
Forbidden
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -25,6 +26,16 @@ namespace Ichni.Story
|
||||
Tutorial
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// TextBlock 的叙事层级。层级只决定剧情树中的视觉样式和 checkpoint 候选资格,
|
||||
/// 不会自行改变 Block 的解锁条件或 Yarn 执行逻辑。
|
||||
/// </summary>
|
||||
public enum TextBlockImportance
|
||||
{
|
||||
Important,
|
||||
Secondary
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 变量条件的比较方式。
|
||||
/// </summary>
|
||||
@@ -69,7 +80,18 @@ namespace Ichni.Story
|
||||
|
||||
[FoldoutGroup("$blockId")]
|
||||
[LabelText("Unlock Condition")]
|
||||
public UnlockCondition unlockCondition = new UnlockCondition();
|
||||
[InfoBox("留空表示无条件解锁(章节起始即可用)。")]
|
||||
public StoryCondition unlockCondition = new StoryCondition();
|
||||
|
||||
/// <summary>
|
||||
/// 用于禁用当前 Block 的可选条件。它与解锁条件共用同一种通用条件树,
|
||||
/// 因而可直接使用剧情变量、Block 完成状态及 AND / OR / NOT 组合。
|
||||
/// 条件满足时,该 Block 的状态固定为 Forbidden,且优先于 Completed / Current / Locked。
|
||||
/// </summary>
|
||||
[FoldoutGroup("$blockId")]
|
||||
[LabelText("Forbidden Condition")]
|
||||
[InfoBox("可选。留空表示此 Block 不会被条件禁用;满足时显示为 Forbidden 且不可点击。")]
|
||||
public StoryCondition forbiddenCondition = new StoryCondition();
|
||||
|
||||
// ── Text Block ──────────────────────────────────────────────────────────
|
||||
|
||||
@@ -83,13 +105,35 @@ namespace Ichni.Story
|
||||
[LabelText("Title Key (Localization)")]
|
||||
public string titleKey;
|
||||
|
||||
/// <summary>
|
||||
/// TextBlock 的视觉和叙事层级。Important 用于主线转折与后续 checkpoint;
|
||||
/// Secondary 用于支线或补充剧情。默认 Important,以保持现有 TextBlock 的呈现语义。
|
||||
/// </summary>
|
||||
[FoldoutGroup("$blockId")]
|
||||
[ShowIf("blockType", StoryBlockType.Text)]
|
||||
[LabelText("Text Importance")]
|
||||
public TextBlockImportance textImportance = TextBlockImportance.Important;
|
||||
|
||||
// ── Song Block ──────────────────────────────────────────────────────────
|
||||
|
||||
[FoldoutGroup("$blockId")]
|
||||
[ShowIf("blockType", StoryBlockType.Song)]
|
||||
[LabelText("Song Name")]
|
||||
[LabelText("Song Name (Stable ID)")]
|
||||
[InfoBox("对应 ChapterSelectionUnit 中 SongItemData.songName 的稳定歌曲标识。它用于查找歌曲资料与进入选曲,不能填写 displaySongName、翻译文本或作曲者名称。")]
|
||||
public string songName;
|
||||
|
||||
/// <summary>
|
||||
/// 插画在 SongBlock 的 Mask 中使用的实际本地 Y 坐标。SongBlock 的 Illustration 固定为 400 x 225,
|
||||
/// Mask 可视区域固定为当前 Prefab 的尺寸;在不露出上下空白的前提下,安全范围为 -74.25 到 74.25。
|
||||
/// 该值是最终坐标而非偏移量:0 表示居中,负值向下移动,正值向上移动。
|
||||
/// </summary>
|
||||
[FoldoutGroup("$blockId")]
|
||||
[ShowIf("blockType", StoryBlockType.Song)]
|
||||
[LabelText("Illustration Local Y")]
|
||||
[Range(-74.25f, 74.25f)]
|
||||
[InfoBox("用于微调 16:9 插画在 SongBlock Mask 中的纵向裁切。请保持 SongBlockUI 的 Illustration 尺寸为 400 x 225。")]
|
||||
public float illustrationLocalY;
|
||||
|
||||
// ── Tutorial Block ──────────────────────────────────────────────────────
|
||||
|
||||
[FoldoutGroup("$blockId")]
|
||||
@@ -145,26 +189,35 @@ namespace Ichni.Story
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Block 的解锁条件。以一棵可组合的条件树(<see cref="StoryConditionNode"/>)表达,
|
||||
/// 支持"与 / 或 / 非 + 叶子条件"的任意嵌套。根节点为空时视为无条件解锁(始终满足)。
|
||||
/// 通用剧情条件容器。以一棵可组合的条件树(<see cref="StoryConditionNode"/>)表达,
|
||||
/// 支持“与 / 或 / 非 + 叶子条件”的任意嵌套。
|
||||
/// <para>该类型不限定用途,可用于 Block 的解锁、禁用、Helper 对话筛选等所有剧情判断。</para>
|
||||
/// <para>根节点为空表示“未配置条件”,其是否视为通过由调用方根据业务语义决定;
|
||||
/// 例如 unlockCondition 留空即允许,而 forbiddenCondition 留空即不禁用。</para>
|
||||
/// </summary>
|
||||
[InlineProperty]
|
||||
[Serializable]
|
||||
public class UnlockCondition
|
||||
public class StoryCondition
|
||||
{
|
||||
[HideLabel]
|
||||
[SerializeReference]
|
||||
[InfoBox("留空表示无条件解锁(章节起始即可用)。可选择 All Of(AND) / Any Of(OR) / Not 复合节点进行任意嵌套。")]
|
||||
[InfoBox("留空表示未配置条件。可选择 All Of(AND) / Any Of(OR) / Not 复合节点进行任意嵌套。")]
|
||||
public StoryConditionNode root;
|
||||
|
||||
/// <summary>
|
||||
/// 检查解锁条件是否满足。根节点为空视为满足。
|
||||
/// 当前容器是否已配置实际条件。
|
||||
/// </summary>
|
||||
public bool IsConfigured => root != null;
|
||||
|
||||
/// <summary>
|
||||
/// 检查已配置条件是否满足。根节点为空时返回 false;调用方应结合
|
||||
/// <see cref="IsConfigured"/> 决定“未配置条件”的业务含义。
|
||||
/// </summary>
|
||||
/// <param name="getVariable">按变量名返回其整型值的委托。</param>
|
||||
/// <param name="isBlockCompleted">按 blockId 判断该 block 是否已完成的委托。</param>
|
||||
public bool IsSatisfied(Func<string, int> getVariable, Func<string, bool> isBlockCompleted)
|
||||
{
|
||||
return root == null || root.Evaluate(getVariable, isBlockCompleted);
|
||||
return root != null && root.Evaluate(getVariable, isBlockCompleted);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user