diff --git a/examples/mouse-state.rs b/examples/mouse-state.rs new file mode 100644 index 00000000..0827c7b2 --- /dev/null +++ b/examples/mouse-state.rs @@ -0,0 +1,47 @@ +extern crate sdl2; + +use sdl2::event::Event; +use sdl2::mouse::MouseButton; +use std::collections::HashSet; +use std::time::Duration; + +pub fn main() { + let sdl_context = sdl2::init().unwrap(); + let video_subsystem = sdl_context.video().unwrap(); + + let _window = video_subsystem.window("Mouse", 800, 600) + .position_centered() + .build() + .unwrap(); + + let mut events = sdl_context.event_pump().unwrap(); + + let mut prev_buttons = HashSet::new(); + + 'running: loop { + for event in events.poll_iter() { + match event { + Event::Quit {..} => break 'running, + _ => () + } + } + + // get a mouse state + let state = events.mouse_state(); + + // Create a set of pressed Keys. + let buttons = state.pressed_mouse_buttons().collect(); + + // Get the difference between the new and old sets. + let new_buttons = &buttons - &prev_buttons; + let old_buttons = &prev_buttons - &buttons; + + if !new_buttons.is_empty() || !old_buttons.is_empty() { + println!("X = {:?}, Y = {:?} : {:?} -> {:?}", state.x(), state.y(), new_buttons, old_buttons); + } + + prev_buttons = buttons; + + std::thread::sleep(Duration::from_millis(100)); + } +} diff --git a/examples/relative-mouse-state.rs b/examples/relative-mouse-state.rs new file mode 100644 index 00000000..ca4e351f --- /dev/null +++ b/examples/relative-mouse-state.rs @@ -0,0 +1,39 @@ +extern crate sdl2; + +use sdl2::event::Event; +use sdl2::mouse::MouseButton; +use std::time::Duration; + +pub fn main() { + let sdl_context = sdl2::init().unwrap(); + let video_subsystem = sdl_context.video().unwrap(); + + let _window = video_subsystem.window("Mouse", 800, 600) + .position_centered() + .build() + .unwrap(); + + let mut events = sdl_context.event_pump().unwrap(); + + let mut state = events.relative_mouse_state(); + let mut old_x = 0; + let mut old_y = 0; + + 'running: loop { + for event in events.poll_iter() { + match event { + Event::Quit {..} => break 'running, + _ => () + } + } + + // get a mouse state using mouse_state() so as not to call + // relative_mouse_state() twice and get a false position reading + if events.mouse_state().is_mouse_button_pressed(MouseButton::Left) { + state = events.relative_mouse_state(); + println!("Relative - X = {:?}, Y = {:?}", state.x(), state.y()); + } + + std::thread::sleep(Duration::from_millis(100)); + } +} diff --git a/src/sdl2/mouse/mod.rs b/src/sdl2/mouse/mod.rs index de01e6c1..588907bd 100644 --- a/src/sdl2/mouse/mod.rs +++ b/src/sdl2/mouse/mod.rs @@ -183,22 +183,22 @@ impl MouseButton { #[derive(Copy, Clone, Eq, PartialEq, Hash)] pub struct MouseState { mouse_state: u32, - x: u32, - y: u32 + x: i32, + y: i32 } impl MouseState { pub fn new(_e: &EventPump) -> MouseState { let mut x = 0; let mut y = 0; - let mouse_state = unsafe { + let mouse_state: u32 = unsafe { ll::SDL_GetMouseState(&mut x, &mut y) }; MouseState { mouse_state: mouse_state, - x: x as u32, - y: y as u32 + x: x as i32, + y: y as i32 } } @@ -233,18 +233,25 @@ impl MouseState { /// Tests if the X2 mouse button was pressed. pub fn x2(&self) -> bool { (self.mouse_state & ll::SDL_BUTTON_X2MASK) != 0 } + /// Returns the x coordinate of the state + pub fn x(&self) -> i32 { self.x } + + /// Returns the y coordinate of the state + pub fn y(&self) -> i32 { self.y } + /// Returns true if the mouse button is pressed. /// /// # Example /// ```no_run /// use sdl2::mouse::MouseButton; /// - /// fn is_a_pressed(e: &sdl2::EventPump) -> bool { + /// fn is_left_pressed(e: &sdl2::EventPump) -> bool { /// e.mouse_state().is_mouse_button_pressed(MouseButton::Left) /// } /// ``` pub fn is_mouse_button_pressed(&self, mouse_button: MouseButton) -> bool { - self.mouse_state<<((mouse_button as u32)-1) != 0 + let mask = 1 << ((mouse_button as u32)-1); + self.mouse_state & mask != 0 } /// Returns an iterator all mouse buttons with a boolean indicating if the scancode is pressed. @@ -305,12 +312,13 @@ impl<'a> Iterator for MouseButtonIterator<'a> { type Item = (MouseButton, bool); fn next(&mut self) -> Option<(MouseButton, bool)> { - if self.index < MouseButton::X2 as usize { + if self.index < MouseButton::X2 as usize +1 { let index = self.index; self.index += 1; if let Some(mouse_button) = FromPrimitive::from_usize(index) { - let pressed = self.mouse_state&(MouseButton::Middle as u32) != 0; + let mask = 1 << ((mouse_button as u32)-1); + let pressed = self.mouse_state & mask != 0; Some((mouse_button, pressed)) } else { diff --git a/src/sdl2/mouse/relative.rs b/src/sdl2/mouse/relative.rs index 74b394aa..f73f1865 100644 --- a/src/sdl2/mouse/relative.rs +++ b/src/sdl2/mouse/relative.rs @@ -7,8 +7,8 @@ use super::{MouseButton, MouseButtonIterator, PressedMouseButtonIterator}; #[derive(Copy, Clone, Eq, PartialEq, Hash)] pub struct RelativeMouseState { mouse_state: u32, - x: u32, - y: u32 + x: i32, + y: i32 } impl RelativeMouseState { @@ -22,8 +22,8 @@ impl RelativeMouseState { RelativeMouseState { mouse_state: mouse_state, - x: x as u32, - y: y as u32 + x: x as i32, + y: y as i32 } } @@ -58,18 +58,25 @@ impl RelativeMouseState { /// Tests if the X2 mouse button was pressed. pub fn x2(&self) -> bool { (self.mouse_state & ll::SDL_BUTTON_X2MASK) != 0 } + /// Returns the x coordinate of the state + pub fn x(&self) -> i32 { self.x } + + /// Returns the y coordinate of the state + pub fn y(&self) -> i32 { self.y } + /// Returns true if the mouse button is pressed. /// /// # Example /// ```no_run /// use sdl2::mouse::MouseButton; /// - /// fn is_a_pressed(e: &sdl2::EventPump) -> bool { + /// fn is_left_pressed(e: &sdl2::EventPump) -> bool { /// e.mouse_state().is_mouse_button_pressed(MouseButton::Left) /// } /// ``` pub fn is_mouse_button_pressed(&self, mouse_button: MouseButton) -> bool { - self.mouse_state<<((mouse_button as u32)-1) != 0 + let mask = 1 << ((mouse_button as u32)-1); + self.mouse_state & mask != 0 } /// Returns an iterator all mouse buttons with a boolean indicating if the scancode is pressed.