diff --git a/src/components/image-editor/model3d-generation/Model3dGenerationFormModel.test.ts b/src/components/image-editor/model3d-generation/Model3dGenerationFormModel.test.ts index 4cdad8ba0..2f551ea9c 100644 --- a/src/components/image-editor/model3d-generation/Model3dGenerationFormModel.test.ts +++ b/src/components/image-editor/model3d-generation/Model3dGenerationFormModel.test.ts @@ -577,6 +577,48 @@ describe('3D 生成面板的参数变更', () => { ).not.toBe(failedDialog.model3dAttemptNonce); }); + it('分件与四边面 / 智能减面互斥:后打开的赢,先打开的自动关掉', () => { + const geometryDialog = createDialog({ + model3dTier: 'geometry-only', + model3dGenerateParts: true, + }); + + const quad = applyModel3dSwitchChange(geometryDialog, { + model3dQuad: true, + }); + expect(quad).toMatchObject({ + model3dQuad: true, + model3dGenerateParts: false, + }); + + const smartLowPoly = applyModel3dSwitchChange( + { ...geometryDialog, model3dGenerateParts: false }, + { model3dSmartLowPoly: true }, + ); + expect(smartLowPoly.model3dQuad).toBe(false); + + const parts = applyModel3dSwitchChange( + { ...geometryDialog, model3dQuad: true, model3dSmartLowPoly: true }, + { model3dGenerateParts: true }, + ); + expect(parts).toMatchObject({ + model3dGenerateParts: true, + model3dQuad: false, + model3dSmartLowPoly: false, + }); + }); + + it('只关掉一个开关时不动其它开关', () => { + const dialog = createDialog({ + model3dTier: 'geometry-only', + model3dQuad: true, + }); + + expect( + applyModel3dSwitchChange(dialog, { model3dGenerateParts: false }), + ).toMatchObject({ model3dQuad: true, model3dGenerateParts: false }); + }); + it('删掉参考图回到空槽位并清掉失败态', () => { const dialog = createDialog({ mode: 'model3d-image-to-model', diff --git a/src/components/image-editor/model3d-generation/Model3dGenerationFormModel.ts b/src/components/image-editor/model3d-generation/Model3dGenerationFormModel.ts index df6daaf44..16bd7d847 100644 --- a/src/components/image-editor/model3d-generation/Model3dGenerationFormModel.ts +++ b/src/components/image-editor/model3d-generation/Model3dGenerationFormModel.ts @@ -447,6 +447,13 @@ export function applyModel3dModelChange( }); } +/** + * 改开关:换代次、清失败态,并把互斥项一起收干净。 + * + * 「生成部件」与「四边面」/「智能减面」不能同时打开(提交前校验会直接拒绝,见 + * `Model3dGenerationValidation`)。这里让刚刚打开的那个赢、另一个自动关掉:面板上不留 + * 一个永远提交不了的组合,也不用用户自己去猜该关哪一个(评审 #86)。 + */ export function applyModel3dSwitchChange( dialog: GenerateDialogState, patch: Partial< @@ -456,7 +463,18 @@ export function applyModel3dSwitchChange( > >, ): GenerateDialogState { - return withNewAttemptNonce({ ...resetFailedStatus(dialog), ...patch }); + const next = { ...resetFailedStatus(dialog), ...patch }; + if (patch.model3dGenerateParts === true) { + return withNewAttemptNonce({ + ...next, + model3dQuad: false, + model3dSmartLowPoly: false, + }); + } + if (patch.model3dQuad === true || patch.model3dSmartLowPoly === true) { + return withNewAttemptNonce({ ...next, model3dGenerateParts: false }); + } + return withNewAttemptNonce(next); } export function applyModel3dPromptChange(