@vincentt-xr/sdk 2.0.0-alpha.7 → 2.0.0-alpha.9

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 (639) hide show
  1. package/GROUNDING.md +5651 -82
  2. package/README.md +1 -0
  3. package/dist/CanonicalHeadFrame-BHcWyaiK.js +1506 -0
  4. package/dist/CanonicalHeadFrame-D-_T1OMU.cjs +1 -0
  5. package/dist/DebuggerUI-7ngnJsBe.js +275 -0
  6. package/dist/DebuggerUI-CoglgKdO.cjs +1 -0
  7. package/dist/FaceRetouch-CLoTfrcs.js +1071 -0
  8. package/dist/FaceRetouch-J1lC1WbS.cjs +134 -0
  9. package/dist/FaceSurface-CHAMEeG1.cjs +1 -0
  10. package/dist/FaceSurface-DmP9AEeC.js +27 -0
  11. package/dist/SegmentationOverlay-D_FWkcyP.cjs +35 -0
  12. package/dist/SegmentationOverlay-vn5x_knv.js +6237 -0
  13. package/dist/SkeletonUtils-C2r90MtN.js +21 -0
  14. package/dist/SkeletonUtils-CddIup1F.cjs +1 -0
  15. package/dist/TextLabel-XE0rQSDn.cjs +2 -0
  16. package/dist/TextLabel-c9BCucOI.js +961 -0
  17. package/dist/assets/cache.d.ts +99 -0
  18. package/dist/assets/estimate.d.ts +11 -0
  19. package/dist/assets/gltfLoader.d.ts +16 -0
  20. package/dist/assets/index.d.ts +7 -0
  21. package/dist/assets/loaders.d.ts +43 -0
  22. package/dist/assets/react.d.ts +33 -0
  23. package/dist/body-pose/index.d.ts +521 -0
  24. package/dist/body-trigger/__fixtures__/syntheticBody.d.ts +83 -0
  25. package/dist/body-trigger/frame.d.ts +88 -0
  26. package/dist/body-trigger/index.d.ts +6 -0
  27. package/dist/body-trigger/moves.d.ts +235 -0
  28. package/dist/body-trigger/trigger.d.ts +75 -0
  29. package/dist/calibration/calibration.d.ts +75 -0
  30. package/dist/calibration/index.d.ts +6 -0
  31. package/dist/calibration/storage.d.ts +13 -0
  32. package/dist/calibration/types.d.ts +53 -0
  33. package/dist/calibration/useXRCalibration.d.ts +46 -0
  34. package/dist/camera/CameraPermissionGate.d.ts +26 -0
  35. package/dist/camera/devices.d.ts +26 -0
  36. package/dist/camera/index.d.ts +8 -0
  37. package/dist/camera/permission.d.ts +86 -0
  38. package/dist/camera/useCameraPermission.d.ts +35 -0
  39. package/dist/canonicalFace-BHwyCx1c.js +9 -0
  40. package/dist/canonicalFace-C83I225R.cjs +1 -0
  41. package/dist/capabilities/detect.d.ts +45 -0
  42. package/dist/capabilities/index.d.ts +5 -0
  43. package/dist/capabilities/types.d.ts +120 -0
  44. package/dist/capabilities/useXRCapabilities.d.ts +18 -0
  45. package/dist/compat/environment.d.ts +5 -0
  46. package/dist/compat/index.d.ts +4 -0
  47. package/dist/compat/run.d.ts +18 -0
  48. package/dist/compat/scenarios.d.ts +10 -0
  49. package/dist/compat/types.d.ts +101 -0
  50. package/dist/components/BodyInstruction/BodyPoseHint.d.ts +63 -0
  51. package/dist/components/BodyInstruction/index.d.ts +69 -0
  52. package/dist/components/BodyInstruction/useBodyPose.d.ts +23 -0
  53. package/dist/components/BodyTracker/index.d.ts +17 -0
  54. package/dist/components/BodyTrigger/index.d.ts +49 -0
  55. package/dist/components/Debugger/DebuggerProvider.d.ts +14 -1
  56. package/dist/components/Debugger/DebuggerUI.d.ts +3 -1
  57. package/dist/components/FaceAtlas/FaceAtlasLayer.d.ts +114 -0
  58. package/dist/components/FaceAtlas/MadeUpCamera.d.ts +80 -0
  59. package/dist/components/FaceAtlas/constants.d.ts +8 -0
  60. package/dist/components/FaceAtlas/index.d.ts +7 -0
  61. package/dist/components/FaceAtlas/useFaceAtlasSurface.d.ts +84 -0
  62. package/dist/components/FaceAtlas/useFaceSkin.d.ts +84 -0
  63. package/dist/components/FaceCharacter/ExternalFaceMesh.d.ts +109 -0
  64. package/dist/components/FaceCharacter/FaceExpressionController.d.ts +53 -0
  65. package/dist/components/FaceCharacter/FaceMorph.d.ts +71 -0
  66. package/dist/components/FaceCharacter/FacePiercing.d.ts +65 -0
  67. package/dist/components/FaceCharacter/FaceReprojection.d.ts +85 -0
  68. package/dist/components/FaceCharacter/FaceRig.d.ts +38 -0
  69. package/dist/components/FaceCharacter/FaceSurface.d.ts +49 -0
  70. package/dist/components/FaceCharacter/FaceSurfaceOccluder.d.ts +39 -0
  71. package/dist/components/FaceCharacter/PinToFaceMesh.d.ts +68 -0
  72. package/dist/components/FaceCharacter/index.d.ts +18 -0
  73. package/dist/components/FaceCharacter/useFaceReprojector.d.ts +10 -0
  74. package/dist/components/FaceInset/FaceInset.d.ts +68 -0
  75. package/dist/components/FaceInset/frame.d.ts +94 -0
  76. package/dist/components/FaceInset/index.d.ts +6 -0
  77. package/dist/components/FaceInset/material.d.ts +40 -0
  78. package/dist/components/FaceInset/useFaceInsetTexture.d.ts +37 -0
  79. package/dist/components/FaceInstruction/FaceExpressionHint.d.ts +43 -0
  80. package/dist/components/FaceInstruction/index.d.ts +56 -0
  81. package/dist/components/FaceInstruction/useFaceExpression.d.ts +20 -0
  82. package/dist/components/FaceLiquify/FaceLiquify.d.ts +49 -0
  83. package/dist/components/FaceLiquify/debug.d.ts +37 -0
  84. package/dist/components/FaceLiquify/frame.d.ts +55 -0
  85. package/dist/components/FaceLiquify/index.d.ts +10 -0
  86. package/dist/components/FaceLiquify/material.d.ts +39 -0
  87. package/dist/components/FaceLiquify/pass.d.ts +49 -0
  88. package/dist/components/FaceLiquify/presence.d.ts +25 -0
  89. package/dist/components/FaceLiquify/presets.d.ts +82 -0
  90. package/dist/components/FaceLiquify/selfTest.d.ts +66 -0
  91. package/dist/components/FaceLiquify/target.d.ts +85 -0
  92. package/dist/components/FaceLiquify/warp.d.ts +72 -0
  93. package/dist/components/FaceMesh/canonical/CanonicalFaceMeshRenderer.d.ts +37 -5
  94. package/dist/components/FaceMesh/canonical/geometryGroups.d.ts +21 -0
  95. package/dist/components/FaceMesh/canonical/parseCanonicalFaceModel.d.ts +21 -0
  96. package/dist/components/FaceMesh/canonical/shaders.d.ts +1 -1
  97. package/dist/components/FaceMesh/index.d.ts +2 -2
  98. package/dist/components/FaceRetouch/Background.d.ts +3 -1
  99. package/dist/components/FaceRetouch/FaceRetouch.d.ts +5 -0
  100. package/dist/components/FaceRetouch/renderState.d.ts +19 -0
  101. package/dist/components/FaceSwap/FaceMirror.d.ts +46 -0
  102. package/dist/components/FaceSwap/FaceSwap.d.ts +58 -0
  103. package/dist/components/FaceSwap/FaceTextureLayer.d.ts +72 -0
  104. package/dist/components/FaceSwap/faceSwapPlan.d.ts +91 -0
  105. package/dist/components/FaceSwap/index.d.ts +13 -0
  106. package/dist/components/FaceSwap/settings.d.ts +300 -0
  107. package/dist/components/FaceSwap/useFaceTexture.d.ts +35 -0
  108. package/dist/components/FaceSwap/useLiveFace.d.ts +38 -0
  109. package/dist/components/FaceSwap/useLiveFaceTexture.d.ts +31 -0
  110. package/dist/components/FaceWarp3D/FaceWarp3D.d.ts +50 -0
  111. package/dist/components/FaceWarp3D/index.d.ts +2 -3
  112. package/dist/components/Faceless/Faceless.d.ts +51 -0
  113. package/dist/components/Faceless/index.d.ts +2 -0
  114. package/dist/components/GestureListener/index.d.ts +11 -0
  115. package/dist/components/HairLock/HairLock.d.ts +39 -0
  116. package/dist/components/HairLock/index.d.ts +2 -0
  117. package/dist/components/HairLock/lockGeometry.d.ts +15 -0
  118. package/dist/components/HandCutout/index.d.ts +35 -0
  119. package/dist/components/HandInstruction/HandGestureHint.d.ts +70 -0
  120. package/dist/components/HandInstruction/index.d.ts +74 -0
  121. package/dist/components/HandInstruction/useHandGesture.d.ts +22 -0
  122. package/dist/components/HandRig/ForearmOccluder.d.ts +29 -0
  123. package/dist/components/HandRig/HandAttachment.d.ts +34 -0
  124. package/dist/components/HandRig/HandOccluder.d.ts +55 -0
  125. package/dist/components/HandRig/HandTattoo.d.ts +61 -0
  126. package/dist/components/HandRig/WristAttachment.d.ts +34 -0
  127. package/dist/components/HandRig/index.d.ts +101 -0
  128. package/dist/components/HandRig/useArmMask.d.ts +29 -0
  129. package/dist/components/HandRig/wristSolve.d.ts +69 -0
  130. package/dist/components/HandTouch/HandTouch.d.ts +62 -0
  131. package/dist/components/HandTouch/Touchable.d.ts +36 -0
  132. package/dist/components/HandTouch/index.d.ts +2 -0
  133. package/dist/components/HandTracker/index.d.ts +10 -0
  134. package/dist/components/HeadBinding/index.d.ts +14 -0
  135. package/dist/components/HeadOccluder/CanonicalHeadFrame.d.ts +22 -0
  136. package/dist/components/HeadOccluder/Earrings.d.ts +55 -0
  137. package/dist/components/HeadOccluder/HeadAttachment.d.ts +38 -0
  138. package/dist/components/HeadOccluder/NeckOccluder.d.ts +64 -0
  139. package/dist/components/HeadOccluder/earringPlacement.d.ts +31 -0
  140. package/dist/components/HeadOccluder/headAttachmentPoints.d.ts +69 -0
  141. package/dist/components/HeadOccluder/index.d.ts +57 -3
  142. package/dist/components/HeadOccluder/useCanonicalHeadFit.d.ts +36 -0
  143. package/dist/components/HeadOccluder/useLandmarkPoseFit.d.ts +80 -0
  144. package/dist/components/HolisticTracker/index.d.ts +69 -0
  145. package/dist/components/HolisticTracker/settings.d.ts +58 -0
  146. package/dist/components/HolisticTracker/signals.d.ts +49 -0
  147. package/dist/components/Instruction/HintStage.d.ts +29 -0
  148. package/dist/components/Instruction/InstructionCue.d.ts +126 -0
  149. package/dist/components/Instruction/gestureHold.d.ts +20 -0
  150. package/dist/components/Instruction/ghost.d.ts +129 -0
  151. package/dist/components/Instruction/hintBlend.d.ts +19 -0
  152. package/dist/components/Instruction/hintLook.d.ts +81 -0
  153. package/dist/components/Instruction/hintLoop.d.ts +36 -0
  154. package/dist/components/Instruction/index.d.ts +41 -0
  155. package/dist/components/Instruction/useGhostModel.d.ts +33 -0
  156. package/dist/components/Instruction/useInstructionHold.d.ts +72 -0
  157. package/dist/components/IrisEffect/IrisMaterial.d.ts +73 -0
  158. package/dist/components/IrisEffect/index.d.ts +51 -0
  159. package/dist/components/IrisEffect/settings.d.ts +117 -0
  160. package/dist/components/LipEffect/LipEffect.d.ts +27 -1
  161. package/dist/components/LipEffect/LipEffectMaterial.d.ts +95 -7
  162. package/dist/components/LipEffect/LipEffects.d.ts +12 -0
  163. package/dist/components/LipEffect/defaults.d.ts +46 -4
  164. package/dist/components/LipEffect/index.d.ts +11 -3
  165. package/dist/components/LipEffect/lipShading.d.ts +73 -0
  166. package/dist/components/LipEffect/settings.d.ts +375 -0
  167. package/dist/components/LipEffect/shader.d.ts +39 -0
  168. package/dist/components/LipEffect/types.d.ts +128 -9
  169. package/dist/components/LipEffect/useLipDesignTextures.d.ts +17 -0
  170. package/dist/components/LipEffect/uvGuide.d.ts +74 -0
  171. package/dist/components/Makeup/Blush.d.ts +18 -0
  172. package/dist/components/Makeup/Brows.d.ts +20 -0
  173. package/dist/components/Makeup/Contour.d.ts +17 -0
  174. package/dist/components/Makeup/Eyeliner.d.ts +20 -0
  175. package/dist/components/Makeup/Eyeshadow.d.ts +20 -0
  176. package/dist/components/Makeup/Highlighter.d.ts +18 -0
  177. package/dist/components/Makeup/MakeupDesign.d.ts +37 -0
  178. package/dist/components/Makeup/MakeupRegion.d.ts +132 -0
  179. package/dist/components/Makeup/constants.d.ts +44 -0
  180. package/dist/components/Makeup/design.d.ts +106 -0
  181. package/dist/components/Makeup/designSamples.d.ts +42 -0
  182. package/dist/components/Makeup/eyes.d.ts +114 -0
  183. package/dist/components/Makeup/fields.d.ts +10 -0
  184. package/dist/components/Makeup/geometry.d.ts +106 -0
  185. package/dist/components/Makeup/index.d.ts +26 -0
  186. package/dist/components/Makeup/looks.d.ts +28 -0
  187. package/dist/components/Makeup/material.d.ts +239 -0
  188. package/dist/components/Makeup/settings.d.ts +54 -0
  189. package/dist/components/Makeup/shades.d.ts +143 -0
  190. package/dist/components/Makeup/shapes.d.ts +27 -0
  191. package/dist/components/Makeup/skinTone.d.ts +135 -0
  192. package/dist/components/Makeup/types.d.ts +110 -0
  193. package/dist/components/Makeup/useMakeupSkinTone.d.ts +40 -0
  194. package/dist/components/Necklace/Necklace.d.ts +44 -0
  195. package/dist/components/Necklace/index.d.ts +1 -0
  196. package/dist/components/ParticleEmitter/ParticleEmitter.d.ts +69 -0
  197. package/dist/components/ParticleEmitter/index.d.ts +1 -0
  198. package/dist/components/PersonCutout/index.d.ts +50 -0
  199. package/dist/components/PersonCutout/personCutout.d.ts +16 -0
  200. package/dist/components/ScreenImage/components/ScreenImageBody.d.ts +1 -1
  201. package/dist/components/ScreenImage/index.d.ts +3 -1
  202. package/dist/components/ScreenImage/materials/ScreenImageBlendMaterial.d.ts +1 -1
  203. package/dist/components/ScreenImage/materials/ScreenImageMaskMaterial.d.ts +11 -0
  204. package/dist/components/ScreenImage/source.d.ts +6 -0
  205. package/dist/components/ScreenImage/types.d.ts +18 -0
  206. package/dist/components/SegmentationOverlay/SegmentationOverlay.d.ts +37 -0
  207. package/dist/components/SegmentationOverlay/SegmentationOverlayMaterial.d.ts +31 -0
  208. package/dist/components/SegmentationOverlay/index.d.ts +9 -0
  209. package/dist/components/SegmentationOverlay/maskTexture.d.ts +23 -0
  210. package/dist/components/SegmentationOverlay/providers.d.ts +72 -0
  211. package/dist/components/SegmentationOverlay/settings.d.ts +65 -0
  212. package/dist/components/ShoulderOccluder/index.d.ts +43 -0
  213. package/dist/components/ShoulderOccluder/useCanonicalTorsoFit.d.ts +24 -0
  214. package/dist/components/SpringSwing/SpringSwing.d.ts +22 -0
  215. package/dist/components/SpringSwing/index.d.ts +1 -0
  216. package/dist/components/XRProvider/index.d.ts +16 -2
  217. package/dist/components/XRScene/renderOutputTarget.d.ts +12 -0
  218. package/dist/components/XRViewport/hooks/useViewportExternalFaces.d.ts +1 -1
  219. package/dist/components/XRViewport/hooks/useViewportMediaSource.d.ts +1 -1
  220. package/dist/components/XRViewport/hooks/useViewportPipeline.d.ts +1 -1
  221. package/dist/components/index.d.ts +11 -0
  222. package/dist/config/index.d.ts +0 -1
  223. package/dist/constants/index.d.ts +4 -1
  224. package/dist/context-DTxSQvp4.js +13 -0
  225. package/dist/context-hA0Rb2Xa.cjs +1 -0
  226. package/dist/contexts-BH7PdKFS.cjs +1 -0
  227. package/dist/contexts-jak8-tND.js +667 -0
  228. package/dist/coordinates/feed.d.ts +52 -0
  229. package/dist/coordinates/index.d.ts +7 -0
  230. package/dist/coordinates/side.d.ts +40 -0
  231. package/dist/coordinates/spaces.d.ts +49 -0
  232. package/dist/coordinates/viewport.d.ts +22 -0
  233. package/dist/coordinates/world.d.ts +15 -0
  234. package/dist/debug-ui/default-setting.cjs +2 -2
  235. package/dist/debug-ui/face-swap-settings/index.d.ts +22 -0
  236. package/dist/debug-ui/gesture-settings/index.d.ts +14 -0
  237. package/dist/debug-ui/hierarchy-panel/index.d.ts +3 -2
  238. package/dist/debug-ui/holistic-tracker-settings/index.d.ts +16 -0
  239. package/dist/debug-ui/index.d.ts +18 -3
  240. package/dist/debug-ui/iris-effect-settings/index.d.ts +12 -0
  241. package/dist/debug-ui/lip-effect-settings/index.d.ts +15 -0
  242. package/dist/debug-ui/media-source/index.d.ts +1 -1
  243. package/dist/debug-ui/media-source/session.d.ts +30 -2
  244. package/dist/debug-ui/media-source.cjs +1 -1
  245. package/dist/debug-ui/media-source.js +1 -1
  246. package/dist/debug-ui/object-inspector-panel/index.d.ts +3 -2
  247. package/dist/debug-ui/product-hotspots/index.d.ts +25 -0
  248. package/dist/debug-ui/scene-editor/hierarchy-panel.d.ts +3 -1
  249. package/dist/debug-ui/scene-editor/inspector-panel.d.ts +3 -1
  250. package/dist/debug-ui/screen-image-settings/index.d.ts +3 -1
  251. package/dist/debug-ui/screen-text-settings/ScreenTextSettingsPanel.d.ts +1 -1
  252. package/dist/debug-ui/screen-text-settings/types.d.ts +2 -0
  253. package/dist/debug-ui/segmentation-overlay-settings/index.d.ts +12 -0
  254. package/dist/debug-ui/settings-panel/index.d.ts +6 -1
  255. package/dist/debug-ui/shared/debugWindow.d.ts +51 -0
  256. package/dist/debug-ui/xr-diagnostics/index.d.ts +26 -0
  257. package/dist/debug-ui.cjs +3 -3
  258. package/dist/debug-ui.js +2695 -2547
  259. package/dist/detector-K8aej4MB.js +59 -0
  260. package/dist/detector-ijypGtse.cjs +1 -0
  261. package/dist/entries/all.d.ts +3 -1
  262. package/dist/entries/core.d.ts +20 -2
  263. package/dist/entries/face-effects.d.ts +123 -9
  264. package/dist/entries/instructions.d.ts +48 -0
  265. package/dist/entries/internal.d.ts +2 -1
  266. package/dist/entries/low-level.d.ts +49 -3
  267. package/dist/entries/particles.d.ts +11 -0
  268. package/dist/entries/product.d.ts +11 -0
  269. package/dist/entries/tracking.d.ts +60 -2
  270. package/dist/face-atlas/attributes.d.ts +30 -0
  271. package/dist/face-atlas/eyes.d.ts +272 -0
  272. package/dist/face-atlas/faceAtlas.generated.d.ts +46 -0
  273. package/dist/face-atlas/glsl/atlasVertex.d.ts +46 -0
  274. package/dist/face-atlas/glsl/common.d.ts +55 -0
  275. package/dist/face-atlas/glsl/design.d.ts +49 -0
  276. package/dist/face-atlas/glsl/eyes.d.ts +73 -0
  277. package/dist/face-atlas/glsl/finish.d.ts +24 -0
  278. package/dist/face-atlas/glsl/format.d.ts +4 -0
  279. package/dist/face-atlas/glsl/index.d.ts +59 -0
  280. package/dist/face-atlas/glsl/shading.d.ts +15 -0
  281. package/dist/face-atlas/glsl/shapes.d.ts +66 -0
  282. package/dist/face-atlas/glsl/sparkle.d.ts +19 -0
  283. package/dist/face-atlas/glsl/uniforms.d.ts +106 -0
  284. package/dist/face-atlas/guide.d.ts +51 -0
  285. package/dist/face-atlas/index.d.ts +25 -0
  286. package/dist/face-atlas/lead.d.ts +117 -0
  287. package/dist/face-atlas/madeUpCamera.d.ts +125 -0
  288. package/dist/face-atlas/masks.d.ts +53 -0
  289. package/dist/face-atlas/obj.d.ts +69 -0
  290. package/dist/face-atlas/polylines.d.ts +63 -0
  291. package/dist/face-atlas/probe/FaceSkinProbe.d.ts +208 -0
  292. package/dist/face-atlas/probe/__fixtures__/emulate.d.ts +9 -0
  293. package/dist/face-atlas/probe/__fixtures__/face.d.ts +24 -0
  294. package/dist/face-atlas/probe/constants.d.ts +137 -0
  295. package/dist/face-atlas/probe/glsl.d.ts +43 -0
  296. package/dist/face-atlas/probe/lightFit.d.ts +108 -0
  297. package/dist/face-atlas/probe/schedule.d.ts +44 -0
  298. package/dist/face-atlas/probe/selfTest.d.ts +87 -0
  299. package/dist/face-atlas/probe/stats.d.ts +143 -0
  300. package/dist/face-atlas/probe/targets.d.ts +70 -0
  301. package/dist/face-atlas/probe/unwrap.d.ts +76 -0
  302. package/dist/face-atlas/quality.d.ts +28 -0
  303. package/dist/face-atlas/regions.d.ts +31 -0
  304. package/dist/face-atlas/registry.d.ts +252 -0
  305. package/dist/face-atlas/renderState.d.ts +86 -0
  306. package/dist/face-atlas/selfOcclusion.d.ts +62 -0
  307. package/dist/face-atlas/shading.d.ts +406 -0
  308. package/dist/face-atlas/shapes.d.ts +86 -0
  309. package/dist/face-atlas/sides.d.ts +41 -0
  310. package/dist/face-atlas/skinMask.d.ts +35 -0
  311. package/dist/face-atlas/surface.d.ts +155 -0
  312. package/dist/face-atlas/topology.d.ts +44 -0
  313. package/dist/face-character/__fixtures__/faceImageDetections.d.ts +25 -0
  314. package/dist/face-character/__fixtures__/faceNode.d.ts +22 -0
  315. package/dist/face-character/bindFaceModel.d.ts +106 -0
  316. package/dist/face-character/canonicalFace.d.ts +17 -0
  317. package/dist/face-character/canonicalFaceGeometry.d.ts +11 -0
  318. package/dist/face-character/canonicalFacePositions.d.ts +7 -0
  319. package/dist/face-character/driveFaceModel.d.ts +57 -0
  320. package/dist/face-character/expressionOutputs.d.ts +45 -0
  321. package/dist/face-character/faceExpressions.d.ts +104 -0
  322. package/dist/face-character/faceImageLandmarker.d.ts +93 -0
  323. package/dist/face-character/faceMeshBinding.d.ts +62 -0
  324. package/dist/face-character/faceMorph.d.ts +77 -0
  325. package/dist/face-character/faceMorphs.d.ts +46 -0
  326. package/dist/face-character/facePhoto.d.ts +138 -0
  327. package/dist/face-character/facePiercings.d.ts +116 -0
  328. package/dist/face-character/facePin.d.ts +131 -0
  329. package/dist/face-character/faceReprojection.d.ts +273 -0
  330. package/dist/face-character/faceReprojector.d.ts +171 -0
  331. package/dist/face-character/faceRig.d.ts +176 -0
  332. package/dist/face-character/faceSwapPresence.d.ts +85 -0
  333. package/dist/face-character/faceTexture.d.ts +169 -0
  334. package/dist/face-character/faceTextureBaker.d.ts +86 -0
  335. package/dist/face-character/faceTextureGuide.d.ts +106 -0
  336. package/dist/face-character/faceTextureStats.d.ts +298 -0
  337. package/dist/face-character/faceTransfer.d.ts +396 -0
  338. package/dist/face-character/faceTransferGeometry.d.ts +109 -0
  339. package/dist/face-character/faceTransferSelfTest.d.ts +94 -0
  340. package/dist/face-character/faceWarp3D.d.ts +101 -0
  341. package/dist/face-character/faceless.d.ts +79 -0
  342. package/dist/face-character/featureWarp.d.ts +28 -0
  343. package/dist/face-character/liveFaceRegistry.d.ts +370 -0
  344. package/dist/face-character/liveValue.d.ts +12 -0
  345. package/dist/face-character/memo.d.ts +15 -0
  346. package/dist/face-effects.cjs +2324 -1
  347. package/dist/face-effects.js +14208 -2268
  348. package/dist/face-expression/index.d.ts +182 -0
  349. package/dist/face-info/landmarks.d.ts +17 -3
  350. package/dist/face-info/types.d.ts +20 -3
  351. package/dist/gestures/definitions.d.ts +98 -0
  352. package/dist/gestures/detector.d.ts +87 -0
  353. package/dist/gestures/index.d.ts +8 -0
  354. package/dist/gestures/measures.d.ts +114 -0
  355. package/dist/gestures/settings.d.ts +49 -0
  356. package/dist/getFaceInfo-B1otSDMX.cjs +1 -0
  357. package/dist/getFaceInfo-Cu4xDWiL.js +62 -0
  358. package/dist/hand/armFit.d.ts +46 -0
  359. package/dist/hand/armMask.d.ts +178 -0
  360. package/dist/hand/handCutout.d.ts +23 -0
  361. package/dist/hand/handCutoutRegistry.d.ts +7 -0
  362. package/dist/hand/handGestures.d.ts +524 -0
  363. package/dist/hand/handPose.d.ts +98 -0
  364. package/dist/hand/handRigSolver.d.ts +159 -0
  365. package/dist/hand/handTattoo.d.ts +81 -0
  366. package/dist/hand/handTouch.d.ts +240 -0
  367. package/dist/hand/wrist.d.ts +44 -0
  368. package/dist/hand/wristFilter.d.ts +44 -0
  369. package/dist/hooks/selectors.d.ts +76 -1
  370. package/dist/hooks/useCalibrationFaceTracker.d.ts +1 -1
  371. package/dist/hooks/useFaceInfo.d.ts +13 -1
  372. package/dist/hooks/useFaceInfos.d.ts +1 -1
  373. package/dist/hooks/useFaceModelAcquisition.d.ts +38 -0
  374. package/dist/hooks/useGesture.d.ts +32 -0
  375. package/dist/hooks/useIrisTracking.d.ts +45 -0
  376. package/dist/hooks/useTrackerContext.d.ts +6 -0
  377. package/dist/hooks/useXRDiagnostics.d.ts +81 -0
  378. package/dist/hooks/useXRModel.d.ts +7 -0
  379. package/dist/hooks/useXRSession/facade.d.ts +42 -2
  380. package/dist/hooks/useXRSession/index.d.ts +2 -2
  381. package/dist/hooks/useXRSession/reason.d.ts +3 -1
  382. package/dist/hooks/useXRSession/registry.d.ts +14 -0
  383. package/dist/hooks/useXRSession/store.d.ts +52 -3
  384. package/dist/index-B1_TzJaI.js +1104 -0
  385. package/dist/index-BavF06C6.js +190 -0
  386. package/dist/index-BfFmpddl.cjs +21 -0
  387. package/dist/index-BuBzneeW.cjs +46 -0
  388. package/dist/index-CGsQWodV.cjs +1 -0
  389. package/dist/index-CIe7eCMH.js +3200 -0
  390. package/dist/index-CfSF8LXa.cjs +1 -0
  391. package/dist/index-D5GTzOzD.cjs +1 -0
  392. package/dist/index-DBhQzvVa.js +314 -0
  393. package/dist/index-DE17y0ZI.cjs +1 -0
  394. package/dist/index-JII7huPk.js +442 -0
  395. package/dist/index-tpCr9CLj.cjs +1 -0
  396. package/dist/index-w1S7fI2B.js +1432 -0
  397. package/dist/index-zGaqrz_K.js +188 -0
  398. package/dist/instructions.cjs +30 -0
  399. package/dist/instructions.js +1507 -0
  400. package/dist/{internal-Dmk1cTXq.js → internal-B90P-clC.js} +138 -119
  401. package/dist/internal-Cjinca64.cjs +1 -0
  402. package/dist/internal.cjs +1 -1
  403. package/dist/internal.js +15 -10
  404. package/dist/iris/compute.d.ts +27 -0
  405. package/dist/iris/index.d.ts +4 -0
  406. package/dist/iris/lead.d.ts +19 -0
  407. package/dist/iris/types.d.ts +89 -0
  408. package/dist/landmarkMask-BFDyBnKM.js +224 -0
  409. package/dist/landmarkMask-u7es2k4X.cjs +1 -0
  410. package/dist/landmarks-BlUqf5MZ.cjs +1 -0
  411. package/dist/landmarks-bftdwq6Z.js +76 -0
  412. package/dist/loaders-BGAUACsd.js +363 -0
  413. package/dist/loaders-BJ1_QCHt.cjs +1 -0
  414. package/dist/low-level.cjs +1 -1
  415. package/dist/low-level.js +1190 -675
  416. package/dist/main.cjs +1 -1
  417. package/dist/main.js +1190 -452
  418. package/dist/models/Base/index.d.ts +49 -0
  419. package/dist/models/Body/index.d.ts +3 -1
  420. package/dist/models/Face/constants.d.ts +8 -0
  421. package/dist/models/Face/index.d.ts +4 -12
  422. package/dist/models/Face/rotation.d.ts +18 -3
  423. package/dist/models/Hand/GestureTracking.d.ts +1 -1
  424. package/dist/models/Hand/HandTracking.d.ts +17 -1
  425. package/dist/models/Holistic/index.d.ts +49 -0
  426. package/dist/models/Holistic/result.d.ts +68 -0
  427. package/dist/models/Segmentation/index.d.ts +2 -0
  428. package/dist/models/SemanticSegmentation/index.d.ts +31 -0
  429. package/dist/models/SemanticSegmentation/presets.d.ts +28 -0
  430. package/dist/models/index.d.ts +2 -0
  431. package/dist/models/nodeSource.d.ts +9 -0
  432. package/dist/particles/emission.d.ts +24 -0
  433. package/dist/particles/eyes.d.ts +24 -0
  434. package/dist/particles/glsl.d.ts +14 -0
  435. package/dist/particles/index.d.ts +10 -0
  436. package/dist/particles/motion.d.ts +42 -0
  437. package/dist/particles/presets.d.ts +12 -0
  438. package/dist/particles/ring.d.ts +58 -0
  439. package/dist/particles/selfTest.d.ts +53 -0
  440. package/dist/particles/settings.d.ts +127 -0
  441. package/dist/particles/shapes.d.ts +29 -0
  442. package/dist/particles/spawner.d.ts +60 -0
  443. package/dist/particles/system.d.ts +64 -0
  444. package/dist/particles.cjs +122 -0
  445. package/dist/particles.js +774 -0
  446. package/dist/product/ProductDimensions.d.ts +16 -0
  447. package/dist/product/ProductHotspot.d.ts +16 -0
  448. package/dist/product/ProductViewer.d.ts +9 -0
  449. package/dist/product/details.d.ts +53 -0
  450. package/dist/product/index.d.ts +14 -0
  451. package/dist/product/loadModelViewer.d.ts +4 -0
  452. package/dist/product/types.d.ts +71 -0
  453. package/dist/product/useProductAr.d.ts +37 -0
  454. package/dist/product/useProductDetails.d.ts +60 -0
  455. package/dist/product.cjs +1 -0
  456. package/dist/product.js +414 -0
  457. package/dist/providers-C8rE26Uf.js +366 -0
  458. package/dist/providers-DHsrhDI2.cjs +62 -0
  459. package/dist/quality/XRQualityController.d.ts +25 -0
  460. package/dist/quality/controller.d.ts +33 -0
  461. package/dist/quality/index.d.ts +6 -0
  462. package/dist/quality/types.d.ts +100 -0
  463. package/dist/quality/useXRQuality.d.ts +28 -0
  464. package/dist/render/renderPasses.d.ts +8 -0
  465. package/dist/render/sceneBeforeRender.d.ts +12 -0
  466. package/dist/{renderGroups-KZk6eRiY.js → renderGroups-B38pUaX2.js} +1 -1
  467. package/dist/{renderGroups-80H3DpTl.cjs → renderGroups-Cb_4Ar1Q.cjs} +1 -1
  468. package/dist/renderPasses-B6l8IpJv.js +1290 -0
  469. package/dist/renderPasses-dqmkft4P.cjs +158 -0
  470. package/dist/renderState-CJNmj5jz.js +39 -0
  471. package/dist/renderState-apSfg4eR.cjs +1 -0
  472. package/dist/scene-object.cjs +1 -1
  473. package/dist/scene-object.js +2 -2
  474. package/dist/segmentation-Cb3ouK6Z.js +1758 -0
  475. package/dist/segmentation-D9pYO6aR.cjs +1 -0
  476. package/dist/segmentation2d/faceMemory.d.ts +28 -0
  477. package/dist/segmentation2d/faceRegions.d.ts +24 -0
  478. package/dist/segmentation2d/index.d.ts +9 -0
  479. package/dist/segmentation2d/maskUv.d.ts +23 -0
  480. package/dist/segmentation2d/rasterize.d.ts +14 -0
  481. package/dist/segmentation2d/types.d.ts +52 -0
  482. package/dist/select-Ck5LGz-J.cjs +1 -0
  483. package/dist/select-pYRo_win.js +233 -0
  484. package/dist/selectors-C4X71aoD.cjs +1 -0
  485. package/dist/selectors-DmNaKIwE.js +196 -0
  486. package/dist/session-BrH8G7iJ.cjs +31 -0
  487. package/dist/session-DgA_z6O1.js +418 -0
  488. package/dist/settings-BJ7FMBsO.js +111 -0
  489. package/dist/settings-C63FMBlF.cjs +1 -0
  490. package/dist/similarityFit-BFqHND2e.cjs +1 -0
  491. package/dist/similarityFit-Bbz-R8AY.js +91 -0
  492. package/dist/spring/index.d.ts +2 -0
  493. package/dist/spring/spring.d.ts +69 -0
  494. package/dist/spring/swing.d.ts +54 -0
  495. package/dist/subjects/index.d.ts +2 -0
  496. package/dist/subjects/select.d.ts +62 -0
  497. package/dist/subjects/types.d.ts +55 -0
  498. package/dist/tracking-config/apply.d.ts +57 -0
  499. package/dist/tracking-config/index.d.ts +7 -0
  500. package/dist/tracking-config/resolve.d.ts +25 -0
  501. package/dist/tracking-config/storage.d.ts +8 -0
  502. package/dist/tracking-config/types.d.ts +106 -0
  503. package/dist/tracking-config/useXRTrackingConfig.d.ts +38 -0
  504. package/dist/tracking.cjs +10 -1
  505. package/dist/tracking.js +1326 -506
  506. package/dist/trigger-D0Pm9noT.cjs +49 -0
  507. package/dist/trigger-IQeys0oS.js +2128 -0
  508. package/dist/types/compositor.d.ts +21 -0
  509. package/dist/types/face.d.ts +20 -1
  510. package/dist/types/hand-tracking.d.ts +9 -0
  511. package/dist/types/holistic.d.ts +121 -0
  512. package/dist/types/index.d.ts +1 -0
  513. package/dist/types/model.d.ts +22 -2
  514. package/dist/types/nodes.d.ts +47 -3
  515. package/dist/types/segmentation.d.ts +24 -0
  516. package/dist/types/session.d.ts +41 -3
  517. package/dist/updateThrottle-BseecYag.js +4 -0
  518. package/dist/updateThrottle-Of5Y4SVa.cjs +1 -0
  519. package/dist/useFaceInfo-BHDNCvsJ.cjs +1 -0
  520. package/dist/useFaceInfo-J4x7LsqL.js +76 -0
  521. package/dist/useFaceResultReader-BvEo5REG.js +61 -0
  522. package/dist/useFaceResultReader-DuaL1KJG.cjs +1 -0
  523. package/dist/useInstructionHold-DOu-RpCM.js +53 -0
  524. package/dist/useInstructionHold-DwJY1Alr.cjs +1 -0
  525. package/dist/useLandmarkPoseFit-Bg-h9BPb.cjs +1 -0
  526. package/dist/useLandmarkPoseFit-Bmb3h6Mw.js +87 -0
  527. package/dist/useXRCapabilities-Cr3RzuAW.cjs +1 -0
  528. package/dist/useXRCapabilities-Cxmlmpbd.js +30 -0
  529. package/dist/utils/canonicalRigidLandmarks.d.ts +8 -0
  530. package/dist/utils/fns.d.ts +6 -3
  531. package/dist/utils/headOccluderFit.d.ts +42 -0
  532. package/dist/utils/integrity.d.ts +21 -1
  533. package/dist/utils/resolveNumFaces.d.ts +13 -0
  534. package/dist/utils/shoulderOccluderFit.d.ts +38 -0
  535. package/dist/utils/similarityFit.d.ts +23 -0
  536. package/dist/utils/updateThrottle.d.ts +2 -0
  537. package/dist/utils/useStableUniforms.d.ts +18 -0
  538. package/dist/uv-BMFt19bg.cjs +1 -0
  539. package/dist/{index-ByoNj0QP.js → uv-DJU_XfmN.js} +15 -247
  540. package/docs/SDK_DOCUMENTATION.md +1 -2
  541. package/docs/api/adaptive-quality.mdx +104 -0
  542. package/docs/api/asset-lifecycle.mdx +78 -0
  543. package/docs/api/body-instructions.mdx +285 -0
  544. package/docs/api/body-triggers.mdx +234 -0
  545. package/docs/api/camera-permission.mdx +142 -0
  546. package/docs/api/coordinate-spaces.mdx +168 -0
  547. package/docs/api/cross-camera.mdx +89 -0
  548. package/docs/api/debug-ui-scene-editor.mdx +23 -2
  549. package/docs/api/diagnostics-calibration.mdx +97 -0
  550. package/docs/api/external-face-mesh.mdx +231 -0
  551. package/docs/api/face-actions.mdx +20 -16
  552. package/docs/api/face-attribute-expression.mdx +1 -1
  553. package/docs/api/face-binding-anchors.mdx +4 -2
  554. package/docs/api/face-character.mdx +157 -0
  555. package/docs/api/face-effects.mdx +9 -0
  556. package/docs/api/face-expression-controller.mdx +153 -0
  557. package/docs/api/face-info.mdx +17 -11
  558. package/docs/api/face-inset.mdx +204 -0
  559. package/docs/api/face-instructions.mdx +183 -0
  560. package/docs/api/face-liquify.mdx +196 -0
  561. package/docs/api/face-mesh.mdx +8 -9
  562. package/docs/api/face-morph.mdx +117 -0
  563. package/docs/api/face-painting.mdx +7 -0
  564. package/docs/api/face-reprojection.mdx +154 -0
  565. package/docs/api/face-retouching.mdx +18 -10
  566. package/docs/api/face-swap.mdx +350 -0
  567. package/docs/api/face-warp-3d.mdx +166 -0
  568. package/docs/api/faceless.mdx +143 -0
  569. package/docs/api/gestures.mdx +209 -0
  570. package/docs/api/hair.mdx +97 -0
  571. package/docs/api/hand-instructions.mdx +222 -0
  572. package/docs/api/hand-rig.mdx +535 -0
  573. package/docs/api/hand-touch.mdx +162 -0
  574. package/docs/api/head-occluder.mdx +563 -0
  575. package/docs/api/holistic-tracker.mdx +164 -0
  576. package/docs/api/instructions.mdx +323 -0
  577. package/docs/api/iris-tracking.mdx +247 -0
  578. package/docs/api/made-up-camera.mdx +131 -0
  579. package/docs/api/makeup-skin-tone.mdx +135 -0
  580. package/docs/api/makeup.mdx +353 -0
  581. package/docs/api/multi-subject.mdx +98 -0
  582. package/docs/api/particles.mdx +155 -0
  583. package/docs/api/person-cutout.mdx +136 -0
  584. package/docs/api/pin-to-face-mesh.mdx +274 -0
  585. package/docs/api/product-ar.mdx +114 -0
  586. package/docs/api/product-details.mdx +78 -0
  587. package/docs/api/screen-space-coordinates.mdx +4 -1
  588. package/docs/api/segmentation-overlay.mdx +301 -0
  589. package/docs/api/session-lifecycle.mdx +136 -0
  590. package/docs/api/trackers.mdx +5 -0
  591. package/docs/api/tracking-config.mdx +108 -0
  592. package/docs/docs.json +51 -1
  593. package/docs/examples/lip-shaders.mdx +273 -0
  594. package/docs/guides/face-atlas-template.svg +1 -0
  595. package/docs/guides/face-atlas-textures.mdx +186 -0
  596. package/docs/guides/face-texture-template.svg +1 -0
  597. package/docs/guides/harness-debug-ui.mdx +4 -4
  598. package/docs/guides/lip-effect-textures.mdx +368 -0
  599. package/docs/guides/lip-uv-template.png +0 -0
  600. package/docs/guides/lip-uv-template.svg +1 -0
  601. package/docs/guides/makeup-design-textures.mdx +109 -0
  602. package/docs/introduction.mdx +1 -2
  603. package/package.json +23 -1
  604. package/dist/DebuggerUI-B6bP6P9r.cjs +0 -1
  605. package/dist/DebuggerUI-BjOMr8q_.js +0 -269
  606. package/dist/FaceMeshRenderer-C5l6VLdO.cjs +0 -155
  607. package/dist/FaceMeshRenderer-wjAHrJzP.js +0 -1270
  608. package/dist/FaceRetouch-BkJzoA79.cjs +0 -134
  609. package/dist/FaceRetouch-DwbKQJAN.js +0 -551
  610. package/dist/components/FaceWarp3D/FaceWarp3DHead.d.ts +0 -15
  611. package/dist/components/FaceWarp3D/defaults.d.ts +0 -37
  612. package/dist/components/FaceWarp3D/warp.d.ts +0 -13
  613. package/dist/contexts-ByhzppYl.js +0 -663
  614. package/dist/contexts-Dr62It_K.cjs +0 -1
  615. package/dist/debug-ui/face-warp-3d/index.d.ts +0 -6
  616. package/dist/getFaceInfo-C4QpCQIY.js +0 -118
  617. package/dist/getFaceInfo-fA1bFBub.cjs +0 -1
  618. package/dist/index-9dlAQAhy.js +0 -1462
  619. package/dist/index-BjmTe9eM.cjs +0 -1
  620. package/dist/index-BpEf2BBb.cjs +0 -1
  621. package/dist/index-CyUUurQT.cjs +0 -1
  622. package/dist/index-DCiMbxC3.cjs +0 -1
  623. package/dist/index-DXT3WccE.js +0 -2089
  624. package/dist/index-DpI-qo5X.cjs +0 -17
  625. package/dist/index-DyVF4vEW.js +0 -111
  626. package/dist/index-VJ0SJwmG.js +0 -214
  627. package/dist/internal-Cq-TEQ5Y.cjs +0 -1
  628. package/dist/renderLayers-lDtL0_43.cjs +0 -1
  629. package/dist/renderLayers-zrK2pv5O.js +0 -13
  630. package/dist/renderPasses-BOoBSr8z.cjs +0 -21
  631. package/dist/renderPasses-BcquyVtu.js +0 -1500
  632. package/dist/selectors-B8H97CKA.js +0 -59
  633. package/dist/selectors-CZLKT2Iv.cjs +0 -1
  634. package/dist/session-CpkiK5YA.cjs +0 -31
  635. package/dist/session-DLFN_VII.js +0 -363
  636. package/dist/useFaceInfo-BJ8-_MOs.cjs +0 -1
  637. package/dist/useFaceInfo-Dk426LTu.js +0 -62
  638. package/dist/useFaceResults-CtetsO9M.js +0 -19
  639. package/dist/useFaceResults-wBJF3zyp.cjs +0 -1
