@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.
- package/CHANGELOG.md +61 -0
- package/dist/components/AccountForm/AccountForm.d.ts +3 -2
- package/dist/components/AccountForm/AccountForm.js +2 -4
- package/dist/components/AccountForm/AccountForm.js.map +1 -1
- package/dist/components/Avatar/Avatar.d.ts +4 -0
- package/dist/components/Avatar/Avatar.js +6 -6
- package/dist/components/Avatar/Avatar.js.map +1 -1
- package/dist/components/Avatar/AvatarView/AvatarComponent/avatarComponent.d.ts +3 -0
- package/dist/components/Avatar/AvatarView/AvatarComponent/avatarComponent.js +3 -3
- package/dist/components/Avatar/AvatarView/AvatarComponent/avatarComponent.js.map +1 -1
- package/dist/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/AnimationController.js +1 -1
- package/dist/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/AnimationController.js.map +1 -1
- package/dist/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/fullbodyAvatar.d.ts +1 -1
- package/dist/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/fullbodyAvatar.js +48 -10
- package/dist/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/fullbodyAvatar.js.map +1 -1
- package/dist/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/types.d.ts +4 -1
- package/dist/components/Avatar/AvatarView/AvatarComponent/components/MorphTargetController.d.ts +17 -0
- package/dist/components/Avatar/AvatarView/AvatarComponent/components/MorphTargetController.js +73 -0
- package/dist/components/Avatar/AvatarView/AvatarComponent/components/MorphTargetController.js.map +1 -0
- package/dist/components/Avatar/AvatarView/AvatarComponent/components/PositionController.d.ts +19 -0
- package/dist/components/Avatar/AvatarView/AvatarComponent/components/PositionController.js +60 -0
- package/dist/components/Avatar/AvatarView/AvatarComponent/components/PositionController.js.map +1 -0
- package/dist/components/Avatar/AvatarView/AvatarComponent/components/constants.d.ts +18 -0
- package/dist/components/Avatar/AvatarView/AvatarComponent/components/constants.js +26 -0
- package/dist/components/Avatar/AvatarView/AvatarComponent/components/constants.js.map +1 -0
- package/dist/components/Avatar/AvatarView/AvatarComponent/components/halfbodyAvatar.d.ts +8 -7
- package/dist/components/Avatar/AvatarView/AvatarComponent/components/halfbodyAvatar.js +65 -78
- package/dist/components/Avatar/AvatarView/AvatarComponent/components/halfbodyAvatar.js.map +1 -1
- package/dist/components/Avatar/AvatarView/AvatarComponent/positionControls/positionControls.css +99 -0
- package/dist/components/Avatar/AvatarView/AvatarComponent/positionControls/positionControls.d.ts +12 -0
- package/dist/components/Avatar/AvatarView/AvatarComponent/positionControls/positionControls.js +98 -0
- package/dist/components/Avatar/AvatarView/AvatarComponent/positionControls/positionControls.js.map +1 -0
- package/dist/components/Avatar/AvatarView/index.d.ts +4 -1
- package/dist/components/Avatar/AvatarView/index.js +36 -13
- package/dist/components/Avatar/AvatarView/index.js.map +1 -1
- package/dist/components/Avatar/AvatarView/utils/hideHands.d.ts +2 -0
- package/dist/components/Avatar/AvatarView/utils/hideHands.js +14 -0
- package/dist/components/Avatar/AvatarView/utils/hideHands.js.map +1 -0
- package/dist/components/Chat/Chat.d.ts +1 -0
- package/dist/components/Chat/Chat.js +5 -2
- package/dist/components/Chat/Chat.js.map +1 -1
- package/dist/components/KnownFacts/KnownFacts.d.ts +3 -2
- package/dist/components/KnownFacts/KnownFacts.js +2 -4
- package/dist/components/KnownFacts/KnownFacts.js.map +1 -1
- package/dist/components/LoginDrawer/LoginDrawer.d.ts +3 -2
- package/dist/components/LoginDrawer/LoginDrawer.js +4 -6
- package/dist/components/LoginDrawer/LoginDrawer.js.map +1 -1
- package/dist/components/MemoriWidget/MemoriWidget.d.ts +3 -2
- package/dist/components/MemoriWidget/MemoriWidget.js +36 -10
- package/dist/components/MemoriWidget/MemoriWidget.js.map +1 -1
- package/dist/components/SettingsDrawer/SettingsDrawer.css +4 -2
- package/dist/components/SettingsDrawer/SettingsDrawer.d.ts +6 -1
- package/dist/components/SettingsDrawer/SettingsDrawer.js +10 -4
- package/dist/components/SettingsDrawer/SettingsDrawer.js.map +1 -1
- package/dist/components/SignupForm/SignupForm.d.ts +3 -2
- package/dist/components/SignupForm/SignupForm.js +2 -4
- package/dist/components/SignupForm/SignupForm.js.map +1 -1
- package/dist/components/layouts/Totem.js +1 -1
- package/dist/components/layouts/Totem.js.map +1 -1
- package/dist/components/layouts/totem.css +9 -9
- package/dist/components/ui/Button.css +4 -0
- package/dist/components/ui/Button.d.ts +1 -0
- package/dist/components/ui/Button.js +2 -1
- package/dist/components/ui/Button.js.map +1 -1
- package/dist/components/ui/Slider.css +177 -0
- package/dist/components/ui/Slider.d.ts +12 -0
- package/dist/components/ui/Slider.js +78 -0
- package/dist/components/ui/Slider.js.map +1 -0
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/dist/locales/en.json +11 -0
- package/dist/locales/it.json +11 -0
- package/dist/styles.css +1 -0
- package/esm/components/AccountForm/AccountForm.d.ts +3 -2
- package/esm/components/AccountForm/AccountForm.js +2 -4
- package/esm/components/AccountForm/AccountForm.js.map +1 -1
- package/esm/components/Avatar/Avatar.d.ts +4 -0
- package/esm/components/Avatar/Avatar.js +6 -6
- package/esm/components/Avatar/Avatar.js.map +1 -1
- package/esm/components/Avatar/AvatarView/AvatarComponent/avatarComponent.d.ts +3 -0
- package/esm/components/Avatar/AvatarView/AvatarComponent/avatarComponent.js +3 -3
- package/esm/components/Avatar/AvatarView/AvatarComponent/avatarComponent.js.map +1 -1
- package/esm/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/AnimationController.js +1 -1
- package/esm/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/AnimationController.js.map +1 -1
- package/esm/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/fullbodyAvatar.d.ts +1 -1
- package/esm/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/fullbodyAvatar.js +45 -8
- package/esm/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/fullbodyAvatar.js.map +1 -1
- package/esm/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/types.d.ts +4 -1
- package/esm/components/Avatar/AvatarView/AvatarComponent/components/MorphTargetController.d.ts +17 -0
- package/esm/components/Avatar/AvatarView/AvatarComponent/components/MorphTargetController.js +69 -0
- package/esm/components/Avatar/AvatarView/AvatarComponent/components/MorphTargetController.js.map +1 -0
- package/esm/components/Avatar/AvatarView/AvatarComponent/components/PositionController.d.ts +19 -0
- package/esm/components/Avatar/AvatarView/AvatarComponent/components/PositionController.js +56 -0
- package/esm/components/Avatar/AvatarView/AvatarComponent/components/PositionController.js.map +1 -0
- package/esm/components/Avatar/AvatarView/AvatarComponent/components/constants.d.ts +18 -0
- package/esm/components/Avatar/AvatarView/AvatarComponent/components/constants.js +23 -0
- package/esm/components/Avatar/AvatarView/AvatarComponent/components/constants.js.map +1 -0
- package/esm/components/Avatar/AvatarView/AvatarComponent/components/halfbodyAvatar.d.ts +8 -7
- package/esm/components/Avatar/AvatarView/AvatarComponent/components/halfbodyAvatar.js +66 -80
- package/esm/components/Avatar/AvatarView/AvatarComponent/components/halfbodyAvatar.js.map +1 -1
- package/esm/components/Avatar/AvatarView/AvatarComponent/positionControls/positionControls.css +99 -0
- package/esm/components/Avatar/AvatarView/AvatarComponent/positionControls/positionControls.d.ts +12 -0
- package/esm/components/Avatar/AvatarView/AvatarComponent/positionControls/positionControls.js +95 -0
- package/esm/components/Avatar/AvatarView/AvatarComponent/positionControls/positionControls.js.map +1 -0
- package/esm/components/Avatar/AvatarView/index.d.ts +4 -1
- package/esm/components/Avatar/AvatarView/index.js +38 -15
- package/esm/components/Avatar/AvatarView/index.js.map +1 -1
- package/esm/components/Avatar/AvatarView/utils/hideHands.d.ts +2 -0
- package/esm/components/Avatar/AvatarView/utils/hideHands.js +10 -0
- package/esm/components/Avatar/AvatarView/utils/hideHands.js.map +1 -0
- package/esm/components/Chat/Chat.d.ts +1 -0
- package/esm/components/Chat/Chat.js +5 -2
- package/esm/components/Chat/Chat.js.map +1 -1
- package/esm/components/KnownFacts/KnownFacts.d.ts +3 -2
- package/esm/components/KnownFacts/KnownFacts.js +2 -4
- package/esm/components/KnownFacts/KnownFacts.js.map +1 -1
- package/esm/components/LoginDrawer/LoginDrawer.d.ts +3 -2
- package/esm/components/LoginDrawer/LoginDrawer.js +4 -6
- package/esm/components/LoginDrawer/LoginDrawer.js.map +1 -1
- package/esm/components/MemoriWidget/MemoriWidget.d.ts +3 -2
- package/esm/components/MemoriWidget/MemoriWidget.js +36 -10
- package/esm/components/MemoriWidget/MemoriWidget.js.map +1 -1
- package/esm/components/SettingsDrawer/SettingsDrawer.css +4 -2
- package/esm/components/SettingsDrawer/SettingsDrawer.d.ts +6 -1
- package/esm/components/SettingsDrawer/SettingsDrawer.js +10 -4
- package/esm/components/SettingsDrawer/SettingsDrawer.js.map +1 -1
- package/esm/components/SignupForm/SignupForm.d.ts +3 -2
- package/esm/components/SignupForm/SignupForm.js +2 -4
- package/esm/components/SignupForm/SignupForm.js.map +1 -1
- package/esm/components/layouts/Totem.js +1 -1
- package/esm/components/layouts/Totem.js.map +1 -1
- package/esm/components/layouts/totem.css +9 -9
- package/esm/components/ui/Button.css +4 -0
- package/esm/components/ui/Button.d.ts +1 -0
- package/esm/components/ui/Button.js +2 -1
- package/esm/components/ui/Button.js.map +1 -1
- package/esm/components/ui/Slider.css +177 -0
- package/esm/components/ui/Slider.d.ts +12 -0
- package/esm/components/ui/Slider.js +75 -0
- package/esm/components/ui/Slider.js.map +1 -0
- package/esm/index.js +4 -1
- package/esm/index.js.map +1 -1
- package/esm/locales/en.json +11 -0
- package/esm/locales/it.json +11 -0
- package/esm/styles.css +1 -0
- package/package.json +3 -2
- package/src/components/AccountForm/AccountForm.test.tsx +2 -1
- package/src/components/AccountForm/AccountForm.tsx +3 -5
- package/src/components/Avatar/Avatar.test.tsx +8 -0
- package/src/components/Avatar/Avatar.tsx +19 -6
- package/src/components/Avatar/AvatarView/AvatarComponent/avatarComponent.tsx +17 -8
- package/src/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/AnimationController.ts +1 -1
- package/src/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/fullbodyAvatar.tsx +69 -18
- package/src/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/types.ts +4 -1
- package/src/components/Avatar/AvatarView/AvatarComponent/components/PositionController.ts +83 -0
- package/src/components/Avatar/AvatarView/AvatarComponent/components/{FullbodyAvatar/constants.ts → constants.ts} +2 -1
- package/src/components/Avatar/AvatarView/AvatarComponent/components/halfbodyAvatar.tsx +106 -124
- package/src/components/Avatar/AvatarView/AvatarComponent/positionControls/positionControls.css +99 -0
- package/src/components/Avatar/AvatarView/AvatarComponent/positionControls/positionControls.tsx +187 -0
- package/src/components/Avatar/AvatarView/index.tsx +115 -43
- package/src/components/Avatar/AvatarView/utils/hideHands.ts +11 -0
- package/src/components/Avatar/__snapshots__/Avatar.test.tsx.snap +32 -93
- package/src/components/Chat/Chat.test.tsx +11 -0
- package/src/components/Chat/Chat.tsx +8 -1
- package/src/components/KnownFacts/KnownFacts.stories.tsx +5 -4
- package/src/components/KnownFacts/KnownFacts.test.tsx +6 -3
- package/src/components/KnownFacts/KnownFacts.tsx +3 -4
- package/src/components/LoginDrawer/LoginDrawer.stories.tsx +2 -1
- package/src/components/LoginDrawer/LoginDrawer.test.tsx +9 -8
- package/src/components/LoginDrawer/LoginDrawer.tsx +5 -6
- package/src/components/MemoriWidget/MemoriWidget.tsx +56 -14
- package/src/components/SettingsDrawer/SettingsDrawer.css +4 -2
- package/src/components/SettingsDrawer/SettingsDrawer.test.tsx +24 -0
- package/src/components/SettingsDrawer/SettingsDrawer.tsx +76 -4
- package/src/components/SignupForm/SignupForm.test.tsx +3 -2
- package/src/components/SignupForm/SignupForm.tsx +3 -4
- package/src/components/layouts/Totem.tsx +1 -1
- package/src/components/layouts/layouts.stories.tsx +111 -3
- package/src/components/layouts/totem.css +9 -9
- package/src/components/ui/Button.css +4 -0
- package/src/components/ui/Button.tsx +3 -0
- package/src/components/ui/Slider.css +177 -0
- package/src/components/ui/Slider.stories.tsx +63 -0
- package/src/components/ui/Slider.tsx +142 -0
- package/src/index.stories.tsx +1 -1
- package/src/index.tsx +5 -1
- package/src/locales/en.json +11 -0
- package/src/locales/it.json +11 -0
- package/src/styles.css +1 -0
- /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: '
|
|
186
|
-
height: '
|
|
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
|
-
|
|
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 '
|
|
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
|
|
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 '
|
|
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
|
-
|
|
20
|
+
SCALE_LERP_FACTOR,
|
|
21
|
+
} from '../constants';
|
|
24
22
|
|
|
25
|
-
export
|
|
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
|
|
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
|
-
|
|
65
|
-
|
|
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
|
-
|
|
120
|
-
|
|
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(
|
|
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={
|
|
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
|
-
|
|
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',
|