diff --git a/assets/models/orbitring.glb b/assets/models/orbitring.glb new file mode 100644 index 0000000..4b24746 Binary files /dev/null and b/assets/models/orbitring.glb differ diff --git a/src/camera.rs b/src/camera.rs index f46973d..d650bef 100644 --- a/src/camera.rs +++ b/src/camera.rs @@ -16,6 +16,7 @@ impl Plugin for CameraPlugin { fn build(&self, app: &mut App) { app.add_systems(Startup, setup_camera); app.add_systems(Update, handle_input); + app.add_systems(Update, update_map_only_object_visibility); app.add_systems(Update, manage_player_actor.after(handle_input)); app.add_systems(PostUpdate, sync_camera_to_player .after(PhysicsSet::Sync) @@ -30,6 +31,12 @@ impl Plugin for CameraPlugin { } } +#[derive(Component)] +pub struct ShowOnlyInMap { + pub min_distance: f64, + pub distance_to_id: String, +} + #[derive(Resource)] pub struct MapCam { pub initialized: bool, @@ -490,6 +497,40 @@ pub fn apply_input_to_player( } } +pub fn update_map_only_object_visibility( + settings: Res, + q_camera: Query<&Transform, With>, + q_player: Query<&Position, With>, + mut q_onlyinmap: Query<(&mut Visibility, &ShowOnlyInMap), Without>, + id2pos: Res, +) { + if q_camera.is_empty() || q_player.is_empty() { + return; + } + let cam: &Transform = q_camera.get_single().unwrap(); + let player_pos: &Position = q_player.get_single().unwrap(); + let cam_pos: Vec3 = cam.translation + player_pos.as_vec3(); + for (mut vis, onlyinmap) in &mut q_onlyinmap { + if let Some(pos) = id2pos.0.get(&onlyinmap.distance_to_id) { + if settings.map_active { + let dist = cam_pos.distance(pos.as_vec3()); + if dist >= onlyinmap.min_distance as f32 { + *vis = Visibility::Inherited; + } + else { + *vis = Visibility::Hidden; + } + } + else { + *vis = Visibility::Hidden; + } + } else { + error!("Failed get position of actor ID '{}'", &onlyinmap.distance_to_id); + *vis = Visibility::Hidden; + } + } +} + // Find the closest world object that the player is looking at #[inline] pub fn find_closest_target( diff --git a/src/commands.rs b/src/commands.rs index 63f8c91..9494572 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -3,7 +3,7 @@ extern crate regex; use bevy::prelude::*; use bevy_xpbd_3d::prelude::*; use bevy::math::DVec3; -use crate::{actor, chat, hud, nature, shading, world}; +use crate::{actor, camera, chat, hud, nature, shading, world}; use regex::Regex; use std::f32::consts::PI; use std::f64::consts::PI as PI64; @@ -74,6 +74,7 @@ struct ParserState { light_brightness: f32, light_color: Option, ar_model: Option, + show_only_in_map_at_distance: Option<(f64, String)>, } impl Default for ParserState { fn default() -> Self { @@ -122,6 +123,7 @@ impl Default for ParserState { light_brightness: 0.0, light_color: None, ar_model: None, + show_only_in_map_at_distance: None, } } } @@ -441,6 +443,15 @@ pub fn load_defs( ["targeted", "yes"] => { state.is_targeted_on_startup = true; } + ["only_in_map_at_dist", value, id] => { + if let Ok(value_float) = value.parse::() { + state.show_only_in_map_at_distance = Some((value_float, id.to_string())); + } + else { + error!("Can't parse float: {line}"); + continue; + } + } _ => { error!("No match for [{}]", parts.join(",")); } @@ -568,6 +579,12 @@ fn spawn_entities( if state.is_targeted_on_startup { actor.insert(hud::IsTargeted); } + if let Some((mindist, id)) = &state.show_only_in_map_at_distance { + actor.insert(camera::ShowOnlyInMap { + min_distance: *mindist, + distance_to_id: id.clone() + }); + } if state.is_player || state.is_vehicle { // used to apply mouse movement to actor rotation actor.insert(ExternalTorque::ZERO.with_persistence(false)); diff --git a/src/defs.txt b/src/defs.txt index abb5a5b..db1f2b3 100644 --- a/src/defs.txt +++ b/src/defs.txt @@ -5,6 +5,16 @@ actor 0 0 0 sphere yes sun yes physics off + actor 0 0 0 orbitring + scale 778479000e3 + only_in_map_at_dist 1e10 jupiter + clickable no + physics off + actor 0 0 0 orbitring + scale 778479000e3 + only_in_map_at_dist 1e10 jupiter + clickable no + physics off actor 0 0 0 jupiter relativeto sol @@ -18,6 +28,54 @@ actor 0 0 0 jupiter rotationx -0.50 rotationz -0.28 angularmomentum 30 30 30 + actor 0 0 0 orbitring + relativeto jupiter + scale 128000e3 + only_in_map_at_dist 1e7 metis + clickable no + physics off + actor 0 0 0 orbitring + relativeto jupiter + scale 129000e3 + only_in_map_at_dist 1e7 adrastea + clickable no + physics off + actor 0 0 0 orbitring + relativeto jupiter + scale 181365.84e3 + only_in_map_at_dist 1e7 amalthea + clickable no + physics off + actor 0 0 0 orbitring + relativeto jupiter + scale 221900e3 + only_in_map_at_dist 1e7 thebe + clickable no + physics off + actor 0 0 0 orbitring + relativeto jupiter + scale 421700e3 + only_in_map_at_dist 1e8 io + clickable no + physics off + actor 0 0 0 orbitring + relativeto jupiter + scale 670900e3 + only_in_map_at_dist 1e8 europa + clickable no + physics off + actor 0 0 0 orbitring + relativeto jupiter + scale 1070400e3 + only_in_map_at_dist 1e8 ganymede + clickable no + physics off + actor 0 0 0 orbitring + relativeto jupiter + scale 1882700e3 + only_in_map_at_dist 1e8 callisto + clickable no + physics off actor 0 593051 0 suit relativeto jupiter diff --git a/src/world.rs b/src/world.rs index ad1e21d..f786980 100644 --- a/src/world.rs +++ b/src/world.rs @@ -39,6 +39,7 @@ pub fn asset_name_to_path(name: &str) -> &'static str { "pizzeria" => "models/pizzeria2.glb#Scene0", "pizzasign" => "models/pizzasign.glb#Scene0", "selectagon" => "models/selectagon.glb#Scene0", + "orbitring" => "models/orbitring.glb#Scene0", "clippy" => "models/clippy.glb#Scene0", "clippy_ar" => "models/clippy_ar.glb#Scene0", "whale" => "models/whale.glb#Scene0",