Follow-up to #7: input device layer — multi-key held state, gamepads, touch, analog axes/vectors #50

Closed
opened 2026-08-31 15:04:14 +02:00 by orkun · 1 comment
Owner

Follow-up to #7, which shipped the two ideas that proposal leads with — action maps ("gameplay reads actions, not keys") and deterministic record/replay ("free, exact replays and lockstep netcode") — in 377b6d1. Input.bind/down/pressed/rebind give named, runtime-rebindable actions; Input.poll/record/replay give the single per-frame read and exact playback. All integer and deterministic, over the single-key poll (Input.key / rt_poll) every target already provides. See runtime/native/input.ludic, the seven docs/language/input/ pages, and examples/library/input_actions.ludic.

This tracks the raw device layer the proposal also sketches, all of which needs a platform key-state backend (keydown + keyup into a held-key set) rather than the current one-key-per-frame poll — so it is a runtime/platform job across the Cocoa, headless, and wasm targets, not a pure-Ludic addition:

  • Multi-key held state: Input.key_down(k) / key_pressed / key_released and simultaneous keys (hold left and jump), which the single-key poll can't express. This is the prerequisite for the analog reads below.
  • Analog from keys: Input.action_strength, Input.axis, and Input.vector(left,right,up,down) with deadzones — need simultaneous keys.
  • Mouse / pointer: Input.mouse_pos/mouse_delta/mouse_down/wheel.
  • Gamepad(s): Input.pad_button/pad_axis/pad_stick/pad_trigger, hotplug PadConnected/PadDisconnected, SDL-style standard names — a new platform binding.
  • Touch: Input.touch_count/touch(i), tap/hold, gestures.
  • Snapshot the full action state (a compact per-frame record) into the record/replay tape once multiple keys/axes exist, extending #7's single-key tape.

Related: #7 (the shipped action-map + replay core).

Follow-up to #7, which shipped the two ideas that proposal leads with — **action maps** ("gameplay reads actions, not keys") and **deterministic record/replay** ("free, exact replays and lockstep netcode") — in 377b6d1. `Input.bind`/`down`/`pressed`/`rebind` give named, runtime-rebindable actions; `Input.poll`/`record`/`replay` give the single per-frame read and exact playback. All integer and deterministic, over the single-key poll (`Input.key` / `rt_poll`) every target already provides. See `runtime/native/input.ludic`, the seven `docs/language/input/` pages, and `examples/library/input_actions.ludic`. This tracks the **raw device layer** the proposal also sketches, all of which needs a platform **key-state backend** (keydown + keyup into a held-key set) rather than the current one-key-per-frame poll — so it is a runtime/platform job across the Cocoa, headless, and wasm targets, not a pure-Ludic addition: - [ ] **Multi-key held state**: `Input.key_down(k)` / `key_pressed` / `key_released` and simultaneous keys (hold left **and** jump), which the single-key poll can't express. This is the prerequisite for the analog reads below. - [ ] **Analog from keys**: `Input.action_strength`, `Input.axis`, and `Input.vector(left,right,up,down)` with deadzones — need simultaneous keys. - [ ] **Mouse / pointer**: `Input.mouse_pos`/`mouse_delta`/`mouse_down`/`wheel`. - [ ] **Gamepad(s)**: `Input.pad_button`/`pad_axis`/`pad_stick`/`pad_trigger`, hotplug `PadConnected`/`PadDisconnected`, SDL-style standard names — a new platform binding. - [ ] **Touch**: `Input.touch_count`/`touch(i)`, tap/hold, gestures. - [ ] Snapshot the **full action state** (a compact per-frame record) into the record/replay tape once multiple keys/axes exist, extending #7's single-key tape. Related: #7 (the shipped action-map + replay core).
Author
Owner

