Browse / github.com/storytold/effectcraft / patch
Fix #2201: one undo reverts a whole mask free-transform drag
mask navigation Hi. Tested 0.16.0. Not able to manually draw and select multiple points on mask. After scaling the mask, pressing undo only undo a small increment of the overall scaling size. It doesn't revert back to the size before applying scaling. Overall, this version has improved a lot. Great work !
- Status
- open
- Score
- 0.00
- Adopters
- 0 other operators
- Author
- jerome25000 (imported from pull request #2426, open)
- Base
362474a843ddb67555d4c2d19ad6a590388aad0e- Size
- +23 −4 in 2 files
- Review
- pending
- Shared
- 2026-10-28
- Id
3bbe2757cce3413949b1dc6d
How it went
No other operator has reported using it yet.
Diff
raw · crates/engine/src/commands/paths.rs crates/engine/src/tests_stubs.rs
@@ -8,7 +8,7 @@ use effectcraft_project::{FeatherFalloff, GroupKind, ItemId, LayerId, LayerSourc use serde_json::{Value, json}; use super::layer_menu::target_masks;-use super::{CommandSpec, b_p, bad, f_p, has_comp, has_layers, layer_mut, layer_p, str_p};+use super::{CommandSpec, b_p, bad, f_p, has_comp, has_layers, layer_mut, layer_p, merge_p, str_p}; use crate::{EngineError, Result, Session, VertexRef, cmd}; // ---------------------------------------------------------------- RotoBezier@@ -308,7 +308,7 @@ fn free_transform(s: &mut Session, p: &Value) -> Result<Value> { let y = v[1] * scale[1]; [x * c - y * sn, x * sn + y * c] };- let n = s.edit("Free Transform Points", None, |proj, _| {+ let n = s.edit("Free Transform Points", merge_p(p), |proj, _| { let mut n = 0; for (lid, uid) in &targets { let l = layer_mut(proj, cid, *lid)?;@@ -541,8 +541,8 @@ pub fn specs() -> Vec<CommandSpec> { "path.freeTransform", "Free Transform Points", ["Layer", "Mask and Shape Path"],- None,- "{layer?, mask?, scale?: % | [x%, y%], rotation?: deg, offset?: [dx, dy], anchor?: [x, y]}",+ None, + "{layer?, mask?, scale?: % | [x%, y%], rotation?: deg, offset?: [dx, dy], anchor?: [x, y], merge?: string}", has_layers, free_transform ),@@ -583,3 +583,22 @@ fn convert_to_bezier_reads_the_shape_as_it_is_set() { let mid = |v: &[f64]| (v.iter().copied().fold(f64::MAX, f64::min) + v.iter().copied().fold(f64::MIN, f64::max)) / 2.0; assert!((mid(&xs) - 10.0).abs() < 1e-6 && (mid(&ys) - 5.0).abs() < 1e-6, "centred on the position: {:?} {:?}", mid(&xs), mid(&ys)); }++/// #2201: a viewer drag on the free-transform box sends one `path.freeTransform` per frame with a+/// shared merge key; one undo must revert the whole drag, not the last frame.+#[test]+fn free_transform_drag_undoes_in_one_step() {+ let mut s = comp();+ let (l, m) = masked(&mut s);+ s.state.selected_vertices.clear();+ let before = mask_path(&s, l, m);+ for k in [90, 90, 90, 90] {+ s.execute("path.freeTransform", json!({"layer": l, "scale": k, "merge": "viewer-drag-1"})).unwrap();+ }+ let after = mask_path(&s, l, m);+ assert_ne!(after, before);+ s.execute("edit.undo", json!({})).unwrap();+ assert_eq!(mask_path(&s, l, m), before, "one undo reverts the whole drag");+ s.execute("edit.redo", json!({})).unwrap();+ assert_eq!(mask_path(&s, l, m), after, "redo restores the whole drag");+}