
# Objective Addressing a suggestion I made in Discord: store gamepad name as a `Name` component. Advantages: - Will be nicely displayed in inspector / editor. - Easier to spawn in tests, just `world.spawn(Gamepad::default())`. ## Solution `Gamepad` component now stores only vendor and product IDs and `Name` stores the gamepad name. Since `GamepadInfo` is no longer necessary, I removed it and merged its fields into the connection event. ## Testing - Run unit tests. --- ## Migration Guide - `GamepadInfo` no longer exists: - Name now accesible via `Name` component. - Other information available on `Gamepad` component directly. - `GamepadConnection::Connected` now stores all info fields directly.
116 lines
4.5 KiB
Rust
116 lines
4.5 KiB
Rust
use crate::{
|
|
converter::{convert_axis, convert_button},
|
|
Gilrs, GilrsGamepads,
|
|
};
|
|
use bevy_ecs::event::EventWriter;
|
|
use bevy_ecs::prelude::Commands;
|
|
#[cfg(target_arch = "wasm32")]
|
|
use bevy_ecs::system::NonSendMut;
|
|
use bevy_ecs::system::ResMut;
|
|
use bevy_input::gamepad::{
|
|
GamepadConnection, GamepadConnectionEvent, RawGamepadAxisChangedEvent,
|
|
RawGamepadButtonChangedEvent, RawGamepadEvent,
|
|
};
|
|
use gilrs::{ev::filter::axis_dpad_to_button, EventType, Filter};
|
|
|
|
pub fn gilrs_event_startup_system(
|
|
mut commands: Commands,
|
|
#[cfg(target_arch = "wasm32")] mut gilrs: NonSendMut<Gilrs>,
|
|
#[cfg(not(target_arch = "wasm32"))] mut gilrs: ResMut<Gilrs>,
|
|
mut gamepads: ResMut<GilrsGamepads>,
|
|
mut events: EventWriter<GamepadConnectionEvent>,
|
|
) {
|
|
for (id, gamepad) in gilrs.0.get().gamepads() {
|
|
// Create entity and add to mapping
|
|
let entity = commands.spawn_empty().id();
|
|
gamepads.id_to_entity.insert(id, entity);
|
|
gamepads.entity_to_id.insert(entity, id);
|
|
|
|
events.send(GamepadConnectionEvent {
|
|
gamepad: entity,
|
|
connection: GamepadConnection::Connected {
|
|
name: gamepad.name().to_string(),
|
|
vendor_id: gamepad.vendor_id(),
|
|
product_id: gamepad.product_id(),
|
|
},
|
|
});
|
|
}
|
|
}
|
|
|
|
pub fn gilrs_event_system(
|
|
mut commands: Commands,
|
|
#[cfg(target_arch = "wasm32")] mut gilrs: NonSendMut<Gilrs>,
|
|
#[cfg(not(target_arch = "wasm32"))] mut gilrs: ResMut<Gilrs>,
|
|
mut gamepads: ResMut<GilrsGamepads>,
|
|
mut events: EventWriter<RawGamepadEvent>,
|
|
mut connection_events: EventWriter<GamepadConnectionEvent>,
|
|
mut button_events: EventWriter<RawGamepadButtonChangedEvent>,
|
|
mut axis_event: EventWriter<RawGamepadAxisChangedEvent>,
|
|
) {
|
|
let gilrs = gilrs.0.get();
|
|
while let Some(gilrs_event) = gilrs.next_event().filter_ev(&axis_dpad_to_button, gilrs) {
|
|
gilrs.update(&gilrs_event);
|
|
match gilrs_event.event {
|
|
EventType::Connected => {
|
|
let pad = gilrs.gamepad(gilrs_event.id);
|
|
let entity = gamepads.get_entity(gilrs_event.id).unwrap_or_else(|| {
|
|
let entity = commands.spawn_empty().id();
|
|
gamepads.id_to_entity.insert(gilrs_event.id, entity);
|
|
gamepads.entity_to_id.insert(entity, gilrs_event.id);
|
|
entity
|
|
});
|
|
|
|
let event = GamepadConnectionEvent::new(
|
|
entity,
|
|
GamepadConnection::Connected {
|
|
name: pad.name().to_string(),
|
|
vendor_id: pad.vendor_id(),
|
|
product_id: pad.product_id(),
|
|
},
|
|
);
|
|
|
|
events.send(event.clone().into());
|
|
connection_events.send(event);
|
|
}
|
|
EventType::Disconnected => {
|
|
let gamepad = gamepads
|
|
.id_to_entity
|
|
.get(&gilrs_event.id)
|
|
.copied()
|
|
.expect("mapping should exist from connection");
|
|
let event = GamepadConnectionEvent::new(gamepad, GamepadConnection::Disconnected);
|
|
events.send(event.clone().into());
|
|
connection_events.send(event);
|
|
}
|
|
EventType::ButtonChanged(gilrs_button, raw_value, _) => {
|
|
let Some(button) = convert_button(gilrs_button) else {
|
|
continue;
|
|
};
|
|
let gamepad = gamepads
|
|
.id_to_entity
|
|
.get(&gilrs_event.id)
|
|
.copied()
|
|
.expect("mapping should exist from connection");
|
|
events.send(RawGamepadButtonChangedEvent::new(gamepad, button, raw_value).into());
|
|
button_events.send(RawGamepadButtonChangedEvent::new(
|
|
gamepad, button, raw_value,
|
|
));
|
|
}
|
|
EventType::AxisChanged(gilrs_axis, raw_value, _) => {
|
|
let Some(axis) = convert_axis(gilrs_axis) else {
|
|
continue;
|
|
};
|
|
let gamepad = gamepads
|
|
.id_to_entity
|
|
.get(&gilrs_event.id)
|
|
.copied()
|
|
.expect("mapping should exist from connection");
|
|
events.send(RawGamepadAxisChangedEvent::new(gamepad, axis, raw_value).into());
|
|
axis_event.send(RawGamepadAxisChangedEvent::new(gamepad, axis, raw_value));
|
|
}
|
|
_ => (),
|
|
};
|
|
}
|
|
gilrs.inc();
|
|
}
|