worlds-history-sim-rs/src/main.rs

250 lines
7.9 KiB
Rust
Raw Normal View History

2022-11-08 21:46:32 +01:00
#![cfg_attr(not(feature = "logging"), windows_subsystem = "windows")]
pub(crate) mod components;
#[cfg(feature = "render")]
pub(crate) mod gui;
pub(crate) mod macros;
pub(crate) mod plugins;
2022-11-06 17:07:21 +01:00
#[cfg(feature = "render")]
pub(crate) mod resources;
2022-09-05 11:43:50 +02:00
2022-10-23 22:09:38 +02:00
#[cfg(all(feature = "render", feature = "logging"))]
use {
bevy::diagnostic::{Diagnostics, FrameTimeDiagnosticsPlugin},
bevy_egui::egui::Frame,
};
use {
bevy::{
app::App,
log::LogSettings,
utils::{default, tracing::Level},
},
planet::WorldManager,
plugins::WorldPlugins,
2022-09-06 20:40:27 +02:00
};
#[cfg(feature = "render")]
2022-09-19 12:48:13 +02:00
use {
bevy::{
asset::Assets,
core_pipeline::core_2d::{Camera2d, Camera2dBundle},
ecs::{
change_detection::{Mut, ResMut},
query::With,
2022-10-23 22:09:38 +02:00
system::{Commands, IntoExclusiveSystem, Query, Res},
world::World,
2022-09-19 12:48:13 +02:00
},
input::{keyboard::KeyCode, Input},
2022-09-19 12:48:13 +02:00
prelude::Vec2,
render::{
camera::{Camera, RenderTarget},
2022-11-08 21:46:32 +01:00
render_resource::{TextureDescriptor, TextureDimension, TextureFormat, TextureUsages},
2022-09-19 12:48:13 +02:00
texture::{Image, ImageSettings},
},
sprite::{Sprite, SpriteBundle},
transform::components::GlobalTransform,
window::{WindowDescriptor, Windows},
2022-09-19 12:48:13 +02:00
winit::WinitSettings,
},
2022-10-23 22:09:38 +02:00
bevy_egui::{
egui::{FontData, FontDefinitions, FontFamily},
EguiContext,
},
components::panning::Pan2d,
2022-11-08 21:46:32 +01:00
gui::{
render_windows,
update_textures,
widget,
widgets::ToolbarWidget,
window::open_window,
windows::TileInfo,
},
planet::WorldRenderSettings,
2022-11-06 17:07:21 +01:00
resources::{CursorMapPosition, OpenedWindows},
2022-09-19 10:54:10 +02:00
};
2022-08-25 15:45:45 +02:00
#[cfg(feature = "render")]
fn update_cursor_map_position(
mut cursor_map_position: ResMut<'_, CursorMapPosition>,
transform: Query<'_, '_, (&Camera, &GlobalTransform), With<Camera2d>>,
windows: Res<'_, Windows>,
world_manager: Res<'_, WorldManager>,
) {
let (camera, transform) = transform.single();
let window = match camera.target {
RenderTarget::Window(window_id) => windows.get(window_id).unwrap(),
RenderTarget::Image(_) => windows.primary(),
};
if let Some(screen_position) = window.cursor_position() {
let window_size = Vec2::new(window.width(), window.height());
// GPU coordinates [-1..1]
let ndc = (screen_position / window_size) * 2.0 - Vec2::ONE;
// Matrix to reverse camera transform
let ndc_to_world = transform.compute_matrix() * camera.projection_matrix().inverse();
let world_position =
ndc_to_world.project_point3(ndc.extend(-1.0)).truncate() / WORLD_SCALE as f32;
let world = world_manager.world();
cursor_map_position.x = world.width as i32 / 2 + f32::ceil(world_position.x) as i32 - 1;
cursor_map_position.y = world.height as i32 / 2 + f32::ceil(world_position.y) as i32 - 1;
}
}
#[cfg(feature = "render")]
fn generate_graphics(
mut commands: Commands<'_, '_>,
2022-11-08 21:46:32 +01:00
world_manager: ResMut<'_, WorldManager>,
mut images: ResMut<'_, Assets<Image>>,
mut egui_context: ResMut<'_, EguiContext>,
2022-11-08 21:46:32 +01:00
mut render_settings: ResMut<'_, WorldRenderSettings>,
) {
// Add Julia-Mono font to egui
{
let ctx = egui_context.ctx_mut();
let mut fonts = FontDefinitions::default();
const FONT_NAME: &str = "Julia-Mono";
_ = fonts.font_data.insert(
FONT_NAME.to_owned(),
FontData::from_static(include_bytes!("../assets/JuliaMono.ttf")),
);
fonts
.families
.get_mut(&FontFamily::Monospace)
.expect("Failed to get 'Monospace' FontFamily")
.insert(0, FONT_NAME.to_owned());
fonts
.families
.get_mut(&FontFamily::Proportional)
.expect("Failed to get 'Proportional' FontFamily")
.push(FONT_NAME.to_owned());
ctx.set_fonts(fonts);
}
let world = world_manager.world();
let custom_sprite_size = Vec2 {
x: (WORLD_SCALE * world.width as i32) as f32,
y: (WORLD_SCALE * world.height as i32) as f32,
};
// Set up 2D map mode
{
let map_image_handle = images.add(Image {
2022-11-08 21:46:32 +01:00
data: vec![],
texture_descriptor: TextureDescriptor {
label: None,
2022-11-08 21:46:32 +01:00
size: default(),
dimension: TextureDimension::D2,
format: TextureFormat::Rgba32Float,
mip_level_count: 1,
sample_count: 1,
usage: TextureUsages::COPY_DST | TextureUsages::TEXTURE_BINDING,
},
..default()
});
2022-11-08 21:46:32 +01:00
render_settings.map_image_handle_id = Some(map_image_handle.id);
_ = commands
.spawn_bundle(Camera2dBundle::default())
.insert(Pan2d::new());
// TODO: Switch to egui
_ = commands.spawn_bundle(SpriteBundle {
2022-11-08 21:46:32 +01:00
texture: images.get_handle(map_image_handle.id),
sprite: Sprite {
custom_size: Some(custom_sprite_size),
..default()
},
..default()
});
}
2022-11-08 21:46:32 +01:00
update_textures(&world_manager, &render_settings, &mut images);
}
#[cfg(feature = "render")]
fn open_tile_info(mut windows: ResMut<OpenedWindows>, keys: Res<Input<KeyCode>>) {
if keys.just_released(KeyCode::I) {
open_window::<TileInfo>(&mut windows);
}
}
2022-10-23 22:09:38 +02:00
#[cfg(feature = "render")]
fn update_gui(world: &mut World) {
world.resource_scope(|world, mut ctx: Mut<'_, EguiContext>| {
let ctx = ctx.ctx_mut();
2022-10-23 22:09:38 +02:00
#[cfg(feature = "logging")]
{
bevy_egui::egui::CentralPanel::default()
.frame(Frame::none())
.show(ctx, |ui| {
_ = ui.label(format!(
"{:.0}",
match world
.resource::<Diagnostics>()
.get_measurement(FrameTimeDiagnosticsPlugin::FPS)
{
None => f64::NAN,
Some(fps) => fps.value,
}
));
});
}
_ = bevy_egui::egui::TopBottomPanel::bottom("Toolbar")
.resizable(false)
.default_height(30.0)
.show(ctx, |ui| {
widget::<ToolbarWidget<'_, '_>>(world, ui, "Toolbar".into());
});
2022-11-06 17:07:21 +01:00
render_windows(world, ctx);
});
}
2022-09-06 20:40:27 +02:00
#[cfg(feature = "render")]
const WORLD_SCALE: i32 = 4;
fn main() -> Result<(), Box<dyn std::error::Error>> {
2022-09-05 11:43:50 +02:00
let mut app = App::new();
let mut manager = WorldManager::new();
2022-09-05 11:43:50 +02:00
#[cfg(feature = "render")]
{
let world = manager.new_world()?;
_ = app
.insert_resource(WinitSettings::game())
2022-09-05 11:43:50 +02:00
// Use nearest-neighbor rendering for cripsier pixels
.insert_resource(ImageSettings::default_nearest())
.insert_resource(WindowDescriptor {
width: (WORLD_SCALE * world.width as i32) as f32,
height: (WORLD_SCALE * world.height as i32) as f32,
2022-09-05 11:43:50 +02:00
title: String::from("World-RS"),
resizable: true,
..default()
})
.insert_resource(CursorMapPosition::default())
2022-11-06 17:07:21 +01:00
.insert_resource(OpenedWindows::default())
2022-11-08 21:46:32 +01:00
.insert_resource(WorldRenderSettings::default())
.add_startup_system(generate_graphics)
.add_system(update_gui.exclusive_system())
.add_system(update_cursor_map_position)
.add_system(open_tile_info);
2022-09-05 11:43:50 +02:00
}
#[cfg(not(feature = "render"))]
{
_ = manager.new_world()?
}
_ = 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();
Ok(())
2022-08-25 15:45:45 +02:00
}