Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: e77cd34a-ce3e-4981-996f-4d37d49df90d
This commit is contained in:
parent
0aabb48687
commit
2050ca083e
|
|
@ -304,6 +304,16 @@ fn pointer_moves(events: &[egui::Event], button: egui::PointerButton, down_at_st
|
|||
out
|
||||
}
|
||||
|
||||
/// Modifiers attached to the pointer event itself. Some input sources provide these without a
|
||||
/// separate `ModifiersChanged` event, so use them for click gestures before falling back to the
|
||||
/// frame-wide modifier state.
|
||||
fn pointer_button_modifiers(events: &[egui::Event], button: egui::PointerButton) -> Option<egui::Modifiers> {
|
||||
events.iter().rev().find_map(|e| match e {
|
||||
egui::Event::PointerButton { button: b, modifiers, .. } if *b == button => Some(*modifiers),
|
||||
_ => None,
|
||||
})
|
||||
}
|
||||
|
||||
/// Abstract tool event, produced by the mouse or by automation (`ui.pointer`).
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
pub enum ToolEvent {
|
||||
|
|
@ -1761,10 +1771,12 @@ pub fn canvas_view(app: &mut PhotocraftApp, ui: &mut egui::Ui, idx: usize, rect:
|
|||
if buttons.clicked
|
||||
&& let Some(p) = response.interact_pointer_pos()
|
||||
{
|
||||
let click_button = if app.secondary_erase { PointerButton::Secondary } else { PointerButton::Primary };
|
||||
let click_mods = ui.input(|i| pointer_button_modifiers(&i.events, click_button)).unwrap_or(mods);
|
||||
let d = xf.to_doc(p);
|
||||
match tool {
|
||||
Tool::Zoom => {
|
||||
let nz = zoom_step(view.zoom, if zoom_out(mods.alt) { -1 } else { 1 });
|
||||
let nz = zoom_step(view.zoom, if zoom_out(click_mods.alt) { -1 } else { 1 });
|
||||
zoom_about(&mut view, &xf, p, nz);
|
||||
}
|
||||
// A click with the (temporary) Hand does nothing, never the tool underneath.
|
||||
|
|
@ -1777,8 +1789,8 @@ pub fn canvas_view(app: &mut PhotocraftApp, ui: &mut egui::Ui, idx: usize, rect:
|
|||
if tool == Tool::Move && app.ui.transform.is_none() {
|
||||
begin_transform_controls_at(app, &ctx, &xf, p);
|
||||
}
|
||||
tool_event(app, ToolEvent::Down { x: d[0], y: d[1], pressure: 1.0 }, mods);
|
||||
tool_event(app, ToolEvent::Up { x: d[0], y: d[1] }, mods);
|
||||
tool_event(app, ToolEvent::Down { x: d[0], y: d[1], pressure: 1.0 }, click_mods);
|
||||
tool_event(app, ToolEvent::Up { x: d[0], y: d[1] }, click_mods);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -223,6 +223,38 @@ mod tests {
|
|||
assert!(alpha_at(&h, a + (b - a) * 0.5) > 0.9);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn shift_click_connects_to_the_previous_brush_stroke() {
|
||||
use egui::{Event, Modifiers};
|
||||
|
||||
let mut h = harness(None);
|
||||
let (_, end) = drag(&mut h, PointerButton::Primary);
|
||||
let previous = h
|
||||
.state()
|
||||
.session
|
||||
.journal
|
||||
.iter()
|
||||
.rev()
|
||||
.find(|(id, _)| id == "paint.stroke")
|
||||
.map(|(_, p)| p["points"].as_array().unwrap().last().unwrap().clone())
|
||||
.unwrap();
|
||||
let target = end + vec2(120.0, 80.0);
|
||||
h.event(Event::PointerMoved(target));
|
||||
h.run_steps(1);
|
||||
for pressed in [true, false] {
|
||||
h.event(Event::PointerButton { pos: target, button: PointerButton::Primary, pressed, modifiers: Modifiers::SHIFT });
|
||||
h.run_steps(2);
|
||||
}
|
||||
|
||||
let strokes = strokes(&h);
|
||||
assert_eq!(strokes.len(), 2, "a Shift-click commits one connected stroke");
|
||||
let points = strokes[1]["points"].as_array().unwrap();
|
||||
assert_eq!(points.len(), 2, "a click has the previous endpoint and clicked endpoint");
|
||||
assert_eq!(points[0][0], previous[0]);
|
||||
assert_eq!(points[0][1], previous[1]);
|
||||
assert!(alpha_at(&h, end + vec2(60.0, 40.0)) > 0.9, "the segment between the strokes is painted");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn right_click_opens_the_brush_picker_and_never_paints() {
|
||||
let mut h = harness(None);
|
||||
|
|
|
|||
Loading…
Reference in New Issue