use std::{ collections::HashMap, fmt::Debug, sync::{Arc, RwLock}, }; use game::GameWindow; use winit::{ application::ApplicationHandler, event::{Event, WindowEvent}, event_loop::{ActiveEventLoop, EventLoopProxy}, window::WindowId, }; use crate::{ controller::ControllerState, emulator::{EmulatorClient, EmulatorCommand}, input::InputMapper, }; mod common; mod game; mod input; pub struct App { windows: HashMap>, client: EmulatorClient, input_mapper: Arc>, controller: ControllerState, proxy: EventLoopProxy, } impl App { pub fn new(client: EmulatorClient, proxy: EventLoopProxy) -> Self { let input_mapper = Arc::new(RwLock::new(InputMapper::new())); let controller = ControllerState::new(input_mapper.clone()); Self { windows: HashMap::new(), client, input_mapper, controller, proxy, } } } impl ApplicationHandler for App { fn resumed(&mut self, event_loop: &ActiveEventLoop) { let mut window = GameWindow::new( event_loop, self.client.clone(), self.input_mapper.clone(), self.proxy.clone(), ); window.init(); self.windows.insert(window.id(), Box::new(window)); } fn window_event( &mut self, event_loop: &ActiveEventLoop, window_id: WindowId, event: WindowEvent, ) { if let WindowEvent::KeyboardInput { event, .. } = &event { if self.controller.key_event(event) { self.client .send_command(EmulatorCommand::SetKeys(self.controller.pressed())); } } let Some(window) = self.windows.get_mut(&window_id) else { return; }; window.handle_event(event_loop, &Event::WindowEvent { window_id, event }); } fn user_event(&mut self, _event_loop: &ActiveEventLoop, event: UserEvent) { match event { UserEvent::OpenWindow(mut window) => { window.init(); self.windows.insert(window.id(), window); } UserEvent::CloseWindow(window_id) => { self.windows.remove(&window_id); } } } fn device_event( &mut self, event_loop: &ActiveEventLoop, device_id: winit::event::DeviceId, event: winit::event::DeviceEvent, ) { for window in self.windows.values_mut() { window.handle_event( event_loop, &Event::DeviceEvent { device_id, event: event.clone(), }, ); } } fn about_to_wait(&mut self, event_loop: &ActiveEventLoop) { for window in self.windows.values_mut() { window.handle_event(event_loop, &Event::AboutToWait); } } } pub trait AppWindow { fn id(&self) -> WindowId; fn init(&mut self); fn handle_event(&mut self, event_loop: &ActiveEventLoop, event: &Event); } pub enum UserEvent { OpenWindow(Box), CloseWindow(WindowId), } impl Debug for UserEvent { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Self::OpenWindow(window) => f.debug_tuple("OpenWindow").field(&window.id()).finish(), Self::CloseWindow(window_id) => f.debug_tuple("CloseWindow").field(window_id).finish(), } } }