@threlte/xr 1.0.0-next.12 → 1.0.0-next.14

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 (41) hide show
  1. package/dist/components/ARButton.svelte +10 -3
  2. package/dist/components/ARButton.svelte.d.ts +2 -4
  3. package/dist/components/Controller.svelte +86 -46
  4. package/dist/components/Controller.svelte.d.ts +10 -10
  5. package/dist/components/Hand.svelte +109 -60
  6. package/dist/components/Hand.svelte.d.ts +6 -6
  7. package/dist/components/Headset.svelte +6 -4
  8. package/dist/components/Headset.svelte.d.ts +0 -1
  9. package/dist/components/VRButton.svelte +8 -3
  10. package/dist/components/VRButton.svelte.d.ts +0 -1
  11. package/dist/components/XR.svelte +156 -96
  12. package/dist/components/XR.svelte.d.ts +8 -9
  13. package/dist/components/XRButton.svelte +71 -38
  14. package/dist/components/XRButton.svelte.d.ts +8 -9
  15. package/dist/components/internal/Cursor.svelte +38 -25
  16. package/dist/components/internal/Cursor.svelte.d.ts +3 -4
  17. package/dist/components/internal/PointerCursor.svelte +46 -34
  18. package/dist/components/internal/PointerCursor.svelte.d.ts +2 -2
  19. package/dist/components/internal/ScenePortal.svelte +15 -12
  20. package/dist/components/internal/ScenePortal.svelte.d.ts +0 -1
  21. package/dist/components/internal/ShortRay.svelte +23 -12
  22. package/dist/components/internal/ShortRay.svelte.d.ts +2 -2
  23. package/dist/components/internal/TeleportCursor.svelte +51 -37
  24. package/dist/components/internal/TeleportCursor.svelte.d.ts +2 -2
  25. package/dist/components/internal/TeleportRay.svelte +76 -53
  26. package/dist/components/internal/TeleportRay.svelte.d.ts +2 -2
  27. package/dist/hooks/useController.d.ts +0 -1
  28. package/dist/hooks/useHand.d.ts +1 -1
  29. package/dist/hooks/useHandJoint.d.ts +1 -1
  30. package/dist/hooks/useHitTest.d.ts +0 -1
  31. package/dist/hooks/useXR.d.ts +0 -1
  32. package/dist/internal/stores.d.ts +0 -1
  33. package/dist/lib/getXRSessionOptions.d.ts +0 -1
  34. package/dist/lib/getXRSupportState.d.ts +1 -2
  35. package/dist/lib/toggleXRSession.d.ts +1 -2
  36. package/dist/plugins/pointerControls/context.d.ts +2 -2
  37. package/dist/plugins/pointerControls/index.d.ts +1 -1
  38. package/dist/plugins/teleportControls/context.d.ts +3 -3
  39. package/dist/plugins/teleportControls/index.d.ts +1 -1
  40. package/dist/types.d.ts +0 -1
  41. package/package.json +8 -8
@@ -9,9 +9,16 @@
9
9
  />
10
10
  ```
11
11
  -->
12
- <script lang="ts">import XRButton from "./XRButton.svelte";
13
- import { defaultFeatures } from "../internal/defaultFeatures";
14
- let { children, ...props } = $props();
12
+ <script lang="ts">
13
+ import type { ComponentProps } from 'svelte'
14
+ import XRButton from './XRButton.svelte'
15
+ import { defaultFeatures } from '../internal/defaultFeatures'
16
+
17
+ type Props = Omit<ComponentProps<XRButton>, 'mode' | 'sessionInit'> & {
18
+ sessionInit?: XRSessionInit & { domOverlay?: { root: HTMLElement } | undefined }
19
+ }
20
+
21
+ let { children, ...props }: Props = $props()
15
22
  </script>
16
23
 
17
24
  <XRButton
@@ -1,5 +1,3 @@
1
- /// <reference types="webxr" />
2
- /// <reference types="svelte" />
3
1
  /**
4
2
  * `<ARButton />` is an HTML `<button />` that can be used to init and display info about your immersive AR session.
5
3
  *
@@ -11,10 +9,10 @@
11
9
  * ```
12
10
  */
