Final docs

This commit is contained in:
2026-06-16 13:07:21 -05:00
parent c0a2ae234f
commit 43d0593872
4 changed files with 127 additions and 22 deletions
+15 -2
View File
@@ -43,8 +43,21 @@ typedef union shadermaterial_u {
} shadermaterial_t;
```
`shaderunlitmaterial_t` typically holds a `texture_t *` and a
tint colour. Check `shaderunlitmaterial.h` for the exact fields.
`shaderunlitmaterial_t` fields:
```c
typedef struct {
color_t color; // tint colour (multiplied with the texture sample)
texture_t *texture; // NULL uses TEXTURE_WHITE (solid colour draw)
} shaderunlitmaterial_t;
```
The shader exposes uniforms `u_Proj`, `u_View`, `u_Model` (mat4),
`u_Texture` (sampler), and `u_Color` (vec4). They are uploaded via
`shaderUnlitSetMaterial(shader, material)`.
A global singleton `SHADER_UNLIT` is the live shader object;
`SHADER_UNLIT_DEFINITION` is its platform definition descriptor.
To use a shader material on a renderable entity:
+10 -3
View File
@@ -97,6 +97,13 @@ eventSubscribe(&state.onComplete, myHandler, myUserPtr);
## Where events are used
- `inputactiondata_t`: `onPressed`, `onReleased` per action
- Any engine subsystem that exposes hooks (network connect/disconnect,
asset batch completion, etc.)
| Subsystem | Event | Fires when |
|-----------|-------|-----------|
| `inputactiondata_t` | `onPressed`, `onReleased` | Action button state changes |
| `uitextbox_t` | `onPageComplete` | Typewriter scroll reveals the full page |
| `uitextbox_t` | `onLastPage` | Last page is fully scrolled |
| `uifullbox_t` | `onTransitionEnd` | Colour transition animation completes |
| `uiloading_t` | `onShow` / `onHide` | Loading indicator fade completes |
| Asset system | `assetbatch_t` callback | All entries in a batch reach LOADED/ERROR |
See `.claude/ui.md` for the UI event details.
+70 -13
View File
@@ -17,6 +17,26 @@ The platform layer implements two hooks:
- `inputButtonGetValuePlatform()` -- return the analog value [0.0, 1.0]
for a given button
## Defined actions
Actions are defined in `src/dusk/input/input.csv` and code-generated
into the `inputaction_t` enum. Current values:
| Constant | Meaning |
|----------|---------|
| `INPUT_ACTION_NULL` | Invalid / sentinel (0) |
| `INPUT_ACTION_UP` | Up direction |
| `INPUT_ACTION_DOWN` | Down direction |
| `INPUT_ACTION_LEFT` | Left direction |
| `INPUT_ACTION_RIGHT` | Right direction |
| `INPUT_ACTION_ACCEPT` | Confirm / primary action |
| `INPUT_ACTION_CANCEL` | Back / secondary action |
| `INPUT_ACTION_RAGEQUIT` | Quit the application |
| `INPUT_ACTION_CONSOLE` | Toggle debug console |
| `INPUT_ACTION_POINTERX` | Mouse / pointer X axis |
| `INPUT_ACTION_POINTERY` | Mouse / pointer Y axis |
| `INPUT_ACTION_COUNT` | Total count (not a valid action) |
## Global state
```c
@@ -40,14 +60,22 @@ 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
// Single axis from a neg + pos pair of actions (returns [-1, 1]):
float_t inputAxis(inputaction_t neg, inputaction_t pos);
// 2D axis from four actions (negX/posX/negY/posY):
void inputAxis2D(
inputaction_t horiz,
inputaction_t vert,
vec2 out
inputaction_t negX, inputaction_t posX,
inputaction_t negY, inputaction_t posY,
vec2 result
);
// Same four-action axis, normalized to a unit vector via atan2:
void inputAngle2D(
inputaction_t negX, inputaction_t posX,
inputaction_t negY, inputaction_t posY,
vec2 result
);
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);
@@ -119,12 +147,41 @@ constants to PSP button names, then calls `inputBind` to wire them:
| L / R | `SDL_CONTROLLER_BUTTON_LEFTSHOULDER` / `RIGHTSHOULDER` |
| L-Stick | `SDL_CONTROLLER_AXIS_LEFTX/Y` |
### Vita (`src/duskvita/input/`)
Layered on top of SDL2 (via vitaSDL2). Behaviour is similar to PSP --
no keyboard, no pointer, gamepad only.
## JS module (`Input`)
The input system is exposed to JS as the global `Input` object with
static methods. Action constants are pre-defined as numeric properties
on the `Input` object (e.g. `Input.ACCEPT`, `Input.UP`):
```js
// Check if the accept button is held this frame:
if(Input.isDown(Input.ACCEPT)) { ... }
// Was the cancel button just pressed?
if(Input.pressed(Input.CANCEL)) { ... }
// Analog value for the right trigger:
var val = Input.getValue(Input.RIGHT);
// Single axis (-1 to 1) from a neg/pos pair:
var h = Input.axis(Input.LEFT, Input.RIGHT);
```
All `Input.*` action constants match the `INPUT_ACTION_*` enum values
from the C layer (UP, DOWN, LEFT, RIGHT, ACCEPT, CANCEL, RAGEQUIT,
CONSOLE, POINTERX, POINTERY).
## 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 | -- | -- |
| Feature | Linux/Knulli | PSP | Vita | GameCube/Wii |
|---------|-------------|-----|------|--------------|
| Keyboard | Yes (SDL2) | No | No | No |
| Pointer/Mouse | Yes (SDL2) | No | No | No |
| Gamepad | Yes (SDL2) | Yes (SDL2) | Yes (SDL2) | Yes (PAD) |
| Analog axes | Yes | L-Stick only | L-Stick, R-Stick | L-Stick, C-Stick, Triggers |
| Touch | Defined, not implemented | -- | -- | -- |
+32 -4
View File
@@ -86,10 +86,38 @@ The shader used for each renderable:
## Transitioning between scenes
To move to a new scene from JS, call the scene module's transition
function (exact API in the `scene` JS module). The C side defers the
actual switch to the start of the next `sceneUpdate` call so the
current tick completes cleanly before any dispose runs.
Scene transitions are handled entirely in JS via the `Scene` global.
The `Scene` object is a singleton with:
```js
// Switch to a new scene. Calls dispose() on the current scene, then
// init() on the new one. Both happen synchronously this tick.
Scene.set(newSceneObject);
// The current scene object (may be null):
Scene.current
```
Typical scene-switch pattern:
```js
// Inside a scene's update or event handler:
const nextScene = require("scenes/gameplay.js");
Scene.set(nextScene);
```
`Scene.set` is synchronous -- it calls `dispose` on the old scene and
`init` on the new scene before returning. If `init` needs async work
(loading assets), use an async function and `await` inside `init`:
```js
nextScene.init = async function() {
await batch.load(); // wait for assets before proceeding
};
```
The C side does not defer the transition; the switch happens inside
the current `sceneUpdate` call.
## Relationship to the engine loop