diff --git a/assets/animate.bmp b/assets/animate.bmp new file mode 100644 index 00000000..2b6f65d0 Binary files /dev/null and b/assets/animate.bmp differ diff --git a/examples/animation.rs b/examples/animation.rs new file mode 100644 index 00000000..fcc32f49 --- /dev/null +++ b/examples/animation.rs @@ -0,0 +1,55 @@ +extern crate sdl2; +use std::path::Path; + +use sdl2::event::Event; +use sdl2::keyboard::Keycode; +use sdl2::rect::Rect; +use sdl2::rect::Point; +use std::time::Duration; + +fn main() { + let sdl_context = sdl2::init().unwrap(); + let video_subsystem = sdl_context.video().unwrap(); + + let window = video_subsystem.window("SDL2", 640, 480) + .position_centered().build().unwrap(); + + let mut renderer = window.renderer() + .accelerated().build().unwrap(); + + renderer.set_draw_color(sdl2::pixels::Color::RGBA(0,0,0,255)); + + let mut timer = sdl_context.timer().unwrap(); + + let mut event_pump = sdl_context.event_pump().unwrap(); + + let temp_surface = sdl2::surface::Surface::load_bmp(Path::new("assets/animate.bmp")).unwrap(); + let texture = renderer.create_texture_from_surface(&temp_surface).unwrap(); + let texture_query = texture.query(); + + let mut center = Point::new(320,240); + let mut source_rect = Rect::new(0, 0, 128, 82); + let mut dest_rect = Rect::new(0,0, 128, 82); + dest_rect.center_on(center); + + let mut running = true; + while running { + for event in event_pump.poll_iter() { + match event { + Event::Quit {..} | Event::KeyDown {keycode: Some(Keycode::Escape), ..} => { + running = false; + }, + _ => {} + } + } + + let ticks = timer.ticks(); + + source_rect.set_x((128 * ((ticks / 100) % 6) ) as i32); + renderer.clear(); + renderer.copy_ex(&texture, Some(source_rect), Some(dest_rect), 10.0, None, true, false); + renderer.present(); + + std::thread::sleep(Duration::from_millis(100)); + } +} 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/sdl2-sys/src/mouse.rs b/sdl2-sys/src/mouse.rs index 56437b6d..894eda4b 100644 --- a/sdl2-sys/src/mouse.rs +++ b/sdl2-sys/src/mouse.rs @@ -22,17 +22,17 @@ pub const SDL_SYSTEM_CURSOR_HAND: SDL_SystemCursor = 11; pub const SDL_NUM_SYSTEM_CURSORS: SDL_SystemCursor = 12; - -pub const SDL_BUTTON_LEFT: u8 = 1; -pub const SDL_BUTTON_MIDDLE: u8 = 2; -pub const SDL_BUTTON_RIGHT: u8 = 3; -pub const SDL_BUTTON_X1: u8 = 4; -pub const SDL_BUTTON_X2: u8 = 5; -pub const SDL_BUTTON_LMASK: u32 = 0x01; -pub const SDL_BUTTON_MMASK: u32 = 0x02; -pub const SDL_BUTTON_RMASK: u32 = 0x04; -pub const SDL_BUTTON_X1MASK: u32 = 0x08; -pub const SDL_BUTTON_X2MASK: u32 = 0x10; +pub const SDL_BUTTON_UNKNOWN: u8 = 0; +pub const SDL_BUTTON_LEFT : u8 = 1; +pub const SDL_BUTTON_MIDDLE : u8 = 2; +pub const SDL_BUTTON_RIGHT : u8 = 3; +pub const SDL_BUTTON_X1 : u8 = 4; +pub const SDL_BUTTON_X2 : u8 = 5; +pub const SDL_BUTTON_LMASK : u32 = 0x01; +pub const SDL_BUTTON_MMASK : u32 = 0x02; +pub const SDL_BUTTON_RMASK : u32 = 0x04; +pub const SDL_BUTTON_X1MASK : u32 = 0x08; +pub const SDL_BUTTON_X2MASK : u32 = 0x10; extern "C" { diff --git a/src/sdl2/event.rs b/src/sdl2/event.rs index f53f0c57..82b31b3e 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::{Mouse, MouseState, MouseWheelDirection}; +use mouse::{MouseButton, MouseState, MouseWheelDirection}; use keyboard::Scancode; use get_error; @@ -456,7 +456,7 @@ pub enum Event { AppDidEnterForeground { timestamp: u32 }, Window { - timestamp: u32 , + timestamp: u32, window_id: u32, win_event_id: WindowEventId, data1: i32, @@ -465,7 +465,7 @@ pub enum Event { // TODO: SysWMEvent KeyDown { - timestamp: u32 , + timestamp: u32, window_id: u32, keycode: Option, scancode: Option, @@ -473,7 +473,7 @@ pub enum Event { repeat: bool }, KeyUp { - timestamp: u32 , + timestamp: u32, window_id: u32, keycode: Option, scancode: Option, @@ -510,7 +510,7 @@ pub enum Event { timestamp: u32, window_id: u32, which: u32, - mouse_btn: Mouse, + mouse_btn: Option, x: i32, y: i32 }, @@ -518,7 +518,7 @@ pub enum Event { timestamp: u32, window_id: u32, which: u32, - mouse_btn: Mouse, + mouse_btn: Option, x: i32, y: i32 }, @@ -755,6 +755,11 @@ fn mk_keysym(scancode: Option, } } +/// Helper function is only to unwrap a mouse_button to u8 +fn mk_mouse_button(mouse_button: Option) -> u8 { + mouse_button.unwrap().to_ll().unwrap() +} + // TODO: Remove this when from_utf8 is updated in Rust // This would honestly be nice if it took &self instead of self, // but Event::User's raw pointers kind of removes that possibility. @@ -870,7 +875,7 @@ impl Event { xrel, yrel } => { - let state = mousestate.to_flags(); + let state = mousestate.to_sdl_state(); let event = ll::SDL_MouseMotionEvent { type_: ll::SDL_MOUSEMOTION, timestamp: timestamp, @@ -896,7 +901,7 @@ impl Event { x, y } => { - let button = mouse_btn.to_ll(); + let button = mk_mouse_button(mouse_btn); let event = ll::SDL_MouseButtonEvent { type_: ll::SDL_MOUSEBUTTONDOWN, timestamp: timestamp, @@ -922,7 +927,7 @@ impl Event { x, y } => { - let button = mouse_btn.to_ll(); + let button = mk_mouse_button(mouse_btn); let event = ll::SDL_MouseButtonEvent { type_: ll::SDL_MOUSEBUTTONUP, timestamp: timestamp, @@ -1355,7 +1360,7 @@ impl Event { timestamp: event.timestamp, window_id: event.windowID, which: event.which, - mousestate: mouse::MouseState::from_flags(event.state), + mousestate: mouse::MouseState::from_sdl_state(event.state), x: event.x, y: event.y, xrel: event.xrel, @@ -1369,7 +1374,7 @@ impl Event { timestamp: event.timestamp, window_id: event.windowID, which: event.which, - mouse_btn: mouse::Mouse::from_ll(event.button), + mouse_btn: mouse::MouseButton::from_ll(event.button), x: event.x, y: event.y } @@ -1381,7 +1386,7 @@ impl Event { timestamp: event.timestamp, window_id: event.windowID, which: event.which, - mouse_btn: mouse::Mouse::from_ll(event.button), + mouse_btn: mouse::MouseButton::from_ll(event.button), x: event.x, y: event.y } @@ -1784,6 +1789,16 @@ impl ::EventPump { pub fn keyboard_state(&self) -> ::keyboard::KeyboardState { ::keyboard::KeyboardState::new(self) } + + #[inline] + pub fn mouse_state(&self) -> ::mouse::MouseState { + ::mouse::MouseState::new(self) + } + + #[inline] + pub fn relative_mouse_state(&self) -> ::mouse::RelativeMouseState { + ::mouse::RelativeMouseState::new(self) + } } /// An iterator that calls `EventPump::poll_event()`. @@ -1827,7 +1842,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 @@ -1880,7 +1895,7 @@ mod test { timestamp: 0, window_id: 0, which: 1, - mousestate: MouseState::from_flags(1), + mousestate: MouseState::from_sdl_state(1), x: 3, y: 91, xrel: -1, @@ -1894,7 +1909,7 @@ mod test { timestamp: 5634, window_id: 2, which: 0, - mouse_btn: Mouse::Left, + mouse_btn: Some(MouseButton::Left), x: 543, y: 345, }; @@ -1906,7 +1921,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/mod.rs similarity index 50% rename from src/sdl2/mouse.rs rename to src/sdl2/mouse/mod.rs index e42a53e0..588907bd 100644 --- a/src/sdl2/mouse.rs +++ b/src/sdl2/mouse/mod.rs @@ -1,11 +1,16 @@ +use num::{ToPrimitive, FromPrimitive}; use std::ptr; use get_error; use surface::SurfaceRef; use video; +use EventPump; use sys::mouse as ll; +mod relative; +pub use self::relative::RelativeMouseState; + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] #[repr(u32)] pub enum SystemCursor { @@ -124,84 +129,219 @@ impl MouseWheelDirection { } #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] -pub enum Mouse { - Left, - Middle, - Right, - X1, - X2, - Unknown(u8) +pub enum MouseButton { + Left = ll::SDL_BUTTON_LEFT as isize, + Middle = ll::SDL_BUTTON_MIDDLE as isize, + Right = ll::SDL_BUTTON_RIGHT as isize, + X1 = ll::SDL_BUTTON_X1 as isize, + X2 = ll::SDL_BUTTON_X2 as isize, } -impl Mouse { +impl ToPrimitive for MouseButton { #[inline] - pub fn from_ll(button: u8) -> Mouse { - match button { - 1 => Mouse::Left, - 2 => Mouse::Middle, - 3 => Mouse::Right, - 4 => Mouse::X1, - 5 => Mouse::X2, - _ => Mouse::Unknown(button) - } + fn to_i64(&self) -> Option { + Some(*self as i64) + } + + #[inline] + fn to_u64(&self) -> Option { + Some(*self as u64) + } + + #[inline] + fn to_isize(&self) -> Option { + Some(*self as isize) + } +} + +impl FromPrimitive for MouseButton { + #[inline] + 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 => 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, + }) } #[inline] - pub fn to_ll(&self) -> u8 { - match *self { - Mouse::Left => 1, - Mouse::Middle => 2, - Mouse::Right => 3, - Mouse::X1 => 4, - Mouse::X2 => 5, - Mouse::Unknown(button) => button, - } + pub fn to_ll(&self) -> Option { + Some(*self as u8) } } #[derive(Copy, Clone, Eq, PartialEq, Hash)] pub struct MouseState { - flags: u32 + mouse_state: u32, + x: i32, + y: i32 } impl MouseState { - /// Tests if a mouse button was pressed. - pub fn button(&self, button: Mouse) -> bool { - match button { - Mouse::Left => self.left(), - Mouse::Middle => self.middle(), - Mouse::Right => self.right(), - Mouse::X1 => self.x1(), - Mouse::X2 => self.x2(), - Mouse::Unknown(x) => { - assert!(x <= 32); - let mask = 1 << ((x as u32) - 1); - (self.flags & mask) != 0 - } + pub fn new(_e: &EventPump) -> MouseState { + let mut x = 0; + let mut y = 0; + let mouse_state: u32 = unsafe { + ll::SDL_GetMouseState(&mut x, &mut y) + }; + + MouseState { + mouse_state: mouse_state, + x: x as i32, + y: y as i32 } } - /// Tests if the left mouse button was pressed. - pub fn left(&self) -> bool { (self.flags & ll::SDL_BUTTON_LMASK) != 0 } - - /// Tests if the middle mouse button was pressed. - pub fn middle(&self) -> bool { (self.flags & ll::SDL_BUTTON_MMASK) != 0 } - - /// Tests if the right mouse button was pressed. - pub fn right(&self) -> bool { (self.flags & ll::SDL_BUTTON_RMASK) != 0 } - - /// Tests if the X1 mouse button was pressed. - pub fn x1(&self) -> bool { (self.flags & ll::SDL_BUTTON_X1MASK) != 0 } - - /// Tests if the X2 mouse button was pressed. - pub fn x2(&self) -> bool { (self.flags & ll::SDL_BUTTON_X2MASK) != 0 } - - pub fn from_flags(flags: u32) -> MouseState { - MouseState { flags: flags } + pub fn from_sdl_state(state: u32) -> MouseState { + MouseState { mouse_state : state, x: 0, y: 0 } + } + pub fn to_sdl_state(&self) -> u32 { + self.mouse_state } - pub fn to_flags(&self) -> u32 { - self.flags + /// 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 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_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 { + 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. + /// + /// # Example + /// ```no_run + /// use sdl2::mouse::MouseButton; + /// use std::collections::HashMap; + /// + /// fn mouse_button_set(e: &sdl2::EventPump) -> HashMap { + /// e.mouse_state().mouse_buttons().collect() + /// } + /// + /// fn find_first_pressed(e: &sdl2::EventPump) -> bool { + /// for (key,value) in mouse_button_set(e) { + /// return value != false + /// } + /// false + /// } + /// + /// ``` + pub fn mouse_buttons(&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_mouse_button_set(e: &sdl2::EventPump) -> HashSet { + /// e.mouse_state().pressed_mouse_buttons().collect() + /// } + /// + /// fn newly_pressed(old: &HashSet, new: &HashSet) -> HashSet { + /// new - old + /// // sugar for: new.difference(old).collect() + /// } + /// ``` + pub fn pressed_mouse_buttons(&self) -> PressedMouseButtonIterator { + PressedMouseButtonIterator { + iter: self.mouse_buttons() + } + } +} + +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 +1 { + let index = self.index; + self.index += 1; + + if let Some(mouse_button) = FromPrimitive::from_usize(index) { + let mask = 1 << ((mouse_button as u32)-1); + let pressed = self.mouse_state & mask != 0; + + Some((mouse_button, 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((mouse_button, pressed)) = self.iter.next() { + if pressed { return Some(mouse_button) } + } + None } } @@ -238,24 +378,6 @@ impl MouseUtil { } } - 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); - } - } - - pub fn relative_mouse_state(&self) -> (MouseState, i32, i32) { - let mut x = 0; - 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); - } - } - pub fn warp_mouse_in_window(&self, window: &video::WindowRef, x: i32, y: i32) { unsafe { ll::SDL_WarpMouseInWindow(window.raw(), x, y); } } diff --git a/src/sdl2/mouse/relative.rs b/src/sdl2/mouse/relative.rs new file mode 100644 index 00000000..f73f1865 --- /dev/null +++ b/src/sdl2/mouse/relative.rs @@ -0,0 +1,129 @@ +use EventPump; + +use sys::mouse as ll; + +use super::{MouseButton, MouseButtonIterator, PressedMouseButtonIterator}; + +#[derive(Copy, Clone, Eq, PartialEq, Hash)] +pub struct RelativeMouseState { + mouse_state: u32, + x: i32, + y: i32 +} + +impl RelativeMouseState { + pub fn new(_e: &EventPump) -> RelativeMouseState { + let mut x = 0; + let mut y = 0; + let mouse_state = unsafe { + // This call is the only difference between MouseState + ll::SDL_GetRelativeMouseState(&mut x, &mut y) + }; + + RelativeMouseState { + mouse_state: mouse_state, + x: x as i32, + y: y as i32 + } + } + + pub fn from_sdl_state(state: u32) -> RelativeMouseState { + RelativeMouseState { mouse_state : state, x: 0, y: 0 } + } + 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 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_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 { + 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. + /// + /// # Example + /// ```no_run + /// use sdl2::mouse::MouseButton; + /// use std::collections::HashMap; + /// + /// fn mouse_button_set(e: &sdl2::EventPump) -> HashMap { + /// e.mouse_state().mouse_buttons().collect() + /// } + /// + /// fn find_first_pressed(e: &sdl2::EventPump) -> bool { + /// for (key,value) in mouse_button_set(e) { + /// return value != false + /// } + /// false + /// } + /// + /// ``` + pub fn mouse_buttons(&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_mouse_button_set(e: &sdl2::EventPump) -> HashSet { + /// e.mouse_state().pressed_mouse_buttons().collect() + /// } + /// + /// fn newly_pressed(old: &HashSet, new: &HashSet) -> HashSet { + /// new - old + /// // sugar for: new.difference(old).collect() + /// } + /// ``` + pub fn pressed_mouse_buttons(&self) -> PressedMouseButtonIterator { + PressedMouseButtonIterator { + iter: self.mouse_buttons() + } + } +}