13
11
  declare const ArButton: import("svelte").Component<Omit<Record<string, any>, "mode" | "sessionInit"> & {
14
- sessionInit?: (XRSessionInit & {
12
+ sessionInit?: XRSessionInit & {
15
13
  domOverlay?: {
16
14
  root: HTMLElement;
17
15
  } | undefined;
18
- }) | undefined;
16
+ };
19
17
  }, {}, "">;
20
18
  export default ArButton;
@@ -4,45 +4,61 @@
4
4
  <script
5
5
  lang="ts"
6
6
  context="module"
7
- >import { writable } from "svelte/store";
8
- import { T } from "@threlte/core";
9
- import { left as leftStore, right as rightStore } from "../hooks/useController";
10
- import { isHandTracking, pointerState, teleportState, controllerEvents } from "../internal/stores";
11
- import PointerCursor from "./internal/PointerCursor.svelte";
12
- import ShortRay from "./internal/ShortRay.svelte";
13
- import ScenePortal from "./internal/ScenePortal.svelte";
14
- import TeleportCursor from "./internal/TeleportCursor.svelte";
15
- import TeleportRay from "./internal/TeleportRay.svelte";
16
- const stores = {
17
- left: leftStore,
18
- right: rightStore
19
- };
7
+ >
8
+ import { writable } from 'svelte/store'
9
+ import { T } from '@threlte/core'
10
+ import { left as leftStore, right as rightStore } from '../hooks/useController'
11
+ import { isHandTracking, pointerState, teleportState, controllerEvents } from '../internal/stores'
12
+ import type { XRControllerEvents } from '../types'
13
+ import PointerCursor from './internal/PointerCursor.svelte'
14
+ import ShortRay from './internal/ShortRay.svelte'
15
+ import ScenePortal from './internal/ScenePortal.svelte'
16
+ import TeleportCursor from './internal/TeleportCursor.svelte'
17
+ import TeleportRay from './internal/TeleportRay.svelte'
18
+ import type { Snippet } from 'svelte'
19
+
20
+ const stores = {
21
+ left: leftStore,
22
+ right: rightStore
23
+ } as const
20
24
  </script>
21
25
 
