mirror of
https://github.com/storytold/effectcraft.git
synced 2026-11-11 16:33:01 -06:00
Merge pull request #1640 from krinry/fix/1611-layer-styles-context-menu
#1611: layer context menu has Layer Styles
This commit is contained in:
@@ -291,6 +291,7 @@ const JAPANESE: &[(&str, &str)] = &[
|
||||
("Layer {}", "レイヤー{}"),
|
||||
("Layer:", "レイヤー:"),
|
||||
("Layer: {}", "レイヤー:{}"),
|
||||
("Layer Styles", "レイヤースタイル"),
|
||||
("Learn", "学習"),
|
||||
("Leave all attributes in \"{}\"", "すべての属性を「{}」に残す"),
|
||||
("Licence: {}", "ライセンス:{}"),
|
||||
@@ -836,6 +837,7 @@ const SIMPLIFIED_CHINESE: &[(&str, &str)] = &[
|
||||
("Layer {}", "图层 {}"),
|
||||
("Layer:", "图层:"),
|
||||
("Layer: {}", "图层:{}"),
|
||||
("Layer Styles", "图层样式"),
|
||||
("Learn", "学习"),
|
||||
("Leave all attributes in \"{}\"", "将所有属性保留在“{}”中"),
|
||||
("Licence: {}", "许可:{}"),
|
||||
@@ -1569,6 +1571,7 @@ const TRADITIONAL_CHINESE: &[(&str, &str)] = &[
|
||||
("Layer {}", "圖層 {}"),
|
||||
("Layer:", "圖層:"),
|
||||
("Layer: {}", "圖層:{}"),
|
||||
("Layer Styles", "圖層樣式"),
|
||||
("Learn", "學習"),
|
||||
("Leave all attributes in \"{}\"", "將所有屬性保留在“{}”中"),
|
||||
("Licence: {}", "許可:{}"),
|
||||
@@ -2305,6 +2308,7 @@ const UKRAINIAN: &[(&str, &str)] = &[
|
||||
("Layer {}", "Шар {}"),
|
||||
("Layer:", "Шар:"),
|
||||
("Layer: {}", "Шар: {}"),
|
||||
("Layer Styles", "Стилі шару"),
|
||||
("Learn", "Навчання"),
|
||||
("Leave all attributes in \"{}\"", "Залишити всі атрибути в «{}»"),
|
||||
("Licence: {}", "Ліцензія: {}"),
|
||||
@@ -2856,6 +2860,7 @@ const PORTUGUESE: &[(&str, &str)] = &[
|
||||
("Layer {}", "Camada {}"),
|
||||
("Layer:", "Camada:"),
|
||||
("Layer: {}", "Camada: {}"),
|
||||
("Layer Styles", "Estilos de camada"),
|
||||
("Learn", "Aprender"),
|
||||
("Leave all attributes in \"{}\"", "Manter todos os atributos em \"{}\""),
|
||||
("Licence: {}", "Licença: {}"),
|
||||
@@ -3308,6 +3313,7 @@ const CZECH: &[(&str, &str)] = &[
|
||||
("Layer {}", "Vrstva {}"),
|
||||
("Layer:", "Vrstva:"),
|
||||
("Layer: {}", "Vrstva: {}"),
|
||||
("Layer Styles", "Styly vrstvy"),
|
||||
("Learn", "Výuka"),
|
||||
("Leave all attributes in \"{}\"", "Ponechat všechny atributy v „{}“"),
|
||||
("Licence: {}", "Licence: {}"),
|
||||
@@ -3865,6 +3871,7 @@ const SPANISH: &[(&str, &str)] = &[
|
||||
("Layer {}", "Capa {}"),
|
||||
("Layer:", "Capa:"),
|
||||
("Layer: {}", "Capa: {}"),
|
||||
("Layer Styles", "Estilos de capa"),
|
||||
("Learn", "Aprender"),
|
||||
("Leave all attributes in \"{}\"", "Dejar todos los atributos en \"{}\""),
|
||||
("Licence: {}", "Licencia: {}"),
|
||||
|
||||
@@ -3958,6 +3958,7 @@ pub(crate) fn layer_menu(ui: &mut egui::Ui, layers: &[u64], caps: LayerMenuCaps,
|
||||
}
|
||||
})
|
||||
});
|
||||
ui.menu_button(crate::i18n::tr("Layer Styles"), |ui| layer_styles_submenu(ui, layers, &mut item));
|
||||
ui.menu_button(crate::i18n::tr("Effects"), |ui| effects_submenu(ui, layers, &mut item));
|
||||
ui.menu_button(crate::i18n::tr("Arrange"), |ui| {
|
||||
item(ui, "Bring Layer to Front", "layer.arrange", json!({"layers": layers, "to": "front"}));
|
||||
@@ -3972,6 +3973,31 @@ pub(crate) fn layer_menu(ui: &mut egui::Ui, layers: &[u64], caps: LayerMenuCaps,
|
||||
item(ui, "Delete", "edit.clear", json!({"layers": layers}));
|
||||
}
|
||||
|
||||
/// The layer context menu's Layer Styles submenu, matching the Layer ▸ Layer Styles application menu.
|
||||
fn layer_styles_submenu(ui: &mut egui::Ui, layers: &[u64], item: &mut dyn FnMut(&mut egui::Ui, &str, &str, serde_json::Value)) {
|
||||
item(ui, "Layer Style Options...", "layer.style.options", json!({}));
|
||||
ui.separator();
|
||||
item(ui, "Convert to Editable Styles", "layer.style.convertToEditable", json!({"layers": layers}));
|
||||
item(ui, "Show All", "layer.style.showAll", json!({"layers": layers}));
|
||||
item(ui, "Remove All", "layer.style.removeAll", json!({"layers": layers}));
|
||||
ui.separator();
|
||||
for (id, label) in effectcraft_engine::project::styles::STYLES {
|
||||
let cmd = match *id {
|
||||
"dropShadow" => "layer.style.dropShadow",
|
||||
"innerShadow" => "layer.style.innerShadow",
|
||||
"outerGlow" => "layer.style.outerGlow",
|
||||
"innerGlow" => "layer.style.innerGlow",
|
||||
"bevelEmboss" => "layer.style.bevelEmboss",
|
||||
"satin" => "layer.style.satin",
|
||||
"colorOverlay" => "layer.style.colorOverlay",
|
||||
"gradientOverlay" => "layer.style.gradientOverlay",
|
||||
"stroke" => "layer.style.stroke",
|
||||
_ => continue,
|
||||
};
|
||||
item(ui, label, cmd, json!({}));
|
||||
}
|
||||
}
|
||||
|
||||
/// The layer context menu's Effects submenu: every effect from the registry grouped by category,
|
||||
/// in the same order as the Effect menu's palette, so the two stay in sync automatically.
|
||||
fn effects_submenu(ui: &mut egui::Ui, layers: &[u64], item: &mut dyn FnMut(&mut egui::Ui, &str, &str, serde_json::Value)) {
|
||||
|
||||
@@ -274,6 +274,31 @@ fn timeline_layer_context_menu_has_the_effects_submenu_and_applies_an_effect() {
|
||||
assert_eq!(names, ["Gaussian Blur"]);
|
||||
}
|
||||
|
||||
/// #1611: the layer context menu has Layer Styles between Blending Mode and Effects.
|
||||
#[test]
|
||||
fn timeline_layer_context_menu_has_layer_styles_submenu() {
|
||||
let mut h = harness();
|
||||
let solid = h.state_mut().session.execute("layer.newSolid", json!({"name": "Solid", "color": "#406080"})).unwrap()["layer"].as_u64().unwrap();
|
||||
h.run_steps(3);
|
||||
let r = rect(&h, &format!("timeline.layer.{solid}.row"));
|
||||
right_click(&mut h, pos2(r.min.x + 210.0, r.center().y));
|
||||
let blending = h.get_by_label("Blending Mode ⏵").rect();
|
||||
let styles = h.get_by_label("Layer Styles ⏵").rect();
|
||||
let effects = h.get_by_label("Effects ⏵").rect();
|
||||
assert!(blending.bottom() <= styles.top() && styles.bottom() <= effects.top(), "Layer Styles between Blending Mode and Effects");
|
||||
h.get_by_label("Layer Styles ⏵").click();
|
||||
h.run_steps(3);
|
||||
assert!(h.query_by_label("Layer Style Options...").is_some());
|
||||
assert!(h.query_by_label("Drop Shadow").is_some());
|
||||
assert!(h.query_by_label("Stroke").is_some());
|
||||
h.get_by_label("Drop Shadow").click();
|
||||
h.run_steps(3);
|
||||
assert_eq!(h.state().dialog, Some(Dialog::LayerStyles));
|
||||
let comp = h.state().session.active_comp().unwrap();
|
||||
let l = comp.layer(effectcraft_engine::project::LayerId(solid)).unwrap();
|
||||
assert!(l.layer_styles().is_some_and(|g| g.sub("dropShadow").is_some()));
|
||||
}
|
||||
|
||||
/// #976: a layer's context menu has After Effects' Markers ▸ Add Marker, which marks the layer that
|
||||
/// was right-clicked (not the one selected before, and not the composition) at the current time.
|
||||
#[test]
|
||||
|
||||
+1
-1
@@ -23,7 +23,7 @@ feel and platform differences, and the 26.x interface changes are not in yet.
|
||||
| Nudging and modifiers | Arrow nudge (1 px, Shift 10 px), Alt/Option duplicates and slips, Shift constrains | 75% | #290 nudging fixed; #491 (Linux multi-layer edits) is closed |
|
||||
| Numeric entry | Scrubbable values, typed entry with Tab / Shift+Tab, angle revolutions, Escape cancels, non-finite rejected | 85% | `ui_angles`, `ui_inline_edit` (#93, #141, #361); rename arrows on Linux (#488) |
|
||||
| Effect Controls | After Effects' twirl-downs, angle dial, point crosshair, eyedropper, curves/levels editors, effect menu on right-click | 70% | `ui_effect_controls`, `ui_fx_editors`; 26.5 rebuilt this panel with icon controls and effect colour labels: labels exist (a colour bar on the effect header and on the effect's Timeline row, right-click Label menu, `effect.setLabel`), the rebuilt controls are not matched |
|
||||
| Context menus | Layer, property, Project, Timeline empty area, work area, labels with colours | 80% | `ui_blank_context_menus`, `ui_project_rows`; #227, #290, #407 fixed; a comp's Project row menu has Composition Settings… (#1058) |
|
||||
| Context menus | Layer, property, Project, Timeline empty area, work area, labels with colours | 80% | `ui_blank_context_menus`, `ui_project_rows`; #227, #290, #407 fixed; a comp's Project row menu has Composition Settings… (#1058); layer context menu has Layer Styles (#1611) |
|
||||
| Keyboard shortcuts | After Effects' defaults; Keyboard Shortcuts editor that rebinds and saves sets | 75% | Shortcut editor in Settings; #467 (adding shortcuts on Linux), #428 and #336 are closed; no shortcuts for scripts |
|
||||
| Drag and drop | Project → Timeline / viewer / New Comp / Render Queue; effects onto layers; files from the OS | 65% | `ui_drag_drop`; OS drops fail on Wayland (winit) and some Linux setups (#268); #552, #351 (multi-file drops) and #511 (crash dragging over the import dialog) are closed |
|
||||
| Text editing on canvas | Point and paragraph text, per-character styles, Character / Paragraph panels, OpenType and variable axes | 70% | `ui_text_edit`, `ui_font_search`; paragraph alignment inverted (#316); toolbar font options (#550); font search by typing (#583) is closed; the font menus' variable-font filter (26.3) landed (#741) |
|
||||
|
||||
Reference in New Issue
Block a user