Pencil: Alt smooths as far from the drag as the Smooth tool does

With "Alt key toggles to Smooth Tool" on, an Alt drag with the Pencil
smoothed within the Pencil's "Edit selected paths" Within distance. At
0, which turns editing off, it smoothed nothing. It now smooths within
the Smooth tool's 12 px radius at every Within value.
This commit is contained in:
dotCooCoo
2026-10-29 10:01:33 +07:00
committed by bflatastic
parent 4116fdbe47
commit 6bb5398119
2 changed files with 38 additions and 2 deletions
+10 -2
View File
@@ -22,6 +22,10 @@ use super::{FEEDBACK, eraser_area, points_json, polyline};
use crate::guides::DrawSnap;
use crate::{Action, Cursor, Mods, Overlay, PointerEvent, PointerKind, Tool, ToolContext, ToolKey};
/// How far from its drag the Smooth tool smooths, in screen pixels. The Pencil uses the same
/// radius while Alt switches it to the Smooth tool.
const SMOOTH_RADIUS: f64 = 12.0;
pub struct GestureTool {
/// How many points the last preview of the stroke had ([`crate::previews_at`]).
previewed: usize,
@@ -339,9 +343,13 @@ impl GestureTool {
let pts = &self.points;
let has_sel = !cx.selection.is_empty();
let tol = cx.tol(self.edit_within);
let radius = cx.tol(SMOOTH_RADIUS);
if self.smoothing {
if has_sel && pts.len() >= 2 {
return vec![Action::Exec("path.smoothRegion".into(), json!({"points": points_json(pts), "radius": tol, "fidelity": self.fidelity}))];
return vec![Action::Exec(
"path.smoothRegion".into(),
json!({"points": points_json(pts), "radius": radius, "fidelity": self.fidelity}),
)];
}
return vec![];
}
@@ -378,7 +386,7 @@ impl GestureTool {
)],
"knife" if pts.len() >= 2 => vec![Action::Exec("path.knife".into(), json!({"points": points_json(pts)}))],
"smooth" if has_sel && pts.len() >= 2 => {
vec![Action::Exec("path.smoothRegion".into(), json!({"points": points_json(pts), "radius": tol, "fidelity": self.fidelity}))]
vec![Action::Exec("path.smoothRegion".into(), json!({"points": points_json(pts), "radius": radius, "fidelity": self.fidelity}))]
}
"pathEraser" if has_sel => vec![Action::Exec("path.eraseSegments".into(), json!({"points": points_json(pts), "width": cx.tol(8.0)}))],
"join" if pts.len() >= 2 => vec![Action::Exec("path.joinScrub".into(), json!({"points": points_json(pts), "tolerance": tol}))],
+28
View File
@@ -703,6 +703,34 @@ fn pencil_alt_with_alt_to_smooth_on_smooths_instead_of_drawing_a_line() {
assert!(matches!(&acts.last().unwrap()[0], Action::Exec(c, v) if c == "path.smoothRegion" && v["points"].as_array().unwrap().len() == 3));
}
/// While Alt switches the Pencil to the Smooth tool, the Pencil smooths within the Smooth tool's
/// radius at any Edit selected paths Within value, 0 included.
#[test]
fn pencil_alt_smooths_within_the_smooth_tools_radius() {
let (d, id) = doc_with_rect();
let mut s = Selection::default();
s.set([id]);
let p = paint();
let mut cx = cx(&d, &s, &p);
cx.smart_guides = false;
let pts = [(50.0, 150.0), (150.0, 150.0), (250.0, 160.0)];
let radius = |acts: &[Vec<Action>]| match acts.last().and_then(|a| a.first()) {
Some(Action::Exec(c, v)) if c == "path.smoothRegion" => v["radius"].as_f64().unwrap(),
a => panic!("expected path.smoothRegion, got: {a:?}"),
};
let alt = Mods { alt: true, ..Default::default() };
for zoom in [1.0, 2.0] {
cx.zoom = zoom;
let want = radius(&drag(&mut GestureTool::new("smooth"), &cx, &pts, Mods::default()));
for within in [0.0, 5.0, 40.0] {
let mut t = GestureTool::new("pencil");
t.set_option("altSmooth", &json!(true));
t.set_option("editWithin", &json!(within));
assert_eq!(radius(&drag_held(&mut t, &cx, &pts, alt)), want, "zoom {zoom}, editWithin {within}");
}
}
}
/// #3799: Alt's line starts and ends on Smart Guides as a stroke does, and pressed on an end of
/// a selected open path it continues the path from that end to the pointer.
#[test]