Rename planet_view to globe view; Use macros slightly better; PlanetView
f45efb28f1be9e8e39b84196b97d121b64fff607
This commit is contained in:
parent
8190666f97
commit
afd2495e43
12 changed files with 289 additions and 148 deletions
8
.github/workflows/release.yaml
vendored
8
.github/workflows/release.yaml
vendored
|
@ -11,7 +11,7 @@ jobs:
|
|||
strategy:
|
||||
matrix:
|
||||
os: [windows-2022, ubuntu-22.04, macos-12]
|
||||
features: ["debug,render", "render", "debug,planet_view", "planet_view", "debug", ""]
|
||||
features: ["debug,render", "render", "debug,globe_view", "globe_view", "debug", ""]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
|
@ -34,11 +34,11 @@ jobs:
|
|||
name: worlds-rs-${{ matrix.os }}-debug-render
|
||||
path: target/release/worlds-sim-rust*
|
||||
|
||||
- name: Upload debug & planet_view binary
|
||||
- name: Upload debug & globe_view binary
|
||||
uses: actions/upload-artifact@v3
|
||||
if: ${{ matrix.features == 'debug,planet_view' }}
|
||||
if: ${{ matrix.features == 'debug,globe_view' }}
|
||||
with:
|
||||
name: worlds-rs-${{ matrix.os }}-debug-planet_view
|
||||
name: worlds-rs-${{ matrix.os }}-debug-globe_view
|
||||
path: target/release/worlds-sim-rust*
|
||||
|
||||
- name: Upload non-debug binary
|
||||
|
|
|
@ -9,7 +9,7 @@ winit = { version = "0.26.1", features=["x11"] }
|
|||
|
||||
[features]
|
||||
debug = ["planet/debug"]
|
||||
planet_view = ["planet/planet_view", "render"]
|
||||
globe_view = ["planet/globe_view", "render"]
|
||||
render = ["bevy/bevy_asset", "bevy/bevy_winit", "bevy/render", "planet/render", "dep:bevy_pancam"]
|
||||
default = ["render", "debug"]
|
||||
|
||||
|
|
|
@ -5,9 +5,9 @@ edition = "2021"
|
|||
|
||||
[features]
|
||||
debug = []
|
||||
planet_view = ["render"]
|
||||
globe_view = ["render"]
|
||||
render = ["bevy/render"]
|
||||
default = ["render", "debug", "planet_view"]
|
||||
default = ["render", "debug", "globe_view"]
|
||||
|
||||
[dependencies.rand]
|
||||
version = "0.8.5"
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
use crate::{macros::iterable_enum, World};
|
||||
#[cfg(feature = "render")]
|
||||
use bevy::render::color::Color;
|
||||
use {
|
||||
crate::World,
|
||||
serde::{Deserialize, Serialize},
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub struct BiomeStats {
|
||||
|
@ -18,20 +15,16 @@ pub struct BiomeStats {
|
|||
pub max_temperature: f32,
|
||||
}
|
||||
|
||||
macro_rules! biome_enum {
|
||||
($($Variant:ident),*$(,)?) =>
|
||||
{
|
||||
#[derive(Debug, Copy, Clone, Deserialize, Serialize)]
|
||||
pub enum BiomeType {
|
||||
$($Variant),*,
|
||||
}
|
||||
impl BiomeType {
|
||||
pub const BIOMES: &'static [BiomeType] = &[$(BiomeType::$Variant),*];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
biome_enum!(IceCap, Ocean, Grassland, Forest, Taiga, Tundra, Desert, Rainforest);
|
||||
iterable_enum!(BiomeType {
|
||||
IceCap,
|
||||
Ocean,
|
||||
Grassland,
|
||||
Forest,
|
||||
Taiga,
|
||||
Tundra,
|
||||
Desert,
|
||||
Rainforest
|
||||
});
|
||||
|
||||
impl From<BiomeType> for BiomeStats {
|
||||
fn from(biome_type: BiomeType) -> BiomeStats {
|
||||
|
|
|
@ -37,8 +37,8 @@ pub use world::*;
|
|||
pub mod biome;
|
||||
pub use biome::*;
|
||||
pub mod world_manager;
|
||||
pub use world_manager::*;
|
||||
pub use world_manager::WorldManager;
|
||||
pub(crate) mod macros;
|
||||
pub mod math_util;
|
||||
pub use math_util::*;
|
||||
pub mod perlin;
|
||||
pub mod saving;
|
||||
|
|
18
planet/src/macros.rs
Normal file
18
planet/src/macros.rs
Normal file
|
@ -0,0 +1,18 @@
|
|||
macro_rules! iterable_enum {
|
||||
($Name:ident { $($Variant:ident),*$(,)? }) =>
|
||||
{
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||
pub enum $Name {
|
||||
$($Variant),*,
|
||||
}
|
||||
impl $Name {
|
||||
pub const ITEMS: &'static [$Name] = &[$($Name::$Variant),*];
|
||||
pub const ITEM_COUNT: usize = $Name::ITEMS.len();
|
||||
|
||||
pub fn iterator() -> core::slice::Iter<'static, $Name> {
|
||||
$Name::ITEMS.iter()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
pub(crate) use iterable_enum;
|
|
@ -1,16 +1,23 @@
|
|||
// TODO: Logging doesn't seem to work here? Figure out why and fix
|
||||
use {
|
||||
crate::{
|
||||
cartesian_coordinates,
|
||||
mix_values,
|
||||
math_util::{
|
||||
cartesian_coordinates,
|
||||
mix_values,
|
||||
random_point_in_sphere,
|
||||
CartesianError,
|
||||
RepeatNum,
|
||||
},
|
||||
perlin,
|
||||
random_point_in_sphere,
|
||||
BiomeStats,
|
||||
BiomeType,
|
||||
CartesianError,
|
||||
RepeatNum,
|
||||
},
|
||||
bevy::{log::info, math::Vec3A, prelude::Vec2, utils::default},
|
||||
bevy::{
|
||||
log::info,
|
||||
math::Vec3A,
|
||||
prelude::Vec2,
|
||||
utils::{default, HashMap},
|
||||
},
|
||||
rand::{rngs::StdRng, Rng, SeedableRng},
|
||||
serde::{Deserialize, Serialize},
|
||||
std::{
|
||||
|
@ -47,6 +54,18 @@ impl Display for WorldGenError {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub enum CompassDirection {
|
||||
North,
|
||||
NorthEast,
|
||||
East,
|
||||
SouthEast,
|
||||
South,
|
||||
SouthWest,
|
||||
West,
|
||||
NorthWest,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct World {
|
||||
pub width: u32,
|
||||
|
@ -456,7 +475,7 @@ impl World {
|
|||
let mut total_presence = 0.0;
|
||||
|
||||
let mut biome_presences = vec![];
|
||||
for biome_type in BiomeType::BIOMES {
|
||||
for biome_type in BiomeType::iterator() {
|
||||
let presence = self.biome_presence(cell, &biome_type.into());
|
||||
|
||||
if presence <= 0.0 {
|
||||
|
@ -526,4 +545,92 @@ impl World {
|
|||
|
||||
presence
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn cell_neighbors(&self, x: usize, y: usize) -> HashMap<CompassDirection, (usize, usize)> {
|
||||
let mut neighbors = HashMap::new();
|
||||
|
||||
let height = self.height as usize;
|
||||
let width = self.width as usize;
|
||||
|
||||
let north_edge = y >= height - 1;
|
||||
let east_edge = x >= width - 1;
|
||||
let south_edge = y == 0;
|
||||
let west_edge = x == 0;
|
||||
|
||||
if !north_edge {
|
||||
_ = neighbors.insert_unique_unchecked(CompassDirection::North, (y + 1, x));
|
||||
}
|
||||
if !north_edge && !east_edge {
|
||||
_ = neighbors.insert_unique_unchecked(CompassDirection::NorthEast, (y + 1, x + 1));
|
||||
}
|
||||
if !east_edge {
|
||||
_ = neighbors.insert_unique_unchecked(CompassDirection::East, (y, x + 1));
|
||||
}
|
||||
if !south_edge && !east_edge {
|
||||
_ = neighbors.insert_unique_unchecked(CompassDirection::SouthEast, (y - 1, x + 1));
|
||||
}
|
||||
if !south_edge {
|
||||
_ = neighbors.insert_unique_unchecked(CompassDirection::South, (y - 1, x));
|
||||
}
|
||||
if !south_edge && !west_edge {
|
||||
_ = neighbors.insert_unique_unchecked(CompassDirection::SouthWest, (y - 1, x - 1));
|
||||
}
|
||||
if !west_edge {
|
||||
_ = neighbors.insert_unique_unchecked(CompassDirection::West, (y, x - 1));
|
||||
};
|
||||
if !north_edge && !west_edge {
|
||||
_ = neighbors.insert_unique_unchecked(CompassDirection::NorthWest, (y + 1, x - 1));
|
||||
};
|
||||
|
||||
neighbors
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn get_slant(&self, x: usize, y: usize) -> f32 {
|
||||
let neighbors = self.cell_neighbors(x, y);
|
||||
let terrain = &self.terrain;
|
||||
|
||||
let mut west_altitude = f32::MIN;
|
||||
if let Some(neighbor_coords) = neighbors.get(&CompassDirection::North) {
|
||||
west_altitude = f32::max(
|
||||
west_altitude,
|
||||
terrain[neighbor_coords.0][neighbor_coords.1].altitude,
|
||||
);
|
||||
}
|
||||
if let Some(neighbor_coords) = neighbors.get(&CompassDirection::NorthWest) {
|
||||
west_altitude = f32::max(
|
||||
west_altitude,
|
||||
terrain[neighbor_coords.0][neighbor_coords.1].altitude,
|
||||
);
|
||||
}
|
||||
if let Some(neighbor_coords) = neighbors.get(&CompassDirection::West) {
|
||||
west_altitude = f32::max(
|
||||
west_altitude,
|
||||
terrain[neighbor_coords.0][neighbor_coords.1].altitude,
|
||||
);
|
||||
}
|
||||
|
||||
let mut east_altitude = f32::MIN;
|
||||
if let Some(neighbor_coords) = neighbors.get(&CompassDirection::North) {
|
||||
east_altitude = f32::max(
|
||||
east_altitude,
|
||||
terrain[neighbor_coords.0][neighbor_coords.1].altitude,
|
||||
);
|
||||
}
|
||||
if let Some(neighbor_coords) = neighbors.get(&CompassDirection::NorthWest) {
|
||||
east_altitude = f32::max(
|
||||
east_altitude,
|
||||
terrain[neighbor_coords.0][neighbor_coords.1].altitude,
|
||||
);
|
||||
}
|
||||
if let Some(neighbor_coords) = neighbors.get(&CompassDirection::West) {
|
||||
east_altitude = f32::max(
|
||||
east_altitude,
|
||||
terrain[neighbor_coords.0][neighbor_coords.1].altitude,
|
||||
);
|
||||
}
|
||||
|
||||
west_altitude - east_altitude
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,19 +2,10 @@
|
|||
use bevy::log::debug;
|
||||
#[cfg(feature = "debug")]
|
||||
use bevy::utils::default;
|
||||
#[cfg(all(feature = "render", feature = "planet_view"))]
|
||||
#[cfg(all(feature = "render", feature = "globe_view"))]
|
||||
use std::f32::consts::PI;
|
||||
#[cfg(feature = "render")]
|
||||
use {
|
||||
crate::{BiomeStats, TerrainCell},
|
||||
bevy::{
|
||||
asset::{Assets, HandleId},
|
||||
render::render_resource::Extent3d,
|
||||
render::{color::Color, texture::Image},
|
||||
},
|
||||
};
|
||||
use {
|
||||
crate::{World, WorldGenError},
|
||||
crate::{macros::iterable_enum, World, WorldGenError},
|
||||
bevy::log::warn,
|
||||
rand::random,
|
||||
std::{
|
||||
|
@ -25,6 +16,15 @@ 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 {
|
||||
|
@ -89,43 +89,46 @@ impl Display for SaveError {
|
|||
}
|
||||
}
|
||||
|
||||
iterable_enum!(PlanetView { Biomes, Altitude });
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct WorldManager {
|
||||
world: Option<World>,
|
||||
|
||||
#[cfg(feature = "render")]
|
||||
pub map_image_handle_id: Option<HandleId>,
|
||||
#[cfg(all(feature = "render", feature = "planet_view"))]
|
||||
pub planet_image_handle_id: Option<HandleId>,
|
||||
#[cfg(all(feature = "render", feature = "planet_view"))]
|
||||
pub planet_material_handle_id: Option<HandleId>,
|
||||
pub map_image_handle_id: Option<HandleId>,
|
||||
#[cfg(all(feature = "render", feature = "globe_view"))]
|
||||
pub globe_image_handle_id: Option<HandleId>,
|
||||
#[cfg(all(feature = "render", feature = "globe_view"))]
|
||||
pub globe_material_handle_id: Option<HandleId>,
|
||||
|
||||
#[cfg(feature = "render")]
|
||||
rainfall_visible: bool,
|
||||
#[cfg(feature = "render")]
|
||||
temperature_visible: bool,
|
||||
#[cfg(feature = "render")]
|
||||
biomes_visible: bool,
|
||||
#[cfg(feature = "render")]
|
||||
contours: bool,
|
||||
#[cfg(feature = "render")]
|
||||
view: PlanetView,
|
||||
}
|
||||
|
||||
impl WorldManager {
|
||||
#[must_use]
|
||||
pub fn new() -> WorldManager {
|
||||
Self {
|
||||
world: None,
|
||||
#[cfg(feature = "render")]
|
||||
map_image_handle_id: None,
|
||||
#[cfg(all(feature = "render", feature = "planet_view"))]
|
||||
planet_image_handle_id: None,
|
||||
#[cfg(all(feature = "render", feature = "planet_view"))]
|
||||
planet_material_handle_id: None,
|
||||
#[cfg(all(feature = "render", feature = "globe_view"))]
|
||||
globe_image_handle_id: None,
|
||||
#[cfg(all(feature = "render", feature = "globe_view"))]
|
||||
globe_material_handle_id: None,
|
||||
#[cfg(feature = "render")]
|
||||
rainfall_visible: false,
|
||||
#[cfg(feature = "render")]
|
||||
temperature_visible: false,
|
||||
#[cfg(feature = "render")]
|
||||
biomes_visible: true,
|
||||
view: PlanetView::Biomes,
|
||||
#[cfg(feature = "render")]
|
||||
contours: false,
|
||||
}
|
||||
|
@ -228,14 +231,19 @@ impl WorldManager {
|
|||
}
|
||||
|
||||
#[cfg(feature = "render")]
|
||||
pub fn toggle_biomes(&mut self) {
|
||||
pub fn cycle_view(&mut self) {
|
||||
let idx = (PlanetView::iterator()
|
||||
.position(|view| *view == self.view)
|
||||
.unwrap()
|
||||
+ 1)
|
||||
% PlanetView::ITEM_COUNT;
|
||||
#[cfg(feature = "debug")]
|
||||
if self.temperature_visible {
|
||||
debug!("Turning biomes off");
|
||||
} else {
|
||||
debug!("Turning biomes on");
|
||||
}
|
||||
self.biomes_visible = !self.biomes_visible;
|
||||
debug!(
|
||||
"Cycling view from {:#?} to {:#?}",
|
||||
self.view,
|
||||
PlanetView::ITEMS[idx]
|
||||
);
|
||||
self.view = PlanetView::ITEMS[idx];
|
||||
}
|
||||
|
||||
#[cfg(feature = "render")]
|
||||
|
@ -249,6 +257,7 @@ impl WorldManager {
|
|||
self.contours = !self.contours;
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn get_world(&self) -> Option<&World> {
|
||||
self.world.as_ref()
|
||||
}
|
||||
|
@ -267,8 +276,9 @@ impl WorldManager {
|
|||
}
|
||||
|
||||
#[cfg(feature = "render")]
|
||||
#[must_use]
|
||||
fn generate_color(&self, cell: &TerrainCell) -> Color {
|
||||
if self.biomes_visible {
|
||||
if self.view == PlanetView::Biomes {
|
||||
return WorldManager::biome_color(cell);
|
||||
}
|
||||
|
||||
|
@ -316,6 +326,7 @@ impl WorldManager {
|
|||
}
|
||||
|
||||
#[cfg(feature = "render")]
|
||||
#[must_use]
|
||||
fn altitude_color(altitude: f32) -> Color {
|
||||
if altitude < 0.0 {
|
||||
Color::rgb(0.0, 0.0, (2.0 - altitude / World::MIN_ALTITUDE) / 2.0)
|
||||
|
@ -327,6 +338,7 @@ impl WorldManager {
|
|||
}
|
||||
|
||||
#[cfg(feature = "render")]
|
||||
#[must_use]
|
||||
fn altitude_contour_color(altitude: f32) -> Color {
|
||||
if altitude < 0.0 {
|
||||
Color::rgb(0.0, 0.0, (2.0 - altitude / World::MIN_ALTITUDE) / 2.0)
|
||||
|
@ -342,6 +354,7 @@ impl WorldManager {
|
|||
}
|
||||
|
||||
#[cfg(feature = "render")]
|
||||
#[must_use]
|
||||
fn rainfall_contour_color(&self, rainfall: f32) -> Color {
|
||||
let mut shade_value = 1.0;
|
||||
let value = rainfall / self.world().max_rainfall;
|
||||
|
@ -354,6 +367,7 @@ impl WorldManager {
|
|||
}
|
||||
|
||||
#[cfg(feature = "render")]
|
||||
#[must_use]
|
||||
fn temperature_contour_color(&self, temperature: f32) -> Color {
|
||||
let mut shade_value = 1.0;
|
||||
let value = (temperature - self.world().min_temperature)
|
||||
|
@ -367,6 +381,7 @@ impl WorldManager {
|
|||
}
|
||||
|
||||
#[cfg(feature = "render")]
|
||||
#[must_use]
|
||||
fn biome_color(cell: &TerrainCell) -> Color {
|
||||
cell.biome_presences
|
||||
.iter()
|
||||
|
@ -412,9 +427,9 @@ impl WorldManager {
|
|||
.collect()
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "render", feature = "planet_view"))]
|
||||
#[cfg(all(feature = "render", feature = "globe_view"))]
|
||||
#[must_use]
|
||||
fn planet_colors(&self) -> Vec<Color> {
|
||||
fn globe_colors(&self) -> Vec<Color> {
|
||||
let world = self.world();
|
||||
let width = world.width as usize;
|
||||
let height = world.height as usize;
|
||||
|
@ -439,10 +454,10 @@ impl WorldManager {
|
|||
colors
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "render", feature = "planet_view"))]
|
||||
#[cfg(all(feature = "render", feature = "globe_view"))]
|
||||
#[must_use]
|
||||
pub fn planet_color_bytes(&self) -> Vec<u8> {
|
||||
self.planet_colors()
|
||||
pub fn globe_color_bytes(&self) -> Vec<u8> {
|
||||
self.globe_colors()
|
||||
.iter()
|
||||
.flat_map(|color| {
|
||||
color
|
||||
|
|
|
@ -1,41 +1,27 @@
|
|||
#[cfg(feature = "render")]
|
||||
use bevy::ecs::component::Component;
|
||||
use {crate::macros::iterable_enum, bevy::ecs::component::Component};
|
||||
|
||||
#[cfg(feature = "render")]
|
||||
macro_rules! toolbar_enum {
|
||||
($($Variant:ident),*$(,)?) =>
|
||||
{
|
||||
#[derive(Debug, Component, Copy, Clone)]
|
||||
pub enum ToolbarButton {
|
||||
$($Variant),*,
|
||||
}
|
||||
impl ToolbarButton {
|
||||
pub const BUTTONS: &'static [ToolbarButton] = &[$(ToolbarButton::$Variant),*];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "render", not(feature = "planet_view")))]
|
||||
toolbar_enum!(
|
||||
#[cfg(all(feature = "render", not(feature = "globe_view")))]
|
||||
iterable_enum!(ToolbarButton {
|
||||
GenerateWorld,
|
||||
SaveWorld,
|
||||
LoadWorld,
|
||||
Rainfall,
|
||||
Temperature,
|
||||
Biomes,
|
||||
Contours,
|
||||
);
|
||||
#[cfg(all(feature = "render", feature = "planet_view"))]
|
||||
toolbar_enum!(
|
||||
GenerateWorld,
|
||||
SaveWorld,
|
||||
LoadWorld,
|
||||
Rainfall,
|
||||
Temperature,
|
||||
Biomes,
|
||||
Contours,
|
||||
PlanetView,
|
||||
);
|
||||
Contours,
|
||||
});
|
||||
#[cfg(all(feature = "render", feature = "globe_view"))]
|
||||
iterable_enum!(ToolbarButton {
|
||||
GenerateWorld,
|
||||
SaveWorld,
|
||||
LoadWorld,
|
||||
Rainfall,
|
||||
Temperature,
|
||||
PlanetView,
|
||||
Contours,
|
||||
GlobeView,
|
||||
});
|
||||
|
||||
#[cfg(feature = "render")]
|
||||
impl From<ToolbarButton> for &'static str {
|
||||
|
@ -44,12 +30,12 @@ impl From<ToolbarButton> for &'static str {
|
|||
ToolbarButton::Rainfall => "Toggle rainfall",
|
||||
ToolbarButton::Temperature => "Toggle temperature",
|
||||
ToolbarButton::Contours => "Toggle contours",
|
||||
ToolbarButton::Biomes => "Toggle biomes",
|
||||
ToolbarButton::PlanetView => "Cycle view",
|
||||
ToolbarButton::GenerateWorld => "Generate new world",
|
||||
ToolbarButton::SaveWorld => "Save",
|
||||
ToolbarButton::LoadWorld => "Load",
|
||||
#[cfg(feature = "planet_view")]
|
||||
ToolbarButton::PlanetView => "Toggle planet view",
|
||||
#[cfg(feature = "globe_view")]
|
||||
ToolbarButton::GlobeView => "Toggle globe",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
19
src/macros.rs
Normal file
19
src/macros.rs
Normal file
|
@ -0,0 +1,19 @@
|
|||
#[cfg(feature = "render")]
|
||||
macro_rules! iterable_enum {
|
||||
($Name:ident { $($Variant:ident),*$(,)? }) =>
|
||||
{
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Component)]
|
||||
pub enum $Name {
|
||||
$($Variant),*,
|
||||
}
|
||||
impl $Name {
|
||||
const ITEMS: &'static [$Name] = &[$($Name::$Variant),*];
|
||||
|
||||
pub fn iterator() -> core::slice::Iter<'static, $Name> {
|
||||
$Name::ITEMS.iter()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#[cfg(feature = "render")]
|
||||
pub(crate) use iterable_enum;
|
91
src/main.rs
91
src/main.rs
|
@ -32,10 +32,11 @@
|
|||
#![warn(unused_results)]
|
||||
#![warn(variant_size_differences)]
|
||||
|
||||
mod components;
|
||||
mod plugins;
|
||||
mod resources;
|
||||
mod ui_helpers;
|
||||
pub(crate) mod components;
|
||||
pub(crate) mod macros;
|
||||
pub(crate) mod plugins;
|
||||
pub(crate) mod resources;
|
||||
pub(crate) mod ui_helpers;
|
||||
|
||||
#[cfg(all(feature = "debug", feature = "render"))]
|
||||
use bevy::{
|
||||
|
@ -103,7 +104,7 @@ use {
|
|||
planet::WorldManager,
|
||||
plugins::WorldPlugins,
|
||||
};
|
||||
#[cfg(all(feature = "render", feature = "planet_view"))]
|
||||
#[cfg(all(feature = "render", feature = "globe_view"))]
|
||||
use {
|
||||
bevy::{
|
||||
asset::Handle,
|
||||
|
@ -121,7 +122,7 @@ use {
|
|||
#[cfg(feature = "render")]
|
||||
fn refresh_map_texture(
|
||||
images: &mut Assets<Image>,
|
||||
#[cfg(feature = "planet_view")] materials: &mut Assets<StandardMaterial>,
|
||||
#[cfg(feature = "globe_view")] materials: &mut Assets<StandardMaterial>,
|
||||
world_manager: &WorldManager,
|
||||
) {
|
||||
let world = world_manager.world();
|
||||
|
@ -142,11 +143,11 @@ fn refresh_map_texture(
|
|||
});
|
||||
map_image.data = world_manager.map_color_bytes();
|
||||
|
||||
#[cfg(feature = "planet_view")]
|
||||
#[cfg(feature = "globe_view")]
|
||||
{
|
||||
let planet_image_handle = images.get_handle(
|
||||
world_manager
|
||||
.planet_image_handle_id
|
||||
.globe_image_handle_id
|
||||
.expect("No planet image handle"),
|
||||
);
|
||||
let planet_image = images
|
||||
|
@ -157,11 +158,11 @@ fn refresh_map_texture(
|
|||
height: world.height,
|
||||
depth_or_array_layers: 1,
|
||||
});
|
||||
planet_image.data = world_manager.planet_color_bytes();
|
||||
planet_image.data = world_manager.globe_color_bytes();
|
||||
|
||||
let planet_material_handle = materials.get_handle(
|
||||
world_manager
|
||||
.planet_material_handle_id
|
||||
.globe_material_handle_id
|
||||
.expect("No planet material handle"),
|
||||
);
|
||||
let planet_material = materials
|
||||
|
@ -188,19 +189,19 @@ fn handle_toolbar_button(
|
|||
mut windows: ResMut<'_, Windows>,
|
||||
mut images: ResMut<'_, Assets<Image>>,
|
||||
mut world_manager: ResMut<'_, WorldManager>,
|
||||
#[cfg(feature = "planet_view")] mut camera_3d_query: Query<
|
||||
#[cfg(feature = "globe_view")] mut camera_3d_query: Query<
|
||||
'_,
|
||||
'_,
|
||||
&mut Camera,
|
||||
(With<Camera3d>, Without<Camera2d>),
|
||||
>,
|
||||
#[cfg(feature = "planet_view")] mut camera_2d_query: Query<
|
||||
#[cfg(feature = "globe_view")] mut camera_2d_query: Query<
|
||||
'_,
|
||||
'_,
|
||||
&mut Camera,
|
||||
(&mut Camera, &mut PanCam),
|
||||
(With<Camera2d>, Without<Camera3d>),
|
||||
>,
|
||||
#[cfg(feature = "planet_view")] mut materials: ResMut<'_, Assets<StandardMaterial>>,
|
||||
#[cfg(feature = "globe_view")] mut materials: ResMut<'_, Assets<StandardMaterial>>,
|
||||
) {
|
||||
for (interaction, mut color, toolbar_button) in &mut interaction_query {
|
||||
match *interaction {
|
||||
|
@ -214,7 +215,7 @@ fn handle_toolbar_button(
|
|||
world_manager.toggle_rainfall();
|
||||
refresh_map_texture(
|
||||
&mut images,
|
||||
#[cfg(feature = "planet_view")]
|
||||
#[cfg(feature = "globe_view")]
|
||||
&mut materials,
|
||||
&world_manager,
|
||||
);
|
||||
|
@ -225,18 +226,18 @@ fn handle_toolbar_button(
|
|||
world_manager.toggle_temperature();
|
||||
refresh_map_texture(
|
||||
&mut images,
|
||||
#[cfg(feature = "planet_view")]
|
||||
#[cfg(feature = "globe_view")]
|
||||
&mut materials,
|
||||
&world_manager,
|
||||
);
|
||||
},
|
||||
ToolbarButton::Biomes => {
|
||||
ToolbarButton::PlanetView => {
|
||||
#[cfg(feature = "debug")]
|
||||
debug!("Toggling biomes");
|
||||
world_manager.toggle_biomes();
|
||||
debug!("Cycling planet view");
|
||||
world_manager.cycle_view();
|
||||
refresh_map_texture(
|
||||
&mut images,
|
||||
#[cfg(feature = "planet_view")]
|
||||
#[cfg(feature = "globe_view")]
|
||||
&mut materials,
|
||||
&world_manager,
|
||||
);
|
||||
|
@ -247,7 +248,7 @@ fn handle_toolbar_button(
|
|||
world_manager.toggle_contours();
|
||||
refresh_map_texture(
|
||||
&mut images,
|
||||
#[cfg(feature = "planet_view")]
|
||||
#[cfg(feature = "globe_view")]
|
||||
&mut materials,
|
||||
&world_manager,
|
||||
);
|
||||
|
@ -260,7 +261,7 @@ fn handle_toolbar_button(
|
|||
.expect("Failed to generate new world");
|
||||
refresh_map_texture(
|
||||
&mut images,
|
||||
#[cfg(feature = "planet_view")]
|
||||
#[cfg(feature = "globe_view")]
|
||||
&mut materials,
|
||||
&world_manager,
|
||||
);
|
||||
|
@ -276,19 +277,20 @@ fn handle_toolbar_button(
|
|||
_ = world_manager.load_world("planet.ron", &mut images);
|
||||
refresh_map_texture(
|
||||
&mut images,
|
||||
#[cfg(feature = "planet_view")]
|
||||
#[cfg(feature = "globe_view")]
|
||||
&mut materials,
|
||||
&world_manager,
|
||||
);
|
||||
},
|
||||
#[cfg(feature = "planet_view")]
|
||||
ToolbarButton::PlanetView => {
|
||||
#[cfg(feature = "globe_view")]
|
||||
ToolbarButton::GlobeView => {
|
||||
#[cfg(feature = "debug")]
|
||||
debug!("Toggling planet view");
|
||||
debug!("Toggling globe view");
|
||||
let mut camera_3d = camera_3d_query.single_mut();
|
||||
camera_3d.is_active = !camera_3d.is_active;
|
||||
let mut camera_2d = camera_2d_query.single_mut();
|
||||
let (mut camera_2d, mut pancam) = camera_2d_query.single_mut();
|
||||
camera_2d.is_active = !camera_2d.is_active;
|
||||
pancam.enabled = camera_2d.is_active;
|
||||
},
|
||||
}
|
||||
},
|
||||
|
@ -336,11 +338,11 @@ fn update_cursor_map_position(
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "render", feature = "planet_view"))]
|
||||
#[cfg(all(feature = "render", feature = "globe_view"))]
|
||||
const ROTATION_SPEED: f32 = 0.002;
|
||||
#[cfg(all(feature = "render", feature = "planet_view"))]
|
||||
fn rotate_planet(mut planet_transform: Query<'_, '_, &mut Transform, With<Handle<Mesh>>>) {
|
||||
planet_transform.single_mut().rotate_y(ROTATION_SPEED);
|
||||
#[cfg(all(feature = "render", feature = "globe_view"))]
|
||||
fn rotate_globe(mut globe_transform: Query<'_, '_, &mut Transform, With<Handle<Mesh>>>) {
|
||||
globe_transform.single_mut().rotate_y(ROTATION_SPEED);
|
||||
}
|
||||
|
||||
#[cfg(feature = "render")]
|
||||
|
@ -431,8 +433,8 @@ fn generate_graphics(
|
|||
mut world_manager: ResMut<'_, WorldManager>,
|
||||
mut images: ResMut<'_, Assets<Image>>,
|
||||
mut fonts: ResMut<'_, Assets<Font>>,
|
||||
#[cfg(feature = "planet_view")] mut materials: ResMut<'_, Assets<StandardMaterial>>,
|
||||
#[cfg(feature = "planet_view")] mut meshes: ResMut<'_, Assets<Mesh>>,
|
||||
#[cfg(feature = "globe_view")] mut materials: ResMut<'_, Assets<StandardMaterial>>,
|
||||
#[cfg(feature = "globe_view")] mut meshes: ResMut<'_, Assets<Mesh>>,
|
||||
) {
|
||||
let julia_mono_handle = fonts.add(
|
||||
Font::try_from_bytes(include_bytes!("../assets/JuliaMono.ttf").to_vec())
|
||||
|
@ -463,11 +465,11 @@ fn generate_graphics(
|
|||
});
|
||||
world_manager.map_image_handle_id = Some(map_image_handle.id);
|
||||
|
||||
#[cfg(feature = "planet_view")]
|
||||
#[cfg(feature = "globe_view")]
|
||||
{
|
||||
let world = world_manager.world();
|
||||
let planet_image_handle = images.add(Image {
|
||||
data: world_manager.planet_color_bytes(),
|
||||
let globe_image_handle = images.add(Image {
|
||||
data: world_manager.globe_color_bytes(),
|
||||
texture_descriptor: TextureDescriptor {
|
||||
label: None,
|
||||
size: Extent3d {
|
||||
|
@ -483,7 +485,7 @@ fn generate_graphics(
|
|||
},
|
||||
..default()
|
||||
});
|
||||
world_manager.planet_image_handle_id = Some(planet_image_handle.id);
|
||||
world_manager.globe_image_handle_id = Some(globe_image_handle.id);
|
||||
|
||||
_ = commands.spawn_bundle(Camera3dBundle {
|
||||
camera: Camera {
|
||||
|
@ -499,19 +501,20 @@ fn generate_graphics(
|
|||
..default()
|
||||
});
|
||||
|
||||
let planet_material_handle = materials.add(
|
||||
let globe_material_handle = materials.add(
|
||||
images
|
||||
.get_handle(world_manager.planet_image_handle_id.unwrap())
|
||||
.get_handle(world_manager.globe_image_handle_id.unwrap())
|
||||
.into(),
|
||||
);
|
||||
world_manager.planet_material_handle_id = Some(planet_material_handle.id);
|
||||
world_manager.globe_material_handle_id = Some(globe_material_handle.id);
|
||||
|
||||
// TODO: Globe texture is mirrored east-to-west.
|
||||
_ = commands.spawn_bundle(PbrBundle {
|
||||
mesh: meshes.add(Mesh::from(UVSphere {
|
||||
radius: 2.0,
|
||||
..default()
|
||||
})),
|
||||
material: planet_material_handle,
|
||||
material: globe_material_handle,
|
||||
transform: Transform::from_rotation(Quat::from_rotation_x(FRAC_PI_2)),
|
||||
..default()
|
||||
});
|
||||
|
@ -591,7 +594,7 @@ fn generate_graphics(
|
|||
..default()
|
||||
})
|
||||
.with_children(|button_box| {
|
||||
ToolbarButton::BUTTONS.iter().for_each(|&button_type| {
|
||||
ToolbarButton::iterator().for_each(|&button_type| {
|
||||
_ = button_box
|
||||
.spawn_bundle(toolbar_button())
|
||||
.with_children(|button| {
|
||||
|
@ -630,9 +633,9 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
.add_system(handle_toolbar_button)
|
||||
.add_system(update_cursor_map_position)
|
||||
.add_system(update_info_panel);
|
||||
#[cfg(all(feature = "render", feature = "planet_view"))]
|
||||
#[cfg(all(feature = "render", feature = "globe_view"))]
|
||||
{
|
||||
_ = app.add_system(rotate_planet);
|
||||
_ = app.add_system(rotate_globe);
|
||||
}
|
||||
}
|
||||
#[cfg(not(feature = "render"))]
|
||||
|
|
|
@ -48,7 +48,7 @@ impl PluginGroup for WorldPlugins {
|
|||
.add(TextPlugin::default())
|
||||
.add(UiPlugin::default())
|
||||
.add(PanCamPlugin::default());
|
||||
#[cfg(feature = "planet_view")]
|
||||
#[cfg(feature = "globe_view")]
|
||||
{
|
||||
use bevy::pbr::PbrPlugin;
|
||||
_ = group.add(PbrPlugin::default())
|
||||
|
|
Loading…
Reference in a new issue