feat(solid history): booleans keep the solids they joined editable

With SOLIDHIST on, UNION, SUBTRACT and INTERSECT no longer reduce the
result's history to a frozen body: each solid's history joins the
result's under a boolean step, in the order the result applied them.
The Properties palette lists a composite's solids under Operand; the one
chosen shows its own geometry rows and grips, placed where it sits in
the composite, and editing it replays the whole tree. A composite read
from a file keeps its saved body; the tree is replayed only on edits.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
Hakan SevenandClaude Opus 5.5 committed 2026-10-07 11:14:13 +03:00
1 parent d1f3bf3013
commit d3033caf24
28 files changed
+383 -52

No files matched your search

+14 -6
View File
@@ -756,11 +756,12 @@ impl Scene {
.iter()
.filter(|handle| !self.solid_models.contains_key(handle))
.filter_map(|&handle| {
let from_history = self
.document
.solid_history_operations(handle)
.and_then(|operations| kernel::acis::rebuild_history(&operations).ok());
let body = from_history.or_else(|| match self.document.get_entity(handle) {
let tree = self.document.solid_history_tree(handle);
let rebuilt = || {
tree.as_ref()
.and_then(|tree| kernel::acis::rebuild_history_tree(tree).ok())
};
let stored = || match self.document.get_entity(handle) {
Some(EntityType::Solid3D(solid)) => {
crate::scene::convert::solid3d_tess::kernel_body(solid)
}
@@ -771,7 +772,14 @@ impl Scene {
crate::scene::convert::solid3d_tess::kernel_surface_body(surface)
}
_ => None,
})?;
};
// A composite's saved body is what its booleans produced;
// replaying them is for edits, not for reading the file.
let body = if tree.as_ref().is_some_and(|tree| tree.has_boolean()) {
stored().or_else(rebuilt)
} else {
rebuilt().or_else(stored)
}?;
Some((handle, body))
})
.collect();