three-gamepad-controls 0.17.0 → 0.19.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.
@@ -1,69 +1,21 @@
1
1
  import { isGamepadVibrationSupported, playGamepadVibrationEffect, resetGamepadVibration } from "./gamepad-haptics.js";
2
2
  import { GamepadManager } from "./gamepad-manager.js";
3
+ import { DEFAULT_GAMEPAD_STICK_PIPELINE } from "./gamepad-stick-processing.js";
3
4
  import { EventDispatcher } from "three";
4
5
  //#region src/gamepad-input.ts
5
6
  const DEFAULT_GAMEPAD_INPUT_OPTIONS = {
6
- deadzone: .1,
7
- deadzoneMode: "axial",
8
- rescale: false
7
+ axisDeadzone: .1,
8
+ stickPipeline: DEFAULT_GAMEPAD_STICK_PIPELINE
9
9
  };
10
10
  /**
11
- * Applies a dead zone and remaps the remaining magnitude to `[0, 1]`.
12
- *
13
- * @param magnitude - Non-negative input magnitude.
14
- * @param threshold - Dead zone size.
15
- * @returns Rescaled magnitude, or `0` when inside a fully closed dead zone.
16
- */
17
- const rescaleGamepadDeadzoneMagnitude = (magnitude, threshold) => {
18
- if (magnitude <= threshold || threshold >= 1) return 0;
19
- return Math.min((magnitude - threshold) / (1 - threshold), 1);
20
- };
21
- /**
22
- * Applies an axial dead zone, optionally rescaling the remaining range.
11
+ * Applies a scalar dead zone without rescaling.
23
12
  *
24
13
  * @param value - Raw axis value.
25
14
  * @param threshold - Dead zone size.
26
- * @param rescale - Whether to remap the remaining magnitude to `[0, 1]`.
27
- * @returns Processed signed axis value.
28
- */
29
- const applyGamepadAxialDeadzone = (value, threshold, rescale) => {
30
- const magnitude = Math.abs(value);
31
- if (magnitude < threshold) return 0;
32
- if (!rescale) return value;
33
- return Math.sign(value) * rescaleGamepadDeadzoneMagnitude(magnitude, threshold);
34
- };
35
- /**
36
- * Returns the stick unchanged, or centered if its magnitude is below the dead
37
- * zone `threshold`.
38
- *
39
- * @param x - Raw horizontal stick value.
40
- * @param y - Raw vertical stick value.
41
- * @param threshold - Radial dead zone size.
42
- * @param rescale - Whether to remap the remaining magnitude to `[0, 1]`.
43
- * @returns The processed stick, or `{ x: 0, y: 0 }` inside the dead zone.
15
+ * @returns The original value outside the dead zone, otherwise `0`.
44
16
  */
