forked from 1b-agent/opencadstudio-upstream
Merge pull request #1118 from MarcelP102/codex/fix-DELOBJ
Implement persistent DELOBJ source deletion policies and cover all four modes through the kernel-backed SWEEP flow.
This commit is contained in:
commit
b19992cbcb
7 files changed
+218
-20
No files matched your search
+113
-10
@@ -1779,7 +1779,7 @@ impl OpenCADStudio {
|
|||||||
} => {
|
} => {
|
||||||
let label = self.history_label_from_active_cmd(i, "SOLID");
|
let label = self.history_label_from_active_cmd(i, "SOLID");
|
||||||
let erase_source = erase_source.filter(|handle| {
|
let erase_source = erase_source.filter(|handle| {
|
||||||
self.tabs[i].scene.document.header.delete_objects
|
self.delete_objects != 0
|
||||||
&& !self.tabs[i].scene.is_layer_locked(*handle)
|
&& !self.tabs[i].scene.is_layer_locked(*handle)
|
||||||
});
|
});
|
||||||
let pending = self.begin_undo(
|
let pending = self.begin_undo(
|
||||||
@@ -2534,7 +2534,7 @@ impl OpenCADStudio {
|
|||||||
CmdResult::EditTableCell { handle, point } => {
|
CmdResult::EditTableCell { handle, point } => {
|
||||||
// TABLEDIT's pick: end the pick phase and hand (table, point)
|
// TABLEDIT's pick: end the pick phase and hand (table, point)
|
||||||
// to the shared cell-edit launcher. A miss or a locked cell
|
// to the shared cell-edit launcher. A miss or a locked cell
|
||||||
// re-prompts, matching AutoCAD's select-until-valid loop.
|
// re-prompts until a valid table cell is selected.
|
||||||
use crate::modules::annotate::table_cmd::{table_cell_at, TableCellEditStart};
|
use crate::modules::annotate::table_cmd::{table_cell_at, TableCellEditStart};
|
||||||
self.tabs[i].active_cmd = None;
|
self.tabs[i].active_cmd = None;
|
||||||
self.tabs[i].snap_result = None;
|
self.tabs[i].snap_result = None;
|
||||||
@@ -3661,7 +3661,7 @@ impl OpenCADStudio {
|
|||||||
taper_angle,
|
taper_angle,
|
||||||
color: _,
|
color: _,
|
||||||
} => {
|
} => {
|
||||||
let delete_sources = self.tabs[i].scene.document.header.delete_objects;
|
let delete_sources = self.delete_objects != 0;
|
||||||
if handles.is_empty()
|
if handles.is_empty()
|
||||||
|| handles
|
|| handles
|
||||||
.iter()
|
.iter()
|
||||||
@@ -3948,7 +3948,7 @@ impl OpenCADStudio {
|
|||||||
self.restore_pre_cmd_tangent();
|
self.restore_pre_cmd_tangent();
|
||||||
return Task::none();
|
return Task::none();
|
||||||
}
|
}
|
||||||
let delete_sources = self.tabs[i].scene.document.header.delete_objects;
|
let delete_sources = self.delete_objects != 0;
|
||||||
use crate::command::ExtrudeMode;
|
use crate::command::ExtrudeMode;
|
||||||
use crate::modules::insert::solid3d_cmds::{
|
use crate::modules::insert::solid3d_cmds::{
|
||||||
empty_revolved_surface, empty_solid3d,
|
empty_revolved_surface, empty_solid3d,
|
||||||
@@ -4082,7 +4082,8 @@ impl OpenCADStudio {
|
|||||||
use crate::command::ExtrudeMode;
|
use crate::command::ExtrudeMode;
|
||||||
use crate::modules::insert::solid3d_cmds::empty_solid3d;
|
use crate::modules::insert::solid3d_cmds::empty_solid3d;
|
||||||
use crate::scene::model::sweep_model;
|
use crate::scene::model::sweep_model;
|
||||||
let delete_sources = self.tabs[i].scene.document.header.delete_objects;
|
let delete_objects = self.delete_objects;
|
||||||
|
let delete_profiles = delete_objects != 0;
|
||||||
let path = self.tabs[i].scene.document.get_entity(path_handle).cloned();
|
let path = self.tabs[i].scene.document.get_entity(path_handle).cloned();
|
||||||
let mut profiles = Vec::new();
|
let mut profiles = Vec::new();
|
||||||
let mut failed = 0usize;
|
let mut failed = 0usize;
|
||||||
@@ -4120,6 +4121,14 @@ impl OpenCADStudio {
|
|||||||
failed += 1;
|
failed += 1;
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
let deletes_path = crate::app::delobj_deletes_auxiliary(
|
||||||
|
delete_objects,
|
||||||
|
surface,
|
||||||
|
);
|
||||||
|
if deletes_path && self.tabs[i].scene.is_layer_locked(path_handle) {
|
||||||
|
failed += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
let created = if surface {
|
let created = if surface {
|
||||||
self.add_surface_model(sweep_model::swept_surface_entity(&record), body)
|
self.add_surface_model(sweep_model::swept_surface_entity(&record), body)
|
||||||
} else {
|
} else {
|
||||||
@@ -4132,9 +4141,12 @@ impl OpenCADStudio {
|
|||||||
failed += 1;
|
failed += 1;
|
||||||
} else {
|
} else {
|
||||||
created_handles.push(created);
|
created_handles.push(created);
|
||||||
if delete_sources {
|
if delete_profiles {
|
||||||
consumed.push(handle);
|
consumed.push(handle);
|
||||||
}
|
}
|
||||||
|
if deletes_path {
|
||||||
|
consumed.push(path_handle);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !created_handles.is_empty() {
|
if !created_handles.is_empty() {
|
||||||
@@ -4175,12 +4187,14 @@ impl OpenCADStudio {
|
|||||||
}).collect::<Vec<_>>();
|
}).collect::<Vec<_>>();
|
||||||
sources.sort_unstable_by_key(|handle| handle.value());
|
sources.sort_unstable_by_key(|handle| handle.value());
|
||||||
sources.dedup();
|
sources.dedup();
|
||||||
let delete_sources = self.tabs[i].scene.document.header.delete_objects;
|
let delete_objects = self.delete_objects;
|
||||||
let locked = delete_sources && sources.iter().any(|handle| self.tabs[i].scene.is_layer_locked(*handle));
|
let delete_sections = delete_objects != 0;
|
||||||
|
let section_locked = delete_sections
|
||||||
|
&& sources.iter().any(|handle| self.tabs[i].scene.is_layer_locked(*handle));
|
||||||
let available = sources.iter().chain(guides.iter()).copied().chain(path)
|
let available = sources.iter().chain(guides.iter()).copied().chain(path)
|
||||||
.filter_map(|handle| self.tabs[i].scene.document.get_entity(handle)
|
.filter_map(|handle| self.tabs[i].scene.document.get_entity(handle)
|
||||||
.cloned().map(|entity| (handle, entity))).collect::<Vec<_>>();
|
.cloned().map(|entity| (handle, entity))).collect::<Vec<_>>();
|
||||||
let result = if locked {
|
let result = if section_locked {
|
||||||
Err("LOFT: a source is on a locked layer; disable source deletion or unlock it.".to_string())
|
Err("LOFT: a source is on a locked layer; disable source deletion or unlock it.".to_string())
|
||||||
} else {
|
} else {
|
||||||
loft_command_model::record(§ions, &guides, path, &available, mode, options)
|
loft_command_model::record(§ions, &guides, path, &available, mode, options)
|
||||||
@@ -4189,6 +4203,19 @@ impl OpenCADStudio {
|
|||||||
match result {
|
match result {
|
||||||
Ok((body, record)) => {
|
Ok((body, record)) => {
|
||||||
let surface = record.parameters.as_ref().is_some_and(|settings| settings.surface);
|
let surface = record.parameters.as_ref().is_some_and(|settings| settings.surface);
|
||||||
|
let delete_auxiliary = crate::app::delobj_deletes_auxiliary(
|
||||||
|
delete_objects,
|
||||||
|
surface,
|
||||||
|
);
|
||||||
|
if delete_auxiliary
|
||||||
|
&& guides.iter().copied().chain(path)
|
||||||
|
.any(|handle| self.tabs[i].scene.is_layer_locked(handle))
|
||||||
|
{
|
||||||
|
self.command_line.push_error(
|
||||||
|
"LOFT: a source is on a locked layer; disable source deletion or unlock it.",
|
||||||
|
);
|
||||||
|
return Task::none();
|
||||||
|
}
|
||||||
let dirty_before = self.tabs[i].dirty;
|
let dirty_before = self.tabs[i].dirty;
|
||||||
let pending = self.begin_undo(i, "LOFT", 1, true);
|
let pending = self.begin_undo(i, "LOFT", 1, true);
|
||||||
let created = if surface {
|
let created = if surface {
|
||||||
@@ -4210,7 +4237,18 @@ impl OpenCADStudio {
|
|||||||
self.command_line.push_error(crate::t!("LOFT could not create a complete display. The source sections were preserved.").as_ref());
|
self.command_line.push_error(crate::t!("LOFT could not create a complete display. The source sections were preserved.").as_ref());
|
||||||
return Task::none();
|
return Task::none();
|
||||||
} else {
|
} else {
|
||||||
if delete_sources { self.tabs[i].scene.erase_entities(&sources); }
|
let mut consumed = if delete_sections {
|
||||||
|
sources.clone()
|
||||||
|
} else {
|
||||||
|
Vec::new()
|
||||||
|
};
|
||||||
|
if delete_auxiliary {
|
||||||
|
consumed.extend(guides.iter().copied());
|
||||||
|
consumed.extend(path);
|
||||||
|
}
|
||||||
|
consumed.sort_unstable_by_key(|handle| handle.value());
|
||||||
|
consumed.dedup();
|
||||||
|
self.tabs[i].scene.erase_entities(&consumed);
|
||||||
self.tabs[i].scene.deselect_all();
|
self.tabs[i].scene.deselect_all();
|
||||||
self.tabs[i].scene.select_entity(created, true);
|
self.tabs[i].scene.select_entity(created, true);
|
||||||
self.tabs[i].dirty = true;
|
self.tabs[i].dirty = true;
|
||||||
@@ -5835,6 +5873,71 @@ fn resample_widths(source: &[(f64, f64)], count: usize) -> Vec<(f64, f64)> {
|
|||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(all(test, not(target_arch = "wasm32")))]
|
||||||
|
mod delobj_tests {
|
||||||
|
use super::*;
|
||||||
|
use acadrust::types::Vector3;
|
||||||
|
|
||||||
|
fn sweep_source_presence(value: i16, mode: crate::command::ExtrudeMode) -> (bool, bool) {
|
||||||
|
let mut app = OpenCADStudio::new_for_test();
|
||||||
|
app.automation_op(r#"{"op":"new"}"#);
|
||||||
|
let i = app.active_tab;
|
||||||
|
let mut circle = acadrust::Circle::new();
|
||||||
|
circle.radius = 2.0;
|
||||||
|
let profile = app.tabs[i]
|
||||||
|
.scene
|
||||||
|
.add_entity(acadrust::EntityType::Circle(circle));
|
||||||
|
let path = app.tabs[i].scene.add_entity(acadrust::EntityType::Line(
|
||||||
|
acadrust::Line::from_points(
|
||||||
|
Vector3::new(0.0, 0.0, 0.0),
|
||||||
|
Vector3::new(0.0, 0.0, 5.0),
|
||||||
|
),
|
||||||
|
));
|
||||||
|
app.delete_objects = value;
|
||||||
|
|
||||||
|
let _ = app.apply_cmd_result(CmdResult::SweepEntities {
|
||||||
|
handles: vec![profile],
|
||||||
|
path_handle: path,
|
||||||
|
mode,
|
||||||
|
options: crate::command::SweepOptions::default(),
|
||||||
|
color: [1.0; 4],
|
||||||
|
});
|
||||||
|
|
||||||
|
let created = app.tabs[i].scene.document.entities().any(|entity| match mode {
|
||||||
|
crate::command::ExtrudeMode::Solid => {
|
||||||
|
matches!(entity, acadrust::EntityType::Solid3D(_))
|
||||||
|
}
|
||||||
|
crate::command::ExtrudeMode::Surface => {
|
||||||
|
matches!(entity, acadrust::EntityType::Surface(_))
|
||||||
|
}
|
||||||
|
});
|
||||||
|
assert!(created, "SWEEP must produce the requested result");
|
||||||
|
(
|
||||||
|
app.tabs[i].scene.document.get_entity(profile).is_some(),
|
||||||
|
app.tabs[i].scene.document.get_entity(path).is_some(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn sweep_applies_all_four_source_deletion_modes() {
|
||||||
|
let solid_expectations = [(true, true), (false, true), (false, false), (false, false)];
|
||||||
|
for (value, expected) in solid_expectations.into_iter().enumerate() {
|
||||||
|
assert_eq!(
|
||||||
|
sweep_source_presence(value as i16, crate::command::ExtrudeMode::Solid),
|
||||||
|
expected,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
assert_eq!(
|
||||||
|
sweep_source_presence(2, crate::command::ExtrudeMode::Surface),
|
||||||
|
(false, false),
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
sweep_source_presence(3, crate::command::ExtrudeMode::Surface),
|
||||||
|
(false, true),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(all(test, not(target_arch = "wasm32")))]
|
#[cfg(all(test, not(target_arch = "wasm32")))]
|
||||||
mod thicken_tests {
|
mod thicken_tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|||||||
@@ -1113,7 +1113,8 @@ impl OpenCADStudio {
|
|||||||
use acadrust::entities::Region;
|
use acadrust::entities::Region;
|
||||||
use acadrust::types::Vector3;
|
use acadrust::types::Vector3;
|
||||||
let mut regions = Vec::new();
|
let mut regions = Vec::new();
|
||||||
for (_, e) in self.tabs[i].scene.selected_entities().iter() {
|
let mut sources = Vec::new();
|
||||||
|
for (handle, e) in self.tabs[i].scene.selected_entities().iter() {
|
||||||
let supported = matches!(
|
let supported = matches!(
|
||||||
e,
|
e,
|
||||||
acadrust::EntityType::LwPolyline(pl)
|
acadrust::EntityType::LwPolyline(pl)
|
||||||
@@ -1136,6 +1137,7 @@ impl OpenCADStudio {
|
|||||||
);
|
);
|
||||||
region.common.layer = self.tabs[i].active_layer.clone();
|
region.common.layer = self.tabs[i].active_layer.clone();
|
||||||
regions.push((region, body));
|
regions.push((region, body));
|
||||||
|
sources.push(*handle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if regions.is_empty() {
|
if regions.is_empty() {
|
||||||
@@ -1154,6 +1156,10 @@ impl OpenCADStudio {
|
|||||||
}
|
}
|
||||||
created.push(handle);
|
created.push(handle);
|
||||||
}
|
}
|
||||||
|
if self.delete_objects != 0 {
|
||||||
|
self.tabs[i].scene.erase_entities(&sources);
|
||||||
|
self.refresh_properties();
|
||||||
|
}
|
||||||
self.tabs[i].dirty = true;
|
self.tabs[i].dirty = true;
|
||||||
self.command_line
|
self.command_line
|
||||||
.push_output(crate::tf!("REGION: created {count} region(s).").as_ref());
|
.push_output(crate::tf!("REGION: created {count} region(s).").as_ref());
|
||||||
@@ -1530,3 +1536,47 @@ impl OpenCADStudio {
|
|||||||
Some(self.finish_dispatch(cmd))
|
Some(self.finish_dispatch(cmd))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod region_tests {
|
||||||
|
use crate::app::OpenCADStudio;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn region_respects_delobj_and_preserves_unconverted_sources() {
|
||||||
|
for delete_sources in [false, true] {
|
||||||
|
let mut app = OpenCADStudio::new_for_test();
|
||||||
|
app.automation_op(r#"{"op":"new"}"#);
|
||||||
|
app.automation_op(r#"{"op":"run","cmd":"CIRCLE 5,5 3"}"#);
|
||||||
|
app.automation_op(r#"{"op":"run","cmd":"LINE 0,0 10,10"}"#);
|
||||||
|
let i = app.active_tab;
|
||||||
|
let sources: Vec<_> = app.tabs[i].scene.document.entities()
|
||||||
|
.map(|entity| {
|
||||||
|
(entity.common().handle, matches!(entity, acadrust::EntityType::Circle(_)))
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
assert_eq!(sources.len(), 2);
|
||||||
|
let handles: Vec<_> = sources.iter().map(|(handle, _)| *handle).collect();
|
||||||
|
app.tabs[i].scene.select_entities(&handles);
|
||||||
|
app.delete_objects = i16::from(delete_sources);
|
||||||
|
|
||||||
|
let _ = app.dispatch_command("REGION");
|
||||||
|
|
||||||
|
for (handle, is_circle) in &sources {
|
||||||
|
assert_eq!(
|
||||||
|
app.tabs[i].scene.document.get_entity(*handle).is_some(),
|
||||||
|
!delete_sources || !is_circle,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
let region_count = app.tabs[i].scene.document.entities()
|
||||||
|
.filter(|entity| matches!(entity, acadrust::EntityType::Region(_)))
|
||||||
|
.count();
|
||||||
|
assert_eq!(region_count, 1);
|
||||||
|
|
||||||
|
app.automation_op(r#"{"op":"undo"}"#);
|
||||||
|
for (handle, _) in &sources {
|
||||||
|
assert!(app.tabs[i].scene.document.get_entity(*handle).is_some());
|
||||||
|
}
|
||||||
|
assert_eq!(app.tabs[i].scene.document.entities().count(), 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1159,6 +1159,11 @@ impl OpenCADStudio {
|
|||||||
"0" | "OFF" | "FALSE" => Some(false),
|
"0" | "OFF" | "FALSE" => Some(false),
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
|
let current_delete_objects = self.delete_objects;
|
||||||
|
let requested_delete_objects = (name == "DELOBJ")
|
||||||
|
.then(|| value.as_deref()?.parse::<i16>().ok())
|
||||||
|
.flatten()
|
||||||
|
.filter(|value| (0..=3).contains(value));
|
||||||
let outcome: Result<(String, bool), String> = {
|
let outcome: Result<(String, bool), String> = {
|
||||||
let h = &mut self.tabs[i].scene.document.header;
|
let h = &mut self.tabs[i].scene.document.header;
|
||||||
match name.as_str() {
|
match name.as_str() {
|
||||||
@@ -1633,15 +1638,18 @@ impl OpenCADStudio {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"DELOBJ" => match &value {
|
"DELOBJ" => match &value {
|
||||||
Some(v) => parse_bool(v)
|
Some(v) => v
|
||||||
.map(|b| {
|
.parse::<i16>()
|
||||||
h.delete_objects = b;
|
.ok()
|
||||||
(format!("DELOBJ = {}", b as i32), true)
|
.filter(|value| (0..=3).contains(value))
|
||||||
|
.map(|value| {
|
||||||
|
(format!("DELOBJ = {value}"), true)
|
||||||
})
|
})
|
||||||
.ok_or_else(|| "SETVAR: 0 or 1 required.".into()),
|
.ok_or_else(|| "SETVAR: integer from 0 to 3 required.".into()),
|
||||||
None => {
|
None => Ok((
|
||||||
Ok((format!("DELOBJ = {}", h.delete_objects as i32), false))
|
format!("DELOBJ = {current_delete_objects}"),
|
||||||
}
|
false,
|
||||||
|
)),
|
||||||
},
|
},
|
||||||
"PLINEGEN" => match &value {
|
"PLINEGEN" => match &value {
|
||||||
Some(v) => parse_bool(v)
|
Some(v) => parse_bool(v)
|
||||||
@@ -2119,6 +2127,9 @@ impl OpenCADStudio {
|
|||||||
};
|
};
|
||||||
match outcome {
|
match outcome {
|
||||||
Ok((msg, changed)) => {
|
Ok((msg, changed)) => {
|
||||||
|
if let Some(value) = requested_delete_objects {
|
||||||
|
self.delete_objects = value;
|
||||||
|
}
|
||||||
if changed {
|
if changed {
|
||||||
if matches!(
|
if matches!(
|
||||||
name.as_str(),
|
name.as_str(),
|
||||||
@@ -2144,6 +2155,7 @@ impl OpenCADStudio {
|
|||||||
| "GRIPHOT"
|
| "GRIPHOT"
|
||||||
| "GRIPHOVER"
|
| "GRIPHOVER"
|
||||||
| "GRIPOBJLIMIT"
|
| "GRIPOBJLIMIT"
|
||||||
|
| "DELOBJ"
|
||||||
) {
|
) {
|
||||||
self.persist_settings_if_changed();
|
self.persist_settings_if_changed();
|
||||||
} else {
|
} else {
|
||||||
@@ -3120,4 +3132,17 @@ mod tests {
|
|||||||
assert!(app.tabs[app.active_tab].active_cmd.is_none());
|
assert!(app.tabs[app.active_tab].active_cmd.is_none());
|
||||||
assert_eq!(app.commandline_fade_ms, 5000);
|
assert_eq!(app.commandline_fade_ms, 5000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn delobj_accepts_values_zero_through_three() {
|
||||||
|
let mut app = fresh_app();
|
||||||
|
|
||||||
|
for value in 0..=3 {
|
||||||
|
let _ = app.run_command_line(&format!("SETVAR DELOBJ {value}"));
|
||||||
|
assert_eq!(app.delete_objects, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
let _ = app.run_command_line("SETVAR DELOBJ 4");
|
||||||
|
assert_eq!(app.delete_objects, 3);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -347,6 +347,10 @@ pub(crate) enum TextEntryMode {
|
|||||||
FreeText,
|
FreeText,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn delobj_deletes_auxiliary(value: i16, creates_surface: bool) -> bool {
|
||||||
|
value == 2 || (value == 3 && !creates_surface)
|
||||||
|
}
|
||||||
|
|
||||||
pub(super) struct OpenCADStudio {
|
pub(super) struct OpenCADStudio {
|
||||||
start: Instant,
|
start: Instant,
|
||||||
control: control::State,
|
control: control::State,
|
||||||
@@ -566,6 +570,8 @@ pub(super) struct OpenCADStudio {
|
|||||||
/// `MIRRTEXT`) — the next command-line entry is its new value, empty keeps
|
/// `MIRRTEXT`) — the next command-line entry is its new value, empty keeps
|
||||||
/// the current one.
|
/// the current one.
|
||||||
pending_setvar: Option<String>,
|
pending_setvar: Option<String>,
|
||||||
|
/// DELOBJ system variable (0–3), shared by every open drawing.
|
||||||
|
delete_objects: i16,
|
||||||
/// Cursor is hovering over the UCS icon body — drives the hover highlight.
|
/// Cursor is hovering over the UCS icon body — drives the hover highlight.
|
||||||
ucs_icon_hover: bool,
|
ucs_icon_hover: bool,
|
||||||
/// UCS icon is selected (clicked): its grips are shown and draggable.
|
/// UCS icon is selected (clicked): its grips are shown and draggable.
|
||||||
@@ -3424,6 +3430,7 @@ impl OpenCADStudio {
|
|||||||
block_usage_last_persist: None,
|
block_usage_last_persist: None,
|
||||||
awaiting_vports: false,
|
awaiting_vports: false,
|
||||||
pending_setvar: None,
|
pending_setvar: None,
|
||||||
|
delete_objects: 1,
|
||||||
ucs_icon_hover: false,
|
ucs_icon_hover: false,
|
||||||
ucs_icon_selected: false,
|
ucs_icon_selected: false,
|
||||||
ucs_grip_drag: None,
|
ucs_grip_drag: None,
|
||||||
|
|||||||
@@ -2293,7 +2293,9 @@ impl super::OpenCADStudio {
|
|||||||
surfaces.push(surf);
|
surfaces.push(surf);
|
||||||
}
|
}
|
||||||
self.push_undo_snapshot(i, "CONVTOSURFACE");
|
self.push_undo_snapshot(i, "CONVTOSURFACE");
|
||||||
self.tabs[i].scene.erase_entities(&handles);
|
if self.delete_objects != 0 {
|
||||||
|
self.tabs[i].scene.erase_entities(&handles);
|
||||||
|
}
|
||||||
let n = surfaces.len();
|
let n = surfaces.len();
|
||||||
for surf in surfaces {
|
for surf in surfaces {
|
||||||
self.tabs[i].scene.add_entity(EntityType::Surface(surf));
|
self.tabs[i].scene.add_entity(EntityType::Surface(surf));
|
||||||
|
|||||||
@@ -219,6 +219,10 @@ pub struct UserSettings {
|
|||||||
/// the current creation layer/style. Registry-style, app-level preference.
|
/// the current creation layer/style. Registry-style, app-level preference.
|
||||||
#[serde(default = "default_dimension_continue_mode")]
|
#[serde(default = "default_dimension_continue_mode")]
|
||||||
pub dimension_continue_mode: i16,
|
pub dimension_continue_mode: i16,
|
||||||
|
/// DELOBJ: source-geometry deletion policy (0–3). Registry-style,
|
||||||
|
/// app-level preference; first-run default is 1.
|
||||||
|
#[serde(default = "default_delete_objects")]
|
||||||
|
pub delete_objects: i16,
|
||||||
/// TEXTFILL: fill TrueType glyphs (true) or draw them hollow (false).
|
/// TEXTFILL: fill TrueType glyphs (true) or draw them hollow (false).
|
||||||
pub textfill: bool,
|
pub textfill: bool,
|
||||||
/// When true, saving over an existing file first copies it to a sibling
|
/// When true, saving over an existing file first copies it to a sibling
|
||||||
@@ -275,6 +279,10 @@ fn default_clipromptlines() -> i32 {
|
|||||||
3
|
3
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn default_delete_objects() -> i16 {
|
||||||
|
1
|
||||||
|
}
|
||||||
|
|
||||||
fn default_commandline_fade_ms() -> i32 {
|
fn default_commandline_fade_ms() -> i32 {
|
||||||
3000
|
3000
|
||||||
}
|
}
|
||||||
@@ -339,6 +347,7 @@ impl Default for UserSettings {
|
|||||||
texteditmode: false,
|
texteditmode: false,
|
||||||
quick_dimension_snap_priority: 0,
|
quick_dimension_snap_priority: 0,
|
||||||
dimension_continue_mode: 1,
|
dimension_continue_mode: 1,
|
||||||
|
delete_objects: 1,
|
||||||
textfill: true,
|
textfill: true,
|
||||||
backup_on_save: true,
|
backup_on_save: true,
|
||||||
file_assoc_enabled: true,
|
file_assoc_enabled: true,
|
||||||
|
|||||||
@@ -392,6 +392,7 @@ impl OpenCADStudio {
|
|||||||
texteditmode: self.texteditmode,
|
texteditmode: self.texteditmode,
|
||||||
quick_dimension_snap_priority: self.quick_dimension_snap_priority,
|
quick_dimension_snap_priority: self.quick_dimension_snap_priority,
|
||||||
dimension_continue_mode: self.dimension_continue_mode,
|
dimension_continue_mode: self.dimension_continue_mode,
|
||||||
|
delete_objects: self.delete_objects,
|
||||||
textfill: crate::scene::text::sdf_atlas::textfill(),
|
textfill: crate::scene::text::sdf_atlas::textfill(),
|
||||||
backup_on_save: self.backup_on_save,
|
backup_on_save: self.backup_on_save,
|
||||||
file_assoc_enabled: self.file_assoc_enabled,
|
file_assoc_enabled: self.file_assoc_enabled,
|
||||||
@@ -460,6 +461,7 @@ impl OpenCADStudio {
|
|||||||
self.texteditmode = s.texteditmode;
|
self.texteditmode = s.texteditmode;
|
||||||
self.quick_dimension_snap_priority = s.quick_dimension_snap_priority.min(1);
|
self.quick_dimension_snap_priority = s.quick_dimension_snap_priority.min(1);
|
||||||
self.dimension_continue_mode = s.dimension_continue_mode.clamp(0, 1);
|
self.dimension_continue_mode = s.dimension_continue_mode.clamp(0, 1);
|
||||||
|
self.delete_objects = s.delete_objects.clamp(0, 3);
|
||||||
crate::scene::text::sdf_atlas::set_textfill(s.textfill);
|
crate::scene::text::sdf_atlas::set_textfill(s.textfill);
|
||||||
self.backup_on_save = s.backup_on_save;
|
self.backup_on_save = s.backup_on_save;
|
||||||
self.file_assoc_enabled = s.file_assoc_enabled;
|
self.file_assoc_enabled = s.file_assoc_enabled;
|
||||||
|
|||||||
Reference in new issue
Block a user