use std::cell::RefCell; use crate::GameState; use crate::eguictx::EguiCtx; use crate::fleet::{Fleet, FleetsManager}; use crate::solar_system::{Kilometers, SolarSystem, SystemId}; use crate::solar_system::body::BodyId; #[derive(Default, Clone)] pub struct FleetWindowState { pub open: bool, pub selected_system: Option, pub new_fleet_window: Option } #[derive(Default, Clone)] pub struct FleetWindowAction { pub new_fleet: Option } #[derive(Default, Clone)] pub struct NewFleetWindowState { pub open: bool, pub parent_system: SystemId, pub parent_body: BodyId, pub fleet_name: String, pub fleet_sma: Kilometers } #[derive(Default, Clone)] pub struct NewFleet { pub system: SystemId, pub orbiting: BodyId, pub name: String, pub sma: Kilometers } impl FleetWindowState { pub fn paint( &mut self, game_state: &GameState, eguictx: &EguiCtx, focused_body: &Option) -> FleetWindowAction { let mut action = FleetWindowAction::default(); let star_systems = game_state.solar_systems(); let fleets_manager = game_state.fleets(); let mut mgr_open = self.open; egui::Window::new("Fleet Manager") .open(&mut mgr_open) .show(eguictx.context(), |ui| { ui.horizontal(|ui| { self.paint_systems_list( &mut action, ui, fleets_manager, star_systems, focused_body ); }); }); match &mut self.new_fleet_window { Some(new_fleet_window) => { action.new_fleet = new_fleet_window.paint(game_state, eguictx); if action.new_fleet.is_some() || !new_fleet_window.open { self.new_fleet_window = None; } } None => {} } self.open = mgr_open; action } fn paint_systems_list( &mut self, action: &mut FleetWindowAction, ui: &mut egui::Ui, fleets_manager: &FleetsManager, star_systems: &[SolarSystem], focused_body: &Option) -> egui::InnerResponse<()> { ui.vertical(|ui| { for system in star_systems { self.paint_fleet_list(fleets_manager, &system, ui); } if self.selected_system.is_none() { return; } if ui.button("New Fleet").clicked() { if self.new_fleet_window.is_none() { self.new_fleet_window = Some(NewFleetWindowState::new( self.selected_system.unwrap(), focused_body.unwrap_or(0) )); } } }) } fn paint_fleet_list( &mut self, fleets_manager: &FleetsManager, star_system: &SolarSystem, ui: &mut egui::Ui) { let fleet_ids = star_system.fleets(fleets_manager); egui::collapsing_header::CollapsingState::load_with_default_open( ui.ctx(), ui.make_persistent_id(format!("fleet_window_star_{}", star_system.id())), true ) .show_header(ui, |ui| { let selected = self.selected_system.is_some_and(|id| { id == star_system.id() }); if ui.selectable_label(selected, star_system.name()).clicked() { self.selected_system = if !selected { Some(star_system.id()) } else { None }; } }) .body(|ui| { for id in fleet_ids { if let Some(fleet) = fleets_manager.entry(id) { self.paint_fleet_entry(fleet, ui); } } }); } fn paint_fleet_entry( &mut self, fleet: &Fleet, ui: &mut egui::Ui) { ui.label(fleet.name()); } } // FleetWindowAction impl NewFleetWindowState { pub fn new( parent_system: SystemId, parent_body: BodyId) -> Self { Self { open: true, parent_system: parent_system, parent_body: parent_body, ..Default::default() } } pub fn paint( &mut self, game_state: &GameState, eguictx: &EguiCtx) -> Option { let solar_system = &game_state.solar_systems()[self.parent_system]; let orbiting = solar_system.body(self.parent_body); match egui::Window::new("New Fleet") .collapsible(false) .open(&mut self.open) .show(eguictx.context(), |ui| { ui.vertical(|ui| { ui.horizontal(|ui| { ui.label("Name: "); ui.add(egui::TextEdit::singleline(&mut self.fleet_name)); }); ui.label(format!("Orbiting: {}", orbiting.name())); ui.horizontal(|ui| { ui.label("SMA: "); ui.add(egui::DragValue::new(&mut self.fleet_sma) .range(orbiting.radius()..=f32::INFINITY) .clamp_existing_to_range(true) .suffix("km")); }); if ui.button("Create").clicked() { return Some(NewFleet { system: self.parent_system, orbiting: self.parent_body, name: self.fleet_name.clone(), sma: self.fleet_sma, }); } None }).inner }) { Some(resp) => { resp.inner? }, None => None } } }