Skip to content

Commit 11d55af

Browse files
committed
✨ feat: dance 文件统一使用 blob
1 parent 7ecc313 commit 11d55af

File tree

8 files changed

+43
-32
lines changed

8 files changed

+43
-32
lines changed

src/features/DanceList/Item/index.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,22 +42,22 @@ const DanceItem = (props: DanceItemProps) => {
4242
const { t } = useTranslation('common');
4343

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

4848
const handlePlayPause = () => {
49-
viewer.model?.resetToIdle();
49+
viewer.model?.disposeAll();
5050
if (isPlaying && isCurrentPlay) {
5151
setIsPlaying(false);
5252
} else {
5353
setCurrentPlayId(danceItem.danceId);
5454
setIsPlaying(true);
5555
const audioPromise = fetchAudioUrl(danceItem.danceId, danceItem.audio);
56-
const dancePromise = fetchDanceBuffer(danceItem.danceId, danceItem.src);
56+
const dancePromise = fetchDanceUrl(danceItem.danceId, danceItem.src);
5757
Promise.all([dancePromise, audioPromise]).then((res) => {
5858
if (!res) return;
59-
const [danceBuffer, audioUrl] = res;
60-
viewer.model?.dance(danceBuffer, audioUrl);
59+
const [danceUrl, audioUrl] = res;
60+
if (danceUrl && audioUrl) viewer.model?.dance(danceUrl, audioUrl);
6161
});
6262
}
6363
};

src/features/MotionList/ActionList/ListItem.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,8 @@ const TouchActionListItem = memo<ActionListItemProps>(({ item }) => {
7272
showAction={true}
7373
onClick={async () => {
7474
if (item.url) {
75-
const url = await fetchMotionUrl(item.id, item.url);
76-
viewer.model?.loadFBX(url);
75+
const motionUrl = await fetchMotionUrl(item.id, item.url);
76+
if (motionUrl) viewer.model?.loadFBX(motionUrl);
7777
}
7878
}}
7979
title={item.name}

src/features/PostureList/ActionList/ListItem.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,8 @@ const TouchActionListItem = memo<ActionListItemProps>(({ item }) => {
7272
showAction={true}
7373
onClick={async () => {
7474
if (item.url) {
75-
const url = await fetchMotionUrl(item.id, item.url);
76-
viewer.model?.loadFBX(url);
75+
const motionUrl = await fetchMotionUrl(item.id, item.url);
76+
if (motionUrl) viewer.model?.loadFBX(motionUrl);
7777
}
7878
}}
7979
title={item.name}

src/hooks/useLoadAudio.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ export const useLoadAudio = () => {
3333
} finally {
3434
setDownloading(false);
3535
}
36+
if (!audioBlob) return null;
37+
3638
return URL.createObjectURL(audioBlob);
3739
};
3840

src/hooks/useLoadDance.tsx

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { isArrayBuffer } from 'lodash-es';
12
import { useState } from 'react';
23

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

11-
const fetchDanceBuffer = async (danceId: string, src: string) => {
12+
const fetchDanceUrl = async (danceId: string, src: string) => {
1213
const localDancePath = getDancePathByDanceId(danceId);
13-
let danceBuffer = (await storage.getItem(localDancePath)) as ArrayBuffer;
14+
let danceBlob = await storage.getItem(localDancePath);
15+
16+
// 存量转换
17+
if (danceBlob && isArrayBuffer(danceBlob)) {
18+
// 如果存的是 ArrayBuffer,设置为空重新下载;
19+
danceBlob = null;
20+
}
1421

1522
try {
16-
if (!danceBuffer) {
23+
if (!danceBlob) {
1724
setDownloading(true);
1825
setPercent(0);
1926

20-
danceBuffer = await fetchWithProgress(src, {
27+
danceBlob = await fetchWithProgress(src, {
2128
onProgress: (loaded, total) => {
2229
setPercent((loaded / total) * 100);
2330
},
24-
}).then((res) => res.arrayBuffer());
25-
await storage.setItem(localDancePath, danceBuffer);
31+
});
32+
await storage.setItem(localDancePath, danceBlob);
2633
}
2734
} finally {
2835
setDownloading(false);
2936
}
30-
return danceBuffer;
37+
38+
if (!danceBlob) return null;
39+
40+
return URL.createObjectURL(danceBlob);
3141
};
3242

3343
return {
3444
downloading,
3545
percent,
36-
fetchDanceBuffer,
46+
fetchDanceUrl,
3747
};
3848
};

src/hooks/useLoadModel.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,20 +16,20 @@ export const useLoadModel = () => {
1616
if (!modelBlob) {
1717
setDownloading(true);
1818
setPercent(0);
19-
const blob = await fetchWithProgress(remoteModelUrl, {
19+
modelBlob = await fetchWithProgress(remoteModelUrl, {
2020
onProgress: (loaded, total) => {
2121
setPercent(Math.ceil((loaded / total) * 100));
2222
},
2323
});
2424
const modelPath = getModelPathByAgentId(agentId);
25-
await storage.setItem(modelPath, blob);
25+
await storage.setItem(modelPath, modelBlob);
2626
}
27-
} catch (e) {
28-
console.error(e);
29-
return null;
3027
} finally {
3128
setDownloading(false);
3229
}
30+
31+
if (!modelBlob) return null;
32+
3333
return URL.createObjectURL(modelBlob);
3434
};
3535

src/hooks/useLoadMotion.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ export const useLoadMotion = () => {
1010

1111
const fetchMotionUrl = async (motionId: string, motionUrl: string) => {
1212
const localMotionPath = getMotionPathByMotionId(motionId);
13-
let motionBlob = (await storage.getItem(localMotionPath)) as Blob;
13+
let motionBlob = await storage.getItem(localMotionPath);
14+
1415
try {
1516
if (!motionBlob) {
1617
setDownloading(true);
@@ -26,6 +27,9 @@ export const useLoadMotion = () => {
2627
} finally {
2728
setDownloading(false);
2829
}
30+
31+
if (!motionBlob) return null;
32+
2933
return URL.createObjectURL(motionBlob);
3034
};
3135

src/libs/vrmViewer/model.ts

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -156,17 +156,15 @@ export class Model {
156156
/**
157157
* 播放舞蹈,以音乐文件的播放作为结束标志。
158158
*/
159-
public async dance(dance: ArrayBuffer, audioUrl: string, onEnd?: () => void) {
159+
public async dance(danceUrl: string, audioUrl: string, onEnd?: () => void) {
160160
const { vrm, mixer } = this;
161161
if (vrm && mixer) {
162162
this.disposeAll();
163-
const animation = convert(dance, toOffset(vrm));
164-
const clip = bindToVRM(animation, vrm);
163+
const clip = await loadVMDAnimation(danceUrl, vrm);
165164
const action = mixer.clipAction(clip);
166165
action.setLoop(LoopOnce, 1).play(); // play animation
167166
if (audioUrl) {
168167
this._audioPlayer?.playFromURL(audioUrl, () => {
169-
this.resetToIdle();
170168
onEnd?.();
171169
});
172170
this._audio = audioUrl;
@@ -178,12 +176,9 @@ export class Model {
178176
}
179177

180178
public async resetToIdle() {
181-
const { vrm, mixer } = this;
182-
if (vrm && mixer) {
183-
this.disposeAll();
179+
this.disposeAll();
184180

185-
await this.loadIdleAnimation();
186-
}
181+
await this.loadIdleAnimation();
187182
}
188183
/**
189184
* 语音播放,配合人物表情动作

0 commit comments

Comments
 (0)