From 3991947a109c568b94458a5b6a8a9f8c300b040b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Wie=C3=9Fner?= Date: Mon, 10 Dec 2018 22:59:35 +0100 Subject: [PATCH 1/7] Add wrapper for `SDL_GameControllerRumble` --- src/sdl2/controller.rs | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/sdl2/controller.rs b/src/sdl2/controller.rs index 9974e8a8..393abe86 100644 --- a/src/sdl2/controller.rs +++ b/src/sdl2/controller.rs @@ -402,6 +402,28 @@ impl GameController { unsafe { sys::SDL_GameControllerGetButton(self.raw, raw_button) != 0 } } + + /// Set the rumble motors to their specified intensities, if supported. + /// Automatically resets back to zero after `duration_ms` milliseconds have passed. + pub fn set_rumble(&mut self, + low_frequency_rumble: u16, + high_frequency_rumble: u16, + duration_ms: u32) + -> Result<(), IntegerOrSdlError> + { + let result = unsafe { + sys::SDL_GameControllerRumble(self.raw, + low_frequency_rumble, + high_frequency_rumble, + duration_ms) + }; + + if result != 0 { + Err(IntegerOrSdlError::SdlError(get_error())) + } else { + Ok(()) + } + } } impl Drop for GameController { From 99659cf7636e0282e7c3d57f9e2b6a66d3818e10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Wie=C3=9Fner?= Date: Mon, 10 Dec 2018 23:01:04 +0100 Subject: [PATCH 2/7] Add wrapper for `SDL_JoystickRumble` --- src/sdl2/joystick.rs | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/sdl2/joystick.rs b/src/sdl2/joystick.rs index bb651ec7..61b2ef8e 100644 --- a/src/sdl2/joystick.rs +++ b/src/sdl2/joystick.rs @@ -21,7 +21,7 @@ impl JoystickSubsystem { } /// Attempt to open the joystick at index `joystick_index` and return it. - pub fn open(&self, joystick_index: u32) + pub fn open(&self, joystick_index: u32) -> Result { use common::IntegerOrSdlError::*; let joystick_index = try!(validate_int(joystick_index, "joystick_index")); @@ -344,6 +344,28 @@ impl Joystick { } } } + + /// Set the rumble motors to their specified intensities, if supported. + /// Automatically resets back to zero after `duration_ms` milliseconds have passed. + pub fn set_rumble(&mut self, + low_frequency_rumble: u16, + high_frequency_rumble: u16, + duration_ms: u32) + -> Result<(), IntegerOrSdlError> + { + let result = unsafe { + sys::SDL_JoystickRumble(self.raw, + low_frequency_rumble, + high_frequency_rumble, + duration_ms) + }; + + if result != 0 { + Err(IntegerOrSdlError::SdlError(get_error())) + } else { + Ok(()) + } + } } impl Drop for Joystick { From 59ad1c094b0a9746e21b6ad69bc7bccce0d32a3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Wie=C3=9Fner?= Date: Mon, 10 Dec 2018 23:02:10 +0100 Subject: [PATCH 3/7] Modify `game-controller` example to include `set_rumble` --- examples/game-controller.rs | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/examples/game-controller.rs b/examples/game-controller.rs index 10cdaacd..517af707 100644 --- a/examples/game-controller.rs +++ b/examples/game-controller.rs @@ -36,7 +36,7 @@ fn main() { } } - let controller = + let mut controller = match controller { Some(c) => c, None => panic!("Couldn't open any controller"), @@ -44,10 +44,29 @@ fn main() { println!("Controller mapping: {}", controller.mapping()); + let (mut lo_freq, mut hi_freq) = (0, 0); + for event in sdl_context.event_pump().unwrap().wait_iter() { use sdl2::event::Event; + use sdl2::controller::Axis; match event { + Event::ControllerAxisMotion{ axis: Axis::TriggerLeft, value: val, .. } => { + // Trigger axes go from 0 to 32767, so this should be okay + lo_freq = (val as u16) * 2; + match controller.set_rumble(lo_freq, hi_freq, 15000) { + Ok(()) => println!("Set rumble to ({}, {})", lo_freq, hi_freq), + Err(e) => println!("Error setting rumble to ({}, {}): {:?}", lo_freq, hi_freq, e), + } + } + Event::ControllerAxisMotion{ axis: Axis::TriggerRight, value: val, .. } => { + // Trigger axes go from 0 to 32767, so this should be okay + hi_freq = (val as u16) * 2; + match controller.set_rumble(lo_freq, hi_freq, 15000) { + Ok(()) => println!("Set rumble to ({}, {})", lo_freq, hi_freq), + Err(e) => println!("Error setting rumble to ({}, {}): {:?}", lo_freq, hi_freq, e), + } + } Event::ControllerAxisMotion{ axis, value: val, .. } => { // Axis motion is an absolute value in the range // [-32768, 32767]. Let's simulate a very rough dead From 5b7d1c108fdedda1c5a7ff7985cf4bc50530b8e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Wie=C3=9Fner?= Date: Mon, 10 Dec 2018 23:02:39 +0100 Subject: [PATCH 4/7] Modify `joystick` example to include `set_rumble` --- examples/joystick.rs | 39 +++++++++++++++++++++++++++++++++------ 1 file changed, 33 insertions(+), 6 deletions(-) diff --git a/examples/joystick.rs b/examples/joystick.rs index 624cb6f4..804a68f5 100644 --- a/examples/joystick.rs +++ b/examples/joystick.rs @@ -28,12 +28,15 @@ fn main() { } // Print the joystick's power level, if a joystick was found. - match joystick { + let mut joystick = match joystick { Some(j) => { println!("\"{}\" power level: {:?}", j.name(), j.power_level().unwrap()); + j }, None => panic!("Couldn't open any joystick"), - } + }; + + let (mut lo_freq, mut hi_freq) = (0, 0); for event in sdl_context.event_pump().unwrap().wait_iter() { use sdl2::event::Event; @@ -48,10 +51,34 @@ fn main() { println!("Axis {} moved to {}", axis_idx, val); } } - Event::JoyButtonDown{ button_idx, .. } => - println!("Button {} down", button_idx), - Event::JoyButtonUp{ button_idx, .. } => - println!("Button {} up", button_idx), + Event::JoyButtonDown{ button_idx, .. } => { + println!("Button {} down", button_idx); + if button_idx == 0 { + lo_freq = 65535; + } else if button_idx == 1 { + hi_freq = 65535; + } + if button_idx < 2 { + match joystick.set_rumble(lo_freq, hi_freq, 15000) { + Ok(()) => println!("Set rumble to ({}, {})", lo_freq, hi_freq), + Err(e) => println!("Error setting rumble to ({}, {}): {:?}", lo_freq, hi_freq, e), + } + } + } + Event::JoyButtonUp{ button_idx, .. } => { + println!("Button {} up", button_idx); + if button_idx == 0 { + lo_freq = 0; + } else if button_idx == 1 { + hi_freq = 0; + } + if button_idx < 2 { + match joystick.set_rumble(lo_freq, hi_freq, 15000) { + Ok(()) => println!("Set rumble to ({}, {})", lo_freq, hi_freq), + Err(e) => println!("Error setting rumble to ({}, {}): {:?}", lo_freq, hi_freq, e), + } + } + } Event::JoyHatMotion{ hat_idx, state, .. } => println!("Hat {} moved to {:?}", hat_idx, state), Event::Quit{..} => break, From 2590b132084bf683773cabf6a166b06c6835668d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Wie=C3=9Fner?= Date: Mon, 10 Dec 2018 23:18:38 +0100 Subject: [PATCH 5/7] Add rumble functions to changelog --- changelog.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/changelog.md b/changelog.md index 05f9315c..5fcab827 100644 --- a/changelog.md +++ b/changelog.md @@ -1,6 +1,11 @@ In this file will be listed the changes, especially the breaking ones that one should be careful of when upgrading from a version of rust-sdl2 to another. +### v0.32.1 (unreleased) + +[PR #824](https://github.com/Rust-SDL2/rust-sdl2/pull/824): +Added `controller::set_rumble` and `joystick::set_rumble`, wrappers for `SDL_GameControllerRumble` and `SDL_JoystickRumble` respectively. + ### v0.32 [PR #790](https://github.com/Rust-SDL2/rust-sdl2/pull/790): Added missing `window_id` field to `Event::DropFile` @@ -41,7 +46,7 @@ Fix `ClipboardUtil::set_clipboard_text` to return an Ok when it went well. Add `video::border_size -> Result<(u16, u16, u16, u16), String>` equivalent of `SDL_GetWindowBorderSize()` [PR #732](https://github.com/Rust-SDL2/rust-sdl2/pull/732): -Implemented `From<(u8, u8, u8)>` and `From<(u8, u8, u8, u8)>` for `pixels::Color`. +Implemented `From<(u8, u8, u8)>` and `From<(u8, u8, u8, u8)>` for `pixels::Color`. `Canvas.set_draw_color` can now be called with tuples or other types which implements `Into` [PR #279](https://github.com/Rust-SDL2/rust-sdl2/pull/729) From a5bf3db4938a3e17f2176e21f8c885165739422f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Wie=C3=9Fner?= Date: Tue, 11 Dec 2018 12:27:55 +0100 Subject: [PATCH 6/7] Update `travis-install-sdl2.sh` to download 2.0.9 tarball --- scripts/travis-install-sdl2.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/travis-install-sdl2.sh b/scripts/travis-install-sdl2.sh index aa80ec3a..76aca1fc 100644 --- a/scripts/travis-install-sdl2.sh +++ b/scripts/travis-install-sdl2.sh @@ -2,7 +2,7 @@ set -xueo pipefail -wget https://www.libsdl.org/release/SDL2-2.0.8.tar.gz -O sdl2.tar.gz +wget https://www.libsdl.org/release/SDL2-2.0.9.tar.gz -O sdl2.tar.gz tar xzf sdl2.tar.gz pushd SDL2-* && ./configure && make && sudo make install && popd wget -q https://www.libsdl.org/projects/SDL_ttf/release/SDL2_ttf-2.0.14.tar.gz From 64a936c9459fdb5e53ff3a38471254060d234f08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Wie=C3=9Fner?= Date: Wed, 12 Dec 2018 02:20:36 +0100 Subject: [PATCH 7/7] Add some notes to `set_rumble`'s docs --- src/sdl2/controller.rs | 9 +++++++++ src/sdl2/joystick.rs | 9 +++++++++ 2 files changed, 18 insertions(+) diff --git a/src/sdl2/controller.rs b/src/sdl2/controller.rs index 393abe86..38b89960 100644 --- a/src/sdl2/controller.rs +++ b/src/sdl2/controller.rs @@ -405,6 +405,15 @@ impl GameController { /// Set the rumble motors to their specified intensities, if supported. /// Automatically resets back to zero after `duration_ms` milliseconds have passed. + /// + /// # Notes + /// + /// The value range for the intensities is 0 to 0xFFFF. + /// + /// Do *not* use `std::u32::MAX` or similar for `duration_ms` if you want + /// the rumble effect to keep playing for a long time, as this results in + /// the effect ending immediately after starting due to an overflow. + /// Use some smaller, "huge enough" number instead. pub fn set_rumble(&mut self, low_frequency_rumble: u16, high_frequency_rumble: u16, diff --git a/src/sdl2/joystick.rs b/src/sdl2/joystick.rs index 61b2ef8e..1c01bb87 100644 --- a/src/sdl2/joystick.rs +++ b/src/sdl2/joystick.rs @@ -347,6 +347,15 @@ impl Joystick { /// Set the rumble motors to their specified intensities, if supported. /// Automatically resets back to zero after `duration_ms` milliseconds have passed. + /// + /// # Notes + /// + /// The value range for the intensities is 0 to 0xFFFF. + /// + /// Do *not* use `std::u32::MAX` or similar for `duration_ms` if you want + /// the rumble effect to keep playing for a long time, as this results in + /// the effect ending immediately after starting due to an overflow. + /// Use some smaller, "huge enough" number instead. pub fn set_rumble(&mut self, low_frequency_rumble: u16, high_frequency_rumble: u16,