@threlte/xr 1.2.0 → 1.4.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/Controller.svelte +1 -1
- package/dist/components/Hand.svelte +7 -12
- package/dist/components/internal/PointerCursor.svelte +2 -5
- package/dist/components/internal/TeleportCursor.svelte +2 -4
- package/dist/components/internal/TeleportRay.svelte +2 -11
- package/dist/hooks/useHandJoint.svelte.js +2 -3
- package/dist/hooks/useHitTest.svelte.js +2 -10
- package/dist/internal/setupHeadset.svelte.js +6 -16
- package/dist/plugins/pointerControls/index.js +3 -3
- package/dist/plugins/pointerControls/setup.svelte.js +2 -2
- package/dist/plugins/teleportControls/index.js +3 -3
- package/package.json +6 -4
|
@@ -72,7 +72,7 @@
|
|
|
72
72
|
|
|
73
73
|
const { scene } = useThrelte()
|
|
74
74
|
|
|
75
|
-
const handedness = $derived<'left' | 'right'>(left ? 'left' : right ? 'right' : hand ?? 'left')
|
|
75
|
+
const handedness = $derived<'left' | 'right'>(left ? 'left' : right ? 'right' : (hand ?? 'left'))
|
|
76
76
|
|
|
77
77
|
$effect.pre(() => {
|
|
78
78
|
controllerEvents[handedness] = {
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
|
|
48
48
|
const { scene, renderer, scheduler, renderStage } = useThrelte()
|
|
49
49
|
|
|
50
|
-
const handedness = $derived<'left' | 'right'>(left ? 'left' : right ? 'right' : hand ?? 'left')
|
|
50
|
+
const handedness = $derived<'left' | 'right'>(left ? 'left' : right ? 'right' : (hand ?? 'left'))
|
|
51
51
|
|
|
52
52
|
$effect.pre(() => {
|
|
53
53
|
handEvents[handedness] = {
|
|
@@ -72,7 +72,7 @@
|
|
|
72
72
|
* @todo(mp) investigate why this is happening and see if there's
|
|
73
73
|
* a way to just parent to the hand to avoid this.
|
|
74
74
|
*/
|
|
75
|
-
|
|
75
|
+
useTask(
|
|
76
76
|
() => {
|
|
77
77
|
const frame = renderer.xr.getFrame()
|
|
78
78
|
const space = renderer.xr.getReferenceSpace()
|
|
@@ -90,19 +90,14 @@
|
|
|
90
90
|
group.quaternion.set(orientation.x, orientation.y, orientation.z, orientation.w)
|
|
91
91
|
},
|
|
92
92
|
{
|
|
93
|
-
|
|
94
|
-
|
|
93
|
+
stage: scheduler.createStage(Symbol('xr-hand-stage'), { before: renderStage }),
|
|
94
|
+
running: () =>
|
|
95
|
+
isHandTracking.current &&
|
|
96
|
+
(wrist !== undefined || children !== undefined) &&
|
|
97
|
+
inputSource !== undefined
|
|
95
98
|
}
|
|
96
99
|
)
|
|
97
100
|
|
|
98
|
-
$effect.pre(() => {
|
|
99
|
-
if (isHandTracking.current && (wrist !== undefined || children !== undefined) && inputSource) {
|
|
100
|
-
start()
|
|
101
|
-
} else {
|
|
102
|
-
stop()
|
|
103
|
-
}
|
|
104
|
-
})
|
|
105
|
-
|
|
106
101
|
const xrHand = $derived(hands[handedness])
|
|
107
102
|
const inputSource = $derived(xrHand?.inputSource)
|
|
108
103
|
const model = $derived(xrHand?.model)
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
|
|
29
29
|
const ref = new Group()
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
useTask(
|
|
32
32
|
() => {
|
|
33
33
|
if (intersection === undefined) {
|
|
34
34
|
return
|
|
@@ -46,16 +46,13 @@
|
|
|
46
46
|
ref.lookAt(vec3.addVectors(point, worldNormal))
|
|
47
47
|
},
|
|
48
48
|
{
|
|
49
|
-
|
|
49
|
+
running: () => hovering && intersection !== undefined
|
|
50
50
|
}
|
|
51
51
|
)
|
|
52
52
|
|
|
53
53
|
$effect.pre(() => {
|
|
54
54
|
if (hovering && intersection) {
|
|
55
55
|
ref.position.copy(intersection.point)
|
|
56
|
-
start()
|
|
57
|
-
} else {
|
|
58
|
-
stop()
|
|
59
56
|
}
|
|
60
57
|
})
|
|
61
58
|
</script>
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
|
|
29
29
|
const ref = new Group()
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
useTask(
|
|
32
32
|
() => {
|
|
33
33
|
if (intersection === undefined) {
|
|
34
34
|
return
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
}
|
|
45
45
|
},
|
|
46
46
|
{
|
|
47
|
-
|
|
47
|
+
running: () => intersection !== undefined
|
|
48
48
|
}
|
|
49
49
|
)
|
|
50
50
|
|
|
@@ -53,11 +53,9 @@
|
|
|
53
53
|
$effect.pre(() => {
|
|
54
54
|
if (intersection === undefined) {
|
|
55
55
|
size.set(0.1)
|
|
56
|
-
stop()
|
|
57
56
|
} else {
|
|
58
57
|
size.set(1)
|
|
59
58
|
ref.position.copy(intersection.point)
|
|
60
|
-
start()
|
|
61
59
|
}
|
|
62
60
|
})
|
|
63
61
|
</script>
|
|
@@ -66,21 +66,12 @@
|
|
|
66
66
|
lineGeometry.setPositions(positions)
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
-
|
|
69
|
+
useTask(
|
|
70
70
|
() => {
|
|
71
71
|
setCurvePoints()
|
|
72
72
|
},
|
|
73
|
-
{
|
|
73
|
+
{ running: () => intersection !== undefined }
|
|
74
74
|
)
|
|
75
|
-
|
|
76
|
-
$effect.pre(() => {
|
|
77
|
-
if (intersection === undefined) {
|
|
78
|
-
stop()
|
|
79
|
-
} else {
|
|
80
|
-
setCurvePoints(1)
|
|
81
|
-
start()
|
|
82
|
-
}
|
|
83
|
-
})
|
|
84
75
|
</script>
|
|
85
76
|
|
|
86
77
|
{#if children}
|
|
@@ -8,14 +8,13 @@ export const useHandJoint = (handedness, joint) => {
|
|
|
8
8
|
const { invalidate } = useThrelte();
|
|
9
9
|
const xrhand = $derived(hands[handedness]);
|
|
10
10
|
let jointSpace = $state.raw();
|
|
11
|
-
|
|
11
|
+
useTask(() => {
|
|
12
12
|
const space = xrhand?.hand.joints[joint];
|
|
13
13
|
// The joint radius is a good indicator that the joint is ready
|
|
14
14
|
if (space?.jointRadius !== undefined) {
|
|
15
15
|
jointSpace = space;
|
|
16
16
|
invalidate();
|
|
17
|
-
stop();
|
|
18
17
|
}
|
|
19
|
-
}, {
|
|
18
|
+
}, { running: () => jointSpace === undefined });
|
|
20
19
|
return toCurrentReadable(() => jointSpace);
|
|
21
20
|
};
|
|
@@ -37,7 +37,7 @@ export const useHitTest = (hitTestCallback, options = {}) => {
|
|
|
37
37
|
getHitTestSource(controller?.inputSource.targetRaySpace);
|
|
38
38
|
});
|
|
39
39
|
}
|
|
40
|
-
|
|
40
|
+
useTask(() => {
|
|
41
41
|
const referenceSpace = xr.getReferenceSpace();
|
|
42
42
|
if (referenceSpace === null || hitTestSource === undefined) {
|
|
43
43
|
return hitTestCallback(hitMatrix, undefined);
|
|
@@ -49,19 +49,11 @@ export const useHitTest = (hitTestCallback, options = {}) => {
|
|
|
49
49
|
}
|
|
50
50
|
hitMatrix.fromArray(pose.transform.matrix);
|
|
51
51
|
hitTestCallback(hitMatrix, hit);
|
|
52
|
-
}, {
|
|
52
|
+
}, { running: () => isPresenting.current && hitTestSource !== undefined });
|
|
53
53
|
$effect.pre(() => {
|
|
54
|
-
if (!isPresenting.current) {
|
|
55
|
-
stop();
|
|
56
|
-
return;
|
|
57
|
-
}
|
|
58
54
|
if (hitTestSource === undefined) {
|
|
59
|
-
stop();
|
|
60
55
|
// Execute callback one last time to inform consumers of no hits.
|
|
61
56
|
hitTestCallback(hitMatrix, undefined);
|
|
62
57
|
}
|
|
63
|
-
else {
|
|
64
|
-
start();
|
|
65
|
-
}
|
|
66
58
|
});
|
|
67
59
|
};
|
|
@@ -6,7 +6,7 @@ export const setupHeadset = () => {
|
|
|
6
6
|
const { renderer, camera, scheduler, renderStage } = useThrelte();
|
|
7
7
|
const { xr } = renderer;
|
|
8
8
|
const stage = scheduler.createStage(Symbol('xr-headset-stage'), { before: renderStage });
|
|
9
|
-
|
|
9
|
+
useTask(() => {
|
|
10
10
|
const space = xr.getReferenceSpace();
|
|
11
11
|
if (space === null)
|
|
12
12
|
return;
|
|
@@ -19,26 +19,16 @@ export const setupHeadset = () => {
|
|
|
19
19
|
headset.position.copy(position);
|
|
20
20
|
headset.quaternion.copy(orientation);
|
|
21
21
|
}, {
|
|
22
|
-
autoStart: false,
|
|
23
22
|
autoInvalidate: false,
|
|
24
|
-
stage
|
|
23
|
+
stage,
|
|
24
|
+
running: () => isPresenting.current
|
|
25
25
|
});
|
|
26
|
-
|
|
26
|
+
useTask(() => {
|
|
27
27
|
headset.position.copy(camera.current.position);
|
|
28
28
|
headset.quaternion.copy(camera.current.quaternion);
|
|
29
29
|
}, {
|
|
30
|
-
autoStart: false,
|
|
31
30
|
autoInvalidate: false,
|
|
32
|
-
stage
|
|
33
|
-
|
|
34
|
-
$effect.pre(() => {
|
|
35
|
-
if (isPresenting.current) {
|
|
36
|
-
immersiveFrame.start();
|
|
37
|
-
nonImmersiveFrame.stop();
|
|
38
|
-
}
|
|
39
|
-
else {
|
|
40
|
-
immersiveFrame.stop();
|
|
41
|
-
nonImmersiveFrame.start();
|
|
42
|
-
}
|
|
31
|
+
stage,
|
|
32
|
+
running: () => isPresenting.current === false
|
|
43
33
|
});
|
|
44
34
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Raycaster, Vector3 } from 'three';
|
|
2
|
-
import { currentWritable,
|
|
2
|
+
import { currentWritable, observe } from '@threlte/core';
|
|
3
3
|
import { defaultComputeFunction } from './compute.js';
|
|
4
4
|
import { injectPointerControlsPlugin } from './plugin.svelte.js';
|
|
5
5
|
import { setupPointerControls } from './setup.svelte.js';
|
|
@@ -34,11 +34,11 @@ export const pointerControls = (handedness, options) => {
|
|
|
34
34
|
setupPointerControls(context, ctx, options?.fixedStep);
|
|
35
35
|
}
|
|
36
36
|
const handContext = getHandContext(handedness);
|
|
37
|
-
|
|
37
|
+
observe.pre(() => [handContext.enabled], ([enabled]) => {
|
|
38
38
|
controlsCounter += enabled ? 1 : -1;
|
|
39
39
|
pointerState[handedness].enabled = controlsCounter > 0;
|
|
40
40
|
});
|
|
41
|
-
|
|
41
|
+
observe.pre(() => [handContext.pointerOverTarget], ([hovering]) => {
|
|
42
42
|
pointerState[handedness].hovering = hovering;
|
|
43
43
|
});
|
|
44
44
|
return {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Vector3 } from 'three';
|
|
2
|
-
import { observe
|
|
2
|
+
import { observe } from '@threlte/core';
|
|
3
3
|
import { getInternalContext } from './context.js';
|
|
4
4
|
import { controllers } from '../../hooks/useController.svelte.js';
|
|
5
5
|
import { useHand } from '../../hooks/useHand.svelte.js';
|
|
@@ -187,7 +187,7 @@ export const setupPointerControls = (context, handContext, fixedStep = 1 / 40) =
|
|
|
187
187
|
return;
|
|
188
188
|
}
|
|
189
189
|
});
|
|
190
|
-
|
|
190
|
+
observe.pre(() => [hand, handContext.enabled], ([input, enabled]) => {
|
|
191
191
|
if (input === undefined)
|
|
192
192
|
return;
|
|
193
193
|
const removeHandlers = () => {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { currentWritable,
|
|
1
|
+
import { currentWritable, observe } from '@threlte/core';
|
|
2
2
|
import { createTeleportContext, useTeleportControls, getHandContext } from './context.js';
|
|
3
3
|
import { injectTeleportControlsPlugin } from './plugin.svelte.js';
|
|
4
4
|
import { setHandContext } from './context.js';
|
|
@@ -24,11 +24,11 @@ export const teleportControls = (handedness, options) => {
|
|
|
24
24
|
setupTeleportControls(context, ctx, options?.fixedStep);
|
|
25
25
|
}
|
|
26
26
|
const handContext = getHandContext(handedness);
|
|
27
|
-
|
|
27
|
+
observe.pre(() => [handContext.enabled], ([enabled]) => {
|
|
28
28
|
controlsCounter += enabled ? 1 : -1;
|
|
29
29
|
teleportState[handedness].enabled = controlsCounter > 0;
|
|
30
30
|
});
|
|
31
|
-
|
|
31
|
+
observe.pre(() => [handContext.active], ([hovering]) => {
|
|
32
32
|
teleportState[handedness].hovering = hovering;
|
|
33
33
|
});
|
|
34
34
|
return {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@threlte/xr",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"author": "Micheal Parks <michealparks1989@gmail.com> (https://parks.lol)",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"description": "Tools to more easily create VR and AR experiences with Threlte",
|
|
@@ -17,8 +17,10 @@
|
|
|
17
17
|
"eslint-plugin-svelte": "^3.5.1",
|
|
18
18
|
"globals": "^16.1.0",
|
|
19
19
|
"postcss": "^8.4.38",
|
|
20
|
+
"prettier": "^3.8.1",
|
|
21
|
+
"prettier-plugin-svelte": "^3.5.1",
|
|
20
22
|
"publint": "^0.2.7",
|
|
21
|
-
"svelte": "5.
|
|
23
|
+
"svelte": "5.53.6",
|
|
22
24
|
"svelte-check": "^4.3.1",
|
|
23
25
|
"three": "^0.175.0",
|
|
24
26
|
"tslib": "^2.6.2",
|
|
@@ -26,7 +28,7 @@
|
|
|
26
28
|
"typescript-eslint": "^8.32.0",
|
|
27
29
|
"vite": "^7.1.4",
|
|
28
30
|
"vite-plugin-mkcert": "^1.17.5",
|
|
29
|
-
"@threlte/core": "8.
|
|
31
|
+
"@threlte/core": "8.5.0"
|
|
30
32
|
},
|
|
31
33
|
"peerDependencies": {
|
|
32
34
|
"svelte": ">=5",
|
|
@@ -46,7 +48,7 @@
|
|
|
46
48
|
"homepage": "https://threlte.xyz",
|
|
47
49
|
"repository": {
|
|
48
50
|
"type": "git",
|
|
49
|
-
"url": "https://github.com/threlte/threlte
|
|
51
|
+
"url": "https://github.com/threlte/threlte",
|
|
50
52
|
"directory": "packages/xr"
|
|
51
53
|
},
|
|
52
54
|
"bugs": {
|