ludic/tools/ui-preview/computed.ludic
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

78 lines
2.2 KiB
Text

# computed.ludic - an element's computed style after the cascade and layout, one `style` line each
# (protocol-v1.md, "box")
function pv_style(o: PvOut, n: UiNode) -> void {
pv_st(o, "font-size")
pv_num(o, n.rsize)
pv_nl(o)
pv_st(o, "color")
pv_rgba(o, n.rfg, n.rfg_a)
pv_nl(o)
pv_st(o, "background")
if n.bg < 0 { pv_w(o, "none") } else { pv_rgba(o, n.bg, n.bg_a) }
pv_nl(o)
pv_st(o, "opacity")
pv_num(o, n.alpha)
pv_nl(o)
pv_four(o, "padding", n.pt, n.pr, n.pb, n.pl)
pv_four(o, "margin", n.mt, n.mr, n.mb, n.ml)
pv_four(o, "border-width", n.bt, n.br, n.bb, n.bl)
pv_st(o, "border-color")
if n.border_c < 0 { pv_w(o, "none") } else { pv_rgba(o, n.border_c, n.border_a) }
pv_nl(o)
pv_one(o, "border-radius", n.radius)
pv_one(o, "gap", n.gap)
pv_one(o, "flex-grow", n.grow)
pv_st(o, "flex-direction")
if n.dir == UI_ROW { pv_w(o, "row") } else { pv_w(o, "column") }
pv_nl(o)
pv_st(o, "align-items")
pv_w(o, pv_place_word(n.align, false))
pv_nl(o)
pv_st(o, "justify-content")
pv_w(o, pv_place_word(n.justify, true))
pv_nl(o)
pv_st(o, "position")
pv_w(o, pv_pos_word(n.pos))
pv_int(o, n.z)
pv_nl(o)
pv_st(o, "content")
pv_num(o, n.mw)
pv_num(o, n.mh)
pv_nl(o)
pv_st(o, "enabled")
if n.enabled { pv_w(o, "true") } else { pv_w(o, "false") }
pv_nl(o)
}
function pv_st(o: PvOut, name: string) -> void {
pv_s(o, "style ")
pv_s(o, name)
}
function pv_one(o: PvOut, name: string, v: float) -> void {
pv_st(o, name)
pv_num(o, v)
pv_nl(o)
}
function pv_four(o: PvOut, name: string, t: float, r: float, b: float, l: float) -> void {
pv_st(o, name)
pv_num(o, t)
pv_num(o, r)
pv_num(o, b)
pv_num(o, l)
pv_nl(o)
}
function pv_place_word(v: int, justify: bool) -> string {
if v == UI_START { return "start" }
if v == UI_CENTER { return "center" }
if v == UI_END { return "end" }
if justify and v == UI_BETWEEN { return "space-between" }
if justify and v == UI_AROUND { return "space-around" }
if justify and v == UI_EVENLY { return "space-evenly" }
if v == UI_STRETCH { return "stretch" }
return "start"
}
function pv_pos_word(p: int) -> string {
if p == 1 { return "relative" }
if p == 2 { return "absolute" }
if p == 3 { return "fixed" }
return "static"
}