beebbd0bc1
ludic.ui: lss_text frees the stripped sheet only when lss_strip made one - a sheet without a comment comes back as src itself since b307118, and freeing it aborted the game at start
...
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 22:40:33 +03:00
b30711877d
ludic.ui: negative numbers' texts made once per value like the positive ones, big ones kept by value in a ring of 16 (mm_int made a string per call for every coordinate), and a stylesheet without a comment is not copied to strip one
...
Found by the windowed walk's exit scan (mm_int 1.2 MB, lss_strip 451 KB unreachable).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 22:34:19 +03:00
1786e144bb
ludic.ui: ui_attr's miss is the node's own kept null (made with the pooled node), not a new one per ask - every control asking min/max/step/value per frame made one; a select's options without a value matched by index without asking
...
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 21:17:05 +03:00
bd2d62ddca
ludic.ui: a select matches a number as a number (its text was made every frame per select); the fired-event queue's lists made with room; ludic.inventory: the counts made at full length at once
...
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 21:09:08 +03:00
179dd60536
ludic.ui: parsing at load gives back what it does not keep - tpl_words written once into bytes of its own (a string a character before), a stylesheet's stripped text, its error list and each reader freed once read, ex_text's joining node freed when it collapses to one piece or none
...
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 20:06:25 +03:00
4df15eacfb
ludic.ui: a fired event, a press, a hold and a native's events make nothing - a ring of 16 event objects and one hold object made with the state with their keys, and every ui_fire with no value carries the kept null
...
The last kept bytes of the leak gate's pack, shop and journal screens (memory_final, count mode).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 19:20:01 +03:00
fc22c3f250
ludic.ui: a bar's min, max and value read without ui_attr's new null for a miss (ui_attr_float), and the action answer ring made full with the state - craft's bar kept a block a frame, pack/shop/journal kept one frame filling the ring
...
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 18:56:10 +03:00
ab6b666fd6
ludic.ui: a scroll box without scroll-top asks ui_attr_has first - ui_attr's miss made a new null every frame on every screen that scrolls (the gate's one kept block a frame on map, shop, journal and craft)
...
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 18:26:46 +03:00
ac8c7b0c0b
ludic.clock: clock_hhmm reads a table of the day's times made with the state; ludic.minimap: minimap_pin past the end is one kept empty mark; ludic.ui: ev_text's memo miss is its own declared function
...
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 17:57:30 +03:00
7d85ea3432
@max on the bounded lists: TextRing's slots, the pack's counts and change ring, the net's fact ring, the compass pools, ludic.ui's memo (its 3/4 of MM_CAP), screen pools, answer and pointer rings; ludic.base's intern test holds the table to its cap now that past it is Mem.over
...
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 16:48:53 +03:00
54c0feafc2
Merge lang/foundations 6fb5118 into lang/ecs
2026-09-28 16:46:20 +03:00
f8825dc55a
ludic.ui, ludic.i18n: frame_keeps and birth_leaks to 0 - :nth-child's a and b read once per argument, a border-image's miss its own function; typing, the dev dump, parsing, the pointer ring's making, Ln's counted line and the plural header declared
...
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 16:46:00 +03:00
6fb5118afd
capacities (25.5a): @max(n) on a list field, and a full table is a failure
...
'@max(64) boxes: []Box' on a property's or a state's field is a promise: the grow path of a push to
that field (only the grow path, so nothing is paid until it doubles) checks it, and growing past n is
reported by the fence - 'PoolState.boxes grew past its @max(16) (it holds 16)' - counted under
count, said under warn, and under fail (a headless or dev build's default) the run ends with exit 87.
Mem.over("what") is the same for a package's own table: ludic.base's StrTable past its most
(sb_intern) and ludic.ui's memo past three quarters of MM_CAP no longer quietly copy per call. The
census counts overflows.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 16:43:02 +03:00
429e419327
ludic.ui, ludic.i18n: frame_allocs to 0 - a wrap, an ellipsis, a tooltip's lines, a text-shadow's colour and a range's value kept by what made them; pointer events from a ring; inline text joined through the memo; the pool's and the state's lists through ui_kept; parse, memo miss, pool miss, lazy start and template errors declared; the translation cache clears in place
...
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 16:41:47 +03:00
0f534731a6
ludic.ui: nothing a frame on the pack screen - a key's down/up carry one kept null, scroll asks filtered in place, a shadow's colour joined through the memo, numbers to 65536 made once each
...
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 16:22:21 +03:00
6cdef20cc2
ludic.ui: an unmounted component is mounted again rather than made again - its record renewed (a generated renew), its props and model kept; an action's call answers into a ring
...
A prompt that comes and goes as a player walks (co-op's netleak: in_get, cmp_*_new, bd_class, value_slot/put)
made a new record, props and model on every mount, and an action's call answered into a new Val (ev_call_with).
examples/library/ui_remount: two thousand comings and goings hold the heap at 0, and the counter starts at 0.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 15:25:55 +03:00
5d71892b7c
ludic.ui: every bar percentage (0% .. 100% to a tenth) made once when the memo starts, so a bar moving never makes its text in play
...
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 11:46:47 +03:00
0068411946
ludic.ui: a float in a text's hole written to one decimal from kept texts (its whole part from mm_int, its tenth a literal) - a bar's width moving every frame made a new string every frame, and read 7.470598e-07%
...
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 11:29:11 +03:00
50f255eea4
ludic.ui, runtime: the last per-frame allocations in the interface - the top popover found without a list, the popover draw list and the clip stack kept, a select's options in a list the node keeps (and matched to its value without writing the index), a number's text kept on its Value until it changes (value_num_set / Value.num_text), a key's label kept per key code until the layout changes it
...
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 11:11:48 +03:00
706c7abc55
ludic.ui: no number made text to be read back - a style handler returns before any text for a key not its own, grow/alpha/animations/scroll read numbers as numbers, el_secs split once per text, a tooltip translated when its title changes
...
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 10:43:44 +03:00
4d8526ad7e
ludic.ui, runtime, compiler: a component call's answer is written into a pooled record while the screen is built (call(p, name, args, into); value_into_*), a component root's passes pooled, an icon's atlas and name read in place; reseeded
...
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 01:51:56 +03:00
ea5eedb5a5
ludic.ui: a hole's text found by its pieces in the memo (built only when it first reads that way), avals left for the attributes read as text, a class's [root] made once, and a dev build's reload lets go of every file it read only to compare
...
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 01:29:02 +03:00
fa119d234b
ludic.ui, runtime, compiler: an expression's Value comes from the screen's pool while it is built (never a state's start or an action's), true and false shared, calc() terms pooled and read in place, a model's list fields filled in place (value_set_ints/strs/floats/bools); reseeded
...
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 01:05:35 +03:00
429eeb7754
ludic.ui, compiler: a component's model is filled in place into an object its instance keeps (value_set_*); colours, border-images and a class screen's stub made once; object-fit into a kept list - benchmark 20 -> 10 KB a frame
...
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 00:17:47 +03:00
08ac2f1125
ludic.ui: var() values found by their pieces, tpl_words/url/border-image by their text, nine-slices, picking, lifecycle, focus, hover, the event queue and input without a list or record made a frame
...
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 00:10:56 +03:00
51a5e06f5c
ludic.ui: props kept an instance, a call's arguments a depth, a loop's index shared, an absent attribute's text without a Value; runtime Value.clear - benchmark 36 -> 20 KB a frame
...
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-27 23:46:18 +03:00
46888b6716
runtime, ludic.ui: a scalar Value is one allocation, not three (lists only for a list or an object); layout and cascade lists kept a depth; small numbers' text made once - benchmark 63 -> 36 KB a frame
...
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-27 23:43:25 +03:00
1d40f6d95a
ludic.ui: splits, words, gradients and keys are made once per text (a bounded memo), sides without a list - benchmark 110 -> 63 KB a frame
...
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-27 23:38:57 +03:00
d1c9359e96
ludic.ui: a screen's nodes and envs are pooled and used again - two generations a screen, reset in place, their own lists emptied not replaced; a tree is good until its screen is built twice more (benchmark 256 -> 110 KB a frame)
...
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-27 23:33:48 +03:00
83200a453b
ludic.ui: string matching compares in place - at_alias, lk_in, colours and every s[a..b] == p made a string per position tried, per rule, per element, per frame (a benchmark page: ~3 MB -> 256 KB a frame)
...
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-27 23:27:02 +03:00
9862ec82e3
refactor(packages): 0.R5 - a question no longer starts its state - 64 lazy starts ('if st.x == null { st.x = ... }' inside a getter) are the state's defaults, gear__ensure is gone, and ludic migrate state --tighten took mut off 208 package parameters: things_all, thing_find, gear_charge, gear_level, jobs_state and the rest read
...
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-27 00:51:03 +03:00
40a91f39ed
fix(ui): the pointer in the renderer's pixels - macOS reports it in window points, so on Retina every hit landed at half the cursor's position
...
The old kit read Input.mouse_x() * gl_scale; ludic.ui read it raw against a layout sized in
drawable pixels. A backend says how many screen pixels one pointer unit is (pointer_scale);
render3d's is gl_pixel_scale(), 1 on Windows and headless.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 23:31:47 +03:00
259b4d9b35
fix(ui): 0.R4 - an action a UI button dispatches is reduced before the frame is presented
...
ludic.ui runs a frame's presses after drawing it, and what they dispatched waited for the end of the
phase - after the host had presented - so a button's change showed a frame late. Decided: drain, not a
phase per action. ui_show and ui_press drain the queue once the presses have run, so the code after
them and the frame presented next see the change; a host that runs presses some other way calls
drain_actions() before it presents.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 07:08:26 +03:00
d46f0adb5e
fix(lang): 0.R4 - ludic.ui's UiAct is its own, and a name that meets a package's export says whose it is
...
A game's exported UiAct collided with ludic.ui's, which nothing outside ludic.ui uses: it is private
to ludic.ui now, and a private record of one spelling in two modules never clashed. A real clash - a
type named like one a package exports - is still refused, and the message names the package and the
way out (`ludic_ui exports it, and exported names are one namespace - rename this one, or declare it
without export inside a module of your own`).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 06:57:35 +03:00
3a87d02696
packages: ludic.ui's render3d backend threads Render3dState; render3d's settable vars (r3d_dem_path, post_*, grass_*, wt_wade_*, ...) are Render3dState's fields again, not lets
...
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 17:11:15 +03:00
7b17b4a1b9
wip(0.S3): outside the runtime, its drawable size, scale, screen and tile size are read and set through its functions; a migration reports such a reference instead of threading the runtime's state
...
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 15:47:21 +03:00
19fcf60599
wip(0.S3): packages and examples migrated again from their pre-0.S sources in one run
...
ludic migrate state packages <every example program> packages/ludic.lab/example/plate.ludic
1804 vars into 126 states, 64 into lets; 23498 edits in 460 files
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 15:31:34 +03:00
5ffe50ed02
wip(0.S2): migrate - a var nothing writes becomes a let; a state is keyed by its module, directory or program, so every program's plan agrees; paths normalized; program states named SceneDemoState / scene_demo_st; the LSP reads state, mut and entry/handler parameters
...
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 15:31:34 +03:00
3eda72e8c2
wip(0.S3): packages and examples migrated in one run - ludic migrate state packages <every example program> packages/ludic.lab/example/plate.ludic
...
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 15:02:45 +03:00
253d8d3632
ui: a renderer installs itself through the UiRenderers registry, not a global's initializer
...
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 14:31:48 +03:00
ec9a650e65
feat(ui): ui_scale and ui_box, on-submit, zoom (and a length over a length in calc), on-hold
...
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 03:31:38 +03:00
077b38e684
feat(ui): a title shows for the keyboard's focus as well as the pointer
...
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-24 22:06:27 +03:00
d15cc79822
feat(ui): a key field takes a mouse button, and is :capturing while it listens
...
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-24 22:04:47 +03:00
6bd3228990
feat(ui): translate="no", and a title of several lines translated whole or line by line
...
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-24 22:03:49 +03:00
7605a0253c
feat(ui): linear-gradient backgrounds, object-fit and aspect-ratio
...
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-24 22:02:49 +03:00
abf45ef9db
feat(ui): scroll-top holds a scroll box at an offset, on-scroll, and ui_scroll_set
...
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-24 22:00:21 +03:00
cf8b9e425e
feat(ui): nine-slice corners clamped to half the box in each direction, cut on whole pixels
...
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-24 21:59:26 +03:00
12f4ba8431
feat(ui): min(), max() and clamp(); insets as percentages of the containing block
...
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-24 21:53:44 +03:00
355201f094
feat(ui): text-fit, line-height, and ems against the font size an element ends with
...
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-24 21:51:41 +03:00
d163bad406
feat(ui): a popover's align along its side, and within= for the bounds it flips against
...
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-24 21:48:58 +03:00