Skip to content

create.input

The input devices Context holds: Keyboard, Mouse and Gamepad, and the Key, MouseButton and GamepadButton they are read with.

Keyboard

struct Keyboard

The keyboard's state for one frame, read as context.keyboard.

Every device answers the same three questions about its buttons: down is held right now, true every frame it stays held; pressed and released are the edges, true only in the frame the key went down or came up. Unlike Processing, where keyPressed means held, pressed is only ever the edge. Keys add typed: pressed, or auto-repeated while held — what an editing key like Backspace acts on.

text is what those keys wrote, as characters rather than keys: shift, the keyboard layout and any IME already applied. A text field appends text and handles Backspace and the arrows through typed; an EditableText does both.

It is the loop's own Keyboard, not a copy: held keys persist in it from frame to frame, and only the edges and text clear. So read it and don't write it.

Implements Copyable, Deinitable, Movable, Writable.

Fields

  • key: Key: The most recent key pressed (Key.NONE before any). Kept until the next press; auto-repeat of a held key does not count as one.
  • text: String: The text typed this frame, UTF-8: empty on most frames, several characters when typing outpaces the frame rate.

Constructors

@staticmethod
def __init__(out self)

down

def down(self, key: Key) -> Bool

Whether key is held right now: true every frame it stays down.

pressed

def pressed(self, key: Key) -> Bool

Whether key went down this frame: true once per press.

released

def released(self, key: Key) -> Bool

Whether key came up this frame: true once per release.

typed

def typed(self, key: Key) -> Bool

Whether key went down or auto-repeated this frame: true once per press, then at the system's repeat rate while held.

Key

struct Key

A key by its position on the keyboard, what the Keyboard queries take: context.keyboard.down(Key.UP).

Positional. Each constant names a key by where it sits on a US layout, whatever the layout prints on it: Key.W is the key above S, which an AZERTY keyboard labels Z, so WASD movement lands under the same fingers on every keyboard. Characters are what the layout makes of those keys, and come from context.keyboard.text, never from a Key. So read keys for controls, and text for what the user typed.

from_name maps a key's name ("up", "page_up", "a") to it, for a binding read from a file; a misspelled constant fails to compile, where a name could only fail to match.

A wrapped SDL scancode rather than a bare Int, so a stray number cannot be passed where a key is expected. Key(scancode) names any key SDL can send, the ones without a constant included.

