diff --git a/src/scene/hit_test.rs b/src/scene/hit_test.rs index 9a45660e5..02a62aa0c 100644 --- a/src/scene/hit_test.rs +++ b/src/scene/hit_test.rs @@ -57,7 +57,9 @@ pub fn click_hit<'a>( /// - **Window mode** (`crossing = false`, left→right drag): /// ALL projected points must lie inside the box. /// - **Crossing mode** (`crossing = true`, right→left drag): -/// ANY projected point inside the box is sufficient. +/// ANY projected point inside the box, OR any wire segment crosses the box +/// boundary (so large entities like viewport frames are caught even when +/// no corner falls inside the selection rectangle). pub fn box_hit<'a>( corner_a: Point, corner_b: Point, @@ -78,6 +80,12 @@ pub fn box_hit<'a>( let inside = |sp: Point| sp.x >= min_x && sp.x <= max_x && sp.y >= min_y && sp.y <= max_y; + // Box corners for segment-intersection tests (crossing mode only). + let box_tl = Point { x: min_x, y: min_y }; + let box_tr = Point { x: max_x, y: min_y }; + let box_bl = Point { x: min_x, y: max_y }; + let box_br = Point { x: max_x, y: max_y }; + wires .iter() .filter_map(|wire| { @@ -92,7 +100,16 @@ pub fn box_hit<'a>( .collect(); let hit = if crossing { + // A wire is hit when any vertex is inside the box OR any of its + // segments crosses one of the four box edges. screen.iter().any(|&sp| inside(sp)) + || screen.windows(2).any(|seg| { + let (a, b) = (seg[0], seg[1]); + segments_intersect(a, b, box_tl, box_tr) + || segments_intersect(a, b, box_tr, box_br) + || segments_intersect(a, b, box_br, box_bl) + || segments_intersect(a, b, box_bl, box_tl) + }) } else { screen.iter().all(|&sp| inside(sp)) }; diff --git a/src/scene/mod.rs b/src/scene/mod.rs index e4cb4c01e..1fc10ccb1 100644 --- a/src/scene/mod.rs +++ b/src/scene/mod.rs @@ -3084,12 +3084,15 @@ fn tessellate_entity( let sel = selected.contains(&h); if let EntityType::Viewport(vp) = e { + // The sheet viewport (overall/id=1) is never shown — it represents the + // paper boundary, not a user-defined content window. + if !Scene::is_content_viewport(vp) { + return vec![]; + } let is_active = active_viewport == Some(h); let is_locked = vp.status.locked; - let color = if sel && vp.id != 1 { + let color = if sel { [1.0, 1.0, 1.0, 1.0] - } else if vp.id == 1 { - [0.40, 0.40, 0.40, 1.0] } else if is_active { [1.0, 0.90, 0.20, 1.0] } else if is_locked {