menus
This commit is contained in:
+38
-1
@@ -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),
|
||||
_ => {}
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user