@threlte/xr 0.1.3 → 1.0.0-next.0
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 +2 -3
- package/dist/components/ARButton.svelte.d.ts +0 -6
- package/dist/components/Controller.svelte +12 -28
- package/dist/components/Hand.svelte +14 -20
- package/dist/components/Hand.svelte.d.ts +8 -1
- package/dist/components/VRButton.svelte +2 -3
- package/dist/components/VRButton.svelte.d.ts +0 -6
- package/dist/components/XR.svelte +15 -15
- package/dist/components/XR.svelte.d.ts +32 -18
- package/dist/components/XRButton.svelte +18 -20
- package/dist/components/XRButton.svelte.d.ts +7 -6
- package/dist/hooks/useXR.d.ts +0 -1
- package/dist/internal/setupControllers.js +2 -2
- package/dist/internal/setupHands.js +2 -2
- package/dist/internal/setupRaf.js +2 -2
- package/dist/internal/stores.d.ts +6 -14
- package/dist/internal/stores.js +2 -2
- package/dist/plugins/pointerControls/useComponentEventHandlers.js +3 -5
- package/package.json +19 -19
- package/dist/plugins/pointerControls/context.d.ts +0 -12
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
```
|
|
11
11
|
-->
|
|
12
12
|
<script>import XRButton from "./XRButton.svelte";
|
|
13
|
+
let { ...props } = $props();
|
|
13
14
|
</script>
|
|
14
15
|
|
|
15
16
|
<XRButton
|
|
@@ -18,8 +19,6 @@
|
|
|
18
19
|
requiredFeatures: ['plane-detection'],
|
|
19
20
|
optionalFeatures: ['local-floor', 'bounded-floor', 'hand-tracking', 'layers', 'hit-test']
|
|
20
21
|
}}
|
|
21
|
-
{
|
|
22
|
+
{...props}
|
|
22
23
|
mode="immersive-ar"
|
|
23
|
-
on:click
|
|
24
|
-
on:error
|
|
25
24
|
/>
|
|
@@ -18,12 +18,6 @@ declare const __propDef: {
|
|
|
18
18
|
}) | undefined;
|
|
19
19
|
};
|
|
20
20
|
events: {
|
|
21
|
-
click: CustomEvent<{
|
|
22
|
-
state: "blocked" | "unsupported" | "insecure" | "supported";
|
|
23
|
-
nativeEvent: MouseEvent;
|
|
24
|
-
}>;
|
|
25
|
-
error: CustomEvent<Error>;
|
|
26
|
-
} & {
|
|
27
21
|
[evt: string]: CustomEvent<any>;
|
|
28
22
|
};
|
|
29
23
|
slots: {};
|
|
@@ -5,14 +5,9 @@
|
|
|
5
5
|
|
|
6
6
|
context="module"
|
|
7
7
|
>import { writable } from "svelte/store";
|
|
8
|
-
import { T
|
|
8
|
+
import { T } from "@threlte/core";
|
|
9
9
|
import { left as leftStore, right as rightStore } from "../hooks/useController";
|
|
10
|
-
import {
|
|
11
|
-
isHandTracking,
|
|
12
|
-
pointerState,
|
|
13
|
-
teleportState,
|
|
14
|
-
controllerDispatchers
|
|
15
|
-
} from "../internal/stores";
|
|
10
|
+
import { isHandTracking, pointerState, teleportState, controllerEvents } from "../internal/stores";
|
|
16
11
|
import PointerCursor from "./internal/PointerCursor.svelte";
|
|
17
12
|
import ShortRay from "./internal/ShortRay.svelte";
|
|
18
13
|
import ScenePortal from "./internal/ScenePortal.svelte";
|
|
@@ -24,28 +19,17 @@ const stores = {
|
|
|
24
19
|
};
|
|
25
20
|
</script>
|
|
26
21
|
|
|
27
|
-
<script>
|
|
28
|
-
export let right = void 0;
|
|
29
|
-
export let hand = void 0;
|
|
30
|
-
const dispatch = createRawEventDispatcher();
|
|
22
|
+
<script>let { left, right, hand, ...props } = $props();
|
|
31
23
|
const handedness = writable(left ? "left" : right ? "right" : hand);
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
$:
|
|
42
|
-
targetRay = $store?.targetRay;
|
|
43
|
-
$:
|
|
44
|
-
model = $store?.model;
|
|
45
|
-
$:
|
|
46
|
-
hasPointerControls = $pointerState[$handedness].enabled;
|
|
47
|
-
$:
|
|
48
|
-
hasTeleportControls = $teleportState[$handedness].enabled;
|
|
24
|
+
$effect.pre(() => handedness.set(left ? "left" : right ? "right" : hand));
|
|
25
|
+
controllerEvents[$handedness].set(props.$$events);
|
|
26
|
+
$effect.pre(() => controllerEvents[$handedness].set(props.$$events));
|
|
27
|
+
let store = $derived(stores[$handedness]);
|
|
28
|
+
let grip = $derived($store?.grip);
|
|
29
|
+
let targetRay = $derived($store?.targetRay);
|
|
30
|
+
let model = $derived($store?.model);
|
|
31
|
+
let hasPointerControls = $derived($pointerState[$handedness].enabled);
|
|
32
|
+
let hasTeleportControls = $derived($teleportState[$handedness].enabled);
|
|
49
33
|
</script>
|
|
50
34
|
|
|
51
35
|
{#if !$isHandTracking}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
<script
|
|
2
2
|
|
|
3
3
|
context="module"
|
|
4
|
-
>import {
|
|
5
|
-
import {
|
|
4
|
+
>import { Group } from "three";
|
|
5
|
+
import { T, useThrelte, useTask } from "@threlte/core";
|
|
6
|
+
import { isHandTracking, handEvents } from "../internal/stores";
|
|
6
7
|
import { left as leftStore, right as rightStore } from "../hooks/useHand";
|
|
7
8
|
import ScenePortal from "./internal/ScenePortal.svelte";
|
|
8
9
|
import { writable } from "svelte/store";
|
|
@@ -12,18 +13,13 @@ const stores = {
|
|
|
12
13
|
};
|
|
13
14
|
</script>
|
|
14
15
|
|
|
15
|
-
<script>
|
|
16
|
-
export let right = void 0;
|
|
17
|
-
export let hand = void 0;
|
|
18
|
-
const dispatch = createRawEventDispatcher();
|
|
16
|
+
<script>let { left, right, hand, ...props } = $props();
|
|
19
17
|
const { xr } = useThrelte().renderer;
|
|
20
18
|
const space = xr.getReferenceSpace();
|
|
21
19
|
const handedness = writable(left ? "left" : right ? "right" : hand);
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
handDispatchers[$handedness].set(dispatch);
|
|
26
|
-
let children;
|
|
20
|
+
$effect.pre(() => handedness.set(left ? "left" : right ? "right" : hand));
|
|
21
|
+
$effect.pre(() => handEvents[$handedness].set(props.$$events));
|
|
22
|
+
let children = new Group();
|
|
27
23
|
const { start, stop } = useTask(
|
|
28
24
|
() => {
|
|
29
25
|
const frame = xr.getFrame();
|
|
@@ -39,18 +35,16 @@ const { start, stop } = useTask(
|
|
|
39
35
|
},
|
|
40
36
|
{ autoStart: false }
|
|
41
37
|
);
|
|
42
|
-
|
|
38
|
+
$effect.pre(() => {
|
|
43
39
|
if ($isHandTracking && ($$slots.wrist || $$slots.default) && inputSource) {
|
|
44
40
|
start();
|
|
45
41
|
} else {
|
|
46
42
|
stop();
|
|
47
43
|
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
$:
|
|
53
|
-
model = $store?.model;
|
|
44
|
+
});
|
|
45
|
+
let store = $derived(stores[$handedness]);
|
|
46
|
+
let inputSource = $derived($store?.inputSource);
|
|
47
|
+
let model = $derived($store?.model);
|
|
54
48
|
</script>
|
|
55
49
|
|
|
56
50
|
{#if $store?.hand && $isHandTracking}
|
|
@@ -69,9 +63,9 @@ $:
|
|
|
69
63
|
|
|
70
64
|
{#if $isHandTracking}
|
|
71
65
|
<ScenePortal>
|
|
72
|
-
<T
|
|
66
|
+
<T is={children}>
|
|
73
67
|
<slot name="wrist" />
|
|
74
68
|
<slot />
|
|
75
|
-
</T
|
|
69
|
+
</T>
|
|
76
70
|
</ScenePortal>
|
|
77
71
|
{/if}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { SvelteComponent } from "svelte";
|
|
2
2
|
import type { XRHandEvent } from '../types';
|
|
3
3
|
declare const __propDef: {
|
|
4
|
-
props: {
|
|
4
|
+
props: ({
|
|
5
5
|
/** Whether the XRHand should be matched with the left hand. */
|
|
6
6
|
left: true;
|
|
7
7
|
right?: undefined;
|
|
@@ -16,6 +16,13 @@ declare const __propDef: {
|
|
|
16
16
|
hand: 'left' | 'right';
|
|
17
17
|
left?: undefined;
|
|
18
18
|
right?: undefined;
|
|
19
|
+
}) & {
|
|
20
|
+
$$events: {
|
|
21
|
+
connected: XRHandEvent<'connected'>;
|
|
22
|
+
disconnected: XRHandEvent<'disconnected'>;
|
|
23
|
+
pinchstart: XRHandEvent<'pinchstart'>;
|
|
24
|
+
pinchend: XRHandEvent<'pinchend'>;
|
|
25
|
+
};
|
|
19
26
|
};
|
|
20
27
|
slots: {
|
|
21
28
|
'target-ray': {};
|
|
@@ -10,14 +10,13 @@
|
|
|
10
10
|
```
|
|
11
11
|
-->
|
|
12
12
|
<script>import XRButton from "./XRButton.svelte";
|
|
13
|
+
let { ...props } = $props();
|
|
13
14
|
</script>
|
|
14
15
|
|
|
15
16
|
<XRButton
|
|
16
17
|
sessionInit={{
|
|
17
18
|
optionalFeatures: ['local-floor', 'bounded-floor', 'hand-tracking', 'layers']
|
|
18
19
|
}}
|
|
19
|
-
{
|
|
20
|
+
{...props}
|
|
20
21
|
mode="immersive-vr"
|
|
21
|
-
on:click
|
|
22
|
-
on:error
|
|
23
22
|
/>
|
|
@@ -12,12 +12,6 @@ declare const __propDef: {
|
|
|
12
12
|
styled?: boolean | undefined;
|
|
13
13
|
}, "mode" | "sessionInit">;
|
|
14
14
|
events: {
|
|
15
|
-
click: CustomEvent<{
|
|
16
|
-
state: "blocked" | "unsupported" | "insecure" | "supported";
|
|
17
|
-
nativeEvent: MouseEvent;
|
|
18
|
-
}>;
|
|
19
|
-
error: CustomEvent<Error>;
|
|
20
|
-
} & {
|
|
21
15
|
[evt: string]: CustomEvent<any>;
|
|
22
16
|
};
|
|
23
17
|
slots: {};
|
|
@@ -30,10 +30,12 @@ import { setupRaf } from "../internal/setupRaf";
|
|
|
30
30
|
import { setupHeadset } from "../internal/setupHeadset";
|
|
31
31
|
import { setupControllers } from "../internal/setupControllers";
|
|
32
32
|
import { setupHands } from "../internal/setupHands";
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
33
|
+
let {
|
|
34
|
+
foveation = 1,
|
|
35
|
+
frameRate,
|
|
36
|
+
referenceSpace = "local-floor",
|
|
37
|
+
...props
|
|
38
|
+
} = $props();
|
|
37
39
|
const { renderer, renderMode } = useThrelte();
|
|
38
40
|
const { xr } = renderer;
|
|
39
41
|
let originalRenderMode = $renderMode;
|
|
@@ -43,22 +45,22 @@ setupControllers();
|
|
|
43
45
|
setupHands();
|
|
44
46
|
const handleSessionStart = () => {
|
|
45
47
|
isPresenting.set(true);
|
|
46
|
-
|
|
48
|
+
props.$$events?.sessionstart?.({ type: "sessionstart", target: $session });
|
|
47
49
|
};
|
|
48
50
|
const handleSessionEnd = () => {
|
|
49
|
-
|
|
51
|
+
props.$$events?.sessionend?.({ type: "sessionend", target: $session });
|
|
50
52
|
isPresenting.set(false);
|
|
51
53
|
session.set(void 0);
|
|
52
54
|
};
|
|
53
55
|
const handleVisibilityChange = (event) => {
|
|
54
|
-
|
|
56
|
+
props.$$events?.visibilitychange?.({ ...event, target: $session });
|
|
55
57
|
};
|
|
56
58
|
const handleInputSourcesChange = (event) => {
|
|
57
59
|
$isHandTracking = Object.values(event.session.inputSources).some((source) => source.hand);
|
|
58
|
-
|
|
60
|
+
props.$$events?.inputsourceschange?.({ ...event, target: $session });
|
|
59
61
|
};
|
|
60
62
|
const handleFramerateChange = (event) => {
|
|
61
|
-
|
|
63
|
+
props.$$events?.visibilitychange?.({ ...event, target: $session });
|
|
62
64
|
};
|
|
63
65
|
const updateTargetFrameRate = (frameRate2) => {
|
|
64
66
|
if (frameRate2 === void 0)
|
|
@@ -102,14 +104,12 @@ onMount(() => {
|
|
|
102
104
|
xr.removeEventListener("sessionend", handleSessionEnd);
|
|
103
105
|
};
|
|
104
106
|
});
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
xr.setFoveation(foveation);
|
|
109
|
-
$: {
|
|
107
|
+
$effect.pre(() => updateTargetFrameRate(frameRate));
|
|
108
|
+
$effect.pre(() => xr.setFoveation(foveation));
|
|
109
|
+
$effect.pre(() => {
|
|
110
110
|
xr.setReferenceSpaceType(referenceSpace);
|
|
111
111
|
$referenceSpaceType = referenceSpace;
|
|
112
|
-
}
|
|
112
|
+
});
|
|
113
113
|
</script>
|
|
114
114
|
|
|
115
115
|
{#if $isPresenting}
|
|
@@ -4,21 +4,35 @@ import type { XRSessionEvent } from '../types';
|
|
|
4
4
|
declare const __propDef: {
|
|
5
5
|
props: {
|
|
6
6
|
/**
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
7
|
+
* Enables foveated rendering. Default is `1`, the three.js default.
|
|
8
|
+
*
|
|
9
|
+
* 0 = no foveation, full resolution
|
|
10
|
+
*
|
|
11
|
+
* 1 = maximum foveation, the edges render at lower resolution
|
|
12
|
+
*/
|
|
13
|
+
foveation?: number | undefined;
|
|
13
14
|
/**
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
15
|
+
* The target framerate for the XRSystem. Smaller rates give more CPU headroom at the cost of responsiveness.
|
|
16
|
+
* Recommended range is `72`-`120`. Default is unset and left to the device.
|
|
17
|
+
* @note If your experience cannot effectively reach the target framerate, it will be subject to frame reprojection
|
|
18
|
+
* which will halve the effective framerate. Choose a conservative estimate that balances responsiveness and
|
|
19
|
+
* headroom based on your experience.
|
|
20
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/API/WebXR_Device_API/Rendering#refresh_rate_and_frame_rate
|
|
21
|
+
*/
|
|
22
|
+
frameRate?: number | undefined;
|
|
23
|
+
/** Type of WebXR reference space to use. Default is `local-floor` */
|
|
24
|
+
referenceSpace?: XRReferenceSpaceType | undefined;
|
|
25
|
+
} & {
|
|
26
|
+
$$events: {
|
|
27
|
+
/** Called as an XRSession is requested */
|
|
28
|
+
sessionstart(): XRSessionEvent<'sessionstart'>;
|
|
29
|
+
/** Called after an XRSession is terminated */
|
|
30
|
+
sessionend(): XRSessionEvent<'sessionend'>;
|
|
31
|
+
/** Called when an XRSession is hidden or unfocused. */
|
|
32
|
+
visibilitychange(): globalThis.XRSessionEvent;
|
|
33
|
+
/** Called when available inputsources change */
|
|
34
|
+
inputsourceschange(): globalThis.XRSessionEvent;
|
|
35
|
+
};
|
|
22
36
|
};
|
|
23
37
|
slots: {
|
|
24
38
|
default: {};
|
|
@@ -26,13 +40,13 @@ declare const __propDef: {
|
|
|
26
40
|
};
|
|
27
41
|
events: {
|
|
28
42
|
/** Called as an XRSession is requested */
|
|
29
|
-
sessionstart: XRSessionEvent<'sessionstart'>;
|
|
43
|
+
sessionstart(): XRSessionEvent<'sessionstart'>;
|
|
30
44
|
/** Called after an XRSession is terminated */
|
|
31
|
-
sessionend: XRSessionEvent<'sessionend'>;
|
|
45
|
+
sessionend(): XRSessionEvent<'sessionend'>;
|
|
32
46
|
/** Called when an XRSession is hidden or unfocused. */
|
|
33
|
-
visibilitychange: globalThis.XRSessionEvent;
|
|
47
|
+
visibilitychange(): globalThis.XRSessionEvent;
|
|
34
48
|
/** Called when available inputsources change */
|
|
35
|
-
inputsourceschange: globalThis.XRSessionEvent;
|
|
49
|
+
inputsourceschange(): globalThis.XRSessionEvent;
|
|
36
50
|
};
|
|
37
51
|
};
|
|
38
52
|
export type XrProps = typeof __propDef.props;
|
|
@@ -17,39 +17,34 @@ display info about your WebXR session. This is aliased by `ARButton` and
|
|
|
17
17
|
/>
|
|
18
18
|
```
|
|
19
19
|
-->
|
|
20
|
-
<script>import {
|
|
21
|
-
import { getXRSupportState } from "../lib/getXRSupportState";
|
|
20
|
+
<script>import { getXRSupportState } from "../lib/getXRSupportState";
|
|
22
21
|
import { toggleXRSession } from "../lib/toggleXRSession";
|
|
23
22
|
import { session, xr } from "../internal/stores";
|
|
24
|
-
|
|
25
|
-
export let sessionInit = void 0;
|
|
26
|
-
export let force = void 0;
|
|
27
|
-
export let styled = true;
|
|
28
|
-
const dispatch = createEventDispatcher();
|
|
23
|
+
let { mode, sessionInit, force, styled = true, ...props } = $props();
|
|
29
24
|
const handleButtonClick = async (nativeEvent, state) => {
|
|
30
25
|
if (!$xr) {
|
|
31
26
|
throw new Error(
|
|
32
27
|
"The <XR> component was not created. This is required to start an XR session."
|
|
33
28
|
);
|
|
34
29
|
}
|
|
35
|
-
|
|
30
|
+
props.$$events?.click?.({ state, nativeEvent });
|
|
36
31
|
if (state !== "supported")
|
|
37
32
|
return;
|
|
38
33
|
try {
|
|
39
34
|
await toggleXRSession(mode, sessionInit, force);
|
|
40
35
|
} catch (error) {
|
|
41
|
-
|
|
36
|
+
props.$$events?.error?.(error);
|
|
42
37
|
}
|
|
43
38
|
};
|
|
44
|
-
|
|
45
|
-
|
|
39
|
+
let modeText = $derived(
|
|
40
|
+
{
|
|
46
41
|
"immersive-vr": "VR",
|
|
47
42
|
"immersive-ar": "AR",
|
|
48
43
|
inline: "inline"
|
|
49
|
-
}[mode]
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
44
|
+
}[mode]
|
|
45
|
+
);
|
|
46
|
+
let style = $derived(
|
|
47
|
+
styled ? `
|
|
53
48
|
position: absolute;
|
|
54
49
|
bottom: 24px;
|
|
55
50
|
left: 50%;
|
|
@@ -60,15 +55,18 @@ $:
|
|
|
60
55
|
color: white;
|
|
61
56
|
outline: none;
|
|
62
57
|
z-index: 10;
|
|
63
|
-
${
|
|
64
|
-
|
|
65
|
-
|
|
58
|
+
${props.style ?? ""}
|
|
59
|
+
` : props.style
|
|
60
|
+
);
|
|
66
61
|
</script>
|
|
67
62
|
|
|
68
63
|
{#await getXRSupportState(mode) then state}
|
|
69
64
|
<button
|
|
70
|
-
{
|
|
71
|
-
|
|
65
|
+
on:click={(event) => {
|
|
66
|
+
handleButtonClick(event, state)
|
|
67
|
+
}}
|
|
68
|
+
{...props}
|
|
69
|
+
{style}
|
|
72
70
|
>
|
|
73
71
|
{#if state === 'unsupported'}
|
|
74
72
|
{modeText} unsupported
|
|
@@ -3,22 +3,23 @@ import { SvelteComponent } from "svelte";
|
|
|
3
3
|
import type { HTMLButtonAttributes } from 'svelte/elements';
|
|
4
4
|
declare const __propDef: {
|
|
5
5
|
props: HTMLButtonAttributes & {
|
|
6
|
+
/** The type of `XRSession` to create */
|
|
6
7
|
mode: XRSessionMode;
|
|
8
|
+
/**
|
|
9
|
+
* `XRSession` configuration options
|
|
10
|
+
* @see https://immersive-web.github.io/webxr/#feature-dependencies
|
|
11
|
+
*/
|
|
7
12
|
sessionInit?: (XRSessionInit & {
|
|
8
13
|
domOverlay?: {
|
|
9
14
|
root: HTMLElement;
|
|
10
15
|
} | undefined;
|
|
11
16
|
}) | undefined;
|
|
17
|
+
/** Whether this button should only enter / exit an `XRSession`. Default is to toggle both ways */
|
|
12
18
|
force?: "enter" | "exit" | undefined;
|
|
19
|
+
/** Whether to apply automatic styling to the button. Set false to apply custom styles. Default is true. */
|
|
13
20
|
styled?: boolean | undefined;
|
|
14
21
|
};
|
|
15
22
|
events: {
|
|
16
|
-
click: CustomEvent<{
|
|
17
|
-
state: 'unsupported' | 'insecure' | 'blocked' | 'supported';
|
|
18
|
-
nativeEvent: MouseEvent;
|
|
19
|
-
}>;
|
|
20
|
-
error: CustomEvent<Error>;
|
|
21
|
-
} & {
|
|
22
23
|
[evt: string]: CustomEvent<any>;
|
|
23
24
|
};
|
|
24
25
|
slots: {};
|
package/dist/hooks/useXR.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { useThrelte } from '@threlte/core';
|
|
|
3
3
|
import { onMount } from 'svelte';
|
|
4
4
|
import { useHandTrackingState } from './useHandTrackingState';
|
|
5
5
|
import { gaze, left, right } from '../hooks/useController';
|
|
6
|
-
import {
|
|
6
|
+
import { controllerEvents } from './stores';
|
|
7
7
|
export const setupControllers = () => {
|
|
8
8
|
const factory = new XRControllerModelFactory();
|
|
9
9
|
const stores = { left, right, none: gaze };
|
|
@@ -23,7 +23,7 @@ export const setupControllers = () => {
|
|
|
23
23
|
if (hasHands())
|
|
24
24
|
return;
|
|
25
25
|
const { data } = event;
|
|
26
|
-
|
|
26
|
+
controllerEvents[data.handedness]?.[event.type]?.(event);
|
|
27
27
|
};
|
|
28
28
|
function handleConnected(event) {
|
|
29
29
|
const { model, targetRay, grip } = indexMap.get(this);
|
|
@@ -3,7 +3,7 @@ import { useThrelte } from '@threlte/core';
|
|
|
3
3
|
import { onMount } from 'svelte';
|
|
4
4
|
import { left, right } from '../hooks/useHand';
|
|
5
5
|
import { useHandTrackingState } from './useHandTrackingState';
|
|
6
|
-
import {
|
|
6
|
+
import { handEvents } from './stores';
|
|
7
7
|
export const setupHands = () => {
|
|
8
8
|
const factory = new XRHandModelFactory();
|
|
9
9
|
const stores = { left, right };
|
|
@@ -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
|
-
|
|
27
|
+
handEvents[handedness]?.[event.type]?.(event);
|
|
28
28
|
};
|
|
29
29
|
function handleConnected(event) {
|
|
30
30
|
const hand = this;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// @ts-expect-error svelte/internal is untyped.
|
|
2
|
-
import { set_raf } from 'svelte/internal'
|
|
2
|
+
// import { set_raf } from 'svelte/internal'
|
|
3
3
|
import { onDestroy } from 'svelte';
|
|
4
4
|
import { watch } from '@threlte/core';
|
|
5
5
|
import { session } from './stores';
|
|
@@ -8,7 +8,7 @@ export const setupRaf = () => {
|
|
|
8
8
|
return;
|
|
9
9
|
const browserRaf = (fn) => requestAnimationFrame(fn);
|
|
10
10
|
const currentRaf = { fn: browserRaf };
|
|
11
|
-
set_raf((fn) => currentRaf.fn(fn))
|
|
11
|
+
// set_raf((fn: FrameRequestCallback) => currentRaf.fn(fn))
|
|
12
12
|
watch(session, (session) => {
|
|
13
13
|
if (session) {
|
|
14
14
|
currentRaf.fn = (fn) => session.requestAnimationFrame(fn);
|
|
@@ -5,21 +5,13 @@ export declare const isHandTracking: import("@threlte/core").CurrentWritable<boo
|
|
|
5
5
|
export declare const session: import("@threlte/core").CurrentWritable<XRSession | undefined>;
|
|
6
6
|
export declare const referenceSpaceType: import("@threlte/core").CurrentWritable<XRReferenceSpaceType | undefined>;
|
|
7
7
|
export declare const xr: import("@threlte/core").CurrentWritable<WebXRManager | undefined>;
|
|
8
|
-
export declare const
|
|
9
|
-
left: import("@threlte/core").CurrentWritable<
|
|
10
|
-
|
|
11
|
-
}) | undefined>;
|
|
12
|
-
right: import("@threlte/core").CurrentWritable<((<Type extends string>(type: Type, payload?: unknown) => void) & {
|
|
13
|
-
hasEventListener: <Type_1 extends string>(type: Type_1) => boolean;
|
|
14
|
-
}) | undefined>;
|
|
8
|
+
export declare const controllerEvents: {
|
|
9
|
+
left: import("@threlte/core").CurrentWritable<Record<string, (arg: unknown) => void> | undefined>;
|
|
10
|
+
right: import("@threlte/core").CurrentWritable<Record<string, (arg: unknown) => void> | undefined>;
|
|
15
11
|
};
|
|
16
|
-
export declare const
|
|
17
|
-
left: import("@threlte/core").CurrentWritable<
|
|
18
|
-
|
|
19
|
-
}) | undefined>;
|
|
20
|
-
right: import("@threlte/core").CurrentWritable<((<Type extends string>(type: Type, payload?: unknown) => void) & {
|
|
21
|
-
hasEventListener: <Type_1 extends string>(type: Type_1) => boolean;
|
|
22
|
-
}) | undefined>;
|
|
12
|
+
export declare const handEvents: {
|
|
13
|
+
left: import("@threlte/core").CurrentWritable<Record<string, (arg: unknown) => void> | undefined>;
|
|
14
|
+
right: import("@threlte/core").CurrentWritable<Record<string, (arg: unknown) => void> | undefined>;
|
|
23
15
|
};
|
|
24
16
|
export declare const teleportState: import("@threlte/core").CurrentWritable<{
|
|
25
17
|
left: {
|
package/dist/internal/stores.js
CHANGED
|
@@ -4,11 +4,11 @@ export const isHandTracking = currentWritable(false);
|
|
|
4
4
|
export const session = currentWritable(undefined);
|
|
5
5
|
export const referenceSpaceType = currentWritable(undefined);
|
|
6
6
|
export const xr = currentWritable(undefined);
|
|
7
|
-
export const
|
|
7
|
+
export const controllerEvents = {
|
|
8
8
|
left: currentWritable(undefined),
|
|
9
9
|
right: currentWritable(undefined)
|
|
10
10
|
};
|
|
11
|
-
export const
|
|
11
|
+
export const handEvents = {
|
|
12
12
|
left: currentWritable(undefined),
|
|
13
13
|
right: currentWritable(undefined)
|
|
14
14
|
};
|
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
import { onMount } from 'svelte';
|
|
2
|
-
import { get_current_component } from 'svelte/internal';
|
|
3
2
|
import { writable } from 'svelte/store';
|
|
4
|
-
import { events } from './types'
|
|
3
|
+
// import { events } from './types'
|
|
5
4
|
export const useComponentHasEventHandlers = () => {
|
|
6
|
-
const component = get_current_component();
|
|
7
5
|
const hasEventHandlers = writable(false);
|
|
8
6
|
onMount(() => {
|
|
9
|
-
const match = Object.keys(component.$$.callbacks).some((callback) => events.includes(callback))
|
|
10
|
-
hasEventHandlers.set(
|
|
7
|
+
// const match = Object.keys(component.$$.callbacks).some((callback) => events.includes(callback))
|
|
8
|
+
hasEventHandlers.set(true);
|
|
11
9
|
});
|
|
12
10
|
return {
|
|
13
11
|
hasEventHandlers
|
package/package.json
CHANGED
|
@@ -1,29 +1,29 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@threlte/xr",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0-next.0",
|
|
4
4
|
"author": "Micheal Parks <michealparks1989@gmail.com> (https://parks.lol)",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"devDependencies": {
|
|
7
|
-
"@sveltejs/adapter-auto": "^3.
|
|
8
|
-
"@sveltejs/kit": "^2.
|
|
9
|
-
"@sveltejs/package": "^2.
|
|
10
|
-
"@sveltejs/vite-plugin-svelte": "^3.0.
|
|
11
|
-
"@typescript-eslint/eslint-plugin": "^
|
|
12
|
-
"@typescript-eslint/parser": "^
|
|
13
|
-
"eslint": "^
|
|
14
|
-
"eslint-plugin-svelte": "^2.
|
|
15
|
-
"svelte-check": "^3.6.
|
|
16
|
-
"typescript": "^5.
|
|
17
|
-
"@types/three": "^0.
|
|
18
|
-
"autoprefixer": "^10.4.
|
|
19
|
-
"postcss": "^8.4.
|
|
7
|
+
"@sveltejs/adapter-auto": "^3.2.0",
|
|
8
|
+
"@sveltejs/kit": "^2.5.5",
|
|
9
|
+
"@sveltejs/package": "^2.3.1",
|
|
10
|
+
"@sveltejs/vite-plugin-svelte": "^3.0.2",
|
|
11
|
+
"@typescript-eslint/eslint-plugin": "^7.5.0",
|
|
12
|
+
"@typescript-eslint/parser": "^7.5.0",
|
|
13
|
+
"eslint": "^9.0.0",
|
|
14
|
+
"eslint-plugin-svelte": "^2.36.0",
|
|
15
|
+
"svelte-check": "^3.6.9",
|
|
16
|
+
"typescript": "^5.4.4",
|
|
17
|
+
"@types/three": "^0.163.0",
|
|
18
|
+
"autoprefixer": "^10.4.19",
|
|
19
|
+
"postcss": "^8.4.38",
|
|
20
20
|
"publint": "^0.2.7",
|
|
21
|
-
"svelte": "^4.2.
|
|
22
|
-
"three": "^0.
|
|
21
|
+
"svelte": "^4.2.12",
|
|
22
|
+
"three": "^0.163.0",
|
|
23
23
|
"tslib": "^2.6.2",
|
|
24
|
-
"vite": "^5.
|
|
25
|
-
"vite-plugin-mkcert": "^1.17.
|
|
26
|
-
"@threlte/core": "
|
|
24
|
+
"vite": "^5.2.8",
|
|
25
|
+
"vite-plugin-mkcert": "^1.17.5",
|
|
26
|
+
"@threlte/core": "8.0.0-next.0"
|
|
27
27
|
},
|
|
28
28
|
"peerDependencies": {
|
|
29
29
|
"svelte": ">=4",
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import type { createRawEventDispatcher } from '@threlte/core';
|
|
2
|
-
import type { ControlsContext, HandContext, ThrelteXREvents } from './types';
|
|
3
|
-
export declare const getHandContext: (hand: 'left' | 'right') => HandContext;
|
|
4
|
-
export declare const setHandContext: (hand: 'left' | 'right', context: HandContext) => void;
|
|
5
|
-
export declare const getControlsContext: () => ControlsContext;
|
|
6
|
-
export declare const setControlsContext: (context: ControlsContext) => void;
|
|
7
|
-
interface InternalContext {
|
|
8
|
-
dispatchers: WeakMap<THREE.Object3D, ReturnType<typeof createRawEventDispatcher<ThrelteXREvents>>>;
|
|
9
|
-
}
|
|
10
|
-
export declare const getInternalContext: () => InternalContext;
|
|
11
|
-
export declare const setInternalContext: () => void;
|
|
12
|
-
export {};
|