From 9e19a10b298d4d5e81ecf6d6aa161b6b66059440 Mon Sep 17 00:00:00 2001 From: Valentin Klein Date: Sun, 11 Oct 2026 00:43:15 +0200 Subject: [PATCH] Layouts: a viewport on a frozen layer hides its contents (fixes #395) (#396) Freezing a viewport's own layer hid only its border; the model space seen through it still showed on screen and in plots. As in AutoCAD, a frozen viewport layer now hides the contents too, while turning the layer off still hides only the border. The check is in the shared layout path, so display, PDF/SVG/PNG export and plotting agree. Co-authored-by: Claude Opus 5.5 --- crates/render/src/lib.rs | 4 ++ crates/render/tests/viewport_frozen_layer.rs | 44 ++++++++++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 crates/render/tests/viewport_frozen_layer.rs diff --git a/crates/render/src/lib.rs b/crates/render/src/lib.rs index b499aa6..84e2bd7 100644 --- a/crates/render/src/lib.rs +++ b/crates/render/src/lib.rs @@ -316,6 +316,10 @@ fn viewport(b: &mut Builder, d: &Drawing, e: &Entity, vp: &cadcraft_doc::Viewpor if vp.id == 1 || !e.common.visible { return; } + // The viewport's layer frozen hides its contents too (layer off hides only the border). + if d.layer(&e.common.layer).is_some_and(|l| l.frozen) { + return; + } // Border (on the viewport's layer; layer off hides only the border). entity(b, &top_ctx(d, Mat3::IDENTITY, e.handle, &[], &[]), e); if b.list.expanded >= MAX_BLOCK_EXPANSION { diff --git a/crates/render/tests/viewport_frozen_layer.rs b/crates/render/tests/viewport_frozen_layer.rs new file mode 100644 index 0000000..9198b26 --- /dev/null +++ b/crates/render/tests/viewport_frozen_layer.rs @@ -0,0 +1,44 @@ +//! A layout viewport whose own layer is frozen shows neither its border nor its contents, on +//! screen and when plotting; turned off, the layer hides only the border (issue #395). + +use cadcraft_doc::{Circle, Common, Drawing, EntityKind, Space, Viewport}; +use cadcraft_geom::{Vec2, Vec3}; +use cadcraft_render::{DisplayList, Options, VIEWPORT_CONTENT, build, build_plot}; + +fn drawing() -> Drawing { + let mut d = Drawing::new_imperial(); + d.add(&Space::Model, Common::default(), EntityKind::Circle(Circle { center: Vec3::ZERO, radius: 5.0 })).unwrap(); + d.ensure_layer("VPORTS"); + let vp = Viewport { + center: Vec3::new(5.0, 4.0, 0.0), + width: 8.0, + height: 6.0, + view_center: Vec2::ZERO, + view_height: 12.0, + id: 2, + locked: false, + frozen_layers: Vec::new(), + layer_colors: Vec::new(), + }; + d.add(&Space::Paper("Layout1".into()), Common { layer: "VPORTS".into(), ..Default::default() }, EntityKind::Viewport(vp)).unwrap(); + d +} + +/// (contents drawn, border drawn) on screen and in a plot. +fn shown(d: &Drawing) -> [(bool, bool); 2] { + let space = Space::Paper("Layout1".into()); + let parts = |l: DisplayList| (l.prims.iter().any(|p| p.handle == VIEWPORT_CONTENT), l.prims.iter().any(|p| p.handle != VIEWPORT_CONTENT)); + [parts(build(d, &space, &Options::default())), parts(build_plot(d, &space, &Options::default()))] +} + +#[test] +fn frozen_viewport_layer_hides_the_contents_off_only_the_border() { + let mut d = drawing(); + assert_eq!(shown(&d), [(true, true); 2]); + d.layer_mut("VPORTS").unwrap().on = false; + assert_eq!(shown(&d), [(true, false); 2], "off: contents stay, border hidden"); + let l = d.layer_mut("VPORTS").unwrap(); + l.on = true; + l.frozen = true; + assert_eq!(shown(&d), [(false, false); 2], "frozen: contents hidden too"); +}