{"version":"1.0","video":{"width":1920,"height":1080,"fps":30,"background":"#FFFFFF"},"scenes":[{"duration":1.0,"children":[{"type":"pointer","position":"absolute","x":0,"y":0,"size":220,"tone":"dark","path":[{"time":0.0,"x":1900,"y":1000},{"time":0.6,"x":900,"y":500}],"path_easing":"linear","style":{"animation":[{"name":"motion_blur","samples":12,"shutter":3.0}]}}]}]}
Context
Follow-up of #359, #360, #361 and #362. A user building a one-take product film called camera and container motion blur one of their three main blockers.
To do
pointermoved bypathis never ghosted (motion_blur and trail ghosts take flex slots again, drop a node's children, and ignore pointer paths #359): a pointer withpathandmotion_blurrenders pixel-identical to the same pointer without it; the same pointer moved bytranslate_x/ykeyframes trails correctly.{"version":"1.0","video":{"width":1920,"height":1080,"fps":30,"background":"#FFFFFF"},"scenes":[{"duration":1.0,"children":[{"type":"pointer","position":"absolute","x":0,"y":0,"size":220,"tone":"dark","path":[{"time":0.0,"x":1900,"y":1000},{"time":0.6,"x":900,"y":500}],"path_easing":"linear","style":{"animation":[{"name":"motion_blur","samples":12,"shutter":3.0}]}}]}]}gapof a column; in a row "Hello" + "World" withmotion_bluron "World", a ghost "World" is painted over "Hello").mode: "smear"is axis-aligned (A directional blur: blur_x/blur_y, a smear mode for motion_blur, and per-unit blur axis in char_* presets #360): a 45° move gives an isotropic blob instead of a diagonal streak. Orient the streak along the velocity.radius_x/radius_y(snake_case) validate and are silently ignored; onlyradius-x/radius-ywork (A directional blur: blur_x/blur_y, a smear mode for motion_blur, and per-unit blur axis in char_* presets #360). Accept both or reject the snake_case form.whipstreak is stepped (A whip transition: a slide with a directional streak along its axis #361): about ten discrete copies are visible mid-transition. Make it continuous.camera.motion_blur: { "samples": 8, "shutter": 0.5 }, accumulating sub-frame camera positions only on frames where the camera moves, with the cost documented.Definition of done
mainis written first. For anything visual it is a render test (scenario → frame → pixel assertions); tests that buildAnimatedPropertiesby hand are not enough — that is exactly how the regressions listed here slipped through.rustmotion validate, render, image inspected.cargo fmt --all --check,cargo clippy --workspace --all-targets -- -D warnings,cargo test --workspacepass.crates/rustmotion/skills/SKILL.md, the relevantrules/file and the exported schema. A field the validator accepts must have an effect, otherwise the validator rejects it or warns.<type>: <verb> <message>. No AI attribution in commits, PRs or issue comments.