diff --git a/src/app/command_driver.rs b/src/app/command_driver.rs index d8a2f787a..d483d8b13 100644 --- a/src/app/command_driver.rs +++ b/src/app/command_driver.rs @@ -3318,6 +3318,31 @@ impl OpenCADStudio { } }; } + CmdResult::CheckHorizontalPoint { kind, pick } => { + use crate::modules::parametric::HorizontalConstraintCommand; + use crate::scene::parametric_constraints::nearest_parametric_point; + + // The reference rejects a missed first point right away and + // asks for it again; a hit moves on to the second point. + let scope = self.tabs[i].current_parametric_scope(); + let found = nearest_parametric_point( + &self.tabs[i].scene.document, + scope, + acadrust::types::Vector3::new(pick.point.x, pick.point.y, pick.point.z), + None, + ) + .is_some(); + if !found { + self.command_line + .push_error("No valid constraint point found."); + } + let command = HorizontalConstraintCommand::resume(kind, found.then_some(pick)); + self.command_line + .push_info(&crate::command::CadCommand::prompt(&command)); + self.tabs[i].active_cmd = Some(Box::new(command)); + self.tabs[i].snap_result = None; + return Task::none(); + } CmdResult::AddHorizontalConstraint { kind, selection, diff --git a/src/command.rs b/src/command.rs index 5b3159445..74333ff0c 100644 --- a/src/command.rs +++ b/src/command.rs @@ -1592,6 +1592,13 @@ pub enum CmdResult { direction: acadrust::types::Vector3, label: &'static str, }, + /// Resolves the first 2Points pick of a Horizontal or Vertical constraint + /// against the live document so a miss is reported at once, before the + /// second point is asked for. + CheckHorizontalPoint { + kind: crate::scene::parametric_constraints::ConstraintKind, + pick: CoincidentPick, + }, /// Adds a point or object symmetry relation around a picked line. The /// first reference and axis remain fixed during initial placement. AddSymmetricConstraint { diff --git a/src/modules/parametric/horizontal.rs b/src/modules/parametric/horizontal.rs index 987cccf48..a343b476b 100644 --- a/src/modules/parametric/horizontal.rs +++ b/src/modules/parametric/horizontal.rs @@ -321,10 +321,12 @@ impl CadCommand for HorizontalConstraintCommand { fn on_point(&mut self, point: DVec3) -> CmdResult { let pick = Self::point_pick(None, point); match self.step { - Step::ObjectOrTwoPoints | Step::FirstPoint => { - self.step = Step::SecondPoint(pick); - CmdResult::NeedPoint - } + // The host resolves the pick against the document: a hit resumes + // at the second point, a miss re-asks for the first one at once. + Step::ObjectOrTwoPoints | Step::FirstPoint => CmdResult::CheckHorizontalPoint { + kind: self.kind, + pick, + }, Step::SecondPoint(first) => self.finish_points(first, pick), } } @@ -375,10 +377,12 @@ mod tests { fn enter_starts_the_two_point_flow() { let mut command = HorizontalConstraintCommand::new(); assert!(matches!(command.on_enter(), CmdResult::NeedPoint)); - assert!(matches!( - command.on_point(DVec3::new(1.0, 2.0, 0.0)), - CmdResult::NeedPoint - )); + let CmdResult::CheckHorizontalPoint { kind, pick } = + command.on_point(DVec3::new(1.0, 2.0, 0.0)) + else { + panic!("the host must check the first point"); + }; + let mut command = HorizontalConstraintCommand::resume(kind, Some(pick)); let CmdResult::AddHorizontalConstraint { selection: HorizontalConstraintSelection::Points(first, second), direction,