~starkingdoms/starkingdoms

ref: 461d3d233fe9f2f94f9a1f1b9ccf9d1cdc9a9edb starkingdoms/crates/unified/src/client/planet/indicators.rs -rw-r--r-- 3.2 KiB
461d3d23TerraMaster85 fix starfield alignment(?) 5 months ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
use bevy::prelude::*;
use bevy::window::PrimaryWindow;
use crate::client::Me;
use crate::config::planet::Planet;
use crate::ecs::MainCamera;

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;
    }
}