@codexo/exojs 0.7.12 → 0.8.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 (219) hide show
  1. package/CHANGELOG.md +737 -0
  2. package/dist/esm/core/Application.d.ts +3 -1
  3. package/dist/esm/core/Application.js +7 -6
  4. package/dist/esm/core/Application.js.map +1 -1
  5. package/dist/esm/core/Scene.d.ts +30 -0
  6. package/dist/esm/core/Scene.js +56 -0
  7. package/dist/esm/core/Scene.js.map +1 -1
  8. package/dist/esm/core/SceneManager.js +2 -2
  9. package/dist/esm/core/SceneManager.js.map +1 -1
  10. package/dist/esm/debug/DebugOverlay.js +2 -2
  11. package/dist/esm/debug/DebugOverlay.js.map +1 -1
  12. package/dist/esm/debug/PointerStackLayer.js +1 -1
  13. package/dist/esm/debug/PointerStackLayer.js.map +1 -1
  14. package/dist/esm/index.js +32 -10
  15. package/dist/esm/index.js.map +1 -1
  16. package/dist/esm/input/ArcadeStickGamepadMapping.js +18 -19
  17. package/dist/esm/input/ArcadeStickGamepadMapping.js.map +1 -1
  18. package/dist/esm/input/Gamepad.d.ts +164 -62
  19. package/dist/esm/input/Gamepad.js +290 -134
  20. package/dist/esm/input/Gamepad.js.map +1 -1
  21. package/dist/esm/input/GamepadAxis.d.ts +120 -0
  22. package/dist/esm/input/GamepadAxis.js +106 -0
  23. package/dist/esm/input/GamepadAxis.js.map +1 -0
  24. package/dist/esm/input/GamepadButton.d.ts +110 -0
  25. package/dist/esm/input/GamepadButton.js +99 -0
  26. package/dist/esm/input/GamepadButton.js.map +1 -0
  27. package/dist/esm/input/GamepadDefinitions.js +4 -0
  28. package/dist/esm/input/GamepadDefinitions.js.map +1 -1
  29. package/dist/esm/input/GamepadMapping.d.ts +28 -24
  30. package/dist/esm/input/GamepadMapping.js +33 -16
  31. package/dist/esm/input/GamepadMapping.js.map +1 -1
  32. package/dist/esm/input/GamepadPromptLayouts.d.ts +10 -8
  33. package/dist/esm/input/GamepadPromptLayouts.js +21 -20
  34. package/dist/esm/input/GamepadPromptLayouts.js.map +1 -1
  35. package/dist/esm/input/GenericDualAnalogGamepadMapping.d.ts +6 -3
  36. package/dist/esm/input/GenericDualAnalogGamepadMapping.js +55 -46
  37. package/dist/esm/input/GenericDualAnalogGamepadMapping.js.map +1 -1
  38. package/dist/esm/input/InputBinding.d.ts +74 -0
  39. package/dist/esm/input/InputBinding.js +100 -0
  40. package/dist/esm/input/InputBinding.js.map +1 -0
  41. package/dist/esm/input/InputManager.d.ts +79 -33
  42. package/dist/esm/input/InputManager.js +229 -104
  43. package/dist/esm/input/InputManager.js.map +1 -1
  44. package/dist/esm/input/InteractionManager.d.ts +1 -1
  45. package/dist/esm/input/InteractionManager.js +13 -13
  46. package/dist/esm/input/InteractionManager.js.map +1 -1
  47. package/dist/esm/input/JoyConLeftGamepadMapping.d.ts +14 -9
  48. package/dist/esm/input/JoyConLeftGamepadMapping.js +39 -9
  49. package/dist/esm/input/JoyConLeftGamepadMapping.js.map +1 -1
  50. package/dist/esm/input/JoyConRightGamepadMapping.d.ts +14 -9
  51. package/dist/esm/input/JoyConRightGamepadMapping.js +35 -9
  52. package/dist/esm/input/JoyConRightGamepadMapping.js.map +1 -1
  53. package/dist/esm/input/Pointer.d.ts +84 -71
  54. package/dist/esm/input/Pointer.js +71 -71
  55. package/dist/esm/input/Pointer.js.map +1 -1
  56. package/dist/esm/input/SteamDeckGamepadMapping.d.ts +18 -0
  57. package/dist/esm/input/SteamDeckGamepadMapping.js +76 -0
  58. package/dist/esm/input/SteamDeckGamepadMapping.js.map +1 -0
  59. package/dist/esm/input/index.d.ts +7 -4
  60. package/dist/esm/input/types.d.ts +0 -76
  61. package/dist/esm/input/types.js +1 -80
  62. package/dist/esm/input/types.js.map +1 -1
  63. package/dist/esm/particles/ParticleSystem.d.ts +180 -83
  64. package/dist/esm/particles/ParticleSystem.js +446 -133
  65. package/dist/esm/particles/ParticleSystem.js.map +1 -1
  66. package/dist/esm/particles/distributions/BoxArea.d.ts +17 -0
  67. package/dist/esm/particles/distributions/BoxArea.js +48 -0
  68. package/dist/esm/particles/distributions/BoxArea.js.map +1 -0
  69. package/dist/esm/particles/distributions/CircleArea.d.ts +19 -0
  70. package/dist/esm/particles/distributions/CircleArea.js +33 -0
  71. package/dist/esm/particles/distributions/CircleArea.js.map +1 -0
  72. package/dist/esm/particles/distributions/ConeDirection.d.ts +28 -0
  73. package/dist/esm/particles/distributions/ConeDirection.js +44 -0
  74. package/dist/esm/particles/distributions/ConeDirection.js.map +1 -0
  75. package/dist/esm/particles/distributions/Constant.d.ts +17 -0
  76. package/dist/esm/particles/distributions/Constant.js +35 -0
  77. package/dist/esm/particles/distributions/Constant.js.map +1 -0
  78. package/dist/esm/particles/distributions/Curve.d.ts +30 -0
  79. package/dist/esm/particles/distributions/Curve.js +53 -0
  80. package/dist/esm/particles/distributions/Curve.js.map +1 -0
  81. package/dist/esm/particles/distributions/Distribution.d.ts +45 -0
  82. package/dist/esm/particles/distributions/Gradient.d.ts +40 -0
  83. package/dist/esm/particles/distributions/Gradient.js +72 -0
  84. package/dist/esm/particles/distributions/Gradient.js.map +1 -0
  85. package/dist/esm/particles/distributions/LineSegment.d.ts +15 -0
  86. package/dist/esm/particles/distributions/LineSegment.js +27 -0
  87. package/dist/esm/particles/distributions/LineSegment.js.map +1 -0
  88. package/dist/esm/particles/distributions/Range.d.ts +12 -0
  89. package/dist/esm/particles/distributions/Range.js +19 -0
  90. package/dist/esm/particles/distributions/Range.js.map +1 -0
  91. package/dist/esm/particles/distributions/VectorRange.d.ts +20 -0
  92. package/dist/esm/particles/distributions/VectorRange.js +31 -0
  93. package/dist/esm/particles/distributions/VectorRange.js.map +1 -0
  94. package/dist/esm/particles/distributions/index.d.ts +12 -0
  95. package/dist/esm/particles/gpu/ParticleGpuState.d.ts +57 -0
  96. package/dist/esm/particles/gpu/ParticleGpuState.js +508 -0
  97. package/dist/esm/particles/gpu/ParticleGpuState.js.map +1 -0
  98. package/dist/esm/particles/index.d.ts +2 -10
  99. package/dist/esm/particles/modules/AlphaFadeOverLifetime.d.ts +24 -0
  100. package/dist/esm/particles/modules/AlphaFadeOverLifetime.js +60 -0
  101. package/dist/esm/particles/modules/AlphaFadeOverLifetime.js.map +1 -0
  102. package/dist/esm/particles/modules/ApplyForce.d.ts +20 -0
  103. package/dist/esm/particles/modules/ApplyForce.js +48 -0
  104. package/dist/esm/particles/modules/ApplyForce.js.map +1 -0
  105. package/dist/esm/particles/modules/AttractToPoint.d.ts +27 -0
  106. package/dist/esm/particles/modules/AttractToPoint.js +73 -0
  107. package/dist/esm/particles/modules/AttractToPoint.js.map +1 -0
  108. package/dist/esm/particles/modules/BurstSpawn.d.ts +53 -0
  109. package/dist/esm/particles/modules/BurstSpawn.js +94 -0
  110. package/dist/esm/particles/modules/BurstSpawn.js.map +1 -0
  111. package/dist/esm/particles/modules/ColorOverLifetime.d.ts +22 -0
  112. package/dist/esm/particles/modules/ColorOverLifetime.js +65 -0
  113. package/dist/esm/particles/modules/ColorOverLifetime.js.map +1 -0
  114. package/dist/esm/particles/modules/ColorOverSpeed.d.ts +27 -0
  115. package/dist/esm/particles/modules/ColorOverSpeed.js +86 -0
  116. package/dist/esm/particles/modules/ColorOverSpeed.js.map +1 -0
  117. package/dist/esm/particles/modules/DeathModule.d.ts +24 -0
  118. package/dist/esm/particles/modules/DeathModule.js +25 -0
  119. package/dist/esm/particles/modules/DeathModule.js.map +1 -0
  120. package/dist/esm/particles/modules/Drag.d.ts +20 -0
  121. package/dist/esm/particles/modules/Drag.js +45 -0
  122. package/dist/esm/particles/modules/Drag.js.map +1 -0
  123. package/dist/esm/particles/modules/OrbitalForce.d.ts +28 -0
  124. package/dist/esm/particles/modules/OrbitalForce.js +65 -0
  125. package/dist/esm/particles/modules/OrbitalForce.js.map +1 -0
  126. package/dist/esm/particles/modules/RateSpawn.d.ts +41 -0
  127. package/dist/esm/particles/modules/RateSpawn.js +76 -0
  128. package/dist/esm/particles/modules/RateSpawn.js.map +1 -0
  129. package/dist/esm/particles/modules/RepelFromPoint.d.ts +24 -0
  130. package/dist/esm/particles/modules/RepelFromPoint.js +76 -0
  131. package/dist/esm/particles/modules/RepelFromPoint.js.map +1 -0
  132. package/dist/esm/particles/modules/RotateOverLifetime.d.ts +20 -0
  133. package/dist/esm/particles/modules/RotateOverLifetime.js +43 -0
  134. package/dist/esm/particles/modules/RotateOverLifetime.js.map +1 -0
  135. package/dist/esm/particles/modules/ScaleOverLifetime.d.ts +26 -0
  136. package/dist/esm/particles/modules/ScaleOverLifetime.js +59 -0
  137. package/dist/esm/particles/modules/ScaleOverLifetime.js.map +1 -0
  138. package/dist/esm/particles/modules/SpawnModule.d.ts +30 -0
  139. package/dist/esm/particles/modules/SpawnModule.js +31 -0
  140. package/dist/esm/particles/modules/SpawnModule.js.map +1 -0
  141. package/dist/esm/particles/modules/SpawnOnDeath.d.ts +24 -0
  142. package/dist/esm/particles/modules/SpawnOnDeath.js +47 -0
  143. package/dist/esm/particles/modules/SpawnOnDeath.js.map +1 -0
  144. package/dist/esm/particles/modules/Turbulence.d.ts +30 -0
  145. package/dist/esm/particles/modules/Turbulence.js +122 -0
  146. package/dist/esm/particles/modules/Turbulence.js.map +1 -0
  147. package/dist/esm/particles/modules/UpdateModule.d.ts +95 -0
  148. package/dist/esm/particles/modules/UpdateModule.js +66 -0
  149. package/dist/esm/particles/modules/UpdateModule.js.map +1 -0
  150. package/dist/esm/particles/modules/VelocityOverLifetime.d.ts +30 -0
  151. package/dist/esm/particles/modules/VelocityOverLifetime.js +84 -0
  152. package/dist/esm/particles/modules/VelocityOverLifetime.js.map +1 -0
  153. package/dist/esm/particles/modules/WgslContribution.d.ts +81 -0
  154. package/dist/esm/particles/modules/WgslContribution.js +34 -0
  155. package/dist/esm/particles/modules/WgslContribution.js.map +1 -0
  156. package/dist/esm/particles/modules/index.d.ts +22 -0
  157. package/dist/esm/rendering/webgl2/WebGl2ParticleRenderer.d.ts +9 -14
  158. package/dist/esm/rendering/webgl2/WebGl2ParticleRenderer.js +90 -61
  159. package/dist/esm/rendering/webgl2/WebGl2ParticleRenderer.js.map +1 -1
  160. package/dist/esm/rendering/webgl2/glsl/particle.vert.js +1 -1
  161. package/dist/esm/rendering/webgpu/WebGpuParticleRenderer.d.ts +9 -0
  162. package/dist/esm/rendering/webgpu/WebGpuParticleRenderer.js +107 -23
  163. package/dist/esm/rendering/webgpu/WebGpuParticleRenderer.js.map +1 -1
  164. package/dist/esm/rendering/webgpu/compute/WebGpuComputePipeline.d.ts +52 -0
  165. package/dist/esm/rendering/webgpu/compute/WebGpuStorageBuffer.d.ts +29 -0
  166. package/dist/esm/rendering/webgpu/compute/index.d.ts +3 -0
  167. package/dist/esm/resources/CacheFirstStrategy.d.ts +7 -4
  168. package/dist/esm/resources/CacheFirstStrategy.js +11 -8
  169. package/dist/esm/resources/CacheFirstStrategy.js.map +1 -1
  170. package/dist/esm/resources/CacheStrategy.d.ts +14 -6
  171. package/dist/esm/resources/Loader.d.ts +8 -3
  172. package/dist/esm/resources/Loader.js +19 -37
  173. package/dist/esm/resources/Loader.js.map +1 -1
  174. package/dist/esm/resources/NetworkOnlyStrategy.d.ts +3 -0
  175. package/dist/esm/resources/NetworkOnlyStrategy.js +8 -3
  176. package/dist/esm/resources/NetworkOnlyStrategy.js.map +1 -1
  177. package/dist/esm/resources/factories/ImageFactory.d.ts +2 -2
  178. package/dist/esm/resources/factories/ImageFactory.js.map +1 -1
  179. package/dist/esm/resources/factories/TextureFactory.d.ts +2 -2
  180. package/dist/esm/resources/factories/TextureFactory.js.map +1 -1
  181. package/dist/esm/resources/factories/VttFactory.d.ts +3 -3
  182. package/dist/esm/resources/factories/VttFactory.js +83 -6
  183. package/dist/esm/resources/factories/VttFactory.js.map +1 -1
  184. package/dist/exo.esm.js +4028 -1518
  185. package/dist/exo.esm.js.map +1 -1
  186. package/package.json +2 -1
  187. package/dist/esm/input/GamepadChannels.d.ts +0 -47
  188. package/dist/esm/input/GamepadChannels.js +0 -53
  189. package/dist/esm/input/GamepadChannels.js.map +0 -1
  190. package/dist/esm/input/GamepadControl.d.ts +0 -33
  191. package/dist/esm/input/GamepadControl.js +0 -42
  192. package/dist/esm/input/GamepadControl.js.map +0 -1
  193. package/dist/esm/input/Input.d.ts +0 -52
  194. package/dist/esm/input/Input.js +0 -90
  195. package/dist/esm/input/Input.js.map +0 -1
  196. package/dist/esm/particles/Particle.d.ts +0 -77
  197. package/dist/esm/particles/Particle.js +0 -143
  198. package/dist/esm/particles/Particle.js.map +0 -1
  199. package/dist/esm/particles/ParticleProperties.d.ts +0 -29
  200. package/dist/esm/particles/affectors/ColorAffector.d.ts +0 -30
  201. package/dist/esm/particles/affectors/ColorAffector.js +0 -55
  202. package/dist/esm/particles/affectors/ColorAffector.js.map +0 -1
  203. package/dist/esm/particles/affectors/ForceAffector.d.ts +0 -24
  204. package/dist/esm/particles/affectors/ForceAffector.js +0 -39
  205. package/dist/esm/particles/affectors/ForceAffector.js.map +0 -1
  206. package/dist/esm/particles/affectors/ParticleAffector.d.ts +0 -19
  207. package/dist/esm/particles/affectors/ScaleAffector.d.ts +0 -23
  208. package/dist/esm/particles/affectors/ScaleAffector.js +0 -38
  209. package/dist/esm/particles/affectors/ScaleAffector.js.map +0 -1
  210. package/dist/esm/particles/affectors/TorqueAffector.d.ts +0 -23
  211. package/dist/esm/particles/affectors/TorqueAffector.js +0 -37
  212. package/dist/esm/particles/affectors/TorqueAffector.js.map +0 -1
  213. package/dist/esm/particles/emitters/ParticleEmitter.d.ts +0 -19
  214. package/dist/esm/particles/emitters/ParticleOptions.d.ts +0 -62
  215. package/dist/esm/particles/emitters/ParticleOptions.js +0 -120
  216. package/dist/esm/particles/emitters/ParticleOptions.js.map +0 -1
  217. package/dist/esm/particles/emitters/UniversalEmitter.d.ts +0 -40
  218. package/dist/esm/particles/emitters/UniversalEmitter.js +0 -68
  219. package/dist/esm/particles/emitters/UniversalEmitter.js.map +0 -1
