@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,37 @@
1
+ import { ReactNode } from 'react';
2
+ import { SemanticMask } from '../../segmentation2d/types';
3
+ import { SegmentationOverlaySettings } from './settings';
4
+ import * as THREE from "three";
5
+ export type SegmentationOverlayMaterialContext = {
6
+ cameraTexture: THREE.Texture | null;
7
+ /**
8
+ * Class-index texture (red channel, 0..255 → index); nearest-filtered.
9
+ * Re-allocated when the mask changes size; the factory is re-run with the
10
+ * new texture, so read it from the context rather than caching it.
11
+ */
12
+ maskTexture: THREE.Texture;
13
+ /** Feed UV → mask UV, including the row flip, mirror and source cover-fit. */
14
+ maskTransform: THREE.Matrix3;
15
+ /** Class indices the overlay selects, resolved from `label` against the mask; empty until the mask has data. */
16
+ labelIndices: number[];
17
+ mask: SemanticMask | null;
18
+ settings: SegmentationOverlaySettings;
19
+ };
20
+ export type SegmentationOverlayMaterialSpec = ReactNode | THREE.Material | ((context: SegmentationOverlayMaterialContext) => ReactNode | THREE.Material);
21
+ export type SegmentationOverlayProps = Partial<SegmentationOverlaySettings> & {
22
+ /** The mask to draw from: a provider hook's result or your own `SemanticMask`. */
23
+ mask: SemanticMask | null;
24
+ /** Optional image multiplied into the paint, sampled in screen UV (cover of the viewport). */
25
+ texture?: THREE.Texture | string;
26
+ /** Custom material (node, instance, or factory). Replaces the built-in look. */
27
+ material?: SegmentationOverlayMaterialSpec;
28
+ /** Default: just above the video background. */
29
+ renderOrder?: number;
30
+ visible?: boolean;
31
+ };
32
+ /**
33
+ * Draw one or more semantic regions of a mask as a screen-aligned 2D layer,
34
+ * tinted and composited over the camera feed. Covers the viewport exactly
35
+ * like `VideoBackground`, so feed-space masks need no coordinate work.
36
+ */
37
+ export declare const SegmentationOverlay: ({ mask, texture, material, renderOrder, visible, ...settingsInput }: SegmentationOverlayProps) => import("react/jsx-runtime").JSX.Element | null;
@@ -0,0 +1,31 @@
1
+ import { SemanticMask } from '../../segmentation2d/types';
2
+ import { SegmentationOverlaySettings } from './settings';
3
+ import * as THREE from "three";
4
+ /** Up to this many labels can be selected by one overlay. */
5
+ export declare const MAX_OVERLAY_LABELS = 4;
6
+ export type SegmentationOverlayMaterialInputs = {
7
+ cameraTexture: THREE.Texture | null;
8
+ maskTexture: THREE.Texture;
9
+ mask: SemanticMask | null;
10
+ settings: SegmentationOverlaySettings;
11
+ /** Optional image sampled in screen UV and multiplied into the paint. */
12
+ designTexture?: THREE.Texture | null;
13
+ /** Feed (camera texture) size, for cover-fitting source-space masks. */
14
+ feedWidth?: number;
15
+ feedHeight?: number;
16
+ };
17
+ export declare const SEGMENTATION_OVERLAY_VERTEX_SHADER = "\nvarying vec2 vUv;\nvoid main() {\n vUv = uv;\n gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\n}";
18
+ export declare const SEGMENTATION_OVERLAY_FRAGMENT_SHADER = "\nuniform sampler2D cameraTexture;\nuniform sampler2D maskTexture;\nuniform sampler2D designTexture;\nuniform float useDesign;\nuniform vec4 labels;\nuniform float labelCount;\nuniform float invert;\nuniform vec3 tint;\nuniform float opacity;\nuniform float blendMode;\nuniform float feather;\nuniform vec2 maskTexel;\nuniform mat3 maskTransform;\nvarying vec2 vUv;\n\nfloat member(vec2 uv) {\n if (uv.x < 0.0 || uv.x > 1.0 || uv.y < 0.0 || uv.y > 1.0) return 0.0;\n float index = floor(texture2D(maskTexture, uv).r * 255.0 + 0.5);\n float m = 0.0;\n if (labelCount > 0.5 && abs(index - labels.x) < 0.5) m = 1.0;\n if (labelCount > 1.5 && abs(index - labels.y) < 0.5) m = 1.0;\n if (labelCount > 2.5 && abs(index - labels.z) < 0.5) m = 1.0;\n if (labelCount > 3.5 && abs(index - labels.w) < 0.5) m = 1.0;\n return invert > 0.5 ? 1.0 - m : m;\n}\n\nvoid main() {\n vec2 maskUv = (maskTransform * vec3(vUv, 1.0)).xy;\n float coverage;\n if (feather > 0.0) {\n vec2 step = maskTexel * feather;\n coverage = 0.0;\n for (int y = -1; y <= 1; y++) {\n for (int x = -1; x <= 1; x++) {\n coverage += member(maskUv + vec2(float(x), float(y)) * step);\n }\n }\n coverage /= 9.0;\n } else {\n coverage = member(maskUv);\n }\n\n vec3 base = texture2D(cameraTexture, vUv).rgb;\n vec4 design = useDesign > 0.5 ? texture2D(designTexture, vUv) : vec4(1.0);\n vec3 paint = tint * design.rgb;\n vec3 blended = blendMode < 0.5\n ? paint\n : blendMode < 1.5\n ? base * paint\n : blendMode < 2.5\n ? 1.0 - (1.0 - base) * (1.0 - paint)\n : mix(2.0 * base * paint, 1.0 - 2.0 * (1.0 - base) * (1.0 - paint), step(0.5, base));\n\n gl_FragColor = vec4(blended, coverage * opacity * design.a);\n #include <colorspace_fragment>\n}";
19
+ /** The built-in overlay material as a plain three.js object (shareable across meshes). */
20
+ export declare const createSegmentationOverlayMaterial: () => THREE.ShaderMaterial;
21
+ /** Resolve the selected labels to class indices for a mask (unknown labels are skipped). */
22
+ export declare const resolveOverlayLabelIndices: (mask: Pick<SemanticMask, "labels"> | null, label: string | readonly string[]) => number[];
23
+ /**
24
+ * The class indices an overlay should draw right now: the resolved labels,
25
+ * or none while the mask is still at `version` 0 (no data yet). Shared by
26
+ * the built-in material and the custom-material context so both agree.
27
+ */
28
+ export declare const resolveActiveOverlayLabelIndices: (mask: SemanticMask | null, label: string | readonly string[]) => number[];
29
+ export declare const updateSegmentationOverlayMaterial: (material: THREE.ShaderMaterial, { cameraTexture, maskTexture, mask, settings, designTexture, feedWidth, feedHeight, }: SegmentationOverlayMaterialInputs) => THREE.ShaderMaterial;
30
+ /** Own one overlay material and keep it in sync with the inputs on every render. */
31
+ export declare const useSegmentationOverlayMaterial: (inputs: SegmentationOverlayMaterialInputs) => THREE.ShaderMaterial;
@@ -0,0 +1,9 @@
1
+ export { SegmentationOverlay } from './SegmentationOverlay';
2
+ export type { SegmentationOverlayMaterialContext, SegmentationOverlayMaterialSpec, SegmentationOverlayProps, } from './SegmentationOverlay';
3
+ export { MAX_OVERLAY_LABELS, SEGMENTATION_OVERLAY_FRAGMENT_SHADER, SEGMENTATION_OVERLAY_VERTEX_SHADER, createSegmentationOverlayMaterial, resolveActiveOverlayLabelIndices, resolveOverlayLabelIndices, updateSegmentationOverlayMaterial, useSegmentationOverlayMaterial, } from './SegmentationOverlayMaterial';
4
+ export type { SegmentationOverlayMaterialInputs } from './SegmentationOverlayMaterial';
5
+ export { createSemanticMaskTexture, uploadSemanticMask, useSemanticMaskTexture, } from './maskTexture';
6
+ export { PERSON_MASK_LABELS, resolveMaskSize, useFaceRegionMask, useHairMask, usePersonMask, useSemanticSegmentationMask, } from './providers';
7
+ export type { SemanticSegmentationMaskResult, UseFaceRegionMaskOptions, UsePersonMaskOptions, UseSemanticSegmentationMaskOptions, } from './providers';
8
+ export { DEFAULT_SEGMENTATION_OVERLAY_SETTINGS, SEGMENTATION_OVERLAY_BLEND_MODES, SEGMENTATION_OVERLAY_SETTINGS_FIELDS, parseOverlayLabels, patchSegmentationOverlaySettings, resolveSegmentationOverlaySettings, } from './settings';
9
+ export type { SegmentationOverlayBlendMode, SegmentationOverlaySettings } from './settings';
@@ -0,0 +1,23 @@
1
+ import { SemanticMask } from '../../segmentation2d/types';
2
+ import * as THREE from "three";
3
+ /** One red byte per pixel holding the class index; nearest filtering keeps classes crisp. */
4
+ export declare const createSemanticMaskTexture: (width?: number, height?: number) => THREE.DataTexture;
5
+ /**
6
+ * Copy a mask into the texture, re-allocating when its size changed. Returns
7
+ * the texture to use (a new one when re-allocated; dispose the old one).
8
+ */
9
+ export declare const uploadSemanticMask: (texture: THREE.DataTexture, mask: SemanticMask) => THREE.DataTexture;
10
+ type Uploaded = {
11
+ texture: THREE.DataTexture;
12
+ version: number;
13
+ mask: SemanticMask | null;
14
+ };
15
+ /**
16
+ * Keep a GPU copy of a mask in sync with its `version`. The returned holder
17
+ * is stable; call `sync()` once per frame (or render) before drawing.
18
+ */
19
+ export declare const useSemanticMaskTexture: (mask: SemanticMask | null) => {
20
+ holder: Uploaded;
21
+ sync: () => THREE.DataTexture;
22
+ };
23
+ export {};
@@ -0,0 +1,72 @@
1
+ import { FaceRegionLabel } from '../../segmentation2d/faceRegions';
2
+ import { SemanticMask } from '../../segmentation2d/types';
3
+ import { SemanticSegmentationModelOptions, SemanticSegmentationStatus } from '../../types/segmentation';
4
+ /** Mask size for a long edge, keeping the feed's aspect ratio. */
5
+ export declare const resolveMaskSize: (feed: {
6
+ width: number;
7
+ height: number;
8
+ }, longEdge: number) => {
9
+ width: number;
10
+ height: number;
11
+ };
12
+ export type UseFaceRegionMaskOptions = {
13
+ /** Which face, or `"all"` to stack every tracked face into one mask. Default `"all"`. */
14
+ faceIndex?: number | "all";
15
+ /** Only rasterize these regions. Default: all of `FACE_REGION_LABELS`. */
16
+ regions?: readonly FaceRegionLabel[];
17
+ /** Mask long edge in pixels. Default 256. */
18
+ resolution?: number;
19
+ /** Cap how often the mask is re-rasterized. Omit for every frame. */
20
+ maxUpdateFps?: number;
21
+ /**
22
+ * Keep a face's last mask for this long (ms) when the tracker drops it,
23
+ * bridging the brief dropouts small or fast faces cause. Default 250,
24
+ * matching `useFaceInfos`. 0 clears the mask on the first missing frame.
25
+ */
26
+ holdMs?: number;
27
+ /**
28
+ * While a face is held, move it along its last velocity for up to this
29
+ * long (ms) so the mask keeps up with a moving subject. Default 0.
30
+ */
31
+ predictMs?: number;
32
+ };
33
+ /**
34
+ * A semantic mask of `face_skin`, `brows`, `eyes`, `lips` and `mouth`
35
+ * rasterized from the face tracker's landmarks every frame. The returned
36
+ * object is stable and mutated in place; its `version` changes on updates.
37
+ * Requires a face tracker in the session.
38
+ */
39
+ export declare const useFaceRegionMask: ({ faceIndex, regions, resolution, maxUpdateFps, holdMs, predictMs, }?: UseFaceRegionMaskOptions) => SemanticMask;
40
+ export declare const PERSON_MASK_LABELS: readonly ["bg", "person"];
41
+ export type UsePersonMaskOptions = {
42
+ /** Cap how often the mask is read back from the GPU. Default 15. */
43
+ maxUpdateFps?: number;
44
+ /** Keep the segmentation model running. Default true. */
45
+ active?: boolean;
46
+ };
47
+ /**
48
+ * The SDK's portrait segmentation as a semantic mask (`bg` / `person`) in
49
+ * feed space. Acquires the segmentation model itself. Each update is a
50
+ * GPU→CPU readback, so it is rate-limited by default.
51
+ */
52
+ export declare const usePersonMask: ({ maxUpdateFps, active, }?: UsePersonMaskOptions) => SemanticMask;
53
+ export type UseSemanticSegmentationMaskOptions = SemanticSegmentationModelOptions & {
54
+ /** Keep the model running. Default true. */
55
+ active?: boolean;
56
+ };
57
+ export type SemanticSegmentationMaskResult = {
58
+ /** Stable mask in feed space; `version` stays 0 until the first inference. */
59
+ mask: SemanticMask;
60
+ status: SemanticSegmentationStatus;
61
+ error: Error | null;
62
+ labels: readonly string[];
63
+ };
64
+ /**
65
+ * A category-segmentation mask from `XRModel.SEMANTIC_SEGMENTATION` (hair or
66
+ * multiclass). Acquires the model itself; the first acquirer in a session
67
+ * picks the preset and model URL. The mask is produced on the model's own
68
+ * loop at its `targetFps` (15 by default), so no extra throttle is needed.
69
+ */
70
+ export declare const useSemanticSegmentationMask: ({ active, ...modelOptions }?: UseSemanticSegmentationMaskOptions) => SemanticSegmentationMaskResult;
71
+ /** MediaPipe Hair Segmenter as a `bg` / `hair` mask in feed space. */
72
+ export declare const useHairMask: (options?: Omit<UseSemanticSegmentationMaskOptions, "preset">) => SemanticSegmentationMaskResult;
@@ -0,0 +1,65 @@
1
+ export declare const SEGMENTATION_OVERLAY_BLEND_MODES: readonly ["normal", "multiply", "screen", "overlay"];
2
+ export type SegmentationOverlayBlendMode = (typeof SEGMENTATION_OVERLAY_BLEND_MODES)[number];
3
+ /** Serializable look of a `SegmentationOverlay`. */
4
+ export type SegmentationOverlaySettings = {
5
+ /** Region label to show (comma-separate several, e.g. `"lips,mouth"`). */
6
+ label: string;
7
+ /** Show everything except the selected labels. */
8
+ invert: boolean;
9
+ color: string;
10
+ opacity: number;
11
+ /** How the paint combines with the camera pixels underneath. */
12
+ blendMode: SegmentationOverlayBlendMode;
13
+ /** Edge feather radius in mask texels (0 = hard class edges). */
14
+ feather: number;
15
+ /** Flip the mask horizontally (source-space masks on a mirrored feed). */
16
+ mirrored: boolean;
17
+ };
18
+ export declare const DEFAULT_SEGMENTATION_OVERLAY_SETTINGS: SegmentationOverlaySettings;
19
+ export declare const resolveSegmentationOverlaySettings: (input?: Partial<SegmentationOverlaySettings>) => SegmentationOverlaySettings;
20
+ export declare const patchSegmentationOverlaySettings: (current: SegmentationOverlaySettings, patch: Partial<SegmentationOverlaySettings>) => SegmentationOverlaySettings;
21
+ /** Split a `label` setting into the individual labels it names. */
22
+ export declare const parseOverlayLabels: (label: string | readonly string[]) => string[];
23
+ export declare const SEGMENTATION_OVERLAY_SETTINGS_FIELDS: [{
24
+ readonly key: "label";
25
+ readonly label: "Region";
26
+ readonly type: "select";
27
+ readonly options: {
28
+ label: "bg" | "brows" | "eyes" | "face_skin" | "hair" | "lips" | "mouth" | "person";
29
+ value: "bg" | "brows" | "eyes" | "face_skin" | "hair" | "lips" | "mouth" | "person";
30
+ }[];
31
+ }, {
32
+ readonly key: "invert";
33
+ readonly label: "Invert selection";
34
+ readonly type: "boolean";
35
+ }, {
36
+ readonly key: "color";
37
+ readonly label: "Color";
38
+ readonly type: "color";
39
+ }, {
40
+ readonly key: "opacity";
41
+ readonly label: "Opacity";
42
+ readonly type: "number";
43
+ readonly min: 0;
44
+ readonly max: 1;
45
+ readonly step: 0.01;
46
+ }, {
47
+ readonly key: "blendMode";
48
+ readonly label: "Blend";
49
+ readonly type: "select";
50
+ readonly options: {
51
+ label: "multiply" | "overlay" | "screen" | "normal";
52
+ value: "multiply" | "overlay" | "screen" | "normal";
53
+ }[];
54
+ }, {
55
+ readonly key: "feather";
56
+ readonly label: "Feather (texels)";
57
+ readonly type: "number";
58
+ readonly min: 0;
59
+ readonly max: 8;
60
+ readonly step: 0.5;
61
+ }, {
62
+ readonly key: "mirrored";
63
+ readonly label: "Mirror mask";
64
+ readonly type: "boolean";
65
+ }];
@@ -1,11 +1,12 @@
1
1
  import { RefObject } from 'react';
