@threlte/xr 1.0.0-next.3 → 1.0.0-next.4
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 +6 -4
- package/dist/components/Controller.svelte +31 -39
- package/dist/components/Controller.svelte.d.ts +25 -15
- package/dist/components/Hand.svelte +29 -14
- package/dist/components/Hand.svelte.d.ts +13 -11
- package/dist/components/VRButton.svelte +2 -1
- package/dist/components/internal/Cursor.svelte.d.ts +3 -3
- package/dist/components/internal/PointerCursor.svelte +5 -3
- package/dist/components/internal/PointerCursor.svelte.d.ts +1 -4
- package/dist/components/internal/ShortRay.svelte +23 -21
- package/dist/components/internal/ShortRay.svelte.d.ts +1 -4
- package/dist/components/internal/TeleportCursor.svelte +5 -3
- package/dist/components/internal/TeleportCursor.svelte.d.ts +1 -4
- package/dist/components/internal/TeleportRay.svelte +5 -3
- package/dist/components/internal/TeleportRay.svelte.d.ts +1 -4
- package/dist/internal/defaultFeatures.d.ts +4 -0
- package/dist/internal/defaultFeatures.js +14 -0
- package/dist/internal/setupControllers.js +1 -1
- package/dist/internal/setupHands.js +1 -1
- package/dist/internal/setupHeadset.js +14 -5
- package/dist/internal/setupRaf.js +8 -12
- package/dist/types.d.ts +21 -19
- package/package.json +1 -1
|
@@ -10,15 +10,17 @@
|
|
|
10
10
|
```
|
|
11
11
|
-->
|
|
12
12
|
<script lang="ts">import XRButton from "./XRButton.svelte";
|
|
13
|
-
|
|
13
|
+
import { defaultFeatures } from "../internal/defaultFeatures";
|
|
14
|
+
let { children, ...props } = $props();
|
|
14
15
|
</script>
|
|
15
16
|
|
|
16
17
|
<XRButton
|
|
17
18
|
sessionInit={{
|
|
18
19
|
domOverlay: typeof document !== 'undefined' ? { root: document.body } : undefined,
|
|
19
|
-
|
|
20
|
-
optionalFeatures: ['local-floor', 'bounded-floor', 'hand-tracking', 'layers', 'hit-test']
|
|
20
|
+
...defaultFeatures
|
|
21
21
|
}}
|
|
22
22
|
{...props}
|
|
23
23
|
mode="immersive-ar"
|
|
24
|
-
|
|
24
|
+
>
|
|
25
|
+
{@render children?.()}
|
|
26
|
+
</XRButton>
|
|
@@ -30,7 +30,14 @@ const stores = {
|
|
|
30
30
|
onselectstart,
|
|
31
31
|
onsqueeze,
|
|
32
32
|
onsqueezeend,
|
|
33
|
-
onsqueezestart
|
|
33
|
+
onsqueezestart,
|
|
34
|
+
children,
|
|
35
|
+
grip: gripSnippet,
|
|
36
|
+
targetRay: targetRaySnippet,
|
|
37
|
+
pointerRay: pointerRaySnippet,
|
|
38
|
+
pointerCursor: pointerCursorSnippet,
|
|
39
|
+
teleportRay: teleportRaySnippet,
|
|
40
|
+
teleportCursor: teleportCursorSnippet
|
|
34
41
|
} = $props();
|
|
35
42
|
const handedness = writable(left ? "left" : right ? "right" : hand);
|
|
36
43
|
$effect.pre(() => handedness.set(left ? "left" : right ? "right" : hand));
|
|
@@ -57,26 +64,25 @@ let hasTeleportControls = $derived($teleportState[$handedness].enabled);
|
|
|
57
64
|
{#if !$isHandTracking}
|
|
58
65
|
{#if grip}
|
|
59
66
|
<T is={grip}>
|
|
60
|
-
|
|
67
|
+
{#if children}
|
|
68
|
+
{@render children?.()}
|
|
69
|
+
{:else}
|
|
61
70
|
<T is={model} />
|
|
62
|
-
|
|
71
|
+
{/if}
|
|
63
72
|
|
|
64
|
-
|
|
73
|
+
{@render gripSnippet?.()}
|
|
65
74
|
</T>
|
|
66
75
|
{/if}
|
|
67
76
|
|
|
68
77
|
{#if targetRay}
|
|
69
78
|
<T is={targetRay}>
|
|
70
|
-
|
|
79
|
+
{@render targetRaySnippet?.()}
|
|
71
80
|
|
|
72
81
|
{#if hasPointerControls || hasTeleportControls}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
{:else}
|
|
78
|
-
<ShortRay handedness={$handedness} />
|
|
79
|
-
{/if}
|
|
82
|
+
<ShortRay
|
|
83
|
+
handedness={$handedness}
|
|
84
|
+
children={pointerRaySnippet}
|
|
85
|
+
/>
|
|
80
86
|
{/if}
|
|
81
87
|
</T>
|
|
82
88
|
{/if}
|
|
@@ -84,36 +90,22 @@ let hasTeleportControls = $derived($teleportState[$handedness].enabled);
|
|
|
84
90
|
|
|
85
91
|
<ScenePortal>
|
|
86
92
|
{#if hasPointerControls}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
{:else}
|
|
92
|
-
<PointerCursor handedness={$handedness} />
|
|
93
|
-
{/if}
|
|
93
|
+
<PointerCursor
|
|
94
|
+
handedness={$handedness}
|
|
95
|
+
children={pointerCursorSnippet}
|
|
96
|
+
/>
|
|
94
97
|
{/if}
|
|
95
98
|
|
|
96
99
|
{#if hasTeleportControls && targetRay !== undefined}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
<slot name="teleport-ray" />
|
|
103
|
-
</TeleportRay>
|
|
104
|
-
{:else}
|
|
105
|
-
<TeleportRay
|
|
106
|
-
{targetRay}
|
|
107
|
-
handedness={$handedness}
|
|
108
|
-
/>
|
|
109
|
-
{/if}
|
|
100
|
+
<TeleportRay
|
|
101
|
+
{targetRay}
|
|
102
|
+
handedness={$handedness}
|
|
103
|
+
children={teleportRaySnippet}
|
|
104
|
+
/>
|
|
110
105
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
{:else}
|
|
116
|
-
<TeleportCursor handedness={$handedness} />
|
|
117
|
-
{/if}
|
|
106
|
+
<TeleportCursor
|
|
107
|
+
handedness={$handedness}
|
|
108
|
+
children={teleportCursorSnippet}
|
|
109
|
+
/>
|
|
118
110
|
{/if}
|
|
119
111
|
</ScenePortal>
|
|
@@ -1,7 +1,29 @@
|
|
|
1
1
|
import { SvelteComponent } from "svelte";
|
|
2
2
|
import type { XRControllerEvents } from '../types';
|
|
3
3
|
declare const __propDef: {
|
|
4
|
-
props:
|
|
4
|
+
props: {
|
|
5
|
+
children?: ((this: void) => typeof import("svelte").SnippetReturn & {
|
|
6
|
+
_: "functions passed to {@render ...} tags must use the `Snippet` type imported from \"svelte\"";
|
|
7
|
+
}) | undefined;
|
|
8
|
+
grip?: ((this: void) => typeof import("svelte").SnippetReturn & {
|
|
9
|
+
_: "functions passed to {@render ...} tags must use the `Snippet` type imported from \"svelte\"";
|
|
10
|
+
}) | undefined;
|
|
11
|
+
targetRay?: ((this: void) => typeof import("svelte").SnippetReturn & {
|
|
12
|
+
_: "functions passed to {@render ...} tags must use the `Snippet` type imported from \"svelte\"";
|
|
13
|
+
}) | undefined;
|
|
14
|
+
pointerRay?: ((this: void) => typeof import("svelte").SnippetReturn & {
|
|
15
|
+
_: "functions passed to {@render ...} tags must use the `Snippet` type imported from \"svelte\"";
|
|
16
|
+
}) | undefined;
|
|
17
|
+
pointerCursor?: ((this: void) => typeof import("svelte").SnippetReturn & {
|
|
18
|
+
_: "functions passed to {@render ...} tags must use the `Snippet` type imported from \"svelte\"";
|
|
19
|
+
}) | undefined;
|
|
20
|
+
teleportRay?: ((this: void) => typeof import("svelte").SnippetReturn & {
|
|
21
|
+
_: "functions passed to {@render ...} tags must use the `Snippet` type imported from \"svelte\"";
|
|
22
|
+
}) | undefined;
|
|
23
|
+
teleportCursor?: ((this: void) => typeof import("svelte").SnippetReturn & {
|
|
24
|
+
_: "functions passed to {@render ...} tags must use the `Snippet` type imported from \"svelte\"";
|
|
25
|
+
}) | undefined;
|
|
26
|
+
} & XRControllerEvents & ({
|
|
5
27
|
/** Whether the controller should be matched with the left hand. */
|
|
6
28
|
left: true;
|
|
7
29
|
right?: undefined;
|
|
@@ -16,23 +38,11 @@ declare const __propDef: {
|
|
|
16
38
|
hand: 'left' | 'right';
|
|
17
39
|
left?: undefined;
|
|
18
40
|
right?: undefined;
|
|
19
|
-
})
|
|
20
|
-
children?: ((this: void) => typeof import("svelte").SnippetReturn & {
|
|
21
|
-
_: "functions passed to {@render ...} tags must use the `Snippet` type imported from \"svelte\"";
|
|
22
|
-
}) | undefined;
|
|
23
|
-
};
|
|
41
|
+
});
|
|
24
42
|
events: {
|
|
25
43
|
[evt: string]: CustomEvent<any>;
|
|
26
44
|
};
|
|
27
|
-
slots: {
|
|
28
|
-
default: {};
|
|
29
|
-
grip: {};
|
|
30
|
-
'target-ray': {};
|
|
31
|
-
'pointer-ray': {};
|
|
32
|
-
'pointer-cursor': {};
|
|
33
|
-
'teleport-ray': {};
|
|
34
|
-
'teleport-cursor': {};
|
|
35
|
-
};
|
|
45
|
+
slots: {};
|
|
36
46
|
};
|
|
37
47
|
export type ControllerProps = typeof __propDef.props;
|
|
38
48
|
export type ControllerEvents = typeof __propDef.events;
|
|
@@ -13,8 +13,20 @@ const stores = {
|
|
|
13
13
|
};
|
|
14
14
|
</script>
|
|
15
15
|
|
|
16
|
-
<script lang="ts">let {
|
|
17
|
-
|
|
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;
|
|
18
30
|
const space = xr.getReferenceSpace();
|
|
19
31
|
const handedness = writable(left ? "left" : right ? "right" : hand);
|
|
20
32
|
$effect.pre(() => handedness.set(left ? "left" : right ? "right" : hand));
|
|
@@ -26,24 +38,27 @@ $effect.pre(
|
|
|
26
38
|
onpinchstart
|
|
27
39
|
})
|
|
28
40
|
);
|
|
29
|
-
let
|
|
41
|
+
let group = new Group();
|
|
30
42
|
const { start, stop } = useTask(
|
|
31
43
|
() => {
|
|
32
44
|
const frame = xr.getFrame();
|
|
33
|
-
const joint = inputSource
|
|
45
|
+
const joint = inputSource?.get("wrist");
|
|
34
46
|
if (joint === void 0 || space === null)
|
|
35
47
|
return;
|
|
36
48
|
const pose = frame.getJointPose?.(joint, space);
|
|
37
49
|
if (pose === void 0 || pose === null)
|
|
38
50
|
return;
|
|
39
51
|
const { position, orientation } = pose.transform;
|
|
40
|
-
|
|
41
|
-
|
|
52
|
+
group.position.set(position.x, position.y, position.z);
|
|
53
|
+
group.quaternion.set(orientation.x, orientation.y, orientation.z, orientation.w);
|
|
42
54
|
},
|
|
43
|
-
{
|
|
55
|
+
{
|
|
56
|
+
autoStart: false,
|
|
57
|
+
stage: scheduler.createStage(Symbol("xr-hand-stage"), { before: renderStage })
|
|
58
|
+
}
|
|
44
59
|
);
|
|
45
60
|
$effect.pre(() => {
|
|
46
|
-
if ($isHandTracking && (
|
|
61
|
+
if ($isHandTracking && (wrist !== void 0 || children !== void 0) && inputSource) {
|
|
47
62
|
start();
|
|
48
63
|
} else {
|
|
49
64
|
stop();
|
|
@@ -56,23 +71,23 @@ let model = $derived($store?.model);
|
|
|
56
71
|
|
|
57
72
|
{#if $store?.hand && $isHandTracking}
|
|
58
73
|
<T is={$store.hand}>
|
|
59
|
-
{#if
|
|
74
|
+
{#if children === undefined}
|
|
60
75
|
<T is={model} />
|
|
61
76
|
{/if}
|
|
62
77
|
</T>
|
|
63
78
|
|
|
64
|
-
{#if
|
|
79
|
+
{#if targetRay !== undefined}
|
|
65
80
|
<T is={$store.targetRay}>
|
|
66
|
-
|
|
81
|
+
{@render targetRay()}
|
|
67
82
|
</T>
|
|
68
83
|
{/if}
|
|
69
84
|
{/if}
|
|
70
85
|
|
|
71
86
|
{#if $isHandTracking}
|
|
72
87
|
<ScenePortal>
|
|
73
|
-
<T is={
|
|
74
|
-
|
|
75
|
-
|
|
88
|
+
<T is={group}>
|
|
89
|
+
{@render wrist?.()}
|
|
90
|
+
{@render children?.()}
|
|
76
91
|
</T>
|
|
77
92
|
</ScenePortal>
|
|
78
93
|
{/if}
|
|
@@ -1,7 +1,17 @@
|
|
|
1
1
|
import { SvelteComponent } from "svelte";
|
|
2
2
|
import type { XRHandEvents } from '../types';
|
|
3
3
|
declare const __propDef: {
|
|
4
|
-
props:
|
|
4
|
+
props: {
|
|
5
|
+
children?: ((this: void) => typeof import("svelte").SnippetReturn & {
|
|
6
|
+
_: "functions passed to {@render ...} tags must use the `Snippet` type imported from \"svelte\"";
|
|
7
|
+
}) | undefined;
|
|
8
|
+
targetRay?: ((this: void) => typeof import("svelte").SnippetReturn & {
|
|
9
|
+
_: "functions passed to {@render ...} tags must use the `Snippet` type imported from \"svelte\"";
|
|
10
|
+
}) | undefined;
|
|
11
|
+
wrist?: ((this: void) => typeof import("svelte").SnippetReturn & {
|
|
12
|
+
_: "functions passed to {@render ...} tags must use the `Snippet` type imported from \"svelte\"";
|
|
13
|
+
}) | undefined;
|
|
14
|
+
} & XRHandEvents & ({
|
|
5
15
|
/** Whether the XRHand should be matched with the left hand. */
|
|
6
16
|
left: true;
|
|
7
17
|
right?: undefined;
|
|
@@ -16,19 +26,11 @@ declare const __propDef: {
|
|
|
16
26
|
hand: 'left' | 'right';
|
|
17
27
|
left?: undefined;
|
|
18
28
|
right?: undefined;
|
|
19
|
-
})
|
|
20
|
-
children?: ((this: void) => typeof import("svelte").SnippetReturn & {
|
|
21
|
-
_: "functions passed to {@render ...} tags must use the `Snippet` type imported from \"svelte\"";
|
|
22
|
-
}) | undefined;
|
|
23
|
-
};
|
|
29
|
+
});
|
|
24
30
|
events: {
|
|
25
31
|
[evt: string]: CustomEvent<any>;
|
|
26
32
|
};
|
|
27
|
-
slots: {
|
|
28
|
-
'target-ray': {};
|
|
29
|
-
wrist: {};
|
|
30
|
-
default: {};
|
|
31
|
-
};
|
|
33
|
+
slots: {};
|
|
32
34
|
};
|
|
33
35
|
export type HandProps = typeof __propDef.props;
|
|
34
36
|
export type HandEvents = typeof __propDef.events;
|
|
@@ -10,12 +10,13 @@
|
|
|
10
10
|
```
|
|
11
11
|
-->
|
|
12
12
|
<script lang="ts">import XRButton from "./XRButton.svelte";
|
|
13
|
+
import { defaultFeatures } from "../internal/defaultFeatures";
|
|
13
14
|
let { ...props } = $props();
|
|
14
15
|
</script>
|
|
15
16
|
|
|
16
17
|
<XRButton
|
|
17
18
|
sessionInit={{
|
|
18
|
-
|
|
19
|
+
...defaultFeatures
|
|
19
20
|
}}
|
|
20
21
|
{...props}
|
|
21
22
|
mode="immersive-vr"
|
|
@@ -2,9 +2,9 @@ import { SvelteComponent } from "svelte";
|
|
|
2
2
|
import { type ColorRepresentation } from 'three';
|
|
3
3
|
declare const __propDef: {
|
|
4
4
|
props: {
|
|
5
|
-
color
|
|
6
|
-
size
|
|
7
|
-
thickness
|
|
5
|
+
color?: ColorRepresentation | undefined;
|
|
6
|
+
size?: number | undefined;
|
|
7
|
+
thickness?: number | undefined;
|
|
8
8
|
};
|
|
9
9
|
events: {
|
|
10
10
|
[evt: string]: CustomEvent<any>;
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { T, useTask } from "@threlte/core";
|
|
3
3
|
import { pointerIntersection, pointerState } from "../../internal/stores";
|
|
4
4
|
import Cursor from "./Cursor.svelte";
|
|
5
|
-
let { handedness } = $props();
|
|
5
|
+
let { handedness, children } = $props();
|
|
6
6
|
const ref = new Group();
|
|
7
7
|
const vec3 = new Vector3();
|
|
8
8
|
const normalMatrix = new Matrix3();
|
|
@@ -39,7 +39,9 @@ $effect.pre(() => {
|
|
|
39
39
|
is={ref}
|
|
40
40
|
visible={hovering}
|
|
41
41
|
>
|
|
42
|
-
|
|
42
|
+
{#if children}
|
|
43
|
+
{@render children()}
|
|
44
|
+
{:else}
|
|
43
45
|
<Cursor />
|
|
44
|
-
|
|
46
|
+
{/if}
|
|
45
47
|
</T>
|
|
@@ -2,7 +2,6 @@ import { SvelteComponent } from "svelte";
|
|
|
2
2
|
declare const __propDef: {
|
|
3
3
|
props: {
|
|
4
4
|
handedness: 'left' | 'right';
|
|
5
|
-
} & {
|
|
6
5
|
children?: ((this: void) => typeof import("svelte").SnippetReturn & {
|
|
7
6
|
_: "functions passed to {@render ...} tags must use the `Snippet` type imported from \"svelte\"";
|
|
8
7
|
}) | undefined;
|
|
@@ -10,9 +9,7 @@ declare const __propDef: {
|
|
|
10
9
|
events: {
|
|
11
10
|
[evt: string]: CustomEvent<any>;
|
|
12
11
|
};
|
|
13
|
-
slots: {
|
|
14
|
-
default: {};
|
|
15
|
-
};
|
|
12
|
+
slots: {};
|
|
16
13
|
};
|
|
17
14
|
export type PointerCursorProps = typeof __propDef.props;
|
|
18
15
|
export type PointerCursorEvents = typeof __propDef.events;
|
|
@@ -1,15 +1,33 @@
|
|
|
1
1
|
<script lang="ts">import { T } from "@threlte/core";
|
|
2
2
|
import { pointerState, teleportState, teleportIntersection } from "../../internal/stores";
|
|
3
|
-
let { handedness } = $props();
|
|
3
|
+
let { handedness, children } = $props();
|
|
4
4
|
let hovering = $derived($teleportState[handedness].hovering);
|
|
5
5
|
let intersection = $derived(teleportIntersection[handedness]);
|
|
6
6
|
let visible = $derived(
|
|
7
7
|
$pointerState[handedness].enabled || hovering && $intersection === void 0
|
|
8
8
|
);
|
|
9
|
+
const vertexShader = `
|
|
10
|
+
uniform mat4 modelViewMatrix;
|
|
11
|
+
uniform mat4 projectionMatrix;
|
|
12
|
+
attribute vec2 uv;
|
|
13
|
+
attribute vec3 position;
|
|
14
|
+
varying vec2 vUv;
|
|
15
|
+
void main() {
|
|
16
|
+
vUv = uv;
|
|
17
|
+
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
|
|
18
|
+
}`;
|
|
19
|
+
const fragmentShader = `
|
|
20
|
+
precision mediump float;
|
|
21
|
+
varying vec2 vUv;
|
|
22
|
+
void main() {
|
|
23
|
+
gl_FragColor = vec4(1.0, 1.0, 1.0, pow(vUv.y - 1.0, 2.0));
|
|
24
|
+
}`;
|
|
9
25
|
</script>
|
|
10
26
|
|
|
11
27
|
<T.Group {visible}>
|
|
12
|
-
|
|
28
|
+
{#if children}
|
|
29
|
+
{@render children()}
|
|
30
|
+
{:else}
|
|
13
31
|
<T.Mesh
|
|
14
32
|
rotation.x={-Math.PI / 2}
|
|
15
33
|
position.z={-0.1}
|
|
@@ -17,25 +35,9 @@ let visible = $derived(
|
|
|
17
35
|
<T.CylinderGeometry args={[0.002, 0.002, 0.2, 16, 1, false]} />
|
|
18
36
|
<T.RawShaderMaterial
|
|
19
37
|
transparent
|
|
20
|
-
vertexShader
|
|
21
|
-
|
|
22
|
-
uniform mat4 projectionMatrix;
|
|
23
|
-
attribute vec2 uv;
|
|
24
|
-
attribute vec3 position;
|
|
25
|
-
varying vec2 vUv;
|
|
26
|
-
void main() {
|
|
27
|
-
vUv = uv;
|
|
28
|
-
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
|
|
29
|
-
}
|
|
30
|
-
`}
|
|
31
|
-
fragmentShader={`
|
|
32
|
-
precision mediump float;
|
|
33
|
-
varying vec2 vUv;
|
|
34
|
-
void main() {
|
|
35
|
-
gl_FragColor = vec4(1.0, 1.0, 1.0, pow(vUv.y - 1.0, 2.0));
|
|
36
|
-
}
|
|
37
|
-
`}
|
|
38
|
+
{vertexShader}
|
|
39
|
+
{fragmentShader}
|
|
38
40
|
/>
|
|
39
41
|
</T.Mesh>
|
|
40
|
-
|
|
42
|
+
{/if}
|
|
41
43
|
</T.Group>
|
|
@@ -2,7 +2,6 @@ import { SvelteComponent } from "svelte";
|
|
|
2
2
|
declare const __propDef: {
|
|
3
3
|
props: {
|
|
4
4
|
handedness: 'left' | 'right';
|
|
5
|
-
} & {
|
|
6
5
|
children?: ((this: void) => typeof import("svelte").SnippetReturn & {
|
|
7
6
|
_: "functions passed to {@render ...} tags must use the `Snippet` type imported from \"svelte\"";
|
|
8
7
|
}) | undefined;
|
|
@@ -10,9 +9,7 @@ declare const __propDef: {
|
|
|
10
9
|
events: {
|
|
11
10
|
[evt: string]: CustomEvent<any>;
|
|
12
11
|
};
|
|
13
|
-
slots: {
|
|
14
|
-
default: {};
|
|
15
|
-
};
|
|
12
|
+
slots: {};
|
|
16
13
|
};
|
|
17
14
|
export type ShortRayProps = typeof __propDef.props;
|
|
18
15
|
export type ShortRayEvents = typeof __propDef.events;
|
|
@@ -3,7 +3,7 @@ import { Group, Matrix3, Vector3 } from "three";
|
|
|
3
3
|
import { T, useTask } from "@threlte/core";
|
|
4
4
|
import { teleportIntersection } from "../../internal/stores";
|
|
5
5
|
import Cursor from "./Cursor.svelte";
|
|
6
|
-
let { handedness } = $props();
|
|
6
|
+
let { handedness, children } = $props();
|
|
7
7
|
const ref = new Group();
|
|
8
8
|
const vec3 = new Vector3();
|
|
9
9
|
const normalMatrix = new Matrix3();
|
|
@@ -42,10 +42,12 @@ $effect.pre(() => {
|
|
|
42
42
|
is={ref}
|
|
43
43
|
visible={$intersection !== undefined}
|
|
44
44
|
>
|
|
45
|
-
|
|
45
|
+
{#if children}
|
|
46
|
+
{@render children()}
|
|
47
|
+
{:else}
|
|
46
48
|
<Cursor
|
|
47
49
|
size={$size}
|
|
48
50
|
thickness={0.015}
|
|
49
51
|
/>
|
|
50
|
-
|
|
52
|
+
{/if}
|
|
51
53
|
</T>
|
|
@@ -2,7 +2,6 @@ import { SvelteComponent } from "svelte";
|
|
|
2
2
|
declare const __propDef: {
|
|
3
3
|
props: {
|
|
4
4
|
handedness: 'left' | 'right';
|
|
5
|
-
} & {
|
|
6
5
|
children?: ((this: void) => typeof import("svelte").SnippetReturn & {
|
|
7
6
|
_: "functions passed to {@render ...} tags must use the `Snippet` type imported from \"svelte\"";
|
|
8
7
|
}) | undefined;
|
|
@@ -10,9 +9,7 @@ declare const __propDef: {
|
|
|
10
9
|
events: {
|
|
11
10
|
[evt: string]: CustomEvent<any>;
|
|
12
11
|
};
|
|
13
|
-
slots: {
|
|
14
|
-
default: {};
|
|
15
|
-
};
|
|
12
|
+
slots: {};
|
|
16
13
|
};
|
|
17
14
|
export type TeleportCursorProps = typeof __propDef.props;
|
|
18
15
|
export type TeleportCursorEvents = typeof __propDef.events;
|
|
@@ -4,7 +4,7 @@ import { LineGeometry } from "three/examples/jsm/lines/LineGeometry.js";
|
|
|
4
4
|
import { LineMaterial } from "three/examples/jsm/lines/LineMaterial.js";
|
|
5
5
|
import { T, useTask } from "@threlte/core";
|
|
6
6
|
import { teleportIntersection } from "../../internal/stores";
|
|
7
|
-
let { handedness, targetRay } = $props();
|
|
7
|
+
let { handedness, targetRay, children } = $props();
|
|
8
8
|
let lineGeometry = new LineGeometry();
|
|
9
9
|
const rayStart = new Vector3();
|
|
10
10
|
const rayMidpoint = new Vector3();
|
|
@@ -55,7 +55,9 @@ $effect.pre(() => {
|
|
|
55
55
|
});
|
|
56
56
|
</script>
|
|
57
57
|
|
|
58
|
-
|
|
58
|
+
{#if children}
|
|
59
|
+
{@render children()}
|
|
60
|
+
{:else}
|
|
59
61
|
<T
|
|
60
62
|
is={Line2}
|
|
61
63
|
visible={$intersection !== undefined}
|
|
@@ -67,4 +69,4 @@ $effect.pre(() => {
|
|
|
67
69
|
linewidth={0.004}
|
|
68
70
|
/>
|
|
69
71
|
</T>
|
|
70
|
-
|
|
72
|
+
{/if}
|
|
@@ -4,7 +4,6 @@ declare const __propDef: {
|
|
|
4
4
|
props: {
|
|
5
5
|
handedness: 'left' | 'right';
|
|
6
6
|
targetRay: XRTargetRaySpace;
|
|
7
|
-
} & {
|
|
8
7
|
children?: ((this: void) => typeof import("svelte").SnippetReturn & {
|
|
9
8
|
_: "functions passed to {@render ...} tags must use the `Snippet` type imported from \"svelte\"";
|
|
10
9
|
}) | undefined;
|
|
@@ -12,9 +11,7 @@ declare const __propDef: {
|
|
|
12
11
|
events: {
|
|
13
12
|
[evt: string]: CustomEvent<any>;
|
|
14
13
|
};
|
|
15
|
-
slots: {
|
|
16
|
-
default: {};
|
|
17
|
-
};
|
|
14
|
+
slots: {};
|
|
18
15
|
};
|
|
19
16
|
export type TeleportRayProps = typeof __propDef.props;
|
|
20
17
|
export type TeleportRayEvents = typeof __propDef.events;
|
|
@@ -23,7 +23,7 @@ export const setupControllers = () => {
|
|
|
23
23
|
if (hasHands())
|
|
24
24
|
return;
|
|
25
25
|
const { data } = event;
|
|
26
|
-
controllerEvents[data.handedness]?.[event.type]?.(event);
|
|
26
|
+
controllerEvents[data.handedness]?.current?.[`on${event.type}`]?.(event);
|
|
27
27
|
};
|
|
28
28
|
function handleConnected(event) {
|
|
29
29
|
const { model, targetRay, grip } = indexMap.get(this);
|
|
@@ -24,7 +24,7 @@ export const setupHands = () => {
|
|
|
24
24
|
return;
|
|
25
25
|
const handEvent = event;
|
|
26
26
|
const handedness = 'handedness' in handEvent ? handEvent.handedness : handEvent.data.handedness;
|
|
27
|
-
handEvents[handedness]?.[event.type]?.(event);
|
|
27
|
+
handEvents[handedness]?.current?.[`on${event.type}`]?.(event);
|
|
28
28
|
};
|
|
29
29
|
function handleConnected(event) {
|
|
30
30
|
const hand = this;
|
|
@@ -3,8 +3,9 @@ import { useThrelte, useTask, watch } from '@threlte/core';
|
|
|
3
3
|
import { useXR } from '../hooks/useXR';
|
|
4
4
|
export const headset = new Group();
|
|
5
5
|
export const setupHeadset = () => {
|
|
6
|
-
const { renderer, camera } = useThrelte();
|
|
6
|
+
const { renderer, camera, scheduler, renderStage } = useThrelte();
|
|
7
7
|
const { xr } = renderer;
|
|
8
|
+
const stage = scheduler.createStage(Symbol('xr-headset-stage'), { before: renderStage });
|
|
8
9
|
const immersiveFrame = useTask(() => {
|
|
9
10
|
const space = xr.getReferenceSpace();
|
|
10
11
|
if (space === null)
|
|
@@ -17,13 +18,21 @@ export const setupHeadset = () => {
|
|
|
17
18
|
const { position, orientation } = pose.transform;
|
|
18
19
|
headset.position.set(position.x, position.y, position.z);
|
|
19
20
|
headset.quaternion.set(orientation.x, orientation.y, orientation.z, orientation.w);
|
|
20
|
-
}, {
|
|
21
|
+
}, {
|
|
22
|
+
autoStart: false,
|
|
23
|
+
autoInvalidate: false,
|
|
24
|
+
stage
|
|
25
|
+
});
|
|
21
26
|
const nonImmersiveFrame = useTask(() => {
|
|
22
27
|
headset.position.copy(camera.current.position);
|
|
23
28
|
headset.quaternion.copy(camera.current.quaternion);
|
|
24
|
-
}, {
|
|
25
|
-
|
|
26
|
-
|
|
29
|
+
}, {
|
|
30
|
+
autoStart: false,
|
|
31
|
+
autoInvalidate: false,
|
|
32
|
+
stage
|
|
33
|
+
});
|
|
34
|
+
watch(useXR().isPresenting, ($isPresenting) => {
|
|
35
|
+
if ($isPresenting) {
|
|
27
36
|
immersiveFrame.start();
|
|
28
37
|
nonImmersiveFrame.stop();
|
|
29
38
|
}
|
|
@@ -1,21 +1,17 @@
|
|
|
1
|
-
// @ts-expect-error svelte/internal is untyped.
|
|
2
|
-
// import { set_raf } from 'svelte/internal'
|
|
3
1
|
import { onDestroy } from 'svelte';
|
|
2
|
+
// @ts-expect-error untyped internal import, when have you ever done me wrong?
|
|
3
|
+
import { raf } from 'svelte/internal/client';
|
|
4
4
|
import { watch } from '@threlte/core';
|
|
5
5
|
import { session } from './stores';
|
|
6
6
|
export const setupRaf = () => {
|
|
7
7
|
if (typeof window === 'undefined')
|
|
8
8
|
return;
|
|
9
|
-
const
|
|
10
|
-
const currentRaf = { fn: browserRaf };
|
|
11
|
-
// set_raf((fn: FrameRequestCallback) => currentRaf.fn(fn))
|
|
9
|
+
const originalTick = raf.tick;
|
|
12
10
|
watch(session, (session) => {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
currentRaf.fn = browserRaf;
|
|
18
|
-
}
|
|
11
|
+
raf.tick =
|
|
12
|
+
session === undefined
|
|
13
|
+
? originalTick
|
|
14
|
+
: (fn) => session.requestAnimationFrame(fn);
|
|
19
15
|
});
|
|
20
|
-
onDestroy(() => (
|
|
16
|
+
onDestroy(() => (raf.tick = originalTick));
|
|
21
17
|
};
|
package/dist/types.d.ts
CHANGED
|
@@ -5,25 +5,26 @@ import type { XRHandModel } from 'three/examples/jsm/webxr/XRHandModelFactory.js
|
|
|
5
5
|
export type XRSessionEventType = 'sessionstart' | 'sessionend' | 'visibilitychange' | 'frameratechange';
|
|
6
6
|
export type XRControllerEventType = 'select' | 'selectstart' | 'selectend' | 'squeeze' | 'squeezeend' | 'squeezestart' | 'disconnected' | 'connected';
|
|
7
7
|
export type XRControllerEvents = {
|
|
8
|
-
onconnected?:
|
|
9
|
-
ondisconnected?:
|
|
10
|
-
onselect?:
|
|
11
|
-
onselectstart?:
|
|
12
|
-
onselectend?:
|
|
13
|
-
onsqueeze?:
|
|
14
|
-
onsqueezeend?:
|
|
15
|
-
onsqueezestart?:
|
|
8
|
+
onconnected?: XRControllerEventCallback<'connected'>;
|
|
9
|
+
ondisconnected?: XRControllerEventCallback<'disconnected'>;
|
|
10
|
+
onselect?: XRControllerEventCallback<'select'>;
|
|
11
|
+
onselectstart?: XRControllerEventCallback<'selectstart'>;
|
|
12
|
+
onselectend?: XRControllerEventCallback<'selectend'>;
|
|
13
|
+
onsqueeze?: XRControllerEventCallback<'squeeze'>;
|
|
14
|
+
onsqueezeend?: XRControllerEventCallback<'squeezeend'>;
|
|
15
|
+
onsqueezestart?: XRControllerEventCallback<'squeezestart'>;
|
|
16
16
|
};
|
|
17
17
|
export type XRHandEventType = 'pinchstart' | 'pinchend' | 'connected' | 'disconnected';
|
|
18
18
|
export type XRSessionEvent<Type = XRSessionEventType> = (event: Event & {
|
|
19
19
|
type: Type;
|
|
20
20
|
target: XRSession;
|
|
21
21
|
}) => void;
|
|
22
|
-
export type XRControllerEvent<Type = XRControllerEventType> =
|
|
22
|
+
export type XRControllerEvent<Type = XRControllerEventType> = Event & {
|
|
23
23
|
type: Type;
|
|
24
24
|
target: Group;
|
|
25
25
|
data: XRInputSource;
|
|
26
|
-
}
|
|
26
|
+
};
|
|
27
|
+
export type XRControllerEventCallback<Type = XRControllerEventType> = (event: XRControllerEvent<Type>) => void;
|
|
27
28
|
export type XRController = {
|
|
28
29
|
targetRay: XRTargetRaySpace;
|
|
29
30
|
grip: XRGripSpace;
|
|
@@ -36,18 +37,19 @@ export type XRHand = {
|
|
|
36
37
|
model?: XRHandModel;
|
|
37
38
|
inputSource: globalThis.XRHand;
|
|
38
39
|
};
|
|
39
|
-
export type
|
|
40
|
-
onconnected?: XRHandEvent<'connected'>;
|
|
41
|
-
ondisconnected?: XRHandEvent<'disconnected'>;
|
|
42
|
-
onpinchstart?: XRHandEvent<'pinchstart'>;
|
|
43
|
-
onpinchend?: XRHandEvent<'pinchend'>;
|
|
44
|
-
};
|
|
45
|
-
export type XRHandEvent<Type = XRHandEventType> = Type extends 'connected' | 'disconnected' ? (event: {
|
|
40
|
+
export type XRHandEvent<Type = XRHandEventType> = Type extends 'connected' | 'disconnected' ? {
|
|
46
41
|
type: Type;
|
|
47
42
|
target: XRHandSpace;
|
|
48
43
|
data: XRInputSource;
|
|
49
|
-
}
|
|
44
|
+
} : Type extends 'pinchstart' | 'pinchend' ? {
|
|
50
45
|
type: Type;
|
|
51
46
|
handedness: 'left' | 'right';
|
|
52
47
|
target: null;
|
|
53
|
-
}
|
|
48
|
+
} : never;
|
|
49
|
+
export type XRHandEventCallback<Type> = (event: XRHandEvent<Type>) => void;
|
|
50
|
+
export type XRHandEvents = {
|
|
51
|
+
onconnected?: XRHandEventCallback<'connected'>;
|
|
52
|
+
ondisconnected?: XRHandEventCallback<'disconnected'>;
|
|
53
|
+
onpinchstart?: XRHandEventCallback<'pinchstart'>;
|
|
54
|
+
onpinchend?: XRHandEventCallback<'pinchend'>;
|
|
55
|
+
};
|