add map foundation

This commit is contained in:
geoffsee
2025-07-03 15:00:06 -04:00
parent cad210c991
commit 496d4b550a
6 changed files with 767 additions and 6 deletions

View File

@@ -63,6 +63,13 @@ systems = { path = "../systems" }
components = { path = "../components" }
wasm-bindgen = "0.2"
web-sys = { version = "0.3", features = ["Document", "Element", "HtmlElement", "Window"] }
reqwest = { version = "0.12", features = ["json"] }
# Platform-specific tokio features
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
tokio = { version = "1.0", features = ["rt", "rt-multi-thread"] }
[target.'cfg(target_arch = "wasm32")'.dependencies]
tokio = { version = "1.0", features = ["rt"] }
# keep the following in sync with Bevy's dependencies
winit = { version = "0.30", default-features = false }

View File

@@ -8,6 +8,7 @@ use bevy::prelude::*;
use std::collections::HashMap;
use systems::{VesselSystem, SystemInteraction, SystemStatus};
use components::{VesselData, SystemIndicator, SystemDisplayArea};
use crate::ui::{spawn_gps_map_window, GpsMapState};
/// Resource for managing all yacht systems
#[derive(Resource)]
@@ -120,7 +121,9 @@ fn update_all_systems(
/// System to handle interactions with system indicator buttons
fn handle_system_indicator_interactions(
mut commands: Commands,
mut system_manager: ResMut<SystemManager>,
mut gps_map_state: ResMut<GpsMapState>,
mut interaction_query: Query<
(&Interaction, &mut BackgroundColor, &SystemIndicator),
(Changed<Interaction>, With<Button>),
@@ -134,6 +137,12 @@ fn handle_system_indicator_interactions(
&indicator.system_id,
SystemInteraction::Select
);
// If GPS system is selected, spawn the map window
if indicator.system_id == "gps" {
spawn_gps_map_window(&mut commands, &mut gps_map_state);
}
*background_color = BackgroundColor(Color::linear_rgb(0.0, 0.3, 0.5));
}
Interaction::Hovered => {

View File

@@ -10,7 +10,7 @@ use bevy::diagnostic::{FrameTimeDiagnosticsPlugin, LogDiagnosticsPlugin};
use bevy::prelude::*;
use crate::core::{ActionsPlugin, SystemManagerPlugin};
use crate::core::system_manager::SystemManager;
use crate::ui::{LoadingPlugin, MenuPlugin};
use crate::ui::{LoadingPlugin, MenuPlugin, GpsMapPlugin};
use systems::{PlayerPlugin, setup_instrument_cluster, get_vessel_systems};
// See https://bevy-cheatbook.github.io/programming/states.html
@@ -40,6 +40,7 @@ impl Plugin for GamePlugin {
app.init_state::<GameState>().add_plugins((
LoadingPlugin,
MenuPlugin,
GpsMapPlugin,
ActionsPlugin,
SystemManagerPlugin,
PlayerPlugin,

View File

@@ -0,0 +1,167 @@
use bevy::prelude::*;
use bevy::window::Window;
use std::collections::HashMap;
/// Component to mark the GPS map window
#[derive(Component)]
pub struct GpsMapWindow;
/// Component to mark map tiles
#[derive(Component)]
pub struct MapTile {
pub x: i32,
pub y: i32,
pub zoom: u8,
}
/// Resource to manage the GPS map state
#[derive(Resource, Default)]
pub struct GpsMapState {
pub window_id: Option<Entity>,
pub center_lat: f64,
pub center_lon: f64,
pub zoom_level: u8,
pub tile_cache: HashMap<String, Handle<Image>>,
}
impl GpsMapState {
pub fn new() -> Self {
Self {
window_id: None,
center_lat: 43.6377, // Default to Monaco coordinates from GPS system
center_lon: -1.4497,
zoom_level: 10,
tile_cache: HashMap::new(),
}
}
}
/// Plugin for GPS map functionality
pub struct GpsMapPlugin;
impl Plugin for GpsMapPlugin {
fn build(&self, app: &mut App) {
app.init_resource::<GpsMapState>()
.add_systems(Update, (
handle_gps_map_window_events,
update_map_tiles,
));
}
}
/// System to handle GPS map window events
fn handle_gps_map_window_events(
mut commands: Commands,
mut gps_map_state: ResMut<GpsMapState>,
windows: Query<Entity, With<Window>>,
) {
// For now, we'll keep this simple and just track the window
// In a full implementation, we would handle window close events properly
if let Some(map_window_id) = gps_map_state.window_id {
// Check if the window still exists
if windows.get(map_window_id).is_err() {
gps_map_state.window_id = None;
info!("GPS map window was closed");
}
}
}
/// System to update map tiles
fn update_map_tiles(
mut commands: Commands,
gps_map_state: Res<GpsMapState>,
asset_server: Res<AssetServer>,
map_tiles: Query<Entity, With<MapTile>>,
) {
if gps_map_state.window_id.is_none() {
return;
}
// For now, we'll create a simple placeholder map
// In a full implementation, this would fetch actual OSM tiles
if map_tiles.is_empty() {
spawn_placeholder_map(&mut commands, &asset_server);
}
}
/// Spawn a placeholder map with basic tiles
fn spawn_placeholder_map(commands: &mut Commands, _asset_server: &Res<AssetServer>) {
// Create a simple grid of colored rectangles to represent map tiles
for x in -2..=2 {
for y in -2..=2 {
let color = if (x + y) % 2 == 0 {
Color::linear_rgb(0.3, 0.7, 0.3) // Green for land
} else {
Color::linear_rgb(0.2, 0.4, 0.8) // Blue for water
};
commands.spawn((
Sprite {
color,
custom_size: Some(Vec2::new(256.0, 256.0)),
..default()
},
Transform::from_translation(Vec3::new(
x as f32 * 256.0,
y as f32 * 256.0,
0.0,
)),
MapTile {
x,
y,
zoom: 10,
},
GpsMapWindow,
));
}
}
// Add a marker for the vessel position
commands.spawn((
Sprite {
color: Color::linear_rgb(1.0, 0.0, 0.0),
custom_size: Some(Vec2::new(20.0, 20.0)),
..default()
},
Transform::from_translation(Vec3::new(0.0, 0.0, 1.0)),
GpsMapWindow,
));
}
/// Function to spawn the GPS map window
pub fn spawn_gps_map_window(
commands: &mut Commands,
gps_map_state: &mut ResMut<GpsMapState>,
) {
if gps_map_state.window_id.is_some() {
info!("GPS map window already open");
return;
}
info!("Spawning GPS map window");
// Create a new window for the GPS map
let window_entity = commands.spawn((
Window {
title: "GPS Navigation - OpenStreetMap".to_string(),
resolution: (800.0, 600.0).into(),
position: bevy::window::WindowPosition::Centered(bevy::window::MonitorSelection::Current),
..default()
},
GpsMapWindow,
)).id();
// Create a camera for the map window
commands.spawn((
Camera2d,
Camera {
target: bevy::render::camera::RenderTarget::Window(bevy::window::WindowRef::Entity(window_entity)),
..default()
},
GpsMapWindow,
));
gps_map_state.window_id = Some(window_entity);
info!("GPS map window spawned with entity: {:?}", window_entity);
}

View File

@@ -1,5 +1,7 @@
pub mod loading;
pub mod menu;
pub mod gps_map;
pub use loading::LoadingPlugin;
pub use menu::MenuPlugin;
pub use gps_map::{GpsMapPlugin, spawn_gps_map_window, GpsMapState};