feat(sweep): associative swept surfaces in the drawing's network

Swept surfaces made with SURFACEASSOCIATIVITY on keep their profile and
path and are written as a swept-surface action of the drawing's
associative network, reading the profile and path and their scale and
twist expressions. They follow edits of their sources.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
ramox81andClaude Opus 5.5 committed 2026-10-08 13:29:55 +03:00
1 parent 018ac455cb
commit 48c3c433a5
10 files changed
+627 -22

No files matched your search

+14 -2
View File
@@ -489,6 +489,8 @@ impl OpenCADStudio {
.collect::<Vec<_>>();
// Group 294: a base point the user picked.
let picked_base = options.base_point.is_some();
let several = profiles.len() > 1;
let picked = options;
let options = sweep_model::sweep_selection_options(&selection, options);
let pending = if profiles.is_empty() {
None
@@ -532,8 +534,10 @@ impl OpenCADStudio {
continue;
}
};
// An associative surface keeps the profile and path it reads.
let associative = surface && sweep_model::surface_associativity();
let deletes_path =
crate::app::delobj_deletes_auxiliary(delete_objects, surface);
!associative && crate::app::delobj_deletes_auxiliary(delete_objects, surface);
if deletes_path && self.tabs[i].scene.is_layer_locked(path_handle) {
failed += 1;
continue;
@@ -546,6 +550,14 @@ impl OpenCADStudio {
created,
&expressions,
);
if associative {
// A picked base point, or the one several profiles share.
let linked = crate::command::SweepOptions {
base_point: if picked_base || several { options.and_then(|o| o.base_point) } else { None },
..picked
};
sweep_model::link_sweep_sources(&mut self.tabs[i].scene.document, created, handle, path_handle, &linked);
}
created
} else {
self.add_solid_model(
@@ -558,7 +570,7 @@ impl OpenCADStudio {
failed += 1;
} else {
created_handles.push(created);
if delete_profiles {
if delete_profiles && !associative {
consumed.push(handle);
}
if deletes_path {
+1
View File
@@ -697,6 +697,7 @@ inventory::submit!(crate::command::CommandRegistration {
"PDFOSNAP",
"UOSNAP",
"FIELDDISPLAY",
"SURFACEASSOCIATIVITY",
"FIELDEVAL",
"PDFIMPORTMODE",
"PDFIMPORTFILTER",
+23
View File
@@ -1093,6 +1093,7 @@ impl OpenCADStudio {
| "DGNOSNAP"
| "UOSNAP"
| "FIELDDISPLAY"
| "SURFACEASSOCIATIVITY"
| "PDFIMPORTMODE"
| "PDFIMPORTFILTER"
| "PDFIMPORTLAYERS"
@@ -1301,6 +1302,28 @@ impl OpenCADStudio {
}
return Some(self.finish_dispatch(cmd));
}
if name == "SURFACEASSOCIATIVITY" {
use crate::scene::model::sweep_model;
let current = i16::from(sweep_model::surface_associativity());
match value.as_deref().map(|v| v.trim().parse::<i16>().ok().filter(|v| (0..=1).contains(v))) {
Some(Some(mode)) => {
if current != mode {
sweep_model::set_surface_associativity(mode == 1);
self.save_config();
}
}
Some(None) => {
self.command_line.push_error(crate::t!("Requires 0 or 1 only.").as_ref());
self.command_line.push_output(&format!("Enter new value for SURFACEASSOCIATIVITY <{current}>:"));
self.pending_setvar = Some(name.clone());
}
None => {
self.command_line.push_output(&format!("Enter new value for SURFACEASSOCIATIVITY <{current}>:"));
self.pending_setvar = Some(name.clone());
}
}
return Some(self.finish_dispatch(cmd));
}
if name == "FIELDDISPLAY" {
let current = i16::from(crate::entities::field::display());
match value.as_deref().map(|v| v.trim().parse::<i16>().ok().filter(|v| (0..=1).contains(v))) {
+3
View File
@@ -412,6 +412,8 @@ pub struct UserSettings {
pub attdef_on_screen: bool,
/// FIELDDISPLAY: fields show on a gray background.
pub field_display: bool,
/// SURFACEASSOCIATIVITY: new surfaces stay associative to their sources.
pub surface_associativity: bool,
/// Nested-copy symbol handling: false inserts, true binds.
pub ncopy_bind: bool,
/// Last Options page; unknown saved names fall back without rejecting the config.
@@ -823,6 +825,7 @@ impl Default for UserSettings {
image_frame: 1,
attdef_on_screen: true,
field_display: true,
surface_associativity: true,
ncopy_bind: false,
cursor_type: CursorType::Crosshair,
crosshair_color: None,
+2
View File
@@ -678,6 +678,7 @@ impl OpenCADStudio {
image_frame: crate::scene::frame::profile_image_mode(),
attdef_on_screen: crate::modules::draw::draw::attdef::session().on_screen,
field_display: crate::entities::field::display(),
surface_associativity: crate::scene::model::sweep_model::surface_associativity(),
ncopy_bind: self.ncopy_bind,
cursor_type: self.cursor_type,
crosshair_color: self.crosshair_color,
@@ -787,6 +788,7 @@ impl OpenCADStudio {
crate::scene::frame::set_profile_image_mode(s.image_frame);
crate::modules::draw::draw::attdef::session().on_screen = s.attdef_on_screen;
crate::entities::field::set_display(s.field_display);
crate::scene::model::sweep_model::set_surface_associativity(s.surface_associativity);
self.ncopy_bind = s.ncopy_bind;
self.cursor_type = s.cursor_type;
self.crosshair_color = s.crosshair_color;