This commit is contained in:
2026-06-15 10:42:21 -05:00
parent 32aef1ea08
commit 439fc44106
6 changed files with 445 additions and 74 deletions
+38 -1
View File
@@ -1,6 +1,7 @@
use ratatui::crossterm::event::{Event, KeyCode, MouseEventKind};
use kiln_core::Direction;
use kiln_core::game::{GameState, ScrollLine};
use crate::menu::{MenuItem, MenuKey, pause_menu_items, ActionRc as MenuActionRc};
use crate::ui::Ui;
/// Moves the player and, if the move crosses a portal, captures both board Rcs
@@ -22,6 +23,8 @@ pub enum InputMode {
Board,
/// A scroll overlay is active; all input is captured for scroll navigation.
Scroll,
/// A menu overlay is active; all input is captured for menu navigation.
Menu,
/// An animation is running; all input is discarded.
Animating,
/// Reserved for a post-transition freeze; nothing currently produces this mode.
@@ -35,6 +38,7 @@ pub(crate) fn current_input_mode(game: &GameState, ui: &Ui) -> InputMode {
if ui.active_animation.is_some() || ui.pending_transition.is_some() {
return InputMode::Animating;
}
if ui.menu.is_some() { return InputMode::Menu; }
if game.active_scroll.is_some() { InputMode::Scroll } else { InputMode::Board }
}
@@ -42,7 +46,7 @@ pub(crate) fn current_input_mode(game: &GameState, ui: &Ui) -> InputMode {
pub(crate) fn handle_board_input(event: Event, log_open: bool, terminal_h: u16, game: &mut GameState, ui: &mut Ui) -> bool {
match event {
Event::Key(key) => match key.code {
KeyCode::Char('q') | KeyCode::Esc => return true,
KeyCode::Esc => ui.open_menu(pause_menu_items()),
KeyCode::Up => try_move_with_transition(game, ui, Direction::North),
KeyCode::Down => try_move_with_transition(game, ui, Direction::South),
KeyCode::Left => try_move_with_transition(game, ui, Direction::West),
@@ -107,3 +111,36 @@ pub(crate) fn handle_scroll_input(event: Event, game: &mut GameState, ui: &mut U
_ => {}
}
}
/// Handles an input event in [`InputMode::Menu`].
///
/// Uses the clone-then-dispatch pattern: the action `Rc` is cloned to release
/// the immutable borrow on `ui.menu`, then the action is called with full `&mut Ui`.
pub(crate) fn handle_menu_input(event: Event, game: &mut GameState, ui: &mut Ui) {
match event {
Event::Key(key) => {
let pressed = match key.code {
KeyCode::Esc => Some(MenuKey::Esc),
KeyCode::Char(c) => Some(MenuKey::Char(c)),
KeyCode::Up => { ui.scroll_menu(-1); None }
KeyCode::Down => { ui.scroll_menu(1); None }
_ => None,
};
if let Some(mk) = pressed {
// Clone the Rc to release the borrow on ui.menu before calling the action.
let action: Option<MenuActionRc> = ui.menu.as_ref()
.and_then(|m| m.items.iter().find(|i| i.key == mk))
.map(|i| i.action_rc());
if let Some(action) = action {
MenuItem::call_action_rc(action, game, ui);
}
}
}
Event::Mouse(m) => match m.kind {
MouseEventKind::ScrollUp => ui.scroll_menu(-1),
MouseEventKind::ScrollDown => ui.scroll_menu(1),
_ => {}
},
_ => {}
}
}