mirror of https://github.com/PCSX2/pcsx2.git
Qt: Add per-game settings UI
This commit is contained in:
parent
48dabd3ca2
commit
b47552c08f
|
@ -41,8 +41,8 @@
|
|||
#include "Settings/InterfaceSettingsWidget.h"
|
||||
#include "svnrev.h"
|
||||
|
||||
static constexpr char DISC_IMAGE_FILTER[] = QT_TRANSLATE_NOOP(
|
||||
"MainWindow", "All File Types (*.bin *.iso *.cue *.chd *.cso *.elf *.irx *.m3u);;Single-Track Raw Images (*.bin "
|
||||
static constexpr char DISC_IMAGE_FILTER[] =
|
||||
QT_TRANSLATE_NOOP("MainWindow", "All File Types (*.bin *.iso *.cue *.chd *.cso *.elf *.irx *.m3u);;Single-Track Raw Images (*.bin "
|
||||
"*.iso);;Cue Sheets (*.cue);;MAME CHD Images (*.chd);;CSO Images (*.cso);;"
|
||||
"ELF Executables (*.elf);;IRX Executables (*.irx);;Playlists (*.m3u)");
|
||||
|
||||
|
@ -106,8 +106,7 @@ void MainWindow::setupAdditionalUi()
|
|||
|
||||
for (u32 scale = 0; scale <= 10; scale++)
|
||||
{
|
||||
QAction* action =
|
||||
m_ui.menuWindowSize->addAction((scale == 0) ? tr("Internal Resolution") : tr("%1x Scale").arg(scale));
|
||||
QAction* action = m_ui.menuWindowSize->addAction((scale == 0) ? tr("Internal Resolution") : tr("%1x Scale").arg(scale));
|
||||
connect(action, &QAction::triggered, [scale]() { g_emu_thread->requestDisplaySize(static_cast<float>(scale)); });
|
||||
}
|
||||
|
||||
|
@ -120,10 +119,8 @@ void MainWindow::connectSignals()
|
|||
connect(m_ui.actionStartBios, &QAction::triggered, this, &MainWindow::onStartBIOSActionTriggered);
|
||||
connect(m_ui.actionChangeDisc, &QAction::triggered, [this] { m_ui.menuChangeDisc->exec(QCursor::pos()); });
|
||||
connect(m_ui.actionChangeDiscFromFile, &QAction::triggered, this, &MainWindow::onChangeDiscFromFileActionTriggered);
|
||||
connect(m_ui.actionChangeDiscFromDevice, &QAction::triggered, this,
|
||||
&MainWindow::onChangeDiscFromDeviceActionTriggered);
|
||||
connect(m_ui.actionChangeDiscFromGameList, &QAction::triggered, this,
|
||||
&MainWindow::onChangeDiscFromGameListActionTriggered);
|
||||
connect(m_ui.actionChangeDiscFromDevice, &QAction::triggered, this, &MainWindow::onChangeDiscFromDeviceActionTriggered);
|
||||
connect(m_ui.actionChangeDiscFromGameList, &QAction::triggered, this, &MainWindow::onChangeDiscFromGameListActionTriggered);
|
||||
connect(m_ui.menuChangeDisc, &QMenu::aboutToShow, this, &MainWindow::onChangeDiscMenuAboutToShow);
|
||||
connect(m_ui.menuChangeDisc, &QMenu::aboutToHide, this, &MainWindow::onChangeDiscMenuAboutToHide);
|
||||
connect(m_ui.actionPowerOff, &QAction::triggered, []() { g_emu_thread->shutdownVM(); });
|
||||
|
@ -132,29 +129,20 @@ void MainWindow::connectSignals()
|
|||
connect(m_ui.actionExit, &QAction::triggered, this, &MainWindow::close);
|
||||
connect(m_ui.menuLoadState, &QMenu::aboutToShow, this, &MainWindow::onLoadStateMenuAboutToShow);
|
||||
connect(m_ui.menuSaveState, &QMenu::aboutToShow, this, &MainWindow::onSaveStateMenuAboutToShow);
|
||||
connect(m_ui.actionSettings, &QAction::triggered, [this]() { doSettings(SettingsDialog::Category::Count); });
|
||||
connect(m_ui.actionInterfaceSettings, &QAction::triggered,
|
||||
[this]() { doSettings(SettingsDialog::Category::InterfaceSettings); });
|
||||
connect(m_ui.actionGameListSettings, &QAction::triggered,
|
||||
[this]() { doSettings(SettingsDialog::Category::GameListSettings); });
|
||||
connect(m_ui.actionEmulationSettings, &QAction::triggered,
|
||||
[this]() { doSettings(SettingsDialog::Category::EmulationSettings); });
|
||||
connect(m_ui.actionBIOSSettings, &QAction::triggered,
|
||||
[this]() { doSettings(SettingsDialog::Category::BIOSSettings); });
|
||||
connect(m_ui.actionSystemSettings, &QAction::triggered,
|
||||
[this]() { doSettings(SettingsDialog::Category::SystemSettings); });
|
||||
connect(m_ui.actionGraphicsSettings, &QAction::triggered,
|
||||
[this]() { doSettings(SettingsDialog::Category::GraphicsSettings); });
|
||||
connect(m_ui.actionAudioSettings, &QAction::triggered,
|
||||
[this]() { doSettings(SettingsDialog::Category::AudioSettings); });
|
||||
connect(m_ui.actionMemoryCardSettings, &QAction::triggered,
|
||||
[this]() { doSettings(SettingsDialog::Category::MemoryCardSettings); });
|
||||
connect(m_ui.actionControllerSettings, &QAction::triggered,
|
||||
[this]() { doControllerSettings(ControllerSettingsDialog::Category::GlobalSettings); });
|
||||
connect(m_ui.actionHotkeySettings, &QAction::triggered,
|
||||
[this]() { doControllerSettings(ControllerSettingsDialog::Category::HotkeySettings); });
|
||||
connect(m_ui.actionAddGameDirectory, &QAction::triggered,
|
||||
[this]() { getSettingsDialog()->getGameListSettingsWidget()->addSearchDirectory(this); });
|
||||
connect(m_ui.actionSettings, &QAction::triggered, [this]() { doSettings(); });
|
||||
connect(m_ui.actionInterfaceSettings, &QAction::triggered, [this]() { doSettings("Interface"); });
|
||||
connect(m_ui.actionGameListSettings, &QAction::triggered, [this]() { doSettings("Game List"); });
|
||||
connect(m_ui.actionEmulationSettings, &QAction::triggered, [this]() { doSettings("Emulation"); });
|
||||
connect(m_ui.actionBIOSSettings, &QAction::triggered, [this]() { doSettings("BIOS"); });
|
||||
connect(m_ui.actionSystemSettings, &QAction::triggered, [this]() { doSettings("System"); });
|
||||
connect(m_ui.actionGraphicsSettings, &QAction::triggered, [this]() { doSettings("Graphics"); });
|
||||
connect(m_ui.actionAudioSettings, &QAction::triggered, [this]() { doSettings("Audio"); });
|
||||
connect(m_ui.actionMemoryCardSettings, &QAction::triggered, [this]() { doSettings("Memory Card"); });
|
||||
connect(
|
||||
m_ui.actionControllerSettings, &QAction::triggered, [this]() { doControllerSettings(ControllerSettingsDialog::Category::GlobalSettings); });
|
||||
connect(m_ui.actionHotkeySettings, &QAction::triggered, [this]() { doControllerSettings(ControllerSettingsDialog::Category::HotkeySettings); });
|
||||
connect(
|
||||
m_ui.actionAddGameDirectory, &QAction::triggered, [this]() { getSettingsDialog()->getGameListSettingsWidget()->addSearchDirectory(this); });
|
||||
connect(m_ui.actionScanForNewGames, &QAction::triggered, [this]() { refreshGameList(false); });
|
||||
connect(m_ui.actionRescanAllGames, &QAction::triggered, [this]() { refreshGameList(true); });
|
||||
connect(m_ui.actionViewToolbar, &QAction::toggled, this, &MainWindow::onViewToolbarActionToggled);
|
||||
|
@ -180,26 +168,22 @@ void MainWindow::connectSignals()
|
|||
if (isShowingGameList())
|
||||
m_game_list_widget->gridZoomOut();
|
||||
});
|
||||
connect(m_ui.actionGridViewRefreshCovers, &QAction::triggered, m_game_list_widget,
|
||||
&GameListWidget::refreshGridCovers);
|
||||
connect(m_ui.actionGridViewRefreshCovers, &QAction::triggered, m_game_list_widget, &GameListWidget::refreshGridCovers);
|
||||
|
||||
// These need to be queued connections to stop crashing due to menus opening/closing and switching focus.
|
||||
connect(m_game_list_widget, &GameListWidget::refreshProgress, this, &MainWindow::onGameListRefreshProgress);
|
||||
connect(m_game_list_widget, &GameListWidget::refreshComplete, this, &MainWindow::onGameListRefreshComplete);
|
||||
connect(m_game_list_widget, &GameListWidget::selectionChanged, this, &MainWindow::onGameListSelectionChanged,
|
||||
Qt::QueuedConnection);
|
||||
connect(m_game_list_widget, &GameListWidget::entryActivated, this, &MainWindow::onGameListEntryActivated,
|
||||
Qt::QueuedConnection);
|
||||
connect(m_game_list_widget, &GameListWidget::entryContextMenuRequested, this,
|
||||
&MainWindow::onGameListEntryContextMenuRequested, Qt::QueuedConnection);
|
||||
connect(m_game_list_widget, &GameListWidget::selectionChanged, this, &MainWindow::onGameListSelectionChanged, Qt::QueuedConnection);
|
||||
connect(m_game_list_widget, &GameListWidget::entryActivated, this, &MainWindow::onGameListEntryActivated, Qt::QueuedConnection);
|
||||
connect(
|
||||
m_game_list_widget, &GameListWidget::entryContextMenuRequested, this, &MainWindow::onGameListEntryContextMenuRequested, Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
void MainWindow::connectVMThreadSignals(EmuThread* thread)
|
||||
{
|
||||
connect(thread, &EmuThread::onCreateDisplayRequested, this, &MainWindow::createDisplay, Qt::BlockingQueuedConnection);
|
||||
connect(thread, &EmuThread::onUpdateDisplayRequested, this, &MainWindow::updateDisplay, Qt::BlockingQueuedConnection);
|
||||
connect(thread, &EmuThread::onDestroyDisplayRequested, this, &MainWindow::destroyDisplay,
|
||||
Qt::BlockingQueuedConnection);
|
||||
connect(thread, &EmuThread::onDestroyDisplayRequested, this, &MainWindow::destroyDisplay, Qt::BlockingQueuedConnection);
|
||||
connect(thread, &EmuThread::onResizeDisplayRequested, this, &MainWindow::displayResizeRequested);
|
||||
connect(thread, &EmuThread::onVMStarting, this, &MainWindow::onVMStarting);
|
||||
connect(thread, &EmuThread::onVMStarted, this, &MainWindow::onVMStarted);
|
||||
|
@ -221,9 +205,8 @@ void MainWindow::connectVMThreadSignals(EmuThread* thread)
|
|||
GSRendererType::OGL, GSRendererType::VK, GSRendererType::SW, GSRendererType::Null};
|
||||
for (GSRendererType renderer : renderers)
|
||||
{
|
||||
connect(
|
||||
m_ui.menuDebugSwitchRenderer->addAction(QString::fromUtf8(Pcsx2Config::GSOptions::GetRendererName(renderer))),
|
||||
&QAction::triggered, [renderer] { g_emu_thread->switchRenderer(renderer); });
|
||||
connect(m_ui.menuDebugSwitchRenderer->addAction(QString::fromUtf8(Pcsx2Config::GSOptions::GetRendererName(renderer))), &QAction::triggered,
|
||||
[renderer] { g_emu_thread->switchRenderer(renderer); });
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -462,10 +445,7 @@ void MainWindow::clearProgressBar()
|
|||
m_ui.statusBar->removeWidget(m_status_progress_widget);
|
||||
}
|
||||
|
||||
bool MainWindow::isShowingGameList() const
|
||||
{
|
||||
return m_ui.mainContainer->currentIndex() == 0;
|
||||
}
|
||||
bool MainWindow::isShowingGameList() const { return m_ui.mainContainer->currentIndex() == 0; }
|
||||
|
||||
void MainWindow::switchToGameListView()
|
||||
{
|
||||
|
@ -498,25 +478,13 @@ void MainWindow::switchToEmulationView()
|
|||
m_display_widget->setFocus();
|
||||
}
|
||||
|
||||
void MainWindow::refreshGameList(bool invalidate_cache)
|
||||
{
|
||||
m_game_list_widget->refresh(invalidate_cache);
|
||||
}
|
||||
void MainWindow::refreshGameList(bool invalidate_cache) { m_game_list_widget->refresh(invalidate_cache); }
|
||||
|
||||
void MainWindow::invalidateSaveStateCache()
|
||||
{
|
||||
m_save_states_invalidated = true;
|
||||
}
|
||||
void MainWindow::invalidateSaveStateCache() { m_save_states_invalidated = true; }
|
||||
|
||||
void MainWindow::reportError(const QString& title, const QString& message)
|
||||
{
|
||||
QMessageBox::critical(this, title, message);
|
||||
}
|
||||
void MainWindow::reportError(const QString& title, const QString& message) { QMessageBox::critical(this, title, message); }
|
||||
|
||||
void Host::InvalidateSaveStateCache()
|
||||
{
|
||||
QMetaObject::invokeMethod(g_main_window, &MainWindow::invalidateSaveStateCache, Qt::QueuedConnection);
|
||||
}
|
||||
void Host::InvalidateSaveStateCache() { QMetaObject::invokeMethod(g_main_window, &MainWindow::invalidateSaveStateCache, Qt::QueuedConnection); }
|
||||
|
||||
void MainWindow::onGameListRefreshProgress(const QString& status, int current, int total)
|
||||
{
|
||||
|
@ -524,10 +492,7 @@ void MainWindow::onGameListRefreshProgress(const QString& status, int current, i
|
|||
setProgressBar(current, total);
|
||||
}
|
||||
|
||||
void MainWindow::onGameListRefreshComplete()
|
||||
{
|
||||
clearProgressBar();
|
||||
}
|
||||
void MainWindow::onGameListRefreshComplete() { clearProgressBar(); }
|
||||
|
||||
void MainWindow::onGameListSelectionChanged()
|
||||
{
|
||||
|
@ -555,8 +520,7 @@ void MainWindow::onGameListEntryActivated()
|
|||
}
|
||||
|
||||
// only resume if the option is enabled, and we have one for this game
|
||||
const bool resume =
|
||||
(VMManager::ShouldSaveResumeState() && VMManager::HasSaveStateInSlot(entry->serial.c_str(), entry->crc, -1));
|
||||
const bool resume = (VMManager::ShouldSaveResumeState() && VMManager::HasSaveStateInSlot(entry->serial.c_str(), entry->crc, -1));
|
||||
startGameListEntry(entry, resume ? std::optional<s32>(-1) : std::optional<s32>(), std::nullopt);
|
||||
}
|
||||
|
||||
|
@ -570,7 +534,9 @@ void MainWindow::onGameListEntryContextMenuRequested(const QPoint& point)
|
|||
if (entry)
|
||||
{
|
||||
QAction* action = menu.addAction(tr("Properties..."));
|
||||
// connect(action, &QAction::triggered, [this, entry]() { GamePropertiesDialog::showForEntry(entry, this); });
|
||||
action->setEnabled(!entry->serial.empty());
|
||||
if (action->isEnabled())
|
||||
connect(action, &QAction::triggered, [this, entry]() { SettingsDialog::openGamePropertiesDialog(entry, entry->crc); });
|
||||
|
||||
action = menu.addAction(tr("Open Containing Directory..."));
|
||||
connect(action, &QAction::triggered, [this, entry]() {
|
||||
|
@ -608,8 +574,7 @@ void MainWindow::onGameListEntryContextMenuRequested(const QPoint& point)
|
|||
}
|
||||
|
||||
menu.addSeparator();
|
||||
populateLoadStateMenu(&menu, QString::fromStdString(entry->path), QString::fromStdString(entry->serial),
|
||||
entry->crc);
|
||||
populateLoadStateMenu(&menu, QString::fromStdString(entry->path), QString::fromStdString(entry->serial), entry->crc);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -632,8 +597,8 @@ void MainWindow::onGameListEntryContextMenuRequested(const QPoint& point)
|
|||
|
||||
void MainWindow::onStartFileActionTriggered()
|
||||
{
|
||||
QString filename = QDir::toNativeSeparators(
|
||||
QFileDialog::getOpenFileName(this, tr("Select Disc Image"), QString(), tr(DISC_IMAGE_FILTER), nullptr));
|
||||
QString filename =
|
||||
QDir::toNativeSeparators(QFileDialog::getOpenFileName(this, tr("Select Disc Image"), QString(), tr(DISC_IMAGE_FILTER), nullptr));
|
||||
if (filename.isEmpty())
|
||||
return;
|
||||
|
||||
|
@ -653,18 +618,14 @@ void MainWindow::onChangeDiscFromFileActionTriggered()
|
|||
{
|
||||
ScopedVMPause pauser(m_vm_paused);
|
||||
|
||||
QString filename =
|
||||
QFileDialog::getOpenFileName(this, tr("Select Disc Image"), QString(), tr(DISC_IMAGE_FILTER), nullptr);
|
||||
QString filename = QFileDialog::getOpenFileName(this, tr("Select Disc Image"), QString(), tr(DISC_IMAGE_FILTER), nullptr);
|
||||
if (filename.isEmpty())
|
||||
return;
|
||||
|
||||
g_emu_thread->changeDisc(filename);
|
||||
}
|
||||
|
||||
void MainWindow::onChangeDiscFromGameListActionTriggered()
|
||||
{
|
||||
switchToGameListView();
|
||||
}
|
||||
void MainWindow::onChangeDiscFromGameListActionTriggered() { switchToGameListView(); }
|
||||
|
||||
void MainWindow::onChangeDiscFromDeviceActionTriggered()
|
||||
{
|
||||
|
@ -676,9 +637,7 @@ void MainWindow::onChangeDiscMenuAboutToShow()
|
|||
// TODO: This is where we would populate the playlist if there is one.
|
||||
}
|
||||
|
||||
void MainWindow::onChangeDiscMenuAboutToHide()
|
||||
{
|
||||
}
|
||||
void MainWindow::onChangeDiscMenuAboutToHide() {}
|
||||
|
||||
void MainWindow::onLoadStateMenuAboutToShow()
|
||||
{
|
||||
|
@ -732,22 +691,29 @@ void MainWindow::onViewGamePropertiesActionTriggered()
|
|||
{
|
||||
if (!m_vm_valid)
|
||||
return;
|
||||
|
||||
// prefer to use a game list entry, if we have one, that way the summary is populated
|
||||
if (!m_current_disc_path.isEmpty())
|
||||
{
|
||||
auto lock = GameList::GetLock();
|
||||
const GameList::Entry* entry = GameList::GetEntryForPath(m_current_disc_path.toUtf8().constData());
|
||||
if (entry)
|
||||
{
|
||||
SettingsDialog::openGamePropertiesDialog(entry, entry->crc);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::onGitHubRepositoryActionTriggered()
|
||||
{
|
||||
QtUtils::OpenURL(this, AboutDialog::getGitHubRepositoryUrl());
|
||||
// open properties for the current running file (isn't in the game list)
|
||||
if (m_current_game_crc != 0)
|
||||
SettingsDialog::openGamePropertiesDialog(nullptr, m_current_game_crc);
|
||||
}
|
||||
|
||||
void MainWindow::onSupportForumsActionTriggered()
|
||||
{
|
||||
QtUtils::OpenURL(this, AboutDialog::getSupportForumsUrl());
|
||||
}
|
||||
void MainWindow::onGitHubRepositoryActionTriggered() { QtUtils::OpenURL(this, AboutDialog::getGitHubRepositoryUrl()); }
|
||||
|
||||
void MainWindow::onDiscordServerActionTriggered()
|
||||
{
|
||||
QtUtils::OpenURL(this, AboutDialog::getDiscordServerUrl());
|
||||
}
|
||||
void MainWindow::onSupportForumsActionTriggered() { QtUtils::OpenURL(this, AboutDialog::getSupportForumsUrl()); }
|
||||
|
||||
void MainWindow::onDiscordServerActionTriggered() { QtUtils::OpenURL(this, AboutDialog::getDiscordServerUrl()); }
|
||||
|
||||
void MainWindow::onAboutActionTriggered()
|
||||
{
|
||||
|
@ -755,9 +721,7 @@ void MainWindow::onAboutActionTriggered()
|
|||
about.exec();
|
||||
}
|
||||
|
||||
void MainWindow::onCheckForUpdatesActionTriggered()
|
||||
{
|
||||
}
|
||||
void MainWindow::onCheckForUpdatesActionTriggered() {}
|
||||
|
||||
void MainWindow::onToolsOpenDataDirectoryTriggered()
|
||||
{
|
||||
|
@ -776,7 +740,7 @@ void MainWindow::onThemeChangedFromSettings()
|
|||
{
|
||||
// reopen the settings dialog after recreating
|
||||
onThemeChanged();
|
||||
g_main_window->doSettings(SettingsDialog::Category::InterfaceSettings);
|
||||
g_main_window->doSettings();
|
||||
}
|
||||
|
||||
void MainWindow::onVMStarting()
|
||||
|
@ -905,9 +869,8 @@ DisplayWidget* MainWindow::createDisplay(bool fullscreen, bool render_to_main)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
if (!host_display->CreateRenderDevice(wi.value(), Host::GetStringSettingValue("EmuCore/GS", "Adapter", ""),
|
||||
EmuConfig.GetEffectiveVsyncMode(), Host::GetBoolSettingValue("EmuCore/GS", "ThreadedPresentation", false),
|
||||
Host::GetBoolSettingValue("EmuCore/GS", "UseDebugDevice", false)))
|
||||
if (!host_display->CreateRenderDevice(wi.value(), Host::GetStringSettingValue("EmuCore/GS", "Adapter", ""), EmuConfig.GetEffectiveVsyncMode(),
|
||||
Host::GetBoolSettingValue("EmuCore/GS", "ThreadedPresentation", false), Host::GetBoolSettingValue("EmuCore/GS", "UseDebugDevice", false)))
|
||||
{
|
||||
QMessageBox::critical(this, tr("Error"), tr("Failed to create host display device context."));
|
||||
destroyDisplayWidget();
|
||||
|
@ -1042,10 +1005,7 @@ void MainWindow::displayResizeRequested(qint32 width, qint32 height)
|
|||
resize(QSize(std::max<qint32>(width, 1), std::max<qint32>(height + extra_height, 1)));
|
||||
}
|
||||
|
||||
void MainWindow::destroyDisplay()
|
||||
{
|
||||
destroyDisplayWidget();
|
||||
}
|
||||
void MainWindow::destroyDisplay() { destroyDisplayWidget(); }
|
||||
|
||||
void MainWindow::focusDisplayWidget()
|
||||
{
|
||||
|
@ -1127,14 +1087,14 @@ SettingsDialog* MainWindow::getSettingsDialog()
|
|||
if (!m_settings_dialog)
|
||||
{
|
||||
m_settings_dialog = new SettingsDialog(this);
|
||||
connect(m_settings_dialog->getInterfaceSettingsWidget(), &InterfaceSettingsWidget::themeChanged, this,
|
||||
&MainWindow::onThemeChangedFromSettings);
|
||||
connect(
|
||||
m_settings_dialog->getInterfaceSettingsWidget(), &InterfaceSettingsWidget::themeChanged, this, &MainWindow::onThemeChangedFromSettings);
|
||||
}
|
||||
|
||||
return m_settings_dialog;
|
||||
}
|
||||
|
||||
void MainWindow::doSettings(SettingsDialog::Category category)
|
||||
void MainWindow::doSettings(const char* category /* = nullptr */)
|
||||
{
|
||||
SettingsDialog* dlg = getSettingsDialog();
|
||||
if (!dlg->isVisible())
|
||||
|
@ -1143,7 +1103,7 @@ void MainWindow::doSettings(SettingsDialog::Category category)
|
|||
dlg->show();
|
||||
}
|
||||
|
||||
if (category != SettingsDialog::Category::Count)
|
||||
if (category)
|
||||
dlg->setCategory(category);
|
||||
}
|
||||
|
||||
|
@ -1168,8 +1128,7 @@ void MainWindow::doControllerSettings(ControllerSettingsDialog::Category categor
|
|||
dlg->setCategory(category);
|
||||
}
|
||||
|
||||
void MainWindow::startGameListEntry(const GameList::Entry* entry, std::optional<s32> save_slot,
|
||||
std::optional<bool> fast_boot)
|
||||
void MainWindow::startGameListEntry(const GameList::Entry* entry, std::optional<s32> save_slot, std::optional<bool> fast_boot)
|
||||
{
|
||||
std::shared_ptr<VMBootParameters> params = std::make_shared<VMBootParameters>();
|
||||
params->fast_boot = fast_boot;
|
||||
|
@ -1193,15 +1152,13 @@ void MainWindow::startGameListEntry(const GameList::Entry* entry, std::optional<
|
|||
|
||||
void MainWindow::setGameListEntryCoverImage(const GameList::Entry* entry)
|
||||
{
|
||||
const QString filename(QFileDialog::getOpenFileName(this, tr("Select Cover Image"), QString(),
|
||||
tr("All Cover Image Types (*.jpg *.jpeg *.png)")));
|
||||
const QString filename(QFileDialog::getOpenFileName(this, tr("Select Cover Image"), QString(), tr("All Cover Image Types (*.jpg *.jpeg *.png)")));
|
||||
if (filename.isEmpty())
|
||||
return;
|
||||
|
||||
if (!GameList::GetCoverImagePathForEntry(entry).empty())
|
||||
{
|
||||
if (QMessageBox::question(this, tr("Cover Already Exists"),
|
||||
tr("A cover image for this game already exists, do you wish to replace it?"),
|
||||
if (QMessageBox::question(this, tr("Cover Already Exists"), tr("A cover image for this game already exists, do you wish to replace it?"),
|
||||
QMessageBox::Yes, QMessageBox::No) != QMessageBox::Yes)
|
||||
{
|
||||
return;
|
||||
|
@ -1276,8 +1233,7 @@ void MainWindow::populateLoadStateMenu(QMenu* menu, const QString& filename, con
|
|||
|
||||
QAction* action = menu->addAction(is_right_click_menu ? tr("Load State File...") : tr("Load From File..."));
|
||||
connect(action, &QAction::triggered, [this, filename]() {
|
||||
const QString path(
|
||||
QFileDialog::getOpenFileName(this, tr("Select Save State File"), QString(), tr("Save States (*.p2s)")));
|
||||
const QString path(QFileDialog::getOpenFileName(this, tr("Select Save State File"), QString(), tr("Save States (*.p2s)")));
|
||||
if (path.isEmpty())
|
||||
return;
|
||||
|
||||
|
@ -1328,8 +1284,7 @@ void MainWindow::populateSaveStateMenu(QMenu* menu, const QString& serial, quint
|
|||
return;
|
||||
|
||||
connect(menu->addAction(tr("Save To File...")), &QAction::triggered, [this]() {
|
||||
const QString path(
|
||||
QFileDialog::getSaveFileName(this, tr("Select Save State File"), QString(), tr("Save States (*.p2s)")));
|
||||
const QString path(QFileDialog::getSaveFileName(this, tr("Select Save State File"), QString(), tr("Save States (*.p2s)")));
|
||||
if (path.isEmpty())
|
||||
return;
|
||||
|
||||
|
|
|
@ -136,7 +136,7 @@ private:
|
|||
void setDisplayFullscreen(const std::string& fullscreen_mode);
|
||||
|
||||
SettingsDialog* getSettingsDialog();
|
||||
void doSettings(SettingsDialog::Category category = SettingsDialog::Category::Count);
|
||||
void doSettings(const char* category = nullptr);
|
||||
|
||||
ControllerSettingsDialog* getControllerSettingsDialog();
|
||||
void doControllerSettings(ControllerSettingsDialog::Category category = ControllerSettingsDialog::Category::Count);
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
|
||||
#include "EmuThread.h"
|
||||
#include "QtHost.h"
|
||||
#include "SettingsDialog.h"
|
||||
|
||||
namespace SettingWidgetBinder
|
||||
{
|
||||
|
@ -41,15 +42,27 @@ namespace SettingWidgetBinder
|
|||
{
|
||||
static bool getBoolValue(const T* widget);
|
||||
static void setBoolValue(T* widget, bool value);
|
||||
static void makeNullableBool(T* widget, bool globalValue);
|
||||
static std::optional<bool> getNullableBoolValue(const T* widget);
|
||||
static void setNullableBoolValue(T* widget, std::optional<bool> value);
|
||||
|
||||
static int getIntValue(const T* widget);
|
||||
static void setIntValue(T* widget, int value);
|
||||
static void setIntValue(T* widget, bool nullable, int value);
|
||||
static void makeNullableInt(T* widget, int globalValue);
|
||||
static std::optional<int> getNullableIntValue(const T* widget);
|
||||
static void setNullableIntValue(T* widget, std::optional<int> value);
|
||||
|
||||
static int getFloatValue(const T* widget);
|
||||
static void setFloatValue(T* widget, int value);
|
||||
static void makeNullableFloat(T* widget, float globalValue);
|
||||
static std::optional<float> getNullableFloatValue(const T* widget);
|
||||
static void setNullableFloatValue(T* widget, std::optional<float> value);
|
||||
|
||||
static QString getStringValue(const T* widget);
|
||||
static void setStringValue(T* widget, const QString& value);
|
||||
static void makeNullableString(T* widget, const QString& globalValue);
|
||||
static std::optional<QString> getNullableStringValue(const T* widget);
|
||||
static void setNullableFloatValue(T* widget, std::optional<QString> value);
|
||||
|
||||
template <typename F>
|
||||
static void connectValueChanged(T* widget, F func);
|
||||
|
@ -59,19 +72,28 @@ namespace SettingWidgetBinder
|
|||
struct SettingAccessor<QLineEdit>
|
||||
{
|
||||
static bool getBoolValue(const QLineEdit* widget) { return widget->text().toInt() != 0; }
|
||||
static void setBoolValue(QLineEdit* widget, bool value)
|
||||
{
|
||||
widget->setText(value ? QStringLiteral("1") : QStringLiteral("0"));
|
||||
}
|
||||
static void setBoolValue(QLineEdit* widget, bool value) { widget->setText(value ? QStringLiteral("1") : QStringLiteral("0")); }
|
||||
static void makeNullableBool(QLineEdit* widget, bool globalValue) { widget->setEnabled(false); }
|
||||
static std::optional<bool> getNullableBoolValue(const QLineEdit* widget) { return getBoolValue(widget); }
|
||||
static void setNullableBoolValue(QLineEdit* widget, std::optional<bool> value) { setBoolValue(widget, value.value_or(false)); }
|
||||
|
||||
static int getIntValue(const QLineEdit* widget) { return widget->text().toInt(); }
|
||||
static void setIntValue(QLineEdit* widget, int value) { widget->setText(QString::number(value)); }
|
||||
static void makeNullableInt(QLineEdit* widget, int globalValue) { widget->setEnabled(false); }
|
||||
static std::optional<int> getNullableIntValue(const QLineEdit* widget) { return getIntValue(widget); }
|
||||
static void setNullableIntValue(QLineEdit* widget, std::optional<int> value) { setIntValue(widget, value.value_or(0)); }
|
||||
|
||||
static float getFloatValue(const QLineEdit* widget) { return widget->text().toFloat(); }
|
||||
static void setFloatValue(QLineEdit* widget, float value) { widget->setText(QString::number(value)); }
|
||||
static void makeNullableFloat(QLineEdit* widget, float globalValue) { widget->setEnabled(false); }
|
||||
static std::optional<float> getNullableFloatValue(const QLineEdit* widget) { return getFloatValue(widget); }
|
||||
static void setNullableFloatValue(QLineEdit* widget, std::optional<float> value) { setFloatValue(widget, value.value_or(0.0f)); }
|
||||
|
||||
static QString getStringValue(const QLineEdit* widget) { return widget->text(); }
|
||||
static void setStringValue(QLineEdit* widget, const QString& value) { widget->setText(value); }
|
||||
static void makeNullableString(QLineEdit* widget, const QString& globalValue) { widget->setEnabled(false); }
|
||||
static std::optional<QString> getNullableStringValue(const QLineEdit* widget) { return getStringValue(widget); }
|
||||
static void setNullableStringValue(QLineEdit* widget, std::optional<QString> value) { setStringValue(widget, value.value_or(QString())); }
|
||||
|
||||
template <typename F>
|
||||
static void connectValueChanged(QLineEdit* widget, F func)
|
||||
|
@ -83,14 +105,49 @@ namespace SettingWidgetBinder
|
|||
template <>
|
||||
struct SettingAccessor<QComboBox>
|
||||
{
|
||||
static bool isNullValue(const QComboBox* widget) { return (widget->currentIndex() == 0); }
|
||||
|
||||
static bool getBoolValue(const QComboBox* widget) { return widget->currentIndex() > 0; }
|
||||
static void setBoolValue(QComboBox* widget, bool value) { widget->setCurrentIndex(value ? 1 : 0); }
|
||||
static void makeNullableBool(QComboBox* widget, bool globalValue)
|
||||
{
|
||||
widget->insertItem(0, globalValue ? qApp->translate("SettingsDialog", "Use Global Setting [Enabled]") :
|
||||
qApp->translate("SettingsDialog", "Use Global Setting [Disabled]"));
|
||||
}
|
||||
|
||||
static int getIntValue(const QComboBox* widget) { return widget->currentIndex(); }
|
||||
static void setIntValue(QComboBox* widget, int value) { widget->setCurrentIndex(value); }
|
||||
static void makeNullableInt(QComboBox* widget, int globalValue)
|
||||
{
|
||||
widget->insertItem(0, qApp->translate("SettingsDialog", "Use Global Setting [%1]")
|
||||
.arg((globalValue >= 0 && globalValue < widget->count()) ? widget->itemText(globalValue) : QString()));
|
||||
}
|
||||
static std::optional<int> getNullableIntValue(const QComboBox* widget)
|
||||
{
|
||||
return isNullValue(widget) ? std::nullopt : std::optional<int>(widget->currentIndex() + 1);
|
||||
}
|
||||
static void setNullableIntValue(QComboBox* widget, std::optional<int> value)
|
||||
{
|
||||
widget->setCurrentIndex(value.has_value() ? (value.value() + 1) : 0);
|
||||
}
|
||||
|
||||
static float getFloatValue(const QComboBox* widget) { return static_cast<float>(widget->currentIndex()); }
|
||||
static void setFloatValue(QComboBox* widget, float value) { widget->setCurrentIndex(static_cast<int>(value)); }
|
||||
static void makeNullableFloat(QComboBox* widget, float globalValue)
|
||||
{
|
||||
widget->insertItem(0,
|
||||
qApp->translate("SettingsDialog", "Use Global Setting [%1]")
|
||||
.arg((globalValue >= 0.0f && static_cast<int>(globalValue) < widget->count()) ? widget->itemText(static_cast<int>(globalValue)) :
|
||||
QString()));
|
||||
}
|
||||
static std::optional<float> getNullableFloatValue(const QComboBox* widget)
|
||||
{
|
||||
return isNullValue(widget) ? std::nullopt : std::optional<float>(static_cast<float>(widget->currentIndex() + 1));
|
||||
}
|
||||
static void setNullableFloatValue(QComboBox* widget, std::optional<float> value)
|
||||
{
|
||||
widget->setCurrentIndex(value.has_value() ? static_cast<int>(value.value() + 1.0f) : 0);
|
||||
}
|
||||
|
||||
static QString getStringValue(const QComboBox* widget)
|
||||
{
|
||||
|
@ -105,7 +162,6 @@ namespace SettingWidgetBinder
|
|||
|
||||
return widget->currentText();
|
||||
}
|
||||
|
||||
static void setStringValue(QComboBox* widget, const QString& value)
|
||||
{
|
||||
const int index = widget->findData(value);
|
||||
|
@ -117,6 +173,15 @@ namespace SettingWidgetBinder
|
|||
|
||||
widget->setCurrentText(value);
|
||||
}
|
||||
static void makeNullableString(QComboBox* widget, const QString& globalValue) { makeNullableInt(widget, widget->findData(globalValue)); }
|
||||
static std::optional<QString> getNullableStringValue(const QComboBox* widget)
|
||||
{
|
||||
return isNullValue(widget) ? std::nullopt : std::optional<QString>(getStringValue(widget));
|
||||
}
|
||||
static void setNullableStringValue(QComboBox* widget, std::optional<QString> value)
|
||||
{
|
||||
isNullValue(widget) ? widget->setCurrentIndex(0) : setStringValue(widget, value.value());
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
static void connectValueChanged(QComboBox* widget, F func)
|
||||
|
@ -130,18 +195,53 @@ namespace SettingWidgetBinder
|
|||
{
|
||||
static bool getBoolValue(const QCheckBox* widget) { return widget->isChecked(); }
|
||||
static void setBoolValue(QCheckBox* widget, bool value) { widget->setChecked(value); }
|
||||
static void makeNullableBool(QCheckBox* widget, bool globalValue) { widget->setTristate(true); }
|
||||
static std::optional<bool> getNullableBoolValue(const QCheckBox* widget)
|
||||
{
|
||||
return (widget->checkState() == Qt::PartiallyChecked) ? std::nullopt : std::optional<bool>(widget->isChecked());
|
||||
}
|
||||
static void setNullableBoolValue(QCheckBox* widget, std::optional<bool> value)
|
||||
{
|
||||
widget->setCheckState(value.has_value() ? (value.value() ? Qt::Checked : Qt::Unchecked) : Qt::PartiallyChecked);
|
||||
}
|
||||
|
||||
static int getIntValue(const QCheckBox* widget) { return widget->isChecked() ? 1 : 0; }
|
||||
static void setIntValue(QCheckBox* widget, int value) { widget->setChecked(value != 0); }
|
||||
static void makeNullableInt(QCheckBox* widget, int globalValue) { widget->setTristate(true); }
|
||||
static std::optional<int> getNullableIntValue(const QCheckBox* widget)
|
||||
{
|
||||
return (widget->checkState() == Qt::PartiallyChecked) ? std::nullopt : std::optional<int>(widget->isChecked() ? 1 : 0);
|
||||
}
|
||||
static void setNullableIntValue(QCheckBox* widget, std::optional<int> value)
|
||||
{
|
||||
widget->setCheckState(value.has_value() ? ((value.value() != 0) ? Qt::Checked : Qt::Unchecked) : Qt::PartiallyChecked);
|
||||
}
|
||||
|
||||
static float getFloatValue(const QCheckBox* widget) { return widget->isChecked() ? 1.0f : 0.0f; }
|
||||
static void setFloatValue(QCheckBox* widget, float value) { widget->setChecked(value != 0.0f); }
|
||||
|
||||
static QString getStringValue(const QCheckBox* widget)
|
||||
static void makeNullableFloat(QCheckBox* widget, float globalValue) { widget->setTristate(true); }
|
||||
static std::optional<float> getNullableFloatValue(const QCheckBox* widget)
|
||||
{
|
||||
return widget->isChecked() ? QStringLiteral("1") : QStringLiteral("0");
|
||||
return (widget->checkState() == Qt::PartiallyChecked) ? std::nullopt : std::optional<float>(widget->isChecked() ? 1.0f : 0.0f);
|
||||
}
|
||||
static void setNullableFloatValue(QCheckBox* widget, std::optional<float> value)
|
||||
{
|
||||
widget->setCheckState(value.has_value() ? ((value.value() != 0.0f) ? Qt::Checked : Qt::Unchecked) : Qt::PartiallyChecked);
|
||||
}
|
||||
|
||||
static QString getStringValue(const QCheckBox* widget) { return widget->isChecked() ? QStringLiteral("1") : QStringLiteral("0"); }
|
||||
static void setStringValue(QCheckBox* widget, const QString& value) { widget->setChecked(value.toInt() != 0); }
|
||||
static void makeNullableString(QCheckBox* widget, const QString& globalValue) { widget->setTristate(true); }
|
||||
static std::optional<QString> getNullableStringValue(const QCheckBox* widget)
|
||||
{
|
||||
return (widget->checkState() == Qt::PartiallyChecked) ?
|
||||
std::nullopt :
|
||||
std::optional<QString>(widget->isChecked() ? QStringLiteral("1") : QStringLiteral("0"));
|
||||
}
|
||||
static void setNullableStringValue(QCheckBox* widget, std::optional<QString> value)
|
||||
{
|
||||
widget->setCheckState(value.has_value() ? ((value->toInt() != 0) ? Qt::Checked : Qt::Unchecked) : Qt::PartiallyChecked);
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
static void connectValueChanged(QCheckBox* widget, F func)
|
||||
|
@ -155,15 +255,27 @@ namespace SettingWidgetBinder
|
|||
{
|
||||
static bool getBoolValue(const QSlider* widget) { return widget->value() > 0; }
|
||||
static void setBoolValue(QSlider* widget, bool value) { widget->setValue(value ? 1 : 0); }
|
||||
static void makeNullableBool(QSlider* widget, bool globalSetting) { widget->setEnabled(false); }
|
||||
static std::optional<bool> getNullableBoolValue(const QSlider* widget) { return getBoolValue(widget); }
|
||||
static void setNullableBoolValue(QSlider* widget, std::optional<bool> value) { setBoolValue(widget, value.value_or(false)); }
|
||||
|
||||
static int getIntValue(const QSlider* widget) { return widget->value(); }
|
||||
static void setIntValue(QSlider* widget, int value) { widget->setValue(value); }
|
||||
static void makeNullableInt(QSlider* widget, int globalValue) { widget->setEnabled(false); }
|
||||
static std::optional<int> getNullableIntValue(const QSlider* widget) { return getIntValue(widget); }
|
||||
static void setNullableIntValue(QSlider* widget, std::optional<int> value) { setIntValue(widget, value.value_or(0)); }
|
||||
|
||||
static float getFloatValue(const QSlider* widget) { return static_cast<float>(widget->value()); }
|
||||
static void setFloatValue(QSlider* widget, float value) { widget->setValue(static_cast<int>(value)); }
|
||||
static void makeNullableFloat(QSlider* widget, float globalValue) { widget->setEnabled(false); }
|
||||
static std::optional<float> getNullableFloatValue(const QSlider* widget) { return getFloatValue(widget); }
|
||||
static void setNullableFloatValue(QSlider* widget, std::optional<float> value) { setFloatValue(widget, value.value_or(0.0f)); }
|
||||
|
||||
static QString getStringValue(const QSlider* widget) { return QString::number(widget->value()); }
|
||||
static void setStringValue(QSlider* widget, const QString& value) { widget->setValue(value.toInt()); }
|
||||
static void makeNullableString(QSlider* widget, const QString& globalValue) { widget->setEnabled(false); }
|
||||
static std::optional<QString> getNullableStringValue(const QSlider* widget) { return getStringValue(widget); }
|
||||
static void setNullableStringValue(QSlider* widget, std::optional<QString> value) { setStringValue(widget, value.value_or(QString())); }
|
||||
|
||||
template <typename F>
|
||||
static void connectValueChanged(QSlider* widget, F func)
|
||||
|
@ -177,15 +289,27 @@ namespace SettingWidgetBinder
|
|||
{
|
||||
static bool getBoolValue(const QSpinBox* widget) { return widget->value() > 0; }
|
||||
static void setBoolValue(QSpinBox* widget, bool value) { widget->setValue(value ? 1 : 0); }
|
||||
static void makeNullableBool(QSpinBox* widget, bool globalSetting) { widget->setEnabled(false); }
|
||||
static std::optional<bool> getNullableBoolValue(const QSpinBox* widget) { return getBoolValue(widget); }
|
||||
static void setNullableBoolValue(QSpinBox* widget, std::optional<bool> value) { setBoolValue(widget, value.value_or(false)); }
|
||||
|
||||
static int getIntValue(const QSpinBox* widget) { return widget->value(); }
|
||||
static void setIntValue(QSpinBox* widget, int value) { widget->setValue(value); }
|
||||
static void makeNullableInt(QSpinBox* widget, int globalValue) { widget->setEnabled(false); }
|
||||
static std::optional<int> getNullableIntValue(const QSpinBox* widget) { return getIntValue(widget); }
|
||||
static void setNullableIntValue(QSpinBox* widget, std::optional<int> value) { setIntValue(widget, value.value_or(0)); }
|
||||
|
||||
static float getFloatValue(const QSpinBox* widget) { return static_cast<float>(widget->value()); }
|
||||
static void setFloatValue(QSpinBox* widget, float value) { widget->setValue(static_cast<int>(value)); }
|
||||
static void makeNullableFloat(QSpinBox* widget, float globalValue) { widget->setEnabled(false); }
|
||||
static std::optional<float> getNullableFloatValue(const QSpinBox* widget) { return getFloatValue(widget); }
|
||||
static void setNullableFloatValue(QSpinBox* widget, std::optional<float> value) { setFloatValue(widget, value.value_or(0.0f)); }
|
||||
|
||||
static QString getStringValue(const QSpinBox* widget) { return QString::number(widget->value()); }
|
||||
static void setStringValue(QSpinBox* widget, const QString& value) { widget->setValue(value.toInt()); }
|
||||
static void makeNullableString(QSpinBox* widget, const QString& globalValue) { widget->setEnabled(false); }
|
||||
static std::optional<QString> getNullableStringValue(const QSpinBox* widget) { return getStringValue(widget); }
|
||||
static void setNullableStringValue(QSpinBox* widget, std::optional<QString> value) { setStringValue(widget, value.value_or(QString())); }
|
||||
|
||||
template <typename F>
|
||||
static void connectValueChanged(QSpinBox* widget, F func)
|
||||
|
@ -199,15 +323,30 @@ namespace SettingWidgetBinder
|
|||
{
|
||||
static bool getBoolValue(const QDoubleSpinBox* widget) { return widget->value() > 0.0; }
|
||||
static void setBoolValue(QDoubleSpinBox* widget, bool value) { widget->setValue(value ? 1.0 : 0.0); }
|
||||
static void makeNullableBool(QDoubleSpinBox* widget, bool globalSetting) { widget->setEnabled(false); }
|
||||
static std::optional<bool> getNullableBoolValue(const QDoubleSpinBox* widget) { return getBoolValue(widget); }
|
||||
static void setNullableBoolValue(QDoubleSpinBox* widget, std::optional<bool> value) { setBoolValue(widget, value.value_or(false)); }
|
||||
|
||||
static int getIntValue(const QDoubleSpinBox* widget) { return static_cast<int>(widget->value()); }
|
||||
static void setIntValue(QDoubleSpinBox* widget, int value) { widget->setValue(static_cast<double>(value)); }
|
||||
static void makeNullableInt(QDoubleSpinBox* widget, int globalValue) { widget->setEnabled(false); }
|
||||
static std::optional<int> getNullableIntValue(const QDoubleSpinBox* widget) { return getIntValue(widget); }
|
||||
static void setNullableIntValue(QDoubleSpinBox* widget, std::optional<int> value) { setIntValue(widget, value.value_or(0)); }
|
||||
|
||||
static float getFloatValue(const QDoubleSpinBox* widget) { return static_cast<float>(widget->value()); }
|
||||
static void setFloatValue(QDoubleSpinBox* widget, float value) { widget->setValue(static_cast<double>(value)); }
|
||||
static void makeNullableFloat(QDoubleSpinBox* widget, float globalValue) { widget->setEnabled(false); }
|
||||
static std::optional<float> getNullableFloatValue(const QDoubleSpinBox* widget) { return getFloatValue(widget); }
|
||||
static void setNullableFloatValue(QDoubleSpinBox* widget, std::optional<float> value) { setFloatValue(widget, value.value_or(0.0f)); }
|
||||
|
||||
static QString getStringValue(const QDoubleSpinBox* widget) { return QString::number(widget->value()); }
|
||||
static void setStringValue(QDoubleSpinBox* widget, const QString& value) { widget->setValue(value.toDouble()); }
|
||||
static void makeNullableString(QDoubleSpinBox* widget, const QString& globalValue) { widget->setEnabled(false); }
|
||||
static std::optional<QString> getNullableStringValue(const QDoubleSpinBox* widget) { return getStringValue(widget); }
|
||||
static void setNullableStringValue(QDoubleSpinBox* widget, std::optional<QString> value)
|
||||
{
|
||||
setStringValue(widget, value.value_or(QString()));
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
static void connectValueChanged(QDoubleSpinBox* widget, F func)
|
||||
|
@ -221,18 +360,27 @@ namespace SettingWidgetBinder
|
|||
{
|
||||
static bool getBoolValue(const QAction* widget) { return widget->isChecked(); }
|
||||
static void setBoolValue(QAction* widget, bool value) { widget->setChecked(value); }
|
||||
static void makeNullableBool(QAction* widget, bool globalSetting) { widget->setEnabled(false); }
|
||||
static std::optional<bool> getNullableBoolValue(const QAction* widget) { return getBoolValue(widget); }
|
||||
static void setNullableBoolValue(QAction* widget, std::optional<bool> value) { setBoolValue(widget, value.value_or(false)); }
|
||||
|
||||
static int getIntValue(const QAction* widget) { return widget->isChecked() ? 1 : 0; }
|
||||
static void setIntValue(QAction* widget, int value) { widget->setChecked(value != 0); }
|
||||
static void makeNullableInt(QAction* widget, int globalValue) { widget->setEnabled(false); }
|
||||
static std::optional<int> getNullableIntValue(const QAction* widget) { return getIntValue(widget); }
|
||||
static void setNullableIntValue(QAction* widget, std::optional<int> value) { setIntValue(widget, value.value_or(0)); }
|
||||
|
||||
static float getFloatValue(const QAction* widget) { return widget->isChecked() ? 1.0f : 0.0f; }
|
||||
static void setFloatValue(QAction* widget, float value) { widget->setChecked(value != 0.0f); }
|
||||
static void makeNullableFloat(QAction* widget, float globalValue) { widget->setEnabled(false); }
|
||||
static std::optional<float> getNullableFloatValue(const QAction* widget) { return getFloatValue(widget); }
|
||||
static void setNullableFloatValue(QAction* widget, std::optional<float> value) { setFloatValue(widget, value.value_or(0.0f)); }
|
||||
|
||||
static QString getStringValue(const QAction* widget)
|
||||
{
|
||||
return widget->isChecked() ? QStringLiteral("1") : QStringLiteral("0");
|
||||
}
|
||||
static QString getStringValue(const QAction* widget) { return widget->isChecked() ? QStringLiteral("1") : QStringLiteral("0"); }
|
||||
static void setStringValue(QAction* widget, const QString& value) { widget->setChecked(value.toInt() != 0); }
|
||||
static void makeNullableString(QAction* widget, const QString& globalValue) { widget->setEnabled(false); }
|
||||
static std::optional<QString> getNullableStringValue(const QAction* widget) { return getStringValue(widget); }
|
||||
static void setNullableStringValue(QAction* widget, std::optional<QString> value) { setStringValue(widget, value.value_or(QString())); }
|
||||
|
||||
template <typename F>
|
||||
static void connectValueChanged(QAction* widget, F func)
|
||||
|
@ -244,12 +392,34 @@ namespace SettingWidgetBinder
|
|||
/// Binds a widget's value to a setting, updating it when the value changes.
|
||||
|
||||
template <typename WidgetType>
|
||||
static void BindWidgetToBoolSetting(WidgetType* widget, std::string section, std::string key, bool default_value)
|
||||
static void BindWidgetToBoolSetting(SettingsInterface* sif, WidgetType* widget, std::string section, std::string key, bool default_value)
|
||||
{
|
||||
using Accessor = SettingAccessor<WidgetType>;
|
||||
|
||||
bool value = QtHost::GetBaseBoolSettingValue(section.c_str(), key.c_str(), default_value);
|
||||
const bool value = QtHost::GetBaseBoolSettingValue(section.c_str(), key.c_str(), default_value);
|
||||
|
||||
if (sif)
|
||||
{
|
||||
Accessor::makeNullableBool(widget, value);
|
||||
|
||||
bool sif_value;
|
||||
if (sif->GetBoolValue(section.c_str(), key.c_str(), &sif_value))
|
||||
Accessor::setNullableBoolValue(widget, sif_value);
|
||||
else
|
||||
Accessor::setNullableBoolValue(widget, std::nullopt);
|
||||
|
||||
Accessor::connectValueChanged(widget, [sif, widget, section, key]() {
|
||||
if (std::optional<bool> new_value = Accessor::getNullableBoolValue(widget); new_value.has_value())
|
||||
sif->SetBoolValue(section.c_str(), key.c_str(), new_value.value());
|
||||
else
|
||||
sif->DeleteValue(section.c_str(), key.c_str());
|
||||
|
||||
sif->Save();
|
||||
g_emu_thread->applySettings();
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
Accessor::setBoolValue(widget, value);
|
||||
|
||||
Accessor::connectValueChanged(widget, [widget, section, key]() {
|
||||
|
@ -258,14 +428,38 @@ namespace SettingWidgetBinder
|
|||
g_emu_thread->applySettings();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
template <typename WidgetType>
|
||||
static void BindWidgetToIntSetting(WidgetType* widget, std::string section, std::string key, int default_value, int option_offset = 0)
|
||||
static void BindWidgetToIntSetting(
|
||||
SettingsInterface* sif, WidgetType* widget, std::string section, std::string key, int default_value, int option_offset = 0)
|
||||
{
|
||||
using Accessor = SettingAccessor<WidgetType>;
|
||||
|
||||
s32 value = QtHost::GetBaseIntSettingValue(section.c_str(), key.c_str(), static_cast<s32>(default_value)) - option_offset;
|
||||
const s32 value = QtHost::GetBaseIntSettingValue(section.c_str(), key.c_str(), static_cast<s32>(default_value)) - option_offset;
|
||||
|
||||
if (sif)
|
||||
{
|
||||
Accessor::makeNullableInt(widget, value);
|
||||
|
||||
int sif_value;
|
||||
if (sif->GetIntValue(section.c_str(), key.c_str(), &sif_value))
|
||||
Accessor::setNullableIntValue(widget, sif_value);
|
||||
else
|
||||
Accessor::setNullableIntValue(widget, std::nullopt);
|
||||
|
||||
Accessor::connectValueChanged(widget, [sif, widget, section, key]() {
|
||||
if (std::optional<int> new_value = Accessor::getNullableIntValue(widget); new_value.has_value())
|
||||
sif->SetIntValue(section.c_str(), key.c_str(), new_value.value());
|
||||
else
|
||||
sif->DeleteValue(section.c_str(), key.c_str());
|
||||
|
||||
sif->Save();
|
||||
g_emu_thread->applySettings();
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
Accessor::setIntValue(widget, static_cast<int>(value));
|
||||
|
||||
Accessor::connectValueChanged(widget, [widget, section, key, option_offset]() {
|
||||
|
@ -274,14 +468,37 @@ namespace SettingWidgetBinder
|
|||
g_emu_thread->applySettings();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
template <typename WidgetType>
|
||||
static void BindWidgetToFloatSetting(WidgetType* widget, std::string section, std::string key, float default_value)
|
||||
static void BindWidgetToFloatSetting(SettingsInterface* sif, WidgetType* widget, std::string section, std::string key, float default_value)
|
||||
{
|
||||
using Accessor = SettingAccessor<WidgetType>;
|
||||
|
||||
float value = QtHost::GetBaseFloatSettingValue(section.c_str(), key.c_str(), default_value);
|
||||
const float value = QtHost::GetBaseFloatSettingValue(section.c_str(), key.c_str(), default_value);
|
||||
|
||||
if (sif)
|
||||
{
|
||||
Accessor::makeNullableFloat(widget, value);
|
||||
|
||||
float sif_value;
|
||||
if (sif->GetFloatValue(section.c_str(), key.c_str(), &sif_value))
|
||||
Accessor::setNullableFloatValue(widget, sif_value);
|
||||
else
|
||||
Accessor::setNullableFloatValue(widget, std::nullopt);
|
||||
|
||||
Accessor::connectValueChanged(widget, [sif, widget, section, key]() {
|
||||
if (std::optional<float> new_value = Accessor::getNullableFloatValue(widget); new_value.has_value())
|
||||
sif->SetFloatValue(section.c_str(), key.c_str(), new_value.value());
|
||||
else
|
||||
sif->DeleteValue(section.c_str(), key.c_str());
|
||||
|
||||
sif->Save();
|
||||
g_emu_thread->applySettings();
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
Accessor::setFloatValue(widget, value);
|
||||
|
||||
Accessor::connectValueChanged(widget, [widget, section, key]() {
|
||||
|
@ -290,15 +507,38 @@ namespace SettingWidgetBinder
|
|||
g_emu_thread->applySettings();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
template <typename WidgetType>
|
||||
static void BindWidgetToNormalizedSetting(WidgetType* widget, std::string section, std::string key, float range,
|
||||
float default_value)
|
||||
static void BindWidgetToNormalizedSetting(
|
||||
SettingsInterface* sif, WidgetType* widget, std::string section, std::string key, float range, float default_value)
|
||||
{
|
||||
using Accessor = SettingAccessor<WidgetType>;
|
||||
|
||||
float value = QtHost::GetBaseFloatSettingValue(section.c_str(), key.c_str(), default_value);
|
||||
const float value = QtHost::GetBaseFloatSettingValue(section.c_str(), key.c_str(), default_value);
|
||||
|
||||
if (sif)
|
||||
{
|
||||
Accessor::makeNullableInt(widget, static_cast<int>(value * range));
|
||||
|
||||
float sif_value;
|
||||
if (sif->GetFloatValue(section.c_str(), key.c_str(), &sif_value))
|
||||
Accessor::setNullableIntValue(widget, static_cast<int>(sif_value * range));
|
||||
else
|
||||
Accessor::setNullableIntValue(widget, std::nullopt);
|
||||
|
||||
Accessor::connectValueChanged(widget, [sif, widget, section, key, range]() {
|
||||
if (std::optional<int> new_value = Accessor::getNullableIntValue(widget); new_value.has_value())
|
||||
sif->SetFloatValue(section.c_str(), key.c_str(), static_cast<float>(new_value.value()) / range);
|
||||
else
|
||||
sif->DeleteValue(section.c_str(), key.c_str());
|
||||
|
||||
sif->Save();
|
||||
g_emu_thread->applySettings();
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
Accessor::setIntValue(widget, static_cast<int>(value * range));
|
||||
|
||||
Accessor::connectValueChanged(widget, [widget, section, key, range]() {
|
||||
|
@ -307,16 +547,39 @@ namespace SettingWidgetBinder
|
|||
g_emu_thread->applySettings();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
template <typename WidgetType>
|
||||
static void BindWidgetToStringSetting(WidgetType* widget, std::string section, std::string key,
|
||||
std::string default_value = std::string())
|
||||
static void BindWidgetToStringSetting(
|
||||
SettingsInterface* sif, WidgetType* widget, std::string section, std::string key, std::string default_value = std::string())
|
||||
{
|
||||
using Accessor = SettingAccessor<WidgetType>;
|
||||
|
||||
std::string value = QtHost::GetBaseStringSettingValue(section.c_str(), key.c_str(), default_value.c_str());
|
||||
const QString value(QString::fromStdString(QtHost::GetBaseStringSettingValue(section.c_str(), key.c_str(), default_value.c_str())));
|
||||
|
||||
Accessor::setStringValue(widget, QString::fromStdString(value));
|
||||
if (sif)
|
||||
{
|
||||
Accessor::makeNullableString(widget, value);
|
||||
|
||||
std::string sif_value;
|
||||
if (sif->GetStringValue(section.c_str(), key.c_str(), &sif_value))
|
||||
Accessor::setNullableStringValue(widget, QString::fromStdString(sif_value));
|
||||
else
|
||||
Accessor::setNullableStringValue(widget, std::nullopt);
|
||||
|
||||
Accessor::connectValueChanged(widget, [sif, widget, section, key]() {
|
||||
if (std::optional<QString> new_value = Accessor::getNullableStringValue(widget); new_value.has_value())
|
||||
sif->SetStringValue(section.c_str(), key.c_str(), new_value->toUtf8().constData());
|
||||
else
|
||||
sif->DeleteValue(section.c_str(), key.c_str());
|
||||
|
||||
sif->Save();
|
||||
g_emu_thread->applySettings();
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
Accessor::setStringValue(widget, value);
|
||||
|
||||
Accessor::connectValueChanged(widget, [widget, section, key]() {
|
||||
const QString new_value = Accessor::getStringValue(widget);
|
||||
|
@ -328,21 +591,55 @@ namespace SettingWidgetBinder
|
|||
g_emu_thread->applySettings();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
template <typename WidgetType, typename DataType>
|
||||
static void BindWidgetToEnumSetting(WidgetType* widget, std::string section, std::string key,
|
||||
std::optional<DataType> (*from_string_function)(const char* str),
|
||||
const char* (*to_string_function)(DataType value), DataType default_value)
|
||||
static void BindWidgetToEnumSetting(SettingsInterface* sif, WidgetType* widget, std::string section, std::string key,
|
||||
std::optional<DataType> (*from_string_function)(const char* str), const char* (*to_string_function)(DataType value), DataType default_value)
|
||||
{
|
||||
using Accessor = SettingAccessor<WidgetType>;
|
||||
using UnderlyingType = std::underlying_type_t<DataType>;
|
||||
|
||||
// TODO: Clean this up?
|
||||
const std::string old_setting_string_value =
|
||||
QtHost::GetBaseStringSettingValue(section.c_str(), key.c_str(), to_string_function(default_value));
|
||||
const std::optional<DataType> old_setting_value = from_string_function(old_setting_string_value.c_str());
|
||||
const std::string value(QtHost::GetBaseStringSettingValue(section.c_str(), key.c_str(), to_string_function(default_value)));
|
||||
const std::optional<DataType> typed_value = from_string_function(value.c_str());
|
||||
|
||||
if (sif)
|
||||
{
|
||||
Accessor::makeNullableInt(widget, typed_value.has_value() ? static_cast<int>(static_cast<UnderlyingType>(typed_value.value())) : 0);
|
||||
|
||||
std::string sif_value;
|
||||
if (sif->GetStringValue(section.c_str(), key.c_str(), &sif_value))
|
||||
{
|
||||
const std::optional<DataType> old_setting_value = from_string_function(sif_value.c_str());
|
||||
if (old_setting_value.has_value())
|
||||
Accessor::setIntValue(widget, static_cast<int>(static_cast<UnderlyingType>(old_setting_value.value())));
|
||||
Accessor::setNullableIntValue(widget, static_cast<int>(static_cast<UnderlyingType>(old_setting_value.value())));
|
||||
else
|
||||
Accessor::setNullableIntValue(widget, std::nullopt);
|
||||
}
|
||||
else
|
||||
{
|
||||
Accessor::setNullableIntValue(widget, std::nullopt);
|
||||
}
|
||||
|
||||
Accessor::connectValueChanged(widget, [sif, widget, section, key]() {
|
||||
if (std::optional<int> new_value = Accessor::getNullableIntValue(widget); new_value.has_value())
|
||||
{
|
||||
const char* string_value = to_string_function(static_cast<DataType>(static_cast<UnderlyingType>(new_value.value())));
|
||||
sif->SetStringValue(section.c_str(), key.c_str(), string_value);
|
||||
}
|
||||
else
|
||||
{
|
||||
sif->DeleteValue(section.c_str(), key.c_str());
|
||||
}
|
||||
|
||||
sif->Save();
|
||||
g_emu_thread->applySettings();
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
if (typed_value.has_value())
|
||||
Accessor::setIntValue(widget, static_cast<int>(static_cast<UnderlyingType>(typed_value.value())));
|
||||
else
|
||||
Accessor::setIntValue(widget, static_cast<int>(static_cast<UnderlyingType>(default_value)));
|
||||
|
||||
|
@ -353,44 +650,76 @@ namespace SettingWidgetBinder
|
|||
g_emu_thread->applySettings();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
template <typename WidgetType, typename DataType>
|
||||
static void BindWidgetToEnumSetting(WidgetType* widget, std::string section, std::string key, const char** enum_names,
|
||||
DataType default_value)
|
||||
static void BindWidgetToEnumSetting(
|
||||
SettingsInterface* sif, WidgetType* widget, std::string section, std::string key, const char** enum_names, DataType default_value)
|
||||
{
|
||||
using Accessor = SettingAccessor<WidgetType>;
|
||||
using UnderlyingType = std::underlying_type_t<DataType>;
|
||||
|
||||
const std::string old_setting_string_value = QtHost::GetBaseStringSettingValue(
|
||||
section.c_str(), key.c_str(), enum_names[static_cast<UnderlyingType>(default_value)]);
|
||||
const std::string value(
|
||||
QtHost::GetBaseStringSettingValue(section.c_str(), key.c_str(), enum_names[static_cast<UnderlyingType>(default_value)]));
|
||||
|
||||
UnderlyingType enum_index = static_cast<UnderlyingType>(default_value);
|
||||
for (UnderlyingType i = 0; enum_names[i] != nullptr; i++)
|
||||
{
|
||||
if (old_setting_string_value == enum_names[i])
|
||||
if (value == enum_names[i])
|
||||
{
|
||||
enum_index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (sif)
|
||||
{
|
||||
Accessor::makeNullableInt(widget, static_cast<int>(enum_index));
|
||||
|
||||
std::string sif_value;
|
||||
std::optional<int> sif_int_value;
|
||||
if (sif->GetStringValue(section.c_str(), key.c_str(), &sif_value))
|
||||
{
|
||||
for (UnderlyingType i = 0; enum_names[i] != nullptr; i++)
|
||||
{
|
||||
if (sif_value == enum_names[i])
|
||||
{
|
||||
sif_int_value = static_cast<int>(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
Accessor::setNullableIntValue(widget, sif_int_value);
|
||||
|
||||
Accessor::connectValueChanged(widget, [sif, widget, section, key, enum_names]() {
|
||||
if (std::optional<int> new_value = Accessor::getNullableIntValue(widget); new_value.has_value())
|
||||
sif->SetStringValue(section.c_str(), key.c_str(), enum_names[new_value.value()]);
|
||||
else
|
||||
sif->DeleteValue(section.c_str(), key.c_str());
|
||||
|
||||
sif->Save();
|
||||
g_emu_thread->applySettings();
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
Accessor::setIntValue(widget, static_cast<int>(enum_index));
|
||||
|
||||
Accessor::connectValueChanged(widget, [widget, section, key, enum_names]() {
|
||||
const UnderlyingType value = static_cast<UnderlyingType>(Accessor::getIntValue(widget));
|
||||
const char* string_value = enum_names[value];
|
||||
QtHost::SetBaseStringSettingValue(section.c_str(), key.c_str(), string_value);
|
||||
QtHost::SetBaseStringSettingValue(section.c_str(), key.c_str(), enum_names[value]);
|
||||
g_emu_thread->applySettings();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
template <typename WidgetType>
|
||||
static void BindWidgetToEnumSetting(WidgetType* widget, std::string section, std::string key, const char** enum_names,
|
||||
static void BindWidgetToEnumSetting(SettingsInterface* sif, WidgetType* widget, std::string section, std::string key, const char** enum_names,
|
||||
const char** enum_values, const char* default_value)
|
||||
{
|
||||
using Accessor = SettingAccessor<WidgetType>;
|
||||
|
||||
const std::string old_setting_string_value =
|
||||
QtHost::GetBaseStringSettingValue(section.c_str(), key.c_str(), default_value);
|
||||
const std::string value = QtHost::GetBaseStringSettingValue(section.c_str(), key.c_str(), default_value);
|
||||
|
||||
for (int i = 0; enum_names[i] != nullptr; i++)
|
||||
widget->addItem(QString::fromUtf8(enum_names[i]));
|
||||
|
@ -398,12 +727,44 @@ namespace SettingWidgetBinder
|
|||
int enum_index = -1;
|
||||
for (int i = 0; enum_values[i] != nullptr; i++)
|
||||
{
|
||||
if (old_setting_string_value == enum_values[i])
|
||||
if (value == enum_values[i])
|
||||
{
|
||||
enum_index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (sif)
|
||||
{
|
||||
Accessor::makeNullableInt(widget, enum_index);
|
||||
|
||||
std::string sif_value;
|
||||
std::optional<int> sif_int_value;
|
||||
if (sif->GetStringValue(section.c_str(), key.c_str(), &sif_value))
|
||||
{
|
||||
for (int i = 0; enum_values[i] != nullptr; i++)
|
||||
{
|
||||
if (value == enum_values[i])
|
||||
{
|
||||
sif_int_value = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
Accessor::setNullableIntValue(widget, sif_int_value);
|
||||
|
||||
Accessor::connectValueChanged(widget, [sif, widget, section, key, enum_names]() {
|
||||
if (std::optional<int> new_value = Accessor::getNullableIntValue(widget); new_value.has_value())
|
||||
sif->SetStringValue(section.c_str(), key.c_str(), enum_names[new_value.value()]);
|
||||
else
|
||||
sif->DeleteValue(section.c_str(), key.c_str());
|
||||
|
||||
sif->Save();
|
||||
g_emu_thread->applySettings();
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
if (enum_index >= 0)
|
||||
Accessor::setIntValue(widget, enum_index);
|
||||
|
||||
|
@ -413,5 +774,6 @@ namespace SettingWidgetBinder
|
|||
g_emu_thread->applySettings();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace SettingWidgetBinder
|
||||
|
|
|
@ -24,27 +24,29 @@
|
|||
#include "SettingWidgetBinder.h"
|
||||
#include "SettingsDialog.h"
|
||||
|
||||
AdvancedSystemSettingsWidget::AdvancedSystemSettingsWidget(QWidget* parent, SettingsDialog* dialog)
|
||||
AdvancedSystemSettingsWidget::AdvancedSystemSettingsWidget(SettingsDialog* dialog, QWidget* parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
SettingsInterface* sif = dialog->getSettingsInterface();
|
||||
|
||||
m_ui.setupUi(this);
|
||||
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.eeRecompiler, "EmuCore/CPU/Recompiler", "EnableEE", true);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.eeCache, "EmuCore/CPU/Recompiler", "EnableEECache", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.eeINTCSpinDetection, "EmuCore/Speedhacks", "IntcStat", true);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.eeWaitLoopDetection, "EmuCore/Speedhacks", "WaitLoop", true);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.eeRecompiler, "EmuCore/CPU/Recompiler", "EnableEE", true);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.eeCache, "EmuCore/CPU/Recompiler", "EnableEECache", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.eeINTCSpinDetection, "EmuCore/Speedhacks", "IntcStat", true);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.eeWaitLoopDetection, "EmuCore/Speedhacks", "WaitLoop", true);
|
||||
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.vu0Recompiler, "EmuCore/CPU/Recompiler", "EnableVU0", true);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.vu1Recompiler, "EmuCore/CPU/Recompiler", "EnableVU1", true);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.vuFlagHack, "EmuCore/Speedhacks", "vuFlagHack", true);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.vu0Recompiler, "EmuCore/CPU/Recompiler", "EnableVU0", true);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.vu1Recompiler, "EmuCore/CPU/Recompiler", "EnableVU1", true);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.vuFlagHack, "EmuCore/Speedhacks", "vuFlagHack", true);
|
||||
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.iopRecompiler, "EmuCore/CPU/Recompiler", "EnableIOP", true);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.iopRecompiler, "EmuCore/CPU/Recompiler", "EnableIOP", true);
|
||||
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.gameFixes, "", "EnableGameFixes", true);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.patches, "EmuCore", "EnablePatches", true);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.gameFixes, "", "EnableGameFixes", true);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.patches, "EmuCore", "EnablePatches", true);
|
||||
|
||||
SettingWidgetBinder::BindWidgetToFloatSetting(m_ui.ntscFrameRate, "EmuCore/GS", "FramerateNTSC", 59.94f);
|
||||
SettingWidgetBinder::BindWidgetToFloatSetting(m_ui.palFrameRate, "EmuCore/GS", "FrameratePAL", 50.00f);
|
||||
SettingWidgetBinder::BindWidgetToFloatSetting(sif, m_ui.ntscFrameRate, "EmuCore/GS", "FramerateNTSC", 59.94f);
|
||||
SettingWidgetBinder::BindWidgetToFloatSetting(sif, m_ui.palFrameRate, "EmuCore/GS", "FrameratePAL", 50.00f);
|
||||
}
|
||||
|
||||
AdvancedSystemSettingsWidget::~AdvancedSystemSettingsWidget() = default;
|
||||
|
|
|
@ -26,7 +26,7 @@ class AdvancedSystemSettingsWidget : public QWidget
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
AdvancedSystemSettingsWidget(QWidget* parent, SettingsDialog* dialog);
|
||||
AdvancedSystemSettingsWidget(SettingsDialog* dialog, QWidget* parent);
|
||||
~AdvancedSystemSettingsWidget();
|
||||
|
||||
private:
|
||||
|
|
|
@ -26,12 +26,14 @@
|
|||
#include "SettingWidgetBinder.h"
|
||||
#include "SettingsDialog.h"
|
||||
|
||||
BIOSSettingsWidget::BIOSSettingsWidget(QWidget* parent, SettingsDialog* dialog)
|
||||
BIOSSettingsWidget::BIOSSettingsWidget(SettingsDialog* dialog, QWidget* parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
SettingsInterface* sif = dialog->getSettingsInterface();
|
||||
|
||||
m_ui.setupUi(this);
|
||||
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.fastBoot, "EmuCore", "EnableFastBoot", true);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.fastBoot, "EmuCore", "EnableFastBoot", true);
|
||||
|
||||
dialog->registerWidgetHelp(m_ui.fastBoot, tr("Fast Boot"), tr("Unchecked"),
|
||||
tr("Patches the BIOS to skip the console's boot animation."));
|
||||
|
|
|
@ -42,7 +42,7 @@ class BIOSSettingsWidget : public QWidget
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
BIOSSettingsWidget(QWidget* parent, SettingsDialog* dialog);
|
||||
BIOSSettingsWidget(SettingsDialog* dialog, QWidget* parent);
|
||||
~BIOSSettingsWidget();
|
||||
|
||||
private Q_SLOTS:
|
||||
|
|
|
@ -38,7 +38,7 @@ ControllerBindingWidget::ControllerBindingWidget(QWidget* parent, ControllerSett
|
|||
populateControllerTypes();
|
||||
onTypeChanged();
|
||||
|
||||
SettingWidgetBinder::BindWidgetToStringSetting(m_ui.controllerType, m_config_section, "Type", "None");
|
||||
SettingWidgetBinder::BindWidgetToStringSetting(nullptr, m_ui.controllerType, m_config_section, "Type", "None");
|
||||
connect(m_ui.controllerType, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
|
||||
&ControllerBindingWidget::onTypeChanged);
|
||||
}
|
||||
|
|
|
@ -26,9 +26,9 @@ ControllerGlobalSettingsWidget::ControllerGlobalSettingsWidget(QWidget* parent,
|
|||
{
|
||||
m_ui.setupUi(this);
|
||||
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.enableSDLSource, "InputSources", "SDL", true);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.enableSDLEnhancedMode, "InputSources", "SDLControllerEnhancedMode", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.enableXInputSource, "InputSources", "XInput", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(nullptr, m_ui.enableSDLSource, "InputSources", "SDL", true);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(nullptr, m_ui.enableSDLEnhancedMode, "InputSources", "SDLControllerEnhancedMode", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(nullptr, m_ui.enableXInputSource, "InputSources", "XInput", false);
|
||||
|
||||
connect(m_ui.enableSDLSource, &QCheckBox::stateChanged, this, &ControllerGlobalSettingsWidget::updateSDLOptionsEnabled);
|
||||
updateSDLOptionsEnabled();
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
#include "PrecompiledHeader.h"
|
||||
|
||||
#include <QtWidgets/QInputDialog>
|
||||
#include <QtWidgets/QMessageBox>
|
||||
#include <limits>
|
||||
|
||||
|
@ -25,92 +26,45 @@
|
|||
|
||||
static constexpr u32 DEFAULT_FRAME_LATENCY = 2;
|
||||
|
||||
static void FillComboBoxWithEmulationSpeeds(QComboBox* cb)
|
||||
{
|
||||
// cb->addItem(qApp->translate("GeneralSettingsWidget", "Custom"),;// TODO: Make use of getInteger to get manual overrides from users
|
||||
// for speed choice along with dropdown presets.
|
||||
cb->addItem(qApp->translate("GeneralSettingsWidget", "Unlimited"), QVariant(0.0f));
|
||||
|
||||
static const int speeds[] = {1, 10, 25, 50, 75, 90, 100, 110,
|
||||
120, 150, 175, 200, 300, 400, 500, 1000};
|
||||
for (const int speed : speeds)
|
||||
{
|
||||
cb->addItem(qApp->translate("EmulationSettingsWidget", "%1% [%2 FPS (NTSC) / %3 FPS (PAL)]")
|
||||
.arg(speed)
|
||||
.arg((60 * speed) / 100)
|
||||
.arg((50 * speed) / 100),
|
||||
QVariant(static_cast<float>(speed) / 100.0f));
|
||||
}
|
||||
}
|
||||
|
||||
EmulationSettingsWidget::EmulationSettingsWidget(QWidget* parent, SettingsDialog* dialog)
|
||||
EmulationSettingsWidget::EmulationSettingsWidget(SettingsDialog* dialog, QWidget* parent)
|
||||
: QWidget(parent)
|
||||
, m_dialog(dialog)
|
||||
{
|
||||
SettingsInterface* sif = dialog->getSettingsInterface();
|
||||
|
||||
m_ui.setupUi(this);
|
||||
|
||||
FillComboBoxWithEmulationSpeeds(m_ui.normalSpeed);
|
||||
if (const int index =
|
||||
m_ui.normalSpeed->findData(QVariant(QtHost::GetBaseFloatSettingValue("Framerate", "NominalScalar", 1.0f)));
|
||||
index >= 0)
|
||||
{
|
||||
m_ui.normalSpeed->setCurrentIndex(index);
|
||||
}
|
||||
connect(m_ui.normalSpeed, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
|
||||
&EmulationSettingsWidget::onNormalSpeedIndexChanged);
|
||||
FillComboBoxWithEmulationSpeeds(m_ui.fastForwardSpeed);
|
||||
initializeSpeedCombo(m_ui.normalSpeed, "Framerate", "NominalScalar", 1.0f);
|
||||
initializeSpeedCombo(m_ui.fastForwardSpeed, "Framerate", "TurboScalar", 2.0f);
|
||||
initializeSpeedCombo(m_ui.slowMotionSpeed, "Framerate", "SlomoScalar", 0.5f);
|
||||
|
||||
if (const int index =
|
||||
m_ui.fastForwardSpeed->findData(QVariant(QtHost::GetBaseFloatSettingValue("Framerate", "TurboScalar", 2.0f)));
|
||||
index >= 0)
|
||||
{
|
||||
m_ui.fastForwardSpeed->setCurrentIndex(index);
|
||||
}
|
||||
connect(m_ui.fastForwardSpeed, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
|
||||
&EmulationSettingsWidget::onFastForwardSpeedIndexChanged);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.speedLimiter, "EmuCore/GS", "FrameLimitEnable", true);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.maxFrameLatency, "EmuCore/GS", "VsyncQueueSize", DEFAULT_FRAME_LATENCY);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.syncToHostRefreshRate, "EmuCore/GS", "SyncToHostRefreshRate", false);
|
||||
connect(m_ui.optimalFramePacing, &QCheckBox::stateChanged, this, &EmulationSettingsWidget::onOptimalFramePacingChanged);
|
||||
m_ui.optimalFramePacing->setTristate(dialog->isPerGameSettings());
|
||||
|
||||
FillComboBoxWithEmulationSpeeds(m_ui.slowMotionSpeed);
|
||||
if (const int index =
|
||||
m_ui.slowMotionSpeed->findData(QVariant(QtHost::GetBaseFloatSettingValue("Framerate", "SlomoScalar", 0.5f)));
|
||||
index >= 0)
|
||||
{
|
||||
m_ui.slowMotionSpeed->setCurrentIndex(index);
|
||||
}
|
||||
connect(m_ui.slowMotionSpeed, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
|
||||
&EmulationSettingsWidget::onSlowMotionSpeedIndexChanged);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.cheats, "EmuCore", "EnableCheats", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.widescreenPatches, "EmuCore", "EnableWideScreenPatches", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.perGameSettings, "EmuCore", "EnablePerGameSettings", true);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.hostFilesystem, "EmuCore", "HostFs", false);
|
||||
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.speedLimiter, "EmuCore/GS", "FrameLimitEnable", true);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(m_ui.maxFrameLatency, "EmuCore/GS", "VsyncQueueSize", DEFAULT_FRAME_LATENCY);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.syncToHostRefreshRate, "EmuCore/GS", "SyncToHostRefreshRate",
|
||||
false);
|
||||
connect(m_ui.optimalFramePacing, &QCheckBox::toggled, this, &EmulationSettingsWidget::onOptimalFramePacingChanged);
|
||||
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.cheats, "EmuCore", "EnableCheats", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.widescreenPatches, "EmuCore", "EnableWideScreenPatches", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.perGameSettings, "EmuCore", "EnablePerGameSettings", true);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.hostFilesystem, "EmuCore", "HostFs", false);
|
||||
|
||||
dialog->registerWidgetHelp(
|
||||
m_ui.normalSpeed, tr("Normal Speed"), "100%",
|
||||
dialog->registerWidgetHelp(m_ui.normalSpeed, tr("Normal Speed"), "100%",
|
||||
tr("Sets the target emulation speed. It is not guaranteed that this speed will be reached, "
|
||||
"and if not, the emulator will run as fast as it can manage."));
|
||||
dialog->registerWidgetHelp(
|
||||
m_ui.fastForwardSpeed, tr("Fast Forward Speed"), tr("User Preference"),
|
||||
dialog->registerWidgetHelp(m_ui.fastForwardSpeed, tr("Fast Forward Speed"), tr("User Preference"),
|
||||
tr("Sets the fast forward speed. This speed will be used when the fast forward hotkey is pressed/toggled."));
|
||||
dialog->registerWidgetHelp(
|
||||
m_ui.slowMotionSpeed, tr("Slow Motion Speed"), tr("User Preference"),
|
||||
dialog->registerWidgetHelp(m_ui.slowMotionSpeed, tr("Slow Motion Speed"), tr("User Preference"),
|
||||
tr("Sets the slow motion speed. This speed will be used when the slow motion hotkey is pressed/toggled."));
|
||||
|
||||
dialog->registerWidgetHelp(
|
||||
m_ui.syncToHostRefreshRate, tr("Sync To Host Refresh Rate"), tr("Unchecked"),
|
||||
dialog->registerWidgetHelp(m_ui.syncToHostRefreshRate, tr("Sync To Host Refresh Rate"), tr("Unchecked"),
|
||||
tr("Adjusts the emulation speed so the console's refresh rate matches the host's refresh rate when both VSync and "
|
||||
"Audio Resampling settings are enabled. This results in the smoothest animations possible, at the cost of "
|
||||
"potentially increasing the emulation speed by less than 1%. Sync To Host Refresh Rate will not take effect if "
|
||||
"the console's refresh rate is too far from the host's refresh rate. Users with variable refresh rate displays "
|
||||
"should disable this option."));
|
||||
dialog->registerWidgetHelp(m_ui.cheats, tr("Enable Cheats"), tr("Unchecked"),
|
||||
tr("Automatically loads and applies cheats on game start."));
|
||||
dialog->registerWidgetHelp(
|
||||
m_ui.perGameSettings, tr("Enable Per-Game Settings"), tr("Checked"),
|
||||
dialog->registerWidgetHelp(m_ui.cheats, tr("Enable Cheats"), tr("Unchecked"), tr("Automatically loads and applies cheats on game start."));
|
||||
dialog->registerWidgetHelp(m_ui.perGameSettings, tr("Enable Per-Game Settings"), tr("Checked"),
|
||||
tr("When enabled, per-game settings will be applied, and incompatible enhancements will be disabled. You should "
|
||||
"leave this option enabled except when testing enhancements with incompatible games."));
|
||||
|
||||
|
@ -119,49 +73,122 @@ EmulationSettingsWidget::EmulationSettingsWidget(QWidget* parent, SettingsDialog
|
|||
|
||||
EmulationSettingsWidget::~EmulationSettingsWidget() = default;
|
||||
|
||||
void EmulationSettingsWidget::onNormalSpeedIndexChanged(int index)
|
||||
void EmulationSettingsWidget::initializeSpeedCombo(QComboBox* cb, const char* section, const char* key, float default_value)
|
||||
{
|
||||
bool okay;
|
||||
const float value = m_ui.normalSpeed->currentData().toFloat(&okay);
|
||||
QtHost::SetBaseFloatSettingValue("Framerate", "NominalScalar", okay ? value : 1.0f);
|
||||
g_emu_thread->applySettings();
|
||||
float value = QtHost::GetBaseFloatSettingValue(section, key, default_value);
|
||||
if (m_dialog->isPerGameSettings())
|
||||
{
|
||||
cb->addItem(tr("Use Global Setting [%1%]").arg(value * 100.0f, 0, 'f', 0));
|
||||
if (!m_dialog->getSettingsInterface()->GetFloatValue(key, section, &value))
|
||||
{
|
||||
// set to something without data
|
||||
value = -1.0f;
|
||||
cb->setCurrentIndex(0);
|
||||
}
|
||||
}
|
||||
|
||||
void EmulationSettingsWidget::onFastForwardSpeedIndexChanged(int index)
|
||||
static const int speeds[] = {1, 10, 25, 50, 75, 90, 100, 110, 120, 150, 175, 200, 300, 400, 500, 1000};
|
||||
for (const int speed : speeds)
|
||||
{
|
||||
bool okay;
|
||||
const float value = m_ui.fastForwardSpeed->currentData().toFloat(&okay);
|
||||
QtHost::SetBaseFloatSettingValue("Framerate", "TurboScalar", okay ? value : 1.0f);
|
||||
g_emu_thread->applySettings();
|
||||
cb->addItem(tr("%1% [%2 FPS (NTSC) / %3 FPS (PAL)]")
|
||||
.arg(speed)
|
||||
.arg((60 * speed) / 100)
|
||||
.arg((50 * speed) / 100),
|
||||
QVariant(static_cast<float>(speed) / 100.0f));
|
||||
}
|
||||
|
||||
void EmulationSettingsWidget::onSlowMotionSpeedIndexChanged(int index)
|
||||
cb->addItem(tr("Unlimited"), QVariant(0.0f));
|
||||
|
||||
const int custom_index = cb->count();
|
||||
cb->addItem(tr("Custom"));
|
||||
|
||||
if (const int index = cb->findData(QVariant(value)); index >= 0)
|
||||
{
|
||||
bool okay;
|
||||
const float value = m_ui.slowMotionSpeed->currentData().toFloat(&okay);
|
||||
QtHost::SetBaseFloatSettingValue("Framerate", "SlomoScalar", okay ? value : 1.0f);
|
||||
g_emu_thread->applySettings();
|
||||
cb->setCurrentIndex(index);
|
||||
}
|
||||
else if (value > 0.0f)
|
||||
{
|
||||
cb->setItemText(custom_index, tr("Custom [%1% / %2 FPS (NTSC) / %3 FPS (PAL)]")
|
||||
.arg(value * 100)
|
||||
.arg(60 * value)
|
||||
.arg(50 * value));
|
||||
cb->setCurrentIndex(custom_index);
|
||||
}
|
||||
|
||||
void EmulationSettingsWidget::onOptimalFramePacingChanged(bool checked)
|
||||
connect(cb, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
|
||||
[this, cb, section, key](int index) { handleSpeedComboChange(cb, section, key); });
|
||||
}
|
||||
|
||||
void EmulationSettingsWidget::handleSpeedComboChange(QComboBox* cb, const char* section, const char* key)
|
||||
{
|
||||
const int custom_index = cb->count() - 1;
|
||||
const int current_index = cb->currentIndex();
|
||||
|
||||
std::optional<float> new_value;
|
||||
if (current_index == custom_index)
|
||||
{
|
||||
bool ok = false;
|
||||
const double custom_value = QInputDialog::getDouble(
|
||||
QtUtils::GetRootWidget(this), tr("Custom Speed"), tr("Enter Custom Speed"), cb->currentData().toFloat(), 0.0f, 5000.0f, 1, &ok);
|
||||
if (!ok)
|
||||
{
|
||||
// we need to set back to the old value
|
||||
float value = m_dialog->getEffectiveFloatValue(section, key, 1.0f);
|
||||
|
||||
QSignalBlocker sb(cb);
|
||||
if (m_dialog->isPerGameSettings() && !m_dialog->getSettingsInterface()->GetFloatValue(section, key, &value))
|
||||
cb->setCurrentIndex(0);
|
||||
else if (const int index = cb->findData(QVariant(value)); index >= 0)
|
||||
cb->setCurrentIndex(index);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
cb->setItemText(custom_index, tr("Custom [%1% / %2 FPS (NTSC) / %3 FPS (PAL)]")
|
||||
.arg(custom_value)
|
||||
.arg((60 * custom_value) / 100)
|
||||
.arg((50 * custom_value) / 100));
|
||||
new_value = static_cast<float>(custom_value / 100.0);
|
||||
}
|
||||
else if (current_index > 0 || !m_dialog->isPerGameSettings())
|
||||
{
|
||||
new_value = cb->currentData().toFloat();
|
||||
}
|
||||
|
||||
m_dialog->setFloatSettingValue(section, key, new_value);
|
||||
}
|
||||
|
||||
void EmulationSettingsWidget::onOptimalFramePacingChanged()
|
||||
{
|
||||
const QSignalBlocker sb(m_ui.maxFrameLatency);
|
||||
m_ui.maxFrameLatency->setValue(DEFAULT_FRAME_LATENCY);
|
||||
m_ui.maxFrameLatency->setEnabled(!checked);
|
||||
|
||||
QtHost::SetBaseIntSettingValue("EmuCore/GS", "VsyncQueueSize", checked ? 0 : DEFAULT_FRAME_LATENCY);
|
||||
g_emu_thread->applySettings();
|
||||
std::optional<int> value;
|
||||
if (m_ui.optimalFramePacing->checkState() != Qt::PartiallyChecked)
|
||||
value = m_ui.optimalFramePacing->isChecked() ? 0 : DEFAULT_FRAME_LATENCY;
|
||||
|
||||
m_ui.maxFrameLatency->setValue(DEFAULT_FRAME_LATENCY);
|
||||
m_ui.maxFrameLatency->setEnabled(!m_dialog->isPerGameSettings() && !m_ui.optimalFramePacing->isChecked());
|
||||
|
||||
m_dialog->setIntSettingValue("EmuCore/GS", "VsyncQueueSize", value);
|
||||
}
|
||||
|
||||
void EmulationSettingsWidget::updateOptimalFramePacing()
|
||||
{
|
||||
const int value = QtHost::GetBaseIntSettingValue("EmuCore/GS", "VsyncQueueSize", DEFAULT_FRAME_LATENCY);
|
||||
const bool optimal = (value == 0);
|
||||
|
||||
const QSignalBlocker sb(m_ui.optimalFramePacing);
|
||||
m_ui.optimalFramePacing->setChecked(optimal);
|
||||
|
||||
const QSignalBlocker sb2(m_ui.maxFrameLatency);
|
||||
|
||||
int value = m_dialog->getEffectiveIntValue("EmuCore/GS", "VsyncQueueSize", DEFAULT_FRAME_LATENCY);
|
||||
bool optimal = (value == 0);
|
||||
if (m_dialog->isPerGameSettings() && !m_dialog->getSettingsInterface()->GetIntValue("EmuCore/GS", "VsyncQueueSize", &value))
|
||||
{
|
||||
m_ui.optimalFramePacing->setCheckState(Qt::PartiallyChecked);
|
||||
m_ui.maxFrameLatency->setEnabled(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_ui.optimalFramePacing->setChecked(optimal);
|
||||
m_ui.maxFrameLatency->setEnabled(!optimal);
|
||||
}
|
||||
|
||||
m_ui.maxFrameLatency->setValue(optimal ? DEFAULT_FRAME_LATENCY : value);
|
||||
}
|
||||
|
|
|
@ -26,17 +26,18 @@ class EmulationSettingsWidget : public QWidget
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
EmulationSettingsWidget(QWidget* parent, SettingsDialog* dialog);
|
||||
EmulationSettingsWidget(SettingsDialog* dialog, QWidget* parent);
|
||||
~EmulationSettingsWidget();
|
||||
|
||||
private Q_SLOTS:
|
||||
void onNormalSpeedIndexChanged(int index);
|
||||
void onFastForwardSpeedIndexChanged(int index);
|
||||
void onSlowMotionSpeedIndexChanged(int index);
|
||||
void onOptimalFramePacingChanged(bool checked);
|
||||
void onOptimalFramePacingChanged();
|
||||
|
||||
private:
|
||||
void initializeSpeedCombo(QComboBox* cb, const char* section, const char* key, float default_value);
|
||||
void handleSpeedComboChange(QComboBox* cb, const char* section, const char* key);
|
||||
void updateOptimalFramePacing();
|
||||
|
||||
SettingsDialog* m_dialog;
|
||||
|
||||
Ui::EmulationSettingsWidget m_ui;
|
||||
};
|
||||
|
|
|
@ -24,27 +24,29 @@
|
|||
#include "SettingWidgetBinder.h"
|
||||
#include "SettingsDialog.h"
|
||||
|
||||
GameFixSettingsWidget::GameFixSettingsWidget(QWidget* parent, SettingsDialog* dialog)
|
||||
GameFixSettingsWidget::GameFixSettingsWidget(SettingsDialog* dialog, QWidget* parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
SettingsInterface* sif = dialog->getSettingsInterface();
|
||||
|
||||
m_ui.setupUi(this);
|
||||
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.FpuMulHack, "EmuCore/Gamefixes", "FpuMulHack", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.FpuNegDivHack, "EmuCore/Gamefixes", "FpuNegDivHack", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.GoemonTlbHack, "EmuCore/Gamefixes", "GoemonTlbHack", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.SoftwareRendererFMVHack, "EmuCore/Gamefixes", "SoftwareRendererFMVHack", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.SkipMPEGHack, "EmuCore/Gamefixes", "SkipMPEGHack", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.OPHFlagHack, "EmuCore/Gamefixes", "OPHFlagHack", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.EETimingHack, "EmuCore/Gamefixes", "EETimingHack", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.DMABusyHack, "EmuCore/Gamefixes", "DMABusyHack", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.GIFFIFOHack, "EmuCore/Gamefixes", "GIFFIFOHack", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.VIFFIFOHack, "EmuCore/Gamefixes", "VIFFIFOHack", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.VIF1StallHack, "EmuCore/Gamefixes", "VIF1StallHack", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.VuAddSubHack, "EmuCore/Gamefixes", "VuAddSubHack", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.IbitHack, "EmuCore/Gamefixes", "IbitHack", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.VUKickstartHack, "EmuCore/Gamefixes", "VUKickstartHack", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.VUOverflowHack, "EmuCore/Gamefixes", "VUOverflowHack", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.XgKickHack, "EmuCore/Gamefixes", "XgKickHack", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.FpuMulHack, "EmuCore/Gamefixes", "FpuMulHack", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.FpuNegDivHack, "EmuCore/Gamefixes", "FpuNegDivHack", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.GoemonTlbHack, "EmuCore/Gamefixes", "GoemonTlbHack", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.SoftwareRendererFMVHack, "EmuCore/Gamefixes", "SoftwareRendererFMVHack", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.SkipMPEGHack, "EmuCore/Gamefixes", "SkipMPEGHack", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.OPHFlagHack, "EmuCore/Gamefixes", "OPHFlagHack", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.EETimingHack, "EmuCore/Gamefixes", "EETimingHack", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.DMABusyHack, "EmuCore/Gamefixes", "DMABusyHack", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.GIFFIFOHack, "EmuCore/Gamefixes", "GIFFIFOHack", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.VIFFIFOHack, "EmuCore/Gamefixes", "VIFFIFOHack", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.VIF1StallHack, "EmuCore/Gamefixes", "VIF1StallHack", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.VuAddSubHack, "EmuCore/Gamefixes", "VuAddSubHack", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.IbitHack, "EmuCore/Gamefixes", "IbitHack", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.VUKickstartHack, "EmuCore/Gamefixes", "VUKickstartHack", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.VUOverflowHack, "EmuCore/Gamefixes", "VUOverflowHack", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.XgKickHack, "EmuCore/Gamefixes", "XgKickHack", false);
|
||||
}
|
||||
|
||||
GameFixSettingsWidget::~GameFixSettingsWidget() = default;
|
||||
|
|
|
@ -26,7 +26,7 @@ class GameFixSettingsWidget : public QWidget
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
GameFixSettingsWidget(QWidget* parent, SettingsDialog* dialog);
|
||||
GameFixSettingsWidget(SettingsDialog* dialog, QWidget* parent);
|
||||
~GameFixSettingsWidget();
|
||||
|
||||
private:
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
#include "QtHost.h"
|
||||
#include "QtUtils.h"
|
||||
|
||||
GameListSettingsWidget::GameListSettingsWidget(QWidget* parent, SettingsDialog* dialog)
|
||||
GameListSettingsWidget::GameListSettingsWidget(SettingsDialog* dialog, QWidget* parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
m_ui.setupUi(this);
|
||||
|
|
|
@ -28,7 +28,7 @@ class GameListSettingsWidget : public QWidget
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
GameListSettingsWidget(QWidget* parent, SettingsDialog* dialog);
|
||||
GameListSettingsWidget(SettingsDialog* dialog, QWidget* parent);
|
||||
~GameListSettingsWidget();
|
||||
|
||||
bool addExcludedPath(const std::string& path);
|
||||
|
|
|
@ -54,69 +54,65 @@ static constexpr RendererInfo s_renderer_info[] = {
|
|||
};
|
||||
|
||||
static const char* s_anisotropic_filtering_entries[] = {QT_TRANSLATE_NOOP("GraphicsSettingsWidget", "Off (Default)"),
|
||||
QT_TRANSLATE_NOOP("GraphicsSettingsWidget", "2x"),
|
||||
QT_TRANSLATE_NOOP("GraphicsSettingsWidget", "4x"),
|
||||
QT_TRANSLATE_NOOP("GraphicsSettingsWidget", "8x"),
|
||||
QT_TRANSLATE_NOOP("GraphicsSettingsWidget", "16x"),
|
||||
nullptr};
|
||||
QT_TRANSLATE_NOOP("GraphicsSettingsWidget", "2x"), QT_TRANSLATE_NOOP("GraphicsSettingsWidget", "4x"),
|
||||
QT_TRANSLATE_NOOP("GraphicsSettingsWidget", "8x"), QT_TRANSLATE_NOOP("GraphicsSettingsWidget", "16x"), nullptr};
|
||||
static const char* s_anisotropic_filtering_values[] = {"1", "2", "4", "8", "16", nullptr};
|
||||
|
||||
static constexpr int DEFAULT_INTERLACE_MODE = 7;
|
||||
|
||||
GraphicsSettingsWidget::GraphicsSettingsWidget(QWidget* parent, SettingsDialog* dialog)
|
||||
GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsDialog* dialog, QWidget* parent)
|
||||
: QWidget(parent)
|
||||
, m_dialog(dialog)
|
||||
{
|
||||
SettingsInterface* sif = dialog->getSettingsInterface();
|
||||
|
||||
m_ui.setupUi(this);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Global Settings
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
SettingWidgetBinder::BindWidgetToStringSetting(m_ui.adapter, "EmuCore/GS", "Adapter");
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(m_ui.vsync, "EmuCore/GS", "VsyncEnable", 0);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.enableHWFixes, "EmuCore/GS", "UserHacks", false);
|
||||
SettingWidgetBinder::BindWidgetToStringSetting(sif, m_ui.adapter, "EmuCore/GS", "Adapter");
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.vsync, "EmuCore/GS", "VsyncEnable", 0);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.enableHWFixes, "EmuCore/GS", "UserHacks", false);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Game Display Settings
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
SettingWidgetBinder::BindWidgetToEnumSetting(m_ui.aspectRatio, "EmuCore/GS", "AspectRatio",
|
||||
Pcsx2Config::GSOptions::AspectRatioNames, AspectRatioType::R4_3);
|
||||
SettingWidgetBinder::BindWidgetToEnumSetting(m_ui.fmvAspectRatio, "EmuCore/GS", "FMVAspectRatioSwitch",
|
||||
Pcsx2Config::GSOptions::FMVAspectRatioSwitchNames,
|
||||
FMVAspectRatioSwitchType::Off);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(m_ui.interlacing, "EmuCore/GS", "interlace", DEFAULT_INTERLACE_MODE);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.bilinearFiltering, "EmuCore/GS", "LinearPresent", true);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.integerScaling, "EmuCore/GS", "IntegerScaling", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.internalResolutionScreenshots, "EmuCore/GS",
|
||||
"InternalResolutionScreenshots", false);
|
||||
SettingWidgetBinder::BindWidgetToFloatSetting(m_ui.zoom, "EmuCore/GS", "Zoom", 100.0f);
|
||||
SettingWidgetBinder::BindWidgetToFloatSetting(m_ui.stretchY, "EmuCore/GS", "StretchY", 100.0f);
|
||||
SettingWidgetBinder::BindWidgetToFloatSetting(m_ui.offsetX, "EmuCore/GS", "OffsetX", 0.0f);
|
||||
SettingWidgetBinder::BindWidgetToFloatSetting(m_ui.offsetY, "EmuCore/GS", "OffsetY", 0.0f);
|
||||
SettingWidgetBinder::BindWidgetToEnumSetting(
|
||||
sif, m_ui.aspectRatio, "EmuCore/GS", "AspectRatio", Pcsx2Config::GSOptions::AspectRatioNames, AspectRatioType::R4_3);
|
||||
SettingWidgetBinder::BindWidgetToEnumSetting(sif, m_ui.fmvAspectRatio, "EmuCore/GS", "FMVAspectRatioSwitch",
|
||||
Pcsx2Config::GSOptions::FMVAspectRatioSwitchNames, FMVAspectRatioSwitchType::Off);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.interlacing, "EmuCore/GS", "interlace", DEFAULT_INTERLACE_MODE);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.bilinearFiltering, "EmuCore/GS", "LinearPresent", true);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.integerScaling, "EmuCore/GS", "IntegerScaling", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.internalResolutionScreenshots, "EmuCore/GS", "InternalResolutionScreenshots", false);
|
||||
SettingWidgetBinder::BindWidgetToFloatSetting(sif, m_ui.zoom, "EmuCore/GS", "Zoom", 100.0f);
|
||||
SettingWidgetBinder::BindWidgetToFloatSetting(sif, m_ui.stretchY, "EmuCore/GS", "StretchY", 100.0f);
|
||||
SettingWidgetBinder::BindWidgetToFloatSetting(sif, m_ui.offsetX, "EmuCore/GS", "OffsetX", 0.0f);
|
||||
SettingWidgetBinder::BindWidgetToFloatSetting(sif, m_ui.offsetY, "EmuCore/GS", "OffsetY", 0.0f);
|
||||
|
||||
connect(m_ui.integerScaling, &QCheckBox::stateChanged, this, &GraphicsSettingsWidget::onIntegerScalingChanged);
|
||||
onIntegerScalingChanged();
|
||||
|
||||
connect(m_ui.fullscreenModes, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
|
||||
&GraphicsSettingsWidget::onFullscreenModeChanged);
|
||||
connect(m_ui.fullscreenModes, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &GraphicsSettingsWidget::onFullscreenModeChanged);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// OSD Settings
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
SettingWidgetBinder::BindWidgetToFloatSetting(m_ui.osdScale, "EmuCore/GS", "OsdScale", 100.0f);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.osdShowMessages, "EmuCore/GS", "OsdShowMessages", true);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.osdShowSpeed, "EmuCore/GS", "OsdShowSpeed", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.osdShowFPS, "EmuCore/GS", "OsdShowFPS", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.osdShowCPU, "EmuCore/GS", "OsdShowCPU", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.osdShowResolution, "EmuCore/GS", "OsdShowResolution", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.osdShowGSStats, "EmuCore/GS", "OsdShowGSStats", false);
|
||||
SettingWidgetBinder::BindWidgetToFloatSetting(sif, m_ui.osdScale, "EmuCore/GS", "OsdScale", 100.0f);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.osdShowMessages, "EmuCore/GS", "OsdShowMessages", true);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.osdShowSpeed, "EmuCore/GS", "OsdShowSpeed", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.osdShowFPS, "EmuCore/GS", "OsdShowFPS", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.osdShowCPU, "EmuCore/GS", "OsdShowCPU", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.osdShowResolution, "EmuCore/GS", "OsdShowResolution", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.osdShowGSStats, "EmuCore/GS", "OsdShowGSStats", false);
|
||||
|
||||
dialog->registerWidgetHelp(m_ui.osdShowMessages, tr("Show OSD Messages"), tr("Checked"),
|
||||
tr("Shows on-screen-display messages when events occur such as save states being "
|
||||
"created/loaded, screenshots being taken, etc."));
|
||||
dialog->registerWidgetHelp(m_ui.osdShowFPS, tr("Show Game Frame Rate"), tr("Unchecked"),
|
||||
tr("Shows the internal frame rate of the game in the top-right corner of the display."));
|
||||
dialog->registerWidgetHelp(
|
||||
m_ui.osdShowSpeed, tr("Show Emulation Speed"), tr("Unchecked"),
|
||||
dialog->registerWidgetHelp(m_ui.osdShowSpeed, tr("Show Emulation Speed"), tr("Unchecked"),
|
||||
tr("Shows the current emulation speed of the system in the top-right corner of the display as a percentage."));
|
||||
dialog->registerWidgetHelp(m_ui.osdShowResolution, tr("Show Resolution"), tr("Unchecked"),
|
||||
tr("Shows the resolution of the game in the top-right corner of the display."));
|
||||
|
@ -124,86 +120,91 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(QWidget* parent, SettingsDialog*
|
|||
//////////////////////////////////////////////////////////////////////////
|
||||
// HW Settings
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(m_ui.upscaleMultiplier, "EmuCore/GS", "upscale_multiplier", 1);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(m_ui.textureFiltering, "EmuCore/GS", "filter",
|
||||
static_cast<int>(BiFiltering::PS2));
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(m_ui.trilinearFiltering, "EmuCore/GS", "UserHacks_TriFilter",
|
||||
static_cast<int>(TriFiltering::Off));
|
||||
SettingWidgetBinder::BindWidgetToEnumSetting(m_ui.anisotropicFiltering, "EmuCore/GS", "MaxAnisotropy",
|
||||
s_anisotropic_filtering_entries, s_anisotropic_filtering_values, "1");
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(m_ui.dithering, "EmuCore/GS", "dithering_ps2", 2);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(m_ui.mipmapping, "EmuCore/GS", "mipmap_hw",
|
||||
static_cast<int>(HWMipmapLevel::Automatic), -1);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(m_ui.crcFixLevel, "EmuCore/GS", "crc_hack_level",
|
||||
static_cast<int>(CRCHackLevel::Automatic), -1);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(m_ui.blending, "EmuCore/GS", "accurate_blending_unit",
|
||||
static_cast<int>(AccBlendLevel::Basic));
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.accurateDATE, "EmuCore/GS", "accurate_date", true);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.conservativeBufferAllocation, "EmuCore/GS",
|
||||
"conservative_framebuffer", true);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.gpuPaletteConversion, "EmuCore/GS", "paltex", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.preloadTexture, "EmuCore/GS", "preload_texture", false);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.upscaleMultiplier, "EmuCore/GS", "upscale_multiplier", 1);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.textureFiltering, "EmuCore/GS", "filter", static_cast<int>(BiFiltering::PS2));
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(
|
||||
sif, m_ui.trilinearFiltering, "EmuCore/GS", "UserHacks_TriFilter", static_cast<int>(TriFiltering::Off));
|
||||
SettingWidgetBinder::BindWidgetToEnumSetting(
|
||||
sif, m_ui.anisotropicFiltering, "EmuCore/GS", "MaxAnisotropy", s_anisotropic_filtering_entries, s_anisotropic_filtering_values, "1");
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.dithering, "EmuCore/GS", "dithering_ps2", 2);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.mipmapping, "EmuCore/GS", "mipmap_hw", static_cast<int>(HWMipmapLevel::Automatic), -1);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.crcFixLevel, "EmuCore/GS", "crc_hack_level", static_cast<int>(CRCHackLevel::Automatic), -1);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.blending, "EmuCore/GS", "accurate_blending_unit", static_cast<int>(AccBlendLevel::Basic));
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.accurateDATE, "EmuCore/GS", "accurate_date", true);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.conservativeBufferAllocation, "EmuCore/GS", "conservative_framebuffer", true);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.gpuPaletteConversion, "EmuCore/GS", "paltex", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.preloadTexture, "EmuCore/GS", "preload_texture", false);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// HW Renderer Fixes
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(m_ui.halfScreenFix, "EmuCore/GS", "UserHacks_Half_Bottom_Override", -1,
|
||||
-1);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(m_ui.skipDrawRangeStart, "EmuCore/GS", "UserHacks_SkipDraw", 0);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(m_ui.skipDrawRangeCount, "EmuCore/GS", "UserHacks_SkipDraw_Offset", 0);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.hwAutoFlush, "EmuCore/GS", "UserHacks_AutoFlush", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.frameBufferConversion, "EmuCore/GS", "UserHacks_CPU_FB_Conversion",
|
||||
false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.disableDepthEmulation, "EmuCore/GS",
|
||||
"UserHacks_DisableDepthSupport", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.memoryWrapping, "EmuCore/GS", "wrap_gs_mem", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.disableSafeFeatures, "EmuCore/GS",
|
||||
"UserHacks_Disable_Safe_Features", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.preloadFrameData, "EmuCore/GS", "preload_frame_with_gs_data",
|
||||
false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.fastTextureInvalidation, "EmuCore/GS",
|
||||
"UserHacks_DisablePartialInvalidation", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.textureInsideRt, "EmuCore/GS",
|
||||
"UserHacks_TextureInsideRt", false);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.halfScreenFix, "EmuCore/GS", "UserHacks_Half_Bottom_Override", -1, -1);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.skipDrawRangeStart, "EmuCore/GS", "UserHacks_SkipDraw", 0);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.skipDrawRangeCount, "EmuCore/GS", "UserHacks_SkipDraw_Offset", 0);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.hwAutoFlush, "EmuCore/GS", "UserHacks_AutoFlush", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.frameBufferConversion, "EmuCore/GS", "UserHacks_CPU_FB_Conversion", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.disableDepthEmulation, "EmuCore/GS", "UserHacks_DisableDepthSupport", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.memoryWrapping, "EmuCore/GS", "wrap_gs_mem", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.disableSafeFeatures, "EmuCore/GS", "UserHacks_Disable_Safe_Features", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.preloadFrameData, "EmuCore/GS", "preload_frame_with_gs_data", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.fastTextureInvalidation, "EmuCore/GS", "UserHacks_DisablePartialInvalidation", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.textureInsideRt, "EmuCore/GS", "UserHacks_TextureInsideRt", false);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// HW Upscaling Fixes
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(m_ui.halfPixelOffset, "EmuCore/GS", "UserHacks_HalfPixelOffset", 0);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(m_ui.roundSprite, "EmuCore/GS", "UserHacks_RoundSprite", 0);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(m_ui.textureOffsetX, "EmuCore/GS", "UserHacks_TCOffsetX", 0);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(m_ui.textureOffsetY, "EmuCore/GS", "UserHacks_TCOffsetY", 0);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.alignSprite, "EmuCore/GS", "UserHacks_align_sprite_X", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.mergeSprite, "EmuCore/GS", "UserHacks_merge_pp_sprite", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.wildHack, "EmuCore/GS", "UserHacks_WildHack", false);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.halfPixelOffset, "EmuCore/GS", "UserHacks_HalfPixelOffset", 0);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.roundSprite, "EmuCore/GS", "UserHacks_RoundSprite", 0);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.textureOffsetX, "EmuCore/GS", "UserHacks_TCOffsetX", 0);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.textureOffsetY, "EmuCore/GS", "UserHacks_TCOffsetY", 0);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.alignSprite, "EmuCore/GS", "UserHacks_align_sprite_X", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.mergeSprite, "EmuCore/GS", "UserHacks_merge_pp_sprite", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.wildHack, "EmuCore/GS", "UserHacks_WildHack", false);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Advanced Settings
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.useBlitSwapChain, "EmuCore/GS", "UseBlitSwapChain", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.useDebugDevice, "EmuCore/GS", "UseDebugDevice", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.useBlitSwapChain, "EmuCore/GS", "UseBlitSwapChain", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.useDebugDevice, "EmuCore/GS", "UseDebugDevice", false);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// SW Settings
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(m_ui.extraSWThreads, "EmuCore/GS", "extrathreads", 2);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.swAutoFlush, "EmuCore/GS", "autoflush_sw", true);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.swAA1, "EmuCore/GS", "aa1", true);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.swMipmap, "EmuCore/GS", "mipmap", true);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.extraSWThreads, "EmuCore/GS", "extrathreads", 2);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.swAutoFlush, "EmuCore/GS", "autoflush_sw", true);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.swAA1, "EmuCore/GS", "aa1", true);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.swMipmap, "EmuCore/GS", "mipmap", true);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Non-trivial settings
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
const GSRendererType current_renderer = static_cast<GSRendererType>(
|
||||
QtHost::GetBaseIntSettingValue("EmuCore/GS", "Renderer", static_cast<int>(GSRendererType::Auto)));
|
||||
const int renderer = m_dialog->getEffectiveIntValue("EmuCore/GS", "Renderer", static_cast<int>(GSRendererType::Auto));
|
||||
for (const RendererInfo& ri : s_renderer_info)
|
||||
{
|
||||
m_ui.renderer->addItem(qApp->translate("GraphicsSettingsWidget", ri.name));
|
||||
if (ri.type == current_renderer)
|
||||
if (renderer == static_cast<int>(ri.type))
|
||||
m_ui.renderer->setCurrentIndex(m_ui.renderer->count() - 1);
|
||||
}
|
||||
connect(m_ui.renderer, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
|
||||
&GraphicsSettingsWidget::onRendererChanged);
|
||||
|
||||
// per-game override for renderer is slightly annoying, since we need to populate the global setting field
|
||||
if (sif)
|
||||
{
|
||||
QString global_renderer_name;
|
||||
for (const RendererInfo& ri : s_renderer_info)
|
||||
{
|
||||
if (renderer == static_cast<int>(ri.type))
|
||||
global_renderer_name = qApp->translate("GraphicsSettingsWidget", ri.name);
|
||||
}
|
||||
m_ui.renderer->insertItem(0, tr("Use Global Setting [%1]").arg(global_renderer_name));
|
||||
|
||||
int override_renderer;
|
||||
if (sif->GetIntValue("EmuCore/GS", "Renderer", &override_renderer))
|
||||
m_ui.renderer->setCurrentIndex(override_renderer + 1);
|
||||
else
|
||||
m_ui.renderer->setCurrentIndex(0);
|
||||
}
|
||||
|
||||
connect(m_ui.renderer, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &GraphicsSettingsWidget::onRendererChanged);
|
||||
connect(m_ui.enableHWFixes, &QCheckBox::stateChanged, this, &GraphicsSettingsWidget::onEnableHardwareFixesChanged);
|
||||
updateRendererDependentOptions();
|
||||
|
||||
|
@ -217,33 +218,69 @@ GraphicsSettingsWidget::~GraphicsSettingsWidget() = default;
|
|||
|
||||
void GraphicsSettingsWidget::onRendererChanged(int index)
|
||||
{
|
||||
QtHost::SetBaseIntSettingValue("EmuCore/GS", "Renderer", static_cast<int>(s_renderer_info[index].type));
|
||||
if (m_dialog->isPerGameSettings())
|
||||
{
|
||||
if (index > 0)
|
||||
m_dialog->setIntSettingValue("EmuCore/GS", "Renderer", static_cast<int>(s_renderer_info[index - 1].type));
|
||||
else
|
||||
m_dialog->setIntSettingValue("EmuCore/GS", "Renderer", std::nullopt);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_dialog->setIntSettingValue("EmuCore/GS", "Renderer", static_cast<int>(s_renderer_info[index].type));
|
||||
}
|
||||
|
||||
g_emu_thread->applySettings();
|
||||
updateRendererDependentOptions();
|
||||
}
|
||||
|
||||
void GraphicsSettingsWidget::onAdapterChanged(int index)
|
||||
{
|
||||
if (index == 0)
|
||||
QtHost::RemoveBaseSettingValue("EmuCore/GS", "Adapter");
|
||||
const int first_adapter = m_dialog->isPerGameSettings() ? 2 : 1;
|
||||
|
||||
if (index >= first_adapter)
|
||||
m_dialog->setStringSettingValue("EmuCore/GS", "Adapter", m_ui.adapter->currentText().toUtf8().constData());
|
||||
else if (index > 0 && m_dialog->isPerGameSettings())
|
||||
m_dialog->setStringSettingValue("EmuCore/GS", "Adapter", "");
|
||||
else
|
||||
QtHost::SetBaseStringSettingValue("EmuCore/GS", "Adapter", m_ui.adapter->currentText().toUtf8().constData());
|
||||
m_dialog->setStringSettingValue("EmuCore/GS", "Adapter", std::nullopt);
|
||||
|
||||
g_emu_thread->applySettings();
|
||||
}
|
||||
|
||||
void GraphicsSettingsWidget::onFullscreenModeChanged(int index)
|
||||
{
|
||||
const int first_mode = m_dialog->isPerGameSettings() ? 2 : 1;
|
||||
|
||||
if (index >= first_mode)
|
||||
m_dialog->setStringSettingValue("EmuCore/GS", "FullscreenMode", m_ui.fullscreenModes->currentText().toUtf8().constData());
|
||||
else if (index > 0 && m_dialog->isPerGameSettings())
|
||||
m_dialog->setStringSettingValue("EmuCore/GS", "FullscreenMode", "");
|
||||
else
|
||||
m_dialog->setStringSettingValue("EmuCore/GS", "FullscreenMode", std::nullopt);
|
||||
|
||||
g_emu_thread->applySettings();
|
||||
}
|
||||
|
||||
void GraphicsSettingsWidget::onIntegerScalingChanged() { m_ui.bilinearFiltering->setEnabled(!m_ui.integerScaling->isChecked()); }
|
||||
|
||||
void GraphicsSettingsWidget::onEnableHardwareFixesChanged()
|
||||
{
|
||||
const bool enabled = m_ui.enableHWFixes->isChecked();
|
||||
const bool enabled = (m_ui.enableHWFixes->checkState() == Qt::Checked);
|
||||
m_ui.hardwareRendererGroup->setTabEnabled(2, enabled);
|
||||
m_ui.hardwareRendererGroup->setTabEnabled(3, enabled);
|
||||
}
|
||||
|
||||
GSRendererType GraphicsSettingsWidget::getEffectiveRenderer() const
|
||||
{
|
||||
const GSRendererType type =
|
||||
static_cast<GSRendererType>(m_dialog->getEffectiveIntValue("EmuCore/GS", "Renderer", static_cast<int>(GSRendererType::Auto)));
|
||||
return (type == GSRendererType::Auto) ? GSUtil::GetPreferredRenderer() : type;
|
||||
}
|
||||
|
||||
void GraphicsSettingsWidget::updateRendererDependentOptions()
|
||||
{
|
||||
const int index = m_ui.renderer->currentIndex();
|
||||
GSRendererType type = s_renderer_info[index].type;
|
||||
if (type == GSRendererType::Auto)
|
||||
type = GSUtil::GetPreferredRenderer();
|
||||
const GSRendererType type = getEffectiveRenderer();
|
||||
|
||||
#ifdef _WIN32
|
||||
const bool is_dx11 = (type == GSRendererType::DX11 || type == GSRendererType::SW);
|
||||
|
@ -253,9 +290,7 @@ void GraphicsSettingsWidget::updateRendererDependentOptions()
|
|||
|
||||
const bool is_hardware = (type == GSRendererType::DX11 || type == GSRendererType::OGL || type == GSRendererType::VK);
|
||||
const bool is_software = (type == GSRendererType::SW);
|
||||
const int current_tab = m_hardware_renderer_visible ?
|
||||
m_ui.hardwareRendererGroup->currentIndex() :
|
||||
m_ui.softwareRendererGroup->currentIndex();
|
||||
const int current_tab = m_hardware_renderer_visible ? m_ui.hardwareRendererGroup->currentIndex() : m_ui.softwareRendererGroup->currentIndex();
|
||||
|
||||
// move advanced tab to the correct parent
|
||||
static constexpr std::array<const char*, 3> move_tab_names = {{"Display", "On-Screen Display", "Advanced"}};
|
||||
|
@ -334,11 +369,26 @@ void GraphicsSettingsWidget::updateRendererDependentOptions()
|
|||
|
||||
// fill+select adapters
|
||||
{
|
||||
const std::string current_adapter = QtHost::GetBaseStringSettingValue("EmuCore/GS", "Adapter", "");
|
||||
QSignalBlocker sb(m_ui.adapter);
|
||||
|
||||
std::string current_adapter = QtHost::GetBaseStringSettingValue("EmuCore/GS", "Adapter", "");
|
||||
m_ui.adapter->clear();
|
||||
m_ui.adapter->setEnabled(!modes.adapter_names.empty());
|
||||
m_ui.adapter->addItem(tr("(Default)"));
|
||||
m_ui.adapter->setCurrentIndex(0);
|
||||
|
||||
if (m_dialog->isPerGameSettings())
|
||||
{
|
||||
m_ui.adapter->insertItem(
|
||||
0, tr("Use Global Setting [%1]").arg(current_adapter.empty() ? tr("(Default)") : QString::fromStdString(current_adapter)));
|
||||
if (!m_dialog->getSettingsInterface()->GetStringValue("EmuCore/GS", "Adapter", ¤t_adapter))
|
||||
{
|
||||
// clear the adapter so we don't set it to the global value
|
||||
current_adapter.clear();
|
||||
m_ui.adapter->setCurrentIndex(0);
|
||||
}
|
||||
}
|
||||
|
||||
for (const std::string& adapter : modes.adapter_names)
|
||||
{
|
||||
m_ui.adapter->addItem(QString::fromStdString(adapter));
|
||||
|
@ -351,12 +401,22 @@ void GraphicsSettingsWidget::updateRendererDependentOptions()
|
|||
{
|
||||
QSignalBlocker sb(m_ui.fullscreenModes);
|
||||
|
||||
const std::string current_mode(QtHost::GetBaseStringSettingValue("EmuCore/GS", "FullscreenMode", ""));
|
||||
std::string current_mode(QtHost::GetBaseStringSettingValue("EmuCore/GS", "FullscreenMode", ""));
|
||||
m_ui.fullscreenModes->clear();
|
||||
m_ui.fullscreenModes->addItem(tr("Borderless Fullscreen"));
|
||||
if (current_mode.empty())
|
||||
m_ui.fullscreenModes->setCurrentIndex(0);
|
||||
|
||||
if (m_dialog->isPerGameSettings())
|
||||
{
|
||||
m_ui.fullscreenModes->insertItem(
|
||||
0, tr("Use Global Setting [%1]").arg(current_mode.empty() ? tr("(Default)") : QString::fromStdString(current_mode)));
|
||||
if (!m_dialog->getSettingsInterface()->GetStringValue("EmuCore/GS", "FullscreenMode", ¤t_mode))
|
||||
{
|
||||
current_mode.clear();
|
||||
m_ui.fullscreenModes->setCurrentIndex(0);
|
||||
}
|
||||
}
|
||||
|
||||
for (const std::string& fs_mode : modes.fullscreen_modes)
|
||||
{
|
||||
m_ui.fullscreenModes->addItem(QString::fromStdString(fs_mode));
|
||||
|
@ -368,23 +428,3 @@ void GraphicsSettingsWidget::updateRendererDependentOptions()
|
|||
m_ui.enableHWFixes->setEnabled(is_hardware);
|
||||
onEnableHardwareFixesChanged();
|
||||
}
|
||||
|
||||
void GraphicsSettingsWidget::onIntegerScalingChanged()
|
||||
{
|
||||
m_ui.bilinearFiltering->setEnabled(!m_ui.integerScaling->isChecked());
|
||||
}
|
||||
|
||||
void GraphicsSettingsWidget::onFullscreenModeChanged(int index)
|
||||
{
|
||||
if (index == 0)
|
||||
{
|
||||
QtHost::RemoveBaseSettingValue("EmuCore/GS", "FullscreenMode");
|
||||
}
|
||||
else
|
||||
{
|
||||
QtHost::SetBaseStringSettingValue("EmuCore/GS", "FullscreenMode",
|
||||
m_ui.fullscreenModes->currentText().toUtf8().constData());
|
||||
}
|
||||
|
||||
g_emu_thread->applySettings();
|
||||
}
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
|
||||
#include "ui_GraphicsSettingsWidget.h"
|
||||
|
||||
enum class GSRendererType : s8;
|
||||
|
||||
class SettingsDialog;
|
||||
|
||||
class GraphicsSettingsWidget : public QWidget
|
||||
|
@ -26,7 +28,7 @@ class GraphicsSettingsWidget : public QWidget
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
GraphicsSettingsWidget(QWidget* parent, SettingsDialog* dialog);
|
||||
GraphicsSettingsWidget(SettingsDialog* dialog, QWidget* parent);
|
||||
~GraphicsSettingsWidget();
|
||||
|
||||
void updateRendererDependentOptions();
|
||||
|
@ -42,6 +44,10 @@ private Q_SLOTS:
|
|||
void onFullscreenModeChanged(int index);
|
||||
|
||||
private:
|
||||
GSRendererType getEffectiveRenderer() const;
|
||||
|
||||
SettingsDialog* m_dialog;
|
||||
|
||||
Ui::GraphicsSettingsWidget m_ui;
|
||||
|
||||
bool m_hardware_renderer_visible = true;
|
||||
|
|
|
@ -27,25 +27,27 @@ static const char* THEME_NAMES[] = {QT_TRANSLATE_NOOP("InterfaceSettingsWidget",
|
|||
|
||||
static const char* THEME_VALUES[] = {"", "fusion", "darkfusion", "darkfusionblue", nullptr};
|
||||
|
||||
InterfaceSettingsWidget::InterfaceSettingsWidget(QWidget* parent, SettingsDialog* dialog)
|
||||
InterfaceSettingsWidget::InterfaceSettingsWidget(SettingsDialog* dialog, QWidget* parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
SettingsInterface* sif = dialog->getSettingsInterface();
|
||||
|
||||
m_ui.setupUi(this);
|
||||
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.inhibitScreensaver, "UI", "InhibitScreensaver", true);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.discordPresence, "UI", "DiscordPresence", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.confirmPowerOff, "UI", "ConfirmPowerOff", true);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.saveStateOnExit, "EmuCore", "AutoStateLoadSave", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.pauseOnStart, "UI", "StartPaused", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.pauseOnFocusLoss, "UI", "PauseOnFocusLoss", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.inhibitScreensaver, "UI", "InhibitScreensaver", true);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.discordPresence, "UI", "DiscordPresence", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.confirmPowerOff, "UI", "ConfirmPowerOff", true);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.saveStateOnExit, "EmuCore", "AutoStateLoadSave", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.pauseOnStart, "UI", "StartPaused", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.pauseOnFocusLoss, "UI", "PauseOnFocusLoss", false);
|
||||
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.startFullscreen, "UI", "StartFullscreen", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.doubleClickTogglesFullscreen, "UI", "DoubleClickTogglesFullscreen",
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.startFullscreen, "UI", "StartFullscreen", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.doubleClickTogglesFullscreen, "UI", "DoubleClickTogglesFullscreen",
|
||||
true);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.hideMouseCursor, "UI", "HideMouseCursor", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.renderToMainWindow, "UI", "RenderToMainWindow", true);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.hideMouseCursor, "UI", "HideMouseCursor", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.renderToMainWindow, "UI", "RenderToMainWindow", true);
|
||||
|
||||
SettingWidgetBinder::BindWidgetToEnumSetting(m_ui.theme, "UI", "Theme", THEME_NAMES, THEME_VALUES,
|
||||
SettingWidgetBinder::BindWidgetToEnumSetting(sif, m_ui.theme, "UI", "Theme", THEME_NAMES, THEME_VALUES,
|
||||
MainWindow::DEFAULT_THEME_NAME);
|
||||
connect(m_ui.theme, QOverload<int>::of(&QComboBox::currentIndexChanged), [this]() { emit themeChanged(); });
|
||||
|
||||
|
@ -57,7 +59,7 @@ InterfaceSettingsWidget::InterfaceSettingsWidget(QWidget* parent, SettingsDialog
|
|||
tr("Shows the game you are currently playing as part of your profile in Discord."));
|
||||
if (true)
|
||||
{
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.autoUpdateEnabled, "AutoUpdater", "CheckAtStartup", true);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.autoUpdateEnabled, "AutoUpdater", "CheckAtStartup", true);
|
||||
dialog->registerWidgetHelp(m_ui.autoUpdateEnabled, tr("Enable Automatic Update Check"), tr("Checked"),
|
||||
tr("Automatically checks for updates to the program on startup. Updates can be deferred "
|
||||
"until later or skipped entirely."));
|
||||
|
|
|
@ -26,7 +26,7 @@ class InterfaceSettingsWidget : public QWidget
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
InterfaceSettingsWidget(QWidget* parent, SettingsDialog* dialog);
|
||||
InterfaceSettingsWidget(SettingsDialog* dialog, QWidget* parent);
|
||||
~InterfaceSettingsWidget();
|
||||
|
||||
Q_SIGNALS:
|
||||
|
|
|
@ -15,7 +15,14 @@
|
|||
|
||||
#include "PrecompiledHeader.h"
|
||||
|
||||
#include "common/FileSystem.h"
|
||||
#include "common/StringUtil.h"
|
||||
#include "pcsx2/Frontend/GameList.h"
|
||||
#include "pcsx2/Frontend/INISettingsInterface.h"
|
||||
|
||||
#include "EmuThread.h"
|
||||
#include "QtHost.h"
|
||||
#include "QtUtils.h"
|
||||
#include "SettingsDialog.h"
|
||||
|
||||
#include "AdvancedSystemSettingsWidget.h"
|
||||
|
@ -31,33 +38,82 @@
|
|||
#include <QtWidgets/QMessageBox>
|
||||
#include <QtWidgets/QTextEdit>
|
||||
|
||||
static constexpr char DEFAULT_SETTING_HELP_TEXT[] = "";
|
||||
static QList<SettingsDialog*> s_open_game_properties_dialogs;
|
||||
|
||||
SettingsDialog::SettingsDialog(QWidget* parent /* = nullptr */)
|
||||
SettingsDialog::SettingsDialog(QWidget* parent)
|
||||
: QDialog(parent)
|
||||
, m_game_crc(0)
|
||||
{
|
||||
m_ui.setupUi(this);
|
||||
setCategoryHelpTexts();
|
||||
setupUi(nullptr);
|
||||
}
|
||||
|
||||
SettingsDialog::SettingsDialog(std::unique_ptr<SettingsInterface> sif, const GameList::Entry* game, u32 game_crc)
|
||||
: QDialog()
|
||||
, m_sif(std::move(sif))
|
||||
, m_game_crc(game_crc)
|
||||
{
|
||||
setupUi(game);
|
||||
|
||||
s_open_game_properties_dialogs.push_back(this);
|
||||
}
|
||||
|
||||
void SettingsDialog::setupUi(const GameList::Entry* game)
|
||||
{
|
||||
const bool show_advanced_settings = true;
|
||||
|
||||
m_ui.setupUi(this);
|
||||
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
||||
|
||||
m_interface_settings = new InterfaceSettingsWidget(m_ui.settingsContainer, this);
|
||||
m_game_list_settings = new GameListSettingsWidget(m_ui.settingsContainer, this);
|
||||
m_bios_settings = new BIOSSettingsWidget(m_ui.settingsContainer, this);
|
||||
m_emulation_settings = new EmulationSettingsWidget(m_ui.settingsContainer, this);
|
||||
m_system_settings = new SystemSettingsWidget(m_ui.settingsContainer, this);
|
||||
m_advanced_system_settings = new AdvancedSystemSettingsWidget(m_ui.settingsContainer, this);
|
||||
m_game_fix_settings_widget = new GameFixSettingsWidget(m_ui.settingsContainer, this);
|
||||
m_graphics_settings = new GraphicsSettingsWidget(m_ui.settingsContainer, this);
|
||||
// We don't include interface/game list/bios settings from per-game settings.
|
||||
if (!isPerGameSettings())
|
||||
{
|
||||
addWidget(m_interface_settings = new InterfaceSettingsWidget(this, m_ui.settingsContainer), tr("Interface"),
|
||||
QStringLiteral("settings-3-line"),
|
||||
tr("<strong>Interface Settings</strong><hr>These options control how the software looks and behaves.<br><br>Mouse over an option for "
|
||||
"additional information."));
|
||||
addWidget(m_game_list_settings = new GameListSettingsWidget(this, m_ui.settingsContainer), tr("Game List"),
|
||||
QStringLiteral("folder-settings-line"),
|
||||
tr("<strong>Game List Settings</strong><hr>The list above shows the directories which will be searched by PCSX2 to populate the game "
|
||||
"list. Search directories can be added, removed, and switched to recursive/non-recursive."));
|
||||
addWidget(m_bios_settings = new BIOSSettingsWidget(this, m_ui.settingsContainer), tr("BIOS"), QStringLiteral("hard-drive-2-line"),
|
||||
tr("<strong>BIOS Settings</strong><hr>"));
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: Summary page.
|
||||
|
||||
m_ui.settingsContainer->insertWidget(static_cast<int>(Category::InterfaceSettings), m_interface_settings);
|
||||
m_ui.settingsContainer->insertWidget(static_cast<int>(Category::GameListSettings), m_game_list_settings);
|
||||
m_ui.settingsContainer->insertWidget(static_cast<int>(Category::BIOSSettings), m_bios_settings);
|
||||
m_ui.settingsContainer->insertWidget(static_cast<int>(Category::EmulationSettings), m_emulation_settings);
|
||||
m_ui.settingsContainer->insertWidget(static_cast<int>(Category::SystemSettings), m_system_settings);
|
||||
m_ui.settingsContainer->insertWidget(static_cast<int>(Category::AdvancedSystemSettings), m_advanced_system_settings);
|
||||
m_ui.settingsContainer->insertWidget(static_cast<int>(Category::GameFixSettings), m_game_fix_settings_widget);
|
||||
m_ui.settingsContainer->insertWidget(static_cast<int>(Category::GraphicsSettings), m_graphics_settings);
|
||||
// remove the preset buttons. but we might want to enable these in the future.
|
||||
m_ui.restoreDefaultsButton->setVisible(false);
|
||||
m_ui.settingsPreset->setVisible(false);
|
||||
}
|
||||
|
||||
// Common to both per-game and global settings.
|
||||
addWidget(m_emulation_settings = new EmulationSettingsWidget(this, m_ui.settingsContainer), tr("Emulation"), QStringLiteral("dashboard-line"),
|
||||
tr("<strong>Emulation Settings</strong><hr>"));
|
||||
addWidget(m_system_settings = new SystemSettingsWidget(this, m_ui.settingsContainer), tr("System"), QStringLiteral("artboard-2-line"),
|
||||
tr("<strong>System Settings</strong><hr>These options determine the configuration of the simulated console.<br><br>Mouse over an option for "
|
||||
"additional information."));
|
||||
|
||||
if (show_advanced_settings)
|
||||
{
|
||||
addWidget(m_advanced_system_settings = new AdvancedSystemSettingsWidget(this, m_ui.settingsContainer), tr("Advanced System"),
|
||||
QStringLiteral("artboard-2-line"), tr("<strong>Advanced System Settings</strong><hr>"));
|
||||
|
||||
// Only show the game fixes for per-game settings, there's really no reason to be setting them globally.
|
||||
if (isPerGameSettings())
|
||||
{
|
||||
addWidget(m_game_fix_settings_widget = new GameFixSettingsWidget(this, m_ui.settingsContainer), tr("Game Fix"),
|
||||
QStringLiteral("close-line"), tr("<strong>Game Fix Settings</strong><hr>"));
|
||||
}
|
||||
}
|
||||
|
||||
addWidget(m_graphics_settings = new GraphicsSettingsWidget(this, m_ui.settingsContainer), tr("Graphics"), QStringLiteral("brush-line"),
|
||||
tr("<strong>Graphics Settings</strong><hr>"));
|
||||
addWidget(new QWidget(m_ui.settingsContainer), tr("Audio"), QStringLiteral("volume-up-line"),
|
||||
tr("<strong>Audio Settings</strong><hr>These options control the audio output of the console. Mouse over an option for additional "
|
||||
"information."));
|
||||
addWidget(
|
||||
new QWidget(m_ui.settingsContainer), tr("Memory Cards"), QStringLiteral("sd-card-line"), tr("<strong>Memory Card Settings</strong><hr>"));
|
||||
|
||||
m_ui.settingsCategory->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
|
||||
m_ui.settingsCategory->setCurrentRow(0);
|
||||
|
@ -68,37 +124,37 @@ SettingsDialog::SettingsDialog(QWidget* parent /* = nullptr */)
|
|||
connect(m_ui.restoreDefaultsButton, &QPushButton::clicked, this, &SettingsDialog::onRestoreDefaultsClicked);
|
||||
}
|
||||
|
||||
SettingsDialog::~SettingsDialog() = default;
|
||||
|
||||
void SettingsDialog::setCategoryHelpTexts()
|
||||
SettingsDialog::~SettingsDialog()
|
||||
{
|
||||
m_category_help_text[static_cast<int>(Category::InterfaceSettings)] =
|
||||
tr("<strong>Interface Settings</strong><hr>These options control how the software looks and behaves.<br><br>Mouse "
|
||||
"over "
|
||||
"an option for additional information.");
|
||||
m_category_help_text[static_cast<int>(Category::SystemSettings)] =
|
||||
tr("<strong>System Settings</strong><hr>These options determine the configuration of the simulated "
|
||||
"console.<br><br>Mouse over an option for additional information.");
|
||||
m_category_help_text[static_cast<int>(Category::GameListSettings)] =
|
||||
tr("<strong>Game List Settings</strong><hr>The list above shows the directories which will be searched by "
|
||||
"PCSX2 to populate the game list. Search directories can be added, removed, and switched to "
|
||||
"recursive/non-recursive.");
|
||||
m_category_help_text[static_cast<int>(Category::AudioSettings)] =
|
||||
tr("<strong>Audio Settings</strong><hr>These options control the audio output of the console. Mouse over an option "
|
||||
"for additional information.");
|
||||
if (isPerGameSettings())
|
||||
s_open_game_properties_dialogs.removeOne(this);
|
||||
}
|
||||
|
||||
void SettingsDialog::setCategory(Category category)
|
||||
void SettingsDialog::closeEvent(QCloseEvent*)
|
||||
{
|
||||
if (category >= Category::Count)
|
||||
return;
|
||||
// we need to clean up ourselves, since we're not modal
|
||||
if (isPerGameSettings())
|
||||
deleteLater();
|
||||
}
|
||||
|
||||
m_ui.settingsCategory->setCurrentRow(static_cast<int>(category));
|
||||
void SettingsDialog::setCategory(const char* category)
|
||||
{
|
||||
// the titles in the category list will be translated.
|
||||
const QString translated_category(qApp->translate("SettingsDialog", category));
|
||||
|
||||
for (int i = 0; i < m_ui.settingsCategory->count(); i++)
|
||||
{
|
||||
if (translated_category == m_ui.settingsCategory->item(i)->text())
|
||||
{
|
||||
// will also update the visible widget
|
||||
m_ui.settingsCategory->setCurrentRow(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SettingsDialog::onCategoryCurrentRowChanged(int row)
|
||||
{
|
||||
Q_ASSERT(row < static_cast<int>(Category::Count));
|
||||
m_ui.settingsContainer->setCurrentIndex(row);
|
||||
m_ui.helpText->setText(m_category_help_text[row]);
|
||||
}
|
||||
|
@ -106,8 +162,8 @@ void SettingsDialog::onCategoryCurrentRowChanged(int row)
|
|||
void SettingsDialog::onRestoreDefaultsClicked()
|
||||
{
|
||||
if (QMessageBox::question(this, tr("Confirm Restore Defaults"),
|
||||
tr("Are you sure you want to restore the default settings? Any preferences will be lost."),
|
||||
QMessageBox::Yes, QMessageBox::No) != QMessageBox::Yes)
|
||||
tr("Are you sure you want to restore the default settings? Any preferences will be lost."), QMessageBox::Yes,
|
||||
QMessageBox::No) != QMessageBox::Yes)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -115,6 +171,20 @@ void SettingsDialog::onRestoreDefaultsClicked()
|
|||
// TODO
|
||||
}
|
||||
|
||||
void SettingsDialog::addWidget(QWidget* widget, QString title, QString icon, QString help_text)
|
||||
{
|
||||
const int index = m_ui.settingsCategory->count();
|
||||
|
||||
QListWidgetItem* item = new QListWidgetItem(m_ui.settingsCategory);
|
||||
item->setText(title);
|
||||
if (!icon.isEmpty())
|
||||
item->setIcon(QIcon::fromTheme(icon));
|
||||
|
||||
m_ui.settingsContainer->addWidget(widget);
|
||||
|
||||
m_category_help_text[index] = std::move(help_text);
|
||||
}
|
||||
|
||||
void SettingsDialog::registerWidgetHelp(QObject* object, QString title, QString recommended_value, QString text)
|
||||
{
|
||||
// construct rich text with formatted description
|
||||
|
@ -154,3 +224,201 @@ bool SettingsDialog::eventFilter(QObject* object, QEvent* event)
|
|||
|
||||
return QDialog::eventFilter(object, event);
|
||||
}
|
||||
|
||||
bool SettingsDialog::getEffectiveBoolValue(const char* section, const char* key, bool default_value) const
|
||||
{
|
||||
bool value;
|
||||
if (m_sif && m_sif->GetBoolValue(section, key, &value))
|
||||
return value;
|
||||
else
|
||||
return QtHost::GetBaseBoolSettingValue(section, key, default_value);
|
||||
}
|
||||
|
||||
int SettingsDialog::getEffectiveIntValue(const char* section, const char* key, int default_value) const
|
||||
{
|
||||
int value;
|
||||
if (m_sif && m_sif->GetIntValue(section, key, &value))
|
||||
return value;
|
||||
else
|
||||
return QtHost::GetBaseIntSettingValue(section, key, default_value);
|
||||
}
|
||||
|
||||
float SettingsDialog::getEffectiveFloatValue(const char* section, const char* key, float default_value) const
|
||||
{
|
||||
float value;
|
||||
if (m_sif && m_sif->GetFloatValue(section, key, &value))
|
||||
return value;
|
||||
else
|
||||
return QtHost::GetBaseFloatSettingValue(section, key, default_value);
|
||||
}
|
||||
|
||||
std::string SettingsDialog::getEffectiveStringValue(const char* section, const char* key, const char* default_value) const
|
||||
{
|
||||
std::string value;
|
||||
if (!m_sif || !m_sif->GetStringValue(section, key, &value))
|
||||
value = QtHost::GetBaseStringSettingValue(section, key, default_value);
|
||||
return value;
|
||||
}
|
||||
|
||||
std::optional<bool> SettingsDialog::getBoolValue(const char* section, const char* key, std::optional<bool> default_value) const
|
||||
{
|
||||
std::optional<bool> value;
|
||||
if (m_sif)
|
||||
{
|
||||
bool bvalue;
|
||||
if (m_sif->GetBoolValue(section, key, &bvalue))
|
||||
value = bvalue;
|
||||
else
|
||||
value = default_value;
|
||||
}
|
||||
else
|
||||
{
|
||||
value = QtHost::GetBaseBoolSettingValue(section, key, default_value.value_or(false));
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
std::optional<int> SettingsDialog::getIntValue(const char* section, const char* key, std::optional<int> default_value) const
|
||||
{
|
||||
std::optional<int> value;
|
||||
if (m_sif)
|
||||
{
|
||||
int ivalue;
|
||||
if (m_sif->GetIntValue(section, key, &ivalue))
|
||||
value = ivalue;
|
||||
else
|
||||
value = default_value;
|
||||
}
|
||||
else
|
||||
{
|
||||
value = QtHost::GetBaseIntSettingValue(section, key, default_value.value_or(0));
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
std::optional<float> SettingsDialog::getFloatValue(const char* section, const char* key, std::optional<float> default_value) const
|
||||
{
|
||||
std::optional<float> value;
|
||||
if (m_sif)
|
||||
{
|
||||
float fvalue;
|
||||
if (m_sif->GetFloatValue(section, key, &fvalue))
|
||||
value = fvalue;
|
||||
else
|
||||
value = default_value;
|
||||
}
|
||||
else
|
||||
{
|
||||
value = QtHost::GetBaseFloatSettingValue(section, key, default_value.value_or(0.0f));
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
std::optional<std::string> SettingsDialog::getStringValue(const char* section, const char* key, std::optional<const char*> default_value) const
|
||||
{
|
||||
std::optional<std::string> value;
|
||||
if (m_sif)
|
||||
{
|
||||
std::string svalue;
|
||||
if (m_sif->GetStringValue(section, key, &svalue))
|
||||
value = std::move(svalue);
|
||||
else if (default_value.has_value())
|
||||
value = default_value.value();
|
||||
}
|
||||
else
|
||||
{
|
||||
value = QtHost::GetBaseStringSettingValue(section, key, default_value.value_or(""));
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
void SettingsDialog::setBoolSettingValue(const char* section, const char* key, std::optional<bool> value)
|
||||
{
|
||||
if (m_sif)
|
||||
{
|
||||
value.has_value() ? m_sif->SetBoolValue(section, key, value.value()) : m_sif->DeleteValue(section, key);
|
||||
m_sif->Save();
|
||||
}
|
||||
else
|
||||
{
|
||||
value.has_value() ? QtHost::SetBaseBoolSettingValue(section, key, value.value()) : QtHost::RemoveBaseSettingValue(section, key);
|
||||
}
|
||||
|
||||
g_emu_thread->applySettings();
|
||||
}
|
||||
|
||||
void SettingsDialog::setIntSettingValue(const char* section, const char* key, std::optional<int> value)
|
||||
{
|
||||
if (m_sif)
|
||||
{
|
||||
value.has_value() ? m_sif->SetIntValue(section, key, value.value()) : m_sif->DeleteValue(section, key);
|
||||
m_sif->Save();
|
||||
}
|
||||
else
|
||||
{
|
||||
value.has_value() ? QtHost::SetBaseIntSettingValue(section, key, value.value()) : QtHost::RemoveBaseSettingValue(section, key);
|
||||
}
|
||||
|
||||
g_emu_thread->applySettings();
|
||||
}
|
||||
|
||||
void SettingsDialog::setFloatSettingValue(const char* section, const char* key, std::optional<float> value)
|
||||
{
|
||||
if (m_sif)
|
||||
{
|
||||
value.has_value() ? m_sif->SetFloatValue(section, key, value.value()) : m_sif->DeleteValue(section, key);
|
||||
m_sif->Save();
|
||||
}
|
||||
else
|
||||
{
|
||||
value.has_value() ? QtHost::SetBaseFloatSettingValue(section, key, value.value()) : QtHost::RemoveBaseSettingValue(section, key);
|
||||
}
|
||||
|
||||
g_emu_thread->applySettings();
|
||||
}
|
||||
|
||||
void SettingsDialog::setStringSettingValue(const char* section, const char* key, std::optional<const char*> value)
|
||||
{
|
||||
if (m_sif)
|
||||
{
|
||||
value.has_value() ? m_sif->SetBoolValue(section, key, value.value()) : m_sif->DeleteValue(section, key);
|
||||
m_sif->Save();
|
||||
}
|
||||
else
|
||||
{
|
||||
value.has_value() ? QtHost::SetBaseStringSettingValue(section, key, value.value()) : QtHost::RemoveBaseSettingValue(section, key);
|
||||
}
|
||||
|
||||
g_emu_thread->applySettings();
|
||||
}
|
||||
|
||||
void SettingsDialog::openGamePropertiesDialog(const GameList::Entry* game, u32 crc)
|
||||
{
|
||||
// check for an existing dialog with this crc
|
||||
for (SettingsDialog* dialog : s_open_game_properties_dialogs)
|
||||
{
|
||||
if (dialog->m_game_crc == crc)
|
||||
{
|
||||
dialog->show();
|
||||
dialog->setFocus();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<INISettingsInterface> sif =
|
||||
std::make_unique<INISettingsInterface>(Path::CombineStdString(EmuFolders::GameSettings, StringUtil::StdStringFromFormat("%08X.ini", crc)));
|
||||
if (FileSystem::FileExists(sif->GetFileName().c_str()))
|
||||
sif->Load();
|
||||
|
||||
const QString window_title(tr("%1 [%2]")
|
||||
.arg(game ? QtUtils::StringViewToQString(game->title) : QStringLiteral("<UNKNOWN>"))
|
||||
.arg(QtUtils::StringViewToQString(FileSystem::GetFileNameFromPath(sif->GetFileName()))));
|
||||
|
||||
SettingsDialog* dialog = new SettingsDialog(std::move(sif), game, crc);
|
||||
dialog->setWindowTitle(window_title);
|
||||
dialog->show();
|
||||
}
|
||||
|
|
|
@ -19,6 +19,14 @@
|
|||
#include <QtCore/QString>
|
||||
#include <QtWidgets/QDialog>
|
||||
#include <array>
|
||||
#include <memory>
|
||||
|
||||
class INISettingsInterface;
|
||||
|
||||
namespace GameList
|
||||
{
|
||||
struct Entry;
|
||||
}
|
||||
|
||||
class InterfaceSettingsWidget;
|
||||
class GameListSettingsWidget;
|
||||
|
@ -36,50 +44,68 @@ class SettingsDialog final : public QDialog
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum class Category
|
||||
{
|
||||
InterfaceSettings,
|
||||
GameListSettings,
|
||||
BIOSSettings,
|
||||
EmulationSettings,
|
||||
SystemSettings,
|
||||
AdvancedSystemSettings,
|
||||
GameFixSettings,
|
||||
GraphicsSettings,
|
||||
AudioSettings,
|
||||
MemoryCardSettings,
|
||||
Count
|
||||
};
|
||||
|
||||
explicit SettingsDialog(QWidget* parent = nullptr);
|
||||
explicit SettingsDialog(QWidget* parent);
|
||||
SettingsDialog(std::unique_ptr<SettingsInterface> sif, const GameList::Entry* game, u32 game_crc);
|
||||
~SettingsDialog();
|
||||
|
||||
InterfaceSettingsWidget* getInterfaceSettingsWidget() const { return m_interface_settings; }
|
||||
GameListSettingsWidget* getGameListSettingsWidget() const { return m_game_list_settings; }
|
||||
BIOSSettingsWidget* getBIOSSettingsWidget() const { return m_bios_settings; }
|
||||
EmulationSettingsWidget* getEmulationSettingsWidget() const { return m_emulation_settings; }
|
||||
SystemSettingsWidget* getSystemSettingsWidget() const { return m_system_settings; }
|
||||
AdvancedSystemSettingsWidget* getAdvancedSystemSettingsWidget() const { return m_advanced_system_settings; }
|
||||
GameFixSettingsWidget* getGameFixSettingsWidget() const { return m_game_fix_settings_widget; }
|
||||
GraphicsSettingsWidget* getGraphicsSettingsWidget() const { return m_graphics_settings; }
|
||||
AudioSettingsWidget* getAudioSettingsWidget() const { return m_audio_settings; }
|
||||
MemoryCardSettingsWidget* getMemoryCardSettingsWidget() const { return m_memory_card_settings; }
|
||||
static void openGamePropertiesDialog(const GameList::Entry* game, u32 crc);
|
||||
|
||||
__fi bool isPerGameSettings() const { return static_cast<bool>(m_sif); }
|
||||
__fi SettingsInterface* getSettingsInterface() const { return m_sif.get(); }
|
||||
|
||||
__fi InterfaceSettingsWidget* getInterfaceSettingsWidget() const { return m_interface_settings; }
|
||||
__fi GameListSettingsWidget* getGameListSettingsWidget() const { return m_game_list_settings; }
|
||||
__fi BIOSSettingsWidget* getBIOSSettingsWidget() const { return m_bios_settings; }
|
||||
__fi EmulationSettingsWidget* getEmulationSettingsWidget() const { return m_emulation_settings; }
|
||||
__fi SystemSettingsWidget* getSystemSettingsWidget() const { return m_system_settings; }
|
||||
__fi AdvancedSystemSettingsWidget* getAdvancedSystemSettingsWidget() const { return m_advanced_system_settings; }
|
||||
__fi GameFixSettingsWidget* getGameFixSettingsWidget() const { return m_game_fix_settings_widget; }
|
||||
__fi GraphicsSettingsWidget* getGraphicsSettingsWidget() const { return m_graphics_settings; }
|
||||
__fi AudioSettingsWidget* getAudioSettingsWidget() const { return m_audio_settings; }
|
||||
__fi MemoryCardSettingsWidget* getMemoryCardSettingsWidget() const { return m_memory_card_settings; }
|
||||
|
||||
void registerWidgetHelp(QObject* object, QString title, QString recommended_value, QString text);
|
||||
bool eventFilter(QObject* object, QEvent* event) override;
|
||||
|
||||
void setCategory(const char* category);
|
||||
|
||||
// Helper functions for reading effective setting values (from game -> global settings).
|
||||
bool getEffectiveBoolValue(const char* section, const char* key, bool default_value) const;
|
||||
int getEffectiveIntValue(const char* section, const char* key, int default_value) const;
|
||||
float getEffectiveFloatValue(const char* section, const char* key, float default_value) const;
|
||||
std::string getEffectiveStringValue(const char* section, const char* key, const char* default_value) const;
|
||||
|
||||
// Helper functions for reading setting values for this layer (game settings or global).
|
||||
std::optional<bool> getBoolValue(const char* section, const char* key, std::optional<bool> default_value) const;
|
||||
std::optional<int> getIntValue(const char* section, const char* key, std::optional<int> default_value) const;
|
||||
std::optional<float> getFloatValue(const char* section, const char* key, std::optional<float> default_value) const;
|
||||
std::optional<std::string> getStringValue(const char* section, const char* key, std::optional<const char*> default_value) const;
|
||||
void setBoolSettingValue(const char* section, const char* key, std::optional<bool> value);
|
||||
void setIntSettingValue(const char* section, const char* key, std::optional<int> value);
|
||||
void setFloatSettingValue(const char* section, const char* key, std::optional<float> value);
|
||||
void setStringSettingValue(const char* section, const char* key, std::optional<const char*> value);
|
||||
|
||||
Q_SIGNALS:
|
||||
void settingsResetToDefaults();
|
||||
|
||||
public Q_SLOTS:
|
||||
void setCategory(Category category);
|
||||
|
||||
private Q_SLOTS:
|
||||
void onCategoryCurrentRowChanged(int row);
|
||||
void onRestoreDefaultsClicked();
|
||||
|
||||
protected:
|
||||
void closeEvent(QCloseEvent*);
|
||||
|
||||
private:
|
||||
void setCategoryHelpTexts();
|
||||
enum : u32
|
||||
{
|
||||
MAX_SETTINGS_WIDGETS = 10
|
||||
};
|
||||
|
||||
void setupUi(const GameList::Entry* game);
|
||||
|
||||
void addWidget(QWidget* widget, QString title, QString icon, QString help_text);
|
||||
|
||||
std::unique_ptr<SettingsInterface> m_sif;
|
||||
|
||||
Ui::SettingsDialog m_ui;
|
||||
|
||||
|
@ -94,8 +120,10 @@ private:
|
|||
AudioSettingsWidget* m_audio_settings = nullptr;
|
||||
MemoryCardSettingsWidget* m_memory_card_settings = nullptr;
|
||||
|
||||
std::array<QString, static_cast<int>(Category::Count)> m_category_help_text;
|
||||
std::array<QString, MAX_SETTINGS_WIDGETS> m_category_help_text;
|
||||
|
||||
QObject* m_current_help_widget = nullptr;
|
||||
QMap<QObject*, QString> m_widget_help_text_map;
|
||||
|
||||
u32 m_game_crc;
|
||||
};
|
||||
|
|
|
@ -49,86 +49,6 @@
|
|||
<height>32</height>
|
||||
</size>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Interface</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="settings-3-line"/>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Game List</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="folder-settings-line"/>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>BIOS</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="hard-drive-2-line"/>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Emulation</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="dashboard-line"/>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>System</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="artboard-2-line"/>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Advanced System</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="artboard-2-line"/>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Game Fixes</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="close-line"/>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Graphics</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="brush-line"/>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Audio</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="volume-up-line"/>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Memory Cards</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="sd-card-line"/>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
|
@ -139,11 +59,6 @@
|
|||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="page"/>
|
||||
<widget class="QWidget" name="page_2"/>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
|
|
|
@ -29,33 +29,49 @@ static constexpr int MAXIMUM_EE_CYCLE_RATE = 3;
|
|||
static constexpr int DEFAULT_EE_CYCLE_RATE = 0;
|
||||
static constexpr int DEFAULT_EE_CYCLE_SKIP = 0;
|
||||
|
||||
SystemSettingsWidget::SystemSettingsWidget(QWidget* parent, SettingsDialog* dialog)
|
||||
SystemSettingsWidget::SystemSettingsWidget(SettingsDialog* dialog, QWidget* parent)
|
||||
: QWidget(parent)
|
||||
, m_dialog(dialog)
|
||||
{
|
||||
SettingsInterface* sif = dialog->getSettingsInterface();
|
||||
|
||||
m_ui.setupUi(this);
|
||||
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(m_ui.eeRoundingMode, "EmuCore/CPU", "FPU.Roundmode", 3);
|
||||
m_ui.eeClampMode->setCurrentIndex(getClampingModeIndex(false));
|
||||
connect(m_ui.eeClampMode, QOverload<int>::of(&QComboBox::currentIndexChanged),
|
||||
[this](int index) { setClampingMode(false, index); });
|
||||
m_ui.eeCycleRate->setCurrentIndex(
|
||||
std::clamp(QtHost::GetBaseIntSettingValue("EmuCore/Speedhacks", "EECycleRate", DEFAULT_EE_CYCLE_RATE),
|
||||
MINIMUM_EE_CYCLE_RATE, MAXIMUM_EE_CYCLE_RATE) +
|
||||
(0 - MINIMUM_EE_CYCLE_RATE));
|
||||
connect(m_ui.eeCycleRate, QOverload<int>::of(&QComboBox::currentIndexChanged), [](int index) {
|
||||
QtHost::SetBaseIntSettingValue("EmuCore/Speedhacks", "EECycleRate", MINIMUM_EE_CYCLE_RATE + index);
|
||||
g_emu_thread->applySettings();
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.eeCycleSkipping, "EmuCore/Speedhacks", "EECycleSkip", 0);
|
||||
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.MTVU, "EmuCore/Speedhacks", "vuThread", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.instantVU1, "EmuCore/Speedhacks", "vu1Instant", true);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.eeRoundingMode, "EmuCore/CPU", "FPU.Roundmode", 3);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.vuRoundingMode, "EmuCore/CPU", "VU.Roundmode", 3);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.fastCDVD, "EmuCore/Speedhacks", "fastCDVD", false);
|
||||
|
||||
if (m_dialog->isPerGameSettings())
|
||||
{
|
||||
m_ui.eeCycleRate->insertItem(
|
||||
0, tr("Use Global Setting [%1]")
|
||||
.arg(m_ui.eeCycleRate->itemText(
|
||||
std::clamp(QtHost::GetBaseIntSettingValue("EmuCore/Speedhacks", "EECycleRate", DEFAULT_EE_CYCLE_RATE) - MINIMUM_EE_CYCLE_RATE,
|
||||
0, MAXIMUM_EE_CYCLE_RATE - MINIMUM_EE_CYCLE_RATE))));
|
||||
m_ui.eeClampMode->insertItem(0, tr("Use Global Setting [%1]").arg(m_ui.eeClampMode->itemText(getGlobalClampingModeIndex(false))));
|
||||
m_ui.vuClampMode->insertItem(0, tr("Use Global Setting [%1]").arg(m_ui.vuClampMode->itemText(getGlobalClampingModeIndex(true))));
|
||||
}
|
||||
|
||||
const std::optional<int> cycle_rate =
|
||||
m_dialog->getIntValue("EmuCore/Speedhacks", "EECycleRate", sif ? std::nullopt : std::optional<int>(DEFAULT_EE_CYCLE_RATE));
|
||||
m_ui.eeCycleRate->setCurrentIndex(cycle_rate.has_value() ? (std::clamp(cycle_rate.value(), MINIMUM_EE_CYCLE_RATE, MAXIMUM_EE_CYCLE_RATE) +
|
||||
(0 - MINIMUM_EE_CYCLE_RATE) + static_cast<int>(m_dialog->isPerGameSettings())) :
|
||||
0);
|
||||
connect(m_ui.eeCycleRate, QOverload<int>::of(&QComboBox::currentIndexChanged), this, [this](int index) {
|
||||
std::optional<int> value;
|
||||
if (!m_dialog->isPerGameSettings() || index > 0)
|
||||
value = MINIMUM_EE_CYCLE_RATE + index - static_cast<int>(m_dialog->isPerGameSettings());
|
||||
m_dialog->setIntSettingValue("EmuCore/Speedhacks", "EECycleRate", value);
|
||||
});
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(m_ui.eeCycleSkipping, "EmuCore/Speedhacks", "EECycleSkip", 0);
|
||||
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.MTVU, "EmuCore/Speedhacks", "vuThread", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.instantVU1, "EmuCore/Speedhacks", "vu1Instant", true);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(m_ui.vuRoundingMode, "EmuCore/CPU", "VU.Roundmode", 3);
|
||||
m_ui.eeClampMode->setCurrentIndex(getClampingModeIndex(false));
|
||||
m_ui.vuClampMode->setCurrentIndex(getClampingModeIndex(true));
|
||||
connect(m_ui.vuClampMode, QOverload<int>::of(&QComboBox::currentIndexChanged),
|
||||
[this](int index) { setClampingMode(true, index); });
|
||||
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.fastCDVD, "EmuCore/Speedhacks", "fastCDVD", false);
|
||||
connect(m_ui.eeClampMode, QOverload<int>::of(&QComboBox::currentIndexChanged), [this](int index) { setClampingMode(false, index); });
|
||||
connect(m_ui.vuClampMode, QOverload<int>::of(&QComboBox::currentIndexChanged), [this](int index) { setClampingMode(true, index); });
|
||||
|
||||
updateVU1InstantState();
|
||||
connect(m_ui.MTVU, &QCheckBox::stateChanged, this, &SystemSettingsWidget::updateVU1InstantState);
|
||||
|
@ -65,24 +81,59 @@ SystemSettingsWidget::~SystemSettingsWidget() = default;
|
|||
|
||||
void SystemSettingsWidget::updateVU1InstantState()
|
||||
{
|
||||
m_ui.instantVU1->setEnabled(!m_ui.MTVU->isChecked());
|
||||
m_ui.instantVU1->setEnabled(!m_dialog->getEffectiveBoolValue("EmuCore/Speedhacks", "vuThread", false));
|
||||
}
|
||||
|
||||
int SystemSettingsWidget::getClampingModeIndex(bool vu)
|
||||
int SystemSettingsWidget::getGlobalClampingModeIndex(bool vu) const
|
||||
{
|
||||
if (QtHost::GetBaseBoolSettingValue("EmuCore/CPU/Recompiler", vu ? "vuSignOverflow" : "fpuFullMode", false))
|
||||
return 3;
|
||||
|
||||
if (QtHost::GetBaseBoolSettingValue("EmuCore/CPU/Recompiler", vu ? "vuExtraOverflow" : "fpuExtraOverflow", false))
|
||||
return 2;
|
||||
|
||||
if (QtHost::GetBaseBoolSettingValue("EmuCore/CPU/Recompiler", vu ? "vuOverflow" : "fpuOverflow", true))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SystemSettingsWidget::getClampingModeIndex(bool vu) const
|
||||
{
|
||||
// This is so messy... maybe we should just make the mode an int in the settings too...
|
||||
const bool base = m_dialog->isPerGameSettings() ? 1 : 0;
|
||||
std::optional<bool> default_false = m_dialog->isPerGameSettings() ? std::nullopt : std::optional<bool>(false);
|
||||
std::optional<bool> default_true = m_dialog->isPerGameSettings() ? std::nullopt : std::optional<bool>(true);
|
||||
|
||||
std::optional<bool> third = m_dialog->getBoolValue("EmuCore/CPU/Recompiler", vu ? "vuSignOverflow" : "fpuFullMode", default_false);
|
||||
std::optional<bool> second = m_dialog->getBoolValue("EmuCore/CPU/Recompiler", vu ? "vuExtraOverflow" : "fpuExtraOverflow", default_false);
|
||||
std::optional<bool> first = m_dialog->getBoolValue("EmuCore/CPU/Recompiler", vu ? "vuOverflow" : "fpuOverflow", default_true);
|
||||
|
||||
if (third.has_value() && third.value())
|
||||
return base + 3;
|
||||
if (second.has_value() && second.value())
|
||||
return base + 2;
|
||||
if (first.has_value() && first.value())
|
||||
return base + 1;
|
||||
else if (first.has_value())
|
||||
return base + 0; // none
|
||||
else
|
||||
return 0; // no per game override
|
||||
}
|
||||
|
||||
void SystemSettingsWidget::setClampingMode(bool vu, int index)
|
||||
{
|
||||
QtHost::SetBaseBoolSettingValue("EmuCore/CPU/Recompiler", vu ? "vuSignOverflow" : "fpuFullMode", (index >= 3));
|
||||
QtHost::SetBaseBoolSettingValue("EmuCore/CPU/Recompiler", vu ? "vuExtraOverflow" : "fpuExtraOverflow", (index >= 2));
|
||||
QtHost::SetBaseBoolSettingValue("EmuCore/CPU/Recompiler", vu ? "vuOverflow" : "fpuOverflow", (index >= 1));
|
||||
g_emu_thread->applySettings();
|
||||
std::optional<bool> first, second, third;
|
||||
|
||||
if (!m_dialog->isPerGameSettings() || index > 0)
|
||||
{
|
||||
const bool base = m_dialog->isPerGameSettings() ? 1 : 0;
|
||||
third = (index >= (base + 3));
|
||||
second = (index >= (base + 2));
|
||||
first = (index >= (base + 1));
|
||||
}
|
||||
|
||||
m_dialog->setBoolSettingValue("EmuCore/CPU/Recompiler", vu ? "vuSignOverflow" : "fpuFullMode", third);
|
||||
m_dialog->setBoolSettingValue("EmuCore/CPU/Recompiler", vu ? "vuExtraOverflow" : "fpuExtraOverflow", second);
|
||||
m_dialog->setBoolSettingValue("EmuCore/CPU/Recompiler", vu ? "vuOverflow" : "fpuOverflow", first);
|
||||
}
|
||||
|
|
|
@ -26,15 +26,18 @@ class SystemSettingsWidget : public QWidget
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
SystemSettingsWidget(QWidget* parent, SettingsDialog* dialog);
|
||||
SystemSettingsWidget(SettingsDialog* dialog, QWidget* parent);
|
||||
~SystemSettingsWidget();
|
||||
|
||||
private Q_SLOTS:
|
||||
void updateVU1InstantState();
|
||||
|
||||
private:
|
||||
static int getClampingModeIndex(bool vu);
|
||||
static void setClampingMode(bool vu, int index);
|
||||
int getGlobalClampingModeIndex(bool vu) const;
|
||||
int getClampingModeIndex(bool vu) const;
|
||||
void setClampingMode(bool vu, int index);
|
||||
|
||||
SettingsDialog* m_dialog;
|
||||
|
||||
Ui::SystemSettingsWidget m_ui;
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue