mirror of
https://github.com/storytold/effectcraft.git
synced 2026-10-29 12:37:08 -06:00
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
//! Edit menu.
|
||||
|
||||
use effectcraft_color::Label;
|
||||
use effectcraft_keyframe::Value as KV;
|
||||
use effectcraft_project::{Comp, Expression, ItemKind, Layer, LayerId, LayerSource, TrackMatte};
|
||||
use effectcraft_time::Tick;
|
||||
use serde_json::{Value, json};
|
||||
@@ -201,6 +202,21 @@ fn delete(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
if l.track_matte.is_some_and(|m| ids.contains(&m.layer)) {
|
||||
l.track_matte = None;
|
||||
}
|
||||
// A layer-reference property (an Environment light's Source, an effect's Clone Source,
|
||||
// Back Layer…) must read as None once its layer is gone, in this same history step: a
|
||||
// dead id renders as nothing while the UI shows "None", which means "fall back to the
|
||||
// comp's Environment Layer" (#2153). Keys carry the same value kind as the property.
|
||||
l.props.walk_mut(&mut |p| {
|
||||
let dead = |v: &KV| matches!(v, KV::Layer(Some(id)) if ids.contains(&LayerId(*id)));
|
||||
if dead(&p.value) {
|
||||
p.value = KV::Layer(None);
|
||||
}
|
||||
for k in &mut p.keys {
|
||||
if dead(&k.value) {
|
||||
k.value = KV::Layer(None);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
st.selected_layers.clear();
|
||||
st.selected_props.clear();
|
||||
|
||||
@@ -131,6 +131,23 @@ fn environment_light_is_listed_and_takes_a_source_layer() {
|
||||
assert_eq!(prop(&s, env, "lightOptions/source").as_layer(), None);
|
||||
}
|
||||
|
||||
/// Deleting the layer a Source points at leaves no dangling id: "None" means the comp's
|
||||
/// Environment Layer, and a dead id rendered as nothing at all (#2153).
|
||||
#[test]
|
||||
fn deleting_a_source_layer_clears_the_reference() {
|
||||
let mut s = session();
|
||||
let sky = s.execute("layer.newSolid", json!({"width": 256, "height": 128, "name": "Sky"})).unwrap()["layer"].as_u64().unwrap();
|
||||
let env = s.execute("layer.newLight", json!({"kind": "Environment", "name": "Env"})).unwrap()["layer"].as_u64().unwrap();
|
||||
s.execute("prop.set", json!({"layer": env, "path": "lightOptions/source", "value": sky})).unwrap();
|
||||
assert_eq!(prop(&s, env, "lightOptions/source").as_layer(), Some(sky));
|
||||
s.execute("edit.clear", json!({"layers": [sky]})).unwrap();
|
||||
assert_eq!(prop(&s, env, "lightOptions/source").as_layer(), None, "the reference goes with the layer");
|
||||
// One history step with the delete, so undo brings both back.
|
||||
s.undo();
|
||||
assert_eq!(prop(&s, env, "lightOptions/source").as_layer(), Some(sky));
|
||||
assert!(s.active_comp().unwrap().layer(effectcraft_project::LayerId(sky)).is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn three_d_switch_undo_redo() {
|
||||
let mut s = session();
|
||||
|
||||
Reference in New Issue
Block a user