@threlte/xr 0.0.12 → 0.1.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.
Files changed (48) hide show
  1. package/dist/components/ARButton.svelte +1 -1
  2. package/dist/components/ARButton.svelte.d.ts +38 -37
  3. package/dist/components/Controller.svelte +24 -83
  4. package/dist/components/Hand.svelte +27 -64
  5. package/dist/components/Hand.svelte.d.ts +1 -0
  6. package/dist/components/Headset.svelte.d.ts +1 -0
  7. package/dist/components/VRButton.svelte.d.ts +38 -37
  8. package/dist/components/XR.svelte +47 -53
  9. package/dist/components/XRButton.svelte +2 -2
  10. package/dist/components/XRButton.svelte.d.ts +38 -37
  11. package/dist/components/internal/Cursor.svelte.d.ts +1 -0
  12. package/dist/components/internal/PointerCursor.svelte +7 -3
  13. package/dist/components/internal/PointerCursor.svelte.d.ts +1 -0
  14. package/dist/components/internal/ScenePortal.svelte.d.ts +1 -0
  15. package/dist/components/internal/ShortRay.svelte.d.ts +1 -0
  16. package/dist/components/internal/TeleportCursor.svelte +7 -3
  17. package/dist/components/internal/TeleportCursor.svelte.d.ts +1 -0
  18. package/dist/components/internal/TeleportRay.svelte.d.ts +1 -0
  19. package/dist/hooks/useController.js +2 -4
  20. package/dist/hooks/useHand.js +2 -0
  21. package/dist/hooks/useHandJoint.d.ts +2 -2
  22. package/dist/hooks/useHeadset.d.ts +2 -1
  23. package/dist/hooks/useHeadset.js +1 -1
  24. package/dist/hooks/useHitTest.d.ts +2 -2
  25. package/dist/hooks/useHitTest.js +16 -6
  26. package/dist/hooks/useTeleport.d.ts +2 -2
  27. package/dist/hooks/useTeleport.js +2 -2
  28. package/dist/internal/setupControllers.d.ts +1 -0
  29. package/dist/internal/setupControllers.js +69 -0
  30. package/dist/internal/setupHands.d.ts +1 -0
  31. package/dist/internal/setupHands.js +63 -0
  32. package/dist/internal/setupHeadset.d.ts +3 -0
  33. package/dist/internal/{headset.js → setupHeadset.js} +2 -3
  34. package/dist/internal/setupRaf.d.ts +1 -0
  35. package/dist/internal/{updateRaf.js → setupRaf.js} +2 -2
  36. package/dist/internal/stores.d.ts +22 -7
  37. package/dist/internal/stores.js +15 -9
  38. package/dist/internal/useFixed.d.ts +1 -1
  39. package/dist/internal/useHandTrackingState.js +1 -1
  40. package/dist/lib/toggleXRSession.js +3 -3
  41. package/dist/plugins/teleportControls/context.d.ts +7 -6
  42. package/dist/plugins/teleportControls/hook.d.ts +5 -4
  43. package/dist/plugins/teleportControls/index.d.ts +1 -1
  44. package/dist/types.d.ts +10 -8
  45. package/package.json +4 -4
  46. package/dist/internal/headset.d.ts +0 -3
  47. package/dist/internal/updateRaf.d.ts +0 -1
  48. package/dist/plugins/pointerControls/types.d.ts +0 -61
@@ -17,7 +17,7 @@
17
17
  sessionInit={{
18
18
  domOverlay: typeof document !== 'undefined' ? { root: document.body } : undefined,
19
19
  requiredFeatures: ['plane-detection'],
20
- optionalFeatures: ['hit-test', 'light-estimation', 'dom-overlay', 'dom-overlay-for-handheld-ar']
20
+ optionalFeatures: ['local-floor', 'bounded-floor', 'hand-tracking', 'layers', 'hit-test']
21
21
  }}
22
22
  {...$$restProps}
23
23
  mode='immersive-ar'
@@ -1,3 +1,4 @@
1
+ /// <reference types="bun-types" />
1
2
  /// <reference types="webxr" />
2
3
  import { SvelteComponent } from "svelte";
