Redraw map as separate system instead of in many places

This commit is contained in:
Tobias Berger 2022-11-08 22:18:51 +01:00
parent a38cafc7b8
commit ec5011a443
Signed by: toby
GPG key ID: 2D05EFAB764D6A88
8 changed files with 108 additions and 158 deletions

View file

@ -1,11 +1,7 @@
#[cfg(feature = "render")] #[cfg(feature = "render")]
use { use {
crate::{BiomeStats, TerrainCell, WorldOverlay, WorldRenderSettings, WorldView}, crate::{BiomeStats, TerrainCell, WorldOverlay, WorldRenderSettings, WorldView},
bevy::{ bevy::render::color::Color,
asset::Assets,
render::render_resource::Extent3d,
render::{color::Color, texture::Image},
},
}; };
use { use {
crate::{World, WorldGenError}, crate::{World, WorldGenError},
@ -124,12 +120,7 @@ impl WorldManager {
} }
} }
pub fn load_world<P: AsRef<Path>>( pub fn load_world<P: AsRef<Path>>(&mut self, path: P) -> Result<(), LoadError> {
&mut self,
path: P,
#[cfg(feature = "render")] render_settings: &WorldRenderSettings,
#[cfg(feature = "render")] images: &mut Assets<Image>,
) -> Result<(), LoadError> {
let mut file = match File::open(path) { let mut file = match File::open(path) {
Ok(file) => file, Ok(file) => file,
Err(err) => { Err(err) => {
@ -145,25 +136,7 @@ impl WorldManager {
}; };
match ron::from_str(buf.as_str()) { match ron::from_str(buf.as_str()) {
Ok(world) => { Ok(world) => {
#[cfg(feature = "render")]
let World { height, width, .. } = world;
self.world = Some(world); self.world = Some(world);
#[cfg(feature = "render")]
{
let image_handle = &images.get_handle(
render_settings
.map_image_handle_id
.expect("Missing image handle, even though world is present"),
);
images
.get_mut(image_handle)
.expect("Handle for missing image")
.resize(Extent3d {
width,
height,
depth_or_array_layers: 0,
});
}
Ok(()) Ok(())
}, },
Err(err) => Err(LoadError::InvalidSave(err)), Err(err) => Err(LoadError::InvalidSave(err)),

View file

@ -6,34 +6,4 @@ pub(crate) use window::*;
pub(crate) mod widgets; pub(crate) mod widgets;
pub(crate) mod windows; pub(crate) mod windows;
use { use crate::gui::{open_window, WidgetId, WidgetSystem};
crate::gui::{open_window, WidgetId, WidgetSystem},
bevy::{
asset::Assets,
log::debug,
render::{render_resource::Extent3d, texture::Image},
},
planet::{WorldManager, WorldRenderSettings},
};
pub(crate) fn update_textures(
world_manager: &WorldManager,
render_settings: &WorldRenderSettings,
images: &mut Assets<Image>,
) {
debug!("refreshing world texture");
let map_image_handle = images.get_handle(
render_settings
.map_image_handle_id
.expect("No map image handle"),
);
let map_image = images
.get_mut(&map_image_handle)
.expect("Map image handle pointing to non-existing image");
map_image.resize(Extent3d {
width: world_manager.world().width,
height: world_manager.world().height,
depth_or_array_layers: 1,
});
map_image.data = world_manager.map_color_bytes(render_settings);
}

View file

@ -2,16 +2,14 @@ use {
crate::{ crate::{
gui::{ gui::{
open_window, open_window,
update_textures,
windows::{SaveLoad, WorldOverlaySelection, WorldViewSelection}, windows::{SaveLoad, WorldOverlaySelection, WorldViewSelection},
WidgetId, WidgetId,
WidgetSystem, WidgetSystem,
}, },
macros::iterable_enum, macros::iterable_enum,
resources::OpenedWindows, resources::{OpenedWindows, ShouldRedraw},
}, },
bevy::{ bevy::{
asset::Assets,
ecs::{ ecs::{
change_detection::Mut, change_detection::Mut,
component::Component, component::Component,
@ -19,10 +17,9 @@ use {
world::World, world::World,
}, },
log::debug, log::debug,
render::texture::Image,
}, },
bevy_egui::egui::{Layout, Ui}, bevy_egui::egui::{Layout, Ui},
planet::{WorldManager, WorldRenderSettings}, planet::WorldManager,
std::marker::PhantomData, std::marker::PhantomData,
}; };
@ -36,26 +33,19 @@ iterable_enum!(ToolbarButton {
impl ToolbarButton { impl ToolbarButton {
fn clicked(self, world: &mut World) { fn clicked(self, world: &mut World) {
world.resource_scope(|world, mut world_manager: Mut<'_, WorldManager>| { world.resource_scope(|world, mut world_manager: Mut<'_, WorldManager>| {
world.resource_scope(|world, render_settings: Mut<'_, WorldRenderSettings>| {
match self { match self {
ToolbarButton::GenerateWorld => { ToolbarButton::GenerateWorld => {
if let Err(err) = world_manager.new_world() { if let Err(err) = world_manager.new_world() {
eprintln!("Failed to generate world: {}", err); eprintln!("Failed to generate world: {}", err);
} else { } else {
update_textures( world.resource_mut::<ShouldRedraw>().0 = true;
&world_manager,
&render_settings,
&mut world.resource_mut::<Assets<Image>>(),
);
} }
}, },
ToolbarButton::SaveLoad => { ToolbarButton::SaveLoad => {
open_window::<SaveLoad>(&mut world.resource_mut::<OpenedWindows>()); open_window::<SaveLoad>(&mut world.resource_mut::<OpenedWindows>());
}, },
ToolbarButton::Views => { ToolbarButton::Views => {
open_window::<WorldViewSelection>( open_window::<WorldViewSelection>(&mut world.resource_mut::<OpenedWindows>());
&mut world.resource_mut::<OpenedWindows>(),
);
}, },
ToolbarButton::Overlays => { ToolbarButton::Overlays => {
open_window::<WorldOverlaySelection>( open_window::<WorldOverlaySelection>(
@ -64,7 +54,6 @@ impl ToolbarButton {
}, },
}; };
}); });
});
} }
} }

View file

@ -1,5 +1,5 @@
use { use {
crate::gui::WindowSystem, crate::{gui::WindowSystem, resources::ShouldRedraw},
bevy::{ bevy::{
ecs::{ ecs::{
change_detection::Mut, change_detection::Mut,
@ -7,10 +7,9 @@ use {
world::World, world::World,
}, },
log::error, log::error,
prelude::{Assets, Image},
}, },
bevy_egui::egui::Ui, bevy_egui::egui::Ui,
planet::{WorldManager, WorldRenderSettings}, planet::WorldManager,
std::marker::PhantomData, std::marker::PhantomData,
}; };
@ -24,13 +23,13 @@ pub(crate) struct SaveLoad<'w, 's> {
impl WindowSystem for SaveLoad<'_, '_> { impl WindowSystem for SaveLoad<'_, '_> {
fn draw_contents(world: &mut World, state: &mut SystemState<Self>, ui: &mut Ui) { fn draw_contents(world: &mut World, state: &mut SystemState<Self>, ui: &mut Ui) {
world.resource_scope(|world, mut world_manager: Mut<WorldManager>| { world.resource_scope(|world, mut world_manager: Mut<WorldManager>| {
world.resource_scope(|world, mut images: Mut<Assets<Image>>| { world.resource_scope(|world, mut should_redraw: Mut<ShouldRedraw>| {
world.resource_scope(|world, render_settings: Mut<WorldRenderSettings>| {
let mut state = state.get_mut(world); let mut state = state.get_mut(world);
// TODO: File selection dialog. // TODO: Real file selection dialog.
ui.text_edit_singleline(&mut *state.file_name); ui.text_edit_singleline(&mut *state.file_name);
ui.horizontal(|ui| {
if ui.button("Save").clicked() { if ui.button("Save").clicked() {
if let Err(err) = world_manager.save_world(&*state.file_name) { if let Err(err) = world_manager.save_world(&*state.file_name) {
// TODO: Error popup // TODO: Error popup
@ -38,13 +37,11 @@ impl WindowSystem for SaveLoad<'_, '_> {
} }
} }
if ui.button("Load").clicked() { if ui.button("Load").clicked() {
if let Err(err) = world_manager.load_world( if let Err(err) = world_manager.load_world(&*state.file_name) {
&*state.file_name, // TODO: Error popup
&render_settings,
&mut images,
) {
error!("Failed to load: {err:#?}"); error!("Failed to load: {err:#?}");
} }
should_redraw.0 = true;
} }
}); });
}); });

View file

@ -1,16 +1,12 @@
use { use {
crate::gui::{update_textures, WindowSystem}, crate::{gui::WindowSystem, resources::ShouldRedraw},
bevy::{ bevy::ecs::{
asset::Assets,
ecs::{
change_detection::Mut, change_detection::Mut,
system::{SystemParam, SystemState}, system::{SystemParam, SystemState},
world::World, world::World,
}, },
render::texture::Image,
},
bevy_egui::egui::Ui, bevy_egui::egui::Ui,
planet::{WorldManager, WorldOverlay, WorldRenderSettings}, planet::{WorldOverlay, WorldRenderSettings},
std::marker::PhantomData, std::marker::PhantomData,
}; };
@ -32,13 +28,7 @@ impl WindowSystem for WorldOverlaySelection<'_, '_> {
.clicked() .clicked()
{ {
render_settings.toggle_overlay(overlay); render_settings.toggle_overlay(overlay);
world.resource_scope(|world, mut images: Mut<Assets<Image>>| { world.resource_mut::<ShouldRedraw>().0 = true;
update_textures(
world.resource::<WorldManager>(),
&render_settings,
&mut images,
);
});
} }
} }
}); });

View file

@ -1,16 +1,12 @@
use { use {
crate::gui::{update_textures, WindowSystem}, crate::{gui::WindowSystem, resources::ShouldRedraw},
bevy::{ bevy::ecs::{
asset::Assets,
ecs::{
change_detection::Mut, change_detection::Mut,
system::{SystemParam, SystemState}, system::{SystemParam, SystemState},
world::World, world::World,
}, },
render::texture::Image,
},
bevy_egui::egui::Ui, bevy_egui::egui::Ui,
planet::{WorldManager, WorldRenderSettings, WorldView}, planet::{WorldRenderSettings, WorldView},
std::marker::PhantomData, std::marker::PhantomData,
}; };
@ -32,13 +28,7 @@ impl WindowSystem for WorldViewSelection<'_, '_> {
&& render_settings.view != view && render_settings.view != view
{ {
render_settings.view = view; render_settings.view = view;
world.resource_scope(|world, mut images: Mut<Assets<Image>>| { world.resource_mut::<ShouldRedraw>().0 = true;
update_textures(
world.resource::<WorldManager>(),
&render_settings,
&mut images,
);
});
} }
} }
}); });

View file

@ -8,11 +8,6 @@ pub(crate) mod plugins;
#[cfg(feature = "render")] #[cfg(feature = "render")]
pub(crate) mod resources; pub(crate) mod resources;
#[cfg(all(feature = "render", feature = "logging"))]
use {
bevy::diagnostic::{Diagnostics, FrameTimeDiagnosticsPlugin},
bevy_egui::egui::Frame,
};
use { use {
bevy::{ bevy::{
app::App, app::App,
@ -37,7 +32,13 @@ use {
prelude::Vec2, prelude::Vec2,
render::{ render::{
camera::{Camera, RenderTarget}, camera::{Camera, RenderTarget},
render_resource::{TextureDescriptor, TextureDimension, TextureFormat, TextureUsages}, render_resource::{
Extent3d,
TextureDescriptor,
TextureDimension,
TextureFormat,
TextureUsages,
},
texture::{Image, ImageSettings}, texture::{Image, ImageSettings},
}, },
sprite::{Sprite, SpriteBundle}, sprite::{Sprite, SpriteBundle},
@ -50,16 +51,17 @@ use {
EguiContext, EguiContext,
}, },
components::panning::Pan2d, components::panning::Pan2d,
gui::{ gui::{render_windows, widget, widgets::ToolbarWidget, window::open_window, windows::TileInfo},
render_windows,
update_textures,
widget,
widgets::ToolbarWidget,
window::open_window,
windows::TileInfo,
},
planet::WorldRenderSettings, planet::WorldRenderSettings,
resources::{CursorMapPosition, OpenedWindows}, resources::{CursorMapPosition, OpenedWindows, ShouldRedraw},
};
#[cfg(all(feature = "render", feature = "logging"))]
use {
bevy::{
diagnostic::{Diagnostics, FrameTimeDiagnosticsPlugin},
log::debug,
},
bevy_egui::egui::Frame,
}; };
#[cfg(feature = "render")] #[cfg(feature = "render")]
@ -159,8 +161,6 @@ fn generate_graphics(
..default() ..default()
}); });
} }
update_textures(&world_manager, &render_settings, &mut images);
} }
#[cfg(feature = "render")] #[cfg(feature = "render")]
@ -203,6 +203,38 @@ fn update_gui(world: &mut World) {
}); });
} }
#[cfg(feature = "render")]
fn redraw_map(
mut should_redraw: ResMut<ShouldRedraw>,
world_manager: Res<WorldManager>,
render_settings: Res<'_, WorldRenderSettings>,
mut images: ResMut<Assets<Image>>,
) {
if should_redraw.0 {
let world_manager: &WorldManager = &world_manager;
let render_settings: &WorldRenderSettings = &render_settings;
let images: &mut Assets<Image> = &mut images;
#[cfg(feature = "logging")]
debug!("refreshing world texture");
let map_image_handle = images.get_handle(
render_settings
.map_image_handle_id
.expect("No map image handle"),
);
let map_image = images
.get_mut(&map_image_handle)
.expect("Map image handle pointing to non-existing image");
map_image.resize(Extent3d {
width: world_manager.world().width,
height: world_manager.world().height,
depth_or_array_layers: 1,
});
map_image.data = world_manager.map_color_bytes(render_settings);
should_redraw.0 = false;
}
}
#[cfg(feature = "render")] #[cfg(feature = "render")]
const WORLD_SCALE: i32 = 4; const WORLD_SCALE: i32 = 4;
fn main() -> Result<(), Box<dyn std::error::Error>> { fn main() -> Result<(), Box<dyn std::error::Error>> {
@ -225,10 +257,12 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
.insert_resource(CursorMapPosition::default()) .insert_resource(CursorMapPosition::default())
.insert_resource(OpenedWindows::default()) .insert_resource(OpenedWindows::default())
.insert_resource(WorldRenderSettings::default()) .insert_resource(WorldRenderSettings::default())
.insert_resource(ShouldRedraw::default())
.add_startup_system(generate_graphics) .add_startup_system(generate_graphics)
.add_system(update_gui.exclusive_system()) .add_system(update_gui.exclusive_system())
.add_system(update_cursor_map_position) .add_system(update_cursor_map_position)
.add_system(open_tile_info); .add_system(open_tile_info)
.add_system(redraw_map);
} }
#[cfg(not(feature = "render"))] #[cfg(not(feature = "render"))]
{ {

View file

@ -11,6 +11,13 @@ impl Display for CursorMapPosition {
} }
} }
pub(crate) struct ShouldRedraw(pub(crate) bool);
impl Default for ShouldRedraw {
fn default() -> Self {
Self(true)
}
}
#[derive(Default)] #[derive(Default)]
pub(crate) struct OpenedWindows(HashSet<WindowId>); pub(crate) struct OpenedWindows(HashSet<WindowId>);