Add biomes!
06f11e44aaeb99bc73522e86a08abd61a9da2e58 0e4387490e18cef0bccda5e7233d6949845e9620 759b4c6c744d4a7f44efb656ab8c5e66d178283c af8b9e06e7935d17153c8603d2dcaf281de753c3
This commit is contained in:
parent
6a17e6df7b
commit
fb78c618e4
7 changed files with 635245 additions and 386343 deletions
1021157
planet.ron
1021157
planet.ron
File diff suppressed because it is too large
Load diff
127
planet/src/biome.rs
Normal file
127
planet/src/biome.rs
Normal file
|
@ -0,0 +1,127 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[cfg(feature = "render")]
|
||||
use bevy::render::color::Color;
|
||||
|
||||
use crate::World;
|
||||
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub struct Biome {
|
||||
pub name: String,
|
||||
#[cfg(feature = "render")]
|
||||
pub color: Color,
|
||||
pub min_altitude: f32,
|
||||
pub max_altitude: f32,
|
||||
pub min_rainfall: f32,
|
||||
pub max_rainfall: f32,
|
||||
pub min_temperature: f32,
|
||||
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);
|
||||
|
||||
impl From<BiomeType> for Biome {
|
||||
fn from(biome_type: BiomeType) -> Biome {
|
||||
match biome_type {
|
||||
BiomeType::IceCap => Biome {
|
||||
name: "Ice Cap".into(),
|
||||
color: Color::rgb_u8(253, 244, 235),
|
||||
min_altitude: World::MIN_ALTITUDE,
|
||||
max_altitude: World::MAX_ALTITUDE,
|
||||
min_rainfall: World::MIN_RAINFALL,
|
||||
max_rainfall: World::MAX_RAINFALL,
|
||||
min_temperature: World::MIN_TEMPERATURE,
|
||||
max_temperature: -15.0,
|
||||
},
|
||||
BiomeType::Ocean => Biome {
|
||||
name: "Ocean".into(),
|
||||
color: Color::rgb_u8(28, 66, 84),
|
||||
min_altitude: World::MIN_ALTITUDE,
|
||||
max_altitude: 0.0,
|
||||
min_rainfall: World::MIN_RAINFALL,
|
||||
max_rainfall: World::MAX_RAINFALL,
|
||||
min_temperature: -15.0,
|
||||
max_temperature: World::MAX_TEMPERATURE,
|
||||
},
|
||||
BiomeType::Grassland => Biome {
|
||||
name: "Grassland".into(),
|
||||
color: Color::rgb_u8(167, 177, 84),
|
||||
min_altitude: 0.0,
|
||||
max_altitude: World::MAX_ALTITUDE,
|
||||
min_rainfall: 25.0,
|
||||
max_rainfall: 1475.0,
|
||||
min_temperature: -5.0,
|
||||
max_temperature: World::MAX_TEMPERATURE,
|
||||
},
|
||||
BiomeType::Forest => Biome {
|
||||
name: "Forest".into(),
|
||||
color: Color::rgb_u8(76, 132, 55),
|
||||
min_altitude: 0.0,
|
||||
max_altitude: World::MAX_ALTITUDE,
|
||||
min_rainfall: 975.0,
|
||||
max_rainfall: 2475.0,
|
||||
min_temperature: -5.0,
|
||||
max_temperature: World::MAX_TEMPERATURE,
|
||||
},
|
||||
BiomeType::Taiga => Biome {
|
||||
name: "Taiga".into(),
|
||||
color: Color::rgb_u8(43, 63, 40),
|
||||
min_altitude: 0.0,
|
||||
max_altitude: World::MAX_ALTITUDE,
|
||||
min_rainfall: 475.0,
|
||||
max_rainfall: World::MAX_RAINFALL,
|
||||
min_temperature: -15.0,
|
||||
max_temperature: -0.0,
|
||||
},
|
||||
BiomeType::Tundra => Biome {
|
||||
name: "Tundra ".into(),
|
||||
color: Color::rgb_u8(139, 139, 128),
|
||||
min_altitude: 0.0,
|
||||
max_altitude: World::MAX_ALTITUDE,
|
||||
min_rainfall: World::MIN_RAINFALL,
|
||||
max_rainfall: 725.0,
|
||||
min_temperature: -20.0,
|
||||
max_temperature: -0.0,
|
||||
},
|
||||
BiomeType::Desert => Biome {
|
||||
name: "Desert ".into(),
|
||||
color: Color::rgb_u8(253, 225, 171),
|
||||
min_altitude: 0.0,
|
||||
max_altitude: World::MAX_ALTITUDE,
|
||||
min_rainfall: World::MIN_RAINFALL,
|
||||
max_rainfall: 125.0,
|
||||
min_temperature: -5.0,
|
||||
max_temperature: World::MAX_TEMPERATURE,
|
||||
},
|
||||
BiomeType::Rainforest => Biome {
|
||||
name: "Rainforest".into(),
|
||||
color: Color::rgb_u8(59, 103, 43),
|
||||
min_altitude: 0.0,
|
||||
max_altitude: World::MAX_ALTITUDE,
|
||||
min_rainfall: 1975.0,
|
||||
max_rainfall: World::MAX_RAINFALL,
|
||||
min_temperature: -5.0,
|
||||
max_temperature: World::MAX_TEMPERATURE,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&BiomeType> for Biome {
|
||||
fn from(biome_type: &BiomeType) -> Biome {
|
||||
(*biome_type).into()
|
||||
}
|
||||
}
|
|
@ -34,6 +34,8 @@
|
|||
|
||||
pub mod world;
|
||||
pub use world::*;
|
||||
pub mod biome;
|
||||
pub use biome::Biome;
|
||||
pub mod world_manager;
|
||||
pub use world_manager::*;
|
||||
pub mod math_util;
|
||||
|
|
|
@ -7,7 +7,7 @@ use std::{
|
|||
|
||||
// TODO: Logging doesn't seem to work here? Figure out why and fix
|
||||
|
||||
use crate::perlin;
|
||||
use crate::{biome::BiomeType, perlin, Biome};
|
||||
use bevy::{log::info, math::Vec3A, prelude::Vec2, utils::default};
|
||||
use rand::{rngs::StdRng, Rng, SeedableRng};
|
||||
|
||||
|
@ -65,23 +65,13 @@ pub struct World {
|
|||
pub rng: StdRng,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, Deserialize, Serialize)]
|
||||
pub struct Biome {
|
||||
pub altitude: f32,
|
||||
pub rainfall: f32,
|
||||
pub temperature: f32,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, Deserialize, Serialize)]
|
||||
pub struct TerrainCell {
|
||||
pub altitude: f32,
|
||||
pub rainfall: f32,
|
||||
pub temperature: f32,
|
||||
|
||||
#[serde(skip)]
|
||||
pub rain_accumulated: f32,
|
||||
#[serde(skip)]
|
||||
pub previous_rain_accumulated: f32,
|
||||
pub biome_presences: Vec<(BiomeType, f32)>,
|
||||
}
|
||||
|
||||
impl World {
|
||||
|
@ -106,33 +96,32 @@ impl World {
|
|||
}
|
||||
}
|
||||
|
||||
pub const NUM_CONTINENTS: u8 = 7;
|
||||
pub const CONTINENT_FACTOR: f32 = 0.75;
|
||||
pub const CONTINENT_MIN_WIDTH_FACTOR: f32 = 3.0;
|
||||
pub const CONTINENT_MAX_WIDTH_FACTOR: f32 = 7.0;
|
||||
const NUM_CONTINENTS: u8 = 7;
|
||||
const CONTINENT_MIN_WIDTH_FACTOR: f32 = 3.0;
|
||||
const CONTINENT_MAX_WIDTH_FACTOR: f32 = 7.0;
|
||||
|
||||
pub const MIN_ALTITUDE: f32 = -10000.0;
|
||||
pub const MAX_ALTITUDE: f32 = 10000.0;
|
||||
pub const ALTITUDE_SPAN: f32 = World::MAX_ALTITUDE - World::MIN_ALTITUDE;
|
||||
pub(crate) const MIN_ALTITUDE: f32 = -15000.0;
|
||||
pub(crate) const MAX_ALTITUDE: f32 = 15000.0;
|
||||
const ALTITUDE_SPAN: f32 = World::MAX_ALTITUDE - World::MIN_ALTITUDE;
|
||||
|
||||
pub const MOUNTAIN_RANGE_MIX_FACTOR: f32 = 0.075;
|
||||
pub const MOUNTAIN_RANGE_WIDTH_FACTOR: f32 = 25.0;
|
||||
const MOUNTAIN_RANGE_MIX_FACTOR: f32 = 0.075;
|
||||
const MOUNTAIN_RANGE_WIDTH_FACTOR: f32 = 25.0;
|
||||
|
||||
pub const TERRAIN_NOISE_FACTOR_1: f32 = 0.2;
|
||||
pub const TERRAIN_NOISE_FACTOR_2: f32 = 0.15;
|
||||
pub const TERRAIN_NOISE_FACTOR_3: f32 = 0.1;
|
||||
const TERRAIN_NOISE_FACTOR_1: f32 = 0.15;
|
||||
const TERRAIN_NOISE_FACTOR_2: f32 = 0.15;
|
||||
const TERRAIN_NOISE_FACTOR_3: f32 = 0.1;
|
||||
const TERRAIN_NOISE_FACTOR_4: f32 = 2.5;
|
||||
|
||||
pub const MIN_RAINFALL: f32 = 0.0;
|
||||
pub const MAX_RAINFALL: f32 = 5000.0;
|
||||
pub const RAINFALL_SPAN: f32 = World::MAX_RAINFALL - World::MIN_RAINFALL;
|
||||
pub const RAINFALL_ALTITUDE_FACTOR: f32 = 1.0;
|
||||
pub const RAINFALL_DRYNESS_FACTOR: f32 = 0.001;
|
||||
pub const RAINFALL_DRYNESS_OFFSET: f32 = World::RAINFALL_DRYNESS_FACTOR * World::MAX_RAINFALL;
|
||||
pub(crate) const MIN_RAINFALL: f32 = 0.0;
|
||||
pub(crate) const MAX_RAINFALL: f32 = 7500.0;
|
||||
const RAINFALL_SPAN: f32 = World::MAX_RAINFALL - World::MIN_RAINFALL;
|
||||
const RAINFALL_DRYNESS_FACTOR: f32 = 0.005;
|
||||
const RAINFALL_DRYNESS_OFFSET: f32 = World::RAINFALL_DRYNESS_FACTOR * World::MAX_RAINFALL;
|
||||
|
||||
pub const MIN_TEMPERATURE: f32 = -50.0;
|
||||
pub const MAX_TEMPERATURE: f32 = 30.0;
|
||||
pub const TEMPERATURE_SPAN: f32 = World::MAX_TEMPERATURE - World::MIN_RAINFALL;
|
||||
pub const TEMPERATURE_ALTITUDE_FACTOR: f32 = 1.0;
|
||||
pub(crate) const MIN_TEMPERATURE: f32 = -60.0;
|
||||
pub(crate) const MAX_TEMPERATURE: f32 = 30.0;
|
||||
const TEMPERATURE_SPAN: f32 = World::MAX_TEMPERATURE - World::MIN_TEMPERATURE;
|
||||
const TEMPERATURE_ALTITUDE_FACTOR: f32 = 1.0;
|
||||
|
||||
pub fn generate(&mut self) -> Result<(), WorldGenError> {
|
||||
if let Err(err) = self.generate_altitude() {
|
||||
|
@ -145,6 +134,8 @@ impl World {
|
|||
return Err(WorldGenError::CartesianError(err));
|
||||
}
|
||||
|
||||
self.generate_biomes();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -254,9 +245,16 @@ impl World {
|
|||
World::MOUNTAIN_RANGE_MIX_FACTOR,
|
||||
)),
|
||||
value_3,
|
||||
World::TERRAIN_NOISE_FACTOR_1 * 1.5,
|
||||
) * mix_values(1.0, value_4, World::TERRAIN_NOISE_FACTOR_2 * 1.5)
|
||||
* mix_values(1.0, value_5, World::TERRAIN_NOISE_FACTOR_3 * 1.5);
|
||||
World::TERRAIN_NOISE_FACTOR_1 * World::TERRAIN_NOISE_FACTOR_4,
|
||||
) * mix_values(
|
||||
1.0,
|
||||
value_4,
|
||||
World::TERRAIN_NOISE_FACTOR_2 * World::TERRAIN_NOISE_FACTOR_4,
|
||||
) * mix_values(
|
||||
1.0,
|
||||
value_5,
|
||||
World::TERRAIN_NOISE_FACTOR_3 * World::TERRAIN_NOISE_FACTOR_4,
|
||||
);
|
||||
|
||||
let mut value_d = mix_values(value_a, value_c, 0.25);
|
||||
value_d = mix_values(value_d, value_c, 0.1);
|
||||
|
@ -364,10 +362,10 @@ impl World {
|
|||
(altitude - (offset_altitude * 1.5) - (offset_altitude_2 * 1.5))
|
||||
/ World::MAX_ALTITUDE;
|
||||
|
||||
let normalized_rainfall = mix_values(latitude_modifier_1, altitude_modifier, 0.6);
|
||||
let rainfall_value = mix_values(latitude_modifier_1, altitude_modifier, 0.63);
|
||||
let rainfall = f32::min(
|
||||
World::MAX_RAINFALL,
|
||||
World::calculate_rainfall(normalized_rainfall),
|
||||
World::calculate_rainfall(rainfall_value),
|
||||
);
|
||||
|
||||
cell.rainfall = rainfall;
|
||||
|
@ -408,17 +406,14 @@ impl World {
|
|||
|
||||
let cell = &mut self.terrain[y][x];
|
||||
|
||||
let latitude_modifer = mix_values(alpha, random_noise * PI, 0.1);
|
||||
let altitude_factor = f32::max(
|
||||
0.0,
|
||||
(cell.altitude / World::MAX_ALTITUDE)
|
||||
* 2.5
|
||||
* World::TEMPERATURE_ALTITUDE_FACTOR,
|
||||
(cell.altitude / World::MAX_ALTITUDE) * World::TEMPERATURE_ALTITUDE_FACTOR,
|
||||
);
|
||||
let temperature =
|
||||
World::calculate_temperature(f32::sin(latitude_modifer) - altitude_factor);
|
||||
|
||||
let latitude_modifer = (alpha * 0.8) + (random_noise * 0.2 * PI);
|
||||
let base_temperature = World::calculate_temperature(f32::sin(latitude_modifer));
|
||||
|
||||
let temperature = base_temperature * (1.0 - altitude_factor);
|
||||
cell.temperature = temperature;
|
||||
|
||||
if temperature > self.max_temperature {
|
||||
|
@ -440,4 +435,83 @@ impl World {
|
|||
World::MAX_TEMPERATURE,
|
||||
)
|
||||
}
|
||||
|
||||
fn generate_biomes(&mut self) {
|
||||
for y in 0..self.terrain.len() {
|
||||
for x in 0..self.terrain[y].len() {
|
||||
let cell = &self.terrain[y][x];
|
||||
|
||||
let mut total_presence = 0.0;
|
||||
|
||||
let mut biome_presences = vec![];
|
||||
for biome_type in BiomeType::BIOMES {
|
||||
let presence = self.biome_presence(cell, &biome_type.into());
|
||||
|
||||
if presence <= 0.0 {
|
||||
continue;
|
||||
}
|
||||
|
||||
biome_presences.push((*biome_type, presence));
|
||||
total_presence += presence;
|
||||
}
|
||||
self.terrain[y][x].biome_presences = biome_presences
|
||||
.iter()
|
||||
.map(|(biome_type, presence)| (*biome_type, presence / total_presence))
|
||||
.collect();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn biome_presence(&self, cell: &TerrainCell, biome: &Biome) -> f32 {
|
||||
let mut presence = 0.0;
|
||||
let altitude_diff = cell.altitude - biome.min_altitude;
|
||||
if altitude_diff < 0.0 {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
let altitude_factor = altitude_diff / (biome.max_altitude - biome.min_altitude);
|
||||
if altitude_factor > 1.0 {
|
||||
return 0.0;
|
||||
};
|
||||
|
||||
presence += if altitude_factor > 0.5 {
|
||||
1.0 - altitude_factor
|
||||
} else {
|
||||
altitude_factor
|
||||
};
|
||||
|
||||
let rainfall_diff = cell.rainfall - biome.min_rainfall;
|
||||
if rainfall_diff < 0.0 {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
let rainfall_factor = rainfall_diff / (biome.max_rainfall - biome.min_rainfall);
|
||||
if rainfall_factor > 1.0 {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
presence += if rainfall_factor > 0.5 {
|
||||
1.0 - rainfall_factor
|
||||
} else {
|
||||
rainfall_factor
|
||||
};
|
||||
|
||||
let temperature_diff = cell.temperature - biome.min_temperature;
|
||||
if temperature_diff < 0.0 {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
let temperature_factor = temperature_diff / (biome.max_temperature - biome.min_temperature);
|
||||
if temperature_factor > 1.0 {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
presence += if temperature_factor > 0.5 {
|
||||
1.0 - temperature_factor
|
||||
} else {
|
||||
temperature_factor
|
||||
};
|
||||
|
||||
presence
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#[cfg(feature = "render")]
|
||||
use crate::TerrainCell;
|
||||
use crate::{World, WorldGenError};
|
||||
use crate::{Biome, World, WorldGenError};
|
||||
#[cfg(all(feature = "debug", feature = "render"))]
|
||||
use bevy::log::debug;
|
||||
use bevy::log::warn;
|
||||
|
@ -94,6 +94,8 @@ pub struct WorldManager {
|
|||
#[cfg(feature = "render")]
|
||||
temperature_visible: bool,
|
||||
#[cfg(feature = "render")]
|
||||
biomes_visible: bool,
|
||||
#[cfg(feature = "render")]
|
||||
contours: bool,
|
||||
}
|
||||
|
||||
|
@ -108,6 +110,8 @@ impl WorldManager {
|
|||
#[cfg(feature = "render")]
|
||||
temperature_visible: false,
|
||||
#[cfg(feature = "render")]
|
||||
biomes_visible: false,
|
||||
#[cfg(feature = "render")]
|
||||
contours: true,
|
||||
}
|
||||
}
|
||||
|
@ -208,6 +212,17 @@ impl WorldManager {
|
|||
self.temperature_visible = !self.temperature_visible;
|
||||
}
|
||||
|
||||
#[cfg(feature = "render")]
|
||||
pub fn toggle_biomes(&mut self) {
|
||||
#[cfg(feature = "debug")]
|
||||
if self.temperature_visible {
|
||||
debug!("Turning biomes off");
|
||||
} else {
|
||||
debug!("Turning biomes on");
|
||||
}
|
||||
self.biomes_visible = !self.biomes_visible;
|
||||
}
|
||||
|
||||
#[cfg(feature = "render")]
|
||||
pub fn toggle_contours(&mut self) {
|
||||
#[cfg(feature = "debug")]
|
||||
|
@ -237,6 +252,10 @@ impl WorldManager {
|
|||
|
||||
#[cfg(feature = "render")]
|
||||
fn generate_color(&self, cell: &TerrainCell) -> Color {
|
||||
if self.biomes_visible {
|
||||
return WorldManager::biome_color(cell);
|
||||
}
|
||||
|
||||
let altitude_color = if self.contours {
|
||||
WorldManager::altitude_contour_color(cell.altitude)
|
||||
} else {
|
||||
|
@ -245,9 +264,9 @@ impl WorldManager {
|
|||
|
||||
let mut layer_count = 1.0;
|
||||
|
||||
let mut r = altitude_color.r();
|
||||
let mut g = altitude_color.g();
|
||||
let mut b = altitude_color.b();
|
||||
let mut red = altitude_color.r();
|
||||
let mut green = altitude_color.g();
|
||||
let mut blue = altitude_color.b();
|
||||
|
||||
if self.rainfall_visible {
|
||||
layer_count += 1.0;
|
||||
|
@ -258,9 +277,9 @@ impl WorldManager {
|
|||
// WorldManager::rainfall_color(cell.rainfall)
|
||||
// };
|
||||
|
||||
r += rainfall_color.r();
|
||||
g += rainfall_color.g();
|
||||
b += rainfall_color.b();
|
||||
red += rainfall_color.r();
|
||||
green += rainfall_color.g();
|
||||
blue += rainfall_color.b();
|
||||
}
|
||||
|
||||
if self.temperature_visible {
|
||||
|
@ -272,12 +291,12 @@ impl WorldManager {
|
|||
// WorldManager::temperature_color(cell.temperature)
|
||||
// };
|
||||
|
||||
r += temperature_color.r();
|
||||
g += temperature_color.g();
|
||||
b += temperature_color.b();
|
||||
red += temperature_color.r();
|
||||
green += temperature_color.g();
|
||||
blue += temperature_color.b();
|
||||
}
|
||||
|
||||
Color::rgb(r / layer_count, g / layer_count, b / layer_count)
|
||||
Color::rgb(red / layer_count, green / layer_count, blue / layer_count)
|
||||
}
|
||||
|
||||
#[cfg(feature = "render")]
|
||||
|
@ -318,15 +337,6 @@ impl WorldManager {
|
|||
Color::rgb(0.0, shade_value, 0.0)
|
||||
}
|
||||
|
||||
#[cfg(feature = "render")]
|
||||
fn rainfall_color(rainfall: f32) -> Color {
|
||||
if rainfall <= 0.0 {
|
||||
Color::BLACK
|
||||
} else {
|
||||
Color::rgb(0.0, rainfall / World::MAX_RAINFALL, 0.0)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "render")]
|
||||
fn temperature_contour_color(&self, temperature: f32) -> Color {
|
||||
let mut shade_value = 1.0;
|
||||
|
@ -341,14 +351,19 @@ impl WorldManager {
|
|||
}
|
||||
|
||||
#[cfg(feature = "render")]
|
||||
fn temperature_color(temperature: f32) -> Color {
|
||||
let normalized_temperature = WorldManager::normalize_temperature(temperature);
|
||||
Color::rgb(normalized_temperature, 1.0 - normalized_temperature, 0.0)
|
||||
}
|
||||
fn biome_color(cell: &TerrainCell) -> Color {
|
||||
cell.biome_presences
|
||||
.iter()
|
||||
.fold(Color::BLACK, |color, (biome_type, presence)| {
|
||||
let biome: Biome = (*biome_type).into();
|
||||
let biome_color = biome.color;
|
||||
|
||||
#[cfg(feature = "render")]
|
||||
fn normalize_temperature(temperature: f32) -> f32 {
|
||||
(temperature - World::MIN_TEMPERATURE) / World::TEMPERATURE_SPAN
|
||||
Color::rgb(
|
||||
color.r() + (biome_color.r() * presence),
|
||||
color.g() + (biome_color.g() * presence),
|
||||
color.b() + (biome_color.b() * presence),
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(feature = "render")]
|
||||
|
|
|
@ -2,28 +2,29 @@
|
|||
use bevy::ecs::component::Component;
|
||||
|
||||
#[cfg(feature = "render")]
|
||||
macro_rules! define_enum {
|
||||
($Name:ident { $($Variant:ident),* $(,)* }) =>
|
||||
macro_rules! toolbar_enum {
|
||||
($($Variant:ident),*$(,)?) =>
|
||||
{
|
||||
#[derive(Debug, Component, Copy, Clone)]
|
||||
pub enum $Name {
|
||||
pub enum ToolbarButton {
|
||||
$($Variant),*,
|
||||
}
|
||||
impl $Name {
|
||||
pub const ITEMS: &'static [$Name] = &[$($Name::$Variant),*];
|
||||
impl ToolbarButton {
|
||||
pub const BUTTONS: &'static [ToolbarButton] = &[$(ToolbarButton::$Variant),*];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "render")]
|
||||
define_enum!(ToolbarButton {
|
||||
toolbar_enum!(
|
||||
GenerateWorld,
|
||||
SaveWorld,
|
||||
LoadWorld,
|
||||
Rainfall,
|
||||
Temperature,
|
||||
Biomes,
|
||||
Contours,
|
||||
});
|
||||
);
|
||||
|
||||
#[cfg(feature = "render")]
|
||||
impl From<ToolbarButton> for &'static str {
|
||||
|
@ -32,6 +33,7 @@ impl From<ToolbarButton> for &'static str {
|
|||
ToolbarButton::Rainfall => "Toggle rainfall",
|
||||
ToolbarButton::Temperature => "Toggle temperature",
|
||||
ToolbarButton::Contours => "Toggle contours",
|
||||
ToolbarButton::Biomes => "Toggle biomes",
|
||||
ToolbarButton::GenerateWorld => "Generate new world",
|
||||
ToolbarButton::SaveWorld => "Save",
|
||||
ToolbarButton::LoadWorld => "Load",
|
||||
|
@ -41,14 +43,7 @@ impl From<ToolbarButton> for &'static str {
|
|||
#[cfg(feature = "render")]
|
||||
impl From<&ToolbarButton> for &'static str {
|
||||
fn from(button: &ToolbarButton) -> Self {
|
||||
match button {
|
||||
ToolbarButton::Rainfall => "Toggle rainfall",
|
||||
ToolbarButton::Temperature => "Toggle temperature",
|
||||
ToolbarButton::Contours => "Toggle contours",
|
||||
ToolbarButton::GenerateWorld => "Generate new world",
|
||||
ToolbarButton::SaveWorld => "Save",
|
||||
ToolbarButton::LoadWorld => "Load",
|
||||
}
|
||||
(*button).into()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
42
src/main.rs
42
src/main.rs
|
@ -82,6 +82,7 @@ use bevy::{
|
|||
window::{CursorIcon, WindowDescriptor, Windows},
|
||||
winit::WinitSettings,
|
||||
};
|
||||
use planet::Biome;
|
||||
|
||||
#[cfg(all(feature = "debug", feature = "render"))]
|
||||
use bevy::{
|
||||
|
@ -154,6 +155,12 @@ fn handle_toolbar_button(
|
|||
world_manager.toggle_temperature();
|
||||
refresh_world_texture(&mut images, &world_manager);
|
||||
}
|
||||
ToolbarButton::Biomes => {
|
||||
#[cfg(feature = "debug")]
|
||||
debug!("Toggling biomes");
|
||||
world_manager.toggle_biomes();
|
||||
refresh_world_texture(&mut images, &world_manager);
|
||||
}
|
||||
ToolbarButton::Contours => {
|
||||
#[cfg(feature = "debug")]
|
||||
debug!("Toggling contours");
|
||||
|
@ -250,7 +257,7 @@ fn update_info_panel(
|
|||
#[cfg(feature = "debug")]
|
||||
{
|
||||
format!(
|
||||
"FPS: ~{}\nMouse position: {}\nAltitude: {}\nRainfall: {}\nTemperature: {}",
|
||||
"FPS: ~{}\nMouse position: {}\nAltitude: {}\nRainfall: {}\nTemperature: {}\n\n{}",
|
||||
match diagnostics.get_measurement(FrameTimeDiagnosticsPlugin::FPS) {
|
||||
None => f64::NAN,
|
||||
Some(fps) => fps.value.round(),
|
||||
|
@ -258,15 +265,40 @@ fn update_info_panel(
|
|||
*cursor_position,
|
||||
cell.altitude,
|
||||
cell.rainfall,
|
||||
cell.temperature
|
||||
cell.temperature,
|
||||
cell.biome_presences
|
||||
.iter()
|
||||
.map(|(biome_type, presence)| {
|
||||
format!(
|
||||
"Biome: {} ({:.2}%)",
|
||||
(<Biome>::from(biome_type).name),
|
||||
presence * 100.0
|
||||
)
|
||||
})
|
||||
.collect::<Vec<String>>()
|
||||
.join("\n")
|
||||
)
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "debug"))]
|
||||
{
|
||||
format!(
|
||||
"Mouse position: {}\nAltitude: {}\nRainfall: {}\nTemperature: {}",
|
||||
*cursor_position, cell.altitude, cell.rainfall, cell.temperature
|
||||
"Mouse position: {}\nAltitude: {}\nRainfall: {}\nTemperature: {}\n{}",
|
||||
*cursor_position,
|
||||
cell.altitude,
|
||||
cell.rainfall,
|
||||
cell.temperature,
|
||||
cell.biome_presences
|
||||
.iter()
|
||||
.map(|(biome_type, presence)| {
|
||||
format!(
|
||||
"Biome: {} ({:.2}%)",
|
||||
(<Biome>::from(biome_type).name),
|
||||
presence * 100.0
|
||||
)
|
||||
})
|
||||
.collect::<Vec<String>>()
|
||||
.join("\n")
|
||||
)
|
||||
}
|
||||
} else {
|
||||
|
@ -422,7 +454,7 @@ fn generate_graphics(
|
|||
..default()
|
||||
})
|
||||
.with_children(|button_box| {
|
||||
ToolbarButton::ITEMS.iter().for_each(|&button_type| {
|
||||
ToolbarButton::BUTTONS.iter().for_each(|&button_type| {
|
||||
_ = button_box
|
||||
.spawn_bundle(toolbar_button())
|
||||
.with_children(|button| {
|
||||
|
|
Loading…
Reference in a new issue