mirror of
https://github.com/jugeeya/UltimateTrainingModpack.git
synced 2025-03-22 22:36:10 +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"
|
$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"
|
$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'
|
$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::common::*;
|
||||||
use crate::input::{ControllerStyle::*, *};
|
use crate::input::{ControllerStyle::*, *};
|
||||||
|
use crate::training::frame_counter;
|
||||||
|
use crate::training::ui::menu::VANILLA_MENU_ACTIVE;
|
||||||
|
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use strum::IntoEnumIterator;
|
use strum::IntoEnumIterator;
|
||||||
use strum_macros::EnumIter;
|
use strum_macros::EnumIter;
|
||||||
|
|
||||||
|
use super::menu::QUICK_MENU_ACTIVE;
|
||||||
|
|
||||||
pub fn button_mapping(
|
pub fn button_mapping(
|
||||||
button_config: ButtonConfig,
|
button_config: ButtonConfig,
|
||||||
style: ControllerStyle,
|
style: ControllerStyle,
|
||||||
|
@ -55,9 +59,12 @@ pub enum ButtonCombo {
|
||||||
InputPlayback,
|
InputPlayback,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub const DEFAULT_OPEN_MENU_CONFIG: ButtonConfig = ButtonConfig::B.union(ButtonConfig::DPAD_UP);
|
||||||
|
|
||||||
unsafe fn get_combo_keys(combo: ButtonCombo) -> ButtonConfig {
|
unsafe fn get_combo_keys(combo: ButtonCombo) -> ButtonConfig {
|
||||||
match combo {
|
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::SaveState => MENU.save_state_save,
|
||||||
ButtonCombo::LoadState => MENU.save_state_load,
|
ButtonCombo::LoadState => MENU.save_state_load,
|
||||||
ButtonCombo::InputRecord => MENU.input_record,
|
ButtonCombo::InputRecord => MENU.input_record,
|
||||||
|
@ -74,6 +81,7 @@ lazy_static! {
|
||||||
(ButtonCombo::InputRecord, false),
|
(ButtonCombo::InputRecord, false),
|
||||||
(ButtonCombo::InputPlayback, false),
|
(ButtonCombo::InputPlayback, false),
|
||||||
]));
|
]));
|
||||||
|
static ref START_HOLD_FRAMES: Mutex<u32> = Mutex::new(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn combo_passes(p1_controller: Controller, combo: ButtonCombo) -> bool {
|
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 {
|
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();
|
let button_combo_requests = &mut *BUTTON_COMBO_REQUESTS.lock();
|
||||||
button_combo_requests
|
button_combo_requests
|
||||||
.iter_mut()
|
.iter_mut()
|
||||||
.for_each(|(combo, is_request)| {
|
.for_each(|(combo, is_request)| {
|
||||||
if !*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
|
// Define struct used for final controller inputs
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct MappedInputs {
|
pub struct MappedInputs {
|
||||||
pub buttons: Buttons,
|
pub buttons: Buttons,
|
||||||
|
|
|
@ -13,13 +13,18 @@ use crate::consts::MENU_OPTIONS_PATH;
|
||||||
use crate::events::{Event, EVENT_QUEUE};
|
use crate::events::{Event, EVENT_QUEUE};
|
||||||
use crate::input::*;
|
use crate::input::*;
|
||||||
use crate::logging::*;
|
use crate::logging::*;
|
||||||
|
use crate::training::frame_counter;
|
||||||
|
|
||||||
// This is a special frame counter that will tick on draw()
|
pub static mut FRAME_COUNTER_INDEX: usize = 0;
|
||||||
// We'll count how long the menu has been open
|
pub const MENU_CLOSE_WAIT_FRAMES: u32 = 15;
|
||||||
pub static mut FRAME_COUNTER: u32 = 0;
|
|
||||||
const MENU_CLOSE_WAIT_FRAMES: u32 = 60;
|
|
||||||
pub static mut QUICK_MENU_ACTIVE: bool = false;
|
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 {
|
pub unsafe fn menu_condition() -> bool {
|
||||||
button_config::combo_passes_exclusive(button_config::ButtonCombo::OpenMenu)
|
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() {
|
pub fn spawn_menu() {
|
||||||
unsafe {
|
unsafe {
|
||||||
FRAME_COUNTER = 0;
|
|
||||||
QUICK_MENU_ACTIVE = true;
|
QUICK_MENU_ACTIVE = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Eq, PartialEq, Hash, Copy, Clone)]
|
#[derive(Eq, PartialEq, Hash, Copy, Clone)]
|
||||||
enum DirectionButton {
|
enum DirectionButton {
|
||||||
DpadLeft,
|
|
||||||
LLeft,
|
LLeft,
|
||||||
RLeft,
|
RLeft,
|
||||||
DpadDown,
|
|
||||||
LDown,
|
LDown,
|
||||||
RDown,
|
RDown,
|
||||||
DpadRight,
|
|
||||||
LRight,
|
LRight,
|
||||||
RRight,
|
RRight,
|
||||||
DpadUp,
|
|
||||||
LUp,
|
LUp,
|
||||||
RUp,
|
RUp,
|
||||||
}
|
}
|
||||||
|
@ -107,16 +107,12 @@ lazy_static! {
|
||||||
static ref DIRECTION_HOLD_FRAMES: Mutex<HashMap<DirectionButton, u32>> = {
|
static ref DIRECTION_HOLD_FRAMES: Mutex<HashMap<DirectionButton, u32>> = {
|
||||||
use DirectionButton::*;
|
use DirectionButton::*;
|
||||||
Mutex::new(HashMap::from([
|
Mutex::new(HashMap::from([
|
||||||
(DpadLeft, 0),
|
|
||||||
(LLeft, 0),
|
(LLeft, 0),
|
||||||
(RLeft, 0),
|
(RLeft, 0),
|
||||||
(DpadDown, 0),
|
|
||||||
(LDown, 0),
|
(LDown, 0),
|
||||||
(RDown, 0),
|
(RDown, 0),
|
||||||
(DpadRight, 0),
|
|
||||||
(LRight, 0),
|
(LRight, 0),
|
||||||
(RRight, 0),
|
(RRight, 0),
|
||||||
(DpadUp, 0),
|
|
||||||
(LUp, 0),
|
(LUp, 0),
|
||||||
(RUp, 0),
|
(RUp, 0),
|
||||||
]))
|
]))
|
||||||
|
@ -125,13 +121,28 @@ lazy_static! {
|
||||||
|
|
||||||
pub fn handle_final_input_mapping(
|
pub fn handle_final_input_mapping(
|
||||||
player_idx: i32,
|
player_idx: i32,
|
||||||
controller_struct: &SomeControllerStruct,
|
controller_struct: &mut SomeControllerStruct,
|
||||||
out: *mut MappedInputs,
|
out: *mut MappedInputs,
|
||||||
) {
|
) {
|
||||||
unsafe {
|
unsafe {
|
||||||
if player_idx == 0 {
|
if player_idx == 0 {
|
||||||
let p1_controller = *controller_struct.controller;
|
let p1_controller = &mut *controller_struct.controller;
|
||||||
*P1_CONTROLLER_STYLE.lock() = p1_controller.style;
|
*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 QUICK_MENU_ACTIVE {
|
||||||
// If we're here, remove all other presses
|
// If we're here, remove all other presses
|
||||||
*out = MappedInputs::empty();
|
*out = MappedInputs::empty();
|
||||||
|
@ -161,16 +172,12 @@ pub fn handle_final_input_mapping(
|
||||||
.iter_mut()
|
.iter_mut()
|
||||||
.for_each(|(direction, frames)| {
|
.for_each(|(direction, frames)| {
|
||||||
let still_held = match direction {
|
let still_held = match direction {
|
||||||
DpadLeft => button_current_held.dpad_left(),
|
|
||||||
LLeft => button_current_held.l_left(),
|
LLeft => button_current_held.l_left(),
|
||||||
RLeft => button_current_held.r_left(),
|
RLeft => button_current_held.r_left(),
|
||||||
DpadDown => button_current_held.dpad_down(),
|
|
||||||
LDown => button_current_held.l_down(),
|
LDown => button_current_held.l_down(),
|
||||||
RDown => button_current_held.r_down(),
|
RDown => button_current_held.r_down(),
|
||||||
DpadRight => button_current_held.dpad_right(),
|
|
||||||
LRight => button_current_held.l_right(),
|
LRight => button_current_held.l_right(),
|
||||||
RRight => button_current_held.r_right(),
|
RRight => button_current_held.r_right(),
|
||||||
DpadUp => button_current_held.dpad_up(),
|
|
||||||
LUp => button_current_held.l_up(),
|
LUp => button_current_held.l_up(),
|
||||||
RUp => button_current_held.r_up(),
|
RUp => button_current_held.r_up(),
|
||||||
};
|
};
|
||||||
|
@ -190,15 +197,24 @@ pub fn handle_final_input_mapping(
|
||||||
received_input = true;
|
received_input = true;
|
||||||
if app.page != AppPage::SUBMENU {
|
if app.page != AppPage::SUBMENU {
|
||||||
app.on_b()
|
app.on_b()
|
||||||
} else if FRAME_COUNTER > MENU_CLOSE_WAIT_FRAMES {
|
} else {
|
||||||
// Leave menu.
|
// Leave menu.
|
||||||
|
frame_counter::start_counting(FRAME_COUNTER_INDEX);
|
||||||
QUICK_MENU_ACTIVE = false;
|
QUICK_MENU_ACTIVE = false;
|
||||||
FRAME_COUNTER = 0;
|
|
||||||
let menu_json = app.get_menu_selections();
|
let menu_json = app.get_menu_selections();
|
||||||
set_menu_from_json(&menu_json);
|
set_menu_from_json(&menu_json);
|
||||||
EVENT_QUEUE.push(Event::menu_open(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(|| {
|
button_mapping(ButtonConfig::X, style, button_presses).then(|| {
|
||||||
app.save_defaults();
|
app.save_defaults();
|
||||||
received_input = true;
|
received_input = true;
|
||||||
|
@ -227,7 +243,7 @@ pub fn handle_final_input_mapping(
|
||||||
(button_presses.dpad_left()
|
(button_presses.dpad_left()
|
||||||
|| button_presses.l_left()
|
|| button_presses.l_left()
|
||||||
|| button_presses.r_left()
|
|| button_presses.r_left()
|
||||||
|| [DpadLeft, LLeft, RLeft].iter().any(hold_condition))
|
|| [LLeft, RLeft].iter().any(hold_condition))
|
||||||
.then(|| {
|
.then(|| {
|
||||||
received_input = true;
|
received_input = true;
|
||||||
app.on_left();
|
app.on_left();
|
||||||
|
@ -235,7 +251,7 @@ pub fn handle_final_input_mapping(
|
||||||
(button_presses.dpad_right()
|
(button_presses.dpad_right()
|
||||||
|| button_presses.l_right()
|
|| button_presses.l_right()
|
||||||
|| button_presses.r_right()
|
|| button_presses.r_right()
|
||||||
|| [DpadRight, LRight, RRight].iter().any(hold_condition))
|
|| [LRight, RRight].iter().any(hold_condition))
|
||||||
.then(|| {
|
.then(|| {
|
||||||
received_input = true;
|
received_input = true;
|
||||||
app.on_right();
|
app.on_right();
|
||||||
|
@ -243,7 +259,7 @@ pub fn handle_final_input_mapping(
|
||||||
(button_presses.dpad_up()
|
(button_presses.dpad_up()
|
||||||
|| button_presses.l_up()
|
|| button_presses.l_up()
|
||||||
|| button_presses.r_up()
|
|| button_presses.r_up()
|
||||||
|| [DpadUp, LUp, RUp].iter().any(hold_condition))
|
|| [LUp, RUp].iter().any(hold_condition))
|
||||||
.then(|| {
|
.then(|| {
|
||||||
received_input = true;
|
received_input = true;
|
||||||
app.on_up();
|
app.on_up();
|
||||||
|
@ -251,7 +267,7 @@ pub fn handle_final_input_mapping(
|
||||||
(button_presses.dpad_down()
|
(button_presses.dpad_down()
|
||||||
|| button_presses.l_down()
|
|| button_presses.l_down()
|
||||||
|| button_presses.r_down()
|
|| button_presses.r_down()
|
||||||
|| [DpadDown, LDown, RDown].iter().any(hold_condition))
|
|| [LDown, RDown].iter().any(hold_condition))
|
||||||
.then(|| {
|
.then(|| {
|
||||||
received_input = true;
|
received_input = true;
|
||||||
app.on_down();
|
app.on_down();
|
||||||
|
|
13
src/lib.rs
13
src/lib.rs
|
@ -18,8 +18,9 @@ use std::fs;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use skyline::nro::{self, NroInfo};
|
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::events::events_loop;
|
||||||
use crate::common::*;
|
use crate::common::*;
|
||||||
use crate::consts::TRAINING_MODPACK_ROOT;
|
use crate::consts::TRAINING_MODPACK_ROOT;
|
||||||
|
@ -117,7 +118,15 @@ pub fn main() {
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
notification("Training Modpack".to_string(), "Welcome!".to_string(), 60);
|
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(
|
notification(
|
||||||
"Save State".to_string(),
|
"Save State".to_string(),
|
||||||
MENU.save_state_save.to_string(),
|
MENU.save_state_save.to_string(),
|
||||||
|
|
|
@ -1,17 +1,27 @@
|
||||||
static mut SHOULD_COUNT: Vec<bool> = vec![];
|
static mut SHOULD_COUNT: Vec<bool> = vec![];
|
||||||
|
static mut NO_RESET: Vec<bool> = vec![];
|
||||||
static mut COUNTERS: Vec<u32> = vec![];
|
static mut COUNTERS: Vec<u32> = vec![];
|
||||||
|
|
||||||
pub fn register_counter() -> usize {
|
fn _register_counter(no_reset: bool) -> usize {
|
||||||
unsafe {
|
unsafe {
|
||||||
let index = COUNTERS.len();
|
let index = COUNTERS.len();
|
||||||
|
|
||||||
COUNTERS.push(0);
|
COUNTERS.push(0);
|
||||||
SHOULD_COUNT.push(false);
|
SHOULD_COUNT.push(false);
|
||||||
|
NO_RESET.push(no_reset);
|
||||||
|
|
||||||
index
|
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) {
|
pub fn start_counting(index: usize) {
|
||||||
unsafe {
|
unsafe {
|
||||||
SHOULD_COUNT[index] = true;
|
SHOULD_COUNT[index] = true;
|
||||||
|
@ -81,6 +91,9 @@ pub fn tick() {
|
||||||
pub fn reset_all() {
|
pub fn reset_all() {
|
||||||
unsafe {
|
unsafe {
|
||||||
for (index, _frame) in COUNTERS.iter().enumerate() {
|
for (index, _frame) in COUNTERS.iter().enumerate() {
|
||||||
|
if NO_RESET[index] {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
full_reset(index);
|
full_reset(index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -701,8 +701,8 @@ unsafe fn handle_final_input_mapping(
|
||||||
if !is_training_mode() {
|
if !is_training_mode() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
button_config::handle_final_input_mapping(player_idx, controller_struct);
|
|
||||||
menu::handle_final_input_mapping(player_idx, controller_struct, out);
|
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);
|
dev_config::handle_final_input_mapping(player_idx, controller_struct);
|
||||||
input_delay::handle_final_input_mapping(player_idx, out);
|
input_delay::handle_final_input_mapping(player_idx, out);
|
||||||
input_record::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();
|
tech::init();
|
||||||
input_record::init();
|
input_record::init();
|
||||||
ui::init();
|
ui::init();
|
||||||
|
menu::init();
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,8 +6,12 @@ use smash::ui2d::{SmashPane, SmashTextBox};
|
||||||
use training_mod_tui::gauge::GaugeState;
|
use training_mod_tui::gauge::GaugeState;
|
||||||
use training_mod_tui::{App, AppPage, NUM_LISTS};
|
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 crate::{common, common::menu::QUICK_MENU_ACTIVE, input::*};
|
||||||
|
|
||||||
|
use super::fade_out;
|
||||||
|
|
||||||
pub static NUM_MENU_TEXT_OPTIONS: usize = 32;
|
pub static NUM_MENU_TEXT_OPTIONS: usize = 32;
|
||||||
pub static _NUM_MENU_TABS: usize = 3;
|
pub static _NUM_MENU_TABS: usize = 3;
|
||||||
|
|
||||||
|
@ -53,6 +57,8 @@ const BG_LEFT_SELECTED_WHITE_COLOR: ResColor = ResColor {
|
||||||
a: 255,
|
a: 255,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub static mut VANILLA_MENU_ACTIVE: bool = false;
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
static ref GCC_BUTTON_MAPPING: HashMap<&'static str, u16> = HashMap::from([
|
static ref GCC_BUTTON_MAPPING: HashMap<&'static str, u16> = HashMap::from([
|
||||||
("L", 0xE204),
|
("L", 0xE204),
|
||||||
|
@ -346,6 +352,15 @@ unsafe fn render_slider_page(app: &App, root_pane: &Pane) {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn draw(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
|
// Update menu display
|
||||||
// Grabbing lock as read-only, essentially
|
// Grabbing lock as read-only, essentially
|
||||||
let app = &*crate::common::menu::QUICK_MENU_APP.data_ptr();
|
let app = &*crate::common::menu::QUICK_MENU_APP.data_ptr();
|
||||||
|
@ -357,12 +372,21 @@ pub unsafe fn draw(root_pane: &Pane) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
root_pane
|
let overall_parent_pane = root_pane.find_pane_by_name_recursive("TrModMenu").unwrap();
|
||||||
.find_pane_by_name_recursive("TrModMenu")
|
overall_parent_pane.set_visible(true);
|
||||||
.unwrap()
|
let menu_close_wait_frame = frame_counter::get_frame_count(menu::FRAME_COUNTER_INDEX);
|
||||||
.set_visible(QUICK_MENU_ACTIVE);
|
|
||||||
if QUICK_MENU_ACTIVE {
|
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
|
// Make all invisible first
|
||||||
|
|
|
@ -10,9 +10,27 @@ use crate::consts::LAYOUT_ARC_PATH;
|
||||||
|
|
||||||
mod damage;
|
mod damage;
|
||||||
mod display;
|
mod display;
|
||||||
mod menu;
|
pub mod menu;
|
||||||
pub mod notifications;
|
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)]
|
#[skyline::hook(offset = 0x4b620)]
|
||||||
pub unsafe fn handle_draw(layout: *mut Layout, draw_info: u64, cmd_buffer: u64) {
|
pub unsafe fn handle_draw(layout: *mut Layout, draw_info: u64, cmd_buffer: u64) {
|
||||||
let layout_name = skyline::from_c_str((*layout).layout_name);
|
let layout_name = skyline::from_c_str((*layout).layout_name);
|
||||||
|
|
|
@ -83,7 +83,7 @@ pub struct TrainingModpackMenu {
|
||||||
pub hitstun_playback: HitstunPlayback,
|
pub hitstun_playback: HitstunPlayback,
|
||||||
pub playback_mash: OnOff,
|
pub playback_mash: OnOff,
|
||||||
pub playback_loop: OnOff,
|
pub playback_loop: OnOff,
|
||||||
pub menu_open: ButtonConfig,
|
pub menu_open_start_press: OnOff,
|
||||||
pub save_state_save: ButtonConfig,
|
pub save_state_save: ButtonConfig,
|
||||||
pub save_state_load: ButtonConfig,
|
pub save_state_load: ButtonConfig,
|
||||||
pub input_record: ButtonConfig,
|
pub input_record: ButtonConfig,
|
||||||
|
@ -139,7 +139,7 @@ pub static DEFAULTS_MENU: TrainingModpackMenu = TrainingModpackMenu {
|
||||||
follow_up: Action::empty(),
|
follow_up: Action::empty(),
|
||||||
frame_advantage: OnOff::Off,
|
frame_advantage: OnOff::Off,
|
||||||
full_hop: BoolFlag::TRUE,
|
full_hop: BoolFlag::TRUE,
|
||||||
hitbox_vis: OnOff::On,
|
hitbox_vis: OnOff::Off,
|
||||||
hud: OnOff::On,
|
hud: OnOff::On,
|
||||||
input_delay: Delay::D0,
|
input_delay: Delay::D0,
|
||||||
ledge_delay: LongDelay::empty(),
|
ledge_delay: LongDelay::empty(),
|
||||||
|
@ -188,7 +188,7 @@ pub static DEFAULTS_MENU: TrainingModpackMenu = TrainingModpackMenu {
|
||||||
hitstun_playback: HitstunPlayback::Hitstun,
|
hitstun_playback: HitstunPlayback::Hitstun,
|
||||||
playback_mash: OnOff::On,
|
playback_mash: OnOff::On,
|
||||||
playback_loop: OnOff::Off,
|
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_save: ButtonConfig::ZL.union(ButtonConfig::DPAD_DOWN),
|
||||||
save_state_load: ButtonConfig::ZL.union(ButtonConfig::DPAD_UP),
|
save_state_load: ButtonConfig::ZL.union(ButtonConfig::DPAD_UP),
|
||||||
input_record: ButtonConfig::ZR.union(ButtonConfig::DPAD_DOWN),
|
input_record: ButtonConfig::ZR.union(ButtonConfig::DPAD_DOWN),
|
||||||
|
@ -339,6 +339,48 @@ pub struct UiMenu {
|
||||||
pub unsafe fn ui_menu(menu: TrainingModpackMenu) -> UiMenu {
|
pub unsafe fn ui_menu(menu: TrainingModpackMenu) -> UiMenu {
|
||||||
let mut overall_menu = UiMenu { tabs: Vec::new() };
|
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 {
|
let mut mash_tab = Tab {
|
||||||
tab_id: "mash".to_string(),
|
tab_id: "mash".to_string(),
|
||||||
tab_title: "Mash Settings".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);
|
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
|
overall_menu
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,6 +48,8 @@ fn test_set_airdodge() -> Result<(), Box<dyn Error>> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let (_terminal, mut app) = test_backend_setup(menu, menu_defaults)?;
|
let (_terminal, mut app) = test_backend_setup(menu, menu_defaults)?;
|
||||||
|
// Enter Mash Section
|
||||||
|
app.next_tab();
|
||||||
// Enter Mash Toggles
|
// Enter Mash Toggles
|
||||||
app.on_a();
|
app.on_a();
|
||||||
// Set Mash Airdodge
|
// 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)?;
|
let (_terminal, mut app) = test_backend_setup(menu, menu_defaults)?;
|
||||||
|
|
||||||
|
// Enter Mash Section
|
||||||
|
app.next_tab();
|
||||||
// Enter Mash Toggles
|
// Enter Mash Toggles
|
||||||
app.on_a();
|
app.on_a();
|
||||||
// Set Mash Airdodge
|
// Set Mash Airdodge
|
||||||
|
@ -146,6 +150,8 @@ fn test_save_and_reset_defaults() -> Result<(), Box<dyn Error>> {
|
||||||
"The menu should have Mash Airdodge"
|
"The menu should have Mash Airdodge"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Enter Mash Section
|
||||||
|
app.next_tab();
|
||||||
// Enter Mash Toggles
|
// Enter Mash Toggles
|
||||||
app.on_a();
|
app.on_a();
|
||||||
// Unset Mash Airdodge
|
// 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)?;
|
let (mut terminal, mut app) = test_backend_setup(menu, menu_defaults)?;
|
||||||
|
// Enter Mash Section
|
||||||
|
app.next_tab();
|
||||||
// Enter Mash Toggles
|
// Enter Mash Toggles
|
||||||
app.on_a();
|
app.on_a();
|
||||||
// Set Mash Airdodge
|
// Set Mash Airdodge
|
||||||
|
|
Loading…
Add table
Reference in a new issue