@@ -0,0 +1,3200 @@
1
+ var cs = Object.defineProperty;
2
+ var ls = (e, s, t) => s in e ? cs(e, s, { enumerable: !0, configurable: !0, writable: !0, value: t }) : e[s] = t;
3
+ var u = (e, s, t) => ls(e, typeof s != "symbol" ? s + "" : s, t);
4
+ import { jsxs as ds, jsx as rt } from "react/jsx-runtime";
5
+ import { useRef as oe, useMemo as ge, useEffect as he, useContext as Be, useCallback as at, createElement as hs, createContext as gt, useState as us } from "react";
6
+ import { FilesetResolver as Q, PoseLandmarker as ms, FaceLandmarker as fs, GestureRecognizer as gs, HolisticLandmarker as ps, HandLandmarker as ys, ImageSegmenter as pt, DrawingUtils as ws } from "@mediapipe/tasks-vision";
7
+ import * as B from "three";
8
+ import { RGBAFormat as yt, LinearFilter as ve, CanvasTexture as wt, SRGBColorSpace as vs } from "three";
9
+ const z = {
10
+ // Pinned to the CDN, NOT build-env-driven: a stale VITE_ASSET_STORAGE_ENDPOINT
11
+ // baked a now-deleted CloudFront domain into every published bundle, breaking
12
+ // WASM/model loads at runtime. The host must never come from a mutable env value.
13
+ assetStorageEndpoint: "https://cdn.vincentt.studio",
14
+ // Versioned bucket for SDK-shipped reference assets (canonical face model, face textures, etc.).
15
+ sdkAssetsBaseUrl: "https://cdn.vincentt.studio/assets/sdk/face/v1",
16
+ loggerPrefix: "[vincentt-xr]:",
17
+ sessionCheckInterval: 3e4
18
+ };
19
+ var F = /* @__PURE__ */ ((e) => (e.WEBCAM = "webcam", e.STREAM = "stream", e.CANVAS = "canvas", e))(F || {}), R = /* @__PURE__ */ ((e) => (e.HAND_TRACKER = "vincentt.xr.hand-tracker", e.GESTURE_TRACKER = "vincentt.xr.gesture-tracker", e.FACE_TRACKER = "vincentt.xr.face-tracker", e.BODY_TRACKER = "vincentt.xr.body-tracker", e.HOLISTIC_TRACKER = "vincentt.xr.holistic-tracker", e.BACKGROUND_SEGMENTATION = "vincentt.xr.background-segmentation", e.SEMANTIC_SEGMENTATION = "vincentt.xr.semantic-segmentation", e))(R || {});
20
+ const Ie = (e) => Array.from({ length: e }, () => ({ x: 0, y: 0, z: 0 }));
21
+ class Ss {
22
+ constructor(s) {
23
+ u(this, "slots", []);
24
+ this.options = s;
25
+ }
26
+ setOptions(s) {
27
+ this.options = s;
28
+ }
29
+ /** Landmark sets to draw this frame: live faces, plus held/predicted ones. */
30
+ update(s, t) {
31
+ const { holdMs: n, predictMs: r, maxVelocityGapMs: a = 250 } = this.options, c = [], o = Math.max(s.length, this.slots.length);
32
+ for (let d = 0; d < o; d += 1) {
33
+ const l = s[d], h = this.slots[d] ?? null;
34
+ if (l && l.length > 0) {
35
+ const S = h && h.points.length === l.length ? h : null, M = S ?? {
36
+ points: Ie(l.length),
37
+ velocity: Ie(l.length),
38
+ lastSeen: t,
39
+ output: Ie(l.length)
40
+ }, C = (t - M.lastSeen) / 1e3, E = S !== null && C > 0 && C * 1e3 <= a;
41
+ for (let _ = 0; _ < l.length; _ += 1) {
42
+ const g = l[_], v = M.points[_], w = M.velocity[_], x = g.z ?? 0;
43
+ E ? (w.x = 0.5 * w.x + 0.5 * ((g.x - v.x) / C), w.y = 0.5 * w.y + 0.5 * ((g.y - v.y) / C), w.z = 0.5 * w.z + 0.5 * ((x - v.z) / C)) : (w.x = 0, w.y = 0, w.z = 0), v.x = g.x, v.y = g.y, v.z = x;
44
+ }
45
+ M.lastSeen = t, this.slots[d] = M, c.push(l);
46
+ continue;
47
+ }
48
+ if (!h) continue;
49
+ const m = t - h.lastSeen;
50
+ if (m > n) {
51
+ this.slots[d] = null;
52
+ continue;
53
+ }
54
+ const y = Math.max(0, Math.min(m, r)) / 1e3;
55
+ for (let S = 0; S < h.points.length; S += 1)
56
+ h.output[S].x = h.points[S].x + h.velocity[S].x * y, h.output[S].y = h.points[S].y + h.velocity[S].y * y, h.output[S].z = h.points[S].z + h.velocity[S].z * y;
57
+ c.push(h.output);
58
+ }
59
+ for (; this.slots.length > 0 && this.slots[this.slots.length - 1] === null; ) this.slots.pop();
60
+ return c;
61
+ }
62
+ reset() {
63
+ this.slots = [];
64
+ }
65
+ }
66
+ const ue = (e, s = { x: 0, y: 0, z: 0 }) => (s.x = e.x * 2 - 1, s.y = 1 - e.y * 2, s.z = -e.z, s), fr = (e, s = { x: 0, y: 0, z: 0 }) => (s.x = (e.x + 1) / 2, s.y = (1 - e.y) / 2, s.z = -e.z, s), vt = "https://storage.googleapis.com/mediapipe-models/holistic_landmarker/holistic_landmarker/float16/latest/holistic_landmarker.task", Ms = 250, Cs = 0, ks = 768, Ne = (e) => ({
67
+ hands: (e == null ? void 0 : e.hands) ?? "both",
68
+ analysisMaxDimension: (e == null ? void 0 : e.analysisMaxDimension) ?? ks,
69
+ holdMs: (e == null ? void 0 : e.holdMs) ?? Ms,
70
+ predictMs: (e == null ? void 0 : e.predictMs) ?? Cs
71
+ }), xs = () => ({
72
+ version: 0,
73
+ timestampMs: 0,
74
+ face: null,
75
+ leftHand: null,
76
+ rightHand: null,
77
+ pose: null
78
+ }), it = [
79
+ 0,
80
+ 4,
81
+ 5,
82
+ 6,
83
+ 1,
84
+ 2,
85
+ 3,
86
+ 8,
87
+ 7,
88
+ 10,
89
+ 9,
90
+ 12,
91
+ 11,
92
+ 14,
93
+ 13,
94
+ 16,
95
+ 15,
96
+ 18,
97
+ 17,
98
+ 20,
99
+ 19,
100
+ 22,
101
+ 21,
102
+ 24,
103
+ 23,
104
+ 26,
105
+ 25,
106
+ 28,
107
+ 27,
108
+ 30,
109
+ 29,
110
+ 32,
111
+ 31
112
+ ], ot = (e, s) => {
113
+ if (e.length !== it.length) return e;
114
+ s.length = e.length;
115
+ for (let t = 0; t < e.length; t += 1) s[t] = e[it[t]];
116
+ return s;
117
+ };
118
+ class we {
119
+ constructor(s, t) {
120
+ u(this, "memory");
121
+ u(this, "holdMs");
122
+ u(this, "lastLiveMs", -1 / 0);
123
+ u(this, "lastConfidence", 0);
124
+ this.holdMs = s, this.memory = new Ss({ holdMs: s, predictMs: t });
125
+ }
126
+ setOptions(s, t) {
127
+ this.holdMs = s, this.memory.setOptions({ holdMs: s, predictMs: t });
128
+ }
129
+ reset() {
130
+ this.memory.reset(), this.lastLiveMs = -1 / 0, this.lastConfidence = 0;
131
+ }
132
+ /**
133
+ * Returns the landmarks to publish this frame (live, or replayed from
134
+ * memory), or `undefined` when the stream is neither detected nor held.
135
+ * A held stream's confidence decays linearly from the last live value to
136
+ * 0 at `holdMs`.
137
+ */
138
+ bridge(s, t, n) {
139
+ const r = s !== void 0 && s.length > 0, a = this.memory.update(r ? [s] : [], n)[0];
140
+ if (!a) return;
141
+ if (r)
142
+ return this.lastLiveMs = n, this.lastConfidence = t, { points: a, held: !1, confidence: t };
143
+ const c = n - this.lastLiveMs, o = this.holdMs > 0 ? Math.max(0, 1 - c / this.holdMs) : 0;
144
+ return { points: a, held: !0, confidence: this.lastConfidence * o };
145
+ }
146
+ }
147
+ const ae = (e, s, t) => {
148
+ for (e.length > s && (e.length = s); e.length < s; ) e.push(t());
149
+ return e;
150
+ }, _e = (e, s) => {
151
+ e.x = s.x, e.y = s.y, e.z = s.z;
152
+ }, bs = (e) => {
153
+ if (e.length === 0) return 0;
154
+ let s = 0;
155
+ for (let t = 0; t < e.length; t += 1) s += e[t].visibility ?? 0;
156
+ return s / e.length;
157
+ };
158
+ class Ts {
159
+ constructor(s) {
160
+ u(this, "options", Ne());
161
+ u(this, "faceMemory", new we(this.options.holdMs, this.options.predictMs));
162
+ u(this, "leftHandMemory", new we(this.options.holdMs, this.options.predictMs));
163
+ u(this, "rightHandMemory", new we(this.options.holdMs, this.options.predictMs));
164
+ u(this, "poseMemory", new we(this.options.holdMs, this.options.predictMs));
165
+ u(this, "face", {
166
+ landmarks: [],
167
+ blendshapes: {},
168
+ confidence: 0,
169
+ held: !1
170
+ });
171
+ u(this, "leftHand", {
172
+ handedness: "left",
173
+ landmarks: [],
174
+ worldLandmarks: [],
175
+ confidence: 0,
176
+ held: !1
177
+ });
178
+ u(this, "rightHand", {
179
+ handedness: "right",
180
+ landmarks: [],
181
+ worldLandmarks: [],
182
+ confidence: 0,
183
+ held: !1
184
+ });
185
+ u(this, "poseScratch", []);
186
+ u(this, "poseWorldScratch", []);
187
+ u(this, "pose", {
188
+ landmarks: [],
189
+ worldLandmarks: [],
190
+ visibility: [],
191
+ confidence: 0,
192
+ held: !1
193
+ });
194
+ this.setOptions(s);
195
+ }
196
+ getOptions() {
197
+ return this.options;
198
+ }
199
+ setOptions(s) {
200
+ this.options = Ne({ ...this.options, ...s });
201
+ const { holdMs: t, predictMs: n } = this.options;
202
+ for (const r of this.memories()) r.setOptions(t, n);
203
+ }
204
+ reset() {
205
+ for (const s of this.memories()) s.reset();
206
+ }
207
+ memories() {
208
+ return [this.faceMemory, this.leftHandMemory, this.rightHandMemory, this.poseMemory];
209
+ }
210
+ /**
211
+ * Publish `raw` (or a miss when `undefined`) into `result` at `nowMs`.
212
+ *
213
+ * `mirrored` says the analysed frame is a mirror of the person (the
214
+ * session's webcam feed). Pose left/right follow the image, and holistic
215
+ * assigns hands from the pose, so on a mirrored frame MediaPipe's "left"
216
+ * is the person's right. Swap both the hands and the pose's left/right
217
+ * landmarks so the whole result is anatomical and self-consistent
218
+ * (`leftHand` and pose wrist 15 are the same physical hand), matching the
219
+ * convention `HandTracker` reports on that feed.
220
+ */
221
+ update(s, t, n, r = !1) {
222
+ var l, h, m, y;
223
+ n.face = this.updateFace(s, t);
224
+ const a = {
225
+ landmarks: (l = s == null ? void 0 : s.leftHandLandmarks) == null ? void 0 : l[0],
226
+ world: (h = s == null ? void 0 : s.leftHandWorldLandmarks) == null ? void 0 : h[0]
227
+ }, c = {
228
+ landmarks: (m = s == null ? void 0 : s.rightHandLandmarks) == null ? void 0 : m[0],
229
+ world: (y = s == null ? void 0 : s.rightHandWorldLandmarks) == null ? void 0 : y[0]
230
+ }, o = r ? c : a, d = r ? a : c;
231
+ return n.leftHand = this.updateHand("left", o.landmarks, o.world, t), n.rightHand = this.updateHand("right", d.landmarks, d.world, t), n.pose = this.updatePose(s, t, r), n.timestampMs = t, n.version += 1, n;
232
+ }
233
+ updateFace(s, t) {
234
+ var o, d, l, h;
235
+ const n = (o = s == null ? void 0 : s.faceLandmarks) == null ? void 0 : o[0], r = this.faceMemory.bridge(n, 1, t);
236
+ if (!r) return null;
237
+ const { face: a } = this, c = !r.held && n;
238
+ ae(a.landmarks, r.points.length, () => ({
239
+ x: 0,
240
+ y: 0,
241
+ z: 0,
242
+ visibility: 0
243
+ }));
244
+ for (let m = 0; m < r.points.length; m += 1) {
245
+ const y = a.landmarks[m];
246
+ _e(y, r.points[m]), y.visibility = c ? ((d = n[m]) == null ? void 0 : d.visibility) ?? 0 : 0;
247
+ }
248
+ if (c) {
249
+ const m = (h = (l = s == null ? void 0 : s.faceBlendshapes) == null ? void 0 : l[0]) == null ? void 0 : h.categories;
250
+ if (m)
251
+ for (const y of m) a.blendshapes[y.categoryName] = y.score;
252
+ }
253
+ return a.confidence = r.confidence, a.held = r.held, a;
254
+ }
255
+ updateHand(s, t, n, r) {
256
+ const a = s === "left" ? this.leftHandMemory : this.rightHandMemory, { hands: c } = this.options;
257
+ if (c === "none" || c !== "both" && c !== s)
258
+ return a.reset(), null;
259
+ const o = a.bridge(t, 1, r);
260
+ if (!o) return null;
261
+ const d = s === "left" ? this.leftHand : this.rightHand;
262
+ ae(d.landmarks, o.points.length, () => ({ x: 0, y: 0, z: 0 }));
263
+ for (let l = 0; l < o.points.length; l += 1)
264
+ ue(o.points[l], d.landmarks[l]);
265
+ if (!o.held && n) {
266
+ ae(d.worldLandmarks, n.length, () => ({ x: 0, y: 0, z: 0 }));
267
+ for (let l = 0; l < n.length; l += 1) _e(d.worldLandmarks[l], n[l]);
268
+ }
269
+ return d.confidence = o.confidence, d.held = o.held, d;
270
+ }
271
+ updatePose(s, t, n) {
272
+ var m, y, S;
273
+ const r = (m = s == null ? void 0 : s.poseLandmarks) == null ? void 0 : m[0], a = r && n ? ot(r, this.poseScratch) : r, c = this.poseMemory.bridge(a, a ? bs(a) : 0, t);
274
+ if (!c) return null;
275
+ const { pose: o } = this, d = !c.held && a;
276
+ ae(o.landmarks, c.points.length, () => ({ x: 0, y: 0, z: 0 })), ae(o.visibility, c.points.length, () => 0);
277
+ for (let M = 0; M < c.points.length; M += 1)
278
+ ue(c.points[M], o.landmarks[M]), d && (o.visibility[M] = ((y = a[M]) == null ? void 0 : y.visibility) ?? 0);
279
+ const l = (S = s == null ? void 0 : s.poseWorldLandmarks) == null ? void 0 : S[0], h = l && n ? ot(l, this.poseWorldScratch) : l;
280
+ if (d && h) {
281
+ ae(o.worldLandmarks, h.length, () => ({ x: 0, y: 0, z: 0 }));
282
+ for (let M = 0; M < h.length; M += 1) _e(o.worldLandmarks[M], h[M]);
283
+ }
284
+ return o.confidence = c.confidence, o.held = c.held, o;
285
+ }
286
+ }
287
+ const St = {
288
+ "camera-permission-denied": "Camera access was blocked. Allow camera permissions in your browser, then refresh.",
289
+ "camera-in-use": "Camera is already in use by another app or browser tab. Close it and refresh.",
290
+ "no-camera": "No camera was found on this device.",
291
+ "camera-insecure-context": "Camera access needs HTTPS (or localhost). Open the page over HTTPS.",
292
+ "camera-unsupported": "This browser cannot open the camera.",
293
+ "camera-lost": "The camera stopped sending frames (disconnected, revoked, or taken by another app).",
294
+ "webgl-unavailable": "WebGL is unavailable, so nothing can render or track.",
295
+ "offscreen-canvas-unavailable": "OffscreenCanvas is unavailable; the tracker feed cannot be built.",
296
+ "wasm-unavailable": "WebAssembly is unavailable; the tracking engine cannot load.",
297
+ "model-unreachable": "The tracker model could not be downloaded.",
298
+ "model-integrity": "The tracker model failed its integrity check.",
299
+ "model-init-failed": "The tracker failed to initialize on this device.",
300
+ "placement-unsupported": "This device cannot place 3D objects in the room (no WebXR, Scene Viewer or Quick Look).",
301
+ unknown: "Tracking is unavailable for an unknown reason."
302
+ }, Es = {
303
+ "camera-permission-denied": !0,
304
+ "camera-in-use": !0,
305
+ "no-camera": !1,
306
+ "camera-insecure-context": !1,
307
+ "camera-unsupported": !1,
308
+ "camera-lost": !0,
309
+ "webgl-unavailable": !1,
310
+ "offscreen-canvas-unavailable": !1,
311
+ "wasm-unavailable": !1,
312
+ "model-unreachable": !0,
313
+ "model-integrity": !1,
314
+ "model-init-failed": !1,
315
+ "placement-unsupported": !1,
316
+ unknown: !0
317
+ }, I = (e, s = St[e]) => ({ code: e, message: s, recoverable: Es[e] }), As = {
318
+ [R.FACE_TRACKER]: "/assets/xr/models/face_tracking.task",
319
+ [R.HAND_TRACKER]: "/assets/xr/models/hand_tracking.task",
320
+ [R.GESTURE_TRACKER]: "/assets/xr/models/gesture_tracking.task",
321
+ [R.BODY_TRACKER]: "/assets/xr/models/body_tracking.task",
322
+ [R.BACKGROUND_SEGMENTATION]: "/assets/xr/models/segmentation.tflite",
323
+ [R.SEMANTIC_SEGMENTATION]: "/assets/xr/models/selfie_multiclass_256x256.tflite",
324
+ [R.HOLISTIC_TRACKER]: vt
325
+ }, Mt = (e) => {
326
+ const s = As[e];
327
+ return s ? /^https?:/.test(s) ? s : new URL(s, z.assetStorageEndpoint).toString() : null;
328
+ }, Rs = Object.values(R), Fs = () => {
329
+ var t, n, r;
330
+ const e = typeof window < "u", s = typeof document < "u";
331
+ return {
332
+ navigator: typeof navigator < "u" ? navigator : void 0,
333
+ isSecureContext: e ? window.isSecureContext : void 0,
334
+ createCanvas: s ? () => document.createElement("canvas") : void 0,
335
+ offscreenCanvas: typeof OffscreenCanvas < "u",
336
+ wasm: typeof WebAssembly < "u",
337
+ fetch: typeof fetch < "u" ? fetch.bind(globalThis) : void 0,
338
+ now: () => typeof performance < "u" ? performance.now() : Date.now(),
339
+ xrSessionSupported: typeof navigator < "u" && ((t = navigator.xr) != null && t.isSessionSupported) ? (a) => navigator.xr.isSessionSupported(a).catch(() => !1) : void 0,
340
+ relSupportsAr: s ? ((r = (n = document.createElement("a").relList) == null ? void 0 : n.supports) == null ? void 0 : r.call(n, "ar")) === !0 : void 0,
341
+ userAgent: typeof navigator < "u" ? navigator.userAgent : void 0
342
+ };
343
+ }, Is = (e) => !!e && /Android/.test(e) && /(Chrome|SamsungBrowser)\//.test(e) && !/Firefox|OPR\//.test(e), _s = async (e) => {
344
+ let s = !1;
345
+ if (e.xrSessionSupported)
346
+ try {
347
+ s = await e.xrSessionSupported("immersive-ar");
348
+ } catch {
349
+ s = !1;
350
+ }
351
+ const t = Is(e.userAgent), n = e.relSupportsAr === !0, r = s || t || n;
352
+ return {
353
+ webxr: s,
354
+ sceneViewer: t,
355
+ quickLook: n,
356
+ any: r,
357
+ reason: r ? null : I("placement-unsupported")
358
+ };
359
+ }, Ps = (e) => {
360
+ switch (e) {
361
+ case "granted":
362
+ return "supported";
363
+ case "denied":
364
+ return "permission-denied";
365
+ case "prompt":
366
+ return "permission-prompt";
367
+ default:
368
+ return "unknown";
369
+ }
370
+ }, Ds = async (e, s) => {
371
+ var o, d, l;
372
+ const t = e.isSecureContext ?? !0, n = (o = e.navigator) == null ? void 0 : o.mediaDevices;
373
+ if (!t)
374
+ return {
375
+ status: "unsupported",
376
+ reason: I("camera-insecure-context"),
377
+ deviceCount: null,
378
+ secureContext: t
379
+ };
380
+ if (!n || typeof n.getUserMedia != "function")
381
+ return {
382
+ status: "unsupported",
383
+ reason: I("camera-unsupported"),
384
+ deviceCount: null,
385
+ secureContext: t
386
+ };
387
+ let r = "unknown";
388
+ if (s && ((l = (d = e.navigator) == null ? void 0 : d.permissions) != null && l.query))
389
+ try {
390
+ const h = await e.navigator.permissions.query({ name: "camera" });
391
+ r = Ps(h.state);
392
+ } catch {
393
+ r = "unknown";
394
+ }
395
+ let a = null, c = !1;
396
+ if (typeof n.enumerateDevices == "function")
397
+ try {
398
+ const h = await n.enumerateDevices();
399
+ a = h.filter((m) => m.kind === "videoinput").length, c = h.some((m) => !!m.label);
400
+ } catch {
401
+ a = null;
402
+ }
403
+ return r === "permission-denied" ? {
404
+ status: r,
405
+ reason: I("camera-permission-denied"),
406
+ deviceCount: a,
407
+ secureContext: t
408
+ } : a === 0 && (r === "supported" || c) ? {
409
+ status: "unsupported",
410
+ reason: I("no-camera"),
411
+ deviceCount: a,
412
+ secureContext: t
413
+ } : { status: r, reason: null, deviceCount: a, secureContext: t };
414
+ }, Ls = (e) => {
415
+ var t;
416
+ const s = (t = e.createCanvas) == null ? void 0 : t.call(e);
417
+ if (!s) return 0;
418
+ try {
419
+ if (s.getContext("webgl2")) return 2;
420
+ if (s.getContext("webgl") || s.getContext("experimental-webgl")) return 1;
421
+ } catch {
422
+ return 0;
423
+ }
424
+ return 0;
425
+ }, Os = (e) => {
426
+ var c;
427
+ const s = Ls(e), t = e.offscreenCanvas ?? !1, n = e.wasm ?? !1, r = !!((c = e.navigator) != null && c.gpu);
428
+ let a = null;
429
+ return s === 0 ? a = I("webgl-unavailable") : t ? n || (a = I("wasm-unavailable")) : a = I("offscreen-canvas-unavailable"), {
430
+ status: a ? "unsupported" : "supported",
431
+ reason: a,
432
+ webglVersion: s,
433
+ webgpu: r,
434
+ offscreenCanvas: t,
435
+ wasm: n
436
+ };
437
+ }, Hs = async (e, s, t) => {
438
+ var c, o;
439
+ const n = Mt(e);
440
+ if (!n || !s.fetch)
441
+ return { model: e, status: "unknown", reason: null, url: n, bytes: null };
442
+ const r = typeof AbortController < "u" ? new AbortController() : void 0, a = setTimeout(() => r == null ? void 0 : r.abort(), t);
443
+ try {
444
+ const d = await s.fetch(n, { method: "HEAD", signal: r == null ? void 0 : r.signal });
445
+ if (!d.ok)
446
+ return {
447
+ model: e,
448
+ status: "unsupported",
449
+ reason: I(
450
+ "model-unreachable",
451
+ `${St["model-unreachable"]} (${d.status})`
452
+ ),
453
+ url: n,
454
+ bytes: null
455
+ };
456
+ const l = Number(((o = (c = d.headers) == null ? void 0 : c.get) == null ? void 0 : o.call(c, "content-length")) ?? NaN);
457
+ return {
458
+ model: e,
459
+ status: "supported",
460
+ reason: null,
461
+ url: n,
462
+ bytes: Number.isFinite(l) && l > 0 ? l : null
463
+ };
464
+ } catch {
465
+ return {
466
+ model: e,
467
+ status: "unsupported",
468
+ reason: I("model-unreachable"),
469
+ url: n,
470
+ bytes: null
471
+ };
472
+ } finally {
473
+ clearTimeout(a);
474
+ }
475
+ }, gr = async (e = {}, s = Fs()) => {
476
+ const t = e.timeoutMs ?? 4e3, n = new Set(e.models ?? []), [r, a, c] = await Promise.all([
477
+ Ds(s, e.queryPermission ?? !0),
478
+ Promise.all(
479
+ Rs.map(
480
+ async (l) => n.has(l) ? Hs(l, s, t) : {
481
+ model: l,
482
+ status: "unknown",
483
+ reason: null,
484
+ url: Mt(l),
485
+ bytes: null
486
+ }
487
+ )
488
+ ),
489
+ _s(s)
490
+ ]), o = Os(s), d = Object.fromEntries(a.map((l) => [l.model, l]));
491
+ return {
492
+ camera: r,
493
+ rendering: o,
494
+ placement: c,
495
+ models: d,
496
+ canRunTracking: o.status === "supported" && r.status !== "unsupported",
497
+ checkedAt: s.now ? s.now() : Date.now()
498
+ };
499
+ }, Ct = (e) => {
500
+ switch (e) {
501
+ case "permission-denied":
502
+ return I("camera-permission-denied");
503
+ case "camera-in-use":
504
+ return I("camera-in-use");
505
+ case "no-camera":
506
+ return I("no-camera");
507
+ case "camera-lost":
508
+ return I("camera-lost");
509
+ case "unsupported":
510
+ return I("camera-unsupported");
511
+ default:
512
+ return I("unknown");
513
+ }
514
+ }, pr = (e, s) => {
515
+ const { camera: t, rendering: n } = e, r = e.models[s], a = t.status === "permission-prompt" || t.status === "unknown";
516
+ return n.reason ? { supported: !1, reason: n.reason, needsPermission: a } : t.reason ? { supported: !1, reason: t.reason, needsPermission: a } : r != null && r.reason ? { supported: !1, reason: r.reason, needsPermission: a } : { supported: !0, reason: null, needsPermission: a };
517
+ }, yr = (e) => {
518
+ const s = e instanceof Error ? e.message : String(e ?? ""), t = s.toLowerCase();
519
+ return t.includes("integrity") || t.includes("sha-384") || t.includes("sha384") ? I("model-integrity", s) : t.includes("failed to fetch") || t.includes("networkerror") || t.includes("load failed") || /\b(404|403|5\d\d)\b/.test(t) || t.includes("fetch") ? I("model-unreachable", s) : t.includes("webgl") || t.includes("gpu") ? I("webgl-unavailable", s) : s ? I("model-init-failed", s) : I("unknown");
520
+ }, kt = (e) => {
521
+ switch (e instanceof DOMException ? e.name : "") {
522
+ case "NotAllowedError":
523
+ case "PermissionDeniedError":
524
+ return "permission-denied";
525
+ case "NotReadableError":
526
+ case "TrackStartError":
527
+ return "camera-in-use";
528
+ case "NotFoundError":
529
+ case "DevicesNotFoundError":
530
+ return "no-camera";
531
+ case "NotSupportedError":
532
+ case "SecurityError":
533
+ case "OverconstrainedError":
534
+ return "unsupported";
535
+ default:
536
+ return e instanceof TypeError ? "unsupported" : "unknown";
537
+ }
538
+ }, ct = {
539
+ "permission-denied": "Camera access was blocked. Allow camera permissions in your browser, then refresh.",
540
+ "camera-in-use": "Camera is already in use by another app or browser tab. Close it and refresh.",
541
+ "no-camera": "No camera was found on this device.",
542
+ "camera-lost": "The camera stopped sending frames. Reconnect it or re-allow access, then start again.",
543
+ unsupported: "Unable to access camera. Allow camera permissions in your browser, then refresh.",
544
+ unknown: "Unable to access camera. Allow camera permissions in your browser, then refresh."
545
+ }, ze = () => ({
546
+ mediaDevices: typeof navigator < "u" ? navigator.mediaDevices : void 0,
547
+ permissions: typeof navigator < "u" ? navigator.permissions : void 0,
548
+ isSecureContext: typeof window < "u" ? window.isSecureContext : void 0
549
+ }), xt = async (e = ze()) => {
550
+ var s;
551
+ if (!((s = e.permissions) != null && s.query)) return { state: "unknown", prompt: !1 };
552
+ try {
553
+ const t = await e.permissions.query({ name: "camera" });
554
+ return t.state === "granted" ? { state: "granted", prompt: !1 } : t.state === "denied" ? { state: "blocked", prompt: !1 } : { state: "unknown", prompt: t.state === "prompt" };
555
+ } catch {
556
+ return { state: "unknown", prompt: !1 };
557
+ }
558
+ }, bt = (e, s) => e === "permission-denied" ? {
559
+ state: s === "blocked" ? "blocked" : "denied",
560
+ reason: I("camera-permission-denied")
561
+ } : { state: "unavailable", reason: Ct(e) }, wr = async (e = {}, s = ze()) => {
562
+ var n;
563
+ if (s.isSecureContext === !1)
564
+ return {
565
+ state: "unavailable",
566
+ reason: I("camera-insecure-context"),
567
+ stream: null
568
+ };
569
+ const t = (n = s.mediaDevices) == null ? void 0 : n.getUserMedia;
570
+ if (typeof t != "function")
571
+ return {
572
+ state: "unavailable",
573
+ reason: I("camera-unsupported"),
574
+ stream: null
575
+ };
576
+ try {
577
+ const r = await t.call(
578
+ s.mediaDevices,
579
+ e.constraints ?? { video: { facingMode: "user" } }
580
+ );
581
+ return e.keepStream ? { state: "granted", reason: null, stream: r } : (r.getTracks().forEach((a) => a.stop()), { state: "granted", reason: null, stream: null });
582
+ } catch (r) {
583
+ const a = kt(r), c = await xt(s);
584
+ return { ...bt(a, c.state), stream: null };
585
+ }
586
+ }, vr = async (e, s = ze()) => {
587
+ var t, n;
588
+ if (!((t = s.permissions) != null && t.query)) return () => {
589
+ };
590
+ try {
591
+ const r = await s.permissions.query({ name: "camera" }), a = () => {
592
+ r.state === "granted" ? e({ state: "granted", prompt: !1 }) : r.state === "denied" ? e({ state: "blocked", prompt: !1 }) : e({ state: "unknown", prompt: r.state === "prompt" });
593
+ };
594
+ return (n = r.addEventListener) == null || n.call(r, "change", a), () => {
595
+ var c;
596
+ return (c = r.removeEventListener) == null ? void 0 : c.call(r, "change", a);
597
+ };
598
+ } catch {
599
+ return () => {
600
+ };
601
+ }
602
+ }, Sr = (e) => e === "unknown" || e === "denied" || e === "granted", Mr = {
603
+ unknown: "This experience uses your camera. Nothing is recorded or uploaded.",
604
+ requesting: "Waiting for you to allow the camera…",
605
+ granted: "Camera access granted.",
606
+ denied: "Camera access was not allowed. You can try again.",
607
+ blocked: "Camera access is blocked for this site. Allow it in your browser's site settings, then reload.",
608
+ unavailable: "The camera is unavailable on this device right now."
609
+ }, Ns = (e, s, t = "cover", n = 1) => {
610
+ if (e.width <= 0 || e.height <= 0 || s.width <= 0 || s.height <= 0)
611
+ return null;
612
+ const r = Number.isFinite(n) && n > 0 ? n : 1, a = s.width / e.width, c = s.height / e.height, o = t === "contain" ? c <= a : c >= a, d = (o ? c : a) * r, l = o ? e.width * c * r : s.width * r, h = o ? s.height * r : e.height * a * r;
613
+ return {
614
+ scale: d,
615
+ drawWidth: l,
616
+ drawHeight: h,
617
+ offsetX: (s.width - l) / 2,
618
+ offsetY: (s.height - h) / 2
619
+ };
620
+ }, Me = (e) => e === "webcam" || e === void 0, Us = ({
621
+ source: e,
622
+ feed: s,
623
+ zoom: t = 1,
624
+ mirrored: n = !1
625
+ }) => {
626
+ const r = Ns(e, s, "cover", t);
627
+ return r ? { ...r, source: e, feed: s, zoom: Number.isFinite(t) && t > 0 ? t : 1, mirrored: n } : null;
628
+ }, Cr = (e, s, t = { x: 0, y: 0 }) => {
629
+ const n = s.mirrored ? s.source.width - e.x : e.x;
630
+ return t.x = (s.offsetX + n * s.scale) / s.feed.width, t.y = (s.offsetY + e.y * s.scale) / s.feed.height, t;
631
+ }, Bs = (e, s, t = { x: 0, y: 0 }) => {
632
+ const n = (e.x * s.feed.width - s.offsetX) / s.scale;
633
+ return t.x = s.mirrored ? s.source.width - n : n, t.y = (e.y * s.feed.height - s.offsetY) / s.scale, t;
634
+ }, kr = (e, s) => {
635
+ const t = Bs(e, s);
636
+ return t.x >= 0 && t.x <= s.source.width && t.y >= 0 && t.y <= s.source.height;
637
+ }, xr = (e, s = { x: 0, y: 0 }) => (s.x = 1 - e.x, s.y = e.y, e.z !== void 0 && (s.z = e.z), s), br = (e, s, t, n = { x: 0, y: 0 }) => {
638
+ switch (t) {
639
+ case 90:
640
+ return n.x = s.height - e.y, n.y = e.x, n;
641
+ case 180:
642
+ return n.x = s.width - e.x, n.y = s.height - e.y, n;
643
+ case 270:
644
+ return n.x = e.y, n.y = s.width - e.x, n;
645
+ default:
646
+ return n.x = e.x, n.y = e.y, n;
647
+ }
648
+ }, Tr = (e, s) => s === 90 || s === 270 ? { width: e.height, height: e.width } : { width: e.width, height: e.height };
649
+ class O extends Error {
650
+ constructor(s) {
651
+ super(s), this.name = "VincenttXRError";
652
+ }
653
+ }
654
+ class zs {
655
+ constructor(s) {
656
+ u(this, "options");
657
+ const t = {
658
+ verbose: !1,
659
+ prefix: z.loggerPrefix
660
+ };
661
+ this.options = { ...t, ...s };
662
+ }
663
+ log(...s) {
664
+ const { verbose: t, prefix: n } = this.options;
665
+ t && console.info(n, ...s);
666
+ }
667
+ error(...s) {
668
+ const { verbose: t, prefix: n } = this.options;
669
+ t && console.error(n, ...s);
670
+ }
671
+ }
672
+ const lt = new B.Vector3(), Pe = new B.Vector3(), Tt = (e, s, t, n, r) => {
673
+ lt.set(e, s, 0).unproject(t), Pe.copy(lt).sub(t.position).normalize();
674
+ const a = (n - t.position.z) / Pe.z;
675
+ return r.copy(t.position).addScaledVector(Pe, a);
676
+ }, Ws = (e, s, t = new B.Vector3(), n = 0) => Tt((e.x - 0.5) * 2, (0.5 - e.y) * 2, s, n, t), Er = (e, s, t = new B.Vector3(), n = 0) => Tt(e.x, e.y, s, n, t), X = new B.Vector3(), Ar = (e, s, t = { x: 0, y: 0, z: 0 }) => (X.set(e.x, e.y, e.z).project(s), t.x = X.x / 2 + 0.5, t.y = 0.5 - X.y / 2, t.z = X.z, t), Rr = (e, s, t = { x: 0, y: 0, z: 0 }) => (X.set(e.x, e.y, e.z).project(s), t.x = X.x, t.y = X.y, t.z = X.z, t), De = (e, s, t) => Ws(e, s, t, 0), qs = (e, s, t = 0.2) => t * s + (1 - t) * e;
677
+ class me {
678
+ constructor(s) {
679
+ u(this, "canvas");
680
+ u(this, "scale", 1);
681
+ this.maxDimension = s;
682
+ }
683
+ /** Multiply the cap (0.25..1); the adaptive-quality tier sets it. */
684
+ setScale(s) {
685
+ this.scale = Math.min(1, Math.max(0.25, Number.isFinite(s) && s > 0 ? s : 1));
686
+ }
687
+ /**
688
+ * Returns a downscaled copy of `source` capped to `maxDimension` on its
689
+ * longest side (or `source` unchanged if it's already within the cap, or if a
690
+ * 2D context can't be obtained). The returned canvas is reused across calls.
691
+ */
692
+ draw(s) {
693
+ const t = s.width, n = s.height, r = Math.min(
694
+ 1,
695
+ this.maxDimension * this.scale / Math.max(t, n)
696
+ );
697
+ if (r >= 1) return s;
698
+ const a = Math.max(1, Math.round(t * r)), c = Math.max(1, Math.round(n * r));
699
+ (!this.canvas || this.canvas.width !== a || this.canvas.height !== c) && (this.canvas = new OffscreenCanvas(a, c));
700
+ const o = this.canvas.getContext("2d");
701
+ return o ? (o.setTransform(1, 0, 0, 1, 0, 0), o.clearRect(0, 0, a, c), o.drawImage(s, 0, 0, a, c), this.canvas) : s;
702
+ }
703
+ dispose() {
704
+ this.canvas = void 0;
705
+ }
706
+ }
707
+ const Vs = {
708
+ "/assets/xr/models/face_tracking.task": "sha384-tYQh+yJE8llY+zO4RviZmWaSKs5W9tsB0ix5rjQVpF5/CLTqmwtP7bYtkUi2w65P",
709
+ "/assets/xr/models/hand_tracking.task": "sha384-uWvruVKd887ov8k43S+DBHCsi7UXXS+CKvvdM1PX00rjPzx/B0QrAPfJ1U9yKcze",
710
+ "/assets/xr/models/gesture_tracking.task": "sha384-2zuseP9JKKWAYlWQGKA2N+ooabB8V/yIxu23Mv8mtY7SowcySB+xKiOmqBhVvlUC",
711
+ "/assets/xr/models/body_tracking.task": "sha384-3Wk9dvRYo36b3Nc9xVjKamb4wCKt9FwiPjcHKfrvyJL/jXoGs+uRLnii6yjWLKul",
712
+ "/assets/xr/models/segmentation.tflite": "sha384-A2bQ8+iZyQM3KIGVBUf0FyetqxuynyKpjsjCE8uzoJEnj1ghCu6ge2daiRffAiS5",
713
+ "/assets/xr/3d-models/head-occluder-v2.glb": "sha384-+0G60Q6EBVE6hpITxGzQgofAeKexPltpsfPq5T5et9GGBjRhFP5HOdsKAhe73OaI",
714
+ // v3: canonical-frame head (first 468 vertices = the canonical face landmarks),
715
+ // authored in assets-src/head-occluder/head-occluder-v3.blend. Hash of the
716
+ // exported GLB; the CDN copy must be byte-identical to example/src/assets/models.
717
+ "/assets/xr/3d-models/head-occluder-v3.glb": "sha384-bmKKYb7k1qsGqkOSUBwv3oqI9eOche97/OvRxXDxrqZAgqpy+4PJ5HU9O94lrjFO",
718
+ // Shoulder / upper-torso occluder in the canonical torso frame (same .blend).
719
+ "/assets/xr/3d-models/shoulder-occluder-v1.glb": "sha384-iXxOvC+IoXfgpf8S/JSsV6lLzzLs6vtmaslJy7R0iLtl5Yb17U+/ATfGdhpmamae",
720
+ // Category segmenters behind XRModel.SEMANTIC_SEGMENTATION. The same bytes
721
+ // are pinned under the SDK CDN paths (not yet published) and under
722
+ // MediaPipe's published paths, which the presets load by default.
723
+ "/assets/xr/models/hair_segmenter.tflite": "sha384-1Eu/EdJcYV/7talPYVVbxPZBLg7UIxqsKisUNh/pEsyvAuUcE49HuqijSXWSHXHK",
724
+ "/mediapipe-models/image_segmenter/hair_segmenter/float32/latest/hair_segmenter.tflite": "sha384-1Eu/EdJcYV/7talPYVVbxPZBLg7UIxqsKisUNh/pEsyvAuUcE49HuqijSXWSHXHK",
725
+ "/assets/xr/models/selfie_multiclass_256x256.tflite": "sha384-LPLPyzBZ6TTE8146rnDx8CZ5LykB8memkmeO8FNVbGlNthvlUltn3W3KeJmtq9bL",
726
+ "/mediapipe-models/image_segmenter/selfie_multiclass_256x256/float32/latest/selfie_multiclass_256x256.tflite": "sha384-LPLPyzBZ6TTE8146rnDx8CZ5LykB8memkmeO8FNVbGlNthvlUltn3W3KeJmtq9bL",
727
+ // MediaPipe Holistic Landmarker (face + hands + pose in one graph) behind
728
+ // XRModel.HOLISTIC_TRACKER. Same bytes pinned under the SDK CDN path (not yet
729
+ // published) and MediaPipe's published path, which the tracker loads by default.
730
+ "/assets/xr/models/holistic_landmarker.task": "sha384-6Y2fQ5yP5QtlvJIasfv0fHEyoMqRYYpLtEpsyeXjYDOuFCEXfKIZPZSXq8TLXmsg",
731
+ "/mediapipe-models/holistic_landmarker/holistic_landmarker/float16/latest/holistic_landmarker.task": "sha384-6Y2fQ5yP5QtlvJIasfv0fHEyoMqRYYpLtEpsyeXjYDOuFCEXfKIZPZSXq8TLXmsg",
732
+ "/assets/sdk/face/v1/canonical_face_model.obj": "sha384-xP8YM/72TXKvbMptXB9a8JUlUf3MZQ8uLurExrsZc05v6/P5RrsaNGMUYS/BZx8A",
733
+ "/opencv/facial_expression_recognition/resolve/main/facial_expression_recognition_mobilefacenet_2022july_int8.onnx": "sha384-g8mtFubiIc/yhqi591RsxD76AJLw2CfYgKhKbVkIiFlwBmIyG7ZAIVyGPXafrDGB"
734
+ };
735
+ async function Ks(e, s) {
736
+ const t = await fetch(e, s != null && s.signal ? { signal: s.signal } : void 0);
737
+ if (!t.ok)
738
+ throw new Error(`fetchAndVerify: ${t.status} ${e}`);
739
+ const n = await t.arrayBuffer(), r = Ys(e);
740
+ if (!r) {
741
+ if (Gs(e))
742
+ throw new Error(`[xr-sdk integrity] no SRI hash for SDK asset ${e}`);
743
+ return console.warn(`[xr-sdk integrity] no SRI hash for ${e} — passing through`), n;
744
+ }
745
+ const a = await js(n);
746
+ if (a !== r)
747
+ throw new Error(
748
+ `[xr-sdk integrity] SRI mismatch for ${e}: expected ${r}, got ${a}`
749
+ );
750
+ return n;
751
+ }
752
+ function Gs(e) {
753
+ try {
754
+ return new URL(e).origin === new URL(z.assetStorageEndpoint).origin;
755
+ } catch {
756
+ return !1;
757
+ }
758
+ }
759
+ async function Z(e) {
760
+ const s = await Ks(e);
761
+ return new Uint8Array(s);
762
+ }
763
+ const ie = /* @__PURE__ */ new Map();
764
+ function Xs(e) {
765
+ let s = ie.get(e);
766
+ if (!s) {
767
+ const r = { bytes: Z(e), holders: 0 };
768
+ r.bytes.catch(() => {
769
+ ie.get(e) === r && ie.delete(e);
770
+ }), ie.set(e, r), s = r;
771
+ }
772
+ const t = s;
773
+ t.holders += 1;
774
+ let n = !1;
775
+ return {
776
+ bytes: t.bytes,
777
+ release: () => {
778
+ n || (n = !0, t.holders -= 1, t.holders <= 0 && ie.get(e) === t && ie.delete(e));
779
+ }
780
+ };
781
+ }
782
+ function Ys(e) {
783
+ try {
784
+ const s = new URL(e);
785
+ return Vs[s.pathname];
786
+ } catch {
787
+ return;
788
+ }
789
+ }
790
+ async function js(e) {
791
+ const s = await crypto.subtle.digest("SHA-384", e), t = new Uint8Array(s);
792
+ let n = "";
793
+ for (let r = 0; r < t.byteLength; r++)
794
+ n += String.fromCharCode(t[r]);
795
+ return `sha384-${btoa(n)}`;
796
+ }
797
+ const Le = /* @__PURE__ */ new Map();
798
+ function J(e) {
799
+ const s = e.wasmBinaryPath;
800
+ let t = Le.get(s);
801
+ return t || (t = Qs(s).catch(() => {
802
+ Le.delete(s);
803
+ }), Le.set(s, t)), t;
804
+ }
805
+ async function Qs(e) {
806
+ const s = await fetch(e, { credentials: "same-origin" });
807
+ if (!s.ok || !s.body)
808
+ throw new Error(`warmVisionWasm: ${s.status} ${e}`);
809
+ const t = s.body.getReader();
810
+ for (; ; ) {
811
+ const { done: n } = await t.read();
812
+ if (n) return;
813
+ }
814
+ }
815
+ class $ {
816
+ constructor() {
817
+ u(this, "disposed", !1);
818
+ u(this, "paused", !1);
819
+ u(this, "rafId", null);
820
+ // Inference bookkeeping behind `getDiagnostics()`. Subclasses call
821
+ // `recordInference(startMs)` right after their detect call and
822
+ // `recordDetections(count, confidence)` after reading the result.
823
+ u(this, "statInferenceMs", null);
824
+ u(this, "statInferences", 0);
825
+ u(this, "statWindowStart", 0);
826
+ u(this, "statWindowCount", 0);
827
+ u(this, "statFps", 0);
828
+ u(this, "statSkipped", 0);
829
+ u(this, "statDetections", null);
830
+ u(this, "statConfidence", null);
831
+ u(this, "statStatus", "ready");
832
+ u(this, "statError", null);
833
+ // Inference-rate throttle. `targetFrameIntervalMs` is 0 when uncapped
834
+ // (detect every frame); a positive value skips detection until that many ms
835
+ // have elapsed since the last inference. `run()` sets this from
836
+ // `params.targetFps`; subclasses call `shouldRunInference()` in their RAF
837
+ // loop to gate the expensive MediaPipe call.
838
+ u(this, "targetFrameIntervalMs", 0);
839
+ u(this, "lastInferenceMs", 0);
840
+ /** Analysis-resolution multiplier (0.25..1) from the quality tier; subclasses read it where they downscale. */
841
+ u(this, "analysisScale", 1);
842
+ }
843
+ /** Record one completed inference that started at `startMs` (`performance.now()`). */
844
+ recordInference(s, t = performance.now()) {
845
+ const n = t - s;
846
+ this.statInferenceMs = n, this.statInferences += 1, this.statWindowCount += 1, this.statWindowStart === 0 && (this.statWindowStart = t);
847
+ const r = t - this.statWindowStart;
848
+ return r >= 1e3 && (this.statFps = this.statWindowCount * 1e3 / r, this.statWindowStart = t, this.statWindowCount = 0), n;
849
+ }
850
+ /** Record what the last inference found (subjects and the primary confidence). */
851
+ recordDetections(s, t = null) {
852
+ this.statDetections = s, this.statConfidence = t;
853
+ }
854
+ /** Record an inference failure (or clear it with `null`). */
855
+ recordInferenceError(s) {
856
+ this.statStatus = s ? "error" : "ready", this.statError = s;
857
+ }
858
+ /** Current health snapshot. Allocates a small object; sample it at UI rate, not per frame. */
859
+ getDiagnostics() {
860
+ const s = this.statWindowStart > 0 && performance.now() - this.statWindowStart > 1500;
861
+ return {
862
+ inferenceMs: this.statInferenceMs,
863
+ inferenceFps: s ? 0 : this.statFps,
864
+ inferences: this.statInferences,
865
+ skippedFrames: this.statSkipped,
866
+ detections: this.statDetections,
867
+ confidence: this.statConfidence,
868
+ status: this.statStatus,
869
+ error: this.statError,
870
+ paused: this.paused,
871
+ disposed: this.disposed
872
+ };
873
+ }
874
+ /** Clamp and store the analysis scale; subclasses with a downscaler forward it. */
875
+ setAnalysisScale(s) {
876
+ this.analysisScale = s !== void 0 && Number.isFinite(s) && s > 0 ? Math.min(1, Math.max(0.25, s)) : 1;
877
+ }
878
+ /** Set the per-frame inference cap. fps <= 0 (or undefined) → uncapped. */
879
+ setTargetFps(s) {
880
+ this.targetFrameIntervalMs = s && s > 0 ? 1e3 / s : 0;
881
+ }
882
+ /**
883
+ * True if enough time has elapsed to run inference this frame (and records
884
+ * the timestamp). Always true when uncapped. Call once per RAF tick, right
885
+ * before the detect call; skip the detect (but keep rescheduling RAF) when
886
+ * it returns false.
887
+ */
888
+ shouldRunInference() {
889
+ if (this.targetFrameIntervalMs <= 0) return !0;
890
+ const s = performance.now();
891
+ return s - this.lastInferenceMs < this.targetFrameIntervalMs ? (this.statSkipped += 1, !1) : (this.lastInferenceMs = s, !0);
892
+ }
893
+ // load models
894
+ async initialize(s) {
895
+ }
896
+ // setup for running + start running
897
+ async run(s) {
898
+ }
899
+ // get model's data while processing
900
+ getModelNode() {
901
+ return {};
902
+ }
903
+ async getPerformanceData() {
904
+ return {
905
+ name: this.constructor.name,
906
+ processingTime: null
907
+ };
908
+ }
909
+ // Cancel the per-frame RAF loop without releasing MediaPipe resources or
910
+ // dropping refs. Subclasses' process* methods check `paused` and return
911
+ // without rescheduling. Idempotent.
912
+ pause() {
913
+ this.paused = !0, this.rafId !== null && (cancelAnimationFrame(this.rafId), this.rafId = null);
914
+ }
915
+ // Resume a paused loop by running the process function once. Subclasses
916
+ // override to kick their specific process* method. Idempotent — no-op if
917
+ // not paused. Calling resume() before run() is a no-op.
918
+ resume() {
919
+ this.paused = !1;
920
+ }
921
+ // Release MediaPipe landmarkers, cancel rAF loops, drop refs.
922
+ // Subclasses MUST override and call super.dispose() at the end.
923
+ dispose() {
924
+ this.disposed = !0, this.rafId !== null && (cancelAnimationFrame(this.rafId), this.rafId = null);
925
+ }
926
+ }
927
+ const Zs = 768;
928
+ class Js extends $ {
929
+ constructor() {
930
+ super();
931
+ u(this, "landmarker", null);
932
+ u(this, "processingTime", null);
933
+ u(this, "coordinates");
934
+ u(this, "visibility");
935
+ u(this, "sourceCanvas");
936
+ u(this, "downscaler", new me(Zs));
937
+ }
938
+ async getBodyData() {
939
+ if (!this.landmarker || !this.sourceCanvas)
940
+ return;
941
+ const t = this.downscaler.draw(this.sourceCanvas), n = performance.now(), r = this.landmarker.detectForVideo(t, n), a = performance.now();
942
+ this.processingTime = a - n, this.recordInference(n, a);
943
+ const c = r.landmarks, o = c == null ? void 0 : c[0];
944
+ this.recordDetections(
945
+ (c == null ? void 0 : c.length) ?? 0,
946
+ o && o.length ? o.reduce((h, m) => h + (m.visibility ?? 0), 0) / o.length : null
947
+ );
948
+ const d = [], l = [];
949
+ if (c)
950
+ return c.forEach((h, m) => {
951
+ d[m] || (d[m] = [], l[m] = []), h.forEach((y) => {
952
+ d[m].push(ue(y)), l[m].push(y.visibility ?? 1);
953
+ });
954
+ }), {
955
+ coordinatesList: d,
956
+ visibilityList: l
957
+ };
958
+ }
959
+ async processBodyTracking() {
960
+ if (!(this.disposed || this.paused || !this.landmarker)) {
961
+ if (this.shouldRunInference()) {
962
+ const t = await this.getBodyData();
963
+ t && (this.coordinates = t.coordinatesList, this.visibility = t.visibilityList);
964
+ }
965
+ this.disposed || this.paused || (this.rafId = requestAnimationFrame(this.processBodyTracking.bind(this)));
966
+ }
967
+ }
968
+ resume() {
969
+ this.paused && (super.resume(), this.processBodyTracking());
970
+ }
971
+ dispose() {
972
+ if (super.dispose(), this.landmarker) {
973
+ try {
974
+ this.landmarker.close();
975
+ } catch {
976
+ }
977
+ this.landmarker = null;
978
+ }
979
+ this.sourceCanvas = void 0, this.downscaler.dispose(), this.coordinates = void 0, this.visibility = void 0;
980
+ }
981
+ getLandmarks2D(t = 0) {
982
+ if (this.coordinates)
983
+ return this.coordinates[t];
984
+ }
985
+ getVisibility(t = 0) {
986
+ var n;
987
+ return (n = this.visibility) == null ? void 0 : n[t];
988
+ }
989
+ async initialize(t) {
990
+ const n = await Q.forVisionTasks(
991
+ new URL("/assets/xr/wasm", z.assetStorageEndpoint).toString()
992
+ ), [r] = await Promise.all([
993
+ Z(
994
+ new URL("/assets/xr/models/body_tracking.task", z.assetStorageEndpoint).toString()
995
+ ),
996
+ J(n)
997
+ ]);
998
+ this.landmarker = await ms.createFromOptions(n, {
999
+ baseOptions: {
1000
+ modelAssetBuffer: r,
1001
+ delegate: "GPU"
1002
+ },
1003
+ runningMode: "VIDEO",
1004
+ numPoses: (t == null ? void 0 : t.numPoses) || 1
1005
+ });
1006
+ }
1007
+ async run({ sourceCanvas: t, targetFps: n, analysisScale: r }) {
1008
+ this.setAnalysisScale(r), this.downscaler.setScale(this.analysisScale), this.sourceCanvas = t, this.setTargetFps(n), this.rafId === null && await this.processBodyTracking();
1009
+ }
1010
+ getModelNode() {
1011
+ return {
1012
+ getLandmarks2D: this.getLandmarks2D.bind(this),
1013
+ getVisibility: this.getVisibility.bind(this)
1014
+ };
1015
+ }
1016
+ async getPerformanceData() {
1017
+ return {
1018
+ name: this.constructor.name,
1019
+ processingTime: this.processingTime
1020
+ };
1021
+ }
1022
+ }
1023
+ const Et = Symbol("xr.modelNodeSource"), Fr = (e) => e[Et] ?? e, $s = 0.11, en = 4e-3, tn = "/assets/xr/models/face_tracking.task", sn = "/assets/xr/wasm", nn = (e, s, t = !0) => t ? s.set(e.x, -e.y, e.z) : s.set(e.x, e.y, -e.z), rn = (e, s) => s.setFromRotationMatrix(e).normalize();
1024
+ class an extends $ {
1025
+ constructor() {
1026
+ super();
1027
+ u(this, "landmarker", null);
1028
+ /** The face model bytes, held while this model is alive (shared with the still-image detector). */
1029
+ u(this, "modelBytes", null);
1030
+ u(this, "processingTime", null);
1031
+ u(this, "sourceCanvas");
1032
+ u(this, "analysisCanvas");
1033
+ u(this, "getSource");
1034
+ u(this, "detectionResults");
1035
+ u(this, "numFaces", 1);
1036
+ u(this, "cameras", []);
1037
+ // camera object to unproject each face's translation
1038
+ u(this, "faces", []);
1039
+ // Reused per-face work vectors. Allocated once per face index and mutated
1040
+ // in place each frame, so the published Face[] doesn't churn the GC at
1041
+ // 30+ fps. Per-face indexing means two faces don't alias each other's
1042
+ // transforms; consumers see "current value" each frame.
1043
+ u(this, "leftCheekScratch", []);
1044
+ u(this, "rightCheekScratch", []);
1045
+ // Reused per-frame rotation scratch (matrix -> quaternion -> mirror -> euler),
1046
+ // allocated once to avoid per-frame churn at 30+ fps.
1047
+ u(this, "rotMatrixScratch", new B.Matrix4());
1048
+ u(this, "rotQuatScratch", new B.Quaternion());
1049
+ u(this, "rotEulerScratch", new B.Euler());
1050
+ }
1051
+ extractAndUpdateFaceData(t) {
1052
+ var a;
1053
+ if (!t.faceLandmarks.length) {
1054
+ this.faces = [];
1055
+ return;
1056
+ }
1057
+ const n = t.faceLandmarks.length;
1058
+ this.faces.length > n && (this.faces.length = n, this.leftCheekScratch.length = n, this.rightCheekScratch.length = n);
1059
+ const r = Me((a = this.getSource) == null ? void 0 : a.call(this));
1060
+ for (; this.faces.length < n; )
1061
+ this.faces.push({
1062
+ transform: {
1063
+ position: new B.Vector3(),
1064
+ rotation: new B.Vector3(),
1065
+ quaternion: new B.Quaternion(),
1066
+ scale: new B.Vector3()
1067
+ },
1068
+ gestures: {},
1069
+ mirrored: r
1070
+ }), this.leftCheekScratch.push(new B.Vector3()), this.rightCheekScratch.push(new B.Vector3());
1071
+ for (let c = 0; c < n; c += 1)
1072
+ this.faces[c].mirrored = r;
1073
+ for (let c = 0; c < n; c += 1) {
1074
+ if (!this.cameras[c])
1075
+ continue;
1076
+ const o = this.faces[c], d = t.faceLandmarks[c], l = t.facialTransformationMatrixes[c];
1077
+ this.rotMatrixScratch.fromArray(l.data), rn(this.rotMatrixScratch, o.transform.quaternion), this.rotQuatScratch.copy(o.transform.quaternion), this.rotQuatScratch.set(
1078
+ -this.rotQuatScratch.x,
1079
+ this.rotQuatScratch.y,
1080
+ this.rotQuatScratch.z,
1081
+ this.rotQuatScratch.w
1082
+ ), this.rotEulerScratch.setFromQuaternion(this.rotQuatScratch, "XYZ"), nn(this.rotEulerScratch, o.transform.rotation, r), De(d[4], this.cameras[c], o.transform.position), De(d[50], this.cameras[c], this.leftCheekScratch[c]), De(d[280], this.cameras[c], this.rightCheekScratch[c]);
1083
+ const m = this.leftCheekScratch[c].distanceTo(this.rightCheekScratch[c]) * $s, y = Math.abs(B.MathUtils.radToDeg(this.rotEulerScratch.y)), S = m + y * en, M = o.transform.scale.x, C = qs(
1084
+ isNaN(M) ? 0 : M,
1085
+ S
1086
+ );
1087
+ o.transform.scale.set(C, C, C);
1088
+ const E = o.gestures, _ = t.faceBlendshapes[c].categories;
1089
+ for (const g of _)
1090
+ E[g.categoryName] = g.score;
1091
+ }
1092
+ }
1093
+ async processFaceTracking() {
1094
+ if (this.disposed || this.paused || !this.landmarker || !this.sourceCanvas)
1095
+ return null;
1096
+ if (!this.shouldRunInference()) {
1097
+ this.rafId = requestAnimationFrame(this.processFaceTracking.bind(this));
1098
+ return;
1099
+ }
1100
+ const t = on(this.numFaces) * this.analysisScale, n = this.sourceCanvas.width, r = this.sourceCanvas.height, a = Math.min(1, t / Math.max(n, r)), c = Math.max(1, Math.round(n * a)), o = Math.max(1, Math.round(r * a));
1101
+ (!this.analysisCanvas || this.analysisCanvas.width !== c || this.analysisCanvas.height !== o) && (this.analysisCanvas = new OffscreenCanvas(c, o));
1102
+ const d = this.analysisCanvas.getContext("2d");
1103
+ if (!d) {
1104
+ this.rafId = requestAnimationFrame(this.processFaceTracking.bind(this));
1105
+ return;
1106
+ }
1107
+ d.setTransform(1, 0, 0, 1, 0, 0), d.clearRect(0, 0, c, o), d.drawImage(this.sourceCanvas, 0, 0, c, o);
1108
+ const l = performance.now(), h = this.landmarker.detectForVideo(this.analysisCanvas, l), m = performance.now();
1109
+ this.processingTime = m - l, this.recordInference(l, m), this.recordDetections(h.faceLandmarks.length, null), this.detectionResults = h, this.extractAndUpdateFaceData(h), !(this.disposed || this.paused) && (this.rafId = requestAnimationFrame(this.processFaceTracking.bind(this)));
1110
+ }
1111
+ resume() {
1112
+ this.paused && (super.resume(), this.processFaceTracking());
1113
+ }
1114
+ dispose() {
1115
+ if (super.dispose(), this.landmarker) {
1116
+ try {
1117
+ this.landmarker.close();
1118
+ } catch {
1119
+ }
1120
+ this.landmarker = null;
1121
+ }
1122
+ this.releaseModelBytes(), this.sourceCanvas = void 0, this.getSource = void 0, this.analysisCanvas = void 0, this.detectionResults = void 0, this.processingTime = null, this.cameras = [], this.faces = [], this.leftCheekScratch = [], this.rightCheekScratch = [];
1123
+ }
1124
+ getFace(t = 0) {
1125
+ return this.faces[t];
1126
+ }
1127
+ getDetectionResults() {
1128
+ return this.detectionResults;
1129
+ }
1130
+ getRawFaceTrackingData(t = 0) {
1131
+ var n, r, a, c;
1132
+ if (this.detectionResults)
1133
+ return {
1134
+ landmarks: (n = this.detectionResults.faceLandmarks) == null ? void 0 : n[t],
1135
+ blendshapes: (a = (r = this.detectionResults.faceBlendshapes) == null ? void 0 : r[t]) == null ? void 0 : a.categories,
1136
+ transformationMatrix: (c = this.detectionResults.facialTransformationMatrixes) == null ? void 0 : c[t]
1137
+ };
1138
+ }
1139
+ async initialize(t) {
1140
+ var c;
1141
+ this.numFaces = (t == null ? void 0 : t.numFaces) || 1;
1142
+ const n = await Q.forVisionTasks(
1143
+ new URL(sn, z.assetStorageEndpoint).toString()
1144
+ );
1145
+ (c = this.modelBytes) == null || c.release();
1146
+ const r = Xs(
1147
+ new URL(tn, z.assetStorageEndpoint).toString()
1148
+ );
1149
+ this.modelBytes = r;
1150
+ let a;
1151
+ try {
1152
+ const [o] = await Promise.all([r.bytes, J(n)]);
1153
+ a = await fs.createFromOptions(n, {
1154
+ baseOptions: {
1155
+ modelAssetBuffer: o,
1156
+ delegate: "GPU"
1157
+ },
1158
+ // Keep detection permissive for calibration workflows with dark webcam input.
1159
+ minFaceDetectionConfidence: 0.3,
1160
+ minFacePresenceConfidence: 0.3,
1161
+ minTrackingConfidence: 0.3,
1162
+ outputFaceBlendshapes: !0,
1163
+ outputFacialTransformationMatrixes: !0,
1164
+ runningMode: "VIDEO",
1165
+ numFaces: this.numFaces
1166
+ });
1167
+ } catch (o) {
1168
+ throw this.releaseModelBytes(r), o;
1169
+ }
1170
+ if (this.disposed) {
1171
+ a.close(), this.releaseModelBytes(r);
1172
+ return;
1173
+ }
1174
+ this.landmarker = a;
1175
+ }
1176
+ releaseModelBytes(t = this.modelBytes) {
1177
+ t == null || t.release(), this.modelBytes === t && (this.modelBytes = null);
1178
+ }
1179
+ async run({
1180
+ sourceCanvas: t,
1181
+ getSource: n,
1182
+ targetFps: r,
1183
+ analysisScale: a
1184
+ }) {
1185
+ this.sourceCanvas = t, this.getSource = n, this.setTargetFps(r), this.setAnalysisScale(a), this.analysisCanvas = void 0, this.rafId === null && this.processFaceTracking();
1186
+ }
1187
+ getModelNode() {
1188
+ const t = this, n = {
1189
+ get detectionResults() {
1190
+ return t.detectionResults;
1191
+ },
1192
+ get numFaces() {
1193
+ return t.numFaces;
1194
+ },
1195
+ getDetectionResults: this.getDetectionResults.bind(this),
1196
+ getFace: this.getFace.bind(this),
1197
+ getRawFaceTrackingData: this.getRawFaceTrackingData.bind(this),
1198
+ setCamera: (r, a = 0) => {
1199
+ this.cameras[a] = r;
1200
+ }
1201
+ };
1202
+ return Object.defineProperty(n, Et, { value: t }), n;
1203
+ }
1204
+ async getPerformanceData() {
1205
+ return {
1206
+ name: this.constructor.name,
1207
+ processingTime: this.processingTime
1208
+ };
1209
+ }
1210
+ }
1211
+ const on = (e) => e > 1 ? 1024 : 512;
1212
+ var G = /* @__PURE__ */ ((e) => (e.ClosedFist = "closed_fist", e.OpenPalm = "open_palm", e.PointingUp = "pointing_up", e.ThumbDown = "thumb_down", e.ThumbUp = "thumb_up", e.Victory = "victory", e.ILoveYou = "i_love_you", e.None = "none", e))(G || {});
1213
+ const cn = 512, ln = {
1214
+ Closed_Fist: G.ClosedFist,
1215
+ Open_Palm: G.OpenPalm,
1216
+ Pointing_Up: G.PointingUp,
1217
+ Thumb_Down: G.ThumbDown,
1218
+ Thumb_Up: G.ThumbUp,
1219
+ Victory: G.Victory,
1220
+ ILoveYou: G.ILoveYou,
1221
+ None: G.None
1222
+ }, dn = 15;
1223
+ class hn extends $ {
1224
+ constructor() {
1225
+ super();
1226
+ u(this, "landmarker", null);
1227
+ u(this, "processingTime", null);
1228
+ u(this, "coordinates");
1229
+ u(this, "gesture");
1230
+ u(this, "sourceCanvas");
1231
+ u(this, "downscaler", new me(cn));
1232
+ }
1233
+ async getGestureData() {
1234
+ var d, l;
1235
+ if (!this.landmarker || !this.sourceCanvas)
1236
+ return;
1237
+ const t = this.downscaler.draw(this.sourceCanvas), n = performance.now(), r = this.landmarker.recognizeForVideo(t, n), a = performance.now();
1238
+ this.processingTime = a - n, this.recordInference(n, a), this.recordDetections(r.landmarks.length, ((l = (d = r.gestures[0]) == null ? void 0 : d[0]) == null ? void 0 : l.score) ?? null);
1239
+ const c = r.landmarks[0], o = [];
1240
+ if (c) {
1241
+ const h = r.gestures[0][0].categoryName;
1242
+ return c.forEach((m) => {
1243
+ o.push(ue(m));
1244
+ }), {
1245
+ coordinates: o,
1246
+ gesture: ln[h]
1247
+ };
1248
+ }
1249
+ return { coordinates: void 0, gesture: void 0 };
1250
+ }
1251
+ async processGestureTracking() {
1252
+ if (!this.disposed) {
1253
+ if (this.shouldRunInference()) {
1254
+ const t = await this.getGestureData();
1255
+ t && (this.coordinates = t.coordinates, this.gesture = t.gesture);
1256
+ }
1257
+ this.disposed || this.paused || (this.rafId = requestAnimationFrame(this.processGestureTracking.bind(this)));
1258
+ }
1259
+ }
1260
+ resume() {
1261
+ this.paused && (super.resume(), this.processGestureTracking());
1262
+ }
1263
+ dispose() {
1264
+ if (super.dispose(), this.landmarker) {
1265
+ try {
1266
+ this.landmarker.close();
1267
+ } catch {
1268
+ }
1269
+ this.landmarker = null;
1270
+ }
1271
+ this.sourceCanvas = void 0, this.downscaler.dispose(), this.coordinates = void 0, this.gesture = void 0;
1272
+ }
1273
+ async initialize() {
1274
+ const t = await Q.forVisionTasks(
1275
+ new URL("/assets/xr/wasm", z.assetStorageEndpoint).toString()
1276
+ ), [n] = await Promise.all([
1277
+ Z(
1278
+ new URL(
1279
+ "/assets/xr/models/gesture_tracking.task",
1280
+ z.assetStorageEndpoint
1281
+ ).toString()
1282
+ ),
1283
+ J(t)
1284
+ ]), r = await gs.createFromOptions(t, {
1285
+ baseOptions: {
1286
+ modelAssetBuffer: n,
1287
+ delegate: "GPU"
1288
+ },
1289
+ runningMode: "VIDEO",
1290
+ numHands: 1
1291
+ });
1292
+ this.landmarker = r;
1293
+ }
1294
+ async run({ sourceCanvas: t, targetFps: n, analysisScale: r }) {
1295
+ this.setAnalysisScale(r), this.downscaler.setScale(this.analysisScale), this.sourceCanvas = t, this.setTargetFps(n ?? dn), this.rafId === null && await this.processGestureTracking();
1296
+ }
1297
+ getModelNode() {
1298
+ const t = this;
1299
+ return {
1300
+ get coordinates() {
1301
+ return t.coordinates;
1302
+ },
1303
+ get gesture() {
1304
+ return t.gesture;
1305
+ }
1306
+ };
1307
+ }
1308
+ async getPerformanceData() {
1309
+ return {
1310
+ name: this.constructor.name,
1311
+ processingTime: this.processingTime
1312
+ };
1313
+ }
1314
+ }
1315
+ class un extends $ {
1316
+ constructor() {
1317
+ super();
1318
+ u(this, "landmarker", null);
1319
+ u(this, "status", "loading");
1320
+ u(this, "error", null);
1321
+ u(this, "processingTime", null);
1322
+ u(this, "sourceCanvas");
1323
+ u(this, "getSource");
1324
+ u(this, "downscaler", new me(Ne().analysisMaxDimension));
1325
+ u(this, "raw");
1326
+ u(this, "delegatePolicy", "auto");
1327
+ u(this, "delegate", "GPU");
1328
+ /** Kept so the graph can be rebuilt on another delegate without refetching. */
1329
+ u(this, "vision", null);
1330
+ u(this, "modelBuffer", null);
1331
+ u(this, "graphOptions", {});
1332
+ u(this, "rebuilding", !1);
1333
+ u(this, "fallbackAttempted", !1);
1334
+ u(this, "result", xs());
1335
+ u(this, "builder", new Ts());
1336
+ u(this, "node");
1337
+ this.node = {
1338
+ getResult: () => this.result,
1339
+ getRawResult: () => this.raw,
1340
+ getStatus: () => this.status,
1341
+ getError: () => this.error,
1342
+ getDelegate: () => this.delegate,
1343
+ setOptions: (t) => this.setRuntimeOptions(t)
1344
+ };
1345
+ }
1346
+ setRuntimeOptions(t) {
1347
+ const n = this.builder.getOptions().analysisMaxDimension;
1348
+ this.builder.setOptions(t);
1349
+ const r = this.builder.getOptions().analysisMaxDimension;
1350
+ r !== n && (this.downscaler.dispose(), this.downscaler = new me(r), this.downscaler.setScale(this.analysisScale));
1351
+ }
1352
+ async initialize(t) {
1353
+ this.status = "loading", this.error = null, this.setRuntimeOptions(t ?? {});
1354
+ try {
1355
+ const n = await Q.forVisionTasks(
1356
+ new URL("/assets/xr/wasm", z.assetStorageEndpoint).toString()
1357
+ ), [r] = await Promise.all([
1358
+ Z((t == null ? void 0 : t.modelUrl) ?? vt),
1359
+ J(n)
1360
+ ]);
1361
+ this.vision = n, this.modelBuffer = r, this.graphOptions = {
1362
+ runningMode: "VIDEO",
1363
+ outputFaceBlendshapes: (t == null ? void 0 : t.outputFaceBlendshapes) ?? !0,
1364
+ minFaceDetectionConfidence: t == null ? void 0 : t.minFaceDetectionConfidence,
1365
+ minFacePresenceConfidence: t == null ? void 0 : t.minFacePresenceConfidence,
1366
+ minPoseDetectionConfidence: t == null ? void 0 : t.minPoseDetectionConfidence,
1367
+ minPosePresenceConfidence: t == null ? void 0 : t.minPosePresenceConfidence,
1368
+ minHandLandmarksConfidence: t == null ? void 0 : t.minHandLandmarksConfidence
1369
+ }, this.delegatePolicy = (t == null ? void 0 : t.delegate) ?? "auto", this.delegate = this.delegatePolicy === "CPU" ? "CPU" : "GPU";
1370
+ const a = await this.createLandmarker(this.delegate);
1371
+ if (this.disposed) {
1372
+ a.close();
1373
+ return;
1374
+ }
1375
+ this.landmarker = a, this.status = "ready";
1376
+ } catch (n) {
1377
+ throw this.status = "error", this.error = n instanceof Error ? n : new Error(String(n)), this.error;
1378
+ }
1379
+ }
1380
+ createLandmarker(t) {
1381
+ if (!this.vision || !this.modelBuffer)
1382
+ throw new Error("HolisticTrackingModel: initialize() has not loaded the model");
1383
+ return ps.createFromOptions(this.vision, {
1384
+ baseOptions: { modelAssetBuffer: this.modelBuffer, delegate: t },
1385
+ ...this.graphOptions
1386
+ });
1387
+ }
1388
+ /**
1389
+ * The GPU graph can fail on its first run (the face-blendshape stage has no
1390
+ * WebGL kernel for one of its ops). Rebuild on the CPU once, keep the RAF
1391
+ * loop alive meanwhile, and run one detection right away so static sources
1392
+ * (which pulse models once) still get a result.
1393
+ */
1394
+ async fallbackToCpu(t) {
1395
+ this.fallbackAttempted = !0, this.rebuilding = !0, this.status = "loading", console.warn(
1396
+ "[xr-sdk holistic] GPU inference failed; rebuilding the graph on the CPU delegate.",
1397
+ t.message
1398
+ );
1399
+ const n = this.landmarker;
1400
+ try {
1401
+ const r = await this.createLandmarker("CPU");
1402
+ if (this.disposed) {
1403
+ r.close();
1404
+ return;
1405
+ }
1406
+ this.landmarker = r, this.delegate = "CPU", this.status = "ready", this.error = null;
1407
+ try {
1408
+ n == null || n.close();
1409
+ } catch {
1410
+ }
1411
+ this.rebuilding = !1, this.detectOnce();
1412
+ } catch (r) {
1413
+ this.rebuilding = !1, this.status = "error", this.error = r instanceof Error ? r : new Error(String(r));
1414
+ }
1415
+ }
1416
+ /** One detect + publish outside the loop (used after a delegate rebuild). */
1417
+ detectOnce() {
1418
+ this.disposed || !this.landmarker || !this.sourceCanvas || (this.detect(), this.builder.update(this.raw, performance.now(), this.result, this.isMirrored()));
1419
+ }
1420
+ detect() {
1421
+ var r, a, c, o, d;
1422
+ if (!this.landmarker || !this.sourceCanvas) return;
1423
+ const t = this.downscaler.draw(this.sourceCanvas), n = performance.now();
1424
+ try {
1425
+ this.raw = this.landmarker.detectForVideo(t, n), this.status === "error" && (this.status = "ready", this.error = null), this.recordInferenceError(null);
1426
+ const l = this.raw, h = ((r = l.faceLandmarks) != null && r.length ? 1 : 0) + ((a = l.leftHandLandmarks) != null && a.length ? 1 : 0) + ((c = l.rightHandLandmarks) != null && c.length ? 1 : 0) + ((o = l.poseLandmarks) != null && o.length ? 1 : 0), m = (d = l.poseLandmarks) == null ? void 0 : d[0];
1427
+ this.recordDetections(
1428
+ h,
1429
+ m && m.length ? m.reduce((y, S) => y + (S.visibility ?? 0), 0) / m.length : null
1430
+ );
1431
+ } catch (l) {
1432
+ const h = l instanceof Error ? l : new Error(String(l));
1433
+ this.delegatePolicy === "auto" && this.delegate === "GPU" && !this.fallbackAttempted ? this.fallbackToCpu(h) : (this.status = "error", this.error = h, this.recordInferenceError(h));
1434
+ }
1435
+ this.processingTime = performance.now() - n, this.recordInference(n);
1436
+ }
1437
+ /** The session mirrors only the webcam feed (an unknown kind is treated as webcam). */
1438
+ isMirrored() {
1439
+ var t;
1440
+ return Me((t = this.getSource) == null ? void 0 : t.call(this));
1441
+ }
1442
+ async run({
1443
+ sourceCanvas: t,
1444
+ getSource: n,
1445
+ targetFps: r,
1446
+ analysisScale: a
1447
+ }) {
1448
+ this.sourceCanvas = t, this.getSource = n, this.setTargetFps(r), this.setAnalysisScale(a), this.downscaler.setScale(this.analysisScale), this.rafId === null && await this.process();
1449
+ }
1450
+ async process() {
1451
+ this.disposed || this.paused || !this.landmarker || (!this.rebuilding && this.shouldRunInference() && this.detect(), this.builder.update(this.raw, performance.now(), this.result, this.isMirrored()), !(this.disposed || this.paused) && (this.rafId = requestAnimationFrame(this.process.bind(this))));
1452
+ }
1453
+ resume() {
1454
+ this.paused && (super.resume(), this.process());
1455
+ }
1456
+ dispose() {
1457
+ if (super.dispose(), this.landmarker) {
1458
+ try {
1459
+ this.landmarker.close();
1460
+ } catch {
1461
+ }
1462
+ this.landmarker = null;
1463
+ }
1464
+ this.sourceCanvas = void 0, this.getSource = void 0, this.downscaler.dispose(), this.vision = null, this.modelBuffer = null, this.raw = void 0, this.builder.reset(), this.result.face = null, this.result.leftHand = null, this.result.rightHand = null, this.result.pose = null;
1465
+ }
1466
+ getModelNode() {
1467
+ return this.node;
1468
+ }
1469
+ async getPerformanceData() {
1470
+ return { name: this.constructor.name, processingTime: this.processingTime };
1471
+ }
1472
+ }
1473
+ const mn = (e) => e === "left" ? "right" : "left", fn = (e, s) => s ? mn(e) : e, gn = /left|right|Left|Right/, pn = {
1474
+ left: "right",
1475
+ right: "left",
1476
+ Left: "Right",
1477
+ Right: "Left"
1478
+ }, yn = (e) => e.replace(gn, (s) => pn[s]), Ir = (e, s) => s ? yn(e) : e, _r = (e) => e ? -1 : 1, wn = [
1479
+ "wrist",
1480
+ "thumbCmc",
1481
+ "thumbMcp",
1482
+ "thumbIp",
1483
+ "thumbTip",
1484
+ "indexMcp",
1485
+ "indexPip",
1486
+ "indexDip",
1487
+ "indexTip",
1488
+ "middleMcp",
1489
+ "middlePip",
1490
+ "middleDip",
1491
+ "middleTip",
1492
+ "ringMcp",
1493
+ "ringPip",
1494
+ "ringDip",
1495
+ "ringTip",
1496
+ "pinkyMcp",
1497
+ "pinkyPip",
1498
+ "pinkyDip",
1499
+ "pinkyTip"
1500
+ ], Pr = Object.fromEntries(
1501
+ wn.map((e, s) => [e, s])
1502
+ ), vn = 200, le = (e, s) => Math.hypot(e.x - s.x, e.y - s.y), de = (e) => e === "left" ? "right" : "left", Oe = (e, s, t) => ({
1503
+ handedness: s,
1504
+ score: e.score,
1505
+ world: e.world,
1506
+ image: e.image,
1507
+ timestampMs: t,
1508
+ held: !1
1509
+ }), Sn = (e, s, t, {
1510
+ holdMs: n = vn,
1511
+ confidentScore: r = 0.8,
1512
+ continuityMs: a = 500
1513
+ } = {}) => {
1514
+ const c = (l) => !!l && t - l.timestampMs <= a && l.image.length > 0, o = { left: null, right: null }, d = e.filter((l) => l.image.length > 0).slice(0, 2);
1515
+ if (d.length === 2) {
1516
+ const [l, h] = d, m = l.handedness !== void 0 && h.handedness !== void 0 && l.handedness !== h.handedness, y = l.score >= r && h.score >= r;
1517
+ let S;
1518
+ if (m && y)
1519
+ S = l.handedness;
1520
+ else if (c(s.left) && c(s.right)) {
1521
+ const M = le(l.image[0], s.left.image[0]) + le(h.image[0], s.right.image[0]), C = le(l.image[0], s.right.image[0]) + le(h.image[0], s.left.image[0]);
1522
+ S = M <= C ? "left" : "right";
1523
+ } else if (m)
1524
+ S = l.handedness;
1525
+ else {
1526
+ const M = l.score >= h.score ? l : h, C = M.handedness ?? "right";
1527
+ S = M === l ? C : de(C);
1528
+ }
1529
+ o[S] = Oe(l, S, t), o[de(S)] = Oe(h, de(S), t);
1530
+ } else if (d.length === 1) {
1531
+ const [l] = d;
1532
+ let h = l.handedness ?? "right";
1533
+ if (l.score < r || l.handedness === void 0) {
1534
+ const m = (M) => c(M) ? le(l.image[0], M.image[0]) : 1 / 0, y = m(s[h]);
1535
+ m(s[de(h)]) < y && (h = de(h));
1536
+ }
1537
+ o[h] = Oe(l, h, t);
1538
+ }
1539
+ for (const l of ["left", "right"]) {
1540
+ const h = s[l];
1541
+ o[l] || !h || t - h.timestampMs <= n && (o[l] = { ...h, held: !0 });
1542
+ }
1543
+ return o;
1544
+ }, Mn = (e, s) => {
1545
+ const t = e == null ? void 0 : e.toLowerCase();
1546
+ if (!(t !== "left" && t !== "right"))
1547
+ return fn(t, s);
1548
+ }, Cn = (e, s = { x: 0, y: 0, z: 0 }) => (s.x = e.x * 100, s.y = -e.y * 100, s.z = -e.z * 100, s), kn = 512, xn = Object.freeze({
1549
+ minHandDetectionConfidence: 0.5,
1550
+ minHandPresenceConfidence: 0.65,
1551
+ minTrackingConfidence: 0.5
1552
+ });
1553
+ class bn extends $ {
1554
+ constructor() {
1555
+ super();
1556
+ u(this, "landmarker", null);
1557
+ u(this, "processingTime", null);
1558
+ u(this, "hands");
1559
+ u(this, "coordinates");
1560
+ u(this, "gesture");
1561
+ u(this, "handedness");
1562
+ u(this, "poses", { left: null, right: null });
1563
+ u(this, "sourceCanvas");
1564
+ u(this, "getSource");
1565
+ u(this, "downscaler", new me(kn));
1566
+ }
1567
+ async getHandData() {
1568
+ var m, y, S;
1569
+ if (!this.landmarker || !this.sourceCanvas)
1570
+ return;
1571
+ const t = this.downscaler.draw(this.sourceCanvas), n = performance.now(), r = this.landmarker.detectForVideo(t, n), a = performance.now();
1572
+ this.processingTime = a - n, this.recordInference(n, a);
1573
+ const c = [], o = [], d = r.handedness ?? r.handednesses ?? [];
1574
+ this.recordDetections(r.landmarks.length, ((y = (m = d[0]) == null ? void 0 : m[0]) == null ? void 0 : y.score) ?? null);
1575
+ const l = Me((S = this.getSource) == null ? void 0 : S.call(this));
1576
+ if (r.landmarks.forEach((M, C) => {
1577
+ var H, T;
1578
+ if (!M || M.length === 0)
1579
+ return;
1580
+ const E = M.map(
1581
+ (U) => ue(U)
1582
+ ), _ = (((H = r.worldLandmarks) == null ? void 0 : H[C]) ?? []).map(
1583
+ (U) => Cn(U)
1584
+ ), g = (T = d[C]) == null ? void 0 : T[0], v = Mn(g == null ? void 0 : g.categoryName, l), w = (g == null ? void 0 : g.score) ?? 0, x = M[0].z < 0 ? "closed_fist" : "open_palm";
1585
+ c.push({ coordinates: E, worldCoordinates: _, gesture: x, handedness: v, handednessScore: w }), o.push({
1586
+ handedness: v,
1587
+ score: w,
1588
+ world: _,
1589
+ image: E
1590
+ });
1591
+ }), this.poses = Sn(o, this.poses, n), !c.length)
1592
+ return {
1593
+ hands: void 0,
1594
+ coordinates: void 0,
1595
+ gesture: void 0,
1596
+ handedness: void 0
1597
+ };
1598
+ const h = c[0];
1599
+ return {
1600
+ hands: c,
1601
+ coordinates: h.coordinates,
1602
+ gesture: h.gesture,
1603
+ handedness: h.handedness
1604
+ };
1605
+ }
1606
+ async processHandTracking() {
1607
+ if (!this.disposed) {
1608
+ if (this.shouldRunInference()) {
1609
+ const t = await this.getHandData();
1610
+ t && (this.hands = t.hands, this.coordinates = t.coordinates, this.gesture = t.gesture, this.handedness = t.handedness);
1611
+ }
1612
+ this.disposed || this.paused || (this.rafId = requestAnimationFrame(this.processHandTracking.bind(this)));
1613
+ }
1614
+ }
1615
+ resume() {
1616
+ this.paused && (super.resume(), this.processHandTracking());
1617
+ }
1618
+ dispose() {
1619
+ if (super.dispose(), this.landmarker) {
1620
+ try {
1621
+ this.landmarker.close();
1622
+ } catch {
1623
+ }
1624
+ this.landmarker = null;
1625
+ }
1626
+ this.sourceCanvas = void 0, this.getSource = void 0, this.hands = void 0, this.poses = { left: null, right: null }, this.downscaler.dispose(), this.coordinates = void 0, this.gesture = void 0, this.handedness = void 0;
1627
+ }
1628
+ async initialize() {
1629
+ const t = await Q.forVisionTasks(
1630
+ new URL("/assets/xr/wasm", z.assetStorageEndpoint).toString()
1631
+ ), [n] = await Promise.all([
1632
+ Z(
1633
+ new URL("/assets/xr/models/hand_tracking.task", z.assetStorageEndpoint).toString()
1634
+ ),
1635
+ J(t)
1636
+ ]), r = await ys.createFromOptions(t, {
1637
+ baseOptions: {
1638
+ modelAssetBuffer: n,
1639
+ delegate: "GPU"
1640
+ },
1641
+ runningMode: "VIDEO",
1642
+ numHands: 2,
1643
+ ...xn
1644
+ });
1645
+ this.landmarker = r;
1646
+ }
1647
+ async run({
1648
+ sourceCanvas: t,
1649
+ getSource: n,
1650
+ targetFps: r,
1651
+ analysisScale: a
1652
+ }) {
1653
+ this.getSource = n, this.setAnalysisScale(a), this.downscaler.setScale(this.analysisScale), this.sourceCanvas = t, this.setTargetFps(r), this.rafId === null && await this.processHandTracking();
1654
+ }
1655
+ getModelNode() {
1656
+ const t = this;
1657
+ return {
1658
+ get hands() {
1659
+ return t.hands;
1660
+ },
1661
+ get coordinates() {
1662
+ return t.coordinates;
1663
+ },
1664
+ get gesture() {
1665
+ return t.gesture;
1666
+ },
1667
+ get handedness() {
1668
+ return t.handedness;
1669
+ },
1670
+ get poses() {
1671
+ return t.poses;
1672
+ },
1673
+ getHandPose: (n) => t.poses[n]
1674
+ };
1675
+ }
1676
+ async getPerformanceData() {
1677
+ return {
1678
+ name: this.constructor.name,
1679
+ processingTime: this.processingTime
1680
+ };
1681
+ }
1682
+ }
1683
+ const Tn = 24, En = 720, An = [
1684
+ [255, 255, 255, 255],
1685
+ // 0: background → green 255, kept
1686
+ [0, 0, 0, 0]
1687
+ // 1: person → green 0, discarded
1688
+ ];
1689
+ class Rn extends $ {
1690
+ constructor() {
1691
+ super();
1692
+ u(this, "segmenter", null);
1693
+ u(this, "processingTime", null);
1694
+ u(this, "sourceCanvas");
1695
+ // input source canvas
1696
+ u(this, "processCanvas");
1697
+ // downscaled canvas of sourceCanvas for processing
1698
+ u(this, "filterCanvas");
1699
+ // post-processing (blur) canvas
1700
+ // Optional high-resolution input override. The shared session feed canvas is
1701
+ // sized to the on-screen display layout (often a small, display-fit crop),
1702
+ // which starves the segmenter of the resolution it needs to capture the whole
1703
+ // body. When a consumer supplies a native-resolution source here (e.g. the raw
1704
+ // <video>/<img>), the segmenter runs on THAT instead — letterboxed into the
1705
+ // process canvas so nothing is cropped. Falls back to `sourceCanvas` when unset.
1706
+ u(this, "inputSource");
1707
+ u(this, "inputSourceSize");
1708
+ // The segmenter's own WebGL2 context. DrawingUtils renders the inverted mask
1709
+ // into this context on the GPU; we then blit that GL canvas straight into the
1710
+ // mask canvas with a single `drawImage` — a GPU→GPU transfer, no CPU readback
1711
+ // and no per-pixel JS loop. (A spike proved `drawImage(glCanvas)` reads the
1712
+ // full DrawingUtils output correctly; the earlier "reads empty" wall that once
1713
+ // forced a readPixels path was a false alarm.)
1714
+ u(this, "glCanvas");
1715
+ u(this, "drawingUtils");
1716
+ u(this, "useGpuMaskPath", !1);
1717
+ // CPU-fallback reused ImageData, allocated on size change only. Used ONLY when
1718
+ // WebGL2 is unavailable and we must read the single-channel mask back by hand.
1719
+ u(this, "maskImageData");
1720
+ u(this, "maskCanvas", null);
1721
+ u(this, "segmentationMaskTexture");
1722
+ u(this, "isMaskSetup", !1);
1723
+ u(this, "isProcessing", !1);
1724
+ // Live clone of the most recent category mask, kept so getRawSegmentationData()
1725
+ // can read the single-channel Uint8Array lazily — that readback is paid ONLY
1726
+ // when a consumer actually asks for raw data. Cloned because the mask returned
1727
+ // by segmentForVideo is invalidated on the next inference call.
1728
+ u(this, "latestMask", null);
1729
+ // Per-frame cache of the read-back array, so repeated getRawSegmentationData()
1730
+ // calls within one frame don't re-run the GPU→CPU transfer.
1731
+ u(this, "rawCache", null);
1732
+ /** When the frame behind `latestMask` was segmented (`performance.now()`). */
1733
+ u(this, "latestMaskTimeMs", 0);
1734
+ u(this, "quality", "medium");
1735
+ u(this, "stagingCanvas");
1736
+ }
1737
+ getQualityScaleFactor() {
1738
+ switch (this.quality) {
1739
+ case "low":
1740
+ return 0.5;
1741
+ case "medium":
1742
+ return 0.75;
1743
+ case "high":
1744
+ return 1;
1745
+ default:
1746
+ return 0.5;
1747
+ }
1748
+ }
1749
+ /**
1750
+ * Set (or clear) a high-resolution input override. Pass the raw <video>/<img>
1751
+ * (or any CanvasImageSource with intrinsic dimensions) to run segmentation on
1752
+ * native-resolution, uncropped frames instead of the small display-fit session
1753
+ * feed. Pass `undefined` to revert to the shared feed canvas.
1754
+ */
1755
+ setInputSource(t) {
1756
+ this.inputSource = t, this.inputSourceSize = t ? this.readIntrinsicSize(t) : void 0;
1757
+ }
1758
+ readIntrinsicSize(t) {
1759
+ if (t instanceof HTMLVideoElement)
1760
+ return t.videoWidth > 0 ? { width: t.videoWidth, height: t.videoHeight } : void 0;
1761
+ if (t instanceof HTMLImageElement)
1762
+ return t.naturalWidth > 0 ? { width: t.naturalWidth, height: t.naturalHeight } : void 0;
1763
+ const n = t.width, r = t.height;
1764
+ return typeof n == "number" && n > 0 && typeof r == "number" && r > 0 ? { width: n, height: r } : void 0;
1765
+ }
1766
+ /**
1767
+ * Size the process canvas to the override input's aspect ratio, bounded by
1768
+ * PROCESS_MAX_DIM on the long edge, and keep the GL canvas in sync so the GPU
1769
+ * mask renders at the same resolution. No-op when there is no override, or when
1770
+ * the intrinsic size hasn't changed since the last frame.
1771
+ */
1772
+ ensureProcessCanvasForInput() {
1773
+ if (!this.processCanvas || !this.inputSource) return;
1774
+ const t = this.readIntrinsicSize(this.inputSource);
1775
+ if (!t) return;
1776
+ this.inputSourceSize = t;
1777
+ const n = Math.min(1, En / Math.max(t.width, t.height)), r = Math.max(1, Math.round(t.width * n)), a = Math.max(1, Math.round(t.height * n));
1778
+ this.processCanvas.width === r && this.processCanvas.height === a || (this.processCanvas.width = r, this.processCanvas.height = a, this.glCanvas && (this.glCanvas.width = r, this.glCanvas.height = a), this.maskImageData = void 0);
1779
+ }
1780
+ async processSegmentation() {
1781
+ if (this.disposed || !this.isProcessing || !this.maskCanvas || !this.processCanvas)
1782
+ return;
1783
+ if (!this.shouldRunInference()) {
1784
+ if (this.disposed || this.paused) return;
1785
+ this.rafId = requestAnimationFrame(this.processSegmentation.bind(this));
1786
+ return;
1787
+ }
1788
+ const t = this.inputSource ?? this.sourceCanvas;
1789
+ if (!this.segmenter || !t) {
1790
+ if (this.disposed || this.paused) return;
1791
+ this.rafId = requestAnimationFrame(this.processSegmentation.bind(this));
1792
+ return;
1793
+ }
1794
+ const n = performance.now();
1795
+ this.ensureProcessCanvasForInput();
1796
+ const r = this.processCanvas.getContext("2d");
1797
+ if (r) {
1798
+ const d = this.processCanvas.width, l = this.processCanvas.height;
1799
+ if (r.clearRect(0, 0, d, l), this.inputSource && this.inputSourceSize) {
1800
+ const { width: h, height: m } = this.inputSourceSize, y = Math.min(d / h, l / m), S = h * y, M = m * y;
1801
+ r.drawImage(this.inputSource, (d - S) / 2, (l - M) / 2, S, M);
1802
+ } else
1803
+ r.drawImage(t, 0, 0, d, l);
1804
+ }
1805
+ const a = performance.now(), o = this.segmenter.segmentForVideo(this.processCanvas, a).categoryMask;
1806
+ if (!o) {
1807
+ if (this.disposed || this.paused) return;
1808
+ this.rafId = requestAnimationFrame(this.processSegmentation.bind(this));
1809
+ return;
1810
+ }
1811
+ if (this.rawCache = null, this.latestMaskTimeMs = a, this.latestMask && (this.latestMask.close(), this.latestMask = null), this.useGpuMaskPath && this.drawingUtils && this.glCanvas)
1812
+ this.drawingUtils.drawCategoryMask(o, An), this.latestMask = o.clone(), o.close(), this.blitGlToMask();
1813
+ else {
1814
+ this.latestMask = o.clone();
1815
+ const d = this.readMaskToImageData(o);
1816
+ o.close(), d && this.blitImageDataToMask(d);
1817
+ }
1818
+ this.segmentationMaskTexture && (this.isMaskSetup || (this.segmentationMaskTexture.format = yt, this.segmentationMaskTexture.minFilter = ve, this.segmentationMaskTexture.magFilter = ve, this.segmentationMaskTexture.generateMipmaps = !1, this.isMaskSetup = !0), this.segmentationMaskTexture.needsUpdate = !0), this.processingTime = performance.now() - n, this.recordInference(n), this.recordDetections(1, null), !(this.disposed || this.paused) && (this.rafId = requestAnimationFrame(this.processSegmentation.bind(this)));
1819
+ }
1820
+ /**
1821
+ * Blit the GPU-rendered mask (already RGBA-inverted by drawCategoryMask)
1822
+ * straight from the GL canvas into the mask canvas, cover-fitted through the
1823
+ * soft-edge blur. `drawImage(glCanvas)` is a GPU→GPU transfer — no readPixels,
1824
+ * no CPU array, no ImageData, no row flip (the 2D canvas presents the WebGL
1825
+ * canvas right-side-up). This is the zero-readback path.
1826
+ */
1827
+ blitGlToMask() {
1828
+ if (!this.maskCanvas || !this.filterCanvas || !this.glCanvas) return;
1829
+ const t = this.maskCanvas.getContext("2d"), n = this.filterCanvas.getContext("2d");
1830
+ !t || !n || (n.filter = "blur(0.5px)", n.clearRect(0, 0, this.filterCanvas.width, this.filterCanvas.height), n.drawImage(this.glCanvas, 0, 0, this.filterCanvas.width, this.filterCanvas.height), t.clearRect(0, 0, this.maskCanvas.width, this.maskCanvas.height), t.drawImage(this.filterCanvas, 0, 0, this.maskCanvas.width, this.maskCanvas.height));
1831
+ }
1832
+ /**
1833
+ * CPU-fallback inverted-alpha ImageData build (only when the GPU path is off).
1834
+ * The single-channel mask is expanded to RGBA with the person→transparent,
1835
+ * background→opaque convention (green carries the signal for the alphaMap).
1836
+ */
1837
+ readMaskToImageData(t) {
1838
+ const n = t.getAsUint8Array(), { width: r, height: a } = t;
1839
+ if (!n || r <= 0 || a <= 0) return null;
1840
+ (!this.maskImageData || this.maskImageData.width !== r || this.maskImageData.height !== a) && (this.maskImageData = new ImageData(r, a));
1841
+ const c = this.maskImageData.data;
1842
+ for (let o = 0; o < n.length; o += 1) {
1843
+ const d = n[o] === 255 ? 0 : 255;
1844
+ c[o * 4] = 255, c[o * 4 + 1] = d, c[o * 4 + 2] = 255, c[o * 4 + 3] = d;
1845
+ }
1846
+ return this.maskImageData;
1847
+ }
1848
+ /**
1849
+ * CPU-fallback blit: put the inverted-alpha mask ImageData into maskCanvas
1850
+ * with a soft-edge blur, cover-fitted to the render target. Only used when the
1851
+ * GPU path is off; the GPU path blits the GL canvas directly (blitGlToMask).
1852
+ */
1853
+ blitImageDataToMask(t) {
1854
+ if (!this.maskCanvas || !this.filterCanvas) return;
1855
+ const n = this.maskCanvas.getContext("2d"), r = this.filterCanvas.getContext("2d");
1856
+ if (!n || !r) return;
1857
+ const a = this.getStagingCanvas(t.width, t.height), c = a.getContext("2d");
1858
+ c && (c.putImageData(t, 0, 0), r.filter = "blur(0.5px)", r.clearRect(0, 0, this.filterCanvas.width, this.filterCanvas.height), r.drawImage(a, 0, 0, this.filterCanvas.width, this.filterCanvas.height), n.clearRect(0, 0, this.maskCanvas.width, this.maskCanvas.height), n.drawImage(this.filterCanvas, 0, 0, this.maskCanvas.width, this.maskCanvas.height));
1859
+ }
1860
+ getStagingCanvas(t, n) {
1861
+ return this.stagingCanvas || (this.stagingCanvas = document.createElement("canvas")), this.stagingCanvas.width !== t && (this.stagingCanvas.width = t), this.stagingCanvas.height !== n && (this.stagingCanvas.height = n), this.stagingCanvas;
1862
+ }
1863
+ resume() {
1864
+ this.paused && (super.resume(), this.processSegmentation());
1865
+ }
1866
+ dispose() {
1867
+ if (super.dispose(), this.isProcessing = !1, this.latestMask) {
1868
+ try {
1869
+ this.latestMask.close();
1870
+ } catch {
1871
+ }
1872
+ this.latestMask = null;
1873
+ }
1874
+ if (this.rawCache = null, this.segmenter) {
1875
+ try {
1876
+ this.segmenter.close();
1877
+ } catch {
1878
+ }
1879
+ this.segmenter = null;
1880
+ }
1881
+ this.drawingUtils = void 0, this.glCanvas = void 0, this.maskImageData = void 0, this.segmentationMaskTexture && (this.segmentationMaskTexture.dispose(), this.segmentationMaskTexture = void 0), this.sourceCanvas = void 0, this.inputSource = void 0, this.inputSourceSize = void 0, this.processCanvas = void 0, this.filterCanvas = void 0, this.stagingCanvas = void 0, this.maskCanvas = null;
1882
+ }
1883
+ async initialize(t) {
1884
+ this.quality = (t == null ? void 0 : t.quality) ?? "low";
1885
+ const n = await Q.forVisionTasks(
1886
+ new URL("/assets/xr/wasm", z.assetStorageEndpoint).toString()
1887
+ ), [r] = await Promise.all([
1888
+ Z(
1889
+ new URL("/assets/xr/models/segmentation.tflite", z.assetStorageEndpoint).toString()
1890
+ ),
1891
+ J(n)
1892
+ ]);
1893
+ this.glCanvas = new OffscreenCanvas(1, 1);
1894
+ const a = this.glCanvas.getContext("webgl2", {
1895
+ preserveDrawingBuffer: !0
1896
+ });
1897
+ this.segmenter = await pt.createFromOptions(n, {
1898
+ baseOptions: {
1899
+ modelAssetBuffer: r,
1900
+ delegate: "GPU"
1901
+ },
1902
+ ...a ? { canvas: this.glCanvas } : {},
1903
+ outputCategoryMask: !0,
1904
+ outputConfidenceMasks: !1,
1905
+ runningMode: "VIDEO"
1906
+ }), a ? (this.drawingUtils = new ws(a), this.useGpuMaskPath = !0) : this.useGpuMaskPath = !1;
1907
+ }
1908
+ async run({
1909
+ sourceCanvas: t,
1910
+ renderWidth: n,
1911
+ renderHeight: r,
1912
+ targetFps: a
1913
+ }) {
1914
+ var o;
1915
+ if (!t)
1916
+ return;
1917
+ this.setTargetFps(a ?? Tn), this.isProcessing = !1, this.rafId !== null && (cancelAnimationFrame(this.rafId), this.rafId = null);
1918
+ const c = this.getQualityScaleFactor();
1919
+ this.sourceCanvas = t, this.processCanvas = document.createElement("canvas"), this.processCanvas.width = t.width * c, this.processCanvas.height = t.height * c, this.glCanvas && (this.glCanvas.width = this.processCanvas.width, this.glCanvas.height = this.processCanvas.height), this.maskImageData = void 0, this.maskCanvas = document.createElement("canvas"), this.maskCanvas.width = n, this.maskCanvas.height = r, this.filterCanvas = document.createElement("canvas"), this.filterCanvas.width = n, this.filterCanvas.height = r, (o = this.segmentationMaskTexture) == null || o.dispose(), this.segmentationMaskTexture = new wt(this.maskCanvas), this.isMaskSetup = !1, this.rawCache = null, this.isProcessing = !0, this.lastInferenceMs = 0, this.rafId = requestAnimationFrame(this.processSegmentation.bind(this));
1920
+ }
1921
+ /**
1922
+ * Lazily read the single-channel mask back to a Uint8Array. Only invoked when
1923
+ * a consumer calls getRawSegmentationData(); the default texture path never
1924
+ * touches it, so apps that only use <VideoBackground> pay no extra readback.
1925
+ */
1926
+ getRawSegmentationData() {
1927
+ if (this.rawCache) return this.rawCache;
1928
+ if (!this.latestMask) return null;
1929
+ const t = this.latestMask.getAsUint8Array();
1930
+ return this.rawCache = {
1931
+ maskData: t,
1932
+ width: this.latestMask.width,
1933
+ height: this.latestMask.height,
1934
+ timestampMs: this.latestMaskTimeMs
1935
+ }, this.rawCache;
1936
+ }
1937
+ getModelNode() {
1938
+ const t = this;
1939
+ return {
1940
+ get backgroundSegmentationMask() {
1941
+ return t.segmentationMaskTexture;
1942
+ },
1943
+ getMaskCanvas: () => t.maskCanvas,
1944
+ getRawSegmentationData: () => t.getRawSegmentationData(),
1945
+ setInputSource: (n) => t.setInputSource(n ?? void 0)
1946
+ };
1947
+ }
1948
+ async getPerformanceData() {
1949
+ return {
1950
+ name: this.constructor.name,
1951
+ processingTime: this.processingTime
1952
+ };
1953
+ }
1954
+ }
1955
+ const Fn = (e, s, t, n = "feed") => ({
1956
+ width: Math.max(1, Math.round(e)),
1957
+ height: Math.max(1, Math.round(s)),
1958
+ indices: new Uint8Array(Math.max(1, Math.round(e)) * Math.max(1, Math.round(s))),
1959
+ labels: t,
1960
+ space: n,
1961
+ version: 0
1962
+ }), Dr = (e) => {
1963
+ e.indices.fill(0);
1964
+ }, Lr = (e, s) => e.labels.indexOf(s), In = (e, s, t) => {
1965
+ const { width: n, height: r, indices: a } = e, c = s.length;
1966
+ if (c < 3) return;
1967
+ let o = 1 / 0, d = -1 / 0;
1968
+ for (let y = 0; y < c; y += 1) {
1969
+ const S = s[y].y * r;
1970
+ S < o && (o = S), S > d && (d = S);
1971
+ }
1972
+ const l = Math.max(0, Math.floor(o)), h = Math.min(r - 1, Math.ceil(d)), m = [];
1973
+ for (let y = l; y <= h; y += 1) {
1974
+ const S = y + 0.5;
1975
+ m.length = 0;
1976
+ for (let C = 0; C < c; C += 1) {
1977
+ const E = s[C], _ = s[(C + 1) % c], g = E.y * r, v = _.y * r;
1978
+ if (S < g == S < v) continue;
1979
+ const w = (S - g) / (v - g);
1980
+ m.push((E.x + w * (_.x - E.x)) * n);
1981
+ }
1982
+ m.sort((C, E) => C - E);
1983
+ const M = y * n;
1984
+ for (let C = 0; C + 1 < m.length; C += 2) {
1985
+ const E = Math.max(0, Math.round(m[C])), _ = Math.min(n, Math.round(m[C + 1]));
1986
+ for (let g = E; g < _; g += 1) a[M + g] = t;
1987
+ }
1988
+ }
1989
+ }, Or = (e, s, t, n, r = []) => {
1990
+ r.length = 0;
1991
+ for (let a = 0; a < t.length; a += 1) {
1992
+ const c = s[t[a]];
1993
+ if (!c) return;
1994
+ r.push(c);
1995
+ }
1996
+ In(e, r, n);
1997
+ }, dt = (e) => e, ht = {
1998
+ hair: {
1999
+ labels: ["bg", "hair"],
2000
+ assetPath: "/assets/xr/models/hair_segmenter.tflite",
2001
+ defaultUrl: "https://storage.googleapis.com/mediapipe-models/image_segmenter/hair_segmenter/float32/latest/hair_segmenter.tflite",
2002
+ decode: dt
2003
+ },
2004
+ multiclass: {
2005
+ labels: ["bg", "hair", "body_skin", "face_skin", "clothes", "others"],
2006
+ assetPath: "/assets/xr/models/selfie_multiclass_256x256.tflite",
2007
+ defaultUrl: "https://storage.googleapis.com/mediapipe-models/image_segmenter/selfie_multiclass_256x256/float32/latest/selfie_multiclass_256x256.tflite",
2008
+ decode: dt
2009
+ }
2010
+ }, _n = (e, s, t) => {
2011
+ const n = t.length === e.length ? t : new Uint8Array(e.length);
2012
+ for (let r = 0; r < e.length; r += 1) n[r] = s(e[r]);
2013
+ return n;
2014
+ }, Pn = 15, Dn = { low: 0.5, medium: 0.75, high: 1 };
2015
+ class Ln extends $ {
2016
+ constructor() {
2017
+ super();
2018
+ u(this, "segmenter", null);
2019
+ u(this, "preset", "hair");
2020
+ u(this, "quality", "medium");
2021
+ u(this, "status", "loading");
2022
+ u(this, "error", null);
2023
+ u(this, "processingTime", null);
2024
+ u(this, "sourceCanvas");
2025
+ u(this, "processCanvas");
2026
+ u(this, "isProcessing", !1);
2027
+ u(this, "mask", Fn(1, 1, ["bg"]));
2028
+ u(this, "node");
2029
+ this.node = {
2030
+ getMask: () => this.mask,
2031
+ getStatus: () => this.status,
2032
+ getError: () => this.error
2033
+ };
2034
+ }
2035
+ async initialize(t) {
2036
+ this.preset = (t == null ? void 0 : t.preset) ?? "hair", this.quality = (t == null ? void 0 : t.quality) ?? "medium";
2037
+ const n = ht[this.preset];
2038
+ this.mask.labels = n.labels, this.status = "loading", this.error = null;
2039
+ try {
2040
+ const r = await Q.forVisionTasks(
2041
+ new URL("/assets/xr/wasm", z.assetStorageEndpoint).toString()
2042
+ ), a = (t == null ? void 0 : t.modelUrl) ?? n.defaultUrl, [c] = await Promise.all([
2043
+ Z(a),
2044
+ J(r)
2045
+ ]);
2046
+ this.segmenter = await pt.createFromOptions(r, {
2047
+ baseOptions: { modelAssetBuffer: c, delegate: "GPU" },
2048
+ outputCategoryMask: !0,
2049
+ outputConfidenceMasks: !1,
2050
+ runningMode: "VIDEO"
2051
+ }), this.status = "ready";
2052
+ } catch (r) {
2053
+ throw this.status = "error", this.error = r instanceof Error ? r : new Error(String(r)), this.error;
2054
+ }
2055
+ }
2056
+ async run({ sourceCanvas: t, targetFps: n }) {
2057
+ t && (this.setTargetFps(n ?? Pn), this.isProcessing = !1, this.rafId !== null && (cancelAnimationFrame(this.rafId), this.rafId = null), this.sourceCanvas = t, this.processCanvas = document.createElement("canvas"), this.isProcessing = !0, this.lastInferenceMs = 0, this.rafId = requestAnimationFrame(this.process.bind(this)));
2058
+ }
2059
+ process() {
2060
+ if (this.disposed || this.paused || !this.isProcessing) return;
2061
+ const { segmenter: t, sourceCanvas: n, processCanvas: r } = this;
2062
+ if (!t || !n || !r || !this.shouldRunInference()) {
2063
+ this.rafId = requestAnimationFrame(this.process.bind(this));
2064
+ return;
2065
+ }
2066
+ const a = performance.now(), c = Dn[this.quality], o = Math.max(1, Math.round(n.width * c)), d = Math.max(1, Math.round(n.height * c));
2067
+ (r.width !== o || r.height !== d) && (r.width = o, r.height = d);
2068
+ const l = r.getContext("2d");
2069
+ l && l.drawImage(n, 0, 0, o, d);
2070
+ try {
2071
+ const m = t.segmentForVideo(r, performance.now()).categoryMask;
2072
+ if (m) {
2073
+ const y = m.getAsUint8Array();
2074
+ (this.mask.width !== m.width || this.mask.height !== m.height) && (this.mask.width = m.width, this.mask.height = m.height), this.mask.indices = _n(
2075
+ y,
2076
+ ht[this.preset].decode,
2077
+ this.mask.indices
2078
+ ), this.mask.version += 1, this.mask.timestampMs = a, m.close();
2079
+ }
2080
+ this.status === "error" && (this.status = "ready", this.error = null), this.recordInferenceError(null), this.recordDetections(m ? 1 : 0, null);
2081
+ } catch (h) {
2082
+ this.status = "error", this.error = h instanceof Error ? h : new Error(String(h)), this.recordInferenceError(this.error);
2083
+ }
2084
+ this.processingTime = performance.now() - a, this.recordInference(a), !(this.disposed || this.paused) && (this.rafId = requestAnimationFrame(this.process.bind(this)));
2085
+ }
2086
+ resume() {
2087
+ this.paused && (super.resume(), this.isProcessing && (this.rafId = requestAnimationFrame(this.process.bind(this))));
2088
+ }
2089
+ getModelNode() {
2090
+ return this.node;
2091
+ }
2092
+ async getPerformanceData() {
2093
+ return { name: this.constructor.name, processingTime: this.processingTime };
2094
+ }
2095
+ dispose() {
2096
+ var t;
2097
+ super.dispose(), this.isProcessing = !1;
2098
+ try {
2099
+ (t = this.segmenter) == null || t.close();
2100
+ } catch {
2101
+ }
2102
+ this.segmenter = null, this.sourceCanvas = void 0, this.processCanvas = void 0;
2103
+ }
2104
+ }
2105
+ const ut = {
2106
+ [R.BACKGROUND_SEGMENTATION]: Rn,
2107
+ [R.SEMANTIC_SEGMENTATION]: Ln,
2108
+ [R.HAND_TRACKER]: bn,
2109
+ [R.GESTURE_TRACKER]: hn,
2110
+ [R.FACE_TRACKER]: an,
2111
+ [R.BODY_TRACKER]: Js,
2112
+ [R.HOLISTIC_TRACKER]: un
2113
+ }, On = async (e) => {
2114
+ const s = document.createElement("video");
2115
+ s.srcObject = e, s.muted = !0, s.playsInline = !0, s.autoplay = !0, await new Promise((n) => {
2116
+ s.onloadedmetadata = () => {
2117
+ s.play(), n();
2118
+ };
2119
+ });
2120
+ const t = s;
2121
+ return await new Promise((n) => {
2122
+ const r = setTimeout(n, 150), a = () => {
2123
+ clearTimeout(r), n();
2124
+ };
2125
+ typeof t.requestVideoFrameCallback == "function" ? t.requestVideoFrameCallback(a) : requestAnimationFrame(() => requestAnimationFrame(() => a()));
2126
+ }), s;
2127
+ }, Hn = (e) => {
2128
+ const s = new wt(e);
2129
+ return s.colorSpace = vs, s.format = yt, s.minFilter = ve, s.magFilter = ve, s.generateMipmaps = !1, s.needsUpdate = !0, s;
2130
+ }, Nn = (e, s) => {
2131
+ const t = e.videoWidth, n = e.videoHeight;
2132
+ t > 0 && n > 0 && (s.width !== t && (s.width = t), s.height !== n && (s.height = n));
2133
+ const r = s.getContext("2d", {
2134
+ colorSpace: "srgb"
2135
+ });
2136
+ r.save(), r.scale(-1, 1), r.drawImage(e, -s.width, 0, s.width, s.height), r.restore();
2137
+ }, Un = (e, s, t = 1) => {
2138
+ const n = s.getContext("2d", {
2139
+ colorSpace: "srgb"
2140
+ }), r = Us({
2141
+ source: { width: e.width, height: e.height },
2142
+ feed: { width: s.width, height: s.height },
2143
+ zoom: t
2144
+ });
2145
+ r && (n.setTransform(1, 0, 0, 1, 0, 0), n.clearRect(0, 0, s.width, s.height), n.drawImage(
2146
+ e,
2147
+ 0,
2148
+ 0,
2149
+ e.width,
2150
+ e.height,
2151
+ r.offsetX,
2152
+ r.offsetY,
2153
+ r.drawWidth,
2154
+ r.drawHeight
2155
+ ));
2156
+ }, Bn = (e, s, t) => {
2157
+ const n = /* @__PURE__ */ new Map(), r = /* @__PURE__ */ new WeakSet();
2158
+ let a = !1;
2159
+ const c = (g, v) => {
2160
+ const w = e.getSnapshot().modelErrors;
2161
+ if (v === null && !w.has(g)) return;
2162
+ const x = new Map(w);
2163
+ v === null ? x.delete(g) : x.set(g, { model: g, error: v, at: performance.now() }), e.set({ modelErrors: x });
2164
+ }, o = (g, v) => {
2165
+ var w;
2166
+ try {
2167
+ (w = v.dispose) == null || w.call(v);
2168
+ } catch (x) {
2169
+ console.warn(`[xr-sdk registry] dispose threw for ${g}`, x);
2170
+ }
2171
+ };
2172
+ return {
2173
+ acquire: async (g, v, w) => {
2174
+ let x = n.get(g);
2175
+ if (x)
2176
+ return x.refs.add(v), x.activeRefs.add(v), x.initPromise;
2177
+ const H = s[g];
2178
+ if (!H)
2179
+ throw new Error(`Invalid model: ${g}`);
2180
+ const T = new H(), U = /* @__PURE__ */ new Set([v]), V = /* @__PURE__ */ new Set([v]);
2181
+ c(g, null);
2182
+ const D = (async () => {
2183
+ await T.initialize(w);
2184
+ const A = n.get(g);
2185
+ if (!A || A.model !== T || A.refs.size === 0)
2186
+ return o(g, T), T;
2187
+ t && await t(g, T);
2188
+ const q = n.get(g);
2189
+ return q && q.refs.size > 0 && (r.add(T), e.setPipeline((K) => K.set(g, T))), T;
2190
+ })();
2191
+ return x = { model: T, refs: U, activeRefs: V, initPromise: D, options: w }, n.set(g, x), D.catch((A) => {
2192
+ n.get(g) === x && (n.delete(g), e.setPipeline((K) => K.delete(g)), c(g, A instanceof Error ? A : new Error(String(A)))), o(g, T);
2193
+ }), D;
2194
+ },
2195
+ release: (g, v) => {
2196
+ const w = n.get(g);
2197
+ w && (w.refs.delete(v), w.activeRefs.delete(v) && w.refs.size > 0 && w.activeRefs.size === 0 && w.model.pause(), !(w.refs.size > 0) && (n.delete(g), o(g, w.model), e.setPipeline((x) => x.delete(g))));
2198
+ },
2199
+ setActive: (g, v, w) => {
2200
+ const x = n.get(g);
2201
+ if (!x || !x.refs.has(v)) return;
2202
+ const H = x.activeRefs.size > 0;
2203
+ w ? x.activeRefs.add(v) : x.activeRefs.delete(v);
2204
+ const T = x.activeRefs.size > 0;
2205
+ H !== T && (T && !a ? x.model.resume() : x.model.pause());
2206
+ },
2207
+ suspendAll: () => {
2208
+ a = !0;
2209
+ for (const g of n.values())
2210
+ g.model.pause();
2211
+ },
2212
+ resumeActive: () => {
2213
+ a = !1;
2214
+ for (const g of n.values())
2215
+ g.activeRefs.size > 0 && g.model.resume();
2216
+ },
2217
+ get: (g) => {
2218
+ var v;
2219
+ return (v = n.get(g)) == null ? void 0 : v.model;
2220
+ },
2221
+ getOptions: (g) => {
2222
+ var v;
2223
+ return (v = n.get(g)) == null ? void 0 : v.options;
2224
+ },
2225
+ releaseAll: () => {
2226
+ for (const g of Array.from(n.keys())) {
2227
+ const v = n.get(g);
2228
+ v && (v.refs.clear(), n.delete(g), o(g, v.model));
2229
+ }
2230
+ e.setPipeline((g) => g.clear());
2231
+ },
2232
+ getState: (g) => {
2233
+ const v = n.get(g);
2234
+ return v ? r.has(v.model) ? "ready" : "initializing" : e.getSnapshot().modelErrors.has(g) ? "error" : "idle";
2235
+ },
2236
+ getOwners: (g) => {
2237
+ const v = n.get(g);
2238
+ return {
2239
+ refs: v ? Array.from(v.refs) : [],
2240
+ active: v ? Array.from(v.activeRefs) : []
2241
+ };
2242
+ }
2243
+ };
2244
+ }, zn = {
2245
+ lifecycle: "idle",
2246
+ ready: !1,
2247
+ error: void 0,
2248
+ cameraTexture: void 0,
2249
+ renderWidth: 0,
2250
+ renderHeight: 0,
2251
+ source: void 0,
2252
+ sourceKind: void 0,
2253
+ cameraFacing: null,
2254
+ cameraDeviceId: null,
2255
+ orientation: { type: "portrait", angle: 0 },
2256
+ quality: null,
2257
+ qualityConfig: null,
2258
+ sourceWidth: 0,
2259
+ sourceHeight: 0,
2260
+ cameraZoom: 1.2,
2261
+ pipeline: /* @__PURE__ */ new Map(),
2262
+ modelErrors: /* @__PURE__ */ new Map(),
2263
+ cameraPermission: "unknown",
2264
+ cameraPermissionReason: null,
2265
+ feedFrames: 0
2266
+ }, Wn = () => {
2267
+ let e = { ...zn, pipeline: /* @__PURE__ */ new Map(), modelErrors: /* @__PURE__ */ new Map() };
2268
+ const s = /* @__PURE__ */ new Set(), t = () => {
2269
+ s.forEach((n) => n());
2270
+ };
2271
+ return {
2272
+ getSnapshot: () => e,
2273
+ set: (n) => {
2274
+ let r = !1;
2275
+ for (const a of Object.keys(n))
2276
+ if (n[a] !== e[a]) {
2277
+ r = !0;
2278
+ break;
2279
+ }
2280
+ r && (e = { ...e, ...n }, t());
2281
+ },
2282
+ setPipeline: (n) => {
2283
+ const r = new Map(e.pipeline);
2284
+ return n(r), e = { ...e, pipeline: r }, t(), r;
2285
+ },
2286
+ subscribe: (n) => (s.add(n), () => {
2287
+ s.delete(n);
2288
+ })
2289
+ };
2290
+ }, mt = (e, s) => s ?? e === "user", qn = ({
2291
+ renderHeight: e,
2292
+ renderWidth: s,
2293
+ videoHeight: t,
2294
+ videoWidth: n
2295
+ }) => ({
2296
+ height: e || t,
2297
+ width: s || n
2298
+ }), Vn = (e, s) => {
2299
+ const t = new zs({ verbose: !0 }), n = Wn();
2300
+ n.set({ cameraZoom: (e == null ? void 0 : e.cameraZoom) ?? 1.2 });
2301
+ let r = s, a = e;
2302
+ const c = (i) => {
2303
+ var p;
2304
+ const f = (p = W.getOptions(i)) == null ? void 0 : p.targetFps;
2305
+ return typeof f == "number" ? f : a == null ? void 0 : a.targetFps;
2306
+ };
2307
+ let o, d, l, h, m, y, S, M, C, E, _, g, v = !1, w = !1, x = !1, H = 0, T, U, V, D = !1, A = 0, q = /* @__PURE__ */ new WeakSet();
2308
+ const K = /* @__PURE__ */ new Set(), pe = (i) => {
2309
+ const f = n.getSnapshot().cameraTexture;
2310
+ f && f.dispose();
2311
+ const p = Hn(i);
2312
+ return n.set({ cameraTexture: p }), p;
2313
+ }, Ce = async (i, f) => {
2314
+ if (q.has(f) || n.getSnapshot().lifecycle !== "running" || !m) return;
2315
+ q.add(f);
2316
+ const p = A;
2317
+ try {
2318
+ await f.run({
2319
+ sourceCanvas: m,
2320
+ renderWidth: n.getSnapshot().renderWidth,
2321
+ renderHeight: n.getSnapshot().renderHeight,
2322
+ getSource: () => n.getSnapshot().sourceKind,
2323
+ targetFps: c(i),
2324
+ analysisScale: a == null ? void 0 : a.analysisScale
2325
+ }), D && (await new Promise((k) => requestAnimationFrame(() => k())), await new Promise((k) => requestAnimationFrame(() => k())), D && A === p && W.suspendAll());
2326
+ } catch (k) {
2327
+ throw q.delete(f), k;
2328
+ }
2329
+ }, W = Bn(n, ut, (i, f) => Ce(i, f));
2330
+ n.subscribe(() => {
2331
+ if (n.getSnapshot().lifecycle !== "running") return;
2332
+ const i = n.getSnapshot().pipeline;
2333
+ for (const [f, p] of i.entries())
2334
+ q.has(p) || Ce(f, p);
2335
+ });
2336
+ const qe = () => {
2337
+ g !== void 0 && (cancelAnimationFrame(g), g = void 0);
2338
+ }, ee = () => {
2339
+ if (qe(), T == null || T(), T = void 0, d) {
2340
+ try {
2341
+ d.pause();
2342
+ } catch {
2343
+ }
2344
+ try {
2345
+ d.srcObject = null;
2346
+ } catch {
2347
+ }
2348
+ d = void 0;
2349
+ }
2350
+ if (l) {
2351
+ try {
2352
+ l.getTracks().forEach((i) => i.stop());
2353
+ } catch {
2354
+ }
2355
+ l = void 0;
2356
+ }
2357
+ }, ke = () => {
2358
+ if (v || !d || !h || !m) return;
2359
+ const i = typeof window < "u" ? window.__xr_debugger_metrics : void 0;
2360
+ if (i != null && i.trackCameraFrame && i.trackCameraFrame(), Me(n.getSnapshot().sourceKind))
2361
+ Nn(d, h);
2362
+ else {
2363
+ const b = h.getContext("2d");
2364
+ if (!b) return;
2365
+ const P = d.videoWidth, L = d.videoHeight;
2366
+ h.width !== P && (h.width = P), h.height !== L && (h.height = L), b.setTransform(1, 0, 0, 1, 0, 0), b.clearRect(0, 0, P, L), b.drawImage(d, 0, 0, P, L);
2367
+ }
2368
+ Un(h, m, (a == null ? void 0 : a.cameraZoom) ?? 1.2);
2369
+ const p = n.getSnapshot();
2370
+ (p.sourceWidth !== d.videoWidth || p.sourceHeight !== d.videoHeight) && n.set({ sourceWidth: d.videoWidth, sourceHeight: d.videoHeight }), H += 1, H % 10 === 0 && n.set({ feedFrames: H });
2371
+ const k = n.getSnapshot().cameraTexture;
2372
+ k && (k.needsUpdate = !0);
2373
+ }, xe = () => {
2374
+ if (!d || !h || !m) return;
2375
+ if (D) {
2376
+ ke();
2377
+ return;
2378
+ }
2379
+ const i = () => {
2380
+ g = requestAnimationFrame(i), ke();
2381
+ };
2382
+ g = requestAnimationFrame(i);
2383
+ }, Dt = async (i, f) => {
2384
+ if (i.source === F.WEBCAM)
2385
+ try {
2386
+ const p = a != null && a.camRes && a.camRes > 0 ? a.camRes : 960;
2387
+ n.set({ cameraPermission: "requesting", cameraPermissionReason: null });
2388
+ const k = i.deviceId ? { deviceId: { exact: i.deviceId } } : { facingMode: { ideal: i.facingMode ?? "user" } }, b = {
2389
+ frameRate: { min: 24, ideal: 30, max: 60 },
2390
+ width: { ideal: p },
2391
+ ...k
2392
+ };
2393
+ let P;
2394
+ try {
2395
+ P = await navigator.mediaDevices.getUserMedia({ video: b });
2396
+ } catch (L) {
2397
+ if (!(L instanceof DOMException && L.name === "OverconstrainedError")) throw L;
2398
+ P = await navigator.mediaDevices.getUserMedia({
2399
+ video: { frameRate: { ideal: 30 }, width: { ideal: p }, ...k }
2400
+ });
2401
+ }
2402
+ return f === A && n.set({ cameraPermission: "granted", cameraPermissionReason: null }), P;
2403
+ } catch (p) {
2404
+ const k = kt(p), b = ct[k], P = await xt(), L = bt(k, P.state);
2405
+ throw f === A && n.set({
2406
+ error: { error: "PermissionError", message: b, reason: k },
2407
+ cameraPermission: L.state,
2408
+ cameraPermissionReason: L.reason
2409
+ }), new O(p instanceof Error ? p.message : "getUserMedia failed");
2410
+ }
2411
+ return i.stream;
2412
+ }, Ve = (i) => {
2413
+ const { lifecycle: f } = n.getSnapshot();
2414
+ f === "idle" || f === "stopped" || v || (ee(), W.suspendAll(), A += 1, o = void 0, n.set({
2415
+ lifecycle: "stopped",
2416
+ ready: !1,
2417
+ error: { error: "PermissionError", message: ct[i], reason: i },
2418
+ cameraPermission: i === "permission-denied" ? "blocked" : "unavailable",
2419
+ cameraPermissionReason: Ct(i)
2420
+ }), t.log("XR session stopped: camera lost.", i));
2421
+ }, Lt = (i) => {
2422
+ var k;
2423
+ T == null || T();
2424
+ const f = ((k = i.getVideoTracks) == null ? void 0 : k.call(i)) ?? [], p = () => {
2425
+ l === i && Ve("camera-lost");
2426
+ };
2427
+ f.forEach((b) => {
2428
+ var P;
2429
+ return (P = b.addEventListener) == null ? void 0 : P.call(b, "ended", p);
2430
+ }), T = () => {
2431
+ f.forEach((b) => {
2432
+ var P;
2433
+ return (P = b.removeEventListener) == null ? void 0 : P.call(b, "ended", p);
2434
+ });
2435
+ };
2436
+ }, Ot = async () => {
2437
+ if (U || typeof navigator > "u") return;
2438
+ const i = navigator.permissions;
2439
+ if (i != null && i.query)
2440
+ try {
2441
+ const f = await i.query({ name: "camera" });
2442
+ if (w) return;
2443
+ U = f, V = () => {
2444
+ f.state === "denied" && (o == null ? void 0 : o.source) === F.WEBCAM && Ve("permission-denied");
2445
+ }, f.addEventListener("change", V);
2446
+ } catch {
2447
+ }
2448
+ }, Ht = () => {
2449
+ var i;
2450
+ U && V && ((i = U.removeEventListener) == null || i.call(U, "change", V)), U = void 0, V = void 0;
2451
+ }, be = async (i) => {
2452
+ var tt, ye, st;
2453
+ const f = A, p = await Dt(i, f);
2454
+ if (f !== A)
2455
+ throw p.getTracks().forEach((re) => re.stop()), new O("Media source superseded by a newer bind");
2456
+ l = p, Lt(p);
2457
+ const k = await On(p);
2458
+ if (f !== A || w)
2459
+ throw p.getTracks().forEach((re) => re.stop()), new O("Media source superseded by a newer bind");
2460
+ d = k, h = new OffscreenCanvas(k.videoWidth, k.videoHeight);
2461
+ const { renderWidth: b, renderHeight: P } = n.getSnapshot(), L = qn({
2462
+ renderWidth: b,
2463
+ renderHeight: P,
2464
+ videoWidth: k.videoWidth,
2465
+ videoHeight: k.videoHeight
2466
+ });
2467
+ m ? (m.width !== L.width || m.height !== L.height) && (m.width = L.width, m.height = L.height, pe(m)) : (m = new OffscreenCanvas(L.width, L.height), pe(m));
2468
+ const et = i.source === F.STREAM ? i.static === !0 : !1;
2469
+ D = et;
2470
+ const ne = (st = (ye = (tt = p.getVideoTracks) == null ? void 0 : tt.call(p)[0]) == null ? void 0 : ye.getSettings) == null ? void 0 : st.call(ye), Fe = ne == null ? void 0 : ne.facingMode, os = Fe === "user" || Fe === "environment" ? Fe : null;
2471
+ if (i.source === F.WEBCAM) {
2472
+ const re = os ?? i.facingMode ?? "user", nt = mt(re, i.mirrored);
2473
+ o = {
2474
+ source: F.WEBCAM,
2475
+ sourceKind: nt ? "webcam" : "rear-camera",
2476
+ facingMode: re,
2477
+ deviceId: i.deviceId,
2478
+ mirrored: nt
2479
+ };
2480
+ } else
2481
+ o = {
2482
+ source: F.STREAM,
2483
+ stream: i.stream,
2484
+ static: et,
2485
+ sourceKind: i.sourceKind ?? "webcam"
2486
+ };
2487
+ n.set({
2488
+ source: i.source,
2489
+ sourceKind: o.sourceKind,
2490
+ cameraFacing: o.source === F.WEBCAM ? o.facingMode : null,
2491
+ cameraDeviceId: o.source === F.WEBCAM ? (ne == null ? void 0 : ne.deviceId) ?? o.deviceId ?? null : null,
2492
+ sourceWidth: k.videoWidth,
2493
+ sourceHeight: k.videoHeight,
2494
+ error: void 0
2495
+ }), i.source === F.WEBCAM && Ot();
2496
+ }, Te = async (i) => {
2497
+ const f = i.sourceKind ?? "webcam";
2498
+ m = i.canvas;
2499
+ const p = pe(m);
2500
+ n.set({
2501
+ cameraTexture: p,
2502
+ source: F.CANVAS,
2503
+ sourceKind: f,
2504
+ cameraFacing: null,
2505
+ cameraDeviceId: null,
2506
+ renderWidth: m.width,
2507
+ renderHeight: m.height,
2508
+ error: void 0
2509
+ }), o = {
2510
+ source: F.CANVAS,
2511
+ canvas: i.canvas,
2512
+ sourceKind: f
2513
+ };
2514
+ }, Nt = (i, f) => {
2515
+ if (!f || i.source !== f.source) return !1;
2516
+ if (i.source === F.STREAM && f.source === F.STREAM)
2517
+ return i.stream === f.stream && (i.sourceKind ?? "webcam") === f.sourceKind;
2518
+ if (i.source === F.WEBCAM && f.source === F.WEBCAM) {
2519
+ const p = i.facingMode ?? "user";
2520
+ return p === f.facingMode && i.deviceId === f.deviceId && mt(p, i.mirrored) === f.mirrored;
2521
+ }
2522
+ return !1;
2523
+ }, Ke = async () => {
2524
+ if (!m) return;
2525
+ const i = A, f = n.getSnapshot().pipeline;
2526
+ for (const [, p] of f.entries())
2527
+ p.resume();
2528
+ await new Promise((p) => requestAnimationFrame(() => p())), await new Promise((p) => requestAnimationFrame(() => p())), D && A === i && W.suspendAll();
2529
+ }, Ut = (i, f) => !f || f.source !== F.CANVAS ? !1 : i.canvas === f.canvas && (i.sourceKind ?? "webcam") === f.sourceKind, Ee = async (i) => {
2530
+ const f = i.source;
2531
+ if (f !== F.WEBCAM && f !== F.STREAM)
2532
+ throw new O(`Invalid media source: ${String(f)}`);
2533
+ if (w) throw new O("session.setMediaSource() called after the provider unmounted");
2534
+ if (Nt(i, o)) {
2535
+ t.log("Media source unchanged, skipping rebind.");
2536
+ return;
2537
+ }
2538
+ A += 1;
2539
+ const { lifecycle: p } = n.getSnapshot();
2540
+ if (p === "idle" || p === "stopped") {
2541
+ await be(i), n.set({ lifecycle: "media-bound" }), t.log("Media source set to:", i.source);
2542
+ return;
2543
+ }
2544
+ if (p === "media-bound") {
2545
+ ee(), await be(i), t.log("Media source rebound to:", i.source);
2546
+ return;
2547
+ }
2548
+ const k = p === "paused";
2549
+ v = !0, await new Promise((b) => requestAnimationFrame(() => b())), ee();
2550
+ try {
2551
+ await be(i);
2552
+ } finally {
2553
+ v = !1;
2554
+ }
2555
+ if (k) {
2556
+ d == null || d.pause(), t.log("Media source swapped (paused) to:", i.source);
2557
+ return;
2558
+ }
2559
+ xe(), D ? await Ke() : W.resumeActive(), t.log("Media source swapped to:", i.source);
2560
+ }, Bt = async (i) => {
2561
+ if (w) throw new O("session.setFrameSource() called after the provider unmounted");
2562
+ if (Ut(i, o)) {
2563
+ t.log("Frame source unchanged, skipping rebind.");
2564
+ return;
2565
+ }
2566
+ A += 1;
2567
+ const { lifecycle: f } = n.getSnapshot();
2568
+ if (f === "idle" || f === "stopped") {
2569
+ await Te(i), n.set({ lifecycle: "media-bound" }), t.log("Frame source set to canvas.");
2570
+ return;
2571
+ }
2572
+ if (f === "media-bound") {
2573
+ ee(), await Te(i), t.log("Frame source rebound to canvas.");
2574
+ return;
2575
+ }
2576
+ v = !0, await new Promise((p) => requestAnimationFrame(() => p())), ee();
2577
+ try {
2578
+ await Te(i);
2579
+ } finally {
2580
+ v = !1;
2581
+ }
2582
+ t.log("Frame source swapped to canvas.");
2583
+ }, Ge = async () => {
2584
+ if (w) throw new O("session.start() called after the provider unmounted");
2585
+ const { lifecycle: i } = n.getSnapshot();
2586
+ if (i === "running") return;
2587
+ if (i === "paused") {
2588
+ await Ae();
2589
+ return;
2590
+ }
2591
+ if (i === "idle")
2592
+ throw new O("session.start() called before setMediaSource — call setMediaSource first");
2593
+ if (!m)
2594
+ throw new O("session.start(): media source not bound");
2595
+ const f = (o == null ? void 0 : o.source) === F.CANVAS;
2596
+ if (!f && (!d || !h))
2597
+ throw i === "stopped" ? new O(
2598
+ "session.start() called from stopped state without a media source — call setMediaSource first"
2599
+ ) : new O("session.start(): media source not bound");
2600
+ f || xe(), W.resumeActive(), n.set({ lifecycle: "running" }), await new Promise((k) => requestAnimationFrame(() => k()));
2601
+ const p = n.getSnapshot().pipeline;
2602
+ for (const [k, b] of p.entries())
2603
+ await Ce(k, b);
2604
+ n.set({ ready: !0 }), t.log("XR session started.");
2605
+ }, Xe = () => {
2606
+ if (n.getSnapshot().lifecycle === "running") {
2607
+ qe(), W.suspendAll();
2608
+ try {
2609
+ d == null || d.pause();
2610
+ } catch {
2611
+ }
2612
+ n.set({ lifecycle: "paused" }), t.log("XR session paused.");
2613
+ }
2614
+ }, Ae = async () => {
2615
+ if (w) throw new O("session.resume() called after the provider unmounted");
2616
+ n.getSnapshot().lifecycle === "paused" && (x = !1, d && d.play().catch(() => {
2617
+ }), (o == null ? void 0 : o.source) !== F.CANVAS && xe(), n.set({ lifecycle: "running" }), D ? await Ke() : W.resumeActive(), t.log("XR session resumed."));
2618
+ }, zt = async (i = {}) => {
2619
+ await Ee({ source: F.WEBCAM, ...i });
2620
+ const { lifecycle: f } = n.getSnapshot();
2621
+ return (f === "media-bound" || f === "stopped") && await Ge(), n.getSnapshot().cameraFacing ?? i.facingMode ?? "user";
2622
+ }, Ye = async () => {
2623
+ const { lifecycle: i } = n.getSnapshot();
2624
+ i === "stopped" || i === "idle" || (x = !1, ee(), W.suspendAll(), o = void 0, n.set({ lifecycle: "stopped", ready: !1 }), t.log("XR session stopped."));
2625
+ }, je = async () => {
2626
+ await Ye(), W.releaseAll(), K.clear();
2627
+ const i = n.getSnapshot().cameraTexture;
2628
+ i && i.dispose(), q = /* @__PURE__ */ new WeakSet(), o = void 0, A += 1, m = void 0, h = void 0, S = void 0, D = !1, Ht(), n.set({
2629
+ lifecycle: "idle",
2630
+ cameraTexture: void 0,
2631
+ source: void 0,
2632
+ sourceKind: void 0,
2633
+ cameraFacing: null,
2634
+ cameraDeviceId: null,
2635
+ error: void 0,
2636
+ modelErrors: /* @__PURE__ */ new Map(),
2637
+ cameraPermission: "unknown",
2638
+ cameraPermissionReason: null
2639
+ }), t.log("XR session reset.");
2640
+ }, Wt = async () => {
2641
+ w || (w = !0, se == null || se(), se = void 0, te == null || te(), te = void 0, await je(), t.log("XR session disposed."));
2642
+ }, qt = () => {
2643
+ w && (w = !1, $e(), Je(), t.log("XR session re-armed."));
2644
+ }, Vt = () => w, Kt = async (i) => {
2645
+ const f = "legacy:registerXRPipeline", p = [];
2646
+ await Promise.all(
2647
+ i.map(async (k) => {
2648
+ const { model: b } = k;
2649
+ if (!ut[b])
2650
+ throw new O(`Invalid model: ${b}`);
2651
+ K.has(b) || p.push(b);
2652
+ const P = "options" in k ? k.options : void 0;
2653
+ await W.acquire(b, f, P);
2654
+ })
2655
+ ), p.length > 0 && (p.forEach((k) => K.add(k)), t.log("XR pipeline registered."));
2656
+ }, Gt = (i) => {
2657
+ const f = W.get(i);
2658
+ if (!f)
2659
+ throw new O(`Model ${i} is not registered in the pipeline`);
2660
+ return f.getModelNode();
2661
+ }, Qe = async (i, f) => {
2662
+ i <= 0 || f <= 0 || (n.set({ renderWidth: i, renderHeight: f }), m && (m.width !== i || m.height !== f) && (m.width = i, m.height = f, pe(m), D && ke()), t.log(`Source canvas set. Render size: ${i}x${f}`));
2663
+ }, Xt = async (i) => {
2664
+ var b;
2665
+ y = i;
2666
+ const f = (b = i.getBoundingClientRect) == null ? void 0 : b.call(i), p = f && f.width > 0 ? Math.round(f.width) : i.clientWidth, k = f && f.height > 0 ? Math.round(f.height) : i.clientHeight;
2667
+ await Qe(p, k);
2668
+ }, Yt = (i) => {
2669
+ S = i;
2670
+ }, Re = () => y && M && C && E ? y : S, jt = (i) => {
2671
+ M = i.renderer, C = i.scene, E = i.camera, _ = i.renderFrame;
2672
+ }, Ze = () => {
2673
+ if (!M || !C || !E)
2674
+ throw new O(
2675
+ "XR frame render requested before the R3F state was bound — make sure <XRScene> is mounted"
2676
+ );
2677
+ _ ? _() : M.render(C, E);
2678
+ }, Qt = () => {
2679
+ const i = y;
2680
+ if (i && Re() === i)
2681
+ return Ze(), i.toDataURL("image/png");
2682
+ const f = Re();
2683
+ if (f) return f.toDataURL("image/png");
2684
+ throw new O(
2685
+ "session.captureFrame() called before an XRScene or XRMediaSurface capture target was bound"
2686
+ );
2687
+ }, Zt = (i = 30) => {
2688
+ const f = Re();
2689
+ if (!(f != null && f.captureStream))
2690
+ throw new O(
2691
+ "session.captureStream() called before an XRScene or XRMediaSurface capture target was bound"
2692
+ );
2693
+ return f.captureStream(i);
2694
+ }, Jt = () => d, $t = () => m ?? null, es = (i) => {
2695
+ if (a = i, n.set({ cameraZoom: (i == null ? void 0 : i.cameraZoom) ?? 1.2 }), n.getSnapshot().lifecycle !== "running" || !m) return;
2696
+ const f = n.getSnapshot().pipeline;
2697
+ for (const [p, k] of f.entries())
2698
+ k.run({
2699
+ sourceCanvas: m,
2700
+ renderWidth: n.getSnapshot().renderWidth,
2701
+ renderHeight: n.getSnapshot().renderHeight,
2702
+ getSource: () => n.getSnapshot().sourceKind,
2703
+ targetFps: c(p),
2704
+ analysisScale: a == null ? void 0 : a.analysisScale
2705
+ });
2706
+ }, ts = () => a, ss = async () => {
2707
+ if (!o || o.source !== F.WEBCAM) return;
2708
+ const { facingMode: i, deviceId: f, mirrored: p } = o;
2709
+ o = void 0, await Ee({ source: F.WEBCAM, facingMode: i, deviceId: f, mirrored: p });
2710
+ }, ns = (i) => {
2711
+ n.set({ quality: i });
2712
+ }, rs = (i) => {
2713
+ n.set({ qualityConfig: i });
2714
+ }, as = (i) => {
2715
+ r = i;
2716
+ }, is = () => {
2717
+ var b;
2718
+ if (typeof window > "u") return { type: "portrait", angle: 0 };
2719
+ const i = (b = window.screen) == null ? void 0 : b.orientation, f = (i == null ? void 0 : i.angle) ?? 0, p = f === 90 || f === 180 || f === 270 ? f : 0;
2720
+ return { type: i != null && i.type ? i.type.startsWith("landscape") ? "landscape" : "portrait" : window.innerWidth > window.innerHeight ? "landscape" : "portrait", angle: p };
2721
+ }, ce = () => {
2722
+ const i = is(), f = n.getSnapshot().orientation, p = f.type !== i.type || f.angle !== i.angle ? { orientation: i } : {};
2723
+ d && d.videoWidth > 0 && (p.sourceWidth = d.videoWidth, p.sourceHeight = d.videoHeight), Object.keys(p).length && n.set(p);
2724
+ };
2725
+ let te;
2726
+ const Je = () => {
2727
+ var f, p, k;
2728
+ if (te || typeof window > "u") return;
2729
+ const i = (f = window.screen) == null ? void 0 : f.orientation;
2730
+ (p = i == null ? void 0 : i.addEventListener) == null || p.call(i, "change", ce), (k = window.addEventListener) == null || k.call(window, "resize", ce), te = () => {
2731
+ var b, P;
2732
+ (b = i == null ? void 0 : i.removeEventListener) == null || b.call(i, "change", ce), (P = window.removeEventListener) == null || P.call(window, "resize", ce);
2733
+ }, ce();
2734
+ };
2735
+ let se;
2736
+ const $e = () => {
2737
+ if (se || typeof document > "u" || typeof document.addEventListener != "function") return;
2738
+ const i = () => {
2739
+ if (!w) {
2740
+ if (document.hidden) {
2741
+ r != null && r.pauseWhenHidden && n.getSnapshot().lifecycle === "running" && (Xe(), x = !0);
2742
+ return;
2743
+ }
2744
+ if (x && n.getSnapshot().lifecycle === "paused") {
2745
+ Ae();
2746
+ return;
2747
+ }
2748
+ n.getSnapshot().lifecycle === "running" && (d != null && d.paused) && d.play().catch(() => {
2749
+ });
2750
+ }
2751
+ };
2752
+ document.addEventListener("visibilitychange", i), se = () => document.removeEventListener("visibilitychange", i);
2753
+ };
2754
+ return $e(), Je(), {
2755
+ store: n,
2756
+ registry: W,
2757
+ setMediaSource: Ee,
2758
+ start: Ge,
2759
+ stop: Ye,
2760
+ reset: je,
2761
+ pause: Xe,
2762
+ resume: Ae,
2763
+ switchCamera: zt,
2764
+ dispose: Wt,
2765
+ rearm: qt,
2766
+ isDisposed: Vt,
2767
+ setFrameSource: Bt,
2768
+ registerXRPipeline: Kt,
2769
+ getModelNode: Gt,
2770
+ captureFrame: Qt,
2771
+ captureStream: Zt,
2772
+ getInputFrame: $t,
2773
+ _setRenderTarget: Xt,
2774
+ _setCaptureTarget: Yt,
2775
+ _setRenderSize: Qe,
2776
+ _setR3FState: jt,
2777
+ _renderFrame: Ze,
2778
+ _getVideoElement: Jt,
2779
+ _setPerf: es,
2780
+ _setLifecycle: as,
2781
+ _rebindMedia: ss,
2782
+ _setQuality: ns,
2783
+ _setQualityConfig: rs,
2784
+ _getPerf: ts
2785
+ };
2786
+ }, Kn = (e, s) => {
2787
+ const t = oe(e), n = oe(s), r = ge(
2788
+ () => Vn(t.current, n.current),
2789
+ []
2790
+ ), a = JSON.stringify(s ?? {});
2791
+ he(() => {
2792
+ r._setLifecycle(s);
2793
+ }, [r, a]), he(() => (r.rearm(), () => void r.dispose()), [r]);
2794
+ const c = JSON.stringify(e ?? {});
2795
+ return he(() => {
2796
+ r._setPerf(e);
2797
+ }, [r, c]), r;
2798
+ }, He = /* @__PURE__ */ new Map(), Gn = () => ({
2799
+ register: (e, s) => {
2800
+ s ? He.set(e, s) : He.delete(e);
2801
+ },
2802
+ resolve: (e) => e ? He.get(e) ?? null : null
2803
+ }), At = Gn(), Rt = gt(null), Xn = ({ children: e }) => {
2804
+ const s = oe(/* @__PURE__ */ new Map()), t = at((a, c) => {
2805
+ c ? s.current.set(a, c) : s.current.delete(a);
2806
+ }, []), n = at(
2807
+ (a) => a ? s.current.get(a) ?? null : null,
2808
+ []
2809
+ ), r = ge(() => ({ register: t, resolve: n }), [t, n]);
2810
+ return hs(Rt.Provider, { value: r }, e);
2811
+ }, Ft = () => Be(Rt) ?? At, Hr = () => Ft().register, Nr = () => Ft().resolve;
2812
+ At.register;
2813
+ const Yn = {
2814
+ [R.FACE_TRACKER]: "face",
2815
+ [R.HAND_TRACKER]: "hand",
2816
+ [R.GESTURE_TRACKER]: "gesture",
2817
+ [R.BODY_TRACKER]: "body",
2818
+ [R.HOLISTIC_TRACKER]: "holistic",
2819
+ [R.BACKGROUND_SEGMENTATION]: "segmentation",
2820
+ [R.SEMANTIC_SEGMENTATION]: "semantic-seg"
2821
+ }, ft = Object.values(R), jn = (e, s) => {
2822
+ var n;
2823
+ const t = (n = e.registry.getOptions(s)) == null ? void 0 : n.targetFps;
2824
+ return typeof t == "number" ? t : null;
2825
+ }, Ue = (e, s, t, n = performance.now()) => {
2826
+ const r = e.store.getSnapshot(), a = t ? n - t.sampledAt : 0, c = t && a > 0 ? Math.max(0, (r.feedFrames - t.feedFrames) * 1e3 / a) : 0, o = r.lifecycle === "running", d = s.map((h) => {
2827
+ var E;
2828
+ const m = e.registry.getState(h), y = e.store.getSnapshot().pipeline.get(h), S = ((E = r.modelErrors.get(h)) == null ? void 0 : E.error) ?? null, M = (y == null ? void 0 : y.getDiagnostics()) ?? {
2829
+ inferenceMs: null,
2830
+ inferenceFps: 0,
2831
+ inferences: 0,
2832
+ skippedFrames: 0,
2833
+ detections: null,
2834
+ confidence: null,
2835
+ status: S ? "error" : "ready",
2836
+ error: S,
2837
+ paused: !1,
2838
+ disposed: !1
2839
+ };
2840
+ let C;
2841
+ return m === "error" || M.status === "error" ? C = "error" : m === "idle" ? C = "unavailable" : m === "initializing" ? C = "loading" : M.paused || !o ? C = "paused" : C = "ready", {
2842
+ ...M,
2843
+ error: M.error ?? S,
2844
+ model: h,
2845
+ label: Yn[h] ?? h,
2846
+ state: C,
2847
+ targetFps: jn(e, h),
2848
+ owners: e.registry.getOwners(h)
2849
+ };
2850
+ }), l = r.quality;
2851
+ return {
2852
+ quality: l ? {
2853
+ tier: l.decision.tier.name,
2854
+ index: l.index,
2855
+ locked: l.locked,
2856
+ reason: l.decision.reason
2857
+ } : null,
2858
+ session: {
2859
+ lifecycle: r.lifecycle,
2860
+ ready: r.ready,
2861
+ error: r.error,
2862
+ source: r.source,
2863
+ sourceKind: r.sourceKind,
2864
+ sourceWidth: r.sourceWidth,
2865
+ sourceHeight: r.sourceHeight,
2866
+ renderWidth: r.renderWidth,
2867
+ renderHeight: r.renderHeight,
2868
+ feedFps: c,
2869
+ feedFrames: r.feedFrames
2870
+ },
2871
+ models: d,
2872
+ inferenceMsTotal: d.reduce(
2873
+ (h, m) => h + (m.state === "ready" ? m.inferenceMs ?? 0 : 0),
2874
+ 0
2875
+ ),
2876
+ sampledAt: n
2877
+ };
2878
+ }, Ur = (e = {}) => {
2879
+ const { intervalMs: s = 250, enabled: t = !0 } = e, { session: n } = Pt(), r = (e.models ?? ft).join("|"), a = ge(
2880
+ () => e.models && e.models.length ? e.models : ft,
2881
+ // modelsKey captures the list by value.
2882
+ // eslint-disable-next-line react-hooks/exhaustive-deps
2883
+ [r]
2884
+ ), c = oe(null), [o, d] = us(
2885
+ () => Ue(n, a, null)
2886
+ );
2887
+ return he(() => {
2888
+ if (!t) return;
2889
+ const l = () => {
2890
+ const m = Ue(n, a, c.current);
2891
+ c.current = { feedFrames: m.session.feedFrames, sampledAt: m.sampledAt }, d(m);
2892
+ };
2893
+ l();
2894
+ const h = window.setInterval(l, Math.max(50, s));
2895
+ return () => window.clearInterval(h);
2896
+ }, [n, a, s, t]), o;
2897
+ }, Qn = [
2898
+ { name: "high", targetFps: 30, renderScale: 1, analysisScale: 1, camRes: 960 },
2899
+ { name: "medium", targetFps: 24, renderScale: 0.8, analysisScale: 0.85, camRes: 720 },
2900
+ { name: "low", targetFps: 15, renderScale: 0.6, analysisScale: 0.7, camRes: 640 }
2901
+ ], j = {
2902
+ maxFrameMs: 1e3 / 24,
2903
+ maxInferenceMs: 24,
2904
+ maxMemoryMb: null,
2905
+ sampleMs: 1e3,
2906
+ downgradeAfter: 2,
2907
+ upgradeAfter: 6,
2908
+ upgradeHeadroom: 0.75,
2909
+ cooldownMs: 4e3
2910
+ }, It = {
2911
+ frameMs: null,
2912
+ fps: null,
2913
+ inferenceMs: null,
2914
+ feedFps: null,
2915
+ memoryMb: null,
2916
+ deviceMemoryGb: null,
2917
+ hardwareConcurrency: null,
2918
+ thermal: "unknown"
2919
+ }, fe = (e, s, t) => Math.min(t, Math.max(s, e)), N = (e, s) => typeof e == "number" && Number.isFinite(e) ? e : s, Zn = (e, s) => ({
2920
+ name: typeof e.name == "string" && e.name ? e.name : `tier-${s}`,
2921
+ ...N(e.targetFps, NaN) > 0 ? { targetFps: N(e.targetFps, 0) } : {},
2922
+ ...N(e.renderScale, NaN) > 0 ? { renderScale: fe(N(e.renderScale, 1), 0.25, 1) } : {},
2923
+ ...N(e.analysisScale, NaN) > 0 ? { analysisScale: fe(N(e.analysisScale, 1), 0.25, 1) } : {},
2924
+ ...N(e.camRes, NaN) > 0 ? { camRes: Math.round(N(e.camRes, 0)) } : {},
2925
+ ...e.rebindCamera ? { rebindCamera: !0 } : {}
2926
+ }), Jn = (e = {}) => ({
2927
+ maxFrameMs: Math.max(1, N(e.maxFrameMs, j.maxFrameMs)),
2928
+ maxInferenceMs: Math.max(
2929
+ 0,
2930
+ N(e.maxInferenceMs, j.maxInferenceMs)
2931
+ ),
2932
+ maxMemoryMb: e.maxMemoryMb === null || e.maxMemoryMb === void 0 ? null : Math.max(1, N(e.maxMemoryMb, 0)) || null,
2933
+ sampleMs: Math.max(100, N(e.sampleMs, j.sampleMs)),
2934
+ downgradeAfter: Math.max(
2935
+ 1,
2936
+ Math.round(N(e.downgradeAfter, j.downgradeAfter))
2937
+ ),
2938
+ upgradeAfter: Math.max(
2939
+ 1,
2940
+ Math.round(N(e.upgradeAfter, j.upgradeAfter))
2941
+ ),
2942
+ upgradeHeadroom: fe(
2943
+ N(e.upgradeHeadroom, j.upgradeHeadroom),
2944
+ 0.1,
2945
+ 1
2946
+ ),
2947
+ cooldownMs: Math.max(0, N(e.cooldownMs, j.cooldownMs))
2948
+ }), Y = (e, s, t) => {
2949
+ if (typeof s == "number" && Number.isInteger(s) && s >= 0 && s < e.length)
2950
+ return s;
2951
+ if (typeof s == "string") {
2952
+ const n = e.findIndex((r) => r.name === s);
2953
+ if (n >= 0) return n;
2954
+ }
2955
+ return t;
2956
+ }, $n = (e = {}) => {
2957
+ const s = e.tiers && e.tiers.length ? e.tiers.map((r, a) => Zn(r, a)) : Qn, t = Y(s, e.maxTier, 0), n = Math.max(t, Y(s, e.minTier, s.length - 1));
2958
+ return {
2959
+ tiers: s,
2960
+ budget: Jn(e.budget),
2961
+ ...e.initialTier !== void 0 ? { initialTier: e.initialTier } : {},
2962
+ minTier: n,
2963
+ maxTier: t,
2964
+ adaptive: e.adaptive !== !1,
2965
+ historySize: Math.max(1, Math.round(N(e.historySize, 20)))
2966
+ };
2967
+ }, er = (e, s) => {
2968
+ const t = Y(e.tiers, e.maxTier, 0), n = Y(e.tiers, e.minTier, e.tiers.length - 1);
2969
+ if (e.initialTier !== void 0)
2970
+ return fe(Y(e.tiers, e.initialTier, t), t, n);
2971
+ const r = s.deviceMemoryGb !== null && s.deviceMemoryGb <= 4 || s.hardwareConcurrency !== null && s.hardwareConcurrency <= 4;
2972
+ return fe(r ? t + 1 : t, t, n);
2973
+ }, _t = (e, s = It, t = 0) => {
2974
+ const n = er(e, s), r = { index: n, tier: e.tiers[n], reason: "init", at: t };
2975
+ return {
2976
+ index: n,
2977
+ locked: !1,
2978
+ badStreak: 0,
2979
+ goodStreak: 0,
2980
+ lastChangeAt: t,
2981
+ decision: r,
2982
+ history: [r],
2983
+ signals: s
2984
+ };
2985
+ }, Se = (e, s, t, n, r, a = e.signals) => {
2986
+ const c = { index: t, tier: s.tiers[t], reason: n, at: r };
2987
+ return {
2988
+ ...e,
2989
+ index: t,
2990
+ badStreak: 0,
2991
+ goodStreak: 0,
2992
+ lastChangeAt: r,
2993
+ decision: c,
2994
+ history: [c, ...e.history].slice(0, s.historySize),
2995
+ signals: a
2996
+ };
2997
+ }, tr = (e, s) => e.thermal === "critical" ? "thermal" : s.maxMemoryMb !== null && e.memoryMb !== null && e.memoryMb > s.maxMemoryMb ? "memory" : e.inferenceMs !== null && e.inferenceMs > s.maxInferenceMs ? "inference" : e.frameMs !== null && e.frameMs > s.maxFrameMs ? "frame-time" : null, sr = (e, s, t, n) => {
2998
+ const { budget: r } = t, a = Y(t.tiers, t.maxTier, 0), c = Y(t.tiers, t.minTier, t.tiers.length - 1);
2999
+ if (e.locked || !t.adaptive) return { ...e, signals: s };
3000
+ const o = tr(s, r), d = o === null && s.frameMs !== null && s.frameMs <= r.maxFrameMs * r.upgradeHeadroom && (s.inferenceMs === null || s.inferenceMs <= r.maxInferenceMs * r.upgradeHeadroom), l = o ? e.badStreak + 1 : 0, h = d ? e.goodStreak + 1 : 0, m = n - e.lastChangeAt >= r.cooldownMs;
3001
+ if (o && l >= r.downgradeAfter && m) {
3002
+ if (e.index < c)
3003
+ return Se(e, t, e.index + 1, o, n, s);
3004
+ const y = o === "frame-time" ? "suspected" : s.thermal;
3005
+ return { ...e, badStreak: l, goodStreak: h, signals: { ...s, thermal: y } };
3006
+ }
3007
+ return d && h >= r.upgradeAfter && m && e.index > a ? Se(e, t, e.index - 1, "recovered", n, s) : { ...e, badStreak: l, goodStreak: h, signals: s };
3008
+ }, Br = (e, s, t, n) => {
3009
+ const r = Y(s.tiers, t, e.index);
3010
+ return r === e.index ? e : Se(e, s, r, "manual", n);
3011
+ }, zr = (e, s, t, n) => t === e.locked ? e : { ...Se(e, s, e.index, t ? "locked" : "manual", n), locked: t }, nr = (e, s) => e.decision.tier === s ? null : e.decision.tier, Wr = (e, s, t) => {
3012
+ const n = _t(e, s, t);
3013
+ return {
3014
+ ...n,
3015
+ decision: { ...n.decision, reason: "reset" },
3016
+ history: [{ ...n.decision, reason: "reset" }]
3017
+ };
3018
+ }, rr = Object.values(R), ar = () => {
3019
+ if (typeof navigator > "u") return { deviceMemoryGb: null, hardwareConcurrency: null };
3020
+ const e = navigator;
3021
+ return {
3022
+ deviceMemoryGb: typeof e.deviceMemory == "number" ? e.deviceMemory : null,
3023
+ hardwareConcurrency: typeof e.hardwareConcurrency == "number" ? e.hardwareConcurrency : null
3024
+ };
3025
+ }, ir = () => {
3026
+ const e = performance.memory;
3027
+ return e ? e.usedJSHeapSize / 1048576 : null;
3028
+ }, or = ({ config: e, thermal: s, onDecision: t }) => {
3029
+ const { session: n } = Pt(), r = JSON.stringify(e ?? {}), a = ge(() => $n(e), [r]), c = oe(s ?? "unknown");
3030
+ c.current = s ?? "unknown";
3031
+ const o = oe(t);
3032
+ return o.current = t, he(() => {
3033
+ const d = ar();
3034
+ let l = _t(
3035
+ a,
3036
+ { ...It, ...d },
3037
+ performance.now()
3038
+ );
3039
+ const h = n.store.getSnapshot().quality;
3040
+ h && h.index < a.tiers.length && (l = {
3041
+ ...h,
3042
+ decision: { ...h.decision, tier: a.tiers[h.index] }
3043
+ }), n._setQualityConfig(a), n._setQuality(l);
3044
+ let m = n._getPerf(), y = null;
3045
+ const S = async (w, x) => {
3046
+ const H = {
3047
+ ...m,
3048
+ ...w.targetFps !== void 0 ? { targetFps: w.targetFps } : {},
3049
+ ...w.analysisScale !== void 0 ? { analysisScale: w.analysisScale } : {},
3050
+ ...w.camRes !== void 0 && w.rebindCamera ? { camRes: w.camRes } : {}
3051
+ };
3052
+ n._setPerf(H), w.rebindCamera && w.camRes !== void 0 && w.camRes !== (x == null ? void 0 : x.camRes) && await n._rebindMedia().catch(() => {
3053
+ });
3054
+ };
3055
+ y = l.decision.tier, S(l.decision.tier, null);
3056
+ let M = 0, C = performance.now(), E = 0;
3057
+ const _ = () => {
3058
+ M += 1, E = requestAnimationFrame(_);
3059
+ };
3060
+ E = requestAnimationFrame(_);
3061
+ let g = null;
3062
+ const v = window.setInterval(() => {
3063
+ var q;
3064
+ if (typeof document < "u" && document.hidden) {
3065
+ M = 0, C = performance.now();
3066
+ return;
3067
+ }
3068
+ const w = performance.now(), x = w - C, H = Ue(n, rr, g, w);
3069
+ g = { feedFrames: H.session.feedFrames, sampledAt: w };
3070
+ const T = n.store.getSnapshot().lifecycle === "running", U = {
3071
+ frameMs: M > 0 && x > 0 && T ? x / M : null,
3072
+ fps: M > 0 && x > 0 ? M * 1e3 / x : null,
3073
+ inferenceMs: T ? H.inferenceMsTotal : null,
3074
+ feedFps: H.session.feedFps,
3075
+ memoryMb: ir(),
3076
+ ...d,
3077
+ thermal: c.current
3078
+ };
3079
+ M = 0, C = w;
3080
+ const V = n.store.getSnapshot().quality ?? l, D = sr(V, U, a, w);
3081
+ l = D, n._setQuality(D);
3082
+ const A = nr(D, y);
3083
+ if (A) {
3084
+ const K = y;
3085
+ y = A, S(A, K), (q = o.current) == null || q.call(o, D);
3086
+ }
3087
+ }, a.budget.sampleMs);
3088
+ return () => {
3089
+ cancelAnimationFrame(E), window.clearInterval(v);
3090
+ const w = (y == null ? void 0 : y.rebindCamera) && y.camRes !== void 0;
3091
+ n._setPerf(m), w && (m == null ? void 0 : m.camRes) !== (y == null ? void 0 : y.camRes) && n._rebindMedia().catch(() => {
3092
+ }), m = void 0, n._setQualityConfig(null);
3093
+ };
3094
+ }, [n, a]), null;
3095
+ }, We = gt(void 0), Pt = () => {
3096
+ const e = Be(We);
3097
+ if (!e)
3098
+ throw new O(
3099
+ "XR context can only be used inside XRProvider, did you forget to wrap your app in <XRProvider>?"
3100
+ );
3101
+ return e;
3102
+ }, qr = () => Be(We) ?? null, Vr = ({ children: e, perf: s, lifecycle: t, quality: n }) => {
3103
+ const r = Kn(s, t), a = ge(() => ({ session: r }), [r]);
3104
+ return /* @__PURE__ */ ds(We.Provider, { value: a, children: [
3105
+ n !== !1 && /* @__PURE__ */ rt(or, { config: n || void 0 }),
3106
+ /* @__PURE__ */ rt(Xn, { children: e })
3107
+ ] });
3108
+ };
3109
+ export {
3110
+ As as $,
3111
+ qr as A,
3112
+ I as B,
3113
+ z as C,
3114
+ Nr as D,
3115
+ It as E,
3116
+ Ss as F,
3117
+ ze as G,
3118
+ wn as H,
3119
+ xt as I,
3120
+ wr as J,
3121
+ vr as K,
3122
+ Sr as L,
3123
+ Mr as M,
3124
+ Vr as N,
3125
+ Bs as O,
3126
+ kr as P,
3127
+ xr as Q,
3128
+ br as R,
3129
+ ht as S,
3130
+ Tr as T,
3131
+ Cr as U,
3132
+ Ar as V,
3133
+ Rr as W,
3134
+ R as X,
3135
+ mn as Y,
3136
+ yn as Z,
3137
+ St as _,
3138
+ Pr as a,
3139
+ Mt as a0,
3140
+ pr as a1,
3141
+ j as a2,
3142
+ Qn as a3,
3143
+ or as a4,
3144
+ Ne as a5,
3145
+ vn as a6,
3146
+ vt as a7,
3147
+ Ms as a8,
3148
+ Cs as a9,
3149
+ ks as aa,
3150
+ Ue as ab,
3151
+ kt as ac,
3152
+ bt as ad,
3153
+ Ur as ae,
3154
+ Yn as af,
3155
+ Ps as ag,
3156
+ _t as ah,
3157
+ tr as ai,
3158
+ ar as aj,
3159
+ er as ak,
3160
+ Jn as al,
3161
+ Zn as am,
3162
+ sr as an,
3163
+ nr as ao,
3164
+ In as ap,
3165
+ Lr as aq,
3166
+ Mn as ar,
3167
+ Sn as as,
3168
+ Cn as at,
3169
+ Hr as au,
3170
+ Fr as av,
3171
+ Xs as aw,
3172
+ tn as ax,
3173
+ sn as ay,
3174
+ J as az,
3175
+ fr as b,
3176
+ Us as c,
3177
+ gr as d,
3178
+ Br as e,
3179
+ Ir as f,
3180
+ Wr as g,
3181
+ Gs as h,
3182
+ Me as i,
3183
+ Ks as j,
3184
+ Ws as k,
3185
+ zr as l,
3186
+ yr as m,
3187
+ ue as n,
3188
+ De as o,
3189
+ _r as p,
3190
+ fn as q,
3191
+ $n as r,
3192
+ Ct as s,
3193
+ Er as t,
3194
+ Pt as u,
3195
+ Ns as v,
3196
+ Dr as w,
3197
+ Or as x,
3198
+ Fn as y,
3199
+ F as z
3200
+ };