Keyboard shortcuts

Press ← or → to navigate between chapters

Press ? to show this help

Press Esc to hide this help

Authoring RON UI files

The engine’s UI documents are hand-written RON deserialized into the real Rust types in manifold-ui-protocol. Validate files with ui-validate; optional editor support is described below.

1. Validate before you run — ui-validate

# validate a single file (or a directory of them):
cargo run -p manifold-ui-validate --bin ui-validate -- path/to/your.ui.ron

# validate the whole engine asset tree (default when no path is given):
cargo run -p manifold-ui-validate --bin ui-validate

It runs two passes:

  • Parse (structural): wrong field names, unknown enum variants, type mismatches, reported with file:line:col.
  • Reference (strict): every binding, slot schema, and typed action is checked against the live registries. A dangling binding is an error, even in a Label, HUD predicate, or template, where the renderer would otherwise silently degrade the value (empty string / false / "??") and hide the mistake.

References intentionally written ahead of their gameplay backing live in assets/ui/.validate-allow.ron and are reported as non-failing info lines. Remove an entry there once its backing exists. A CI test fails if an allowlist row no longer matches any asset (no stale rows), and another fails if a new dangling reference appears without an allowlist entry.

The same checks run in CI: manifold-ui-runtime’s parse gate covers every assets/ui/** file structurally, and manifold-ui-validate’s asset gate resolves every reference.

It also checks text and direction (see text and localization):

  • Hardcoded text (warning): Literal or Template text with words, on a node without text_options: (untranslated: true).
  • Unknown message keys (error): a Localized key that the engine’s or the owning mod’s catalogs (the nearest mod.toml) lack.
  • Mirroring (warning): a physical-side anchor (TopLeft, …) or unequal left/right margins without mirror: Never.
  • Catalog lints (warning): messages without a translator comment.

A developer-only document (a debug panel, an editor fixture) opts out of the hardcoded-text warning with a // ui-validate: untranslated line.

Validate a translation pack against the mods it translates with ui-validate --translation-pack PACK_DIR --source MOD_DIR....

2. Text players read

Write text as message keys resolved in the player’s language:

Label(text: Localized(key: "mymod.shop.title")),
Button(
    label: Localized(key: "mymod.shop.buy", args: {"price": Bind("Shop.price")}),
    action: Typed("Buy", ()),
),

The key mymod.shop.buy is the message shop-buy in locales/<language>/*.ftl of the mod whose id is mymod. Numbers passed as arguments are formatted for the player’s locale and drive plural selectors. Literal(..) is for names and symbols. Template(..) is for language-independent formatting like {0} / {1}.

text_options controls how a text node lays out:

  • dir: Some(Auto | Ltr | Rtl | Locale). The default is Locale for Localized text and Auto (first strong letter) otherwise.
  • overflow_wrap: Normal | BreakWord | Anywhere.
  • max_lines: Some(n) and ellipsis: End.
  • untranslated: true.

Place things logically. Anchors TopStart, CenterEnd, BottomStart, … and Margin(start: Some(..), end: Some(..)) follow the reading direction. Rows, grids, anchors and margins mirror in a right-to-left UI unless the node sets mirror: Never. Icons flip only when icons.ron marks them mirror_in_rtl.

A Dropdown with append: Languages lists every installed language after its authored options, each named in its own language.

3. Editor autocomplete — ron-lsp (optional)

For RON autocomplete, try the third-party JasonMcGhee.ron-lsp extension, which derives completions / diagnostics / hover from Rust types rather than a schema.

  1. Install RON (Rusty Object Notation) LSP and CLI (JasonMcGhee.ron-lsp) in VS Code.
  2. Annotate the document’s root Rust type so the LSP knows what to complete against (see the extension’s docs for the annotation syntax, e.g. the root Node for *.ui.ron, HudLayerDocument for hud/*, Theme for *.theme.ron).
  3. Open a .ui.ron file and confirm completions for the Node variants/fields.

Workspace support is unverified. Test whether ron-lsp resolves manifold_ui_protocol’s cross-crate types in your editor, then record the result and any working root-type annotation here. Use ui-validate for validation regardless of editor support.