From 14f4dc2e3ca52b9530c72dd5a36c3dd3c708221f Mon Sep 17 00:00:00 2001 From: Dustin Carlino Date: Wed, 11 Dec 2019 13:52:01 -0800 Subject: [PATCH] left click to open info panel. refiddling how drag events are detected. kind of messy code, but the behavior is FINALLY right. --- ezgui/src/canvas.rs | 49 +++++++++++++++++++++++--------- ezgui/src/event_ctx.rs | 10 ++++++- ezgui/src/input.rs | 9 +----- game/src/common/info.rs | 3 +- game/src/common/mod.rs | 2 +- game/src/mission/neighborhood.rs | 3 +- 6 files changed, 48 insertions(+), 28 deletions(-) diff --git a/ezgui/src/canvas.rs b/ezgui/src/canvas.rs index 63900a9970..9bd2154878 100644 --- a/ezgui/src/canvas.rs +++ b/ezgui/src/canvas.rs @@ -18,7 +18,10 @@ pub struct Canvas { pub(crate) cursor_y: f64, pub(crate) window_has_cursor: bool, - pub(crate) left_mouse_drag_from: Option, + // Only for drags starting on the map. Only used to pan the map. + pub(crate) drag_canvas_from: Option, + pub(crate) actually_dragging: bool, + pub(crate) drag_just_ended: bool, pub window_width: f64, pub window_height: f64, @@ -48,7 +51,10 @@ impl Canvas { cursor_y: 0.0, window_has_cursor: true, - left_mouse_drag_from: None, + drag_canvas_from: None, + actually_dragging: false, + drag_just_ended: false, + window_width: initial_width, window_height: initial_height, @@ -63,20 +69,13 @@ impl Canvas { } } - pub(crate) fn is_dragging(&self) -> bool { - self.left_mouse_drag_from.is_some() - } - pub fn handle_event(&mut self, input: &mut UserInput) { // Can't start dragging or zooming on top of covered area - let mouse_on_map = self.get_cursor_in_map_space().is_some(); - if input.left_mouse_button_pressed() && mouse_on_map { - self.left_mouse_drag_from = Some(self.get_cursor_in_screen_space()); - } - if input.left_mouse_button_released() { - self.left_mouse_drag_from = None; - } - if mouse_on_map { + if self.get_cursor_in_map_space().is_some() { + if input.left_mouse_button_pressed() { + self.drag_canvas_from = Some(self.get_cursor_in_screen_space()); + } + if let Some(scroll) = input.get_mouse_scroll() { let old_zoom = self.cam_zoom; self.cam_zoom = 1.1_f64.powf(old_zoom.log(1.1) + scroll); @@ -88,6 +87,28 @@ impl Canvas { ((self.cam_zoom / old_zoom) * (self.cursor_y + self.cam_y)) - self.cursor_y; } } + + // If we start the drag on the map and move the mouse off the map, keep dragging. + if let Some(click) = self.drag_canvas_from { + let pt = self.get_cursor_in_screen_space(); + self.cam_x += click.x - pt.x; + self.cam_y += click.y - pt.y; + self.drag_canvas_from = Some(pt); + if !self.actually_dragging && click != pt { + self.actually_dragging = true; + } + + if input.left_mouse_button_released() { + self.drag_canvas_from = None; + if self.actually_dragging { + self.drag_just_ended = true; + } else { + } + self.actually_dragging = false; + } + } else if self.drag_just_ended { + self.drag_just_ended = false; + } } pub(crate) fn start_drawing(&self) { diff --git a/ezgui/src/event_ctx.rs b/ezgui/src/event_ctx.rs index d4cc74c1ec..e15fa67bbf 100644 --- a/ezgui/src/event_ctx.rs +++ b/ezgui/src/event_ctx.rs @@ -43,10 +43,18 @@ impl<'a> EventCtx<'a> { pub fn redo_mouseover(&self) -> bool { self.input.window_lost_cursor() - || (!self.canvas.is_dragging() && self.input.get_moved_mouse().is_some()) + || (!self.is_dragging() && self.input.get_moved_mouse().is_some()) || self.input.get_mouse_scroll().is_some() } + pub fn normal_left_click(&mut self) -> bool { + !self.is_dragging() && self.input.left_mouse_button_released() + } + + fn is_dragging(&self) -> bool { + self.canvas.drag_canvas_from.is_some() || self.canvas.drag_just_ended + } + pub fn set_textures(&mut self, textures: Vec<(&str, TextureType)>, timer: &mut Timer) { self.canvas.texture_arrays.clear(); self.canvas.texture_lookups.clear(); diff --git a/ezgui/src/input.rs b/ezgui/src/input.rs index d4438f0ec7..f7935b68c7 100644 --- a/ezgui/src/input.rs +++ b/ezgui/src/input.rs @@ -56,15 +56,8 @@ impl UserInput { if let Some(pt) = input.get_moved_mouse() { canvas.cursor_x = pt.x; canvas.cursor_y = pt.y; - - // OK to update this here; the drag has to be initiated from canvas.handle_event, which - // the caller must invoke. - if let Some(click) = canvas.left_mouse_drag_from { - canvas.cam_x += click.x - pt.x; - canvas.cam_y += click.y - pt.y; - canvas.left_mouse_drag_from = Some(pt); - } } + if input.event == Event::WindowGainedCursor { canvas.window_has_cursor = true; } diff --git a/game/src/common/info.rs b/game/src/common/info.rs index b1436a0d26..357e13c3eb 100644 --- a/game/src/common/info.rs +++ b/game/src/common/info.rs @@ -28,8 +28,7 @@ impl State for InfoPanel { self.menu.event(ctx); // Can click on the map to cancel if self.menu.action("quit") - || (ctx.input.left_mouse_button_released() - && ctx.canvas.get_cursor_in_map_space().is_some()) + || (ctx.normal_left_click() && ctx.canvas.get_cursor_in_map_space().is_some()) { Transition::Pop } else { diff --git a/game/src/common/mod.rs b/game/src/common/mod.rs index a1eef40b32..3e39febc58 100644 --- a/game/src/common/mod.rs +++ b/game/src/common/mod.rs @@ -73,7 +73,7 @@ impl CommonState { } if let Some(ref id) = ui.primary.current_selection { - if ctx.input.contextual_action(Key::I, "info") { + if ctx.input.contextual_action(Key::I, "info") || ctx.normal_left_click() { return Some(Transition::Push(Box::new(info::InfoPanel::new( id.clone(), ui, diff --git a/game/src/mission/neighborhood.rs b/game/src/mission/neighborhood.rs index af6da7c389..4bccec60a6 100644 --- a/game/src/mission/neighborhood.rs +++ b/game/src/mission/neighborhood.rs @@ -118,8 +118,7 @@ impl State for NeighborhoodEditor { } else { self.mouseover_pt = None; } - // TODO mouse dragging might be more intuitive, but it's unclear how to - // override part of canvas.handle_event + // TODO maybe click-and-drag is more intuitive if self.mouseover_pt.is_some() && ctx .input