diff --git a/config_spec.yml b/config_spec.yml index b858606e68..d79c3db738 100644 --- a/config_spec.yml +++ b/config_spec.yml @@ -7,6 +7,7 @@ general: type: bool default: true screenshot_dir: string + games_dir: string skip_boot_anim: bool # throttle_io: bool last_viewed_menu_index: integer diff --git a/ui/xui/actions.cc b/ui/xui/actions.cc index dc2c830c50..dc5b86d3cc 100644 --- a/ui/xui/actions.cc +++ b/ui/xui/actions.cc @@ -36,8 +36,6 @@ void ActionEjectDisc(void) void ActionLoadDisc(void) { - Error *err = NULL; - const char *iso_file_filters = ".iso Files\0*.iso\0All Files\0*.*\0"; const char *new_disc_path = PausedFileOpen(NOC_FILE_DIALOG_OPEN, iso_file_filters, @@ -47,7 +45,14 @@ void ActionLoadDisc(void) return; } - xemu_load_disc(new_disc_path, &err); + ActionLoadDiscFile(new_disc_path); +} + +void ActionLoadDiscFile(const char *file_path) +{ + Error *err = NULL; + xemu_load_disc(file_path, &err); + if (err) { xemu_queue_error_message(error_get_pretty(err)); error_free(err); diff --git a/ui/xui/actions.hh b/ui/xui/actions.hh index 08aedd3c9b..d0aff3fd23 100644 --- a/ui/xui/actions.hh +++ b/ui/xui/actions.hh @@ -20,6 +20,7 @@ void ActionEjectDisc(); void ActionLoadDisc(); +void ActionLoadDiscFile(const char *file_path); void ActionTogglePause(); void ActionReset(); void ActionShutdown(); diff --git a/ui/xui/main-menu.cc b/ui/xui/main-menu.cc index 75b88cafb6..fed22c79df 100644 --- a/ui/xui/main-menu.cc +++ b/ui/xui/main-menu.cc @@ -71,6 +71,7 @@ void MainMenuGeneralView::Draw() "Skip the full Xbox boot animation sequence"); FilePicker("Screenshot output directory", &g_config.general.screenshot_dir, NULL, true); + FilePicker("Games directory", &g_config.general.games_dir, NULL, true); // toggle("Throttle DVD/HDD speeds", &g_config.general.throttle_io, // "Limit DVD/HDD throughput to approximate Xbox load times"); } diff --git a/ui/xui/popup-menu.cc b/ui/xui/popup-menu.cc index 82ae785137..9679f8523e 100644 --- a/ui/xui/popup-menu.cc +++ b/ui/xui/popup-menu.cc @@ -17,19 +17,21 @@ // along with this program. If not, see . // #include "ui/xemu-notifications.h" -#include -#include -#include "misc.hh" +#include "popup-menu.hh" +#include "../xemu-snapshots.h" +#include "IconsFontAwesome6.h" #include "actions.hh" #include "font-manager.hh" -#include "viewport-manager.hh" -#include "scene-manager.hh" -#include "popup-menu.hh" #include "input-manager.hh" -#include "xemu-hud.h" -#include "IconsFontAwesome6.h" -#include "../xemu-snapshots.h" #include "main-menu.hh" +#include "misc.hh" +#include "scene-manager.hh" +#include "viewport-manager.hh" +#include "xemu-hud.h" +#include +#include +#include +#include PopupMenuItemDelegate::~PopupMenuItemDelegate() {} void PopupMenuItemDelegate::PushMenu(PopupMenu &menu) {} @@ -338,9 +340,58 @@ public: } }; +class GamesPopupMenu : public virtual PopupMenu { +public: + bool DrawItems(PopupMenuItemDelegate &nav) override + { + bool pop = false; + + if (m_focus && !m_pop_focus) { + ImGui::SetKeyboardFocusHere(); + } + + const char *games_dir = g_config.general.games_dir; + std::filesystem::path directory(games_dir); + std::multimap sorted_file_names; + + if (std::filesystem::is_directory(directory)) { + for (const auto &entry : + std::filesystem::directory_iterator(directory)) { + const auto &entry_path = entry.path(); + if (std::filesystem::is_regular_file(entry_path) && + entry_path.extension() == ".iso") { + sorted_file_names.insert( + { entry_path.stem().string(), entry_path }); + } + } + } + + for (const auto &[label, file_path] : sorted_file_names) { + if (PopupMenuButton(label, ICON_FA_GAMEPAD)) { + ActionLoadDiscFile(file_path.c_str()); + nav.ClearMenuStack(); + pop = true; + } + } + + if (sorted_file_names.size() == 0) { + if (PopupMenuButton("No games found", ICON_FA_SLIDERS)) { + nav.ClearMenuStack(); + g_scene_mgr.PushScene(g_main_menu); + } + } + + if (m_pop_focus) { + nav.PopFocus(); + } + return pop; + } +}; + class RootPopupMenu : public virtual PopupMenu { protected: SettingsPopupMenu settings; + GamesPopupMenu games; bool refocus_first_item; public: @@ -378,6 +429,10 @@ public: xemu_queue_notification("Created new snapshot"); pop = true; } + if (PopupMenuSubmenuButton("Games", ICON_FA_GAMEPAD)) { + nav.PushFocus(); + nav.PushMenu(games); + } if (PopupMenuButton("Eject Disc", ICON_FA_EJECT)) { ActionEjectDisc(); pop = true;