use std::collections::HashMap;
use crate::binding::DeviceState;
use crate::{Device, InputEvent};
#[cfg(feature = "hid")]
use crate::backends::hid::probe_devices;
pub struct DeviceManager {
devices: Vec<Box<dyn Device>>,
snapshot_cache: HashMap<String, DeviceState>,
}
impl DeviceManager {
pub fn new() -> Self {
let mut devices = Vec::new();
#[cfg(feature = "hid")]
{
match hidapi::HidApi::new() {
Ok(api) => {
let hid_devices = probe_devices(&api);
println!("Discovered {} HID device(s)", hid_devices.len());
devices.extend(hid_devices);
}
Err(e) => {
eprintln!("Failed to initialize HID API: {e}");
}
}
}
#[cfg(feature = "virtual")]
{
let virtual_devices = crate::backends::virtual_input::create_virtual_devices();
println!("Loaded {} virtual device(s)", virtual_devices.len());
devices.extend(virtual_devices);
}
Self {
devices,
snapshot_cache: HashMap::new(),
}
}
pub fn add_device<D: Device + 'static>(&mut self, device: D) {
self.devices.push(Box::new(device));
}
pub fn poll_all(&mut self) -> Vec<InputEvent> {
let mut events = Vec::new();
for device in self.devices.iter_mut() {
events.extend(device.poll());
}
events
}
pub fn snapshot(&mut self) -> &HashMap<String, DeviceState> {
self.snapshot_cache.clear();
for device in self.devices.iter_mut() {
let device_id = device.id().to_string();
let mut state = DeviceState::default();
for event in device.poll() {
match event {
InputEvent::AxisMoved { axis, value } => {
state.axes.insert(axis.to_string(), value);
}
InputEvent::ButtonPressed { button } => {
state.buttons.insert(button.to_string(), true);
}
InputEvent::ButtonReleased { button } => {
state.buttons.insert(button.to_string(), false);
}
}
}
self.snapshot_cache.insert(device_id, state);
}
&self.snapshot_cache
}
pub fn get_axis(&mut self, binding: &str) -> Option<f32> {
if let Some((device_id, axis_id)) = binding.split_once('.') {
let snapshot = self.snapshot();
return snapshot.get(device_id)?.axes.get(axis_id).copied();
}
None
}
pub fn is_pressed(&mut self, binding: &str) -> bool {
if let Some((device_id, button_id)) = binding.split_once('.') {
let snapshot = self.snapshot();
return snapshot
.get(device_id)
.and_then(|state| state.buttons.get(button_id))
.copied()
.unwrap_or(false);
}
false
}
pub fn devices(&self) -> impl Iterator<Item = &Box<dyn Device>> {
self.devices.iter()
}
}