diff --git a/planet/src/world_manager.rs b/planet/src/world_manager.rs index 3ab09e3..df9698c 100644 --- a/planet/src/world_manager.rs +++ b/planet/src/world_manager.rs @@ -162,28 +162,10 @@ impl WorldManager { self.world.as_ref() } - #[must_use] - pub fn world(&self) -> &World { - assert!(self.world.is_some(), "No world."); - self.get_world().unwrap() - } - - pub fn set_world(&mut self, world: World) { + pub fn set_world(&mut self, world: World) { self.world = Some(world); } - pub fn new_world(&mut self, seed: Option) -> Result<&World, WorldGenError> { - let seed = seed.unwrap_or_else(random); - let mut new_world = World::new( - WorldManager::NEW_WORLD_WIDTH, - WorldManager::NEW_WORLD_HEIGHT, - seed, - ); - new_world.generate()?; - self.world = Some(new_world); - Ok(self.get_world().unwrap()) - } - pub fn new_world_async(&mut self, seed: Option) -> Task> { AsyncComputeTaskPool::get().spawn(async move { let seed = seed.unwrap_or_else(random); diff --git a/src/gui/windows/tile_info.rs b/src/gui/windows/tile_info.rs index 4e1add7..d50ee14 100644 --- a/src/gui/windows/tile_info.rs +++ b/src/gui/windows/tile_info.rs @@ -25,11 +25,14 @@ impl WindowSystem for TileInfo<'_, '_> { let cursor_y = cursor_position.y; let cursor_x = cursor_position.x; - let world_manager = world.resource::(); + let Some(world) = world.resource::().get_world() else { + ui.label("No world."); + return; + }; if cursor_x >= 0 - && cursor_x < world_manager.world().width.try_into().unwrap() + && cursor_x < world.width.try_into().unwrap() && cursor_y >= 0 - && cursor_y < world_manager.world().height.try_into().unwrap() + && cursor_y < world.height.try_into().unwrap() { let TerrainCell { altitude, @@ -38,7 +41,7 @@ impl WindowSystem for TileInfo<'_, '_> { biome_presences, x, y, - } = &world_manager.world().terrain[cursor_y as usize][cursor_x as usize]; + } = &world.terrain[cursor_y as usize][cursor_x as usize]; _ = ui.label("Coordinates"); _ = ui.label(format!("{x}:{y}")); diff --git a/src/main.rs b/src/main.rs index ff8c76d..7417e5e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -42,6 +42,9 @@ fn update_cursor_map_position( windows: Res<'_, Windows>, world_manager: Res<'_, WorldManager>, ) { + let Some(world) = world_manager.get_world() else { + return + }; let (camera, transform) = transform.single(); let window = match camera.target { @@ -61,7 +64,6 @@ fn update_cursor_map_position( let world_position = ndc_to_world.project_point3(ndc.extend(-1.0)).truncate() / WORLD_SCALE as f32; - let world = world_manager.world(); cursor_map_position.x = world.width as i32 / 2 + f32::ceil(world_position.x) as i32 - 1; cursor_map_position.y = world.height as i32 / 2 + f32::ceil(world_position.y) as i32 - 1; } @@ -74,7 +76,7 @@ fn handle_generate_world_task( ) { if let Some(task) = &mut generate_world_task.0 { if task.is_finished() { - debug!("Done"); + debug!("Done generating world"); if let Some(result) = block_on(poll_once(task)) { match result { Ok(world) => { @@ -82,6 +84,8 @@ fn handle_generate_world_task( #[cfg(feature = "render")] { should_redraw.0 = true; + #[cfg(feature = "logging")] + debug!("Requesting map redraw"); } }, Err(err) => error!("{err:#?}"), @@ -89,7 +93,7 @@ fn handle_generate_world_task( } generate_world_task.0 = None; } else { - debug!("Working") + debug!("Still generating world") } } } @@ -97,13 +101,11 @@ fn handle_generate_world_task( #[cfg(feature = "render")] fn generate_graphics( mut commands: Commands<'_, '_>, - world_manager: ResMut<'_, WorldManager>, images: ResMut<'_, Assets>, egui_context: ResMut<'_, EguiContext>, render_settings: ResMut<'_, WorldRenderSettings>, ) { // Add Julia-Mono font to egui - { let egui_context = egui_context.into_inner(); let ctx = egui_context.ctx_mut(); @@ -126,19 +128,15 @@ fn generate_graphics( ctx.set_fonts(fonts); let mut style = (*ctx.style()).clone(); + // Make all text 33% bigger because I have bad eyes (and the font is small) for style in style.text_styles.iter_mut() { style.1.size *= 16.0 / 12.0; } ctx.set_style(style); - #[cfg(feature = "logging")] - debug!("Fonts: {:#?}", &ctx.style().text_styles); + // #[cfg(feature = "logging")] + // debug!("Fonts: {:#?}", &ctx.style().text_styles); } - let world = world_manager.world(); - let custom_sprite_size = Vec2 { - x: (WORLD_SCALE * world.width as i32) as f32, - y: (WORLD_SCALE * world.height as i32) as f32, - }; // Set up 2D map mode { use bevy::render::render_resource::{ @@ -150,7 +148,7 @@ fn generate_graphics( let images = images.into_inner(); let mut render_settings = render_settings.into_inner(); let map_image_handle = images.add(Image { - data: vec![], + data: vec![0; 16], texture_descriptor: TextureDescriptor { label: None, size: default(), @@ -167,12 +165,7 @@ fn generate_graphics( // TODO: Switch to egui _ = commands.spawn(SpriteBundle { - texture: images - .get_handle(unsafe { render_settings.map_image_handle_id.unwrap_unchecked() }), - sprite: Sprite { - custom_size: Some(custom_sprite_size), - ..default() - }, + texture: images.get_handle(render_settings.map_image_handle_id.unwrap()), ..default() }); } @@ -224,7 +217,17 @@ fn redraw_map( world_manager: Res, render_settings: Res<'_, WorldRenderSettings>, mut images: ResMut>, + mut map_sprite: Query<'_, '_, &mut Sprite>, ) { + let Some(world) = world_manager.get_world() else { + #[cfg(feature = "logging")] + if should_redraw.0 { + debug!("Couldn't redraw map despite wanting to, because world isn't generated"); + } + return; + }; + assert!(world.width > 0); + if should_redraw.0 { let world_manager: &WorldManager = &world_manager; let render_settings: &WorldRenderSettings = &render_settings; @@ -239,60 +242,61 @@ fn redraw_map( let map_image = images .get_mut(&map_image_handle) .expect("Map image handle pointing to non-existing image"); + #[cfg(feature = "logging")] + debug!("Resizing image to {}x{}", world.width, world.height); map_image.resize(bevy::render::render_resource::Extent3d { - width: world_manager.world().width, - height: world_manager.world().height, - depth_or_array_layers: 1, + width: world.width, + height: world.height, + ..default() }); map_image.data = world_manager.map_color_bytes(render_settings); + map_sprite.single_mut().custom_size = Some(Vec2 { + x: (world.width * WORLD_SCALE as u32) as f32, + y: (world.height * WORLD_SCALE as u32) as f32, + }); should_redraw.0 = false; } } #[cfg(feature = "render")] -const WORLD_SCALE: i32 = 2; +const WORLD_SCALE: i32 = 4; fn main() -> Result<(), Box> { let mut app = App::new(); - let mut manager = WorldManager::new(); #[cfg(feature = "render")] { - use bevy::winit::WinitSettings; + use bevy::winit::{UpdateMode, WinitSettings}; - let world = manager.new_world(Some(0))?; _ = app - .insert_resource(WinitSettings::game()) + .insert_resource(WinitSettings { + focused_mode: UpdateMode::Continuous, + unfocused_mode: UpdateMode::ReactiveLowPower { + max_wait: std::time::Duration::from_secs(10), + }, + ..default() + }) .insert_resource(CursorMapPosition::default()) .insert_resource(OpenedWindows::default()) .insert_resource(WorldRenderSettings::default()) .insert_resource(ShouldRedraw::default()) - .insert_resource(GenerateWorldTask::default()) .add_startup_system(generate_graphics) .add_system(update_gui) .add_system(update_cursor_map_position) .add_system(open_tile_info) .add_system(redraw_map); - app.add_plugins(WorldPlugins.set(WindowPlugin { - window: WindowDescriptor { - width: (WORLD_SCALE * world.width as i32) as f32, - height: (WORLD_SCALE * world.height as i32) as f32, - title: String::from("World-RS"), - resizable: true, - ..default() - }, - ..default() - })); + app.add_plugins(WorldPlugins); } #[cfg(not(feature = "render"))] { - _ = manager.new_world(Some(0))?; - app.add_plugins(WorldPlugins); } - app.add_system(handle_generate_world_task) - .insert_resource(manager) + app.insert_resource(WorldManager::new()) + .insert_resource(GenerateWorldTask( + /* Some(manager.new_world_async(Some(0))) */ None, + )) + .add_system(handle_generate_world_task) .run(); Ok(()) diff --git a/src/planet_renderer.rs b/src/planet_renderer.rs index fb0ba86..d2d8a50 100644 --- a/src/planet_renderer.rs +++ b/src/planet_renderer.rs @@ -173,7 +173,10 @@ pub(crate) trait WorldRenderer { impl WorldRenderer for WorldManager { #[must_use] fn map_color_bytes(&self, render_settings: &WorldRenderSettings) -> Vec { - self.world() + let Some(world) = self.get_world() else { + return vec![]; + }; + world .terrain .iter() .rev() @@ -190,10 +193,11 @@ impl WorldRenderer for WorldManager { #[must_use] fn generate_color(&self, cell: &TerrainCell, render_settings: &WorldRenderSettings) -> Color { + let world = self.get_world().expect("No world in generate_color"); let base_color = match render_settings.view { - WorldView::Biomes => biome_color(self.world(), cell), - WorldView::Topography => altitude_contour_color(self.world(), cell.altitude), - WorldView::Coastlines => coastline_color(self.world(), cell), + WorldView::Biomes => biome_color(world, cell), + WorldView::Topography => altitude_contour_color(world, cell.altitude), + WorldView::Coastlines => coastline_color(world, cell), }; let mut normalizer = 1.0; diff --git a/src/plugins/world_plugins.rs b/src/plugins/world_plugins.rs index b29180c..1d880dc 100644 --- a/src/plugins/world_plugins.rs +++ b/src/plugins/world_plugins.rs @@ -46,7 +46,16 @@ impl PluginGroup for WorldPlugins { group_builder = group_builder .add(TransformPlugin) .add(InputPlugin) - .add(WindowPlugin::default()) + .add(WindowPlugin { + window: WindowDescriptor { + width: 1600.0, + height: 800.0, + title: String::from("World-RS"), + resizable: true, + ..default() + }, + ..default() + }) .add(AssetPlugin::default()) .add(RenderPlugin) .add(ImagePlugin::default_nearest()) diff --git a/src/resources/mod.rs b/src/resources/mod.rs index 2e54c1b..57cf392 100644 --- a/src/resources/mod.rs +++ b/src/resources/mod.rs @@ -19,15 +19,8 @@ impl Display for CursorMapPosition { } #[cfg(feature = "render")] -#[derive(Resource)] +#[derive(Resource, Default)] pub(crate) struct ShouldRedraw(pub(crate) bool); -#[cfg(feature = "render")] -impl Default for ShouldRedraw { - fn default() -> Self { - Self(true) - } -} - #[cfg(feature = "render")] #[derive(Default, Resource)] pub(crate) struct OpenedWindows(HashSet);