talking-head-studio 0.4.0 → 0.4.2

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 (42) hide show
  1. package/dist/TalkingHeadVisualization.d.ts +1 -1
  2. package/dist/TalkingHeadVisualization.js +13 -13
  3. package/dist/editor/AvatarCanvas.d.ts +3 -14
  4. package/dist/editor/AvatarCanvas.js +5 -4
  5. package/dist/editor/AvatarEditor.d.ts +1 -0
  6. package/dist/editor/AvatarEditor.js +6 -0
  7. package/dist/editor/AvatarEditor.native.d.ts +4 -0
  8. package/dist/editor/AvatarEditor.native.js +93 -0
  9. package/dist/editor/boneSnap.d.ts +25 -0
  10. package/dist/editor/boneSnap.js +93 -0
  11. package/dist/editor/index.d.ts +4 -0
  12. package/dist/editor/index.js +13 -1
  13. package/dist/editor/types.d.ts +18 -4
  14. package/dist/utils/avatarUtils.d.ts +2 -3
  15. package/dist/utils/avatarUtils.js +5 -6
  16. package/dist/wardrobe/wardrobeStore.d.ts +1 -1
  17. package/dist/wgpu/WgpuAvatar.d.ts +3 -0
  18. package/dist/wgpu/WgpuAvatar.js +55 -87
  19. package/dist/{filament → wgpu}/morphTables.js +1 -1
  20. package/dist/wgpu/useAuthedModelUri.d.ts +11 -0
  21. package/dist/{filament/useAuthedFilamentUri.js → wgpu/useAuthedModelUri.js} +9 -9
  22. package/package.json +2 -15
  23. package/dist/filament/FilamentAvatar.d.ts +0 -41
  24. package/dist/filament/FilamentAvatar.js +0 -755
  25. package/dist/filament/editor/FilamentEditor.d.ts +0 -16
  26. package/dist/filament/editor/FilamentEditor.js +0 -880
  27. package/dist/filament/editor/FilamentEditor.web.d.ts +0 -19
  28. package/dist/filament/editor/FilamentEditor.web.js +0 -58
  29. package/dist/filament/editor/PrecisionPanel.d.ts +0 -1
  30. package/dist/filament/editor/PrecisionPanel.js +0 -252
  31. package/dist/filament/editor/boneSnap.d.ts +0 -10
  32. package/dist/filament/editor/boneSnap.js +0 -97
  33. package/dist/filament/editor/index.d.ts +0 -5
  34. package/dist/filament/editor/index.js +0 -19
  35. package/dist/filament/index.d.ts +0 -6
  36. package/dist/filament/index.js +0 -24
  37. package/dist/filament/useAuthedFilamentUri.d.ts +0 -11
  38. /package/dist/{filament/editor → editor}/studioTheme.d.ts +0 -0
  39. /package/dist/{filament/editor → editor}/studioTheme.js +0 -0
  40. /package/dist/{filament → wgpu}/faceSqueezeAssets.d.ts +0 -0
  41. /package/dist/{filament → wgpu}/faceSqueezeAssets.js +0 -0
  42. /package/dist/{filament → wgpu}/morphTables.d.ts +0 -0
