Merge pull request #305 from wheremyfoodat/rhappy

Add file picker to Qt frontend
This commit is contained in:
wheremyfoodat 2023-10-02 02:53:28 +03:00 committed by GitHub
commit 8d6c222db7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 67 additions and 14 deletions

View file

@ -5,7 +5,9 @@
#include <QMenuBar> #include <QMenuBar>
#include <QPalette> #include <QPalette>
#include <QtWidgets> #include <QtWidgets>
#include <atomic>
#include <thread> #include <thread>
#include <filesystem>
#include "emulator.hpp" #include "emulator.hpp"
#include "panda_qt/screen.hpp" #include "panda_qt/screen.hpp"
@ -24,13 +26,19 @@ class MainWindow : public QMainWindow {
Emulator* emu = nullptr; Emulator* emu = nullptr;
std::thread emuThread; std::thread emuThread;
std::atomic<bool> appRunning = true; // Is the application itself running?
std::atomic<bool> needToLoadROM = false;
std::filesystem::path romToLoad = "";
ScreenWidget screen;
QComboBox* themeSelect = nullptr; QComboBox* themeSelect = nullptr;
QMenuBar* menuBar = nullptr; QMenuBar* menuBar = nullptr;
ScreenWidget screen;
Theme currentTheme; Theme currentTheme;
void setTheme(Theme theme); void setTheme(Theme theme);
void swapEmuBuffer(); void swapEmuBuffer();
void emuThreadMainLoop();
void selectROM();
// Tracks whether we are using an OpenGL-backed renderer or a Vulkan-backed renderer // Tracks whether we are using an OpenGL-backed renderer or a Vulkan-backed renderer
bool usingGL = false; bool usingGL = false;

View file

@ -1,18 +1,28 @@
#include "panda_qt/main_window.hpp" #include "panda_qt/main_window.hpp"
#include <QFileDialog>
#include <cstdio>
MainWindow::MainWindow(QApplication* app, QWidget* parent) : QMainWindow(parent), screen(this) { MainWindow::MainWindow(QApplication* app, QWidget* parent) : QMainWindow(parent), screen(this) {
setWindowTitle("Alber"); setWindowTitle("Alber");
// Enable drop events for loading ROMs // Enable drop events for loading ROMs
setAcceptDrops(true); setAcceptDrops(true);
resize(400, 240 * 2); resize(800, 240 * 4);
screen.show(); screen.show();
appRunning = true;
// Set our menu bar up // Set our menu bar up
menuBar = new QMenuBar(this); menuBar = new QMenuBar(this);
setMenuBar(menuBar); setMenuBar(menuBar);
auto pandaMenu = menuBar->addMenu(tr("PANDA")); auto fileMenu = menuBar->addMenu(tr("File"));
auto pandaAction = pandaMenu->addAction(tr("panda...")); auto pandaAction = fileMenu->addAction(tr("panda..."));
connect(pandaAction, &QAction::triggered, this, &MainWindow::selectROM);
auto emulationMenu = menuBar->addMenu(tr("Emulation"));
auto helpMenu = menuBar->addMenu(tr("Help"));
auto aboutMenu = menuBar->addMenu(tr("About"));
// Set up theme selection // Set up theme selection
setTheme(Theme::Dark); setTheme(Theme::Dark);
@ -30,7 +40,7 @@ MainWindow::MainWindow(QApplication* app, QWidget* parent) : QMainWindow(parent)
emu->setOutputSize(screen.surfaceWidth, screen.surfaceHeight); emu->setOutputSize(screen.surfaceWidth, screen.surfaceHeight);
// The emulator graphics context for the thread should be initialized in the emulator thread due to how GL contexts work // The emulator graphics context for the thread should be initialized in the emulator thread due to how GL contexts work
emuThread = std::thread([&]() { emuThread = std::thread([this]() {
const RendererType rendererType = emu->getConfig().rendererType; const RendererType rendererType = emu->getConfig().rendererType;
usingGL = (rendererType == RendererType::OpenGL || rendererType == RendererType::Software || rendererType == RendererType::Null); usingGL = (rendererType == RendererType::OpenGL || rendererType == RendererType::Software || rendererType == RendererType::Null);
usingVk = (rendererType == RendererType::Vulkan); usingVk = (rendererType == RendererType::Vulkan);
@ -48,16 +58,29 @@ MainWindow::MainWindow(QApplication* app, QWidget* parent) : QMainWindow(parent)
Helpers::panic("Unsupported graphics backend for Qt frontend!"); Helpers::panic("Unsupported graphics backend for Qt frontend!");
} }
bool success = emu->loadROM("OoT.3ds"); emuThreadMainLoop();
if (!success) { });
Helpers::panic("Failed to load ROM"); }
void MainWindow::emuThreadMainLoop() {
while (appRunning) {
if (needToLoadROM.load()) {
bool success = emu->loadROM(romToLoad);
if (!success) {
printf("Failed to load ROM");
}
needToLoadROM.store(false, std::memory_order::seq_cst);
} }
while (true) { emu->runFrame();
emu->runFrame(); swapEmuBuffer();
swapEmuBuffer(); }
}
}); // Unbind GL context if we're using GL, otherwise some setups seem to be unable to join this thread
if (usingGL) {
screen.getGLContext()->DoneCurrent();
}
} }
void MainWindow::swapEmuBuffer() { void MainWindow::swapEmuBuffer() {
@ -68,8 +91,30 @@ void MainWindow::swapEmuBuffer() {
} }
} }
void MainWindow::selectROM() {
// Are we already waiting for a ROM to be loaded? Then complain about it!
if (needToLoadROM.load()) {
QMessageBox::warning(this, tr("Already loading ROM"), tr("Panda3DS is already busy loading a ROM, please wait"));
return;
}
auto path =
QFileDialog::getOpenFileName(this, tr("Select 3DS ROM to load"), "", tr("Nintendo 3DS ROMs (*.3ds *.cci *.cxi *.app *.3dsx *.elf *.axf)"));
if (!path.isEmpty()) {
romToLoad = path.toStdU16String();
needToLoadROM.store(true, std::memory_order_seq_cst);
}
}
// Cleanup when the main window closes // Cleanup when the main window closes
MainWindow::~MainWindow() { MainWindow::~MainWindow() {
appRunning = false; // Set our running atomic to false in order to make the emulator thread stop, and join it
if (emuThread.joinable()) {
emuThread.join();
}
delete emu; delete emu;
delete menuBar; delete menuBar;
delete themeSelect; delete themeSelect;

View file

@ -20,7 +20,7 @@
#ifdef PANDA3DS_ENABLE_OPENGL #ifdef PANDA3DS_ENABLE_OPENGL
ScreenWidget::ScreenWidget(QWidget* parent) : QWidget(parent) { ScreenWidget::ScreenWidget(QWidget* parent) : QWidget(parent) {
// Create a native window for use with our graphics API of choice // Create a native window for use with our graphics API of choice
resize(400, 240 * 2); resize(800, 240 * 4);
setAutoFillBackground(false); setAutoFillBackground(false);
setAttribute(Qt::WA_NativeWindow, true); setAttribute(Qt::WA_NativeWindow, true);