forked from 1b-agent/opencadstudio-upstream
Merge PR #1000: cache selection filter entity types
This commit is contained in:
commit
92e1dfd685
4 files changed
+51
-12
No files matched your search
@@ -3687,8 +3687,8 @@ impl OpenCADStudio {
|
|||||||
let i = self.active_tab;
|
let i = self.active_tab;
|
||||||
let types = self.tabs[i].scene.entity_type_names_in_layout();
|
let types = self.tabs[i].scene.entity_type_names_in_layout();
|
||||||
let f = &mut self.tabs[i].scene.selection_filter;
|
let f = &mut self.tabs[i].scene.selection_filter;
|
||||||
for t in types {
|
for t in types.iter() {
|
||||||
f.insert(t.to_string());
|
f.insert(t.clone());
|
||||||
}
|
}
|
||||||
Task::none()
|
Task::none()
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-3
@@ -1932,9 +1932,8 @@ impl OpenCADStudio {
|
|||||||
selection_types: tab
|
selection_types: tab
|
||||||
.scene
|
.scene
|
||||||
.entity_type_names_in_layout()
|
.entity_type_names_in_layout()
|
||||||
.into_iter()
|
.as_ref()
|
||||||
.map(|name| name.to_string())
|
.clone(),
|
||||||
.collect(),
|
|
||||||
selection_filter: &tab.scene.selection_filter,
|
selection_filter: &tab.scene.selection_filter,
|
||||||
tooltip_hidden: self.status_menu_tooltip_hidden,
|
tooltip_hidden: self.status_menu_tooltip_hidden,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1789,6 +1789,11 @@ pub struct Scene {
|
|||||||
/// Reverse map: entity_handle → block_record_handle, built from entity_handles lists.
|
/// Reverse map: entity_handle → block_record_handle, built from entity_handles lists.
|
||||||
/// Keyed by geometry_epoch. Eliminates the O(B) fallback scan in belongs_to_visible_block.
|
/// Keyed by geometry_epoch. Eliminates the O(B) fallback scan in belongs_to_visible_block.
|
||||||
entity_block_map_cache: RefCell<Option<(u64, HashMap<Handle, Handle>)>>,
|
entity_block_map_cache: RefCell<Option<(u64, HashMap<Handle, Handle>)>>,
|
||||||
|
/// Distinct entity type names present in a layout, keyed by
|
||||||
|
/// (geometry_epoch, layout block). The status bar asks for this on every
|
||||||
|
/// frame to populate the selection-filter menu, but the answer only
|
||||||
|
/// changes when entities are added or removed.
|
||||||
|
layout_type_names_cache: RefCell<Option<(u64, Handle, std::sync::Arc<Vec<String>>)>>,
|
||||||
/// Reverse dependencies from layer/style/block definitions to the top-level
|
/// Reverse dependencies from layer/style/block definitions to the top-level
|
||||||
/// entities whose resident wire runs actually change. Kept independent from
|
/// entities whose resident wire runs actually change. Kept independent from
|
||||||
/// `geometry_epoch`: a layer colour toggle can reuse the index, invalidate
|
/// `geometry_epoch`: a layer colour toggle can reuse the index, invalidate
|
||||||
@@ -2024,6 +2029,7 @@ impl Scene {
|
|||||||
annotation_affects_wires: std::cell::Cell::new(None),
|
annotation_affects_wires: std::cell::Cell::new(None),
|
||||||
model_extents_cache: RefCell::new(None),
|
model_extents_cache: RefCell::new(None),
|
||||||
entity_block_map_cache: RefCell::new(None),
|
entity_block_map_cache: RefCell::new(None),
|
||||||
|
layout_type_names_cache: RefCell::new(None),
|
||||||
dependency_index_cache: RefCell::new(None),
|
dependency_index_cache: RefCell::new(None),
|
||||||
associative_hatch_source_cache: RefCell::new(None),
|
associative_hatch_source_cache: RefCell::new(None),
|
||||||
block_defn_cache: RefCell::new(HashMap::default()),
|
block_defn_cache: RefCell::new(HashMap::default()),
|
||||||
|
|||||||
+41
-7
@@ -363,16 +363,50 @@ impl Scene {
|
|||||||
/// Returns the sorted set of entity-type names present in the active
|
/// Returns the sorted set of entity-type names present in the active
|
||||||
/// layout. Used to populate the Quick Select "Object type" dropdown
|
/// layout. Used to populate the Quick Select "Object type" dropdown
|
||||||
/// with only the types that actually exist in the drawing.
|
/// with only the types that actually exist in the drawing.
|
||||||
pub fn entity_type_names_in_layout(&self) -> Vec<String> {
|
/// Distinct entity type names in the current layout, for the
|
||||||
|
/// selection-filter menu.
|
||||||
|
///
|
||||||
|
/// The status bar rebuilds on every frame, so this used to run once per
|
||||||
|
/// mouse move over the canvas: a full clone of the layout's handle list
|
||||||
|
/// (1.16 M handles, ~9 MB, on the reproducer), then a lookup, a `String`
|
||||||
|
/// allocation and a `BTreeSet` insert for each one — about 107 ms of a
|
||||||
|
/// 110 ms frame, to produce roughly twenty names.
|
||||||
|
///
|
||||||
|
/// The answer only changes when entities are added or removed, so it is
|
||||||
|
/// cached against `geometry_epoch` and the layout block. The scan itself
|
||||||
|
/// now borrows the handle list instead of cloning it and collects
|
||||||
|
/// `&str`, allocating only for the names it actually returns.
|
||||||
|
pub fn entity_type_names_in_layout(&self) -> std::sync::Arc<Vec<String>> {
|
||||||
use crate::entities::traits::entity_type_name;
|
use crate::entities::traits::entity_type_name;
|
||||||
let mut names: std::collections::BTreeSet<String> =
|
let block = self.current_layout_block_handle();
|
||||||
std::collections::BTreeSet::new();
|
{
|
||||||
for h in self.current_layout_entity_handles() {
|
let cache = self.layout_type_names_cache.borrow();
|
||||||
if let Some(e) = self.document.get_entity(h) {
|
if let Some((epoch, cached_block, names)) = cache.as_ref() {
|
||||||
names.insert(entity_type_name(e).to_string());
|
if *epoch == self.geometry_epoch && *cached_block == block {
|
||||||
|
return std::sync::Arc::clone(names);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
names.into_iter().collect()
|
let mut names: std::collections::BTreeSet<&str> =
|
||||||
|
std::collections::BTreeSet::new();
|
||||||
|
if let Some(record) = self
|
||||||
|
.document
|
||||||
|
.block_records
|
||||||
|
.iter()
|
||||||
|
.find(|record| record.handle == block)
|
||||||
|
{
|
||||||
|
for &handle in &record.entity_handles {
|
||||||
|
if let Some(entity) = self.document.get_entity(handle) {
|
||||||
|
names.insert(entity_type_name(entity));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let names: std::sync::Arc<Vec<String>> = std::sync::Arc::new(
|
||||||
|
names.into_iter().map(str::to_string).collect(),
|
||||||
|
);
|
||||||
|
*self.layout_type_names_cache.borrow_mut() =
|
||||||
|
Some((self.geometry_epoch, block, std::sync::Arc::clone(&names)));
|
||||||
|
names
|
||||||
}
|
}
|
||||||
|
|
||||||
/// True when `handle`'s entity type is allowed by the selection filter.
|
/// True when `handle`'s entity type is allowed by the selection filter.
|
||||||
|
|||||||
Reference in new issue
Block a user