@threlte/xr 0.0.11 → 0.0.13
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 +1 -1
- package/dist/components/Controller.svelte +69 -79
- package/dist/components/Controller.svelte.d.ts +4 -0
- package/dist/components/Hand.svelte +25 -58
- package/dist/components/Hand.svelte.d.ts +1 -0
- package/dist/components/Headset.svelte +4 -7
- package/dist/components/XR.svelte +46 -52
- package/dist/components/XRButton.svelte +2 -2
- package/dist/components/internal/Cursor.svelte +51 -0
- package/dist/components/internal/Cursor.svelte.d.ts +19 -0
- package/dist/components/internal/PointerCursor.svelte +46 -0
- package/dist/components/internal/PointerCursor.svelte.d.ts +18 -0
- package/dist/components/internal/ScenePortal.svelte +10 -0
- package/dist/components/internal/ScenePortal.svelte.d.ts +16 -0
- package/dist/components/internal/ShortRay.svelte +45 -0
- package/dist/components/{ShortRay.svelte.d.ts → internal/ShortRay.svelte.d.ts} +4 -2
- package/dist/components/internal/TeleportCursor.svelte +51 -0
- package/dist/components/internal/TeleportCursor.svelte.d.ts +18 -0
- package/dist/components/internal/TeleportRay.svelte +71 -0
- package/dist/components/internal/TeleportRay.svelte.d.ts +20 -0
- package/dist/hooks/useController.d.ts +0 -4
- package/dist/hooks/useController.js +2 -15
- package/dist/hooks/useHand.js +2 -0
- package/dist/hooks/useHandJoint.d.ts +2 -2
- package/dist/hooks/useHeadset.d.ts +2 -1
- package/dist/hooks/useHeadset.js +1 -1
- package/dist/hooks/useHitTest.d.ts +2 -2
- package/dist/hooks/useHitTest.js +16 -6
- package/dist/hooks/useTeleport.d.ts +2 -2
- package/dist/hooks/useTeleport.js +2 -2
- package/dist/index.d.ts +10 -3
- package/dist/index.js +13 -2
- package/dist/internal/setupControllers.d.ts +1 -0
- package/dist/internal/setupControllers.js +69 -0
- package/dist/internal/setupHands.d.ts +1 -0
- package/dist/internal/setupHands.js +63 -0
- package/dist/internal/setupHeadset.d.ts +3 -0
- package/dist/internal/{headset.js → setupHeadset.js} +3 -4
- package/dist/internal/setupRaf.d.ts +1 -0
- package/dist/internal/{updateRaf.js → setupRaf.js} +2 -2
- package/dist/internal/stores.d.ts +46 -5
- package/dist/internal/stores.js +36 -4
- package/dist/internal/useFixed.d.ts +11 -0
- package/dist/internal/useFixed.js +17 -0
- package/dist/internal/useHandTrackingState.js +1 -1
- package/dist/lib/toggleXRSession.js +3 -3
- package/dist/plugins/pointerControls/compute.d.ts +3 -0
- package/dist/plugins/pointerControls/compute.js +14 -0
- package/dist/plugins/pointerControls/context.d.ts +12 -0
- package/dist/plugins/pointerControls/context.js +27 -0
- package/dist/plugins/pointerControls/hook.d.ts +5 -0
- package/dist/plugins/pointerControls/hook.js +24 -0
- package/dist/plugins/pointerControls/index.d.ts +27 -0
- package/dist/plugins/pointerControls/index.js +54 -0
- package/dist/plugins/pointerControls/plugin.d.ts +1 -0
- package/dist/plugins/pointerControls/plugin.js +28 -0
- package/dist/plugins/pointerControls/setup.d.ts +2 -0
- package/dist/plugins/pointerControls/setup.js +203 -0
- package/dist/plugins/pointerControls/types.d.ts +62 -0
- package/dist/plugins/pointerControls/types.js +11 -0
- package/dist/plugins/pointerControls/useComponentEventHandlers.d.ts +4 -0
- package/dist/plugins/pointerControls/useComponentEventHandlers.js +15 -0
- package/dist/plugins/teleportControls/compute.d.ts +3 -0
- package/dist/plugins/teleportControls/compute.js +14 -0
- package/dist/plugins/teleportControls/context.d.ts +21 -0
- package/dist/plugins/teleportControls/context.js +18 -0
- package/dist/plugins/teleportControls/hook.d.ts +7 -0
- package/dist/plugins/teleportControls/hook.js +40 -0
- package/dist/plugins/teleportControls/index.d.ts +19 -0
- package/dist/plugins/teleportControls/index.js +54 -0
- package/dist/plugins/teleportControls/plugin.d.ts +4 -0
- package/dist/plugins/teleportControls/plugin.js +54 -0
- package/dist/plugins/teleportControls/setup.d.ts +2 -0
- package/dist/plugins/teleportControls/setup.js +62 -0
- package/dist/types.d.ts +10 -8
- package/package.json +4 -4
- package/dist/components/Ray.svelte +0 -23
- package/dist/components/Ray.svelte.d.ts +0 -18
- package/dist/components/ShortRay.svelte +0 -32
- package/dist/components/TeleportControls.svelte +0 -136
- package/dist/components/TeleportControls.svelte.d.ts +0 -54
- package/dist/hooks/index.d.ts +0 -7
- package/dist/hooks/index.js +0 -7
- package/dist/internal/headset.d.ts +0 -3
- package/dist/internal/updateRaf.d.ts +0 -1
- package/dist/plugins/teleportPlugin.d.ts +0 -1
- package/dist/plugins/teleportPlugin.js +0 -41
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
sessionInit={{
|
|
18
18
|
domOverlay: typeof document !== 'undefined' ? { root: document.body } : undefined,
|
|
19
19
|
requiredFeatures: ['plane-detection'],
|
|
20
|
-
optionalFeatures: ['
|
|
20
|
+
optionalFeatures: ['local-floor', 'bounded-floor', 'hand-tracking', 'layers', 'hit-test']
|
|
21
21
|
}}
|
|
22
22
|
{...$$restProps}
|
|
23
23
|
mode='immersive-ar'
|
|
@@ -4,96 +4,48 @@
|
|
|
4
4
|
<script
|
|
5
5
|
|
|
6
6
|
context="module"
|
|
7
|
-
>import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import
|
|
11
|
-
import
|
|
12
|
-
import
|
|
13
|
-
import
|
|
14
|
-
|
|
7
|
+
>import { writable } from "svelte/store";
|
|
8
|
+
import { T, createRawEventDispatcher } from "@threlte/core";
|
|
9
|
+
import { left as leftStore, right as rightStore } from "../hooks/useController";
|
|
10
|
+
import { isHandTracking, pointerState, teleportState, controllerDispatchers } 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";
|
|
15
16
|
const stores = {
|
|
16
17
|
left: leftStore,
|
|
17
|
-
right: rightStore
|
|
18
|
-
none: gaze
|
|
18
|
+
right: rightStore
|
|
19
19
|
};
|
|
20
|
-
const events = [
|
|
21
|
-
"select",
|
|
22
|
-
"selectstart",
|
|
23
|
-
"selectend",
|
|
24
|
-
"squeeze",
|
|
25
|
-
"squeezeend",
|
|
26
|
-
"squeezestart"
|
|
27
|
-
];
|
|
28
|
-
const eventMap = /* @__PURE__ */ new WeakMap();
|
|
29
20
|
</script>
|
|
30
21
|
|
|
31
22
|
<script>export let left = void 0;
|
|
32
23
|
export let right = void 0;
|
|
33
24
|
export let hand = void 0;
|
|
34
|
-
$:
|
|
35
|
-
handedness = left ? "left" : right ? "right" : hand;
|
|
36
25
|
const dispatch = createRawEventDispatcher();
|
|
37
|
-
const
|
|
38
|
-
const handTrackingNow = useHandTrackingState();
|
|
39
|
-
const handleEvent = (event) => {
|
|
40
|
-
if (!handTrackingNow()) {
|
|
41
|
-
dispatch(event.type, event);
|
|
42
|
-
}
|
|
43
|
-
};
|
|
44
|
-
const handleConnected = (event) => {
|
|
45
|
-
const targetData = eventMap.get(event.target);
|
|
46
|
-
if (event.data.handedness !== handedness || !targetData)
|
|
47
|
-
return;
|
|
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));
|
|
53
|
-
};
|
|
54
|
-
const handleDisconnected = (event) => {
|
|
55
|
-
if (event.data.handedness !== handedness)
|
|
56
|
-
return;
|
|
57
|
-
stores[handedness].set(void 0);
|
|
58
|
-
if (!$isHandTracking) {
|
|
59
|
-
dispatch("disconnected", event);
|
|
60
|
-
}
|
|
61
|
-
events.forEach((name) => event.target.removeEventListener(name, handleEvent));
|
|
62
|
-
};
|
|
63
|
-
for (const index of [0, 1]) {
|
|
64
|
-
const controller = xr.getController(index);
|
|
65
|
-
const grip2 = xr.getControllerGrip(index);
|
|
66
|
-
const model2 = factory.createControllerModel(grip2);
|
|
67
|
-
eventMap.set(controller, { targetRay: controller, model: model2, grip: grip2 });
|
|
68
|
-
controller.addEventListener("connected", handleConnected);
|
|
69
|
-
controller.addEventListener("disconnected", handleDisconnected);
|
|
70
|
-
}
|
|
26
|
+
const handedness = writable(left ? "left" : right ? "right" : hand);
|
|
71
27
|
$:
|
|
72
|
-
|
|
28
|
+
handedness.set(left ? "left" : right ? "right" : hand);
|
|
29
|
+
controllerDispatchers[$handedness].set(dispatch);
|
|
30
|
+
$:
|
|
31
|
+
controllerDispatchers[$handedness].set(dispatch);
|
|
32
|
+
$:
|
|
33
|
+
store = stores[$handedness];
|
|
73
34
|
$:
|
|
74
35
|
grip = $store?.grip;
|
|
75
36
|
$:
|
|
76
37
|
targetRay = $store?.targetRay;
|
|
77
38
|
$:
|
|
78
39
|
model = $store?.model;
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
controller2.removeEventListener("disconnected", handleDisconnected);
|
|
84
|
-
}
|
|
85
|
-
const controller = $store?.targetRay;
|
|
86
|
-
events.forEach((name) => controller?.removeEventListener(name, handleEvent));
|
|
87
|
-
store.set(void 0);
|
|
88
|
-
});
|
|
40
|
+
$:
|
|
41
|
+
hasPointerControls = $pointerState[$handedness].enabled;
|
|
42
|
+
$:
|
|
43
|
+
hasTeleportControls = $teleportState[$handedness].enabled;
|
|
89
44
|
</script>
|
|
90
45
|
|
|
91
46
|
{#if !$isHandTracking}
|
|
92
47
|
{#if grip}
|
|
93
|
-
<T
|
|
94
|
-
is={grip}
|
|
95
|
-
name="XR controller grip {handedness}"
|
|
96
|
-
>
|
|
48
|
+
<T is={grip}>
|
|
97
49
|
<slot>
|
|
98
50
|
<T is={model} />
|
|
99
51
|
</slot>
|
|
@@ -103,16 +55,54 @@ onDestroy(() => {
|
|
|
103
55
|
{/if}
|
|
104
56
|
|
|
105
57
|
{#if targetRay}
|
|
106
|
-
<T
|
|
107
|
-
is={targetRay}
|
|
108
|
-
name="XR controller {handedness}"
|
|
109
|
-
visible={!$isHandTracking}
|
|
110
|
-
>
|
|
58
|
+
<T is={targetRay}>
|
|
111
59
|
<slot name="target-ray" />
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
60
|
+
|
|
61
|
+
{#if hasPointerControls || hasTeleportControls}
|
|
62
|
+
{#if $$slots['pointer-ray']}
|
|
63
|
+
<ShortRay handedness={$handedness}>
|
|
64
|
+
<slot name="pointer-ray" />
|
|
65
|
+
</ShortRay>
|
|
66
|
+
{:else}
|
|
67
|
+
<ShortRay handedness={$handedness} />
|
|
68
|
+
{/if}
|
|
69
|
+
{/if}
|
|
116
70
|
</T>
|
|
117
71
|
{/if}
|
|
118
72
|
{/if}
|
|
73
|
+
|
|
74
|
+
<ScenePortal>
|
|
75
|
+
{#if hasPointerControls}
|
|
76
|
+
{#if $$slots['pointer-cursor']}
|
|
77
|
+
<PointerCursor handedness={$handedness}>
|
|
78
|
+
<slot name="pointer-cursor" />
|
|
79
|
+
</PointerCursor>
|
|
80
|
+
{:else}
|
|
81
|
+
<PointerCursor handedness={$handedness} />
|
|
82
|
+
{/if}
|
|
83
|
+
{/if}
|
|
84
|
+
|
|
85
|
+
{#if hasTeleportControls && targetRay !== undefined}
|
|
86
|
+
{#if $$slots['teleport-ray']}
|
|
87
|
+
<TeleportRay
|
|
88
|
+
{targetRay}
|
|
89
|
+
handedness={$handedness}
|
|
90
|
+
>
|
|
91
|
+
<slot name="teleport-ray" />
|
|
92
|
+
</TeleportRay>
|
|
93
|
+
{:else}
|
|
94
|
+
<TeleportRay
|
|
95
|
+
{targetRay}
|
|
96
|
+
handedness={$handedness}
|
|
97
|
+
/>
|
|
98
|
+
{/if}
|
|
99
|
+
|
|
100
|
+
{#if $$slots['teleport-ray']}
|
|
101
|
+
<TeleportCursor handedness={$handedness}>
|
|
102
|
+
<slot name="teleport-cursor" />
|
|
103
|
+
</TeleportCursor>
|
|
104
|
+
{:else}
|
|
105
|
+
<TeleportCursor handedness={$handedness} />
|
|
106
|
+
{/if}
|
|
107
|
+
{/if}
|
|
108
|
+
</ScenePortal>
|
|
@@ -1,49 +1,26 @@
|
|
|
1
|
-
<script context='module'>import {
|
|
2
|
-
import {
|
|
3
|
-
import { isHandTracking } from "../internal/stores";
|
|
4
|
-
import { useHandTrackingState } from "../internal/useHandTrackingState";
|
|
1
|
+
<script context='module'>import { Group } from "three";
|
|
2
|
+
import { T, useThrelte, createRawEventDispatcher, useFrame } from "@threlte/core";
|
|
3
|
+
import { isHandTracking, handDispatchers } from "../internal/stores";
|
|
5
4
|
import { left as leftStore, right as rightStore } from "../hooks/useHand";
|
|
6
|
-
import
|
|
7
|
-
|
|
5
|
+
import ScenePortal from "./internal/ScenePortal.svelte";
|
|
6
|
+
import { writable } from "svelte/store";
|
|
8
7
|
const stores = {
|
|
9
8
|
left: leftStore,
|
|
10
9
|
right: rightStore
|
|
11
10
|
};
|
|
12
|
-
const eventMap = /* @__PURE__ */ new WeakMap();
|
|
13
11
|
</script>
|
|
14
12
|
|
|
15
13
|
<script>export let left = void 0;
|
|
16
14
|
export let right = void 0;
|
|
17
15
|
export let hand = void 0;
|
|
18
|
-
const handTrackingNow = useHandTrackingState();
|
|
19
16
|
const dispatch = createRawEventDispatcher();
|
|
20
17
|
const { xr } = useThrelte().renderer;
|
|
21
18
|
const space = xr.getReferenceSpace();
|
|
19
|
+
const handedness = writable(left ? "left" : right ? "right" : hand);
|
|
22
20
|
$:
|
|
23
|
-
handedness
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
return;
|
|
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);
|
|
33
|
-
};
|
|
34
|
-
const handleDisconnected = (event) => {
|
|
35
|
-
if (event.data.handedness !== handedness)
|
|
36
|
-
return;
|
|
37
|
-
stores[handedness].set(void 0);
|
|
38
|
-
if ($isHandTracking) {
|
|
39
|
-
dispatch("disconnected", event);
|
|
40
|
-
}
|
|
41
|
-
event.target.removeEventListener("pinchstart", handlePinchEvent);
|
|
42
|
-
event.target.removeEventListener("pinchend", handlePinchEvent);
|
|
43
|
-
};
|
|
44
|
-
const handlePinchEvent = (event) => {
|
|
45
|
-
dispatch(event.type, event);
|
|
46
|
-
};
|
|
21
|
+
handedness.set(left ? "left" : right ? "right" : hand);
|
|
22
|
+
$:
|
|
23
|
+
handDispatchers[$handedness].set(dispatch);
|
|
47
24
|
let children;
|
|
48
25
|
const { start, stop } = useFrame(() => {
|
|
49
26
|
const frame = xr.getFrame();
|
|
@@ -58,48 +35,38 @@ const { start, stop } = useFrame(() => {
|
|
|
58
35
|
children.quaternion.set(orientation.x, orientation.y, orientation.z, orientation.w);
|
|
59
36
|
}, { autostart: false });
|
|
60
37
|
$:
|
|
61
|
-
if (($$slots.wrist || $$slots.default) && inputSource) {
|
|
38
|
+
if ($isHandTracking && ($$slots.wrist || $$slots.default) && inputSource) {
|
|
62
39
|
start();
|
|
63
40
|
} else {
|
|
64
41
|
stop();
|
|
65
42
|
}
|
|
66
43
|
$:
|
|
67
|
-
store = stores[handedness];
|
|
44
|
+
store = stores[$handedness];
|
|
68
45
|
$:
|
|
69
46
|
inputSource = $store?.inputSource;
|
|
70
47
|
$:
|
|
71
48
|
model = $store?.model;
|
|
72
|
-
for (const index of [0, 1]) {
|
|
73
|
-
const hand2 = xr.getHand(index);
|
|
74
|
-
const model2 = factory.createHandModel(hand2, "mesh");
|
|
75
|
-
eventMap.set(hand2, { hand: hand2, model: model2 });
|
|
76
|
-
hand2.addEventListener("connected", handleConnected);
|
|
77
|
-
hand2.addEventListener("disconnected", handleDisconnected);
|
|
78
|
-
}
|
|
79
|
-
onDestroy(() => {
|
|
80
|
-
for (const index of [0, 1]) {
|
|
81
|
-
const hand3 = xr.getHand(index);
|
|
82
|
-
hand3.removeEventListener("connected", handleConnected);
|
|
83
|
-
hand3.removeEventListener("disconnected", handleDisconnected);
|
|
84
|
-
}
|
|
85
|
-
const hand2 = stores[handedness].current?.hand;
|
|
86
|
-
hand2?.removeEventListener("pinchstart", handlePinchEvent);
|
|
87
|
-
hand2?.removeEventListener("pinchend", handlePinchEvent);
|
|
88
|
-
stores[handedness].set(void 0);
|
|
89
|
-
});
|
|
90
49
|
</script>
|
|
91
50
|
|
|
92
|
-
{#if $store?.hand}
|
|
93
|
-
<T
|
|
94
|
-
is={$store.hand}
|
|
95
|
-
name='XR hand {handedness}'
|
|
96
|
-
>
|
|
51
|
+
{#if $store?.hand && $isHandTracking}
|
|
52
|
+
<T is={$store.hand}>
|
|
97
53
|
{#if $$slots.default === undefined}
|
|
98
54
|
<T is={model} />
|
|
99
55
|
{/if}
|
|
56
|
+
</T>
|
|
57
|
+
|
|
58
|
+
{#if $$slots['target-ray'] !== undefined}
|
|
59
|
+
<T is={$store.targetRay}>
|
|
60
|
+
<slot name='target-ray' />
|
|
61
|
+
</T>
|
|
62
|
+
{/if}
|
|
63
|
+
{/if}
|
|
64
|
+
|
|
65
|
+
{#if $isHandTracking}
|
|
66
|
+
<ScenePortal>
|
|
100
67
|
<T.Group bind:ref={children}>
|
|
101
68
|
<slot name='wrist' />
|
|
102
69
|
<slot />
|
|
103
70
|
</T.Group>
|
|
104
|
-
</
|
|
71
|
+
</ScenePortal>
|
|
105
72
|
{/if}
|
|
@@ -1,15 +1,12 @@
|
|
|
1
1
|
|
|
2
|
-
<script>import { T
|
|
2
|
+
<script>import { T } from "@threlte/core";
|
|
3
3
|
import { useHeadset } from "../hooks/useHeadset";
|
|
4
|
-
|
|
4
|
+
import ScenePortal from "./internal/ScenePortal.svelte";
|
|
5
5
|
const headset = useHeadset();
|
|
6
6
|
</script>
|
|
7
7
|
|
|
8
|
-
<
|
|
9
|
-
onChildMount={(child) => { scene.add(child) }}
|
|
10
|
-
onChildDestroy={(child) => { scene.remove(child) }}
|
|
11
|
-
>
|
|
8
|
+
<ScenePortal>
|
|
12
9
|
<T is={headset}>
|
|
13
10
|
<slot />
|
|
14
11
|
</T>
|
|
15
|
-
</
|
|
12
|
+
</ScenePortal>
|
|
@@ -17,33 +17,38 @@ This should be placed within a Threlte `<Canvas />`.
|
|
|
17
17
|
```
|
|
18
18
|
|
|
19
19
|
-->
|
|
20
|
-
<script>import {
|
|
21
|
-
import { createRawEventDispatcher, useThrelte } from "@threlte/core";
|
|
20
|
+
<script>import { onMount } from "svelte";
|
|
21
|
+
import { createRawEventDispatcher, useThrelte, watch } from "@threlte/core";
|
|
22
22
|
import {
|
|
23
|
-
initialized,
|
|
24
23
|
isHandTracking,
|
|
25
24
|
isPresenting,
|
|
26
25
|
referenceSpaceType,
|
|
27
26
|
session,
|
|
28
27
|
xr as xrStore
|
|
29
28
|
} from "../internal/stores";
|
|
30
|
-
import {
|
|
31
|
-
import {
|
|
29
|
+
import { setupRaf } from "../internal/setupRaf";
|
|
30
|
+
import { setupHeadset } from "../internal/setupHeadset";
|
|
31
|
+
import { setupControllers } from "../internal/setupControllers";
|
|
32
|
+
import { setupHands } from "../internal/setupHands";
|
|
32
33
|
export let foveation = 1;
|
|
33
34
|
export let frameRate = void 0;
|
|
34
35
|
export let referenceSpace = "local-floor";
|
|
35
36
|
const dispatch = createRawEventDispatcher();
|
|
36
|
-
updateRaf();
|
|
37
37
|
const { renderer, frameloop } = useThrelte();
|
|
38
38
|
const { xr } = renderer;
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
39
|
+
let originalFrameloop = $frameloop;
|
|
40
|
+
setupRaf();
|
|
41
|
+
setupHeadset();
|
|
42
|
+
setupControllers();
|
|
43
|
+
setupHands();
|
|
44
|
+
const handleSessionStart = () => {
|
|
45
|
+
isPresenting.set(true);
|
|
46
|
+
dispatch("sessionstart", { type: "sessionstart", target: $session });
|
|
42
47
|
};
|
|
43
|
-
const handleSessionEnd = (
|
|
44
|
-
dispatch("sessionend", {
|
|
45
|
-
|
|
46
|
-
|
|
48
|
+
const handleSessionEnd = () => {
|
|
49
|
+
dispatch("sessionend", { type: "sessionend", target: $session });
|
|
50
|
+
isPresenting.set(false);
|
|
51
|
+
session.set(void 0);
|
|
47
52
|
};
|
|
48
53
|
const handleVisibilityChange = (event) => {
|
|
49
54
|
dispatch("visibilitychange", { ...event, target: $session });
|
|
@@ -63,14 +68,7 @@ const updateTargetFrameRate = (frameRate2) => {
|
|
|
63
68
|
} catch {
|
|
64
69
|
}
|
|
65
70
|
};
|
|
66
|
-
|
|
67
|
-
if (currentSession === void 0)
|
|
68
|
-
return;
|
|
69
|
-
currentSession.removeEventListener("visibilitychange", handleVisibilityChange);
|
|
70
|
-
currentSession.removeEventListener("inputsourceschange", handleInputSourcesChange);
|
|
71
|
-
currentSession.removeEventListener("frameratechange", handleFramerateChange);
|
|
72
|
-
};
|
|
73
|
-
const updateSession = async (currentSession) => {
|
|
71
|
+
watch(session, (currentSession) => {
|
|
74
72
|
if (currentSession === void 0)
|
|
75
73
|
return;
|
|
76
74
|
currentSession.addEventListener("visibilitychange", handleVisibilityChange);
|
|
@@ -78,44 +76,40 @@ const updateSession = async (currentSession) => {
|
|
|
78
76
|
currentSession.addEventListener("frameratechange", handleFramerateChange);
|
|
79
77
|
xr.setFoveation(foveation);
|
|
80
78
|
updateTargetFrameRate(frameRate);
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
xr.addEventListener("sessionstart", handleSessionStart);
|
|
87
|
-
xr.addEventListener("sessionend", handleSessionEnd);
|
|
88
|
-
useUpdateHeadset();
|
|
89
|
-
onDestroy(() => {
|
|
90
|
-
$initialized = false;
|
|
91
|
-
$xrStore = void 0;
|
|
92
|
-
xr.enabled = false;
|
|
93
|
-
xr.removeEventListener("sessionstart", handleSessionStart);
|
|
94
|
-
xr.removeEventListener("sessionend", handleSessionEnd);
|
|
79
|
+
return () => {
|
|
80
|
+
currentSession.removeEventListener("visibilitychange", handleVisibilityChange);
|
|
81
|
+
currentSession.removeEventListener("inputsourceschange", handleInputSourcesChange);
|
|
82
|
+
currentSession.removeEventListener("frameratechange", handleFramerateChange);
|
|
83
|
+
};
|
|
95
84
|
});
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
$:
|
|
101
|
-
if (lastSession !== $session) {
|
|
102
|
-
cleanupSession(lastSession);
|
|
103
|
-
updateSession($session);
|
|
104
|
-
lastSession = $session;
|
|
105
|
-
}
|
|
106
|
-
let originalFrameloop = $frameloop;
|
|
107
|
-
$frameloop = "always";
|
|
108
|
-
$:
|
|
109
|
-
if ($isPresenting) {
|
|
110
|
-
originalFrameloop = $frameloop;
|
|
111
|
-
$frameloop = "always";
|
|
85
|
+
watch(isPresenting, (presenting) => {
|
|
86
|
+
if (presenting) {
|
|
87
|
+
originalFrameloop = frameloop.current;
|
|
88
|
+
frameloop.set("always");
|
|
112
89
|
} else {
|
|
113
|
-
|
|
90
|
+
frameloop.set(originalFrameloop);
|
|
114
91
|
}
|
|
92
|
+
});
|
|
93
|
+
onMount(() => {
|
|
94
|
+
$xrStore = xr;
|
|
95
|
+
xr.enabled = true;
|
|
96
|
+
xr.addEventListener("sessionstart", handleSessionStart);
|
|
97
|
+
xr.addEventListener("sessionend", handleSessionEnd);
|
|
98
|
+
return () => {
|
|
99
|
+
$xrStore = void 0;
|
|
100
|
+
xr.enabled = false;
|
|
101
|
+
xr.removeEventListener("sessionstart", handleSessionStart);
|
|
102
|
+
xr.removeEventListener("sessionend", handleSessionEnd);
|
|
103
|
+
};
|
|
104
|
+
});
|
|
115
105
|
$:
|
|
116
106
|
updateTargetFrameRate(frameRate);
|
|
117
107
|
$:
|
|
118
108
|
xr.setFoveation(foveation);
|
|
109
|
+
$: {
|
|
110
|
+
xr.setReferenceSpaceType(referenceSpace);
|
|
111
|
+
$referenceSpaceType = referenceSpace;
|
|
112
|
+
}
|
|
119
113
|
</script>
|
|
120
114
|
|
|
121
115
|
{#if $isPresenting}
|
|
@@ -21,14 +21,14 @@ display info about your WebXR session. This is aliased by `ARButton` and
|
|
|
21
21
|
<script>import { createEventDispatcher } from "svelte";
|
|
22
22
|
import { getXRSupportState } from "../lib/getXRSupportState";
|
|
23
23
|
import { toggleXRSession } from "../lib/toggleXRSession";
|
|
24
|
-
import { session,
|
|
24
|
+
import { session, xr } from "../internal/stores";
|
|
25
25
|
export let mode;
|
|
26
26
|
export let sessionInit = void 0;
|
|
27
27
|
export let force = void 0;
|
|
28
28
|
export let styled = true;
|
|
29
29
|
const dispatch = createEventDispatcher();
|
|
30
30
|
const handleButtonClick = async (nativeEvent, state) => {
|
|
31
|
-
if (!$
|
|
31
|
+
if (!$xr) {
|
|
32
32
|
throw new Error("The <XR> component was not created. This is required to start an XR session.");
|
|
33
33
|
}
|
|
34
34
|
dispatch("click", { state, nativeEvent });
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
<script>import { Color, DoubleSide, RawShaderMaterial } from "three";
|
|
2
|
+
import { T } from "@threlte/core";
|
|
3
|
+
export let color = new Color("white");
|
|
4
|
+
export let size = 0.03;
|
|
5
|
+
export let thickness = 0.035;
|
|
6
|
+
const vertexShader = `
|
|
7
|
+
uniform mat4 projectionMatrix;
|
|
8
|
+
uniform mat4 modelViewMatrix;
|
|
9
|
+
attribute vec2 uv;
|
|
10
|
+
attribute vec3 position;
|
|
11
|
+
varying vec2 vUv;
|
|
12
|
+
void main() {
|
|
13
|
+
vUv = uv;
|
|
14
|
+
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
|
|
15
|
+
}
|
|
16
|
+
`;
|
|
17
|
+
const fragmentShader = `
|
|
18
|
+
precision mediump float;
|
|
19
|
+
uniform float thickness;
|
|
20
|
+
uniform vec3 color;
|
|
21
|
+
varying vec2 vUv;
|
|
22
|
+
void main() {
|
|
23
|
+
float radius = 0.1;
|
|
24
|
+
float dist = length(vUv - vec2(0.5));
|
|
25
|
+
float alpha = 1.0 - step(thickness, abs(distance(vUv, vec2(0.5)) - 0.25));
|
|
26
|
+
gl_FragColor = vec4(color, alpha);
|
|
27
|
+
}
|
|
28
|
+
`;
|
|
29
|
+
const shaderMaterial = new RawShaderMaterial({
|
|
30
|
+
vertexShader,
|
|
31
|
+
fragmentShader,
|
|
32
|
+
uniforms: {
|
|
33
|
+
thickness: { value: thickness },
|
|
34
|
+
color: { value: color }
|
|
35
|
+
},
|
|
36
|
+
side: DoubleSide,
|
|
37
|
+
transparent: true,
|
|
38
|
+
depthTest: false
|
|
39
|
+
});
|
|
40
|
+
$:
|
|
41
|
+
shaderMaterial.uniforms.thickness.value = thickness;
|
|
42
|
+
$:
|
|
43
|
+
shaderMaterial.uniforms.color.value = color;
|
|
44
|
+
</script>
|
|
45
|
+
|
|
46
|
+
<T.Mesh
|
|
47
|
+
scale={size}
|
|
48
|
+
>
|
|
49
|
+
<T.PlaneGeometry />
|
|
50
|
+
<T is={shaderMaterial} />
|
|
51
|
+
</T.Mesh>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { SvelteComponent } from "svelte";
|
|
2
|
+
import { type ColorRepresentation } from 'three';
|
|
3
|
+
declare const __propDef: {
|
|
4
|
+
props: {
|
|
5
|
+
color?: ColorRepresentation;
|
|
6
|
+
size?: number;
|
|
7
|
+
thickness?: number;
|
|
8
|
+
};
|
|
9
|
+
events: {
|
|
10
|
+
[evt: string]: CustomEvent<any>;
|
|
11
|
+
};
|
|
12
|
+
slots: {};
|
|
13
|
+
};
|
|
14
|
+
export type CursorProps = typeof __propDef.props;
|
|
15
|
+
export type CursorEvents = typeof __propDef.events;
|
|
16
|
+
export type CursorSlots = typeof __propDef.slots;
|
|
17
|
+
export default class Cursor extends SvelteComponent<CursorProps, CursorEvents, CursorSlots> {
|
|
18
|
+
}
|
|
19
|
+
export {};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
<script>import { Group, Vector3, Matrix3 } from "three";
|
|
2
|
+
import { T, useFrame } from "@threlte/core";
|
|
3
|
+
import { pointerIntersection, pointerState } from "../../internal/stores";
|
|
4
|
+
import Cursor from "./Cursor.svelte";
|
|
5
|
+
export let handedness;
|
|
6
|
+
const ref = new Group();
|
|
7
|
+
const vec3 = new Vector3();
|
|
8
|
+
const normalMatrix = new Matrix3();
|
|
9
|
+
const worldNormal = new Vector3();
|
|
10
|
+
$:
|
|
11
|
+
hovering = $pointerState[handedness].hovering;
|
|
12
|
+
$:
|
|
13
|
+
intersection = pointerIntersection[handedness];
|
|
14
|
+
const { start, stop } = useFrame(
|
|
15
|
+
() => {
|
|
16
|
+
if (intersection.current === void 0)
|
|
17
|
+
return;
|
|
18
|
+
const { point, face, object } = intersection.current;
|
|
19
|
+
ref.position.lerp(point, 0.4);
|
|
20
|
+
if (face) {
|
|
21
|
+
normalMatrix.getNormalMatrix(object.matrixWorld);
|
|
22
|
+
worldNormal.copy(face.normal).applyMatrix3(normalMatrix).normalize();
|
|
23
|
+
ref.lookAt(vec3.addVectors(point, worldNormal));
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
autostart: false
|
|
28
|
+
}
|
|
29
|
+
);
|
|
30
|
+
$:
|
|
31
|
+
if (hovering) {
|
|
32
|
+
ref.position.copy(intersection.current.point);
|
|
33
|
+
start();
|
|
34
|
+
} else {
|
|
35
|
+
stop();
|
|
36
|
+
}
|
|
37
|
+
</script>
|
|
38
|
+
|
|
39
|
+
<T
|
|
40
|
+
is={ref}
|
|
41
|
+
visible={hovering}
|
|
42
|
+
>
|
|
43
|
+
<slot>
|
|
44
|
+
<Cursor />
|
|
45
|
+
</slot>
|
|
46
|
+
</T>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { SvelteComponent } from "svelte";
|
|
2
|
+
declare const __propDef: {
|
|
3
|
+
props: {
|
|
4
|
+
handedness: 'left' | 'right';
|
|
5
|
+
};
|
|
6
|
+
events: {
|
|
7
|
+
[evt: string]: CustomEvent<any>;
|
|
8
|
+
};
|
|
9
|
+
slots: {
|
|
10
|
+
default: {};
|
|
11
|
+
};
|
|
12
|
+
};
|
|
13
|
+
export type PointerCursorProps = typeof __propDef.props;
|
|
14
|
+
export type PointerCursorEvents = typeof __propDef.events;
|
|
15
|
+
export type PointerCursorSlots = typeof __propDef.slots;
|
|
16
|
+
export default class PointerCursor extends SvelteComponent<PointerCursorProps, PointerCursorEvents, PointerCursorSlots> {
|
|
17
|
+
}
|
|
18
|
+
export {};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
<script>import { useThrelte, HierarchicalObject } from "@threlte/core";
|
|
2
|
+
const { scene } = useThrelte();
|
|
3
|
+
</script>
|
|
4
|
+
|
|
5
|
+
<HierarchicalObject
|
|
6
|
+
onChildMount={(child) => scene.add(child)}
|
|
7
|
+
onChildDestroy={(child) => scene.remove(child)}
|
|
8
|
+
>
|
|
9
|
+
<slot />
|
|
10
|
+
</HierarchicalObject>
|