mirror of
https://github.com/jugeeya/UltimateTrainingModpack.git
synced 2024-11-20 00:46:34 +00:00
[Menu Input] Fixes to input hold + consistency (#586)
This commit is contained in:
parent
a76808c838
commit
8abc20812e
4 changed files with 111 additions and 64 deletions
|
@ -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<HashMap<ButtonCombo, bool>> =
|
||||
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);
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -78,18 +78,6 @@ pub fn spawn_menu() {
|
|||
}
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
pub static ref QUICK_MENU_APP: Mutex<training_mod_tui::App<'static>> = 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<Controller> = 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<training_mod_tui::App<'static>> = 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<ControllerStyle> =
|
||||
Mutex::new(ControllerStyle::default());
|
||||
static ref DIRECTION_HOLD_FRAMES: Mutex<HashMap<DirectionButton, u32>> = {
|
||||
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<DirectionButton, u32> =
|
||||
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::<Vec<u32>>();
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in a new issue