Merge pull request #1015: The grid overlay was rebuilding the whole drawing

This commit is contained in:
Hakan Seven committed 2026-09-05 19:28:30 +03:00
commit 52d9c047d9
3 files changed
+208 -29

No files matched your search

+68 -3
View File
@@ -197,6 +197,20 @@ impl OpenCADStudio {
/// `view` so the single-window web build can render it directly, bypassing
/// the multi-window id dispatch above (the web build has no extra windows).
pub fn view_main(&self) -> Element<'_, Message> {
// Section marks for `view-detail`. A closure over a RefCell rather
// than one binding per section: two of these sections sit inside a
// nested block and would otherwise be out of scope at the report.
let view_t0 = crate::perf::enabled().then(iced::time::Instant::now);
let view_marks: std::cell::RefCell<Vec<(&'static str, f64)>> =
std::cell::RefCell::new(Vec::with_capacity(8));
let mark = |name: &'static str| {
if let Some(t0) = view_t0 {
view_marks
.borrow_mut()
.push((name, t0.elapsed().as_secs_f64() * 1000.0));
}
};
let i = self.active_tab;
let tab = &self.tabs[i];
let thumbnail_capture_clean = self.thumbnail_capture_clean;
@@ -257,6 +271,7 @@ impl OpenCADStudio {
// the same shader as model space: a full-canvas top-locked "sheet"
// viewport draws the layout's own geometry (white sheet + entities +
// borders) and the floating content viewports blit on top.
mark("viewport_3d");
let viewport_3d: Element<'_, Message> = if tab.is_start {
start_page_view(
&self.patrons,
@@ -334,6 +349,7 @@ impl OpenCADStudio {
// the shader pane_grid (same `model_panes` → identical layout). Layered
// above the crosshair overlay so it actually receives mouse events, and
// it owns the divider resize. Only built for the Model layout.
mark("model_input");
let model_input_layer: Option<Element<'_, Message>> = if is_paper || tab.is_start {
None
} else {
@@ -351,6 +367,7 @@ impl OpenCADStudio {
)
};
mark("grid");
let grid_overlay = {
let (vw, vh) = tab.scene.selection.borrow().vp_size;
let model_basis = {
@@ -365,9 +382,15 @@ impl OpenCADStudio {
);
(o, (ux.as_vec3(), uy.as_vec3(), uz.as_vec3()))
};
let grid: Vec<crate::ui::overlay::GridParams> = tab
.scene
.grid_views(vw, vh)
// The first paper frame spends seconds in this block and `grid`
// alone cannot say which part. Reported only when it costs
// something, so ordinary frames stay quiet.
let t_grid = crate::perf::enabled().then(iced::time::Instant::now);
let views = tab.scene.grid_views(vw, vh);
let views_ms = crate::perf::elapsed_ms(t_grid);
let view_count = views.len();
let t_params = crate::perf::enabled().then(iced::time::Instant::now);
let grid: Vec<crate::ui::overlay::GridParams> = views
.into_iter()
.map(|(bounds, cam, handle)| {
let (origin, mut axes): (glam::DVec3, _) = if is_paper {
@@ -411,7 +434,16 @@ impl OpenCADStudio {
}
})
.collect();
let params_ms = crate::perf::elapsed_ms(t_params);
let t_bg = crate::perf::enabled().then(iced::time::Instant::now);
let bg = crosshair_background(tab, is_paper);
let bg_ms = crate::perf::elapsed_ms(t_bg);
if views_ms + params_ms + bg_ms >= 1.0 {
crate::perf_record!(
"[perf] grid-detail views={views_ms:.1}ms params={params_ms:.1}ms \
bg={bg_ms:.1}ms n={view_count}"
);
}
let bg_lum = 0.299 * bg[0] + 0.587 * bg[1] + 0.114 * bg[2];
let grid_style = crate::ui::overlay::GridStyle {
opacity: self.model_space.grid_opacity,
@@ -420,6 +452,7 @@ impl OpenCADStudio {
crate::ui::overlay::grid_overlay(grid, grid_style)
};
mark("selection_overlay");
let selection_overlay = {
// Hold a single `Ref<'_, SelectionState>` for the whole overlay
// block. The `vp_size` and `last_move_pos` reads below become
@@ -790,6 +823,7 @@ impl OpenCADStudio {
)
};
mark("viewport_mouse");
let viewport_mouse = mouse_area(container(
iced::widget::Space::new().width(Fill).height(Fill),
))
@@ -935,6 +969,7 @@ impl OpenCADStudio {
None
};
mark("viewport_stack");
let mut viewport_stack = if tab.is_start {
// Start tab: only the welcome widget over a flat background.
// Skip every drawing-only overlay (selection markers, snap info,
@@ -1053,6 +1088,7 @@ impl OpenCADStudio {
// both layered ABOVE the viewport mouse_area so they receive
// clicks (the shader viewport sits below it). Positioned with
// leading Spaces sized to the viewport's screen rectangle.
mark("active_vp_rect");
let active_vp_rect: Option<(acadrust::Handle, iced::Rectangle)> =
if is_paper && !tab.is_start {
tab.scene.active_viewport.and_then(|h| {
@@ -1383,6 +1419,7 @@ impl OpenCADStudio {
}
// Reserve the overlaid command line when placing cursor-anchored panels.
mark("chrome");
let command_line_inset = if self.command_line.history_open {
self.command_line.history_height.clamp(
crate::ui::command_line::HISTORY_HEIGHT_MIN,
@@ -2102,6 +2139,34 @@ impl OpenCADStudio {
};
// Shared CAD colour picker. Indexed ACI colours use OpenCADStudio's own
// dialog; True Color keeps the existing iced_aw gradient picker.
// Which part of the widget tree the frame went into. Reported as a
// breakdown rather than one number, because a first switch to a paper
// layout spends seconds here and `view` alone cannot say where.
if let Some(t0) = view_t0 {
mark("end");
let total = t0.elapsed().as_secs_f64() * 1000.0;
if total >= 1.0 {
let marks = view_marks.borrow();
// A mark opens a section; the following mark closes it, so a
// section's cost is the gap to its successor. The first mark
// is preceded by the preamble, reported as `head`.
let mut detail = String::new();
if let Some((_, first)) = marks.first() {
let _ = std::fmt::Write::write_fmt(
&mut detail,
format_args!(" head={first:.1}"),
);
}
for pair in marks.windows(2) {
let _ = std::fmt::Write::write_fmt(
&mut detail,
format_args!(" {}={:.1}", pair[0].0, pair[1].1 - pair[0].1),
);
}
crate::perf_record!("[perf] view-detail total={total:.1}ms{detail}");
}
}
if let Some((_, current)) = self.color_pick_target.as_ref() {
match self.color_picker_tab {
super::ColorPickerTab::Index => {