summaryrefslogtreecommitdiffstats
path: root/src/ui
diff options
context:
space:
mode:
authorJon Santmyer <jon@jonsantmyer.com>2026-05-10 13:29:56 -0400
committerJon Santmyer <jon@jonsantmyer.com>2026-05-10 13:29:56 -0400
commit7f63ec5c10eb7e8dd4edaabd1a6a437328911d39 (patch)
tree36bd3d75ebc0c25256413c21a7cb28c9296953f5 /src/ui
parentc9041e2e6fe59d6127bb1085b874e8e3cda8000e (diff)
downloadsystemic4x-7f63ec5c10eb7e8dd4edaabd1a6a437328911d39.tar.gz
systemic4x-7f63ec5c10eb7e8dd4edaabd1a6a437328911d39.tar.bz2
systemic4x-7f63ec5c10eb7e8dd4edaabd1a6a437328911d39.zip
fleets
Diffstat (limited to 'src/ui')
-rw-r--r--src/ui/bodies_window.rs4
-rw-r--r--src/ui/fleet_window.rs160
-rw-r--r--src/ui/topbar.rs29
3 files changed, 165 insertions, 28 deletions
diff --git a/src/ui/bodies_window.rs b/src/ui/bodies_window.rs
index ece605b..21a2060 100644
--- a/src/ui/bodies_window.rs
+++ b/src/ui/bodies_window.rs
@@ -10,6 +10,7 @@ use crate::timeman::TimeMan;
#[derive(Default, Clone)]
pub struct BodiesWindowState
{
+ pub open: bool,
last_system: Option<SystemId>,
system_heirarchy: NTree<SystemId>,
selected_body: Option<BodyId>
@@ -76,7 +77,9 @@ impl BodiesWindowState
let mut action = BodiesWindowAction::default();
+ let mut bodies_window_open = self.open;
egui::Window::new("Bodies")
+ .open(&mut &mut bodies_window_open)
.resizable(true)
.show(eguictx.context(), |ui| {
@@ -85,6 +88,7 @@ impl BodiesWindowState
self.paint_body_info_panel(&mut action, current_system, ui);
});
});
+ self.open = bodies_window_open;
action
}
diff --git a/src/ui/fleet_window.rs b/src/ui/fleet_window.rs
index 67a0dd9..eb8ccde 100644
--- a/src/ui/fleet_window.rs
+++ b/src/ui/fleet_window.rs
@@ -1,56 +1,112 @@
use std::cell::RefCell;
-use crate::{GameState, eguictx::EguiCtx, solar_system::{self, SolarSystem, fleet::Fleet}, ui};
+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<SystemId>,
+ pub new_fleet_window: Option<NewFleetWindowState>
}
#[derive(Default, Clone)]
pub struct FleetWindowAction
{
-
+ pub new_fleet: Option<NewFleet>
+}
+
+#[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 render(
+ pub fn paint(
&mut self,
game_state: &GameState,
- eguictx: &EguiCtx)
+ eguictx: &EguiCtx,
+ focused_body: &Option<BodyId>)
-> 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(star_systems, ui);
- ui.add(egui::Separator::default().vertical());
+ 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],
- ui: &mut egui::Ui)
+ focused_body: &Option<BodyId>)
-> egui::InnerResponse<()>
{
ui.vertical(|ui| {
for system in star_systems {
- let resp = self.paint_fleet_list(&system, ui);
- if resp.header_response.secondary_clicked() {
- resp.header_response.context_menu(|ui| {
+ 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)
+ ));
}
}
})
@@ -58,16 +114,29 @@ impl FleetWindowState
fn paint_fleet_list(
&mut self,
+ fleets_manager: &FleetsManager,
star_system: &SolarSystem,
ui: &mut egui::Ui)
- -> egui::CollapsingResponse<()>
{
- let fleets = star_system.fleets();
- ui.collapsing(star_system.name(), |ui| {
- for fleet in fleets {
- self.paint_fleet_entry(fleet, 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(
@@ -77,4 +146,63 @@ impl FleetWindowState
{
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<NewFleet>
+ {
+ 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
+ }
+ }
}
diff --git a/src/ui/topbar.rs b/src/ui/topbar.rs
index a5d92c5..ba26d7c 100644
--- a/src/ui/topbar.rs
+++ b/src/ui/topbar.rs
@@ -1,6 +1,6 @@
use std::cell::RefCell;
-use crate::{GameState, eguictx::EguiCtx, solar_system::SystemId, timeman::{self, Second, TimeMan}};
+use crate::{GameState, eguictx::EguiCtx, solar_system::SystemId, timeman::{self, Second, TimeMan}, ui::{self, bodies_window::BodiesWindowState, fleet_window::FleetWindowState}};
#[derive(Default, Clone)]
pub struct TopBarState
@@ -8,23 +8,24 @@ pub struct TopBarState
pub current_system: Option<SystemId>,
pub auto_tick: Option<Second>,
pub do_auto_tick: bool,
-
- pub bodies_window_visible: bool,
- pub fleet_window_visible: bool,
}
#[derive(Default, Clone)]
pub struct TopBarAction
{
pub advance_tick: Option<Second>,
+ pub toggle_bodies_window: bool,
+ pub toggle_fleets_window: bool,
}
impl TopBarState
{
- pub fn render(
+ pub fn paint(
&mut self,
+ eguictx: &EguiCtx,
game_state: &GameState,
- eguictx: &EguiCtx)
+ bodies_window_state: &BodiesWindowState,
+ fleets_window_state: &FleetWindowState)
-> TopBarAction
{
let mut action: TopBarAction = TopBarAction::default();
@@ -57,7 +58,7 @@ impl TopBarState
});
ui.horizontal(|ui| {
- self.paint_empire_buttons(ui);
+ self.paint_empire_buttons(ui, &mut action, bodies_window_state, fleets_window_state);
});
});
@@ -77,13 +78,17 @@ impl TopBarState
pub fn paint_empire_buttons(
&mut self,
- ui: &mut egui::Ui)
+ ui: &mut egui::Ui,
+ action: &mut TopBarAction,
+ bodies_window_state: &BodiesWindowState,
+ fleets_window_state: &FleetWindowState
+ )
{
- if ui.add(egui::Button::new("Bodies").selected(self.bodies_window_visible)).clicked() {
- self.bodies_window_visible = !self.bodies_window_visible;
+ if ui.add(egui::Button::new("Bodies").selected(bodies_window_state.open)).clicked() {
+ action.toggle_bodies_window = true;
}
- if ui.add(egui::Button::new("Fleets").selected(self.fleet_window_visible)).clicked() {
- self.fleet_window_visible = !self.fleet_window_visible;
+ if ui.add(egui::Button::new("Fleets").selected(fleets_window_state.open)).clicked() {
+ action.toggle_fleets_window = true;
}
}