use winit::{
event::*,
event::Event as WinitEvent,
platform::run_return::EventLoopExtRunReturn,
};
use crate::render::{
backend::window::WindowBuilder,
renderer::Renderer,
pbr::material::*,
};
#[cfg(feature = "egui")]
use crate::render::ui::GuiContext;
use crate::assets::*;
use crate::ecs::*;
use crate::physics::*;
use crate::time::*;
pub mod error;
pub mod assets;
pub mod math;
pub mod ecs;
pub mod time;
pub mod render;
pub mod physics;
pub mod scripting;
pub mod prelude;
pub use crate::error::Result;
pub struct Despero {
world: World,
systems: ScheduleBuilder,
setup_systems: ScheduleBuilder,
#[cfg(feature = "egui")]
egui_ctx: EventHandler<GuiContext>,
app_exit: EventHandler<AppExit>,
physics_handler: PhysicsHandler,
time_handler: Time,
renderer: Renderer,
asset_manager: AssetManager,
}
impl Despero {
pub fn init(window_builder: WindowBuilder) -> Despero {
init_logger();
let mut renderer = Renderer::init(window_builder).expect("Cannot create renderer");
renderer.bind_material::<DefaultMat>();
Despero {
world: World::new(),
setup_systems: Schedule::builder(),
systems: Schedule::builder(),
#[cfg(feature = "egui")]
egui_ctx: EventHandler::<GuiContext>::new(),
app_exit: EventHandler::<AppExit>::new(),
physics_handler: PhysicsHandler::new(),
time_handler: Time::new(),
renderer,
asset_manager: AssetManager::new(),
}
}
pub fn add_system<Args, Ret, S>(mut self, system: S) -> Self
where
S: 'static + System<Args, Ret> + Send,
{
self.systems.add_system(system);
self
}
pub fn add_setup_system<Args, Ret, S>(mut self, system: S) -> Self
where
S: 'static + System<Args, Ret> + Send,
{
self.setup_systems.add_system(system);
self
}
pub fn default_systems(mut self) -> Self {
self.setup_systems
.add_system(main_setup);
self.systems
.add_system(update_models_system)
.add_system(rendering_system)
.add_system(time_system)
.add_system(update_lights)
.add_system(update_physics)
.add_system(generate_textures);
return self;
}
pub fn run(mut self) {
let mut setup_systems = self.setup_systems.build();
let mut systems = self.systems.build();
setup_systems.execute((
&mut self.world,
&mut self.renderer,
#[cfg(feature = "egui")]
&mut self.egui_ctx,
&mut self.app_exit,
&mut self.time_handler,
&mut self.physics_handler,
&mut self.asset_manager,
)).expect("Cannot execute setup schedule");
let event_loop = (&self.renderer.window.event_loop).clone();
(*event_loop.lock().unwrap()).run_return(move |event, _, controlflow| match event {
WinitEvent::WindowEvent { event, window_id: _ } => {
#[cfg(feature = "egui")]
let _response = self.renderer.egui.handle_event(&event);
match event {
WindowEvent::CloseRequested => {
*controlflow = winit::event_loop::ControlFlow::Exit;
}
_ => (),
}
}
WinitEvent::NewEvents(StartCause::Init) => {
unsafe { self.renderer.recreate_swapchain().expect("Cannot recreate swapchain"); }
log::debug!("Recreated swapchain");
}
WinitEvent::MainEventsCleared => {
self.renderer.window.request_redraw();
if let Some(_) = self.app_exit.read() {
*controlflow = winit::event_loop::ControlFlow::Exit;
}
}
WinitEvent::RedrawRequested(_) => {
systems.execute((
&mut self.world,
&mut self.renderer,
#[cfg(feature = "egui")]
&mut self.egui_ctx,
&mut self.app_exit,
&mut self.time_handler,
&mut self.physics_handler,
&mut self.asset_manager,
)).expect("Cannot execute loop schedule");
self.world.clear_trackers();
}
_ => {}
});
}
}
impl Drop for Despero {
fn drop(&mut self) {
self.asset_manager.cleanup(&mut self.renderer);
self.renderer.cleanup(&mut self.world);
}
}
fn init_logger() {
#[cfg(debug_assertions)]
pretty_env_logger::formatted_builder()
.filter_level(
env_logger::filter::Builder::new()
.parse(&std::env::var("DESPERO_LOG").unwrap_or(String::from("DESPERO_LOG=debug")))
.build()
.filter()
)
.init();
#[cfg(not(debug_assertions))]
pretty_env_logger::formatted_builder()
.filter_level(
env_logger::filter::Builder::new()
.parse(&std::env::var("DESPERO_LOG").unwrap_or(String::from("DESPERO_LOG=info")))
.build()
.filter()
)
.init();
}