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")]
use {
crate::{BiomeStats, TerrainCell, WorldOverlay, WorldRenderSettings, WorldView},
bevy::{
asset::Assets,
render::render_resource::Extent3d,
render::{color::Color, texture::Image},
},
bevy::render::color::Color,
};
use {
crate::{World, WorldGenError},
@ -124,12 +120,7 @@ impl WorldManager {
}
}
pub fn load_world<P: AsRef<Path>>(
&mut self,
path: P,
#[cfg(feature = "render")] render_settings: &WorldRenderSettings,
#[cfg(feature = "render")] images: &mut Assets<Image>,
) -> Result<(), LoadError> {
pub fn load_world<P: AsRef<Path>>(&mut self, path: P) -> Result<(), LoadError> {
let mut file = match File::open(path) {
Ok(file) => file,
Err(err) => {
@ -145,25 +136,7 @@ impl WorldManager {
};
match ron::from_str(buf.as_str()) {
Ok(world) => {
#[cfg(feature = "render")]
let World { height, width, .. } = 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(())
},
Err(err) => Err(LoadError::InvalidSave(err)),

View file

@ -6,34 +6,4 @@ pub(crate) use window::*;
pub(crate) mod widgets;
pub(crate) mod windows;
use {
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);
}
use crate::gui::{open_window, WidgetId, WidgetSystem};

View file

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

View file

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

View file

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

View file

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

View file

@ -8,11 +8,6 @@ pub(crate) mod plugins;
#[cfg(feature = "render")]
pub(crate) mod resources;
#[cfg(all(feature = "render", feature = "logging"))]
use {
bevy::diagnostic::{Diagnostics, FrameTimeDiagnosticsPlugin},
bevy_egui::egui::Frame,
};
use {
bevy::{
app::App,
@ -37,7 +32,13 @@ use {
prelude::Vec2,
render::{
camera::{Camera, RenderTarget},
render_resource::{TextureDescriptor, TextureDimension, TextureFormat, TextureUsages},
render_resource::{
Extent3d,
TextureDescriptor,
TextureDimension,
TextureFormat,
TextureUsages,
},
texture::{Image, ImageSettings},
},
sprite::{Sprite, SpriteBundle},
@ -50,16 +51,17 @@ use {
EguiContext,
},
components::panning::Pan2d,
gui::{
render_windows,
update_textures,
widget,
widgets::ToolbarWidget,
window::open_window,
windows::TileInfo,
},
gui::{render_windows, widget, widgets::ToolbarWidget, window::open_window, windows::TileInfo},
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")]
@ -159,8 +161,6 @@ fn generate_graphics(
..default()
});
}
update_textures(&world_manager, &render_settings, &mut images);
}
#[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")]
const WORLD_SCALE: i32 = 4;
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(OpenedWindows::default())
.insert_resource(WorldRenderSettings::default())
.insert_resource(ShouldRedraw::default())
.add_startup_system(generate_graphics)
.add_system(update_gui.exclusive_system())
.add_system(update_cursor_map_position)
.add_system(open_tile_info);
.add_system(open_tile_info)
.add_system(redraw_map);
}
#[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)]
pub(crate) struct OpenedWindows(HashSet<WindowId>);