129 lines
3.9 KiB
Rust
129 lines
3.9 KiB
Rust
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<RwLock<InputMapping>>,
|
|
}
|
|
|
|
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<VBKey> {
|
|
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<VBKey> {
|
|
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<VBKey> {
|
|
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<VBKey> {
|
|
self.mapping.read().unwrap().map_keyboard(key)
|
|
}
|
|
|
|
fn map_button(&self, id: &GamepadId, code: &Code) -> Option<VBKey> {
|
|
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));
|
|
}
|
|
}
|
|
}
|
|
}
|