Stop using nested viewports
This commit is contained in:
+8
-144
@@ -1,157 +1,21 @@
|
||||
use std::{
|
||||
sync::{
|
||||
atomic::{AtomicBool, Ordering},
|
||||
Arc, Mutex,
|
||||
},
|
||||
thread,
|
||||
};
|
||||
|
||||
use egui::{Context, ViewportBuilder, ViewportId};
|
||||
use game::GameWindow;
|
||||
use game_screen::GameScreen;
|
||||
use gilrs::{EventType, Gilrs};
|
||||
use input::InputWindow;
|
||||
use winit::{event::KeyEvent, event_loop::EventLoopProxy};
|
||||
|
||||
use crate::{
|
||||
application::UserEvent,
|
||||
controller::ControllerManager,
|
||||
emulator::{EmulatorClient, EmulatorCommand, SimId},
|
||||
input::MappingProvider,
|
||||
};
|
||||
pub use game::GameWindow;
|
||||
pub use input::InputWindow;
|
||||
use winit::event::KeyEvent;
|
||||
|
||||
mod game;
|
||||
mod game_screen;
|
||||
mod input;
|
||||
|
||||
pub struct WindowManager {
|
||||
p1: GameWindow,
|
||||
p2: Arc<Mutex<GameWindow>>,
|
||||
client: EmulatorClient,
|
||||
input: ChildWindow<InputWindow>,
|
||||
controllers: ControllerManager,
|
||||
}
|
||||
impl WindowManager {
|
||||
pub fn new(client: EmulatorClient, proxy: EventLoopProxy<UserEvent>) -> Self {
|
||||
let mappings = MappingProvider::new();
|
||||
let controllers = ControllerManager::new(client.clone(), &mappings);
|
||||
{
|
||||
let mappings = mappings.clone();
|
||||
thread::spawn(|| process_gamepad_input(mappings, proxy));
|
||||
}
|
||||
let input = ChildWindow::new(InputWindow::new(mappings));
|
||||
let p1 = GameWindow::new(client.clone(), SimId::Player1, input.open.clone());
|
||||
let p2 = GameWindow::new(client.clone(), SimId::Player2, input.open.clone());
|
||||
Self {
|
||||
p1,
|
||||
p2: Arc::new(Mutex::new(p2)),
|
||||
client,
|
||||
input,
|
||||
controllers,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn init_renderer(&mut self, render_state: &egui_wgpu::RenderState) {
|
||||
GameScreen::init_pipeline(render_state);
|
||||
self.p2.lock().unwrap().init_renderer(render_state);
|
||||
self.p1.init_renderer(render_state);
|
||||
}
|
||||
|
||||
pub fn initial_viewport(&self) -> ViewportBuilder {
|
||||
self.p1.initial_viewport()
|
||||
}
|
||||
|
||||
pub fn show(&mut self, ctx: &Context) {
|
||||
self.p1.show(ctx);
|
||||
self.input.show(ctx);
|
||||
if self.client.has_player_2() {
|
||||
let (viewport_id, viewport) = {
|
||||
let p2 = self.p2.lock().unwrap();
|
||||
(p2.viewport_id(), p2.initial_viewport())
|
||||
};
|
||||
let client = self.client.clone();
|
||||
let p2 = self.p2.clone();
|
||||
ctx.show_viewport_deferred(viewport_id, viewport, move |ctx, _| {
|
||||
p2.lock().unwrap().show(ctx);
|
||||
if ctx.input(|i| i.viewport().close_requested()) {
|
||||
client.send_command(EmulatorCommand::StopSecondSim);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
pub fn handle_key_event(&mut self, event: winit::event::KeyEvent) {
|
||||
self.controllers.handle_key_event(&event);
|
||||
self.input.handle_key_event(&event);
|
||||
}
|
||||
|
||||
pub fn handle_gamepad_event(&mut self, event: gilrs::Event) {
|
||||
self.controllers.handle_gamepad_event(&event);
|
||||
}
|
||||
}
|
||||
|
||||
fn process_gamepad_input(mappings: MappingProvider, proxy: EventLoopProxy<UserEvent>) {
|
||||
let Ok(mut gilrs) = Gilrs::new() else {
|
||||
eprintln!("could not connect gamepad listener");
|
||||
return;
|
||||
};
|
||||
while let Some(event) = gilrs.next_event_blocking(None) {
|
||||
if event.event == EventType::Connected {
|
||||
let Some(gamepad) = gilrs.connected_gamepad(event.id) else {
|
||||
continue;
|
||||
};
|
||||
mappings.map_gamepad(SimId::Player1, &gamepad);
|
||||
}
|
||||
if proxy.send_event(UserEvent::GamepadEvent(event)).is_err() {
|
||||
// main thread has closed! we done
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
trait AppWindow {
|
||||
pub trait AppWindow {
|
||||
fn viewport_id(&self) -> ViewportId;
|
||||
fn initial_viewport(&self) -> ViewportBuilder;
|
||||
fn show(&mut self, ctx: &Context);
|
||||
fn on_init(&mut self, render_state: &egui_wgpu::RenderState) {
|
||||
let _ = render_state;
|
||||
}
|
||||
fn on_destroy(&mut self) {}
|
||||
fn handle_key_event(&mut self, event: &KeyEvent) {
|
||||
let _ = event;
|
||||
}
|
||||
}
|
||||
|
||||
struct ChildWindow<T: AppWindow> {
|
||||
pub open: Arc<AtomicBool>,
|
||||
window: Arc<Mutex<T>>,
|
||||
}
|
||||
impl<T: AppWindow + Send + 'static> ChildWindow<T> {
|
||||
fn new(window: T) -> Self {
|
||||
Self {
|
||||
open: Arc::new(AtomicBool::new(false)),
|
||||
window: Arc::new(Mutex::new(window)),
|
||||
}
|
||||
}
|
||||
|
||||
fn show(&self, ctx: &Context) {
|
||||
if !self.open.load(Ordering::Relaxed) {
|
||||
return;
|
||||
}
|
||||
let (viewport_id, viewport) = {
|
||||
let window = self.window.lock().unwrap();
|
||||
(window.viewport_id(), window.initial_viewport())
|
||||
};
|
||||
let open = self.open.clone();
|
||||
let window = self.window.clone();
|
||||
ctx.show_viewport_deferred(viewport_id, viewport, move |ctx, _| {
|
||||
window.lock().unwrap().show(ctx);
|
||||
if ctx.input(|i| i.viewport().close_requested()) {
|
||||
open.store(false, Ordering::Relaxed);
|
||||
ctx.request_repaint();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn handle_key_event(&self, event: &KeyEvent) {
|
||||
if self.open.load(Ordering::Relaxed) {
|
||||
self.window.lock().unwrap().handle_key_event(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user