mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-10-26 10:47:11 -06:00
Merge pull request #2720 from MarekSpodBiedry/issue-2655
Magic Wand: only select objects inside the isolated group (#2655)
This commit is contained in:
@@ -7,6 +7,7 @@ use serde_json::{Value, json};
|
||||
use vectorcraft_color::Paint;
|
||||
use vectorcraft_doc::{Document, Node, NodeId, NodeKind};
|
||||
|
||||
use super::select::selectable_ids;
|
||||
use super::*;
|
||||
|
||||
/// Magic Wand panel settings. Tolerances: colours as 0–255 RGB distance, stroke weight in
|
||||
@@ -153,7 +154,13 @@ fn magic_wand(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
let st = s.doc()?;
|
||||
let reference = st.doc.node(id).ok_or(EngineError::NoNode(id))?.clone();
|
||||
let w = s.menu.wand.clone();
|
||||
let hits: Vec<NodeId> = paintable(&st.doc).into_iter().filter(|i| st.doc.node(*i).is_some_and(|n| w.matches(&reference, n))).collect();
|
||||
// In isolation mode only the isolated group's contents can be picked, as for Select Same.
|
||||
let inside = st.isolation.map(|iso| selectable_ids(&st.doc, Some(iso)));
|
||||
let hits: Vec<NodeId> = paintable(&st.doc)
|
||||
.into_iter()
|
||||
.filter(|i| inside.as_ref().is_none_or(|set| set.contains(i)))
|
||||
.filter(|i| st.doc.node(*i).is_some_and(|n| w.matches(&reference, n)))
|
||||
.collect();
|
||||
let ids: Vec<NodeId> = match str_param(p, "mode").unwrap_or("set") {
|
||||
"add" => st.selection.objects.iter().copied().chain(hits.iter().copied().filter(|h| !st.selection.objects.contains(h))).collect(),
|
||||
"subtract" => st.selection.objects.iter().copied().filter(|i| !hits.contains(i)).collect(),
|
||||
@@ -222,4 +229,19 @@ mod tests {
|
||||
s.execute("select.magicWand", &json!({"id": b})).unwrap();
|
||||
assert_eq!(selected(&s), [b]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn isolation_mode_limits_the_wand_to_the_isolated_group() {
|
||||
let mut s = Session::new();
|
||||
s.execute("file.new", &json!({"width": 400, "height": 200})).unwrap();
|
||||
let a = rect(&mut s, 0.0, "#ff0000", 1.0);
|
||||
let b = rect(&mut s, 20.0, "#ff0000", 1.0);
|
||||
let outside = rect(&mut s, 40.0, "#ff0000", 1.0);
|
||||
s.execute("select.set", &json!({"ids": [a, b]})).unwrap();
|
||||
let g = s.execute("object.group", &json!({})).unwrap()["id"].as_u64().unwrap();
|
||||
s.execute("object.isolate", &json!({"id": g})).unwrap();
|
||||
s.execute("select.magicWand", &json!({"id": a})).unwrap();
|
||||
assert_eq!(selected(&s), [a, b]);
|
||||
assert!(!selected(&s).contains(&outside));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -497,7 +497,7 @@ Moved from the ROADMAP's "Shipped so far" on 2026-10-10. Update it when a featur
|
||||
The command palette lists `select.key` as Cancel Key Object, and a pick cancels the key object (#541).
|
||||
Agent selection commands validate every object id before changing the selection and report the resulting count and ids (#784).
|
||||
Agents read the key object: `select.key` returns it, and `document.inspect` and the `ui.pointer` and `pointer_gesture` replies report it as `key`. `select.key` with an id that isn't a selected top-level object returns an error and leaves the key unchanged.
|
||||
The Select menu's Same commands, its Object commands that select art, Next Object Above and Below and saved selections select only objects that Select All selects and objects inside them: nothing hidden or locked, nothing in a hidden or locked group, layer or sublayer, nothing on a template layer, and in isolation mode nothing outside the isolated group or layer. In isolation mode Select All, All on Active Artboard and Inverse select nothing while the isolated group or layer, or a group or layer it is in, is hidden, locked or a template layer.
|
||||
The Select menu's Same commands, its Object commands that select art, Next Object Above and Below, saved selections and the Magic Wand (#2655) select only objects that Select All selects and objects inside them: nothing hidden or locked, nothing in a hidden or locked group, layer or sublayer, nothing on a template layer, and in isolation mode nothing outside the isolated group or layer. In isolation mode Select All, All on Active Artboard and Inverse select nothing while the isolated group or layer, or a group or layer it is in, is hidden, locked or a template layer.
|
||||
Align and Distribute Spacing keep a compound path or selected group that contains the key object in place, as they keep the key object itself.
|
||||
Anchor Align moves the selected points to their bounds or the artboard (#1180). Repeating it, or moving by at most 1e-9 pt on both axes as whole-object Align does, leaves the document, Undo, Redo and saved state unchanged; actual moves still take one undo step. `crates/engine/src/tests.rs` covers repeated alignment, rounding-only alignment, unchanged handles, saved state, command recording and Undo/Redo.
|
||||
A symbol instance is measured by its symbol's art, as its transform places it, for clicks, the marquee, the bounding box, the Transform panel, Align and Distribute (the art's strokes too with Use Preview Bounds), Fit to Artwork Bounds, exports of the art, thumbnails and canvas culling; one whose symbol is missing is measured as the 20 × 20 square around the origin.
|
||||
|
||||
Reference in New Issue
Block a user