Merge remote-tracking branch 'origin/main' into HEAD

This commit is contained in:
bflatastic
2026-10-30 05:08:13 +07:00
335 changed files with 17928 additions and 1551 deletions
+34
View File
@@ -608,3 +608,37 @@ fn presets_saved_by_the_old_core_panel_carry_over() {
let win = open_panel(&mut s);
assert_eq!(control(&mut s, win, "presets")["items"].as_array().unwrap().len(), 12);
}
/// #2465: the Linear preset sets Linear interpolation on every side it applies to, including the
/// unused first-in and last-out sides; editing its speeds makes a Bezier curve.
#[test]
fn the_linear_preset_sets_linear_interpolation_and_edited_speeds_give_bezier() {
let store = Arc::new(MemoryConfig::default());
let mut s = session(&store);
let l = setup(&mut s);
animate(&mut s, l, "transform/opacity", &[(0.0, json!(0)), (1.0, json!(100)), (3.0, json!(20))]);
s.execute("prop.select", json!({"layer": l, "path": "transform/opacity"})).unwrap();
let win = open_panel(&mut s);
// Start from Bezier keys so Linear has something to restore.
ok(
&mut s,
r#"var p = app.project.activeItem.layer(1).transform.opacity, K = KeyframeInterpolationType;
for (var i = 1; i <= p.numKeys; i++) p.setInterpolationTypeAtKey(i, K.BEZIER, K.BEZIER);"#,
);
let op = prop(&s, l, "transform/opacity");
for (i, k) in op.keys.iter().enumerate() {
assert_eq!((k.in_interp, k.out_interp), (Interp::Bezier, Interp::Bezier), "initial key {i}");
}
let steps = s.history.undo.len();
set(&mut s, win, "presets", json!("Linear"));
assert_eq!(s.history.undo.len(), steps + 1, "one undo step");
let op = prop(&s, l, "transform/opacity");
for (i, k) in op.keys.iter().enumerate() {
assert_eq!((k.in_interp, k.out_interp), (Interp::Linear, Interp::Linear), "key {i}");
}
// Edited speeds make a custom Bezier curve even though Linear is still the selected preset.
select_keys(&mut s, l, &[("transform/opacity", 1.0)]);
apply_typed(&mut s, win, "In-Out", [33.0, 2.0, 33.0, 2.0]);
let k = &prop(&s, l, "transform/opacity").keys[1];
assert_eq!((k.in_interp, k.out_interp), (Interp::Bezier, Interp::Bezier));
}
+24
View File
@@ -86,3 +86,27 @@ fn open_panels_open_again_at_the_next_launch() {
let mut s = session(&store);
assert_eq!(s.execute("window.restoreScriptPanels", json!({})).unwrap(), json!({"opened": [], "failed": []}));
}
/// A panel in a subfolder (Window ▸ Motion Kit ▸ Animate.jsx) is `Motion Kit/Animate.jsx`: it opens
/// titled after its file and opens again at the next launch.
#[test]
fn a_panel_in_a_subfolder_opens_and_opens_again_at_the_next_launch() {
let store = Arc::new(MemoryConfig::default());
store.write(&format!("{PANELS_DIR}/Motion Kit/Animate.jsx"), PANEL).unwrap();
let mut s = session(&store);
let list = s.execute("file.scripts.list", json!({})).unwrap();
assert!(list.as_array().unwrap().iter().any(|e| e["name"] == "Motion Kit/Animate.jsx" && e["panel"] == true), "{list}");
let r = s.execute("window.scriptPanel", json!({"name": "Motion Kit/Animate.jsx"})).unwrap();
let w = s.script_ui.window(r["window"].as_u64().unwrap() as u32).unwrap();
assert_eq!((w.kind, w.title.as_str()), (WindowKind::Panel, "Animate"));
assert_eq!(remembered(&store), json!({"open": ["Motion Kit/Animate.jsx"]}));
// A saved name that leaves the folder, or goes two folders deep, fails and is forgotten.
store.write(OPEN_PANELS_FILE, &json!({"open": ["../Top.jsx", "Motion Kit/Animate.jsx", "a/b/c.jsx"]}).to_string()).unwrap();
drop(s);
let mut s = session(&store);
let r = s.execute("window.restoreScriptPanels", json!({})).unwrap();
assert_eq!(r["opened"], json!(["Motion Kit/Animate.jsx"]));
assert_eq!(r["failed"].as_array().unwrap().iter().map(|f| f["name"].as_str().unwrap()).collect::<Vec<_>>(), ["../Top.jsx", "a/b/c.jsx"]);
assert!(panel_window(&s, "Motion Kit/Animate.jsx").is_some());
assert_eq!(remembered(&store), json!({"open": ["Motion Kit/Animate.jsx"]}));
}