mirror of
https://github.com/storytold/effectcraft.git
synced 2026-10-30 21:16:52 -06:00
Shapes: Wiggle Paths has Spatial Phase, which slides its wiggle along the path
Wiggle Paths had Size, Detail, Points, Wiggles/Second, Correlation, Temporal Phase and Random Seed, but no Spatial Phase, which After Effects lists among its properties (ADBE Vector Spatial Phase). Spatial Phase now moves each point's own displacement along its subpath: 360 degrees is once around, and a fraction of a point is interpolated between neighbors. At 0 degrees a path draws as before. A project saved without the property gets it at 0 degrees, after Temporal Phase, when it opens. Scripts can read and set every Wiggle Paths property by its match name.
This commit is contained in:
@@ -317,6 +317,38 @@ fn wiggle_full_correlation_translates() {
|
||||
assert_eq!(zero[0], s[0]);
|
||||
}
|
||||
|
||||
/// Spatial Phase moves the pattern of displacements along the path: 360° is once around, and a
|
||||
/// whole number of points' worth gives each point the displacement of the point that far ahead.
|
||||
#[test]
|
||||
fn wiggle_spatial_phase_moves_the_pattern_along_the_path() {
|
||||
let s = [sq(0.0, 0.0, 100.0)];
|
||||
let w = WiggleParams { detail: 3.0, correlation: 0.0, smooth: false, ..Default::default() };
|
||||
// Displacements are proportional to Size: twice the size less once the size.
|
||||
let disp = |w: WiggleParams| -> Vec<Vec2> {
|
||||
let a = on_curve(&wiggle(&s, &w, 0.4)[0]);
|
||||
let b = on_curve(&wiggle(&s, &WiggleParams { size: w.size * 2.0, ..w }, 0.4)[0]);
|
||||
a.iter().zip(&b).map(|(a, b)| *b - *a).take(16).collect()
|
||||
};
|
||||
let d0 = disp(w);
|
||||
let n = d0.len();
|
||||
assert_eq!(n, 16);
|
||||
for k in [1, 5] {
|
||||
let dk = disp(WiggleParams { spatial_phase_deg: 360.0 * k as f64 / n as f64, ..w });
|
||||
for j in 0..n {
|
||||
let e = d0[(j + k) % n];
|
||||
assert!(close(dk[j].x, e.x, 1e-9) && close(dk[j].y, e.y, 1e-9), "{k} ahead, point {j}: {:?} vs {e:?}", dk[j]);
|
||||
}
|
||||
}
|
||||
// Whole turns either way leave the path as it is.
|
||||
let base = wiggle(&s, &w, 0.4);
|
||||
assert_eq!(wiggle(&s, &WiggleParams { spatial_phase_deg: 360.0, ..w }, 0.4), base);
|
||||
assert_eq!(wiggle(&s, &WiggleParams { spatial_phase_deg: -720.0, ..w }, 0.4), base);
|
||||
// Half a point ahead, the displacements change and stay within Size.
|
||||
let half = disp(WiggleParams { spatial_phase_deg: 180.0 / n as f64, ..w });
|
||||
assert!(half.iter().zip(&d0).any(|(h, d)| (*h - *d).hypot() > 1e-3));
|
||||
assert!(half.iter().all(|h| h.x.abs() <= 10.0 + 1e-9 && h.y.abs() <= 10.0 + 1e-9));
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------- merge / booleans
|
||||
|
||||
fn inclusion_exclusion(a: BezPath, b: BezPath) {
|
||||
|
||||
Reference in New Issue
Block a user