forked from 1b-agent/opencadstudio-upstream
Merge pull request #1331 from ramox81/codex/smooth-constraint-parity
# Conflicts: # src/app/commands/styleprops.rs
This commit is contained in:
commit
76451f7298
18 files changed
+762
-127
No files matched your search
@@ -3182,9 +3182,24 @@ impl OpenCADStudio {
|
||||
&refs,
|
||||
driving_param.as_ref(),
|
||||
) {
|
||||
self.tabs[i].active_cmd = None;
|
||||
let keep_smooth_selection = kind
|
||||
== crate::scene::parametric_constraints::ConstraintKind::Smooth
|
||||
&& self.tabs[i]
|
||||
.active_cmd
|
||||
.as_ref()
|
||||
.is_some_and(|command| command.name() == "GCSMOOTH");
|
||||
if !keep_smooth_selection {
|
||||
self.tabs[i].active_cmd = None;
|
||||
}
|
||||
self.tabs[i].snap_result = None;
|
||||
self.command_line.push_error(message);
|
||||
if keep_smooth_selection {
|
||||
if let Some(prompt) =
|
||||
self.tabs[i].active_cmd.as_ref().map(|command| command.prompt())
|
||||
{
|
||||
self.command_line.push_info(&prompt);
|
||||
}
|
||||
}
|
||||
return Task::none();
|
||||
}
|
||||
let scope = self.tabs[i].current_parametric_scope();
|
||||
|
||||
@@ -1206,17 +1206,38 @@ impl OpenCADStudio {
|
||||
}
|
||||
}
|
||||
|
||||
"SMOOTHCONSTRAINT" => {
|
||||
"GCSMOOTH" | "SMOOTHCONSTRAINT" => {
|
||||
use crate::modules::parametric::SmoothConstraintCommand;
|
||||
let handles = self.tabs[i].scene.selected_handles_in_order();
|
||||
if handles.is_empty() {
|
||||
use crate::modules::draw::select::SelectObjectsCommand;
|
||||
let sel = SelectObjectsCommand::new(cmd);
|
||||
self.command_line.push_info(&sel.prompt());
|
||||
self.tabs[i].active_cmd = Some(Box::new(sel));
|
||||
let command = SmoothConstraintCommand::new();
|
||||
self.command_line.push_info(&command.prompt());
|
||||
self.tabs[i].active_cmd = Some(Box::new(command));
|
||||
} else if handles.len() != 2 {
|
||||
self.tabs[i].scene.deselect_all();
|
||||
self.command_line.push_error(
|
||||
"Smooth requires an open spline first and a target curve second.",
|
||||
);
|
||||
let command = SmoothConstraintCommand::new();
|
||||
self.command_line.push_info(&command.prompt());
|
||||
self.tabs[i].active_cmd = Some(Box::new(command));
|
||||
} else {
|
||||
let Some(refs) = self.tabs[i].scene.smooth_constraint_refs(&handles) else {
|
||||
self.command_line
|
||||
.push_output("Select one open spline and one open target curve.");
|
||||
let first = self.tabs[i].scene.document.get_entity(handles[0]);
|
||||
let second = self.tabs[i].scene.document.get_entity(handles[1]);
|
||||
let refs = first.zip(second).and_then(|(first, second)| {
|
||||
SmoothConstraintCommand::preselected_refs(
|
||||
(first, handles[0]),
|
||||
(second, handles[1]),
|
||||
)
|
||||
});
|
||||
let Some(refs) = refs else {
|
||||
self.tabs[i].scene.deselect_all();
|
||||
self.command_line.push_error(
|
||||
"Smooth requires an open spline first and a line, arc, polyline segment or open spline second.",
|
||||
);
|
||||
let command = SmoothConstraintCommand::new();
|
||||
self.command_line.push_info(&command.prompt());
|
||||
self.tabs[i].active_cmd = Some(Box::new(command));
|
||||
return None;
|
||||
};
|
||||
use crate::command::CmdResult;
|
||||
|
||||
@@ -1051,6 +1051,7 @@ impl OpenCADStudio {
|
||||
| "CONSTRAINTSOLVEMODE"
|
||||
| "CONSTRAINTINFER"
|
||||
| "CONSTRAINTBARDISPLAY"
|
||||
| "CONSTRAINTBARMODE"
|
||||
) =>
|
||||
{
|
||||
return self.dispatch_styleprops(&format!("SETVAR {cmd}"), i);
|
||||
@@ -1073,7 +1074,7 @@ impl OpenCADStudio {
|
||||
let value = it.next().map(|s| s.trim().to_string());
|
||||
if name.is_empty() || name == "?" {
|
||||
self.command_line.push_info(
|
||||
crate::t!("SETVAR: CETRANSPARENCY LTSCALE CELTSCALE PDMODE PDSIZE TEXTSIZE ORTHOMODE FILLMODE MIRRTEXT FRAME IMAGEFRAME PDFFRAME WIPEOUTFRAME XCLIPFRAME POINTCLOUDCLIPFRAME ZOOMWHEEL ZOOMFACTOR SHORTCUTMENU SHORTCUTMENUDURATION CURSORSIZE PICKBOX CURSORTYPE SNAPANG TEXTFILL CLIPROMPTLINES COMMANDLINEFADETIME ATTREQ ATTDIA DIMASSOC DIMCONTINUEMODE CONSTRAINTSOLVEMODE CONSTRAINTINFER CONSTRAINTBARDISPLAY ANGBASE ANGDIR SKETCHINC SKPOLY SKTOLERANCE DONUTID DONUTOD CENTEREXE CENTERLAYER CENTERLTYPE CENTERLTSCALE CENTERLTYPEFILE CENTERCROSSSIZE CENTERCROSSGAP CENTERMARKEXE COLORTHEME SELECTIONAREA SELECTIONAREAOPACITY SELECTIONEFFECT SELECTIONEFFECTCOLOR WINDOWSAREACOLOR CROSSINGAREACOLOR SELECTIONPREVIEW GRIPSIZE GRIPCOLOR GRIPHOT GRIPHOVER GRIPOBJLIMIT | CLAYER CELTYPE TEXTSTYLE (read-only)").as_ref(),
|
||||
crate::t!("SETVAR: CETRANSPARENCY LTSCALE CELTSCALE PDMODE PDSIZE TEXTSIZE ORTHOMODE FILLMODE MIRRTEXT FRAME IMAGEFRAME PDFFRAME WIPEOUTFRAME XCLIPFRAME POINTCLOUDCLIPFRAME ZOOMWHEEL ZOOMFACTOR SHORTCUTMENU SHORTCUTMENUDURATION CURSORSIZE PICKBOX CURSORTYPE SNAPANG TEXTFILL CLIPROMPTLINES COMMANDLINEFADETIME ATTREQ ATTDIA DIMASSOC DIMCONTINUEMODE CONSTRAINTSOLVEMODE CONSTRAINTINFER CONSTRAINTBARDISPLAY CONSTRAINTBARMODE ANGBASE ANGDIR SKETCHINC SKPOLY SKTOLERANCE DONUTID DONUTOD CENTEREXE CENTERLAYER CENTERLTYPE CENTERLTSCALE CENTERLTYPEFILE CENTERCROSSSIZE CENTERCROSSGAP CENTERMARKEXE COLORTHEME SELECTIONAREA SELECTIONAREAOPACITY SELECTIONEFFECT SELECTIONEFFECTCOLOR WINDOWSAREACOLOR CROSSINGAREACOLOR SELECTIONPREVIEW GRIPSIZE GRIPCOLOR GRIPHOT GRIPHOVER GRIPOBJLIMIT | CLAYER CELTYPE TEXTSTYLE (read-only)").as_ref(),
|
||||
);
|
||||
} else {
|
||||
if name == "CETRANSPARENCY" {
|
||||
@@ -1269,15 +1270,23 @@ impl OpenCADStudio {
|
||||
}
|
||||
if matches!(
|
||||
name.as_str(),
|
||||
"CONSTRAINTSOLVEMODE" | "CONSTRAINTINFER" | "CONSTRAINTBARDISPLAY"
|
||||
"CONSTRAINTSOLVEMODE"
|
||||
| "CONSTRAINTINFER"
|
||||
| "CONSTRAINTBARDISPLAY"
|
||||
| "CONSTRAINTBARMODE"
|
||||
) {
|
||||
let current = match name.as_str() {
|
||||
"CONSTRAINTSOLVEMODE" => i16::from(self.constraint_solve_mode),
|
||||
"CONSTRAINTINFER" => i16::from(self.constraint_infer),
|
||||
"CONSTRAINTBARDISPLAY" => self.constraint_bar_display,
|
||||
"CONSTRAINTBARMODE" => self.constraint_bar_mode,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
let maximum = if name == "CONSTRAINTBARDISPLAY" { 3 } else { 1 };
|
||||
let maximum = match name.as_str() {
|
||||
"CONSTRAINTBARDISPLAY" => 3,
|
||||
"CONSTRAINTBARMODE" => 4095,
|
||||
_ => 1,
|
||||
};
|
||||
if let Some(value) = &value {
|
||||
match value
|
||||
.parse::<i16>()
|
||||
@@ -1293,6 +1302,7 @@ impl OpenCADStudio {
|
||||
"CONSTRAINTBARDISPLAY" => {
|
||||
self.constraint_bar_display = mode
|
||||
}
|
||||
"CONSTRAINTBARMODE" => self.constraint_bar_mode = mode,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
self.persist_settings_if_changed();
|
||||
|
||||
@@ -602,6 +602,7 @@ pub(super) struct OpenCADStudio {
|
||||
pub constraint_solve_mode: bool,
|
||||
pub constraint_infer: bool,
|
||||
pub constraint_bar_display: i16,
|
||||
pub constraint_bar_mode: i16,
|
||||
/// Minutes between autosaves to a `.sv$` recovery file (SAVETIME command);
|
||||
/// 0 disables autosave.
|
||||
pub savetime_min: i32,
|
||||
@@ -3882,6 +3883,7 @@ impl OpenCADStudio {
|
||||
constraint_solve_mode: true,
|
||||
constraint_infer: false,
|
||||
constraint_bar_display: 3,
|
||||
constraint_bar_mode: 4095,
|
||||
savetime_min: 10,
|
||||
default_bg_color: None,
|
||||
default_paper_bg_color: None,
|
||||
|
||||
@@ -465,6 +465,9 @@ pub struct UserSettings {
|
||||
/// Constraint bar display bit mask: 1 after applying, 2 on selection.
|
||||
#[serde(default = "default_constraint_bar_display")]
|
||||
pub constraint_bar_display: i16,
|
||||
/// Geometric constraint type bit mask (1..2048, combined; default all).
|
||||
#[serde(default = "default_constraint_bar_mode")]
|
||||
pub constraint_bar_mode: i16,
|
||||
/// Minutes between autosaves to a `.sv$` recovery file (SAVETIME command).
|
||||
/// 0 disables autosave.
|
||||
pub savetime_min: i32,
|
||||
@@ -595,6 +598,10 @@ fn default_constraint_bar_display() -> i16 {
|
||||
3
|
||||
}
|
||||
|
||||
fn default_constraint_bar_mode() -> i16 {
|
||||
4095
|
||||
}
|
||||
|
||||
fn deserialize_clipromptlines<'de, D>(de: D) -> Result<i32, D::Error>
|
||||
where
|
||||
D: serde::Deserializer<'de>,
|
||||
@@ -660,6 +667,7 @@ impl Default for UserSettings {
|
||||
constraint_solve_mode: true,
|
||||
constraint_infer: false,
|
||||
constraint_bar_display: 3,
|
||||
constraint_bar_mode: 4095,
|
||||
savetime_min: 10,
|
||||
default_save_format: crate::io::DEFAULT_SAVE_FORMAT.to_string(),
|
||||
pick_add: true,
|
||||
|
||||
@@ -1739,15 +1739,13 @@ pub(super) fn on_tab_close(&mut self, idx: usize) -> Task<Message> {
|
||||
.get_entity(popup.handle)
|
||||
.is_some_and(|entity| match (item.action, entity) {
|
||||
(GripMenuAction::ShowFit, acadrust::EntityType::Spline(spline)) => {
|
||||
!spline.cv_frame_visible
|
||||
&& crate::entities::spline::uses_fit_method(spline)
|
||||
crate::entities::spline::shows_fit_points(spline)
|
||||
}
|
||||
(
|
||||
GripMenuAction::ShowControlVertices,
|
||||
acadrust::EntityType::Spline(spline),
|
||||
) => {
|
||||
spline.cv_frame_visible
|
||||
|| !crate::entities::spline::uses_fit_method(spline)
|
||||
crate::entities::spline::shows_control_vertices(spline)
|
||||
}
|
||||
_ => false,
|
||||
});
|
||||
|
||||
@@ -521,6 +521,7 @@ impl OpenCADStudio {
|
||||
constraint_solve_mode: self.constraint_solve_mode,
|
||||
constraint_infer: self.constraint_infer,
|
||||
constraint_bar_display: self.constraint_bar_display,
|
||||
constraint_bar_mode: self.constraint_bar_mode,
|
||||
savetime_min: self.savetime_min,
|
||||
default_save_format: self.default_save_format.clone(),
|
||||
pick_add: self.pick_add,
|
||||
@@ -624,6 +625,7 @@ impl OpenCADStudio {
|
||||
self.constraint_solve_mode = s.constraint_solve_mode;
|
||||
self.constraint_infer = s.constraint_infer;
|
||||
self.constraint_bar_display = s.constraint_bar_display.clamp(0, 3);
|
||||
self.constraint_bar_mode = s.constraint_bar_mode.clamp(0, 4095);
|
||||
self.savetime_min = s.savetime_min;
|
||||
self.default_save_format =
|
||||
crate::io::canonical_save_format(&s.default_save_format).to_string();
|
||||
|
||||
@@ -3051,6 +3051,7 @@ impl OpenCADStudio {
|
||||
vp_size,
|
||||
self.show_constraint_values,
|
||||
self.constraint_bar_display,
|
||||
self.constraint_bar_mode,
|
||||
cursor,
|
||||
)?;
|
||||
let set = self.tabs[i].scene.parametric_constraint_set(scope)?;
|
||||
@@ -4577,6 +4578,7 @@ properties={:.1}ms picked={}",
|
||||
canvas_sz,
|
||||
self.show_constraint_values,
|
||||
self.constraint_bar_display,
|
||||
self.constraint_bar_mode,
|
||||
p_full,
|
||||
)
|
||||
})
|
||||
@@ -6683,6 +6685,7 @@ mod selection_preview_tests {
|
||||
(800.0, 600.0),
|
||||
true,
|
||||
3,
|
||||
4095,
|
||||
)[0].1;
|
||||
let point = (-30..=30).find_map(|y| {
|
||||
(-30..=30).find_map(|x| {
|
||||
|
||||
+3
-1
@@ -611,7 +611,8 @@ bg={bg_ms:.1}ms n={view_count}"
|
||||
};
|
||||
let control_polygon = tab.selected_handle.and_then(|handle| {
|
||||
let spline = match tab.scene.document.get_entity(handle) {
|
||||
Some(acadrust::EntityType::Spline(spline)) if spline.cv_frame_visible => spline,
|
||||
Some(acadrust::EntityType::Spline(spline))
|
||||
if crate::entities::spline::shows_control_vertices(spline) => spline,
|
||||
_ => return None,
|
||||
};
|
||||
if tab
|
||||
@@ -850,6 +851,7 @@ bg={bg_ms:.1}ms n={view_count}"
|
||||
sel_ref.vp_size,
|
||||
self.show_constraint_values,
|
||||
self.constraint_bar_display,
|
||||
self.constraint_bar_mode,
|
||||
)
|
||||
.into_iter()
|
||||
.map(|(id, point, direction, label, is_conflicting, hover_points)| {
|
||||
|
||||
Reference in new issue
Block a user