mirror of
https://github.com/jugeeya/UltimateTrainingModpack.git
synced 2025-03-14 02:16:10 +00:00
Fix menu buttons for Gamecube Controller users (#481)
* Initial * Move filepaths * Small fix * Notification on save state save * Fix buttons for GCC
This commit is contained in:
parent
e981a0bfd0
commit
b20a44ca5c
1 changed files with 206 additions and 99 deletions
|
@ -1,8 +1,11 @@
|
|||
use lazy_static::lazy_static;
|
||||
use skyline::nn::hid::GetNpadStyleSet;
|
||||
use skyline::nn::ui2d::*;
|
||||
use smash::ui2d::{SmashPane, SmashTextBox};
|
||||
use std::collections::HashMap;
|
||||
|
||||
use training_mod_tui::{App, AppPage};
|
||||
use training_mod_tui::gauge::GaugeState;
|
||||
use training_mod_tui::{App, AppPage};
|
||||
|
||||
use crate::{common, common::menu::QUICK_MENU_ACTIVE};
|
||||
|
||||
|
@ -51,6 +54,17 @@ const BG_LEFT_SELECTED_WHITE_COLOR: ResColor = ResColor {
|
|||
a: 255,
|
||||
};
|
||||
|
||||
lazy_static! {
|
||||
static ref GCC_BUTTON_MAPPING: HashMap<&'static str, u16> =
|
||||
HashMap::from([("L", 0xE204), ("R", 0xE205), ("X", 0xE206), ("Z", 0xE208)]);
|
||||
static ref PROCON_BUTTON_MAPPING: HashMap<&'static str, u16> = HashMap::from([
|
||||
("L", 0xE0E4),
|
||||
("R", 0xE0E5),
|
||||
("X", 0xE0E2),
|
||||
("ZL", 0xE0E6),
|
||||
("ZR", 0xE0E7)
|
||||
]);
|
||||
}
|
||||
|
||||
unsafe fn render_submenu_page(app: &App, root_pane: &mut Pane) {
|
||||
let tab_selected = app.tab_selected();
|
||||
|
@ -60,18 +74,22 @@ unsafe fn render_submenu_page(app: &App, root_pane: &mut Pane) {
|
|||
// Valid options in this submenu
|
||||
.filter_map(|idx| tab.idx_to_list_idx_opt(idx))
|
||||
.for_each(|(list_section, list_idx)| {
|
||||
let menu_button_row = root_pane.find_pane_by_name_recursive(
|
||||
format!("TrModMenuButtonRow{list_idx}").as_str()
|
||||
).unwrap();
|
||||
let menu_button_row = root_pane
|
||||
.find_pane_by_name_recursive(format!("TrModMenuButtonRow{list_idx}").as_str())
|
||||
.unwrap();
|
||||
menu_button_row.set_visible(true);
|
||||
let menu_button = menu_button_row.find_pane_by_name_recursive(
|
||||
format!("Button{list_section}").as_str()
|
||||
).unwrap();
|
||||
let menu_button = menu_button_row
|
||||
.find_pane_by_name_recursive(format!("Button{list_section}").as_str())
|
||||
.unwrap();
|
||||
menu_button.set_visible(true);
|
||||
let title_text = menu_button.find_pane_by_name_recursive("TitleTxt")
|
||||
.unwrap().as_textbox();
|
||||
let title_bg = menu_button.find_pane_by_name_recursive("TitleBg")
|
||||
.unwrap().as_picture();
|
||||
let title_text = menu_button
|
||||
.find_pane_by_name_recursive("TitleTxt")
|
||||
.unwrap()
|
||||
.as_textbox();
|
||||
let title_bg = menu_button
|
||||
.find_pane_by_name_recursive("TitleBg")
|
||||
.unwrap()
|
||||
.as_picture();
|
||||
|
||||
let list = &tab.lists[list_section];
|
||||
let submenu = &list.items[list_idx];
|
||||
|
@ -79,8 +97,11 @@ unsafe fn render_submenu_page(app: &App, root_pane: &mut Pane) {
|
|||
title_text.set_text_string(submenu.submenu_title);
|
||||
let title_bg_material = &mut *title_bg.material;
|
||||
if is_selected {
|
||||
root_pane.find_pane_by_name_recursive("FooterTxt")
|
||||
.unwrap().as_textbox().set_text_string(submenu.help_text);
|
||||
root_pane
|
||||
.find_pane_by_name_recursive("FooterTxt")
|
||||
.unwrap()
|
||||
.as_textbox()
|
||||
.set_text_string(submenu.help_text);
|
||||
title_bg_material.set_white_res_color(BG_LEFT_ON_WHITE_COLOR);
|
||||
title_bg_material.set_black_res_color(BG_LEFT_ON_BLACK_COLOR);
|
||||
title_text.text_shadow_enable(true);
|
||||
|
@ -105,23 +126,32 @@ unsafe fn render_toggle_page(app: &App, root_pane: &mut Pane) {
|
|||
.iter()
|
||||
.enumerate()
|
||||
.for_each(|(list_idx, (checked, name))| {
|
||||
let menu_button_row = root_pane.find_pane_by_name_recursive(
|
||||
format!("TrModMenuButtonRow{list_idx}").as_str()
|
||||
).unwrap();
|
||||
let menu_button_row = root_pane
|
||||
.find_pane_by_name_recursive(format!("TrModMenuButtonRow{list_idx}").as_str())
|
||||
.unwrap();
|
||||
menu_button_row.set_visible(true);
|
||||
let menu_button = menu_button_row.find_pane_by_name_recursive(
|
||||
format!("Button{list_section}").as_str()
|
||||
).unwrap();
|
||||
let menu_button = menu_button_row
|
||||
.find_pane_by_name_recursive(format!("Button{list_section}").as_str())
|
||||
.unwrap();
|
||||
menu_button.set_visible(true);
|
||||
|
||||
let title_text = menu_button.find_pane_by_name_recursive("TitleTxt")
|
||||
.unwrap().as_textbox();
|
||||
let title_bg = menu_button.find_pane_by_name_recursive("TitleBg")
|
||||
.unwrap().as_picture();
|
||||
let value_text = menu_button.find_pane_by_name_recursive("ValueTxt")
|
||||
.unwrap().as_textbox();
|
||||
let title_text = menu_button
|
||||
.find_pane_by_name_recursive("TitleTxt")
|
||||
.unwrap()
|
||||
.as_textbox();
|
||||
let title_bg = menu_button
|
||||
.find_pane_by_name_recursive("TitleBg")
|
||||
.unwrap()
|
||||
.as_picture();
|
||||
let value_text = menu_button
|
||||
.find_pane_by_name_recursive("ValueTxt")
|
||||
.unwrap()
|
||||
.as_textbox();
|
||||
|
||||
let is_selected = sub_menu_state.selected().filter(|s| *s == list_idx).is_some();
|
||||
let is_selected = sub_menu_state
|
||||
.selected()
|
||||
.filter(|s| *s == list_idx)
|
||||
.is_some();
|
||||
title_text.set_text_string(name);
|
||||
if is_selected {
|
||||
title_text.text_shadow_enable(true);
|
||||
|
@ -155,30 +185,52 @@ unsafe fn render_slider_page(app: &App, root_pane: &mut Pane) {
|
|||
let selected_min = gauge_vals.selected_min;
|
||||
let selected_max = gauge_vals.selected_max;
|
||||
|
||||
let slider_pane = root_pane.find_pane_by_name_recursive("TrModSlider").unwrap();
|
||||
let slider_pane = root_pane
|
||||
.find_pane_by_name_recursive("TrModSlider")
|
||||
.unwrap();
|
||||
slider_pane.set_visible(true);
|
||||
|
||||
let _background = slider_pane.find_pane_by_name_recursive("Background")
|
||||
.unwrap().as_picture();
|
||||
let header = slider_pane.find_pane_by_name_recursive("Header")
|
||||
.unwrap().as_textbox();
|
||||
let _background = slider_pane
|
||||
.find_pane_by_name_recursive("Background")
|
||||
.unwrap()
|
||||
.as_picture();
|
||||
let header = slider_pane
|
||||
.find_pane_by_name_recursive("Header")
|
||||
.unwrap()
|
||||
.as_textbox();
|
||||
header.set_text_string(title);
|
||||
let min_button = slider_pane.find_pane_by_name_recursive("MinButton")
|
||||
.unwrap().as_picture();
|
||||
let max_button = slider_pane.find_pane_by_name_recursive("MaxButton")
|
||||
.unwrap().as_picture();
|
||||
let min_title_text = min_button.find_pane_by_name_recursive("TitleTxt")
|
||||
.unwrap().as_textbox();
|
||||
let min_title_bg = min_button.find_pane_by_name_recursive("TitleBg")
|
||||
.unwrap().as_picture();
|
||||
let min_value_text = min_button.find_pane_by_name_recursive("ValueTxt")
|
||||
.unwrap().as_textbox();
|
||||
let max_title_text = max_button.find_pane_by_name_recursive("TitleTxt")
|
||||
.unwrap().as_textbox();
|
||||
let max_title_bg = max_button.find_pane_by_name_recursive("TitleBg")
|
||||
.unwrap().as_picture();
|
||||
let max_value_text = max_button.find_pane_by_name_recursive("ValueTxt")
|
||||
.unwrap().as_textbox();
|
||||
let min_button = slider_pane
|
||||
.find_pane_by_name_recursive("MinButton")
|
||||
.unwrap()
|
||||
.as_picture();
|
||||
let max_button = slider_pane
|
||||
.find_pane_by_name_recursive("MaxButton")
|
||||
.unwrap()
|
||||
.as_picture();
|
||||
let min_title_text = min_button
|
||||
.find_pane_by_name_recursive("TitleTxt")
|
||||
.unwrap()
|
||||
.as_textbox();
|
||||
let min_title_bg = min_button
|
||||
.find_pane_by_name_recursive("TitleBg")
|
||||
.unwrap()
|
||||
.as_picture();
|
||||
let min_value_text = min_button
|
||||
.find_pane_by_name_recursive("ValueTxt")
|
||||
.unwrap()
|
||||
.as_textbox();
|
||||
let max_title_text = max_button
|
||||
.find_pane_by_name_recursive("TitleTxt")
|
||||
.unwrap()
|
||||
.as_textbox();
|
||||
let max_title_bg = max_button
|
||||
.find_pane_by_name_recursive("TitleBg")
|
||||
.unwrap()
|
||||
.as_picture();
|
||||
let max_value_text = max_button
|
||||
.find_pane_by_name_recursive("ValueTxt")
|
||||
.unwrap()
|
||||
.as_textbox();
|
||||
|
||||
min_title_text.set_text_string("Min");
|
||||
match gauge_vals.state {
|
||||
|
@ -215,7 +267,7 @@ unsafe fn render_slider_page(app: &App, root_pane: &mut Pane) {
|
|||
let min_colors = match gauge_vals.state {
|
||||
GaugeState::MinHover => (BG_LEFT_ON_WHITE_COLOR, BG_LEFT_ON_BLACK_COLOR),
|
||||
GaugeState::MinSelected => (BG_LEFT_SELECTED_WHITE_COLOR, BG_LEFT_SELECTED_BLACK_COLOR),
|
||||
_ => (BG_LEFT_OFF_WHITE_COLOR, BG_LEFT_OFF_BLACK_COLOR)
|
||||
_ => (BG_LEFT_OFF_WHITE_COLOR, BG_LEFT_OFF_BLACK_COLOR),
|
||||
};
|
||||
|
||||
min_title_bg_material.set_white_res_color(min_colors.0);
|
||||
|
@ -225,7 +277,7 @@ unsafe fn render_slider_page(app: &App, root_pane: &mut Pane) {
|
|||
let max_colors = match gauge_vals.state {
|
||||
GaugeState::MaxHover => (BG_LEFT_ON_WHITE_COLOR, BG_LEFT_ON_BLACK_COLOR),
|
||||
GaugeState::MaxSelected => (BG_LEFT_SELECTED_WHITE_COLOR, BG_LEFT_SELECTED_BLACK_COLOR),
|
||||
_ => (BG_LEFT_OFF_WHITE_COLOR, BG_LEFT_OFF_BLACK_COLOR)
|
||||
_ => (BG_LEFT_OFF_WHITE_COLOR, BG_LEFT_OFF_BLACK_COLOR),
|
||||
};
|
||||
|
||||
max_title_bg_material.set_white_res_color(max_colors.0);
|
||||
|
@ -257,7 +309,10 @@ pub unsafe fn draw(root_pane: &mut Pane) {
|
|||
}
|
||||
}
|
||||
|
||||
root_pane.find_pane_by_name_recursive("TrModMenu").unwrap().set_visible(QUICK_MENU_ACTIVE);
|
||||
root_pane
|
||||
.find_pane_by_name_recursive("TrModMenu")
|
||||
.unwrap()
|
||||
.set_visible(QUICK_MENU_ACTIVE);
|
||||
if QUICK_MENU_ACTIVE {
|
||||
common::menu::FRAME_COUNTER += 1;
|
||||
}
|
||||
|
@ -267,19 +322,25 @@ pub unsafe fn draw(root_pane: &mut Pane) {
|
|||
let col_idx = idx % 3;
|
||||
let row_idx = idx / 3;
|
||||
|
||||
let menu_button_row = root_pane.find_pane_by_name_recursive(
|
||||
format!("TrModMenuButtonRow{row_idx}").as_str()
|
||||
).unwrap();
|
||||
let menu_button_row = root_pane
|
||||
.find_pane_by_name_recursive(format!("TrModMenuButtonRow{row_idx}").as_str())
|
||||
.unwrap();
|
||||
menu_button_row.set_visible(false);
|
||||
let menu_button = menu_button_row.find_pane_by_name_recursive(
|
||||
format!("Button{col_idx}").as_str()
|
||||
).unwrap();
|
||||
let menu_button = menu_button_row
|
||||
.find_pane_by_name_recursive(format!("Button{col_idx}").as_str())
|
||||
.unwrap();
|
||||
menu_button.set_visible(false);
|
||||
|
||||
menu_button.find_pane_by_name_recursive("ValueTxt").unwrap().set_visible(false);
|
||||
menu_button
|
||||
.find_pane_by_name_recursive("ValueTxt")
|
||||
.unwrap()
|
||||
.set_visible(false);
|
||||
});
|
||||
|
||||
root_pane.find_pane_by_name_recursive("TrModSlider").unwrap().set_visible(false);
|
||||
root_pane
|
||||
.find_pane_by_name_recursive("TrModSlider")
|
||||
.unwrap()
|
||||
.set_visible(false);
|
||||
|
||||
let app_tabs = &app.tabs.items;
|
||||
let tab_selected = app.tabs.state.selected().unwrap();
|
||||
|
@ -295,66 +356,112 @@ pub unsafe fn draw(root_pane: &mut Pane) {
|
|||
};
|
||||
let tab_titles = [prev_tab, tab_selected, next_tab].map(|idx| app_tabs[idx]);
|
||||
|
||||
[(Some(0xE0E6), "LeftTab"), (None, "CurrentTab"), (Some(0xE0E7), "RightTab")]
|
||||
.iter().enumerate().for_each(|(idx, (key, name))| {
|
||||
let key_help_pane = root_pane.find_pane_by_name_recursive(name)
|
||||
.unwrap();
|
||||
let p1_controller_id = crate::training::input_delay::p1_controller_id();
|
||||
let p1_style_set = GetNpadStyleSet(&p1_controller_id as *const _);
|
||||
let is_gcc = (p1_style_set.flags & (1 << 5)) > 0;
|
||||
let button_mapping = if is_gcc {
|
||||
GCC_BUTTON_MAPPING.clone()
|
||||
} else {
|
||||
PROCON_BUTTON_MAPPING.clone()
|
||||
};
|
||||
|
||||
let icon_pane = key_help_pane.find_pane_by_name_recursive("set_txt_icon")
|
||||
.unwrap().as_textbox();
|
||||
let help_pane = key_help_pane.find_pane_by_name_recursive("set_txt_help")
|
||||
.unwrap().as_textbox();
|
||||
let (x_key, l_key, r_key, zl_key, zr_key, z_key) = (
|
||||
button_mapping.get("X"),
|
||||
button_mapping.get("L"),
|
||||
button_mapping.get("R"),
|
||||
button_mapping.get("ZL"),
|
||||
button_mapping.get("ZR"),
|
||||
button_mapping.get("Z"),
|
||||
);
|
||||
|
||||
let (left_tab_key, right_tab_key, save_defaults_key, reset_current_key, reset_all_key) =
|
||||
if is_gcc {
|
||||
(None, z_key, x_key, l_key, r_key)
|
||||
} else {
|
||||
(zl_key, zr_key, x_key, l_key, r_key)
|
||||
};
|
||||
|
||||
[
|
||||
(left_tab_key, "LeftTab"),
|
||||
(None, "CurrentTab"),
|
||||
(right_tab_key, "RightTab"),
|
||||
]
|
||||
.iter()
|
||||
.enumerate()
|
||||
.for_each(|(idx, (key, name))| {
|
||||
let key_help_pane = root_pane.find_pane_by_name_recursive(name).unwrap();
|
||||
|
||||
let icon_pane = key_help_pane
|
||||
.find_pane_by_name_recursive("set_txt_icon")
|
||||
.unwrap()
|
||||
.as_textbox();
|
||||
let help_pane = key_help_pane
|
||||
.find_pane_by_name_recursive("set_txt_help")
|
||||
.unwrap()
|
||||
.as_textbox();
|
||||
icon_pane.set_text_string("");
|
||||
|
||||
// Left/Right tabs have keys
|
||||
if let Some(key) = key {
|
||||
let it = icon_pane.text_buf as *mut u16;
|
||||
icon_pane.text_len = 1;
|
||||
*it = *key as u16;
|
||||
*it = **key;
|
||||
*(it.add(1)) = 0x0;
|
||||
} else {
|
||||
}
|
||||
|
||||
if *name == "CurrentTab" {
|
||||
icon_pane.set_text_string("");
|
||||
// Center tab should be highlighted
|
||||
help_pane.set_default_material_colors();
|
||||
help_pane.set_color(255, 255, 0, 255);
|
||||
}
|
||||
help_pane.set_text_string(tab_titles[idx]);
|
||||
});
|
||||
[(0xE0E2, "SaveDefaults"), (0xE0E4, "ResetCurrentDefaults"), (0xE0E5, "ResetAllDefaults")].iter()
|
||||
.for_each(|(key, name)| {
|
||||
let key_help_pane = root_pane.find_pane_by_name_recursive(name)
|
||||
.unwrap();
|
||||
[
|
||||
(save_defaults_key, "SaveDefaults"),
|
||||
(reset_current_key, "ResetCurrentDefaults"),
|
||||
(reset_all_key, "ResetAllDefaults"),
|
||||
]
|
||||
.iter()
|
||||
.for_each(|(key, name)| {
|
||||
let key_help_pane = root_pane.find_pane_by_name_recursive(name).unwrap();
|
||||
|
||||
let icon_pane = key_help_pane.find_pane_by_name_recursive("set_txt_icon")
|
||||
.unwrap().as_textbox();
|
||||
icon_pane.set_text_string("");
|
||||
let it = icon_pane.text_buf as *mut u16;
|
||||
icon_pane.text_len = 1;
|
||||
*it = *key as u16;
|
||||
*(it.add(1)) = 0x0;
|
||||
let icon_pane = key_help_pane
|
||||
.find_pane_by_name_recursive("set_txt_icon")
|
||||
.unwrap()
|
||||
.as_textbox();
|
||||
icon_pane.set_text_string("");
|
||||
let it = icon_pane.text_buf as *mut u16;
|
||||
icon_pane.text_len = 1;
|
||||
*it = *key.unwrap();
|
||||
*(it.add(1)) = 0x0;
|
||||
|
||||
// PascalCase to Title Case
|
||||
let title_case = name
|
||||
.chars()
|
||||
.fold(vec![], |mut acc, ch| {
|
||||
if ch.is_uppercase() {
|
||||
acc.push(String::new());
|
||||
}
|
||||
if let Some(last) = acc.last_mut() {
|
||||
last.push(ch);
|
||||
}
|
||||
acc
|
||||
})
|
||||
.into_iter()
|
||||
.collect::<Vec<String>>()
|
||||
.join(" ");
|
||||
key_help_pane.find_pane_by_name_recursive("set_txt_help")
|
||||
.unwrap().as_textbox().set_text_string(title_case.as_str());
|
||||
});
|
||||
// PascalCase to Title Case
|
||||
let title_case = name
|
||||
.chars()
|
||||
.fold(vec![], |mut acc, ch| {
|
||||
if ch.is_uppercase() {
|
||||
acc.push(String::new());
|
||||
}
|
||||
if let Some(last) = acc.last_mut() {
|
||||
last.push(ch);
|
||||
}
|
||||
acc
|
||||
})
|
||||
.into_iter()
|
||||
.collect::<Vec<String>>()
|
||||
.join(" ");
|
||||
key_help_pane
|
||||
.find_pane_by_name_recursive("set_txt_help")
|
||||
.unwrap()
|
||||
.as_textbox()
|
||||
.set_text_string(title_case.as_str());
|
||||
});
|
||||
|
||||
match app.page {
|
||||
AppPage::SUBMENU => render_submenu_page(app, root_pane),
|
||||
AppPage::SLIDER => render_slider_page(app, root_pane),
|
||||
AppPage::TOGGLE => render_toggle_page(app, root_pane),
|
||||
AppPage::CONFIRMATION => todo!()
|
||||
AppPage::CONFIRMATION => todo!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue