Event-based Input Manager: rebindable actions with defaults (currently poll-based); frame loop should drive the device layer #83
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#83
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 is loop/poll-based (
Input.poll()each frame +Input.key_down(...)). Action maps exist (Input.bind) but are still polled, and there is no first-class Input Manager offering: (a) event-based dispatch (on-press/on-release handlers), (b) rebindable actions with sensible defaults shipped by the game, (c) device-agnostic actions (keyboard/mouse/gamepad mapped to one action).Separately, a papercut/bug: the generated frame loop calls
rt_poll()(feeds onlyInput.key()) but neverinput_poll(), soInput.key_down/mouse/padread empty unless the game manually callsInput.poll()at the top of its Input phase. The loop should commit the device layer automatically when a game uses it.Proposal: an Input Manager (declare actions + default bindings, rebind at runtime, receive input as events), and auto-driving of the device layer.
Shipped in
bccd26f(real implementation, tested — full suite 107/0, golden renders byte-identical, C-free bootstrap fixpoint intact).The bug/papercut — fixed. The generated frame loop called
rt_poll()(which feeds onlyInput.key) but neverinput_poll(), soInput.active/key_down/ mouse / pad read empty unless the game manually calledInput.poll()at the top of its Input phase. The loop now auto-commits the device layer: when a game uses any Input action-map / device method it callsinput_poll()each frame (reads the live key, records/replays, rebuilds the held-key + mouse + gamepad state) and stores the returned key soInput.keystill works. A game that uses no Input runtime keeps the plainrt_pollpath, byte-identical. Verified byexamples/library/input_auto.ludic— a handler game that readsInput.activein Update and never callsInput.poll, driven by stdin keys.Input Manager API (the proposal's three asks, in a deterministic, dispatch-free form):
Input.action(name, key)ships a default binding, kept if the action is already bound so a player'sInput.rebind(or a loaded key-map) is never clobbered.Input.bind_pad(name, button)maps a gamepad button to the same action; one action fires from keyboard or pad.Input.active(held),Input.just_pressed(on-press edge),Input.just_released(on-release edge) read the whole multi-key device layer. These are the deterministic equivalent of on-press/on-release handlers: a handler polls the edge and reacts, so a replay fires the exact same edges. True runtime callback dispatch is intentionally not added — it would break the no-dispatch determinism guarantee the engine (and lockstep netcode) rests on; edge-polling is the idiomatic replacement.Verified by
examples/library/input_manager.ludic. Both wired as feat_cases; 5 docs pages added.