Log inGet started
World

The Eighth Ketyl

Branchmain
Branchesmain
Commite99ff0a216

README.md

Focus

Menu focus navigation for THE EIGHTH KETYL. A controller has no pointer, so every menu in this game carries an ordered ring of focusable ids and exactly one of them is lit; this module is what walks that ring.

Why it exists. A game published to a television has to be finishable with a thumbstick alone, and a game published to a phone has to answer a finger on the same rows. The four families reach one model here — the stick and the d-pad step the focus, confirm acts on whatever is lit, a mouse crossing a row moves the focus onto it, and a finger tapping a row does both — so nothing on screen ever disagrees about what is selected.

The repeat is the part with teeth. A held stick has to walk the list rather than sprint it, and a flick has to be one step. The delay is measured in seconds AND in frames: on a machine running long frames a single flick can arrive as one onInput carrying half a second of dt, and a delay measured only in time turns that flick into two steps down the menu.

What it provides

  • Focus.open(list, prefer) — open a menu: the ids in the order the stick walks them, and which one starts lit.
  • Focus.close() / Focus.release() — close it; let go of a held direction.
  • Focus.id() / Focus.isFocused(id) / Focus.items() — read the focus.
  • Focus.axis(v, dt) — feed the navigate axis; handles the press edge and the held repeat, and wraps at both ends so a pad never dead-ends.
  • Focus.step(delta) — move by whole items.
  • Focus.point(id) — put the focus on a named item: what a mouse crossing it, or a finger tapping it, does.
  • Focus.generation() — a number that changes each time a menu opens, for a screen that animates its entrance.

Who consumes it

The Screens component, which feeds it the console.inputMap controls, and ui.Menus, which asks it which row to draw lit. It holds no widgets and reads no input itself.