@@ -1,194 +1,350 @@
1
1
  import { Signal } from '../core/Signal.js';
2
2
  import { ChannelOffset, ChannelSize } from './types.js';
3
+ import { InputBinding } from './InputBinding.js';
3
4
 
4
5
  /**
5
- * Runtime wrapper for a single browser gamepad slot.
6
+ * One of four stable gamepad slots. Lives for the entire `Application`
7
+ * lifetime even when no physical pad is attached — a "mailbox" that
8
+ * physical hardware moves into and out of.
6
9
  *
7
- * Owns the slot's {@link GamepadMapping}, reads raw button and axis values from
8
- * the browser's Gamepad API each frame via {@link update}, and writes transformed
9
- * values into the shared `Float32Array` channel buffer. Emits {@link onConnect},
10
- * {@link onDisconnect}, and per-channel {@link onUpdate} signals so consumers can
11
- * react without polling.
10
+ * Subscribe to {@link onConnect} / {@link onDisconnect} for hardware
11
+ * lifecycle, {@link onButtonDown} / {@link onButtonUp} / {@link onAxisChange}
12
+ * for granular per-event notifications, or call {@link onTrigger} /
13
+ * {@link onActive} / {@link onStart} / {@link onStop} to register
14
+ * stateful {@link InputBinding}s pinned to this slot.
15
+ *
16
+ * Listeners survive disconnect/reconnect cycles — a binding registered when
17
+ * the slot was empty will automatically activate when a pad connects.
12
18
  */
