forked from 1b-agent/opencadstudio-upstream
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:
1 parent
018ac455cb
commit
48c3c433a5
10 files changed
+627
-22
No files matched your search
@@ -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 {
|
||||
|
||||
@@ -697,6 +697,7 @@ inventory::submit!(crate::command::CommandRegistration {
|
||||
"PDFOSNAP",
|
||||
"UOSNAP",
|
||||
"FIELDDISPLAY",
|
||||
"SURFACEASSOCIATIVITY",
|
||||
"FIELDEVAL",
|
||||
"PDFIMPORTMODE",
|
||||
"PDFIMPORTFILTER",
|
||||
|
||||
@@ -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))) {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in new issue
Block a user