@memori.ai/memori-react 7.7.0 → 7.8.0-rc.0

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 (178) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/dist/components/Avatar/Avatar.js +2 -2
  3. package/dist/components/Avatar/Avatar.js.map +1 -1
  4. package/dist/components/Avatar/AvatarView/AvatarComponent/avatarComponent.d.ts +2 -0
  5. package/dist/components/Avatar/AvatarView/AvatarComponent/avatarComponent.js +2 -2
  6. package/dist/components/Avatar/AvatarView/AvatarComponent/avatarComponent.js.map +1 -1
  7. package/dist/components/Avatar/AvatarView/AvatarComponent/components/fullbodyAvatar.d.ts +2 -0
  8. package/dist/components/Avatar/AvatarView/AvatarComponent/components/fullbodyAvatar.js +1 -1
  9. package/dist/components/Avatar/AvatarView/AvatarComponent/components/fullbodyAvatar.js.map +1 -1
  10. package/dist/components/Avatar/AvatarView/AvatarComponent/components/halfbodyAvatar.d.ts +3 -1
  11. package/dist/components/Avatar/AvatarView/AvatarComponent/components/halfbodyAvatar.js +77 -50
  12. package/dist/components/Avatar/AvatarView/AvatarComponent/components/halfbodyAvatar.js.map +1 -1
  13. package/dist/components/Avatar/AvatarView/index.d.ts +3 -1
  14. package/dist/components/Avatar/AvatarView/index.js +2 -2
  15. package/dist/components/Avatar/AvatarView/index.js.map +1 -1
  16. package/dist/components/MemoriWidget/MemoriWidget.js +127 -113
  17. package/dist/components/MemoriWidget/MemoriWidget.js.map +1 -1
  18. package/dist/components/layouts/ZoomedFullBody.js +1 -8
  19. package/dist/components/layouts/ZoomedFullBody.js.map +1 -1
  20. package/dist/components/layouts/zoomed-full-body.css +6 -2
  21. package/dist/context/visemeContext.d.ts +1 -0
  22. package/dist/context/visemeContext.js +19 -9
  23. package/dist/context/visemeContext.js.map +1 -1
  24. package/dist/styles.css +0 -1
  25. package/esm/components/Avatar/Avatar.js +2 -2
  26. package/esm/components/Avatar/Avatar.js.map +1 -1
  27. package/esm/components/Avatar/AvatarView/AvatarComponent/avatarComponent.d.ts +2 -0
  28. package/esm/components/Avatar/AvatarView/AvatarComponent/avatarComponent.js +2 -2
  29. package/esm/components/Avatar/AvatarView/AvatarComponent/avatarComponent.js.map +1 -1
  30. package/esm/components/Avatar/AvatarView/AvatarComponent/components/fullbodyAvatar.d.ts +2 -0
  31. package/esm/components/Avatar/AvatarView/AvatarComponent/components/fullbodyAvatar.js +1 -1
  32. package/esm/components/Avatar/AvatarView/AvatarComponent/components/fullbodyAvatar.js.map +1 -1
  33. package/esm/components/Avatar/AvatarView/AvatarComponent/components/halfbodyAvatar.d.ts +3 -1
  34. package/esm/components/Avatar/AvatarView/AvatarComponent/components/halfbodyAvatar.js +81 -53
  35. package/esm/components/Avatar/AvatarView/AvatarComponent/components/halfbodyAvatar.js.map +1 -1
  36. package/esm/components/Avatar/AvatarView/index.d.ts +3 -1
  37. package/esm/components/Avatar/AvatarView/index.js +2 -2
  38. package/esm/components/Avatar/AvatarView/index.js.map +1 -1
  39. package/esm/components/MemoriWidget/MemoriWidget.js +127 -113
  40. package/esm/components/MemoriWidget/MemoriWidget.js.map +1 -1
  41. package/esm/components/layouts/ZoomedFullBody.js +1 -8
  42. package/esm/components/layouts/ZoomedFullBody.js.map +1 -1
  43. package/esm/components/layouts/zoomed-full-body.css +6 -2
  44. package/esm/context/visemeContext.d.ts +1 -0
  45. package/esm/context/visemeContext.js +20 -10
  46. package/esm/context/visemeContext.js.map +1 -1
  47. package/esm/styles.css +0 -1
  48. package/package.json +1 -1
  49. package/src/components/Avatar/Avatar.stories.tsx +5 -7
  50. package/src/components/Avatar/Avatar.tsx +3 -1
  51. package/src/components/Avatar/AvatarView/AvatarComponent/avatarComponent.tsx +13 -0
  52. package/src/components/Avatar/AvatarView/AvatarComponent/components/fullbodyAvatar.tsx +3 -1
  53. package/src/components/Avatar/AvatarView/AvatarComponent/components/halfbodyAvatar.tsx +116 -65
  54. package/src/components/Avatar/AvatarView/AvatarView.stories.tsx +12 -36
  55. package/src/components/Avatar/AvatarView/index.tsx +6 -0
  56. package/src/components/MemoriWidget/MemoriWidget.tsx +164 -136
  57. package/src/components/layouts/ZoomedFullBody.test.tsx +1 -1
  58. package/src/components/layouts/ZoomedFullBody.tsx +4 -9
  59. package/src/components/layouts/zoomed-full-body.css +6 -2
  60. package/src/context/visemeContext.tsx +104 -70
  61. package/src/index.stories.tsx +23 -21
  62. package/src/styles.css +0 -1
  63. package/dist/components/AttachmentMediaModal/AttachmentMediaModal.d.ts +0 -14
  64. package/dist/components/AttachmentMediaModal/AttachmentMediaModal.js +0 -66
  65. package/dist/components/AttachmentMediaModal/AttachmentMediaModal.js.map +0 -1
  66. package/dist/components/Avatar/AvatarView/components/controls.d.ts +0 -23
  67. package/dist/components/Avatar/AvatarView/components/controls.js +0 -55
  68. package/dist/components/Avatar/AvatarView/components/controls.js.map +0 -1
  69. package/dist/components/Avatar/AvatarView/components/fullbodyAvatar.d.ts +0 -19
  70. package/dist/components/Avatar/AvatarView/components/fullbodyAvatar.js +0 -61
  71. package/dist/components/Avatar/AvatarView/components/fullbodyAvatar.js.map +0 -1
  72. package/dist/components/Avatar/AvatarView/components/halfbodyAvatar.d.ts +0 -9
  73. package/dist/components/Avatar/AvatarView/components/halfbodyAvatar.js +0 -39
  74. package/dist/components/Avatar/AvatarView/components/halfbodyAvatar.js.map +0 -1
  75. package/dist/components/Avatar/AvatarView/components/loader.d.ts +0 -5
  76. package/dist/components/Avatar/AvatarView/components/loader.js +0 -12
  77. package/dist/components/Avatar/AvatarView/components/loader.js.map +0 -1
  78. package/dist/components/Avatar/AvatarView/utils/useMouthSpeaking.d.ts +0 -2
  79. package/dist/components/Avatar/AvatarView/utils/useMouthSpeaking.js +0 -68
  80. package/dist/components/Avatar/AvatarView/utils/useMouthSpeaking.js.map +0 -1
  81. package/dist/components/AvatarView/components/avatar.d.ts +0 -9
  82. package/dist/components/AvatarView/components/avatar.js +0 -35
  83. package/dist/components/AvatarView/components/avatar.js.map +0 -1
  84. package/dist/components/AvatarView/components/fullbodyAvatar.d.ts +0 -10
  85. package/dist/components/AvatarView/components/fullbodyAvatar.js +0 -62
  86. package/dist/components/AvatarView/components/fullbodyAvatar.js.map +0 -1
  87. package/dist/components/AvatarView/components/loader.d.ts +0 -5
  88. package/dist/components/AvatarView/components/loader.js +0 -12
  89. package/dist/components/AvatarView/components/loader.js.map +0 -1
  90. package/dist/components/AvatarView/index.d.ts +0 -17
  91. package/dist/components/AvatarView/index.js +0 -35
  92. package/dist/components/AvatarView/index.js.map +0 -1
  93. package/dist/components/AvatarView/utils/useEyeBlink.d.ts +0 -2
  94. package/dist/components/AvatarView/utils/useEyeBlink.js +0 -40
  95. package/dist/components/AvatarView/utils/useEyeBlink.js.map +0 -1
  96. package/dist/components/AvatarView/utils/useHeadMovement.d.ts +0 -2
  97. package/dist/components/AvatarView/utils/useHeadMovement.js +0 -53
  98. package/dist/components/AvatarView/utils/useHeadMovement.js.map +0 -1
  99. package/dist/components/AvatarView/utils/useLoadingMorphAnim.d.ts +0 -2
  100. package/dist/components/AvatarView/utils/useLoadingMorphAnim.js +0 -34
  101. package/dist/components/AvatarView/utils/useLoadingMorphAnim.js.map +0 -1
  102. package/dist/components/AvatarView/utils/useMouthSpeaking.d.ts +0 -2
  103. package/dist/components/AvatarView/utils/useMouthSpeaking.js +0 -60
  104. package/dist/components/AvatarView/utils/useMouthSpeaking.js.map +0 -1
  105. package/dist/components/AvatarView/utils/useSmile.d.ts +0 -2
  106. package/dist/components/AvatarView/utils/useSmile.js +0 -30
  107. package/dist/components/AvatarView/utils/useSmile.js.map +0 -1
  108. package/dist/components/AvatarView/utils/utils.d.ts +0 -13
  109. package/dist/components/AvatarView/utils/utils.js +0 -42
  110. package/dist/components/AvatarView/utils/utils.js.map +0 -1
  111. package/dist/components/ImageUpload/ImageUpload.css +0 -168
  112. package/dist/components/ImageUpload/ImageUpload.d.ts +0 -28
  113. package/dist/components/ImageUpload/ImageUpload.js +0 -163
  114. package/dist/components/ImageUpload/ImageUpload.js.map +0 -1
  115. package/dist/components/layouts/Default.d.ts +0 -17
  116. package/dist/components/layouts/Default.js +0 -8
  117. package/dist/components/layouts/Default.js.map +0 -1
  118. package/dist/components/ui/Message.d.ts +0 -17
  119. package/dist/components/ui/Message.js +0 -13
  120. package/dist/components/ui/Message.js.map +0 -1
  121. package/esm/components/AttachmentMediaModal/AttachmentMediaModal.d.ts +0 -14
  122. package/esm/components/AttachmentMediaModal/AttachmentMediaModal.js +0 -63
  123. package/esm/components/AttachmentMediaModal/AttachmentMediaModal.js.map +0 -1
  124. package/esm/components/Avatar/AvatarView/components/controls.d.ts +0 -23
  125. package/esm/components/Avatar/AvatarView/components/controls.js +0 -52
  126. package/esm/components/Avatar/AvatarView/components/controls.js.map +0 -1
  127. package/esm/components/Avatar/AvatarView/components/fullbodyAvatar.d.ts +0 -19
  128. package/esm/components/Avatar/AvatarView/components/fullbodyAvatar.js +0 -57
  129. package/esm/components/Avatar/AvatarView/components/fullbodyAvatar.js.map +0 -1
  130. package/esm/components/Avatar/AvatarView/components/halfbodyAvatar.d.ts +0 -9
  131. package/esm/components/Avatar/AvatarView/components/halfbodyAvatar.js +0 -35
  132. package/esm/components/Avatar/AvatarView/components/halfbodyAvatar.js.map +0 -1
  133. package/esm/components/Avatar/AvatarView/components/loader.d.ts +0 -5
  134. package/esm/components/Avatar/AvatarView/components/loader.js +0 -9
  135. package/esm/components/Avatar/AvatarView/components/loader.js.map +0 -1
  136. package/esm/components/Avatar/AvatarView/utils/useMouthSpeaking.d.ts +0 -2
  137. package/esm/components/Avatar/AvatarView/utils/useMouthSpeaking.js +0 -65
  138. package/esm/components/Avatar/AvatarView/utils/useMouthSpeaking.js.map +0 -1
  139. package/esm/components/AvatarView/components/avatar.d.ts +0 -9
  140. package/esm/components/AvatarView/components/avatar.js +0 -31
  141. package/esm/components/AvatarView/components/avatar.js.map +0 -1
  142. package/esm/components/AvatarView/components/fullbodyAvatar.d.ts +0 -10
  143. package/esm/components/AvatarView/components/fullbodyAvatar.js +0 -58
  144. package/esm/components/AvatarView/components/fullbodyAvatar.js.map +0 -1
  145. package/esm/components/AvatarView/components/loader.d.ts +0 -5
  146. package/esm/components/AvatarView/components/loader.js +0 -9
  147. package/esm/components/AvatarView/components/loader.js.map +0 -1
  148. package/esm/components/AvatarView/index.d.ts +0 -17
  149. package/esm/components/AvatarView/index.js +0 -31
  150. package/esm/components/AvatarView/index.js.map +0 -1
  151. package/esm/components/AvatarView/utils/useEyeBlink.d.ts +0 -2
  152. package/esm/components/AvatarView/utils/useEyeBlink.js +0 -37
  153. package/esm/components/AvatarView/utils/useEyeBlink.js.map +0 -1
  154. package/esm/components/AvatarView/utils/useHeadMovement.d.ts +0 -2
  155. package/esm/components/AvatarView/utils/useHeadMovement.js +0 -50
  156. package/esm/components/AvatarView/utils/useHeadMovement.js.map +0 -1
  157. package/esm/components/AvatarView/utils/useLoadingMorphAnim.d.ts +0 -2
  158. package/esm/components/AvatarView/utils/useLoadingMorphAnim.js +0 -31
  159. package/esm/components/AvatarView/utils/useLoadingMorphAnim.js.map +0 -1
  160. package/esm/components/AvatarView/utils/useMouthSpeaking.d.ts +0 -2
  161. package/esm/components/AvatarView/utils/useMouthSpeaking.js +0 -57
  162. package/esm/components/AvatarView/utils/useMouthSpeaking.js.map +0 -1
  163. package/esm/components/AvatarView/utils/useSmile.d.ts +0 -2
  164. package/esm/components/AvatarView/utils/useSmile.js +0 -27
  165. package/esm/components/AvatarView/utils/useSmile.js.map +0 -1
  166. package/esm/components/AvatarView/utils/utils.d.ts +0 -13
  167. package/esm/components/AvatarView/utils/utils.js +0 -33
  168. package/esm/components/AvatarView/utils/utils.js.map +0 -1
  169. package/esm/components/ImageUpload/ImageUpload.css +0 -168
  170. package/esm/components/ImageUpload/ImageUpload.d.ts +0 -28
  171. package/esm/components/ImageUpload/ImageUpload.js +0 -160
  172. package/esm/components/ImageUpload/ImageUpload.js.map +0 -1
  173. package/esm/components/layouts/Default.d.ts +0 -17
  174. package/esm/components/layouts/Default.js +0 -5
  175. package/esm/components/layouts/Default.js.map +0 -1
  176. package/esm/components/ui/Message.d.ts +0 -17
  177. package/esm/components/ui/Message.js +0 -10
  178. package/esm/components/ui/Message.js.map +0 -1
