use serde::{Deserialize, Serialize};
use std::collections::HashMap;
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum ControlType {
Axis,
Button,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct ControlPath {
pub control_id: String,
pub control_type: ControlType,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Binding {
pub device_id: String,
pub control: ControlPath,
pub action_name: String,
pub invert: bool,
pub deadzone: f32,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BindingProfile {
pub name: String,
pub description: Option<String>,
pub bindings: Vec<Binding>,
}
#[derive(Default, Debug, Serialize, Deserialize)]
pub struct BindingOutput {
pub axis: HashMap<String, f32>,
pub buttons: HashMap<String, bool>,
}
#[derive(Default, Debug, Serialize, Deserialize)]
pub struct DeviceState {
pub axes: HashMap<String, f32>,
pub buttons: HashMap<String, bool>,
}
impl BindingProfile {
pub fn resolve(&self, devices: &HashMap<String, DeviceState>) -> BindingOutput {
let mut output = BindingOutput::default();
for binding in &self.bindings {
if let Some(state) = devices.get(&binding.device_id) {
match binding.control.control_type {
ControlType::Axis => {
let mut value = state.get_axis(&binding.control.control_id);
if binding.invert {
value *= -1.0;
}
if value.abs() < binding.deadzone {
value = 0.0;
}
output.axis.insert(binding.action_name.clone(), value);
}
ControlType::Button => {
let pressed = state.get_button(&binding.control.control_id);
output.buttons.insert(binding.action_name.clone(), pressed);
}
}
}
}
output
}
}
impl DeviceState {
pub fn get_axis(&self, name: &str) -> f32 {
self.axes.get(name).copied().unwrap_or(0.0)
}
pub fn get_button(&self, name: &str) -> bool {
self.buttons.get(name).copied().unwrap_or(false)
}
}