@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.
- package/README.md +19 -0
- package/dist/protocol/glyphs.d.ts +7 -0
- package/dist/protocol/glyphs.d.ts.map +1 -1
- package/dist/protocol/glyphs.js +26 -0
- package/dist/protocol/glyphs.js.map +1 -1
- package/dist/protocol/version.d.ts +1 -1
- package/dist/protocol/version.js +1 -1
- package/dist/three/perf-overlay.d.ts +52 -2
- package/dist/three/perf-overlay.d.ts.map +1 -1
- package/dist/three/perf-overlay.js +188 -3
- package/dist/three/perf-overlay.js.map +1 -1
- package/dist/ui/README.md +119 -0
- package/dist/ui/controller/combo-demo.d.ts +74 -0
- package/dist/ui/controller/combo-demo.d.ts.map +1 -0
- package/dist/ui/controller/combo-demo.js +295 -0
- package/dist/ui/controller/combo-demo.js.map +1 -0
- package/dist/ui/controller/combo-strip.d.ts +36 -0
- package/dist/ui/controller/combo-strip.d.ts.map +1 -0
- package/dist/ui/controller/combo-strip.js +66 -0
- package/dist/ui/controller/combo-strip.js.map +1 -0
- package/dist/ui/controller/control-trainer.d.ts +132 -0
- package/dist/ui/controller/control-trainer.d.ts.map +1 -0
- package/dist/ui/controller/control-trainer.js +570 -0
- package/dist/ui/controller/control-trainer.js.map +1 -0
- package/dist/ui/controller/controller-map.d.ts +82 -0
- package/dist/ui/controller/controller-map.d.ts.map +1 -0
- package/dist/ui/controller/controller-map.js +291 -0
- package/dist/ui/controller/controller-map.js.map +1 -0
- package/dist/ui/controller/controller-pad.d.ts +122 -0
- package/dist/ui/controller/controller-pad.d.ts.map +1 -0
- package/dist/ui/controller/controller-pad.js +200 -0
- package/dist/ui/controller/controller-pad.js.map +1 -0
- package/dist/ui/controller/index.d.ts +26 -0
- package/dist/ui/controller/index.d.ts.map +1 -0
- package/dist/ui/controller/index.js +26 -0
- package/dist/ui/controller/index.js.map +1 -0
- package/dist/ui/controller/input-chip.d.ts +100 -0
- package/dist/ui/controller/input-chip.d.ts.map +1 -0
- package/dist/ui/controller/input-chip.js +322 -0
- package/dist/ui/controller/input-chip.js.map +1 -0
- package/dist/ui/controller/layouts/dualsense.d.ts +12 -0
- package/dist/ui/controller/layouts/dualsense.d.ts.map +1 -0
- package/dist/ui/controller/layouts/dualsense.js +64 -0
- package/dist/ui/controller/layouts/dualsense.js.map +1 -0
- package/dist/ui/controller/layouts/index.d.ts +20 -0
- package/dist/ui/controller/layouts/index.d.ts.map +1 -0
- package/dist/ui/controller/layouts/index.js +34 -0
- package/dist/ui/controller/layouts/index.js.map +1 -0
- package/dist/ui/controller/layouts/joycon.d.ts +21 -0
- package/dist/ui/controller/layouts/joycon.d.ts.map +1 -0
- package/dist/ui/controller/layouts/joycon.js +76 -0
- package/dist/ui/controller/layouts/joycon.js.map +1 -0
- package/dist/ui/controller/layouts/switch-pro.d.ts +12 -0
- package/dist/ui/controller/layouts/switch-pro.d.ts.map +1 -0
- package/dist/ui/controller/layouts/switch-pro.js +60 -0
- package/dist/ui/controller/layouts/switch-pro.js.map +1 -0
- package/dist/ui/controller/layouts/xbox.d.ts +11 -0
- package/dist/ui/controller/layouts/xbox.d.ts.map +1 -0
- package/dist/ui/controller/layouts/xbox.js +59 -0
- package/dist/ui/controller/layouts/xbox.js.map +1 -0
- package/dist/ui/controller/layouts/zwift.d.ts +27 -0
- package/dist/ui/controller/layouts/zwift.d.ts.map +1 -0
- package/dist/ui/controller/layouts/zwift.js +62 -0
- package/dist/ui/controller/layouts/zwift.js.map +1 -0
- package/dist/ui/controller/pad-svg.d.ts +105 -0
- package/dist/ui/controller/pad-svg.d.ts.map +1 -0
- package/dist/ui/controller/pad-svg.js +289 -0
- package/dist/ui/controller/pad-svg.js.map +1 -0
- package/dist/ui/controller/parts-map.d.ts +96 -0
- package/dist/ui/controller/parts-map.d.ts.map +1 -0
- package/dist/ui/controller/parts-map.js +187 -0
- package/dist/ui/controller/parts-map.js.map +1 -0
- package/dist/ui/controller/styles.d.ts +19 -0
- package/dist/ui/controller/styles.d.ts.map +1 -0
- package/dist/ui/controller/styles.js +364 -0
- package/dist/ui/controller/styles.js.map +1 -0
- package/dist/ui/controller/tokens.d.ts +106 -0
- package/dist/ui/controller/tokens.d.ts.map +1 -0
- package/dist/ui/controller/tokens.js +50 -0
- package/dist/ui/controller/tokens.js.map +1 -0
- package/dist/ui/controller/types.d.ts +157 -0
- package/dist/ui/controller/types.d.ts.map +1 -0
- package/dist/ui/controller/types.js +61 -0
- package/dist/ui/controller/types.js.map +1 -0
- package/dist/ui/index.d.ts +8 -0
- package/dist/ui/index.d.ts.map +1 -1
- package/dist/ui/index.js +8 -0
- package/dist/ui/index.js.map +1 -1
- package/dist/ui/keycap.d.ts +14 -0
- package/dist/ui/keycap.d.ts.map +1 -1
- package/dist/ui/keycap.js +5 -0
- package/dist/ui/keycap.js.map +1 -1
- package/dist/ui/showcase/gallery.d.ts +13 -1
- package/dist/ui/showcase/gallery.d.ts.map +1 -1
- package/dist/ui/showcase/gallery.js.map +1 -1
- package/dist/ui/showcase/index.d.ts.map +1 -1
- package/dist/ui/showcase/index.js +257 -1
- package/dist/ui/showcase/index.js.map +1 -1
- 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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"}
|