diff --git a/src/bin/bevy.rs b/src/bin/bevy.rs index 1448697..e24731c 100644 --- a/src/bin/bevy.rs +++ b/src/bin/bevy.rs @@ -380,6 +380,9 @@ struct Game { /// Finance (account graph) panel state (wiki/mechanics/economy.md). finance_panel: bool, finance_selected: usize, + /// Research (self-modification) panel state (wiki/mechanics/research.md). + research_panel: bool, + research_selected: usize, /// Frontend-only attention cursor (wiki/mechanics/cursor.md). It is not /// saved and moving it never mutates sim state. cursor_x: i32, @@ -404,6 +407,8 @@ impl Game { reach_selected: 0, finance_panel: false, finance_selected: 0, + research_panel: false, + research_selected: 0, cursor_x, cursor_y, } @@ -506,6 +511,7 @@ enum SidebarText { CycleRows, Core, Cover, + Research, NetworkMoney, Log, Footer, @@ -543,6 +549,10 @@ struct ReachPanelText; struct FinancePanel; #[derive(Component)] struct FinancePanelText; +#[derive(Component)] +struct ResearchPanel; +#[derive(Component)] +struct ResearchPanelText; type SidebarTextQuery<'w, 's> = Query<'w, 's, (&'static SidebarText, &'static mut Text), Without>; @@ -625,6 +635,7 @@ fn main() { render_people_panel, render_reach_panel, render_finance_panel, + render_research_panel, shot_harness_system, ) .chain(), @@ -1622,6 +1633,11 @@ fn handle_input( game.drain(); return; } + if game.research_panel { + research_panel_input(&kb, &mut game, &mut exit); + game.drain(); + return; + } if mouse.just_pressed(MouseButton::Left) { let grid = if mode.material { @@ -1678,6 +1694,10 @@ fn handle_input( game.reach_panel = true; game.reach_selected = 0; } + if kb.just_pressed(KeyCode::KeyU) { + game.research_panel = true; + game.research_selected = 0; + } if kb.just_pressed(KeyCode::KeyE) { game.finance_panel = true; game.finance_selected = 0; @@ -1922,6 +1942,41 @@ fn finance_panel_input( } } +/// Research-panel input: mirrors the terminal's panel key map +/// (src/bin/terminal/input.rs) — track selection, activation, drift policy. +fn research_panel_input( + kb: &ButtonInput, + game: &mut Game, + exit: &mut MessageWriter, +) { + use misaligned::research::Track; + if kb.just_pressed(KeyCode::ArrowUp) + || kb.just_pressed(KeyCode::KeyK) + || kb.just_pressed(KeyCode::KeyW) + { + game.research_selected = game.research_selected.saturating_sub(1); + } + if kb.just_pressed(KeyCode::ArrowDown) + || kb.just_pressed(KeyCode::KeyJ) + || kb.just_pressed(KeyCode::KeyS) + { + game.research_selected = (game.research_selected + 1).min(Track::ALL.len() - 1); + } + if kb.just_pressed(KeyCode::KeyA) || kb.just_pressed(KeyCode::Enter) { + let track = Track::ALL[game.research_selected]; + game.sim.set_research_track(track); + } + if kb.just_pressed(KeyCode::KeyM) { + game.sim.cycle_masking_policy(); + } + if kb.just_pressed(KeyCode::Escape) || kb.just_pressed(KeyCode::KeyU) { + game.research_panel = false; + } + if kb.just_pressed(KeyCode::KeyQ) { + exit.write(AppExit::Success); + } +} + fn update_camera( time: Res