mirror of
https://github.com/storytold/photocraft.git
synced 2026-10-28 18:22:06 +01:00
Conflicts: crates/engine/src/atn_cmds/tests.rs: appended test helper and tests (two blocks), kept both
This commit is contained in:
@@ -1203,8 +1203,18 @@ fn make_from(d: &Descriptor) -> Mapped {
|
||||
if let Some(n) = using.and_then(|u| get_text(u, "Nm ")) {
|
||||
p.insert("name".into(), n.into());
|
||||
}
|
||||
let id = if get_ref(d, "From").is_some() { "layer.groupLayers" } else { "layer.new.group" };
|
||||
step(id, Value::Object(p))
|
||||
match get_ref(d, "From") {
|
||||
// A named source layer stays the source (#7236); a target reference and an
|
||||
// index/id source (our exporter never writes those) keep the old implicit
|
||||
// import: the group lands on the current selection at playback.
|
||||
Some(r) => {
|
||||
if let Some(t) = layer_target(r) {
|
||||
p.extend(t);
|
||||
}
|
||||
step("layer.groupLayers", Value::Object(p))
|
||||
}
|
||||
None => step("layer.new.group", Value::Object(p)),
|
||||
}
|
||||
}
|
||||
_ => Mapped::Unsupported { harmless: false },
|
||||
}
|
||||
@@ -1231,7 +1241,9 @@ fn make_to(id: &str, p: &Value) -> Option<Descriptor> {
|
||||
}
|
||||
"layer.new.group" => desc("null").with("null", class_ref("layerSection")).with("Usng", D::Descriptor(with_name("layerSection"))),
|
||||
"layer.groupLayers" => {
|
||||
desc("null").with("null", class_ref("layerSection")).with("From", target_ref("Lyr ")).with("Usng", D::Descriptor(with_name("layerSection")))
|
||||
// An explicit source layer goes in by name like every other layer reference; a
|
||||
// step without one keeps the target-layer form (#7236).
|
||||
desc("null").with("null", class_ref("layerSection")).with("From", layer_ref(p)).with("Usng", D::Descriptor(with_name("layerSection")))
|
||||
}
|
||||
"layer.new.layerViaCopy" | "layer.new.layerViaCut" => {
|
||||
let mut d = desc("null").with("Nw ", D::Descriptor(desc("Lyr "))).with("Usng", enm("ArSl", "Slct"));
|
||||
|
||||
@@ -604,6 +604,16 @@ fn photo_filter_round_trip(params: Value) -> Option<Value> {
|
||||
}
|
||||
}
|
||||
|
||||
/// A `Mk` layerSection step exported to .atn and imported back → (id, params), or None.
|
||||
fn group_round_trip(id: &str, params: &Value) -> Option<(String, Value)> {
|
||||
let item = export_item(id, params, "S")?;
|
||||
let e = event_for(&item.event)?;
|
||||
match (e.from)(item.descriptor.as_ref()?) {
|
||||
Mapped::Steps(steps) => steps.first().map(|(i, p)| (i.clone(), p.clone())),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn photo_filter_preset_only_step_keeps_its_resolved_color() {
|
||||
// #7235: the Photoshop descriptor keeps only a colour (`phfl`/`PhtF` are colour-only; the io
|
||||
@@ -630,6 +640,44 @@ fn photo_filter_preset_only_step_keeps_its_resolved_color() {
|
||||
assert_eq!(back, json!({"density": 25}));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn group_layers_keeps_its_explicit_target_through_atn() {
|
||||
// #7236: a recorded step with an explicit layer groups that layer, not the current
|
||||
// selection. The source goes into the `From` reference by name and comes back the same
|
||||
// way; a step with no source layer keeps the implicit form, imported as before.
|
||||
let (id, p) = group_round_trip("layer.groupLayers", &json!({"layer": "A", "name": "Group"})).unwrap();
|
||||
assert_eq!(id, "layer.groupLayers");
|
||||
assert_eq!(p, json!({"layer": "A", "name": "Group"}));
|
||||
// The implicit form survives unchanged: the reference stays the target layer.
|
||||
let (id, p) = group_round_trip("layer.groupLayers", &json!({"name": "Group"})).unwrap();
|
||||
assert_eq!(id, "layer.groupLayers");
|
||||
assert_eq!(p, json!({"name": "Group"}));
|
||||
let (id, p) = group_round_trip("layer.groupLayers", &json!({})).unwrap();
|
||||
assert_eq!(id, "layer.groupLayers");
|
||||
assert_eq!(p, json!({}));
|
||||
// Group Without Layers: no `From` at all, imported as a plain new group.
|
||||
let (id, p) = group_round_trip("layer.new.group", &json!({"name": "G"})).unwrap();
|
||||
assert_eq!(id, "layer.new.group");
|
||||
assert_eq!(p, json!({"name": "G"}));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn group_layers_from_index_reference_stays_implicit() {
|
||||
// A Photoshop-authored `From` that names nothing portable (a zero-based index) keeps the
|
||||
// old implicit import instead of inventing a wrong explicit target (#7236, edge).
|
||||
let d = desc("null")
|
||||
.with("null", class_ref("layerSection"))
|
||||
.with("From", D::Reference(vec![ReferenceItem::Index { class: class("Lyr "), index: 2 }]))
|
||||
.with("Usng", D::Descriptor(desc("layerSection").with("Nm ", text("Group"))));
|
||||
match make_from(&d) {
|
||||
Mapped::Steps(steps) => {
|
||||
assert_eq!(steps[0].0, "layer.groupLayers");
|
||||
assert_eq!(steps[0].1, json!({"name": "Group"}));
|
||||
}
|
||||
_ => panic!("an index source imports as the implicit form"),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unsupported_shapes_become_photoshop_steps_not_errors() {
|
||||
// Image size in two different percentages, a Paint Bucket click in percent of the canvas, a
|
||||
|
||||
Reference in New Issue
Block a user