22
- <script lang="ts">let {
23
- left,
24
- right,
25
- hand,
26
- onconnected,
27
- ondisconnected,
28
- onselect,
29
- onselectend,
30
- onselectstart,
31
- onsqueeze,
32
- onsqueezeend,
33
- onsqueezestart,
34
- children,
35
- grip: gripSnippet,
36
- targetRay: targetRaySnippet,
37
- pointerRay: pointerRaySnippet,
38
- pointerCursor: pointerCursorSnippet,
39
- teleportRay: teleportRaySnippet,
40
- teleportCursor: teleportCursorSnippet
41
- } = $props();
42
- const handedness = writable(left ? "left" : right ? "right" : hand);
43
- $effect.pre(() => handedness.set(left ? "left" : right ? "right" : hand));
44
- $effect.pre(
45
- () => controllerEvents[$handedness].set({
26
+ <script lang="ts">
27
+ type Props = {
28
+ children?: Snippet
29
+ grip?: Snippet
30
+ targetRay?: Snippet
31
+ pointerRay?: Snippet
32
+ pointerCursor?: Snippet
33
+ teleportRay?: Snippet
34
+ teleportCursor?: Snippet
35
+ } & XRControllerEvents &
36
+ (
37
+ | {
38
+ /** Whether the controller should be matched with the left hand. */
39
+ left: true
40
+ right?: undefined
41
+ hand?: undefined
42
+ }
43
+ | {
44
+ /** Whether the controller should be matched with the right hand. */
45
+ right: true
46
+ left?: undefined
47
+ hand?: undefined
48
+ }
49
+ | {
50
+ /** Whether the controller should be matched with the left or right hand. */
51
+ hand: 'left' | 'right'
52
+ left?: undefined
53
+ right?: undefined
54
+ }
55
+ )
56
+
57
+ let {
58
+ left,
59
+ right,
60
+ hand,
61
+
46
62
  onconnected,
47
63
  ondisconnected,
48
64
  onselect,
@@ -50,15 +66,39 @@ $effect.pre(
50
66
  onselectstart,
51
67
  onsqueeze,
52
68
  onsqueezeend,
53
- onsqueezestart
54
- })
55
- );
56
- let store = $derived(stores[$handedness]);
57
- let grip = $derived($store?.grip);
58
- let targetRay = $derived($store?.targetRay);
59
- let model = $derived($store?.model);
60
- let hasPointerControls = $derived($pointerState[$handedness].enabled);
61
- let hasTeleportControls = $derived($teleportState[$handedness].enabled);
69
+ onsqueezestart,
70
+
71
+ children,
72
+ grip: gripSnippet,
73
+ targetRay: targetRaySnippet,
74
+ pointerRay: pointerRaySnippet,
75
+ pointerCursor: pointerCursorSnippet,
76
+ teleportRay: teleportRaySnippet,
77
+ teleportCursor: teleportCursorSnippet
78
+ }: Props = $props()
79
+
80
+ const handedness = writable<'left' | 'right'>(left ? 'left' : right ? 'right' : hand)
81
+ $effect.pre(() => handedness.set(left ? 'left' : right ? 'right' : (hand as 'left' | 'right')))
82
+
83
+ $effect.pre(() =>
84
+ controllerEvents[$handedness].set({
85
+ onconnected,
86
+ ondisconnected,
87
+ onselect,
88
+ onselectend,
89
+ onselectstart,
90
+ onsqueeze,
91
+ onsqueezeend,
92
+ onsqueezestart
93
+ })
94
+ )
95
+
96
+ let store = $derived(stores[$handedness])
97
+ let grip = $derived($store?.grip)
98
+ let targetRay = $derived($store?.targetRay)
99
+ let model = $derived($store?.model)
100
+ let hasPointerControls = $derived($pointerState[$handedness].enabled)
101
+ let hasTeleportControls = $derived($teleportState[$handedness].enabled)
62
102
  </script>
63
103
 
64
104
  {#if !$isHandTracking}
@@ -2,14 +2,14 @@ import type { XRControllerEvents } from '../types';
2
2
  import type { Snippet } from 'svelte';
3
3
  /** `<Controller />` represents a THREE.XRTargetRaySpace, a THREE.XRGripSpace, and a controller model. */
4
4
  declare const Controller: import("svelte").Component<{
5
- children?: Snippet<[]> | undefined;
6
- grip?: Snippet<[]> | undefined;
7
- targetRay?: Snippet<[]> | undefined;
8
- pointerRay?: Snippet<[]> | undefined;
9
- pointerCursor?: Snippet<[]> | undefined;
10
- teleportRay?: Snippet<[]> | undefined;
11
- teleportCursor?: Snippet<[]> | undefined;
12
- } & XRControllerEvents & ({
5
+ children?: Snippet;
6
+ grip?: Snippet;
7
+ targetRay?: Snippet;
8
+ pointerRay?: Snippet;
9
+ pointerCursor?: Snippet;
10
+ teleportRay?: Snippet;
11
+ teleportCursor?: Snippet;
12
+ } & (XRControllerEvents & ({
13
13
  /** Whether the controller should be matched with the left hand. */
14
14
  left: true;
15
15
  right?: undefined;
@@ -21,8 +21,8 @@ declare const Controller: import("svelte").Component<{
21
21
  hand?: undefined;
22
22
  } | {
23
23
  /** Whether the controller should be matched with the left or right hand. */
24
- hand: 'left' | 'right';
24
+ hand: "left" | "right";
25
25
  left?: undefined;
26
26
  right?: undefined;
27
- }), {}, "">;
27
+ })), {}, "">;
28
28
  export default Controller;
@@ -1,72 +1,121 @@
1
1
  <script
2
2
  lang="ts"
3
3
  context="module"
4
- >import { Group } from "three";
5
- import { T, useThrelte, useTask } from "@threlte/core";
6
- import { isHandTracking, handEvents } from "../internal/stores";
7
- import { left as leftStore, right as rightStore } from "../hooks/useHand";
8
- import ScenePortal from "./internal/ScenePortal.svelte";
9
- import { writable } from "svelte/store";
10
- const stores = {
11
- left: leftStore,
12
- right: rightStore
13
- };
4
+ >
5
+ import { Group } from 'three'
6
+ import { T, useThrelte, useTask } from '@threlte/core'
7
+ import type { XRHandEvents } from '../types'
8
+ import { isHandTracking, handEvents } from '../internal/stores'
9
+ import { left as leftStore, right as rightStore } from '../hooks/useHand'
10
+ import ScenePortal from './internal/ScenePortal.svelte'
11
+ import { writable } from 'svelte/store'
12
+ import type { Snippet } from 'svelte'
13
+
14
+ const stores = {
15
+ left: leftStore,
16
+ right: rightStore
17
+ } as const
14
18
  </script>
15
19
 
16
- <script lang="ts">let {
17
- left,
18
- right,
19
- hand,
20
- onconnected,
21
- ondisconnected,
22
- onpinchend,
23
- onpinchstart,
24
- children,
25
- targetRay,
26
- wrist
27
- } = $props();
28
- const { renderer, scheduler, renderStage } = useThrelte();
29
- const { xr } = renderer;
30
- const space = xr.getReferenceSpace();
31
- const handedness = writable(left ? "left" : right ? "right" : hand);
32
- $effect.pre(() => handedness.set(left ? "left" : right ? "right" : hand));
33
- $effect.pre(
34
- () => handEvents[$handedness].set({
20
+ <script lang="ts">
21
+ type Props = {
22
+ children?: Snippet
23
+ targetRay?: Snippet
24
+ wrist?: Snippet
25
+ } & XRHandEvents &
26
+ (
27
+ | {
28
+ /** Whether the XRHand should be matched with the left hand. */
29
+ left: true
30
+ right?: undefined
31
+ hand?: undefined
32
+ }
33
+ | {
34
+ /** Whether the XRHand should be matched with the right hand. */
35
+ right: true
36
+ left?: undefined
37
+ hand?: undefined
38
+ }
39
+ | {
40
+ /** Whether the XRHand should be matched with the left or right hand. */
41
+ hand: 'left' | 'right'
42
+ left?: undefined
43
+ right?: undefined
44
+ }
45
+ )
46
+
47
+ let {
48
+ left,
49
+ right,
50
+ hand,
35
51
  onconnected,
36
52
  ondisconnected,
37
53
  onpinchend,
38
- onpinchstart
54
+ onpinchstart,
55
+ children,
56
+ targetRay,
57
+ wrist
58
+ }: Props = $props()
59
+
60
+ const { renderer, scheduler, renderStage } = useThrelte()
61
+ const { xr } = renderer
62
+ const space = xr.getReferenceSpace()
63
+
64
+ const handedness = writable<'left' | 'right'>(left ? 'left' : right ? 'right' : hand)
65
+ $effect.pre(() => handedness.set(left ? 'left' : right ? 'right' : (hand as 'left' | 'right')))
66
+
67
+ $effect.pre(() =>
68
+ handEvents[$handedness].set({
69
+ onconnected,
70
+ ondisconnected,
71
+ onpinchend,
72
+ onpinchstart
73
+ })
74
+ )
75
+
76
+ let group = new Group()
77
+
78
+ /**
79
+ * Currently children of a hand XRSpace or model will not
80
+ * move relative to their parent, so this hack of checking wrist position
81
+ * and syncing any snippets is used.
82
+ *
83
+ * @todo(mp) investigate why this is happening and see if there's
84
+ * a way to just parent to the hand to avoid this.
85
+ */
86
+ const { start, stop } = useTask(
87
+ () => {
88
+ const frame = xr.getFrame()
89
+ const joint = inputSource?.get('wrist' as unknown as number)
90
+
91
+ if (joint === undefined || space === null) return
92
+
93
+ const pose = frame.getJointPose?.(joint, space)
94
+
95
+ // This isn't correctly typed by @types/xr. Pose can also be null.
96
+ if (pose === undefined || pose === null) return
97
+
98
+ const { position, orientation } = pose.transform
99
+ group.position.set(position.x, position.y, position.z)
100
+ group.quaternion.set(orientation.x, orientation.y, orientation.z, orientation.w)
101
+ },
102
+ {
103
+ autoStart: false,
104
+ stage: scheduler.createStage(Symbol('xr-hand-stage'), { before: renderStage })
105
+ }
106
+ )
107
+
108
+ $effect.pre(() => {
109
+ if ($isHandTracking && (wrist !== undefined || children !== undefined) && inputSource) {
110
+ start()
111
+ } else {
112
+ stop()
113
+ }
39
114
  })
40
- );
41
- let group = new Group();
42
- const { start, stop } = useTask(
43
- () => {
44
- const frame = xr.getFrame();
45
- const joint = inputSource?.get("wrist");
46
- if (joint === void 0 || space === null)
47
- return;
48
- const pose = frame.getJointPose?.(joint, space);
49
- if (pose === void 0 || pose === null)
50
- return;
51
- const { position, orientation } = pose.transform;
52
- group.position.set(position.x, position.y, position.z);
53
- group.quaternion.set(orientation.x, orientation.y, orientation.z, orientation.w);
54
- },
55
- {
56
- autoStart: false,
57
- stage: scheduler.createStage(Symbol("xr-hand-stage"), { before: renderStage })
58
- }
59
- );
60
- $effect.pre(() => {
61
- if ($isHandTracking && (wrist !== void 0 || children !== void 0) && inputSource) {
62
- start();
63
- } else {
64
- stop();
65
- }
66
- });
67
- let store = $derived(stores[$handedness]);
68
- let inputSource = $derived($store?.inputSource);
69
- let model = $derived($store?.model);
115
+
116
+ let store = $derived(stores[$handedness])
117
+ let inputSource = $derived($store?.inputSource)
118
+ let model = $derived($store?.model)
70
119
  </script>
71
120
 
72
121
  {#if $store?.hand && $isHandTracking}
@@ -1,10 +1,10 @@
1
1
  import type { XRHandEvents } from '../types';
2
2
  import type { Snippet } from 'svelte';
3
3
  declare const Hand: import("svelte").Component<{
4
- children?: Snippet<[]> | undefined;
5
- targetRay?: Snippet<[]> | undefined;
6
- wrist?: Snippet<[]> | undefined;
7
- } & XRHandEvents & ({
4
+ children?: Snippet;
5
+ targetRay?: Snippet;
6
+ wrist?: Snippet;
7
+ } & (XRHandEvents & ({
8
8
  /** Whether the XRHand should be matched with the left hand. */
9
9
  left: true;
10
10
  right?: undefined;
@@ -16,8 +16,8 @@ declare const Hand: import("svelte").Component<{
16
16
  hand?: undefined;
17
17
  } | {
18
18
  /** Whether the XRHand should be matched with the left or right hand. */
19
- hand: 'left' | 'right';
19
+ hand: "left" | "right";
20
20
  left?: undefined;
21
21
  right?: undefined;
22
- }), {}, "">;
22
+ })), {}, "">;
23
23
  export default Hand;
@@ -1,7 +1,9 @@
1
- <script lang="ts">import { T } from "@threlte/core";
2
- import { useHeadset } from "../hooks/useHeadset";
3
- import ScenePortal from "./internal/ScenePortal.svelte";
4
- const headset = useHeadset();
1
+ <script lang="ts">
2
+ import { T } from '@threlte/core'
3
+ import { useHeadset } from '../hooks/useHeadset'
4
+ import ScenePortal from './internal/ScenePortal.svelte'
5
+
6
+ const headset = useHeadset()
5
7
  </script>
6
8
 
7
9
  <ScenePortal>
@@ -1,4 +1,3 @@
1
- /// <reference types="svelte" />
2
1
  interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
3
2
  new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
4
3
  $$bindings?: Bindings;
@@ -9,9 +9,14 @@
9
9
  />
10
10
  ```
11
11
  -->
12
- <script lang="ts">import XRButton from "./XRButton.svelte";
13
- import { defaultFeatures } from "../internal/defaultFeatures";
14
- let { ...props } = $props();
12
+ <script lang="ts">
13
+ import type { ComponentProps } from 'svelte'
14
+ import XRButton from './XRButton.svelte'
15
+ import { defaultFeatures } from '../internal/defaultFeatures'
16
+
17
+ type Props = Omit<ComponentProps<XRButton>, 'mode' | 'sessionInit'>
18
+
19
+ let { ...props }: Props = $props()
15
20
  </script>
16
21
 
17
22
  <XRButton
@@ -1,4 +1,3 @@
1
- /// <reference types="svelte" />
2
1
  /**
3
2
  * `<VRButton />` is an HTML `<button />` that can be used to init and display info about your immersive VR session.
4
3
  *