mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-06-09 12:31:40 +12:00
[WIP] Qt: Add config window controls (#655)
* Qt: Add config window controls * Fix Windows build * Fix audio slider * Qt configs: Make thread-safe, properly update audio enable & renderdoc settings * Qt configs: Add `connectCheckbox` function * Qt configs: Add `connectCheckbox` function * Rename spuLayout * Add Discord RPC reloading * Allow configuring the app icon * Qt: Serialize icon & theme, properly set them * Add rnap and rcow icons * Qt: Fix forceShadergen config --------- Co-authored-by: wheremyfoodat <44909372+wheremyfoodat@users.noreply.github.com>
This commit is contained in:
parent
c2b479889c
commit
156328fbfb
22 changed files with 509 additions and 25 deletions
|
@ -130,6 +130,16 @@ void EmulatorConfig::load() {
|
|||
sdWriteProtected = toml::find_or<toml::boolean>(sd, "WriteProtectVirtualSD", false);
|
||||
}
|
||||
}
|
||||
|
||||
if (data.contains("UI")) {
|
||||
auto uiResult = toml::expect<toml::value>(data.at("UI"));
|
||||
if (uiResult.is_ok()) {
|
||||
auto ui = uiResult.unwrap();
|
||||
|
||||
frontendSettings.theme = FrontendSettings::themeFromString(toml::find_or<std::string>(ui, "Theme", "dark"));
|
||||
frontendSettings.icon = FrontendSettings::iconFromString(toml::find_or<std::string>(ui, "WindowIcon", "rpog"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EmulatorConfig::save() {
|
||||
|
@ -186,6 +196,9 @@ void EmulatorConfig::save() {
|
|||
data["SD"]["UseVirtualSD"] = sdCardInserted;
|
||||
data["SD"]["WriteProtectVirtualSD"] = sdWriteProtected;
|
||||
|
||||
data["UI"]["Theme"] = std::string(FrontendSettings::themeToString(frontendSettings.theme));
|
||||
data["UI"]["WindowIcon"] = std::string(FrontendSettings::iconToString(frontendSettings.icon));
|
||||
|
||||
std::ofstream file(path, std::ios::out);
|
||||
file << data;
|
||||
file.close();
|
||||
|
|
|
@ -444,3 +444,24 @@ void Emulator::loadRenderdoc() {
|
|||
Renderdoc::loadRenderdoc();
|
||||
Renderdoc::setOutputDir(capturePath, "");
|
||||
}
|
||||
|
||||
void Emulator::reloadSettings() {
|
||||
setAudioEnabled(config.audioEnabled);
|
||||
|
||||
if (Renderdoc::isSupported() && config.enableRenderdoc && !Renderdoc::isLoaded()) {
|
||||
loadRenderdoc();
|
||||
}
|
||||
|
||||
#ifdef PANDA3DS_ENABLE_DISCORD_RPC
|
||||
// Reload RPC setting if we're compiling with RPC support
|
||||
|
||||
if (discordRpc.running() != config.discordRpcEnabled) {
|
||||
if (config.discordRpcEnabled) {
|
||||
discordRpc.init();
|
||||
updateDiscord();
|
||||
} else {
|
||||
discordRpc.stop();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
64
src/frontend_settings.cpp
Normal file
64
src/frontend_settings.cpp
Normal file
|
@ -0,0 +1,64 @@
|
|||
#include "frontend_settings.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include <unordered_map>
|
||||
|
||||
// Frontend setting serialization/deserialization functions
|
||||
|
||||
FrontendSettings::Theme FrontendSettings::themeFromString(std::string inString) {
|
||||
// Transform to lower-case to make the setting case-insensitive
|
||||
std::transform(inString.begin(), inString.end(), inString.begin(), [](unsigned char c) { return std::tolower(c); });
|
||||
|
||||
static const std::unordered_map<std::string, Theme> map = {
|
||||
{"system", Theme::System}, {"light", Theme::Light}, {"dark", Theme::Dark}, {"greetingscat", Theme::GreetingsCat}, {"cream", Theme::Cream},
|
||||
};
|
||||
|
||||
if (auto search = map.find(inString); search != map.end()) {
|
||||
return search->second;
|
||||
}
|
||||
|
||||
// Default to dark theme
|
||||
return Theme::Dark;
|
||||
}
|
||||
|
||||
const char* FrontendSettings::themeToString(Theme theme) {
|
||||
switch (theme) {
|
||||
case Theme::System: return "system";
|
||||
case Theme::Light: return "light";
|
||||
case Theme::GreetingsCat: return "greetingscat";
|
||||
case Theme::Cream: return "cream";
|
||||
|
||||
case Theme::Dark:
|
||||
default: return "dark";
|
||||
}
|
||||
}
|
||||
|
||||
FrontendSettings::WindowIcon FrontendSettings::iconFromString(std::string inString) { // Transform to lower-case to make the setting case-insensitive
|
||||
std::transform(inString.begin(), inString.end(), inString.begin(), [](unsigned char c) { return std::tolower(c); });
|
||||
|
||||
static const std::unordered_map<std::string, WindowIcon> map = {
|
||||
{"rpog", WindowIcon::Rpog},
|
||||
{"rsyn", WindowIcon::Rsyn},
|
||||
{"rcow", WindowIcon::Rcow},
|
||||
{"rnap", WindowIcon::Rnap},
|
||||
};
|
||||
|
||||
if (auto search = map.find(inString); search != map.end()) {
|
||||
return search->second;
|
||||
}
|
||||
|
||||
// Default to the icon rpog icon
|
||||
return WindowIcon::Rpog;
|
||||
}
|
||||
|
||||
const char* FrontendSettings::iconToString(WindowIcon icon) {
|
||||
switch (icon) {
|
||||
case WindowIcon::Rsyn: return "rsyn";
|
||||
case WindowIcon::Rcow: return "rcow";
|
||||
case WindowIcon::Rnap: return "rnap";
|
||||
|
||||
case WindowIcon::Rpog:
|
||||
default: return "rpog";
|
||||
}
|
||||
}
|
|
@ -1,26 +1,286 @@
|
|||
#include "panda_qt/config_window.hpp"
|
||||
|
||||
ConfigWindow::ConfigWindow(QWidget* parent) : QDialog(parent) {
|
||||
ConfigWindow::ConfigWindow(ConfigCallback configCallback, IconCallback iconCallback, const EmulatorConfig& emuConfig, QWidget* parent)
|
||||
: QDialog(parent), config(emuConfig) {
|
||||
setWindowTitle(tr("Configuration"));
|
||||
|
||||
updateConfig = std::move(configCallback);
|
||||
updateIcon = std::move(iconCallback);
|
||||
|
||||
// Set up theme selection
|
||||
setTheme(Theme::Dark);
|
||||
themeSelect = new QComboBox(this);
|
||||
setTheme(config.frontendSettings.theme);
|
||||
setIcon(config.frontendSettings.icon);
|
||||
|
||||
// Initialize the widget list and the widget container widgets
|
||||
widgetList = new QListWidget(this);
|
||||
widgetContainer = new QStackedWidget(this);
|
||||
|
||||
helpText = new QTextEdit(this);
|
||||
helpText->setReadOnly(true);
|
||||
|
||||
helpText->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
||||
helpText->setFixedHeight(50);
|
||||
|
||||
widgetList->setMinimumWidth(100);
|
||||
widgetList->setMaximumWidth(100);
|
||||
widgetList->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
|
||||
widgetList->setPalette(QPalette(QColor(25, 25, 25)));
|
||||
|
||||
widgetList->setCurrentRow(0);
|
||||
widgetContainer->setCurrentIndex(0);
|
||||
|
||||
connect(widgetList, &QListWidget::currentRowChanged, this, [&](int row) {
|
||||
widgetContainer->setCurrentIndex(row);
|
||||
helpText->setText(helpTexts[row]);
|
||||
});
|
||||
|
||||
auto connectCheckbox = [&](QCheckBox* checkbox, bool& setting) {
|
||||
checkbox->setChecked(setting);
|
||||
|
||||
connect(checkbox, &QCheckBox::toggled, this, [&](bool checked) {
|
||||
setting = checked;
|
||||
updateConfig();
|
||||
});
|
||||
};
|
||||
|
||||
QVBoxLayout* mainLayout = new QVBoxLayout();
|
||||
QHBoxLayout* hLayout = new QHBoxLayout();
|
||||
|
||||
// Set up widget layouts
|
||||
setLayout(mainLayout);
|
||||
mainLayout->addLayout(hLayout);
|
||||
mainLayout->addWidget(helpText);
|
||||
|
||||
hLayout->setAlignment(Qt::AlignLeft);
|
||||
hLayout->addWidget(widgetList);
|
||||
hLayout->addWidget(widgetContainer);
|
||||
|
||||
// Interface settings
|
||||
QGroupBox* guiGroupBox = new QGroupBox(tr("Interface Settings"), this);
|
||||
QFormLayout* guiLayout = new QFormLayout(guiGroupBox);
|
||||
guiLayout->setHorizontalSpacing(20);
|
||||
guiLayout->setVerticalSpacing(10);
|
||||
|
||||
QComboBox* themeSelect = new QComboBox();
|
||||
themeSelect->addItem(tr("System"));
|
||||
themeSelect->addItem(tr("Light"));
|
||||
themeSelect->addItem(tr("Dark"));
|
||||
themeSelect->addItem(tr("Greetings Cat"));
|
||||
themeSelect->addItem(tr("Cream"));
|
||||
themeSelect->setCurrentIndex(static_cast<int>(currentTheme));
|
||||
themeSelect->setCurrentIndex(static_cast<int>(config.frontendSettings.theme));
|
||||
connect(themeSelect, &QComboBox::currentIndexChanged, this, [&](int index) {
|
||||
config.frontendSettings.theme = static_cast<Theme>(index);
|
||||
setTheme(static_cast<Theme>(index));
|
||||
|
||||
themeSelect->setGeometry(40, 40, 100, 50);
|
||||
themeSelect->show();
|
||||
connect(themeSelect, &QComboBox::currentIndexChanged, this, [&](int index) { setTheme(static_cast<Theme>(index)); });
|
||||
updateConfig();
|
||||
});
|
||||
guiLayout->addRow(tr("Color theme"), themeSelect);
|
||||
|
||||
QComboBox* iconSelect = new QComboBox();
|
||||
iconSelect->addItem(tr("Happy panda"));
|
||||
iconSelect->addItem(tr("Happy panda (colourful)"));
|
||||
iconSelect->addItem(tr("Sleepy panda"));
|
||||
iconSelect->addItem(tr("Cow panda"));
|
||||
iconSelect->setCurrentIndex(static_cast<int>(config.frontendSettings.icon));
|
||||
|
||||
connect(iconSelect, &QComboBox::currentIndexChanged, this, [&](int index) {
|
||||
config.frontendSettings.icon = static_cast<WindowIcon>(index);
|
||||
setIcon(static_cast<WindowIcon>(index));
|
||||
|
||||
updateConfig();
|
||||
});
|
||||
guiLayout->addRow(tr("Window icon"), iconSelect);
|
||||
|
||||
QCheckBox* showAppVersion = new QCheckBox(tr("Show version on window title"));
|
||||
connectCheckbox(showAppVersion, config.windowSettings.showAppVersion);
|
||||
guiLayout->addRow(showAppVersion);
|
||||
|
||||
QCheckBox* rememberPosition = new QCheckBox(tr("Remember window position"));
|
||||
connectCheckbox(rememberPosition, config.windowSettings.rememberPosition);
|
||||
guiLayout->addRow(rememberPosition);
|
||||
|
||||
// General settings
|
||||
QGroupBox* genGroupBox = new QGroupBox(tr("General Settings"), this);
|
||||
QFormLayout* genLayout = new QFormLayout(genGroupBox);
|
||||
genLayout->setHorizontalSpacing(20);
|
||||
genLayout->setVerticalSpacing(10);
|
||||
|
||||
QLineEdit* defaultRomPath = new QLineEdit;
|
||||
defaultRomPath->setText(QString::fromStdU16String(config.defaultRomPath.u16string()));
|
||||
connect(defaultRomPath, &QLineEdit::textChanged, this, [&](const QString& text) {
|
||||
config.defaultRomPath = text.toStdString();
|
||||
updateConfig();
|
||||
});
|
||||
QPushButton* browseRomPath = new QPushButton(tr("Browse..."));
|
||||
browseRomPath->setAutoDefault(false);
|
||||
connect(browseRomPath, &QPushButton::pressed, this, [&, defaultRomPath]() {
|
||||
QString newPath = QFileDialog::getExistingDirectory(
|
||||
this, tr("Select Directory"), QString::fromStdU16String(config.defaultRomPath.u16string()),
|
||||
QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks
|
||||
);
|
||||
if (!newPath.isEmpty()) {
|
||||
defaultRomPath->setText(newPath);
|
||||
}
|
||||
});
|
||||
QHBoxLayout* romLayout = new QHBoxLayout;
|
||||
romLayout->setSpacing(4);
|
||||
romLayout->addWidget(defaultRomPath);
|
||||
romLayout->addWidget(browseRomPath);
|
||||
genLayout->addRow(tr("Default ROMs path"), romLayout);
|
||||
|
||||
QCheckBox* discordRpcEnabled = new QCheckBox(tr("Enable Discord RPC"));
|
||||
connectCheckbox(discordRpcEnabled, config.discordRpcEnabled);
|
||||
genLayout->addRow(discordRpcEnabled);
|
||||
|
||||
QCheckBox* usePortableBuild = new QCheckBox(tr("Use portable build"));
|
||||
connectCheckbox(usePortableBuild, config.usePortableBuild);
|
||||
genLayout->addRow(usePortableBuild);
|
||||
|
||||
QCheckBox* printAppVersion = new QCheckBox(tr("Print version in console output"));
|
||||
connectCheckbox(printAppVersion, config.printAppVersion);
|
||||
genLayout->addRow(printAppVersion);
|
||||
|
||||
// Graphics settings
|
||||
QGroupBox* gpuGroupBox = new QGroupBox(tr("Graphics Settings"), this);
|
||||
QFormLayout* gpuLayout = new QFormLayout(gpuGroupBox);
|
||||
gpuLayout->setHorizontalSpacing(20);
|
||||
gpuLayout->setVerticalSpacing(10);
|
||||
|
||||
QComboBox* rendererType = new QComboBox;
|
||||
rendererType->addItem(tr("Null"));
|
||||
rendererType->addItem(tr("OpenGL"));
|
||||
rendererType->addItem(tr("Vulkan"));
|
||||
rendererType->setCurrentIndex(static_cast<int>(config.rendererType));
|
||||
connect(rendererType, &QComboBox::currentIndexChanged, this, [&](int index) {
|
||||
config.rendererType = static_cast<RendererType>(index);
|
||||
updateConfig();
|
||||
});
|
||||
gpuLayout->addRow(tr("GPU renderer"), rendererType);
|
||||
|
||||
QCheckBox* enableRenderdoc = new QCheckBox(tr("Enable Renderdoc"));
|
||||
connectCheckbox(enableRenderdoc, config.enableRenderdoc);
|
||||
gpuLayout->addRow(enableRenderdoc);
|
||||
|
||||
QCheckBox* shaderJitEnabled = new QCheckBox(tr("Enable shader JIT"));
|
||||
connectCheckbox(shaderJitEnabled, config.shaderJitEnabled);
|
||||
gpuLayout->addRow(shaderJitEnabled);
|
||||
|
||||
QCheckBox* vsyncEnabled = new QCheckBox(tr("Enable VSync"));
|
||||
connectCheckbox(vsyncEnabled, config.vsyncEnabled);
|
||||
gpuLayout->addRow(vsyncEnabled);
|
||||
|
||||
QCheckBox* useUbershaders = new QCheckBox(tr("Use ubershaders (No stutter, maybe slower)"));
|
||||
connectCheckbox(useUbershaders, config.useUbershaders);
|
||||
gpuLayout->addRow(useUbershaders);
|
||||
|
||||
QCheckBox* accurateShaderMul = new QCheckBox(tr("Accurate shader multiplication"));
|
||||
connectCheckbox(accurateShaderMul, config.accurateShaderMul);
|
||||
gpuLayout->addRow(accurateShaderMul);
|
||||
|
||||
QCheckBox* accelerateShaders = new QCheckBox(tr("Accelerate shaders"));
|
||||
connectCheckbox(accelerateShaders, config.accelerateShaders);
|
||||
gpuLayout->addRow(accelerateShaders);
|
||||
|
||||
QCheckBox* forceShadergenForLights = new QCheckBox(tr("Force shadergen when rendering lights"));
|
||||
connectCheckbox(forceShadergenForLights, config.forceShadergenForLights);
|
||||
gpuLayout->addRow(forceShadergenForLights);
|
||||
|
||||
QSpinBox* lightShadergenThreshold = new QSpinBox;
|
||||
lightShadergenThreshold->setRange(1, 8);
|
||||
lightShadergenThreshold->setValue(config.lightShadergenThreshold);
|
||||
connect(lightShadergenThreshold, &QSpinBox::valueChanged, this, [&](int value) {
|
||||
config.lightShadergenThreshold = static_cast<int>(value);
|
||||
updateConfig();
|
||||
});
|
||||
gpuLayout->addRow(tr("Light threshold for forcing shadergen"), lightShadergenThreshold);
|
||||
|
||||
// Audio settings
|
||||
QGroupBox* spuGroupBox = new QGroupBox(tr("Audio Settings"), this);
|
||||
QFormLayout* audioLayout = new QFormLayout(spuGroupBox);
|
||||
audioLayout->setHorizontalSpacing(20);
|
||||
audioLayout->setVerticalSpacing(10);
|
||||
|
||||
QComboBox* dspType = new QComboBox;
|
||||
dspType->addItem(tr("Null"));
|
||||
dspType->addItem(tr("LLE"));
|
||||
dspType->addItem(tr("HLE"));
|
||||
dspType->setCurrentIndex(static_cast<int>(config.dspType));
|
||||
connect(dspType, &QComboBox::currentIndexChanged, this, [&](int index) {
|
||||
config.dspType = static_cast<Audio::DSPCore::Type>(index);
|
||||
updateConfig();
|
||||
});
|
||||
audioLayout->addRow(tr("DSP emulation"), dspType);
|
||||
|
||||
QCheckBox* audioEnabled = new QCheckBox(tr("Enable audio"));
|
||||
connectCheckbox(audioEnabled, config.audioEnabled);
|
||||
audioLayout->addRow(audioEnabled);
|
||||
|
||||
QCheckBox* aacEnabled = new QCheckBox(tr("Enable AAC audio"));
|
||||
connectCheckbox(aacEnabled, config.aacEnabled);
|
||||
audioLayout->addRow(aacEnabled);
|
||||
|
||||
QCheckBox* printDSPFirmware = new QCheckBox(tr("Print DSP firmware"));
|
||||
connectCheckbox(printDSPFirmware, config.printDSPFirmware);
|
||||
audioLayout->addRow(printDSPFirmware);
|
||||
|
||||
QCheckBox* muteAudio = new QCheckBox(tr("Mute audio device"));
|
||||
connectCheckbox(muteAudio, config.audioDeviceConfig.muteAudio);
|
||||
audioLayout->addRow(muteAudio);
|
||||
|
||||
QSpinBox* volumeRaw = new QSpinBox();
|
||||
volumeRaw->setRange(0, 200);
|
||||
volumeRaw->setValue(config.audioDeviceConfig.volumeRaw* 100);
|
||||
connect(volumeRaw, &QSpinBox::valueChanged, this, [&](int value) {
|
||||
config.audioDeviceConfig.volumeRaw = static_cast<float>(value) / 100.0f;
|
||||
updateConfig();
|
||||
});
|
||||
audioLayout->addRow(tr("Audio device volume"), volumeRaw);
|
||||
|
||||
// Battery settings
|
||||
QGroupBox* batGroupBox = new QGroupBox(tr("Battery Settings"), this);
|
||||
QFormLayout* batLayout = new QFormLayout(batGroupBox);
|
||||
batLayout->setHorizontalSpacing(20);
|
||||
batLayout->setVerticalSpacing(10);
|
||||
|
||||
QSpinBox* batteryPercentage = new QSpinBox;
|
||||
batteryPercentage->setRange(1, 100);
|
||||
batteryPercentage->setValue(config.batteryPercentage);
|
||||
connect(batteryPercentage, &QSpinBox::valueChanged, this, [&](int value) {
|
||||
config.batteryPercentage = static_cast<int>(value);
|
||||
updateConfig();
|
||||
});
|
||||
batLayout->addRow(tr("Battery percentage"), batteryPercentage);
|
||||
|
||||
QCheckBox* chargerPlugged = new QCheckBox(tr("Charger plugged"));
|
||||
connectCheckbox(chargerPlugged, config.chargerPlugged);
|
||||
batLayout->addRow(chargerPlugged);
|
||||
|
||||
// SD Card settings
|
||||
QGroupBox* sdcGroupBox = new QGroupBox(tr("SD Card Settings"), this);
|
||||
QFormLayout* sdcLayout = new QFormLayout(sdcGroupBox);
|
||||
sdcLayout->setHorizontalSpacing(20);
|
||||
sdcLayout->setVerticalSpacing(10);
|
||||
|
||||
QCheckBox* sdCardInserted = new QCheckBox(tr("Enable virtual SD card"));
|
||||
connectCheckbox(sdCardInserted, config.sdCardInserted);
|
||||
sdcLayout->addRow(sdCardInserted);
|
||||
|
||||
QCheckBox* sdWriteProtected = new QCheckBox(tr("Write protect virtual SD card"));
|
||||
connectCheckbox(sdWriteProtected, config.sdWriteProtected);
|
||||
sdcLayout->addRow(sdWriteProtected);
|
||||
|
||||
// Add all our settings widgets to our widget list
|
||||
addWidget(guiGroupBox, tr("Interface"), ":/docs/img/sparkling_icon.png", tr("User Interface settings"));
|
||||
addWidget(genGroupBox, tr("General"), ":/docs/img/settings_icon.png", tr("General emulator settings"));
|
||||
addWidget(gpuGroupBox, tr("Graphics"), ":/docs/img/display_icon.png", tr("Graphics emulation and output settings"));
|
||||
addWidget(spuGroupBox, tr("Audio"), ":/docs/img/speaker_icon.png", tr("Audio emulation and output settings"));
|
||||
addWidget(batGroupBox, tr("Battery"), ":/docs/img/battery_icon.png", tr("Battery emulation settings"));
|
||||
addWidget(sdcGroupBox, tr("SD Card"), ":/docs/img/sdcard_icon.png", tr("SD Card emulation settings"));
|
||||
|
||||
widgetList->setCurrentRow(0);
|
||||
}
|
||||
|
||||
void ConfigWindow::setTheme(Theme theme) {
|
||||
currentTheme = theme;
|
||||
|
||||
switch (theme) {
|
||||
case Theme::Dark: {
|
||||
QApplication::setStyle(QStyleFactory::create("Fusion"));
|
||||
|
@ -119,4 +379,36 @@ void ConfigWindow::setTheme(Theme theme) {
|
|||
}
|
||||
}
|
||||
|
||||
ConfigWindow::~ConfigWindow() { delete themeSelect; }
|
||||
void ConfigWindow::setIcon(WindowIcon icon) {
|
||||
switch (icon) {
|
||||
case WindowIcon::Rsyn: updateIcon(":/docs/img/rsyn_icon.png"); break;
|
||||
case WindowIcon::Rnap: updateIcon(":/docs/img/rnap_icon.png"); break;
|
||||
case WindowIcon::Rcow: updateIcon(":/docs/img/rcow_icon.png"); break;
|
||||
|
||||
case WindowIcon::Rpog:
|
||||
default: updateIcon(":/docs/img/rpog_icon.png"); break;
|
||||
}
|
||||
}
|
||||
|
||||
void ConfigWindow::addWidget(QWidget* widget, QString title, QString icon, QString helpText) {
|
||||
const int index = widgetList->count();
|
||||
|
||||
QListWidgetItem* item = new QListWidgetItem(widgetList);
|
||||
item->setText(title);
|
||||
if (!icon.isEmpty()) {
|
||||
item->setIcon(QIcon::fromTheme(icon));
|
||||
}
|
||||
|
||||
widgetContainer->addWidget(widget);
|
||||
|
||||
if (index >= settingWidgetCount) {
|
||||
Helpers::panic("Qt: ConfigWindow::settingWidgetCount has not been updated correctly!");
|
||||
}
|
||||
helpTexts[index] = std::move(helpText);
|
||||
}
|
||||
|
||||
ConfigWindow::~ConfigWindow() {
|
||||
delete helpText;
|
||||
delete widgetList;
|
||||
delete widgetContainer;
|
||||
}
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
|
||||
MainWindow::MainWindow(QApplication* app, QWidget* parent) : QMainWindow(parent), keyboardMappings(InputMappings::defaultKeyboardMappings()) {
|
||||
setWindowTitle("Alber");
|
||||
setWindowIcon(QIcon(":/docs/img/rpog_icon.png"));
|
||||
|
||||
// Enable drop events for loading ROMs
|
||||
setAcceptDrops(true);
|
||||
|
@ -81,7 +80,6 @@ MainWindow::MainWindow(QApplication* app, QWidget* parent) : QMainWindow(parent)
|
|||
|
||||
// Set up misc objects
|
||||
aboutWindow = new AboutWindow(nullptr);
|
||||
configWindow = new ConfigWindow(this);
|
||||
cheatsEditor = new CheatsWindow(emu, {}, this);
|
||||
patchWindow = new PatchWindow(this);
|
||||
luaEditor = new TextEditorWindow(this, "script.lua", "");
|
||||
|
@ -92,6 +90,14 @@ MainWindow::MainWindow(QApplication* app, QWidget* parent) : QMainWindow(parent)
|
|||
shaderEditor->setText(emu->getRenderer()->getUbershader());
|
||||
}
|
||||
|
||||
configWindow = new ConfigWindow(
|
||||
[&]() {
|
||||
EmulatorMessage message{.type = MessageType::UpdateConfig};
|
||||
sendMessage(message);
|
||||
},
|
||||
[&](const QString& icon) { setWindowIcon(QIcon(icon)); }, emu->getConfig(), this
|
||||
);
|
||||
|
||||
auto args = QCoreApplication::arguments();
|
||||
if (args.size() > 1) {
|
||||
auto romPath = std::filesystem::current_path() / args.at(1).toStdU16String();
|
||||
|
@ -410,6 +416,14 @@ void MainWindow::dispatchMessage(const EmulatorMessage& message) {
|
|||
screen->resizeSurface(width, height);
|
||||
break;
|
||||
}
|
||||
|
||||
case MessageType::UpdateConfig:
|
||||
emu->getConfig() = configWindow->getConfig();
|
||||
emu->reloadSettings();
|
||||
|
||||
// Save new settings to disk
|
||||
emu->getConfig().save();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -23,6 +23,8 @@ namespace Renderdoc {
|
|||
};
|
||||
|
||||
static CaptureState captureState{CaptureState::Idle};
|
||||
static bool renderdocLoaded{false};
|
||||
|
||||
RENDERDOC_API_1_6_0* rdocAPI{};
|
||||
|
||||
void loadRenderdoc() {
|
||||
|
@ -73,6 +75,8 @@ namespace Renderdoc {
|
|||
}
|
||||
#endif
|
||||
if (rdocAPI) {
|
||||
renderdocLoaded = true;
|
||||
|
||||
// Disable default capture keys as they suppose to trigger present-to-present capturing
|
||||
// and it is not what we want
|
||||
rdocAPI->SetCaptureKeys(nullptr, 0);
|
||||
|
@ -115,5 +119,7 @@ namespace Renderdoc {
|
|||
rdocAPI->SetCaptureFilePathTemplate((path + '\\' + prefix).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
bool isLoaded() { return renderdocLoaded; }
|
||||
} // namespace Renderdoc
|
||||
#endif
|
Loading…
Add table
Add a link
Reference in a new issue