diff --git a/crates/engine/src/cmd/props.rs b/crates/engine/src/cmd/props.rs index 0259fac..31618f8 100644 --- a/crates/engine/src/cmd/props.rs +++ b/crates/engine/src/cmd/props.rs @@ -326,7 +326,19 @@ fn run_set(s: &mut Session, p: &Value) -> Result { } EntityKind::Insert(i) => { if let Some(x) = num("rotation") { + let turn = x.to_radians() - i.rotation; i.rotation = x.to_radians(); + // The attached text turns with the reference, around its insertion point (as ROTATE does). + let base = i.insert.xy(); + for a in &mut i.attribs { + let t = &mut a.text; + for q in std::iter::once(&mut t.insert).chain(t.align_pt.as_mut()) { + let r = q.xy().rotate_about(base, turn); + q.x = r.x; + q.y = r.y; + } + t.rotation = cadcraft_geom::norm_angle(t.rotation + turn); + } } if let Some(x) = num("scale").filter(|x| *x != 0.0) { // A new positive scale carries the attached attribute text with it, like SCALE about the insertion point. diff --git a/crates/engine/src/tests.rs b/crates/engine/src/tests.rs index dffd824..1955683 100644 --- a/crates/engine/src/tests.rs +++ b/crates/engine/src/tests.rs @@ -1121,3 +1121,22 @@ fn press_and_drag_selection_window() { assert!(!s.begin_window(Vec2::new(f64::NAN, 0.0))); assert!(s.pending_window.is_none()); } + +#[test] +fn block_rotation_property_turns_attribute_text() { + let mut s = Session::new(); + s.execute("attdef", &json!({"tag": "TAG", "at": [10, 0], "default": "D", "height": 2.5})).unwrap(); + let def = s.doc().unwrap().model.last().unwrap().handle; + s.execute("block", &json!({"name": "B", "base": [0, 0], "handles": [def.hex()], "keep": "delete"})).unwrap(); + s.execute("insert", &json!({"name": "B", "at": [0, 0], "attribs": {"TAG": "hello"}})).unwrap(); + let h = s.doc().unwrap().model.last().unwrap().handle; + s.execute("properties.set", &json!({"handles": [h.hex()], "rotation": 90})).unwrap(); + let doc = s.doc().unwrap(); + let Some(EntityKind::Insert(i)) = doc.model.last().map(|e| &e.kind) else { panic!("no insert") }; + let t = &i.attribs[0].text; + assert!((i.rotation - std::f64::consts::FRAC_PI_2).abs() < 1e-9); + assert!(t.insert.x.abs() < 1e-9 && (t.insert.y - 10.0).abs() < 1e-9, "text at {:?}", t.insert); + assert!((t.rotation - std::f64::consts::FRAC_PI_2).abs() < 1e-9); + assert_eq!(t.value, "hello"); + assert!((t.height - 2.5).abs() < 1e-12); +}