shrooms-vb-native/src/app.rs

118 lines
3.2 KiB
Rust

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<WindowId, Box<dyn AppWindow>>,
focused_window: Option<WindowId>,
client: EmulatorClient,
proxy: EventLoopProxy<UserEvent>,
}
impl App {
pub fn new(client: EmulatorClient, proxy: EventLoopProxy<UserEvent>) -> Self {
Self {
windows: HashMap::new(),
focused_window: None,
client,
proxy,
}
}
fn active_window(&mut self) -> Option<&mut Box<dyn AppWindow>> {
let active_window = self.focused_window?;
self.windows.get_mut(&active_window)
}
}
impl ApplicationHandler<UserEvent> 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<UserEvent>);
}
pub enum UserEvent {
OpenWindow(Box<dyn AppWindow>),
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(),
}
}
}