@@ -178,6 +178,70 @@ function hasMatch3DGeneratedModelSource(asset: Match3DGeneratedItemAsset) {
|
||||
return Boolean(asset.modelSrc?.trim() || asset.modelObjectKey?.trim());
|
||||
}
|
||||
|
||||
function hasPersistableMatch3DGeneratedItemAsset(
|
||||
asset: Match3DGeneratedItemAsset,
|
||||
) {
|
||||
return Boolean(
|
||||
asset.imageSrc?.trim() ||
|
||||
asset.imageObjectKey?.trim() ||
|
||||
asset.modelSrc?.trim() ||
|
||||
asset.modelObjectKey?.trim() ||
|
||||
asset.taskUuid?.trim() ||
|
||||
asset.subscriptionKey?.trim() ||
|
||||
asset.backgroundMusic ||
|
||||
asset.clickSound,
|
||||
);
|
||||
}
|
||||
|
||||
function getMatch3DGeneratedItemAssetPersistenceSignature(
|
||||
asset: Match3DGeneratedItemAsset,
|
||||
) {
|
||||
return [
|
||||
asset.itemId.trim(),
|
||||
asset.itemName.trim(),
|
||||
asset.imageSrc?.trim() ?? '',
|
||||
asset.imageObjectKey?.trim() ?? '',
|
||||
asset.modelSrc?.trim() ?? '',
|
||||
asset.modelObjectKey?.trim() ?? '',
|
||||
asset.modelFileName?.trim() ?? '',
|
||||
asset.taskUuid?.trim() ?? '',
|
||||
asset.subscriptionKey?.trim() ?? '',
|
||||
asset.status.trim(),
|
||||
asset.backgroundMusic?.audioSrc?.trim() ??
|
||||
asset.backgroundMusic?.assetObjectId?.trim() ??
|
||||
asset.backgroundMusic?.taskId?.trim() ??
|
||||
'',
|
||||
asset.clickSound?.audioSrc?.trim() ??
|
||||
asset.clickSound?.assetObjectId?.trim() ??
|
||||
asset.clickSound?.taskId?.trim() ??
|
||||
'',
|
||||
asset.error?.trim() ?? '',
|
||||
].join('\u001f');
|
||||
}
|
||||
|
||||
function shouldPersistGeneratedItemAssets(
|
||||
currentAssets: readonly Match3DGeneratedItemAsset[],
|
||||
savedAssets: readonly Match3DGeneratedItemAsset[] = [],
|
||||
) {
|
||||
if (currentAssets.length <= 0) {
|
||||
return false;
|
||||
}
|
||||
if (currentAssets.length !== savedAssets.length) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return currentAssets.some(
|
||||
(asset, index) => {
|
||||
const savedAsset = savedAssets[index];
|
||||
return (
|
||||
!savedAsset ||
|
||||
getMatch3DGeneratedItemAssetPersistenceSignature(asset) !==
|
||||
getMatch3DGeneratedItemAssetPersistenceSignature(savedAsset)
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
function mergeMatch3DGeneratedItemAsset(
|
||||
base: Match3DGeneratedItemAsset,
|
||||
override: Match3DGeneratedItemAsset,
|
||||
@@ -636,6 +700,19 @@ function attachMatch3DGeneratedItemAssets(
|
||||
};
|
||||
}
|
||||
|
||||
function buildPersistableGeneratedItemAssets(
|
||||
assetDrafts: Match3DRodinAssetDraft[],
|
||||
generatedItemAssets: readonly Match3DGeneratedItemAsset[],
|
||||
) {
|
||||
if (generatedItemAssets.length <= 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return createGeneratedAssetsFromDrafts(assetDrafts, generatedItemAssets).filter(
|
||||
hasPersistableMatch3DGeneratedItemAsset,
|
||||
);
|
||||
}
|
||||
|
||||
function Match3DResultHeader({
|
||||
autoSaveState,
|
||||
isBusy,
|
||||
@@ -1459,8 +1536,12 @@ export function Match3DResultView({
|
||||
if (cancelled) {
|
||||
return;
|
||||
}
|
||||
const playableItem = attachMatch3DGeneratedItemAssets(
|
||||
item,
|
||||
generatedItemAssets,
|
||||
);
|
||||
setAutoSaveState('saved');
|
||||
onSaved?.(item);
|
||||
onSaved?.(playableItem);
|
||||
})
|
||||
.catch((saveError) => {
|
||||
if (cancelled) {
|
||||
@@ -1477,7 +1558,7 @@ export function Match3DResultView({
|
||||
cancelled = true;
|
||||
window.clearTimeout(timer);
|
||||
};
|
||||
}, [editState, onSaved, profile]);
|
||||
}, [editState, generatedItemAssets, onSaved, profile]);
|
||||
|
||||
const saveNow = async () => {
|
||||
const payload = buildSavePayload(editState);
|
||||
@@ -1489,10 +1570,34 @@ export function Match3DResultView({
|
||||
setAutoSaveState('saving');
|
||||
setLocalError(null);
|
||||
const { item } = await updateMatch3DWork(profile.profileId, payload);
|
||||
const playableItem = attachMatch3DGeneratedItemAssets(
|
||||
item,
|
||||
const currentGeneratedItemAssets = buildPersistableGeneratedItemAssets(
|
||||
assetDrafts,
|
||||
generatedItemAssets,
|
||||
);
|
||||
let playableItem = attachMatch3DGeneratedItemAssets(
|
||||
item,
|
||||
currentGeneratedItemAssets.length > 0
|
||||
? currentGeneratedItemAssets
|
||||
: generatedItemAssets,
|
||||
);
|
||||
if (
|
||||
shouldPersistGeneratedItemAssets(
|
||||
currentGeneratedItemAssets,
|
||||
item.generatedItemAssets ?? [],
|
||||
)
|
||||
) {
|
||||
// 中文注释:历史草稿可能只在页面 draft 中带 3D 模型;试玩和发布前必须先把当前可见素材写回 profile。
|
||||
const { item: persistedItem } = await updateMatch3DGeneratedItemAssets(
|
||||
profile.profileId,
|
||||
{
|
||||
generatedItemAssets: currentGeneratedItemAssets,
|
||||
},
|
||||
);
|
||||
playableItem = attachMatch3DGeneratedItemAssets(
|
||||
persistedItem,
|
||||
currentGeneratedItemAssets,
|
||||
);
|
||||
}
|
||||
setAutoSaveState('saved');
|
||||
onSaved?.(playableItem);
|
||||
return playableItem;
|
||||
@@ -1829,7 +1934,12 @@ export function Match3DResultView({
|
||||
const { item } = await publishMatch3DWork(
|
||||
savedProfile?.profileId ?? profile.profileId,
|
||||
);
|
||||
onPublished?.(item);
|
||||
onPublished?.(
|
||||
attachMatch3DGeneratedItemAssets(
|
||||
item,
|
||||
savedProfile?.generatedItemAssets ?? generatedItemAssets,
|
||||
),
|
||||
);
|
||||
setLocalError(null);
|
||||
} catch (caughtError) {
|
||||
setLocalError(
|
||||
|
||||
Reference in New Issue
Block a user