diff --git a/src/common/button_config.rs b/src/common/button_config.rs index a0ca4b2..7055c6d 100644 --- a/src/common/button_config.rs +++ b/src/common/button_config.rs @@ -31,14 +31,15 @@ pub fn button_mapping( GCController => b.r() || b.real_digital_r(), _ => b.zr() || b.left_sr() || b.right_sr(), }, - ButtonConfig::DpadUp => b.dpad_up(), - ButtonConfig::DpadDown => b.dpad_down(), - ButtonConfig::DpadLeft => b.dpad_left(), - ButtonConfig::DpadRight => b.dpad_right(), - ButtonConfig::Plus => b.plus(), - ButtonConfig::Minus => b.minus(), - ButtonConfig::LStick => b.stick_l(), - ButtonConfig::RStick => b.stick_r(), + ButtonConfig::DPAD_UP => b.dpad_up(), + ButtonConfig::DPAD_DOWN => b.dpad_down(), + ButtonConfig::DPAD_LEFT => b.dpad_left(), + ButtonConfig::DPAD_RIGHT => b.dpad_right(), + ButtonConfig::PLUS => b.plus(), + ButtonConfig::MINUS => b.minus(), + ButtonConfig::LSTICK => b.stick_l(), + ButtonConfig::RSTICK => b.stick_r(), + _ => false, } } @@ -51,30 +52,44 @@ pub enum ButtonCombo { InputPlayback, } -unsafe fn get_combo_keys(combo: ButtonCombo) -> (ButtonConfig, ButtonConfig) { +unsafe fn get_combo_keys(combo: ButtonCombo) -> ButtonConfig { match combo { - ButtonCombo::OpenMenu => (MENU.menu_open_hold, MENU.menu_open_press), - ButtonCombo::SaveState => (MENU.save_state_save_hold, MENU.save_state_save_press), - ButtonCombo::LoadState => (MENU.save_state_load_hold, MENU.save_state_load_press), - ButtonCombo::InputRecord => (MENU.input_record_hold, MENU.input_record_press), - ButtonCombo::InputPlayback => (MENU.input_playback_hold, MENU.input_playback_press), + ButtonCombo::OpenMenu => MENU.menu_open, + ButtonCombo::SaveState => MENU.save_state_save, + ButtonCombo::LoadState => MENU.save_state_load, + ButtonCombo::InputRecord => MENU.input_record, + ButtonCombo::InputPlayback => MENU.input_playback, } } fn combo_passes(combo: ButtonCombo) -> bool { unsafe { - let (hold, press) = get_combo_keys(combo); + let combo_keys = get_combo_keys(combo).to_vec(); let p1_controller_state = *P1_CONTROLLER_STATE.data_ptr(); - button_mapping( - hold, - p1_controller_state.style, - p1_controller_state.current_buttons, - ) && button_mapping( - press, - p1_controller_state.style, - p1_controller_state.just_down, - ) + 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, + ) && 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, + ) + }) + { + this_combo_passes = true; + } + } + + this_combo_passes } } diff --git a/src/lib.rs b/src/lib.rs index eb645c9..6e63c7b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,5 @@ #![feature(proc_macro_hygiene)] +#![feature(iter_intersperse)] #![feature(const_mut_refs)] #![feature(exclusive_range_pattern)] #![feature(c_variadic)] @@ -108,47 +109,52 @@ pub fn main() { notification("Training Modpack".to_string(), "Welcome!".to_string(), 60); notification( "Open Menu".to_string(), - format!( - "{} + {}", - MENU.menu_open_hold.as_str(), - MENU.menu_open_press.as_str() - ), + MENU.menu_open + .to_vec() + .iter() + .map(|button| button.as_str().unwrap()) + .intersperse(" + ") + .collect(), 120, ); notification( "Save State".to_string(), - format!( - "{} + {}", - MENU.save_state_save_hold.as_str(), - MENU.save_state_save_press.as_str() - ), + MENU.save_state_save + .to_vec() + .iter() + .map(|button| button.as_str().unwrap()) + .intersperse(" + ") + .collect(), 120, ); notification( "Load State".to_string(), - format!( - "{} + {}", - MENU.save_state_load_hold.as_str(), - MENU.save_state_load_press.as_str() - ), + MENU.save_state_load + .to_vec() + .iter() + .map(|button| button.as_str().unwrap()) + .intersperse(" + ") + .collect(), 120, ); notification( "Input Record".to_string(), - format!( - "{} + {}", - MENU.input_record_hold.as_str(), - MENU.input_record_press.as_str() - ), + MENU.input_record + .to_vec() + .iter() + .map(|button| button.as_str().unwrap()) + .intersperse(" + ") + .collect(), 120, ); notification( "Input Playback".to_string(), - format!( - "{} + {}", - MENU.input_playback_hold.as_str(), - MENU.input_playback_press.as_str() - ), + MENU.input_playback + .to_vec() + .iter() + .map(|button| button.as_str().unwrap()) + .intersperse(" + ") + .collect(), 120, ); } diff --git a/training_mod_consts/src/lib.rs b/training_mod_consts/src/lib.rs index 39b9fee..9a93d64 100644 --- a/training_mod_consts/src/lib.rs +++ b/training_mod_consts/src/lib.rs @@ -80,16 +80,11 @@ pub struct TrainingModpackMenu { pub hitstun_playback: HitstunPlayback, pub playback_mash: OnOff, pub playback_loop: OnOff, - pub menu_open_hold: ButtonConfig, - pub menu_open_press: ButtonConfig, - pub save_state_save_hold: ButtonConfig, - pub save_state_save_press: ButtonConfig, - pub save_state_load_hold: ButtonConfig, - pub save_state_load_press: ButtonConfig, - pub input_record_hold: ButtonConfig, - pub input_record_press: ButtonConfig, - pub input_playback_hold: ButtonConfig, - pub input_playback_press: ButtonConfig, + pub menu_open: ButtonConfig, + pub save_state_save: ButtonConfig, + pub save_state_load: ButtonConfig, + pub input_record: ButtonConfig, + pub input_playback: ButtonConfig, } #[repr(C)] @@ -188,16 +183,11 @@ pub static DEFAULTS_MENU: TrainingModpackMenu = TrainingModpackMenu { hitstun_playback: HitstunPlayback::Hitstun, playback_mash: OnOff::On, playback_loop: OnOff::Off, - menu_open_hold: ButtonConfig::B, - menu_open_press: ButtonConfig::DpadUp, - save_state_save_hold: ButtonConfig::ZL, - save_state_save_press: ButtonConfig::DpadDown, - save_state_load_hold: ButtonConfig::ZL, - save_state_load_press: ButtonConfig::DpadUp, - input_record_hold: ButtonConfig::ZR, - input_record_press: ButtonConfig::DpadDown, - input_playback_hold: ButtonConfig::ZR, - input_playback_press: ButtonConfig::DpadUp, + menu_open: ButtonConfig::B.union(ButtonConfig::DPAD_UP), + save_state_save: ButtonConfig::ZL.union(ButtonConfig::DPAD_DOWN), + save_state_load: ButtonConfig::ZL.union(ButtonConfig::DPAD_UP), + input_record: ButtonConfig::ZR.union(ButtonConfig::DPAD_DOWN), + input_playback: ButtonConfig::ZR.union(ButtonConfig::DPAD_UP), }; pub static mut MENU: TrainingModpackMenu = DEFAULTS_MENU; @@ -832,74 +822,40 @@ pub unsafe fn ui_menu(menu: TrainingModpackMenu) -> UiMenu<'static> { tab_submenus: Vec::new(), }; button_tab.add_submenu_with_toggles::( - "Menu Open: Hold", - "menu_open_hold", - "Menu Open: Hold: Which button to hold down before pressing Menu Open: Press", - true, - &(menu.menu_open_hold as u32), + "Menu Open", + "menu_open", + "Menu Open: Hold: Hold any one button and press the others to trigger", + false, + &(menu.menu_open.bits() as u32), ); button_tab.add_submenu_with_toggles::( - "Menu Open: Press", - "menu_open_press", - "Menu Open: Press: Which button to press after holding Menu Open: Hold", - true, - &(menu.menu_open_press as u32), + "Save State Save", + "save_state_save", + "Save State Save: Hold any one button and press the others to trigger", + false, + &(menu.save_state_save.bits() as u32), + ); + + button_tab.add_submenu_with_toggles::( + "Save State Load", + "save_state_load", + "Save State Load: Hold any one button and press the others to trigger", + false, + &(menu.save_state_load.bits() as u32), ); button_tab.add_submenu_with_toggles::( - "Save State Save: Hold", - "save_state_save_hold", - "Save State Save: Hold: Which button to hold down before pressing Save State Save: Press", - true, - &(menu.save_state_save_hold as u32), + "Input Record", + "input_record", + "Input Record: Hold any one button and press the others to trigger", + false, + &(menu.input_record.bits() as u32), ); button_tab.add_submenu_with_toggles::( - "Save State Save: Press", - "save_state_save_press", - "Save State Save: Press: Which button to press after holding Save State Save: Hold", - true, - &(menu.save_state_save_press as u32), - ); - button_tab.add_submenu_with_toggles::( - "Save State Load: Hold", - "save_state_load_hold", - "Save State Load: Hold: Which button to hold down before pressing Save State Load: Press", - true, - &(menu.save_state_load_hold as u32), - ); - button_tab.add_submenu_with_toggles::( - "Save State Load: Press", - "save_state_load_press", - "Save State Load: Press: Which button to press after holding Save State Load: Hold", - true, - &(menu.save_state_load_press as u32), - ); - button_tab.add_submenu_with_toggles::( - "Input Record: Hold", - "input_record_hold", - "Input Record: Hold: Which button to hold down before pressing Input Record: Press", - true, - &(menu.input_record_hold as u32), - ); - button_tab.add_submenu_with_toggles::( - "Input Record: Press", - "input_record_press", - "Input Record: Press: Which button to press after holding Input Record: Hold", - true, - &(menu.input_record_press as u32), - ); - button_tab.add_submenu_with_toggles::( - "Input Playback: Hold", - "input_playback_hold", - "Input Playback: Hold: Which button to hold down before pressing Input Playback: Press", - true, - &(menu.input_playback_hold as u32), - ); - button_tab.add_submenu_with_toggles::( - "Input Playback: Press", - "input_playback_press", - "Input Playback: Press: Which button to press after holding Input Playback: Hold", - true, - &(menu.input_playback_press as u32), + "Input Playback", + "input_playback", + "Input Playback: Hold any one button and press the others to trigger", + false, + &(menu.input_playback.bits() as u32), ); overall_menu.tabs.push(button_tab); diff --git a/training_mod_consts/src/options.rs b/training_mod_consts/src/options.rs index 7c08895..4796f87 100644 --- a/training_mod_consts/src/options.rs +++ b/training_mod_consts/src/options.rs @@ -1442,33 +1442,31 @@ impl ToggleTrait for RecordingFrames { } } -#[repr(u32)] -#[derive( - Debug, Clone, Copy, PartialEq, FromPrimitive, EnumIter, Serialize_repr, Deserialize_repr, -)] -pub enum ButtonConfig { - A = 0b0000_0000_0000_0000_0001, - B = 0b0000_0000_0000_0000_0010, - X = 0b0000_0000_0000_0000_0100, - Y = 0b0000_0000_0000_0000_1000, - L = 0b0000_0000_0000_0001_0000, - R = 0b0000_0000_0000_0010_0000, - ZL = 0b0000_0000_0000_0100_0000, - ZR = 0b0000_0000_0000_1000_0000, - DpadUp = 0b0000_0000_0001_0000_0000, - DpadDown = 0b0000_0000_0010_0000_0000, - DpadLeft = 0b0000_0000_0100_0000_0000, - DpadRight = 0b0000_0000_1000_0000_0000, - Plus = 0b0000_0001_0000_0000_0000, - Minus = 0b0000_0010_0000_0000_0000, - LStick = 0b0000_0100_0000_0000_0000, - RStick = 0b0000_1000_0000_0000_0000, +bitflags! { + pub struct ButtonConfig : u32 { + const A = 0b0000_0000_0000_0000_0001; + const B = 0b0000_0000_0000_0000_0010; + const X = 0b0000_0000_0000_0000_0100; + const Y = 0b0000_0000_0000_0000_1000; + const L = 0b0000_0000_0000_0001_0000; + const R = 0b0000_0000_0000_0010_0000; + const ZL = 0b0000_0000_0000_0100_0000; + const ZR = 0b0000_0000_0000_1000_0000; + const DPAD_UP = 0b0000_0000_0001_0000_0000; + const DPAD_DOWN = 0b0000_0000_0010_0000_0000; + const DPAD_LEFT = 0b0000_0000_0100_0000_0000; + const DPAD_RIGHT = 0b0000_0000_1000_0000_0000; + const PLUS = 0b0000_0001_0000_0000_0000; + const MINUS = 0b0000_0010_0000_0000_0000; + const LSTICK = 0b0000_0100_0000_0000_0000; + const RSTICK = 0b0000_1000_0000_0000_0000; + } } impl ButtonConfig { // Should we use the font glyphs? Or do that special casing in the menu? - pub fn as_str(self) -> &'static str { - match self { + pub fn as_str(self) -> Option<&'static str> { + Some(match self { ButtonConfig::A => "A", ButtonConfig::B => "B", ButtonConfig::X => "X", @@ -1477,24 +1475,18 @@ impl ButtonConfig { ButtonConfig::R => "Pro R; GCC Z", ButtonConfig::ZL => "Pro ZL; GCC L", ButtonConfig::ZR => "Pro ZR; GCC R", - ButtonConfig::DpadUp => "DPad Up", - ButtonConfig::DpadDown => "DPad Down", - ButtonConfig::DpadLeft => "DPad Left", - ButtonConfig::DpadRight => "DPad Right", - ButtonConfig::Plus => "Plus", - ButtonConfig::Minus => "Minus", - ButtonConfig::LStick => "Left Stick Press", - ButtonConfig::RStick => "Right Stick Press", - } + ButtonConfig::DPAD_UP => "DPad Up", + ButtonConfig::DPAD_DOWN => "DPad Down", + ButtonConfig::DPAD_LEFT => "DPad Left", + ButtonConfig::DPAD_RIGHT => "DPad Right", + ButtonConfig::PLUS => "Plus", + ButtonConfig::MINUS => "Minus", + ButtonConfig::LSTICK => "Left Stick Press", + ButtonConfig::RSTICK => "Right Stick Press", + _ => return None, + }) } } -impl ToggleTrait for ButtonConfig { - fn to_toggle_strs() -> Vec<&'static str> { - ButtonConfig::iter().map(|i| i.as_str()).collect() - } - - fn to_toggle_vals() -> Vec { - ButtonConfig::iter().map(|i| i as u32).collect() - } -} +extra_bitflag_impls! {ButtonConfig} +impl_serde_for_bitflags!(ButtonConfig);