@rydr/game-sdk 8.11.0 → 8.12.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 +26 -2
- package/dist/client/PlatformClient.d.ts.map +1 -1
- package/dist/client/PlatformClient.js +14 -2
- package/dist/client/PlatformClient.js.map +1 -1
- package/dist/client/Room.d.ts +9 -4
- package/dist/client/Room.d.ts.map +1 -1
- package/dist/client/Room.js +8 -5
- package/dist/client/Room.js.map +1 -1
- package/dist/host/PlatformHost.d.ts +4 -2
- package/dist/host/PlatformHost.d.ts.map +1 -1
- package/dist/host/PlatformHost.js +5 -3
- package/dist/host/PlatformHost.js.map +1 -1
- package/dist/protocol/messages.d.ts +11 -4
- package/dist/protocol/messages.d.ts.map +1 -1
- package/dist/protocol/room.d.ts +26 -0
- package/dist/protocol/room.d.ts.map +1 -1
- package/dist/protocol/version.d.ts +2 -2
- package/dist/protocol/version.d.ts.map +1 -1
- package/dist/protocol/version.js +23 -2
- package/dist/protocol/version.js.map +1 -1
- package/dist/three/README.md +111 -0
- package/dist/three/character/index.d.ts +14 -0
- package/dist/three/character/index.d.ts.map +1 -0
- package/dist/three/character/index.js +14 -0
- package/dist/three/character/index.js.map +1 -0
- package/dist/three/character/kit.d.ts +74 -0
- package/dist/three/character/kit.d.ts.map +1 -0
- package/dist/three/character/kit.js +254 -0
- package/dist/three/character/kit.js.map +1 -0
- package/dist/three/character/riders.d.ts +20 -0
- package/dist/three/character/riders.d.ts.map +1 -0
- package/dist/three/character/riders.js +383 -0
- package/dist/three/character/riders.js.map +1 -0
- package/dist/three/character/skeleton.d.ts +105 -0
- package/dist/three/character/skeleton.d.ts.map +1 -0
- package/dist/three/character/skeleton.js +57 -0
- package/dist/three/character/skeleton.js.map +1 -0
- package/dist/three/controller/glyph-texture.d.ts +29 -0
- package/dist/three/controller/glyph-texture.d.ts.map +1 -0
- package/dist/three/controller/glyph-texture.js +68 -0
- package/dist/three/controller/glyph-texture.js.map +1 -0
- package/dist/three/controller/index.d.ts +12 -0
- package/dist/three/controller/index.d.ts.map +1 -0
- package/dist/three/controller/index.js +12 -0
- package/dist/three/controller/index.js.map +1 -0
- package/dist/three/controller/joycon-designs.d.ts +49 -0
- package/dist/three/controller/joycon-designs.d.ts.map +1 -0
- package/dist/three/controller/joycon-designs.js +742 -0
- package/dist/three/controller/joycon-designs.js.map +1 -0
- package/dist/three/controller/joycon-shoulder-mesh.d.ts +41 -0
- package/dist/three/controller/joycon-shoulder-mesh.d.ts.map +1 -0
- package/dist/three/controller/joycon-shoulder-mesh.js +527 -0
- package/dist/three/controller/joycon-shoulder-mesh.js.map +1 -0
- package/dist/three/controller/joycon-spec.d.ts +233 -0
- package/dist/three/controller/joycon-spec.d.ts.map +1 -0
- package/dist/three/controller/joycon-spec.js +285 -0
- package/dist/three/controller/joycon-spec.js.map +1 -0
- package/dist/three/controller/three-pad-renderer.d.ts +81 -0
- package/dist/three/controller/three-pad-renderer.d.ts.map +1 -0
- package/dist/three/controller/three-pad-renderer.js +433 -0
- package/dist/three/controller/three-pad-renderer.js.map +1 -0
- package/dist/three/index.d.ts +2 -0
- package/dist/three/index.d.ts.map +1 -1
- package/dist/three/index.js +2 -0
- package/dist/three/index.js.map +1 -1
- package/dist/three/rider/cyclist-pose.d.ts +62 -0
- package/dist/three/rider/cyclist-pose.d.ts.map +1 -0
- package/dist/three/rider/cyclist-pose.js +173 -0
- package/dist/three/rider/cyclist-pose.js.map +1 -0
- package/dist/three/rider/index.d.ts +8 -0
- package/dist/three/rider/index.d.ts.map +1 -0
- package/dist/three/rider/index.js +8 -0
- package/dist/three/rider/index.js.map +1 -0
- package/dist/three/rider/three-rider-rig.d.ts +80 -0
- package/dist/three/rider/three-rider-rig.d.ts.map +1 -0
- package/dist/three/rider/three-rider-rig.js +418 -0
- package/dist/three/rider/three-rider-rig.js.map +1 -0
- package/dist/ui/README.md +153 -1
- package/dist/ui/controller/combo-demo.d.ts +9 -0
- package/dist/ui/controller/combo-demo.d.ts.map +1 -1
- package/dist/ui/controller/combo-demo.js +1 -0
- package/dist/ui/controller/combo-demo.js.map +1 -1
- package/dist/ui/controller/control-spotlight.d.ts +10 -1
- package/dist/ui/controller/control-spotlight.d.ts.map +1 -1
- package/dist/ui/controller/control-spotlight.js +42 -42
- package/dist/ui/controller/control-spotlight.js.map +1 -1
- package/dist/ui/controller/control-trainer.d.ts +14 -0
- package/dist/ui/controller/control-trainer.d.ts.map +1 -1
- package/dist/ui/controller/control-trainer.js +6 -0
- package/dist/ui/controller/control-trainer.js.map +1 -1
- package/dist/ui/controller/controller-map.d.ts +9 -0
- package/dist/ui/controller/controller-map.d.ts.map +1 -1
- package/dist/ui/controller/controller-map.js +8 -6
- package/dist/ui/controller/controller-map.js.map +1 -1
- package/dist/ui/controller/controller-pad.d.ts +35 -2
- package/dist/ui/controller/controller-pad.d.ts.map +1 -1
- package/dist/ui/controller/controller-pad.js +47 -7
- package/dist/ui/controller/controller-pad.js.map +1 -1
- package/dist/ui/controller/index.d.ts +1 -0
- package/dist/ui/controller/index.d.ts.map +1 -1
- package/dist/ui/controller/index.js +1 -0
- package/dist/ui/controller/index.js.map +1 -1
- package/dist/ui/controller/renderer.d.ts +118 -0
- package/dist/ui/controller/renderer.d.ts.map +1 -0
- package/dist/ui/controller/renderer.js +93 -0
- package/dist/ui/controller/renderer.js.map +1 -0
- package/dist/ui/controller/styles.js +30 -0
- package/dist/ui/controller/styles.js.map +1 -1
- package/dist/ui/index.d.ts +6 -0
- package/dist/ui/index.d.ts.map +1 -1
- package/dist/ui/index.js +6 -0
- package/dist/ui/index.js.map +1 -1
- package/dist/ui/rider-rig.d.ts +315 -0
- package/dist/ui/rider-rig.d.ts.map +1 -0
- package/dist/ui/rider-rig.js +1000 -0
- package/dist/ui/rider-rig.js.map +1 -0
- package/dist/ui/showcase/index.d.ts +11 -0
- package/dist/ui/showcase/index.d.ts.map +1 -1
- package/dist/ui/showcase/index.js +109 -1
- package/dist/ui/showcase/index.js.map +1 -1
- package/package.json +8 -4
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WHAT A JOY-CON ACTUALLY IS, in numbers — the shared spec behind every 3D design.
|
|
3
|
+
*
|
|
4
|
+
* The first attempt at a 3D pad extruded the flat drawing's viewBox and gave it a little depth. That
|
|
5
|
+
* produced something that reads as *the flat pad, tilted*: the shell was 6× wider than it was thick,
|
|
6
|
+
* and the buttons stood 3% of their own diameter proud of it. Both are wrong. A real Joy-Con is
|
|
7
|
+
* **102 × 35.9 × 28.4 mm** — nearly as thick as it is wide, a bar rather than a plate — and its buttons
|
|
8
|
+
* are domes you could catch a fingernail on.
|
|
9
|
+
*
|
|
10
|
+
* So the geometry here is built from the HARDWARE's proportions, and the flat layout is used only for
|
|
11
|
+
* what it is genuinely authoritative about: **which control sits where on the face**, as a fraction of
|
|
12
|
+
* the shell. That split is deliberate —
|
|
13
|
+
*
|
|
14
|
+
* - the layout owns the *arrangement* (stick above the d-pad on the left, diamond above the stick on
|
|
15
|
+
* the right, `−` top-inner, Home bottom-centre), which is the thing every view depends on;
|
|
16
|
+
* - this file owns the *proportions*, which the layout deliberately distorts because a schematic
|
|
17
|
+
* drawing is not a scale drawing.
|
|
18
|
+
*
|
|
19
|
+
* Every number below was MEASURED off a reference Joy-Con model, not estimated: proportions, control
|
|
20
|
+
* positions, control sizes and how far each stands off the face. `u` runs 0 → 1 left-to-right across
|
|
21
|
+
* one shell, `v` runs 0 → 1 top-to-bottom.
|
|
22
|
+
*
|
|
23
|
+
* The measurements corrected two things the estimates got wrong: the halves sit much further apart
|
|
24
|
+
* than the flat drawing suggests (0.72 of a shell's width), and both control clusters are pushed
|
|
25
|
+
* INWARD, towards the middle of the pair, where the thumbs actually fall.
|
|
26
|
+
*/
|
|
27
|
+
/**
|
|
28
|
+
* THE TUNABLE NUMBERS.
|
|
29
|
+
*
|
|
30
|
+
* Everything below is derived from this object, and {@link applyTuning} recomputes the derived values
|
|
31
|
+
* in place. That exists so the shape can be dialled in from a control panel in the showcase instead of
|
|
32
|
+
* through an edit-rebuild-look loop — the person judging the shape is the one who should be turning
|
|
33
|
+
* the knobs.
|
|
34
|
+
*
|
|
35
|
+
* Values are RATIOS, not absolute sizes, so the pad stays coherent whatever you change: depths and
|
|
36
|
+
* radii are fractions of the shell's width, the width itself is a fraction of its height.
|
|
37
|
+
*/
|
|
38
|
+
export declare const TUNING: {
|
|
39
|
+
/**
|
|
40
|
+
* Shell height and width, INDEPENDENTLY.
|
|
41
|
+
*
|
|
42
|
+
* They used to be one knob (a height ÷ width ratio), which meant you could not make the pad taller
|
|
43
|
+
* without also making it narrower. Everything else in this object is a fraction of the WIDTH, so
|
|
44
|
+
* depths, radii and control sizes still follow it — only the height is now free.
|
|
45
|
+
*
|
|
46
|
+
* For reference, the measured hardware ratio is 2.9869 : 1.
|
|
47
|
+
*/
|
|
48
|
+
shellHeight: number;
|
|
49
|
+
shellWidth: number;
|
|
50
|
+
/** Depth at the crown, ÷ width. */
|
|
51
|
+
depthTop: number;
|
|
52
|
+
/** Depth at the base, ÷ width. The taper that makes room for the triggers. */
|
|
53
|
+
depthBottom: number;
|
|
54
|
+
/** Height fraction (0 = crown) at which the taper happens, and how softly. */
|
|
55
|
+
breakV: number;
|
|
56
|
+
breakSoft: number;
|
|
57
|
+
/** Space between the two halves, ÷ width. */
|
|
58
|
+
gap: number;
|
|
59
|
+
/** Rounding of the shell's vertical edges, ÷ width. */
|
|
60
|
+
shellRadius: number;
|
|
61
|
+
/** Corner radii of the face outline, ÷ width. Outer is the rounded side, inner the rail side. */
|
|
62
|
+
outerTopR: number;
|
|
63
|
+
outerBottomR: number;
|
|
64
|
+
innerTopR: number;
|
|
65
|
+
innerBottomR: number;
|
|
66
|
+
/** Radii, ÷ width. */
|
|
67
|
+
faceR: number;
|
|
68
|
+
dpadR: number;
|
|
69
|
+
systemR: number;
|
|
70
|
+
/** How far a domed button stands proud of the face, ÷ width. */
|
|
71
|
+
buttonRise: number;
|
|
72
|
+
/** `−` and `+` are nearly flush. */
|
|
73
|
+
systemRise: number;
|
|
74
|
+
stickWellR: number;
|
|
75
|
+
stickCapR: number;
|
|
76
|
+
stickHeight: number;
|
|
77
|
+
/** Height of the cap itself, ÷ its own radius. A real thumb cap is roughly 0.7 — it is not a disc. */
|
|
78
|
+
stickCapDepth: number;
|
|
79
|
+
/** How deep the thumb dish sinks below the rim, ÷ cap radius. */
|
|
80
|
+
stickCapDish: number;
|
|
81
|
+
/**
|
|
82
|
+
* The shoulder keys are the reference model's own triangles, so their SHAPE is fixed. What is
|
|
83
|
+
* adjustable is how they sit: pushed out along their normals so they clear the generated crown,
|
|
84
|
+
* lifted, and scaled.
|
|
85
|
+
*
|
|
86
|
+
* `lift` matters most, and must not be 0. On the reference, `ZL`'s surface IS the shell's top —
|
|
87
|
+
* coplanar with it. Ours is a separate mesh, so at 0 the two surfaces occupy the same plane and
|
|
88
|
+
* z-fight, which shows as a ragged hole in the key.
|
|
89
|
+
*/
|
|
90
|
+
shoulderLift: number;
|
|
91
|
+
/** Extra vertical raise, ÷ width. */
|
|
92
|
+
shoulderRaise: number;
|
|
93
|
+
/** Overall scale of the shoulder keys, 1 = as measured. */
|
|
94
|
+
shoulderScale: number;
|
|
95
|
+
/** Default camera pitch in DEGREES. Past ~35° the pad foreshortens into a plan view. */
|
|
96
|
+
pitchDeg: number;
|
|
97
|
+
/** Camera field of view. */
|
|
98
|
+
fovDeg: number;
|
|
99
|
+
};
|
|
100
|
+
/** Shell height in world units. */
|
|
101
|
+
export declare let H: number;
|
|
102
|
+
/** Shell width. */
|
|
103
|
+
export declare let W: number;
|
|
104
|
+
/** Depth at the TOP of the shell, where it is thickest. */
|
|
105
|
+
export declare let DEPTH_TOP: number;
|
|
106
|
+
/**
|
|
107
|
+
* Depth at the BOTTOM.
|
|
108
|
+
*
|
|
109
|
+
* Measured at 58% of the top, and it is the shape's whole point: the shell is a wedge, thick at the
|
|
110
|
+
* top and tapering down. The bulge makes room for the triggers, and it is entirely on the BACK — the
|
|
111
|
+
* front face, where every button lives, is dead flat top to bottom.
|
|
112
|
+
*/
|
|
113
|
+
export declare let DEPTH_BOTTOM: number;
|
|
114
|
+
/** Deepest the shell ever gets — what the pair's bounding box is sized from. */
|
|
115
|
+
export declare let D: number;
|
|
116
|
+
/** Gap between the halves. */
|
|
117
|
+
export declare let GAP: number;
|
|
118
|
+
/** Corner rounding of the shell. */
|
|
119
|
+
export declare let SHELL_RADIUS: number;
|
|
120
|
+
/**
|
|
121
|
+
* The silhouette is ASYMMETRIC, and that is the shape's signature.
|
|
122
|
+
*
|
|
123
|
+
* The INNER edge — the one carrying the rail, that docks against the console — runs dead straight from
|
|
124
|
+
* top to bottom. All the rounding is on the OUTER edge. A symmetric rounded rectangle reads as a
|
|
125
|
+
* generic slab; this is what makes it a Joy-Con.
|
|
126
|
+
*/
|
|
127
|
+
export declare let SILHOUETTE: {
|
|
128
|
+
outerTopR: number;
|
|
129
|
+
outerBottomR: number;
|
|
130
|
+
innerTopR: number;
|
|
131
|
+
innerBottomR: number;
|
|
132
|
+
};
|
|
133
|
+
/** Control sizes, as fractions of the shell width — so they scale with the model. */
|
|
134
|
+
export declare let SIZES: {
|
|
135
|
+
faceR: number;
|
|
136
|
+
dpadR: number;
|
|
137
|
+
systemR: number;
|
|
138
|
+
stickWellR: number;
|
|
139
|
+
stickCapR: number;
|
|
140
|
+
stickHeight: number;
|
|
141
|
+
buttonRise: number;
|
|
142
|
+
systemRise: number;
|
|
143
|
+
};
|
|
144
|
+
/**
|
|
145
|
+
* Recompute every derived value from {@link TUNING}.
|
|
146
|
+
*
|
|
147
|
+
* Call after changing TUNING and before rebuilding a model. The exports above are ES module live
|
|
148
|
+
* bindings, so importers see the new numbers without re-importing.
|
|
149
|
+
*/
|
|
150
|
+
export declare function applyTuning(): void;
|
|
151
|
+
/** The shell's depth at height `v` (0 = top, 1 = bottom). */
|
|
152
|
+
export declare function depthAtV(v: number): number;
|
|
153
|
+
/** A control's place on one shell's face, as a fraction: `u` across, `v` down. */
|
|
154
|
+
export interface FacePos {
|
|
155
|
+
/** Across the shell, 0 = outer edge … 1 = inner (rail) edge. */
|
|
156
|
+
u: number;
|
|
157
|
+
/** Down the shell, 0 = crown … 1 = base. */
|
|
158
|
+
v: number;
|
|
159
|
+
}
|
|
160
|
+
/** Convert a face position to world x/y within a shell centred on the origin. */
|
|
161
|
+
export declare function faceToLocal(p: FacePos): {
|
|
162
|
+
x: number;
|
|
163
|
+
y: number;
|
|
164
|
+
};
|
|
165
|
+
/**
|
|
166
|
+
* The LEFT half's controls, normalised from `JOYCON_LAYOUT` (shell x 24→104, y 16→142).
|
|
167
|
+
*
|
|
168
|
+
* The left half is the one with the stick UP TOP and four discrete direction buttons below it — not a
|
|
169
|
+
* cross. That is real: a Joy-Con's left half has four separate round buttons, which is why the flat
|
|
170
|
+
* layout models them individually too.
|
|
171
|
+
*/
|
|
172
|
+
export declare const LEFT_FACE: Record<string, FacePos>;
|
|
173
|
+
/** The RIGHT half's controls: the face diamond up top, stick below it. */
|
|
174
|
+
export declare const RIGHT_FACE: Record<string, FacePos>;
|
|
175
|
+
/**
|
|
176
|
+
* The shoulder row, on the TOP face of each half.
|
|
177
|
+
*
|
|
178
|
+
* `SR`/`SL` (the inner rail buttons) are omitted throughout: they only exist when a half is used
|
|
179
|
+
* sideways as its own controller, which is not how a paired set is held, and drawing a control the
|
|
180
|
+
* rider can't press is worse than drawing nothing — the same rule the flat layout follows.
|
|
181
|
+
*/
|
|
182
|
+
export declare const SHOULDER: {
|
|
183
|
+
/**
|
|
184
|
+
* Width and depth, PER KEY — they are not the same shape, and that is the point.
|
|
185
|
+
*
|
|
186
|
+
* Measured off the reference's top face:
|
|
187
|
+
* `L`/`R` a thin band across nearly the full width — 96% wide, 19% deep
|
|
188
|
+
* `ZL`/`ZR` a broad pad running back to the rear edge — 79% wide, 56% deep
|
|
189
|
+
*
|
|
190
|
+
* So the rear key takes almost THREE TIMES the depth of the front one while being slightly narrower.
|
|
191
|
+
* Giving them near-identical footprints (the previous version: 20% and 26% deep, same width) is what
|
|
192
|
+
* made the row read as two matching bars instead of a bumper and a trigger.
|
|
193
|
+
*
|
|
194
|
+
* The widths are pulled in slightly from the measured 0.96 / 0.79, because our crown is rounded
|
|
195
|
+
* harder than the reference's — a full-width band would hang off it.
|
|
196
|
+
*/
|
|
197
|
+
readonly bumperWidthFrac: 0.9;
|
|
198
|
+
readonly bumperDepthFrac: 0.19;
|
|
199
|
+
readonly triggerWidthFrac: 0.74;
|
|
200
|
+
readonly triggerDepthFrac: 0.56;
|
|
201
|
+
/**
|
|
202
|
+
* How far each stands proud of the top face.
|
|
203
|
+
*
|
|
204
|
+
* On the reference neither really does: the front band clears the shell by 0.0018, and the rear pad
|
|
205
|
+
* IS the shell's top surface, in a different colour. We keep a small lift so the two still read as
|
|
206
|
+
* separate controls from metres away, but nothing like the blocks this started as.
|
|
207
|
+
*/
|
|
208
|
+
readonly bumperRise: number;
|
|
209
|
+
readonly triggerRise: number;
|
|
210
|
+
/**
|
|
211
|
+
* How far `ZL`/`ZR` runs DOWN THE BACK of the shell, past the top-rear corner.
|
|
212
|
+
*
|
|
213
|
+
* The defining feature of the rear trigger, and the thing that separates it from a bumper: it is
|
|
214
|
+
* pressed with the index finger from behind, so it wraps the corner instead of lying on the crown.
|
|
215
|
+
* `L`/`R` has no wrap at all.
|
|
216
|
+
*/
|
|
217
|
+
readonly triggerWrap: number;
|
|
218
|
+
};
|
|
219
|
+
/**
|
|
220
|
+
* Default viewing angles, radians.
|
|
221
|
+
*
|
|
222
|
+
* A three-quarter view is the whole point: head-on, a 3D pad is indistinguishable from the flat one,
|
|
223
|
+
* and the triggers — the reason for modelling it at all — are invisible. Tilting the top towards the
|
|
224
|
+
* viewer reveals the top face; a slight yaw gives the shell's thickness somewhere to read.
|
|
225
|
+
*/
|
|
226
|
+
export declare const VIEW: {
|
|
227
|
+
/** Pitch, from {@link TUNING.pitchDeg}. Kept modest: the pad is 3× taller than wide, so pitch eats
|
|
228
|
+
* its apparent height fast and past ~35° you are looking down at its top face. */
|
|
229
|
+
readonly pitch: number;
|
|
230
|
+
/** Yaw: a slight turn so the pair isn't perfectly symmetric and the side walls catch light. */
|
|
231
|
+
yaw: number;
|
|
232
|
+
};
|
|
233
|
+
//# sourceMappingURL=joycon-spec.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"joycon-spec.d.ts","sourceRoot":"","sources":["../../../src/three/controller/joycon-spec.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH;;;;;;;;;;GAUG;AACH,eAAO,MAAM,MAAM;IAEjB;;;;;;;;OAQG;;;IAGH,mCAAmC;;IAEnC,8EAA8E;;IAE9E,8EAA8E;;;IAG9E,6CAA6C;;IAE7C,uDAAuD;;IAIvD,iGAAiG;;;;;IAOjG,sBAAsB;;;;IAItB,gEAAgE;;IAEhE,oCAAoC;;;;;IAKpC,sGAAsG;;IAEtG,iEAAiE;;IAIjE;;;;;;;;OAQG;;IAEH,qCAAqC;;IAErC,2DAA2D;;IAI3D,wFAAwF;;IAExF,4BAA4B;;CAE7B,CAAC;AAEF,mCAAmC;AACnC,eAAO,IAAI,CAAC,QAAqB,CAAC;AAGlC,mBAAmB;AACnB,eAAO,IAAI,CAAC,QAAoB,CAAC;AACjC,2DAA2D;AAC3D,eAAO,IAAI,SAAS,QAAsB,CAAC;AAC3C;;;;;;GAMG;AACH,eAAO,IAAI,YAAY,QAAyB,CAAC;AACjD,gFAAgF;AAChF,eAAO,IAAI,CAAC,QAAY,CAAC;AACzB,8BAA8B;AAC9B,eAAO,IAAI,GAAG,QAAiB,CAAC;AAChC,oCAAoC;AACpC,eAAO,IAAI,YAAY,QAAyB,CAAC;AAEjD;;;;;;GAMG;AACH,eAAO,IAAI,UAAU;;;;;CAKpB,CAAC;AAEF,qFAAqF;AACrF,eAAO,IAAI,KAAK;;;;;;;;;CASf,CAAC;AAGF;;;;;GAKG;AACH,wBAAgB,WAAW,IAAI,IAAI,CAwBlC;AAED,6DAA6D;AAC7D,wBAAgB,QAAQ,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAI1C;AAED,kFAAkF;AAClF,MAAM,WAAW,OAAO;IACtB,gEAAgE;IAChE,CAAC,EAAE,MAAM,CAAC;IACV,4CAA4C;IAC5C,CAAC,EAAE,MAAM,CAAC;CACX;AAED,iFAAiF;AACjF,wBAAgB,WAAW,CAAC,CAAC,EAAE,OAAO,GAAG;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAEhE;AAED;;;;;;GAMG;AACH,eAAO,MAAM,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAU7C,CAAC;AAEF,0EAA0E;AAC1E,eAAO,MAAM,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAa9C,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,QAAQ;IACnB;;;;;;;;;;;;;OAaG;;;;;IAKH;;;;;;OAMG;;;IAGH;;;;;;OAMG;;CAEK,CAAC;AAEX;;;;;;GAMG;AACH,eAAO,MAAM,IAAI;IACf;uFACmF;oBACtE,MAAM;IAGnB,+FAA+F;;CAEhG,CAAC"}
|
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WHAT A JOY-CON ACTUALLY IS, in numbers — the shared spec behind every 3D design.
|
|
3
|
+
*
|
|
4
|
+
* The first attempt at a 3D pad extruded the flat drawing's viewBox and gave it a little depth. That
|
|
5
|
+
* produced something that reads as *the flat pad, tilted*: the shell was 6× wider than it was thick,
|
|
6
|
+
* and the buttons stood 3% of their own diameter proud of it. Both are wrong. A real Joy-Con is
|
|
7
|
+
* **102 × 35.9 × 28.4 mm** — nearly as thick as it is wide, a bar rather than a plate — and its buttons
|
|
8
|
+
* are domes you could catch a fingernail on.
|
|
9
|
+
*
|
|
10
|
+
* So the geometry here is built from the HARDWARE's proportions, and the flat layout is used only for
|
|
11
|
+
* what it is genuinely authoritative about: **which control sits where on the face**, as a fraction of
|
|
12
|
+
* the shell. That split is deliberate —
|
|
13
|
+
*
|
|
14
|
+
* - the layout owns the *arrangement* (stick above the d-pad on the left, diamond above the stick on
|
|
15
|
+
* the right, `−` top-inner, Home bottom-centre), which is the thing every view depends on;
|
|
16
|
+
* - this file owns the *proportions*, which the layout deliberately distorts because a schematic
|
|
17
|
+
* drawing is not a scale drawing.
|
|
18
|
+
*
|
|
19
|
+
* Every number below was MEASURED off a reference Joy-Con model, not estimated: proportions, control
|
|
20
|
+
* positions, control sizes and how far each stands off the face. `u` runs 0 → 1 left-to-right across
|
|
21
|
+
* one shell, `v` runs 0 → 1 top-to-bottom.
|
|
22
|
+
*
|
|
23
|
+
* The measurements corrected two things the estimates got wrong: the halves sit much further apart
|
|
24
|
+
* than the flat drawing suggests (0.72 of a shell's width), and both control clusters are pushed
|
|
25
|
+
* INWARD, towards the middle of the pair, where the thumbs actually fall.
|
|
26
|
+
*/
|
|
27
|
+
/**
|
|
28
|
+
* THE TUNABLE NUMBERS.
|
|
29
|
+
*
|
|
30
|
+
* Everything below is derived from this object, and {@link applyTuning} recomputes the derived values
|
|
31
|
+
* in place. That exists so the shape can be dialled in from a control panel in the showcase instead of
|
|
32
|
+
* through an edit-rebuild-look loop — the person judging the shape is the one who should be turning
|
|
33
|
+
* the knobs.
|
|
34
|
+
*
|
|
35
|
+
* Values are RATIOS, not absolute sizes, so the pad stays coherent whatever you change: depths and
|
|
36
|
+
* radii are fractions of the shell's width, the width itself is a fraction of its height.
|
|
37
|
+
*/
|
|
38
|
+
export const TUNING = {
|
|
39
|
+
// ── proportions ──
|
|
40
|
+
/**
|
|
41
|
+
* Shell height and width, INDEPENDENTLY.
|
|
42
|
+
*
|
|
43
|
+
* They used to be one knob (a height ÷ width ratio), which meant you could not make the pad taller
|
|
44
|
+
* without also making it narrower. Everything else in this object is a fraction of the WIDTH, so
|
|
45
|
+
* depths, radii and control sizes still follow it — only the height is now free.
|
|
46
|
+
*
|
|
47
|
+
* For reference, the measured hardware ratio is 2.9869 : 1.
|
|
48
|
+
*/
|
|
49
|
+
shellHeight: 1.42,
|
|
50
|
+
shellWidth: 0.77,
|
|
51
|
+
/** Depth at the crown, ÷ width. */
|
|
52
|
+
depthTop: 0.625,
|
|
53
|
+
/** Depth at the base, ÷ width. The taper that makes room for the triggers. */
|
|
54
|
+
depthBottom: 0.461,
|
|
55
|
+
/** Height fraction (0 = crown) at which the taper happens, and how softly. */
|
|
56
|
+
breakV: 0.25,
|
|
57
|
+
breakSoft: 0.36,
|
|
58
|
+
/** Space between the two halves, ÷ width. */
|
|
59
|
+
gap: 0.7162,
|
|
60
|
+
/** Rounding of the shell's vertical edges, ÷ width. */
|
|
61
|
+
shellRadius: 0.17,
|
|
62
|
+
// ── silhouette ──
|
|
63
|
+
/** Corner radii of the face outline, ÷ width. Outer is the rounded side, inner the rail side. */
|
|
64
|
+
outerTopR: 0.5,
|
|
65
|
+
outerBottomR: 0.5,
|
|
66
|
+
innerTopR: 0.09,
|
|
67
|
+
innerBottomR: 0.09,
|
|
68
|
+
// ── controls ──
|
|
69
|
+
/** Radii, ÷ width. */
|
|
70
|
+
faceR: 0.07,
|
|
71
|
+
dpadR: 0.07,
|
|
72
|
+
systemR: 0.06,
|
|
73
|
+
/** How far a domed button stands proud of the face, ÷ width. */
|
|
74
|
+
buttonRise: 0.042,
|
|
75
|
+
/** `−` and `+` are nearly flush. */
|
|
76
|
+
systemRise: 0.008,
|
|
77
|
+
stickWellR: 0.215,
|
|
78
|
+
stickCapR: 0.15,
|
|
79
|
+
stickHeight: 0.17,
|
|
80
|
+
/** Height of the cap itself, ÷ its own radius. A real thumb cap is roughly 0.7 — it is not a disc. */
|
|
81
|
+
stickCapDepth: 0.7,
|
|
82
|
+
/** How deep the thumb dish sinks below the rim, ÷ cap radius. */
|
|
83
|
+
stickCapDish: 0.26,
|
|
84
|
+
// ── shoulders ──
|
|
85
|
+
/**
|
|
86
|
+
* The shoulder keys are the reference model's own triangles, so their SHAPE is fixed. What is
|
|
87
|
+
* adjustable is how they sit: pushed out along their normals so they clear the generated crown,
|
|
88
|
+
* lifted, and scaled.
|
|
89
|
+
*
|
|
90
|
+
* `lift` matters most, and must not be 0. On the reference, `ZL`'s surface IS the shell's top —
|
|
91
|
+
* coplanar with it. Ours is a separate mesh, so at 0 the two surfaces occupy the same plane and
|
|
92
|
+
* z-fight, which shows as a ragged hole in the key.
|
|
93
|
+
*/
|
|
94
|
+
shoulderLift: 0.008,
|
|
95
|
+
/** Extra vertical raise, ÷ width. */
|
|
96
|
+
shoulderRaise: 0.052,
|
|
97
|
+
/** Overall scale of the shoulder keys, 1 = as measured. */
|
|
98
|
+
shoulderScale: 1.07,
|
|
99
|
+
// ── view ──
|
|
100
|
+
/** Default camera pitch in DEGREES. Past ~35° the pad foreshortens into a plan view. */
|
|
101
|
+
pitchDeg: 21,
|
|
102
|
+
/** Camera field of view. */
|
|
103
|
+
fovDeg: 32,
|
|
104
|
+
};
|
|
105
|
+
/** Shell height in world units. */
|
|
106
|
+
export let H = TUNING.shellHeight;
|
|
107
|
+
/* eslint-disable prefer-const -- these are live bindings, rewritten by applyTuning(). */
|
|
108
|
+
/** Shell width. */
|
|
109
|
+
export let W = TUNING.shellWidth;
|
|
110
|
+
/** Depth at the TOP of the shell, where it is thickest. */
|
|
111
|
+
export let DEPTH_TOP = W * TUNING.depthTop;
|
|
112
|
+
/**
|
|
113
|
+
* Depth at the BOTTOM.
|
|
114
|
+
*
|
|
115
|
+
* Measured at 58% of the top, and it is the shape's whole point: the shell is a wedge, thick at the
|
|
116
|
+
* top and tapering down. The bulge makes room for the triggers, and it is entirely on the BACK — the
|
|
117
|
+
* front face, where every button lives, is dead flat top to bottom.
|
|
118
|
+
*/
|
|
119
|
+
export let DEPTH_BOTTOM = W * TUNING.depthBottom;
|
|
120
|
+
/** Deepest the shell ever gets — what the pair's bounding box is sized from. */
|
|
121
|
+
export let D = DEPTH_TOP;
|
|
122
|
+
/** Gap between the halves. */
|
|
123
|
+
export let GAP = W * TUNING.gap;
|
|
124
|
+
/** Corner rounding of the shell. */
|
|
125
|
+
export let SHELL_RADIUS = W * TUNING.shellRadius;
|
|
126
|
+
/**
|
|
127
|
+
* The silhouette is ASYMMETRIC, and that is the shape's signature.
|
|
128
|
+
*
|
|
129
|
+
* The INNER edge — the one carrying the rail, that docks against the console — runs dead straight from
|
|
130
|
+
* top to bottom. All the rounding is on the OUTER edge. A symmetric rounded rectangle reads as a
|
|
131
|
+
* generic slab; this is what makes it a Joy-Con.
|
|
132
|
+
*/
|
|
133
|
+
export let SILHOUETTE = {
|
|
134
|
+
outerTopR: W * TUNING.outerTopR,
|
|
135
|
+
outerBottomR: W * TUNING.outerBottomR,
|
|
136
|
+
innerTopR: W * TUNING.innerTopR,
|
|
137
|
+
innerBottomR: W * TUNING.innerBottomR,
|
|
138
|
+
};
|
|
139
|
+
/** Control sizes, as fractions of the shell width — so they scale with the model. */
|
|
140
|
+
export let SIZES = {
|
|
141
|
+
faceR: W * TUNING.faceR,
|
|
142
|
+
dpadR: W * TUNING.dpadR,
|
|
143
|
+
systemR: W * TUNING.systemR,
|
|
144
|
+
stickWellR: W * TUNING.stickWellR,
|
|
145
|
+
stickCapR: W * TUNING.stickCapR,
|
|
146
|
+
stickHeight: W * TUNING.stickHeight,
|
|
147
|
+
buttonRise: W * TUNING.buttonRise,
|
|
148
|
+
systemRise: W * TUNING.systemRise,
|
|
149
|
+
};
|
|
150
|
+
/* eslint-enable prefer-const */
|
|
151
|
+
/**
|
|
152
|
+
* Recompute every derived value from {@link TUNING}.
|
|
153
|
+
*
|
|
154
|
+
* Call after changing TUNING and before rebuilding a model. The exports above are ES module live
|
|
155
|
+
* bindings, so importers see the new numbers without re-importing.
|
|
156
|
+
*/
|
|
157
|
+
export function applyTuning() {
|
|
158
|
+
H = TUNING.shellHeight;
|
|
159
|
+
W = TUNING.shellWidth;
|
|
160
|
+
DEPTH_TOP = W * TUNING.depthTop;
|
|
161
|
+
DEPTH_BOTTOM = W * TUNING.depthBottom;
|
|
162
|
+
D = DEPTH_TOP;
|
|
163
|
+
GAP = W * TUNING.gap;
|
|
164
|
+
SHELL_RADIUS = W * TUNING.shellRadius;
|
|
165
|
+
SILHOUETTE = {
|
|
166
|
+
outerTopR: W * TUNING.outerTopR,
|
|
167
|
+
outerBottomR: W * TUNING.outerBottomR,
|
|
168
|
+
innerTopR: W * TUNING.innerTopR,
|
|
169
|
+
innerBottomR: W * TUNING.innerBottomR,
|
|
170
|
+
};
|
|
171
|
+
SIZES = {
|
|
172
|
+
faceR: W * TUNING.faceR,
|
|
173
|
+
dpadR: W * TUNING.dpadR,
|
|
174
|
+
systemR: W * TUNING.systemR,
|
|
175
|
+
stickWellR: W * TUNING.stickWellR,
|
|
176
|
+
stickCapR: W * TUNING.stickCapR,
|
|
177
|
+
stickHeight: W * TUNING.stickHeight,
|
|
178
|
+
buttonRise: W * TUNING.buttonRise,
|
|
179
|
+
systemRise: W * TUNING.systemRise,
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
/** The shell's depth at height `v` (0 = top, 1 = bottom). */
|
|
183
|
+
export function depthAtV(v) {
|
|
184
|
+
const t = Math.min(1, Math.max(0, (v - TUNING.breakV) / TUNING.breakSoft));
|
|
185
|
+
const smooth = t * t * (3 - 2 * t);
|
|
186
|
+
return DEPTH_TOP + (DEPTH_BOTTOM - DEPTH_TOP) * smooth;
|
|
187
|
+
}
|
|
188
|
+
/** Convert a face position to world x/y within a shell centred on the origin. */
|
|
189
|
+
export function faceToLocal(p) {
|
|
190
|
+
return { x: (p.u - 0.5) * W, y: (0.5 - p.v) * H };
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* The LEFT half's controls, normalised from `JOYCON_LAYOUT` (shell x 24→104, y 16→142).
|
|
194
|
+
*
|
|
195
|
+
* The left half is the one with the stick UP TOP and four discrete direction buttons below it — not a
|
|
196
|
+
* cross. That is real: a Joy-Con's left half has four separate round buttons, which is why the flat
|
|
197
|
+
* layout models them individually too.
|
|
198
|
+
*/
|
|
199
|
+
export const LEFT_FACE = {
|
|
200
|
+
stick: { u: 0.568, v: 0.284 },
|
|
201
|
+
dpadUp: { u: 0.600, v: 0.465 },
|
|
202
|
+
dpadDown: { u: 0.600, v: 0.600 },
|
|
203
|
+
dpadLeft: { u: 0.395, v: 0.531 },
|
|
204
|
+
dpadRight: { u: 0.792, v: 0.531 },
|
|
205
|
+
/** `−`, top INNER corner — towards the right half. */
|
|
206
|
+
select: { u: 0.79, v: 0.124 },
|
|
207
|
+
/** The square capture button, bottom. */
|
|
208
|
+
capture: { u: 0.742, v: 0.707 },
|
|
209
|
+
};
|
|
210
|
+
/** The RIGHT half's controls: the face diamond up top, stick below it. */
|
|
211
|
+
export const RIGHT_FACE = {
|
|
212
|
+
/** X — top of the diamond. Glyphs are in TRUE PHYSICAL places, as on the hardware. */
|
|
213
|
+
faceTop: { u: 0.442, v: 0.231 },
|
|
214
|
+
/** A — right. */
|
|
215
|
+
faceRight: { u: 0.633, v: 0.297 },
|
|
216
|
+
/** B — bottom. */
|
|
217
|
+
faceBottom: { u: 0.442, v: 0.365 },
|
|
218
|
+
/** Y — left. */
|
|
219
|
+
faceLeft: { u: 0.237, v: 0.297 },
|
|
220
|
+
stick: { u: 0.429, v: 0.569 },
|
|
221
|
+
/** `+`, top INNER corner — towards the left half. */
|
|
222
|
+
start: { u: 0.21, v: 0.124 },
|
|
223
|
+
home: { u: 0.299, v: 0.738 },
|
|
224
|
+
};
|
|
225
|
+
/**
|
|
226
|
+
* The shoulder row, on the TOP face of each half.
|
|
227
|
+
*
|
|
228
|
+
* `SR`/`SL` (the inner rail buttons) are omitted throughout: they only exist when a half is used
|
|
229
|
+
* sideways as its own controller, which is not how a paired set is held, and drawing a control the
|
|
230
|
+
* rider can't press is worse than drawing nothing — the same rule the flat layout follows.
|
|
231
|
+
*/
|
|
232
|
+
export const SHOULDER = {
|
|
233
|
+
/**
|
|
234
|
+
* Width and depth, PER KEY — they are not the same shape, and that is the point.
|
|
235
|
+
*
|
|
236
|
+
* Measured off the reference's top face:
|
|
237
|
+
* `L`/`R` a thin band across nearly the full width — 96% wide, 19% deep
|
|
238
|
+
* `ZL`/`ZR` a broad pad running back to the rear edge — 79% wide, 56% deep
|
|
239
|
+
*
|
|
240
|
+
* So the rear key takes almost THREE TIMES the depth of the front one while being slightly narrower.
|
|
241
|
+
* Giving them near-identical footprints (the previous version: 20% and 26% deep, same width) is what
|
|
242
|
+
* made the row read as two matching bars instead of a bumper and a trigger.
|
|
243
|
+
*
|
|
244
|
+
* The widths are pulled in slightly from the measured 0.96 / 0.79, because our crown is rounded
|
|
245
|
+
* harder than the reference's — a full-width band would hang off it.
|
|
246
|
+
*/
|
|
247
|
+
bumperWidthFrac: 0.9,
|
|
248
|
+
bumperDepthFrac: 0.19,
|
|
249
|
+
triggerWidthFrac: 0.74,
|
|
250
|
+
triggerDepthFrac: 0.56,
|
|
251
|
+
/**
|
|
252
|
+
* How far each stands proud of the top face.
|
|
253
|
+
*
|
|
254
|
+
* On the reference neither really does: the front band clears the shell by 0.0018, and the rear pad
|
|
255
|
+
* IS the shell's top surface, in a different colour. We keep a small lift so the two still read as
|
|
256
|
+
* separate controls from metres away, but nothing like the blocks this started as.
|
|
257
|
+
*/
|
|
258
|
+
bumperRise: W * 0.05,
|
|
259
|
+
triggerRise: W * 0.085,
|
|
260
|
+
/**
|
|
261
|
+
* How far `ZL`/`ZR` runs DOWN THE BACK of the shell, past the top-rear corner.
|
|
262
|
+
*
|
|
263
|
+
* The defining feature of the rear trigger, and the thing that separates it from a bumper: it is
|
|
264
|
+
* pressed with the index finger from behind, so it wraps the corner instead of lying on the crown.
|
|
265
|
+
* `L`/`R` has no wrap at all.
|
|
266
|
+
*/
|
|
267
|
+
triggerWrap: W * 0.34,
|
|
268
|
+
};
|
|
269
|
+
/**
|
|
270
|
+
* Default viewing angles, radians.
|
|
271
|
+
*
|
|
272
|
+
* A three-quarter view is the whole point: head-on, a 3D pad is indistinguishable from the flat one,
|
|
273
|
+
* and the triggers — the reason for modelling it at all — are invisible. Tilting the top towards the
|
|
274
|
+
* viewer reveals the top face; a slight yaw gives the shell's thickness somewhere to read.
|
|
275
|
+
*/
|
|
276
|
+
export const VIEW = {
|
|
277
|
+
/** Pitch, from {@link TUNING.pitchDeg}. Kept modest: the pad is 3× taller than wide, so pitch eats
|
|
278
|
+
* its apparent height fast and past ~35° you are looking down at its top face. */
|
|
279
|
+
get pitch() {
|
|
280
|
+
return (TUNING.pitchDeg * Math.PI) / 180;
|
|
281
|
+
},
|
|
282
|
+
/** Yaw: a slight turn so the pair isn't perfectly symmetric and the side walls catch light. */
|
|
283
|
+
yaw: -0.34,
|
|
284
|
+
};
|
|
285
|
+
//# sourceMappingURL=joycon-spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"joycon-spec.js","sourceRoot":"","sources":["../../../src/three/controller/joycon-spec.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* THE 3D PAD RENDERER — a Joy-Con pair in three.js, drop-in wherever the flat drawing goes.
|
|
3
|
+
*
|
|
4
|
+
* ```ts
|
|
5
|
+
* import { createThreePadRenderer } from "@rydr/game-sdk/three";
|
|
6
|
+
* import { mountControllerMap } from "@rydr/game-sdk/ui";
|
|
7
|
+
*
|
|
8
|
+
* mountControllerMap(host, { press: session, actions, renderer: createThreePadRenderer });
|
|
9
|
+
* ```
|
|
10
|
+
*
|
|
11
|
+
* It satisfies `PadRenderer` (see `ui/controller/renderer.ts`), which is the entire contract the five
|
|
12
|
+
* controller views speak. So the map's leader lines, the combo demo's timeline, the spotlight's
|
|
13
|
+
* captions and the guided lesson's gating all work against it **unchanged** — none of them knows or
|
|
14
|
+
* cares that there is a WebGL canvas where an `<svg>` used to be.
|
|
15
|
+
*
|
|
16
|
+
* ## What the third dimension actually buys
|
|
17
|
+
*
|
|
18
|
+
* Two things the flat pad could not say:
|
|
19
|
+
*
|
|
20
|
+
* 1. **The triggers are visible.** `ZL`/`ZR` live on the back of each half. The flat drawing had to
|
|
21
|
+
* float them above the shell (that's what the `y −20` band in `PAD_VIEWBOX` is for). Here they sit
|
|
22
|
+
* where they really are, and the pad tilts forward just enough to show them.
|
|
23
|
+
* 2. **A press is a press.** The flat pad simulates depth by dropping a shape onto its own drop
|
|
24
|
+
* shadow. Here the button actually moves along the viewing axis, and a stick actually leans.
|
|
25
|
+
*
|
|
26
|
+
* ## Only the Joy-Con
|
|
27
|
+
*
|
|
28
|
+
* `brand: "joycon"` is the one silhouette modelled — it's what PLAT-1556 asked for, and it happens to
|
|
29
|
+
* be the most tractable shape in the kit (two rounded slabs rather than one organic shell). Ask this
|
|
30
|
+
* renderer for any other brand and it says so and draws the Joy-Con anyway, rather than failing: a
|
|
31
|
+
* caller who pinned `brand` has a bug, and a blank canvas hides it.
|
|
32
|
+
*
|
|
33
|
+
* ## Cost
|
|
34
|
+
*
|
|
35
|
+
* One WebGL context per mounted pad, and browsers cap those (~8–16). A page showing several 3D views at
|
|
36
|
+
* once is close to that ceiling — which is why the render loop is shared, idle-skipping and paused on a
|
|
37
|
+
* hidden tab: a pad nobody is touching costs nothing per frame, exactly like the flat one's dirty-guard.
|
|
38
|
+
*/
|
|
39
|
+
import { type PadRenderer, type PadRendererOptions } from "../../ui/controller/renderer.js";
|
|
40
|
+
import type { PadLayout } from "../../ui/controller/types.js";
|
|
41
|
+
import { type JoyconDesignId } from "./joycon-designs.js";
|
|
42
|
+
export interface ThreePadRendererOptions extends PadRendererOptions {
|
|
43
|
+
/** Which art direction to draw. Default `"toy"` — the one built for reading at a distance. */
|
|
44
|
+
design?: JoyconDesignId;
|
|
45
|
+
/** Forward tilt in radians. Default {@link VIEW.pitch}. */
|
|
46
|
+
tilt?: number;
|
|
47
|
+
/** Turn about the vertical axis, radians. Default 0 — head-on. */
|
|
48
|
+
yaw?: number;
|
|
49
|
+
/**
|
|
50
|
+
* Extra forward tilt applied while a TRIGGER is being shown, radians. Default 0.38 (~22°).
|
|
51
|
+
*
|
|
52
|
+
* This is the reason the pad is modelled in 3D at all. `ZL`/`ZR` sit on the back of the crown: from
|
|
53
|
+
* the reading angle they are edge-on, and a view teaching one would be pointing at a sliver. When a
|
|
54
|
+
* trigger lights, the pad rolls forward so the top face — and the key — come into view, then rolls
|
|
55
|
+
* back when it is released. The flat pad had to draw the triggers floating above the shell instead,
|
|
56
|
+
* which is a picture of a controller that does not exist.
|
|
57
|
+
*
|
|
58
|
+
* Set to 0 to pin the pad still.
|
|
59
|
+
*/
|
|
60
|
+
triggerTilt?: number;
|
|
61
|
+
/** Seconds the roll takes, each way. Default 0.42. */
|
|
62
|
+
triggerTiltMs?: number;
|
|
63
|
+
/**
|
|
64
|
+
* How much of the frame the pad fills, 0…1. Default 0.82.
|
|
65
|
+
*
|
|
66
|
+
* A control map surrounds the pad with callout cards, so it wants a smaller pad than a view showing
|
|
67
|
+
* the pad alone; this is the knob for that rather than resizing the host.
|
|
68
|
+
*/
|
|
69
|
+
fill?: number;
|
|
70
|
+
/** Nudge within the frame, in fractions of the frame. Positive x is right, positive y is up. */
|
|
71
|
+
offsetX?: number;
|
|
72
|
+
offsetY?: number;
|
|
73
|
+
/** Device pixel ratio cap. Default 2 — past that a pad this small costs pixels for nothing. */
|
|
74
|
+
maxPixelRatio?: number;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Build a three.js pad renderer. Matches {@link PadRendererFactory}, so it can be handed straight to
|
|
78
|
+
* any controller view's `renderer` option.
|
|
79
|
+
*/
|
|
80
|
+
export declare function createThreePadRenderer(layout: PadLayout, opts?: ThreePadRendererOptions): PadRenderer;
|
|
81
|
+
//# sourceMappingURL=three-pad-renderer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"three-pad-renderer.d.ts","sourceRoot":"","sources":["../../../src/three/controller/three-pad-renderer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAKH,OAAO,EAEL,KAAK,WAAW,EAChB,KAAK,kBAAkB,EAExB,MAAM,iCAAiC,CAAC;AACzC,OAAO,KAAK,EAAE,SAAS,EAAW,MAAM,8BAA8B,CAAC;AACvE,OAAO,EAAoC,KAAK,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAmC5F,MAAM,WAAW,uBAAwB,SAAQ,kBAAkB;IACjE,8FAA8F;IAC9F,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB,2DAA2D;IAC3D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,kEAAkE;IAClE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;;;;;;;;;OAUG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,sDAAsD;IACtD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;;OAKG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,gGAAgG;IAChG,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,+FAA+F;IAC/F,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,SAAS,EACjB,IAAI,GAAE,uBAA4B,GACjC,WAAW,CAuXb"}
|