mirror of
https://github.com/jugeeya/UltimateTrainingModpack.git
synced 2024-11-24 10:54:16 +00:00
Change Menu Buttons and Help Text; HUD Off Outside Training (#488)
* Avoid making layouts invisible outside training mode with HUD off * Switch menu buttons around; change defaults resetting texts * Fix unused feature import
This commit is contained in:
parent
7fb93ea309
commit
d05f8ce918
5 changed files with 206 additions and 158 deletions
|
@ -80,6 +80,7 @@ pub struct ButtonPresses {
|
||||||
pub a: ButtonPress,
|
pub a: ButtonPress,
|
||||||
pub b: ButtonPress,
|
pub b: ButtonPress,
|
||||||
pub x: ButtonPress,
|
pub x: ButtonPress,
|
||||||
|
pub y: ButtonPress,
|
||||||
pub r: ButtonPress,
|
pub r: ButtonPress,
|
||||||
pub l: ButtonPress,
|
pub l: ButtonPress,
|
||||||
pub zr: ButtonPress,
|
pub zr: ButtonPress,
|
||||||
|
@ -133,6 +134,11 @@ pub static mut BUTTON_PRESSES: ButtonPresses = ButtonPresses {
|
||||||
is_pressed: false,
|
is_pressed: false,
|
||||||
lockout_frames: 0,
|
lockout_frames: 0,
|
||||||
},
|
},
|
||||||
|
y: ButtonPress {
|
||||||
|
prev_frame_is_pressed: false,
|
||||||
|
is_pressed: false,
|
||||||
|
lockout_frames: 0,
|
||||||
|
},
|
||||||
r: ButtonPress {
|
r: ButtonPress {
|
||||||
prev_frame_is_pressed: false,
|
prev_frame_is_pressed: false,
|
||||||
is_pressed: false,
|
is_pressed: false,
|
||||||
|
@ -180,7 +186,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 {
|
||||||
|
|
||||||
if (*state).Buttons & (1 << 0) > 0 {
|
if (*state).Buttons & (1 << 0) > 0 {
|
||||||
BUTTON_PRESSES.a.is_pressed = true;
|
BUTTON_PRESSES.a.is_pressed = true;
|
||||||
}
|
}
|
||||||
|
@ -190,6 +195,9 @@ pub fn handle_get_npad_state(state: *mut NpadGcState, _controller_id: *const u32
|
||||||
if (*state).Buttons & (1 << 2) > 0 {
|
if (*state).Buttons & (1 << 2) > 0 {
|
||||||
BUTTON_PRESSES.x.is_pressed = true;
|
BUTTON_PRESSES.x.is_pressed = true;
|
||||||
}
|
}
|
||||||
|
if (*state).Buttons & (1 << 3) > 0 {
|
||||||
|
BUTTON_PRESSES.y.is_pressed = true;
|
||||||
|
}
|
||||||
if (*state).Buttons & (1 << 6) > 0 {
|
if (*state).Buttons & (1 << 6) > 0 {
|
||||||
BUTTON_PRESSES.l.is_pressed = true;
|
BUTTON_PRESSES.l.is_pressed = true;
|
||||||
}
|
}
|
||||||
|
@ -239,6 +247,12 @@ lazy_static! {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub unsafe fn p1_controller_is_gcc() -> bool {
|
||||||
|
let p1_controller_id = crate::training::input_delay::p1_controller_id();
|
||||||
|
let p1_style_set = GetNpadStyleSet(&p1_controller_id as *const _);
|
||||||
|
(p1_style_set.flags & (1 << 5)) > 0
|
||||||
|
}
|
||||||
|
|
||||||
pub unsafe fn quick_menu_loop() {
|
pub unsafe fn quick_menu_loop() {
|
||||||
loop {
|
loop {
|
||||||
std::thread::sleep(std::time::Duration::from_secs(10));
|
std::thread::sleep(std::time::Duration::from_secs(10));
|
||||||
|
@ -262,6 +276,8 @@ pub unsafe fn quick_menu_loop() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let is_gcc = p1_controller_is_gcc();
|
||||||
|
|
||||||
let app = &mut *QUICK_MENU_APP.data_ptr();
|
let app = &mut *QUICK_MENU_APP.data_ptr();
|
||||||
button_presses.a.read_press().then(|| {
|
button_presses.a.read_press().then(|| {
|
||||||
app.on_a();
|
app.on_a();
|
||||||
|
@ -282,23 +298,39 @@ pub unsafe fn quick_menu_loop() {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
button_presses.x.read_press().then(|| {
|
button_presses.x.read_press().then(|| {
|
||||||
app.on_x();
|
app.save_defaults();
|
||||||
|
received_input = true;
|
||||||
|
});
|
||||||
|
button_presses.y.read_press().then(|| {
|
||||||
|
app.reset_current_submenu();
|
||||||
received_input = true;
|
received_input = true;
|
||||||
});
|
});
|
||||||
button_presses.l.read_press().then(|| {
|
button_presses.l.read_press().then(|| {
|
||||||
app.on_l();
|
if is_gcc {
|
||||||
|
app.previous_tab();
|
||||||
|
}
|
||||||
received_input = true;
|
received_input = true;
|
||||||
});
|
});
|
||||||
button_presses.r.read_press().then(|| {
|
button_presses.r.read_press().then(|| {
|
||||||
app.on_r();
|
if is_gcc {
|
||||||
|
app.next_tab();
|
||||||
|
} else {
|
||||||
|
app.reset_all_submenus();
|
||||||
|
}
|
||||||
received_input = true;
|
received_input = true;
|
||||||
});
|
});
|
||||||
button_presses.zl.read_press().then(|| {
|
button_presses.zl.read_press().then(|| {
|
||||||
app.on_zl();
|
if !is_gcc {
|
||||||
|
app.previous_tab();
|
||||||
|
}
|
||||||
received_input = true;
|
received_input = true;
|
||||||
});
|
});
|
||||||
button_presses.zr.read_press().then(|| {
|
button_presses.zr.read_press().then(|| {
|
||||||
app.on_zr();
|
if !is_gcc {
|
||||||
|
app.next_tab();
|
||||||
|
} else {
|
||||||
|
app.reset_all_submenus();
|
||||||
|
}
|
||||||
received_input = true;
|
received_input = true;
|
||||||
});
|
});
|
||||||
button_presses.left.read_press().then(|| {
|
button_presses.left.read_press().then(|| {
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use skyline::nn::hid::GetNpadStyleSet;
|
|
||||||
use skyline::nn::ui2d::*;
|
use skyline::nn::ui2d::*;
|
||||||
use smash::ui2d::{SmashPane, SmashTextBox};
|
use smash::ui2d::{SmashPane, SmashTextBox};
|
||||||
use training_mod_tui::gauge::GaugeState;
|
use training_mod_tui::gauge::GaugeState;
|
||||||
|
@ -55,12 +54,18 @@ const BG_LEFT_SELECTED_WHITE_COLOR: ResColor = ResColor {
|
||||||
};
|
};
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
static ref GCC_BUTTON_MAPPING: HashMap<&'static str, u16> =
|
static ref GCC_BUTTON_MAPPING: HashMap<&'static str, u16> = HashMap::from([
|
||||||
HashMap::from([("L", 0xE204), ("R", 0xE205), ("X", 0xE206), ("Z", 0xE208)]);
|
("L", 0xE204),
|
||||||
|
("R", 0xE205),
|
||||||
|
("X", 0xE206),
|
||||||
|
("Y", 0xE207),
|
||||||
|
("Z", 0xE208)
|
||||||
|
]);
|
||||||
static ref PROCON_BUTTON_MAPPING: HashMap<&'static str, u16> = HashMap::from([
|
static ref PROCON_BUTTON_MAPPING: HashMap<&'static str, u16> = HashMap::from([
|
||||||
("L", 0xE0E4),
|
("L", 0xE0E4),
|
||||||
("R", 0xE0E5),
|
("R", 0xE0E5),
|
||||||
("X", 0xE0E2),
|
("X", 0xE0E2),
|
||||||
|
("Y", 0xE0E3),
|
||||||
("ZL", 0xE0E6),
|
("ZL", 0xE0E6),
|
||||||
("ZR", 0xE0E7)
|
("ZR", 0xE0E7)
|
||||||
]);
|
]);
|
||||||
|
@ -138,7 +143,7 @@ unsafe fn render_submenu_page(app: &App, root_pane: &mut Pane) {
|
||||||
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,11 +199,15 @@ unsafe fn render_toggle_page(app: &App, root_pane: &mut Pane) {
|
||||||
});
|
});
|
||||||
|
|
||||||
title_text.set_text_string(name);
|
title_text.set_text_string(name);
|
||||||
menu_button.find_pane_by_name_recursive("check")
|
menu_button
|
||||||
|
.find_pane_by_name_recursive("check")
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.set_visible(true);
|
.set_visible(true);
|
||||||
|
|
||||||
menu_button.find_pane_by_name_recursive("Icon").unwrap().set_visible(*checked);
|
menu_button
|
||||||
|
.find_pane_by_name_recursive("Icon")
|
||||||
|
.unwrap()
|
||||||
|
.set_visible(*checked);
|
||||||
|
|
||||||
let title_bg_material = &mut *title_bg.material;
|
let title_bg_material = &mut *title_bg.material;
|
||||||
|
|
||||||
|
@ -403,17 +412,16 @@ pub unsafe fn draw(root_pane: &mut Pane) {
|
||||||
};
|
};
|
||||||
let tab_titles = [prev_tab, tab_selected, next_tab].map(|idx| app_tabs[idx]);
|
let tab_titles = [prev_tab, tab_selected, next_tab].map(|idx| app_tabs[idx]);
|
||||||
|
|
||||||
let p1_controller_id = crate::training::input_delay::p1_controller_id();
|
let is_gcc = common::menu::p1_controller_is_gcc();
|
||||||
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 {
|
let button_mapping = if is_gcc {
|
||||||
GCC_BUTTON_MAPPING.clone()
|
GCC_BUTTON_MAPPING.clone()
|
||||||
} else {
|
} else {
|
||||||
PROCON_BUTTON_MAPPING.clone()
|
PROCON_BUTTON_MAPPING.clone()
|
||||||
};
|
};
|
||||||
|
|
||||||
let (x_key, l_key, r_key, zl_key, zr_key, z_key) = (
|
let (x_key, y_key, l_key, r_key, zl_key, zr_key, z_key) = (
|
||||||
button_mapping.get("X"),
|
button_mapping.get("X"),
|
||||||
|
button_mapping.get("Y"),
|
||||||
button_mapping.get("L"),
|
button_mapping.get("L"),
|
||||||
button_mapping.get("R"),
|
button_mapping.get("R"),
|
||||||
button_mapping.get("ZL"),
|
button_mapping.get("ZL"),
|
||||||
|
@ -423,9 +431,9 @@ pub unsafe fn draw(root_pane: &mut Pane) {
|
||||||
|
|
||||||
let (left_tab_key, right_tab_key, save_defaults_key, reset_current_key, reset_all_key) =
|
let (left_tab_key, right_tab_key, save_defaults_key, reset_current_key, reset_all_key) =
|
||||||
if is_gcc {
|
if is_gcc {
|
||||||
(None, z_key, x_key, l_key, r_key)
|
(l_key, r_key, x_key, y_key, z_key)
|
||||||
} else {
|
} else {
|
||||||
(zl_key, zr_key, x_key, l_key, r_key)
|
(zl_key, zr_key, x_key, y_key, r_key)
|
||||||
};
|
};
|
||||||
|
|
||||||
[
|
[
|
||||||
|
@ -465,12 +473,12 @@ pub unsafe fn draw(root_pane: &mut Pane) {
|
||||||
help_pane.set_text_string(tab_titles[idx]);
|
help_pane.set_text_string(tab_titles[idx]);
|
||||||
});
|
});
|
||||||
[
|
[
|
||||||
(save_defaults_key, "SaveDefaults"),
|
(save_defaults_key, "SaveDefaults", "Save Defaults"),
|
||||||
(reset_current_key, "ResetCurrentDefaults"),
|
(reset_current_key, "ResetCurrentDefaults", "Reset Current"),
|
||||||
(reset_all_key, "ResetAllDefaults"),
|
(reset_all_key, "ResetAllDefaults", "Reset All"),
|
||||||
]
|
]
|
||||||
.iter()
|
.iter()
|
||||||
.for_each(|(key, name)| {
|
.for_each(|(key, name, title)| {
|
||||||
let key_help_pane = root_pane.find_pane_by_name_recursive(name).unwrap();
|
let key_help_pane = root_pane.find_pane_by_name_recursive(name).unwrap();
|
||||||
|
|
||||||
let icon_pane = key_help_pane
|
let icon_pane = key_help_pane
|
||||||
|
@ -483,26 +491,11 @@ pub unsafe fn draw(root_pane: &mut Pane) {
|
||||||
*it = *key.unwrap();
|
*it = *key.unwrap();
|
||||||
*(it.add(1)) = 0x0;
|
*(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
|
key_help_pane
|
||||||
.find_pane_by_name_recursive("set_txt_help")
|
.find_pane_by_name_recursive("set_txt_help")
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.as_textbox()
|
.as_textbox()
|
||||||
.set_text_string(title_case.as_str());
|
.set_text_string(title);
|
||||||
});
|
});
|
||||||
|
|
||||||
match app.page {
|
match app.page {
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
#[cfg(feature = "layout_arc_from_file")]
|
||||||
use byte_unit::MEBIBYTE;
|
use byte_unit::MEBIBYTE;
|
||||||
use sarc::SarcFile;
|
use sarc::SarcFile;
|
||||||
use skyline::nn::ui2d::*;
|
use skyline::nn::ui2d::*;
|
||||||
|
@ -22,6 +23,8 @@ pub unsafe fn handle_draw(layout: *mut Layout, draw_info: u64, cmd_buffer: u64)
|
||||||
// InfluencedAlpha means "Should my children panes' alpha be influenced by mine, as the parent?"
|
// InfluencedAlpha means "Should my children panes' alpha be influenced by mine, as the parent?"
|
||||||
root_pane.flags |= 1 << PaneFlag::InfluencedAlpha as u8;
|
root_pane.flags |= 1 << PaneFlag::InfluencedAlpha as u8;
|
||||||
root_pane.set_visible(MENU.hud == OnOff::On);
|
root_pane.set_visible(MENU.hud == OnOff::On);
|
||||||
|
} else {
|
||||||
|
root_pane.set_visible(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
damage::draw(root_pane, layout_name);
|
damage::draw(root_pane, layout_name);
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
use training_mod_consts::{MenuJsonStruct, Slider, SubMenu, SubMenuType, Toggle, UiMenu, ui_menu, TrainingModpackMenu};
|
use training_mod_consts::{
|
||||||
|
ui_menu, MenuJsonStruct, Slider, SubMenu, SubMenuType, Toggle, TrainingModpackMenu, UiMenu,
|
||||||
|
};
|
||||||
use tui::{
|
use tui::{
|
||||||
backend::Backend,
|
backend::Backend,
|
||||||
layout::{Constraint, Corner, Direction, Layout, Rect},
|
layout::{Constraint, Corner, Direction, Layout, Rect},
|
||||||
|
@ -8,8 +10,8 @@ use tui::{
|
||||||
Frame,
|
Frame,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use serde_json::{json, Map};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use serde_json::{Map, json};
|
|
||||||
pub use tui::{backend::TestBackend, style::Color, Terminal};
|
pub use tui::{backend::TestBackend, style::Color, Terminal};
|
||||||
|
|
||||||
pub mod gauge;
|
pub mod gauge;
|
||||||
|
@ -25,7 +27,7 @@ pub enum AppPage {
|
||||||
SUBMENU,
|
SUBMENU,
|
||||||
TOGGLE,
|
TOGGLE,
|
||||||
SLIDER,
|
SLIDER,
|
||||||
CONFIRMATION
|
CONFIRMATION,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// We should hold a list of SubMenus.
|
/// We should hold a list of SubMenus.
|
||||||
|
@ -58,7 +60,7 @@ impl<'a> App<'a> {
|
||||||
selected_sub_menu_toggles: MultiStatefulList::with_items(vec![], 0),
|
selected_sub_menu_toggles: MultiStatefulList::with_items(vec![], 0),
|
||||||
selected_sub_menu_slider: DoubleEndedGauge::new(),
|
selected_sub_menu_slider: DoubleEndedGauge::new(),
|
||||||
page: AppPage::SUBMENU,
|
page: AppPage::SUBMENU,
|
||||||
default_menu: default_menu
|
default_menu: default_menu,
|
||||||
};
|
};
|
||||||
app.set_sub_menu_items();
|
app.set_sub_menu_items();
|
||||||
app
|
app
|
||||||
|
@ -224,15 +226,13 @@ impl<'a> App<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns information about the currently selected submenu
|
/// Returns information about the currently selected submenu
|
||||||
///
|
///
|
||||||
/// 0: Submenu Title
|
/// 0: Submenu Title
|
||||||
/// 1: Submenu Help Text
|
/// 1: Submenu Help Text
|
||||||
/// 2: Vec(toggle checked, title) for toggles, Vec(nothing) for slider
|
/// 2: Vec(toggle checked, title) for toggles, Vec(nothing) for slider
|
||||||
/// 3: ListState for toggles, ListState::new() for slider
|
/// 3: ListState for toggles, ListState::new() for slider
|
||||||
/// TODO: Refactor return type into a nice struct
|
/// TODO: Refactor return type into a nice struct
|
||||||
pub fn sub_menu_strs_and_states(
|
pub fn sub_menu_strs_and_states(&self) -> (&str, &str, Vec<(Vec<(bool, &str)>, ListState)>) {
|
||||||
&self,
|
|
||||||
) -> (&str, &str, Vec<(Vec<(bool, &str)>, ListState)>) {
|
|
||||||
(
|
(
|
||||||
self.sub_menu_selected().submenu_title,
|
self.sub_menu_selected().submenu_title,
|
||||||
self.sub_menu_selected().help_text,
|
self.sub_menu_selected().help_text,
|
||||||
|
@ -293,8 +293,7 @@ impl<'a> App<'a> {
|
||||||
.get(tab_selected)
|
.get(tab_selected)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.idx_to_list_idx(self.menu_items.get(tab_selected).unwrap().state);
|
.idx_to_list_idx(self.menu_items.get(tab_selected).unwrap().state);
|
||||||
let selected_sub_menu = self.menu_items.get_mut(tab_selected).unwrap().lists
|
let selected_sub_menu = self.menu_items.get_mut(tab_selected).unwrap().lists[list_section]
|
||||||
[list_section]
|
|
||||||
.items
|
.items
|
||||||
.get_mut(list_idx)
|
.get_mut(list_idx)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
@ -305,7 +304,7 @@ impl<'a> App<'a> {
|
||||||
self.page = AppPage::SLIDER;
|
self.page = AppPage::SLIDER;
|
||||||
self.selected_sub_menu_slider.state = GaugeState::MinHover;
|
self.selected_sub_menu_slider.state = GaugeState::MinHover;
|
||||||
}
|
}
|
||||||
SubMenuType::TOGGLE => self.page = AppPage::TOGGLE
|
SubMenuType::TOGGLE => self.page = AppPage::TOGGLE,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
match SubMenuType::from_str(selected_sub_menu._type) {
|
match SubMenuType::from_str(selected_sub_menu._type) {
|
||||||
|
@ -323,7 +322,9 @@ impl<'a> App<'a> {
|
||||||
if !o.checked {
|
if !o.checked {
|
||||||
o.checked = true;
|
o.checked = true;
|
||||||
} else {
|
} else {
|
||||||
if is_single_option { return; }
|
if is_single_option {
|
||||||
|
return;
|
||||||
|
}
|
||||||
o.checked = false;
|
o.checked = false;
|
||||||
}
|
}
|
||||||
} else if is_single_option {
|
} else if is_single_option {
|
||||||
|
@ -341,7 +342,9 @@ impl<'a> App<'a> {
|
||||||
if !o.checked {
|
if !o.checked {
|
||||||
o.checked = true;
|
o.checked = true;
|
||||||
} else {
|
} else {
|
||||||
if is_single_option { return; }
|
if is_single_option {
|
||||||
|
return;
|
||||||
|
}
|
||||||
o.checked = false;
|
o.checked = false;
|
||||||
}
|
}
|
||||||
} else if is_single_option {
|
} else if is_single_option {
|
||||||
|
@ -358,7 +361,7 @@ impl<'a> App<'a> {
|
||||||
}
|
}
|
||||||
GaugeState::MinSelected => {
|
GaugeState::MinSelected => {
|
||||||
self.selected_sub_menu_slider.state = GaugeState::MinHover;
|
self.selected_sub_menu_slider.state = GaugeState::MinHover;
|
||||||
selected_sub_menu.slider = Some(Slider{
|
selected_sub_menu.slider = Some(Slider {
|
||||||
selected_min: self.selected_sub_menu_slider.selected_min,
|
selected_min: self.selected_sub_menu_slider.selected_min,
|
||||||
selected_max: self.selected_sub_menu_slider.selected_max,
|
selected_max: self.selected_sub_menu_slider.selected_max,
|
||||||
abs_min: self.selected_sub_menu_slider.abs_min,
|
abs_min: self.selected_sub_menu_slider.abs_min,
|
||||||
|
@ -367,7 +370,7 @@ impl<'a> App<'a> {
|
||||||
}
|
}
|
||||||
GaugeState::MaxSelected => {
|
GaugeState::MaxSelected => {
|
||||||
self.selected_sub_menu_slider.state = GaugeState::MaxHover;
|
self.selected_sub_menu_slider.state = GaugeState::MaxHover;
|
||||||
selected_sub_menu.slider = Some(Slider{
|
selected_sub_menu.slider = Some(Slider {
|
||||||
selected_min: self.selected_sub_menu_slider.selected_min,
|
selected_min: self.selected_sub_menu_slider.selected_min,
|
||||||
selected_max: self.selected_sub_menu_slider.selected_max,
|
selected_max: self.selected_sub_menu_slider.selected_max,
|
||||||
abs_min: self.selected_sub_menu_slider.abs_min,
|
abs_min: self.selected_sub_menu_slider.abs_min,
|
||||||
|
@ -405,7 +408,7 @@ impl<'a> App<'a> {
|
||||||
SubMenuType::SLIDER => match self.selected_sub_menu_slider.state {
|
SubMenuType::SLIDER => match self.selected_sub_menu_slider.state {
|
||||||
GaugeState::MinSelected => {
|
GaugeState::MinSelected => {
|
||||||
self.selected_sub_menu_slider.state = GaugeState::MinHover;
|
self.selected_sub_menu_slider.state = GaugeState::MinHover;
|
||||||
selected_sub_menu.slider = Some(Slider{
|
selected_sub_menu.slider = Some(Slider {
|
||||||
selected_min: self.selected_sub_menu_slider.selected_min,
|
selected_min: self.selected_sub_menu_slider.selected_min,
|
||||||
selected_max: self.selected_sub_menu_slider.selected_max,
|
selected_max: self.selected_sub_menu_slider.selected_max,
|
||||||
abs_min: self.selected_sub_menu_slider.abs_min,
|
abs_min: self.selected_sub_menu_slider.abs_min,
|
||||||
|
@ -416,7 +419,7 @@ impl<'a> App<'a> {
|
||||||
}
|
}
|
||||||
GaugeState::MaxSelected => {
|
GaugeState::MaxSelected => {
|
||||||
self.selected_sub_menu_slider.state = GaugeState::MaxHover;
|
self.selected_sub_menu_slider.state = GaugeState::MaxHover;
|
||||||
selected_sub_menu.slider = Some(Slider{
|
selected_sub_menu.slider = Some(Slider {
|
||||||
selected_min: self.selected_sub_menu_slider.selected_min,
|
selected_min: self.selected_sub_menu_slider.selected_min,
|
||||||
selected_max: self.selected_sub_menu_slider.selected_max,
|
selected_max: self.selected_sub_menu_slider.selected_max,
|
||||||
abs_min: self.selected_sub_menu_slider.abs_min,
|
abs_min: self.selected_sub_menu_slider.abs_min,
|
||||||
|
@ -434,23 +437,27 @@ impl<'a> App<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Save defaults command
|
/// Save defaults command
|
||||||
pub fn on_x(&mut self) {
|
pub fn save_defaults(&mut self) {
|
||||||
if self.page == AppPage::SUBMENU {
|
if self.page == AppPage::SUBMENU {
|
||||||
let json = self.to_json();
|
let json = self.to_json();
|
||||||
unsafe {
|
unsafe {
|
||||||
self.default_menu = (ui_menu(serde_json::from_str::<TrainingModpackMenu>(&json).unwrap()), json);
|
self.default_menu = (
|
||||||
|
ui_menu(serde_json::from_str::<TrainingModpackMenu>(&json).unwrap()),
|
||||||
|
json,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reset current submenu to defaults
|
/// Reset current submenu to defaults
|
||||||
pub fn on_l(&mut self) {
|
pub fn reset_current_submenu(&mut self) {
|
||||||
if self.page == AppPage::TOGGLE || self.page == AppPage::SLIDER {
|
if self.page == AppPage::TOGGLE || self.page == AppPage::SLIDER {
|
||||||
let json = self.to_json();
|
let json = self.to_json();
|
||||||
let mut json_value = serde_json::from_str::<serde_json::Value>(&json).unwrap();
|
let mut json_value = serde_json::from_str::<serde_json::Value>(&json).unwrap();
|
||||||
let selected_sub_menu= self.sub_menu_selected();
|
let selected_sub_menu = self.sub_menu_selected();
|
||||||
let id = selected_sub_menu.submenu_id;
|
let id = selected_sub_menu.submenu_id;
|
||||||
let default_json_value = serde_json::from_str::<serde_json::Value>(&self.default_menu.1).unwrap();
|
let default_json_value =
|
||||||
|
serde_json::from_str::<serde_json::Value>(&self.default_menu.1).unwrap();
|
||||||
*json_value.get_mut(id).unwrap() = default_json_value.get(id).unwrap().clone();
|
*json_value.get_mut(id).unwrap() = default_json_value.get(id).unwrap().clone();
|
||||||
let new_menu = serde_json::from_value::<TrainingModpackMenu>(json_value).unwrap();
|
let new_menu = serde_json::from_value::<TrainingModpackMenu>(json_value).unwrap();
|
||||||
*self = App::new(unsafe { ui_menu(new_menu) }, self.default_menu.clone());
|
*self = App::new(unsafe { ui_menu(new_menu) }, self.default_menu.clone());
|
||||||
|
@ -458,18 +465,18 @@ impl<'a> App<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reset all menus to defaults
|
/// Reset all menus to defaults
|
||||||
pub fn on_r(&mut self) {
|
pub fn reset_all_submenus(&mut self) {
|
||||||
*self = App::new(self.default_menu.0.clone(), self.default_menu.clone());
|
*self = App::new(self.default_menu.0.clone(), self.default_menu.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn on_zl(&mut self) {
|
pub fn previous_tab(&mut self) {
|
||||||
if self.page == AppPage::SUBMENU {
|
if self.page == AppPage::SUBMENU {
|
||||||
self.tabs.previous();
|
self.tabs.previous();
|
||||||
self.set_sub_menu_items();
|
self.set_sub_menu_items();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn on_zr(&mut self) {
|
pub fn next_tab(&mut self) {
|
||||||
if self.page == AppPage::SUBMENU {
|
if self.page == AppPage::SUBMENU {
|
||||||
self.tabs.next();
|
self.tabs.next();
|
||||||
self.set_sub_menu_items();
|
self.set_sub_menu_items();
|
||||||
|
@ -571,35 +578,40 @@ impl<'a> App<'a> {
|
||||||
serde_json::to_string(&settings).unwrap()
|
serde_json::to_string(&settings).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Returns the current menu selections and the default menu selections.
|
/// Returns the current menu selections and the default menu selections.
|
||||||
pub fn get_menu_selections(&self) -> String {
|
pub fn get_menu_selections(&self) -> String {
|
||||||
serde_json::to_string(
|
serde_json::to_string(&MenuJsonStruct {
|
||||||
&MenuJsonStruct {
|
|
||||||
menu: serde_json::from_str(self.to_json().as_str()).unwrap(),
|
menu: serde_json::from_str(self.to_json().as_str()).unwrap(),
|
||||||
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> {
|
pub fn submenu_ids(&self) -> Vec<&str> {
|
||||||
return self.menu_items
|
return self
|
||||||
.values()
|
.menu_items
|
||||||
.flat_map(|multi_stateful_list| {
|
.values()
|
||||||
multi_stateful_list
|
.flat_map(|multi_stateful_list| {
|
||||||
.lists
|
multi_stateful_list
|
||||||
.iter()
|
.lists
|
||||||
.flat_map(|sub_stateful_list| {
|
.iter()
|
||||||
sub_stateful_list
|
.flat_map(|sub_stateful_list| {
|
||||||
.items
|
sub_stateful_list
|
||||||
.iter()
|
.items
|
||||||
.map(|submenu| submenu.submenu_id)
|
.iter()
|
||||||
})
|
.map(|submenu| submenu.submenu_id)
|
||||||
})
|
})
|
||||||
.collect::<Vec<&str>>();
|
})
|
||||||
|
.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,
|
||||||
|
) {
|
||||||
let tab_selected = app.tab_selected();
|
let tab_selected = app.tab_selected();
|
||||||
let mut item_help = None;
|
let mut item_help = None;
|
||||||
for (list_section, stateful_list) in app
|
for (list_section, stateful_list) in app
|
||||||
|
@ -648,11 +660,16 @@ fn render_submenu_page<B: Backend>(f: &mut Frame<B>, app: &mut App, list_chunks:
|
||||||
item_help.unwrap_or("").replace('\"', "")
|
item_help.unwrap_or("").replace('\"', "")
|
||||||
+ "\nZL/ZR: Next tab | X: Save Defaults | R: Reset All Menus",
|
+ "\nZL/ZR: Next tab | X: Save Defaults | R: Reset All Menus",
|
||||||
)
|
)
|
||||||
.style(Style::default().fg(Color::Cyan));
|
.style(Style::default().fg(Color::Cyan));
|
||||||
f.render_widget(help_paragraph, help_chunk);
|
f.render_widget(help_paragraph, help_chunk);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render_toggle_page<B: Backend>(f: &mut Frame<B>, app: &mut App, list_chunks: Vec<Rect>, help_chunk: Rect) {
|
pub fn render_toggle_page<B: Backend>(
|
||||||
|
f: &mut Frame<B>,
|
||||||
|
app: &mut App,
|
||||||
|
list_chunks: Vec<Rect>,
|
||||||
|
help_chunk: Rect,
|
||||||
|
) {
|
||||||
let (title, help_text, mut sub_menu_str_lists) = app.sub_menu_strs_and_states();
|
let (title, help_text, mut sub_menu_str_lists) = app.sub_menu_strs_and_states();
|
||||||
for list_section in 0..sub_menu_str_lists.len() {
|
for list_section in 0..sub_menu_str_lists.len() {
|
||||||
let sub_menu_str = sub_menu_str_lists[list_section].0.clone();
|
let sub_menu_str = sub_menu_str_lists[list_section].0.clone();
|
||||||
|
@ -677,15 +694,17 @@ pub fn render_toggle_page<B: Backend>(f: &mut Frame<B>, app: &mut App, list_chun
|
||||||
.highlight_symbol(">> ");
|
.highlight_symbol(">> ");
|
||||||
f.render_stateful_widget(values_list, list_chunks[list_section], sub_menu_state);
|
f.render_stateful_widget(values_list, list_chunks[list_section], sub_menu_state);
|
||||||
}
|
}
|
||||||
let help_paragraph = Paragraph::new(
|
let help_paragraph = Paragraph::new(help_text.replace('\"', "") + "\nL: Reset Current Menu")
|
||||||
help_text.replace('\"', "") + "\nL: Reset Current Menu",
|
|
||||||
)
|
|
||||||
.style(Style::default().fg(Color::Cyan));
|
.style(Style::default().fg(Color::Cyan));
|
||||||
f.render_widget(help_paragraph, help_chunk);
|
f.render_widget(help_paragraph, help_chunk);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn render_slider_page<B: Backend>(
|
||||||
pub fn render_slider_page<B: Backend>(f: &mut Frame<B>, app: &mut App, vertical_chunk: Rect, help_chunk: Rect) {
|
f: &mut Frame<B>,
|
||||||
|
app: &mut App,
|
||||||
|
vertical_chunk: Rect,
|
||||||
|
help_chunk: Rect,
|
||||||
|
) {
|
||||||
let (_title, help_text, gauge_vals) = app.sub_menu_strs_for_slider();
|
let (_title, help_text, gauge_vals) = app.sub_menu_strs_for_slider();
|
||||||
let abs_min = gauge_vals.abs_min;
|
let abs_min = gauge_vals.abs_min;
|
||||||
let abs_max = gauge_vals.abs_max;
|
let abs_max = gauge_vals.abs_max;
|
||||||
|
@ -693,9 +712,18 @@ pub fn render_slider_page<B: Backend>(f: &mut Frame<B>, app: &mut App, vertical_
|
||||||
let selected_max = gauge_vals.selected_max;
|
let selected_max = gauge_vals.selected_max;
|
||||||
let lbl_ratio = 0.95; // Needed so that the upper limit label is visible
|
let lbl_ratio = 0.95; // Needed so that the upper limit label is visible
|
||||||
let constraints = [
|
let constraints = [
|
||||||
Constraint::Ratio((lbl_ratio * (selected_min-abs_min) as f32) as u32, abs_max-abs_min),
|
Constraint::Ratio(
|
||||||
Constraint::Ratio((lbl_ratio * (selected_max-selected_min) as f32) as u32, abs_max-abs_min),
|
(lbl_ratio * (selected_min - abs_min) as f32) as u32,
|
||||||
Constraint::Ratio((lbl_ratio * (abs_max-selected_max) as f32) as u32, abs_max-abs_min),
|
abs_max - abs_min,
|
||||||
|
),
|
||||||
|
Constraint::Ratio(
|
||||||
|
(lbl_ratio * (selected_max - selected_min) as f32) as u32,
|
||||||
|
abs_max - abs_min,
|
||||||
|
),
|
||||||
|
Constraint::Ratio(
|
||||||
|
(lbl_ratio * (abs_max - selected_max) as f32) as u32,
|
||||||
|
abs_max - abs_min,
|
||||||
|
),
|
||||||
Constraint::Min(3), // For upper limit label
|
Constraint::Min(3), // For upper limit label
|
||||||
];
|
];
|
||||||
let gauge_chunks = Layout::default()
|
let gauge_chunks = Layout::default()
|
||||||
|
@ -703,12 +731,7 @@ pub fn render_slider_page<B: Backend>(f: &mut Frame<B>, app: &mut App, vertical_
|
||||||
.constraints(constraints)
|
.constraints(constraints)
|
||||||
.split(vertical_chunk);
|
.split(vertical_chunk);
|
||||||
|
|
||||||
let slider_lbls = [
|
let slider_lbls = [abs_min, selected_min, selected_max, abs_max];
|
||||||
abs_min,
|
|
||||||
selected_min,
|
|
||||||
selected_max,
|
|
||||||
abs_max,
|
|
||||||
];
|
|
||||||
for (idx, lbl) in slider_lbls.iter().enumerate() {
|
for (idx, lbl) in slider_lbls.iter().enumerate() {
|
||||||
let mut line_set = tui::symbols::line::NORMAL;
|
let mut line_set = tui::symbols::line::NORMAL;
|
||||||
line_set.horizontal = "-";
|
line_set.horizontal = "-";
|
||||||
|
@ -721,24 +744,16 @@ pub fn render_slider_page<B: Backend>(f: &mut Frame<B>, app: &mut App, vertical_
|
||||||
if idx == 1 {
|
if idx == 1 {
|
||||||
// Slider between selected_min and selected_max
|
// Slider between selected_min and selected_max
|
||||||
match gauge_vals.state {
|
match gauge_vals.state {
|
||||||
GaugeState::MinHover => {
|
GaugeState::MinHover => gauge = gauge.style(Style::default().fg(Color::Red)),
|
||||||
gauge = gauge.style(Style::default().fg(Color::Red))
|
GaugeState::MinSelected => gauge = gauge.style(Style::default().fg(Color::Green)),
|
||||||
}
|
|
||||||
GaugeState::MinSelected => {
|
|
||||||
gauge = gauge.style(Style::default().fg(Color::Green))
|
|
||||||
}
|
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
gauge = gauge.gauge_style(Style::default().fg(Color::Yellow).bg(Color::Black));
|
gauge = gauge.gauge_style(Style::default().fg(Color::Yellow).bg(Color::Black));
|
||||||
} else if idx == 2 {
|
} else if idx == 2 {
|
||||||
// Slider between selected_max and abs_max
|
// Slider between selected_max and abs_max
|
||||||
match gauge_vals.state {
|
match gauge_vals.state {
|
||||||
GaugeState::MaxHover => {
|
GaugeState::MaxHover => gauge = gauge.style(Style::default().fg(Color::Red)),
|
||||||
gauge = gauge.style(Style::default().fg(Color::Red))
|
GaugeState::MaxSelected => gauge = gauge.style(Style::default().fg(Color::Green)),
|
||||||
}
|
|
||||||
GaugeState::MaxSelected => {
|
|
||||||
gauge = gauge.style(Style::default().fg(Color::Green))
|
|
||||||
}
|
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
} else if idx == 3 {
|
} else if idx == 3 {
|
||||||
|
@ -762,9 +777,7 @@ pub fn render_slider_page<B: Backend>(f: &mut Frame<B>, app: &mut App, vertical_
|
||||||
f.render_widget(gauge, gauge_chunks[idx]);
|
f.render_widget(gauge, gauge_chunks[idx]);
|
||||||
}
|
}
|
||||||
|
|
||||||
let help_paragraph = Paragraph::new(
|
let help_paragraph = Paragraph::new(help_text.replace('\"', "") + "\nL: Reset Current Menu")
|
||||||
help_text.replace('\"', "") + "\nL: Reset Current Menu",
|
|
||||||
)
|
|
||||||
.style(Style::default().fg(Color::Cyan));
|
.style(Style::default().fg(Color::Cyan));
|
||||||
f.render_widget(help_paragraph, help_chunk);
|
f.render_widget(help_paragraph, help_chunk);
|
||||||
}
|
}
|
||||||
|
@ -846,22 +859,20 @@ pub fn ui<B: Backend>(f: &mut Frame<B>, app: &mut App) {
|
||||||
// is not publicly exposed, and the attribute defaults to true.
|
// is not publicly exposed, and the attribute defaults to true.
|
||||||
// https://github.com/fdehau/tui-rs/blob/v0.19.0/src/layout.rs#L121
|
// https://github.com/fdehau/tui-rs/blob/v0.19.0/src/layout.rs#L121
|
||||||
let vertical_chunks: Vec<Rect> = vertical_chunks
|
let vertical_chunks: Vec<Rect> = vertical_chunks
|
||||||
.iter()
|
.iter()
|
||||||
.map(|chunk| {
|
.map(|chunk| {
|
||||||
Layout::default()
|
Layout::default()
|
||||||
.direction(Direction::Horizontal)
|
.direction(Direction::Horizontal)
|
||||||
.constraints(
|
.constraints(
|
||||||
[
|
[
|
||||||
Constraint::Length(NX_TUI_WIDTH), // Width of the TUI terminal
|
Constraint::Length(NX_TUI_WIDTH), // Width of the TUI terminal
|
||||||
Constraint::Min(0), // Fill the remainder margin
|
Constraint::Min(0), // Fill the remainder margin
|
||||||
]
|
]
|
||||||
.as_ref(),
|
.as_ref(),
|
||||||
)
|
)
|
||||||
.split(*chunk)[0]
|
.split(*chunk)[0]
|
||||||
}
|
})
|
||||||
)
|
.collect();
|
||||||
.collect();
|
|
||||||
|
|
||||||
|
|
||||||
let list_chunks = Layout::default()
|
let list_chunks = Layout::default()
|
||||||
.direction(Direction::Horizontal)
|
.direction(Direction::Horizontal)
|
||||||
|
@ -881,6 +892,6 @@ pub fn ui<B: Backend>(f: &mut Frame<B>, app: &mut App) {
|
||||||
AppPage::SUBMENU => render_submenu_page(f, app, list_chunks, vertical_chunks[2]),
|
AppPage::SUBMENU => render_submenu_page(f, app, list_chunks, vertical_chunks[2]),
|
||||||
AppPage::SLIDER => render_slider_page(f, app, vertical_chunks[1], vertical_chunks[2]),
|
AppPage::SLIDER => render_slider_page(f, app, vertical_chunks[1], vertical_chunks[2]),
|
||||||
AppPage::TOGGLE => render_toggle_page(f, app, list_chunks, vertical_chunks[2]),
|
AppPage::TOGGLE => render_toggle_page(f, app, list_chunks, vertical_chunks[2]),
|
||||||
AppPage::CONFIRMATION => todo!()
|
AppPage::CONFIRMATION => todo!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,21 +5,28 @@ use crossterm::{
|
||||||
terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
|
terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(feature = "has_terminal")]
|
use std::error::Error;
|
||||||
use tui::backend::CrosstermBackend;
|
|
||||||
#[cfg(feature = "has_terminal")]
|
#[cfg(feature = "has_terminal")]
|
||||||
use std::{
|
use std::{
|
||||||
io,
|
io,
|
||||||
time::{Duration, Instant},
|
time::{Duration, Instant},
|
||||||
};
|
};
|
||||||
use std::error::Error;
|
#[cfg(feature = "has_terminal")]
|
||||||
|
use tui::backend::CrosstermBackend;
|
||||||
use tui::Terminal;
|
use tui::Terminal;
|
||||||
|
|
||||||
use training_mod_consts::*;
|
use training_mod_consts::*;
|
||||||
|
|
||||||
fn test_backend_setup<'a>(ui_menu: UiMenu<'a>, menu_defaults: (UiMenu<'a>, String)) -> Result<
|
fn test_backend_setup<'a>(
|
||||||
(Terminal<training_mod_tui::TestBackend>, training_mod_tui::App<'a>),
|
ui_menu: UiMenu<'a>,
|
||||||
Box<dyn Error>> {
|
menu_defaults: (UiMenu<'a>, String),
|
||||||
|
) -> Result<
|
||||||
|
(
|
||||||
|
Terminal<training_mod_tui::TestBackend>,
|
||||||
|
training_mod_tui::App<'a>,
|
||||||
|
),
|
||||||
|
Box<dyn Error>,
|
||||||
|
> {
|
||||||
let app = training_mod_tui::App::<'a>::new(ui_menu, menu_defaults);
|
let app = training_mod_tui::App::<'a>::new(ui_menu, menu_defaults);
|
||||||
let backend = tui::backend::TestBackend::new(75, 15);
|
let backend = tui::backend::TestBackend::new(75, 15);
|
||||||
let terminal = Terminal::new(backend)?;
|
let terminal = Terminal::new(backend)?;
|
||||||
|
@ -103,7 +110,7 @@ fn test_save_and_reset_defaults() -> Result<(), Box<dyn Error>> {
|
||||||
// Return to submenu selection
|
// Return to submenu selection
|
||||||
app.on_b();
|
app.on_b();
|
||||||
// Save Defaults
|
// Save Defaults
|
||||||
app.on_x();
|
app.save_defaults();
|
||||||
// Enter Mash Toggles again
|
// Enter Mash Toggles again
|
||||||
app.on_a();
|
app.on_a();
|
||||||
// Unset Mash Airdodge
|
// Unset Mash Airdodge
|
||||||
|
@ -127,7 +134,7 @@ fn test_save_and_reset_defaults() -> Result<(), Box<dyn Error>> {
|
||||||
);
|
);
|
||||||
|
|
||||||
// Reset current menu alone to defaults
|
// Reset current menu alone to defaults
|
||||||
app.on_l();
|
app.reset_current_submenu();
|
||||||
let menu_json = app.get_menu_selections();
|
let menu_json = app.get_menu_selections();
|
||||||
let menu_struct = serde_json::from_str::<MenuJsonStruct>(&menu_json).unwrap();
|
let menu_struct = serde_json::from_str::<MenuJsonStruct>(&menu_json).unwrap();
|
||||||
let menu = menu_struct.menu;
|
let menu = menu_struct.menu;
|
||||||
|
@ -155,7 +162,7 @@ fn test_save_and_reset_defaults() -> Result<(), Box<dyn Error>> {
|
||||||
// Return to submenu selection
|
// Return to submenu selection
|
||||||
app.on_b();
|
app.on_b();
|
||||||
// Save defaults
|
// Save defaults
|
||||||
app.on_x();
|
app.save_defaults();
|
||||||
// Go back in and unset Jump
|
// Go back in and unset Jump
|
||||||
app.on_a();
|
app.on_a();
|
||||||
app.on_down();
|
app.on_down();
|
||||||
|
@ -163,7 +170,7 @@ fn test_save_and_reset_defaults() -> Result<(), Box<dyn Error>> {
|
||||||
// Return to submenu selection
|
// Return to submenu selection
|
||||||
app.on_b();
|
app.on_b();
|
||||||
// Reset all to defaults
|
// Reset all to defaults
|
||||||
app.on_r();
|
app.reset_all_submenus();
|
||||||
let menu_json = app.get_menu_selections();
|
let menu_json = app.get_menu_selections();
|
||||||
let menu_struct = serde_json::from_str::<MenuJsonStruct>(&menu_json).unwrap();
|
let menu_struct = serde_json::from_str::<MenuJsonStruct>(&menu_json).unwrap();
|
||||||
let menu = menu_struct.menu;
|
let menu = menu_struct.menu;
|
||||||
|
@ -177,7 +184,6 @@ fn test_save_and_reset_defaults() -> Result<(), Box<dyn Error>> {
|
||||||
"The menu should have Mash Airdodge off and Followup Jump on"
|
"The menu should have Mash Airdodge off and Followup Jump on"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -192,16 +198,19 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||||
menu_defaults = (ui_menu(MENU), serde_json::to_string(&MENU).unwrap());
|
menu_defaults = (ui_menu(MENU), serde_json::to_string(&MENU).unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "has_terminal"))] {
|
#[cfg(not(feature = "has_terminal"))]
|
||||||
|
{
|
||||||
let (mut terminal, mut app) = test_backend_setup(menu, menu_defaults)?;
|
let (mut terminal, mut app) = test_backend_setup(menu, menu_defaults)?;
|
||||||
if inputs.is_some() {
|
if inputs.is_some() {
|
||||||
inputs.unwrap().split(",").for_each(|input| {
|
inputs
|
||||||
match input.to_uppercase().as_str() {
|
.unwrap()
|
||||||
"X" => app.on_x(),
|
.split(",")
|
||||||
"L" => app.on_l(),
|
.for_each(|input| match input.to_uppercase().as_str() {
|
||||||
"R" => app.on_r(),
|
"X" => app.save_defaults(),
|
||||||
"O" => app.on_zl(),
|
"Y" => app.reset_current_submenu(),
|
||||||
"P" => app.on_zr(),
|
"Z" => app.reset_all_submenus(),
|
||||||
|
"L" => app.previous_tab(),
|
||||||
|
"R" => app.next_tab(),
|
||||||
"A" => app.on_a(),
|
"A" => app.on_a(),
|
||||||
"B" => app.on_b(),
|
"B" => app.on_b(),
|
||||||
"UP" => app.on_up(),
|
"UP" => app.on_up(),
|
||||||
|
@ -209,8 +218,7 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||||
"LEFT" => app.on_left(),
|
"LEFT" => app.on_left(),
|
||||||
"RIGHT" => app.on_right(),
|
"RIGHT" => app.on_right(),
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
})
|
||||||
})
|
|
||||||
}
|
}
|
||||||
let frame_res = terminal.draw(|f| training_mod_tui::ui(f, &mut app))?;
|
let frame_res = terminal.draw(|f| training_mod_tui::ui(f, &mut app))?;
|
||||||
let menu_json = app.get_menu_selections();
|
let menu_json = app.get_menu_selections();
|
||||||
|
@ -226,7 +234,8 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||||
println!("Menu:\n{menu_json}");
|
println!("Menu:\n{menu_json}");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "has_terminal")] {
|
#[cfg(feature = "has_terminal")]
|
||||||
|
{
|
||||||
let app = training_mod_tui::App::new(menu, menu_defaults);
|
let app = training_mod_tui::App::new(menu, menu_defaults);
|
||||||
|
|
||||||
// setup terminal
|
// setup terminal
|
||||||
|
@ -281,11 +290,11 @@ fn run_app<B: tui::backend::Backend>(
|
||||||
if let Event::Key(key) = event::read()? {
|
if let Event::Key(key) = event::read()? {
|
||||||
match key.code {
|
match key.code {
|
||||||
KeyCode::Char('q') => return Ok(menu_json),
|
KeyCode::Char('q') => return Ok(menu_json),
|
||||||
KeyCode::Char('x') => app.on_x(),
|
KeyCode::Char('x') => app.save_defaults(),
|
||||||
KeyCode::Char('p') => app.on_zr(),
|
KeyCode::Char('p') => app.reset_current_submenu(),
|
||||||
KeyCode::Char('o') => app.on_zl(),
|
KeyCode::Char('o') => app.reset_all_submenus(),
|
||||||
KeyCode::Char('r') => app.on_r(),
|
KeyCode::Char('r') => app.next_tab(),
|
||||||
KeyCode::Char('l') => app.on_l(),
|
KeyCode::Char('l') => app.previous_tab(),
|
||||||
KeyCode::Left => app.on_left(),
|
KeyCode::Left => app.on_left(),
|
||||||
KeyCode::Right => app.on_right(),
|
KeyCode::Right => app.on_right(),
|
||||||
KeyCode::Down => app.on_down(),
|
KeyCode::Down => app.on_down(),
|
||||||
|
|
Loading…
Reference in a new issue