UNPKG

@react-three/xr

Version:

VR/AR for react-three-fiber

83 lines (82 loc) 3.42 kB
import { jsx as _jsx } from "react/jsx-runtime"; import { createXRHitTestSource, requestXRHitTest } from '@pmndrs/xr'; import { useFrame } from '@react-three/fiber'; import { forwardRef, useCallback, useEffect, useImperativeHandle, useRef, useState } from 'react'; import { useStore } from 'zustand'; import { useXRStore } from './xr.js'; export { createXRHitTestSource, requestXRHitTest } from '@pmndrs/xr'; /** * Hook for creating a hit test source originating from the provided object or xrspace */ export function useXRHitTestSource(relativeTo, trackableType) { const [source, setState] = useState(); // eslint-disable-next-line react-hooks/rules-of-hooks useCreateXRHitTestSource(relativeTo, trackableType, setState); return source; } /** * Hook for setting up a continous hit test originating from the provided object or xrspace */ export function useXRHitTest(fn, relativeTo, trackableType) { const sourceRef = useRef(undefined); useCreateXRHitTestSource(relativeTo, trackableType, useCallback((source) => (sourceRef.current = source), [])); useFrame((_s, _d, frame) => { if (fn == null || frame == null || sourceRef.current == null) { return; } fn(frame.getHitTestResults(sourceRef.current.source), sourceRef.current.getWorldMatrix); }); } function useCreateXRHitTestSource(relativeTo, trackableType, onLoad) { const store = useXRStore(); const session = useStore(store, (s) => s.session); useEffect(() => { if (session == null) { return; } let storedResult; let cancelled = false; const relativeToResolved = relativeTo instanceof XRSpace || typeof relativeTo === 'string' ? relativeTo : relativeTo?.current; if (relativeToResolved == null) { return; } createXRHitTestSource(store, session, relativeToResolved, trackableType).then((result) => { if (cancelled) { return; } storedResult = result; onLoad(result); }); return () => { onLoad(undefined); cancelled = true; storedResult?.source.cancel(); }; }, [session, store, relativeTo, trackableType, onLoad]); } /** * Hook that returns a function to request a single hit test */ export function useXRRequestHitTest() { const store = useXRStore(); return useCallback((relativeTo, trackableType) => { const relativeToResolved = relativeTo instanceof XRSpace || typeof relativeTo === 'string' ? relativeTo : relativeTo.current; if (relativeToResolved == null) { return; } return requestXRHitTest(store, relativeToResolved, trackableType); }, [store]); } /** * Component for getting hit tests originating based on its position in the scene graph * * @param props ‎ * #### `space` - [XRSpaceType](https://developer.mozilla.org/en-US/docs/Web/API/XRSpace) | [XRReferenceSpaceType](https://developer.mozilla.org/en-US/docs/Web/API/XRReferenceSpace#reference_space_types) * @function */ export const XRHitTest = forwardRef(({ trackableType, onResults, space, ...rest }, ref) => { const internalRef = useRef(null); useImperativeHandle(ref, () => internalRef.current); useXRHitTest(onResults, space ?? internalRef, trackableType); return _jsx("group", { ...rest, ref: internalRef }); });