use std::str::FromStr; use crate::GameState; use crate::fleet::FleetsManager; use crate::solar_system::body::{BodyId, OrbitalBody}; use crate::solar_system::{Kilometers, SolarSystem, SystemId}; use crate::ui::contact::MapContact; pub struct FleetsListWidget<'f> { fleets_man: &'f FleetsManager, selected: &'f mut Option, } pub struct FleetsListResponse { pub response: egui::Response, pub refocus: Option<(SystemId, MapContact)> } pub struct FleetsControlPanel { new_fleet_modal: Option } pub struct FleetsControlResponse { pub new_fleet: Option } #[derive(Clone)] pub struct NewFleetModal { pub name: String, pub sma: Kilometers, } impl<'f> FleetsListWidget<'f> { pub fn new( fleets_man: &'f FleetsManager, selected: &'f mut Option) -> Self { Self { fleets_man, selected } } pub fn show_ui( mut self, ui: &mut egui::Ui) -> FleetsListResponse { let frame_resp = egui::Frame::new() .fill(egui::Color32::from_gray(48)) .outer_margin(egui::Margin::same(4)) .inner_margin(egui::Margin::same(4)) .show(ui, |frame| { frame.set_max_height(frame.available_height() / 2.0); self.show_fleets_list(frame) }); FleetsListResponse { response: frame_resp.response, refocus: frame_resp.inner } } fn show_fleets_list( &mut self, ui: &mut egui::Ui) -> Option<(SystemId, MapContact)> { egui::ScrollArea::vertical() .auto_shrink(false) .show(ui, |scrollarea| { let mut refocus: Option<(SystemId, MapContact)> = None; for id in self.fleets_man.all() { let fleet = match self.fleets_man.fleet(id) { Some(v) => v, None => { continue; } }; let contact = MapContact::from_fleet(id); let selected = self.selected.is_some_and(|v| { v == contact }); let resp = scrollarea.selectable_label(selected, fleet.name()); if resp.double_clicked() { refocus = Some((fleet.system(), contact)); }else if resp.clicked() { *self.selected = if selected { None } else { Some(contact) }; } } refocus }).inner } } // impl FleetsListWidget impl FleetsControlPanel { pub fn show( &mut self, selected_contact: &Option, fleets_man: &FleetsManager, star_system: &SolarSystem, ui: &mut egui::Ui) -> FleetsControlResponse { let mut response = FleetsControlResponse { new_fleet: None }; egui::Frame::new() .inner_margin(egui::Margin::same(4)) .outer_margin(egui::Margin::same(4)) .fill(egui::Color32::from_gray(48)) .show(ui, |frame| { frame.horizontal(|horizontal| { horizontal.take_available_width(); if horizontal.button("New Fleet").clicked() { self.new_fleet_modal = Some(NewFleetModal::default()); } }); }); if let Some(new_fleet_modal) = &mut self.new_fleet_modal { let modal = new_fleet_modal.show( selected_contact, fleets_man, star_system, ui.ctx()); if modal.inner { response.new_fleet = self.new_fleet_modal.take(); } if modal.should_close() { self.new_fleet_modal = None; } } response } } impl Default for FleetsControlPanel { fn default() -> Self { Self { new_fleet_modal: None } } } impl NewFleetModal { pub fn show( &mut self, selected_contact: &Option, fleets_man: &FleetsManager, star_system: &SolarSystem, ctx: &egui::Context) -> egui::ModalResponse { let sma_min = match selected_contact.unwrap_or(MapContact::from_body(0)).body() { Some(id) => star_system.body(id).radius(), None => 0.0 }; egui::Modal::new(egui::Id::new("NewFleetModal")).show(ctx, |ui| { ui.set_width(256.0); ui.heading("Create new debug fleet"); ui.horizontal(|ui| { ui.label("Name: "); ui.text_edit_singleline(&mut self.name); }); ui.horizontal(|ui| { ui.label("Orbiting: "); ui.label(selected_contact.unwrap_or(MapContact::from_body(0)).name(star_system, fleets_man)); ui.label(" above "); ui.add( egui::DragValue::new(&mut self.sma).range(sma_min..=f32::MAX).suffix("km") ); }); if ui.button("Create").clicked() { ui.close(); return true; } false }) } } impl Default for NewFleetModal { fn default() -> Self { Self { name: String::from_str("New Fleet").unwrap(), sma: 0.0 } } } impl GameState { pub fn new_fleet_from_modal( &mut self, modal: NewFleetModal, star_system: SystemId, contact: Option) { let contact = contact.unwrap_or(MapContact::from_body(0)); let star_system = &self.solar_systems[star_system]; let body = match contact.body() { Some(id) => id, None => 0 }; self.fleets.new_fleet_from_modal(modal, star_system, body); } } impl FleetsManager { pub fn new_fleet_from_modal( &mut self, modal: NewFleetModal, star_system: &SolarSystem, body: BodyId) { let id = self.new_fleet(modal.name, star_system.id()); let fleet = self.fleet_mut(id).unwrap(); fleet.make_orbit(star_system, body, modal.sma); } }