限制序列帧去背景仅用于视频转换
后端仅接受 character-animation.convert 结果执行序列帧去背景 前端工具栏与工作流同步收紧视频转换门禁 更新相关测试与Spine序列帧技术方案
This commit is contained in:
@@ -70,15 +70,13 @@ import {
|
||||
} from './ImageCanvasGenerationModel';
|
||||
|
||||
describe('ImageCanvasGenerationModel', () => {
|
||||
it('allows sequence background removal only for green generated animations', () => {
|
||||
it('allows sequence background removal only for direct video conversions', () => {
|
||||
const layer = {
|
||||
assetKind: 'character-animation',
|
||||
generationInputs: {
|
||||
version: 2 as const,
|
||||
action: 'character-animation.generate' as const,
|
||||
fields: [
|
||||
{ id: 'backgroundColor', title: '背景颜色', value: 'green' as const },
|
||||
],
|
||||
action: 'character-animation.convert' as const,
|
||||
fields: [],
|
||||
references: [],
|
||||
},
|
||||
} as unknown as CanvasLayer;
|
||||
@@ -88,7 +86,7 @@ describe('ImageCanvasGenerationModel', () => {
|
||||
...layer,
|
||||
generationInputs: {
|
||||
...layer.generationInputs!,
|
||||
action: 'character-animation.convert',
|
||||
action: 'character-animation.generate',
|
||||
},
|
||||
}),
|
||||
).toBe(false);
|
||||
@@ -97,7 +95,7 @@ describe('ImageCanvasGenerationModel', () => {
|
||||
...layer,
|
||||
generationInputs: {
|
||||
...layer.generationInputs!,
|
||||
fields: [{ id: 'backgroundColor', title: '背景颜色', value: 'blue' }],
|
||||
action: 'character-animation.remove-background',
|
||||
},
|
||||
}),
|
||||
).toBe(false);
|
||||
|
||||
@@ -1041,15 +1041,10 @@ export function buildCharacterAnimationGenerationInputs(
|
||||
}
|
||||
|
||||
export function canRemoveCharacterAnimationBackground(layer: CanvasLayer) {
|
||||
if (
|
||||
layer.assetKind !== 'character-animation' ||
|
||||
layer.generationInputs?.version !== 2 ||
|
||||
layer.generationInputs.action !== 'character-animation.generate'
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
return layer.generationInputs.fields.some(
|
||||
(field) => field.id === 'backgroundColor' && field.value === 'green',
|
||||
return (
|
||||
layer.assetKind === 'character-animation' &&
|
||||
layer.generationInputs?.version === 2 &&
|
||||
layer.generationInputs.action === 'character-animation.convert'
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -459,11 +459,8 @@ describe('ImageCanvasSelectedLayerToolbarView', () => {
|
||||
assetKind: 'character-animation',
|
||||
generationInputs: {
|
||||
version: 2,
|
||||
action: 'character-animation.generate',
|
||||
fields: [
|
||||
{ id: 'prompt', title: '动作描述', value: '挥手' },
|
||||
{ id: 'backgroundColor', title: '背景颜色', value: 'green' },
|
||||
],
|
||||
action: 'character-animation.convert',
|
||||
fields: [],
|
||||
references: [],
|
||||
},
|
||||
}),
|
||||
@@ -492,21 +489,18 @@ describe('ImageCanvasSelectedLayerToolbarView', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('hides sequence background removal unless the authoritative background is green', () => {
|
||||
const whiteLayer = createLayer({
|
||||
it('shows sequence background removal only for direct video conversions', () => {
|
||||
const generatedLayer = createLayer({
|
||||
mediaType: 'image-sequence',
|
||||
assetKind: 'character-animation',
|
||||
generationInputs: {
|
||||
version: 2,
|
||||
action: 'character-animation.generate',
|
||||
fields: [
|
||||
{ id: 'prompt', title: '动作描述', value: '挥手' },
|
||||
{ id: 'backgroundColor', title: '背景颜色', value: 'white' },
|
||||
],
|
||||
fields: [{ id: 'prompt', title: '动作描述', value: '挥手' }],
|
||||
references: [],
|
||||
},
|
||||
});
|
||||
renderSelectedToolbar({ selectedLayer: whiteLayer });
|
||||
renderSelectedToolbar({ selectedLayer: generatedLayer });
|
||||
|
||||
expect(screen.queryByRole('button', { name: '去背景' })).toBeNull();
|
||||
|
||||
@@ -517,13 +511,13 @@ describe('ImageCanvasSelectedLayerToolbarView', () => {
|
||||
generationInputs: {
|
||||
version: 2,
|
||||
action: 'character-animation.convert',
|
||||
fields: [{ id: 'backgroundColor', title: '背景颜色', value: 'green' }],
|
||||
fields: [],
|
||||
references: [],
|
||||
},
|
||||
});
|
||||
renderSelectedToolbar({ selectedLayer: convertedLayer });
|
||||
|
||||
expect(screen.queryByRole('button', { name: '去背景' })).toBeNull();
|
||||
expect(screen.getByRole('button', { name: '去背景' })).toBeTruthy();
|
||||
});
|
||||
|
||||
it('disables frame splitting while a character animation resource is pending registration', () => {
|
||||
|
||||
@@ -3067,6 +3067,12 @@ describe('useImageCanvasGenerationWorkflow', () => {
|
||||
title: '勇者奔跑',
|
||||
assetKind: 'character-animation',
|
||||
mediaType: 'image-sequence',
|
||||
generationInputs: {
|
||||
version: 2,
|
||||
action: 'character-animation.convert',
|
||||
fields: [],
|
||||
references: [],
|
||||
},
|
||||
}),
|
||||
]}
|
||||
/>,
|
||||
|
||||
@@ -96,6 +96,7 @@ import {
|
||||
appendLimitedImageReferences,
|
||||
buildDeterministicGenerationInputs,
|
||||
calculateCharacterAnimationPrice,
|
||||
canRemoveCharacterAnimationBackground,
|
||||
canSplitCharacterAnimationFrames,
|
||||
CANVAS_GENERATION_PARAMETER_FALLBACK_WARNING,
|
||||
CHARACTER_ANIMATION_DURATION_OPTIONS,
|
||||
@@ -3677,6 +3678,7 @@ export function useImageCanvasGenerationWorkflow({
|
||||
const removeSelectedCharacterAnimationBackground = useCallback(
|
||||
async (sourceLayer: CanvasLayer) => {
|
||||
if (
|
||||
!canRemoveCharacterAnimationBackground(sourceLayer) ||
|
||||
!canSplitCharacterAnimationFrames(sourceLayer) ||
|
||||
!projectId ||
|
||||
removingBackgroundCharacterAnimationLayerIdsRef.current.has(
|
||||
|
||||
Reference in New Issue
Block a user