@@ -14,6 +14,8 @@ interface Props {
14
14
  speaking: boolean;
15
15
  isZoomed: boolean;
16
16
  chatEmission: any;
17
+ stopProcessing: () => void;
18
+ resetVisemeQueue: () => void;
17
19
  updateCurrentViseme: (currentTime: number) => { name: string; weight: number } | null;
18
20
  }
19
21
 
@@ -50,6 +52,7 @@ const baseActions: Record<string, BaseAction> = {
50
52
 
51
53
 
52
54
  export const AvatarView: React.FC<Props & { halfBody: boolean }> = ({
55
+ stopProcessing,
53
56
  chatEmission,
54
57
  showControls,
55
58
  animation,
@@ -62,6 +65,7 @@ export const AvatarView: React.FC<Props & { halfBody: boolean }> = ({
62
65
  loading,
63
66
  isZoomed,
64
67
  updateCurrentViseme,
68
+ resetVisemeQueue,
65
69
  }) => {
66
70
  const [currentBaseAction, setCurrentBaseAction] = useState({
67
71
  action: animation || 'Idle1',
@@ -178,6 +182,12 @@ export const AvatarView: React.FC<Props & { halfBody: boolean }> = ({
178
182
  }
179
183
  }, [loading]);
180
184
 
185
+ // useEffect(() => {
186
+ // if (speaking && currentBaseAction.action !== 'Idle1') {
187
+ // const animation = `Idle1`;
188
+ // onBaseActionChange(animation);
189
+ // }
190
+ // }, [speaking]);
181
191
 
182
192
  return (
183
193
  <>
@@ -202,17 +212,20 @@ export const AvatarView: React.FC<Props & { halfBody: boolean }> = ({
202
212
  morphTargetInfluences={morphTargetInfluences}
203
213
  setMorphTargetInfluences={setMorphTargetInfluences}
204
214
  setMorphTargetDictionary={setMorphTargetDictionary}
215
+ updateCurrentViseme={updateCurrentViseme}
205
216
  />
206
217
  ) : (
207
218
  <FullbodyAvatar
208
219
  url={url}
209
220
  sex={sex}
221
+ resetVisemeQueue={resetVisemeQueue}
210
222
  eyeBlink={eyeBlink}
211
223
  currentBaseAction={currentBaseAction}
212
224
  timeScale={timeScale}
213
225
  morphTargetInfluences={morphTargetInfluences}
214
226
  isZoomed={isZoomed}
215
227
  updateCurrentViseme={updateCurrentViseme}
228
+ stopProcessing={stopProcessing}
216
229
  setMorphTargetDictionary={setMorphTargetDictionary}
217
230
  setMorphTargetInfluences={setMorphTargetInfluences}
218
231
  emotionMorphTargets={emotionMorphTargets}
@@ -24,6 +24,8 @@ interface FullbodyAvatarProps {
24
24
  timeScale: number;
25
25
  isZoomed?: boolean;
26
26
  eyeBlink?: boolean;
27
+ stopProcessing: () => void;
28
+ resetVisemeQueue: () => void;
27
29
  updateCurrentViseme: (
28
30
  currentTime: number
29
31
  ) => { name: string; weight: number } | null;
@@ -239,7 +241,7 @@ export default function FullbodyAvatar({
239
241
 
240
242
  // Handle visemes (additive layer)
241
243
  if (currentViseme && key === currentViseme.name) {
242
- targetValue += currentViseme.weight * 1.2; // Amplify the effect
244
+ targetValue += currentViseme.weight * 1.3; // Amplify the effect
243
245
  }
244
246
 
245
247
  // Handle blinking (additive layer, only for 'eyesClosed')
@@ -6,7 +6,7 @@ import { useGraph, dispose, useFrame } from '@react-three/fiber';
6
6
  import { useAvatarBlink } from '../../utils/useEyeBlink';
7
7
  import useHeadMovement from '../../utils/useHeadMovement';
8
8
  import { hideHands } from '../../utils/utils';
9
-
9
+ import { AnimationMixer, MathUtils } from 'three';
10
10
 
11
11
  interface HalfBodyAvatarProps {
12
12
  url: string;
@@ -17,101 +17,152 @@ interface HalfBodyAvatarProps {
17
17
  setMorphTargetDictionary: (morphTargetDictionary: any) => void;
18
18
  eyeBlink?: boolean;
19
19
  morphTargetInfluences: any;
20
+ updateCurrentViseme: (currentTime: number) => any;
21
+ morphTargetSmoothing?: number;
20
22
  }
21
23
 
22
24
  const AVATAR_POSITION = new Vector3(0, -0.6, 0);
23
- const lerp = (start: number, end: number, alpha: number): number => {
24
- return start * (1 - alpha) + end * alpha;
25
+ // Blink configuration
26
+ const BLINK_CONFIG = {
27
+ minInterval: 1000,
28
+ maxInterval: 5000,
29
+ blinkDuration: 150,
25
30
  };
31
+
26
32
  export default function HalfBodyAvatar({
27
33
  url,
28
34
  setMorphTargetInfluences,
29
35
  setMorphTargetDictionary,
30
- headMovement,
31
36
  eyeBlink,
32
37
  onLoaded,
33
- morphTargetInfluences,
38
+ morphTargetSmoothing = 0.5,
39
+ updateCurrentViseme,
34
40
  }: HalfBodyAvatarProps) {
35
41
  const { scene } = useGLTF(url);
36
42
  const { nodes, materials } = useGraph(scene);
43
+ const mixer = useRef(new AnimationMixer(scene));
37
44
  const avatarMeshRef = useRef<SkinnedMesh | null>(null);
38
45
 
39
- useAvatarBlink({
40
- enabled: eyeBlink || false,
41
- setMorphTargetInfluences,
42
- config: {
43
- minInterval: 1500,
44
- maxInterval: 4000,
45
- blinkDuration: 120
46
- }
47
- });
48
- useHeadMovement(headMovement, nodes);
46
+ // Blink state
47
+ const lastBlinkTime = useRef(0);
48
+ const nextBlinkTime = useRef(0);
49
+ const isBlinking = useRef(false);
50
+ const blinkStartTime = useRef(0);
51
+
52
+ const headMeshRef = useRef<SkinnedMesh>();
49
53
 
50
54
  useEffect(() => {
51
- const setupAvatar = () => {
52
- hideHands(nodes);
53
- correctMaterials(materials);
54
- // Set mesh reference for the first SkinnedMesh found
55
- const firstSkinnedMesh = Object.values(nodes).find(isSkinnedMesh) as SkinnedMesh;
56
- if (firstSkinnedMesh) {
57
- avatarMeshRef.current = firstSkinnedMesh;
58
- if (firstSkinnedMesh.morphTargetDictionary && firstSkinnedMesh.morphTargetInfluences) {
59
- setMorphTargetDictionary(firstSkinnedMesh.morphTargetDictionary);
60
- const initialInfluences = Object.keys(
61
- firstSkinnedMesh.morphTargetDictionary
62
- ).reduce((acc, key) => ({ ...acc, [key]: 0 }), {});
63
- setMorphTargetInfluences(initialInfluences);
55
+ correctMaterials(materials);
56
+
57
+ scene.traverse((object: Object3D) => {
58
+ if (object instanceof SkinnedMesh) {
59
+ if (object.name === 'GBNL__Head' || object.name === 'Wolf3D_Avatar') {
60
+ headMeshRef.current = object;
61
+ if (object.morphTargetDictionary && object.morphTargetInfluences) {
62
+ setMorphTargetDictionary(object.morphTargetDictionary);
63
+
64
+ const initialInfluences = Object.keys(
65
+ object.morphTargetDictionary
66
+ ).reduce((acc, key) => ({ ...acc, [key]: 0 }), {});
67
+ setMorphTargetInfluences(initialInfluences);
68
+ }
64
69
  }
65
70
  }
66
- onLoaded?.();
67
- };
71
+ });
68
72
 
69
- setupAvatar();
73
+ onLoaded?.();
70
74
 
71
75
  return () => {
72
- const disposeObjects = () => {
73
- Object.values(materials).forEach(dispose);
74
- Object.values(nodes).filter(isSkinnedMesh).forEach(dispose);
75
- };
76
-
77
- disposeObjects();
76
+ Object.values(materials).forEach(material => material.dispose());
77
+ Object.values(nodes)
78
+ .filter(isSkinnedMesh)
79
+ .forEach(mesh => mesh.geometry.dispose());
78
80
  };
79
- }, [materials, nodes, url, onLoaded]);
81
+ }, [materials, nodes, url, onLoaded, scene]);
82
+ useFrame(state => {
80
83
 
81
- const skinnedMeshes = useMemo(
82
- () => Object.values(nodes).filter(isSkinnedMesh),
83
- [nodes]
84
- );
84
+ if (
85
+ headMeshRef.current &&
86
+ headMeshRef.current.morphTargetDictionary &&
87
+ headMeshRef.current.morphTargetInfluences
88
+ ) {
89
+ const currentTime = state.clock.getElapsedTime() * 1000; // Convert to milliseconds
85
90
 
86
- // Update morph target influences
87
- useFrame((_) => {
88
- if (avatarMeshRef.current && avatarMeshRef.current.morphTargetDictionary) {
89
- updateMorphTargetInfluences();
90
- }
91
-
92
- function updateMorphTargetInfluences() {
93
- Object.entries(morphTargetInfluences).forEach(([key, value]) => {
94
- const index = avatarMeshRef.current!.morphTargetDictionary![key];
95
- if (typeof index === 'number' &&
96
- avatarMeshRef.current!.morphTargetInfluences) {
97
- const currentValue = avatarMeshRef.current!.morphTargetInfluences[index];
98
- const smoothValue = lerp(currentValue, value as number, 0.1);
99
- avatarMeshRef.current!.morphTargetInfluences[index] = smoothValue;
91
+ // Handle blinking
92
+ let blinkValue = 0;
93
+ if (eyeBlink) {
94
+ if (currentTime >= nextBlinkTime.current && !isBlinking.current) {
95
+ isBlinking.current = true;
96
+ blinkStartTime.current = currentTime;
97
+ lastBlinkTime.current = currentTime;
98
+ nextBlinkTime.current =
99
+ currentTime +
100
+ Math.random() *
101
+ (BLINK_CONFIG.maxInterval - BLINK_CONFIG.minInterval) +
102
+ BLINK_CONFIG.minInterval;
103
+ }
104
+
105
+ if (isBlinking.current) {
106
+ const blinkProgress =
107
+ (currentTime - blinkStartTime.current) / BLINK_CONFIG.blinkDuration;
108
+ if (blinkProgress <= 0.5) {
109
+ // Eyes closing
110
+ blinkValue = blinkProgress * 2;
111
+ } else if (blinkProgress <= 1) {
112
+ // Eyes opening
113
+ blinkValue = 2 - blinkProgress * 2;
114
+ } else {
115
+ // Blink finished
116
+ isBlinking.current = false;
117
+ blinkValue = 0;
100
118
  }
101
- });
119
+ }
102
120
  }
103
- });
104
121
 
122
+ const currentViseme = updateCurrentViseme(currentTime / 1000);
123
+
124
+ // Update morph targets
125
+ Object.entries(headMeshRef.current.morphTargetDictionary).forEach(
126
+ ([key, index]) => {
127
+ if (typeof index === 'number') {
128
+ let targetValue = 0;
129
+
130
+ // Handle visemes (additive layer)
131
+ if (currentViseme && key === currentViseme.name) {
132
+ targetValue += currentViseme.weight * 1.3; // Amplify the effect
133
+ }
134
+
135
+ // Handle blinking (additive layer, only for 'eyesClosed')
136
+ if (key === 'eyesClosed' && eyeBlink) {
137
+ targetValue += blinkValue;
138
+ }
139
+
140
+ // Clamp the final value between 0 and 1
141
+ targetValue = MathUtils.clamp(targetValue, 0, 1);
142
+
143
+ // Apply smoothing
144
+ if (
145
+ headMeshRef.current &&
146
+ headMeshRef.current.morphTargetInfluences
147
+ ) {
148
+ headMeshRef.current.morphTargetInfluences[index] = MathUtils.lerp(
149
+ headMeshRef.current.morphTargetInfluences[index],
150
+ targetValue,
151
+ morphTargetSmoothing
152
+ );
153
+ }
154
+ }
155
+ }
156
+ );
157
+
158
+ // Update the animation mixer
159
+ mixer.current.update(0.01); // Fixed delta time for consistent animation speed
160
+ }
161
+ });
105
162
 
106
163
  return (
107
164
  <group position={AVATAR_POSITION}>
108
- {nodes.Hips && <primitive key="armature" object={nodes.Hips} />}
109
- {skinnedMeshes.map(
110
- (node: Object3D) =>
111
- node && (
112
- <primitive key={node.name} object={node} receiveShadow castShadow />
113
- )
114
- )}
165
+ <primitive object={scene} />
115
166
  </group>
116
167
  );
117
168
  }
@@ -96,9 +96,7 @@ Default.args = {
96
96
  headMovement: false,
97
97
  rotateAvatar: false,
98
98
  speaking: false,
99
- stopProcessing: () => {},
100
- resetVisemeQueue: () => {},
101
- updateCurrentViseme: () => null,
99
+ updateCurrentViseme: () => {},
102
100
  url: 'https://assets.memori.ai/api/v2/asset/b791f77c-1a94-4272-829e-eca82fcc62b7.glb',
103
101
  fallbackImg:
104
102
  'https://assets.memori.ai/api/v2/asset/d8035229-08cf-42a7-a532-ab051df2603d.png',
@@ -106,9 +104,7 @@ Default.args = {
106
104
 
107
105
  export const EyeBlink = Template.bind({});
108
106
  EyeBlink.args = {
109
- stopProcessing: () => {},
110
- resetVisemeQueue: () => {},
111
- updateCurrentViseme: () => null,
107
+ updateCurrentViseme: () => {},
112
108
  eyeBlink: true,
113
109
  headMovement: false,
114
110
  rotateAvatar: false,
@@ -120,9 +116,7 @@ EyeBlink.args = {
120
116
 
121
117
  export const HeadMovement = Template.bind({});
122
118
  HeadMovement.args = {
123
- stopProcessing: () => {},
124
- resetVisemeQueue: () => {},
125
- updateCurrentViseme: () => null,
119
+ updateCurrentViseme: () => {},
126
120
  eyeBlink: false,
127
121
  headMovement: true,
128
122
  rotateAvatar: false,
@@ -134,9 +128,7 @@ HeadMovement.args = {
134
128
 
135
129
  export const RotateAvatar = Template.bind({});
136
130
  RotateAvatar.args = {
137
- stopProcessing: () => {},
138
- resetVisemeQueue: () => {},
139
- updateCurrentViseme: () => null,
131
+ updateCurrentViseme: () => {},
140
132
  eyeBlink: false,
141
133
  headMovement: false,
142
134
  rotateAvatar: true,
@@ -148,9 +140,7 @@ RotateAvatar.args = {
148
140
 
149
141
  export const Speaking = Template.bind({});
150
142
  Speaking.args = {
151
- stopProcessing: () => {},
152
- resetVisemeQueue: () => {},
153
- updateCurrentViseme: () => null,
143
+ updateCurrentViseme: () => {},
154
144
  eyeBlink: false,
155
145
  headMovement: false,
156
146
  rotateAvatar: false,
@@ -167,9 +157,7 @@ Fullbody.args = {
167
157
  headMovement: true,
168
158
  rotateAvatar: true,
169
159
  speaking: false,
170
- stopProcessing: () => {},
171
- resetVisemeQueue: () => {},
172
- updateCurrentViseme: () => null,
160
+ updateCurrentViseme: () => {},
173
161
  url: 'https://models.readyplayer.me/63b55751f17e295642bf07a2.glb',
174
162
  fallbackImg:
175
163
  'https://assets.memori.ai/api/v2/asset/3049582f-db5f-452c-913d-e4340d4afd0a.png',
@@ -184,9 +172,7 @@ FullbodyZoomed.args = {
184
172
  rotateAvatar: true,
185
173
  speaking: false,
186
174
  isZoomed: true,
187
- stopProcessing: () => {},
188
- resetVisemeQueue: () => {},
189
- updateCurrentViseme: () => null,
175
+ updateCurrentViseme: () => {},
190
176
  url: 'https://assets.memori.ai/api/v2/asset/3f5ef41c-6c4c-449c-888d-cf9c89782528.glb',
191
177
  fallbackImg:
192
178
  'https://assets.memori.ai/api/v2/asset/3049582f-db5f-452c-913d-e4340d4afd0a.png',
@@ -200,9 +186,7 @@ FullbodyAnimatedIdle.args = {
200
186
  headMovement: true,
201
187
  rotateAvatar: true,
202
188
  speaking: false,
203
- stopProcessing: () => {},
204
- resetVisemeQueue: () => {},
205
- updateCurrentViseme: () => null,
189
+ updateCurrentViseme: () => {},
206
190
  url: 'https://models.readyplayer.me/63b55751f17e295642bf07a2.glb',
207
191
  fallbackImg:
208
192
  'https://assets.memori.ai/api/v2/asset/3049582f-db5f-452c-913d-e4340d4afd0a.png',
@@ -217,9 +201,7 @@ FullbodyAnimatedLoading.args = {
217
201
  headMovement: true,
218
202
  rotateAvatar: true,
219
203
  speaking: false,
220
- stopProcessing: () => {},
221
- resetVisemeQueue: () => {},
222
- updateCurrentViseme: () => null,
204
+ updateCurrentViseme: () => {},
223
205
  url: 'https://models.readyplayer.me/63b55751f17e295642bf07a2.glb',
224
206
  fallbackImg:
225
207
  'https://assets.memori.ai/api/v2/asset/3049582f-db5f-452c-913d-e4340d4afd0a.png',
@@ -234,9 +216,7 @@ FullbodyAnimatedSpeaking.args = {
234
216
  headMovement: true,
235
217
  rotateAvatar: true,
236
218
  speaking: true,
237
- stopProcessing: () => {},
238
- resetVisemeQueue: () => {},
239
- updateCurrentViseme: () => null,
219
+ updateCurrentViseme: () => {},
240
220
  url: 'https://models.readyplayer.me/63b55751f17e295642bf07a2.glb',
241
221
  fallbackImg:
242
222
  'https://assets.memori.ai/api/v2/asset/3049582f-db5f-452c-913d-e4340d4afd0a.png',
@@ -251,9 +231,7 @@ FullbodyFemale.args = {
251
231
  headMovement: true,
252
232
  rotateAvatar: true,
253
233
  speaking: false,
254
- stopProcessing: () => {},
255
- resetVisemeQueue: () => {},
256
- updateCurrentViseme: () => null,
234
+ updateCurrentViseme: () => {},
257
235
  url: 'https://models.readyplayer.me/650d50c2663b19e0d2831b2b.glb',
258
236
  fallbackImg:
259
237
  'https://assets.memori.ai/api/v2/asset/3049582f-db5f-452c-913d-e4340d4afd0a.png',
@@ -267,9 +245,7 @@ FullbodyAnimatedFemale.args = {
267
245
  headMovement: true,
268
246
  rotateAvatar: true,
269
247
  speaking: true,
270
- stopProcessing: () => {},
271
- resetVisemeQueue: () => {},
272
- updateCurrentViseme: () => null,
248
+ updateCurrentViseme: () => {},
273
249
  url: 'https://models.readyplayer.me/650d50c2663b19e0d2831b2b.glb',
274
250
  fallbackImg:
275
251
  'https://assets.memori.ai/api/v2/asset/3049582f-db5f-452c-913d-e4340d4afd0a.png',
@@ -23,6 +23,8 @@ export interface Props {
23
23
  isZoomed?: boolean;
24
24
  chatEmission?: any;
25
25
  setMeshRef?: any;
26
+ stopProcessing: () => void;
27
+ resetVisemeQueue: () => void;
26
28
  updateCurrentViseme: (currentTime: number) => { name: string; weight: number } | null;
27
29
  }
28
30
 
@@ -87,6 +89,8 @@ export default function ContainerAvatarView({
87
89
  showControls = false,
88
90
  isZoomed,
89
91
  chatEmission,
92
+ stopProcessing,
93
+ resetVisemeQueue,
90
94
  updateCurrentViseme,
91
95
  }: Props) {
92
96
  return (
@@ -112,6 +116,8 @@ export default function ContainerAvatarView({
112
116
  halfBody={halfBody || false}
113
117
  chatEmission={chatEmission}
114
118
  updateCurrentViseme={updateCurrentViseme}
119
+ stopProcessing={stopProcessing}
120
+ resetVisemeQueue={resetVisemeQueue}
115
121
  />
116
122
  </Suspense>
117
123
  </Canvas>