Input
Keyboard, mouse and gamepad state, input actions, and rebinding.
Files: input.odin, input_rebind.odin.
File overviews
Section titled “File overviews”input.odin
Section titled “input.odin”Input: the keyboard, mouse and gamepads as state a script can ask about, and actions: named inputs (“jump”, “move_left”) that any of several keys, mouse buttons, gamepad buttons or stick directions trigger, like Godot’s input map. Scripts ask about actions, so players can remap them and one game runs on a keyboard or a gamepad without code changes:
update = proc(self: ^Player, _: []sdl.Event, dt: f64) { move := e.Input_GetVector("move_left", "move_right", "move_up", "move_down") self.node.position += move * 200 * f32(dt) if e.Input_IsActionJustPressed("jump") do jump(self)}Projects define their actions in project.xml (the editor’s Project Settings > Input):
<action name="jump" deadzone="0.5"> <key key="Space"/> <mouse button="Left"/> <gamepad button="South"/> <axis axis="LeftY" direction="-1"/></action>Pressed: held down now.JustPressed/JustReleased: this frame only (a key’s repeats don’t count).Strength: 0 to 1 (1 for keys and buttons; how far a stick or trigger is pushed, 0 inside the action’sdeadzone).- Raw state without actions:
Input_IsKeyPressed(.Space),Input_IsMouseButtonJustPressed(.Left),Input_GetMousePosition()(game coordinates),Input_GetGamepadAxis(.LeftX)… The engine’s ownKey,MouseButton,GamepadButtonandGamepadAxisenums name them; SDL isn’t needed. The SDL events passed toupdateare still there for code that wants them. - Gamepads are numbered from 0 in the order they’re connected; device -1 means any of them.
- The game’s
inputis updated at the start of every frame (Game_Update), before globals and scenes. Procedures use the game that’s playing (likeGlobal) unless given one.
input_rebind.odin
Section titled “input_rebind.odin”Rebinding: letting players change what triggers an action, from the game’s options menu, and keeping their choice. And gamepad rumble.
Input_StartCapture(game), then each frameInput_GetCapturedBinding(game): the next key, mouse button, gamepad button, or stick or trigger pushed past halfway comes back once (Escape too: the game decides whether it cancels). Until then, and on the frame it comes, actions don’t press or release, so the press being bound doesn’t also act.Input_SetBindings(name, bindings)changes an action’s bindings (Input_GetBindingsreads them;Input_ActionsUsingfinds actions a binding is already on;Input_ResetBindingsputs back the project’s).Input_SaveBindings()keeps every action’s bindings with the game’s saves (Input_LoadBindingsat start, after the project is loaded: actions the save doesn’t have keep the project’s).
Example
// The options menu's "Jump" buttone.Input_StartCapture()// Its update:if binding, ok := e.Input_GetCapturedBinding(); ok { if binding != e.InputBinding(e.KeyBinding{.Escape}) { e.Input_SetBindings("jump", {binding}) e.Input_SaveBindings() }}Key :: enum i32 { Unknown = 0, A = i32(sdl.Scancode.A), B = i32(sdl.Scancode.B), C = i32(sdl.Scancode.C), D = i32(sdl.Scancode.D), E = i32(sdl.Scancode.E), F = i32(sdl.Scancode.F), G = i32(sdl.Scancode.G), H = i32(sdl.Scancode.H), I = i32(sdl.Scancode.I), J = i32(sdl.Scancode.J), K = i32(sdl.Scancode.K), L = i32(sdl.Scancode.L), M = i32(sdl.Scancode.M), N = i32(sdl.Scancode.N), O = i32(sdl.Scancode.O), P = i32(sdl.Scancode.P), Q = i32(sdl.Scancode.Q), R = i32(sdl.Scancode.R), S = i32(sdl.Scancode.S), T = i32(sdl.Scancode.T), U = i32(sdl.Scancode.U), V = i32(sdl.Scancode.V), W = i32(sdl.Scancode.W), X = i32(sdl.Scancode.X), Y = i32(sdl.Scancode.Y), Z = i32(sdl.Scancode.Z), Num1 = i32(sdl.Scancode._1), Num2 = i32(sdl.Scancode._2), Num3 = i32(sdl.Scancode._3), Num4 = i32(sdl.Scancode._4), Num5 = i32(sdl.Scancode._5), Num6 = i32(sdl.Scancode._6), Num7 = i32(sdl.Scancode._7), Num8 = i32(sdl.Scancode._8), Num9 = i32(sdl.Scancode._9), Num0 = i32(sdl.Scancode._0), Enter = i32(sdl.Scancode.RETURN), Escape = i32(sdl.Scancode.ESCAPE), Backspace = i32(sdl.Scancode.BACKSPACE), Tab = i32(sdl.Scancode.TAB), Space = i32(sdl.Scancode.SPACE), Minus = i32(sdl.Scancode.MINUS), Equals = i32(sdl.Scancode.EQUALS), LeftBracket = i32(sdl.Scancode.LEFTBRACKET), RightBracket = i32(sdl.Scancode.RIGHTBRACKET), Backslash = i32(sdl.Scancode.BACKSLASH), Semicolon = i32(sdl.Scancode.SEMICOLON), Apostrophe = i32(sdl.Scancode.APOSTROPHE), Grave = i32(sdl.Scancode.GRAVE), Comma = i32(sdl.Scancode.COMMA), Period = i32(sdl.Scancode.PERIOD), Slash = i32(sdl.Scancode.SLASH), CapsLock = i32(sdl.Scancode.CAPSLOCK), F1 = i32(sdl.Scancode.F1), F2 = i32(sdl.Scancode.F2), F3 = i32(sdl.Scancode.F3), F4 = i32(sdl.Scancode.F4), F5 = i32(sdl.Scancode.F5), F6 = i32(sdl.Scancode.F6), F7 = i32(sdl.Scancode.F7), F8 = i32(sdl.Scancode.F8), F9 = i32(sdl.Scancode.F9), F10 = i32(sdl.Scancode.F10), F11 = i32(sdl.Scancode.F11), F12 = i32(sdl.Scancode.F12), PrintScreen = i32(sdl.Scancode.PRINTSCREEN), ScrollLock = i32(sdl.Scancode.SCROLLLOCK), Pause = i32(sdl.Scancode.PAUSE), Insert = i32(sdl.Scancode.INSERT), Home = i32(sdl.Scancode.HOME), PageUp = i32(sdl.Scancode.PAGEUP), Delete = i32(sdl.Scancode.DELETE), End = i32(sdl.Scancode.END), PageDown = i32(sdl.Scancode.PAGEDOWN), Right = i32(sdl.Scancode.RIGHT), Left = i32(sdl.Scancode.LEFT), Down = i32(sdl.Scancode.DOWN), Up = i32(sdl.Scancode.UP), NumLock = i32(sdl.Scancode.NUMLOCKCLEAR), KeypadDivide = i32(sdl.Scancode.KP_DIVIDE), KeypadMultiply = i32(sdl.Scancode.KP_MULTIPLY), KeypadMinus = i32(sdl.Scancode.KP_MINUS), KeypadPlus = i32(sdl.Scancode.KP_PLUS), KeypadEnter = i32(sdl.Scancode.KP_ENTER), Keypad1 = i32(sdl.Scancode.KP_1), Keypad2 = i32(sdl.Scancode.KP_2), Keypad3 = i32(sdl.Scancode.KP_3), Keypad4 = i32(sdl.Scancode.KP_4), Keypad5 = i32(sdl.Scancode.KP_5), Keypad6 = i32(sdl.Scancode.KP_6), Keypad7 = i32(sdl.Scancode.KP_7), Keypad8 = i32(sdl.Scancode.KP_8), Keypad9 = i32(sdl.Scancode.KP_9), Keypad0 = i32(sdl.Scancode.KP_0), KeypadPeriod = i32(sdl.Scancode.KP_PERIOD), LeftCtrl = i32(sdl.Scancode.LCTRL), LeftShift = i32(sdl.Scancode.LSHIFT), LeftAlt = i32(sdl.Scancode.LALT), LeftSuper = i32(sdl.Scancode.LGUI), RightCtrl = i32(sdl.Scancode.RCTRL), RightShift = i32(sdl.Scancode.RSHIFT), RightAlt = i32(sdl.Scancode.RALT), RightSuper = i32(sdl.Scancode.RGUI),}A keyboard key, by position (a US layout’s names). Values are SDL scancodes
enum. Source: input.odin:44
MouseButton
Section titled “MouseButton”MouseButton :: enum { Left, Middle, Right, // The back side button (SDL's X1) Back, // The forward side button (SDL's X2) Forward, // The wheel turned up (away from the player), for one frame WheelUp, WheelDown, WheelLeft, WheelRight,}A mouse button. The wheel’s four directions count as buttons pressed for the frame it turns
enum. Source: input.odin:81
GamepadButton
Section titled “GamepadButton”GamepadButton :: enum i32 { South = i32(sdl.GamepadButton.SOUTH), East = i32(sdl.GamepadButton.EAST), West = i32(sdl.GamepadButton.WEST), North = i32(sdl.GamepadButton.NORTH), Back = i32(sdl.GamepadButton.BACK), Guide = i32(sdl.GamepadButton.GUIDE), Start = i32(sdl.GamepadButton.START), LeftStick = i32(sdl.GamepadButton.LEFT_STICK), RightStick = i32(sdl.GamepadButton.RIGHT_STICK), LeftShoulder = i32(sdl.GamepadButton.LEFT_SHOULDER), RightShoulder = i32(sdl.GamepadButton.RIGHT_SHOULDER), DpadUp = i32(sdl.GamepadButton.DPAD_UP), DpadDown = i32(sdl.GamepadButton.DPAD_DOWN), DpadLeft = i32(sdl.GamepadButton.DPAD_LEFT), DpadRight = i32(sdl.GamepadButton.DPAD_RIGHT), Misc = i32(sdl.GamepadButton.MISC1), Touchpad = i32(sdl.GamepadButton.TOUCHPAD),}A gamepad button, by position (South is Xbox A, PlayStation Cross, Nintendo B). Values are SDL’s
enum. Source: input.odin:97
GamepadAxis
Section titled “GamepadAxis”GamepadAxis :: enum i32 { LeftX = i32(sdl.GamepadAxis.LEFTX), LeftY = i32(sdl.GamepadAxis.LEFTY), RightX = i32(sdl.GamepadAxis.RIGHTX), RightY = i32(sdl.GamepadAxis.RIGHTY), LeftTrigger = i32(sdl.GamepadAxis.LEFT_TRIGGER), RightTrigger = i32(sdl.GamepadAxis.RIGHT_TRIGGER),}A gamepad stick axis (-1 to 1; down and right are positive) or trigger (0 to 1). Values are SDL’s
enum. Source: input.odin:118
InputBinding
Section titled “InputBinding”InputBinding :: union { KeyBinding, MouseBinding, GamepadButtonBinding, GamepadAxisBinding,}What triggers an action
union. Source: input.odin:128
KeyBinding
Section titled “KeyBinding”KeyBinding :: struct { // The key key: Key,}A keyboard key triggers the action
struct. Source: input.odin:136
MouseBinding
Section titled “MouseBinding”MouseBinding :: struct { // The button button: MouseButton,}A mouse button (or a wheel direction) triggers the action
struct. Source: input.odin:142
GamepadButtonBinding
Section titled “GamepadButtonBinding”GamepadButtonBinding :: struct { // The button button: GamepadButton, // Which gamepad (0 the first connected); -1 any device: int,}A gamepad button triggers the action
struct. Source: input.odin:148
GamepadAxisBinding
Section titled “GamepadAxisBinding”GamepadAxisBinding :: struct { // The stick axis or trigger axis: GamepadAxis, // +1 (right, down, pressed) or -1 (left, up) direction: f32, // Which gamepad (0 the first connected); -1 any device: int,}A stick or trigger pushed one way: direction +1 (right, down, pressed) or -1 (left, up)
struct. Source: input.odin:156
InputActionData
Section titled “InputActionData”InputActionData :: struct { // The action's name, as scripts ask for it ("jump") name: string, // Sticks and triggers below this count as not pressed deadzone: f32, // What triggers it: any one of them bindings: [dynamic]InputBinding,}A named input and what triggers it: project.xml’s <action> (format version 8)
struct. Source: input.odin:169
InputState
Section titled “InputState”InputState :: struct { // Keys held, gone down this frame, and let go this frame keys, keysPressed, keysReleased: #sparse[Key]bool, // Mouse buttons held, gone down this frame, and let go this frame mouse, mousePressed, mouseReleased: [MouseButton]bool, // Where the mouse is, in game coordinates (the app converts window positions) mousePosition: [2]f32, // How far it moved this frame, in game coordinates mouseMotion: [2]f32, // This frame's wheel turn (y up positive, x right positive) wheel: [2]f32, // The connected gamepads, in the order they connected (their index is the device number) gamepads: [dynamic]GamepadState, // The actions and their state this frame (`Input_SetActions`, `Input_AddAction`) actions: [dynamic]ActionState, // Unknown action names already reported, so a typo warns once (owned keys) warned: map[string]bool, // Waiting for the next input to bind (input_rebind.odin) capture: InputCapture, // Fingers on the screen, and those lifted this frame (touch.odin) touches: [dynamic]Touch, // The screen has been touched (touch controls show) touched: bool, // The last mouse press or release came from a finger (SDL's touch mouse): touch controls // take the finger, not that mouse press mouseFromTouch: bool, // Touch controls always show (editors' previews) showTouchControls: bool, // The VirtualJoysticks and TouchButtons of the game's scenes (they add and remove themselves) touchControls: [dynamic]^TouchControl, // Counts updates (touch controls use the ones that updated last frame) frame: u64, // Local players: who plays with which device (players.odin) players: PlayersState,}The game’s input: what’s held, what changed this frame, and the actions (Game.input)
struct. Source: input.odin:198
InputCaptureState
Section titled “InputCaptureState”InputCaptureState :: enum u8 { // No capture Off, // Waiting for the next input Waiting, // Got it: Input_GetCapturedBinding hands it out once Done,}Where a capture is (InputState.capture)
enum. Source: input_rebind.odin:40
InputCapture
Section titled “InputCapture”InputCapture :: struct { // Where it is state: InputCaptureState, // The input captured, once `state` is .Done binding: InputBinding, // Gamepad bindings for any gamepad (device -1), or the one used anyDevice: bool, // Each gamepad's axes when the capture started: a stick resting off-center isn't a push baseline: [8][GamepadAxis]f32,}A capture of the next input (Input_StartCapture)
struct. Source: input_rebind.odin:50
Procedures
Section titled “Procedures”Input_SetActions
Section titled “Input_SetActions”Input_SetActions :: proc(game: ^Game, actions: []InputActionData)Sets the game’s actions (replacing any): Game_LoadProject does this with the project’s. Names,
bindings and the list are copied into the game’s memory; the bindings also become each action’s
defaults (Input_ResetBindings).
Inputs
- game: The game
- actions: The actions
procedure. Source: input.odin:243
Input_AddAction
Section titled “Input_AddAction”Input_AddAction :: proc(name: string, bindings: ..InputBinding, deadzone: f32 = DEFAULT_ACTION_DEADZONE, game: ^Game = nil)Adds an action from code, or more bindings to one that exists (its deadzone then stays). The
bindings also become part of its defaults (Input_ResetBindings).
Inputs
- name: The action’s name (copied)
- bindings: What triggers it
- deadzone: How far a stick or trigger must move to count (0 to 1), for a new action
- game: The game (nil: the one playing)
Example
e.Input_AddAction("dash", e.KeyBinding{.LeftShift}, e.GamepadButtonBinding{.East, -1})procedure. Source: input.odin:269
Input_HasAction
Section titled “Input_HasAction”Input_HasAction :: proc(name: string, game: ^Game = nil) -> boolTells whether the game has an action by that name (without warning when it doesn’t).
Inputs
- name: The action’s name
- game: The game (nil: the one playing)
Returns
- true if it exists
procedure. Source: input.odin:298
Input_IsActionPressed
Section titled “Input_IsActionPressed”Input_IsActionPressed :: proc(name: string, game: ^Game = nil) -> boolTells whether an action is held: any of its bindings is down (a stick past its deadzone). An unknown name logs a warning once and counts as not pressed.
Inputs
- name: The action’s name
- game: The game (nil: the one playing)
Returns
- true while it’s held
Example
if e.Input_IsActionPressed("fire") do log.info("firing")procedure. Source: input.odin:316
Input_IsActionJustPressed
Section titled “Input_IsActionJustPressed”Input_IsActionJustPressed :: proc(name: string, game: ^Game = nil) -> boolTells whether an action went down this frame. Not while an input is being captured for rebinding (input_rebind.odin).
Inputs
- name: The action’s name
- game: The game (nil: the one playing)
Returns
- true on the frame it was pressed
Example
if e.Input_IsActionJustPressed("jump") do log.info("jump")procedure. Source: input.odin:335
Input_IsActionJustReleased
Section titled “Input_IsActionJustReleased”Input_IsActionJustReleased :: proc(name: string, game: ^Game = nil) -> boolTells whether an action was let go this frame. Not while an input is being captured for rebinding (input_rebind.odin).
Inputs
- name: The action’s name
- game: The game (nil: the one playing)
Returns
- true on the frame it was released
procedure. Source: input.odin:351
Input_GetActionStrength
Section titled “Input_GetActionStrength”Input_GetActionStrength :: proc(name: string, game: ^Game = nil) -> f32How hard an action is pressed: the strongest of its bindings.
Inputs
- name: The action’s name
- game: The game (nil: the one playing)
Returns
- 0 to 1: 1 for keys and buttons, a stick’s or trigger’s travel past the deadzone (rescaled so it starts at 0 there); 0 for an unknown action
procedure. Source: input.odin:366
Input_GetAxis
Section titled “Input_GetAxis”Input_GetAxis :: proc(negative, positive: string, game: ^Game = nil) -> f32One axis from two actions: positive’s strength minus negative’s.
Inputs
- negative: The action for -1 (left, up)
- positive: The action for +1 (right, down)
- game: The game (nil: the one playing)
Returns
- -1 to 1
Example
steer := e.Input_GetAxis("turn_left", "turn_right")procedure. Source: input.odin:385
Input_GetVector
Section titled “Input_GetVector”Input_GetVector :: proc(negativeX, positiveX, negativeY, positiveY: string, game: ^Game = nil) -> [2]f32A direction from four actions (x right, y down), at most 1 long: diagonals aren’t faster.
Inputs
- negativeX: The action for left
- positiveX: The action for right
- negativeY: The action for up
- positiveY: The action for down
- game: The game (nil: the one playing)
Returns
- The direction, each axis -1 to 1, length at most 1
Example
// Given: speed: f32velocity := e.Input_GetVector("move_left", "move_right", "move_up", "move_down") * speednode.position += velocity * f32(dt)procedure. Source: input.odin:407
Input_IsKeyPressed
Section titled “Input_IsKeyPressed”Input_IsKeyPressed :: proc(key: Key, game: ^Game = nil) -> boolTells whether a key is held.
Inputs
- key: The key
- game: The game (nil: the one playing)
Returns
- true while it’s down
Example
if e.Input_IsKeyPressed(.LeftShift) do log.info("running")procedure. Source: input.odin:426
Input_IsKeyJustPressed
Section titled “Input_IsKeyJustPressed”Input_IsKeyJustPressed :: proc(key: Key, game: ^Game = nil) -> boolTells whether a key went down this frame (its repeats don’t count).
Inputs
- key: The key
- game: The game (nil: the one playing)
Returns
- true on the frame it was pressed
Example
if e.Input_IsKeyJustPressed(.Escape) do log.info("pause")procedure. Source: input.odin:444
Input_IsKeyJustReleased
Section titled “Input_IsKeyJustReleased”Input_IsKeyJustReleased :: proc(key: Key, game: ^Game = nil) -> boolTells whether a key was let go this frame (or the window lost focus while it was held).
Inputs
- key: The key
- game: The game (nil: the one playing)
Returns
- true on the frame it was released
procedure. Source: input.odin:459
Input_IsMouseButtonPressed
Section titled “Input_IsMouseButtonPressed”Input_IsMouseButtonPressed :: proc(button: MouseButton, game: ^Game = nil) -> boolTells whether a mouse button is held. A wheel direction counts as held on the frame the wheel turns.
Inputs
- button: The button
- game: The game (nil: the one playing)
Returns
- true while it’s down
procedure. Source: input.odin:474
Input_IsMouseButtonJustPressed
Section titled “Input_IsMouseButtonJustPressed”Input_IsMouseButtonJustPressed :: proc(button: MouseButton, game: ^Game = nil) -> boolTells whether a mouse button went down this frame (a wheel direction: the wheel turned this frame).
Inputs
- button: The button
- game: The game (nil: the one playing)
Returns
- true on the frame it was pressed
Example
if e.Input_IsMouseButtonJustPressed(.Left) do log.infof("click at %v", e.Input_GetMousePosition())procedure. Source: input.odin:492
Input_IsMouseButtonJustReleased
Section titled “Input_IsMouseButtonJustReleased”Input_IsMouseButtonJustReleased :: proc(button: MouseButton, game: ^Game = nil) -> boolTells whether a mouse button was let go this frame (a wheel direction: the frame after it turned).
Inputs
- button: The button
- game: The game (nil: the one playing)
Returns
- true on the frame it was released
procedure. Source: input.odin:507
Input_GetMousePosition
Section titled “Input_GetMousePosition”Input_GetMousePosition :: proc(game: ^Game = nil) -> [2]f32Where the mouse is, in game coordinates (Scene_ScreenToWorld gives the world point under it).
Inputs
- game: The game (nil: the one playing)
Returns
- The position in game coordinates (zero without a game)
procedure. Source: input.odin:521
Input_GetMouseMotion
Section titled “Input_GetMouseMotion”Input_GetMouseMotion :: proc(game: ^Game = nil) -> [2]f32How far the mouse moved this frame.
Inputs
- game: The game (nil: the one playing)
Returns
- The movement in game coordinates
procedure. Source: input.odin:535
Input_GetMouseWheel
Section titled “Input_GetMouseWheel”Input_GetMouseWheel :: proc(game: ^Game = nil) -> [2]f32How far the wheel turned this frame.
Inputs
- game: The game (nil: the one playing)
Returns
- The turn: y positive up, x positive right (SDL’s wheel units)
procedure. Source: input.odin:549
Input_GamepadCount
Section titled “Input_GamepadCount”Input_GamepadCount :: proc(game: ^Game = nil) -> intHow many gamepads are connected (devices 0 to the count minus 1).
Inputs
- game: The game (nil: the one playing)
Returns
- The count
procedure. Source: input.odin:563
Input_IsGamepadButtonPressed
Section titled “Input_IsGamepadButtonPressed”Input_IsGamepadButtonPressed :: proc(button: GamepadButton, device := -1, game: ^Game = nil) -> boolTells whether a gamepad button is held.
Inputs
- button: The button
- device: Which gamepad (0 the first connected); -1 any
- game: The game (nil: the one playing)
Returns
- true while it’s down (false for a device that isn’t connected)
procedure. Source: input.odin:579
Input_IsGamepadButtonJustPressed
Section titled “Input_IsGamepadButtonJustPressed”Input_IsGamepadButtonJustPressed :: proc(button: GamepadButton, device := -1, game: ^Game = nil) -> boolTells whether a gamepad button went down this frame.
Inputs
- button: The button
- device: Which gamepad (0 the first connected); -1 any
- game: The game (nil: the one playing)
Returns
- true on the frame it was pressed
Example
if e.Input_IsGamepadButtonJustPressed(.Start) do log.info("pause")procedure. Source: input.odin:598
Input_IsGamepadButtonJustReleased
Section titled “Input_IsGamepadButtonJustReleased”Input_IsGamepadButtonJustReleased :: proc(button: GamepadButton, device := -1, game: ^Game = nil) -> boolTells whether a gamepad button was let go this frame.
Inputs
- button: The button
- device: Which gamepad (0 the first connected); -1 any
- game: The game (nil: the one playing)
Returns
- true on the frame it was released
procedure. Source: input.odin:614
Input_GetGamepadAxis
Section titled “Input_GetGamepadAxis”Input_GetGamepadAxis :: proc(axis: GamepadAxis, device := 0, game: ^Game = nil) -> f32A gamepad’s stick axis or trigger, raw (no deadzone).
Inputs
- axis: The stick axis or trigger
- device: Which gamepad (0 the first connected, the default); -1 the one pushed furthest
- game: The game (nil: the one playing)
Returns
- -1 to 1 for a stick (down and right positive), 0 to 1 for a trigger; 0 for a device that isn’t connected
Example
aim := [2]f32{e.Input_GetGamepadAxis(.RightX), e.Input_GetGamepadAxis(.RightY)}_ = aimprocedure. Source: input.odin:634
Input_Update
Section titled “Input_Update”Input_Update :: proc(input: ^InputState, events: []sdl.Event)Starts a frame: forgets last frame’s presses and releases, applies this frame’s events, and works out every action. Game_Update calls it; call it yourself only for input outside a game loop.
Inputs
- input: The input state (usually
&game.input) - events: This frame’s SDL events
procedure. Source: input.odin:648
FormatInputBinding
Section titled “FormatInputBinding”FormatInputBinding :: proc(binding: InputBinding) -> (element: string, attributes: []ScriptPropData)A binding as project files store it: its element and attributes, e.g. key key="Space",
axis axis="LeftX" direction="-1". ParseInputBinding reads it back.
Inputs
- binding: The binding
Returns
- element: The element name (“key”, “mouse”, “gamepad”, “axis”)
- attributes: Its attributes as name / value pairs (temp allocated); device is left out when it is -1
procedure. Source: input.odin:786
ParseInputBinding
Section titled “ParseInputBinding”ParseInputBinding :: proc(element: string, get: proc(user: rawptr, key: string) -> (string, bool), user: rawptr) -> (InputBinding, bool)Reads a binding element (FormatInputBinding’s). A missing device is -1 (any gamepad), a missing
direction +1.
Inputs
- element: The element name (“key”, “mouse”, “gamepad”, “axis”)
- get: Returns an attribute’s value by name, and whether it is there
- user: Passed to
get(e.g. the XML element being read)
Returns
- The binding, and false for an unknown element or value
procedure. Source: input.odin:822
InputBinding_Describe
Section titled “InputBinding_Describe”InputBinding_Describe :: proc(binding: InputBinding) -> stringA binding as a person reads it, for a controls menu: “Space”, “Mouse Left”, “Gamepad South”, “Gamepad LeftX −”, “Gamepad 1 South” (one gamepad, numbered from 1).
Inputs
- binding: The binding
Returns
- The text (temp allocated, or a constant)
procedure. Source: input.odin:863
Input_StartCapture
Section titled “Input_StartCapture”Input_StartCapture :: proc(anyDevice := true, game: ^Game = nil)Starts waiting for the next input to bind (see above). Replaces a capture already going.
Inputs
- anyDevice: A gamepad binding works on any gamepad (else only on the one pressed)
- game: The game (nil: the one playing)
Example
e.Input_StartCapture()procedure. Source: input_rebind.odin:71
Input_CancelCapture
Section titled “Input_CancelCapture”Input_CancelCapture :: proc(game: ^Game = nil)Stops waiting for an input to bind (a captured one not taken yet is dropped).
Inputs
- game: The game (nil: the one playing)
procedure. Source: input_rebind.odin:84
Input_IsCapturing
Section titled “Input_IsCapturing”Input_IsCapturing :: proc(game: ^Game = nil) -> boolTells whether a capture is waiting for its input.
Inputs
- game: The game (nil: the one playing)
Returns
- true from
Input_StartCaptureuntil an input comes or the capture is cancelled
procedure. Source: input_rebind.odin:97
Input_GetCapturedBinding
Section titled “Input_GetCapturedBinding”Input_GetCapturedBinding :: proc(game: ^Game = nil) -> (InputBinding, bool)The input a capture got, once: from the frame it came (Game_Update’s Input_Update), then the capture is over.
Inputs
- game: The game (nil: the one playing)
Returns
- The binding, and whether there is one (false while waiting or with no capture)
Example
if binding, ok := e.Input_GetCapturedBinding(); ok { e.Input_SetBindings("jump", {binding})}procedure. Source: input_rebind.odin:117
Input_GetBindings
Section titled “Input_GetBindings”Input_GetBindings :: proc(name: string, game: ^Game = nil) -> []InputBindingAn action’s bindings. An unknown name logs a warning once.
Inputs
- name: The action’s name
- game: The game (nil: the one playing)
Returns
- The game’s list (don’t keep it past a change), nil when there’s no such action
procedure. Source: input_rebind.odin:135
Input_SetBindings
Section titled “Input_SetBindings”Input_SetBindings :: proc(name: string, bindings: []InputBinding, game: ^Game = nil) -> boolReplaces an action’s bindings (copied). An unknown name logs a warning once.
Inputs
- name: The action’s name
- bindings: Its new bindings (an empty slice unbinds it)
- game: The game (nil: the one playing)
Returns
- false when there’s no such action
Example
e.Input_SetBindings("jump", {e.KeyBinding{.Space}, e.GamepadButtonBinding{.South, -1}})procedure. Source: input_rebind.odin:154
Input_ActionsUsing
Section titled “Input_ActionsUsing”Input_ActionsUsing :: proc(binding: InputBinding, game: ^Game = nil) -> []stringThe actions a binding triggers (to warn about, or take it off, before binding it to another). Bindings match exactly: a gamepad binding for device -1 doesn’t match one for device 0.
Inputs
- binding: The binding
- game: The game (nil: the one playing)
Returns
- Their names (the game’s strings; the list is temp allocated)
procedure. Source: input_rebind.odin:173
Input_ResetBindings
Section titled “Input_ResetBindings”Input_ResetBindings :: proc(game: ^Game = nil)Puts every action’s bindings back as the project (or Input_AddAction) made them. Doesn’t save:
call Input_SaveBindings to keep it.
Inputs
- game: The game (nil: the one playing)
procedure. Source: input_rebind.odin:193
Input_FormatBindings
Section titled “Input_FormatBindings”Input_FormatBindings :: proc(game: ^Game = nil, allocator := context.allocator) -> stringEvery action’s bindings as text, one line per action (what Input_SaveBindings writes):
jump = key key=Space | gamepad button=Southmove_left = key key=A | axis axis=LeftX direction=-1Inputs
- game: The game (nil: the one playing)
- allocator: Allocates the text
Returns
- The text, allocated with
allocator(“” without a game)
procedure. Source: input_rebind.odin:215
Input_ParseBindings
Section titled “Input_ParseBindings”Input_ParseBindings :: proc(text: string, game: ^Game = nil) -> intSets actions’ bindings from Input_FormatBindings text. Actions the text doesn’t list keep
theirs; lines for actions the game doesn’t have, and bindings that can’t be read, are skipped.
Inputs
- text: The text
- game: The game (nil: the one playing)
Returns
- How many actions it set
procedure. Source: input_rebind.odin:249
Input_SaveBindings
Section titled “Input_SaveBindings”Input_SaveBindings :: proc(slot := INPUT_BINDINGS_SLOT, game: ^Game = nil) -> boolKeeps every action’s bindings with the game’s saves (save.odin’s storage: a file in the player’s data folder, the browser’s localStorage).
Inputs
- slot: The save slot name
- game: The game (nil: the one playing)
Returns
- Whether it was written (failures are logged)
Example
if !e.Input_SaveBindings() do log.warn("bindings not saved")procedure. Source: input_rebind.odin:296
Input_LoadBindings
Section titled “Input_LoadBindings”Input_LoadBindings :: proc(slot := INPUT_BINDINGS_SLOT, game: ^Game = nil) -> boolLoads bindings Input_SaveBindings kept (call it once the project is loaded), as
Input_ParseBindings.
Inputs
- slot: The save slot name
- game: The game (nil: the one playing)
Returns
- false when there’s none
Example
e.Input_LoadBindings()procedure. Source: input_rebind.odin:321
Input_Rumble
Section titled “Input_Rumble”Input_Rumble :: proc(low, high: f32, seconds: f32, device := -1, game: ^Game = nil) -> boolRumbles gamepads (those that can; others ignore it).
Inputs
- low: The low-frequency motor’s strength, 0 to 1
- high: The high-frequency motor’s strength, 0 to 1
- seconds: How long (a new rumble replaces one still going)
- device: Which gamepad (0 the first connected); -1 all of them
- game: The game (nil: the one playing)
Returns
- Whether any gamepad took it
Example
// A hit: a short, strong thumpe.Input_Rumble(0.8, 0.4, 0.15)procedure. Source: input_rebind.odin:347
Constants and variables
Section titled “Constants and variables”DEFAULT_ACTION_DEADZONE
Section titled “DEFAULT_ACTION_DEADZONE”DEFAULT_ACTION_DEADZONE :: 0.5The deadzone actions get unless they set one: how far a stick must move to count
constant. Source: input.odin:166
INPUT_BINDINGS_SLOT
Section titled “INPUT_BINDINGS_SLOT”INPUT_BINDINGS_SLOT :: "bindings"The save slot bindings are kept in (Input_SaveBindings)
constant. Source: input_rebind.odin:34
INPUT_CAPTURE_AXIS
Section titled “INPUT_CAPTURE_AXIS”INPUT_CAPTURE_AXIS :: 0.5How far a stick or trigger must move to be captured
constant. Source: input_rebind.odin:37
