@rydr/game-sdk 7.0.0 → 7.1.0

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.
Files changed (99) hide show
  1. package/README.md +19 -0
  2. package/dist/protocol/glyphs.d.ts +7 -0
  3. package/dist/protocol/glyphs.d.ts.map +1 -1
  4. package/dist/protocol/glyphs.js +26 -0
  5. package/dist/protocol/glyphs.js.map +1 -1
  6. package/dist/protocol/version.d.ts +1 -1
  7. package/dist/protocol/version.js +1 -1
  8. package/dist/three/perf-overlay.d.ts +52 -2
  9. package/dist/three/perf-overlay.d.ts.map +1 -1
  10. package/dist/three/perf-overlay.js +188 -3
  11. package/dist/three/perf-overlay.js.map +1 -1
  12. package/dist/ui/README.md +119 -0
  13. package/dist/ui/controller/combo-demo.d.ts +74 -0
  14. package/dist/ui/controller/combo-demo.d.ts.map +1 -0
  15. package/dist/ui/controller/combo-demo.js +295 -0
  16. package/dist/ui/controller/combo-demo.js.map +1 -0
  17. package/dist/ui/controller/combo-strip.d.ts +36 -0
  18. package/dist/ui/controller/combo-strip.d.ts.map +1 -0
  19. package/dist/ui/controller/combo-strip.js +66 -0
  20. package/dist/ui/controller/combo-strip.js.map +1 -0
  21. package/dist/ui/controller/control-trainer.d.ts +132 -0
  22. package/dist/ui/controller/control-trainer.d.ts.map +1 -0
  23. package/dist/ui/controller/control-trainer.js +570 -0
  24. package/dist/ui/controller/control-trainer.js.map +1 -0
  25. package/dist/ui/controller/controller-map.d.ts +82 -0
  26. package/dist/ui/controller/controller-map.d.ts.map +1 -0
  27. package/dist/ui/controller/controller-map.js +291 -0
  28. package/dist/ui/controller/controller-map.js.map +1 -0
  29. package/dist/ui/controller/controller-pad.d.ts +122 -0
  30. package/dist/ui/controller/controller-pad.d.ts.map +1 -0
  31. package/dist/ui/controller/controller-pad.js +200 -0
  32. package/dist/ui/controller/controller-pad.js.map +1 -0
  33. package/dist/ui/controller/index.d.ts +26 -0
  34. package/dist/ui/controller/index.d.ts.map +1 -0
  35. package/dist/ui/controller/index.js +26 -0
  36. package/dist/ui/controller/index.js.map +1 -0
  37. package/dist/ui/controller/input-chip.d.ts +100 -0
  38. package/dist/ui/controller/input-chip.d.ts.map +1 -0
  39. package/dist/ui/controller/input-chip.js +322 -0
  40. package/dist/ui/controller/input-chip.js.map +1 -0
  41. package/dist/ui/controller/layouts/dualsense.d.ts +12 -0
  42. package/dist/ui/controller/layouts/dualsense.d.ts.map +1 -0
  43. package/dist/ui/controller/layouts/dualsense.js +64 -0
  44. package/dist/ui/controller/layouts/dualsense.js.map +1 -0
  45. package/dist/ui/controller/layouts/index.d.ts +20 -0
  46. package/dist/ui/controller/layouts/index.d.ts.map +1 -0
  47. package/dist/ui/controller/layouts/index.js +34 -0
  48. package/dist/ui/controller/layouts/index.js.map +1 -0
  49. package/dist/ui/controller/layouts/joycon.d.ts +21 -0
  50. package/dist/ui/controller/layouts/joycon.d.ts.map +1 -0
  51. package/dist/ui/controller/layouts/joycon.js +76 -0
  52. package/dist/ui/controller/layouts/joycon.js.map +1 -0
  53. package/dist/ui/controller/layouts/switch-pro.d.ts +12 -0
  54. package/dist/ui/controller/layouts/switch-pro.d.ts.map +1 -0
  55. package/dist/ui/controller/layouts/switch-pro.js +60 -0
  56. package/dist/ui/controller/layouts/switch-pro.js.map +1 -0
  57. package/dist/ui/controller/layouts/xbox.d.ts +11 -0
  58. package/dist/ui/controller/layouts/xbox.d.ts.map +1 -0
  59. package/dist/ui/controller/layouts/xbox.js +59 -0
  60. package/dist/ui/controller/layouts/xbox.js.map +1 -0
  61. package/dist/ui/controller/layouts/zwift.d.ts +27 -0
  62. package/dist/ui/controller/layouts/zwift.d.ts.map +1 -0
  63. package/dist/ui/controller/layouts/zwift.js +62 -0
  64. package/dist/ui/controller/layouts/zwift.js.map +1 -0
  65. package/dist/ui/controller/pad-svg.d.ts +105 -0
  66. package/dist/ui/controller/pad-svg.d.ts.map +1 -0
  67. package/dist/ui/controller/pad-svg.js +289 -0
  68. package/dist/ui/controller/pad-svg.js.map +1 -0
  69. package/dist/ui/controller/parts-map.d.ts +96 -0
  70. package/dist/ui/controller/parts-map.d.ts.map +1 -0
  71. package/dist/ui/controller/parts-map.js +187 -0
  72. package/dist/ui/controller/parts-map.js.map +1 -0
  73. package/dist/ui/controller/styles.d.ts +19 -0
  74. package/dist/ui/controller/styles.d.ts.map +1 -0
  75. package/dist/ui/controller/styles.js +364 -0
  76. package/dist/ui/controller/styles.js.map +1 -0
  77. package/dist/ui/controller/tokens.d.ts +106 -0
  78. package/dist/ui/controller/tokens.d.ts.map +1 -0
  79. package/dist/ui/controller/tokens.js +50 -0
  80. package/dist/ui/controller/tokens.js.map +1 -0
  81. package/dist/ui/controller/types.d.ts +157 -0
  82. package/dist/ui/controller/types.d.ts.map +1 -0
  83. package/dist/ui/controller/types.js +61 -0
  84. package/dist/ui/controller/types.js.map +1 -0
  85. package/dist/ui/index.d.ts +8 -0
  86. package/dist/ui/index.d.ts.map +1 -1
  87. package/dist/ui/index.js +8 -0
  88. package/dist/ui/index.js.map +1 -1
  89. package/dist/ui/keycap.d.ts +14 -0
  90. package/dist/ui/keycap.d.ts.map +1 -1
  91. package/dist/ui/keycap.js +5 -0
  92. package/dist/ui/keycap.js.map +1 -1
  93. package/dist/ui/showcase/gallery.d.ts +13 -1
  94. package/dist/ui/showcase/gallery.d.ts.map +1 -1
  95. package/dist/ui/showcase/gallery.js.map +1 -1
  96. package/dist/ui/showcase/index.d.ts.map +1 -1
  97. package/dist/ui/showcase/index.js +257 -1
  98. package/dist/ui/showcase/index.js.map +1 -1
  99. package/package.json +1 -1
