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, ui}; use crate::solar_system::{SolarSystem, SystemId}; use crate::wgpuctx::{RenderPassBuilder, SceneCtx, WgpuCtx}; use crate::eguictx::EguiCtx; pub struct GameWindow { window: Arc, wgpuctx: WgpuCtx, eguictx: EguiCtx, tactical_map: TacticalMap, ui_state: ui::State } 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)); let ui_state = ui::State{ current_system: Some(0), camera_info: ui::camera_info::CameraWindowState { target: Some(0), ..Default::default() }, ..Default::default() }; Ok(Self { window: window, wgpuctx: wgpuctx, eguictx: eguictx, tactical_map: tacmap, ui_state: ui_state }) } pub fn update( &mut self, game_state: &RefCell, dt: Duration) { let mut game_state = game_state.borrow_mut(); if self.ui_state.do_auto_tick { game_state.timeman.auto_tick = self.ui_state.auto_time; }else{ game_state.timeman.auto_tick = None; } let current_system = match self.ui_state.current_system { Some(id) => &game_state.solar_systems()[id], None => { return; } }; self.tactical_map.update(current_system, &mut self.ui_state, dt); } pub fn keyboard_input( &mut self, key_code: KeyCode, key_state: ElementState) { self.tactical_map.keyboard_input(key_code, key_state); } pub fn render( &mut self, game_state: &RefCell) -> Result<(), wgpu::SurfaceError> { if !self.wgpuctx.is_ready() { return Ok(()); } if self.ui_state.current_system.is_some() { let game_state = game_state.borrow(); let current_system = &game_state.solar_systems()[self.ui_state.current_system.unwrap()]; self.tactical_map.draw( &self.wgpuctx, current_system, game_state.timeman())?; } let view = self.wgpuctx.prepare_surface(&wgpu::TextureViewDescriptor::default())?; let mut scene = SceneCtx::from_view_default(&self.wgpuctx, &view, Some("Systemic window scene")); { let mut pass = RenderPassBuilder::new(Some("Systemic window render pass"), &view) .clear_color(wgpu::Color { r: 0.0, g: 0.0, b: 0.0, a: 1.0 }) .build_from_scene(&mut scene); //Draw the tactical map canvas. self.tactical_map.present(&mut pass)?; } { self.eguictx.prepare(&self.window); self.ui_state.render(game_state, &self.eguictx); self.eguictx.present( &self.window, &self.wgpuctx, scene.encoder_mut(), &view); } scene.submit(&self.wgpuctx); 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() } }