@vincentt-xr/sdk 2.0.0-alpha.7 → 2.0.0-alpha.8
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/GROUNDING.md +1109 -13
- package/dist/{DebuggerUI-BjOMr8q_.js → DebuggerUI-C-ldiozL.js} +1 -1
- package/dist/{DebuggerUI-B6bP6P9r.cjs → DebuggerUI-CWX5EtQv.cjs} +1 -1
- package/dist/FaceMeshRenderer-BEEXZwS6.cjs +158 -0
- package/dist/FaceMeshRenderer-UuH5sTXG.js +1322 -0
- package/dist/FaceRetouch-C7h7x9kd.js +683 -0
- package/dist/FaceRetouch-DqftT26Y.cjs +134 -0
- package/dist/GLTFLoader-C5q63sKO.js +1633 -0
- package/dist/GLTFLoader-Cb_CRwmG.cjs +1 -0
- package/dist/SegmentationOverlay-DQuW3dsc.js +133 -0
- package/dist/SegmentationOverlay-aWVod8Kl.cjs +1 -0
- package/dist/assets/cache.d.ts +99 -0
- package/dist/assets/estimate.d.ts +11 -0
- package/dist/assets/index.d.ts +7 -0
- package/dist/assets/loaders.d.ts +28 -0
- package/dist/assets/react.d.ts +33 -0
- package/dist/calibration/calibration.d.ts +70 -0
- package/dist/calibration/index.d.ts +6 -0
- package/dist/calibration/storage.d.ts +13 -0
- package/dist/calibration/types.d.ts +53 -0
- package/dist/calibration/useXRCalibration.d.ts +46 -0
- package/dist/camera/CameraPermissionGate.d.ts +26 -0
- package/dist/camera/devices.d.ts +26 -0
- package/dist/camera/index.d.ts +8 -0
- package/dist/camera/permission.d.ts +86 -0
- package/dist/camera/useCameraPermission.d.ts +35 -0
- package/dist/capabilities/detect.d.ts +45 -0
- package/dist/capabilities/index.d.ts +5 -0
- package/dist/capabilities/types.d.ts +120 -0
- package/dist/capabilities/useXRCapabilities.d.ts +18 -0
- package/dist/compat/environment.d.ts +5 -0
- package/dist/compat/index.d.ts +4 -0
- package/dist/compat/run.d.ts +18 -0
- package/dist/compat/scenarios.d.ts +10 -0
- package/dist/compat/types.d.ts +101 -0
- package/dist/components/BodyTracker/index.d.ts +9 -0
- package/dist/components/FaceMesh/canonical/CanonicalFaceMeshRenderer.d.ts +33 -3
- package/dist/components/FaceMesh/canonical/parseCanonicalFaceModel.d.ts +12 -0
- package/dist/components/FaceMesh/canonical/shaders.d.ts +1 -1
- package/dist/components/FaceMesh/index.d.ts +1 -1
- package/dist/components/GestureListener/index.d.ts +11 -0
- package/dist/components/HandTracker/index.d.ts +10 -0
- package/dist/components/HolisticTracker/index.d.ts +69 -0
- package/dist/components/HolisticTracker/settings.d.ts +58 -0
- package/dist/components/HolisticTracker/signals.d.ts +49 -0
- package/dist/components/IrisEffect/IrisMaterial.d.ts +73 -0
- package/dist/components/IrisEffect/index.d.ts +51 -0
- package/dist/components/IrisEffect/settings.d.ts +117 -0
- package/dist/components/LipEffect/LipEffect.d.ts +7 -1
- package/dist/components/LipEffect/LipEffectMaterial.d.ts +43 -7
- package/dist/components/LipEffect/LipEffects.d.ts +9 -0
- package/dist/components/LipEffect/defaults.d.ts +27 -4
- package/dist/components/LipEffect/index.d.ts +11 -3
- package/dist/components/LipEffect/settings.d.ts +271 -0
- package/dist/components/LipEffect/types.d.ts +56 -9
- package/dist/components/LipEffect/useLipDesignTextures.d.ts +11 -0
- package/dist/components/LipEffect/uvGuide.d.ts +59 -0
- package/dist/components/PersonCutout/index.d.ts +50 -0
- package/dist/components/PersonCutout/personCutout.d.ts +16 -0
- package/dist/components/ScreenImage/components/ScreenImageBody.d.ts +1 -1
- package/dist/components/ScreenImage/index.d.ts +3 -1
- package/dist/components/ScreenImage/materials/ScreenImageBlendMaterial.d.ts +1 -1
- package/dist/components/ScreenImage/materials/ScreenImageMaskMaterial.d.ts +11 -0
- package/dist/components/ScreenImage/source.d.ts +6 -0
- package/dist/components/ScreenImage/types.d.ts +18 -0
- package/dist/components/SegmentationOverlay/SegmentationOverlay.d.ts +37 -0
- package/dist/components/SegmentationOverlay/SegmentationOverlayMaterial.d.ts +31 -0
- package/dist/components/SegmentationOverlay/index.d.ts +9 -0
- package/dist/components/SegmentationOverlay/maskTexture.d.ts +23 -0
- package/dist/components/SegmentationOverlay/providers.d.ts +72 -0
- package/dist/components/SegmentationOverlay/settings.d.ts +65 -0
- package/dist/components/XRProvider/index.d.ts +16 -2
- package/dist/components/XRViewport/hooks/useViewportExternalFaces.d.ts +1 -1
- package/dist/components/XRViewport/hooks/useViewportMediaSource.d.ts +1 -1
- package/dist/components/XRViewport/hooks/useViewportPipeline.d.ts +1 -1
- package/dist/components/index.d.ts +3 -0
- package/dist/constants/index.d.ts +4 -1
- package/dist/contexts-CO0sd4JQ.cjs +1 -0
- package/dist/{contexts-ByhzppYl.js → contexts-FzlnnMYD.js} +252 -246
- package/dist/coordinates/feed.d.ts +52 -0
- package/dist/coordinates/index.d.ts +5 -0
- package/dist/coordinates/spaces.d.ts +49 -0
- package/dist/coordinates/viewport.d.ts +22 -0
- package/dist/coordinates/world.d.ts +15 -0
- package/dist/debug-ui/gesture-settings/index.d.ts +14 -0
- package/dist/debug-ui/holistic-tracker-settings/index.d.ts +16 -0
- package/dist/debug-ui/index.d.ts +14 -0
- package/dist/debug-ui/iris-effect-settings/index.d.ts +12 -0
- package/dist/debug-ui/lip-effect-settings/index.d.ts +15 -0
- package/dist/debug-ui/media-source.cjs +1 -1
- package/dist/debug-ui/media-source.js +1 -1
- package/dist/debug-ui/product-hotspots/index.d.ts +24 -0
- package/dist/debug-ui/segmentation-overlay-settings/index.d.ts +12 -0
- package/dist/debug-ui/xr-diagnostics/index.d.ts +25 -0
- package/dist/debug-ui.cjs +3 -3
- package/dist/debug-ui.js +2057 -1687
- package/dist/detector-K8aej4MB.js +59 -0
- package/dist/detector-ijypGtse.cjs +1 -0
- package/dist/entries/core.d.ts +18 -1
- package/dist/entries/face-effects.d.ts +11 -3
- package/dist/entries/low-level.d.ts +22 -3
- package/dist/entries/product.d.ts +11 -0
- package/dist/entries/tracking.d.ts +24 -1
- package/dist/face-effects.cjs +155 -1
- package/dist/face-effects.js +1134 -2197
- package/dist/gestures/definitions.d.ts +85 -0
- package/dist/gestures/detector.d.ts +87 -0
- package/dist/gestures/index.d.ts +8 -0
- package/dist/gestures/measures.d.ts +101 -0
- package/dist/gestures/settings.d.ts +49 -0
- package/dist/{getFaceInfo-C4QpCQIY.js → getFaceInfo-BkZfaQs-.js} +5 -5
- package/dist/{getFaceInfo-fA1bFBub.cjs → getFaceInfo-ahPxQFGu.cjs} +1 -1
- package/dist/hooks/selectors.d.ts +68 -1
- package/dist/hooks/useCalibrationFaceTracker.d.ts +1 -1
- package/dist/hooks/useFaceInfo.d.ts +13 -1
- package/dist/hooks/useFaceInfos.d.ts +1 -1
- package/dist/hooks/useGesture.d.ts +32 -0
- package/dist/hooks/useIrisTracking.d.ts +45 -0
- package/dist/hooks/useXRDiagnostics.d.ts +81 -0
- package/dist/hooks/useXRModel.d.ts +7 -0
- package/dist/hooks/useXRSession/facade.d.ts +42 -2
- package/dist/hooks/useXRSession/index.d.ts +2 -2
- package/dist/hooks/useXRSession/reason.d.ts +3 -1
- package/dist/hooks/useXRSession/registry.d.ts +14 -0
- package/dist/hooks/useXRSession/store.d.ts +52 -3
- package/dist/index--RgGzZ6X.cjs +47 -0
- package/dist/{index-VJ0SJwmG.js → index-CHVbH0hz.js} +4 -4
- package/dist/index-CeVkgsag.cjs +1 -0
- package/dist/index-CnGox6Xr.js +3054 -0
- package/dist/{index-ByoNj0QP.js → index-CsUdQ-pn.js} +113 -111
- package/dist/{index-BjmTe9eM.cjs → index-DKBAh6hV.cjs} +1 -1
- package/dist/index-DsZwTfG0.cjs +1 -0
- package/dist/index-Dw6tj2Mi.js +144 -0
- package/dist/index-OCPjOaeP.cjs +1 -0
- package/dist/{index-DXT3WccE.js → index-s9pF4zkG.js} +1065 -1101
- package/dist/internal-BYza1h8_.cjs +1 -0
- package/dist/{internal-Dmk1cTXq.js → internal-vsfNQycj.js} +15 -16
- package/dist/internal.cjs +1 -1
- package/dist/internal.js +2 -2
- package/dist/iris/compute.d.ts +25 -0
- package/dist/iris/index.d.ts +4 -0
- package/dist/iris/lead.d.ts +19 -0
- package/dist/iris/types.d.ts +87 -0
- package/dist/landmarkMask-CbTFzBYG.js +224 -0
- package/dist/landmarkMask-u7es2k4X.cjs +1 -0
- package/dist/low-level.cjs +1 -1
- package/dist/low-level.js +1085 -634
- package/dist/main.cjs +1 -1
- package/dist/main.js +1519 -465
- package/dist/measures-9dQPdw96.js +154 -0
- package/dist/measures-KfJzpvod.cjs +1 -0
- package/dist/models/Base/index.d.ts +49 -0
- package/dist/models/Body/index.d.ts +1 -1
- package/dist/models/Face/index.d.ts +1 -1
- package/dist/models/Hand/GestureTracking.d.ts +1 -1
- package/dist/models/Hand/HandTracking.d.ts +1 -1
- package/dist/models/Holistic/index.d.ts +49 -0
- package/dist/models/Holistic/result.d.ts +68 -0
- package/dist/models/SemanticSegmentation/index.d.ts +31 -0
- package/dist/models/SemanticSegmentation/presets.d.ts +28 -0
- package/dist/models/index.d.ts +2 -0
- package/dist/product/ProductDimensions.d.ts +16 -0
- package/dist/product/ProductHotspot.d.ts +16 -0
- package/dist/product/ProductViewer.d.ts +9 -0
- package/dist/product/details.d.ts +53 -0
- package/dist/product/index.d.ts +14 -0
- package/dist/product/loadModelViewer.d.ts +4 -0
- package/dist/product/types.d.ts +71 -0
- package/dist/product/useProductAr.d.ts +37 -0
- package/dist/product/useProductDetails.d.ts +60 -0
- package/dist/product.cjs +1 -0
- package/dist/product.js +414 -0
- package/dist/providers-C0Dlhh9Z.js +365 -0
- package/dist/providers-YNwkmNeK.cjs +62 -0
- package/dist/quality/XRQualityController.d.ts +25 -0
- package/dist/quality/controller.d.ts +33 -0
- package/dist/quality/index.d.ts +6 -0
- package/dist/quality/types.d.ts +100 -0
- package/dist/quality/useXRQuality.d.ts +28 -0
- package/dist/{renderGroups-KZk6eRiY.js → renderGroups-CN1cGFUo.js} +1 -1
- package/dist/{renderGroups-80H3DpTl.cjs → renderGroups-O4KmaMl9.cjs} +1 -1
- package/dist/renderPasses-Cg-zqmEz.cjs +21 -0
- package/dist/renderPasses-NnKZVfBy.js +1460 -0
- package/dist/scene-object.cjs +1 -1
- package/dist/scene-object.js +2 -2
- package/dist/screenTransform-BenfCtZt.js +44 -0
- package/dist/screenTransform-BiXdpVf0.cjs +1 -0
- package/dist/segmentation-9PhSvc-R.cjs +1 -0
- package/dist/segmentation-CeOTKemr.js +5 -0
- package/dist/segmentation2d/faceMemory.d.ts +28 -0
- package/dist/segmentation2d/faceRegions.d.ts +24 -0
- package/dist/segmentation2d/index.d.ts +9 -0
- package/dist/segmentation2d/maskUv.d.ts +23 -0
- package/dist/segmentation2d/rasterize.d.ts +14 -0
- package/dist/segmentation2d/types.d.ts +46 -0
- package/dist/selectors-C5G1PMYL.js +195 -0
- package/dist/selectors-Du_PsVnW.cjs +1 -0
- package/dist/{session-CpkiK5YA.cjs → session-BBr0yN8h.cjs} +7 -7
- package/dist/{session-DLFN_VII.js → session-Cy0m7l7-.js} +76 -76
- package/dist/settings-DRR7-snV.cjs +1 -0
- package/dist/settings-aQk845NJ.js +73 -0
- package/dist/subjects/index.d.ts +2 -0
- package/dist/subjects/select.d.ts +62 -0
- package/dist/subjects/types.d.ts +55 -0
- package/dist/tracking-config/apply.d.ts +57 -0
- package/dist/tracking-config/index.d.ts +7 -0
- package/dist/tracking-config/resolve.d.ts +25 -0
- package/dist/tracking-config/storage.d.ts +8 -0
- package/dist/tracking-config/types.d.ts +106 -0
- package/dist/tracking-config/useXRTrackingConfig.d.ts +38 -0
- package/dist/tracking.cjs +1 -1
- package/dist/tracking.js +1056 -383
- package/dist/types/compositor.d.ts +21 -0
- package/dist/types/holistic.d.ts +121 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/model.d.ts +22 -2
- package/dist/types/nodes.d.ts +27 -2
- package/dist/types/segmentation.d.ts +19 -0
- package/dist/types/session.d.ts +41 -3
- package/dist/useFaceInfo-Blf7FCu3.js +303 -0
- package/dist/useFaceInfo-C5mO8NQY.cjs +1 -0
- package/dist/useXRCapabilities-B1R2ghy-.cjs +1 -0
- package/dist/useXRCapabilities-C68v__wB.js +30 -0
- package/dist/utils/fns.d.ts +6 -3
- package/dist/utils/integrity.d.ts +4 -1
- package/dist/utils/updateThrottle.d.ts +2 -0
- package/dist/utils/useStableUniforms.d.ts +18 -0
- package/docs/api/adaptive-quality.mdx +104 -0
- package/docs/api/asset-lifecycle.mdx +78 -0
- package/docs/api/camera-permission.mdx +142 -0
- package/docs/api/coordinate-spaces.mdx +165 -0
- package/docs/api/cross-camera.mdx +88 -0
- package/docs/api/diagnostics-calibration.mdx +97 -0
- package/docs/api/face-effects.mdx +6 -0
- package/docs/api/face-mesh.mdx +4 -2
- package/docs/api/gestures.mdx +173 -0
- package/docs/api/holistic-tracker.mdx +159 -0
- package/docs/api/iris-tracking.mdx +242 -0
- package/docs/api/multi-subject.mdx +95 -0
- package/docs/api/person-cutout.mdx +136 -0
- package/docs/api/product-ar.mdx +111 -0
- package/docs/api/product-details.mdx +78 -0
- package/docs/api/screen-space-coordinates.mdx +4 -1
- package/docs/api/segmentation-overlay.mdx +301 -0
- package/docs/api/session-lifecycle.mdx +136 -0
- package/docs/api/trackers.mdx +5 -0
- package/docs/api/tracking-config.mdx +108 -0
- package/docs/docs.json +23 -1
- package/docs/examples/lip-shaders.mdx +224 -0
- package/docs/guides/lip-effect-textures.mdx +292 -0
- package/docs/guides/lip-uv-template.png +0 -0
- package/docs/guides/lip-uv-template.svg +1 -0
- package/package.json +13 -1
- package/dist/FaceMeshRenderer-C5l6VLdO.cjs +0 -155
- package/dist/FaceMeshRenderer-wjAHrJzP.js +0 -1270
- package/dist/FaceRetouch-BkJzoA79.cjs +0 -134
- package/dist/FaceRetouch-DwbKQJAN.js +0 -551
- package/dist/contexts-Dr62It_K.cjs +0 -1
- package/dist/index-9dlAQAhy.js +0 -1462
- package/dist/index-BpEf2BBb.cjs +0 -1
- package/dist/index-CyUUurQT.cjs +0 -1
- package/dist/index-DCiMbxC3.cjs +0 -1
- package/dist/index-DpI-qo5X.cjs +0 -17
- package/dist/index-DyVF4vEW.js +0 -111
- package/dist/internal-Cq-TEQ5Y.cjs +0 -1
- package/dist/renderLayers-lDtL0_43.cjs +0 -1
- package/dist/renderLayers-zrK2pv5O.js +0 -13
- package/dist/renderPasses-BOoBSr8z.cjs +0 -21
- package/dist/renderPasses-BcquyVtu.js +0 -1500
- package/dist/selectors-B8H97CKA.js +0 -59
- package/dist/selectors-CZLKT2Iv.cjs +0 -1
- package/dist/useFaceInfo-BJ8-_MOs.cjs +0 -1
- package/dist/useFaceInfo-Dk426LTu.js +0 -62
- package/dist/useFaceResults-CtetsO9M.js +0 -19
- package/dist/useFaceResults-wBJF3zyp.cjs +0 -1
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
import { UseCameraPermissionResult } from './useCameraPermission';
|
|
3
|
+
export type CameraPermissionGateProps = {
|
|
4
|
+
/** Rendered once the camera is usable (`granted`). */
|
|
5
|
+
children: ReactNode;
|
|
6
|
+
/**
|
|
7
|
+
* Rendered in every other state. Receives the hook result so the fallback
|
|
8
|
+
* can show the state, the reason and a request button. Omit for the
|
|
9
|
+
* built-in accessible fallback.
|
|
10
|
+
*/
|
|
11
|
+
fallback?: (permission: UseCameraPermissionResult) => ReactNode;
|
|
12
|
+
/** Prompt on mount instead of waiting for the button. Default `false`. */
|
|
13
|
+
auto?: boolean;
|
|
14
|
+
constraints?: MediaStreamConstraints;
|
|
15
|
+
/** Copy for the built-in fallback's button. */
|
|
16
|
+
requestLabel?: string;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Renders `children` only while camera access is `granted`; otherwise a
|
|
20
|
+
* fallback that explains the state and offers a request button. The
|
|
21
|
+
* built-in fallback announces state changes through `aria-live`, keeps the
|
|
22
|
+
* request behind a real button (a user gesture, as browsers require), and
|
|
23
|
+
* disables it when a prompt cannot help (`blocked`, `unavailable`). No camera
|
|
24
|
+
* frame is captured until the viewer allows access and the session binds.
|
|
25
|
+
*/
|
|
26
|
+
export declare const CameraPermissionGate: ({ children, fallback, auto, constraints, requestLabel, }: CameraPermissionGateProps) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { XRCameraFacing } from '../types/compositor';
|
|
2
|
+
/** One video input the browser lists. Labels are empty until camera permission is granted. */
|
|
3
|
+
export type XRCameraDevice = {
|
|
4
|
+
deviceId: string;
|
|
5
|
+
label: string;
|
|
6
|
+
/** Guessed from the label (`back`, `rear`, `environment` → rear; `front`, `user`, `facetime` → front); `null` when unknown. */
|
|
7
|
+
facing: XRCameraFacing | null;
|
|
8
|
+
};
|
|
9
|
+
export type XRCameraDeviceEnvironment = {
|
|
10
|
+
enumerateDevices?: () => Promise<Array<{
|
|
11
|
+
kind: string;
|
|
12
|
+
deviceId: string;
|
|
13
|
+
label: string;
|
|
14
|
+
}>>;
|
|
15
|
+
};
|
|
16
|
+
/** Guess a camera's facing from its label. */
|
|
17
|
+
export declare const guessCameraFacing: (label: string) => XRCameraFacing | null;
|
|
18
|
+
/**
|
|
19
|
+
* List the cameras the browser exposes. Before permission is granted most
|
|
20
|
+
* browsers return devices with empty labels (and some return none), so call
|
|
21
|
+
* it after `requestCameraAccess` / a first bind for a usable list. Never
|
|
22
|
+
* throws; an unsupported browser yields `[]`.
|
|
23
|
+
*/
|
|
24
|
+
export declare const listCameras: (env?: XRCameraDeviceEnvironment) => Promise<XRCameraDevice[]>;
|
|
25
|
+
/** Pick the device for a facing from a list (first match), or `null`. */
|
|
26
|
+
export declare const findCameraByFacing: (cameras: XRCameraDevice[], facing: XRCameraFacing) => XRCameraDevice | null;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { CAMERA_PERMISSION_MESSAGES, canPromptForCamera, classifyCameraFailure, queryCameraPermission, requestCameraAccess, subscribeCameraPermission, } from './permission';
|
|
2
|
+
export type { XRCameraAccessOptions, XRCameraAccessResult, XRCameraPermissionEnvironment, XRCameraPermissionQuery, XRCameraPermissionState, } from './permission';
|
|
3
|
+
export { useCameraPermission } from './useCameraPermission';
|
|
4
|
+
export type { UseCameraPermissionOptions, UseCameraPermissionResult } from './useCameraPermission';
|
|
5
|
+
export { CameraPermissionGate } from './CameraPermissionGate';
|
|
6
|
+
export { findCameraByFacing, guessCameraFacing, listCameras } from './devices';
|
|
7
|
+
export type { XRCameraDevice, XRCameraDeviceEnvironment } from './devices';
|
|
8
|
+
export type { CameraPermissionGateProps } from './CameraPermissionGate';
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { XRFallbackReason } from '../capabilities/types';
|
|
2
|
+
import { XRErrorReason } from '../hooks/useXRSession/reason';
|
|
3
|
+
/**
|
|
4
|
+
* Creator-facing camera permission state.
|
|
5
|
+
*
|
|
6
|
+
* - `unknown`: never asked (the next request will prompt), or the browser
|
|
7
|
+
* cannot say.
|
|
8
|
+
* - `requesting`: a `getUserMedia` prompt is open.
|
|
9
|
+
* - `granted`: usable; the session may bind the webcam.
|
|
10
|
+
* - `denied`: this request was declined or the prompt was dismissed; asking
|
|
11
|
+
* again will prompt again.
|
|
12
|
+
* - `blocked`: persistently denied in the browser's site settings; asking
|
|
13
|
+
* again will fail without a prompt, so the viewer must change the setting.
|
|
14
|
+
* - `unavailable`: no camera, insecure context, unsupported browser, or the
|
|
15
|
+
* device is held by another app (`reason` says which).
|
|
16
|
+
*/
|
|
17
|
+
export type XRCameraPermissionState = "unknown" | "requesting" | "granted" | "denied" | "blocked" | "unavailable";
|
|
18
|
+
/** What the Permissions API can tell before any request. */
|
|
19
|
+
export type XRCameraPermissionQuery = {
|
|
20
|
+
state: "unknown" | "granted" | "blocked";
|
|
21
|
+
/** True when the browser reported `prompt` (it will ask on the next request). */
|
|
22
|
+
prompt: boolean;
|
|
23
|
+
};
|
|
24
|
+
export type XRCameraAccessResult = {
|
|
25
|
+
state: XRCameraPermissionState;
|
|
26
|
+
reason: XRFallbackReason | null;
|
|
27
|
+
/** The stream, only when `keepStream` was true and access was granted. */
|
|
28
|
+
stream: MediaStream | null;
|
|
29
|
+
};
|
|
30
|
+
export type XRCameraAccessOptions = {
|
|
31
|
+
/** Keep the granted stream open and return it. Default `false`: the probe stops every track at once. */
|
|
32
|
+
keepStream?: boolean;
|
|
33
|
+
/** Constraints for the probe (default `{ video: { facingMode: "user" } }`). */
|
|
34
|
+
constraints?: MediaStreamConstraints;
|
|
35
|
+
};
|
|
36
|
+
/** Minimal environment the helpers read, injectable for tests. */
|
|
37
|
+
export type XRCameraPermissionEnvironment = {
|
|
38
|
+
mediaDevices?: {
|
|
39
|
+
getUserMedia?: (constraints: MediaStreamConstraints) => Promise<MediaStream>;
|
|
40
|
+
};
|
|
41
|
+
permissions?: {
|
|
42
|
+
query: (desc: {
|
|
43
|
+
name: string;
|
|
44
|
+
}) => Promise<{
|
|
45
|
+
state: string;
|
|
46
|
+
addEventListener?: (type: "change", listener: () => void) => void;
|
|
47
|
+
removeEventListener?: (type: "change", listener: () => void) => void;
|
|
48
|
+
}>;
|
|
49
|
+
};
|
|
50
|
+
isSecureContext?: boolean;
|
|
51
|
+
};
|
|
52
|
+
export declare const defaultCameraEnvironment: () => XRCameraPermissionEnvironment;
|
|
53
|
+
/**
|
|
54
|
+
* Ask the Permissions API for the camera state without prompting. `unknown`
|
|
55
|
+
* covers both "will prompt" (`prompt: true`) and "cannot tell" (Firefox and
|
|
56
|
+
* older Safari reject the camera descriptor).
|
|
57
|
+
*/
|
|
58
|
+
export declare const queryCameraPermission: (env?: XRCameraPermissionEnvironment) => Promise<XRCameraPermissionQuery>;
|
|
59
|
+
/**
|
|
60
|
+
* Turn a failed `getUserMedia` (its SDK reason) plus the permission state
|
|
61
|
+
* read *after* the failure into a creator-facing state. A denial while the
|
|
62
|
+
* browser now reports `denied` is a persistent block; a denial while it still
|
|
63
|
+
* reports `prompt` was a dismissal or a one-off decline.
|
|
64
|
+
*/
|
|
65
|
+
export declare const classifyCameraFailure: (reason: XRErrorReason, permission: XRCameraPermissionQuery["state"]) => {
|
|
66
|
+
state: XRCameraPermissionState;
|
|
67
|
+
reason: XRFallbackReason;
|
|
68
|
+
};
|
|
69
|
+
/**
|
|
70
|
+
* Request camera access explicitly, before (or outside) a session. The
|
|
71
|
+
* granted stream is stopped immediately unless `keepStream` is set, so the
|
|
72
|
+
* camera indicator goes off and no frame is processed: this only moves the
|
|
73
|
+
* permission. Pass the returned stream to `session.setMediaSource` when you
|
|
74
|
+
* keep it. Never throws; read `state` and `reason`.
|
|
75
|
+
*/
|
|
76
|
+
export declare const requestCameraAccess: (options?: XRCameraAccessOptions, env?: XRCameraPermissionEnvironment) => Promise<XRCameraAccessResult>;
|
|
77
|
+
/**
|
|
78
|
+
* Subscribe to Permissions API changes (the viewer toggling the site's camera
|
|
79
|
+
* setting). The listener receives the new query; returns an unsubscribe.
|
|
80
|
+
* Resolves to a no-op where the API is unavailable.
|
|
81
|
+
*/
|
|
82
|
+
export declare const subscribeCameraPermission: (listener: (query: XRCameraPermissionQuery) => void, env?: XRCameraPermissionEnvironment) => Promise<() => void>;
|
|
83
|
+
/** True when a request can show a prompt or succeed (not blocked / unavailable). */
|
|
84
|
+
export declare const canPromptForCamera: (state: XRCameraPermissionState) => boolean;
|
|
85
|
+
/** Display copy per state (reword freely; branch on `state`, never on this text). */
|
|
86
|
+
export declare const CAMERA_PERMISSION_MESSAGES: Record<XRCameraPermissionState, string>;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { XRFallbackReason } from '../capabilities/types';
|
|
2
|
+
import { XRCameraAccessOptions, XRCameraPermissionEnvironment, XRCameraPermissionState } from './permission';
|
|
3
|
+
export type UseCameraPermissionOptions = {
|
|
4
|
+
/** Request on mount (shows the prompt immediately). Default `false`: query only, prompt on `request()`. */
|
|
5
|
+
auto?: boolean;
|
|
6
|
+
/** Probe constraints passed to `requestCameraAccess`. */
|
|
7
|
+
constraints?: MediaStreamConstraints;
|
|
8
|
+
/** Environment override for tests. */
|
|
9
|
+
env?: XRCameraPermissionEnvironment;
|
|
10
|
+
};
|
|
11
|
+
export type UseCameraPermissionResult = {
|
|
12
|
+
state: XRCameraPermissionState;
|
|
13
|
+
reason: XRFallbackReason | null;
|
|
14
|
+
/** The next `request()` can show a prompt or succeed. */
|
|
15
|
+
canPrompt: boolean;
|
|
16
|
+
/** `granted`. */
|
|
17
|
+
usable: boolean;
|
|
18
|
+
/**
|
|
19
|
+
* Prompt (or re-prompt). Resolves to the new state. The probe stream is
|
|
20
|
+
* always stopped at once; to keep a stream, call `requestCameraAccess`
|
|
21
|
+
* directly, which returns it.
|
|
22
|
+
*/
|
|
23
|
+
request: (options?: Pick<XRCameraAccessOptions, "constraints">) => Promise<XRCameraPermissionState>;
|
|
24
|
+
/** Re-read the Permissions API without prompting. */
|
|
25
|
+
refresh: () => Promise<XRCameraPermissionState>;
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* Camera permission for a landing or gate screen. Needs no `<XRProvider>`.
|
|
29
|
+
* Queries on mount (never prompts unless `auto`), follows the browser's
|
|
30
|
+
* site-setting changes, and exposes `request()` for a user-gesture button.
|
|
31
|
+
* Once `usable`, mount the session and call `setMediaSource({ source:
|
|
32
|
+
* XRMediaSource.WEBCAM })`; the session reports its own live state through
|
|
33
|
+
* `useXRSessionCameraPermission()` (`/low-level`).
|
|
34
|
+
*/
|
|
35
|
+
export declare const useCameraPermission: (options?: UseCameraPermissionOptions) => UseCameraPermissionResult;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { XRModel } from '../constants';
|
|
2
|
+
import { XRCapabilities, XRCapabilityCheckOptions, XRCapabilityEnvironment, XRCapabilityStatus, XRFallbackCode, XRFallbackReason } from './types';
|
|
3
|
+
export declare const XR_FALLBACK_MESSAGES: Record<XRFallbackCode, string>;
|
|
4
|
+
/** Build a fallback reason from its code (the message table is SDK-owned). */
|
|
5
|
+
export declare const createFallbackReason: (code: XRFallbackCode, message?: string) => XRFallbackReason;
|
|
6
|
+
/**
|
|
7
|
+
* The SDK-owned asset each tracker downloads on first use, relative to the
|
|
8
|
+
* asset CDN. Semantic segmentation loads a preset-specific file and holistic
|
|
9
|
+
* loads from the MediaPipe bucket until the CDN copy is published.
|
|
10
|
+
*/
|
|
11
|
+
export declare const XR_MODEL_ASSET_URLS: Record<XRModel, string | null>;
|
|
12
|
+
export declare const resolveModelAssetUrl: (model: XRModel) => string | null;
|
|
13
|
+
/** Android Chrome / Samsung Internet (ARCore devices) can hand off to Scene Viewer. */
|
|
14
|
+
export declare const isSceneViewerUserAgent: (ua: string | undefined) => boolean;
|
|
15
|
+
/** Map a browser permission state onto the SDK status vocabulary. */
|
|
16
|
+
export declare const permissionStateToStatus: (state: string | undefined) => XRCapabilityStatus;
|
|
17
|
+
/**
|
|
18
|
+
* Probe the platform before a session starts: camera (secure context,
|
|
19
|
+
* `getUserMedia`, device count, permission state), rendering (WebGL,
|
|
20
|
+
* OffscreenCanvas, WebAssembly, WebGPU presence) and, for the `models` listed,
|
|
21
|
+
* whether each tracker's asset is reachable. Never opens the camera and never
|
|
22
|
+
* downloads a model body. Pass `env` only in tests.
|
|
23
|
+
*/
|
|
24
|
+
export declare const detectXRCapabilities: (options?: XRCapabilityCheckOptions, env?: XRCapabilityEnvironment) => Promise<XRCapabilities>;
|
|
25
|
+
/** Map a session (camera) error reason onto the fallback vocabulary. */
|
|
26
|
+
export declare const sessionReasonToFallback: (reason: "permission-denied" | "camera-in-use" | "no-camera" | "unsupported" | "camera-lost" | "unknown") => XRFallbackReason;
|
|
27
|
+
export type XRTrackerSupport = {
|
|
28
|
+
supported: boolean;
|
|
29
|
+
/** The first blocking reason, most fundamental first: rendering, then camera, then the model. */
|
|
30
|
+
reason: XRFallbackReason | null;
|
|
31
|
+
/** The camera has not been granted yet; the session's first `getUserMedia` will prompt. */
|
|
32
|
+
needsPermission: boolean;
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* Collapse a capability report into one answer for a tracker. A
|
|
36
|
+
* `permission-prompt` camera counts as supported (the prompt is the next
|
|
37
|
+
* step); a denied camera does not.
|
|
38
|
+
*/
|
|
39
|
+
export declare const resolveTrackerSupport: (capabilities: XRCapabilities, model: XRModel) => XRTrackerSupport;
|
|
40
|
+
/**
|
|
41
|
+
* Classify a model initialization error (what `useXRModel().error` carries)
|
|
42
|
+
* into a fallback reason. Integrity failures and network failures come from
|
|
43
|
+
* the SDK's own fetch; anything else is a MediaPipe init failure on this device.
|
|
44
|
+
*/
|
|
45
|
+
export declare const mapModelErrorToReason: (error: unknown) => XRFallbackReason;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export type { XRCameraCapability, XRCapabilities, XRCapabilityCheckOptions, XRCapabilityEnvironment, XRCapabilityStatus, XRFallbackCode, XRFallbackReason, XRModelCapability, XRPlacementCapability, XRRenderingCapability, } from './types';
|
|
2
|
+
export { XR_FALLBACK_MESSAGES, XR_MODEL_ASSET_URLS, createFallbackReason, detectXRCapabilities, mapModelErrorToReason, permissionStateToStatus, resolveModelAssetUrl, resolveTrackerSupport, } from './detect';
|
|
3
|
+
export type { XRTrackerSupport } from './detect';
|
|
4
|
+
export { useXRCapabilities } from './useXRCapabilities';
|
|
5
|
+
export type { UseXRCapabilitiesResult, XRCapabilityCheckStatus } from './useXRCapabilities';
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { XRModel } from '../constants';
|
|
2
|
+
/**
|
|
3
|
+
* Whether one platform feature can be used. `permission-prompt` is camera-only:
|
|
4
|
+
* the browser has not asked yet, so the first `getUserMedia` will prompt.
|
|
5
|
+
*/
|
|
6
|
+
export type XRCapabilityStatus = "supported" | "unsupported" | "permission-denied" | "permission-prompt" | "unknown";
|
|
7
|
+
/** Stable, machine-readable reason a feature or tracker cannot run. */
|
|
8
|
+
export type XRFallbackCode = "camera-permission-denied" | "camera-in-use" | "no-camera" | "camera-insecure-context" | "camera-unsupported" | "camera-lost" | "webgl-unavailable" | "offscreen-canvas-unavailable" | "wasm-unavailable" | "model-unreachable" | "model-integrity" | "model-init-failed" | "placement-unsupported" | "unknown";
|
|
9
|
+
/**
|
|
10
|
+
* Structured reason for a degraded state. `message` is prose and may be
|
|
11
|
+
* reworded; branch on `code`. `recoverable` says whether a user action (grant
|
|
12
|
+
* permission, close the other tab, reconnect) can fix it without a reload.
|
|
13
|
+
*/
|
|
14
|
+
export type XRFallbackReason = {
|
|
15
|
+
code: XRFallbackCode;
|
|
16
|
+
message: string;
|
|
17
|
+
recoverable: boolean;
|
|
18
|
+
};
|
|
19
|
+
export type XRCameraCapability = {
|
|
20
|
+
status: XRCapabilityStatus;
|
|
21
|
+
reason: XRFallbackReason | null;
|
|
22
|
+
/** Number of video input devices the browser lists (labels need permission). */
|
|
23
|
+
deviceCount: number | null;
|
|
24
|
+
/** True when the page runs in a secure context (`getUserMedia` requires it). */
|
|
25
|
+
secureContext: boolean;
|
|
26
|
+
};
|
|
27
|
+
export type XRRenderingCapability = {
|
|
28
|
+
status: XRCapabilityStatus;
|
|
29
|
+
reason: XRFallbackReason | null;
|
|
30
|
+
/** `2` for WebGL2, `1` for WebGL1, `0` when neither context can be created. */
|
|
31
|
+
webglVersion: 0 | 1 | 2;
|
|
32
|
+
/** `navigator.gpu` is present. The SDK does not need WebGPU; this is informational. */
|
|
33
|
+
webgpu: boolean;
|
|
34
|
+
offscreenCanvas: boolean;
|
|
35
|
+
/** WebAssembly is present (MediaPipe needs it). */
|
|
36
|
+
wasm: boolean;
|
|
37
|
+
};
|
|
38
|
+
export type XRModelCapability = {
|
|
39
|
+
model: XRModel;
|
|
40
|
+
status: XRCapabilityStatus;
|
|
41
|
+
reason: XRFallbackReason | null;
|
|
42
|
+
/** The asset the check probed; `null` when the model has no SDK-owned asset path. */
|
|
43
|
+
url: string | null;
|
|
44
|
+
/** Content-Length from the probe, when the server reports it. */
|
|
45
|
+
bytes: number | null;
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* Surface-placement ("view in your space") AR, the model-viewer route: each
|
|
49
|
+
* native path the device can take. None of these is the SDK's own camera
|
|
50
|
+
* session; a page offers "View in AR" when `any` is true.
|
|
51
|
+
*/
|
|
52
|
+
export type XRPlacementCapability = {
|
|
53
|
+
/** WebXR `immersive-ar` (Android Chrome, some headsets). */
|
|
54
|
+
webxr: boolean;
|
|
55
|
+
/** Android Scene Viewer intent (Android Chrome / Samsung Internet with ARCore). */
|
|
56
|
+
sceneViewer: boolean;
|
|
57
|
+
/** iOS AR Quick Look (`<a rel="ar">`), needs a USDZ. */
|
|
58
|
+
quickLook: boolean;
|
|
59
|
+
any: boolean;
|
|
60
|
+
reason: XRFallbackReason | null;
|
|
61
|
+
};
|
|
62
|
+
export type XRCapabilities = {
|
|
63
|
+
camera: XRCameraCapability;
|
|
64
|
+
rendering: XRRenderingCapability;
|
|
65
|
+
placement: XRPlacementCapability;
|
|
66
|
+
models: Record<XRModel, XRModelCapability>;
|
|
67
|
+
/** True when camera and rendering are both usable (models are checked per tracker). */
|
|
68
|
+
canRunTracking: boolean;
|
|
69
|
+
/** When the check ran (`performance.now()` milliseconds). */
|
|
70
|
+
checkedAt: number;
|
|
71
|
+
};
|
|
72
|
+
export type XRCapabilityCheckOptions = {
|
|
73
|
+
/**
|
|
74
|
+
* Trackers to probe. Each probe is a `HEAD` request to the model asset; omit
|
|
75
|
+
* to skip asset probes (models report `unknown`). Probing is cheap (headers
|
|
76
|
+
* only) but it is a network round trip per model.
|
|
77
|
+
*/
|
|
78
|
+
models?: XRModel[];
|
|
79
|
+
/** Per-probe timeout in milliseconds. Default 4000. */
|
|
80
|
+
timeoutMs?: number;
|
|
81
|
+
/**
|
|
82
|
+
* Query the Permissions API for the camera state. Default `true`. Turning it
|
|
83
|
+
* off keeps the check from touching permissions at all (status stays
|
|
84
|
+
* `unknown` until the first `getUserMedia`).
|
|
85
|
+
*/
|
|
86
|
+
queryPermission?: boolean;
|
|
87
|
+
};
|
|
88
|
+
/** Minimal environment the detector reads, injectable for tests. */
|
|
89
|
+
export type XRCapabilityEnvironment = {
|
|
90
|
+
navigator?: {
|
|
91
|
+
mediaDevices?: {
|
|
92
|
+
getUserMedia?: (constraints?: MediaStreamConstraints) => Promise<MediaStream>;
|
|
93
|
+
enumerateDevices?: () => Promise<Array<{
|
|
94
|
+
kind: string;
|
|
95
|
+
label?: string;
|
|
96
|
+
}>>;
|
|
97
|
+
};
|
|
98
|
+
permissions?: {
|
|
99
|
+
query: (desc: {
|
|
100
|
+
name: string;
|
|
101
|
+
}) => Promise<{
|
|
102
|
+
state: string;
|
|
103
|
+
}>;
|
|
104
|
+
};
|
|
105
|
+
gpu?: unknown;
|
|
106
|
+
};
|
|
107
|
+
isSecureContext?: boolean;
|
|
108
|
+
createCanvas?: () => {
|
|
109
|
+
getContext: (id: string) => unknown;
|
|
110
|
+
} | null;
|
|
111
|
+
/** `navigator.xr.isSessionSupported("immersive-ar")`; absent when WebXR is missing. */
|
|
112
|
+
xrSessionSupported?: (mode: string) => Promise<boolean>;
|
|
113
|
+
/** `a.relList.supports("ar")` for Quick Look. */
|
|
114
|
+
relSupportsAr?: boolean;
|
|
115
|
+
userAgent?: string;
|
|
116
|
+
offscreenCanvas?: boolean;
|
|
117
|
+
wasm?: boolean;
|
|
118
|
+
fetch?: typeof fetch;
|
|
119
|
+
now?: () => number;
|
|
120
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { XRCapabilities, XRCapabilityCheckOptions } from './types';
|
|
2
|
+
export type XRCapabilityCheckStatus = "idle" | "checking" | "ready" | "error";
|
|
3
|
+
export type UseXRCapabilitiesResult = {
|
|
4
|
+
/** `null` until the first check resolves. */
|
|
5
|
+
capabilities: XRCapabilities | null;
|
|
6
|
+
status: XRCapabilityCheckStatus;
|
|
7
|
+
error: Error | null;
|
|
8
|
+
/** Re-run the check (after the user granted permission, reconnected, …). */
|
|
9
|
+
refresh: () => Promise<XRCapabilities | null>;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Run `detectXRCapabilities` on mount and expose the report. Needs no
|
|
13
|
+
* `<XRProvider>`: call it on the landing screen to decide whether to offer the
|
|
14
|
+
* AR experience at all. Pass `enabled: false` to defer the check.
|
|
15
|
+
*/
|
|
16
|
+
export declare const useXRCapabilities: (options?: XRCapabilityCheckOptions & {
|
|
17
|
+
enabled?: boolean;
|
|
18
|
+
}) => UseXRCapabilitiesResult;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { XRCompatEnvironment } from './types';
|
|
2
|
+
/** Best-effort browser / OS identification from a user agent (for the report label, not for feature gating). */
|
|
3
|
+
export declare const parseUserAgent: (ua: string) => Pick<XRCompatEnvironment, "browser" | "os" | "mobile">;
|
|
4
|
+
/** Describe the current browser for the report. */
|
|
5
|
+
export declare const describeCompatEnvironment: () => XRCompatEnvironment;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export type { XRCompatAutomatedScenarioId, XRCompatManualScenarioId, XRCompatScenarioId, XRCompatCause, XRCompatEnvironment, XRCompatReport, XRCompatResult, XRCompatRunOptions, XRCompatScenario, XRCompatStatus, } from './types';
|
|
2
|
+
export { COMPAT_SCENARIOS, MANUAL_COMPAT_SCENARIOS, findCompatScenario } from './scenarios';
|
|
3
|
+
export { describeCompatEnvironment, parseUserAgent } from './environment';
|
|
4
|
+
export { classifyCompatCause, createCompatReport, runCompatChecks, summarizeCompatResults, waitFor, } from './run';
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { XRCapabilities } from '../capabilities/types';
|
|
2
|
+
import { SessionFacade } from '../hooks/useXRSession';
|
|
3
|
+
import { XRCompatCause, XRCompatReport, XRCompatResult, XRCompatRunOptions } from './types';
|
|
4
|
+
/** Poll `predicate` until true or the timeout; resolves to whether it became true. */
|
|
5
|
+
export declare const waitFor: (predicate: () => boolean, timeoutMs: number, stepMs?: number) => Promise<boolean>;
|
|
6
|
+
/** Attribute a failure to a layer from the structured codes the SDK produces. */
|
|
7
|
+
export declare const classifyCompatCause: (code: string | null, layer: XRCompatCause) => XRCompatCause;
|
|
8
|
+
export declare const summarizeCompatResults: (results: XRCompatResult[]) => XRCompatReport["summary"];
|
|
9
|
+
export declare const createCompatReport: (results: XRCompatResult[], capabilities: XRCapabilities | null, options?: Pick<XRCompatRunOptions, "label" | "sdkVersion">) => XRCompatReport;
|
|
10
|
+
/**
|
|
11
|
+
* Run the automated compatibility scenarios against a live session (an
|
|
12
|
+
* `<XRProvider>`'s facade). Opens the webcam unless `stream` is supplied,
|
|
13
|
+
* acquires the requested models, exercises pause / resume / stop / start,
|
|
14
|
+
* samples performance, releases what it acquired and stops the session
|
|
15
|
+
* (releasing the camera) unless `keepSessionRunning`. Never throws: every
|
|
16
|
+
* scenario ends as a result with a classified `cause`.
|
|
17
|
+
*/
|
|
18
|
+
export declare const runCompatChecks: (session: SessionFacade, options?: XRCompatRunOptions) => Promise<XRCompatReport>;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { XRCompatAutomatedScenarioId, XRCompatManualScenarioId, XRCompatScenario, XRCompatScenarioId } from './types';
|
|
2
|
+
/** Scenarios the harness runs by itself, in order. */
|
|
3
|
+
export declare const COMPAT_SCENARIOS: Array<XRCompatScenario & {
|
|
4
|
+
id: XRCompatAutomatedScenarioId;
|
|
5
|
+
}>;
|
|
6
|
+
/** Scenarios only a person on a real device can run; results are entered by hand. */
|
|
7
|
+
export declare const MANUAL_COMPAT_SCENARIOS: Array<XRCompatScenario & {
|
|
8
|
+
id: XRCompatManualScenarioId;
|
|
9
|
+
}>;
|
|
10
|
+
export declare const findCompatScenario: (id: XRCompatScenarioId | string) => XRCompatScenario | undefined;
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { XRCapabilities } from '../capabilities/types';
|
|
2
|
+
import { XRModel } from '../constants';
|
|
3
|
+
/** Which layer a failed check points at. */
|
|
4
|
+
export type XRCompatCause = "capability" | "model" | "lifecycle" | "performance" | "unknown";
|
|
5
|
+
export type XRCompatStatus = "pass" | "fail" | "skip";
|
|
6
|
+
/** Ids of the automated scenarios, in run order. */
|
|
7
|
+
export type XRCompatAutomatedScenarioId = "capabilities" | "session-start" | "model-ready" | "model-detects" | "pause-resume" | "stop-start" | "performance";
|
|
8
|
+
/** Ids of the manual (device) scenarios. */
|
|
9
|
+
export type XRCompatManualScenarioId = "permission-prompt" | "permission-blocked" | "rear-camera" | "orientation" | "background-foreground" | "camera-interrupted" | "thermal" | "low-end";
|
|
10
|
+
export type XRCompatScenarioId = XRCompatAutomatedScenarioId | XRCompatManualScenarioId;
|
|
11
|
+
/** One scenario the harness can run (automated) or a person runs (manual). */
|
|
12
|
+
export type XRCompatScenario = {
|
|
13
|
+
id: XRCompatScenarioId;
|
|
14
|
+
title: string;
|
|
15
|
+
/** What a tester does / what the harness does. */
|
|
16
|
+
steps: string;
|
|
17
|
+
/** What must be true. */
|
|
18
|
+
expect: string;
|
|
19
|
+
mode: "automated" | "manual";
|
|
20
|
+
/** The layer this scenario exercises; a failure is attributed here unless the harness knows better. */
|
|
21
|
+
layer: Exclude<XRCompatCause, "unknown">;
|
|
22
|
+
};
|
|
23
|
+
export type XRCompatResult = {
|
|
24
|
+
id: XRCompatScenarioId;
|
|
25
|
+
status: XRCompatStatus;
|
|
26
|
+
cause: XRCompatCause | null;
|
|
27
|
+
/** Machine-readable detail (a fallback code, a model name, a lifecycle state, a number). */
|
|
28
|
+
code: string | null;
|
|
29
|
+
/** Human detail. */
|
|
30
|
+
detail: string;
|
|
31
|
+
durationMs: number;
|
|
32
|
+
/** Free text from a manual tester. */
|
|
33
|
+
notes?: string;
|
|
34
|
+
};
|
|
35
|
+
/** The device under test, as the browser describes it. */
|
|
36
|
+
export type XRCompatEnvironment = {
|
|
37
|
+
userAgent: string;
|
|
38
|
+
platform: string;
|
|
39
|
+
/** Best-effort browser family + major version parsed from the UA. */
|
|
40
|
+
browser: {
|
|
41
|
+
name: string;
|
|
42
|
+
version: string;
|
|
43
|
+
};
|
|
44
|
+
os: {
|
|
45
|
+
name: string;
|
|
46
|
+
version: string;
|
|
47
|
+
};
|
|
48
|
+
mobile: boolean;
|
|
49
|
+
screen: {
|
|
50
|
+
width: number;
|
|
51
|
+
height: number;
|
|
52
|
+
dpr: number;
|
|
53
|
+
};
|
|
54
|
+
deviceMemoryGb: number | null;
|
|
55
|
+
hardwareConcurrency: number | null;
|
|
56
|
+
secureContext: boolean;
|
|
57
|
+
/** `HTMLVideoElement.captureStream` exists (hosted clips can feed the session). */
|
|
58
|
+
videoCaptureStream: boolean;
|
|
59
|
+
touch: boolean;
|
|
60
|
+
};
|
|
61
|
+
export type XRCompatReport = {
|
|
62
|
+
/** Report schema version. */
|
|
63
|
+
version: 1;
|
|
64
|
+
/** Harness identity: SDK version string the app embeds, or "dev". */
|
|
65
|
+
sdkVersion: string;
|
|
66
|
+
/** ISO-8601 wall clock. */
|
|
67
|
+
checkedAt: string;
|
|
68
|
+
/** Free label a tester gives the device ("iPhone 13, iOS 17.5"). */
|
|
69
|
+
label: string;
|
|
70
|
+
environment: XRCompatEnvironment;
|
|
71
|
+
capabilities: XRCapabilities | null;
|
|
72
|
+
results: XRCompatResult[];
|
|
73
|
+
summary: {
|
|
74
|
+
pass: number;
|
|
75
|
+
fail: number;
|
|
76
|
+
skip: number;
|
|
77
|
+
causes: Record<XRCompatCause, number>;
|
|
78
|
+
};
|
|
79
|
+
};
|
|
80
|
+
export type XRCompatRunOptions = {
|
|
81
|
+
/** Models to load and check (default face + hand + body). */
|
|
82
|
+
models?: XRModel[];
|
|
83
|
+
/** Per-step timeout (ms). Default 20000 (model downloads on mobile data). */
|
|
84
|
+
timeoutMs?: number;
|
|
85
|
+
/** Scenario ids to run; default every automated scenario. */
|
|
86
|
+
scenarios?: XRCompatAutomatedScenarioId[];
|
|
87
|
+
/**
|
|
88
|
+
* Leave the session running (webcam open) when the run ends. Default
|
|
89
|
+
* `false`: the harness calls `session.stop()` in a `finally`, releasing
|
|
90
|
+
* the camera; the caller re-binds if it wants to continue.
|
|
91
|
+
*/
|
|
92
|
+
keepSessionRunning?: boolean;
|
|
93
|
+
/** Use this stream instead of opening the webcam (CI, fixtures). */
|
|
94
|
+
stream?: MediaStream;
|
|
95
|
+
/** Performance window (ms). Default 3000. */
|
|
96
|
+
performanceWindowMs?: number;
|
|
97
|
+
/** Progress callback after each result. */
|
|
98
|
+
onResult?: (result: XRCompatResult) => void;
|
|
99
|
+
label?: string;
|
|
100
|
+
sdkVersion?: string;
|
|
101
|
+
};
|
|
@@ -1,4 +1,13 @@
|
|
|
1
1
|
import { PropsWithChildren } from 'react';
|
|
2
|
+
import { BodyTarget } from '../../types/tracking';
|
|
3
|
+
/**
|
|
4
|
+
* MediaPipe Pose landmark indices (33 landmarks). Names follow the
|
|
5
|
+
* person's perspective: `body.leftShoulder` is the *person's* left.
|
|
6
|
+
*
|
|
7
|
+
* `body.neck` is synthesized at runtime as the midpoint of the two
|
|
8
|
+
* shoulders (no native MediaPipe landmark exists for the neck).
|
|
9
|
+
*/
|
|
10
|
+
export declare const BODY_LANDMARK_INDEX: Partial<Record<BodyTarget, number>>;
|
|
2
11
|
type BodyTrackerProps = PropsWithChildren & {
|
|
3
12
|
bodyIndex?: number;
|
|
4
13
|
/**
|
|
@@ -2,6 +2,7 @@ import { ReactNode } from 'react';
|
|
|
2
2
|
import { Transform3DSettings } from '../../Transform3D';
|
|
3
3
|
import { FaceWarp3DSettings } from '../../FaceWarp3D';
|
|
4
4
|
import { FaceMeshAlphaMap, FaceMeshBlendMode, FaceMeshMaskTextureSource, FaceMeshMaterialType, FaceMeshShaderPreset, FaceMeshSide, FaceMeshTextureMap } from '../material/types';
|
|
5
|
+
import { shouldSkipUpdate } from '../../../utils/updateThrottle';
|
|
5
6
|
import { ParsedCanonicalMesh } from './parseCanonicalFaceModel';
|
|
6
7
|
import { CanonicalFaceMeshGeometryKey } from './geometryGroups';
|
|
7
8
|
import * as THREE from "three";
|
|
@@ -54,18 +55,47 @@ export type CanonicalFaceMeshRendererProps = {
|
|
|
54
55
|
meshUrl?: string;
|
|
55
56
|
/** Optional material override, rendered for every visible geometry group. */
|
|
56
57
|
materialOverride?: FaceMeshMaterialOverride;
|
|
58
|
+
/**
|
|
59
|
+
* Cap how often vertex positions follow the landmarks (updates per second).
|
|
60
|
+
* Visibility still tracks face presence every frame. Omit for every frame.
|
|
61
|
+
*/
|
|
62
|
+
maxUpdateFps?: number;
|
|
63
|
+
/**
|
|
64
|
+
* Keep the mesh on its last landmarks for this long (ms) when the tracker
|
|
65
|
+
* drops the face, bridging the one- or two-frame dropouts small or fast
|
|
66
|
+
* faces cause. Default 250, matching `useFaceInfos`. 0 hides the mesh on
|
|
67
|
+
* the first missing frame.
|
|
68
|
+
*/
|
|
69
|
+
holdMs?: number;
|
|
70
|
+
/**
|
|
71
|
+
* While held, move the landmarks along their last smoothed velocity for up
|
|
72
|
+
* to this long (ms) so the mesh keeps pace with a moving subject. Default 0.
|
|
73
|
+
*/
|
|
74
|
+
predictMs?: number;
|
|
57
75
|
};
|
|
58
76
|
export type FaceMeshMaterialOverrideContext = {
|
|
59
77
|
cameraTexture: THREE.Texture | null;
|
|
60
78
|
geometryKey: CanonicalFaceMeshGeometryKey;
|
|
79
|
+
/**
|
|
80
|
+
* Live per-vertex camera-texture UVs, shared by every geometry group and
|
|
81
|
+
* bound to the geometry as the `faceUv` attribute. `null` until the
|
|
82
|
+
* canonical mesh has loaded.
|
|
83
|
+
*/
|
|
84
|
+
faceUv: THREE.BufferAttribute | null;
|
|
85
|
+
/** Static per-vertex lip band position (`attribute float lipEdge`); `null` until the mesh has loaded. */
|
|
86
|
+
lipEdge: THREE.BufferAttribute | null;
|
|
61
87
|
};
|
|
88
|
+
/** A material node, or a three.js material instance to set on the mesh directly (shareable). */
|
|
89
|
+
export type FaceMeshMaterialOverrideResult = ReactNode | THREE.Material;
|
|
62
90
|
/**
|
|
63
91
|
* Runtime-only material escape hatch. Preset settings remain serializable;
|
|
64
|
-
* pass a material node or factory here from JSX or a
|
|
92
|
+
* pass a material node, a material instance, or a factory here from JSX or a
|
|
93
|
+
* scene host instead.
|
|
65
94
|
*/
|
|
66
|
-
export type FaceMeshMaterialOverride =
|
|
95
|
+
export type FaceMeshMaterialOverride = FaceMeshMaterialOverrideResult | ((context: FaceMeshMaterialOverrideContext) => FaceMeshMaterialOverrideResult);
|
|
96
|
+
export { shouldSkipUpdate };
|
|
67
97
|
/**
|
|
68
98
|
* @deprecated Use `FaceMeshRenderer` for scene-object/editor integrations.
|
|
69
99
|
* This remains as the low-level canonical mesh renderer for existing imports.
|
|
70
100
|
*/
|
|
71
|
-
export declare const CanonicalFaceMeshRenderer: ({ faceIndex, baseColor, color, opacity, materialType, shaderPreset, textureMap, alphaMap, alphaOpacity, side, blendMode, blendOpacity, showOverlayMask, showMouthMask, showEyeMask, showLeftEyeMask, showRightEyeMask, showNoseMask, showEyeGeometry, showLeftEyeGeometry, showRightEyeGeometry, showMouthGeometry, showLipsGeometry, showBaseGeometry, showNoseGeometry, maskTextureSource, maskSourceUrl, maskColor, maskOpacity, faceTextureUrl, faceTextureStyle2Url, faceAlphaMaskUrl, compositeShading, faceWarp3D, transform, renderOrder, externalScale, mesh, meshUrl, materialOverride, }: CanonicalFaceMeshRendererProps) => import("react/jsx-runtime").JSX.Element;
|
|
101
|
+
export declare const CanonicalFaceMeshRenderer: ({ faceIndex, baseColor, color, opacity, materialType, shaderPreset, textureMap, alphaMap, alphaOpacity, side, blendMode, blendOpacity, showOverlayMask, showMouthMask, showEyeMask, showLeftEyeMask, showRightEyeMask, showNoseMask, showEyeGeometry, showLeftEyeGeometry, showRightEyeGeometry, showMouthGeometry, showLipsGeometry, showBaseGeometry, showNoseGeometry, maskTextureSource, maskSourceUrl, maskColor, maskOpacity, faceTextureUrl, faceTextureStyle2Url, faceAlphaMaskUrl, compositeShading, faceWarp3D, transform, renderOrder, externalScale, mesh, meshUrl, materialOverride, maxUpdateFps, holdMs, predictMs, }: CanonicalFaceMeshRendererProps) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -2,6 +2,12 @@ export type ParsedCanonicalMesh = {
|
|
|
2
2
|
baseIndices: Uint16Array;
|
|
3
3
|
mouthIndices: Uint16Array;
|
|
4
4
|
lipIndices: Uint16Array;
|
|
5
|
+
/**
|
|
6
|
+
* Per-vertex position across the lip band: 0 on the outer lip ring, 1 on
|
|
7
|
+
* the inner ring (mouth line), interpolated in between; 1 elsewhere. Bound
|
|
8
|
+
* to the geometry as `attribute float lipEdge` for feathering and tints.
|
|
9
|
+
*/
|
|
10
|
+
lipEdgeDistance: Float32Array;
|
|
5
11
|
leftEyeIndices: Uint16Array;
|
|
6
12
|
rightEyeIndices: Uint16Array;
|
|
7
13
|
eyeIndices: Uint16Array;
|
|
@@ -9,10 +15,16 @@ export type ParsedCanonicalMesh = {
|
|
|
9
15
|
uvs: Float32Array;
|
|
10
16
|
vertexCount: number;
|
|
11
17
|
};
|
|
18
|
+
export declare const CANONICAL_OUTER_LIP_RING: number[];
|
|
19
|
+
export declare const CANONICAL_INNER_LIP_RING: number[];
|
|
12
20
|
/**
|
|
13
21
|
* Parse the MediaPipe canonical face OBJ into vertex/UV/index buffers
|
|
14
22
|
* grouped by anatomical region (base / mouth / eye / nose).
|
|
15
23
|
*
|
|
24
|
+
* `lipIndices` is an effect-only overlay: the lip-surface triangles between
|
|
25
|
+
* the outer and inner lip rings. They are also kept in `baseIndices`, so the
|
|
26
|
+
* region groups still tile the whole face.
|
|
27
|
+
*
|
|
16
28
|
* Indices are emitted as Uint16Array — the canonical model has 468
|
|
17
29
|
* vertices and ~900 faces, well within range.
|
|
18
30
|
*/
|