Input.key_pressed / key_released never fire (edge detection broken) — key_down works #87
Labels
No labels
area:ci
area:docs
area:input
area:net
area:rendering
area:repo
area:stdlib
area:tooling
area:types
cleanup
dx
priority:high
priority:low
priority:medium
proposal
status:in-progress
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: workshopsoft/ludic#87
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Input.key_pressed(key:)never returns true even when the key transitions from up to down;Input.key_downreports the key correctly. Reproduced deterministically headless (the device layer buildsin_heldfrom the polled stdin char):input_device_commitsnapshotsin_prev <- in_heldbefore rebuildingin_held, andinput_key_pressedisheld && !prev, so on paper the edge should appear on the first held frame. It doesn't, so something else is resetting/aliasingin_prev(suspects:in_init()re-allocating sets, or prev being refreshed again after the rebuild).key_releasedlikely shares the fault.Impact: any game verb bound to a press edge (dash, melee, menu confirm) silently never triggers. Workaround: game-side edge detection with a previous-state flag. Windowed path shares the same code, so this is not headless-only.
Fixed in
0497029(full suite 110/0, golden renders byte-identical, fixpoint intact).Root cause — a double-commit, exactly as you suspected (
in_prevgetting aliased toin_held). Since #83 the generated frame loop commits the device layer once per frame (input_drive). A game that also calledInput.pollby hand — which was the only way to get device state before #83 — committed a second time in the same frame.input_device_commitcopiesin_heldintoin_prevat the top of every commit, so the second commit madein_prev == in_held, andkey_pressed(held && !prev) /key_releasedcould never see a transition. Your repro (which callsInput.pollin the handler) hit exactly this.Fix — an
in_have_frame_driverflag: the loop'sinput_drivesets it, and a manualInput.pollunder the loop becomes a no-op that returns the frame's key instead of re-committing. So there is exactly one commit per frame and the edges fire on the transition frame. An entry-driven harness (no loop) leaves the flag false, so eachInput.pollstill commits a frame of input as before — the #7/#50 record/replay + device tests are unchanged.Verified with
examples/library/input_edge.ludic— a handler game reading the key edges in Update, driven by stdinxkkxq, prints0 11 1 100 0: the press edge fires on the frame the key goes down (11), stays held with no edge (1), and the release edge fires on the frame it goes up (100). Your original repro now prints the expected... 211 310 ...too (frame 2 shows the held+pressed edge). Wired as a feat_case.