mod window; mod ui; mod tacmap; mod wgpuctx; mod eguictx; mod vertex; mod texture; mod canvas; mod solar_system; mod known_stars; mod timeman; use std::cell::RefCell; use std::thread; use std::time::{Duration, Instant}; use serde::de; use winit::event::{KeyEvent, WindowEvent}; use winit::event_loop::{EventLoop, ActiveEventLoop, ControlFlow}; use winit::error::{EventLoopError}; use winit::application::{ApplicationHandler}; use winit::keyboard::PhysicalKey; use winit::window::{Window, WindowId, WindowAttributes}; use solar_system::*; use crate::timeman::TimeMan; use crate::window::GameWindow; const TARGET_FPS: f32 = 100.0; const TARGET_DT: Duration = Duration::from_millis((1000.0 / TARGET_FPS) as u64); struct SystemicApp { window: Option, wgpu_instance: wgpu::Instance, last_render_time: Instant, game_state: Option> } struct GameState { timeman: TimeMan, solar_systems: Vec } impl SystemicApp { fn create_window( &mut self, event_loop: &ActiveEventLoop) { self.window = Some(GameWindow::new( &self.wgpu_instance, event_loop).unwrap()); self.game_state = Some(RefCell::new(GameState::new())); } } impl GameState { pub fn new() -> Self { let timeman = TimeMan::new(0); let mut sol_system = match SolarSystem::new_from_known_star(0, "sol") { Ok(system) => system, Err(e) => panic!("Unable to create sol system : {}", e) }; sol_system.update(timeman.seconds()); Self { timeman: timeman, solar_systems: vec![ sol_system ] } } pub fn solar_systems(&self) -> &[SolarSystem] { self.solar_systems.as_slice() } pub fn timeman(&self) -> &TimeMan { &self.timeman } pub fn timeman_mut(&mut self) -> &mut TimeMan { &mut self.timeman } fn update( &mut self, dt: Duration) { let ticks = self.timeman.update(); ticks.iter().for_each(|time| { solar_system::update_systems(self.solar_systems.iter_mut(), *time); }); } } impl ApplicationHandler for SystemicApp { fn resumed( &mut self, event_loop: &ActiveEventLoop ) { match self.window { Some(_) => {} None => self.create_window(event_loop) } } fn window_event( &mut self, event_loop: &ActiveEventLoop, window_id: WindowId, event: winit::event::WindowEvent, ) { let window = match &mut self.window { Some(w) => w, None => return }; let game_state = match &self.game_state { Some(state) => state, None => return }; window.on_event(&event); match event { WindowEvent::CloseRequested => { event_loop.exit(); } WindowEvent::Resized(size) => { window.resize(size.width, size.height); } WindowEvent::RedrawRequested => { let now = Instant::now(); let delta_time = now - self.last_render_time; self.last_render_time = now; game_state.borrow_mut().update(delta_time); window.update(game_state, delta_time); match window.render(game_state) { Ok(_) => {} Err(wgpu::SurfaceError::Outdated | wgpu::SurfaceError::Lost) => { let size = window.size(); window.resize(size.width, size.height); }, Err(e) => { log::error!("Unable to render: {}", e); } } if delta_time < TARGET_DT { thread::sleep(TARGET_DT - delta_time); } } WindowEvent::KeyboardInput { event: KeyEvent { physical_key: PhysicalKey::Code(key_code), state: key_state, .. }, .. } => { window.keyboard_input(key_code, key_state); } _ => {} } } } // impl ApplicationHandler for SystemicApp fn main() -> Result<(), EventLoopError> { env_logger::init(); let event_loop = EventLoop::new().unwrap(); event_loop.set_control_flow(ControlFlow::Poll); let mut app = SystemicApp { window: None, wgpu_instance: wgpu::Instance::default(), last_render_time: Instant::now(), game_state: None }; event_loop.run_app(&mut app) }