Effects: Scribble has a Variation for Path Overlap, Curviness and Spacing, and stores 270° as -90°

The reference app's Scribble Options have a Variation for each of Path
Overlap, Curviness and Spacing. Scribble had one `variation`, which
moved each line's ends both along the line and across it, and every
turn of a scribble took the same curviness. An angle such as 270 was
stored as given.

Scribble now takes `overlapVariation` (pt, default 0.5), which moves
the ends along the line, `spacingVariation` (pt, 0.5), which moves
them across it, and `curvinessVariation` (%, 0), which varies the
curviness from one turn to the next. The dialog shows each Variation
after the option it varies, and the Appearance panel lists all three.
A Scribble saved or scripted with the earlier `variation` reads it as
the Path Overlap and Spacing variations. With the defaults, and with
the earlier `variation`, Scribble draws the same outline as before.
`effect.apply` and `effect.setParams` store an angle above -180 and up
to 180, so 270 is stored as -90, and the dialog shows the stored value.

The Appearance panel's inline editor lists an effect's values in
their current form, as the dialog does. It listed an earlier key next
to the defaults of the keys that replace it.

Docs: docs/effects-parity.md (Stylize row), docs/target-app-parity.md.
This commit is contained in:
dotCooCoo
2026-10-16 04:04:51 +07:00
committed by bflatastic
parent 6f9ee7825b
commit 04ed30a23d
10 changed files with 190 additions and 22 deletions
+18
View File
@@ -647,6 +647,24 @@ mod tests {
assert_eq!(params(&s), json!({"lightRotation": 0.0, "lightHeight": 60, "lightBehind": false}));
}
/// Scripts from before Scribble's separate variations give one `variation`, which is stored as the
/// Path Overlap and Spacing variations. An angle is stored above -180° and up to 180°.
#[test]
fn scribble_stores_an_earlier_variation_as_two_and_its_angle_within_180() {
let (mut s, id) = session_with_rect();
let p = json!({"effect": "stylize.scribble", "ids": [id.0], "item": null, "params": {"angle": 270, "variation": 2}});
s.execute("effect.apply", &p).unwrap();
let params = |s: &Session| node(s, id).appearance.effects[0].params.clone();
assert_eq!((params(&s)["angle"].as_f64(), params(&s).get("variation")), (Some(-90.0), None), "{}", params(&s));
assert_eq!((&params(&s)["overlapVariation"], &params(&s)["spacingVariation"]), (&json!(2), &json!(2)));
s.execute("effect.setParams", &json!({"index": 0, "params": {"angle": -200}, "ids": [id.0], "item": null})).unwrap();
assert_eq!(params(&s)["angle"].as_f64(), Some(160.0));
// A file of then stores its variation; setting one of the two keeps it for the other.
std::sync::Arc::make_mut(&mut s.doc_mut().unwrap().doc).node_mut(id).unwrap().appearance.effects[0].params = json!({"variation": 3});
s.execute("effect.setParams", &json!({"index": 0, "params": {"spacingVariation": 1}, "ids": [id.0], "item": null})).unwrap();
assert_eq!(params(&s), json!({"overlapVariation": 3, "spacingVariation": 1}));
}
fn effects_for_test(s: &Session, id: NodeId) -> vectorcraft_doc::Node {
effects::revolve_art(&node(s, id)).unwrap()
}