@memori.ai/memori-react 7.8.8 → 7.9.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 (190) hide show
  1. package/CHANGELOG.md +61 -0
  2. package/dist/components/AccountForm/AccountForm.d.ts +3 -2
  3. package/dist/components/AccountForm/AccountForm.js +2 -4
  4. package/dist/components/AccountForm/AccountForm.js.map +1 -1
  5. package/dist/components/Avatar/Avatar.d.ts +4 -0
  6. package/dist/components/Avatar/Avatar.js +6 -6
  7. package/dist/components/Avatar/Avatar.js.map +1 -1
  8. package/dist/components/Avatar/AvatarView/AvatarComponent/avatarComponent.d.ts +3 -0
  9. package/dist/components/Avatar/AvatarView/AvatarComponent/avatarComponent.js +3 -3
  10. package/dist/components/Avatar/AvatarView/AvatarComponent/avatarComponent.js.map +1 -1
  11. package/dist/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/AnimationController.js +1 -1
  12. package/dist/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/AnimationController.js.map +1 -1
  13. package/dist/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/fullbodyAvatar.d.ts +1 -1
  14. package/dist/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/fullbodyAvatar.js +48 -10
  15. package/dist/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/fullbodyAvatar.js.map +1 -1
  16. package/dist/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/types.d.ts +4 -1
  17. package/dist/components/Avatar/AvatarView/AvatarComponent/components/MorphTargetController.d.ts +17 -0
  18. package/dist/components/Avatar/AvatarView/AvatarComponent/components/MorphTargetController.js +73 -0
  19. package/dist/components/Avatar/AvatarView/AvatarComponent/components/MorphTargetController.js.map +1 -0
  20. package/dist/components/Avatar/AvatarView/AvatarComponent/components/PositionController.d.ts +19 -0
  21. package/dist/components/Avatar/AvatarView/AvatarComponent/components/PositionController.js +60 -0
  22. package/dist/components/Avatar/AvatarView/AvatarComponent/components/PositionController.js.map +1 -0
  23. package/dist/components/Avatar/AvatarView/AvatarComponent/components/constants.d.ts +18 -0
  24. package/dist/components/Avatar/AvatarView/AvatarComponent/components/constants.js +26 -0
  25. package/dist/components/Avatar/AvatarView/AvatarComponent/components/constants.js.map +1 -0
  26. package/dist/components/Avatar/AvatarView/AvatarComponent/components/halfbodyAvatar.d.ts +8 -7
  27. package/dist/components/Avatar/AvatarView/AvatarComponent/components/halfbodyAvatar.js +65 -78
  28. package/dist/components/Avatar/AvatarView/AvatarComponent/components/halfbodyAvatar.js.map +1 -1
  29. package/dist/components/Avatar/AvatarView/AvatarComponent/positionControls/positionControls.css +99 -0
  30. package/dist/components/Avatar/AvatarView/AvatarComponent/positionControls/positionControls.d.ts +12 -0
  31. package/dist/components/Avatar/AvatarView/AvatarComponent/positionControls/positionControls.js +98 -0
  32. package/dist/components/Avatar/AvatarView/AvatarComponent/positionControls/positionControls.js.map +1 -0
  33. package/dist/components/Avatar/AvatarView/index.d.ts +4 -1
  34. package/dist/components/Avatar/AvatarView/index.js +36 -13
  35. package/dist/components/Avatar/AvatarView/index.js.map +1 -1
  36. package/dist/components/Avatar/AvatarView/utils/hideHands.d.ts +2 -0
  37. package/dist/components/Avatar/AvatarView/utils/hideHands.js +14 -0
  38. package/dist/components/Avatar/AvatarView/utils/hideHands.js.map +1 -0
  39. package/dist/components/Chat/Chat.d.ts +1 -0
  40. package/dist/components/Chat/Chat.js +5 -2
  41. package/dist/components/Chat/Chat.js.map +1 -1
  42. package/dist/components/KnownFacts/KnownFacts.d.ts +3 -2
  43. package/dist/components/KnownFacts/KnownFacts.js +2 -4
  44. package/dist/components/KnownFacts/KnownFacts.js.map +1 -1
  45. package/dist/components/LoginDrawer/LoginDrawer.d.ts +3 -2
  46. package/dist/components/LoginDrawer/LoginDrawer.js +4 -6
  47. package/dist/components/LoginDrawer/LoginDrawer.js.map +1 -1
  48. package/dist/components/MemoriWidget/MemoriWidget.d.ts +3 -2
  49. package/dist/components/MemoriWidget/MemoriWidget.js +36 -10
  50. package/dist/components/MemoriWidget/MemoriWidget.js.map +1 -1
  51. package/dist/components/SettingsDrawer/SettingsDrawer.css +4 -2
  52. package/dist/components/SettingsDrawer/SettingsDrawer.d.ts +6 -1
  53. package/dist/components/SettingsDrawer/SettingsDrawer.js +10 -4
  54. package/dist/components/SettingsDrawer/SettingsDrawer.js.map +1 -1
  55. package/dist/components/SignupForm/SignupForm.d.ts +3 -2
  56. package/dist/components/SignupForm/SignupForm.js +2 -4
  57. package/dist/components/SignupForm/SignupForm.js.map +1 -1
  58. package/dist/components/layouts/Totem.js +1 -1
  59. package/dist/components/layouts/Totem.js.map +1 -1
  60. package/dist/components/layouts/totem.css +9 -9
  61. package/dist/components/ui/Button.css +4 -0
  62. package/dist/components/ui/Button.d.ts +1 -0
  63. package/dist/components/ui/Button.js +2 -1
  64. package/dist/components/ui/Button.js.map +1 -1
  65. package/dist/components/ui/Slider.css +177 -0
  66. package/dist/components/ui/Slider.d.ts +12 -0
  67. package/dist/components/ui/Slider.js +78 -0
  68. package/dist/components/ui/Slider.js.map +1 -0
  69. package/dist/index.js +4 -1
  70. package/dist/index.js.map +1 -1
  71. package/dist/locales/en.json +11 -0
  72. package/dist/locales/it.json +11 -0
  73. package/dist/styles.css +1 -0
  74. package/esm/components/AccountForm/AccountForm.d.ts +3 -2
  75. package/esm/components/AccountForm/AccountForm.js +2 -4
  76. package/esm/components/AccountForm/AccountForm.js.map +1 -1
  77. package/esm/components/Avatar/Avatar.d.ts +4 -0
  78. package/esm/components/Avatar/Avatar.js +6 -6
  79. package/esm/components/Avatar/Avatar.js.map +1 -1
  80. package/esm/components/Avatar/AvatarView/AvatarComponent/avatarComponent.d.ts +3 -0
  81. package/esm/components/Avatar/AvatarView/AvatarComponent/avatarComponent.js +3 -3
  82. package/esm/components/Avatar/AvatarView/AvatarComponent/avatarComponent.js.map +1 -1
  83. package/esm/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/AnimationController.js +1 -1
  84. package/esm/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/AnimationController.js.map +1 -1
  85. package/esm/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/fullbodyAvatar.d.ts +1 -1
  86. package/esm/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/fullbodyAvatar.js +45 -8
  87. package/esm/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/fullbodyAvatar.js.map +1 -1
  88. package/esm/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/types.d.ts +4 -1
  89. package/esm/components/Avatar/AvatarView/AvatarComponent/components/MorphTargetController.d.ts +17 -0
  90. package/esm/components/Avatar/AvatarView/AvatarComponent/components/MorphTargetController.js +69 -0
  91. package/esm/components/Avatar/AvatarView/AvatarComponent/components/MorphTargetController.js.map +1 -0
  92. package/esm/components/Avatar/AvatarView/AvatarComponent/components/PositionController.d.ts +19 -0
  93. package/esm/components/Avatar/AvatarView/AvatarComponent/components/PositionController.js +56 -0
  94. package/esm/components/Avatar/AvatarView/AvatarComponent/components/PositionController.js.map +1 -0
  95. package/esm/components/Avatar/AvatarView/AvatarComponent/components/constants.d.ts +18 -0
  96. package/esm/components/Avatar/AvatarView/AvatarComponent/components/constants.js +23 -0
  97. package/esm/components/Avatar/AvatarView/AvatarComponent/components/constants.js.map +1 -0
  98. package/esm/components/Avatar/AvatarView/AvatarComponent/components/halfbodyAvatar.d.ts +8 -7
  99. package/esm/components/Avatar/AvatarView/AvatarComponent/components/halfbodyAvatar.js +66 -80
  100. package/esm/components/Avatar/AvatarView/AvatarComponent/components/halfbodyAvatar.js.map +1 -1
  101. package/esm/components/Avatar/AvatarView/AvatarComponent/positionControls/positionControls.css +99 -0
  102. package/esm/components/Avatar/AvatarView/AvatarComponent/positionControls/positionControls.d.ts +12 -0
  103. package/esm/components/Avatar/AvatarView/AvatarComponent/positionControls/positionControls.js +95 -0
  104. package/esm/components/Avatar/AvatarView/AvatarComponent/positionControls/positionControls.js.map +1 -0
  105. package/esm/components/Avatar/AvatarView/index.d.ts +4 -1
  106. package/esm/components/Avatar/AvatarView/index.js +38 -15
  107. package/esm/components/Avatar/AvatarView/index.js.map +1 -1
  108. package/esm/components/Avatar/AvatarView/utils/hideHands.d.ts +2 -0
  109. package/esm/components/Avatar/AvatarView/utils/hideHands.js +10 -0
  110. package/esm/components/Avatar/AvatarView/utils/hideHands.js.map +1 -0
  111. package/esm/components/Chat/Chat.d.ts +1 -0
  112. package/esm/components/Chat/Chat.js +5 -2
  113. package/esm/components/Chat/Chat.js.map +1 -1
  114. package/esm/components/KnownFacts/KnownFacts.d.ts +3 -2
  115. package/esm/components/KnownFacts/KnownFacts.js +2 -4
  116. package/esm/components/KnownFacts/KnownFacts.js.map +1 -1
  117. package/esm/components/LoginDrawer/LoginDrawer.d.ts +3 -2
  118. package/esm/components/LoginDrawer/LoginDrawer.js +4 -6
  119. package/esm/components/LoginDrawer/LoginDrawer.js.map +1 -1
  120. package/esm/components/MemoriWidget/MemoriWidget.d.ts +3 -2
  121. package/esm/components/MemoriWidget/MemoriWidget.js +36 -10
  122. package/esm/components/MemoriWidget/MemoriWidget.js.map +1 -1
  123. package/esm/components/SettingsDrawer/SettingsDrawer.css +4 -2
  124. package/esm/components/SettingsDrawer/SettingsDrawer.d.ts +6 -1
  125. package/esm/components/SettingsDrawer/SettingsDrawer.js +10 -4
  126. package/esm/components/SettingsDrawer/SettingsDrawer.js.map +1 -1
  127. package/esm/components/SignupForm/SignupForm.d.ts +3 -2
  128. package/esm/components/SignupForm/SignupForm.js +2 -4
  129. package/esm/components/SignupForm/SignupForm.js.map +1 -1
  130. package/esm/components/layouts/Totem.js +1 -1
  131. package/esm/components/layouts/Totem.js.map +1 -1
  132. package/esm/components/layouts/totem.css +9 -9
  133. package/esm/components/ui/Button.css +4 -0
  134. package/esm/components/ui/Button.d.ts +1 -0
  135. package/esm/components/ui/Button.js +2 -1
  136. package/esm/components/ui/Button.js.map +1 -1
  137. package/esm/components/ui/Slider.css +177 -0
  138. package/esm/components/ui/Slider.d.ts +12 -0
  139. package/esm/components/ui/Slider.js +75 -0
  140. package/esm/components/ui/Slider.js.map +1 -0
  141. package/esm/index.js +4 -1
  142. package/esm/index.js.map +1 -1
  143. package/esm/locales/en.json +11 -0
  144. package/esm/locales/it.json +11 -0
  145. package/esm/styles.css +1 -0
  146. package/package.json +3 -2
  147. package/src/components/AccountForm/AccountForm.test.tsx +2 -1
  148. package/src/components/AccountForm/AccountForm.tsx +3 -5
  149. package/src/components/Avatar/Avatar.test.tsx +8 -0
  150. package/src/components/Avatar/Avatar.tsx +19 -6
  151. package/src/components/Avatar/AvatarView/AvatarComponent/avatarComponent.tsx +17 -8
  152. package/src/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/AnimationController.ts +1 -1
  153. package/src/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/fullbodyAvatar.tsx +69 -18
  154. package/src/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/types.ts +4 -1
  155. package/src/components/Avatar/AvatarView/AvatarComponent/components/PositionController.ts +83 -0
  156. package/src/components/Avatar/AvatarView/AvatarComponent/components/{FullbodyAvatar/constants.ts → constants.ts} +2 -1
  157. package/src/components/Avatar/AvatarView/AvatarComponent/components/halfbodyAvatar.tsx +106 -124
  158. package/src/components/Avatar/AvatarView/AvatarComponent/positionControls/positionControls.css +99 -0
  159. package/src/components/Avatar/AvatarView/AvatarComponent/positionControls/positionControls.tsx +187 -0
  160. package/src/components/Avatar/AvatarView/index.tsx +115 -43
  161. package/src/components/Avatar/AvatarView/utils/hideHands.ts +11 -0
  162. package/src/components/Avatar/__snapshots__/Avatar.test.tsx.snap +32 -93
  163. package/src/components/Chat/Chat.test.tsx +11 -0
  164. package/src/components/Chat/Chat.tsx +8 -1
  165. package/src/components/KnownFacts/KnownFacts.stories.tsx +5 -4
  166. package/src/components/KnownFacts/KnownFacts.test.tsx +6 -3
  167. package/src/components/KnownFacts/KnownFacts.tsx +3 -4
  168. package/src/components/LoginDrawer/LoginDrawer.stories.tsx +2 -1
  169. package/src/components/LoginDrawer/LoginDrawer.test.tsx +9 -8
  170. package/src/components/LoginDrawer/LoginDrawer.tsx +5 -6
  171. package/src/components/MemoriWidget/MemoriWidget.tsx +56 -14
  172. package/src/components/SettingsDrawer/SettingsDrawer.css +4 -2
  173. package/src/components/SettingsDrawer/SettingsDrawer.test.tsx +24 -0
  174. package/src/components/SettingsDrawer/SettingsDrawer.tsx +76 -4
  175. package/src/components/SignupForm/SignupForm.test.tsx +3 -2
  176. package/src/components/SignupForm/SignupForm.tsx +3 -4
  177. package/src/components/layouts/Totem.tsx +1 -1
  178. package/src/components/layouts/layouts.stories.tsx +111 -3
  179. package/src/components/layouts/totem.css +9 -9
  180. package/src/components/ui/Button.css +4 -0
  181. package/src/components/ui/Button.tsx +3 -0
  182. package/src/components/ui/Slider.css +177 -0
  183. package/src/components/ui/Slider.stories.tsx +63 -0
  184. package/src/components/ui/Slider.tsx +142 -0
  185. package/src/index.stories.tsx +1 -1
  186. package/src/index.tsx +5 -1
  187. package/src/locales/en.json +11 -0
  188. package/src/locales/it.json +11 -0
  189. package/src/styles.css +1 -0
  190. /package/src/components/Avatar/AvatarView/AvatarComponent/components/{FullbodyAvatar/MorhTargetController.ts → MorphTargetController.ts} +0 -0
