Markers: the disk key keeps protected markers with a duration and drops a lone plain comp marker (#1083)

pixel_form_with borrowed the comp unchanged when it held only comp markers and no layer
markers, so a lone plain comp marker still reached the disk key. Tests: a lone comp marker
keeps the key; a protected marker with a duration (and its duration) on a stretched precomp's
source changes the key of the comp that nests it.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
vangel76
2026-10-13 19:07:25 +02:00
co-authored by Claude Sonnet 5.5
parent 46aa69482d
commit 6bf9c87a1a
2 changed files with 40 additions and 1 deletions
+39
View File
@@ -156,3 +156,42 @@ fn markers_keep_the_content_key_unless_an_expression_reads_them() {
s.execute("comp.addMarker", json!({"time": 1.0})).unwrap();
assert_ne!(key(&s), k1, "a marker read by an expression");
}
/// A comp marker alone (no layer marker beside it) keeps the key too.
#[test]
fn a_lone_comp_marker_keeps_the_content_key() {
let mut s = Session::default();
s.execute("comp.new", json!({"name": "M", "width": 8, "height": 8, "frameRate": 30, "duration": 2})).unwrap();
let cid = s.active_comp_id().unwrap();
s.execute("layer.newSolid", json!({"color": "#ff0000"})).unwrap();
let key = |s: &Session| effectcraft_render::disk_cache::comp_content_key(&s.project, cid);
let k0 = key(&s);
s.execute("comp.addMarker", json!({"time": 0.5, "comment": "beat"})).unwrap();
assert_eq!(key(&s), k0);
}
/// A protected marker with a duration retimes a stretched precomp layer (Responsive Design), so
/// changing it changes the key of the comp that nests it; a plain marker beside it does not.
#[test]
fn protected_markers_with_a_duration_change_the_content_key() {
let mut s = Session::default();
s.execute("comp.new", json!({"name": "Inner", "width": 8, "height": 8, "frameRate": 30, "duration": 4})).unwrap();
let inner = s.active_comp_id().unwrap();
s.execute("layer.newSolid", json!({"color": "#ff0000"})).unwrap();
s.execute("comp.new", json!({"name": "Outer", "width": 8, "height": 8, "frameRate": 30, "duration": 10})).unwrap();
let outer = s.active_comp_id().unwrap();
let l = s.execute("layer.addItem", json!({"item": inner.0})).unwrap()["layer"].as_u64().unwrap();
s.execute("layer.select", json!({"layers": [l]})).unwrap();
s.execute("layer.timeStretch", json!({"percent": 200})).unwrap();
let key = |s: &Session| effectcraft_render::disk_cache::comp_content_key(&s.project, outer);
let k0 = key(&s);
s.execute("comp.addMarker", json!({"comp": inner.0, "time": 2.0, "comment": "beat"})).unwrap();
assert_eq!(key(&s), k0, "a plain marker");
s.execute("comp.addMarker", json!({"comp": inner.0, "time": 1.0})).unwrap();
let index = s.project.comp(inner).unwrap().markers.iter().position(|m| m.time.seconds() == 1.0).unwrap();
s.execute("markers.set", json!({"comp": inner.0, "index": index, "duration": 1.0, "protected": true})).unwrap();
let k1 = key(&s);
assert_ne!(k1, k0, "a protected marker with a duration");
s.execute("markers.set", json!({"comp": inner.0, "index": index, "duration": 2.0})).unwrap();
assert_ne!(key(&s), k1, "its duration");
}
+1 -1
View File
@@ -931,7 +931,7 @@ impl Comp {
if !self.hide_shy
&& self.resolution.is_auto()
&& self.layers.iter().all(|l| l.switches == l.switches.pixels())
&& (with_markers || (self.markers.iter().all(|m| !is_timing_marker(m)) && self.layers.iter().all(|l| l.markers.is_empty())))
&& (with_markers || (self.markers.iter().all(is_timing_marker) && self.layers.iter().all(|l| l.markers.is_empty())))
{
return std::borrow::Cow::Borrowed(self);
}