From 83e1ebd44a8928f32d33bba0f7eb59929e708cb8 Mon Sep 17 00:00:00 2001 From: Hakan Seven Date: Fri, 25 Sep 2026 22:20:16 +0300 Subject: [PATCH] fix(dimension): lay automatic text out from the style again (#1412) Since the stored text point became authoritative (85619f49), new linear and aligned dimensions drew their text at the placeholder the commands stored (the middle of the dimension line), so DIMTAD Above/Below and the text offset had no effect; a style or override edit left the stale point in place too. reset_automatic_text_position clears the point of text the user did not place, so it is laid out from the current settings. DIMLINEAR, DIMALIGNED, DIMBASELINE, DIMCONTINUE and QDIM call it on creation; a DIMSTYLE edit, a dimension override row and a style change call it for the dimensions they touch. Loaded, untouched dimensions keep their pictured position. Co-Authored-By: Claude Opus 5.5 --- src/app/update/style.rs | 5 +++++ src/entities/dim_override.rs | 17 +++++++++++++++++ src/entities/dimension.rs | 11 +++++++++++ src/modules/annotate/aligned_dim.rs | 1 + src/modules/annotate/dim_baseline.rs | 2 ++ src/modules/annotate/dim_continue.rs | 8 ++++++-- src/modules/annotate/linear_dim.rs | 1 + src/modules/annotate/qdim.rs | 1 + 8 files changed, 44 insertions(+), 2 deletions(-) diff --git a/src/app/update/style.rs b/src/app/update/style.rs index 5e2ebf147..3313a9a3f 100644 --- a/src/app/update/style.rs +++ b/src/app/update/style.rs @@ -479,6 +479,11 @@ impl OpenCADStudio { }) .collect(); for handle in stale { + if let Some(codec::EntityType::Dimension(dimension)) = + self.tabs[tab].scene.document.get_entity_mut(handle) + { + crate::entities::dimension::reset_automatic_text_position(dimension.base_mut()); + } self.tabs[tab].scene.invalidate_dim_block_recorded(handle); } diff --git a/src/entities/dim_override.rs b/src/entities/dim_override.rs index 1b1f4b9b4..3739456f2 100644 --- a/src/entities/dim_override.rs +++ b/src/entities/dim_override.rs @@ -450,11 +450,28 @@ fn split_template(value: &str) -> (&str, &str) { value.split_once("<>").unwrap_or(("", value)) } +/// Apply a dimension override row. A changed override lays automatic text +/// out afresh, so e.g. a new DIMTAD moves it off the stored position. pub fn set_property( doc: &mut CadDocument, handle: Handle, field: &str, value: &str, +) -> bool { + let applied = apply_property(doc, handle, field, value); + if applied { + if let Some(EntityType::Dimension(dimension)) = doc.get_entity_mut(handle) { + crate::entities::dimension::reset_automatic_text_position(dimension.base_mut()); + } + } + applied +} + +fn apply_property( + doc: &mut CadDocument, + handle: Handle, + field: &str, + value: &str, ) -> bool { let trimmed = value.trim(); if field == "dim_center_type" { diff --git a/src/entities/dimension.rs b/src/entities/dimension.rs index 337bd7118..a4b105512 100644 --- a/src/entities/dimension.rs +++ b/src/entities/dimension.rs @@ -373,6 +373,7 @@ fn apply_base_prop(base: &mut DimensionBase, field: &str, value: &str) -> bool { } "style_name" => { base.style_name = value.to_string(); + reset_automatic_text_position(base); true } // Editing the text position in the properties panel pins it to a @@ -7620,6 +7621,16 @@ fn stored_text_point(dim: &Dimension) -> Option { (p.x * p.x + p.y * p.y + p.z * p.z > 1e-16).then_some(p) } +/// Clear an automatic text position so the dimension is laid out from its +/// current settings again. A loaded point is kept so a drawing looks as it +/// was drawn; a new dimension, or one whose style or overrides just changed, +/// has no valid one. Text the user placed keeps its point (#1412). +pub(crate) fn reset_automatic_text_position(base: &mut DimensionBase) { + if !base.text_user_positioned { + base.text_middle_point = Vector3::new(0.0, 0.0, 0.0); + } +} + /// The point on the circle a radial leader leaves from: the arc point of a /// radius, or whichever end of a diameter's chord is nearer the text. fn radial_leader_tip(dim: &Dimension, text: Vector3) -> Vector3 { diff --git a/src/modules/annotate/aligned_dim.rs b/src/modules/annotate/aligned_dim.rs index c43bb6772..aba871423 100644 --- a/src/modules/annotate/aligned_dim.rs +++ b/src/modules/annotate/aligned_dim.rs @@ -92,6 +92,7 @@ pub(crate) fn aligned_dimension_entity( let (d1, d2) = dim_line_endpoints(first, second, point); dim.base.text_middle_point = v3((d1 + d2) * 0.5); dim.base.insertion_point = dim.base.text_middle_point; + crate::entities::dimension::reset_automatic_text_position(&mut dim.base); dim.base.actual_measurement = dim.measurement(); crate::entities::dimension::set_dimension_text_override(&mut dim.base, text_override); EntityType::Dimension(Dimension::Aligned(dim)) diff --git a/src/modules/annotate/dim_baseline.rs b/src/modules/annotate/dim_baseline.rs index 2425feec3..63ffdf79f 100644 --- a/src/modules/annotate/dim_baseline.rs +++ b/src/modules/annotate/dim_baseline.rs @@ -546,6 +546,7 @@ fn build_linear( result.base.definition_point = result.definition_point; result.base.text_middle_point = world(plane, first_line.lerp(second_line, 0.5)); result.base.insertion_point = result.base.text_middle_point; + crate::entities::dimension::reset_automatic_text_position(&mut result.base); Some(Dimension::Aligned(result)) } else { let mut result = DimensionLinear::new(world(plane, fixed), world(plane, point)); @@ -554,6 +555,7 @@ fn build_linear( result.base.definition_point = result.definition_point; result.base.text_middle_point = world(plane, first_line.lerp(second_line, 0.5)); result.base.insertion_point = result.base.text_middle_point; + crate::entities::dimension::reset_automatic_text_position(&mut result.base); Some(Dimension::Linear(result)) } } diff --git a/src/modules/annotate/dim_continue.rs b/src/modules/annotate/dim_continue.rs index 8ae02d021..2de9dcd40 100644 --- a/src/modules/annotate/dim_continue.rs +++ b/src/modules/annotate/dim_continue.rs @@ -453,6 +453,7 @@ fn build_linear( result.base.definition_point = result.definition_point; result.base.text_middle_point = world(plane, first_line.lerp(second_line, 0.5)); result.base.insertion_point = result.base.text_middle_point; + crate::entities::dimension::reset_automatic_text_position(&mut result.base); Dimension::Linear(result) } @@ -565,7 +566,8 @@ fn preview_for_dimension(dimension: &Dimension) -> WireModel { project(&plane, value.second_point), value.rotation, project(&plane, value.definition_point), - project(&plane, value.base.text_middle_point), + (value.base.text_middle_point != Vector3::ZERO) + .then(|| project(&plane, value.base.text_middle_point)), value.base.actual_measurement, ); } @@ -634,7 +636,7 @@ fn linear_preview( second: Vec2, rotation: f64, definition: Vec2, - text: Vec2, + text: Option, measurement: f64, ) { let axis = Vec2::new(rotation.cos(), rotation.sin()); @@ -642,6 +644,8 @@ fn linear_preview( let coordinate = definition.dot(perpendicular); let first_line = project_to_line(first, perpendicular, coordinate); let second_line = project_to_line(second, perpendicular, coordinate); + // Automatic text stores no point; mark the middle of the dimension line. + let text = text.unwrap_or_else(|| first_line.lerp(second_line, 0.5)); segment(points, plane, first, first_line); segment(points, plane, second, second_line); segment(points, plane, first_line, second_line); diff --git a/src/modules/annotate/linear_dim.rs b/src/modules/annotate/linear_dim.rs index 90cc913be..27149b707 100644 --- a/src/modules/annotate/linear_dim.rs +++ b/src/modules/annotate/linear_dim.rs @@ -140,6 +140,7 @@ pub(crate) fn linear_dimension_entity( dim.base.definition_point = dim.definition_point; dim.base.text_middle_point = v3(linear_text_pos(first, second, point, axis)); dim.base.insertion_point = dim.base.text_middle_point; + crate::entities::dimension::reset_automatic_text_position(&mut dim.base); dim.base.actual_measurement = dim.measurement(); crate::entities::dimension::set_dimension_text_override(&mut dim.base, text_override); EntityType::Dimension(Dimension::Linear(dim)) diff --git a/src/modules/annotate/qdim.rs b/src/modules/annotate/qdim.rs index ae56fdeb4..9dfe42d02 100644 --- a/src/modules/annotate/qdim.rs +++ b/src/modules/annotate/qdim.rs @@ -201,6 +201,7 @@ impl QdimCommand { dimension.base.definition_point = v3(definition); dimension.base.text_middle_point = v3(text); dimension.base.insertion_point = v3(text); + crate::entities::dimension::reset_automatic_text_position(&mut dimension.base); dimension.base.actual_measurement = dimension.measurement(); let association = DimensionAssociationInput::Explicit(vec![first.sources.first().copied(), second.sources.first().copied()]); (self.plane.place_entity(EntityType::Dimension(Dimension::Linear(dimension))), association)