@memori.ai/memori-react 7.19.2 → 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 +45 -0
- 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/ChatBubble/ChatBubble.js +7 -1
- package/dist/components/ChatBubble/ChatBubble.js.map +1 -1
- package/dist/components/MemoriWidget/MemoriWidget.js +130 -62
- package/dist/components/MemoriWidget/MemoriWidget.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/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/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/ChatBubble/ChatBubble.js +7 -1
- package/esm/components/ChatBubble/ChatBubble.js.map +1 -1
- package/esm/components/MemoriWidget/MemoriWidget.js +130 -62
- package/esm/components/MemoriWidget/MemoriWidget.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/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/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/ChatBubble/ChatBubble.tsx +14 -2
- package/src/components/MemoriWidget/MemoriWidget.tsx +168 -76
- 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/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/components/Avatar/AvatarView/AvatarComponent/components/controllers/AnimationController.ts +0 -308
|
@@ -40,17 +40,6 @@ const timing = {
|
|
|
40
40
|
calculateWeight: (progress) => Math.sin(Math.PI * Math.min(progress, 1)) * WEIGHT_MULTIPLIER,
|
|
41
41
|
smoothWeight: (currentWeight, targetWeight) => currentWeight + (targetWeight - currentWeight) * SMOOTHING_FACTOR,
|
|
42
42
|
};
|
|
43
|
-
const createLogger = (type) => (event, data) => {
|
|
44
|
-
const styles = {
|
|
45
|
-
event: 'color: #4CAF50; font-weight: bold;',
|
|
46
|
-
error: 'color: #f44336; font-weight: bold;',
|
|
47
|
-
debug: 'color: #2196F3; font-weight: bold;',
|
|
48
|
-
};
|
|
49
|
-
console.log(`%c[VisemeContext] ${event}`, styles[type], data);
|
|
50
|
-
};
|
|
51
|
-
const logVisemeEvent = createLogger('event');
|
|
52
|
-
const logVisemeError = createLogger('error');
|
|
53
|
-
const logVisemeDebug = createLogger('debug');
|
|
54
43
|
export const VisemeProvider = ({ children, }) => {
|
|
55
44
|
const visemeQueueRef = useRef([]);
|
|
56
45
|
const audioContextRef = useRef(null);
|
|
@@ -63,10 +52,6 @@ export const VisemeProvider = ({ children, }) => {
|
|
|
63
52
|
const setAudioContext = useCallback((ctx) => {
|
|
64
53
|
audioContextRef.current = ctx;
|
|
65
54
|
ctx.onstatechange = () => {
|
|
66
|
-
logVisemeEvent('Audio Context State Change', {
|
|
67
|
-
state: ctx.state,
|
|
68
|
-
currentTime: ctx.currentTime,
|
|
69
|
-
});
|
|
70
55
|
switch (ctx.state) {
|
|
71
56
|
case 'running':
|
|
72
57
|
setVisemeState('active');
|
|
@@ -104,7 +89,6 @@ export const VisemeProvider = ({ children, }) => {
|
|
|
104
89
|
}, [visemeState]);
|
|
105
90
|
const startProcessing = useCallback((audioCtx) => {
|
|
106
91
|
if (!audioCtx) {
|
|
107
|
-
logVisemeError('No audio context provided', { state: visemeState });
|
|
108
92
|
return;
|
|
109
93
|
}
|
|
110
94
|
audioContextRef.current = audioCtx;
|
|
@@ -112,11 +96,6 @@ export const VisemeProvider = ({ children, }) => {
|
|
|
112
96
|
frameCountRef.current = 0;
|
|
113
97
|
setIsProcessing(true);
|
|
114
98
|
setVisemeState('active');
|
|
115
|
-
logVisemeEvent('Started Processing', {
|
|
116
|
-
audioTime: audioCtx.currentTime,
|
|
117
|
-
queueLength: visemeQueueRef.current.length,
|
|
118
|
-
state: visemeState,
|
|
119
|
-
});
|
|
120
99
|
}, []);
|
|
121
100
|
const stopProcessing = useCallback(() => {
|
|
122
101
|
setIsProcessing(false);
|
|
@@ -125,10 +104,6 @@ export const VisemeProvider = ({ children, }) => {
|
|
|
125
104
|
lastVisemeRef.current = null;
|
|
126
105
|
frameCountRef.current = 0;
|
|
127
106
|
audioContextRef.current = null;
|
|
128
|
-
logVisemeEvent('Stopped Processing', {
|
|
129
|
-
queueLength: visemeQueueRef.current.length,
|
|
130
|
-
state: visemeState,
|
|
131
|
-
});
|
|
132
107
|
}, []);
|
|
133
108
|
const updateCurrentViseme = useCallback((_) => {
|
|
134
109
|
if (!isProcessing || !audioContextRef.current)
|
|
@@ -138,13 +113,6 @@ export const VisemeProvider = ({ children, }) => {
|
|
|
138
113
|
PRELOAD;
|
|
139
114
|
visemeQueueRef.current = visemeQueueRef.current.filter(v => !timing.isExpired(v, audioTime));
|
|
140
115
|
const currentViseme = visemeQueueRef.current.find(v => v.startTime <= audioTime && v.endTime > audioTime - VISEME_OVERLAP);
|
|
141
|
-
if (frameCountRef.current % LOG_INTERVAL === 60) {
|
|
142
|
-
logVisemeDebug('Current Viseme', {
|
|
143
|
-
currentViseme,
|
|
144
|
-
audioTime,
|
|
145
|
-
visemeQueue: visemeQueueRef.current,
|
|
146
|
-
});
|
|
147
|
-
}
|
|
148
116
|
if (currentViseme) {
|
|
149
117
|
const progress = (audioTime - currentViseme.startTime) /
|
|
150
118
|
(currentViseme.endTime - currentViseme.startTime);
|
|
@@ -173,15 +141,8 @@ export const VisemeProvider = ({ children, }) => {
|
|
|
173
141
|
firstVisemeTimeRef.current = null;
|
|
174
142
|
frameCountRef.current = 0;
|
|
175
143
|
setVisemeState('idle');
|
|
176
|
-
logVisemeEvent('Reset Viseme Queue', {
|
|
177
|
-
previousState: visemeState,
|
|
178
|
-
});
|
|
179
144
|
}, [visemeState]);
|
|
180
145
|
const resetAndStartProcessing = useCallback((audioCtx) => {
|
|
181
|
-
logVisemeEvent('Reset And Start Processing', {
|
|
182
|
-
previousState: visemeState,
|
|
183
|
-
queueLength: visemeQueueRef.current.length,
|
|
184
|
-
});
|
|
185
146
|
stopProcessing();
|
|
186
147
|
resetVisemeQueue();
|
|
187
148
|
startProcessing(audioCtx);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"visemeContext.js","sourceRoot":"","sources":["../../src/context/visemeContext.tsx"],"names":[],"mappings":";AAAA,OAAc,EACZ,aAAa,EACb,UAAU,EACV,MAAM,EACN,WAAW,EACX,QAAQ,EACR,OAAO,GACR,MAAM,OAAO,CAAC;AAqBf,MAAM,aAAa,GAAG,aAAa,CAAgC,SAAS,CAAC,CAAC;AAE9E,MAAM,UAAU,GAAwC;IACtD,CAAC,EAAE,YAAY;IACf,CAAC,EAAE,WAAW;IACd,CAAC,EAAE,WAAW;IACd,CAAC,EAAE,WAAW;IACd,CAAC,EAAE,WAAW;IACd,CAAC,EAAE,WAAW;IACd,CAAC,EAAE,WAAW;IACd,CAAC,EAAE,WAAW;IACd,CAAC,EAAE,WAAW;IACd,CAAC,EAAE,WAAW;IACd,EAAE,EAAE,WAAW;IACf,EAAE,EAAE,UAAU;IACd,EAAE,EAAE,UAAU;IACd,EAAE,EAAE,UAAU;IACd,EAAE,EAAE,UAAU;IACd,EAAE,EAAE,WAAW;IACf,EAAE,EAAE,WAAW;IACf,EAAE,EAAE,WAAW;IACf,EAAE,EAAE,WAAW;IACf,EAAE,EAAE,WAAW;IACf,EAAE,EAAE,WAAW;IACf,EAAE,EAAE,WAAW;CAChB,CAAC;AAGF,MAAM,SAAS,GAAG;IAKhB,uBAAuB,EAAE,IAAI;IAK7B,cAAc,EAAE,IAAI;IAMpB,gBAAgB,EAAE,GAAG;IAKrB,YAAY,EAAE,EAAE;IAKhB,OAAO,EAAE,GAAG;IAIZ,iBAAiB,EAAE,GAAG;CACd,CAAC;AAGX,MAAM,CAAC,MAAM,EACX,uBAAuB,EACvB,cAAc,EACd,gBAAgB,EAChB,YAAY,EACZ,OAAO,EACP,iBAAiB,GAClB,GAAG,SAAS,CAAC;AAGd,MAAM,MAAM,GAAG;IAEb,gBAAgB,EAAE,CAAC,SAAiB,EAAE,EAAE,CAAC,SAAS,GAAG,uBAAuB;IAG5E,SAAS,EAAE,CAAC,MAAc,EAAE,WAAmB,EAAE,EAAE,CACjD,MAAM,CAAC,OAAO,GAAG,WAAW,GAAG,cAAc;IAG/C,eAAe,EAAE,CAAC,QAAgB,EAAE,EAAE,CACpC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,GAAG,iBAAiB;IAG/D,YAAY,EAAE,CAAC,aAAqB,EAAE,YAAoB,EAAE,EAAE,CAC5D,aAAa,GAAG,CAAC,YAAY,GAAG,aAAa,CAAC,GAAG,gBAAgB;CACpE,CAAC;
|
|
1
|
+
{"version":3,"file":"visemeContext.js","sourceRoot":"","sources":["../../src/context/visemeContext.tsx"],"names":[],"mappings":"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"}
|
package/esm/locales/de.json
CHANGED
|
@@ -46,6 +46,7 @@
|
|
|
46
46
|
"generatedByAI": "Von KI generierte Antworten können gelegentlich falsche Informationen generieren",
|
|
47
47
|
"whyThisAnswer": "Warum diese Antwort?",
|
|
48
48
|
"whyThisAnswerHelper": "Diese Antwort wurde automatisch von einer künstlichen Intelligenz auf Basis dieser verifizierten Inhalte generiert.",
|
|
49
|
+
"receiverLabel": "Zugewiesen an",
|
|
49
50
|
"completionsEnabled": "Fortschrittliche KI kann mit automatisch generierten Antworten reagieren, die manchmal falsche Informationen enthalten können",
|
|
50
51
|
"completionProviderDown": "Dieser Zwilling ist mit einer generativen KI von integriert {{provider}}, aber es ist derzeit nicht verfügbar. ",
|
|
51
52
|
"completionProviderFallbackName": "ein externer Anbieter",
|
package/esm/locales/en.json
CHANGED
|
@@ -46,6 +46,7 @@
|
|
|
46
46
|
"generatedByAI": "Answer generated by AI, may occasionally generate incorrect informations",
|
|
47
47
|
"whyThisAnswer": "Why this answer?",
|
|
48
48
|
"whyThisAnswerHelper": "This answer was generated automatically by an artificial intelligence based on these verified contents.",
|
|
49
|
+
"receiverLabel": "Assigned to",
|
|
49
50
|
"completionsEnabled": "Advanced AI, can respond with automatically generated answers that may sometimes contain incorrect information",
|
|
50
51
|
"completionProviderDown": "This agent is integrated with a generative AI from {{provider}}, but it is currently unavailable. Try again later.",
|
|
51
52
|
"completionProviderFallbackName": "an external provider",
|
package/esm/locales/es.json
CHANGED
|
@@ -46,6 +46,7 @@
|
|
|
46
46
|
"generatedByAI": "La respuesta generada por IA, ocasionalmente puede generar información incorrecta",
|
|
47
47
|
"whyThisAnswer": "¿Por qué esta respuesta?",
|
|
48
48
|
"whyThisAnswerHelper": "Esta respuesta fue generada automáticamente por una inteligencia artificial basada en estos contenidos verificados.",
|
|
49
|
+
"receiverLabel": "Asignado a",
|
|
49
50
|
"completionsEnabled": "La IA avanzada puede responder con respuestas generadas automáticamente que a veces pueden contener información incorrecta.",
|
|
50
51
|
"completionProviderDown": "Este Agent está integrado con una IA generativa de {{provider}}, pero actualmente no está disponible. ",
|
|
51
52
|
"completionProviderFallbackName": "un proveedor externo",
|
package/esm/locales/fr.json
CHANGED
|
@@ -46,6 +46,7 @@
|
|
|
46
46
|
"generatedByAI": "Réponse générée par l'IA, peut occasionnellement générer des informations incorrectes",
|
|
47
47
|
"whyThisAnswer": "Pourquoi cette réponse ?",
|
|
48
48
|
"whyThisAnswerHelper": "Cette réponse a été générée automatiquement par une intelligence artificielle basée sur ces contenus vérifiés.",
|
|
49
|
+
"receiverLabel": "Assigné à",
|
|
49
50
|
"completionsEnabled": "L'IA avancée peut répondre avec des réponses générées automatiquement qui peuvent parfois contenir des informations incorrectes",
|
|
50
51
|
"completionProviderDown": "Ce Agent est intégré à une IA générative de {{provider}}, mais il est actuellement indisponible. ",
|
|
51
52
|
"completionProviderFallbackName": "un prestataire externe",
|
package/esm/locales/it.json
CHANGED
|
@@ -46,6 +46,7 @@
|
|
|
46
46
|
"generatedByAI": "Risposta generata da IA, può talvolta generare informazioni non corrette",
|
|
47
47
|
"whyThisAnswer": "Perché questa risposta?",
|
|
48
48
|
"whyThisAnswerHelper": "Questa risposta è stata generata automaticamente da un'intelligenza artificiale sulla base di questi contenuti verificati.",
|
|
49
|
+
"receiverLabel": "Assegnato a",
|
|
49
50
|
"completionsEnabled": "IA evoluta, può rispondere con risposte generate automaticamente che talvolta potrebbero contenere informazioni non corrette",
|
|
50
51
|
"completionProviderDown": "Questo agente è integrato con una IA generativa di {{provider}}, ma al momento non è disponibile. Riprova più tardi.",
|
|
51
52
|
"completionProviderFallbackName": "un provider esterno",
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "7.
|
|
2
|
+
"version": "7.21.0",
|
|
3
3
|
"name": "@memori.ai/memori-react",
|
|
4
4
|
"author": "Memori Srl",
|
|
5
5
|
"main": "dist/index.js",
|
|
@@ -292,7 +292,7 @@
|
|
|
292
292
|
},
|
|
293
293
|
"dependencies": {
|
|
294
294
|
"@headlessui/react": "1.7.4",
|
|
295
|
-
"@memori.ai/memori-api-client": "^6.0.
|
|
295
|
+
"@memori.ai/memori-api-client": "^6.0.3",
|
|
296
296
|
"@react-three/drei": "8.20.2",
|
|
297
297
|
"@react-three/fiber": "7.0.25",
|
|
298
298
|
"classnames": "2.5.1",
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import React, { useEffect, useState } from 'react';
|
|
2
2
|
import { Canvas } from '@react-three/fiber';
|
|
3
3
|
import { ContactShadows, PerspectiveCamera } from '@react-three/drei';
|
|
4
|
+
import { AvatarAnimator } from '../components/controllers/AvatarAnimator';
|
|
4
5
|
|
|
5
6
|
const DynamicShadow = ({
|
|
6
|
-
|
|
7
|
+
animator,
|
|
7
8
|
avatarPosition,
|
|
8
|
-
}: {
|
|
9
|
-
|
|
9
|
+
}: {
|
|
10
|
+
animator: AvatarAnimator | null;
|
|
10
11
|
avatarPosition: any;
|
|
11
12
|
}) => {
|
|
12
13
|
// Calculate shadow properties based on animation
|
|
@@ -21,8 +22,14 @@ const DynamicShadow = ({
|
|
|
21
22
|
color: '#000000',
|
|
22
23
|
};
|
|
23
24
|
|
|
25
|
+
if (!animator) {
|
|
26
|
+
return {
|
|
27
|
+
...baseProps,
|
|
28
|
+
opacity: 0,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
24
31
|
// Adjust shadow based on animation type
|
|
25
|
-
if (
|
|
32
|
+
if (animator.getCurrentAnimationName()?.startsWith('Loading')) {
|
|
26
33
|
return {
|
|
27
34
|
...baseProps,
|
|
28
35
|
opacity: 0.85,
|
|
@@ -31,8 +38,8 @@ const DynamicShadow = ({
|
|
|
31
38
|
height: 12,
|
|
32
39
|
};
|
|
33
40
|
} else if (
|
|
34
|
-
|
|
35
|
-
|
|
41
|
+
animator.getCurrentAnimationName()?.includes('Gioia') ||
|
|
42
|
+
animator.getCurrentAnimationName()?.includes('Joy')
|
|
36
43
|
) {
|
|
37
44
|
return {
|
|
38
45
|
...baseProps,
|
|
@@ -42,8 +49,8 @@ const DynamicShadow = ({
|
|
|
42
49
|
height: 11,
|
|
43
50
|
};
|
|
44
51
|
} else if (
|
|
45
|
-
|
|
46
|
-
|
|
52
|
+
animator.getCurrentAnimationName()?.includes('Rabbia') ||
|
|
53
|
+
animator.getCurrentAnimationName()?.includes('Anger')
|
|
47
54
|
) {
|
|
48
55
|
return {
|
|
49
56
|
...baseProps,
|
|
@@ -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
|