three-gamepad-controls 0.4.0 → 0.6.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 +2 -0
- package/dist/gamepad-first-person-controls.d.ts +81 -0
- package/dist/gamepad-first-person-controls.js +124 -0
- package/dist/gamepad-map-controls.d.ts +22 -0
- package/dist/gamepad-map-controls.js +35 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.js +3 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -38,6 +38,8 @@ bun add three-gamepad-controls
|
|
|
38
38
|
|
|
39
39
|
- [Core](./docs/core.md) — The fundamental building blocks.
|
|
40
40
|
- [GamepadControls](./docs/gamepad-controls.md) — Abstract base class for custom gamepad controls.
|
|
41
|
+
- [GamepadFirstPersonControls](./docs/gamepad-first-person-controls.md) — Gamepad support for `FirstPersonControls`.
|
|
41
42
|
- [GamepadFlyControls](./docs/gamepad-fly-controls.md) — Gamepad support for `FlyControls`.
|
|
43
|
+
- [GamepadMapControls](./docs/gamepad-map-controls.md) — Gamepad support for `MapControls`.
|
|
42
44
|
- [GamepadOrbitControls](./docs/gamepad-orbit-controls.md) — Gamepad support for `OrbitControls`.
|
|
43
45
|
- [GamepadPointerLockControls](./docs/gamepad-pointer-lock-controls.md) — Gamepad support for `PointerLockControls`.
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { GamepadControls } from "./gamepad-controls.js";
|
|
2
|
+
import { FirstPersonControls } from "three/addons/controls/FirstPersonControls.js";
|
|
3
|
+
|
|
4
|
+
//#region src/gamepad-first-person-controls.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* Configuration for {@link GamepadFirstPersonControls}.
|
|
7
|
+
*
|
|
8
|
+
* Every property has a sensible default, so you only need to pass the properties you want to override.
|
|
9
|
+
*/
|
|
10
|
+
type GamepadFirstPersonControlsOptions = {
|
|
11
|
+
/**
|
|
12
|
+
* Multiplier on `FirstPersonControls.movementSpeed` for translation.
|
|
13
|
+
* @default 1.0
|
|
14
|
+
*/
|
|
15
|
+
moveSpeed: number;
|
|
16
|
+
/**
|
|
17
|
+
* Multiplier on `FirstPersonControls.lookSpeed` for camera look.
|
|
18
|
+
* @default 1.0
|
|
19
|
+
*/
|
|
20
|
+
lookSpeed: number;
|
|
21
|
+
/**
|
|
22
|
+
* Axis dead zone threshold in the range `[0, 1]`.
|
|
23
|
+
* @default 0.1
|
|
24
|
+
*/
|
|
25
|
+
deadzone: number;
|
|
26
|
+
/**
|
|
27
|
+
* Axis index for **forward / backward** movement.
|
|
28
|
+
* @default 1 - Left stick Y
|
|
29
|
+
*/
|
|
30
|
+
axisMoveForward: number;
|
|
31
|
+
/**
|
|
32
|
+
* Axis index for **right / left** strafe movement.
|
|
33
|
+
* @default 0 - Left stick X
|
|
34
|
+
*/
|
|
35
|
+
axisMoveRight: number;
|
|
36
|
+
/**
|
|
37
|
+
* Axis index for **horizontal** camera look (yaw).
|
|
38
|
+
* @default 2 - Right stick X
|
|
39
|
+
*/
|
|
40
|
+
axisLookX: number;
|
|
41
|
+
/**
|
|
42
|
+
* Axis index for **vertical** camera look (pitch).
|
|
43
|
+
* @default 3 - Right stick Y
|
|
44
|
+
*/
|
|
45
|
+
axisLookY: number;
|
|
46
|
+
/**
|
|
47
|
+
* Button index for **moving up** (analog trigger value used for proportional speed).
|
|
48
|
+
* @default 6 - Left trigger
|
|
49
|
+
*/
|
|
50
|
+
buttonMoveUp: number;
|
|
51
|
+
/**
|
|
52
|
+
* Button index for **moving down** (analog trigger value used for proportional speed).
|
|
53
|
+
* @default 7 - Right trigger
|
|
54
|
+
*/
|
|
55
|
+
buttonMoveDown: number;
|
|
56
|
+
};
|
|
57
|
+
/**
|
|
58
|
+
* Adds gamepad support to Three.js `FirstPersonControls`.
|
|
59
|
+
*
|
|
60
|
+
* Gamepad input is additive with keyboard/mouse input - call
|
|
61
|
+
* `gamepadControls.update(delta)` before `controls.update(delta)` each frame.
|
|
62
|
+
* Bindings and speeds are configurable via {@link GamepadFirstPersonControlsOptions}.
|
|
63
|
+
*/
|
|
64
|
+
declare class GamepadFirstPersonControls extends GamepadControls {
|
|
65
|
+
#private;
|
|
66
|
+
/**
|
|
67
|
+
* @param controls - A Three.js `FirstPersonControls` instance.
|
|
68
|
+
* @param options - Optional overrides for the default behavior.
|
|
69
|
+
* Any property not provided falls back to its default value.
|
|
70
|
+
*/
|
|
71
|
+
constructor(controls: FirstPersonControls, options?: Partial<GamepadFirstPersonControlsOptions>);
|
|
72
|
+
/**
|
|
73
|
+
* Maps the current gamepad state to `FirstPersonControls` translation and look.
|
|
74
|
+
*
|
|
75
|
+
* @param deltaTime - Seconds since the last frame.
|
|
76
|
+
* @param gamepad - Fresh gamepad snapshot provided by the base class.
|
|
77
|
+
*/
|
|
78
|
+
protected onUpdate(deltaTime: number, gamepad: Gamepad): void;
|
|
79
|
+
}
|
|
80
|
+
//#endregion
|
|
81
|
+
export { GamepadFirstPersonControls, GamepadFirstPersonControlsOptions };
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { GAMEPAD_AXIS, GAMEPAD_BUTTON } from "./core.js";
|
|
2
|
+
import { GamepadControls } from "./gamepad-controls.js";
|
|
3
|
+
import { MathUtils, Spherical, Vector3 } from "three";
|
|
4
|
+
//#region src/gamepad-first-person-controls.ts
|
|
5
|
+
/**
|
|
6
|
+
* Default options merged in the constructor when no explicit configuration is provided.
|
|
7
|
+
*/
|
|
8
|
+
const DEFAULT_FIRST_PERSON_OPTIONS = {
|
|
9
|
+
moveSpeed: 1,
|
|
10
|
+
lookSpeed: 1,
|
|
11
|
+
deadzone: .1,
|
|
12
|
+
axisMoveForward: GAMEPAD_AXIS.LeftY,
|
|
13
|
+
axisMoveRight: GAMEPAD_AXIS.LeftX,
|
|
14
|
+
axisLookX: GAMEPAD_AXIS.RightX,
|
|
15
|
+
axisLookY: GAMEPAD_AXIS.RightY,
|
|
16
|
+
buttonMoveUp: GAMEPAD_BUTTON.LeftTrigger,
|
|
17
|
+
buttonMoveDown: GAMEPAD_BUTTON.RightTrigger
|
|
18
|
+
};
|
|
19
|
+
const LOOK_SPEED_SCALE = 36e3;
|
|
20
|
+
/**
|
|
21
|
+
* Adds gamepad support to Three.js `FirstPersonControls`.
|
|
22
|
+
*
|
|
23
|
+
* Gamepad input is additive with keyboard/mouse input - call
|
|
24
|
+
* `gamepadControls.update(delta)` before `controls.update(delta)` each frame.
|
|
25
|
+
* Bindings and speeds are configurable via {@link GamepadFirstPersonControlsOptions}.
|
|
26
|
+
*/
|
|
27
|
+
var GamepadFirstPersonControls = class extends GamepadControls {
|
|
28
|
+
#controls;
|
|
29
|
+
#options;
|
|
30
|
+
#lookDirection;
|
|
31
|
+
#spherical;
|
|
32
|
+
#targetPosition;
|
|
33
|
+
/**
|
|
34
|
+
* @param controls - A Three.js `FirstPersonControls` instance.
|
|
35
|
+
* @param options - Optional overrides for the default behavior.
|
|
36
|
+
* Any property not provided falls back to its default value.
|
|
37
|
+
*/
|
|
38
|
+
constructor(controls, options) {
|
|
39
|
+
super();
|
|
40
|
+
this.#controls = controls;
|
|
41
|
+
this.#options = {
|
|
42
|
+
...DEFAULT_FIRST_PERSON_OPTIONS,
|
|
43
|
+
...options
|
|
44
|
+
};
|
|
45
|
+
this.#lookDirection = new Vector3();
|
|
46
|
+
this.#spherical = new Spherical();
|
|
47
|
+
this.#targetPosition = new Vector3();
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Maps the current gamepad state to `FirstPersonControls` translation and look.
|
|
51
|
+
*
|
|
52
|
+
* @param deltaTime - Seconds since the last frame.
|
|
53
|
+
* @param gamepad - Fresh gamepad snapshot provided by the base class.
|
|
54
|
+
*/
|
|
55
|
+
onUpdate(deltaTime, gamepad) {
|
|
56
|
+
const { moveSpeed, lookSpeed, deadzone, axisMoveForward, axisMoveRight, axisLookX, axisLookY, buttonMoveUp, buttonMoveDown } = this.#options;
|
|
57
|
+
this.#applyMovement(deltaTime, gamepad, moveSpeed, deadzone, axisMoveForward, axisMoveRight, buttonMoveUp, buttonMoveDown);
|
|
58
|
+
this.#applyLook(deltaTime, gamepad, lookSpeed, deadzone, axisLookX, axisLookY);
|
|
59
|
+
}
|
|
60
|
+
#applyMovement(deltaTime, gamepad, moveSpeed, deadzone, axisMoveForward, axisMoveRight, buttonMoveUp, buttonMoveDown) {
|
|
61
|
+
const controls = this.#controls;
|
|
62
|
+
const moveMult = deltaTime * controls.movementSpeed * moveSpeed;
|
|
63
|
+
const forward = this.#applyDeadzone(gamepad.axes[axisMoveForward] ?? 0, deadzone);
|
|
64
|
+
if (forward !== 0) {
|
|
65
|
+
let distance = forward * moveMult;
|
|
66
|
+
if (forward < 0 && controls.heightSpeed) {
|
|
67
|
+
const heightDelta = MathUtils.clamp(controls.object.position.y, controls.heightMin, controls.heightMax) - controls.heightMin;
|
|
68
|
+
distance -= -forward * deltaTime * heightDelta * controls.heightCoef * moveSpeed;
|
|
69
|
+
}
|
|
70
|
+
controls.object.translateZ(distance);
|
|
71
|
+
}
|
|
72
|
+
const strafe = this.#applyDeadzone(gamepad.axes[axisMoveRight] ?? 0, deadzone);
|
|
73
|
+
if (strafe !== 0) controls.object.translateX(strafe * moveMult);
|
|
74
|
+
const up = gamepad.buttons[buttonMoveUp]?.value ?? 0;
|
|
75
|
+
const down = gamepad.buttons[buttonMoveDown]?.value ?? 0;
|
|
76
|
+
if (up > deadzone) controls.object.translateY(up * moveMult);
|
|
77
|
+
if (down > deadzone) controls.object.translateY(-down * moveMult);
|
|
78
|
+
}
|
|
79
|
+
#applyLook(deltaTime, gamepad, lookSpeed, deadzone, axisLookX, axisLookY) {
|
|
80
|
+
const lookX = this.#applyDeadzone(gamepad.axes[axisLookX] ?? 0, deadzone);
|
|
81
|
+
const lookY = this.#applyDeadzone(gamepad.axes[axisLookY] ?? 0, deadzone);
|
|
82
|
+
if (lookX === 0 && lookY === 0) return;
|
|
83
|
+
const controls = this.#controls;
|
|
84
|
+
const actualLookSpeed = controls.lookSpeed * lookSpeed * deltaTime * LOOK_SPEED_SCALE;
|
|
85
|
+
let { lat, lon } = this.#getOrientation();
|
|
86
|
+
let verticalLookRatio = 1;
|
|
87
|
+
const verticalRange = controls.verticalMax - controls.verticalMin;
|
|
88
|
+
if (controls.constrainVertical && verticalRange !== 0) verticalLookRatio = Math.PI / verticalRange;
|
|
89
|
+
lon -= lookX * actualLookSpeed;
|
|
90
|
+
if (controls.lookVertical) lat -= lookY * actualLookSpeed * verticalLookRatio;
|
|
91
|
+
lat = Math.max(-85, Math.min(85, lat));
|
|
92
|
+
let phi = MathUtils.degToRad(90 - lat);
|
|
93
|
+
const theta = MathUtils.degToRad(lon);
|
|
94
|
+
if (controls.constrainVertical) phi = MathUtils.mapLinear(phi, 0, Math.PI, controls.verticalMin, controls.verticalMax);
|
|
95
|
+
this.#targetPosition.setFromSphericalCoords(1, phi, theta).add(controls.object.position);
|
|
96
|
+
controls.object.lookAt(this.#targetPosition);
|
|
97
|
+
controls._lat = lat;
|
|
98
|
+
controls._lon = lon;
|
|
99
|
+
}
|
|
100
|
+
#getOrientation() {
|
|
101
|
+
const { _lat, _lon } = this.#controls;
|
|
102
|
+
if (Number.isFinite(_lat) && Number.isFinite(_lon)) return {
|
|
103
|
+
lat: _lat,
|
|
104
|
+
lon: _lon
|
|
105
|
+
};
|
|
106
|
+
this.#lookDirection.set(0, 0, -1).applyQuaternion(this.#controls.object.quaternion);
|
|
107
|
+
this.#spherical.setFromVector3(this.#lookDirection);
|
|
108
|
+
return {
|
|
109
|
+
lat: 90 - MathUtils.radToDeg(this.#spherical.phi),
|
|
110
|
+
lon: MathUtils.radToDeg(this.#spherical.theta)
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Returns `value` unchanged, or `0` if below the dead zone `threshold`.
|
|
115
|
+
*
|
|
116
|
+
* @param value - Raw axis or trigger value, typically in `[-1, 1]`.
|
|
117
|
+
* @param threshold - Dead zone size; values below this magnitude are zeroed.
|
|
118
|
+
*/
|
|
119
|
+
#applyDeadzone(value, threshold) {
|
|
120
|
+
return Math.abs(value) < threshold ? 0 : value;
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
//#endregion
|
|
124
|
+
export { GamepadFirstPersonControls };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { GamepadOrbitControls, GamepadOrbitControlsOptions } from "./gamepad-orbit-controls.js";
|
|
2
|
+
import { MapControls } from "three/addons/controls/MapControls.js";
|
|
3
|
+
|
|
4
|
+
//#region src/gamepad-map-controls.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* Adds gamepad support to Three.js `MapControls`.
|
|
7
|
+
*
|
|
8
|
+
* Pan is the primary action (left stick by default), matching `MapControls`'
|
|
9
|
+
* mouse conventions. All options from {@link GamepadOrbitControlsOptions} are available.
|
|
10
|
+
*
|
|
11
|
+
* Call `update()` inside the render loop **before** `MapControls.update()`.
|
|
12
|
+
*/
|
|
13
|
+
declare class GamepadMapControls extends GamepadOrbitControls {
|
|
14
|
+
/**
|
|
15
|
+
* @param controls - A Three.js `MapControls` instance.
|
|
16
|
+
* @param options - Optional overrides for the default behavior.
|
|
17
|
+
* Any property not provided falls back to its default value.
|
|
18
|
+
*/
|
|
19
|
+
constructor(controls: MapControls, options?: Partial<GamepadOrbitControlsOptions>);
|
|
20
|
+
}
|
|
21
|
+
//#endregion
|
|
22
|
+
export { GamepadMapControls };
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { GAMEPAD_AXIS } from "./core.js";
|
|
2
|
+
import { GamepadOrbitControls } from "./gamepad-orbit-controls.js";
|
|
3
|
+
//#region src/gamepad-map-controls.ts
|
|
4
|
+
/**
|
|
5
|
+
* Axis overrides for {@link GamepadMapControls}: left stick pans, right stick orbits.
|
|
6
|
+
*/
|
|
7
|
+
const DEFAULT_MAP_OPTIONS = {
|
|
8
|
+
axisPanX: GAMEPAD_AXIS.LeftX,
|
|
9
|
+
axisPanY: GAMEPAD_AXIS.LeftY,
|
|
10
|
+
axisRotateX: GAMEPAD_AXIS.RightX,
|
|
11
|
+
axisRotateY: GAMEPAD_AXIS.RightY
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Adds gamepad support to Three.js `MapControls`.
|
|
15
|
+
*
|
|
16
|
+
* Pan is the primary action (left stick by default), matching `MapControls`'
|
|
17
|
+
* mouse conventions. All options from {@link GamepadOrbitControlsOptions} are available.
|
|
18
|
+
*
|
|
19
|
+
* Call `update()` inside the render loop **before** `MapControls.update()`.
|
|
20
|
+
*/
|
|
21
|
+
var GamepadMapControls = class extends GamepadOrbitControls {
|
|
22
|
+
/**
|
|
23
|
+
* @param controls - A Three.js `MapControls` instance.
|
|
24
|
+
* @param options - Optional overrides for the default behavior.
|
|
25
|
+
* Any property not provided falls back to its default value.
|
|
26
|
+
*/
|
|
27
|
+
constructor(controls, options) {
|
|
28
|
+
super(controls, {
|
|
29
|
+
...DEFAULT_MAP_OPTIONS,
|
|
30
|
+
...options
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
//#endregion
|
|
35
|
+
export { GamepadMapControls };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { GAMEPAD_AXIS, GAMEPAD_BUTTON, GamepadAxisKey, GamepadAxisValue, GamepadButtonKey, GamepadButtonValue } from "./core.js";
|
|
2
2
|
import { GamepadControls, GamepadControlsEventMap } from "./gamepad-controls.js";
|
|
3
|
+
import { GamepadFirstPersonControls, GamepadFirstPersonControlsOptions } from "./gamepad-first-person-controls.js";
|
|
3
4
|
import { GamepadFlyControls, GamepadFlyControlsOptions } from "./gamepad-fly-controls.js";
|
|
4
5
|
import { GamepadOrbitControls, GamepadOrbitControlsOptions } from "./gamepad-orbit-controls.js";
|
|
6
|
+
import { GamepadMapControls } from "./gamepad-map-controls.js";
|
|
5
7
|
import { GamepadPointerLockControls, GamepadPointerLockControlsOptions } from "./gamepad-pointer-lock-controls.js";
|
|
6
|
-
export { GAMEPAD_AXIS, GAMEPAD_BUTTON, GamepadAxisKey, GamepadAxisValue, GamepadButtonKey, GamepadButtonValue, GamepadControls, GamepadControlsEventMap, GamepadFlyControls, GamepadFlyControlsOptions, GamepadOrbitControls, GamepadOrbitControlsOptions, GamepadPointerLockControls, GamepadPointerLockControlsOptions };
|
|
8
|
+
export { GAMEPAD_AXIS, GAMEPAD_BUTTON, GamepadAxisKey, GamepadAxisValue, GamepadButtonKey, GamepadButtonValue, GamepadControls, GamepadControlsEventMap, GamepadFirstPersonControls, GamepadFirstPersonControlsOptions, GamepadFlyControls, GamepadFlyControlsOptions, GamepadMapControls, GamepadOrbitControls, GamepadOrbitControlsOptions, GamepadPointerLockControls, GamepadPointerLockControlsOptions };
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { GAMEPAD_AXIS, GAMEPAD_BUTTON } from "./core.js";
|
|
2
2
|
import { GamepadControls } from "./gamepad-controls.js";
|
|
3
|
+
import { GamepadFirstPersonControls } from "./gamepad-first-person-controls.js";
|
|
3
4
|
import { GamepadFlyControls } from "./gamepad-fly-controls.js";
|
|
4
5
|
import { GamepadOrbitControls } from "./gamepad-orbit-controls.js";
|
|
6
|
+
import { GamepadMapControls } from "./gamepad-map-controls.js";
|
|
5
7
|
import { GamepadPointerLockControls } from "./gamepad-pointer-lock-controls.js";
|
|
6
|
-
export { GAMEPAD_AXIS, GAMEPAD_BUTTON, GamepadControls, GamepadFlyControls, GamepadOrbitControls, GamepadPointerLockControls };
|
|
8
|
+
export { GAMEPAD_AXIS, GAMEPAD_BUTTON, GamepadControls, GamepadFirstPersonControls, GamepadFlyControls, GamepadMapControls, GamepadOrbitControls, GamepadPointerLockControls };
|
package/package.json
CHANGED