@memori.ai/memori-react 7.19.2 → 7.21.1

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 (111) hide show
  1. package/CHANGELOG.md +52 -0
  2. package/dist/components/Avatar/AvatarView/AvatarComponent/Shadow/DynamicShadow.d.ts +3 -2
  3. package/dist/components/Avatar/AvatarView/AvatarComponent/Shadow/DynamicShadow.js +13 -6
  4. package/dist/components/Avatar/AvatarView/AvatarComponent/Shadow/DynamicShadow.js.map +1 -1
  5. package/dist/components/Avatar/AvatarView/AvatarComponent/avatarComponent.d.ts +14 -18
  6. package/dist/components/Avatar/AvatarView/AvatarComponent/avatarComponent.js +19 -77
  7. package/dist/components/Avatar/AvatarView/AvatarComponent/avatarComponent.js.map +1 -1
  8. package/dist/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/fullbodyAvatar.d.ts +17 -2
  9. package/dist/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/fullbodyAvatar.js +95 -70
  10. package/dist/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/fullbodyAvatar.js.map +1 -1
  11. package/dist/components/Avatar/AvatarView/AvatarComponent/components/controllers/AvatarAnimator.d.ts +65 -0
  12. package/dist/components/Avatar/AvatarView/AvatarComponent/components/controllers/AvatarAnimator.js +747 -0
  13. package/dist/components/Avatar/AvatarView/AvatarComponent/components/controllers/AvatarAnimator.js.map +1 -0
  14. package/dist/components/Avatar/AvatarView/AvatarComponent/components/controllers/MorphTargetController.d.ts +9 -2
  15. package/dist/components/Avatar/AvatarView/AvatarComponent/components/controllers/MorphTargetController.js +60 -2
  16. package/dist/components/Avatar/AvatarView/AvatarComponent/components/controllers/MorphTargetController.js.map +1 -1
  17. package/dist/components/Avatar/AvatarView/AvatarComponent/components/halfbodyAvatar.d.ts +3 -4
  18. package/dist/components/Avatar/AvatarView/AvatarComponent/components/halfbodyAvatar.js +5 -11
  19. package/dist/components/Avatar/AvatarView/AvatarComponent/components/halfbodyAvatar.js.map +1 -1
  20. package/dist/components/Avatar/AvatarView/AvatarComponent/constants.d.ts +13 -52
  21. package/dist/components/Avatar/AvatarView/AvatarComponent/constants.js +68 -70
  22. package/dist/components/Avatar/AvatarView/AvatarComponent/constants.js.map +1 -1
  23. package/dist/components/Avatar/AvatarView/index.d.ts +1 -1
  24. package/dist/components/Avatar/AvatarView/index.js +2 -2
  25. package/dist/components/Avatar/AvatarView/index.js.map +1 -1
  26. package/dist/components/ChatBubble/ChatBubble.css +9 -0
  27. package/dist/components/ChatBubble/ChatBubble.js +7 -1
  28. package/dist/components/ChatBubble/ChatBubble.js.map +1 -1
  29. package/dist/components/MemoriWidget/MemoriWidget.js +130 -62
  30. package/dist/components/MemoriWidget/MemoriWidget.js.map +1 -1
  31. package/dist/components/UploadButton/UploadButton.js +2 -2
  32. package/dist/components/UploadButton/UploadButton.js.map +1 -1
  33. package/dist/components/WhyThisAnswer/WhyThisAnswer.css +43 -0
  34. package/dist/components/WhyThisAnswer/WhyThisAnswer.js +2 -1
  35. package/dist/components/WhyThisAnswer/WhyThisAnswer.js.map +1 -1
  36. package/dist/context/visemeContext.js +0 -39
  37. package/dist/context/visemeContext.js.map +1 -1
  38. package/dist/locales/de.json +1 -0
  39. package/dist/locales/en.json +1 -0
  40. package/dist/locales/es.json +1 -0
  41. package/dist/locales/fr.json +1 -0
  42. package/dist/locales/it.json +1 -0
  43. package/esm/components/Avatar/AvatarView/AvatarComponent/Shadow/DynamicShadow.d.ts +3 -2
  44. package/esm/components/Avatar/AvatarView/AvatarComponent/Shadow/DynamicShadow.js +13 -6
  45. package/esm/components/Avatar/AvatarView/AvatarComponent/Shadow/DynamicShadow.js.map +1 -1
  46. package/esm/components/Avatar/AvatarView/AvatarComponent/avatarComponent.d.ts +14 -18
  47. package/esm/components/Avatar/AvatarView/AvatarComponent/avatarComponent.js +20 -78
  48. package/esm/components/Avatar/AvatarView/AvatarComponent/avatarComponent.js.map +1 -1
  49. package/esm/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/fullbodyAvatar.d.ts +17 -2
  50. package/esm/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/fullbodyAvatar.js +99 -74
  51. package/esm/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/fullbodyAvatar.js.map +1 -1
  52. package/esm/components/Avatar/AvatarView/AvatarComponent/components/controllers/AvatarAnimator.d.ts +65 -0
  53. package/esm/components/Avatar/AvatarView/AvatarComponent/components/controllers/AvatarAnimator.js +743 -0
  54. package/esm/components/Avatar/AvatarView/AvatarComponent/components/controllers/AvatarAnimator.js.map +1 -0
  55. package/esm/components/Avatar/AvatarView/AvatarComponent/components/controllers/MorphTargetController.d.ts +9 -2
  56. package/esm/components/Avatar/AvatarView/AvatarComponent/components/controllers/MorphTargetController.js +61 -3
  57. package/esm/components/Avatar/AvatarView/AvatarComponent/components/controllers/MorphTargetController.js.map +1 -1
  58. package/esm/components/Avatar/AvatarView/AvatarComponent/components/halfbodyAvatar.d.ts +3 -4
  59. package/esm/components/Avatar/AvatarView/AvatarComponent/components/halfbodyAvatar.js +5 -11
  60. package/esm/components/Avatar/AvatarView/AvatarComponent/components/halfbodyAvatar.js.map +1 -1
  61. package/esm/components/Avatar/AvatarView/AvatarComponent/constants.d.ts +13 -52
  62. package/esm/components/Avatar/AvatarView/AvatarComponent/constants.js +67 -69
  63. package/esm/components/Avatar/AvatarView/AvatarComponent/constants.js.map +1 -1
  64. package/esm/components/Avatar/AvatarView/index.d.ts +1 -1
  65. package/esm/components/Avatar/AvatarView/index.js +2 -2
  66. package/esm/components/Avatar/AvatarView/index.js.map +1 -1
  67. package/esm/components/ChatBubble/ChatBubble.css +9 -0
  68. package/esm/components/ChatBubble/ChatBubble.js +7 -1
  69. package/esm/components/ChatBubble/ChatBubble.js.map +1 -1
  70. package/esm/components/MemoriWidget/MemoriWidget.js +130 -62
  71. package/esm/components/MemoriWidget/MemoriWidget.js.map +1 -1
  72. package/esm/components/UploadButton/UploadButton.js +2 -2
  73. package/esm/components/UploadButton/UploadButton.js.map +1 -1
  74. package/esm/components/WhyThisAnswer/WhyThisAnswer.css +43 -0
  75. package/esm/components/WhyThisAnswer/WhyThisAnswer.js +2 -1
  76. package/esm/components/WhyThisAnswer/WhyThisAnswer.js.map +1 -1
  77. package/esm/context/visemeContext.js +0 -39
  78. package/esm/context/visemeContext.js.map +1 -1
  79. package/esm/locales/de.json +1 -0
  80. package/esm/locales/en.json +1 -0
  81. package/esm/locales/es.json +1 -0
  82. package/esm/locales/fr.json +1 -0
  83. package/esm/locales/it.json +1 -0
  84. package/package.json +2 -2
  85. package/src/components/Avatar/AvatarView/AvatarComponent/Shadow/DynamicShadow.tsx +15 -8
  86. package/src/components/Avatar/AvatarView/AvatarComponent/avatarComponent.tsx +64 -219
  87. package/src/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/fullbodyAvatar.tsx +221 -124
  88. package/src/components/Avatar/AvatarView/AvatarComponent/components/controllers/AvatarAnimator.ts +1250 -0
  89. package/src/components/Avatar/AvatarView/AvatarComponent/components/controllers/MorphTargetController.ts +164 -8
  90. package/src/components/Avatar/AvatarView/AvatarComponent/components/halfbodyAvatar.tsx +19 -17
  91. package/src/components/Avatar/AvatarView/AvatarComponent/constants.ts +80 -79
  92. package/src/components/Avatar/AvatarView/index.tsx +1 -7
  93. package/src/components/ChatBubble/ChatBubble.css +9 -0
  94. package/src/components/ChatBubble/ChatBubble.tsx +14 -2
  95. package/src/components/MemoriWidget/MemoriWidget.tsx +168 -76
  96. package/src/components/UploadButton/UploadButton.tsx +4 -4
  97. package/src/components/UploadButton/__snapshots__/UploadButton.test.tsx.snap +1 -1
  98. package/src/components/WhyThisAnswer/WhyThisAnswer.css +43 -0
  99. package/src/components/WhyThisAnswer/WhyThisAnswer.stories.tsx +44 -3
  100. package/src/components/WhyThisAnswer/WhyThisAnswer.test.tsx +128 -8
  101. package/src/components/WhyThisAnswer/WhyThisAnswer.tsx +28 -3
  102. package/src/components/WhyThisAnswer/__snapshots__/WhyThisAnswer.test.tsx.snap +15 -1
  103. package/src/components/layouts/layouts.stories.tsx +0 -8
  104. package/src/context/visemeContext.tsx +40 -41
  105. package/src/index.stories.tsx +63 -65
  106. package/src/locales/de.json +1 -0
  107. package/src/locales/en.json +1 -0
  108. package/src/locales/es.json +1 -0
  109. package/src/locales/fr.json +1 -0
  110. package/src/locales/it.json +1 -0
  111. package/src/components/Avatar/AvatarView/AvatarComponent/components/controllers/AnimationController.ts +0 -308
