async mesh import via background thread + mpsc channel

This commit is contained in:
jess 2026-04-02 11:56:12 -07:00
parent 97653580e5
commit 71c18313b5
1 changed files with 44 additions and 6 deletions

View File

@ -6,7 +6,7 @@ use iced::widget::{
use iced::{Background, Border, Color, Element, Fill, Length, Padding, Shadow, Subscription}; use iced::{Background, Border, Color, Element, Fill, Length, Padding, Shadow, Subscription};
use iced::{mouse, keyboard, window, Point, Vector}; use iced::{mouse, keyboard, window, Point, Vector};
use std::path::PathBuf; use std::path::PathBuf;
use std::sync::Arc; use std::sync::{Arc, mpsc};
use std::time::Duration; use std::time::Duration;
use cord_expr::{classify, classify_from, expr_to_sdf, parse_expr, parse_expr_scene, ExprInfo}; use cord_expr::{classify, classify_from, expr_to_sdf, parse_expr, parse_expr_scene, ExprInfo};
@ -39,6 +39,7 @@ pub struct App {
cursor_line: usize, cursor_line: usize,
line_eval_text: Option<String>, line_eval_text: Option<String>,
mesh_path: Option<PathBuf>, mesh_path: Option<PathBuf>,
mesh_import_rx: Option<mpsc::Receiver<Result<(String, PathBuf), String>>>,
} }
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
@ -80,6 +81,7 @@ pub enum Message {
RenderPlots, RenderPlots,
RenderAll, RenderAll,
DecomposeMesh, DecomposeMesh,
MeshImportComplete(Result<(String, PathBuf), String>),
Tick, Tick,
} }
@ -147,6 +149,7 @@ impl App {
cursor_line: 0, cursor_line: 0,
line_eval_text: None, line_eval_text: None,
mesh_path: None, mesh_path: None,
mesh_import_rx: None,
}; };
app.reparse(); app.reparse();
@ -328,12 +331,39 @@ impl App {
} }
} }
Message::DecomposeMesh => self.decompose_mesh(), Message::DecomposeMesh => self.decompose_mesh(),
Message::MeshImportComplete(result) => {
match result {
Ok((source, path)) => {
self.source = text_editor::Content::with_text(&source);
self.undo_stack = vec![source];
self.redo_stack.clear();
self.mesh_path = Some(path.clone());
self.current_path = Some(path.clone());
self.dirty = false;
self.detect_mode();
self.reparse();
self.update_markdown();
self.push_recent(&path);
self.status = Some(format!("opened: {}", path.display()));
}
Err(e) => {
self.status = Some(format!("mesh import error: {e}"));
}
}
}
Message::Tick => { Message::Tick => {
if !self.menu_ready { if !self.menu_ready {
setup_native_menu(); setup_native_menu();
self.menu_ready = true; self.menu_ready = true;
} }
self.poll_menu_events(); self.poll_menu_events();
if let Some(rx) = &self.mesh_import_rx {
if let Ok(result) = rx.try_recv() {
self.mesh_import_rx = None;
self.update(Message::MeshImportComplete(result));
return;
}
}
let new_line = self.source.cursor().position.line; let new_line = self.source.cursor().position.line;
if new_line != self.cursor_line { if new_line != self.cursor_line {
self.cursor_line = new_line; self.cursor_line = new_line;
@ -637,7 +667,18 @@ impl App {
.unwrap_or("") .unwrap_or("")
.to_lowercase(); .to_lowercase();
let is_mesh = matches!(ext.as_str(), "obj" | "stl" | "3mf"); if matches!(ext.as_str(), "obj" | "stl" | "3mf") {
self.status = Some(format!("decomposing mesh: {}", path.display()));
let (tx, rx) = mpsc::channel();
let path_owned = path.to_path_buf();
std::thread::spawn(move || {
let result = import_mesh(&path_owned)
.map(|source| (source, path_owned));
let _ = tx.send(result);
});
self.mesh_import_rx = Some(rx);
return;
}
let result = match ext.as_str() { let result = match ext.as_str() {
"zcd" => load_zcd(path), "zcd" => load_zcd(path),
@ -645,9 +686,6 @@ impl App {
"cord" | "bin" => { "cord" | "bin" => {
Err("binary format (.cord) — no source to edit".into()) Err("binary format (.cord) — no source to edit".into())
} }
"obj" | "stl" | "3mf" => {
import_mesh(path)
}
"step" | "stp" => { "step" | "stp" => {
Err(format!("import for .{ext} not yet implemented")) Err(format!("import for .{ext} not yet implemented"))
} }
@ -660,7 +698,7 @@ impl App {
self.undo_stack = vec![source]; self.undo_stack = vec![source];
self.redo_stack.clear(); self.redo_stack.clear();
self.current_path = Some(path.to_path_buf()); self.current_path = Some(path.to_path_buf());
self.mesh_path = if is_mesh { Some(path.to_path_buf()) } else { None }; self.mesh_path = None;
self.dirty = false; self.dirty = false;
self.detect_mode(); self.detect_mode();
self.reparse(); self.reparse();