Data, events and lists
Your game and its UI agree on two things: data paths the UI reads, and event names the UI sends. That’s the whole contract. Re-export the UI as often as you like and game code doesn’t change.
Bindings
Bind a layer property to a data path:
| Property | Example |
|---|---|
text |
player.name |
value, max |
Progress bars: player.hp, player.hpMax |
visible |
hud.showCrit (prefix with ! to negate: !store.any) |
opacity |
ui.fade |
disabled |
!shop.canAfford |
Text layers can also use templates: {player.hp} / {player.hpMax}. A path the data doesn’t have leaves the template visible, on purpose, so you notice.
From the game:
ui.set_data("player.hp", 48)
ui.merge_data({"boss": {"hp": 22, "antlers": 2}})
ui.setData("player.hp", 48);
ui.setData({ boss: { hp: 22, antlers: 2 } });
Sample data and scenarios
Sample data fills the canvas and preview before the game exists. Scenarios are named patches over it: Hunt start, Low health, Boss enraged. Pick one to see it on the canvas. The AI handoff renders every screen in every scenario, so the programmer sees the edge cases too. Runtimes never read scenarios.
Events
A button’s click can emit an event with an optional payload. Game code listens for the name, never for a particular button:
func _on_ui_event(event: String, payload: String) -> void:
match event:
"new_hunt": start_new_hunt()
"buy": shop.buy(payload)
ui.on("new_hunt", () => game.startHunt());
ui.on("*", (payload, event) => console.log(event, payload));
Actions
A click runs a list of actions in order, no code needed:
| Action | Does |
|---|---|
emit |
Sends an event to the game |
goto |
Shows another screen (with the screen’s transition, or its own) |
push / pop |
Opens a screen over this one, closes the top one |
play |
Plays an animation |
set / toggle |
Changes data, like settings.subtitles |
The Last Hunt’s menu items emit new_hunt and then go to Character select, so the prototype clicks through and the game still gets its event.
Lists
Bind a frame to an array and its template child is drawn once per item:
"list": { "path": "store.items", "template": "<row id>", "key": "id" }
Inside the template, item.x and {item.x} refer to the current item, and {index} is its position. An emit payload like {item.id} tells the game which item was clicked. Items with a key keep their layers when the list is reordered. Lists can nest.
Preview a list empty, with a few items or with a hundred, using scenarios.