Properties: changing a block's scale moves and resizes its attributes (#481) (#579)

Squash of PR #579 by @MarekSpodBiedry.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
MarekSpodBiedry
2026-10-11 13:41:10 -04:00
committed by GitHub
co-authored by Claude Opus 5.5
parent 63a0ab4a32
commit fc30f2c2ea
2 changed files with 48 additions and 0 deletions
+11
View File
@@ -328,6 +328,17 @@ fn run_set(s: &mut Session, p: &Value) -> Result<Value> {
i.rotation = x.to_radians();
}
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.
if x > 0.0 && i.scale.x > 0.0 {
let m = cadcraft_geom::Mat3::scale_about(i.insert.xy(), x / i.scale.x);
for a in &mut i.attribs {
let mut k = EntityKind::Text(a.text.clone());
k.transform(&m);
if let EntityKind::Text(t) = k {
a.text = t;
}
}
}
i.scale = Vec3::new(x, x, x);
}
}
@@ -0,0 +1,37 @@
//! Setting a block reference's scale through Properties moves and resizes its attributes like SCALE
//! about the insertion point (#481).
use cadcraft_engine::Session;
use cadcraft_engine::doc::{EntityKind, Handle};
use serde_json::json;
fn setup(at: [f64; 2], scale: f64) -> (Session, Handle) {
let mut s = Session::new();
s.execute("attdef", &json!({"tag": "TAG", "at": [10, 0], "height": 2.5, "default": "D"})).unwrap();
let hs: Vec<String> = s.doc().unwrap().model.iter().map(|e| e.handle.hex()).collect();
s.execute("block", &json!({"name": "B", "base": [0, 0], "handles": hs, "keep": "delete"})).unwrap();
let r = s.execute("insert", &json!({"name": "B", "at": at, "scale": scale, "attribs": {"TAG": "hello"}})).unwrap();
(s, Handle::parse_hex(r["handle"].as_str().unwrap()).unwrap())
}
fn attrib(s: &Session, h: Handle) -> (f64, f64, f64, String, f64, f64) {
let EntityKind::Insert(i) = &s.doc().unwrap().entity(h).unwrap().kind else { panic!("not an insert") };
let a = &i.attribs[0].text;
(a.insert.x, a.insert.y, a.height, a.value.clone(), i.scale.x, i.insert.x)
}
#[test]
fn scale_property_moves_and_resizes_attribute() {
let (mut s, h) = setup([0.0, 0.0], 1.0);
s.execute("properties.set", &json!({"handles": [h.hex()], "scale": 2})).unwrap();
let (x, y, height, value, scale, ix) = attrib(&s, h);
assert_eq!((x, y, height, value.as_str(), scale, ix), (20.0, 0.0, 5.0, "hello", 2.0, 0.0));
}
#[test]
fn scale_property_is_absolute_about_the_insertion_point() {
let (mut s, h) = setup([7.0, 11.0], 2.0);
s.execute("properties.set", &json!({"handles": [h.hex()], "scale": 3})).unwrap();
let (x, y, height, value, scale, ix) = attrib(&s, h);
assert_eq!((x, y, height, value.as_str(), scale, ix), (37.0, 11.0, 7.5, "hello", 3.0, 7.0));
}