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)