diff --git a/src/common/menu.rs b/src/common/menu.rs index f76183e..1001aba 100644 --- a/src/common/menu.rs +++ b/src/common/menu.rs @@ -1,3 +1,4 @@ +use std::collections::HashMap; use std::fs; use lazy_static::lazy_static; @@ -89,6 +90,22 @@ lazy_static! { pub static ref P1_CONTROLLER_STATE: Mutex = Mutex::new(Controller::default()); } +#[derive(Eq, PartialEq, Hash, Copy, Clone)] +enum DirectionButton { + DpadLeft, + LLeft, + RLeft, + DpadDown, + LDown, + RDown, + DpadRight, + LRight, + RRight, + DpadUp, + LUp, + RUp, +} + pub fn handle_final_input_mapping( player_idx: i32, controller_struct: &SomeControllerStruct, @@ -100,102 +117,143 @@ pub fn handle_final_input_mapping( if QUICK_MENU_ACTIVE { // If we're here, remove all other presses *out = MappedInputs::empty(); - } - } - } -} -pub unsafe fn quick_menu_loop() { - loop { - std::thread::sleep(std::time::Duration::from_secs(10)); - let mut received_input = true; - loop { - std::thread::sleep(std::time::Duration::from_millis(16)); + let mut received_input = false; - if !QUICK_MENU_ACTIVE { - continue; - } + const DIRECTION_HOLD_REPEAT_FRAMES: u32 = 20; + use DirectionButton::*; + let directions = [ + DpadLeft, LLeft, RLeft, DpadDown, LDown, RDown, DpadRight, LRight, RRight, + DpadUp, LUp, RUp, + ]; + let mut direction_hold_frames: HashMap = + directions.iter().map(|config| (*config, 0)).collect(); - // Check for all controllers unplugged - let mut potential_controller_ids = (0..8).collect::>(); - potential_controller_ids.push(0x20); - if potential_controller_ids - .iter() - .all(|i| GetNpadStyleSet(i as *const _).flags == 0) - { - QUICK_MENU_ACTIVE = false; - continue; - } - - let p1_controller_state = *P1_CONTROLLER_STATE.data_ptr(); - let style = p1_controller_state.style; - let button_presses = p1_controller_state.just_down; - - let app = &mut *QUICK_MENU_APP.data_ptr(); - button_mapping(ButtonConfig::A, style, button_presses).then(|| { - app.on_a(); - received_input = true; - }); - button_mapping(ButtonConfig::B, style, button_presses).then(|| { - received_input = true; - if app.page != AppPage::SUBMENU { - app.on_b() - } else if FRAME_COUNTER > MENU_CLOSE_WAIT_FRAMES { - // Leave menu. + // Check for all controllers unplugged + let mut potential_controller_ids = (0..8).collect::>(); + potential_controller_ids.push(0x20); + if potential_controller_ids + .iter() + .all(|i| GetNpadStyleSet(i as *const _).flags == 0) + { QUICK_MENU_ACTIVE = false; - FRAME_COUNTER = 0; - let menu_json = app.get_menu_selections(); - set_menu_from_json(&menu_json); - EVENT_QUEUE.push(Event::menu_open(menu_json)); + return; } - }); - button_mapping(ButtonConfig::X, style, button_presses).then(|| { - app.save_defaults(); - received_input = true; - }); - button_mapping(ButtonConfig::Y, style, button_presses).then(|| { - app.reset_all_submenus(); - received_input = true; - }); - button_mapping(ButtonConfig::ZL, style, button_presses).then(|| { - app.previous_tab(); - received_input = true; - }); - button_mapping(ButtonConfig::ZR, style, button_presses).then(|| { - app.next_tab(); - received_input = true; - }); - button_mapping(ButtonConfig::R, style, button_presses).then(|| { - app.reset_current_submenu(); - received_input = true; - }); + let p1_controller_state = *P1_CONTROLLER_STATE.data_ptr(); + let style = p1_controller_state.style; + let button_presses = p1_controller_state.just_down; - (button_presses.dpad_left() || button_presses.l_left() || button_presses.r_left()) + let button_current_held = p1_controller_state.current_buttons; + let button_released = p1_controller_state.just_release; + direction_hold_frames + .iter_mut() + .for_each(|(direction, frames)| { + let (still_held, released) = match direction { + DpadLeft => { + (button_current_held.dpad_left(), button_released.dpad_left()) + } + LLeft => (button_current_held.l_left(), button_released.l_left()), + RLeft => (button_current_held.r_left(), button_released.r_left()), + DpadDown => { + (button_current_held.dpad_down(), button_released.dpad_down()) + } + LDown => (button_current_held.l_down(), button_released.l_down()), + RDown => (button_current_held.r_down(), button_released.r_down()), + DpadRight => ( + button_current_held.dpad_right(), + button_released.dpad_right(), + ), + LRight => (button_current_held.l_right(), button_released.l_right()), + RRight => (button_current_held.r_right(), button_released.r_right()), + DpadUp => (button_current_held.dpad_up(), button_released.dpad_up()), + LUp => (button_current_held.l_up(), button_released.l_up()), + RUp => (button_current_held.r_up(), button_released.r_up()), + }; + if still_held { + *frames += 1; + } + + if released { + *frames = 0; + } + }); + + let app = &mut *QUICK_MENU_APP.data_ptr(); + button_mapping(ButtonConfig::A, style, button_presses).then(|| { + app.on_a(); + received_input = true; + }); + button_mapping(ButtonConfig::B, style, button_presses).then(|| { + received_input = true; + if app.page != AppPage::SUBMENU { + app.on_b() + } else if FRAME_COUNTER > MENU_CLOSE_WAIT_FRAMES { + // Leave menu. + QUICK_MENU_ACTIVE = false; + FRAME_COUNTER = 0; + let menu_json = app.get_menu_selections(); + set_menu_from_json(&menu_json); + EVENT_QUEUE.push(Event::menu_open(menu_json)); + } + }); + button_mapping(ButtonConfig::X, style, button_presses).then(|| { + app.save_defaults(); + received_input = true; + }); + button_mapping(ButtonConfig::Y, style, button_presses).then(|| { + app.reset_all_submenus(); + received_input = true; + }); + + button_mapping(ButtonConfig::ZL, style, button_presses).then(|| { + app.previous_tab(); + received_input = true; + }); + button_mapping(ButtonConfig::ZR, style, button_presses).then(|| { + app.next_tab(); + received_input = true; + }); + button_mapping(ButtonConfig::R, style, button_presses).then(|| { + app.reset_current_submenu(); + received_input = true; + }); + + let hold_condition = |direction_button| { + direction_hold_frames[direction_button] > DIRECTION_HOLD_REPEAT_FRAMES + }; + (button_presses.dpad_left() + || button_presses.l_left() + || button_presses.r_left() + || [DpadLeft, LLeft, RLeft].iter().any(hold_condition)) .then(|| { app.on_left(); - received_input = true; }); - (button_presses.dpad_right() || button_presses.l_right() || button_presses.r_right()) + (button_presses.dpad_right() + || button_presses.l_right() + || button_presses.r_right() + || [DpadRight, LRight, RRight].iter().any(hold_condition)) .then(|| { app.on_right(); - received_input = true; }); - (button_presses.dpad_up() || button_presses.l_up() || button_presses.r_up()).then( - || { + (button_presses.dpad_up() + || button_presses.l_up() + || button_presses.r_up() + || [DpadUp, LUp, RUp].iter().any(hold_condition)) + .then(|| { app.on_up(); - received_input = true; - }, - ); - (button_presses.dpad_down() || button_presses.l_down() || button_presses.r_down()) + }); + (button_presses.dpad_down() + || button_presses.l_down() + || button_presses.r_down() + || [DpadDown, LDown, RDown].iter().any(hold_condition)) .then(|| { app.on_down(); - received_input = true; }); - if received_input { - received_input = false; - set_menu_from_json(&app.get_menu_selections()); + if received_input { + set_menu_from_json(&app.get_menu_selections()); + } } } } diff --git a/src/lib.rs b/src/lib.rs index 6e63c7b..a3bf0df 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -25,7 +25,6 @@ use crate::common::*; use crate::consts::TRAINING_MODPACK_ROOT; use crate::events::{Event, EVENT_QUEUE}; use crate::logging::*; -use crate::menu::quick_menu_loop; use crate::training::ui::notifications::notification; pub mod common; @@ -160,6 +159,4 @@ pub fn main() { } std::thread::spawn(events_loop); - - std::thread::spawn(|| unsafe { quick_menu_loop() }); }