@memori.ai/memori-react 7.8.3 → 7.8.5

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 (66) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/dist/components/Avatar/Avatar.js.map +1 -1
  3. package/dist/components/Avatar/AvatarView/AvatarComponent/avatarComponent.js +4 -2
  4. package/dist/components/Avatar/AvatarView/AvatarComponent/avatarComponent.js.map +1 -1
  5. package/dist/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/AnimationController.d.ts +34 -0
  6. package/dist/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/AnimationController.js +147 -0
  7. package/dist/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/AnimationController.js.map +1 -0
  8. package/dist/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/MorhTargetController.d.ts +17 -0
  9. package/dist/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/MorhTargetController.js +73 -0
  10. package/dist/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/MorhTargetController.js.map +1 -0
  11. package/dist/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/constants.d.ts +17 -0
  12. package/dist/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/constants.js +25 -0
  13. package/dist/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/constants.js.map +1 -0
  14. package/dist/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/fullbodyAvatar.d.ts +2 -0
  15. package/dist/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/fullbodyAvatar.js +83 -0
  16. package/dist/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/fullbodyAvatar.js.map +1 -0
  17. package/dist/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/types.d.ts +35 -0
  18. package/dist/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/types.js +10 -0
  19. package/dist/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/types.js.map +1 -0
  20. package/dist/components/Avatar/AvatarView/index.js.map +1 -1
  21. package/dist/components/MemoriWidget/MemoriWidget.js +2 -2
  22. package/dist/components/MemoriWidget/MemoriWidget.js.map +1 -1
  23. package/dist/context/visemeContext.d.ts +1 -1
  24. package/dist/context/visemeContext.js +2 -2
  25. package/dist/context/visemeContext.js.map +1 -1
  26. package/dist/index.js +1 -1
  27. package/dist/index.js.map +1 -1
  28. package/esm/components/Avatar/Avatar.js.map +1 -1
  29. package/esm/components/Avatar/AvatarView/AvatarComponent/avatarComponent.js +4 -2
  30. package/esm/components/Avatar/AvatarView/AvatarComponent/avatarComponent.js.map +1 -1
  31. package/esm/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/AnimationController.d.ts +34 -0
  32. package/esm/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/AnimationController.js +143 -0
  33. package/esm/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/AnimationController.js.map +1 -0
  34. package/esm/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/MorhTargetController.d.ts +17 -0
  35. package/esm/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/MorhTargetController.js +69 -0
  36. package/esm/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/MorhTargetController.js.map +1 -0
  37. package/esm/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/constants.d.ts +17 -0
  38. package/esm/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/constants.js +22 -0
  39. package/esm/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/constants.js.map +1 -0
  40. package/esm/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/fullbodyAvatar.d.ts +2 -0
  41. package/esm/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/fullbodyAvatar.js +80 -0
  42. package/esm/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/fullbodyAvatar.js.map +1 -0
  43. package/esm/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/types.d.ts +35 -0
  44. package/esm/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/types.js +7 -0
  45. package/esm/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/types.js.map +1 -0
  46. package/esm/components/Avatar/AvatarView/index.js.map +1 -1
  47. package/esm/components/MemoriWidget/MemoriWidget.js +2 -2
  48. package/esm/components/MemoriWidget/MemoriWidget.js.map +1 -1
  49. package/esm/context/visemeContext.d.ts +1 -1
  50. package/esm/context/visemeContext.js +2 -2
  51. package/esm/context/visemeContext.js.map +1 -1
  52. package/esm/index.js +1 -1
  53. package/esm/index.js.map +1 -1
  54. package/package.json +1 -1
  55. package/src/components/Avatar/Avatar.tsx +2 -3
  56. package/src/components/Avatar/AvatarView/AvatarComponent/avatarComponent.tsx +6 -13
  57. package/src/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/AnimationController.ts +260 -0
  58. package/src/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/MorhTargetController.ts +123 -0
  59. package/src/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/constants.ts +28 -0
  60. package/src/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/fullbodyAvatar.tsx +147 -0
  61. package/src/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/types.ts +40 -0
  62. package/src/components/Avatar/AvatarView/index.tsx +4 -4
  63. package/src/components/MemoriWidget/MemoriWidget.tsx +2 -2
  64. package/src/context/visemeContext.tsx +2 -2
  65. package/src/index.tsx +5 -1
  66. package/src/components/Avatar/AvatarView/AvatarComponent/components/fullbodyAvatar.tsx +0 -281
