@threlte/xr 0.0.4 → 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -9,13 +9,8 @@ import { onDestroy } from "svelte";
9
9
  import { XRControllerModelFactory } from "three/examples/jsm/webxr/XRControllerModelFactory";
10
10
  import ShortRay from "./ShortRay.svelte";
11
11
  import { gaze, left as leftStore, right as rightStore } from "../hooks/useController";
12
- import { useControllerEvent } from "../hooks/useEvent";
13
- import { fire } from "../internal/events";
14
- import {
15
- activeTeleportController,
16
- isHandTracking,
17
- pendingTeleportDestination
18
- } from "../internal/stores";
12
+ import { activeTeleportController, pendingTeleportDestination, isHandTracking } from "../internal/stores";
13
+ import { useHandTrackingState } from "../internal/useHandTrackingState";
19
14
  const factory = new XRControllerModelFactory();
20
15
  const stores = {
21
16
  left: leftStore,
@@ -33,35 +28,38 @@ const events = [
33
28
  const eventMap = /* @__PURE__ */ new WeakMap();
34
29
  </script>
35
30
 
36
- <script>export let left = false;
37
- export let right = false;
31
+ <script>export let left = void 0;
32
+ export let right = void 0;
33
+ export let hand = void 0;
38
34
  $:
39
- if (left && right) {
40
- throw new Error("A <Controller> component can only specify one hand.");
41
- }
42
- $:
43
- if (!left && !right) {
44
- throw new Error("A <Controller> component must specify a hand.");
45
- }
46
- $:
47
- handedness = left ? "left" : "right";
35
+ handedness = left ? "left" : right ? "right" : hand;
48
36
  const dispatch = createRawEventDispatcher();
49
37
  const { xr } = useThrelte().renderer;
38
+ const handTrackingNow = useHandTrackingState();
39
+ const handleEvent = (event) => {
40
+ if (!handTrackingNow()) {
41
+ dispatch(event.type, event);
42
+ }
43
+ };
50
44
  const handleConnected = (event) => {
51
- const data = event.data;
52
45
  const targetData = eventMap.get(event.target);
53
- if (data.handedness !== handedness || !targetData)
46
+ if (event.data.handedness !== handedness || !targetData)
54
47
  return;
55
- stores[data.handedness].set({ ...targetData, inputSource: data });
56
- fire("connected", event, { input: "controller" });
48
+ stores[handedness].set({ ...targetData, inputSource: event.data });
49
+ if (!handTrackingNow()) {
50
+ dispatch("connected", event);
51
+ }
52
+ events.forEach((name) => event.target.addEventListener(name, handleEvent));
57
53
  };
58
54
  const handleDisconnected = (event) => {
59
55
  if (event.data.handedness !== handedness)
60
56
  return;
61
- stores[event.data.handedness].set(void 0);
62
- fire("disconnected", event, { input: "controller" });
57
+ stores[handedness].set(void 0);
58
+ if (!$isHandTracking) {
59
+ dispatch("disconnected", event);
60
+ }
61
+ events.forEach((name) => event.target.removeEventListener(name, handleEvent));
63
62
  };
64
- const handleEvent = (event) => fire(event.type, event);
65
63
  for (const index of [0, 1]) {
66
64
  const controller = xr.getController(index);
67
65
  const grip2 = xr.getControllerGrip(index);
@@ -69,28 +67,24 @@ for (const index of [0, 1]) {
69
67
  eventMap.set(controller, { targetRay: controller, model: model2, grip: grip2 });
70
68
  controller.addEventListener("connected", handleConnected);
71
69
  controller.addEventListener("disconnected", handleDisconnected);
72
- events.forEach((name) => controller.addEventListener(name, handleEvent));
73
70
  }
74
71
  $:
75
- store = left ? stores.left : stores.right;
72
+ store = stores[handedness];
76
73
  $:
77
74
  grip = $store?.grip;
78
75
  $:
79
76
  targetRay = $store?.targetRay;
80
77
  $:
81
78
  model = $store?.model;
82
- for (const type of ["connected", "disconnected", ...events]) {
83
- useControllerEvent(type, (event) => dispatch(type, event), {
84
- handedness: left ? "left" : "right"
85
- });
86
- }
87
79
  onDestroy(() => {
88
80
  for (const index of [0, 1]) {
89
- const controller = xr.getController(index);
90
- controller.removeEventListener("connected", handleConnected);
91
- controller.removeEventListener("disconnected", handleDisconnected);
92
- events.forEach((name) => controller.removeEventListener(name, handleEvent));
81
+ const controller2 = xr.getController(index);
82
+ controller2.removeEventListener("connected", handleConnected);
83
+ controller2.removeEventListener("disconnected", handleDisconnected);
93
84
  }
85
+ const controller = $store?.targetRay;
86
+ events.forEach((name) => controller?.removeEventListener(name, handleEvent));
87
+ store.set(void 0);
94
88
  });
95
89
  </script>
96
90
 
@@ -2,9 +2,20 @@ import { SvelteComponent } from "svelte";
2
2
  import type { XRControllerEvent } from '../types';
3
3
  declare const __propDef: {
4
4
  props: {
5
+ /** Whether the controller should be matched with the left hand. */
5
6
  left: true;
7
+ right?: undefined;
8
+ hand?: undefined;
6
9
  } | {
10
+ /** Whether the controller should be matched with the right hand. */
7
11
  right: true;
12
+ left?: undefined;
13
+ hand?: undefined;
14
+ } | {
15
+ /** Whether the controller should be matched with the left or right hand. */
16
+ hand: 'left' | 'right';
17
+ left?: undefined;
18
+ right?: undefined;
8
19
  };
9
20
  slots: {
10
21
  default: {};
@@ -1,8 +1,8 @@
1
1
  <script context='module'>import { T, useThrelte, createRawEventDispatcher, useFrame } from "@threlte/core";
2
2
  import { XRHandModelFactory } from "three/examples/jsm/webxr/XRHandModelFactory";
3
- import { fire } from "../internal/events";
3
+ import { isHandTracking } from "../internal/stores";
4
+ import { useHandTrackingState } from "../internal/useHandTrackingState";
4
5
  import { left as leftStore, right as rightStore } from "../hooks/useHand";
5
- import { useHandEvent } from "../hooks/useEvent";
6
6
  import { onDestroy } from "svelte";
7
7
  const factory = new XRHandModelFactory();
8
8
  const stores = {
@@ -12,48 +12,38 @@ const stores = {
12
12
  const eventMap = /* @__PURE__ */ new WeakMap();
13
13
  </script>
14
14
 
15
- <script>export let left = false;
16
- export let right = false;
15
+ <script>export let left = void 0;
16
+ export let right = void 0;
17
+ export let hand = void 0;
18
+ const handTrackingNow = useHandTrackingState();
17
19
  const dispatch = createRawEventDispatcher();
18
20
  const { xr } = useThrelte().renderer;
19
21
  const space = xr.getReferenceSpace();
20
22
  $:
21
- if (left && right) {
22
- throw new Error("A <Hand> component can only specify one hand.");
23
- }
24
- $:
25
- if (!left && !right) {
26
- throw new Error("A <Hand> component must specify a hand.");
27
- }
28
- $:
29
- handedness = left ? "left" : "right";
23
+ handedness = left ? "left" : right ? "right" : hand;
30
24
  const handleConnected = (event) => {
31
- const inputSource2 = event.data.hand;
32
- const eventHandedness = event.data.handedness;
33
- if (eventHandedness !== handedness)
25
+ if (event.data.handedness !== handedness)
34
26
  return;
35
- stores[handedness].set({ ...eventMap.get(event.target), inputSource: inputSource2 });
36
- fire("connected", event, { input: "hand" });
27
+ stores[handedness].set({ ...eventMap.get(event.target), inputSource: event.data.hand });
28
+ if (handTrackingNow()) {
29
+ dispatch("connected", event);
30
+ }
31
+ event.target.addEventListener("pinchstart", handlePinchEvent);
32
+ event.target.addEventListener("pinchend", handlePinchEvent);
37
33
  };
38
34
  const handleDisconnected = (event) => {
39
- const eventHandedness = event.data.handedness;
40
- if (eventHandedness !== handedness)
35
+ if (event.data.handedness !== handedness)
41
36
  return;
42
37
  stores[handedness].set(void 0);
43
- fire("disconnected", event, { input: "hand" });
38
+ if ($isHandTracking) {
39
+ dispatch("disconnected", event);
40
+ }
41
+ event.target.removeEventListener("pinchstart", handlePinchEvent);
42
+ event.target.removeEventListener("pinchend", handlePinchEvent);
44
43
  };
45
44
  const handlePinchEvent = (event) => {
46
- fire(event.type, event);
45
+ dispatch(event.type, event);
47
46
  };
48
- for (const index of [0, 1]) {
49
- const hand2 = xr.getHand(index);
50
- const model2 = factory.createHandModel(hand2, "mesh");
51
- eventMap.set(hand2, { hand: hand2, model: model2 });
52
- hand2.addEventListener("connected", handleConnected);
53
- hand2.addEventListener("disconnected", handleDisconnected);
54
- hand2.addEventListener("pinchstart", handlePinchEvent);
55
- hand2.addEventListener("pinchend", handlePinchEvent);
56
- }
57
47
  let children;
58
48
  const { start, stop } = useFrame(() => {
59
49
  const frame = xr.getFrame();
@@ -74,32 +64,30 @@ $:
74
64
  stop();
75
65
  }
76
66
  $:
77
- store = left ? stores.left : stores.right;
67
+ store = stores[handedness];
78
68
  $:
79
69
  hand = $store?.hand;
80
70
  $:
81
71
  inputSource = $store?.inputSource;
82
72
  $:
83
73
  model = $store?.model;
84
- const handEvents = [
85
- "connected",
86
- "disconnected",
87
- "pinchstart",
88
- "pinchend"
89
- ];
90
- for (const name of handEvents) {
91
- useHandEvent(name, (event) => dispatch(name, event), {
92
- handedness: left ? "left" : "right"
93
- });
74
+ for (const index of [0, 1]) {
75
+ const hand2 = xr.getHand(index);
76
+ const model2 = factory.createHandModel(hand2, "mesh");
77
+ eventMap.set(hand2, { hand: hand2, model: model2 });
78
+ hand2.addEventListener("connected", handleConnected);
79
+ hand2.addEventListener("disconnected", handleDisconnected);
94
80
  }
95
81
  onDestroy(() => {
96
82
  for (const index of [0, 1]) {
97
- const hand2 = xr.getHand(index);
98
- hand2.removeEventListener("connected", handleConnected);
99
- hand2.removeEventListener("disconnected", handleDisconnected);
100
- hand2.removeEventListener("pinchstart", handlePinchEvent);
101
- hand2.removeEventListener("pinchend", handlePinchEvent);
83
+ const hand3 = xr.getHand(index);
84
+ hand3.removeEventListener("connected", handleConnected);
85
+ hand3.removeEventListener("disconnected", handleDisconnected);
102
86
  }
87
+ const hand2 = stores[handedness].current?.hand;
88
+ hand2?.removeEventListener("pinchstart", handlePinchEvent);
89
+ hand2?.removeEventListener("pinchend", handlePinchEvent);
90
+ stores[handedness].set(void 0);
103
91
  });
104
92
  </script>
105
93
 
@@ -2,18 +2,30 @@ import { SvelteComponent } from "svelte";
2
2
  import type { XRHandEvent } from '../types';
3
3
  declare const __propDef: {
4
4
  props: {
5
- /** Whether the XRHand should be matched with the left hand. */ left?: boolean;
6
- /** Whether the XRHand should be matched with the right hand. */ right?: boolean;
5
+ /** Whether the XRHand should be matched with the left hand. */
6
+ left: true;
7
+ right?: undefined;
8
+ hand?: undefined;
9
+ } | {
10
+ /** Whether the XRHand should be matched with the right hand. */
11
+ right: true;
12
+ left?: undefined;
13
+ hand?: undefined;
14
+ } | {
15
+ /** Whether the XRHand should be matched with the left or right hand. */
16
+ hand: 'left' | 'right';
17
+ left?: undefined;
18
+ right?: undefined;
7
19
  };
8
20
  slots: {
9
21
  wrist: {};
10
22
  default: {};
11
23
  };
12
24
  events: {
13
- connected: XRHandEvent<'connected', null>;
14
- disconnected: XRHandEvent<'disconnected', null>;
15
- pinchstart: XRHandEvent<'pinchstart', THREE.XRHandSpace>;
16
- pinchend: XRHandEvent<'pinchend', THREE.XRHandSpace>;
25
+ connected: XRHandEvent<'connected'>;
26
+ disconnected: XRHandEvent<'disconnected'>;
27
+ pinchstart: XRHandEvent<'pinchstart'>;
28
+ pinchend: XRHandEvent<'pinchend'>;
17
29
  };
18
30
  };
19
31
  export type HandProps = typeof __propDef.props;
@@ -1,21 +1,37 @@
1
1
  <script>import { T, HierarchicalObject, useFrame, useThrelte } from "@threlte/core";
2
2
  import { Group } from "three";
3
- import { useBaseReferenceSpace } from "../internal/useBaseReferenceSpace";
4
- const { renderer, scene } = useThrelte();
3
+ import { useXR } from "../hooks";
4
+ const { isPresenting } = useXR();
5
+ const { renderer, scene, camera } = useThrelte();
6
+ const { xr } = renderer;
5
7
  const group = new Group();
6
- const baseReferenceSpace = useBaseReferenceSpace();
7
- useFrame(() => {
8
- const space = baseReferenceSpace.current;
8
+ const immersiveFrame = useFrame(() => {
9
+ const space = xr.getReferenceSpace();
9
10
  if (space === null)
10
11
  return;
11
- const frame = renderer.xr.getFrame();
12
- const pose = frame.getViewerPose(space);
12
+ const pose = xr.getFrame().getViewerPose(space);
13
13
  if (pose === void 0)
14
14
  return;
15
15
  const { position, orientation } = pose.transform;
16
16
  group.position.set(position.x, position.y, position.z);
17
17
  group.quaternion.set(orientation.x, orientation.y, orientation.z, orientation.w);
18
- });
18
+ }, { autostart: false });
19
+ $:
20
+ if ($isPresenting) {
21
+ immersiveFrame.start();
22
+ } else {
23
+ immersiveFrame.stop();
24
+ }
25
+ const nonImmersiveFrame = useFrame(() => {
26
+ group.position.copy(camera.current.position);
27
+ group.quaternion.copy(camera.current.quaternion);
28
+ }, { autostart: false });
29
+ $:
30
+ if ($isPresenting === false) {
31
+ nonImmersiveFrame.start();
32
+ } else {
33
+ nonImmersiveFrame.stop();
34
+ }
19
35
  </script>
20
36
 
21
37
  <HierarchicalObject
@@ -46,7 +46,7 @@ const handleVisibilityChange = (event) => {
46
46
  dispatch("visibilitychange", { ...event, target: $session });
47
47
  };
48
48
  const handleInputSourcesChange = (event) => {
49
- $isHandTracking = Object.values($session.inputSources).some((source) => source.hand);
49
+ $isHandTracking = Object.values(event.session.inputSources).some((source) => source.hand);
50
50
  dispatch("inputsourceschange", { ...event, target: $session });
51
51
  };
52
52
  const handleFramerateChange = (event) => {
@@ -1,5 +1,4 @@
1
1
  export { useController, useGamepad } from './useController';
2
- export { useControllerEvent, useHandEvent } from './useEvent';
3
2
  export { useHand } from './useHand';
4
3
  export { useHandJoint } from './useHandJoint';
5
4
  export { useHitTest } from './useHitTest';
@@ -1,5 +1,4 @@
1
1
  export { useController, useGamepad } from './useController';
2
- export { useControllerEvent, useHandEvent } from './useEvent';
3
2
  export { useHand } from './useHand';
4
3
  export { useHandJoint } from './useHandJoint';
5
4
  export { useHitTest } from './useHitTest';
@@ -1,6 +1,6 @@
1
1
  import * as THREE from 'three';
2
2
  /**
3
- * Returns a callback to teleport the player to a position.
3
+ * Returns a callback to teleport the player from the world origin to a position and optional orientation.
4
4
  *
5
5
  * @example
6
6
  * const teleport = useTeleport()
@@ -9,5 +9,9 @@ import * as THREE from 'three';
9
9
  * vec3.set(5, 0, 5)
10
10
  *
11
11
  * teleport(vec3)
12
+ *
13
+ * const quat = new THREE.Quaternion()
14
+ *
15
+ * teleport(vec3, quat)
12
16
  */
13
- export declare const useTeleport: () => (position: THREE.Vector3 | THREE.Vector3Tuple, direction?: THREE.Quaternion) => void;
17
+ export declare const useTeleport: () => (position: THREE.Vector3 | THREE.Vector3Tuple, orientation?: THREE.Quaternion) => void;
@@ -1,10 +1,9 @@
1
1
  import * as THREE from 'three';
2
2
  import { useThrelte } from '@threlte/core';
3
- import { useBaseReferenceSpace } from '../internal/useBaseReferenceSpace';
4
3
  const quaternion = new THREE.Quaternion();
5
4
  const offset = { x: 0, y: 0, z: 0 };
6
5
  /**
7
- * Returns a callback to teleport the player to a position.
6
+ * Returns a callback to teleport the player from the world origin to a position and optional orientation.
8
7
  *
9
8
  * @example
10
9
  * const teleport = useTeleport()
@@ -13,36 +12,37 @@ const offset = { x: 0, y: 0, z: 0 };
13
12
  * vec3.set(5, 0, 5)
14
13
  *
15
14
  * teleport(vec3)
15
+ *
16
+ * const quat = new THREE.Quaternion()
17
+ *
18
+ * teleport(vec3, quat)
16
19
  */
17
20
  export const useTeleport = () => {
18
21
  const { xr } = useThrelte().renderer;
19
- const baseReferenceSpace = useBaseReferenceSpace();
22
+ let space = xr.getReferenceSpace();
20
23
  /**
21
- * Teleports a player to a position - and optionally a direction.
24
+ * Teleports a player from the world origin to a position and optional orientation.
22
25
  */
23
- return (position, direction = quaternion) => {
24
- const space = baseReferenceSpace.current;
25
- if (space === null || space === undefined)
26
+ return (position, orientation = quaternion) => {
27
+ space ??= xr.getReferenceSpace();
28
+ if (space === null)
26
29
  return;
27
- let x = 0, y = 0, z = 0;
28
30
  if (Array.isArray(position)) {
29
- ;
30
- [x, y, z] = position;
31
+ offset.x = -position[0];
32
+ offset.y = -position[1];
33
+ offset.z = -position[2];
31
34
  }
32
35
  else {
33
- x = position.x;
34
- y = position.y;
35
- z = position.z;
36
+ offset.x = -position.x;
37
+ offset.y = -position.y;
38
+ offset.z = -position.z;
36
39
  }
37
- offset.x = -x;
38
- offset.y = -y;
39
- offset.z = -z;
40
- const pose = xr.getFrame().getViewerPose(space);
40
+ const pose = xr.getFrame()?.getViewerPose(space);
41
41
  if (pose !== undefined) {
42
42
  offset.x += pose.transform.position.x;
43
43
  offset.z += pose.transform.position.z;
44
44
  }
45
- const teleportOffset = new XRRigidTransform(offset, direction);
45
+ const teleportOffset = new XRRigidTransform(offset, orientation);
46
46
  xr.setReferenceSpace(space.getOffsetReferenceSpace(teleportOffset));
47
47
  };
48
48
  };
@@ -0,0 +1,5 @@
1
+ /**
2
+ * There are some cases where we need to know if hand tracking is now active before an input source
3
+ * connection or disconnection event. This is the way to do that.
4
+ */
5
+ export declare const useHandTrackingState: () => () => boolean;
@@ -0,0 +1,17 @@
1
+ import { useThrelte } from '@threlte/core';
2
+ /**
3
+ * There are some cases where we need to know if hand tracking is now active before an input source
4
+ * connection or disconnection event. This is the way to do that.
5
+ */
6
+ export const useHandTrackingState = () => {
7
+ const { xr } = useThrelte().renderer;
8
+ return () => {
9
+ let handTracking = false;
10
+ xr.getSession()?.inputSources.forEach((value) => {
11
+ if (value.hand) {
12
+ handTracking = true;
13
+ }
14
+ });
15
+ return handTracking;
16
+ };
17
+ };
package/dist/types.d.ts CHANGED
@@ -10,8 +10,8 @@ export type XRSessionEvent<Type = XRSessionEventType> = THREE.Event & {
10
10
  };
11
11
  export type XRControllerEvent<Type = XRControllerEventType> = THREE.Event & {
12
12
  type: Type;
13
- target: any;
14
- data?: XRInputSource;
13
+ target: THREE.Group;
14
+ data: XRInputSource;
15
15
  };
16
16
  export type XRController = {
17
17
  targetRay: THREE.XRTargetRaySpace;
@@ -24,8 +24,13 @@ export type XRHand = {
24
24
  model?: XRHandModel;
25
25
  inputSource: globalThis.XRHand;
26
26
  };
27
- export type XRHandEvent<Type = XRHandEventType, Target = null | THREE.XRHandSpace> = THREE.Event & {
27
+ export type XRHandEvent<Type = XRHandEventType> = Type extends 'connected' | 'disconnected' ? {
28
28
  type: Type;
29
- target: Target;
30
- };
29
+ target: THREE.XRHandSpace;
30
+ data: XRInputSource;
31
+ } : Type extends 'pinchstart' | 'pinchend' ? {
32
+ type: Type;
33
+ handedness: 'left' | 'right';
34
+ target: null;
35
+ } : never;
31
36
  export type HitTestCallback = (hitMatrix: THREE.Matrix4, hit: XRHitTestResult) => void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@threlte/xr",
3
- "version": "0.0.4",
3
+ "version": "0.0.5",
4
4
  "author": "Micheal Parks <michealparks1989@gmail.com> (https://parks.lol)",
5
5
  "license": "MIT",
6
6
  "devDependencies": {
@@ -1,35 +0,0 @@
1
- <!--
2
- @component
3
- Creates XRHand inputs for devices that allow hand tracking.
4
- -->
5
- <script>import { createRawEventDispatcher } from "@threlte/core";
6
- import Hand from "./Hand.svelte";
7
- export let profile = "mesh";
8
- const dispatch = createRawEventDispatcher();
9
- const handedness = [void 0, void 0];
10
- const setHandedness = (index, event) => {
11
- if (event.data) {
12
- handedness[index] = event.data.handedness;
13
- }
14
- };
15
- </script>
16
-
17
- {#each [0, 1] as index (index)}
18
- <Hand
19
- {index}
20
- {profile}
21
- on:connected={(event) => {
22
- setHandedness(index, event)
23
- dispatch(event.type, event)
24
- }}
25
- on:disconnected
26
- on:pinchstart
27
- on:pinchend
28
- >
29
- {#if handedness[index] === 'left'}
30
- <slot name='left' />
31
- {:else if handedness[index] === 'right'}
32
- <slot name='right' />
33
- {/if}
34
- </Hand>
35
- {/each}
@@ -1,24 +0,0 @@
1
- import { SvelteComponent } from "svelte";
2
- import type { XRHandEvent } from '../types';
3
- declare const __propDef: {
4
- props: {
5
- profile?: 'mesh' | 'spheres' | 'boxes' | 'none';
6
- };
7
- slots: {
8
- left: {};
9
- right: {};
10
- };
11
- events: {
12
- connected: XRHandEvent<'connected', null>;
13
- disconnected: XRHandEvent<'disconnected', null>;
14
- pinchstart: XRHandEvent<'pinchstart', THREE.XRHandSpace>;
15
- pinchend: XRHandEvent<'pinchend', THREE.XRHandSpace>;
16
- };
17
- };
18
- export type HandsProps = typeof __propDef.props;
19
- export type HandsEvents = typeof __propDef.events;
20
- export type HandsSlots = typeof __propDef.slots;
21
- /** Creates XRHand inputs for devices that allow hand tracking. */
22
- export default class Hands extends SvelteComponent<HandsProps, HandsEvents, HandsSlots> {
23
- }
24
- export {};
@@ -1,14 +0,0 @@
1
- /// <reference types="webxr" />
2
- import type { XRControllerEvent, XRControllerEventType, XRHandEvent, XRHandEventType } from '../types';
3
- /**
4
- * Adds listeners for controller events.
5
- */
6
- export declare const useControllerEvent: (event: XRControllerEventType, handler: (event: XRControllerEvent) => void, { handedness }?: {
7
- handedness?: XRHandedness;
8
- }) => void;
9
- /**
10
- * Adds listeners for hand events.
11
- */
12
- export declare const useHandEvent: (event: XRHandEventType, handler: (event: XRHandEvent<XRHandEventType, null | THREE.XRHandSpace>) => void, { handedness }?: {
13
- handedness?: 'left' | 'right';
14
- }) => void;
@@ -1,33 +0,0 @@
1
- import { onDestroy } from 'svelte';
2
- import { off, on } from '../internal/events';
3
- /**
4
- * Adds listeners for controller events.
5
- */
6
- export const useControllerEvent = (event, handler, { handedness } = {}) => {
7
- const listener = (event, metadata) => {
8
- if (metadata?.input === 'hand')
9
- return;
10
- if (handedness !== undefined && event.data?.handedness !== handedness) {
11
- return;
12
- }
13
- handler(event);
14
- };
15
- on(event, listener);
16
- onDestroy(() => off(event, listener));
17
- };
18
- /**
19
- * Adds listeners for hand events.
20
- */
21
- export const useHandEvent = (event, handler, { handedness } = {}) => {
22
- const listener = (event, metadata) => {
23
- if (metadata?.input === 'controller')
24
- return;
25
- const eventHandedness = event.handedness ?? event.data?.handedness;
26
- if (handedness !== undefined && eventHandedness !== handedness) {
27
- return;
28
- }
29
- handler(event);
30
- };
31
- on(event, listener);
32
- onDestroy(() => off(event, listener));
33
- };
@@ -1,5 +0,0 @@
1
- type Callback<T = any, O = any> = (event: T, metadata?: O) => void;
2
- export declare const on: <T, O = any>(name: string, cb: Callback<T, O>) => (() => void);
3
- export declare const off: <T>(name: string, cb: Callback<T, any>) => void;
4
- export declare const fire: <T, O = any>(name: string, payload: T, metadata?: O | undefined) => void;
5
- export {};
@@ -1,26 +0,0 @@
1
- const events = {};
2
- export const on = (name, cb) => {
3
- const fns = events[name];
4
- if (fns === undefined) {
5
- events[name] = [cb];
6
- }
7
- else {
8
- fns.push(cb);
9
- }
10
- return () => off(name, cb);
11
- };
12
- export const off = (name, cb) => {
13
- const arr = events[name];
14
- if (arr === undefined)
15
- return;
16
- arr.splice(arr.indexOf(cb), 1);
17
- if (arr.length === 0)
18
- delete events[name];
19
- };
20
- export const fire = (name, payload, metadata) => {
21
- const fns = events[name];
22
- if (fns === undefined)
23
- return;
24
- for (const fn of fns)
25
- fn(payload, metadata);
26
- };
@@ -1,6 +0,0 @@
1
- /// <reference types="webxr" />
2
- /**
3
- * Provides a reference space of the world origin,
4
- * useful for determining offsets using XRReferenceSpace
5
- */
6
- export declare const useBaseReferenceSpace: () => import("@threlte/core").CurrentWritable<XRReferenceSpace | null>;
@@ -1,19 +0,0 @@
1
- import { onDestroy } from 'svelte';
2
- import { useThrelte, currentWritable } from '@threlte/core';
3
- import { session } from './stores';
4
- /**
5
- * Provides a reference space of the world origin,
6
- * useful for determining offsets using XRReferenceSpace
7
- */
8
- export const useBaseReferenceSpace = () => {
9
- const { xr } = useThrelte().renderer;
10
- const baseReferenceSpace = currentWritable(null);
11
- onDestroy(session.subscribe((value) => {
12
- if (value === undefined) {
13
- baseReferenceSpace.set(null);
14
- return;
15
- }
16
- baseReferenceSpace.set(xr.getReferenceSpace());
17
- }));
18
- return baseReferenceSpace;
19
- };