fishsticks 0.2.3

A simple gamepad input library
Documentation
pub use gilrs::{Axis, Button};

use crate::analog::AnalogInputValue;
use crate::{Gamepad, GamepadId};
use std::collections::HashMap;

use crate::Result;

pub type ImplementationId = gilrs::GamepadId;

impl From<GamepadId> for usize {
    fn from(id: GamepadId) -> Self {
        id.0.into()
    }
}

pub enum OwnedImplementationGamepad {}

pub struct ImplementationContext {
    context: gilrs::Gilrs,
    init_gamepads: Vec<GamepadId>,
}

impl ImplementationContext {
    pub fn new() -> Result<Self> {
        match gilrs::Gilrs::new() {
            Ok(context) => {
                let mut init_gamepads = Vec::new();

                for (gamepad_id, _) in context.gamepads() {
                    init_gamepads.push(GamepadId(gamepad_id));
                }

                Ok(Self {
                    context,
                    init_gamepads,
                })
            }
            Err(e) => Err(e.to_string()),
        }
    }
}

impl super::Backend for ImplementationContext {
    fn update(&mut self, gamepads: &mut HashMap<GamepadId, Gamepad>) -> Result<()> {
        for gamepad in self.init_gamepads.drain(..) {
            gamepads.insert(gamepad, Gamepad::new(None));
        }

        for (_, gamepad) in gamepads.iter_mut() {
            gamepad.update_inputs();
        }

        while let Some(gilrs::Event { id, event, .. }) = self.context.next_event() {
            use gilrs::EventType;
            match event {
                EventType::Connected => {
                    gamepads.insert(GamepadId(id), Gamepad::new(None));

                    #[cfg(debug_assertions)]
                    println!("Added gamepad \"{}\"", self.context.gamepad(id).name());
                }
                EventType::Disconnected => {
                    gamepads.remove(&GamepadId(id));

                    #[cfg(debug_assertions)]
                    println!("Removed gamepad \"{}\"", self.context.gamepad(id).name());
                }
                EventType::AxisChanged(axis, value, _) => {
                    if let Some(gamepad) = gamepads.get_mut(&GamepadId(id)) {
                        gamepad
                            .analog_inputs
                            .set(axis, AnalogInputValue::from(value));
                    }
                }
                EventType::ButtonPressed(button, _) => {
                    if let Some(gamepad) = gamepads.get_mut(&GamepadId(id)) {
                        gamepad.digital_inputs.activate(button);
                    }
                }
                EventType::ButtonReleased(button, _) => {
                    if let Some(gamepad) = gamepads.get_mut(&GamepadId(id)) {
                        gamepad.digital_inputs.deactivate(button);
                    }
                }
                _ => (),
            }
        }

        Ok(())
    }
}