Shortcuts: deselect keyframes and properties

keys.deselectAll (Shift+F2, Cmd+Alt+Shift+A) clears the selected
keyframes, properties and groups and leaves the layers selected.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
pravdomil
2026-10-12 20:59:48 +02:00
co-authored by Claude Opus 5.5
parent d444eceb90
commit cf912d5049
3 changed files with 24 additions and 1 deletions
+10 -1
View File
@@ -6,7 +6,7 @@ use effectcraft_project::{ItemId, LayerSource, Project};
use effectcraft_time::Tick;
use serde_json::{Value, json};
use super::{CommandSpec, comp_id, has_comp, layers_p};
use super::{CommandSpec, always, comp_id, has_comp, layers_p};
use crate::{EngineError, Result, Session, cmd};
/// Ctrl+Alt+B: the work area spans the selected layers (their earliest In to their latest Out
@@ -30,6 +30,14 @@ fn work_area_to_selection(s: &mut Session, p: &Value) -> Result<Value> {
Ok(json!({"start": c.work_area.0.seconds(), "end": c.work_area.1.seconds()}))
}
/// Shift+F2: no keyframe, property or property group is selected; the layers stay selected.
fn deselect_keys(s: &mut Session, _: &Value) -> Result<Value> {
s.state.selected_keys.clear();
s.state.selected_props.clear();
s.state.selected_vertices.clear();
Ok(Value::Null)
}
/// The comps connected to `from` by nesting, in either direction (its network of nested
/// compositions), `from` included.
fn hierarchy(proj: &Project, from: ItemId) -> BTreeSet<ItemId> {
@@ -84,5 +92,6 @@ pub fn specs() -> Vec<CommandSpec> {
work_area_to_selection
),
cmd!("comp.activateRecent", "Activate Most Recent Composition in Hierarchy", [], Some("Shift+Escape"), "{comp?}", has_comp, activate_recent),
cmd!("keys.deselectAll", "Deselect All Keyframes and Properties", [], ["Shift+F2", "Cmd+Alt+Shift+A"], "{}", always, deselect_keys),
]
}
+12
View File
@@ -95,3 +95,15 @@ fn the_most_recent_comp_of_the_hierarchy_comes_back() {
s.execute("comp.activateRecent", json!({})).unwrap();
assert_eq!(s.state.active_comp.map(|c| c.0), Some(main));
}
#[test]
fn keyframes_and_properties_deselect_but_layers_stay() {
let (mut s, ids) = session([(0.0, 10.0); 3]);
s.execute("layer.select", json!({"layers": [ids[0]]})).unwrap();
s.execute("prop.addKey", json!({"layer": ids[0], "path": "transform/opacity", "time": 1.0, "value": 50.0})).unwrap();
s.execute("keys.selectAll", json!({})).unwrap();
assert!(!s.state.selected_keys.is_empty());
s.execute("keys.deselectAll", json!({})).unwrap();
assert!(s.state.selected_keys.is_empty() && s.state.selected_props.is_empty());
assert_eq!(s.state.selected_layers.len(), 1);
}
+2
View File
@@ -2129,6 +2129,8 @@ mod tests {
("time.nextInOut", "Cmd+Alt+Shift+ArrowRight"),
("comp.workAreaToSelection", "Cmd+Alt+B"),
("comp.activateRecent", "Shift+Escape"),
("keys.deselectAll", "Shift+F2"),
("keys.deselectAll", "Cmd+Alt+Shift+A"),
] {
assert!(bindings(&app.session).into_iter().any(|x| x.2 == id && Some((x.0, x.1)) == parse_shortcut(keys)), "{id} on {keys}");
}