fishsticks 0.2.3

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

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

use crate::Result;

pub type ImplementationId = u32;

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

pub struct OwnedImplementationGamepad(sdl2::controller::GameController);

pub struct ImplementationContext {
    sdl_context: sdl2::Sdl,
    controller_subsystem: sdl2::GameControllerSubsystem,
}

impl ImplementationContext {
    pub fn new() -> Result<Self> {
        let sdl_context = sdl2::init()?;
        let controller_subsystem = sdl_context.game_controller()?;

        Ok(Self {
            sdl_context,
            controller_subsystem,
        })
    }
}

impl super::Backend for ImplementationContext {
    fn update(&mut self, gamepads: &mut HashMap<GamepadId, Gamepad>) -> Result<()> {
        let mut event_pump = self.sdl_context.event_pump()?;

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

        for event in event_pump.poll_iter() {
            use sdl2::event::Event;
            match event {
                Event::ControllerDeviceAdded { which, .. } => {
                    let gamepad = self.controller_subsystem.open(which);
                    if let Ok(gamepad) = gamepad {
                        #[cfg(debug_assertions)]
                        let name = gamepad.name();

                        gamepads.insert(
                            GamepadId(gamepad.instance_id()),
                            Gamepad::new(Some(OwnedImplementationGamepad(gamepad))),
                        );

                        #[cfg(debug_assertions)]
                        println!("Added gamepad \"{}\"", name);
                    }
                }
                Event::ControllerDeviceRemoved { which, .. } => {
                    #[cfg(debug_assertions)]
                    let name = gamepads
                        .get(&GamepadId(which))
                        .unwrap()
                        .owned_internal_gamepad
                        .as_ref()
                        .unwrap()
                        .0
                        .name();

                    gamepads.remove(&GamepadId(which));

                    #[cfg(debug_assertions)]
                    println!("Removed gamepad \"{}\"", name);
                }
                Event::ControllerAxisMotion {
                    which, axis, value, ..
                } => {
                    if let Some(gamepad) = gamepads.get_mut(&GamepadId(which)) {
                        gamepad
                            .analog_inputs
                            .set(axis, AnalogInputValue::from(value));
                    }
                }
                Event::ControllerButtonDown { which, button, .. } => {
                    if let Some(gamepad) = gamepads.get_mut(&GamepadId(which)) {
                        gamepad.digital_inputs.activate(button);
                    }
                }
                Event::ControllerButtonUp { which, button, .. } => {
                    if let Some(gamepad) = gamepads.get_mut(&GamepadId(which)) {
                        gamepad.digital_inputs.deactivate(button);
                    }
                }
                _ => (),
            }
        }

        Ok(())
    }
}