@pmndrs/viverse 0.1.20 → 0.2.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.
Files changed (67) hide show
  1. package/dist/animation/bone-map.d.ts +4 -0
  2. package/dist/animation/bone-map.js +11 -0
  3. package/dist/animation/default.d.ts +9 -0
  4. package/dist/animation/default.js +25 -0
  5. package/dist/animation/index.d.ts +12 -19
  6. package/dist/animation/index.js +76 -72
  7. package/dist/animation/mask.d.ts +6 -0
  8. package/dist/animation/mask.js +53 -0
  9. package/dist/camera.d.ts +7 -7
  10. package/dist/camera.js +33 -26
  11. package/dist/index.d.ts +3 -2
  12. package/dist/index.js +3 -2
  13. package/dist/input/action.d.ts +41 -0
  14. package/dist/input/action.js +97 -0
  15. package/dist/input/index.d.ts +12 -27
  16. package/dist/input/index.js +17 -69
  17. package/dist/input/keyboard.d.ts +29 -7
  18. package/dist/input/keyboard.js +84 -72
  19. package/dist/input/pointer-capture.d.ts +6 -11
  20. package/dist/input/pointer-capture.js +10 -30
  21. package/dist/input/pointer-lock.d.ts +6 -11
  22. package/dist/input/pointer-lock.js +8 -29
  23. package/dist/input/screen-joystick.d.ts +12 -11
  24. package/dist/input/screen-joystick.js +39 -49
  25. package/dist/input/screen-jump-button.d.ts +2 -4
  26. package/dist/input/screen-jump-button.js +7 -12
  27. package/dist/model/index.d.ts +9 -13
  28. package/dist/model/index.js +12 -34
  29. package/dist/physics/index.d.ts +2 -5
  30. package/dist/physics/index.js +7 -16
  31. package/dist/simple-character/apply-input-options.d.ts +2 -0
  32. package/dist/simple-character/apply-input-options.js +28 -0
  33. package/dist/simple-character/defaults.d.ts +2 -0
  34. package/dist/simple-character/defaults.js +2 -0
  35. package/dist/simple-character/index.d.ts +116 -0
  36. package/dist/simple-character/index.js +104 -0
  37. package/dist/simple-character/state/index.d.ts +6 -0
  38. package/dist/simple-character/state/index.js +6 -0
  39. package/dist/simple-character/state/jump-down.d.ts +3 -0
  40. package/dist/simple-character/state/jump-down.js +26 -0
  41. package/dist/simple-character/state/jump-forward.d.ts +5 -0
  42. package/dist/simple-character/state/jump-forward.js +41 -0
  43. package/dist/simple-character/state/jump-loop.d.ts +3 -0
  44. package/dist/simple-character/state/jump-loop.js +24 -0
  45. package/dist/simple-character/state/jump-start.d.ts +4 -0
  46. package/dist/simple-character/state/jump-start.js +30 -0
  47. package/dist/simple-character/state/jump-up.d.ts +5 -0
  48. package/dist/simple-character/state/jump-up.js +40 -0
  49. package/dist/simple-character/state/movement.d.ts +3 -0
  50. package/dist/simple-character/state/movement.js +63 -0
  51. package/dist/simple-character/update-input-velocity.d.ts +4 -0
  52. package/dist/simple-character/update-input-velocity.js +25 -0
  53. package/dist/simple-character/update-rotation.d.ts +6 -0
  54. package/dist/simple-character/update-rotation.js +40 -0
  55. package/dist/utils.d.ts +12 -5
  56. package/dist/utils.js +37 -39
  57. package/package.json +2 -2
  58. package/dist/animation/bvh.d.ts +0 -4
  59. package/dist/animation/bvh.js +0 -8
  60. package/dist/animation/fbx.d.ts +0 -4
  61. package/dist/animation/fbx.js +0 -8
  62. package/dist/animation/gltf.d.ts +0 -3
  63. package/dist/animation/gltf.js +0 -8
  64. package/dist/animation/vrma.d.ts +0 -3
  65. package/dist/animation/vrma.js +0 -8
  66. package/dist/simple-character.d.ts +0 -107
  67. package/dist/simple-character.js +0 -344
