use std::sync::{Arc, RwLock}; use gilrs::{ev::Code, Event as GamepadEvent, EventType, GamepadId}; use winit::{ event::{ElementState, KeyEvent}, keyboard::PhysicalKey, }; use crate::{ emulator::{EmulatorClient, EmulatorCommand, SimId, VBKey}, input::{InputMapping, MappingProvider}, }; pub struct Controller { pub sim_id: SimId, state: VBKey, mapping: Arc>, } impl Controller { pub fn new(sim_id: SimId, mappings: &MappingProvider) -> Self { Self { sim_id, state: VBKey::SGN, mapping: mappings.for_sim(sim_id).clone(), } } pub fn key_event(&mut self, event: &KeyEvent) -> Option { let keys = self.map_keys(&event.physical_key)?; match event.state { ElementState::Pressed => self.update_state(keys, VBKey::empty()), ElementState::Released => self.update_state(VBKey::empty(), keys), } } pub fn gamepad_event(&mut self, event: &GamepadEvent) -> Option { let (pressed, released) = match event.event { EventType::ButtonPressed(_, code) => { let mappings = self.map_button(&event.id, &code)?; (mappings, VBKey::empty()) } EventType::ButtonReleased(_, code) => { let mappings = self.map_button(&event.id, &code)?; (VBKey::empty(), mappings) } EventType::AxisChanged(_, value, code) => { let (neg, pos) = self.map_axis(&event.id, &code)?; let mut pressed = VBKey::empty(); let mut released = VBKey::empty(); if value < -0.75 { pressed = pressed.union(neg); } if value > 0.75 { pressed = pressed.union(pos); } if value > -0.65 { released = released.union(neg); } if value < 0.65 { released = released.union(pos); } (pressed, released) } _ => { return None; } }; self.update_state(pressed, released) } fn update_state(&mut self, pressed: VBKey, released: VBKey) -> Option { let old_state = self.state; self.state = self.state.union(pressed).difference(released); if self.state != old_state { Some(self.state) } else { None } } fn map_keys(&self, key: &PhysicalKey) -> Option { self.mapping.read().unwrap().map_keyboard(key) } fn map_button(&self, id: &GamepadId, code: &Code) -> Option { self.mapping.read().unwrap().map_button(id, code) } fn map_axis(&self, id: &GamepadId, code: &Code) -> Option<(VBKey, VBKey)> { self.mapping.read().unwrap().map_axis(id, code) } } pub struct ControllerManager { client: EmulatorClient, controllers: [Controller; 2], } impl ControllerManager { pub fn new(client: EmulatorClient, mappings: &MappingProvider) -> Self { Self { client, controllers: [ Controller::new(SimId::Player1, mappings), Controller::new(SimId::Player2, mappings), ], } } pub fn handle_key_event(&mut self, event: &KeyEvent) { for controller in &mut self.controllers { if let Some(pressed) = controller.key_event(event) { self.client .send_command(EmulatorCommand::SetKeys(controller.sim_id, pressed)); } } } pub fn handle_gamepad_event(&mut self, event: &GamepadEvent) { for controller in &mut self.controllers { if let Some(pressed) = controller.gamepad_event(event) { self.client .send_command(EmulatorCommand::SetKeys(controller.sim_id, pressed)); } } } }