mirror of
https://github.com/storytold/photocraft.git
synced 2026-10-14 19:26:51 -04:00
Inspect: report each layer's vector mask (#2980)
`hasMask` in document inspection covers only raster masks, so a layer with a vector mask looked unmasked to an agent. Layers, groups included, now also report `hasVectorMask` and `vectorMaskEnabled` (null when there is no vector mask). `hasMask` keeps its meaning.
This commit is contained in:
1 parent
28874bbfad
commit
2d6ff3f6cc
2 files changed
+58
No files matched your search
@@ -81,6 +81,8 @@ fn layer_sel(l: &Layer, selected: &[photocraft_doc::LayerId]) -> Value {
|
||||
"blend": l.blend.label(),
|
||||
"clipped": l.clipped,
|
||||
"hasMask": l.mask.is_some(),
|
||||
"hasVectorMask": l.vector_mask.is_some(),
|
||||
"vectorMaskEnabled": l.vector_mask.as_ref().map(|mask| mask.enabled),
|
||||
"bounds": bounds,
|
||||
"selected": selected.contains(&l.id),
|
||||
"linkGroup": l.link_group,
|
||||
@@ -154,3 +156,56 @@ fn layer_sel(l: &Layer, selected: &[photocraft_doc::LayerId]) -> Value {
|
||||
}
|
||||
v
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use photocraft_color::PixelFormat;
|
||||
use photocraft_doc::{LayerMask, Path, VectorMask};
|
||||
|
||||
#[test]
|
||||
fn document_inspect_reports_raster_and_vector_masks_when_nested() {
|
||||
let cases = [(false, None), (true, None), (false, Some(true)), (false, Some(false)), (true, Some(true))];
|
||||
let mut session = Session::new();
|
||||
session.execute("file.new", json!({"width": 1, "height": 1})).unwrap();
|
||||
let layers = cases
|
||||
.iter()
|
||||
.map(|&(raster, enabled)| {
|
||||
let mut layer = Layer::raster("Mask case", PixelFormat::RGBA8);
|
||||
layer.mask = raster.then(LayerMask::reveal_all);
|
||||
layer.vector_mask = enabled.map(|enabled| VectorMask { enabled, ..VectorMask::new(Path::default()) });
|
||||
layer
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
let mut group = Layer::group("Inner", layers.clone());
|
||||
group.vector_mask = Some(VectorMask { enabled: false, ..VectorMask::new(Path::default()) });
|
||||
let mut roots = layers;
|
||||
roots.push(Layer::group("Outer", vec![group]));
|
||||
session
|
||||
.edit("Mask fixtures", |doc, _| {
|
||||
doc.layers = roots;
|
||||
Ok(())
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
let inspected = session.execute("document.inspect", json!({})).unwrap();
|
||||
|
||||
let roots = inspected["layers"].as_array().unwrap();
|
||||
let outer = &roots[0];
|
||||
let inner = &outer["children"][0];
|
||||
assert_eq!(outer.get("hasMask"), Some(&json!(false)));
|
||||
assert_eq!(outer.get("hasVectorMask"), Some(&json!(false)));
|
||||
assert_eq!(outer.get("vectorMaskEnabled"), Some(&Value::Null));
|
||||
assert_eq!(inner.get("hasMask"), Some(&json!(false)));
|
||||
assert_eq!(inner.get("hasVectorMask"), Some(&json!(true)));
|
||||
assert_eq!(inner.get("vectorMaskEnabled"), Some(&json!(false)));
|
||||
for nodes in [&roots[1..], inner["children"].as_array().unwrap().as_slice()] {
|
||||
assert_eq!(nodes.len(), cases.len());
|
||||
for (node, &(raster, enabled)) in nodes.iter().zip(cases.iter().rev()) {
|
||||
assert_eq!(node.get("hasMask"), Some(&json!(raster)));
|
||||
assert_eq!(node.get("hasVectorMask"), Some(&json!(enabled.is_some())));
|
||||
assert_eq!(node.get("vectorMaskEnabled"), Some(&json!(enabled)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,9 @@ described in [development.md](development.md). UI tools require a running deskto
|
||||
- `command_batch`: ordered `steps`, optional `stop_on_error`; one history step per command,
|
||||
not an atomic transaction. Existing per-step results and reply budgets are preserved.
|
||||
- `doc_inspect`: layer tree, history and selection; an empty session returns `document:null`.
|
||||
Every layer (including groups and nested children) reports raster-only `hasMask`,
|
||||
`hasVectorMask` for vector mask presence, and `vectorMaskEnabled` (`true`/`false` when
|
||||
present, `null` when absent). A disabled vector mask still has `hasVectorMask:true`.
|
||||
- `render_preview`: bounded PNG content; `index` and `max_side` (default 1024, maximum 2048).
|
||||
- `ui_inspect` and `ui_screenshot`: live app state/window in bridge mode.
|
||||
|
||||
|
||||
Reference in new issue
Block a user