feat(model-space): theme-aware model space canvas and CAD selection/grip sysvars

Model space appearance now follows the active UI theme instead of a
hardcoded dark background. Canvas mode is user-selectable (Match Theme /
Classic CAD Dark / Custom RGB), with matching controls for the paper
sheet and desk surround backgrounds and grid opacity.
Implements industry-standard CAD system variables, all settable via
command name, SETVAR, and the Options dialog:
- COLORTHEME (0/1 dark/light UI scheme, preserves custom palettes)
- COLORSCHEME (interactive named-theme selection)
- BACKGROUND (THEME/CLASSIC/DEFAULT/DESK presets, RGB triplets)
- SELECTIONAREA, SELECTIONAREAOPACITY (translucent marquee fill)
- WINDOWSAREACOLOR/WINDOWAREACOLOR, CROSSINGAREACOLOR (ACI or theme)
- SELECTIONEFFECT, SELECTIONEFFECTCOLOR (GPU highlight pass, driven by
  selection_generation invalidation — no retessellation)
- SELECTIONPREVIEW (bit 0 = idle rollover, bit 1 = in-command hover)
- GRIPSIZE, GRIPCOLOR, GRIPHOT, GRIPHOVER (grip overlay styling)
This commit is contained in:
Karim Jerbi committed 2026-09-03 17:44:44 +01:00
1 parent 89b1a22850
commit 688785a6cf
18 files changed
+1949 -316

No files matched your search

+19 -2
View File
@@ -255,6 +255,10 @@ pub struct Primitive {
pub(in crate::scene) bg_color: [f32; 4],
/// Active Iced theme text colour for GPU-rendered ViewCube labels.
pub(in crate::scene) viewcube_text_color: [f32; 4],
/// Color used to draw the selection highlight overlay wires.
pub(in crate::scene) selection_color: [f32; 4],
/// Whether selection visual effect (glow/highlight) is enabled.
pub(in crate::scene) selection_effect: bool,
/// One input-to-render sample, carried only when PERF tracing is enabled.
pub(in crate::scene) nav_perf: Option<NavPerfSample>,
}
@@ -989,6 +993,11 @@ impl shader::Primitive for Primitive {
&& !Arc::ptr_eq(previous, &vp.annotation_context_wires)
});
if selection_changed || highlighted_geometry_changed || annotation_context_changed {
let sel_color = if self.selection_effect {
Some(self.selection_color)
} else {
None
};
inner.upload_selected_wires(
device,
&vp_wires[..],
@@ -996,6 +1005,7 @@ impl shader::Primitive for Primitive {
&vp.hover_handles,
&vp.annotation_context_wires,
&draw_depths,
sel_color,
);
// Text highlight rides the same selection key: a pick / rollover
// recolours the selected / hovered glyphs without touching the
@@ -1007,6 +1017,7 @@ impl shader::Primitive for Primitive {
&vp.hover_handles,
&vp.annotation_context_wires,
&draw_depths,
sel_color,
);
inner.cached_annotation_highlight_source =
Some(Arc::clone(&vp.annotation_context_wires));
@@ -3339,7 +3350,7 @@ impl Scene {
}
let tint = if selected {
WireModel::SELECTED
self.selection_color
} else {
WireModel::HOVER
};
@@ -3387,7 +3398,7 @@ impl Scene {
entity,
content_viewport.then_some(inst.handle),
);
wire.color = WireModel::SELECTED;
wire.color = self.selection_color;
wire.selected = true;
wire.pattern_length = pattern_length;
wire.pattern = pattern;
@@ -3527,6 +3538,8 @@ impl Scene {
viewports,
bg_color,
viewcube_text_color,
selection_color: self.selection_color,
selection_effect: self.selection_effect,
nav_perf: perf_nav,
}
}
@@ -3555,6 +3568,8 @@ impl Scene {
viewports: vec![],
bg_color,
viewcube_text_color,
selection_color: self.selection_color,
selection_effect: self.selection_effect,
nav_perf: None,
};
};
@@ -3615,6 +3630,8 @@ impl Scene {
viewports,
bg_color,
viewcube_text_color,
selection_color: self.selection_color,
selection_effect: self.selection_effect,
nav_perf: perf_nav,
}
}