-
Notifications
You must be signed in to change notification settings - Fork 914
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Overhaul device events API and add gamepad support on Windows (#804)
* Initial implementation * Corrected RAWINPUT buffer sizing * Mostly complete XInput implementation * XInput triggers * Add preliminary CHANGELOG entry. * match unix common API to evl 2.0 * wayland: eventloop2.0 * make EventLoopProxy require T: 'static * Revamp device event API, as well as several misc. fixes on Windows: * When you have multiple windows, you no longer receive duplicate device events * Mouse Device Events now send X-button input * Mouse Device Events now send horizontal scroll wheel input * Add MouseEvent documentation and Device ID debug passthrough * Improve type safety on get_raw_input_data * Remove button_id field from MouseEvent::Button in favor of �utton * Remove regex dependency on Windows * Remove axis filtering in XInput * Make gamepads not use lazy_static * Publicly expose gamepad rumble * Unstack DeviceEvent and fix examples/tests * Add HANDLE retrieval method to DeviceExtWindows * Add distinction between non-joystick axes and joystick axes. This helps with properly calculating the deadzone for controller joysticks. One potential issue is that the `Stick` variant isn't used for *all* joysticks, which could be potentially confusing - for example, raw input joysticks will never use the `Stick` variant because we don't understand the semantic meaning of raw input joystick axes. * Add ability to get gamepad port * Fix xinput controller hot swapping * Add functions for enumerating attached devices * Clamp input to [0.0, 1.0] on gamepad rumble * Expose gamepad rumble errors * Add method to check if device is still connected * Add docs * Rename AxisHint and ButtonHint to GamepadAxis and GamepadButton * Add CHANGELOG entry * Update CHANGELOG.md * Add HidId and MovedAbsolute * Fix xinput deprecation warnings * Add ability to retrieve gamepad battery level * Fix weird imports in gamepad example * Update CHANGELOG.md * Resolve francesca64 comments
- Loading branch information
Showing
24 changed files
with
2,101 additions
and
475 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
use winit::{ | ||
event::{ | ||
device::{GamepadEvent, GamepadHandle}, | ||
Event, WindowEvent, | ||
}, | ||
event_loop::{ControlFlow, EventLoop}, | ||
window::WindowBuilder, | ||
}; | ||
|
||
fn main() { | ||
let event_loop = EventLoop::new(); | ||
|
||
let _window = WindowBuilder::new() | ||
.with_title("The world's worst video game") | ||
.build(&event_loop) | ||
.unwrap(); | ||
|
||
println!("enumerating gamepads:"); | ||
for gamepad in GamepadHandle::enumerate(&event_loop) { | ||
println!( | ||
" gamepad={:?}\tport={:?}\tbattery level={:?}", | ||
gamepad, | ||
gamepad.port(), | ||
gamepad.battery_level() | ||
); | ||
} | ||
|
||
let deadzone = 0.12; | ||
|
||
event_loop.run(move |event, _, control_flow| { | ||
match event { | ||
Event::GamepadEvent(gamepad_handle, event) => { | ||
match event { | ||
// Discard any Axis events that has a corresponding Stick event. | ||
GamepadEvent::Axis { stick: true, .. } => (), | ||
|
||
// Discard any Stick event that falls inside the stick's deadzone. | ||
GamepadEvent::Stick { | ||
x_value, y_value, .. | ||
} if (x_value.powi(2) + y_value.powi(2)).sqrt() < deadzone => (), | ||
|
||
_ => println!("[{:?}] {:#?}", gamepad_handle, event), | ||
} | ||
}, | ||
Event::WindowEvent { | ||
event: WindowEvent::CloseRequested, | ||
.. | ||
} => *control_flow = ControlFlow::Exit, | ||
_ => (), | ||
} | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
use std::time::Instant; | ||
use winit::event_loop::EventLoop; | ||
|
||
#[derive(Debug, Clone)] | ||
enum Rumble { | ||
None, | ||
Left, | ||
Right, | ||
} | ||
|
||
fn main() { | ||
let event_loop = EventLoop::new(); | ||
|
||
// You should generally use `GamepadEvent::Added/Removed` to detect gamepads, as doing that will | ||
// allow you to more easily support gamepad hotswapping. However, we're using `enumerate` here | ||
// because it makes this example more concise. | ||
let gamepads = winit::event::device::GamepadHandle::enumerate(&event_loop).collect::<Vec<_>>(); | ||
|
||
let rumble_patterns = &[ | ||
(0.5, Rumble::None), | ||
(2.0, Rumble::Left), | ||
(0.5, Rumble::None), | ||
(2.0, Rumble::Right), | ||
]; | ||
let mut rumble_iter = rumble_patterns.iter().cloned().cycle(); | ||
|
||
let mut active_pattern = rumble_iter.next().unwrap(); | ||
let mut timeout = active_pattern.0; | ||
let mut timeout_start = Instant::now(); | ||
|
||
event_loop.run(move |_, _, _| { | ||
if timeout <= active_pattern.0 { | ||
let t = (timeout / active_pattern.0) * std::f64::consts::PI; | ||
let intensity = t.sin(); | ||
|
||
for g in &gamepads { | ||
let result = match active_pattern.1 { | ||
Rumble::Left => g.rumble(intensity, 0.0), | ||
Rumble::Right => g.rumble(0.0, intensity), | ||
Rumble::None => Ok(()), | ||
}; | ||
|
||
if let Err(e) = result { | ||
println!("Rumble failed: {:?}", e); | ||
} | ||
} | ||
|
||
timeout = (Instant::now() - timeout_start).as_millis() as f64 / 1000.0; | ||
} else { | ||
active_pattern = rumble_iter.next().unwrap(); | ||
println!( | ||
"Rumbling {:?} for {:?} seconds", | ||
active_pattern.1, active_pattern.0 | ||
); | ||
|
||
timeout = 0.0; | ||
timeout_start = Instant::now(); | ||
} | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.