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:
parent
b20a44ca5c
commit
d128b902ed
6 changed files with 93 additions and 33 deletions
|
@ -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" }
|
||||||
|
|
|
@ -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.
|
@ -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();
|
||||||
|
|
|
@ -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`
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
Loading…
Reference in a new issue