Qt6 frontend
Reviewed-on: #1 Co-authored-by: iris <iris.kaizen@pm.me> Co-committed-by: iris <iris.kaizen@pm.me>
This commit was merged in pull request #1.
This commit is contained in:
+174
-341
@@ -1,358 +1,191 @@
|
||||
#include <KaizenGui.hpp>
|
||||
#include <backend/Core.hpp>
|
||||
#include <ImGuiImpl/GUI.hpp>
|
||||
#include <ImGuiImpl/ProgressIndicators.hpp>
|
||||
#include <ImGuiImpl/StatusBar.hpp>
|
||||
#include <QMenuBar>
|
||||
#include <QMenu>
|
||||
#include <QMessageBox>
|
||||
#include <QCoreApplication>
|
||||
#include <QStatusBar>
|
||||
#include <QTimer>
|
||||
#include <QMimeData>
|
||||
#include <resources/gamecontrollerdb.h>
|
||||
#include <Options.hpp>
|
||||
#include <Scheduler.hpp>
|
||||
|
||||
KaizenGui::KaizenGui() noexcept :
|
||||
window("Kaizen " KAIZEN_VERSION_STR, 1280, 720), settingsWindow(window), vulkanWidget(window.getHandle()),
|
||||
emuThread(fpsCounter, settingsWindow) {
|
||||
gui::Initialize(n64::Core::GetInstance().parallel.wsi, window.getHandle());
|
||||
KaizenGui::KaizenGui() noexcept : QMainWindow(nullptr), settings(QSettings::UserScope) {
|
||||
SDL_InitSubSystem(SDL_INIT_GAMEPAD);
|
||||
|
||||
SDL_AddGamepadMapping(gamecontrollerdb_str);
|
||||
hide();
|
||||
|
||||
restoreGeometry(settings.value("geometry").toByteArray());
|
||||
restoreState(settings.value("windowState").toByteArray());
|
||||
|
||||
vulkanWidget = new RenderWidget();
|
||||
vulkanWidget->hide();
|
||||
|
||||
cpuTypeLabel = new QLabel("Interpreter");
|
||||
if (Options::GetCpuType() == 1)
|
||||
cpuTypeLabel->setText("Cached Interpreter");
|
||||
|
||||
idleSkipLabel = new QLabel("Idle skipping");
|
||||
if (!Options::GetIdleSkip())
|
||||
idleSkipLabel->hide();
|
||||
|
||||
fpsLabel = new QLabel("Not running");
|
||||
|
||||
statusBar()->addWidget(fpsLabel);
|
||||
statusBar()->addWidget(cpuTypeLabel);
|
||||
statusBar()->addWidget(idleSkipLabel);
|
||||
|
||||
setWindowTitle("Kaizen " KAIZEN_VERSION_STR);
|
||||
setMinimumSize(640, 480);
|
||||
setCentralWidget(vulkanWidget);
|
||||
|
||||
setAcceptDrops(true);
|
||||
|
||||
statusBarTimer = new QTimer();
|
||||
statusBarTimer->setInterval(1000);
|
||||
|
||||
connect(statusBarTimer, &QTimer::timeout, this, [&] {
|
||||
pause->setText("Pause");
|
||||
fpsLabel->setText(std::format("FPS: {:.2f}", 1000.f / elapsed).c_str());
|
||||
if (core.pause) {
|
||||
pause->setText("Resume");
|
||||
fpsLabel->setText("Paused");
|
||||
}
|
||||
|
||||
if (!core.romLoaded) {
|
||||
pause->setDisabled(true);
|
||||
reset->setDisabled(true);
|
||||
stop->setDisabled(true);
|
||||
fpsLabel->setText("Not running");
|
||||
}
|
||||
});
|
||||
|
||||
statusBarTimer->start();
|
||||
|
||||
auto fileMenu = menuBar()->addMenu("File");
|
||||
auto open = fileMenu->addAction("Open");
|
||||
connect(open, &QAction::triggered, this, [&] {
|
||||
auto fileToLoad =
|
||||
QFileDialog::getOpenFileName(this, "Select a Nintendo 64 ROM", QDir::currentPath(),
|
||||
"N64 ROM (*.z64 *.n64 *.v64)", nullptr, QFileDialog::DontUseNativeDialog)
|
||||
.toStdString();
|
||||
if (!fileToLoad.empty())
|
||||
LoadROM(fileToLoad);
|
||||
});
|
||||
|
||||
auto exit = fileMenu->addAction("Exit");
|
||||
connect(exit, &QAction::triggered, this, [&] { Scheduler::GetInstance().EnqueueRelative(0, STOP); });
|
||||
connect(exit, &QAction::triggered, this, &QMainWindow::close);
|
||||
auto emulationMenu = menuBar()->addMenu("Emulation");
|
||||
auto settingsMenu = emulationMenu->addAction("Settings");
|
||||
settingsWindow = new SettingsWindow();
|
||||
connect(settingsMenu, &QAction::triggered, settingsWindow, &SettingsWindow::show);
|
||||
|
||||
connect(settingsWindow->cpu, &CPUSettings::cpuTypeChanged, this, [&] {
|
||||
cpuTypeLabel->setText("Cached Interpreter");
|
||||
if (Options::GetCpuType() == 0)
|
||||
cpuTypeLabel->setText("Interpreter");
|
||||
});
|
||||
|
||||
connect(settingsWindow->cpu, &CPUSettings::idleSkipChanged, this, [&] {
|
||||
idleSkipLabel->show();
|
||||
if (!Options::GetIdleSkip())
|
||||
idleSkipLabel->hide();
|
||||
});
|
||||
|
||||
emulationMenu->addSeparator();
|
||||
|
||||
pause->setDisabled(true);
|
||||
emulationMenu->addAction(pause);
|
||||
connect(pause, &QAction::triggered, this, [&] {
|
||||
if (!core.pause)
|
||||
Scheduler::GetInstance().EnqueueRelative(0, PAUSE);
|
||||
else
|
||||
core.TogglePause();
|
||||
});
|
||||
|
||||
reset->setDisabled(true);
|
||||
emulationMenu->addAction(reset);
|
||||
connect(reset, &QAction::triggered, this, [&] { Scheduler::GetInstance().EnqueueRelative(0, RESET); });
|
||||
|
||||
stop->setDisabled(true);
|
||||
emulationMenu->addAction(stop);
|
||||
connect(stop, &QAction::triggered, this, [&] {
|
||||
Scheduler::GetInstance().EnqueueRelative(0, STOP);
|
||||
vulkanWidget->show();
|
||||
});
|
||||
|
||||
auto helpMenu = menuBar()->addMenu("Help");
|
||||
auto about = helpMenu->addAction("About");
|
||||
connect(about, &QAction::triggered, this, [&] {
|
||||
auto text = std::format("<p>Kaizen is a Nintendo 64 emulator that strives<br>"
|
||||
"to offer a friendly user experience and compatibility.<br>"
|
||||
"Kaizen is licensed under the BSD 3-clause license.<br>"
|
||||
"Nintendo 64 is a registered trademark of Nintendo Co., Ltd.</p><hr>"
|
||||
"Kaizen {}{}",
|
||||
KAIZEN_USE_HASH ? "dev build " : "", KAIZEN_VERSION_STR);
|
||||
|
||||
QMessageBox::about(this, "About", text.c_str());
|
||||
});
|
||||
|
||||
show();
|
||||
|
||||
emuThread = QThread::create([&] {
|
||||
core.parallel.Init(vulkanWidget->wsiPlatform, vulkanWidget->windowInfo, vulkanWidget->qtVkInstanceFactory.get(),
|
||||
core.GetMem().GetRDRAMPtr());
|
||||
while (!emuThread->isInterruptionRequested()) {
|
||||
if (!core.romLoaded) {
|
||||
core.parallel.UpdateScreen<false>();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!core.pause) {
|
||||
auto timeStart = SDL_GetTicks();
|
||||
core.Run();
|
||||
core.parallel.UpdateScreen<true>();
|
||||
elapsed = SDL_GetTicks() - timeStart;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
emuThread->start();
|
||||
}
|
||||
|
||||
KaizenGui::~KaizenGui() {
|
||||
gui::Cleanup();
|
||||
SDL_Quit();
|
||||
}
|
||||
|
||||
void KaizenGui::QueryDevices(const SDL_Event &event) {
|
||||
switch (event.type) {
|
||||
case SDL_EVENT_GAMEPAD_ADDED:
|
||||
if (!gamepad) {
|
||||
const auto index = event.gdevice.which;
|
||||
|
||||
gamepad = SDL_OpenGamepad(index);
|
||||
info("Found controller!");
|
||||
info("Name: {}", SDL_GetGamepadName(gamepad));
|
||||
info("Vendor: {}", SDL_GetGamepadVendor(gamepad));
|
||||
}
|
||||
break;
|
||||
case SDL_EVENT_GAMEPAD_REMOVED:
|
||||
if (gamepad)
|
||||
SDL_CloseGamepad(gamepad);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void KaizenGui::HandleInput(const SDL_Event &event) {
|
||||
const n64::Core &core = n64::Core::GetInstance();
|
||||
n64::PIF &pif = n64::Core::GetMem().mmio.si.pif;
|
||||
switch (event.type) {
|
||||
case SDL_EVENT_GAMEPAD_AXIS_MOTION:
|
||||
if (!gamepad)
|
||||
break;
|
||||
{
|
||||
pif.UpdateButton(0, n64::Controller::Key::Z,
|
||||
SDL_GetGamepadAxis(gamepad, SDL_GAMEPAD_AXIS_LEFT_TRIGGER) == SDL_JOYSTICK_AXIS_MAX);
|
||||
pif.UpdateButton(0, n64::Controller::Key::CUp,
|
||||
SDL_GetGamepadAxis(gamepad, SDL_GAMEPAD_AXIS_RIGHTY) <= -127);
|
||||
pif.UpdateButton(0, n64::Controller::Key::CDown,
|
||||
SDL_GetGamepadAxis(gamepad, SDL_GAMEPAD_AXIS_RIGHTY) >= 127);
|
||||
pif.UpdateButton(0, n64::Controller::Key::CLeft,
|
||||
SDL_GetGamepadAxis(gamepad, SDL_GAMEPAD_AXIS_RIGHTX) <= -127);
|
||||
pif.UpdateButton(0, n64::Controller::Key::CRight,
|
||||
SDL_GetGamepadAxis(gamepad, SDL_GAMEPAD_AXIS_RIGHTX) >= 127);
|
||||
|
||||
float xclamped = SDL_GetGamepadAxis(gamepad, SDL_GAMEPAD_AXIS_LEFTX);
|
||||
if (xclamped < 0) {
|
||||
xclamped /= static_cast<float>(std::abs(SDL_JOYSTICK_AXIS_MAX));
|
||||
} else {
|
||||
xclamped /= SDL_JOYSTICK_AXIS_MAX;
|
||||
}
|
||||
|
||||
xclamped *= 86;
|
||||
|
||||
float yclamped = SDL_GetGamepadAxis(gamepad, SDL_GAMEPAD_AXIS_LEFTY);
|
||||
if (yclamped < 0) {
|
||||
yclamped /= static_cast<float>(std::abs(SDL_JOYSTICK_AXIS_MIN));
|
||||
} else {
|
||||
yclamped /= SDL_JOYSTICK_AXIS_MAX;
|
||||
}
|
||||
|
||||
yclamped *= 86;
|
||||
|
||||
pif.UpdateAxis(0, n64::Controller::Axis::Y, static_cast<s8>(-yclamped));
|
||||
pif.UpdateAxis(0, n64::Controller::Axis::X, static_cast<s8>(xclamped));
|
||||
}
|
||||
break;
|
||||
case SDL_EVENT_GAMEPAD_BUTTON_DOWN:
|
||||
case SDL_EVENT_GAMEPAD_BUTTON_UP:
|
||||
if (!gamepad)
|
||||
break;
|
||||
|
||||
pif.UpdateButton(0, n64::Controller::Key::A, SDL_GetGamepadButton(gamepad, SDL_GAMEPAD_BUTTON_SOUTH));
|
||||
pif.UpdateButton(0, n64::Controller::Key::B, SDL_GetGamepadButton(gamepad, SDL_GAMEPAD_BUTTON_WEST));
|
||||
pif.UpdateButton(0, n64::Controller::Key::Start, SDL_GetGamepadButton(gamepad, SDL_GAMEPAD_BUTTON_START));
|
||||
pif.UpdateButton(0, n64::Controller::Key::DUp, SDL_GetGamepadButton(gamepad, SDL_GAMEPAD_BUTTON_DPAD_UP));
|
||||
pif.UpdateButton(0, n64::Controller::Key::DDown, SDL_GetGamepadButton(gamepad, SDL_GAMEPAD_BUTTON_DPAD_DOWN));
|
||||
pif.UpdateButton(0, n64::Controller::Key::DLeft, SDL_GetGamepadButton(gamepad, SDL_GAMEPAD_BUTTON_DPAD_LEFT));
|
||||
pif.UpdateButton(0, n64::Controller::Key::DRight, SDL_GetGamepadButton(gamepad, SDL_GAMEPAD_BUTTON_DPAD_RIGHT));
|
||||
pif.UpdateButton(0, n64::Controller::Key::LT, SDL_GetGamepadButton(gamepad, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER));
|
||||
pif.UpdateButton(0, n64::Controller::Key::RT, SDL_GetGamepadButton(gamepad, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER));
|
||||
break;
|
||||
case SDL_EVENT_KEY_DOWN:
|
||||
case SDL_EVENT_KEY_UP:
|
||||
{
|
||||
const auto keys = SDL_GetKeyboardState(nullptr);
|
||||
if ((keys[SDL_SCANCODE_LCTRL] || keys[SDL_SCANCODE_RCTRL]) && keys[SDL_SCANCODE_O]) {
|
||||
fileDialogOpen = true;
|
||||
}
|
||||
|
||||
fastForward = keys[SDL_SCANCODE_SPACE];
|
||||
if (!unlockFramerate)
|
||||
core.parallel.SetFramerateUnlocked(fastForward);
|
||||
|
||||
if (core.romLoaded) {
|
||||
if (keys[SDL_SCANCODE_P]) {
|
||||
emuThread.TogglePause();
|
||||
}
|
||||
|
||||
if (keys[SDL_SCANCODE_R]) {
|
||||
emuThread.Reset();
|
||||
}
|
||||
|
||||
if (keys[SDL_SCANCODE_Q]) {
|
||||
emuThread.Stop();
|
||||
}
|
||||
}
|
||||
|
||||
if (gamepad)
|
||||
break;
|
||||
|
||||
pif.UpdateButton(0, n64::Controller::Key::Z, keys[SDL_SCANCODE_Z]);
|
||||
pif.UpdateButton(0, n64::Controller::Key::CUp, keys[SDL_SCANCODE_HOME]);
|
||||
pif.UpdateButton(0, n64::Controller::Key::CDown, keys[SDL_SCANCODE_END]);
|
||||
pif.UpdateButton(0, n64::Controller::Key::CLeft, keys[SDL_SCANCODE_DELETE]);
|
||||
pif.UpdateButton(0, n64::Controller::Key::CRight, keys[SDL_SCANCODE_PAGEDOWN]);
|
||||
pif.UpdateButton(0, n64::Controller::Key::A, keys[SDL_SCANCODE_X]);
|
||||
pif.UpdateButton(0, n64::Controller::Key::B, keys[SDL_SCANCODE_C]);
|
||||
pif.UpdateButton(0, n64::Controller::Key::Start, keys[SDL_SCANCODE_RETURN]);
|
||||
pif.UpdateButton(0, n64::Controller::Key::DUp, keys[SDL_SCANCODE_I]);
|
||||
pif.UpdateButton(0, n64::Controller::Key::DDown, keys[SDL_SCANCODE_K]);
|
||||
pif.UpdateButton(0, n64::Controller::Key::DLeft, keys[SDL_SCANCODE_J]);
|
||||
pif.UpdateButton(0, n64::Controller::Key::DRight, keys[SDL_SCANCODE_L]);
|
||||
pif.UpdateButton(0, n64::Controller::Key::LT, keys[SDL_SCANCODE_A]);
|
||||
pif.UpdateButton(0, n64::Controller::Key::RT, keys[SDL_SCANCODE_S]);
|
||||
|
||||
float x = 0, y = 0;
|
||||
|
||||
if (keys[SDL_SCANCODE_UP])
|
||||
y = 86;
|
||||
if (keys[SDL_SCANCODE_DOWN])
|
||||
y = -86;
|
||||
if (keys[SDL_SCANCODE_LEFT])
|
||||
x = -86;
|
||||
if (keys[SDL_SCANCODE_RIGHT])
|
||||
x = 86;
|
||||
|
||||
pif.UpdateAxis(0, n64::Controller::Axis::X, x);
|
||||
pif.UpdateAxis(0, n64::Controller::Axis::Y, y);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void KaizenGui::RenderUI() {
|
||||
n64::Core &core = n64::Core::GetInstance();
|
||||
gui::StartFrame();
|
||||
|
||||
if (ImGui::BeginMainMenuBar()) {
|
||||
if (ImGui::BeginMenu("File")) {
|
||||
if (ImGui::MenuItem("Open", "Ctrl-O")) {
|
||||
fileDialogOpen = true;
|
||||
}
|
||||
if (ImGui::MenuItem("Exit")) {
|
||||
quit = true;
|
||||
emuThread.Stop();
|
||||
}
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
if (ImGui::BeginMenu("Emulation")) {
|
||||
ImGui::BeginDisabled(!core.romLoaded);
|
||||
|
||||
if (ImGui::MenuItem(core.pause ? "Resume" : "Pause", "P")) {
|
||||
emuThread.TogglePause();
|
||||
}
|
||||
|
||||
if (ImGui::MenuItem("Reset", "R")) {
|
||||
emuThread.Reset();
|
||||
}
|
||||
|
||||
if (ImGui::MenuItem("Stop", "Q")) {
|
||||
emuThread.Stop();
|
||||
core.romLoaded = false;
|
||||
}
|
||||
|
||||
if (ImGui::Checkbox("Unlock framerate", &unlockFramerate)) {
|
||||
core.parallel.SetFramerateUnlocked(unlockFramerate);
|
||||
}
|
||||
|
||||
if (ImGui::MenuItem("Open Debugger")) {
|
||||
debugger.Open();
|
||||
}
|
||||
|
||||
ImGui::EndDisabled();
|
||||
|
||||
if (ImGui::MenuItem("Options")) {
|
||||
settingsWindow.isOpen = true;
|
||||
}
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
if (ImGui::BeginMenu("Help")) {
|
||||
if (ImGui::MenuItem("About")) {
|
||||
aboutOpen = true;
|
||||
}
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
ImGui::EndMainMenuBar();
|
||||
}
|
||||
|
||||
if (settingsWindow.isOpen) {
|
||||
ImGui::OpenPopup("Settings", ImGuiPopupFlags_None);
|
||||
}
|
||||
|
||||
if (aboutOpen) {
|
||||
ImGui::OpenPopup("About Kaizen");
|
||||
}
|
||||
|
||||
settingsWindow.render();
|
||||
debugger.render();
|
||||
|
||||
const ImVec2 center = ImGui::GetMainViewport()->GetCenter();
|
||||
ImGui::SetNextWindowPos(center, ImGuiCond_Appearing, ImVec2(0.5f, 0.5f));
|
||||
|
||||
if (ImGui::BeginPopupModal("About Kaizen", &aboutOpen, ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||
ImGui::Text("Kaizen is a Nintendo 64 emulator that strives");
|
||||
ImGui::Text("to offer a friendly user experience and compatibility.");
|
||||
ImGui::Text("Kaizen is licensed under the BSD 3-clause license.");
|
||||
ImGui::Text("Nintendo 64 is a registered trademark of Nintendo Co., Ltd.");
|
||||
ImGui::Separator();
|
||||
ImGui::Text("Kaizen %s%s", KAIZEN_USE_HASH ? "dev build " : "", KAIZEN_VERSION_STR);
|
||||
ImGui::Separator();
|
||||
if (ImGui::Button("OK")) {
|
||||
aboutOpen = false;
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
ImGui::SetNextWindowPos(center, ImGuiCond_Appearing, ImVec2(0.5f, 0.5f));
|
||||
|
||||
if (ImGui::BeginMainStatusBar()) {
|
||||
ImGui::Text("FPS: %.2f", ImGui::GetIO().Framerate);
|
||||
ImGui::EndMainStatusBar();
|
||||
}
|
||||
|
||||
if (shouldDisplaySpinner) {
|
||||
ImGui::SetNextWindowPos({static_cast<float>(width) * 0.5f, static_cast<float>(height) * 0.5f}, 0,
|
||||
ImVec2(0.5f, 0.5f));
|
||||
ImGui::PushStyleColor(ImGuiCol_WindowBg, IM_COL32_BLACK_TRANS);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
|
||||
|
||||
ImGui::Begin("##spinnerContainer", nullptr, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoDecoration);
|
||||
|
||||
ImGui::Spinner("##spinner", 10.f, 4.f, ImGui::GetColorU32(ImGui::GetStyle().Colors[ImGuiCol_TitleBgActive]));
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGui::PushFont(nullptr, ImGui::GetStyle().FontSizeBase * 2.f);
|
||||
ImGui::Text("Loading \"%s\"...", fs::path(fileToLoad).filename().string().c_str());
|
||||
ImGui::PopFont();
|
||||
|
||||
ImGui::End();
|
||||
|
||||
ImGui::PopStyleVar();
|
||||
ImGui::PopStyleColor();
|
||||
}
|
||||
|
||||
ImGui::Render();
|
||||
if (ImGui::GetIO().ConfigFlags & ImGuiConfigFlags_ViewportsEnable) {
|
||||
ImGui::UpdatePlatformWindows();
|
||||
ImGui::RenderPlatformWindowsDefault();
|
||||
}
|
||||
|
||||
if (fileDialogOpen) {
|
||||
fileDialogOpen = false;
|
||||
constexpr SDL_DialogFileFilter filters[] = {{"All files", "*"},
|
||||
{"Nintendo 64 executable", "n64;z64;v64"},
|
||||
{"Nintendo 64 executable archive", "rar;tar;zip;7z"}};
|
||||
SDL_ShowOpenFileDialog(
|
||||
[](void *userdata, const char *const *filelist, int) {
|
||||
auto kaizen = static_cast<KaizenGui *>(userdata);
|
||||
|
||||
if (!filelist) {
|
||||
panic("An error occured: {}", SDL_GetError());
|
||||
}
|
||||
|
||||
if (!*filelist) {
|
||||
warn("The user did not select any file.");
|
||||
warn("Most likely, the dialog was canceled.");
|
||||
return;
|
||||
}
|
||||
|
||||
kaizen->fileToLoad = *filelist;
|
||||
kaizen->shouldDisplaySpinner = true;
|
||||
std::thread fileWorker(&KaizenGui::FileWorker, kaizen);
|
||||
fileWorker.detach();
|
||||
},
|
||||
this, window.getHandle(), filters, 3, nullptr, false);
|
||||
}
|
||||
|
||||
if (minimized)
|
||||
return;
|
||||
|
||||
if (core.romLoaded) {
|
||||
core.parallel.UpdateScreen<true>();
|
||||
return;
|
||||
}
|
||||
|
||||
core.parallel.UpdateScreen<false>();
|
||||
emuThread->requestInterruption();
|
||||
emuThread->quit();
|
||||
}
|
||||
|
||||
void KaizenGui::LoadROM(const std::string &path) noexcept {
|
||||
n64::Core &core = n64::Core::GetInstance();
|
||||
core.LoadROM(path);
|
||||
const auto gameNameDB = n64::Core::GetMem().rom.gameNameDB;
|
||||
SDL_SetWindowTitle(window.getHandle(), ("Kaizen " KAIZEN_VERSION_STR " - " + gameNameDB).c_str());
|
||||
}
|
||||
|
||||
void KaizenGui::run() {
|
||||
while (!quit) {
|
||||
SDL_Event e;
|
||||
while (SDL_PollEvent(&e)) {
|
||||
ImGui_ImplSDL3_ProcessEvent(&e);
|
||||
switch (e.type) {
|
||||
case SDL_EVENT_QUIT:
|
||||
quit = true;
|
||||
emuThread.Stop();
|
||||
break;
|
||||
case SDL_EVENT_WINDOW_MINIMIZED:
|
||||
minimized = true;
|
||||
break;
|
||||
case SDL_EVENT_WINDOW_RESTORED:
|
||||
minimized = false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
QueryDevices(e);
|
||||
HandleInput(e);
|
||||
}
|
||||
|
||||
SDL_GetWindowSize(window.getHandle(), &width, &height);
|
||||
|
||||
emuThread.run();
|
||||
RenderUI();
|
||||
}
|
||||
pause->setEnabled(true);
|
||||
reset->setEnabled(true);
|
||||
stop->setEnabled(true);
|
||||
vulkanWidget->show();
|
||||
setWindowTitle(("Kaizen " KAIZEN_VERSION_STR " - " + n64::Core::GetMem().rom.gameNameDB).c_str());
|
||||
}
|
||||
|
||||
void KaizenGui::LoadTAS(const std::string &path) noexcept { n64::Core::GetInstance().LoadTAS(fs::path(path)); }
|
||||
|
||||
void KaizenGui::closeEvent(QCloseEvent *event) {
|
||||
Scheduler::GetInstance().EnqueueRelative(0, STOP);
|
||||
settings.setValue("geometry", saveGeometry());
|
||||
settings.setValue("windowState", saveState());
|
||||
QMainWindow::closeEvent(event);
|
||||
}
|
||||
|
||||
void KaizenGui::dropEvent(QDropEvent *event) {
|
||||
if (event->mimeData()->hasUrls()) {
|
||||
auto file = event->mimeData()->urls()[0].toLocalFile().toStdString();
|
||||
LoadROM(file);
|
||||
event->acceptProposedAction();
|
||||
}
|
||||
}
|
||||
|
||||
void KaizenGui::dragEnterEvent(QDragEnterEvent *event) {
|
||||
if (event->mimeData()->hasUrls())
|
||||
event->acceptProposedAction();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user