@@ -1,19 +0,0 @@
1
- import { type ViewStyle } from 'react-native';
2
- import type { AvatarAppearance } from '../../appearance';
3
- import type { WearableAsset } from '../../api/types';
4
- import type { AssetPlacement } from '../../wardrobe/wardrobeStore';
5
- export interface FilamentEditorProps {
6
- avatarUrl: string;
7
- style?: ViewStyle;
8
- onDone: () => void;
9
- skinColor?: string;
10
- /** Web-only: structured appearance object (native uses skinColor hex) */
11
- appearance?: AvatarAppearance;
12
- equipped: Record<string, WearableAsset>;
13
- placements: Record<string, AssetPlacement>;
14
- activeAssetId: string | null;
15
- onActiveAssetChange: (assetId: string | null) => void;
16
- onPlacementChange: (assetId: string, placement: AssetPlacement) => void;
17
- }
18
- export declare function FilamentEditor({ avatarUrl, style, onDone, appearance, equipped, placements, activeAssetId, onPlacementChange, }: FilamentEditorProps): import("react/jsx-runtime").JSX.Element;
19
- export default FilamentEditor;
@@ -1,58 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.FilamentEditor = void 0;
4
- const jsx_runtime_1 = require("react/jsx-runtime");
5
- const react_native_1 = require("react-native");
6
- const editor_1 = require("../../editor");
7
- function FilamentEditor({ avatarUrl, style, onDone, appearance, equipped, placements, activeAssetId, onPlacementChange, }) {
8
- // Convert Record<slot, WearableAsset> → EquippedAsset[] for AvatarCanvas
9
- const equippedItems = Object.values(equipped)
10
- .filter(Boolean)
11
- .map((a) => ({
12
- id: a.id,
13
- url: a.url,
14
- slot: a.slot,
15
- type: a.type,
16
- attach_bone: a.attach_bone ?? undefined,
17
- offset_position: a.offset_position ?? undefined,
18
- offset_rotation: a.offset_rotation ?? undefined,
19
- }));
20
- const normalizedPlacements = Object.fromEntries(Object.entries(placements).map(([assetId, placement]) => [
21
- assetId,
22
- {
23
- ...placement,
24
- scale: placement.scale,
25
- },
26
- ]));
27
- const handlePlacementChange = (assetId, placement) => {
28
- onPlacementChange(assetId, {
29
- bone: placement.bone,
30
- position: placement.position,
31
- rotation: placement.rotation,
32
- scale: placement.scale ?? 1,
33
- });
34
- };
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
- }
37
- exports.FilamentEditor = FilamentEditor;
38
- exports.default = FilamentEditor;
39
- const styles = react_native_1.StyleSheet.create({
40
- container: {
41
- flex: 1,
42
- position: 'relative',
43
- },
44
- doneButton: {
45
- position: 'absolute',
46
- top: 12,
47
- right: 16,
48
- backgroundColor: '#6c63ff',
49
- borderRadius: 8,
50
- paddingHorizontal: 16,
51
- paddingVertical: 8,
52
- },
53
- doneText: {
54
- color: '#fff',
55
- fontWeight: '700',
56
- fontSize: 14,
57
- },
58
- });
@@ -1 +0,0 @@
1
- export default function PrecisionPanel(): import("react/jsx-runtime").JSX.Element | null;
@@ -1,252 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
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
- };
25
- Object.defineProperty(exports, "__esModule", { value: true });
26
- const jsx_runtime_1 = require("react/jsx-runtime");
27
- const react_1 = require("react");
28
- const react_native_1 = require("react-native");
29
- const react_native_gesture_handler_1 = require("react-native-gesture-handler");
30
- const react_native_reanimated_1 = __importStar(require("react-native-reanimated"));
31
- const Haptics = __importStar(require("expo-haptics"));
32
- const moti_1 = require("moti");
33
- const wardrobeStore_1 = require("../../wardrobe/wardrobeStore");
34
- const TICK_COUNT = 81;
35
- const PIXELS_PER_STEP = 10;
36
- const WRAP_DISTANCE = 50; // 5 ticks * 10 pixels
37
- const MODES = [
38
- { key: 'translate', label: 'Position' },
39
- { key: 'rotate', label: 'Rotation' },
40
- { key: 'scale', label: 'Scale' },
41
- ];
42
- const PrecisionSlider = ({ label, value, onChange, step, unit = '', }) => {
43
- const startValue = (0, react_native_reanimated_1.useSharedValue)(0);
44
- const lastHapticTick = (0, react_native_reanimated_1.useSharedValue)(0);
45
- const currentValue = (0, react_native_reanimated_1.useSharedValue)(value);
46
- (0, react_1.useEffect)(() => {
47
- currentValue.value = value;
48
- }, [value, currentValue]);
49
- const triggerHaptic = () => {
50
- Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light);
51
- };
52
- const inDeadzone = (0, react_native_reanimated_1.useSharedValue)(false);
53
- const pan = react_native_gesture_handler_1.Gesture.Pan()
54
- .onStart(() => {
55
- startValue.value = currentValue.value;
56
- lastHapticTick.value = 0;
57
- inDeadzone.value = false;
58
- })
59
- .onUpdate((event) => {
60
- const deltaSteps = event.translationX / PIXELS_PER_STEP;
61
- const deltaValue = deltaSteps * step;
62
- let newValue = startValue.value + deltaValue;
63
- if (label === 'Uniform' && newValue < 0.01) {
64
- newValue = 0.01;
65
- }
66
- // Detent at 0 (snap to 0 and fire Medium haptic)
67
- if (Math.abs(newValue) < step * 1.5) {
68
- if (!inDeadzone.value) {
69
- inDeadzone.value = true;
70
- (0, react_native_reanimated_1.runOnJS)(Haptics.impactAsync)(Haptics.ImpactFeedbackStyle.Medium);
71
- }
72
- newValue = 0; // Snap exactly to 0
73
- }
74
- else {
75
- inDeadzone.value = false;
76
- // Light haptic every tick outside deadzone
77
- const ticks = Math.floor(Math.abs(event.translationX) / PIXELS_PER_STEP);
78
- if (ticks > lastHapticTick.value) {
79
- lastHapticTick.value = ticks;
80
- (0, react_native_reanimated_1.runOnJS)(triggerHaptic)();
81
- }
82
- }
83
- currentValue.value = newValue;
84
- (0, react_native_reanimated_1.runOnJS)(onChange)(newValue);
85
- });
86
- const animatedTapeStyle = (0, react_native_reanimated_1.useAnimatedStyle)(() => {
87
- const tapePosition = (currentValue.value / step) * PIXELS_PER_STEP;
88
- const remainder = tapePosition % WRAP_DISTANCE;
89
- return {
90
- transform: [{ translateX: remainder }],
91
- };
92
- });
93
- const tickMarks = (0, react_1.useMemo)(() => Array.from({ length: TICK_COUNT }).map((_, i) => {
94
- const isMajor = i % 5 === 0;
95
- return ((0, jsx_runtime_1.jsx)(react_native_1.View, { style: styles.tickContainer, children: (0, jsx_runtime_1.jsx)(react_native_1.View, { style: [styles.tickMark, isMajor && styles.tickMarkMajor] }) }, i));
96
- }), []);
97
- return ((0, jsx_runtime_1.jsxs)(react_native_1.View, { style: styles.sliderRow, children: [(0, jsx_runtime_1.jsxs)(react_native_1.View, { style: styles.sliderLabelContainer, children: [(0, jsx_runtime_1.jsx)(react_native_1.Text, { style: styles.sliderLabel, children: label }), (0, jsx_runtime_1.jsxs)(react_native_1.Text, { style: styles.sliderValueText, children: [value.toFixed(2), unit] })] }), (0, jsx_runtime_1.jsx)(react_native_gesture_handler_1.GestureDetector, { gesture: pan, children: (0, jsx_runtime_1.jsxs)(react_native_1.View, { style: styles.dialContainer, children: [(0, jsx_runtime_1.jsx)(react_native_reanimated_1.default.View, { style: [styles.dialTape, animatedTapeStyle], children: tickMarks }), (0, jsx_runtime_1.jsx)(react_native_1.View, { style: styles.centerPointer })] }) })] }));
98
- };
99
- function PrecisionPanel() {
100
- const activeAssetId = (0, wardrobeStore_1.useWardrobeStore)((s) => s.activeAssetId);
101
- const placements = (0, wardrobeStore_1.useWardrobeStore)((s) => s.placements);
102
- const setPlacement = (0, wardrobeStore_1.useWardrobeStore)((s) => s.setPlacement);
103
- const gizmoMode = (0, wardrobeStore_1.useWardrobeStore)((s) => s.gizmoMode);
104
- const setGizmoMode = (0, wardrobeStore_1.useWardrobeStore)((s) => s.setGizmoMode);
105
- if (!activeAssetId) {
106
- return null;
107
- }
108
- const placement = placements[activeAssetId];
109
- if (!placement) {
110
- console.warn('[PrecisionPanel] No placement data for asset:', activeAssetId);
111
- return null;
112
- }
113
- const updateAxis = (axis, val) => {
114
- if (!activeAssetId || !placement)
115
- return;
116
- if (gizmoMode === 'translate') {
117
- const pos = [...placement.position];
118
- if (axis === 'x')
119
- pos[0] = val;
120
- if (axis === 'y')
121
- pos[1] = val;
122
- if (axis === 'z')
123
- pos[2] = val;
124
- setPlacement(activeAssetId, { ...placement, position: pos });
125
- }
126
- else if (gizmoMode === 'rotate') {
127
- const rot = [...placement.rotation];
128
- if (axis === 'x')
129
- rot[0] = val;
130
- if (axis === 'y')
131
- rot[1] = val;
132
- if (axis === 'z')
133
- rot[2] = val;
134
- setPlacement(activeAssetId, { ...placement, rotation: rot });
135
- }
136
- };
137
- const updateScale = (val) => {
138
- if (!activeAssetId || !placement)
139
- return;
140
- setPlacement(activeAssetId, { ...placement, scale: val });
141
- };
142
- return ((0, jsx_runtime_1.jsxs)(moti_1.MotiView, { from: { opacity: 0, translateY: 100 }, animate: { opacity: 1, translateY: 0 }, transition: { type: 'timing', duration: 180 }, style: styles.container, children: [(0, jsx_runtime_1.jsx)(react_native_1.View, { style: styles.segmentedControl, children: MODES.map((m) => {
143
- const isActive = gizmoMode === m.key;
144
- return ((0, jsx_runtime_1.jsx)(react_native_1.Pressable, { style: [styles.segmentButton, isActive && styles.segmentButtonActive], onPress: () => {
145
- setGizmoMode(m.key);
146
- Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light);
147
- }, children: (0, jsx_runtime_1.jsx)(react_native_1.Text, { style: [styles.segmentText, isActive && styles.segmentTextActive], children: m.label }) }, m.key));
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 }) }))] }));
149
- }
150
- exports.default = PrecisionPanel;
151
- const styles = react_native_1.StyleSheet.create({
152
- container: {
153
- position: 'absolute',
154
- bottom: 24,
155
- left: 16,
156
- right: 16,
157
- backgroundColor: '#161d28',
158
- borderRadius: 16,
159
- borderWidth: 1,
160
- borderColor: '#232933',
161
- padding: 16,
162
- shadowColor: '#000',
163
- shadowOffset: { width: 0, height: 8 },
164
- shadowOpacity: 0.4,
165
- shadowRadius: 16,
166
- elevation: 10,
167
- },
168
- segmentedControl: {
169
- flexDirection: 'row',
170
- backgroundColor: '#0a0a0a',
171
- borderRadius: 8,
172
- padding: 4,
173
- marginBottom: 20,
174
- borderWidth: 1,
175
- borderColor: '#232933',
176
- },
177
- segmentButton: {
178
- flex: 1,
179
- paddingVertical: 8,
180
- alignItems: 'center',
181
- borderRadius: 6,
182
- },
183
- segmentButtonActive: {
184
- backgroundColor: '#232933',
185
- },
186
- segmentText: {
187
- color: '#8892b0',
188
- fontSize: 13,
189
- fontWeight: '600',
190
- },
191
- segmentTextActive: {
192
- color: '#f1f5fb',
193
- },
194
- sliderRow: {
195
- marginBottom: 16,
196
- },
197
- sliderLabelContainer: {
198
- flexDirection: 'row',
199
- justifyContent: 'space-between',
200
- marginBottom: 8,
201
- paddingHorizontal: 4,
202
- },
203
- sliderLabel: {
204
- color: '#8892b0',
205
- fontSize: 12,
206
- fontWeight: '600',
207
- textTransform: 'uppercase',
208
- letterSpacing: 0.5,
209
- },
210
- sliderValueText: {
211
- color: '#6c63ff',
212
- fontSize: 13,
213
- fontWeight: '700',
214
- fontVariant: ['tabular-nums'],
215
- },
216
- dialContainer: {
217
- height: 44,
218
- backgroundColor: '#0a0a0a',
219
- borderRadius: 8,
220
- overflow: 'hidden',
221
- justifyContent: 'center',
222
- alignItems: 'center',
223
- borderWidth: 1,
224
- borderColor: '#232933',
225
- },
226
- dialTape: {
227
- flexDirection: 'row',
228
- alignItems: 'center',
229
- position: 'absolute',
230
- },
231
- tickContainer: {
232
- width: 10,
233
- alignItems: 'center',
234
- },
235
- tickMark: {
236
- width: 2,
237
- height: 12,
238
- backgroundColor: '#3b4353',
239
- borderRadius: 1,
240
- },
241
- tickMarkMajor: {
242
- height: 20,
243
- backgroundColor: '#8892b0',
244
- },
245
- centerPointer: {
246
- position: 'absolute',
247
- width: 2,
248
- height: 28,
249
- backgroundColor: '#6c63ff',
250
- borderRadius: 1,
251
- },
252
- });
@@ -1,10 +0,0 @@
1
- import type { AssetPlacement } from '../../wardrobe/wardrobeStore';
2
- export declare const HUMANOID_BONES: Record<string, [number, number, number]>;
3
- export declare function findNearestBone(position: [number, number, number]): {
4
- bone: string;
5
- distance: number;
6
- position: [number, number, number];
7
- };
8
- export declare function getWorldPositionForPlacement(placement: Pick<AssetPlacement, 'bone' | 'position'>): [number, number, number];
9
- export declare function snapPlacementToNearestBone(placement: AssetPlacement): AssetPlacement;
10
- export declare function useBoneSnap(): () => void;
@@ -1,97 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
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
- };
25
- Object.defineProperty(exports, "__esModule", { value: true });
26
- exports.useBoneSnap = exports.snapPlacementToNearestBone = exports.getWorldPositionForPlacement = exports.findNearestBone = exports.HUMANOID_BONES = void 0;
27
- const react_1 = require("react");
28
- const Haptics = __importStar(require("expo-haptics"));
29
- const wardrobeStore_1 = require("../../wardrobe/wardrobeStore");
30
- exports.HUMANOID_BONES = {
31
- Head: [0, 0.12, 0],
32
- Neck: [0, 1.5, 0],
33
- Spine: [0, 1.0, 0],
34
- RightHand: [0.8, 1.0, 0],
35
- LeftHand: [-0.8, 1.0, 0],
36
- RightFoot: [0.2, 0.1, 0],
37
- LeftFoot: [-0.2, 0.1, 0],
38
- };
39
- function findNearestBone(position) {
40
- let nearestBone = 'Head';
41
- let minDistance = Infinity;
42
- let nearestPos = [0, 1.7, 0];
43
- const [px, py, pz] = position;
44
- for (const [bone, pos] of Object.entries(exports.HUMANOID_BONES)) {
45
- const [bx, by, bz] = pos;
46
- const distance = Math.sqrt((px - bx) * (px - bx) +
47
- (py - by) * (py - by) +
48
- (pz - bz) * (pz - bz));
49
- if (distance < minDistance) {
50
- minDistance = distance;
51
- nearestBone = bone;
52
- nearestPos = pos;
53
- }
54
- }
55
- return {
56
- bone: nearestBone,
57
- distance: minDistance,
58
- position: nearestPos,
59
- };
60
- }
61
- exports.findNearestBone = findNearestBone;
62
- function getWorldPositionForPlacement(placement) {
63
- const bonePos = exports.HUMANOID_BONES[placement.bone] ?? exports.HUMANOID_BONES['Head'];
64
- return [
65
- bonePos[0] + placement.position[0],
66
- bonePos[1] + placement.position[1],
67
- bonePos[2] + placement.position[2],
68
- ];
69
- }
70
- exports.getWorldPositionForPlacement = getWorldPositionForPlacement;
71
- function snapPlacementToNearestBone(placement) {
72
- const nearest = findNearestBone(getWorldPositionForPlacement(placement));
73
- return {
74
- ...placement,
75
- bone: nearest.bone,
76
- position: [0, 0, 0],
77
- };
78
- }
79
- exports.snapPlacementToNearestBone = snapPlacementToNearestBone;
80
- function useBoneSnap() {
81
- const activeAssetId = (0, wardrobeStore_1.useWardrobeStore)((state) => state.activeAssetId);
82
- const placements = (0, wardrobeStore_1.useWardrobeStore)((state) => state.placements);
83
- const setPlacement = (0, wardrobeStore_1.useWardrobeStore)((state) => state.setPlacement);
84
- const snap = (0, react_1.useCallback)(() => {
85
- if (!activeAssetId)
86
- return;
87
- const placement = placements[activeAssetId];
88
- if (!placement)
89
- return;
90
- setPlacement(activeAssetId, snapPlacementToNearestBone(placement));
91
- Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Heavy).catch(() => {
92
- // Ignore if haptics fail or aren't supported
93
- });
94
- }, [activeAssetId, placements, setPlacement]);
95
- return snap;
96
- }
97
- exports.useBoneSnap = useBoneSnap;
@@ -1,5 +0,0 @@
1
- export { FilamentEditor } from './FilamentEditor';
2
- export type { FilamentEditorProps } from './FilamentEditor';
3
- export { default as PrecisionPanel } from './PrecisionPanel';
4
- export { studioTheme, withAlpha } from './studioTheme';
5
- export { HUMANOID_BONES, findNearestBone, getWorldPositionForPlacement, snapPlacementToNearestBone, useBoneSnap, } from './boneSnap';
@@ -1,19 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.useBoneSnap = exports.snapPlacementToNearestBone = exports.getWorldPositionForPlacement = exports.findNearestBone = exports.HUMANOID_BONES = exports.withAlpha = exports.studioTheme = exports.PrecisionPanel = exports.FilamentEditor = void 0;
7
- var FilamentEditor_1 = require("./FilamentEditor");
8
- Object.defineProperty(exports, "FilamentEditor", { enumerable: true, get: function () { return FilamentEditor_1.FilamentEditor; } });
9
- var PrecisionPanel_1 = require("./PrecisionPanel");
10
- Object.defineProperty(exports, "PrecisionPanel", { enumerable: true, get: function () { return __importDefault(PrecisionPanel_1).default; } });
11
- var studioTheme_1 = require("./studioTheme");
12
- Object.defineProperty(exports, "studioTheme", { enumerable: true, get: function () { return studioTheme_1.studioTheme; } });
13
- Object.defineProperty(exports, "withAlpha", { enumerable: true, get: function () { return studioTheme_1.withAlpha; } });
14
- var boneSnap_1 = require("./boneSnap");
15
- Object.defineProperty(exports, "HUMANOID_BONES", { enumerable: true, get: function () { return boneSnap_1.HUMANOID_BONES; } });
16
- Object.defineProperty(exports, "findNearestBone", { enumerable: true, get: function () { return boneSnap_1.findNearestBone; } });
17
- Object.defineProperty(exports, "getWorldPositionForPlacement", { enumerable: true, get: function () { return boneSnap_1.getWorldPositionForPlacement; } });
18
- Object.defineProperty(exports, "snapPlacementToNearestBone", { enumerable: true, get: function () { return boneSnap_1.snapPlacementToNearestBone; } });
19
- Object.defineProperty(exports, "useBoneSnap", { enumerable: true, get: function () { return boneSnap_1.useBoneSnap; } });
@@ -1,6 +0,0 @@
1
- export { FilamentAvatar } from './FilamentAvatar';
2
- export type { FilamentAvatarRef } from './FilamentAvatar';
3
- export { useAuthedFilamentUri } from './useAuthedFilamentUri';
4
- export type { AuthedFileResult } from './useAuthedFilamentUri';
5
- export * from './morphTables';
6
- export { FACE_SQUEEZE_LOCAL_MODULE } from './faceSqueezeAssets';
@@ -1,24 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
- for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
- };
16
- Object.defineProperty(exports, "__esModule", { value: true });
17
- exports.FACE_SQUEEZE_LOCAL_MODULE = exports.useAuthedFilamentUri = exports.FilamentAvatar = void 0;
18
- var FilamentAvatar_1 = require("./FilamentAvatar");
19
- Object.defineProperty(exports, "FilamentAvatar", { enumerable: true, get: function () { return FilamentAvatar_1.FilamentAvatar; } });
20
- var useAuthedFilamentUri_1 = require("./useAuthedFilamentUri");
21
- Object.defineProperty(exports, "useAuthedFilamentUri", { enumerable: true, get: function () { return useAuthedFilamentUri_1.useAuthedFilamentUri; } });
22
- __exportStar(require("./morphTables"), exports);
23
- var faceSqueezeAssets_1 = require("./faceSqueezeAssets");
24
- Object.defineProperty(exports, "FACE_SQUEEZE_LOCAL_MODULE", { enumerable: true, get: function () { return faceSqueezeAssets_1.FACE_SQUEEZE_LOCAL_MODULE; } });
@@ -1,11 +0,0 @@
1
- export type AuthedFileResult = {
2
- uri: string;
3
- size: number;
4
- } | null;
5
- /**
6
- * Downloads a remote URL (with Bearer auth) to the local cache and returns a
7
- * `file://` URI suitable for react-native-filament's <Model> source prop.
8
- * The native Filament fetcher doesn't send auth headers, so we pre-fetch here.
9
- * Also returns the file size in bytes for GPU memory budgeting.
10
- */
11
- export declare function useAuthedFilamentUri(remoteUrl: string | null): AuthedFileResult;
File without changes
File without changes
File without changes
File without changes