@memori.ai/memori-react 7.19.1 → 7.21.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.
- package/CHANGELOG.md +57 -0
- package/dist/components/Avatar/Avatar.js +3 -3
- package/dist/components/Avatar/Avatar.js.map +1 -1
- package/dist/components/Avatar/AvatarView/AvatarComponent/Shadow/DynamicShadow.d.ts +3 -2
- package/dist/components/Avatar/AvatarView/AvatarComponent/Shadow/DynamicShadow.js +13 -6
- package/dist/components/Avatar/AvatarView/AvatarComponent/Shadow/DynamicShadow.js.map +1 -1
- package/dist/components/Avatar/AvatarView/AvatarComponent/avatarComponent.d.ts +14 -18
- package/dist/components/Avatar/AvatarView/AvatarComponent/avatarComponent.js +19 -77
- package/dist/components/Avatar/AvatarView/AvatarComponent/avatarComponent.js.map +1 -1
- package/dist/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/fullbodyAvatar.d.ts +17 -2
- package/dist/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/fullbodyAvatar.js +95 -70
- package/dist/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/fullbodyAvatar.js.map +1 -1
- package/dist/components/Avatar/AvatarView/AvatarComponent/components/controllers/AvatarAnimator.d.ts +65 -0
- package/dist/components/Avatar/AvatarView/AvatarComponent/components/controllers/AvatarAnimator.js +747 -0
- package/dist/components/Avatar/AvatarView/AvatarComponent/components/controllers/AvatarAnimator.js.map +1 -0
- package/dist/components/Avatar/AvatarView/AvatarComponent/components/controllers/MorphTargetController.d.ts +9 -2
- package/dist/components/Avatar/AvatarView/AvatarComponent/components/controllers/MorphTargetController.js +60 -2
- package/dist/components/Avatar/AvatarView/AvatarComponent/components/controllers/MorphTargetController.js.map +1 -1
- package/dist/components/Avatar/AvatarView/AvatarComponent/components/halfbodyAvatar.d.ts +3 -4
- package/dist/components/Avatar/AvatarView/AvatarComponent/components/halfbodyAvatar.js +5 -11
- package/dist/components/Avatar/AvatarView/AvatarComponent/components/halfbodyAvatar.js.map +1 -1
- package/dist/components/Avatar/AvatarView/AvatarComponent/constants.d.ts +13 -52
- package/dist/components/Avatar/AvatarView/AvatarComponent/constants.js +68 -70
- package/dist/components/Avatar/AvatarView/AvatarComponent/constants.js.map +1 -1
- package/dist/components/Avatar/AvatarView/index.d.ts +1 -1
- package/dist/components/Avatar/AvatarView/index.js +2 -2
- package/dist/components/Avatar/AvatarView/index.js.map +1 -1
- package/dist/components/Chat/Chat.js +2 -2
- package/dist/components/Chat/Chat.js.map +1 -1
- package/dist/components/ChatBubble/ChatBubble.js +12 -9
- package/dist/components/ChatBubble/ChatBubble.js.map +1 -1
- package/dist/components/ExpertsDrawer/ExpertsDrawer.js +1 -1
- package/dist/components/ExpertsDrawer/ExpertsDrawer.js.map +1 -1
- package/dist/components/LoginDrawer/LoginDrawer.js +6 -6
- package/dist/components/LoginDrawer/LoginDrawer.js.map +1 -1
- package/dist/components/MemoriWidget/MemoriWidget.js +143 -64
- package/dist/components/MemoriWidget/MemoriWidget.js.map +1 -1
- package/dist/components/SignupForm/SignupForm.js +4 -4
- package/dist/components/SignupForm/SignupForm.js.map +1 -1
- package/dist/components/StartPanel/StartPanel.js +5 -5
- package/dist/components/StartPanel/StartPanel.js.map +1 -1
- package/dist/components/UploadButton/UploadButton.js +2 -2
- package/dist/components/UploadButton/UploadButton.js.map +1 -1
- package/dist/components/WhyThisAnswer/WhyThisAnswer.css +43 -0
- package/dist/components/WhyThisAnswer/WhyThisAnswer.js +2 -1
- package/dist/components/WhyThisAnswer/WhyThisAnswer.js.map +1 -1
- package/dist/context/visemeContext.js +0 -39
- package/dist/context/visemeContext.js.map +1 -1
- package/dist/index.js +4 -3
- package/dist/index.js.map +1 -1
- package/dist/locales/de.json +1 -0
- package/dist/locales/en.json +1 -0
- package/dist/locales/es.json +1 -0
- package/dist/locales/fr.json +1 -0
- package/dist/locales/it.json +1 -0
- package/esm/components/Avatar/Avatar.js +3 -3
- package/esm/components/Avatar/Avatar.js.map +1 -1
- package/esm/components/Avatar/AvatarView/AvatarComponent/Shadow/DynamicShadow.d.ts +3 -2
- package/esm/components/Avatar/AvatarView/AvatarComponent/Shadow/DynamicShadow.js +13 -6
- package/esm/components/Avatar/AvatarView/AvatarComponent/Shadow/DynamicShadow.js.map +1 -1
- package/esm/components/Avatar/AvatarView/AvatarComponent/avatarComponent.d.ts +14 -18
- package/esm/components/Avatar/AvatarView/AvatarComponent/avatarComponent.js +20 -78
- package/esm/components/Avatar/AvatarView/AvatarComponent/avatarComponent.js.map +1 -1
- package/esm/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/fullbodyAvatar.d.ts +17 -2
- package/esm/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/fullbodyAvatar.js +99 -74
- package/esm/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/fullbodyAvatar.js.map +1 -1
- package/esm/components/Avatar/AvatarView/AvatarComponent/components/controllers/AvatarAnimator.d.ts +65 -0
- package/esm/components/Avatar/AvatarView/AvatarComponent/components/controllers/AvatarAnimator.js +743 -0
- package/esm/components/Avatar/AvatarView/AvatarComponent/components/controllers/AvatarAnimator.js.map +1 -0
- package/esm/components/Avatar/AvatarView/AvatarComponent/components/controllers/MorphTargetController.d.ts +9 -2
- package/esm/components/Avatar/AvatarView/AvatarComponent/components/controllers/MorphTargetController.js +61 -3
- package/esm/components/Avatar/AvatarView/AvatarComponent/components/controllers/MorphTargetController.js.map +1 -1
- package/esm/components/Avatar/AvatarView/AvatarComponent/components/halfbodyAvatar.d.ts +3 -4
- package/esm/components/Avatar/AvatarView/AvatarComponent/components/halfbodyAvatar.js +5 -11
- package/esm/components/Avatar/AvatarView/AvatarComponent/components/halfbodyAvatar.js.map +1 -1
- package/esm/components/Avatar/AvatarView/AvatarComponent/constants.d.ts +13 -52
- package/esm/components/Avatar/AvatarView/AvatarComponent/constants.js +67 -69
- package/esm/components/Avatar/AvatarView/AvatarComponent/constants.js.map +1 -1
- package/esm/components/Avatar/AvatarView/index.d.ts +1 -1
- package/esm/components/Avatar/AvatarView/index.js +2 -2
- package/esm/components/Avatar/AvatarView/index.js.map +1 -1
- package/esm/components/Chat/Chat.js +2 -2
- package/esm/components/Chat/Chat.js.map +1 -1
- package/esm/components/ChatBubble/ChatBubble.js +12 -9
- package/esm/components/ChatBubble/ChatBubble.js.map +1 -1
- package/esm/components/ExpertsDrawer/ExpertsDrawer.js +1 -1
- package/esm/components/ExpertsDrawer/ExpertsDrawer.js.map +1 -1
- package/esm/components/LoginDrawer/LoginDrawer.js +6 -6
- package/esm/components/LoginDrawer/LoginDrawer.js.map +1 -1
- package/esm/components/MemoriWidget/MemoriWidget.js +143 -64
- package/esm/components/MemoriWidget/MemoriWidget.js.map +1 -1
- package/esm/components/SignupForm/SignupForm.js +4 -4
- package/esm/components/SignupForm/SignupForm.js.map +1 -1
- package/esm/components/StartPanel/StartPanel.js +5 -5
- package/esm/components/StartPanel/StartPanel.js.map +1 -1
- package/esm/components/UploadButton/UploadButton.js +2 -2
- package/esm/components/UploadButton/UploadButton.js.map +1 -1
- package/esm/components/WhyThisAnswer/WhyThisAnswer.css +43 -0
- package/esm/components/WhyThisAnswer/WhyThisAnswer.js +2 -1
- package/esm/components/WhyThisAnswer/WhyThisAnswer.js.map +1 -1
- package/esm/context/visemeContext.js +0 -39
- package/esm/context/visemeContext.js.map +1 -1
- package/esm/index.js +4 -3
- package/esm/index.js.map +1 -1
- package/esm/locales/de.json +1 -0
- package/esm/locales/en.json +1 -0
- package/esm/locales/es.json +1 -0
- package/esm/locales/fr.json +1 -0
- package/esm/locales/it.json +1 -0
- package/package.json +2 -2
- package/src/components/Avatar/Avatar.tsx +3 -3
- package/src/components/Avatar/AvatarView/AvatarComponent/Shadow/DynamicShadow.tsx +15 -8
- package/src/components/Avatar/AvatarView/AvatarComponent/avatarComponent.tsx +64 -219
- package/src/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/fullbodyAvatar.tsx +221 -124
- package/src/components/Avatar/AvatarView/AvatarComponent/components/controllers/AvatarAnimator.ts +1250 -0
- package/src/components/Avatar/AvatarView/AvatarComponent/components/controllers/MorphTargetController.ts +164 -8
- package/src/components/Avatar/AvatarView/AvatarComponent/components/halfbodyAvatar.tsx +19 -17
- package/src/components/Avatar/AvatarView/AvatarComponent/constants.ts +80 -79
- package/src/components/Avatar/AvatarView/index.tsx +1 -7
- package/src/components/Chat/Chat.tsx +2 -2
- package/src/components/ChatBubble/ChatBubble.tsx +37 -26
- package/src/components/ExpertsDrawer/ExpertsDrawer.tsx +1 -1
- package/src/components/LoginDrawer/LoginDrawer.tsx +6 -6
- package/src/components/MemoriWidget/MemoriWidget.tsx +184 -78
- package/src/components/SignupForm/SignupForm.tsx +5 -5
- package/src/components/StartPanel/StartPanel.tsx +5 -5
- package/src/components/UploadButton/UploadButton.tsx +4 -4
- package/src/components/UploadButton/__snapshots__/UploadButton.test.tsx.snap +1 -1
- package/src/components/WhyThisAnswer/WhyThisAnswer.css +43 -0
- package/src/components/WhyThisAnswer/WhyThisAnswer.stories.tsx +44 -3
- package/src/components/WhyThisAnswer/WhyThisAnswer.test.tsx +128 -8
- package/src/components/WhyThisAnswer/WhyThisAnswer.tsx +28 -3
- package/src/components/WhyThisAnswer/__snapshots__/WhyThisAnswer.test.tsx.snap +15 -1
- package/src/components/layouts/layouts.stories.tsx +0 -8
- package/src/context/visemeContext.tsx +40 -41
- package/src/index.stories.tsx +63 -65
- package/src/index.tsx +5 -3
- package/src/locales/de.json +1 -0
- package/src/locales/en.json +1 -0
- package/src/locales/es.json +1 -0
- package/src/locales/fr.json +1 -0
- package/src/locales/it.json +1 -0
- package/src/mocks/data.ts +3 -9
- package/src/components/Avatar/AvatarView/AvatarComponent/components/controllers/AnimationController.ts +0 -308
- package/src/helpers/tenant.ts +0 -47
|
@@ -1,261 +1,106 @@
|
|
|
1
|
-
|
|
2
|
-
import
|
|
3
|
-
import AnimationControlPanel from './components/controls';
|
|
1
|
+
import { useRef, useEffect, useCallback, memo } from 'react';
|
|
2
|
+
import { AvatarAnimator } from './components/controllers/AvatarAnimator';
|
|
4
3
|
import { FullbodyAvatar } from './components/FullbodyAvatar/fullbodyAvatar';
|
|
5
4
|
import HalfBodyAvatar from './components/halfbodyAvatar';
|
|
6
|
-
import {
|
|
7
|
-
BASE_ACTIONS,
|
|
8
|
-
MAPPING_BLEND_SHAPE_TO_EMOTION_CUSTOM_GLB,
|
|
9
|
-
MAPPING_BLEND_SHAPE_TO_EMOTION_RPM,
|
|
10
|
-
} from './constants';
|
|
11
5
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
showControls: boolean;
|
|
15
|
-
animation?: string;
|
|
16
|
-
loading: boolean;
|
|
6
|
+
interface AvatarViewProps {
|
|
7
|
+
chatEmission: string | null | undefined;
|
|
17
8
|
url: string;
|
|
18
9
|
sex: 'MALE' | 'FEMALE';
|
|
19
10
|
eyeBlink: boolean;
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
avatarHeight?: number;
|
|
25
|
-
avatarDepth?: number;
|
|
26
|
-
stopProcessing: () => void;
|
|
27
|
-
resetVisemeQueue: () => void;
|
|
11
|
+
halfBody: boolean;
|
|
12
|
+
loading: boolean;
|
|
13
|
+
avatarHeight: number;
|
|
14
|
+
avatarDepth: number;
|
|
28
15
|
updateCurrentViseme: (
|
|
29
16
|
currentTime: number
|
|
30
17
|
) => { name: string; weight: number } | null;
|
|
31
|
-
setCameraZ: (
|
|
18
|
+
setCameraZ: (cameraZ: number) => void;
|
|
19
|
+
headMovement: boolean;
|
|
20
|
+
speaking: boolean;
|
|
21
|
+
showControls: boolean;
|
|
32
22
|
}
|
|
33
23
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
24
|
+
// Memoized FullbodyAvatar component to prevent unnecessary re-renders
|
|
25
|
+
const MemoizedFullbodyAvatar = memo(FullbodyAvatar);
|
|
26
|
+
|
|
27
|
+
// Memoized HalfBodyAvatar component to prevent unnecessary re-renders
|
|
28
|
+
const MemoizedHalfBodyAvatar = memo(HalfBodyAvatar);
|
|
29
|
+
|
|
30
|
+
export const AvatarView = ({
|
|
40
31
|
chatEmission,
|
|
41
|
-
showControls,
|
|
42
|
-
animation,
|
|
43
32
|
url,
|
|
44
33
|
sex,
|
|
45
34
|
eyeBlink,
|
|
46
|
-
headMovement,
|
|
47
35
|
halfBody,
|
|
48
36
|
loading,
|
|
49
37
|
avatarHeight = 50,
|
|
50
38
|
avatarDepth = -50,
|
|
51
39
|
updateCurrentViseme,
|
|
52
|
-
resetVisemeQueue,
|
|
53
40
|
setCameraZ,
|
|
54
|
-
|
|
55
|
-
//
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
const [emotionMorphTargets, setEmotionMorphTargets] = useState<
|
|
67
|
-
Record<string, number>
|
|
68
|
-
>({});
|
|
69
|
-
const [isRPM, setIsRPM] = useState(false);
|
|
70
|
-
const [timeScale, setTimeScale] = useState(0.8);
|
|
71
|
-
|
|
72
|
-
// Map of basic emotions with their corresponding morph values
|
|
73
|
-
const emotionMap: Record<string, Record<string, number>> = {
|
|
74
|
-
Joy: { Joy: 1 },
|
|
75
|
-
Anger: { Anger: 1 },
|
|
76
|
-
Surprise: { Surprise: 1 },
|
|
77
|
-
Sadness: { Sadness: 1 },
|
|
78
|
-
Fear: { Fear: 1 },
|
|
79
|
-
};
|
|
80
|
-
|
|
81
|
-
// Helper function to get default emotion state (all set to 0)
|
|
82
|
-
const getDefaultEmotions = () =>
|
|
83
|
-
Object.keys(emotionMap).reduce((acc, key) => ({ ...acc, [key]: 0 }), {});
|
|
84
|
-
|
|
85
|
-
// Handlers for different blend shape types
|
|
86
|
-
const handleRPMBlendShape = useCallback(
|
|
87
|
-
(outputContent: string) =>
|
|
88
|
-
MAPPING_BLEND_SHAPE_TO_EMOTION_RPM[
|
|
89
|
-
outputContent as keyof typeof MAPPING_BLEND_SHAPE_TO_EMOTION_RPM
|
|
90
|
-
],
|
|
91
|
-
[]
|
|
92
|
-
);
|
|
93
|
-
|
|
94
|
-
const handleCustomGLBBlendShape = useCallback(
|
|
95
|
-
(outputContent: string) =>
|
|
96
|
-
MAPPING_BLEND_SHAPE_TO_EMOTION_CUSTOM_GLB[
|
|
97
|
-
outputContent as keyof typeof MAPPING_BLEND_SHAPE_TO_EMOTION_CUSTOM_GLB
|
|
98
|
-
],
|
|
99
|
-
[]
|
|
100
|
-
);
|
|
101
|
-
|
|
102
|
-
// Handler for setting emotion morph target influences, used for RPM and GLB blend shapes
|
|
103
|
-
const setEmotionMorphTargetInfluences = useCallback(
|
|
104
|
-
(action: string, outputContent: string) => {
|
|
105
|
-
if (action.startsWith('Loading')) return;
|
|
106
|
-
|
|
107
|
-
const defaultEmotions = getDefaultEmotions();
|
|
108
|
-
|
|
109
|
-
// If output content is default, set default emotions
|
|
110
|
-
if (outputContent === 'default') {
|
|
111
|
-
setEmotionMorphTargets(defaultEmotions);
|
|
112
|
-
return;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
// If RPM, convert emotion to blend shape
|
|
116
|
-
/*from the chat output, we get the emotion and we convert it to the blend shapes
|
|
117
|
-
* we map the emotion to the blend shape, example:
|
|
118
|
-
* Anger -> {browDownLeft: 1, browDownRight: 0}
|
|
119
|
-
* Joy -> {browUpLeft: 1, browUpRight: 0}
|
|
120
|
-
* Surprise -> {browUpLeft: 1, browUpRight: 0}
|
|
121
|
-
* Sadness -> {browDownLeft: 1, browDownRight: 0}
|
|
122
|
-
* Fear -> {browDownLeft: 1, browDownRight: 0}
|
|
123
|
-
*/
|
|
124
|
-
if (isRPM) {
|
|
125
|
-
const emotion = handleRPMBlendShape(outputContent);
|
|
126
|
-
setEmotionMorphTargets(_ => ({ ...defaultEmotions, ...emotion }));
|
|
127
|
-
} else {
|
|
128
|
-
// If GLB, convert italian emotions to english ones
|
|
129
|
-
const emotion = handleCustomGLBBlendShape(outputContent);
|
|
130
|
-
const emotionValues =
|
|
131
|
-
emotion === 'default' ? defaultEmotions : emotionMap[emotion];
|
|
132
|
-
setEmotionMorphTargets(_ => ({ ...defaultEmotions, ...emotionValues }));
|
|
133
|
-
}
|
|
134
|
-
},
|
|
135
|
-
[isRPM, handleRPMBlendShape, handleCustomGLBBlendShape]
|
|
136
|
-
);
|
|
137
|
-
|
|
138
|
-
// Callback handlers for various avatar state changes
|
|
139
|
-
const onBaseActionChange = useCallback(
|
|
140
|
-
(action: string, outputContent: string) => {
|
|
141
|
-
// Set emotion morph target influences
|
|
142
|
-
setEmotionMorphTargetInfluences(action, outputContent);
|
|
143
|
-
|
|
144
|
-
// Set current base action
|
|
145
|
-
setCurrentBaseAction({ action, weight: 1 });
|
|
146
|
-
},
|
|
147
|
-
[setEmotionMorphTargetInfluences]
|
|
148
|
-
);
|
|
149
|
-
|
|
150
|
-
const onMorphTargetInfluencesChange = useCallback(
|
|
151
|
-
(influences: Record<string, number>) => {
|
|
152
|
-
// Set morph target influences
|
|
153
|
-
setMorphTargetInfluences(prev => ({ ...prev, ...influences }));
|
|
154
|
-
},
|
|
155
|
-
[]
|
|
156
|
-
);
|
|
157
|
-
|
|
158
|
-
const onMorphTargetDictionaryChange = useCallback(
|
|
159
|
-
(dictionary: Record<string, number>) => {
|
|
160
|
-
// Set morph target dictionary
|
|
161
|
-
setMorphTargetDictionary(dictionary);
|
|
162
|
-
},
|
|
163
|
-
[]
|
|
164
|
-
);
|
|
165
|
-
|
|
166
|
-
// Effect to handle animation changes based on loading state and chat emissions
|
|
167
|
-
useEffect(() => {
|
|
168
|
-
// If loading, set a random loading animation
|
|
169
|
-
if (loading) {
|
|
170
|
-
const randomNumber = Math.floor(Math.random() * 3) + 1;
|
|
171
|
-
onBaseActionChange(`Loading${randomNumber}`, '');
|
|
172
|
-
return;
|
|
41
|
+
headMovement,
|
|
42
|
+
// speaking,
|
|
43
|
+
showControls,
|
|
44
|
+
}: AvatarViewProps) => {
|
|
45
|
+
// Reference to the AvatarAnimator instance for animation control
|
|
46
|
+
const animatorRef = useRef<AvatarAnimator | null>(null);
|
|
47
|
+
|
|
48
|
+
// Memoize the setAnimatorRef callback to ensure it doesn't change on re-renders
|
|
49
|
+
const setAnimatorRef = useCallback((animator: AvatarAnimator | null) => {
|
|
50
|
+
if (animator !== animatorRef.current) {
|
|
51
|
+
console.log('[AvatarView] Animator reference updated');
|
|
52
|
+
animatorRef.current = animator;
|
|
173
53
|
}
|
|
54
|
+
}, []); // Empty dependency array ensures this function never changes
|
|
174
55
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
);
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
:
|
|
185
|
-
|
|
186
|
-
// Check if chat emission contains animation sequence
|
|
187
|
-
const hasOutputTagSequence = chatEmission?.includes(
|
|
188
|
-
'<output class="animation-sequence">'
|
|
189
|
-
);
|
|
190
|
-
const outputContentSequence = hasOutputTagSequence
|
|
191
|
-
? chatEmission
|
|
192
|
-
?.split('<output class="animation-sequence">')[1]
|
|
193
|
-
?.split('</output>')[0]
|
|
194
|
-
?.trim()
|
|
195
|
-
: null;
|
|
196
|
-
|
|
197
|
-
if (outputContentSequence && outputContentSequence.includes('->')) {
|
|
198
|
-
// It's a sequence
|
|
199
|
-
onBaseActionChange(outputContentSequence, outputContentSequence);
|
|
200
|
-
} else if (outputContentEmotion) {
|
|
201
|
-
|
|
202
|
-
console.log('[AvatarView] outputContentEmotion:', outputContentEmotion);
|
|
203
|
-
// It's an emotion
|
|
204
|
-
const randomNumber = Math.floor(Math.random() * 3) + 1;
|
|
205
|
-
onBaseActionChange(
|
|
206
|
-
`${outputContentEmotion}${randomNumber}`,
|
|
207
|
-
outputContentEmotion
|
|
208
|
-
);
|
|
209
|
-
} else {
|
|
210
|
-
const randomNumber = Math.floor(Math.random() * 5) + 1;
|
|
211
|
-
onBaseActionChange(`Idle${randomNumber === 3 ? 4 : randomNumber}`, '');
|
|
56
|
+
// React to changes in chat emission or loading state
|
|
57
|
+
// This effect doesn't re-create the animator, it just uses it
|
|
58
|
+
useEffect(() => {
|
|
59
|
+
if (!animatorRef.current) return;
|
|
60
|
+
|
|
61
|
+
try {
|
|
62
|
+
// Prevents any extra work if loading/emission hasn't changed
|
|
63
|
+
animatorRef.current.processChatEmission(chatEmission, loading);
|
|
64
|
+
} catch (error) {
|
|
65
|
+
console.error('Error processing chat emission:', error);
|
|
212
66
|
}
|
|
213
|
-
}, [
|
|
67
|
+
}, [loading, chatEmission]); // Both dependencies are needed
|
|
214
68
|
|
|
215
|
-
//
|
|
216
|
-
const commonAvatarProps = {
|
|
69
|
+
// Memoize common props to prevent unnecessary object creation on re-renders
|
|
70
|
+
const commonAvatarProps = useCallback(() => ({
|
|
217
71
|
url,
|
|
218
72
|
onCameraZChange: setCameraZ,
|
|
219
|
-
setMorphTargetInfluences,
|
|
220
|
-
setMorphTargetDictionary,
|
|
221
73
|
updateCurrentViseme,
|
|
222
74
|
avatarHeight,
|
|
223
75
|
avatarDepth,
|
|
224
|
-
|
|
76
|
+
setAnimatorRef, // This is now stable across renders
|
|
77
|
+
}), [url, setCameraZ, updateCurrentViseme, avatarHeight, avatarDepth, setAnimatorRef]);
|
|
225
78
|
|
|
226
|
-
// Render avatar
|
|
79
|
+
// Render avatar based on halfBody flag
|
|
227
80
|
return (
|
|
228
81
|
<>
|
|
229
|
-
{showControls && (
|
|
230
|
-
<AnimationControlPanel
|
|
231
|
-
timeScale={timeScale}
|
|
232
|
-
morphTargetDictionary={morphTargetDictionary}
|
|
233
|
-
onBaseActionChange={onBaseActionChange}
|
|
234
|
-
onMorphTargetInfluencesChange={onMorphTargetInfluencesChange}
|
|
235
|
-
onMorphTargetDictionaryChange={onMorphTargetDictionaryChange}
|
|
236
|
-
baseActions={BASE_ACTIONS}
|
|
237
|
-
currentBaseAction={currentBaseAction}
|
|
238
|
-
modifyTimeScale={setTimeScale}
|
|
239
|
-
/>
|
|
240
|
-
)}
|
|
241
|
-
|
|
242
82
|
{halfBody ? (
|
|
243
|
-
<
|
|
83
|
+
<MemoizedHalfBodyAvatar
|
|
84
|
+
{...commonAvatarProps()}
|
|
85
|
+
eyeBlink={eyeBlink}
|
|
86
|
+
headMovement={headMovement}
|
|
87
|
+
/>
|
|
244
88
|
) : (
|
|
245
|
-
<
|
|
246
|
-
{...commonAvatarProps}
|
|
89
|
+
<MemoizedFullbodyAvatar
|
|
90
|
+
{...commonAvatarProps()}
|
|
247
91
|
sex={sex}
|
|
248
|
-
setIsRpm={setIsRPM}
|
|
249
|
-
resetVisemeQueue={resetVisemeQueue}
|
|
250
92
|
eyeBlink={eyeBlink}
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
morphTargetInfluences={morphTargetInfluences}
|
|
254
|
-
stopProcessing={stopProcessing}
|
|
255
|
-
emotionMorphTargets={emotionMorphTargets}
|
|
256
|
-
halfBody={halfBody}
|
|
93
|
+
chatEmission={chatEmission}
|
|
94
|
+
loading={loading}
|
|
257
95
|
/>
|
|
258
96
|
)}
|
|
97
|
+
{showControls && animatorRef.current && (
|
|
98
|
+
<div className="animation-controls">
|
|
99
|
+
{/* Optional animation control UI could be added here */}
|
|
100
|
+
</div>
|
|
101
|
+
)}
|
|
259
102
|
</>
|
|
260
103
|
);
|
|
261
104
|
};
|
|
105
|
+
|
|
106
|
+
export default memo(AvatarView); // Memoize the entire component
|