45
- const applyGamepadRadialDeadzone = (x, y, threshold, rescale) => {
46
- const magnitude = Math.hypot(x, y);
47
- if (magnitude < threshold) return {
48
- x: 0,
49
- y: 0
50
- };
51
- if (rescale) {
52
- const rescaledMagnitude = rescaleGamepadDeadzoneMagnitude(magnitude, threshold);
53
- if (rescaledMagnitude === 0 || magnitude === 0) return {
54
- x: 0,
55
- y: 0
56
- };
57
- const scale = rescaledMagnitude / magnitude;
58
- return {
59
- x: x * scale,
60
- y: y * scale
61
- };
62
- }
63
- return {
64
- x,
65
- y
66
- };
17
+ const applyGamepadAxisDeadzone = (value, threshold) => {
18
+ return Math.abs(value) < threshold ? 0 : value;
67
19
  };
68
20
  /**
69
21
  * Returns whether a gamepad button is currently pressed.
@@ -274,27 +226,23 @@ var GamepadInput = class extends EventDispatcher {
274
226
  */
275
227
  axis(axis, options) {
276
228
  const value = this.#gamepad?.axes[axis] ?? 0;
277
- return applyGamepadAxialDeadzone(value, this.#getDeadzone(options), false);
229
+ return applyGamepadAxisDeadzone(value, this.#getAxisDeadzone(options));
278
230
  }
279
231
  /**
280
- * Returns a two-axis stick after dead zone processing.
232
+ * Returns a two-axis stick after applying a stateless processing pipeline.
281
233
  *
282
234
  * @param xAxis - Horizontal axis index.
283
235
  * @param yAxis - Vertical axis index.
284
- * @param options - Optional per-read stick options.
236
+ * @param pipeline - Optional pipeline replacing the instance default.
285
237
  * @returns Object containing processed `x` and `y` values.
286
238
  */
287
- stick(xAxis, yAxis, options) {
288
- const deadzoneMode = options?.deadzoneMode ?? this.#options.deadzoneMode;
289
- const rescale = options?.rescale ?? this.#options.rescale;
290
- const threshold = this.#getDeadzone(options);
239
+ stick(xAxis, yAxis, pipeline) {
291
240
  const x = this.#gamepad?.axes[xAxis] ?? 0;
292
241
  const y = this.#gamepad?.axes[yAxis] ?? 0;
293
- if (deadzoneMode === "radial") return applyGamepadRadialDeadzone(x, y, threshold, rescale);
294
- return {
295
- x: applyGamepadAxialDeadzone(x, threshold, rescale),
296
- y: applyGamepadAxialDeadzone(y, threshold, rescale)
297
- };
242
+ return (pipeline ?? this.#options.stickPipeline).process({
243
+ x,
244
+ y
245
+ });
298
246
  }
299
247
  /**
300
248
  * Plays an effect through the active gamepad's primary vibration actuator.
@@ -383,13 +331,13 @@ var GamepadInput = class extends EventDispatcher {
383
331
  this.#previousPressedButtons.clear();
384
332
  }
385
333
  /**
386
- * Resolves the dead zone for a single axis or stick read.
334
+ * Resolves the dead zone for a single-axis read.
387
335
  *
388
336
  * @param options - Optional per-read axis options.
389
337
  * @returns The per-read dead zone when provided, otherwise the instance default.
390
338
  */
391
- #getDeadzone(options) {
392
- return options?.deadzone ?? this.#options.deadzone;
339
+ #getAxisDeadzone(options) {
340
+ return options?.deadzone ?? this.#options.axisDeadzone;
393
341
  }
394
342
  };
395
343
  //#endregion
@@ -69,7 +69,7 @@ var GamepadManager = class {
69
69
  * Polls the Gamepad API and refreshes the active gamepad snapshot.
70
70
  *
71
71
  * Polling re-resolves the browser slot so a disconnected device, a reused
72
- * index, or an updated active device is observed before controls read input.
72
+ * index, or an updated active device is observed before consumers read input.
73
73
  *
74
74
  * @returns The active gamepad and any connect/disconnect transition found.
75
75
  */
@@ -2,10 +2,14 @@ import { GAMEPAD_AXIS } from "./core.js";
2
2
  import { GamepadOrbitControls } from "./gamepad-orbit-controls.js";
3
3
  //#region src/gamepad-map-controls.ts
4
4
  const DEFAULT_MAP_OPTIONS = {
5
- axisPanX: GAMEPAD_AXIS.LeftX,
6
- axisPanY: GAMEPAD_AXIS.LeftY,
7
- axisRotateX: GAMEPAD_AXIS.RightX,
8
- axisRotateY: GAMEPAD_AXIS.RightY
5
+ panStick: {
6
+ xAxis: GAMEPAD_AXIS.LeftX,
7
+ yAxis: GAMEPAD_AXIS.LeftY
8
+ },
9
+ rotateStick: {
10
+ xAxis: GAMEPAD_AXIS.RightX,
11
+ yAxis: GAMEPAD_AXIS.RightY
12
+ }
9
13
  };
10
14
  /**
11
15
  * Adds gamepad support to Three.js `MapControls`.
@@ -24,7 +28,15 @@ var GamepadMapControls = class extends GamepadOrbitControls {
24
28
  constructor(controls, options) {
25
29
  super(controls, {
26
30
  ...DEFAULT_MAP_OPTIONS,
27
- ...options
31
+ ...options,
32
+ panStick: {
33
+ ...DEFAULT_MAP_OPTIONS.panStick,
34
+ ...options?.panStick
35
+ },
36
+ rotateStick: {
37
+ ...DEFAULT_MAP_OPTIONS.rotateStick,
38
+ ...options?.rotateStick
39
+ }
28
40
  });
29
41
  }
30
42
  };
@@ -1,3 +1,4 @@
1
+ import { GamepadStickBindingOptions } from "./gamepad-stick-processing.js";
1
2
  import { GamepadControls, GamepadControlsOptions } from "./gamepad-controls.js";
2
3
  import { OrbitControls } from "three/addons/controls/OrbitControls.js";
3
4
  //#region src/gamepad-orbit-controls.d.ts
@@ -23,30 +24,20 @@ type GamepadOrbitControlsOptions = GamepadControlsOptions & {
23
24
  */
24
25
  zoomSpeed: number;
25
26
  /**
26
- * Axis dead zone threshold in the range `[0, 1]`.
27
- * @default 0.1
28
- */
29
- deadzone: number;
30
- /**
31
- * Axis index for **horizontal** orbit rotation.
32
- * @default 0 — Left stick X
27
+ * Stick binding used for orbit rotation.
28
+ * @default Left stick with the default stick pipeline
33
29
  */
34
- axisRotateX: number;
30
+ rotateStick: GamepadStickBindingOptions;
35
31
  /**
36
- * Axis index for **vertical** orbit rotation.
37
- * @default 1 — Left stick Y
32
+ * Stick binding used for panning.
33
+ * @default Right stick with the default stick pipeline
38
34
  */
39
- axisRotateY: number;
35
+ panStick: GamepadStickBindingOptions;
40
36
  /**
41
- * Axis index for **horizontal** panning.
42
- * @default 2 — Right stick X
43
- */
44
- axisPanX: number;
45
- /**
46
- * Axis index for **vertical** panning.
47
- * @default 3 — Right stick Y
37
+ * Dead zone threshold for analog trigger values.
38
+ * @default 0.1
48
39
  */
49
- axisPanY: number;
40
+ buttonDeadzone: number;
50
41
  /**
51
42
  * Button index for zooming **in** (analog trigger value used for proportional zoom).
52
43
  * @default 7 — Right trigger
@@ -1,15 +1,22 @@
1
1
  import { GAMEPAD_AXIS, GAMEPAD_BUTTON } from "./core.js";
2
+ import { DEFAULT_GAMEPAD_STICK_PIPELINE, resolveGamepadStickBinding } from "./gamepad-stick-processing.js";
2
3
  import { GamepadControls } from "./gamepad-controls.js";
3
4
  //#region src/gamepad-orbit-controls.ts
4
5
  const DEFAULT_ORBIT_OPTIONS = {
5
6
  rotateSpeed: 1,
6
7
  panSpeed: 1,
7
8
  zoomSpeed: 1,
8
- deadzone: .1,
9
- axisRotateX: GAMEPAD_AXIS.LeftX,
10
- axisRotateY: GAMEPAD_AXIS.LeftY,
11
- axisPanX: GAMEPAD_AXIS.RightX,
12
- axisPanY: GAMEPAD_AXIS.RightY,
9
+ rotateStick: {
10
+ xAxis: GAMEPAD_AXIS.LeftX,
11
+ yAxis: GAMEPAD_AXIS.LeftY,
12
+ pipeline: DEFAULT_GAMEPAD_STICK_PIPELINE
13
+ },
14
+ panStick: {
15
+ xAxis: GAMEPAD_AXIS.RightX,
16
+ yAxis: GAMEPAD_AXIS.RightY,
17
+ pipeline: DEFAULT_GAMEPAD_STICK_PIPELINE
18
+ },
19
+ buttonDeadzone: .1,
13
20
  buttonDollyIn: GAMEPAD_BUTTON.RightTrigger,
14
21
  buttonDollyOut: GAMEPAD_BUTTON.LeftTrigger
15
22
  };
@@ -32,7 +39,9 @@ var GamepadOrbitControls = class extends GamepadControls {
32
39
  this.#controls = controls;
33
40
  this.#options = {
34
41
  ...DEFAULT_ORBIT_OPTIONS,
35
- ...options
42
+ ...options,
43
+ rotateStick: resolveGamepadStickBinding(DEFAULT_ORBIT_OPTIONS.rotateStick, options?.rotateStick),
44
+ panStick: resolveGamepadStickBinding(DEFAULT_ORBIT_OPTIONS.panStick, options?.panStick)
36
45
  };
37
46
  }
38
47
  /**
@@ -41,19 +50,17 @@ var GamepadOrbitControls = class extends GamepadControls {
41
50
  * @param deltaTime - Seconds since the last frame.
42
51
  */
43
52
  onUpdate(deltaTime) {
44
- const { rotateSpeed, panSpeed, zoomSpeed, deadzone, axisRotateX, axisRotateY, axisPanX, axisPanY, buttonDollyIn, buttonDollyOut } = this.#options;
53
+ const { rotateSpeed, panSpeed, zoomSpeed, rotateStick, panStick, buttonDeadzone, buttonDollyIn, buttonDollyOut } = this.#options;
45
54
  const input = this.gamepadInput;
46
- const rotX = input.axis(axisRotateX, { deadzone });
47
- const rotY = input.axis(axisRotateY, { deadzone });
48
- if (rotX !== 0) this.#controls.rotateLeft(rotX * rotateSpeed * deltaTime * Math.PI);
49
- if (rotY !== 0) this.#controls.rotateUp(rotY * rotateSpeed * deltaTime * Math.PI);
50
- const panX = input.axis(axisPanX, { deadzone });
51
- const panY = input.axis(axisPanY, { deadzone });
52
- if (panX !== 0 || panY !== 0) this.#controls.pan(panX * panSpeed * deltaTime * 500, panY * panSpeed * deltaTime * 500);
55
+ const rotate = input.stick(rotateStick.xAxis, rotateStick.yAxis, rotateStick.pipeline);
56
+ if (rotate.x !== 0) this.#controls.rotateLeft(rotate.x * rotateSpeed * deltaTime * Math.PI);
57
+ if (rotate.y !== 0) this.#controls.rotateUp(rotate.y * rotateSpeed * deltaTime * Math.PI);
58
+ const pan = input.stick(panStick.xAxis, panStick.yAxis, panStick.pipeline);
59
+ if (pan.x !== 0 || pan.y !== 0) this.#controls.pan(pan.x * panSpeed * deltaTime * 500, pan.y * panSpeed * deltaTime * 500);
53
60
  const triggerIn = input.buttonValue(buttonDollyIn);
54
61
  const triggerOut = input.buttonValue(buttonDollyOut);
55
- if (triggerIn > deadzone) this.#controls.dollyIn(1 / (1 + zoomSpeed * triggerIn * deltaTime));
56
- if (triggerOut > deadzone) this.#controls.dollyOut(1 / (1 + zoomSpeed * triggerOut * deltaTime));
62
+ if (triggerIn > buttonDeadzone) this.#controls.dollyIn(1 / (1 + zoomSpeed * triggerIn * deltaTime));
63
+ if (triggerOut > buttonDeadzone) this.#controls.dollyOut(1 / (1 + zoomSpeed * triggerOut * deltaTime));
57
64
  }
58
65
  };
59
66
  //#endregion
@@ -1,3 +1,4 @@
1
+ import { GamepadStickBindingOptions } from "./gamepad-stick-processing.js";
1
2
  import { GamepadControls, GamepadControlsOptions } from "./gamepad-controls.js";
2
3
  import { PointerLockControls } from "three/addons/controls/PointerLockControls.js";
3
4
  //#region src/gamepad-pointer-lock-controls.d.ts
@@ -18,30 +19,15 @@ type GamepadPointerLockControlsOptions = GamepadControlsOptions & {
18
19
  */
19
20
  lookSpeed: number;
20
21
  /**
21
- * Axis dead zone threshold in the range `[0, 1]`.
22
- * @default 0.1
22
+ * Stick binding used for horizontal and forward movement.
23
+ * @default Left stick with the default stick pipeline
23
24
  */
24
- deadzone: number;
25
+ moveStick: GamepadStickBindingOptions;
25
26
  /**
26
- * Axis index for **forward / backward** movement.
27
- * @default 1 — Left stick Y
27
+ * Stick binding used for yaw and pitch.
28
+ * @default Right stick with the default stick pipeline
28
29
  */
29
- axisMoveForward: number;
30
- /**
31
- * Axis index for **right / left** strafe movement.
32
- * @default 0 — Left stick X
33
- */
34
- axisMoveRight: number;
35
- /**
36
- * Axis index for **horizontal** camera look (yaw).
37
- * @default 2 — Right stick X
38
- */
39
- axisLookX: number;
40
- /**
41
- * Axis index for **vertical** camera look (pitch).
42
- * @default 3 — Right stick Y
43
- */
44
- axisLookY: number;
30
+ lookStick: GamepadStickBindingOptions;
45
31
  };
46
32
  /**
47
33
  * Adds gamepad support to Three.js `PointerLockControls`.
@@ -1,15 +1,21 @@
1
1
  import { GAMEPAD_AXIS } from "./core.js";
2
+ import { DEFAULT_GAMEPAD_STICK_PIPELINE, resolveGamepadStickBinding } from "./gamepad-stick-processing.js";
2
3
  import { GamepadControls } from "./gamepad-controls.js";
3
4
  import { Euler } from "three";
4
5
  //#region src/gamepad-pointer-lock-controls.ts
5
6
  const DEFAULT_POINTER_LOCK_OPTIONS = {
6
7
  moveSpeed: 5,
7
8
  lookSpeed: 1,
8
- deadzone: .1,
9
- axisMoveForward: GAMEPAD_AXIS.LeftY,
10
- axisMoveRight: GAMEPAD_AXIS.LeftX,
11
- axisLookX: GAMEPAD_AXIS.RightX,
12
- axisLookY: GAMEPAD_AXIS.RightY
9
+ moveStick: {
10
+ xAxis: GAMEPAD_AXIS.LeftX,
11
+ yAxis: GAMEPAD_AXIS.LeftY,
12
+ pipeline: DEFAULT_GAMEPAD_STICK_PIPELINE
13
+ },
14
+ lookStick: {
15
+ xAxis: GAMEPAD_AXIS.RightX,
16
+ yAxis: GAMEPAD_AXIS.RightY,
17
+ pipeline: DEFAULT_GAMEPAD_STICK_PIPELINE
18
+ }
13
19
  };
14
20
  /**
15
21
  * Adds gamepad support to Three.js `PointerLockControls`.
@@ -32,7 +38,9 @@ var GamepadPointerLockControls = class extends GamepadControls {
32
38
  this.#controls = controls;
33
39
  this.#options = {
34
40
  ...DEFAULT_POINTER_LOCK_OPTIONS,
35
- ...options
41
+ ...options,
42
+ moveStick: resolveGamepadStickBinding(DEFAULT_POINTER_LOCK_OPTIONS.moveStick, options?.moveStick),
43
+ lookStick: resolveGamepadStickBinding(DEFAULT_POINTER_LOCK_OPTIONS.lookStick, options?.lookStick)
36
44
  };
37
45
  this.#euler = new Euler(0, 0, 0, "YXZ");
38
46
  }
@@ -42,20 +50,18 @@ var GamepadPointerLockControls = class extends GamepadControls {
42
50
  * @param deltaTime - Seconds since the last frame.
43
51
  */
44
52
  onUpdate(deltaTime) {
45
- const { moveSpeed, lookSpeed, deadzone, axisMoveForward, axisMoveRight, axisLookX, axisLookY } = this.#options;
53
+ const { moveSpeed, lookSpeed, moveStick, lookStick } = this.#options;
46
54
  const input = this.gamepadInput;
47
- const fwd = input.axis(axisMoveForward, { deadzone });
48
- const strafe = input.axis(axisMoveRight, { deadzone });
49
- if (fwd !== 0) this.#controls.moveForward(-fwd * moveSpeed * deltaTime);
50
- if (strafe !== 0) this.#controls.moveRight(strafe * moveSpeed * deltaTime);
51
- const lookX = input.axis(axisLookX, { deadzone });
52
- const lookY = input.axis(axisLookY, { deadzone });
53
- if (lookX !== 0 || lookY !== 0) {
55
+ const move = input.stick(moveStick.xAxis, moveStick.yAxis, moveStick.pipeline);
56
+ if (move.y !== 0) this.#controls.moveForward(-move.y * moveSpeed * deltaTime);
57
+ if (move.x !== 0) this.#controls.moveRight(move.x * moveSpeed * deltaTime);
58
+ const look = input.stick(lookStick.xAxis, lookStick.yAxis, lookStick.pipeline);
59
+ if (look.x !== 0 || look.y !== 0) {
54
60
  const camera = this.#controls.object;
55
61
  const scale = lookSpeed * this.#controls.pointerSpeed * deltaTime * Math.PI;
56
62
  this.#euler.setFromQuaternion(camera.quaternion);
57
- this.#euler.y -= lookX * scale;
58
- this.#euler.x -= lookY * scale;
63
+ this.#euler.y -= look.x * scale;
64
+ this.#euler.x -= look.y * scale;
59
65
  this.#euler.x = Math.max(Math.PI / 2 - this.#controls.maxPolarAngle, Math.min(Math.PI / 2 - this.#controls.minPolarAngle, this.#euler.x));
60
66
  camera.quaternion.setFromEuler(this.#euler);
61
67
  }
@@ -0,0 +1,138 @@
1
+ //#region src/gamepad-stick-processing.d.ts
2
+ /**
3
+ * Dead zone processing mode for two-dimensional stick reads.
4
+ */
5
+ type GamepadDeadzoneMode = "axial" | "radial";
6
+ /**
7
+ * Two-dimensional gamepad stick value.
8
+ */
9
+ type GamepadStick = {
10
+ /**
11
+ * Horizontal stick component.
12
+ */
13
+ x: number;
14
+ /**
15
+ * Vertical stick component.
16
+ */
17
+ y: number;
18
+ };
19
+ /**
20
+ * Pure, stateless transformation applied to a gamepad stick.
21
+ *
22
+ * Implementations must not mutate `value`. Stateful processing such as
23
+ * smoothing belongs in a separate lifecycle-aware abstraction.
24
+ */
25
+ type GamepadStickProcessor = {
26
+ /**
27
+ * Transforms one stick value.
28
+ *
29
+ * @param value - Input value from the previous processor.
30
+ * @returns Processed stick value.
31
+ */
32
+ process(value: Readonly<GamepadStick>): GamepadStick;
33
+ };
34
+ /**
35
+ * Ordered, reusable sequence of stateless stick processors.
36
+ */
37
+ type GamepadStickPipeline = GamepadStickProcessor & {
38
+ /**
39
+ * Processors in execution order.
40
+ */
41
+ readonly processors: readonly GamepadStickProcessor[];
42
+ };
43
+ /**
44
+ * Options for {@link createGamepadDeadzoneProcessor}.
45
+ */
46
+ type GamepadDeadzoneProcessorOptions = {
47
+ /**
48
+ * Dead zone threshold.
49
+ * @default 0.1
50
+ */
51
+ threshold?: number;
52
+ /**
53
+ * Whether to process each component or the vector magnitude.
54
+ * @default "axial"
55
+ */
56
+ mode?: GamepadDeadzoneMode;
57
+ /**
58
+ * Whether to remap values outside the dead zone to the full output range.
59
+ * @default false
60
+ */
61
+ rescale?: boolean;
62
+ };
63
+ /**
64
+ * Options for {@link createGamepadInversionProcessor}.
65
+ */
66
+ type GamepadInversionProcessorOptions = {
67
+ /**
68
+ * Whether to invert the horizontal component.
69
+ * @default false
70
+ */
71
+ invertX?: boolean;
72
+ /**
73
+ * Whether to invert the vertical component.
74
+ * @default false
75
+ */
76
+ invertY?: boolean;
77
+ };
78
+ /**
79
+ * Partial binding for a two-dimensional stick action.
80
+ *
81
+ * Omitted fields inherit the action-specific defaults.
82
+ */
83
+ type GamepadStickBindingOptions = {
84
+ /**
85
+ * Axis index used as the horizontal component.
86
+ */
87
+ xAxis?: number;
88
+ /**
89
+ * Axis index used as the vertical component.
90
+ */
91
+ yAxis?: number;
92
+ /**
93
+ * Stateless processing pipeline for this action.
94
+ */
95
+ pipeline?: GamepadStickPipeline;
96
+ };
97
+ /**
98
+ * Fully resolved binding used when reading a two-dimensional stick action.
99
+ */
100
+ type GamepadStickBinding = Required<GamepadStickBindingOptions>;
101
+ /**
102
+ * Creates an ordered pipeline from stateless stick processors.
103
+ *
104
+ * The processor list is copied once. Processor errors are not caught, and a
105
+ * processor's result is passed directly to the next processor.
106
+ *
107
+ * @param processors - Processors in execution order.
108
+ * @returns Reusable stick pipeline.
109
+ */
110
+ declare const createGamepadStickPipeline: (...processors: readonly GamepadStickProcessor[]) => GamepadStickPipeline;
111
+ /**
112
+ * Creates an axial or radial dead zone processor.
113
+ *
114
+ * @param options - Optional dead zone configuration.
115
+ * @returns Stateless dead zone processor.
116
+ */
117
+ declare const createGamepadDeadzoneProcessor: (options?: GamepadDeadzoneProcessorOptions) => GamepadStickProcessor;
118
+ /**
119
+ * Creates a processor that independently inverts stick components.
120
+ *
121
+ * @param options - Optional inversion configuration.
122
+ * @returns Stateless inversion processor.
123
+ */
124
+ declare const createGamepadInversionProcessor: (options?: GamepadInversionProcessorOptions) => GamepadStickProcessor;
125
+ /**
126
+ * Historical stick processing used when no custom pipeline is supplied.
127
+ */
128
+ declare const DEFAULT_GAMEPAD_STICK_PIPELINE: GamepadStickPipeline;
129
+ /**
130
+ * Resolves a partial stick binding over an action-specific default.
131
+ *
132
+ * @param defaults - Complete default binding.
133
+ * @param options - Optional binding overrides.
134
+ * @returns Complete resolved binding.
135
+ */
136
+ declare const resolveGamepadStickBinding: (defaults: GamepadStickBinding, options?: GamepadStickBindingOptions) => GamepadStickBinding;
137
+ //#endregion
138
+ export { DEFAULT_GAMEPAD_STICK_PIPELINE, GamepadDeadzoneMode, GamepadDeadzoneProcessorOptions, GamepadInversionProcessorOptions, GamepadStick, GamepadStickBinding, GamepadStickBindingOptions, GamepadStickPipeline, GamepadStickProcessor, createGamepadDeadzoneProcessor, createGamepadInversionProcessor, createGamepadStickPipeline, resolveGamepadStickBinding };