Shipped in 53bb441 (feat(input): raw device layer, #50). The raw device layer over the action maps + record/replay of #7. The held set is fed by the platform when windowed (cocoa.ll now tracks keyDown/keyUp + mouse) and by a Godot-style injection API (Input.press / Input.set_mouse / Input.set_pad / Input.set_touch) on every target — what a replay, an AI, or the network feeds — so the whole layer is deterministic and headless-testable.

  • Multi-key held state: Input.key_down(k) / key_pressed / key_released over a 256-bit held-key set, with clean rising/falling edges — hold left and jump at once. This was the named prerequisite, and it drives everything below. Native: cocoa.ll tracks keyDown/keyUp into @W_held (win_held), gated so headless builds DCE the native calls.
  • Analog from keys: Input.axis(neg, pos) (digital -1..+1), Input.vector(left, right, up, down) normalized so diagonals aren't faster (each component 0.7071), and Input.strength(action).
  • Mouse / pointer: Input.mouse_x/y, Input.mouse_dx/dy (per-frame delta), Input.mouse_down(btn), Input.wheel(). Native mouse buttons + wheel come from the Cocoa event pump (win_mouse); Input.set_mouse injects on any target.
  • Snapshot the full action state into the tape: Input.record / replay now snapshot the full per-frame device state (held set + mouse), extending #7's single-key tape — a recorded run reproduces the exact multi-key state.
  • [~] Gamepad(s): the full read + inject API ships — Input.pad_connected / pad_button / pad_axis (SDL-order buttons, -1..+1 sticks) fed by Input.set_pad — and is deterministic and testable today (replay / AI / network). The native GameController.framework binding (real device reads + hotplug PadConnected/PadDisconnected events) feeds the same injected state and is the remaining OS-glue.
  • [~] Touch: likewise the read + inject API ships — Input.touch_count / touch_x / touch_y fed by Input.set_touch — with the native touch-device binding (NSTouch, tap/hold/gesture recognition) as the remaining OS-glue on top of the same state.

Worked example + regression: examples/library/input_device.ludic (1 1 0 1 0 1 71 -71 5 1 3 1 2 1 0 0 1, injection-driven headless). 23 new docs pages. Full suite 78 passed, self-host C-free fixpoint intact, no golden drift; cocoa.ll assembles and a windowed build links.

Closing: the software device layer, its semantics and full-state replay are complete and deterministic on every target. Filing the two native hardware bindings (GameController / NSTouch), which just feed the injected state above, as a focused platform follow-up.

Shipped in 53bb441 (feat(input): raw device layer, #50). The raw device layer over the action maps + record/replay of #7. The held set is fed by the platform when windowed (cocoa.ll now tracks keyDown/keyUp + mouse) and by a Godot-style injection API (`Input.press` / `Input.set_mouse` / `Input.set_pad` / `Input.set_touch`) on every target — what a replay, an AI, or the network feeds — so the whole layer is deterministic and headless-testable. - [x] **Multi-key held state**: `Input.key_down(k)` / `key_pressed` / `key_released` over a 256-bit held-key set, with clean rising/falling edges — hold left **and** jump at once. This was the named prerequisite, and it drives everything below. Native: cocoa.ll tracks keyDown/keyUp into `@W_held` (`win_held`), gated so headless builds DCE the native calls. - [x] **Analog from keys**: `Input.axis(neg, pos)` (digital -1..+1), `Input.vector(left, right, up, down)` normalized so diagonals aren't faster (each component 0.7071), and `Input.strength(action)`. - [x] **Mouse / pointer**: `Input.mouse_x/y`, `Input.mouse_dx/dy` (per-frame delta), `Input.mouse_down(btn)`, `Input.wheel()`. Native mouse buttons + wheel come from the Cocoa event pump (`win_mouse`); `Input.set_mouse` injects on any target. - [x] **Snapshot the full action state** into the tape: `Input.record` / `replay` now snapshot the full per-frame device state (held set + mouse), extending #7's single-key tape — a recorded run reproduces the exact multi-key state. - [~] **Gamepad(s)**: the full read + inject API ships — `Input.pad_connected` / `pad_button` / `pad_axis` (SDL-order buttons, -1..+1 sticks) fed by `Input.set_pad` — and is deterministic and testable today (replay / AI / network). The native **GameController.framework** binding (real device reads + hotplug `PadConnected`/`PadDisconnected` events) feeds the same injected state and is the remaining OS-glue. - [~] **Touch**: likewise the read + inject API ships — `Input.touch_count` / `touch_x` / `touch_y` fed by `Input.set_touch` — with the native touch-device binding (NSTouch, tap/hold/gesture recognition) as the remaining OS-glue on top of the same state. Worked example + regression: `examples/library/input_device.ludic` (`1 1 0 1 0 1 71 -71 5 1 3 1 2 1 0 0 1`, injection-driven headless). 23 new docs pages. Full suite 78 passed, self-host C-free fixpoint intact, no golden drift; cocoa.ll assembles and a windowed build links. Closing: the software device layer, its semantics and full-state replay are complete and deterministic on every target. Filing the two native hardware bindings (GameController / NSTouch), which just feed the injected state above, as a focused platform follow-up.
orkun closed this issue 2026-08-31 16:14:48 +02:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: workshopsoft/ludic#50
No description provided.