You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Part of #326. Batch 2 — depends on #336 for TimePoint.
Reproducing the reel's camera shake took 155 sampled camera keyframes, generated by a Python loop evaluating a damped sine. GSAP writes the same motion as {x: 7, duration: .035, repeat: 11, yoyo: true}. AnimationTiming.repeat is a bool with no count, there is no yoyo, and EasingType has no steps, so a blinking caret and an oscillating offset both have to be spelled out keyframe by keyframe.
Do NOT write: schema/scenario.rs (#336 registers Scene.shake), cli/commands/geometry.rs (#334).
Deliverables
repeat: n — an integer count, with true still meaning infinite. This widens an existing bool, so the deserializer accepts both forms and nothing breaks.
yoyo: bool and repeat_delay, on any animation rather than on a fixed set of presets.
EasingType::Steps(n) — the blinking caret and anything else that must jump rather than interpolate.
Scene.shake — { impacts: [{ at, amplitude }], decay, frequency, rotation }, where at is a TimePoint so impacts can be written on the beat grid. Additive over camera, so a pan and a shake coexist rather than fighting over the same keyframe track.
PostEffect::Flash { at, color, intensity, duration }, which costs almost nothing once impacts exist and is what the reference reel pairs with every impact.
Acceptance
A six-impact shake written as six {at, amplitude} pairs replaces 155 hand-generated keyframes and renders the same motion
repeat: true on an existing scenario behaves exactly as it does today
A caret on steps(1) holds each state rather than fading between them
Part of #326. Batch 2 — depends on #336 for
TimePoint.Reproducing the reel's camera shake took 155 sampled camera keyframes, generated by a Python loop evaluating a damped sine. GSAP writes the same motion as
{x: 7, duration: .035, repeat: 11, yoyo: true}.AnimationTiming.repeatis a bool with no count, there is noyoyo, andEasingTypehas nosteps, so a blinking caret and an oscillating offset both have to be spelled out keyframe by keyframe.Owned files
crates/rustmotion-core/src/schema/animation.rs(EasingType::Steps, repeat widening)crates/rustmotion-core/src/schema/video.rs(AnimationTiming)crates/rustmotion-core/src/schema/shake.rs(new),crates/rustmotion-core/src/engine/shake.rs(new)crates/rustmotion-core/src/engine/animator.rs(modifier resolution — coordinate with Animate scalars that other attributes derive from #329, which owns variable tracks in the same file)Do NOT write:
schema/scenario.rs(#336 registersScene.shake),cli/commands/geometry.rs(#334).Deliverables
repeat: n— an integer count, withtruestill meaning infinite. This widens an existing bool, so the deserializer accepts both forms and nothing breaks.yoyo: boolandrepeat_delay, on any animation rather than on a fixed set of presets.EasingType::Steps(n)— the blinking caret and anything else that must jump rather than interpolate.Scene.shake—{ impacts: [{ at, amplitude }], decay, frequency, rotation }, whereatis aTimePointso impacts can be written on the beat grid. Additive overcamera, so a pan and a shake coexist rather than fighting over the same keyframe track.PostEffect::Flash { at, color, intensity, duration }, which costs almost nothing once impacts exist and is what the reference reel pairs with every impact.Acceptance
{at, amplitude}pairs replaces 155 hand-generated keyframes and renders the same motionrepeat: trueon an existing scenario behaves exactly as it does todaysteps(1)holds each state rather than fading between them