talking-head-studio 0.3.6 → 0.3.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.
- package/dist/TalkingHead.web.js +7 -17
- package/dist/api/studioApi.js +26 -25
- package/dist/appearance/apply.d.ts +6 -0
- package/dist/appearance/apply.js +72 -7
- package/dist/appearance/index.d.ts +1 -1
- package/dist/appearance/index.js +2 -1
- package/dist/appearance/matchers.js +2 -1
- package/dist/appearance/schema.d.ts +1 -0
- package/dist/appearance/schema.js +3 -1
- package/dist/appearance/sharedState.d.ts +11 -0
- package/dist/appearance/sharedState.js +13 -0
- package/dist/editor/AvatarCanvas.d.ts +1 -0
- package/dist/editor/AvatarCanvas.js +3 -2
- package/dist/editor/AvatarModel.d.ts +1 -3
- package/dist/editor/AvatarModel.js +13 -5
- package/dist/editor/RigidAccessory.js +2 -1
- package/dist/editor/SkinnedClothing.js +9 -18
- package/dist/filament/FilamentAvatar.js +20 -42
- package/dist/filament/editor/FilamentEditor.js +12 -21
- package/dist/filament/editor/FilamentEditor.web.js +2 -1
- package/dist/filament/editor/PrecisionPanel.js +8 -18
- package/dist/filament/editor/boneSnap.js +12 -22
- package/dist/filament/editor/studioTheme.js +2 -2
- package/dist/filament/useAuthedFilamentUri.js +9 -18
- package/dist/html.js +2 -1
- package/dist/index.d.ts +0 -2
- package/dist/index.js +1 -3
- package/dist/sketchfab/api.js +5 -4
- package/dist/sketchfab/useSketchfabSearch.js +2 -1
- package/dist/tts/useDirectVisemeStream.js +2 -1
- package/dist/tts/useMotionMarkers.d.ts +1 -0
- package/dist/tts/useMotionMarkers.js +2 -1
- package/dist/utils/avatarUtils.js +3 -2
- package/dist/utils/faceLandmarkerToShapeWeights.d.ts +44 -0
- package/dist/utils/faceLandmarkerToShapeWeights.js +112 -0
- package/dist/voice/convertToWav.js +2 -1
- package/dist/voice/useAudioPlayer.js +2 -1
- package/dist/voice/useAudioRecording.js +2 -1
- package/dist/wardrobe/useAvatarWardrobeHydration.js +2 -1
- package/package.json +15 -3
|
@@ -15,23 +15,13 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
|
|
|
15
15
|
}) : function(o, v) {
|
|
16
16
|
o["default"] = v;
|
|
17
17
|
});
|
|
18
|
-
var __importStar = (this && this.__importStar) ||
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
35
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
26
|
exports.FilamentAvatar = exports.CAMERA_FOCAL_PIP = exports.CAMERA_FOCAL_FULL = void 0;
|
|
37
27
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
@@ -51,7 +41,6 @@ const react_1 = __importStar(require("react"));
|
|
|
51
41
|
const react_native_1 = require("react-native");
|
|
52
42
|
const react_native_filament_1 = require("react-native-filament");
|
|
53
43
|
const useAuthedFilamentUri_1 = require("./useAuthedFilamentUri");
|
|
54
|
-
const expo_asset_1 = require("expo-asset");
|
|
55
44
|
const faceSqueezeAssets_1 = require("./faceSqueezeAssets");
|
|
56
45
|
const morphTables_1 = require("./morphTables");
|
|
57
46
|
// ---------------------------------------------------------------------------
|
|
@@ -148,10 +137,11 @@ function buildVisemeMorphCache(dispatchMap) {
|
|
|
148
137
|
}
|
|
149
138
|
function FilamentAvatarInner({ localUri, mood: initialMood = 'neutral', hairColor: initialHairColor, skinColor: initialSkinColor, eyeColor: initialEyeColor, onReady, onError: _onError, // eslint-disable-line @typescript-eslint/no-unused-vars
|
|
150
139
|
innerRef, aspect, focalLength = exports.CAMERA_FOCAL_FULL, }) {
|
|
151
|
-
//
|
|
152
|
-
//
|
|
153
|
-
//
|
|
154
|
-
|
|
140
|
+
// localUri is either a file:// string (remote download) or a require() number (bundled fallback).
|
|
141
|
+
// useModel accepts both as BufferSource (number | { uri: string }) — cast to any since
|
|
142
|
+
// tsconfig resolves to an older type declaration that only shows { uri: string }.
|
|
143
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
144
|
+
const model = (0, react_native_filament_1.useModel)(typeof localUri === 'number' ? localUri : { uri: localUri });
|
|
155
145
|
const modelRef = (0, react_1.useRef)(model);
|
|
156
146
|
modelRef.current = model;
|
|
157
147
|
const { renderableManager } = (0, react_native_filament_1.useFilamentContext)();
|
|
@@ -697,36 +687,24 @@ innerRef, aspect, focalLength = exports.CAMERA_FOCAL_FULL, }) {
|
|
|
697
687
|
// ---------------------------------------------------------------------------
|
|
698
688
|
// Outer component — handles URL resolution + FilamentScene wrapper
|
|
699
689
|
// ---------------------------------------------------------------------------
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
if (_fallbackGlbUri)
|
|
703
|
-
return _fallbackGlbUri;
|
|
704
|
-
const asset = expo_asset_1.Asset.fromModule(faceSqueezeAssets_1.FACE_SQUEEZE_LOCAL_MODULE);
|
|
705
|
-
await asset.downloadAsync();
|
|
706
|
-
_fallbackGlbUri = asset.localUri ?? asset.uri ?? '';
|
|
707
|
-
return _fallbackGlbUri;
|
|
708
|
-
}
|
|
690
|
+
// The fallback is the bundled require() number — useModel accepts this directly
|
|
691
|
+
// (BufferSource = number | { uri: string }), so no async asset resolution needed.
|
|
709
692
|
exports.FilamentAvatar = (0, react_1.forwardRef)(({ style, avatarUrl, aspect, focalLength, mood, hairColor, skinColor, eyeColor, accessories, onReady, onError }, ref) => {
|
|
710
693
|
const fileResult = (0, useAuthedFilamentUri_1.useAuthedFilamentUri)(avatarUrl ?? null);
|
|
711
694
|
const currentUri = fileResult?.uri ?? null;
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
getFallbackGlbUri().then(setFallbackUri).catch((e) => console.error('[FilamentAvatar] fallback uri failed:', e));
|
|
715
|
-
}, []);
|
|
716
|
-
// Stabilize localUri: once a valid file URI resolves, keep it until a new one
|
|
717
|
-
// arrives. Never let it drop to null between URL transitions — that would cause
|
|
718
|
-
// the conditional below to unmount FilamentScene mid-render.
|
|
695
|
+
// Stabilize localUri: once a valid remote file URI resolves, keep it until a new
|
|
696
|
+
// one arrives. Falls back to the bundled require() number — always available sync.
|
|
719
697
|
const stableUriRef = react_1.default.useRef(null);
|
|
720
698
|
if (currentUri)
|
|
721
699
|
stableUriRef.current = currentUri;
|
|
722
|
-
const localUri = stableUriRef.current ??
|
|
700
|
+
const localUri = stableUriRef.current ?? faceSqueezeAssets_1.FACE_SQUEEZE_LOCAL_MODULE;
|
|
723
701
|
// FilamentScene MUST stay mounted for the lifetime of this component.
|
|
724
702
|
// Unmounting it disposes GPU assets on the JS thread while Filament's native
|
|
725
703
|
// render thread (FEngine::loop) and surface thread (JNISurfaceTextu) still hold
|
|
726
704
|
// references to those objects → SIGSEGV / corrupted-PC use-after-free crashes.
|
|
727
|
-
//
|
|
728
|
-
//
|
|
729
|
-
return ((0, jsx_runtime_1.jsx)(react_native_1.View, { style: [style, styles.fill], children: (0, jsx_runtime_1.jsx)(react_native_filament_1.FilamentScene, { children: (0, jsx_runtime_1.jsx)(FilamentAvatarInner, { localUri: localUri
|
|
705
|
+
// FilamentAvatarInner keeps FilamentView permanently mounted; only ModelRenderer
|
|
706
|
+
// is conditional on the model being ready.
|
|
707
|
+
return ((0, jsx_runtime_1.jsx)(react_native_1.View, { style: [style, styles.fill], children: (0, jsx_runtime_1.jsx)(react_native_filament_1.FilamentScene, { children: (0, jsx_runtime_1.jsx)(FilamentAvatarInner, { localUri: localUri, avatarUrl: avatarUrl, aspect: aspect, focalLength: focalLength, mood: mood, hairColor: hairColor, skinColor: skinColor, eyeColor: eyeColor, accessories: accessories, innerRef: ref, onReady: onReady, onError: onError }) }) }));
|
|
730
708
|
});
|
|
731
709
|
exports.FilamentAvatar.displayName = 'FilamentAvatar';
|
|
732
710
|
const styles = react_native_1.StyleSheet.create({
|
|
@@ -15,28 +15,18 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
|
|
|
15
15
|
}) : function(o, v) {
|
|
16
16
|
o["default"] = v;
|
|
17
17
|
});
|
|
18
|
-
var __importStar = (this && this.__importStar) ||
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
35
25
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
26
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
27
|
};
|
|
38
28
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
-
exports.FilamentEditor =
|
|
29
|
+
exports.FilamentEditor = void 0;
|
|
40
30
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
41
31
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
42
32
|
const vector_icons_1 = require("@expo/vector-icons");
|
|
@@ -44,9 +34,6 @@ const Haptics = __importStar(require("expo-haptics"));
|
|
|
44
34
|
const react_1 = require("react");
|
|
45
35
|
const react_native_1 = require("react-native");
|
|
46
36
|
const react_native_filament_1 = require("react-native-filament");
|
|
47
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
48
|
-
const rnFilament = require('react-native-filament'); // eslint-disable-line @typescript-eslint/no-require-imports
|
|
49
|
-
const useCameraManipulator = rnFilament.useCameraManipulator;
|
|
50
37
|
const react_native_gesture_handler_1 = require("react-native-gesture-handler");
|
|
51
38
|
const react_native_reanimated_1 = __importStar(require("react-native-reanimated"));
|
|
52
39
|
const useAuthedFilamentUri_1 = require("../useAuthedFilamentUri");
|
|
@@ -54,6 +41,9 @@ const boneSnap_1 = require("./boneSnap");
|
|
|
54
41
|
const studioApi_1 = require("../../api/studioApi");
|
|
55
42
|
const PrecisionPanel_1 = __importDefault(require("./PrecisionPanel"));
|
|
56
43
|
const studioTheme_1 = require("./studioTheme");
|
|
44
|
+
// Lazy require avoids mixing require/import at module top level (Metro bug).
|
|
45
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-explicit-any
|
|
46
|
+
const useCameraManipulator = require('react-native-filament').useCameraManipulator;
|
|
57
47
|
// Pure JS transform helpers (no 'worklet' directive — avoids Reanimated
|
|
58
48
|
// babel plugin serializing gesture closure variables).
|
|
59
49
|
function applyDragTranslate(startPos, translationX, translationY, sensitivity) {
|
|
@@ -294,6 +284,7 @@ function AvatarModel({ uri, onLoaded, skinColor }) {
|
|
|
294
284
|
function FilamentEditor(props) {
|
|
295
285
|
return ((0, jsx_runtime_1.jsx)(react_native_filament_1.FilamentScene, { children: (0, jsx_runtime_1.jsx)(FilamentEditorContent, { ...props }) }));
|
|
296
286
|
}
|
|
287
|
+
exports.FilamentEditor = FilamentEditor;
|
|
297
288
|
// ---------------------------------------------------------------------------
|
|
298
289
|
// Inner component — has access to Filament context
|
|
299
290
|
// ---------------------------------------------------------------------------
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.FilamentEditor =
|
|
3
|
+
exports.FilamentEditor = void 0;
|
|
4
4
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
5
|
const react_native_1 = require("react-native");
|
|
6
6
|
const editor_1 = require("../../editor");
|
|
@@ -34,6 +34,7 @@ function FilamentEditor({ avatarUrl, style, onDone, appearance, equipped, placem
|
|
|
34
34
|
};
|
|
35
35
|
return ((0, jsx_runtime_1.jsxs)(react_native_1.View, { style: [styles.container, style], children: [(0, jsx_runtime_1.jsx)(editor_1.AvatarCanvas, { avatarUrl: avatarUrl, appearance: appearance, equipped: equippedItems, placements: normalizedPlacements, editingAssetId: activeAssetId, onPlacementChange: handlePlacementChange, style: { width: '100%', height: '100%' } }), (0, jsx_runtime_1.jsx)(react_native_1.Pressable, { style: styles.doneButton, onPress: onDone, children: (0, jsx_runtime_1.jsx)(react_native_1.Text, { style: styles.doneText, children: "Done" }) })] }));
|
|
36
36
|
}
|
|
37
|
+
exports.FilamentEditor = FilamentEditor;
|
|
37
38
|
exports.default = FilamentEditor;
|
|
38
39
|
const styles = react_native_1.StyleSheet.create({
|
|
39
40
|
container: {
|
|
@@ -15,25 +15,14 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
|
|
|
15
15
|
}) : function(o, v) {
|
|
16
16
|
o["default"] = v;
|
|
17
17
|
});
|
|
18
|
-
var __importStar = (this && this.__importStar) ||
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
35
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.default = PrecisionPanel;
|
|
37
26
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
38
27
|
const react_1 = require("react");
|
|
39
28
|
const react_native_1 = require("react-native");
|
|
@@ -158,6 +147,7 @@ function PrecisionPanel() {
|
|
|
158
147
|
}, children: (0, jsx_runtime_1.jsx)(react_native_1.Text, { style: [styles.segmentText, isActive && styles.segmentTextActive], children: m.label }) }, m.key));
|
|
159
148
|
}) }), gizmoMode === 'translate' && ((0, jsx_runtime_1.jsxs)(react_native_reanimated_1.default.View, { children: [(0, jsx_runtime_1.jsx)(PrecisionSlider, { label: "X", value: placement.position[0], onChange: (v) => updateAxis('x', v), step: 0.01 }), (0, jsx_runtime_1.jsx)(PrecisionSlider, { label: "Y", value: placement.position[1], onChange: (v) => updateAxis('y', v), step: 0.01 }), (0, jsx_runtime_1.jsx)(PrecisionSlider, { label: "Z", value: placement.position[2], onChange: (v) => updateAxis('z', v), step: 0.01 })] })), gizmoMode === 'rotate' && ((0, jsx_runtime_1.jsxs)(react_native_reanimated_1.default.View, { children: [(0, jsx_runtime_1.jsx)(PrecisionSlider, { label: "Pitch", value: placement.rotation[0], onChange: (v) => updateAxis('x', v), step: 1, unit: "\u00B0" }), (0, jsx_runtime_1.jsx)(PrecisionSlider, { label: "Yaw", value: placement.rotation[1], onChange: (v) => updateAxis('y', v), step: 1, unit: "\u00B0" }), (0, jsx_runtime_1.jsx)(PrecisionSlider, { label: "Roll", value: placement.rotation[2], onChange: (v) => updateAxis('z', v), step: 1, unit: "\u00B0" })] })), gizmoMode === 'scale' && ((0, jsx_runtime_1.jsx)(react_native_reanimated_1.default.View, { children: (0, jsx_runtime_1.jsx)(PrecisionSlider, { label: "Uniform", value: placement.scale, onChange: updateScale, step: 0.01 }) }))] }));
|
|
160
149
|
}
|
|
150
|
+
exports.default = PrecisionPanel;
|
|
161
151
|
const styles = react_native_1.StyleSheet.create({
|
|
162
152
|
container: {
|
|
163
153
|
position: 'absolute',
|
|
@@ -15,29 +15,15 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
|
|
|
15
15
|
}) : function(o, v) {
|
|
16
16
|
o["default"] = v;
|
|
17
17
|
});
|
|
18
|
-
var __importStar = (this && this.__importStar) ||
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
35
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.HUMANOID_BONES = void 0;
|
|
37
|
-
exports.findNearestBone = findNearestBone;
|
|
38
|
-
exports.getWorldPositionForPlacement = getWorldPositionForPlacement;
|
|
39
|
-
exports.snapPlacementToNearestBone = snapPlacementToNearestBone;
|
|
40
|
-
exports.useBoneSnap = useBoneSnap;
|
|
26
|
+
exports.useBoneSnap = exports.snapPlacementToNearestBone = exports.getWorldPositionForPlacement = exports.findNearestBone = exports.HUMANOID_BONES = void 0;
|
|
41
27
|
const react_1 = require("react");
|
|
42
28
|
const Haptics = __importStar(require("expo-haptics"));
|
|
43
29
|
const wardrobeStore_1 = require("../../wardrobe/wardrobeStore");
|
|
@@ -72,6 +58,7 @@ function findNearestBone(position) {
|
|
|
72
58
|
position: nearestPos,
|
|
73
59
|
};
|
|
74
60
|
}
|
|
61
|
+
exports.findNearestBone = findNearestBone;
|
|
75
62
|
function getWorldPositionForPlacement(placement) {
|
|
76
63
|
const bonePos = exports.HUMANOID_BONES[placement.bone] ?? exports.HUMANOID_BONES['Head'];
|
|
77
64
|
return [
|
|
@@ -80,6 +67,7 @@ function getWorldPositionForPlacement(placement) {
|
|
|
80
67
|
bonePos[2] + placement.position[2],
|
|
81
68
|
];
|
|
82
69
|
}
|
|
70
|
+
exports.getWorldPositionForPlacement = getWorldPositionForPlacement;
|
|
83
71
|
function snapPlacementToNearestBone(placement) {
|
|
84
72
|
const nearest = findNearestBone(getWorldPositionForPlacement(placement));
|
|
85
73
|
return {
|
|
@@ -88,6 +76,7 @@ function snapPlacementToNearestBone(placement) {
|
|
|
88
76
|
position: [0, 0, 0],
|
|
89
77
|
};
|
|
90
78
|
}
|
|
79
|
+
exports.snapPlacementToNearestBone = snapPlacementToNearestBone;
|
|
91
80
|
function useBoneSnap() {
|
|
92
81
|
const activeAssetId = (0, wardrobeStore_1.useWardrobeStore)((state) => state.activeAssetId);
|
|
93
82
|
const placements = (0, wardrobeStore_1.useWardrobeStore)((state) => state.placements);
|
|
@@ -105,3 +94,4 @@ function useBoneSnap() {
|
|
|
105
94
|
}, [activeAssetId, placements, setPlacement]);
|
|
106
95
|
return snap;
|
|
107
96
|
}
|
|
97
|
+
exports.useBoneSnap = useBoneSnap;
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.studioTheme = void 0;
|
|
4
|
-
exports.withAlpha = withAlpha;
|
|
3
|
+
exports.withAlpha = exports.studioTheme = void 0;
|
|
5
4
|
exports.studioTheme = {
|
|
6
5
|
colors: {
|
|
7
6
|
background: '#111315',
|
|
@@ -87,3 +86,4 @@ function withAlpha(hexOrRgb, alphaHex) {
|
|
|
87
86
|
}
|
|
88
87
|
return hexOrRgb;
|
|
89
88
|
}
|
|
89
|
+
exports.withAlpha = withAlpha;
|
|
@@ -15,25 +15,15 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
|
|
|
15
15
|
}) : function(o, v) {
|
|
16
16
|
o["default"] = v;
|
|
17
17
|
});
|
|
18
|
-
var __importStar = (this && this.__importStar) ||
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
35
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.useAuthedFilamentUri =
|
|
26
|
+
exports.useAuthedFilamentUri = void 0;
|
|
37
27
|
const react_1 = require("react");
|
|
38
28
|
const FileSystem = __importStar(require("expo-file-system/legacy"));
|
|
39
29
|
const studioApi_1 = require("../api/studioApi");
|
|
@@ -124,3 +114,4 @@ function useAuthedFilamentUri(remoteUrl) {
|
|
|
124
114
|
}, [remoteUrl]);
|
|
125
115
|
return result;
|
|
126
116
|
}
|
|
117
|
+
exports.useAuthedFilamentUri = useAuthedFilamentUri;
|
package/dist/html.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.buildAvatarHtml =
|
|
3
|
+
exports.buildAvatarHtml = void 0;
|
|
4
4
|
const UPSTREAM_SAFE_MOOD_MAP = {
|
|
5
5
|
neutral: 'neutral',
|
|
6
6
|
happy: 'happy',
|
|
@@ -1138,3 +1138,4 @@ await init();
|
|
|
1138
1138
|
</html>
|
|
1139
1139
|
`;
|
|
1140
1140
|
}
|
|
1141
|
+
exports.buildAvatarHtml = buildAvatarHtml;
|
package/dist/index.d.ts
CHANGED
|
@@ -6,8 +6,6 @@ export { normalizeAppearance } from './appearance/schema';
|
|
|
6
6
|
export type { AppearanceTarget } from './appearance/matchers';
|
|
7
7
|
export * from './api';
|
|
8
8
|
export * from './wardrobe';
|
|
9
|
-
export { TalkingHeadVisualization } from './TalkingHeadVisualization';
|
|
10
|
-
export type { TalkingHeadVisualizationRef } from './TalkingHeadVisualization';
|
|
11
9
|
export { useDirectVisemeStream } from './tts/useDirectVisemeStream';
|
|
12
10
|
export type { VisemeStreamPayload } from './tts/useDirectVisemeStream';
|
|
13
11
|
export { useMotionMarkers } from './tts/useMotionMarkers';
|
package/dist/index.js
CHANGED
|
@@ -14,7 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
exports.useMotionMarkers = exports.useDirectVisemeStream = exports.
|
|
17
|
+
exports.useMotionMarkers = exports.useDirectVisemeStream = exports.normalizeAppearance = exports.pickTargetForMaterialName = exports.applyAppearanceToObject3D = exports.TalkingHead = void 0;
|
|
18
18
|
var TalkingHead_1 = require("./TalkingHead");
|
|
19
19
|
Object.defineProperty(exports, "TalkingHead", { enumerable: true, get: function () { return TalkingHead_1.TalkingHead; } });
|
|
20
20
|
// Export appearance utilities, but exclude AvatarAppearance — the canonical
|
|
@@ -27,8 +27,6 @@ var schema_1 = require("./appearance/schema");
|
|
|
27
27
|
Object.defineProperty(exports, "normalizeAppearance", { enumerable: true, get: function () { return schema_1.normalizeAppearance; } });
|
|
28
28
|
__exportStar(require("./api"), exports);
|
|
29
29
|
__exportStar(require("./wardrobe"), exports);
|
|
30
|
-
var TalkingHeadVisualization_1 = require("./TalkingHeadVisualization");
|
|
31
|
-
Object.defineProperty(exports, "TalkingHeadVisualization", { enumerable: true, get: function () { return TalkingHeadVisualization_1.TalkingHeadVisualization; } });
|
|
32
30
|
var useDirectVisemeStream_1 = require("./tts/useDirectVisemeStream");
|
|
33
31
|
Object.defineProperty(exports, "useDirectVisemeStream", { enumerable: true, get: function () { return useDirectVisemeStream_1.useDirectVisemeStream; } });
|
|
34
32
|
var useMotionMarkers_1 = require("./tts/useMotionMarkers");
|
package/dist/sketchfab/api.js
CHANGED
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.searchSketchfab =
|
|
4
|
-
exports.getDownloadUrl = getDownloadUrl;
|
|
5
|
-
exports.downloadModel = downloadModel;
|
|
6
|
-
exports.getBestThumbnail = getBestThumbnail;
|
|
3
|
+
exports.getBestThumbnail = exports.downloadModel = exports.getDownloadUrl = exports.searchSketchfab = void 0;
|
|
7
4
|
const SKETCHFAB_API_BASE = 'https://api.sketchfab.com/v3';
|
|
8
5
|
const PAGE_SIZE = 24;
|
|
9
6
|
async function searchSketchfab(options) {
|
|
@@ -26,6 +23,7 @@ async function searchSketchfab(options) {
|
|
|
26
23
|
}
|
|
27
24
|
return response.json();
|
|
28
25
|
}
|
|
26
|
+
exports.searchSketchfab = searchSketchfab;
|
|
29
27
|
async function getDownloadUrl(uid, apiKey) {
|
|
30
28
|
const response = await fetch(`${SKETCHFAB_API_BASE}/models/${uid}/download`, {
|
|
31
29
|
headers: { Authorization: `Token ${apiKey}` },
|
|
@@ -36,6 +34,7 @@ async function getDownloadUrl(uid, apiKey) {
|
|
|
36
34
|
const data = (await response.json());
|
|
37
35
|
return data?.glb?.url ?? data?.gltf?.url ?? null;
|
|
38
36
|
}
|
|
37
|
+
exports.getDownloadUrl = getDownloadUrl;
|
|
39
38
|
async function downloadModel(uid, name, apiKey) {
|
|
40
39
|
const url = await getDownloadUrl(uid, apiKey);
|
|
41
40
|
if (!url) {
|
|
@@ -49,6 +48,7 @@ async function downloadModel(uid, name, apiKey) {
|
|
|
49
48
|
const cleanName = name.replace(/[^\w\s-]/g, '').trim() || 'model';
|
|
50
49
|
return new File([blob], `${cleanName}.glb`, { type: 'model/gltf-binary' });
|
|
51
50
|
}
|
|
51
|
+
exports.downloadModel = downloadModel;
|
|
52
52
|
function getBestThumbnail(thumbnails, targetWidth = 280) {
|
|
53
53
|
if (!thumbnails?.images?.length) {
|
|
54
54
|
return '';
|
|
@@ -56,3 +56,4 @@ function getBestThumbnail(thumbnails, targetWidth = 280) {
|
|
|
56
56
|
const sorted = [...thumbnails.images].sort((left, right) => Math.abs(left.width - targetWidth) - Math.abs(right.width - targetWidth));
|
|
57
57
|
return sorted[0].url;
|
|
58
58
|
}
|
|
59
|
+
exports.getBestThumbnail = getBestThumbnail;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.useSketchfabSearch =
|
|
3
|
+
exports.useSketchfabSearch = void 0;
|
|
4
4
|
const react_1 = require("react");
|
|
5
5
|
const api_1 = require("./api");
|
|
6
6
|
function useSketchfabSearch({ apiKey, initialQuery = 'character humanoid avatar', debounceMs = 400, }) {
|
|
@@ -79,3 +79,4 @@ function useSketchfabSearch({ apiKey, initialQuery = 'character humanoid avatar'
|
|
|
79
79
|
prevPage,
|
|
80
80
|
};
|
|
81
81
|
}
|
|
82
|
+
exports.useSketchfabSearch = useSketchfabSearch;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.useDirectVisemeStream =
|
|
3
|
+
exports.useDirectVisemeStream = void 0;
|
|
4
4
|
const react_1 = require("react");
|
|
5
5
|
const fetch_1 = require("expo/fetch");
|
|
6
6
|
// How long to keep retrying a stream before giving up (ms).
|
|
@@ -100,6 +100,7 @@ function useDirectVisemeStream(onVisemes) {
|
|
|
100
100
|
}, []);
|
|
101
101
|
return { openStream };
|
|
102
102
|
}
|
|
103
|
+
exports.useDirectVisemeStream = useDirectVisemeStream;
|
|
103
104
|
// ─── SSE parser ──────────────────────────────────────────────────────────────
|
|
104
105
|
/**
|
|
105
106
|
* Reads an SSE stream to completion, dispatching `event: visemes` messages.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.useMotionMarkers =
|
|
3
|
+
exports.useMotionMarkers = void 0;
|
|
4
4
|
const react_1 = require("react");
|
|
5
5
|
/**
|
|
6
6
|
* Parses ::marker_name:: tokens out of LLM transcript text, fires the
|
|
@@ -22,3 +22,4 @@ function useMotionMarkers(ref) {
|
|
|
22
22
|
return '';
|
|
23
23
|
}), [ref]);
|
|
24
24
|
}
|
|
25
|
+
exports.useMotionMarkers = useMotionMarkers;
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.resolveFilamentAssetUri =
|
|
4
|
-
exports.resolveLocalAssetUrl = resolveLocalAssetUrl;
|
|
3
|
+
exports.resolveLocalAssetUrl = exports.resolveFilamentAssetUri = void 0;
|
|
5
4
|
const expo_asset_1 = require("expo-asset");
|
|
6
5
|
const react_native_1 = require("react-native");
|
|
7
6
|
const expo_file_system_1 = require("expo-file-system");
|
|
@@ -22,6 +21,7 @@ async function resolveFilamentAssetUri(module) {
|
|
|
22
21
|
return null;
|
|
23
22
|
}
|
|
24
23
|
}
|
|
24
|
+
exports.resolveFilamentAssetUri = resolveFilamentAssetUri;
|
|
25
25
|
/**
|
|
26
26
|
* Resolves a local Expo asset module (from require()) into a usable URL string.
|
|
27
27
|
* On web, returns an absolute URL.
|
|
@@ -54,3 +54,4 @@ async function resolveLocalAssetUrl(module) {
|
|
|
54
54
|
return null;
|
|
55
55
|
}
|
|
56
56
|
}
|
|
57
|
+
exports.resolveLocalAssetUrl = resolveLocalAssetUrl;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* faceLandmarkerToShapeWeights
|
|
3
|
+
*
|
|
4
|
+
* Runs MediaPipe FaceLandmarker on a photo and returns a
|
|
5
|
+
* faceShapeWeights Record<string, number> ready to store in
|
|
6
|
+
* AvatarAppearance. Works with any GLB that has ARKit morph
|
|
7
|
+
* target names — mesh-agnostic, pure named floats.
|
|
8
|
+
*
|
|
9
|
+
* Lazy-loads @mediapipe/tasks-vision on first call (~3MB WASM).
|
|
10
|
+
* Subsequent calls reuse the same FaceLandmarker instance.
|
|
11
|
+
*
|
|
12
|
+
* Apache 2.0 — no API key, no license restrictions.
|
|
13
|
+
*/
|
|
14
|
+
type ImageSource = HTMLImageElement | HTMLVideoElement | HTMLCanvasElement | ImageBitmap;
|
|
15
|
+
export type FaceShapeWeights = Record<string, number>;
|
|
16
|
+
export interface FaceLandmarkerOptions {
|
|
17
|
+
/**
|
|
18
|
+
* Minimum score threshold to include a blendshape weight.
|
|
19
|
+
* Shapes below this are omitted to keep the dict lean.
|
|
20
|
+
* Default: 0.01
|
|
21
|
+
*/
|
|
22
|
+
minScore?: number;
|
|
23
|
+
/**
|
|
24
|
+
* If true, also includes near-zero weights (useful for
|
|
25
|
+
* resetting a previously shaped face to neutral).
|
|
26
|
+
* Default: false
|
|
27
|
+
*/
|
|
28
|
+
includeNeutral?: boolean;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Detect face blendshapes from a photo and return a faceShapeWeights
|
|
32
|
+
* dict compatible with AvatarAppearance.
|
|
33
|
+
*
|
|
34
|
+
* @param source Any image/video/canvas/bitmap element
|
|
35
|
+
* @param options Optional thresholds
|
|
36
|
+
* @returns faceShapeWeights Record<string, number>, or null if no face detected
|
|
37
|
+
*/
|
|
38
|
+
export declare function faceLandmarkerToShapeWeights(source: ImageSource, options?: FaceLandmarkerOptions): Promise<FaceShapeWeights | null>;
|
|
39
|
+
/**
|
|
40
|
+
* Load the FaceLandmarker WASM bundle eagerly — call this on app start
|
|
41
|
+
* to avoid a cold-start delay when the user first uploads a photo.
|
|
42
|
+
*/
|
|
43
|
+
export declare function prefetchFaceLandmarker(): void;
|
|
44
|
+
export {};
|