Merge pull request #1642 from ramox81/codex/sweep-corner-followups

This commit is contained in:
Hakan Seven committed 2026-10-07 12:55:08 +03:00
commit 737981791b
29 files changed
+482 -108

No files matched your search

+93 -35
View File
@@ -1606,6 +1606,10 @@ impl CadCommand for RevolveCommand {
// ── SWEEP command ──────────────────────────────────────────────────────────
/// Banking stays on for later sweeps until a twist angle is entered, as in
/// the reference.
static SWEEP_BANK: std::sync::atomic::AtomicBool = std::sync::atomic::AtomicBool::new(false);
pub struct SweepCommand {
step: SweepStep,
profiles: Vec<(Handle, EntityType)>,
@@ -1618,6 +1622,9 @@ pub struct SweepCommand {
reference_start: Option<DVec3>,
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],
}
@@ -1630,12 +1637,15 @@ enum SweepStep {
Alignment,
BasePoint,
Scale,
/// The start reference length: a distance, or two points.
ReferenceLength,
ReferenceEnd,
/// The end reference length: a distance, or two points.
NewLength,
NewLengthStart,
NewLengthEnd,
Twist,
ScaleExpression,
TwistExpression,
}
impl SweepCommand {
@@ -1648,15 +1658,31 @@ impl SweepCommand {
preview_key: None,
preview_cache: Vec::new(),
mode: ExtrudeMode::Solid,
options: SweepOptions::default(),
options: SweepOptions {
bank: SWEEP_BANK.load(std::sync::atomic::Ordering::Relaxed),
..SweepOptions::default()
},
reference_start: None,
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() {
@@ -1715,10 +1741,13 @@ impl SweepCommand {
true
}
fn length_anchor(&self) -> DVec3 {
self.reference_start
.or_else(|| self.selection_options().and_then(|options| options.base_point))
.unwrap_or(DVec3::ZERO)
/// The Reference scale is the start reference length over the end one.
fn set_end_length(&mut self, length: f64) -> bool {
if !length.is_finite() || length <= 1e-12 {
return false;
}
self.end_length = length;
self.set_scale(self.reference_length / length)
}
}
@@ -1742,25 +1771,28 @@ 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 reference length or first point"),
t!("SWEEP Specify start reference length"),
crate::entities::common::format_length(self.reference_length),
),
SweepStep::ReferenceEnd => t!("SWEEP Specify second reference point:").into_owned(),
SweepStep::ReferenceEnd | SweepStep::NewLengthEnd => t!("SWEEP Specify second point:").into_owned(),
SweepStep::NewLength => format!(
"{} <{}>:",
t!("SWEEP Specify new length or [Points]"),
crate::entities::common::format_length(self.reference_length * self.options.scale),
t!("SWEEP Specify end reference length"),
crate::entities::common::format_length(self.end_length),
),
SweepStep::NewLengthStart => t!("SWEEP Specify first point of new length:").into_owned(),
SweepStep::NewLengthEnd => t!("SWEEP Specify second point of new length:").into_owned(),
SweepStep::Twist => format!(
"{} <{}>:",
t!("SWEEP Specify twist angle or [Bank]"),
crate::entities::common::format_angle(self.options.twist_angle),
"{}<{}>:",
t!("SWEEP Enter twist angle or allow banking for a non-planar sweep path [Bank/EXpression]"),
if self.options.bank {
"Bank".to_string()
} else {
format!("{:.4}", self.options.twist_angle.to_degrees())
},
),
}
}
@@ -1776,9 +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::NewLength => vec![CmdOption::new("Points", "POINTS")],
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(),
}
}
@@ -1801,11 +1832,18 @@ impl CadCommand for SweepCommand {
.filter(|(hovered, _)| *hovered == handle)
.map(|(_, entity)| entity.clone())
});
if path.as_ref().is_some_and(crate::scene::model::sweep_model::is_sweep_path) {
self.finish(handle)
} else {
CmdResult::NeedPoint
let Some(path) = path.filter(crate::scene::model::sweep_model::is_sweep_path) else {
return CmdResult::NeedPoint;
};
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(format!(
"{}
{}", t!(message), t!("The selected path curve is not valid."),
));
}
}
self.finish(handle)
}
fn on_point(&mut self, point: DVec3) -> CmdResult {
@@ -1827,15 +1865,12 @@ impl CadCommand for SweepCommand {
}
}
SweepStep::NewLength => {
self.set_scale(point.distance(self.length_anchor()) / self.reference_length);
}
SweepStep::NewLengthStart => {
self.new_length_start = Some(point);
self.step = SweepStep::NewLengthEnd;
}
SweepStep::NewLengthEnd => {
if let Some(start) = self.new_length_start {
self.set_scale(point.distance(start) / self.reference_length);
self.set_end_length(point.distance(start));
}
}
_ => {}
@@ -1848,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
)
}
@@ -1900,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;
@@ -1916,22 +1954,39 @@ impl CadCommand for SweepCommand {
}
}
SweepStep::NewLength => {
if "POINTS".starts_with(&keyword) {
self.step = SweepStep::NewLengthStart;
} else if let Some(length) = crate::entities::common::parse_typed_length(value) {
self.set_scale(length / self.reference_length);
if let Some(length) = crate::entities::common::parse_typed_length(value) {
self.set_end_length(length);
} else {
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;
} else if let Some(angle) = crate::entities::common::parse_angle(value) {
if angle.is_finite() {
self.options.twist_angle = angle;
self.options.bank = false;
SWEEP_BANK.store(false, std::sync::atomic::Ordering::Relaxed);
self.step = SweepStep::PickPath;
}
}
@@ -1947,9 +2002,12 @@ impl CadCommand for SweepCommand {
self.step = SweepStep::PickPath;
}
SweepStep::Mode => self.step = SweepStep::PickProfiles,
SweepStep::Alignment | SweepStep::Scale | SweepStep::Twist
| SweepStep::NewLength => self.step = SweepStep::PickPath,
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);
}
_ => return CmdResult::Cancel,
}
CmdResult::NeedPoint