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

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 (88) hide show
  1. package/GROUNDING.md +92 -7
  2. package/dist/{DebuggerUI-bnGHSSOb.cjs → DebuggerUI-B6bP6P9r.cjs} +1 -1
  3. package/dist/{DebuggerUI-DhKTXTY2.js → DebuggerUI-BjOMr8q_.js} +1 -1
  4. package/dist/FaceMeshRenderer-C5l6VLdO.cjs +155 -0
  5. package/dist/FaceMeshRenderer-wjAHrJzP.js +1270 -0
  6. package/dist/{FaceRetouch-TZeBGIqW.cjs → FaceRetouch-BkJzoA79.cjs} +1 -1
  7. package/dist/{FaceRetouch-Bg-OBU4n.js → FaceRetouch-DwbKQJAN.js} +30 -30
  8. package/dist/components/FaceMesh/FaceMeshRenderer.d.ts +11 -3
  9. package/dist/components/FaceMesh/canonical/CanonicalFaceMeshRenderer.d.ts +17 -1
  10. package/dist/components/FaceMesh/canonical/geometryGroups.d.ts +1 -1
  11. package/dist/components/FaceMesh/canonical/parseCanonicalFaceModel.d.ts +1 -0
  12. package/dist/components/FaceMesh/index.d.ts +2 -2
  13. package/dist/components/LipEffect/LipEffect.d.ts +2 -0
  14. package/dist/components/LipEffect/LipEffectMaterial.d.ts +10 -0
  15. package/dist/components/LipEffect/defaults.d.ts +9 -0
  16. package/dist/components/LipEffect/index.d.ts +4 -0
  17. package/dist/components/LipEffect/types.d.ts +22 -0
  18. package/dist/components/SceneObjectRenderer/index.d.ts +9 -2
  19. package/dist/components/XRMediaSurface/index.d.ts +2 -1
  20. package/dist/{contexts-B2_NsTnk.js → contexts-ByhzppYl.js} +6 -3
  21. package/dist/contexts-Dr62It_K.cjs +1 -0
  22. package/dist/debug-ui/media-source.cjs +1 -1
  23. package/dist/debug-ui/media-source.js +1 -1
  24. package/dist/debug-ui.cjs +1 -1
  25. package/dist/debug-ui.js +10 -10
  26. package/dist/entries/core.d.ts +3 -2
  27. package/dist/entries/face-effects.d.ts +4 -2
  28. package/dist/entries/tracking.d.ts +2 -0
  29. package/dist/face-effects.cjs +1 -1
  30. package/dist/face-effects.js +622 -508
  31. package/dist/{getFaceInfo-4DhcPZDJ.js → getFaceInfo-C4QpCQIY.js} +1 -1
  32. package/dist/{getFaceInfo-QOQ_dc-W.cjs → getFaceInfo-fA1bFBub.cjs} +1 -1
  33. package/dist/hooks/useXRSession/facade.d.ts +2 -0
  34. package/dist/{index-BMeBJ0dV.js → index-9dlAQAhy.js} +457 -416
  35. package/dist/{index-C9yQVzAh.cjs → index-BjmTe9eM.cjs} +1 -1
  36. package/dist/{index-WPPnlFO1.cjs → index-BpEf2BBb.cjs} +1 -1
  37. package/dist/{index-D1kj6uc-.js → index-ByoNj0QP.js} +1 -1
  38. package/dist/{index-ZaDEzDtR.cjs → index-CyUUurQT.cjs} +1 -1
  39. package/dist/index-DCiMbxC3.cjs +1 -0
  40. package/dist/{index-Cj3fGDtZ.js → index-DXT3WccE.js} +808 -787
  41. package/dist/index-DpI-qo5X.cjs +17 -0
  42. package/dist/{index-g250Tqme.js → index-DyVF4vEW.js} +1 -1
  43. package/dist/{index-72Wb15Ca.js → index-VJ0SJwmG.js} +1 -1
  44. package/dist/{internal-Dtvo4WYo.cjs → internal-Cq-TEQ5Y.cjs} +1 -1
  45. package/dist/{internal-34pb7djs.js → internal-Dmk1cTXq.js} +3 -3
  46. package/dist/internal.cjs +1 -1
  47. package/dist/internal.js +1 -1
  48. package/dist/low-level.cjs +1 -1
  49. package/dist/low-level.js +344 -330
  50. package/dist/main.cjs +1 -1
  51. package/dist/main.js +94 -91
  52. package/dist/{renderGroups-jSUOY1Oq.cjs → renderGroups-80H3DpTl.cjs} +1 -1
  53. package/dist/{renderGroups-CPWUX6z9.js → renderGroups-KZk6eRiY.js} +1 -1
  54. package/dist/{renderPasses-KUJUSevp.cjs → renderPasses-BOoBSr8z.cjs} +1 -1
  55. package/dist/{renderPasses-CLlYRdMk.js → renderPasses-BcquyVtu.js} +4 -4
  56. package/dist/scene-object.cjs +1 -1
  57. package/dist/scene-object.js +2 -2
  58. package/dist/screen2d/coordinates.d.ts +20 -0
  59. package/dist/{selectors-DLxL8Q66.js → selectors-B8H97CKA.js} +1 -1
  60. package/dist/{selectors-S8g25ke9.cjs → selectors-CZLKT2Iv.cjs} +1 -1
  61. package/dist/{session-DP8AF7Rg.cjs → session-CpkiK5YA.cjs} +1 -1
  62. package/dist/{session-CbtvwiaD.js → session-DLFN_VII.js} +1 -1
  63. package/dist/tracking/coordinates.d.ts +5 -0
  64. package/dist/tracking.cjs +1 -1
  65. package/dist/tracking.js +69 -66
  66. package/dist/types/common.d.ts +11 -1
  67. package/dist/types/gesture-tracking.d.ts +2 -2
  68. package/dist/types/hand-tracking.d.ts +3 -3
  69. package/dist/types/nodes.d.ts +2 -2
  70. package/dist/types/session.d.ts +7 -1
  71. package/dist/{useFaceInfo-BvZeUBsL.cjs → useFaceInfo-BJ8-_MOs.cjs} +1 -1
  72. package/dist/{useFaceInfo-C06EyScd.js → useFaceInfo-Dk426LTu.js} +3 -3
  73. package/dist/{useFaceResults-C1Ppc8rS.js → useFaceResults-CtetsO9M.js} +1 -1
  74. package/dist/{useFaceResults-CCNiH7VZ.cjs → useFaceResults-wBJF3zyp.cjs} +1 -1
  75. package/dist/utils/visionWasm.d.ts +18 -0
  76. package/docs/SDK_DOCUMENTATION.md +3 -0
  77. package/docs/api/capture-recording.mdx +9 -1
  78. package/docs/api/face-mesh.mdx +33 -0
  79. package/docs/api/runtime-3d.mdx +5 -0
  80. package/docs/api/screen-image.mdx +3 -1
  81. package/docs/api/screen-space-coordinates.mdx +31 -0
  82. package/docs/api/trackers.mdx +13 -0
  83. package/package.json +4 -1
  84. package/dist/FaceMeshRenderer-B2i2NW71.js +0 -1195
  85. package/dist/FaceMeshRenderer-BSOq1OnG.cjs +0 -155
  86. package/dist/contexts-BgWfyxre.cjs +0 -1
  87. package/dist/index-CNGzE49z.cjs +0 -17
  88. package/dist/index-Da7uycur.cjs +0 -1
package/GROUNDING.md CHANGED
@@ -20,10 +20,11 @@ Trackers (`<FaceTracker>`, `<GestureTracker>`, `<HandTracker>`, `<BodyTracker>`)
20
20
  **self-register** when mounted — no explicit `registerXRPipeline` call. Per-frame
21
21
  logic is R3F `useFrame`; per-mount setup is `useEffect`.
22
22
 
23
- > This file ships inside the SDK tarball. In a v2-template project it is combined
24
- > with the template's own grounding (template-local helpers + project notes +
25
- > patterns) into the project's `GROUNDING.md`. Edit the SDK API here, in the repo
26
- > that owns the API.
23
+ > This file ships inside the SDK tarball, and that is how it reaches a project:
24
+ > on disk at `node_modules/@vincentt-xr/sdk/GROUNDING.md`. Nothing merges it into
25
+ > the project's own `GROUNDING.md` — a v2-template project has two grounding
26
+ > files, this one for the SDK API and the template's for its local helpers, and
27
+ > an agent reads both. Edit the SDK API here, in the repo that owns the API.
27
28
 
28
29
  ### Internal source layout
29
30
 
@@ -93,6 +94,19 @@ import { ScreenSpaceUI, ScreenTransform } from "@vincentt-xr/sdk";
93
94
 
94
95
  Coordinates are normalized: -1 to +1, with +y up. The center of the screen is `(0, 0)`. The anchors rect controls BOTH size and placement of the child — it stretches the child (plane, TextLabel, sprite) to fill the rect. Don't add `scale`/`position`/`planeGeometry args` to size or move a screen-anchored child; set the anchors.
95
96
 
