Record the UI's paper trail and bump to 0.9.0

Two TODO.md notes the UI work created. The text texture ring cache (plan
item 2) now has its second consumer, and the bigger one: the UI executor
draws every TEXT render command through akgl_text_rendertextat, one wrapped
line per command per frame, so a five-row menu re-rasterizes five lines at
60 Hz against the original case of one HUD line changing once a second.
And akgl_ControlMap's mouseid/penid fields stay dead deliberately -- the
mouse path lives in the UI subsystem because control maps and pointer state
are different consumers, and the note says where the work lands when a game
wants mouse-driven actors.

0.8.0 to 0.9.0: a new public header, a new status code, three new drawing
primitives and a new subsystem is new API, and while the major version is 0
the soname carries major.minor -- libakgl.so.0.9 is what makes 0.8.0 and
0.9.0 unmixable at load time, which is the honesty the bump is for.

Co-Authored-By: Claude Code (Claude Fable 5, claude-fable-5) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KzBDV2fqgnUAcqCKqKvc71
Co-Authored-By: Andrew Kesterson <andrew@aklabs.net>
This commit is contained in:
2026-08-02 11:34:12 -04:00
parent 7e9704e8c8
commit ce94d300e9
2 changed files with 22 additions and 1 deletions

21
TODO.md
View File

@@ -1273,6 +1273,15 @@ engines spend the same frame**.
cached") with the raw-SDL control row the perf rules require. Budget to
move: `tests/perf_render.c:391`.
**The UI subsystem is this cache's second consumer, and the bigger one.**
`akgl_ui_execute_commands` (`src/ui.c`) draws every TEXT render command
through `akgl_text_rendertextat`, one wrapped line per command per frame —
a menu of five rows re-rasterizes five lines at 60 Hz whether or not any
of them changed, where the original HUD case was one line changing once a
second. Abstract-on-the-second-consumer says this item's time has come;
the key already fits, since clay hands the executor stable text bytes
between frames.
3. **Non-raising sprite lookup — target 10, a design change.** Give
`akgl_character_sprite_get` (`src/character.c:84-94`) the companion that
returns `NULL` without raising, then convert the three sites that raise
@@ -2196,6 +2205,18 @@ a live defect -- but nothing rejects it, and `max_timestep` is caller-settable.
`renderfunc`. This item is the half that remains: one uniform `scale`, with no way
to expand a single axis.
3. **`akgl_ControlMap.mouseid` and `.penid` are still dead fields, deliberately.**
The UI subsystem (0.9.0) brought the mouse into the library, and it would have
been natural to wire these up on the way -- it did not, on purpose. Control maps
translate device events into *actor handler calls*, and the UI wants absolute
pointer state per event; those are different consumers, and building
gameplay-mouse machinery into `src/controller.c` with no game asking for it is
the abstract-before-the-second-consumer mistake. The mouse path lives in
`src/ui.c` (`akgl_ui_handle_event`); when a game wants mouse-driven actors,
*that* is the consumer these fields were declared for, and the work lands in
`controller.c` then. Same for `.axis`, `.axis_range_min` and `.axis_range_max`,
which `akgl_controller_handle_event` has never consulted.
## Found while writing the manual
Twenty-one chapters and two tutorial games were written against `src/` rather than