fix(render): compose PLOTSTYLE wire-fill depth like the wire pipeline

When a display plot style maps an ACI to a fill pattern, wire fill
triangles are re-emitted as PLOTSTYLE hatches. Those took
depth_override raw — a per-block child label for block wires and 0.0
for top-level ones — while everything else in the hatch/wipeout pass
sorts at the composed depths[insert] + label * half. The fill could
land outside its host's band and get buried under its own block's
masks (same shape as the block-text bug).

Both the display and PDF paths now travel through wire_draw_depth /
the PlotWire's composed depth, and the display cache key rides the
depth generation so a DRAWORDER edit re-ranks the fills without
needing a wire rebuild.
This commit is contained in:
huanld committed 2026-09-18 08:38:35 +07:00
1 parent 454d99b1d3
commit 36d5c4db79
3 files changed
+22 -3

No files matched your search

+7 -1
View File
@@ -605,6 +605,7 @@ fn append_pdf_page(
emit_wire_fills(
&mut ops,
std::slice::from_ref(&wire.wire),
wire.draw_depth,
ox,
oy,
plot_style,
@@ -1036,6 +1037,7 @@ fn plotted_color(
fn emit_wire_fills(
ops: &mut Vec<Op>,
wires: &[WireModel],
wire_depth: f32,
ox: f64,
oy: f64,
plot_style: Option<&PlotStyleTable>,
@@ -1090,7 +1092,11 @@ fn emit_wire_fills(
line_weight_px: wire.line_weight_px,
angle_offset: 0.0,
scale: 1.0 / scale.max(1.0e-6),
draw_depth: wire.depth_override.unwrap_or(0.0),
// The host wire's composed draw depth (PlotWire carries
// wire_draw_depth). depth_override alone is a per-block
// child label and would sort the fill outside its block's
// band; keep the pattern fill co-sorted with its wire.
draw_depth: wire_depth,
};
emit_hatch(
ops,
+2 -1
View File
@@ -2204,7 +2204,8 @@ pub struct Scene {
RefCell<HashMap<(String, String), Option<Arc<crate::io::plot_style::PlotStyleTable>>>>,
styled_wire_cache: RefCell<HashMap<(u64, String), (u64, Arc<Vec<WireModel>>)>>,
styled_hatch_cache: RefCell<HashMap<(u64, usize, usize, String, u32), Arc<Vec<HatchModel>>>>,
styled_wire_fill_cache: RefCell<HashMap<(u64, String, u32), Arc<Vec<HatchModel>>>>,
styled_wire_fill_cache:
RefCell<HashMap<(u64, String, u32, u64), Arc<Vec<HatchModel>>>>,
/// Per-viewport projected wire cache for paper-space content viewports.
/// Stores projected + clipped wires in paper-space coordinates.
/// Maps vp_handle → (geometry_epoch, Vec<WireModel>).
+13 -1
View File
@@ -3102,14 +3102,19 @@ impl Scene {
let Some(style) = self.display_plot_style() else {
return None;
};
// Depth generation rides in the key: the fills below compose their
// depth from the live depth map, which can move independently of the
// wire set (a DRAWORDER edit re-ranks without retessellating).
let key = (
source_gen,
style.name.to_ascii_lowercase(),
pattern_scale.to_bits(),
self.draw_depth_generation(),
);
if let Some(hatches) = self.styled_wire_fill_cache.borrow().get(&key) {
return Some(Arc::clone(hatches));
}
let depths = self.draw_depth_map();
let mut hatches = Vec::new();
for wire in wires.iter().filter(|wire| wire.fill_is_2d_solid && wire.aci > 0) {
let Some(pattern) = style
@@ -3161,7 +3166,14 @@ impl Scene {
line_weight_px,
angle_offset: 0.0,
scale: pattern_scale,
draw_depth: wire.depth_override.unwrap_or(0.0),
// Compose against the scene graph exactly like the wire
// pipeline does. The raw depth_override is a per-block
// child label (or None for top-level wires) — either way
// it would place the fill outside its host's depth band
// and let sibling wipes/masks bury it.
draw_depth: crate::scene::pipeline::wire_gpu::wire_draw_depth(
wire, &depths,
),
});
}
}