M5.2–M5.5: keyframe clipboard, easy ease, velocity/interpolation dialogs, roving, time remap/stretch/reverse/freeze, graph editor, separate dimensions, pick-whip

Engine (all commands with undo/redo + tests in engine/src/tests_timeline.rs):
- keys.copy/paste (Edit Copy/Cut/Paste route to keys when keys are selected;
  relative timing kept, paste at CTI, cross-property paste of same type),
  keys.selectAll (Cmd+Alt+A), keys.nudge* (Alt+Arrow, Alt+Shift+Arrow),
  keys.set / keys.setEase (graph editor drags), keys.info (dialog data),
  keys.timeReverse; keys.interpolation gains continuous/auto Bezier, spatial
  interpolation and roving; keys.velocity takes per-dimension values and
  Continuous.
- Roving keys (keyframe::retime_roving): constant speed along the motion path.
- Layer > Time: layer.timeStretch (percent|duration, hold in/current/out),
  layer.timeReverse (Cmd+Alt+R), layer.enableTimeRemap (Cmd+Alt+T),
  layer.freezeFrame, layer.freezeOnLastFrame; render uses Time Remap as the
  source time for precomp/footage layers.
- prop.separateDimensions (X/Y/Z Position; prop.set on Position writes them).
- layer.setParent compensates so the layer stays in place (compensate:false
  to opt out).
- prop.pickWhip writes AE-style reference expressions (thisComp.layer(..),
  effect(..)(..), mask(..).maskFeather, temp=…;[temp,temp], …[0]).
- prop.setExpression: syntax errors keep the text but disable the expression.
- expr: arrays of properties returned by an expression are resolved.

UI: Keyframe Velocity, Keyframe Interpolation and Time Stretch dialogs;
Graph Editor (value + speed graphs, draggable keys and Bezier/influence
handles, auto-zoom, fit, show selected, separate dimensions, hold/linear/
auto Bezier/Easy Ease buttons); key + layer context menus. Clears the
workspace clippy -D warnings failures.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Brandon Thomas
2026-10-01 21:47:29 -04:00
co-authored by Claude Opus 5.5
parent dee16181fe
commit 951ed1fa3d
29 changed files with 2705 additions and 203 deletions
+2 -1
View File
@@ -22,7 +22,8 @@ fn open(s: &mut Session, args: &[String]) {
eprintln!("effectcraft: {e}");
std::process::exit(1);
}
} else if args.iter().any(|a| a == "--demo") || true {
} else {
// `--demo` or no project: the demo project.
let _ = s.execute("file.openDemoProject", json!({}));
}
}