@@ -1,281 +0,0 @@
1
- import React, { useEffect, useRef, useMemo, useCallback } from 'react';
2
- import {
3
- Vector3,
4
- Euler,
5
- AnimationMixer,
6
- SkinnedMesh,
7
- Object3D,
8
- MathUtils,
9
- AnimationAction,
10
- LoopOnce,
11
- } from 'three';
12
- import { useAnimations, useGLTF } from '@react-three/drei';
13
- import { useGraph, useFrame } from '@react-three/fiber';
14
-
15
- interface FullbodyAvatarProps {
16
- url: string;
17
- sex: 'MALE' | 'FEMALE';
18
- onLoaded?: () => void;
19
- currentBaseAction: {
20
- action: string;
21
- weight: number;
22
- };
23
- timeScale: number;
24
- isZoomed?: boolean;
25
- eyeBlink?: boolean;
26
- stopProcessing: () => void;
27
- resetVisemeQueue: () => void;
28
- updateCurrentViseme: (
29
- currentTime: number
30
- ) => { name: string; weight: number } | null;
31
- smoothMorphTarget?: boolean;
32
- morphTargetSmoothing?: number;
33
- morphTargetInfluences: Record<string, number>;
34
- setMorphTargetDictionary: (
35
- morphTargetDictionary: Record<string, number>
36
- ) => void;
37
- setMorphTargetInfluences: (
38
- morphTargetInfluences: Record<string, number>
39
- ) => void;
40
- emotionMorphTargets: Record<string, number>;
41
- }
42
-
43
- const AVATAR_POSITION = new Vector3(0, -1, 0);
44
- const AVATAR_ROTATION = new Euler(0.175, 0, 0);
45
- const AVATAR_POSITION_ZOOMED = new Vector3(0, -1.45, 0);
46
-
47
- const ANIMATION_URLS = {
48
- MALE: 'https://assets.memori.ai/api/v2/asset/2c5e88a4-cf62-408b-9ef0-518b099dfcb2.glb',
49
- FEMALE:
50
- 'https://assets.memori.ai/api/v2/asset/8d1a5853-f05a-4a34-9f99-6eff64986081.glb',
51
- };
52
-
53
- const BLINK_CONFIG = {
54
- minInterval: 1000,
55
- maxInterval: 5000,
56
- blinkDuration: 150,
57
- };
58
-
59
- const EMOTION_SMOOTHING = 0.3;
60
- const VISME_SMOOTHING = 0.5;
61
-
62
- export default function FullbodyAvatar({
63
- url,
64
- sex,
65
- currentBaseAction,
66
- timeScale,
67
- isZoomed,
68
- eyeBlink,
69
- updateCurrentViseme,
70
- setMorphTargetDictionary,
71
- setMorphTargetInfluences,
72
- emotionMorphTargets,
73
- }: FullbodyAvatarProps) {
74
- const { scene } = useGLTF(url);
75
- const { animations } = useGLTF(ANIMATION_URLS[sex]);
76
- const { actions } = useAnimations(animations, scene);
77
-
78
- const mixerRef = useRef<AnimationMixer>();
79
- const headMeshRef = useRef<SkinnedMesh>();
80
- const currentActionRef = useRef<AnimationAction | null>(null);
81
- const isTransitioningToIdleRef = useRef(false);
82
-
83
- const lastBlinkTimeRef = useRef(0);
84
- const nextBlinkTimeRef = useRef(0);
85
- const isBlinkingRef = useRef(false);
86
- const blinkStartTimeRef = useRef(0);
87
-
88
- const currentEmotionRef = useRef<Record<string, number>>({});
89
- const previousEmotionKeysRef = useRef<Set<string>>(new Set());
90
-
91
- // Memoize the scene traversal
92
- const headMesh = useMemo(() => {
93
- let foundMesh: SkinnedMesh | undefined;
94
- scene.traverse((object: Object3D) => {
95
- if (
96
- object instanceof SkinnedMesh &&
97
- (object.name === 'GBNL__Head' || object.name === 'Wolf3D_Avatar')
98
- ) {
99
- foundMesh = object;
100
- }
101
- });
102
- return foundMesh;
103
- }, [scene]);
104
-
105
- useEffect(() => {
106
- if (headMesh) {
107
- headMeshRef.current = headMesh;
108
- if (headMesh.morphTargetDictionary && headMesh.morphTargetInfluences) {
109
- setMorphTargetDictionary(headMesh.morphTargetDictionary);
110
- const initialInfluences = Object.keys(
111
- headMesh.morphTargetDictionary
112
- ).reduce((acc, key) => ({ ...acc, [key]: 0 }), {});
113
- setMorphTargetInfluences(initialInfluences);
114
- }
115
- }
116
- mixerRef.current = new AnimationMixer(scene);
117
- }, [headMesh, scene, setMorphTargetDictionary, setMorphTargetInfluences]);
118
-
119
- // Memoize the animation change handler
120
- const handleAnimationChange = useCallback(() => {
121
- if (!actions || !currentBaseAction.action) return;
122
-
123
- const newAction = actions[currentBaseAction.action];
124
- if (!newAction) {
125
- console.warn(
126
- `Animation "${currentBaseAction.action}" not found in actions.`
127
- );
128
- return;
129
- }
130
-
131
- const fadeOutDuration = 0.8;
132
- const fadeInDuration = 0.8;
133
-
134
- if (currentActionRef.current) {
135
- currentActionRef.current.fadeOut(fadeOutDuration);
136
- }
137
-
138
- newAction.reset().fadeIn(fadeInDuration).play();
139
- currentActionRef.current = newAction;
140
- newAction.timeScale = timeScale;
141
-
142
- if (
143
- currentBaseAction.action.startsWith('Gioia') ||
144
- currentBaseAction.action.startsWith('Rabbia') ||
145
- currentBaseAction.action.startsWith('Sorpresa') ||
146
- currentBaseAction.action.startsWith('Timore') ||
147
- currentBaseAction.action.startsWith('Tristezza')
148
- ) {
149
- newAction.setLoop(LoopOnce, 1);
150
- newAction.clampWhenFinished = true;
151
- isTransitioningToIdleRef.current = true;
152
- }
153
- }, [actions, currentBaseAction, timeScale]);
154
-
155
- useEffect(() => {
156
- handleAnimationChange();
157
- }, [handleAnimationChange]);
158
-
159
- // Optimize the frame update function
160
- const updateFrame = useCallback(
161
- (currentTime: number) => {
162
- if (
163
- !headMeshRef.current ||
164
- !headMeshRef.current.morphTargetDictionary ||
165
- !headMeshRef.current.morphTargetInfluences
166
- )
167
- return;
168
-
169
- let blinkValue = 0;
170
- if (eyeBlink) {
171
- if (currentTime >= nextBlinkTimeRef.current && !isBlinkingRef.current) {
172
- isBlinkingRef.current = true;
173
- blinkStartTimeRef.current = currentTime;
174
- lastBlinkTimeRef.current = currentTime;
175
- nextBlinkTimeRef.current =
176
- currentTime +
177
- Math.random() *
178
- (BLINK_CONFIG.maxInterval - BLINK_CONFIG.minInterval) +
179
- BLINK_CONFIG.minInterval;
180
- }
181
-
182
- if (isBlinkingRef.current) {
183
- const blinkProgress =
184
- (currentTime - blinkStartTimeRef.current) /
185
- BLINK_CONFIG.blinkDuration;
186
- if (blinkProgress <= 0.5) {
187
- blinkValue = blinkProgress * 2;
188
- } else if (blinkProgress <= 1) {
189
- blinkValue = 2 - blinkProgress * 2;
190
- } else {
191
- isBlinkingRef.current = false;
192
- blinkValue = 0;
193
- }
194
- }
195
- }
196
-
197
- // Update current viseme
198
- const currentViseme = updateCurrentViseme(currentTime / 1000);
199
- const currentEmotionKeys = new Set(Object.keys(emotionMorphTargets));
200
-
201
- // Update morph target influences
202
- Object.entries(headMeshRef.current.morphTargetDictionary).forEach(
203
- ([key, index]) => {
204
- if (typeof index === 'number') {
205
- let targetValue = 0;
206
-
207
- if (currentEmotionKeys.has(key)) {
208
- const targetEmotionValue = emotionMorphTargets[key];
209
- const currentEmotionValue = currentEmotionRef.current[key] || 0;
210
- const newEmotionValue = MathUtils.lerp(
211
- currentEmotionValue,
212
- targetEmotionValue * 2.5,
213
- EMOTION_SMOOTHING
214
- );
215
- currentEmotionRef.current[key] = newEmotionValue;
216
- targetValue += newEmotionValue;
217
- }
218
-
219
- if (currentViseme && key === currentViseme.name) {
220
- targetValue += currentViseme.weight;
221
- }
222
-
223
- if (key === 'eyesClosed' && eyeBlink) {
224
- targetValue += blinkValue;
225
- }
226
-
227
- targetValue = MathUtils.clamp(targetValue, 0, 1);
228
- if (
229
- headMeshRef.current &&
230
- headMeshRef.current.morphTargetInfluences
231
- ) {
232
- headMeshRef.current.morphTargetInfluences[index] = MathUtils.lerp(
233
- headMeshRef.current.morphTargetInfluences[index],
234
- targetValue,
235
- VISME_SMOOTHING
236
- );
237
- }
238
- }
239
- }
240
- );
241
-
242
- // Update previous emotion keys
243
- previousEmotionKeysRef.current = currentEmotionKeys;
244
-
245
- // Transition to idle
246
- if (isTransitioningToIdleRef.current && currentActionRef.current) {
247
- if (
248
- currentActionRef.current.time >=
249
- currentActionRef.current.getClip().duration
250
- ) {
251
- const idleNumber = Math.floor(Math.random() * 5) + 1;
252
- const idleAction =
253
- actions[`Idle${idleNumber === 3 ? 4 : idleNumber}`];
254
-
255
- if (idleAction) {
256
- currentActionRef.current.fadeOut(0.5);
257
- idleAction.reset().fadeIn(0.5).play();
258
- currentActionRef.current = idleAction;
259
- isTransitioningToIdleRef.current = false;
260
- }
261
- }
262
- }
263
-
264
- mixerRef.current?.update(0.01);
265
- },
266
- [actions, emotionMorphTargets, eyeBlink, updateCurrentViseme]
267
- );
268
-
269
- useFrame(state => {
270
- updateFrame(state.clock.elapsedTime * 1000);
271
- });
272
-
273
- return (
274
- <group
275
- position={isZoomed ? AVATAR_POSITION_ZOOMED : AVATAR_POSITION}
276
- rotation={AVATAR_ROTATION}
277
- >
278
- <primitive object={scene} />
279
- </group>
280
- );
281
- }