diff --git a/crates/engine/src/cmd/globaledit.rs b/crates/engine/src/cmd/globaledit.rs index fe1830946..6ff31dabe 100644 --- a/crates/engine/src/cmd/globaledit.rs +++ b/crates/engine/src/cmd/globaledit.rs @@ -357,7 +357,10 @@ fn can_toggle(s: &Session) -> std::result::Result<(), String> { let [id] = st.selection.objects.as_slice() else { return Err(if st.selection.is_empty() { "nothing selected" } else { "select one object" }.into()); }; + // A group's contents are checked when Global Edit starts: building its shape here would walk + // every object in it each time the menu or the Properties panel asks. match st.doc.node(*id) { + Some(n) if n.extras().mask.is_none() && plain_group(n) => Ok(()), Some(n) if supported(n) => Ok(()), _ => Err(UNSUPPORTED.into()), } diff --git a/crates/engine/src/tests/globaledit.rs b/crates/engine/src/tests/globaledit.rs index fe87d57b3..aeb426ac4 100644 --- a/crates/engine/src/tests/globaledit.rs +++ b/crates/engine/src/tests/globaledit.rs @@ -295,8 +295,10 @@ fn global_edit_needs_one_supported_object() { }; let (g, _) = (group(&mut s, 600.0), group(&mut s, 700.0)); sel(&mut s, &[g]); + // The menu only checks that it is a group; starting refuses its contents. let e = s.execute("select.globalEdit", &json!({})).unwrap_err(); - assert!(matches!(e, EngineError::Disabled(..)) && e.to_string().contains("symbol instances and groups of them"), "{e}"); + assert!(e.to_string().contains("symbol instances and groups of them"), "{e}"); + assert!(s.doc().unwrap().global_edit.is_none()); } #[test]