diff --git a/examples/haptic.rs b/examples/haptic.rs new file mode 100644 index 00000000..145d9213 --- /dev/null +++ b/examples/haptic.rs @@ -0,0 +1,64 @@ +extern crate sdl2; + +fn main() { + let sdl_context = sdl2::init().unwrap(); + let joystick_subsystem = sdl_context.joystick().unwrap(); + let haptic_subsystem = sdl_context.haptic().unwrap(); + + let available = + match joystick_subsystem.num_joysticks() { + Ok(n) => n, + Err(e) => panic!("can't enumerate joysticks: {}", e), + }; + + println!("{} joysticks available", available); + + let mut joystick = None; + + // Iterate over all available joysticks and stop once we manage to + // open one. + for id in 0..available { + match joystick_subsystem.open(id) { + Ok(c) => { + println!("Success: opened \"{}\"", c.name()); + joystick = Some(c); + break; + }, + Err(e) => println!("failed: {:?}", e), + } + } + + if joystick.is_none() { + panic!("Couldn't open any joystick"); + }; + + let joystick = joystick.unwrap(); + + let mut haptic = haptic_subsystem.open_from_joystick_id(joystick.instance_id()).unwrap(); + + for event in sdl_context.event_pump().unwrap().wait_iter() { + use sdl2::event::Event; + + match event { + Event::JoyAxisMotion{ axis_idx, value: val, .. } => { + // Axis motion is an absolute value in the range + // [-32768, 32767]. Let's simulate a very rough dead + // zone to ignore spurious events. + let dead_zone = 10000; + if val > dead_zone || val < -dead_zone { + println!("Axis {} moved to {}", axis_idx, val); + } + } + Event::JoyButtonDown{ button_idx, .. } =>{ + println!("Button {} down", button_idx); + haptic.rumble_play(0.5, 500); + }, + Event::JoyButtonUp{ button_idx, .. } => + println!("Button {} up", button_idx), + Event::JoyHatMotion{ hat_idx, state, .. } => + println!("Hat {} moved to {:?}", hat_idx, state), + Event::Quit{..} => break, + _ => (), + } + } +} diff --git a/src/sdl2/haptic.rs b/src/sdl2/haptic.rs index e72ed7bd..586479f4 100644 --- a/src/sdl2/haptic.rs +++ b/src/sdl2/haptic.rs @@ -1,3 +1,58 @@ //! Haptic Functions -#[allow(unused)] use sys::haptic as ll; +use sys::joystick as sys_joystick; + +use HapticSubsystem; +use common::IntegerOrSdlError; +use get_error; + +impl HapticSubsystem { + /// Attempt to open the joystick at number `id` and return it. + pub fn open_from_joystick_id(&self, joystick_index: i32) -> Result { + use common::IntegerOrSdlError::*; + + let haptic = unsafe { + let joystick = sys_joystick::SDL_JoystickOpen(joystick_index); + ll::SDL_HapticOpenFromJoystick(joystick) + }; + + if haptic.is_null() { + Err(SdlError(get_error())) + } else { + unsafe { ll::SDL_HapticRumbleInit(haptic) }; + Ok(Haptic { + subsystem: self.clone(), + raw: haptic, + }) + } + } +} + +/// Wrapper around the SDL_Haptic object +pub struct Haptic { + subsystem: HapticSubsystem, + raw: *mut ll::SDL_Haptic, +} + + +impl Haptic { + #[inline] + pub fn subsystem(&self) -> &HapticSubsystem { &self.subsystem } + + /// Run a simple rumble effect on the haptic device. + pub fn rumble_play(&mut self, strength: f32, duration: u32) { + unsafe { ll::SDL_HapticRumblePlay(self.raw, strength, duration) }; + } + + /// Stop the simple rumble on the haptic device. + pub fn rumble_stop(&mut self) { + unsafe { ll::SDL_HapticRumbleStop(self.raw) }; + } +} + + +impl Drop for Haptic { + fn drop(&mut self) { + unsafe { ll::SDL_HapticClose(self.raw) } + } +}