@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.
- package/dist/components/ARButton.svelte +10 -3
- package/dist/components/ARButton.svelte.d.ts +2 -4
- package/dist/components/Controller.svelte +86 -46
- package/dist/components/Controller.svelte.d.ts +10 -10
- package/dist/components/Hand.svelte +109 -60
- package/dist/components/Hand.svelte.d.ts +6 -6
- package/dist/components/Headset.svelte +6 -4
- package/dist/components/Headset.svelte.d.ts +0 -1
- package/dist/components/VRButton.svelte +8 -3
- package/dist/components/VRButton.svelte.d.ts +0 -1
- package/dist/components/XR.svelte +156 -96
- package/dist/components/XR.svelte.d.ts +8 -9
- package/dist/components/XRButton.svelte +71 -38
- package/dist/components/XRButton.svelte.d.ts +8 -9
- package/dist/components/internal/Cursor.svelte +38 -25
- package/dist/components/internal/Cursor.svelte.d.ts +3 -4
- package/dist/components/internal/PointerCursor.svelte +46 -34
- package/dist/components/internal/PointerCursor.svelte.d.ts +2 -2
- package/dist/components/internal/ScenePortal.svelte +15 -12
- package/dist/components/internal/ScenePortal.svelte.d.ts +0 -1
- package/dist/components/internal/ShortRay.svelte +23 -12
- package/dist/components/internal/ShortRay.svelte.d.ts +2 -2
- package/dist/components/internal/TeleportCursor.svelte +51 -37
- package/dist/components/internal/TeleportCursor.svelte.d.ts +2 -2
- package/dist/components/internal/TeleportRay.svelte +76 -53
- package/dist/components/internal/TeleportRay.svelte.d.ts +2 -2
- package/dist/hooks/useController.d.ts +0 -1
- package/dist/hooks/useHand.d.ts +1 -1
- package/dist/hooks/useHandJoint.d.ts +1 -1
- package/dist/hooks/useHitTest.d.ts +0 -1
- package/dist/hooks/useXR.d.ts +0 -1
- package/dist/internal/stores.d.ts +0 -1
- package/dist/lib/getXRSessionOptions.d.ts +0 -1
- package/dist/lib/getXRSupportState.d.ts +1 -2
- package/dist/lib/toggleXRSession.d.ts +1 -2
- package/dist/plugins/pointerControls/context.d.ts +2 -2
- package/dist/plugins/pointerControls/index.d.ts +1 -1
- package/dist/plugins/teleportControls/context.d.ts +3 -3
- package/dist/plugins/teleportControls/index.d.ts +1 -1
- package/dist/types.d.ts +0 -1
- package/package.json +8 -8
|
@@ -9,9 +9,16 @@
|
|
|
9
9
|
/>
|
|
10
10
|
```
|
|
11
11
|
-->
|
|
12
|
-
<script lang="ts">
|
|
13
|
-
import {
|
|
14
|
-
|
|
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?:
|
|
12
|
+
sessionInit?: XRSessionInit & {
|
|
15
13
|
domOverlay?: {
|
|
16
14
|
root: HTMLElement;
|
|
17
15
|
} | undefined;
|
|
18
|
-
}
|
|
16
|
+
};
|
|
19
17
|
}, {}, "">;
|
|
20
18
|
export default ArButton;
|
|
@@ -4,45 +4,61 @@
|
|
|
4
4
|
<script
|
|
5
5
|
lang="ts"
|
|
6
6
|
context="module"
|
|
7
|
-
>
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import
|
|
12
|
-
import
|
|
13
|
-
import
|
|
14
|
-
import
|
|
15
|
-
import
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
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">
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
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
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
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
|
|
6
|
-
grip?: Snippet
|
|
7
|
-
targetRay?: Snippet
|
|
8
|
-
pointerRay?: Snippet
|
|
9
|
-
pointerCursor?: Snippet
|
|
10
|
-
teleportRay?: Snippet
|
|
11
|
-
teleportCursor?: Snippet
|
|
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:
|
|
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
|
-
>
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import
|
|
9
|
-
import {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
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">
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
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
|
|
42
|
-
|
|
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
|
|
5
|
-
targetRay?: Snippet
|
|
6
|
-
wrist?: Snippet
|
|
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:
|
|
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">
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
4
|
-
|
|
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">
|
|
13
|
-
import {
|
|
14
|
-
|
|
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
|