mirror of
https://github.com/jugeeya/UltimateTrainingModpack.git
synced 2024-11-30 22:00:16 +00:00
Open Menu with Start Press (#598)
* Initial * Another fix * Don't allow opening our menu when vanilla menu is active * Add menu option ; remove delay to close menu * Fix issues when closing menu * Show button config first, log fade * Fix test * Fix test again * Fix initial notification, turn off hitbox visualization by default
This commit is contained in:
parent
58f699b285
commit
00f2284397
11 changed files with 221 additions and 87 deletions
2
ryujinx_build.ps1
vendored
2
ryujinx_build.ps1
vendored
|
@ -7,7 +7,7 @@ $LOCAL_LAYOUT_ARC_PATH="C:\Users\Josh\Documents\Games\UltimateTrainingModpack\sr
|
|||
$RYUJINX_PLUGIN_PATH="C:\Users\Josh\AppData\Roaming\Ryujinx\mods\contents\01006a800016e000\romfs\skyline\plugins\libtraining_modpack.nro"
|
||||
$LOCAL_PLUGIN_PATH="C:\Users\Josh\Documents\Games\UltimateTrainingModpack\target\aarch64-skyline-switch\release\libtraining_modpack.nro"
|
||||
|
||||
$RYUJINX_EXE_PATH="C:\Users\Josh\Documents\Games\Ryujinx\publish\Ryujinx.exe"
|
||||
$RYUJINX_EXE_PATH="C:\Users\Josh\Documents\Games\Ryujinx\ryujinx-1.1.999-win_x64\publish\Ryujinx.exe"
|
||||
$SMASH_NSP_PATH='C:\Users\Josh\Documents\Games\ROMs\Super Smash Bros Ultimate [Base Game]\Super Smash Bros Ultimate[01006A800016E000][US][v0].nsp'
|
||||
|
||||
|
||||
|
|
|
@ -2,12 +2,16 @@ use std::collections::HashMap;
|
|||
|
||||
use crate::common::*;
|
||||
use crate::input::{ControllerStyle::*, *};
|
||||
use crate::training::frame_counter;
|
||||
use crate::training::ui::menu::VANILLA_MENU_ACTIVE;
|
||||
|
||||
use lazy_static::lazy_static;
|
||||
use parking_lot::Mutex;
|
||||
use strum::IntoEnumIterator;
|
||||
use strum_macros::EnumIter;
|
||||
|
||||
use super::menu::QUICK_MENU_ACTIVE;
|
||||
|
||||
pub fn button_mapping(
|
||||
button_config: ButtonConfig,
|
||||
style: ControllerStyle,
|
||||
|
@ -55,9 +59,12 @@ pub enum ButtonCombo {
|
|||
InputPlayback,
|
||||
}
|
||||
|
||||
pub const DEFAULT_OPEN_MENU_CONFIG: ButtonConfig = ButtonConfig::B.union(ButtonConfig::DPAD_UP);
|
||||
|
||||
unsafe fn get_combo_keys(combo: ButtonCombo) -> ButtonConfig {
|
||||
match combo {
|
||||
ButtonCombo::OpenMenu => MENU.menu_open,
|
||||
// For OpenMenu, have a default in addition to accepting start press
|
||||
ButtonCombo::OpenMenu => DEFAULT_OPEN_MENU_CONFIG,
|
||||
ButtonCombo::SaveState => MENU.save_state_save,
|
||||
ButtonCombo::LoadState => MENU.save_state_load,
|
||||
ButtonCombo::InputRecord => MENU.input_record,
|
||||
|
@ -74,6 +81,7 @@ lazy_static! {
|
|||
(ButtonCombo::InputRecord, false),
|
||||
(ButtonCombo::InputPlayback, false),
|
||||
]));
|
||||
static ref START_HOLD_FRAMES: Mutex<u32> = Mutex::new(0);
|
||||
}
|
||||
|
||||
fn combo_passes(p1_controller: Controller, combo: ButtonCombo) -> bool {
|
||||
|
@ -124,15 +132,53 @@ pub fn combo_passes_exclusive(combo: ButtonCombo) -> bool {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn handle_final_input_mapping(player_idx: i32, controller_struct: &SomeControllerStruct) {
|
||||
pub fn handle_final_input_mapping(player_idx: i32, controller_struct: &mut SomeControllerStruct) {
|
||||
if player_idx == 0 {
|
||||
let p1_controller = *controller_struct.controller;
|
||||
let p1_controller = &mut *controller_struct.controller;
|
||||
let mut start_menu_request = false;
|
||||
|
||||
let menu_close_wait_frame =
|
||||
unsafe { frame_counter::get_frame_count(menu::FRAME_COUNTER_INDEX) };
|
||||
if unsafe { MENU.menu_open_start_press == OnOff::On } {
|
||||
let start_hold_frames = &mut *START_HOLD_FRAMES.lock();
|
||||
if p1_controller.current_buttons.plus() {
|
||||
*start_hold_frames += 1;
|
||||
p1_controller.previous_buttons.set_plus(false);
|
||||
p1_controller.current_buttons.set_plus(false);
|
||||
p1_controller.just_down.set_plus(false);
|
||||
p1_controller.just_release.set_plus(false);
|
||||
} else {
|
||||
if *start_hold_frames > 0 && menu_close_wait_frame == 0 {
|
||||
// Here, we just finished holding start
|
||||
if *start_hold_frames < 10
|
||||
&& unsafe { !VANILLA_MENU_ACTIVE }
|
||||
&& menu_close_wait_frame == 0
|
||||
{
|
||||
// If we held for fewer than 10 frames, let's open the training mod menu
|
||||
start_menu_request = true;
|
||||
} else if unsafe { !QUICK_MENU_ACTIVE } {
|
||||
// Otherwise, let's let the game know that we had pressed start
|
||||
// So long as our menu isn't active
|
||||
p1_controller.current_buttons.set_plus(true);
|
||||
p1_controller.just_down.set_plus(true);
|
||||
unsafe {
|
||||
VANILLA_MENU_ACTIVE = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
*start_hold_frames = 0;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
*is_request = _combo_passes_exclusive(*p1_controller, *combo);
|
||||
if *combo == button_config::ButtonCombo::OpenMenu && start_menu_request {
|
||||
*is_request = true;
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -267,7 +267,7 @@ pub struct SomeControllerStruct {
|
|||
}
|
||||
|
||||
// Define struct used for final controller inputs
|
||||
#[derive(Copy, Clone)]
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
#[repr(C)]
|
||||
pub struct MappedInputs {
|
||||
pub buttons: Buttons,
|
||||
|
|
|
@ -13,13 +13,18 @@ use crate::consts::MENU_OPTIONS_PATH;
|
|||
use crate::events::{Event, EVENT_QUEUE};
|
||||
use crate::input::*;
|
||||
use crate::logging::*;
|
||||
use crate::training::frame_counter;
|
||||
|
||||
// This is a special frame counter that will tick on draw()
|
||||
// We'll count how long the menu has been open
|
||||
pub static mut FRAME_COUNTER: u32 = 0;
|
||||
const MENU_CLOSE_WAIT_FRAMES: u32 = 60;
|
||||
pub static mut FRAME_COUNTER_INDEX: usize = 0;
|
||||
pub const MENU_CLOSE_WAIT_FRAMES: u32 = 15;
|
||||
pub static mut QUICK_MENU_ACTIVE: bool = false;
|
||||
|
||||
pub fn init() {
|
||||
unsafe {
|
||||
FRAME_COUNTER_INDEX = frame_counter::register_counter_no_reset();
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn menu_condition() -> bool {
|
||||
button_config::combo_passes_exclusive(button_config::ButtonCombo::OpenMenu)
|
||||
}
|
||||
|
@ -72,23 +77,18 @@ pub unsafe fn set_menu_from_json(message: &str) {
|
|||
|
||||
pub fn spawn_menu() {
|
||||
unsafe {
|
||||
FRAME_COUNTER = 0;
|
||||
QUICK_MENU_ACTIVE = true;
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Eq, PartialEq, Hash, Copy, Clone)]
|
||||
enum DirectionButton {
|
||||
DpadLeft,
|
||||
LLeft,
|
||||
RLeft,
|
||||
DpadDown,
|
||||
LDown,
|
||||
RDown,
|
||||
DpadRight,
|
||||
LRight,
|
||||
RRight,
|
||||
DpadUp,
|
||||
LUp,
|
||||
RUp,
|
||||
}
|
||||
|
@ -107,16 +107,12 @@ lazy_static! {
|
|||
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),
|
||||
]))
|
||||
|
@ -125,13 +121,28 @@ lazy_static! {
|
|||
|
||||
pub fn handle_final_input_mapping(
|
||||
player_idx: i32,
|
||||
controller_struct: &SomeControllerStruct,
|
||||
controller_struct: &mut SomeControllerStruct,
|
||||
out: *mut MappedInputs,
|
||||
) {
|
||||
unsafe {
|
||||
if player_idx == 0 {
|
||||
let p1_controller = *controller_struct.controller;
|
||||
let p1_controller = &mut *controller_struct.controller;
|
||||
*P1_CONTROLLER_STYLE.lock() = p1_controller.style;
|
||||
if frame_counter::get_frame_count(FRAME_COUNTER_INDEX) > 0
|
||||
&& frame_counter::get_frame_count(FRAME_COUNTER_INDEX) < MENU_CLOSE_WAIT_FRAMES
|
||||
{
|
||||
// If we just closed the menu, kill all inputs to avoid accidental presses
|
||||
*out = MappedInputs::empty();
|
||||
p1_controller.current_buttons = ButtonBitfield::default();
|
||||
p1_controller.previous_buttons = ButtonBitfield::default();
|
||||
p1_controller.just_down = ButtonBitfield::default();
|
||||
p1_controller.just_release = ButtonBitfield::default();
|
||||
} else if frame_counter::get_frame_count(FRAME_COUNTER_INDEX) >= MENU_CLOSE_WAIT_FRAMES
|
||||
{
|
||||
frame_counter::reset_frame_count(FRAME_COUNTER_INDEX);
|
||||
frame_counter::stop_counting(FRAME_COUNTER_INDEX);
|
||||
}
|
||||
|
||||
if QUICK_MENU_ACTIVE {
|
||||
// If we're here, remove all other presses
|
||||
*out = MappedInputs::empty();
|
||||
|
@ -161,16 +172,12 @@ pub fn handle_final_input_mapping(
|
|||
.iter_mut()
|
||||
.for_each(|(direction, frames)| {
|
||||
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(),
|
||||
};
|
||||
|
@ -190,15 +197,24 @@ pub fn handle_final_input_mapping(
|
|||
received_input = true;
|
||||
if app.page != AppPage::SUBMENU {
|
||||
app.on_b()
|
||||
} else if FRAME_COUNTER > MENU_CLOSE_WAIT_FRAMES {
|
||||
} else {
|
||||
// Leave menu.
|
||||
frame_counter::start_counting(FRAME_COUNTER_INDEX);
|
||||
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::PLUS, style, button_presses).then(|| {
|
||||
received_input = true;
|
||||
// Leave menu.
|
||||
frame_counter::start_counting(FRAME_COUNTER_INDEX);
|
||||
QUICK_MENU_ACTIVE = false;
|
||||
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;
|
||||
|
@ -227,7 +243,7 @@ pub fn handle_final_input_mapping(
|
|||
(button_presses.dpad_left()
|
||||
|| button_presses.l_left()
|
||||
|| button_presses.r_left()
|
||||
|| [DpadLeft, LLeft, RLeft].iter().any(hold_condition))
|
||||
|| [LLeft, RLeft].iter().any(hold_condition))
|
||||
.then(|| {
|
||||
received_input = true;
|
||||
app.on_left();
|
||||
|
@ -235,7 +251,7 @@ pub fn handle_final_input_mapping(
|
|||
(button_presses.dpad_right()
|
||||
|| button_presses.l_right()
|
||||
|| button_presses.r_right()
|
||||
|| [DpadRight, LRight, RRight].iter().any(hold_condition))
|
||||
|| [LRight, RRight].iter().any(hold_condition))
|
||||
.then(|| {
|
||||
received_input = true;
|
||||
app.on_right();
|
||||
|
@ -243,7 +259,7 @@ pub fn handle_final_input_mapping(
|
|||
(button_presses.dpad_up()
|
||||
|| button_presses.l_up()
|
||||
|| button_presses.r_up()
|
||||
|| [DpadUp, LUp, RUp].iter().any(hold_condition))
|
||||
|| [LUp, RUp].iter().any(hold_condition))
|
||||
.then(|| {
|
||||
received_input = true;
|
||||
app.on_up();
|
||||
|
@ -251,7 +267,7 @@ pub fn handle_final_input_mapping(
|
|||
(button_presses.dpad_down()
|
||||
|| button_presses.l_down()
|
||||
|| button_presses.r_down()
|
||||
|| [DpadDown, LDown, RDown].iter().any(hold_condition))
|
||||
|| [LDown, RDown].iter().any(hold_condition))
|
||||
.then(|| {
|
||||
received_input = true;
|
||||
app.on_down();
|
||||
|
|
13
src/lib.rs
13
src/lib.rs
|
@ -18,8 +18,9 @@ use std::fs;
|
|||
use std::path::PathBuf;
|
||||
|
||||
use skyline::nro::{self, NroInfo};
|
||||
use training_mod_consts::LEGACY_TRAINING_MODPACK_ROOT;
|
||||
use training_mod_consts::{OnOff, LEGACY_TRAINING_MODPACK_ROOT};
|
||||
|
||||
use crate::common::button_config::DEFAULT_OPEN_MENU_CONFIG;
|
||||
use crate::common::events::events_loop;
|
||||
use crate::common::*;
|
||||
use crate::consts::TRAINING_MODPACK_ROOT;
|
||||
|
@ -117,7 +118,15 @@ pub fn main() {
|
|||
|
||||
unsafe {
|
||||
notification("Training Modpack".to_string(), "Welcome!".to_string(), 60);
|
||||
notification("Open Menu".to_string(), MENU.menu_open.to_string(), 120);
|
||||
notification(
|
||||
"Open Menu".to_string(),
|
||||
if MENU.menu_open_start_press == OnOff::On {
|
||||
"Start".to_string()
|
||||
} else {
|
||||
DEFAULT_OPEN_MENU_CONFIG.to_string()
|
||||
},
|
||||
120,
|
||||
);
|
||||
notification(
|
||||
"Save State".to_string(),
|
||||
MENU.save_state_save.to_string(),
|
||||
|
|
|
@ -1,17 +1,27 @@
|
|||
static mut SHOULD_COUNT: Vec<bool> = vec![];
|
||||
static mut NO_RESET: Vec<bool> = vec![];
|
||||
static mut COUNTERS: Vec<u32> = vec![];
|
||||
|
||||
pub fn register_counter() -> usize {
|
||||
fn _register_counter(no_reset: bool) -> usize {
|
||||
unsafe {
|
||||
let index = COUNTERS.len();
|
||||
|
||||
COUNTERS.push(0);
|
||||
SHOULD_COUNT.push(false);
|
||||
NO_RESET.push(no_reset);
|
||||
|
||||
index
|
||||
}
|
||||
}
|
||||
|
||||
pub fn register_counter_no_reset() -> usize {
|
||||
_register_counter(true)
|
||||
}
|
||||
|
||||
pub fn register_counter() -> usize {
|
||||
_register_counter(false)
|
||||
}
|
||||
|
||||
pub fn start_counting(index: usize) {
|
||||
unsafe {
|
||||
SHOULD_COUNT[index] = true;
|
||||
|
@ -81,6 +91,9 @@ pub fn tick() {
|
|||
pub fn reset_all() {
|
||||
unsafe {
|
||||
for (index, _frame) in COUNTERS.iter().enumerate() {
|
||||
if NO_RESET[index] {
|
||||
continue;
|
||||
}
|
||||
full_reset(index);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -701,8 +701,8 @@ 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);
|
||||
button_config::handle_final_input_mapping(player_idx, controller_struct);
|
||||
dev_config::handle_final_input_mapping(player_idx, controller_struct);
|
||||
input_delay::handle_final_input_mapping(player_idx, out);
|
||||
input_record::handle_final_input_mapping(player_idx, out);
|
||||
|
@ -800,4 +800,5 @@ pub fn training_mods() {
|
|||
tech::init();
|
||||
input_record::init();
|
||||
ui::init();
|
||||
menu::init();
|
||||
}
|
||||
|
|
|
@ -6,8 +6,12 @@ use smash::ui2d::{SmashPane, SmashTextBox};
|
|||
use training_mod_tui::gauge::GaugeState;
|
||||
use training_mod_tui::{App, AppPage, NUM_LISTS};
|
||||
|
||||
use crate::common::menu::{self, MENU_CLOSE_WAIT_FRAMES};
|
||||
use crate::training::frame_counter;
|
||||
use crate::{common, common::menu::QUICK_MENU_ACTIVE, input::*};
|
||||
|
||||
use super::fade_out;
|
||||
|
||||
pub static NUM_MENU_TEXT_OPTIONS: usize = 32;
|
||||
pub static _NUM_MENU_TABS: usize = 3;
|
||||
|
||||
|
@ -53,6 +57,8 @@ const BG_LEFT_SELECTED_WHITE_COLOR: ResColor = ResColor {
|
|||
a: 255,
|
||||
};
|
||||
|
||||
pub static mut VANILLA_MENU_ACTIVE: bool = false;
|
||||
|
||||
lazy_static! {
|
||||
static ref GCC_BUTTON_MAPPING: HashMap<&'static str, u16> = HashMap::from([
|
||||
("L", 0xE204),
|
||||
|
@ -346,6 +352,15 @@ unsafe fn render_slider_page(app: &App, root_pane: &Pane) {
|
|||
}
|
||||
|
||||
pub unsafe fn draw(root_pane: &Pane) {
|
||||
// Determine if we're in the menu by seeing if the "help" footer has
|
||||
// begun moving upward. It starts at -80 and moves to 0 over 10 frames
|
||||
// in info_training_in_menu.bflan
|
||||
VANILLA_MENU_ACTIVE = root_pane
|
||||
.find_pane_by_name_recursive("L_staying_help")
|
||||
.unwrap()
|
||||
.pos_y
|
||||
!= -80.0;
|
||||
|
||||
// Update menu display
|
||||
// Grabbing lock as read-only, essentially
|
||||
let app = &*crate::common::menu::QUICK_MENU_APP.data_ptr();
|
||||
|
@ -357,12 +372,21 @@ pub unsafe fn draw(root_pane: &Pane) {
|
|||
}
|
||||
}
|
||||
|
||||
root_pane
|
||||
.find_pane_by_name_recursive("TrModMenu")
|
||||
.unwrap()
|
||||
.set_visible(QUICK_MENU_ACTIVE);
|
||||
let overall_parent_pane = root_pane.find_pane_by_name_recursive("TrModMenu").unwrap();
|
||||
overall_parent_pane.set_visible(true);
|
||||
let menu_close_wait_frame = frame_counter::get_frame_count(menu::FRAME_COUNTER_INDEX);
|
||||
if QUICK_MENU_ACTIVE {
|
||||
common::menu::FRAME_COUNTER += 1;
|
||||
overall_parent_pane.alpha = 255;
|
||||
overall_parent_pane.global_alpha = 255;
|
||||
} else if menu_close_wait_frame > 0 {
|
||||
fade_out(
|
||||
overall_parent_pane,
|
||||
MENU_CLOSE_WAIT_FRAMES - menu_close_wait_frame,
|
||||
MENU_CLOSE_WAIT_FRAMES,
|
||||
);
|
||||
} else {
|
||||
overall_parent_pane.alpha = 0;
|
||||
overall_parent_pane.global_alpha = 0;
|
||||
}
|
||||
|
||||
// Make all invisible first
|
||||
|
|
|
@ -10,9 +10,27 @@ use crate::consts::LAYOUT_ARC_PATH;
|
|||
|
||||
mod damage;
|
||||
mod display;
|
||||
mod menu;
|
||||
pub mod menu;
|
||||
pub mod notifications;
|
||||
|
||||
pub fn fade_out(pane: &mut Pane, current_frame: u32, total_frames: u32) {
|
||||
if current_frame < total_frames {
|
||||
// Logarithmic fade out
|
||||
let alpha = ((255.0 / (total_frames as f32 + 1.0).log10())
|
||||
* (current_frame as f32 + 1.0).log10()) as u8;
|
||||
pane.alpha = alpha;
|
||||
pane.global_alpha = alpha;
|
||||
|
||||
// Linear fade out
|
||||
// let alpha = ((current_frame as f32 / 100.0) * 255.0) as u8;
|
||||
// pane.alpha = alpha;
|
||||
// pane.global_alpha = alpha;
|
||||
} else {
|
||||
pane.alpha = 0;
|
||||
pane.global_alpha = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#[skyline::hook(offset = 0x4b620)]
|
||||
pub unsafe fn handle_draw(layout: *mut Layout, draw_info: u64, cmd_buffer: u64) {
|
||||
let layout_name = skyline::from_c_str((*layout).layout_name);
|
||||
|
|
|
@ -83,7 +83,7 @@ pub struct TrainingModpackMenu {
|
|||
pub hitstun_playback: HitstunPlayback,
|
||||
pub playback_mash: OnOff,
|
||||
pub playback_loop: OnOff,
|
||||
pub menu_open: ButtonConfig,
|
||||
pub menu_open_start_press: OnOff,
|
||||
pub save_state_save: ButtonConfig,
|
||||
pub save_state_load: ButtonConfig,
|
||||
pub input_record: ButtonConfig,
|
||||
|
@ -139,7 +139,7 @@ pub static DEFAULTS_MENU: TrainingModpackMenu = TrainingModpackMenu {
|
|||
follow_up: Action::empty(),
|
||||
frame_advantage: OnOff::Off,
|
||||
full_hop: BoolFlag::TRUE,
|
||||
hitbox_vis: OnOff::On,
|
||||
hitbox_vis: OnOff::Off,
|
||||
hud: OnOff::On,
|
||||
input_delay: Delay::D0,
|
||||
ledge_delay: LongDelay::empty(),
|
||||
|
@ -188,7 +188,7 @@ pub static DEFAULTS_MENU: TrainingModpackMenu = TrainingModpackMenu {
|
|||
hitstun_playback: HitstunPlayback::Hitstun,
|
||||
playback_mash: OnOff::On,
|
||||
playback_loop: OnOff::Off,
|
||||
menu_open: ButtonConfig::B.union(ButtonConfig::DPAD_UP),
|
||||
menu_open_start_press: OnOff::On,
|
||||
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),
|
||||
|
@ -339,6 +339,48 @@ pub struct UiMenu {
|
|||
pub unsafe fn ui_menu(menu: TrainingModpackMenu) -> UiMenu {
|
||||
let mut overall_menu = UiMenu { tabs: Vec::new() };
|
||||
|
||||
let mut button_tab = Tab {
|
||||
tab_id: "button".to_string(),
|
||||
tab_title: "Button Config".to_string(),
|
||||
tab_submenus: Vec::new(),
|
||||
};
|
||||
button_tab.add_submenu_with_toggles::<OnOff>(
|
||||
"Menu Open Start Press".to_string(),
|
||||
"menu_open_start_press".to_string(),
|
||||
"Menu Open Start Press: Press start to open the mod menu. To open the original menu, hold start.\nThe default menu open option is always available as Hold B + Press DPad Up.".to_string(),
|
||||
true,
|
||||
&(menu.menu_open_start_press as u32),
|
||||
);
|
||||
button_tab.add_submenu_with_toggles::<ButtonConfig>(
|
||||
"Save State Save".to_string(),
|
||||
"save_state_save".to_string(),
|
||||
"Save State Save: Hold any one button and press the others to trigger".to_string(),
|
||||
false,
|
||||
&(menu.save_state_save.bits() as u32),
|
||||
);
|
||||
button_tab.add_submenu_with_toggles::<ButtonConfig>(
|
||||
"Save State Load".to_string(),
|
||||
"save_state_load".to_string(),
|
||||
"Save State Load: Hold any one button and press the others to trigger".to_string(),
|
||||
false,
|
||||
&(menu.save_state_load.bits() as u32),
|
||||
);
|
||||
button_tab.add_submenu_with_toggles::<ButtonConfig>(
|
||||
"Input Record".to_string(),
|
||||
"input_record".to_string(),
|
||||
"Input Record: Hold any one button and press the others to trigger".to_string(),
|
||||
false,
|
||||
&(menu.input_record.bits() as u32),
|
||||
);
|
||||
button_tab.add_submenu_with_toggles::<ButtonConfig>(
|
||||
"Input Playback".to_string(),
|
||||
"input_playback".to_string(),
|
||||
"Input Playback: Hold any one button and press the others to trigger".to_string(),
|
||||
false,
|
||||
&(menu.input_playback.bits() as u32),
|
||||
);
|
||||
overall_menu.tabs.push(button_tab);
|
||||
|
||||
let mut mash_tab = Tab {
|
||||
tab_id: "mash".to_string(),
|
||||
tab_title: "Mash Settings".to_string(),
|
||||
|
@ -851,48 +893,5 @@ pub unsafe fn ui_menu(menu: TrainingModpackMenu) -> UiMenu {
|
|||
);
|
||||
overall_menu.tabs.push(input_tab);
|
||||
|
||||
let mut button_tab = Tab {
|
||||
tab_id: "button".to_string(),
|
||||
tab_title: "Button Config".to_string(),
|
||||
tab_submenus: Vec::new(),
|
||||
};
|
||||
button_tab.add_submenu_with_toggles::<ButtonConfig>(
|
||||
"Menu Open".to_string(),
|
||||
"menu_open".to_string(),
|
||||
"Menu Open: Hold: Hold any one button and press the others to trigger".to_string(),
|
||||
false,
|
||||
&(menu.menu_open.bits() as u32),
|
||||
);
|
||||
button_tab.add_submenu_with_toggles::<ButtonConfig>(
|
||||
"Save State Save".to_string(),
|
||||
"save_state_save".to_string(),
|
||||
"Save State Save: Hold any one button and press the others to trigger".to_string(),
|
||||
false,
|
||||
&(menu.save_state_save.bits() as u32),
|
||||
);
|
||||
|
||||
button_tab.add_submenu_with_toggles::<ButtonConfig>(
|
||||
"Save State Load".to_string(),
|
||||
"save_state_load".to_string(),
|
||||
"Save State Load: Hold any one button and press the others to trigger".to_string(),
|
||||
false,
|
||||
&(menu.save_state_load.bits() as u32),
|
||||
);
|
||||
button_tab.add_submenu_with_toggles::<ButtonConfig>(
|
||||
"Input Record".to_string(),
|
||||
"input_record".to_string(),
|
||||
"Input Record: Hold any one button and press the others to trigger".to_string(),
|
||||
false,
|
||||
&(menu.input_record.bits() as u32),
|
||||
);
|
||||
button_tab.add_submenu_with_toggles::<ButtonConfig>(
|
||||
"Input Playback".to_string(),
|
||||
"input_playback".to_string(),
|
||||
"Input Playback: Hold any one button and press the others to trigger".to_string(),
|
||||
false,
|
||||
&(menu.input_playback.bits() as u32),
|
||||
);
|
||||
overall_menu.tabs.push(button_tab);
|
||||
|
||||
overall_menu
|
||||
}
|
||||
|
|
|
@ -48,6 +48,8 @@ fn test_set_airdodge() -> Result<(), Box<dyn Error>> {
|
|||
}
|
||||
|
||||
let (_terminal, mut app) = test_backend_setup(menu, menu_defaults)?;
|
||||
// Enter Mash Section
|
||||
app.next_tab();
|
||||
// Enter Mash Toggles
|
||||
app.on_a();
|
||||
// Set Mash Airdodge
|
||||
|
@ -103,6 +105,8 @@ fn test_save_and_reset_defaults() -> Result<(), Box<dyn Error>> {
|
|||
|
||||
let (_terminal, mut app) = test_backend_setup(menu, menu_defaults)?;
|
||||
|
||||
// Enter Mash Section
|
||||
app.next_tab();
|
||||
// Enter Mash Toggles
|
||||
app.on_a();
|
||||
// Set Mash Airdodge
|
||||
|
@ -146,6 +150,8 @@ fn test_save_and_reset_defaults() -> Result<(), Box<dyn Error>> {
|
|||
"The menu should have Mash Airdodge"
|
||||
);
|
||||
|
||||
// Enter Mash Section
|
||||
app.next_tab();
|
||||
// Enter Mash Toggles
|
||||
app.on_a();
|
||||
// Unset Mash Airdodge
|
||||
|
@ -216,6 +222,8 @@ fn test_toggle_naming() -> Result<(), Box<dyn Error>> {
|
|||
}
|
||||
|
||||
let (mut terminal, mut app) = test_backend_setup(menu, menu_defaults)?;
|
||||
// Enter Mash Section
|
||||
app.next_tab();
|
||||
// Enter Mash Toggles
|
||||
app.on_a();
|
||||
// Set Mash Airdodge
|
||||
|
|
Loading…
Reference in a new issue