talking-head-studio 0.4.11 → 0.4.12

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 (142) hide show
  1. package/README.md +279 -193
  2. package/dist/TalkingHead.d.ts +28 -3
  3. package/dist/TalkingHead.js +21 -2
  4. package/dist/TalkingHead.web.d.ts +31 -4
  5. package/dist/TalkingHead.web.js +11 -1
  6. package/dist/TalkingHeadVisualization.d.ts +22 -0
  7. package/dist/TalkingHeadVisualization.js +30 -10
  8. package/dist/api/studioApi.d.ts +12 -1
  9. package/dist/api/studioApi.js +16 -2
  10. package/dist/contract.d.ts +14 -0
  11. package/dist/contract.js +30 -0
  12. package/dist/core/avatar/avatarCapabilities.d.ts +60 -0
  13. package/dist/core/avatar/avatarCapabilities.js +100 -0
  14. package/dist/core/avatar/backends/gaussian.js +6 -4
  15. package/dist/core/avatar/motion.d.ts +1713 -0
  16. package/dist/core/avatar/motion.js +550 -0
  17. package/dist/core/avatar/motionRuntime.d.ts +46 -0
  18. package/dist/core/avatar/motionRuntime.js +84 -0
  19. package/dist/core/avatar/schema.d.ts +33 -5
  20. package/dist/core/avatar/visemes.d.ts +16 -1
  21. package/dist/core/avatar/visemes.js +48 -1
  22. package/dist/editor/AvatarCanvas.js +92 -1
  23. package/dist/editor/AvatarEditor.native.js +1 -0
  24. package/dist/editor/AvatarModel.js +1 -0
  25. package/dist/editor/FaceSqueezeEditor.d.ts +3 -1
  26. package/dist/editor/FaceSqueezeEditor.js +176 -112
  27. package/dist/editor/FaceSqueezeEditor.web.d.ts +3 -1
  28. package/dist/editor/FaceSqueezeEditor.web.js +30 -28
  29. package/dist/editor/RigidAccessory.js +17 -2
  30. package/dist/editor/SkinnedClothing.js +1 -0
  31. package/dist/editor/boneLockedDrag.d.ts +11 -0
  32. package/dist/editor/boneLockedDrag.js +68 -0
  33. package/dist/editor/boneSnap.web.d.ts +27 -0
  34. package/dist/editor/boneSnap.web.js +99 -0
  35. package/dist/editor/index.web.d.ts +10 -0
  36. package/dist/editor/index.web.js +26 -0
  37. package/dist/editor/sounds/haha.wav +0 -0
  38. package/dist/editor/sounds/owie.wav +0 -0
  39. package/dist/editor/sounds/stop.wav +0 -0
  40. package/dist/editor/studioTheme.d.ts +14 -14
  41. package/dist/editor/studioTheme.js +17 -14
  42. package/dist/editor/types.d.ts +1 -0
  43. package/dist/html/accessories.d.ts +7 -0
  44. package/dist/html/accessories.js +149 -0
  45. package/dist/html/motion.d.ts +1 -0
  46. package/dist/html/motion.js +189 -0
  47. package/dist/html/visemes.d.ts +7 -0
  48. package/dist/html/visemes.js +348 -0
  49. package/dist/html.d.ts +1 -1
  50. package/dist/html.js +55 -732
  51. package/dist/index.d.ts +7 -3
  52. package/dist/index.js +17 -1
  53. package/dist/index.web.d.ts +18 -1
  54. package/dist/index.web.js +36 -3
  55. package/dist/sketchfab/api.js +1 -0
  56. package/dist/sketchfab/glbInspect.d.ts +22 -0
  57. package/dist/sketchfab/glbInspect.js +58 -0
  58. package/dist/sketchfab/index.d.ts +3 -0
  59. package/dist/sketchfab/index.js +8 -1
  60. package/dist/sketchfab/inspectRemote.d.ts +13 -0
  61. package/dist/sketchfab/inspectRemote.js +77 -0
  62. package/dist/sketchfab/types.d.ts +10 -0
  63. package/dist/studio/AccessoryBrowserScreen.d.ts +6 -0
  64. package/dist/studio/AccessoryBrowserScreen.js +626 -0
  65. package/dist/studio/AccessoryPanel.d.ts +10 -0
  66. package/dist/studio/AccessoryPanel.js +396 -0
  67. package/dist/studio/AppearancePanel.d.ts +9 -0
  68. package/dist/studio/AppearancePanel.js +77 -0
  69. package/dist/studio/AvatarCreatorScreen.d.ts +5 -0
  70. package/dist/studio/AvatarCreatorScreen.js +806 -0
  71. package/dist/studio/AvatarEditorScreen.d.ts +14 -0
  72. package/dist/studio/AvatarEditorScreen.js +510 -0
  73. package/dist/studio/AvatarGrid.d.ts +23 -0
  74. package/dist/studio/AvatarGrid.js +257 -0
  75. package/dist/studio/ColorSwatch.d.ts +8 -0
  76. package/dist/studio/ColorSwatch.js +100 -0
  77. package/dist/studio/CreateVoiceProfileSheet.d.ts +8 -0
  78. package/dist/studio/CreateVoiceProfileSheet.js +242 -0
  79. package/dist/studio/DetailsPanel.d.ts +15 -0
  80. package/dist/studio/DetailsPanel.js +239 -0
  81. package/dist/studio/FilamentEditor.d.ts +2 -0
  82. package/dist/studio/FilamentEditor.js +6 -0
  83. package/dist/studio/PrecisionPanel.d.ts +2 -0
  84. package/dist/studio/PrecisionPanel.js +7 -0
  85. package/dist/studio/PublicGalleryScreen.d.ts +5 -0
  86. package/dist/studio/PublicGalleryScreen.js +358 -0
  87. package/dist/studio/SketchfabModelCard.d.ts +20 -0
  88. package/dist/studio/SketchfabModelCard.js +104 -0
  89. package/dist/studio/StudioBrowseHeader.d.ts +9 -0
  90. package/dist/studio/StudioBrowseHeader.js +28 -0
  91. package/dist/studio/StudioEmptyState.d.ts +8 -0
  92. package/dist/studio/StudioEmptyState.js +29 -0
  93. package/dist/studio/StudioFloatingAction.d.ts +13 -0
  94. package/dist/studio/StudioFloatingAction.js +42 -0
  95. package/dist/studio/StudioSectionHeader.d.ts +7 -0
  96. package/dist/studio/StudioSectionHeader.js +27 -0
  97. package/dist/studio/StudioSurfaceCard.d.ts +8 -0
  98. package/dist/studio/StudioSurfaceCard.js +20 -0
  99. package/dist/studio/VoicePanel.d.ts +15 -0
  100. package/dist/studio/VoicePanel.js +305 -0
  101. package/dist/studio/constants.d.ts +3 -0
  102. package/dist/studio/constants.js +6 -0
  103. package/dist/studio/index.d.ts +29 -0
  104. package/dist/studio/index.js +54 -0
  105. package/dist/studio/useSketchfabCapabilities.d.ts +31 -0
  106. package/dist/studio/useSketchfabCapabilities.js +82 -0
  107. package/dist/tts/useDirectVisemeStream.js +15 -10
  108. package/dist/utils/avatarUtils.js +92 -5
  109. package/dist/utils/faceLandmarkerToShapeWeights.js +2 -4
  110. package/dist/voice/useAudioPlayer.js +17 -4
  111. package/dist/voice/useVoicePreview.js +4 -2
  112. package/dist/wardrobe/index.d.ts +1 -0
  113. package/dist/wardrobe/index.js +6 -1
  114. package/dist/wardrobe/useAccessoryGestures.d.ts +20 -0
  115. package/dist/wardrobe/useAccessoryGestures.js +94 -0
  116. package/dist/wardrobe/useAvatarWardrobeHydration.js +8 -2
  117. package/dist/wardrobe/useStudioAvatar.js +11 -2
  118. package/dist/wardrobe/wardrobeStore.d.ts +2 -0
  119. package/dist/wardrobe/wardrobeStore.js +12 -2
  120. package/dist/wgpu/R3FWebGpuCanvas.d.ts +15 -0
  121. package/dist/wgpu/R3FWebGpuCanvas.js +176 -0
  122. package/dist/wgpu/WgpuAvatar.d.ts +26 -2
  123. package/dist/wgpu/WgpuAvatar.js +296 -39
  124. package/dist/wgpu/accessoryDefaults.d.ts +12 -0
  125. package/dist/wgpu/accessoryDefaults.js +19 -0
  126. package/dist/wgpu/blobShim.d.ts +2 -0
  127. package/dist/wgpu/blobShim.js +191 -0
  128. package/dist/wgpu/index.d.ts +1 -0
  129. package/dist/wgpu/index.js +4 -1
  130. package/dist/wgpu/loadGLTFFromUri.d.ts +2 -0
  131. package/dist/wgpu/loadGLTFFromUri.js +75 -0
  132. package/dist/wgpu/morphTables.js +21 -10
  133. package/dist/wgpu/motionState.d.ts +20 -0
  134. package/dist/wgpu/motionState.js +31 -0
  135. package/dist/wgpu/patchThreeForRN.d.ts +28 -0
  136. package/dist/wgpu/patchThreeForRN.js +292 -0
  137. package/dist/wgpu/scenePlacement.d.ts +5 -0
  138. package/dist/wgpu/scenePlacement.js +50 -0
  139. package/dist/wgpu/useAuthedModelUri.js +4 -2
  140. package/dist/wgpu/useNativeGLTF.d.ts +7 -0
  141. package/dist/wgpu/useNativeGLTF.js +36 -0
  142. package/package.json +97 -31