13
19
  class Gamepad {
20
+ /** Fires when a physical pad connects to this slot. */
14
21
  onConnect = new Signal();
22
+ /** Fires when the physical pad in this slot disconnects. */
15
23
  onDisconnect = new Signal();
16
- onUpdate = new Signal();
17
- indexValue;
18
- channelsValue;
19
- channelOffset;
20
- mappingValue;
21
- browserGamepad = null;
22
- info = {
23
- name: 'Generic Gamepad',
24
- label: 'Generic Gamepad',
25
- vendorId: null,
26
- productId: null,
27
- productKey: null,
28
- };
29
- constructor(indexOrGamepad, channels, mappingOrDefinition) {
30
- const isBrowserGamepad = typeof indexOrGamepad !== 'number';
31
- const gamepad = isBrowserGamepad ? indexOrGamepad : null;
32
- const index = isBrowserGamepad ? indexOrGamepad.index : indexOrGamepad;
33
- this.indexValue = index;
34
- this.channelsValue = channels;
35
- this.channelOffset = ChannelOffset.Gamepads + (index * ChannelSize.Gamepad);
36
- this.mappingValue = gamepad
37
- ? mappingOrDefinition.mapping
38
- : mappingOrDefinition;
39
- if (gamepad) {
40
- const definition = mappingOrDefinition;
41
- this.setInfo({
42
- name: definition.name,
43
- label: definition.descriptor.label,
44
- vendorId: definition.descriptor.vendorId,
45
- productId: definition.descriptor.productId,
46
- productKey: definition.descriptor.productKey,
47
- });
48
- this.connect(gamepad);
49
- }
24
+ /** Fires for every button transition from inactive to active. */
25
+ onButtonDown = new Signal();
26
+ /** Fires for every button transition from active to inactive. */
27
+ onButtonUp = new Signal();
28
+ /** Fires whenever an axis crosses its activation threshold. */
29
+ onAxisChange = new Signal();
30
+ /**
31
+ * Fires when this slot's physical pad has been replaced by a previously
32
+ * higher-numbered slot's pad, after a `'compact'`-strategy disconnect.
33
+ * Dispatched with the source slot index the pad came from. Listeners
34
+ * remain attached and the channel buffer is preserved across the move.
35
+ */
36
+ onPadReassigned = new Signal();
37
+ _slot;
38
+ _channels;
39
+ _bindings = new Set();
40
+ _detacher = { detach: (binding) => { this._bindings.delete(binding); } };
41
+ _channelOffset;
42
+ _mapping = null;
43
+ _info = null;
44
+ _browserGamepad = null;
45
+ constructor(slot, channels) {
46
+ this._slot = slot;
47
+ this._channels = channels;
48
+ this._channelOffset = ChannelOffset.Gamepads + (slot * ChannelSize.Gamepad);
50
49
  }
51
- get mapping() {
52
- return this.mappingValue;
50
+ /** This pad's stable slot (0..3). */
51
+ get slot() {
52
+ return this._slot;
53
53
  }
54
- set mapping(mapping) {
55
- this.mappingValue = mapping;
54
+ /** `true` while a physical pad is attached to this slot. */
55
+ get connected() {
56
+ return this._browserGamepad !== null;
56
57
  }
57
- /** The {@link GamepadMappingFamily} of the currently active mapping. */
58
+ /** The active mapping, or `null` when disconnected. */
59
+ get mapping() {
60
+ return this._mapping;
61
+ }
62
+ /** The {@link GamepadMappingFamily}, or `null` when disconnected. */
58
63
  get mappingFamily() {
59
- return this.mappingValue.family;
64
+ return this._mapping?.family ?? null;
60
65
  }
61
- get channels() {
62
- return this.channelsValue;
66
+ /** Identity metadata, or `null` when disconnected. */
67
+ get info() {
68
+ return this._info;
63
69
  }
64
- get gamepad() {
65
- return this.browserGamepad;
70
+ /** The underlying browser gamepad object, or `null` when disconnected. */
71
+ get browserGamepad() {
72
+ return this._browserGamepad;
66
73
  }
67
- get index() {
68
- return this.indexValue;
74
+ /**
75
+ * Browser-assigned hardware index from `navigator.getGamepads()` (i.e.
76
+ * `Gamepad.index`), or `null` when no pad is attached. Stable for the
77
+ * lifetime of a single physical connection but may change across
78
+ * disconnect/reconnect. Low-level escape hatch for advanced consumers
79
+ * that need to correlate slots with the raw browser API; prefer
80
+ * {@link slot} for stable per-application pad identity.
81
+ */
82
+ get internalIndex() {
83
+ return this._browserGamepad?.index ?? null;
69
84
  }
70
- /** Whether a browser gamepad is currently attached to this slot. */
71
- get connected() {
72
- return this.browserGamepad !== null;
85
+ /** `true` when the connected pad supports rumble via the Web Gamepad API. */
86
+ get canVibrate() {
87
+ return this._browserGamepad?.vibrationActuator != null;
73
88
  }
74
- get name() {
75
- return this.info.name;
89
+ /**
90
+ * Returns `true` when this pad's mapping declares the requested channel.
91
+ * Use to gate listener registration on optional hardware (e.g. Joy-Con
92
+ * solo lacks a right stick — `pad.hasChannel(GamepadAxis.RightStickX)`
93
+ * returns `false`).
94
+ */
95
+ hasChannel(channel) {
96
+ return this._mapping?.hasChannel(channel) ?? false;
76
97
  }
77
- get label() {
78
- return this.info.label;
98
+ /**
99
+ * Trigger a rumble effect on this pad. Resolves when the effect finishes.
100
+ * Silent no-op when the pad is disconnected or the platform does not
101
+ * support haptic feedback. Use {@link canVibrate} to detect support.
102
+ */
103
+ async vibrate(options) {
104
+ const actuator = this._browserGamepad?.vibrationActuator;
105
+ if (!actuator?.playEffect) {
106
+ return;
107
+ }
108
+ await actuator.playEffect('dual-rumble', {
109
+ duration: options.duration,
110
+ weakMagnitude: options.weakMagnitude ?? 1,
111
+ strongMagnitude: options.strongMagnitude ?? 1,
112
+ startDelay: options.startDelay ?? 0,
113
+ });
79
114
  }
80
- get vendorId() {
81
- return this.info.vendorId;
115
+ /** Stop any active rumble on this pad. Silent no-op when unsupported. */
116
+ stopVibration() {
117
+ this._browserGamepad?.vibrationActuator?.reset?.();
82
118
  }
83
- get productId() {
84
- return this.info.productId;
119
+ /**
120
+ * Register a callback fired once when any of `channels` becomes active.
121
+ * Listener survives disconnect/reconnect; call `.unbind()` on the
122
+ * returned {@link InputBinding} to detach.
123
+ */
124
+ onStart(channel, callback, options) {
125
+ const binding = this._createBinding(channel, options);
126
+ binding.onStart.add(callback);
127
+ return binding;
85
128
  }
86
- get productKey() {
87
- return this.info.productKey;
129
+ /**
130
+ * Register a callback fired every frame while any of `channels` is active.
131
+ * Receives the channel value (0..1 for buttons, -1..1 for bipolar axes).
132
+ */
133
+ onActive(channel, callback, options) {
134
+ const binding = this._createBinding(channel, options);
135
+ binding.onActive.add(callback);
136
+ return binding;
137
+ }
138
+ /** Register a callback fired once when all of `channels` become inactive. */
139
+ onStop(channel, callback, options) {
140
+ const binding = this._createBinding(channel, options);
141
+ binding.onStop.add(callback);
142
+ return binding;
88
143
  }
89
144
  /**
90
- * Replaces the gamepad's identity metadata.
91
- * Called automatically during construction when a {@link BrowserGamepad} is
92
- * provided; exposed publicly to allow runtime overrides.
145
+ * Register a callback fired when the input is released within
146
+ * {@link InputBindingOptions.threshold} ms of activation (a "tap").
93
147
  */
94
- setInfo(info) {
95
- this.info = info;
96
- return this;
148
+ onTrigger(channel, callback, options) {
149
+ const binding = this._createBinding(channel, options);
150
+ binding.onTrigger.add(callback);
151
+ return binding;
97
152
  }
98
153
  /**
99
- * Attaches a live browser gamepad to this slot and dispatches {@link onConnect}
100
- * if the slot was previously disconnected.
154
+ * Attach a physical browser gamepad to this slot. Called by
155
+ * {@link InputManager} on connect.
156
+ *
157
+ * @internal
101
158
  */
102
- connect(gamepad) {
103
- const wasConnected = this.connected;
104
- this.browserGamepad = gamepad;
105
- if (!wasConnected) {
106
- this.onConnect.dispatch(this);
159
+ _bind(gamepad, definition) {
160
+ this._browserGamepad = gamepad;
161
+ this._mapping = definition.mapping;
162
+ this._info = {
163
+ name: definition.name,
164
+ label: definition.descriptor.label,
165
+ vendorId: definition.descriptor.vendorId,
166
+ productId: definition.descriptor.productId,
167
+ productKey: definition.descriptor.productKey,
168
+ };
169
+ this.onConnect.dispatch();
170
+ }
171
+ /**
172
+ * Detach the physical gamepad and clear its channels.
173
+ *
174
+ * @internal
175
+ */
176
+ _unbind() {
177
+ if (this._browserGamepad === null) {
178
+ return;
107
179
  }
108
- return this;
180
+ this._clearMappedChannels();
181
+ this._browserGamepad = null;
182
+ this._mapping = null;
183
+ this._info = null;
184
+ this.onDisconnect.dispatch();
109
185
  }
110
186
  /**
111
- * Detaches the browser gamepad, zeros all mapped channels, and dispatches
112
- * {@link onDisconnect}. No-op when already disconnected.
187
+ * Detach the physical gamepad and clear channels without firing
188
+ * {@link onDisconnect}. Used by {@link InputManager} during the compact
189
+ * slot-shift to silently vacate a slot before another pad shifts into
190
+ * its place; the disconnect signal is fired separately on the slot that
191
+ * ends up empty after compaction.
192
+ *
193
+ * @internal
113
194
  */
114
- disconnect() {
115
- if (this.connected) {
116
- this.browserGamepad = null;
117
- this.clearMappedChannels();
118
- this.onDisconnect.dispatch(this);
195
+ _silentUnbind() {
196
+ if (this._browserGamepad === null) {
197
+ return;
119
198
  }
120
- return this;
199
+ this._clearMappedChannels();
200
+ this._browserGamepad = null;
201
+ this._mapping = null;
202
+ this._info = null;
203
+ }
204
+ /**
205
+ * Dispatch this slot's {@link onDisconnect} signal without altering its
206
+ * state. Used by {@link InputManager} after a compact-mode shift, when a
207
+ * slot has already been emptied by {@link _rebindFrom} and now needs to
208
+ * notify subscribers that its mailbox is no longer occupied.
209
+ *
210
+ * @internal
211
+ */
212
+ _dispatchDisconnect() {
213
+ this.onDisconnect.dispatch();
121
214
  }
122
215
  /**
123
- * Samples the browser gamepad's current state and writes transformed values
124
- * into the shared channel buffer, dispatching {@link onUpdate} for each channel
125
- * whose value changed. Should be called once per frame by the engine's input loop.
126
- * No-op when disconnected.
216
+ * Reassign this slot to take over another slot's physical gamepad without
217
+ * firing the full disconnect / connect cycle. Used by {@link InputManager}
218
+ * when the `'compact'` slot strategy shuffles pads after a disconnect.
219
+ *
220
+ * @internal
221
+ */
222
+ _rebindFrom(other) {
223
+ const gamepad = other._browserGamepad;
224
+ const mapping = other._mapping;
225
+ const info = other._info;
226
+ this._clearMappedChannels();
227
+ other._clearMappedChannels();
228
+ other._browserGamepad = null;
229
+ other._mapping = null;
230
+ other._info = null;
231
+ this._browserGamepad = gamepad;
232
+ this._mapping = mapping;
233
+ this._info = info;
234
+ }
235
+ /**
236
+ * Sample the browser gamepad's current state and write transformed values
237
+ * into the shared channel buffer, dispatching transition events when
238
+ * channel activity crosses thresholds. Called once per frame by the
239
+ * engine's input loop. No-op when disconnected.
240
+ *
241
+ * @internal
127
242
  */
128
243
  update() {
129
- if (this.browserGamepad === null) {
130
- return this;
244
+ if (this._browserGamepad === null || this._mapping === null) {
245
+ this._updateBindings();
246
+ return;
131
247
  }
132
- const channels = this.channelsValue;
133
- const { buttons: gamepadButtons, axes: gamepadAxes } = this.browserGamepad;
134
- for (const control of this.mappingValue.buttons) {
135
- const offsetChannel = this.resolveChannelOffset(control.channel);
136
- if (control.index < gamepadButtons.length) {
137
- const value = control.transformValue(gamepadButtons[control.index].value) || 0;
138
- if (channels[offsetChannel] !== value) {
139
- channels[offsetChannel] = value;
140
- this.onUpdate.dispatch(control.channel, value, this);
141
- }
248
+ const channels = this._channels;
249
+ const { buttons: rawButtons, axes: rawAxes } = this._browserGamepad;
250
+ for (const button of this._mapping.buttons) {
251
+ if (button.index >= rawButtons.length) {
252
+ continue;
253
+ }
254
+ const offset = this._resolveOffset(button.channel);
255
+ const previous = channels[offset];
256
+ const value = button.transformValue(rawButtons[button.index].value) || 0;
257
+ if (previous === value) {
258
+ continue;
259
+ }
260
+ channels[offset] = value;
261
+ if (previous === 0 && value !== 0) {
262
+ this.onButtonDown.dispatch(button, value);
263
+ }
264
+ else if (previous !== 0 && value === 0) {
265
+ this.onButtonUp.dispatch(button, value);
142
266
  }
143
267
  }
144
- for (const control of this.mappingValue.axes) {
145
- const offsetChannel = this.resolveChannelOffset(control.channel);
146
- if (control.index < gamepadAxes.length) {
147
- const value = control.transformValue(gamepadAxes[control.index]) || 0;
148
- if (channels[offsetChannel] !== value) {
149
- channels[offsetChannel] = value;
150
- this.onUpdate.dispatch(control.channel, value, this);
151
- }
268
+ for (const axis of this._mapping.axes) {
269
+ if (axis.index >= rawAxes.length) {
270
+ continue;
152
271
  }
272
+ const offset = this._resolveOffset(axis.channel);
273
+ const previous = channels[offset];
274
+ const value = axis.transformValue(rawAxes[axis.index]) || 0;
275
+ if (previous === value) {
276
+ continue;
277
+ }
278
+ channels[offset] = value;
279
+ this.onAxisChange.dispatch(axis, value);
153
280
  }
154
- return this;
155
- }
156
- /** Zeroes all channel buffer entries that belong to this gamepad's mapping. */
157
- clearChannels() {
158
- this.clearMappedChannels();
159
- return this;
281
+ this._updateBindings();
160
282
  }
161
283
  /**
162
- * Disconnects the gamepad, clears its channels, and destroys all signals.
163
- * The instance must not be used after this call.
284
+ * Tear down this gamepad slot. Called on application shutdown.
164
285
  */
165
286
  destroy() {
166
- this.disconnect();
167
- this.clearMappedChannels();
287
+ for (const binding of Array.from(this._bindings)) {
288
+ binding.unbind();
289
+ }
290
+ this._bindings.clear();
291
+ this._unbind();
168
292
  this.onConnect.destroy();
169
293
  this.onDisconnect.destroy();
170
- this.onUpdate.destroy();
294
+ this.onButtonDown.destroy();
295
+ this.onButtonUp.destroy();
296
+ this.onAxisChange.destroy();
297
+ this.onPadReassigned.destroy();
171
298
  }
172
299
  /**
173
- * Converts a {@link GamepadChannel} to its absolute index in the shared channel
174
- * buffer for this gamepad instance.
300
+ * Convert a slot-relative channel value to its absolute index in the
301
+ * shared channel buffer for this slot.
175
302
  */
176
303
  resolveChannelOffset(channel) {
177
- return this.channelOffset + (channel ^ ChannelOffset.Gamepads);
304
+ return this._resolveOffset(channel);
178
305
  }
179
306
  /**
180
- * Converts a gamepad slot index and {@link GamepadChannel} to an absolute
181
- * channel buffer offset without requiring a {@link Gamepad} instance.
307
+ * Static counterpart to {@link Gamepad.resolveChannelOffset} resolves
308
+ * an absolute channel-buffer offset for a given slot index without
309
+ * requiring a Gamepad instance.
182
310
  */
183
- static resolveChannelOffset(gamepadIndex, channel) {
184
- return ChannelOffset.Gamepads + (gamepadIndex * ChannelSize.Gamepad) + (channel ^ ChannelOffset.Gamepads);
311
+ static resolveChannelOffset(slot, channel) {
312
+ return ChannelOffset.Gamepads + (slot * ChannelSize.Gamepad) + (channel ^ ChannelOffset.Gamepads);
313
+ }
314
+ _resolveOffset(channel) {
315
+ return this._channelOffset + (channel ^ ChannelOffset.Gamepads);
316
+ }
317
+ _clearMappedChannels() {
318
+ if (this._mapping === null) {
319
+ return;
320
+ }
321
+ for (const button of this._mapping.buttons) {
322
+ this._channels[this._resolveOffset(button.channel)] = 0;
323
+ }
324
+ for (const axis of this._mapping.axes) {
325
+ this._channels[this._resolveOffset(axis.channel)] = 0;
326
+ }
185
327
  }
186
- clearMappedChannels() {
187
- for (const control of this.mappingValue.buttons) {
188
- this.channelsValue[this.resolveChannelOffset(control.channel)] = 0;
328
+ _createBinding(channel, options = {}) {
329
+ const list = Array.isArray(channel) ? channel : [channel];
330
+ const resolved = list.map((c) => this._resolveExternalChannel(c));
331
+ const binding = new InputBinding(resolved, options, this._detacher);
332
+ this._bindings.add(binding);
333
+ return binding;
334
+ }
335
+ _resolveExternalChannel(channel) {
336
+ // Keyboard channels are global (no slot offset). Gamepad channels
337
+ // need slot-aware translation. Any channel value within the
338
+ // gamepad-section maps through this pad's slot offset; others
339
+ // (Keyboard, Pointer) pass through as-is.
340
+ if (channel >= ChannelOffset.Gamepads && channel < ChannelOffset.Gamepads + ChannelSize.Category) {
341
+ return this._resolveOffset(channel);
189
342
  }
190
- for (const control of this.mappingValue.axes) {
191
- this.channelsValue[this.resolveChannelOffset(control.channel)] = 0;
343
+ return channel;
344
+ }
345
+ _updateBindings() {
346
+ for (const binding of this._bindings) {
347
+ binding.update(this._channels);
192
348
  }
193
349
  }
194
350
  }
@@ -1 +1 @@
1
- {"version":3,"file":"Gamepad.js","sources":["../../../../src/input/Gamepad.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Gamepad.js","sources":["../../../../src/input/Gamepad.ts"],"sourcesContent":[null],"names":[],"mappings":";;;;AAiCA;;;;;;;;;;;;;AAaG;MACU,OAAO,CAAA;;AAEA,IAAA,SAAS,GAAG,IAAI,MAAM,EAAM;;AAE5B,IAAA,YAAY,GAAG,IAAI,MAAM,EAAM;;AAE/B,IAAA,YAAY,GAAG,IAAI,MAAM,EAA2B;;AAEpD,IAAA,UAAU,GAAG,IAAI,MAAM,EAA2B;;AAElD,IAAA,YAAY,GAAG,IAAI,MAAM,EAAyB;AAClE;;;;;AAKG;AACa,IAAA,eAAe,GAAG,IAAI,MAAM,EAA6B;AAExD,IAAA,KAAK;AACL,IAAA,SAAS;AACT,IAAA,SAAS,GAAsB,IAAI,GAAG,EAAgB;IACtD,SAAS,GAAG,EAAE,MAAM,EAAE,CAAC,OAAqB,KAAU,EAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE;AAE5F,IAAA,cAAc;IACvB,QAAQ,GAA0B,IAAI;IACtC,KAAK,GAAuB,IAAI;IAChC,eAAe,GAA0B,IAAI;IAErD,WAAA,CAAmB,IAAmB,EAAE,QAAsB,EAAA;AAC1D,QAAA,IAAI,CAAC,KAAK,GAAG,IAAI;AACjB,QAAA,IAAI,CAAC,SAAS,GAAG,QAAQ;AACzB,QAAA,IAAI,CAAC,cAAc,GAAG,aAAa,CAAC,QAAQ,IAAI,IAAI,GAAG,WAAW,CAAC,OAAO,CAAC;IAC/E;;AAGA,IAAA,IAAW,IAAI,GAAA;QACX,OAAO,IAAI,CAAC,KAAK;IACrB;;AAGA,IAAA,IAAW,SAAS,GAAA;AAChB,QAAA,OAAO,IAAI,CAAC,eAAe,KAAK,IAAI;IACxC;;AAGA,IAAA,IAAW,OAAO,GAAA;QACd,OAAO,IAAI,CAAC,QAAQ;IACxB;;AAGA,IAAA,IAAW,aAAa,GAAA;AACpB,QAAA,OAAO,IAAI,CAAC,QAAQ,EAAE,MAAM,IAAI,IAAI;IACxC;;AAGA,IAAA,IAAW,IAAI,GAAA;QACX,OAAO,IAAI,CAAC,KAAK;IACrB;;AAGA,IAAA,IAAW,cAAc,GAAA;QACrB,OAAO,IAAI,CAAC,eAAe;IAC/B;AAEA;;;;;;;AAOG;AACH,IAAA,IAAW,aAAa,GAAA;AACpB,QAAA,OAAO,IAAI,CAAC,eAAe,EAAE,KAAK,IAAI,IAAI;IAC9C;;AAGA,IAAA,IAAW,UAAU,GAAA;AACjB,QAAA,OAAO,IAAI,CAAC,eAAe,EAAE,iBAAiB,IAAI,IAAI;IAC1D;AAEA;;;;;AAKG;AACI,IAAA,UAAU,CAAC,OAAkD,EAAA;QAChE,OAAO,IAAI,CAAC,QAAQ,EAAE,UAAU,CAAC,OAAO,CAAC,IAAI,KAAK;IACtD;AAEA;;;;AAIG;IACI,MAAM,OAAO,CAAC,OAAgC,EAAA;AACjD,QAAA,MAAM,QAAQ,GAAG,IAAI,CAAC,eAAe,EAAE,iBAAiB;AAExD,QAAA,IAAI,CAAC,QAAQ,EAAE,UAAU,EAAE;YACvB;QACJ;AAEA,QAAA,MAAM,QAAQ,CAAC,UAAU,CAAC,aAAa,EAAE;YACrC,QAAQ,EAAE,OAAO,CAAC,QAAQ;AAC1B,YAAA,aAAa,EAAE,OAAO,CAAC,aAAa,IAAI,CAAC;AACzC,YAAA,eAAe,EAAE,OAAO,CAAC,eAAe,IAAI,CAAC;AAC7C,YAAA,UAAU,EAAE,OAAO,CAAC,UAAU,IAAI,CAAC;AACtC,SAAA,CAAC;IACN;;IAGO,aAAa,GAAA;QAChB,IAAI,CAAC,eAAe,EAAE,iBAAiB,EAAE,KAAK,IAAI;IACtD;AAEA;;;;AAIG;AACI,IAAA,OAAO,CAAC,OAAmD,EAAE,QAAiC,EAAE,OAA6B,EAAA;QAChI,MAAM,OAAO,GAAG,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE,OAAO,CAAC;AACrD,QAAA,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC;AAC7B,QAAA,OAAO,OAAO;IAClB;AAEA;;;AAGG;AACI,IAAA,QAAQ,CAAC,OAAmD,EAAE,QAAiC,EAAE,OAA6B,EAAA;QACjI,MAAM,OAAO,GAAG,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE,OAAO,CAAC;AACrD,QAAA,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC;AAC9B,QAAA,OAAO,OAAO;IAClB;;AAGO,IAAA,MAAM,CAAC,OAAmD,EAAE,QAAiC,EAAE,OAA6B,EAAA;QAC/H,MAAM,OAAO,GAAG,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE,OAAO,CAAC;AACrD,QAAA,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;AAC5B,QAAA,OAAO,OAAO;IAClB;AAEA;;;AAGG;AACI,IAAA,SAAS,CAAC,OAAmD,EAAE,QAAiC,EAAE,OAA6B,EAAA;QAClI,MAAM,OAAO,GAAG,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE,OAAO,CAAC;AACrD,QAAA,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC;AAC/B,QAAA,OAAO,OAAO;IAClB;AAEA;;;;;AAKG;IACI,KAAK,CAAC,OAAuB,EAAE,UAAqC,EAAA;AACvE,QAAA,IAAI,CAAC,eAAe,GAAG,OAAO;AAC9B,QAAA,IAAI,CAAC,QAAQ,GAAG,UAAU,CAAC,OAAO;QAClC,IAAI,CAAC,KAAK,GAAG;YACT,IAAI,EAAE,UAAU,CAAC,IAAI;AACrB,YAAA,KAAK,EAAE,UAAU,CAAC,UAAU,CAAC,KAAK;AAClC,YAAA,QAAQ,EAAE,UAAU,CAAC,UAAU,CAAC,QAAQ;AACxC,YAAA,SAAS,EAAE,UAAU,CAAC,UAAU,CAAC,SAAS;AAC1C,YAAA,UAAU,EAAE,UAAU,CAAC,UAAU,CAAC,UAAU;SAC/C;AACD,QAAA,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE;IAC7B;AAEA;;;;AAIG;IACI,OAAO,GAAA;AACV,QAAA,IAAI,IAAI,CAAC,eAAe,KAAK,IAAI,EAAE;YAC/B;QACJ;QAEA,IAAI,CAAC,oBAAoB,EAAE;AAC3B,QAAA,IAAI,CAAC,eAAe,GAAG,IAAI;AAC3B,QAAA,IAAI,CAAC,QAAQ,GAAG,IAAI;AACpB,QAAA,IAAI,CAAC,KAAK,GAAG,IAAI;AACjB,QAAA,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE;IAChC;AAEA;;;;;;;;AAQG;IACI,aAAa,GAAA;AAChB,QAAA,IAAI,IAAI,CAAC,eAAe,KAAK,IAAI,EAAE;YAC/B;QACJ;QAEA,IAAI,CAAC,oBAAoB,EAAE;AAC3B,QAAA,IAAI,CAAC,eAAe,GAAG,IAAI;AAC3B,QAAA,IAAI,CAAC,QAAQ,GAAG,IAAI;AACpB,QAAA,IAAI,CAAC,KAAK,GAAG,IAAI;IACrB;AAEA;;;;;;;AAOG;IACI,mBAAmB,GAAA;AACtB,QAAA,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE;IAChC;AAEA;;;;;;AAMG;AACI,IAAA,WAAW,CAAC,KAAc,EAAA;AAC7B,QAAA,MAAM,OAAO,GAAG,KAAK,CAAC,eAAe;AACrC,QAAA,MAAM,OAAO,GAAG,KAAK,CAAC,QAAQ;AAC9B,QAAA,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK;QAExB,IAAI,CAAC,oBAAoB,EAAE;QAC3B,KAAK,CAAC,oBAAoB,EAAE;AAC5B,QAAA,KAAK,CAAC,eAAe,GAAG,IAAI;AAC5B,QAAA,KAAK,CAAC,QAAQ,GAAG,IAAI;AACrB,QAAA,KAAK,CAAC,KAAK,GAAG,IAAI;AAElB,QAAA,IAAI,CAAC,eAAe,GAAG,OAAO;AAC9B,QAAA,IAAI,CAAC,QAAQ,GAAG,OAAO;AACvB,QAAA,IAAI,CAAC,KAAK,GAAG,IAAI;IACrB;AAEA;;;;;;;AAOG;IACI,MAAM,GAAA;AACT,QAAA,IAAI,IAAI,CAAC,eAAe,KAAK,IAAI,IAAI,IAAI,CAAC,QAAQ,KAAK,IAAI,EAAE;YACzD,IAAI,CAAC,eAAe,EAAE;YACtB;QACJ;AAEA,QAAA,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS;AAC/B,QAAA,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC,eAAe;QAEnE,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE;YACxC,IAAI,MAAM,CAAC,KAAK,IAAI,UAAU,CAAC,MAAM,EAAE;gBACnC;YACJ;YAEA,MAAM,MAAM,GAAG,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,OAAO,CAAC;AAClD,YAAA,MAAM,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC;AACjC,YAAA,MAAM,KAAK,GAAG,MAAM,CAAC,cAAc,CAAC,UAAU,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC;AAExE,YAAA,IAAI,QAAQ,KAAK,KAAK,EAAE;gBACpB;YACJ;AAEA,YAAA,QAAQ,CAAC,MAAM,CAAC,GAAG,KAAK;YAExB,IAAI,QAAQ,KAAK,CAAC,IAAI,KAAK,KAAK,CAAC,EAAE;gBAC/B,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC;YAC7C;iBAAO,IAAI,QAAQ,KAAK,CAAC,IAAI,KAAK,KAAK,CAAC,EAAE;gBACtC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC;YAC3C;QACJ;QAEA,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE;YACnC,IAAI,IAAI,CAAC,KAAK,IAAI,OAAO,CAAC,MAAM,EAAE;gBAC9B;YACJ;YAEA,MAAM,MAAM,GAAG,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC;AAChD,YAAA,MAAM,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC;AACjC,YAAA,MAAM,KAAK,GAAG,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC;AAE3D,YAAA,IAAI,QAAQ,KAAK,KAAK,EAAE;gBACpB;YACJ;AAEA,YAAA,QAAQ,CAAC,MAAM,CAAC,GAAG,KAAK;YACxB,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC;QAC3C;QAEA,IAAI,CAAC,eAAe,EAAE;IAC1B;AAEA;;AAEG;IACI,OAAO,GAAA;AACV,QAAA,KAAK,MAAM,OAAO,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE;YAC9C,OAAO,CAAC,MAAM,EAAE;QACpB;AAEA,QAAA,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE;QACtB,IAAI,CAAC,OAAO,EAAE;AACd,QAAA,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE;AACxB,QAAA,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE;AAC3B,QAAA,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE;AAC3B,QAAA,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE;AACzB,QAAA,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE;AAC3B,QAAA,IAAI,CAAC,eAAe,CAAC,OAAO,EAAE;IAClC;AAEA;;;AAGG;AACI,IAAA,oBAAoB,CAAC,OAAkD,EAAA;AAC1E,QAAA,OAAO,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC;IACvC;AAEA;;;;AAIG;AACI,IAAA,OAAO,oBAAoB,CAAC,IAAY,EAAE,OAAkD,EAAA;AAC/F,QAAA,OAAO,aAAa,CAAC,QAAQ,IAAI,IAAI,GAAG,WAAW,CAAC,OAAO,CAAC,IAAI,OAAO,GAAG,aAAa,CAAC,QAAQ,CAAC;IACrG;AAEQ,IAAA,cAAc,CAAC,OAAkD,EAAA;QACrE,OAAO,IAAI,CAAC,cAAc,IAAI,OAAO,GAAG,aAAa,CAAC,QAAQ,CAAC;IACnE;IAEQ,oBAAoB,GAAA;AACxB,QAAA,IAAI,IAAI,CAAC,QAAQ,KAAK,IAAI,EAAE;YACxB;QACJ;QAEA,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE;AACxC,YAAA,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC;QAC3D;QAEA,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE;AACnC,YAAA,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC;QACzD;IACJ;AAEQ,IAAA,cAAc,CAClB,OAAmD,EACnD,OAAA,GAA+B,EAAE,EAAA;AAEjC,QAAA,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,GAAG,CAAC,OAAuB,CAAC;AACzE,QAAA,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,uBAAuB,CAAC,CAAC,CAAC,CAAC;AACjE,QAAA,MAAM,OAAO,GAAG,IAAI,YAAY,CAAC,QAAQ,EAAE,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC;AACnE,QAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC;AAC3B,QAAA,OAAO,OAAO;IAClB;AAEQ,IAAA,uBAAuB,CAAC,OAAqB,EAAA;;;;;AAKjD,QAAA,IAAI,OAAO,IAAI,aAAa,CAAC,QAAQ,IAAI,OAAO,GAAG,aAAa,CAAC,QAAQ,GAAG,WAAW,CAAC,QAAQ,EAAE;AAC9F,YAAA,OAAO,IAAI,CAAC,cAAc,CAAC,OAAoD,CAAC;QACpF;AAEA,QAAA,OAAO,OAAO;IAClB;IAEQ,eAAe,GAAA;AACnB,QAAA,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,SAAS,EAAE;AAClC,YAAA,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC;QAClC;IACJ;AACH;;;;"}
@@ -0,0 +1,120 @@
1
+ declare const gamepadAxisChannelBrand: unique symbol;
2
+ /**
3
+ * Branded literal-union type identifying a canonical analog axis-style
4
+ * gamepad input channel. Members are absolute offsets into the engine's
5
+ * shared {@link Float32Array} input channel buffer (relative to slot 0):
6
+ * the 32 slots reserved for a gamepad slot's axis section, computed as
7
+ * `ChannelOffset.Gamepads + 32..63` (544..575 with the default layout).
8
+ *
9
+ * The 24 named axes (sticks split + signed aggregates + dual touchpad XY +
10
+ * 4 auxiliary bipolar) cover offsets 32..55; offsets 56..63 are reserved
11
+ * for forward-compat / custom-mapping use and remain part of this type so
12
+ * custom `GamepadMapping` subclasses can address them without casting.
13
+ *
14
+ * The brand keeps the type system from confusing axis channels with
15
+ * {@link GamepadButtonChannel} or raw `number`s during mapping authoring.
16
+ * User code does not construct values of this type directly — read them
17
+ * from the {@link GamepadAxis} namespace (`GamepadAxis.LeftStickLeft`, ...).
18
+ *
19
+ * @internal
20
+ */
21
+ export type GamepadAxisChannel = (544 | 545 | 546 | 547 | 548 | 549 | 550 | 551 | 552 | 553 | 554 | 555 | 556 | 557 | 558 | 559 | 560 | 561 | 562 | 563 | 564 | 565 | 566 | 567 | 568 | 569 | 570 | 571 | 572 | 573 | 574 | 575) & {
22
+ readonly [gamepadAxisChannelBrand]: void;
23
+ };
24
+ /** Construction options for a {@link GamepadAxis}. */
25
+ export interface GamepadAxisOptions {
26
+ /** Negate the raw value before further processing. Default `false`. */
27
+ invert?: boolean;
28
+ /**
29
+ * Convert from bipolar [-1, +1] to unipolar [0, 1] via `(v + 1) / 2`.
30
+ * Used for direction-split channels where each direction reads 0..1.
31
+ * Default `false`.
32
+ */
33
+ normalize?: boolean;
34
+ /**
35
+ * Activation threshold (deadzone). After the invert/normalize pipeline,
36
+ * any value at or below this reads as 0. Default 0.2.
37
+ */
38
+ threshold?: number;
39
+ /**
40
+ * Skip the deadzone clamp. Used for aggregate signed channels
41
+ * (`LeftStickX`, `LeftStickY`, ...) that need to preserve the full
42
+ * [-1, +1] range and apply their own deadzone client-side.
43
+ * Default `false`.
44
+ */
45
+ bipolar?: boolean;
46
+ }
47
+ /**
48
+ * Single mappable analog axis on a physical gamepad. Holds the raw browser
49
+ * `Gamepad.axes[]` index, the canonical channel the value is written to, and
50
+ * the transform pipeline applied each frame by {@link transformValue}.
51
+ *
52
+ * Direction-split axis channels (e.g. `LeftStickLeft`, `LeftStickRight`)
53
+ * live in the 0..1 range — set `invert: true` on the negative half so it
54
+ * reads positive when pushed in its direction.
55
+ *
56
+ * Aggregate channels (e.g. `LeftStickX`, `LeftStickY`) live in the full
57
+ * -1..1 range — set `bipolar: true` to preserve sign through the pipeline.
58
+ *
59
+ * The static namespace exports (`GamepadAxis.LeftStickLeft`,
60
+ * `.LeftStickX`, ...) carry the canonical channel offsets used to address
61
+ * each axis.
62
+ */
63
+ export declare class GamepadAxis {
64
+ readonly index: number;
65
+ readonly channel: GamepadAxisChannel;
66
+ readonly invert: boolean;
67
+ readonly normalize: boolean;
68
+ readonly threshold: number;
69
+ readonly bipolar: boolean;
70
+ constructor(index: number, channel: GamepadAxisChannel, options?: GamepadAxisOptions);
71
+ /**
72
+ * Apply the axis transform pipeline to a raw browser axis value
73
+ * (typically `Gamepad.axes[i]`, in -1..1).
74
+ *
75
+ * Pipeline: clamp to [-1, 1] → optional invert → optional normalize to
76
+ * [0, 1] → bipolar passthrough OR deadzone (returns 0 when the absolute
77
+ * value is at or below `threshold`).
78
+ */
79
+ transformValue(value: number): number;
80
+ }
81
+ /**
82
+ * Channel-identifier constants. The axis section starts after the 32-slot
83
+ * button block: 24 named axes (offsets 32..55) plus 8 reserved slots
84
+ * (offsets 56..63).
85
+ */
86
+ export declare namespace GamepadAxis {
87
+ const LeftStickLeft: GamepadAxisChannel;
88
+ const LeftStickRight: GamepadAxisChannel;
89
+ const LeftStickUp: GamepadAxisChannel;
90
+ const LeftStickDown: GamepadAxisChannel;
91
+ const RightStickLeft: GamepadAxisChannel;
92
+ const RightStickRight: GamepadAxisChannel;
93
+ const RightStickUp: GamepadAxisChannel;
94
+ const RightStickDown: GamepadAxisChannel;
95
+ /** Signed left-stick X axis (-1..1). Negative = left, positive = right. */
96
+ const LeftStickX: GamepadAxisChannel;
97
+ /** Signed left-stick Y axis (-1..1). Negative = up (screen-up), positive = down. */
98
+ const LeftStickY: GamepadAxisChannel;
99
+ /** Signed right-stick X axis (-1..1). */
100
+ const RightStickX: GamepadAxisChannel;
101
+ /** Signed right-stick Y axis (-1..1). */
102
+ const RightStickY: GamepadAxisChannel;
103
+ /** Primary touchpad X (0..1, left to right). PlayStation, Steam Deck (left pad), Steam Controller. */
104
+ const TouchpadX: GamepadAxisChannel;
105
+ /** Primary touchpad Y (0..1, top to bottom). */
106
+ const TouchpadY: GamepadAxisChannel;
107
+ /** Secondary touchpad X (0..1). Steam Deck (right pad), other dual-touchpad hardware. */
108
+ const Touchpad2X: GamepadAxisChannel;
109
+ /** Secondary touchpad Y (0..1). */
110
+ const Touchpad2Y: GamepadAxisChannel;
111
+ const AuxiliaryAxis0Negative: GamepadAxisChannel;
112
+ const AuxiliaryAxis0Positive: GamepadAxisChannel;
113
+ const AuxiliaryAxis1Negative: GamepadAxisChannel;
114
+ const AuxiliaryAxis1Positive: GamepadAxisChannel;
115
+ const AuxiliaryAxis2Negative: GamepadAxisChannel;
116
+ const AuxiliaryAxis2Positive: GamepadAxisChannel;
117
+ const AuxiliaryAxis3Negative: GamepadAxisChannel;
118
+ const AuxiliaryAxis3Positive: GamepadAxisChannel;
119
+ }
120
+ export {};