mirror of
https://github.com/doukutsu-rs/doukutsu-rs
synced 2025-03-23 18:39:20 +00:00
refactor menus to use enums instead of indices
This commit is contained in:
parent
4a6b2c4400
commit
ef040a393c
|
@ -10,10 +10,38 @@ pub enum CurrentMenu {
|
|||
PlayerSkin,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
|
||||
pub enum CoopMenuEntry {
|
||||
Title,
|
||||
One,
|
||||
Two,
|
||||
Back,
|
||||
}
|
||||
|
||||
impl Default for CoopMenuEntry {
|
||||
fn default() -> Self {
|
||||
CoopMenuEntry::One
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
|
||||
pub enum SkinMenuEntry {
|
||||
Title,
|
||||
Skin,
|
||||
Start,
|
||||
Back,
|
||||
}
|
||||
|
||||
impl Default for SkinMenuEntry {
|
||||
fn default() -> Self {
|
||||
SkinMenuEntry::Skin
|
||||
}
|
||||
}
|
||||
|
||||
pub struct PlayerCountMenu {
|
||||
current_menu: CurrentMenu,
|
||||
coop_menu: Menu,
|
||||
skin_menu: Menu,
|
||||
coop_menu: Menu<CoopMenuEntry>,
|
||||
skin_menu: Menu<SkinMenuEntry>,
|
||||
}
|
||||
|
||||
impl PlayerCountMenu {
|
||||
|
@ -28,18 +56,19 @@ impl PlayerCountMenu {
|
|||
self.coop_menu = Menu::new(0, 0, 130, 0);
|
||||
self.skin_menu = Menu::new(0, 0, 130, 0);
|
||||
|
||||
self.coop_menu.push_entry(MenuEntry::Disabled(state.t("menus.coop_menu.title")));
|
||||
self.coop_menu.push_entry(MenuEntry::Active(state.t("menus.coop_menu.one")));
|
||||
self.coop_menu.push_entry(MenuEntry::Active(state.t("menus.coop_menu.two")));
|
||||
self.coop_menu.push_entry(MenuEntry::Active(state.t("common.back")));
|
||||
self.coop_menu.push_entry(CoopMenuEntry::Title, MenuEntry::Disabled(state.t("menus.coop_menu.title")));
|
||||
self.coop_menu.push_entry(CoopMenuEntry::One, MenuEntry::Active(state.t("menus.coop_menu.one")));
|
||||
self.coop_menu.push_entry(CoopMenuEntry::Two, MenuEntry::Active(state.t("menus.coop_menu.two")));
|
||||
self.coop_menu.push_entry(CoopMenuEntry::Back, MenuEntry::Active(state.t("common.back")));
|
||||
|
||||
self.coop_menu.selected = 1;
|
||||
self.coop_menu.selected = CoopMenuEntry::One;
|
||||
|
||||
self.skin_menu.push_entry(MenuEntry::Disabled(state.t("menus.skin_menu.title")));
|
||||
self.skin_menu.push_entry(MenuEntry::PlayerSkin);
|
||||
self.skin_menu.push_entry(MenuEntry::Active(state.t("menus.main_menu.start")));
|
||||
self.skin_menu.push_entry(MenuEntry::Active(state.t("common.back")));
|
||||
self.skin_menu.selected = 1;
|
||||
self.skin_menu.push_entry(SkinMenuEntry::Title, MenuEntry::Disabled(state.t("menus.skin_menu.title")));
|
||||
self.skin_menu.push_entry(SkinMenuEntry::Skin, MenuEntry::PlayerSkin);
|
||||
self.skin_menu.push_entry(SkinMenuEntry::Start, MenuEntry::Active(state.t("menus.main_menu.start")));
|
||||
self.skin_menu.push_entry(SkinMenuEntry::Back, MenuEntry::Active(state.t("common.back")));
|
||||
|
||||
self.skin_menu.selected = SkinMenuEntry::Skin;
|
||||
|
||||
self.update_sizes(state);
|
||||
|
||||
|
@ -68,13 +97,13 @@ impl PlayerCountMenu {
|
|||
self.update_sizes(state);
|
||||
match self.current_menu {
|
||||
CurrentMenu::CoopMenu => match self.coop_menu.tick(controller, state) {
|
||||
MenuSelectionResult::Selected(3, _) | MenuSelectionResult::Canceled => exit_action(),
|
||||
MenuSelectionResult::Selected(1, _) => {
|
||||
MenuSelectionResult::Selected(CoopMenuEntry::Back, _) | MenuSelectionResult::Canceled => exit_action(),
|
||||
MenuSelectionResult::Selected(CoopMenuEntry::One, _) => {
|
||||
state.player_count = PlayerCount::One;
|
||||
state.reload_resources(ctx)?;
|
||||
state.load_or_start_game(ctx)?;
|
||||
}
|
||||
MenuSelectionResult::Selected(2, _) => {
|
||||
MenuSelectionResult::Selected(CoopMenuEntry::Two, _) => {
|
||||
if state.constants.is_cs_plus {
|
||||
self.current_menu = CurrentMenu::PlayerSkin;
|
||||
} else {
|
||||
|
@ -86,13 +115,13 @@ impl PlayerCountMenu {
|
|||
_ => (),
|
||||
},
|
||||
CurrentMenu::PlayerSkin => match self.skin_menu.tick(controller, state) {
|
||||
MenuSelectionResult::Selected(3, _) | MenuSelectionResult::Canceled => {
|
||||
MenuSelectionResult::Selected(SkinMenuEntry::Back, _) | MenuSelectionResult::Canceled => {
|
||||
self.current_menu = CurrentMenu::CoopMenu;
|
||||
}
|
||||
MenuSelectionResult::Selected(1, _) => {
|
||||
MenuSelectionResult::Selected(SkinMenuEntry::Skin, _) => {
|
||||
state.player2_skin += 2;
|
||||
}
|
||||
MenuSelectionResult::Selected(2, _) => {
|
||||
MenuSelectionResult::Selected(SkinMenuEntry::Start, _) => {
|
||||
state.player_count = PlayerCount::Two;
|
||||
state.reload_resources(ctx)?;
|
||||
state.load_or_start_game(ctx)?;
|
||||
|
|
|
@ -9,10 +9,10 @@ use crate::input::combined_menu_controller::CombinedMenuController;
|
|||
use crate::menu::save_select_menu::MenuSaveInfo;
|
||||
use crate::shared_game_state::{GameDifficulty, MenuCharacter, SharedGameState};
|
||||
|
||||
pub mod coop_menu;
|
||||
pub mod pause_menu;
|
||||
pub mod save_select_menu;
|
||||
pub mod settings_menu;
|
||||
pub mod coop_menu;
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Clone)]
|
||||
|
@ -62,40 +62,40 @@ impl MenuEntry {
|
|||
MenuEntry::SaveData(_) => true,
|
||||
MenuEntry::SaveDataSingle(_) => true,
|
||||
MenuEntry::NewSave => true,
|
||||
MenuEntry::PlayerSkin=> true,
|
||||
MenuEntry::PlayerSkin => true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub enum MenuSelectionResult<'a> {
|
||||
pub enum MenuSelectionResult<'a, T: std::cmp::PartialEq> {
|
||||
None,
|
||||
Canceled,
|
||||
Selected(usize, &'a mut MenuEntry),
|
||||
Left(usize, &'a mut MenuEntry, i16),
|
||||
Right(usize, &'a mut MenuEntry, i16),
|
||||
Selected(T, &'a mut MenuEntry),
|
||||
Left(T, &'a mut MenuEntry, i16),
|
||||
Right(T, &'a mut MenuEntry, i16),
|
||||
}
|
||||
|
||||
pub struct Menu {
|
||||
pub struct Menu<T: std::cmp::PartialEq> {
|
||||
pub x: isize,
|
||||
pub y: isize,
|
||||
pub width: u16,
|
||||
pub height: u16,
|
||||
pub selected: usize,
|
||||
pub entries: Vec<MenuEntry>,
|
||||
pub selected: T,
|
||||
pub entries: Vec<(T, MenuEntry)>,
|
||||
anim_num: u16,
|
||||
anim_wait: u16,
|
||||
custom_cursor: Cell<bool>,
|
||||
pub draw_cursor: bool,
|
||||
}
|
||||
|
||||
impl Menu {
|
||||
pub fn new(x: isize, y: isize, width: u16, height: u16) -> Menu {
|
||||
impl<T: std::cmp::PartialEq + std::default::Default + Copy> Menu<T> {
|
||||
pub fn new(x: isize, y: isize, width: u16, height: u16) -> Menu<T> {
|
||||
Menu {
|
||||
x,
|
||||
y,
|
||||
width,
|
||||
height,
|
||||
selected: 0,
|
||||
selected: T::default(),
|
||||
anim_num: 0,
|
||||
anim_wait: 0,
|
||||
entries: Vec::new(),
|
||||
|
@ -104,14 +104,23 @@ impl Menu {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn push_entry(&mut self, entry: MenuEntry) {
|
||||
self.entries.push(entry);
|
||||
pub fn push_entry(&mut self, id: T, entry: MenuEntry) {
|
||||
self.entries.push((id, entry));
|
||||
}
|
||||
|
||||
pub fn set_entry(&mut self, id: T, entry: MenuEntry) {
|
||||
for i in 0..self.entries.len() {
|
||||
if self.entries[i].0 == id {
|
||||
self.entries[i].1 = entry;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update_width(&mut self, state: &SharedGameState) {
|
||||
let mut width = self.width as f32;
|
||||
|
||||
for entry in &self.entries {
|
||||
for (_, entry) in &self.entries {
|
||||
match entry {
|
||||
MenuEntry::Hidden => {}
|
||||
MenuEntry::Active(entry) | MenuEntry::DisabledWhite(entry) | MenuEntry::Disabled(entry) => {
|
||||
|
@ -176,7 +185,7 @@ impl Menu {
|
|||
pub fn update_height(&mut self) {
|
||||
let mut height = 8.0;
|
||||
|
||||
for entry in &self.entries {
|
||||
for (_, entry) in &self.entries {
|
||||
height += entry.height();
|
||||
}
|
||||
|
||||
|
@ -281,7 +290,17 @@ impl Menu {
|
|||
let mut entry_y = 0;
|
||||
|
||||
if !self.entries.is_empty() {
|
||||
entry_y = self.entries[0..(self.selected)].iter().map(|e| e.height()).sum::<f64>().max(0.0) as u16;
|
||||
let mut sum = 0.0;
|
||||
|
||||
for (id, entry) in &self.entries {
|
||||
if *id == self.selected {
|
||||
break;
|
||||
}
|
||||
|
||||
sum += entry.height();
|
||||
}
|
||||
|
||||
entry_y = sum as u16;
|
||||
}
|
||||
|
||||
if self.draw_cursor {
|
||||
|
@ -340,7 +359,7 @@ impl Menu {
|
|||
}
|
||||
|
||||
y = self.y as f32 + 8.0;
|
||||
for entry in &self.entries {
|
||||
for (_, entry) in &self.entries {
|
||||
match entry {
|
||||
MenuEntry::Active(name) | MenuEntry::DisabledWhite(name) => {
|
||||
state.font.draw_text(
|
||||
|
@ -512,7 +531,7 @@ impl Menu {
|
|||
y - 4.0,
|
||||
&Rect::new_size(0, (state.player2_skin).saturating_mul(2 * 16), 16, 16),
|
||||
);
|
||||
batch.draw(ctx)?;
|
||||
batch.draw(ctx)?;
|
||||
}
|
||||
MenuEntry::SaveData(save) | MenuEntry::SaveDataSingle(save) => {
|
||||
let name = &state.stages[save.current_map as usize].name;
|
||||
|
@ -597,7 +616,7 @@ impl Menu {
|
|||
&mut self,
|
||||
controller: &mut CombinedMenuController,
|
||||
state: &mut SharedGameState,
|
||||
) -> MenuSelectionResult {
|
||||
) -> MenuSelectionResult<T> {
|
||||
if controller.trigger_back() {
|
||||
state.sound_manager.play_sfx(5);
|
||||
return MenuSelectionResult::Canceled;
|
||||
|
@ -605,21 +624,25 @@ impl Menu {
|
|||
|
||||
if (controller.trigger_up() || controller.trigger_down()) && !self.entries.is_empty() {
|
||||
state.sound_manager.play_sfx(1);
|
||||
|
||||
let mut selected = self.entries.iter().position(|(idx, _)| *idx == self.selected).ok_or(0).unwrap();
|
||||
|
||||
loop {
|
||||
if controller.trigger_down() {
|
||||
self.selected += 1;
|
||||
if self.selected == self.entries.len() {
|
||||
self.selected = 0;
|
||||
selected += 1;
|
||||
if selected == self.entries.len() {
|
||||
selected = 0;
|
||||
}
|
||||
} else {
|
||||
if self.selected == 0 {
|
||||
self.selected = self.entries.len();
|
||||
if selected == 0 {
|
||||
selected = self.entries.len();
|
||||
}
|
||||
self.selected -= 1;
|
||||
selected -= 1;
|
||||
}
|
||||
|
||||
if let Some(entry) = self.entries.get(self.selected) {
|
||||
if let Some((id, entry)) = self.entries.get(selected) {
|
||||
if entry.selectable() {
|
||||
self.selected = *id;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
|
@ -629,7 +652,8 @@ impl Menu {
|
|||
}
|
||||
|
||||
let mut y = self.y as f32 + 8.0;
|
||||
for (idx, entry) in self.entries.iter_mut().enumerate() {
|
||||
for (id, entry) in self.entries.iter_mut() {
|
||||
let idx = *id;
|
||||
let entry_bounds = Rect::new_size(self.x, y as isize, self.width as isize, entry.height() as isize);
|
||||
let right_entry_bounds =
|
||||
Rect::new_size(self.x + self.width as isize, y as isize, self.width as isize, entry.height() as isize);
|
||||
|
|
|
@ -19,13 +19,41 @@ enum CurrentMenu {
|
|||
ConfirmMenu,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
|
||||
enum PauseMenuEntry {
|
||||
Resume,
|
||||
Retry,
|
||||
Options,
|
||||
Title,
|
||||
Quit,
|
||||
}
|
||||
|
||||
impl Default for PauseMenuEntry {
|
||||
fn default() -> Self {
|
||||
PauseMenuEntry::Resume
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
|
||||
enum ConfirmMenuEntry {
|
||||
Empty,
|
||||
Yes,
|
||||
No,
|
||||
}
|
||||
|
||||
impl Default for ConfirmMenuEntry {
|
||||
fn default() -> Self {
|
||||
ConfirmMenuEntry::Yes
|
||||
}
|
||||
}
|
||||
|
||||
pub struct PauseMenu {
|
||||
is_paused: bool,
|
||||
current_menu: CurrentMenu,
|
||||
settings_menu: SettingsMenu,
|
||||
controller: CombinedMenuController,
|
||||
pause_menu: Menu,
|
||||
confirm_menu: Menu,
|
||||
pause_menu: Menu<PauseMenuEntry>,
|
||||
confirm_menu: Menu<ConfirmMenuEntry>,
|
||||
tick: u32,
|
||||
}
|
||||
|
||||
|
@ -48,17 +76,17 @@ impl PauseMenu {
|
|||
self.controller.add(state.settings.create_player1_controller());
|
||||
self.controller.add(state.settings.create_player2_controller());
|
||||
|
||||
self.pause_menu.push_entry(MenuEntry::Active(state.t("menus.pause_menu.resume")));
|
||||
self.pause_menu.push_entry(MenuEntry::Active(state.t("menus.pause_menu.retry")));
|
||||
self.pause_menu.push_entry(MenuEntry::Active(state.t("menus.pause_menu.options")));
|
||||
self.pause_menu.push_entry(MenuEntry::Active(state.t("menus.pause_menu.title")));
|
||||
self.pause_menu.push_entry(MenuEntry::Active(state.t("menus.pause_menu.quit")));
|
||||
self.pause_menu.push_entry(PauseMenuEntry::Resume, MenuEntry::Active(state.t("menus.pause_menu.resume")));
|
||||
self.pause_menu.push_entry(PauseMenuEntry::Retry, MenuEntry::Active(state.t("menus.pause_menu.retry")));
|
||||
self.pause_menu.push_entry(PauseMenuEntry::Options, MenuEntry::Active(state.t("menus.pause_menu.options")));
|
||||
self.pause_menu.push_entry(PauseMenuEntry::Title, MenuEntry::Active(state.t("menus.pause_menu.title")));
|
||||
self.pause_menu.push_entry(PauseMenuEntry::Quit, MenuEntry::Active(state.t("menus.pause_menu.quit")));
|
||||
|
||||
self.confirm_menu.push_entry(MenuEntry::Disabled("".to_owned()));
|
||||
self.confirm_menu.push_entry(MenuEntry::Active(state.t("common.yes")));
|
||||
self.confirm_menu.push_entry(MenuEntry::Active(state.t("common.no")));
|
||||
self.confirm_menu.push_entry(ConfirmMenuEntry::Empty, MenuEntry::Disabled("".to_owned()));
|
||||
self.confirm_menu.push_entry(ConfirmMenuEntry::Yes, MenuEntry::Active(state.t("common.yes")));
|
||||
self.confirm_menu.push_entry(ConfirmMenuEntry::No, MenuEntry::Active(state.t("common.no")));
|
||||
|
||||
self.confirm_menu.selected = 1;
|
||||
self.confirm_menu.selected = ConfirmMenuEntry::Yes;
|
||||
|
||||
self.update_sizes(state);
|
||||
|
||||
|
@ -108,27 +136,33 @@ impl PauseMenu {
|
|||
|
||||
match self.current_menu {
|
||||
CurrentMenu::PauseMenu => match self.pause_menu.tick(&mut self.controller, state) {
|
||||
MenuSelectionResult::Selected(0, _) | MenuSelectionResult::Canceled => {
|
||||
MenuSelectionResult::Selected(PauseMenuEntry::Resume, _) | MenuSelectionResult::Canceled => {
|
||||
// double tap prevention
|
||||
if self.tick >= 3 {
|
||||
self.tick = 0;
|
||||
self.is_paused = false;
|
||||
}
|
||||
}
|
||||
MenuSelectionResult::Selected(1, _) => {
|
||||
MenuSelectionResult::Selected(PauseMenuEntry::Retry, _) => {
|
||||
state.stop_noise();
|
||||
state.sound_manager.play_song(0, &state.constants, &state.settings, ctx)?;
|
||||
state.load_or_start_game(ctx)?;
|
||||
}
|
||||
MenuSelectionResult::Selected(2, _) => {
|
||||
MenuSelectionResult::Selected(PauseMenuEntry::Options, _) => {
|
||||
self.current_menu = CurrentMenu::OptionsMenu;
|
||||
}
|
||||
MenuSelectionResult::Selected(3, _) => {
|
||||
self.confirm_menu.entries[0] = MenuEntry::Disabled(state.t("menus.pause_menu.title_confirm"));
|
||||
MenuSelectionResult::Selected(PauseMenuEntry::Title, _) => {
|
||||
self.confirm_menu.set_entry(
|
||||
ConfirmMenuEntry::Empty,
|
||||
MenuEntry::Disabled(state.t("menus.pause_menu.title_confirm")),
|
||||
);
|
||||
self.current_menu = CurrentMenu::ConfirmMenu;
|
||||
}
|
||||
MenuSelectionResult::Selected(4, _) => {
|
||||
self.confirm_menu.entries[0] = MenuEntry::Disabled(state.t("menus.pause_menu.quit_confirm"));
|
||||
MenuSelectionResult::Selected(PauseMenuEntry::Quit, _) => {
|
||||
self.confirm_menu.set_entry(
|
||||
ConfirmMenuEntry::Empty,
|
||||
MenuEntry::Disabled(state.t("menus.pause_menu.quit_confirm")),
|
||||
);
|
||||
self.current_menu = CurrentMenu::ConfirmMenu;
|
||||
}
|
||||
_ => (),
|
||||
|
@ -145,18 +179,18 @@ impl PauseMenu {
|
|||
)?;
|
||||
}
|
||||
CurrentMenu::ConfirmMenu => match self.confirm_menu.tick(&mut self.controller, state) {
|
||||
MenuSelectionResult::Selected(1, _) => match self.pause_menu.selected {
|
||||
3 => {
|
||||
MenuSelectionResult::Selected(ConfirmMenuEntry::Yes, _) => match self.pause_menu.selected {
|
||||
PauseMenuEntry::Title => {
|
||||
state.stop_noise();
|
||||
state.textscript_vm.flags.set_cutscene_skip(false);
|
||||
state.next_scene = Some(Box::new(TitleScene::new()));
|
||||
}
|
||||
4 => {
|
||||
PauseMenuEntry::Quit => {
|
||||
state.shutdown();
|
||||
}
|
||||
_ => (),
|
||||
},
|
||||
MenuSelectionResult::Selected(2, _) | MenuSelectionResult::Canceled => {
|
||||
MenuSelectionResult::Selected(ConfirmMenuEntry::No, _) | MenuSelectionResult::Canceled => {
|
||||
self.current_menu = CurrentMenu::PauseMenu;
|
||||
}
|
||||
_ => (),
|
||||
|
|
|
@ -33,15 +33,68 @@ pub enum CurrentMenu {
|
|||
DeleteConfirm,
|
||||
LoadConfirm,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
|
||||
pub enum SaveMenuEntry {
|
||||
Load(usize),
|
||||
New(usize),
|
||||
Back,
|
||||
}
|
||||
|
||||
impl Default for SaveMenuEntry {
|
||||
fn default() -> Self {
|
||||
SaveMenuEntry::Load(0)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
|
||||
pub enum DifficultyMenuEntry {
|
||||
Title,
|
||||
Difficulty(GameDifficulty),
|
||||
Back,
|
||||
}
|
||||
|
||||
impl Default for DifficultyMenuEntry {
|
||||
fn default() -> Self {
|
||||
DifficultyMenuEntry::Difficulty(GameDifficulty::Normal)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
|
||||
pub enum DeleteConfirmMenuEntry {
|
||||
Title,
|
||||
Yes,
|
||||
No,
|
||||
}
|
||||
|
||||
impl Default for DeleteConfirmMenuEntry {
|
||||
fn default() -> Self {
|
||||
DeleteConfirmMenuEntry::No
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
|
||||
pub enum LoadConfirmMenuEntry {
|
||||
Start,
|
||||
Delete,
|
||||
Back,
|
||||
}
|
||||
|
||||
impl Default for LoadConfirmMenuEntry {
|
||||
fn default() -> Self {
|
||||
LoadConfirmMenuEntry::Start
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SaveSelectMenu {
|
||||
pub saves: [MenuSaveInfo; 3],
|
||||
current_menu: CurrentMenu,
|
||||
save_menu: Menu,
|
||||
save_detailed: Menu,
|
||||
difficulty_menu: Menu,
|
||||
save_menu: Menu<SaveMenuEntry>,
|
||||
save_detailed: Menu<usize>,
|
||||
difficulty_menu: Menu<DifficultyMenuEntry>,
|
||||
coop_menu: PlayerCountMenu,
|
||||
delete_confirm: Menu,
|
||||
load_confirm: Menu,
|
||||
delete_confirm: Menu<DeleteConfirmMenuEntry>,
|
||||
load_confirm: Menu<LoadConfirmMenuEntry>,
|
||||
skip_difficulty_menu: bool,
|
||||
}
|
||||
|
||||
|
@ -69,6 +122,8 @@ impl SaveSelectMenu {
|
|||
self.load_confirm = Menu::new(0, 0, 75, 0);
|
||||
self.skip_difficulty_menu = false;
|
||||
|
||||
let mut should_mutate_selection = true;
|
||||
|
||||
for (iter, save) in self.saves.iter_mut().enumerate() {
|
||||
if let Ok(data) = filesystem::user_open(ctx, state.get_save_filename(iter + 1).unwrap_or("".to_string())) {
|
||||
let loaded_save = GameProfile::load_from_save(data)?;
|
||||
|
@ -80,38 +135,60 @@ impl SaveSelectMenu {
|
|||
save.weapon_id = loaded_save.weapon_data.map(|weapon| weapon.weapon_id);
|
||||
save.difficulty = loaded_save.difficulty;
|
||||
|
||||
self.save_menu.push_entry(MenuEntry::SaveData(*save));
|
||||
self.save_menu.push_entry(SaveMenuEntry::Load(iter), MenuEntry::SaveData(*save));
|
||||
|
||||
if should_mutate_selection {
|
||||
should_mutate_selection = false;
|
||||
self.save_menu.selected = SaveMenuEntry::Load(iter);
|
||||
}
|
||||
} else {
|
||||
self.save_menu.push_entry(MenuEntry::NewSave);
|
||||
self.save_menu.push_entry(SaveMenuEntry::New(iter), MenuEntry::NewSave);
|
||||
|
||||
if should_mutate_selection {
|
||||
should_mutate_selection = false;
|
||||
self.save_menu.selected = SaveMenuEntry::New(iter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.save_menu.push_entry(MenuEntry::Active(state.t("common.back")));
|
||||
self.save_menu.push_entry(SaveMenuEntry::Back, MenuEntry::Active(state.t("common.back")));
|
||||
|
||||
self.difficulty_menu.push_entry(MenuEntry::Disabled(state.t("menus.difficulty_menu.title")));
|
||||
self.difficulty_menu.push_entry(MenuEntry::Active(state.t("menus.difficulty_menu.easy")));
|
||||
self.difficulty_menu.push_entry(MenuEntry::Active(state.t("menus.difficulty_menu.normal")));
|
||||
self.difficulty_menu.push_entry(MenuEntry::Active(state.t("menus.difficulty_menu.hard")));
|
||||
self.difficulty_menu.push_entry(MenuEntry::Active(state.t("common.back")));
|
||||
self.difficulty_menu
|
||||
.push_entry(DifficultyMenuEntry::Title, MenuEntry::Disabled(state.t("menus.difficulty_menu.title")));
|
||||
self.difficulty_menu.push_entry(
|
||||
DifficultyMenuEntry::Difficulty(GameDifficulty::Easy),
|
||||
MenuEntry::Active(state.t("menus.difficulty_menu.easy")),
|
||||
);
|
||||
self.difficulty_menu.push_entry(
|
||||
DifficultyMenuEntry::Difficulty(GameDifficulty::Normal),
|
||||
MenuEntry::Active(state.t("menus.difficulty_menu.normal")),
|
||||
);
|
||||
self.difficulty_menu.push_entry(
|
||||
DifficultyMenuEntry::Difficulty(GameDifficulty::Hard),
|
||||
MenuEntry::Active(state.t("menus.difficulty_menu.hard")),
|
||||
);
|
||||
self.difficulty_menu.push_entry(DifficultyMenuEntry::Back, MenuEntry::Active(state.t("common.back")));
|
||||
|
||||
self.difficulty_menu.selected = 2;
|
||||
self.difficulty_menu.selected = DifficultyMenuEntry::Difficulty(GameDifficulty::Normal);
|
||||
|
||||
//self.coop_menu.init(state, ctx);
|
||||
|
||||
self.delete_confirm.push_entry(MenuEntry::Disabled(state.t("menus.save_menu.delete_confirm")));
|
||||
self.delete_confirm.push_entry(MenuEntry::Active(state.t("common.yes")));
|
||||
self.delete_confirm.push_entry(MenuEntry::Active(state.t("common.no")));
|
||||
self.delete_confirm
|
||||
.push_entry(DeleteConfirmMenuEntry::Title, MenuEntry::Disabled(state.t("menus.save_menu.delete_confirm")));
|
||||
self.delete_confirm.push_entry(DeleteConfirmMenuEntry::Yes, MenuEntry::Active(state.t("common.yes")));
|
||||
self.delete_confirm.push_entry(DeleteConfirmMenuEntry::No, MenuEntry::Active(state.t("common.no")));
|
||||
|
||||
self.delete_confirm.selected = 2;
|
||||
self.delete_confirm.selected = DeleteConfirmMenuEntry::No;
|
||||
|
||||
self.load_confirm.push_entry(MenuEntry::Active(state.t("menus.main_menu.start")));
|
||||
self.load_confirm.push_entry(MenuEntry::Active(state.t("menus.save_menu.delete_confirm")));
|
||||
self.load_confirm.push_entry(MenuEntry::Active(state.t("common.back")));
|
||||
self.load_confirm.push_entry(LoadConfirmMenuEntry::Start, MenuEntry::Active(state.t("menus.main_menu.start")));
|
||||
self.load_confirm
|
||||
.push_entry(LoadConfirmMenuEntry::Delete, MenuEntry::Active(state.t("menus.save_menu.delete_confirm")));
|
||||
self.load_confirm.push_entry(LoadConfirmMenuEntry::Back, MenuEntry::Active(state.t("common.back")));
|
||||
|
||||
self.save_detailed.draw_cursor = false;
|
||||
|
||||
if let MenuEntry::SaveData(save) = self.save_menu.entries[0] {
|
||||
self.save_detailed.push_entry(MenuEntry::SaveDataSingle(save));
|
||||
if let (_, MenuEntry::SaveData(save)) = self.save_menu.entries[0] {
|
||||
self.save_detailed.push_entry(0, MenuEntry::SaveDataSingle(save));
|
||||
}
|
||||
|
||||
self.update_sizes(state);
|
||||
|
@ -161,42 +238,40 @@ impl SaveSelectMenu {
|
|||
self.update_sizes(state);
|
||||
match self.current_menu {
|
||||
CurrentMenu::SaveMenu => match self.save_menu.tick(controller, state) {
|
||||
MenuSelectionResult::Selected(3, _) | MenuSelectionResult::Canceled => exit_action(),
|
||||
MenuSelectionResult::Selected(slot, _) => {
|
||||
MenuSelectionResult::Selected(SaveMenuEntry::Back, _) | MenuSelectionResult::Canceled => exit_action(),
|
||||
MenuSelectionResult::Selected(SaveMenuEntry::New(slot), _) => {
|
||||
state.save_slot = slot + 1;
|
||||
|
||||
if self.skip_difficulty_menu {
|
||||
self.current_menu = CurrentMenu::PlayerCountMenu;
|
||||
} else {
|
||||
self.difficulty_menu.selected = DifficultyMenuEntry::Difficulty(GameDifficulty::Normal);
|
||||
self.current_menu = CurrentMenu::DifficultyMenu;
|
||||
}
|
||||
}
|
||||
MenuSelectionResult::Selected(SaveMenuEntry::Load(slot), _) => {
|
||||
state.save_slot = slot + 1;
|
||||
|
||||
if let Ok(_) =
|
||||
filesystem::user_open(ctx, state.get_save_filename(state.save_slot).unwrap_or("".to_string()))
|
||||
{
|
||||
if let MenuEntry::SaveData(save) = self.save_menu.entries[slot] {
|
||||
if let (_, MenuEntry::SaveData(save)) = self.save_menu.entries[slot] {
|
||||
self.save_detailed.entries.clear();
|
||||
self.save_detailed.push_entry(MenuEntry::SaveDataSingle(save));
|
||||
self.save_detailed.push_entry(0, MenuEntry::SaveDataSingle(save));
|
||||
}
|
||||
|
||||
self.current_menu = CurrentMenu::LoadConfirm;
|
||||
self.load_confirm.selected = 0;
|
||||
} else if self.skip_difficulty_menu {
|
||||
self.current_menu = CurrentMenu::PlayerCountMenu;
|
||||
} else {
|
||||
self.difficulty_menu.selected = 2;
|
||||
self.current_menu = CurrentMenu::DifficultyMenu;
|
||||
self.load_confirm.selected = LoadConfirmMenuEntry::Start;
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
},
|
||||
CurrentMenu::DifficultyMenu => match self.difficulty_menu.tick(controller, state) {
|
||||
MenuSelectionResult::Selected(4, _) | MenuSelectionResult::Canceled => {
|
||||
MenuSelectionResult::Selected(DifficultyMenuEntry::Back, _) | MenuSelectionResult::Canceled => {
|
||||
self.current_menu = CurrentMenu::SaveMenu;
|
||||
}
|
||||
MenuSelectionResult::Selected(1, _) => {
|
||||
state.difficulty = GameDifficulty::Easy;
|
||||
self.current_menu = CurrentMenu::PlayerCountMenu;
|
||||
}
|
||||
MenuSelectionResult::Selected(2, _) => {
|
||||
state.difficulty = GameDifficulty::Normal;
|
||||
self.current_menu = CurrentMenu::PlayerCountMenu;
|
||||
}
|
||||
MenuSelectionResult::Selected(3, _) => {
|
||||
state.difficulty = GameDifficulty::Hard;
|
||||
MenuSelectionResult::Selected(DifficultyMenuEntry::Difficulty(difficulty), _) => {
|
||||
state.difficulty = difficulty;
|
||||
self.current_menu = CurrentMenu::PlayerCountMenu;
|
||||
}
|
||||
_ => (),
|
||||
|
@ -214,30 +289,33 @@ impl SaveSelectMenu {
|
|||
)?;
|
||||
}
|
||||
CurrentMenu::DeleteConfirm => match self.delete_confirm.tick(controller, state) {
|
||||
MenuSelectionResult::Selected(1, _) => {
|
||||
state.sound_manager.play_sfx(17); // Player Death sfx
|
||||
filesystem::user_delete(
|
||||
ctx,
|
||||
state.get_save_filename(self.save_menu.selected + 1).unwrap_or("".to_string()),
|
||||
)?;
|
||||
self.save_menu.entries[self.save_menu.selected] = MenuEntry::NewSave;
|
||||
MenuSelectionResult::Selected(DeleteConfirmMenuEntry::Yes, _) => {
|
||||
match self.save_menu.selected {
|
||||
SaveMenuEntry::Load(slot) => {
|
||||
state.sound_manager.play_sfx(17); // Player Death sfx
|
||||
filesystem::user_delete(ctx, state.get_save_filename(slot + 1).unwrap_or("".to_string()))?;
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
|
||||
self.save_menu.set_entry(self.save_menu.selected, MenuEntry::NewSave);
|
||||
self.current_menu = CurrentMenu::SaveMenu;
|
||||
}
|
||||
MenuSelectionResult::Selected(2, _) | MenuSelectionResult::Canceled => {
|
||||
MenuSelectionResult::Selected(DeleteConfirmMenuEntry::No, _) | MenuSelectionResult::Canceled => {
|
||||
self.current_menu = CurrentMenu::LoadConfirm;
|
||||
self.load_confirm.selected = 0;
|
||||
self.load_confirm.selected = LoadConfirmMenuEntry::Start;
|
||||
}
|
||||
_ => (),
|
||||
},
|
||||
CurrentMenu::LoadConfirm => match self.load_confirm.tick(controller, state) {
|
||||
MenuSelectionResult::Selected(0, _) => {
|
||||
MenuSelectionResult::Selected(LoadConfirmMenuEntry::Start, _) => {
|
||||
self.current_menu = CurrentMenu::PlayerCountMenu;
|
||||
}
|
||||
MenuSelectionResult::Selected(1, _) => {
|
||||
MenuSelectionResult::Selected(LoadConfirmMenuEntry::Delete, _) => {
|
||||
self.current_menu = CurrentMenu::DeleteConfirm;
|
||||
self.delete_confirm.selected = 2;
|
||||
self.delete_confirm.selected = DeleteConfirmMenuEntry::No;
|
||||
}
|
||||
MenuSelectionResult::Selected(2, _) | MenuSelectionResult::Canceled => {
|
||||
MenuSelectionResult::Selected(LoadConfirmMenuEntry::Back, _) | MenuSelectionResult::Canceled => {
|
||||
self.current_menu = CurrentMenu::SaveMenu;
|
||||
}
|
||||
_ => (),
|
||||
|
|
|
@ -24,13 +24,90 @@ enum CurrentMenu {
|
|||
LanguageMenu,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
|
||||
enum MainMenuEntry {
|
||||
Graphics,
|
||||
Sound,
|
||||
Language,
|
||||
GameTiming,
|
||||
DiscordLink,
|
||||
Back,
|
||||
}
|
||||
|
||||
impl Default for MainMenuEntry {
|
||||
fn default() -> Self {
|
||||
MainMenuEntry::Graphics
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
|
||||
enum GraphicsMenuEntry {
|
||||
WindowMode,
|
||||
VSyncMode,
|
||||
LightingEffects,
|
||||
WeaponLightCone,
|
||||
ScreenShake,
|
||||
MotionInterpolation,
|
||||
SubpixelScrolling,
|
||||
OriginalTextures,
|
||||
SeasonalTextures,
|
||||
Renderer,
|
||||
Back,
|
||||
}
|
||||
|
||||
impl Default for GraphicsMenuEntry {
|
||||
fn default() -> Self {
|
||||
GraphicsMenuEntry::WindowMode
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
|
||||
enum SoundMenuEntry {
|
||||
MusicVolume,
|
||||
EffectsVolume,
|
||||
BGMInterpolation,
|
||||
Soundtrack,
|
||||
Back,
|
||||
}
|
||||
|
||||
impl Default for SoundMenuEntry {
|
||||
fn default() -> Self {
|
||||
SoundMenuEntry::MusicVolume
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
|
||||
enum SoundtrackMenuEntry {
|
||||
Soundtrack(usize),
|
||||
Back,
|
||||
}
|
||||
|
||||
impl Default for SoundtrackMenuEntry {
|
||||
fn default() -> Self {
|
||||
SoundtrackMenuEntry::Soundtrack(0)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
|
||||
enum LanguageMenuEntry {
|
||||
Title,
|
||||
Language(Language),
|
||||
Back,
|
||||
}
|
||||
|
||||
impl Default for LanguageMenuEntry {
|
||||
fn default() -> Self {
|
||||
LanguageMenuEntry::Language(Language::English)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SettingsMenu {
|
||||
current: CurrentMenu,
|
||||
main: Menu,
|
||||
graphics: Menu,
|
||||
sound: Menu,
|
||||
soundtrack: Menu,
|
||||
language: Menu,
|
||||
main: Menu<MainMenuEntry>,
|
||||
graphics: Menu<GraphicsMenuEntry>,
|
||||
sound: Menu<SoundMenuEntry>,
|
||||
soundtrack: Menu<SoundtrackMenuEntry>,
|
||||
language: Menu<LanguageMenuEntry>,
|
||||
pub on_title: bool,
|
||||
}
|
||||
|
||||
|
@ -49,155 +126,182 @@ impl SettingsMenu {
|
|||
|
||||
pub fn init(&mut self, state: &mut SharedGameState, ctx: &mut Context) -> GameResult {
|
||||
#[cfg(not(target_os = "android"))]
|
||||
self.graphics.push_entry(MenuEntry::Options(
|
||||
state.t("menus.options_menu.graphics_menu.window_mode.entry"),
|
||||
state.settings.window_mode as usize,
|
||||
vec![
|
||||
state.t("menus.options_menu.graphics_menu.window_mode.windowed"),
|
||||
state.t("menus.options_menu.graphics_menu.window_mode.fullscreen"),
|
||||
],
|
||||
));
|
||||
self.graphics.push_entry(
|
||||
GraphicsMenuEntry::WindowMode,
|
||||
MenuEntry::Options(
|
||||
state.t("menus.options_menu.graphics_menu.window_mode.entry"),
|
||||
state.settings.window_mode as usize,
|
||||
vec![
|
||||
state.t("menus.options_menu.graphics_menu.window_mode.windowed"),
|
||||
state.t("menus.options_menu.graphics_menu.window_mode.fullscreen"),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
{
|
||||
let entry_text = state.t("menus.options_menu.graphics_menu.window_mode.entry") + " N/A";
|
||||
self.graphics.push_entry(MenuEntry::Disabled(entry_text));
|
||||
self.graphics.selected += 1;
|
||||
}
|
||||
|
||||
self.graphics.push_entry(MenuEntry::DescriptiveOptions(
|
||||
state.t("menus.options_menu.graphics_menu.vsync_mode.entry"),
|
||||
state.settings.vsync_mode as usize,
|
||||
vec![
|
||||
state.t("menus.options_menu.graphics_menu.vsync_mode.uncapped"),
|
||||
state.t("menus.options_menu.graphics_menu.vsync_mode.vsync"),
|
||||
state.t("menus.options_menu.graphics_menu.vsync_mode.vrr_1x"),
|
||||
state.t("menus.options_menu.graphics_menu.vsync_mode.vrr_2x"),
|
||||
state.t("menus.options_menu.graphics_menu.vsync_mode.vrr_3x"),
|
||||
],
|
||||
vec![
|
||||
state.t("menus.options_menu.graphics_menu.vsync_mode.uncapped_desc"),
|
||||
state.t("menus.options_menu.graphics_menu.vsync_mode.vsync_desc"),
|
||||
state.t("menus.options_menu.graphics_menu.vsync_mode.vrr_1x_desc"),
|
||||
state.t("menus.options_menu.graphics_menu.vsync_mode.vrr_2x_desc"),
|
||||
state.t("menus.options_menu.graphics_menu.vsync_mode.vrr_3x_desc"),
|
||||
],
|
||||
));
|
||||
self.graphics.push_entry(MenuEntry::Toggle(
|
||||
state.t("menus.options_menu.graphics_menu.lighting_effects"),
|
||||
state.settings.shader_effects,
|
||||
));
|
||||
self.graphics.push_entry(MenuEntry::Toggle(
|
||||
state.t("menus.options_menu.graphics_menu.weapon_light_cone"),
|
||||
state.settings.light_cone,
|
||||
));
|
||||
self.graphics.push_entry(MenuEntry::Options(
|
||||
state.t("menus.options_menu.graphics_menu.screen_shake.entry"),
|
||||
state.settings.screen_shake_intensity as usize,
|
||||
vec![
|
||||
state.t("menus.options_menu.graphics_menu.screen_shake.full"),
|
||||
state.t("menus.options_menu.graphics_menu.screen_shake.half"),
|
||||
state.t("menus.options_menu.graphics_menu.screen_shake.off"),
|
||||
],
|
||||
));
|
||||
self.graphics.push_entry(MenuEntry::Toggle(
|
||||
state.t("menus.options_menu.graphics_menu.motion_interpolation"),
|
||||
state.settings.motion_interpolation,
|
||||
));
|
||||
self.graphics.push_entry(MenuEntry::Toggle(
|
||||
state.t("menus.options_menu.graphics_menu.subpixel_scrolling"),
|
||||
state.settings.subpixel_coords,
|
||||
));
|
||||
self.graphics.push_entry(
|
||||
GraphicsMenuEntry::VSyncMode,
|
||||
MenuEntry::DescriptiveOptions(
|
||||
state.t("menus.options_menu.graphics_menu.vsync_mode.entry"),
|
||||
state.settings.vsync_mode as usize,
|
||||
vec![
|
||||
state.t("menus.options_menu.graphics_menu.vsync_mode.uncapped"),
|
||||
state.t("menus.options_menu.graphics_menu.vsync_mode.vsync"),
|
||||
state.t("menus.options_menu.graphics_menu.vsync_mode.vrr_1x"),
|
||||
state.t("menus.options_menu.graphics_menu.vsync_mode.vrr_2x"),
|
||||
state.t("menus.options_menu.graphics_menu.vsync_mode.vrr_3x"),
|
||||
],
|
||||
vec![
|
||||
state.t("menus.options_menu.graphics_menu.vsync_mode.uncapped_desc"),
|
||||
state.t("menus.options_menu.graphics_menu.vsync_mode.vsync_desc"),
|
||||
state.t("menus.options_menu.graphics_menu.vsync_mode.vrr_1x_desc"),
|
||||
state.t("menus.options_menu.graphics_menu.vsync_mode.vrr_2x_desc"),
|
||||
state.t("menus.options_menu.graphics_menu.vsync_mode.vrr_3x_desc"),
|
||||
],
|
||||
),
|
||||
);
|
||||
self.graphics.push_entry(
|
||||
GraphicsMenuEntry::LightingEffects,
|
||||
MenuEntry::Toggle(
|
||||
state.t("menus.options_menu.graphics_menu.lighting_effects"),
|
||||
state.settings.shader_effects,
|
||||
),
|
||||
);
|
||||
self.graphics.push_entry(
|
||||
GraphicsMenuEntry::WeaponLightCone,
|
||||
MenuEntry::Toggle(state.t("menus.options_menu.graphics_menu.weapon_light_cone"), state.settings.light_cone),
|
||||
);
|
||||
self.graphics.push_entry(
|
||||
GraphicsMenuEntry::ScreenShake,
|
||||
MenuEntry::Options(
|
||||
state.t("menus.options_menu.graphics_menu.screen_shake.entry"),
|
||||
state.settings.screen_shake_intensity as usize,
|
||||
vec![
|
||||
state.t("menus.options_menu.graphics_menu.screen_shake.full"),
|
||||
state.t("menus.options_menu.graphics_menu.screen_shake.half"),
|
||||
state.t("menus.options_menu.graphics_menu.screen_shake.off"),
|
||||
],
|
||||
),
|
||||
);
|
||||
self.graphics.push_entry(
|
||||
GraphicsMenuEntry::MotionInterpolation,
|
||||
MenuEntry::Toggle(
|
||||
state.t("menus.options_menu.graphics_menu.motion_interpolation"),
|
||||
state.settings.motion_interpolation,
|
||||
),
|
||||
);
|
||||
self.graphics.push_entry(
|
||||
GraphicsMenuEntry::SubpixelScrolling,
|
||||
MenuEntry::Toggle(
|
||||
state.t("menus.options_menu.graphics_menu.subpixel_scrolling"),
|
||||
state.settings.subpixel_coords,
|
||||
),
|
||||
);
|
||||
|
||||
// NS version uses two different maps, therefore we can't dynamically switch between graphics presets.
|
||||
if state.constants.supports_og_textures {
|
||||
if !state.constants.is_switch || self.on_title {
|
||||
self.graphics.push_entry(MenuEntry::Toggle(
|
||||
state.t("menus.options_menu.graphics_menu.original_textures"),
|
||||
state.settings.original_textures,
|
||||
));
|
||||
self.graphics.push_entry(
|
||||
GraphicsMenuEntry::OriginalTextures,
|
||||
MenuEntry::Toggle(
|
||||
state.t("menus.options_menu.graphics_menu.original_textures"),
|
||||
state.settings.original_textures,
|
||||
),
|
||||
);
|
||||
} else {
|
||||
self.graphics
|
||||
.push_entry(MenuEntry::Disabled(state.t("menus.options_menu.graphics_menu.original_textures")));
|
||||
self.graphics.push_entry(
|
||||
GraphicsMenuEntry::OriginalTextures,
|
||||
MenuEntry::Disabled(state.t("menus.options_menu.graphics_menu.original_textures")),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
self.graphics.push_entry(MenuEntry::Hidden);
|
||||
}
|
||||
|
||||
if state.constants.is_cs_plus {
|
||||
self.graphics.push_entry(MenuEntry::Toggle(
|
||||
state.t("menus.options_menu.graphics_menu.seasonal_textures"),
|
||||
state.settings.seasonal_textures,
|
||||
));
|
||||
} else {
|
||||
self.graphics.push_entry(MenuEntry::Hidden);
|
||||
self.graphics.push_entry(
|
||||
GraphicsMenuEntry::SeasonalTextures,
|
||||
MenuEntry::Toggle(
|
||||
state.t("menus.options_menu.graphics_menu.seasonal_textures"),
|
||||
state.settings.seasonal_textures,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
self.graphics.push_entry(MenuEntry::Disabled(format!(
|
||||
"{} {}",
|
||||
state.t("menus.options_menu.graphics_menu.renderer"),
|
||||
ctx.renderer.as_ref().unwrap().renderer_name()
|
||||
)));
|
||||
self.graphics.push_entry(
|
||||
GraphicsMenuEntry::Renderer,
|
||||
MenuEntry::Disabled(format!(
|
||||
"{} {}",
|
||||
state.t("menus.options_menu.graphics_menu.renderer"),
|
||||
ctx.renderer.as_ref().unwrap().renderer_name()
|
||||
)),
|
||||
);
|
||||
|
||||
self.graphics.push_entry(MenuEntry::Active(state.t("common.back")));
|
||||
self.graphics.push_entry(GraphicsMenuEntry::Back, MenuEntry::Active(state.t("common.back")));
|
||||
|
||||
self.main.push_entry(MenuEntry::Active(state.t("menus.options_menu.graphics")));
|
||||
self.main.push_entry(MenuEntry::Active(state.t("menus.options_menu.sound")));
|
||||
self.main.push_entry(MainMenuEntry::Graphics, MenuEntry::Active(state.t("menus.options_menu.graphics")));
|
||||
self.main.push_entry(MainMenuEntry::Sound, MenuEntry::Active(state.t("menus.options_menu.sound")));
|
||||
|
||||
self.language.push_entry(LanguageMenuEntry::Title, MenuEntry::Disabled(state.t("menus.options_menu.language")));
|
||||
|
||||
self.language.push_entry(MenuEntry::Disabled(state.t("menus.options_menu.language")));
|
||||
for language in Language::values() {
|
||||
self.language.push_entry(MenuEntry::Active(language.to_string()));
|
||||
self.language.push_entry(LanguageMenuEntry::Language(language), MenuEntry::Active(language.to_string()));
|
||||
}
|
||||
self.language.push_entry(MenuEntry::Active(state.t("common.back")));
|
||||
|
||||
self.language.push_entry(LanguageMenuEntry::Back, MenuEntry::Active(state.t("common.back")));
|
||||
|
||||
if self.on_title {
|
||||
self.main.push_entry(MenuEntry::Active(state.t("menus.options_menu.language")));
|
||||
} else {
|
||||
self.main.push_entry(MenuEntry::Disabled(state.t("menus.options_menu.language")));
|
||||
self.main.push_entry(MainMenuEntry::Language, MenuEntry::Active(state.t("menus.options_menu.language")));
|
||||
}
|
||||
|
||||
self.main.push_entry(MenuEntry::Options(
|
||||
state.t("menus.options_menu.game_timing.entry"),
|
||||
if state.settings.timing_mode == TimingMode::_50Hz { 0 } else { 1 },
|
||||
vec![state.t("menus.options_menu.game_timing.50tps"), state.t("menus.options_menu.game_timing.60tps")],
|
||||
));
|
||||
self.main.push_entry(
|
||||
MainMenuEntry::GameTiming,
|
||||
MenuEntry::Options(
|
||||
state.t("menus.options_menu.game_timing.entry"),
|
||||
if state.settings.timing_mode == TimingMode::_50Hz { 0 } else { 1 },
|
||||
vec![state.t("menus.options_menu.game_timing.50tps"), state.t("menus.options_menu.game_timing.60tps")],
|
||||
),
|
||||
);
|
||||
|
||||
self.main.push_entry(MenuEntry::Active(DISCORD_LINK.to_owned()));
|
||||
self.main.push_entry(MainMenuEntry::DiscordLink, MenuEntry::Active(DISCORD_LINK.to_owned()));
|
||||
|
||||
self.main.push_entry(MenuEntry::Active(state.t("common.back")));
|
||||
self.main.push_entry(MainMenuEntry::Back, MenuEntry::Active(state.t("common.back")));
|
||||
|
||||
self.sound.push_entry(MenuEntry::OptionsBar(
|
||||
state.t("menus.options_menu.sound_menu.music_volume"),
|
||||
state.settings.bgm_volume,
|
||||
));
|
||||
self.sound.push_entry(MenuEntry::OptionsBar(
|
||||
state.t("menus.options_menu.sound_menu.effects_volume"),
|
||||
state.settings.sfx_volume,
|
||||
));
|
||||
self.sound.push_entry(
|
||||
SoundMenuEntry::MusicVolume,
|
||||
MenuEntry::OptionsBar(state.t("menus.options_menu.sound_menu.music_volume"), state.settings.bgm_volume),
|
||||
);
|
||||
self.sound.push_entry(
|
||||
SoundMenuEntry::EffectsVolume,
|
||||
MenuEntry::OptionsBar(state.t("menus.options_menu.sound_menu.effects_volume"), state.settings.sfx_volume),
|
||||
);
|
||||
|
||||
self.sound.push_entry(MenuEntry::DescriptiveOptions(
|
||||
state.t("menus.options_menu.sound_menu.bgm_interpolation.entry"),
|
||||
state.settings.organya_interpolation as usize,
|
||||
vec![
|
||||
state.t("menus.options_menu.sound_menu.bgm_interpolation.nearest"),
|
||||
state.t("menus.options_menu.sound_menu.bgm_interpolation.linear"),
|
||||
state.t("menus.options_menu.sound_menu.bgm_interpolation.cosine"),
|
||||
state.t("menus.options_menu.sound_menu.bgm_interpolation.cubic"),
|
||||
state.t("menus.options_menu.sound_menu.bgm_interpolation.linear_lp"),
|
||||
],
|
||||
vec![
|
||||
state.t("menus.options_menu.sound_menu.bgm_interpolation.nearest_desc"),
|
||||
state.t("menus.options_menu.sound_menu.bgm_interpolation.linear_desc"),
|
||||
state.t("menus.options_menu.sound_menu.bgm_interpolation.cosine_desc"),
|
||||
state.t("menus.options_menu.sound_menu.bgm_interpolation.cubic_desc"),
|
||||
state.t("menus.options_menu.sound_menu.bgm_interpolation.linear_lp_desc"),
|
||||
],
|
||||
));
|
||||
self.sound.push_entry(MenuEntry::Active(state.tt(
|
||||
"menus.options_menu.sound_menu.soundtrack",
|
||||
HashMap::from([("soundtrack".to_owned(), state.settings.soundtrack.to_owned())]),
|
||||
)));
|
||||
self.sound.push_entry(MenuEntry::Active(state.t("common.back")));
|
||||
self.sound.push_entry(
|
||||
SoundMenuEntry::BGMInterpolation,
|
||||
MenuEntry::DescriptiveOptions(
|
||||
state.t("menus.options_menu.sound_menu.bgm_interpolation.entry"),
|
||||
state.settings.organya_interpolation as usize,
|
||||
vec![
|
||||
state.t("menus.options_menu.sound_menu.bgm_interpolation.nearest"),
|
||||
state.t("menus.options_menu.sound_menu.bgm_interpolation.linear"),
|
||||
state.t("menus.options_menu.sound_menu.bgm_interpolation.cosine"),
|
||||
state.t("menus.options_menu.sound_menu.bgm_interpolation.cubic"),
|
||||
state.t("menus.options_menu.sound_menu.bgm_interpolation.linear_lp"),
|
||||
],
|
||||
vec![
|
||||
state.t("menus.options_menu.sound_menu.bgm_interpolation.nearest_desc"),
|
||||
state.t("menus.options_menu.sound_menu.bgm_interpolation.linear_desc"),
|
||||
state.t("menus.options_menu.sound_menu.bgm_interpolation.cosine_desc"),
|
||||
state.t("menus.options_menu.sound_menu.bgm_interpolation.cubic_desc"),
|
||||
state.t("menus.options_menu.sound_menu.bgm_interpolation.linear_lp_desc"),
|
||||
],
|
||||
),
|
||||
);
|
||||
self.sound.push_entry(
|
||||
SoundMenuEntry::Soundtrack,
|
||||
MenuEntry::Active(state.tt(
|
||||
"menus.options_menu.sound_menu.soundtrack",
|
||||
HashMap::from([("soundtrack".to_owned(), state.settings.soundtrack.to_owned())]),
|
||||
)),
|
||||
);
|
||||
self.sound.push_entry(SoundMenuEntry::Back, MenuEntry::Active(state.t("common.back")));
|
||||
|
||||
let mut soundtrack_entries =
|
||||
state.constants.soundtracks.iter().filter(|s| s.available).map(|s| s.name.to_owned()).collect_vec();
|
||||
|
@ -217,8 +321,8 @@ impl SettingsMenu {
|
|||
|
||||
soundtrack_entries.sort();
|
||||
|
||||
for soundtrack in &soundtrack_entries {
|
||||
self.soundtrack.push_entry(MenuEntry::Active(soundtrack.to_string()));
|
||||
for (idx, soundtrack) in soundtrack_entries.iter().enumerate() {
|
||||
self.soundtrack.push_entry(SoundtrackMenuEntry::Soundtrack(idx), MenuEntry::Active(soundtrack.to_string()));
|
||||
}
|
||||
|
||||
self.soundtrack.width = soundtrack_entries
|
||||
|
@ -228,7 +332,7 @@ impl SettingsMenu {
|
|||
.unwrap_or(self.soundtrack.width as f32) as u16
|
||||
+ 32;
|
||||
|
||||
self.soundtrack.push_entry(MenuEntry::Active(state.t("common.back")));
|
||||
self.soundtrack.push_entry(SoundtrackMenuEntry::Back, MenuEntry::Active(state.t("common.back")));
|
||||
|
||||
self.update_sizes(state);
|
||||
|
||||
|
@ -273,17 +377,17 @@ impl SettingsMenu {
|
|||
|
||||
match self.current {
|
||||
CurrentMenu::MainMenu => match self.main.tick(controller, state) {
|
||||
MenuSelectionResult::Selected(0, _) => {
|
||||
MenuSelectionResult::Selected(MainMenuEntry::Graphics, _) => {
|
||||
self.current = CurrentMenu::GraphicsMenu;
|
||||
}
|
||||
MenuSelectionResult::Selected(1, _) => {
|
||||
MenuSelectionResult::Selected(MainMenuEntry::Sound, _) => {
|
||||
self.current = CurrentMenu::SoundMenu;
|
||||
}
|
||||
MenuSelectionResult::Selected(2, _) => {
|
||||
self.language.selected = (state.settings.locale as usize) + 1;
|
||||
MenuSelectionResult::Selected(MainMenuEntry::Language, _) => {
|
||||
self.language.selected = LanguageMenuEntry::Language(state.settings.locale);
|
||||
self.current = CurrentMenu::LanguageMenu;
|
||||
}
|
||||
MenuSelectionResult::Selected(3, toggle) => {
|
||||
MenuSelectionResult::Selected(MainMenuEntry::GameTiming, toggle) => {
|
||||
if let MenuEntry::Options(_, value, _) = toggle {
|
||||
match state.settings.timing_mode {
|
||||
TimingMode::_50Hz => {
|
||||
|
@ -299,18 +403,18 @@ impl SettingsMenu {
|
|||
let _ = state.settings.save(ctx);
|
||||
}
|
||||
}
|
||||
MenuSelectionResult::Selected(4, _) => {
|
||||
MenuSelectionResult::Selected(MainMenuEntry::DiscordLink, _) => {
|
||||
if let Err(e) = webbrowser::open(DISCORD_LINK) {
|
||||
log::warn!("Error opening web browser: {}", e);
|
||||
}
|
||||
}
|
||||
MenuSelectionResult::Selected(5, _) | MenuSelectionResult::Canceled => exit_action(),
|
||||
MenuSelectionResult::Selected(MainMenuEntry::Back, _) | MenuSelectionResult::Canceled => exit_action(),
|
||||
_ => (),
|
||||
},
|
||||
CurrentMenu::GraphicsMenu => match self.graphics.tick(controller, state) {
|
||||
MenuSelectionResult::Selected(0, toggle)
|
||||
| MenuSelectionResult::Right(0, toggle, _)
|
||||
| MenuSelectionResult::Left(0, toggle, _) => {
|
||||
MenuSelectionResult::Selected(GraphicsMenuEntry::WindowMode, toggle)
|
||||
| MenuSelectionResult::Right(GraphicsMenuEntry::WindowMode, toggle, _)
|
||||
| MenuSelectionResult::Left(GraphicsMenuEntry::WindowMode, toggle, _) => {
|
||||
if let MenuEntry::Options(_, value, _) = toggle {
|
||||
let (new_mode, new_value) = match *value {
|
||||
0 => (WindowMode::Fullscreen, 1),
|
||||
|
@ -324,7 +428,8 @@ impl SettingsMenu {
|
|||
let _ = state.settings.save(ctx);
|
||||
}
|
||||
}
|
||||
MenuSelectionResult::Selected(1, toggle) | MenuSelectionResult::Right(1, toggle, _) => {
|
||||
MenuSelectionResult::Selected(GraphicsMenuEntry::VSyncMode, toggle)
|
||||
| MenuSelectionResult::Right(GraphicsMenuEntry::VSyncMode, toggle, _) => {
|
||||
if let MenuEntry::DescriptiveOptions(_, value, _, _) = toggle {
|
||||
let (new_mode, new_value) = match *value {
|
||||
0 => (VSyncMode::VSync, 1),
|
||||
|
@ -341,7 +446,7 @@ impl SettingsMenu {
|
|||
let _ = state.settings.save(ctx);
|
||||
}
|
||||
}
|
||||
MenuSelectionResult::Left(1, toggle, _) => {
|
||||
MenuSelectionResult::Left(GraphicsMenuEntry::VSyncMode, toggle, _) => {
|
||||
if let MenuEntry::DescriptiveOptions(_, value, _, _) = toggle {
|
||||
let (new_mode, new_value) = match *value {
|
||||
0 => (VSyncMode::VRRTickSync3x, 4),
|
||||
|
@ -358,7 +463,7 @@ impl SettingsMenu {
|
|||
let _ = state.settings.save(ctx);
|
||||
}
|
||||
}
|
||||
MenuSelectionResult::Selected(2, toggle) => {
|
||||
MenuSelectionResult::Selected(GraphicsMenuEntry::LightingEffects, toggle) => {
|
||||
if let MenuEntry::Toggle(_, value) = toggle {
|
||||
state.settings.shader_effects = !state.settings.shader_effects;
|
||||
let _ = state.settings.save(ctx);
|
||||
|
@ -366,7 +471,7 @@ impl SettingsMenu {
|
|||
*value = state.settings.shader_effects;
|
||||
}
|
||||
}
|
||||
MenuSelectionResult::Selected(3, toggle) => {
|
||||
MenuSelectionResult::Selected(GraphicsMenuEntry::WeaponLightCone, toggle) => {
|
||||
if let MenuEntry::Toggle(_, value) = toggle {
|
||||
state.settings.light_cone = !state.settings.light_cone;
|
||||
let _ = state.settings.save(ctx);
|
||||
|
@ -374,7 +479,8 @@ impl SettingsMenu {
|
|||
*value = state.settings.light_cone;
|
||||
}
|
||||
}
|
||||
MenuSelectionResult::Selected(4, toggle) | MenuSelectionResult::Right(4, toggle, _) => {
|
||||
MenuSelectionResult::Selected(GraphicsMenuEntry::ScreenShake, toggle)
|
||||
| MenuSelectionResult::Right(GraphicsMenuEntry::ScreenShake, toggle, _) => {
|
||||
if let MenuEntry::Options(_, value, _) = toggle {
|
||||
let (new_intensity, new_value) = match *value {
|
||||
0 => (ScreenShakeIntensity::Half, 1),
|
||||
|
@ -388,7 +494,7 @@ impl SettingsMenu {
|
|||
let _ = state.settings.save(ctx);
|
||||
}
|
||||
}
|
||||
MenuSelectionResult::Left(4, toggle, _) => {
|
||||
MenuSelectionResult::Left(GraphicsMenuEntry::ScreenShake, toggle, _) => {
|
||||
if let MenuEntry::Options(_, value, _) = toggle {
|
||||
let (new_intensity, new_value) = match *value {
|
||||
0 => (ScreenShakeIntensity::Off, 2),
|
||||
|
@ -402,7 +508,7 @@ impl SettingsMenu {
|
|||
let _ = state.settings.save(ctx);
|
||||
}
|
||||
}
|
||||
MenuSelectionResult::Selected(5, toggle) => {
|
||||
MenuSelectionResult::Selected(GraphicsMenuEntry::MotionInterpolation, toggle) => {
|
||||
if let MenuEntry::Toggle(_, value) = toggle {
|
||||
state.settings.motion_interpolation = !state.settings.motion_interpolation;
|
||||
let _ = state.settings.save(ctx);
|
||||
|
@ -410,7 +516,7 @@ impl SettingsMenu {
|
|||
*value = state.settings.motion_interpolation;
|
||||
}
|
||||
}
|
||||
MenuSelectionResult::Selected(6, toggle) => {
|
||||
MenuSelectionResult::Selected(GraphicsMenuEntry::SubpixelScrolling, toggle) => {
|
||||
if let MenuEntry::Toggle(_, value) = toggle {
|
||||
state.settings.subpixel_coords = !state.settings.subpixel_coords;
|
||||
let _ = state.settings.save(ctx);
|
||||
|
@ -418,7 +524,7 @@ impl SettingsMenu {
|
|||
*value = state.settings.subpixel_coords;
|
||||
}
|
||||
}
|
||||
MenuSelectionResult::Selected(7, toggle) => {
|
||||
MenuSelectionResult::Selected(GraphicsMenuEntry::OriginalTextures, toggle) => {
|
||||
if let MenuEntry::Toggle(_, value) = toggle {
|
||||
state.settings.original_textures = !state.settings.original_textures;
|
||||
if self.on_title {
|
||||
|
@ -431,7 +537,7 @@ impl SettingsMenu {
|
|||
*value = state.settings.original_textures;
|
||||
}
|
||||
}
|
||||
MenuSelectionResult::Selected(8, toggle) => {
|
||||
MenuSelectionResult::Selected(GraphicsMenuEntry::SeasonalTextures, toggle) => {
|
||||
if let MenuEntry::Toggle(_, value) = toggle {
|
||||
state.settings.seasonal_textures = !state.settings.seasonal_textures;
|
||||
state.reload_graphics();
|
||||
|
@ -440,13 +546,14 @@ impl SettingsMenu {
|
|||
*value = state.settings.seasonal_textures;
|
||||
}
|
||||
}
|
||||
MenuSelectionResult::Selected(10, _) | MenuSelectionResult::Canceled => {
|
||||
MenuSelectionResult::Selected(GraphicsMenuEntry::Back, _) | MenuSelectionResult::Canceled => {
|
||||
self.current = CurrentMenu::MainMenu
|
||||
}
|
||||
_ => (),
|
||||
},
|
||||
CurrentMenu::SoundMenu => match self.sound.tick(controller, state) {
|
||||
MenuSelectionResult::Left(0, bgm, direction) | MenuSelectionResult::Right(0, bgm, direction) => {
|
||||
MenuSelectionResult::Left(SoundMenuEntry::MusicVolume, bgm, direction)
|
||||
| MenuSelectionResult::Right(SoundMenuEntry::MusicVolume, bgm, direction) => {
|
||||
if let MenuEntry::OptionsBar(_, value) = bgm {
|
||||
*value = (*value * 10.0 + (direction as f32)).clamp(0.0, 10.0) / 10.0;
|
||||
state.settings.bgm_volume = *value;
|
||||
|
@ -455,7 +562,8 @@ impl SettingsMenu {
|
|||
let _ = state.settings.save(ctx);
|
||||
}
|
||||
}
|
||||
MenuSelectionResult::Left(1, sfx, direction) | MenuSelectionResult::Right(1, sfx, direction) => {
|
||||
MenuSelectionResult::Left(SoundMenuEntry::EffectsVolume, sfx, direction)
|
||||
| MenuSelectionResult::Right(SoundMenuEntry::EffectsVolume, sfx, direction) => {
|
||||
if let MenuEntry::OptionsBar(_, value) = sfx {
|
||||
*value = (*value * 10.0 + (direction as f32)).clamp(0.0, 10.0) / 10.0;
|
||||
state.settings.sfx_volume = *value;
|
||||
|
@ -464,7 +572,7 @@ impl SettingsMenu {
|
|||
let _ = state.settings.save(ctx);
|
||||
}
|
||||
}
|
||||
MenuSelectionResult::Selected(2, toggle) => {
|
||||
MenuSelectionResult::Selected(SoundMenuEntry::BGMInterpolation, toggle) => {
|
||||
if let MenuEntry::DescriptiveOptions(_, value, _, _) = toggle {
|
||||
let (new_mode, new_value) = match *value {
|
||||
0 => (InterpolationMode::Linear, 1),
|
||||
|
@ -481,77 +589,72 @@ impl SettingsMenu {
|
|||
let _ = state.settings.save(ctx);
|
||||
}
|
||||
}
|
||||
MenuSelectionResult::Selected(3, _) => {
|
||||
let mut active_soundtrack_index = 0;
|
||||
MenuSelectionResult::Selected(SoundMenuEntry::Soundtrack, _) => {
|
||||
let mut active_soundtrack = SoundtrackMenuEntry::Soundtrack(0);
|
||||
|
||||
for (idx, entry) in self.soundtrack.entries.iter().enumerate() {
|
||||
for (id, entry) in &self.soundtrack.entries {
|
||||
if let MenuEntry::Active(soundtrack) = entry {
|
||||
if soundtrack == &state.settings.soundtrack {
|
||||
active_soundtrack_index = idx;
|
||||
active_soundtrack = *id;
|
||||
let _ = state.settings.save(ctx);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.soundtrack.selected = active_soundtrack_index;
|
||||
self.soundtrack.selected = active_soundtrack;
|
||||
|
||||
self.current = CurrentMenu::SoundtrackMenu
|
||||
}
|
||||
MenuSelectionResult::Selected(4, _) | MenuSelectionResult::Canceled => {
|
||||
MenuSelectionResult::Selected(SoundMenuEntry::Back, _) | MenuSelectionResult::Canceled => {
|
||||
self.current = CurrentMenu::MainMenu
|
||||
}
|
||||
_ => (),
|
||||
},
|
||||
CurrentMenu::LanguageMenu => {
|
||||
let last = self.language.entries.len() - 1;
|
||||
CurrentMenu::LanguageMenu => match self.language.tick(controller, state) {
|
||||
MenuSelectionResult::Selected(LanguageMenuEntry::Language(new_locale), entry) => {
|
||||
if let MenuEntry::Active(_) = entry {
|
||||
if new_locale == state.settings.locale {
|
||||
self.current = CurrentMenu::MainMenu;
|
||||
} else {
|
||||
state.settings.locale = new_locale;
|
||||
state.reload_fonts(ctx);
|
||||
|
||||
match self.language.tick(controller, state) {
|
||||
MenuSelectionResult::Selected(idx, entry) => {
|
||||
if let (true, MenuEntry::Active(_)) = (idx != last, entry) {
|
||||
let new_locale = Language::from_primitive(idx.saturating_sub(1));
|
||||
if new_locale == state.settings.locale {
|
||||
self.current = CurrentMenu::MainMenu;
|
||||
} else {
|
||||
state.settings.locale = new_locale;
|
||||
state.reload_fonts(ctx);
|
||||
|
||||
let _ = state.settings.save(ctx);
|
||||
|
||||
let mut new_menu = TitleScene::new();
|
||||
new_menu.open_settings_menu()?;
|
||||
state.next_scene = Some(Box::new(new_menu));
|
||||
}
|
||||
}
|
||||
|
||||
self.current = CurrentMenu::MainMenu;
|
||||
}
|
||||
MenuSelectionResult::Canceled => {
|
||||
self.current = CurrentMenu::MainMenu;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
CurrentMenu::SoundtrackMenu => {
|
||||
let last = self.soundtrack.entries.len() - 1;
|
||||
match self.soundtrack.tick(controller, state) {
|
||||
MenuSelectionResult::Selected(idx, entry) => {
|
||||
if let (true, MenuEntry::Active(name)) = (idx != last, entry) {
|
||||
state.settings.soundtrack = name.to_owned();
|
||||
let _ = state.settings.save(ctx);
|
||||
self.sound.entries[3] =
|
||||
MenuEntry::Active(format!("Soundtrack: {}", state.settings.soundtrack));
|
||||
state.sound_manager.reload_songs(&state.constants, &state.settings, ctx)?;
|
||||
}
|
||||
|
||||
self.current = CurrentMenu::SoundMenu;
|
||||
let mut new_menu = TitleScene::new();
|
||||
new_menu.open_settings_menu()?;
|
||||
state.next_scene = Some(Box::new(new_menu));
|
||||
}
|
||||
}
|
||||
MenuSelectionResult::Canceled => {
|
||||
self.current = CurrentMenu::SoundMenu;
|
||||
}
|
||||
_ => (),
|
||||
|
||||
self.current = CurrentMenu::MainMenu;
|
||||
}
|
||||
}
|
||||
MenuSelectionResult::Selected(LanguageMenuEntry::Back, _) | MenuSelectionResult::Canceled => {
|
||||
self.current = CurrentMenu::MainMenu;
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
CurrentMenu::SoundtrackMenu => match self.soundtrack.tick(controller, state) {
|
||||
MenuSelectionResult::Selected(SoundtrackMenuEntry::Soundtrack(_), entry) => {
|
||||
if let MenuEntry::Active(name) = entry {
|
||||
state.settings.soundtrack = name.to_owned();
|
||||
let _ = state.settings.save(ctx);
|
||||
|
||||
self.sound.set_entry(
|
||||
SoundMenuEntry::Soundtrack,
|
||||
MenuEntry::Active(format!("Soundtrack: {}", state.settings.soundtrack)),
|
||||
);
|
||||
state.sound_manager.reload_songs(&state.constants, &state.settings, ctx)?;
|
||||
}
|
||||
|
||||
self.current = CurrentMenu::SoundMenu;
|
||||
}
|
||||
MenuSelectionResult::Selected(SoundtrackMenuEntry::Back, _) | MenuSelectionResult::Canceled => {
|
||||
self.current = CurrentMenu::SoundMenu;
|
||||
}
|
||||
_ => (),
|
||||
},
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -29,14 +29,57 @@ enum CurrentMenu {
|
|||
PlayerCountMenu,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
|
||||
pub enum MainMenuEntry {
|
||||
Start,
|
||||
Challenges,
|
||||
Options,
|
||||
Editor,
|
||||
Jukebox,
|
||||
Quit,
|
||||
}
|
||||
|
||||
impl Default for MainMenuEntry {
|
||||
fn default() -> Self {
|
||||
MainMenuEntry::Start
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
|
||||
pub enum ChallengesMenuEntry {
|
||||
Back,
|
||||
Challenge(usize),
|
||||
}
|
||||
|
||||
impl Default for ChallengesMenuEntry {
|
||||
fn default() -> Self {
|
||||
ChallengesMenuEntry::Back
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
|
||||
pub enum ConfirmMenuEntry {
|
||||
Title,
|
||||
StartChallenge,
|
||||
ReplayBest,
|
||||
DeleteReplay,
|
||||
Back,
|
||||
}
|
||||
|
||||
impl Default for ConfirmMenuEntry {
|
||||
fn default() -> Self {
|
||||
ConfirmMenuEntry::StartChallenge
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TitleScene {
|
||||
tick: usize,
|
||||
controller: CombinedMenuController,
|
||||
current_menu: CurrentMenu,
|
||||
main_menu: Menu,
|
||||
main_menu: Menu<MainMenuEntry>,
|
||||
save_select_menu: SaveSelectMenu,
|
||||
challenges_menu: Menu,
|
||||
confirm_menu: Menu,
|
||||
challenges_menu: Menu<ChallengesMenuEntry>,
|
||||
confirm_menu: Menu<ConfirmMenuEntry>,
|
||||
coop_menu: PlayerCountMenu,
|
||||
settings_menu: SettingsMenu,
|
||||
background: Background,
|
||||
|
@ -152,24 +195,24 @@ impl Scene for TitleScene {
|
|||
self.controller.add(state.settings.create_player1_controller());
|
||||
self.controller.add(state.settings.create_player2_controller());
|
||||
|
||||
self.main_menu.push_entry(MenuEntry::Active(state.t("menus.main_menu.start")));
|
||||
self.main_menu.push_entry(MainMenuEntry::Start, MenuEntry::Active(state.t("menus.main_menu.start")));
|
||||
|
||||
if !state.mod_list.mods.is_empty() {
|
||||
self.main_menu.push_entry(MenuEntry::Active(state.t("menus.main_menu.challenges")));
|
||||
} else {
|
||||
self.main_menu.push_entry(MenuEntry::Hidden);
|
||||
self.main_menu
|
||||
.push_entry(MainMenuEntry::Challenges, MenuEntry::Active(state.t("menus.main_menu.challenges")));
|
||||
}
|
||||
self.main_menu.push_entry(MenuEntry::Active(state.t("menus.main_menu.options")));
|
||||
|
||||
self.main_menu.push_entry(MainMenuEntry::Options, MenuEntry::Active(state.t("menus.main_menu.options")));
|
||||
|
||||
if cfg!(feature = "editor") {
|
||||
self.main_menu.push_entry(MenuEntry::Active(state.t("menus.main_menu.editor")));
|
||||
} else {
|
||||
self.main_menu.push_entry(MenuEntry::Hidden);
|
||||
self.main_menu.push_entry(MainMenuEntry::Editor, MenuEntry::Active(state.t("menus.main_menu.editor")));
|
||||
}
|
||||
|
||||
if state.constants.is_switch {
|
||||
self.main_menu.push_entry(MenuEntry::Active(state.t("menus.main_menu.jukebox")));
|
||||
} else {
|
||||
self.main_menu.push_entry(MenuEntry::Hidden);
|
||||
self.main_menu.push_entry(MainMenuEntry::Jukebox, MenuEntry::Active(state.t("menus.main_menu.jukebox")));
|
||||
}
|
||||
self.main_menu.push_entry(MenuEntry::Active(state.t("menus.main_menu.quit")));
|
||||
|
||||
self.main_menu.push_entry(MainMenuEntry::Quit, MenuEntry::Active(state.t("menus.main_menu.quit")));
|
||||
|
||||
self.settings_menu.init(state, ctx)?;
|
||||
|
||||
|
@ -177,34 +220,39 @@ impl Scene for TitleScene {
|
|||
|
||||
self.coop_menu.init(state)?;
|
||||
|
||||
let mut selected: usize = 0;
|
||||
let mut selected = ChallengesMenuEntry::Back;
|
||||
let mut mutate_selection = true;
|
||||
|
||||
for mod_info in state.mod_list.mods.iter() {
|
||||
for (idx, mod_info) in state.mod_list.mods.iter().enumerate() {
|
||||
if !mod_info.valid {
|
||||
self.challenges_menu.push_entry(MenuEntry::Disabled(mod_info.path.clone()));
|
||||
self.challenges_menu
|
||||
.push_entry(ChallengesMenuEntry::Challenge(idx), MenuEntry::Disabled(mod_info.path.clone()));
|
||||
continue;
|
||||
}
|
||||
if mod_info.satisfies_requirement(&state.mod_requirements) {
|
||||
self.challenges_menu.push_entry(MenuEntry::Active(mod_info.name.clone()));
|
||||
mutate_selection = false;
|
||||
} else {
|
||||
self.challenges_menu.push_entry(MenuEntry::Disabled("???".to_owned()));
|
||||
self.challenges_menu
|
||||
.push_entry(ChallengesMenuEntry::Challenge(idx), MenuEntry::Active(mod_info.name.clone()));
|
||||
|
||||
if mutate_selection {
|
||||
selected += 1;
|
||||
selected = ChallengesMenuEntry::Challenge(idx);
|
||||
mutate_selection = false;
|
||||
}
|
||||
} else {
|
||||
self.challenges_menu
|
||||
.push_entry(ChallengesMenuEntry::Challenge(idx), MenuEntry::Disabled("???".to_owned()));
|
||||
}
|
||||
}
|
||||
self.challenges_menu.push_entry(MenuEntry::Active(state.t("common.back")));
|
||||
self.challenges_menu.push_entry(ChallengesMenuEntry::Back, MenuEntry::Active(state.t("common.back")));
|
||||
self.challenges_menu.selected = selected;
|
||||
|
||||
self.confirm_menu.push_entry(MenuEntry::Disabled("".to_owned()));
|
||||
self.confirm_menu.push_entry(MenuEntry::Active(state.t("menus.challenge_menu.start")));
|
||||
self.confirm_menu.push_entry(MenuEntry::Disabled(state.t("menus.challenge_menu.no_replay")));
|
||||
self.confirm_menu.push_entry(MenuEntry::Hidden);
|
||||
self.confirm_menu.push_entry(MenuEntry::Active(state.t("common.back")));
|
||||
self.confirm_menu.selected = 1;
|
||||
self.confirm_menu.push_entry(ConfirmMenuEntry::Title, MenuEntry::Disabled("".to_owned()));
|
||||
self.confirm_menu
|
||||
.push_entry(ConfirmMenuEntry::StartChallenge, MenuEntry::Active(state.t("menus.challenge_menu.start")));
|
||||
self.confirm_menu
|
||||
.push_entry(ConfirmMenuEntry::ReplayBest, MenuEntry::Disabled(state.t("menus.challenge_menu.no_replay")));
|
||||
self.confirm_menu.push_entry(ConfirmMenuEntry::DeleteReplay, MenuEntry::Hidden);
|
||||
self.confirm_menu.push_entry(ConfirmMenuEntry::Back, MenuEntry::Active(state.t("common.back")));
|
||||
self.confirm_menu.selected = ConfirmMenuEntry::StartChallenge;
|
||||
|
||||
self.controller.update(state, ctx)?;
|
||||
self.controller.update_trigger();
|
||||
|
@ -237,19 +285,19 @@ impl Scene for TitleScene {
|
|||
|
||||
match self.current_menu {
|
||||
CurrentMenu::MainMenu => match self.main_menu.tick(&mut self.controller, state) {
|
||||
MenuSelectionResult::Selected(0, _) => {
|
||||
MenuSelectionResult::Selected(MainMenuEntry::Start, _) => {
|
||||
state.mod_path = None;
|
||||
self.save_select_menu.init(state, ctx)?;
|
||||
self.save_select_menu.set_skip_difficulty_menu(false);
|
||||
self.current_menu = CurrentMenu::SaveSelectMenu;
|
||||
}
|
||||
MenuSelectionResult::Selected(1, _) => {
|
||||
MenuSelectionResult::Selected(MainMenuEntry::Challenges, _) => {
|
||||
self.current_menu = CurrentMenu::ChallengesMenu;
|
||||
}
|
||||
MenuSelectionResult::Selected(2, _) => {
|
||||
MenuSelectionResult::Selected(MainMenuEntry::Options, _) => {
|
||||
self.current_menu = CurrentMenu::OptionMenu;
|
||||
}
|
||||
MenuSelectionResult::Selected(3, _) => {
|
||||
MenuSelectionResult::Selected(MainMenuEntry::Editor, _) => {
|
||||
// this comment is just there because rustfmt removes parenthesis around the match case and breaks compilation
|
||||
#[cfg(feature = "editor")]
|
||||
{
|
||||
|
@ -257,10 +305,10 @@ impl Scene for TitleScene {
|
|||
state.next_scene = Some(Box::new(EditorScene::new()));
|
||||
}
|
||||
}
|
||||
MenuSelectionResult::Selected(4, _) => {
|
||||
MenuSelectionResult::Selected(MainMenuEntry::Jukebox, _) => {
|
||||
state.next_scene = Some(Box::new(JukeboxScene::new()));
|
||||
}
|
||||
MenuSelectionResult::Selected(5, _) => {
|
||||
MenuSelectionResult::Selected(MainMenuEntry::Quit, _) => {
|
||||
state.shutdown();
|
||||
}
|
||||
_ => {}
|
||||
|
@ -292,68 +340,70 @@ impl Scene for TitleScene {
|
|||
ctx,
|
||||
)?;
|
||||
}
|
||||
CurrentMenu::ChallengesMenu => {
|
||||
let last_idx = self.challenges_menu.entries.len() - 1;
|
||||
match self.challenges_menu.tick(&mut self.controller, state) {
|
||||
MenuSelectionResult::Selected(idx, _) => {
|
||||
if last_idx == idx {
|
||||
state.mod_path = None;
|
||||
CurrentMenu::ChallengesMenu => match self.challenges_menu.tick(&mut self.controller, state) {
|
||||
MenuSelectionResult::Selected(ChallengesMenuEntry::Challenge(idx), _) => {
|
||||
if let Some(mod_info) = state.mod_list.mods.get(idx) {
|
||||
state.mod_path = Some(mod_info.path.clone());
|
||||
if mod_info.save_slot >= 0 {
|
||||
self.save_select_menu.init(state, ctx)?;
|
||||
self.save_select_menu.set_skip_difficulty_menu(true);
|
||||
self.nikumaru_rec.load_counter(state, ctx)?;
|
||||
self.current_menu = CurrentMenu::MainMenu;
|
||||
} else if let Some(mod_info) = state.mod_list.mods.get(idx) {
|
||||
state.mod_path = Some(mod_info.path.clone());
|
||||
if mod_info.save_slot >= 0 {
|
||||
self.save_select_menu.init(state, ctx)?;
|
||||
self.save_select_menu.set_skip_difficulty_menu(true);
|
||||
self.nikumaru_rec.load_counter(state, ctx)?;
|
||||
self.current_menu = CurrentMenu::SaveSelectMenu;
|
||||
self.current_menu = CurrentMenu::SaveSelectMenu;
|
||||
} else {
|
||||
let mod_name = mod_info.name.clone();
|
||||
self.confirm_menu.width =
|
||||
(state.font.text_width(mod_name.chars(), &state.constants).max(50.0) + 32.0) as u16;
|
||||
|
||||
self.confirm_menu.set_entry(ConfirmMenuEntry::Title, MenuEntry::Disabled(mod_name));
|
||||
|
||||
if state.has_replay_data(ctx) {
|
||||
self.confirm_menu.set_entry(
|
||||
ConfirmMenuEntry::ReplayBest,
|
||||
MenuEntry::Active(state.t("menus.challenge_menu.replay_best")),
|
||||
);
|
||||
self.confirm_menu.set_entry(
|
||||
ConfirmMenuEntry::DeleteReplay,
|
||||
MenuEntry::Active(state.t("menus.challenge_menu.delete_replay")),
|
||||
);
|
||||
} else {
|
||||
let mod_name = mod_info.name.clone();
|
||||
self.confirm_menu.width =
|
||||
(state.font.text_width(mod_name.chars(), &state.constants).max(50.0) + 32.0) as u16;
|
||||
self.confirm_menu.entries[0] = MenuEntry::Disabled(mod_name);
|
||||
if state.has_replay_data(ctx) {
|
||||
self.confirm_menu.entries[2] =
|
||||
MenuEntry::Active(state.t("menus.challenge_menu.replay_best"));
|
||||
self.confirm_menu.entries[3] =
|
||||
MenuEntry::Active(state.t("menus.challenge_menu.delete_replay"));
|
||||
} else {
|
||||
self.confirm_menu.entries[2] =
|
||||
MenuEntry::Disabled(state.t("menus.challenge_menu.no_replay"));
|
||||
self.confirm_menu.entries[3] = MenuEntry::Hidden;
|
||||
}
|
||||
self.nikumaru_rec.load_counter(state, ctx)?;
|
||||
self.current_menu = CurrentMenu::ChallengeConfirmMenu;
|
||||
self.confirm_menu.set_entry(
|
||||
ConfirmMenuEntry::ReplayBest,
|
||||
MenuEntry::Disabled(state.t("menus.challenge_menu.no_replay")),
|
||||
);
|
||||
self.confirm_menu.set_entry(ConfirmMenuEntry::DeleteReplay, MenuEntry::Hidden);
|
||||
}
|
||||
state.reload_graphics();
|
||||
|
||||
self.nikumaru_rec.load_counter(state, ctx)?;
|
||||
self.current_menu = CurrentMenu::ChallengeConfirmMenu;
|
||||
}
|
||||
}
|
||||
MenuSelectionResult::Canceled => {
|
||||
state.mod_path = None;
|
||||
self.nikumaru_rec.load_counter(state, ctx)?;
|
||||
self.current_menu = CurrentMenu::MainMenu;
|
||||
state.reload_graphics();
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
MenuSelectionResult::Selected(ChallengesMenuEntry::Back, _) | MenuSelectionResult::Canceled => {
|
||||
state.mod_path = None;
|
||||
self.nikumaru_rec.load_counter(state, ctx)?;
|
||||
self.current_menu = CurrentMenu::MainMenu;
|
||||
state.reload_graphics();
|
||||
}
|
||||
_ => (),
|
||||
},
|
||||
CurrentMenu::ChallengeConfirmMenu => match self.confirm_menu.tick(&mut self.controller, state) {
|
||||
MenuSelectionResult::Selected(1, _) => {
|
||||
MenuSelectionResult::Selected(ConfirmMenuEntry::StartChallenge, _) => {
|
||||
state.difficulty = GameDifficulty::Normal;
|
||||
state.replay_state = ReplayState::Recording;
|
||||
self.current_menu = CurrentMenu::PlayerCountMenu;
|
||||
}
|
||||
MenuSelectionResult::Selected(2, _) => {
|
||||
MenuSelectionResult::Selected(ConfirmMenuEntry::ReplayBest, _) => {
|
||||
state.difficulty = GameDifficulty::Normal;
|
||||
state.replay_state = ReplayState::Playback;
|
||||
state.reload_resources(ctx)?;
|
||||
state.start_new_game(ctx)?;
|
||||
}
|
||||
MenuSelectionResult::Selected(3, _) => {
|
||||
MenuSelectionResult::Selected(ConfirmMenuEntry::DeleteReplay, _) => {
|
||||
state.delete_replay_data(ctx)?;
|
||||
self.current_menu = CurrentMenu::ChallengesMenu;
|
||||
}
|
||||
MenuSelectionResult::Selected(4, _) | MenuSelectionResult::Canceled => {
|
||||
MenuSelectionResult::Selected(ConfirmMenuEntry::Back, _) | MenuSelectionResult::Canceled => {
|
||||
self.current_menu = CurrentMenu::ChallengesMenu;
|
||||
}
|
||||
_ => (),
|
||||
|
|
|
@ -94,7 +94,7 @@ impl WindowMode {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Copy, Clone, num_derive::FromPrimitive)]
|
||||
#[derive(PartialEq, Eq, Copy, Clone, Debug, num_derive::FromPrimitive)]
|
||||
pub enum GameDifficulty {
|
||||
Normal = 0,
|
||||
Easy = 2,
|
||||
|
@ -113,7 +113,7 @@ impl GameDifficulty {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Copy, Clone, Hash, num_derive::FromPrimitive, serde::Serialize, serde::Deserialize)]
|
||||
#[derive(PartialEq, Eq, Copy, Clone, Debug, Hash, num_derive::FromPrimitive, serde::Serialize, serde::Deserialize)]
|
||||
pub enum Language {
|
||||
English,
|
||||
Japanese,
|
||||
|
|
Loading…
Reference in a new issue