forked from 1b-agent/opencadstudio-upstream
SWEEP: Expression option, reference prompts and localized messages
- Scale and Twist take an Expression evaluated with the drawing's parameters; invalid input prints the reference message and asks again. - The scale and twist prompts use the reference wording and defaults. - The SWEEP prompts and refusal messages are in the locale catalog with translations in every locale. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
1a18fdd0cf
commit
56f3f68de9
27 files changed
+346
-64
No files matched your search
@@ -519,8 +519,8 @@ impl OpenCADStudio {
|
||||
Ok(value) => value,
|
||||
Err(code) => {
|
||||
if let Some(code) = code {
|
||||
self.command_line.push_output(&format!("Modeling Operation Error:
|
||||
Error Code Number is {code}"));
|
||||
self.command_line.push_output(crate::t!("Modeling Operation Error:").as_ref());
|
||||
self.command_line.push_output(crate::tf!("Error Code Number is {code}", code = code).as_ref());
|
||||
}
|
||||
failed += 1;
|
||||
continue;
|
||||
@@ -564,7 +564,7 @@ Error Code Number is {code}"));
|
||||
self.tabs[i].dirty = true;
|
||||
}
|
||||
if failed > 0 {
|
||||
self.command_line.push_output(&format!("Unable to sweep {failed} selected objects."));
|
||||
self.command_line.push_output(crate::tf!("Unable to sweep {failed} selected objects.", failed = failed).as_ref());
|
||||
}
|
||||
if let Some(pending) = pending {
|
||||
self.commit_undo_delta(i, pending);
|
||||
|
||||
@@ -817,6 +817,7 @@ impl OpenCADStudio {
|
||||
let color = self.tabs[i].scene.layer_color(&self.tabs[i].active_layer);
|
||||
let isolines = crate::entities::solid3d::clamp_header_isolines(self.tabs[i].scene.document.header.isolines);
|
||||
let mut cmd = SweepCommand::new(color, isolines);
|
||||
cmd.set_parameters(self.tabs[i].scene.named_parameters().clone());
|
||||
let selected = self.tabs[i].scene.selected_handles_in_order()
|
||||
.into_iter()
|
||||
.filter_map(|handle| self.tabs[i].scene.document.get_entity(handle)
|
||||
|
||||
@@ -3947,10 +3947,10 @@ pub(super) fn on_tab_close(&mut self, idx: usize) -> Task<Message> {
|
||||
.scene
|
||||
.solid_history_property_refusal(handle, field, &val)
|
||||
{
|
||||
self.command_line.push_output(&format!(
|
||||
"Modeling Operation Error:
|
||||
Error Code Number is {code}"
|
||||
));
|
||||
self.command_line.push_output(crate::t!("Modeling Operation Error:").as_ref());
|
||||
self.command_line.push_output(
|
||||
crate::tf!("Error Code Number is {code}", code = code).as_ref(),
|
||||
);
|
||||
}
|
||||
}
|
||||
} else if self.tabs[i]
|
||||
|
||||
+13
-2
@@ -4463,13 +4463,24 @@ pub(super) fn message_attribute(source: &str) -> Option<(&'static str, &'static
|
||||
"SWEEP Select sweep path or [Alignment/Base point/Scale/Twist]:" => Some(("insert", "sweep-select-sweep-path-or-alignment-base-point-scale-twist")),
|
||||
"SWEEP Align sweep object perpendicular to path [Yes/No]" => Some(("insert", "sweep-align-sweep-object-perpendicular-to-path-yes-no")),
|
||||
"SWEEP Specify base point:" => Some(("insert", "sweep-specify-base-point")),
|
||||
"SWEEP Enter scale factor or [Reference]" => Some(("insert", "sweep-enter-scale-factor-or-reference")),
|
||||
"SWEEP Enter scale factor or [Reference/Expression]" => Some(("insert", "sweep-enter-scale-factor-or-reference")),
|
||||
"SWEEP Specify reference length or first point" => Some(("insert", "sweep-specify-reference-length-or-first-point")),
|
||||
"SWEEP Specify second reference point:" => Some(("insert", "sweep-specify-second-reference-point")),
|
||||
"SWEEP Specify new length or [Points]" => Some(("insert", "sweep-specify-new-length-or-points")),
|
||||
"SWEEP Specify first point of new length:" => Some(("insert", "sweep-specify-first-point-of-new-length")),
|
||||
"SWEEP Specify second point of new length:" => Some(("insert", "sweep-specify-second-point-of-new-length")),
|
||||
"SWEEP Specify twist angle or [Bank]" => Some(("insert", "sweep-specify-twist-angle-or-bank")),
|
||||
"SWEEP Enter twist angle or allow banking for a non-planar sweep path [Bank/EXpression]" => Some(("insert", "sweep-specify-twist-angle-or-bank")),
|
||||
"SWEEP Enter expression:" => Some(("insert", "sweep-enter-expression")),
|
||||
"SWEEP Specify start reference length" => Some(("insert", "sweep-specify-start-reference-length")),
|
||||
"SWEEP Specify end reference length" => Some(("insert", "sweep-specify-end-reference-length")),
|
||||
"SWEEP Specify second point:" => Some(("insert", "sweep-specify-second-point")),
|
||||
"The syntax is incorrect or a variable is not defined. Reenter the expression or value." => Some(("insert", "sweep-expression-invalid")),
|
||||
"Modeling Operation Error:" => Some(("insert", "sweep-modeling-operation-error")),
|
||||
"Error Code Number is {code}" => Some(("insert", "sweep-error-code-number")),
|
||||
"Unable to sweep {failed} selected objects." => Some(("insert", "sweep-unable-to-sweep-selected-objects")),
|
||||
"Cannot use scale option when path curve is closed." => Some(("insert", "sweep-scale-closed-path")),
|
||||
"Path curve must be smooth when using scale option." => Some(("insert", "sweep-scale-smooth-path")),
|
||||
"The selected path curve is not valid." => Some(("insert", "sweep-path-curve-not-valid")),
|
||||
"Point cross-sections are allowed only at the first or last end, with a curve between point ends." => Some(("insert", "point-cross-sections-are-allowed-only-at-the-first-or-last-end-with-a-curve-between-p")),
|
||||
"LOFT requires at least two cross-sections." => Some(("insert", "loft-requires-at-least-two-cross-sections")),
|
||||
"A closed loft requires at least three curve cross-sections and no point ends." => Some(("insert", "a-closed-loft-requires-at-least-three-curve-cross-sections-and-no-point-ends")),
|
||||
|
||||
@@ -1623,6 +1623,8 @@ pub struct SweepCommand {
|
||||
reference_length: f64,
|
||||
new_length_start: Option<DVec3>,
|
||||
end_length: f64,
|
||||
/// The drawing's named parameters, for Expression input.
|
||||
parameters: crate::scene::named_parameters::ParameterTable,
|
||||
isolines: usize,
|
||||
color: [f32; 4],
|
||||
}
|
||||
@@ -1642,6 +1644,8 @@ enum SweepStep {
|
||||
NewLength,
|
||||
NewLengthEnd,
|
||||
Twist,
|
||||
ScaleExpression,
|
||||
TwistExpression,
|
||||
}
|
||||
|
||||
impl SweepCommand {
|
||||
@@ -1662,11 +1666,23 @@ impl SweepCommand {
|
||||
reference_length: 1.0,
|
||||
new_length_start: None,
|
||||
end_length: 1.0,
|
||||
parameters: Default::default(),
|
||||
isolines,
|
||||
color,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_parameters(&mut self, parameters: crate::scene::named_parameters::ParameterTable) {
|
||||
self.parameters = parameters;
|
||||
}
|
||||
|
||||
/// An Expression input, evaluated against the drawing's parameters.
|
||||
fn evaluate(&self, text: &str) -> Option<f64> {
|
||||
let mut table = self.parameters.clone();
|
||||
table.set("sweepExpression", text).ok()?;
|
||||
table.resolve("sweepExpression").ok().filter(|value| value.is_finite())
|
||||
}
|
||||
|
||||
pub fn set_preselection(&mut self, profiles: Vec<(Handle, EntityType)>) {
|
||||
self.set_profiles(profiles);
|
||||
if !self.profiles.is_empty() {
|
||||
@@ -1755,8 +1771,9 @@ impl CadCommand for SweepCommand {
|
||||
),
|
||||
SweepStep::BasePoint => t!("SWEEP Specify base point:").into_owned(),
|
||||
SweepStep::Scale => format!(
|
||||
"{} <{}>:", t!("SWEEP Enter scale factor or [Reference]"), self.options.scale,
|
||||
"{}<{:.4}>:", t!("SWEEP Enter scale factor or [Reference/Expression]"), self.options.scale,
|
||||
),
|
||||
SweepStep::ScaleExpression | SweepStep::TwistExpression => t!("SWEEP Enter expression:").into_owned(),
|
||||
SweepStep::ReferenceLength => format!(
|
||||
"{} <{}>:",
|
||||
t!("SWEEP Specify start reference length"),
|
||||
@@ -1769,12 +1786,12 @@ impl CadCommand for SweepCommand {
|
||||
crate::entities::common::format_length(self.end_length),
|
||||
),
|
||||
SweepStep::Twist => format!(
|
||||
"{} <{}>:",
|
||||
t!("SWEEP Specify twist angle or [Bank]"),
|
||||
"{}<{}>:",
|
||||
t!("SWEEP Enter twist angle or allow banking for a non-planar sweep path [Bank/EXpression]"),
|
||||
if self.options.bank {
|
||||
"Bank".to_string()
|
||||
} else {
|
||||
crate::entities::common::format_angle(self.options.twist_angle)
|
||||
format!("{:.4}", self.options.twist_angle.to_degrees())
|
||||
},
|
||||
),
|
||||
}
|
||||
@@ -1791,8 +1808,8 @@ impl CadCommand for SweepCommand {
|
||||
CmdOption::new("Twist", "TWIST"),
|
||||
],
|
||||
SweepStep::Alignment => vec![CmdOption::new("Yes", "YES"), CmdOption::new("No", "NO")],
|
||||
SweepStep::Scale => vec![CmdOption::new("Reference", "REFERENCE")],
|
||||
SweepStep::Twist => vec![CmdOption::new("Bank", "BANK")],
|
||||
SweepStep::Scale => vec![CmdOption::new("Reference", "REFERENCE"), CmdOption::new("Expression", "EXPRESSION")],
|
||||
SweepStep::Twist => vec![CmdOption::new("Bank", "BANK"), CmdOption::new("EXpression", "EXPRESSION")],
|
||||
_ => Vec::new(),
|
||||
}
|
||||
}
|
||||
@@ -1820,7 +1837,10 @@ impl CadCommand for SweepCommand {
|
||||
};
|
||||
if (self.options.scale - 1.0).abs() > 1e-12 {
|
||||
if let Some(message) = crate::scene::model::sweep_model::scaled_sweep_path_refusal(&path) {
|
||||
return CmdResult::ReportMeasurement(message.to_string());
|
||||
return CmdResult::ReportMeasurement(format!(
|
||||
"{}
|
||||
{}", t!(message), t!("The selected path curve is not valid."),
|
||||
));
|
||||
}
|
||||
}
|
||||
self.finish(handle)
|
||||
@@ -1863,6 +1883,7 @@ impl CadCommand for SweepCommand {
|
||||
SweepStep::PickProfiles | SweepStep::Mode | SweepStep::PickPath
|
||||
| SweepStep::Alignment | SweepStep::Scale | SweepStep::ReferenceLength
|
||||
| SweepStep::NewLength | SweepStep::Twist
|
||||
| SweepStep::ScaleExpression | SweepStep::TwistExpression
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1915,7 +1936,9 @@ impl CadCommand for SweepCommand {
|
||||
self.step = SweepStep::PickPath;
|
||||
}
|
||||
SweepStep::Scale => {
|
||||
if "REFERENCE".starts_with(&keyword) {
|
||||
if "EXPRESSION".starts_with(&keyword) {
|
||||
self.step = SweepStep::ScaleExpression;
|
||||
} else if "REFERENCE".starts_with(&keyword) {
|
||||
self.reference_start = None;
|
||||
self.new_length_start = None;
|
||||
self.step = SweepStep::ReferenceLength;
|
||||
@@ -1937,8 +1960,25 @@ impl CadCommand for SweepCommand {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
SweepStep::ScaleExpression | SweepStep::TwistExpression => {
|
||||
let Some(value) = self.evaluate(value) else {
|
||||
return Some(CmdResult::ReportMeasurement(t!(
|
||||
"The syntax is incorrect or a variable is not defined. Reenter the expression or value."
|
||||
).into_owned()));
|
||||
};
|
||||
if self.step == SweepStep::ScaleExpression {
|
||||
self.set_scale(value);
|
||||
} else {
|
||||
self.options.twist_angle = value.to_radians();
|
||||
self.options.bank = false;
|
||||
SWEEP_BANK.store(false, std::sync::atomic::Ordering::Relaxed);
|
||||
}
|
||||
self.step = SweepStep::PickPath;
|
||||
}
|
||||
SweepStep::Twist => {
|
||||
if "BANK".starts_with(&keyword) {
|
||||
if keyword.len() >= 2 && "EXPRESSION".starts_with(&keyword) {
|
||||
self.step = SweepStep::TwistExpression;
|
||||
} else if "BANK".starts_with(&keyword) {
|
||||
self.options.bank = true;
|
||||
SWEEP_BANK.store(true, std::sync::atomic::Ordering::Relaxed);
|
||||
self.step = SweepStep::PickPath;
|
||||
@@ -1963,6 +2003,7 @@ impl CadCommand for SweepCommand {
|
||||
}
|
||||
SweepStep::Mode => self.step = SweepStep::PickProfiles,
|
||||
SweepStep::Alignment | SweepStep::Scale | SweepStep::Twist => self.step = SweepStep::PickPath,
|
||||
SweepStep::ScaleExpression | SweepStep::TwistExpression => {}
|
||||
SweepStep::ReferenceLength => self.step = SweepStep::NewLength,
|
||||
SweepStep::NewLength => {
|
||||
self.set_end_length(self.end_length);
|
||||
|
||||
@@ -76,11 +76,9 @@ pub fn scaled_sweep_path_refusal(path: &EntityType) -> Option<&'static str> {
|
||||
},
|
||||
};
|
||||
if closed {
|
||||
Some("Cannot use scale option when path curve is closed.
|
||||
The selected path curve is not valid.")
|
||||
Some("Cannot use scale option when path curve is closed.")
|
||||
} else if !smooth {
|
||||
Some("Path curve must be smooth when using scale option.
|
||||
The selected path curve is not valid.")
|
||||
Some("Path curve must be smooth when using scale option.")
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user