mirror of
https://github.com/bherbruck/solidcraft.git
synced 2026-11-08 13:01:52 +00:00
Preserve warm assembly caches across Save As renames (#2120)
Thanks @yutyan0119.
This commit is contained in:
@@ -294,12 +294,23 @@ fn saved_name(name: &str, old_path: Option<&str>, path: &str) -> Option<String>
|
||||
/// Rename the design, and the undo and redo states that still carry the old name, so undo
|
||||
/// does not bring the default name back and leave the design looking changed.
|
||||
fn rename_design(s: &mut Session, from: &str, to: &str) {
|
||||
// A prepared world is keyed by the document's Arc. Changing only its name
|
||||
// must not make an opted-in save lose warm geometry and display caches.
|
||||
// Retag only a cache that already matches: cold or stale placements stay so.
|
||||
let model = s.model.state();
|
||||
let keep_world = s.world_cache.lock().ok().is_some_and(|cache| cache.as_ref().is_some_and(|cache| cache.matches(s, &model)));
|
||||
s.doc_mut().name = to.to_string();
|
||||
for snap in s.undo.iter_mut().chain(s.redo.iter_mut()) {
|
||||
if snap.doc.name == from {
|
||||
std::sync::Arc::make_mut(&mut snap.doc).name = to.to_string();
|
||||
}
|
||||
}
|
||||
if keep_world
|
||||
&& let Ok(mut cache) = s.world_cache.lock()
|
||||
&& let Some(cache) = cache.as_mut()
|
||||
{
|
||||
cache.doc = std::sync::Arc::clone(&s.doc);
|
||||
}
|
||||
}
|
||||
|
||||
fn write(s: &mut Session, path: &str, format: &str, compression: &str, preview: bool, cache: bool) -> Result<Value> {
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
//! Optional save caches survive a filename-driven rename, without warming or
|
||||
//! certifying placements that do not match the document being saved.
|
||||
use serde_json::json;
|
||||
use solidcraft_doc::Document;
|
||||
use solidcraft_engine::Session;
|
||||
|
||||
fn assembly() -> Session {
|
||||
let mut session = Session::new(Document::new("Untitled"));
|
||||
session.execute("component.create", &json!({"name":"PlacedPart"})).unwrap();
|
||||
session.execute("solid.box", &json!({"length":2,"width":3,"height":4})).unwrap();
|
||||
session
|
||||
}
|
||||
|
||||
fn warm(session: &Session) {
|
||||
for body in &session.world_state().bodies {
|
||||
body.mesh();
|
||||
}
|
||||
}
|
||||
|
||||
fn save(session: &mut Session, label: &str) -> Vec<u8> {
|
||||
let path = std::env::temp_dir().join(format!("solidcraft-save-as-{label}-{}.solidcraft", std::process::id()));
|
||||
session.execute("file.save_as", &json!({"path":path,"cache":true,"preview":true})).unwrap();
|
||||
let bytes = std::fs::read(&path).unwrap();
|
||||
assert_eq!(solidcraft_io::read_design(&bytes).unwrap().name, path.file_stem().unwrap().to_string_lossy());
|
||||
std::fs::remove_file(&path).unwrap();
|
||||
let _ = std::fs::remove_file(format!("{}.bak", path.display()));
|
||||
bytes
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_filename_rename_preserves_opted_in_warm_assembly_caches() {
|
||||
let mut session = assembly();
|
||||
warm(&session);
|
||||
for label in ["first-warm", "renamed-warm"] {
|
||||
let bytes = save(&mut session, label);
|
||||
let geometry = solidcraft_io::read_design_geometry(&bytes).expect("warm geometry survives the rename");
|
||||
assert_eq!(geometry.len(), 1);
|
||||
assert!((solidcraft_kernel::measure(&geometry[0].body).unwrap().volume - 24.0).abs() < 1e-9);
|
||||
assert!(solidcraft_io::read_design_preview(&bytes).is_some(), "warm display meshes survive the rename");
|
||||
warm(&session);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn naming_a_design_does_not_warm_cold_or_revalidate_stale_placements() {
|
||||
let original = assembly();
|
||||
let mut cold = Session::new((*original.doc).clone());
|
||||
let bytes = save(&mut cold, "cold");
|
||||
assert!(solidcraft_io::read_design_geometry(&bytes).is_none());
|
||||
assert!(solidcraft_io::read_design_preview(&bytes).is_none());
|
||||
|
||||
let mut stale = assembly();
|
||||
warm(&stale);
|
||||
stale.doc_mut().occurrences.first_mut().unwrap().transform[3][0] = 25.0;
|
||||
let bytes = save(&mut stale, "stale");
|
||||
assert!(solidcraft_io::read_design_geometry(&bytes).is_none(), "old placements must not be certified for a changed document");
|
||||
assert!(solidcraft_io::read_design_preview(&bytes).is_none());
|
||||
}
|
||||
Reference in New Issue
Block a user