Files
sporel-lib-core.input/README.md
Axel Meyer 837dc3cbc7 feat(input): v0.4.0 — was_action_released release-edge (P.3.10)
Additive, backward-compatible. Mirrors was_action_pressed dispatch
pattern. Selection-Lib's prev_click_down workaround now obsolete.
Engine bindings (was_released + was_mouse_released) added in
sporel-engine commit covering P.3.10 Task 1.

Removes was_released-edge entry from DEPRECATED-MVP list.
2026-05-15 21:26:24 +02:00

4.4 KiB

lib-core.input

P.0 action-mapping lib. Decouples physical keys from logical actions. Polling-based (is_action_down) + edge-based (was_action_pressed, was_action_released). Direction-vector helper composes 4 actions into {x, y} ∈ {-1, 0, +1}².

  • Lib-ID: lib-core.input
  • Version: 0.4.0
  • Spec v0.3.0 (P.3.3): meta/docs/superpowers/specs/2026-05-12-p3-3-mouse-input-design.md
  • Spec v0.2.0 (P.2.6): meta/docs/superpowers/specs/2026-05-11-engine-input-symbolic-keys-design.md
  • Spec v0.1.0 (P.0): meta/docs/superpowers/specs/2026-05-09-p0-lib-input-design.md

Forward-compat stubs (DEPRECATED-MVP) for mouse-button actions, gamepad bindings, action-context-stack, key-rebinding-config, modifier-combos, analog-axis, right-modifier-keys, function-keys, special-keys (delete/insert/home/end/pageup/pagedown).

API

  • input.bind(action_name, {"keyname1", "keyname2", ...}) — bind multi-key array (string-keys only, see §Key-Names)
  • input.unbind(action_name) — remove binding
  • input.is_action_down(action) → bool — any bound key currently down
  • input.was_action_pressed(action) → bool — any bound key just-pressed (press-edge; true for exactly one frame per key-down event)
  • input.was_action_released(action) → bool — any bound key just-released (release-edge; true for exactly one frame per key-up event; triggers once per press-release cycle)
  • input.direction(left, right, up, down) → {x, y} — vec in {-1,0,+1}², Y-down-positive
  • input.action_count() → number — bound-actions count

Key-Names (v0.2.0)

Strict-lowercase. Engine-internal engine.input.KEY_* integer-args are rejected.

Category Names
Letters a, b, …, z
Numbers 0, 1, …, 9
Arrows left, right, up, down
Whitespace + control space, tab, enter, backspace, escape
Modifiers (left-side) shift (= lshift), ctrl (= lctrl), alt (= lalt)
Console-toggle ^ (DE: Zirkumflex / US: backtick — Quake/Source-Tradition)

Right-modifier-aliases (rshift, rctrl, ralt) + function-keys (f1..f12) + special-keys (delete, insert, …) are forthcoming — additiv wenn engine.input die entsprechenden KEY_*-Konstanten exposed.

Unknown key-names raise a Lua-error with hint to this README.

Conventions

  • Y-down-positive per Sporel pixel-convention (ADR-0031).
  • Multi-key per action (e.g., {"a", "left"} for both A and Left-Arrow).
  • Silent-false for undefined actions (debug-friendly; lookup-misuse won't drown the game-loop in errors).
  • Lua error(...) for bind() misuse (caller-bug fast-fail). Atomic: invalid key fails the entire bind without partial-state mutation.

Consumer pattern

local input = require("lib-core.input")
input.bind("quit",       { "escape" })
input.bind("move_left",  { "a", "left" })
input.bind("move_right", { "d", "right" })
input.bind("move_up",    { "w", "up" })
input.bind("move_down",  { "s", "down" })

function update(ctx, dt)
    if input.was_action_pressed("quit") then engine.exit(0) end
    local d = input.direction("move_left", "move_right", "move_up", "move_down")
    -- d.x, d.y ∈ {-1, 0, +1}
end

Migration v0.1.0 → v0.2.0

bind() switched from integer engine.input.KEY_* arguments to lowercase string-keys (per P.2.6). Reason: stop leaking engine-internal namespace into modules; align with ADR-0001 „engine knows verbs, libs bring nouns".

v0.1.0 v0.2.0
bind("quit", { engine.input.KEY_ESCAPE }) bind("quit", { "escape" })
bind("move", { engine.input.KEY_A, engine.input.KEY_LEFT }) bind("move", { "a", "left" })

engine.input.KEY_* constants remain available for direct engine-input use (e.g. engine.input.is_key_down(engine.input.KEY_F1) for edge-cases without bind), but lib-core.input.bind strict-rejects them.

CHANGELOG

v0.4.0 (P.3.10, 2026-05-15)

  • Added was_action_released(action_name) — release-edge detection per action. Selection-Lib's prev_click_down workaround promoted.
  • Engine surface: engine.input.was_released + was_mouse_released.

v0.3.0 (P.3.3, 2026-05-12)

  • bind() now accepts unified key+mouse strings via BIND_MAP with kind-tagged entries.
  • Mixed bindings supported (e.g. {"e", "mouse_left"}).
  • Backward-compatible with v0.2.0 callsites.

v0.2.0 (P.2.6, 2026-05-11)

  • bind() accepts string-key-names only. Integer engine.input.KEY_* args are rejected.