One cycle of keyboard, text, mouse and gamepad input.
App.Input contains the host's observation as input.devices. A snapshot is
pure data and grants no device authority.
Two kinds of information are in it, and each field says which it is. A
state sample is the latest value at the cycle boundary: a held key, the
pointer position, a gamepad axis. An interval event is something that
happened since the previous input: a press, a release, a typed character,
a wheel notch. On a desktop host the keyboard, mouse-button, wheel and text
events are recorded from the window system's own event callbacks, so an
event that reaches the process is in the next input or reported as an
overflow, never silently lost, with a latency of at most one cycle.
Gamepad buttons are the exception: raylib polls them with no callback, so
their edges are sampled and a press-and-release between two polls is lost.
The interval events come in two views. The packed bits behind
key_pressed, mouse.button_pressed and friends are the coalesced view:
at least one press, at least one release, per key or button. events is
the record: every event in delivery order, with count, order across
sources and the pointer position of every click preserved up to a stated
capacity. Read the bits for simple held-or-pressed logic; read the list
when order or count matters -- a double tap, a drag that ended and began
again inside one frame, text editing where a keystroke has to land between
two characters.
Tests can start from Devices.none and set only the relevant state with the
with_key_* and with_mouse_* methods.
A neutral snapshot with the host's own packed list lengths, for tests.
empty and none return the same result for every query -- nothing held,
nothing typed, pointer at the origin, no gamepad connected. They differ in
what they are made of. empty's packed lists are empty, which is all a
model seed needs and costs nothing. none's are the lengths the host
actually samples: 349 key bytes, 7 mouse-button bytes, 4 gamepad
availability bytes, 4 x 18 gamepad button bytes, and 4 x 6 axes. That is
what makes it writable, so the with_key_* and with_mouse_* methods
have somewhere to put a bit.
A snapshot in which nothing is pressed, nothing was typed, the pointer is
at the origin, and no gamepad is connected.
Use this to initialize models before the first device snapshot is sampled.
Devices.none is the same observation with the host's packed list lengths,
which is what a test that wants to say "SPACE was pressed" needs.
Check whether a key was pressed during this input interval. Receiver form:
input.key_pressed(KeyW). Static Keys.key_pressed(input, KeyW)
remains available; combine singular queries with or when checking
alternatives.
Say that one key is held, as Devices.none.with_key_down(KeyW).
Each with_key_* states the complete state of the key it names,
replacing whatever that key had. Different keys are independent
bytes, so these compose:
Devices.none.with_key_pressed(KeySpace).with_key_down(KeyLeftShift).
Only a snapshot with the host's packed list lengths can hold these.
Start from Devices.none, not Devices.empty.
Say that one mouse button is held. The with_mouse_button_* family
states the complete state of the button it names, exactly as the
with_key_* family does.
Say that these codepoints were typed this cycle, in order, as
Devices.none.with_text_input([72, 105]) for typing "Hi".
As the host does, at most 32 codepoints are kept; a longer burst keeps
the first 32 and sets text_input_overflow. The key bits and the
event record are not derived from it: a test that wants them to
agree states them too, as the host would have.
State the interval's event record, as
Devices.none.with_events([KeyPressed(KeySpace), KeyReleased(KeySpace)]).
The bits are not derived from it: a test that wants both views to
agree states both, as the host would have. Unlike the with_key_*
methods this works on Devices.empty too, since a list has no
fixed length to fit.
Say whether the event record was cut at its capacity, which is what
events_overflow reports.
Event : [
KeyPressed(Key),
KeyReleased(Key),
ButtonPressed(Button, { x : F32, y : F32 }),
ButtonReleased(Button, { x : F32, y : F32 }),
Wheel({ x : F32, y : F32 }),
Text(U32),
]
One input event, as the window system delivered it.
KeyPressed and KeyReleased are physical key edges; auto-repeat is
not an event. ButtonPressed and ButtonReleased include the pointer
position where the click happened, in the same logical coordinates as
mouse.position(). Wheel is one scroll event's offsets, which
mouse.wheel_delta() sums. Text is one typed codepoint, following the
active keyboard layout, which is why it is separate from the key edge
that produced it.