git.lucas.co / cce-designer
graphic design tool
git clone https://git.lucas.co/cce-designer.git

commit6d31e7ed628b430d9068ec189f8f75f2f1d802cf
parent38b7d0b26c
authorLucas Galante <lsgalante12@gmail.com>
date2026-09-25 10:43
feat: a Show Point Markers switch in the viewport menu's points group

The existing toggle_point_markers command as a marked row directly above
Point Marker Size, so each switch in the group sits over its own size.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

 CLAUDE.md   |  3 ++-
 src/app.rs  |  6 ++++--
 src/main.rs | 37 +++++++++++++++++++++++++++++++++++--
 3 files changed, 41 insertions(+), 5 deletions(-)

diff --git a/CLAUDE.md b/CLAUDE.md
index d068df3..aefb128 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -1378,7 +1378,8 @@ multi-selection, so taking `Shift+L` now would have to be given back later.
 
 The viewport's right-click menu carries the DISPLAY MODE under Frame All
 and View 1:1, in three groups a separator apart — wireframe (switch,
-thickness), points (Show Points and the three size sliders), surface
+thickness), points (Show Points and Point Size, Show Point Markers and
+its size, Group Marker Scale — each switch over its own size), surface
 (shading, opacity,
 Show Occluded); `the_viewport_menu_groups_its_display_rows` holds the
 order. The rows: the Show Wireframe switch (its registry command), **Flat
diff --git a/src/app.rs b/src/app.rs
index 2b23afb..5f4df90 100644
--- a/src/app.rs
+++ b/src/app.rs
@@ -4463,8 +4463,9 @@ impl State {
 
     /// The viewport menu's rows and what each does, in groups a separator
     /// apart: framing; the WIREFRAME (its switch and thickness); the POINTS
-    /// (the Show Points switch, point size, point marker size, group marker
-    /// scale); the SURFACE
+    /// (the Show Points switch and point size, the Show Point Markers switch
+    /// and its size, group marker scale — each switch over its own size);
+    /// the SURFACE
     /// (flat or smooth shading as a radio pair, the polygon opacity, Show
     /// Occluded — the three that decide how the fill itself reads); then
     /// the editor pin. Split from the open so a test can read it. Marks are
@@ -4489,6 +4490,7 @@ impl State {
         row(&mut options, &mut actions, "-".into(), sep);
         row(&mut options, &mut actions, format!("{} {}", mark(self.render_points), label("toggle_render_points", "Show Points")), ViewportMenuAction::Command("toggle_render_points"));
         row(&mut options, &mut actions, "Point Size".into(), ViewportMenuAction::PointSizeSlider);
+        row(&mut options, &mut actions, format!("{} {}", mark(self.show_point_markers), label("toggle_point_markers", "Show Point Markers")), ViewportMenuAction::Command("toggle_point_markers"));
         row(&mut options, &mut actions, "Point Marker Size".into(), ViewportMenuAction::PointMarkerSizeSlider);
         row(&mut options, &mut actions, "Group Marker Scale".into(), ViewportMenuAction::GroupMarkerScaleSlider);
 
diff --git a/src/main.rs b/src/main.rs
index c2a7813..5cebea9 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1660,7 +1660,13 @@ mod tests {
         assert_eq!(groups[1], vec![A::Command("toggle_wireframe"), A::WireThicknessSlider]);
         assert_eq!(
             groups[2],
-            vec![A::Command("toggle_render_points"), A::PointSizeSlider, A::PointMarkerSizeSlider, A::GroupMarkerScaleSlider]
+            vec![
+                A::Command("toggle_render_points"),
+                A::PointSizeSlider,
+                A::Command("toggle_point_markers"),
+                A::PointMarkerSizeSlider,
+                A::GroupMarkerScaleSlider,
+            ]
         );
         assert_eq!(
             groups[3],
@@ -1670,6 +1676,33 @@ mod tests {
         assert!(options.iter().zip(&actions).all(|(o, a)| (o == "-") == (*a == A::Separator)), "separator rows line up");
     }
 
+    /// Show Point Markers is a switch in the Points group, over its own
+    /// size slider, marked from the live flag; the row runs the command,
+    /// which rebuilds the overlay (and keeps the positions the size slider
+    /// re-sizes from).
+    #[test]
+    fn the_viewport_menu_toggles_show_point_markers() {
+        use crate::app::ViewportMenuAction as A;
+        let mut state = State::new(false);
+        state.show_point_markers = false;
+        state.rebuild_scene_geometry();
+        let row = |state: &State| {
+            let (options, actions) = state.viewport_menu_rows();
+            let i = actions.iter().position(|a| *a == A::Command("toggle_point_markers")).expect("a Show Point Markers row");
+            options[i].clone()
+        };
+        let label = crate::command::by_id("toggle_point_markers").unwrap().label;
+        assert_eq!(row(&state), format!("○ {label}"));
+        assert!(state.overlay_marker_verts.is_empty());
+        state.run_viewport_menu_action(A::Command("toggle_point_markers"));
+        assert!(state.show_point_markers);
+        assert_eq!(row(&state), format!("● {label}"));
+        assert!(!state.overlay_marker_verts.is_empty(), "the overlay was built");
+        assert!(!state.overlay_marker_points.is_empty(), "and its positions kept for re-sizing");
+        let kdl = fs::read_to_string(crate::app::DesignSettings::file_path()).expect("saved");
+        assert!(crate::app::DesignSettings::from_kdl_str(&kdl).viewport.show_point_markers, "persisted");
+    }
+
     /// Show Points heads the Points group as a switch over the Render
     /// points, marked from the live flag, and the row runs its command.
     #[test]
@@ -1799,7 +1832,7 @@ mod tests {
         state.cursor_y = 200.0;
         state.open_viewport_context_menu();
         let i = state.viewport_menu_actions.iter().position(|a| *a == A::PointMarkerSizeSlider).expect("a Point Marker Size row");
-        assert_eq!(state.viewport_menu_actions[i - 1], A::PointSizeSlider, "it sits under Point Size");
+        assert_eq!(state.viewport_menu_actions[i - 1], A::Command("toggle_point_markers"), "it sits under its switch");
         let sl = context_menu::slider(i).expect("a slider");
         assert_eq!((sl.min, sl.max, sl.step), (0.005, 0.1, 0.005));
         assert!((sl.value - 0.02).abs() < 1e-6);