From 23402fea424118d9a8a4c47ba535071d14e929a5 Mon Sep 17 00:00:00 2001 From: Behrang Shafei <50267830+bertiqwerty@users.noreply.github.com> Date: Thu, 8 Aug 2024 20:37:07 +0200 Subject: [PATCH] zoom on mousewheel and pinch --- rvimage/src/main.rs | 50 +++++++++++------- rvimage/src/rvlib/events.rs | 17 ++++++ rvimage/src/rvlib/lib.rs | 2 +- rvimage/src/rvlib/tools/always_active_zoom.rs | 52 ++++++++++++++----- rvimage/src/rvlib/tools/core.rs | 6 +-- 5 files changed, 93 insertions(+), 34 deletions(-) diff --git a/rvimage/src/main.rs b/rvimage/src/main.rs index aaa9e10..5fa0e76 100644 --- a/rvimage/src/main.rs +++ b/rvimage/src/main.rs @@ -21,7 +21,7 @@ use rvlib::{ tools::{self, BBOX_NAME, BRUSH_NAME}, tracing_setup, view_pos_2_orig_pos, write_coco, Annotation, BboxAnnotation, BrushAnnotation, GeoFig, ImageU8, InstanceAnnotate, KeyCode, MainEventLoop, MetaData, Rot90ToolData, ShapeI, - UpdateImage, UpdatePermAnnos, UpdateTmpAnno, UpdateZoomBox, + UpdateImage, UpdatePermAnnos, UpdateTmpAnno, UpdateZoomBox, ZoomAmount, }; use std::{ iter, @@ -192,24 +192,38 @@ fn map_mouse_events( let mut btn_codes = LastSensedBtns::default(); ui.input(|i| { for e in i.events.iter() { - if let egui::Event::PointerButton { - pos: _, - button, - pressed: _, - modifiers, - } = e - { - let modifier_events = map_modifiers(modifiers); - if let Some(me) = modifier_events { - let btn_code = match button { - PointerButton::Primary => KeyCode::MouseLeft, - PointerButton::Secondary => KeyCode::MouseRight, - _ => KeyCode::DontCare, - }; - btn_codes.btn_codes.push(btn_code); - btn_codes.modifiers = me; + match e { + egui::Event::PointerButton { + pos: _, + button, + pressed: _, + modifiers, + } => { + let modifier_events = map_modifiers(modifiers); + if let Some(me) = modifier_events { + let btn_code = match button { + PointerButton::Primary => KeyCode::MouseLeft, + PointerButton::Secondary => KeyCode::MouseRight, + _ => KeyCode::DontCare, + }; + btn_codes.btn_codes.push(btn_code); + btn_codes.modifiers = me; + } } - } + egui::Event::Zoom(z) => { + events.push(rvlib::Event::Zoom(ZoomAmount::Factor(*z as f64))); + } + egui::Event::MouseWheel { + unit: _, + delta, + modifiers, + } => { + if modifiers.ctrl { + events.push(rvlib::Event::Zoom(ZoomAmount::Delta(delta.y as f64))); + } + } + _ => {} + }; } }); if !btn_codes.is_empty() { diff --git a/rvimage/src/rvlib/events.rs b/rvimage/src/rvlib/events.rs index eb97de1..36464fa 100644 --- a/rvimage/src/rvlib/events.rs +++ b/rvimage/src/rvlib/events.rs @@ -1,5 +1,10 @@ use rvimage_domain::PtF; +#[derive(Clone, Copy, Debug)] +pub enum ZoomAmount { + Delta(f64), + Factor(f64), +} macro_rules! action_keycode { ($name:ident, $action:ident, $key_code:ident) => { pub fn $name(&self) -> bool { @@ -48,6 +53,17 @@ impl Events { self.events.append(&mut events); self } + pub fn zoom(&self) -> Option { + self.events + .iter() + .find(|e| matches!(e, Event::Zoom(_))) + .map(|e| match e { + Event::Zoom(z) => *z, + _ => { + unreachable!(); + } + }) + } action_keycode!(held_alt, Held, Alt); action_keycode!(held_shift, Held, Shift); action_keycode!(held_ctrl, Held, Ctrl); @@ -110,4 +126,5 @@ pub enum Event { Released(KeyCode), Held(KeyCode), MouseWheel(i64), + Zoom(ZoomAmount), } diff --git a/rvimage/src/rvlib/lib.rs b/rvimage/src/rvlib/lib.rs index 580e220..0502925 100644 --- a/rvimage/src/rvlib/lib.rs +++ b/rvimage/src/rvlib/lib.rs @@ -27,7 +27,7 @@ pub use drawme::{ Annotation, BboxAnnotation, BrushAnnotation, Stroke, UpdateImage, UpdatePermAnnos, UpdateTmpAnno, UpdateView, UpdateZoomBox, }; -pub use events::{Event, Events, KeyCode}; +pub use events::{Event, Events, KeyCode, ZoomAmount}; pub use file_util::get_test_folder; pub use main_loop::MainEventLoop; pub use meta_data::MetaData; diff --git a/rvimage/src/rvlib/tools/always_active_zoom.rs b/rvimage/src/rvlib/tools/always_active_zoom.rs index 8b43fc6..ae27686 100644 --- a/rvimage/src/rvlib/tools/always_active_zoom.rs +++ b/rvimage/src/rvlib/tools/always_active_zoom.rs @@ -3,7 +3,7 @@ use std::fmt::Debug; use rvimage_domain::{BbF, BbI, ShapeI}; use crate::{ - events::{Events, KeyCode}, + events::{Events, KeyCode, ZoomAmount}, history::History, make_tool_transform, tools::core::Manipulate, @@ -15,19 +15,28 @@ use super::{core::Mover, zoom::move_zoom_box}; fn event_move_zoom_box(events: &Events) -> bool { events.held_ctrl() && (events.pressed(KeyCode::MouseLeft) || events.held(KeyCode::MouseLeft)) } -fn zoom_box_mouse_wheel(zoom_box: Option, shape_orig: ShapeI, y_delta: f64) -> Option { +fn zoom_box_mouse_wheel( + zoom_box: Option, + shape_orig: ShapeI, + amount: ZoomAmount, +) -> Option { let current_zb = if let Some(zb) = zoom_box { zb } else { BbI::from_arr(&[0, 0, shape_orig.w, shape_orig.h]).into() }; let clip_val = 1.0; - let y_delta_clipped = if y_delta > 0.0 { - y_delta.min(clip_val) - } else { - y_delta.max(-clip_val) + let factor = match amount { + ZoomAmount::Delta(y_delta) => { + let y_delta_clipped = if y_delta > 0.0 { + y_delta.min(clip_val) + } else { + y_delta.max(-clip_val) + }; + 1.0 - y_delta_clipped * 0.1 + } + ZoomAmount::Factor(factor) => factor, }; - let factor = 1.0 - y_delta_clipped * 0.1; Some(current_zb.center_scale(factor, shape_orig)) } @@ -73,9 +82,17 @@ impl AlwaysActiveZoom { let zb = if events.released(KeyCode::Key0) { None } else if events.released(KeyCode::PlusEquals) { - zoom_box_mouse_wheel(*world.zoom_box(), world.shape_orig(), 1.0) + zoom_box_mouse_wheel( + *world.zoom_box(), + world.shape_orig(), + ZoomAmount::Delta(1.0), + ) } else if events.released(KeyCode::Minus) { - zoom_box_mouse_wheel(*world.zoom_box(), world.shape_orig(), -1.0) + zoom_box_mouse_wheel( + *world.zoom_box(), + world.shape_orig(), + ZoomAmount::Delta(-1.0), + ) } else { *world.zoom_box() }; @@ -94,10 +111,21 @@ impl Manipulate for AlwaysActiveZoom { let zoomed = events.held_ctrl() && (events.released(KeyCode::Key0) || events.released(KeyCode::PlusEquals) - || events.released(KeyCode::Minus)); + || events.released(KeyCode::Minus) + || events.zoom().is_some()); Some(zoomed || event_move_zoom_box(events)) } - fn events_tf(&mut self, world: World, history: History, events: &Events) -> (World, History) { + fn events_tf( + &mut self, + mut world: World, + history: History, + events: &Events, + ) -> (World, History) { + let zoom_factor = events.zoom(); + if let Some(z) = zoom_factor { + let zb = zoom_box_mouse_wheel(*world.zoom_box(), world.shape_orig(), z); + world.set_zoom_box(zb); + } make_tool_transform!( self, world, @@ -119,7 +147,7 @@ fn test_zb() { fn test(zb: Option, y_delta: f64, reference_coords: &[u32; 4]) { println!("y_delta {}", y_delta); let shape = ShapeI::new(200, 100); - let zb_new = zoom_box_mouse_wheel(zb, shape, y_delta); + let zb_new = zoom_box_mouse_wheel(zb, shape, ZoomAmount::Delta(y_delta)); assert_eq!(zb_new, Some(BbI::from_arr(reference_coords).into())); } test(None, 1.0, &[10, 5, 180, 90]); diff --git a/rvimage/src/rvlib/tools/core.rs b/rvimage/src/rvlib/tools/core.rs index 49e8d2d..b6fba02 100644 --- a/rvimage/src/rvlib/tools/core.rs +++ b/rvimage/src/rvlib/tools/core.rs @@ -599,14 +599,14 @@ macro_rules! make_tool_transform { $self:expr, $world:expr, $history:expr, - $event:expr, + $events:expr, [$(($key_event:ident, $key_btn:expr, $method_name:ident)),*] ) => { if false { ($world, $history) } - $(else if $event.$key_event($key_btn) { - $self.$method_name($event, $world, $history) + $(else if $events.$key_event($key_btn) { + $self.$method_name($events, $world, $history) })* else { ($world, $history)