fix(model): repair solid booleans
Track selection order for directional subtraction and use the kernel fixes for periodic curved-face intersections.\n\nRefs #816
This commit is contained in:
commit
bb49f92e99
5 changed files with 57 additions and 10 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
|
@ -878,7 +878,7 @@ checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04"
|
|||
[[package]]
|
||||
name = "cadkernel"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/HakanSeven12/cadkernel.git?rev=eda1263#eda1263da23c1b18e7593151a277a0593bb317ef"
|
||||
source = "git+https://github.com/HakanSeven12/cadkernel.git?rev=3d5de36#3d5de36cb5b391f17da924c5f80e34a0cdc1d948"
|
||||
dependencies = [
|
||||
"acadrust",
|
||||
"cavalier_contours",
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ rfd = "0.17"
|
|||
clap = { version = "4", features = ["derive"] }
|
||||
env_logger = "0.11"
|
||||
acadrust = { git = "https://github.com/HakanSeven12/cadcodec.git", rev = "0975677", features = ["serde"] }
|
||||
cadkernel = { git = "https://github.com/HakanSeven12/cadkernel.git", rev = "eda1263", features = ["acis", "offset"] }
|
||||
cadkernel = { git = "https://github.com/HakanSeven12/cadkernel.git", rev = "3d5de36", features = ["acis", "offset"] }
|
||||
dwg-thumbnailer = { path = "crates/dwg-thumbnailer" }
|
||||
flate2 = "1"
|
||||
image = { version = "0.25", default-features = false, features = ["png", "jpeg", "bmp", "tiff"] }
|
||||
|
|
|
|||
|
|
@ -43,9 +43,8 @@ impl super::OpenCADStudio {
|
|||
// Selected entities that have a cached B-rep.
|
||||
let handles: Vec<Handle> = self.tabs[i]
|
||||
.scene
|
||||
.selected
|
||||
.iter()
|
||||
.copied()
|
||||
.selected_handles_in_order()
|
||||
.into_iter()
|
||||
.filter(|h| !self.tabs[i].scene.is_layer_locked(*h))
|
||||
.filter(|h| self.tabs[i].scene.solid_models.contains_key(h))
|
||||
.collect();
|
||||
|
|
|
|||
|
|
@ -1422,6 +1422,7 @@ pub struct Scene {
|
|||
lighting_cache: RefCell<HashMap<(Handle, u64), Vec<SceneLight>>>,
|
||||
/// Currently selected entity handles.
|
||||
pub selected: HashSet<Handle>,
|
||||
selected_order: Vec<Handle>,
|
||||
/// Session-only ISOLATEOBJECTS / HIDEOBJECTS state. Never written to DWG/DXF.
|
||||
pub object_isolation: ObjectIsolationState,
|
||||
/// Entity handles temporarily removed from the base render while an
|
||||
|
|
@ -1841,6 +1842,7 @@ impl Scene {
|
|||
object_data_cache: crate::entities::object_data::ObjectDataCache::default(),
|
||||
lighting_cache: RefCell::new(HashMap::default()),
|
||||
selected: HashSet::default(),
|
||||
selected_order: Vec::new(),
|
||||
object_isolation: ObjectIsolationState::default(),
|
||||
preview_hidden: HashSet::default(),
|
||||
command_preview_hidden: HashSet::default(),
|
||||
|
|
@ -4377,6 +4379,7 @@ impl Scene {
|
|||
.hidden
|
||||
.extend(self.selected.iter().copied());
|
||||
self.selected.clear();
|
||||
self.selected_order.clear();
|
||||
self.bump_entities(&changes);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -40,17 +40,42 @@ impl Scene {
|
|||
|
||||
if exclusive {
|
||||
self.selected.clear();
|
||||
self.selected_order.clear();
|
||||
}
|
||||
|
||||
self.selected.extend(handles);
|
||||
for handle in handles {
|
||||
if self.selected.insert(handle) {
|
||||
self.selected_order.push(handle);
|
||||
}
|
||||
}
|
||||
self.bump_selection();
|
||||
}
|
||||
|
||||
pub fn deselect_all(&mut self) {
|
||||
self.selected.clear();
|
||||
self.selected_order.clear();
|
||||
self.bump_selection();
|
||||
}
|
||||
|
||||
pub(crate) fn selected_handles_in_order(&self) -> Vec<Handle> {
|
||||
let mut seen = HashSet::default();
|
||||
let mut ordered: Vec<_> = self
|
||||
.selected_order
|
||||
.iter()
|
||||
.copied()
|
||||
.filter(|handle| self.selected.contains(handle) && seen.insert(*handle))
|
||||
.collect();
|
||||
let mut missing: Vec<_> = self
|
||||
.selected
|
||||
.iter()
|
||||
.copied()
|
||||
.filter(|handle| seen.insert(*handle))
|
||||
.collect();
|
||||
missing.sort_unstable_by_key(|handle| handle.value());
|
||||
ordered.extend(missing);
|
||||
ordered
|
||||
}
|
||||
|
||||
/// Replace the complete selection and invalidate the GPU highlight overlay
|
||||
/// only when its contents actually changed. History/file/command paths must
|
||||
/// use this instead of assigning `selected` directly.
|
||||
|
|
@ -62,7 +87,22 @@ impl Scene {
|
|||
.collect();
|
||||
|
||||
if self.selected != selected {
|
||||
let mut seen = HashSet::default();
|
||||
let mut order: Vec<_> = self
|
||||
.selected_order
|
||||
.iter()
|
||||
.copied()
|
||||
.filter(|handle| selected.contains(handle) && seen.insert(*handle))
|
||||
.collect();
|
||||
let mut added: Vec<_> = selected
|
||||
.iter()
|
||||
.copied()
|
||||
.filter(|handle| seen.insert(*handle))
|
||||
.collect();
|
||||
added.sort_unstable_by_key(|handle| handle.value());
|
||||
order.extend(added);
|
||||
self.selected = selected;
|
||||
self.selected_order = order;
|
||||
self.bump_selection();
|
||||
}
|
||||
}
|
||||
|
|
@ -74,6 +114,7 @@ impl Scene {
|
|||
|
||||
for handle in handles {
|
||||
changed |= self.selected.remove(&handle);
|
||||
self.selected_order.retain(|selected| *selected != handle);
|
||||
}
|
||||
|
||||
if changed {
|
||||
|
|
@ -82,9 +123,9 @@ impl Scene {
|
|||
}
|
||||
|
||||
pub fn selected_entities(&self) -> Vec<(Handle, &EntityType)> {
|
||||
self.selected
|
||||
.iter()
|
||||
.filter_map(|&h| self.document.get_entity(h).map(|e| (h, e)))
|
||||
self.selected_handles_in_order()
|
||||
.into_iter()
|
||||
.filter_map(|h| self.document.get_entity(h).map(|e| (h, e)))
|
||||
.collect()
|
||||
}
|
||||
|
||||
|
|
@ -107,7 +148,7 @@ impl Scene {
|
|||
match scope {
|
||||
crate::app::QSelectScope::CurrentSpace => self.current_layout_entity_handles(),
|
||||
crate::app::QSelectScope::CurrentSelection => {
|
||||
self.selected.iter().copied().collect()
|
||||
self.selected_handles_in_order()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -152,6 +193,7 @@ impl Scene {
|
|||
let key = (entity_type_name(e), e.as_entity().layer().to_string());
|
||||
if pairs.contains(&key) {
|
||||
self.selected.insert(h);
|
||||
self.selected_order.push(h);
|
||||
added += 1;
|
||||
}
|
||||
}
|
||||
|
|
@ -174,9 +216,11 @@ impl Scene {
|
|||
.filter_map(|w| Self::handle_from_wire_name(&w.name))
|
||||
.collect();
|
||||
self.selected.clear();
|
||||
self.selected_order.clear();
|
||||
for h in all {
|
||||
if !prev.contains(&h) {
|
||||
self.selected.insert(h);
|
||||
self.selected_order.push(h);
|
||||
}
|
||||
}
|
||||
self.bump_selection();
|
||||
|
|
@ -679,6 +723,7 @@ impl Scene {
|
|||
self.remember_removed_cache_categories(h);
|
||||
self.document.remove_entity_arc(h);
|
||||
highlight_changed |= self.selected.remove(&h);
|
||||
self.selected_order.retain(|selected| *selected != h);
|
||||
if self.hover_highlight == Some(h) {
|
||||
self.hover_highlight = None;
|
||||
highlight_changed = true;
|
||||
|
|
|
|||
Loading…
Reference in a new issue