mirror of
https://github.com/storytold/effectcraft.git
synced 2026-10-31 07:38:24 +00:00
Text: duplicate during a text edit leaves no keyframe or mask vertex selected on the original (#2226)
Opening the editor keeps the keyframe and mask-vertex selection as well as the property one, and Duplicate cleared only the properties. With the copy selected, Clear then deleted a key or vertex of the original instead of the copy. During an edit the copies now take the selection the way a click on them does: layer.select's rule, moved into one helper both use. With no edit open, Duplicate's selection is unchanged.
This commit is contained in:
1 parent
0e3b894cd9
commit
c8b07b4b06
4 files changed
+53
-9
No files matched your search
@@ -151,11 +151,13 @@ fn duplicate(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
}
|
||||
relink_copies(comp, &map);
|
||||
proj.next_id = next;
|
||||
st.selected_layers = created.clone();
|
||||
// The property selection the edit kept was passed over above and belongs to the
|
||||
// originals: left in place, the next Duplicate or Clear would act on it, not the copies.
|
||||
// The property, keyframe and mask-vertex selection the edit kept belongs to the originals;
|
||||
// left in place, the next Duplicate or Clear would act on it, not on the copies. So during
|
||||
// an edit the copies take the selection the way a click on them would.
|
||||
if editing {
|
||||
st.selected_props.clear();
|
||||
super::layer::select_only(st, created.clone());
|
||||
} else {
|
||||
st.selected_layers = created.clone();
|
||||
}
|
||||
Ok(created)
|
||||
})?;
|
||||
|
||||
@@ -28,6 +28,7 @@ pub(crate) use create::{color_p, index_p, insert_layer, insert_layer_at, place,
|
||||
pub(crate) use parent::parent_fixes;
|
||||
use parent::set_parent;
|
||||
use replace::{has_replace_source, replace_source};
|
||||
pub(crate) use select::select_only;
|
||||
use select::{select, select_next, select_prev, select_step};
|
||||
use switches::{blend, rename, set_comment, set_switch, track_matte};
|
||||
use timing::{arrange, move_frames, precompose, slip, timing};
|
||||
|
||||
@@ -25,15 +25,21 @@ pub(super) fn select(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
s.state.selected_layers = ids;
|
||||
s.state.selected_props.clear();
|
||||
s.state.selected_keys.clear();
|
||||
let keep = s.state.selected_layers.clone();
|
||||
s.state.selected_vertices.retain(|v| keep.contains(&v.layer));
|
||||
select_only(&mut s.state, ids);
|
||||
}
|
||||
Ok(json!(s.state.selected_layers.iter().map(|l| l.0).collect::<Vec<_>>()))
|
||||
}
|
||||
|
||||
/// Make `ids` the whole layer selection, as a plain click on them does: no property or keyframe
|
||||
/// stays selected, and mask vertices stay selected only on layers that are still selected.
|
||||
pub(crate) fn select_only(st: &mut crate::EditorState, ids: Vec<LayerId>) {
|
||||
st.selected_layers = ids;
|
||||
st.selected_props.clear();
|
||||
st.selected_keys.clear();
|
||||
let keep = st.selected_layers.clone();
|
||||
st.selected_vertices.retain(|v| keep.contains(&v.layer));
|
||||
}
|
||||
|
||||
pub(super) fn select_step(s: &mut Session, p: &Value, dir: i64) -> Result<Value> {
|
||||
let comp = s.active_comp().ok_or(EngineError::NoComp)?;
|
||||
if comp.layers.is_empty() {
|
||||
|
||||
@@ -1277,6 +1277,41 @@ fn duplicate_during_an_edit_copies_the_layer_not_a_selected_property_group() {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn duplicate_during_an_edit_leaves_no_key_or_vertex_selected_on_the_original() {
|
||||
use effectcraft_project::LayerId;
|
||||
// Opening the editor keeps the keyframe and mask-vertex selection too. Once the copy takes the
|
||||
// selection, Clear deletes the copy, not a key or a vertex of the original.
|
||||
for what in ["keyframe", "mask vertex"] {
|
||||
let (mut s, t) = session("Hello");
|
||||
let mask = match what {
|
||||
"keyframe" => {
|
||||
for time in [0.0, 1.0] {
|
||||
s.execute("prop.addKey", json!({"layer": t, "path": "transform/opacity", "time": time, "value": 50})).unwrap();
|
||||
}
|
||||
s.execute("keys.select", json!({"keys": [{"layer": t, "path": "transform/opacity", "time": 0.0}]})).unwrap();
|
||||
None
|
||||
}
|
||||
// The Pen leaves the new mask's last vertex selected.
|
||||
_ => Some(s.execute("mask.new", json!({"layer": t, "vertices": [[0, 0], [40, 0], [40, 40]], "closed": true})).unwrap()["mask"].as_u64().unwrap()),
|
||||
};
|
||||
let original = |s: &Session| {
|
||||
let l = s.active_comp().unwrap().layer(LayerId(t)).unwrap();
|
||||
match mask {
|
||||
None => l.props.prop("transform/opacity").unwrap().keys.len(),
|
||||
Some(m) => l.props.find_group(m).unwrap().get("path").unwrap().value.as_path().unwrap().vertices.len(),
|
||||
}
|
||||
};
|
||||
let (n, before) = (original(&s), layer_count(&s));
|
||||
begin_edit_at(&mut s, t, 5);
|
||||
let copy = s.execute("edit.duplicate", json!({})).unwrap()[0].as_u64().unwrap();
|
||||
assert_eq!(s.state.selected_layers, vec![LayerId(copy)], "{what}: the copy is selected");
|
||||
s.execute("edit.clear", json!({})).unwrap();
|
||||
assert_eq!(layer_count(&s), before, "{what}: Clear deletes the selected copy");
|
||||
assert_eq!(original(&s), n, "{what}: and leaves the original's {what} alone");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn duplicate_ends_the_open_edit_and_selects_the_copy() {
|
||||
let (mut s, t) = editing("Hello", 5);
|
||||
|
||||
Reference in new issue
Block a user