Animations: add 34 PowerPoint motion path presets

Adds Basic (stars, heart, crescent moon, teardrop, ...), Lines & Curves
(zigzag, waves, S curves, spirals, bounces, ...) and Special (figure 8,
bean, peanut, neutron, ...) motion paths with PowerPoint preset ids, so
they appear in the Motion Paths gallery, play back, and round-trip
through PPTX.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Nikita Rakitin
2026-10-13 23:37:00 +03:00
co-authored by Cursor
parent 457406a7a5
commit d4175d2902
6 changed files with 225 additions and 3 deletions
+1
View File
@@ -69,6 +69,7 @@ pub(crate) fn emphasis_persists(effect: &str) -> bool {
fn uses_default_smoothing(effect: &str) -> bool {
matches!(effect, "fly" | "float" | "rise" | "peek" | "lines" | "arcs" | "turns" | "shapes" | "loops" | "customPath")
|| deckcraft_model::anim::preset_path(effect).is_some()
}
impl EffectSpec {
+22 -1
View File
@@ -288,6 +288,27 @@ pub fn default_path(effect: &str, option: &str) -> String {
}
},
"loops" => "M 0 0 C 0.08 -0.1 0.16 0 0.08 0.05 C 0 0.1 -0.08 0.1 -0.08 0 C -0.08 -0.1 0 -0.05 0 0 E".into(),
_ => String::new(),
other => deckcraft_model::anim::preset_path(other).unwrap_or_default(),
}
}
#[cfg(test)]
mod preset_path_tests {
use super::*;
#[test]
fn every_extra_motion_path_preset_starts_at_its_shape_and_moves() {
use deckcraft_model::anim::{ANIMATIONS, AnimClass, preset_path};
let extra: Vec<_> = ANIMATIONS.iter().filter(|a| a.2 == AnimClass::Path && preset_path(a.0).is_some()).collect();
assert!(extra.len() >= 30);
for a in extra {
assert_eq!(default_path(a.0, ""), preset_path(a.0).unwrap_or_default());
let mp = MotionPath::parse(&default_path(a.0, ""));
let (x, y) = mp.at(0.0);
assert!(x.abs() < 1e-9 && y.abs() < 1e-9, "{} starts at its shape", a.0);
let far = mp.points.iter().map(|p| p.0.abs() + p.1.abs()).fold(0.0, f64::max);
assert!(far > 0.05, "{} moves", a.0);
assert!(mp.points.iter().all(|p| p.0.abs() < 0.5 && p.1.abs() < 0.5), "{} stays near its shape", a.0);
}
}
}