@@ -0,0 +1,570 @@
1
+ /**
2
+ * CONTROL TRAINER — a guided lesson: "here's what to press; now you do it."
3
+ *
4
+ * Where {@link mountComboDemo} only *shows* a combination on a loop, this one **watches the rider** and
5
+ * gates on them actually performing it. It exists for the paired lessons where two related controls have
6
+ * to be taught together — the case that named it being the trainer resistance, which is one concept
7
+ * (`Changer la résistance`) with two opposite halves (`−` and `+`).
8
+ *
9
+ * ```ts
10
+ * mountControlTrainer(modalBody, {
11
+ * title: "Changer la résistance",
12
+ * press: shellInput,
13
+ * steps: [
14
+ * { label: "Réduire la résistance", combo: ["LSTICK_PRESS", "LB"] },
15
+ * { label: "Augmenter la résistance", combo: ["LSTICK_PRESS", "RB"] },
16
+ * ],
17
+ * onComplete: () => closeModal(),
18
+ * });
19
+ * ```
20
+ *
21
+ * Layout: the title, then one panel per step laid left → right, then **one shared controller drawing
22
+ * spanning the full width** underneath. Sharing the drawing is the point — both halves of the lesson are
23
+ * on the same physical pad, and seeing the left paddle and the right paddle light up on one picture is
24
+ * what teaches the pairing.
25
+ *
26
+ * Each step walks three states, and each one has to *look* like what it means:
27
+ *
28
+ * 1. **hint** — whitish, pulsing, on both the panel's chips and the pad's buttons. This is an
29
+ * instruction, so it must not look like a press; the pulse is what separates the two, since a solid
30
+ * fill is what a real press already looks like. The prompt shows **one step at a time, alternating**,
31
+ * and builds each combination up **cumulatively** — the first control lights, STAYS lit, and the next
32
+ * joins it a beat later. Prompting both halves at once would light four controls on one pad and read
33
+ * as "press all of this"; blinking them in turn would never show that they are held together.
34
+ * 2. **active** — the accent colour, and the pulse STOPS. The rider has started but the combination
35
+ * isn't complete yet: on a two-control step this is the state between the first control and the
36
+ * second.
37
+ * 3. **done** — the step's PANEL turns green and its ✓ pops, the moment the WHOLE combination is held.
38
+ * Holding all of it is doing it; there is nothing further to wait for, and it stays done whether or
39
+ * not the rider keeps the controls down.
40
+ *
41
+ * **The controller drawing is never green.** White and blue have already taught the rider that colour on
42
+ * the pad means *now*, so progress there would be a third colour breaking that rule — a green button
43
+ * beside a white one reads as "and this one too". Progress lives on the panels, whose chips picture the
44
+ * same combination one line up, so the confirmation still lands on the controls they just pressed. See
45
+ * `paint` for the two languages.
46
+ *
47
+ * When every step is done, `onComplete` fires after a short beat so the last ✓ is actually seen. The
48
+ * component does not close anything itself — it has no idea it's in a modal. The host owns that, exactly
49
+ * as with every other piece of this kit.
50
+ *
51
+ * ⚠️ **The resistance case needs a shell-side input source.** `LB`/`RB` are shell-owned: the
52
+ * SDK client turns those keys into `trainer.adjustResistance` intents and they never reach a game's
53
+ * `onButton` (see {@link ShellControl}). So a *game* can build a trainer for its own buttons, but a
54
+ * resistance lesson has to be driven by the shell, which is also the only place that lesson belongs.
55
+ */
56
+ import { createComboStrip } from "./combo-strip.js";
57
+ import { mountControllerPad } from "./controller-pad.js";
58
+ import { DPAD_DIRECTIONS, litPartOfControl } from "./parts-map.js";
59
+ import { STICK_LIT_DEADZONE } from "./pad-svg.js";
60
+ import { injectPadCss } from "./styles.js";
61
+ import { isShellControl, parseToken, STICK_DIR_VECTOR } from "./tokens.js";
62
+ const CHECK = "✓";
63
+ /** Is this one of the four directions the d-pad SHARES with the left stick? */
64
+ function isDpadName(name) {
65
+ return name === "UP" || name === "DOWN" || name === "LEFT" || name === "RIGHT";
66
+ }
67
+ /**
68
+ * Demonstration timings, in ms.
69
+ *
70
+ * `REVEAL` is the beat before the NEXT control joins the highlight — the previous ones stay lit, so the
71
+ * rider watches a combination assemble. `HOLD` is how long the finished combination sits there, and `GAP`
72
+ * is a short dark beat before the other step takes its turn, so the switch is legible as a switch rather
73
+ * than as controls mutating.
74
+ */
75
+ const REVEAL_MS = 750;
76
+ const HOLD_MS = 1000;
77
+ const GAP_MS = 380;
78
+ /**
79
+ * How long focus stays on a step that has just been completed, before the rotation moves on.
80
+ *
81
+ * Short, because the pad no longer carries any completion colour of its own — this only stops the next
82
+ * combination's prompt from appearing in the same instant the rider succeeds, which would read as the
83
+ * lesson brushing past them. The ✓ and the green panel do the actual confirming.
84
+ */
85
+ const CELEBRATE_MS = 500;
86
+ /** One out-and-back sweep of a hinted stick cap. Slow enough to read as a gesture, not a twitch. */
87
+ const STICK_HINT_MS = 1400;
88
+ export function mountControlTrainer(host, opts) {
89
+ injectPadCss();
90
+ const root = document.createElement("div");
91
+ root.className = "rydr-padtrainer";
92
+ root.style.setProperty("--rydr-padtrainer-cols", String(Math.max(1, opts.steps.length)));
93
+ const titleEl = document.createElement("h2");
94
+ titleEl.className = "rydr-padtrainer-title";
95
+ titleEl.textContent = opts.title;
96
+ root.appendChild(titleEl);
97
+ const row = document.createElement("div");
98
+ row.className = "rydr-padtrainer-row";
99
+ root.appendChild(row);
100
+ const padCell = document.createElement("div");
101
+ padCell.className = "rydr-padtrainer-pad";
102
+ root.appendChild(padCell);
103
+ host.appendChild(root);
104
+ // Does any step name a shell-owned control? If so the drawing must be allowed to light it — that IS
105
+ // the lesson. Derived rather than asked for, so a caller can't forget it and get a dead highlight.
106
+ const teachesShellOwned = opts.steps.some((s) => s.combo.some((t) => {
107
+ const p = parseToken(t);
108
+ return p.kind === "button" && isShellControl(p.name);
109
+ }));
110
+ // Glyph-only: the lesson owns the drawing's state, so real presses must not write it too. We route
111
+ // them ourselves, into the step states, which then paint the pad.
112
+ const pad = mountControllerPad(padCell, {
113
+ press: opts.press && { onButton: () => () => { }, hardware: opts.press.hardware },
114
+ brand: opts.brand,
115
+ glyphSet: opts.glyphSet,
116
+ size: opts.size ?? "lg",
117
+ labels: opts.labels,
118
+ accent: opts.accent,
119
+ allowShellOwned: teachesShellOwned,
120
+ });
121
+ let steps = [];
122
+ let finished = false;
123
+ let completionTimer;
124
+ /** Which step is currently being demonstrated. Rotates among the unfinished ones. */
125
+ let focus = 0;
126
+ /** How many of the focused step's controls are lit right now. Grows; never shrinks mid-step. */
127
+ let reveal = 1;
128
+ /** ms elapsed in the current step's demonstration. */
129
+ let promptT = 0;
130
+ /**
131
+ * Free-running clock for the stick hint gesture. A button prompt pulses via CSS, but a stick cap
132
+ * can't — a cap parked at full deflection would read as "already done". So a hinted stick SWEEPS out
133
+ * and back, which is unmistakably an instruction. Never reset, so the motion stays smooth across
134
+ * step changes.
135
+ */
136
+ let hintPhase = 0;
137
+ /** A step just completed: hold focus on it briefly so its green is actually seen. -1 = none. */
138
+ let celebrateIdx = -1;
139
+ let celebrateT = 0;
140
+ /** Every part any step touches, so `paint` can turn OFF the ones no longer being prompted. */
141
+ let allParts = [];
142
+ /**
143
+ * Every part this lesson has ever written, lesson control or not.
144
+ *
145
+ * The pad reflects ANY press, not just the ones the lesson is about — a rider pressing a button and
146
+ * seeing the drawing ignore it reads as broken, whatever the lesson happens to be teaching. Those
147
+ * extra parts aren't in `allParts`, so without remembering them a released one would never be set
148
+ * back to "off" and would stay lit for good.
149
+ */
150
+ const writtenParts = new Set();
151
+ function buildSteps() {
152
+ for (const s of steps) {
153
+ s.strip.dispose();
154
+ s.panel.remove();
155
+ }
156
+ row.textContent = "";
157
+ steps = opts.steps.map((spec) => {
158
+ const panel = document.createElement("div");
159
+ panel.className = "rydr-padtrainer-step";
160
+ const head = document.createElement("div");
161
+ head.className = "rydr-padtrainer-head";
162
+ const label = document.createElement("div");
163
+ label.className = "rydr-padtrainer-label";
164
+ label.textContent = spec.label;
165
+ const check = document.createElement("span");
166
+ check.className = "rydr-padtrainer-check";
167
+ check.textContent = CHECK;
168
+ check.setAttribute("aria-hidden", "true");
169
+ head.append(label, check);
170
+ panel.appendChild(head);
171
+ if (spec.hint) {
172
+ const hint = document.createElement("div");
173
+ hint.className = "rydr-padtrainer-hint";
174
+ hint.textContent = spec.hint;
175
+ panel.appendChild(hint);
176
+ }
177
+ const strip = createComboStrip({ label: spec.label, combo: spec.combo, sequence: spec.sequence }, { glyphSet: opts.glyphSet ?? pad.glyphSet(), colored: opts.colored, stickStyle: opts.stickStyle });
178
+ panel.appendChild(strip.el);
179
+ row.appendChild(panel);
180
+ return {
181
+ spec,
182
+ strip,
183
+ panel,
184
+ check,
185
+ parts: spec.combo.map((t) => {
186
+ const p = parseToken(t);
187
+ return p.kind === "button" ? litPartOfControl(p.name) : undefined;
188
+ }),
189
+ sticks: spec.combo.map((t) => {
190
+ const p = parseToken(t);
191
+ if (p.kind !== "stick")
192
+ return undefined;
193
+ return {
194
+ side: p.stick === "LSTICK" ? "l" : "r",
195
+ vec: p.dir ? STICK_DIR_VECTOR[p.dir] : null, // null = any direction
196
+ };
197
+ }),
198
+ engaged: spec.combo.map(() => false),
199
+ progress: 0,
200
+ state: "hint",
201
+ };
202
+ });
203
+ // Every part any step touches. `paint` needs the full set so it can turn OFF the controls that are
204
+ // no longer being prompted — without it, the previous step's highlights would linger after the
205
+ // rotation moved on, which is precisely the "press all of this" confusion the rotation exists to avoid.
206
+ allParts = [...new Set(steps.flatMap((s) => s.parts.filter((p) => p != null)))];
207
+ }
208
+ /**
209
+ * Advance the demonstration by `dt` ms.
210
+ *
211
+ * Frozen while the rider is mid-attempt: once they're engaged, focus locks to the step they're
212
+ * attempting and the reveal stops moving. Nothing needs to be demonstrated to someone who has already
213
+ * started, and a prompt that kept cycling underneath them would fight their own feedback.
214
+ */
215
+ function advance(dt) {
216
+ // The dwell comes FIRST, ahead of the busy check — including the rider still holding controls. It has
217
+ // to: the two halves share the stick click, so the moment one half completes the OTHER half is
218
+ // technically already in progress (its stick click is down). Letting that claim focus would put the
219
+ // next combination's prompt on screen in the same frame the rider succeeded.
220
+ if (celebrateIdx >= 0) {
221
+ focus = celebrateIdx;
222
+ celebrateT += dt;
223
+ if (celebrateT < CELEBRATE_MS)
224
+ return;
225
+ celebrateIdx = -1;
226
+ celebrateT = 0;
227
+ promptT = 0;
228
+ reveal = 1;
229
+ }
230
+ // Two steps that SHARE a control both go active the instant it's held, so "which one are they
231
+ // attempting?" is genuinely ambiguous. Resolve it by furthest-along: the step with the most controls
232
+ // engaged wins, ties to the earlier one. Pressing the shoulder then settles it immediately.
233
+ let busyIdx = -1;
234
+ let bestEngaged = 0;
235
+ steps.forEach((s, i) => {
236
+ if (s.state !== "active")
237
+ return;
238
+ const n = s.engaged.filter(Boolean).length;
239
+ if (n > bestEngaged) {
240
+ bestEngaged = n;
241
+ busyIdx = i;
242
+ }
243
+ });
244
+ if (busyIdx >= 0) {
245
+ focus = busyIdx;
246
+ promptT = 0;
247
+ reveal = steps[busyIdx]?.spec.combo.length ?? 1;
248
+ return;
249
+ }
250
+ const pending = steps.map((s, i) => (s.state === "done" ? -1 : i)).filter((i) => i >= 0);
251
+ if (pending.length === 0)
252
+ return;
253
+ if (!pending.includes(focus)) {
254
+ focus = pending[0];
255
+ promptT = 0;
256
+ }
257
+ const step = steps[focus];
258
+ if (!step)
259
+ return;
260
+ const n = Math.max(1, step.spec.combo.length);
261
+ const cycle = n * REVEAL_MS + HOLD_MS + GAP_MS;
262
+ promptT += dt;
263
+ if (promptT >= cycle) {
264
+ // Hand over to the next unfinished step — the "alternance" between the two halves.
265
+ promptT = 0;
266
+ const at = pending.indexOf(focus);
267
+ focus = pending[(at + 1) % pending.length];
268
+ reveal = 1;
269
+ return;
270
+ }
271
+ // The dark beat at the end of a cycle: nothing lit, so the switch reads as a switch.
272
+ if (promptT > n * REVEAL_MS + HOLD_MS) {
273
+ reveal = 0;
274
+ return;
275
+ }
276
+ reveal = Math.min(n, 1 + Math.floor(promptT / REVEAL_MS));
277
+ }
278
+ /**
279
+ * Push every step's state onto its panel, its chips and the shared drawing.
280
+ *
281
+ * Three rules do the work here:
282
+ *
283
+ * 1. **Only ONE step prompts at a time** (`focus`), and it rotates. Prompting both halves of a paired
284
+ * lesson at once lights four controls simultaneously on one pad, which reads as "press all of this"
285
+ * rather than as two alternatives.
286
+ * 2. **Within a step the reveal ACCUMULATES.** The first control lights, stays lit, and the next joins
287
+ * it a beat later — so the rider sees a combination being built, not two controls blinking. The
288
+ * whole point of `reveal` is that earlier controls do not turn off.
289
+ * 3. **The two surfaces speak different languages, and neither borrows the other's.**
290
+ *
291
+ * the PAD — physical: white = *press this*, blue = *you are pressing it*. Never green.
292
+ * the PANELS — logical: grey = *to do*, green + ✓ = *done*, and it stays.
293
+ *
294
+ * The pad is where the rider looks to find a button, and white/blue have already taught them that
295
+ * colour there means *now*. Putting progress on it as a third colour breaks that rule — a green
296
+ * button beside a white one reads as "and this one too". Progress belongs on the panels, whose chips
297
+ * are a picture of the very same combination one line up, so the confirmation still lands on the
298
+ * controls the rider just pressed.
299
+ *
300
+ * This is also why nothing special happens to the pad at completion: blue simply persists while the
301
+ * controls are held and clears when they let go, because that is the truth of the hardware.
302
+ */
303
+ function paint() {
304
+ const wanted = new Map();
305
+ for (const part of allParts)
306
+ wanted.set(part, "off");
307
+ for (const part of writtenParts)
308
+ wanted.set(part, "off");
309
+ /** A chip's state — the LOGICAL language, so this one does carry `done`. */
310
+ const chipStateOf = (step, i, focused) => {
311
+ if (step.state === "done")
312
+ return "done";
313
+ // Only the focused step is shown. Two steps sharing a control BOTH go active the instant it's held,
314
+ // and without this the alternative half would light up underneath the one being attempted.
315
+ if (!focused)
316
+ return "idle";
317
+ if (step.engaged[i])
318
+ return "active";
319
+ // Mid-attempt: show everything still missing at once. The rider has already started, so there is
320
+ // nothing left to attract them — what they need is "you have that one, now add this".
321
+ if (step.state === "active")
322
+ return "hint";
323
+ return reduceMotion || i < reveal ? "hint" : "idle";
324
+ };
325
+ steps.forEach((step, index) => {
326
+ const focused = reduceMotion || index === focus;
327
+ step.panel.classList.toggle("active", step.state === "active");
328
+ step.panel.classList.toggle("done", step.state === "done");
329
+ step.panel.classList.toggle("focus", focused && step.state === "hint");
330
+ step.check.classList.toggle("show", step.state === "done");
331
+ if (step.spec.sequence)
332
+ step.strip.setStep(step.state === "done" ? step.spec.combo.length : step.progress);
333
+ step.spec.combo.forEach((_token, i) => step.strip.chips[i]?.setState(chipStateOf(step, i, focused)));
334
+ });
335
+ // Pass 1 — the prompt: the focused, unfinished step's controls, as far as the reveal has got.
336
+ const stickWant = {};
337
+ steps.forEach((step, index) => {
338
+ const focused = reduceMotion || index === focus;
339
+ if (!focused || step.state === "done")
340
+ return;
341
+ step.spec.combo.forEach((_t, i) => {
342
+ const shown = step.state === "active" || reduceMotion || i < reveal;
343
+ const part = step.parts[i];
344
+ if (part && shown)
345
+ wanted.set(part, "hint");
346
+ // A stick token has no part to light, so demonstrate it by MOVING the cap. Parked at full
347
+ // deflection it would read as "already done", so it sweeps out and back — an instruction, not a
348
+ // state. Skipped once the rider engages that stick: pass 2 then shows their real position.
349
+ const stick = step.sticks[i];
350
+ if (!stick || !shown || step.engaged[i])
351
+ return;
352
+ // Under reduced motion the loop never runs, so `hintPhase` is frozen at 0 — park the cap at a
353
+ // clearly-deflected position instead of the sweep's starting point.
354
+ const sweep = reduceMotion
355
+ ? 0.85
356
+ : 0.35 + 0.65 * (0.5 - 0.5 * Math.cos((hintPhase / STICK_HINT_MS) * Math.PI * 2));
357
+ if (stick.vec) {
358
+ stickWant[stick.side] = { x: stick.vec[0] * sweep, y: stick.vec[1] * sweep, lit: "hint" };
359
+ }
360
+ else {
361
+ // "Any direction" — walk the cap around its circle rather than picking one.
362
+ const a = (hintPhase / STICK_HINT_MS) * Math.PI * 2;
363
+ stickWant[stick.side] = { x: Math.cos(a) * 0.8, y: Math.sin(a) * 0.8, lit: "hint" };
364
+ }
365
+ });
366
+ });
367
+ // Pass 2 — what is actually HELD, which outranks any prompt, from ANY step including a finished one.
368
+ // The pad reports the hardware: if a control is down it is blue, and that stays true after the step
369
+ // it belongs to has been completed.
370
+ // Pass 2 — the hardware. EVERY held control goes blue, whether or not the lesson mentions it: the
371
+ // pad is a picture of the controller, and a press it ignores looks like a fault.
372
+ const axis = opts.press?.axis;
373
+ const lx = axis?.("LX") ?? 0;
374
+ const ly = axis?.("LY") ?? 0;
375
+ for (const name of held) {
376
+ // UP/DOWN/LEFT/RIGHT come from the d-pad AND from the left stick past its deadzone (see
377
+ // protocol/buttons.ts) — nothing in the canonical stream says which. So when the axes already
378
+ // explain a direction, DON'T light the d-pad: the stick's own cap is the truthful picture, and
379
+ // lighting both makes it look like the rider is pressing a d-pad they never touched.
380
+ // `mountControllerPad` has always done this; the "reflect everything" pass added here skipped it.
381
+ if (axis && isDpadName(name)) {
382
+ const [vx, vy] = DPAD_DIRECTIONS[name];
383
+ if (lx * vx + ly * vy > STICK_LIT_DEADZONE)
384
+ continue;
385
+ }
386
+ const part = litPartOfControl(name);
387
+ if (part)
388
+ wanted.set(part, "on");
389
+ }
390
+ // Both sticks, live, for the same reason — and this overrides any demonstration on that side.
391
+ if (axis) {
392
+ for (const side of ["l", "r"]) {
393
+ const x = axis(side === "l" ? "LX" : "RX");
394
+ const y = axis(side === "l" ? "LY" : "RY");
395
+ if (Math.hypot(x, y) > STICK_LIT_DEADZONE)
396
+ stickWant[side] = { x, y, lit: "on" };
397
+ }
398
+ }
399
+ const driver = pad.driver();
400
+ for (const [part, state] of wanted) {
401
+ driver.setPartState(part, state);
402
+ if (state !== "off")
403
+ writtenParts.add(part);
404
+ }
405
+ // Every stick every frame: a side with nothing to say must be recentred, or a demonstration would
406
+ // leave the cap parked where the previous step pushed it.
407
+ for (const side of ["l", "r"]) {
408
+ const v = stickWant[side];
409
+ driver.setStick(side, v?.x ?? 0, v?.y ?? 0, v?.lit ?? "off");
410
+ }
411
+ }
412
+ /** Is one token satisfied right now? */
413
+ function tokenEngaged(token, held) {
414
+ const t = parseToken(token);
415
+ if (t.kind === "button")
416
+ return held.has(t.name);
417
+ const axis = opts.press?.axis;
418
+ if (!axis)
419
+ return false;
420
+ const x = axis(t.stick === "LSTICK" ? "LX" : "RX");
421
+ const y = axis(t.stick === "LSTICK" ? "LY" : "RY");
422
+ if (!t.dir)
423
+ return Math.hypot(x, y) > STICK_LIT_DEADZONE;
424
+ const [vx, vy] = STICK_DIR_VECTOR[t.dir];
425
+ return x * vx + y * vy > STICK_LIT_DEADZONE;
426
+ }
427
+ const held = new Set();
428
+ /**
429
+ * Recompute every step from the current input, then repaint.
430
+ *
431
+ * A step is DONE the moment its whole combination is satisfied — holding all of it *is* doing it, so
432
+ * there is nothing further to wait for. (An earlier version also required a release, to guarantee a
433
+ * visible blue phase on a one-control step. That was the wrong trade: it left a rider who was holding
434
+ * the combination correctly staring at blue, with no way to tell whether they had got it right.)
435
+ *
436
+ * Blue still appears wherever it means something: on a multi-control combination it is the state
437
+ * between the first control and the last.
438
+ */
439
+ function evaluate() {
440
+ let changed = false;
441
+ for (const step of steps) {
442
+ // Engagement is tracked for EVERY step, including finished ones. `paint`'s "what's held" pass reads
443
+ // it to keep the pad honest about the hardware, and if a done step stopped updating, its controls
444
+ // would stay frozen as held and sit blue on the drawing forever.
445
+ const engaged = step.spec.combo.map((t) => tokenEngaged(t, held));
446
+ if (engaged.some((v, i) => v !== step.engaged[i]))
447
+ changed = true;
448
+ step.engaged = engaged;
449
+ // …but a completed step's STATE is final. Only its engagement keeps moving.
450
+ if (step.state === "done")
451
+ continue;
452
+ let satisfied;
453
+ if (step.spec.sequence) {
454
+ // Advance one control at a time; a press out of order is ignored rather than punished.
455
+ const next = step.spec.combo[step.progress];
456
+ if (next != null && engaged[step.progress]) {
457
+ step.progress++;
458
+ changed = true;
459
+ }
460
+ satisfied = step.progress >= step.spec.combo.length;
461
+ }
462
+ else {
463
+ satisfied = engaged.every(Boolean);
464
+ }
465
+ // "Busy" = mid-attempt: holding something, or part-way through a sequence but not finished.
466
+ const midSequence = step.spec.sequence === true && step.progress > 0 && !satisfied;
467
+ const busy = engaged.some(Boolean) || midSequence;
468
+ const nextState = satisfied ? "done" : busy ? "active" : "hint";
469
+ if (nextState !== step.state) {
470
+ step.state = nextState;
471
+ changed = true;
472
+ if (nextState === "done") {
473
+ celebrateIdx = steps.indexOf(step);
474
+ celebrateT = 0;
475
+ opts.onStepComplete?.(step.spec, celebrateIdx);
476
+ }
477
+ }
478
+ }
479
+ if (changed)
480
+ paint();
481
+ if (!finished && steps.length > 0 && steps.every((s) => s.state === "done")) {
482
+ finished = true;
483
+ completionTimer = setTimeout(() => opts.onComplete?.(), opts.completionDelayMs ?? 900);
484
+ }
485
+ }
486
+ const offButton = opts.press?.onButton((e) => {
487
+ if (e.edge === "down")
488
+ held.add(e.name);
489
+ else
490
+ held.delete(e.name);
491
+ evaluate();
492
+ });
493
+ // ── the demonstration loop ──────────────────────────────────────────────────────────────────────
494
+ // It drives the rotating reveal, and doubles as the poll for stick tokens (sticks have no event). The
495
+ // driver's dirty-guard means a frame that changes nothing writes nothing.
496
+ const reduceMotion = typeof matchMedia === "function" && matchMedia("(prefers-reduced-motion: reduce)").matches;
497
+ let raf = 0;
498
+ let lastTs = 0;
499
+ function frame(ts) {
500
+ raf = requestAnimationFrame(frame);
501
+ const dt = lastTs ? Math.min(120, ts - lastTs) : 0;
502
+ lastTs = ts;
503
+ hintPhase += dt;
504
+ advance(dt);
505
+ evaluate();
506
+ paint();
507
+ }
508
+ const onVisibility = () => {
509
+ if (document.visibilityState === "hidden") {
510
+ if (raf)
511
+ cancelAnimationFrame(raf);
512
+ raf = 0;
513
+ }
514
+ else if (!reduceMotion && !raf) {
515
+ lastTs = 0;
516
+ raf = requestAnimationFrame(frame);
517
+ }
518
+ };
519
+ if (!reduceMotion) {
520
+ raf = requestAnimationFrame(frame);
521
+ document.addEventListener("visibilitychange", onVisibility);
522
+ }
523
+ // Rebuild the chips when the rider swaps pads — the drawing already re-letters itself.
524
+ const offRebuild = pad.onRebuild(() => {
525
+ const wasDone = steps.map((s) => s.state === "done");
526
+ buildSteps();
527
+ steps.forEach((s, i) => {
528
+ // A pad swap must not cost the rider progress they already earned.
529
+ if (wasDone[i])
530
+ s.state = "done";
531
+ });
532
+ paint();
533
+ });
534
+ buildSteps();
535
+ paint();
536
+ return {
537
+ root,
538
+ pad,
539
+ completed: () => steps.map((s) => s.state === "done"),
540
+ reset() {
541
+ if (completionTimer)
542
+ clearTimeout(completionTimer);
543
+ completionTimer = undefined;
544
+ finished = false;
545
+ celebrateIdx = -1;
546
+ celebrateT = 0;
547
+ focus = 0;
548
+ reveal = 1;
549
+ promptT = 0;
550
+ held.clear();
551
+ pad.driver().clearAll();
552
+ buildSteps();
553
+ paint();
554
+ },
555
+ dispose() {
556
+ offButton?.();
557
+ offRebuild();
558
+ if (completionTimer)
559
+ clearTimeout(completionTimer);
560
+ if (raf)
561
+ cancelAnimationFrame(raf);
562
+ document.removeEventListener("visibilitychange", onVisibility);
563
+ for (const s of steps)
564
+ s.strip.dispose();
565
+ pad.dispose();
566
+ root.remove();
567
+ },
568
+ };
569
+ }
570
+ //# sourceMappingURL=control-trainer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"control-trainer.js","sourceRoot":"","sources":["../../../src/ui/controller/control-trainer.ts"],"names":[],"mappings":"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"}