Add more windows, move rendering logic
This commit is contained in:
parent
23eed81343
commit
a38cafc7b8
14 changed files with 321 additions and 174 deletions
|
@ -6,7 +6,7 @@ cargo build --no-default-features --features=logging &&
|
|||
echo "Debug-build with features: render" &&
|
||||
cargo build --no-default-features --features=render &&
|
||||
echo "Debug-build with features: logging render" &&
|
||||
cargo build --no-default-features --features=logging,render &&
|
||||
cargo build --no-default-features --features="logging,render" &&
|
||||
echo "Release-build with features: minimal"
|
||||
cargo build --release --no-default-features --features= &&
|
||||
echo "Release-build with features: logging" &&
|
||||
|
@ -14,5 +14,5 @@ cargo build --release --no-default-features --features=logging &&
|
|||
echo "Release-build with features: render" &&
|
||||
cargo build --release --no-default-features --features=render &&
|
||||
echo "Release-build with features: logging render" &&
|
||||
cargo build --release --no-default-features --features=logging,render &&
|
||||
cargo build --release --no-default-features --features="logging,render" &&
|
||||
echo "Done!"
|
|
@ -41,4 +41,8 @@ pub use world_manager::WorldManager;
|
|||
pub(crate) mod macros;
|
||||
pub mod math_util;
|
||||
pub mod perlin;
|
||||
#[cfg(feature = "render")]
|
||||
pub mod rendering;
|
||||
#[cfg(feature = "render")]
|
||||
pub use rendering::*;
|
||||
pub mod saving;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
macro_rules! iterable_enum {
|
||||
($Name:ident { $($Variant:ident),*$(,)? }) =>
|
||||
{
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, serde::Deserialize, serde::Serialize)]
|
||||
pub enum $Name {
|
||||
$($Variant),*,
|
||||
}
|
||||
|
@ -13,6 +13,20 @@ macro_rules! iterable_enum {
|
|||
$Name::ITEMS.iter()
|
||||
}
|
||||
}
|
||||
impl From<$Name> for &'static str {
|
||||
fn from(value: $Name) -> &'static str {
|
||||
match value {
|
||||
$($Name::$Variant => stringify!($Variant),)*
|
||||
}
|
||||
}
|
||||
}
|
||||
impl From<&$Name> for &'static str {
|
||||
fn from(value: &$Name) -> &'static str {
|
||||
match value {
|
||||
$($Name::$Variant => stringify!($Variant),)*
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
pub(crate) use iterable_enum;
|
||||
|
|
45
planet/src/rendering/mod.rs
Normal file
45
planet/src/rendering/mod.rs
Normal file
|
@ -0,0 +1,45 @@
|
|||
#[cfg(feature = "render")]
|
||||
use bevy::asset::HandleId;
|
||||
use {crate::macros::iterable_enum, bevy::utils::HashSet};
|
||||
|
||||
iterable_enum!(WorldView { Biomes, Topography });
|
||||
iterable_enum!(WorldOverlay {
|
||||
Temperature,
|
||||
Rainfall
|
||||
});
|
||||
|
||||
#[cfg(feature = "render")]
|
||||
#[derive(Debug, Default)]
|
||||
pub struct WorldRenderSettings {
|
||||
pub map_image_handle_id: Option<HandleId>,
|
||||
|
||||
visible_overlays: HashSet<WorldOverlay>,
|
||||
pub view: WorldView,
|
||||
}
|
||||
|
||||
#[cfg(feature = "render")]
|
||||
impl WorldRenderSettings {
|
||||
pub fn overlay_visible(&self, overlay: &WorldOverlay) -> bool {
|
||||
self.visible_overlays.contains(overlay)
|
||||
}
|
||||
|
||||
pub fn toggle_overlay(&mut self, overlay: &WorldOverlay) {
|
||||
if self.visible_overlays.contains(overlay) {
|
||||
assert!(
|
||||
self.visible_overlays.remove(overlay),
|
||||
"Failed to remove overlay [{overlay:#?}], that shouldn't happen."
|
||||
);
|
||||
} else {
|
||||
assert!(
|
||||
self.visible_overlays.insert(*overlay),
|
||||
"Failed to insert overlay [{overlay:#?}], that shouldn't happen."
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for WorldView {
|
||||
fn default() -> Self {
|
||||
WorldView::Biomes
|
||||
}
|
||||
}
|
|
@ -1,7 +1,14 @@
|
|||
#[cfg(all(feature = "logging", feature = "render"))]
|
||||
use bevy::log::debug;
|
||||
#[cfg(feature = "render")]
|
||||
use {
|
||||
crate::{macros::iterable_enum, World, WorldGenError},
|
||||
crate::{BiomeStats, TerrainCell, WorldOverlay, WorldRenderSettings, WorldView},
|
||||
bevy::{
|
||||
asset::Assets,
|
||||
render::render_resource::Extent3d,
|
||||
render::{color::Color, texture::Image},
|
||||
},
|
||||
};
|
||||
use {
|
||||
crate::{World, WorldGenError},
|
||||
bevy::{log::warn, utils::default},
|
||||
rand::random,
|
||||
std::{
|
||||
|
@ -12,15 +19,6 @@ use {
|
|||
path::Path,
|
||||
},
|
||||
};
|
||||
#[cfg(feature = "render")]
|
||||
use {
|
||||
crate::{BiomeStats, TerrainCell},
|
||||
bevy::{
|
||||
asset::{Assets, HandleId},
|
||||
render::render_resource::Extent3d,
|
||||
render::{color::Color, texture::Image},
|
||||
},
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum LoadError {
|
||||
|
@ -85,71 +83,9 @@ impl Display for SaveError {
|
|||
}
|
||||
}
|
||||
|
||||
iterable_enum!(PlanetView { Biomes, Altitude });
|
||||
|
||||
#[cfg(feature = "render")]
|
||||
#[derive(Debug, Default)]
|
||||
pub struct WorldRenderSettings {
|
||||
pub map_image_handle_id: Option<HandleId>,
|
||||
|
||||
rainfall_visible: bool,
|
||||
temperature_visible: bool,
|
||||
view: PlanetView,
|
||||
}
|
||||
|
||||
#[cfg(feature = "render")]
|
||||
impl WorldRenderSettings {
|
||||
#[cfg(feature = "render")]
|
||||
pub fn toggle_rainfall(&mut self) {
|
||||
#[cfg(feature = "logging")]
|
||||
if self.rainfall_visible {
|
||||
debug!("Turning rainfall off");
|
||||
} else {
|
||||
debug!("Turning rainfall on");
|
||||
}
|
||||
self.rainfall_visible = !self.rainfall_visible;
|
||||
}
|
||||
|
||||
#[cfg(feature = "render")]
|
||||
pub fn toggle_temperature(&mut self) {
|
||||
#[cfg(feature = "logging")]
|
||||
if self.temperature_visible {
|
||||
debug!("Turning temperature off");
|
||||
} else {
|
||||
debug!("Turning temperature on");
|
||||
}
|
||||
self.temperature_visible = !self.temperature_visible;
|
||||
}
|
||||
|
||||
#[cfg(feature = "render")]
|
||||
pub fn cycle_view(&mut self) {
|
||||
let idx = (PlanetView::iterator()
|
||||
.position(|view| *view == self.view)
|
||||
.unwrap()
|
||||
+ 1)
|
||||
% PlanetView::ITEM_COUNT;
|
||||
#[cfg(feature = "logging")]
|
||||
debug!(
|
||||
"Cycling view from {:#?} to {:#?}",
|
||||
self.view,
|
||||
PlanetView::ITEMS[idx]
|
||||
);
|
||||
self.view = PlanetView::ITEMS[idx];
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for PlanetView {
|
||||
fn default() -> Self {
|
||||
PlanetView::Biomes
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct WorldManager {
|
||||
world: Option<World>,
|
||||
|
||||
#[cfg(feature = "render")]
|
||||
pub render_settings: WorldRenderSettings,
|
||||
}
|
||||
|
||||
impl WorldManager {
|
||||
|
@ -191,6 +127,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> {
|
||||
let mut file = match File::open(path) {
|
||||
|
@ -214,7 +151,7 @@ impl WorldManager {
|
|||
#[cfg(feature = "render")]
|
||||
{
|
||||
let image_handle = &images.get_handle(
|
||||
self.render_settings
|
||||
render_settings
|
||||
.map_image_handle_id
|
||||
.expect("Missing image handle, even though world is present"),
|
||||
);
|
||||
|
@ -264,8 +201,8 @@ impl WorldManager {
|
|||
|
||||
#[cfg(feature = "render")]
|
||||
#[must_use]
|
||||
fn generate_color(&self, cell: &TerrainCell) -> Color {
|
||||
if self.render_settings.view == PlanetView::Biomes {
|
||||
fn generate_color(&self, cell: &TerrainCell, render_settings: &WorldRenderSettings) -> Color {
|
||||
if render_settings.view == WorldView::Biomes {
|
||||
return WorldManager::biome_color(cell);
|
||||
}
|
||||
|
||||
|
@ -282,7 +219,7 @@ impl WorldManager {
|
|||
let mut green = altitude_color.g();
|
||||
let mut blue = altitude_color.b();
|
||||
|
||||
if self.render_settings.rainfall_visible {
|
||||
if render_settings.overlay_visible(&WorldOverlay::Rainfall) {
|
||||
layer_count += 1.0;
|
||||
let rainfall_color = self.rainfall_contour_color(cell.rainfall);
|
||||
// if self.contours {
|
||||
|
@ -296,7 +233,7 @@ impl WorldManager {
|
|||
blue += rainfall_color.b();
|
||||
}
|
||||
|
||||
if self.render_settings.temperature_visible {
|
||||
if render_settings.overlay_visible(&WorldOverlay::Temperature) {
|
||||
layer_count += 1.0;
|
||||
let temperature_color = self.temperature_contour_color(cell.temperature);
|
||||
// if self.contours {
|
||||
|
@ -399,14 +336,14 @@ impl WorldManager {
|
|||
|
||||
#[cfg(feature = "render")]
|
||||
#[must_use]
|
||||
pub fn map_color_bytes(&self) -> Vec<u8> {
|
||||
pub fn map_color_bytes(&self, render_settings: &WorldRenderSettings) -> Vec<u8> {
|
||||
self.world()
|
||||
.terrain
|
||||
.iter()
|
||||
.rev()
|
||||
.flatten()
|
||||
.flat_map(|cell| {
|
||||
self.generate_color(cell)
|
||||
self.generate_color(cell, render_settings)
|
||||
.as_rgba_f32()
|
||||
.iter()
|
||||
.flat_map(|num| num.to_le_bytes())
|
||||
|
|
|
@ -10,18 +10,20 @@ use {
|
|||
crate::gui::{open_window, WidgetId, WidgetSystem},
|
||||
bevy::{
|
||||
asset::Assets,
|
||||
ecs::change_detection::Mut,
|
||||
log::debug,
|
||||
render::{render_resource::Extent3d, texture::Image},
|
||||
},
|
||||
planet::WorldManager,
|
||||
planet::{WorldManager, WorldRenderSettings},
|
||||
};
|
||||
|
||||
fn update_textures(world_manager: &WorldManager, images: &mut Mut<Assets<Image>>) {
|
||||
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(
|
||||
world_manager
|
||||
.render_settings
|
||||
render_settings
|
||||
.map_image_handle_id
|
||||
.expect("No map image handle"),
|
||||
);
|
||||
|
@ -33,5 +35,5 @@ fn update_textures(world_manager: &WorldManager, images: &mut Mut<Assets<Image>>
|
|||
height: world_manager.world().height,
|
||||
depth_or_array_layers: 1,
|
||||
});
|
||||
map_image.data = world_manager.map_color_bytes();
|
||||
map_image.data = world_manager.map_color_bytes(render_settings);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,12 @@
|
|||
use {
|
||||
crate::{
|
||||
gui::{open_window, update_textures, windows::Overlay, WidgetId, WidgetSystem},
|
||||
gui::{
|
||||
open_window,
|
||||
update_textures,
|
||||
windows::{SaveLoad, WorldOverlaySelection, WorldViewSelection},
|
||||
WidgetId,
|
||||
WidgetSystem,
|
||||
},
|
||||
macros::iterable_enum,
|
||||
resources::OpenedWindows,
|
||||
},
|
||||
|
@ -16,50 +22,48 @@ use {
|
|||
render::texture::Image,
|
||||
},
|
||||
bevy_egui::egui::{Layout, Ui},
|
||||
planet::WorldManager,
|
||||
planet::{WorldManager, WorldRenderSettings},
|
||||
std::marker::PhantomData,
|
||||
};
|
||||
|
||||
iterable_enum!(ToolbarButton {
|
||||
GenerateWorld,
|
||||
SaveWorld,
|
||||
LoadWorld,
|
||||
SaveLoad,
|
||||
Views,
|
||||
Overlays,
|
||||
ToggleBiomes,
|
||||
});
|
||||
|
||||
impl ToolbarButton {
|
||||
fn clicked(self, world: &mut World) {
|
||||
world.resource_scope(|world, mut world_manager: Mut<'_, WorldManager>| {
|
||||
match self {
|
||||
ToolbarButton::GenerateWorld => {
|
||||
if let Err(err) = world_manager.new_world() {
|
||||
eprintln!("Failed to generate world: {}", err);
|
||||
} else {
|
||||
update_textures(&world_manager, &mut world.resource_mut::<Assets<Image>>());
|
||||
}
|
||||
},
|
||||
ToolbarButton::SaveWorld => {
|
||||
if let Err(err) = world_manager.save_world("planet.ron") {
|
||||
eprintln!("Failed to save planet.ron: {}", err);
|
||||
}
|
||||
},
|
||||
ToolbarButton::LoadWorld => {
|
||||
let mut images = world.resource_mut::<Assets<Image>>();
|
||||
if let Err(err) = world_manager.load_world("planet.ron", &mut images) {
|
||||
eprintln!("Failed to load planet.ron: {}", err);
|
||||
} else {
|
||||
update_textures(&world_manager, &mut images);
|
||||
}
|
||||
},
|
||||
ToolbarButton::Overlays => {
|
||||
open_window::<Overlay>(&mut world.resource_mut::<OpenedWindows>());
|
||||
},
|
||||
ToolbarButton::ToggleBiomes => {
|
||||
world_manager.render_settings.cycle_view();
|
||||
update_textures(&world_manager, &mut world.resource_mut::<Assets<Image>>());
|
||||
},
|
||||
};
|
||||
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>(),
|
||||
);
|
||||
},
|
||||
};
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -67,11 +71,10 @@ impl ToolbarButton {
|
|||
impl From<ToolbarButton> for &'static str {
|
||||
fn from(button: ToolbarButton) -> Self {
|
||||
match button {
|
||||
ToolbarButton::Views => "Change view",
|
||||
ToolbarButton::Overlays => "Overlays",
|
||||
ToolbarButton::ToggleBiomes => "Toggle biome view",
|
||||
ToolbarButton::GenerateWorld => "Generate new world",
|
||||
ToolbarButton::SaveWorld => "Save",
|
||||
ToolbarButton::LoadWorld => "Load",
|
||||
ToolbarButton::SaveLoad => "Save/Load",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,10 +21,13 @@ pub(crate) trait WindowSystem: SystemParam {
|
|||
}
|
||||
|
||||
pub(crate) fn render_windows(world: &mut World, ctx: &Context) {
|
||||
// TODO: Windows are hard-coded here instead of being iterable.
|
||||
// Is that good enough? Probably, yea.
|
||||
window::<windows::Overlay>(world, ctx);
|
||||
// TODO: Windows are hard-coded here instead of being iterable, and allows
|
||||
// creating new windows that are never rendered.
|
||||
// Is that good enough?
|
||||
window::<windows::TileInfo>(world, ctx);
|
||||
window::<windows::WorldViewSelection>(world, ctx);
|
||||
window::<windows::WorldOverlaySelection>(world, ctx);
|
||||
window::<windows::SaveLoad>(world, ctx);
|
||||
}
|
||||
|
||||
pub(crate) fn open_window<S: 'static + WindowSystem>(windows: &mut OpenedWindows) {
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
mod overlay;
|
||||
pub(crate) use overlay::Overlay;
|
||||
mod tile_info;
|
||||
pub(crate) use tile_info::TileInfo;
|
||||
mod world_view_selection;
|
||||
pub(crate) use world_view_selection::WorldViewSelection;
|
||||
mod world_overlay_selection;
|
||||
pub(crate) use world_overlay_selection::WorldOverlaySelection;
|
||||
mod save_load;
|
||||
pub(crate) use save_load::SaveLoad;
|
|
@ -1,25 +0,0 @@
|
|||
use {
|
||||
crate::gui::WindowSystem,
|
||||
bevy::ecs::{
|
||||
system::{SystemParam, SystemState},
|
||||
world::World,
|
||||
},
|
||||
bevy_egui::egui::Ui,
|
||||
std::marker::PhantomData,
|
||||
};
|
||||
|
||||
#[derive(SystemParam)]
|
||||
pub(crate) struct Overlay<'w, 's> {
|
||||
#[system_param(ignore)]
|
||||
_phantom: PhantomData<(&'w (), &'s ())>,
|
||||
}
|
||||
|
||||
impl WindowSystem for Overlay<'_, '_> {
|
||||
fn draw_contents(world: &mut World, _state: &mut SystemState<Self>, ui: &mut Ui) {
|
||||
ui.label(format!("{world:#?}"));
|
||||
}
|
||||
|
||||
fn name() -> &'static str {
|
||||
"Overlay Selection"
|
||||
}
|
||||
}
|
57
src/gui/windows/save_load.rs
Normal file
57
src/gui/windows/save_load.rs
Normal file
|
@ -0,0 +1,57 @@
|
|||
use {
|
||||
crate::gui::WindowSystem,
|
||||
bevy::{
|
||||
ecs::{
|
||||
change_detection::Mut,
|
||||
system::{Local, SystemParam, SystemState},
|
||||
world::World,
|
||||
},
|
||||
log::error,
|
||||
prelude::{Assets, Image},
|
||||
},
|
||||
bevy_egui::egui::Ui,
|
||||
planet::{WorldManager, WorldRenderSettings},
|
||||
std::marker::PhantomData,
|
||||
};
|
||||
|
||||
#[derive(SystemParam)]
|
||||
pub(crate) struct SaveLoad<'w, 's> {
|
||||
pub file_name: Local<'s, String>,
|
||||
#[system_param(ignore)]
|
||||
_phantom: PhantomData<(&'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);
|
||||
|
||||
// TODO: File selection dialog.
|
||||
ui.text_edit_singleline(&mut *state.file_name);
|
||||
|
||||
if ui.button("Save").clicked() {
|
||||
if let Err(err) = world_manager.save_world(&*state.file_name) {
|
||||
// TODO: Error popup
|
||||
error!("Failed to save: {err:#?}");
|
||||
}
|
||||
}
|
||||
if ui.button("Load").clicked() {
|
||||
if let Err(err) = world_manager.load_world(
|
||||
&*state.file_name,
|
||||
&render_settings,
|
||||
&mut images,
|
||||
) {
|
||||
error!("Failed to load: {err:#?}");
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
fn name() -> &'static str {
|
||||
"Save/Load world"
|
||||
}
|
||||
}
|
50
src/gui/windows/world_overlay_selection.rs
Normal file
50
src/gui/windows/world_overlay_selection.rs
Normal file
|
@ -0,0 +1,50 @@
|
|||
use {
|
||||
crate::gui::{update_textures, WindowSystem},
|
||||
bevy::{
|
||||
asset::Assets,
|
||||
ecs::{
|
||||
change_detection::Mut,
|
||||
system::{SystemParam, SystemState},
|
||||
world::World,
|
||||
},
|
||||
render::texture::Image,
|
||||
},
|
||||
bevy_egui::egui::Ui,
|
||||
planet::{WorldManager, WorldOverlay, WorldRenderSettings},
|
||||
std::marker::PhantomData,
|
||||
};
|
||||
|
||||
#[derive(SystemParam)]
|
||||
pub(crate) struct WorldOverlaySelection<'w, 's> {
|
||||
#[system_param(ignore)]
|
||||
_phantom: PhantomData<(&'w (), &'s ())>,
|
||||
}
|
||||
|
||||
impl WindowSystem for WorldOverlaySelection<'_, '_> {
|
||||
fn draw_contents(world: &mut World, _state: &mut SystemState<Self>, ui: &mut Ui) {
|
||||
world.resource_scope(|world, mut render_settings: Mut<WorldRenderSettings>| {
|
||||
for overlay in WorldOverlay::iterator() {
|
||||
if ui
|
||||
.selectable_label(
|
||||
render_settings.overlay_visible(overlay),
|
||||
<&'static str>::from(overlay),
|
||||
)
|
||||
.clicked()
|
||||
{
|
||||
render_settings.toggle_overlay(overlay);
|
||||
world.resource_scope(|world, mut images: Mut<Assets<Image>>| {
|
||||
update_textures(
|
||||
world.resource::<WorldManager>(),
|
||||
&render_settings,
|
||||
&mut images,
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn name() -> &'static str {
|
||||
"Overlay Selection"
|
||||
}
|
||||
}
|
50
src/gui/windows/world_view_selection.rs
Normal file
50
src/gui/windows/world_view_selection.rs
Normal file
|
@ -0,0 +1,50 @@
|
|||
use {
|
||||
crate::gui::{update_textures, WindowSystem},
|
||||
bevy::{
|
||||
asset::Assets,
|
||||
ecs::{
|
||||
change_detection::Mut,
|
||||
system::{SystemParam, SystemState},
|
||||
world::World,
|
||||
},
|
||||
render::texture::Image,
|
||||
},
|
||||
bevy_egui::egui::Ui,
|
||||
planet::{WorldManager, WorldRenderSettings, WorldView},
|
||||
std::marker::PhantomData,
|
||||
};
|
||||
|
||||
#[derive(SystemParam)]
|
||||
pub(crate) struct WorldViewSelection<'w, 's> {
|
||||
#[system_param(ignore)]
|
||||
_phantom: PhantomData<(&'w (), &'s ())>,
|
||||
}
|
||||
|
||||
impl WindowSystem for WorldViewSelection<'_, '_> {
|
||||
fn draw_contents(world: &mut World, _state: &mut SystemState<Self>, ui: &mut Ui) {
|
||||
world.resource_scope(|world, mut render_settings: Mut<WorldRenderSettings>| {
|
||||
let current_selection = render_settings.view;
|
||||
for view in WorldView::iterator() {
|
||||
let view = *view;
|
||||
if ui
|
||||
.selectable_label(view == current_selection, <&'static str>::from(view))
|
||||
.clicked()
|
||||
&& 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,
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn name() -> &'static str {
|
||||
"View Selection"
|
||||
}
|
||||
}
|
37
src/main.rs
37
src/main.rs
|
@ -1,3 +1,5 @@
|
|||
#![cfg_attr(not(feature = "logging"), windows_subsystem = "windows")]
|
||||
|
||||
pub(crate) mod components;
|
||||
#[cfg(feature = "render")]
|
||||
pub(crate) mod gui;
|
||||
|
@ -35,13 +37,7 @@ use {
|
|||
prelude::Vec2,
|
||||
render::{
|
||||
camera::{Camera, RenderTarget},
|
||||
render_resource::{
|
||||
Extent3d,
|
||||
TextureDescriptor,
|
||||
TextureDimension,
|
||||
TextureFormat,
|
||||
TextureUsages,
|
||||
},
|
||||
render_resource::{TextureDescriptor, TextureDimension, TextureFormat, TextureUsages},
|
||||
texture::{Image, ImageSettings},
|
||||
},
|
||||
sprite::{Sprite, SpriteBundle},
|
||||
|
@ -54,7 +50,15 @@ use {
|
|||
EguiContext,
|
||||
},
|
||||
components::panning::Pan2d,
|
||||
gui::{render_windows, widget, widgets::ToolbarWidget, window::open_window, windows::TileInfo},
|
||||
gui::{
|
||||
render_windows,
|
||||
update_textures,
|
||||
widget,
|
||||
widgets::ToolbarWidget,
|
||||
window::open_window,
|
||||
windows::TileInfo,
|
||||
},
|
||||
planet::WorldRenderSettings,
|
||||
resources::{CursorMapPosition, OpenedWindows},
|
||||
};
|
||||
|
||||
|
@ -93,9 +97,10 @@ fn update_cursor_map_position(
|
|||
#[cfg(feature = "render")]
|
||||
fn generate_graphics(
|
||||
mut commands: Commands<'_, '_>,
|
||||
mut world_manager: ResMut<'_, WorldManager>,
|
||||
world_manager: ResMut<'_, WorldManager>,
|
||||
mut images: ResMut<'_, Assets<Image>>,
|
||||
mut egui_context: ResMut<'_, EguiContext>,
|
||||
mut render_settings: ResMut<'_, WorldRenderSettings>,
|
||||
) {
|
||||
// Add Julia-Mono font to egui
|
||||
{
|
||||
|
@ -127,14 +132,10 @@ fn generate_graphics(
|
|||
// Set up 2D map mode
|
||||
{
|
||||
let map_image_handle = images.add(Image {
|
||||
data: world_manager.map_color_bytes(),
|
||||
data: vec![],
|
||||
texture_descriptor: TextureDescriptor {
|
||||
label: None,
|
||||
size: Extent3d {
|
||||
width: world.width,
|
||||
height: world.height,
|
||||
..default()
|
||||
},
|
||||
size: default(),
|
||||
dimension: TextureDimension::D2,
|
||||
format: TextureFormat::Rgba32Float,
|
||||
mip_level_count: 1,
|
||||
|
@ -143,14 +144,14 @@ fn generate_graphics(
|
|||
},
|
||||
..default()
|
||||
});
|
||||
world_manager.render_settings.map_image_handle_id = Some(map_image_handle.id);
|
||||
render_settings.map_image_handle_id = Some(map_image_handle.id);
|
||||
_ = commands
|
||||
.spawn_bundle(Camera2dBundle::default())
|
||||
.insert(Pan2d::new());
|
||||
|
||||
// TODO: Switch to egui
|
||||
_ = commands.spawn_bundle(SpriteBundle {
|
||||
texture: images.get_handle(world_manager.render_settings.map_image_handle_id.unwrap()),
|
||||
texture: images.get_handle(map_image_handle.id),
|
||||
sprite: Sprite {
|
||||
custom_size: Some(custom_sprite_size),
|
||||
..default()
|
||||
|
@ -159,6 +160,7 @@ fn generate_graphics(
|
|||
});
|
||||
}
|
||||
|
||||
update_textures(&world_manager, &render_settings, &mut images);
|
||||
}
|
||||
|
||||
#[cfg(feature = "render")]
|
||||
|
@ -222,6 +224,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
})
|
||||
.insert_resource(CursorMapPosition::default())
|
||||
.insert_resource(OpenedWindows::default())
|
||||
.insert_resource(WorldRenderSettings::default())
|
||||
.add_startup_system(generate_graphics)
|
||||
.add_system(update_gui.exclusive_system())
|
||||
.add_system(update_cursor_map_position)
|
||||
|
|
Loading…
Reference in a new issue