@@ -17,6 +17,8 @@ import Edit from '../icons/Edit';
17
17
  import cx from 'classnames';
18
18
  import ContainerAvatarView from './AvatarView';
19
19
  import { useViseme } from '../../context/visemeContext';
20
+ import PositionControls from './AvatarView/AvatarComponent/positionControls/positionControls';
21
+ import { getLocalConfig } from '../../helpers/configuration';
20
22
 
21
23
  export interface Props {
22
24
  memori: Memori;
@@ -34,6 +36,10 @@ export interface Props {
34
36
  animation?: string;
35
37
  isZoomed?: boolean;
36
38
  chatProps?: any;
39
+ enablePositionControls?: boolean;
40
+ setEnablePositionControls: (value: boolean) => void;
41
+ avatarType?: 'blob' | 'avatar3d' | null;
42
+ isTotem?: boolean;
37
43
  }
38
44
 
39
45
  const Avatar: React.FC<Props> = ({
@@ -52,6 +58,10 @@ const Avatar: React.FC<Props> = ({
52
58
  animation,
53
59
  isZoomed = false,
54
60
  chatProps,
61
+ avatarType = null,
62
+ enablePositionControls,
63
+ setEnablePositionControls,
64
+ isTotem = false,
55
65
  }) => {
56
66
  const { t } = useTranslation();
57
67
  const [isClient, setIsClient] = useState(false);
@@ -86,7 +96,8 @@ const Avatar: React.FC<Props> = ({
86
96
  integrationConfig?.avatar === 'readyplayerme-full' ||
87
97
  integrationConfig?.avatar === 'customglb' ||
88
98
  integrationConfig?.avatar === 'customrpm') &&
89
- integrationConfig?.avatarURL
99
+ integrationConfig?.avatarURL &&
100
+ (avatarType && avatarType !== 'blob')
90
101
  ) {
91
102
  return (
92
103
  <>
@@ -114,11 +125,10 @@ const Avatar: React.FC<Props> = ({
114
125
 
115
126
  const renderAvatarContent = () => {
116
127
  if (!isClient) return null;
117
-
118
128
  if (
119
129
  integrationConfig?.avatar === 'readyplayerme' ||
120
130
  integrationConfig?.avatar === 'readyplayerme-full' ||
121
- integrationConfig?.avatar === 'customrpm'
131
+ integrationConfig?.avatar === 'customrpm'
122
132
  ) {
123
133
  return (
124
134
  <ErrorBoundary
@@ -131,6 +141,7 @@ const Avatar: React.FC<Props> = ({
131
141
  }
132
142
  >
133
143
  <ContainerAvatarView
144
+ enablePositionControls={enablePositionControls}
134
145
  updateCurrentViseme={updateCurrentViseme}
135
146
  url={integrationConfig.avatarURL}
136
147
  sex={memori.voiceType === 'FEMALE' ? 'FEMALE' : 'MALE'}
@@ -145,7 +156,9 @@ const Avatar: React.FC<Props> = ({
145
156
  stopProcessing={stopProcessing}
146
157
  resetVisemeQueue={resetVisemeQueue}
147
158
  isZoomed={isZoomed}
159
+ isTotem={isTotem}
148
160
  chatEmission={chatProps?.dialogState?.emission}
161
+ setEnablePositionControls={setEnablePositionControls}
149
162
  />
150
163
  </ErrorBoundary>
151
164
  );
@@ -182,10 +195,10 @@ const Avatar: React.FC<Props> = ({
182
195
  const getAvatarStyle = () => {
183
196
  if (integrationConfig?.avatar === 'readyplayerme') {
184
197
  return {
185
- width: '300px',
186
- height: '300px',
198
+ width: '100%',
199
+ height: '100%',
187
200
  backgroundColor: 'none',
188
- borderRadius: '100%',
201
+ // borderRadius: '100%',
189
202
  boxShadow: 'none',
190
203
  };
191
204
  }
@@ -1,6 +1,6 @@
1
1
  import React, { useState, useEffect, useCallback } from 'react';
2
2
  import AnimationControlPanel from './components/controls';
3
- import FullbodyAvatar from './components/FullbodyAvatar/fullbodyAvatar';
3
+ import { FullbodyAvatar } from './components/FullbodyAvatar/fullbodyAvatar'
4
4
  import HalfBodyAvatar from './components/halfbodyAvatar';
5
5
 
6
6
  interface Props {
@@ -14,11 +14,14 @@ interface Props {
14
14
  speaking: boolean;
15
15
  isZoomed: boolean;
16
16
  chatEmission: any;
17
+ avatarHeight?: number;
18
+ avatarDepth?: number;
17
19
  stopProcessing: () => void;
18
20
  resetVisemeQueue: () => void;
19
21
  updateCurrentViseme: (
20
22
  currentTime: number
21
23
  ) => { name: string; weight: number } | null;
24
+ setCameraZ: (value: number) => void;
22
25
  }
23
26
 
24
27
  interface BaseAction {
@@ -61,12 +64,15 @@ export const AvatarView: React.FC<Props & { halfBody: boolean }> = ({
61
64
  sex,
62
65
  eyeBlink,
63
66
  headMovement,
64
- speaking,
67
+ // speaking,
65
68
  halfBody,
66
69
  loading,
67
- isZoomed,
70
+ // isZoomed,
71
+ avatarHeight,
72
+ avatarDepth,
68
73
  updateCurrentViseme,
69
74
  resetVisemeQueue,
75
+ setCameraZ,
70
76
  }) => {
71
77
  const [currentBaseAction, setCurrentBaseAction] = useState({
72
78
  action: animation || 'Idle1',
@@ -207,13 +213,13 @@ export const AvatarView: React.FC<Props & { halfBody: boolean }> = ({
207
213
  {halfBody ? (
208
214
  <HalfBodyAvatar
209
215
  url={url}
210
- headMovement={headMovement}
211
- speaking={speaking}
212
- eyeBlink={eyeBlink}
213
- morphTargetInfluences={morphTargetInfluences}
216
+ onCameraZChange={setCameraZ}
214
217
  setMorphTargetInfluences={setMorphTargetInfluences}
215
218
  setMorphTargetDictionary={setMorphTargetDictionary}
216
219
  updateCurrentViseme={updateCurrentViseme}
220
+ avatarHeight={avatarHeight || 50}
221
+ avatarDepth={avatarDepth || -50}
222
+ headMovement={headMovement}
217
223
  />
218
224
  ) : (
219
225
  <FullbodyAvatar
@@ -224,12 +230,15 @@ export const AvatarView: React.FC<Props & { halfBody: boolean }> = ({
224
230
  currentBaseAction={currentBaseAction}
225
231
  timeScale={timeScale}
226
232
  morphTargetInfluences={morphTargetInfluences}
227
- isZoomed={isZoomed}
228
233
  updateCurrentViseme={updateCurrentViseme}
229
234
  stopProcessing={stopProcessing}
230
235
  setMorphTargetDictionary={setMorphTargetDictionary}
231
236
  setMorphTargetInfluences={setMorphTargetInfluences}
232
237
  emotionMorphTargets={emotionMorphTargets}
238
+ halfBody={halfBody}
239
+ onCameraZChange={setCameraZ}
240
+ avatarHeight={avatarHeight || 50}
241
+ avatarDepth={avatarDepth || -50}
233
242
  />
234
243
  )}
235
244
  </>
@@ -1,6 +1,6 @@
1
1
  import { AnimationState, AnimationConfig } from './types';
2
2
  import { AnimationAction, AnimationMixer, LoopOnce } from 'three';
3
- import { DEFAULT_CONFIG } from './constants';
3
+ import { DEFAULT_CONFIG } from '../constants';
4
4
 
5
5
  /**
6
6
  * Controller class for managing avatar animations and transitions between states
@@ -1,38 +1,38 @@
1
- import React, { useEffect, useRef, useMemo, useCallback } from 'react';
1
+ import { useEffect, useRef, useMemo } from 'react';
2
2
  import {
3
- Vector3,
4
- Euler,
5
3
  AnimationMixer,
6
4
  SkinnedMesh,
7
5
  Object3D,
8
- MathUtils,
9
6
  AnimationAction,
10
- LoopOnce,
11
7
  } from 'three';
12
8
  import { useAnimations, useGLTF } from '@react-three/drei';
13
9
  import { useFrame } from '@react-three/fiber';
14
10
  import { AnimationState, FullbodyAvatarProps } from './types';
15
11
  import { AnimationController } from './AnimationController';
16
- import { MorphTargetController } from './MorhTargetController';
12
+ import { MorphTargetController } from '../MorphTargetController';
13
+ import { AvatarPositionController } from '../PositionController';
17
14
  import {
18
15
  AVATAR_POSITION,
19
16
  AVATAR_ROTATION,
20
17
  AVATAR_POSITION_ZOOMED,
21
18
  ANIMATION_URLS,
22
19
  DEFAULT_CONFIG,
23
- } from './constants';
20
+ SCALE_LERP_FACTOR,
21
+ } from '../constants';
24
22
 
25
- export default function FullbodyAvatar({
23
+ export function FullbodyAvatar({
26
24
  url,
27
25
  sex,
28
26
  currentBaseAction,
29
27
  timeScale,
30
- isZoomed,
31
28
  eyeBlink,
32
29
  updateCurrentViseme,
33
30
  setMorphTargetDictionary,
34
31
  setMorphTargetInfluences,
35
32
  emotionMorphTargets,
33
+ avatarHeight = 50,
34
+ avatarDepth = 0,
35
+ onCameraZChange,
36
36
  }: FullbodyAvatarProps) {
37
37
  const { scene } = useGLTF(url);
38
38
  const { animations } = useGLTF(ANIMATION_URLS[sex]);
@@ -40,6 +40,8 @@ export default function FullbodyAvatar({
40
40
 
41
41
  const animationControllerRef = useRef<AnimationController>();
42
42
  const morphTargetControllerRef = useRef<MorphTargetController>();
43
+ const positionControllerRef = useRef<AvatarPositionController>();
44
+
43
45
  const blinkStateRef = useRef({
44
46
  isBlinking: false,
45
47
  lastBlinkTime: 0,
@@ -47,10 +49,49 @@ export default function FullbodyAvatar({
47
49
  blinkStartTime: 0,
48
50
  });
49
51
 
52
+ // Initialize controllers
53
+ useEffect(() => {
54
+ if (!positionControllerRef.current) {
55
+ positionControllerRef.current = new AvatarPositionController(AVATAR_POSITION);
56
+ }
57
+
58
+ if (!actions || !scene) return;
59
+
60
+ const mixer = new AnimationMixer(scene);
61
+ animationControllerRef.current = new AnimationController(
62
+ mixer,
63
+ actions as Record<string, AnimationAction>,
64
+ { ...DEFAULT_CONFIG }
65
+ );
66
+
67
+ if (headMesh) {
68
+ morphTargetControllerRef.current = new MorphTargetController(headMesh);
69
+
70
+ if (headMesh.morphTargetDictionary && headMesh.morphTargetInfluences) {
71
+ setMorphTargetDictionary(headMesh.morphTargetDictionary);
72
+ const initialInfluences = Object.keys(headMesh.morphTargetDictionary)
73
+ .reduce((acc, key) => ({ ...acc, [key]: 0 }), {});
74
+ setMorphTargetInfluences(initialInfluences);
75
+ }
76
+ }
77
+ }, [actions, scene]);
78
+ useEffect(() => {
79
+ if (positionControllerRef.current) {
80
+ positionControllerRef.current.updateHeight(avatarHeight, false);
81
+ }
82
+ }, [avatarHeight]);
83
+
84
+ useEffect(() => {
85
+ if (positionControllerRef.current && onCameraZChange) {
86
+ const newCameraZ = positionControllerRef.current.updateDepth(avatarDepth, false);
87
+ onCameraZChange(newCameraZ);
88
+ }
89
+ }, [avatarDepth, onCameraZChange]);
90
+
50
91
  // Find head mesh
51
92
  const headMesh = useMemo(() => {
52
93
  let foundMesh: SkinnedMesh | undefined;
53
- scene.traverse((object: Object3D) => {
94
+ scene?.traverse((object: Object3D) => {
54
95
  if (
55
96
  object instanceof SkinnedMesh &&
56
97
  (object.name === 'GBNL__Head' || object.name === 'Wolf3D_Avatar')
@@ -61,8 +102,8 @@ export default function FullbodyAvatar({
61
102
  return foundMesh;
62
103
  }, [scene]);
63
104
 
64
- // Initialize controllers
65
- useEffect(() => {
105
+ // Initialize controllers
106
+ useEffect(() => {
66
107
  if (!actions || !headMesh) return;
67
108
 
68
109
  const mixer = new AnimationMixer(scene);
@@ -96,6 +137,7 @@ export default function FullbodyAvatar({
96
137
  if (!animationControllerRef.current) return;
97
138
 
98
139
  if (currentBaseAction.action.startsWith('Loading')) {
140
+ animationControllerRef.current.updateIsChatAlreadyStarted(true);
99
141
  animationControllerRef.current.transitionTo(
100
142
  AnimationState.LOADING,
101
143
  currentBaseAction.action
@@ -103,7 +145,6 @@ export default function FullbodyAvatar({
103
145
  } else if (currentBaseAction.action.startsWith('Idle')) {
104
146
  animationControllerRef.current.transitionTo(AnimationState.IDLE);
105
147
  } else {
106
- animationControllerRef.current.updateIsChatAlreadyStarted(true);
107
148
  animationControllerRef.current.transitionTo(
108
149
  AnimationState.EMOTION,
109
150
  currentBaseAction.action
@@ -116,12 +157,13 @@ export default function FullbodyAvatar({
116
157
  animationControllerRef.current?.setTimeScale(timeScale);
117
158
  }, [timeScale]);
118
159
 
119
- // Animation update loop
120
- useFrame(state => {
160
+
161
+ // Animation and scaling update loop
162
+ useFrame((state, delta) => {
121
163
  const currentTime = state.clock.elapsedTime * 1000;
122
164
 
123
165
  // Update animations
124
- animationControllerRef.current?.update(state.clock.getDelta());
166
+ animationControllerRef.current?.update(delta);
125
167
 
126
168
  // Update morph targets
127
169
  if (morphTargetControllerRef.current) {
@@ -134,14 +176,23 @@ export default function FullbodyAvatar({
134
176
  blinkStateRef.current
135
177
  );
136
178
  }
179
+
180
+ // Update scale with smooth transition
181
+ if (scene && positionControllerRef.current) {
182
+ const newScale = positionControllerRef.current.updateScale(SCALE_LERP_FACTOR);
183
+ scene.scale.copy(newScale);
184
+ }
137
185
  });
138
186
 
187
+ // Get current position from controller
188
+ const position = positionControllerRef.current?.getPosition() || AVATAR_POSITION;
189
+
139
190
  return (
140
191
  <group
141
- position={isZoomed ? AVATAR_POSITION_ZOOMED : AVATAR_POSITION}
192
+ position={position}
142
193
  rotation={AVATAR_ROTATION}
143
194
  >
144
195
  <primitive object={scene} />
145
196
  </group>
146
197
  );
147
- }
198
+ }
@@ -20,8 +20,10 @@ export interface FullbodyAvatarProps {
20
20
  weight: number;
21
21
  };
22
22
  timeScale: number;
23
- isZoomed?: boolean;
23
+ onCameraZChange: (value: number) => void;
24
24
  eyeBlink?: boolean;
25
+ avatarDepth?: number;
26
+ avatarHeight?: number;
25
27
  stopProcessing: () => void;
26
28
  resetVisemeQueue: () => void;
27
29
  updateCurrentViseme: (
@@ -37,4 +39,5 @@ export interface FullbodyAvatarProps {
37
39
  morphTargetInfluences: Record<string, number>
38
40
  ) => void;
39
41
  emotionMorphTargets: Record<string, number>;
42
+ halfBody: boolean;
40
43
  }
@@ -0,0 +1,83 @@
1
+ import { Vector3, MathUtils } from 'three';
2
+ import { AVATAR_POSITION, AVATAR_POSITION_ZOOMED } from './constants';
3
+
4
+ export class AvatarPositionController {
5
+ private currentScale: Vector3;
6
+ private targetScale: Vector3;
7
+ private currentPosition: Vector3;
8
+ private basePosition: Vector3;
9
+ private defaultPosition: Vector3;
10
+ private zoomedPosition: Vector3;
11
+ private initialCameraPosition: Vector3;
12
+
13
+ constructor(
14
+ defaultPosition: Vector3 = AVATAR_POSITION.clone(),
15
+ zoomedPosition: Vector3 = AVATAR_POSITION_ZOOMED.clone(),
16
+ initialCameraZ: number = 0.6
17
+ ) {
18
+ this.defaultPosition = defaultPosition;
19
+ this.zoomedPosition = zoomedPosition;
20
+ this.currentScale = new Vector3(1, 1, 1);
21
+ this.targetScale = new Vector3(1, 1, 1);
22
+ this.currentPosition = defaultPosition.clone();
23
+ this.basePosition = defaultPosition.clone();
24
+ this.initialCameraPosition = new Vector3(0, 0, initialCameraZ);
25
+ }
26
+
27
+ // Map height slider value (0 to 100) to scale (0.8 to 1.2)
28
+ private mapHeightToScale(sliderValue: number, isHalfBody: boolean): number {
29
+ // Convert slider value to scale factor
30
+ if (isHalfBody) {
31
+ return MathUtils.lerp(1.4, 2.1, sliderValue / 100);
32
+ } else {
33
+ return MathUtils.lerp(0.5, 1.5, sliderValue / 100);
34
+ }
35
+ }
36
+
37
+ // Map depth slider value (0 to 100) to camera Z position
38
+ private mapDepthToCamera(depthValue: number, isHalfBody: boolean): number {
39
+ const baseZ = this.initialCameraPosition.z;
40
+ if (isHalfBody) {
41
+ return MathUtils.lerp(baseZ, baseZ + 3, depthValue / 100);
42
+ } else {
43
+ return MathUtils.lerp(baseZ, baseZ + 3, depthValue / 100);
44
+ }
45
+ }
46
+
47
+ // Update height from GUI control (0-100)
48
+ updateHeight(heightValue: number, isHalfBody: boolean): void {
49
+ const heightScale = this.mapHeightToScale(heightValue, isHalfBody);
50
+ this.targetScale.set(heightScale, heightScale, heightScale);
51
+ }
52
+
53
+ // Update depth and return new camera Z position
54
+ updateDepth(depthValue: number, isHalfBody: boolean): number {
55
+ return this.mapDepthToCamera(depthValue, isHalfBody);
56
+ }
57
+
58
+ // Update base position for zooming
59
+ updateBasePosition(isZoomed: boolean): void {
60
+ const newPosition = isZoomed ? this.zoomedPosition : this.defaultPosition;
61
+ this.basePosition.copy(newPosition);
62
+ this.currentPosition.copy(newPosition);
63
+ }
64
+
65
+ // Smoothly interpolate current scale to target scale
66
+ updateScale(lerpFactor: number): Vector3 {
67
+ this.currentScale.lerp(this.targetScale, lerpFactor);
68
+ return this.currentScale;
69
+ }
70
+
71
+ // Get current position
72
+ getPosition(): Vector3 {
73
+ return this.currentPosition;
74
+ }
75
+
76
+ // Reset to default values
77
+ reset(): void {
78
+ this.currentScale.set(1, 1, 1);
79
+ this.targetScale.set(1, 1, 1);
80
+ this.currentPosition.copy(this.defaultPosition);
81
+ this.basePosition.copy(this.defaultPosition);
82
+ }
83
+ }
@@ -1,9 +1,10 @@
1
1
  import { Vector3, Euler } from 'three';
2
- import { AnimationConfig } from './types';
2
+ import { AnimationConfig } from './FullbodyAvatar/types';
3
3
 
4
4
  export const AVATAR_POSITION = new Vector3(0, -1, 0);
5
5
  export const AVATAR_ROTATION = new Euler(0.175, 0, 0);
6
6
  export const AVATAR_POSITION_ZOOMED = new Vector3(0, -1.45, 0);
7
+ export const SCALE_LERP_FACTOR = 0.1;
7
8
 
8
9
  export const ANIMATION_URLS = {
9
10
  MALE: 'https://assets.memori.ai/api/v2/asset/2c5e88a4-cf62-408b-9ef0-518b099dfcb2.glb',