ludic/tools/ui-preview
Orkuncakilkaya 49b5e80af5 ludic ui-preview: ludic.ui components previewed for a studio over stdio (R5)
A prebuilt tool, bin/ludic-ui-preview (built by ludic-dev build, shipped beside ludic-lsp, run as
`ludic ui-preview [--font DIR]`): ludic.ui with a backend that records every draw call as a line,
and mock component classes the studio describes (load / model / calls). frame t runs ui_show at
interface time t; text is measured on the CPU with the game's font.json metrics; locale goes
through ludic.i18n; tree / box / rules inspect the frame. No game code, no GPU, no network. The wire
protocol is frozen as tools/ui-preview/protocol-v1.md; smoke.txt is a transcript to run.

ludic.ui gains, all additive: UiClass.make_of, UiBackend.said / emitted, UiRule.text / at (with
comment line breaks kept so rule lines count true, and a class's styles read under its .lss path),
and ui_root, ui_find, ui_rules_of, ui_rule_value, ui_building, ui_class, ui_class_load,
ui_file_forget, ui_errors_clear; ui_nine_cuts_into exported.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 19:53:26 +03:00
..
calls.ludic ludic ui-preview: ludic.ui components previewed for a studio over stdio (R5) 2026-09-29 19:53:26 +03:00
cmd_load.ludic ludic ui-preview: ludic.ui components previewed for a studio over stdio (R5) 2026-09-29 19:53:26 +03:00
cmd_world.ludic ludic ui-preview: ludic.ui components previewed for a studio over stdio (R5) 2026-09-29 19:53:26 +03:00
cmds.ludic ludic ui-preview: ludic.ui components previewed for a studio over stdio (R5) 2026-09-29 19:53:26 +03:00
computed.ludic ludic ui-preview: ludic.ui components previewed for a studio over stdio (R5) 2026-09-29 19:53:26 +03:00
draw.ludic ludic ui-preview: ludic.ui components previewed for a studio over stdio (R5) 2026-09-29 19:53:26 +03:00
events.ludic ludic ui-preview: ludic.ui components previewed for a studio over stdio (R5) 2026-09-29 19:53:26 +03:00
font.ludic ludic ui-preview: ludic.ui components previewed for a studio over stdio (R5) 2026-09-29 19:53:26 +03:00
images.ludic ludic ui-preview: ludic.ui components previewed for a studio over stdio (R5) 2026-09-29 19:53:26 +03:00
input.ludic ludic ui-preview: ludic.ui components previewed for a studio over stdio (R5) 2026-09-29 19:53:26 +03:00
input_keys.ludic ludic ui-preview: ludic.ui components previewed for a studio over stdio (R5) 2026-09-29 19:53:26 +03:00
inspect.ludic ludic ui-preview: ludic.ui components previewed for a studio over stdio (R5) 2026-09-29 19:53:26 +03:00
json.ludic ludic ui-preview: ludic.ui components previewed for a studio over stdio (R5) 2026-09-29 19:53:26 +03:00
line.ludic ludic ui-preview: ludic.ui components previewed for a studio over stdio (R5) 2026-09-29 19:53:26 +03:00
main.ludic ludic ui-preview: ludic.ui components previewed for a studio over stdio (R5) 2026-09-29 19:53:26 +03:00
mock.ludic ludic ui-preview: ludic.ui components previewed for a studio over stdio (R5) 2026-09-29 19:53:26 +03:00
num.ludic ludic ui-preview: ludic.ui components previewed for a studio over stdio (R5) 2026-09-29 19:53:26 +03:00
out.ludic ludic ui-preview: ludic.ui components previewed for a studio over stdio (R5) 2026-09-29 19:53:26 +03:00
protocol-v1.md ludic ui-preview: ludic.ui components previewed for a studio over stdio (R5) 2026-09-29 19:53:26 +03:00
README.md ludic ui-preview: ludic.ui components previewed for a studio over stdio (R5) 2026-09-29 19:53:26 +03:00
smoke.txt ludic ui-preview: ludic.ui components previewed for a studio over stdio (R5) 2026-09-29 19:53:26 +03:00

ludic ui-preview

A game's ludic.ui components, previewed for a studio (a UI editor) without the game: ludic.ui itself, with a backend that records its draw calls instead of drawing them, and component classes the studio describes over stdin. No game code is built, nothing touches a GPU, nothing opens a network connection. It is the toolchain's own program, shipped prebuilt as bin/ludic-ui-preview.

ludic ui-preview [--font DIR]      # the host on stdin/stdout; DIR holds the game's font.json

The wire protocol is protocol-v1.md, frozen: every request, every reply and every line format. smoke.txt is a scripted session with what each reply must contain.

What it does

  • Components are mocks. load registers a UiClass named as the component, with the template and styles the studio sends (unsaved text is fine), or changes that class in place. Its model is the story's (model), with the props its parent's tag gives it and whatever its template sets laid over it; its functions answer from the story's table (calls). A component tag the studio has not sent yet is an empty class until it is.
  • The frame is ludic.ui's own. frame t sets the interface clock to t, hands over the input the studio sent (input ...), and calls ui_show: build, cascade, layout, pointer and focus, draw, then the actions a press ran. The draw list is every UiBackend call in painting order.
  • Text is measured as the game measures it. font DIR (or --font DIR) reads the same font.json ludic.render3d's overlay reads, and the width of a run is the overlay's sum of glyph advances at the font's whole-pixel size; each text line carries it, so the studio fits its own rendering to the game's line breaks.
  • Languages are the game's: locale <file.po> translates every drawn text with ludic.i18n.
  • Natives (a radar, a dial) are game code, so a native line is a box for the studio to fill.
  • Inspection: tree, box <id> (box and computed style) and rules <id> (the matching rules, each with the file and line its selector was written on).

ludic.ui additions it relies on

All additive, and none changes what a game draws:

  • UiClass.make_of - a constructor handed the class, so one host function makes every mock.
  • UiBackend.said - template errors to the host instead of print; UiBackend.emitted - every emit, for the host's log.
  • UiRule.text and UiRule.at - a rule's selector as written and file:line. A stylesheet's comments keep their line breaks when stripped, so lines count true; a component's own styles are read under its .lss path.
  • inspect.ludic: ui_root, ui_find, ui_rules_of, ui_rule_value, ui_building, ui_class_load, ui_file_forget, ui_errors_clear; class.ludic: ui_class; ui_nine_cuts_into exported.

Limits in v1

  • An error's column is not known (col is 0): ludic.ui records a file and line per element and per rule, not a column. A malformed XML file is read leniently by the runtime's parser and does not report a syntax error.
  • In a GAME build a component's styles have their @imports inlined by the compiler, so a rule's line there counts in the inlined text; in the host the studio sends the file as written, and lines are the file's.
  • A declaration's value is given as written only when it is plain text; one with {...} holes is "" in rules (its computed result is in box).
  • Images are referenced, not decoded: the studio draws them from its own copies of the game's files and atlases, and says a picture's natural size with image when object-fit needs it.