feat(statusbar): selection filtering by object type (FILTER pill)

Add a per-type selection filter to the scene: the FILTER pill opens a
checklist of the entity types in the layout, and unchecking a type
excludes it from interactive picking (click, box and lasso selection all
honour it). The pill lights up while any type is filtered out.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
Hakan SevenandClaude Opus 4.8 committed 2026-06-04 23:39:48 +03:00
1 parent 834780ec5d
commit f7eac09b55
8 files changed
+219

No files matched your search

+9
View File
@@ -177,6 +177,8 @@ pub(super) struct OpenCADStudio {
units_popup_open: bool,
/// True while the Isolate pill's action menu is open.
isolate_popup_open: bool,
/// True while the selection-filter type picker is open.
selection_filter_popup_open: bool,
/// Clean-screen mode: hide ribbon and side panels for a full canvas.
clean_screen: bool,
/// Quick Properties: show a compact floating property panel on selection.
@@ -756,6 +758,12 @@ pub enum Message {
ToggleTransparencyDisplay,
/// Toggle the Quick Properties floating panel.
ToggleQuickProperties,
/// Toggle the selection-filter type picker open/closed.
ToggleSelectionFilterPopup,
/// Close the selection-filter type picker.
CloseSelectionFilterPopup,
/// Include/exclude an entity type from interactive selection.
ToggleSelectionFilterType(String),
/// Toggle the drawing-units picker open/closed.
ToggleUnitsPopup,
/// Close the drawing-units picker.
@@ -1225,6 +1233,7 @@ impl OpenCADStudio {
statusbar_menu_open: false,
units_popup_open: false,
isolate_popup_open: false,
selection_filter_popup_open: false,
statusbar_config: crate::ui::statusbar_config::StatusBarConfig::load(),
clean_screen: false,
quick_properties: false,
+22
View File
@@ -2889,6 +2889,8 @@ impl OpenCADStudio {
vp_mat,
bounds,
));
// Selection filter: keep only allowed types.
handles.retain(|&h| self.tabs[i].scene.passes_selection_filter(h));
self.tabs[i].scene.deselect_all();
for h in &handles {
self.tabs[i].scene.select_entity(*h, false);
@@ -2932,6 +2934,9 @@ impl OpenCADStudio {
// body, not just the thin projected edges.
self.tabs[i].scene.mesh_click_hit(p, vp_mat, bounds)
});
// Selection filter: drop a pick whose type is excluded.
let hit =
hit.filter(|&h| self.tabs[i].scene.passes_selection_filter(h));
if let Some(handle) = hit {
// Individual picks accumulate (issue #47):
// each plain click adds to the selection,
@@ -2980,6 +2985,8 @@ impl OpenCADStudio {
vp_mat,
bounds,
));
// Selection filter: keep only allowed types.
handles.retain(|&h| self.tabs[i].scene.passes_selection_filter(h));
self.tabs[i].scene.deselect_all();
for h in &handles {
self.tabs[i].scene.select_entity(*h, false);
@@ -3594,6 +3601,21 @@ impl OpenCADStudio {
self.quick_properties ^= true;
Task::none()
}
Message::ToggleSelectionFilterPopup => {
self.selection_filter_popup_open ^= true;
Task::none()
}
Message::CloseSelectionFilterPopup => {
self.selection_filter_popup_open = false;
Task::none()
}
Message::ToggleSelectionFilterType(name) => {
let f = &mut self.tabs[self.active_tab].scene.selection_filter;
if !f.remove(&name) {
f.insert(name);
}
Task::none()
}
Message::ToggleUnitsPopup => {
self.units_popup_open ^= true;
Task::none()
+17
View File
@@ -1173,6 +1173,7 @@ impl OpenCADStudio {
tab.scene.is_isolation_active(),
tab.scene.transparency_display,
self.quick_properties,
tab.scene.selection_filter_active(),
&self.statusbar_config,
)
})
@@ -1232,6 +1233,21 @@ impl OpenCADStudio {
iced::widget::Space::new().width(0).height(0).into()
};
let sel_filter_layer: Element<'_, Message> = if self.selection_filter_popup_open {
let types: Vec<String> = tab
.scene
.entity_type_names_in_layout()
.into_iter()
.map(|s| s.to_string())
.collect();
crate::ui::selection_filter_popup::selection_filter_popup_overlay(
types,
&tab.scene.selection_filter,
)
} else {
iced::widget::Space::new().width(0).height(0).into()
};
let dropdown_layer: Element<'_, Message> = self
.ribbon
.dropdown_overlay(
@@ -1270,6 +1286,7 @@ impl OpenCADStudio {
statusbar_menu_layer,
units_layer,
isolate_layer,
sel_filter_layer,
dropdown_layer,
layout_ctx_layer,
qselect_layer,