three-gamepad-controls 0.10.3 → 0.10.5
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/dist/gamepad-arcball-controls.js +8 -25
- package/dist/gamepad-controls.js +12 -3
- package/dist/gamepad-drag-controls.js +6 -17
- package/dist/gamepad-first-person-controls.js +7 -15
- package/dist/gamepad-fly-controls.js +8 -16
- package/dist/gamepad-orbit-controls.js +7 -15
- package/dist/gamepad-pointer-lock-controls.js +5 -13
- package/dist/gamepad-trackball-controls.js +14 -14
- package/dist/gamepad-transform-controls.js +4 -12
- package/dist/utils.js +60 -0
- package/package.json +3 -3
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { GAMEPAD_AXIS, GAMEPAD_BUTTON } from "./core.js";
|
|
2
|
+
import { applyGamepadDeadzone, getGamepadButtonPressed, getGamepadButtonValue } from "./utils.js";
|
|
2
3
|
import { GamepadControls } from "./gamepad-controls.js";
|
|
3
4
|
import { Vector2, Vector3 } from "three";
|
|
4
5
|
//#region src/gamepad-arcball-controls.ts
|
|
@@ -76,12 +77,12 @@ var GamepadArcballControls = class extends GamepadControls {
|
|
|
76
77
|
this.#endInteraction();
|
|
77
78
|
return;
|
|
78
79
|
}
|
|
79
|
-
const rotateX = controls.enableRotate ?
|
|
80
|
-
const rotateY = controls.enableRotate ?
|
|
81
|
-
const panX = controls.enablePan ?
|
|
82
|
-
const panY = controls.enablePan ?
|
|
83
|
-
const zoom = controls.enableZoom ?
|
|
84
|
-
const zRotation = controls.enableRotate ?
|
|
80
|
+
const rotateX = controls.enableRotate ? applyGamepadDeadzone(gamepad.axes[axisRotateX] ?? 0, deadzone) : 0;
|
|
81
|
+
const rotateY = controls.enableRotate ? applyGamepadDeadzone(gamepad.axes[axisRotateY] ?? 0, deadzone) : 0;
|
|
82
|
+
const panX = controls.enablePan ? applyGamepadDeadzone(gamepad.axes[axisPanX] ?? 0, deadzone) : 0;
|
|
83
|
+
const panY = controls.enablePan ? applyGamepadDeadzone(gamepad.axes[axisPanY] ?? 0, deadzone) : 0;
|
|
84
|
+
const zoom = controls.enableZoom ? getGamepadButtonValue(gamepad, buttonZoomIn) - getGamepadButtonValue(gamepad, buttonZoomOut) : 0;
|
|
85
|
+
const zRotation = controls.enableRotate ? getGamepadButtonValue(gamepad, buttonZRotateLeft) - getGamepadButtonValue(gamepad, buttonZRotateRight) : 0;
|
|
85
86
|
const activeInput = rotateX !== 0 || rotateY !== 0 || panX !== 0 || panY !== 0 || Math.abs(zoom) > deadzone || Math.abs(zRotation) > deadzone;
|
|
86
87
|
if (!activeInput && focusPoint === null) {
|
|
87
88
|
this.#endInteraction();
|
|
@@ -171,7 +172,7 @@ var GamepadArcballControls = class extends GamepadControls {
|
|
|
171
172
|
}
|
|
172
173
|
#consumeFocusPoint(gamepad, buttonFocus) {
|
|
173
174
|
const controls = this.#controls;
|
|
174
|
-
const focusPressed =
|
|
175
|
+
const focusPressed = getGamepadButtonPressed(gamepad, buttonFocus);
|
|
175
176
|
const shouldFocus = focusPressed && !this.#focusButtonPressed;
|
|
176
177
|
this.#focusButtonPressed = focusPressed;
|
|
177
178
|
if (!shouldFocus || !controls.enabled || !controls.enablePan || !controls.enableFocus || controls.scene === null) return null;
|
|
@@ -182,24 +183,6 @@ var GamepadArcballControls = class extends GamepadControls {
|
|
|
182
183
|
this.#controls.dispatchEvent({ type: "end" });
|
|
183
184
|
this.#wasInteracting = false;
|
|
184
185
|
}
|
|
185
|
-
#getButtonValue(gamepad, button) {
|
|
186
|
-
const gamepadButton = gamepad.buttons[button];
|
|
187
|
-
if (gamepadButton === void 0) return 0;
|
|
188
|
-
if (gamepadButton.value !== 0) return gamepadButton.value;
|
|
189
|
-
return gamepadButton.pressed ? 1 : 0;
|
|
190
|
-
}
|
|
191
|
-
#getButtonPressed(gamepad, button) {
|
|
192
|
-
return gamepad.buttons[button]?.pressed ?? false;
|
|
193
|
-
}
|
|
194
|
-
/**
|
|
195
|
-
* Returns `value` unchanged, or `0` if below the dead zone `threshold`.
|
|
196
|
-
*
|
|
197
|
-
* @param value - Raw axis or trigger value, typically in `[-1, 1]`.
|
|
198
|
-
* @param threshold - Dead zone size; values below this magnitude are zeroed.
|
|
199
|
-
*/
|
|
200
|
-
#applyDeadzone(value, threshold) {
|
|
201
|
-
return Math.abs(value) < threshold ? 0 : value;
|
|
202
|
-
}
|
|
203
186
|
};
|
|
204
187
|
//#endregion
|
|
205
188
|
export { GamepadArcballControls };
|
package/dist/gamepad-controls.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { getFirstConnectedGamepad, getGamepadByIndex } from "./utils.js";
|
|
1
2
|
import { EventDispatcher } from "three";
|
|
2
3
|
//#region src/gamepad-controls.ts
|
|
3
4
|
/**
|
|
@@ -36,9 +37,17 @@ var GamepadControls = class extends EventDispatcher {
|
|
|
36
37
|
*/
|
|
37
38
|
update(deltaTime) {
|
|
38
39
|
if (!this.enabled) return;
|
|
39
|
-
if (this.gamepad
|
|
40
|
-
const
|
|
41
|
-
|
|
40
|
+
if (this.gamepad === null) {
|
|
41
|
+
const connectedGamepad = getFirstConnectedGamepad();
|
|
42
|
+
if (connectedGamepad !== null) this.onGamepadConnected(connectedGamepad);
|
|
43
|
+
} else {
|
|
44
|
+
const previousGamepad = this.gamepad;
|
|
45
|
+
const nextGamepad = getGamepadByIndex(previousGamepad.index);
|
|
46
|
+
if (nextGamepad === null) {
|
|
47
|
+
this.onGamepadDisconnected(previousGamepad);
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
this.gamepad = nextGamepad;
|
|
42
51
|
}
|
|
43
52
|
if (this.gamepad === null) return;
|
|
44
53
|
this.onUpdate(deltaTime, this.gamepad);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { GAMEPAD_AXIS, GAMEPAD_BUTTON } from "./core.js";
|
|
2
|
+
import { applyGamepadDeadzone, getGamepadButtonPressed } from "./utils.js";
|
|
2
3
|
import { GamepadControls } from "./gamepad-controls.js";
|
|
3
4
|
import { Matrix4, Vector2, Vector3 } from "three";
|
|
4
5
|
//#region src/gamepad-drag-controls.ts
|
|
@@ -71,7 +72,7 @@ var GamepadDragControls = class extends GamepadControls {
|
|
|
71
72
|
*/
|
|
72
73
|
onUpdate(deltaTime, gamepad) {
|
|
73
74
|
const controls = this.#controls;
|
|
74
|
-
const selectPressed =
|
|
75
|
+
const selectPressed = getGamepadButtonPressed(gamepad, this.#options.buttonSelect);
|
|
75
76
|
const selectStarted = selectPressed && !this.#selectButtonPressed;
|
|
76
77
|
this.#selectButtonPressed = selectPressed;
|
|
77
78
|
if (!controls.enabled) {
|
|
@@ -114,10 +115,10 @@ var GamepadDragControls = class extends GamepadControls {
|
|
|
114
115
|
const selected = this.#selected;
|
|
115
116
|
if (selected === null) return;
|
|
116
117
|
const { dragSpeed, rotateSpeed, deadzone, axisDragX, axisDragY, axisRotateX, axisRotateY } = this.#options;
|
|
117
|
-
const dragX =
|
|
118
|
-
const dragY =
|
|
119
|
-
const rotateX =
|
|
120
|
-
const rotateY =
|
|
118
|
+
const dragX = applyGamepadDeadzone(gamepad.axes[axisDragX] ?? 0, deadzone);
|
|
119
|
+
const dragY = applyGamepadDeadzone(gamepad.axes[axisDragY] ?? 0, deadzone);
|
|
120
|
+
const rotateX = applyGamepadDeadzone(gamepad.axes[axisRotateX] ?? 0, deadzone);
|
|
121
|
+
const rotateY = applyGamepadDeadzone(gamepad.axes[axisRotateY] ?? 0, deadzone);
|
|
121
122
|
const dragged = this.#applyDrag(deltaTime, dragX, dragY, dragSpeed);
|
|
122
123
|
const rotated = this.#applyRotation(deltaTime, rotateX, rotateY, rotateSpeed);
|
|
123
124
|
if (dragged || rotated) this.#controls.dispatchEvent({
|
|
@@ -243,18 +244,6 @@ var GamepadDragControls = class extends GamepadControls {
|
|
|
243
244
|
#isOrthographicCamera(camera) {
|
|
244
245
|
return camera.isOrthographicCamera === true;
|
|
245
246
|
}
|
|
246
|
-
#getButtonPressed(gamepad, button) {
|
|
247
|
-
return gamepad.buttons[button]?.pressed ?? false;
|
|
248
|
-
}
|
|
249
|
-
/**
|
|
250
|
-
* Returns `value` unchanged, or `0` if below the dead zone `threshold`.
|
|
251
|
-
*
|
|
252
|
-
* @param value - Raw axis value, typically in `[-1, 1]`.
|
|
253
|
-
* @param threshold - Dead zone size; values below this magnitude are zeroed.
|
|
254
|
-
*/
|
|
255
|
-
#applyDeadzone(value, threshold) {
|
|
256
|
-
return Math.abs(value) < threshold ? 0 : value;
|
|
257
|
-
}
|
|
258
247
|
};
|
|
259
248
|
//#endregion
|
|
260
249
|
export { GamepadDragControls };
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { GAMEPAD_AXIS, GAMEPAD_BUTTON } from "./core.js";
|
|
2
|
+
import { applyGamepadDeadzone, getGamepadButtonValue } from "./utils.js";
|
|
2
3
|
import { GamepadControls } from "./gamepad-controls.js";
|
|
3
4
|
import { MathUtils, Spherical, Vector3 } from "three";
|
|
4
5
|
//#region src/gamepad-first-person-controls.ts
|
|
@@ -60,7 +61,7 @@ var GamepadFirstPersonControls = class extends GamepadControls {
|
|
|
60
61
|
#applyMovement(deltaTime, gamepad, moveSpeed, deadzone, axisMoveForward, axisMoveRight, buttonMoveUp, buttonMoveDown) {
|
|
61
62
|
const controls = this.#controls;
|
|
62
63
|
const moveMult = deltaTime * controls.movementSpeed * moveSpeed;
|
|
63
|
-
const forward =
|
|
64
|
+
const forward = applyGamepadDeadzone(gamepad.axes[axisMoveForward] ?? 0, deadzone);
|
|
64
65
|
if (forward !== 0) {
|
|
65
66
|
let distance = forward * moveMult;
|
|
66
67
|
if (forward < 0 && controls.heightSpeed) {
|
|
@@ -69,16 +70,16 @@ var GamepadFirstPersonControls = class extends GamepadControls {
|
|
|
69
70
|
}
|
|
70
71
|
controls.object.translateZ(distance);
|
|
71
72
|
}
|
|
72
|
-
const strafe =
|
|
73
|
+
const strafe = applyGamepadDeadzone(gamepad.axes[axisMoveRight] ?? 0, deadzone);
|
|
73
74
|
if (strafe !== 0) controls.object.translateX(strafe * moveMult);
|
|
74
|
-
const up = gamepad
|
|
75
|
-
const down = gamepad
|
|
75
|
+
const up = getGamepadButtonValue(gamepad, buttonMoveUp);
|
|
76
|
+
const down = getGamepadButtonValue(gamepad, buttonMoveDown);
|
|
76
77
|
if (up > deadzone) controls.object.translateY(up * moveMult);
|
|
77
78
|
if (down > deadzone) controls.object.translateY(-down * moveMult);
|
|
78
79
|
}
|
|
79
80
|
#applyLook(deltaTime, gamepad, lookSpeed, deadzone, axisLookX, axisLookY) {
|
|
80
|
-
const lookX =
|
|
81
|
-
const lookY =
|
|
81
|
+
const lookX = applyGamepadDeadzone(gamepad.axes[axisLookX] ?? 0, deadzone);
|
|
82
|
+
const lookY = applyGamepadDeadzone(gamepad.axes[axisLookY] ?? 0, deadzone);
|
|
82
83
|
if (lookX === 0 && lookY === 0) return;
|
|
83
84
|
const controls = this.#controls;
|
|
84
85
|
const actualLookSpeed = controls.lookSpeed * lookSpeed * deltaTime * LOOK_SPEED_SCALE;
|
|
@@ -110,15 +111,6 @@ var GamepadFirstPersonControls = class extends GamepadControls {
|
|
|
110
111
|
lon: MathUtils.radToDeg(this.#spherical.theta)
|
|
111
112
|
};
|
|
112
113
|
}
|
|
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
114
|
};
|
|
123
115
|
//#endregion
|
|
124
116
|
export { GamepadFirstPersonControls };
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { GAMEPAD_AXIS, GAMEPAD_BUTTON } from "./core.js";
|
|
2
|
+
import { applyGamepadDeadzone, getGamepadButtonPressed, getGamepadButtonValue } from "./utils.js";
|
|
2
3
|
import { GamepadControls } from "./gamepad-controls.js";
|
|
3
4
|
import { Quaternion } from "three";
|
|
4
5
|
//#region src/gamepad-fly-controls.ts
|
|
@@ -52,32 +53,23 @@ var GamepadFlyControls = class extends GamepadControls {
|
|
|
52
53
|
onUpdate(deltaTime, gamepad) {
|
|
53
54
|
const { moveSpeed, rotateSpeed, deadzone, axisMoveForward, axisMoveRight, axisLookX, axisLookY, buttonRollLeft, buttonRollRight, buttonMoveUp, buttonMoveDown } = this.#options;
|
|
54
55
|
const moveMult = deltaTime * this.#controls.movementSpeed * moveSpeed;
|
|
55
|
-
const fwd =
|
|
56
|
+
const fwd = applyGamepadDeadzone(gamepad.axes[axisMoveForward] ?? 0, deadzone);
|
|
56
57
|
if (fwd !== 0) this.#controls.object.translateZ(fwd * moveMult);
|
|
57
|
-
const strafe =
|
|
58
|
+
const strafe = applyGamepadDeadzone(gamepad.axes[axisMoveRight] ?? 0, deadzone);
|
|
58
59
|
if (strafe !== 0) this.#controls.object.translateX(strafe * moveMult);
|
|
59
|
-
const up = gamepad
|
|
60
|
-
const down = gamepad
|
|
60
|
+
const up = getGamepadButtonValue(gamepad, buttonMoveUp);
|
|
61
|
+
const down = getGamepadButtonValue(gamepad, buttonMoveDown);
|
|
61
62
|
if (up > deadzone) this.#controls.object.translateY(up * moveMult);
|
|
62
63
|
if (down > deadzone) this.#controls.object.translateY(-down * moveMult);
|
|
63
64
|
const rotMult = deltaTime * this.#controls.rollSpeed * rotateSpeed;
|
|
64
|
-
const pitch = -
|
|
65
|
-
const yaw = -
|
|
66
|
-
const roll = (gamepad
|
|
65
|
+
const pitch = -applyGamepadDeadzone(gamepad.axes[axisLookY] ?? 0, deadzone);
|
|
66
|
+
const yaw = -applyGamepadDeadzone(gamepad.axes[axisLookX] ?? 0, deadzone);
|
|
67
|
+
const roll = (getGamepadButtonPressed(gamepad, buttonRollLeft) ? 1 : 0) - (getGamepadButtonPressed(gamepad, buttonRollRight) ? 1 : 0);
|
|
67
68
|
if (pitch !== 0 || yaw !== 0 || roll !== 0) {
|
|
68
69
|
this.#tmpQuaternion.set(pitch * rotMult, yaw * rotMult, roll * rotMult, 1).normalize();
|
|
69
70
|
this.#controls.object.quaternion.multiply(this.#tmpQuaternion);
|
|
70
71
|
}
|
|
71
72
|
}
|
|
72
|
-
/**
|
|
73
|
-
* Returns `value` unchanged, or `0` if below the dead zone `threshold`.
|
|
74
|
-
*
|
|
75
|
-
* @param value - Raw axis or trigger value, typically in `[-1, 1]`.
|
|
76
|
-
* @param threshold - Dead zone size; values below this magnitude are zeroed.
|
|
77
|
-
*/
|
|
78
|
-
#applyDeadzone(value, threshold) {
|
|
79
|
-
return Math.abs(value) < threshold ? 0 : value;
|
|
80
|
-
}
|
|
81
73
|
};
|
|
82
74
|
//#endregion
|
|
83
75
|
export { GamepadFlyControls };
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { GAMEPAD_AXIS, GAMEPAD_BUTTON } from "./core.js";
|
|
2
|
+
import { applyGamepadDeadzone, getGamepadButtonValue } from "./utils.js";
|
|
2
3
|
import { GamepadControls } from "./gamepad-controls.js";
|
|
3
4
|
//#region src/gamepad-orbit-controls.ts
|
|
4
5
|
/**
|
|
@@ -46,27 +47,18 @@ var GamepadOrbitControls = class extends GamepadControls {
|
|
|
46
47
|
*/
|
|
47
48
|
onUpdate(deltaTime, gamepad) {
|
|
48
49
|
const { rotateSpeed, panSpeed, zoomSpeed, deadzone, axisRotateX, axisRotateY, axisPanX, axisPanY, buttonDollyIn, buttonDollyOut } = this.#options;
|
|
49
|
-
const rotX =
|
|
50
|
-
const rotY =
|
|
50
|
+
const rotX = applyGamepadDeadzone(gamepad.axes[axisRotateX] ?? 0, deadzone);
|
|
51
|
+
const rotY = applyGamepadDeadzone(gamepad.axes[axisRotateY] ?? 0, deadzone);
|
|
51
52
|
if (rotX !== 0) this.#controls.rotateLeft(rotX * rotateSpeed * deltaTime * Math.PI);
|
|
52
53
|
if (rotY !== 0) this.#controls.rotateUp(rotY * rotateSpeed * deltaTime * Math.PI);
|
|
53
|
-
const panX =
|
|
54
|
-
const panY =
|
|
54
|
+
const panX = applyGamepadDeadzone(gamepad.axes[axisPanX] ?? 0, deadzone);
|
|
55
|
+
const panY = applyGamepadDeadzone(gamepad.axes[axisPanY] ?? 0, deadzone);
|
|
55
56
|
if (panX !== 0 || panY !== 0) this.#controls.pan(panX * panSpeed * deltaTime * 500, panY * panSpeed * deltaTime * 500);
|
|
56
|
-
const triggerIn = gamepad
|
|
57
|
-
const triggerOut = gamepad
|
|
57
|
+
const triggerIn = getGamepadButtonValue(gamepad, buttonDollyIn);
|
|
58
|
+
const triggerOut = getGamepadButtonValue(gamepad, buttonDollyOut);
|
|
58
59
|
if (triggerIn > deadzone) this.#controls.dollyIn(1 / (1 + zoomSpeed * triggerIn * deltaTime));
|
|
59
60
|
if (triggerOut > deadzone) this.#controls.dollyOut(1 / (1 + zoomSpeed * triggerOut * deltaTime));
|
|
60
61
|
}
|
|
61
|
-
/**
|
|
62
|
-
* Returns `value` unchanged, or `0` if below the dead zone `threshold`.
|
|
63
|
-
*
|
|
64
|
-
* @param value - Raw axis or trigger value, typically in `[-1, 1]`.
|
|
65
|
-
* @param threshold - Dead zone size; values below this magnitude are zeroed.
|
|
66
|
-
*/
|
|
67
|
-
#applyDeadzone(value, threshold) {
|
|
68
|
-
return Math.abs(value) < threshold ? 0 : value;
|
|
69
|
-
}
|
|
70
62
|
};
|
|
71
63
|
//#endregion
|
|
72
64
|
export { GamepadOrbitControls };
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { GAMEPAD_AXIS } from "./core.js";
|
|
2
|
+
import { applyGamepadDeadzone } from "./utils.js";
|
|
2
3
|
import { GamepadControls } from "./gamepad-controls.js";
|
|
3
4
|
import { Euler } from "three";
|
|
4
5
|
//#region src/gamepad-pointer-lock-controls.ts
|
|
@@ -47,12 +48,12 @@ var GamepadPointerLockControls = class extends GamepadControls {
|
|
|
47
48
|
*/
|
|
48
49
|
onUpdate(deltaTime, gamepad) {
|
|
49
50
|
const { moveSpeed, lookSpeed, deadzone, axisMoveForward, axisMoveRight, axisLookX, axisLookY } = this.#options;
|
|
50
|
-
const fwd =
|
|
51
|
-
const strafe =
|
|
51
|
+
const fwd = applyGamepadDeadzone(gamepad.axes[axisMoveForward] ?? 0, deadzone);
|
|
52
|
+
const strafe = applyGamepadDeadzone(gamepad.axes[axisMoveRight] ?? 0, deadzone);
|
|
52
53
|
if (fwd !== 0) this.#controls.moveForward(-fwd * moveSpeed * deltaTime);
|
|
53
54
|
if (strafe !== 0) this.#controls.moveRight(strafe * moveSpeed * deltaTime);
|
|
54
|
-
const lookX =
|
|
55
|
-
const lookY =
|
|
55
|
+
const lookX = applyGamepadDeadzone(gamepad.axes[axisLookX] ?? 0, deadzone);
|
|
56
|
+
const lookY = applyGamepadDeadzone(gamepad.axes[axisLookY] ?? 0, deadzone);
|
|
56
57
|
if (lookX !== 0 || lookY !== 0) {
|
|
57
58
|
const camera = this.#controls.object;
|
|
58
59
|
const scale = lookSpeed * this.#controls.pointerSpeed * deltaTime * Math.PI;
|
|
@@ -63,15 +64,6 @@ var GamepadPointerLockControls = class extends GamepadControls {
|
|
|
63
64
|
camera.quaternion.setFromEuler(this.#euler);
|
|
64
65
|
}
|
|
65
66
|
}
|
|
66
|
-
/**
|
|
67
|
-
* Returns `value` unchanged, or `0` if below the dead zone `threshold`.
|
|
68
|
-
*
|
|
69
|
-
* @param value - Raw axis value, typically in `[-1, 1]`.
|
|
70
|
-
* @param threshold - Dead zone size; values below this magnitude are zeroed.
|
|
71
|
-
*/
|
|
72
|
-
#applyDeadzone(value, threshold) {
|
|
73
|
-
return Math.abs(value) < threshold ? 0 : value;
|
|
74
|
-
}
|
|
75
67
|
};
|
|
76
68
|
//#endregion
|
|
77
69
|
export { GamepadPointerLockControls };
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { GAMEPAD_AXIS, GAMEPAD_BUTTON } from "./core.js";
|
|
2
|
+
import { applyGamepadDeadzone, getGamepadButtonValue } from "./utils.js";
|
|
2
3
|
import { GamepadControls } from "./gamepad-controls.js";
|
|
3
4
|
//#region src/gamepad-trackball-controls.ts
|
|
4
5
|
/**
|
|
@@ -57,8 +58,8 @@ var GamepadTrackballControls = class extends GamepadControls {
|
|
|
57
58
|
controls._lastAngle = 0;
|
|
58
59
|
return;
|
|
59
60
|
}
|
|
60
|
-
const rotX =
|
|
61
|
-
const rotY =
|
|
61
|
+
const rotX = applyGamepadDeadzone(gamepad.axes[axisRotateX] ?? 0, deadzone);
|
|
62
|
+
const rotY = applyGamepadDeadzone(gamepad.axes[axisRotateY] ?? 0, deadzone);
|
|
62
63
|
if (rotX === 0 && rotY === 0) return;
|
|
63
64
|
const scale = rotateSpeed * deltaTime * Math.PI;
|
|
64
65
|
controls._moveCurr.x += rotX * scale;
|
|
@@ -70,10 +71,10 @@ var GamepadTrackballControls = class extends GamepadControls {
|
|
|
70
71
|
controls._panStart.copy(controls._panEnd);
|
|
71
72
|
return;
|
|
72
73
|
}
|
|
73
|
-
const panX =
|
|
74
|
-
const panY =
|
|
74
|
+
const panX = applyGamepadDeadzone(gamepad.axes[axisPanX] ?? 0, deadzone);
|
|
75
|
+
const panY = applyGamepadDeadzone(gamepad.axes[axisPanY] ?? 0, deadzone);
|
|
75
76
|
if (panX === 0 && panY === 0) return;
|
|
76
|
-
const scale = panSpeed * deltaTime;
|
|
77
|
+
const scale = panSpeed * deltaTime * this.#getInputDampingFactor();
|
|
77
78
|
controls._panEnd.x += panX * scale;
|
|
78
79
|
controls._panEnd.y += panY * scale;
|
|
79
80
|
}
|
|
@@ -83,19 +84,18 @@ var GamepadTrackballControls = class extends GamepadControls {
|
|
|
83
84
|
controls._zoomStart.copy(controls._zoomEnd);
|
|
84
85
|
return;
|
|
85
86
|
}
|
|
86
|
-
const triggerIn = gamepad
|
|
87
|
-
const triggerOut = gamepad
|
|
87
|
+
const triggerIn = getGamepadButtonValue(gamepad, buttonZoomIn);
|
|
88
|
+
const triggerOut = getGamepadButtonValue(gamepad, buttonZoomOut);
|
|
88
89
|
if (triggerIn <= deadzone && triggerOut <= deadzone) return;
|
|
89
|
-
controls._zoomEnd.y += (triggerOut - triggerIn) * zoomSpeed * deltaTime;
|
|
90
|
+
controls._zoomEnd.y += (triggerOut - triggerIn) * zoomSpeed * deltaTime * this.#getInputDampingFactor();
|
|
90
91
|
}
|
|
91
92
|
/**
|
|
92
|
-
*
|
|
93
|
-
*
|
|
94
|
-
* @param value - Raw axis or trigger value, typically in `[-1, 1]`.
|
|
95
|
-
* @param threshold - Dead zone size; values below this magnitude are zeroed.
|
|
93
|
+
* Compensates for TrackballControls reapplying queued pan and zoom deltas
|
|
94
|
+
* while their input state catches up through damping.
|
|
96
95
|
*/
|
|
97
|
-
#
|
|
98
|
-
|
|
96
|
+
#getInputDampingFactor() {
|
|
97
|
+
const controls = this.#controls;
|
|
98
|
+
return controls.staticMoving ? 1 : controls.dynamicDampingFactor;
|
|
99
99
|
}
|
|
100
100
|
};
|
|
101
101
|
//#endregion
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { GAMEPAD_AXIS, GAMEPAD_BUTTON } from "./core.js";
|
|
2
|
+
import { applyGamepadDeadzone, getGamepadButtonPressed } from "./utils.js";
|
|
2
3
|
import { GamepadControls } from "./gamepad-controls.js";
|
|
3
4
|
import { Matrix4, Quaternion, Vector2, Vector3 } from "three";
|
|
4
5
|
//#region src/gamepad-transform-controls.ts
|
|
@@ -172,8 +173,8 @@ var GamepadTransformControls = class extends GamepadControls {
|
|
|
172
173
|
this.#endTransform(true);
|
|
173
174
|
return;
|
|
174
175
|
}
|
|
175
|
-
const transformX =
|
|
176
|
-
const transformY =
|
|
176
|
+
const transformX = applyGamepadDeadzone(gamepad.axes[this.#options.axisTransformX] ?? 0, this.#options.deadzone);
|
|
177
|
+
const transformY = applyGamepadDeadzone(gamepad.axes[this.#options.axisTransformY] ?? 0, this.#options.deadzone);
|
|
177
178
|
if (transformX === 0 && transformY === 0) {
|
|
178
179
|
this.#endTransform(false);
|
|
179
180
|
return;
|
|
@@ -605,7 +606,7 @@ var GamepadTransformControls = class extends GamepadControls {
|
|
|
605
606
|
#getStartedButtons(gamepad) {
|
|
606
607
|
const startedButtons = /* @__PURE__ */ new Set();
|
|
607
608
|
for (let index = 0; index < gamepad.buttons.length; index += 1) {
|
|
608
|
-
const pressed = gamepad
|
|
609
|
+
const pressed = getGamepadButtonPressed(gamepad, index);
|
|
609
610
|
const wasPressed = this.#pressedButtons.has(index);
|
|
610
611
|
if (pressed) {
|
|
611
612
|
this.#pressedButtons.add(index);
|
|
@@ -620,15 +621,6 @@ var GamepadTransformControls = class extends GamepadControls {
|
|
|
620
621
|
#isOrthographicCamera(camera) {
|
|
621
622
|
return camera.isOrthographicCamera === true;
|
|
622
623
|
}
|
|
623
|
-
/**
|
|
624
|
-
* Returns `value` unchanged, or `0` if below the dead zone `threshold`.
|
|
625
|
-
*
|
|
626
|
-
* @param value - Raw axis value, typically in `[-1, 1]`.
|
|
627
|
-
* @param threshold - Dead zone size; values below this magnitude are zeroed.
|
|
628
|
-
*/
|
|
629
|
-
#applyDeadzone(value, threshold) {
|
|
630
|
-
return Math.abs(value) < threshold ? 0 : value;
|
|
631
|
-
}
|
|
632
624
|
};
|
|
633
625
|
//#endregion
|
|
634
626
|
export { GamepadTransformControls };
|
package/dist/utils.js
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
//#region src/utils.ts
|
|
2
|
+
/**
|
|
3
|
+
* Returns `value` unchanged, or `0` if below the dead zone `threshold`.
|
|
4
|
+
*
|
|
5
|
+
* @param value - Raw axis or trigger value, typically in `[-1, 1]`.
|
|
6
|
+
* @param threshold - Dead zone size; values below this magnitude are zeroed.
|
|
7
|
+
* @returns The original value when outside the dead zone, otherwise `0`.
|
|
8
|
+
*/
|
|
9
|
+
const applyGamepadDeadzone = (value, threshold) => {
|
|
10
|
+
return Math.abs(value) < threshold ? 0 : value;
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* Returns whether a gamepad button is currently pressed.
|
|
14
|
+
*
|
|
15
|
+
* Missing buttons are treated as not pressed.
|
|
16
|
+
*
|
|
17
|
+
* @param gamepad - Gamepad snapshot to read from.
|
|
18
|
+
* @param button - Button index to inspect.
|
|
19
|
+
* @returns `true` when the button exists and is pressed, otherwise `false`.
|
|
20
|
+
*/
|
|
21
|
+
const getGamepadButtonPressed = (gamepad, button) => {
|
|
22
|
+
return gamepad.buttons[button]?.pressed ?? false;
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Returns the analog value for a gamepad button.
|
|
26
|
+
*
|
|
27
|
+
* Some digital buttons may report `pressed` without a meaningful non-zero
|
|
28
|
+
* `value`, so pressed buttons fall back to `1`.
|
|
29
|
+
*
|
|
30
|
+
* @param gamepad - Gamepad snapshot to read from.
|
|
31
|
+
* @param button - Button index to inspect.
|
|
32
|
+
* @returns The button value, `1` for pressed digital buttons, or `0` when unavailable.
|
|
33
|
+
*/
|
|
34
|
+
const getGamepadButtonValue = (gamepad, button) => {
|
|
35
|
+
const gamepadButton = gamepad.buttons[button];
|
|
36
|
+
if (gamepadButton === void 0) return 0;
|
|
37
|
+
if (gamepadButton.value !== 0) return gamepadButton.value;
|
|
38
|
+
return gamepadButton.pressed ? 1 : 0;
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* Returns a fresh connected gamepad snapshot by index.
|
|
42
|
+
*
|
|
43
|
+
* @param index - Gamepad index to look up.
|
|
44
|
+
* @returns The connected gamepad snapshot at the index, or `null` when unavailable.
|
|
45
|
+
*/
|
|
46
|
+
const getGamepadByIndex = (index) => {
|
|
47
|
+
const gamepad = navigator.getGamepads()[index] ?? null;
|
|
48
|
+
return gamepad?.connected === true ? gamepad : null;
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* Returns the first currently connected gamepad snapshot.
|
|
52
|
+
*
|
|
53
|
+
* @returns The first connected gamepad snapshot, or `null` when none are connected.
|
|
54
|
+
*/
|
|
55
|
+
const getFirstConnectedGamepad = () => {
|
|
56
|
+
for (const gamepad of navigator.getGamepads()) if (gamepad?.connected === true) return gamepad;
|
|
57
|
+
return null;
|
|
58
|
+
};
|
|
59
|
+
//#endregion
|
|
60
|
+
export { applyGamepadDeadzone, getFirstConnectedGamepad, getGamepadButtonPressed, getGamepadButtonValue, getGamepadByIndex };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "three-gamepad-controls",
|
|
3
3
|
"description": "Gamepad support for Three.js controls.",
|
|
4
|
-
"version": "0.10.
|
|
4
|
+
"version": "0.10.5",
|
|
5
5
|
"homepage": "https://github.com/luckasnix/three-gamepad-controls#readme",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "Kasnix",
|
|
@@ -46,11 +46,11 @@
|
|
|
46
46
|
}
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
|
-
"@biomejs/biome": "2.
|
|
49
|
+
"@biomejs/biome": "2.5.0",
|
|
50
50
|
"@commitlint/cli": "21.0.2",
|
|
51
51
|
"@commitlint/config-conventional": "21.0.2",
|
|
52
52
|
"@commitlint/types": "21.0.1",
|
|
53
|
-
"@types/node": "24.
|
|
53
|
+
"@types/node": "24.13.2",
|
|
54
54
|
"@types/three": "0.184.1",
|
|
55
55
|
"husky": "9.1.7",
|
|
56
56
|
"three": "0.184.0",
|