three-gamepad-controls 0.24.0 โ 0.24.1
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 +33 -5
- package/dist/core.d.ts +9 -10
- package/dist/gamepad-arcball-controls.d.ts +5 -4
- package/dist/gamepad-arcball-controls.js +28 -13
- package/dist/gamepad-controls.d.ts +18 -11
- package/dist/gamepad-controls.js +13 -6
- package/dist/gamepad-drag-controls.d.ts +4 -6
- package/dist/gamepad-drag-controls.js +24 -15
- package/dist/gamepad-first-person-controls.d.ts +3 -4
- package/dist/gamepad-first-person-controls.js +1 -0
- package/dist/gamepad-fly-controls.d.ts +3 -4
- package/dist/gamepad-fly-controls.js +1 -0
- package/dist/gamepad-input.d.ts +26 -14
- package/dist/gamepad-input.js +15 -6
- package/dist/gamepad-manager.js +4 -2
- package/dist/gamepad-map-controls.d.ts +2 -3
- package/dist/gamepad-orbit-controls.d.ts +3 -4
- package/dist/gamepad-orbit-controls.js +22 -5
- package/dist/gamepad-pointer-lock-controls.d.ts +3 -4
- package/dist/gamepad-pointer-lock-controls.js +1 -0
- package/dist/gamepad-stick-processing.d.ts +16 -17
- package/dist/gamepad-trackball-controls.d.ts +3 -4
- package/dist/gamepad-trackball-controls.js +4 -13
- package/dist/gamepad-transform-controls.d.ts +4 -5
- package/dist/gamepad-transform-controls.js +52 -28
- package/package.json +10 -9
package/README.md
CHANGED
|
@@ -25,8 +25,8 @@ npm i -D @types/three # optional: for TypeScript projects
|
|
|
25
25
|
pnpm:
|
|
26
26
|
|
|
27
27
|
```bash
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
pn add three three-gamepad-controls
|
|
29
|
+
pn add -D @types/three # optional: for TypeScript projects
|
|
30
30
|
```
|
|
31
31
|
|
|
32
32
|
Yarn:
|
|
@@ -58,13 +58,41 @@ bun add three three-gamepad-controls
|
|
|
58
58
|
bun add -d @types/three # optional: for TypeScript projects
|
|
59
59
|
```
|
|
60
60
|
|
|
61
|
+
## ๐งช Testing
|
|
62
|
+
|
|
63
|
+
Tests use Vitest with Browser Mode and Playwright for browser-dependent behavior in Chromium. Browser-independent tests run directly in Node.js.
|
|
64
|
+
|
|
65
|
+
After installing the project dependencies, install Chromium once:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
pn exec playwright install chromium
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Run the test suite once:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
pn test
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Start Vitest in watch mode while developing:
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
pn test:watch
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Generate the coverage report:
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
pn test:coverage
|
|
87
|
+
```
|
|
88
|
+
|
|
61
89
|
## ๐ Compatibility
|
|
62
90
|
|
|
63
91
|
| Three.js | Three.js Gamepad Controls |
|
|
64
92
|
| --- | --- |
|
|
65
|
-
|
|
|
66
|
-
|
|
|
67
|
-
|
|
|
93
|
+
| `0.184.x` | `<=0.22.x` |
|
|
94
|
+
| `0.185.x` | `0.23.x` |
|
|
95
|
+
| `0.186.x` | `0.24.x` |
|
|
68
96
|
|
|
69
97
|
## ๐ Documentation
|
|
70
98
|
|
package/dist/core.d.ts
CHANGED
|
@@ -4,19 +4,19 @@
|
|
|
4
4
|
*
|
|
5
5
|
* Gamepad slots cannot be negative.
|
|
6
6
|
*/
|
|
7
|
-
declare const MIN_GAMEPAD_INDEX = 0;
|
|
7
|
+
export declare const MIN_GAMEPAD_INDEX = 0;
|
|
8
8
|
/**
|
|
9
9
|
* Largest valid browser-assigned gamepad index.
|
|
10
10
|
*
|
|
11
11
|
* `Gamepad.index` is a Web IDL `long`, a signed 32-bit integer. Because
|
|
12
12
|
* gamepad slots cannot be negative, the largest valid index is 2^31 - 1.
|
|
13
13
|
*/
|
|
14
|
-
declare const MAX_GAMEPAD_INDEX = 2147483647;
|
|
14
|
+
export declare const MAX_GAMEPAD_INDEX = 2147483647;
|
|
15
15
|
/**
|
|
16
16
|
* Button indices for the W3C Standard Gamepad mapping.
|
|
17
17
|
* @see https://www.w3.org/TR/gamepad/#dfn-standard-gamepad
|
|
18
18
|
*/
|
|
19
|
-
declare const GAMEPAD_BUTTON: {
|
|
19
|
+
export declare const GAMEPAD_BUTTON: {
|
|
20
20
|
readonly South: 0;
|
|
21
21
|
readonly East: 1;
|
|
22
22
|
readonly West: 2;
|
|
@@ -39,7 +39,7 @@ declare const GAMEPAD_BUTTON: {
|
|
|
39
39
|
* Axis indices for the W3C Standard Gamepad mapping.
|
|
40
40
|
* @see https://www.w3.org/TR/gamepad/#dfn-standard-gamepad
|
|
41
41
|
*/
|
|
42
|
-
declare const GAMEPAD_AXIS: {
|
|
42
|
+
export declare const GAMEPAD_AXIS: {
|
|
43
43
|
readonly LeftX: 0;
|
|
44
44
|
readonly LeftY: 1;
|
|
45
45
|
readonly RightX: 2;
|
|
@@ -48,18 +48,17 @@ declare const GAMEPAD_AXIS: {
|
|
|
48
48
|
/**
|
|
49
49
|
* Union type of all valid {@link GAMEPAD_BUTTON} keys.
|
|
50
50
|
*/
|
|
51
|
-
type GamepadButtonKey = keyof typeof GAMEPAD_BUTTON;
|
|
51
|
+
export type GamepadButtonKey = keyof typeof GAMEPAD_BUTTON;
|
|
52
52
|
/**
|
|
53
53
|
* Union type of all valid {@link GAMEPAD_BUTTON} values.
|
|
54
54
|
*/
|
|
55
|
-
type GamepadButtonValue = (typeof GAMEPAD_BUTTON)[keyof typeof GAMEPAD_BUTTON];
|
|
55
|
+
export type GamepadButtonValue = (typeof GAMEPAD_BUTTON)[keyof typeof GAMEPAD_BUTTON];
|
|
56
56
|
/**
|
|
57
57
|
* Union type of all valid {@link GAMEPAD_AXIS} keys.
|
|
58
58
|
*/
|
|
59
|
-
type GamepadAxisKey = keyof typeof GAMEPAD_AXIS;
|
|
59
|
+
export type GamepadAxisKey = keyof typeof GAMEPAD_AXIS;
|
|
60
60
|
/**
|
|
61
61
|
* Union type of all valid {@link GAMEPAD_AXIS} values.
|
|
62
62
|
*/
|
|
63
|
-
type GamepadAxisValue = (typeof GAMEPAD_AXIS)[keyof typeof GAMEPAD_AXIS];
|
|
64
|
-
//#endregion
|
|
65
|
-
export { GAMEPAD_AXIS, GAMEPAD_BUTTON, GamepadAxisKey, GamepadAxisValue, GamepadButtonKey, GamepadButtonValue, MAX_GAMEPAD_INDEX, MIN_GAMEPAD_INDEX };
|
|
63
|
+
export type GamepadAxisValue = (typeof GAMEPAD_AXIS)[keyof typeof GAMEPAD_AXIS];
|
|
64
|
+
//#endregion
|
|
@@ -7,7 +7,7 @@ import { ArcballControls } from "three/addons/controls/ArcballControls.js";
|
|
|
7
7
|
*
|
|
8
8
|
* Every property has a sensible default, so you only need to pass the properties you want to override.
|
|
9
9
|
*/
|
|
10
|
-
type GamepadArcballControlsOptions = GamepadControlsOptions & {
|
|
10
|
+
export type GamepadArcballControlsOptions = GamepadControlsOptions & {
|
|
11
11
|
/**
|
|
12
12
|
* Multiplier on `ArcballControls.rotateSpeed` for rotation.
|
|
13
13
|
* @default 1.0
|
|
@@ -76,7 +76,7 @@ type GamepadArcballControlsOptions = GamepadControlsOptions & {
|
|
|
76
76
|
* Arcball transformations. The wrapped `ArcballControls.update()` is only
|
|
77
77
|
* needed after manual camera or target changes, matching Arcball's native API.
|
|
78
78
|
*/
|
|
79
|
-
declare class GamepadArcballControls extends GamepadControls {
|
|
79
|
+
export declare class GamepadArcballControls extends GamepadControls {
|
|
80
80
|
#private;
|
|
81
81
|
/**
|
|
82
82
|
* @param controls - A Three.js `ArcballControls` instance.
|
|
@@ -91,6 +91,7 @@ declare class GamepadArcballControls extends GamepadControls {
|
|
|
91
91
|
* @param deltaTime - Seconds since the last frame.
|
|
92
92
|
*/
|
|
93
93
|
protected onUpdate(deltaTime: number): void;
|
|
94
|
+
dispose(): void;
|
|
95
|
+
protected onGamepadDisconnected(gamepad: Gamepad): void;
|
|
94
96
|
}
|
|
95
|
-
//#endregion
|
|
96
|
-
export { GamepadArcballControls, GamepadArcballControlsOptions };
|
|
97
|
+
//#endregion
|
|
@@ -77,10 +77,7 @@ var GamepadArcballControls = class extends GamepadControls {
|
|
|
77
77
|
const { rotateSpeed, panSpeed, zoomSpeed, zRotateSpeed, rotateStick, panStick, buttonDeadzone, buttonZoomIn, buttonZoomOut, buttonZRotateLeft, buttonZRotateRight, buttonFocus } = this.#options;
|
|
78
78
|
const input = this.gamepadInput;
|
|
79
79
|
const focusPoint = this.#consumeFocusPoint(buttonFocus);
|
|
80
|
-
if (!
|
|
81
|
-
this.#endInteraction();
|
|
82
|
-
return;
|
|
83
|
-
}
|
|
80
|
+
if (!this.#canApplyInput()) return;
|
|
84
81
|
let rotateX = 0;
|
|
85
82
|
let rotateY = 0;
|
|
86
83
|
if (controls.enableRotate) {
|
|
@@ -102,20 +99,38 @@ var GamepadArcballControls = class extends GamepadControls {
|
|
|
102
99
|
this.#endInteraction();
|
|
103
100
|
return;
|
|
104
101
|
}
|
|
105
|
-
if (!this.#wasInteracting)
|
|
102
|
+
if (!this.#wasInteracting) {
|
|
103
|
+
this.#wasInteracting = true;
|
|
104
|
+
controls.dispatchEvent({ type: "start" });
|
|
105
|
+
}
|
|
106
|
+
if (!this.#canApplyInput()) return;
|
|
106
107
|
let changed = false;
|
|
107
|
-
changed = this.#applyRotation(deltaTime, rotateX, rotateY, rotateSpeed) || changed;
|
|
108
|
-
changed = this.#applyPan(deltaTime, panX, panY, panSpeed) || changed;
|
|
109
|
-
changed = this.#applyZoom(deltaTime, zoom, zoomSpeed, buttonDeadzone) || changed;
|
|
110
|
-
changed = this.#applyZRotation(deltaTime, zRotation, zRotateSpeed, buttonDeadzone) || changed;
|
|
111
|
-
changed = this.#applyFocus(focusPoint) || changed;
|
|
108
|
+
if (controls.enableRotate) changed = this.#applyRotation(deltaTime, rotateX, rotateY, rotateSpeed) || changed;
|
|
109
|
+
if (controls.enablePan) changed = this.#applyPan(deltaTime, panX, panY, panSpeed) || changed;
|
|
110
|
+
if (controls.enableZoom) changed = this.#applyZoom(deltaTime, zoom, zoomSpeed, buttonDeadzone) || changed;
|
|
111
|
+
if (controls.enableRotate) changed = this.#applyZRotation(deltaTime, zRotation, zRotateSpeed, buttonDeadzone) || changed;
|
|
112
|
+
if (controls.enablePan && controls.enableFocus) changed = this.#applyFocus(focusPoint) || changed;
|
|
112
113
|
if (changed) {
|
|
113
114
|
controls.update();
|
|
114
115
|
controls.updateMatrixState();
|
|
115
116
|
controls.dispatchEvent({ type: "change" });
|
|
116
117
|
}
|
|
117
|
-
this.#
|
|
118
|
-
|
|
118
|
+
if (!activeInput || !controls.enabled) this.#endInteraction();
|
|
119
|
+
}
|
|
120
|
+
dispose() {
|
|
121
|
+
super.dispose();
|
|
122
|
+
this.#endInteraction();
|
|
123
|
+
}
|
|
124
|
+
onGamepadDisconnected(gamepad) {
|
|
125
|
+
this.#endInteraction();
|
|
126
|
+
super.onGamepadDisconnected(gamepad);
|
|
127
|
+
}
|
|
128
|
+
#canApplyInput() {
|
|
129
|
+
if (!this.#controls.enabled) {
|
|
130
|
+
this.#endInteraction();
|
|
131
|
+
return false;
|
|
132
|
+
}
|
|
133
|
+
return this.enabled && this.gamepad !== null;
|
|
119
134
|
}
|
|
120
135
|
/**
|
|
121
136
|
* Applies gamepad stick rotation through Arcball's runtime rotation helper.
|
|
@@ -253,8 +268,8 @@ var GamepadArcballControls = class extends GamepadControls {
|
|
|
253
268
|
}
|
|
254
269
|
#endInteraction() {
|
|
255
270
|
if (!this.#wasInteracting) return;
|
|
256
|
-
this.#controls.dispatchEvent({ type: "end" });
|
|
257
271
|
this.#wasInteracting = false;
|
|
272
|
+
this.#controls.dispatchEvent({ type: "end" });
|
|
258
273
|
}
|
|
259
274
|
};
|
|
260
275
|
//#endregion
|
|
@@ -7,7 +7,7 @@ import { EventDispatcher } from "three";
|
|
|
7
7
|
* Each key is an event name, and its value is the extra data included in the event object
|
|
8
8
|
* alongside the standard `type` and `target` fields.
|
|
9
9
|
*/
|
|
10
|
-
type GamepadControlsEventMap = {
|
|
10
|
+
export type GamepadControlsEventMap = {
|
|
11
11
|
/**
|
|
12
12
|
* Fired when a gamepad is connected and set as the active gamepad.
|
|
13
13
|
*/
|
|
@@ -18,7 +18,8 @@ type GamepadControlsEventMap = {
|
|
|
18
18
|
gamepad: Gamepad;
|
|
19
19
|
};
|
|
20
20
|
/**
|
|
21
|
-
* Fired
|
|
21
|
+
* Fired on a matching browser disconnection event or when polling observes
|
|
22
|
+
* the active slot missing or disconnected, not on snapshot identity changes.
|
|
22
23
|
*/
|
|
23
24
|
disconnected: {
|
|
24
25
|
/**
|
|
@@ -30,22 +31,25 @@ type GamepadControlsEventMap = {
|
|
|
30
31
|
/**
|
|
31
32
|
* Shared configuration for Three.js gamepad control wrappers.
|
|
32
33
|
*/
|
|
33
|
-
type GamepadControlsOptions = Pick<GamepadInputOptions, "gamepadIndex">;
|
|
34
|
+
export type GamepadControlsOptions = Pick<GamepadInputOptions, "gamepadIndex">;
|
|
34
35
|
/**
|
|
35
36
|
* Abstract base class for Three.js gamepad controls.
|
|
36
37
|
*
|
|
37
38
|
* Delegates gamepad connection lifecycle and input polling to {@link GamepadInput}
|
|
38
39
|
* so subclasses can focus on mapping input to the wrapped Three.js control.
|
|
39
40
|
*/
|
|
40
|
-
declare abstract class GamepadControls extends EventDispatcher<GamepadControlsEventMap> {
|
|
41
|
+
export declare abstract class GamepadControls extends EventDispatcher<GamepadControlsEventMap> {
|
|
41
42
|
#private;
|
|
42
43
|
/**
|
|
43
|
-
* When `false`,
|
|
44
|
+
* When `false`, `update()` pauses polling and subclass input application,
|
|
45
|
+
* retaining state. Browser connection/disconnection listeners remain active.
|
|
46
|
+
* Assignment alone does not cancel an interaction or dispose the wrapper.
|
|
44
47
|
* @default true
|
|
45
48
|
*/
|
|
46
49
|
enabled: boolean;
|
|
47
50
|
/**
|
|
48
|
-
* The
|
|
51
|
+
* The active gamepad snapshot, or `null` if none has been adopted.
|
|
52
|
+
* Automatic selection keeps its adopted slot until an observed loss.
|
|
49
53
|
*/
|
|
50
54
|
gamepad: Gamepad | null;
|
|
51
55
|
/**
|
|
@@ -72,6 +76,8 @@ declare abstract class GamepadControls extends EventDispatcher<GamepadControlsEv
|
|
|
72
76
|
get vibrationSupported(): boolean;
|
|
73
77
|
/**
|
|
74
78
|
* Advances the controller by one frame. Call this inside your render loop.
|
|
79
|
+
* While paused, polling-only losses remain unobserved until updates resume.
|
|
80
|
+
* Resume compares button state with the last observation, without replay.
|
|
75
81
|
*
|
|
76
82
|
* @param deltaTime - Seconds since the last frame.
|
|
77
83
|
*/
|
|
@@ -98,7 +104,9 @@ declare abstract class GamepadControls extends EventDispatcher<GamepadControlsEv
|
|
|
98
104
|
*/
|
|
99
105
|
resetVibration(): Promise<GamepadHapticsResult | null>;
|
|
100
106
|
/**
|
|
101
|
-
* Removes
|
|
107
|
+
* Removes this wrapper's internal input listeners, clears state, and disables
|
|
108
|
+
* it without dispatching a synthetic disconnection. Does not dispose the
|
|
109
|
+
* wrapped Three.js control or affect other wrappers. Reuse is unsupported.
|
|
102
110
|
*/
|
|
103
111
|
dispose(): void;
|
|
104
112
|
/**
|
|
@@ -116,8 +124,8 @@ declare abstract class GamepadControls extends EventDispatcher<GamepadControlsEv
|
|
|
116
124
|
*/
|
|
117
125
|
protected onGamepadConnected(gamepad: Gamepad): void;
|
|
118
126
|
/**
|
|
119
|
-
* Called when the
|
|
120
|
-
*
|
|
127
|
+
* Called when the shared input reader observes a matching disconnection
|
|
128
|
+
* event or a missing/disconnected active slot, including events during pause.
|
|
121
129
|
*
|
|
122
130
|
* The default dispatches a `disconnected` event.
|
|
123
131
|
*
|
|
@@ -125,5 +133,4 @@ declare abstract class GamepadControls extends EventDispatcher<GamepadControlsEv
|
|
|
125
133
|
*/
|
|
126
134
|
protected onGamepadDisconnected(gamepad: Gamepad): void;
|
|
127
135
|
}
|
|
128
|
-
//#endregion
|
|
129
|
-
export { GamepadControls, GamepadControlsEventMap, GamepadControlsOptions };
|
|
136
|
+
//#endregion
|
package/dist/gamepad-controls.js
CHANGED
|
@@ -9,12 +9,15 @@ import { EventDispatcher } from "three";
|
|
|
9
9
|
*/
|
|
10
10
|
var GamepadControls = class extends EventDispatcher {
|
|
11
11
|
/**
|
|
12
|
-
* When `false`,
|
|
12
|
+
* When `false`, `update()` pauses polling and subclass input application,
|
|
13
|
+
* retaining state. Browser connection/disconnection listeners remain active.
|
|
14
|
+
* Assignment alone does not cancel an interaction or dispose the wrapper.
|
|
13
15
|
* @default true
|
|
14
16
|
*/
|
|
15
17
|
enabled = true;
|
|
16
18
|
/**
|
|
17
|
-
* The
|
|
19
|
+
* The active gamepad snapshot, or `null` if none has been adopted.
|
|
20
|
+
* Automatic selection keeps its adopted slot until an observed loss.
|
|
18
21
|
*/
|
|
19
22
|
gamepad = null;
|
|
20
23
|
#gamepadInput;
|
|
@@ -73,6 +76,8 @@ var GamepadControls = class extends EventDispatcher {
|
|
|
73
76
|
}
|
|
74
77
|
/**
|
|
75
78
|
* Advances the controller by one frame. Call this inside your render loop.
|
|
79
|
+
* While paused, polling-only losses remain unobserved until updates resume.
|
|
80
|
+
* Resume compares button state with the last observation, without replay.
|
|
76
81
|
*
|
|
77
82
|
* @param deltaTime - Seconds since the last frame.
|
|
78
83
|
*/
|
|
@@ -80,7 +85,7 @@ var GamepadControls = class extends EventDispatcher {
|
|
|
80
85
|
if (!this.enabled) return;
|
|
81
86
|
this.#gamepadInput.update();
|
|
82
87
|
this.gamepad = this.#gamepadInput.gamepad;
|
|
83
|
-
if (this.gamepad === null) return;
|
|
88
|
+
if (!this.enabled || this.gamepad === null) return;
|
|
84
89
|
this.onUpdate(deltaTime);
|
|
85
90
|
}
|
|
86
91
|
/**
|
|
@@ -109,7 +114,9 @@ var GamepadControls = class extends EventDispatcher {
|
|
|
109
114
|
return this.#gamepadInput.resetVibration();
|
|
110
115
|
}
|
|
111
116
|
/**
|
|
112
|
-
* Removes
|
|
117
|
+
* Removes this wrapper's internal input listeners, clears state, and disables
|
|
118
|
+
* it without dispatching a synthetic disconnection. Does not dispose the
|
|
119
|
+
* wrapped Three.js control or affect other wrappers. Reuse is unsupported.
|
|
113
120
|
*/
|
|
114
121
|
dispose() {
|
|
115
122
|
this.#gamepadInput.removeEventListener("connected", this.#onGamepadConnected);
|
|
@@ -132,8 +139,8 @@ var GamepadControls = class extends EventDispatcher {
|
|
|
132
139
|
});
|
|
133
140
|
}
|
|
134
141
|
/**
|
|
135
|
-
* Called when the
|
|
136
|
-
*
|
|
142
|
+
* Called when the shared input reader observes a matching disconnection
|
|
143
|
+
* event or a missing/disconnected active slot, including events during pause.
|
|
137
144
|
*
|
|
138
145
|
* The default dispatches a `disconnected` event.
|
|
139
146
|
*
|
|
@@ -7,7 +7,7 @@ import { DragControls } from "three/addons/controls/DragControls.js";
|
|
|
7
7
|
*
|
|
8
8
|
* Every property has a sensible default, so you only need to pass the properties you want to override.
|
|
9
9
|
*/
|
|
10
|
-
type GamepadDragControlsOptions = GamepadControlsOptions & {
|
|
10
|
+
export type GamepadDragControlsOptions = GamepadControlsOptions & {
|
|
11
11
|
/**
|
|
12
12
|
* Screen-relative translation speed multiplier.
|
|
13
13
|
* @default 1.0
|
|
@@ -40,7 +40,7 @@ type GamepadDragControlsOptions = GamepadControlsOptions & {
|
|
|
40
40
|
* The center of the viewport acts as a logical reticle. Press the select button
|
|
41
41
|
* once to grab the centered object and again to drop it.
|
|
42
42
|
*/
|
|
43
|
-
declare class GamepadDragControls extends GamepadControls {
|
|
43
|
+
export declare class GamepadDragControls extends GamepadControls {
|
|
44
44
|
#private;
|
|
45
45
|
/**
|
|
46
46
|
* @param controls - A Three.js `DragControls` instance.
|
|
@@ -56,8 +56,7 @@ declare class GamepadDragControls extends GamepadControls {
|
|
|
56
56
|
*/
|
|
57
57
|
protected onUpdate(deltaTime: number): void;
|
|
58
58
|
/**
|
|
59
|
-
*
|
|
60
|
-
* gamepad lifecycle listeners.
|
|
59
|
+
* Disables gamepad updates, releases selection, and removes hover state.
|
|
61
60
|
*/
|
|
62
61
|
dispose(): void;
|
|
63
62
|
/**
|
|
@@ -67,5 +66,4 @@ declare class GamepadDragControls extends GamepadControls {
|
|
|
67
66
|
*/
|
|
68
67
|
protected onGamepadDisconnected(gamepad: Gamepad): void;
|
|
69
68
|
}
|
|
70
|
-
//#endregion
|
|
71
|
-
export { GamepadDragControls, GamepadDragControlsOptions };
|
|
69
|
+
//#endregion
|
|
@@ -73,13 +73,8 @@ var GamepadDragControls = class extends GamepadControls {
|
|
|
73
73
|
* @param deltaTime - Seconds since the last frame.
|
|
74
74
|
*/
|
|
75
75
|
onUpdate(deltaTime) {
|
|
76
|
-
const controls = this.#controls;
|
|
77
76
|
const selectStarted = this.gamepadInput.wasPressed(this.#options.buttonSelect);
|
|
78
|
-
if (!
|
|
79
|
-
this.#releaseSelected();
|
|
80
|
-
this.#clearHover();
|
|
81
|
-
return;
|
|
82
|
-
}
|
|
77
|
+
if (!this.#canApplyInput()) return;
|
|
83
78
|
const selected = this.#selected;
|
|
84
79
|
if (selected !== null) {
|
|
85
80
|
if (selectStarted) {
|
|
@@ -91,16 +86,19 @@ var GamepadDragControls = class extends GamepadControls {
|
|
|
91
86
|
}
|
|
92
87
|
const hit = this.#intersectCenter();
|
|
93
88
|
this.#updateHover(hit?.object ?? null);
|
|
94
|
-
if (
|
|
89
|
+
if (!this.#canApplyInput()) return;
|
|
90
|
+
if (selectStarted && hit !== void 0) {
|
|
91
|
+
this.#grabObject(hit.object);
|
|
92
|
+
this.#canApplyInput();
|
|
93
|
+
}
|
|
95
94
|
}
|
|
96
95
|
/**
|
|
97
|
-
*
|
|
98
|
-
* gamepad lifecycle listeners.
|
|
96
|
+
* Disables gamepad updates, releases selection, and removes hover state.
|
|
99
97
|
*/
|
|
100
98
|
dispose() {
|
|
99
|
+
super.dispose();
|
|
101
100
|
this.#releaseSelected();
|
|
102
101
|
this.#clearHover();
|
|
103
|
-
super.dispose();
|
|
104
102
|
}
|
|
105
103
|
/**
|
|
106
104
|
* Releases the selected object if the active gamepad disconnects mid-drag.
|
|
@@ -112,6 +110,14 @@ var GamepadDragControls = class extends GamepadControls {
|
|
|
112
110
|
this.#clearHover();
|
|
113
111
|
super.onGamepadDisconnected(gamepad);
|
|
114
112
|
}
|
|
113
|
+
#canApplyInput() {
|
|
114
|
+
if (!this.#controls.enabled) {
|
|
115
|
+
this.#releaseSelected();
|
|
116
|
+
this.#clearHover();
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
119
|
+
return this.enabled && this.gamepad !== null;
|
|
120
|
+
}
|
|
115
121
|
/**
|
|
116
122
|
* Updates the selected object from gamepad drag and rotation input.
|
|
117
123
|
*
|
|
@@ -125,10 +131,13 @@ var GamepadDragControls = class extends GamepadControls {
|
|
|
125
131
|
const rotate = input.stick(rotateStick.xAxis, rotateStick.yAxis, rotateStick.pipeline);
|
|
126
132
|
const dragged = this.#applyDrag(selected, deltaTime, drag.x, drag.y, dragSpeed);
|
|
127
133
|
const rotated = this.#applyRotation(selected, deltaTime, rotate.x, rotate.y, rotateSpeed);
|
|
128
|
-
if (dragged || rotated)
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
134
|
+
if (dragged || rotated) {
|
|
135
|
+
this.#controls.dispatchEvent({
|
|
136
|
+
type: "drag",
|
|
137
|
+
object: selected
|
|
138
|
+
});
|
|
139
|
+
this.#canApplyInput();
|
|
140
|
+
}
|
|
132
141
|
}
|
|
133
142
|
/**
|
|
134
143
|
* Moves the selected object in the camera-facing plane.
|
|
@@ -188,7 +197,7 @@ var GamepadDragControls = class extends GamepadControls {
|
|
|
188
197
|
#updateHover(object) {
|
|
189
198
|
if (this.#hovered === object) return;
|
|
190
199
|
this.#clearHover();
|
|
191
|
-
if (object === null) return;
|
|
200
|
+
if (object === null || !this.#canApplyInput()) return;
|
|
192
201
|
this.#hovered = object;
|
|
193
202
|
this.#controls.dispatchEvent({
|
|
194
203
|
type: "hoveron",
|
|
@@ -7,7 +7,7 @@ import { FirstPersonControls } from "three/addons/controls/FirstPersonControls.j
|
|
|
7
7
|
*
|
|
8
8
|
* Every property has a sensible default, so you only need to pass the properties you want to override.
|
|
9
9
|
*/
|
|
10
|
-
type GamepadFirstPersonControlsOptions = GamepadControlsOptions & {
|
|
10
|
+
export type GamepadFirstPersonControlsOptions = GamepadControlsOptions & {
|
|
11
11
|
/**
|
|
12
12
|
* Multiplier on `FirstPersonControls.movementSpeed` for translation.
|
|
13
13
|
* @default 1.0
|
|
@@ -49,7 +49,7 @@ type GamepadFirstPersonControlsOptions = GamepadControlsOptions & {
|
|
|
49
49
|
* `gamepadControls.update(delta)` before `controls.update(delta)` each frame.
|
|
50
50
|
* Bindings and speeds are configurable via {@link GamepadFirstPersonControlsOptions}.
|
|
51
51
|
*/
|
|
52
|
-
declare class GamepadFirstPersonControls extends GamepadControls {
|
|
52
|
+
export declare class GamepadFirstPersonControls extends GamepadControls {
|
|
53
53
|
#private;
|
|
54
54
|
/**
|
|
55
55
|
* @param controls - A Three.js `FirstPersonControls` instance.
|
|
@@ -64,5 +64,4 @@ declare class GamepadFirstPersonControls extends GamepadControls {
|
|
|
64
64
|
*/
|
|
65
65
|
protected onUpdate(deltaTime: number): void;
|
|
66
66
|
}
|
|
67
|
-
//#endregion
|
|
68
|
-
export { GamepadFirstPersonControls, GamepadFirstPersonControlsOptions };
|
|
67
|
+
//#endregion
|
|
@@ -58,6 +58,7 @@ var GamepadFirstPersonControls = class extends GamepadControls {
|
|
|
58
58
|
* @param deltaTime - Seconds since the last frame.
|
|
59
59
|
*/
|
|
60
60
|
onUpdate(deltaTime) {
|
|
61
|
+
if (!this.#controls.enabled) return;
|
|
61
62
|
const { moveSpeed, lookSpeed, moveStick, lookStick, buttonDeadzone, buttonMoveUp, buttonMoveDown } = this.#options;
|
|
62
63
|
this.#applyMovement(deltaTime, moveSpeed, moveStick, buttonDeadzone, buttonMoveUp, buttonMoveDown);
|
|
63
64
|
this.#applyLook(deltaTime, lookSpeed, lookStick);
|
|
@@ -7,7 +7,7 @@ import { FlyControls } from "three/addons/controls/FlyControls.js";
|
|
|
7
7
|
*
|
|
8
8
|
* Every property has a sensible default, so you only need to pass the properties you want to override.
|
|
9
9
|
*/
|
|
10
|
-
type GamepadFlyControlsOptions = GamepadControlsOptions & {
|
|
10
|
+
export type GamepadFlyControlsOptions = GamepadControlsOptions & {
|
|
11
11
|
/**
|
|
12
12
|
* Multiplier on `FlyControls.movementSpeed` for translation.
|
|
13
13
|
* @default 1.0
|
|
@@ -59,7 +59,7 @@ type GamepadFlyControlsOptions = GamepadControlsOptions & {
|
|
|
59
59
|
* `gamepadControls.update(delta)` and `controls.update(delta)` each frame.
|
|
60
60
|
* Bindings and speeds are configurable via {@link GamepadFlyControlsOptions}.
|
|
61
61
|
*/
|
|
62
|
-
declare class GamepadFlyControls extends GamepadControls {
|
|
62
|
+
export declare class GamepadFlyControls extends GamepadControls {
|
|
63
63
|
#private;
|
|
64
64
|
/**
|
|
65
65
|
* @param controls - A Three.js `FlyControls` instance.
|
|
@@ -74,5 +74,4 @@ declare class GamepadFlyControls extends GamepadControls {
|
|
|
74
74
|
*/
|
|
75
75
|
protected onUpdate(deltaTime: number): void;
|
|
76
76
|
}
|
|
77
|
-
//#endregion
|
|
78
|
-
export { GamepadFlyControls, GamepadFlyControlsOptions };
|
|
77
|
+
//#endregion
|
|
@@ -55,6 +55,7 @@ var GamepadFlyControls = class extends GamepadControls {
|
|
|
55
55
|
* @param deltaTime - Seconds since the last frame.
|
|
56
56
|
*/
|
|
57
57
|
onUpdate(deltaTime) {
|
|
58
|
+
if (!this.#controls.enabled) return;
|
|
58
59
|
const { moveSpeed, rotateSpeed, buttonDeadzone, moveStick, lookStick, buttonRollLeft, buttonRollRight, buttonMoveUp, buttonMoveDown } = this.#options;
|
|
59
60
|
const input = this.gamepadInput;
|
|
60
61
|
const move = input.stick(moveStick.xAxis, moveStick.yAxis, moveStick.pipeline);
|
package/dist/gamepad-input.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { EventDispatcher } from "three";
|
|
|
4
4
|
/**
|
|
5
5
|
* Event map for {@link GamepadInput}.
|
|
6
6
|
*/
|
|
7
|
-
type GamepadInputEventMap = {
|
|
7
|
+
export type GamepadInputEventMap = {
|
|
8
8
|
/**
|
|
9
9
|
* Fired when a gamepad is connected and becomes active.
|
|
10
10
|
*/
|
|
@@ -15,7 +15,9 @@ type GamepadInputEventMap = {
|
|
|
15
15
|
gamepad: Gamepad;
|
|
16
16
|
};
|
|
17
17
|
/**
|
|
18
|
-
* Fired
|
|
18
|
+
* Fired on a matching browser disconnection event or when polling observes
|
|
19
|
+
* the active slot missing or disconnected. Continuous snapshots in the same
|
|
20
|
+
* slot do not establish a physical-device identity or signal replacement.
|
|
19
21
|
*/
|
|
20
22
|
disconnected: {
|
|
21
23
|
/**
|
|
@@ -27,7 +29,7 @@ type GamepadInputEventMap = {
|
|
|
27
29
|
/**
|
|
28
30
|
* Configuration for {@link GamepadInput}.
|
|
29
31
|
*/
|
|
30
|
-
type GamepadInputOptions = {
|
|
32
|
+
export type GamepadInputOptions = {
|
|
31
33
|
/**
|
|
32
34
|
* Default dead zone threshold for {@link GamepadInput.axis} reads.
|
|
33
35
|
* @default 0.1
|
|
@@ -41,7 +43,9 @@ type GamepadInputOptions = {
|
|
|
41
43
|
/**
|
|
42
44
|
* Browser-assigned gamepad slot to use.
|
|
43
45
|
*
|
|
44
|
-
* When omitted, the connected
|
|
46
|
+
* When omitted, the lowest connected index is chosen at adoption and kept
|
|
47
|
+
* until its loss is observed, even if a lower index subsequently connects.
|
|
48
|
+
* Multiple unconfigured instances may adopt the same slot.
|
|
45
49
|
* The index must be an integer from `MIN_GAMEPAD_INDEX` through
|
|
46
50
|
* `MAX_GAMEPAD_INDEX`.
|
|
47
51
|
* A valid but empty slot keeps this input disconnected without falling back
|
|
@@ -52,7 +56,7 @@ type GamepadInputOptions = {
|
|
|
52
56
|
/**
|
|
53
57
|
* Options for axis reads.
|
|
54
58
|
*/
|
|
55
|
-
type GamepadAxisOptions = {
|
|
59
|
+
export type GamepadAxisOptions = {
|
|
56
60
|
/**
|
|
57
61
|
* Axis dead zone threshold for this read.
|
|
58
62
|
*/
|
|
@@ -63,10 +67,12 @@ type GamepadAxisOptions = {
|
|
|
63
67
|
*
|
|
64
68
|
* Call {@link update} once per frame before reading button transitions or axes.
|
|
65
69
|
*/
|
|
66
|
-
declare class GamepadInput extends EventDispatcher<GamepadInputEventMap> {
|
|
70
|
+
export declare class GamepadInput extends EventDispatcher<GamepadInputEventMap> {
|
|
67
71
|
#private;
|
|
68
72
|
/**
|
|
69
|
-
* When `false`,
|
|
73
|
+
* When `false`, polling through `update()` is paused and the last observed
|
|
74
|
+
* state, including button transitions, is retained. Browser listeners remain
|
|
75
|
+
* active and may adopt or disconnect a gamepad; connection events may poll.
|
|
70
76
|
* @default true
|
|
71
77
|
*/
|
|
72
78
|
enabled: boolean;
|
|
@@ -112,10 +118,15 @@ declare class GamepadInput extends EventDispatcher<GamepadInputEventMap> {
|
|
|
112
118
|
get vibrationSupported(): boolean;
|
|
113
119
|
/**
|
|
114
120
|
* Polls the gamepad and refreshes current and previous button state.
|
|
121
|
+
*
|
|
122
|
+
* Resuming compares against the last observed state, without replaying clicks
|
|
123
|
+
* completed during the pause. Adoption seeds held buttons without transitions.
|
|
115
124
|
*/
|
|
116
125
|
update(): void;
|
|
117
126
|
/**
|
|
118
|
-
* Removes
|
|
127
|
+
* Removes this reader's window listeners, clears its state, and disables it.
|
|
128
|
+
* Does not dispatch a synthetic disconnection or affect other input readers.
|
|
129
|
+
* Reusing a disposed reader is unsupported; create a new instance instead.
|
|
119
130
|
*/
|
|
120
131
|
dispose(): void;
|
|
121
132
|
/**
|
|
@@ -126,17 +137,19 @@ declare class GamepadInput extends EventDispatcher<GamepadInputEventMap> {
|
|
|
126
137
|
*/
|
|
127
138
|
isPressed(button: number): boolean;
|
|
128
139
|
/**
|
|
129
|
-
* Returns whether a button
|
|
140
|
+
* Returns whether a button changed to pressed in the latest observed state.
|
|
141
|
+
* Paused updates retain this result until the next observation or cleanup.
|
|
130
142
|
*
|
|
131
143
|
* @param button - Button index to inspect.
|
|
132
|
-
* @returns
|
|
144
|
+
* @returns Whether the latest observed button state transitioned to pressed.
|
|
133
145
|
*/
|
|
134
146
|
wasPressed(button: number): boolean;
|
|
135
147
|
/**
|
|
136
|
-
* Returns whether a button
|
|
148
|
+
* Returns whether a button changed to released in the latest observed state.
|
|
149
|
+
* Paused updates retain this result until the next observation or cleanup.
|
|
137
150
|
*
|
|
138
151
|
* @param button - Button index to inspect.
|
|
139
|
-
* @returns
|
|
152
|
+
* @returns Whether the latest observed button state transitioned to released.
|
|
140
153
|
*/
|
|
141
154
|
wasReleased(button: number): boolean;
|
|
142
155
|
/**
|
|
@@ -185,5 +198,4 @@ declare class GamepadInput extends EventDispatcher<GamepadInputEventMap> {
|
|
|
185
198
|
*/
|
|
186
199
|
resetVibration(): Promise<GamepadHapticsResult | null>;
|
|
187
200
|
}
|
|
188
|
-
//#endregion
|
|
189
|
-
export { GamepadAxisOptions, GamepadInput, GamepadInputEventMap, GamepadInputOptions };
|
|
201
|
+
//#endregion
|
package/dist/gamepad-input.js
CHANGED
|
@@ -52,7 +52,9 @@ const getGamepadButtonValue = (gamepad, button) => {
|
|
|
52
52
|
*/
|
|
53
53
|
var GamepadInput = class extends EventDispatcher {
|
|
54
54
|
/**
|
|
55
|
-
* When `false`,
|
|
55
|
+
* When `false`, polling through `update()` is paused and the last observed
|
|
56
|
+
* state, including button transitions, is retained. Browser listeners remain
|
|
57
|
+
* active and may adopt or disconnect a gamepad; connection events may poll.
|
|
56
58
|
* @default true
|
|
57
59
|
*/
|
|
58
60
|
enabled = true;
|
|
@@ -144,6 +146,9 @@ var GamepadInput = class extends EventDispatcher {
|
|
|
144
146
|
}
|
|
145
147
|
/**
|
|
146
148
|
* Polls the gamepad and refreshes current and previous button state.
|
|
149
|
+
*
|
|
150
|
+
* Resuming compares against the last observed state, without replaying clicks
|
|
151
|
+
* completed during the pause. Adoption seeds held buttons without transitions.
|
|
147
152
|
*/
|
|
148
153
|
update() {
|
|
149
154
|
if (!this.enabled) return;
|
|
@@ -170,7 +175,9 @@ var GamepadInput = class extends EventDispatcher {
|
|
|
170
175
|
this.#syncButtonState({ seedPrevious: false });
|
|
171
176
|
}
|
|
172
177
|
/**
|
|
173
|
-
* Removes
|
|
178
|
+
* Removes this reader's window listeners, clears its state, and disables it.
|
|
179
|
+
* Does not dispatch a synthetic disconnection or affect other input readers.
|
|
180
|
+
* Reusing a disposed reader is unsupported; create a new instance instead.
|
|
174
181
|
*/
|
|
175
182
|
dispose() {
|
|
176
183
|
window.removeEventListener("gamepadconnected", this.#onGamepadConnected);
|
|
@@ -190,19 +197,21 @@ var GamepadInput = class extends EventDispatcher {
|
|
|
190
197
|
return this.#pressedButtons.has(button);
|
|
191
198
|
}
|
|
192
199
|
/**
|
|
193
|
-
* Returns whether a button
|
|
200
|
+
* Returns whether a button changed to pressed in the latest observed state.
|
|
201
|
+
* Paused updates retain this result until the next observation or cleanup.
|
|
194
202
|
*
|
|
195
203
|
* @param button - Button index to inspect.
|
|
196
|
-
* @returns
|
|
204
|
+
* @returns Whether the latest observed button state transitioned to pressed.
|
|
197
205
|
*/
|
|
198
206
|
wasPressed(button) {
|
|
199
207
|
return this.#pressedButtons.has(button) && !this.#previousPressedButtons.has(button);
|
|
200
208
|
}
|
|
201
209
|
/**
|
|
202
|
-
* Returns whether a button
|
|
210
|
+
* Returns whether a button changed to released in the latest observed state.
|
|
211
|
+
* Paused updates retain this result until the next observation or cleanup.
|
|
203
212
|
*
|
|
204
213
|
* @param button - Button index to inspect.
|
|
205
|
-
* @returns
|
|
214
|
+
* @returns Whether the latest observed button state transitioned to released.
|
|
206
215
|
*/
|
|
207
216
|
wasReleased(button) {
|
|
208
217
|
return !this.#pressedButtons.has(button) && this.#previousPressedButtons.has(button);
|
package/dist/gamepad-manager.js
CHANGED
|
@@ -68,8 +68,10 @@ var GamepadManager = class {
|
|
|
68
68
|
/**
|
|
69
69
|
* Polls the Gamepad API and refreshes the active gamepad snapshot.
|
|
70
70
|
*
|
|
71
|
-
* Polling
|
|
72
|
-
*
|
|
71
|
+
* Polling refreshes the active slot without treating changes in object
|
|
72
|
+
* reference, `id`, or `timestamp` as reconnections. A missing or disconnected
|
|
73
|
+
* slot reports only a disconnection; adoption waits until the next update.
|
|
74
|
+
* Physical replacements without an observed loss cannot be distinguished.
|
|
73
75
|
*
|
|
74
76
|
* @returns The active gamepad and any connect/disconnect transition found.
|
|
75
77
|
*/
|
|
@@ -9,7 +9,7 @@ import { MapControls } from "three/addons/controls/MapControls.js";
|
|
|
9
9
|
*
|
|
10
10
|
* Call `update()` inside the render loop **before** `MapControls.update()`.
|
|
11
11
|
*/
|
|
12
|
-
declare class GamepadMapControls extends GamepadOrbitControls {
|
|
12
|
+
export declare class GamepadMapControls extends GamepadOrbitControls {
|
|
13
13
|
/**
|
|
14
14
|
* @param controls - A Three.js `MapControls` instance.
|
|
15
15
|
* @param options - Optional overrides for the default behavior.
|
|
@@ -17,5 +17,4 @@ declare class GamepadMapControls extends GamepadOrbitControls {
|
|
|
17
17
|
*/
|
|
18
18
|
constructor(controls: MapControls, options?: Partial<GamepadOrbitControlsOptions>);
|
|
19
19
|
}
|
|
20
|
-
//#endregion
|
|
21
|
-
export { GamepadMapControls };
|
|
20
|
+
//#endregion
|
|
@@ -7,7 +7,7 @@ import { OrbitControls } from "three/addons/controls/OrbitControls.js";
|
|
|
7
7
|
*
|
|
8
8
|
* Every property has a sensible default, so you only need to pass the properties you want to override.
|
|
9
9
|
*/
|
|
10
|
-
type GamepadOrbitControlsOptions = GamepadControlsOptions & {
|
|
10
|
+
export type GamepadOrbitControlsOptions = GamepadControlsOptions & {
|
|
11
11
|
/**
|
|
12
12
|
* Multiplier on orbit rotation speed.
|
|
13
13
|
* @default 1.0
|
|
@@ -55,7 +55,7 @@ type GamepadOrbitControlsOptions = GamepadControlsOptions & {
|
|
|
55
55
|
* Call `update()` inside the render loop **before** `OrbitControls.update()`.
|
|
56
56
|
* Bindings and speeds are configurable via {@link GamepadOrbitControlsOptions}.
|
|
57
57
|
*/
|
|
58
|
-
declare class GamepadOrbitControls extends GamepadControls {
|
|
58
|
+
export declare class GamepadOrbitControls extends GamepadControls {
|
|
59
59
|
#private;
|
|
60
60
|
/**
|
|
61
61
|
* @param controls - A Three.js `OrbitControls` instance.
|
|
@@ -70,5 +70,4 @@ declare class GamepadOrbitControls extends GamepadControls {
|
|
|
70
70
|
*/
|
|
71
71
|
protected onUpdate(deltaTime: number): void;
|
|
72
72
|
}
|
|
73
|
-
//#endregion
|
|
74
|
-
export { GamepadOrbitControls, GamepadOrbitControlsOptions };
|
|
73
|
+
//#endregion
|
|
@@ -50,17 +50,34 @@ var GamepadOrbitControls = class extends GamepadControls {
|
|
|
50
50
|
* @param deltaTime - Seconds since the last frame.
|
|
51
51
|
*/
|
|
52
52
|
onUpdate(deltaTime) {
|
|
53
|
+
if (!this.#canApplyInput()) return;
|
|
54
|
+
const controls = this.#controls;
|
|
53
55
|
const { rotateSpeed, panSpeed, zoomSpeed, rotateStick, panStick, buttonDeadzone, buttonDollyIn, buttonDollyOut } = this.#options;
|
|
54
56
|
const input = this.gamepadInput;
|
|
55
57
|
const rotate = input.stick(rotateStick.xAxis, rotateStick.yAxis, rotateStick.pipeline);
|
|
56
|
-
if (rotate.x !== 0)
|
|
57
|
-
|
|
58
|
+
if (controls.enableRotate && rotate.x !== 0) {
|
|
59
|
+
controls.rotateLeft(rotate.x * rotateSpeed * deltaTime * Math.PI);
|
|
60
|
+
if (!this.#canApplyInput()) return;
|
|
61
|
+
}
|
|
62
|
+
if (controls.enableRotate && rotate.y !== 0) {
|
|
63
|
+
controls.rotateUp(rotate.y * rotateSpeed * deltaTime * Math.PI);
|
|
64
|
+
if (!this.#canApplyInput()) return;
|
|
65
|
+
}
|
|
58
66
|
const pan = input.stick(panStick.xAxis, panStick.yAxis, panStick.pipeline);
|
|
59
|
-
if (pan.x !== 0 || pan.y !== 0)
|
|
67
|
+
if (controls.enablePan && (pan.x !== 0 || pan.y !== 0)) {
|
|
68
|
+
controls.pan(pan.x * panSpeed * deltaTime * 500, pan.y * panSpeed * deltaTime * 500);
|
|
69
|
+
if (!this.#canApplyInput()) return;
|
|
70
|
+
}
|
|
60
71
|
const triggerIn = input.buttonValue(buttonDollyIn);
|
|
61
72
|
const triggerOut = input.buttonValue(buttonDollyOut);
|
|
62
|
-
if (
|
|
63
|
-
|
|
73
|
+
if (controls.enableZoom && triggerIn > buttonDeadzone) {
|
|
74
|
+
controls.dollyIn(1 / (1 + zoomSpeed * triggerIn * deltaTime));
|
|
75
|
+
if (!this.#canApplyInput()) return;
|
|
76
|
+
}
|
|
77
|
+
if (controls.enableZoom && triggerOut > buttonDeadzone) controls.dollyOut(1 / (1 + zoomSpeed * triggerOut * deltaTime));
|
|
78
|
+
}
|
|
79
|
+
#canApplyInput() {
|
|
80
|
+
return this.enabled && this.#controls.enabled && this.gamepad !== null;
|
|
64
81
|
}
|
|
65
82
|
};
|
|
66
83
|
//#endregion
|
|
@@ -7,7 +7,7 @@ import { PointerLockControls } from "three/addons/controls/PointerLockControls.j
|
|
|
7
7
|
*
|
|
8
8
|
* Every property has a sensible default, so you only need to pass the properties you want to override.
|
|
9
9
|
*/
|
|
10
|
-
type GamepadPointerLockControlsOptions = GamepadControlsOptions & {
|
|
10
|
+
export type GamepadPointerLockControlsOptions = GamepadControlsOptions & {
|
|
11
11
|
/**
|
|
12
12
|
* Camera movement speed in world units per second at full stick deflection.
|
|
13
13
|
* @default 5.0
|
|
@@ -36,7 +36,7 @@ type GamepadPointerLockControlsOptions = GamepadControlsOptions & {
|
|
|
36
36
|
* IS locked, mouse and gamepad look inputs are additive.
|
|
37
37
|
* Bindings and speeds are configurable via {@link GamepadPointerLockControlsOptions}.
|
|
38
38
|
*/
|
|
39
|
-
declare class GamepadPointerLockControls extends GamepadControls {
|
|
39
|
+
export declare class GamepadPointerLockControls extends GamepadControls {
|
|
40
40
|
#private;
|
|
41
41
|
/**
|
|
42
42
|
* @param controls - A Three.js `PointerLockControls` instance.
|
|
@@ -51,5 +51,4 @@ declare class GamepadPointerLockControls extends GamepadControls {
|
|
|
51
51
|
*/
|
|
52
52
|
protected onUpdate(deltaTime: number): void;
|
|
53
53
|
}
|
|
54
|
-
//#endregion
|
|
55
|
-
export { GamepadPointerLockControls, GamepadPointerLockControlsOptions };
|
|
54
|
+
//#endregion
|
|
@@ -50,6 +50,7 @@ var GamepadPointerLockControls = class extends GamepadControls {
|
|
|
50
50
|
* @param deltaTime - Seconds since the last frame.
|
|
51
51
|
*/
|
|
52
52
|
onUpdate(deltaTime) {
|
|
53
|
+
if (!this.#controls.enabled) return;
|
|
53
54
|
const { moveSpeed, lookSpeed, moveStick, lookStick } = this.#options;
|
|
54
55
|
const input = this.gamepadInput;
|
|
55
56
|
const move = input.stick(moveStick.xAxis, moveStick.yAxis, moveStick.pipeline);
|
|
@@ -5,19 +5,19 @@
|
|
|
5
5
|
* Axial processing transforms each component independently. Radial processing
|
|
6
6
|
* transforms vector magnitude while preserving direction.
|
|
7
7
|
*/
|
|
8
|
-
type GamepadStickProcessingMode = "axial" | "radial";
|
|
8
|
+
export type GamepadStickProcessingMode = "axial" | "radial";
|
|
9
9
|
/**
|
|
10
10
|
* Built-in response curve applied to stick components or magnitude.
|
|
11
11
|
*/
|
|
12
|
-
type GamepadResponseCurve = "linear" | "quadratic" | "cubic";
|
|
12
|
+
export type GamepadResponseCurve = "linear" | "quadratic" | "cubic";
|
|
13
13
|
/**
|
|
14
14
|
* Stick component selection used by inversion processing.
|
|
15
15
|
*/
|
|
16
|
-
type GamepadStickInversionAxis = "x" | "y" | "both";
|
|
16
|
+
export type GamepadStickInversionAxis = "x" | "y" | "both";
|
|
17
17
|
/**
|
|
18
18
|
* Two-dimensional gamepad stick value.
|
|
19
19
|
*/
|
|
20
|
-
type GamepadStick = {
|
|
20
|
+
export type GamepadStick = {
|
|
21
21
|
/**
|
|
22
22
|
* Horizontal stick component.
|
|
23
23
|
*/
|
|
@@ -30,14 +30,14 @@ type GamepadStick = {
|
|
|
30
30
|
/**
|
|
31
31
|
* Pure custom transformation applied to a gamepad stick.
|
|
32
32
|
*/
|
|
33
|
-
type GamepadStickTransform = (value: Readonly<GamepadStick>) => GamepadStick;
|
|
33
|
+
export type GamepadStickTransform = (value: Readonly<GamepadStick>) => GamepadStick;
|
|
34
34
|
/**
|
|
35
35
|
* Pure, stateless transformation applied to a gamepad stick.
|
|
36
36
|
*
|
|
37
37
|
* Implementations must not mutate `value`. Stateful processing such as
|
|
38
38
|
* smoothing belongs in a separate lifecycle-aware abstraction.
|
|
39
39
|
*/
|
|
40
|
-
type GamepadStickProcessor = {
|
|
40
|
+
export type GamepadStickProcessor = {
|
|
41
41
|
/**
|
|
42
42
|
* Transforms one stick value.
|
|
43
43
|
*
|
|
@@ -49,7 +49,7 @@ type GamepadStickProcessor = {
|
|
|
49
49
|
/**
|
|
50
50
|
* Options for {@link gamepadStickPipeline}.
|
|
51
51
|
*/
|
|
52
|
-
type GamepadStickPipelineOptions = {
|
|
52
|
+
export type GamepadStickPipelineOptions = {
|
|
53
53
|
/**
|
|
54
54
|
* Default geometry for processing methods that support axial and radial modes.
|
|
55
55
|
* @default "axial"
|
|
@@ -59,7 +59,7 @@ type GamepadStickPipelineOptions = {
|
|
|
59
59
|
/**
|
|
60
60
|
* Options for {@link GamepadStickPipeline.deadzone}.
|
|
61
61
|
*/
|
|
62
|
-
type GamepadDeadzoneOptions = {
|
|
62
|
+
export type GamepadDeadzoneOptions = {
|
|
63
63
|
/**
|
|
64
64
|
* Geometry for this dead zone, overriding the pipeline default.
|
|
65
65
|
*/
|
|
@@ -73,7 +73,7 @@ type GamepadDeadzoneOptions = {
|
|
|
73
73
|
/**
|
|
74
74
|
* Options for {@link GamepadStickPipeline.responseCurve}.
|
|
75
75
|
*/
|
|
76
|
-
type GamepadResponseCurveOptions = {
|
|
76
|
+
export type GamepadResponseCurveOptions = {
|
|
77
77
|
/**
|
|
78
78
|
* Geometry for this response curve, overriding the pipeline default.
|
|
79
79
|
*/
|
|
@@ -85,7 +85,7 @@ type GamepadResponseCurveOptions = {
|
|
|
85
85
|
* Every configuration method returns a new frozen pipeline and leaves the
|
|
86
86
|
* current pipeline unchanged.
|
|
87
87
|
*/
|
|
88
|
-
type GamepadStickPipeline = GamepadStickProcessor & {
|
|
88
|
+
export type GamepadStickPipeline = GamepadStickProcessor & {
|
|
89
89
|
/**
|
|
90
90
|
* Appends an axial or radial dead zone.
|
|
91
91
|
*
|
|
@@ -129,7 +129,7 @@ type GamepadStickPipeline = GamepadStickProcessor & {
|
|
|
129
129
|
*
|
|
130
130
|
* Omitted fields inherit the action-specific defaults.
|
|
131
131
|
*/
|
|
132
|
-
type GamepadStickBindingOptions = {
|
|
132
|
+
export type GamepadStickBindingOptions = {
|
|
133
133
|
/**
|
|
134
134
|
* Axis index used as the horizontal component.
|
|
135
135
|
*/
|
|
@@ -146,7 +146,7 @@ type GamepadStickBindingOptions = {
|
|
|
146
146
|
/**
|
|
147
147
|
* Fully resolved binding used when reading a two-dimensional stick action.
|
|
148
148
|
*/
|
|
149
|
-
type GamepadStickBinding = Required<GamepadStickBindingOptions>;
|
|
149
|
+
export type GamepadStickBinding = Required<GamepadStickBindingOptions>;
|
|
150
150
|
/**
|
|
151
151
|
* Creates an immutable, fluent stick processing pipeline.
|
|
152
152
|
*
|
|
@@ -157,11 +157,11 @@ type GamepadStickBinding = Required<GamepadStickBindingOptions>;
|
|
|
157
157
|
* @param options - Optional pipeline defaults.
|
|
158
158
|
* @returns Frozen stick pipeline.
|
|
159
159
|
*/
|
|
160
|
-
declare const gamepadStickPipeline: (options?: GamepadStickPipelineOptions) => GamepadStickPipeline;
|
|
160
|
+
export declare const gamepadStickPipeline: (options?: GamepadStickPipelineOptions) => GamepadStickPipeline;
|
|
161
161
|
/**
|
|
162
162
|
* Historical stick processing used when no custom pipeline is supplied.
|
|
163
163
|
*/
|
|
164
|
-
declare const DEFAULT_GAMEPAD_STICK_PIPELINE: GamepadStickPipeline;
|
|
164
|
+
export declare const DEFAULT_GAMEPAD_STICK_PIPELINE: GamepadStickPipeline;
|
|
165
165
|
/**
|
|
166
166
|
* Resolves a partial stick binding over an action-specific default.
|
|
167
167
|
*
|
|
@@ -169,6 +169,5 @@ declare const DEFAULT_GAMEPAD_STICK_PIPELINE: GamepadStickPipeline;
|
|
|
169
169
|
* @param options - Optional binding overrides.
|
|
170
170
|
* @returns Complete resolved binding.
|
|
171
171
|
*/
|
|
172
|
-
declare const resolveGamepadStickBinding: (defaults: GamepadStickBinding, options?: GamepadStickBindingOptions) => GamepadStickBinding;
|
|
173
|
-
//#endregion
|
|
174
|
-
export { DEFAULT_GAMEPAD_STICK_PIPELINE, GamepadDeadzoneOptions, GamepadResponseCurve, GamepadResponseCurveOptions, GamepadStick, GamepadStickBinding, GamepadStickBindingOptions, GamepadStickInversionAxis, GamepadStickPipeline, GamepadStickPipelineOptions, GamepadStickProcessingMode, GamepadStickProcessor, GamepadStickTransform, gamepadStickPipeline, resolveGamepadStickBinding };
|
|
172
|
+
export declare const resolveGamepadStickBinding: (defaults: GamepadStickBinding, options?: GamepadStickBindingOptions) => GamepadStickBinding;
|
|
173
|
+
//#endregion
|
|
@@ -7,7 +7,7 @@ import { TrackballControls } from "three/addons/controls/TrackballControls.js";
|
|
|
7
7
|
*
|
|
8
8
|
* Every property has a sensible default, so you only need to pass the properties you want to override.
|
|
9
9
|
*/
|
|
10
|
-
type GamepadTrackballControlsOptions = GamepadControlsOptions & {
|
|
10
|
+
export type GamepadTrackballControlsOptions = GamepadControlsOptions & {
|
|
11
11
|
/**
|
|
12
12
|
* Multiplier on `TrackballControls.rotateSpeed` for rotation.
|
|
13
13
|
* @default 1.0
|
|
@@ -55,7 +55,7 @@ type GamepadTrackballControlsOptions = GamepadControlsOptions & {
|
|
|
55
55
|
* Call `update()` inside the render loop **before** `TrackballControls.update()`.
|
|
56
56
|
* Bindings and speed multipliers are configurable via {@link GamepadTrackballControlsOptions}.
|
|
57
57
|
*/
|
|
58
|
-
declare class GamepadTrackballControls extends GamepadControls {
|
|
58
|
+
export declare class GamepadTrackballControls extends GamepadControls {
|
|
59
59
|
#private;
|
|
60
60
|
/**
|
|
61
61
|
* @param controls - A Three.js `TrackballControls` instance.
|
|
@@ -70,5 +70,4 @@ declare class GamepadTrackballControls extends GamepadControls {
|
|
|
70
70
|
*/
|
|
71
71
|
protected onUpdate(deltaTime: number): void;
|
|
72
72
|
}
|
|
73
|
-
//#endregion
|
|
74
|
-
export { GamepadTrackballControls, GamepadTrackballControlsOptions };
|
|
73
|
+
//#endregion
|
|
@@ -50,6 +50,7 @@ var GamepadTrackballControls = class extends GamepadControls {
|
|
|
50
50
|
* @param deltaTime - Seconds since the last frame.
|
|
51
51
|
*/
|
|
52
52
|
onUpdate(deltaTime) {
|
|
53
|
+
if (!this.#controls.enabled) return;
|
|
53
54
|
const { rotateSpeed, panSpeed, zoomSpeed, rotateStick, panStick, buttonDeadzone, buttonZoomIn, buttonZoomOut } = this.#options;
|
|
54
55
|
this.#queueRotation(deltaTime, rotateSpeed, rotateStick);
|
|
55
56
|
this.#queuePan(deltaTime, panSpeed, panStick);
|
|
@@ -64,11 +65,7 @@ var GamepadTrackballControls = class extends GamepadControls {
|
|
|
64
65
|
*/
|
|
65
66
|
#queueRotation(deltaTime, rotateSpeed, rotateStick) {
|
|
66
67
|
const controls = this.#controls;
|
|
67
|
-
if (controls.noRotate)
|
|
68
|
-
controls._movePrev.copy(controls._moveCurr);
|
|
69
|
-
controls._lastAngle = 0;
|
|
70
|
-
return;
|
|
71
|
-
}
|
|
68
|
+
if (controls.noRotate) return;
|
|
72
69
|
const rotate = this.gamepadInput.stick(rotateStick.xAxis, rotateStick.yAxis, rotateStick.pipeline);
|
|
73
70
|
if (rotate.x === 0 && rotate.y === 0) return;
|
|
74
71
|
const scale = rotateSpeed * deltaTime * Math.PI;
|
|
@@ -84,10 +81,7 @@ var GamepadTrackballControls = class extends GamepadControls {
|
|
|
84
81
|
*/
|
|
85
82
|
#queuePan(deltaTime, panSpeed, panStick) {
|
|
86
83
|
const controls = this.#controls;
|
|
87
|
-
if (controls.noPan)
|
|
88
|
-
controls._panStart.copy(controls._panEnd);
|
|
89
|
-
return;
|
|
90
|
-
}
|
|
84
|
+
if (controls.noPan) return;
|
|
91
85
|
const pan = this.gamepadInput.stick(panStick.xAxis, panStick.yAxis, panStick.pipeline);
|
|
92
86
|
if (pan.x === 0 && pan.y === 0) return;
|
|
93
87
|
const scale = panSpeed * deltaTime * this.#getInputDampingFactor();
|
|
@@ -105,10 +99,7 @@ var GamepadTrackballControls = class extends GamepadControls {
|
|
|
105
99
|
*/
|
|
106
100
|
#queueZoom(deltaTime, zoomSpeed, buttonDeadzone, buttonZoomIn, buttonZoomOut) {
|
|
107
101
|
const controls = this.#controls;
|
|
108
|
-
if (controls.noZoom)
|
|
109
|
-
controls._zoomStart.copy(controls._zoomEnd);
|
|
110
|
-
return;
|
|
111
|
-
}
|
|
102
|
+
if (controls.noZoom) return;
|
|
112
103
|
const input = this.gamepadInput;
|
|
113
104
|
const triggerIn = input.buttonValue(buttonZoomIn);
|
|
114
105
|
const triggerOut = input.buttonValue(buttonZoomOut);
|
|
@@ -7,7 +7,7 @@ import { TransformControls } from "three/addons/controls/TransformControls.js";
|
|
|
7
7
|
*
|
|
8
8
|
* Every property has a sensible default, so you only need to pass the properties you want to override.
|
|
9
9
|
*/
|
|
10
|
-
type GamepadTransformControlsOptions = GamepadControlsOptions & {
|
|
10
|
+
export type GamepadTransformControlsOptions = GamepadControlsOptions & {
|
|
11
11
|
/**
|
|
12
12
|
* Screen-relative translation speed multiplier.
|
|
13
13
|
* @default 1.0
|
|
@@ -91,7 +91,7 @@ type GamepadTransformControlsOptions = GamepadControlsOptions & {
|
|
|
91
91
|
* stick starts a native-style transform interaction, and releasing it ends
|
|
92
92
|
* the interaction while keeping the active axis highlighted.
|
|
93
93
|
*/
|
|
94
|
-
declare class GamepadTransformControls extends GamepadControls {
|
|
94
|
+
export declare class GamepadTransformControls extends GamepadControls {
|
|
95
95
|
#private;
|
|
96
96
|
/**
|
|
97
97
|
* @param controls - A Three.js `TransformControls` instance.
|
|
@@ -107,7 +107,7 @@ declare class GamepadTransformControls extends GamepadControls {
|
|
|
107
107
|
*/
|
|
108
108
|
protected onUpdate(deltaTime: number): void;
|
|
109
109
|
/**
|
|
110
|
-
*
|
|
110
|
+
* Disables gamepad updates and ends only this wrapper's active transform.
|
|
111
111
|
*/
|
|
112
112
|
dispose(): void;
|
|
113
113
|
/**
|
|
@@ -117,5 +117,4 @@ declare class GamepadTransformControls extends GamepadControls {
|
|
|
117
117
|
*/
|
|
118
118
|
protected onGamepadDisconnected(gamepad: Gamepad): void;
|
|
119
119
|
}
|
|
120
|
-
//#endregion
|
|
121
|
-
export { GamepadTransformControls, GamepadTransformControlsOptions };
|
|
120
|
+
//#endregion
|
|
@@ -100,6 +100,7 @@ var GamepadTransformControls = class extends GamepadControls {
|
|
|
100
100
|
#rotationQuaternion2;
|
|
101
101
|
#tempQuaternion;
|
|
102
102
|
#isTransforming = false;
|
|
103
|
+
#transformStarted = false;
|
|
103
104
|
#rotationAmount = 0;
|
|
104
105
|
#freeRotationX = 0;
|
|
105
106
|
#freeRotationY = 0;
|
|
@@ -158,16 +159,21 @@ var GamepadTransformControls = class extends GamepadControls {
|
|
|
158
159
|
* @param deltaTime - Seconds since the last frame.
|
|
159
160
|
*/
|
|
160
161
|
onUpdate(deltaTime) {
|
|
162
|
+
const controls = this.#controls;
|
|
163
|
+
if (!this.#canApplyInput()) return;
|
|
164
|
+
if (controls.dragging && !this.#isTransforming) return;
|
|
161
165
|
const startedButtons = this.#getStartedButtons();
|
|
162
166
|
this.#handleModeAndAxisButtons(startedButtons);
|
|
167
|
+
if (!this.#canApplyInput()) return;
|
|
163
168
|
if (startedButtons.has(this.#options.buttonReset)) this.#resetActiveTransform();
|
|
164
|
-
|
|
169
|
+
if (!this.#canApplyInput()) return;
|
|
165
170
|
const object = controls.object;
|
|
166
|
-
if (
|
|
171
|
+
if (object === void 0) {
|
|
167
172
|
this.#endTransform(true);
|
|
168
173
|
return;
|
|
169
174
|
}
|
|
170
175
|
const axis = this.#ensureValidAxis();
|
|
176
|
+
if (!this.#canApplyInput()) return;
|
|
171
177
|
if (axis === null) {
|
|
172
178
|
this.#endTransform(true);
|
|
173
179
|
return;
|
|
@@ -179,17 +185,26 @@ var GamepadTransformControls = class extends GamepadControls {
|
|
|
179
185
|
return;
|
|
180
186
|
}
|
|
181
187
|
if (!this.#isTransforming) this.#startTransform(object);
|
|
188
|
+
if (!this.#canApplyInput()) return;
|
|
189
|
+
if (!this.#transformStarted) {
|
|
190
|
+
this.#transformStarted = true;
|
|
191
|
+
controls.dispatchEvent({
|
|
192
|
+
type: "mouseDown",
|
|
193
|
+
mode: controls.mode
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
if (!this.#canApplyInput()) return;
|
|
182
197
|
if (this.#applyCurrentTransform(object, axis, deltaTime, transform.x, transform.y)) {
|
|
183
198
|
controls.dispatchEvent({ type: "change" });
|
|
184
199
|
controls.dispatchEvent({ type: "objectChange" });
|
|
185
200
|
}
|
|
186
201
|
}
|
|
187
202
|
/**
|
|
188
|
-
*
|
|
203
|
+
* Disables gamepad updates and ends only this wrapper's active transform.
|
|
189
204
|
*/
|
|
190
205
|
dispose() {
|
|
191
|
-
this.#endTransform(true);
|
|
192
206
|
super.dispose();
|
|
207
|
+
this.#endTransform(true);
|
|
193
208
|
}
|
|
194
209
|
/**
|
|
195
210
|
* Ends any active transform if the active gamepad disconnects mid-drag.
|
|
@@ -200,6 +215,13 @@ var GamepadTransformControls = class extends GamepadControls {
|
|
|
200
215
|
this.#endTransform(true);
|
|
201
216
|
super.onGamepadDisconnected(gamepad);
|
|
202
217
|
}
|
|
218
|
+
#canApplyInput() {
|
|
219
|
+
if (!this.#controls.enabled) {
|
|
220
|
+
this.#endTransform(true);
|
|
221
|
+
return false;
|
|
222
|
+
}
|
|
223
|
+
return this.enabled && this.gamepad !== null;
|
|
224
|
+
}
|
|
203
225
|
/**
|
|
204
226
|
* Applies mode, space, and axis button transitions from the current frame.
|
|
205
227
|
*
|
|
@@ -207,16 +229,16 @@ var GamepadTransformControls = class extends GamepadControls {
|
|
|
207
229
|
*/
|
|
208
230
|
#handleModeAndAxisButtons(startedButtons) {
|
|
209
231
|
const { buttonTranslate, buttonRotate, buttonScale, buttonToggleSpace, buttonAxisX, buttonAxisY, buttonAxisZ, buttonAxisComposite, buttonAxisPrevious, buttonAxisNext } = this.#options;
|
|
210
|
-
if (startedButtons.has(buttonTranslate)) this.#setMode("translate");
|
|
211
|
-
if (startedButtons.has(buttonRotate)) this.#setMode("rotate");
|
|
212
|
-
if (startedButtons.has(buttonScale)) this.#setMode("scale");
|
|
213
|
-
if (startedButtons.has(buttonToggleSpace)) this.#toggleSpace();
|
|
214
|
-
if (startedButtons.has(buttonAxisX)) this.#selectAxis("X");
|
|
215
|
-
if (startedButtons.has(buttonAxisY)) this.#selectAxis("Y");
|
|
216
|
-
if (startedButtons.has(buttonAxisZ)) this.#selectAxis("Z");
|
|
217
|
-
if (startedButtons.has(buttonAxisComposite)) this.#cycleCompositeAxis();
|
|
218
|
-
if (startedButtons.has(buttonAxisPrevious)) this.#cycleAxis(-1);
|
|
219
|
-
if (startedButtons.has(buttonAxisNext)) this.#cycleAxis(1);
|
|
232
|
+
if (startedButtons.has(buttonTranslate) && this.#canApplyInput()) this.#setMode("translate");
|
|
233
|
+
if (startedButtons.has(buttonRotate) && this.#canApplyInput()) this.#setMode("rotate");
|
|
234
|
+
if (startedButtons.has(buttonScale) && this.#canApplyInput()) this.#setMode("scale");
|
|
235
|
+
if (startedButtons.has(buttonToggleSpace) && this.#canApplyInput()) this.#toggleSpace();
|
|
236
|
+
if (startedButtons.has(buttonAxisX) && this.#canApplyInput()) this.#selectAxis("X");
|
|
237
|
+
if (startedButtons.has(buttonAxisY) && this.#canApplyInput()) this.#selectAxis("Y");
|
|
238
|
+
if (startedButtons.has(buttonAxisZ) && this.#canApplyInput()) this.#selectAxis("Z");
|
|
239
|
+
if (startedButtons.has(buttonAxisComposite) && this.#canApplyInput()) this.#cycleCompositeAxis();
|
|
240
|
+
if (startedButtons.has(buttonAxisPrevious) && this.#canApplyInput()) this.#cycleAxis(-1);
|
|
241
|
+
if (startedButtons.has(buttonAxisNext) && this.#canApplyInput()) this.#cycleAxis(1);
|
|
220
242
|
}
|
|
221
243
|
/**
|
|
222
244
|
* Switches TransformControls mode and refreshes the active axis.
|
|
@@ -226,12 +248,14 @@ var GamepadTransformControls = class extends GamepadControls {
|
|
|
226
248
|
#setMode(mode) {
|
|
227
249
|
if (this.#controls.mode === mode) return;
|
|
228
250
|
this.#endTransform(false);
|
|
251
|
+
if (!this.#canApplyInput()) return;
|
|
229
252
|
this.#controls.setMode(mode);
|
|
230
|
-
this.#ensureValidAxis();
|
|
253
|
+
if (this.#canApplyInput()) this.#ensureValidAxis();
|
|
231
254
|
}
|
|
232
255
|
#toggleSpace() {
|
|
233
256
|
const nextSpace = this.#controls.space === "world" ? "local" : "world";
|
|
234
257
|
this.#endTransform(false);
|
|
258
|
+
if (!this.#canApplyInput()) return;
|
|
235
259
|
this.#controls.setSpace(nextSpace);
|
|
236
260
|
}
|
|
237
261
|
/**
|
|
@@ -242,6 +266,7 @@ var GamepadTransformControls = class extends GamepadControls {
|
|
|
242
266
|
#selectAxis(axis) {
|
|
243
267
|
if (!this.#isAxisAllowed(this.#controls.mode, axis)) return;
|
|
244
268
|
this.#endTransform(false);
|
|
269
|
+
if (!this.#canApplyInput()) return;
|
|
245
270
|
this.#activeAxisByMode[this.#controls.mode] = axis;
|
|
246
271
|
this.#ensureValidAxis();
|
|
247
272
|
}
|
|
@@ -269,6 +294,7 @@ var GamepadTransformControls = class extends GamepadControls {
|
|
|
269
294
|
return;
|
|
270
295
|
}
|
|
271
296
|
this.#endTransform(false);
|
|
297
|
+
if (!this.#canApplyInput()) return;
|
|
272
298
|
const current = this.#activeAxisByMode[this.#controls.mode];
|
|
273
299
|
const currentIndex = current === null ? -1 : axes.indexOf(current);
|
|
274
300
|
const nextIndex = currentIndex === -1 ? 0 : (currentIndex + direction + axes.length) % axes.length;
|
|
@@ -356,12 +382,8 @@ var GamepadTransformControls = class extends GamepadControls {
|
|
|
356
382
|
#startTransform(object) {
|
|
357
383
|
const controls = this.#controls;
|
|
358
384
|
this.#captureTransformStart(object);
|
|
359
|
-
controls.dragging = true;
|
|
360
385
|
this.#isTransforming = true;
|
|
361
|
-
controls.
|
|
362
|
-
type: "mouseDown",
|
|
363
|
-
mode: controls.mode
|
|
364
|
-
});
|
|
386
|
+
controls.dragging = true;
|
|
365
387
|
}
|
|
366
388
|
/**
|
|
367
389
|
* Ends an active TransformControls drag interaction.
|
|
@@ -369,15 +391,17 @@ var GamepadTransformControls = class extends GamepadControls {
|
|
|
369
391
|
* @param clearAxis - Whether to clear the highlighted axis after ending.
|
|
370
392
|
*/
|
|
371
393
|
#endTransform(clearAxis) {
|
|
394
|
+
if (!this.#isTransforming) return;
|
|
372
395
|
const controls = this.#controls;
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
}
|
|
396
|
+
const started = this.#transformStarted;
|
|
397
|
+
const mode = controls.mode;
|
|
398
|
+
this.#isTransforming = false;
|
|
399
|
+
this.#transformStarted = false;
|
|
400
|
+
if (started) controls.dispatchEvent({
|
|
401
|
+
type: "mouseUp",
|
|
402
|
+
mode
|
|
403
|
+
});
|
|
404
|
+
controls.dragging = false;
|
|
381
405
|
if (clearAxis) this.#setActiveAxis(null);
|
|
382
406
|
}
|
|
383
407
|
#resetActiveTransform() {
|
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.24.
|
|
4
|
+
"version": "0.24.1",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://github.com/luckasnix/three-gamepad-controls#readme",
|
|
7
7
|
"author": {
|
|
@@ -46,19 +46,20 @@
|
|
|
46
46
|
}
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
|
-
"@biomejs/biome": "2.5.
|
|
50
|
-
"@commitlint/cli": "21.2.
|
|
51
|
-
"@commitlint/config-conventional": "21.2.
|
|
52
|
-
"@commitlint/types": "21.2.
|
|
49
|
+
"@biomejs/biome": "2.5.14",
|
|
50
|
+
"@commitlint/cli": "21.2.3",
|
|
51
|
+
"@commitlint/config-conventional": "21.2.3",
|
|
52
|
+
"@commitlint/types": "21.2.3",
|
|
53
53
|
"@types/node": "24.13.3",
|
|
54
54
|
"@types/three": "0.186.0",
|
|
55
|
-
"@vitest/
|
|
55
|
+
"@vitest/browser-playwright": "5.0.2",
|
|
56
|
+
"@vitest/coverage-v8": "5.0.2",
|
|
56
57
|
"husky": "9.1.7",
|
|
57
|
-
"
|
|
58
|
+
"playwright": "1.63.0",
|
|
58
59
|
"three": "0.186.0",
|
|
59
|
-
"tsdown": "0.
|
|
60
|
+
"tsdown": "0.23.0",
|
|
60
61
|
"typescript": "7.0.2",
|
|
61
|
-
"vitest": "5.0.
|
|
62
|
+
"vitest": "5.0.2"
|
|
62
63
|
},
|
|
63
64
|
"peerDependencies": {
|
|
64
65
|
"@types/three": "~0.186.0",
|