three-gamepad-controls 0.18.0 → 0.20.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 +4 -1
- package/dist/gamepad-arcball-controls.d.ts +10 -19
- package/dist/gamepad-arcball-controls.js +39 -20
- package/dist/gamepad-drag-controls.d.ts +7 -21
- package/dist/gamepad-drag-controls.js +19 -13
- package/dist/gamepad-first-person-controls.d.ts +8 -19
- package/dist/gamepad-first-person-controls.js +29 -24
- package/dist/gamepad-fly-controls.d.ts +7 -18
- package/dist/gamepad-fly-controls.js +24 -13
- package/dist/gamepad-input.d.ts +10 -69
- package/dist/gamepad-input.js +18 -78
- package/dist/gamepad-manager.js +1 -1
- package/dist/gamepad-map-controls.js +17 -5
- package/dist/gamepad-orbit-controls.d.ts +10 -19
- package/dist/gamepad-orbit-controls.js +23 -16
- package/dist/gamepad-pointer-lock-controls.d.ts +7 -21
- package/dist/gamepad-pointer-lock-controls.js +22 -16
- package/dist/gamepad-stick-processing.d.ts +165 -0
- package/dist/gamepad-stick-processing.js +176 -0
- package/dist/gamepad-trackball-controls.d.ts +10 -19
- package/dist/gamepad-trackball-controls.js +34 -33
- package/dist/gamepad-transform-controls.d.ts +4 -13
- package/dist/gamepad-transform-controls.js +12 -8
- package/dist/index.d.ts +3 -2
- package/dist/index.js +2 -1
- package/package.json +1 -1
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
//#region src/gamepad-stick-processing.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Geometry used when processing two-dimensional stick values.
|
|
4
|
+
*
|
|
5
|
+
* Axial processing transforms each component independently. Radial processing
|
|
6
|
+
* transforms vector magnitude while preserving direction.
|
|
7
|
+
*/
|
|
8
|
+
type GamepadStickProcessingMode = "axial" | "radial";
|
|
9
|
+
/**
|
|
10
|
+
* Built-in response curve applied to stick components or magnitude.
|
|
11
|
+
*/
|
|
12
|
+
type GamepadResponseCurve = "linear" | "quadratic" | "cubic";
|
|
13
|
+
/**
|
|
14
|
+
* Two-dimensional gamepad stick value.
|
|
15
|
+
*/
|
|
16
|
+
type GamepadStick = {
|
|
17
|
+
/**
|
|
18
|
+
* Horizontal stick component.
|
|
19
|
+
*/
|
|
20
|
+
x: number;
|
|
21
|
+
/**
|
|
22
|
+
* Vertical stick component.
|
|
23
|
+
*/
|
|
24
|
+
y: number;
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Pure, stateless transformation applied to a gamepad stick.
|
|
28
|
+
*
|
|
29
|
+
* Implementations must not mutate `value`. Stateful processing such as
|
|
30
|
+
* smoothing belongs in a separate lifecycle-aware abstraction.
|
|
31
|
+
*/
|
|
32
|
+
type GamepadStickProcessor = {
|
|
33
|
+
/**
|
|
34
|
+
* Transforms one stick value.
|
|
35
|
+
*
|
|
36
|
+
* @param value - Input value from the previous processor.
|
|
37
|
+
* @returns Processed stick value.
|
|
38
|
+
*/
|
|
39
|
+
process(value: Readonly<GamepadStick>): GamepadStick;
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Ordered, reusable sequence of stateless stick processors.
|
|
43
|
+
*/
|
|
44
|
+
type GamepadStickPipeline = GamepadStickProcessor & {
|
|
45
|
+
/**
|
|
46
|
+
* Processors in execution order.
|
|
47
|
+
*/
|
|
48
|
+
readonly processors: readonly GamepadStickProcessor[];
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* Options for {@link createGamepadDeadzoneProcessor}.
|
|
52
|
+
*/
|
|
53
|
+
type GamepadDeadzoneProcessorOptions = {
|
|
54
|
+
/**
|
|
55
|
+
* Dead zone threshold.
|
|
56
|
+
* @default 0.1
|
|
57
|
+
*/
|
|
58
|
+
threshold?: number;
|
|
59
|
+
/**
|
|
60
|
+
* Whether to process each component or the vector magnitude.
|
|
61
|
+
* @default "axial"
|
|
62
|
+
*/
|
|
63
|
+
mode?: GamepadStickProcessingMode;
|
|
64
|
+
/**
|
|
65
|
+
* Whether to remap values outside the dead zone to the full output range.
|
|
66
|
+
* @default false
|
|
67
|
+
*/
|
|
68
|
+
rescale?: boolean;
|
|
69
|
+
};
|
|
70
|
+
/**
|
|
71
|
+
* Options for {@link createGamepadResponseCurveProcessor}.
|
|
72
|
+
*/
|
|
73
|
+
type GamepadResponseCurveProcessorOptions = {
|
|
74
|
+
/**
|
|
75
|
+
* Curve used to transform values in the normalized input range.
|
|
76
|
+
*/
|
|
77
|
+
curve: GamepadResponseCurve;
|
|
78
|
+
/**
|
|
79
|
+
* Whether to process each component or the vector magnitude.
|
|
80
|
+
*/
|
|
81
|
+
mode: GamepadStickProcessingMode;
|
|
82
|
+
};
|
|
83
|
+
/**
|
|
84
|
+
* Options for {@link createGamepadInversionProcessor}.
|
|
85
|
+
*/
|
|
86
|
+
type GamepadInversionProcessorOptions = {
|
|
87
|
+
/**
|
|
88
|
+
* Whether to invert the horizontal component.
|
|
89
|
+
* @default false
|
|
90
|
+
*/
|
|
91
|
+
invertX?: boolean;
|
|
92
|
+
/**
|
|
93
|
+
* Whether to invert the vertical component.
|
|
94
|
+
* @default false
|
|
95
|
+
*/
|
|
96
|
+
invertY?: boolean;
|
|
97
|
+
};
|
|
98
|
+
/**
|
|
99
|
+
* Partial binding for a two-dimensional stick action.
|
|
100
|
+
*
|
|
101
|
+
* Omitted fields inherit the action-specific defaults.
|
|
102
|
+
*/
|
|
103
|
+
type GamepadStickBindingOptions = {
|
|
104
|
+
/**
|
|
105
|
+
* Axis index used as the horizontal component.
|
|
106
|
+
*/
|
|
107
|
+
xAxis?: number;
|
|
108
|
+
/**
|
|
109
|
+
* Axis index used as the vertical component.
|
|
110
|
+
*/
|
|
111
|
+
yAxis?: number;
|
|
112
|
+
/**
|
|
113
|
+
* Stateless processing pipeline for this action.
|
|
114
|
+
*/
|
|
115
|
+
pipeline?: GamepadStickPipeline;
|
|
116
|
+
};
|
|
117
|
+
/**
|
|
118
|
+
* Fully resolved binding used when reading a two-dimensional stick action.
|
|
119
|
+
*/
|
|
120
|
+
type GamepadStickBinding = Required<GamepadStickBindingOptions>;
|
|
121
|
+
/**
|
|
122
|
+
* Creates an ordered pipeline from stateless stick processors.
|
|
123
|
+
*
|
|
124
|
+
* The processor list is copied once. Processor errors are not caught, and a
|
|
125
|
+
* processor's result is passed directly to the next processor.
|
|
126
|
+
*
|
|
127
|
+
* @param processors - Processors in execution order.
|
|
128
|
+
* @returns Reusable stick pipeline.
|
|
129
|
+
*/
|
|
130
|
+
declare const createGamepadStickPipeline: (...processors: readonly GamepadStickProcessor[]) => GamepadStickPipeline;
|
|
131
|
+
/**
|
|
132
|
+
* Creates an axial or radial dead zone processor.
|
|
133
|
+
*
|
|
134
|
+
* @param options - Optional dead zone configuration.
|
|
135
|
+
* @returns Stateless dead zone processor.
|
|
136
|
+
*/
|
|
137
|
+
declare const createGamepadDeadzoneProcessor: (options?: GamepadDeadzoneProcessorOptions) => GamepadStickProcessor;
|
|
138
|
+
/**
|
|
139
|
+
* Creates an axial or radial response curve processor.
|
|
140
|
+
*
|
|
141
|
+
* @param options - Response curve configuration.
|
|
142
|
+
* @returns Stateless response curve processor.
|
|
143
|
+
*/
|
|
144
|
+
declare const createGamepadResponseCurveProcessor: (options: GamepadResponseCurveProcessorOptions) => GamepadStickProcessor;
|
|
145
|
+
/**
|
|
146
|
+
* Creates a processor that independently inverts stick components.
|
|
147
|
+
*
|
|
148
|
+
* @param options - Optional inversion configuration.
|
|
149
|
+
* @returns Stateless inversion processor.
|
|
150
|
+
*/
|
|
151
|
+
declare const createGamepadInversionProcessor: (options?: GamepadInversionProcessorOptions) => GamepadStickProcessor;
|
|
152
|
+
/**
|
|
153
|
+
* Historical stick processing used when no custom pipeline is supplied.
|
|
154
|
+
*/
|
|
155
|
+
declare const DEFAULT_GAMEPAD_STICK_PIPELINE: GamepadStickPipeline;
|
|
156
|
+
/**
|
|
157
|
+
* Resolves a partial stick binding over an action-specific default.
|
|
158
|
+
*
|
|
159
|
+
* @param defaults - Complete default binding.
|
|
160
|
+
* @param options - Optional binding overrides.
|
|
161
|
+
* @returns Complete resolved binding.
|
|
162
|
+
*/
|
|
163
|
+
declare const resolveGamepadStickBinding: (defaults: GamepadStickBinding, options?: GamepadStickBindingOptions) => GamepadStickBinding;
|
|
164
|
+
//#endregion
|
|
165
|
+
export { DEFAULT_GAMEPAD_STICK_PIPELINE, GamepadDeadzoneProcessorOptions, GamepadInversionProcessorOptions, GamepadResponseCurve, GamepadResponseCurveProcessorOptions, GamepadStick, GamepadStickBinding, GamepadStickBindingOptions, GamepadStickPipeline, GamepadStickProcessingMode, GamepadStickProcessor, createGamepadDeadzoneProcessor, createGamepadInversionProcessor, createGamepadResponseCurveProcessor, createGamepadStickPipeline, resolveGamepadStickBinding };
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
//#region src/gamepad-stick-processing.ts
|
|
2
|
+
const DEFAULT_DEADZONE_PROCESSOR_OPTIONS = {
|
|
3
|
+
threshold: .1,
|
|
4
|
+
mode: "axial",
|
|
5
|
+
rescale: false
|
|
6
|
+
};
|
|
7
|
+
const DEFAULT_INVERSION_PROCESSOR_OPTIONS = {
|
|
8
|
+
invertX: false,
|
|
9
|
+
invertY: false
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Returns a canonical stick result and preserves the original value when
|
|
13
|
+
* processing produced no change.
|
|
14
|
+
*
|
|
15
|
+
* @param source - Original stick value.
|
|
16
|
+
* @param x - Processed horizontal component.
|
|
17
|
+
* @param y - Processed vertical component.
|
|
18
|
+
* @returns Canonical processed stick value.
|
|
19
|
+
*/
|
|
20
|
+
const createGamepadStickResult = (source, x, y) => {
|
|
21
|
+
const canonicalX = x === 0 ? 0 : x;
|
|
22
|
+
const canonicalY = y === 0 ? 0 : y;
|
|
23
|
+
if (canonicalX === source.x && canonicalY === source.y && !Object.is(source.x, -0) && !Object.is(source.y, -0)) return source;
|
|
24
|
+
return {
|
|
25
|
+
x: canonicalX,
|
|
26
|
+
y: canonicalY
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Transforms the magnitude of a signed scalar while preserving its sign.
|
|
31
|
+
*
|
|
32
|
+
* @param value - Signed scalar value.
|
|
33
|
+
* @param mapMagnitude - Magnitude transformation.
|
|
34
|
+
* @returns Transformed signed value.
|
|
35
|
+
*/
|
|
36
|
+
const mapGamepadSignedMagnitude = (value, mapMagnitude) => {
|
|
37
|
+
if (value === 0) return 0;
|
|
38
|
+
return Math.sign(value) * mapMagnitude(Math.abs(value));
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* Transforms stick magnitude while preserving vector direction.
|
|
42
|
+
*
|
|
43
|
+
* @param value - Stick value to transform.
|
|
44
|
+
* @param mapMagnitude - Magnitude transformation.
|
|
45
|
+
* @returns Stick with transformed magnitude.
|
|
46
|
+
*/
|
|
47
|
+
const mapGamepadStickMagnitude = (value, mapMagnitude) => {
|
|
48
|
+
const magnitude = Math.hypot(value.x, value.y);
|
|
49
|
+
if (magnitude === 0) return createGamepadStickResult(value, 0, 0);
|
|
50
|
+
const mappedMagnitude = mapMagnitude(magnitude);
|
|
51
|
+
if (mappedMagnitude === magnitude) return createGamepadStickResult(value, value.x, value.y);
|
|
52
|
+
if (mappedMagnitude === 0) return createGamepadStickResult(value, 0, 0);
|
|
53
|
+
const scale = mappedMagnitude / magnitude;
|
|
54
|
+
return createGamepadStickResult(value, value.x * scale, value.y * scale);
|
|
55
|
+
};
|
|
56
|
+
/**
|
|
57
|
+
* Applies a dead zone and remaps the remaining magnitude to `[0, 1]`.
|
|
58
|
+
*
|
|
59
|
+
* @param magnitude - Non-negative input magnitude.
|
|
60
|
+
* @param threshold - Dead zone size.
|
|
61
|
+
* @returns Rescaled magnitude, or `0` when inside a fully closed dead zone.
|
|
62
|
+
*/
|
|
63
|
+
const rescaleGamepadDeadzoneMagnitude = (magnitude, threshold) => {
|
|
64
|
+
if (magnitude <= threshold || threshold >= 1) return 0;
|
|
65
|
+
return Math.min((magnitude - threshold) / (1 - threshold), 1);
|
|
66
|
+
};
|
|
67
|
+
/**
|
|
68
|
+
* Applies a built-in curve to a normalized magnitude.
|
|
69
|
+
*
|
|
70
|
+
* Magnitudes above `1` remain unchanged so response curves do not implicitly
|
|
71
|
+
* clamp or normalize custom processor output.
|
|
72
|
+
*
|
|
73
|
+
* @param magnitude - Non-negative component or vector magnitude.
|
|
74
|
+
* @param curve - Curve to apply.
|
|
75
|
+
* @returns Curved magnitude.
|
|
76
|
+
*/
|
|
77
|
+
const applyGamepadResponseCurve = (magnitude, curve) => {
|
|
78
|
+
if (magnitude > 1) return magnitude;
|
|
79
|
+
switch (curve) {
|
|
80
|
+
case "linear": return magnitude;
|
|
81
|
+
case "quadratic": return magnitude ** 2;
|
|
82
|
+
case "cubic": return magnitude ** 3;
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
/**
|
|
86
|
+
* Creates an ordered pipeline from stateless stick processors.
|
|
87
|
+
*
|
|
88
|
+
* The processor list is copied once. Processor errors are not caught, and a
|
|
89
|
+
* processor's result is passed directly to the next processor.
|
|
90
|
+
*
|
|
91
|
+
* @param processors - Processors in execution order.
|
|
92
|
+
* @returns Reusable stick pipeline.
|
|
93
|
+
*/
|
|
94
|
+
const createGamepadStickPipeline = (...processors) => {
|
|
95
|
+
const pipelineProcessors = Object.freeze([...processors]);
|
|
96
|
+
return Object.freeze({
|
|
97
|
+
processors: pipelineProcessors,
|
|
98
|
+
process(value) {
|
|
99
|
+
let processed = value;
|
|
100
|
+
for (const processor of pipelineProcessors) processed = processor.process(processed);
|
|
101
|
+
return processed;
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
};
|
|
105
|
+
/**
|
|
106
|
+
* Creates an axial or radial dead zone processor.
|
|
107
|
+
*
|
|
108
|
+
* @param options - Optional dead zone configuration.
|
|
109
|
+
* @returns Stateless dead zone processor.
|
|
110
|
+
*/
|
|
111
|
+
const createGamepadDeadzoneProcessor = (options) => {
|
|
112
|
+
const { threshold, mode, rescale } = {
|
|
113
|
+
...DEFAULT_DEADZONE_PROCESSOR_OPTIONS,
|
|
114
|
+
...options
|
|
115
|
+
};
|
|
116
|
+
const mapMagnitude = (magnitude) => {
|
|
117
|
+
if (magnitude < threshold) return 0;
|
|
118
|
+
return rescale ? rescaleGamepadDeadzoneMagnitude(magnitude, threshold) : magnitude;
|
|
119
|
+
};
|
|
120
|
+
return Object.freeze({ process(value) {
|
|
121
|
+
if (mode === "axial") return createGamepadStickResult(value, mapGamepadSignedMagnitude(value.x, mapMagnitude), mapGamepadSignedMagnitude(value.y, mapMagnitude));
|
|
122
|
+
return mapGamepadStickMagnitude(value, mapMagnitude);
|
|
123
|
+
} });
|
|
124
|
+
};
|
|
125
|
+
/**
|
|
126
|
+
* Creates an axial or radial response curve processor.
|
|
127
|
+
*
|
|
128
|
+
* @param options - Response curve configuration.
|
|
129
|
+
* @returns Stateless response curve processor.
|
|
130
|
+
*/
|
|
131
|
+
const createGamepadResponseCurveProcessor = (options) => {
|
|
132
|
+
const { curve, mode } = options;
|
|
133
|
+
const mapMagnitude = (magnitude) => applyGamepadResponseCurve(magnitude, curve);
|
|
134
|
+
return Object.freeze({ process(value) {
|
|
135
|
+
if (mode === "axial") return createGamepadStickResult(value, mapGamepadSignedMagnitude(value.x, mapMagnitude), mapGamepadSignedMagnitude(value.y, mapMagnitude));
|
|
136
|
+
return mapGamepadStickMagnitude(value, mapMagnitude);
|
|
137
|
+
} });
|
|
138
|
+
};
|
|
139
|
+
/**
|
|
140
|
+
* Creates a processor that independently inverts stick components.
|
|
141
|
+
*
|
|
142
|
+
* @param options - Optional inversion configuration.
|
|
143
|
+
* @returns Stateless inversion processor.
|
|
144
|
+
*/
|
|
145
|
+
const createGamepadInversionProcessor = (options) => {
|
|
146
|
+
const { invertX, invertY } = {
|
|
147
|
+
...DEFAULT_INVERSION_PROCESSOR_OPTIONS,
|
|
148
|
+
...options
|
|
149
|
+
};
|
|
150
|
+
return Object.freeze({ process(value) {
|
|
151
|
+
if (!invertX && !invertY) return createGamepadStickResult(value, value.x, value.y);
|
|
152
|
+
const x = value.x === 0 ? 0 : invertX ? -value.x : value.x;
|
|
153
|
+
const y = value.y === 0 ? 0 : invertY ? -value.y : value.y;
|
|
154
|
+
return createGamepadStickResult(value, x, y);
|
|
155
|
+
} });
|
|
156
|
+
};
|
|
157
|
+
/**
|
|
158
|
+
* Historical stick processing used when no custom pipeline is supplied.
|
|
159
|
+
*/
|
|
160
|
+
const DEFAULT_GAMEPAD_STICK_PIPELINE = createGamepadStickPipeline(createGamepadDeadzoneProcessor());
|
|
161
|
+
/**
|
|
162
|
+
* Resolves a partial stick binding over an action-specific default.
|
|
163
|
+
*
|
|
164
|
+
* @param defaults - Complete default binding.
|
|
165
|
+
* @param options - Optional binding overrides.
|
|
166
|
+
* @returns Complete resolved binding.
|
|
167
|
+
*/
|
|
168
|
+
const resolveGamepadStickBinding = (defaults, options) => {
|
|
169
|
+
return {
|
|
170
|
+
xAxis: options?.xAxis ?? defaults.xAxis,
|
|
171
|
+
yAxis: options?.yAxis ?? defaults.yAxis,
|
|
172
|
+
pipeline: options?.pipeline ?? defaults.pipeline
|
|
173
|
+
};
|
|
174
|
+
};
|
|
175
|
+
//#endregion
|
|
176
|
+
export { DEFAULT_GAMEPAD_STICK_PIPELINE, createGamepadDeadzoneProcessor, createGamepadInversionProcessor, createGamepadResponseCurveProcessor, createGamepadStickPipeline, resolveGamepadStickBinding };
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { GamepadStickBindingOptions } from "./gamepad-stick-processing.js";
|
|
1
2
|
import { GamepadControls, GamepadControlsOptions } from "./gamepad-controls.js";
|
|
2
3
|
import { TrackballControls } from "three/addons/controls/TrackballControls.js";
|
|
3
4
|
//#region src/gamepad-trackball-controls.d.ts
|
|
@@ -23,30 +24,20 @@ type GamepadTrackballControlsOptions = GamepadControlsOptions & {
|
|
|
23
24
|
*/
|
|
24
25
|
zoomSpeed: number;
|
|
25
26
|
/**
|
|
26
|
-
*
|
|
27
|
-
* @default
|
|
28
|
-
*/
|
|
29
|
-
deadzone: number;
|
|
30
|
-
/**
|
|
31
|
-
* Axis index for **horizontal** trackball rotation.
|
|
32
|
-
* @default 0 - Left stick X
|
|
27
|
+
* Stick binding used for trackball rotation.
|
|
28
|
+
* @default Left stick with the default stick pipeline
|
|
33
29
|
*/
|
|
34
|
-
|
|
30
|
+
rotateStick: GamepadStickBindingOptions;
|
|
35
31
|
/**
|
|
36
|
-
*
|
|
37
|
-
* @default
|
|
32
|
+
* Stick binding used for panning.
|
|
33
|
+
* @default Right stick with the default stick pipeline
|
|
38
34
|
*/
|
|
39
|
-
|
|
35
|
+
panStick: GamepadStickBindingOptions;
|
|
40
36
|
/**
|
|
41
|
-
*
|
|
42
|
-
* @default
|
|
43
|
-
*/
|
|
44
|
-
axisPanX: number;
|
|
45
|
-
/**
|
|
46
|
-
* Axis index for **vertical** panning.
|
|
47
|
-
* @default 3 - Right stick Y
|
|
37
|
+
* Dead zone threshold for analog trigger values.
|
|
38
|
+
* @default 0.1
|
|
48
39
|
*/
|
|
49
|
-
|
|
40
|
+
buttonDeadzone: number;
|
|
50
41
|
/**
|
|
51
42
|
* Button index for zooming **in** (analog trigger value used for proportional zoom).
|
|
52
43
|
* @default 7 - Right trigger
|
|
@@ -1,15 +1,22 @@
|
|
|
1
1
|
import { GAMEPAD_AXIS, GAMEPAD_BUTTON } from "./core.js";
|
|
2
|
+
import { DEFAULT_GAMEPAD_STICK_PIPELINE, resolveGamepadStickBinding } from "./gamepad-stick-processing.js";
|
|
2
3
|
import { GamepadControls } from "./gamepad-controls.js";
|
|
3
4
|
//#region src/gamepad-trackball-controls.ts
|
|
4
5
|
const DEFAULT_TRACKBALL_OPTIONS = {
|
|
5
6
|
rotateSpeed: 1,
|
|
6
7
|
panSpeed: 1,
|
|
7
8
|
zoomSpeed: 1,
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
rotateStick: {
|
|
10
|
+
xAxis: GAMEPAD_AXIS.LeftX,
|
|
11
|
+
yAxis: GAMEPAD_AXIS.LeftY,
|
|
12
|
+
pipeline: DEFAULT_GAMEPAD_STICK_PIPELINE
|
|
13
|
+
},
|
|
14
|
+
panStick: {
|
|
15
|
+
xAxis: GAMEPAD_AXIS.RightX,
|
|
16
|
+
yAxis: GAMEPAD_AXIS.RightY,
|
|
17
|
+
pipeline: DEFAULT_GAMEPAD_STICK_PIPELINE
|
|
18
|
+
},
|
|
19
|
+
buttonDeadzone: .1,
|
|
13
20
|
buttonZoomIn: GAMEPAD_BUTTON.RightTrigger,
|
|
14
21
|
buttonZoomOut: GAMEPAD_BUTTON.LeftTrigger
|
|
15
22
|
};
|
|
@@ -32,7 +39,9 @@ var GamepadTrackballControls = class extends GamepadControls {
|
|
|
32
39
|
this.#controls = controls;
|
|
33
40
|
this.#options = {
|
|
34
41
|
...DEFAULT_TRACKBALL_OPTIONS,
|
|
35
|
-
...options
|
|
42
|
+
...options,
|
|
43
|
+
rotateStick: resolveGamepadStickBinding(DEFAULT_TRACKBALL_OPTIONS.rotateStick, options?.rotateStick),
|
|
44
|
+
panStick: resolveGamepadStickBinding(DEFAULT_TRACKBALL_OPTIONS.panStick, options?.panStick)
|
|
36
45
|
};
|
|
37
46
|
}
|
|
38
47
|
/**
|
|
@@ -41,68 +50,60 @@ var GamepadTrackballControls = class extends GamepadControls {
|
|
|
41
50
|
* @param deltaTime - Seconds since the last frame.
|
|
42
51
|
*/
|
|
43
52
|
onUpdate(deltaTime) {
|
|
44
|
-
const { rotateSpeed, panSpeed, zoomSpeed,
|
|
45
|
-
this.#queueRotation(deltaTime, rotateSpeed,
|
|
46
|
-
this.#queuePan(deltaTime, panSpeed,
|
|
47
|
-
this.#queueZoom(deltaTime, zoomSpeed,
|
|
53
|
+
const { rotateSpeed, panSpeed, zoomSpeed, rotateStick, panStick, buttonDeadzone, buttonZoomIn, buttonZoomOut } = this.#options;
|
|
54
|
+
this.#queueRotation(deltaTime, rotateSpeed, rotateStick);
|
|
55
|
+
this.#queuePan(deltaTime, panSpeed, panStick);
|
|
56
|
+
this.#queueZoom(deltaTime, zoomSpeed, buttonDeadzone, buttonZoomIn, buttonZoomOut);
|
|
48
57
|
}
|
|
49
58
|
/**
|
|
50
59
|
* Queues rotation input into TrackballControls' normalized move state.
|
|
51
60
|
*
|
|
52
61
|
* @param deltaTime - Seconds since the last frame.
|
|
53
62
|
* @param rotateSpeed - User-configured rotation speed multiplier.
|
|
54
|
-
* @param
|
|
55
|
-
* @param axisRotateX - Axis index for horizontal rotation.
|
|
56
|
-
* @param axisRotateY - Axis index for vertical rotation.
|
|
63
|
+
* @param rotateStick - Resolved stick binding for rotation.
|
|
57
64
|
*/
|
|
58
|
-
#queueRotation(deltaTime, rotateSpeed,
|
|
65
|
+
#queueRotation(deltaTime, rotateSpeed, rotateStick) {
|
|
59
66
|
const controls = this.#controls;
|
|
60
67
|
if (controls.noRotate) {
|
|
61
68
|
controls._movePrev.copy(controls._moveCurr);
|
|
62
69
|
controls._lastAngle = 0;
|
|
63
70
|
return;
|
|
64
71
|
}
|
|
65
|
-
const
|
|
66
|
-
|
|
67
|
-
const rotY = input.axis(axisRotateY, { deadzone });
|
|
68
|
-
if (rotX === 0 && rotY === 0) return;
|
|
72
|
+
const rotate = this.gamepadInput.stick(rotateStick.xAxis, rotateStick.yAxis, rotateStick.pipeline);
|
|
73
|
+
if (rotate.x === 0 && rotate.y === 0) return;
|
|
69
74
|
const scale = rotateSpeed * deltaTime * Math.PI;
|
|
70
|
-
controls._moveCurr.x +=
|
|
71
|
-
controls._moveCurr.y += -
|
|
75
|
+
controls._moveCurr.x += rotate.x * scale;
|
|
76
|
+
controls._moveCurr.y += -rotate.y * scale;
|
|
72
77
|
}
|
|
73
78
|
/**
|
|
74
79
|
* Queues pan input into TrackballControls' normalized pan state.
|
|
75
80
|
*
|
|
76
81
|
* @param deltaTime - Seconds since the last frame.
|
|
77
82
|
* @param panSpeed - User-configured pan speed multiplier.
|
|
78
|
-
* @param
|
|
79
|
-
* @param axisPanX - Axis index for horizontal panning.
|
|
80
|
-
* @param axisPanY - Axis index for vertical panning.
|
|
83
|
+
* @param panStick - Resolved stick binding for panning.
|
|
81
84
|
*/
|
|
82
|
-
#queuePan(deltaTime, panSpeed,
|
|
85
|
+
#queuePan(deltaTime, panSpeed, panStick) {
|
|
83
86
|
const controls = this.#controls;
|
|
84
87
|
if (controls.noPan) {
|
|
85
88
|
controls._panStart.copy(controls._panEnd);
|
|
86
89
|
return;
|
|
87
90
|
}
|
|
88
|
-
const
|
|
89
|
-
|
|
90
|
-
const panY = input.axis(axisPanY, { deadzone });
|
|
91
|
-
if (panX === 0 && panY === 0) return;
|
|
91
|
+
const pan = this.gamepadInput.stick(panStick.xAxis, panStick.yAxis, panStick.pipeline);
|
|
92
|
+
if (pan.x === 0 && pan.y === 0) return;
|
|
92
93
|
const scale = panSpeed * deltaTime * this.#getInputDampingFactor();
|
|
93
|
-
controls._panEnd.x +=
|
|
94
|
-
controls._panEnd.y +=
|
|
94
|
+
controls._panEnd.x += pan.x * scale;
|
|
95
|
+
controls._panEnd.y += pan.y * scale;
|
|
95
96
|
}
|
|
96
97
|
/**
|
|
97
98
|
* Queues trigger zoom input into TrackballControls' normalized zoom state.
|
|
98
99
|
*
|
|
99
100
|
* @param deltaTime - Seconds since the last frame.
|
|
100
101
|
* @param zoomSpeed - User-configured zoom speed multiplier.
|
|
101
|
-
* @param
|
|
102
|
+
* @param buttonDeadzone - Trigger dead zone threshold.
|
|
102
103
|
* @param buttonZoomIn - Button index for zooming in.
|
|
103
104
|
* @param buttonZoomOut - Button index for zooming out.
|
|
104
105
|
*/
|
|
105
|
-
#queueZoom(deltaTime, zoomSpeed,
|
|
106
|
+
#queueZoom(deltaTime, zoomSpeed, buttonDeadzone, buttonZoomIn, buttonZoomOut) {
|
|
106
107
|
const controls = this.#controls;
|
|
107
108
|
if (controls.noZoom) {
|
|
108
109
|
controls._zoomStart.copy(controls._zoomEnd);
|
|
@@ -111,7 +112,7 @@ var GamepadTrackballControls = class extends GamepadControls {
|
|
|
111
112
|
const input = this.gamepadInput;
|
|
112
113
|
const triggerIn = input.buttonValue(buttonZoomIn);
|
|
113
114
|
const triggerOut = input.buttonValue(buttonZoomOut);
|
|
114
|
-
if (triggerIn <=
|
|
115
|
+
if (triggerIn <= buttonDeadzone && triggerOut <= buttonDeadzone) return;
|
|
115
116
|
controls._zoomEnd.y += (triggerOut - triggerIn) * zoomSpeed * deltaTime * this.#getInputDampingFactor();
|
|
116
117
|
}
|
|
117
118
|
/**
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { GamepadStickBindingOptions } from "./gamepad-stick-processing.js";
|
|
1
2
|
import { GamepadControls, GamepadControlsOptions } from "./gamepad-controls.js";
|
|
2
3
|
import { TransformControls } from "three/addons/controls/TransformControls.js";
|
|
3
4
|
//#region src/gamepad-transform-controls.d.ts
|
|
@@ -23,20 +24,10 @@ type GamepadTransformControlsOptions = GamepadControlsOptions & {
|
|
|
23
24
|
*/
|
|
24
25
|
scaleSpeed: number;
|
|
25
26
|
/**
|
|
26
|
-
*
|
|
27
|
-
* @default
|
|
27
|
+
* Stick binding used for translation, rotation, and scaling.
|
|
28
|
+
* @default Left stick with the default stick pipeline
|
|
28
29
|
*/
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Axis index for **horizontal** transform input.
|
|
32
|
-
* @default 0 - Left stick X
|
|
33
|
-
*/
|
|
34
|
-
axisTransformX: number;
|
|
35
|
-
/**
|
|
36
|
-
* Axis index for **vertical** transform input.
|
|
37
|
-
* @default 1 - Left stick Y
|
|
38
|
-
*/
|
|
39
|
-
axisTransformY: number;
|
|
30
|
+
transformStick: GamepadStickBindingOptions;
|
|
40
31
|
/**
|
|
41
32
|
* Button index for selecting translate mode.
|
|
42
33
|
* @default 0 - South face button
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { GAMEPAD_AXIS, GAMEPAD_BUTTON } from "./core.js";
|
|
2
|
+
import { DEFAULT_GAMEPAD_STICK_PIPELINE, resolveGamepadStickBinding } from "./gamepad-stick-processing.js";
|
|
2
3
|
import { GamepadControls } from "./gamepad-controls.js";
|
|
3
4
|
import { Matrix4, Quaternion, Vector2, Vector3 } from "three";
|
|
4
5
|
//#region src/gamepad-transform-controls.ts
|
|
@@ -6,9 +7,11 @@ const DEFAULT_TRANSFORM_OPTIONS = {
|
|
|
6
7
|
translateSpeed: 1,
|
|
7
8
|
rotateSpeed: 1,
|
|
8
9
|
scaleSpeed: 1,
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
transformStick: {
|
|
11
|
+
xAxis: GAMEPAD_AXIS.LeftX,
|
|
12
|
+
yAxis: GAMEPAD_AXIS.LeftY,
|
|
13
|
+
pipeline: DEFAULT_GAMEPAD_STICK_PIPELINE
|
|
14
|
+
},
|
|
12
15
|
buttonTranslate: GAMEPAD_BUTTON.South,
|
|
13
16
|
buttonRotate: GAMEPAD_BUTTON.East,
|
|
14
17
|
buttonScale: GAMEPAD_BUTTON.West,
|
|
@@ -110,7 +113,8 @@ var GamepadTransformControls = class extends GamepadControls {
|
|
|
110
113
|
this.#controls = controls;
|
|
111
114
|
this.#options = {
|
|
112
115
|
...DEFAULT_TRANSFORM_OPTIONS,
|
|
113
|
-
...options
|
|
116
|
+
...options,
|
|
117
|
+
transformStick: resolveGamepadStickBinding(DEFAULT_TRANSFORM_OPTIONS.transformStick, options?.transformStick)
|
|
114
118
|
};
|
|
115
119
|
this.#activeAxisByMode = {
|
|
116
120
|
translate: "X",
|
|
@@ -166,14 +170,14 @@ var GamepadTransformControls = class extends GamepadControls {
|
|
|
166
170
|
this.#endTransform(true);
|
|
167
171
|
return;
|
|
168
172
|
}
|
|
169
|
-
const
|
|
170
|
-
const
|
|
171
|
-
if (
|
|
173
|
+
const { transformStick } = this.#options;
|
|
174
|
+
const transform = this.gamepadInput.stick(transformStick.xAxis, transformStick.yAxis, transformStick.pipeline);
|
|
175
|
+
if (transform.x === 0 && transform.y === 0) {
|
|
172
176
|
this.#endTransform(false);
|
|
173
177
|
return;
|
|
174
178
|
}
|
|
175
179
|
if (!this.#isTransforming && !this.#startTransform()) return;
|
|
176
|
-
if (this.#applyCurrentTransform(deltaTime,
|
|
180
|
+
if (this.#applyCurrentTransform(deltaTime, transform.x, transform.y)) {
|
|
177
181
|
controls.dispatchEvent({ type: "change" });
|
|
178
182
|
controls.dispatchEvent({ type: "objectChange" });
|
|
179
183
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { GAMEPAD_AXIS, GAMEPAD_BUTTON, GamepadAxisKey, GamepadAxisValue, GamepadButtonKey, GamepadButtonValue, MAX_GAMEPAD_INDEX, MIN_GAMEPAD_INDEX } from "./core.js";
|
|
2
|
-
import {
|
|
2
|
+
import { DEFAULT_GAMEPAD_STICK_PIPELINE, GamepadDeadzoneProcessorOptions, GamepadInversionProcessorOptions, GamepadResponseCurve, GamepadResponseCurveProcessorOptions, GamepadStick, GamepadStickBinding, GamepadStickBindingOptions, GamepadStickPipeline, GamepadStickProcessingMode, GamepadStickProcessor, createGamepadDeadzoneProcessor, createGamepadInversionProcessor, createGamepadResponseCurveProcessor, createGamepadStickPipeline, resolveGamepadStickBinding } from "./gamepad-stick-processing.js";
|
|
3
|
+
import { GamepadAxisOptions, GamepadInput, GamepadInputEventMap, GamepadInputOptions } from "./gamepad-input.js";
|
|
3
4
|
import { GamepadControls, GamepadControlsEventMap, GamepadControlsOptions } from "./gamepad-controls.js";
|
|
4
5
|
import { GamepadArcballControls, GamepadArcballControlsOptions } from "./gamepad-arcball-controls.js";
|
|
5
6
|
import { GamepadDragControls, GamepadDragControlsOptions } from "./gamepad-drag-controls.js";
|
|
@@ -10,4 +11,4 @@ import { GamepadMapControls } from "./gamepad-map-controls.js";
|
|
|
10
11
|
import { GamepadPointerLockControls, GamepadPointerLockControlsOptions } from "./gamepad-pointer-lock-controls.js";
|
|
11
12
|
import { GamepadTrackballControls, GamepadTrackballControlsOptions } from "./gamepad-trackball-controls.js";
|
|
12
13
|
import { GamepadTransformControls, GamepadTransformControlsOptions } from "./gamepad-transform-controls.js";
|
|
13
|
-
export { GAMEPAD_AXIS, GAMEPAD_BUTTON, GamepadArcballControls, GamepadArcballControlsOptions, GamepadAxisKey, GamepadAxisOptions, GamepadAxisValue, GamepadButtonKey, GamepadButtonValue, GamepadControls, GamepadControlsEventMap, GamepadControlsOptions,
|
|
14
|
+
export { DEFAULT_GAMEPAD_STICK_PIPELINE, GAMEPAD_AXIS, GAMEPAD_BUTTON, GamepadArcballControls, GamepadArcballControlsOptions, GamepadAxisKey, GamepadAxisOptions, GamepadAxisValue, GamepadButtonKey, GamepadButtonValue, GamepadControls, GamepadControlsEventMap, GamepadControlsOptions, GamepadDeadzoneProcessorOptions, GamepadDragControls, GamepadDragControlsOptions, GamepadFirstPersonControls, GamepadFirstPersonControlsOptions, GamepadFlyControls, GamepadFlyControlsOptions, GamepadInput, GamepadInputEventMap, GamepadInputOptions, GamepadInversionProcessorOptions, GamepadMapControls, GamepadOrbitControls, GamepadOrbitControlsOptions, GamepadPointerLockControls, GamepadPointerLockControlsOptions, GamepadResponseCurve, GamepadResponseCurveProcessorOptions, GamepadStick, GamepadStickBinding, GamepadStickBindingOptions, GamepadStickPipeline, GamepadStickProcessingMode, GamepadStickProcessor, GamepadTrackballControls, GamepadTrackballControlsOptions, GamepadTransformControls, GamepadTransformControlsOptions, MAX_GAMEPAD_INDEX, MIN_GAMEPAD_INDEX, createGamepadDeadzoneProcessor, createGamepadInversionProcessor, createGamepadResponseCurveProcessor, createGamepadStickPipeline, resolveGamepadStickBinding };
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { GAMEPAD_AXIS, GAMEPAD_BUTTON, MAX_GAMEPAD_INDEX, MIN_GAMEPAD_INDEX } from "./core.js";
|
|
2
|
+
import { DEFAULT_GAMEPAD_STICK_PIPELINE, createGamepadDeadzoneProcessor, createGamepadInversionProcessor, createGamepadResponseCurveProcessor, createGamepadStickPipeline, resolveGamepadStickBinding } from "./gamepad-stick-processing.js";
|
|
2
3
|
import { GamepadInput } from "./gamepad-input.js";
|
|
3
4
|
import { GamepadControls } from "./gamepad-controls.js";
|
|
4
5
|
import { GamepadArcballControls } from "./gamepad-arcball-controls.js";
|
|
@@ -10,4 +11,4 @@ import { GamepadMapControls } from "./gamepad-map-controls.js";
|
|
|
10
11
|
import { GamepadPointerLockControls } from "./gamepad-pointer-lock-controls.js";
|
|
11
12
|
import { GamepadTrackballControls } from "./gamepad-trackball-controls.js";
|
|
12
13
|
import { GamepadTransformControls } from "./gamepad-transform-controls.js";
|
|
13
|
-
export { GAMEPAD_AXIS, GAMEPAD_BUTTON, GamepadArcballControls, GamepadControls, GamepadDragControls, GamepadFirstPersonControls, GamepadFlyControls, GamepadInput, GamepadMapControls, GamepadOrbitControls, GamepadPointerLockControls, GamepadTrackballControls, GamepadTransformControls, MAX_GAMEPAD_INDEX, MIN_GAMEPAD_INDEX };
|
|
14
|
+
export { DEFAULT_GAMEPAD_STICK_PIPELINE, GAMEPAD_AXIS, GAMEPAD_BUTTON, GamepadArcballControls, GamepadControls, GamepadDragControls, GamepadFirstPersonControls, GamepadFlyControls, GamepadInput, GamepadMapControls, GamepadOrbitControls, GamepadPointerLockControls, GamepadTrackballControls, GamepadTransformControls, MAX_GAMEPAD_INDEX, MIN_GAMEPAD_INDEX, createGamepadDeadzoneProcessor, createGamepadInversionProcessor, createGamepadResponseCurveProcessor, createGamepadStickPipeline, resolveGamepadStickBinding };
|
package/package.json
CHANGED