use bevy::prelude::*;
use bevy::window::PrimaryWindow;
use crate::client::Me;
use crate::config::planet::Planet;
use crate::ecs::{MainCamera, StarfieldBack, StarfieldFront, StarfieldMid};
pub fn indicators_plugin(app: &mut App) {
app.add_systems(PreUpdate, (add_indicators, update_indicators))
.add_systems(PostUpdate, update_indicators_position);
}
#[derive(Component)]
struct PlanetIndicator(String);
#[derive(Component)]
struct HasIndicator(Entity);
fn add_indicators(planets_wo_indicators: Query<(Entity, &Planet), Without<HasIndicator>>, player: Query<Entity, With<Me>>, asset_server: Res<AssetServer>, mut commands: Commands) {
let Ok(me) = player.single() else { return; };
for (planet, planet_data) in &planets_wo_indicators {
let Some(indicator_url) = &planet_data.indicator_sprite else { continue };
let mut sprite = Sprite::from_image(asset_server.load(indicator_url));
sprite.custom_size = Some(Vec2::new(25.0, 25.0));
let indicator = commands.spawn((
ChildOf(me),
PlanetIndicator(planet_data.name.clone()),
sprite,
Transform::from_xyz(0.0, 0.0, 0.0)
)).id();
commands.entity(planet).insert(HasIndicator(indicator));
}
}
fn update_indicators(changed_planets_w_indicators: Query<(&Planet, &HasIndicator), Changed<Planet>>, asset_server: Res<AssetServer>, mut commands: Commands) {
for (planet_data, indicator) in changed_planets_w_indicators.iter() {
let Some(indicator_sprite) = &planet_data.indicator_sprite else { continue; };
let mut sprite = Sprite::from_image(asset_server.load(indicator_sprite));
sprite.custom_size = Some(Vec2::new(50.0, 50.0));
commands.entity(indicator.0)
.remove::<Sprite>()
.insert(sprite);
}
}
fn update_indicators_position(
planets_w_indicator: Query<(&Transform, &HasIndicator), Without<PlanetIndicator>>,
player: Query<&Transform, (With<Me>, Without<PlanetIndicator>)>,
mut indicators: Query<(&mut Transform, &mut Sprite), (With<PlanetIndicator>, Without<HasIndicator>, Without<Me>, Without<MainCamera>)>,
window: Query<&Window, With<PrimaryWindow>>,
camera: Single<&Transform, (With<MainCamera>, Without<PlanetIndicator>)>,
)
{
let Ok(player_position) = player.single() else { return; };
let Ok(window) = window.single() else { return };
for (planet_position, indicator_id) in &planets_w_indicator {
let mut offset = planet_position.translation - player_position.translation;
let sprite_size = 25.0 * camera.scale.z;
let half_window_height = window.height() * camera.scale.z / 2.0 - (sprite_size / 2.0);
let half_window_width = window.width() * camera.scale.z / 2.0 - (sprite_size / 2.0);
offset.x = offset.x.clamp(-half_window_width, half_window_width);
offset.y = offset.y.clamp(-half_window_height, half_window_height);
let Ok((mut this_indicator, mut this_sprite)) = indicators.get_mut(indicator_id.0) else { continue; };
this_sprite.custom_size = Some(Vec2::splat(sprite_size));
let inv_rot = player_position.rotation.inverse();
this_indicator.translation = inv_rot.mul_vec3(Vec3::new(offset.x, offset.y, 0.0));
this_indicator.rotation = inv_rot;
}
}