@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,200 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CONTROLLER PAD — the live drawing of the controller in the rider's hands.
|
|
3
|
+
*
|
|
4
|
+
* ```ts
|
|
5
|
+
* const pad = mountControllerPad(host, { press: session, size: "lg" });
|
|
6
|
+
* // …buttons light as they're pressed, stick caps follow the real axes. Nothing to call per frame.
|
|
7
|
+
* pad.dispose();
|
|
8
|
+
* ```
|
|
9
|
+
*
|
|
10
|
+
* This is the game-side counterpart of the shell's own controller diagram, and it is deliberately fed by
|
|
11
|
+
* **canonical input, not raw hardware**: a game never sees gamepad indices, per-device bindings or analog
|
|
12
|
+
* trigger travel, so this module translates `ButtonName` → drawn position (`parts-map.ts`) and polls
|
|
13
|
+
* `session.axis()` for the sticks. Three consequences worth knowing:
|
|
14
|
+
*
|
|
15
|
+
* 1. **Axes are polled, buttons are not.** `onButton` is an edge stream, so presses cost nothing between
|
|
16
|
+
* events; axes have no event, so when the source exposes `axis()` the pad runs its own
|
|
17
|
+
* `requestAnimationFrame` loop. It stops on `dispose()` and while the tab is hidden, and the
|
|
18
|
+
* `PadDriver` dirty-guard means an idle stick performs zero DOM writes per frame.
|
|
19
|
+
*
|
|
20
|
+
* 2. **The d-pad is shared with the left stick.** `UP`/`DOWN`/`LEFT`/`RIGHT` are emitted by the d-pad
|
|
21
|
+
* *and* by the left stick past its deadzone (see `protocol/buttons.ts`), and nothing in the canonical
|
|
22
|
+
* stream says which. When `axis()` is available we suppress the d-pad highlight for a direction the
|
|
23
|
+
* stick already explains — so pushing the stick moves the cap instead of falsely lighting the d-pad.
|
|
24
|
+
* Without `axis()` the d-pad lights for both, which is the honest best we can do.
|
|
25
|
+
*
|
|
26
|
+
* 3. **Triggers are clicks.** `LT`/`RT` have no analog travel in this protocol, so their travel meters
|
|
27
|
+
* are driven 0/1 from button state.
|
|
28
|
+
*
|
|
29
|
+
* It also **re-letters itself.** A keycap resolves its glyph set once, on the reasoning that keycaps are
|
|
30
|
+
* cheap to recreate; a controls screen is long-lived and `/hardware` is exactly where a rider swaps pads.
|
|
31
|
+
* So if the source exposes `hardware.subscribe`, the pad rebuilds its drawing in place when the resolved
|
|
32
|
+
* set changes, restoring anything currently held. Callers keep their handle and need to know nothing.
|
|
33
|
+
*/
|
|
34
|
+
import { DEFAULT_GLYPH_SET } from "../../protocol/glyphs.js";
|
|
35
|
+
import { layoutForBrand } from "./layouts/index.js";
|
|
36
|
+
import { DPAD_DIRECTIONS, litPartOfButton, litPartOfControl } from "./parts-map.js";
|
|
37
|
+
import { buildPadSvg, createPadDriver, STICK_LIT_DEADZONE } from "./pad-svg.js";
|
|
38
|
+
import { injectPadCss } from "./styles.js";
|
|
39
|
+
const DPAD_NAMES = ["UP", "DOWN", "LEFT", "RIGHT"];
|
|
40
|
+
/** Explicit option → what the rider's hardware reports → the SDK-wide fallback. */
|
|
41
|
+
function resolveGlyphSet(opts) {
|
|
42
|
+
return opts.glyphSet ?? opts.press?.hardware?.current?.glyphSet ?? DEFAULT_GLYPH_SET;
|
|
43
|
+
}
|
|
44
|
+
export function mountControllerPad(host, opts = {}) {
|
|
45
|
+
injectPadCss();
|
|
46
|
+
const root = document.createElement("div");
|
|
47
|
+
root.className = `rydr-pad ${opts.size ?? "md"}${opts.ghost ? " ghost" : ""}`;
|
|
48
|
+
if (opts.accent) {
|
|
49
|
+
root.style.setProperty("--pad-accent", opts.accent);
|
|
50
|
+
root.style.setProperty("--pad-glow", opts.accent);
|
|
51
|
+
}
|
|
52
|
+
host.appendChild(root);
|
|
53
|
+
const live = !opts.ghost && opts.press != null;
|
|
54
|
+
const source = opts.press;
|
|
55
|
+
const hasAxis = live && typeof source?.axis === "function";
|
|
56
|
+
/** Everything currently held, so a rebuild can restore the lit state rather than dropping it. */
|
|
57
|
+
const held = new Set();
|
|
58
|
+
const rebuildCbs = new Set();
|
|
59
|
+
let glyphSet = resolveGlyphSet(opts);
|
|
60
|
+
let pad;
|
|
61
|
+
let driver;
|
|
62
|
+
let layout;
|
|
63
|
+
const availableParts = () => {
|
|
64
|
+
if (!opts.available)
|
|
65
|
+
return null;
|
|
66
|
+
const parts = [];
|
|
67
|
+
for (const name of opts.available) {
|
|
68
|
+
const part = litPartOfButton(name);
|
|
69
|
+
if (part)
|
|
70
|
+
parts.push(part);
|
|
71
|
+
}
|
|
72
|
+
return parts;
|
|
73
|
+
};
|
|
74
|
+
function build() {
|
|
75
|
+
layout = layoutForBrand(opts.brand ?? glyphSet);
|
|
76
|
+
pad = buildPadSvg(layout, { labels: opts.labels ?? true });
|
|
77
|
+
driver = createPadDriver(pad, layout, { allowShellOwned: opts.allowShellOwned });
|
|
78
|
+
root.textContent = "";
|
|
79
|
+
root.appendChild(pad.svg);
|
|
80
|
+
driver.setAvailable(availableParts());
|
|
81
|
+
}
|
|
82
|
+
build();
|
|
83
|
+
/**
|
|
84
|
+
* Apply one button's state to the drawing.
|
|
85
|
+
*
|
|
86
|
+
* The d-pad directions are skipped when we have axes, because the rAF loop is then their single
|
|
87
|
+
* writer — it has to be, since only it knows whether the left stick is explaining the direction. Two
|
|
88
|
+
* writers on the same part would fight every frame.
|
|
89
|
+
*/
|
|
90
|
+
function applyButton(name, down) {
|
|
91
|
+
if (hasAxis && DPAD_NAMES.includes(name))
|
|
92
|
+
return;
|
|
93
|
+
const part = litPartOfControl(name);
|
|
94
|
+
if (part)
|
|
95
|
+
driver.setPart(part, down);
|
|
96
|
+
if (name === "LT")
|
|
97
|
+
driver.setMeter("l", down ? 1 : 0);
|
|
98
|
+
if (name === "RT")
|
|
99
|
+
driver.setMeter("r", down ? 1 : 0);
|
|
100
|
+
}
|
|
101
|
+
function applyAllHeld() {
|
|
102
|
+
for (const name of held)
|
|
103
|
+
applyButton(name, true);
|
|
104
|
+
}
|
|
105
|
+
const offButton = live
|
|
106
|
+
? source?.onButton((e) => {
|
|
107
|
+
if (e.edge === "down")
|
|
108
|
+
held.add(e.name);
|
|
109
|
+
else
|
|
110
|
+
held.delete(e.name);
|
|
111
|
+
applyButton(e.name, e.edge === "down");
|
|
112
|
+
})
|
|
113
|
+
: undefined;
|
|
114
|
+
// Seed from whatever is already held, so mounting mid-press shows the truth immediately.
|
|
115
|
+
if (live && source?.buttonsDown) {
|
|
116
|
+
for (const name of source.buttonsDown())
|
|
117
|
+
held.add(name);
|
|
118
|
+
applyAllHeld();
|
|
119
|
+
}
|
|
120
|
+
// ── axis polling ────────────────────────────────────────────────────────────────────────────────
|
|
121
|
+
let raf = 0;
|
|
122
|
+
function frame() {
|
|
123
|
+
raf = requestAnimationFrame(frame);
|
|
124
|
+
const axis = source?.axis;
|
|
125
|
+
if (!axis)
|
|
126
|
+
return;
|
|
127
|
+
const lx = axis("LX");
|
|
128
|
+
const ly = axis("LY");
|
|
129
|
+
driver.setStick("l", lx, ly);
|
|
130
|
+
driver.setStick("r", axis("RX"), axis("RY"));
|
|
131
|
+
// The suppression rule: light a d-pad arm only if it's held AND the left stick isn't already
|
|
132
|
+
// showing that direction (projection of the stick vector onto the direction, past the deadzone).
|
|
133
|
+
for (const name of DPAD_NAMES) {
|
|
134
|
+
const [vx, vy] = DPAD_DIRECTIONS[name];
|
|
135
|
+
const explained = lx * vx + ly * vy > STICK_LIT_DEADZONE;
|
|
136
|
+
const part = litPartOfButton(name);
|
|
137
|
+
if (part)
|
|
138
|
+
driver.setPart(part, held.has(name) && !explained);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
function startFrames() {
|
|
142
|
+
if (hasAxis && !raf)
|
|
143
|
+
raf = requestAnimationFrame(frame);
|
|
144
|
+
}
|
|
145
|
+
function stopFrames() {
|
|
146
|
+
if (raf)
|
|
147
|
+
cancelAnimationFrame(raf);
|
|
148
|
+
raf = 0;
|
|
149
|
+
}
|
|
150
|
+
const onVisibility = () => {
|
|
151
|
+
if (document.visibilityState === "hidden")
|
|
152
|
+
stopFrames();
|
|
153
|
+
else
|
|
154
|
+
startFrames();
|
|
155
|
+
};
|
|
156
|
+
if (hasAxis) {
|
|
157
|
+
startFrames();
|
|
158
|
+
document.addEventListener("visibilitychange", onVisibility);
|
|
159
|
+
}
|
|
160
|
+
// ── re-lettering ────────────────────────────────────────────────────────────────────────────────
|
|
161
|
+
// Only when the caller did NOT pin a glyph set: an explicit one is a deliberate preview.
|
|
162
|
+
const offHardware = !opts.glyphSet && live
|
|
163
|
+
? source?.hardware?.subscribe?.((snapshot) => {
|
|
164
|
+
const next = snapshot.glyphSet ?? DEFAULT_GLYPH_SET;
|
|
165
|
+
if (next === glyphSet)
|
|
166
|
+
return; // a second pad of the same family is a non-event
|
|
167
|
+
glyphSet = next;
|
|
168
|
+
build();
|
|
169
|
+
applyAllHeld();
|
|
170
|
+
for (const cb of rebuildCbs)
|
|
171
|
+
cb();
|
|
172
|
+
})
|
|
173
|
+
: undefined;
|
|
174
|
+
return {
|
|
175
|
+
root,
|
|
176
|
+
svg: () => pad,
|
|
177
|
+
driver: () => driver,
|
|
178
|
+
layout: () => layout,
|
|
179
|
+
glyphSet: () => glyphSet,
|
|
180
|
+
onRebuild(cb) {
|
|
181
|
+
rebuildCbs.add(cb);
|
|
182
|
+
return () => rebuildCbs.delete(cb);
|
|
183
|
+
},
|
|
184
|
+
setVisible(on) {
|
|
185
|
+
root.style.display = on ? "" : "none";
|
|
186
|
+
},
|
|
187
|
+
dispose() {
|
|
188
|
+
offButton?.();
|
|
189
|
+
offHardware?.();
|
|
190
|
+
stopFrames();
|
|
191
|
+
document.removeEventListener("visibilitychange", onVisibility);
|
|
192
|
+
// Release everything before detaching: a button held at teardown must never leave a lit pad
|
|
193
|
+
// behind if the caller re-parents or re-mounts the node.
|
|
194
|
+
driver.clearAll();
|
|
195
|
+
rebuildCbs.clear();
|
|
196
|
+
root.remove();
|
|
197
|
+
},
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
//# sourceMappingURL=controller-pad.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"controller-pad.js","sourceRoot":"","sources":["../../../src/ui/controller/controller-pad.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The controller family of `@rydr/game-sdk/ui` — one drawing of the rider's controller, and the two
|
|
3
|
+
* views built on it.
|
|
4
|
+
*
|
|
5
|
+
* mountControllerPad the live pad: buttons light on press, stick caps follow the real axes
|
|
6
|
+
* mountControllerMap STATIC — the pad flanked by action callouts, each joined by a line to its button
|
|
7
|
+
* mountComboDemo DYNAMIC — a looping animation of the combination one action requires
|
|
8
|
+
*
|
|
9
|
+
* A game describes its controls once, declaratively, and the SDK owns everything else — which physical
|
|
10
|
+
* button that is on the rider's pad, the letter printed on it, where the callout sits, how the line
|
|
11
|
+
* routes, and how the demo animates. See `tokens.ts` for the vocabulary and `parts-map.ts` for the
|
|
12
|
+
* positional mapping that makes one action list correct on every controller.
|
|
13
|
+
*/
|
|
14
|
+
export * from "./types.js";
|
|
15
|
+
export * from "./tokens.js";
|
|
16
|
+
export * from "./parts-map.js";
|
|
17
|
+
export * from "./layouts/index.js";
|
|
18
|
+
export * from "./pad-svg.js";
|
|
19
|
+
export * from "./input-chip.js";
|
|
20
|
+
export * from "./combo-strip.js";
|
|
21
|
+
export * from "./controller-pad.js";
|
|
22
|
+
export * from "./controller-map.js";
|
|
23
|
+
export * from "./combo-demo.js";
|
|
24
|
+
export * from "./control-trainer.js";
|
|
25
|
+
export { injectPadCss } from "./styles.js";
|
|
26
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/ui/controller/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,oBAAoB,CAAC;AACnC,cAAc,cAAc,CAAC;AAC7B,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,iBAAiB,CAAC;AAChC,cAAc,sBAAsB,CAAC;AACrC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The controller family of `@rydr/game-sdk/ui` — one drawing of the rider's controller, and the two
|
|
3
|
+
* views built on it.
|
|
4
|
+
*
|
|
5
|
+
* mountControllerPad the live pad: buttons light on press, stick caps follow the real axes
|
|
6
|
+
* mountControllerMap STATIC — the pad flanked by action callouts, each joined by a line to its button
|
|
7
|
+
* mountComboDemo DYNAMIC — a looping animation of the combination one action requires
|
|
8
|
+
*
|
|
9
|
+
* A game describes its controls once, declaratively, and the SDK owns everything else — which physical
|
|
10
|
+
* button that is on the rider's pad, the letter printed on it, where the callout sits, how the line
|
|
11
|
+
* routes, and how the demo animates. See `tokens.ts` for the vocabulary and `parts-map.ts` for the
|
|
12
|
+
* positional mapping that makes one action list correct on every controller.
|
|
13
|
+
*/
|
|
14
|
+
export * from "./types.js";
|
|
15
|
+
export * from "./tokens.js";
|
|
16
|
+
export * from "./parts-map.js";
|
|
17
|
+
export * from "./layouts/index.js";
|
|
18
|
+
export * from "./pad-svg.js";
|
|
19
|
+
export * from "./input-chip.js";
|
|
20
|
+
export * from "./combo-strip.js";
|
|
21
|
+
export * from "./controller-pad.js";
|
|
22
|
+
export * from "./controller-map.js";
|
|
23
|
+
export * from "./combo-demo.js";
|
|
24
|
+
export * from "./control-trainer.js";
|
|
25
|
+
export { injectPadCss } from "./styles.js";
|
|
26
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/ui/controller/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,oBAAoB,CAAC;AACnC,cAAc,cAAc,CAAC;AAC7B,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,iBAAiB,CAAC;AAChC,cAAc,sBAAsB,CAAC;AACrC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* INPUT CHIP — the small pictogram for one control, and the atom both controller views are built from.
|
|
3
|
+
*
|
|
4
|
+
* One factory, five renderers, chosen by the token:
|
|
5
|
+
*
|
|
6
|
+
* DIAMOND_* → `createKeycap` (the kit's existing face-button keycap)
|
|
7
|
+
* UP/DOWN/LEFT/RIGHT, R* → `createDpadKeycap` (the kit's chevron-on-steel keycap)
|
|
8
|
+
* LT / RT / OPTIONS → `createLabelKeycap` (the kit's pill: "L2"/"ZL", "Menu"/"Options"/"+")
|
|
9
|
+
* LSTICK / RSTICK → a stick pictogram, cap centred inside four outward arrows
|
|
10
|
+
* LSTICK / RSTICK :direction → the same pictogram with ONE arrow, cap already slid that way
|
|
11
|
+
* LSTICK_PRESS / RSTICK_PRESS → a stick pictogram of the cap CLICKED: sunk inside a collar,
|
|
12
|
+
* with a chevron pressing down into it
|
|
13
|
+
*
|
|
14
|
+
* The sticks are pictures rather than lettered chips throughout, because that is the one control where
|
|
15
|
+
* the letter tells a rider nothing: "L3" does not say *click the stick*, and it changes per brand on
|
|
16
|
+
* top of that. The printed label still reaches them through the chip's tooltip and assistive tech.
|
|
17
|
+
*
|
|
18
|
+
* All the button shapes REUSE the keycap kit rather than redrawing it, so a control looks identical in a
|
|
19
|
+
* controls legend and in an in-game prompt — same shape, same per-role hue, same letter for the rider's
|
|
20
|
+
* own pad. Only the shapes the kit didn't have are new, and they're inline SVG built with
|
|
21
|
+
* `createElementNS` from string path constants, exactly as `keycap.ts` does with its `CHEVRON`: this SDK
|
|
22
|
+
* ships **no non-TS assets** and adds no build step.
|
|
23
|
+
*
|
|
24
|
+
* **Press wiring lives here, not in the keycap.** The keycaps are built without their own `press`
|
|
25
|
+
* option, because `createDpadKeycap("UP")` listens for `UP` and there is no way to ask it to listen for
|
|
26
|
+
* `RUP` instead. Doing it in one place covers all five renderers uniformly and lets the combo demo drive
|
|
27
|
+
* exactly the same `setPressed` path that real input drives.
|
|
28
|
+
*/
|
|
29
|
+
import type { ButtonEdge } from "../../protocol/buttons.js";
|
|
30
|
+
import { type GlyphSet } from "../../protocol/glyphs.js";
|
|
31
|
+
import { type ComboToken, type ControlName } from "./tokens.js";
|
|
32
|
+
/**
|
|
33
|
+
* A control-event source. A `PlatformSession` satisfies it structurally.
|
|
34
|
+
*
|
|
35
|
+
* Typed on {@link ControlName} rather than `ButtonName` so a SHELL-side source can drive the shell-owned
|
|
36
|
+
* controls too — a session only ever emits the `ButtonName` subset, and still satisfies this.
|
|
37
|
+
*/
|
|
38
|
+
export interface ChipPressSource {
|
|
39
|
+
onButton(cb: (e: {
|
|
40
|
+
name: ControlName;
|
|
41
|
+
edge: ButtonEdge;
|
|
42
|
+
}) => void): () => void;
|
|
43
|
+
}
|
|
44
|
+
export interface InputChipOptions {
|
|
45
|
+
/** Which controller's lettering to draw. Default {@link DEFAULT_GLYPH_SET}. */
|
|
46
|
+
glyphSet?: GlyphSet;
|
|
47
|
+
/** Wire to real input: the chip shows its pressed state while ITS control is held. */
|
|
48
|
+
press?: ChipPressSource;
|
|
49
|
+
/** Per-role hue on face keycaps (confirm green, back amber). Default true, as elsewhere in the kit. */
|
|
50
|
+
colored?: boolean;
|
|
51
|
+
/** Drawing convention for the joystick pictograms. Default {@link DEFAULT_STICK_STYLE}. */
|
|
52
|
+
stickStyle?: StickPictogramStyle;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* What a chip is saying, for a guided lesson. Mirrors {@link PadPartState} so the chip in the card and
|
|
56
|
+
* the button on the drawing can never disagree.
|
|
57
|
+
*/
|
|
58
|
+
export type InputChipState = "idle" | "hint" | "active" | "done";
|
|
59
|
+
export interface InputChip {
|
|
60
|
+
/** The element to place. Sized to share a baseline with the kit's 38px keycap. */
|
|
61
|
+
readonly el: HTMLElement;
|
|
62
|
+
/** Pressed/held state. Driven by real input when `press` was given, and by the combo demo. */
|
|
63
|
+
setPressed(on: boolean): void;
|
|
64
|
+
/** Lesson state: `hint` = do this, `active` = doing it, `done` = finished. */
|
|
65
|
+
setState(state: InputChipState): void;
|
|
66
|
+
/**
|
|
67
|
+
* Deflect a stick chip's cap. `x`/`y` are −1..1 in the SDK's convention (right = +1, **up = +1**).
|
|
68
|
+
* A no-op on every other chip kind, so callers can drive a whole strip without branching.
|
|
69
|
+
*/
|
|
70
|
+
setDeflection(x: number, y: number): void;
|
|
71
|
+
dispose(): void;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Which drawing convention to use for the joystick pictograms. Three real ones from the industry, kept
|
|
75
|
+
* as an option because they trade off differently and the right answer is a judgement call:
|
|
76
|
+
*
|
|
77
|
+
* - **`"topdown"`** — the abstract plan view: a well, a cap dot, outline chevrons. Compact and neutral,
|
|
78
|
+
* the PlayStation/Steam-overlay convention. Weakest at small sizes, and the *click* is its hard case:
|
|
79
|
+
* pressing along the view axis is exactly what a top-down view cannot show.
|
|
80
|
+
* - **`"profile"`** — the hybrid the free prompt packs (Kenney, Xelu) settled on, and the clearest of
|
|
81
|
+
* the three: **plan view with bold filled arrows for directions**, and a **side view for the click** —
|
|
82
|
+
* a real stick with a shaft and a thumb pad, being pushed down by a solid arrow. Each gesture gets the
|
|
83
|
+
* viewpoint that can actually depict it.
|
|
84
|
+
* - **`"glyph"`** — the bold console-UI mark (Xbox / Steam Input): a solid disc with solid triangles,
|
|
85
|
+
* and a click drawn as a heavy ring with an arrow inside it. Loudest and most legible far away;
|
|
86
|
+
* least literal about the hardware.
|
|
87
|
+
*
|
|
88
|
+
* Compare them in the showcase's "Joystick pictograms" section before changing {@link DEFAULT_STICK_STYLE}.
|
|
89
|
+
*/
|
|
90
|
+
export type StickPictogramStyle = "topdown" | "profile" | "glyph";
|
|
91
|
+
/** The style used when a caller doesn't ask for one. */
|
|
92
|
+
export declare const DEFAULT_STICK_STYLE: StickPictogramStyle;
|
|
93
|
+
/**
|
|
94
|
+
* Build the chip for one control.
|
|
95
|
+
*
|
|
96
|
+
* Always returns something drawable: an unrecognised token falls through to a text chip carrying
|
|
97
|
+
* `buttonLabel`'s own fallback (the name itself), so a caller can never render an empty box.
|
|
98
|
+
*/
|
|
99
|
+
export declare function createInputChip(token: ComboToken, opts?: InputChipOptions): InputChip;
|
|
100
|
+
//# sourceMappingURL=input-chip.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"input-chip.d.ts","sourceRoot":"","sources":["../../../src/ui/controller/input-chip.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,EAA+C,KAAK,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAGtG,OAAO,EAAgD,KAAK,UAAU,EAAE,KAAK,WAAW,EAAiB,MAAM,aAAa,CAAC;AAE7H;;;;;GAKG;AACH,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE;QAAE,IAAI,EAAE,WAAW,CAAC;QAAC,IAAI,EAAE,UAAU,CAAA;KAAE,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;CAChF;AAED,MAAM,WAAW,gBAAgB;IAC/B,+EAA+E;IAC/E,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,sFAAsF;IACtF,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,uGAAuG;IACvG,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,2FAA2F;IAC3F,UAAU,CAAC,EAAE,mBAAmB,CAAC;CAClC;AAED;;;GAGG;AACH,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,MAAM,GAAG,QAAQ,GAAG,MAAM,CAAC;AAEjE,MAAM,WAAW,SAAS;IACxB,kFAAkF;IAClF,QAAQ,CAAC,EAAE,EAAE,WAAW,CAAC;IACzB,8FAA8F;IAC9F,UAAU,CAAC,EAAE,EAAE,OAAO,GAAG,IAAI,CAAC;IAC9B,8EAA8E;IAC9E,QAAQ,CAAC,KAAK,EAAE,cAAc,GAAG,IAAI,CAAC;IACtC;;;OAGG;IACH,aAAa,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1C,OAAO,IAAI,IAAI,CAAC;CACjB;AAID;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,MAAM,mBAAmB,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,CAAC;AAElE,wDAAwD;AACxD,eAAO,MAAM,mBAAmB,EAAE,mBAA+B,CAAC;AA8KlE;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,UAAU,EAAE,IAAI,GAAE,gBAAqB,GAAG,SAAS,CAmHzF"}
|