Add design containers with deduplicated blobs and JSON compatibility (#327)

* Add fast design containers with lossless deduplicated payloads

* Keep display caching opt-in to avoid default save overhead
This commit is contained in:
selune authored and GitHub committed 2026-10-12 19:15:41 -04:00
1 parent 8e0c3d2794
commit 006a23a767
30 files changed
+1921 -71

No files matched your search

+30 -5
View File
@@ -19,7 +19,7 @@ mod control_server;
#[cfg(any(target_os = "windows", target_os = "linux"))]
mod space_mouse;
use solidcraft_engine::Session;
use solidcraft_engine::{Session, io};
use solidcraft_ui_egui::{Services, SolveApp};
struct App {
@@ -66,10 +66,25 @@ fn services() -> Services {
rfd::FileDialog::new()
.add_filter(
"Designs, STEP, IGES and meshes",
&["solidcraft", "solvecraft", "step", "stp", "STEP", "STP", "igs", "iges", "IGS", "IGES", "3mf", "3MF", "stl", "STL"],
&[
io::DESIGN_EXT,
io::LEGACY_DESIGN_EXT,
"json",
"step",
"stp",
"STEP",
"STP",
"igs",
"iges",
"IGS",
"IGES",
"3mf",
"3MF",
"stl",
"STL",
],
)
// The legacy extension is a compatibility shim (docs/compatibility.md).
.add_filter("SolidCraft design", &solidcraft_engine::io::DESIGN_EXTS)
.add_filter("SolidCraft design (container or JSON)", &[io::DESIGN_EXT, io::LEGACY_DESIGN_EXT, "json"])
.add_filter("STEP", &["step", "stp", "STEP", "STP"])
.add_filter("IGES", &["igs", "iges", "IGS", "IGES"])
.add_filter("Mesh (3MF, STL)", &["3mf", "3MF", "stl", "STL"])
@@ -79,7 +94,17 @@ fn services() -> Services {
.map(|p| p.to_string_lossy().to_string())
})),
pick_save: Some(Box::new(|name: &str, exts: &[&str]| {
rfd::FileDialog::new().set_file_name(name).add_filter("File", exts).save_file().map(|p| p.to_string_lossy().to_string())
let dialog = rfd::FileDialog::new().set_file_name(name);
let dialog = if exts == [io::DESIGN_EXT, "json"] {
if name.ends_with(".json") {
dialog.add_filter("Plain JSON design", &["json"]).add_filter("SolidCraft container", &[io::DESIGN_EXT])
} else {
dialog.add_filter("SolidCraft container", &[io::DESIGN_EXT]).add_filter("Plain JSON design", &["json"])
}
} else {
dialog.add_filter("File", exts)
};
dialog.save_file().map(|p| p.to_string_lossy().to_string())
})),
graphics_path: graphics_path().map(|p| p.to_string_lossy().to_string()),
show_in_folder: Some(Box::new(|path| {