From 14ca7b5fc15eb2618b46bde0cac85e37ebc9ebd9 Mon Sep 17 00:00:00 2001 From: Jon Santmyer Date: Thu, 21 May 2026 07:58:47 -0400 Subject: tacmap back as canvas. begin work on fleet scheduling --- src/ui/bodies_window.rs | 7 +-- src/ui/fleet_schedule.rs | 150 +++++++++++++++++++++++++++++++++++++++++++++++ src/ui/fleet_window.rs | 114 +++++++++++++++++++++-------------- src/ui/topbar.rs | 3 +- 4 files changed, 223 insertions(+), 51 deletions(-) create mode 100644 src/ui/fleet_schedule.rs (limited to 'src/ui') diff --git a/src/ui/bodies_window.rs b/src/ui/bodies_window.rs index 7e24948..a93f11c 100644 --- a/src/ui/bodies_window.rs +++ b/src/ui/bodies_window.rs @@ -1,6 +1,6 @@ -use crate::ntree::{NTree, NTreeNode}; -use crate::solar_system::body::{BodyId, OrbitalBody}; -use crate::solar_system::{SolarSystem, SystemId}; +use crate::ntree::NTreeNode; +use crate::solar_system::body::BodyId; +use crate::solar_system::SolarSystem; use crate::timeman::TimeMan; @@ -88,7 +88,6 @@ impl BodiesWindowState -> Option { let resp = egui::ScrollArea::vertical() - .auto_shrink(true) .min_scrolled_height(200.0) .show(ui, |ui| { ui.vertical(|ui| { diff --git a/src/ui/fleet_schedule.rs b/src/ui/fleet_schedule.rs new file mode 100644 index 0000000..b0e5dd7 --- /dev/null +++ b/src/ui/fleet_schedule.rs @@ -0,0 +1,150 @@ +use crate::solar_system::SolarSystem; +use crate::solar_system::body::BodyId; +use crate::fleet::{Fleet, FleetId, FleetsManager}; + +#[derive(Clone)] +pub struct FleetScheduleWindow +{ + pub target: (Option, Option), + pub linear_acceleration_limit: f32, + pub angular_acceleration_limit: f32, +} + +impl Default for FleetScheduleWindow +{ + fn default() -> Self { + Self { + target: Default::default(), + linear_acceleration_limit: 9.81, + angular_acceleration_limit: 15.0 + } + } +} + +impl FleetScheduleWindow +{ + pub fn paint( + &mut self, + star_systems: &[SolarSystem], + fleets_man: &FleetsManager, + fleet: &Fleet, + ui: &mut egui::Ui) + { + ui.horizontal(|limits_ui| { + limits_ui.vertical(|linear_limit_ui| { + linear_limit_ui.label("Linear acceleration limit"); + linear_limit_ui.add( + egui::DragValue::new(&mut self.linear_acceleration_limit) + .range(0.0..=(9.8*2.0)) + .clamp_existing_to_range(true) + .suffix(" m/s^2") + .speed(0.1) + .max_decimals_opt(Some(2)) + ); + }); + limits_ui.separator(); + limits_ui.vertical(|angular_limit_ui| { + angular_limit_ui.label("Angular acceleration limit"); + angular_limit_ui.add( + egui::DragValue::new(&mut self.angular_acceleration_limit) + .range(0.0..=30.0) + .clamp_existing_to_range(true) + .suffix(" °/s^2") + .speed(0.1) + .max_decimals_opt(Some(2)) + ); + }); + }); + ui.separator(); + + let fleet_system = &star_systems[fleet.system().unwrap_or(0)]; + let bodies = fleet_system.bodies(); + let bodies_order = fleet_system.heirarchy().traverse_preorder(); + let system_fleets = fleet_system.fleets(fleets_man); + + let row_height = ui.spacing().interact_size.y; + ui.horizontal(|panel_ui| + { + panel_ui.vertical(|vertical_ui| { + vertical_ui.set_max_width(128.0); + vertical_ui.vertical_centered(|centered_ui| { + centered_ui.label("Target"); + }); + egui::ScrollArea::vertical() + .id_salt("fleet_schedule_objs") + .auto_shrink(false) + .min_scrolled_height(256.0) + .show_rows(vertical_ui, row_height, bodies.len() + system_fleets.len(), + |objs_ui, rows| { + let fleet_rows_start = 0; + let bodies_rows_start = system_fleets.len(); + + for row in rows { + match row < bodies_rows_start { + true => { + let id = system_fleets[row - fleet_rows_start]; + let selected = self.target.1 + .is_some_and(|v| { v == id }); + let fleet = fleets_man.fleet(id); + if let Some(fleet) = fleet { + if objs_ui.selectable_label(selected, fleet.name()).clicked() { + self.select_fleet_from_schedule_objs(id, selected); + } + } + }, + false => { + let id = *bodies_order[row - bodies_rows_start]; + let selected = self.target.0 + .is_some_and(|v| { v == id }); + let body = &bodies[id]; + if objs_ui.selectable_label(selected, body.name()).clicked() { + self.select_body_from_schedule_objs(id, selected); + } + } + } + } + }); + }); + + panel_ui.vertical(|vertical_ui| { + vertical_ui.set_max_width(128.0); + vertical_ui.vertical_centered(|centered_ui| { + centered_ui.label("Commands"); + }); + egui::ScrollArea::vertical() + .id_salt("fleet_schedule_commands") + .auto_shrink(false) + .min_scrolled_height(256.0) + .show_rows(vertical_ui, row_height, 0, + |cmd_ui, rows| { + + }); + }); + + panel_ui.vertical(|vertical_ui| { + vertical_ui.set_max_width(128.0); + vertical_ui.vertical_centered(|centered_ui| { + centered_ui.label("Schedule"); + }); + }); + }); + } + + fn select_body_from_schedule_objs( + &mut self, + id: BodyId, + selected: bool) + { + self.target = + (if selected { None } else { Some(id) }, None); + } + + fn select_fleet_from_schedule_objs( + &mut self, + id: FleetId, + selected: bool) + { + self.target = + (None, if selected { None } else { Some(id) }); + } +} diff --git a/src/ui/fleet_window.rs b/src/ui/fleet_window.rs index 55e3d59..4db4ce8 100644 --- a/src/ui/fleet_window.rs +++ b/src/ui/fleet_window.rs @@ -3,6 +3,7 @@ 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; +use crate::ui::fleet_schedule::FleetScheduleWindow; #[derive(Default, Clone, PartialEq)] enum FleetMenuPanelSel { @@ -16,7 +17,9 @@ pub struct FleetWindowState { pub open: bool, pub selected_fleet: Option, - pub menu_panel: FleetMenuPanelSel, + + menu_panel: FleetMenuPanelSel, + fleet_schedule_window: FleetScheduleWindow, pub new_fleet_window: Option } @@ -107,7 +110,7 @@ impl FleetWindowState ui: &mut egui::Ui) { let fleet = match self.selected_fleet { - Some(id) => { fleets_man.entry(id) }, + Some(id) => { fleets_man.fleet(id) }, None => { return; } }; let fleet = match fleet { @@ -128,64 +131,74 @@ impl FleetWindowState self.menu_panel = FleetMenuPanelSel::Schedule; } }); - self.paint_fleet_menu_info(star_systems, fleets_man, fleet, ui); + + egui::Frame::new() + .stroke(egui::Stroke::new(1.0, egui::Color32::LIGHT_GRAY)) + .show(ui, |ui| { + ui.set_min_width(200.0); + ui.set_min_height(200.0); + ui.style_mut().interaction.selectable_labels = false; + + match self.menu_panel { + FleetMenuPanelSel::Info => + self.paint_fleet_menu_info(star_systems, fleets_man, fleet, ui), + FleetMenuPanelSel::Schedule => + self.fleet_schedule_window.paint(star_systems, fleets_man, fleet, ui) + }; + }); }); } fn paint_fleet_menu_info( &mut self, star_systems: &[SolarSystem], - fleets_man: &FleetsManager, + _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()); + 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.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(); - } + 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) - )); - }); + 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) + )); }); }); }); @@ -199,7 +212,7 @@ impl FleetWindowState let fleet_ids = fleets_man.all(); ui.vertical(|ui| { for id in fleet_ids { - if let Some(fleet) = fleets_man.entry(id) { + if let Some(fleet) = fleets_man.fleet(id) { self.paint_fleet_entry(fleet, ui); } } @@ -213,9 +226,18 @@ impl FleetWindowState { 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()) }; + self.select_fleet_from_entries_list(fleet, selected); } } + + fn select_fleet_from_entries_list( + &mut self, + fleet: &Fleet, + selected: bool) + { + self.selected_fleet = if selected { None } else { Some(fleet.id()) }; + self.fleet_schedule_window.target = (None, None); + } } // FleetWindowAction impl NewFleetWindowState @@ -287,4 +309,6 @@ impl Default for NewFleet sma: Default::default() } } -} +} // impl NewFleet + + diff --git a/src/ui/topbar.rs b/src/ui/topbar.rs index 511c67e..f560310 100644 --- a/src/ui/topbar.rs +++ b/src/ui/topbar.rs @@ -1,6 +1,5 @@ -use std::cell::RefCell; -use crate::{GameState, eguictx::EguiCtx, solar_system::SystemId, timeman::{self, Second, TimeMan}, ui::{self, bodies_window::BodiesWindowState, fleet_window::FleetWindowState}}; +use crate::{GameState, solar_system::SystemId, timeman::{self, Second, TimeMan}, ui::{bodies_window::BodiesWindowState, fleet_window::FleetWindowState}}; #[derive(Default, Clone)] pub struct TopBarState -- cgit v1.2.3