graphic design tool
git clone https://git.lucas.co/cce-designer.git
refactor: retire Main's Style section — DE chrome is config-owned
The Main utility node carried "Bevel Profile", "Edge Profile" and "Plate
Color", which retinted the params plate and reshaped every relief wall for the
whole process. All three already exist in config.kdl —
`style.surface.relief.profile`, `.edge_profile` and `style.surface.param.color`
— and cce-ui applies them for every client at startup. Main's copies were
applied on project load, so opening a project silently outranked the user's
config with whatever styling that file happened to carry.
The build site, the four MAIN_PARAM_ORDER entries and the three apply arms go;
a retain drops the params from older saves, matching how the retired Node
Color and Help rows are handled. Styling is now config-only.
src/main.rs | 37 +++++++++++++++++++++++++++++++
src/playbar.rs | 6 ++---
src/project.rs | 69 +++++++++++-----------------------------------------------
3 files changed, 53 insertions(+), 59 deletions(-)
diff --git a/src/main.rs b/src/main.rs
index d3354a4..8207346 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -68,6 +68,43 @@ mod tests {
use crate::shortcut::{Shortcut, ShortcutManager, Action};
use crate::geometry::{GAttribute, GVertex, Geometry, line_vertices};
+ /// DE chrome is config-owned (`style.surface.relief.profile` /
+ /// `.edge_profile` / `style.surface.param.color`), so Main's retired Style
+ /// section must not come back from an older project file — while it did,
+ /// loading a project silently outranked the user's config.kdl.
+ #[test]
+ fn test_legacy_style_params_are_dropped_from_main() {
+ let mut state = State::new(false);
+ state.ensure_menubar_subnets();
+ let main_idx = state.fs_root.children.iter().position(|c| c.name == "Main").expect("Main node");
+
+ // Re-seed the params exactly as a pre-removal save carries them.
+ for (name, ty, val) in [
+ ("Style", "section", ""),
+ ("Bevel Profile", "ramp", "smooth;0.000:0.000,0.500:0.900,1.000:1.000"),
+ ("Edge Profile", "ramp", "smooth;0.000:0.000,1.000:1.000"),
+ ("Plate Color", "rgba", "#11223344"),
+ ] {
+ state.fs_root.children[main_idx].params.push(crate::app::ParamDef {
+ name: name.to_string(),
+ label: String::new(),
+ param_type: ty.to_string(),
+ default: val.to_string(),
+ options: Vec::new(),
+ min: None,
+ max: None,
+ step: None,
+ });
+ }
+
+ state.ensure_menubar_subnets();
+ let names: Vec<&str> = state.fs_root.children[main_idx]
+ .params.iter().map(|p| p.name.as_str()).collect();
+ for retired in ["Style", "Bevel Profile", "Edge Profile", "Plate Color"] {
+ assert!(!names.contains(&retired), "retired style param survived load: {retired} in {names:?}");
+ }
+ }
+
/// The roster macro (`widget_roster!` in `src/slots.rs`) numbers the `*_IDX`
/// constants from declaration order. A mis-expansion that skipped a number would
/// leave the last slot addressed as `WIDGET_COUNT`, unreachable through `get_dyn`
diff --git a/src/playbar.rs b/src/playbar.rs
index 73a63ef..bfceaa6 100644
--- a/src/playbar.rs
+++ b/src/playbar.rs
@@ -83,9 +83,9 @@ impl Paint for Playbar {
/// The pane IS its own plate, exactly the ParametersBg contract: the
/// parameter plate's fill — tint, opacity, and blur-behind marker
- /// (`param_plate_fill`) — so it tracks a live retint / opacity / blur
- /// toggle with the other panes (the old hand-rolled PARAM_BG copy froze
- /// the Style section's "Plate Color" out of this pane).
+ /// (`param_plate_fill`) — so it tracks the configured plate tint
+ /// (`style.surface.param.color`) with the other panes, where the old
+ /// hand-rolled PARAM_BG copy froze this pane at the built-in default.
fn color(&self) -> [f32; 4] {
colors::param_plate_fill()
}
diff --git a/src/project.rs b/src/project.rs
index 148a9f6..32593fb 100644
--- a/src/project.rs
+++ b/src/project.rs
@@ -431,31 +431,19 @@ impl State {
ensure_param(main_node, "Ray Traced Preview", "toggle", bool_str(vp_rt_mode), &[], None, None, None);
ensure_param(main_node, "Background Color", "color", &color_to_hex(vp_bg_color), &[], None, None, None);
- // Style — the DE-chrome styling this instance renders with. The bevel
- // profile ramp reshapes every recess/boss wall live (the identity 0→1
- // smooth curve IS the analytic default the toolkit ships).
- ensure_param(main_node, "Style", "section", "", &[], None, None, None);
- ensure_param(main_node, "Bevel Profile", "ramp", "smooth;0.000:0.000,1.000:1.000", &[], None, None, None);
- // The plate perimeter roll's descent curve (face join → silhouette).
- // Unlike the carve ramp — whose identity curve IS its analytic
- // default — the roll's identity would be a straight chamfer, so the
- // untouched identity spec means "analytic quadrant" (apply below
- // clears the profile for it) and any edited curve takes over.
- ensure_param(main_node, "Edge Profile", "ramp", "smooth;0.000:0.000,1.000:1.000", &[], None, None, None);
- // The params plate's tint, rgba — alpha doubles as the frost strength
- // under plate blur. Seeded from the live cce-ui color (linear → sRGB
- // for the hex; alpha is stored linear on both sides).
- let plate_hex = {
- let c = cce_ui::color::param_bg_color();
- format!(
- "#{:02x}{:02x}{:02x}{:02x}",
- (cce_ui::color::linear_to_srgb(c[0]) * 255.0).round().clamp(0.0, 255.0) as u8,
- (cce_ui::color::linear_to_srgb(c[1]) * 255.0).round().clamp(0.0, 255.0) as u8,
- (cce_ui::color::linear_to_srgb(c[2]) * 255.0).round().clamp(0.0, 255.0) as u8,
- (c[3] * 255.0).round().clamp(0.0, 255.0) as u8,
+ // The Style section is retired — DE chrome is config-owned, not
+ // per-project: the wall and edge relief curves are
+ // `style.surface.relief.profile` / `.edge_profile` and the params
+ // plate tint is `style.surface.param.color` in config.kdl, which
+ // cce-ui already applies for every client. Main's copies shadowed
+ // those on load, so a project file silently outranked the user's
+ // config. Drop them from older saves.
+ main_node.params.retain(|p| {
+ !matches!(
+ p.name.as_str(),
+ "Style" | "Bevel Profile" | "Edge Profile" | "Plate Color"
)
- };
- ensure_param(main_node, "Plate Color", "rgba", &plate_hex, &[], None, None, None);
+ });
// The Help section is retired — its only row was an About button nothing
// dispatched. Drop it from older saves too.
@@ -519,7 +507,7 @@ impl State {
}
}
- const MAIN_PARAM_ORDER: [&str; 23] = [
+ const MAIN_PARAM_ORDER: [&str; 19] = [
"File", "New Project", "Open", "Save", "Save As", "Exit",
"Edit", "Undo", "Redo",
"Network", "Zoom In", "Zoom Out",
@@ -527,7 +515,6 @@ impl State {
"Viewport", "Active Camera",
"Ray Traced Preview",
"Background Color",
- "Style", "Bevel Profile", "Edge Profile", "Plate Color",
];
main_node.params.sort_by_key(|p| {
MAIN_PARAM_ORDER
@@ -769,36 +756,6 @@ impl State {
self.viewport_mut().active_camera = cam;
}
- // Style
- "Bevel Profile" => {
- if let Some((keys, smooth)) = cce_ui::widget::parse_ramp_spec(&p.default) {
- cce_ui::layout::set_bevel_profile_keys(&keys, smooth);
- } else {
- cce_ui::layout::clear_bevel_profile();
- }
- }
- "Edge Profile" => {
- // The untouched identity spec means "analytic
- // quadrant", not a straight chamfer (see the
- // ensure_param note).
- if p.default == "smooth;0.000:0.000,1.000:1.000" {
- cce_ui::layout::clear_roll_profile();
- } else if let Some((keys, smooth)) = cce_ui::widget::parse_ramp_spec(&p.default) {
- cce_ui::layout::set_roll_profile_keys(&keys, smooth);
- } else {
- cce_ui::layout::clear_roll_profile();
- }
- }
- "Plate Color" => {
- if let Some(c) = cce_ui::color::parse_hex_bytes(&p.default) {
- cce_ui::color::set_param_bg_color([
- cce_ui::color::srgb_to_linear(c[0] as f32 / 255.0),
- cce_ui::color::srgb_to_linear(c[1] as f32 / 255.0),
- cce_ui::color::srgb_to_linear(c[2] as f32 / 255.0),
- c[3] as f32 / 255.0,
- ]);
- }
- }
_ => {}
}
}