// -*- coding: utf-8 -*- // // Copyright 2021-2023 Michael Büsch // // Licensed under the Apache License version 2.0 // or the MIT license, at your option. // SPDX-License-Identifier: Apache-2.0 OR MIT // use cassette::Cassette; use std::cell::RefCell; use std::future::Future; use std::pin::Pin; use std::rc::Rc; use std::task::Context; use std::task::Poll; use stick::{Controller, Event, Listener}; /// Wrap a Future in a Rc> macro_rules! def_rc_refcell_future { ($name:ident, $future:ident, $output:ty) => { struct $name { fut: Rc>, } impl $name { fn new(fut: Rc>) -> Self { Self { fut } } } impl Future for $name { type Output = $output; fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll { Pin::new(&mut *self.fut.borrow_mut()).poll(cx) } } }; } def_rc_refcell_future!(RcRefCellListener, Listener, Controller); def_rc_refcell_future!(RcRefCellController, Controller, Event); #[derive(Default, Debug, Clone)] pub struct Joy2D { x: f64, y: f64, } impl Joy2D { pub fn x(&self) -> f64 { self.x } pub fn y(&self) -> f64 { self.y } } #[derive(Default, Debug, Clone)] pub struct JoystickState { stick: Joy2D, view: Joy2D, buttons: [bool; 5], throttle: f64, } impl JoystickState { fn new() -> Self { Default::default() } pub fn get_stick(&self) -> &Joy2D { &self.stick } #[allow(dead_code)] pub fn get_view(&self) -> &Joy2D { &self.view } #[allow(dead_code)] pub fn get_button(&self, index: usize) -> bool { if index < self.buttons.len() { self.buttons[index] } else { false } } pub fn get_throttle(&self) -> f64 { self.throttle } } pub struct Joystick { listener: Rc>, listener_cas: Option>, controllers: Vec>>, controllers_cas: Vec>>, controller_states: Vec, } impl Joystick { pub fn new() -> Self { let listener: Rc> = Rc::new(RefCell::new(Default::default())); let listener_cas = Cassette::new(RcRefCellListener::new(Rc::clone(&listener))); Self { listener, listener_cas: Some(listener_cas), controllers: vec![], controllers_cas: vec![], controller_states: vec![], } } pub fn get_count(&self) -> usize { self.controllers.len() } pub fn get_state(&self, index: usize) -> &JoystickState { if index < self.get_count() { &self.controller_states[index] } else { panic!("Joystick {} is not available.", index); } } fn handle_listener_event(&mut self, controller: Controller) { println!("Joystick '{}' connected.", controller.name()); self.controllers .push(Rc::new(RefCell::new(controller))); self.controllers_cas.push(Some(Cassette::new( RcRefCellController::new(Rc::clone( &self.controllers[self.controllers.len() - 1] ))))); self.controller_states.push(JoystickState::new()); } fn handle_controller_event( &mut self, index: usize, remove: &mut Vec, event: stick::Event, ) { let state = &mut self.controller_states[index]; match event { stick::Event::Disconnect => { println!("Joystick {} disconnected.", index); remove.push(index); } stick::Event::Up(pressed) => { if pressed { state.view.y = 1.0; } else { state.view.y = 0.0; } } stick::Event::Down(pressed) => { if pressed { state.view.y = -1.0; } else { state.view.y = 0.0; } } stick::Event::Left(pressed) => { if pressed { state.view.x = -1.0; } else { state.view.x = 0.0; } } stick::Event::Right(pressed) => { if pressed { state.view.x = 1.0; } else { state.view.x = 0.0; } } stick::Event::JoyX(value) => { state.stick.x = value; } stick::Event::JoyY(value) => { state.stick.y = value; } stick::Event::JoyZ(_value) => { //TODO } stick::Event::CamX(_value) => { //TODO } stick::Event::CamY(_value) => { //TODO } stick::Event::CamZ(_value) => { //TODO } stick::Event::ActionA(pressed) => { state.buttons[0] = pressed; } stick::Event::ActionB(pressed) => { state.buttons[1] = pressed; } stick::Event::ActionC(pressed) => { state.buttons[2] = pressed; } stick::Event::ActionH(pressed) => { state.buttons[3] = pressed; } stick::Event::ActionV(pressed) => { state.buttons[4] = pressed; } stick::Event::BumperR(_pressed) => { //TODO } stick::Event::BumperL(_pressed) => { //TODO } stick::Event::TriggerR(_pressed) => { //TODO } stick::Event::TriggerL(_pressed) => { //TODO } stick::Event::Throttle(value) => { state.throttle = 1.0 - value; } event => { println!("Unhandled joystick controller event: {index}, {event:?}"); } } } pub fn update(&mut self) { if let Some(mut listener_cas) = self.listener_cas.take() { if let Some(controller) = listener_cas.poll_on() { self.handle_listener_event(controller); self.listener_cas = Some(Cassette::new(RcRefCellListener::new(Rc::clone(&self.listener)))); } else { self.listener_cas = Some(listener_cas); } } else { unreachable!(); } let mut remove = Vec::with_capacity(0); for index in 0..self.controllers.len() { if let Some(mut controller_cas) = self.controllers_cas[index].take() { if let Some(event) = controller_cas.poll_on() { self.handle_controller_event(index, &mut remove, event); self.controllers_cas[index] = Some(Cassette::new(RcRefCellController::new(Rc::clone(&self.controllers[index])))); } else { self.controllers_cas[index] = Some(controller_cas); } } else { unreachable!(); } } for index in remove.iter().rev() { self.controllers.remove(*index); self.controllers_cas.remove(*index); self.controller_states.remove(*index); } debug_assert_eq!(self.controllers.len(), self.controllers_cas.len()); debug_assert_eq!(self.controllers.len(), self.controller_states.len()); } } impl Default for Joystick { fn default() -> Self { Self::new() } } // vim: ts=4 sw=4 expandtab