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

commit041a49e6e08effa9ebfad82d518aece0b2889875
parent1ed0801533
authorLucas Galante <lsgalante12@gmail.com>
date2026-09-29 19:10
refactor: the Custom preset is retired

It was the template's defaults with their numbers scaled by half again:
a stand-in that stored nothing and read nothing of the node's own
values. Reset Parameters is what is left of the two menus.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

 CLAUDE.md      | 26 ++++++++++++++------------
 src/app.rs     | 40 ++++++----------------------------------
 src/command.rs |  6 +++---
 src/main.rs    |  9 ++++-----
 src/window.rs  |  8 +++-----
 5 files changed, 30 insertions(+), 59 deletions(-)

diff --git a/CLAUDE.md b/CLAUDE.md
index 15544f4..db197bc 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -112,21 +112,23 @@ where it used to be accepted and, the item lists having drifted from the
 matches, ran the wrong item (the header's Save opened a project).
 `a_menubar_click_is_dispatched_or_refused` is the test.
 
-**The cameras and the presets are commands too** (the same day), so the
-palette reaches them and a chord can: `next_camera` / `previous_camera`
-step through `State::camera_names` (the Default Camera, then the level's
-camera nodes) and wrap, `default_camera` goes back to it, and each camera
-NODE is a row of the palette — `Camera: camera1`, id under
+**The cameras and the parameter reset are commands too** (the same day),
+so the palette reaches them and a chord can: `next_camera` /
+`previous_camera` step through `State::camera_names` (the Default Camera,
+then the level's camera nodes) and wrap, `default_camera` goes back to it,
+and each camera NODE is a row of the palette — `Camera: camera1`, id under
 `CAMERA_ROW_PREFIX`, ranked among the commands as the viewport's, with
 `active` in the chord column of the one in use. They are rows and not
 registry commands because they are nodes, as the recent projects are paths.
-`State::choose_camera` is the one entry. `reset_parameters` and
-`custom_preset` run `State::apply_param_preset` on the node the params pane
-shows, from `template_default` — so a child inside a subnet instance resets
-to the subnet template's override, where the menubar's arm looked the
-template up by node type and missed it. All five ship unbound. The three
-menubar menus run the same functions.
-`the_cameras_and_the_presets_are_commands` is the test.
+`State::choose_camera` is the one entry. `reset_parameters` runs
+`State::reset_parameters` on the node the params pane shows, from
+`template_default` — so a child inside a subnet instance resets to the
+subnet template's override, where the menubar's arm looked the template up
+by node type and missed it. All four ship unbound, and the three menubar
+menus run the same functions. **The Custom preset is retired**: it was the
+template's defaults with their numbers scaled by half again, a stand-in
+that stored nothing and read nothing of the node's own values.
+`the_cameras_and_the_parameter_reset_are_commands` is the test.
 
 (The former bespoke HTTP API on port 3000 was retired in favor of this;
 app-internal threads like the cce-files choosers now return results via
diff --git a/src/app.rs b/src/app.rs
index b33080c..f6e3b2d 100644
--- a/src/app.rs
+++ b/src/app.rs
@@ -3097,9 +3097,8 @@ impl State {
 
     /// Set every parameter of the node the params pane shows back to its
     /// template's default — the text AND whether it is an expression, so a
-    /// default that is a reference is one again. `custom` is the menubar's
-    /// other preset: the defaults with their numbers half as large again.
-    pub fn apply_param_preset(&mut self, custom: bool) -> bool {
+    /// default that is a reference is one again.
+    pub fn reset_parameters(&mut self) -> bool {
         let Some(slot) = self.param_editor_selected() else {
             self.update_status_text("No node selected");
             return false;
@@ -3121,41 +3120,17 @@ impl State {
             self.update_status_text(&format!("{name} has no template to reset to"));
             return false;
         }
-        let half_again = |text: &str| -> String {
-            let one = |t: &str| -> Option<String> {
-                if let Ok(v) = t.parse::<i32>() {
-                    Some(format!("{}", v * 2))
-                } else {
-                    t.parse::<f32>().ok().map(|v| format!("{:.2}", v * 1.5))
-                }
-            };
-            if let Some(v) = one(text) {
-                v
-            } else if text.contains(':') {
-                text.split(':').map(|t| one(t).unwrap_or_else(|| t.to_string())).collect::<Vec<_>>().join(":")
-            } else {
-                text.to_string()
-            }
-        };
         let node = &mut self.param_editor_dir_mut().children[slot];
         for (pname, text, is_expr) in defaults {
             if let Some(p) = node.params.iter_mut().find(|p| p.name == pname) {
-                if custom && !is_expr {
-                    p.set_text(half_again(&text));
-                } else {
-                    p.set_text(text);
-                }
+                p.set_text(text);
                 p.set_expr(is_expr);
             }
         }
         self.sync_nodes();
         self.rebuild_scene_geometry();
         self.sync_parameters_pane();
-        self.update_status_text(&if custom {
-            format!("{name}: custom preset")
-        } else {
-            format!("{name}: parameters reset")
-        });
+        self.update_status_text(&format!("{name}: parameters reset"));
         true
     }
 
@@ -3921,10 +3896,7 @@ impl State {
                 self.choose_camera("Default Camera");
             }
             "Reset Parameters" => {
-                self.apply_param_preset(false);
-            }
-            "Custom Preset" => {
-                self.apply_param_preset(true);
+                self.reset_parameters();
             }
             "New Project" | "New" => {
                 self.new_project();
@@ -6546,7 +6518,7 @@ pub(crate) fn geometry_to_spreadsheet_data(geom: &Detail) -> (Vec<String>, Vec<V
             canvas: Canvas::new(),
             left_menubar: MenuBar::new(0.0, 0.0, 0.0, MENUBAR_H).with_title("0: Network").with_label("Network Menu Bar").with_item("File", &["New", "Save", "Save As"]).with_item("Edit", &["Undo", "Redo"]).with_item("View", &["Zoom In", "Zoom Out", "Network Plate", "Circular Pane", "Detach Pane", "Close Pane"]).with_context_options(context_opts.clone(), 0),
             right_menubar: MenuBar::new(0.0, 0.0, 0.0, MENUBAR_H).with_title("1: Viewport").with_label("Viewport Menu Bar").with_item("Camera", &["Perspective", "Orthographic"]).with_item("Display", &["Square Aspect"]).with_item("Guides", &["Show Grid", "Origin", "Camera Pivot"]).with_item("View", &["Close Pane"]).with_context_options(context_opts.clone(), 1),
-            param_menubar: MenuBar::new(0.0, 0.0, 0.0, MENUBAR_H).with_title("2: Parameters").with_label("Parameters Menu Bar").with_item("Preset", &["Default", "Custom"]).with_item("Reset", &["All"]).with_item("View", &["Close Pane"]).with_context_options(context_opts.clone(), 2),
+            param_menubar: MenuBar::new(0.0, 0.0, 0.0, MENUBAR_H).with_title("2: Parameters").with_label("Parameters Menu Bar").with_item("Preset", &["Default"]).with_item("Reset", &["All"]).with_item("View", &["Close Pane"]).with_context_options(context_opts.clone(), 2),
             status: StatusBar::new().with_text("Ready"),
             breadcrumb: {
                 let mut bc = Breadcrumb::new();
diff --git a/src/command.rs b/src/command.rs
index cfb8439..2e10006 100644
--- a/src/command.rs
+++ b/src/command.rs
@@ -229,10 +229,10 @@ pub const COMMANDS: &[Command] = &[
 
     // --- Parameters ---
     Command { id: "export", label: "Export", context: Context::Parameters, run: Run::Menu("Export"), default_chord: None },
-    // The parameters menubar's Preset and Reset menus. That bar is not
-    // drawn, so until these rows the two were reachable by MCP alone.
+    // The parameters menubar's Preset and Reset menus, which did one
+    // thing. That bar is not drawn, so until this row it was reachable by
+    // MCP alone.
     Command { id: "reset_parameters", label: "Reset Parameters", context: Context::Parameters, run: Run::Menu("Reset Parameters"), default_chord: None },
-    Command { id: "custom_preset", label: "Custom Preset", context: Context::Parameters, run: Run::Menu("Custom Preset"), default_chord: None },
 
     // --- Playbar ---
     Command { id: "play_pause", label: "Play / Pause", context: Context::Playbar, run: Run::Key(Action::PlayPause), default_chord: Some("Up") },
diff --git a/src/main.rs b/src/main.rs
index f0b7a5b..613925b 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -6653,10 +6653,10 @@ mod tests {
         assert_eq!(state.fs_root.children.len(), nodes, "a refused click ran New Project");
     }
 
-    /// The cameras and the parameter presets are commands. They were menus
+    /// The cameras and the parameter reset are commands. They were menus
     /// of two menubars that are not drawn, so nothing on screen reached them.
     #[test]
-    fn the_cameras_and_the_presets_are_commands() {
+    fn the_cameras_and_the_parameter_reset_are_commands() {
         use crate::dialog::CAMERA_ROW_PREFIX;
         let mut state = State::new(false);
         assert!(state.camera_names().contains(&"camera1".to_string()), "the bundled project has camera1");
@@ -6687,7 +6687,7 @@ mod tests {
         assert_eq!(state.active_camera, "camera1");
         assert_eq!(state.viewport().active_camera, "camera1");
 
-        // Reset puts a changed parameter back; the custom preset moves it.
+        // Reset puts a changed parameter back.
         let slot = state
             .current_dir()
             .children
@@ -6705,8 +6705,7 @@ mod tests {
         state.current_dir_mut().children[slot].params.iter_mut().find(|p| p.name == "Radius").unwrap().set_text("3.25".to_string());
         assert!(state.run_command("reset_parameters"));
         assert_eq!(radius(&state), default);
-        assert!(state.run_command("custom_preset"));
-        assert_ne!(radius(&state), default, "the custom preset left Radius at its default");
+        assert!(crate::command::by_id("custom_preset").is_none(), "the custom preset is retired");
 
         // With nothing selected there is nothing to reset, and it says so.
         state.graph_mut().set_selected_node(None);
diff --git a/src/window.rs b/src/window.rs
index 9874e56..87a195c 100644
--- a/src/window.rs
+++ b/src/window.rs
@@ -167,11 +167,9 @@ impl State {
             }
 
             if let Some((menu_idx, item_idx)) = state.menu_mut(PARAM_MENUBAR_IDX).menu_click() {
-                // Preset: Default, Custom. Reset: All, which is Default.
-                match (menu_idx, item_idx) {
-                    (0, 0) | (1, 0) => changed |= state.apply_param_preset(false),
-                    (0, 1) => changed |= state.apply_param_preset(true),
-                    _ => {}
+                // Preset's Default and Reset's All are one thing.
+                if menu_idx <= 1 && item_idx == 0 {
+                    changed |= state.reset_parameters();
                 }
             }