use glc::vector::{Angle, Vector2f, Vector4f}; use space_crush_common::{ components::{Fleet, Orbit, Player, Position}, constants::SHIP_ORBIT_DISTANCE_MAX, continue_if_none, misc::LogResult, return_if_none, }; use specs::{prelude::*, ReadExpect, ReadStorage, System, World, WriteExpect}; use crate::{ misc::{HorizontalAlign, Text, TextManager, VerticalAlign}, resources::{Camera, Geometry, PlayerState}, Error, }; pub struct Fleets { text: Text, } #[derive(SystemData)] pub struct FleetData<'a> { player_state: ReadExpect<'a, PlayerState>, geometry: WriteExpect<'a, Geometry>, camera: ReadExpect<'a, Camera>, positions: ReadStorage<'a, Position>, players: ReadStorage<'a, Player>, orbits: ReadStorage<'a, Orbit>, fleets: ReadStorage<'a, Fleet>, } impl Fleets { pub fn new(manager: &TextManager) -> Result { let cache = manager.create_cache()?; let text = cache .new_text() .scale(20.0) .font("resources/fonts/DroidSansMono.ttf") .color(0.7, 0.7, 0.7, 1.0) .vert_align(VerticalAlign::Center) .horz_align(HorizontalAlign::Center) .text("") .build()?; Ok(Self { text }) } } impl<'a> System<'a> for Fleets { type SystemData = FleetData<'a>; fn run(&mut self, data: Self::SystemData) { let FleetData { player_state, mut geometry, camera, positions, players, orbits, fleets, } = data; let player = return_if_none!(players.get(player_state.player_id)); gl::enable(gl::BLEND); for (position, orbit) in (&positions, &orbits).join() { let fleet_id = continue_if_none!(orbit.fleets.get(player.index)); let fleet_id = continue_if_none!(fleet_id); let fleet = continue_if_none!(fleets.get(*fleet_id)); gl::blend_func(gl::SRC_ALPHA, gl::ONE); gl::blend_equation(gl::FUNC_ADD); geometry.render_lines( Vector4f::new(0.5, 0.5, 0.5, 0.05), &create_circle(position.pos, orbit.min), ); geometry.render_lines( Vector4f::new(0.5, 0.5, 0.5, 0.05), &create_circle(position.pos, orbit.max), ); geometry.render_lines( Vector4f::new(0.5, 0.5, 0.5, 0.05), &create_circle(position.pos, SHIP_ORBIT_DISTANCE_MAX * orbit.max), ); gl::blend_func(gl::SRC_ALPHA, gl::ONE_MINUS_SRC_ALPHA); gl::blend_equation(gl::FUNC_SUBTRACT); self.text .update( 0, format!( "F:{}\nB:{}\nT:{}", fleet.count.fighter, fleet.count.bomber, fleet.count.transporter ), ) .panic("Unable to update text") .render_offset(&camera.world_to_window(position.pos)); } gl::blend_equation(gl::FUNC_ADD); gl::disable(gl::BLEND); } } fn create_circle(p: Vector2f, r: f32) -> Vec { let mut points = Vec::new(); for i in 0..=180 { points.push(Vector2f::new( p.x + r * Angle::Deg(i as f32 * 2.0).cos(), p.y + r * Angle::Deg(i as f32 * 2.0).sin(), )); } points }