@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,60 @@
1
+ /**
2
+ * Switch Pro arrangement — the diagonal mirror of Xbox: left stick high-left, D-pad low-left, face
3
+ * diamond high-right, right stick low-right.
4
+ *
5
+ * Note the face glyphs: `A` sits on the RIGHT and `B` on the BOTTOM, the mirror of an Xbox pad. That
6
+ * inversion is the single most likely thing to get wrong here, and it is exactly why parts are keyed
7
+ * by position and the letters come from `buttonLabel()` instead of being assumed. A game asking for
8
+ * `DIAMOND_DOWN` still lights the BOTTOM button on this pad — only the letter printed on it changes.
9
+ */
10
+ import { PAD_VIEWBOX, PAD_BODY_PATH } from "../types.js";
11
+ import { buttonLabel } from "../../../protocol/glyphs.js";
12
+ const L = (n) => buttonLabel("nintendo", n);
13
+ export const SWITCH_PRO_LAYOUT = {
14
+ brand: "nintendo",
15
+ displayName: "Switch Pro-style controller",
16
+ viewBox: PAD_VIEWBOX,
17
+ body: { d: PAD_BODY_PATH },
18
+ // Switch draws its D-pad as four separate round buttons rather than a cross.
19
+ dpad: {
20
+ up: { geom: { kind: "circle", cx: 92, cy: 70, r: 5.5 }, label: "D-pad up" },
21
+ down: { geom: { kind: "circle", cx: 92, cy: 92, r: 5.5 }, label: "D-pad down" },
22
+ left: { geom: { kind: "circle", cx: 81, cy: 81, r: 5.5 }, label: "D-pad left" },
23
+ right: { geom: { kind: "circle", cx: 103, cy: 81, r: 5.5 }, label: "D-pad right" },
24
+ },
25
+ face: {
26
+ top: { geom: { kind: "circle", cx: 176, cy: 37, r: 9.5 }, glyph: L("DIAMOND_UP"), label: `${L("DIAMOND_UP")} button (top)` },
27
+ right: { geom: { kind: "circle", cx: 193, cy: 54, r: 9.5 }, glyph: L("DIAMOND_RIGHT"), label: `${L("DIAMOND_RIGHT")} button (right) — back` },
28
+ bottom: { geom: { kind: "circle", cx: 176, cy: 71, r: 9.5 }, glyph: L("DIAMOND_DOWN"), label: `${L("DIAMOND_DOWN")} button (bottom) — confirm` },
29
+ left: { geom: { kind: "circle", cx: 159, cy: 54, r: 9.5 }, glyph: L("DIAMOND_LEFT"), label: `${L("DIAMOND_LEFT")} button (left)` },
30
+ },
31
+ bumpers: {
32
+ l: { geom: { kind: "rect", x: 60, y: 2, w: 46, h: 12, rx: 6 }, glyph: "L", label: "L — the shell's resistance −, not the game's" },
33
+ r: { geom: { kind: "rect", x: 134, y: 2, w: 46, h: 12, rx: 6 }, glyph: "R", label: "R — the shell's resistance +, not the game's" },
34
+ },
35
+ triggers: {
36
+ l: {
37
+ geom: { kind: "rect", x: 66, y: -18, w: 34, h: 13, rx: 6 },
38
+ meter: { x: 68, y: -16, w: 30, h: 9, rx: 4 },
39
+ glyph: L("LT"),
40
+ label: "ZL trigger",
41
+ },
42
+ r: {
43
+ geom: { kind: "rect", x: 140, y: -18, w: 34, h: 13, rx: 6 },
44
+ meter: { x: 142, y: -16, w: 30, h: 9, rx: 4 },
45
+ glyph: L("RT"),
46
+ label: "ZR trigger",
47
+ },
48
+ },
49
+ sticks: {
50
+ l: { cx: 62, cy: 54, well: 16, cap: 11, travel: 5, label: "Left stick" },
51
+ r: { cx: 150, cy: 82, well: 16, cap: 11, travel: 5, label: "Right stick" },
52
+ },
53
+ system: {
54
+ select: { geom: { kind: "circle", cx: 104, cy: 52, r: 5.5 }, glyph: "−", label: "Minus — the shell's, not the game's" },
55
+ start: { geom: { kind: "circle", cx: 136, cy: 52, r: 5.5 }, glyph: "+", label: "Plus" },
56
+ home: { geom: { kind: "circle", cx: 136, cy: 34, r: 5 }, label: "Home — the shell's, not the game's" },
57
+ },
58
+ decor: [{ geom: { kind: "rect", x: 100, y: 30, w: 9, h: 9, rx: 2 }, opacity: 0.5 }],
59
+ };
60
+ //# sourceMappingURL=switch-pro.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"switch-pro.js","sourceRoot":"","sources":["../../../../src/ui/controller/layouts/switch-pro.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Xbox-style pad — also the fallback silhouette for any unrecognised controller, since X-input
3
+ * lettering is what most riders read without thinking.
4
+ *
5
+ * Arrangement: the asymmetric "offset stick" layout — left stick high-left, face diamond high-right,
6
+ * D-pad low-left, right stick low-right. Every control sits inside the interior documented on
7
+ * {@link PAD_BODY_PATH}; bumpers straddle the top edge and triggers sit above it, as on the hardware.
8
+ */
9
+ import { type PadLayout } from "../types.js";
10
+ export declare const XBOX_LAYOUT: PadLayout;
11
+ //# sourceMappingURL=xbox.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"xbox.d.ts","sourceRoot":"","sources":["../../../../src/ui/controller/layouts/xbox.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAA8B,KAAK,SAAS,EAAE,MAAM,aAAa,CAAC;AAMzE,eAAO,MAAM,WAAW,EAAE,SA8CzB,CAAC"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Xbox-style pad — also the fallback silhouette for any unrecognised controller, since X-input
3
+ * lettering is what most riders read without thinking.
4
+ *
5
+ * Arrangement: the asymmetric "offset stick" layout — left stick high-left, face diamond high-right,
6
+ * D-pad low-left, right stick low-right. Every control sits inside the interior documented on
7
+ * {@link PAD_BODY_PATH}; bumpers straddle the top edge and triggers sit above it, as on the hardware.
8
+ */
9
+ import { PAD_VIEWBOX, PAD_BODY_PATH } from "../types.js";
10
+ import { buttonLabel } from "../../../protocol/glyphs.js";
11
+ const L = (n) => buttonLabel("xbox", n);
12
+ export const XBOX_LAYOUT = {
13
+ brand: "xbox",
14
+ displayName: "Xbox-style controller",
15
+ viewBox: PAD_VIEWBOX,
16
+ body: { d: PAD_BODY_PATH },
17
+ // Low-left, arms kept inside the y<98 central mass.
18
+ dpad: {
19
+ up: { geom: { kind: "rect", x: 87, y: 66, w: 10, h: 11, rx: 2.5 }, label: "D-pad up" },
20
+ down: { geom: { kind: "rect", x: 87, y: 87, w: 10, h: 11, rx: 2.5 }, label: "D-pad down" },
21
+ left: { geom: { kind: "rect", x: 76, y: 77, w: 11, h: 10, rx: 2.5 }, label: "D-pad left" },
22
+ right: { geom: { kind: "rect", x: 97, y: 77, w: 11, h: 10, rx: 2.5 }, label: "D-pad right" },
23
+ },
24
+ // High-right diamond, centre (176, 54), offset 17, r 9.5.
25
+ face: {
26
+ top: { geom: { kind: "circle", cx: 176, cy: 37, r: 9.5 }, glyph: L("DIAMOND_UP"), label: `${L("DIAMOND_UP")} button (top)` },
27
+ right: { geom: { kind: "circle", cx: 193, cy: 54, r: 9.5 }, glyph: L("DIAMOND_RIGHT"), label: `${L("DIAMOND_RIGHT")} button (right) — back` },
28
+ bottom: { geom: { kind: "circle", cx: 176, cy: 71, r: 9.5 }, glyph: L("DIAMOND_DOWN"), label: `${L("DIAMOND_DOWN")} button (bottom) — confirm` },
29
+ left: { geom: { kind: "circle", cx: 159, cy: 54, r: 9.5 }, glyph: L("DIAMOND_LEFT"), label: `${L("DIAMOND_LEFT")} button (left)` },
30
+ },
31
+ bumpers: {
32
+ l: { geom: { kind: "rect", x: 60, y: 2, w: 46, h: 12, rx: 6 }, glyph: "LB", label: "Left bumper — the shell's resistance −, not the game's" },
33
+ r: { geom: { kind: "rect", x: 134, y: 2, w: 46, h: 12, rx: 6 }, glyph: "RB", label: "Right bumper — the shell's resistance +, not the game's" },
34
+ },
35
+ triggers: {
36
+ l: {
37
+ geom: { kind: "rect", x: 66, y: -18, w: 34, h: 13, rx: 6 },
38
+ meter: { x: 68, y: -16, w: 30, h: 9, rx: 4 },
39
+ glyph: L("LT"),
40
+ label: "Left trigger",
41
+ },
42
+ r: {
43
+ geom: { kind: "rect", x: 140, y: -18, w: 34, h: 13, rx: 6 },
44
+ meter: { x: 142, y: -16, w: 30, h: 9, rx: 4 },
45
+ glyph: L("RT"),
46
+ label: "Right trigger",
47
+ },
48
+ },
49
+ sticks: {
50
+ l: { cx: 62, cy: 54, well: 16, cap: 11, travel: 5, label: "Left stick" },
51
+ r: { cx: 150, cy: 82, well: 16, cap: 11, travel: 5, label: "Right stick" },
52
+ },
53
+ system: {
54
+ select: { geom: { kind: "circle", cx: 104, cy: 60, r: 5 }, label: "View — the shell's, not the game's" },
55
+ start: { geom: { kind: "circle", cx: 136, cy: 60, r: 5 }, glyph: "☰", label: "Menu / Options" },
56
+ home: { geom: { kind: "circle", cx: 120, cy: 42, r: 7 }, label: "Guide — the shell's, not the game's" },
57
+ },
58
+ };
59
+ //# sourceMappingURL=xbox.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"xbox.js","sourceRoot":"","sources":["../../../../src/ui/controller/layouts/xbox.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Zwift Play / Ride / Click — two handlebar-mounted pods, not a gamepad.
3
+ *
4
+ * **This is the one layout that is not a port.** The platform shell has no Zwift silhouette at all: its
5
+ * `GamepadBrand` is X-input-shaped (`xbox | playstation | nintendo | 8bitdo | steam | stadia |
6
+ * generic`) because a Zwift controller is BLE and never appears in `navigator.getGamepads()`. The shell
7
+ * gets away with that — its drawing lives in an admin mapping modal. A rider-facing controls screen
8
+ * does not, and on an indoor-cycling platform this is plausibly the most common controller there is.
9
+ *
10
+ * **Every part here is what the hardware actually reports**, taken from the shell's
11
+ * `ZwiftPlayManager` button map rather than from the shape of the other layouts:
12
+ *
13
+ * d-pad UP / DOWN / LEFT / RIGHT → the left pod's 4-way cluster
14
+ * face diamond by POSITION, printed Y A B Z → the right pod (`"zwift"` glyph set)
15
+ * shift paddles NOT game input → drawn, dimmed: they drive the rider's resistance
16
+ *
17
+ * And, just as importantly, what it does **not** have: no joysticks, no stick clicks, no `LT`/`RT`
18
+ * triggers, no system buttons. Those keys are absent from this layout rather than drawn dead, which is
19
+ * why `dpad`/`sticks`/`triggers`/`system` are optional on {@link PadLayout}. Drawing a control a rider
20
+ * cannot press is worse than drawing nothing — it invites a game to build a flow around it.
21
+ *
22
+ * The pod outlines are schematic (two rounded shells flanking a bar), not a traced product render. The
23
+ * point is that a rider recognises the shape of the thing on their handlebars and can find the button.
24
+ */
25
+ import { type PadLayout } from "../types.js";
26
+ export declare const ZWIFT_LAYOUT: PadLayout;
27
+ //# sourceMappingURL=zwift.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"zwift.d.ts","sourceRoot":"","sources":["../../../../src/ui/controller/layouts/zwift.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAAe,KAAK,SAAS,EAAE,MAAM,aAAa,CAAC;AAa1D,eAAO,MAAM,YAAY,EAAE,SA4B1B,CAAC"}
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Zwift Play / Ride / Click — two handlebar-mounted pods, not a gamepad.
3
+ *
4
+ * **This is the one layout that is not a port.** The platform shell has no Zwift silhouette at all: its
5
+ * `GamepadBrand` is X-input-shaped (`xbox | playstation | nintendo | 8bitdo | steam | stadia |
6
+ * generic`) because a Zwift controller is BLE and never appears in `navigator.getGamepads()`. The shell
7
+ * gets away with that — its drawing lives in an admin mapping modal. A rider-facing controls screen
8
+ * does not, and on an indoor-cycling platform this is plausibly the most common controller there is.
9
+ *
10
+ * **Every part here is what the hardware actually reports**, taken from the shell's
11
+ * `ZwiftPlayManager` button map rather than from the shape of the other layouts:
12
+ *
13
+ * d-pad UP / DOWN / LEFT / RIGHT → the left pod's 4-way cluster
14
+ * face diamond by POSITION, printed Y A B Z → the right pod (`"zwift"` glyph set)
15
+ * shift paddles NOT game input → drawn, dimmed: they drive the rider's resistance
16
+ *
17
+ * And, just as importantly, what it does **not** have: no joysticks, no stick clicks, no `LT`/`RT`
18
+ * triggers, no system buttons. Those keys are absent from this layout rather than drawn dead, which is
19
+ * why `dpad`/`sticks`/`triggers`/`system` are optional on {@link PadLayout}. Drawing a control a rider
20
+ * cannot press is worse than drawing nothing — it invites a game to build a flow around it.
21
+ *
22
+ * The pod outlines are schematic (two rounded shells flanking a bar), not a traced product render. The
23
+ * point is that a rider recognises the shape of the thing on their handlebars and can find the button.
24
+ */
25
+ import { PAD_VIEWBOX } from "../types.js";
26
+ import { buttonLabel } from "../../../protocol/glyphs.js";
27
+ const L = (n) => buttonLabel("zwift", n);
28
+ /** Two rounded pods flanking the bar: left x 26–106, right x 134–214, both y 18–138. */
29
+ const BODY = "M 46 18 H 86 A 20 20 0 0 1 106 38 V 118 A 20 20 0 0 1 86 138 H 46 " +
30
+ "A 20 20 0 0 1 26 118 V 38 A 20 20 0 0 1 46 18 Z " +
31
+ "M 154 18 H 194 A 20 20 0 0 1 214 38 V 118 A 20 20 0 0 1 194 138 H 154 " +
32
+ "A 20 20 0 0 1 134 118 V 38 A 20 20 0 0 1 154 18 Z";
33
+ export const ZWIFT_LAYOUT = {
34
+ brand: "zwift",
35
+ displayName: "Zwift Play-style controller",
36
+ viewBox: PAD_VIEWBOX,
37
+ body: { d: BODY },
38
+ // Left pod: the 4-way navigation cluster, a cross centred on (66, 78).
39
+ dpad: {
40
+ up: { geom: { kind: "rect", x: 60, y: 55, w: 12, h: 13, rx: 2.5 }, label: "Up" },
41
+ down: { geom: { kind: "rect", x: 60, y: 88, w: 12, h: 13, rx: 2.5 }, label: "Down" },
42
+ left: { geom: { kind: "rect", x: 43, y: 72, w: 13, h: 12, rx: 2.5 }, label: "Left" },
43
+ right: { geom: { kind: "rect", x: 76, y: 72, w: 13, h: 12, rx: 2.5 }, label: "Right" },
44
+ },
45
+ // Right pod: the face diamond, centred (174, 78), offset 19, r 10. Positions are physical; the
46
+ // letters (Y top, A right, B bottom, Z left) come from the "zwift" glyph table.
47
+ face: {
48
+ top: { geom: { kind: "circle", cx: 174, cy: 59, r: 10 }, glyph: L("DIAMOND_UP"), label: `${L("DIAMOND_UP")} button (top)` },
49
+ right: { geom: { kind: "circle", cx: 193, cy: 78, r: 10 }, glyph: L("DIAMOND_RIGHT"), label: `${L("DIAMOND_RIGHT")} button (right) — back` },
50
+ bottom: { geom: { kind: "circle", cx: 174, cy: 97, r: 10 }, glyph: L("DIAMOND_DOWN"), label: `${L("DIAMOND_DOWN")} button (bottom) — confirm` },
51
+ left: { geom: { kind: "circle", cx: 155, cy: 78, r: 10 }, glyph: L("DIAMOND_LEFT"), label: `${L("DIAMOND_LEFT")} button (left)` },
52
+ },
53
+ // The shift paddles. Deliberately mapped onto the bumper slot, which is exactly what it means
54
+ // everywhere else too: shell-owned resistance, never delivered to a game.
55
+ bumpers: {
56
+ l: { geom: { kind: "rect", x: 32, y: 2, w: 68, h: 12, rx: 6 }, glyph: "−", label: "Left shift paddle — the shell's resistance −, never game input" },
57
+ r: { geom: { kind: "rect", x: 140, y: 2, w: 68, h: 12, rx: 6 }, glyph: "+", label: "Right shift paddle — the shell's resistance +, never game input" },
58
+ },
59
+ // No triggers, no sticks, no system buttons — this hardware has none. See the file header.
60
+ decor: [{ geom: { kind: "rect", x: 100, y: 73, w: 44, h: 10, rx: 5 }, opacity: 0.5 }],
61
+ };
62
+ //# sourceMappingURL=zwift.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"zwift.js","sourceRoot":"","sources":["../../../../src/ui/controller/layouts/zwift.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAAE,WAAW,EAAkB,MAAM,aAAa,CAAC;AAC1D,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAG1D,MAAM,CAAC,GAAG,CAAC,CAAa,EAAU,EAAE,CAAC,WAAW,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;AAE7D,wFAAwF;AACxF,MAAM,IAAI,GACR,oEAAoE;IACpE,kDAAkD;IAClD,wEAAwE;IACxE,mDAAmD,CAAC;AAEtD,MAAM,CAAC,MAAM,YAAY,GAAc;IACrC,KAAK,EAAE,OAAO;IACd,WAAW,EAAE,6BAA6B;IAC1C,OAAO,EAAE,WAAW;IACpB,IAAI,EAAE,EAAE,CAAC,EAAE,IAAI,EAAE;IACjB,uEAAuE;IACvE,IAAI,EAAE;QACJ,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE;QAChF,IAAI,EAAE,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE;QACpF,IAAI,EAAE,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE;QACpF,KAAK,EAAE,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE;KACvF;IACD,+FAA+F;IAC/F,gFAAgF;IAChF,IAAI,EAAE;QACJ,GAAG,EAAE,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC,YAAY,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC,YAAY,CAAC,eAAe,EAAE;QAC3H,KAAK,EAAE,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC,eAAe,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC,eAAe,CAAC,wBAAwB,EAAE;QAC5I,MAAM,EAAE,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC,cAAc,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC,cAAc,CAAC,4BAA4B,EAAE;QAC/I,IAAI,EAAE,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC,cAAc,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC,cAAc,CAAC,gBAAgB,EAAE;KAClI;IACD,8FAA8F;IAC9F,0EAA0E;IAC1E,OAAO,EAAE;QACP,CAAC,EAAE,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,gEAAgE,EAAE;QACpJ,CAAC,EAAE,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,iEAAiE,EAAE;KACvJ;IACD,2FAA2F;IAC3F,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;CACtF,CAAC"}
@@ -0,0 +1,105 @@
1
+ /**
2
+ * The one SVG renderer for every controller silhouette, plus the animation layer that drives it.
3
+ *
4
+ * `buildPadSvg` emits nodes and hands back the node caches directly — `parts`, `sticks`, `meters`. That
5
+ * is the ONLY coupling between the drawing and whatever animates it: nothing ever re-renders the SVG
6
+ * per frame; a driver mutates classes and attributes on cached nodes. (The platform's Lit version had
7
+ * to re-scan the shadow root with `querySelectorAll` after each render to rebuild these maps; building
8
+ * them as we go is strictly less machinery.)
9
+ *
10
+ * `createPadDriver` is that animation layer. It keeps a `lastVal` dirty-guard so an **idle pad costs
11
+ * zero DOM writes** even when polled at 60 Hz — that guard is not an optimisation to trim, it's the
12
+ * reason this is cheap enough to run beside a game loop.
13
+ *
14
+ * Both are input-agnostic: they know about positions (`PadPart`), never about `ButtonName`s, key codes
15
+ * or gamepad indices. `controller-pad.ts` owns the translation from canonical input to positions.
16
+ */
17
+ import { type PadLayout, type PadPart } from "./types.js";
18
+ /**
19
+ * Parts a game can never bind, so the drawing must never light them.
20
+ *
21
+ * The bumpers are the rider's resistance − / + and `select`/`home` are the shell's own menu and guide —
22
+ * all four are handled by the shell and are never delivered to a game (see `protocol/buttons.ts` on
23
+ * the shell-owned keys). They are still DRAWN, faintly, because a rider needs to tell "this game
24
+ * doesn't use that button" apart from "that button isn't the game's to use".
25
+ *
26
+ * `setPart` refuses them outright rather than trusting callers: today no `ButtonName` maps here, and
27
+ * enforcing it in the driver keeps that true if someone later adds one by mistake.
28
+ */
29
+ export declare const SHELL_OWNED_PARTS: ReadonlySet<PadPart>;
30
+ /** Past this deflection the stick glows like a pressed button. Matches the shell's feel. */
31
+ export declare const STICK_LIT_DEADZONE = 0.18;
32
+ export interface PadSvg {
33
+ svg: SVGSVGElement;
34
+ /** Every drawn part, by position. Absent parts (a Zwift pod has no sticks) are simply not keyed. */
35
+ parts: Map<PadPart, SVGGElement>;
36
+ /** The transformed stick groups — these carry BOTH the translate and the `.deflected` class. */
37
+ sticks: Partial<Record<"l" | "r", SVGGElement>>;
38
+ /** The trigger travel meters. */
39
+ meters: Partial<Record<"l" | "r", SVGRectElement>>;
40
+ }
41
+ /**
42
+ * How far a pressed control travels, in viewBox units, and equally how far its shadow sits below it at
43
+ * rest. One number for both, because the effect only reads if the face lands exactly ON its own shadow.
44
+ */
45
+ export declare const PRESS_DEPTH = 1.4;
46
+ /**
47
+ * Build the drawing for `layout`.
48
+ *
49
+ * Draw order matters and matches the shell's: body → decor → triggers → bumpers → d-pad → face →
50
+ * system → sticks. Sticks come last so a deflected cap draws over the shell rather than under it.
51
+ */
52
+ export declare function buildPadSvg(layout: PadLayout, opts?: {
53
+ labels?: boolean;
54
+ }): PadSvg;
55
+ /**
56
+ * What a part is currently saying.
57
+ *
58
+ * `"off"` and `"on"` are the live-pad pair — released and held. The other two exist for a guided lesson,
59
+ * where a part has to say three different things over time:
60
+ *
61
+ * `"hint"` — *do this* (a whitish pulse: the instruction, not a press)
62
+ * `"on"` — *you're doing it* (the accent colour, same as a real press)
63
+ * `"done"` — *that one's finished* (green)
64
+ *
65
+ * Note that `"done"` is a state the CALLER decides how long to hold. The trainer only leaves a control
66
+ * green while that step is the one on screen: the pad is an instruction surface, so a green button
67
+ * sitting beside a white one while a different combination is being taught would read as "and this one
68
+ * too". The persistent record of progress lives on the step panels instead.
69
+ */
70
+ export type PadPartState = "off" | "hint" | "on" | "done";
71
+ export interface PadDriver {
72
+ /** Light / unlight a part. Shell-owned parts are refused — see {@link SHELL_OWNED_PARTS}. */
73
+ setPart(part: PadPart, on: boolean): void;
74
+ /** Set a part's full state. Same shell-owned rule as {@link setPart}. */
75
+ setPartState(part: PadPart, state: PadPartState): void;
76
+ /**
77
+ * Move a stick cap. `x`/`y` are −1..1 in the SDK's convention: right = +1 and **up = +1**.
78
+ *
79
+ * `lit` decides what the deflection MEANS, which the position alone cannot say:
80
+ * `"auto"` (default) — glow past the deadzone. The live pad: a moved stick is a moved stick.
81
+ * `"hint"` — whitish and pulsing: a lesson DEMONSTRATING the gesture, not the rider doing
82
+ * it. Without this a demonstration is painted in the accent, i.e. in the exact
83
+ * colour that everywhere else means "you are doing this right now".
84
+ * `"on"` / `"off"` — force it.
85
+ */
86
+ setStick(side: "l" | "r", x: number, y: number, lit?: "auto" | "hint" | "on" | "off"): void;
87
+ /** Fill a trigger's travel meter, 0..1. */
88
+ setMeter(side: "l" | "r", v01: number): void;
89
+ /** Dim the parts the rider's device can't produce. `null` clears the dimming. */
90
+ setAvailable(parts: readonly PadPart[] | null): void;
91
+ /** Release everything. Call on teardown so a button held at unmount never stays lit. */
92
+ clearAll(): void;
93
+ }
94
+ export interface PadDriverOptions {
95
+ /**
96
+ * Let the driver light the shell-owned parts (the resistance bumpers, View, Guide).
97
+ *
98
+ * Off by default, deliberately: a game can never receive those controls, so lighting them would be
99
+ * telling the rider something untrue. The one legitimate caller is a **lesson that teaches the rider
100
+ * where the resistance buttons are** — there, highlighting them is the entire point.
101
+ */
102
+ allowShellOwned?: boolean;
103
+ }
104
+ export declare function createPadDriver(pad: PadSvg, layout: PadLayout, opts?: PadDriverOptions): PadDriver;
105
+ //# sourceMappingURL=pad-svg.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pad-svg.d.ts","sourceRoot":"","sources":["../../../src/ui/controller/pad-svg.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAc,KAAK,SAAS,EAAE,KAAK,OAAO,EAAkD,MAAM,YAAY,CAAC;AAItH;;;;;;;;;;GAUG;AACH,eAAO,MAAM,iBAAiB,EAAE,WAAW,CAAC,OAAO,CAAoD,CAAC;AAIxG,4FAA4F;AAC5F,eAAO,MAAM,kBAAkB,OAAO,CAAC;AAEvC,MAAM,WAAW,MAAM;IACrB,GAAG,EAAE,aAAa,CAAC;IACnB,oGAAoG;IACpG,KAAK,EAAE,GAAG,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;IACjC,gGAAgG;IAChG,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,GAAG,GAAG,GAAG,EAAE,WAAW,CAAC,CAAC,CAAC;IAChD,iCAAiC;IACjC,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,GAAG,GAAG,GAAG,EAAE,cAAc,CAAC,CAAC,CAAC;CACpD;AA8BD;;;GAGG;AACH,eAAO,MAAM,WAAW,MAAM,CAAC;AA6D/B;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,SAAS,EAAE,IAAI,GAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,MAAM,CAoFtF;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,MAAM,YAAY,GAAG,KAAK,GAAG,MAAM,GAAG,IAAI,GAAG,MAAM,CAAC;AAE1D,MAAM,WAAW,SAAS;IACxB,6FAA6F;IAC7F,OAAO,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,OAAO,GAAG,IAAI,CAAC;IAC1C,yEAAyE;IACzE,YAAY,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,YAAY,GAAG,IAAI,CAAC;IACvD;;;;;;;;;OASG;IACH,QAAQ,CAAC,IAAI,EAAE,GAAG,GAAG,GAAG,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,KAAK,GAAG,IAAI,CAAC;IAC5F,2CAA2C;IAC3C,QAAQ,CAAC,IAAI,EAAE,GAAG,GAAG,GAAG,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7C,iFAAiF;IACjF,YAAY,CAAC,KAAK,EAAE,SAAS,OAAO,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC;IACrD,wFAAwF;IACxF,QAAQ,IAAI,IAAI,CAAC;CAClB;AAED,MAAM,WAAW,gBAAgB;IAC/B;;;;;;OAMG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,GAAE,gBAAqB,GAAG,SAAS,CAwFtG"}