From 0c8692c9784176793f859351a4c57173821e42ef Mon Sep 17 00:00:00 2001 From: Luke Jones Date: Fri, 18 Nov 2016 19:44:04 +1300 Subject: [PATCH 1/7] Initial rework of mouse --- sdl2-sys/src/mouse.rs | 25 ++++----- src/sdl2/event.rs | 35 ++++++++----- src/sdl2/mouse.rs | 116 ++++++++++++++++++++---------------------- 3 files changed, 89 insertions(+), 87 deletions(-) diff --git a/sdl2-sys/src/mouse.rs b/sdl2-sys/src/mouse.rs index 56437b6d867..bdddab2ccdd 100644 --- a/sdl2-sys/src/mouse.rs +++ b/sdl2-sys/src/mouse.rs @@ -21,18 +21,19 @@ 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; - - -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; +// #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; +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 f53f0c57f21..7d141330f6d 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::{Mousecode, 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,10 @@ fn mk_keysym(scancode: Option, } } +fn mk_mousesym(mousecode: Option) -> u8 { + mousecode.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 +874,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 +900,7 @@ impl Event { x, y } => { - let button = mouse_btn.to_ll(); + let button = mk_mousesym(mouse_btn); let event = ll::SDL_MouseButtonEvent { type_: ll::SDL_MOUSEBUTTONDOWN, timestamp: timestamp, @@ -922,7 +926,7 @@ impl Event { x, y } => { - let button = mouse_btn.to_ll(); + let button = mk_mousesym(mouse_btn); let event = ll::SDL_MouseButtonEvent { type_: ll::SDL_MOUSEBUTTONUP, timestamp: timestamp, @@ -1355,7 +1359,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 +1373,7 @@ impl Event { timestamp: event.timestamp, window_id: event.windowID, which: event.which, - mouse_btn: mouse::Mouse::from_ll(event.button), + mouse_btn: mouse::Mousecode::from_ll(event.button), x: event.x, y: event.y } @@ -1381,7 +1385,7 @@ impl Event { timestamp: event.timestamp, window_id: event.windowID, which: event.which, - mouse_btn: mouse::Mouse::from_ll(event.button), + mouse_btn: mouse::Mousecode::from_ll(event.button), x: event.x, y: event.y } @@ -1784,6 +1788,11 @@ 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) + } } /// An iterator that calls `EventPump::poll_event()`. @@ -1880,7 +1889,7 @@ mod test { timestamp: 0, window_id: 0, which: 1, - mousestate: MouseState::from_flags(1), + mousestate: MouseState::from_state(1), x: 3, y: 91, xrel: -1, diff --git a/src/sdl2/mouse.rs b/src/sdl2/mouse.rs index e42a53e005d..4c6cfc99c0b 100644 --- a/src/sdl2/mouse.rs +++ b/src/sdl2/mouse.rs @@ -1,8 +1,11 @@ +use num::{ToPrimitive, FromPrimitive}; use std::ptr; use get_error; use surface::SurfaceRef; use video; +// +use EventPump; use sys::mouse as ll; @@ -124,84 +127,73 @@ impl MouseWheelDirection { } #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] -pub enum Mouse { - Left, - Middle, - Right, - X1, - X2, - Unknown(u8) +pub enum Mousecode { + 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 Mousecode { #[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] - 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, - } + fn to_u64(&self) -> Option { + Some(*self as u64) + } + + #[inline] + fn to_isize(&self) -> Option { + Some(*self as isize) + } +} + +impl Mousecode { + #[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, + _ => return None, + }) + } + #[inline] + pub fn to_ll(&self) -> Option { + Some(*self as u8) } } #[derive(Copy, Clone, Eq, PartialEq, Hash)] pub struct MouseState { - flags: u32 + mouse_state: u32, } 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 mouse_state: u32 = unsafe { + let mut x = 0; + let mut y = 0; + ll::SDL_GetMouseState(&mut x, &mut y) + }; + + MouseState { + mouse_state: mouse_state } } - /// 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 } } - - pub fn to_flags(&self) -> u32 { - self.flags + pub fn to_sdl_state(&self) -> u32 { + self.mouse_state } } @@ -237,7 +229,7 @@ impl MouseUtil { Some(id) } } - +/* pub fn mouse_state(&self) -> (MouseState, i32, i32) { let mut x = 0; let mut y = 0; @@ -255,7 +247,7 @@ impl MouseUtil { 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); } } From c696bc5a85d6de9dc2b746b35a996f6045722959 Mon Sep 17 00:00:00 2001 From: Luke Jones Date: Fri, 18 Nov 2016 20:22:22 +1300 Subject: [PATCH 2/7] Hopeful finished implementation of EventPump mouse_state() - implemented tests using keyboard_state() as a template - renamed some functions and structs in the process to better reflect their use - `EventPump` should now return a `MouseState` via `fn mouse_state(&self) -> MouseState`. New functions added. - `fn is_mousebutton_pressed(&self, mousebutton: Mousebutton) -> bool` - `fn mousebuttons(&self) -> MousebuttonIterator` - `fn pressed_mousebuttons(&self) -> PressedMousebuttonIterator` - Implemented `ToPrimitive` and `FromPrimitive` for struct `Mousebutton` --- sdl2-sys/src/mouse.rs | 3 +- src/sdl2/event.rs | 23 +++---- src/sdl2/mouse.rs | 141 ++++++++++++++++++++++++++++++++++++++---- 3 files changed, 141 insertions(+), 26 deletions(-) diff --git a/sdl2-sys/src/mouse.rs b/sdl2-sys/src/mouse.rs index bdddab2ccdd..894eda4b1b2 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 7d141330f6d..8164784c7fa 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 4c6cfc99c0b..fdb2262daba 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); } } From 2295e440e04e25af218cdbac242524302824c3b4 Mon Sep 17 00:00:00 2001 From: Luke Jones Date: Sat, 19 Nov 2016 08:18:43 +1300 Subject: [PATCH 3/7] Further changes: - `MouseState` now contains the x,y coordinates - removal of `mousestate()` from `MouseUtil`, `MouseState` contains x,y by default now - `RelativeMouseState` is a new struct and function set which is exactly the same as `MouseState`, except if calls (raw sdl)`SDL_GetRelativeMouseState` on construction - removal of `relative_mouse_state()` from `MouseUtil`, see above. - move mouse functionality in to `/sdl2/mouse/`, split `RelativeMouseState` in to own file; the main reason for this is to make tests easier to write/work with - add additional tests for button iterators - add `EventPump::relative_mouse_state()` to complement `mouse_state()` --- src/sdl2/event.rs | 31 ++-- src/sdl2/mouse.rs | 385 ---------------------------------------------- 2 files changed, 18 insertions(+), 398 deletions(-) delete mode 100644 src/sdl2/mouse.rs diff --git a/src/sdl2/event.rs b/src/sdl2/event.rs index 8164784c7fa..82b31b3e31a 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::{Mousebutton, 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,9 +755,9 @@ fn mk_keysym(scancode: Option, } } -/// Helper function is only to unwrap a mousebutton to u8 -fn mk_mousesym(mousebutton: Option) -> u8 { - mousebutton.unwrap().to_ll().unwrap() +/// 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 @@ -901,7 +901,7 @@ impl Event { x, y } => { - let button = mk_mousesym(mouse_btn); + let button = mk_mouse_button(mouse_btn); let event = ll::SDL_MouseButtonEvent { type_: ll::SDL_MOUSEBUTTONDOWN, timestamp: timestamp, @@ -927,7 +927,7 @@ impl Event { x, y } => { - let button = mk_mousesym(mouse_btn); + let button = mk_mouse_button(mouse_btn); let event = ll::SDL_MouseButtonEvent { type_: ll::SDL_MOUSEBUTTONUP, timestamp: timestamp, @@ -1374,7 +1374,7 @@ impl Event { timestamp: event.timestamp, window_id: event.windowID, which: event.which, - mouse_btn: mouse::Mousebutton::from_ll(event.button), + mouse_btn: mouse::MouseButton::from_ll(event.button), x: event.x, y: event.y } @@ -1386,7 +1386,7 @@ impl Event { timestamp: event.timestamp, window_id: event.windowID, which: event.which, - mouse_btn: mouse::Mousebutton::from_ll(event.button), + mouse_btn: mouse::MouseButton::from_ll(event.button), x: event.x, y: event.y } @@ -1794,6 +1794,11 @@ impl ::EventPump { 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()`. @@ -1837,7 +1842,7 @@ mod test { use super::WindowEventId; use super::super::controller::{Button, Axis}; use super::super::joystick::{HatState}; - use super::super::mouse::{Mousebutton, 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 @@ -1904,7 +1909,7 @@ mod test { timestamp: 5634, window_id: 2, which: 0, - mouse_btn: Some(Mousebutton::Left), + mouse_btn: Some(MouseButton::Left), x: 543, y: 345, }; @@ -1916,7 +1921,7 @@ mod test { timestamp: 0, window_id: 2, which: 0, - mouse_btn: Some(Mousebutton::Left), + mouse_btn: Some(MouseButton::Left), x: 543, y: 345, diff --git a/src/sdl2/mouse.rs b/src/sdl2/mouse.rs deleted file mode 100644 index fdb2262daba..00000000000 --- a/src/sdl2/mouse.rs +++ /dev/null @@ -1,385 +0,0 @@ -use num::{ToPrimitive, FromPrimitive}; -use std::ptr; - -use get_error; -use surface::SurfaceRef; -use video; -// -use EventPump; - -use sys::mouse as ll; - -#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] -#[repr(u32)] -pub enum SystemCursor { - Arrow = ll::SDL_SYSTEM_CURSOR_ARROW, - IBeam = ll::SDL_SYSTEM_CURSOR_IBEAM, - Wait = ll::SDL_SYSTEM_CURSOR_WAIT, - Crosshair = ll::SDL_SYSTEM_CURSOR_CROSSHAIR, - WaitArrow = ll::SDL_SYSTEM_CURSOR_WAITARROW, - SizeNWSE = ll::SDL_SYSTEM_CURSOR_SIZENWSE, - SizeNESW = ll::SDL_SYSTEM_CURSOR_SIZENESW, - SizeWE = ll::SDL_SYSTEM_CURSOR_SIZEWE, - SizeNS = ll::SDL_SYSTEM_CURSOR_SIZENS, - SizeAll = ll::SDL_SYSTEM_CURSOR_SIZEALL, - No = ll::SDL_SYSTEM_CURSOR_NO, - Hand = ll::SDL_SYSTEM_CURSOR_HAND, -} - -pub struct Cursor { - raw: *mut ll::SDL_Cursor -} - -impl Drop for Cursor { - #[inline] - fn drop(&mut self) { - unsafe { ll::SDL_FreeCursor(self.raw) }; - } -} - -impl Cursor { - pub fn new(data: &[u8], mask: &[u8], width: i32, height: i32, hot_x: i32, hot_y: i32) -> Result { - unsafe { - let raw = ll::SDL_CreateCursor(data.as_ptr(), - mask.as_ptr(), - width as i32, height as i32, - hot_x as i32, hot_y as i32); - - if raw == ptr::null_mut() { - Err(get_error()) - } else { - Ok(Cursor{ raw: raw }) - } - } - } - - // TODO: figure out how to pass Surface in here correctly - pub fn from_surface>(surface: S, hot_x: i32, hot_y: i32) -> Result { - unsafe { - let raw = ll::SDL_CreateColorCursor(surface.as_ref().raw(), hot_x, hot_y); - - if raw == ptr::null_mut() { - Err(get_error()) - } else { - Ok(Cursor{ raw: raw }) - } - } - } - - pub fn from_system(cursor: SystemCursor) -> Result { - unsafe { - let raw = ll::SDL_CreateSystemCursor(cursor as u32); - - if raw == ptr::null_mut() { - Err(get_error()) - } else { - Ok(Cursor{ raw: raw }) - } - } - } - - pub fn set(&self) { - unsafe { ll::SDL_SetCursor(self.raw); } - } -} - -#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] -pub enum MouseWheelDirection { - Normal, - Flipped, - Unknown(u32), -} - -// 0 and 1 are not fixed values in the SDL source code. This value is defined as an enum which is then cast to a Uint32. -// The enum in C is defined as such: - -/** - * \brief Scroll direction types for the Scroll event - */ -//typedef enum -//{ -// SDL_MOUSEWHEEL_NORMAL, /**< The scroll direction is normal */ -// SDL_MOUSEWHEEL_FLIPPED /**< The scroll direction is flipped / natural */ -//} SDL_MouseWheelDirection; - -// Since no value is given in the enum definition these values are auto assigned by the C compiler starting at 0. -// Normally I would prefer to use the enum rather than hard code what it is implied to represent however -// the mouse wheel direction value could be described equally as well by a bool, so I don't think changes -// to this enum in the C source code are going to be a problem. - -impl MouseWheelDirection { - #[inline] - pub fn from_ll(direction: u32) -> MouseWheelDirection { - match direction { - 0 => MouseWheelDirection::Normal, - 1 => MouseWheelDirection::Flipped, - _ => MouseWheelDirection::Unknown(direction), - } - } - #[inline] - pub fn to_ll(&self) -> u32 { - match *self { - MouseWheelDirection::Normal => 0, - MouseWheelDirection::Flipped => 1, - MouseWheelDirection::Unknown(direction) => direction, - } - } -} - -#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] -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 ToPrimitive for Mousebutton { - #[inline] - 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) -> Option { - Some(*self as u8) - } - -} - -#[derive(Copy, Clone, Eq, PartialEq, Hash)] -pub struct MouseState { - mouse_state: u32, -} - -impl MouseState { - pub fn new(_e: &EventPump) -> MouseState { - let mouse_state: u32 = unsafe { - let mut x = 0; - let mut y = 0; - ll::SDL_GetMouseState(&mut x, &mut y) - }; - - MouseState { - mouse_state: mouse_state - } - } - - pub fn from_sdl_state(state: u32) -> MouseState { - MouseState { mouse_state : state } - } - 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 { - #[inline] - pub fn mouse(&self) -> MouseUtil { - MouseUtil { - _sdldrop: self.sdldrop() - } - } -} - -/// Mouse utility functions. Access with `Sdl::mouse()`. -/// -/// ```no_run -/// let sdl_context = sdl2::init().unwrap(); -/// -/// // Hide the cursor -/// sdl_context.mouse().show_cursor(false); -/// ``` -pub struct MouseUtil { - _sdldrop: ::std::rc::Rc<::SdlDrop> -} - -impl MouseUtil { - /// Gets the id of the window which currently has mouse focus. - pub fn focused_window_id(&self) -> Option { - let raw = unsafe { ll::SDL_GetMouseFocus() }; - if raw == ptr::null_mut() { - None - } else { - let id = unsafe { ::sys::video::SDL_GetWindowID(raw) }; - 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_sdl_state(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_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); } - } - - pub fn set_relative_mouse_mode(&self, on: bool) { - unsafe { ll::SDL_SetRelativeMouseMode(on as i32); } - } - - pub fn relative_mouse_mode(&self) -> bool { - unsafe { ll::SDL_GetRelativeMouseMode() == 1 } - } - - pub fn is_cursor_showing(&self) -> bool { - unsafe { ll::SDL_ShowCursor(::sys::SDL_QUERY) == 1 } - } - - pub fn show_cursor(&self, show: bool) { - unsafe { ll::SDL_ShowCursor(show as i32); } - } -} From 6ee98e1a9c0d6bddc4f32874bc24e4d68fa5256b Mon Sep 17 00:00:00 2001 From: Luke Jones Date: Sat, 19 Nov 2016 09:28:22 +1300 Subject: [PATCH 4/7] Forgot to actually include the file changes in the commit --- src/sdl2/mouse/mod.rs | 392 +++++++++++++++++++++++++++++++++++++ src/sdl2/mouse/relative.rs | 122 ++++++++++++ 2 files changed, 514 insertions(+) create mode 100644 src/sdl2/mouse/mod.rs create mode 100644 src/sdl2/mouse/relative.rs diff --git a/src/sdl2/mouse/mod.rs b/src/sdl2/mouse/mod.rs new file mode 100644 index 00000000000..de01e6c189b --- /dev/null +++ b/src/sdl2/mouse/mod.rs @@ -0,0 +1,392 @@ +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 { + Arrow = ll::SDL_SYSTEM_CURSOR_ARROW, + IBeam = ll::SDL_SYSTEM_CURSOR_IBEAM, + Wait = ll::SDL_SYSTEM_CURSOR_WAIT, + Crosshair = ll::SDL_SYSTEM_CURSOR_CROSSHAIR, + WaitArrow = ll::SDL_SYSTEM_CURSOR_WAITARROW, + SizeNWSE = ll::SDL_SYSTEM_CURSOR_SIZENWSE, + SizeNESW = ll::SDL_SYSTEM_CURSOR_SIZENESW, + SizeWE = ll::SDL_SYSTEM_CURSOR_SIZEWE, + SizeNS = ll::SDL_SYSTEM_CURSOR_SIZENS, + SizeAll = ll::SDL_SYSTEM_CURSOR_SIZEALL, + No = ll::SDL_SYSTEM_CURSOR_NO, + Hand = ll::SDL_SYSTEM_CURSOR_HAND, +} + +pub struct Cursor { + raw: *mut ll::SDL_Cursor +} + +impl Drop for Cursor { + #[inline] + fn drop(&mut self) { + unsafe { ll::SDL_FreeCursor(self.raw) }; + } +} + +impl Cursor { + pub fn new(data: &[u8], mask: &[u8], width: i32, height: i32, hot_x: i32, hot_y: i32) -> Result { + unsafe { + let raw = ll::SDL_CreateCursor(data.as_ptr(), + mask.as_ptr(), + width as i32, height as i32, + hot_x as i32, hot_y as i32); + + if raw == ptr::null_mut() { + Err(get_error()) + } else { + Ok(Cursor{ raw: raw }) + } + } + } + + // TODO: figure out how to pass Surface in here correctly + pub fn from_surface>(surface: S, hot_x: i32, hot_y: i32) -> Result { + unsafe { + let raw = ll::SDL_CreateColorCursor(surface.as_ref().raw(), hot_x, hot_y); + + if raw == ptr::null_mut() { + Err(get_error()) + } else { + Ok(Cursor{ raw: raw }) + } + } + } + + pub fn from_system(cursor: SystemCursor) -> Result { + unsafe { + let raw = ll::SDL_CreateSystemCursor(cursor as u32); + + if raw == ptr::null_mut() { + Err(get_error()) + } else { + Ok(Cursor{ raw: raw }) + } + } + } + + pub fn set(&self) { + unsafe { ll::SDL_SetCursor(self.raw); } + } +} + +#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] +pub enum MouseWheelDirection { + Normal, + Flipped, + Unknown(u32), +} + +// 0 and 1 are not fixed values in the SDL source code. This value is defined as an enum which is then cast to a Uint32. +// The enum in C is defined as such: + +/** + * \brief Scroll direction types for the Scroll event + */ +//typedef enum +//{ +// SDL_MOUSEWHEEL_NORMAL, /**< The scroll direction is normal */ +// SDL_MOUSEWHEEL_FLIPPED /**< The scroll direction is flipped / natural */ +//} SDL_MouseWheelDirection; + +// Since no value is given in the enum definition these values are auto assigned by the C compiler starting at 0. +// Normally I would prefer to use the enum rather than hard code what it is implied to represent however +// the mouse wheel direction value could be described equally as well by a bool, so I don't think changes +// to this enum in the C source code are going to be a problem. + +impl MouseWheelDirection { + #[inline] + pub fn from_ll(direction: u32) -> MouseWheelDirection { + match direction { + 0 => MouseWheelDirection::Normal, + 1 => MouseWheelDirection::Flipped, + _ => MouseWheelDirection::Unknown(direction), + } + } + #[inline] + pub fn to_ll(&self) -> u32 { + match *self { + MouseWheelDirection::Normal => 0, + MouseWheelDirection::Flipped => 1, + MouseWheelDirection::Unknown(direction) => direction, + } + } +} + +#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] +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 ToPrimitive for MouseButton { + #[inline] + 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) -> Option { + Some(*self as u8) + } + +} + +#[derive(Copy, Clone, Eq, PartialEq, Hash)] +pub struct MouseState { + mouse_state: u32, + x: u32, + y: u32 +} + +impl MouseState { + pub fn new(_e: &EventPump) -> MouseState { + let mut x = 0; + let mut y = 0; + let mouse_state = unsafe { + ll::SDL_GetMouseState(&mut x, &mut y) + }; + + MouseState { + mouse_state: mouse_state, + x: x as u32, + y: y as u32 + } + } + + 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 + } + + /// 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_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 + } + + /// 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 { + 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; + + 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 + } +} + +impl ::Sdl { + #[inline] + pub fn mouse(&self) -> MouseUtil { + MouseUtil { + _sdldrop: self.sdldrop() + } + } +} + +/// Mouse utility functions. Access with `Sdl::mouse()`. +/// +/// ```no_run +/// let sdl_context = sdl2::init().unwrap(); +/// +/// // Hide the cursor +/// sdl_context.mouse().show_cursor(false); +/// ``` +pub struct MouseUtil { + _sdldrop: ::std::rc::Rc<::SdlDrop> +} + +impl MouseUtil { + /// Gets the id of the window which currently has mouse focus. + pub fn focused_window_id(&self) -> Option { + let raw = unsafe { ll::SDL_GetMouseFocus() }; + if raw == ptr::null_mut() { + None + } else { + let id = unsafe { ::sys::video::SDL_GetWindowID(raw) }; + Some(id) + } + } + + pub fn warp_mouse_in_window(&self, window: &video::WindowRef, x: i32, y: i32) { + unsafe { ll::SDL_WarpMouseInWindow(window.raw(), x, y); } + } + + pub fn set_relative_mouse_mode(&self, on: bool) { + unsafe { ll::SDL_SetRelativeMouseMode(on as i32); } + } + + pub fn relative_mouse_mode(&self) -> bool { + unsafe { ll::SDL_GetRelativeMouseMode() == 1 } + } + + pub fn is_cursor_showing(&self) -> bool { + unsafe { ll::SDL_ShowCursor(::sys::SDL_QUERY) == 1 } + } + + pub fn show_cursor(&self, show: bool) { + unsafe { ll::SDL_ShowCursor(show as i32); } + } +} diff --git a/src/sdl2/mouse/relative.rs b/src/sdl2/mouse/relative.rs new file mode 100644 index 00000000000..74b394aae64 --- /dev/null +++ b/src/sdl2/mouse/relative.rs @@ -0,0 +1,122 @@ +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: u32, + y: u32 +} + +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 u32, + y: y as u32 + } + } + + 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 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_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 + } + + /// 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() + } + } +} From e4812cea7e9dc81d725cd1429b999ca68647d417 Mon Sep 17 00:00:00 2001 From: Luke Jones Date: Sat, 19 Nov 2016 11:39:46 +1300 Subject: [PATCH 5/7] - correct the mouse button iterator, it now works correctly - correct `is_mouse_button_pressed()`, now uses mask correctly - add examples for `mouse_state()` and `relative_mouse_state()` --- examples/mouse-state.rs | 47 ++++++++++++++++++++++++++++++++ examples/relative-mouse-state.rs | 39 ++++++++++++++++++++++++++ src/sdl2/mouse/mod.rs | 26 ++++++++++++------ src/sdl2/mouse/relative.rs | 19 +++++++++---- 4 files changed, 116 insertions(+), 15 deletions(-) create mode 100644 examples/mouse-state.rs create mode 100644 examples/relative-mouse-state.rs diff --git a/examples/mouse-state.rs b/examples/mouse-state.rs new file mode 100644 index 00000000000..0827c7b21e3 --- /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 00000000000..ca4e351f0e8 --- /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 de01e6c189b..588907bd3b4 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 74b394aae64..f73f1865eb6 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. From 0e6dd1e6afcc8fca3133de78592f3672ed60beeb Mon Sep 17 00:00:00 2001 From: Luke Jones Date: Sat, 19 Nov 2016 14:54:02 +1300 Subject: [PATCH 6/7] Add animation example --- assets/animate.bmp | Bin 0 -> 188984 bytes examples/animation.rs | 58 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 assets/animate.bmp create mode 100644 examples/animation.rs diff --git a/assets/animate.bmp b/assets/animate.bmp new file mode 100644 index 0000000000000000000000000000000000000000..2b6f65d0db830c58069499d8d0a1a27706eafb62 GIT binary patch literal 188984 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 { + running = false; + }, + _ => {} + } + } + + let ticks = timer.ticks(); + + // Cycle through coords + // 0 + // 128 + // 384 + // 512 + // 640 + // source_rect.set_x((128 * ((ticks / 100) % 6) ) as i32); + renderer.clear(); + renderer.copy_ex(&texture, Some(source_rect), Some(dest_rect), 0.0, None, true, false); + renderer.present(); + + std::thread::sleep(Duration::from_millis(100)); + } +} From ed1ced7cbe480b4ba7c5f8619acfa94664596539 Mon Sep 17 00:00:00 2001 From: Luke Jones Date: Sun, 20 Nov 2016 17:59:51 +1300 Subject: [PATCH 7/7] Update animation example. - There is a problem with the SDL2 libraries software renderer such that `RenderCopyEx` will draw a flipped or rotated rect in the wrong place if; - the position of both source and destination are 0, or; - the dimensions of source and destination are the same. - a workaround if using the software renderer is to make the destination 1 pixel larger x,y, or shift the source over 1 pixel. Not ideal. Issue #492 contains more details. --- examples/animation.rs | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/examples/animation.rs b/examples/animation.rs index 8f521f88e4a..fcc32f490b9 100644 --- a/examples/animation.rs +++ b/examples/animation.rs @@ -4,6 +4,7 @@ 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() { @@ -14,7 +15,7 @@ fn main() { .position_centered().build().unwrap(); let mut renderer = window.renderer() - .software().build().unwrap(); + .accelerated().build().unwrap(); renderer.set_draw_color(sdl2::pixels::Color::RGBA(0,0,0,255)); @@ -23,11 +24,13 @@ fn main() { 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 = 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 dest_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 { @@ -42,15 +45,9 @@ fn main() { let ticks = timer.ticks(); - // Cycle through coords - // 0 - // 128 - // 384 - // 512 - // 640 - // source_rect.set_x((128 * ((ticks / 100) % 6) ) as i32); + source_rect.set_x((128 * ((ticks / 100) % 6) ) as i32); renderer.clear(); - renderer.copy_ex(&texture, Some(source_rect), Some(dest_rect), 0.0, None, true, false); + renderer.copy_ex(&texture, Some(source_rect), Some(dest_rect), 10.0, None, true, false); renderer.present(); std::thread::sleep(Duration::from_millis(100));