mirror of
https://github.com/storytold/effectcraft.git
synced 2026-11-15 06:42:31 +00:00
#2817: honor combined path and shape group selections
This commit is contained in:
1 parent
c5bf611909
commit
2b1b688557
2 files changed
+35
-12
No files matched your search
@@ -38,19 +38,18 @@ fn targets(s: &Session) -> Result<Vec<Target>> {
|
||||
props: s.state.selected_props.iter().filter(|(lid, _)| s.state.selected_layers.contains(lid)).copied().collect(),
|
||||
time: s.time(),
|
||||
};
|
||||
let whole_layers = selection.vertices.is_empty() && selection.props.is_empty();
|
||||
let mut targets = Vec::new();
|
||||
for layer in comp.layers.iter() {
|
||||
let selected_layer = if !selection.vertices.is_empty() {
|
||||
selection.vertices.iter().any(|v| v.layer == layer.id)
|
||||
} else if !selection.props.is_empty() {
|
||||
selection.props.iter().any(|(lid, _)| *lid == layer.id)
|
||||
} else {
|
||||
let selected_layer = if whole_layers {
|
||||
s.state.selected_layers.contains(&layer.id)
|
||||
} else {
|
||||
selection.vertices.iter().any(|v| v.layer == layer.id) || selection.props.iter().any(|(lid, _)| *lid == layer.id)
|
||||
};
|
||||
if !selected_layer || layer.switches.locked {
|
||||
continue;
|
||||
}
|
||||
collect(&selection, layer, &layer.props, &mut Vec::new(), selection.props.is_empty(), &mut targets)?;
|
||||
collect(&selection, layer, &layer.props, &mut Vec::new(), whole_layers, &mut targets)?;
|
||||
}
|
||||
if targets.is_empty() {
|
||||
return Err(bad("path.toggleClosed", "select an unlocked mask or Bezier shape path"));
|
||||
@@ -70,11 +69,10 @@ fn collect(selection: &Selection, layer: &Layer, group: &PropGroup, route: &mut
|
||||
&& let Some(prop) = group.get("path")
|
||||
&& let KV::Path(path) = prop.value_at(layer.layer_time(selection.time))
|
||||
{
|
||||
let selected = if selection.vertices.is_empty() {
|
||||
selected || selection.props.contains(&(layer.id, prop.uid))
|
||||
} else {
|
||||
selection.vertices.iter().any(|v| v.layer == layer.id && v.mask == group.uid && v.index < path.vertices.len())
|
||||
};
|
||||
// Property selection also selects its points; both describe the selected paths.
|
||||
let selected = selected
|
||||
|| selection.props.contains(&(layer.id, prop.uid))
|
||||
|| selection.vertices.iter().any(|v| v.layer == layer.id && v.mask == group.uid && v.index < path.vertices.len());
|
||||
if selected {
|
||||
targets.push(Target { layer: layer.id, route: route.clone(), closed: path.closed });
|
||||
}
|
||||
|
||||
@@ -302,7 +302,7 @@ fn toggle_closed_respects_path_and_vertex_selection() {
|
||||
s.state.selected_props = vec![(LayerId(lid), b)];
|
||||
s.state.selected_vertices = vec![crate::VertexRef { layer: LayerId(lid), mask: a, index: 1 }];
|
||||
s.execute("path.toggleClosed", json!({})).unwrap();
|
||||
assert!(shape_path(&s, lid, a).closed, "vertices take precedence over property selection");
|
||||
assert!(shape_path(&s, lid, a).closed, "selected points and properties both describe target paths");
|
||||
assert!(shape_path(&s, lid, b).closed);
|
||||
s.state.selected_vertices.clear();
|
||||
s.state.selected_props = vec![(LayerId(lid), a), (LayerId(lid), leaf), (LayerId(lid), b)];
|
||||
@@ -323,6 +323,31 @@ fn toggle_closed_respects_path_and_vertex_selection() {
|
||||
assert!(!shape_path(&s, lid, b).closed, "layer selection addresses all editable paths");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn toggle_closed_combines_property_and_shape_group_selections() {
|
||||
let mut s = comp();
|
||||
let a = s.execute("shape.newPath", json!({"vertices": [[0, 0], [100, 0], [100, 100]], "closed": true})).unwrap();
|
||||
let (lid, a_path) = (a["layer"].as_u64().unwrap(), a["path"].as_u64().unwrap());
|
||||
let b = s.execute("shape.newPath", json!({"layer": lid, "vertices": [[10, 10], [90, 10], [90, 90]], "closed": true})).unwrap();
|
||||
let (b_path, b_group) = (b["path"].as_u64().unwrap(), b["group"].as_u64().unwrap());
|
||||
let c_path =
|
||||
s.execute("shape.newPath", json!({"layer": lid, "vertices": [[20, 20], [80, 20], [80, 80]], "closed": true})).unwrap()["path"].as_u64().unwrap();
|
||||
s.execute("prop.select", json!({"layer": lid, "prop": a_path})).unwrap();
|
||||
s.execute("prop.select", json!({"layer": lid, "prop": b_group, "add": true})).unwrap();
|
||||
assert!(s.state.selected_vertices.iter().all(|v| v.mask == a_path), "only the path property implies selected vertices");
|
||||
assert!(!s.state.selected_vertices.is_empty());
|
||||
assert!(s.state.selected_props.contains(&(LayerId(lid), b_group)));
|
||||
let result = s.execute("path.toggleClosed", json!({})).unwrap();
|
||||
assert_eq!(result["paths"], json!(2));
|
||||
assert!(!shape_path(&s, lid, a_path).closed);
|
||||
assert!(!shape_path(&s, lid, b_path).closed, "the added shape group is included alongside implied vertices");
|
||||
assert!(shape_path(&s, lid, c_path).closed, "unselected sibling stays unchanged");
|
||||
s.execute("edit.undo", json!({})).unwrap();
|
||||
assert!(shape_path(&s, lid, a_path).closed);
|
||||
assert!(shape_path(&s, lid, b_path).closed, "both selected paths undo together");
|
||||
assert!(shape_path(&s, lid, c_path).closed);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn toggle_closed_ignores_selections_retained_on_other_layers() {
|
||||
let mut s = comp();
|
||||
|
||||
Reference in new issue
Block a user