Save as mesh: one dialog for STL and 3MF, with Send to slicer (#1272)

One docked Save as mesh dialog replaces Export STL / 3MF / 3MF with face tags, with an optional Send to slicer that lists the slicers installed on this machine. Engine: file.save_mesh and file.slicers; the Convert Mesh dialog goes (mesh.convert and the MeshConvert feature stay, so existing designs open). Strings in all catalogs; screenshots in the PR. Checked on main + this branch: cargo check --workspace, the engine slicer/mesh/file tests, the UI catalog and menu tests and scenario s14 (the one local colour-token failure is epaint's TexturesDelta panic, which main shows on this machine too).
This commit is contained in:
froglemonade2 authored and GitHub committed 2026-10-15 03:51:28 -04:00
1 parent 3e13eb6392
commit 0872eb959a
28 files changed
+1483 -100

No files matched your search

+7
View File
@@ -98,6 +98,7 @@ impl eframe::App for App {
fn services(cc: &eframe::CreationContext<'_>) -> Services {
let parent = rfd::AsyncFileDialog::new().set_parent(cc);
let open_parent = parent.clone();
let program_parent = parent.clone();
Services {
pick_open: Some(Box::new(move || {
let future = open_parent
@@ -131,6 +132,12 @@ fn services(cc: &eframe::CreationContext<'_>) -> Services {
.pick_file();
Box::pin(async move { future.await.map(|p| p.path().to_string_lossy().into_owned()) })
})),
pick_program: Some(Box::new(move || {
let dialog = program_parent.clone().set_title("Choose your slicer");
let dialog = if cfg!(target_os = "windows") { dialog.add_filter("Programs", &["exe"]) } else { dialog };
let future = dialog.pick_file();
Box::pin(async move { future.await.map(|p| p.path().to_string_lossy().into_owned()) })
})),
pick_save: Some(Box::new(move |name: &str, exts: &[&str]| {
let dialog = parent.clone().set_file_name(name);
let dialog = if exts == [io::DESIGN_EXT, "json"] {