port: F6 FOUND -- the gate was declared data the renderer was discarding
The sweep starts early because ScreenView drew a leaf WITHOUT multiplying its
parent's alpha in. ptloop01/ptloop02 declare 0:0 70:0 100:255 238:255 250:0, so
the sweep is invisible until t=70 and full at t=100. The port has had that ramp
in its export the whole time and was throwing it away at the draw call.
Three changes:
1. Parent alpha multiplies into the leaf's. This file asserted the opposite,
arguing from the sweeps being drawn while their parent had expired -- but that
could not separate 'the leaf wins' from 'the parent is ignored because it
draws nothing', and its own comment said so and named the interval that would
settle it. Measured there: dividing the leaf's declared curve out of the drawn
alpha pins the implied parent at 255.0 (+/-1.5) over hundreds of frames while
the drawn alpha swings 242 -> 132 -> 145.
2. rate 0.5, calibrated against a DECLARED interval (ptloop01's own 30-unit ramp)
rather than captured frames: two runs differing 2x in frames give 0.4795 and
0.4667, 2.7% apart. This number was 0.514, withdrawn, now reinstated at 0.5 --
what failed the first time was quoting a rate in presents, and the ratio was
discarded along with the frames.
3. The 107-unit authored offset is DELETED, with its guard tool. It came from a
ratio measured against an element identified only by screen position; the
declared ramp needs no such identification. Deleting an authored value because
the data already says it is the outcome PORT-MISSION asks for.
Also reverted, same day I made it: removing the transparent-parent skip. I read
'the game submits the sweep ~950 frames past its parent's expiry' as the leaf
outliving the parent. It does not follow -- a draw submitted at alpha 0 is still
a draw, and submitted is not visible. With the multiply, skipping on a
transparent parent IS multiplying by zero.
VERIFIED, pre-registered before running, via --probe-leaf:
u= 60 -> no draw at all (predicted: parent alpha 0.00, gated off)
u=100 -> leaf_t 50.0, x -439 (predicted 50.0, -439)
u=236 -> leaf_t 118.0, x -167 (predicted 118.0, -167)
verify-capture: every row unchanged.
⚠️ BUILD-SENSITIVE: builds 5 and 6 of GP_TITLE declare these records as a single
flat a=255 with no ramp. This export reads the ramped build; if that changes the
gate disappears silently.
This commit is contained in:
@@ -708,7 +708,7 @@ static func _rot_of(pose: Dictionary) -> float:
|
||||
## "the parent is ignored because it draws nothing" are NOT separated. A capture
|
||||
## during t=100...238 would separate them.
|
||||
## Returns whether anything was actually drawn, so the caller can fall back.
|
||||
func _draw_leaf(element: Dictionary) -> bool:
|
||||
func _draw_leaf(element: Dictionary, colour: Color) -> bool:
|
||||
var any_drawn := false
|
||||
for fe: Dictionary in element.get("leaf", {}).get("elements", []):
|
||||
var rel: String = fe.get("sprite", "")
|
||||
@@ -758,7 +758,24 @@ func _draw_leaf(element: Dictionary) -> bool:
|
||||
skipped.append("%s (leaf scale 0 -- parent drawn instead)" % fe.get("id", ""))
|
||||
continue
|
||||
var pivot := _vec(fe.get("pivot", [0, 0]))
|
||||
_draw_quad(tex, placement(pose, pivot, tex.get_size()), modulate_of(pose),
|
||||
# 🔴 THE PARENT'S ALPHA MULTIPLIES IN, and this file said the opposite
|
||||
# until 2026-09-02. The old text argued from the sweeps being drawn at
|
||||
# t=355 while their parent had expired -- but that reasoning could not
|
||||
# separate "the leaf wins" from "the parent is ignored because it draws
|
||||
# nothing", and its own comment said so and named the interval that would.
|
||||
#
|
||||
# Measured there: dividing the leaf's declared curve out of the drawn
|
||||
# alpha pins the implied parent at 255.0 (+/-1.5) across hundreds of
|
||||
# frames while the drawn alpha swings 242 -> 132 -> 145
|
||||
# (`docs/re/f6-unit10-parent-alpha-gates-the-sweep.md`).
|
||||
#
|
||||
# 📌 And this IS F6's gate, from declared data rather than a measured
|
||||
# constant: `ptloop01`/`ptloop02` declare `0:0 70:0 100:255`, so the sweep
|
||||
# is invisible until t=70 and full at t=100. The port had the ramp in its
|
||||
# export the whole time and was throwing it away at this line.
|
||||
var leaf_colour := modulate_of(pose)
|
||||
leaf_colour.a *= colour.a
|
||||
_draw_quad(tex, placement(pose, pivot, tex.get_size()), leaf_colour,
|
||||
pivot, _vec(pose.get("pos", [0, 0])), _rot_of(pose))
|
||||
drawn.append(fe.get("id", ""))
|
||||
any_drawn = true
|
||||
@@ -915,19 +932,16 @@ func _draw() -> void:
|
||||
var pose: Dictionary = element.get("rest", {}) if pose_mode == Pose.REST \
|
||||
else pose_at(element, time_units)
|
||||
var colour := modulate_of(pose)
|
||||
# 🔴 A LEAF OUTLIVES ITS PARENT, AND SKIPPING HERE KILLED IT EARLY.
|
||||
# 🔴 I REMOVED THIS GUARD ON 2026-09-02 AND PUT IT BACK THE SAME DAY.
|
||||
#
|
||||
# The parent's pose gates the whole element, so `ptloop01` expiring at
|
||||
# t=250 stopped the sweep being drawn at all -- while this file's own
|
||||
# decode says the leaf runs on its OWN timeline and the parent's alpha is
|
||||
# not multiplied in. The two were inconsistent and the gate won silently.
|
||||
#
|
||||
# The capture settles it: the game submits the sweep across frames
|
||||
# 746..1913 while the parent expires at frame 956, so it keeps drawing for
|
||||
# roughly 950 frames after the parent is gone
|
||||
# (`f6-unit3-sweep-track-fits.md`, `f6-unit8-leaf-clock-in-title-units.md`).
|
||||
# A transparent parent is not evidence that its leaf is transparent.
|
||||
if colour.a <= 0.0 and not draw_leaf_for.has(id):
|
||||
# The argument for removing it was that the game keeps SUBMITTING the
|
||||
# sweep for ~950 frames after its parent expires, which is true and which
|
||||
# I read as "the leaf outlives the parent". It does not follow: a draw
|
||||
# submitted with alpha 0 is still a draw in the command stream, and
|
||||
# submitted is not visible. Now that the parent's alpha is known to
|
||||
# multiply into the leaf's (below), skipping on a transparent parent is
|
||||
# exactly multiplying by zero, and the two are pixel-identical.
|
||||
if colour.a <= 0.0:
|
||||
# 🔴 THIS LINE USED TO SAY "at rest" WHATEVER INSTANT IT HAD POSED.
|
||||
#
|
||||
# On the timeline path the pose is `pose_at(time_units)`, not
|
||||
@@ -953,7 +967,7 @@ func _draw() -> void:
|
||||
# and rotation. See `_draw_leaf`.
|
||||
if element.get("leaf_carries_geometry", false) \
|
||||
and draw_leaf_for.has(String(element.get("id", ""))) \
|
||||
and _draw_leaf(element):
|
||||
and _draw_leaf(element, colour):
|
||||
continue
|
||||
# A FOCUSED button draws its record INSTEAD of its base sprite -- measured,
|
||||
# the focused sprite covers the base at 100.0 % of base-visible pixels.
|
||||
|
||||
Reference in New Issue
Block a user