2024-11-09 23:14:18 +00:00
|
|
|
use std::{collections::HashMap, fmt::Debug};
|
|
|
|
|
|
|
|
use game::GameWindow;
|
2024-11-03 16:32:53 +00:00
|
|
|
use winit::{
|
|
|
|
application::ApplicationHandler,
|
2024-11-05 05:07:48 +00:00
|
|
|
event::{Event, WindowEvent},
|
2024-11-09 23:14:18 +00:00
|
|
|
event_loop::{ActiveEventLoop, EventLoopProxy},
|
|
|
|
window::WindowId,
|
2024-11-03 16:32:53 +00:00
|
|
|
};
|
|
|
|
|
2024-11-09 23:14:18 +00:00
|
|
|
use crate::emulator::EmulatorClient;
|
2024-11-03 16:32:53 +00:00
|
|
|
|
2024-11-09 23:14:18 +00:00
|
|
|
mod common;
|
|
|
|
mod game;
|
|
|
|
mod input;
|
2024-11-03 16:32:53 +00:00
|
|
|
|
|
|
|
pub struct App {
|
2024-11-09 23:14:18 +00:00
|
|
|
windows: HashMap<WindowId, Box<dyn AppWindow>>,
|
|
|
|
focused_window: Option<WindowId>,
|
2024-11-03 16:32:53 +00:00
|
|
|
client: EmulatorClient,
|
2024-11-09 23:14:18 +00:00
|
|
|
proxy: EventLoopProxy<UserEvent>,
|
2024-11-03 16:32:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl App {
|
2024-11-09 23:14:18 +00:00
|
|
|
pub fn new(client: EmulatorClient, proxy: EventLoopProxy<UserEvent>) -> Self {
|
2024-11-03 16:32:53 +00:00
|
|
|
Self {
|
2024-11-09 23:14:18 +00:00
|
|
|
windows: HashMap::new(),
|
|
|
|
focused_window: None,
|
2024-11-03 16:32:53 +00:00
|
|
|
client,
|
2024-11-09 23:14:18 +00:00
|
|
|
proxy,
|
2024-11-03 16:32:53 +00:00
|
|
|
}
|
|
|
|
}
|
2024-11-09 23:14:18 +00:00
|
|
|
|
|
|
|
fn active_window(&mut self) -> Option<&mut Box<dyn AppWindow>> {
|
|
|
|
let active_window = self.focused_window?;
|
|
|
|
self.windows.get_mut(&active_window)
|
|
|
|
}
|
2024-11-03 16:32:53 +00:00
|
|
|
}
|
|
|
|
|
2024-11-09 23:14:18 +00:00
|
|
|
impl ApplicationHandler<UserEvent> for App {
|
2024-11-03 16:32:53 +00:00
|
|
|
fn resumed(&mut self, event_loop: &ActiveEventLoop) {
|
2024-11-09 23:14:18 +00:00
|
|
|
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));
|
2024-11-03 16:32:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn window_event(
|
|
|
|
&mut self,
|
|
|
|
event_loop: &ActiveEventLoop,
|
2024-11-09 23:14:18 +00:00
|
|
|
window_id: WindowId,
|
2024-11-03 16:32:53 +00:00
|
|
|
event: WindowEvent,
|
|
|
|
) {
|
2024-11-09 23:14:18 +00:00
|
|
|
if let WindowEvent::Focused(focused) = event {
|
|
|
|
if focused {
|
|
|
|
self.focused_window = Some(window_id);
|
|
|
|
} else {
|
|
|
|
self.focused_window = None;
|
2024-11-03 16:32:53 +00:00
|
|
|
}
|
|
|
|
}
|
2024-11-09 23:14:18 +00:00
|
|
|
let Some(window) = self.windows.get_mut(&window_id) else {
|
|
|
|
return;
|
|
|
|
};
|
|
|
|
window.handle_event(event_loop, &Event::WindowEvent { window_id, event });
|
2024-11-03 16:32:53 +00:00
|
|
|
}
|
|
|
|
|
2024-11-09 23:14:18 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
2024-11-03 16:32:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn device_event(
|
|
|
|
&mut self,
|
2024-11-09 23:14:18 +00:00
|
|
|
event_loop: &ActiveEventLoop,
|
2024-11-03 16:32:53 +00:00
|
|
|
device_id: winit::event::DeviceId,
|
|
|
|
event: winit::event::DeviceEvent,
|
|
|
|
) {
|
2024-11-09 23:14:18 +00:00
|
|
|
let Some(window) = self.active_window() else {
|
|
|
|
return;
|
|
|
|
};
|
|
|
|
window.handle_event(event_loop, &Event::DeviceEvent { device_id, event });
|
2024-11-03 16:32:53 +00:00
|
|
|
}
|
|
|
|
|
2024-11-09 23:14:18 +00:00
|
|
|
fn about_to_wait(&mut self, event_loop: &ActiveEventLoop) {
|
|
|
|
let Some(window) = self.active_window() else {
|
|
|
|
return;
|
|
|
|
};
|
|
|
|
window.handle_event(event_loop, &Event::AboutToWait);
|
2024-11-03 16:32:53 +00:00
|
|
|
}
|
|
|
|
}
|
2024-11-03 18:49:10 +00:00
|
|
|
|
2024-11-09 23:14:18 +00:00
|
|
|
pub trait AppWindow {
|
|
|
|
fn id(&self) -> WindowId;
|
|
|
|
fn init(&mut self);
|
|
|
|
fn handle_event(&mut self, event_loop: &ActiveEventLoop, event: &Event<UserEvent>);
|
|
|
|
}
|
2024-11-05 04:39:00 +00:00
|
|
|
|
2024-11-09 23:14:18 +00:00
|
|
|
pub enum UserEvent {
|
|
|
|
OpenWindow(Box<dyn AppWindow>),
|
|
|
|
CloseWindow(WindowId),
|
2024-11-05 04:39:00 +00:00
|
|
|
}
|
|
|
|
|
2024-11-09 23:14:18 +00:00
|
|
|
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(),
|
|
|
|
}
|
|
|
|
}
|
2024-11-03 18:49:10 +00:00
|
|
|
}
|