UNPKG

@threlte/xr

Version:

Tools to more easily create VR and AR experiences with Threlte

64 lines (63 loc) 2.56 kB
import { XRHandModelFactory } from 'three/examples/jsm/webxr/XRHandModelFactory.js'; import { useThrelte } from '@threlte/core'; import { onMount } from 'svelte'; import { left, right } from '../hooks/useHand'; import { useHandTrackingState } from './useHandTrackingState'; import { handEvents } from './stores'; export const setupHands = () => { const factory = new XRHandModelFactory(); const stores = { left, right }; const { xr } = useThrelte().renderer; const hasHands = useHandTrackingState(); const handSpaces = [xr.getHand(0), xr.getHand(1)]; const map = new Map(); handSpaces.forEach((handSpace, index) => { map.set(handSpace, { hand: handSpace, targetRay: xr.getController(index), model: factory.createHandModel(handSpace, 'mesh') }); }); onMount(() => { const dispatch = (event) => { if (!hasHands()) return; const handEvent = event; const handedness = 'handedness' in handEvent ? handEvent.handedness : handEvent.data.handedness; handEvents[handedness]?.current?.[`on${event.type}`]?.(event); }; function handleConnected(event) { const hand = this; const { model, targetRay } = map.get(this); const { data } = event; const { handedness, hand: inputSource } = data; stores[handedness].set({ hand, model, inputSource, targetRay }); dispatch(event); } const handleDisconnected = (event) => { dispatch(event); stores[event.data.handedness].set(undefined); }; for (const handSpace of handSpaces) { handSpace.addEventListener('connected', handleConnected); handSpace.addEventListener('disconnected', handleDisconnected); handSpace.addEventListener('pinchstart', dispatch); handSpace.addEventListener('pinchend', dispatch); } return () => { for (const handSpace of handSpaces) { handSpace.removeEventListener('connected', handleConnected); handSpace.removeEventListener('disconnected', handleDisconnected); handSpace.removeEventListener('pinchstart', dispatch); handSpace.removeEventListener('pinchend', dispatch); } stores.left.set(undefined); stores.right.set(undefined); }; }); };