@vincentt-xr/sdk 2.0.0-alpha.6 → 2.0.0-alpha.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (287) hide show
  1. package/GROUNDING.md +1188 -14
  2. package/dist/{DebuggerUI-C_rbLdkh.js → DebuggerUI-C-ldiozL.js} +1 -1
  3. package/dist/{DebuggerUI-DYT_dk1E.cjs → DebuggerUI-CWX5EtQv.cjs} +1 -1
  4. package/dist/FaceMeshRenderer-BEEXZwS6.cjs +158 -0
  5. package/dist/FaceMeshRenderer-UuH5sTXG.js +1322 -0
  6. package/dist/FaceRetouch-C7h7x9kd.js +683 -0
  7. package/dist/FaceRetouch-DqftT26Y.cjs +134 -0
  8. package/dist/GLTFLoader-C5q63sKO.js +1633 -0
  9. package/dist/GLTFLoader-Cb_CRwmG.cjs +1 -0
  10. package/dist/SegmentationOverlay-DQuW3dsc.js +133 -0
  11. package/dist/SegmentationOverlay-aWVod8Kl.cjs +1 -0
  12. package/dist/assets/cache.d.ts +99 -0
  13. package/dist/assets/estimate.d.ts +11 -0
  14. package/dist/assets/index.d.ts +7 -0
  15. package/dist/assets/loaders.d.ts +28 -0
  16. package/dist/assets/react.d.ts +33 -0
  17. package/dist/calibration/calibration.d.ts +70 -0
  18. package/dist/calibration/index.d.ts +6 -0
  19. package/dist/calibration/storage.d.ts +13 -0
  20. package/dist/calibration/types.d.ts +53 -0
  21. package/dist/calibration/useXRCalibration.d.ts +46 -0
  22. package/dist/camera/CameraPermissionGate.d.ts +26 -0
  23. package/dist/camera/devices.d.ts +26 -0
  24. package/dist/camera/index.d.ts +8 -0
  25. package/dist/camera/permission.d.ts +86 -0
  26. package/dist/camera/useCameraPermission.d.ts +35 -0
  27. package/dist/capabilities/detect.d.ts +45 -0
  28. package/dist/capabilities/index.d.ts +5 -0
  29. package/dist/capabilities/types.d.ts +120 -0
  30. package/dist/capabilities/useXRCapabilities.d.ts +18 -0
  31. package/dist/compat/environment.d.ts +5 -0
  32. package/dist/compat/index.d.ts +4 -0
  33. package/dist/compat/run.d.ts +18 -0
  34. package/dist/compat/scenarios.d.ts +10 -0
  35. package/dist/compat/types.d.ts +101 -0
  36. package/dist/components/BodyTracker/index.d.ts +9 -0
  37. package/dist/components/FaceMesh/FaceMeshRenderer.d.ts +11 -3
  38. package/dist/components/FaceMesh/canonical/CanonicalFaceMeshRenderer.d.ts +41 -5
  39. package/dist/components/FaceMesh/canonical/parseCanonicalFaceModel.d.ts +12 -0
  40. package/dist/components/FaceMesh/canonical/shaders.d.ts +1 -1
  41. package/dist/components/FaceMesh/index.d.ts +2 -2
  42. package/dist/components/GestureListener/index.d.ts +11 -0
  43. package/dist/components/HandTracker/index.d.ts +10 -0
  44. package/dist/components/HolisticTracker/index.d.ts +69 -0
  45. package/dist/components/HolisticTracker/settings.d.ts +58 -0
  46. package/dist/components/HolisticTracker/signals.d.ts +49 -0
  47. package/dist/components/IrisEffect/IrisMaterial.d.ts +73 -0
  48. package/dist/components/IrisEffect/index.d.ts +51 -0
  49. package/dist/components/IrisEffect/settings.d.ts +117 -0
  50. package/dist/components/LipEffect/LipEffect.d.ts +7 -1
  51. package/dist/components/LipEffect/LipEffectMaterial.d.ts +43 -7
  52. package/dist/components/LipEffect/LipEffects.d.ts +9 -0
  53. package/dist/components/LipEffect/defaults.d.ts +27 -4
  54. package/dist/components/LipEffect/index.d.ts +11 -3
  55. package/dist/components/LipEffect/settings.d.ts +271 -0
  56. package/dist/components/LipEffect/types.d.ts +56 -9
  57. package/dist/components/LipEffect/useLipDesignTextures.d.ts +11 -0
  58. package/dist/components/LipEffect/uvGuide.d.ts +59 -0
  59. package/dist/components/PersonCutout/index.d.ts +50 -0
  60. package/dist/components/PersonCutout/personCutout.d.ts +16 -0
  61. package/dist/components/SceneObjectRenderer/index.d.ts +9 -2
  62. package/dist/components/ScreenImage/components/ScreenImageBody.d.ts +1 -1
  63. package/dist/components/ScreenImage/index.d.ts +3 -1
  64. package/dist/components/ScreenImage/materials/ScreenImageBlendMaterial.d.ts +1 -1
  65. package/dist/components/ScreenImage/materials/ScreenImageMaskMaterial.d.ts +11 -0
  66. package/dist/components/ScreenImage/source.d.ts +6 -0
  67. package/dist/components/ScreenImage/types.d.ts +18 -0
  68. package/dist/components/SegmentationOverlay/SegmentationOverlay.d.ts +37 -0
  69. package/dist/components/SegmentationOverlay/SegmentationOverlayMaterial.d.ts +31 -0
  70. package/dist/components/SegmentationOverlay/index.d.ts +9 -0
  71. package/dist/components/SegmentationOverlay/maskTexture.d.ts +23 -0
  72. package/dist/components/SegmentationOverlay/providers.d.ts +72 -0
  73. package/dist/components/SegmentationOverlay/settings.d.ts +65 -0
  74. package/dist/components/XRMediaSurface/index.d.ts +2 -1
  75. package/dist/components/XRProvider/index.d.ts +16 -2
  76. package/dist/components/XRViewport/hooks/useViewportExternalFaces.d.ts +1 -1
  77. package/dist/components/XRViewport/hooks/useViewportMediaSource.d.ts +1 -1
  78. package/dist/components/XRViewport/hooks/useViewportPipeline.d.ts +1 -1
  79. package/dist/components/index.d.ts +3 -0
  80. package/dist/constants/index.d.ts +4 -1
  81. package/dist/contexts-CO0sd4JQ.cjs +1 -0
  82. package/dist/{contexts-DvQI4PqI.js → contexts-FzlnnMYD.js} +252 -246
  83. package/dist/coordinates/feed.d.ts +52 -0
  84. package/dist/coordinates/index.d.ts +5 -0
  85. package/dist/coordinates/spaces.d.ts +49 -0
  86. package/dist/coordinates/viewport.d.ts +22 -0
  87. package/dist/coordinates/world.d.ts +15 -0
  88. package/dist/debug-ui/gesture-settings/index.d.ts +14 -0
  89. package/dist/debug-ui/holistic-tracker-settings/index.d.ts +16 -0
  90. package/dist/debug-ui/index.d.ts +14 -0
  91. package/dist/debug-ui/iris-effect-settings/index.d.ts +12 -0
  92. package/dist/debug-ui/lip-effect-settings/index.d.ts +15 -0
  93. package/dist/debug-ui/media-source.cjs +1 -1
  94. package/dist/debug-ui/media-source.js +1 -1
  95. package/dist/debug-ui/product-hotspots/index.d.ts +24 -0
  96. package/dist/debug-ui/segmentation-overlay-settings/index.d.ts +12 -0
  97. package/dist/debug-ui/xr-diagnostics/index.d.ts +25 -0
  98. package/dist/debug-ui.cjs +3 -3
  99. package/dist/debug-ui.js +2057 -1687
  100. package/dist/detector-K8aej4MB.js +59 -0
  101. package/dist/detector-ijypGtse.cjs +1 -0
  102. package/dist/entries/core.d.ts +21 -3
  103. package/dist/entries/face-effects.d.ts +12 -4
  104. package/dist/entries/low-level.d.ts +22 -3
  105. package/dist/entries/product.d.ts +11 -0
  106. package/dist/entries/tracking.d.ts +26 -1
  107. package/dist/face-effects.cjs +155 -1
  108. package/dist/face-effects.js +1134 -2196
  109. package/dist/gestures/definitions.d.ts +85 -0
  110. package/dist/gestures/detector.d.ts +87 -0
  111. package/dist/gestures/index.d.ts +8 -0
  112. package/dist/gestures/measures.d.ts +101 -0
  113. package/dist/gestures/settings.d.ts +49 -0
  114. package/dist/{getFaceInfo-B43Cwq4n.js → getFaceInfo-BkZfaQs-.js} +5 -5
  115. package/dist/{getFaceInfo-DEzcL_Ub.cjs → getFaceInfo-ahPxQFGu.cjs} +1 -1
  116. package/dist/hooks/selectors.d.ts +68 -1
  117. package/dist/hooks/useCalibrationFaceTracker.d.ts +1 -1
  118. package/dist/hooks/useFaceInfo.d.ts +13 -1
  119. package/dist/hooks/useFaceInfos.d.ts +1 -1
  120. package/dist/hooks/useGesture.d.ts +32 -0
  121. package/dist/hooks/useIrisTracking.d.ts +45 -0
  122. package/dist/hooks/useXRDiagnostics.d.ts +81 -0
  123. package/dist/hooks/useXRModel.d.ts +7 -0
  124. package/dist/hooks/useXRSession/facade.d.ts +44 -2
  125. package/dist/hooks/useXRSession/index.d.ts +2 -2
  126. package/dist/hooks/useXRSession/reason.d.ts +3 -1
  127. package/dist/hooks/useXRSession/registry.d.ts +14 -0
  128. package/dist/hooks/useXRSession/store.d.ts +52 -3
  129. package/dist/index--RgGzZ6X.cjs +47 -0
  130. package/dist/{index-uE3sKczj.js → index-CHVbH0hz.js} +4 -4
  131. package/dist/index-CeVkgsag.cjs +1 -0
  132. package/dist/index-CnGox6Xr.js +3054 -0
  133. package/dist/{index-B-s4YbWu.js → index-CsUdQ-pn.js} +113 -111
  134. package/dist/{index-CY7Z8cHV.cjs → index-DKBAh6hV.cjs} +1 -1
  135. package/dist/index-DsZwTfG0.cjs +1 -0
  136. package/dist/index-Dw6tj2Mi.js +144 -0
  137. package/dist/index-OCPjOaeP.cjs +1 -0
  138. package/dist/{index-G_5h_FJQ.js → index-s9pF4zkG.js} +999 -1014
  139. package/dist/internal-BYza1h8_.cjs +1 -0
  140. package/dist/{internal-ldPYiUF0.js → internal-vsfNQycj.js} +15 -16
  141. package/dist/internal.cjs +1 -1
  142. package/dist/internal.js +2 -2
  143. package/dist/iris/compute.d.ts +25 -0
  144. package/dist/iris/index.d.ts +4 -0
  145. package/dist/iris/lead.d.ts +19 -0
  146. package/dist/iris/types.d.ts +87 -0
  147. package/dist/landmarkMask-CbTFzBYG.js +224 -0
  148. package/dist/landmarkMask-u7es2k4X.cjs +1 -0
  149. package/dist/low-level.cjs +1 -1
  150. package/dist/low-level.js +1104 -639
  151. package/dist/main.cjs +1 -1
  152. package/dist/main.js +1519 -462
  153. package/dist/measures-9dQPdw96.js +154 -0
  154. package/dist/measures-KfJzpvod.cjs +1 -0
  155. package/dist/models/Base/index.d.ts +49 -0
  156. package/dist/models/Body/index.d.ts +1 -1
  157. package/dist/models/Face/index.d.ts +1 -1
  158. package/dist/models/Hand/GestureTracking.d.ts +1 -1
  159. package/dist/models/Hand/HandTracking.d.ts +1 -1
  160. package/dist/models/Holistic/index.d.ts +49 -0
  161. package/dist/models/Holistic/result.d.ts +68 -0
  162. package/dist/models/SemanticSegmentation/index.d.ts +31 -0
  163. package/dist/models/SemanticSegmentation/presets.d.ts +28 -0
  164. package/dist/models/index.d.ts +2 -0
  165. package/dist/product/ProductDimensions.d.ts +16 -0
  166. package/dist/product/ProductHotspot.d.ts +16 -0
  167. package/dist/product/ProductViewer.d.ts +9 -0
  168. package/dist/product/details.d.ts +53 -0
  169. package/dist/product/index.d.ts +14 -0
  170. package/dist/product/loadModelViewer.d.ts +4 -0
  171. package/dist/product/types.d.ts +71 -0
  172. package/dist/product/useProductAr.d.ts +37 -0
  173. package/dist/product/useProductDetails.d.ts +60 -0
  174. package/dist/product.cjs +1 -0
  175. package/dist/product.js +414 -0
  176. package/dist/providers-C0Dlhh9Z.js +365 -0
  177. package/dist/providers-YNwkmNeK.cjs +62 -0
  178. package/dist/quality/XRQualityController.d.ts +25 -0
  179. package/dist/quality/controller.d.ts +33 -0
  180. package/dist/quality/index.d.ts +6 -0
  181. package/dist/quality/types.d.ts +100 -0
  182. package/dist/quality/useXRQuality.d.ts +28 -0
  183. package/dist/{renderGroups-CFt1yYLB.js → renderGroups-CN1cGFUo.js} +1 -1
  184. package/dist/{renderGroups-BJsx32q5.cjs → renderGroups-O4KmaMl9.cjs} +1 -1
  185. package/dist/renderPasses-Cg-zqmEz.cjs +21 -0
  186. package/dist/renderPasses-NnKZVfBy.js +1460 -0
  187. package/dist/scene-object.cjs +1 -1
  188. package/dist/scene-object.js +2 -2
  189. package/dist/screen2d/coordinates.d.ts +20 -0
  190. package/dist/screenTransform-BenfCtZt.js +44 -0
  191. package/dist/screenTransform-BiXdpVf0.cjs +1 -0
  192. package/dist/segmentation-9PhSvc-R.cjs +1 -0
  193. package/dist/segmentation-CeOTKemr.js +5 -0
  194. package/dist/segmentation2d/faceMemory.d.ts +28 -0
  195. package/dist/segmentation2d/faceRegions.d.ts +24 -0
  196. package/dist/segmentation2d/index.d.ts +9 -0
  197. package/dist/segmentation2d/maskUv.d.ts +23 -0
  198. package/dist/segmentation2d/rasterize.d.ts +14 -0
  199. package/dist/segmentation2d/types.d.ts +46 -0
  200. package/dist/selectors-C5G1PMYL.js +195 -0
  201. package/dist/selectors-Du_PsVnW.cjs +1 -0
  202. package/dist/{session-CANvoLD6.cjs → session-BBr0yN8h.cjs} +7 -7
  203. package/dist/{session-Dhi0OqZo.js → session-Cy0m7l7-.js} +76 -76
  204. package/dist/settings-DRR7-snV.cjs +1 -0
  205. package/dist/settings-aQk845NJ.js +73 -0
  206. package/dist/subjects/index.d.ts +2 -0
  207. package/dist/subjects/select.d.ts +62 -0
  208. package/dist/subjects/types.d.ts +55 -0
  209. package/dist/tracking/coordinates.d.ts +5 -0
  210. package/dist/tracking-config/apply.d.ts +57 -0
  211. package/dist/tracking-config/index.d.ts +7 -0
  212. package/dist/tracking-config/resolve.d.ts +25 -0
  213. package/dist/tracking-config/storage.d.ts +8 -0
  214. package/dist/tracking-config/types.d.ts +106 -0
  215. package/dist/tracking-config/useXRTrackingConfig.d.ts +38 -0
  216. package/dist/tracking.cjs +1 -1
  217. package/dist/tracking.js +1056 -380
  218. package/dist/types/common.d.ts +11 -1
  219. package/dist/types/compositor.d.ts +21 -0
  220. package/dist/types/gesture-tracking.d.ts +2 -2
  221. package/dist/types/hand-tracking.d.ts +3 -3
  222. package/dist/types/holistic.d.ts +121 -0
  223. package/dist/types/index.d.ts +1 -0
  224. package/dist/types/model.d.ts +22 -2
  225. package/dist/types/nodes.d.ts +29 -4
  226. package/dist/types/segmentation.d.ts +19 -0
  227. package/dist/types/session.d.ts +48 -4
  228. package/dist/useFaceInfo-Blf7FCu3.js +303 -0
  229. package/dist/useFaceInfo-C5mO8NQY.cjs +1 -0
  230. package/dist/useXRCapabilities-B1R2ghy-.cjs +1 -0
  231. package/dist/useXRCapabilities-C68v__wB.js +30 -0
  232. package/dist/utils/fns.d.ts +6 -3
  233. package/dist/utils/integrity.d.ts +4 -1
  234. package/dist/utils/updateThrottle.d.ts +2 -0
  235. package/dist/utils/useStableUniforms.d.ts +18 -0
  236. package/docs/SDK_DOCUMENTATION.md +3 -0
  237. package/docs/api/adaptive-quality.mdx +104 -0
  238. package/docs/api/asset-lifecycle.mdx +78 -0
  239. package/docs/api/camera-permission.mdx +142 -0
  240. package/docs/api/capture-recording.mdx +9 -1
  241. package/docs/api/coordinate-spaces.mdx +165 -0
  242. package/docs/api/cross-camera.mdx +88 -0
  243. package/docs/api/diagnostics-calibration.mdx +97 -0
  244. package/docs/api/face-effects.mdx +6 -0
  245. package/docs/api/face-mesh.mdx +35 -0
  246. package/docs/api/gestures.mdx +173 -0
  247. package/docs/api/holistic-tracker.mdx +159 -0
  248. package/docs/api/iris-tracking.mdx +242 -0
  249. package/docs/api/multi-subject.mdx +95 -0
  250. package/docs/api/person-cutout.mdx +136 -0
  251. package/docs/api/product-ar.mdx +111 -0
  252. package/docs/api/product-details.mdx +78 -0
  253. package/docs/api/runtime-3d.mdx +5 -0
  254. package/docs/api/screen-image.mdx +3 -1
  255. package/docs/api/screen-space-coordinates.mdx +35 -1
  256. package/docs/api/segmentation-overlay.mdx +301 -0
  257. package/docs/api/session-lifecycle.mdx +136 -0
  258. package/docs/api/trackers.mdx +18 -0
  259. package/docs/api/tracking-config.mdx +108 -0
  260. package/docs/docs.json +23 -1
  261. package/docs/examples/lip-shaders.mdx +224 -0
  262. package/docs/guides/lip-effect-textures.mdx +292 -0
  263. package/docs/guides/lip-uv-template.png +0 -0
  264. package/docs/guides/lip-uv-template.svg +1 -0
  265. package/package.json +16 -1
  266. package/dist/FaceMeshRenderer-D1WsrTLA.cjs +0 -155
  267. package/dist/FaceMeshRenderer-DSCd1H55.js +0 -1264
  268. package/dist/FaceRetouch-CMJbGThL.js +0 -551
  269. package/dist/FaceRetouch-DsE0Dbw-.cjs +0 -134
  270. package/dist/contexts-h-9TRH0r.cjs +0 -1
  271. package/dist/index-C0-fg1Hk.cjs +0 -1
  272. package/dist/index-CxMEeCRP.cjs +0 -1
  273. package/dist/index-D67hHm44.cjs +0 -1
  274. package/dist/index-DPPpU5By.cjs +0 -17
  275. package/dist/index-DYfY9ljy.js +0 -111
  276. package/dist/index-I4eF5TKT.js +0 -1457
  277. package/dist/internal-MvKrz0Nt.cjs +0 -1
  278. package/dist/renderLayers-lDtL0_43.cjs +0 -1
  279. package/dist/renderLayers-zrK2pv5O.js +0 -13
  280. package/dist/renderPasses-C72MbZ-a.js +0 -1500
  281. package/dist/renderPasses-D-Krl6D0.cjs +0 -21
  282. package/dist/selectors-ByKNTXeA.js +0 -59
  283. package/dist/selectors-CAwmL9VW.cjs +0 -1
  284. package/dist/useFaceInfo-BSZq7AO1.cjs +0 -1
  285. package/dist/useFaceInfo-FVQBBNdY.js +0 -62
  286. package/dist/useFaceResults-C3oZkn2Z.cjs +0 -1
  287. package/dist/useFaceResults-D62STzT1.js +0 -19
