diff --git a/sdl2-sys/src/mouse.rs b/sdl2-sys/src/mouse.rs index bdddab2c..894eda4b 100644 --- a/sdl2-sys/src/mouse.rs +++ b/sdl2-sys/src/mouse.rs @@ -21,8 +21,7 @@ pub const SDL_SYSTEM_CURSOR_NO: SDL_SystemCursor = 10; pub const SDL_SYSTEM_CURSOR_HAND: SDL_SystemCursor = 11; pub const SDL_NUM_SYSTEM_CURSORS: SDL_SystemCursor = 12; -// #define SDL_BUTTON(X) (SDL_PRESSED<<(X-1)) -// need to shift the SDL_BUTTON_LEFT over per above + pub const SDL_BUTTON_UNKNOWN: u8 = 0; pub const SDL_BUTTON_LEFT : u8 = 1; pub const SDL_BUTTON_MIDDLE : u8 = 2; diff --git a/src/sdl2/event.rs b/src/sdl2/event.rs index 7d141330..8164784c 100644 --- a/src/sdl2/event.rs +++ b/src/sdl2/event.rs @@ -23,7 +23,7 @@ use keyboard::Mod; use sys::keycode::SDL_Keymod; use keyboard::Keycode; use mouse; -use mouse::{Mousecode, MouseState, MouseWheelDirection}; +use mouse::{Mousebutton, MouseState, MouseWheelDirection}; use keyboard::Scancode; use get_error; @@ -510,7 +510,7 @@ pub enum Event { timestamp: u32, window_id: u32, which: u32, - mouse_btn: Option, + mouse_btn: Option, x: i32, y: i32 }, @@ -518,7 +518,7 @@ pub enum Event { timestamp: u32, window_id: u32, which: u32, - mouse_btn: Option, + mouse_btn: Option, x: i32, y: i32 }, @@ -755,8 +755,9 @@ fn mk_keysym(scancode: Option, } } -fn mk_mousesym(mousecode: Option) -> u8 { - mousecode.unwrap().to_ll().unwrap() +/// Helper function is only to unwrap a mousebutton to u8 +fn mk_mousesym(mousebutton: Option) -> u8 { + mousebutton.unwrap().to_ll().unwrap() } // TODO: Remove this when from_utf8 is updated in Rust @@ -1373,7 +1374,7 @@ impl Event { timestamp: event.timestamp, window_id: event.windowID, which: event.which, - mouse_btn: mouse::Mousecode::from_ll(event.button), + mouse_btn: mouse::Mousebutton::from_ll(event.button), x: event.x, y: event.y } @@ -1385,7 +1386,7 @@ impl Event { timestamp: event.timestamp, window_id: event.windowID, which: event.which, - mouse_btn: mouse::Mousecode::from_ll(event.button), + mouse_btn: mouse::Mousebutton::from_ll(event.button), x: event.x, y: event.y } @@ -1836,7 +1837,7 @@ mod test { use super::WindowEventId; use super::super::controller::{Button, Axis}; use super::super::joystick::{HatState}; - use super::super::mouse::{Mouse, MouseState, MouseWheelDirection}; + use super::super::mouse::{Mousebutton, MouseState, MouseWheelDirection}; use super::super::keyboard::{Keycode, Scancode, Mod}; // Tests a round-trip conversion from an Event type to @@ -1889,7 +1890,7 @@ mod test { timestamp: 0, window_id: 0, which: 1, - mousestate: MouseState::from_state(1), + mousestate: MouseState::from_sdl_state(1), x: 3, y: 91, xrel: -1, @@ -1903,7 +1904,7 @@ mod test { timestamp: 5634, window_id: 2, which: 0, - mouse_btn: Mouse::Left, + mouse_btn: Some(Mousebutton::Left), x: 543, y: 345, }; @@ -1915,7 +1916,7 @@ mod test { timestamp: 0, window_id: 2, which: 0, - mouse_btn: Mouse::Left, + mouse_btn: Some(Mousebutton::Left), x: 543, y: 345, diff --git a/src/sdl2/mouse.rs b/src/sdl2/mouse.rs index 4c6cfc99..fdb2262d 100644 --- a/src/sdl2/mouse.rs +++ b/src/sdl2/mouse.rs @@ -127,7 +127,7 @@ impl MouseWheelDirection { } #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] -pub enum Mousecode { +pub enum Mousebutton { Left = ll::SDL_BUTTON_LEFT as isize, Middle = ll::SDL_BUTTON_MIDDLE as isize, Right = ll::SDL_BUTTON_RIGHT as isize, @@ -135,7 +135,7 @@ pub enum Mousecode { X2 = ll::SDL_BUTTON_X2 as isize, } -impl ToPrimitive for Mousecode { +impl ToPrimitive for Mousebutton { #[inline] fn to_i64(&self) -> Option { Some(*self as i64) @@ -152,15 +152,22 @@ impl ToPrimitive for Mousecode { } } -impl Mousecode { +impl FromPrimitive for Mousebutton { #[inline] - pub fn from_ll(button: u8) -> Option { + fn from_i64(n: i64) -> Option { Mousebutton::from_ll(n as u8) } + #[inline] + fn from_u64(n: u64) -> Option { Mousebutton::from_ll(n as u8) } +} + +impl Mousebutton { + #[inline] + pub fn from_ll(button: u8) -> Option { Some(match button { - ll::SDL_BUTTON_LEFT => Mousecode::Left, - ll::SDL_BUTTON_MIDDLE => Mousecode::Middle, - ll::SDL_BUTTON_RIGHT => Mousecode::Right, - ll::SDL_BUTTON_X1 => Mousecode::X1, - ll::SDL_BUTTON_X2 => Mousecode::X2, + ll::SDL_BUTTON_LEFT => Mousebutton::Left, + ll::SDL_BUTTON_MIDDLE => Mousebutton::Middle, + ll::SDL_BUTTON_RIGHT => Mousebutton::Right, + ll::SDL_BUTTON_X1 => Mousebutton::X1, + ll::SDL_BUTTON_X2 => Mousebutton::X2, _ => return None, }) } @@ -195,6 +202,114 @@ impl MouseState { pub fn to_sdl_state(&self) -> u32 { self.mouse_state } + + /// Returns true if the left mouse button is pressed. + /// + /// # Example + /// ```no_run + /// use sdl2::mouse::Mousebutton; + /// + /// fn is_a_pressed(e: &sdl2::EventPump) -> bool { + /// e.mouse_state().left() + /// } + pub fn left(&self) -> bool { (self.mouse_state & ll::SDL_BUTTON_LMASK) != 0 } + + /// Tests if the middle mouse button was pressed. + pub fn middle(&self) -> bool { (self.mouse_state & ll::SDL_BUTTON_MMASK) != 0 } + + /// Tests if the right mouse button was pressed. + pub fn right(&self) -> bool { (self.mouse_state & ll::SDL_BUTTON_RMASK) != 0 } + + /// Tests if the X1 mouse button was pressed. + pub fn x1(&self) -> bool { (self.mouse_state & ll::SDL_BUTTON_X1MASK) != 0 } + + /// Tests if the X2 mouse button was pressed. + pub fn x2(&self) -> bool { (self.mouse_state & ll::SDL_BUTTON_X2MASK) != 0 } + + /// Returns true if the mouse button is pressed. + /// + /// # Example + /// ```no_run + /// use sdl2::mouse::Mousebutton; + /// + /// fn is_a_pressed(e: &sdl2::EventPump) -> bool { + /// e.mouse_state().is_mousebutton_pressed(Mousebutton::Left) + /// } + /// ``` + pub fn is_mousebutton_pressed(&self, mousebutton: Mousebutton) -> bool { + self.mouse_state<<((mousebutton as u32)-1) != 0 + } + + /// Returns an iterator all scancodes with a boolean indicating if the scancode is pressed. + pub fn mousebuttons(&self) -> MousebuttonIterator { + MousebuttonIterator { + index: 0, + mouse_state: &self.mouse_state + } + } + + /// Returns an iterator of pressed mouse buttons. + /// + /// # Example + /// ```no_run + /// use sdl2::mouse::Mousebutton; + /// use std::collections::HashSet; + /// + /// fn pressed_mousebutton_set(e: &sdl2::EventPump) -> HashSet { + /// e.mouse_state().pressed_mousebuttons().collect() + /// } + /// + /// fn newly_pressed(old: &HashSet, new: &HashSet) -> HashSet { + /// new - old + /// // sugar for: new.difference(old).collect() + /// } + /// ``` + pub fn pressed_mousebuttons(&self) -> PressedMousebuttonIterator { + PressedMousebuttonIterator { + iter: self.mousebuttons() + } + } +} + +pub struct MousebuttonIterator<'a> { + index: usize, + mouse_state: &'a u32 +} + +impl<'a> Iterator for MousebuttonIterator<'a> { + type Item = (Mousebutton, bool); + + fn next(&mut self) -> Option<(Mousebutton, bool)> { + if self.index < Mousebutton::X2 as usize { + let index = self.index; + self.index += 1; + + if let Some(mousebutton) = FromPrimitive::from_usize(index) { + let pressed = self.mouse_state&(Mousebutton::Middle as u32) != 0; + + Some((mousebutton, pressed)) + } else { + self.next() + } + } else { + None + } + } +} + +pub struct PressedMousebuttonIterator<'a> { + iter: MousebuttonIterator<'a> +} + +impl<'a> Iterator for PressedMousebuttonIterator<'a> { + type Item = Mousebutton; + + fn next(&mut self) -> Option { + while let Some((mousebutton, pressed)) = self.iter.next() { + if pressed { return Some(mousebutton) } + } + None + } } impl ::Sdl { @@ -229,13 +344,13 @@ impl MouseUtil { Some(id) } } -/* + pub fn mouse_state(&self) -> (MouseState, i32, i32) { let mut x = 0; let mut y = 0; unsafe { let raw = ll::SDL_GetMouseState(&mut x, &mut y); - return (MouseState::from_flags(raw), x as i32, y as i32); + return (MouseState::from_sdl_state(raw), x as i32, y as i32); } } @@ -244,10 +359,10 @@ impl MouseUtil { let mut y = 0; unsafe { let raw = ll::SDL_GetRelativeMouseState(&mut x, &mut y); - return (MouseState::from_flags(raw), x as i32, y as i32); + return (MouseState::from_sdl_state(raw), x as i32, y as i32); } } -*/ + pub fn warp_mouse_in_window(&self, window: &video::WindowRef, x: i32, y: i32) { unsafe { ll::SDL_WarpMouseInWindow(window.raw(), x, y); } }