Merge pull request #1017 from marcoarnulfo/feat/layer-context-add-marker
# Conflicts: # crates/ui-egui/tests/ui_blank_context_menus.rs
This commit is contained in:
commit
c4a162b2dc
|
|
@ -305,6 +305,7 @@ const JAPANESE: &[(&str, &str)] = &[
|
|||
("MIT OR Apache-2.0 • Fonts: Inter, JetBrains Mono (OFL)", "MIT OR Apache-2.0 • フォント:Inter、JetBrains Mono (OFL)"),
|
||||
("Magnification ratio popup", "拡大率のポップアップ"),
|
||||
("Make Comp Size", "コンポジションサイズにする"),
|
||||
("Markers", "マーカー"),
|
||||
("Masks", "マスク"),
|
||||
("Maximize Panel", "パネルを最大化"),
|
||||
("Media Replacement", "メディアの置き換え"),
|
||||
|
|
@ -841,6 +842,7 @@ const SIMPLIFIED_CHINESE: &[(&str, &str)] = &[
|
|||
("MIT OR Apache-2.0 • Fonts: Inter, JetBrains Mono (OFL)", "MIT 或 Apache-2.0 • 字体:Inter、JetBrains Mono(OFL)"),
|
||||
("Magnification ratio popup", "放大倍率弹出菜单"),
|
||||
("Make Comp Size", "设为合成长宽"),
|
||||
("Markers", "标记"),
|
||||
("Masks", "蒙版"),
|
||||
("Maximize Panel", "最大化面板"),
|
||||
("Media Replacement", "媒体替换"),
|
||||
|
|
@ -1565,6 +1567,7 @@ const TRADITIONAL_CHINESE: &[(&str, &str)] = &[
|
|||
("MIT OR Apache-2.0 • Fonts: Inter, JetBrains Mono (OFL)", "MIT 或 Apache-2.0 • 字型:Inter、JetBrains Mono(OFL)"),
|
||||
("Magnification ratio popup", "放大倍率快顯選單"),
|
||||
("Make Comp Size", "設為合成長寬"),
|
||||
("Markers", "標記"),
|
||||
("Masks", "遮色片"),
|
||||
("Maximize Panel", "最大化面板"),
|
||||
("Media Replacement", "媒體替換"),
|
||||
|
|
@ -2292,6 +2295,7 @@ const UKRAINIAN: &[(&str, &str)] = &[
|
|||
("MIT OR Apache-2.0 • Fonts: Inter, JetBrains Mono (OFL)", "MIT OR Apache-2.0 • Шрифти: Inter, JetBrains Mono (OFL)"),
|
||||
("Magnification ratio popup", "Меню коефіцієнта збільшення"),
|
||||
("Make Comp Size", "За розміром композиції"),
|
||||
("Markers", "Маркери"),
|
||||
("Masks", "Маски"),
|
||||
("Maximize Panel", "Розгорнути панель"),
|
||||
("Media Replacement", "Заміна матеріалу"),
|
||||
|
|
@ -2831,6 +2835,7 @@ const PORTUGUESE: &[(&str, &str)] = &[
|
|||
("MIT OR Apache-2.0 • Fonts: Inter, JetBrains Mono (OFL)", "MIT OU Apache-2.0 • Fontes: Inter, JetBrains Mono (OFL)"),
|
||||
("Magnification ratio popup", "Menu de proporção de ampliação"),
|
||||
("Make Comp Size", "Ajustar ao tamanho da composição"),
|
||||
("Markers", "Marcadores"),
|
||||
("Masks", "Máscaras"),
|
||||
("Maximize Panel", "Maximizar painel"),
|
||||
("Media Replacement", "Substituição de mídia"),
|
||||
|
|
@ -3277,6 +3282,7 @@ const CZECH: &[(&str, &str)] = &[
|
|||
("MIT OR Apache-2.0 • Fonts: Inter, JetBrains Mono (OFL)", "MIT OR Apache-2.0 • Písma: Inter, JetBrains Mono (OFL)"),
|
||||
("Magnification ratio popup", "Nabídka míry přiblížení"),
|
||||
("Make Comp Size", "Nastavit velikost kompozice"),
|
||||
("Markers", "Značky"),
|
||||
("Masks", "Masky"),
|
||||
("Maximize Panel", "Maximalizovat panel"),
|
||||
("Media Replacement", "Nahrazení médií"),
|
||||
|
|
|
|||
|
|
@ -1836,6 +1836,11 @@ fn handle_shortcuts_impl(app: &mut EffectcraftApp, ctx: &egui::Context, tab_only
|
|||
// comes as text.
|
||||
if !tab_only && clipboard && app.dialog.is_none() && ctx.input(|i| i.events.iter().any(|e| matches!(e, egui::Event::Text(t) if t == "*"))) {
|
||||
let bound = app.session.shortcuts().bindings().into_iter().find(|(k, _)| *k == "Num*").map(|(_, b)| (b.command.clone(), b.params.clone()));
|
||||
// As in After Effects, it marks the selected layers; only with none selected does it add
|
||||
// a composition marker (#976).
|
||||
let bound = bound.map(|(id, params)| {
|
||||
if id == "comp.addMarker" && !app.session.state.selected_layers.is_empty() { ("layer.addMarker".to_owned(), params) } else { (id, params) }
|
||||
});
|
||||
if let Some((id, params)) = bound
|
||||
&& let Err(e) = invoke(app, ctx, &id, if params.is_null() { json!({}) } else { params })
|
||||
{
|
||||
|
|
|
|||
|
|
@ -3798,6 +3798,9 @@ pub(crate) fn layer_menu(ui: &mut egui::Ui, layers: &[u64], vector: bool, action
|
|||
item(ui, "Freeze Frame", "layer.freezeFrame", json!({"layers": layers}));
|
||||
item(ui, "Freeze on Last Frame", "layer.freezeOnLastFrame", json!({"layers": layers}));
|
||||
});
|
||||
ui.menu_button(crate::i18n::tr("Markers"), |ui| {
|
||||
item(ui, "Add Marker", "layer.addMarker", json!({"layers": layers}));
|
||||
});
|
||||
ui.menu_button(crate::i18n::tr("Blending Mode"), |ui| {
|
||||
widgets::menu_scroll(ui, |ui| {
|
||||
for m in BlendMode::ALL {
|
||||
|
|
|
|||
|
|
@ -259,3 +259,32 @@ fn timeline_layer_context_menu_has_the_effects_submenu_and_applies_an_effect() {
|
|||
.unwrap_or_default();
|
||||
assert_eq!(names, ["Gaussian Blur"]);
|
||||
}
|
||||
|
||||
/// #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]
|
||||
fn layer_context_menu_adds_a_layer_marker() {
|
||||
let mut h = harness();
|
||||
let solid = |h: &mut Harness<'_, EffectcraftApp>, name: &str| -> u64 {
|
||||
h.state_mut().session.execute("layer.newSolid", json!({"name": name, "color": "#406080"})).unwrap()["layer"].as_u64().unwrap()
|
||||
};
|
||||
let (below, top) = (solid(&mut h, "Below"), solid(&mut h, "Top"));
|
||||
h.state_mut().session.execute("layer.select", json!({"layers": [below]})).unwrap();
|
||||
h.state_mut().session.execute("time.set", json!({"time": 1.5})).unwrap();
|
||||
h.run_steps(3);
|
||||
let r = rect(&h, &format!("timeline.layer.{top}.row"));
|
||||
right_click(&mut h, pos2(r.min.x + 210.0, r.center().y));
|
||||
h.get_by_label("Markers ⏵").click();
|
||||
h.run_steps(3);
|
||||
snapshot(&mut h, "layer-markers");
|
||||
h.get_by_label("Add Marker").click();
|
||||
h.run_steps(3);
|
||||
let now = h.state().session.time().seconds();
|
||||
let comp = h.state().session.active_comp().unwrap();
|
||||
let markers = |id: u64| -> Vec<f64> { comp.layer(effectcraft_engine::project::LayerId(id)).unwrap().markers.iter().map(|m| m.time.seconds()).collect() };
|
||||
assert_eq!(markers(top), vec![now]);
|
||||
assert!((now - 1.5).abs() < 0.01, "at the current time: {now}");
|
||||
assert!(markers(below).is_empty(), "{:?}", markers(below));
|
||||
assert!(comp.markers.is_empty(), "no composition marker");
|
||||
assert_eq!(h.state().session.history.undo.last().map(|u| u.0.as_str()), Some("Add Marker"));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -356,13 +356,38 @@ fn dragging_out_of_the_marker_bin_adds_a_comp_marker() {
|
|||
assert_eq!(markers(&h), vec![13.0]);
|
||||
let history = &h.state().session.history.undo;
|
||||
assert_eq!((history.len(), history.last().map(|u| u.0.as_str())), (undo + 1, Some("Add Marker")), "one undo step");
|
||||
// Numpad * (it arrives as text): Add Marker at the current time.
|
||||
// Numpad * (it arrives as text) with no layer selected: Add Marker at the current time.
|
||||
h.state_mut().session.execute("edit.deselectAll", json!({})).unwrap();
|
||||
h.state_mut().session.execute("time.set", json!({"time": 20.0})).unwrap();
|
||||
h.event(Event::Text("*".into()));
|
||||
h.run_steps(2);
|
||||
assert_eq!(markers(&h), vec![13.0, 20.0]);
|
||||
}
|
||||
|
||||
/// #976: as in After Effects, Numpad * marks the selected layers at the current time; only with
|
||||
/// no layer selected does it add a composition marker.
|
||||
#[test]
|
||||
fn numpad_star_marks_the_selected_layer() {
|
||||
let (mut h, layer) = harness();
|
||||
let comp_markers =
|
||||
|h: &Harness<'_, EffectcraftApp>| -> Vec<f64> { h.state().session.active_comp().unwrap().markers.iter().map(|m| m.time.seconds()).collect() };
|
||||
let layer_markers = |h: &Harness<'_, EffectcraftApp>| -> Vec<f64> {
|
||||
let comp = h.state().session.active_comp().unwrap();
|
||||
comp.layer(effectcraft_engine::project::LayerId(layer)).unwrap().markers.iter().map(|m| m.time.seconds()).collect()
|
||||
};
|
||||
let star = |h: &mut Harness<'_, EffectcraftApp>, time: f64| {
|
||||
h.state_mut().session.execute("time.set", json!({"time": time})).unwrap();
|
||||
h.event(Event::Text("*".into()));
|
||||
h.run_steps(2);
|
||||
};
|
||||
h.state_mut().session.execute("layer.select", json!({"layers": [layer]})).unwrap();
|
||||
star(&mut h, 2.0);
|
||||
assert_eq!((layer_markers(&h), comp_markers(&h)), (vec![2.0], vec![]));
|
||||
h.state_mut().session.execute("edit.deselectAll", json!({})).unwrap();
|
||||
star(&mut h, 3.0);
|
||||
assert_eq!((layer_markers(&h), comp_markers(&h)), (vec![2.0], vec![3.0]));
|
||||
}
|
||||
|
||||
/// #468: zoomed in, a CTI scrub held past the right end of the ruler scrolls the timeline (the
|
||||
/// CTI rides the edge), past the left end scrolls it back; during playback the view pages to
|
||||
/// keep the CTI in sight.
|
||||
|
|
|
|||
Loading…
Reference in New Issue