Skip to content

UI Demo

apps/ui_demo is the end-to-end proof of the retained-mode UI: a .ui document authored as TOML, loaded with Ui.load, and rendered full-window each frame with Ui.render. It shows a dark backdrop, a centered card with a title and subtitle, and a Play button whose on_click dispatches to Game.onPlay().

  • Loading a documentUi.load("ui/main.ui") parses and validates the file; a bad file returns null (never a crash).
  • Letterboxing — the document is authored at a 960×540 design size and rendered into the full window; the engine scales it uniformly (aspect preserved, centered), so the layout is resolution-independent.
  • Panels, text, and a button in one tree — panels/buttons draw as quads, the title/subtitle/label reuse the crisp SDF Text pass, and the button changes tint on hover/press.
  • Click dispatch — releasing the pointer inside the button fires Game.onPlay() from native engine context (after draw), so a handler may safely call back into the engine.

The layout lives in apps/ui_demo/ui/main.ui — a [document] plus [[element]] array with parent-by-id references and uGUI-style anchors/offsets. See the Ui API for the full field reference.

import "engine" for Engine, Logger, Window, Ui
class Game {
construct new() { _doc = null }
init() {
_doc = Ui.load("ui/main.ui")
if (_doc == null) Logger.error("failed to load ui/main.ui")
}
draw() {
if (_doc != null) Ui.render(_doc, 0, 0, Window.getWidth(), Window.getHeight())
}
// Dispatched from the button's on_click = "onPlay".
onPlay() { Logger.info("Play clicked") }
quit() {}
}

The demo auto-captures ui_demo.png after ~1.5 s so the render can be verified headlessly.

See the Ui API for the full document format and runtime surface, and Gui for the immediate-mode alternative.