143 lines
4.0 KiB
Rust
143 lines
4.0 KiB
Rust
use std::{
|
|
collections::HashMap,
|
|
fmt::Debug,
|
|
sync::{Arc, RwLock},
|
|
};
|
|
|
|
use game::GameWindow;
|
|
use input::InputWindow;
|
|
use winit::{
|
|
application::ApplicationHandler,
|
|
event::{Event, WindowEvent},
|
|
event_loop::{ActiveEventLoop, EventLoopProxy},
|
|
window::WindowId,
|
|
};
|
|
|
|
use crate::{
|
|
controller::ControllerState,
|
|
emulator::{EmulatorClient, EmulatorCommand, SimId},
|
|
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>,
|
|
player_2_window: Option<WindowId>,
|
|
}
|
|
|
|
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,
|
|
player_2_window: None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ApplicationHandler<UserEvent> for App {
|
|
fn resumed(&mut self, event_loop: &ActiveEventLoop) {
|
|
let window = GameWindow::new(
|
|
event_loop,
|
|
SimId::Player1,
|
|
self.client.clone(),
|
|
self.proxy.clone(),
|
|
);
|
|
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 let Some((sim_id, pressed)) = self.controller.key_event(event) {
|
|
self.client
|
|
.send_command(EmulatorCommand::SetKeys(sim_id, 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::OpenInputWindow => {
|
|
let window =
|
|
InputWindow::new(event_loop, self.input_mapper.clone(), self.proxy.clone());
|
|
self.windows.insert(window.id(), Box::new(window));
|
|
}
|
|
UserEvent::OpenPlayer2Window => {
|
|
if self.player_2_window.is_some() {
|
|
return;
|
|
}
|
|
let window = GameWindow::new(
|
|
event_loop,
|
|
SimId::Player2,
|
|
self.client.clone(),
|
|
self.proxy.clone(),
|
|
);
|
|
self.player_2_window = Some(window.id());
|
|
self.windows.insert(window.id(), Box::new(window));
|
|
}
|
|
UserEvent::Close(window_id) => {
|
|
if self.player_2_window == Some(window_id) {
|
|
self.player_2_window.take();
|
|
}
|
|
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 handle_event(&mut self, event_loop: &ActiveEventLoop, event: &Event<UserEvent>);
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub enum UserEvent {
|
|
OpenInputWindow,
|
|
OpenPlayer2Window,
|
|
Close(WindowId),
|
|
}
|