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" &&
|
echo "Debug-build with features: render" &&
|
||||||
cargo build --no-default-features --features=render &&
|
cargo build --no-default-features --features=render &&
|
||||||
echo "Debug-build with features: logging 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"
|
echo "Release-build with features: minimal"
|
||||||
cargo build --release --no-default-features --features= &&
|
cargo build --release --no-default-features --features= &&
|
||||||
echo "Release-build with features: logging" &&
|
echo "Release-build with features: logging" &&
|
||||||
|
@ -14,5 +14,5 @@ cargo build --release --no-default-features --features=logging &&
|
||||||
echo "Release-build with features: render" &&
|
echo "Release-build with features: render" &&
|
||||||
cargo build --release --no-default-features --features=render &&
|
cargo build --release --no-default-features --features=render &&
|
||||||
echo "Release-build with features: logging 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!"
|
echo "Done!"
|
|
@ -41,4 +41,8 @@ pub use world_manager::WorldManager;
|
||||||
pub(crate) mod macros;
|
pub(crate) mod macros;
|
||||||
pub mod math_util;
|
pub mod math_util;
|
||||||
pub mod perlin;
|
pub mod perlin;
|
||||||
|
#[cfg(feature = "render")]
|
||||||
|
pub mod rendering;
|
||||||
|
#[cfg(feature = "render")]
|
||||||
|
pub use rendering::*;
|
||||||
pub mod saving;
|
pub mod saving;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
macro_rules! iterable_enum {
|
macro_rules! iterable_enum {
|
||||||
($Name:ident { $($Variant:ident),*$(,)? }) =>
|
($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 {
|
pub enum $Name {
|
||||||
$($Variant),*,
|
$($Variant),*,
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,20 @@ macro_rules! iterable_enum {
|
||||||
$Name::ITEMS.iter()
|
$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;
|
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"))]
|
#[cfg(feature = "render")]
|
||||||
use bevy::log::debug;
|
|
||||||
use {
|
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},
|
bevy::{log::warn, utils::default},
|
||||||
rand::random,
|
rand::random,
|
||||||
std::{
|
std::{
|
||||||
|
@ -12,15 +19,6 @@ use {
|
||||||
path::Path,
|
path::Path,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
#[cfg(feature = "render")]
|
|
||||||
use {
|
|
||||||
crate::{BiomeStats, TerrainCell},
|
|
||||||
bevy::{
|
|
||||||
asset::{Assets, HandleId},
|
|
||||||
render::render_resource::Extent3d,
|
|
||||||
render::{color::Color, texture::Image},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum LoadError {
|
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)]
|
#[derive(Debug, Default)]
|
||||||
pub struct WorldManager {
|
pub struct WorldManager {
|
||||||
world: Option<World>,
|
world: Option<World>,
|
||||||
|
|
||||||
#[cfg(feature = "render")]
|
|
||||||
pub render_settings: WorldRenderSettings,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WorldManager {
|
impl WorldManager {
|
||||||
|
@ -191,6 +127,7 @@ impl WorldManager {
|
||||||
pub fn load_world<P: AsRef<Path>>(
|
pub fn load_world<P: AsRef<Path>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
path: P,
|
path: P,
|
||||||
|
#[cfg(feature = "render")] render_settings: &WorldRenderSettings,
|
||||||
#[cfg(feature = "render")] images: &mut Assets<Image>,
|
#[cfg(feature = "render")] images: &mut Assets<Image>,
|
||||||
) -> Result<(), LoadError> {
|
) -> Result<(), LoadError> {
|
||||||
let mut file = match File::open(path) {
|
let mut file = match File::open(path) {
|
||||||
|
@ -214,7 +151,7 @@ impl WorldManager {
|
||||||
#[cfg(feature = "render")]
|
#[cfg(feature = "render")]
|
||||||
{
|
{
|
||||||
let image_handle = &images.get_handle(
|
let image_handle = &images.get_handle(
|
||||||
self.render_settings
|
render_settings
|
||||||
.map_image_handle_id
|
.map_image_handle_id
|
||||||
.expect("Missing image handle, even though world is present"),
|
.expect("Missing image handle, even though world is present"),
|
||||||
);
|
);
|
||||||
|
@ -264,8 +201,8 @@ impl WorldManager {
|
||||||
|
|
||||||
#[cfg(feature = "render")]
|
#[cfg(feature = "render")]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
fn generate_color(&self, cell: &TerrainCell) -> Color {
|
fn generate_color(&self, cell: &TerrainCell, render_settings: &WorldRenderSettings) -> Color {
|
||||||
if self.render_settings.view == PlanetView::Biomes {
|
if render_settings.view == WorldView::Biomes {
|
||||||
return WorldManager::biome_color(cell);
|
return WorldManager::biome_color(cell);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -282,7 +219,7 @@ impl WorldManager {
|
||||||
let mut green = altitude_color.g();
|
let mut green = altitude_color.g();
|
||||||
let mut blue = altitude_color.b();
|
let mut blue = altitude_color.b();
|
||||||
|
|
||||||
if self.render_settings.rainfall_visible {
|
if render_settings.overlay_visible(&WorldOverlay::Rainfall) {
|
||||||
layer_count += 1.0;
|
layer_count += 1.0;
|
||||||
let rainfall_color = self.rainfall_contour_color(cell.rainfall);
|
let rainfall_color = self.rainfall_contour_color(cell.rainfall);
|
||||||
// if self.contours {
|
// if self.contours {
|
||||||
|
@ -296,7 +233,7 @@ impl WorldManager {
|
||||||
blue += rainfall_color.b();
|
blue += rainfall_color.b();
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.render_settings.temperature_visible {
|
if render_settings.overlay_visible(&WorldOverlay::Temperature) {
|
||||||
layer_count += 1.0;
|
layer_count += 1.0;
|
||||||
let temperature_color = self.temperature_contour_color(cell.temperature);
|
let temperature_color = self.temperature_contour_color(cell.temperature);
|
||||||
// if self.contours {
|
// if self.contours {
|
||||||
|
@ -399,14 +336,14 @@ impl WorldManager {
|
||||||
|
|
||||||
#[cfg(feature = "render")]
|
#[cfg(feature = "render")]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn map_color_bytes(&self) -> Vec<u8> {
|
pub fn map_color_bytes(&self, render_settings: &WorldRenderSettings) -> Vec<u8> {
|
||||||
self.world()
|
self.world()
|
||||||
.terrain
|
.terrain
|
||||||
.iter()
|
.iter()
|
||||||
.rev()
|
.rev()
|
||||||
.flatten()
|
.flatten()
|
||||||
.flat_map(|cell| {
|
.flat_map(|cell| {
|
||||||
self.generate_color(cell)
|
self.generate_color(cell, render_settings)
|
||||||
.as_rgba_f32()
|
.as_rgba_f32()
|
||||||
.iter()
|
.iter()
|
||||||
.flat_map(|num| num.to_le_bytes())
|
.flat_map(|num| num.to_le_bytes())
|
||||||
|
|
|
@ -10,18 +10,20 @@ use {
|
||||||
crate::gui::{open_window, WidgetId, WidgetSystem},
|
crate::gui::{open_window, WidgetId, WidgetSystem},
|
||||||
bevy::{
|
bevy::{
|
||||||
asset::Assets,
|
asset::Assets,
|
||||||
ecs::change_detection::Mut,
|
|
||||||
log::debug,
|
log::debug,
|
||||||
render::{render_resource::Extent3d, texture::Image},
|
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");
|
debug!("refreshing world texture");
|
||||||
let map_image_handle = images.get_handle(
|
let map_image_handle = images.get_handle(
|
||||||
world_manager
|
render_settings
|
||||||
.render_settings
|
|
||||||
.map_image_handle_id
|
.map_image_handle_id
|
||||||
.expect("No map image handle"),
|
.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,
|
height: world_manager.world().height,
|
||||||
depth_or_array_layers: 1,
|
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 {
|
use {
|
||||||
crate::{
|
crate::{
|
||||||
gui::{open_window, update_textures, windows::Overlay, WidgetId, WidgetSystem},
|
gui::{
|
||||||
|
open_window,
|
||||||
|
update_textures,
|
||||||
|
windows::{SaveLoad, WorldOverlaySelection, WorldViewSelection},
|
||||||
|
WidgetId,
|
||||||
|
WidgetSystem,
|
||||||
|
},
|
||||||
macros::iterable_enum,
|
macros::iterable_enum,
|
||||||
resources::OpenedWindows,
|
resources::OpenedWindows,
|
||||||
},
|
},
|
||||||
|
@ -16,62 +22,59 @@ use {
|
||||||
render::texture::Image,
|
render::texture::Image,
|
||||||
},
|
},
|
||||||
bevy_egui::egui::{Layout, Ui},
|
bevy_egui::egui::{Layout, Ui},
|
||||||
planet::WorldManager,
|
planet::{WorldManager, WorldRenderSettings},
|
||||||
std::marker::PhantomData,
|
std::marker::PhantomData,
|
||||||
};
|
};
|
||||||
|
|
||||||
iterable_enum!(ToolbarButton {
|
iterable_enum!(ToolbarButton {
|
||||||
GenerateWorld,
|
GenerateWorld,
|
||||||
SaveWorld,
|
SaveLoad,
|
||||||
LoadWorld,
|
Views,
|
||||||
Overlays,
|
Overlays,
|
||||||
ToggleBiomes,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
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_manager, &mut world.resource_mut::<Assets<Image>>());
|
update_textures(
|
||||||
|
&world_manager,
|
||||||
|
&render_settings,
|
||||||
|
&mut world.resource_mut::<Assets<Image>>(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
ToolbarButton::SaveWorld => {
|
ToolbarButton::SaveLoad => {
|
||||||
if let Err(err) = world_manager.save_world("planet.ron") {
|
open_window::<SaveLoad>(&mut world.resource_mut::<OpenedWindows>());
|
||||||
eprintln!("Failed to save planet.ron: {}", err);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
ToolbarButton::LoadWorld => {
|
ToolbarButton::Views => {
|
||||||
let mut images = world.resource_mut::<Assets<Image>>();
|
open_window::<WorldViewSelection>(
|
||||||
if let Err(err) = world_manager.load_world("planet.ron", &mut images) {
|
&mut world.resource_mut::<OpenedWindows>(),
|
||||||
eprintln!("Failed to load planet.ron: {}", err);
|
);
|
||||||
} else {
|
|
||||||
update_textures(&world_manager, &mut images);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
ToolbarButton::Overlays => {
|
ToolbarButton::Overlays => {
|
||||||
open_window::<Overlay>(&mut world.resource_mut::<OpenedWindows>());
|
open_window::<WorldOverlaySelection>(
|
||||||
},
|
&mut world.resource_mut::<OpenedWindows>(),
|
||||||
ToolbarButton::ToggleBiomes => {
|
);
|
||||||
world_manager.render_settings.cycle_view();
|
|
||||||
update_textures(&world_manager, &mut world.resource_mut::<Assets<Image>>());
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<ToolbarButton> for &'static str {
|
impl From<ToolbarButton> for &'static str {
|
||||||
fn from(button: ToolbarButton) -> Self {
|
fn from(button: ToolbarButton) -> Self {
|
||||||
match button {
|
match button {
|
||||||
|
ToolbarButton::Views => "Change view",
|
||||||
ToolbarButton::Overlays => "Overlays",
|
ToolbarButton::Overlays => "Overlays",
|
||||||
ToolbarButton::ToggleBiomes => "Toggle biome view",
|
|
||||||
ToolbarButton::GenerateWorld => "Generate new world",
|
ToolbarButton::GenerateWorld => "Generate new world",
|
||||||
ToolbarButton::SaveWorld => "Save",
|
ToolbarButton::SaveLoad => "Save/Load",
|
||||||
ToolbarButton::LoadWorld => "Load",
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,10 +21,13 @@ pub(crate) trait WindowSystem: SystemParam {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn render_windows(world: &mut World, ctx: &Context) {
|
pub(crate) fn render_windows(world: &mut World, ctx: &Context) {
|
||||||
// TODO: Windows are hard-coded here instead of being iterable.
|
// TODO: Windows are hard-coded here instead of being iterable, and allows
|
||||||
// Is that good enough? Probably, yea.
|
// creating new windows that are never rendered.
|
||||||
window::<windows::Overlay>(world, ctx);
|
// Is that good enough?
|
||||||
window::<windows::TileInfo>(world, ctx);
|
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) {
|
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;
|
mod tile_info;
|
||||||
pub(crate) use tile_info::TileInfo;
|
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;
|
pub(crate) mod components;
|
||||||
#[cfg(feature = "render")]
|
#[cfg(feature = "render")]
|
||||||
pub(crate) mod gui;
|
pub(crate) mod gui;
|
||||||
|
@ -35,13 +37,7 @@ use {
|
||||||
prelude::Vec2,
|
prelude::Vec2,
|
||||||
render::{
|
render::{
|
||||||
camera::{Camera, RenderTarget},
|
camera::{Camera, RenderTarget},
|
||||||
render_resource::{
|
render_resource::{TextureDescriptor, TextureDimension, TextureFormat, TextureUsages},
|
||||||
Extent3d,
|
|
||||||
TextureDescriptor,
|
|
||||||
TextureDimension,
|
|
||||||
TextureFormat,
|
|
||||||
TextureUsages,
|
|
||||||
},
|
|
||||||
texture::{Image, ImageSettings},
|
texture::{Image, ImageSettings},
|
||||||
},
|
},
|
||||||
sprite::{Sprite, SpriteBundle},
|
sprite::{Sprite, SpriteBundle},
|
||||||
|
@ -54,7 +50,15 @@ use {
|
||||||
EguiContext,
|
EguiContext,
|
||||||
},
|
},
|
||||||
components::panning::Pan2d,
|
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},
|
resources::{CursorMapPosition, OpenedWindows},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -93,9 +97,10 @@ fn update_cursor_map_position(
|
||||||
#[cfg(feature = "render")]
|
#[cfg(feature = "render")]
|
||||||
fn generate_graphics(
|
fn generate_graphics(
|
||||||
mut commands: Commands<'_, '_>,
|
mut commands: Commands<'_, '_>,
|
||||||
mut world_manager: ResMut<'_, WorldManager>,
|
world_manager: ResMut<'_, WorldManager>,
|
||||||
mut images: ResMut<'_, Assets<Image>>,
|
mut images: ResMut<'_, Assets<Image>>,
|
||||||
mut egui_context: ResMut<'_, EguiContext>,
|
mut egui_context: ResMut<'_, EguiContext>,
|
||||||
|
mut render_settings: ResMut<'_, WorldRenderSettings>,
|
||||||
) {
|
) {
|
||||||
// Add Julia-Mono font to egui
|
// Add Julia-Mono font to egui
|
||||||
{
|
{
|
||||||
|
@ -127,14 +132,10 @@ fn generate_graphics(
|
||||||
// Set up 2D map mode
|
// Set up 2D map mode
|
||||||
{
|
{
|
||||||
let map_image_handle = images.add(Image {
|
let map_image_handle = images.add(Image {
|
||||||
data: world_manager.map_color_bytes(),
|
data: vec![],
|
||||||
texture_descriptor: TextureDescriptor {
|
texture_descriptor: TextureDescriptor {
|
||||||
label: None,
|
label: None,
|
||||||
size: Extent3d {
|
size: default(),
|
||||||
width: world.width,
|
|
||||||
height: world.height,
|
|
||||||
..default()
|
|
||||||
},
|
|
||||||
dimension: TextureDimension::D2,
|
dimension: TextureDimension::D2,
|
||||||
format: TextureFormat::Rgba32Float,
|
format: TextureFormat::Rgba32Float,
|
||||||
mip_level_count: 1,
|
mip_level_count: 1,
|
||||||
|
@ -143,14 +144,14 @@ fn generate_graphics(
|
||||||
},
|
},
|
||||||
..default()
|
..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
|
_ = commands
|
||||||
.spawn_bundle(Camera2dBundle::default())
|
.spawn_bundle(Camera2dBundle::default())
|
||||||
.insert(Pan2d::new());
|
.insert(Pan2d::new());
|
||||||
|
|
||||||
// TODO: Switch to egui
|
// TODO: Switch to egui
|
||||||
_ = commands.spawn_bundle(SpriteBundle {
|
_ = 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 {
|
sprite: Sprite {
|
||||||
custom_size: Some(custom_sprite_size),
|
custom_size: Some(custom_sprite_size),
|
||||||
..default()
|
..default()
|
||||||
|
@ -159,6 +160,7 @@ fn generate_graphics(
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
update_textures(&world_manager, &render_settings, &mut images);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "render")]
|
#[cfg(feature = "render")]
|
||||||
|
@ -222,6 +224,7 @@ 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())
|
||||||
.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)
|
||||||
|
|
Loading…
Reference in a new issue