@@ -0,0 +1,303 @@
1
+ import { useMemo as I, useEffect as N, useCallback as k, useRef as U } from "react";
2
+ import { Vector2 as X, Raycaster as S, Ray as Y, Vector3 as L } from "three";
3
+ import { D as d, a as y } from "./screenTransform-BenfCtZt.js";
4
+ import { n as j, t as A, X as p } from "./index-CnGox6Xr.js";
5
+ import { useThree as D } from "@react-three/fiber";
6
+ import { g as B, u as J } from "./getFaceInfo-BkZfaQs-.js";
7
+ import { u as V } from "./index-CsUdQ-pn.js";
8
+ const a = (e, n) => {
9
+ if (!Number.isFinite(e) || e <= 0) throw new RangeError(`${n} must be positive`);
10
+ return e;
11
+ }, q = (e, n) => {
12
+ const t = a(n.width, "root.width"), s = a(n.height, "root.height");
13
+ return !Number.isFinite(e.width) || !Number.isFinite(e.height) || e.width <= 0 || e.height <= 0 ? 0 : Math.min(e.width / t, e.height / s);
14
+ }, b = (e, n, t, s) => n.width <= 0 || n.height <= 0 ? Object.assign(s, { x: 0, y: 0 }) : (a(t.width, "root.width"), a(t.height, "root.height"), s.x = (e.x / n.width - 0.5) * t.width, s.y = (0.5 - e.y / n.height) * t.height, s), P = (e, n, t, s) => n.width <= 0 || n.height <= 0 ? Object.assign(s, { x: 0, y: 0 }) : (a(t.width, "root.width"), a(t.height, "root.height"), s.x = (e.x / t.width + 0.5) * n.width, s.y = (0.5 - e.y / t.height) * n.height, s), O = ({
15
+ parentSize: e,
16
+ referencePixelsPerUnit: n = y,
17
+ root: t = d
18
+ }) => q(e, t) * (y / a(n, "referencePixelsPerUnit")), re = (e, n) => e * O(n), ce = (e, n) => {
19
+ const t = O(n);
20
+ return t === 0 ? 0 : e / t;
21
+ }, oe = ({
22
+ point: e,
23
+ parentSize: n,
24
+ referencePixelsPerUnit: t = y,
25
+ root: s = d,
26
+ target: i = { x: 0, y: 0 }
27
+ }) => {
28
+ if (n.width <= 0 || n.height <= 0) return Object.assign(i, { x: 0, y: 0 });
29
+ const r = y / a(t, "referencePixelsPerUnit");
30
+ return i.x = e.x * (n.width / a(s.width, "root.width")) * r, i.y = e.y * (n.height / a(s.height, "root.height")) * r, i;
31
+ }, he = ({
32
+ point: e,
33
+ parentSize: n,
34
+ referencePixelsPerUnit: t = y,
35
+ root: s = d,
36
+ target: i = { x: 0, y: 0 }
37
+ }) => {
38
+ if (n.width <= 0 || n.height <= 0) return Object.assign(i, { x: 0, y: 0 });
39
+ const r = y / a(t, "referencePixelsPerUnit");
40
+ return i.x = e.x / (n.width / a(s.width, "root.width") * r), i.y = e.y / (n.height / a(s.height, "root.height") * r), i;
41
+ }, xe = ({
42
+ point: e,
43
+ rect: n,
44
+ root: t = d,
45
+ target: s = { x: 0, y: 0 }
46
+ }) => b({ x: e.x - n.left, y: e.y - n.top }, n, t, s), ae = ({
47
+ point: e,
48
+ rect: n,
49
+ root: t = d,
50
+ target: s = { x: 0, y: 0 }
51
+ }) => (P(e, n, t, s), s.x += n.left, s.y += n.top, s), _ = ({
52
+ point: e,
53
+ root: n = d,
54
+ target: t = { x: 0, y: 0 },
55
+ viewportSize: s
56
+ }) => b(
57
+ { x: e.x * s.width, y: e.y * s.height },
58
+ s,
59
+ n,
60
+ t
61
+ ), K = ({
62
+ point: e,
63
+ root: n = d,
64
+ target: t = { x: 0, y: 0 },
65
+ viewportSize: s
66
+ }) => s.width <= 0 || s.height <= 0 ? Object.assign(t, { x: 0, y: 0 }) : (P(e, s, n, t), t.x /= s.width, t.y /= s.height, t), de = ({
67
+ point: e,
68
+ root: n = d,
69
+ target: t = { x: 0, y: 0 },
70
+ viewportSize: s
71
+ }) => _({
72
+ point: { x: (e.x + 1) / 2, y: (1 - e.y) / 2 },
73
+ viewportSize: s,
74
+ root: n,
75
+ target: t
76
+ }), le = ({
77
+ layout: e,
78
+ mirrored: n = !1,
79
+ point: t,
80
+ root: s = d,
81
+ target: i = { x: 0, y: 0 }
82
+ }) => {
83
+ if (e.scale <= 0) return Object.assign(i, { x: 0, y: 0 });
84
+ const r = e.offsetX + t.x * e.scale;
85
+ return b(
86
+ {
87
+ x: n ? e.destination.width - r : r,
88
+ y: e.offsetY + t.y * e.scale
89
+ },
90
+ e.destination,
91
+ s,
92
+ i
93
+ );
94
+ }, ue = ({
95
+ layout: e,
96
+ mirrored: n = !1,
97
+ point: t,
98
+ root: s = d,
99
+ target: i = { x: 0, y: 0 }
100
+ }) => {
101
+ if (e.scale <= 0) return Object.assign(i, { x: 0, y: 0 });
102
+ P(t, e.destination, s, i);
103
+ const r = n ? e.destination.width - i.x : i.x;
104
+ return i.x = (r - e.offsetX) / e.scale, i.y = (i.y - e.offsetY) / e.scale, i;
105
+ }, w = new L(), g = new X(), R = new S(), fe = ({
106
+ camera: e,
107
+ point: n,
108
+ root: t = d,
109
+ target: s = { x: 0, y: 0, depth: 0 },
110
+ viewportSize: i
111
+ }) => (a(t.width, "root.width"), a(t.height, "root.height"), w.set(n.x, n.y, n.z).project(e), s.x = w.x * t.width / 2, s.y = w.y * t.height / 2, s.depth = w.z, s), ye = ({
112
+ camera: e,
113
+ point: n,
114
+ root: t = d,
115
+ target: s = new Y(),
116
+ viewportSize: i
117
+ }) => (a(t.width, "root.width"), a(t.height, "root.height"), g.set(n.x * 2 / t.width, n.y * 2 / t.height), R.setFromCamera(g, e), s.copy(R.ray)), me = (e, n) => j({ x: e.x, y: e.y, z: e.z ?? 0 }, n), H = (e, n = { x: 0, y: 0 }) => {
118
+ const t = A(e);
119
+ return n.x = t.x, n.y = t.y, n.z = t.z, n;
120
+ }, we = (e, n, t = { x: 0, y: 0 }) => (t.x = e.x * n.width, t.y = e.y * n.height, t), Te = (e, n, t = { x: 0, y: 0 }) => n.width <= 0 || n.height <= 0 ? Object.assign(t, { x: 0, y: 0 }) : (t.x = e.x / n.width, t.y = e.y / n.height, t), be = (e, n, t = {}) => _({
121
+ point: e,
122
+ viewportSize: n,
123
+ root: t.root,
124
+ target: t.target
125
+ }), Pe = (e, n, t = {}) => {
126
+ const s = t.target ?? { x: 0, y: 0 };
127
+ return K({ point: e, viewportSize: n, root: t.root, target: s }), s;
128
+ }, W = { selection: "index", index: 0 }, $ = Object.freeze({
129
+ face: { max: 10, default: 1, option: "numFaces" },
130
+ hand: { max: 2, default: 2, option: null },
131
+ gesture: { max: 1, default: 1, option: null },
132
+ body: { max: 1, default: 1, option: null },
133
+ holistic: { max: 1, default: 1, option: null }
134
+ }), C = { center: null }, f = (e, n) => Math.hypot(e.x - n.x, e.y - n.y), M = (e, n, t) => {
135
+ if (!e.length) return null;
136
+ switch (n) {
137
+ case "largest":
138
+ return e.reduce((s, i) => i.size > s.size ? i : s);
139
+ case "nearest-center":
140
+ return e.reduce(
141
+ (s, i) => f(i.center, { x: 0.5, y: 0.5 }) < f(s.center, { x: 0.5, y: 0.5 }) ? i : s
142
+ );
143
+ case "leftmost":
144
+ return e.reduce((s, i) => i.center.x < s.center.x ? i : s);
145
+ case "rightmost":
146
+ return e.reduce((s, i) => i.center.x > s.center.x ? i : s);
147
+ default:
148
+ return e.find((s) => s.index === t) ?? null;
149
+ }
150
+ }, G = (e, n = W, t = C) => {
151
+ const s = n.index ?? 0;
152
+ if (n.selection !== "sticky") {
153
+ const c = M(e, n.selection, s);
154
+ return {
155
+ index: (c == null ? void 0 : c.index) ?? null,
156
+ reason: c ? n.selection : "none",
157
+ memory: c ? { center: { ...c.center }, label: c.label } : t
158
+ };
159
+ }
160
+ const i = n.stickyRadius ?? 0.2;
161
+ if (t.center) {
162
+ const c = t.center, x = e.filter((l) => f(l.center, c) <= i).sort((l, m) => f(l.center, c) - f(m.center, c)), h = (t.label ? x.find((l) => l.label === t.label) : void 0) ?? x[0];
163
+ if (h)
164
+ return {
165
+ index: h.index,
166
+ reason: "sticky",
167
+ memory: { center: { ...h.center }, label: h.label }
168
+ };
169
+ }
170
+ const r = M(e, n.fallback ?? "largest", s);
171
+ return {
172
+ index: (r == null ? void 0 : r.index) ?? null,
173
+ reason: r ? "sticky-fallback" : "none",
174
+ // Keep the old memory on a miss so a brief dropout does not forget the subject.
175
+ memory: r ? { center: { ...r.center }, label: r.label } : t
176
+ };
177
+ }, Fe = (e) => e.map((n, t) => {
178
+ let s = 1 / 0, i = -1 / 0, r = 1 / 0, c = -1 / 0;
179
+ for (const o of n)
180
+ o.x < s && (s = o.x), o.x > i && (i = o.x), o.y < r && (r = o.y), o.y > c && (c = o.y);
181
+ const x = n.length > 0 && Number.isFinite(s);
182
+ return {
183
+ index: t,
184
+ center: x ? { x: (s + i) / 2, y: (r + c) / 2 } : { x: 0.5, y: 0.5 },
185
+ size: x ? i - s : 0
186
+ };
187
+ }), Ee = (e) => e.map((n, t) => {
188
+ const s = (n.coordinates ?? []).map((h) => H(h));
189
+ let i = 1 / 0, r = -1 / 0, c = 1 / 0, x = -1 / 0;
190
+ for (const h of s)
191
+ h.x < i && (i = h.x), h.x > r && (r = h.x), h.y < c && (c = h.y), h.y > x && (x = h.y);
192
+ const o = s.length > 0;
193
+ return {
194
+ index: t,
195
+ center: o ? { x: (i + r) / 2, y: (c + x) / 2 } : { x: 0.5, y: 0.5 },
196
+ size: o ? Math.max(r - i, x - c) : 0,
197
+ ...n.label ? { label: n.label } : {}
198
+ };
199
+ }), ge = (e, n, t = 0.35) => {
200
+ const s = [];
201
+ for (const c of e)
202
+ for (const x of n) {
203
+ const o = f(c.center, x.center);
204
+ o <= t && s.push({ primaryIndex: c.index, secondaryIndex: x.index, distance: o });
205
+ }
206
+ s.sort((c, x) => c.distance - x.distance);
207
+ const i = /* @__PURE__ */ new Set(), r = /* @__PURE__ */ new Set();
208
+ return s.filter((c) => i.has(c.primaryIndex) || r.has(c.secondaryIndex) ? !1 : (i.add(c.primaryIndex), r.add(c.secondaryIndex), !0));
209
+ }, Q = ({
210
+ active: e = !0,
211
+ holdMs: n = 250,
212
+ numFaces: t = 1,
213
+ targetFps: s,
214
+ throttleMs: i = 16
215
+ } = {}) => {
216
+ const { camera: r } = D(), c = Number.isFinite(t) ? Math.min($.face.max, Math.max(1, Math.round(t))) : 1, x = s !== void 0 && Number.isFinite(s) && s > 0 ? s : void 0, o = I(
217
+ () => ({
218
+ numFaces: c,
219
+ ...x ? { targetFps: x } : {}
220
+ }),
221
+ [c, x]
222
+ ), { node: h, ready: l } = V(
223
+ p.FACE_TRACKER,
224
+ o,
225
+ e
226
+ );
227
+ N(() => {
228
+ if (h)
229
+ for (let u = 0; u < o.numFaces; u += 1)
230
+ h.setCamera(r, u);
231
+ }, [o.numFaces, r, h]);
232
+ const m = k(
233
+ (u) => {
234
+ if (!h) return [];
235
+ const F = [];
236
+ for (let T = 0; T < u.faceLandmarks.length; T += 1) {
237
+ const E = B(h, u, T);
238
+ E && F.push(E);
239
+ }
240
+ return F;
241
+ },
242
+ [h]
243
+ );
244
+ return J({
245
+ enabled: e && l,
246
+ holdMs: Number.isFinite(n) ? Math.max(0, n) : 250,
247
+ node: h,
248
+ prepare: m,
249
+ throttleMs: Number.isFinite(i) ? Math.max(0, i) : 16
250
+ });
251
+ }, Z = 4, Re = ({
252
+ faceIndex: e = 0,
253
+ numFaces: n,
254
+ subject: t,
255
+ ...s
256
+ } = {}) => {
257
+ const i = Number.isFinite(e) ? Math.max(0, Math.round(e)) : 0, r = Q({
258
+ ...s,
259
+ numFaces: Math.max(n ?? (t ? Z : i + 1), i + 1)
260
+ }), c = U(C), x = JSON.stringify(t ?? null), o = I(() => {
261
+ if (!t) return null;
262
+ const h = r.map((l, m) => ({
263
+ index: m,
264
+ center: { x: l.bounds.centerX, y: l.bounds.centerY },
265
+ size: l.bounds.width
266
+ }));
267
+ return G(h, t, c.current);
268
+ }, [r, x]);
269
+ return N(() => {
270
+ o && (c.current = o.memory);
271
+ }, [o]), t ? o && o.index !== null ? r[o.index] ?? null : null : r[i] ?? null;
272
+ };
273
+ export {
274
+ W as D,
275
+ C as E,
276
+ $ as X,
277
+ ge as a,
278
+ Z as b,
279
+ Re as c,
280
+ xe as d,
281
+ re as e,
282
+ Fe as f,
283
+ ae as g,
284
+ ue as h,
285
+ K as i,
286
+ Ee as j,
287
+ oe as k,
288
+ ye as l,
289
+ le as m,
290
+ _ as n,
291
+ he as o,
292
+ ce as p,
293
+ be as q,
294
+ me as r,
295
+ G as s,
296
+ de as t,
297
+ Q as u,
298
+ we as v,
299
+ fe as w,
300
+ Pe as x,
301
+ H as y,
302
+ Te as z
303
+ };
@@ -0,0 +1 @@
1
+ "use strict";const T=require("react"),R=require("three"),l=require("./screenTransform-BiXdpVf0.cjs"),F=require("./index-CeVkgsag.cjs"),j=require("@react-three/fiber"),w=require("./getFaceInfo-ahPxQFGu.cjs"),q=require("./index-OCPjOaeP.cjs"),h=(e,n)=>{if(!Number.isFinite(e)||e<=0)throw new RangeError(`${n} must be positive`);return e},B=(e,n)=>{const t=h(n.width,"root.width"),i=h(n.height,"root.height");return!Number.isFinite(e.width)||!Number.isFinite(e.height)||e.width<=0||e.height<=0?0:Math.min(e.width/t,e.height/i)},m=(e,n,t,i)=>n.width<=0||n.height<=0?Object.assign(i,{x:0,y:0}):(h(t.width,"root.width"),h(t.height,"root.height"),i.x=(e.x/n.width-.5)*t.width,i.y=(.5-e.y/n.height)*t.height,i),P=(e,n,t,i)=>n.width<=0||n.height<=0?Object.assign(i,{x:0,y:0}):(h(t.width,"root.width"),h(t.height,"root.height"),i.x=(e.x/t.width+.5)*n.width,i.y=(.5-e.y/t.height)*n.height,i),I=({parentSize:e,referencePixelsPerUnit:n=l.DEFAULT_REFERENCE_PIXELS_PER_UNIT,root:t=l.DEFAULT_SCREEN_TRANSFORM_ROOT})=>B(e,t)*(l.DEFAULT_REFERENCE_PIXELS_PER_UNIT/h(n,"referencePixelsPerUnit")),J=(e,n)=>e*I(n),V=(e,n)=>{const t=I(n);return t===0?0:e/t},p=({point:e,parentSize:n,referencePixelsPerUnit:t=l.DEFAULT_REFERENCE_PIXELS_PER_UNIT,root:i=l.DEFAULT_SCREEN_TRANSFORM_ROOT,target:s={x:0,y:0}})=>{if(n.width<=0||n.height<=0)return Object.assign(s,{x:0,y:0});const r=l.DEFAULT_REFERENCE_PIXELS_PER_UNIT/h(t,"referencePixelsPerUnit");return s.x=e.x*(n.width/h(i.width,"root.width"))*r,s.y=e.y*(n.height/h(i.height,"root.height"))*r,s},H=({point:e,parentSize:n,referencePixelsPerUnit:t=l.DEFAULT_REFERENCE_PIXELS_PER_UNIT,root:i=l.DEFAULT_SCREEN_TRANSFORM_ROOT,target:s={x:0,y:0}})=>{if(n.width<=0||n.height<=0)return Object.assign(s,{x:0,y:0});const r=l.DEFAULT_REFERENCE_PIXELS_PER_UNIT/h(t,"referencePixelsPerUnit");return s.x=e.x/(n.width/h(i.width,"root.width")*r),s.y=e.y/(n.height/h(i.height,"root.height")*r),s},K=({point:e,rect:n,root:t=l.DEFAULT_SCREEN_TRANSFORM_ROOT,target:i={x:0,y:0}})=>m({x:e.x-n.left,y:e.y-n.top},n,t,i),$=({point:e,rect:n,root:t=l.DEFAULT_SCREEN_TRANSFORM_ROOT,target:i={x:0,y:0}})=>(P(e,n,t,i),i.x+=n.left,i.y+=n.top,i),S=({point:e,root:n=l.DEFAULT_SCREEN_TRANSFORM_ROOT,target:t={x:0,y:0},viewportSize:i})=>m({x:e.x*i.width,y:e.y*i.height},i,n,t),L=({point:e,root:n=l.DEFAULT_SCREEN_TRANSFORM_ROOT,target:t={x:0,y:0},viewportSize:i})=>i.width<=0||i.height<=0?Object.assign(t,{x:0,y:0}):(P(e,i,n,t),t.x/=i.width,t.y/=i.height,t),W=({point:e,root:n=l.DEFAULT_SCREEN_TRANSFORM_ROOT,target:t={x:0,y:0},viewportSize:i})=>S({point:{x:(e.x+1)/2,y:(1-e.y)/2},viewportSize:i,root:n,target:t}),z=({layout:e,mirrored:n=!1,point:t,root:i=l.DEFAULT_SCREEN_TRANSFORM_ROOT,target:s={x:0,y:0}})=>{if(e.scale<=0)return Object.assign(s,{x:0,y:0});const r=e.offsetX+t.x*e.scale;return m({x:n?e.destination.width-r:r,y:e.offsetY+t.y*e.scale},e.destination,i,s)},G=({layout:e,mirrored:n=!1,point:t,root:i=l.DEFAULT_SCREEN_TRANSFORM_ROOT,target:s={x:0,y:0}})=>{if(e.scale<=0)return Object.assign(s,{x:0,y:0});P(t,e.destination,i,s);const r=n?e.destination.width-s.x:s.x;return s.x=(r-e.offsetX)/e.scale,s.y=(s.y-e.offsetY)/e.scale,s},y=new R.Vector3,C=new R.Vector2,A=new R.Raycaster,Q=({camera:e,point:n,root:t=l.DEFAULT_SCREEN_TRANSFORM_ROOT,target:i={x:0,y:0,depth:0},viewportSize:s})=>(h(t.width,"root.width"),h(t.height,"root.height"),y.set(n.x,n.y,n.z).project(e),i.x=y.x*t.width/2,i.y=y.y*t.height/2,i.depth=y.z,i),Z=({camera:e,point:n,root:t=l.DEFAULT_SCREEN_TRANSFORM_ROOT,target:i=new R.Ray,viewportSize:s})=>(h(t.width,"root.width"),h(t.height,"root.height"),C.set(n.x*2/t.width,n.y*2/t.height),A.setFromCamera(C,e),i.copy(A.ray)),v=(e,n)=>F.normalizedTrackerPointToTrackerPoint({x:e.x,y:e.y,z:e.z??0},n),b=(e,n={x:0,y:0})=>{const t=F.trackerPointToNormalizedTrackerPoint(e);return n.x=t.x,n.y=t.y,n.z=t.z,n},ee=(e,n,t={x:0,y:0})=>(t.x=e.x*n.width,t.y=e.y*n.height,t),ne=(e,n,t={x:0,y:0})=>n.width<=0||n.height<=0?Object.assign(t,{x:0,y:0}):(t.x=e.x/n.width,t.y=e.y/n.height,t),te=(e,n,t={})=>S({point:e,viewportSize:n,root:t.root,target:t.target}),ie=(e,n,t={})=>{const i=t.target??{x:0,y:0};return L({point:e,viewportSize:n,root:t.root,target:i}),i},D={selection:"index",index:0},g=Object.freeze({face:{max:10,default:1,option:"numFaces"},hand:{max:2,default:2,option:null},gesture:{max:1,default:1,option:null},body:{max:1,default:1,option:null},holistic:{max:1,default:1,option:null}}),O={center:null},f=(e,n)=>Math.hypot(e.x-n.x,e.y-n.y),M=(e,n,t)=>{if(!e.length)return null;switch(n){case"largest":return e.reduce((i,s)=>s.size>i.size?s:i);case"nearest-center":return e.reduce((i,s)=>f(s.center,{x:.5,y:.5})<f(i.center,{x:.5,y:.5})?s:i);case"leftmost":return e.reduce((i,s)=>s.center.x<i.center.x?s:i);case"rightmost":return e.reduce((i,s)=>s.center.x>i.center.x?s:i);default:return e.find(i=>i.index===t)??null}},X=(e,n=D,t=O)=>{const i=n.index??0;if(n.selection!=="sticky"){const c=M(e,n.selection,i);return{index:(c==null?void 0:c.index)??null,reason:c?n.selection:"none",memory:c?{center:{...c.center},label:c.label}:t}}const s=n.stickyRadius??.2;if(t.center){const c=t.center,d=e.filter(a=>f(a.center,c)<=s).sort((a,E)=>f(a.center,c)-f(E.center,c)),x=(t.label?d.find(a=>a.label===t.label):void 0)??d[0];if(x)return{index:x.index,reason:"sticky",memory:{center:{...x.center},label:x.label}}}const r=M(e,n.fallback??"largest",i);return{index:(r==null?void 0:r.index)??null,reason:r?"sticky-fallback":"none",memory:r?{center:{...r.center},label:r.label}:t}},se=e=>e.map((n,t)=>{let i=1/0,s=-1/0,r=1/0,c=-1/0;for(const o of n)o.x<i&&(i=o.x),o.x>s&&(s=o.x),o.y<r&&(r=o.y),o.y>c&&(c=o.y);const d=n.length>0&&Number.isFinite(i);return{index:t,center:d?{x:(i+s)/2,y:(r+c)/2}:{x:.5,y:.5},size:d?s-i:0}}),re=e=>e.map((n,t)=>{const i=(n.coordinates??[]).map(x=>b(x));let s=1/0,r=-1/0,c=1/0,d=-1/0;for(const x of i)x.x<s&&(s=x.x),x.x>r&&(r=x.x),x.y<c&&(c=x.y),x.y>d&&(d=x.y);const o=i.length>0;return{index:t,center:o?{x:(s+r)/2,y:(c+d)/2}:{x:.5,y:.5},size:o?Math.max(r-s,d-c):0,...n.label?{label:n.label}:{}}}),ce=(e,n,t=.35)=>{const i=[];for(const c of e)for(const d of n){const o=f(c.center,d.center);o<=t&&i.push({primaryIndex:c.index,secondaryIndex:d.index,distance:o})}i.sort((c,d)=>c.distance-d.distance);const s=new Set,r=new Set;return i.filter(c=>s.has(c.primaryIndex)||r.has(c.secondaryIndex)?!1:(s.add(c.primaryIndex),r.add(c.secondaryIndex),!0))},k=({active:e=!0,holdMs:n=250,numFaces:t=1,targetFps:i,throttleMs:s=16}={})=>{const{camera:r}=j.useThree(),c=Number.isFinite(t)?Math.min(g.face.max,Math.max(1,Math.round(t))):1,d=i!==void 0&&Number.isFinite(i)&&i>0?i:void 0,o=T.useMemo(()=>({numFaces:c,...d?{targetFps:d}:{}}),[c,d]),{node:x,ready:a}=q.useXRModel(F.XRModel.FACE_TRACKER,o,e);T.useEffect(()=>{if(x)for(let u=0;u<o.numFaces;u+=1)x.setCamera(r,u)},[o.numFaces,r,x]);const E=T.useCallback(u=>{if(!x)return[];const N=[];for(let _=0;_<u.faceLandmarks.length;_+=1){const U=w.getFaceInfoFromResults(x,u,_);U&&N.push(U)}return N},[x]);return w.useFaceResultReader({enabled:e&&a,holdMs:Number.isFinite(n)?Math.max(0,n):250,node:x,prepare:E,throttleMs:Number.isFinite(s)?Math.max(0,s):16})},Y=4,oe=({faceIndex:e=0,numFaces:n,subject:t,...i}={})=>{const s=Number.isFinite(e)?Math.max(0,Math.round(e)):0,r=k({...i,numFaces:Math.max(n??(t?Y:s+1),s+1)}),c=T.useRef(O),d=JSON.stringify(t??null),o=T.useMemo(()=>{if(!t)return null;const x=r.map((a,E)=>({index:E,center:{x:a.bounds.centerX,y:a.bounds.centerY},size:a.bounds.width}));return X(x,t,c.current)},[r,d]);return T.useEffect(()=>{o&&(c.current=o.memory)},[o]),t?o&&o.index!==null?r[o.index]??null:null:r[s]??null};exports.DEFAULT_POLICY_NUM_FACES=Y;exports.DEFAULT_SUBJECT_POLICY=D;exports.EMPTY_SUBJECT_MEMORY=O;exports.XR_MAX_SUBJECTS=g;exports.associateSubjects=ce;exports.clientToScreenPixels=K;exports.faceCandidates=se;exports.feedToScreenPixels=te;exports.feedToTracker=v;exports.feedToViewport=ee;exports.jointCandidates=re;exports.mediaToScreenPixels=z;exports.normalizedToScreenPixels=S;exports.screenPixelsToClient=$;exports.screenPixelsToFeed=ie;exports.screenPixelsToMedia=G;exports.screenPixelsToNormalized=L;exports.screenPixelsToScreenSpace=p;exports.screenPixelsToUnits=J;exports.screenPointToRay=Z;exports.screenSpaceToScreenPixels=H;exports.screenUnitsToPixels=V;exports.selectSubject=X;exports.trackerPointToScreenPixels=W;exports.trackerToFeed=b;exports.useFaceInfo=oe;exports.useFaceInfos=k;exports.viewportToFeed=ne;exports.worldToScreenPixels=Q;
@@ -0,0 +1 @@
1
+ "use strict";const e=require("react"),C=require("./index-CeVkgsag.cjs"),S=(s={})=>{const{enabled:c=!0,timeoutMs:i,queryPermission:l}=s,f=(s.models??[]).join("|"),a=e.useRef(s.models);a.current=s.models;const[m,b]=e.useState(null),[R,n]=e.useState("idle"),[y,o]=e.useState(null),t=e.useRef(0),u=e.useCallback(async()=>{t.current+=1;const d=t.current;n("checking");try{const r=await C.detectXRCapabilities({models:a.current,timeoutMs:i,queryPermission:l});return d!==t.current?null:(b(r),o(null),n("ready"),r)}catch(r){return d!==t.current||(o(r instanceof Error?r:new Error(String(r))),n("error")),null}},[i,l]);return e.useEffect(()=>{if(c)return u(),()=>{t.current+=1}},[c,u,f]),{capabilities:m,status:R,error:y,refresh:u}};exports.useXRCapabilities=S;
@@ -0,0 +1,30 @@
1
+ import { useRef as m, useState as u, useCallback as E, useEffect as R } from "react";
2
+ import { d as g } from "./index-CnGox6Xr.js";
3
+ const k = (t = {}) => {
4
+ const { enabled: c = !0, timeoutMs: o, queryPermission: l } = t, f = (t.models ?? []).join("|"), i = m(t.models);
5
+ i.current = t.models;
6
+ const [b, p] = u(null), [y, n] = u("idle"), [C, a] = u(null), e = m(0), s = E(async () => {
7
+ e.current += 1;
8
+ const d = e.current;
9
+ n("checking");
10
+ try {
11
+ const r = await g({
12
+ models: i.current,
13
+ timeoutMs: o,
14
+ queryPermission: l
15
+ });
16
+ return d !== e.current ? null : (p(r), a(null), n("ready"), r);
17
+ } catch (r) {
18
+ return d !== e.current || (a(r instanceof Error ? r : new Error(String(r))), n("error")), null;
19
+ }
20
+ }, [o, l]);
21
+ return R(() => {
22
+ if (c)
23
+ return s(), () => {
24
+ e.current += 1;
25
+ };
26
+ }, [c, s, f]), { capabilities: b, status: y, error: C, refresh: s };
27
+ };
28
+ export {
29
+ k as u
30
+ };
@@ -14,11 +14,11 @@ export declare const drawImageDataCover: (canvas: HTMLCanvasElement, input: Imag
14
14
  * trackers call this once per landmark per frame (~468× for face), so the
15
15
  * allocating variant below shows up as a real GC pressure source.
16
16
  */
17
- export declare const unprojectToZZeroInto: ({ x, y, z }: NormalizedLandmark, camera: THREE.Camera, out: THREE.Vector3) => THREE.Vector3;
17
+ export declare const unprojectToZZeroInto: (landmark: NormalizedLandmark, camera: THREE.Camera, out: THREE.Vector3) => THREE.Vector3;
18
18
  /**
19
19
  * Allocating wrapper kept for backwards compatibility with any
20
- * consumer-facing API surface. New call sites in the trackers use
21
- * unprojectToZZeroInto with a pre-allocated out vector.
20
+ * consumer-facing API surface. New call sites use `feedToWorld` from
21
+ * `lib/coordinates` (or `unprojectToZZeroInto` with a pre-allocated out).
22
22
  */
23
23
  export declare const unprojectToZZero: (landmark: NormalizedLandmark, camera: THREE.Camera) => THREE.Vector3;
24
24
  export declare const smoothScale: (originalScale: number, newScale: number, alpha?: number) => number;
@@ -37,7 +37,10 @@ export declare const smoothScale: (originalScale: number, newScale: number, alph
37
37
  export declare class AnalysisDownscaler {
38
38
  private readonly maxDimension;
39
39
  private canvas;
40
+ private scale;
40
41
  constructor(maxDimension: number);
42
+ /** Multiply the cap (0.25..1); the adaptive-quality tier sets it. */
43
+ setScale(scale: number): void;
41
44
  /**
42
45
  * Returns a downscaled copy of `source` capped to `maxDimension` on its
43
46
  * longest side (or `source` unchanged if it's already within the cap, or if a
@@ -14,7 +14,10 @@ export declare const INTEGRITY_MANIFEST: Record<string, IntegrityHash>;
14
14
  * Consumer-owned URLs with no manifest entry pass through with a warning.
15
15
  * SDK-owned CDN URLs with no entry fail closed.
16
16
  */
17
- export declare function fetchAndVerify(url: string): Promise<ArrayBuffer>;
17
+ export declare function fetchAndVerify(url: string, init?: {
18
+ signal?: AbortSignal;
19
+ }): Promise<ArrayBuffer>;
20
+ export declare function isSdkOwnedUrl(url: string): boolean;
18
21
  /**
19
22
  * fetchAndVerify variant that returns a Uint8Array view — what MediaPipe's
20
23
  * `modelAssetBuffer` expects.
@@ -0,0 +1,2 @@
1
+ /** True when a per-frame update should be skipped to honour a `maxFps` cap. */
2
+ export declare const shouldSkipUpdate: (elapsed: number, lastUpdate: number, maxFps: number | undefined) => boolean;
@@ -0,0 +1,18 @@
1
+ export type StableUniforms<T extends Record<string, unknown>> = {
2
+ [K in keyof T]: {
3
+ value: T[K];
4
+ };
5
+ };
6
+ /**
7
+ * Build a `ShaderMaterial` uniforms object whose entries never change identity.
8
+ *
9
+ * three.js captures `material.uniforms` once, when the program is compiled,
10
+ * and keeps reading that object on every draw. A uniforms object re-created
11
+ * on a React render (a plain literal, or a `useMemo` with dependencies) is
12
+ * therefore silently ignored after the first frame unless the material is
13
+ * re-mounted. This hook allocates each `{ value }` entry once and copies the
14
+ * latest values into them on every render, so prop changes reach the shader.
15
+ *
16
+ * The set of keys must be the same on every render.
17
+ */
18
+ export declare const useStableUniforms: <T extends Record<string, unknown>>(values: T) => StableUniforms<T>;
@@ -341,6 +341,7 @@ import { XRScene } from "@vincentt-xr/sdk";
341
341
  - media source selection
342
342
  - cover/contain fitting
343
343
  - mirror state
344
+ - a shared media composition canvas for display, tracker input, and DOM capture
344
345
  - DOM overlay composition
345
346
  - optional scene adapter mounting
346
347
 
@@ -360,6 +361,8 @@ Modes:
360
361
  Media strategies:
361
362
 
362
363
  - `internal` — viewport owns webcam/image/video and tracking preview lifecycle
364
+ - `internal` media reuses its composed canvas for session tracker input and
365
+ `session.captureFrame()` / `session.captureStream()` when no XRScene is mounted
363
366
  - `external` — legacy session/media owner stays in control while viewport provides responsive scene/overlay composition
364
367
 
365
368
  Core props:
@@ -0,0 +1,104 @@
1
+ ---
2
+ title: "Adaptive Quality & Performance Budget"
3
+ description: "An opt-out performance budget that measures frame time, inference time, memory and device signals, then steps tracker fps, analysis resolution, render pixel ratio and camera resolution between declared tiers; bounded, observable, reversible."
4
+ sidebarTitle: "Adaptive Quality"
5
+ icon: "gauge"
6
+ ---
7
+
8
+ Phones differ by an order of magnitude and heat up over a session. Instead
9
+ of hand-tuning `perf.targetFps`, declare quality tiers and a budget; the
10
+ controller moves between the tiers and tells you why.
11
+
12
+ ```tsx
13
+ import { XRProvider, useXRQuality } from "@vincentt-xr/sdk";
14
+
15
+ // On by default. Customise, pin, or turn it off:
16
+ <XRProvider quality={{ budget: { maxFrameMs: 33 }, minTier: "medium" }}>…</XRProvider>;
17
+ <XRProvider quality={{ adaptive: false, initialTier: "medium" }}>…</XRProvider>;
18
+ <XRProvider quality={false}>…</XRProvider>;
19
+
20
+ const { tier, decision, signals, setTier, lock, unlock, reset } = useXRQuality();
21
+ ```
22
+
23
+ ## Tiers and budget (serializable)
24
+
25
+ ```ts
26
+ const DEFAULT_QUALITY_TIERS = [
27
+ { name: "high", targetFps: 30, renderScale: 1, analysisScale: 1, camRes: 960 },
28
+ { name: "medium", targetFps: 24, renderScale: 0.8, analysisScale: 0.85, camRes: 720 },
29
+ { name: "low", targetFps: 15, renderScale: 0.6, analysisScale: 0.7, camRes: 640 },
30
+ ];
31
+ const DEFAULT_PERFORMANCE_BUDGET = {
32
+ maxFrameMs: 1000 / 24,
33
+ maxInferenceMs: 24,
34
+ maxMemoryMb: null,
35
+ sampleMs: 1000,
36
+ downgradeAfter: 2,
37
+ upgradeAfter: 6,
38
+ upgradeHeadroom: 0.75,
39
+ cooldownMs: 4000,
40
+ };
41
+ ```
42
+
43
+ Tiers are ordered best → worst; every knob is optional. `resolveQualityConfig`
44
+ validates a partial config (clamps scales to 0.25..1, drops invalid knobs,
45
+ resolves `initialTier` / `minTier` / `maxTier` by index or name), and the
46
+ result is plain JSON you can persist.
47
+
48
+ ## Knobs and ownership
49
+
50
+ | Knob | Owner | Applied how |
51
+ | --------------- | ------------------------------------------------------------------- | -------------------------------------------------------------- |
52
+ | `targetFps` | session perf config → every tracker without its own `targetFps` | `_setPerf` re-runs the models; immediate |
53
+ | `analysisScale` | session perf config → every model's analysis downscaler | immediate (next inference) |
54
+ | `renderScale` | `<XRScene>` pixel ratio: `min(devicePixelRatio, cap) × renderScale` | immediate; `cap` is the `dpr` ceiling (3 or `canvasProps.dpr`) |
55
+ | `camRes` | session perf config, **only with `rebindCamera: true`** | re-opens the webcam once when the tier changes |
56
+
57
+ A per-tracker `targetFps` prop still beats the tier. The app's own `perf`
58
+ is the base the tiers are merged over, and it is restored when the
59
+ controller unmounts.
60
+
61
+ ## Behaviour
62
+
63
+ - **Sample** every `sampleMs`: mean main-thread frame time (window RAF),
64
+ fps, total tracker inference (`inferenceMsTotal` from diagnostics), feed
65
+ fps, JS heap (`performance.memory` where it exists), `deviceMemory`,
66
+ `hardwareConcurrency`, thermal. Hidden tabs are never judged.
67
+ - **Judge** most severe first: thermal `critical` → memory over
68
+ `maxMemoryMb` → inference over `maxInferenceMs` → frame time over
69
+ `maxFrameMs`.
70
+ - **Step down** after `downgradeAfter` consecutive bad samples, at most once
71
+ per `cooldownMs`, never below `minTier`. At the floor and still over
72
+ budget on frame time, `signals.thermal` becomes `"suspected"` so the app
73
+ can shed content; nothing else changes.
74
+ - **Step up** after `upgradeAfter` consecutive good samples (frame time and
75
+ inference under `budget × upgradeHeadroom`), never above `maxTier`.
76
+ - **Initial tier**: `initialTier` if set, else one step down from the top on
77
+ devices with ≤ 4 GB or ≤ 4 cores.
78
+ - **Manual**: `setTier()` (controller may move again after the cooldown),
79
+ `lock()` / `unlock()`, `reset()`. Every change is a decision with a
80
+ `reason` (`init`, `frame-time`, `inference`, `memory`, `thermal`,
81
+ `recovered`, `manual`, `locked`, `reset`) kept in `history`.
82
+ - **Unsupported signals degrade gracefully**: no `performance.memory` →
83
+ `memoryMb: null` and memory is ignored; no thermal API in browsers →
84
+ `thermal: "unknown"` unless the host passes one to
85
+ `<XRQualityController thermal=…>`.
86
+
87
+ The state is published to the session store (`useXRQualityState()` in
88
+ low-level) and shows in `useXRDiagnostics().quality` and the
89
+ `XRDiagnosticsPanel`. The pure stepping functions (`stepQualityController`,
90
+ `judgeSample`, …) are exported from `/low-level` for tests and custom
91
+ controllers.
92
+
93
+ ## Manual validation
94
+
95
+ Run `/adaptive-quality` (budget tightened: 2 bad samples, 3 s cooldown):
96
+
97
+ | Case | Steps | Expect |
98
+ | ----------- | --------------------------- | ----------------------------------------------------------------- |
99
+ | Baseline | load with a video source | tier `high` (or `medium` on a weak device), `init` |
100
+ | Load | simulated load 60 ms | within ~3 s `medium` (`frame-time`), then `low` |
101
+ | Recover | load 0 | after ~4 good samples back to `medium`, then `high` (`recovered`) |
102
+ | Lock | lock, load 60 | stays put |
103
+ | Manual | pick `low` | tier `low` (`manual`), diagnostics panel shows it |
104
+ | Pixel ratio | pick `low` on a DPR-3 phone | scene renders softer (0.6×) |
@@ -0,0 +1,78 @@
1
+ ---
2
+ title: "Asset Lifecycle & GPU Memory"
3
+ description: "Preload, cache, reference-count, de-duplicate, dispose and budget textures, GLB models and video with the SDK's own three.js loaders; observe usage and eviction."
4
+ sidebarTitle: "Asset Lifecycle"
5
+ icon: "memory"
6
+ ---
7
+
8
+ GPU memory grows when the same texture is loaded twice, when a route change
9
+ leaves a model behind, or when nobody owns disposal. The asset cache gives
10
+ every asset one identity, one load, one owner list and one disposal.
11
+
12
+ ```tsx
13
+ import {
14
+ XRAssetCacheProvider,
15
+ defineGltfAsset,
16
+ defineTextureAsset,
17
+ useXRAsset,
18
+ useXRAssetStats,
19
+ } from "@vincentt-xr/sdk";
20
+
21
+ const HAT = defineGltfAsset("https://cdn.example.com/hat.glb");
22
+ const LOGO = defineTextureAsset("https://cdn.example.com/logo.png");
23
+
24
+ const Hat = () => {
25
+ const { value, status } = useXRAsset(HAT); // shared with every other <Hat>
26
+ return value ? <primitive object={value.scene} /> : null;
27
+ };
28
+
29
+ <XRAssetCacheProvider>
30
+ {" "}
31
+ {/* optional: scopes a cache; releases unreferenced assets on unmount */}
32
+ <Hat />
33
+ <Hat /> {/* second mount: cache hit, same scene object */}
34
+ </XRAssetCacheProvider>;
35
+ ```
36
+
37
+ ## Model
38
+
39
+ - **Definition** `XRAssetDefinition<T> = { key, load(signal), dispose?(value), bytes?(value) }`. `key` is the identity; `defineTextureAsset`, `defineGltfAsset` and `defineVideoAsset` build one over three's loaders (no drei); SDK-CDN URLs go through the verifying fetch (fail closed without a pinned hash), consumer URLs are fetched plainly. Loads honour the abort signal, and a decode or parse that finishes after a release is disposed, not leaked. Write your own for anything else (audio buffers, JSON, fonts).
40
+ - **Acquire / release** `cache.acquire(asset, ownerId)` returns the shared value (in-flight loads are shared too); `cache.release(key, ownerId)` drops that owner. Owners are ids, so a re-render or a StrictMode double mount never double-counts. `useXRAsset` does both for a component.
41
+ - **Unreferenced values stay cached** until the budget needs room, `disposeUnreferenced()` or `disposeAll()`. A value nobody wanted by the time its load finished is disposed at once; releasing during a load aborts it.
42
+ - **Budget** `createAssetCache({ budgetBytes })` (default 256 MiB, `Infinity` disables). Above it, unreferenced values are disposed least-recently-used first; referenced values are never evicted, so `overBudget` can stay true while everything is in use. `setBudget` applies immediately; `evict(bytes)` forces room.
43
+ - **Bytes** come from `bytes(value)`: `estimateTextureBytes` (RGBA × mip chain), `estimateGeometryBytes`, `estimateObjectBytes` (geometries and textures reachable from a scene, each once). They are estimates of resident GPU memory; the browser exposes no exact figure.
44
+ - **Disposal is exactly once**: `dispose(value)` runs once per loaded value, on eviction, `disposeUnreferenced`, `disposeAll` or a too-late load. `disposeObject3D` releases every geometry, material and texture under an object.
45
+ - **Errors** are recorded on the entry (`status: "error"`); the next acquire retries.
46
+
47
+ ## Observability
48
+
49
+ `useXRAssetStats()` (or `cache.getStats()`) reports `assets`,
50
+ `referencedAssets`, `loadingAssets`, `erroredAssets`, `usageBytes`,
51
+ `reclaimableBytes`, `budgetBytes`, `overBudget`, `evictions`, `hits` and
52
+ `misses`; `cache.list()` gives every entry with its status, bytes and owner
53
+ count; `cache.subscribe(listener)` fires on every change.
54
+
55
+ ## Route changes and session shutdown
56
+
57
+ Owners release on unmount, so navigating away drops every reference held by
58
+ the page. `<XRAssetCacheProvider>` then calls `disposeUnreferenced()` as it
59
+ unmounts (`disposeUnreferencedOnUnmount`, default `true`), so a page-scoped
60
+ cache leaves nothing behind; the app-wide default cache (no provider) keeps
61
+ unreferenced values for the next page until the budget says otherwise. For
62
+ a hard shutdown call `cache.disposeAll()`. Tracker-owned resources (the
63
+ MediaPipe models, the camera texture, segmentation masks) are managed by the
64
+ session registry, released once when the provider unmounts; the asset cache
65
+ covers everything the app loads on top.
66
+
67
+ ## Manual validation
68
+
69
+ Run `/asset-lifecycle` (a 24 MB page-scoped cache):
70
+
71
+ | Case | Steps | Expect |
72
+ | ------------ | ----------------------------------- | ------------------------------------------------------------------ |
73
+ | Dedupe | mount texture 1 twice (remount) | `hits` rises, one entry |
74
+ | Release | unmount a texture | entry stays with 0 owners, `reclaimable` grows |
75
+ | Budget | lower the budget slider | unreferenced entries disappear oldest first, `evictions` counts up |
76
+ | Referenced | budget below usage with all mounted | `OVER` shown, nothing evicted |
77
+ | Preload | "preload texture 4" | entry `ready` with 0 owners; mounting it is a hit |
78
+ | Route change | navigate away and back | entries empty on return (provider disposed the unreferenced ones) |