From f796aef7e23f00e2821ce22eb421862199e1024e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=BE=B7=E5=AE=87?= Date: Tue, 8 Sep 2026 18:32:36 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E5=96=84UI=E8=87=AA=E5=8A=A8=E5=88=86?= =?UTF-8?q?=E7=A6=BB=E6=89=B9=E6=AC=A1=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 复用资源ID安全路径并修正像素坐标 加入标记图、Raw编辑、视觉绑定修复与问题节点继续处理 --- .../src/ui_editor/commands/separation.rs | 77 ++++++++++++++----- 1 file changed, 58 insertions(+), 19 deletions(-) diff --git a/apps/ai-game-creator-shell/src-tauri/src/ui_editor/commands/separation.rs b/apps/ai-game-creator-shell/src-tauri/src/ui_editor/commands/separation.rs index d1217aefa..fb65a02c5 100644 --- a/apps/ai-game-creator-shell/src-tauri/src/ui_editor/commands/separation.rs +++ b/apps/ai-game-creator-shell/src-tauri/src/ui_editor/commands/separation.rs @@ -16,7 +16,6 @@ use platform_llm::{ }; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -use sha2::{Digest, Sha256}; use std::fs; use std::path::{Path, PathBuf}; use ts_rs::TS; @@ -331,18 +330,10 @@ pub fn separation_sidecar_dir(root: &Path, asset_id: &str) -> Result>(); + for node in batch { + state.problematic_nodes.push(ProblematicNode { + node_id: node.id.clone(), + problem_description: error.clone(), + rework_count: MAX_REWORK_COUNT, + }); + } + if let Some(tree) = state.unprocessed_trees.get_mut(tree_index) { + remove_ids(&mut tree.root, &ids); + } +} + fn increment_rework_count(node: &mut SeparationNode, id: &NodeId, count: u32) { if node.id == *id { node.rework_count = count; @@ -662,22 +675,41 @@ pub(crate) async fn separate_ui_impl( let Some(current_tree) = separation.unprocessed_trees.get(tree_index) else { break; }; - let batch = next_leaf_batch(current_tree); - if batch.is_empty() { + let batch_nodes = next_leaf_batch(current_tree) + .into_iter() + .cloned() + .collect::>(); + if batch_nodes.is_empty() { break; } + let batch = batch_nodes.iter().collect::>(); let prompt = gen_extract_prompt(&batch.iter().map(|n| n.note.clone()).collect::>()); let marker_path = sidecar.join(format!("marked-{}.png", separation.bound.len())); - let marked_url = build_marked_image(&source_url, &batch, &marker_path)?; - let processed_url = raw_image_edit( + let marked_url = match build_marked_image(&source_url, &batch, &marker_path) { + Ok(value) => value, + Err(error) => { + mark_batch_problematic(&mut separation, tree_index, &batch, error); + write_separation_state(&state_path, &separation)?; + continue; + } + }; + let processed_url = match raw_image_edit( &session, &marked_url, &prompt, image.pixel_size.x as u32, image.pixel_size.y as u32, ) - .await?; + .await + { + Ok(value) => value, + Err(error) => { + mark_batch_problematic(&mut separation, tree_index, &batch, error); + write_separation_state(&state_path, &separation)?; + continue; + } + }; let processed_path = sidecar.join(format!("processed-{}.png", separation.bound.len())); let processed_bytes = base64::engine::general_purpose::STANDARD .decode( @@ -688,7 +720,14 @@ pub(crate) async fn separate_ui_impl( ) .map_err(|e| e.to_string())?; fs::write(&processed_path, processed_bytes).map_err(|e| e.to_string())?; - let binding = visual_binding(source_url.clone(), processed_url, &batch).await?; + let binding = match visual_binding(source_url.clone(), processed_url, &batch).await { + Ok(value) => value, + Err(error) => { + mark_batch_problematic(&mut separation, tree_index, &batch, error); + write_separation_state(&state_path, &separation)?; + continue; + } + }; let mut cut_paths = std::collections::HashMap::new(); for decision in &binding.decisions { if let BindingDecision::Ok {