From ad6f902ed794b22a28a74962a84bdb91442c1f2f Mon Sep 17 00:00:00 2001 From: ramox81 <184937705+ramox81@users.noreply.github.com> Date: Mon, 21 Sep 2026 09:18:40 +0300 Subject: [PATCH 1/3] Equal follow-ups: one glyph per object, unshown Multiple bars, typed object picks - An object that carries several Equal relations shows a single "=" badge, as the reference does, instead of one stacked badge per relation. - A pick made in the Multiple flow leaves its new constraint bar unshown until the object is selected or bars are shown, matching the reference; the single flow still shows the bar at once. - A typed coordinate at the Fix `Select object:` prompt and at the Horizontal/Vertical `Select an object or [2Points]` prompt picks the object under that point, like a click, instead of being read as a point. Co-Authored-By: Claude Fable 5.1 --- src/app/command_driver.rs | 4 +++- src/modules/parametric/fixed.rs | 4 ++++ src/modules/parametric/horizontal.rs | 4 ++++ src/scene/parametric_constraints.rs | 23 +++++++++++++++++++++-- 4 files changed, 32 insertions(+), 3 deletions(-) diff --git a/src/app/command_driver.rs b/src/app/command_driver.rs index 0e21a8e6e..453754747 100644 --- a/src/app/command_driver.rs +++ b/src/app/command_driver.rs @@ -3429,10 +3429,12 @@ impl OpenCADStudio { .scene .parametric_constraint_set_mut(scope) .add(ConstraintKind::Equal, vec![first, *follower], None); + // A Multiple pick leaves its new bar unshown, as the + // reference does; the single flow shows it at once. self.tabs[i].scene.note_parametric_constraint_applied( scope, id, - self.constraint_bar_display, + if multiple { 0 } else { self.constraint_bar_display }, ); } let changes = touched diff --git a/src/modules/parametric/fixed.rs b/src/modules/parametric/fixed.rs index c4c641500..2860ac772 100644 --- a/src/modules/parametric/fixed.rs +++ b/src/modules/parametric/fixed.rs @@ -104,6 +104,10 @@ impl CadCommand for FixConstraintCommand { true } + fn typed_point_picks_entity(&self) -> bool { + matches!(self.step, Step::Object) + } + fn entity_pick_highlights_hover(&self) -> bool { true } diff --git a/src/modules/parametric/horizontal.rs b/src/modules/parametric/horizontal.rs index b4b98911b..ca2aea80f 100644 --- a/src/modules/parametric/horizontal.rs +++ b/src/modules/parametric/horizontal.rs @@ -269,6 +269,10 @@ impl CadCommand for HorizontalConstraintCommand { true } + fn typed_point_picks_entity(&self) -> bool { + matches!(self.step, Step::ObjectOrTwoPoints) + } + fn entity_pick_highlights_hover(&self) -> bool { true } diff --git a/src/scene/parametric_constraints.rs b/src/scene/parametric_constraints.rs index 0ab068550..4c9e87d34 100644 --- a/src/scene/parametric_constraints.rs +++ b/src/scene/parametric_constraints.rs @@ -1859,7 +1859,8 @@ impl super::Scene { let cam = self.camera.borrow(); (cam.view_proj_rte(bounds), cam.eye()) }; - set.constraints + let mut placements = set + .constraints .iter() .filter(|c| c.enabled) .filter(|c| { @@ -1952,7 +1953,25 @@ impl super::Scene { }) .collect::>() }) - .collect() + .collect::>(); + // The reference marks an object once for Equal however many + // relations of that kind it carries; the stacked duplicates only + // repeated the same badge. + let mut equal_anchors: Vec = Vec::new(); + placements.retain(|(_, point, _, label, _, _)| { + if label != "=" { + return true; + } + if equal_anchors + .iter() + .any(|seen| (seen.x - point.x).abs() < 0.5 && (seen.y - point.y).abs() < 0.5) + { + return false; + } + equal_anchors.push(*point); + true + }); + placements } /// Hit-tests screen point `p` (same coordinate space as `p_full` in the From 842ae461fce81c1f0eb815d9e5eb6a55831e4530 Mon Sep 17 00:00:00 2001 From: ramox81 <184937705+ramox81@users.noreply.github.com> Date: Mon, 21 Sep 2026 09:46:13 +0300 Subject: [PATCH 2/3] Equal: ask for the second object again after a refused pick, name the kind it needs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A second object of the wrong kind (a circle after a line, a line after a circle) or a pair that already carries Equal now reports and asks for the second object again instead of ending the command. The mismatch message names what the first object asks for — `Select a line segment, polyline segment, text, MText, major or minor axis of ellipse or elliptical arc.` after a length object, `Select a circle or arc.` after a radius object — and the same-pick message carries the reference's double space. Co-Authored-By: Claude Fable 5.1 --- src/app/command_driver.rs | 16 ++++++++++++---- src/modules/parametric/equal.rs | 6 +++++- src/modules/parametric/horizontal.rs | 2 +- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src/app/command_driver.rs b/src/app/command_driver.rs index 453754747..d93c47950 100644 --- a/src/app/command_driver.rs +++ b/src/app/command_driver.rs @@ -3357,8 +3357,13 @@ impl OpenCADStudio { || equal_size_follower(&self.tabs[i].scene.document, first, other) .is_none() { - self.command_line - .push_error(EqualConstraintCommand::INVALID_OBJECT); + // The reference names the kind the first object + // asks for. + let message = match equal_size(&self.tabs[i].scene.document, first) { + Some(EqualSize::Radius(_)) => EqualConstraintCommand::INVALID_RADIUS_OBJECT, + _ => EqualConstraintCommand::INVALID_LENGTH_OBJECT, + }; + self.command_line.push_error(message); continue; } let exists = self.tabs[i] @@ -3378,7 +3383,10 @@ impl OpenCADStudio { } followers.push(other); } - if multiple && !finishing { + // A refused second object is asked for again, as in the + // reference; Multiple keeps asking anyway. + let keep = (multiple && !finishing) || (!multiple && followers.is_empty()); + if keep { if let Some(prompt) = self.tabs[i].active_cmd.as_ref().map(|command| command.prompt()) { @@ -3601,7 +3609,7 @@ impl OpenCADStudio { ("No valid constraint point found.", Some(first)) } else { ( - "The object or point is already selected. Select a different object or constraint point.", + "The object or point is already selected. Select a different object or constraint point.", Some(first), ) }; diff --git a/src/modules/parametric/equal.rs b/src/modules/parametric/equal.rs index fde973082..023487e55 100644 --- a/src/modules/parametric/equal.rs +++ b/src/modules/parametric/equal.rs @@ -31,8 +31,12 @@ impl EqualConstraintCommand { pub const NO_OBJECT: &'static str = "No object found."; pub const INVALID_OBJECT: &'static str = "Invalid selection for Equal. Select a line, polyline segment, circle or arc."; + pub const INVALID_LENGTH_OBJECT: &'static str = + "Invalid selection for Equal. Select a line segment, polyline segment, text, MText, major or minor axis of ellipse or elliptical arc."; + pub const INVALID_RADIUS_OBJECT: &'static str = + "Invalid selection for Equal. Select a circle or arc."; pub const SAME_OBJECT: &'static str = - "The object or point is already selected. Select a different object or constraint point."; + "The object or point is already selected. Select a different object or constraint point."; pub fn new() -> Self { Self { diff --git a/src/modules/parametric/horizontal.rs b/src/modules/parametric/horizontal.rs index ca2aea80f..26de8718f 100644 --- a/src/modules/parametric/horizontal.rs +++ b/src/modules/parametric/horizontal.rs @@ -200,7 +200,7 @@ impl HorizontalConstraintCommand { if first.handle == second.handle && (first.point - second.point).length() <= 1.0e-9 { self.step = Step::SecondPoint(first); return CmdResult::ReportError( - "The object or point is already selected. Select a different object or constraint point." + "The object or point is already selected. Select a different object or constraint point." .to_string(), ); } From 959d0011d6ace9df2dcdc5bf4436c50723cc32bb Mon Sep 17 00:00:00 2001 From: ramox81 <184937705+ramox81@users.noreply.github.com> Date: Mon, 21 Sep 2026 09:58:57 +0300 Subject: [PATCH 3/3] Equal: show the bar of a Multiple pick at once, like the two-object flow A fresh reference session shows the "=" bar of every object made equal through Multiple right away; the earlier hidden state was not the rule. Co-Authored-By: Claude Fable 5.1 --- src/app/command_driver.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/app/command_driver.rs b/src/app/command_driver.rs index d93c47950..017600e12 100644 --- a/src/app/command_driver.rs +++ b/src/app/command_driver.rs @@ -3437,12 +3437,10 @@ impl OpenCADStudio { .scene .parametric_constraint_set_mut(scope) .add(ConstraintKind::Equal, vec![first, *follower], None); - // A Multiple pick leaves its new bar unshown, as the - // reference does; the single flow shows it at once. self.tabs[i].scene.note_parametric_constraint_applied( scope, id, - if multiple { 0 } else { self.constraint_bar_display }, + self.constraint_bar_display, ); } let changes = touched