2022-09-20 15:14:16 +02:00
|
|
|
pub(crate) mod components;
|
2022-10-11 15:19:36 +02:00
|
|
|
#[cfg(feature = "render")]
|
|
|
|
pub(crate) mod gui;
|
2022-09-20 15:14:16 +02:00
|
|
|
pub(crate) mod macros;
|
|
|
|
pub(crate) mod plugins;
|
2022-11-06 17:07:21 +01:00
|
|
|
#[cfg(feature = "render")]
|
2022-09-20 15:14:16 +02:00
|
|
|
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,
|
|
|
|
};
|
2022-10-11 15:19:36 +02:00
|
|
|
use {
|
|
|
|
bevy::{
|
|
|
|
app::App,
|
|
|
|
log::LogSettings,
|
|
|
|
utils::{default, tracing::Level},
|
|
|
|
},
|
|
|
|
planet::WorldManager,
|
|
|
|
plugins::WorldPlugins,
|
2022-09-06 20:40:27 +02:00
|
|
|
};
|
2022-09-06 15:40:09 +02:00
|
|
|
#[cfg(feature = "render")]
|
2022-09-19 12:48:13 +02:00
|
|
|
use {
|
|
|
|
bevy::{
|
|
|
|
asset::Assets,
|
|
|
|
core_pipeline::core_2d::{Camera2d, Camera2dBundle},
|
|
|
|
ecs::{
|
2022-10-11 15:19:36 +02:00
|
|
|
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
|
|
|
},
|
2022-11-07 10:43:18 +01:00
|
|
|
input::{keyboard::KeyCode, Input},
|
2022-09-19 12:48:13 +02:00
|
|
|
prelude::Vec2,
|
|
|
|
render::{
|
|
|
|
camera::{Camera, RenderTarget},
|
|
|
|
render_resource::{
|
|
|
|
Extent3d,
|
|
|
|
TextureDescriptor,
|
|
|
|
TextureDimension,
|
|
|
|
TextureFormat,
|
|
|
|
TextureUsages,
|
|
|
|
},
|
|
|
|
texture::{Image, ImageSettings},
|
|
|
|
},
|
|
|
|
sprite::{Sprite, SpriteBundle},
|
|
|
|
transform::components::GlobalTransform,
|
2022-10-11 15:19:36 +02:00
|
|
|
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,
|
|
|
|
},
|
2022-10-11 15:19:36 +02:00
|
|
|
components::panning::Pan2d,
|
2022-11-07 10:43:18 +01:00
|
|
|
gui::{render_windows, widget, widgets::ToolbarWidget, window::open_window, windows::TileInfo},
|
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
|
|
|
|
2022-09-06 15:40:09 +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]
|
2022-09-06 23:16:47 +02:00
|
|
|
let ndc = (screen_position / window_size) * 2.0 - Vec2::ONE;
|
2022-09-06 15:40:09 +02:00
|
|
|
|
|
|
|
// 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;
|
|
|
|
|
2022-09-06 23:16:47 +02:00
|
|
|
let world = world_manager.world();
|
2022-09-18 17:30:04 +02:00
|
|
|
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;
|
2022-09-06 15:40:09 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-06 11:07:13 +02:00
|
|
|
#[cfg(feature = "render")]
|
|
|
|
fn generate_graphics(
|
2022-09-03 21:40:18 +02:00
|
|
|
mut commands: Commands<'_, '_>,
|
2022-09-19 12:48:13 +02:00
|
|
|
mut world_manager: ResMut<'_, WorldManager>,
|
2022-09-03 21:40:18 +02:00
|
|
|
mut images: ResMut<'_, Assets<Image>>,
|
2022-10-11 15:19:36 +02:00
|
|
|
mut egui_context: ResMut<'_, EguiContext>,
|
2022-09-03 21:40:18 +02:00
|
|
|
) {
|
2022-10-11 15:19:36 +02:00
|
|
|
// 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);
|
|
|
|
}
|
|
|
|
|
2022-09-06 15:40:09 +02:00
|
|
|
let world = world_manager.world();
|
|
|
|
let custom_sprite_size = Vec2 {
|
2022-09-18 17:30:04 +02:00
|
|
|
x: (WORLD_SCALE * world.width as i32) as f32,
|
|
|
|
y: (WORLD_SCALE * world.height as i32) as f32,
|
2022-09-06 15:40:09 +02:00
|
|
|
};
|
2022-10-11 15:19:36 +02:00
|
|
|
// Set up 2D map mode
|
|
|
|
{
|
|
|
|
let map_image_handle = images.add(Image {
|
|
|
|
data: world_manager.map_color_bytes(),
|
|
|
|
texture_descriptor: TextureDescriptor {
|
|
|
|
label: None,
|
|
|
|
size: Extent3d {
|
|
|
|
width: world.width,
|
|
|
|
height: world.height,
|
|
|
|
..default()
|
|
|
|
},
|
|
|
|
dimension: TextureDimension::D2,
|
|
|
|
format: TextureFormat::Rgba32Float,
|
|
|
|
mip_level_count: 1,
|
|
|
|
sample_count: 1,
|
|
|
|
usage: TextureUsages::COPY_DST | TextureUsages::TEXTURE_BINDING,
|
|
|
|
},
|
|
|
|
..default()
|
|
|
|
});
|
2022-11-07 10:43:18 +01:00
|
|
|
world_manager.render_settings.map_image_handle_id = Some(map_image_handle.id);
|
2022-10-11 15:19:36 +02:00
|
|
|
_ = commands
|
|
|
|
.spawn_bundle(Camera2dBundle::default())
|
|
|
|
.insert(Pan2d::new());
|
2022-09-03 21:40:18 +02:00
|
|
|
|
2022-10-11 15:19:36 +02:00
|
|
|
// TODO: Switch to egui
|
|
|
|
_ = commands.spawn_bundle(SpriteBundle {
|
2022-11-07 10:43:18 +01:00
|
|
|
texture: images.get_handle(world_manager.render_settings.map_image_handle_id.unwrap()),
|
2022-10-11 15:19:36 +02:00
|
|
|
sprite: Sprite {
|
|
|
|
custom_size: Some(custom_sprite_size),
|
2022-09-03 21:40:18 +02:00
|
|
|
..default()
|
|
|
|
},
|
2022-10-11 15:19:36 +02:00
|
|
|
..default()
|
|
|
|
});
|
|
|
|
}
|
2022-09-03 21:40:18 +02:00
|
|
|
|
2022-10-11 15:19:36 +02:00
|
|
|
}
|
2022-09-06 22:09:53 +02:00
|
|
|
|
2022-11-07 10:43:18 +01:00
|
|
|
#[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")]
|
2022-10-11 15:19:36 +02:00
|
|
|
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,
|
|
|
|
}
|
|
|
|
));
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2022-10-11 15:19:36 +02:00
|
|
|
_ = 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-10-11 15:19:36 +02:00
|
|
|
});
|
2022-09-03 21:40:18 +02:00
|
|
|
}
|
|
|
|
|
2022-09-06 20:40:27 +02:00
|
|
|
#[cfg(feature = "render")]
|
2022-09-06 23:16:47 +02:00
|
|
|
const WORLD_SCALE: i32 = 4;
|
2022-09-03 21:40:18 +02:00
|
|
|
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
2022-09-05 11:43:50 +02:00
|
|
|
let mut app = App::new();
|
2022-09-03 21:40:18 +02:00
|
|
|
let mut manager = WorldManager::new();
|
2022-09-05 11:43:50 +02:00
|
|
|
#[cfg(feature = "render")]
|
|
|
|
{
|
|
|
|
let world = manager.new_world()?;
|
|
|
|
_ = app
|
2022-09-06 16:49:41 +02:00
|
|
|
.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 {
|
2022-09-18 17:30:04 +02:00
|
|
|
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()
|
|
|
|
})
|
2022-09-06 15:40:09 +02:00
|
|
|
.insert_resource(CursorMapPosition::default())
|
2022-11-06 17:07:21 +01:00
|
|
|
.insert_resource(OpenedWindows::default())
|
2022-09-06 11:07:13 +02:00
|
|
|
.add_startup_system(generate_graphics)
|
2022-10-11 15:19:36 +02:00
|
|
|
.add_system(update_gui.exclusive_system())
|
2022-11-07 10:43:18 +01:00
|
|
|
.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()?
|
|
|
|
}
|
2022-09-06 11:07:13 +02:00
|
|
|
|
2022-09-07 00:08:33 +02:00
|
|
|
_ = app.insert_resource(LogSettings {
|
2022-09-21 14:13:33 +02:00
|
|
|
#[cfg(feature = "logging")]
|
2022-09-07 00:08:33 +02:00
|
|
|
level: Level::DEBUG,
|
2022-09-21 14:13:33 +02:00
|
|
|
#[cfg(not(feature = "logging"))]
|
2022-09-07 00:08:33 +02:00
|
|
|
level: Level::WARN,
|
|
|
|
..default()
|
|
|
|
});
|
2022-09-06 11:07:13 +02:00
|
|
|
|
2022-09-06 15:40:09 +02:00
|
|
|
app.add_plugins(WorldPlugins).insert_resource(manager).run();
|
2022-09-03 21:40:18 +02:00
|
|
|
|
|
|
|
Ok(())
|
2022-08-25 15:45:45 +02:00
|
|
|
}
|