1
0
Fork 0
mirror of https://github.com/jugeeya/UltimateTrainingModpack.git synced 2024-11-28 04:44:06 +00:00

Add icons to the new menu (#482)

* Added test icons to layout,
toggle visibility of icon based on submenu_id

* disable icon container pane when menu is open

* Add icons to 'layout.arc'

* Add remaining icons to 'layout.arc'

* Apply suggestions from code review

Co-authored-by: jugeeya <jugeeya@live.com>

* Incorporate feedback, remove deltas from formatting differences

* Updated some icon textures, updated layout

* Swapped x for check icon on selected toggles

* Moved logic to collect submenu id's to app impl

---------

Co-authored-by: Matthew Edell <edell.matthew@gmail.com>
Co-authored-by: jugeeya <jugeeya@live.com>
This commit is contained in:
Austin Traver 2023-02-15 22:47:36 -08:00 committed by GitHub
parent b20a44ca5c
commit d128b902ed
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 93 additions and 33 deletions

View file

@ -33,6 +33,7 @@ training_mod_consts = { path = "training_mod_consts" }
training_mod_tui = { path = "training_mod_tui" } training_mod_tui = { path = "training_mod_tui" }
native-tls = { version = "0.2.11", features = ["vendored"] } native-tls = { version = "0.2.11", features = ["vendored"] }
log = "0.4.17" log = "0.4.17"
byte-unit = "4.0.18"
[patch.crates-io] [patch.crates-io]
native-tls = { git = "https://github.com/skyline-rs/rust-native-tls", rev = "f202fca" } native-tls = { git = "https://github.com/skyline-rs/rust-native-tls", rev = "f202fca" }

View file

@ -180,15 +180,6 @@ pub fn handle_get_npad_state(state: *mut NpadGcState, _controller_id: *const u32
let update_count = (*state).updateCount; let update_count = (*state).updateCount;
let flags = (*state).Flags; let flags = (*state).Flags;
if QUICK_MENU_ACTIVE { if QUICK_MENU_ACTIVE {
// TODO: This should make more sense, look into.
// BUTTON_PRESSES.a.is_pressed = (*state).Buttons & (1 << 0) > 0;
// BUTTON_PRESSES.b.is_pressed = (*state).Buttons & (1 << 1) > 0;
// BUTTON_PRESSES.zl.is_pressed = (*state).Buttons & (1 << 8) > 0;
// BUTTON_PRESSES.zr.is_pressed = (*state).Buttons & (1 << 9) > 0;
// BUTTON_PRESSES.left.is_pressed = (*state).Buttons & ((1 << 12) | (1 << 16)) > 0;
// BUTTON_PRESSES.right.is_pressed = (*state).Buttons & ((1 << 14) | (1 << 18)) > 0;
// BUTTON_PRESSES.down.is_pressed = (*state).Buttons & ((1 << 15) | (1 << 19)) > 0;
// BUTTON_PRESSES.up.is_pressed = (*state).Buttons & ((1 << 13) | (1 << 17)) > 0;
if (*state).Buttons & (1 << 0) > 0 { if (*state).Buttons & (1 << 0) > 0 {
BUTTON_PRESSES.a.is_pressed = true; BUTTON_PRESSES.a.is_pressed = true;

Binary file not shown.

View file

@ -1,9 +1,9 @@
use std::collections::HashMap;
use lazy_static::lazy_static; use lazy_static::lazy_static;
use skyline::nn::hid::GetNpadStyleSet; use skyline::nn::hid::GetNpadStyleSet;
use skyline::nn::ui2d::*; use skyline::nn::ui2d::*;
use smash::ui2d::{SmashPane, SmashTextBox}; use smash::ui2d::{SmashPane, SmashTextBox};
use std::collections::HashMap;
use training_mod_tui::gauge::GaugeState; use training_mod_tui::gauge::GaugeState;
use training_mod_tui::{App, AppPage}; use training_mod_tui::{App, AppPage};
@ -69,6 +69,7 @@ lazy_static! {
unsafe fn render_submenu_page(app: &App, root_pane: &mut Pane) { unsafe fn render_submenu_page(app: &App, root_pane: &mut Pane) {
let tab_selected = app.tab_selected(); let tab_selected = app.tab_selected();
let tab = app.menu_items.get(tab_selected).unwrap(); let tab = app.menu_items.get(tab_selected).unwrap();
let submenu_ids = app.submenu_ids();
(0..NUM_MENU_TEXT_OPTIONS) (0..NUM_MENU_TEXT_OPTIONS)
// Valid options in this submenu // Valid options in this submenu
@ -78,42 +79,74 @@ unsafe fn render_submenu_page(app: &App, root_pane: &mut Pane) {
.find_pane_by_name_recursive(format!("TrModMenuButtonRow{list_idx}").as_str()) .find_pane_by_name_recursive(format!("TrModMenuButtonRow{list_idx}").as_str())
.unwrap(); .unwrap();
menu_button_row.set_visible(true); menu_button_row.set_visible(true);
let menu_button = menu_button_row let menu_button = menu_button_row
.find_pane_by_name_recursive(format!("Button{list_section}").as_str()) .find_pane_by_name_recursive(format!("Button{list_section}").as_str())
.unwrap(); .unwrap();
menu_button.set_visible(true);
let title_text = menu_button let title_text = menu_button
.find_pane_by_name_recursive("TitleTxt") .find_pane_by_name_recursive("TitleTxt")
.unwrap() .unwrap()
.as_textbox(); .as_textbox();
let title_bg = menu_button let title_bg = menu_button
.find_pane_by_name_recursive("TitleBg") .find_pane_by_name_recursive("TitleBg")
.unwrap() .unwrap()
.as_picture(); .as_picture();
let title_bg_material = &mut *title_bg.material;
let list = &tab.lists[list_section]; let list = &tab.lists[list_section];
let submenu = &list.items[list_idx]; let submenu = &list.items[list_idx];
let is_selected = list.state.selected().filter(|s| *s == list_idx).is_some(); let is_selected = list.state.selected().filter(|s| *s == list_idx).is_some();
title_text.set_text_string(submenu.submenu_title); title_text.set_text_string(submenu.submenu_title);
let title_bg_material = &mut *title_bg.material;
// In the actual 'layout.arc' file, every icon image is stacked
// into a single container pane, with each image directly on top of another.
// Hide all icon images, and strategically mark the icon that
// corresponds with a particular button to be visible.
submenu_ids.iter().for_each(|id| {
menu_button
.find_pane_by_name_recursive(id)
.unwrap()
.set_visible(id == &submenu.submenu_id);
});
menu_button
.find_pane_by_name_recursive("check")
.unwrap()
.set_visible(false);
if is_selected { if is_selected {
root_pane root_pane
.find_pane_by_name_recursive("FooterTxt") .find_pane_by_name_recursive("FooterTxt")
.unwrap() .unwrap()
.as_textbox() .as_textbox()
.set_text_string(submenu.help_text); .set_text_string(submenu.help_text);
title_bg_material.set_white_res_color(BG_LEFT_ON_WHITE_COLOR); 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_bg_material.set_black_res_color(BG_LEFT_ON_BLACK_COLOR);
title_text.text_shadow_enable(true); title_text.text_shadow_enable(true);
title_text.text_outline_enable(true); title_text.text_outline_enable(true);
title_text.set_color(255, 255, 255, 255); title_text.set_color(255, 255, 255, 255);
} else { } else {
title_bg_material.set_white_res_color(BG_LEFT_OFF_WHITE_COLOR); title_bg_material.set_white_res_color(BG_LEFT_OFF_WHITE_COLOR);
title_bg_material.set_black_res_color(BG_LEFT_OFF_BLACK_COLOR); title_bg_material.set_black_res_color(BG_LEFT_OFF_BLACK_COLOR);
title_text.text_shadow_enable(false); title_text.text_shadow_enable(false);
title_text.text_outline_enable(false); title_text.text_outline_enable(false);
title_text.set_color(178, 199, 211, 255); title_text.set_color(178, 199, 211, 255);
} }
menu_button.set_visible(true);
menu_button
.find_pane_by_name_recursive("Icon")
.unwrap()
.set_visible(true);
}); });
} }
@ -130,6 +163,7 @@ unsafe fn render_toggle_page(app: &App, root_pane: &mut Pane) {
.find_pane_by_name_recursive(format!("TrModMenuButtonRow{list_idx}").as_str()) .find_pane_by_name_recursive(format!("TrModMenuButtonRow{list_idx}").as_str())
.unwrap(); .unwrap();
menu_button_row.set_visible(true); menu_button_row.set_visible(true);
let menu_button = menu_button_row let menu_button = menu_button_row
.find_pane_by_name_recursive(format!("Button{list_section}").as_str()) .find_pane_by_name_recursive(format!("Button{list_section}").as_str())
.unwrap(); .unwrap();
@ -139,43 +173,52 @@ unsafe fn render_toggle_page(app: &App, root_pane: &mut Pane) {
.find_pane_by_name_recursive("TitleTxt") .find_pane_by_name_recursive("TitleTxt")
.unwrap() .unwrap()
.as_textbox(); .as_textbox();
let title_bg = menu_button let title_bg = menu_button
.find_pane_by_name_recursive("TitleBg") .find_pane_by_name_recursive("TitleBg")
.unwrap() .unwrap()
.as_picture(); .as_picture();
let value_text = menu_button
.find_pane_by_name_recursive("ValueTxt")
.unwrap()
.as_textbox();
let is_selected = sub_menu_state let is_selected = sub_menu_state
.selected() .selected()
.filter(|s| *s == list_idx) .filter(|s| *s == list_idx)
.is_some(); .is_some();
let submenu_ids = app.submenu_ids();
submenu_ids.iter().for_each(|id| {
menu_button
.find_pane_by_name_recursive(id)
.unwrap()
.set_visible(false)
});
title_text.set_text_string(name); title_text.set_text_string(name);
menu_button.find_pane_by_name_recursive("check")
.unwrap()
.set_visible(true);
menu_button.find_pane_by_name_recursive("Icon").unwrap().set_visible(*checked);
let title_bg_material = &mut *title_bg.material;
if is_selected { if is_selected {
title_text.text_shadow_enable(true); title_text.text_shadow_enable(true);
title_text.text_outline_enable(true); title_text.text_outline_enable(true);
title_text.set_color(255, 255, 255, 255);
} else {
title_text.text_shadow_enable(false);
title_text.text_outline_enable(false);
title_text.set_color(178, 199, 211, 255);
}
let title_bg_material = &mut *title_bg.material; title_text.set_color(255, 255, 255, 255);
if is_selected {
title_bg_material.set_white_res_color(BG_LEFT_ON_WHITE_COLOR); 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_bg_material.set_black_res_color(BG_LEFT_ON_BLACK_COLOR);
} else { } else {
title_text.text_shadow_enable(false);
title_text.text_outline_enable(false);
title_text.set_color(178, 199, 211, 255);
title_bg_material.set_white_res_color(BG_LEFT_OFF_WHITE_COLOR); title_bg_material.set_white_res_color(BG_LEFT_OFF_WHITE_COLOR);
title_bg_material.set_black_res_color(BG_LEFT_OFF_BLACK_COLOR); title_bg_material.set_black_res_color(BG_LEFT_OFF_BLACK_COLOR);
} }
if *checked {
value_text.set_text_string("X");
value_text.set_visible(true);
}
}); });
}); });
} }
@ -282,6 +325,9 @@ unsafe fn render_slider_page(app: &App, root_pane: &mut Pane) {
max_title_bg_material.set_white_res_color(max_colors.0); max_title_bg_material.set_white_res_color(max_colors.0);
max_title_bg_material.set_black_res_color(max_colors.1); max_title_bg_material.set_black_res_color(max_colors.1);
min_value_text.set_visible(true);
max_value_text.set_visible(true);
} }
pub unsafe fn draw(root_pane: &mut Pane) { pub unsafe fn draw(root_pane: &mut Pane) {
@ -326,6 +372,7 @@ pub unsafe fn draw(root_pane: &mut Pane) {
.find_pane_by_name_recursive(format!("TrModMenuButtonRow{row_idx}").as_str()) .find_pane_by_name_recursive(format!("TrModMenuButtonRow{row_idx}").as_str())
.unwrap(); .unwrap();
menu_button_row.set_visible(false); menu_button_row.set_visible(false);
let menu_button = menu_button_row let menu_button = menu_button_row
.find_pane_by_name_recursive(format!("Button{col_idx}").as_str()) .find_pane_by_name_recursive(format!("Button{col_idx}").as_str())
.unwrap(); .unwrap();

View file

@ -1,3 +1,4 @@
use byte_unit::MEBIBYTE;
use sarc::SarcFile; use sarc::SarcFile;
use skyline::nn::ui2d::*; use skyline::nn::ui2d::*;
use training_mod_consts::{OnOff, MENU}; use training_mod_consts::{OnOff, MENU};
@ -33,10 +34,13 @@ pub unsafe fn handle_draw(layout: *mut Layout, draw_info: u64, cmd_buffer: u64)
original!()(layout, draw_info, cmd_buffer); original!()(layout, draw_info, cmd_buffer);
} }
// We'll keep some sane max size here; we shouldn't reach above 600KiB is the idea, // Allocate a static amount of memory that Smash isn't allowed to deallocate,
// but we can try higher if we need to. // in order for us to be able to swap the 'layout.arc' with the current
// version of the file in between loads of training mode.
#[cfg(feature = "layout_arc_from_file")] #[cfg(feature = "layout_arc_from_file")]
static mut LAYOUT_ARC: &mut [u8; 600000] = &mut [0u8; 600000]; const LAYOUT_ARC_SIZE: usize = (2 * MEBIBYTE) as usize;
#[cfg(feature = "layout_arc_from_file")]
static mut LAYOUT_ARC: &mut [u8; LAYOUT_ARC_SIZE] = &mut [0u8; LAYOUT_ARC_SIZE];
/// We are editing the info_training/layout.arc and replacing the original file with our /// We are editing the info_training/layout.arc and replacing the original file with our
/// modified version from `LAYOUT_ARC_PATH` /// modified version from `LAYOUT_ARC_PATH`

View file

@ -578,6 +578,23 @@ impl<'a> App<'a> {
defaults_menu: serde_json::from_str(self.default_menu.1.clone().as_str()).unwrap(), defaults_menu: serde_json::from_str(self.default_menu.1.clone().as_str()).unwrap(),
}).unwrap() }).unwrap()
} }
pub fn submenu_ids(&self) -> Vec<&str> {
return self.menu_items
.values()
.flat_map(|multi_stateful_list| {
multi_stateful_list
.lists
.iter()
.flat_map(|sub_stateful_list| {
sub_stateful_list
.items
.iter()
.map(|submenu| submenu.submenu_id)
})
})
.collect::<Vec<&str>>();
}
} }
fn render_submenu_page<B: Backend>(f: &mut Frame<B>, app: &mut App, list_chunks: Vec<Rect>, help_chunk: Rect) { fn render_submenu_page<B: Backend>(f: &mut Frame<B>, app: &mut App, list_chunks: Vec<Rect>, help_chunk: Rect) {