diff --git a/src/app/update/dynamic.rs b/src/app/update/dynamic.rs index 5a4be7276..f6b76b849 100644 --- a/src/app/update/dynamic.rs +++ b/src/app/update/dynamic.rs @@ -212,8 +212,15 @@ impl OpenCADStudio { .unwrap_or(glam::Vec3::ZERO); // Buffer value parsed as f32 (de-scaled by the role so a typed diameter // becomes a radius), or the supplied geometric live value. Width/Height - // are shown unsigned, so a typed value takes the sign of the cursor's - // delta on that axis (`live` is the signed delta in the cartesian arms). + // are shown unsigned, so a typed value normally takes the sign of the + // cursor's delta on that axis (`live` is the signed delta in the + // cartesian arms). But once the user separates the two values with `,` + // — e.g. the rectangle opposite corner entered as "50,50" — the entry + // is a cartesian coordinate pair, not cursor-signed W/H dimensions, so + // the typed sign must stay literal. `,` is the only thing that sets + // `dyn_user_reshaped`, so it cleanly distinguishes comma-cartesian entry + // from Tab-separated dimension entry (#269). + let comma_cartesian = self.dyn_user_reshaped; let val = |idx: usize, live: f32| -> f32 { match fields[idx] .buffer @@ -226,7 +233,8 @@ impl OpenCADStudio { if matches!( fields[idx].role, crate::command::DynRole::Width | crate::command::DynRole::Height - ) { + ) && !comma_cartesian + { v.abs().copysign(live) } else { v diff --git a/src/app/view/controls.rs b/src/app/view/controls.rs index 15c0ca376..92c73cd56 100644 --- a/src/app/view/controls.rs +++ b/src/app/view/controls.rs @@ -194,6 +194,7 @@ pub(super) fn dyn_component_value( w: glam::Vec3, base: Option, xf: &super::super::helpers::UcsXform, + comma_cartesian: bool, ) -> String { if let Some(b) = &f.buffer { return b.clone(); @@ -211,8 +212,12 @@ pub(super) fn dyn_component_value( // coordinate use the same frame. See #35. let has_base = base.is_some(); // Width / Height read as unsigned magnitudes (the sign is taken from the - // cursor side on commit), matching the rectangle's two-edge entry. - let wh = matches!(f.role, crate::command::DynRole::Width | crate::command::DynRole::Height); + // cursor side on commit), matching the rectangle's two-edge entry. But once + // the user separates the values with `,` the entry is a cartesian + // coordinate pair, so the fields read as signed X/Y deltas to match the + // committed point (#269). + let wh = matches!(f.role, crate::command::DynRole::Width | crate::command::DynRole::Height) + && !comma_cartesian; match f.component { DynComponent::X if has_base => format!("{:.4}", if wh { dx.abs() } else { dx }), DynComponent::Y if has_base => format!("{:.4}", if wh { dy.abs() } else { dy }), diff --git a/src/app/view/mod.rs b/src/app/view/mod.rs index e2451fb76..b1ff7434c 100644 --- a/src/app/view/mod.rs +++ b/src/app/view/mod.rs @@ -524,7 +524,13 @@ impl OpenCADStudio { { format!("{lv:.4}") } - _ => dyn_component_value(f, w, base, &tab.ucs_xform()), + _ => dyn_component_value( + f, + w, + base, + &tab.ucs_xform(), + self.dyn_user_reshaped, + ), }; crate::ui::overlay::DynBox { label: f.role.label().to_string(),