mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-10-25 02:07:09 -06:00
Effect menu: Glowing Edges moves to a Stylize submenu under Raster Effects
On main, Glowing Edges… is listed in the Effect menu's vector Stylize submenu, after Drop Shadow, Inner Glow, Outer Glow and Feather. The reference app lists it in the Stylize submenu of its Photoshop effects, below the vector effects. The Effect menu now has a Stylize submenu under Raster Effects, between Sharpen and Texture, and Glowing Edges is listed there. The menu sends the effects at the Stylize path that PIXEL_EFFECTS names to that submenu, and the vector Stylize submenu keeps its six effects. The effect's id, its catalog entry, its effect.list entry and Apply Last Effect do not change.
This commit is contained in:
@@ -3504,13 +3504,16 @@ fn font_items(english_names: bool) -> Vec<Item> {
|
||||
|
||||
/// The raster effects' submenus of the Effect menu (the Photoshop-style effects, below the
|
||||
/// vector effects): (submenu, the catalogue's menu path of its effects).
|
||||
const RASTER_MENUS: [(&str, &[&str]); 8] = [
|
||||
/// The raster Stylize submenu shares its path with the vector one and lists only the effects at
|
||||
/// that path that [`vectorcraft_effects::PIXEL_EFFECTS`] names.
|
||||
const RASTER_MENUS: [(&str, &[&str]); 9] = [
|
||||
("Artistic", &["Effect", "Artistic"]),
|
||||
("Blur", &["Effect", "Blur"]),
|
||||
("Brush Strokes", &["Effect", "Brush Strokes"]),
|
||||
("Distort", &["Effect", "Distort"]),
|
||||
("Pixelate", &["Effect", "Pixelate"]),
|
||||
("Sharpen", &["Effect", "Sharpen"]),
|
||||
("Stylize", &["Effect", "Stylize"]),
|
||||
("Texture", &["Effect", "Texture"]),
|
||||
("Video", &["Effect", "Video"]),
|
||||
];
|
||||
@@ -3540,10 +3543,16 @@ fn effect_menu() -> Vec<Item> {
|
||||
"Warp",
|
||||
];
|
||||
let top_level = |e: &vectorcraft_effects::EffectInfo| e.menu == ["Effect"] && order.contains(&e.label);
|
||||
// An effect goes in the vector submenu its path names unless it is a Photoshop-style effect,
|
||||
// which goes in the raster submenu of the same name when `RASTER_MENUS` has one (Stylize ›
|
||||
// Glowing Edges).
|
||||
let in_vector_menu =
|
||||
|e: &vectorcraft_effects::EffectInfo| order.iter().any(|s| e.menu == ["Effect", *s]) && !vectorcraft_effects::PIXEL_EFFECTS.contains(&e.id);
|
||||
// The effects whose catalogue menu path is `path`.
|
||||
let items_at = |path: &[&str]| -> Vec<Item> {
|
||||
// `vector` picks the ones for the vector submenu or the ones for the raster submenu.
|
||||
let items_at = |path: &[&str], vector: bool| -> Vec<Item> {
|
||||
cat.iter()
|
||||
.filter(|e| e.menu == path)
|
||||
.filter(|e| e.menu == path && in_vector_menu(e) == vector)
|
||||
.map(|e| match e.defaults.as_object().is_some_and(|o| o.is_empty()) {
|
||||
// No options (Effect → Pathfinder): apply directly, like Illustrator.
|
||||
true => Item::Cmd(e.label, "effect.apply", json!({ "effect": e.id })),
|
||||
@@ -3556,7 +3565,7 @@ fn effect_menu() -> Vec<Item> {
|
||||
out.push(Item::Cmd(e.label, "effect.apply", json!({ "effect": e.id })));
|
||||
continue;
|
||||
}
|
||||
let items = items_at(&["Effect", sub_name]);
|
||||
let items = items_at(&["Effect", sub_name], true);
|
||||
if items.is_empty() {
|
||||
let placeholder = match sub_name {
|
||||
"3D and Materials" => vec![todo("Extrude & Bevel…"), todo("Revolve…"), todo("Inflate…"), todo("Rotate…"), todo("Materials…")],
|
||||
@@ -3583,7 +3592,7 @@ fn effect_menu() -> Vec<Item> {
|
||||
let raster: Vec<Item> = RASTER_MENUS
|
||||
.iter()
|
||||
.filter_map(|(name, path)| {
|
||||
let items = items_at(path);
|
||||
let items = items_at(path, false);
|
||||
(!items.is_empty()).then(|| sub(name, items))
|
||||
})
|
||||
.collect();
|
||||
@@ -3593,9 +3602,7 @@ fn effect_menu() -> Vec<Item> {
|
||||
out.extend(raster);
|
||||
}
|
||||
// Anything not placed above (future effects) still shows up.
|
||||
let placed = |e: &vectorcraft_effects::EffectInfo| {
|
||||
top_level(e) || order.iter().any(|s| e.menu == ["Effect", *s]) || RASTER_MENUS.iter().any(|(_, path)| e.menu == *path)
|
||||
};
|
||||
let placed = |e: &vectorcraft_effects::EffectInfo| top_level(e) || in_vector_menu(e) || RASTER_MENUS.iter().any(|(_, path)| e.menu == *path);
|
||||
for e in cat.iter().filter(|e| !placed(e)) {
|
||||
out.push(Item::Cmd(e.label, "effect.dialog", json!({ "effect": e.id })));
|
||||
}
|
||||
|
||||
@@ -140,6 +140,40 @@ fn effect_menu_lists_the_texture_filters_between_sharpen_and_video() {
|
||||
assert!(at("Sharpen") < at("Texture") && at("Texture") < at("Video"));
|
||||
}
|
||||
|
||||
/// Effect › Stylize under Raster Effects, between Sharpen and Texture: Glowing Edges opens its
|
||||
/// dialog.
|
||||
#[test]
|
||||
fn effect_menu_lists_glowing_edges_in_the_raster_stylize_between_sharpen_and_texture() {
|
||||
let app = app();
|
||||
let entries = menus::menu_entries(&app);
|
||||
let at = |label: &str| entries.iter().position(|e| e.path[0] == "Effect" && e.label == label).unwrap();
|
||||
let glowing = &entries[at("Glowing Edges…")];
|
||||
assert_eq!(glowing.path, ["Effect", "Stylize"]);
|
||||
assert_eq!(glowing.command.as_deref(), Some("effect.dialog"));
|
||||
assert_eq!(glowing.params, json!({"effect": "stylize.glowingEdges"}));
|
||||
assert!(at("Unsharp Mask…") < at("Glowing Edges…") && at("Glowing Edges…") < at("Craquelure…"));
|
||||
}
|
||||
|
||||
/// The vector effects' Stylize keeps its six effects and leaves Glowing Edges out.
|
||||
#[test]
|
||||
fn effect_menu_keeps_glowing_edges_out_of_the_vector_stylize() {
|
||||
let tree = menus::menu_tree();
|
||||
let (_, effect) = tree.iter().find(|(t, _)| *t == "Effect").expect("Effect menu");
|
||||
let raster = effect.iter().position(|i| matches!(i, Item::Header("Raster Effects"))).expect("Raster Effects");
|
||||
let stylize: Vec<(usize, Vec<&str>)> = effect
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter_map(|(i, it)| match it {
|
||||
Item::Sub("Stylize", items) => Some((i, items.iter().filter_map(|c| if let Item::Cmd(l, ..) = c { Some(*l) } else { None }).collect())),
|
||||
_ => None,
|
||||
})
|
||||
.collect();
|
||||
assert_eq!(stylize.len(), 2);
|
||||
assert!(stylize[0].0 < raster && raster < stylize[1].0);
|
||||
assert_eq!(stylize[0].1, ["Round Corners…", "Scribble…", "Drop Shadow…", "Inner Glow…", "Outer Glow…", "Feather…"]);
|
||||
assert_eq!(stylize[1].1, ["Glowing Edges…"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn library_submenus_are_disabled_placeholders() {
|
||||
let app = app();
|
||||
|
||||
Reference in New Issue
Block a user