Skip to content

Commit

Permalink
✨ feat: dance 文件统一使用 blob
Browse files Browse the repository at this point in the history
  • Loading branch information
rdmclin2 committed Aug 4, 2024
1 parent 7ecc313 commit 11d55af
Show file tree
Hide file tree
Showing 8 changed files with 43 additions and 32 deletions.
10 changes: 5 additions & 5 deletions src/features/DanceList/Item/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,22 +42,22 @@ const DanceItem = (props: DanceItemProps) => {
const { t } = useTranslation('common');

const { downloading: audioDownloading, percent: audioPercent, fetchAudioUrl } = useLoadAudio();
const { downloading: danceDownloading, percent: dancePercent, fetchDanceBuffer } = useLoadDance();
const { downloading: danceDownloading, percent: dancePercent, fetchDanceUrl } = useLoadDance();
const viewer = useGlobalStore((s) => s.viewer);

const handlePlayPause = () => {
viewer.model?.resetToIdle();
viewer.model?.disposeAll();
if (isPlaying && isCurrentPlay) {
setIsPlaying(false);
} else {
setCurrentPlayId(danceItem.danceId);
setIsPlaying(true);
const audioPromise = fetchAudioUrl(danceItem.danceId, danceItem.audio);
const dancePromise = fetchDanceBuffer(danceItem.danceId, danceItem.src);
const dancePromise = fetchDanceUrl(danceItem.danceId, danceItem.src);
Promise.all([dancePromise, audioPromise]).then((res) => {
if (!res) return;
const [danceBuffer, audioUrl] = res;
viewer.model?.dance(danceBuffer, audioUrl);
const [danceUrl, audioUrl] = res;
if (danceUrl && audioUrl) viewer.model?.dance(danceUrl, audioUrl);
});
}
};
Expand Down
4 changes: 2 additions & 2 deletions src/features/MotionList/ActionList/ListItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,8 @@ const TouchActionListItem = memo<ActionListItemProps>(({ item }) => {
showAction={true}
onClick={async () => {
if (item.url) {
const url = await fetchMotionUrl(item.id, item.url);
viewer.model?.loadFBX(url);
const motionUrl = await fetchMotionUrl(item.id, item.url);
if (motionUrl) viewer.model?.loadFBX(motionUrl);
}
}}
title={item.name}
Expand Down
4 changes: 2 additions & 2 deletions src/features/PostureList/ActionList/ListItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,8 @@ const TouchActionListItem = memo<ActionListItemProps>(({ item }) => {
showAction={true}
onClick={async () => {
if (item.url) {
const url = await fetchMotionUrl(item.id, item.url);
viewer.model?.loadFBX(url);
const motionUrl = await fetchMotionUrl(item.id, item.url);
if (motionUrl) viewer.model?.loadFBX(motionUrl);
}
}}
title={item.name}
Expand Down
2 changes: 2 additions & 0 deletions src/hooks/useLoadAudio.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ export const useLoadAudio = () => {
} finally {
setDownloading(false);
}
if (!audioBlob) return null;

return URL.createObjectURL(audioBlob);
};

Expand Down
26 changes: 18 additions & 8 deletions src/hooks/useLoadDance.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { isArrayBuffer } from 'lodash-es';
import { useState } from 'react';

import { fetchWithProgress } from '@/utils/fetch';
Expand All @@ -8,31 +9,40 @@ export const useLoadDance = () => {
const [downloading, setDownloading] = useState(false);
const [percent, setPercent] = useState(0);

const fetchDanceBuffer = async (danceId: string, src: string) => {
const fetchDanceUrl = async (danceId: string, src: string) => {
const localDancePath = getDancePathByDanceId(danceId);
let danceBuffer = (await storage.getItem(localDancePath)) as ArrayBuffer;
let danceBlob = await storage.getItem(localDancePath);

// 存量转换
if (danceBlob && isArrayBuffer(danceBlob)) {
// 如果存的是 ArrayBuffer,设置为空重新下载;
danceBlob = null;
}

try {
if (!danceBuffer) {
if (!danceBlob) {
setDownloading(true);
setPercent(0);

danceBuffer = await fetchWithProgress(src, {
danceBlob = await fetchWithProgress(src, {
onProgress: (loaded, total) => {
setPercent((loaded / total) * 100);
},
}).then((res) => res.arrayBuffer());
await storage.setItem(localDancePath, danceBuffer);
});
await storage.setItem(localDancePath, danceBlob);
}
} finally {
setDownloading(false);
}
return danceBuffer;

if (!danceBlob) return null;

return URL.createObjectURL(danceBlob);
};

return {
downloading,
percent,
fetchDanceBuffer,
fetchDanceUrl,
};
};
10 changes: 5 additions & 5 deletions src/hooks/useLoadModel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,20 @@ export const useLoadModel = () => {
if (!modelBlob) {
setDownloading(true);
setPercent(0);
const blob = await fetchWithProgress(remoteModelUrl, {
modelBlob = await fetchWithProgress(remoteModelUrl, {
onProgress: (loaded, total) => {
setPercent(Math.ceil((loaded / total) * 100));
},
});
const modelPath = getModelPathByAgentId(agentId);
await storage.setItem(modelPath, blob);
await storage.setItem(modelPath, modelBlob);
}
} catch (e) {
console.error(e);
return null;
} finally {
setDownloading(false);
}

if (!modelBlob) return null;

return URL.createObjectURL(modelBlob);
};

Expand Down
6 changes: 5 additions & 1 deletion src/hooks/useLoadMotion.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ export const useLoadMotion = () => {

const fetchMotionUrl = async (motionId: string, motionUrl: string) => {
const localMotionPath = getMotionPathByMotionId(motionId);
let motionBlob = (await storage.getItem(localMotionPath)) as Blob;
let motionBlob = await storage.getItem(localMotionPath);

try {
if (!motionBlob) {
setDownloading(true);
Expand All @@ -26,6 +27,9 @@ export const useLoadMotion = () => {
} finally {
setDownloading(false);
}

if (!motionBlob) return null;

return URL.createObjectURL(motionBlob);
};

Expand Down
13 changes: 4 additions & 9 deletions src/libs/vrmViewer/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -156,17 +156,15 @@ export class Model {
/**
* 播放舞蹈,以音乐文件的播放作为结束标志。
*/
public async dance(dance: ArrayBuffer, audioUrl: string, onEnd?: () => void) {
public async dance(danceUrl: string, audioUrl: string, onEnd?: () => void) {
const { vrm, mixer } = this;
if (vrm && mixer) {
this.disposeAll();
const animation = convert(dance, toOffset(vrm));
const clip = bindToVRM(animation, vrm);
const clip = await loadVMDAnimation(danceUrl, vrm);
const action = mixer.clipAction(clip);
action.setLoop(LoopOnce, 1).play(); // play animation
if (audioUrl) {
this._audioPlayer?.playFromURL(audioUrl, () => {
this.resetToIdle();
onEnd?.();
});
this._audio = audioUrl;
Expand All @@ -178,12 +176,9 @@ export class Model {
}

public async resetToIdle() {
const { vrm, mixer } = this;
if (vrm && mixer) {
this.disposeAll();
this.disposeAll();

await this.loadIdleAnimation();
}
await this.loadIdleAnimation();
}
/**
* 语音播放,配合人物表情动作
Expand Down

0 comments on commit 11d55af

Please sign in to comment.