@woosh/meep-engine 3.36.0 → 3.37.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/package.json +1 -1
- package/src/engine/input/devices/XRInputDevice.d.ts +51 -23
- package/src/engine/input/devices/XRInputDevice.d.ts.map +1 -1
- package/src/engine/input/devices/XRInputDevice.js +145 -52
- package/src/engine/input/devices/xr/XRGamepadMapping.d.ts +14 -0
- package/src/engine/input/devices/xr/XRGamepadMapping.d.ts.map +1 -0
- package/src/engine/input/devices/xr/XRGamepadMapping.js +9 -0
- package/src/engine/input/devices/xr/XRHandedness.d.ts +15 -0
- package/src/engine/input/devices/xr/XRHandedness.d.ts.map +1 -0
- package/src/engine/input/devices/xr/XRHandedness.js +10 -0
- package/src/engine/input/devices/xr/XRInputAction.d.ts +24 -11
- package/src/engine/input/devices/xr/XRInputAction.d.ts.map +1 -1
- package/src/engine/input/devices/xr/XRInputAction.js +55 -24
- package/src/engine/input/devices/xr/XRInputButton.d.ts +7 -9
- package/src/engine/input/devices/xr/XRInputButton.d.ts.map +1 -1
- package/src/engine/input/devices/xr/XRInputButton.js +18 -8
- package/src/engine/input/devices/xr/XRInputCoordinates.d.ts +11 -3
- package/src/engine/input/devices/xr/XRInputCoordinates.d.ts.map +1 -1
- package/src/engine/input/devices/xr/XRInputCoordinates.js +17 -3
- package/src/engine/input/devices/xr/XRInputHandle.d.ts +41 -11
- package/src/engine/input/devices/xr/XRInputHandle.d.ts.map +1 -1
- package/src/engine/input/devices/xr/XRInputHandle.js +129 -32
- package/src/engine/input/devices/xr/XRInputPose.d.ts +41 -5
- package/src/engine/input/devices/xr/XRInputPose.d.ts.map +1 -1
- package/src/engine/input/devices/xr/XRInputPose.js +57 -16
- package/src/engine/input/devices/xr/XRInputTypes.d.ts +18 -18
- package/src/engine/input/devices/xr/XRInputTypes.js +3 -3
- package/src/engine/input/devices/xr/XRTargetRayMode.d.ts +17 -0
- package/src/engine/input/devices/xr/XRTargetRayMode.d.ts.map +1 -0
- package/src/engine/input/devices/xr/XRTargetRayMode.js +12 -0
- package/src/engine/input/devices/xr/XRVisibilityState.d.ts +15 -0
- package/src/engine/input/devices/xr/XRVisibilityState.d.ts.map +1 -0
- package/src/engine/input/devices/xr/XRVisibilityState.js +10 -0
- package/src/engine/input/ecs/ism/coordinate/InputCoordinateDevice.d.ts +3 -1
- package/src/engine/input/ecs/ism/coordinate/InputCoordinateDevice.d.ts.map +1 -1
- package/src/engine/input/ecs/ism/coordinate/InputCoordinateDevice.js +5 -1
- package/src/engine/input/ecs/ism/device/XRInputDeviceAdapter.d.ts +19 -5
- package/src/engine/input/ecs/ism/device/XRInputDeviceAdapter.d.ts.map +1 -1
- package/src/engine/input/ecs/ism/device/XRInputDeviceAdapter.js +42 -9
- package/src/engine/input/ecs/ism/device/XR_INPUT_DEVICE_IDS.d.ts +8 -2
- package/src/engine/input/ecs/ism/device/XR_INPUT_DEVICE_IDS.d.ts.map +1 -1
- package/src/engine/input/ecs/ism/device/XR_INPUT_DEVICE_IDS.js +19 -9
- package/src/engine/input/ecs/ism/trigger/InputTriggerXRButton.d.ts +10 -2
- package/src/engine/input/ecs/ism/trigger/InputTriggerXRButton.d.ts.map +1 -1
- package/src/engine/input/ecs/ism/trigger/InputTriggerXRButton.js +12 -2
- package/src/shade/renderer/animation/chunk_pose_accumulator.js +14 -24
- package/src/shade/renderer/animation/skinning/bounds_refresh/shader_meshlet_bounds_reduce.js +16 -15
- package/src/shade/renderer/deferred/indirect/chunk_lpv_sample_light.js +1 -1
- package/src/shade/renderer/gpu_primitive/bvh/GPU_BVH_BUILD_PLAN.md +1123 -1122
- package/src/shade/renderer/gpu_primitive/bvh/PHASE1_HANDOVER.md +202 -201
- package/src/shade/renderer/light/environment/chunk_roughness_to_mip_ratio.js +24 -0
- package/src/shade/renderer/light/environment/chunk_sphere_probe_roughness_to_lod.js +2 -25
- package/src/shade/renderer/light/environment/shader_project_environment_sh.d.ts +2 -2
- package/src/shade/renderer/light/environment/shader_project_environment_sh.d.ts.map +1 -1
- package/src/shade/renderer/light/environment/shader_project_environment_sh.js +50 -19
- package/src/shade/renderer/particles/DESIGN.md +1 -1
- package/src/shade/renderer/particles/bounds/chunk_particle_bounds.js +10 -9
- package/src/shade/renderer/scene/shader_bvh_extract_instance_leaves.js +10 -8
- package/src/shade/renderer/shader/chunk/atomic/chunk_atomic_add_f32_storage.js +25 -0
- package/src/shade/renderer/shader/chunk/atomic/chunk_atomic_max_f32_storage.js +28 -0
- package/src/shade/renderer/shader/chunk/atomic/chunk_atomic_min_f32_storage.js +28 -0
- package/src/shade/renderer/shader/chunk/geometry/plane/{plane_ray_raycast.js → chunk_plane_ray_raycast.js} +1 -1
- package/src/shade/renderer/shadow/map/csm/shader/shader_csm_caster_range.js +3 -3
- package/src/shade/renderer/animation/skinning/bounds_refresh/chunk_aabb_atomic_f32.js +0 -59
|
@@ -1,46 +1,75 @@
|
|
|
1
|
+
import { assert } from "../../../../core/assert.js";
|
|
1
2
|
import Signal from "../../../../core/events/signal/Signal.js";
|
|
2
3
|
import { Vector1 } from "../../../../core/geom/Vector1.js";
|
|
3
4
|
import { XRInputValueSource } from "./XRInputValueSource.js";
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
|
-
*
|
|
7
|
-
*
|
|
7
|
+
* Native interaction lifecycle, independent of pressure.
|
|
8
|
+
* @readonly
|
|
9
|
+
* @enum {number}
|
|
10
|
+
*/
|
|
11
|
+
const InteractionState = {
|
|
12
|
+
Idle: 0,
|
|
13
|
+
Started: 1,
|
|
14
|
+
Completed: 2
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Observable amount of a select/squeeze action, in [0, 1]. Read {@link x} and subscribe to
|
|
19
|
+
* {@link onChanged} as with any Vector1. The device owns mutation.
|
|
8
20
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
21
|
+
* {@link valueSource} identifies a native button amount or an event-derived 0/1 value.
|
|
22
|
+
* {@link completed} fires on native action completion; {@link cancelled} fires when an unfinished
|
|
23
|
+
* interaction ends or is interrupted. Each interaction has at most one outcome. Amount changes alone
|
|
24
|
+
* do not complete or cancel an action.
|
|
12
25
|
*/
|
|
13
26
|
export class XRInputAction extends Vector1 {
|
|
14
|
-
/**
|
|
27
|
+
/**
|
|
28
|
+
* Successful native action completion. Dispatches no arguments.
|
|
29
|
+
* @readonly
|
|
30
|
+
* @type {Signal}
|
|
31
|
+
*/
|
|
15
32
|
completed = new Signal();
|
|
16
33
|
|
|
17
|
-
/**
|
|
34
|
+
/**
|
|
35
|
+
* An unfinished interaction ended or was interrupted. Dispatches no arguments.
|
|
36
|
+
* @readonly
|
|
37
|
+
* @type {Signal}
|
|
38
|
+
*/
|
|
18
39
|
cancelled = new Signal();
|
|
19
40
|
|
|
20
|
-
/**
|
|
41
|
+
/**
|
|
42
|
+
* Origin of the current amount. Do not modify directly.
|
|
43
|
+
* @type {XRInputValueSource}
|
|
44
|
+
*/
|
|
21
45
|
valueSource = XRInputValueSource.Unavailable;
|
|
22
46
|
|
|
23
|
-
|
|
24
|
-
#interaction = 0;
|
|
47
|
+
#interaction = InteractionState.Idle;
|
|
25
48
|
|
|
26
49
|
#cancelled = false;
|
|
27
50
|
|
|
28
51
|
/**
|
|
52
|
+
* Store the supplied amount and its source.
|
|
29
53
|
* @internal
|
|
30
|
-
* @param {
|
|
31
|
-
* @param {
|
|
54
|
+
* @param {number} [value=0]
|
|
55
|
+
* @param {XRInputValueSource} [source=XRInputValueSource.Unavailable]
|
|
32
56
|
*/
|
|
33
|
-
update(
|
|
57
|
+
update(value = 0, source = XRInputValueSource.Unavailable) {
|
|
58
|
+
assert.greaterThanOrEqual(value, 0, 'value >= 0');
|
|
59
|
+
assert.lessThanOrEqual(value, 1, 'value <= 1');
|
|
60
|
+
assert.enum(source, XRInputValueSource, 'source');
|
|
61
|
+
|
|
34
62
|
this.valueSource = source;
|
|
35
|
-
this.set(
|
|
63
|
+
this.set(value);
|
|
36
64
|
}
|
|
37
65
|
|
|
38
66
|
/** @internal Called only for a native start, never inferred from the amount. */
|
|
39
67
|
begin() {
|
|
40
|
-
if (this.#interaction !==
|
|
68
|
+
if (this.#interaction !== InteractionState.Idle) {
|
|
41
69
|
return;
|
|
42
70
|
}
|
|
43
|
-
|
|
71
|
+
|
|
72
|
+
this.#interaction = InteractionState.Started;
|
|
44
73
|
if (this.valueSource === XRInputValueSource.Action) {
|
|
45
74
|
this.set(1);
|
|
46
75
|
}
|
|
@@ -48,20 +77,23 @@ export class XRInputAction extends Vector1 {
|
|
|
48
77
|
|
|
49
78
|
/** @internal A completion without an observed start is not replayed after a rebind/interruption. */
|
|
50
79
|
complete() {
|
|
51
|
-
if (this.#interaction !==
|
|
80
|
+
if (this.#interaction !== InteractionState.Started) {
|
|
52
81
|
return;
|
|
53
82
|
}
|
|
54
|
-
|
|
83
|
+
|
|
84
|
+
this.#interaction = InteractionState.Completed;
|
|
55
85
|
this.completed.send0();
|
|
56
86
|
}
|
|
57
87
|
|
|
58
88
|
/** @internal */
|
|
59
89
|
end() {
|
|
60
|
-
const cancelled = this.#interaction ===
|
|
61
|
-
this.#interaction =
|
|
90
|
+
const cancelled = this.#interaction === InteractionState.Started;
|
|
91
|
+
this.#interaction = InteractionState.Idle;
|
|
92
|
+
|
|
62
93
|
if (this.valueSource === XRInputValueSource.Action) {
|
|
63
94
|
this.set(0);
|
|
64
95
|
}
|
|
96
|
+
|
|
65
97
|
if (cancelled) {
|
|
66
98
|
this.cancelled.send0();
|
|
67
99
|
}
|
|
@@ -69,10 +101,9 @@ export class XRInputAction extends Vector1 {
|
|
|
69
101
|
|
|
70
102
|
/** @internal Stage cancellation so the whole handle can become neutral before its notification. */
|
|
71
103
|
reset() {
|
|
72
|
-
this.#cancelled = this.#cancelled || this.#interaction ===
|
|
73
|
-
this.#interaction =
|
|
74
|
-
this.
|
|
75
|
-
this.set(0);
|
|
104
|
+
this.#cancelled = this.#cancelled || this.#interaction === InteractionState.Started;
|
|
105
|
+
this.#interaction = InteractionState.Idle;
|
|
106
|
+
this.update();
|
|
76
107
|
}
|
|
77
108
|
|
|
78
109
|
/** @internal */
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* One raw GamepadButton: its
|
|
3
|
-
* pressed is
|
|
4
|
-
* The device owns mutation. Switches and onChanged
|
|
2
|
+
* One raw GamepadButton: its amount in [0, 1] and its native pressed/touched switches.
|
|
3
|
+
* {@link pressed} is independent of {@link x}; a partially depressed trigger need not be pressed.
|
|
4
|
+
* The device owns mutation. Switches and {@link onChanged} retain their identity across source replacement.
|
|
5
5
|
*/
|
|
6
6
|
export class XRInputButton extends Vector1 {
|
|
7
7
|
/** @readonly */
|
|
@@ -12,13 +12,11 @@ export class XRInputButton extends Vector1 {
|
|
|
12
12
|
* Stage binary state while updating the scalar. All numeric channels and poses are sampled before
|
|
13
13
|
* the device calls flushSwitches, so an input-map action can read the corresponding amount.
|
|
14
14
|
* @internal
|
|
15
|
-
* @param {
|
|
15
|
+
* @param {number} [value=0]
|
|
16
|
+
* @param {boolean} [pressed=false]
|
|
17
|
+
* @param {boolean} [touched=false]
|
|
16
18
|
*/
|
|
17
|
-
update(
|
|
18
|
-
value: number;
|
|
19
|
-
pressed: boolean;
|
|
20
|
-
touched: boolean;
|
|
21
|
-
} | undefined): void;
|
|
19
|
+
update(value?: number, pressed?: boolean, touched?: boolean): void;
|
|
22
20
|
/** @internal */
|
|
23
21
|
flushSwitches(): void;
|
|
24
22
|
#private;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"XRInputButton.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/input/devices/xr/XRInputButton.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"XRInputButton.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/input/devices/xr/XRInputButton.js"],"names":[],"mappings":"AAIA;;;;GAIG;AACH;IACI,gBAAgB;IAChB,oCAAkC;IAElC,gBAAgB;IAChB,oCAAkC;IAKlC;;;;;;;OAOG;IACH,eAJW,MAAM,YACN,OAAO,YACP,OAAO,QAWjB;IAED,gBAAgB;IAChB,sBAYC;;CACJ;wBAnDuB,kCAAkC;kCACxB,yBAAyB"}
|
|
@@ -1,14 +1,16 @@
|
|
|
1
|
+
import { assert } from "../../../../core/assert.js";
|
|
1
2
|
import { Vector1 } from "../../../../core/geom/Vector1.js";
|
|
2
3
|
import { InputDeviceSwitch } from "../InputDeviceSwitch.js";
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
|
-
* One raw GamepadButton: its
|
|
6
|
-
* pressed is
|
|
7
|
-
* The device owns mutation. Switches and onChanged
|
|
6
|
+
* One raw GamepadButton: its amount in [0, 1] and its native pressed/touched switches.
|
|
7
|
+
* {@link pressed} is independent of {@link x}; a partially depressed trigger need not be pressed.
|
|
8
|
+
* The device owns mutation. Switches and {@link onChanged} retain their identity across source replacement.
|
|
8
9
|
*/
|
|
9
10
|
export class XRInputButton extends Vector1 {
|
|
10
11
|
/** @readonly */
|
|
11
12
|
pressed = new InputDeviceSwitch();
|
|
13
|
+
|
|
12
14
|
/** @readonly */
|
|
13
15
|
touched = new InputDeviceSwitch();
|
|
14
16
|
|
|
@@ -19,12 +21,19 @@ export class XRInputButton extends Vector1 {
|
|
|
19
21
|
* Stage binary state while updating the scalar. All numeric channels and poses are sampled before
|
|
20
22
|
* the device calls flushSwitches, so an input-map action can read the corresponding amount.
|
|
21
23
|
* @internal
|
|
22
|
-
* @param {
|
|
24
|
+
* @param {number} [value=0]
|
|
25
|
+
* @param {boolean} [pressed=false]
|
|
26
|
+
* @param {boolean} [touched=false]
|
|
23
27
|
*/
|
|
24
|
-
update(
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
+
update(value = 0, pressed = false, touched = false) {
|
|
29
|
+
assert.greaterThanOrEqual(value, 0, 'value >= 0');
|
|
30
|
+
assert.lessThanOrEqual(value, 1, 'value <= 1');
|
|
31
|
+
assert.isBoolean(pressed, 'pressed');
|
|
32
|
+
assert.isBoolean(touched, 'touched');
|
|
33
|
+
|
|
34
|
+
this.#pressed = pressed;
|
|
35
|
+
this.#touched = touched;
|
|
36
|
+
this.set(value);
|
|
28
37
|
}
|
|
29
38
|
|
|
30
39
|
/** @internal */
|
|
@@ -34,6 +43,7 @@ export class XRInputButton extends Vector1 {
|
|
|
34
43
|
} else {
|
|
35
44
|
this.pressed.release();
|
|
36
45
|
}
|
|
46
|
+
|
|
37
47
|
if (this.#touched) {
|
|
38
48
|
this.touched.press();
|
|
39
49
|
} else {
|
|
@@ -1,9 +1,17 @@
|
|
|
1
|
-
/**
|
|
1
|
+
/**
|
|
2
|
+
* Code for a raw button's scalar amount. Use InputTriggerXRButton for pressed/touched switches.
|
|
3
|
+
* @param {number} index Native button index.
|
|
4
|
+
* @returns {number}
|
|
5
|
+
*/
|
|
2
6
|
export function xr_input_button_coordinate(index: number): number;
|
|
3
|
-
/**
|
|
7
|
+
/**
|
|
8
|
+
* Code for a raw axis, without stick calibration.
|
|
9
|
+
* @param {number} index Native axis index.
|
|
10
|
+
* @returns {number}
|
|
11
|
+
*/
|
|
4
12
|
export function xr_input_axis_coordinate(index: number): number;
|
|
5
13
|
/**
|
|
6
|
-
* Stable codes used in serialized input maps.
|
|
14
|
+
* Stable coordinate codes used in serialized input maps.
|
|
7
15
|
*/
|
|
8
16
|
export type XRInputCoordinates = number;
|
|
9
17
|
export namespace XRInputCoordinates {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"XRInputCoordinates.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/input/devices/xr/XRInputCoordinates.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"XRInputCoordinates.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/input/devices/xr/XRInputCoordinates.js"],"names":[],"mappings":"AAcA;;;;GAIG;AACH,kDAHW,MAAM,GACJ,MAAM,CAMlB;AAED;;;;GAIG;AACH,gDAHW,MAAM,GACJ,MAAM,CAMlB;;;;iCA7BS,MAAM"}
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { assert } from "../../../../core/assert.js";
|
|
2
2
|
|
|
3
|
-
/**
|
|
3
|
+
/**
|
|
4
|
+
* Stable coordinate codes used in serialized input maps.
|
|
5
|
+
* @readonly
|
|
6
|
+
* @enum {number}
|
|
7
|
+
*/
|
|
4
8
|
export const XRInputCoordinates = {
|
|
5
9
|
select: 0,
|
|
6
10
|
squeeze: 1,
|
|
@@ -8,14 +12,24 @@ export const XRInputCoordinates = {
|
|
|
8
12
|
touchpad: 3
|
|
9
13
|
};
|
|
10
14
|
|
|
11
|
-
/**
|
|
15
|
+
/**
|
|
16
|
+
* Code for a raw button's scalar amount. Use InputTriggerXRButton for pressed/touched switches.
|
|
17
|
+
* @param {number} index Native button index.
|
|
18
|
+
* @returns {number}
|
|
19
|
+
*/
|
|
12
20
|
export function xr_input_button_coordinate(index) {
|
|
13
21
|
assert.isNonNegativeInteger(index, 'index');
|
|
22
|
+
|
|
14
23
|
return 4 + index * 2;
|
|
15
24
|
}
|
|
16
25
|
|
|
17
|
-
/**
|
|
26
|
+
/**
|
|
27
|
+
* Code for a raw axis, without stick calibration.
|
|
28
|
+
* @param {number} index Native axis index.
|
|
29
|
+
* @returns {number}
|
|
30
|
+
*/
|
|
18
31
|
export function xr_input_axis_coordinate(index) {
|
|
19
32
|
assert.isNonNegativeInteger(index, 'index');
|
|
33
|
+
|
|
20
34
|
return 5 + index * 2;
|
|
21
35
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* One XR input source, or a persistent handedness slot owned by XRInputDevice.
|
|
3
3
|
* All control objects survive disconnection. Consumers read them; the device owns mutation.
|
|
4
|
-
*
|
|
5
|
-
* buttons/axes, while select/squeeze
|
|
4
|
+
* With xr-standard, select/squeeze read native button amounts. Other mappings remain available through
|
|
5
|
+
* buttons/axes, while select/squeeze report 0/1 from native events; check their valueSource.
|
|
6
6
|
*
|
|
7
7
|
* Button indices 0/1 are select/squeeze; axes 0/1 are touchpad and 2/3 thumbstick in xr-standard.
|
|
8
8
|
* Placeholder entries are allowed by WebXR: a zero entry does not prove that a control exists.
|
|
@@ -12,33 +12,63 @@ export class XRInputHandle {
|
|
|
12
12
|
readonly select: XRInputAction;
|
|
13
13
|
/** @readonly */
|
|
14
14
|
readonly squeeze: XRInputAction;
|
|
15
|
-
/**
|
|
15
|
+
/**
|
|
16
|
+
* Raw native buttons. Use {@link getButton} for an index that may not exist yet.
|
|
17
|
+
* @readonly
|
|
18
|
+
* @type {XRInputButton[]}
|
|
19
|
+
*/
|
|
16
20
|
readonly buttons: XRInputButton[];
|
|
17
|
-
/**
|
|
21
|
+
/**
|
|
22
|
+
* Raw native axes in [-1, 1]. Use {@link getAxis} for an index that may not exist yet.
|
|
23
|
+
* @readonly
|
|
24
|
+
* @type {Vector1[]}
|
|
25
|
+
*/
|
|
18
26
|
readonly axes: Vector1[];
|
|
19
|
-
/**
|
|
27
|
+
/**
|
|
28
|
+
* Calibrated xr-standard thumbstick, +x right and +y down.
|
|
29
|
+
* @readonly
|
|
30
|
+
*/
|
|
20
31
|
readonly thumbstick: GamepadStick;
|
|
21
|
-
/**
|
|
32
|
+
/**
|
|
33
|
+
* Uncalibrated xr-standard touchpad coordinates, +x right and +y down.
|
|
34
|
+
* @readonly
|
|
35
|
+
*/
|
|
22
36
|
readonly touchpad: Vector2;
|
|
23
37
|
/** @readonly */
|
|
24
38
|
readonly targetRay: XRInputPose;
|
|
25
39
|
/** @readonly */
|
|
26
40
|
readonly grip: XRInputPose;
|
|
27
|
-
/**
|
|
41
|
+
/**
|
|
42
|
+
* Native source, or null while disconnected. Set by the device.
|
|
43
|
+
* @readonly
|
|
44
|
+
* @type {import('./XRInputTypes.js').XRInputSource|null}
|
|
45
|
+
*/
|
|
28
46
|
readonly nativeSource: import('./XRInputTypes.js').XRInputSource | null;
|
|
29
|
-
/** Number of native
|
|
47
|
+
/** Number of native buttons, excluding controls materialised for bindings. Do not modify directly. */
|
|
30
48
|
buttonCount: number;
|
|
49
|
+
/** Number of native axes, excluding controls materialised for bindings. Do not modify directly. */
|
|
31
50
|
axisCount: number;
|
|
32
51
|
get connected(): boolean;
|
|
33
52
|
get handedness(): string;
|
|
34
53
|
get targetRayMode(): string;
|
|
35
54
|
/** @returns {ReadonlyArray<string>} */
|
|
36
55
|
get profiles(): readonly string[];
|
|
37
|
-
/**
|
|
56
|
+
/**
|
|
57
|
+
* Return a stable button, creating neutral entries up to this index if needed.
|
|
58
|
+
* @param {number} index
|
|
59
|
+
* @returns {XRInputButton}
|
|
60
|
+
*/
|
|
38
61
|
getButton(index: number): XRInputButton;
|
|
39
|
-
/**
|
|
62
|
+
/**
|
|
63
|
+
* Return a stable axis, creating neutral entries up to this index if needed.
|
|
64
|
+
* @param {number} index
|
|
65
|
+
* @returns {Vector1}
|
|
66
|
+
*/
|
|
40
67
|
getAxis(index: number): Vector1;
|
|
41
|
-
/**
|
|
68
|
+
/**
|
|
69
|
+
* @internal
|
|
70
|
+
* @param {import('./XRInputTypes.js').XRInputSource|null} source
|
|
71
|
+
*/
|
|
42
72
|
bind(source: import('./XRInputTypes.js').XRInputSource | null): void;
|
|
43
73
|
/**
|
|
44
74
|
* @internal Sample values and poses before publishing raw switch edges.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"XRInputHandle.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/input/devices/xr/XRInputHandle.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"XRInputHandle.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/input/devices/xr/XRInputHandle.js"],"names":[],"mappings":"AA2BA;;;;;;;;GAQG;AACH;IACI,gBAAgB;IAChB,+BAA6B;IAE7B,gBAAgB;IAChB,gCAA8B;IAE9B;;;;OAIG;IACH,kBAFU,aAAa,EAAE,CAEZ;IAEb;;;;OAIG;IACH,eAFU,OAAO,EAAE,CAET;IAEV;;;OAGG;IACH,kCAAoC;IAEpC;;;OAGG;IACH,2BAAyB;IAEzB,gBAAgB;IAChB,gCAA8B;IAE9B,gBAAgB;IAChB,2BAAyB;IAEzB;;;;OAIG;IACH,uBAFU,OAAO,mBAAmB,EAAE,aAAa,GAAC,IAAI,CAEpC;IAQpB,sGAAsG;IACtG,oBAAgB;IAEhB,mGAAmG;IACnG,kBAAc;IAOd,yBAEC;IAED,yBAEC;IAED,4BAEC;IAED,uCAAuC;IACvC,kCAEC;IAED;;;;OAIG;IACH,iBAHW,MAAM,GACJ,aAAa,CAUzB;IAED;;;;OAIG;IACH,eAHW,MAAM,GACJ,OAAO,CAUnB;IAED;;;OAGG;IACH,aAFW,OAAO,mBAAmB,EAAE,aAAa,GAAC,IAAI,QAgBxD;IAED;;;;OAIG;IACH,cAHW,OAAO,mBAAmB,EAAE,OAAO,GAAC,IAAI,kBACxC,WAAW,GAAC,IAAI,QA+C1B;IAmBD,sEAAsE;IACtE,wBAGC;IAED,yFAAyF;IACzF,cAeC;IAED,gBAAgB;IAChB,cAMC;;CACJ;8BAvQ6B,oBAAoB;8BACpB,oBAAoB;wBAJ1B,kCAAkC;6BAE7B,4BAA4B;oBADrC,kCAAkC;4BAIN,kBAAkB"}
|
|
@@ -4,17 +4,32 @@ import Vector2 from "../../../../core/geom/Vector2.js";
|
|
|
4
4
|
import { GamepadStick } from "../gamepad/GamepadStick.js";
|
|
5
5
|
import { XRInputAction } from "./XRInputAction.js";
|
|
6
6
|
import { XRInputButton } from "./XRInputButton.js";
|
|
7
|
-
import { XRInputPose } from "./XRInputPose.js";
|
|
7
|
+
import { XRInputPose, xr_input_read_pose } from "./XRInputPose.js";
|
|
8
8
|
import { XRInputValueSource } from "./XRInputValueSource.js";
|
|
9
|
+
import { XRHandedness } from "./XRHandedness.js";
|
|
10
|
+
import { XRTargetRayMode } from "./XRTargetRayMode.js";
|
|
11
|
+
import { XRGamepadMapping } from "./XRGamepadMapping.js";
|
|
9
12
|
|
|
10
|
-
|
|
11
|
-
|
|
13
|
+
const DEFAULT_METADATA = Object.freeze({
|
|
14
|
+
handedness: XRHandedness.None,
|
|
15
|
+
targetRayMode: XRTargetRayMode.Unavailable,
|
|
16
|
+
profiles: Object.freeze([])
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
/** @type {import('./XRInputTypes.js').XRGamepad} */
|
|
20
|
+
const DEFAULT_GAMEPAD = Object.freeze({
|
|
21
|
+
mapping: XRGamepadMapping.Unmapped,
|
|
22
|
+
buttons: Object.freeze([]),
|
|
23
|
+
axes: Object.freeze([])
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
const DEFAULT_BUTTON = Object.freeze({ value: 0, pressed: false, touched: false });
|
|
12
27
|
|
|
13
28
|
/**
|
|
14
29
|
* One XR input source, or a persistent handedness slot owned by XRInputDevice.
|
|
15
30
|
* All control objects survive disconnection. Consumers read them; the device owns mutation.
|
|
16
|
-
*
|
|
17
|
-
* buttons/axes, while select/squeeze
|
|
31
|
+
* With xr-standard, select/squeeze read native button amounts. Other mappings remain available through
|
|
32
|
+
* buttons/axes, while select/squeeze report 0/1 from native events; check their valueSource.
|
|
18
33
|
*
|
|
19
34
|
* Button indices 0/1 are select/squeeze; axes 0/1 are touchpad and 2/3 thumbstick in xr-standard.
|
|
20
35
|
* Placeholder entries are allowed by WebXR: a zero entry does not prove that a control exists.
|
|
@@ -22,28 +37,59 @@ const NO_PROFILES = Object.freeze([]);
|
|
|
22
37
|
export class XRInputHandle {
|
|
23
38
|
/** @readonly */
|
|
24
39
|
select = new XRInputAction();
|
|
40
|
+
|
|
25
41
|
/** @readonly */
|
|
26
42
|
squeeze = new XRInputAction();
|
|
27
|
-
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Raw native buttons. Use {@link getButton} for an index that may not exist yet.
|
|
46
|
+
* @readonly
|
|
47
|
+
* @type {XRInputButton[]}
|
|
48
|
+
*/
|
|
28
49
|
buttons = [];
|
|
29
|
-
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Raw native axes in [-1, 1]. Use {@link getAxis} for an index that may not exist yet.
|
|
53
|
+
* @readonly
|
|
54
|
+
* @type {Vector1[]}
|
|
55
|
+
*/
|
|
30
56
|
axes = [];
|
|
31
|
-
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Calibrated xr-standard thumbstick, +x right and +y down.
|
|
60
|
+
* @readonly
|
|
61
|
+
*/
|
|
32
62
|
thumbstick = new GamepadStick(2, 3);
|
|
33
|
-
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Uncalibrated xr-standard touchpad coordinates, +x right and +y down.
|
|
66
|
+
* @readonly
|
|
67
|
+
*/
|
|
34
68
|
touchpad = new Vector2();
|
|
69
|
+
|
|
35
70
|
/** @readonly */
|
|
36
71
|
targetRay = new XRInputPose();
|
|
72
|
+
|
|
37
73
|
/** @readonly */
|
|
38
74
|
grip = new XRInputPose();
|
|
39
75
|
|
|
40
|
-
/**
|
|
76
|
+
/**
|
|
77
|
+
* Native source, or null while disconnected. Set by the device.
|
|
78
|
+
* @readonly
|
|
79
|
+
* @type {import('./XRInputTypes.js').XRInputSource|null}
|
|
80
|
+
*/
|
|
41
81
|
nativeSource = null;
|
|
82
|
+
|
|
83
|
+
/** @type {Pick<import('./XRInputTypes.js').XRInputSource, 'handedness'|'targetRayMode'|'profiles'>} */
|
|
84
|
+
#metadata = DEFAULT_METADATA;
|
|
85
|
+
|
|
42
86
|
/** @type {number[]} */
|
|
43
87
|
#axisValues = [0, 0, 0, 0];
|
|
44
88
|
|
|
45
|
-
/** Number of native
|
|
89
|
+
/** Number of native buttons, excluding controls materialised for bindings. Do not modify directly. */
|
|
46
90
|
buttonCount = 0;
|
|
91
|
+
|
|
92
|
+
/** Number of native axes, excluding controls materialised for bindings. Do not modify directly. */
|
|
47
93
|
axisCount = 0;
|
|
48
94
|
|
|
49
95
|
constructor() {
|
|
@@ -51,40 +97,71 @@ export class XRInputHandle {
|
|
|
51
97
|
this.getAxis(3);
|
|
52
98
|
}
|
|
53
99
|
|
|
54
|
-
get connected() {
|
|
55
|
-
|
|
56
|
-
|
|
100
|
+
get connected() {
|
|
101
|
+
return this.nativeSource !== null;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
get handedness() {
|
|
105
|
+
return this.#metadata.handedness;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
get targetRayMode() {
|
|
109
|
+
return this.#metadata.targetRayMode;
|
|
110
|
+
}
|
|
111
|
+
|
|
57
112
|
/** @returns {ReadonlyArray<string>} */
|
|
58
|
-
get profiles() {
|
|
113
|
+
get profiles() {
|
|
114
|
+
return this.#metadata.profiles;
|
|
115
|
+
}
|
|
59
116
|
|
|
60
|
-
/**
|
|
117
|
+
/**
|
|
118
|
+
* Return a stable button, creating neutral entries up to this index if needed.
|
|
119
|
+
* @param {number} index
|
|
120
|
+
* @returns {XRInputButton}
|
|
121
|
+
*/
|
|
61
122
|
getButton(index) {
|
|
62
123
|
assert.isNonNegativeInteger(index, 'index');
|
|
124
|
+
|
|
63
125
|
while (this.buttons.length <= index) {
|
|
64
126
|
this.buttons.push(new XRInputButton());
|
|
65
127
|
}
|
|
128
|
+
|
|
66
129
|
return this.buttons[index];
|
|
67
130
|
}
|
|
68
131
|
|
|
69
|
-
/**
|
|
132
|
+
/**
|
|
133
|
+
* Return a stable axis, creating neutral entries up to this index if needed.
|
|
134
|
+
* @param {number} index
|
|
135
|
+
* @returns {Vector1}
|
|
136
|
+
*/
|
|
70
137
|
getAxis(index) {
|
|
71
138
|
assert.isNonNegativeInteger(index, 'index');
|
|
139
|
+
|
|
72
140
|
while (this.axes.length <= index) {
|
|
73
141
|
this.axes.push(new Vector1());
|
|
74
142
|
}
|
|
143
|
+
|
|
75
144
|
return this.axes[index];
|
|
76
145
|
}
|
|
77
146
|
|
|
78
|
-
/**
|
|
147
|
+
/**
|
|
148
|
+
* @internal
|
|
149
|
+
* @param {import('./XRInputTypes.js').XRInputSource|null} source
|
|
150
|
+
*/
|
|
79
151
|
bind(source) {
|
|
152
|
+
assert.defined(source, 'source');
|
|
153
|
+
assert.isObject(source, 'source');
|
|
154
|
+
|
|
80
155
|
if (this.nativeSource === source) {
|
|
81
156
|
return;
|
|
82
157
|
}
|
|
83
158
|
this.nativeSource = null;
|
|
159
|
+
this.#metadata = DEFAULT_METADATA;
|
|
84
160
|
this.clear();
|
|
85
161
|
this.flush();
|
|
86
162
|
this.thumbstick.forgetCalibration();
|
|
87
163
|
this.nativeSource = source;
|
|
164
|
+
this.#metadata = source ?? DEFAULT_METADATA;
|
|
88
165
|
}
|
|
89
166
|
|
|
90
167
|
/**
|
|
@@ -93,6 +170,9 @@ export class XRInputHandle {
|
|
|
93
170
|
* @param {EventTarget|null} referenceSpace
|
|
94
171
|
*/
|
|
95
172
|
sample(frame, referenceSpace) {
|
|
173
|
+
assert.defined(frame, 'frame');
|
|
174
|
+
assert.defined(referenceSpace, 'referenceSpace');
|
|
175
|
+
|
|
96
176
|
const source = this.nativeSource;
|
|
97
177
|
if (source === null) {
|
|
98
178
|
return;
|
|
@@ -100,17 +180,16 @@ export class XRInputHandle {
|
|
|
100
180
|
// A source/visibility notification has no pose frame. Preserve the last sample in that case;
|
|
101
181
|
// only an actual unavailable pose, a reference-space change or cleanup invalidates it.
|
|
102
182
|
if (frame !== null) {
|
|
103
|
-
const ray =
|
|
104
|
-
const grip =
|
|
105
|
-
? frame.getPose(source.gripSpace, referenceSpace) ?? null : null;
|
|
183
|
+
const ray = xr_input_read_pose(frame, source.targetRaySpace, referenceSpace);
|
|
184
|
+
const grip = xr_input_read_pose(frame, source.gripSpace ?? null, referenceSpace);
|
|
106
185
|
this.targetRay.update(ray);
|
|
107
186
|
this.grip.update(grip);
|
|
108
187
|
}
|
|
109
188
|
|
|
110
|
-
const gamepad = source.gamepad;
|
|
111
|
-
const mapped = gamepad
|
|
112
|
-
this.buttonCount = gamepad
|
|
113
|
-
this.axisCount = gamepad
|
|
189
|
+
const gamepad = source.gamepad ?? DEFAULT_GAMEPAD;
|
|
190
|
+
const mapped = gamepad.mapping === XRGamepadMapping.Standard;
|
|
191
|
+
this.buttonCount = gamepad.buttons.length;
|
|
192
|
+
this.axisCount = gamepad.axes.length;
|
|
114
193
|
if (this.buttonCount > 0) {
|
|
115
194
|
this.getButton(this.buttonCount - 1);
|
|
116
195
|
}
|
|
@@ -118,10 +197,11 @@ export class XRInputHandle {
|
|
|
118
197
|
this.getAxis(this.axisCount - 1);
|
|
119
198
|
}
|
|
120
199
|
for (let i = 0; i < this.buttons.length; i++) {
|
|
121
|
-
|
|
200
|
+
const button = gamepad.buttons[i] ?? DEFAULT_BUTTON;
|
|
201
|
+
this.buttons[i].update(button.value, button.pressed, button.touched);
|
|
122
202
|
}
|
|
123
203
|
for (let i = 0; i < this.axes.length; i++) {
|
|
124
|
-
const value =
|
|
204
|
+
const value = gamepad.axes[i] ?? 0;
|
|
125
205
|
this.#axisValues[i] = value;
|
|
126
206
|
this.axes[i].set(value);
|
|
127
207
|
}
|
|
@@ -132,14 +212,31 @@ export class XRInputHandle {
|
|
|
132
212
|
this.touchpad.set(0, 0);
|
|
133
213
|
this.thumbstick.reset();
|
|
134
214
|
}
|
|
135
|
-
this
|
|
136
|
-
this
|
|
215
|
+
this.#sampleAction(this.select, 0, mapped);
|
|
216
|
+
this.#sampleAction(this.squeeze, 1, mapped);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* @param {XRInputAction} action
|
|
221
|
+
* @param {number} buttonIndex
|
|
222
|
+
* @param {boolean} mapped
|
|
223
|
+
*/
|
|
224
|
+
#sampleAction(action, buttonIndex, mapped) {
|
|
225
|
+
if (mapped && buttonIndex < this.buttonCount) {
|
|
226
|
+
action.update(this.buttons[buttonIndex].x, XRInputValueSource.Gamepad);
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
// Preserve event-driven amounts between native begin/end events. Clear a previous hardware
|
|
230
|
+
// amount when entering event-only mode.
|
|
231
|
+
if (action.valueSource !== XRInputValueSource.Action) {
|
|
232
|
+
action.update(0, XRInputValueSource.Action);
|
|
233
|
+
}
|
|
137
234
|
}
|
|
138
235
|
|
|
139
236
|
/** @internal Tracking loss does not imply release or cancellation. */
|
|
140
237
|
invalidatePoses() {
|
|
141
|
-
this.targetRay.update(
|
|
142
|
-
this.grip.update(
|
|
238
|
+
this.targetRay.update();
|
|
239
|
+
this.grip.update();
|
|
143
240
|
}
|
|
144
241
|
|
|
145
242
|
/** @internal Neutralise everything before switch releases and cancellation callbacks. */
|
|
@@ -148,7 +245,7 @@ export class XRInputHandle {
|
|
|
148
245
|
this.buttonCount = 0;
|
|
149
246
|
this.axisCount = 0;
|
|
150
247
|
for (let i = 0; i < this.buttons.length; i++) {
|
|
151
|
-
this.buttons[i].update(
|
|
248
|
+
this.buttons[i].update();
|
|
152
249
|
}
|
|
153
250
|
for (let i = 0; i < this.axes.length; i++) {
|
|
154
251
|
this.axes[i].set(0);
|