Skip to content

Commit

Permalink
feat: 优化文件加载体验
Browse files Browse the repository at this point in the history
  • Loading branch information
rdmclin2 committed Sep 21, 2024
1 parent 2ac9feb commit 1d1eb76
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 10 deletions.
9 changes: 7 additions & 2 deletions locales/zh-CN/welcome.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@
}
},
"greet": "你好,我是{{name}},有什么可以帮助你的吗?",
"loadingTitle": "应用初始化中,请稍后...",
"waiting": "正在为你准备我的整个世界"
"loading": {
"waiting": "正在为你准备我的整个世界...",
"model": "正在加载模型",
"motions": "正在加载动作",
"voices": "正在加载语音"
},
"loadingTitle": "应用初始化中,请稍后..."
}
56 changes: 49 additions & 7 deletions src/features/AgentViewer/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,13 @@ function AgentViewer(props: Props) {
const playingRef = useRef(false);
const ref = useRef<HTMLDivElement>(null);
const viewer = useGlobalStore((s) => s.viewer);
const { t } = useTranslation('chat');
const { t } = useTranslation('welcome');

const { fetchModelUrl } = useLoadModel();
const { fetchModelUrl, percent: modelPercent } = useLoadModel();
const [loading, setLoading] = useState(false);
const [loadingStep, setLoadingStep] = useState(0);
const [voiceLoadingProgress, setVoiceLoadingProgress] = useState(0);
const [motionLoadingProgress, setMotionLoadingProgress] = useState(0);
const agent = useAgentStore((s) => s.getAgentById(agentId));
const getAgentTouchActionsByIdAndArea = useAgentStore((s) =>
agentSelectors.getAgentTouchActionsByIdAndArea(s),
Expand Down Expand Up @@ -81,15 +84,36 @@ function AgentViewer(props: Props) {

const preloadAgentResources = async () => {
setLoading(true);
setLoadingStep(1);
try {
// 加载模型
// 加载步骤一: 加载模型
const modelUrl = await fetchModelUrl(agent!.agentId, agent!.meta.model!);
if (!modelUrl) return;
await viewer.loadVrm(modelUrl);

// 预加载动作,目前预加载的动作都是通用的
setLoadingStep(2);
// 加载步骤二: 预加载动作,目前预加载的动作都是通用的
if (viewer?.model) {
await viewer.model.preloadAllMotions();
await viewer.model.preloadAllMotions((loaded, total) => {
setMotionLoadingProgress((loaded / total) * 100);
});
}

setLoadingStep(3);
// 加载步骤三:加载语音
let voiceCount = 0;
let totalVoices = 0;

// 计算总语音数量
if (agent?.greeting) {
totalVoices++;
}
const touchAreas = Object.values(TouchAreaEnum);
for (const area of touchAreas) {
const touchActions = getAgentTouchActionsByIdAndArea(agentId, area);
if (touchActions) {
totalVoices += touchActions.length;
}
}

// 预加载语音,根据角色的语音配置不同,需要每次重新判断预加载
Expand All @@ -99,9 +123,10 @@ function AgentViewer(props: Props) {
...agent.tts,
message: agent.greeting,
});
voiceCount++;
setVoiceLoadingProgress((voiceCount / totalVoices) * 100);
}
// 这个是角色的触摸动画语音
const touchAreas = Object.values(TouchAreaEnum);
for (const area of touchAreas) {
const touchActions = getAgentTouchActionsByIdAndArea(agentId, area);
if (touchActions) {
Expand All @@ -110,11 +135,16 @@ function AgentViewer(props: Props) {
...agent!.tts,
message: action.text,
});
voiceCount++;
setVoiceLoadingProgress((voiceCount / totalVoices) * 100);
}
}
}
} finally {
setLoading(false);
setLoadingStep(0);
setVoiceLoadingProgress(0);
setMotionLoadingProgress(0);
}
};

Expand Down Expand Up @@ -209,7 +239,19 @@ function AgentViewer(props: Props) {
>
<ToolBar className={styles.toolbar} viewer={viewer} />
{loading ? (
<ScreenLoading title={t('toolBar.downloading')} className={styles.loading} />
<ScreenLoading
title={t('loading.waiting')}
className={styles.loading}
description={
loadingStep === 1
? `${t('loading.model')} ${modelPercent}%`
: loadingStep === 2
? `${t('loading.motions')} ${Math.round(motionLoadingProgress)}%`
: loadingStep === 3
? `${t('loading.voices')} ${Math.round(voiceLoadingProgress)}%`
: undefined
}
/>
) : null}
<canvas ref={canvasRef} className={styles.canvas} id={'canvas'}></canvas>
</div>
Expand Down
6 changes: 5 additions & 1 deletion src/libs/vrmViewer/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,10 +104,14 @@ export class Model {
public async preloadMotion(motion: MotionPresetName) {
await this.emoteController?.preloadMotion(motion);
}
public async preloadAllMotions() {
public async preloadAllMotions(onLoad?: (loaded: number, total: number) => void) {
const motions = Object.values(MotionPresetName);
let loaded = 0;
const total = motions.length;
for (const motion of motions) {
await this.preloadMotion(motion);
loaded++;
onLoad?.(loaded, total);
}
}

Expand Down

0 comments on commit 1d1eb76

Please sign in to comment.