NONE is no key (SDL's unknown scancode), what Keyboard.key reads before any press; it is never down.

CTRL, SHIFT, ALT and SUPER are either side of a modifier: down while the left or the right one is. They are queries only, never a key SDL sends, so Keyboard.key is always the side that was pressed.

Implements Copyable, Deinitable, Equatable, ImplicitlyCopyable, Movable, Writable.

Constants

  • NONE = Key(Int(0))
  • LEFT_CTRL = Key(Int(224))
  • RIGHT_CTRL = Key(Int(228))
  • LEFT_SHIFT = Key(Int(225))
  • RIGHT_SHIFT = Key(Int(229))
  • LEFT_ALT = Key(Int(226))
  • RIGHT_ALT = Key(Int(230))
  • LEFT_SUPER = Key(Int(227))
  • RIGHT_SUPER = Key(Int(231))
  • CTRL = Key(Int(-1))
  • SHIFT = Key(Int(-2))
  • ALT = Key(Int(-3))
  • SUPER = Key(Int(-4))
  • UP = Key(Int(82))
  • DOWN = Key(Int(81))
  • LEFT = Key(Int(80))
  • RIGHT = Key(Int(79))
  • INSERT = Key(Int(73))
  • HOME = Key(Int(74))
  • PAGE_UP = Key(Int(75))
  • PAGE_DOWN = Key(Int(78))
  • END = Key(Int(77))
  • ENTER = Key(Int(40))
  • ESCAPE = Key(Int(41))
  • BACKSPACE = Key(Int(42))
  • TAB = Key(Int(43))
  • SPACE = Key(Int(44))
  • DELETE = Key(Int(76))
  • CAPS_LOCK = Key(Int(57))
  • F1 = Key(Int(58))
  • F2 = Key(Int(59))
  • F3 = Key(Int(60))
  • F4 = Key(Int(61))
  • F5 = Key(Int(62))
  • F6 = Key(Int(63))
  • F7 = Key(Int(64))
  • F8 = Key(Int(65))
  • F9 = Key(Int(66))
  • F10 = Key(Int(67))
  • F11 = Key(Int(68))
  • F12 = Key(Int(69))
  • A = Key(Int(4))
  • B = Key(Int(5))
  • C = Key(Int(6))
  • D = Key(Int(7))
  • E = Key(Int(8))
  • F = Key(Int(9))
  • G = Key(Int(10))
  • H = Key(Int(11))
  • I = Key(Int(12))
  • J = Key(Int(13))
  • K = Key(Int(14))
  • L = Key(Int(15))
  • M = Key(Int(16))
  • N = Key(Int(17))
  • O = Key(Int(18))
  • P = Key(Int(19))
  • Q = Key(Int(20))
  • R = Key(Int(21))
  • S = Key(Int(22))
  • T = Key(Int(23))
  • U = Key(Int(24))
  • V = Key(Int(25))
  • W = Key(Int(26))
  • X = Key(Int(27))
  • Y = Key(Int(28))
  • Z = Key(Int(29))
  • ONE = Key(Int(30))
  • TWO = Key(Int(31))
  • THREE = Key(Int(32))
  • FOUR = Key(Int(33))
  • FIVE = Key(Int(34))
  • SIX = Key(Int(35))
  • SEVEN = Key(Int(36))
  • EIGHT = Key(Int(37))
  • NINE = Key(Int(38))
  • ZERO = Key(Int(39))
  • MINUS = Key(Int(45))
  • EQUALS = Key(Int(46))
  • LEFT_BRACKET = Key(Int(47))
  • RIGHT_BRACKET = Key(Int(48))
  • BACKSLASH = Key(Int(49))
  • SEMICOLON = Key(Int(51))
  • APOSTROPHE = Key(Int(52))
  • GRAVE = Key(Int(53))
  • COMMA = Key(Int(54))
  • PERIOD = Key(Int(55))
  • SLASH = Key(Int(56))

Fields

  • value: Int

Constructors

@staticmethod
def __init__(out self, value: Int)

__eq__

def __eq__(self, other: Self) -> Bool

__ne__

def __ne__(self, other: Self) -> Bool

from_name

@staticmethod
def from_name(name: String) -> Optional[Self]

The key whose constant is name, case folded: "up", "page_up", "f1", "left_ctrl", "a", "zero", "slash". A single character is the key that types it unshifted on a US layout, so "/", "7" and "A" work too. None for an unknown name.

Mouse

struct Mouse

The mouse's state for one frame, read as context.mouse.

Buttons follow the vocabulary every device shares: down is held right now, pressed/released are the edges, true only in the frame the button went down or came up. Each takes MouseButton.LEFT unless told otherwise, so context.mouse.pressed() is a click.

position is in screen coordinates — origin at the centre, y up, so negative left of and below it — and camera-independent, since the loop reads a frame's events before the Canvas (and any Camera it sets) exists. Convert with camera.to_world, or canvas.to_local for the frame a shape is drawn in. position and press_position are Point2Ds because they are locations; wheel is a Vector2D because a scroll is a displacement.

It is the loop's own Mouse, not a copy: held buttons persist in it from frame to frame, and only the edges and the wheel clear. So read it and don't write it.

Implements Copyable, Deinitable, Movable, Writable.

Fields

  • position: Point2D: Where the pointer is, in screen space.
  • button: MouseButton: The most recent button pressed (MouseButton.NONE before any). Kept until the next press.
  • movement: Vector2D: How far the pointer moved this frame, in screen units, y up: zero on a frame it stayed still. It keeps counting where position stops — at the screen's edge, and while context.lock_mouse(True) holds the pointer — so it is what a first-person camera or an endless drag turns by.
  • wheel: Vector2D: This frame's scroll, zero on a frame without any.
  • press_position: Point2D: Where the most recent press happened, in screen space. Captured from the press itself, so a move later in the same frame doesn't overwrite where a click started, and kept until the next press, so a drag is position - press_position for as long as the button is down.

Constructors

@staticmethod
def __init__(out self)

down

def down(self, button: MouseButton = MouseButton.LEFT) -> Bool

Whether button is held right now.

pressed

def pressed(self, button: MouseButton = MouseButton.LEFT) -> Bool

Whether button went down this frame: true once per click. press_position is where it happened.

released

def released(self, button: MouseButton = MouseButton.LEFT) -> Bool

Whether button came up this frame: true once.

MouseButton

struct MouseButton

A mouse button, for Mouse.down/pressed/released.

Matches SDL's own button numbering, not named after it: BACK/FORWARD are the side thumb buttons (SDL's X1/X2) — named for what a mouse driver or browser calls them, not SDL's internal label, since nobody looks at their mouse and thinks "that's my X1 button."

