修正自动切分素材检查条件

移除自动切分对预先导入独立素材的错误要求。
统一自动切分前置与结果检查,并补齐图片和字体引用校验。
在新建和重新开始自动切分时执行前置检查,恢复流程继续尽力完成。
This commit is contained in:
2026-09-10 18:43:31 +08:00
parent 1509235c1b
commit 74f726e65d
4 changed files with 62 additions and 59 deletions
@@ -72,7 +72,7 @@ export function validateComponentRecognitionPrerequisites(
return issues;
}
export function validateAssetRecognitionPrerequisites(
export function validateAssetSeparationPrerequisites(
state: State,
): UiEditorPrerequisiteIssue[] {
const issues = validateComponentRecognitionPrerequisites(state);
@@ -91,58 +91,9 @@ export function validateAssetRecognitionPrerequisites(
});
}
}
if (Object.keys(state.sprite_assets).length === 0) {
issues.push({
code: 'missing-sprite-assets',
message: '请先导入独立素材',
});
}
return issues;
}
export function validateLayoutGenerationPrerequisites(
state: State,
): UiEditorPrerequisiteIssue[] {
const issues = validateAssetRecognitionPrerequisites(state);
const visit = (nodes: State['ui_trees'][number]['root']['children']) => {
for (const node of nodes) {
const component = node.component;
if (component) {
if (
'Image' in component &&
component.Image.target_graphic !== null &&
!(component.Image.target_graphic in state.sprite_assets)
) {
issues.push({
code: 'missing-target-graphic',
message: '图片组件引用的独立素材不存在',
resourceId: component.Image.target_graphic,
});
}
if ('Text' in component) {
const font = component.Text.font;
if (typeof font !== 'string' && !(font.Bound in state.font_assets)) {
issues.push({
code: 'missing-font',
message: '文本组件引用的字体不存在',
resourceId: font.Bound,
});
}
}
}
visit(node.children);
}
};
for (const tree of state.ui_trees) visit([tree.root]);
return issues;
}
export function validateLayoutReviewPrerequisites(
state: State,
): UiEditorPrerequisiteIssue[] {
return validateLayoutGenerationPrerequisites(state);
}
function layoutStatusIssue(
status: StageStatus,
): UiEditorPrerequisiteIssue | null {
@@ -214,7 +165,7 @@ export function validateStructureRecognitionResult(
return issues;
}
export function validateVisualBindingResult(
export function validateAssetSeparationResult(
state: State,
): UiEditorPrerequisiteIssue[] {
const issues: UiEditorPrerequisiteIssue[] = [];
@@ -225,6 +176,32 @@ export function validateVisualBindingResult(
}
const issue = componentStatusIssue(node.metadata.component_status);
if (issue) issues.push(issue);
const component = node.component;
if ('Image' in component) {
const targetGraphic = component.Image.target_graphic;
if (targetGraphic === null) {
issues.push({
code: 'missing-separated-image',
message: '图片组件尚未完成素材切分',
});
} else if (!(targetGraphic in state.sprite_assets)) {
issues.push({
code: 'missing-target-graphic',
message: '图片组件引用的切分素材不存在',
resourceId: targetGraphic,
});
}
}
if ('Text' in component) {
const font = component.Text.font;
if (typeof font !== 'string' && !(font.Bound in state.font_assets)) {
issues.push({
code: 'missing-font',
message: '文本组件引用的字体不存在',
resourceId: font.Bound,
});
}
}
});
}
return issues;
@@ -1,11 +1,10 @@
import {
type UiEditorPrerequisiteIssue,
validateAssetRecognitionPrerequisites,
validateAssetSeparationPrerequisites,
validateAssetSeparationResult,
validateComponentRecognitionPrerequisites,
validateLayoutReviewPrerequisites,
validateReferenceAnalysisResult,
validateStructureRecognitionResult,
validateVisualBindingResult,
} from '../../../features/ui-editor/requisites';
import type { State } from '../../../features/ui-editor/types/State';
import type { UiEditorStepId } from '../model';
@@ -22,7 +21,7 @@ export function prerequisiteIssuesForStep(
case 'structure-recognition':
return validateComponentRecognitionPrerequisites(state);
case 'asset-separation':
return validateAssetRecognitionPrerequisites(state);
return validateAssetSeparationPrerequisites(state);
}
}
@@ -36,7 +35,7 @@ export function postCheckIssuesForStep(
case 'structure-recognition':
return validateStructureRecognitionResult(state);
case 'asset-separation':
return validateVisualBindingResult(state);
return validateAssetSeparationResult(state);
}
}
@@ -46,7 +45,7 @@ export function postCheckIssuesForSave(
return [
...validateReferenceAnalysisResult(state),
...validateStructureRecognitionResult(state),
...validateVisualBindingResult(state),
...validateAssetSeparationResult(state),
];
}
@@ -58,8 +57,8 @@ export function activeStepPrerequisiteIssues(
case 'reference-analysis':
return validateComponentRecognitionPrerequisites(state);
case 'structure-recognition':
return validateAssetRecognitionPrerequisites(state);
return validateComponentRecognitionPrerequisites(state);
case 'asset-separation':
return validateLayoutReviewPrerequisites(state);
return validateAssetSeparationPrerequisites(state);
}
}
@@ -1241,6 +1241,19 @@ export function useUiEditorSession(
setSeparationRecovery(recovery);
return;
}
const prerequisiteIssues = prerequisiteIssuesForStep(
editor.state,
'asset-separation',
);
if (prerequisiteIssues.length > 0) {
reportWorkflowCompletion(
'asset-separation',
'failure',
prerequisiteIssues.map((issue) => issue.message).join(''),
setSeparationStatus,
);
return;
}
await runSeparationWorkflow();
} catch (cause) {
setSeparationStatus(
@@ -1257,6 +1270,19 @@ export function useUiEditorSession(
async function restartSeparation() {
if (!resourceId) return;
setSeparationRecovery(null);
const prerequisiteIssues = prerequisiteIssuesForStep(
editor.state,
'asset-separation',
);
if (prerequisiteIssues.length > 0) {
reportWorkflowCompletion(
'asset-separation',
'failure',
prerequisiteIssues.map((issue) => issue.message).join(''),
setSeparationStatus,
);
return;
}
try {
await invoke('discard_separation_recovery', {
projectPath,