@@ -1,5 +1,7 @@
1
1
  import type { OculusViseme } from './visemes';
2
- export type VísemeTier = 'oculus' | 'arkit' | 'minimal' | 'none';
2
+ export type VisemeTier = 'oculus' | 'arkit' | 'minimal' | 'none';
3
+ /** @deprecated Use VisemeTier. */
4
+ export type VísemeTier = VisemeTier;
3
5
  export interface MorphCoverage {
4
6
  /** All morph target names found across all meshes in the scene. */
5
7
  all: string[];
@@ -12,7 +14,7 @@ export interface MorphCoverage {
12
14
  /** Whether a meaningful ARKit set is present (≥10 mouth shapes). */
13
15
  hasArkitSet: boolean;
14
16
  /** Best lip-sync strategy available for this model. */
15
- visemeTier: VísemeTier;
17
+ visemeTier: VisemeTier;
16
18
  }
17
19
  export interface SkeletonInfo {
18
20
  /** Whether a skeleton (SkinnedMesh) was found. */
@@ -39,12 +41,38 @@ export interface AvatarSchemaReport {
39
41
  /** Whether this model is ready for full-quality talking-head rendering. */
40
42
  isReadyForLipSync: boolean;
41
43
  }
44
+ /** Minimal scene shape needed by the GLB schema walker. */
45
+ interface AvatarSchemaScene {
46
+ traverse: (cb: (obj: AvatarSchemaObject) => void) => void;
47
+ }
48
+ /** Minimal traversed object shape used to avoid depending on runtime Three.js classes. */
49
+ interface AvatarSchemaObject {
50
+ isSkinnedMesh?: boolean;
51
+ isBone?: boolean;
52
+ isMesh?: boolean;
53
+ name?: string;
54
+ skeleton?: {
55
+ bones?: Array<{
56
+ name?: string;
57
+ }>;
58
+ };
59
+ morphTargetDictionary?: Record<string, unknown>;
60
+ geometry?: {
61
+ index?: {
62
+ count: number;
63
+ };
64
+ attributes?: {
65
+ position?: {
66
+ count: number;
67
+ };
68
+ };
69
+ };
70
+ }
42
71
  /**
43
72
  * Scan a loaded Three.js Object3D scene and return a structured compatibility
44
73
  * report for lip-sync, skeleton, and mesh quality.
45
74
  *
46
75
  * @param scene - The root Object3D from a GLTFLoader result (gltf.scene)
47
76
  */
48
- export declare function walkAvatarSchema(scene: {
49
- traverse: (cb: (obj: any) => void) => void;
50
- }): AvatarSchemaReport;
77
+ export declare function walkAvatarSchema(scene: AvatarSchemaScene): AvatarSchemaReport;
78
+ export {};
@@ -2,11 +2,12 @@
2
2
  * Standard viseme keys supported by the avatar (Oculus set).
3
3
  */
4
4
  export type OculusViseme = 'sil' | 'PP' | 'FF' | 'TH' | 'DD' | 'kk' | 'CH' | 'SS' | 'nn' | 'RR' | 'aa' | 'ee' | 'ih' | 'oh' | 'ou';
5
+ export type RhubarbViseme = 'A' | 'B' | 'C' | 'D' | 'E' | 'F' | 'G' | 'H' | 'X';
5
6
  /** Rhubarb mouth shape cue (Preston Blair set: A-H, X) */
6
7
  export interface VisemeCue {
7
8
  startMs: number;
8
9
  endMs: number;
9
- viseme: 'A' | 'B' | 'C' | 'D' | 'E' | 'F' | 'G' | 'H' | 'X';
10
+ viseme: RhubarbViseme;
10
11
  weight?: number;
11
12
  }
12
13
  /**
@@ -31,6 +32,10 @@ export interface AgentVisemePayload {
31
32
  cues: VisemeCue[];
32
33
  }
33
34
  export declare const OCULUS_VISEMES: OculusViseme[];
35
+ export declare const RHUBARB_VISEMES: RhubarbViseme[];
36
+ export declare const OCULUS_MORPH_TARGET_NAMES: Record<OculusViseme, string>;
37
+ export type OculusVisemeWeights = Partial<Record<OculusViseme, number>>;
38
+ export declare const RHUBARB_TO_OCULUS: Record<RhubarbViseme, OculusVisemeWeights>;
34
39
  export type ArkitBlendShape = 'jawOpen' | 'jawForward' | 'jawLeft' | 'jawRight' | 'mouthClose' | 'mouthFunnel' | 'mouthPucker' | 'mouthLeft' | 'mouthRight' | 'mouthSmileLeft' | 'mouthSmileRight' | 'mouthFrownLeft' | 'mouthFrownRight' | 'mouthDimpleLeft' | 'mouthDimpleRight' | 'mouthStretchLeft' | 'mouthStretchRight' | 'mouthRollLower' | 'mouthRollUpper' | 'mouthShrugLower' | 'mouthShrugUpper' | 'mouthPressLeft' | 'mouthPressRight' | 'mouthLowerDownLeft' | 'mouthLowerDownRight' | 'mouthUpperUpLeft' | 'mouthUpperUpRight' | 'tongueOut';
35
40
  /**
36
41
  * Each Oculus viseme expressed as a weighted combination of ARKit blend shapes.
@@ -41,6 +46,16 @@ export type ArkitBlendShape = 'jawOpen' | 'jawForward' | 'jawLeft' | 'jawRight'
41
46
  * - Empirical tuning against RPM and face-squeeze avatars
42
47
  */
43
48
  export declare const ARKIT_TO_OCULUS: Record<OculusViseme, Partial<Record<ArkitBlendShape, number>>>;
49
+ export type EngineVisemeMappingArtifact = {
50
+ schemaVersion: 1;
51
+ rhubarbVisemes: RhubarbViseme[];
52
+ oculusVisemes: OculusViseme[];
53
+ oculusMorphTargetNames: Record<OculusViseme, string>;
54
+ rhubarbToOculus: Record<RhubarbViseme, OculusVisemeWeights>;
55
+ oculusToArkit: Record<OculusViseme, Partial<Record<ArkitBlendShape, number>>>;
56
+ };
57
+ export declare const ENGINE_VISEME_MAPPING: EngineVisemeMappingArtifact;
58
+ export declare function oculusWeightsForRhubarbCue(cue: Pick<VisemeCue, 'viseme' | 'weight'>): Record<OculusViseme, number>;
44
59
  /**
45
60
  * Remap a set of ARKit blend shape weights to Oculus viseme weights.
46
61
  *
@@ -1,11 +1,41 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ARKIT_TO_OCULUS = exports.OCULUS_VISEMES = void 0;
3
+ exports.ENGINE_VISEME_MAPPING = exports.ARKIT_TO_OCULUS = exports.RHUBARB_TO_OCULUS = exports.OCULUS_MORPH_TARGET_NAMES = exports.RHUBARB_VISEMES = exports.OCULUS_VISEMES = void 0;
4
+ exports.oculusWeightsForRhubarbCue = oculusWeightsForRhubarbCue;
4
5
  exports.remapArkitToOculus = remapArkitToOculus;
5
6
  exports.getArkitWeightsForViseme = getArkitWeightsForViseme;
6
7
  exports.OCULUS_VISEMES = [
7
8
  'sil', 'PP', 'FF', 'TH', 'DD', 'kk', 'CH', 'SS', 'nn', 'RR', 'aa', 'ee', 'ih', 'oh', 'ou',
8
9
  ];
10
+ exports.RHUBARB_VISEMES = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'X'];
11
+ exports.OCULUS_MORPH_TARGET_NAMES = {
12
+ sil: 'viseme_sil',
13
+ PP: 'viseme_PP',
14
+ FF: 'viseme_FF',
15
+ TH: 'viseme_TH',
16
+ DD: 'viseme_DD',
17
+ kk: 'viseme_kk',
18
+ CH: 'viseme_CH',
19
+ SS: 'viseme_SS',
20
+ nn: 'viseme_nn',
21
+ RR: 'viseme_RR',
22
+ aa: 'viseme_aa',
23
+ ee: 'viseme_ee',
24
+ ih: 'viseme_ih',
25
+ oh: 'viseme_oh',
26
+ ou: 'viseme_ou',
27
+ };
28
+ exports.RHUBARB_TO_OCULUS = {
29
+ A: { aa: 0.72 },
30
+ B: { PP: 0.85 },
31
+ C: { ih: 0.68 },
32
+ D: { FF: 0.78 },
33
+ E: { ee: 0.72 },
34
+ F: { oh: 0.62 },
35
+ G: { ou: 0.58 },
36
+ H: { nn: 0.72 },
37
+ X: { sil: 1 },
38
+ };
9
39
  /**
10
40
  * Each Oculus viseme expressed as a weighted combination of ARKit blend shapes.
11
41
  * Weights are in 0–1 range. Apply by multiplying each ARKit shape's influence.
@@ -31,6 +61,23 @@ exports.ARKIT_TO_OCULUS = {
31
61
  oh: { jawOpen: 0.4, mouthFunnel: 0.8 },
32
62
  ou: { mouthPucker: 0.9, mouthRollLower: 0.3 },
33
63
  };
64
+ exports.ENGINE_VISEME_MAPPING = {
65
+ schemaVersion: 1,
66
+ rhubarbVisemes: exports.RHUBARB_VISEMES,
67
+ oculusVisemes: exports.OCULUS_VISEMES,
68
+ oculusMorphTargetNames: exports.OCULUS_MORPH_TARGET_NAMES,
69
+ rhubarbToOculus: exports.RHUBARB_TO_OCULUS,
70
+ oculusToArkit: exports.ARKIT_TO_OCULUS,
71
+ };
72
+ function oculusWeightsForRhubarbCue(cue) {
73
+ const weight = Math.max(0, Math.min(1, cue.weight ?? 1));
74
+ const result = Object.fromEntries(exports.OCULUS_VISEMES.map((viseme) => [viseme, 0]));
75
+ const mapping = exports.RHUBARB_TO_OCULUS[cue.viseme];
76
+ for (const [viseme, value] of Object.entries(mapping)) {
77
+ result[viseme] = Math.max(0, Math.min(1, value * weight));
78
+ }
79
+ return result;
80
+ }
34
81
  /**
35
82
  * Remap a set of ARKit blend shape weights to Oculus viseme weights.
36
83
  *
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.AvatarCanvas = AvatarCanvas;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  // @ts-nocheck
6
+ /* eslint-disable @typescript-eslint/no-explicit-any -- R3F pointer events and Three.js scene internals are intentionally dynamic in this editor bridge. */
6
7
  const drei_1 = require("@react-three/drei");
7
8
  const fiber_1 = require("@react-three/fiber");
8
9
  const react_1 = require("react");
@@ -10,6 +11,96 @@ const AvatarCanvasErrorBoundary_1 = require("./AvatarCanvasErrorBoundary");
10
11
  const AvatarModel_1 = require("./AvatarModel");
11
12
  const RigidAccessory_1 = require("./RigidAccessory");
12
13
  const SkinnedClothing_1 = require("./SkinnedClothing");
14
+ function DirectTransform({ activeAssetId, placements, onPlacementChange }) {
15
+ const { gl } = (0, fiber_1.useThree)();
16
+ (0, react_1.useEffect)(() => {
17
+ const canvas = gl.domElement;
18
+ let dragging = false;
19
+ let lastX = 0;
20
+ let lastY = 0;
21
+ function isModified(e) {
22
+ return e.shiftKey || e.ctrlKey || e.metaKey;
23
+ }
24
+ function onPointerDown(e) {
25
+ if (!activeAssetId || !isModified(e))
26
+ return;
27
+ e.stopPropagation();
28
+ canvas.setPointerCapture(e.pointerId);
29
+ dragging = true;
30
+ lastX = e.clientX;
31
+ lastY = e.clientY;
32
+ }
33
+ function onPointerMove(e) {
34
+ if (!dragging || !activeAssetId || !onPlacementChange)
35
+ return;
36
+ const rect = canvas.getBoundingClientRect();
37
+ // Normalise deltas to canvas size so sensitivity is viewport-independent
38
+ const dx = (e.clientX - lastX) / rect.width;
39
+ const dy = (e.clientY - lastY) / rect.height;
40
+ lastX = e.clientX;
41
+ lastY = e.clientY;
42
+ const p = placements[activeAssetId];
43
+ if (!p)
44
+ return;
45
+ const TRANSLATE_SPEED = 2.0;
46
+ const ROTATE_SPEED = Math.PI * 2;
47
+ if (e.shiftKey && (e.altKey || e.metaKey)) {
48
+ // Shift+Alt/Meta drag → Y axis (lift/lower)
49
+ onPlacementChange(activeAssetId, {
50
+ ...p,
51
+ position: [p.position[0], p.position[1] - dy * TRANSLATE_SPEED, p.position[2]],
52
+ });
53
+ }
54
+ else if (e.shiftKey) {
55
+ // Shift drag → XZ plane (slide left/right/forward/back)
56
+ onPlacementChange(activeAssetId, {
57
+ ...p,
58
+ position: [
59
+ p.position[0] + dx * TRANSLATE_SPEED,
60
+ p.position[1],
61
+ p.position[2] + dy * TRANSLATE_SPEED,
62
+ ],
63
+ });
64
+ }
65
+ else if (e.ctrlKey || e.metaKey) {
66
+ // Ctrl/Cmd drag → Y-axis rotation (yaw)
67
+ onPlacementChange(activeAssetId, {
68
+ ...p,
69
+ rotation: [p.rotation[0], p.rotation[1] + dx * ROTATE_SPEED, p.rotation[2]],
70
+ });
71
+ }
72
+ }
73
+ function onPointerUp(e) {
74
+ if (dragging)
75
+ canvas.releasePointerCapture(e.pointerId);
76
+ dragging = false;
77
+ }
78
+ function onWheel(e) {
79
+ if (!e.shiftKey || !activeAssetId || !onPlacementChange)
80
+ return;
81
+ e.preventDefault();
82
+ const p = placements[activeAssetId];
83
+ if (!p)
84
+ return;
85
+ const factor = e.deltaY > 0 ? 0.95 : 1.05;
86
+ onPlacementChange(activeAssetId, {
87
+ ...p,
88
+ scale: Math.max(0.01, (p.scale ?? 1) * factor),
89
+ });
90
+ }
91
+ canvas.addEventListener('pointerdown', onPointerDown);
92
+ canvas.addEventListener('pointermove', onPointerMove);
93
+ canvas.addEventListener('pointerup', onPointerUp);
94
+ canvas.addEventListener('wheel', onWheel, { passive: false });
95
+ return () => {
96
+ canvas.removeEventListener('pointerdown', onPointerDown);
97
+ canvas.removeEventListener('pointermove', onPointerMove);
98
+ canvas.removeEventListener('pointerup', onPointerUp);
99
+ canvas.removeEventListener('wheel', onWheel);
100
+ };
101
+ }, [activeAssetId, placements, onPlacementChange, gl]);
102
+ return null;
103
+ }
13
104
  /** Captures the R3F scene object (which contains everything) and passes it up. */
14
105
  function SceneRefCapture({ onSceneRef }) {
15
106
  const { scene } = (0, fiber_1.useThree)();
@@ -45,7 +136,7 @@ function AvatarCanvas({ avatarUrl, equipped = [], placements = {}, editingAssetI
45
136
  ]
46
137
  .filter(Boolean)
47
138
  .join(' ');
48
- return ((0, jsx_runtime_1.jsxs)("div", { className: wrapperClass, style: style, children: [(0, jsx_runtime_1.jsx)("div", { className: "absolute inset-0 opacity-[0.04] pointer-events-none", style: { backgroundImage: 'linear-gradient(rgba(255,255,255,0.3) 1px,transparent 1px),linear-gradient(90deg,rgba(255,255,255,0.3) 1px,transparent 1px)', backgroundSize: '60px 60px' } }), avatarUrl ? ((0, jsx_runtime_1.jsx)(AvatarCanvasErrorBoundary_1.AvatarCanvasErrorBoundary, { children: (0, jsx_runtime_1.jsx)(fiber_1.Canvas, { ref: canvasRef, camera: { position: cameraPosition, fov: 45 }, style: { width: '100%', height: '100%' }, children: (0, jsx_runtime_1.jsxs)(react_1.Suspense, { fallback: null, children: [onSceneRef && (0, jsx_runtime_1.jsx)(SceneRefCapture, { onSceneRef: onSceneRef }), (0, jsx_runtime_1.jsx)("ambientLight", { intensity: 0.6 }), (0, jsx_runtime_1.jsx)("directionalLight", { position: [5, 5, 5], intensity: 0.8 }), (0, jsx_runtime_1.jsx)(drei_1.Environment, { preset: "studio" }), (0, jsx_runtime_1.jsx)(drei_1.OrbitControls, { target: cameraTarget, minDistance: 1, maxDistance: 10, enablePan: false, makeDefault: true, enabled: !editingId }), (0, jsx_runtime_1.jsx)(AvatarModel_1.AvatarModel, { url: avatarUrl, scale: 1, onSkeletonReady: handleSkeletonReady, onBoundsReady: handleBoundsReady }), equippedItems.map((asset) => {
139
+ return ((0, jsx_runtime_1.jsxs)("div", { className: wrapperClass, style: style, children: [(0, jsx_runtime_1.jsx)("div", { className: "absolute inset-0 opacity-[0.04] pointer-events-none", style: { backgroundImage: 'linear-gradient(rgba(255,255,255,0.3) 1px,transparent 1px),linear-gradient(90deg,rgba(255,255,255,0.3) 1px,transparent 1px)', backgroundSize: '60px 60px' } }), avatarUrl ? ((0, jsx_runtime_1.jsx)(AvatarCanvasErrorBoundary_1.AvatarCanvasErrorBoundary, { children: (0, jsx_runtime_1.jsx)(fiber_1.Canvas, { ref: canvasRef, camera: { position: cameraPosition, fov: 45 }, style: { width: '100%', height: '100%' }, children: (0, jsx_runtime_1.jsxs)(react_1.Suspense, { fallback: null, children: [onSceneRef && (0, jsx_runtime_1.jsx)(SceneRefCapture, { onSceneRef: onSceneRef }), (0, jsx_runtime_1.jsx)("ambientLight", { intensity: 0.6 }), (0, jsx_runtime_1.jsx)("directionalLight", { position: [5, 5, 5], intensity: 0.8 }), (0, jsx_runtime_1.jsx)(drei_1.Environment, { preset: "studio" }), (0, jsx_runtime_1.jsx)(drei_1.OrbitControls, { target: cameraTarget, minDistance: 1, maxDistance: 10, enablePan: false, makeDefault: true }), (0, jsx_runtime_1.jsx)(drei_1.GizmoHelper, { alignment: "bottom-right", margin: [60, 60], children: (0, jsx_runtime_1.jsx)(drei_1.GizmoViewport, { axisColors: ['#e24444', '#44cc44', '#4488ff'], labelColor: "white" }) }), (0, jsx_runtime_1.jsx)(DirectTransform, { activeAssetId: editingId, placements: placements, onPlacementChange: onPlacementChange }), (0, jsx_runtime_1.jsx)(AvatarModel_1.AvatarModel, { url: avatarUrl, scale: 1, onSkeletonReady: handleSkeletonReady, onBoundsReady: handleBoundsReady }), equippedItems.map((asset) => {
49
140
  if (!asset)
50
141
  return null;
51
142
  const llmPlacement = placements[asset.id];
@@ -40,6 +40,7 @@ const jsx_runtime_1 = require("react/jsx-runtime");
40
40
  * Uses WgpuAvatar (R3F + expo-gl) as the render surface and Three.js raycasting
41
41
  * for gesture-driven accessory placement. Replaces the old FilamentEditor.
42
42
  */
43
+ /* eslint-disable @typescript-eslint/no-explicit-any -- React Native gesture events and Three.js raycast payloads do not expose complete structural types here. */
43
44
  const react_1 = require("react");
44
45
  const react_native_1 = require("react-native");
45
46
  const THREE = __importStar(require("three"));
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.AvatarModel = AvatarModel;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  // @ts-nocheck
6
+ /* eslint-disable @typescript-eslint/no-explicit-any -- R3F GLTF skeleton data is passed through from untyped loader internals. */
6
7
  const drei_1 = require("@react-three/drei");
7
8
  const fiber_1 = require("@react-three/fiber");
8
9
  const react_1 = require("react");
@@ -10,8 +10,10 @@
10
10
  * Drop-in replacement: same FaceSqueezeEditorProps interface.
11
11
  * The .web.tsx stub is shared — import from FaceSqueezeEditor.web.tsx.
12
12
  */
13
+ import '../wgpu/blobShim';
13
14
  export declare const FACE_SQUEEZE_LOCAL_MODULE: number;
14
15
  export interface FaceSqueezeEditorProps {
15
16
  onClose: () => void;
17
+ avatarModule?: unknown;
16
18
  }
17
- export declare function FaceSqueezeEditor({ onClose }: FaceSqueezeEditorProps): import("react/jsx-runtime").JSX.Element;
19
+ export declare function FaceSqueezeEditor({ onClose, avatarModule, }: FaceSqueezeEditorProps): import("react/jsx-runtime").JSX.Element;