vn_view
One pure function, `View.build(model)`, from a view model to the widget tree of screen `amagiri_vn`, plus `View.portrait(model)`, which renders whichever of the two portrait shapes was registered.
vn_view — the conversation layer's presentation
One pure function, View.build(model), from a view model to the widget tree of
screen amagiri_vn, plus View.portrait(model), which renders whichever of the
two portrait shapes was registered.
It knows nothing about dialogue scripts, run state or any character. vn.vn
works all of that out and hands the finished numbers down, which is what lets
the look change without touching the state machine.
The model
| Field | Meaning |
|---|---|
speaker | the name plate |
text | the revealed part of the line, already cut to a codepoint boundary |
complete | the typewriter has reached the end |
emotion | which portrait frame this line asks for |
portrait | the spec Game.registerPortrait was given, or nil |
portraitKey | what the script called it, shown on the placeholder |
choices | { { text, selected } }, or nil while the line is simply spoken |
fading | 0..1 — the layer loses saturation as the valley forgets itself |
entering | play the open animation on this build |
Portraits
{ sheet, cols, rows, frames = { <emotion> = index } } is drawn by scaling the
whole strip to cols × rows portrait boxes and sliding it under a clipping
window one box wide — the frame index is 1-based and row-major.
{ images = { <emotion> = texture } } draws every image the spec carries,
stacked, all but the current one at zero opacity. A texture materialises the
first time it is asked for, so a portrait with one image per emotion would
otherwise flash the engine's not-yet-loaded placeholder each time the line
changes the face.
A texture may arrive as a resolved asset proxy or as a plain string; either
resolves to something the image widget's src accepts.
With no spec, or a spec naming nothing usable, the slot draws a placeholder carrying the portrait key and the current emotion — so the layer stays legible, and the emotion swap stays provable, before any art exists.
Callback ids
vn:advance on the box, vn:choice:<n> on each choice row. vn.vn owns them
through ui.registerCallbackEnv.
Scoped to this part · feeds back into the world's score.