Make world generation asynchronous; Update dependencies (Bevy 0.9, ayyy)
This commit is contained in:
parent
030f590d79
commit
f65f29e6b0
17 changed files with 535 additions and 503 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1 +1,2 @@
|
|||
/target
|
||||
.fleet/run.json
|
614
Cargo.lock
generated
614
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
10
Cargo.toml
10
Cargo.toml
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "worlds-history-sim-rs"
|
||||
version = "0.2.1"
|
||||
version = "0.3.0"
|
||||
edition = "2021"
|
||||
resolver = "2"
|
||||
|
||||
|
@ -35,7 +35,7 @@ path = "planet"
|
|||
default-features = false
|
||||
|
||||
[dependencies.bevy]
|
||||
version = "0.8.1"
|
||||
version = "0.9.0"
|
||||
default-features = false
|
||||
|
||||
[dependencies.fxhash]
|
||||
|
@ -43,7 +43,7 @@ version = "0.2.1"
|
|||
optional = true
|
||||
|
||||
[dependencies.bevy_egui]
|
||||
version = "0.16.1"
|
||||
version = "0.17"
|
||||
optional = true
|
||||
default-features = false
|
||||
features = ["manage_clipboard"]
|
||||
|
@ -51,3 +51,7 @@ features = ["manage_clipboard"]
|
|||
[dependencies.tinyfiledialogs]
|
||||
version = "3.9.1"
|
||||
optional = true
|
||||
|
||||
[dependencies.futures-lite]
|
||||
version = "1.12.0"
|
||||
default-features = false
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "planet"
|
||||
version = "0.2.1"
|
||||
version = "0.3.0"
|
||||
edition = "2021"
|
||||
|
||||
[profile]
|
||||
|
@ -15,7 +15,7 @@ default = ["logging", "render"]
|
|||
version = "0.8.5"
|
||||
|
||||
[dependencies.bevy]
|
||||
version = "0.8"
|
||||
version = "0.9.0"
|
||||
default-features = false
|
||||
|
||||
[dependencies.serde]
|
||||
|
@ -24,4 +24,4 @@ default-features = false
|
|||
features = ["derive"]
|
||||
|
||||
[dependencies.ron]
|
||||
version = "0.7.1"
|
||||
version = "0.8.0"
|
|
@ -1,4 +1,3 @@
|
|||
// TODO: Logging doesn't seem to work here? Figure out why and fix
|
||||
use {
|
||||
crate::{
|
||||
math_util::{
|
||||
|
@ -149,6 +148,27 @@ impl World {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn async_new(width: u32, height: u32, seed: u32) -> World {
|
||||
World {
|
||||
width,
|
||||
height,
|
||||
seed,
|
||||
terrain: vec![
|
||||
vec![TerrainCell::default(); width.try_into().unwrap()];
|
||||
height.try_into().unwrap()
|
||||
],
|
||||
continent_offsets: [default(); World::NUM_CONTINENTS as usize],
|
||||
continent_sizes: [default(); World::NUM_CONTINENTS as usize],
|
||||
max_altitude: World::MIN_ALTITUDE,
|
||||
min_altitude: World::MAX_ALTITUDE,
|
||||
max_rainfall: World::MIN_RAINFALL,
|
||||
min_rainfall: World::MAX_RAINFALL,
|
||||
max_temperature: World::MIN_TEMPERATURE,
|
||||
min_temperature: World::MAX_TEMPERATURE,
|
||||
rng: StdRng::seed_from_u64(seed as u64),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn generate(&mut self) -> Result<(), WorldGenError> {
|
||||
if let Err(err) = self.generate_altitude() {
|
||||
return Err(WorldGenError::CartesianError(err));
|
||||
|
|
|
@ -1,6 +1,11 @@
|
|||
use {
|
||||
crate::{World, WorldGenError},
|
||||
bevy::{log::warn, utils::default},
|
||||
bevy::{
|
||||
log::warn,
|
||||
prelude::Resource,
|
||||
tasks::{AsyncComputeTaskPool, Task},
|
||||
utils::default,
|
||||
},
|
||||
rand::random,
|
||||
std::{
|
||||
error::Error,
|
||||
|
@ -14,7 +19,7 @@ use {
|
|||
#[derive(Debug)]
|
||||
pub enum LoadError {
|
||||
MissingSave(io::Error),
|
||||
InvalidSave(ron::Error),
|
||||
InvalidSave(ron::error::SpannedError),
|
||||
}
|
||||
impl Error for LoadError {
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
|
@ -74,12 +79,15 @@ impl Display for SaveError {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
#[derive(Debug, Default, Resource)]
|
||||
pub struct WorldManager {
|
||||
world: Option<World>,
|
||||
}
|
||||
|
||||
impl WorldManager {
|
||||
const NEW_WORLD_HEIGHT: u32 = 200;
|
||||
const NEW_WORLD_WIDTH: u32 = 400;
|
||||
|
||||
#[must_use]
|
||||
pub fn new() -> WorldManager {
|
||||
default()
|
||||
|
@ -160,11 +168,34 @@ impl WorldManager {
|
|||
self.get_world().unwrap()
|
||||
}
|
||||
|
||||
pub fn set_world(&mut self, world: World) {
|
||||
self.world = Some(world);
|
||||
}
|
||||
|
||||
pub fn new_world(&mut self, seed: Option<u32>) -> Result<&World, WorldGenError> {
|
||||
let seed = seed.unwrap_or_else(random);
|
||||
let mut new_world = World::new(400, 200, seed);
|
||||
let mut new_world = World::new(
|
||||
WorldManager::NEW_WORLD_WIDTH,
|
||||
WorldManager::NEW_WORLD_HEIGHT,
|
||||
seed,
|
||||
);
|
||||
new_world.generate()?;
|
||||
self.world = Some(new_world);
|
||||
Ok(self.get_world().unwrap())
|
||||
}
|
||||
|
||||
pub fn new_world_async(&mut self, seed: Option<u32>) -> Task<Result<World, WorldGenError>> {
|
||||
AsyncComputeTaskPool::get().spawn(async move {
|
||||
let seed = seed.unwrap_or_else(random);
|
||||
let mut new_world = World::async_new(
|
||||
WorldManager::NEW_WORLD_WIDTH,
|
||||
WorldManager::NEW_WORLD_HEIGHT,
|
||||
seed,
|
||||
);
|
||||
match new_world.generate() {
|
||||
Ok(()) => Ok(new_world),
|
||||
Err(err) => Err(err),
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,2 +1 @@
|
|||
#[cfg(feature = "render")]
|
||||
pub(crate) mod panning;
|
||||
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
use bevy::ecs::component::Component;
|
||||
|
||||
#[derive(Component)]
|
||||
pub(crate) struct Pan2d {
|
||||
pub(crate) enabled: bool,
|
||||
}
|
||||
impl Pan2d {
|
||||
#[must_use]
|
||||
pub(crate) const fn new() -> Pan2d {
|
||||
Pan2d { enabled: true }
|
||||
}
|
||||
}
|
|
@ -6,6 +6,7 @@ use {
|
|||
world::World,
|
||||
},
|
||||
log::debug,
|
||||
prelude::*,
|
||||
utils::HashMap,
|
||||
},
|
||||
bevy_egui::egui::Ui,
|
||||
|
@ -44,8 +45,8 @@ pub(crate) fn widget<S: 'static + WidgetSystem>(world: &mut World, ui: &mut Ui,
|
|||
/// A UI widget may have multiple instances. We need to ensure the local state
|
||||
/// of these instances is not shared. This hashmap allows us to dynamically
|
||||
/// store instance states.
|
||||
#[derive(Default)]
|
||||
struct StateInstances<T: WidgetSystem> {
|
||||
#[derive(Default, Resource)]
|
||||
struct StateInstances<T: WidgetSystem + 'static> {
|
||||
instances: HashMap<WidgetId, SystemState<T>>,
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ use {
|
|||
WidgetSystem,
|
||||
},
|
||||
macros::iterable_enum,
|
||||
resources::{OpenedWindows, ShouldRedraw},
|
||||
resources::{GenerateWorldTask, OpenedWindows},
|
||||
},
|
||||
bevy::{
|
||||
ecs::{
|
||||
|
@ -34,10 +34,11 @@ impl ToolbarButton {
|
|||
world.resource_scope(|world, mut world_manager: Mut<'_, WorldManager>| {
|
||||
match self {
|
||||
ToolbarButton::GenerateWorld => {
|
||||
if let Err(err) = world_manager.new_world(None) {
|
||||
eprintln!("Failed to generate world: {}", err);
|
||||
let generate_world_task = &mut world.resource_mut::<GenerateWorldTask>();
|
||||
if generate_world_task.0.is_some() {
|
||||
debug!("Already generating new world")
|
||||
} else {
|
||||
world.resource_mut::<ShouldRedraw>().0 = true;
|
||||
generate_world_task.0 = Some(world_manager.new_world_async(None))
|
||||
}
|
||||
},
|
||||
ToolbarButton::SaveLoad => {
|
||||
|
|
|
@ -8,6 +8,7 @@ use {
|
|||
world::World,
|
||||
},
|
||||
log::debug,
|
||||
prelude::Resource,
|
||||
utils::HashMap,
|
||||
},
|
||||
bevy_egui::egui::{Context, Ui, Window},
|
||||
|
@ -80,8 +81,8 @@ fn window<S: 'static + WindowSystem>(world: &mut World, ctx: &Context) {
|
|||
});
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct StateInstances<T: WindowSystem> {
|
||||
#[derive(Default, Resource)]
|
||||
struct StateInstances<T: WindowSystem + 'static> {
|
||||
instances: HashMap<WindowId, SystemState<T>>,
|
||||
}
|
||||
|
||||
|
|
152
src/main.rs
152
src/main.rs
|
@ -1,5 +1,10 @@
|
|||
#![cfg_attr(not(feature = "logging"), windows_subsystem = "windows")]
|
||||
|
||||
use {
|
||||
crate::resources::GenerateWorldTask,
|
||||
futures_lite::future::{block_on, poll_once},
|
||||
};
|
||||
|
||||
pub(crate) mod components;
|
||||
#[cfg(feature = "render")]
|
||||
pub(crate) mod gui;
|
||||
|
@ -7,52 +12,16 @@ pub(crate) mod macros;
|
|||
#[cfg(feature = "render")]
|
||||
pub(crate) mod planet_renderer;
|
||||
pub(crate) mod plugins;
|
||||
#[cfg(feature = "render")]
|
||||
pub(crate) mod resources;
|
||||
|
||||
use {
|
||||
bevy::{
|
||||
app::App,
|
||||
log::LogSettings,
|
||||
utils::{default, tracing::Level},
|
||||
},
|
||||
planet::WorldManager,
|
||||
plugins::WorldPlugins,
|
||||
};
|
||||
use {bevy::prelude::*, planet::WorldManager, plugins::WorldPlugins};
|
||||
#[cfg(feature = "render")]
|
||||
use {
|
||||
bevy::{
|
||||
asset::Assets,
|
||||
core_pipeline::core_2d::{Camera2d, Camera2dBundle},
|
||||
ecs::{
|
||||
change_detection::{Mut, ResMut},
|
||||
query::With,
|
||||
system::{Commands, IntoExclusiveSystem, Query, Res},
|
||||
world::World,
|
||||
},
|
||||
input::{keyboard::KeyCode, Input},
|
||||
prelude::Vec2,
|
||||
render::{
|
||||
camera::{Camera, RenderTarget},
|
||||
render_resource::{
|
||||
Extent3d,
|
||||
TextureDescriptor,
|
||||
TextureDimension,
|
||||
TextureFormat,
|
||||
TextureUsages,
|
||||
},
|
||||
texture::{Image, ImageSettings},
|
||||
},
|
||||
sprite::{Sprite, SpriteBundle},
|
||||
transform::components::GlobalTransform,
|
||||
window::{WindowDescriptor, Windows},
|
||||
winit::WinitSettings,
|
||||
},
|
||||
bevy::render::camera::RenderTarget,
|
||||
bevy_egui::{
|
||||
egui::{FontData, FontDefinitions, FontFamily},
|
||||
EguiContext,
|
||||
},
|
||||
components::panning::Pan2d,
|
||||
gui::{render_windows, widget, widgets::ToolbarWidget, window::open_window, windows::TileInfo},
|
||||
planet_renderer::{WorldRenderSettings, WorldRenderer},
|
||||
resources::{CursorMapPosition, OpenedWindows, ShouldRedraw},
|
||||
|
@ -98,16 +67,45 @@ fn update_cursor_map_position(
|
|||
}
|
||||
}
|
||||
|
||||
fn handle_generate_world_task(
|
||||
mut generate_world_task: ResMut<'_, GenerateWorldTask>,
|
||||
mut world_manager: ResMut<'_, WorldManager>,
|
||||
#[cfg(feature = "render")] mut should_redraw: ResMut<'_, ShouldRedraw>,
|
||||
) {
|
||||
if let Some(task) = &mut generate_world_task.0 {
|
||||
if task.is_finished() {
|
||||
debug!("Done");
|
||||
if let Some(result) = block_on(poll_once(task)) {
|
||||
match result {
|
||||
Ok(world) => {
|
||||
world_manager.set_world(world);
|
||||
#[cfg(feature = "render")]
|
||||
{
|
||||
should_redraw.0 = true;
|
||||
}
|
||||
},
|
||||
Err(err) => error!("{err:#?}"),
|
||||
}
|
||||
}
|
||||
generate_world_task.0 = None;
|
||||
} else {
|
||||
debug!("Working")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "render")]
|
||||
fn generate_graphics(
|
||||
mut commands: Commands<'_, '_>,
|
||||
world_manager: ResMut<'_, WorldManager>,
|
||||
mut images: ResMut<'_, Assets<Image>>,
|
||||
mut egui_context: ResMut<'_, EguiContext>,
|
||||
mut render_settings: ResMut<'_, WorldRenderSettings>,
|
||||
images: ResMut<'_, Assets<Image>>,
|
||||
egui_context: ResMut<'_, EguiContext>,
|
||||
render_settings: ResMut<'_, WorldRenderSettings>,
|
||||
) {
|
||||
// Add Julia-Mono font to egui
|
||||
|
||||
{
|
||||
let egui_context = egui_context.into_inner();
|
||||
let ctx = egui_context.ctx_mut();
|
||||
let mut fonts = FontDefinitions::default();
|
||||
const FONT_NAME: &str = "Julia-Mono";
|
||||
|
@ -143,6 +141,14 @@ fn generate_graphics(
|
|||
};
|
||||
// Set up 2D map mode
|
||||
{
|
||||
use bevy::render::render_resource::{
|
||||
TextureDescriptor,
|
||||
TextureDimension,
|
||||
TextureFormat,
|
||||
TextureUsages,
|
||||
};
|
||||
let images = images.into_inner();
|
||||
let mut render_settings = render_settings.into_inner();
|
||||
let map_image_handle = images.add(Image {
|
||||
data: vec![],
|
||||
texture_descriptor: TextureDescriptor {
|
||||
|
@ -156,14 +162,13 @@ fn generate_graphics(
|
|||
},
|
||||
..default()
|
||||
});
|
||||
render_settings.map_image_handle_id = Some(map_image_handle.id);
|
||||
_ = commands
|
||||
.spawn_bundle(Camera2dBundle::default())
|
||||
.insert(Pan2d::new());
|
||||
render_settings.map_image_handle_id = Some(map_image_handle.id());
|
||||
_ = commands.spawn(Camera2dBundle::default());
|
||||
|
||||
// TODO: Switch to egui
|
||||
_ = commands.spawn_bundle(SpriteBundle {
|
||||
texture: images.get_handle(map_image_handle.id),
|
||||
_ = commands.spawn(SpriteBundle {
|
||||
texture: images
|
||||
.get_handle(unsafe { render_settings.map_image_handle_id.unwrap_unchecked() }),
|
||||
sprite: Sprite {
|
||||
custom_size: Some(custom_sprite_size),
|
||||
..default()
|
||||
|
@ -234,7 +239,7 @@ fn redraw_map(
|
|||
let map_image = images
|
||||
.get_mut(&map_image_handle)
|
||||
.expect("Map image handle pointing to non-existing image");
|
||||
map_image.resize(Extent3d {
|
||||
map_image.resize(bevy::render::render_resource::Extent3d {
|
||||
width: world_manager.world().width,
|
||||
height: world_manager.world().height,
|
||||
depth_or_array_layers: 1,
|
||||
|
@ -246,48 +251,49 @@ fn redraw_map(
|
|||
}
|
||||
|
||||
#[cfg(feature = "render")]
|
||||
const WORLD_SCALE: i32 = 4;
|
||||
const WORLD_SCALE: i32 = 2;
|
||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let mut app = App::new();
|
||||
let mut manager = WorldManager::new();
|
||||
#[cfg(feature = "render")]
|
||||
{
|
||||
let world = manager.new_world(None)?;
|
||||
use bevy::winit::WinitSettings;
|
||||
|
||||
let world = manager.new_world(Some(0))?;
|
||||
_ = app
|
||||
.insert_resource(WinitSettings::game())
|
||||
// Use nearest-neighbor rendering for cripsier pixels
|
||||
.insert_resource(ImageSettings::default_nearest())
|
||||
.insert_resource(WindowDescriptor {
|
||||
.insert_resource(CursorMapPosition::default())
|
||||
.insert_resource(OpenedWindows::default())
|
||||
.insert_resource(WorldRenderSettings::default())
|
||||
.insert_resource(ShouldRedraw::default())
|
||||
.insert_resource(GenerateWorldTask::default())
|
||||
.add_startup_system(generate_graphics)
|
||||
.add_system(update_gui)
|
||||
.add_system(update_cursor_map_position)
|
||||
.add_system(open_tile_info)
|
||||
.add_system(redraw_map);
|
||||
|
||||
app.add_plugins(WorldPlugins.set(WindowPlugin {
|
||||
window: WindowDescriptor {
|
||||
width: (WORLD_SCALE * world.width as i32) as f32,
|
||||
height: (WORLD_SCALE * world.height as i32) as f32,
|
||||
title: String::from("World-RS"),
|
||||
resizable: true,
|
||||
..default()
|
||||
})
|
||||
.insert_resource(CursorMapPosition::default())
|
||||
.insert_resource(OpenedWindows::default())
|
||||
.insert_resource(WorldRenderSettings::default())
|
||||
.insert_resource(ShouldRedraw::default())
|
||||
.add_startup_system(generate_graphics)
|
||||
.add_system(update_gui.exclusive_system())
|
||||
.add_system(update_cursor_map_position)
|
||||
.add_system(open_tile_info)
|
||||
.add_system(redraw_map);
|
||||
},
|
||||
..default()
|
||||
}));
|
||||
}
|
||||
#[cfg(not(feature = "render"))]
|
||||
{
|
||||
_ = manager.new_world()?
|
||||
_ = manager.new_world(Some(0))?;
|
||||
|
||||
app.add_plugins(WorldPlugins);
|
||||
}
|
||||
|
||||
_ = app.insert_resource(LogSettings {
|
||||
#[cfg(feature = "logging")]
|
||||
level: Level::DEBUG,
|
||||
#[cfg(not(feature = "logging"))]
|
||||
level: Level::WARN,
|
||||
..default()
|
||||
});
|
||||
|
||||
app.add_plugins(WorldPlugins).insert_resource(manager).run();
|
||||
app.add_system(handle_generate_world_task)
|
||||
.insert_resource(manager)
|
||||
.run();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
use {
|
||||
crate::macros::iterable_enum_stringify,
|
||||
bevy::{asset::HandleId, prelude::Color, utils::HashSet},
|
||||
bevy::{
|
||||
asset::HandleId,
|
||||
prelude::{Color, Resource},
|
||||
utils::HashSet,
|
||||
},
|
||||
planet::{BiomeStats, TerrainCell, World, WorldManager},
|
||||
};
|
||||
|
||||
|
@ -15,7 +19,7 @@ iterable_enum_stringify!(WorldOverlay {
|
|||
});
|
||||
|
||||
#[cfg(feature = "render")]
|
||||
#[derive(Debug, Default)]
|
||||
#[derive(Debug, Default, Resource)]
|
||||
pub struct WorldRenderSettings {
|
||||
pub map_image_handle_id: Option<HandleId>,
|
||||
|
||||
|
|
|
@ -1,4 +1,2 @@
|
|||
#[cfg(feature = "render")]
|
||||
pub(crate) mod panning_plugin;
|
||||
pub(crate) mod world_plugins;
|
||||
pub(crate) use world_plugins::WorldPlugins;
|
||||
|
|
|
@ -1,47 +0,0 @@
|
|||
use {
|
||||
crate::components::panning::Pan2d,
|
||||
bevy::{
|
||||
app::{App, Plugin},
|
||||
ecs::{
|
||||
event::EventReader,
|
||||
query::With,
|
||||
system::{Query, Res},
|
||||
},
|
||||
input::{
|
||||
mouse::{MouseButton, MouseMotion},
|
||||
Input,
|
||||
},
|
||||
sprite::Sprite,
|
||||
transform::components::Transform,
|
||||
},
|
||||
};
|
||||
|
||||
#[derive(Default)]
|
||||
pub(crate) struct PanningPlugin;
|
||||
|
||||
impl Plugin for PanningPlugin {
|
||||
fn build(&self, app: &mut App) {
|
||||
_ = app.add_system(panning_system_2d);
|
||||
}
|
||||
}
|
||||
|
||||
fn panning_system_2d(
|
||||
mut query: Query<'_, '_, (&mut Transform, &Pan2d), With<Sprite>>,
|
||||
mut mouse_motion_events: EventReader<'_, '_, MouseMotion>,
|
||||
input_mouse: Res<'_, Input<MouseButton>>,
|
||||
) {
|
||||
if !input_mouse.pressed(MouseButton::Left) {
|
||||
return;
|
||||
}
|
||||
|
||||
let mut horizontal = 0.0;
|
||||
for movement in mouse_motion_events.iter() {
|
||||
horizontal += movement.delta.x;
|
||||
}
|
||||
|
||||
query.for_each_mut(|(mut transform, pan)| {
|
||||
if pan.enabled {
|
||||
transform.translation.x += horizontal;
|
||||
}
|
||||
});
|
||||
}
|
|
@ -1,65 +1,75 @@
|
|||
pub(crate) struct WorldPlugins;
|
||||
|
||||
#[cfg(not(feature = "render"))]
|
||||
use bevy::app::ScheduleRunnerPlugin;
|
||||
#[cfg(all(feature = "logging"))]
|
||||
use bevy::diagnostic::{DiagnosticsPlugin, FrameTimeDiagnosticsPlugin, LogDiagnosticsPlugin};
|
||||
use bevy::{
|
||||
app::{PluginGroup, PluginGroupBuilder},
|
||||
core::CorePlugin,
|
||||
diagnostic::{DiagnosticsPlugin, LogDiagnosticsPlugin},
|
||||
log::LogPlugin,
|
||||
log::{Level, LogPlugin},
|
||||
prelude::*,
|
||||
time::TimePlugin,
|
||||
};
|
||||
#[cfg(feature = "render")]
|
||||
use {
|
||||
bevy::{
|
||||
asset::AssetPlugin,
|
||||
core_pipeline::CorePipelinePlugin,
|
||||
input::InputPlugin,
|
||||
render::RenderPlugin,
|
||||
sprite::SpritePlugin,
|
||||
text::TextPlugin,
|
||||
transform::TransformPlugin,
|
||||
ui::UiPlugin,
|
||||
window::WindowPlugin,
|
||||
winit::WinitPlugin,
|
||||
},
|
||||
bevy_egui::EguiPlugin,
|
||||
};
|
||||
|
||||
impl PluginGroup for WorldPlugins {
|
||||
fn build(&mut self, group: &mut PluginGroupBuilder) {
|
||||
_ = group.add(LogPlugin).add(CorePlugin).add(TimePlugin);
|
||||
fn build(self) -> PluginGroupBuilder {
|
||||
let mut group_builder = PluginGroupBuilder::start::<Self>()
|
||||
.add(LogPlugin {
|
||||
#[cfg(feature = "logging")]
|
||||
level: Level::DEBUG,
|
||||
#[cfg(not(feature = "logging"))]
|
||||
level: Level::WARN,
|
||||
..default()
|
||||
})
|
||||
.add(CorePlugin::default()) // sets compute pool config
|
||||
.add(TimePlugin);
|
||||
|
||||
#[cfg(feature = "render")]
|
||||
{
|
||||
use {
|
||||
crate::plugins::panning_plugin::PanningPlugin,
|
||||
bevy::{
|
||||
asset::AssetPlugin,
|
||||
core_pipeline::CorePipelinePlugin,
|
||||
hierarchy::HierarchyPlugin,
|
||||
input::InputPlugin,
|
||||
render::RenderPlugin,
|
||||
sprite::SpritePlugin,
|
||||
text::TextPlugin,
|
||||
transform::TransformPlugin,
|
||||
ui::UiPlugin,
|
||||
window::WindowPlugin,
|
||||
winit::WinitPlugin,
|
||||
},
|
||||
bevy_egui::EguiPlugin,
|
||||
};
|
||||
|
||||
_ = group
|
||||
group_builder = group_builder
|
||||
.add(TransformPlugin)
|
||||
// hierarchy
|
||||
.add(InputPlugin)
|
||||
.add(WindowPlugin)
|
||||
.add(AssetPlugin)
|
||||
.add(HierarchyPlugin)
|
||||
.add(WinitPlugin)
|
||||
.add(WindowPlugin::default())
|
||||
.add(AssetPlugin::default())
|
||||
.add(RenderPlugin)
|
||||
.add(ImagePlugin::default_nearest())
|
||||
.add(WinitPlugin)
|
||||
.add(CorePipelinePlugin)
|
||||
.add(SpritePlugin)
|
||||
.add(TextPlugin)
|
||||
.add(UiPlugin)
|
||||
.add(PanningPlugin)
|
||||
.add(EguiPlugin);
|
||||
}
|
||||
#[cfg(not(feature = "render"))]
|
||||
{
|
||||
use bevy::app::ScheduleRunnerPlugin;
|
||||
_ = group.add(ScheduleRunnerPlugin);
|
||||
group_builder = group_builder.add(ScheduleRunnerPlugin);
|
||||
}
|
||||
|
||||
_ = group.add(DiagnosticsPlugin);
|
||||
#[cfg(all(feature = "logging"))]
|
||||
#[cfg(feature = "logging")]
|
||||
{
|
||||
use bevy::diagnostic::FrameTimeDiagnosticsPlugin;
|
||||
_ = group.add(FrameTimeDiagnosticsPlugin);
|
||||
group_builder = group_builder
|
||||
.add(DiagnosticsPlugin)
|
||||
.add(FrameTimeDiagnosticsPlugin)
|
||||
.add(LogDiagnosticsPlugin::default());
|
||||
}
|
||||
_ = group.add(LogDiagnosticsPlugin::default());
|
||||
|
||||
group_builder
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,26 +1,38 @@
|
|||
#[cfg(feature = "render")]
|
||||
use {crate::gui::WindowId, bevy::utils::HashSet, std::fmt::Display};
|
||||
use {
|
||||
bevy::{prelude::Resource, tasks::Task},
|
||||
planet::{World, WorldGenError},
|
||||
};
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
#[cfg(feature = "render")]
|
||||
#[derive(Default, Debug, Resource)]
|
||||
pub(crate) struct CursorMapPosition {
|
||||
pub(crate) x: i32,
|
||||
pub(crate) y: i32,
|
||||
}
|
||||
#[cfg(feature = "render")]
|
||||
impl Display for CursorMapPosition {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.write_fmt(format_args!("x: {}, y: {}", self.x, self.y))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "render")]
|
||||
#[derive(Resource)]
|
||||
pub(crate) struct ShouldRedraw(pub(crate) bool);
|
||||
#[cfg(feature = "render")]
|
||||
impl Default for ShouldRedraw {
|
||||
fn default() -> Self {
|
||||
Self(true)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
#[cfg(feature = "render")]
|
||||
#[derive(Default, Resource)]
|
||||
pub(crate) struct OpenedWindows(HashSet<WindowId>);
|
||||
|
||||
#[cfg(feature = "render")]
|
||||
impl OpenedWindows {
|
||||
pub(crate) fn open(&mut self, id: WindowId) {
|
||||
// Ignore opening already opened windows
|
||||
|
@ -36,3 +48,6 @@ impl OpenedWindows {
|
|||
self.0.contains(id)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default, Resource)]
|
||||
pub struct GenerateWorldTask(pub Option<Task<Result<World, WorldGenError>>>);
|
||||
|
|
Loading…
Reference in a new issue