re(ui): scale 0 means collapsed, not "unset" -- stop drawing it full size

blit() and fill_quad() both opened with

    let sx_pct = if kf.scale_x == 0 { 100 } else { kf.scale_x };

so an element whose pose is collapsed to nothing rendered at FULL SIZE.
I first described this as "a 1-pixel sliver", reading the .max(1) in the
size arithmetic two lines below -- the guard above it meant .max(1) never
saw a zero. Read the whole function, not the lines you went looking for.

Control run before the change: if 0 meant "unset", something on the disc
would use it throughout. Nothing does.

  elements with a keyframe group                    15 493
  at least one keyframe at scale 0                   2 166
  EVERY keyframe at scale 0                              0
  zero is a transient the element grows out of       1 762

ptlogo_eff3.t32 runs 0% -> 200%. An "unset" marker no element ever uses
throughout is not a marker.

Both functions now return without drawing when either scale is 0.

Reach: 24 of 24 renders byte-identical across GP_TITLE (all 16 builds),
GP_PAUSE_MENU and GP_OPTIONS -- additive on every screen the port needs.
195 elements have a guessed rest pose at scale 0 and 126 of those have a
non-zero alpha, so the old code painted them; all 126 are in
GP_READY_ROOM.pak, which S1 already declared a no-go. They are
tactical-map sprites at sx=0/sy=100, mid-horizontal-wipe, that the
coercion drew full-width.

So: a real correctness fix with no visible effect on the menu port.
Suite green, 122 passed / 0 failed across 3 suites at commit time.
This commit is contained in:
Sylpheed RE agent
2026-08-28 23:38:37 +00:00
parent c2c69b02be
commit b973d8cde3
7 changed files with 187 additions and 4 deletions

View File

@@ -291,6 +291,15 @@ authored version can be deleted.
the defensible one there — see below. Still worth flagging plateau-less
elements in an export rather than silently inheriting our guess; it is one pass
over the keyframes.
✅ **One concrete part of it is fixed (2026-08-28): `scale = 0` no longer
renders at full size.** `blit`/`fill_quad` coerced `scale == 0` to 100 %, so an
element collapsed to nothing was drawn full-size. The disc settles the reading:
2 166 elements have a zero-scale keyframe, **not one is zero throughout**, and
1 762 grow back out of zero — so 0 means collapsed, not "unset". **Renders are
24/24 byte-identical** on `GP_TITLE` (all 16 builds), `GP_PAUSE_MENU` and
`GP_OPTIONS`, so nothing you rely on moves; the 126 elements the old
code actually painted are **all in `GP_READY_ROOM.pak`**, already a no-go.
[`structures/ui-rat-layout.md`](../re/structures/ui-rat-layout.md)
🔴 **"rest = last keyframe" is refuted** as the fix. The splash has three
sibling glows with identical structure and times, differing in one byte
(`a=212` vs `a=255` at `t=45`); that rule would make `anima_eff` alone