1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
//! Markdown story-import schema.
/// Imports a Markdown story file as a single declaration.
///
/// One `StoryImport` stands in for a whole branching, click-through story (a
/// visual-novel flow). The build parses the Markdown and expands the import
/// into the UI assets that play it: a [Screen](#screen) per page with a backdrop
/// [Sprite](#sprite), [TextLabel](#textlabel)s for narration and speaker
/// names, and [HitRegion](#hitregion)s wiring page to page, so `world.jsonl`
/// stays a single readable line while the story lives in the Markdown file.
///
/// The `source` file is CommonMark Markdown opening with a YAML frontmatter
/// block:
///
/// - frontmatter declares the story `title`, its `characters`, and an
/// optional `background` (a full-bleed image drawn behind the title menu,
/// dimmed so the light menu text stays readable over a bright photo)
/// - each `# heading` starts a node (a jump target)
/// - each paragraph is one click-through page of narration
/// - a paragraph opening `**id:**` attributes the line to a declared
/// character, shown as a name plate in that character's color
/// - a bullet list of links is a choice menu; each link targets a heading
/// (`[Into the wood](#the-wood)`)
/// - a paragraph that is a single link shows its label and jumps to its
/// target when clicked
/// - a lone link to an audio file is a media directive: `music` loops from
/// the next page onward until replaced, `sound` plays once when the next
/// page shows (`[music](assets/theme.ogg)`, `[sound](assets/door.wav)`);
/// these expand to [AudioClip](#audioclip) + [AudioCue](#audiocue) entries
/// - `` sets the backdrop image from the next page
/// onward; `` / `` / ``
/// place a character portrait at that stage position, bottom-anchored at
/// the image's own pixel size (scaled down if taller than the canvas).
/// Portraits persist until replaced; a `![bg]` change is a scene change
/// and clears them all. Images expand to [Texture](#texture) entries drawn
/// by [Sprite](#sprite)s. Directives may stack on adjacent lines in one
/// paragraph
/// - a node whose last page has no link falls through to the next heading
/// in document order; the final node ends the story
/// - a ```` ```story ```` fenced block scripts state. All story state is
/// named integer variables starting at `0` each playthrough (a flag is a
/// variable holding `1`): `set <var>` assigns 1, `clear <var>` assigns 0,
/// `set <var> = <int>` assigns, and `add <var> <int>` adds (negatives
/// subtract). Operations run when the next page (or choice menu) shows.
/// `if <condition> -> #node` jumps there instead of showing it, where a
/// condition is `<var>` (not zero), `not <var>` (zero), or a comparison
/// `<var> <op> <int>` with `<op>` one of `==` `!=` `<` `<=` `>` `>=`
/// - a choice link's quoted title gates the option with the same condition
/// grammar: `- [Ask her](#ask "if asked")`, `- [Buy](#shop "if gold >= 3")`
///
/// The stage's dialog box carries a quick row of reader controls: Log (a
/// dialogue-history overlay), Auto (pages turn on their own once revealed),
/// Skip (instant reveal and rapid turns, stopping at menus), and Save
/// (numbered save slots). A pulsing marker shows when a fully revealed page
/// waits for a click.
///
/// Play position and variables auto-save page by page (into the project's
/// save files); the generated title screen's Continue resumes
/// them, and finishing the story clears the auto-save. Save writes one of
/// three numbered slots, resumed from the title screen's Load. The title
/// menu keeps only the buttons that apply, laid out contiguously: Continue
/// appears once an auto-save exists and Load once a slot does, so a fresh
/// project shows just Start and Quit with no gap.
///
/// Under the editor's debug run, saving the `source` file hot-reloads the
/// story: the graph re-compiles and swaps into the running game in place,
/// keeping the current position (matched by heading). New image or audio
/// files still need a restart.
///
/// Any other Markdown construct (tables, other code fences, inline
/// emphasis, ...) is an error at build time, as are links to headings that
/// do not exist, undeclared speakers, and duplicate headings.
///
/// **Generated names** are prefixed with the import's own asset `name`
/// (`<name>_title`, `<name>_<node>_p0`, ...), so they never clash with
/// hand-authored assets.
///
/// Characters take a nested block, a one-line name, or a `{ ... }` flow map
/// (`ayame: { name: Ayame, color: [1.0, 0.85, 0.8] }`).
///
/// ```markdown
/// ---
/// title: The Crossroads
/// characters:
/// ayame:
/// name: Ayame
/// color: [1.0, 0.85, 0.8]
/// keeper: Innkeeper
/// ---
///
/// # inn
///
/// You wake at a roadside inn. A note rests on the pillow.
///
/// **ayame:** You came. I wasn't sure you would.
///
/// - [Into the wood](#wood)
/// - [Toward the shore](#shore)
/// ```
///
/// ```rust
/// # use concinnity_world::registry::build_only::StoryImport;
/// StoryImport {
/// source: "assets/crossroads.md".into(),
/// ..Default::default()
/// };
/// ```