"""The engine's own entries: the actions every tree has before a game declares anything.
These are the eight UI navigation actions. They sit at the bottom of every
tree's map, beneath the project's settings and every node's context, so a
project that lists none still navigates, a game redefines one by declaring the
same name on a context, and a player rebinds one with ``InputMap.rebind`` like
any other action. A clean branch, ``hides=InputContext.ALL``, takes every name
the game declared and gives these back as the engine declared them, because a
menu that could hide navigation could not be left.
**A controller drives all of it.** ``ui_accept`` is also the bottom face
button, ``ui_cancel`` the right one, the two traversal actions are the
shoulders, and the four directions are the D-pad and the left stick.
The four directions have **no keyboard default**. Binding them to the arrow
keys would take those keys away from every game that steers with them the
moment a control holds focus; a game that wants arrow navigation declares it,
``{"ui_up": [Key.UP], ...}``.
The engine's Tab is exact (``exact=True``), so it is not Shift+Tab, which is
``ui_focus_prev``; Enter and Escape follow the ordinary rule and fire under
any modifier.
"""
from __future__ import annotations
from .contexts import InputContext
from .controls import Controller, DeviceAxis, Key
from .events import InputBinding
__all__ = [
"ENGINE_CONTEXT",
"UI_ACCEPT",
"UI_ACTIONS",
"UI_CANCEL",
"UI_DOWN",
"UI_FOCUS_NEXT",
"UI_FOCUS_PREV",
"UI_LEFT",
"UI_RIGHT",
"UI_UP",
]
UI_FOCUS_NEXT = "ui_focus_next"
UI_FOCUS_PREV = "ui_focus_prev"
UI_ACCEPT = "ui_accept"
UI_CANCEL = "ui_cancel"
UI_UP = "ui_up"
UI_DOWN = "ui_down"
UI_LEFT = "ui_left"
UI_RIGHT = "ui_right"
def _stick(half: DeviceAxis) -> InputBinding:
"""Half a stick axis, with a deadzone wide enough that a resting stick is still."""
return InputBinding(half, deadzone=0.5)
#: The engine's entries, as one context at the bottom of every tree's map.
ENGINE_CONTEXT = InputContext(
{
UI_FOCUS_NEXT: [InputBinding(Key.TAB, exact=True), Controller.RIGHT_BUMPER],
UI_FOCUS_PREV: [Key.SHIFT + Key.TAB, Controller.LEFT_BUMPER],
UI_ACCEPT: [Key.ENTER, Controller.A],
UI_CANCEL: [Key.ESCAPE, Controller.B],
UI_UP: [Controller.DPAD_UP, _stick(Controller.LEFT_STICK.up)],
UI_DOWN: [Controller.DPAD_DOWN, _stick(Controller.LEFT_STICK.down)],
UI_LEFT: [Controller.DPAD_LEFT, _stick(Controller.LEFT_STICK.left)],
UI_RIGHT: [Controller.DPAD_RIGHT, _stick(Controller.LEFT_STICK.right)],
},
name="engine",
)
#: Every name the engine declares, in declaration order.
UI_ACTIONS: tuple[str, ...] = tuple(ENGINE_CONTEXT._actions)