forked from 1b-agent/opencadstudio-upstream
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:
1 parent
89b1a22850
commit
688785a6cf
18 files changed
+1949
-316
No files matched your search
@@ -1466,6 +1466,10 @@ pub struct Scene {
|
||||
/// Entity drawn with the selection-highlight colour without being part
|
||||
/// of the real selection — used to preview a row in the cycling list box.
|
||||
pub hover_highlight: Option<Handle>,
|
||||
/// Color used to draw the selection highlight overlay wires (SELECTIONEFFECTCOLOR).
|
||||
pub selection_color: [f32; 4],
|
||||
/// Whether selection visual effect (glow/highlight) is enabled (SELECTIONEFFECT).
|
||||
pub selection_effect: bool,
|
||||
/// Whether entity transparency is honoured on screen. When false the
|
||||
/// wire shader forces every line opaque (a uniform toggle, no retessellate).
|
||||
pub transparency_display: bool,
|
||||
@@ -1882,6 +1886,8 @@ impl Scene {
|
||||
command_preview_hidden: HashSet::default(),
|
||||
refedit_keep: None,
|
||||
hover_highlight: None,
|
||||
selection_color: crate::scene::model::wire_model::WireModel::SELECTED,
|
||||
selection_effect: true,
|
||||
transparency_display: true,
|
||||
model_lineweight_scale: 1.0,
|
||||
selection_filter: HashSet::default(),
|
||||
|
||||
+53
-35
@@ -2430,6 +2430,7 @@ impl Pipeline {
|
||||
hovered: &rustc_hash::FxHashSet<acadrust::Handle>,
|
||||
annotation_context_wires: &[WireModel],
|
||||
depth_map: &rustc_hash::FxHashMap<u64, [f32; 2]>,
|
||||
selected_tint: Option<[f32; 4]>,
|
||||
) {
|
||||
let perf_started = crate::perf::enabled().then(iced::time::Instant::now);
|
||||
if selected.is_empty() && hovered.is_empty() && annotation_context_wires.is_empty() {
|
||||
@@ -2490,13 +2491,17 @@ impl Pipeline {
|
||||
.copied()
|
||||
.filter(|wire| wire.render_instance.is_some())
|
||||
.collect();
|
||||
let mut gpu = WireGpu::from_highlight_refs(
|
||||
device,
|
||||
&selected_regular,
|
||||
WireModel::SELECTED,
|
||||
depth_map,
|
||||
self.wire_const_bgl.as_ref(),
|
||||
);
|
||||
let mut gpu = if let Some(tint) = selected_tint {
|
||||
WireGpu::from_highlight_refs(
|
||||
device,
|
||||
&selected_regular,
|
||||
tint,
|
||||
depth_map,
|
||||
self.wire_const_bgl.as_ref(),
|
||||
)
|
||||
} else {
|
||||
Vec::new()
|
||||
};
|
||||
gpu.extend(WireGpu::from_highlight_refs(
|
||||
device,
|
||||
&hover_regular,
|
||||
@@ -2505,13 +2510,17 @@ impl Pipeline {
|
||||
self.wire_const_bgl.as_ref(),
|
||||
));
|
||||
self.gpu_selected_wires = gpu;
|
||||
let mut block_gpu = BlockWireGpu::from_wires(
|
||||
device,
|
||||
&selected_blocks,
|
||||
depth_map,
|
||||
Some(WireModel::SELECTED),
|
||||
&self.block_wire_const_bgl,
|
||||
);
|
||||
let mut block_gpu = if let Some(tint) = selected_tint {
|
||||
BlockWireGpu::from_wires(
|
||||
device,
|
||||
&selected_blocks,
|
||||
depth_map,
|
||||
Some(tint),
|
||||
&self.block_wire_const_bgl,
|
||||
)
|
||||
} else {
|
||||
Vec::new()
|
||||
};
|
||||
block_gpu.extend(BlockWireGpu::from_wires(
|
||||
device,
|
||||
&hover_blocks,
|
||||
@@ -2549,6 +2558,7 @@ impl Pipeline {
|
||||
hovered: &rustc_hash::FxHashSet<acadrust::Handle>,
|
||||
annotation_context_wires: &[WireModel],
|
||||
depth_map: &rustc_hash::FxHashMap<u64, [f32; 2]>,
|
||||
selected_tint: Option<[f32; 4]>,
|
||||
) {
|
||||
let perf_started = crate::perf::enabled().then(iced::time::Instant::now);
|
||||
if selected.is_empty() && hovered.is_empty() && annotation_context_wires.is_empty() {
|
||||
@@ -2585,15 +2595,17 @@ impl Pipeline {
|
||||
}
|
||||
}
|
||||
}
|
||||
for h in selected {
|
||||
push(
|
||||
&self.wire_handle_index,
|
||||
h.value(),
|
||||
WireModel::SELECTED,
|
||||
wires,
|
||||
&mut out,
|
||||
&mut selected_blocks,
|
||||
);
|
||||
if let Some(tint) = selected_tint {
|
||||
for h in selected {
|
||||
push(
|
||||
&self.wire_handle_index,
|
||||
h.value(),
|
||||
tint,
|
||||
wires,
|
||||
&mut out,
|
||||
&mut selected_blocks,
|
||||
);
|
||||
}
|
||||
}
|
||||
for h in hovered.iter().filter(|handle| !selected.contains(handle)) {
|
||||
push(
|
||||
@@ -2607,25 +2619,31 @@ impl Pipeline {
|
||||
}
|
||||
for wire in annotation_context_wires {
|
||||
let tint = if wire.selected {
|
||||
WireModel::SELECTED
|
||||
selected_tint.unwrap_or(WireModel::SELECTED)
|
||||
} else {
|
||||
WireModel::HOVER
|
||||
};
|
||||
for vertex in &wire.text_verts {
|
||||
out.push(text_gpu::TextVertex {
|
||||
color: [tint[0], tint[1], tint[2], vertex.color[3]],
|
||||
..*vertex
|
||||
});
|
||||
if !wire.selected || selected_tint.is_some() {
|
||||
for vertex in &wire.text_verts {
|
||||
out.push(text_gpu::TextVertex {
|
||||
color: [tint[0], tint[1], tint[2], vertex.color[3]],
|
||||
..*vertex
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
self.text_highlight_vcount = out.len() as u32;
|
||||
self.text_highlight_vbuf = text_gpu::upload_vertices(device, &out);
|
||||
let mut block_gpu = text_gpu::upload_block_vertex_refs(
|
||||
device,
|
||||
&selected_blocks,
|
||||
depth_map,
|
||||
Some(WireModel::SELECTED),
|
||||
);
|
||||
let mut block_gpu = if let Some(tint) = selected_tint {
|
||||
text_gpu::upload_block_vertex_refs(
|
||||
device,
|
||||
&selected_blocks,
|
||||
depth_map,
|
||||
Some(tint),
|
||||
)
|
||||
} else {
|
||||
Vec::new()
|
||||
};
|
||||
block_gpu.extend(text_gpu::upload_block_vertex_refs(
|
||||
device,
|
||||
&hover_blocks,
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user