Module for reading input and working with player bindings.
Scripts ask about roles, not physical keys. A role is a game action such as jumping, drawing a weapon, or opening a menu. The key or button that triggers it depends on the player's device and layout.
Use \{input ...} in text to draw the binding for a role.
A few functions read the keyboard and the controller themselves, for a script that needs the key rather than the action, such as one reading a passcode.
A key that prints a character is named by the character the player's layout
prints, so the key labelled 5 is "5" on every layout. A key with a label
rather than a character keeps the spelling the window system gives it, in
lower case: "escape", "return", "left shift", "f5", "keypad 5".
While a rebind is reading a device, hardware reads report no input. The
presses are not saved. trx.input.is_reserved reports this state. Key and
button names remain available.
trx.input.grab gives a script exclusive input. Use trx.console.is_open
when a script must ignore text entered in the console.
A controller button or axis keeps the name SDL gives it, because a pad
prints a different label on the same button depending on who made it. The
buttons are "a", "b", "x", "y", "back", "guide", "start",
"leftstick", "rightstick", "leftshoulder", "rightshoulder",
"dpup", "dpdown", "dpleft", "dpright", "misc1", "paddle1" to
"paddle4" and "touchpad". The axes are "leftx", "lefty", "rightx",
"righty", "lefttrigger" and "righttrigger".
trx.input.backend (trx.input.Backend). The current input source. (read-only)trx.input.has_touchscreen (boolean). Whether the device has a screen the player touches. A trackpad does not count. (read-only)trx.input.layout (trx.input.Layout). The current layout for the current input source. (read-only)trx.input.is_listening (boolean). Whether script input capture is on. (read-only)A game action the player can bind to a key or button. In text, \{input ...} draws its current binding.
ACTION, BACK, CAMERA_BACK, CAMERA_DOWN, CAMERA_FORWARD,
CAMERA_LEFT, CAMERA_RESET, CAMERA_RIGHT, CAMERA_UP, CHANGE_OUTFIT,
CHANGE_TARGET, CROUCH, CYCLE_AMMO, CYCLE_LIGHTING_MODEL, DRAW,
ENTER_CONSOLE, EQUIP_AUTOS, EQUIP_CROSSBOW, EQUIP_DESERT_EAGLE,
EQUIP_GRENADE_LAUNCHER, EQUIP_HARPOON, EQUIP_M16, EQUIP_MAGNUMS,
EQUIP_MP5, EQUIP_PISTOLS, EQUIP_REVOLVER, EQUIP_ROCKET_LAUNCHER,
EQUIP_SHOTGUN, EQUIP_UZIS, FAST_FORWARD_CHEAT, FLY_CHEAT, FORWARD,
ITEM_CHEAT, JUMP, LEFT, LEVEL_SKIP_CHEAT, LOAD, LOOK,
MENU_BACK, MENU_COARSE_ADJUST, MENU_CONFIRM, MENU_DOWN,
MENU_FINE_ADJUST, MENU_LEFT, MENU_RIGHT, MENU_SHOW_INFO,
MENU_SKIP, MENU_TAB_LEFT, MENU_TAB_RIGHT, MENU_UP, OPTION,
PAUSE, QUICK_LOAD, QUICK_SAVE, RESET_BINDINGS, RIGHT, ROLL,
SAVE, SCREENSHOT, SLOW, SLOW_MOTION_CHEAT, SPRINT, STEP_LEFT,
STEP_RIGHT, SWITCH_BORDERS, SWITCH_UPSCALING,
TOGGLE_BILINEAR_FILTER, TOGGLE_FPS_COUNTER, TOGGLE_FULLSCREEN,
TOGGLE_PHOTO_MODE, TOGGLE_TEXTURES, TOGGLE_TRAPEZOID_FILTER,
TOGGLE_UI, TOGGLE_WIREFRAME, TURBO_CHEAT, UNBIND_KEY,
USE_BIG_MEDI, USE_BINOCULARS, USE_FLARE, USE_SMALL_MEDI
An input source, such as keyboard, controller, or touch.
trx.input.Backend.KEYBOARDtrx.input.Backend.CONTROLLERtrx.input.Backend.TOUCHWhere the player lands after skipping a scene. It decides which roles a skip holds inactive.
trx.input.SkipContext.TO_SCREENtrx.input.SkipContext.TO_GAMEtrx.input.SkipContext.IN_GAMEA saved set of bindings for one input source. The default layout is read-only; the custom layouts belong to the player.
trx.input.Layout.DEFAULTtrx.input.Layout.CUSTOM_1trx.input.Layout.CUSTOM_2trx.input.Layout.CUSTOM_3Which of the two bindings a role can use. Counted from 1.
The slot, input source, and layout of a role binding.
Properties:
backend: trx.input.Backend, optional. Input source. Defaults to the current one.layout: trx.input.Layout, optional. Layout. Defaults to the current one.slot: trx.input.Slot, optional, default 1. Binding slot. Defaults to the first.A set of roles a script holds inactive.
Methods:
A binding capture waiting for the player to press something.
Methods:
The devices a script holds, taken from the game.
Methods:
trx.input.signals
Input roles as signals.
Each role has one shared signal, so several consumers of the same role use one read per tick.
trx.input.is_held(role)
Whether a role is active right now.
This stays true while the player holds the bound key or button. Use it for actions that continue while held.
Parameters:
role (trx.input.Role). The role to ask about.Returns: boolean. Whether the role is active.
trx.input.is_pressed(role)
Whether a role became active this frame.
This is true for one frame only. Use it for actions that happen once per press.
Parameters:
role (trx.input.Role). The role to ask about.Returns: boolean. Whether the role was pressed.
trx.input.is_anything_held()
Whether any role is active right now.
Use this to wait for the player to let go before reading input for something else, such as a rebind.
Returns: boolean. Whether anything is held.
trx.input.hold_off(role)
Keeps a handled role inactive until the player releases it.
Use this after a script handles a press, so the same press does not reach other input code or fire again while held.
Parameters:
role (trx.input.Role). The role to take.trx.input.hold_off_skip(context)
Keeps each role that can skip a scene inactive until the player releases it.
Use this after a script ends a scene on a skip press, so the same press does not act on what comes after the scene.
Parameters:
context (trx.input.SkipContext). Where the player lands after the skip.trx.input.is_reserved()
Whether the game has the keyboard and the pad rather than the player.
This is true while a rebind is reading input. Every hardware read reports nothing then, so a script that would otherwise answer an empty keypad can tell the two apart.
A script holding the devices with trx.input.grab is not this, and
trx.input.is_grabbed reports that instead. The console is one such script.
Returns: boolean. Whether the game has the devices.
trx.input.is_key_held(key)
Whether a key is down right now.
This reads the keyboard rather than the player's bindings, so it answers for
the key itself and says nothing about a controller. Prefer
trx.input.is_held for a game action: it follows what the player bound and
works on every device.
Reports false while trx.input.is_reserved is true. A name no key on the
player's layout carries raises.
Parameters:
Returns: boolean. Whether the key is down.
trx.input.is_key_pressed(key)
Whether a key went down in this frame.
This is true for one frame only. trx.events.on_key_down reports the same
presses without a script naming the keys it cares about in advance.
Reports false while trx.input.is_reserved, and a press that arrived then
is not kept for afterwards. A key still held as the game gives the keyboard
back fires trx.events.on_key_down but reports no press here.
A name no key on the player's layout carries raises.
Parameters:
Returns: boolean. Whether the key went down.
trx.input.is_key_known(key)
Whether the player's layout has a key of that name.
Use this to check a name a mod's own settings supplied, rather than letting
trx.input.is_key_held raise on it.
Parameters:
Returns: boolean. Whether a key carries it.
trx.input.is_button_held(button)
Whether a controller button is down right now.
This reads the pad rather than the player's bindings, so it answers for the
button itself. Prefer trx.input.is_held for a game action: it follows what
the player bound and works on every device.
Reports false while trx.input.is_reserved. A name SDL does not know
raises.
Parameters:
Returns: boolean. Whether the button is down.
trx.input.is_button_pressed(button)
Whether a controller button went down in this frame.
This is true for one frame only. trx.events.on_button_down reports the
same presses without a script naming the buttons it cares about in advance.
Reports false while trx.input.is_reserved, and a press that arrived then
is not kept for afterwards. A button still held as the game gives the pad
back fires trx.events.on_button_down but reports no press here.
A name SDL does not know raises.
Parameters:
Returns: boolean. Whether the button went down.
trx.input.is_button_known(button)
Whether a controller button carries that name.
Parameters:
Returns: boolean. Whether a button carries it.
trx.input.axis(axis)
Where a controller axis stands, from -1 to 1.
A stick reaches -1 left or up and 1 right or down. A trigger runs from 0 at
rest to 1 held down. An axis reads 0 while the pad is unplugged and while
trx.input.is_reserved.
A name SDL does not know raises.
Parameters:
Returns: number. Where the axis stands.
trx.input.is_axis_known(axis)
Whether a controller axis carries that name.
Parameters:
Returns: boolean. Whether an axis carries it.
trx.input.suppress(...)
Holds roles inactive until the returned suppression is released.
The game does not act on the role, and trx.input.is_held and
trx.input.signals report it inactive as well. Use this to take an action
away for as long as a script needs it gone, such as while the player works a
puzzle.
Only the roles named are affected. A suppressed movement role still moves the menu cursor, so a script that wants both suppresses both.
Suppressions are released when the level unloads.
Parameters:
... (trx.input.Role). The roles to hold inactive.Returns: trx.input.Suppression. The running suppression.
Example:
local held = trx.input.suppress(
trx.input.Role.JUMP,
trx.input.Role.ROLL
)
local function on_puzzle_solved()
held:release()
end
trx.input.is_suppressed(role)
Whether a role is held inactive by any suppression.
Parameters:
role (trx.input.Role). The role to ask about.Returns: boolean. Whether the role is held.
trx.input.is_backend_enabled(backend)
Whether an input source is enabled.
Disabled sources are not read or shown in the controls dialog.
Parameters:
backend (trx.input.Backend). The input source to ask about.Returns: boolean. Whether the input source is enabled.
trx.input.role_name(role)
The name the game shows for a role, in the player's language.
Parameters:
role (trx.input.Role). The role to name.Returns: string. The name of the role.
trx.input.layout_name([layout])
The name the game shows for a layout, in the player's language.
Parameters:
layout (trx.input.Layout, optional). The layout to name. Defaults to the current one.Returns: string. The name of the layout.
trx.input.key_name(role, [opts], [backend], [layout])
Text for the key or button bound to a role.
This is the text drawn by \{input ...}: a glyph when one exists, otherwise
a key name. Empty bindings return nil.
Use trx.input.Binding to choose a slot, input source, or layout without
placeholder nils. Positional arguments still work.
Parameters:
role (trx.input.Role). The role to ask about.opts (trx.input.Slot or trx.input.Binding, optional). Binding to read. Defaults to the first slot on the current source and layout.backend (trx.input.Backend, optional). The input source to read. Defaults to the current one.layout (trx.input.Layout, optional). The layout to read. Defaults to the current one.Returns: string or nil. The key text, or nil if the binding is empty.
trx.input.has_glyph(role, [opts], [backend], [layout])
Whether trx.input.key_name has text to draw for a role binding.
Use this to hide prompts for unbound roles.
Use trx.input.Binding to choose a slot, input source, or layout without
placeholder nils. Positional arguments still work.
Parameters:
role (trx.input.Role). The role to ask about.opts (trx.input.Slot or trx.input.Binding, optional). Binding to read. Defaults to the first slot on the current source and layout.backend (trx.input.Backend, optional). The input source to read. Defaults to the current one.layout (trx.input.Layout, optional). The layout to read. Defaults to the current one.Returns: boolean. Whether the binding has text to draw.
trx.input.is_rebindable(role)
Whether the player can change a role's binding.
Roles reserved by the game cannot be rebound and do not count as conflicts.
Parameters:
role (trx.input.Role). The role to ask about.Returns: boolean. Whether it can be bound.
trx.input.is_unbindable(role)
Whether the player can leave a role without a binding.
Parameters:
role (trx.input.Role). The role to ask about.Returns: boolean. Whether it can be left unbound.
trx.input.is_conflicted(role, [opts], [layout])
Whether another role uses the same binding in the same layout.
Use trx.input.Binding to choose an input source or layout without
placeholder nils. Positional arguments still work.
Parameters:
role (trx.input.Role). The role to ask about.opts (trx.input.Backend or trx.input.Binding, optional). Binding to check. Defaults to the current source and layout.layout (trx.input.Layout, optional). The layout to read. Defaults to the current one.Returns: boolean. Whether the binding is used twice.
trx.input.listen(enabled)
Turns script input capture on or off.
While capture is on, scripts can read or bind input without the game acting on the same input. Turn capture off as soon as the input is handled.
Parameters:
trx.input.with_listen(fn)
Runs a function with script input capture on.
Restores the previous capture state after the function returns or raises an error. Returns the function's results.
Parameters:
trx.input.bind_pressed(role, [opts], [backend], [layout])
Binds a role to the key or button the player is holding.
Returns false if no input is held. Call it each frame while waiting for
input, with trx.input.listen on or from inside trx.input.with_listen.
The default layout is read-only. A new binding is saved with the settings.
Use trx.input.Binding to choose a slot, input source, or layout without
placeholder nils. Positional arguments still work.
Parameters:
role (trx.input.Role). The role to bind.opts (trx.input.Slot or trx.input.Binding, optional). Binding to write. Defaults to the first slot on the current source and layout.backend (trx.input.Backend, optional). The input source to bind on. Defaults to the current one.layout (trx.input.Layout, optional). The layout to write. Defaults to the current one.Returns: boolean. Whether a key was taken.
trx.input.capture(role, [opts], [done])
Binds a role to the next key or button the player presses.
The capture spans frames: it waits for the player to let go of what is already down, turns capture on, and takes the first press after that. The previous capture state is restored when it lands or when the capture is cancelled.
Use this instead of trx.input.listen and trx.input.bind_pressed, which
only answer for the frame they run on. The default layout is read-only.
Use trx.input.Binding to choose a slot, input source, or layout without
placeholder nils.
Parameters:
role (trx.input.Role). The role to bind.opts (trx.input.Slot or trx.input.Binding, optional). Binding to write. Defaults to the first slot on the current source and layout.done (function, optional). Called when the capture ends.
Called with:
Returns: trx.input.Capture. The running capture.
trx.input.unbind(role, [opts], [backend], [layout])
Clears one role binding, and saves the bindings with the settings.
The default layout is read-only. A slot that holds no key is left as it is.
A role that must keep a key, such as jumping, loses a binding only while
another slot still holds a key; see trx.input.can_unbind.
Use trx.input.Binding to choose a slot, input source, or layout without
placeholder nils. Positional arguments still work.
Parameters:
role (trx.input.Role). The role to unbind.opts (trx.input.Slot or trx.input.Binding, optional). Binding to clear. Defaults to the first slot on the current source and layout.backend (trx.input.Backend, optional). The input source to write. Defaults to the current one.layout (trx.input.Layout, optional). The layout to write. Defaults to the current one.trx.input.can_unbind(role, [opts], [backend], [layout])
Whether trx.input.unbind can clear a role binding.
It cannot on the default layout, for a slot that holds no key, nor for the last key of a role that must keep one, such as jumping.
Use trx.input.Binding to choose a slot, input source, or layout without
placeholder nils. Positional arguments still work.
Parameters:
role (trx.input.Role). The role to ask about.opts (trx.input.Slot or trx.input.Binding, optional). Binding to clear. Defaults to the first slot on the current source and layout.backend (trx.input.Backend, optional). The input source to ask about. Defaults to the current one.layout (trx.input.Layout, optional). The layout to ask about. Defaults to the current one.Returns: boolean. Whether the binding can be cleared.
trx.input.reset_layout([opts], [layout])
Restores a custom layout to the default bindings, and saves the bindings
with the settings.
Use trx.input.Binding to choose an input source or layout without
placeholder nils. Positional arguments still work.
Parameters:
opts (trx.input.Backend or trx.input.Binding, optional). Layout to reset. Defaults to the current source and layout.layout (trx.input.Layout, optional). The layout to write. Defaults to the current one.trx.input.grab()
Takes the keyboard and the pad from the game until the returned grab is
released.
The game stops responding to the devices while the script can still read them. Use this for text fields, consoles, and passcode boxes. Release the grab when the script no longer needs the devices.
trx.input.suppress removes one action. A grab takes both devices. The game
still has priority while trx.input.is_reserved is true. Grabs are released
when the level unloads.
Returns: trx.input.Grab. The running grab.
Example:
local grab = trx.input.grab()
if typed == passcode then
grab:release()
end
trx.input.is_grabbed()
Whether a script holds the devices.
This reports what trx.input.grab took, and says nothing about
trx.input.is_reserved, which is the game holding them instead.
Returns: boolean. Whether a script holds the devices.
trx.input.signals.held(role)
A signal for whether a role is active.
It is true while the player holds the bound key or button. It changes when the role becomes active and when it stops.
Parameters:
role (trx.input.Role). The role to follow.Returns: trx.signal.Signal. The role's signal.
trx.input.signals.pressed(role)
A signal for when a role becomes active.
It is true for one tick only, so listeners run once per press.
Parameters:
role (trx.input.Role). The role to follow.Returns: trx.signal.Signal. The role's signal.