diff --git a/src/common/button_config.rs b/src/common/button_config.rs index 7055c6d..8c6508d 100644 --- a/src/common/button_config.rs +++ b/src/common/button_config.rs @@ -1,7 +1,10 @@ -use crate::common::menu::P1_CONTROLLER_STATE; +use std::collections::HashMap; + use crate::common::*; use crate::input::{ControllerStyle::*, *}; +use lazy_static::lazy_static; +use parking_lot::Mutex; use strum::IntoEnumIterator; use strum_macros::EnumIter; @@ -43,7 +46,7 @@ pub fn button_mapping( } } -#[derive(Debug, EnumIter, PartialEq)] +#[derive(Debug, EnumIter, PartialEq, Eq, Hash, Copy, Clone)] pub enum ButtonCombo { OpenMenu, SaveState, @@ -62,27 +65,32 @@ unsafe fn get_combo_keys(combo: ButtonCombo) -> ButtonConfig { } } -fn combo_passes(combo: ButtonCombo) -> bool { +lazy_static! { + static ref BUTTON_COMBO_REQUESTS: Mutex> = + Mutex::new(HashMap::from([ + (ButtonCombo::OpenMenu, false), + (ButtonCombo::SaveState, false), + (ButtonCombo::LoadState, false), + (ButtonCombo::InputRecord, false), + (ButtonCombo::InputPlayback, false), + ])); +} + +fn combo_passes(p1_controller: Controller, combo: ButtonCombo) -> bool { unsafe { let combo_keys = get_combo_keys(combo).to_vec(); - let p1_controller_state = *P1_CONTROLLER_STATE.data_ptr(); - let mut this_combo_passes = false; for hold_button in &combo_keys[..] { if button_mapping( *hold_button, - p1_controller_state.style, - p1_controller_state.current_buttons, + p1_controller.style, + p1_controller.current_buttons, ) && combo_keys .iter() .filter(|press_button| **press_button != *hold_button) .all(|press_button| { - button_mapping( - *press_button, - p1_controller_state.style, - p1_controller_state.just_down, - ) + button_mapping(*press_button, p1_controller.style, p1_controller.just_down) }) { this_combo_passes = true; @@ -93,9 +101,39 @@ fn combo_passes(combo: ButtonCombo) -> bool { } } -pub fn combo_passes_exclusive(combo: ButtonCombo) -> bool { +pub fn _combo_passes_exclusive(p1_controller: Controller, combo: ButtonCombo) -> bool { let other_combo_passes = ButtonCombo::iter() .filter(|other_combo| *other_combo != combo) - .any(combo_passes); - combo_passes(combo) && !other_combo_passes + .any(|other_combo| combo_passes(p1_controller, other_combo)); + combo_passes(p1_controller, combo) && !other_combo_passes +} + +pub fn combo_passes_exclusive(combo: ButtonCombo) -> bool { + unsafe { + let button_combo_requests = &mut *BUTTON_COMBO_REQUESTS.data_ptr(); + let passes = button_combo_requests.get_mut(&combo); + let mut did_pass = false; + if let Some(passes) = passes { + if *passes { + did_pass = true; + } + *passes = false; + } + + did_pass + } +} + +pub fn handle_final_input_mapping(player_idx: i32, controller_struct: &SomeControllerStruct) { + if player_idx == 0 { + let p1_controller = *controller_struct.controller; + let button_combo_requests = &mut *BUTTON_COMBO_REQUESTS.lock(); + button_combo_requests + .iter_mut() + .for_each(|(combo, is_request)| { + if !*is_request { + *is_request = _combo_passes_exclusive(p1_controller, *combo); + } + }) + } } diff --git a/src/common/menu.rs b/src/common/menu.rs index 1001aba..c689629 100644 --- a/src/common/menu.rs +++ b/src/common/menu.rs @@ -78,18 +78,6 @@ pub fn spawn_menu() { } } -lazy_static! { - pub static ref QUICK_MENU_APP: Mutex> = Mutex::new( - training_mod_tui::App::new(unsafe { ui_menu(MENU) }, unsafe { - ( - ui_menu(DEFAULTS_MENU), - serde_json::to_string(&DEFAULTS_MENU).unwrap(), - ) - }) - ); - pub static ref P1_CONTROLLER_STATE: Mutex = Mutex::new(Controller::default()); -} - #[derive(Eq, PartialEq, Hash, Copy, Clone)] enum DirectionButton { DpadLeft, @@ -106,6 +94,36 @@ enum DirectionButton { RUp, } +lazy_static! { + pub static ref QUICK_MENU_APP: Mutex> = Mutex::new( + training_mod_tui::App::new(unsafe { ui_menu(MENU) }, unsafe { + ( + ui_menu(DEFAULTS_MENU), + serde_json::to_string(&DEFAULTS_MENU).unwrap(), + ) + }) + ); + pub static ref P1_CONTROLLER_STYLE: Mutex = + Mutex::new(ControllerStyle::default()); + static ref DIRECTION_HOLD_FRAMES: Mutex> = { + use DirectionButton::*; + Mutex::new(HashMap::from([ + (DpadLeft, 0), + (LLeft, 0), + (RLeft, 0), + (DpadDown, 0), + (LDown, 0), + (RDown, 0), + (DpadRight, 0), + (LRight, 0), + (RRight, 0), + (DpadUp, 0), + (LUp, 0), + (RUp, 0), + ])) + }; +} + pub fn handle_final_input_mapping( player_idx: i32, controller_struct: &SomeControllerStruct, @@ -113,7 +131,8 @@ pub fn handle_final_input_mapping( ) { unsafe { if player_idx == 0 { - *P1_CONTROLLER_STATE.lock() = *controller_struct.controller; + let p1_controller = *controller_struct.controller; + *P1_CONTROLLER_STYLE.lock() = p1_controller.style; if QUICK_MENU_ACTIVE { // If we're here, remove all other presses *out = MappedInputs::empty(); @@ -122,12 +141,7 @@ pub fn handle_final_input_mapping( 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(); + let direction_hold_frames = &mut *DIRECTION_HOLD_FRAMES.lock(); // Check for all controllers unplugged let mut potential_controller_ids = (0..8).collect::>(); @@ -140,41 +154,30 @@ pub fn handle_final_input_mapping( return; } - let p1_controller_state = *P1_CONTROLLER_STATE.data_ptr(); - let style = p1_controller_state.style; - let button_presses = p1_controller_state.just_down; + let style = p1_controller.style; + let button_presses = p1_controller.just_down; - let button_current_held = p1_controller_state.current_buttons; - let button_released = p1_controller_state.just_release; + let button_current_held = p1_controller.current_buttons; 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()), + let still_held = match direction { + DpadLeft => button_current_held.dpad_left(), + LLeft => button_current_held.l_left(), + RLeft => button_current_held.r_left(), + DpadDown => button_current_held.dpad_down(), + LDown => button_current_held.l_down(), + RDown => button_current_held.r_down(), + DpadRight => button_current_held.dpad_right(), + LRight => button_current_held.l_right(), + RRight => button_current_held.r_right(), + DpadUp => button_current_held.dpad_up(), + LUp => button_current_held.l_up(), + RUp => button_current_held.r_up(), }; if still_held { *frames += 1; - } - - if released { + } else { *frames = 0; } }); @@ -227,6 +230,7 @@ pub fn handle_final_input_mapping( || button_presses.r_left() || [DpadLeft, LLeft, RLeft].iter().any(hold_condition)) .then(|| { + received_input = true; app.on_left(); }); (button_presses.dpad_right() @@ -234,6 +238,7 @@ pub fn handle_final_input_mapping( || button_presses.r_right() || [DpadRight, LRight, RRight].iter().any(hold_condition)) .then(|| { + received_input = true; app.on_right(); }); (button_presses.dpad_up() @@ -241,6 +246,7 @@ pub fn handle_final_input_mapping( || button_presses.r_up() || [DpadUp, LUp, RUp].iter().any(hold_condition)) .then(|| { + received_input = true; app.on_up(); }); (button_presses.dpad_down() @@ -248,10 +254,12 @@ pub fn handle_final_input_mapping( || button_presses.r_down() || [DpadDown, LDown, RDown].iter().any(hold_condition)) .then(|| { + received_input = true; app.on_down(); }); if received_input { + direction_hold_frames.iter_mut().for_each(|(_, f)| *f = 0); set_menu_from_json(&app.get_menu_selections()); } } diff --git a/src/training/mod.rs b/src/training/mod.rs index 2d2ede0..7e17a1e 100644 --- a/src/training/mod.rs +++ b/src/training/mod.rs @@ -1,3 +1,4 @@ +use crate::common::button_config; use crate::common::{ consts::BuffOption, consts::FighterId, consts::MENU, dev_config, get_module_accessor, is_training_mode, menu, FIGHTER_MANAGER_ADDR, ITEM_MANAGER_ADDR, STAGE_MANAGER_ADDR, @@ -628,6 +629,7 @@ unsafe fn handle_final_input_mapping( if !is_training_mode() { return; } + button_config::handle_final_input_mapping(player_idx, controller_struct); menu::handle_final_input_mapping(player_idx, controller_struct, out); dev_config::handle_final_input_mapping(player_idx, controller_struct); input_delay::handle_final_input_mapping(player_idx, out); diff --git a/src/training/ui/menu.rs b/src/training/ui/menu.rs index c9bc76d..0824f30 100644 --- a/src/training/ui/menu.rs +++ b/src/training/ui/menu.rs @@ -405,8 +405,7 @@ pub unsafe fn draw(root_pane: &Pane) { }; let tab_titles = [prev_tab, tab_selected, next_tab].map(|idx| app_tabs[idx]); - let is_gcc = - (*common::menu::P1_CONTROLLER_STATE.data_ptr()).style == ControllerStyle::GCController; + let is_gcc = (*common::menu::P1_CONTROLLER_STYLE.data_ptr()) == ControllerStyle::GCController; let button_mapping = if is_gcc { GCC_BUTTON_MAPPING.clone() } else {