mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-10-29 12:17:14 -06:00
Blob Brush: Alt switches to the Smooth tool only before the pointer moves
Alt switched a Blob Brush stroke to the Smooth tool while the stroke held fewer than two points, so a drag that had moved less than the sampling tolerance still switched when Alt went down. The tool now records whether the pointer has moved from the press point at all. A release with Alt held, after a press without Alt and no movement, also smooths instead of painting a dot, matching the Smooth cursor shown before it.
This commit is contained in:
@@ -73,6 +73,9 @@ pub struct GestureTool {
|
||||
pub live_fit: bool,
|
||||
/// Active drag is smoothing with the Pencil or the Blob Brush (Alt held).
|
||||
smoothing: bool,
|
||||
/// The pointer has moved from the press point, by any distance (a move too short to add a
|
||||
/// point counts).
|
||||
moved: bool,
|
||||
/// Active Pencil drag draws a straight line (Shift or Alt held at the press): the stroke is
|
||||
/// the press point and the pointer.
|
||||
straight: bool,
|
||||
@@ -143,6 +146,7 @@ impl GestureTool {
|
||||
live_preview: true,
|
||||
live_fit: true,
|
||||
smoothing: false,
|
||||
moved: false,
|
||||
straight: false,
|
||||
unconstrained: false,
|
||||
shift_raw: vec![],
|
||||
@@ -193,7 +197,7 @@ impl GestureTool {
|
||||
/// Would Alt held now switch the Blob Brush to the Smooth tool? It does before a press, and
|
||||
/// during a drag that has not moved from the press point yet.
|
||||
fn blob_alt_smooths(&self, m: Mods) -> bool {
|
||||
self.id == "blobBrush" && m.alt && self.points.len() < 2
|
||||
self.id == "blobBrush" && m.alt && !self.moved
|
||||
}
|
||||
|
||||
/// Where the stroke takes a pointer at `p`. For the Blob Brush with Shift held, that is the
|
||||
@@ -237,6 +241,7 @@ impl GestureTool {
|
||||
|
||||
/// Forget the stroke.
|
||||
fn clear(&mut self) {
|
||||
self.moved = false;
|
||||
self.points.clear();
|
||||
self.pressures.clear();
|
||||
self.previewed = 0;
|
||||
@@ -455,6 +460,7 @@ impl Tool for GestureTool {
|
||||
if (!self.began && !self.straight && self.id == "pencil" && self.alt_smooth && ev.mods.alt) || self.blob_alt_smooths(ev.mods) {
|
||||
self.smoothing = true;
|
||||
}
|
||||
self.moved |= self.points.first().is_some_and(|start| p.distance(*start) > vectorcraft_geom::EPS);
|
||||
let p = self.constrained(cx, p, ev.mods);
|
||||
let mut end = p;
|
||||
if self.snaps() && !self.smoothing && !self.straight {
|
||||
@@ -513,6 +519,10 @@ impl Tool for GestureTool {
|
||||
if !self.active {
|
||||
return vec![];
|
||||
}
|
||||
// Alt pressed while the pointer stood still at the press point switches the release too.
|
||||
if self.blob_alt_smooths(ev.mods) {
|
||||
self.smoothing = true;
|
||||
}
|
||||
let p = self.constrained(cx, p, ev.mods);
|
||||
let end = if self.snaps() && !self.smoothing && (!self.straight || self.unconstrained) { self.snap.drag(cx, p, None) } else { p };
|
||||
self.snap.clear();
|
||||
|
||||
@@ -397,6 +397,18 @@ fn blob_brush_alt_switches_to_the_smooth_tool() {
|
||||
t.pointer(&cx, &PointerEvent::new(PointerKind::Drag, 200.0, 150.0).with_mods(alt));
|
||||
let acts = t.pointer(&cx, &PointerEvent::new(PointerKind::Up, 250.0, 150.0).with_mods(alt));
|
||||
assert!(matches!(acts.as_slice(), [Action::Exec(c, v)] if c == "path.blob" && v["points"].as_array().unwrap().len() == 4), "{acts:?}");
|
||||
// So does a stroke that has moved too little to add a point.
|
||||
t.pointer(&cx, &PointerEvent::new(PointerKind::Down, 50.0, 150.0));
|
||||
t.pointer(&cx, &PointerEvent::new(PointerKind::Drag, 50.25, 150.0));
|
||||
assert_eq!(t.cursor(&cx, at, alt), Cursor::BlobBrush);
|
||||
t.pointer(&cx, &PointerEvent::new(PointerKind::Drag, 150.0, 150.0).with_mods(alt));
|
||||
let acts = t.pointer(&cx, &PointerEvent::new(PointerKind::Up, 250.0, 150.0).with_mods(alt));
|
||||
assert!(matches!(acts.as_slice(), [Action::Exec(c, _)] if c == "path.blob"), "{acts:?}");
|
||||
// Alt pressed while the pointer stands still at the press point does not paint on the release.
|
||||
t.pointer(&cx, &PointerEvent::new(PointerKind::Down, 50.0, 150.0));
|
||||
assert_eq!(t.cursor(&cx, at, alt), Cursor::Smooth);
|
||||
let acts = t.pointer(&cx, &PointerEvent::new(PointerKind::Up, 50.0, 150.0).with_mods(alt));
|
||||
assert!(acts.is_empty(), "{acts:?}");
|
||||
// With nothing selected an Alt drag sends nothing.
|
||||
let none = Selection::default();
|
||||
let empty = crate::testutil::cx(&d, &none, &p);
|
||||
|
||||
Reference in New Issue
Block a user