mirror of
https://github.com/storytold/effectcraft.git
synced 2026-10-14 19:27:05 -04:00
Work area: an edit never clamps with crossed bounds (#605 follow-up)
A project saved with an inverted work area, or a comp shorter than a frame, made Tick::clamp panic on the next start or end edit. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01QiAJeFttZp83Fh7YuzAR5f
This commit is contained in:
2 files changed
+17
-2
No files matched your search
@@ -182,10 +182,11 @@ fn work_area(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
_ => {}
|
||||
}
|
||||
if let Some(b) = begin {
|
||||
c.work_area.0 = b.clamp(Tick::ZERO, c.duration - fd);
|
||||
// min/max, not clamp: the bounds cross on a comp shorter than a frame or an inverted area.
|
||||
c.work_area.0 = b.min(c.duration - fd).max(Tick::ZERO);
|
||||
}
|
||||
if let Some(e) = end {
|
||||
c.work_area.1 = e.clamp(c.work_area.0 + fd, c.duration);
|
||||
c.work_area.1 = e.max(c.work_area.0 + fd).min(c.duration);
|
||||
}
|
||||
// A start on its own can land after the current end. Pull it back so the interval
|
||||
// still covers one frame, the same rule as `set: "begin"`.
|
||||
|
||||
@@ -196,6 +196,7 @@ fn separated_position_follows_canvas_resize_and_crop() {
|
||||
placed(&separated, b, 1.0, 50.0, 30.0);
|
||||
assert_eq!(opaque_bounds(&separated, Tick::ZERO), (70, 70, 25, 25, 34, 34, 100));
|
||||
assert_eq!(opaque_bounds(&separated, Tick::from_seconds_f64(1.0)), (70, 70, 45, 25, 54, 34, 100));
|
||||
}
|
||||
|
||||
/// Pixel-centre of the opaque samples, so a 10×10 solid centred on (11, 22) reports (11, 22).
|
||||
fn opaque_centroid(s: &Session) -> (f64, f64, u32) {
|
||||
@@ -399,6 +400,19 @@ fn lift_and_extract_work_area() {
|
||||
assert!((spans[1].0 - 2.0).abs() < 1e-6 && (spans[1].1 - 8.0).abs() < 1e-6, "{spans:?}");
|
||||
}
|
||||
|
||||
/// A project saved with an inverted work area (by an older build) is edited without a panic:
|
||||
/// `clamp` with crossed bounds would abort.
|
||||
#[test]
|
||||
fn an_inverted_saved_work_area_takes_an_end_edit() {
|
||||
let mut s = comp();
|
||||
let cid = s.active_comp_id().unwrap();
|
||||
std::sync::Arc::make_mut(&mut s.project).comp_mut(cid).unwrap().work_area = (Tick::from_seconds_f64(9.0), Tick::from_seconds_f64(2.0));
|
||||
s.execute("comp.workArea", json!({"end": 1.0})).unwrap();
|
||||
s.execute("comp.workArea", json!({"start": 50.0})).unwrap();
|
||||
let c = s.active_comp().unwrap();
|
||||
assert!(c.work_area.0 >= Tick::ZERO && c.work_area.0 + c.frame_duration() <= c.work_area.1 && c.work_area.1 <= c.duration);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn work_area_stays_ordered_when_the_start_passes_the_end() {
|
||||
let ordered = |s: &Session| {
|
||||
|
||||
Reference in new issue
Block a user