1
0
Fork 0
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:
jugeeya 2023-02-15 00:07:45 -08:00 committed by GitHub
parent e981a0bfd0
commit b20a44ca5c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -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!(),
}
}
}