use std::{collections::HashMap, fmt::Debug}; use game::GameWindow; use winit::{ application::ApplicationHandler, event::{Event, WindowEvent}, event_loop::{ActiveEventLoop, EventLoopProxy}, window::WindowId, }; use crate::emulator::EmulatorClient; mod common; mod game; mod input; pub struct App { windows: HashMap>, focused_window: Option, client: EmulatorClient, proxy: EventLoopProxy, } impl App { pub fn new(client: EmulatorClient, proxy: EventLoopProxy) -> Self { Self { windows: HashMap::new(), focused_window: None, client, proxy, } } fn active_window(&mut self) -> Option<&mut Box> { let active_window = self.focused_window?; self.windows.get_mut(&active_window) } } impl ApplicationHandler for App { fn resumed(&mut self, event_loop: &ActiveEventLoop) { let mut window = GameWindow::new(event_loop, self.client.clone(), self.proxy.clone()); window.init(); self.focused_window = Some(window.id()); self.windows.insert(window.id(), Box::new(window)); } fn window_event( &mut self, event_loop: &ActiveEventLoop, window_id: WindowId, event: WindowEvent, ) { if let WindowEvent::Focused(focused) = event { if focused { self.focused_window = Some(window_id); } else { self.focused_window = None; } } 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, ) { let Some(window) = self.active_window() else { return; }; window.handle_event(event_loop, &Event::DeviceEvent { device_id, event }); } fn about_to_wait(&mut self, event_loop: &ActiveEventLoop) { let Some(window) = self.active_window() else { return; }; 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(), } } }