@@ -0,0 +1,97 @@
1
+ // no external imports
2
+ export class EventAction {
3
+ latestTime = -Infinity;
4
+ subscriptionListeners = new Set();
5
+ emit(value) {
6
+ this.latestTime = performance.now() / 1000;
7
+ for (const listener of this.subscriptionListeners) {
8
+ listener(value);
9
+ }
10
+ }
11
+ subscribe(callback, options) {
12
+ const listener = (value) => {
13
+ if (options?.once === true) {
14
+ this.subscriptionListeners.delete(listener);
15
+ }
16
+ callback(value);
17
+ };
18
+ this.subscriptionListeners.add(listener);
19
+ if (options?.signal != null) {
20
+ options.signal.addEventListener('abort', () => this.subscriptionListeners.delete(listener), { once: true });
21
+ }
22
+ }
23
+ waitFor(signal) {
24
+ return new Promise((resolve) => this.subscribe(resolve, { once: true, signal }));
25
+ }
26
+ getLatestTime() {
27
+ return this.latestTime;
28
+ }
29
+ }
30
+ /**
31
+ * StateAction keeps the latest state per writer and merges them on read.
32
+ * Values persist until the writer is disposed (abortSignal aborts).
33
+ */
34
+ export class StateAction {
35
+ mergeWriters;
36
+ neutral;
37
+ absoluteActions = new Map();
38
+ constructor(mergeWriters, neutral) {
39
+ this.mergeWriters = mergeWriters;
40
+ this.neutral = neutral;
41
+ }
42
+ createWriter(abortSignal) {
43
+ const emitterUuid = globalThis.crypto?.randomUUID?.() ?? Math.random().toString(36).slice(2);
44
+ abortSignal.addEventListener('abort', () => this.absoluteActions.delete(emitterUuid), { once: true });
45
+ return {
46
+ write: (value) => {
47
+ if (!abortSignal.aborted) {
48
+ this.absoluteActions.set(emitterUuid, value);
49
+ }
50
+ },
51
+ };
52
+ }
53
+ get() {
54
+ const values = [...this.absoluteActions.values()];
55
+ return values.length ? this.mergeWriters(...values) : this.neutral;
56
+ }
57
+ }
58
+ /**
59
+ * DeltaAction accumulates transient values each frame and clears them on frame advance.
60
+ * Multiple writes per frame from any source are combined using combine().
61
+ */
62
+ export class DeltaAction {
63
+ combine;
64
+ neutral;
65
+ constructor(combine, neutral) {
66
+ this.combine = combine;
67
+ this.neutral = neutral;
68
+ }
69
+ readers = new Set();
70
+ write(value) {
71
+ for (const reader of this.readers) {
72
+ reader.next.push(value);
73
+ }
74
+ }
75
+ createReader(abortSignal) {
76
+ const reader = { next: new Array(), current: new Array() };
77
+ this.readers.add(reader);
78
+ abortSignal.addEventListener('abort', () => {
79
+ this.readers.delete(reader);
80
+ }, { once: true });
81
+ return {
82
+ update: () => {
83
+ reader.current.length = 0;
84
+ if (reader.next.length) {
85
+ reader.current.push(...reader.next);
86
+ reader.next.length = 0;
87
+ }
88
+ },
89
+ get: () => {
90
+ if (reader.current.length === 0) {
91
+ return this.neutral;
92
+ }
93
+ return this.combine(...reader.current);
94
+ },
95
+ };
96
+ }
97
+ }
@@ -1,32 +1,17 @@
1
- export declare class InputSystem {
2
- private readonly inputs;
3
- constructor(domElement: HTMLElement, inputs: ReadonlyArray<Input | {
4
- new (element: HTMLElement, options?: {}): Input;
5
- }>, options?: {});
6
- add(input: Input): void;
7
- remove(input: Input): void;
8
- dispose(): void;
9
- get<T>(field: InputField<T>): T;
10
- }
11
- export type InputField<T> = {
12
- default: T;
13
- combine: (v1: any, v2: any) => T;
14
- };
15
- export declare const MoveForwardField: InputField<number>;
16
- export declare const MoveBackwardField: InputField<number>;
17
- export declare const MoveLeftField: InputField<number>;
18
- export declare const MoveRightField: InputField<number>;
19
- export declare const LastTimeJumpPressedField: InputField<number | null>;
20
- export declare const RunField: InputField<boolean>;
21
- export declare const DeltaZoomField: InputField<number>;
22
- export declare const DeltaYawField: InputField<number>;
23
- export declare const DeltaPitchField: InputField<number>;
24
- export interface Input {
25
- get<T>(field: InputField<T>): T | undefined;
26
- dispose?(): void;
27
- }
1
+ import { EventAction, StateAction, DeltaAction } from './action.js';
2
+ export declare function BooleanOr(...values: Array<boolean>): boolean;
3
+ export declare const MoveForwardAction: StateAction<number>;
4
+ export declare const MoveBackwardAction: StateAction<number>;
5
+ export declare const MoveLeftAction: StateAction<number>;
6
+ export declare const MoveRightAction: StateAction<number>;
7
+ export declare const RunAction: StateAction<boolean>;
8
+ export declare const JumpAction: EventAction<void>;
9
+ export declare const ZoomAction: DeltaAction<number>;
10
+ export declare const RotateYawAction: DeltaAction<number>;
11
+ export declare const RotatePitchAction: DeltaAction<number>;
28
12
  export * from './pointer-lock.js';
