Modules
std::system::nav
Stability: Stable — the operations that change the system’s mode stack.
std::system::nav holds the navigation operations. UI changes the mode stack only through these
functions and through the methods of the Narrative handle. All of them are builtin fns, so
they may be called from any fn code (button handlers, effects, exit handlers), but never from a
render or the story.
The prelude imports the module itself, so call the functions as nav::call(Config),
nav::back() and so on, without a use.
See Mode types for the kinds of modes and where each may sit on the stack.
Overview
| Function | Effect |
|---|---|
nav::call(o) | Pushes the overlay o |
nav::dialog(d) | Pushes the dialog d |
nav::back() | Pops the top mode; ignored on a base |
nav::goto(p) | Replaces the whole stack with the root page p |
nav::start(e, args, on_exit) | Replaces the stack with a new game running the entry scene e |
nav::load(slot) | Replaces the stack with the game restored from slot |
nav::quit() | Quits the program at once |
The operations on a running game are methods of the Narrative handle (see
std::narrative):
| Operation | Effect |
|---|---|
game.advance() | Sends NextStep to the story |
game.select(arm) | Selects a shown arm of the current choice |
game.save(slot) | Writes the running game to slot |
game.rewind(i) | Restores the story to backlog entry i |
game.call(o) | Pushes the game overlay o |
A handle exists only in the game view and in game overlays, so “needs a running game” is enforced by types: a Save button on the title page does not type-check.
Mode graph checks
At compile time, the compiler collects the nav operations each mode’s handlers can run and
builds a graph of the modes. It reports:
| Code | Problem |
|---|---|
W6001 | A mode no reachable mode opens, or a game that is never started |
E6002 | nav::back() in a mode at the base of the stack |
E6003 | A mode with no way out (no back, goto, start, load or quit, and no Action::Back binding) |
W6004 | Overlays that open each other with nav::call, so the stack can grow without bound |
See the game system diagnostics.
Function: call(overlay)
#[builtin] pub fn call(overlay: fn() -> Overlay);overlayfn() -> Overlay— the overlay component, as a function pointer.- Kind:
fn· Builtin: yes
Pushes the overlay over the current top mode. The overlay’s component runs once, when it is shown.
button!{on_click = || nav::call(Config), t!["Config"]}Function: dialog(dialog)
#[builtin] pub fn dialog(dialog: fn() -> Dialog);dialogfn() -> Dialog— the dialog component.- Kind:
fn· Builtin: yes
Pushes a modal dialog. The dialog is drawn over a still image of the modes below. A dialog must
offer a way out, usually a button calling nav::back() (E6003 otherwise).
fn ConfirmQuit() -> Dialog { Dialog(column![ t!["Quit the game?"], row![ button!{on_click = || nav::quit(), t!["Yes"]}, button!{on_click = || nav::back(), t!["No"]}, ], ])}Function: back()
#[builtin] pub fn back();- Kind:
fn· Builtin: yes
Pops the top mode, returning to the mode below. On a base mode (a root page or the game mode) it
does nothing at run time; a nav::back() the compiler can see running in a base mode is the error
E6002. To leave a root page, use nav::goto instead. Action::Back calls
nav::back().
Function: goto(page)
#[builtin] pub fn goto(page: fn() -> RootPage);pagefn() -> RootPage— the root page component.- Kind:
fn· Builtin: yes
Replaces the whole stack with the root page page. Called while a game runs, it ends the game;
for example, a “Back to title” button.
button!{on_click = || nav::goto(Title), t!["Back to title"]}Function: start(entry, args, on_exit)
#[builtin] pub fn start<E, A, R>(entry: E, args: A, on_exit: Fn(R));entryE— a pointer to an#[entry]scene, of typescene fn(P1, …, Pn) -> R.argsA— the tuple(P1, …, Pn)of the scene’s arguments.on_exitFn(R)— the exit handler; it receives the scene’s return value.- Kind:
fn· Builtin: yes
Replaces the stack with a new game that runs the entry scene entry with args. This is the only
way into the story.
- The typing of this signature is special: the compiler relates
E,AandRas above. See Compiler Rules. - The arguments have the entry scene’s finite parameter types. They are recorded in the save, and
they are how meta values reach the story: read a
Metawithget()in the system and pass it in. - When the entry scene returns, its value is passed to
on_exit. A return type such as anEndingenum is handled with an ordinary exhaustivematch. - If
on_exitnavigates nowhere, the stack resets to theSystem::startpage. - A new game starts fresh: story variables have their initial values. A replay of a scene is a
nav::startof a further#[entry]scene (see System Recipes).
fn start_button() -> Element { button!{on_click = || nav::start(story::Main, (CLEARED_AZUSA.get(),), on_ending), t!["Start"]}}
fn on_ending(ending: story::Ending) { match ending { story::Ending::AzusaEnd => { CLEARED_AZUSA.set(true); nav::goto(Credits) } story::Ending::NormalEnd => nav::goto(Credits), }}For an entry scene without arguments or result, pass () and a closure that ignores its
argument:
button!{on_click = || nav::start(story::Main, (), |_end| nav::goto(Title)), t!["Start"]}Function: load(slot)
#[builtin] pub fn load(slot: SaveSlot) -> Result<(), Divergence>;slotSaveSlot— the slot to load.- Returns:
Result<(), Divergence>—Ok(())when the game was restored;Err(divergence)when the save no longer fits the program. - Kind:
fn· Builtin: yes
Replaces the stack with the game restored from slot. A save records the path the player took;
if a later version of the script changed that path, the save diverges: load returns Err
and leaves the stack unchanged. Show the player
Divergence::describe().
use std::system::saves::SaveSlot;
fn Load() -> Overlay { let (error, set_error) = signal(""); Overlay(column![ button!{ on_click = || match nav::load(SaveSlot::Manual(0)) { Ok(()) => {} Err(divergence) => set_error(divergence.describe()), }, t!["Slot 1"], }, text!(error()), button!{on_click = || nav::back(), t!["Back"]}, ])}Function: quit()
#[builtin] pub fn quit();- Kind:
fn· Builtin: yes
Quits the program at once, without confirmation. A Quit button that should ask first opens a
Dialog the studio writes.
Last updated Oct 29, 2026