summaryrefslogtreecommitdiffstats
path: root/src/ui
diff options
context:
space:
mode:
Diffstat (limited to 'src/ui')
-rw-r--r--src/ui/bodies_window.rs180
-rw-r--r--src/ui/camera_info.rs3
-rw-r--r--src/ui/fleet_window.rs80
-rw-r--r--src/ui/topbar.rs151
4 files changed, 355 insertions, 59 deletions
diff --git a/src/ui/bodies_window.rs b/src/ui/bodies_window.rs
new file mode 100644
index 0000000..6300f5f
--- /dev/null
+++ b/src/ui/bodies_window.rs
@@ -0,0 +1,180 @@
+use egui::Sense;
+
+use crate::eguictx::EguiCtx;
+use crate::ntree::{NTree, NTreeNode};
+use crate::solar_system::body::{BodyId, OrbitalBody};
+use crate::solar_system::{SolarSystem, SystemId};
+
+
+#[derive(Default, Clone)]
+pub struct BodiesWindowState
+{
+ last_system: Option<SystemId>,
+ system_heirarchy: NTree<SystemId>,
+ selected_body: Option<BodyId>
+}
+
+#[derive(Default, Clone)]
+pub struct BodiesWindowAction
+{
+ pub focus_body: Option<BodyId>
+}
+
+impl BodiesWindowState
+{
+ fn build_system_heirarchy_rec(
+ bodies: &[OrbitalBody],
+ node: &mut NTreeNode<BodyId>)
+ {
+ for body in bodies {
+ let orbit = body.get_orbit();
+ match orbit {
+ Some(orbit) => {
+ if orbit.parent() != *node.value() {
+ continue;
+ }
+ },
+ None => {
+ continue;
+ }
+ }
+ let mut subnode = NTreeNode::new(body.id());
+ BodiesWindowState::build_system_heirarchy_rec(bodies, &mut subnode);
+ node.insert_node(subnode);
+ }
+ }
+
+ fn rebuild_system_heirarchy(
+ &mut self,
+ star_system: &SolarSystem)
+ {
+ let mut root_node = NTreeNode::<BodyId>::new(0);
+
+ let bodies = star_system.bodies();
+ BodiesWindowState::build_system_heirarchy_rec(bodies, &mut root_node);
+ self.system_heirarchy.set_root(root_node);
+ }
+
+ pub fn render(
+ &mut self,
+ current_system: &SolarSystem,
+ eguictx: &EguiCtx)
+ -> BodiesWindowAction
+ {
+ match self.last_system {
+ Some(last_system) => {
+ if last_system != current_system.id() {
+ self.rebuild_system_heirarchy(current_system);
+ }
+ },
+ None => {
+ self.rebuild_system_heirarchy(current_system);
+ }
+ }
+ self.last_system = Some(current_system.id());
+
+ let mut action = BodiesWindowAction::default();
+
+ egui::Window::new("Bodies")
+ .resizable(true)
+ .show(eguictx.context(), |ui| {
+
+ ui.horizontal(|ui| {
+ self.paint_bodies_list(current_system, ui);
+ self.paint_body_info_panel(&mut action, current_system, ui);
+ });
+ });
+ action
+ }
+
+ fn paint_bodies_node_rec(
+ &self,
+ star_system: &SolarSystem,
+ node: &NTreeNode<BodyId>,
+ ui: &mut egui::Ui)
+ -> Option<BodyId>
+ {
+ let body = star_system.body(*node.value());
+ let children = node.children();
+
+ let selected = self.selected_body.is_some_and(|v| { v == *node.value() });
+ let mut new_selected = None;
+
+ if children.is_empty() {
+ if ui.selectable_label(selected, body.name()).clicked() {
+ new_selected = Some(*node.value());
+ }
+ }else{
+ egui::collapsing_header::CollapsingState::load_with_default_open(
+ ui.ctx(),
+ ui.make_persistent_id(format!("bodies_window_body_{}", body.id())),
+ true)
+ .show_header(ui, |ui| {
+ if ui.selectable_label(selected, body.name()).clicked() {
+ new_selected = Some(*node.value());
+ }
+ })
+ .body(|ui| {
+ for child in children {
+ let child_selected = self.paint_bodies_node_rec(star_system, child, ui);
+ if child_selected.is_some() {
+ new_selected = child_selected;
+ }
+ }
+ });
+ };
+ new_selected
+ }
+
+ fn paint_bodies_list(
+ &mut self,
+ star_system: &SolarSystem,
+ ui: &mut egui::Ui)
+ -> Option<egui::Response>
+ {
+ let resp = egui::ScrollArea::vertical()
+ .auto_shrink(true)
+ .min_scrolled_height(200.0)
+ .show(ui, |ui| {
+ ui.vertical(|ui| {
+ let root = self.system_heirarchy.root();
+ let new_sel = self.paint_bodies_node_rec(star_system, root.as_ref().unwrap(), ui);
+ if new_sel.is_some() {
+ self.selected_body = new_sel;
+ }
+ }).response
+ });
+ Some(resp.inner)
+ }
+
+ fn paint_body_info_panel(
+ &mut self,
+ action: &mut BodiesWindowAction,
+ star_system: &SolarSystem,
+ ui: &mut egui::Ui)
+ {
+ let selected_body = match self.selected_body {
+ Some(id) => { star_system.body(id) },
+ None => { return; }
+ };
+
+ ui.separator();
+ egui::Frame::canvas(ui.style())
+ .show(ui, |ui| {
+ ui.set_width(200.0);
+ ui.vertical_centered(|ui| {
+ ui.label(
+ egui::RichText::new(selected_body.name())
+ .heading());
+ });
+
+ ui.horizontal(|ui| {
+ let focus_resp = ui.button("Focus");
+
+ if focus_resp.clicked() {
+ action.focus_body = Some(selected_body.id());
+ }
+ });
+ });
+ }
+}
diff --git a/src/ui/camera_info.rs b/src/ui/camera_info.rs
index 8114f63..5332370 100644
--- a/src/ui/camera_info.rs
+++ b/src/ui/camera_info.rs
@@ -16,7 +16,7 @@ impl CameraWindowState
{
pub fn render(
ui_state: &mut ui::State,
- game_state: &RefCell<GameState>,
+ game_state: &GameState,
eguictx: &EguiCtx)
{
let topbar_state = &ui_state.topbar_sate;
@@ -25,7 +25,6 @@ impl CameraWindowState
}
let camera_state = &mut ui_state.camera_info;
- let game_state = game_state.borrow();
let current_system = &game_state.solar_systems()[topbar_state.current_system.unwrap()];
diff --git a/src/ui/fleet_window.rs b/src/ui/fleet_window.rs
new file mode 100644
index 0000000..67a0dd9
--- /dev/null
+++ b/src/ui/fleet_window.rs
@@ -0,0 +1,80 @@
+use std::cell::RefCell;
+
+use crate::{GameState, eguictx::EguiCtx, solar_system::{self, SolarSystem, fleet::Fleet}, ui};
+
+
+#[derive(Default, Clone)]
+pub struct FleetWindowState
+{
+
+}
+
+#[derive(Default, Clone)]
+pub struct FleetWindowAction
+{
+
+}
+
+impl FleetWindowState
+{
+ pub fn render(
+ &mut self,
+ game_state: &GameState,
+ eguictx: &EguiCtx)
+ -> FleetWindowAction
+ {
+ let mut action = FleetWindowAction::default();
+
+ let star_systems = game_state.solar_systems();
+
+ egui::Window::new("Fleet Manager")
+ .show(eguictx.context(), |ui| {
+
+ ui.horizontal(|ui| {
+ self.paint_systems_list(star_systems, ui);
+ ui.add(egui::Separator::default().vertical());
+ });
+ });
+ action
+ }
+
+ fn paint_systems_list(
+ &mut self,
+ star_systems: &[SolarSystem],
+ ui: &mut egui::Ui)
+ -> 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| {
+
+ });
+ }
+ }
+ })
+ }
+
+ fn paint_fleet_list(
+ &mut self,
+ 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);
+ }
+ })
+ }
+
+ fn paint_fleet_entry(
+ &mut self,
+ fleet: &Fleet,
+ ui: &mut egui::Ui)
+ {
+ ui.label(fleet.name());
+ }
+}
diff --git a/src/ui/topbar.rs b/src/ui/topbar.rs
index 296a84e..a5d92c5 100644
--- a/src/ui/topbar.rs
+++ b/src/ui/topbar.rs
@@ -7,84 +7,64 @@ pub struct TopBarState
{
pub current_system: Option<SystemId>,
pub auto_tick: Option<Second>,
- pub do_auto_tick: bool
+ 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>,
}
impl TopBarState
{
pub fn render(
- state: &mut TopBarState,
- game_state: &RefCell<GameState>,
+ &mut self,
+ game_state: &GameState,
eguictx: &EguiCtx)
+ -> TopBarAction
{
- let mut game_state = game_state.borrow_mut();
+ let mut action: TopBarAction = TopBarAction::default();
+
+ let solar_systems = game_state.solar_systems();
+ let timeman = game_state.timeman();
egui::TopBottomPanel::top("topbar").show(
eguictx.context(),
|ui| {
ui.horizontal(|ui| {
- let solar_systems = game_state.solar_systems();
- let selected_system_label = match state.current_system {
- Some(id) => solar_systems[id].name(),
- None => ""
- };
-
- egui::ComboBox::from_label("Current System")
- .selected_text(selected_system_label)
- .show_ui(ui, |ui| {
-
- for (i, system) in solar_systems.iter().enumerate() {
- ui.selectable_value(
- &mut state.current_system,
- Some(i),
- system.name()
- );
- }
- });
-
- ui.separator();
-
- let button_seconds = [
- 1,
- 5,
- 30,
- timeman::MINUTE,
- timeman::MINUTE * 5,
- timeman::MINUTE * 30,
- timeman::HOUR,
- timeman::DAY,
- timeman::DAY * 5,
- timeman::YEAR
- ];
- let selected_button = state.auto_tick;
-
- let timeman = game_state.timeman_mut();
ui.vertical(|ui| {
- ui.label("Manual");
- ui.checkbox(&mut state.do_auto_tick, "Auto");
- });
-
- button_seconds.iter().for_each(|&seconds| {
- ui.vertical(|ui| {
- let auto_selected = match selected_button {
- Some(o) => o == seconds,
- None => false
- };
- let label = TimeMan::format_duration(seconds);
+ let selected_system_label = match self.current_system {
+ Some(id) => solar_systems[id].name(),
+ None => ""
+ };
- if ui.button(label.clone()).clicked() {
- timeman.advance(seconds);
+ egui::ComboBox::from_label("Current System")
+ .selected_text(selected_system_label)
+ .show_ui(ui, |ui| {
+
+ for (i, system) in solar_systems.iter().enumerate() {
+ ui.selectable_value(
+ &mut self.current_system,
+ Some(i),
+ system.name()
+ );
}
+ });
- if ui.add(egui::Button::new(label.clone()).selected(auto_selected)).clicked() {
- state.auto_tick = Some(seconds);
- }
+ ui.horizontal(|ui| {
+ self.paint_empire_buttons(ui);
});
});
+
+ self.paint_tick_buttons(&mut action, timeman, ui);
+
});
ui.vertical_centered_justified(|ui| {
- let timeman = game_state.timeman_mut();
let time_str = TimeMan::format_duration(timeman.seconds());
ui.label(
egui::RichText::new(time_str)
@@ -92,5 +72,62 @@ impl TopBarState
);
});
});
+ action
+ }
+
+ pub fn paint_empire_buttons(
+ &mut self,
+ ui: &mut egui::Ui)
+ {
+ 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("Fleets").selected(self.fleet_window_visible)).clicked() {
+ self.fleet_window_visible = !self.fleet_window_visible;
+ }
+ }
+
+ pub fn paint_tick_buttons(
+ &mut self,
+ action: &mut TopBarAction,
+ timeman: &TimeMan,
+ ui: &mut egui::Ui)
+ {
+ let button_seconds = [
+ 1,
+ 5,
+ 30,
+ timeman::MINUTE,
+ timeman::MINUTE * 5,
+ timeman::MINUTE * 30,
+ timeman::HOUR,
+ timeman::DAY,
+ timeman::DAY * 5,
+ timeman::YEAR
+ ];
+ let selected_button = self.auto_tick;
+
+ ui.vertical(|ui| {
+ ui.label("Manual");
+ ui.checkbox(&mut self.do_auto_tick, "Auto");
+ });
+
+ button_seconds.iter().for_each(|&seconds| {
+ ui.vertical(|ui| {
+ let auto_selected = match selected_button {
+ Some(o) => o == seconds,
+ None => false
+ };
+ let label = TimeMan::format_duration(seconds);
+
+ if ui.button(label.clone()).clicked() {
+ action.advance_tick = Some(seconds);
+ }
+
+ if ui.add(egui::Button::new(label.clone()).selected(auto_selected)).clicked() {
+ self.auto_tick = Some(seconds);
+ }
+ });
+ });
}
}