3
4
  declare const __propDef: {
@@ -56,12 +57,12 @@ declare const __propDef: {
56
57
  results?: number | null | undefined;
57
58
  security?: string | null | undefined;
58
59
  unselectable?: "on" | "off" | null | undefined;
59
- inputmode?: "search" | "none" | "text" | "tel" | "url" | "email" | "numeric" | "decimal" | null | undefined;
60
+ inputmode?: "url" | "search" | "none" | "text" | "tel" | "email" | "numeric" | "decimal" | null | undefined;
60
61
  is?: string | null | undefined;
61
62
  'bind:innerHTML'?: string | null | undefined;
62
63
  'bind:textContent'?: string | null | undefined;
63
64
  'bind:innerText'?: string | null | undefined;
64
- 'bind:contentRect'?: DOMRectReadOnly | null | undefined;
65
+ 'bind:contentRect'?: any;
65
66
  'bind:contentBoxSize'?: ResizeObserverSize[] | null | undefined;
66
67
  'bind:borderBoxSize'?: ResizeObserverSize[] | null | undefined;
67
68
  'bind:devicePixelContentBoxSize'?: ResizeObserverSize[] | null | undefined;
@@ -134,37 +135,37 @@ declare const __propDef: {
134
135
  'on:input'?: import("svelte/elements").FormEventHandler<HTMLButtonElement> | null | undefined;
135
136
  'on:reset'?: import("svelte/elements").FormEventHandler<HTMLButtonElement> | null | undefined;
136
137
  'on:submit'?: import("svelte/elements").EventHandler<SubmitEvent, HTMLButtonElement> | null | undefined;
137
- 'on:invalid'?: import("svelte/elements").EventHandler<Event, HTMLButtonElement> | null | undefined;
138
+ 'on:invalid'?: import("svelte/elements").EventHandler<Event<EventTarget>, HTMLButtonElement> | null | undefined;
138
139
  'on:formdata'?: import("svelte/elements").EventHandler<FormDataEvent, HTMLButtonElement> | null | undefined;
139
- 'on:load'?: import("svelte/elements").EventHandler<Event, Element> | null | undefined;
140
- 'on:error'?: import("svelte/elements").EventHandler<Event, Element> | null | undefined;
141
- 'on:toggle'?: import("svelte/elements").EventHandler<Event, HTMLButtonElement> | null | undefined;
140
+ 'on:load'?: import("svelte/elements").EventHandler<Event<EventTarget>, Element> | null | undefined;
141
+ 'on:error'?: import("svelte/elements").EventHandler<Event<EventTarget>, Element> | null | undefined;
142
+ 'on:toggle'?: import("svelte/elements").EventHandler<Event<EventTarget>, HTMLButtonElement> | null | undefined;
142
143
  'on:keydown'?: import("svelte/elements").KeyboardEventHandler<HTMLButtonElement> | null | undefined;
143
144
  'on:keypress'?: import("svelte/elements").KeyboardEventHandler<HTMLButtonElement> | null | undefined;
144
145
  'on:keyup'?: import("svelte/elements").KeyboardEventHandler<HTMLButtonElement> | null | undefined;
145
- 'on:abort'?: import("svelte/elements").EventHandler<Event, HTMLButtonElement> | null | undefined;
146
- 'on:canplay'?: import("svelte/elements").EventHandler<Event, HTMLButtonElement> | null | undefined;
147
- 'on:canplaythrough'?: import("svelte/elements").EventHandler<Event, HTMLButtonElement> | null | undefined;
148
- 'on:cuechange'?: import("svelte/elements").EventHandler<Event, HTMLButtonElement> | null | undefined;
149
- 'on:durationchange'?: import("svelte/elements").EventHandler<Event, HTMLButtonElement> | null | undefined;
150
- 'on:emptied'?: import("svelte/elements").EventHandler<Event, HTMLButtonElement> | null | undefined;
151
- 'on:encrypted'?: import("svelte/elements").EventHandler<Event, HTMLButtonElement> | null | undefined;
152
- 'on:ended'?: import("svelte/elements").EventHandler<Event, HTMLButtonElement> | null | undefined;
153
- 'on:loadeddata'?: import("svelte/elements").EventHandler<Event, HTMLButtonElement> | null | undefined;
154
- 'on:loadedmetadata'?: import("svelte/elements").EventHandler<Event, HTMLButtonElement> | null | undefined;
155
- 'on:loadstart'?: import("svelte/elements").EventHandler<Event, HTMLButtonElement> | null | undefined;
156
- 'on:pause'?: import("svelte/elements").EventHandler<Event, HTMLButtonElement> | null | undefined;
157
- 'on:play'?: import("svelte/elements").EventHandler<Event, HTMLButtonElement> | null | undefined;
158
- 'on:playing'?: import("svelte/elements").EventHandler<Event, HTMLButtonElement> | null | undefined;
159
- 'on:progress'?: import("svelte/elements").EventHandler<Event, HTMLButtonElement> | null | undefined;
160
- 'on:ratechange'?: import("svelte/elements").EventHandler<Event, HTMLButtonElement> | null | undefined;
161
- 'on:seeked'?: import("svelte/elements").EventHandler<Event, HTMLButtonElement> | null | undefined;
162
- 'on:seeking'?: import("svelte/elements").EventHandler<Event, HTMLButtonElement> | null | undefined;
163
- 'on:stalled'?: import("svelte/elements").EventHandler<Event, HTMLButtonElement> | null | undefined;
164
- 'on:suspend'?: import("svelte/elements").EventHandler<Event, HTMLButtonElement> | null | undefined;
165
- 'on:timeupdate'?: import("svelte/elements").EventHandler<Event, HTMLButtonElement> | null | undefined;
166
- 'on:volumechange'?: import("svelte/elements").EventHandler<Event, HTMLButtonElement> | null | undefined;
167
- 'on:waiting'?: import("svelte/elements").EventHandler<Event, HTMLButtonElement> | null | undefined;
146
+ 'on:abort'?: import("svelte/elements").EventHandler<Event<EventTarget>, HTMLButtonElement> | null | undefined;
147
+ 'on:canplay'?: import("svelte/elements").EventHandler<Event<EventTarget>, HTMLButtonElement> | null | undefined;
148
+ 'on:canplaythrough'?: import("svelte/elements").EventHandler<Event<EventTarget>, HTMLButtonElement> | null | undefined;
149
+ 'on:cuechange'?: import("svelte/elements").EventHandler<Event<EventTarget>, HTMLButtonElement> | null | undefined;
150
+ 'on:durationchange'?: import("svelte/elements").EventHandler<Event<EventTarget>, HTMLButtonElement> | null | undefined;
151
+ 'on:emptied'?: import("svelte/elements").EventHandler<Event<EventTarget>, HTMLButtonElement> | null | undefined;
152
+ 'on:encrypted'?: import("svelte/elements").EventHandler<Event<EventTarget>, HTMLButtonElement> | null | undefined;
153
+ 'on:ended'?: import("svelte/elements").EventHandler<Event<EventTarget>, HTMLButtonElement> | null | undefined;
154
+ 'on:loadeddata'?: import("svelte/elements").EventHandler<Event<EventTarget>, HTMLButtonElement> | null | undefined;
155
+ 'on:loadedmetadata'?: import("svelte/elements").EventHandler<Event<EventTarget>, HTMLButtonElement> | null | undefined;
156
+ 'on:loadstart'?: import("svelte/elements").EventHandler<Event<EventTarget>, HTMLButtonElement> | null | undefined;
157
+ 'on:pause'?: import("svelte/elements").EventHandler<Event<EventTarget>, HTMLButtonElement> | null | undefined;
158
+ 'on:play'?: import("svelte/elements").EventHandler<Event<EventTarget>, HTMLButtonElement> | null | undefined;
159
+ 'on:playing'?: import("svelte/elements").EventHandler<Event<EventTarget>, HTMLButtonElement> | null | undefined;
160
+ 'on:progress'?: import("svelte/elements").EventHandler<Event<EventTarget>, HTMLButtonElement> | null | undefined;
161
+ 'on:ratechange'?: import("svelte/elements").EventHandler<Event<EventTarget>, HTMLButtonElement> | null | undefined;
162
+ 'on:seeked'?: import("svelte/elements").EventHandler<Event<EventTarget>, HTMLButtonElement> | null | undefined;
163
+ 'on:seeking'?: import("svelte/elements").EventHandler<Event<EventTarget>, HTMLButtonElement> | null | undefined;
164
+ 'on:stalled'?: import("svelte/elements").EventHandler<Event<EventTarget>, HTMLButtonElement> | null | undefined;
165
+ 'on:suspend'?: import("svelte/elements").EventHandler<Event<EventTarget>, HTMLButtonElement> | null | undefined;
166
+ 'on:timeupdate'?: import("svelte/elements").EventHandler<Event<EventTarget>, HTMLButtonElement> | null | undefined;
167
+ 'on:volumechange'?: import("svelte/elements").EventHandler<Event<EventTarget>, HTMLButtonElement> | null | undefined;
168
+ 'on:waiting'?: import("svelte/elements").EventHandler<Event<EventTarget>, HTMLButtonElement> | null | undefined;
168
169
  'on:auxclick'?: import("svelte/elements").MouseEventHandler<HTMLButtonElement> | null | undefined;
169
170
  'on:click'?: import("svelte/elements").MouseEventHandler<HTMLButtonElement> | null | undefined;
170
171
  'on:contextmenu'?: import("svelte/elements").MouseEventHandler<HTMLButtonElement> | null | undefined;
@@ -184,9 +185,9 @@ declare const __propDef: {
184
185
  'on:mouseout'?: import("svelte/elements").MouseEventHandler<HTMLButtonElement> | null | undefined;
185
186
  'on:mouseover'?: import("svelte/elements").MouseEventHandler<HTMLButtonElement> | null | undefined;
186
187
  'on:mouseup'?: import("svelte/elements").MouseEventHandler<HTMLButtonElement> | null | undefined;
187
- 'on:select'?: import("svelte/elements").EventHandler<Event, HTMLButtonElement> | null | undefined;
188
- 'on:selectionchange'?: import("svelte/elements").EventHandler<Event, HTMLButtonElement> | null | undefined;
189
- 'on:selectstart'?: import("svelte/elements").EventHandler<Event, HTMLButtonElement> | null | undefined;
188
+ 'on:select'?: import("svelte/elements").EventHandler<Event<EventTarget>, HTMLButtonElement> | null | undefined;
189
+ 'on:selectionchange'?: import("svelte/elements").EventHandler<Event<EventTarget>, HTMLButtonElement> | null | undefined;
190
+ 'on:selectstart'?: import("svelte/elements").EventHandler<Event<EventTarget>, HTMLButtonElement> | null | undefined;
190
191
  'on:touchcancel'?: import("svelte/elements").TouchEventHandler<HTMLButtonElement> | null | undefined;
191
192
  'on:touchend'?: import("svelte/elements").TouchEventHandler<HTMLButtonElement> | null | undefined;
192
193
  'on:touchmove'?: import("svelte/elements").TouchEventHandler<HTMLButtonElement> | null | undefined;
@@ -217,11 +218,11 @@ declare const __propDef: {
217
218
  'on:introend'?: import("svelte/elements").EventHandler<CustomEvent<null>, HTMLButtonElement> | null | undefined;
218
219
  'on:message'?: import("svelte/elements").MessageEventHandler<HTMLButtonElement> | null | undefined;
219
220
  'on:messageerror'?: import("svelte/elements").MessageEventHandler<HTMLButtonElement> | null | undefined;
220
- 'on:visibilitychange'?: import("svelte/elements").EventHandler<Event, HTMLButtonElement> | null | undefined;
221
- 'on:cancel'?: import("svelte/elements").EventHandler<Event, HTMLButtonElement> | null | undefined;
222
- 'on:close'?: import("svelte/elements").EventHandler<Event, HTMLButtonElement> | null | undefined;
223
- 'on:fullscreenchange'?: import("svelte/elements").EventHandler<Event, HTMLButtonElement> | null | undefined;
224
- 'on:fullscreenerror'?: import("svelte/elements").EventHandler<Event, HTMLButtonElement> | null | undefined;
221
+ 'on:visibilitychange'?: import("svelte/elements").EventHandler<Event<EventTarget>, HTMLButtonElement> | null | undefined;
222
+ 'on:cancel'?: import("svelte/elements").EventHandler<Event<EventTarget>, HTMLButtonElement> | null | undefined;
223
+ 'on:close'?: import("svelte/elements").EventHandler<Event<EventTarget>, HTMLButtonElement> | null | undefined;
224
+ 'on:fullscreenchange'?: import("svelte/elements").EventHandler<Event<EventTarget>, HTMLButtonElement> | null | undefined;
225
+ 'on:fullscreenerror'?: import("svelte/elements").EventHandler<Event<EventTarget>, HTMLButtonElement> | null | undefined;
225
226
  sessionInit?: XRSessionInit & {
226
227
  domOverlay?: {
227
228
  root: HTMLElement;
@@ -4,76 +4,33 @@
4
4
  <script
5
5
 
6
6
  context="module"
7
- >import { XRControllerModelFactory } from "three/examples/jsm/webxr/XRControllerModelFactory";
8
- import { onDestroy } from "svelte";
9
- import { T, createRawEventDispatcher, useThrelte } from "@threlte/core";
10
- import { gaze, left as leftStore, right as rightStore } from "../hooks/useController";
11
- import { isHandTracking, pointerState, teleportState } from "../internal/stores";
12
- import { useHandTrackingState } from "../internal/useHandTrackingState";
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";
13
11
  import PointerCursor from "./internal/PointerCursor.svelte";
14
12
  import ShortRay from "./internal/ShortRay.svelte";
15
13
  import ScenePortal from "./internal/ScenePortal.svelte";
16
14
  import TeleportCursor from "./internal/TeleportCursor.svelte";
17
15
  import TeleportRay from "./internal/TeleportRay.svelte";
18
- const factory = new XRControllerModelFactory();
19
16
  const stores = {
20
17
  left: leftStore,
21
- right: rightStore,
22
- none: gaze
18
+ right: rightStore
23
19
  };
24
- const events = [
25
- "select",
26
- "selectstart",
27
- "selectend",
28
- "squeeze",
29
- "squeezeend",
30
- "squeezestart"
31
- ];
32
- const eventMap = /* @__PURE__ */ new WeakMap();
33
20
  </script>
34
21
 
35
22
  <script>export let left = void 0;
36
23
  export let right = void 0;
37
24
  export let hand = void 0;
38
- $:
39
- handedness = left ? "left" : right ? "right" : hand;
40
25
  const dispatch = createRawEventDispatcher();
41
- const { xr } = useThrelte().renderer;
42
- const handTrackingNow = useHandTrackingState();
43
- const handleEvent = (event) => {
44
- if (!handTrackingNow()) {
45
- dispatch(event.type, event);
46
- }
47
- };
48
- const handleConnected = (event) => {
49
- const targetData = eventMap.get(event.target);
50
- if (event.data.handedness !== handedness || !targetData)
51
- return;
52
- stores[handedness].set({ ...targetData, inputSource: event.data });
53
- if (!handTrackingNow()) {
54
- dispatch("connected", event);
55
- }
56
- events.forEach((name) => event.target.addEventListener(name, handleEvent));
57
- };
58
- const handleDisconnected = (event) => {
59
- if (event.data.handedness !== handedness)
60
- return;
61
- stores[handedness].set(void 0);
62
- if (!$isHandTracking) {
63
- dispatch("disconnected", event);
64
- }
65
- events.forEach((name) => event.target.removeEventListener(name, handleEvent));
66
- };
67
- for (const index of [0, 1]) {
68
- const targetRay2 = xr.getController(index);
69
- const grip2 = xr.getControllerGrip(index);
70
- const model2 = factory.createControllerModel(grip2);
71
- eventMap.set(targetRay2, { targetRay: targetRay2, model: model2, grip: grip2 });
72
- targetRay2.addEventListener("connected", handleConnected);
73
- targetRay2.addEventListener("disconnected", handleDisconnected);
74
- }
26
+ const handedness = writable(left ? "left" : right ? "right" : hand);
27
+ $:
28
+ handedness.set(left ? "left" : right ? "right" : hand);
29
+ controllerDispatchers[$handedness].set(dispatch);
30
+ $:
31
+ controllerDispatchers[$handedness].set(dispatch);
75
32
  $:
76
- store = stores[handedness];
33
+ store = stores[$handedness];
77
34
  $:
78
35
  grip = $store?.grip;
79
36
  $:
@@ -81,27 +38,14 @@ $:
81
38
  $:
82
39
  model = $store?.model;
83
40
  $:
84
- hasPointerControls = $pointerState[handedness].enabled;
41
+ hasPointerControls = $pointerState[$handedness].enabled;
85
42
  $:
86
- hasTeleportControls = $teleportState[handedness].enabled;
87
- onDestroy(() => {
88
- for (const index of [0, 1]) {
89
- const controller2 = xr.getController(index);
90
- controller2.removeEventListener("connected", handleConnected);
91
- controller2.removeEventListener("disconnected", handleDisconnected);
92
- }
93
- const controller = $store?.targetRay;
94
- events.forEach((name) => controller?.removeEventListener(name, handleEvent));
95
- store.set(void 0);
96
- });
43
+ hasTeleportControls = $teleportState[$handedness].enabled;
97
44
  </script>
98
45
 
99
46
  {#if !$isHandTracking}
100
47
  {#if grip}
101
- <T
102
- is={grip}
103
- name="XR controller grip {handedness}"
104
- >
48
+ <T is={grip}>
105
49
  <slot>
106
50
  <T is={model} />
107
51
  </slot>
@@ -111,19 +55,16 @@ onDestroy(() => {
111
55
  {/if}
112
56
 
113
57
  {#if targetRay}
114
- <T
115
- is={targetRay}
116
- name="XR controller {handedness}"
117
- >
58
+ <T is={targetRay}>
118
59
  <slot name="target-ray" />
119
60
 
120
61
  {#if hasPointerControls || hasTeleportControls}
121
62
  {#if $$slots['pointer-ray']}
122
- <ShortRay {handedness}>
63
+ <ShortRay handedness={$handedness}>
123
64
  <slot name="pointer-ray" />
124
65
  </ShortRay>
125
66
  {:else}
126
- <ShortRay {handedness} />
67
+ <ShortRay handedness={$handedness} />
127
68
  {/if}
128
69
  {/if}
129
70
  </T>
@@ -133,11 +74,11 @@ onDestroy(() => {
133
74
  <ScenePortal>
134
75
  {#if hasPointerControls}
135
76
  {#if $$slots['pointer-cursor']}
136
- <PointerCursor {handedness}>
77
+ <PointerCursor handedness={$handedness}>
137
78
  <slot name="pointer-cursor" />
138
79
  </PointerCursor>
139
80
  {:else}
140
- <PointerCursor {handedness} />
81
+ <PointerCursor handedness={$handedness} />
141
82
  {/if}
142
83
  {/if}
143
84
 
@@ -145,23 +86,23 @@ onDestroy(() => {
145
86
  {#if $$slots['teleport-ray']}
146
87
  <TeleportRay
147
88
  {targetRay}
148
- {handedness}
89
+ handedness={$handedness}
149
90
  >
150
91
  <slot name="teleport-ray" />
151
92
  </TeleportRay>
152
93
  {:else}
153
94
  <TeleportRay
154
95
  {targetRay}
155
- {handedness}
96
+ handedness={$handedness}
156
97
  />
157
98
  {/if}
158
99
 
159
100
  {#if $$slots['teleport-ray']}
160
- <TeleportCursor {handedness}>
101
+ <TeleportCursor handedness={$handedness}>
161
102
  <slot name="teleport-cursor" />
162
103
  </TeleportCursor>
163
104
  {:else}
164
- <TeleportCursor {handedness} />
105
+ <TeleportCursor handedness={$handedness} />
165
106
  {/if}
166
107
  {/if}
167
108
  </ScenePortal>
@@ -1,50 +1,26 @@
1
- <script context='module'>import { onDestroy } from "svelte";
2
- import { XRHandModelFactory } from "three/examples/jsm/webxr/XRHandModelFactory";
1
+ <script context='module'>import { Group } from "three";
3
2
  import { T, useThrelte, createRawEventDispatcher, useFrame } from "@threlte/core";
4
- import { isHandTracking } from "../internal/stores";
5
- import { useHandTrackingState } from "../internal/useHandTrackingState";
3
+ import { isHandTracking, handDispatchers } from "../internal/stores";
6
4
  import { left as leftStore, right as rightStore } from "../hooks/useHand";
7
- const factory = new XRHandModelFactory();
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
- <script>import ScenePortal from "./internal/ScenePortal.svelte";
16
- export let left = void 0;
13
+ <script>export let left = void 0;
17
14
  export let right = void 0;
18
15
  export let hand = void 0;
19
- const handTrackingNow = useHandTrackingState();
20
16
  const dispatch = createRawEventDispatcher();
21
17
  const { xr } = useThrelte().renderer;
22
18
  const space = xr.getReferenceSpace();
19
+ const handedness = writable(left ? "left" : right ? "right" : hand);
23
20
  $:
24
- handedness = left ? "left" : right ? "right" : hand;
25
- const handleConnected = (event) => {
26
- if (event.data.handedness !== handedness)
27
- return;
28
- stores[handedness].set({ ...eventMap.get(event.target), inputSource: event.data.hand });
29
- if (handTrackingNow()) {
30
- dispatch("connected", event);
31
- }
32
- event.target.addEventListener("pinchstart", handlePinchEvent);
33
- event.target.addEventListener("pinchend", handlePinchEvent);
34
- };
35
- const handleDisconnected = (event) => {
36
- if (event.data.handedness !== handedness)
37
- return;
38
- stores[handedness].set(void 0);
39
- if ($isHandTracking) {
40
- dispatch("disconnected", event);
41
- }
42
- event.target.removeEventListener("pinchstart", handlePinchEvent);
43
- event.target.removeEventListener("pinchend", handlePinchEvent);
44
- };
45
- const handlePinchEvent = (event) => {
46
- dispatch(event.type, event);
47
- };
21
+ handedness.set(left ? "left" : right ? "right" : hand);
22
+ $:
23
+ handDispatchers[$handedness].set(dispatch);
48
24
  let children;
49
25
  const { start, stop } = useFrame(() => {
50
26
  const frame = xr.getFrame();
@@ -59,51 +35,38 @@ const { start, stop } = useFrame(() => {
59
35
  children.quaternion.set(orientation.x, orientation.y, orientation.z, orientation.w);
60
36
  }, { autostart: false });
61
37
  $:
62
- if (($$slots.wrist || $$slots.default) && inputSource) {
38
+ if ($isHandTracking && ($$slots.wrist || $$slots.default) && inputSource) {
63
39
  start();
64
40
  } else {
65
41
  stop();
66
42
  }
67
43
  $:
68
- store = stores[handedness];
44
+ store = stores[$handedness];
69
45
  $:
70
46
  inputSource = $store?.inputSource;
71
47
  $:
72
48
  model = $store?.model;
73
- for (const index of [0, 1]) {
74
- const hand2 = xr.getHand(index);
75
- const model2 = factory.createHandModel(hand2, "mesh");
76
- eventMap.set(hand2, { hand: hand2, model: model2 });
77
- hand2.addEventListener("connected", handleConnected);
78
- hand2.addEventListener("disconnected", handleDisconnected);
79
- }
80
- onDestroy(() => {
81
- for (const index of [0, 1]) {
82
- const hand3 = xr.getHand(index);
83
- hand3.removeEventListener("connected", handleConnected);
84
- hand3.removeEventListener("disconnected", handleDisconnected);
85
- }
86
- const hand2 = stores[handedness].current?.hand;
87
- hand2?.removeEventListener("pinchstart", handlePinchEvent);
88
- hand2?.removeEventListener("pinchend", handlePinchEvent);
89
- stores[handedness].set(void 0);
90
- });
91
49
  </script>
92
50
 
93
- {#if $store?.hand}
94
- <T
95
- is={$store.hand}
96
- name='XR hand {handedness}'
97
- >
51
+ {#if $store?.hand && $isHandTracking}
52
+ <T is={$store.hand}>
98
53
  {#if $$slots.default === undefined}
99
54
  <T is={model} />
100
55
  {/if}
101
56
  </T>
57
+
58
+ {#if $$slots['target-ray'] !== undefined}
59
+ <T is={$store.targetRay}>
60
+ <slot name='target-ray' />
61
+ </T>
62
+ {/if}
102
63
  {/if}
103
64
 
104
- <ScenePortal>
105
- <T.Group bind:ref={children}>
106
- <slot name='wrist' />
107
- <slot />
108
- </T.Group>
109
- </ScenePortal>
65
+ {#if $isHandTracking}
66
+ <ScenePortal>
67
+ <T.Group bind:ref={children}>
68
+ <slot name='wrist' />
69
+ <slot />
70
+ </T.Group>
71
+ </ScenePortal>
72
+ {/if}
@@ -18,6 +18,7 @@ declare const __propDef: {
18
18
  right?: undefined;
19
19
  };
20
20
  slots: {
21
+ 'target-ray': {};
21
22
  wrist: {};
22
23
  default: {};
23
24
  };
@@ -1,3 +1,4 @@
1
+ /// <reference types="bun-types" />
1
2
  import { SvelteComponent } from "svelte";
2
3
  declare const __propDef: {
3
4
  props: Record<string, never>;
@@ -1,3 +1,4 @@
1
+ /// <reference types="bun-types" />
1
2
  import { SvelteComponent } from "svelte";
2
3
  declare const __propDef: {
3
4
  props: {
@@ -55,12 +56,12 @@ declare const __propDef: {
55
56
  results?: number | null | undefined;
56
57
  security?: string | null | undefined;
57
58
  unselectable?: "on" | "off" | null | undefined;
58
- inputmode?: "search" | "none" | "text" | "tel" | "url" | "email" | "numeric" | "decimal" | null | undefined;
59
+ inputmode?: "url" | "search" | "none" | "text" | "tel" | "email" | "numeric" | "decimal" | null | undefined;
59
60
  is?: string | null | undefined;
60
61
  'bind:innerHTML'?: string | null | undefined;
61
62
  'bind:textContent'?: string | null | undefined;
62
63
  'bind:innerText'?: string | null | undefined;
63
- 'bind:contentRect'?: DOMRectReadOnly | null | undefined;
64
+ 'bind:contentRect'?: any;
64
65
  'bind:contentBoxSize'?: ResizeObserverSize[] | null | undefined;
65
66
  'bind:borderBoxSize'?: ResizeObserverSize[] | null | undefined;
66
67
  'bind:devicePixelContentBoxSize'?: ResizeObserverSize[] | null | undefined;
@@ -133,37 +134,37 @@ declare const __propDef: {
133
134
  'on:input'?: import("svelte/elements").FormEventHandler<HTMLButtonElement> | null | undefined;
134
135
  'on:reset'?: import("svelte/elements").FormEventHandler<HTMLButtonElement> | null | undefined;
135
136
  'on:submit'?: import("svelte/elements").EventHandler<SubmitEvent, HTMLButtonElement> | null | undefined;
136
- 'on:invalid'?: import("svelte/elements").EventHandler<Event, HTMLButtonElement> | null | undefined;
137
+ 'on:invalid'?: import("svelte/elements").EventHandler<Event<EventTarget>, HTMLButtonElement> | null | undefined;
137
138
  'on:formdata'?: import("svelte/elements").EventHandler<FormDataEvent, HTMLButtonElement> | null | undefined;
138
- 'on:load'?: import("svelte/elements").EventHandler<Event, Element> | null | undefined;
139
- 'on:error'?: import("svelte/elements").EventHandler<Event, Element> | null | undefined;
140
- 'on:toggle'?: import("svelte/elements").EventHandler<Event, HTMLButtonElement> | null | undefined;
139
+ 'on:load'?: import("svelte/elements").EventHandler<Event<EventTarget>, Element> | null | undefined;
140
+ 'on:error'?: import("svelte/elements").EventHandler<Event<EventTarget>, Element> | null | undefined;
141
+ 'on:toggle'?: import("svelte/elements").EventHandler<Event<EventTarget>, HTMLButtonElement> | null | undefined;
141
142
  'on:keydown'?: import("svelte/elements").KeyboardEventHandler<HTMLButtonElement> | null | undefined;
142
143
  'on:keypress'?: import("svelte/elements").KeyboardEventHandler<HTMLButtonElement> | null | undefined;
143
144
  'on:keyup'?: import("svelte/elements").KeyboardEventHandler<HTMLButtonElement> | null | undefined;
144
- 'on:abort'?: import("svelte/elements").EventHandler<Event, HTMLButtonElement> | null | undefined;
145
- 'on:canplay'?: import("svelte/elements").EventHandler<Event, HTMLButtonElement> | null | undefined;
146
- 'on:canplaythrough'?: import("svelte/elements").EventHandler<Event, HTMLButtonElement> | null | undefined;
147
- 'on:cuechange'?: import("svelte/elements").EventHandler<Event, HTMLButtonElement> | null | undefined;
148
- 'on:durationchange'?: import("svelte/elements").EventHandler<Event, HTMLButtonElement> | null | undefined;
149
- 'on:emptied'?: import("svelte/elements").EventHandler<Event, HTMLButtonElement> | null | undefined;
150
- 'on:encrypted'?: import("svelte/elements").EventHandler<Event, HTMLButtonElement> | null | undefined;
151
- 'on:ended'?: import("svelte/elements").EventHandler<Event, HTMLButtonElement> | null | undefined;
152
- 'on:loadeddata'?: import("svelte/elements").EventHandler<Event, HTMLButtonElement> | null | undefined;
153
- 'on:loadedmetadata'?: import("svelte/elements").EventHandler<Event, HTMLButtonElement> | null | undefined;
154
- 'on:loadstart'?: import("svelte/elements").EventHandler<Event, HTMLButtonElement> | null | undefined;
155
- 'on:pause'?: import("svelte/elements").EventHandler<Event, HTMLButtonElement> | null | undefined;
156
- 'on:play'?: import("svelte/elements").EventHandler<Event, HTMLButtonElement> | null | undefined;
157
- 'on:playing'?: import("svelte/elements").EventHandler<Event, HTMLButtonElement> | null | undefined;
158
- 'on:progress'?: import("svelte/elements").EventHandler<Event, HTMLButtonElement> | null | undefined;
159
- 'on:ratechange'?: import("svelte/elements").EventHandler<Event, HTMLButtonElement> | null | undefined;
160
- 'on:seeked'?: import("svelte/elements").EventHandler<Event, HTMLButtonElement> | null | undefined;
161
- 'on:seeking'?: import("svelte/elements").EventHandler<Event, HTMLButtonElement> | null | undefined;
162
- 'on:stalled'?: import("svelte/elements").EventHandler<Event, HTMLButtonElement> | null | undefined;
163
- 'on:suspend'?: import("svelte/elements").EventHandler<Event, HTMLButtonElement> | null | undefined;
164
- 'on:timeupdate'?: import("svelte/elements").EventHandler<Event, HTMLButtonElement> | null | undefined;
165
- 'on:volumechange'?: import("svelte/elements").EventHandler<Event, HTMLButtonElement> | null | undefined;
166
- 'on:waiting'?: import("svelte/elements").EventHandler<Event, HTMLButtonElement> | null | undefined;
145
+ 'on:abort'?: import("svelte/elements").EventHandler<Event<EventTarget>, HTMLButtonElement> | null | undefined;
146
+ 'on:canplay'?: import("svelte/elements").EventHandler<Event<EventTarget>, HTMLButtonElement> | null | undefined;
147
+ 'on:canplaythrough'?: import("svelte/elements").EventHandler<Event<EventTarget>, HTMLButtonElement> | null | undefined;
148
+ 'on:cuechange'?: import("svelte/elements").EventHandler<Event<EventTarget>, HTMLButtonElement> | null | undefined;
149
+ 'on:durationchange'?: import("svelte/elements").EventHandler<Event<EventTarget>, HTMLButtonElement> | null | undefined;
150
+ 'on:emptied'?: import("svelte/elements").EventHandler<Event<EventTarget>, HTMLButtonElement> | null | undefined;
151
+ 'on:encrypted'?: import("svelte/elements").EventHandler<Event<EventTarget>, HTMLButtonElement> | null | undefined;
152
+ 'on:ended'?: import("svelte/elements").EventHandler<Event<EventTarget>, HTMLButtonElement> | null | undefined;
153
+ 'on:loadeddata'?: import("svelte/elements").EventHandler<Event<EventTarget>, HTMLButtonElement> | null | undefined;
154
+ 'on:loadedmetadata'?: import("svelte/elements").EventHandler<Event<EventTarget>, HTMLButtonElement> | null | undefined;
155
+ 'on:loadstart'?: import("svelte/elements").EventHandler<Event<EventTarget>, HTMLButtonElement> | null | undefined;
156
+ 'on:pause'?: import("svelte/elements").EventHandler<Event<EventTarget>, HTMLButtonElement> | null | undefined;
157
+ 'on:play'?: import("svelte/elements").EventHandler<Event<EventTarget>, HTMLButtonElement> | null | undefined;
158
+ 'on:playing'?: import("svelte/elements").EventHandler<Event<EventTarget>, HTMLButtonElement> | null | undefined;
159
+ 'on:progress'?: import("svelte/elements").EventHandler<Event<EventTarget>, HTMLButtonElement> | null | undefined;
160
+ 'on:ratechange'?: import("svelte/elements").EventHandler<Event<EventTarget>, HTMLButtonElement> | null | undefined;
161
+ 'on:seeked'?: import("svelte/elements").EventHandler<Event<EventTarget>, HTMLButtonElement> | null | undefined;
162
+ 'on:seeking'?: import("svelte/elements").EventHandler<Event<EventTarget>, HTMLButtonElement> | null | undefined;
163
+ 'on:stalled'?: import("svelte/elements").EventHandler<Event<EventTarget>, HTMLButtonElement> | null | undefined;
164
+ 'on:suspend'?: import("svelte/elements").EventHandler<Event<EventTarget>, HTMLButtonElement> | null | undefined;
165
+ 'on:timeupdate'?: import("svelte/elements").EventHandler<Event<EventTarget>, HTMLButtonElement> | null | undefined;
166
+ 'on:volumechange'?: import("svelte/elements").EventHandler<Event<EventTarget>, HTMLButtonElement> | null | undefined;
167
+ 'on:waiting'?: import("svelte/elements").EventHandler<Event<EventTarget>, HTMLButtonElement> | null | undefined;
167
168
  'on:auxclick'?: import("svelte/elements").MouseEventHandler<HTMLButtonElement> | null | undefined;
168
169
  'on:click'?: import("svelte/elements").MouseEventHandler<HTMLButtonElement> | null | undefined;
169
170
  'on:contextmenu'?: import("svelte/elements").MouseEventHandler<HTMLButtonElement> | null | undefined;
@@ -183,9 +184,9 @@ declare const __propDef: {
183
184
  'on:mouseout'?: import("svelte/elements").MouseEventHandler<HTMLButtonElement> | null | undefined;
184
185
  'on:mouseover'?: import("svelte/elements").MouseEventHandler<HTMLButtonElement> | null | undefined;
185
186
  'on:mouseup'?: import("svelte/elements").MouseEventHandler<HTMLButtonElement> | null | undefined;
186
- 'on:select'?: import("svelte/elements").EventHandler<Event, HTMLButtonElement> | null | undefined;
187
- 'on:selectionchange'?: import("svelte/elements").EventHandler<Event, HTMLButtonElement> | null | undefined;
188
- 'on:selectstart'?: import("svelte/elements").EventHandler<Event, HTMLButtonElement> | null | undefined;
187
+ 'on:select'?: import("svelte/elements").EventHandler<Event<EventTarget>, HTMLButtonElement> | null | undefined;
188
+ 'on:selectionchange'?: import("svelte/elements").EventHandler<Event<EventTarget>, HTMLButtonElement> | null | undefined;
189
+ 'on:selectstart'?: import("svelte/elements").EventHandler<Event<EventTarget>, HTMLButtonElement> | null | undefined;
189
190
  'on:touchcancel'?: import("svelte/elements").TouchEventHandler<HTMLButtonElement> | null | undefined;
190
191
  'on:touchend'?: import("svelte/elements").TouchEventHandler<HTMLButtonElement> | null | undefined;
191
192
  'on:touchmove'?: import("svelte/elements").TouchEventHandler<HTMLButtonElement> | null | undefined;
@@ -216,11 +217,11 @@ declare const __propDef: {
216
217
  'on:introend'?: import("svelte/elements").EventHandler<CustomEvent<null>, HTMLButtonElement> | null | undefined;
217
218
  'on:message'?: import("svelte/elements").MessageEventHandler<HTMLButtonElement> | null | undefined;
218
219
  'on:messageerror'?: import("svelte/elements").MessageEventHandler<HTMLButtonElement> | null | undefined;
219
- 'on:visibilitychange'?: import("svelte/elements").EventHandler<Event, HTMLButtonElement> | null | undefined;
220
- 'on:cancel'?: import("svelte/elements").EventHandler<Event, HTMLButtonElement> | null | undefined;
221
- 'on:close'?: import("svelte/elements").EventHandler<Event, HTMLButtonElement> | null | undefined;
222
- 'on:fullscreenchange'?: import("svelte/elements").EventHandler<Event, HTMLButtonElement> | null | undefined;
223
- 'on:fullscreenerror'?: import("svelte/elements").EventHandler<Event, HTMLButtonElement> | null | undefined;
220
+ 'on:visibilitychange'?: import("svelte/elements").EventHandler<Event<EventTarget>, HTMLButtonElement> | null | undefined;
221
+ 'on:cancel'?: import("svelte/elements").EventHandler<Event<EventTarget>, HTMLButtonElement> | null | undefined;
222
+ 'on:close'?: import("svelte/elements").EventHandler<Event<EventTarget>, HTMLButtonElement> | null | undefined;
223
+ 'on:fullscreenchange'?: import("svelte/elements").EventHandler<Event<EventTarget>, HTMLButtonElement> | null | undefined;
224
+ 'on:fullscreenerror'?: import("svelte/elements").EventHandler<Event<EventTarget>, HTMLButtonElement> | null | undefined;
224
225
  };
225
226
  events: {
226
227
  click: CustomEvent<{