diff options
Diffstat (limited to 'src/ui/fleets_widget.rs')
| -rw-r--r-- | src/ui/fleets_widget.rs | 246 |
1 files changed, 246 insertions, 0 deletions
diff --git a/src/ui/fleets_widget.rs b/src/ui/fleets_widget.rs new file mode 100644 index 0000000..b31a04b --- /dev/null +++ b/src/ui/fleets_widget.rs @@ -0,0 +1,246 @@ +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<MapContact>, +} + +pub struct FleetsListResponse +{ + pub response: egui::Response, + pub refocus: Option<(SystemId, MapContact)> +} + +pub struct FleetsControlPanel +{ + new_fleet_modal: Option<NewFleetModal> +} + +pub struct FleetsControlResponse +{ + pub new_fleet: Option<NewFleetModal> +} + +#[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<MapContact>) + -> 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<MapContact>, + 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<MapContact>, + fleets_man: &FleetsManager, + star_system: &SolarSystem, + ctx: &egui::Context) + -> egui::ModalResponse<bool> + { + 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<MapContact>) + { + 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); + } +} |