2
2
  import { XRLayerConfig, XRMediaLayout, XRMediaSourceKind } from '../../types/compositor';
3
- export declare const XRMediaSurface: ({ canvasRef, imageRef, layer, layout, mirrored, sourceKind, videoRef, }: {
3
+ export declare const XRMediaSurface: ({ canvasRef, imageRef, layer, layout, mirrored, onCaptureTarget, sourceKind, videoRef, }: {
4
4
  canvasRef: RefObject<HTMLCanvasElement | null>;
5
5
  imageRef: RefObject<HTMLImageElement | null>;
6
6
  layer: XRLayerConfig;
7
7
  layout: XRMediaLayout | null;
8
8
  mirrored: boolean;
9
+ onCaptureTarget?: (canvas: HTMLCanvasElement | undefined) => void;
9
10
  sourceKind: XRMediaSourceKind;
10
11
  videoRef: RefObject<HTMLVideoElement | null>;
11
12
  }) => import("react/jsx-runtime").JSX.Element;
@@ -1,13 +1,27 @@
1
1
  import { PropsWithChildren } from 'react';
2
2
  import { SessionFacade } from '../../hooks/useXRSession';
3
- import { XRPerfConfig } from '../../types';
3
+ import { XRLifecycleConfig, XRPerfConfig } from '../../types';
4
+ import { XRQualityConfigInput } from '../../quality/types';
4
5
  export type XRContextType = {
5
6
  session: SessionFacade;
6
7
  };
7
8
  export declare const useXRContext: () => XRContextType;
9
+ /** The session facade when inside an `<XRProvider>`, else `null` (for components that work with or without a session). */
10
+ export declare const useOptionalXRContext: () => XRContextType | null;
8
11
  export type XRProviderProps = PropsWithChildren<{
9
12
  /** Performance config: cap ML inference fps and camera resolution to reduce
10
13
  * GPU/CPU load and heat. See {@link XRPerfConfig}. */
11
14
  perf?: XRPerfConfig;
15
+ /** Lifecycle behaviour (pause while hidden). See {@link XRLifecycleConfig}. */
16
+ lifecycle?: XRLifecycleConfig;
17
+ /**
18
+ * Adaptive quality. ON by default with `DEFAULT_QUALITY_TIERS` and
19
+ * `DEFAULT_PERFORMANCE_BUDGET`: tracker fps, analysis resolution and the
20
+ * render pixel ratio step down under load and back up when it clears.
21
+ * Pass a partial config ({@link XRQualityConfigInput}) to customise (tiers, budget,
22
+ * bounds, `adaptive: false` to pin), or `false` to mount no controller
23
+ * (mount `<XRQualityController>` yourself, or manage `perf` by hand).
24
+ */
25
+ quality?: XRQualityConfigInput | false;
12
26
  }>;
13
- export declare const XRProvider: ({ children, perf }: XRProviderProps) => import("react/jsx-runtime").JSX.Element;
27
+ export declare const XRProvider: ({ children, perf, lifecycle, quality }: XRProviderProps) => import("react/jsx-runtime").JSX.Element;
@@ -9,5 +9,5 @@ export declare const useViewportExternalFaces: ({ enabled, selectedSource, }: {
9
9
  selectedSource: CalibrationMediaSourceKind;
10
10
  }) => {
11
11
  faces: import('../../../types').FaceTrackingResult[];
12
- trackerStatus: "idle" | "ready";
12
+ trackerStatus: "ready" | "idle";
13
13
  };
@@ -11,6 +11,6 @@ export declare const useViewportMediaSource: ({ enabled, imageAsset, selectedSou
11
11
  imageRef: import('react').RefObject<HTMLImageElement>;
12
12
  stream: MediaStream | null;
13
13
  mediaSize: XRViewportSize;
14
- status: "idle" | "ready" | "error" | "requesting";
14
+ status: "ready" | "error" | "requesting" | "idle";
15
15
  error: string | null;
16
16
  };
@@ -24,7 +24,7 @@ export declare const useViewportPipeline: ({ fitMode, imageOptions, initialImage
24
24
  imageRef: import('react').RefObject<HTMLImageElement>;
25
25
  stream: MediaStream | null;
26
26
  mediaSize: import('..').XRViewportSize;
27
- status: "idle" | "ready" | "error" | "requesting";
27
+ status: "ready" | "error" | "requesting" | "idle";
28
28
  error: string | null;
29
29
  };
30
30
  renderOutputState: import('..').XRViewportRenderOutputs;
@@ -6,8 +6,11 @@ export * from './FaceMesh';
6
6
  export * from './FaceRetouch';
7
7
  export * from './FaceWarp3D';
8
8
  export * from './GestureTracker';
9
+ export * from './GestureListener';
9
10
  export * from './GestureTrigger';
10
11
  export * from './HandTracker';
12
+ export * from './IrisEffect';
13
+ export * from './HolisticTracker';
11
14
  export * from './HandTracking3D';
12
15
  export * from './HandTracking2DController';
13
16
  export * from './HandTracking2D';
@@ -8,7 +8,10 @@ export declare enum XRModel {
8
8
  GESTURE_TRACKER = "vincentt.xr.gesture-tracker",
9
9
  FACE_TRACKER = "vincentt.xr.face-tracker",
10
10
  BODY_TRACKER = "vincentt.xr.body-tracker",
11
- BACKGROUND_SEGMENTATION = "vincentt.xr.background-segmentation"
11
+ /** One MediaPipe Holistic inference for face + both hands + pose (single person). */
12
+ HOLISTIC_TRACKER = "vincentt.xr.holistic-tracker",
13
+ BACKGROUND_SEGMENTATION = "vincentt.xr.background-segmentation",
14
+ SEMANTIC_SEGMENTATION = "vincentt.xr.semantic-segmentation"
12
15
  }
13
16
  export declare enum XRComponentEnum {
14
17
  CAMERA = "vincentt.component.camera",
@@ -0,0 +1 @@
1
+ "use strict";var Re=Object.defineProperty;var Ee=(e,t,n)=>t in e?Re(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n;var Q=(e,t,n)=>Ee(e,typeof t!="symbol"?t+"":t,n);const L=require("react/jsx-runtime"),J=require("@react-three/fiber"),A=require("react"),Te=require("three"),O=require("./selectors-Du_PsVnW.cjs"),fe=require("./index-CeVkgsag.cjs"),se=require("./index-DKBAh6hV.cjs");function Me(e){const t=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(e){for(const n in e)if(n!=="default"){const a=Object.getOwnPropertyDescriptor(e,n);Object.defineProperty(t,n,a.get?a:{enumerable:!0,get:()=>e[n]})}}return t.default=e,Object.freeze(t)}const j=Me(Te),ue={display:"flex",alignItems:"center",justifyContent:"center",height:"100%",background:"#363636",color:"white",fontFamily:"monospace"},Ae=()=>L.jsx("div",{style:ue,children:"Loading..."}),Ce=e=>L.jsx("div",{style:ue,children:e.error}),Fe=e=>typeof e=="number"?e:Array.isArray(e)?e[1]:3,le={position:"absolute",top:0,left:0,width:"100%",height:"100%",zIndex:10},ce={sceneColorTexture:null,sceneDepthTexture:null},ke=({cap:e})=>{const t=J.useThree(o=>o.setDpr),n=O.useXRQualityState(),r=O.useXRQualityConfig()?(n==null?void 0:n.decision.tier.renderScale)??1:1;return A.useEffect(()=>{const o=Math.min(typeof window<"u"&&window.devicePixelRatio||1,e);t(Math.max(.5,o*r))},[t,e,r]),null},Ie=({onRenderOutputs:e,renderOutputs:t,size:n})=>{const{gl:a,scene:r,size:o}=J.useThree(),{session:c}=fe.useXRContext(),s=Math.max(1,Math.round((n==null?void 0:n.width)??o.width)),d=Math.max(1,Math.round((n==null?void 0:n.height)??o.height)),f=!!(t.sceneColor||t.sceneDepth),l=A.useMemo(()=>{if(!f)return null;const i=new j.WebGLRenderTarget(s,d,{colorSpace:j.SRGBColorSpace,depthBuffer:!0,stencilBuffer:!1});return t.sceneDepth&&(i.depthTexture=new j.DepthTexture(s,d),i.depthTexture.format=j.DepthFormat,i.depthTexture.type=j.UnsignedShortType),i},[f,d,t.sceneDepth,s]);return A.useEffect(()=>{if(!l){e==null||e(ce);return}return e==null||e({sceneColorTexture:t.sceneColor?l.texture:null,sceneDepthTexture:t.sceneDepth&&l.depthTexture?l.depthTexture:null}),()=>{var i;l.dispose(),(i=l.depthTexture)==null||i.dispose(),e==null||e(ce)}},[e,t.sceneColor,t.sceneDepth,l]),J.useFrame(()=>{if(!l)return;const i=[];t.excludeScreenUI!==!1&&r.traverse(x=>{x.visible&&x.renderOrder>=O.RENDER_LAYERS.SCREEN_UI&&(i.push(x),x.visible=!1)});const p=a.getRenderTarget(),v=a.xr.enabled;a.xr.enabled=!1,a.setRenderTarget(l),a.clear(),c._renderFrame(),a.setRenderTarget(p),a.xr.enabled=v,i.forEach(x=>{x.visible=!0})},-100),null},Le=({style:e,canvasProps:t,children:n,loadingComponent:a,loadingTransitionDuration:r,errorComponent:o,renderTargetSize:c,renderOutputs:s={},onRenderOutputs:d})=>{const f=A.useRef(null),l=A.useRef(null),i=A.useRef(null),p=A.useRef(!1),{session:v}=fe.useXRContext(),x=O.useXRReady(),u=O.useXRError(),[h,g]=A.useState(!0);return A.useEffect(()=>{if(c){v._setRenderSize(Math.round(c.width),Math.round(c.height));return}const y=(w,E)=>{w<=0||E<=0||v._setRenderSize(Math.round(w),Math.round(E))},m=()=>{!l.current||p.current||(p.current=!0,v._setRenderTarget(l.current))},C=(w,E)=>{i.current!==null&&cancelAnimationFrame(i.current),i.current=requestAnimationFrame(()=>{i.current=null,y(w,E)})},S=new ResizeObserver(w=>{const E=w[0];if(!E)return;const{width:B,height:I}=E.contentRect;m(),C(B,I)});return f.current&&S.observe(f.current),m(),()=>{S.disconnect(),i.current!==null&&(cancelAnimationFrame(i.current),i.current=null),p.current=!1}},[c,v]),A.useEffect(()=>{x&&(r?setTimeout(()=>{g(!1)},r):g(!1))},[x,r]),L.jsxs("div",{id:"vincentt-xr-container",ref:f,style:{width:"100%",height:"100%",...e,position:"relative"},children:[h&&L.jsx("div",{style:le,children:a||L.jsx(Ae,{})}),u&&L.jsx("div",{style:le,children:o||L.jsx(Ce,{error:u.message})}),L.jsxs(J.Canvas,{id:"vincentt-xr-canvas",ref:l,dpr:[1,3],gl:{alpha:!0,preserveDrawingBuffer:!1,antialias:!0,stencil:!0,premultipliedAlpha:!1,toneMapping:j.NoToneMapping},...t,onCreated:y=>{c?v._setRenderSize(Math.round(c.width),Math.round(c.height)):v._setRenderTarget(l.current),v._setR3FState({renderer:y.gl,scene:y.scene,camera:y.camera}),y.gl.outputColorSpace=j.SRGBColorSpace,t!=null&&t.onCreated&&t.onCreated(y)},children:[L.jsx(Ie,{onRenderOutputs:d,renderOutputs:s,size:c}),L.jsx(ke,{cap:Fe(t==null?void 0:t.dpr)}),n]})]})},xe=(e,t,n,a,r)=>{const o=e/2,c=t/2,s=n.left*o+a.left,d=n.right*o-a.right,f=n.bottom*c+a.bottom,l=n.top*c-a.top,i=d-s,p=l-f,v=(s+d)/2,x=(f+l)/2,u=r[0]*i/2,h=r[1]*p/2;return{centerX:v,centerY:x,width:i,height:p,pivotX:u,pivotY:h}},Xe={left:0,right:0,top:0,bottom:0},Be={left:0,right:0,top:0,bottom:0},Ge=[0,0],De=({anchors:e,offsets:t,pivot:n=Ge,children:a})=>{const{width:r,height:o}=se.useScreenSpace(),c=A.useMemo(()=>({anchors:{...Xe,...e??{}},offsets:{...Be,...t??{}}}),[e,t]),s=A.useMemo(()=>xe(r,o,c.anchors,c.offsets,n),[r,o,c,n]);A.useEffect(()=>{const i=c.anchors;i.left>i.right&&console.warn(`[ScreenTransform] inverted X axis: anchors.left (${i.left}) > anchors.right (${i.right})`),i.bottom>i.top&&console.warn(`[ScreenTransform] inverted Y axis: anchors.bottom (${i.bottom}) > anchors.top (${i.top})`),s.width<=0&&console.warn(`[ScreenTransform] zero or negative width (${s.width.toFixed(3)}) — anchors + offsets collapse the X extent`),s.height<=0&&console.warn(`[ScreenTransform] zero or negative height (${s.height.toFixed(3)}) — anchors + offsets collapse the Y extent`)},[c,s.width,s.height]);const d=n[0]!==0||n[1]!==0,f=d?[1,1,1]:[s.width,s.height,1],l=!d&&s.width>0&&s.height>0?s.width/s.height:null;return L.jsx("group",{position:[s.centerX-s.pivotX,s.centerY-s.pivotY,0],scale:f,renderOrder:O.RENDER_LAYERS.SCREEN_UI,children:L.jsx(se.ScreenRectAspectContext.Provider,{value:l,children:a})})};class ve{constructor(t,n){Q(this,"capabilities");Q(this,"snapshot");Q(this,"listeners",new Set);Q(this,"eventListeners",new Map);this.capabilities=t,this.snapshot={state:"idle",frame:0,time:0,playMode:"forward",loop:!0,loopCount:0,...n}}play(){const t=this.snapshot.state==="paused";this.update({state:"playing"}),this.emit(t?"Resume":"PlayBegin")}pause(){this.update({state:"paused"}),this.emit("Pause")}restart(){this.update({state:"playing",frame:0,time:0}),this.emit("PlayBegin")}setPlayMode(t){!this.capabilities.canReverse&&(t==="reverse"||t==="ping-pong"||t==="random")||this.update({playMode:t})}setLoop(t,n=0){this.update({loop:t,loopCount:n})}seek(t){this.capabilities.canSeek&&this.update({frame:Math.max(0,Math.floor(t)),time:Math.max(0,t)})}subscribe(t){return this.listeners.add(t),()=>this.listeners.delete(t)}on(t,n){const a=this.eventListeners.get(t)??new Set;return a.add(n),this.eventListeners.set(t,a),()=>this.off(t,n)}off(t,n){var a;(a=this.eventListeners.get(t))==null||a.delete(n)}getSnapshot(){return this.snapshot}dispose(){this.listeners.clear(),this.eventListeners.clear(),this.snapshot={...this.snapshot,state:"idle"}}updateSnapshot(t){this.update(t)}emit(t){var n;(n=this.eventListeners.get(t))==null||n.forEach(a=>a({type:t,snapshot:this.snapshot}))}update(t){this.snapshot={...this.snapshot,...t},this.listeners.forEach(n=>n(this.snapshot))}}const pe=(e,t,n,a,r)=>{const o=Math.max(1,Math.floor(t)),c=Math.max(0,Math.floor(e)),s=n==="ping-pong"&&o>1?o*2-2:o,d=Math.floor(c/s),f=r>0?d>=r:!a&&c>=s,l=f?s-1:c%s;return{frame:n==="reverse"?o-1-l%o:n==="random"?l*7919%o:n==="ping-pong"&&l>=o?s-l:l,ended:f,loop:d}},je=(e,t,n)=>{const a=Math.max(1,Math.floor(n));return Math.floor(Math.max(0,e)*Math.max(0,t))%a};var he={},ge,Ue;function $e(e,t,n,o){var r=0,o=o===void 0?{}:o,c=o.loop===void 0?null:o.loop,s=o.palette===void 0?null:o.palette;if(t<=0||n<=0||t>65535||n>65535)throw new Error("Width/Height invalid.");function d(h){var g=h.length;if(g<2||g>256||g&g-1)throw new Error("Invalid code/color length, must be power of 2 and 2 .. 256.");return g}e[r++]=71,e[r++]=73,e[r++]=70,e[r++]=56,e[r++]=57,e[r++]=97;var f=0,l=0;if(s!==null){for(var i=d(s);i>>=1;)++f;if(i=1<<f,--f,o.background!==void 0){if(l=o.background,l>=i)throw new Error("Background index out of range.");if(l===0)throw new Error("Background index explicitly passed as 0.")}}if(e[r++]=t&255,e[r++]=t>>8&255,e[r++]=n&255,e[r++]=n>>8&255,e[r++]=(s!==null?128:0)|f,e[r++]=l,e[r++]=0,s!==null)for(var p=0,v=s.length;p<v;++p){var x=s[p];e[r++]=x>>16&255,e[r++]=x>>8&255,e[r++]=x&255}if(c!==null){if(c<0||c>65535)throw new Error("Loop count invalid.");e[r++]=33,e[r++]=255,e[r++]=11,e[r++]=78,e[r++]=69,e[r++]=84,e[r++]=83,e[r++]=67,e[r++]=65,e[r++]=80,e[r++]=69,e[r++]=50,e[r++]=46,e[r++]=48,e[r++]=3,e[r++]=1,e[r++]=c&255,e[r++]=c>>8&255,e[r++]=0}var u=!1;this.addFrame=function(h,g,y,m,C,S){if(u===!0&&(--r,u=!1),S=S===void 0?{}:S,h<0||g<0||h>65535||g>65535)throw new Error("x/y invalid.");if(y<=0||m<=0||y>65535||m>65535)throw new Error("Width/Height invalid.");if(C.length<y*m)throw new Error("Not enough pixels for the frame size.");var w=!0,E=S.palette;if(E==null&&(w=!1,E=s),E==null)throw new Error("Must supply either a local or global palette.");for(var B=d(E),I=0;B>>=1;)++I;B=1<<I;var U=S.delay===void 0?0:S.delay,R=S.disposal===void 0?0:S.disposal;if(R<0||R>3)throw new Error("Disposal out of range.");var T=!1,k=0;if(S.transparent!==void 0&&S.transparent!==null&&(T=!0,k=S.transparent,k<0||k>=B))throw new Error("Transparent color index.");if((R!==0||T||U!==0)&&(e[r++]=33,e[r++]=249,e[r++]=4,e[r++]=R<<2|(T===!0?1:0),e[r++]=U&255,e[r++]=U>>8&255,e[r++]=k,e[r++]=0),e[r++]=44,e[r++]=h&255,e[r++]=h>>8&255,e[r++]=g&255,e[r++]=g>>8&255,e[r++]=y&255,e[r++]=y>>8&255,e[r++]=m&255,e[r++]=m>>8&255,e[r++]=w===!0?128|I-1:0,w===!0)for(var $=0,X=E.length;$<X;++$){var F=E[$];e[r++]=F>>16&255,e[r++]=F>>8&255,e[r++]=F&255}return r=qe(e,r,I<2?2:I,C),r},this.end=function(){return u===!1&&(e[r++]=59,u=!0),r},this.getOutputBuffer=function(){return e},this.setOutputBuffer=function(h){e=h},this.getOutputBufferPosition=function(){return r},this.setOutputBufferPosition=function(h){r=h}}function qe(e,t,n,a){e[t++]=n;var r=t++,o=1<<n,c=o-1,s=o+1,d=s+1,f=n+1,l=0,i=0;function p(S){for(;l>=S;)e[t++]=i&255,i>>=8,l-=8,t===r+256&&(e[r]=255,r=t++)}function v(S){i|=S<<l,l+=f,p(8)}var x=a[0]&c,u={};v(o);for(var h=1,g=a.length;h<g;++h){var y=a[h]&c,m=x<<8|y,C=u[m];if(C===void 0){for(i|=x<<l,l+=f;l>=8;)e[t++]=i&255,i>>=8,l-=8,t===r+256&&(e[r]=255,r=t++);d===4096?(v(o),d=s+1,f=n+1,u={}):(d>=1<<f&&++f,u[m]=d++),x=y}else x=C}return v(x),v(s),p(1),r+1===t?e[r]=0:(e[r]=t-r-1,e[t++]=0),t}function We(e){var t=0;if(e[t++]!==71||e[t++]!==73||e[t++]!==70||e[t++]!==56||(e[t++]+1&253)!==56||e[t++]!==97)throw new Error("Invalid GIF 87a/89a header.");var n=e[t++]|e[t++]<<8,a=e[t++]|e[t++]<<8,r=e[t++],o=r>>7,c=r&7,s=1<<c+1;e[t++],e[t++];var d=null,f=null;o&&(d=t,f=s,t+=s*3);var l=!0,i=[],p=0,v=null,x=0,u=null;for(this.width=n,this.height=a;l&&t<e.length;)switch(e[t++]){case 33:switch(e[t++]){case 255:if(e[t]!==11||e[t+1]==78&&e[t+2]==69&&e[t+3]==84&&e[t+4]==83&&e[t+5]==67&&e[t+6]==65&&e[t+7]==80&&e[t+8]==69&&e[t+9]==50&&e[t+10]==46&&e[t+11]==48&&e[t+12]==3&&e[t+13]==1&&e[t+16]==0)t+=14,u=e[t++]|e[t++]<<8,t++;else for(t+=12;;){var h=e[t++];if(!(h>=0))throw Error("Invalid block size");if(h===0)break;t+=h}break;case 249:if(e[t++]!==4||e[t+4]!==0)throw new Error("Invalid graphics extension block.");var g=e[t++];p=e[t++]|e[t++]<<8,v=e[t++],g&1||(v=null),x=g>>2&7,t++;break;case 254:for(;;){var h=e[t++];if(!(h>=0))throw Error("Invalid block size");if(h===0)break;t+=h}break;default:throw new Error("Unknown graphic control label: 0x"+e[t-1].toString(16))}break;case 44:var y=e[t++]|e[t++]<<8,m=e[t++]|e[t++]<<8,C=e[t++]|e[t++]<<8,S=e[t++]|e[t++]<<8,w=e[t++],E=w>>7,B=w>>6&1,I=w&7,U=1<<I+1,R=d,T=f,k=!1;if(E){var k=!0;R=t,T=U,t+=U*3}var $=t;for(t++;;){var h=e[t++];if(!(h>=0))throw Error("Invalid block size");if(h===0)break;t+=h}i.push({x:y,y:m,width:C,height:S,has_local_palette:k,palette_offset:R,palette_size:T,data_offset:$,data_length:t-$,transparent_index:v,interlaced:!!B,delay:p,disposal:x});break;case 59:l=!1;break;default:throw new Error("Unknown gif block: 0x"+e[t-1].toString(16))}this.numFrames=function(){return i.length},this.loopCount=function(){return u},this.frameInfo=function(X){if(X<0||X>=i.length)throw new Error("Frame index out of range.");return i[X]},this.decodeAndBlitFrameBGRA=function(X,F){var _=this.frameInfo(X),Z=_.width*_.height,q=new Uint8Array(Z);de(e,_.data_offset,q,Z);var W=_.palette_offset,P=_.transparent_index;P===null&&(P=256);var G=_.width,N=n-G,Y=G,K=(_.y*n+_.x)*4,ee=((_.y+_.height)*n+_.x)*4,M=K,V=N*4;_.interlaced===!0&&(V+=n*4*7);for(var H=8,z=0,te=q.length;z<te;++z){var D=q[z];if(Y===0&&(M+=V,Y=G,M>=ee&&(V=N*4+n*4*(H-1),M=K+(G+N)*(H<<1),H>>=1)),D===P)M+=4;else{var re=e[W+D*3],ne=e[W+D*3+1],ae=e[W+D*3+2];F[M++]=ae,F[M++]=ne,F[M++]=re,F[M++]=255}--Y}},this.decodeAndBlitFrameRGBA=function(X,F){var _=this.frameInfo(X),Z=_.width*_.height,q=new Uint8Array(Z);de(e,_.data_offset,q,Z);var W=_.palette_offset,P=_.transparent_index;P===null&&(P=256);var G=_.width,N=n-G,Y=G,K=(_.y*n+_.x)*4,ee=((_.y+_.height)*n+_.x)*4,M=K,V=N*4;_.interlaced===!0&&(V+=n*4*7);for(var H=8,z=0,te=q.length;z<te;++z){var D=q[z];if(Y===0&&(M+=V,Y=G,M>=ee&&(V=N*4+n*4*(H-1),M=K+(G+N)*(H<<1),H>>=1)),D===P)M+=4;else{var re=e[W+D*3],ne=e[W+D*3+1],ae=e[W+D*3+2];F[M++]=re,F[M++]=ne,F[M++]=ae,F[M++]=255}--Y}}}function de(e,t,n,a){for(var r=e[t++],o=1<<r,c=o+1,s=c+1,d=r+1,f=(1<<d)-1,l=0,i=0,p=0,v=e[t++],x=new Int32Array(4096),u=null;;){for(;l<16&&v!==0;)i|=e[t++]<<l,l+=8,v===1?v=e[t++]:--v;if(l<d)break;var h=i&f;if(i>>=d,l-=d,h===o){s=c+1,d=r+1,f=(1<<d)-1,u=null;continue}else if(h===c)break;for(var g=h<s?h:u,y=0,m=g;m>o;)m=x[m]>>8,++y;var C=m,S=p+y+(g!==h?1:0);if(S>a){console.log("Warning, gif stream longer than expected.");return}n[p++]=C,p+=y;var w=p;for(g!==h&&(n[p++]=C),m=g;y--;)m=x[m],n[--w]=m&255,m>>=8;u!==null&&s<4096&&(x[s++]=u<<8|C,s>=f+1&&d<12&&(++d,f=f<<1|1)),u=h}return p!==a&&console.log("Warning, gif stream shorter than expected."),n}try{Ue=he.GifWriter=$e,ge=he.GifReader=We}catch{}const Pe=ge;function Ne(e){return async(t,n)=>{const a=e.find(r=>r.canResolve(t));if(!a)throw new me("No texture provider matched source",t);return we(a.resolve.bind(a),t,n)}}class me extends Error{constructor(n,a){super(n);Q(this,"source");this.name="TextureSourceLoadError",this.source=a}}function b(e){if(e.aborted)throw new DOMException("Texture source load aborted","AbortError")}async function we(e,t,n){b(n);const a=await e(t,n);return n.aborted&&(a.dispose(),b(n)),a}function Ye(e){e==null||e.dispose()}const ye=5*1024*1024,oe=1e6,ie=180,Ve=(e,t,n)=>{for(let a=n.y;a<n.y+n.height;a+=1)e.fill(0,(a*t+n.x)*4,(a*t+n.x+n.width)*4)},He=(e,t,n,a,r)=>t.byteLength>ye?`file is ${(t.byteLength/1024/1024).toFixed(1)} MB; max is 5 MB`:n*a>oe?`canvas is ${n}x${a}; max area is ${oe}`:r>ie?`frame count is ${r}; max is ${ie}`:r===0?"frame count is 0":e?null:"source URL is empty",ze=e=>typeof e=="string"?e:e.src,Qe={canResolve:e=>typeof e=="string"?/\.gif(?:[?#].*)?$/i.test(e):e.kind==="gif",async resolve(e,t){const n=ze(e),a=await fetch(n,{signal:t});if(!a.ok)throw new Error(`GIF request failed with ${a.status}`);const r=new Uint8Array(await a.arrayBuffer());b(t);const o=new Pe(r),c=o.numFrames(),s=He(n,r,o.width,o.height,c);if(s)throw console.warn(`[xr-sdk] GIF ScreenImage source rejected: ${s}`,n),new Error(`GIF source rejected: ${s}`);const d=document.createElement("canvas");d.width=o.width,d.height=o.height;const f=d.getContext("2d");if(!f)throw new Error("Could not create GIF canvas context");const l=new j.CanvasTexture(d);l.colorSpace=j.SRGBColorSpace;const i=new Uint8Array(o.width*o.height*4),p=new ImageData(new Uint8ClampedArray(i.buffer),o.width,o.height),v=Array.from({length:c},(R,T)=>o.frameInfo(T)),x=v.reduce((R,T)=>R+Math.max(20,T.delay*10),0)/1e3,u=new ve({canSeek:!1,canReverse:!1,supportsLoopCount:!0},{state:"ready",duration:x,frameCount:c});let h=0,g=0,y=!1,m=!1,C=0,S=0,w=null;const E=(R,T=!1)=>{T&&(i.fill(0),w=null),(w==null?void 0:w.info.disposal)===2?Ve(i,o.width,w.info):w!=null&&w.restorePixels&&i.set(w.restorePixels);const k=v[R],$=k.disposal===3?new Uint8Array(i):null;return o.decodeAndBlitFrameRGBA(R,i),f.putImageData(p,0,0),l.needsUpdate=!0,w={info:k,restorePixels:$},m=!0,u.updateSnapshot({frame:R,time:v.slice(0,R).reduce((X,F)=>X+Math.max(20,F.delay*10),0)/1e3}),m=!1,u.emit("KeyFrameInSecond"),Math.max(20,k.delay*10)},B=R=>{g=window.setTimeout(()=>{h=requestAnimationFrame(I)},R)},I=()=>{if(y||u.getSnapshot().state!=="playing")return;const R=u.getSnapshot(),T=pe(C,c,R.playMode,R.loop,R.loopCount);if(T.ended){u.updateSnapshot({state:"ended",frame:T.frame,time:x}),u.emit("PlayEnd");return}const k=T.loop!==S;S=T.loop,C+=1,B(E(T.frame,k))},U=u.subscribe(R=>{m||(clearTimeout(g),cancelAnimationFrame(h),R.state==="playing"&&(h=requestAnimationFrame(I)))});return E(0),u.play(),{texture:l,controller:u,metadata:{width:o.width,height:o.height,duration:x,frameCount:c},dispose(){y=!0,U(),clearTimeout(g),cancelAnimationFrame(h),u.dispose(),l.dispose()}}}},Se=A.createContext(null),_e=A.createContext(null),Oe=()=>A.useContext(Se),Ze=()=>A.useContext(_e);exports.BasicAnimatedTextureController=ve;exports.MAX_GIF_BYTES=ye;exports.MAX_GIF_FRAMES=ie;exports.MAX_GIF_PIXELS=oe;exports.ScreenTransform=De;exports.TextureSourceLoadError=me;exports.XRScene=Le;exports.XRViewportRenderOutputsContext=_e;exports.XRViewportStateContext=Se;exports.computeScreenTransform=xe;exports.createTextureSourceResolver=Ne;exports.disposeResolvedTextureSource=Ye;exports.getPlaybackFrame=pe;exports.getSequenceFrame=je;exports.gifTextureSourceProvider=Qe;exports.resolveTextureSource=we;exports.throwIfAborted=b;exports.useXRViewportRenderOutputs=Ze;exports.useXRViewportState=Oe;