29
13
  export * from './pointer-capture.js';
30
14
  export * from './keyboard.js';
31
15
  export * from './screen-joystick.js';
32
16
  export * from './screen-jump-button.js';
17
+ export * from './action.js';
@@ -1,76 +1,24 @@
1
- export class InputSystem {
2
- inputs;
3
- constructor(domElement, inputs, options) {
4
- this.inputs = inputs.map((input) => (typeof input === 'function' ? new input(domElement, options) : input));
5
- }
6
- add(input) {
7
- this.inputs.push(input);
8
- }
9
- remove(input) {
10
- const index = this.inputs.indexOf(input);
11
- if (index === -1) {
12
- return;
13
- }
14
- this.inputs.splice(index, 1);
15
- }
16
- dispose() {
17
- this.inputs.forEach((input) => input.dispose?.());
18
- this.inputs.length = 0;
19
- }
20
- get(field) {
21
- let current;
22
- for (const input of this.inputs) {
23
- const result = input.get(field);
24
- if (result == null) {
25
- continue;
26
- }
27
- if (current == undefined) {
28
- current = result;
29
- continue;
30
- }
31
- current = field.combine(current, result);
32
- }
33
- return current ?? field.default;
1
+ import { EventAction, StateAction, DeltaAction } from './action.js';
2
+ export function BooleanOr(...values) {
3
+ let value = false;
4
+ for (let i = 0; i < values.length; i++) {
5
+ value ||= values[i];
34
6
  }
7
+ return value;
35
8
  }
36
- export const MoveForwardField = {
37
- default: 0,
38
- combine: Math.max,
39
- };
40
- export const MoveBackwardField = {
41
- default: 0,
42
- combine: Math.max,
43
- };
44
- export const MoveLeftField = {
45
- default: 0,
46
- combine: Math.max,
47
- };
48
- export const MoveRightField = {
49
- default: 0,
50
- combine: Math.max,
51
- };
52
- export const LastTimeJumpPressedField = {
53
- default: null,
54
- combine: (v1, v2) => (v1 == null && v2 == null ? null : Math.min(v1 ?? Infinity, v2 ?? Infinity)),
55
- };
56
- export const RunField = {
57
- default: false,
58
- combine: (v1, v2) => v1 || v2,
59
- };
60
- export const DeltaZoomField = {
61
- default: 0,
62
- combine: Math.max,
63
- };
64
- export const DeltaYawField = {
65
- default: 0,
66
- combine: Math.max,
67
- };
68
- export const DeltaPitchField = {
69
- default: 0,
70
- combine: Math.max,
71
- };
9
+ const sum = (...values) => values.reduce((a, b) => a + b, 0);
10
+ export const MoveForwardAction = new StateAction(Math.max, 0);
11
+ export const MoveBackwardAction = new StateAction(Math.max, 0);
12
+ export const MoveLeftAction = new StateAction(Math.max, 0);
13
+ export const MoveRightAction = new StateAction(Math.max, 0);
14
+ export const RunAction = new StateAction(BooleanOr, false);
15
+ export const JumpAction = new EventAction();
16
+ export const ZoomAction = new DeltaAction(sum, 0);
17
+ export const RotateYawAction = new DeltaAction(sum, 0);
18
+ export const RotatePitchAction = new DeltaAction(sum, 0);
72
19
  export * from './pointer-lock.js';
73
20
  export * from './pointer-capture.js';
74
21
  export * from './keyboard.js';
75
22
  export * from './screen-joystick.js';
76
23
  export * from './screen-jump-button.js';
24
+ export * from './action.js';
@@ -1,4 +1,18 @@
1
- import { Input, InputField } from './index.js';
1
+ import { EventAction, StateAction } from './index.js';
2
+ export declare class KeyboardInput {
3
+ private readonly domElement;
4
+ private readonly abortController;
5
+ options: Partial<{
6
+ keys: Array<string>;
7
+ }>;
8
+ abortSignal: AbortSignal;
9
+ private readonly pressedKeys;
10
+ constructor(domElement: HTMLElement);
11
+ bindEvent(action: EventAction): void;
12
+ bindValue(action: StateAction<boolean>): void;
13
+ bindValue<T>(action: StateAction<T>, map: (value: boolean) => T): void;
14
+ dispose(): void;
15
+ }
2
16
  export type LocomotionKeyboardInputOptions = {
3
17
  keyboardMoveForwardKeys?: Array<string>;
4
18
  keyboardMoveBackwardKeys?: Array<string>;
@@ -7,11 +21,19 @@ export type LocomotionKeyboardInputOptions = {
7
21
  keyboardRunKeys?: Array<string>;
8
22
  keyboardJumpKeys?: Array<string>;
9
23
  };
10
- export declare class LocomotionKeyboardInput implements Input {
11
- private readonly options;
12
- private readonly abortController;
13
- private readonly keyState;
14
- constructor(domElement: HTMLElement, options?: LocomotionKeyboardInputOptions);
15
- get<T>(field: InputField<T>): T | undefined;
24
+ export declare const DefaultMoveForwardKeys: string[];
25
+ export declare const DefaultMoveBackwardKeys: string[];
26
+ export declare const DefaultMoveLeftKeys: string[];
27
+ export declare const DefaultMoveRightKeys: string[];
28
+ export declare const DefaultRunKeys: string[];
29
+ export declare const DefaultJumpKeys: string[];
30
+ export declare class LocomotionKeyboardInput {
31
+ forward: KeyboardInput;
32
+ left: KeyboardInput;
33
+ right: KeyboardInput;
34
+ backward: KeyboardInput;
35
+ jump: KeyboardInput;
36
+ run: KeyboardInput;
37
+ constructor(domElement: HTMLElement);
16
38
  dispose(): void;
17
39
  }
@@ -1,84 +1,96 @@
1
- import { MoveForwardField, MoveBackwardField, MoveLeftField, MoveRightField, LastTimeJumpPressedField, RunField, } from './index.js';
2
- const DefaultMoveForwardKeys = ['KeyW'];
3
- const DefaultMoveBackwardKeys = ['KeyS'];
4
- const DefaultMoveLeftKeys = ['KeyA'];
5
- const DefaultMoveRightKeys = ['KeyD'];
6
- const DefaultRunKeys = ['ShiftRight', 'ShiftLeft'];
7
- const DefaultJumpKeys = ['Space'];
8
- export class LocomotionKeyboardInput {
9
- options;
1
+ import { JumpAction, MoveBackwardAction, MoveForwardAction, MoveLeftAction, MoveRightAction, RunAction, } from './index.js';
2
+ export class KeyboardInput {
3
+ domElement;
10
4
  abortController = new AbortController();
11
- keyState = new Map();
12
- constructor(domElement, options = {}) {
13
- this.options = options;
14
- domElement.tabIndex = 0;
15
- domElement.addEventListener('keydown', (event) => {
16
- let state = this.keyState.get(event.code);
17
- const now = performance.now() / 1000;
18
- if (state == null) {
19
- this.keyState.set(event.code, (state = { pressTime: now }));
5
+ options = {};
6
+ abortSignal = this.abortController.signal;
7
+ pressedKeys = new Set();
8
+ constructor(domElement) {
9
+ this.domElement = domElement;
10
+ }
11
+ bindEvent(action) {
12
+ const isWatched = (e) => this.options.keys == null || this.options.keys.length === 0 || this.options.keys.includes(e.code);
13
+ this.domElement.addEventListener('keydown', (e) => {
14
+ if (!isWatched(e) || e.repeat) {
15
+ return;
16
+ }
17
+ action.emit({});
18
+ }, { signal: this.abortController.signal });
19
+ }
20
+ bindValue(action, map) {
21
+ const writer = action.createWriter(this.abortSignal);
22
+ const isWatched = (e) => this.options.keys == null || this.options.keys.length === 0 || this.options.keys.includes(e.code);
23
+ let isPressed = false;
24
+ const write = (value) => {
25
+ if (isPressed === value) {
26
+ return;
27
+ }
28
+ isPressed = value;
29
+ writer.write(map?.(value) ?? value);
30
+ };
31
+ this.domElement.tabIndex = 0;
32
+ this.domElement.addEventListener('keydown', (e) => {
33
+ if (!isWatched(e)) {
34
+ return;
20
35
  }
21
- else {
22
- state.pressTime = now;
36
+ const wasEmpty = this.pressedKeys.size === 0;
37
+ this.pressedKeys.add(e.code);
38
+ if (wasEmpty && this.pressedKeys.size > 0) {
39
+ write(true);
23
40
  }
24
- }, {
25
- signal: this.abortController.signal,
26
- });
27
- domElement.addEventListener('keyup', (event) => {
28
- let state = this.keyState.get(event.code);
29
- const now = performance.now() / 1000;
30
- if (state == null) {
31
- this.keyState.set(event.code, (state = { releaseTime: now }));
41
+ }, { signal: this.abortController.signal });
42
+ this.domElement.addEventListener('keyup', (e) => {
43
+ if (!isWatched(e)) {
44
+ return;
32
45
  }
33
- else {
34
- state.releaseTime = now;
46
+ if (this.pressedKeys.delete(e.code) && this.pressedKeys.size === 0) {
47
+ write(false);
35
48
  }
36
- }, {
37
- signal: this.abortController.signal,
38
- });
49
+ }, { signal: this.abortController.signal });
39
50
  // Handle focus loss to clear pressed keys
40
- domElement.addEventListener('blur', () => this.keyState.clear(), {
41
- signal: this.abortController.signal,
42
- });
43
- }
44
- get(field) {
45
- if (field === LastTimeJumpPressedField) {
46
- const jumpKeys = this.options.keyboardJumpKeys ?? DefaultJumpKeys;
47
- const pressed = jumpKeys
48
- .map((key) => this.keyState.get(key)?.pressTime ?? null)
49
- .filter((t) => t != null);
50
- return (pressed.length > 0 ? Math.max(...pressed) : null);
51
- }
52
- let keys;
53
- switch (field) {
54
- case MoveForwardField:
55
- keys = this.options.keyboardMoveForwardKeys ?? DefaultMoveForwardKeys;
56
- break;
57
- case MoveBackwardField:
58
- keys = this.options.keyboardMoveBackwardKeys ?? DefaultMoveBackwardKeys;
59
- break;
60
- case MoveLeftField:
61
- keys = this.options.keyboardMoveLeftKeys ?? DefaultMoveLeftKeys;
62
- break;
63
- case MoveRightField:
64
- keys = this.options.keyboardMoveRightKeys ?? DefaultMoveRightKeys;
65
- break;
66
- case RunField:
67
- keys = this.options.keyboardRunKeys ?? DefaultRunKeys;
68
- break;
69
- }
70
- if (keys == null) {
71
- return undefined;
72
- }
73
- return keys.some((key) => {
74
- const state = this.keyState.get(key);
75
- if (state?.pressTime == null) {
76
- return false;
51
+ this.domElement.addEventListener('blur', () => {
52
+ if (this.pressedKeys.size > 0) {
53
+ this.pressedKeys.clear();
54
+ write(false);
77
55
  }
78
- return state.releaseTime == null || state.pressTime > state.releaseTime;
79
- });
56
+ }, { signal: this.abortController.signal });
80
57
  }
81
58
  dispose() {
82
59
  this.abortController.abort();
83
60
  }
84
61
  }
62
+ export const DefaultMoveForwardKeys = ['KeyW'];
63
+ export const DefaultMoveBackwardKeys = ['KeyS'];
64
+ export const DefaultMoveLeftKeys = ['KeyA'];
65
+ export const DefaultMoveRightKeys = ['KeyD'];
66
+ export const DefaultRunKeys = ['ShiftRight', 'ShiftLeft'];
67
+ export const DefaultJumpKeys = ['Space'];
68
+ export class LocomotionKeyboardInput {
69
+ forward;
70
+ left;
71
+ right;
72
+ backward;
73
+ jump;
74
+ run;
75
+ constructor(domElement) {
76
+ this.forward = new KeyboardInput(domElement);
77
+ this.forward.options.keys = DefaultMoveForwardKeys;
78
+ this.forward.bindValue(MoveForwardAction, (isPressed) => (isPressed ? 1 : 0));
79
+ this.left = new KeyboardInput(domElement);
80
+ this.left.options.keys = DefaultMoveLeftKeys;
81
+ this.left.bindValue(MoveLeftAction, (isPressed) => (isPressed ? 1 : 0));
82
+ this.right = new KeyboardInput(domElement);
83
+ this.right.options.keys = DefaultMoveRightKeys;
84
+ this.right.bindValue(MoveRightAction, (isPressed) => (isPressed ? 1 : 0));
85
+ this.backward = new KeyboardInput(domElement);
86
+ this.backward.options.keys = DefaultMoveBackwardKeys;
87
+ this.backward.bindValue(MoveBackwardAction, (isPressed) => (isPressed ? 1 : 0));
88
+ this.jump = new KeyboardInput(domElement);
89
+ this.jump.options.keys = DefaultJumpKeys;
90
+ this.jump.bindEvent(JumpAction);
91
+ this.run = new KeyboardInput(domElement);
92
+ this.run.options.keys = DefaultRunKeys;
93
+ this.run.bindValue(RunAction);
94
+ }
95
+ dispose() { }
96
+ }
@@ -1,20 +1,15 @@
1
- import { Input, InputField } from './index.js';
2
- export type PointerCaptureInputOptions = {
3
- pointerCaptureRotationSpeed?: number;
4
- pointerCaptureZoomSpeed?: number;
5
- };
6
1
  /**
7
2
  * @requires to manually execute `domElement.setPointerCapture(pointerId)` on pointerdown
8
3
  */
9
- export declare class PointerCaptureInput implements Input {
4
+ export declare class PointerCaptureInput {
10
5
  private readonly domElement;
11
6
  private readonly abortController;
12
- private deltaZoom;
13
- private deltaYaw;
14
- private deltaPitch;
15
7
  private activePointers;
16
8
  private lastPinchDist;
17
- constructor(domElement: HTMLElement, options?: PointerCaptureInputOptions);
18
- get<T>(field: InputField<T>): T | undefined;
9
+ options: {
10
+ rotationSpeed?: number;
11
+ zoomSpeed?: number;
12
+ };
13
+ constructor(domElement: HTMLElement);
19
14
  dispose(): void;
20
15
  }
@@ -1,16 +1,14 @@
1
- import { DeltaPitchField, DeltaYawField, DeltaZoomField } from './index.js';
1
+ import { RotatePitchAction, RotateYawAction, ZoomAction } from './index.js';
2
2
  /**
3
3
  * @requires to manually execute `domElement.setPointerCapture(pointerId)` on pointerdown
4
4
  */
5
5
  export class PointerCaptureInput {
6
6
  domElement;
7
7
  abortController = new AbortController();
8
- deltaZoom = 0;
9
- deltaYaw = 0;
10
- deltaPitch = 0;
11
8
  activePointers = new Map();
12
9
  lastPinchDist = null;
13
- constructor(domElement, options = {}) {
10
+ options = {};
11
+ constructor(domElement) {
14
12
  this.domElement = domElement;
15
13
  domElement.addEventListener('pointerdown', (event) => {
16
14
  this.domElement.setPointerCapture(event.pointerId);
@@ -31,16 +29,16 @@ export class PointerCaptureInput {
31
29
  const pts = Array.from(this.activePointers.values());
32
30
  if (this.lastPinchDist != null) {
33
31
  const d = Math.hypot(pts[0].x - pts[1].x, pts[0].y - pts[1].y);
34
- const zoomSpeed = options.pointerCaptureZoomSpeed ?? 0.0001;
35
- this.deltaZoom += (this.lastPinchDist - d) * zoomSpeed;
32
+ const zoomSpeed = this.options.zoomSpeed ?? 0.0001;
33
+ ZoomAction.write((this.lastPinchDist - d) * zoomSpeed);
36
34
  this.lastPinchDist = d;
37
35
  }
38
36
  event.preventDefault();
39
37
  return;
40
38
  }
41
- const rotationSpeed = options.pointerCaptureRotationSpeed ?? 0.4;
42
- this.deltaYaw -= (rotationSpeed * event.movementX) / window.innerHeight;
43
- this.deltaPitch -= (rotationSpeed * event.movementY) / window.innerHeight;
39
+ const rotationSpeed = this.options.rotationSpeed ?? 0.4;
40
+ RotateYawAction.write(-(event.movementX / window.innerHeight) * rotationSpeed);
41
+ RotatePitchAction.write(-(event.movementY / window.innerHeight) * rotationSpeed);
44
42
  }, {
45
43
  signal: this.abortController.signal,
46
44
  });
@@ -64,30 +62,12 @@ export class PointerCaptureInput {
64
62
  });
65
63
  domElement.addEventListener('wheel', (event) => {
66
64
  event.preventDefault();
67
- const zoomSpeed = options.pointerCaptureZoomSpeed ?? 0.0001;
68
- this.deltaZoom += event.deltaY * zoomSpeed;
65
+ const zoomSpeed = this.options.zoomSpeed ?? 0.0001;
66
+ ZoomAction.write(event.deltaY * zoomSpeed);
69
67
  }, {
70
68
  signal: this.abortController.signal,
71
69
  });
72
70
  }
73
- get(field) {
74
- let result;
75
- switch (field) {
76
- case DeltaPitchField:
77
- result = this.deltaPitch;
78
- this.deltaPitch = 0;
79
- break;
80
- case DeltaYawField:
81
- result = this.deltaYaw;
82
- this.deltaYaw = 0;
83
- break;
84
- case DeltaZoomField:
85
- result = this.deltaZoom;
86
- this.deltaZoom = 0;
87
- break;
88
- }
89
- return result;
90
- }
91
71
  dispose() {
92
72
  this.abortController.abort();
93
73
  }
@@ -1,17 +1,12 @@
1
- import { Input, InputField } from './index.js';
2
- export type PointerLockInputOptions = {
3
- pointerLockRotationSpeed?: number;
4
- pointerLockZoomSpeed?: number;
5
- };
6
1
  /**
7
2
  * @requires to manually execute `domElement.requestPointerLock()`
8
3
  */
9
- export declare class PointerLockInput implements Input {
4
+ export declare class PointerLockInput {
10
5
  private readonly abortController;
11
- private deltaZoom;
12
- private deltaYaw;
13
- private deltaPitch;
14
- constructor(domElement: HTMLElement, options?: PointerLockInputOptions);
15
- get<T>(field: InputField<T>): T | undefined;
6
+ options: {
7
+ rotationSpeed?: number;
8
+ zoomSpeed?: number;
9
+ };
10
+ constructor(domElement: HTMLElement);
16
11
  dispose(): void;
17
12
  }
@@ -1,22 +1,19 @@
1
- import { DeltaPitchField, DeltaYawField, DeltaZoomField } from './index.js';
1
+ import { RotatePitchAction, RotateYawAction, ZoomAction } from './index.js';
2
2
  /**
3
3
  * @requires to manually execute `domElement.requestPointerLock()`
4
4
  */
5
5
  export class PointerLockInput {
6
6
  abortController = new AbortController();
7
- deltaZoom = 0;
8
- deltaYaw = 0;
9
- deltaPitch = 0;
10
- constructor(domElement, options = {}) {
7
+ options = {};
8
+ constructor(domElement) {
11
9
  domElement.addEventListener('pointermove', (event) => {
12
10
  if (document.pointerLockElement != domElement) {
13
11
  return;
14
12
  }
15
- const rotationSpeed = options.pointerLockRotationSpeed ?? 0.4;
16
- // Compute based on domElement bounds instead of window.innerHeight
17
13
  const rect = domElement.getBoundingClientRect();
18
- this.deltaYaw -= (rotationSpeed * event.movementX) / rect.height;
19
- this.deltaPitch -= (rotationSpeed * event.movementY) / rect.height;
14
+ const rotationSpeed = this.options.rotationSpeed ?? 0.4;
15
+ RotateYawAction.write(-(event.movementX / rect.height) * rotationSpeed);
16
+ RotatePitchAction.write(-(event.movementY / rect.height) * rotationSpeed);
20
17
  }, {
21
18
  signal: this.abortController.signal,
22
19
  });
@@ -24,31 +21,13 @@ export class PointerLockInput {
24
21
  if (document.pointerLockElement != domElement) {
25
22
  return;
26
23
  }
27
- const zoomSpeed = options.pointerLockZoomSpeed ?? 0.0001;
28
- this.deltaZoom += event.deltaY * zoomSpeed;
24
+ const zoomSpeed = this.options.zoomSpeed ?? 0.0001;
25
+ ZoomAction.write(event.deltaY * zoomSpeed);
29
26
  event.preventDefault();
30
27
  }, {
31
28
  signal: this.abortController.signal,
32
29
  });
33
30
  }
34
- get(field) {
35
- let result;
36
- switch (field) {
37
- case DeltaPitchField:
38
- result = this.deltaPitch;
39
- this.deltaPitch = 0;
40
- break;
41
- case DeltaYawField:
42
- result = this.deltaYaw;
43
- this.deltaYaw = 0;
44
- break;
45
- case DeltaZoomField:
46
- result = this.deltaZoom;
47
- this.deltaZoom = 0;
48
- break;
49
- }
50
- return result;
51
- }
52
31
  dispose() {
53
32
  this.abortController.abort();
54
33
  }