Add per game configuration options (#6187)
* common: Move settings to common from core. - Removes a dependency on core and input_common from common. * code: Wrap settings values * Port from yuzu to allow per game settings * citra_qt: Initial per-game settings dialog * citra_qt: Use new API for read/save of config values * citra_qt: Per game audio settings * citra_qt: Per game graphics settings * citra_qt: Per game system settings * citra_qt: Per game general settings * citra_qt: Document and run clang format * citra_qt: Make icon smaller and centered * citra_qt: Remove version number * Not sure how to extract that, can always add it back later * citra_qt: Wrap UISettings * citra_qt: Fix unthottled fps setting * citra_qt: Remove margin in emulation tab * citra_qt: Implement some suggestions * Bring back speed switch hotkey * Allow configuration when game is running * Rename/adjust UI stuff * citra_qt: Fix build with separate windows * citra_qt: Address feedback * citra_qt: Log per-game settings before launching games * citra_qt: Add shader cache options * Also fix android build * citra_qt: Add DLC menu option * citra_qt: Run clang-format * citra_qt: Adjust for time offset * citra_qt: Implement suggestions * Run clang-format Co-authored-by: bunnei <bunneidev@gmail.com>
This commit is contained in:
parent
f261daf2fa
commit
48ee112ceb
92 changed files with 3171 additions and 1546 deletions
|
@ -3,6 +3,7 @@
|
|||
// Refer to the license.txt file included.
|
||||
|
||||
#include <clocale>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <memory>
|
||||
#include <thread>
|
||||
|
@ -34,6 +35,7 @@
|
|||
#include "citra_qt/compatibility_list.h"
|
||||
#include "citra_qt/configuration/config.h"
|
||||
#include "citra_qt/configuration/configure_dialog.h"
|
||||
#include "citra_qt/configuration/configure_per_game.h"
|
||||
#include "citra_qt/debugger/console.h"
|
||||
#include "citra_qt/debugger/graphics/graphics.h"
|
||||
#include "citra_qt/debugger/graphics/graphics_breakpoints.h"
|
||||
|
@ -70,9 +72,11 @@
|
|||
#include "common/microprofile.h"
|
||||
#include "common/scm_rev.h"
|
||||
#include "common/scope_exit.h"
|
||||
#include "common/string_util.h"
|
||||
#ifdef ARCHITECTURE_x86_64
|
||||
#include "common/x64/cpu_detect.h"
|
||||
#endif
|
||||
#include "common/settings.h"
|
||||
#include "core/core.h"
|
||||
#include "core/dumping/backend.h"
|
||||
#include "core/file_sys/archive_extsavedata.h"
|
||||
|
@ -85,7 +89,6 @@
|
|||
#include "core/loader/loader.h"
|
||||
#include "core/movie.h"
|
||||
#include "core/savestate.h"
|
||||
#include "core/settings.h"
|
||||
#include "game_list_p.h"
|
||||
#include "input_common/main.h"
|
||||
#include "network/network_settings.h"
|
||||
|
@ -124,11 +127,13 @@ enum class CalloutFlag : uint32_t {
|
|||
};
|
||||
|
||||
void GMainWindow::ShowTelemetryCallout() {
|
||||
if (UISettings::values.callout_flags & static_cast<uint32_t>(CalloutFlag::Telemetry)) {
|
||||
if (UISettings::values.callout_flags.GetValue() &
|
||||
static_cast<uint32_t>(CalloutFlag::Telemetry)) {
|
||||
return;
|
||||
}
|
||||
|
||||
UISettings::values.callout_flags |= static_cast<uint32_t>(CalloutFlag::Telemetry);
|
||||
UISettings::values.callout_flags =
|
||||
UISettings::values.callout_flags.GetValue() | static_cast<uint32_t>(CalloutFlag::Telemetry);
|
||||
const QString telemetry_message =
|
||||
tr("<a href='https://citra-emu.org/entry/telemetry-and-why-thats-a-good-thing/'>Anonymous "
|
||||
"data is collected</a> to help improve Citra. "
|
||||
|
@ -143,7 +148,7 @@ const int GMainWindow::max_recent_files_item;
|
|||
|
||||
static void InitializeLogging() {
|
||||
Log::Filter log_filter;
|
||||
log_filter.ParseFilterString(Settings::values.log_filter);
|
||||
log_filter.ParseFilterString(Settings::values.log_filter.GetValue());
|
||||
Log::SetGlobalFilter(log_filter);
|
||||
|
||||
const std::string& log_dir = FileUtil::GetUserPath(FileUtil::UserPath::LogDir);
|
||||
|
@ -175,7 +180,7 @@ GMainWindow::GMainWindow()
|
|||
default_theme_paths = QIcon::themeSearchPaths();
|
||||
UpdateUITheme();
|
||||
|
||||
SetDiscordEnabled(UISettings::values.enable_discord_presence);
|
||||
SetDiscordEnabled(UISettings::values.enable_discord_presence.GetValue());
|
||||
discord_rpc->Update();
|
||||
|
||||
Network::Init();
|
||||
|
@ -556,8 +561,7 @@ void GMainWindow::InitializeHotkeys() {
|
|||
});
|
||||
connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Toggle Alternate Speed"), this),
|
||||
&QShortcut::activated, this, [&] {
|
||||
Settings::values.use_frame_limit_alternate =
|
||||
!Settings::values.use_frame_limit_alternate;
|
||||
Settings::values.frame_limit.SetGlobal(!Settings::values.frame_limit.UsingGlobal());
|
||||
UpdateStatusBar();
|
||||
});
|
||||
connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Toggle Texture Dumping"), this),
|
||||
|
@ -568,42 +572,25 @@ void GMainWindow::InitializeHotkeys() {
|
|||
static constexpr u16 SPEED_LIMIT_STEP = 5;
|
||||
connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Increase Speed Limit"), this),
|
||||
&QShortcut::activated, this, [&] {
|
||||
if (Settings::values.use_frame_limit_alternate) {
|
||||
if (Settings::values.frame_limit_alternate == 0) {
|
||||
return;
|
||||
}
|
||||
if (Settings::values.frame_limit_alternate < 995 - SPEED_LIMIT_STEP) {
|
||||
Settings::values.frame_limit_alternate += SPEED_LIMIT_STEP;
|
||||
} else {
|
||||
Settings::values.frame_limit_alternate = 0;
|
||||
}
|
||||
if (Settings::values.frame_limit.GetValue() == 0) {
|
||||
return;
|
||||
}
|
||||
if (Settings::values.frame_limit.GetValue() < 995 - SPEED_LIMIT_STEP) {
|
||||
Settings::values.frame_limit.SetValue(Settings::values.frame_limit.GetValue() +
|
||||
SPEED_LIMIT_STEP);
|
||||
} else {
|
||||
if (Settings::values.frame_limit == 0) {
|
||||
return;
|
||||
}
|
||||
if (Settings::values.frame_limit < 995 - SPEED_LIMIT_STEP) {
|
||||
Settings::values.frame_limit += SPEED_LIMIT_STEP;
|
||||
} else {
|
||||
Settings::values.frame_limit = 0;
|
||||
}
|
||||
Settings::values.frame_limit = 0;
|
||||
}
|
||||
UpdateStatusBar();
|
||||
});
|
||||
connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Decrease Speed Limit"), this),
|
||||
&QShortcut::activated, this, [&] {
|
||||
if (Settings::values.use_frame_limit_alternate) {
|
||||
if (Settings::values.frame_limit_alternate == 0) {
|
||||
Settings::values.frame_limit_alternate = 995;
|
||||
} else if (Settings::values.frame_limit_alternate > SPEED_LIMIT_STEP) {
|
||||
Settings::values.frame_limit_alternate -= SPEED_LIMIT_STEP;
|
||||
}
|
||||
} else {
|
||||
if (Settings::values.frame_limit == 0) {
|
||||
Settings::values.frame_limit = 995;
|
||||
} else if (Settings::values.frame_limit > SPEED_LIMIT_STEP) {
|
||||
Settings::values.frame_limit -= SPEED_LIMIT_STEP;
|
||||
UpdateStatusBar();
|
||||
}
|
||||
if (Settings::values.frame_limit.GetValue() == 0) {
|
||||
Settings::values.frame_limit = 995;
|
||||
} else if (Settings::values.frame_limit.GetValue() > SPEED_LIMIT_STEP) {
|
||||
Settings::values.frame_limit.SetValue(Settings::values.frame_limit.GetValue() -
|
||||
SPEED_LIMIT_STEP);
|
||||
UpdateStatusBar();
|
||||
}
|
||||
UpdateStatusBar();
|
||||
});
|
||||
|
@ -663,25 +650,26 @@ void GMainWindow::RestoreUIState() {
|
|||
render_window->restoreGeometry(UISettings::values.renderwindow_geometry);
|
||||
#if MICROPROFILE_ENABLED
|
||||
microProfileDialog->restoreGeometry(UISettings::values.microprofile_geometry);
|
||||
microProfileDialog->setVisible(UISettings::values.microprofile_visible);
|
||||
microProfileDialog->setVisible(UISettings::values.microprofile_visible.GetValue());
|
||||
#endif
|
||||
ui->action_Cheats->setEnabled(false);
|
||||
|
||||
game_list->LoadInterfaceLayout();
|
||||
|
||||
ui->action_Single_Window_Mode->setChecked(UISettings::values.single_window_mode);
|
||||
ui->action_Single_Window_Mode->setChecked(UISettings::values.single_window_mode.GetValue());
|
||||
ToggleWindowMode();
|
||||
|
||||
ui->action_Fullscreen->setChecked(UISettings::values.fullscreen);
|
||||
ui->action_Fullscreen->setChecked(UISettings::values.fullscreen.GetValue());
|
||||
SyncMenuUISettings();
|
||||
|
||||
ui->action_Display_Dock_Widget_Headers->setChecked(UISettings::values.display_titlebar);
|
||||
ui->action_Display_Dock_Widget_Headers->setChecked(
|
||||
UISettings::values.display_titlebar.GetValue());
|
||||
OnDisplayTitleBars(ui->action_Display_Dock_Widget_Headers->isChecked());
|
||||
|
||||
ui->action_Show_Filter_Bar->setChecked(UISettings::values.show_filter_bar);
|
||||
ui->action_Show_Filter_Bar->setChecked(UISettings::values.show_filter_bar.GetValue());
|
||||
game_list->SetFilterVisible(ui->action_Show_Filter_Bar->isChecked());
|
||||
|
||||
ui->action_Show_Status_Bar->setChecked(UISettings::values.show_status_bar);
|
||||
ui->action_Show_Status_Bar->setChecked(UISettings::values.show_status_bar.GetValue());
|
||||
statusBar()->setVisible(ui->action_Show_Status_Bar->isChecked());
|
||||
}
|
||||
|
||||
|
@ -717,6 +705,9 @@ void GMainWindow::ConnectWidgetEvents() {
|
|||
connect(game_list, &GameList::PopulatingCompleted, this,
|
||||
[this] { multiplayer_state->UpdateGameList(game_list->GetModel()); });
|
||||
|
||||
connect(game_list, &GameList::OpenPerGameGeneralRequested, this,
|
||||
&GMainWindow::OnGameListOpenPerGameProperties);
|
||||
|
||||
connect(this, &GMainWindow::EmulationStarting, render_window,
|
||||
&GRenderWindow::OnEmulationStarting);
|
||||
connect(this, &GMainWindow::EmulationStopping, render_window,
|
||||
|
@ -752,6 +743,8 @@ void GMainWindow::ConnectMenuEvents() {
|
|||
connect(ui->action_Report_Compatibility, &QAction::triggered, this,
|
||||
&GMainWindow::OnMenuReportCompatibility);
|
||||
connect(ui->action_Configure, &QAction::triggered, this, &GMainWindow::OnConfigure);
|
||||
connect(ui->action_Configure_Current_Game, &QAction::triggered, this,
|
||||
&GMainWindow::OnConfigurePerGame);
|
||||
connect(ui->action_Cheats, &QAction::triggered, this, &GMainWindow::OnCheats);
|
||||
|
||||
// View
|
||||
|
@ -1086,6 +1079,22 @@ void GMainWindow::BootGame(const QString& filename) {
|
|||
Core::Movie::GetInstance().PrepareForPlayback(movie_playback_path.toStdString());
|
||||
}
|
||||
|
||||
u64 title_id{0};
|
||||
const std::string path = filename.toStdString();
|
||||
const auto loader = Loader::GetLoader(path);
|
||||
|
||||
if (loader != nullptr && loader->ReadProgramId(title_id) == Loader::ResultStatus::Success) {
|
||||
// Load per game settings
|
||||
const std::string name{FileUtil::GetFilename(filename.toStdString())};
|
||||
const std::string config_file_name =
|
||||
title_id == 0 ? name : fmt::format("{:016X}", title_id);
|
||||
Config per_game_config(config_file_name, Config::ConfigType::PerGameConfig);
|
||||
Settings::Apply();
|
||||
|
||||
LOG_INFO(Frontend, "Using per game config file for title id {}", config_file_name);
|
||||
Settings::LogSettings();
|
||||
}
|
||||
|
||||
// Save configurations
|
||||
UpdateUISettings();
|
||||
game_list->SaveInterfaceLayout();
|
||||
|
@ -1239,6 +1248,7 @@ void GMainWindow::ShutdownGame() {
|
|||
ui->action_Stop->setEnabled(false);
|
||||
ui->action_Restart->setEnabled(false);
|
||||
ui->action_Cheats->setEnabled(false);
|
||||
ui->action_Configure_Current_Game->setEnabled(false);
|
||||
ui->action_Load_Amiibo->setEnabled(false);
|
||||
ui->action_Remove_Amiibo->setEnabled(false);
|
||||
ui->action_Report_Compatibility->setEnabled(false);
|
||||
|
@ -1398,26 +1408,42 @@ void GMainWindow::OnGameListOpenFolder(u64 data_id, GameListOpenTarget target) {
|
|||
path = Service::AM::GetTitlePath(media_type, data_id) + "content/";
|
||||
break;
|
||||
}
|
||||
case GameListOpenTarget::UPDATE_DATA:
|
||||
case GameListOpenTarget::UPDATE_DATA: {
|
||||
open_target = "Update Data";
|
||||
path = Service::AM::GetTitlePath(Service::FS::MediaType::SDMC, data_id + 0xe00000000) +
|
||||
"content/";
|
||||
break;
|
||||
case GameListOpenTarget::TEXTURE_DUMP:
|
||||
}
|
||||
case GameListOpenTarget::TEXTURE_DUMP: {
|
||||
open_target = "Dumped Textures";
|
||||
path = fmt::format("{}textures/{:016X}/",
|
||||
FileUtil::GetUserPath(FileUtil::UserPath::DumpDir), data_id);
|
||||
break;
|
||||
case GameListOpenTarget::TEXTURE_LOAD:
|
||||
}
|
||||
case GameListOpenTarget::TEXTURE_LOAD: {
|
||||
open_target = "Custom Textures";
|
||||
path = fmt::format("{}textures/{:016X}/",
|
||||
FileUtil::GetUserPath(FileUtil::UserPath::LoadDir), data_id);
|
||||
break;
|
||||
case GameListOpenTarget::MODS:
|
||||
}
|
||||
case GameListOpenTarget::MODS: {
|
||||
open_target = "Mods";
|
||||
path = fmt::format("{}mods/{:016X}/", FileUtil::GetUserPath(FileUtil::UserPath::LoadDir),
|
||||
data_id);
|
||||
break;
|
||||
}
|
||||
case GameListOpenTarget::DLC_DATA: {
|
||||
open_target = "DLC Data";
|
||||
path = fmt::format("{}Nintendo 3DS/00000000000000000000000000000000/"
|
||||
"00000000000000000000000000000000/title/0004008c/{:08x}/content/",
|
||||
FileUtil::GetUserPath(FileUtil::UserPath::SDMCDir), data_id);
|
||||
break;
|
||||
}
|
||||
case GameListOpenTarget::SHADER_CACHE: {
|
||||
open_target = "Shader Cache";
|
||||
path = FileUtil::GetUserPath(FileUtil::UserPath::ShaderDir);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
LOG_ERROR(Frontend, "Unexpected target {}", static_cast<int>(target));
|
||||
return;
|
||||
|
@ -1529,6 +1555,19 @@ void GMainWindow::OnGameListShowList(bool show) {
|
|||
game_list_placeholder->setVisible(!show);
|
||||
};
|
||||
|
||||
void GMainWindow::OnGameListOpenPerGameProperties(const QString& file) {
|
||||
const auto loader = Loader::GetLoader(file.toStdString());
|
||||
|
||||
u64 title_id{};
|
||||
if (!loader || loader->ReadProgramId(title_id) != Loader::ResultStatus::Success) {
|
||||
QMessageBox::information(this, tr("Properties"),
|
||||
tr("The game properties could not be loaded."));
|
||||
return;
|
||||
}
|
||||
|
||||
OpenPerGameConfiguration(title_id, file);
|
||||
}
|
||||
|
||||
void GMainWindow::OnMenuLoadFile() {
|
||||
const QString extensions = QStringLiteral("*.").append(
|
||||
GameList::supported_file_extensions.join(QStringLiteral(" *.")));
|
||||
|
@ -1654,6 +1693,7 @@ void GMainWindow::OnStartGame() {
|
|||
ui->action_Stop->setEnabled(true);
|
||||
ui->action_Restart->setEnabled(true);
|
||||
ui->action_Cheats->setEnabled(true);
|
||||
ui->action_Configure_Current_Game->setEnabled(true);
|
||||
ui->action_Load_Amiibo->setEnabled(true);
|
||||
ui->action_Report_Compatibility->setEnabled(true);
|
||||
ui->action_Capture_Screenshot->setEnabled(true);
|
||||
|
@ -1676,6 +1716,7 @@ void GMainWindow::OnPauseGame() {
|
|||
|
||||
void GMainWindow::OnStopGame() {
|
||||
ShutdownGame();
|
||||
Settings::RestoreGlobalState(false);
|
||||
}
|
||||
|
||||
void GMainWindow::OnLoadComplete() {
|
||||
|
@ -1769,7 +1810,7 @@ void GMainWindow::UpdateSecondaryWindowVisibility() {
|
|||
if (!emulation_running) {
|
||||
return;
|
||||
}
|
||||
if (Settings::values.layout_option == Settings::LayoutOption::SeparateWindows) {
|
||||
if (Settings::values.layout_option.GetValue() == Settings::LayoutOption::SeparateWindows) {
|
||||
secondary_window->RestoreGeometry();
|
||||
secondary_window->show();
|
||||
} else {
|
||||
|
@ -1800,7 +1841,7 @@ void GMainWindow::ChangeScreenLayout() {
|
|||
|
||||
void GMainWindow::ToggleScreenLayout() {
|
||||
const Settings::LayoutOption new_layout = []() {
|
||||
switch (Settings::values.layout_option) {
|
||||
switch (Settings::values.layout_option.GetValue()) {
|
||||
case Settings::LayoutOption::Default:
|
||||
return Settings::LayoutOption::SingleScreen;
|
||||
case Settings::LayoutOption::SingleScreen:
|
||||
|
@ -1812,7 +1853,8 @@ void GMainWindow::ToggleScreenLayout() {
|
|||
case Settings::LayoutOption::SeparateWindows:
|
||||
return Settings::LayoutOption::Default;
|
||||
default:
|
||||
LOG_ERROR(Frontend, "Unknown layout option {}", Settings::values.layout_option);
|
||||
LOG_ERROR(Frontend, "Unknown layout option {}",
|
||||
Settings::values.layout_option.GetValue());
|
||||
return Settings::LayoutOption::Default;
|
||||
}
|
||||
}();
|
||||
|
@ -1864,6 +1906,7 @@ void GMainWindow::OnLoadState() {
|
|||
}
|
||||
|
||||
void GMainWindow::OnConfigure() {
|
||||
Settings::SetConfiguringGlobal(true);
|
||||
ConfigureDialog configureDialog(this, hotkey_registry,
|
||||
!multiplayer_state->IsHostingPublicRoom());
|
||||
connect(&configureDialog, &ConfigureDialog::LanguageChanged, this,
|
||||
|
@ -1872,15 +1915,15 @@ void GMainWindow::OnConfigure() {
|
|||
const int old_input_profile_index = Settings::values.current_input_profile_index;
|
||||
const auto old_input_profiles = Settings::values.input_profiles;
|
||||
const auto old_touch_from_button_maps = Settings::values.touch_from_button_maps;
|
||||
const bool old_discord_presence = UISettings::values.enable_discord_presence;
|
||||
const bool old_discord_presence = UISettings::values.enable_discord_presence.GetValue();
|
||||
auto result = configureDialog.exec();
|
||||
if (result == QDialog::Accepted) {
|
||||
configureDialog.ApplyConfiguration();
|
||||
InitializeHotkeys();
|
||||
if (UISettings::values.theme != old_theme)
|
||||
UpdateUITheme();
|
||||
if (UISettings::values.enable_discord_presence != old_discord_presence)
|
||||
SetDiscordEnabled(UISettings::values.enable_discord_presence);
|
||||
if (UISettings::values.enable_discord_presence.GetValue() != old_discord_presence)
|
||||
SetDiscordEnabled(UISettings::values.enable_discord_presence.GetValue());
|
||||
if (!multiplayer_state->IsHostingPublicRoom())
|
||||
multiplayer_state->UpdateCredentials();
|
||||
emit UpdateThemedIcons();
|
||||
|
@ -2057,24 +2100,26 @@ void GMainWindow::OnSaveMovie() {
|
|||
|
||||
void GMainWindow::OnCaptureScreenshot() {
|
||||
OnPauseGame();
|
||||
QString path = UISettings::values.screenshot_path;
|
||||
if (!FileUtil::IsDirectory(path.toStdString())) {
|
||||
if (!FileUtil::CreateFullPath(path.toStdString())) {
|
||||
std::string path = UISettings::values.screenshot_path.GetValue();
|
||||
if (!FileUtil::IsDirectory(path)) {
|
||||
if (!FileUtil::CreateFullPath(path)) {
|
||||
QMessageBox::information(this, tr("Invalid Screenshot Directory"),
|
||||
tr("Cannot create specified screenshot directory. Screenshot "
|
||||
"path is set back to its default value."));
|
||||
path = QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::UserDir));
|
||||
path.append(QStringLiteral("screenshots/"));
|
||||
path = FileUtil::GetUserPath(FileUtil::UserPath::UserDir);
|
||||
path.append("screenshots/");
|
||||
UISettings::values.screenshot_path = path;
|
||||
};
|
||||
}
|
||||
const QString filename = game_title.remove(QRegularExpression(QStringLiteral("[\\/:?\"<>|]")));
|
||||
const QString timestamp =
|
||||
QDateTime::currentDateTime().toString(QStringLiteral("dd.MM.yy_hh.mm.ss.z"));
|
||||
path.append(QStringLiteral("/%1_%2.png").arg(filename, timestamp));
|
||||
const std::string filename =
|
||||
game_title.remove(QRegularExpression(QStringLiteral("[\\/:?\"<>|]"))).toStdString();
|
||||
const std::string timestamp =
|
||||
QDateTime::currentDateTime().toString(QStringLiteral("dd.MM.yy_hh.mm.ss.z")).toStdString();
|
||||
path.append(fmt::format("/{}_{}.png", filename, timestamp));
|
||||
|
||||
auto* const screenshot_window = secondary_window->HasFocus() ? secondary_window : render_window;
|
||||
screenshot_window->CaptureScreenshot(UISettings::values.screenshot_resolution_factor, path);
|
||||
screenshot_window->CaptureScreenshot(UISettings::values.screenshot_resolution_factor.GetValue(),
|
||||
QString::fromStdString(path));
|
||||
OnStartGame();
|
||||
}
|
||||
|
||||
|
@ -2166,22 +2211,12 @@ void GMainWindow::UpdateStatusBar() {
|
|||
|
||||
auto results = Core::System::GetInstance().GetAndResetPerfStats();
|
||||
|
||||
if (Settings::values.use_frame_limit_alternate) {
|
||||
if (Settings::values.frame_limit_alternate == 0) {
|
||||
emu_speed_label->setText(
|
||||
tr("Speed: %1%").arg(results.emulation_speed * 100.0, 0, 'f', 0));
|
||||
|
||||
} else {
|
||||
emu_speed_label->setText(tr("Speed: %1% / %2%")
|
||||
.arg(results.emulation_speed * 100.0, 0, 'f', 0)
|
||||
.arg(Settings::values.frame_limit_alternate));
|
||||
}
|
||||
} else if (Settings::values.frame_limit == 0) {
|
||||
if (Settings::values.frame_limit.GetValue() == 0) {
|
||||
emu_speed_label->setText(tr("Speed: %1%").arg(results.emulation_speed * 100.0, 0, 'f', 0));
|
||||
} else {
|
||||
emu_speed_label->setText(tr("Speed: %1% / %2%")
|
||||
.arg(results.emulation_speed * 100.0, 0, 'f', 0)
|
||||
.arg(Settings::values.frame_limit));
|
||||
.arg(Settings::values.frame_limit.GetValue()));
|
||||
}
|
||||
game_fps_label->setText(tr("Game: %1 FPS").arg(results.game_fps, 0, 'f', 0));
|
||||
emu_frametime_label->setText(tr("Frame: %1 ms").arg(results.frametime * 1000.0, 0, 'f', 2));
|
||||
|
@ -2192,7 +2227,7 @@ void GMainWindow::UpdateStatusBar() {
|
|||
}
|
||||
|
||||
void GMainWindow::HideMouseCursor() {
|
||||
if (emu_thread == nullptr || UISettings::values.hide_mouse == false) {
|
||||
if (emu_thread == nullptr || !UISettings::values.hide_mouse.GetValue()) {
|
||||
mouse_hide_timer.stop();
|
||||
ShowMouseCursor();
|
||||
return;
|
||||
|
@ -2455,6 +2490,35 @@ void GMainWindow::OnLanguageChanged(const QString& locale) {
|
|||
ui->action_Start->setText(tr("Continue"));
|
||||
}
|
||||
|
||||
void GMainWindow::OnConfigurePerGame() {
|
||||
u64 title_id{};
|
||||
Core::System::GetInstance().GetAppLoader().ReadProgramId(title_id);
|
||||
OpenPerGameConfiguration(title_id, game_path);
|
||||
}
|
||||
|
||||
void GMainWindow::OpenPerGameConfiguration(u64 title_id, const QString& file_name) {
|
||||
Core::System& system = Core::System::GetInstance();
|
||||
|
||||
Settings::SetConfiguringGlobal(false);
|
||||
ConfigurePerGame dialog(this, title_id, file_name, system);
|
||||
const auto result = dialog.exec();
|
||||
|
||||
if (result != QDialog::Accepted) {
|
||||
Settings::RestoreGlobalState(system.IsPoweredOn());
|
||||
return;
|
||||
} else if (result == QDialog::Accepted) {
|
||||
dialog.ApplyConfiguration();
|
||||
}
|
||||
|
||||
// Do not cause the global config to write local settings into the config file
|
||||
const bool is_powered_on = system.IsPoweredOn();
|
||||
Settings::RestoreGlobalState(system.IsPoweredOn());
|
||||
|
||||
if (!is_powered_on) {
|
||||
config->Save();
|
||||
}
|
||||
}
|
||||
|
||||
void GMainWindow::OnMoviePlaybackCompleted() {
|
||||
OnPauseGame();
|
||||
QMessageBox::information(this, tr("Playback Completed"), tr("Movie playback completed."));
|
||||
|
@ -2489,18 +2553,19 @@ void GMainWindow::UpdateUISettings() {
|
|||
}
|
||||
|
||||
void GMainWindow::SyncMenuUISettings() {
|
||||
ui->action_Screen_Layout_Default->setChecked(Settings::values.layout_option ==
|
||||
ui->action_Screen_Layout_Default->setChecked(Settings::values.layout_option.GetValue() ==
|
||||
Settings::LayoutOption::Default);
|
||||
ui->action_Screen_Layout_Single_Screen->setChecked(Settings::values.layout_option ==
|
||||
ui->action_Screen_Layout_Single_Screen->setChecked(Settings::values.layout_option.GetValue() ==
|
||||
Settings::LayoutOption::SingleScreen);
|
||||
ui->action_Screen_Layout_Large_Screen->setChecked(Settings::values.layout_option ==
|
||||
ui->action_Screen_Layout_Large_Screen->setChecked(Settings::values.layout_option.GetValue() ==
|
||||
Settings::LayoutOption::LargeScreen);
|
||||
ui->action_Screen_Layout_Side_by_Side->setChecked(Settings::values.layout_option ==
|
||||
ui->action_Screen_Layout_Side_by_Side->setChecked(Settings::values.layout_option.GetValue() ==
|
||||
Settings::LayoutOption::SideScreen);
|
||||
ui->action_Screen_Layout_Separate_Windows->setChecked(Settings::values.layout_option ==
|
||||
Settings::LayoutOption::SeparateWindows);
|
||||
ui->action_Screen_Layout_Swap_Screens->setChecked(Settings::values.swap_screen);
|
||||
ui->action_Screen_Layout_Upright_Screens->setChecked(Settings::values.upright_screen);
|
||||
ui->action_Screen_Layout_Separate_Windows->setChecked(
|
||||
Settings::values.layout_option.GetValue() == Settings::LayoutOption::SeparateWindows);
|
||||
ui->action_Screen_Layout_Swap_Screens->setChecked(Settings::values.swap_screen.GetValue());
|
||||
ui->action_Screen_Layout_Upright_Screens->setChecked(
|
||||
Settings::values.upright_screen.GetValue());
|
||||
}
|
||||
|
||||
void GMainWindow::RetranslateStatusBar() {
|
||||
|
@ -2573,11 +2638,13 @@ int main(int argc, char* argv[]) {
|
|||
|
||||
// Register frontend applets
|
||||
Frontend::RegisterDefaultApplets();
|
||||
Core::System::GetInstance().RegisterMiiSelector(std::make_shared<QtMiiSelector>(main_window));
|
||||
Core::System::GetInstance().RegisterSoftwareKeyboard(std::make_shared<QtKeyboard>(main_window));
|
||||
|
||||
Core::System& system = Core::System::GetInstance();
|
||||
system.RegisterMiiSelector(std::make_shared<QtMiiSelector>(main_window));
|
||||
system.RegisterSoftwareKeyboard(std::make_shared<QtKeyboard>(main_window));
|
||||
|
||||
// Register Qt image interface
|
||||
Core::System::GetInstance().RegisterImageInterface(std::make_shared<QtImageInterface>());
|
||||
system.RegisterImageInterface(std::make_shared<QtImageInterface>());
|
||||
|
||||
main_window.show();
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue