Fix #321: the perspective grid hides while a perspective tool is chosen

The grid was drawn whenever its `visible` flag was set or a perspective
tool was active, and choosing the Perspective Grid tool (Shift+P) didn't set
the flag. So with the tool chosen, View > Perspective Grid > Hide Grid
(perspective.grid.show) turned the hidden flag on instead of off and the
grid stayed on screen however it was toggled.

Choosing a perspective tool now shows the grid (sets `visible`, view state,
no undo step), and the grid, its widget and the Perspective Grid tool's
handles are drawn only while it is visible. Hide Grid hides it with the
tool still chosen; choosing the tool again shows it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
EthanSuquet
2026-10-08 03:27:36 +07:00
committed by bflatastic
co-authored by Claude Opus 5.5
parent f17c34a067
commit 4a676c4d5e
7 changed files with 48 additions and 21 deletions
+2 -2
View File
@@ -452,7 +452,7 @@ impl Session {
let w = self.prefs.perspective_widget;
let st = self.active().filter(|_| w.show)?;
let g = PerspectiveGrid::current(&st.doc);
if !g.shown(self.tool_id()) {
if !g.visible {
return None;
}
let place = WidgetPlace { screen: view.screen.as_ref(), corner: w.position };
@@ -476,6 +476,6 @@ impl Session {
ToolKey::Digit(4) => Plane::None,
_ => return None,
};
PerspectiveGrid::current(&self.active()?.doc).shown(self.tool_id()).then_some(plane)
PerspectiveGrid::current(&self.active()?.doc).visible.then_some(plane)
}
}
+20
View File
@@ -247,6 +247,26 @@ fn grid_show_and_plane_are_view_state() {
assert!(s.overlays(ViewInfo::default()).len() > 20);
}
#[test]
fn the_grid_hides_while_a_perspective_tool_is_chosen() {
// #321: choosing the Perspective Grid tool showed the grid for good.
let mut s = session();
let v = ViewInfo::default();
for tool in ["perspectiveGrid", "perspectiveSelection"] {
s.select_tool(tool, v).unwrap();
assert!(s.overlays(v).len() > 20, "{tool}");
let n = undo_len(&s);
assert_eq!(s.execute("perspective.grid.show", &json!({})).unwrap(), json!({"visible": false}));
assert!(s.overlays(v).is_empty(), "{tool}: the hidden grid still draws");
assert_eq!(undo_len(&s), n);
// Choosing the tool again shows it again.
s.select_tool(tool, v).unwrap();
assert!(s.overlays(v).len() > 20, "{tool}");
s.execute("perspective.grid.show", &json!({"visible": false})).unwrap();
s.select_tool("selection", v).unwrap();
}
}
#[test]
fn grid_preset_and_set_are_undoable() {
let mut s = session();
+1 -1
View File
@@ -401,7 +401,7 @@ fn the_plane_widget_stays_on_screen_and_takes_clicks_with_any_tool() {
assert_eq!(grid(&s).plane, Plane::Right);
assert!(s.doc().unwrap().selection.is_empty());
assert_eq!(undo_len(&s), n);
// While the grid is hidden only the perspective tools show it (and take its clicks).
// A hidden grid takes no clicks; choosing a perspective tool shows it.
run(&mut s, "perspective.grid.show", json!({"visible": false}));
let q = face(&s, view, WidgetCorner::TopLeft, Plane::Ground);
click(&mut s, q, view);
+8 -1
View File
@@ -58,6 +58,13 @@ impl Session {
/// Switch tools (finishing any pending tool work first).
pub fn select_tool(&mut self, id: &str, view: ViewInfo) -> Result<()> {
// Choosing a perspective tool shows the document's perspective grid; Hide Grid hides it
// again, the tool staying chosen.
if matches!(id, "perspectiveGrid" | "perspectiveSelection")
&& self.active().is_some_and(|d| !vectorcraft_tools::distort::perspective::PerspectiveGrid::current(&d.doc).visible)
{
crate::cmd::distortcmds::silent(self, |g| g.visible = true)?;
}
if self.tool.id() == id {
return Ok(());
}
@@ -247,7 +254,7 @@ impl Session {
if let Some(d) = self.active() {
let w = self.prefs.perspective_widget;
let place = w.show.then_some(WidgetPlace { screen: view.screen.as_ref(), corner: w.position });
v.splice(0..0, vectorcraft_tools::distort::perspective::grid_overlays_in(&d.doc, 1.0 / view.zoom.max(1e-9), self.tool.id(), place));
v.splice(0..0, vectorcraft_tools::distort::perspective::grid_overlays_in(&d.doc, 1.0 / view.zoom.max(1e-9), place));
}
v
}