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 56437b6d..bdddab2c 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 f53f0c57..7d141330 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 e42a53e0..4c6cfc99 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] + 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) -> 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, } 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 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); } } 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 8164784c..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::{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 fdb2262d..00000000 --- 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 00000000..de01e6c1 --- /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 00000000..74b394aa --- /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 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. 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 8f521f88..fcc32f49 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));