Files
photocraft/crates/engine/tests/brush_smoothing.rs
T
61c52c08db Brush Settings: toggle switch rows without losing smoothing settings (#4463)
Noise, Wet Edges, Build-up, Smoothing and Protect Texture toggle from
anywhere on their row while keeping the selected controls open. Keep
lock clicks independent and expose each switch as one accessible checkbox.

Give Smoothing a default-on enable flag so disabling it preserves the
amount and modes. Old brush JSON stays compatible; toolbar amount edits
and explicit stroke overrides enable it, and ABR imports retain disabled
smoothing values.

Cover row, checkbox, lock and keyboard gestures, old section selections,
command replay, presets, legacy JSON and 8/16/32-bit rendering.

Fixes #4283

Co-authored-by: augrclk <217665348+augrclk@users.noreply.github.com>
Co-authored-by: GPT-6 <noreply@openai.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-12 19:23:17 -04:00

57 lines
3.3 KiB
Rust

//! Smoothing is a tool option: the Brush starts at Photoshop's 10 %, and picking a brush preset
//! keeps the current smoothing (amount and mode) instead of taking the preset's.
use photocraft_engine::Session;
use serde_json::json;
#[test]
fn presets_keep_the_tool_smoothing() {
let mut s = Session::new();
s.execute("file.new", json!({"width": 64, "height": 64})).unwrap();
assert_eq!(s.tools.brush.smoothing.amount, 0.1, "Photoshop's default");
let preset = s.tools.presets.iter().find(|p| p.brush.smoothing.amount == 0.0).map(|p| p.name.clone()).unwrap();
let smoothed = s.tools.presets.iter().find(|p| p.brush.smoothing.amount > 0.2).map(|p| p.name.clone()).unwrap();
s.execute("tools.setBrush", json!({"preset": preset})).unwrap();
assert_eq!(s.tools.brush.smoothing.amount, 0.1);
s.execute("tools.setBrush", json!({"brush": {"smoothing": {"amount": 0.6, "pulledString": true}}})).unwrap();
s.execute("tools.setBrush", json!({"preset": smoothed})).unwrap();
assert_eq!((s.tools.brush.smoothing.amount, s.tools.brush.smoothing.pulled_string), (0.6, true));
// An explicit smoothing alongside the preset still applies.
s.execute("tools.setBrush", json!({"preset": preset, "brush": {"smoothing": {"amount": 0.0}}})).unwrap();
assert_eq!(s.tools.brush.smoothing.amount, 0.0);
}
#[test]
fn smoothing_switch_is_drivable_and_presets_keep_the_disabled_settings() {
let mut s = Session::new();
let params = json!({"brush": {"smoothing": {"enabled": false, "amount": 0.6, "pulledString": true, "catchUpOnEnd": false}}});
s.execute("tools.setBrush", params.clone()).unwrap();
let off = s.tools.brush.smoothing.clone();
assert!(!off.enabled && off.amount == 0.6 && off.pulled_string && !off.catch_up_on_end);
let preset = s.tools.presets[0].name.clone();
s.execute("tools.setBrush", json!({"preset": preset})).unwrap();
assert_eq!(s.tools.brush.smoothing, off);
s.execute("tools.setBrush", json!({"brush": {"smoothing": {"enabled": true}}})).unwrap();
assert!(s.tools.brush.smoothing.enabled);
assert_eq!(s.tools.brush.smoothing.amount, off.amount);
assert_eq!(s.tools.brush.smoothing.pulled_string, off.pulled_string);
// The same parameter patch reproduces the off state in another session (CLI/MCP path).
let mut other = Session::new();
other.execute("tools.setBrush", params).unwrap();
assert_eq!(other.tools.brush.smoothing, off);
let before = other.tools.brush.clone();
assert!(other.execute("tools.setBrush", json!({"brush": {"smoothing": {"enabled": "no"}}})).is_err());
assert_eq!(other.tools.brush, before);
}
#[test]
fn an_explicit_stroke_smoothing_amount_overrides_the_tool_switch() {
let mut s = Session::new();
s.execute("tools.setBrush", json!({"brush": {"smoothing": {"enabled": false, "amount": 0.6}}})).unwrap();
let inherited = photocraft_engine::brush_cmds::resolve_brush(&s, &json!({}), "paint.stroke").unwrap();
assert!(!inherited.smoothing.enabled && inherited.smoothing.amount == 0.6);
let explicit = photocraft_engine::brush_cmds::resolve_brush(&s, &json!({"smoothing": 0.4}), "paint.stroke").unwrap();
assert!(explicit.smoothing.enabled && explicit.smoothing.amount == 0.4);
assert!(!s.tools.brush.smoothing.enabled, "a stroke override does not change the tool");
}