use crate::GameState; use crate::fleet::{Fleet, FleetId, FleetsManager}; use crate::solar_system::orbit::StaticOrbiter; use crate::solar_system::{Kilometers, SolarSystem, SystemId}; use crate::solar_system::body::BodyId; #[derive(Default, Clone, PartialEq)] enum FleetMenuPanelSel { #[default] Info, Schedule } #[derive(Default, Clone)] pub struct FleetWindowState { pub open: bool, pub selected_fleet: Option, pub menu_panel: FleetMenuPanelSel, 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(Clone)] pub struct NewFleet { pub system: SystemId, pub orbiting: BodyId, pub name: String, pub sma: Kilometers } impl FleetWindowState { pub fn paint( &mut self, ui: &mut egui::Ui, game_state: &GameState, focused_system: &Option, 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(ui.ctx(), |ui| { ui.vertical(|ui| { ui.horizontal(|ui| { self.paint_fleet_list(fleets_manager, ui); self.paint_fleet_menu(star_systems, fleets_manager, ui); }); if focused_system.is_some() { if ui.button("New Fleet").clicked() { if self.new_fleet_window.is_none() { self.new_fleet_window = Some(NewFleetWindowState::new( focused_system.unwrap(), focused_body.unwrap_or(0) )); } } } }); }); match &mut self.new_fleet_window { Some(new_fleet_window) => { action.new_fleet = new_fleet_window.paint(ui, game_state); if action.new_fleet.is_some() || !new_fleet_window.open { self.new_fleet_window = None; } } None => {} } self.open = mgr_open; action } fn paint_fleet_menu( &mut self, star_systems: &[SolarSystem], fleets_man: &FleetsManager, ui: &mut egui::Ui) { let fleet = match self.selected_fleet { Some(id) => { fleets_man.entry(id) }, None => { return; } }; let fleet = match fleet { Some(entry) => entry, None => { self.selected_fleet = None; return; } }; ui.separator(); ui.vertical(|ui| { ui.horizontal(|ui| { if ui.button("Info").clicked() { self.menu_panel = FleetMenuPanelSel::Info; } if ui.button("Schedule").clicked() { self.menu_panel = FleetMenuPanelSel::Schedule; } }); self.paint_fleet_menu_info(star_systems, fleets_man, fleet, ui); }); } fn paint_fleet_menu_info( &mut self, star_systems: &[SolarSystem], fleets_man: &FleetsManager, fleet: &Fleet, ui: &mut egui::Ui) { if self.menu_panel != FleetMenuPanelSel::Info { return; } egui::Frame::canvas(ui.style()).show(ui, |ui| { ui.set_min_width(200.0); ui.style_mut().interaction.selectable_labels = false; if let Some(orbit) = fleet.orbit() { let star_system = &star_systems[orbit.system()]; let parent = star_system.body(orbit.parent()); ui.push_id("orbital_info_table", |ui| { egui_extras::TableBuilder::new(ui) .column(egui_extras::Column::auto()) .column(egui_extras::Column::remainder()) .body(|mut body| { body.row(16.0, |mut row| { row.col(|col| { col.label("System"); }); row.col(|col| { col.label(star_system.name()); }); }); body.row(16.0, |mut row| { row.col(|col| { col.label("Orbiting"); }); row.col(|col| { col.label(parent.name()); }); }); body.row(16.0, |mut row| { row.col(|col| { col.label("Radius"); }); row.col(|col| { col.label(format!("{:.1}", orbit.sma())); }); }); }); }); ui.separator(); } let heading = fleet.heading(); egui_extras::TableBuilder::new(ui) .column(egui_extras::Column::auto()) .column(egui_extras::Column::remainder()) .body(|mut body| { body.row(16.0, |mut row| { row.col(|col| { col.label("Heading"); }); row.col(|col| { col.label(format!("{:?} by {:?}", cgmath::Deg::::from(heading.x), cgmath::Deg::::from(heading.y) )); }); }); }); }); } fn paint_fleet_list( &mut self, fleets_man: &FleetsManager, ui: &mut egui::Ui) { let fleet_ids = fleets_man.all(); ui.vertical(|ui| { for id in fleet_ids { if let Some(fleet) = fleets_man.entry(id) { self.paint_fleet_entry(fleet, ui); } } }); } fn paint_fleet_entry( &mut self, fleet: &Fleet, ui: &mut egui::Ui) { let selected = self.selected_fleet.is_some_and(|id| { id == fleet.id() }); if ui.selectable_label(selected, fleet.name()).clicked() { self.selected_fleet = if selected { None } else { Some(fleet.id()) }; } } } // 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, ui: &mut egui::Ui, game_state: &GameState,) -> 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(ui.ctx(), |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 } } } // impl FleetWindowState impl Default for NewFleet { fn default() -> Self { Self { system: Default::default(), orbiting: Default::default(), name: "New Fleet".to_string(), sma: Default::default() } } }