pub mod ui; mod window { pub use super::ui; } use std::cell::RefCell; use std::sync::{Arc}; use std::time::Duration; use winit::event::{ElementState, WindowEvent}; use winit::keyboard::KeyCode; use crate::tacmap::TacticalMap; use crate::{GameState, SystemicApp}; use crate::solar_system::{SolarSystem, SystemId}; use crate::wgpuctx::{RenderPassBuilder, WgpuCtx}; use crate::eguictx::EguiCtx; use ui::*; pub struct GameWindow { window: Arc, wgpuctx: WgpuCtx, eguictx: EguiCtx, tactical_map: TacticalMap, ui_state: GameWindowUiState } impl GameWindow { pub fn new( instance: &wgpu::Instance, event_loop: &winit::event_loop::ActiveEventLoop) -> Result { let window_attrs = winit::window::Window::default_attributes() .with_title("Systemic 4X") .with_inner_size(winit::dpi::LogicalSize::new(640, 480)); let window = Arc::new(event_loop.create_window(window_attrs).unwrap()); let wgpuctx = pollster::block_on(WgpuCtx::new(instance, window.clone())); let eguictx = EguiCtx::new(&window, &wgpuctx); let tacmap = TacticalMap::new( &wgpuctx, winit::dpi::LogicalPosition::new(0.0, 0.0), winit::dpi::LogicalSize::new(1.0, 1.0)); Ok(Self { window: window, wgpuctx: wgpuctx, eguictx: eguictx, tactical_map: tacmap, ui_state: Default::default() }) } pub fn update( &mut self, game_state: &RefCell, dt: Duration) { self.tactical_map.update(game_state, &mut self.ui_state, dt); } pub fn keyboard_input( &mut self, game_state: &RefCell, key_code: KeyCode, key_state: ElementState) { self.tactical_map.keyboard_input(game_state, key_code, key_state); } pub fn render( &mut self, game_state: &RefCell) -> Result<(), wgpu::SurfaceError> { if !self.wgpuctx.is_ready() { return Ok(()); } self.tactical_map.draw( &self.wgpuctx, game_state, self.ui_state.current_system)?; let mut encoder = self.wgpuctx.create_default_encoder("Systemic window command encoder"); let view = self.wgpuctx.prepare_surface(&wgpu::TextureViewDescriptor::default())?; { let mut pass = RenderPassBuilder::new("Systemic window render pass", &view) .clear_color(wgpu::Color { r: 1.0, g: 1.0, b: 1.0, a: 1.0 }) .build(&mut encoder); //Draw the tactical map canvas. self.tactical_map.present(&mut pass)?; } { self.eguictx.prepare(&self.window); self.ui_state = GameWindowUiState::render(&self.ui_state, game_state, &self.eguictx); self.eguictx.present( &self.window, &self.wgpuctx, &mut encoder, &view); } self.wgpuctx.submit_encoder(encoder); self.wgpuctx.present_surface(); self.window.request_redraw(); Ok(()) } pub fn on_event( &mut self, event: &WindowEvent) { if self.eguictx.window_event(&self.window, event).consumed { return; } } pub fn resize( &mut self, width: u32, height: u32 ) { if width > 0 && height > 0 { self.wgpuctx.resize(width, height); self.tactical_map.resize(&self.wgpuctx, width, height); self.window.request_redraw(); } } pub fn size( &self) -> winit::dpi::PhysicalSize { self.window.inner_size() } }