@diffenderfer-games/hub 2.0.0-next.0 → 2.0.0-next.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +9 -0
- package/LICENSE +21 -21
- package/README.md +191 -139
- package/dist/doctor/cli.mjs +49 -19
- package/dist/doctor/cli.mjs.map +1 -1
- package/dist/shared/client-version.gen.js +1 -1
- package/dist/shared/daily.js +1 -1
- package/dist/shared/globals.js +8 -3
- package/dist/shared/globals.js.map +1 -1
- package/dist/shared/index.d.ts +1 -1
- package/package.json +89 -89
- package/src/auto.ts +39 -39
- package/src/core/connection.ts +299 -299
- package/src/core/errors.ts +147 -147
- package/src/core/game-data.ts +38 -38
- package/src/core/hub-economy.ts +179 -179
- package/src/core/hub-progress.ts +205 -205
- package/src/core/hub.ts +131 -131
- package/src/core/menu-control.ts +61 -61
- package/src/core/offline/events.ts +50 -50
- package/src/core/offline/favorites.ts +21 -21
- package/src/core/offline/local-store.ts +261 -261
- package/src/core/offline/queue.ts +171 -171
- package/src/core/page.ts +74 -74
- package/src/core/rest/endpoint-types.ts +22 -22
- package/src/core/rest/rest-client.ts +152 -152
- package/src/core/storage/json-guards.ts +74 -74
- package/src/core/storage/key-value.ts +66 -66
- package/src/core/ticket.ts +43 -43
- package/src/core/types.ts +134 -134
- package/src/core/version/client-version.gen.ts +1 -1
- package/src/core/version/hub-version.ts +62 -62
- package/src/core/version/semver.ts +97 -97
- package/src/daily/daily-system.ts +161 -161
- package/src/daily/page-daily.ts +36 -36
- package/src/daily/types.ts +67 -67
- package/src/daily.ts +10 -10
- package/src/doctor/checks.ts +78 -76
- package/src/doctor/cli.ts +98 -106
- package/src/doctor/hub-version-fetch.ts +43 -0
- package/src/doctor/tsconfig.json +12 -12
- package/src/globals.ts +115 -110
- package/src/index.ts +50 -50
- package/src/input/device-state.ts +146 -146
- package/src/input/edges.ts +55 -55
- package/src/input/gamepad.ts +61 -61
- package/src/input/input-events.ts +32 -32
- package/src/input/input-registry.ts +164 -164
- package/src/input/input-system.ts +393 -393
- package/src/input/legacy-controls.ts +64 -64
- package/src/input/nav-state.ts +191 -191
- package/src/input/navigator.ts +171 -171
- package/src/input/on-screen-controls.ts +101 -101
- package/src/input/page-control.ts +43 -43
- package/src/input/page-input.ts +193 -193
- package/src/input/player-remaps.ts +77 -77
- package/src/input/source-values.ts +116 -116
- package/src/input/spatial.ts +47 -47
- package/src/input/types.ts +331 -331
- package/src/input/zero-config.ts +177 -177
- package/src/input.ts +22 -22
- package/src/mp.ts +10 -10
- package/src/overlay/controls-panel.ts +163 -163
- package/src/overlay/dom.ts +46 -46
- package/src/overlay/layout-clusters.ts +162 -162
- package/src/overlay/layout-geometry.ts +136 -136
- package/src/overlay/layout.ts +203 -203
- package/src/overlay/listener-scope.ts +23 -23
- package/src/overlay/on-screen-keyboard.ts +137 -137
- package/src/overlay/overlay.ts +208 -208
- package/src/overlay/styles.ts +9 -9
- package/src/overlay/virtual-controls.ts +262 -262
- package/src/race.ts +10 -10
- package/src/realtime/bridge.ts +121 -121
- package/src/realtime/cross-bundle.ts +29 -29
- package/src/realtime/fallback-notice.ts +48 -48
- package/src/realtime/hub-link.ts +65 -65
- package/src/realtime/latest-state.ts +33 -33
- package/src/realtime/multiplayer-forwarder.ts +28 -28
- package/src/realtime/multiplayer-types.ts +52 -52
- package/src/realtime/page-runtime.ts +60 -60
- package/src/realtime/race-forwarder.ts +59 -59
- package/src/realtime/race-types.ts +132 -132
- package/src/realtime/room-types.ts +125 -125
- package/src/realtime/rooms-forwarder.ts +79 -79
- package/src/realtime/runtime-api.ts +49 -49
- package/src/realtime/runtime-opener.ts +61 -61
- package/src/realtime/social-forwarder.ts +72 -72
- package/src/realtime/social-types.ts +78 -78
- package/src/realtime/types.ts +53 -53
- package/src/realtime/wire-types.ts +72 -72
- package/src/rooms.ts +10 -10
- package/src/social.ts +18 -18
- package/src/types.ts +13 -13
- package/src/uistack/page-stack.ts +45 -45
- package/src/uistack/play-suspension.ts +82 -82
- package/src/uistack/types.ts +76 -76
- package/src/uistack/ui-stack.ts +144 -144
package/src/input/types.ts
CHANGED
|
@@ -1,331 +1,331 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The input system's public shapes (`hub.input`, docs/hub.md "Input system").
|
|
3
|
-
* A game declares named inputs that each read as 0..1 and maps each to
|
|
4
|
-
* keyboard, mouse, touch and gamepad sources.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
/** The device the player is using right now. */
|
|
8
|
-
export type InputSource = 'keyboard' | 'mouse' | 'gamepad' | 'touch';
|
|
9
|
-
|
|
10
|
-
/** A direction or half of an axis. */
|
|
11
|
-
export type AxisSide = '+' | '-';
|
|
12
|
-
|
|
13
|
-
/** How the mouse drives an input. */
|
|
14
|
-
export interface MouseMapping {
|
|
15
|
-
/** Held while this mouse button is down. */
|
|
16
|
-
button?: number;
|
|
17
|
-
/** 1 for one frame on a double-click. */
|
|
18
|
-
dblclick?: boolean;
|
|
19
|
-
/** The pointer's position from screen centre on this axis maps to 0..1 on one side. */
|
|
20
|
-
centerAxis?: 'x' | 'y';
|
|
21
|
-
/** Which side of centre fills 0..1 (default `+`). */
|
|
22
|
-
centerSide?: AxisSide;
|
|
23
|
-
/** Relative movement on this axis, scaled by `moveScale`. */
|
|
24
|
-
moveAxis?: 'x' | 'y';
|
|
25
|
-
/** Which direction of movement counts (default `+`). */
|
|
26
|
-
moveSign?: AxisSide;
|
|
27
|
-
/** Movement scale (default 0.1). */
|
|
28
|
-
moveScale?: number;
|
|
29
|
-
/** Wheel delta in this direction (decays). */
|
|
30
|
-
wheel?: AxisSide;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/** How a gamepad drives an input. */
|
|
34
|
-
export interface GamepadMapping {
|
|
35
|
-
/** A standard-gamepad button index (0/1, or a 0..1 trigger). */
|
|
36
|
-
button?: number;
|
|
37
|
-
/** An axis index and which half: `+` positive, `-` negative, `±` absolute value. */
|
|
38
|
-
axis?: [number, AxisSide | '±'];
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/** How touch and the on-screen controls drive an input. */
|
|
42
|
-
export interface TouchMapping {
|
|
43
|
-
/** The id of a virtual button that drives this input. */
|
|
44
|
-
button?: string;
|
|
45
|
-
/** The id of a virtual joystick. */
|
|
46
|
-
stick?: string;
|
|
47
|
-
/** Which half or axis of that stick. */
|
|
48
|
-
axis?: 'x+' | 'x-' | 'y+' | 'y-' | 'x' | 'y';
|
|
49
|
-
/** 1 for one frame on a tap anywhere on a tap control. */
|
|
50
|
-
tap?: boolean;
|
|
51
|
-
/** The last touch's position from screen centre on this axis maps to 0..1 on one side. */
|
|
52
|
-
centerAxis?: 'x' | 'y';
|
|
53
|
-
/** Which side of centre fills 0..1 (default `+`). */
|
|
54
|
-
centerSide?: AxisSide;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/** One named input and its sources. */
|
|
58
|
-
export interface InputDef {
|
|
59
|
-
/** `KeyboardEvent.key` values (case-insensitive). */
|
|
60
|
-
keys?: string[];
|
|
61
|
-
/** Mouse source (counts while the mouse is the active pointer). */
|
|
62
|
-
mouse?: MouseMapping;
|
|
63
|
-
/** Gamepad source (counts while a gamepad is the active pointer). */
|
|
64
|
-
gamepad?: GamepadMapping;
|
|
65
|
-
/** Touch and on-screen control source. */
|
|
66
|
-
touch?: TouchMapping;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* A named axis. Each of `x` and `y` is a `[negative, positive]` pair of input
|
|
71
|
-
* names (read as -1..1), or one input name read directly.
|
|
72
|
-
*/
|
|
73
|
-
export interface AxisDef {
|
|
74
|
-
/** The horizontal axis. */
|
|
75
|
-
x?: string | [string, string];
|
|
76
|
-
/** The vertical axis. */
|
|
77
|
-
y?: string | [string, string];
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
/** Where an on-screen control sits. */
|
|
81
|
-
export type Anchor =
|
|
82
|
-
| 'top-left' | 'top' | 'top-right'
|
|
83
|
-
| 'left' | 'center' | 'right'
|
|
84
|
-
| 'bottom-left' | 'bottom' | 'bottom-right';
|
|
85
|
-
|
|
86
|
-
/** The kinds of on-screen control. */
|
|
87
|
-
export type VirtualControlType = 'button' | 'joystick' | 'dpad' | 'tap';
|
|
88
|
-
|
|
89
|
-
/** Pixel distances from the viewport edges. */
|
|
90
|
-
export interface EdgeOffsets {
|
|
91
|
-
/** From the left edge. */
|
|
92
|
-
left?: number;
|
|
93
|
-
/** From the right edge. */
|
|
94
|
-
right?: number;
|
|
95
|
-
/** From the top edge. */
|
|
96
|
-
top?: number;
|
|
97
|
-
/** From the bottom edge. */
|
|
98
|
-
bottom?: number;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
/** The inputs a dpad or button drives. */
|
|
102
|
-
export interface VirtualInputs {
|
|
103
|
-
/** Up. */
|
|
104
|
-
up?: string;
|
|
105
|
-
/** Down. */
|
|
106
|
-
down?: string;
|
|
107
|
-
/** Left. */
|
|
108
|
-
left?: string;
|
|
109
|
-
/** Right. */
|
|
110
|
-
right?: string;
|
|
111
|
-
/** A press. */
|
|
112
|
-
press?: string;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
/** An on-screen touch control. */
|
|
116
|
-
export interface VirtualDef {
|
|
117
|
-
/** Its id (inputs reference it from `touch.button` or `touch.stick`). */
|
|
118
|
-
id: string;
|
|
119
|
-
/** What it is. */
|
|
120
|
-
type: VirtualControlType;
|
|
121
|
-
/** Its anchor for the automatic layout. */
|
|
122
|
-
place: Anchor;
|
|
123
|
-
/**
|
|
124
|
-
* An explicit pixel position from the viewport edges; bypasses the automatic
|
|
125
|
-
* layout for this control (e.g. pin a pause button just above a stick).
|
|
126
|
-
*/
|
|
127
|
-
pos?: EdgeOffsets;
|
|
128
|
-
/**
|
|
129
|
-
* Nudge an auto-placed control away from its anchor's edges, in px: `x`
|
|
130
|
-
* moves it inward from the left/right edge, `y` away from the top/bottom
|
|
131
|
-
* edge. For a band every control should avoid, use `hub.input.setInsets`.
|
|
132
|
-
*/
|
|
133
|
-
offset?: { x?: number; y?: number };
|
|
134
|
-
/** Diameter in px (or the width when `width`/`height` are given). */
|
|
135
|
-
size?: number;
|
|
136
|
-
/** Width in px; overrides `size` for non-square controls. */
|
|
137
|
-
width?: number;
|
|
138
|
-
/** Height in px; overrides `size` for non-square controls. */
|
|
139
|
-
height?: number;
|
|
140
|
-
/** Default circle for sticks, round for buttons. */
|
|
141
|
-
shape?: 'round' | 'circle' | 'square' | 'pill';
|
|
142
|
-
/** A stick's travel: `both` (default), or single-axis `x` / `y`. */
|
|
143
|
-
axis?: 'x' | 'y' | 'both';
|
|
144
|
-
/** 0..1. */
|
|
145
|
-
opacity?: number;
|
|
146
|
-
/** Accent colour (border, knob, pressed fill). */
|
|
147
|
-
color?: string;
|
|
148
|
-
/** Resting background colour. */
|
|
149
|
-
bg?: string;
|
|
150
|
-
/** Label text colour. */
|
|
151
|
-
text?: string;
|
|
152
|
-
/** Text on a button. */
|
|
153
|
-
label?: string;
|
|
154
|
-
/** Raw HTML inside a button. */
|
|
155
|
-
html?: string;
|
|
156
|
-
/** For a dpad or button: the inputs it drives. Joysticks drive the inputs that reference them. */
|
|
157
|
-
inputs?: VirtualInputs;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
/** A screen rectangle in px. */
|
|
161
|
-
export interface Rect {
|
|
162
|
-
/** Left. */
|
|
163
|
-
x: number;
|
|
164
|
-
/** Top. */
|
|
165
|
-
y: number;
|
|
166
|
-
/** Width. */
|
|
167
|
-
width: number;
|
|
168
|
-
/** Height. */
|
|
169
|
-
height: number;
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
/** What a navigable element is, for `act`. */
|
|
173
|
-
export type NavElementKind = 'button' | 'text' | 'range' | 'custom';
|
|
174
|
-
|
|
175
|
-
/** A navigable element that isn't (only) a DOM node, e.g. a canvas-drawn button. */
|
|
176
|
-
export interface NavElement {
|
|
177
|
-
/** Its id, echoed in focus/blur/act events. */
|
|
178
|
-
id?: string;
|
|
179
|
-
/** What it is (`text` opens the on-screen keyboard on act). */
|
|
180
|
-
kind?: NavElementKind;
|
|
181
|
-
/** A DOM element: bounds, click and focus come from it. */
|
|
182
|
-
el?: HTMLElement;
|
|
183
|
-
/** Its bounds, for elements without `el`. */
|
|
184
|
-
getBounds?: () => Rect;
|
|
185
|
-
/** Called when it gains the highlight. */
|
|
186
|
-
onFocus?: () => void;
|
|
187
|
-
/** Called when it loses the highlight. */
|
|
188
|
-
onBlur?: () => void;
|
|
189
|
-
/** Called when the player activates it. */
|
|
190
|
-
onAct?: () => void;
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
/** What a navigable group's element list may hold. */
|
|
194
|
-
export type NavTarget = HTMLElement | NavElement;
|
|
195
|
-
|
|
196
|
-
/** Makes a group's UI navigable by gamepad and keys. */
|
|
197
|
-
export interface NavigableDef {
|
|
198
|
-
/** Input that steps to the previous element. */
|
|
199
|
-
prev?: string;
|
|
200
|
-
/** Input that steps to the next element. */
|
|
201
|
-
next?: string;
|
|
202
|
-
/** Input that moves up spatially. */
|
|
203
|
-
up?: string;
|
|
204
|
-
/** Input that moves down spatially. */
|
|
205
|
-
down?: string;
|
|
206
|
-
/** Input that activates the highlighted element. */
|
|
207
|
-
act: string;
|
|
208
|
-
/** The elements, re-queried after every interaction (the DOM can change). */
|
|
209
|
-
elements: () => NavTarget[];
|
|
210
|
-
/** Wrap around at the ends (default true). */
|
|
211
|
-
wrap?: boolean;
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
/** A named group of inputs, enabled and disabled together. */
|
|
215
|
-
export interface GroupDef {
|
|
216
|
-
/** The inputs, by name. */
|
|
217
|
-
inputs: Record<string, InputDef>;
|
|
218
|
-
/** Named axes over the inputs. */
|
|
219
|
-
axes?: Record<string, AxisDef>;
|
|
220
|
-
/** On-screen controls shown while the group is enabled. */
|
|
221
|
-
virtual?: VirtualDef[];
|
|
222
|
-
/** Makes the group's UI navigable. */
|
|
223
|
-
navigable?: NavigableDef;
|
|
224
|
-
/** Start enabled (default false; call `enable()` yourself). */
|
|
225
|
-
enabled?: boolean;
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
/** What `hub.input.define` takes. */
|
|
229
|
-
export interface InputConfig {
|
|
230
|
-
/** The groups, by name. */
|
|
231
|
-
groups: Record<string, GroupDef>;
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
/** One input's reading this frame. */
|
|
235
|
-
export interface InputReading {
|
|
236
|
-
/** 0..1. */
|
|
237
|
-
value: number;
|
|
238
|
-
/** Same as `value`. */
|
|
239
|
-
raw: number;
|
|
240
|
-
/** It crossed 0.5 upward this frame. */
|
|
241
|
-
isDown: boolean;
|
|
242
|
-
/** It crossed 0.5 downward this frame. */
|
|
243
|
-
isUp: boolean;
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
/** A 2D reading, clamped to the unit circle. */
|
|
247
|
-
export interface Vector {
|
|
248
|
-
/** -1..1. */
|
|
249
|
-
x: number;
|
|
250
|
-
/** -1..1. */
|
|
251
|
-
y: number;
|
|
252
|
-
/** 0..1. */
|
|
253
|
-
mag: number;
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
/** A player-dragged spot: the control's top-left corner as % of the viewport. */
|
|
257
|
-
export interface DraggedSpot {
|
|
258
|
-
/** % of the viewport width. */
|
|
259
|
-
x?: number;
|
|
260
|
-
/** % of the viewport height. */
|
|
261
|
-
y?: number;
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
/** A player's changes to a virtual control. */
|
|
265
|
-
export type VirtualOverride = Partial<VirtualDef> & DraggedSpot;
|
|
266
|
-
|
|
267
|
-
/** The player's remaps and control customisations, persisted per game. */
|
|
268
|
-
export interface InputOverrides {
|
|
269
|
-
/** Rebound inputs, by input name. */
|
|
270
|
-
bindings?: Record<string, Partial<InputDef>>;
|
|
271
|
-
/** Moved or restyled on-screen controls, by control id. */
|
|
272
|
-
virtual?: Record<string, VirtualOverride>;
|
|
273
|
-
/** The player's show/hide choice for the on-screen controls. */
|
|
274
|
-
showVirtual?: boolean;
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
/** The hub menu, as the input system drives it (toggle on Select, gamepad navigation inside). */
|
|
278
|
-
export interface MenuBridge {
|
|
279
|
-
/** Open or close the menu; returns whether it is now open. */
|
|
280
|
-
toggle: () => boolean;
|
|
281
|
-
/** Whether the menu is open. */
|
|
282
|
-
isOpen: () => boolean;
|
|
283
|
-
/** Close the menu. */
|
|
284
|
-
close: () => void;
|
|
285
|
-
/** The menu's shadow root (its focusables are navigated). */
|
|
286
|
-
root: ShadowRoot | null;
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
/** A navigation focus or act event. */
|
|
290
|
-
export interface NavFocusEvent {
|
|
291
|
-
/** The element's id, if it has one. */
|
|
292
|
-
id?: string | undefined;
|
|
293
|
-
/** The DOM element, if any. */
|
|
294
|
-
el?: HTMLElement | undefined;
|
|
295
|
-
/** What it is. */
|
|
296
|
-
kind?: NavElementKind | undefined;
|
|
297
|
-
/** Its index in the list. */
|
|
298
|
-
index: number;
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
/** A navigation blur event. */
|
|
302
|
-
export interface NavBlurEvent {
|
|
303
|
-
/** The element's id, if it has one. */
|
|
304
|
-
id?: string | undefined;
|
|
305
|
-
/** Its index in the list. */
|
|
306
|
-
index: number;
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
/** Events `hub.input.on` delivers, name → payload. */
|
|
310
|
-
export interface InputEvents {
|
|
311
|
-
/** An element gained the highlight. */
|
|
312
|
-
focus: NavFocusEvent;
|
|
313
|
-
/** An element lost the highlight. */
|
|
314
|
-
blur: NavBlurEvent;
|
|
315
|
-
/** The player activated an element. */
|
|
316
|
-
act: NavFocusEvent;
|
|
317
|
-
/** The active device changed. */
|
|
318
|
-
sourcechange: InputSource;
|
|
319
|
-
/** Reserved. */
|
|
320
|
-
navigate: NavFocusEvent;
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
/** Where the input system persists the player's remaps. */
|
|
324
|
-
export interface InputHost {
|
|
325
|
-
/** This page's game slug. */
|
|
326
|
-
readonly slug: string | null;
|
|
327
|
-
/** The saved overrides, or `null`. */
|
|
328
|
-
loadOverrides(): InputOverrides | null;
|
|
329
|
-
/** Save overrides (locally, and to the cloud when signed in). */
|
|
330
|
-
saveOverrides(overrides: InputOverrides): void;
|
|
331
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* The input system's public shapes (`hub.input`, docs/hub.md "Input system").
|
|
3
|
+
* A game declares named inputs that each read as 0..1 and maps each to
|
|
4
|
+
* keyboard, mouse, touch and gamepad sources.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/** The device the player is using right now. */
|
|
8
|
+
export type InputSource = 'keyboard' | 'mouse' | 'gamepad' | 'touch';
|
|
9
|
+
|
|
10
|
+
/** A direction or half of an axis. */
|
|
11
|
+
export type AxisSide = '+' | '-';
|
|
12
|
+
|
|
13
|
+
/** How the mouse drives an input. */
|
|
14
|
+
export interface MouseMapping {
|
|
15
|
+
/** Held while this mouse button is down. */
|
|
16
|
+
button?: number;
|
|
17
|
+
/** 1 for one frame on a double-click. */
|
|
18
|
+
dblclick?: boolean;
|
|
19
|
+
/** The pointer's position from screen centre on this axis maps to 0..1 on one side. */
|
|
20
|
+
centerAxis?: 'x' | 'y';
|
|
21
|
+
/** Which side of centre fills 0..1 (default `+`). */
|
|
22
|
+
centerSide?: AxisSide;
|
|
23
|
+
/** Relative movement on this axis, scaled by `moveScale`. */
|
|
24
|
+
moveAxis?: 'x' | 'y';
|
|
25
|
+
/** Which direction of movement counts (default `+`). */
|
|
26
|
+
moveSign?: AxisSide;
|
|
27
|
+
/** Movement scale (default 0.1). */
|
|
28
|
+
moveScale?: number;
|
|
29
|
+
/** Wheel delta in this direction (decays). */
|
|
30
|
+
wheel?: AxisSide;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** How a gamepad drives an input. */
|
|
34
|
+
export interface GamepadMapping {
|
|
35
|
+
/** A standard-gamepad button index (0/1, or a 0..1 trigger). */
|
|
36
|
+
button?: number;
|
|
37
|
+
/** An axis index and which half: `+` positive, `-` negative, `±` absolute value. */
|
|
38
|
+
axis?: [number, AxisSide | '±'];
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** How touch and the on-screen controls drive an input. */
|
|
42
|
+
export interface TouchMapping {
|
|
43
|
+
/** The id of a virtual button that drives this input. */
|
|
44
|
+
button?: string;
|
|
45
|
+
/** The id of a virtual joystick. */
|
|
46
|
+
stick?: string;
|
|
47
|
+
/** Which half or axis of that stick. */
|
|
48
|
+
axis?: 'x+' | 'x-' | 'y+' | 'y-' | 'x' | 'y';
|
|
49
|
+
/** 1 for one frame on a tap anywhere on a tap control. */
|
|
50
|
+
tap?: boolean;
|
|
51
|
+
/** The last touch's position from screen centre on this axis maps to 0..1 on one side. */
|
|
52
|
+
centerAxis?: 'x' | 'y';
|
|
53
|
+
/** Which side of centre fills 0..1 (default `+`). */
|
|
54
|
+
centerSide?: AxisSide;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** One named input and its sources. */
|
|
58
|
+
export interface InputDef {
|
|
59
|
+
/** `KeyboardEvent.key` values (case-insensitive). */
|
|
60
|
+
keys?: string[];
|
|
61
|
+
/** Mouse source (counts while the mouse is the active pointer). */
|
|
62
|
+
mouse?: MouseMapping;
|
|
63
|
+
/** Gamepad source (counts while a gamepad is the active pointer). */
|
|
64
|
+
gamepad?: GamepadMapping;
|
|
65
|
+
/** Touch and on-screen control source. */
|
|
66
|
+
touch?: TouchMapping;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* A named axis. Each of `x` and `y` is a `[negative, positive]` pair of input
|
|
71
|
+
* names (read as -1..1), or one input name read directly.
|
|
72
|
+
*/
|
|
73
|
+
export interface AxisDef {
|
|
74
|
+
/** The horizontal axis. */
|
|
75
|
+
x?: string | [string, string];
|
|
76
|
+
/** The vertical axis. */
|
|
77
|
+
y?: string | [string, string];
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/** Where an on-screen control sits. */
|
|
81
|
+
export type Anchor =
|
|
82
|
+
| 'top-left' | 'top' | 'top-right'
|
|
83
|
+
| 'left' | 'center' | 'right'
|
|
84
|
+
| 'bottom-left' | 'bottom' | 'bottom-right';
|
|
85
|
+
|
|
86
|
+
/** The kinds of on-screen control. */
|
|
87
|
+
export type VirtualControlType = 'button' | 'joystick' | 'dpad' | 'tap';
|
|
88
|
+
|
|
89
|
+
/** Pixel distances from the viewport edges. */
|
|
90
|
+
export interface EdgeOffsets {
|
|
91
|
+
/** From the left edge. */
|
|
92
|
+
left?: number;
|
|
93
|
+
/** From the right edge. */
|
|
94
|
+
right?: number;
|
|
95
|
+
/** From the top edge. */
|
|
96
|
+
top?: number;
|
|
97
|
+
/** From the bottom edge. */
|
|
98
|
+
bottom?: number;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/** The inputs a dpad or button drives. */
|
|
102
|
+
export interface VirtualInputs {
|
|
103
|
+
/** Up. */
|
|
104
|
+
up?: string;
|
|
105
|
+
/** Down. */
|
|
106
|
+
down?: string;
|
|
107
|
+
/** Left. */
|
|
108
|
+
left?: string;
|
|
109
|
+
/** Right. */
|
|
110
|
+
right?: string;
|
|
111
|
+
/** A press. */
|
|
112
|
+
press?: string;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/** An on-screen touch control. */
|
|
116
|
+
export interface VirtualDef {
|
|
117
|
+
/** Its id (inputs reference it from `touch.button` or `touch.stick`). */
|
|
118
|
+
id: string;
|
|
119
|
+
/** What it is. */
|
|
120
|
+
type: VirtualControlType;
|
|
121
|
+
/** Its anchor for the automatic layout. */
|
|
122
|
+
place: Anchor;
|
|
123
|
+
/**
|
|
124
|
+
* An explicit pixel position from the viewport edges; bypasses the automatic
|
|
125
|
+
* layout for this control (e.g. pin a pause button just above a stick).
|
|
126
|
+
*/
|
|
127
|
+
pos?: EdgeOffsets;
|
|
128
|
+
/**
|
|
129
|
+
* Nudge an auto-placed control away from its anchor's edges, in px: `x`
|
|
130
|
+
* moves it inward from the left/right edge, `y` away from the top/bottom
|
|
131
|
+
* edge. For a band every control should avoid, use `hub.input.setInsets`.
|
|
132
|
+
*/
|
|
133
|
+
offset?: { x?: number; y?: number };
|
|
134
|
+
/** Diameter in px (or the width when `width`/`height` are given). */
|
|
135
|
+
size?: number;
|
|
136
|
+
/** Width in px; overrides `size` for non-square controls. */
|
|
137
|
+
width?: number;
|
|
138
|
+
/** Height in px; overrides `size` for non-square controls. */
|
|
139
|
+
height?: number;
|
|
140
|
+
/** Default circle for sticks, round for buttons. */
|
|
141
|
+
shape?: 'round' | 'circle' | 'square' | 'pill';
|
|
142
|
+
/** A stick's travel: `both` (default), or single-axis `x` / `y`. */
|
|
143
|
+
axis?: 'x' | 'y' | 'both';
|
|
144
|
+
/** 0..1. */
|
|
145
|
+
opacity?: number;
|
|
146
|
+
/** Accent colour (border, knob, pressed fill). */
|
|
147
|
+
color?: string;
|
|
148
|
+
/** Resting background colour. */
|
|
149
|
+
bg?: string;
|
|
150
|
+
/** Label text colour. */
|
|
151
|
+
text?: string;
|
|
152
|
+
/** Text on a button. */
|
|
153
|
+
label?: string;
|
|
154
|
+
/** Raw HTML inside a button. */
|
|
155
|
+
html?: string;
|
|
156
|
+
/** For a dpad or button: the inputs it drives. Joysticks drive the inputs that reference them. */
|
|
157
|
+
inputs?: VirtualInputs;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/** A screen rectangle in px. */
|
|
161
|
+
export interface Rect {
|
|
162
|
+
/** Left. */
|
|
163
|
+
x: number;
|
|
164
|
+
/** Top. */
|
|
165
|
+
y: number;
|
|
166
|
+
/** Width. */
|
|
167
|
+
width: number;
|
|
168
|
+
/** Height. */
|
|
169
|
+
height: number;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/** What a navigable element is, for `act`. */
|
|
173
|
+
export type NavElementKind = 'button' | 'text' | 'range' | 'custom';
|
|
174
|
+
|
|
175
|
+
/** A navigable element that isn't (only) a DOM node, e.g. a canvas-drawn button. */
|
|
176
|
+
export interface NavElement {
|
|
177
|
+
/** Its id, echoed in focus/blur/act events. */
|
|
178
|
+
id?: string;
|
|
179
|
+
/** What it is (`text` opens the on-screen keyboard on act). */
|
|
180
|
+
kind?: NavElementKind;
|
|
181
|
+
/** A DOM element: bounds, click and focus come from it. */
|
|
182
|
+
el?: HTMLElement;
|
|
183
|
+
/** Its bounds, for elements without `el`. */
|
|
184
|
+
getBounds?: () => Rect;
|
|
185
|
+
/** Called when it gains the highlight. */
|
|
186
|
+
onFocus?: () => void;
|
|
187
|
+
/** Called when it loses the highlight. */
|
|
188
|
+
onBlur?: () => void;
|
|
189
|
+
/** Called when the player activates it. */
|
|
190
|
+
onAct?: () => void;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/** What a navigable group's element list may hold. */
|
|
194
|
+
export type NavTarget = HTMLElement | NavElement;
|
|
195
|
+
|
|
196
|
+
/** Makes a group's UI navigable by gamepad and keys. */
|
|
197
|
+
export interface NavigableDef {
|
|
198
|
+
/** Input that steps to the previous element. */
|
|
199
|
+
prev?: string;
|
|
200
|
+
/** Input that steps to the next element. */
|
|
201
|
+
next?: string;
|
|
202
|
+
/** Input that moves up spatially. */
|
|
203
|
+
up?: string;
|
|
204
|
+
/** Input that moves down spatially. */
|
|
205
|
+
down?: string;
|
|
206
|
+
/** Input that activates the highlighted element. */
|
|
207
|
+
act: string;
|
|
208
|
+
/** The elements, re-queried after every interaction (the DOM can change). */
|
|
209
|
+
elements: () => NavTarget[];
|
|
210
|
+
/** Wrap around at the ends (default true). */
|
|
211
|
+
wrap?: boolean;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/** A named group of inputs, enabled and disabled together. */
|
|
215
|
+
export interface GroupDef {
|
|
216
|
+
/** The inputs, by name. */
|
|
217
|
+
inputs: Record<string, InputDef>;
|
|
218
|
+
/** Named axes over the inputs. */
|
|
219
|
+
axes?: Record<string, AxisDef>;
|
|
220
|
+
/** On-screen controls shown while the group is enabled. */
|
|
221
|
+
virtual?: VirtualDef[];
|
|
222
|
+
/** Makes the group's UI navigable. */
|
|
223
|
+
navigable?: NavigableDef;
|
|
224
|
+
/** Start enabled (default false; call `enable()` yourself). */
|
|
225
|
+
enabled?: boolean;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/** What `hub.input.define` takes. */
|
|
229
|
+
export interface InputConfig {
|
|
230
|
+
/** The groups, by name. */
|
|
231
|
+
groups: Record<string, GroupDef>;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/** One input's reading this frame. */
|
|
235
|
+
export interface InputReading {
|
|
236
|
+
/** 0..1. */
|
|
237
|
+
value: number;
|
|
238
|
+
/** Same as `value`. */
|
|
239
|
+
raw: number;
|
|
240
|
+
/** It crossed 0.5 upward this frame. */
|
|
241
|
+
isDown: boolean;
|
|
242
|
+
/** It crossed 0.5 downward this frame. */
|
|
243
|
+
isUp: boolean;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/** A 2D reading, clamped to the unit circle. */
|
|
247
|
+
export interface Vector {
|
|
248
|
+
/** -1..1. */
|
|
249
|
+
x: number;
|
|
250
|
+
/** -1..1. */
|
|
251
|
+
y: number;
|
|
252
|
+
/** 0..1. */
|
|
253
|
+
mag: number;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/** A player-dragged spot: the control's top-left corner as % of the viewport. */
|
|
257
|
+
export interface DraggedSpot {
|
|
258
|
+
/** % of the viewport width. */
|
|
259
|
+
x?: number;
|
|
260
|
+
/** % of the viewport height. */
|
|
261
|
+
y?: number;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/** A player's changes to a virtual control. */
|
|
265
|
+
export type VirtualOverride = Partial<VirtualDef> & DraggedSpot;
|
|
266
|
+
|
|
267
|
+
/** The player's remaps and control customisations, persisted per game. */
|
|
268
|
+
export interface InputOverrides {
|
|
269
|
+
/** Rebound inputs, by input name. */
|
|
270
|
+
bindings?: Record<string, Partial<InputDef>>;
|
|
271
|
+
/** Moved or restyled on-screen controls, by control id. */
|
|
272
|
+
virtual?: Record<string, VirtualOverride>;
|
|
273
|
+
/** The player's show/hide choice for the on-screen controls. */
|
|
274
|
+
showVirtual?: boolean;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
/** The hub menu, as the input system drives it (toggle on Select, gamepad navigation inside). */
|
|
278
|
+
export interface MenuBridge {
|
|
279
|
+
/** Open or close the menu; returns whether it is now open. */
|
|
280
|
+
toggle: () => boolean;
|
|
281
|
+
/** Whether the menu is open. */
|
|
282
|
+
isOpen: () => boolean;
|
|
283
|
+
/** Close the menu. */
|
|
284
|
+
close: () => void;
|
|
285
|
+
/** The menu's shadow root (its focusables are navigated). */
|
|
286
|
+
root: ShadowRoot | null;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/** A navigation focus or act event. */
|
|
290
|
+
export interface NavFocusEvent {
|
|
291
|
+
/** The element's id, if it has one. */
|
|
292
|
+
id?: string | undefined;
|
|
293
|
+
/** The DOM element, if any. */
|
|
294
|
+
el?: HTMLElement | undefined;
|
|
295
|
+
/** What it is. */
|
|
296
|
+
kind?: NavElementKind | undefined;
|
|
297
|
+
/** Its index in the list. */
|
|
298
|
+
index: number;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
/** A navigation blur event. */
|
|
302
|
+
export interface NavBlurEvent {
|
|
303
|
+
/** The element's id, if it has one. */
|
|
304
|
+
id?: string | undefined;
|
|
305
|
+
/** Its index in the list. */
|
|
306
|
+
index: number;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
/** Events `hub.input.on` delivers, name → payload. */
|
|
310
|
+
export interface InputEvents {
|
|
311
|
+
/** An element gained the highlight. */
|
|
312
|
+
focus: NavFocusEvent;
|
|
313
|
+
/** An element lost the highlight. */
|
|
314
|
+
blur: NavBlurEvent;
|
|
315
|
+
/** The player activated an element. */
|
|
316
|
+
act: NavFocusEvent;
|
|
317
|
+
/** The active device changed. */
|
|
318
|
+
sourcechange: InputSource;
|
|
319
|
+
/** Reserved. */
|
|
320
|
+
navigate: NavFocusEvent;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
/** Where the input system persists the player's remaps. */
|
|
324
|
+
export interface InputHost {
|
|
325
|
+
/** This page's game slug. */
|
|
326
|
+
readonly slug: string | null;
|
|
327
|
+
/** The saved overrides, or `null`. */
|
|
328
|
+
loadOverrides(): InputOverrides | null;
|
|
329
|
+
/** Save overrides (locally, and to the cloud when signed in). */
|
|
330
|
+
saveOverrides(overrides: InputOverrides): void;
|
|
331
|
+
}
|