mirror of
https://github.com/doukutsu-rs/doukutsu-rs
synced 2025-04-07 12:24:31 +00:00
add menu options for opening user and data dirs
This commit is contained in:
parent
30c85c2f8b
commit
d6715bccea
|
@ -73,6 +73,7 @@ log = "0.4"
|
|||
lua-ffi = { git = "https://github.com/doukutsu-rs/lua-ffi.git", rev = "e0b2ff5960f7ef9974aa9675cebe4907bee0134f", optional = true }
|
||||
num-derive = "0.3"
|
||||
num-traits = "0.2"
|
||||
open = "3.2"
|
||||
paste = "1.0"
|
||||
pelite = { version = ">=0.9.2", default-features = false, features = ["std"] }
|
||||
sdl2 = { git = "https://github.com/doukutsu-rs/rust-sdl2.git", rev = "95bcf63768abf422527f86da41da910649b9fcc9", optional = true, features = ["unsafe_textures", "bundled", "static-link"] }
|
||||
|
|
|
@ -128,7 +128,12 @@
|
|||
"fastforward": "Fast-Forward"
|
||||
}
|
||||
},
|
||||
"links": "Links..."
|
||||
"links": "Links...",
|
||||
"advanced": "Advanced...",
|
||||
"advanced_menu": {
|
||||
"open_user_data": "Open user data directory",
|
||||
"open_game_data": "Open game data directory"
|
||||
}
|
||||
},
|
||||
"controls_menu": {
|
||||
"select_player": {
|
||||
|
|
|
@ -128,7 +128,12 @@
|
|||
"fastforward": "はやおくり"
|
||||
}
|
||||
},
|
||||
"links": "リンク"
|
||||
"links": "リンク",
|
||||
"advanced": "詳細設定",
|
||||
"advanced_menu": {
|
||||
"open_user_data": "ユーザープロファイルを開く",
|
||||
"open_game_data": "ゲームファイルを開く"
|
||||
}
|
||||
},
|
||||
"controls_menu": {
|
||||
"select_player": {
|
||||
|
|
171
src/game/filesystem_container.rs
Normal file
171
src/game/filesystem_container.rs
Normal file
|
@ -0,0 +1,171 @@
|
|||
use std::path::PathBuf;
|
||||
|
||||
use crate::{
|
||||
data::builtin_fs::BuiltinFS,
|
||||
framework::{
|
||||
context::Context,
|
||||
error::GameResult,
|
||||
filesystem::{mount_user_vfs, mount_vfs},
|
||||
vfs::PhysicalFS,
|
||||
},
|
||||
};
|
||||
|
||||
pub struct FilesystemContainer {
|
||||
pub user_path: PathBuf,
|
||||
pub game_path: PathBuf,
|
||||
}
|
||||
|
||||
impl FilesystemContainer {
|
||||
pub fn new() -> Self {
|
||||
Self { user_path: PathBuf::new(), game_path: PathBuf::new() }
|
||||
}
|
||||
|
||||
pub fn mount_fs(&mut self, context: &mut Context) -> GameResult {
|
||||
#[cfg(not(any(target_os = "android", target_os = "horizon")))]
|
||||
let resource_dir = if let Ok(data_dir) = std::env::var("CAVESTORY_DATA_DIR") {
|
||||
PathBuf::from(data_dir)
|
||||
} else {
|
||||
let mut resource_dir = std::env::current_exe()?;
|
||||
if resource_dir.file_name().is_some() {
|
||||
let _ = resource_dir.pop();
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
{
|
||||
let mut bundle_dir = resource_dir.clone();
|
||||
let _ = bundle_dir.pop();
|
||||
let mut bundle_exec_dir = bundle_dir.clone();
|
||||
let mut csplus_data_dir = bundle_dir.clone();
|
||||
let _ = csplus_data_dir.pop();
|
||||
let _ = csplus_data_dir.pop();
|
||||
let mut csplus_data_base_dir = csplus_data_dir.clone();
|
||||
csplus_data_base_dir.push("data");
|
||||
csplus_data_base_dir.push("base");
|
||||
|
||||
bundle_exec_dir.push("MacOS");
|
||||
bundle_dir.push("Resources");
|
||||
|
||||
if bundle_exec_dir.is_dir() && bundle_dir.is_dir() {
|
||||
log::info!("Running in macOS bundle mode");
|
||||
|
||||
if csplus_data_base_dir.is_dir() {
|
||||
log::info!("Cave Story+ Steam detected");
|
||||
resource_dir = csplus_data_dir;
|
||||
} else {
|
||||
resource_dir = bundle_dir;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resource_dir.push("data");
|
||||
resource_dir
|
||||
};
|
||||
|
||||
#[cfg(not(any(target_os = "android", target_os = "horizon")))]
|
||||
log::info!("Resource directory: {:?}", resource_dir);
|
||||
|
||||
log::info!("Initializing engine...");
|
||||
|
||||
#[cfg(not(any(target_os = "android", target_os = "horizon")))]
|
||||
{
|
||||
mount_vfs(context, Box::new(PhysicalFS::new(&resource_dir, true)));
|
||||
self.game_path = resource_dir.clone();
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "android", target_os = "horizon")))]
|
||||
let project_dirs = match directories::ProjectDirs::from("", "", "doukutsu-rs") {
|
||||
Some(dirs) => dirs,
|
||||
None => {
|
||||
use crate::framework::error::GameError;
|
||||
return Err(GameError::FilesystemError(String::from(
|
||||
"No valid home directory path could be retrieved.",
|
||||
)));
|
||||
}
|
||||
};
|
||||
#[cfg(target_os = "android")]
|
||||
{
|
||||
let mut data_path =
|
||||
PathBuf::from(ndk_glue::native_activity().internal_data_path().to_string_lossy().to_string());
|
||||
let mut user_path = data_path.clone();
|
||||
|
||||
data_path.push("data");
|
||||
user_path.push("saves");
|
||||
|
||||
let _ = std::fs::create_dir_all(&data_path);
|
||||
let _ = std::fs::create_dir_all(&user_path);
|
||||
|
||||
log::info!("Android data directories: data_path={:?} user_path={:?}", &data_path, &user_path);
|
||||
|
||||
mount_vfs(context, Box::new(PhysicalFS::new(&data_path, true)));
|
||||
mount_user_vfs(context, Box::new(PhysicalFS::new(&user_path, false)));
|
||||
|
||||
self.user_path = user_path.clone();
|
||||
self.game_path = data_path.clone();
|
||||
}
|
||||
#[cfg(target_os = "horizon")]
|
||||
{
|
||||
let mut data_path = PathBuf::from("sdmc:/switch/doukutsu-rs/data");
|
||||
let mut user_path = PathBuf::from("sdmc:/switch/doukutsu-rs/user");
|
||||
|
||||
let _ = std::fs::create_dir_all(&data_path);
|
||||
let _ = std::fs::create_dir_all(&user_path);
|
||||
|
||||
log::info!("Mounting VFS");
|
||||
mount_vfs(context, Box::new(PhysicalFS::new(&data_path, true)));
|
||||
if crate::framework::backend_horizon::mount_romfs() {
|
||||
mount_vfs(context, Box::new(PhysicalFS::new_lowercase(&PathBuf::from("romfs:/data"))));
|
||||
}
|
||||
log::info!("Mounting user VFS");
|
||||
mount_user_vfs(context, Box::new(PhysicalFS::new(&user_path, false)));
|
||||
log::info!("ok");
|
||||
|
||||
self.user_path = user_path.clone();
|
||||
self.game_path = data_path.clone();
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "android", target_os = "horizon")))]
|
||||
{
|
||||
if crate::framework::filesystem::open(&context, "/.drs_localstorage").is_ok() {
|
||||
let mut user_dir = resource_dir.clone();
|
||||
user_dir.push("_drs_profile");
|
||||
|
||||
let _ = std::fs::create_dir_all(&user_dir);
|
||||
mount_user_vfs(context, Box::new(PhysicalFS::new(&user_dir, false)));
|
||||
|
||||
self.user_path = user_dir.clone();
|
||||
} else {
|
||||
let user_dir = project_dirs.data_local_dir();
|
||||
mount_user_vfs(context, Box::new(PhysicalFS::new(user_dir, false)));
|
||||
|
||||
self.user_path = user_dir.to_path_buf();
|
||||
}
|
||||
}
|
||||
|
||||
log::info!("Mounting built-in FS");
|
||||
mount_vfs(context, Box::new(BuiltinFS::new()));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn open_user_directory(&self) -> GameResult {
|
||||
self.open_directory(self.user_path.clone())
|
||||
}
|
||||
|
||||
pub fn open_game_directory(&self) -> GameResult {
|
||||
self.open_directory(self.game_path.clone())
|
||||
}
|
||||
|
||||
fn open_directory(&self, path: PathBuf) -> GameResult {
|
||||
#[cfg(target_os = "horizon")]
|
||||
return Ok(()); // can't open directories on switch
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
return Ok(()); // TODO: figure out how to do this on android
|
||||
|
||||
#[cfg(not(any(target_os = "android", target_os = "horizon")))]
|
||||
open::that(path).map_err(|e| {
|
||||
use crate::framework::error::GameError;
|
||||
GameError::FilesystemError(format!("Failed to open directory: {}", e))
|
||||
})
|
||||
}
|
||||
}
|
114
src/game/mod.rs
114
src/game/mod.rs
|
@ -1,5 +1,4 @@
|
|||
use std::cell::UnsafeCell;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Mutex;
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
|
@ -7,20 +6,19 @@ use lazy_static::lazy_static;
|
|||
|
||||
use scripting::tsc::text_script::ScriptMode;
|
||||
|
||||
use crate::data::builtin_fs::BuiltinFS;
|
||||
use crate::framework::context::Context;
|
||||
use crate::framework::error::GameResult;
|
||||
use crate::framework::filesystem::{mount_user_vfs, mount_vfs};
|
||||
use crate::framework::graphics;
|
||||
use crate::framework::graphics::VSyncMode;
|
||||
use crate::framework::ui::UI;
|
||||
use crate::framework::vfs::PhysicalFS;
|
||||
use crate::game::filesystem_container::FilesystemContainer;
|
||||
use crate::game::shared_game_state::{Fps, SharedGameState, TimingMode};
|
||||
use crate::graphics::texture_set::{G_MAG, I_MAG};
|
||||
use crate::scene::loading_scene::LoadingScene;
|
||||
use crate::scene::Scene;
|
||||
|
||||
pub mod caret;
|
||||
pub mod filesystem_container;
|
||||
pub mod frame;
|
||||
pub mod inventory;
|
||||
pub mod map;
|
||||
|
@ -221,112 +219,10 @@ pub fn init(options: LaunchOptions) -> GameResult {
|
|||
.with_level(log::Level::Info.to_level_filter())
|
||||
.init();
|
||||
|
||||
#[cfg(not(any(target_os = "android", target_os = "horizon")))]
|
||||
let resource_dir = if let Ok(data_dir) = std::env::var("CAVESTORY_DATA_DIR") {
|
||||
PathBuf::from(data_dir)
|
||||
} else {
|
||||
let mut resource_dir = std::env::current_exe()?;
|
||||
if resource_dir.file_name().is_some() {
|
||||
let _ = resource_dir.pop();
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
{
|
||||
let mut bundle_dir = resource_dir.clone();
|
||||
let _ = bundle_dir.pop();
|
||||
let mut bundle_exec_dir = bundle_dir.clone();
|
||||
let mut csplus_data_dir = bundle_dir.clone();
|
||||
let _ = csplus_data_dir.pop();
|
||||
let _ = csplus_data_dir.pop();
|
||||
let mut csplus_data_base_dir = csplus_data_dir.clone();
|
||||
csplus_data_base_dir.push("data");
|
||||
csplus_data_base_dir.push("base");
|
||||
|
||||
bundle_exec_dir.push("MacOS");
|
||||
bundle_dir.push("Resources");
|
||||
|
||||
if bundle_exec_dir.is_dir() && bundle_dir.is_dir() {
|
||||
log::info!("Running in macOS bundle mode");
|
||||
|
||||
if csplus_data_base_dir.is_dir() {
|
||||
log::info!("Cave Story+ Steam detected");
|
||||
resource_dir = csplus_data_dir;
|
||||
} else {
|
||||
resource_dir = bundle_dir;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resource_dir.push("data");
|
||||
resource_dir
|
||||
};
|
||||
|
||||
#[cfg(not(any(target_os = "android", target_os = "horizon")))]
|
||||
log::info!("Resource directory: {:?}", resource_dir);
|
||||
log::info!("Initializing engine...");
|
||||
|
||||
let mut context = Box::pin(Context::new());
|
||||
#[cfg(not(any(target_os = "android", target_os = "horizon")))]
|
||||
mount_vfs(&mut context, Box::new(PhysicalFS::new(&resource_dir, true)));
|
||||
|
||||
#[cfg(not(any(target_os = "android", target_os = "horizon")))]
|
||||
let project_dirs = match directories::ProjectDirs::from("", "", "doukutsu-rs") {
|
||||
Some(dirs) => dirs,
|
||||
None => {
|
||||
use crate::framework::error::GameError;
|
||||
return Err(GameError::FilesystemError(String::from("No valid home directory path could be retrieved.")));
|
||||
}
|
||||
};
|
||||
#[cfg(target_os = "android")]
|
||||
{
|
||||
let mut data_path =
|
||||
PathBuf::from(ndk_glue::native_activity().internal_data_path().to_string_lossy().to_string());
|
||||
let mut user_path = data_path.clone();
|
||||
|
||||
data_path.push("data");
|
||||
user_path.push("saves");
|
||||
|
||||
let _ = std::fs::create_dir_all(&data_path);
|
||||
let _ = std::fs::create_dir_all(&user_path);
|
||||
|
||||
log::info!("Android data directories: data_path={:?} user_path={:?}", &data_path, &user_path);
|
||||
|
||||
mount_vfs(&mut context, Box::new(PhysicalFS::new(&data_path, true)));
|
||||
mount_user_vfs(&mut context, Box::new(PhysicalFS::new(&user_path, false)));
|
||||
}
|
||||
#[cfg(target_os = "horizon")]
|
||||
{
|
||||
let mut data_path = PathBuf::from("sdmc:/switch/doukutsu-rs/data");
|
||||
let mut user_path = PathBuf::from("sdmc:/switch/doukutsu-rs/user");
|
||||
|
||||
let _ = std::fs::create_dir_all(&data_path);
|
||||
let _ = std::fs::create_dir_all(&user_path);
|
||||
|
||||
log::info!("Mounting VFS");
|
||||
mount_vfs(&mut context, Box::new(PhysicalFS::new(&data_path, true)));
|
||||
if crate::framework::backend_horizon::mount_romfs() {
|
||||
mount_vfs(&mut context, Box::new(PhysicalFS::new_lowercase(&PathBuf::from("romfs:/data"))));
|
||||
}
|
||||
log::info!("Mounting user VFS");
|
||||
mount_user_vfs(&mut context, Box::new(PhysicalFS::new(&user_path, false)));
|
||||
log::info!("ok");
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "android", target_os = "horizon")))]
|
||||
{
|
||||
if crate::framework::filesystem::open(&context, "/.drs_localstorage").is_ok() {
|
||||
let mut user_dir = resource_dir.clone();
|
||||
user_dir.push("_drs_profile");
|
||||
|
||||
let _ = std::fs::create_dir_all(&user_dir);
|
||||
mount_user_vfs(&mut context, Box::new(PhysicalFS::new(&user_dir, false)));
|
||||
} else {
|
||||
mount_user_vfs(&mut context, Box::new(PhysicalFS::new(project_dirs.data_local_dir(), false)));
|
||||
}
|
||||
}
|
||||
|
||||
log::info!("Mounting built-in FS");
|
||||
mount_vfs(&mut context, Box::new(BuiltinFS::new()));
|
||||
let mut fs_container = FilesystemContainer::new();
|
||||
fs_container.mount_fs(&mut context)?;
|
||||
|
||||
if options.server_mode {
|
||||
log::info!("Running in server mode...");
|
||||
|
@ -339,6 +235,8 @@ pub fn init(options: LaunchOptions) -> GameResult {
|
|||
game.state.get().lua.update_refs(unsafe { &mut *game.state.get() }, &mut context as *mut Context);
|
||||
}
|
||||
|
||||
game.state.get_mut().fs_container = Some(fs_container);
|
||||
|
||||
game.state.get_mut().next_scene = Some(Box::new(LoadingScene::new()));
|
||||
log::info!("Starting main loop...");
|
||||
context.run(game.as_mut().get_mut())?;
|
||||
|
|
|
@ -34,6 +34,8 @@ use crate::sound::SoundManager;
|
|||
use crate::util::bitvec::BitVec;
|
||||
use crate::util::rng::XorShift;
|
||||
|
||||
use super::filesystem_container::FilesystemContainer;
|
||||
|
||||
#[derive(PartialEq, Eq, Copy, Clone, serde::Serialize, serde::Deserialize)]
|
||||
pub enum TimingMode {
|
||||
_50Hz,
|
||||
|
@ -314,6 +316,7 @@ pub struct SharedGameState {
|
|||
pub lightmap_canvas: Option<Box<dyn BackendTexture>>,
|
||||
pub season: Season,
|
||||
pub menu_character: MenuCharacter,
|
||||
pub fs_container: Option<FilesystemContainer>,
|
||||
pub constants: EngineConstants,
|
||||
pub font: BMFont,
|
||||
pub texture_set: TextureSet,
|
||||
|
@ -468,6 +471,7 @@ impl SharedGameState {
|
|||
lightmap_canvas: None,
|
||||
season,
|
||||
menu_character: MenuCharacter::Quote,
|
||||
fs_container: None,
|
||||
constants,
|
||||
font,
|
||||
texture_set: TextureSet::new(),
|
||||
|
|
|
@ -27,6 +27,7 @@ enum CurrentMenu {
|
|||
LanguageMenu,
|
||||
BehaviorMenu,
|
||||
LinksMenu,
|
||||
AdvancedMenu,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
|
||||
|
@ -37,6 +38,7 @@ enum MainMenuEntry {
|
|||
Language,
|
||||
Behavior,
|
||||
Links,
|
||||
Advanced,
|
||||
Back,
|
||||
}
|
||||
|
||||
|
@ -134,6 +136,20 @@ impl Default for LinksMenuEntry {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
|
||||
enum AdvancedMenuEntry {
|
||||
Title,
|
||||
OpenUserData,
|
||||
OpenGameData,
|
||||
Back,
|
||||
}
|
||||
|
||||
impl Default for AdvancedMenuEntry {
|
||||
fn default() -> Self {
|
||||
AdvancedMenuEntry::OpenUserData
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SettingsMenu {
|
||||
current: CurrentMenu,
|
||||
main: Menu<MainMenuEntry>,
|
||||
|
@ -143,6 +159,7 @@ pub struct SettingsMenu {
|
|||
language: Menu<LanguageMenuEntry>,
|
||||
behavior: Menu<BehaviorMenuEntry>,
|
||||
links: Menu<LinksMenuEntry>,
|
||||
advanced: Menu<AdvancedMenuEntry>,
|
||||
controls_menu: ControlsMenu,
|
||||
pub on_title: bool,
|
||||
}
|
||||
|
@ -164,6 +181,7 @@ impl SettingsMenu {
|
|||
let language = Menu::new(0, 0, 120, 0);
|
||||
let behavior = Menu::new(0, 0, 220, 0);
|
||||
let links = Menu::new(0, 0, 220, 0);
|
||||
let advanced = Menu::new(0, 0, 220, 0);
|
||||
|
||||
let controls_menu = ControlsMenu::new();
|
||||
|
||||
|
@ -176,6 +194,7 @@ impl SettingsMenu {
|
|||
language,
|
||||
behavior,
|
||||
links,
|
||||
advanced,
|
||||
controls_menu,
|
||||
on_title: false,
|
||||
}
|
||||
|
@ -349,6 +368,26 @@ impl SettingsMenu {
|
|||
);
|
||||
self.links.push_entry(LinksMenuEntry::Link(GETPLUS_LINK), MenuEntry::Active("Get Cave Story+".to_owned()));
|
||||
|
||||
#[cfg(not(any(target_os = "android", target_os = "horizon")))]
|
||||
self.main.push_entry(
|
||||
MainMenuEntry::Advanced,
|
||||
MenuEntry::Active(state.loc.t("menus.options_menu.advanced").to_owned()),
|
||||
);
|
||||
|
||||
self.advanced.push_entry(
|
||||
AdvancedMenuEntry::Title,
|
||||
MenuEntry::Disabled(state.loc.t("menus.options_menu.advanced").to_owned()),
|
||||
);
|
||||
self.advanced.push_entry(
|
||||
AdvancedMenuEntry::OpenUserData,
|
||||
MenuEntry::Active(state.loc.t("menus.options_menu.advanced_menu.open_user_data").to_owned()),
|
||||
);
|
||||
self.advanced.push_entry(
|
||||
AdvancedMenuEntry::OpenGameData,
|
||||
MenuEntry::Active(state.loc.t("menus.options_menu.advanced_menu.open_game_data").to_owned()),
|
||||
);
|
||||
self.advanced.push_entry(AdvancedMenuEntry::Back, MenuEntry::Active(state.loc.t("common.back").to_owned()));
|
||||
|
||||
self.main.push_entry(MainMenuEntry::Back, MenuEntry::Active(state.loc.t("common.back").to_owned()));
|
||||
|
||||
self.sound.push_entry(
|
||||
|
@ -507,6 +546,11 @@ impl SettingsMenu {
|
|||
self.links.update_height();
|
||||
self.links.x = ((state.canvas_size.0 - self.links.width as f32) / 2.0).floor() as isize;
|
||||
self.links.y = 30 + ((state.canvas_size.1 - self.links.height as f32) / 2.0).floor() as isize;
|
||||
|
||||
self.advanced.update_width(state);
|
||||
self.advanced.update_height();
|
||||
self.advanced.x = ((state.canvas_size.0 - self.advanced.width as f32) / 2.0).floor() as isize;
|
||||
self.advanced.y = 30 + ((state.canvas_size.1 - self.advanced.height as f32) / 2.0).floor() as isize;
|
||||
}
|
||||
|
||||
pub fn tick(
|
||||
|
@ -538,6 +582,9 @@ impl SettingsMenu {
|
|||
MenuSelectionResult::Selected(MainMenuEntry::Links, _) => {
|
||||
self.current = CurrentMenu::LinksMenu;
|
||||
}
|
||||
MenuSelectionResult::Selected(MainMenuEntry::Advanced, _) => {
|
||||
self.current = CurrentMenu::AdvancedMenu;
|
||||
}
|
||||
MenuSelectionResult::Selected(MainMenuEntry::Back, _) | MenuSelectionResult::Canceled => exit_action(),
|
||||
_ => (),
|
||||
},
|
||||
|
@ -868,6 +915,22 @@ impl SettingsMenu {
|
|||
}
|
||||
_ => (),
|
||||
},
|
||||
CurrentMenu::AdvancedMenu => match self.advanced.tick(controller, state) {
|
||||
MenuSelectionResult::Selected(AdvancedMenuEntry::OpenUserData, _) => {
|
||||
if let Some(fs_container) = &state.fs_container {
|
||||
fs_container.open_user_directory()?;
|
||||
}
|
||||
}
|
||||
MenuSelectionResult::Selected(AdvancedMenuEntry::OpenGameData, _) => {
|
||||
if let Some(fs_container) = &state.fs_container {
|
||||
fs_container.open_game_directory()?;
|
||||
}
|
||||
}
|
||||
MenuSelectionResult::Selected(AdvancedMenuEntry::Back, _) | MenuSelectionResult::Canceled => {
|
||||
self.current = CurrentMenu::MainMenu;
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
@ -882,6 +945,7 @@ impl SettingsMenu {
|
|||
CurrentMenu::LanguageMenu => self.language.draw(state, ctx)?,
|
||||
CurrentMenu::BehaviorMenu => self.behavior.draw(state, ctx)?,
|
||||
CurrentMenu::LinksMenu => self.links.draw(state, ctx)?,
|
||||
CurrentMenu::AdvancedMenu => self.advanced.draw(state, ctx)?,
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
|
Loading…
Reference in a new issue