engine: move winit ApplicationHandler to winit plugin
This commit is contained in:
parent
8b1077cab7
commit
2107b8f7b0
|
@ -1,10 +1,8 @@
|
|||
use std::{cell::OnceCell, collections::VecDeque, ptr::NonNull, sync::Arc};
|
||||
use std::{cell::OnceCell, collections::VecDeque, ptr::NonNull};
|
||||
|
||||
use async_std::task::block_on;
|
||||
use lyra_ecs::{system::{IntoSystem, System}, ResourceObject, World};
|
||||
use lyra_math::{IVec2, Vec2};
|
||||
use rustc_hash::FxHashMap;
|
||||
use tracing::{debug, debug_span, info, warn, error, Level};
|
||||
use lyra_math::IVec2;
|
||||
use tracing::{info, error, Level};
|
||||
use tracing_appender::non_blocking;
|
||||
use tracing_subscriber::{
|
||||
layer::SubscriberExt,
|
||||
|
@ -12,9 +10,7 @@ use tracing_subscriber::{
|
|||
util::SubscriberInitExt, fmt,
|
||||
};
|
||||
|
||||
use winit::{application::ApplicationHandler, event::{DeviceEvent, ElementState, Event, KeyEvent, WindowEvent}, event_loop::{ControlFlow, EventLoop}, keyboard::{Key, NamedKey}, window::{Window, WindowId}};
|
||||
|
||||
use crate::{change_tracker::Ct, input::InputEvent, plugin::Plugin, render::{renderer::{BasicRenderer, Renderer}, window::{PrimaryWindow, WindowOptions}}, winit::WinitWindows, EventQueue, Stage, StagedExecutor};
|
||||
use crate::{plugin::Plugin, render::renderer::Renderer, Stage, StagedExecutor};
|
||||
|
||||
#[derive(Clone, Copy, Hash, Debug)]
|
||||
pub enum GameStages {
|
||||
|
@ -54,8 +50,7 @@ impl WindowState {
|
|||
}
|
||||
|
||||
pub struct App {
|
||||
windows: FxHashMap<WindowId, Arc<Window>>,
|
||||
renderer: OnceCell<Box<dyn Renderer>>,
|
||||
pub(crate) renderer: OnceCell<Box<dyn Renderer>>,
|
||||
pub world: World,
|
||||
plugins: VecDeque<Box<dyn Plugin>>,
|
||||
startup_systems: VecDeque<Box<dyn System>>,
|
||||
|
@ -97,7 +92,6 @@ impl App {
|
|||
staged.add_stage_after(GameStages::PostUpdate, GameStages::Last);
|
||||
|
||||
Self {
|
||||
windows: FxHashMap::default(),
|
||||
renderer: OnceCell::new(),
|
||||
world,
|
||||
plugins: Default::default(),
|
||||
|
@ -115,13 +109,13 @@ impl App {
|
|||
}
|
||||
}
|
||||
|
||||
fn on_resize(&mut self, new_size: winit::dpi::PhysicalSize<u32>) {
|
||||
pub(crate) fn on_resize(&mut self, new_size: winit::dpi::PhysicalSize<u32>) {
|
||||
self.renderer.get_mut()
|
||||
.expect("renderer was not initialized")
|
||||
.on_resize(&mut self.world, new_size);
|
||||
}
|
||||
|
||||
fn on_exit(&mut self) {
|
||||
pub(crate) fn on_exit(&mut self) {
|
||||
info!("On exit!");
|
||||
}
|
||||
|
||||
|
@ -221,109 +215,3 @@ impl App {
|
|||
f(self);
|
||||
}
|
||||
}
|
||||
|
||||
impl ApplicationHandler for App {
|
||||
fn about_to_wait(&mut self, event_loop: &winit::event_loop::ActiveEventLoop) {
|
||||
debug!("update now");
|
||||
|
||||
self.update();
|
||||
|
||||
let renderer = self.renderer.get_mut().expect("renderer was not initialized");
|
||||
renderer.prepare(&mut self.world);
|
||||
|
||||
if let Some(mut event_queue) = self.world.try_get_resource_mut::<EventQueue>() {
|
||||
event_queue.update_events();
|
||||
}
|
||||
|
||||
match renderer.render() {
|
||||
Ok(_) => {}
|
||||
// Reconfigure the surface if lost
|
||||
//Err(wgpu::SurfaceError::Lost) => self.on_resize(.surface_size()),
|
||||
// The system is out of memory, we should probably quit
|
||||
Err(wgpu::SurfaceError::OutOfMemory) => {
|
||||
error!("OOM");
|
||||
event_loop.exit();
|
||||
}
|
||||
// All other errors (Outdated, Timeout) should be resolved by the next frame
|
||||
Err(e) => eprintln!("{:?}", e),
|
||||
}
|
||||
}
|
||||
|
||||
fn resumed(&mut self, event_loop: &winit::event_loop::ActiveEventLoop) {
|
||||
let world = &mut self.world;
|
||||
let en = world.spawn((WindowOptions::default(), PrimaryWindow));
|
||||
|
||||
let attr = Window::default_attributes();
|
||||
let mut windows = world.get_resource_mut::<WinitWindows>();
|
||||
let wid = windows.create_window(event_loop, en, attr).unwrap();
|
||||
let window = windows.windows.get(&wid).unwrap().clone();
|
||||
drop(windows);
|
||||
|
||||
let renderer = block_on(BasicRenderer::create_with_window(world, window));
|
||||
if self.renderer.set(Box::new(renderer)).is_err() {
|
||||
warn!("renderer was re-initialized");
|
||||
}
|
||||
}
|
||||
|
||||
fn window_event(
|
||||
&mut self,
|
||||
event_loop: &winit::event_loop::ActiveEventLoop,
|
||||
window_id: winit::window::WindowId,
|
||||
event: WindowEvent,
|
||||
) {
|
||||
//let _e = debug_span!("window_event", window=window_id).entered();
|
||||
let windows = self.world.get_resource::<WinitWindows>();
|
||||
let window = match windows.windows.get(&window_id) {
|
||||
Some(w) => w.clone(),
|
||||
None => return,
|
||||
};
|
||||
drop(windows);
|
||||
|
||||
// If try_from failed, that means that the WindowEvent is not an
|
||||
// input related event.
|
||||
if let Some(input_ev) = InputEvent::from_window_event(&event) {
|
||||
// Its possible to receive multiple input events before the update event for
|
||||
// the InputSystem is called, so we must use a queue for the events.
|
||||
if let Some(mut event_queue) = self.world.try_get_resource_mut::<EventQueue>() {
|
||||
event_queue.trigger_event(input_ev.clone());
|
||||
}
|
||||
} else {
|
||||
|
||||
match event {
|
||||
WindowEvent::ActivationTokenDone { serial, token } => todo!(),
|
||||
WindowEvent::Resized(physical_size) => {
|
||||
self.on_resize(physical_size);
|
||||
},
|
||||
WindowEvent::Moved(physical_position) => {
|
||||
let mut state = self.world.get_resource_or_else(WindowState::new);
|
||||
state.position = IVec2::new(physical_position.x, physical_position.y);
|
||||
},
|
||||
WindowEvent::CloseRequested => {
|
||||
self.on_exit();
|
||||
event_loop.exit();
|
||||
},
|
||||
WindowEvent::Destroyed => todo!(),
|
||||
WindowEvent::DroppedFile(path_buf) => todo!(),
|
||||
WindowEvent::HoveredFile(path_buf) => todo!(),
|
||||
WindowEvent::HoveredFileCancelled => todo!(),
|
||||
WindowEvent::Focused(focused) => {
|
||||
let mut state = self.world.get_resource_or_else(WindowState::new);
|
||||
state.focused = focused;
|
||||
},
|
||||
WindowEvent::ModifiersChanged(modifiers) => debug!("modifiers changed: {:?}", modifiers),
|
||||
WindowEvent::ScaleFactorChanged { scale_factor, inner_size_writer } => {
|
||||
info!("changed scale to {scale_factor}");
|
||||
},
|
||||
WindowEvent::ThemeChanged(theme) => todo!(),
|
||||
WindowEvent::Occluded(occ) => {
|
||||
let mut state = self.world.get_resource_or_else(WindowState::new);
|
||||
state.occluded = occ;
|
||||
},
|
||||
WindowEvent::RedrawRequested => {
|
||||
debug!("should redraw");
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,3 @@
|
|||
use std::cell::Cell;
|
||||
use std::cell::OnceCell;
|
||||
use std::cell::RefCell;
|
||||
use std::ptr::NonNull;
|
||||
|
||||
use lyra_ecs::system::System;
|
||||
use lyra_ecs::CommandQueue;
|
||||
use lyra_resource::ResourceManager;
|
||||
|
||||
|
@ -41,18 +35,6 @@ impl<P> Plugin for P
|
|||
}
|
||||
}
|
||||
|
||||
/// An ECS system converted to a plugin.
|
||||
///
|
||||
/// The system is executed in plugin setup phase.
|
||||
pub(crate) struct SystemPlugin<S: System>(pub RefCell<S>);
|
||||
|
||||
impl<S: System> Plugin for SystemPlugin<S> {
|
||||
fn setup(&self, app: &mut App) {
|
||||
let mut s = self.0.borrow_mut();
|
||||
s.execute(NonNull::from(&app.world));
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents a set of plugins that will be executed in order they are supplied.
|
||||
#[derive(Default)]
|
||||
pub struct PluginSet {
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use async_std::task::block_on;
|
||||
use glam::IVec2;
|
||||
use lyra_ecs::Entity;
|
||||
use rustc_hash::FxHashMap;
|
||||
use tracing::debug;
|
||||
use winit::{application::ApplicationHandler, event_loop::{ActiveEventLoop, EventLoop}, window::{Window, WindowAttributes, WindowId}};
|
||||
use tracing::{debug, error, info, warn};
|
||||
use winit::{application::ApplicationHandler, event::WindowEvent, event_loop::{ActiveEventLoop, EventLoop}, window::{Window, WindowAttributes, WindowId}};
|
||||
|
||||
use crate::{game::App, plugin::Plugin, render::window::WindowOptions};
|
||||
use crate::{game::{App, WindowState}, input::InputEvent, plugin::Plugin, render::{renderer::BasicRenderer, window::{PrimaryWindow, WindowOptions}}, EventQueue};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct WinitPlugin;
|
||||
|
@ -16,15 +18,15 @@ impl Plugin for WinitPlugin {
|
|||
app.add_resource(WinitWindows::default());
|
||||
}
|
||||
|
||||
fn is_ready(&self, app: &mut crate::game::App) -> bool {
|
||||
fn is_ready(&self, _app: &mut crate::game::App) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn complete(&self, app: &mut crate::game::App) {
|
||||
fn complete(&self, _app: &mut crate::game::App) {
|
||||
|
||||
}
|
||||
|
||||
fn cleanup(&self, app: &mut crate::game::App) {
|
||||
fn cleanup(&self, _app: &mut crate::game::App) {
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -52,37 +54,122 @@ impl WinitWindows {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn winit_app_runner(mut app: App) {
|
||||
pub fn winit_app_runner(app: App) {
|
||||
let evloop = EventLoop::new()
|
||||
.expect("failed to create winit EventLoop");
|
||||
|
||||
evloop.run_app(&mut app)
|
||||
let mut winit_runner = WinitRunner {
|
||||
app,
|
||||
};
|
||||
evloop.run_app(&mut winit_runner)
|
||||
.expect("loop error");
|
||||
}
|
||||
|
||||
/* struct WinitRunner {
|
||||
struct WinitRunner {
|
||||
app: App
|
||||
}
|
||||
|
||||
impl ApplicationHandler for WinitRunner {
|
||||
fn resumed(&mut self, event_loop: &ActiveEventLoop) {
|
||||
debug!("resumed")
|
||||
fn about_to_wait(&mut self, event_loop: &winit::event_loop::ActiveEventLoop) {
|
||||
debug!("update now");
|
||||
|
||||
self.app.update();
|
||||
|
||||
let renderer = self.app.renderer.get_mut().expect("renderer was not initialized");
|
||||
renderer.prepare(&mut self.app.world);
|
||||
|
||||
if let Some(mut event_queue) = self.app.world.try_get_resource_mut::<EventQueue>() {
|
||||
event_queue.update_events();
|
||||
}
|
||||
|
||||
match renderer.render() {
|
||||
Ok(_) => {}
|
||||
// Reconfigure the surface if lost
|
||||
//Err(wgpu::SurfaceError::Lost) => self.on_resize(.surface_size()),
|
||||
// The system is out of memory, we should probably quit
|
||||
Err(wgpu::SurfaceError::OutOfMemory) => {
|
||||
error!("OOM");
|
||||
event_loop.exit();
|
||||
}
|
||||
// All other errors (Outdated, Timeout) should be resolved by the next frame
|
||||
Err(e) => eprintln!("{:?}", e),
|
||||
}
|
||||
}
|
||||
|
||||
fn resumed(&mut self, event_loop: &winit::event_loop::ActiveEventLoop) {
|
||||
let world = &mut self.app.world;
|
||||
let en = world.spawn((WindowOptions::default(), PrimaryWindow));
|
||||
|
||||
let attr = Window::default_attributes();
|
||||
let mut windows = world.get_resource_mut::<WinitWindows>();
|
||||
let wid = windows.create_window(event_loop, en, attr).unwrap();
|
||||
let window = windows.windows.get(&wid).unwrap().clone();
|
||||
drop(windows);
|
||||
|
||||
let renderer = block_on(BasicRenderer::create_with_window(world, window));
|
||||
if self.app.renderer.set(Box::new(renderer)).is_err() {
|
||||
warn!("renderer was re-initialized");
|
||||
}
|
||||
}
|
||||
|
||||
fn window_event(
|
||||
&mut self,
|
||||
event_loop: &ActiveEventLoop,
|
||||
window_id: WindowId,
|
||||
event: winit::event::WindowEvent,
|
||||
event_loop: &winit::event_loop::ActiveEventLoop,
|
||||
window_id: winit::window::WindowId,
|
||||
event: WindowEvent,
|
||||
) {
|
||||
let world = &mut self.app.world;
|
||||
let mut windows = world.get_resource_mut::<WinitWindows>();
|
||||
|
||||
let window = match windows.windows.get_mut(&window_id) {
|
||||
Some(w) => w,
|
||||
let windows = self.app.world.get_resource::<WinitWindows>();
|
||||
let window = match windows.windows.get(&window_id) {
|
||||
Some(w) => w.clone(),
|
||||
None => return,
|
||||
};
|
||||
drop(windows);
|
||||
|
||||
|
||||
// If try_from failed, that means that the WindowEvent is not an
|
||||
// input related event.
|
||||
if let Some(input_ev) = InputEvent::from_window_event(&event) {
|
||||
// Its possible to receive multiple input events before the update event for
|
||||
// the InputSystem is called, so we must use a queue for the events.
|
||||
if let Some(mut event_queue) = self.app.world.try_get_resource_mut::<EventQueue>() {
|
||||
event_queue.trigger_event(input_ev.clone());
|
||||
}
|
||||
} */
|
||||
} else {
|
||||
|
||||
match event {
|
||||
WindowEvent::ActivationTokenDone { serial, token } => todo!(),
|
||||
WindowEvent::Resized(physical_size) => {
|
||||
self.app.on_resize(physical_size);
|
||||
},
|
||||
WindowEvent::Moved(physical_position) => {
|
||||
let mut state = self.app.world.get_resource_or_else(WindowState::new);
|
||||
state.position = IVec2::new(physical_position.x, physical_position.y);
|
||||
},
|
||||
WindowEvent::CloseRequested => {
|
||||
self.app.on_exit();
|
||||
event_loop.exit();
|
||||
},
|
||||
WindowEvent::Destroyed => todo!(),
|
||||
WindowEvent::DroppedFile(path_buf) => todo!(),
|
||||
WindowEvent::HoveredFile(path_buf) => todo!(),
|
||||
WindowEvent::HoveredFileCancelled => todo!(),
|
||||
WindowEvent::Focused(focused) => {
|
||||
let mut state = self.app.world.get_resource_or_else(WindowState::new);
|
||||
state.focused = focused;
|
||||
},
|
||||
WindowEvent::ModifiersChanged(modifiers) => debug!("modifiers changed: {:?}", modifiers),
|
||||
WindowEvent::ScaleFactorChanged { scale_factor, inner_size_writer } => {
|
||||
info!("changed scale to {scale_factor}");
|
||||
},
|
||||
WindowEvent::ThemeChanged(theme) => todo!(),
|
||||
WindowEvent::Occluded(occ) => {
|
||||
let mut state = self.app.world.get_resource_or_else(WindowState::new);
|
||||
state.occluded = occ;
|
||||
},
|
||||
WindowEvent::RedrawRequested => {
|
||||
debug!("should redraw");
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue