diff --git a/crates/engine/src/cmd/buildcmds/trace.rs b/crates/engine/src/cmd/buildcmds/trace.rs index 8d72568e8..308e300ec 100644 --- a/crates/engine/src/cmd/buildcmds/trace.rs +++ b/crates/engine/src/cmd/buildcmds/trace.rs @@ -377,8 +377,11 @@ fn grouped(d: &mut Document, nodes: Vec, parents: &[Option]) -> Vec struct TraceInputs { target: NodeId, image: Box, - /// The settings traced with, as JSON, the library's colours in. + /// The settings traced with, as JSON. params: Value, + /// Document Library: the library's colours, which the JSON leaves out + /// ([`tr::TraceParams::swatches`]). + swatches: Vec<[u8; 3]>, } /// What `imageTrace.make` and `imageTrace.makeAndExpand` take from the session before they trace. @@ -431,7 +434,7 @@ fn prepare(s: &Session, c: &str, p: &Value) -> Result { let bytes = Arc::clone(&blob.bytes); let library = trace_library(c, s, &mut params)?; let traced_with = serde_json::to_value(¶ms).map_err(|e| EngineError::Other(e.to_string()))?; - let inputs = TraceInputs { target, image, params: traced_with }; + let inputs = TraceInputs { target, image, params: traced_with, swatches: params.swatches.clone() }; Ok(Prepared { inputs, trace: params, view, params_json, preset_label, library, bytes }) } @@ -544,7 +547,7 @@ pub(super) fn trace_make(s: &mut Session, p: &Value, expand: bool) -> Result traced, _ => trace_now(&inputs, &trace, &bytes, &|_, _| true)?, }; - let TraceInputs { target, image: img, params: _ } = inputs; + let TraceInputs { target, image: img, .. } = inputs; let warnings = trace_warnings((img.width, img.height), raster, res.worked_at); // Pixel space of the decoded raster → the image object's pixel space → document. let sx = img.width.max(1) as f64 / raster.0.max(1) as f64; diff --git a/crates/engine/src/tests/build.rs b/crates/engine/src/tests/build.rs index 5c7baad6f..cb4c2d018 100644 --- a/crates/engine/src/tests/build.rs +++ b/crates/engine/src/tests/build.rs @@ -2768,6 +2768,21 @@ fn a_trace_run_hands_its_trace_to_the_command() { assert!((bb.center().x - 160.0).abs() < 1.5, "traced where the image is now: {bb:?}"); } +/// A Document Library trace made away from its command no longer applies once the library's +/// colours change: the settings' JSON leaves them out (#4605 review). +#[test] +fn a_trace_run_needs_the_library_colours_it_traced_with() { + let mut s = session(); + image_doc(&mut s); + let p = json!({"preset": "6 Colors", "params": {"palette": "documentLibrary"}}); + let run = cmd::TraceRun::prepare(&s, "imageTrace.make", &p).unwrap(); + assert!(run.current(&s)); + let swatch = |w: &&vectorcraft_color::Swatch| matches!(w.paint, Paint::Solid { .. }) && !w.name.starts_with('['); + let name = s.doc().unwrap().doc.swatches_iter().find(swatch).map(|w| w.name.clone()).unwrap(); + s.execute("swatch.edit", &json!({"name": name, "color": "#123456"})).unwrap(); + assert!(!run.current(&s), "{name} changed"); +} + /// Shapes: the disc of the test image comes out as a live ellipse where the image lies, the same /// circle as its traced path; without the option it is a plain path. #[test] diff --git a/crates/ui-egui/src/app.rs b/crates/ui-egui/src/app.rs index 5a46f6157..6e2527fb6 100644 --- a/crates/ui-egui/src/app.rs +++ b/crates/ui-egui/src/app.rs @@ -298,6 +298,7 @@ impl VectorcraftApp { || !self.opening.pending.is_empty() || !self.plugin_runs.running.is_empty() || !self.placing.pending.is_empty() + || !self.trace_runs.running.is_empty() { // Keep the status bar's progress moving and pick the result up when it arrives. ctx.request_repaint_after(std::time::Duration::from_millis(100));