Studio

FolioTier 1

scene-flow

Scene structure, routing arrows, and the vocabulary that moves a story between scenes.

Scene flow is the backbone of every Vizno story. A scene is a named unit of script - everything from a single line of dialogue to a long conversation belongs to exactly one scene, and every scene has a name you choose when you write it. That name is the address other parts of your script use to route the player forward, backward, or sideways through the story.

You reach for scene flow anytime you need to decide what happens next based on a player action or a story condition. The arrow notation is the connective tissue: write the destination scene name after an arrow at the end of a branch option, a conditional, or a jump, and Vizno will move the player there when that path is taken. A scene that has no outgoing arrows ends the story at that point, so a scene named "end" is just a convention - what actually matters is whether execution has anywhere left to go.

Scene names must be unique within a project. If two scenes share a name, routing becomes ambiguous and Vizno will flag an error before the project runs. Names are case-sensitive, so "Kitchen-Morning" and "kitchen-morning" are treated as different destinations.

A scene does not need to be defined before it is referenced. You can write a routing arrow pointing to a scene that appears later in the file, or even in a different file in the same project. Vizno resolves all scene addresses after the full script is loaded, not as it reads line by line. This means forward references are safe, but typos in destination names will only surface at that resolution step - not while you are writing.

Scenes have no built-in concept of "returning." When a player reaches a scene via an arrow, there is no implicit path back to where they came from. If you want hub-and-spoke navigation - a location the player revisits - you need each spoke to carry its own arrow back to the hub scene explicitly. Relying on scene flow alone to manage a complex map of locations gets unwieldy quickly; for that kind of structure, consider pairing it with flags or a state variable so you can route conditionally rather than duplicating scenes.

Reference page - scene flow isn't a verb. This page collects the shape of a Folio scene file and the routing vocabulary that connects scenes together.

Scene file shape

Scene identity (id and title) lives in canonical project metadata, not in source. Each scene's source is just its body of events; the project's sceneSeed buffer slices into per-scene chunks with # scene <id> comment markers.

# scene kitchen-morning

bg bg-kitchen-morning
say "Emma": "Morning, sleepyhead."

The id is whatever the canonical scene carries (a UUID for scenes created in Studio, a slug for legacy or imported scenes). Titles are edited via the studio scene panel and are not parsed from the source.

Routing vocabulary

Scenes flow into each other in two ways:

  1. Natural order. When a scene's last block finishes, playback advances to the next scene in timeline order. No explicit next -> line needed.
  2. Explicit jumps. Use jump, call, when, or choice to route somewhere that isn't the next scene.

| Verb | Form | What it does | |---|---|---| | jump | jump <target> | Unconditional transfer - never returns | | call | call <target> | Jump-with-return - the called scene runs, then return brings execution back | | when | when <cond>: + optional else: | Conditional block - runs inline steps (e.g. a jump) only while the condition holds. For a two-way scene branch, jump inside the body and the else: branch (or pair a guarded jump <a> if <cond> with a jump <b>) | | choice | option "<label>" -> <target> (per child line) | Player-driven branch - each option carries its own arrow |

Each routing target is a scene ID or the literal end.

End-points

Two verbs end execution explicitly:

  • end - terminates the story branch. The player runtime treats this as a "you reached an ending" marker.
  • return - pops a call frame. Returning from the top-level scene is equivalent to end.

jump end and option "..." -> end are common - they mark a branch terminus without a named exit scene.

Conditional tails

Most verbs (including the routing ones) carry an optional if <cond> tail. A conditional jump if <cond> is a common shorthand for the two-way when <cond>: / else: shape when the false target is the next block in source order. Use the explicit when block for clarity in the Story Map; reserve the tail form for narrow guards on side-effecting verbs (set love = love + 1 if emma-route).

Importer translation

The Ren'Py shapes lower predictably:

| Ren'Py | Folio | |---|---| | label scene_one:
... | # scene scene-one
(body…) | | jump scene_two | jump scene-two | | call scene_subroutine
return | call scene-subroutine
(implicit return in callee scene) | | menu:
"Pick":
jump branch_a | choice:
option "Pick" -> branch-a | | if love >= 5:
jump good_route
else:
jump neutral_route | when love >= 5:
jump good-route
else:
jump neutral-route |

Menus with embedded code (Python in option bodies, set between options, non-jump terminal lines) lower into a choice plus a small per-option scene that runs the body before the routing. The read-only migration report shows the original Ren'Py menu beside the Folio it became, and flags any option line the importer couldn't lower.

See also

  • jump - unconditional transfer
  • call - jump-with-return
  • when - conditional block; branch by pairing a body jump with an else: branch
  • choice - player-driven branch
  • return - pop a call frame
  • end - terminate a branch