shrooms-vb-native/src/app.rs

132 lines
3.5 KiB
Rust

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<WindowId, Box<dyn AppWindow>>,
client: EmulatorClient,
input_mapper: Arc<RwLock<InputMapper>>,
controller: ControllerState,
proxy: EventLoopProxy<UserEvent>,
}
impl App {
pub fn new(client: EmulatorClient, proxy: EventLoopProxy<UserEvent>) -> 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<UserEvent> 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<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(),
}
}
}