97
+ Canvas screen pixels map across the live viewport on both axes, including
98
+ landscape and square displays. They are not automatically letterboxed. Preserve
99
+ an image or video's own aspect with its fit mode inside a screen rect, not with
100
+ manual point conversion. `ScreenTransform2DSettings`, used by serialized editor
101
+ layouts, is intentionally contain-fitted so text and its transform guide retain
102
+ their authored aspect ratio.
103
+
104
+ For a custom R3F mesh that needs a translated design point, use
105
+ `screenPixelsToScreenSpace({ point, parentSize })`; it applies the same separate
106
+ X/Y mapping as the screen primitives. `screenPixelsToUnits` is scalar conversion
107
+ for uniform distances and is not a substitute for point placement on a
108
+ non-design-aspect viewport.
109
+
96
110
  ```tsx
97
111
  // Full-screen frame
98
112
  <ScreenTransform anchors={{ left: -1, right: 1, top: 1, bottom: -1 }}>
@@ -527,6 +541,34 @@ projection correction. Author a Transform with `position.y = 0` to opt out.
527
541
  Use it only when bridging custom runtime code; ordinary scene-object rendering
528
542
  should use `SceneObjectRenderer`.
529
543
 
544
+ SDK material types and shader presets are convenience defaults, not a closed
545
+ material system. For an advanced effect, pass `materialOverride` to
546
+ `FaceMeshRenderer`. It accepts a material node or a factory invoked per visible
547
+ face geometry with `{ cameraTexture, geometryKey }`. The override takes
548
+ precedence over presets and stays runtime-only: do not place `THREE.Material`,
549
+ uniforms, or factories in `FaceMeshRendererSettings` or a persisted
550
+ `SceneObjectStore`.
551
+
552
+ ```tsx
553
+ <FaceMeshRenderer
554
+ value={faceMeshSettings}
555
+ materialOverride={({ cameraTexture, geometryKey }) => (
556
+ <shaderMaterial
557
+ key={geometryKey}
558
+ uniforms={{ cameraTexture: { value: cameraTexture } }}
559
+ vertexShader={vertexShader}
560
+ fragmentShader={fragmentShader}
561
+ transparent
562
+ />
563
+ )}
564
+ />
565
+ ```
566
+
567
+ For serialized scene objects, pass runtime overrides separately to
568
+ `SceneObjectRenderer`, keyed by the FaceMeshRenderer component ID. R3F owns a
569
+ material node's lifecycle; factories must return stable, ordinary React material
570
+ nodes and must not mutate private renderer internals.
571
+
530
572
  `CanonicalFaceMeshRenderer` remains exported from `@vincentt-xr/sdk/face-effects`
531
573
  for backwards compatibility and low-level experiments, but new editor and
532
574
  scene-object work should use `FaceMeshRenderer`.
@@ -884,6 +926,13 @@ Supports multiple detected hands: `hand` selects `"left"` or `"right"` when that
884
926
  hand is available; `handIndex` falls back to positional selection. Existing
885
927
  one-hand scenes keep working via the default first-hand selection.
886
928
 
929
+ Low-level `node.coordinates` are `TrackerPoint` values: center-origin, X right,
930
+ Y up, and positive Z toward the viewer. X/Y are in `[-1, 1]`; Z is
931
+ tracker-relative depth, not a normalized screen axis. For a bespoke cursor or
932
+ overlay, call `trackerPointToScreenPixels({ point, viewportSize })` from
933
+ `@vincentt-xr/sdk`. The SDK already owns the mirror and origin conversion; do
934
+ not repeat it in app code.
935
+
887
936
  ### `<GestureTracker>` — Named gestures
888
937
 
889
938
  The gesture door — the component that recognizes named gestures. Its `node.gesture` is one of these exact strings (copy verbatim — these are the only valid values):
@@ -919,6 +968,10 @@ import { BodyTracker, TrackingAnchor } from "@vincentt-xr/sdk/tracking";
919
968
  </BodyTracker>;
920
969
  ```
921
970
 
971
+ Low-level body landmarks use the same `TrackerPoint` contract as hand and
972
+ gesture points. `TrackingAnchor` is preferred for attachment; use
973
+ `trackerPointToScreenPixels` only when rendering a bespoke 2D projection.
974
+
922
975
  ### `<Segmentation type="portrait">` — Background segmentation (declarative)
923
976
 
924
977
  Registers the portrait segmentation pipeline. The resulting mask feeds into `<VideoBackground segmentationMask={...} />` for background replacement. Mount it alongside a ref or state that holds the mask texture.
@@ -945,6 +998,12 @@ Fix: mount trackers that more than one scene needs **once**, above the phase swi
945
998
 
946
999
  Scope a tracker to a single scene only when just that scene uses it (e.g. a `<FaceTracker>` catcher that exists only during gameplay).
947
1000
 
1001
+ ### First load: each tracker you mount is a download
1002
+
1003
+ Before a tracker reports anything, the viewer's phone downloads its model and the shared MediaPipe engine (`vision_wasm_internal.wasm`, served gzip-compressed, ~2.9 MB). The SDK fetches the two in parallel, and trackers mounted together share one engine download. Model sizes: face 3.8 MB, hand 7.8 MB, gesture 8.4 MB, body 5.8 MB. All are cached by the browser for a year, so a returning viewer downloads nothing.
1004
+
1005
+ So every extra tracker costs a first-time viewer its full model on mobile data. Mount only the trackers the experience actually reads; a face-only effect should not also mount `<HandTracker>`.
1006
+
948
1007
  ### `active` — pause an off-scene tracker without unmounting it
949
1008
 
950
1009
  The "mount once" rule keeps a model alive across scenes, but a persistent tracker then runs its MediaPipe pipeline **every frame for the whole session** — even in scenes that don't use it. Each running model does a GPU→CPU readback per inference, and that readback is often the single largest cost in the app; two persistent trackers (e.g. gesture on the menus, face in gameplay) stack two readbacks the whole time when only one is ever needed at once.
@@ -1381,6 +1440,11 @@ design pixels are Three.js world units.
1381
1440
  SDK screen pixels use the Effect House-style `720x1280` design canvas, center
1382
1441
  origin, and +Y up.
1383
1442
 
1443
+ `docs/api/screen-space-coordinates.mdx` is the API source of truth for which
1444
+ helper owns each conversion. Keep this grounding summary and that page aligned;
1445
+ raw MediaPipe face landmarks are normalized image points, while SDK low-level
1446
+ hand, gesture, and body reads are center-origin tracker points.
1447
+
1384
1448
  ```ts
1385
1449
  const units = screenPixelsToUnits(120, { parentSize: screenDimensions });
1386
1450
  const pixels = screenUnitsToPixels(units, { parentSize: screenDimensions });
@@ -2117,6 +2181,22 @@ request; `"unknown"` is anything unrecognized.
2117
2181
 
2118
2182
  Grab a photo of the live render or record the canvas, then save or share it.
2119
2183
 
2184
+ ### Camera, layout, mirror, and capture parity
2185
+
2186
+ One owner composes media pixels before they are displayed, tracked, or captured.
2187
+ For direct session media, the session owns the webcam source and mirrors it once
2188
+ before its cover-cropped camera texture reaches trackers and R3F content. For
2189
+ `XRViewport mediaStrategy="internal"`, the viewport owns source selection,
2190
+ fit, and mirror state; it sends that already composed canvas to the session, so
2191
+ the tracker, visible media surface, and capture target share the same pixels.
2192
+
2193
+ Resize and source changes recompute this composition before the next tracker
2194
+ frame. Do not add a second CSS, canvas, or shader mirror to a session camera
2195
+ texture or viewport media canvas. `captureFrame()` and `captureStream()` capture
2196
+ the active XRScene canvas when present, otherwise the DOM viewport media canvas.
2197
+ They capture canvas composition only; arbitrary DOM HUD elements are not part of
2198
+ the image or recording.
2199
+
2120
2200
  ### `useFrameCapture()` + `dataURLtoFile()` — Single-shot photo
2121
2201
 
2122
2202
  Use `useFrameCapture` for UI/effect logic. It exposes `status`, `capturePhoto`,
@@ -2137,7 +2217,13 @@ await photo.capturePhoto();
2137
2217
  ```
2138
2218
 
2139
2219
  For synchronous low-level code, `session.captureFrame()` remains available via
2140
- `useXRContext` from `@vincentt-xr/sdk/low-level`.
2220
+ `useXRContext` from `@vincentt-xr/sdk/low-level`. It also exposes
2221
+ `session.captureStream(fps?)`, which records the same active canvas:
2222
+
2223
+ ```tsx
2224
+ const rec = useMediaRecorder();
2225
+ await rec.start(session.captureStream(30));
2226
+ ```
2141
2227
 
2142
2228
  ### `useMediaRecorder()` — Record the canvas to a video Blob
2143
2229
 
@@ -2149,8 +2235,7 @@ the first supported codec (mp4 → webm). Pass `audio: true` to mix in the mic,
2149
2235
  import { useMediaRecorder } from "@vincentt-xr/sdk";
2150
2236
 
2151
2237
  const rec = useMediaRecorder();
2152
- const canvas = document.querySelector("#vincentt-xr-canvas canvas");
2153
- await rec.start(canvas.captureStream(30));
2238
+ await rec.start(session.captureStream(30));
2154
2239
  // ...later
