diff --git a/src/Cafe/GraphicPack/GraphicPack2.cpp b/src/Cafe/GraphicPack/GraphicPack2.cpp index 6ae05c5b..ab4dbd3a 100644 --- a/src/Cafe/GraphicPack/GraphicPack2.cpp +++ b/src/Cafe/GraphicPack/GraphicPack2.cpp @@ -85,7 +85,7 @@ bool GraphicPack2::LoadGraphicPack(const fs::path& rulesPath, IniParser& rules) auto gp = std::make_shared(rulesPath, rules); // check if enabled and preset set - const auto& config_entries = g_config.data().graphic_pack_entries; + const auto& config_entries = GetConfigHandle().data().graphic_pack_entries; // legacy absolute path checking for not breaking compatibility auto file = gp->GetRulesPath(); diff --git a/src/config/ActiveSettings.cpp b/src/config/ActiveSettings.cpp index e552d164..58a83a15 100644 --- a/src/config/ActiveSettings.cpp +++ b/src/config/ActiveSettings.cpp @@ -60,14 +60,6 @@ bool ActiveSettings::DisplayDRCEnabled() return g_current_game_profile->StartWithGamepadView(); } -bool ActiveSettings::FullscreenEnabled() -{ - if (LaunchSettings::FullscreenEnabled().has_value()) - return LaunchSettings::FullscreenEnabled().value(); - - return GetConfig().fullscreen; -} - CPUMode ActiveSettings::GetCPUMode() { auto mode = g_current_game_profile->GetCPUMode().value_or(CPUMode::Auto); diff --git a/src/config/ActiveSettings.h b/src/config/ActiveSettings.h index 0d7ecfec..c01170e2 100644 --- a/src/config/ActiveSettings.h +++ b/src/config/ActiveSettings.h @@ -83,7 +83,6 @@ public: // general [[nodiscard]] static bool LoadSharedLibrariesEnabled(); [[nodiscard]] static bool DisplayDRCEnabled(); - [[nodiscard]] static bool FullscreenEnabled(); // cpu [[nodiscard]] static CPUMode GetCPUMode(); diff --git a/src/config/CemuConfig.cpp b/src/config/CemuConfig.cpp index 8022d139..620f005e 100644 --- a/src/config/CemuConfig.cpp +++ b/src/config/CemuConfig.cpp @@ -6,17 +6,15 @@ #include "ActiveSettings.h" -XMLCemuConfig_t g_config(L"settings.xml"); - void CemuConfig::SetMLCPath(fs::path path, bool save) { mlc_path.SetValue(_pathToUtf8(path)); if(save) - g_config.Save(); + GetConfigHandle().Save(); Account::RefreshAccounts(); } -void CemuConfig::Load(XMLConfigParser& parser) +XMLConfigParser CemuConfig::Load(XMLConfigParser& parser) { auto new_parser = parser.get("content"); if (new_parser.valid()) @@ -32,94 +30,11 @@ void CemuConfig::Load(XMLConfigParser& parser) permanent_storage = parser.get("permanent_storage", permanent_storage); - language = parser.get("language", 0); - use_discord_presence = parser.get("use_discord_presence", true); - fullscreen_menubar = parser.get("fullscreen_menubar", false); - feral_gamemode = parser.get("feral_gamemode", false); - check_update = parser.get("check_update", check_update); - receive_untested_updates = parser.get("receive_untested_updates", receive_untested_updates); - save_screenshot = parser.get("save_screenshot", save_screenshot); - did_show_vulkan_warning = parser.get("vk_warning", did_show_vulkan_warning); - did_show_graphic_pack_download = parser.get("gp_download", did_show_graphic_pack_download); - did_show_macos_disclaimer = parser.get("macos_disclaimer", did_show_macos_disclaimer); - fullscreen = parser.get("fullscreen", fullscreen); proxy_server = parser.get("proxy_server", ""); disable_screensaver = parser.get("disable_screensaver", disable_screensaver); play_boot_sound = parser.get("play_boot_sound", play_boot_sound); console_language = parser.get("console_language", console_language.GetInitValue()); - window_position.x = parser.get("window_position").get("x", -1); - window_position.y = parser.get("window_position").get("y", -1); - - window_size.x = parser.get("window_size").get("x", -1); - window_size.y = parser.get("window_size").get("y", -1); - window_maximized = parser.get("window_maximized", false); - - pad_open = parser.get("open_pad", false); - pad_position.x = parser.get("pad_position").get("x", -1); - pad_position.y = parser.get("pad_position").get("y", -1); - - pad_size.x = parser.get("pad_size").get("x", -1); - pad_size.y = parser.get("pad_size").get("y", -1); - pad_maximized = parser.get("pad_maximized", false); - - auto gamelist = parser.get("GameList"); - game_list_style = gamelist.get("style", 0); - game_list_column_order = gamelist.get("order", ""); - - show_icon_column = parser.get("show_icon_column", true); - - // return default width if value in config file out of range - auto loadColumnSize = [&gamelist] (const char *name, uint32 defaultWidth) - { - sint64 val = gamelist.get(name, DefaultColumnSize::name); - if (val < 0 || val > (sint64) std::numeric_limits::max) - return defaultWidth; - return static_cast(val); - }; - column_width.name = loadColumnSize("name_width", DefaultColumnSize::name); - column_width.version = loadColumnSize("version_width", DefaultColumnSize::version); - column_width.dlc = loadColumnSize("dlc_width", DefaultColumnSize::dlc); - column_width.game_time = loadColumnSize("game_time_width", DefaultColumnSize::game_time); - column_width.game_started = loadColumnSize("game_started_width", DefaultColumnSize::game_started); - column_width.region = loadColumnSize("region_width", DefaultColumnSize::region); - column_width.title_id = loadColumnSize("title_id", DefaultColumnSize::title_id); - - recent_launch_files.clear(); - auto launch_parser = parser.get("RecentLaunchFiles"); - for (auto element = launch_parser.get("Entry"); element.valid(); element = launch_parser.get("Entry", element)) - { - const std::string path = element.value(""); - if (path.empty()) - continue; - - try - { - recent_launch_files.emplace_back(path); - } - catch (const std::exception&) - { - cemuLog_log(LogType::Force, "config load error: can't load recently launched game file: {}", path); - } - } - - recent_nfc_files.clear(); - auto nfc_parser = parser.get("RecentNFCFiles"); - for (auto element = nfc_parser.get("Entry"); element.valid(); element = nfc_parser.get("Entry", element)) - { - const std::string path = element.value(""); - if (path.empty()) - continue; - try - { - recent_nfc_files.emplace_back(path); - } - catch (const std::exception&) - { - cemuLog_log(LogType::Force, "config load error: can't load recently launched nfc file: {}", path); - } - } - game_paths.clear(); auto game_path_parser = parser.get("GamePaths"); for (auto element = game_path_parser.get("Entry"); element.valid(); element = game_path_parser.get("Entry", element)) @@ -353,23 +268,16 @@ void CemuConfig::Load(XMLConfigParser& parser) dsu_client.host = dsuc.get_attribute("host", dsu_client.host); dsu_client.port = dsuc.get_attribute("port", dsu_client.port); - // hotkeys - auto xml_hotkeys = parser.get("Hotkeys"); - hotkeys.modifiers = xml_hotkeys.get("modifiers", WindowSystem::getDefaultHotkeyConfig(WindowSystem::HotKey::MODIFIERS)); - hotkeys.exitFullscreen = xml_hotkeys.get("ExitFullscreen", WindowSystem::getDefaultHotkeyConfig(WindowSystem::HotKey::EXIT_FULLSCREEN)); - hotkeys.toggleFullscreen = xml_hotkeys.get("ToggleFullscreen", WindowSystem::getDefaultHotkeyConfig(WindowSystem::HotKey::TOGGLE_FULLSCREEN)); - hotkeys.toggleFullscreenAlt = xml_hotkeys.get("ToggleFullscreenAlt", WindowSystem::getDefaultHotkeyConfig(WindowSystem::HotKey::TOGGLE_FULLSCREEN_ALT)); - hotkeys.takeScreenshot = xml_hotkeys.get("TakeScreenshot", WindowSystem::getDefaultHotkeyConfig(WindowSystem::HotKey::TAKE_SCREENSHOT)); - hotkeys.toggleFastForward = xml_hotkeys.get("ToggleFastForward", WindowSystem::getDefaultHotkeyConfig(WindowSystem::HotKey::TOGGLE_FAST_FORWARD)); - // emulatedusbdevices auto usbdevices = parser.get("EmulatedUsbDevices"); emulated_usb_devices.emulate_skylander_portal = usbdevices.get("EmulateSkylanderPortal", emulated_usb_devices.emulate_skylander_portal); emulated_usb_devices.emulate_infinity_base = usbdevices.get("EmulateInfinityBase", emulated_usb_devices.emulate_infinity_base); emulated_usb_devices.emulate_dimensions_toypad = usbdevices.get("EmulateDimensionsToypad", emulated_usb_devices.emulate_dimensions_toypad); + + return parser; } -void CemuConfig::Save(XMLConfigParser& parser) +XMLConfigParser CemuConfig::Save(XMLConfigParser& parser) { auto config = parser.set("content"); // general settings @@ -377,65 +285,12 @@ void CemuConfig::Save(XMLConfigParser& parser) config.set("advanced_ppc_logging", advanced_ppc_logging.GetValue()); config.set("mlc_path", mlc_path.GetValue().c_str()); config.set("permanent_storage", permanent_storage); - config.set("language", language); - config.set("use_discord_presence", use_discord_presence); - config.set("fullscreen_menubar", fullscreen_menubar); - config.set("feral_gamemode", feral_gamemode); - config.set("check_update", check_update); - config.set("receive_untested_updates", receive_untested_updates); - config.set("save_screenshot", save_screenshot); - config.set("vk_warning", did_show_vulkan_warning); - config.set("gp_download", did_show_graphic_pack_download); - config.set("macos_disclaimer", did_show_macos_disclaimer); - config.set("fullscreen", fullscreen); config.set("proxy_server", proxy_server.GetValue().c_str()); - config.set("disable_screensaver", disable_screensaver); config.set("play_boot_sound", play_boot_sound); // config.set("cpu_mode", cpu_mode.GetValue()); //config.set("console_region", console_region.GetValue()); config.set("console_language", console_language.GetValue()); - - auto wpos = config.set("window_position"); - wpos.set("x", window_position.x); - wpos.set("y", window_position.y); - auto wsize = config.set("window_size"); - wsize.set("x", window_size.x); - wsize.set("y", window_size.y); - config.set("window_maximized", window_maximized); - - config.set("open_pad", pad_open); - auto ppos = config.set("pad_position"); - ppos.set("x", pad_position.x); - ppos.set("y", pad_position.y); - auto psize = config.set("pad_size"); - psize.set("x", pad_size.x); - psize.set("y", pad_size.y); - config.set("pad_maximized", pad_maximized); - config.set("show_icon_column" , show_icon_column); - - auto gamelist = config.set("GameList"); - gamelist.set("style", game_list_style); - gamelist.set("order", game_list_column_order); - gamelist.set("name_width", column_width.name); - gamelist.set("version_width", column_width.version); - gamelist.set("dlc_width", column_width.dlc); - gamelist.set("game_time_width", column_width.game_time); - gamelist.set("game_started_width", column_width.game_started); - gamelist.set("region_width", column_width.region); - gamelist.set("title_id", column_width.title_id); - - auto launch_files_parser = config.set("RecentLaunchFiles"); - for (const auto& entry : recent_launch_files) - { - launch_files_parser.set("Entry", entry.c_str()); - } - - auto nfc_files_parser = config.set("RecentNFCFiles"); - for (const auto& entry : recent_nfc_files) - { - nfc_files_parser.set("Entry", entry.c_str()); - } // game paths auto game_path_parser = config.set("GamePaths"); @@ -565,20 +420,13 @@ void CemuConfig::Save(XMLConfigParser& parser) dsuc.set_attribute("host", dsu_client.host); dsuc.set_attribute("port", dsu_client.port); - // hotkeys - auto xml_hotkeys = config.set("Hotkeys"); - xml_hotkeys.set("modifiers", hotkeys.modifiers); - xml_hotkeys.set("ExitFullscreen", hotkeys.exitFullscreen); - xml_hotkeys.set("ToggleFullscreen", hotkeys.toggleFullscreen); - xml_hotkeys.set("ToggleFullscreenAlt", hotkeys.toggleFullscreenAlt); - xml_hotkeys.set("TakeScreenshot", hotkeys.takeScreenshot); - xml_hotkeys.set("ToggleFastForward", hotkeys.toggleFastForward); - // emulated usb devices auto usbdevices = config.set("EmulatedUsbDevices"); usbdevices.set("EmulateSkylanderPortal", emulated_usb_devices.emulate_skylander_portal.GetValue()); usbdevices.set("EmulateInfinityBase", emulated_usb_devices.emulate_infinity_base.GetValue()); usbdevices.set("EmulateDimensionsToypad", emulated_usb_devices.emulate_dimensions_toypad.GetValue()); + + return config; } GameEntry* CemuConfig::GetGameEntryByTitleId(uint64 titleId) @@ -645,22 +493,6 @@ void CemuConfig::SetGameListCustomName(uint64 titleId, std::string customName) gameEntry->custom_name = std::move(customName); } -void CemuConfig::AddRecentlyLaunchedFile(std::string_view file) -{ - recent_launch_files.insert(recent_launch_files.begin(), std::string(file)); - RemoveDuplicatesKeepOrder(recent_launch_files); - while(recent_launch_files.size() > kMaxRecentEntries) - recent_launch_files.pop_back(); -} - -void CemuConfig::AddRecentNfcFile(std::string_view file) -{ - recent_nfc_files.insert(recent_nfc_files.begin(), std::string(file)); - RemoveDuplicatesKeepOrder(recent_nfc_files); - while (recent_nfc_files.size() > kMaxRecentEntries) - recent_nfc_files.pop_back(); -} - NetworkService CemuConfig::GetAccountNetworkService(uint32 persistentId) { auto it = account.service_select.find(persistentId); diff --git a/src/config/CemuConfig.h b/src/config/CemuConfig.h index 95fea00b..ff892fb8 100644 --- a/src/config/CemuConfig.h +++ b/src/config/CemuConfig.h @@ -188,49 +188,6 @@ enum class CrashDump ENABLE_ENUM_ITERATORS(CrashDump, CrashDump::Disabled, CrashDump::Enabled); #endif -typedef union -{ - struct - { - uint16 key : 13; // enough bits for all keycodes - uint16 alt : 1; - uint16 ctrl : 1; - uint16 shift : 1; - }; - uint16 raw; -} uKeyboardHotkey; - -typedef sint16 ControllerHotkey_t; - -struct sHotkeyCfg -{ - static constexpr uint8 keyboardNone{0}; - static constexpr sint8 controllerNone{-1}; // no enums to work with, but buttons start from 0 - - uKeyboardHotkey keyboard{keyboardNone}; - ControllerHotkey_t controller{controllerNone}; - - /* for defaults */ - sHotkeyCfg(const uKeyboardHotkey& keyboard = {keyboardNone}, const ControllerHotkey_t& controller = {controllerNone}) : keyboard(keyboard), controller(controller) {}; - - /* for reading from xml */ - sHotkeyCfg(const char* xml_values) - { - std::istringstream iss(xml_values); - iss >> keyboard.raw >> controller; - } -}; - -template <> -struct fmt::formatter : formatter -{ - template - auto format(const sHotkeyCfg c, FormatContext &ctx) const { - std::string xml_values = fmt::format("{} {}", c.keyboard.raw, c.controller); - return formatter::format(xml_values, ctx); - } -}; - template <> struct fmt::formatter : formatter { template @@ -375,17 +332,6 @@ struct fmt::formatter : formatter { }; #endif -namespace DefaultColumnSize { - enum : uint32 { - name = 500u, - version = 60u, - dlc = 50u, - game_time = 140u, - game_started = 160u, - region = 80u, - title_id = 160u - }; -}; struct CemuConfig { @@ -404,12 +350,7 @@ struct CemuConfig ConfigValue permanent_storage{ true }; - ConfigValue language{ 0 }; - ConfigValue use_discord_presence{ true }; ConfigValue mlc_path{}; - ConfigValue fullscreen_menubar{ false }; - ConfigValue fullscreen{ false }; - ConfigValue feral_gamemode{false}; ConfigValue proxy_server{}; // temporary workaround because feature crashes on macOS @@ -440,43 +381,6 @@ struct CemuConfig ConfigValueBounds cpu_mode{ CPUMode::Auto }; ConfigValueBounds console_language{ CafeConsoleLanguage::EN }; - // max 15 entries - static constexpr size_t kMaxRecentEntries = 15; - std::vector recent_launch_files; - std::vector recent_nfc_files; - - Vector2i window_position{-1,-1}; - Vector2i window_size{ -1,-1 }; - ConfigValue window_maximized; - - ConfigValue pad_open; - Vector2i pad_position{ -1,-1 }; - Vector2i pad_size{ -1,-1 }; - ConfigValue pad_maximized; - - ConfigValue check_update{true}; - ConfigValue receive_untested_updates{false}; - ConfigValue save_screenshot{true}; - - ConfigValue did_show_vulkan_warning{false}; - ConfigValue did_show_graphic_pack_download{false}; // no longer used but we keep the config value around in case people downgrade Cemu. Despite the name this was used for the Getting Started dialog - ConfigValue did_show_macos_disclaimer{false}; - - ConfigValue show_icon_column{ true }; - - int game_list_style = 0; - std::string game_list_column_order; - struct - { - uint32 name = DefaultColumnSize::name; - uint32 version = DefaultColumnSize::version; - uint32 dlc = DefaultColumnSize::dlc; - uint32 game_time = DefaultColumnSize::game_time; - uint32 game_started = DefaultColumnSize::game_started; - uint32 region = DefaultColumnSize::region; - uint32 title_id = 0; - } column_width{}; - // graphics ConfigValue graphic_api{ kVulkan }; std::array graphic_device_uuid; @@ -539,26 +443,12 @@ struct CemuConfig ConfigValue port{ 26760 }; }dsu_client{}; - // hotkeys - struct - { - sHotkeyCfg modifiers; - sHotkeyCfg toggleFullscreen; - sHotkeyCfg toggleFullscreenAlt; - sHotkeyCfg exitFullscreen; - sHotkeyCfg takeScreenshot; - sHotkeyCfg toggleFastForward; - } hotkeys{}; - // debug ConfigValueBounds crash_dump{ CrashDump::Disabled }; ConfigValue gdb_port{ 1337 }; - void Load(XMLConfigParser& parser); - void Save(XMLConfigParser& parser); - - void AddRecentlyLaunchedFile(std::string_view file); - void AddRecentNfcFile(std::string_view file); + XMLConfigParser Load(XMLConfigParser& parser); + XMLConfigParser Save(XMLConfigParser& parser); bool IsGameListFavorite(uint64 titleId); void SetGameListFavorite(uint64 titleId, bool isFavorite); @@ -594,8 +484,15 @@ struct CemuConfig GameEntry* CreateGameEntry(uint64 titleId); }; -typedef XMLDataConfig XMLCemuConfig_t; -extern XMLCemuConfig_t g_config; -inline CemuConfig& GetConfig() { return g_config.data(); } +typedef XMLDataConfig XMLCemuConfig_t; +inline XMLCemuConfig_t& GetConfigHandle() +{ + static XMLCemuConfig_t config; + return config; +} +inline CemuConfig& GetConfig() +{ + return GetConfigHandle().data(); +} diff --git a/src/config/NetworkSettings.h b/src/config/NetworkSettings.h index 6e114a0e..6957cce4 100644 --- a/src/config/NetworkSettings.h +++ b/src/config/NetworkSettings.h @@ -71,7 +71,7 @@ struct PretendoURLs { inline static std::string OLVURL = "https://discovery.olv.pretendo.cc/v1/endpoint"; }; -typedef XMLDataConfig XMLNetworkConfig_t; +typedef XMLDataConfig XMLNetworkConfig_t; extern XMLNetworkConfig_t n_config; inline NetworkConfig& GetNetworkConfig() { return n_config.data();}; diff --git a/src/config/XMLConfig.h b/src/config/XMLConfig.h index dbec8a6e..eb730ef5 100644 --- a/src/config/XMLConfig.h +++ b/src/config/XMLConfig.h @@ -320,7 +320,15 @@ private: bool m_is_root; }; -template +using ChildXMLConfigParser = std::pair, std::function>; + +template +concept XMLConfigurable = requires(T t, XMLConfigParser& configParser) { + { t.Save(configParser) } -> std::same_as; + { t.Load(configParser) } -> std::same_as; +}; + +template class XMLConfig { public: @@ -339,9 +347,6 @@ public: bool Load() { - if (L == nullptr) - return false; - if (m_filename.empty()) return false; @@ -350,8 +355,6 @@ public: bool Load(const std::wstring& filename) { - if (L == nullptr) - return false; FileStream* fs = FileStream::openFile(filename.c_str()); if (!fs) { @@ -370,19 +373,23 @@ public: { cemuLog_logDebug(LogType::Force, "XMLConfig::Load > LoadFile {}", error); } - if (success) + + if (!success) { - auto parser = XMLConfigParser(&doc); - (m_instance.*L)(parser); + return false; } + + auto parser = XMLConfigParser(&doc); + auto parentParser = m_instance.Load(parser); + + for (auto [save, load] : m_childConfigParsers) + load(parentParser); + return true; } bool Save() { - if (S == nullptr) - return false; - if (m_filename.empty()) return false; @@ -391,9 +398,6 @@ public: bool Save(const std::wstring& filename) { - if (S == nullptr) - return false; - std::wstring tmp_name = fmt::format(L"{}_{}.tmp", filename,rand() % 1000); std::error_code err; fs::create_directories(fs::path(filename).parent_path(), err); @@ -420,7 +424,10 @@ public: doc.InsertFirstChild(declaration); auto parser = XMLConfigParser(&doc); - (m_instance.*S)(parser); + auto parentParser = m_instance.Save(parser); + + for (auto [save, load] : m_childConfigParsers) + save(parentParser); const tinyxml2::XMLError error = doc.SaveFile(file); const bool success = error == tinyxml2::XML_SUCCESS; @@ -445,24 +452,96 @@ public: std::unique_lock Lock() { return std::unique_lock(m_mutex); } -private: + void AddChildConfig(ChildXMLConfigParser childConfigParser) + { + m_childConfigParsers.push_back(childConfigParser); + } + + private: + std::vector m_childConfigParsers; T& m_instance; std::wstring m_filename; std::mutex m_mutex; }; -template -class XMLDataConfig : public XMLConfig +template +concept XMLConfigProvider = requires(T t, ChildXMLConfigParser& configParser) { + { t().Save() } -> std::same_as; + { t().Load() } -> std::same_as; + { t().Lock() } -> std::same_as>; + { t().AddChildConfig(configParser) } -> std::same_as; +}; + +template +class XMLChildConfig +{ + public: + XMLChildConfig(XMLConfigProvider auto getParentConfig) + { + m_parentConfig = { + .lock = [getParentConfig]() { return getParentConfig().Lock(); }, + .save = [getParentConfig]() { return getParentConfig().Load(); }, + .load = [getParentConfig]() { return getParentConfig().Save(); }, + }; + + auto configParser = std::make_pair( + [this](XMLConfigParser& parser) { + (m_data.*S)(parser); + }, + [this](XMLConfigParser& parser) { + (m_data.*L)(parser); + }); + + getParentConfig().AddChildConfig(configParser); + } + + bool Save() + { + return m_parentConfig.save(); + } + + bool Load() + { + return m_parentConfig.load(); + } + + T& Data() + { + return m_data; + } + + std::unique_lock Lock() + { + return m_parentConfig.lock(); + } + + virtual ~XMLChildConfig() = default; + + private: + T m_data; + struct + { + std::function()> lock; + std::function save; + std::function load; + } m_parentConfig; +}; + +template +struct XMLDataConfig {}; + +template +class XMLDataConfig : public XMLConfig { public: XMLDataConfig() - : XMLConfig::XMLConfig(m_data), m_data() {} + : XMLConfig::XMLConfig(m_data), m_data() {} XMLDataConfig(std::wstring_view filename) - : XMLConfig::XMLConfig(m_data, filename), m_data() {} + : XMLConfig::XMLConfig(m_data, filename), m_data() {} XMLDataConfig(std::wstring_view filename, T init_data) - : XMLConfig::XMLConfig(m_data, filename), m_data(std::move(init_data)) {} + : XMLConfig::XMLConfig(m_data, filename), m_data(std::move(init_data)) {} XMLDataConfig(const XMLDataConfig& o) = delete; @@ -471,3 +550,51 @@ public: private: T m_data; }; + +template +concept XMLStandaloneConfigurable = requires(T t, XMLConfigParser& configParser) { + { t.Save(configParser) } -> std::same_as; + { t.Load(configParser) } -> std::same_as; +}; + +template +struct XMLConfigWrapper +{ + XMLConfigParser Save(XMLConfigParser& configParser) + { + data.Save(configParser); + return configParser; + } + + XMLConfigParser Load(XMLConfigParser& configParser) + { + data.Load(configParser); + return configParser; + } + + T data; +}; + +template +class XMLDataConfig : public XMLConfig> +{ + public: + XMLDataConfig() + : XMLConfig>::XMLConfig(m_configWrapper), m_configWrapper() {} + + XMLDataConfig(std::wstring_view filename) + : XMLConfig>::XMLConfig(m_configWrapper, filename), m_configWrapper() {} + + XMLDataConfig(std::wstring_view filename, T init_data) + : XMLConfig>::XMLConfig(m_configWrapper, filename), m_configWrapper(std::move(init_data)) {} + + XMLDataConfig(const XMLDataConfig& o) = delete; + + T& data() + { + return m_configWrapper.data; + } + + private: + XMLConfigWrapper m_configWrapper; +}; diff --git a/src/gui/interface/WindowSystem.h b/src/gui/interface/WindowSystem.h index 48a30e1a..24daa938 100644 --- a/src/gui/interface/WindowSystem.h +++ b/src/gui/interface/WindowSystem.h @@ -123,17 +123,4 @@ namespace WindowSystem bool isFullScreen(); void captureInput(const ControllerState& currentState, const ControllerState& lastState); - - enum class HotKey - { - - MODIFIERS, - EXIT_FULLSCREEN, - TOGGLE_FULLSCREEN, - TOGGLE_FULLSCREEN_ALT, - TAKE_SCREENSHOT, - TOGGLE_FAST_FORWARD, - }; - - sHotkeyCfg getDefaultHotkeyConfig(HotKey hotKey); }; // namespace WindowSystem diff --git a/src/gui/wxgui/CMakeLists.txt b/src/gui/wxgui/CMakeLists.txt index bacbdd1b..921ba053 100644 --- a/src/gui/wxgui/CMakeLists.txt +++ b/src/gui/wxgui/CMakeLists.txt @@ -104,6 +104,8 @@ add_library(CemuWxGui PadViewFrame.h TitleManager.cpp TitleManager.h + wxCemuConfig.cpp + wxCemuConfig.h EmulatedUSBDevices/EmulatedUSBDeviceFrame.cpp EmulatedUSBDevices/EmulatedUSBDeviceFrame.h windows/PPCThreadsViewer diff --git a/src/gui/wxgui/CemuApp.cpp b/src/gui/wxgui/CemuApp.cpp index 5d4b1668..78f4b83f 100644 --- a/src/gui/wxgui/CemuApp.cpp +++ b/src/gui/wxgui/CemuApp.cpp @@ -1,4 +1,5 @@ #include "wxgui/CemuApp.h" +#include "wxCemuConfig.h" #include "wxgui/MainWindow.h" #include "wxgui/wxgui.h" #include "config/CemuConfig.h" @@ -11,6 +12,7 @@ #include "wxgui/helpers/wxHelpers.h" #include "Cemu/ncrypto/ncrypto.h" #include "wxgui/input/HotkeySettings.h" +#include #if BOOST_OS_LINUX && HAS_WAYLAND #include "wxgui/helpers/wxWayland.h" @@ -237,7 +239,7 @@ void CemuApp::InitializeExistingMLCOrFail(fs::path mlc) else // reset path { GetConfig().mlc_path = ""; - g_config.Save(); + GetConfigHandle().Save(); } } else @@ -263,16 +265,19 @@ bool CemuApp::OnInit() // make sure default cemu directories exist CreateDefaultCemuFiles(); - g_config.SetFilename(ActiveSettings::GetConfigPath("settings.xml").generic_wstring()); + GetConfigHandle().SetFilename(ActiveSettings::GetConfigPath("settings.xml").generic_wstring()); + + auto& config = GetWxGUIConfig(); std::error_code ec; bool isFirstStart = !fs::exists(ActiveSettings::GetConfigPath("settings.xml"), ec); NetworkConfig::LoadOnce(); - if(!isFirstStart) + if (!isFirstStart) { - g_config.Load(); - LocalizeUI(static_cast(GetConfig().language == wxLANGUAGE_DEFAULT ? wxLocale::GetSystemLanguage() : GetConfig().language.GetValue())); + GetConfigHandle().Load(); + sint32 language = config.language.GetValue(); + LocalizeUI(static_cast(language == wxLANGUAGE_DEFAULT ? wxLocale::GetSystemLanguage() : language)); } else { @@ -293,7 +298,7 @@ bool CemuApp::OnInit() GettingStartedDialog dia(nullptr); dia.ShowModal(); // make sure config is created. Gfx pack UI and input UI may create it earlier already, but we still want to update it - g_config.Save(); + GetConfigHandle().Save(); // create mlc, on failure the user can quit here. So do this after the Getting Started dialog InitializeNewMLCOrFail(ActiveSettings::GetMlcPath()); } @@ -332,7 +337,6 @@ bool CemuApp::OnInit() Bind(wxEVT_ACTIVATE_APP, &CemuApp::ActivateApp, this); - auto& config = GetConfig(); m_mainFrame = new MainWindow(); std::unique_lock lock(g_mutex); @@ -350,7 +354,7 @@ bool CemuApp::OnInit() // show warning on macOS about state of builds #if BOOST_OS_MACOS - if (!GetConfig().did_show_macos_disclaimer) + if (!config.did_show_macos_disclaimer) { const auto message = _( "Thank you for testing the in-development build of Cemu for macOS.\n \n" @@ -359,8 +363,8 @@ bool CemuApp::OnInit() wxMessageDialog dialog(nullptr, message, _("Preview version"), wxCENTRE | wxOK | wxICON_WARNING); dialog.SetOKLabel(_("I understand")); dialog.ShowModal(); - GetConfig().did_show_macos_disclaimer = true; - g_config.Save(); + config.did_show_macos_disclaimer = true; + GetConfigHandle().Save(); } #endif diff --git a/src/gui/wxgui/CemuUpdateWindow.cpp b/src/gui/wxgui/CemuUpdateWindow.cpp index 523c95ba..c45a0ab8 100644 --- a/src/gui/wxgui/CemuUpdateWindow.cpp +++ b/src/gui/wxgui/CemuUpdateWindow.cpp @@ -5,6 +5,7 @@ #include "util/helpers/SystemException.h" #include "config/ActiveSettings.h" #include "Common/FileStream.h" +#include "wxCemuConfig.h" #include #include @@ -118,7 +119,7 @@ bool CemuUpdateWindow::QueryUpdateInfo(std::string& downloadUrlOut, std::string& #elif #error Name for current platform is missing #endif - const auto& config = GetConfig(); + const auto& config = GetWxGUIConfig(); if(config.receive_untested_updates) urlStr.append("&allowNewUpdates=1"); diff --git a/src/gui/wxgui/EmulatedUSBDevices/EmulatedUSBDeviceFrame.cpp b/src/gui/wxgui/EmulatedUSBDevices/EmulatedUSBDeviceFrame.cpp index 303c0a63..5750f48b 100644 --- a/src/gui/wxgui/EmulatedUSBDevices/EmulatedUSBDeviceFrame.cpp +++ b/src/gui/wxgui/EmulatedUSBDevices/EmulatedUSBDeviceFrame.cpp @@ -73,7 +73,7 @@ wxPanel* EmulatedUSBDeviceFrame::AddSkylanderPage(wxNotebook* notebook) m_emulatePortal->Bind(wxEVT_CHECKBOX, [this](wxCommandEvent&) { GetConfig().emulated_usb_devices.emulate_skylander_portal = m_emulatePortal->IsChecked(); - g_config.Save(); + GetConfigHandle().Save(); }); row->Add(m_emulatePortal, 1, wxEXPAND | wxALL, 2); boxSizer->Add(row, 1, wxEXPAND | wxALL, 2); @@ -103,7 +103,7 @@ wxPanel* EmulatedUSBDeviceFrame::AddInfinityPage(wxNotebook* notebook) m_emulateBase->Bind(wxEVT_CHECKBOX, [this](wxCommandEvent&) { GetConfig().emulated_usb_devices.emulate_infinity_base = m_emulateBase->IsChecked(); - g_config.Save(); + GetConfigHandle().Save(); }); row->Add(m_emulateBase, 1, wxEXPAND | wxALL, 2); boxSizer->Add(row, 1, wxEXPAND | wxALL, 2); @@ -139,7 +139,7 @@ wxPanel* EmulatedUSBDeviceFrame::AddDimensionsPage(wxNotebook* notebook) m_emulateToypad->Bind(wxEVT_CHECKBOX, [this](wxCommandEvent&) { GetConfig().emulated_usb_devices.emulate_dimensions_toypad = m_emulateToypad->IsChecked(); - g_config.Save(); + GetConfigHandle().Save(); }); row->Add(m_emulateToypad, 1, wxEXPAND | wxALL, 2); box_sizer->Add(row, 1, wxEXPAND | wxALL, 2); diff --git a/src/gui/wxgui/GeneralSettings2.cpp b/src/gui/wxgui/GeneralSettings2.cpp index 9c3b40b9..ac993700 100644 --- a/src/gui/wxgui/GeneralSettings2.cpp +++ b/src/gui/wxgui/GeneralSettings2.cpp @@ -1,3 +1,4 @@ +#include "wxCemuConfig.h" #include "wxgui/wxgui.h" #include "wxgui/GeneralSettings2.h" #include "wxgui/CemuApp.h" @@ -959,14 +960,15 @@ void GeneralSettings2::StoreConfig() { auto* app = (CemuApp*)wxTheApp; auto& config = GetConfig(); + auto& wxGuiConfig = GetWxGUIConfig(); - config.use_discord_presence = m_discord_presence->IsChecked(); - config.fullscreen_menubar = m_fullscreen_menubar->IsChecked(); - config.check_update = m_auto_update->IsChecked(); - config.save_screenshot = m_save_screenshot->IsChecked(); - config.receive_untested_updates = m_receive_untested_releases->IsChecked(); + wxGuiConfig.use_discord_presence = m_discord_presence->IsChecked(); + wxGuiConfig.fullscreen_menubar = m_fullscreen_menubar->IsChecked(); + wxGuiConfig.check_update = m_auto_update->IsChecked(); + wxGuiConfig.save_screenshot = m_save_screenshot->IsChecked(); + wxGuiConfig.receive_untested_updates = m_receive_untested_releases->IsChecked(); #if BOOST_OS_LINUX && defined(ENABLE_FERAL_GAMEMODE) - config.feral_gamemode = m_feral_gamemode->IsChecked(); + wxGuiConfig.feral_gamemode = m_feral_gamemode->IsChecked(); #endif config.play_boot_sound = m_play_boot_sound->IsChecked(); config.disable_screensaver = m_disable_screensaver->IsChecked(); @@ -978,10 +980,10 @@ void GeneralSettings2::StoreConfig() // -1 is default wx widget value -> set to dummy 0 so mainwindow and padwindow will update it - config.window_position = m_save_window_position_size->IsChecked() ? Vector2i{ 0,0 } : Vector2i{-1,-1}; - config.window_size = m_save_window_position_size->IsChecked() ? Vector2i{ 0,0 } : Vector2i{-1,-1}; - config.pad_position = m_save_padwindow_position_size->IsChecked() ? Vector2i{ 0,0 } : Vector2i{-1,-1}; - config.pad_size = m_save_padwindow_position_size->IsChecked() ? Vector2i{ 0,0 } : Vector2i{-1,-1}; + wxGuiConfig.window_position = m_save_window_position_size->IsChecked() ? Vector2i{ 0,0 } : Vector2i{-1,-1}; + wxGuiConfig.window_size = m_save_window_position_size->IsChecked() ? Vector2i{ 0,0 } : Vector2i{-1,-1}; + wxGuiConfig.pad_position = m_save_padwindow_position_size->IsChecked() ? Vector2i{ 0,0 } : Vector2i{-1,-1}; + wxGuiConfig.pad_size = m_save_padwindow_position_size->IsChecked() ? Vector2i{ 0,0 } : Vector2i{-1,-1}; config.game_paths.clear(); for (auto& path : m_game_paths->GetStrings()) @@ -989,7 +991,7 @@ void GeneralSettings2::StoreConfig() auto selection = m_language->GetSelection(); if (selection == 0) - GetConfig().language = wxLANGUAGE_DEFAULT; + wxGuiConfig.language = wxLANGUAGE_DEFAULT; else { const auto language = m_language->GetStringSelection(); @@ -997,7 +999,7 @@ void GeneralSettings2::StoreConfig() { if (lang->DescriptionNative == language) { - GetConfig().language = lang->Language; + wxGuiConfig.language = lang->Language; break; } } @@ -1112,7 +1114,7 @@ void GeneralSettings2::StoreConfig() config.crash_dump = (CrashDump)m_crash_dump->GetSelection(); config.gdb_port = m_gdb_port->GetValue(); - g_config.Save(); + GetConfigHandle().Save(); } GeneralSettings2::~GeneralSettings2() @@ -1133,9 +1135,9 @@ void GeneralSettings2::OnClose(wxCloseEvent& event) void GeneralSettings2::ValidateConfig() { - g_config.Load(); + GetConfigHandle().Load(); - auto& data = g_config.data(); + auto& data = GetConfigHandle().data(); // todo //data.fullscreen_scaling = min(max(data.fullscreen_scaling,)) } @@ -1610,6 +1612,7 @@ void GeneralSettings2::HandleGraphicsApiSelection() void GeneralSettings2::ApplyConfig() { ValidateConfig(); + auto& wxGUIconfig = GetWxGUIConfig(); auto& config = GetConfig(); if (LaunchSettings::GetMLCPath().has_value()) @@ -1617,20 +1620,20 @@ void GeneralSettings2::ApplyConfig() else m_mlc_path->SetValue(wxHelper::FromUtf8(config.mlc_path.GetValue())); - m_save_window_position_size->SetValue(config.window_position != Vector2i{-1,-1}); - m_save_padwindow_position_size->SetValue(config.pad_position != Vector2i{-1,-1}); + m_save_window_position_size->SetValue(wxGUIconfig.window_position != Vector2i{-1,-1}); + m_save_padwindow_position_size->SetValue(wxGUIconfig.pad_position != Vector2i{-1,-1}); - m_discord_presence->SetValue(config.use_discord_presence); - m_fullscreen_menubar->SetValue(config.fullscreen_menubar); + m_discord_presence->SetValue(wxGUIconfig.use_discord_presence); + m_fullscreen_menubar->SetValue(wxGUIconfig.fullscreen_menubar); - m_auto_update->SetValue(config.check_update); - m_receive_untested_releases->SetValue(config.receive_untested_updates); - m_save_screenshot->SetValue(config.save_screenshot); + m_auto_update->SetValue(wxGUIconfig.check_update); + m_receive_untested_releases->SetValue(wxGUIconfig.receive_untested_updates); + m_save_screenshot->SetValue(wxGUIconfig.save_screenshot); m_disable_screensaver->SetValue(config.disable_screensaver); m_play_boot_sound->SetValue(config.play_boot_sound); #if BOOST_OS_LINUX && defined(ENABLE_FERAL_GAMEMODE) - m_feral_gamemode->SetValue(config.feral_gamemode); + m_feral_gamemode->SetValue(wxGUIconfig.feral_gamemode); #endif // temporary workaround because feature crashes on macOS #if BOOST_OS_MACOS @@ -1646,7 +1649,7 @@ void GeneralSettings2::ApplyConfig() const auto app = (CemuApp*)wxTheApp; for (const auto& language : app->GetLanguages()) { - if (config.language == language->Language) + if (wxGUIconfig.language == language->Language) { m_language->SetStringSelection(language->DescriptionNative); break; @@ -2124,7 +2127,7 @@ void GeneralSettings2::OnMLCPathClear(wxCommandEvent& event) return; GetConfig().SetMLCPath(""); StoreConfig(); - g_config.Save(); + GetConfigHandle().Save(); wxMessageBox(_("Cemu needs to be restarted for the changes to take effect."), _("Information"), wxOK | wxCENTRE | wxICON_INFORMATION, this); // close settings and then cemu wxCloseEvent closeEvent(wxEVT_CLOSE_WINDOW); diff --git a/src/gui/wxgui/GettingStartedDialog.cpp b/src/gui/wxgui/GettingStartedDialog.cpp index f2fc9122..dc9bc811 100644 --- a/src/gui/wxgui/GettingStartedDialog.cpp +++ b/src/gui/wxgui/GettingStartedDialog.cpp @@ -8,6 +8,7 @@ #include #include "config/ActiveSettings.h" +#include "wxCemuConfig.h" #include "wxgui/CemuApp.h" #include "wxgui/DownloadGraphicPacksWindow.h" #include "wxgui/GraphicPacksWindow2.h" @@ -204,7 +205,7 @@ wxPanel* GettingStartedDialog::CreatePage2() void GettingStartedDialog::ApplySettings() { - auto& config = GetConfig(); + auto& config = GetWxGUIConfig(); m_page2.fullscreenCheckbox->SetValue(config.fullscreen.GetValue()); m_page2.updateCheckbox->SetValue(config.check_update.GetValue()); m_page2.separateCheckbox->SetValue(config.pad_open.GetValue()); @@ -225,11 +226,12 @@ void GettingStartedDialog::OnClose(wxCloseEvent& event) { event.Skip(); - auto& config = GetConfig(); - config.fullscreen = m_page2.fullscreenCheckbox->GetValue(); - config.check_update = m_page2.updateCheckbox->GetValue(); - config.pad_open = m_page2.separateCheckbox->GetValue(); + auto& wxGUIConfig = GetWxGUIConfig(); + wxGUIConfig.fullscreen = m_page2.fullscreenCheckbox->GetValue(); + wxGUIConfig.check_update = m_page2.updateCheckbox->GetValue(); + wxGUIConfig.pad_open = m_page2.separateCheckbox->GetValue(); + auto& config = GetConfig(); const fs::path gamePath = wxHelper::MakeFSPath(m_page1.gamePathPicker->GetPath()); std::error_code ec; if (!gamePath.empty() && fs::exists(gamePath, ec)) diff --git a/src/gui/wxgui/GraphicPacksWindow2.cpp b/src/gui/wxgui/GraphicPacksWindow2.cpp index 32e111c6..1298f72f 100644 --- a/src/gui/wxgui/GraphicPacksWindow2.cpp +++ b/src/gui/wxgui/GraphicPacksWindow2.cpp @@ -325,7 +325,7 @@ GraphicPacksWindow2::GraphicPacksWindow2(wxWindow* parent, uint64_t title_id_fil void GraphicPacksWindow2::SaveStateToConfig() { - auto& data = g_config.data(); + auto& data = GetConfigHandle().data(); data.graphic_pack_entries.clear(); for (const auto& gp : GraphicPack2::GetGraphicPacks()) @@ -348,7 +348,7 @@ void GraphicPacksWindow2::SaveStateToConfig() } } - g_config.Save(); + GetConfigHandle().Save(); } GraphicPacksWindow2::~GraphicPacksWindow2() diff --git a/src/gui/wxgui/MainWindow.cpp b/src/gui/wxgui/MainWindow.cpp index 59a1e6a1..d9f5518f 100644 --- a/src/gui/wxgui/MainWindow.cpp +++ b/src/gui/wxgui/MainWindow.cpp @@ -1,5 +1,6 @@ #include "Cafe/HW/Latte/Renderer/Renderer.h" #include "interface/WindowSystem.h" +#include "wxCemuConfig.h" #include "wxgui/wxgui.h" #include "wxgui/MainWindow.h" @@ -274,7 +275,7 @@ public: std::string path = filenames[0].utf8_string(); if (nfc::TouchTagFromFile(_utf8ToPath(path), &nfcError)) { - GetConfig().AddRecentNfcFile(path); + GetWxGUIConfig().AddRecentNfcFile(path); m_window->UpdateNFCMenu(); return true; } @@ -363,9 +364,8 @@ MainWindow::MainWindow() LoadSettings(); - auto& config = GetConfig(); #ifdef ENABLE_DISCORD_RPC - if (config.use_discord_presence) + if (GetWxGUIConfig().use_discord_presence) m_discord = std::make_unique(); #endif @@ -374,7 +374,7 @@ MainWindow::MainWindow() if (LaunchSettings::GDBStubEnabled()) { - g_gdbstub = std::make_unique(config.gdb_port); + g_gdbstub = std::make_unique(GetConfig().gdb_port); } } @@ -572,9 +572,9 @@ bool MainWindow::FileLoad(const fs::path launchPath, wxLaunchGameEvent::INITIATE } if(launchTitle.IsValid()) - GetConfig().AddRecentlyLaunchedFile(_pathToUtf8(launchTitle.GetPath())); + GetWxGUIConfig().AddRecentlyLaunchedFile(_pathToUtf8(launchTitle.GetPath())); else - GetConfig().AddRecentlyLaunchedFile(_pathToUtf8(launchPath)); + GetWxGUIConfig().AddRecentlyLaunchedFile(_pathToUtf8(launchPath)); wxWindowUpdateLocker lock(this); @@ -599,12 +599,12 @@ bool MainWindow::FileLoad(const fs::path launchPath, wxLaunchGameEvent::INITIATE // ScreenSaver::SetInhibit(false); } - if (ActiveSettings::FullscreenEnabled()) + if (FullscreenEnabled()) SetFullScreen(true); //GameMode support #if BOOST_OS_LINUX && defined(ENABLE_FERAL_GAMEMODE) - if(GetConfig().feral_gamemode) + if(GetWxGUIConfig().feral_gamemode) { // attempt to start gamemode if(gamemode_request_start() < 0) @@ -666,7 +666,7 @@ void MainWindow::OnFileMenu(wxCommandEvent& event) } else if (menuId >= MAINFRAME_MENU_ID_FILE_RECENT_0 && menuId <= MAINFRAME_MENU_ID_FILE_RECENT_LAST) { - const auto& config = GetConfig(); + const auto& config = GetWxGUIConfig(); const size_t index = menuId - MAINFRAME_MENU_ID_FILE_RECENT_0; if (index < config.recent_launch_files.size()) { @@ -760,14 +760,14 @@ void MainWindow::OnNFCMenu(wxCommandEvent& event) } else { - GetConfig().AddRecentNfcFile(wxStrFilePath.utf8_string()); + GetWxGUIConfig().AddRecentNfcFile(wxStrFilePath.utf8_string()); UpdateNFCMenu(); } } else if (event.GetId() >= MAINFRAME_MENU_ID_NFC_RECENT_0 && event.GetId() <= MAINFRAME_MENU_ID_NFC_RECENT_LAST) { const size_t index = event.GetId() - MAINFRAME_MENU_ID_NFC_RECENT_0; - auto& config = GetConfig(); + auto& config = GetWxGUIConfig(); if (index < config.recent_nfc_files.size()) { const auto& path = config.recent_nfc_files[index]; @@ -800,7 +800,7 @@ void MainWindow::OnFileExit(wxCommandEvent& event) void MainWindow::TogglePadView() { - const auto& config = GetConfig(); + const auto& config = GetWxGUIConfig(); if (config.pad_open) { if (m_padView) @@ -849,7 +849,7 @@ WXLRESULT MainWindow::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lPara void MainWindow::OpenSettings() { - auto& config = GetConfig(); + auto& config = GetWxGUIConfig(); const auto language = config.language; GeneralSettings2 frame(this, m_game_launched); @@ -901,8 +901,8 @@ void MainWindow::OnOptionsInput(wxCommandEvent& event) } case MAINFRAME_MENU_ID_OPTIONS_SECOND_WINDOW_PADVIEW: { - GetConfig().pad_open = !GetConfig().pad_open; - g_config.Save(); + GetWxGUIConfig().pad_open = !GetWxGUIConfig().pad_open; + g_wxConfig.Save(); TogglePadView(); break; @@ -954,7 +954,7 @@ void MainWindow::OnAccountSelect(wxCommandEvent& event) auto& config = GetConfig(); config.account.m_persistent_id = accounts[index].GetPersistentId(); // config.account.online_enabled.value = false; // reset online for safety - g_config.Save(); + GetConfigHandle().Save(); } void MainWindow::OnConsoleLanguage(wxCommandEvent& event) @@ -1005,7 +1005,7 @@ void MainWindow::OnConsoleLanguage(wxCommandEvent& event) m_game_list->DeleteCachedStrings(); m_game_list->ReloadGameEntries(false); } - g_config.Save(); + GetConfigHandle().Save(); } //void MainWindow::OnCPUMode(wxCommandEvent& event) @@ -1021,7 +1021,7 @@ void MainWindow::OnConsoleLanguage(wxCommandEvent& event) // else // cemu_assert_debug(false); // -// g_config.Save(); +// GetConfigHandle().Save(); //} void MainWindow::OnDebugSetting(wxCommandEvent& event) @@ -1085,7 +1085,7 @@ void MainWindow::OnDebugSetting(wxCommandEvent& event) else cemu_assert_debug(false); - g_config.Save(); + GetConfigHandle().Save(); } void MainWindow::OnDebugLoggingToggleFlagGeneric(wxCommandEvent& event) @@ -1102,14 +1102,14 @@ void MainWindow::OnDebugLoggingToggleFlagGeneric(wxCommandEvent& event) else GetConfig().log_flag = GetConfig().log_flag.GetValue() & ~cemuLog_getFlag(loggingType); cemuLog_setActiveLoggingFlags(GetConfig().log_flag.GetValue()); - g_config.Save(); + GetConfigHandle().Save(); } } void MainWindow::OnPPCInfoToggle(wxCommandEvent& event) { GetConfig().advanced_ppc_logging = !GetConfig().advanced_ppc_logging.GetValue(); - g_config.Save(); + GetConfigHandle().Save(); } void MainWindow::OnDebugDumpGeneric(wxCommandEvent& event) @@ -1290,8 +1290,8 @@ wxRect MainWindow::GetDesktopRect() void MainWindow::LoadSettings() { - g_config.Load(); - const auto& config = GetConfig(); + GetConfigHandle().Load(); + const auto& config = GetWxGUIConfig(); if(config.check_update) m_update_available = CemuUpdateWindow::IsUpdateAvailableAsync(); @@ -1329,8 +1329,8 @@ void MainWindow::LoadSettings() void MainWindow::SaveSettings() { - auto lock = g_config.Lock(); - auto& config = GetConfig(); + auto lock = GetConfigHandle().Lock(); + auto& config = GetWxGUIConfig(); if (config.window_position != Vector2i{ -1,-1 }) { @@ -1369,7 +1369,7 @@ void MainWindow::SaveSettings() if(m_game_list) m_game_list->SaveConfig(); - g_config.Save(); + g_wxConfig.Save(); } void MainWindow::OnMouseMove(wxMouseEvent& event) @@ -1389,7 +1389,7 @@ void MainWindow::OnMouseMove(wxMouseEvent& event) if (!IsFullScreen()) return; - const auto& config = GetConfig(); + const auto& config = GetWxGUIConfig(); // if mouse goes to upper screen then show our menu in fullscreen mode if (config.fullscreen_menubar) SetMenuVisible(event.GetPosition().y < 50); @@ -1688,7 +1688,7 @@ void MainWindow::OnDebuggerClose(wxCloseEvent& event) void MainWindow::OnPadClose(wxCloseEvent& event) { - auto& config = GetConfig(); + auto& config = GetWxGUIConfig(); config.pad_open = false; if (config.pad_position != Vector2i{ -1,-1 }) m_padView->GetPosition(&config.pad_position.x, &config.pad_position.y); @@ -1696,7 +1696,7 @@ void MainWindow::OnPadClose(wxCloseEvent& event) if (config.pad_size != Vector2i{ -1,-1 }) m_padView->GetSize(&config.pad_size.x, &config.pad_size.y); - g_config.Save(); + g_wxConfig.Save(); // already deleted by wxwidget m_padView = nullptr; @@ -1727,8 +1727,8 @@ void MainWindow::SetFullScreen(bool state) // only update config entry if we dont't have launch parameters if (!LaunchSettings::FullscreenEnabled().has_value()) { - GetConfig().fullscreen = state; - g_config.Save(); + GetWxGUIConfig().fullscreen = state; + g_wxConfig.Save(); } if (state && !m_game_launched) return; @@ -1760,14 +1760,14 @@ void MainWindow::UpdateNFCMenu() m_nfcMenuSeparator0 = nullptr; } // remove recent files list - for (sint32 i = 0; i < CemuConfig::kMaxRecentEntries; i++) + for (sint32 i = 0; i < wxCemuConfig::kMaxRecentEntries; i++) { if (m_nfcMenu->FindChildItem(MAINFRAME_MENU_ID_NFC_RECENT_0 + i) == nullptr) continue; m_nfcMenu->Remove(MAINFRAME_MENU_ID_NFC_RECENT_0 + i); } // add entries - const auto& config = GetConfig(); + const auto& config = GetWxGUIConfig(); sint32 recentFileIndex = 0; for (size_t i = 0; i < config.recent_nfc_files.size(); i++) { @@ -2098,7 +2098,7 @@ void MainWindow::RecreateMenu() m_menuBar = nullptr; } - auto& config = GetConfig(); + auto& guiConfig = GetWxGUIConfig(); m_menuBar = new wxMenuBar(); // file submenu @@ -2112,9 +2112,9 @@ void MainWindow::RecreateMenu() sint32 recentFileIndex = 0; m_fileMenuSeparator0 = nullptr; m_fileMenuSeparator1 = nullptr; - for (size_t i = 0; i < config.recent_launch_files.size(); i++) + for (size_t i = 0; i < guiConfig.recent_launch_files.size(); i++) { - const std::string& pathStr = config.recent_launch_files[i]; + const std::string& pathStr = guiConfig.recent_launch_files[i]; if (pathStr.empty()) continue; if (recentFileIndex == 0) @@ -2156,6 +2156,8 @@ void MainWindow::RecreateMenu() ++index; } + auto& config = GetConfig(); + auto& wxConfig = GetWxGUIConfig(); // options->console language submenu wxMenu* optionsConsoleLanguageMenu = new wxMenu(); optionsConsoleLanguageMenu->AppendRadioItem(MAINFRAME_MENU_ID_OPTIONS_LANGUAGE_ENGLISH, _("&English"), wxEmptyString)->Check(config.console_language == CafeConsoleLanguage::EN); @@ -2182,11 +2184,11 @@ void MainWindow::RecreateMenu() // options submenu wxMenu* optionsMenu = new wxMenu(); m_fullscreenMenuItem = optionsMenu->AppendCheckItem(MAINFRAME_MENU_ID_OPTIONS_FULLSCREEN, _("&Fullscreen"), wxEmptyString); - m_fullscreenMenuItem->Check(ActiveSettings::FullscreenEnabled()); + m_fullscreenMenuItem->Check(FullscreenEnabled()); optionsMenu->Append(MAINFRAME_MENU_ID_OPTIONS_GRAPHIC_PACKS2, _("&Graphic packs")); m_padViewMenuItem = optionsMenu->AppendCheckItem(MAINFRAME_MENU_ID_OPTIONS_SECOND_WINDOW_PADVIEW, _("&Separate GamePad view"), wxEmptyString); - m_padViewMenuItem->Check(GetConfig().pad_open); + m_padViewMenuItem->Check(wxConfig.pad_open); optionsMenu->AppendSeparator(); #if BOOST_OS_MACOS optionsMenu->Append(MAINFRAME_MENU_ID_OPTIONS_MAC_SETTINGS, _("&Settings..." "\tCtrl-,")); @@ -2409,3 +2411,8 @@ void MainWindow::CafeRecreateCanvas() wxQueueEvent(g_mainFrame, evt); sem.decrementWithWait(); } + +bool MainWindow::FullscreenEnabled() const +{ + return LaunchSettings::FullscreenEnabled().value_or(GetWxGUIConfig().fullscreen); +} diff --git a/src/gui/wxgui/MainWindow.h b/src/gui/wxgui/MainWindow.h index 2259893b..2f251ca8 100644 --- a/src/gui/wxgui/MainWindow.h +++ b/src/gui/wxgui/MainWindow.h @@ -145,6 +145,7 @@ public: static void RequestLaunchGame(fs::path filePath, wxLaunchGameEvent::INITIATED_BY initiatedBy); private: + bool FullscreenEnabled() const; void RecreateMenu(); void UpdateChildWindowTitleRunningState(); static wxString GetInitialWindowTitle(); diff --git a/src/gui/wxgui/components/wxGameList.cpp b/src/gui/wxgui/components/wxGameList.cpp index ad76c50a..bb6e9653 100644 --- a/src/gui/wxgui/components/wxGameList.cpp +++ b/src/gui/wxgui/components/wxGameList.cpp @@ -1,6 +1,7 @@ #include "wxgui/components/wxGameList.h" #include "wxgui/helpers/wxCustomData.h" +#include "wxCemuConfig.h" #include "util/helpers/helpers.h" #include "wxgui/GameProfileWindow.h" @@ -137,7 +138,7 @@ bool writeICNS(const fs::path& pngPath, const fs::path& icnsPath) { wxGameList::wxGameList(wxWindow* parent, wxWindowID id) : wxListView(parent, id, wxDefaultPosition, wxDefaultSize, GetStyleFlags(Style::kList)), m_style(Style::kList) { - const auto& config = GetConfig(); + const auto& config = GetWxGUIConfig(); InsertColumn(ColumnHiddenName, "", wxLIST_FORMAT_LEFT, 0); if(config.show_icon_column) @@ -221,7 +222,7 @@ wxGameList::~wxGameList() void wxGameList::LoadConfig() { - const auto& config = GetConfig(); + const auto& config = GetWxGUIConfig(); SetStyle((Style)config.game_list_style, false); if (!config.game_list_column_order.empty()) @@ -327,7 +328,7 @@ int wxGameList::GetColumnDefaultWidth(int column) void wxGameList::SaveConfig(bool flush) { - auto& config = GetConfig(); + auto& config = GetWxGUIConfig(); config.game_list_style = (int)m_style; #ifdef wxHAS_LISTCTRL_COLUMN_ORDER @@ -335,7 +336,7 @@ void wxGameList::SaveConfig(bool flush) #endif if (flush) - g_config.Save(); + GetConfigHandle().Save(); } bool wxGameList::IsVisible(long item) const @@ -426,8 +427,8 @@ void wxGameList::SetStyle(Style style, bool save) if(save) { - GetConfig().game_list_style = (int)m_style; - g_config.Save(); + GetWxGUIConfig().game_list_style = (int)m_style; + GetConfigHandle().Save(); } if (style == Style::kList) @@ -726,7 +727,7 @@ void wxGameList::OnContextMenuSelected(wxCommandEvent& event) const auto custom_name = dialog.GetValue(); GetConfig().SetGameListCustomName(title_id, custom_name.utf8_string()); m_name_cache.clear(); - g_config.Save(); + GetConfigHandle().Save(); // update list entry for (int i = 0; i < GetItemCount(); ++i) { @@ -906,7 +907,7 @@ void wxGameList::OnColumnRightClick(wxListEvent& event) const auto menu = dynamic_cast(event.GetEventObject()); const int column = dynamic_cast*>(menu->GetClientObject())->GetData(); - auto& config = GetConfig(); + auto& config = GetWxGUIConfig(); switch (event.GetId()) { @@ -980,7 +981,7 @@ void wxGameList::OnColumnRightClick(wxListEvent& event) } } - g_config.Save(); + GetConfigHandle().Save(); ApplyGameListColumnWidths(); }); @@ -990,7 +991,7 @@ void wxGameList::OnColumnRightClick(wxListEvent& event) void wxGameList::ApplyGameListColumnWidths() { - const auto& config = GetConfig(); + const auto& config = GetWxGUIConfig(); wxWindowUpdateLocker lock(this); if(config.show_icon_column) SetColumnWidth(ColumnIcon, kListIconWidth); @@ -1044,7 +1045,7 @@ void wxGameList::OnColumnResize(wxListEvent& event) const int column = event.GetColumn(); const int width = GetColumnWidth(column); - auto& config = GetConfig(); + auto& config = GetWxGUIConfig(); switch (column) { case ColumnName: @@ -1069,7 +1070,7 @@ void wxGameList::OnColumnResize(wxListEvent& event) break; } - g_config.Save(); + GetConfigHandle().Save(); AdjustLastColumnWidth(); } diff --git a/src/gui/wxgui/debugger/DebuggerWindow2.h b/src/gui/wxgui/debugger/DebuggerWindow2.h index 99336564..fa00efce 100644 --- a/src/gui/wxgui/debugger/DebuggerWindow2.h +++ b/src/gui/wxgui/debugger/DebuggerWindow2.h @@ -42,7 +42,7 @@ struct DebuggerConfig void Load(XMLConfigParser& parser); void Save(XMLConfigParser& parser); }; -typedef XMLDataConfig XMLDebuggerConfig; +typedef XMLDataConfig XMLDebuggerConfig; struct DebuggerModuleStorage { @@ -54,7 +54,7 @@ struct DebuggerModuleStorage void Load(XMLConfigParser& parser); void Save(XMLConfigParser& parser); }; -typedef XMLDataConfig XMLDebuggerModuleConfig; +typedef XMLDataConfig XMLDebuggerModuleConfig; class DebuggerWindow2 : public wxFrame, public DebuggerCallbacks { diff --git a/src/gui/wxgui/input/HotkeySettings.cpp b/src/gui/wxgui/input/HotkeySettings.cpp index f017cc81..626bdcd1 100644 --- a/src/gui/wxgui/input/HotkeySettings.cpp +++ b/src/gui/wxgui/input/HotkeySettings.cpp @@ -81,7 +81,7 @@ std::optional SaveScreenshot(std::vector data, int width, in // to make this work we need to call OleInitialize() on the same thread OleInitialize(nullptr); #endif - bool save_screenshot = g_config.data().save_screenshot; + bool save_screenshot = GetWxGUIConfig().save_screenshot; wxImage image(width, height, data.data(), true); if (mainWindow) { @@ -174,7 +174,7 @@ HotkeySettings::~HotkeySettings() m_controllerTimer->Stop(); if (m_needToSave) { - g_config.Save(); + GetConfigHandle().Save(); } } diff --git a/src/gui/wxgui/input/HotkeySettings.h b/src/gui/wxgui/input/HotkeySettings.h index f418a930..c9395b5a 100644 --- a/src/gui/wxgui/input/HotkeySettings.h +++ b/src/gui/wxgui/input/HotkeySettings.h @@ -1,7 +1,7 @@ #pragma once #include -#include "config/CemuConfig.h" +#include "wxCemuConfig.h" #include "input/api/Controller.h" class HotkeyEntry; @@ -22,7 +22,7 @@ private: static const std::unordered_map> s_cfgHotkeyToFuncMap; inline static std::unordered_map> s_keyboardHotkeyToFuncMap{}; inline static std::unordered_map> s_controllerHotkeyToFuncMap{}; - inline static auto& s_cfgHotkeys = GetConfig().hotkeys; + inline static auto& s_cfgHotkeys = GetWxGUIConfig().hotkeys; wxPanel* m_panel; wxFlexGridSizer* m_sizer; diff --git a/src/gui/wxgui/wxCemuConfig.cpp b/src/gui/wxgui/wxCemuConfig.cpp new file mode 100644 index 00000000..87355797 --- /dev/null +++ b/src/gui/wxgui/wxCemuConfig.cpp @@ -0,0 +1,184 @@ +#include "wxCemuConfig.h" +#include "Common/precompiled.h" +#include "config/CemuConfig.h" +#include "config/XMLConfig.h" +#include "util/helpers/helpers.h" +#include + +XMLWxCemuConfig_t g_wxConfig(&GetConfigHandle); + +void wxCemuConfig::AddRecentlyLaunchedFile(std::string_view file) +{ + recent_launch_files.insert(recent_launch_files.begin(), std::string(file)); + RemoveDuplicatesKeepOrder(recent_launch_files); + while (recent_launch_files.size() > kMaxRecentEntries) + recent_launch_files.pop_back(); +} + +void wxCemuConfig::AddRecentNfcFile(std::string_view file) +{ + recent_nfc_files.insert(recent_nfc_files.begin(), std::string(file)); + RemoveDuplicatesKeepOrder(recent_nfc_files); + while (recent_nfc_files.size() > kMaxRecentEntries) + recent_nfc_files.pop_back(); +} + +void wxCemuConfig::Load(XMLConfigParser& parser) +{ + language = parser.get("language", wxLANGUAGE_DEFAULT); + use_discord_presence = parser.get("use_discord_presence", true); + fullscreen_menubar = parser.get("fullscreen_menubar", false); + feral_gamemode = parser.get("feral_gamemode", false); + check_update = parser.get("check_update", check_update); + receive_untested_updates = parser.get("receive_untested_updates", receive_untested_updates); + save_screenshot = parser.get("save_screenshot", save_screenshot); + did_show_vulkan_warning = parser.get("vk_warning", did_show_vulkan_warning); + did_show_graphic_pack_download = parser.get("gp_download", did_show_graphic_pack_download); + did_show_macos_disclaimer = parser.get("macos_disclaimer", did_show_macos_disclaimer); + fullscreen = parser.get("fullscreen", fullscreen); + + window_position.x = parser.get("window_position").get("x", -1); + window_position.y = parser.get("window_position").get("y", -1); + + window_size.x = parser.get("window_size").get("x", -1); + window_size.y = parser.get("window_size").get("y", -1); + window_maximized = parser.get("window_maximized", false); + + pad_open = parser.get("open_pad", false); + pad_position.x = parser.get("pad_position").get("x", -1); + pad_position.y = parser.get("pad_position").get("y", -1); + + pad_size.x = parser.get("pad_size").get("x", -1); + pad_size.y = parser.get("pad_size").get("y", -1); + pad_maximized = parser.get("pad_maximized", false); + + auto gamelist = parser.get("GameList"); + game_list_style = gamelist.get("style", 0); + game_list_column_order = gamelist.get("order", ""); + + show_icon_column = parser.get("show_icon_column", true); + + // return default width if value in config file out of range + auto loadColumnSize = [&gamelist](const char* name, uint32 defaultWidth) { + sint64 val = gamelist.get(name, DefaultColumnSize::name); + if (val < 0 || val > (sint64)std::numeric_limits::max) + return defaultWidth; + return static_cast(val); + }; + column_width.name = loadColumnSize("name_width", DefaultColumnSize::name); + column_width.version = loadColumnSize("version_width", DefaultColumnSize::version); + column_width.dlc = loadColumnSize("dlc_width", DefaultColumnSize::dlc); + column_width.game_time = loadColumnSize("game_time_width", DefaultColumnSize::game_time); + column_width.game_started = loadColumnSize("game_started_width", DefaultColumnSize::game_started); + column_width.region = loadColumnSize("region_width", DefaultColumnSize::region); + column_width.title_id = loadColumnSize("title_id", DefaultColumnSize::title_id); + + recent_launch_files.clear(); + auto launch_parser = parser.get("RecentLaunchFiles"); + for (auto element = launch_parser.get("Entry"); element.valid(); element = launch_parser.get("Entry", element)) + { + const std::string path = element.value(""); + if (path.empty()) + continue; + + try + { + recent_launch_files.emplace_back(path); + } catch (const std::exception&) + { + cemuLog_log(LogType::Force, "config load error: can't load recently launched game file: {}", path); + } + } + + recent_nfc_files.clear(); + auto nfc_parser = parser.get("RecentNFCFiles"); + for (auto element = nfc_parser.get("Entry"); element.valid(); element = nfc_parser.get("Entry", element)) + { + const std::string path = element.value(""); + if (path.empty()) + continue; + try + { + recent_nfc_files.emplace_back(path); + } catch (const std::exception&) + { + cemuLog_log(LogType::Force, "config load error: can't load recently launched nfc file: {}", path); + } + } + + // hotkeys + auto xml_hotkeys = parser.get("Hotkeys"); + hotkeys.modifiers = xml_hotkeys.get("modifiers", sHotkeyCfg{}); + hotkeys.exitFullscreen = xml_hotkeys.get("ExitFullscreen", sHotkeyCfg{uKeyboardHotkey{WXK_ESCAPE}}); + hotkeys.toggleFullscreen = xml_hotkeys.get("ToggleFullscreen", sHotkeyCfg{uKeyboardHotkey{WXK_F11}}); + hotkeys.toggleFullscreenAlt = xml_hotkeys.get("ToggleFullscreenAlt", sHotkeyCfg{uKeyboardHotkey{WXK_CONTROL_M, true}}); // ALT+ENTER + hotkeys.takeScreenshot = xml_hotkeys.get("TakeScreenshot", sHotkeyCfg{uKeyboardHotkey{WXK_F12}}); + hotkeys.toggleFastForward = xml_hotkeys.get("ToggleFastForward", sHotkeyCfg{}); +} + +void wxCemuConfig::Save(XMLConfigParser& config) +{ + // general settings + config.set("language", language); + config.set("use_discord_presence", use_discord_presence); + config.set("fullscreen_menubar", fullscreen_menubar); + config.set("feral_gamemode", feral_gamemode); + config.set("check_update", check_update); + config.set("receive_untested_updates", receive_untested_updates); + config.set("save_screenshot", save_screenshot); + config.set("vk_warning", did_show_vulkan_warning); + config.set("gp_download", did_show_graphic_pack_download); + config.set("macos_disclaimer", did_show_macos_disclaimer); + config.set("fullscreen", fullscreen); + + auto wpos = config.set("window_position"); + wpos.set("x", window_position.x); + wpos.set("y", window_position.y); + auto wsize = config.set("window_size"); + wsize.set("x", window_size.x); + cemu_assert_debug(window_size.x != 0); + wsize.set("y", window_size.y); + config.set("window_maximized", window_maximized); + + config.set("open_pad", pad_open); + auto ppos = config.set("pad_position"); + ppos.set("x", pad_position.x); + ppos.set("y", pad_position.y); + auto psize = config.set("pad_size"); + psize.set("x", pad_size.x); + psize.set("y", pad_size.y); + config.set("pad_maximized", pad_maximized); + config.set("show_icon_column", show_icon_column); + + auto gamelist = config.set("GameList"); + gamelist.set("style", game_list_style); + gamelist.set("order", game_list_column_order); + gamelist.set("name_width", column_width.name); + gamelist.set("version_width", column_width.version); + gamelist.set("dlc_width", column_width.dlc); + gamelist.set("game_time_width", column_width.game_time); + gamelist.set("game_started_width", column_width.game_started); + gamelist.set("region_width", column_width.region); + gamelist.set("title_id", column_width.title_id); + + auto launch_files_parser = config.set("RecentLaunchFiles"); + for (const auto& entry : recent_launch_files) + { + launch_files_parser.set("Entry", entry.c_str()); + } + + auto nfc_files_parser = config.set("RecentNFCFiles"); + for (const auto& entry : recent_nfc_files) + { + nfc_files_parser.set("Entry", entry.c_str()); + } + + // hotkeys + auto xml_hotkeys = config.set("Hotkeys"); + xml_hotkeys.set("modifiers", hotkeys.modifiers); + xml_hotkeys.set("ExitFullscreen", hotkeys.exitFullscreen); + xml_hotkeys.set("ToggleFullscreen", hotkeys.toggleFullscreen); + xml_hotkeys.set("ToggleFullscreenAlt", hotkeys.toggleFullscreenAlt); + xml_hotkeys.set("TakeScreenshot", hotkeys.takeScreenshot); + xml_hotkeys.set("ToggleFastForward", hotkeys.toggleFastForward); +} diff --git a/src/gui/wxgui/wxCemuConfig.h b/src/gui/wxgui/wxCemuConfig.h new file mode 100644 index 00000000..8024e27e --- /dev/null +++ b/src/gui/wxgui/wxCemuConfig.h @@ -0,0 +1,142 @@ +#pragma once + +#include "config/CemuConfig.h" +#include "config/XMLConfig.h" +#include "util/math/vector2.h" + +#include "wxgui.h" + +namespace DefaultColumnSize +{ + enum : uint32 + { + name = 500u, + version = 60u, + dlc = 50u, + game_time = 140u, + game_started = 160u, + region = 80u, + title_id = 160u + }; +}; + +typedef union +{ + struct + { + uint16 key : 13; // enough bits for all keycodes + uint16 alt : 1; + uint16 ctrl : 1; + uint16 shift : 1; + }; + uint16 raw; +} uKeyboardHotkey; + +typedef sint16 ControllerHotkey_t; + +struct sHotkeyCfg +{ + static constexpr uint8 keyboardNone{WXK_NONE}; + static constexpr sint8 controllerNone{-1}; // no enums to work with, but buttons start from 0 + + uKeyboardHotkey keyboard{keyboardNone}; + ControllerHotkey_t controller{controllerNone}; + + /* for defaults */ + sHotkeyCfg(const uKeyboardHotkey& keyboard = {keyboardNone}, const ControllerHotkey_t& controller = {controllerNone}) : keyboard(keyboard), controller(controller) {}; + + /* for reading from xml */ + sHotkeyCfg(const char* xml_values) + { + std::istringstream iss(xml_values); + iss >> keyboard.raw >> controller; + } +}; + +template<> +struct fmt::formatter : formatter +{ + template + auto format(const sHotkeyCfg c, FormatContext& ctx) const + { + std::string xml_values = fmt::format("{} {}", c.keyboard.raw, c.controller); + return formatter::format(xml_values, ctx); + } +}; + +struct wxCemuConfig +{ + ConfigValue language{wxLANGUAGE_DEFAULT}; + ConfigValue use_discord_presence{true}; + ConfigValue fullscreen{ false }; + ConfigValue fullscreen_menubar{false}; + ConfigValue feral_gamemode{false}; + + // max 15 entries + static constexpr size_t kMaxRecentEntries = 15; + std::vector recent_launch_files; + std::vector recent_nfc_files; + + Vector2i window_position{-1, -1}; + Vector2i window_size{-1, -1}; + ConfigValue window_maximized; + + ConfigValue pad_open; + Vector2i pad_position{-1, -1}; + Vector2i pad_size{-1, -1}; + ConfigValue pad_maximized; + + ConfigValue check_update{true}; + ConfigValue receive_untested_updates{false}; + ConfigValue save_screenshot{true}; + + ConfigValue did_show_vulkan_warning{false}; + ConfigValue did_show_graphic_pack_download{false}; // no longer used but we keep the config value around in case people downgrade Cemu. Despite the name this was used for the Getting Started dialog + ConfigValue did_show_macos_disclaimer{false}; + + ConfigValue show_icon_column{true}; + + int game_list_style = 0; + std::string game_list_column_order; + struct + { + uint32 name = DefaultColumnSize::name; + uint32 version = DefaultColumnSize::version; + uint32 dlc = DefaultColumnSize::dlc; + uint32 game_time = DefaultColumnSize::game_time; + uint32 game_started = DefaultColumnSize::game_started; + uint32 region = DefaultColumnSize::region; + uint32 title_id = 0; + } column_width{}; + + // hotkeys + struct + { + sHotkeyCfg modifiers; + sHotkeyCfg toggleFullscreen; + sHotkeyCfg toggleFullscreenAlt; + sHotkeyCfg exitFullscreen; + sHotkeyCfg takeScreenshot; + sHotkeyCfg toggleFastForward; + } hotkeys{}; + + void AddRecentlyLaunchedFile(std::string_view file); + void AddRecentNfcFile(std::string_view file); + + void Load(XMLConfigParser& parser); + void Save(XMLConfigParser& parser); +}; + +typedef XMLChildConfig XMLWxCemuConfig_t; + +extern XMLWxCemuConfig_t g_wxConfig; + +inline XMLWxCemuConfig_t& GetWxGuiConfigHandle() +{ + return g_wxConfig; +} + +inline wxCemuConfig& GetWxGUIConfig() +{ + return GetWxGuiConfigHandle().Data(); +} \ No newline at end of file diff --git a/src/gui/wxgui/wxWindowSystem.cpp b/src/gui/wxgui/wxWindowSystem.cpp index d717580c..344bf1c2 100644 --- a/src/gui/wxgui/wxWindowSystem.cpp +++ b/src/gui/wxgui/wxWindowSystem.cpp @@ -343,23 +343,6 @@ void WindowSystem::captureInput(const ControllerState& currentState, const Contr HotkeySettings::CaptureInput(currentState, lastState); } -sHotkeyCfg WindowSystem::getDefaultHotkeyConfig(HotKey hotKey) -{ - switch (hotKey) - { - case HotKey::EXIT_FULLSCREEN: - return sHotkeyCfg{uKeyboardHotkey{WXK_ESCAPE}}; - case HotKey::TOGGLE_FULLSCREEN: - return sHotkeyCfg{uKeyboardHotkey{WXK_F11}}; - case HotKey::TOGGLE_FULLSCREEN_ALT: - return sHotkeyCfg{uKeyboardHotkey{WXK_CONTROL_M, true}}; // ALT+ENTER - case HotKey::TAKE_SCREENSHOT: - return sHotkeyCfg{uKeyboardHotkey{WXK_F12}}; - default: - return sHotkeyCfg{}; - } -} - bool WindowSystem::isFullScreen() { return g_window_info.is_fullscreen; diff --git a/src/main.cpp b/src/main.cpp index 68f4ef12..926fb27f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -120,7 +120,7 @@ void CemuCommonInit() WindowsInitCwd(); ExceptionHandler_Init(); // read config - g_config.Load(); + GetConfigHandle().Load(); if (NetworkConfig::XMLExists()) n_config.Load(); // parallelize expensive init code