Add claude docs
This commit is contained in:
@@ -0,0 +1,130 @@
|
||||
# Input System
|
||||
|
||||
Source: `src/dusk/input/`, platform layers in `src/dusk<platform>/input/`
|
||||
|
||||
## Architecture
|
||||
|
||||
The input system has two layers:
|
||||
|
||||
1. **Action layer** (`inputaction_t`) -- named gameplay inputs, e.g.
|
||||
UP, DOWN, ACCEPT, CANCEL. This is what game code reads.
|
||||
2. **Button layer** (`inputbutton_t`) -- physical hardware inputs, e.g.
|
||||
keyboard key, gamepad button, analog axis, mouse axis. Multiple
|
||||
buttons can bind to the same action (the highest value wins).
|
||||
|
||||
The platform layer implements two hooks:
|
||||
- `inputUpdatePlatform()` -- read hardware state once per frame
|
||||
- `inputButtonGetValuePlatform()` -- return the analog value [0.0, 1.0]
|
||||
for a given button
|
||||
|
||||
## Global state
|
||||
|
||||
```c
|
||||
extern input_t INPUT;
|
||||
// INPUT.actions[INPUT_ACTION_COUNT] -- all action states
|
||||
// INPUT.platform -- platform-specific data
|
||||
```
|
||||
|
||||
## Reading actions (game code)
|
||||
|
||||
```c
|
||||
// Analog value this frame (0.0 - 1.0)
|
||||
float_t inputGetCurrentValue(inputaction_t action);
|
||||
|
||||
// Analog value last frame
|
||||
float_t inputGetLastValue(inputaction_t action);
|
||||
|
||||
// Boolean helpers (built on current/last values)
|
||||
bool_t inputIsDown(inputaction_t action);
|
||||
bool_t inputWasDown(inputaction_t action);
|
||||
bool_t inputPressed(inputaction_t action); // was up, now down
|
||||
bool_t inputReleased(inputaction_t action); // was down, now up
|
||||
|
||||
// 2D axis helpers
|
||||
void inputAxis2D(
|
||||
inputaction_t horiz,
|
||||
inputaction_t vert,
|
||||
vec2 out
|
||||
);
|
||||
float_t inputAngle2D(inputaction_t horiz, inputaction_t vert);
|
||||
void inputAxis(inputaction_t action, float_t *out);
|
||||
|
||||
// Deadzone filter (applied to raw axis values)
|
||||
float_t inputDeadzone(float_t value, float_t deadzone);
|
||||
```
|
||||
|
||||
## Binding buttons to actions
|
||||
|
||||
```c
|
||||
void inputBind(inputaction_t action, inputbutton_t button);
|
||||
```
|
||||
|
||||
Each platform's init function calls `inputBind` to wire its hardware
|
||||
buttons to the standard action IDs. Game code should never need to call
|
||||
`inputBind` -- it is set up once during platform init.
|
||||
|
||||
## Button types
|
||||
|
||||
```c
|
||||
INPUT_BUTTON_TYPE_KEYBOARD // SDL scancode (SDL2 targets only)
|
||||
INPUT_BUTTON_TYPE_POINTER // Mouse axes: X, Y, Z, WHEEL_X, WHEEL_Y
|
||||
INPUT_BUTTON_TYPE_TOUCH // Touch (defined, not fully implemented)
|
||||
INPUT_BUTTON_TYPE_GAMEPAD // Digital gamepad buttons
|
||||
INPUT_BUTTON_TYPE_GAMEPAD_AXIS // Analog axes (-1.0 to 1.0 internally)
|
||||
```
|
||||
|
||||
## Events
|
||||
|
||||
Each action has `onPressed` and `onReleased` event callbacks. Subscribe
|
||||
via the event system (see `.claude/events.md`):
|
||||
|
||||
```c
|
||||
eventSubscribe(&INPUT.actions[ACTION_ACCEPT].onPressed, myCallback, NULL);
|
||||
```
|
||||
|
||||
## Platform implementations
|
||||
|
||||
### SDL2 (`src/dusksdl2/input/`)
|
||||
|
||||
Handles Linux, Knulli, and PSP (PSP adds its own button mapping layer
|
||||
on top of SDL2).
|
||||
|
||||
- Keyboard: SDL scancode array from `SDL_GetKeyboardState()`
|
||||
- Pointer: normalized mouse position (0.0-1.0), scroll axes
|
||||
- Gamepad: first available `SDL_GameController`; axis values normalized
|
||||
to [-1.0, 1.0] with deadzone (default 0.2f via `inputGetDeadzoneSDL2`)
|
||||
|
||||
### Dolphin -- GameCube / Wii (`src/duskdolphin/input/`)
|
||||
|
||||
Uses `libogc` PAD API. No keyboard or pointer input -- trying to use
|
||||
those button types is a compile-time `#error`.
|
||||
|
||||
- Gamepad: `PAD_ScanPads()` + `PAD_ButtonsHeld()` for pad 0
|
||||
- Axes: left stick X/Y, C-stick X/Y, L/R triggers (6 total)
|
||||
- Deadzone: hardcoded 0.2f
|
||||
- Default bindings set at init: D-pad/L-stick = directional actions,
|
||||
A = ACCEPT, B = CANCEL, X = CONSOLE, Start = RAGEQUIT
|
||||
|
||||
### PSP (`src/duskpsp/input/`)
|
||||
|
||||
Layered on top of SDL2. `inputInitPSP()` remaps SDL2 controller button
|
||||
constants to PSP button names, then calls `inputBind` to wire them:
|
||||
|
||||
| PSP button | SDL2 constant |
|
||||
|------------|---------------|
|
||||
| Cross | `SDL_CONTROLLER_BUTTON_A` |
|
||||
| Circle | `SDL_CONTROLLER_BUTTON_B` |
|
||||
| Triangle | `SDL_CONTROLLER_BUTTON_Y` |
|
||||
| Square | `SDL_CONTROLLER_BUTTON_X` |
|
||||
| L / R | `SDL_CONTROLLER_BUTTON_LEFTSHOULDER` / `RIGHTSHOULDER` |
|
||||
| L-Stick | `SDL_CONTROLLER_AXIS_LEFTX/Y` |
|
||||
|
||||
## Platform capability notes
|
||||
|
||||
| Feature | Linux/Knulli | PSP | GameCube/Wii |
|
||||
|---------|-------------|-----|--------------|
|
||||
| Keyboard | Yes (SDL2) | No | No |
|
||||
| Pointer/Mouse | Yes (SDL2) | No | No |
|
||||
| Gamepad | Yes (SDL2) | Yes (SDL2) | Yes (PAD) |
|
||||
| Analog axes | Yes | L-Stick only | L-Stick, C-Stick, Triggers |
|
||||
| Touch | Defined, not implemented | -- | -- |
|
||||
Reference in New Issue
Block a user