2155
2240
  rec.stop(); // -> rec.recordedBlob is the video Blob
2156
2241
  ```
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),x=require("react"),C=require("react-dom"),s=require("./internal-Dtvo4WYo.cjs"),P={position:"fixed",top:"10px",left:"10px",zIndex:9999,fontFamily:"'Monaco', 'Menlo', 'Ubuntu Mono', 'Consolas', monospace",fontSize:"12px",color:"#fff",pointerEvents:"auto",userSelect:"none"},h={background:"rgba(0, 0, 0, 0.85)",borderRadius:"6px",padding:"12px 16px",boxShadow:"0 4px 12px rgba(0, 0, 0, 0.5)",backdropFilter:"blur(10px)",border:"1px solid rgba(255, 255, 255, 0.1)",minWidth:"240px"},k={...h,padding:"8px 12px",minWidth:"auto"},F={display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:"12px",paddingBottom:"8px",borderBottom:"1px solid rgba(255, 255, 255, 0.2)"},M={fontSize:"13px",fontWeight:"bold",color:"#00ff9f",letterSpacing:"0.5px",textTransform:"uppercase"},z={display:"flex",gap:"6px"},f={background:"rgba(255, 255, 255, 0.1)",border:"1px solid rgba(255, 255, 255, 0.2)",borderRadius:"4px",color:"#fff",padding:"4px 8px",fontSize:"11px",cursor:"pointer",transition:"all 0.2s"},R={display:"grid",gridTemplateColumns:"1fr 1fr",gap:"10px"},i={display:"flex",flexDirection:"column",gap:"4px"},o={fontSize:"10px",color:"rgba(255, 255, 255, 0.6)",textTransform:"uppercase",letterSpacing:"0.5px"},d={fontSize:"16px",fontWeight:"bold",color:"#fff"},u={...d,color:"#00ff9f"},g={...d,color:"#ffaa00"},m={...d,color:"#ff4444"},l={fontSize:"11px",color:"rgba(255, 255, 255, 0.5)",marginLeft:"4px"},N={width:"100%",height:"4px",background:"rgba(255, 255, 255, 0.2)",borderRadius:"2px",overflow:"hidden",marginTop:"4px"},w=t=>({width:`${t}%`,height:"100%",background:t>90?"#ff4444":t>70?"#ffaa00":"#00ff9f",transition:"width 0.3s ease, background 0.3s ease"}),B={fontSize:"9px",color:"rgba(255, 255, 255, 0.4)",marginTop:"8px",textAlign:"center",fontStyle:"italic"};function a(t,n){return n==="fps"?t>=30?u:t>=20?g:m:t<=40?u:t<=60?g:m}function D({metrics:t,collapsed:n,onCollapse:y,onClose:b,position:c="top-left",keyboardShortcut:j="ctrl+shift+d"}){const[p,v]=x.useState(null);if(x.useEffect(()=>{const r=document.createElement("div");return r.id="xr-debugger-overlay",document.body.appendChild(r),v(r),()=>{document.body.removeChild(r)}},[]),!p)return null;const S={...P,...c==="top-right"&&{left:"auto",right:"10px"},...c==="bottom-left"&&{top:"auto",bottom:"10px"},...c==="bottom-right"&&{top:"auto",bottom:"10px",left:"auto",right:"10px"}};return C.createPortal(e.jsx("div",{style:S,children:e.jsxs("div",{style:n?k:h,children:[e.jsxs("div",{style:F,children:[e.jsx("div",{style:M,children:n?"AR Debugger":"AR Performance"}),e.jsxs("div",{style:z,children:[e.jsx("button",{style:f,onClick:()=>y(!n),onMouseEnter:r=>{r.currentTarget.style.background="rgba(255, 255, 255, 0.2)"},onMouseLeave:r=>{r.currentTarget.style.background="rgba(255, 255, 255, 0.1)"},children:n?"+":"−"}),e.jsx("button",{style:f,onClick:b,onMouseEnter:r=>{r.currentTarget.style.background="rgba(255, 255, 255, 0.2)"},onMouseLeave:r=>{r.currentTarget.style.background="rgba(255, 255, 255, 0.1)"},children:"✕"})]})]}),!n&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{style:R,children:[e.jsxs("div",{style:i,children:[e.jsx("div",{style:o,children:"Camera FPS"}),e.jsxs("div",{children:[e.jsx("span",{style:a(t.cameraFPS,"fps"),children:s.formatNumber(t.cameraFPS,0)}),e.jsx("span",{style:l,children:"fps"})]})]}),e.jsxs("div",{style:i,children:[e.jsx("div",{style:o,children:"Resolution"}),e.jsx("span",{style:d,children:t.resolution})]}),e.jsxs("div",{style:i,children:[e.jsx("div",{style:o,children:"Detection"}),e.jsxs("div",{children:[e.jsx("span",{style:a(t.detectionTime,"time"),children:s.formatNumber(t.detectionTime,1)}),e.jsx("span",{style:l,children:"ms"})]})]}),e.jsxs("div",{style:i,children:[e.jsx("div",{style:o,children:"Rendering"}),e.jsxs("div",{children:[e.jsx("span",{style:a(t.renderTime,"time"),children:s.formatNumber(t.renderTime,1)}),e.jsx("span",{style:l,children:"ms"})]})]}),e.jsxs("div",{style:i,children:[e.jsx("div",{style:o,children:"Effective FPS"}),e.jsxs("div",{children:[e.jsx("span",{style:a(t.effectiveFPS,"fps"),children:s.formatNumber(t.effectiveFPS,0)}),e.jsx("span",{style:l,children:"fps"})]})]}),e.jsxs("div",{style:i,children:[e.jsx("div",{style:o,children:"Memory"}),t.memory?e.jsxs(e.Fragment,{children:[e.jsxs("div",{children:[e.jsx("span",{style:d,children:s.formatNumber(t.memory.used,0)}),e.jsxs("span",{style:l,children:["/ ",s.formatNumber(t.memory.total,0)," MB"]})]}),e.jsx("div",{style:N,children:e.jsx("div",{style:w(t.memory.percentage)})})]}):e.jsx("span",{style:d,children:"N/A"})]})]}),t.modelPerformance.length>0&&e.jsx(e.Fragment,{children:e.jsxs("div",{style:{borderTop:"1px solid rgba(255, 255, 255, 0.15)",marginTop:"12px",paddingTop:"12px"},children:[e.jsx("div",{style:o,children:"Model Performance"}),e.jsx("div",{style:{marginTop:"8px",display:"flex",flexDirection:"column",gap:"6px"},children:t.modelPerformance.map((r,T)=>e.jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center",fontSize:"11px"},children:[e.jsx("span",{style:{color:"rgba(255, 255, 255, 0.7)"},children:r.name}),e.jsxs("div",{children:[e.jsx("span",{style:a(r.processingTime,"time"),children:s.formatNumber(r.processingTime,1)}),e.jsx("span",{style:l,children:"ms"})]})]},T))})]})}),e.jsxs("div",{style:B,children:["Press ",j.toUpperCase()," to toggle"]})]})]})}),p)}exports.DebuggerUI=D;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),x=require("react"),C=require("react-dom"),s=require("./internal-Cq-TEQ5Y.cjs"),P={position:"fixed",top:"10px",left:"10px",zIndex:9999,fontFamily:"'Monaco', 'Menlo', 'Ubuntu Mono', 'Consolas', monospace",fontSize:"12px",color:"#fff",pointerEvents:"auto",userSelect:"none"},h={background:"rgba(0, 0, 0, 0.85)",borderRadius:"6px",padding:"12px 16px",boxShadow:"0 4px 12px rgba(0, 0, 0, 0.5)",backdropFilter:"blur(10px)",border:"1px solid rgba(255, 255, 255, 0.1)",minWidth:"240px"},k={...h,padding:"8px 12px",minWidth:"auto"},F={display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:"12px",paddingBottom:"8px",borderBottom:"1px solid rgba(255, 255, 255, 0.2)"},M={fontSize:"13px",fontWeight:"bold",color:"#00ff9f",letterSpacing:"0.5px",textTransform:"uppercase"},z={display:"flex",gap:"6px"},f={background:"rgba(255, 255, 255, 0.1)",border:"1px solid rgba(255, 255, 255, 0.2)",borderRadius:"4px",color:"#fff",padding:"4px 8px",fontSize:"11px",cursor:"pointer",transition:"all 0.2s"},R={display:"grid",gridTemplateColumns:"1fr 1fr",gap:"10px"},i={display:"flex",flexDirection:"column",gap:"4px"},o={fontSize:"10px",color:"rgba(255, 255, 255, 0.6)",textTransform:"uppercase",letterSpacing:"0.5px"},d={fontSize:"16px",fontWeight:"bold",color:"#fff"},u={...d,color:"#00ff9f"},g={...d,color:"#ffaa00"},m={...d,color:"#ff4444"},l={fontSize:"11px",color:"rgba(255, 255, 255, 0.5)",marginLeft:"4px"},N={width:"100%",height:"4px",background:"rgba(255, 255, 255, 0.2)",borderRadius:"2px",overflow:"hidden",marginTop:"4px"},w=t=>({width:`${t}%`,height:"100%",background:t>90?"#ff4444":t>70?"#ffaa00":"#00ff9f",transition:"width 0.3s ease, background 0.3s ease"}),B={fontSize:"9px",color:"rgba(255, 255, 255, 0.4)",marginTop:"8px",textAlign:"center",fontStyle:"italic"};function a(t,n){return n==="fps"?t>=30?u:t>=20?g:m:t<=40?u:t<=60?g:m}function D({metrics:t,collapsed:n,onCollapse:y,onClose:b,position:c="top-left",keyboardShortcut:j="ctrl+shift+d"}){const[p,v]=x.useState(null);if(x.useEffect(()=>{const r=document.createElement("div");return r.id="xr-debugger-overlay",document.body.appendChild(r),v(r),()=>{document.body.removeChild(r)}},[]),!p)return null;const S={...P,...c==="top-right"&&{left:"auto",right:"10px"},...c==="bottom-left"&&{top:"auto",bottom:"10px"},...c==="bottom-right"&&{top:"auto",bottom:"10px",left:"auto",right:"10px"}};return C.createPortal(e.jsx("div",{style:S,children:e.jsxs("div",{style:n?k:h,children:[e.jsxs("div",{style:F,children:[e.jsx("div",{style:M,children:n?"AR Debugger":"AR Performance"}),e.jsxs("div",{style:z,children:[e.jsx("button",{style:f,onClick:()=>y(!n),onMouseEnter:r=>{r.currentTarget.style.background="rgba(255, 255, 255, 0.2)"},onMouseLeave:r=>{r.currentTarget.style.background="rgba(255, 255, 255, 0.1)"},children:n?"+":"−"}),e.jsx("button",{style:f,onClick:b,onMouseEnter:r=>{r.currentTarget.style.background="rgba(255, 255, 255, 0.2)"},onMouseLeave:r=>{r.currentTarget.style.background="rgba(255, 255, 255, 0.1)"},children:"✕"})]})]}),!n&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{style:R,children:[e.jsxs("div",{style:i,children:[e.jsx("div",{style:o,children:"Camera FPS"}),e.jsxs("div",{children:[e.jsx("span",{style:a(t.cameraFPS,"fps"),children:s.formatNumber(t.cameraFPS,0)}),e.jsx("span",{style:l,children:"fps"})]})]}),e.jsxs("div",{style:i,children:[e.jsx("div",{style:o,children:"Resolution"}),e.jsx("span",{style:d,children:t.resolution})]}),e.jsxs("div",{style:i,children:[e.jsx("div",{style:o,children:"Detection"}),e.jsxs("div",{children:[e.jsx("span",{style:a(t.detectionTime,"time"),children:s.formatNumber(t.detectionTime,1)}),e.jsx("span",{style:l,children:"ms"})]})]}),e.jsxs("div",{style:i,children:[e.jsx("div",{style:o,children:"Rendering"}),e.jsxs("div",{children:[e.jsx("span",{style:a(t.renderTime,"time"),children:s.formatNumber(t.renderTime,1)}),e.jsx("span",{style:l,children:"ms"})]})]}),e.jsxs("div",{style:i,children:[e.jsx("div",{style:o,children:"Effective FPS"}),e.jsxs("div",{children:[e.jsx("span",{style:a(t.effectiveFPS,"fps"),children:s.formatNumber(t.effectiveFPS,0)}),e.jsx("span",{style:l,children:"fps"})]})]}),e.jsxs("div",{style:i,children:[e.jsx("div",{style:o,children:"Memory"}),t.memory?e.jsxs(e.Fragment,{children:[e.jsxs("div",{children:[e.jsx("span",{style:d,children:s.formatNumber(t.memory.used,0)}),e.jsxs("span",{style:l,children:["/ ",s.formatNumber(t.memory.total,0)," MB"]})]}),e.jsx("div",{style:N,children:e.jsx("div",{style:w(t.memory.percentage)})})]}):e.jsx("span",{style:d,children:"N/A"})]})]}),t.modelPerformance.length>0&&e.jsx(e.Fragment,{children:e.jsxs("div",{style:{borderTop:"1px solid rgba(255, 255, 255, 0.15)",marginTop:"12px",paddingTop:"12px"},children:[e.jsx("div",{style:o,children:"Model Performance"}),e.jsx("div",{style:{marginTop:"8px",display:"flex",flexDirection:"column",gap:"6px"},children:t.modelPerformance.map((r,T)=>e.jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center",fontSize:"11px"},children:[e.jsx("span",{style:{color:"rgba(255, 255, 255, 0.7)"},children:r.name}),e.jsxs("div",{children:[e.jsx("span",{style:a(r.processingTime,"time"),children:s.formatNumber(r.processingTime,1)}),e.jsx("span",{style:l,children:"ms"})]})]},T))})]})}),e.jsxs("div",{style:B,children:["Press ",j.toUpperCase()," to toggle"]})]})]})}),p)}exports.DebuggerUI=D;
@@ -1,7 +1,7 @@
1
1
  import { jsx as e, jsxs as r, Fragment as f } from "react/jsx-runtime";
2
2
  import { useState as P, useEffect as M } from "react";
3
3
  import { createPortal as F } from "react-dom";
4
- import { f as i } from "./internal-34pb7djs.js";
4
+ import { f as i } from "./internal-Dmk1cTXq.js";
5
5
  const z = {
6
6
  position: "fixed",
7
7
  top: "10px",
@@ -0,0 +1,155 @@
1
+ "use strict";const u=require("react/jsx-runtime"),te=require("@react-three/fiber"),c=require("react"),ee=require("three"),Q=require("./index-DCiMbxC3.cjs"),Ve=require("./selectors-CZLKT2Iv.cjs"),Fe=require("./index-CyUUurQT.cjs"),Zt=require("@react-three/drei");function Jt(e){const n=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(e){for(const t in e)if(t!=="default"){const r=Object.getOwnPropertyDescriptor(e,t);Object.defineProperty(n,t,r.get?r:{enumerable:!0,get:()=>e[t]})}}return n.default=e,Object.freeze(n)}const p=Jt(ee),he=8,Y={type:"linear",stops:[{offset:0,color:"#38bdf8"},{offset:1,color:"#a78bfa"}],angle:0,center:{x:.5,y:.5},radius:.5},en=e=>{const n=e.slice(0,he).map(t=>({...t,offset:ee.MathUtils.clamp(t.offset,0,1)})).sort((t,r)=>t.offset-r.offset);return n.length>=2?n:Y.stops.map(t=>({...t}))},Ye=e=>({...Y,...e,center:{...Y.center,...e==null?void 0:e.center},radius:Math.max(.01,(e==null?void 0:e.radius)??Y.radius),stops:en((e==null?void 0:e.stops)??Y.stops)}),tn=`
2
+ varying vec2 vPosition;
3
+ void main() {
4
+ vPosition = position.xy;
5
+ gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
6
+ }
7
+ `,nn=`
8
+ #define MAX_STOPS 8
9
+ uniform vec3 stopColors[MAX_STOPS];
10
+ uniform float stopOffsets[MAX_STOPS];
11
+ uniform int stopCount;
12
+ uniform int gradientType;
13
+ uniform vec2 direction;
14
+ uniform vec2 center;
15
+ uniform float radius;
16
+ uniform float angleOffset;
17
+ uniform float opacity;
18
+ varying vec2 vPosition;
19
+
20
+ vec3 sampleGradient(float amount) {
21
+ vec3 color = stopColors[0];
22
+ for (int index = 1; index < MAX_STOPS; index++) {
23
+ if (index >= stopCount) break;
24
+ if (amount <= stopOffsets[index]) {
25
+ float width = max(0.0001, stopOffsets[index] - stopOffsets[index - 1]);
26
+ return mix(stopColors[index - 1], stopColors[index], clamp((amount - stopOffsets[index - 1]) / width, 0.0, 1.0));
27
+ }
28
+ color = stopColors[index];
29
+ }
30
+ return color;
31
+ }
32
+
33
+ void main() {
34
+ vec2 delta = vPosition - center;
35
+ float amount;
36
+ if (gradientType == 1) {
37
+ amount = clamp(length(delta) / radius, 0.0, 1.0);
38
+ } else if (gradientType == 2) {
39
+ amount = fract(atan(delta.y, delta.x) / 6.28318530718 + 0.5 + angleOffset);
40
+ } else {
41
+ amount = clamp(dot(delta, direction) + 0.5, 0.0, 1.0);
42
+ }
43
+ gl_FragColor = vec4(sampleGradient(amount), opacity);
44
+ }
45
+ `,rn={linear:0,radial:1,angular:2},$e=({opacity:e=1,value:n})=>{const t=c.useMemo(()=>{const r=Ye(n),o=ee.MathUtils.degToRad(r.angle),a=r.stops.map(s=>new ee.Color(s.color)),i=r.stops.map(s=>s.offset);for(;a.length<he;)a.push(a[a.length-1]);for(;i.length<he;)i.push(1);return{stopColors:{value:a},stopOffsets:{value:i},stopCount:{value:r.stops.length},gradientType:{value:rn[r.type]},direction:{value:new ee.Vector2(Math.cos(o),Math.sin(o))},center:{value:new ee.Vector2(r.center.x-.5,.5-r.center.y)},radius:{value:r.radius},angleOffset:{value:r.angle/360},opacity:{value:e}}},[e,n]);return u.jsx("shaderMaterial",{uniforms:t,vertexShader:tn,fragmentShader:nn,transparent:e<1,depthTest:!1,depthWrite:!1,toneMapped:!1})},on="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8/x8AAwMCAO2YpZcAAAAASUVORK5CYII=",an={source:"solid",color:"#ffffff",opacity:1,textureUrl:"",gradient:Y},we=e=>({...Y,stops:[{offset:0,color:"#ffffff"},{offset:1,color:e}]}),sn=({depthTest:e,depthWrite:n,settings:t,side:r,toneMapped:o})=>{const a=te.useLoader(p.TextureLoader,t.textureUrl||on);return u.jsx("meshBasicMaterial",{color:t.color,map:a,transparent:!0,opacity:t.opacity,side:r,depthWrite:n,depthTest:e,toneMapped:o})},Ke=({depthTest:e=!1,depthWrite:n=!1,settings:t,side:r,toneMapped:o=!1})=>{const a=c.useMemo(()=>t.gradient??we(t.color),[t.color,t.gradient]);return t.source==="gradient"?u.jsx($e,{value:a,opacity:t.opacity}):t.source==="texture"?u.jsx(sn,{settings:t,side:r,depthTest:e,depthWrite:n,toneMapped:o}):u.jsx("meshBasicMaterial",{color:t.color,transparent:!0,opacity:t.opacity,side:r,depthWrite:n,depthTest:e,toneMapped:o})},Re=Math.PI/180,Se=180/Math.PI,B=e=>Number(e.toFixed(6)),ke={enabled:!0,linked:{position:!1,rotation:!1,scale:!1},showTransformControls:!1,transformControlMode:"translate",transformControlSpace:"local",position:{x:0,y:0,z:0},rotation:{x:0,y:0,z:0},scale:{x:1,y:1,z:1},visible:!0},cn=({children:e,objectRef:n,onChange:t,value:r})=>{const o=c.useRef(null),a=c.useRef(n);a.current=n;const[i,s]=c.useState(null),d=c.useCallback(l=>{var x;o.current=l,s(l),(x=a.current)==null||x.call(a,l)},[]),h=c.useCallback(()=>{const l=o.current;!l||!t||t({...r,position:{x:B(l.position.x),y:B(l.position.y),z:B(l.position.z)},rotation:{x:B(l.rotation.x*Se),y:B(l.rotation.y*Se),z:B(l.rotation.z*Se)},scale:{x:B(l.scale.x),y:B(l.scale.y),z:B(l.scale.z)}})},[t,r]);return r.enabled?u.jsxs(u.Fragment,{children:[u.jsx("group",{ref:d,position:[r.position.x,r.position.y,r.position.z],rotation:[r.rotation.x*Re,r.rotation.y*Re,r.rotation.z*Re],scale:[r.scale.x,r.scale.y,r.scale.z],visible:r.visible,children:e}),i&&r.showTransformControls&&u.jsx(Zt.TransformControls,{object:i,mode:r.transformControlMode,space:r.transformControlSpace,size:.85,onMouseUp:h,onObjectChange:h})]}):null},ae=e=>Math.min(1,Math.max(0,e)),O=(e,n,t)=>ae(1-Math.abs(e-n)/t),ln=e=>{let n=1/0,t=-1/0,r=1/0,o=-1/0;for(const s of e)n=Math.min(n,s.x),t=Math.max(t,s.x),r=Math.min(r,s.y),o=Math.max(o,s.y);const a=Math.max(t-n,.001),i=Math.max(o-r,.001);return{centerX:n+a*.5,centerY:r+i*.5,width:a,height:i}},un=e=>e!=null&&e.enabled?(e.strength??1)!==0&&Object.entries(e).some(([n,t])=>n!=="enabled"&&n!=="strength"&&typeof t=="number"&&t!==0):!1,fn=(e,n,t,r)=>{const o=t.enabled?t.strength??1:0;if(o===0)return r.x=e.x,r.y=e.y,r.z=e.z,r;const a=(e.x-n.centerX)/n.width,i=(e.y-n.centerY)/n.height,s=Math.abs(a),d=ae((-i+.42)/.55),h=O(i,-.02,.34),l=O(i,-.24,.16)*ae((s-.05)/.28),x=O(i,.02,.26)*O(s,0,.18),_=O(i,.29,.18)*O(s,0,.36),D=ae((i-.16)/.36),C=h*O(s,.34,.22),k=d*O(s,0,.48),S=O(i,-.19,.1)*ae((s-.05)/.3),$=O(i,.48,.2)*O(s,0,.26);let A=e.x,y=e.y,w=e.z;const E=(v,m=1)=>{A+=a*n.width*v*o*m},f=(v,m=1)=>{y+=i*n.height*v*o*m};E(t.faceWidth??0),f(t.faceHeight??0),E(t.faceRoundness??0,h*(1-s)),y-=n.height*(t.midfaceHeight??0)*o*h*.25,f(-(t.foreheadHeight??0),k),E(t.foreheadWidth??0,k),E(t.cheekboneWidth??0,O(i,-.06,.16)*O(s,.34,.2)),E(t.cheekWidth??0,C),E(t.jawWidth??0,D),f(t.chinHeight??0,$),y-=n.height*(t.scalpHeight??0)*o*d*.3,w-=(t.midfaceDepth??0)*o*h*.08,w+=(t.cheekHollowness??0)*o*C*.06,w-=(t.browDepth??0)*o*S*.05,y-=n.height*(t.browHeight??0)*o*S*.2,A+=Math.sign(a||1)*n.width*(t.browDistance??0)*o*S*.16;const F=(t.headCurve??0)*o*(i+.1);w-=F*F*.04*Math.sign(t.headCurve??0),A+=n.width*(t.faceTwist??0)*o*i*.18;const H=(t.faceSwirl??0)*o*.22;A+=-i*n.width*H,y+=a*n.height*H;const I=a<0?t.leftEyeSize??0:t.rightEyeSize??0,b=((t.eyeSize??0)+I)*o*l;A+=a*n.width*b*.45,y+=(i+.24)*n.height*b*.7,A+=Math.sign(a||1)*n.width*(t.eyeDistance??0)*o*l*.2,A+=n.width*(a<0?t.leftEyeX??0:t.rightEyeX??0)*o*l*.15,y+=n.height*(a<0?t.leftEyeY??0:t.rightEyeY??0)*o*l*.15;const R=(t.noseSize??0)*o*x;return A+=a*n.width*R*.7,y+=(i-.02)*n.height*R*.5,y+=n.height*(t.noseLength??0)*o*x*Math.max(i+.08,0)*.4,w-=(t.noseSize??0)*o*x*.08,A+=a*n.width*(t.mouthWidth??0)*o*_,y+=(i-.29)*n.height*(t.mouthHeight??0)*o*_,r.x=A,r.y=y,r.z=w,r},ve=new Set([61,146,91,181,84,17,314,405,321,375,291,78,95,88,178,87,14,317,402,318,324,308,191,80,81,82,13,312,311,310,415]),Xe=[61,146,91,181,84,17,314,405,321,375,291,409,270,269,267,0,37,39,40,185],Te=new Set([33,7,163,144,145,153,154,155,133,173,157,158,159,160,161,246]),_e=new Set([362,382,381,380,374,373,390,249,263,466,388,387,386,385,384,398]),dn=new Set([814,815,816,817,818,819,830,831,832,833]),hn=(e,n,t)=>{const r=ve.has(e)&&ve.has(n)&&ve.has(t),o=Te.has(e)&&Te.has(n)&&Te.has(t),a=_e.has(e)&&_e.has(n)&&_e.has(t);return r?"mouth":o?"leftEye":a?"rightEye":"base"},mn=e=>{const n=new Map;for(let s=0;s<e.length;s+=3){const d=[e[s],e[s+1],e[s+2]];for(let h=0;h<3;h+=1){const l=d[h],x=d[(h+1)%3],_=l<x?`${l}:${x}`:`${x}:${l}`,D=n.get(_);D?D.count+=1:n.set(_,{a:l,b:x,count:1})}}const t=new Map;n.forEach(({a:s,b:d,count:h})=>{h===1&&(t.set(s,[...t.get(s)??[],d]),t.set(d,[...t.get(d)??[],s]))});const r=[...t.keys()].sort((s,d)=>s-d)[0];if(r===void 0)return[];const o=[r];let a=-1,i=r;for(;o.length<=t.size+1;){const s=(t.get(i)??[]).find(d=>d!==a);if(s===void 0||s===r)break;o.push(s),a=i,i=s}return o},qe=e=>{const n=[],t=[],r=[],o=[],a=[],i=[],s=[],d=[];let h=0,l=0;e.split(`
46
+ `).forEach(E=>{const f=E.trim();if(!f)return;if(f.startsWith("v ")){const[,b,R,v]=f.split(/\s+/);s.push([Number(b),Number(R),Number(v)]),h+=1;return}if(f.startsWith("vt ")){const[,b,R]=f.split(/\s+/);i.push([Number(b),Number(R)]);return}if(!f.startsWith("f "))return;const F=l;l+=1;const[,...H]=f.split(/\s+/),I=H.map(b=>{const[R,v]=b.split("/"),m=Number(R)-1,G=Number(v)-1;return G>=0&&i[G]&&!d[m]&&(d[m]=i[G]),m});if(!(I.length<3))for(let b=1;b<I.length-1;b+=1){const R=I[0],v=I[b],m=I[b+1],G=hn(R,v,m);dn.has(F)?a.push(R,v,m):G==="mouth"?t.push(R,v,m):G==="leftEye"?r.push(R,v,m):G==="rightEye"?o.push(R,v,m):n.push(R,v,m)}});const x=[];for(let E=0;E<h;E+=1){const[f,F]=d[E]??[0,0];x.push(f,F)}const _=new Uint16Array(r),D=new Uint16Array(o),C=new Uint16Array(r.length+o.length);C.set(_),C.set(D,_.length);const k=Xe.map(E=>{const[f,F]=s[E]??[0,0];return new p.Vector2(f,F)}),S=mn(t),$=S.map(E=>{const[f,F]=s[E]??[0,0];return new p.Vector2(f,F)}),A=p.ShapeUtils.triangulateShape(k,[$]),y=[...Xe,...S],w=new Uint16Array(S.length>2?A.flatMap(E=>E.map(f=>y[f])):[]);return{baseIndices:new Uint16Array(n),mouthIndices:new Uint16Array(t),lipIndices:w,leftEyeIndices:_,rightEyeIndices:D,eyeIndices:C,noseIndices:new Uint16Array(a),uvs:new Float32Array(x),vertexCount:h}},pn="canonical_face_model.obj",yn=new TextDecoder("utf-8"),Ce=new Map,En=e=>{const n=Ce.get(e);if(n)return n;const t=Q.fetchAndVerify(e).then(r=>qe(yn.decode(r))).catch(r=>{throw Ce.delete(e),r});return Ce.set(e,t),t},Qe=e=>{const{mesh:n,url:t}=e??{},r=t??`${Q.libConfig.sdkAssetsBaseUrl}/${pn}`,[o,a]=c.useState(n??null);return c.useEffect(()=>{if(n){a(n);return}let i=!1;return En(r).then(s=>{i||a(s)}).catch(s=>{i||console.error(`${Q.libConfig.loggerPrefix} canonical face mesh load failed`,s)}),()=>{i=!0}},[n,r]),o},T={basic:"basic",standard:"standard",physical:"physical",toon:"toon",normal:"normal",matcap:"matcap",wireframe:"wireframe",shader:"shader"},V={originalFace:"originalFace",composite:"composite"},X={none:"none",canonical:"canonical",style2:"style2"},q={none:"none",canonical:"canonical"},oe={solid:"solid",gradient:"gradient",imageUrl:"imageUrl",mediaUrl:"mediaUrl"},ne={front:"front",back:"back",double:"double"},Ie={normal:"normal",add:"add",subtract:"subtract",multiply:"multiply",screen:"screen",overlay:"overlay",softLight:"softLight",hardLight:"hardLight",lighten:"lighten",darken:"darken",difference:"difference",exclusion:"exclusion"},Mn={textureMap:X.canonical,alphaMap:q.canonical,alphaOpacity:1},We={...Mn,blendMode:Ie.hardLight,blendOpacity:.85,baseColor:"#ffffff",opacity:1,compositeShading:!0},N={materialType:T.basic,shaderPreset:V.originalFace,textureMap:X.none,alphaMap:q.none,alphaOpacity:1,side:ne.front,blendMode:Ie.normal,blendOpacity:1,baseColor:"#38bdf8",opacity:.45,compositeShading:!1};T.shader,V.composite,ne.front;const fe={mouth:!0,eyes:!0,nose:!0},re={textureSource:oe.solid,color:"#111111",opacity:.5},An=24,Ze=10,Le=(e,n,t)=>e!==T.shader?"none":n===V.originalFace?"originalFace":n===V.composite?t===X.none?"originalFace":"composite":"none",bn=(e,n)=>e===T.basic||e===T.standard||e===T.physical||e===T.toon||e===T.shader&&n===V.composite,gn=(e,n,t=X.canonical)=>Le(e,n,t)==="composite",xn=(e,n,t)=>Le(e,n,t)==="originalFace",me=e=>e===oe.imageUrl||e===oe.mediaUrl,Je=e=>e===oe.solid||e===oe.gradient,Ue={normal:0,add:1,subtract:2,multiply:3,screen:4,overlay:5,softLight:6,hardLight:7,lighten:8,darken:9,difference:10,exclusion:11},de="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8/x8AAwMCAO2YpZcAAAAASUVORK5CYII=",Rn=()=>{const e=new Uint8Array([32,32,32,255,96,96,96,255,176,176,176,255,255,255,255,255]),n=new p.DataTexture(e,4,1,p.RGBAFormat);return n.minFilter=p.NearestFilter,n.magFilter=p.NearestFilter,n.generateMipmaps=!1,n.needsUpdate=!0,n},Sn=()=>{const e=document.createElement("canvas");e.width=256,e.height=256;const n=e.getContext("2d");if(!n)return new p.CanvasTexture(e);const t=n.createRadialGradient(96,80,10,128,128,128);t.addColorStop(0,"#ffffff"),t.addColorStop(.18,"#f7d794"),t.addColorStop(.45,"#d97706"),t.addColorStop(.72,"#78350f"),t.addColorStop(1,"#120701"),n.fillStyle=t,n.fillRect(0,0,e.width,e.height);const r=new p.CanvasTexture(e);return r.needsUpdate=!0,r},vn=`
47
+ attribute vec2 faceUv;
48
+ varying vec2 vUv;
49
+ varying vec2 vFaceUv;
50
+ varying vec3 vNormal;
51
+
52
+ void main() {
53
+ vUv = uv;
54
+ vFaceUv = faceUv;
55
+ vNormal = normalize(normalMatrix * normal);
56
+ gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
57
+ }
58
+ `,Tn=`
59
+ uniform sampler2D cameraTexture;
60
+ uniform sampler2D canonicalTexture;
61
+ uniform sampler2D alphaMask;
62
+ uniform vec3 textureTint;
63
+ uniform float opacity;
64
+ uniform int blendMode;
65
+ uniform float blendOpacity;
66
+ uniform float useCanonicalTexture;
67
+ uniform float useAlphaMask;
68
+ uniform float alphaOpacity;
69
+ uniform float compositeShading;
70
+ uniform vec3 lightDirection;
71
+ uniform float ambientStrength;
72
+ uniform float directionalStrength;
73
+ varying vec2 vUv;
74
+ varying vec2 vFaceUv;
75
+ varying vec3 vNormal;
76
+
77
+ vec3 linearToSrgb(vec3 value) {
78
+ vec3 low = value * 12.92;
79
+ vec3 high = 1.055 * pow(max(value, vec3(0.0)), vec3(1.0 / 2.4)) - 0.055;
80
+ return mix(high, low, step(value, vec3(0.0031308)));
81
+ }
82
+
83
+ vec3 srgbToLinear(vec3 value) {
84
+ vec3 low = value / 12.92;
85
+ vec3 high = pow(max((value + 0.055) / 1.055, vec3(0.0)), vec3(2.4));
86
+ return mix(high, low, step(value, vec3(0.04045)));
87
+ }
88
+
89
+ float overlayChannel(float base, float blend) {
90
+ return base < 0.5 ? 2.0 * base * blend : 1.0 - 2.0 * (1.0 - base) * (1.0 - blend);
91
+ }
92
+
93
+ float hardLightChannel(float base, float blend) {
94
+ return blend < 0.5 ? 2.0 * base * blend : 1.0 - 2.0 * (1.0 - base) * (1.0 - blend);
95
+ }
96
+
97
+ float softLightChannel(float base, float blend) {
98
+ if (blend <= 0.5) {
99
+ return base - (1.0 - 2.0 * blend) * base * (1.0 - base);
100
+ }
101
+
102
+ float d = base <= 0.25
103
+ ? ((16.0 * base - 12.0) * base + 4.0) * base
104
+ : sqrt(base);
105
+
106
+ return base + (2.0 * blend - 1.0) * (d - base);
107
+ }
108
+
109
+ vec3 applyBlendMode(vec3 base, vec3 blend, int mode) {
110
+ if (mode == 0) return blend;
111
+ if (mode == 1) return min(base + blend, 1.0);
112
+ if (mode == 2) return max(base - blend, 0.0);
113
+ if (mode == 3) return base * blend;
114
+ if (mode == 4) return 1.0 - (1.0 - base) * (1.0 - blend);
115
+ if (mode == 5) {
116
+ return vec3(
117
+ overlayChannel(base.r, blend.r),
118
+ overlayChannel(base.g, blend.g),
119
+ overlayChannel(base.b, blend.b)
120
+ );
121
+ }
122
+ if (mode == 6) {
123
+ return vec3(
124
+ softLightChannel(base.r, blend.r),
125
+ softLightChannel(base.g, blend.g),
126
+ softLightChannel(base.b, blend.b)
127
+ );
128
+ }
129
+ if (mode == 7) {
130
+ return vec3(
131
+ hardLightChannel(base.r, blend.r),
132
+ hardLightChannel(base.g, blend.g),
133
+ hardLightChannel(base.b, blend.b)
134
+ );
135
+ }
136
+ if (mode == 8) return max(base, blend);
137
+ if (mode == 9) return min(base, blend);
138
+ if (mode == 10) return abs(base - blend);
139
+ return base + blend - 2.0 * base * blend;
140
+ }
141
+
142
+ void main() {
143
+ vec3 base = linearToSrgb(texture2D(cameraTexture, vFaceUv).rgb);
144
+ vec4 textureSample = texture2D(canonicalTexture, vUv);
145
+ vec3 blend = linearToSrgb(textureSample.rgb) * textureTint;
146
+ float light = ambientStrength + max(dot(normalize(vNormal), normalize(lightDirection)), 0.0) * directionalStrength;
147
+ blend *= mix(1.0, clamp(light, 0.35, 1.35), compositeShading);
148
+ float maskSample = texture2D(alphaMask, vUv).r;
149
+ float mask = useAlphaMask > 0.5 ? mix(1.0, maskSample, alphaOpacity) : 1.0;
150
+ float textureAlpha = useCanonicalTexture > 0.5 ? textureSample.a : 1.0;
151
+ vec3 blended = applyBlendMode(base, blend, blendMode);
152
+ vec3 color = useCanonicalTexture > 0.5 ? mix(base, blended, blendOpacity) : base;
153
+ gl_FragColor = vec4(srgbToLinear(color), opacity * mask * textureAlpha);
154
+ }
155
+ `,et=({alphaMap:e,alphaOpacity:n,blendMode:t,blendOpacity:r,cameraTexture:o,color:a,compositeShading:i,faceAlphaMaskUrl:s,faceTextureStyle2Url:d,faceTextureUrl:h,masked:l=!1,maskColor:x,maskOpacity:_,maskSourceUrl:D,maskTextureSource:C,materialType:k,opacity:S,shaderPreset:$,side:A,textureMap:y})=>{const w=te.useLoader(p.TextureLoader,h||de),E=te.useLoader(p.TextureLoader,d||h||de),f=te.useLoader(p.TextureLoader,s||de),F=c.useMemo(()=>Rn(),[]),H=c.useMemo(()=>Sn(),[]);c.useEffect(()=>()=>{F.dispose(),H.dispose()},[H,F]);const I=y===X.style2?E:w,b=y!==X.none,R=Le(k,$,y),v=["composite-material",y,e,n,t,r,i?"lit":"flat",a,S,h,d,s].join("|"),m={side:A,transparent:!0,opacity:S,wireframe:!1},G=c.useMemo(()=>({source:me(C)?"texture":C,color:Je(C)?x:"#ffffff",opacity:_,textureUrl:me(C)?D:"",gradient:we(x)}),[x,_,D,C]),U=c.useMemo(()=>({cameraTexture:{value:null},canonicalTexture:{value:null},alphaMask:{value:null},textureTint:{value:new p.Color(a)},opacity:{value:S},blendMode:{value:Ue[t]},blendOpacity:{value:r},useCanonicalTexture:{value:b?1:0},useAlphaMask:{value:e===q.canonical?1:0},alphaOpacity:{value:n},compositeShading:{value:i?1:0},lightDirection:{value:new p.Vector3(.3,.65,.7).normalize()},ambientStrength:{value:.78},directionalStrength:{value:.38}}),[e,n,t,r,a,i,b,S]);if(c.useEffect(()=>{U.cameraTexture.value=o??w,U.canonicalTexture.value=I,U.alphaMask.value=f,U.textureTint.value.set(a),U.opacity.value=S,U.blendMode.value=Ue[t],U.blendOpacity.value=r,U.useCanonicalTexture.value=b?1:0,U.useAlphaMask.value=e===q.canonical?1:0,U.alphaOpacity.value=n,U.compositeShading.value=i?1:0},[e,f,n,t,r,o,a,i,U,w,b,S,I]),l)return u.jsx(Ke,{settings:G,side:A},`masked-${C}-material`);if(k===T.wireframe)return u.jsx("meshBasicMaterial",{color:a,transparent:!0,opacity:S,side:A,depthWrite:!1,depthTest:!1,wireframe:!0,toneMapped:!1},"wireframe-material");if(R==="originalFace"&&o)return u.jsx("meshBasicMaterial",{map:o,alphaMap:f,transparent:!0,opacity:S,side:A,depthWrite:!1,depthTest:!0,toneMapped:!1},"use-original-face-material");if(R==="composite"&&o)return u.jsx("shaderMaterial",{uniforms:U,vertexShader:vn,fragmentShader:Tn,transparent:!0,side:A,depthWrite:!1,depthTest:!0,toneMapped:!1},v);const Z=b?I:null,K=e===q.canonical&&n>0?f:null,W=`${k}-${y}-${e}-${n>0?"alpha-on":"alpha-off"}`;return k===T.standard?u.jsx("meshStandardMaterial",{...m,color:a,map:Z??void 0,alphaMap:K??void 0,depthWrite:!0,depthTest:!0,metalness:.05,roughness:.72},W):k===T.physical?u.jsx("meshPhysicalMaterial",{...m,color:a,map:Z??void 0,alphaMap:K??void 0,depthWrite:!0,depthTest:!0,roughness:.58,metalness:.08,clearcoat:.35,clearcoatRoughness:.4},W):k===T.toon?u.jsx("meshToonMaterial",{...m,color:a,map:Z??void 0,alphaMap:K??void 0,gradientMap:F,depthWrite:!0,depthTest:!0},W):k===T.normal?u.jsx("meshNormalMaterial",{...m,depthWrite:!0,depthTest:!0,flatShading:!1},"normal-material"):k===T.matcap?u.jsx("meshMatcapMaterial",{...m,color:a,matcap:H,depthWrite:!0,depthTest:!0},"matcap-material"):u.jsx("meshBasicMaterial",{...m,color:a,map:Z??void 0,alphaMap:K??void 0,depthWrite:!1,depthTest:y!==X.none||e!==q.none,toneMapped:!1},W)},tt=[{key:"base",getIndices:e=>e.baseIndices,masked:!1,renderOrderOffset:0},{key:"mouth",getIndices:e=>e.mouthIndices,masked:!1,renderOrderOffset:2},{key:"lips",getIndices:e=>e.lipIndices,masked:!1,renderOrderOffset:3},{key:"left-eye",getIndices:e=>e.leftEyeIndices,masked:!1,renderOrderOffset:2},{key:"right-eye",getIndices:e=>e.rightEyeIndices,masked:!1,renderOrderOffset:2},{key:"nose",getIndices:e=>e.noseIndices,masked:!1,renderOrderOffset:2},{key:"mouth-mask",getIndices:e=>e.mouthIndices,masked:!0,renderOrderOffset:3},{key:"left-eye-mask",getIndices:e=>e.leftEyeIndices,masked:!0,renderOrderOffset:3},{key:"right-eye-mask",getIndices:e=>e.rightEyeIndices,masked:!0,renderOrderOffset:3},{key:"nose-mask",getIndices:e=>e.noseIndices,masked:!0,renderOrderOffset:3}],_n={[ne.front]:p.FrontSide,[ne.back]:p.BackSide,[ne.double]:p.DoubleSide},Cn=(e,n,t)=>{e.setAttribute("position",n.position),e.setAttribute("uv",n.uv),e.setAttribute("faceUv",n.faceUv),e.setIndex(new p.BufferAttribute(t,1))},nt=({faceIndex:e=0,baseColor:n,color:t=N.baseColor,opacity:r=N.opacity,materialType:o=N.materialType,shaderPreset:a=N.shaderPreset,textureMap:i=N.textureMap,alphaMap:s=N.alphaMap,alphaOpacity:d=N.alphaOpacity,side:h=N.side,blendMode:l=N.blendMode,blendOpacity:x=N.blendOpacity,showOverlayMask:_=!1,showMouthMask:D=fe.mouth,showEyeMask:C=fe.eyes,showLeftEyeMask:k,showRightEyeMask:S,showNoseMask:$=fe.nose,showEyeGeometry:A=!0,showLeftEyeGeometry:y,showRightEyeGeometry:w,showMouthGeometry:E=!0,showLipsGeometry:f=!1,showBaseGeometry:F=!0,showNoseGeometry:H=!0,maskTextureSource:I=re.textureSource,maskSourceUrl:b="",maskColor:R=re.color,maskOpacity:v=re.opacity,faceTextureUrl:m="",faceTextureStyle2Url:G="",faceAlphaMaskUrl:U="",compositeShading:Z=!1,faceWarp3D:K,transform:W,renderOrder:lt=Ze,externalScale:pe=1,mesh:ut,meshUrl:ft,materialOverride:se})=>{const ye=Ve.useXRModelNode(Q.XRModel.FACE_TRACKER),Oe=Ve.useXRCameraTexture(),{camera:dt}=te.useThree(),j=Qe({mesh:ut,url:ft}),De=c.useRef(null),ht=c.useRef(null),mt=c.useRef(null),pt=c.useRef(null),yt=c.useRef(null),Et=c.useRef(null),Mt=c.useRef(null),At=c.useRef(null),bt=c.useRef(null),gt=c.useRef(null),xt=c.useRef(null),Rt=c.useRef(null),St=c.useRef(null),vt=c.useRef(null),Tt=c.useRef(null),_t=c.useRef(null),Ct=c.useRef(null),Ft=c.useRef(null),kt=c.useRef(null),Ut=c.useRef(null),Ee=c.useRef(null),Me=c.useRef(null),Ae=c.useRef(null),Pe=c.useRef(null),wt=c.useRef(new p.Vector3),It=c.useRef({x:0,y:0,z:0}),Lt=c.useRef({x:0,y:0,z:0}),Ot=c.useRef({x:0,y:0,z:0}),ie=c.useRef(!1),Dt=_n[h],Pt=n??t,Nt=y??A,Gt=w??A,Ht=_||(k??C),jt=_||(S??C),zt=_||D,Bt=_||$,Vt={base:De,mouth:ht,lips:mt,"left-eye":pt,"right-eye":yt,nose:Et,"mouth-mask":Mt,"left-eye-mask":At,"right-eye-mask":bt,"nose-mask":gt},Xt={base:xt,mouth:Rt,lips:St,"left-eye":vt,"right-eye":Tt,nose:_t,"mouth-mask":Ct,"left-eye-mask":Ft,"right-eye-mask":kt,"nose-mask":Ut},Wt={base:F,mouth:E,lips:f,"left-eye":Nt,"right-eye":Gt,nose:H,"mouth-mask":zt,"left-eye-mask":Ht,"right-eye-mask":jt,"nose-mask":Bt},Yt=g=>u.jsx(et,{alphaMap:s,alphaOpacity:d,blendMode:l,blendOpacity:x,cameraTexture:Oe,color:Pt,compositeShading:Z,faceAlphaMaskUrl:U,faceTextureStyle2Url:G,faceTextureUrl:m,masked:g,maskColor:R,maskOpacity:v,maskSourceUrl:b,maskTextureSource:I,materialType:o,opacity:r,shaderPreset:a,side:Dt,textureMap:i}),J=tt.map(g=>({...g,geometryRef:Vt[g.key],meshRef:Xt[g.key],visible:Wt[g.key]})),$t=g=>Fe.projectLandmarkWithDepth(g,dt,wt.current);return te.useFrame(()=>{var je,ze;const g=De.current,z=(ze=(je=ye==null?void 0:ye.detectionResults)==null?void 0:je.faceLandmarks)==null?void 0:ze[e],Kt=J.every(M=>M.geometryRef.current&&M.meshRef.current);if(!j||!g||!Kt)return;if(!z||z.length<j.vertexCount){J.forEach(M=>{M.meshRef.current.visible=!1});return}if(Pe.current!==j){Ee.current=new Float32Array(j.vertexCount*3),Me.current=new Float32Array(j.uvs),Ae.current=new Float32Array(j.vertexCount*2);const M={position:new p.BufferAttribute(Ee.current,3),uv:new p.BufferAttribute(Me.current,2),faceUv:new p.BufferAttribute(Ae.current,2)};J.forEach(L=>{Cn(L.geometryRef.current,M,L.getIndices(j))}),M.uv.needsUpdate=!0,Pe.current=j,ie.current=!1}const ce=Ee.current,be=Ae.current,le=Me.current;if(!ce||!be||!le)return;const Ne=xn(o,a,i),Ge=un(K),He=Ge?ln(z):null,P=W?Ot.current:null;if(P){P.x=0,P.y=0,P.z=0;for(let M=0;M<z.length;M++){const L=z[M];P.x+=L.x,P.y+=L.y,P.z+=L.z}P.x/=z.length,P.y/=z.length,P.z/=z.length}const qt=Math.min(z.length,j.vertexCount);for(let M=0;M<qt;M++){const L=z[M],Be=Ge&&He?fn(L,He,K,It.current):L,Qt=W&&P?Fe.transformFaceMeshLandmark(Be,P,W,Lt.current):Be,ge=M*3,ue=M*2,xe=$t(Qt);ce[ge]=xe.x,ce[ge+1]=xe.y,ce[ge+2]=xe.z,be[ue]=L.x,be[ue+1]=1-L.y,Ne&&(le[ue]=L.x,le[ue+1]=1-L.y)}Ne?(g.attributes.uv.needsUpdate=!0,ie.current=!0):ie.current&&(le.set(j.uvs),g.attributes.uv.needsUpdate=!0,ie.current=!1),J.forEach(M=>{M.meshRef.current.visible=M.visible}),g.attributes.position.needsUpdate=!0,g.attributes.faceUv.needsUpdate=!0,J.forEach(M=>{M.geometryRef.current.computeVertexNormals()})}),u.jsx("group",{scale:[pe,pe,pe],children:J.map(g=>u.jsxs("mesh",{ref:g.meshRef,renderOrder:lt+g.renderOrderOffset,frustumCulled:!1,children:[u.jsx("bufferGeometry",{ref:g.geometryRef}),se?typeof se=="function"?se({cameraTexture:Oe??null,geometryKey:g.key}):se:Yt(g.masked)]},g.key))})},rt=`${Q.libConfig.sdkAssetsBaseUrl}/Canonical_Face_Color.png`,ot=`${Q.libConfig.sdkAssetsBaseUrl}/Canonical_Face_Color_style_2.png`,at=`${Q.libConfig.sdkAssetsBaseUrl}/Canonical_Face_Color_Mask.png`,st={...ke,position:{...ke.position,y:.001}},Fn={enabled:!0,faceIndex:0,targetFps:An,...N,showLeftEyeGeometry:!0,showRightEyeGeometry:!0,showMouthGeometry:!0,showNoseGeometry:!0,externalScale:1,showOverlayMask:!1,showMouthMask:!1,showLeftEyeMask:!1,showRightEyeMask:!1,showNoseMask:!1,maskTextureSource:re.textureSource,maskSourceUrl:"",maskColor:re.color,maskOpacity:re.opacity,faceTextureUrl:rt,faceTextureStyle2Url:ot,faceAlphaMaskUrl:at,renderOrder:Ze},it=e=>{const{externalMeshUrl:n,...t}=e;return{...t,color:t.baseColor,meshUrl:n}},ct=({materialOverride:e,value:n})=>({...it(n),materialOverride:e}),kn=(e,n)=>{const t={...e,...n};return n.maskTextureSource&&!me(n.maskTextureSource)&&(t.maskSourceUrl=""),t.materialType===T.shader&&n.shaderPreset===V.composite?{...t,...We,materialType:T.shader,shaderPreset:V.composite}:t.materialType===T.shader&&t.shaderPreset===V.composite&&t.textureMap===X.none?{...t,textureMap:We.textureMap}:t},Un=({transform:e,value:n,materialOverride:t})=>n.enabled?u.jsxs(u.Fragment,{children:[u.jsx(Fe.FaceTracker,{active:n.enabled,faceIndex:n.faceIndex,numFaces:n.faceIndex+1,targetFps:n.targetFps}),u.jsx(nt,{...ct({value:n,materialOverride:t}),transform:e??st})]}):null;exports.CANONICAL_FACE_MESH_GEOMETRY_SPECS=tt;exports.CanonicalFaceMeshRenderer=nt;exports.DEFAULT_APPEARANCE=N;exports.DEFAULT_FACE_MESH_RENDERER=Fn;exports.DEFAULT_FACE_MESH_TRANSFORM=st;exports.DEFAULT_MASKING=fe;exports.DEFAULT_MATERIAL_FILL=an;exports.DEFAULT_SCREEN_GRADIENT=Y;exports.DEFAULT_TRANSFORM_3D=ke;exports.FACE_MESH_ALPHA_MAPS=q;exports.FACE_MESH_BLEND_MODES=Ie;exports.FACE_MESH_MASK_TEXTURE_SOURCES=oe;exports.FACE_MESH_MATERIAL_TYPES=T;exports.FACE_MESH_SHADER_PRESETS=V;exports.FACE_MESH_SIDES=ne;exports.FACE_MESH_TEXTURE_MAPS=X;exports.FaceMeshMaterial=et;exports.FaceMeshRenderer=Un;exports.MAX_SCREEN_GRADIENT_STOPS=he;exports.MaterialFill=Ke;exports.ScreenGradientMaterial=$e;exports.TRANSPARENT_TEXTURE_DATA_URL=de;exports.Transform3D=cn;exports.blendModeIndices=Ue;exports.canonicalFaceAlphaMaskUrl=at;exports.canonicalFaceTextureStyle2Url=ot;exports.canonicalFaceTextureUrl=rt;exports.createTwoStopGradient=we;exports.mapFaceMeshRendererProps=ct;exports.mapFaceMeshRendererSettingsToProps=it;exports.normalizeScreenGradient=Ye;exports.parseCanonicalFaceModel=qe;exports.resolveFaceMeshRendererSettings=kn;exports.supportsBlendMode=gn;exports.supportsTexturePanel=bn;exports.useCanonicalFaceMesh=Qe;exports.usesMaskColor=Je;exports.usesMaskSourceUrl=me;