fix: hide sheet viewport border and improve crossing selection

Two layout-related fixes:

1. Sheet viewport (id=1) was rendered as a grey rectangle border in
   paper-space layouts. It is the paper boundary, not a user viewport,
   and should not appear. Now filtered via is_content_viewport() before
   tessellation. The redundant id==1 color branch is removed.

2. Box crossing-selection (right-to-left drag) only detected wires whose
   vertex points fell inside the selection box. Large entities like viewport
   frames could be visually crossed without any corner inside the box and
   would not be selected. Added segment-box edge intersection tests so any
   wire segment that crosses the selection rectangle boundary is included.

Fixes part of #10

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
This commit is contained in:
Hakan SevenandClaude Sonnet 4.6 committed 2026-05-01 21:12:14 +03:00
1 parent c0ee0d6edc
commit ebef467720
2 files changed
+24 -4

No files matched your search

+18 -1
View File
@@ -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))
};
+6 -3
View File
@@ -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 {