Replace grid BG with dots

This commit is contained in:
2026-09-10 09:51:23 +02:00
parent fb7257d709
commit 2422e65b2b
2 changed files with 32 additions and 28 deletions
-2
View File
@@ -635,7 +635,6 @@ impl App {
self.view.zoom_to_selection(&self.doc.canvas); self.view.zoom_to_selection(&self.doc.canvas);
} }
ui.separator(); ui.separator();
ui.checkbox(&mut self.view.show_grid, "Show grid");
ui.checkbox(&mut self.view.snap_to_grid, "Snap to grid"); ui.checkbox(&mut self.view.snap_to_grid, "Snap to grid");
ui.checkbox(&mut self.show_inspector, "Inspector"); ui.checkbox(&mut self.show_inspector, "Inspector");
ui.checkbox(&mut self.dark_mode, "Dark mode"); ui.checkbox(&mut self.dark_mode, "Dark mode");
@@ -715,7 +714,6 @@ impl App {
ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| { ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| {
ui.toggle_value(&mut self.show_inspector, "Inspector"); ui.toggle_value(&mut self.show_inspector, "Inspector");
ui.toggle_value(&mut self.view.snap_to_grid, "Snap"); ui.toggle_value(&mut self.view.snap_to_grid, "Snap");
ui.toggle_value(&mut self.view.show_grid, "Grid");
let icon = if self.dark_mode { "Light theme" } else { "Dark theme" }; let icon = if self.dark_mode { "Light theme" } else { "Dark theme" };
if ui.button(icon).on_hover_text("Switch theme").clicked() { if ui.button(icon).on_hover_text("Switch theme").clicked() {
self.dark_mode = !self.dark_mode; self.dark_mode = !self.dark_mode;
+32 -26
View File
@@ -26,6 +26,12 @@ const MIN_ZOOM: f32 = 0.05;
const MAX_ZOOM: f32 = 3.0; const MAX_ZOOM: f32 = 3.0;
/// Spacing of the background grid, in canvas units. /// Spacing of the background grid, in canvas units.
const GRID: f32 = 20.0; const GRID: f32 = 20.0;
/// Every this many dots the background gets a heavier one.
const MAJOR: f32 = 5.0;
/// Radius of a background dot, in screen pixels.
const DOT_RADIUS: f32 = 0.9;
/// Radius of a heavier background dot, in screen pixels.
const DOT_RADIUS_MAJOR: f32 = 1.5;
/// How close the pointer has to be to an edge to hit it, in screen pixels. /// How close the pointer has to be to an edge to hit it, in screen pixels.
const EDGE_HIT_RADIUS: f32 = 8.0; const EDGE_HIT_RADIUS: f32 = 8.0;
/// Size of the resize/connect handles, in screen pixels. /// Size of the resize/connect handles, in screen pixels.
@@ -239,7 +245,6 @@ pub struct CanvasView {
hovered_node: Option<String>, hovered_node: Option<String>,
/// Node whose connect handles are on screen, held still during a drag. /// Node whose connect handles are on screen, held still during a drag.
connect_target: Option<String>, connect_target: Option<String>,
pub show_grid: bool,
pub snap_to_grid: bool, pub snap_to_grid: bool,
pub previews: PreviewCache, pub previews: PreviewCache,
/// How far each node's contents are scrolled, and how far they can go. /// How far each node's contents are scrolled, and how far they can go.
@@ -287,7 +292,6 @@ impl CanvasView {
hovered_edge: None, hovered_edge: None,
hovered_node: None, hovered_node: None,
connect_target: None, connect_target: None,
show_grid: true,
snap_to_grid: false, snap_to_grid: false,
previews: PreviewCache::default(), previews: PreviewCache::default(),
body_scroll: HashMap::new(), body_scroll: HashMap::new(),
@@ -615,9 +619,7 @@ impl CanvasView {
ui.ctx().set_transform_layer(layer, self.to_global); ui.ctx().set_transform_layer(layer, self.to_global);
if self.show_grid { self.paint_grid(&scene, visible, palette);
self.paint_grid(&scene, visible, palette);
}
// Groups are painted first so they cannot cover the edges, which in // Groups are painted first so they cannot cover the edges, which in
// turn run underneath the nodes they connect. // turn run underneath the nodes they connect.
let mut interactions = let mut interactions =
@@ -710,33 +712,37 @@ impl CanvasView {
// -- painting --------------------------------------------------------- // -- painting ---------------------------------------------------------
fn paint_grid(&self, ui: &egui::Ui, visible: Rect, palette: &Palette) { fn paint_grid(&self, ui: &egui::Ui, visible: Rect, palette: &Palette) {
// Below this the grid turns into noise, so it is skipped. // Zoomed out far enough the dots crowd into noise, so only every fifth
if self.to_global.scaling < 0.35 { // one is kept; below that they are dropped altogether.
let scale = self.to_global.scaling;
let step = if GRID * scale < 10.0 { GRID * MAJOR } else { GRID };
if step * scale < 6.0 {
return; return;
} }
let painter = ui.painter(); let painter = ui.painter();
let thin = Stroke::new(1.0 / self.to_global.scaling, palette.grid); // The dots keep the same size on screen whatever the zoom is.
let thick = Stroke::new(1.0 / self.to_global.scaling, palette.grid_strong); let radius = DOT_RADIUS / scale;
let radius_major = DOT_RADIUS_MAJOR / scale;
// A dot lands on a multiple of this wherever the paper is emphasised.
let major = GRID * MAJOR;
let on_major = |v: f32| (v / major).fract().abs() < 1e-3;
let first_x = (visible.left() / GRID).floor() * GRID; let first_x = (visible.left() / step).floor() * step;
let first_y = (visible.top() / step).floor() * step;
let mut x = first_x; let mut x = first_x;
while x <= visible.right() { while x <= visible.right() {
let stroke = if (x / (GRID * 5.0)).fract().abs() < 1e-3 { thick } else { thin }; let major_x = on_major(x);
painter.line_segment( let mut y = first_y;
[pos2(x, visible.top()), pos2(x, visible.bottom())], while y <= visible.bottom() {
stroke, let (radius, color) = if major_x && on_major(y) {
); (radius_major, palette.grid_strong)
x += GRID; } else {
} (radius, palette.grid)
let first_y = (visible.top() / GRID).floor() * GRID; };
let mut y = first_y; painter.circle_filled(pos2(x, y), radius, color);
while y <= visible.bottom() { y += step;
let stroke = if (y / (GRID * 5.0)).fract().abs() < 1e-3 { thick } else { thin }; }
painter.line_segment( x += step;
[pos2(visible.left(), y), pos2(visible.right(), y)],
stroke,
);
y += GRID;
} }
} }