@@ -0,0 +1,743 @@
1
+ import { AnimationMixer, LoopOnce, } from 'three';
2
+ import { MAPPING_EMOTIONS_ITALIAN_TO_ENGLISH } from '../../constants';
3
+ export class AvatarAnimator {
4
+ constructor() {
5
+ this.mixer = null;
6
+ this.actions = {};
7
+ this.animations = new Map();
8
+ this.currentAnimation = null;
9
+ this.currentSequence = null;
10
+ this.sequenceIndex = 0;
11
+ this.isTransitioning = false;
12
+ this.timeScale = 1.0;
13
+ this.fadeInDuration = 0.8;
14
+ this.fadeOutDuration = 0.8;
15
+ this.avatarType = 'CUSTOM_GLB';
16
+ this.eventListeners = {
17
+ start: [],
18
+ complete: [],
19
+ loop: [],
20
+ transition: [],
21
+ error: [],
22
+ };
23
+ this.initialized = false;
24
+ this.idleRotationCount = 0;
25
+ this.currentIdleAnimation = null;
26
+ this.idleRotationLimit = 5;
27
+ this.lastAnimationTime = null;
28
+ }
29
+ async initialize(scene, preloadedActions, animations = [], avatarType = 'CUSTOM_GLB') {
30
+ if (this.initialized || this.mixer) {
31
+ console.warn('[AvatarAnimator] Already initialized, ignoring duplicate initialization');
32
+ return;
33
+ }
34
+ this.mixer = new AnimationMixer(scene);
35
+ this.avatarType = avatarType;
36
+ this.actions = {};
37
+ this.registerClipsDirectly(animations);
38
+ Object.entries(preloadedActions).forEach(([name, action]) => {
39
+ if (!this.actions[name]) {
40
+ this.actions[name] = action;
41
+ this.registerAnimation(name, action);
42
+ }
43
+ });
44
+ this.setupMixerEvents();
45
+ const idleAnimations = ['Idle1', 'Idle2', 'Idle3', 'Idle4', 'Idle5'];
46
+ let startedSuccessfully = false;
47
+ for (const idleName of idleAnimations) {
48
+ if (this.actions[idleName]) {
49
+ try {
50
+ const idleAction = this.actions[idleName];
51
+ idleAction.reset();
52
+ idleAction.setEffectiveTimeScale(1);
53
+ idleAction.setEffectiveWeight(1);
54
+ idleAction.setLoop(Infinity, Infinity);
55
+ idleAction.play();
56
+ this.currentAnimation = idleName;
57
+ this.currentIdleAnimation = idleName;
58
+ this.idleRotationCount = 0;
59
+ startedSuccessfully = true;
60
+ break;
61
+ }
62
+ catch (error) {
63
+ console.error(`Error starting ${idleName}:`, error);
64
+ }
65
+ }
66
+ }
67
+ if (!startedSuccessfully) {
68
+ console.warn('[AvatarAnimator] Could not start any idle animation directly');
69
+ }
70
+ this.initialized = true;
71
+ }
72
+ registerClipsDirectly(clips) {
73
+ if (!this.mixer)
74
+ return;
75
+ clips.forEach(clip => {
76
+ var _a;
77
+ const action = (_a = this.mixer) === null || _a === void 0 ? void 0 : _a.clipAction(clip);
78
+ if (!action) {
79
+ console.warn(`[AvatarAnimator] Failed to create action for clip: ${clip.name}`);
80
+ return;
81
+ }
82
+ this.actions[clip.name] = action;
83
+ this.registerAnimation(clip.name, action);
84
+ });
85
+ }
86
+ registerAnimations(actions, clips = []) {
87
+ const allAnimationNames = new Set();
88
+ clips.forEach(clip => allAnimationNames.add(clip.name));
89
+ Object.keys(actions).forEach(name => allAnimationNames.add(name));
90
+ clips.forEach(clip => {
91
+ if (this.mixer) {
92
+ const action = this.mixer.clipAction(clip);
93
+ this.actions[clip.name] = action;
94
+ this.registerAnimation(clip.name, action);
95
+ }
96
+ });
97
+ Object.entries(actions).forEach(([name, action]) => {
98
+ if (!this.actions[name]) {
99
+ this.actions[name] = action;
100
+ this.registerAnimation(name, action);
101
+ }
102
+ });
103
+ const idleAnimations = this.getAnimationsByCategory('IDLE');
104
+ const loadingAnimations = this.getAnimationsByCategory('LOADING');
105
+ const actionAnimations = this.getAnimationsByCategory('ACTION');
106
+ }
107
+ registerAnimation(name, action) {
108
+ const duration = action.getClip().duration;
109
+ let category = 'ACTION';
110
+ let defaultLoopCount = 1;
111
+ let canLoop = false;
112
+ const lowerName = name.toLowerCase();
113
+ if (lowerName.includes('idle')) {
114
+ category = 'IDLE';
115
+ defaultLoopCount = 0;
116
+ canLoop = true;
117
+ }
118
+ else if (lowerName.includes('loading') || lowerName.includes('wait')) {
119
+ category = 'LOADING';
120
+ defaultLoopCount = 0;
121
+ canLoop = true;
122
+ }
123
+ this.animations.set(name, {
124
+ name,
125
+ category,
126
+ duration,
127
+ canLoop,
128
+ defaultLoopCount,
129
+ });
130
+ }
131
+ play(animationName, options = {}) {
132
+ var _a, _b, _c, _d;
133
+ try {
134
+ if (!this.initialized || !this.mixer) {
135
+ console.warn(`[AvatarAnimator] Cannot play ${animationName} - not initialized`);
136
+ return;
137
+ }
138
+ const nextAction = this.actions[animationName];
139
+ if (!nextAction) {
140
+ console.warn(`[AvatarAnimator] Animation not found: ${animationName}`);
141
+ if (options.fallbackToIdle !== false) {
142
+ const fallbackAnim = Object.keys(this.actions)[0];
143
+ if (fallbackAnim) {
144
+ this.play(fallbackAnim, { ...options, fallbackToIdle: false });
145
+ }
146
+ }
147
+ return;
148
+ }
149
+ const animInfo = this.getAnimationInfo(animationName);
150
+ if (!animInfo) {
151
+ console.warn(`[AvatarAnimator] Animation info not found: ${animationName}`);
152
+ if (options.fallbackToIdle !== false) {
153
+ this.idle();
154
+ }
155
+ return;
156
+ }
157
+ if (this.currentAnimation === animationName &&
158
+ !this.isTransitioning &&
159
+ options.loopCount === undefined) {
160
+ return;
161
+ }
162
+ if (this.isTransitioning) {
163
+ if (this.currentAnimation) {
164
+ const currentAction = this.actions[this.currentAnimation];
165
+ if (currentAction) {
166
+ currentAction.fadeOut(0.1);
167
+ }
168
+ }
169
+ }
170
+ const fadeIn = (_a = options.fadeInDuration) !== null && _a !== void 0 ? _a : this.fadeInDuration;
171
+ const fadeOut = (_b = options.fadeOutDuration) !== null && _b !== void 0 ? _b : this.fadeOutDuration;
172
+ const loopCount = (_c = options.loopCount) !== null && _c !== void 0 ? _c : animInfo.defaultLoopCount;
173
+ const timeScale = (_d = options.timeScale) !== null && _d !== void 0 ? _d : this.timeScale;
174
+ const isIdleAnimation = animInfo.category === 'IDLE';
175
+ if (isIdleAnimation) {
176
+ this.currentIdleAnimation = animationName;
177
+ this.idleRotationCount = 0;
178
+ }
179
+ this.emit('transition', {
180
+ from: this.currentAnimation,
181
+ to: animationName,
182
+ });
183
+ if (this.currentAnimation) {
184
+ const currentAction = this.actions[this.currentAnimation];
185
+ if (currentAction) {
186
+ if (this.currentAnimation === animationName) {
187
+ currentAction.stop();
188
+ }
189
+ else {
190
+ currentAction.fadeOut(fadeOut);
191
+ }
192
+ }
193
+ }
194
+ nextAction.reset();
195
+ nextAction.fadeIn(fadeIn);
196
+ nextAction.timeScale = timeScale;
197
+ nextAction.enabled = true;
198
+ if (loopCount === 0) {
199
+ nextAction.setLoop(Infinity, Infinity);
200
+ }
201
+ else {
202
+ nextAction.setLoop(loopCount > 1 ? loopCount : LoopOnce, loopCount > 1 ? loopCount : 1);
203
+ nextAction.clampWhenFinished = true;
204
+ }
205
+ nextAction.play();
206
+ this.currentAnimation = animationName;
207
+ this.isTransitioning = true;
208
+ const transitionDuration = Math.max(fadeIn, fadeOut) * 1000;
209
+ setTimeout(() => {
210
+ this.isTransitioning = false;
211
+ }, transitionDuration);
212
+ this.emit('start', {
213
+ animation: animationName,
214
+ category: animInfo.category,
215
+ loopCount,
216
+ });
217
+ }
218
+ catch (error) {
219
+ console.error(`[AvatarAnimator] Error in play method for ${animationName}:`, error);
220
+ if (options.fallbackToIdle !== false) {
221
+ try {
222
+ this.idle();
223
+ }
224
+ catch (recoveryError) {
225
+ console.error('[AvatarAnimator] Failed to recover with idle animation:', recoveryError);
226
+ }
227
+ }
228
+ }
229
+ }
230
+ execute(command) {
231
+ if (!this.initialized) {
232
+ console.warn('[AvatarAnimator] Cannot execute - not initialized');
233
+ return;
234
+ }
235
+ try {
236
+ let loopCount;
237
+ const loopMatch = command.match(/\[loop=(\d+)\]/);
238
+ if (loopMatch) {
239
+ loopCount = parseInt(loopMatch[1], 10);
240
+ command = command.replace(loopMatch[0], '').trim();
241
+ }
242
+ if (command.includes('->')) {
243
+ const sequence = command.split('->').map(s => s.trim());
244
+ this.playSequence(sequence, { loopCount });
245
+ }
246
+ else {
247
+ this.play(command, { loopCount });
248
+ }
249
+ }
250
+ catch (error) {
251
+ console.error('[AvatarAnimator] Error executing animation command:', error);
252
+ this.emit('error', { error, command });
253
+ this.idle();
254
+ }
255
+ }
256
+ processChatEmission(chatEmission, isLoading) {
257
+ if (!this.initialized) {
258
+ console.warn('[AvatarAnimator] Cannot process chat emission - not initialized');
259
+ return;
260
+ }
261
+ const wasInLoadingState = this.getAnimationCategory() === 'LOADING';
262
+ if (isLoading) {
263
+ if (wasInLoadingState) {
264
+ return;
265
+ }
266
+ this.loading();
267
+ return;
268
+ }
269
+ if (!chatEmission) {
270
+ if (this.getAnimationCategory() === 'IDLE') {
271
+ return;
272
+ }
273
+ this.idle(wasInLoadingState
274
+ ? { fadeInDuration: 1.2, fadeOutDuration: 1.0 }
275
+ : undefined);
276
+ return;
277
+ }
278
+ const sequenceMatch = chatEmission.match(/<output class="animation-sequence">(.*?)<\/output>/);
279
+ const animationMatch = chatEmission.match(/<output class="animation">(.*?)(\[loop=(\d+)\])?<\/output>/);
280
+ const emotionMatch = chatEmission.match(/<output class="memori-emotion">(.*?)<\/output>/);
281
+ const transitionOptions = this.calculateTransitionOptions();
282
+ if (sequenceMatch && sequenceMatch[1]) {
283
+ const sequence = sequenceMatch[1].trim();
284
+ if (this.currentSequence &&
285
+ this.currentSequence.join('->') === sequence &&
286
+ this.sequenceIndex < this.currentSequence.length) {
287
+ return;
288
+ }
289
+ this.executeWithTransition(sequence, transitionOptions);
290
+ return;
291
+ }
292
+ if (animationMatch && animationMatch[1]) {
293
+ const animation = animationMatch[1].trim();
294
+ let loopCount;
295
+ if (animationMatch[3]) {
296
+ loopCount = parseInt(animationMatch[3], 10);
297
+ }
298
+ this.play(animation, {
299
+ ...transitionOptions,
300
+ loopCount,
301
+ });
302
+ return;
303
+ }
304
+ if (emotionMatch && emotionMatch[1]) {
305
+ const emotion = emotionMatch[1].trim();
306
+ console.log('[AvatarAnimator] Processing emotion:', emotion);
307
+ let matchingAnimations = [];
308
+ if (MAPPING_EMOTIONS_ITALIAN_TO_ENGLISH.find(item => item.english === emotion)) {
309
+ console.log('[AvatarAnimator] Found emotion in English mapping');
310
+ let matchingEmotions = MAPPING_EMOTIONS_ITALIAN_TO_ENGLISH.filter(item => item.english === emotion);
311
+ console.log('[AvatarAnimator] Matching emotions:', matchingEmotions);
312
+ matchingAnimations = this.getAllAnimationNames().filter(name => matchingEmotions.some(emotion => name.toLowerCase().startsWith(emotion.italian.toLowerCase())));
313
+ }
314
+ else {
315
+ console.log('[AvatarAnimator] Using generalized emotion matching approach');
316
+ matchingAnimations = this.getAllAnimationNames().filter(name => name.toLowerCase().startsWith(emotion.toLowerCase()));
317
+ }
318
+ console.log('[AvatarAnimator] Found matching animations:', matchingAnimations);
319
+ if (matchingAnimations.length > 0) {
320
+ const randomIndex = Math.floor(Math.random() * matchingAnimations.length);
321
+ const animationToPlay = matchingAnimations[randomIndex];
322
+ console.log('[AvatarAnimator] Selected animation to play:', animationToPlay);
323
+ this.play(animationToPlay, transitionOptions);
324
+ return;
325
+ }
326
+ else {
327
+ console.log('[AvatarAnimator] No matching animations found for emotion:', emotion);
328
+ }
329
+ }
330
+ if (this.getAnimationCategory() !== 'IDLE') {
331
+ this.idle(transitionOptions);
332
+ }
333
+ }
334
+ calculateTransitionOptions() {
335
+ var _a, _b;
336
+ const options = {
337
+ fadeInDuration: this.fadeInDuration,
338
+ fadeOutDuration: this.fadeOutDuration,
339
+ timeScale: this.timeScale,
340
+ };
341
+ const currentCategory = this.getAnimationCategory();
342
+ const currentAction = this.currentAnimation
343
+ ? this.actions[this.currentAnimation]
344
+ : null;
345
+ options.fadeOutDuration = 0.8;
346
+ options.fadeInDuration = 0.8;
347
+ if (currentAction) {
348
+ const clip = currentAction.getClip();
349
+ const progress = currentAction.time / clip.duration;
350
+ if (progress > 0.75) {
351
+ options.fadeOutDuration = Math.max(0.4, ((_a = options.fadeOutDuration) !== null && _a !== void 0 ? _a : 0.8) * 0.8);
352
+ }
353
+ else if (progress < 0.25) {
354
+ options.fadeInDuration = Math.max(0.4, ((_b = options.fadeInDuration) !== null && _b !== void 0 ? _b : 0.8) * 0.8);
355
+ }
356
+ }
357
+ return options;
358
+ }
359
+ executeWithTransition(command, options = {}) {
360
+ if (!this.initialized) {
361
+ console.warn('[AvatarAnimator] Cannot execute - not initialized');
362
+ return;
363
+ }
364
+ try {
365
+ let loopCount;
366
+ const loopMatch = command.match(/\[loop=(\d+)\]/);
367
+ if (loopMatch) {
368
+ loopCount = parseInt(loopMatch[1], 10);
369
+ command = command.replace(loopMatch[0], '').trim();
370
+ }
371
+ if (command.includes('->')) {
372
+ const sequence = command.split('->').map(s => s.trim());
373
+ const sequenceOptions = {
374
+ ...options,
375
+ loopCount: loopCount || 1,
376
+ };
377
+ this.playSequence(sequence, sequenceOptions);
378
+ }
379
+ else {
380
+ this.play(command, {
381
+ ...options,
382
+ loopCount,
383
+ });
384
+ }
385
+ }
386
+ catch (error) {
387
+ console.error('[AvatarAnimator] Error executing animation command:', error);
388
+ this.emit('error', { error, command });
389
+ this.idle();
390
+ }
391
+ }
392
+ idle(options = {}) {
393
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j;
394
+ const idleAnimations = this.getAnimationsByCategory('IDLE');
395
+ if (idleAnimations.length > 0) {
396
+ let availableIdles = idleAnimations;
397
+ if (this.getAnimationCategory() === 'IDLE') {
398
+ availableIdles = idleAnimations.filter(info => info.name !== this.currentAnimation);
399
+ if (availableIdles.length === 0) {
400
+ availableIdles = idleAnimations;
401
+ }
402
+ }
403
+ const randomIndex = Math.floor(Math.random() * availableIdles.length);
404
+ const selectedIdle = availableIdles[randomIndex].name;
405
+ const transitionOptions = {
406
+ fadeInDuration: (_a = options.fadeInDuration) !== null && _a !== void 0 ? _a : 0.7,
407
+ fadeOutDuration: (_b = options.fadeOutDuration) !== null && _b !== void 0 ? _b : 0.7,
408
+ timeScale: (_c = options.timeScale) !== null && _c !== void 0 ? _c : 0.9,
409
+ loopCount: 0,
410
+ ...options,
411
+ };
412
+ transitionOptions.loopCount = 0;
413
+ this.play(selectedIdle, transitionOptions);
414
+ this.currentIdleAnimation = selectedIdle;
415
+ this.idleRotationCount = 0;
416
+ return;
417
+ }
418
+ else {
419
+ console.warn('[AvatarAnimator] No idle animations available, checking fallback options');
420
+ const loopableAnimations = Array.from(this.animations.values())
421
+ .filter(info => info.canLoop)
422
+ .map(info => info.name);
423
+ if (loopableAnimations.length > 0) {
424
+ const randomIndex = Math.floor(Math.random() * loopableAnimations.length);
425
+ const fallbackAnimation = loopableAnimations[randomIndex];
426
+ this.play(fallbackAnimation, {
427
+ loopCount: 0,
428
+ fadeInDuration: (_d = options.fadeInDuration) !== null && _d !== void 0 ? _d : 0.7,
429
+ fadeOutDuration: (_e = options.fadeOutDuration) !== null && _e !== void 0 ? _e : 0.7,
430
+ timeScale: (_f = options.timeScale) !== null && _f !== void 0 ? _f : 0.9,
431
+ });
432
+ this.currentIdleAnimation = fallbackAnimation;
433
+ this.idleRotationCount = 0;
434
+ }
435
+ else if (Object.keys(this.actions).length > 0) {
436
+ const firstAnimation = Object.keys(this.actions)[0];
437
+ this.play(firstAnimation, {
438
+ loopCount: 0,
439
+ fadeInDuration: (_g = options.fadeInDuration) !== null && _g !== void 0 ? _g : 0.7,
440
+ fadeOutDuration: (_h = options.fadeOutDuration) !== null && _h !== void 0 ? _h : 0.7,
441
+ timeScale: (_j = options.timeScale) !== null && _j !== void 0 ? _j : 0.9,
442
+ });
443
+ this.currentIdleAnimation = firstAnimation;
444
+ this.idleRotationCount = 0;
445
+ }
446
+ }
447
+ }
448
+ loading(options = {}) {
449
+ var _a, _b, _c;
450
+ const randomLoading = this.getRandomAnimation('LOADING');
451
+ if (randomLoading) {
452
+ const transitionOptions = {
453
+ loopCount: 0,
454
+ fadeInDuration: (_a = options.fadeInDuration) !== null && _a !== void 0 ? _a : 0.8,
455
+ fadeOutDuration: (_b = options.fadeOutDuration) !== null && _b !== void 0 ? _b : 0.8,
456
+ timeScale: (_c = options.timeScale) !== null && _c !== void 0 ? _c : this.timeScale,
457
+ ...options,
458
+ };
459
+ transitionOptions.loopCount = 0;
460
+ this.play(randomLoading, transitionOptions);
461
+ }
462
+ else {
463
+ console.warn('[AvatarAnimator] No loading animations available, using idle instead');
464
+ this.idle(options);
465
+ }
466
+ }
467
+ playSequence(sequence, options = {}) {
468
+ var _a;
469
+ if (!sequence || sequence.length === 0) {
470
+ console.warn('[AvatarAnimator] Empty animation sequence provided');
471
+ return;
472
+ }
473
+ if (sequence.length > 5) {
474
+ console.warn(`[AvatarAnimator] Sequence too long (${sequence.length}), limiting to 5 animations`);
475
+ sequence = sequence.slice(0, 5);
476
+ }
477
+ const validSequence = sequence.filter(name => this.actions[name]);
478
+ if (validSequence.length === 0) {
479
+ console.error('[AvatarAnimator] No valid animations in sequence, defaulting to idle');
480
+ this.idle();
481
+ return;
482
+ }
483
+ if (this.isTransitioning) {
484
+ setTimeout(() => {
485
+ this.playSequence(sequence, options);
486
+ }, 100);
487
+ return;
488
+ }
489
+ this.currentSequence = [...validSequence];
490
+ this.sequenceIndex = 0;
491
+ const firstAnimationOptions = {
492
+ fadeInDuration: 0.6,
493
+ fadeOutDuration: 0.6,
494
+ loopCount: 1,
495
+ timeScale: (_a = options.timeScale) !== null && _a !== void 0 ? _a : this.timeScale,
496
+ };
497
+ const firstAnimation = validSequence[0];
498
+ this.play(firstAnimation, firstAnimationOptions);
499
+ }
500
+ forceIdle() {
501
+ const idleAnimations = this.getAnimationsByCategory('IDLE');
502
+ if (idleAnimations.length > 0) {
503
+ const forcedIdle = idleAnimations[0].name;
504
+ this.play(forcedIdle, {
505
+ loopCount: 0,
506
+ fadeInDuration: 0.8,
507
+ fadeOutDuration: 0.8,
508
+ });
509
+ this.currentIdleAnimation = forcedIdle;
510
+ this.idleRotationCount = 0;
511
+ }
512
+ else {
513
+ console.error('[AvatarAnimator] No idle animations available for forced transition');
514
+ }
515
+ }
516
+ update(delta) {
517
+ if (!this.initialized || !this.mixer)
518
+ return;
519
+ const clampedDelta = Math.min(delta, 0.1);
520
+ this.mixer.update(clampedDelta);
521
+ if (this.isTransitioning) {
522
+ return;
523
+ }
524
+ if (this.currentSequence && this.currentAnimation) {
525
+ const currentAction = this.actions[this.currentAnimation];
526
+ if (currentAction) {
527
+ const clipDuration = currentAction.getClip().duration;
528
+ const progress = currentAction.time / clipDuration;
529
+ if (progress > 0.85 && !this.isTransitioning) {
530
+ if (this.sequenceIndex < this.currentSequence.length - 1) {
531
+ this.sequenceIndex++;
532
+ const nextAnimation = this.currentSequence[this.sequenceIndex];
533
+ this.play(nextAnimation, {
534
+ fadeInDuration: 0.5,
535
+ fadeOutDuration: 0.5,
536
+ loopCount: 1,
537
+ });
538
+ }
539
+ else {
540
+ this.currentSequence = null;
541
+ this.sequenceIndex = 0;
542
+ this.idle({
543
+ fadeInDuration: 0.7,
544
+ fadeOutDuration: 0.7,
545
+ });
546
+ }
547
+ }
548
+ }
549
+ }
550
+ if (this.currentAnimation &&
551
+ this.currentIdleAnimation &&
552
+ this.getAnimationCategory() === 'IDLE') {
553
+ const currentAction = this.actions[this.currentAnimation];
554
+ if (currentAction) {
555
+ const clipDuration = currentAction.getClip().duration;
556
+ const currentTime = currentAction.time % clipDuration;
557
+ const previousTime = this.lastAnimationTime || 0;
558
+ if (previousTime > currentTime + 0.1) {
559
+ this.idleRotationCount++;
560
+ if (this.idleRotationCount >= this.idleRotationLimit) {
561
+ this.idleRotationCount = 0;
562
+ this.idle({
563
+ fadeInDuration: 0.6,
564
+ fadeOutDuration: 0.6,
565
+ });
566
+ }
567
+ }
568
+ this.lastAnimationTime = currentTime;
569
+ }
570
+ }
571
+ }
572
+ isAnimationPlaying(animationName) {
573
+ if (!this.actions[animationName])
574
+ return false;
575
+ const action = this.actions[animationName];
576
+ return action.isRunning() && action.getEffectiveWeight() > 0.1;
577
+ }
578
+ setupMixerEvents() {
579
+ if (!this.mixer) {
580
+ console.warn('[AvatarAnimator] Cannot setup mixer events - mixer not initialized');
581
+ return;
582
+ }
583
+ this.mixer.addEventListener('loop', event => {
584
+ const action = event.action;
585
+ if (!action || !this.currentAnimation)
586
+ return;
587
+ if (action === this.actions[this.currentAnimation]) {
588
+ this.emit('loop', { animation: this.currentAnimation });
589
+ }
590
+ });
591
+ this.mixer.addEventListener('finished', event => {
592
+ const action = event.action;
593
+ if (!action || !this.currentAnimation)
594
+ return;
595
+ if (action === this.actions[this.currentAnimation]) {
596
+ if (this.isTransitioning) {
597
+ return;
598
+ }
599
+ this.emit('complete', { animation: this.currentAnimation });
600
+ setTimeout(() => {
601
+ var _a;
602
+ if (this.currentSequence &&
603
+ this.sequenceIndex < this.currentSequence.length - 1) {
604
+ this.sequenceIndex++;
605
+ this.play(this.currentSequence[this.sequenceIndex], {
606
+ fadeInDuration: 0.5,
607
+ fadeOutDuration: 0.5,
608
+ loopCount: 1,
609
+ });
610
+ }
611
+ else if (this.currentSequence &&
612
+ this.sequenceIndex >= this.currentSequence.length - 1) {
613
+ this.currentSequence = null;
614
+ this.sequenceIndex = 0;
615
+ this.idle({
616
+ fadeInDuration: 0.7,
617
+ fadeOutDuration: 0.7,
618
+ });
619
+ }
620
+ else if (this.currentAnimation &&
621
+ ((_a = this.getAnimationInfo(this.currentAnimation)) === null || _a === void 0 ? void 0 : _a.category) !== 'IDLE') {
622
+ this.idle({
623
+ fadeInDuration: 0.7,
624
+ fadeOutDuration: 0.7,
625
+ });
626
+ }
627
+ }, 50);
628
+ }
629
+ });
630
+ }
631
+ handleSequenceProgressionIfNeeded() {
632
+ if (!this.currentSequence ||
633
+ !this.currentAnimation ||
634
+ this.sequenceIndex >= this.currentSequence.length - 1) {
635
+ return;
636
+ }
637
+ const currentAction = this.actions[this.currentAnimation];
638
+ if (!currentAction)
639
+ return;
640
+ const clipDuration = currentAction.getClip().duration;
641
+ const progress = currentAction.time / clipDuration;
642
+ if (progress > 0.9 && !this.isTransitioning) {
643
+ this.sequenceIndex++;
644
+ if (this.sequenceIndex < this.currentSequence.length) {
645
+ const nextAnimation = this.currentSequence[this.sequenceIndex];
646
+ this.play(nextAnimation, {
647
+ fadeInDuration: 0.3,
648
+ fadeOutDuration: 0.3,
649
+ loopCount: 1,
650
+ });
651
+ }
652
+ else {
653
+ this.currentSequence = null;
654
+ this.sequenceIndex = 0;
655
+ this.idle();
656
+ }
657
+ }
658
+ }
659
+ handleIdleRotationIfNeeded() {
660
+ if (!this.currentAnimation ||
661
+ !this.currentIdleAnimation ||
662
+ this.getAnimationCategory() !== 'IDLE') {
663
+ return;
664
+ }
665
+ const currentAction = this.actions[this.currentAnimation];
666
+ if (!currentAction)
667
+ return;
668
+ const clipDuration = currentAction.getClip().duration;
669
+ const currentTime = currentAction.time % clipDuration;
670
+ const previousTime = this.lastAnimationTime || 0;
671
+ if (previousTime > currentTime + 0.1) {
672
+ this.idleRotationCount++;
673
+ if (this.idleRotationCount >= this.idleRotationLimit) {
674
+ this.idleRotationCount = 0;
675
+ this.idle();
676
+ }
677
+ }
678
+ this.lastAnimationTime = currentTime;
679
+ }
680
+ setTimeScale(timeScale) {
681
+ this.timeScale = timeScale;
682
+ if (this.currentAnimation) {
683
+ const currentAction = this.actions[this.currentAnimation];
684
+ if (currentAction) {
685
+ currentAction.timeScale = timeScale;
686
+ }
687
+ }
688
+ }
689
+ getRandomAnimation(category, exclude = []) {
690
+ const filteredAnimations = Array.from(this.animations.values()).filter(info => info.category === category && !exclude.includes(info.name));
691
+ if (filteredAnimations.length === 0)
692
+ return null;
693
+ const randomIndex = Math.floor(Math.random() * filteredAnimations.length);
694
+ return filteredAnimations[randomIndex].name;
695
+ }
696
+ getAnimationInfo(name) {
697
+ return this.animations.get(name) || null;
698
+ }
699
+ getAnimationCategory() {
700
+ var _a;
701
+ if (!this.currentAnimation)
702
+ return null;
703
+ return ((_a = this.getAnimationInfo(this.currentAnimation)) === null || _a === void 0 ? void 0 : _a.category) || null;
704
+ }
705
+ on(event, callback) {
706
+ if (this.eventListeners[event]) {
707
+ this.eventListeners[event].push(callback);
708
+ }
709
+ }
710
+ off(event, callback) {
711
+ if (this.eventListeners[event]) {
712
+ this.eventListeners[event] = this.eventListeners[event].filter(cb => cb !== callback);
713
+ }
714
+ }
715
+ emit(event, data) {
716
+ if (this.eventListeners[event]) {
717
+ this.eventListeners[event].forEach(callback => {
718
+ try {
719
+ callback(data);
720
+ }
721
+ catch (error) {
722
+ console.error(`Error in ${event} event handler:`, error);
723
+ }
724
+ });
725
+ }
726
+ }
727
+ getCurrentAnimationName() {
728
+ return this.currentAnimation;
729
+ }
730
+ getAvatarType() {
731
+ return this.avatarType;
732
+ }
733
+ isInitialized() {
734
+ return this.initialized;
735
+ }
736
+ getAllAnimationNames() {
737
+ return Array.from(this.animations.keys());
738
+ }
739
+ getAnimationsByCategory(category) {
740
+ return Array.from(this.animations.values()).filter(info => info.category === category);
741
+ }
742
+ }
743
+ //# sourceMappingURL=AvatarAnimator.js.map