A wrapped button number rather than a bare Int, like Key, so a stray number cannot be passed where a button is expected — the numbering is not what anyone guesses (RIGHT is 3, not 2). MouseButton(n) names a button past FORWARD on a mouse that has one.

NONE is no button, what Mouse.button reads before any press; it is never down.

Implements Copyable, Deinitable, Equatable, ImplicitlyCopyable, Movable, Writable.

Constants

  • NONE = MouseButton(Int(0))
  • LEFT = MouseButton(Int(1))
  • MIDDLE = MouseButton(Int(2))
  • RIGHT = MouseButton(Int(3))
  • BACK = MouseButton(Int(4))
  • FORWARD = MouseButton(Int(5))

Fields

  • value: Int

Constructors

@staticmethod
def __init__(out self, value: Int)

__eq__

def __eq__(self, other: Self) -> Bool

__ne__

def __ne__(self, other: Self) -> Bool

from_name

@staticmethod
def from_name(name: String) -> Optional[Self]

The button whose constant is name, case folded: "left", "right", "back". None for an unknown name — for a binding read from a file, where a misspelled constant would have failed to compile.

Gamepad

struct Gamepad

One gamepad's state for one frame, read as context.gamepad(player).

Buttons follow the vocabulary every device shares: down is held right now, pressed/released are the edges, true only in the frame the button went down or came up. Name buttons through GamepadButton.

Sticks are Vector2Ds in screen orientation — y up, like every other direction in the library — inside the unit circle, so position += pad.left_stick * speed * context.time.delta moves at speed at full tilt and never faster on a diagonal. Each has a radial dead zone of STICK_DEAD_ZONE, rescaled so the stick still eases up from zero past it: a resting stick reads exactly Vector2D.ZERO rather than drifting. Triggers are 0 (released) to 1 (pulled all the way), and also buttons, GamepadButton.LEFT_TRIGGER/RIGHT_TRIGGER, so "fire on pull" is pad.pressed(GamepadButton.RIGHT_TRIGGER): down from TRIGGER_PRESS and up again below TRIGGER_RELEASE, so a trigger held near halfway doesn't flicker between the two.

A slot that holds no gamepad reads all zero and connected False, so a program can read player two's pad before one is plugged in. connected_this_frame and disconnected_this_frame are the edges of connected, true only in the frame the pad arrived or left — the frame to show "Player 2 joined" or to pause. In the frame a pad leaves, its slot still has its name, so the message can say which.

Implements Copyable, Deinitable, ImplicitlyCopyable, Movable, Writable.

Constants

  • STICK_DEAD_ZONE = 0.20000000000000001: How far a stick moves before it reads anything, as a fraction of full tilt. A resting stick sits up to about a quarter of the way off centre on a worn pad; 0.2 hides that on most without making small moves sluggish.
  • TRIGGER_PRESS = 0.5: How far a trigger is pulled before it reads as its button down.
  • TRIGGER_RELEASE = 0.40000000000000002: How far a trigger falls back before its button reads up again: below TRIGGER_PRESS, so a pull resting near the line stays one press.

