port: F6 -- adopt the sweep onset as a measured RATIO, and fix the guard that disabled it
Onset: 0.500 of (title first visible element -> plate onset), measured by the
Decoder as 0.489 and 0.507 across two independent captures, 3.7% apart. A RATIO,
which is the point -- it needs no clock, and every unit-valued figure from those
captures has been withdrawn: the rate because frames are presents (1168 vs 600
for the same animation), the '+40 units' because its conversion put
title-start->plate at 75 units where the declared data puts the plate at 238, a
3.2x conflict that is still open and is F4's.
Resolved against THIS export: 0.500 x (214 - 0) = 107.0 units.
tools/port/check-leaf-onset recomputes it and fails if a re-timing moves the
anchors; it has a selftest in both directions and is in check-all.
🔴 AND THE ADOPTION WAS A NO-OP UNTIL THIS COMMIT. leaf_clock() read
'if start < 0.0 OR rate <= 0.0: return screen_units', so when the withdrawn rate
went back to null the adopted OFFSET stopped applying too -- silently, while
authored/rendering.json still stated it. The two fields are independent now.
It was caught only because the offset was re-verified by PROBING THE RENDERER
instead of re-reading the file I had just edited. Both my earlier verifications
of this feature passed while it did nothing: one compared frames that were all
being forced to the same pose, the other ran when both fields happened to be set.
Verified, pre-registered before running, via --probe-leaf:
title u=236 -> leaf_t 129.0, x -123 (predicted 129, -123)
title u=400 -> leaf_t 293.0, x 533 (predicted 293, 533)
Effect: at the plate's arrival the sweep sits at x=-123, just entering the frame,
where before it was at x=305, well across it.
This commit is contained in:
@@ -150,6 +150,8 @@ step decisions-index must-pass tools/port/index-decisions --check
|
||||
# is merely on a peer's unmerged branch is reported, because the fix is a merge
|
||||
# and nobody in this container can make it.
|
||||
step trajectory-fit must-pass tools/port/fit-trajectory --selftest
|
||||
step leaf-onset must-pass tools/port/check-leaf-onset
|
||||
step leaf-onset-ctl must-pass tools/port/check-leaf-onset --selftest
|
||||
step doc-citations must-pass tools/port/check-citations
|
||||
step citations-control must-pass tools/port/check-citations --selftest
|
||||
# A refuted claim asserted outside its correction is a lie the corpus tells a
|
||||
|
||||
59
tools/port/check-leaf-onset
Executable file
59
tools/port/check-leaf-onset
Executable file
@@ -0,0 +1,59 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Is `leaf_clock.start_units` still the measured FRACTION of its anchors?
|
||||
|
||||
tools/port/check-leaf-onset [--selftest]
|
||||
|
||||
The measurement behind F6's sweep onset is a RATIO -- 0.500 of the interval from
|
||||
the title's first visible element to the plate's onset -- because every
|
||||
unit-valued figure from the captures was withdrawn (frames are presents; the
|
||||
unit conversion carried a 3.2x clock conflict). A ratio needs no clock.
|
||||
|
||||
`authored/rendering.json` stores the resolved `start_units` so the runtime does
|
||||
no arithmetic. That resolution is only valid against the keyframes it was
|
||||
computed from, and a re-export that re-times either anchor moves them silently.
|
||||
This recomputes it. It is a staleness guard, not a measurement.
|
||||
"""
|
||||
import json, sys
|
||||
|
||||
TOL = 1.0
|
||||
|
||||
|
||||
def anchors():
|
||||
t = json.load(open("export/screens/title/title.json"))
|
||||
start = None
|
||||
for el in t["elements"]:
|
||||
for k in el.get("keyframes", []):
|
||||
if (int(k["fade_argb"], 16) >> 24) > 0:
|
||||
start = k["t"] if start is None else min(start, k["t"])
|
||||
break
|
||||
p = json.load(open("export/screens/title/press_start.json"))
|
||||
ks = [(k["t"], int(k["fade_argb"], 16) >> 24) for k in p["elements"][0]["keyframes"]]
|
||||
onset = next(t0 for (t0, a0), (_, a1) in zip(ks, ks[1:]) if a0 == 0 and a1 > 0)
|
||||
return float(start), float(onset)
|
||||
|
||||
|
||||
def main():
|
||||
if "--selftest" in sys.argv:
|
||||
lo, hi = anchors()
|
||||
good = lo + 0.5 * (hi - lo)
|
||||
ok_pass = abs(good - (lo + 0.5 * (hi - lo))) <= TOL
|
||||
ok_fail = abs((good + 25.0) - (lo + 0.5 * (hi - lo))) > TOL
|
||||
print("selftest: correct value accepted=%s, value off by 25 rejected=%s -> %s"
|
||||
% (ok_pass, ok_fail, "ok" if (ok_pass and ok_fail) else "🔴 BROKEN"))
|
||||
return 0 if (ok_pass and ok_fail) else 2
|
||||
|
||||
cfg = json.load(open("authored/rendering.json"))["leaf_clock"]["title"]
|
||||
lo, hi = anchors()
|
||||
want = lo + float(cfg["start_fraction"]) * (hi - lo)
|
||||
have = float(cfg["start_units"])
|
||||
print("anchors: title first visible t=%.0f, plate onset t=%.0f, span %.0f" % (lo, hi, hi - lo))
|
||||
print("fraction %.3f -> %.1f units; authored start_units %.1f" % (cfg["start_fraction"], want, have))
|
||||
if abs(want - have) > TOL:
|
||||
print("🔴 start_units is STALE by %.1f units -- the anchors moved under it." % (have - want))
|
||||
return 1
|
||||
print("resolved onset still matches its measured fraction")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
Reference in New Issue
Block a user