mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-10-27 03:06:57 -06:00
Merge pull request #2138 from dotCooCoo/fix/glowing-edges-raster-stylize
Effect menu: Glowing Edges moves to a Stylize submenu under Raster Effects
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