Fields

  • connected: Bool
  • connected_this_frame: Bool
  • disconnected_this_frame: Bool
  • name: String
  • left_stick: Vector2D
  • right_stick: Vector2D
  • left_trigger: Float64
  • right_trigger: Float64
  • button: GamepadButton

Constructors

@staticmethod
def __init__(out self)

down

def down(self, button: GamepadButton) -> Bool

Whether button is held right now.

pressed

def pressed(self, button: GamepadButton) -> Bool

Whether button went down this frame: true once per press.

released

def released(self, button: GamepadButton) -> Bool

Whether button came up this frame: true once per release.

GamepadButton

struct GamepadButton

A gamepad button, for Gamepad.down/pressed/released.

Matches SDL's own button numbering. The face buttons are named by position, not label, because the labels disagree: SOUTH is Xbox A, PlayStation Cross and Nintendo B alike — the button a thumb rests on, so the one to confirm with. BACK/START are the two small centre buttons (View/Menu, Share/Options, -/+), GUIDE the logo button between them.

A wrapped button number rather than a bare Int, like Key, so a stray number cannot be passed where a button is expected.

NONE is no button, what Gamepad.button reads before any press (SDL's invalid button, since SOUTH is 0); it is never down.

Implements Copyable, Deinitable, Equatable, ImplicitlyCopyable, Movable, Writable.

Constants

  • NONE = GamepadButton(Int(-1))
  • SOUTH = GamepadButton(Int(0))
  • EAST = GamepadButton(Int(1))
  • WEST = GamepadButton(Int(2))
  • NORTH = GamepadButton(Int(3))
  • BACK = GamepadButton(Int(4))
  • GUIDE = GamepadButton(Int(5))
  • START = GamepadButton(Int(6))
  • LEFT_STICK = GamepadButton(Int(7)): Clicking the left stick in.
  • RIGHT_STICK = GamepadButton(Int(8))
  • LEFT_SHOULDER = GamepadButton(Int(9))
  • RIGHT_SHOULDER = GamepadButton(Int(10))
  • DPAD_UP = GamepadButton(Int(11))
  • DPAD_DOWN = GamepadButton(Int(12))
  • DPAD_LEFT = GamepadButton(Int(13))
  • DPAD_RIGHT = GamepadButton(Int(14))
  • MISC_1 = GamepadButton(Int(15)): The extra centre button: Xbox Share, PlayStation microphone, Switch capture.
  • RIGHT_PADDLE_1 = GamepadButton(Int(16))
  • LEFT_PADDLE_1 = GamepadButton(Int(17))
  • RIGHT_PADDLE_2 = GamepadButton(Int(18))
  • LEFT_PADDLE_2 = GamepadButton(Int(19))
  • TOUCHPAD = GamepadButton(Int(20)): Pressing the PlayStation touchpad.
  • MISC_2 = GamepadButton(Int(21))
  • MISC_3 = GamepadButton(Int(22))
  • MISC_4 = GamepadButton(Int(23))
  • MISC_5 = GamepadButton(Int(24))
  • MISC_6 = GamepadButton(Int(25))
  • LEFT_TRIGGER = GamepadButton(Int(26)): The left trigger pulled past halfway, read as a button: not one SDL sends, but worked out from Gamepad.left_trigger so a pull has edges.
  • RIGHT_TRIGGER = GamepadButton(Int(27)): The right trigger pulled past halfway, like LEFT_TRIGGER.

Fields

  • value: Int

Constructors

@staticmethod
def __init__(out self, value: Int)

__eq__

def __eq__(self, other: Self) -> Bool

__ne__

def __ne__(self, other: Self) -> Bool

from_name

@staticmethod
def from_name(name: String) -> Optional[Self]

The button whose constant is name, case folded: "south", "start", "right_trigger". None for an unknown name — for a binding read from a file, where a misspelled constant would have failed to compile.