fix(grid): independent, clipped grid per viewport

Grid (and grid-snap) state was shared through the global show_grid flag, so
toggling it in model space also turned it on in paper space, and a floating
viewport's grid painted across the whole paper — and beyond the 3-D view when
zoomed in.

- Store grid/snap per view: a model tile in model space, the active floating
  viewport or the layout's sheet viewport in paper space, round-tripped via the
  viewport status flags.
- adopt_view_display on layout switch and viewport enter/exit so the live
  toggle follows the view you are in.
- Render one grid per view (paper_viewport_grid_views): the sheet over the
  paper, each floating viewport clipped to its screen rectangle.
- Clamp the grid clip to the widget so an overflowing viewport rectangle never
  paints grid outside the 3-D view.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
Hakan SevenandClaude Opus 4.8 committed 2026-06-22 00:18:01 +03:00
1 parent ba834fb166
commit 26479b6faa
4 files changed
+122 -35

No files matched your search

+9 -1
View File
@@ -5589,6 +5589,10 @@ impl OpenCADStudio {
self.tabs[i].scene.deselect_all();
self.tabs[i].scene.restore_saved_camera();
self.tabs[i].last_synced_camera_gen = self.tabs[i].scene.camera_generation;
// Grid/snap are per-view: load the layout we just entered (its
// sheet viewport in paper space, the model tile in model space)
// so model and each layout keep independent grid state.
self.adopt_view_display(i);
// Paper-space tools live in the right-edge side toolbar now, so
// entering/leaving a layout no longer hijacks the ribbon tab.
let _ = going_to_paper;
@@ -6101,6 +6105,8 @@ impl OpenCADStudio {
// Clear paper-space selection before entering model space.
self.tabs[i].scene.deselect_all();
self.tabs[i].scene.active_viewport = Some(handle);
// Grid/snap follow the entered viewport.
self.adopt_view_display(i);
self.refresh_properties();
self.command_line.push_output("MSPACE");
Task::none()
@@ -6110,8 +6116,10 @@ impl OpenCADStudio {
let i = self.active_tab;
// Clear model-space selection before returning to paper space.
self.tabs[i].scene.deselect_all();
self.refresh_properties();
self.tabs[i].scene.active_viewport = None;
// Grid/snap return to the paper sheet's own state.
self.adopt_view_display(i);
self.refresh_properties();
self.command_line.push_output("PSPACE");
Task::none()
}
+17 -25
View File
@@ -133,33 +133,25 @@ impl OpenCADStudio {
// the correct place and scale.
let vp_bounds = tab.scene.active_model_tile_bounds(vw, vh);
// Model layout: one grid per tile that has grid display on, drawn
// in its own bounds + camera so panes are independent and never
// flicker on hover. Paper layout: a single grid gated by show_grid.
let grid: Vec<overlay::GridParams> = if !is_paper {
tab.scene
.model_tile_grid_views(vw, vh)
.into_iter()
.map(|(bounds, cam)| {
let plane = grid_plane_from_camera(cam.pitch, cam.yaw);
overlay::GridParams {
view_proj: cam.view_proj(bounds),
bounds,
plane,
}
})
.collect()
} else if self.show_grid {
let cam = tab.scene.camera.borrow();
let plane = grid_plane_from_camera(cam.pitch, cam.yaw);
vec![overlay::GridParams {
view_proj: cam.view_proj(vp_bounds),
bounds: vp_bounds,
plane,
}]
// Each view draws its own grid, clipped to its own bounds, so they
// stay independent: model tiles in model space; the sheet plus each
// floating viewport (clipped to its rectangle) in paper space.
let grid_views = if !is_paper {
tab.scene.model_tile_grid_views(vw, vh)
} else {
Vec::new()
tab.scene.paper_viewport_grid_views(vw, vh)
};
let grid: Vec<overlay::GridParams> = grid_views
.into_iter()
.map(|(bounds, cam)| {
let plane = grid_plane_from_camera(cam.pitch, cam.yaw);
overlay::GridParams {
view_proj: cam.view_proj(bounds),
bounds,
plane,
}
})
.collect();
let ucs_icon = if self.show_ucs_icon && !is_paper {
let cam = tab.scene.camera.borrow();