diff options
Diffstat (limited to 'src/yuzu/main.cpp')
-rw-r--r-- | src/yuzu/main.cpp | 97 |
1 files changed, 84 insertions, 13 deletions
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index e36774cc6..0bd0c5b04 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -19,6 +19,7 @@ #include "common/nvidia_flags.h" #include "configuration/configure_input.h" #include "configuration/configure_per_game.h" +#include "configuration/configure_tas.h" #include "configuration/configure_vibration.h" #include "core/file_sys/vfs.h" #include "core/file_sys/vfs_real.h" @@ -102,6 +103,7 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual #include "core/perf_stats.h" #include "core/telemetry_session.h" #include "input_common/main.h" +#include "input_common/tas/tas_input.h" #include "util/overlay_dialog.h" #include "video_core/gpu.h" #include "video_core/renderer_base.h" @@ -557,7 +559,8 @@ void GMainWindow::WebBrowserOpenWebPage(const std::string& main_url, const std::string& additional_args, bool is_local) { #ifdef YUZU_USE_QT_WEB_ENGINE - if (disable_web_applet) { + // Raw input breaks with the web applet, Disable web applets if enabled + if (disable_web_applet || Settings::values.enable_raw_input) { emit WebBrowserClosed(Service::AM::Applets::WebExitReason::WindowClosed, "http://localhost/"); return; @@ -746,6 +749,11 @@ void GMainWindow::InitializeWidgets() { statusBar()->addPermanentWidget(label); } + tas_label = new QLabel(); + tas_label->setObjectName(QStringLiteral("TASlabel")); + tas_label->setFocusPolicy(Qt::NoFocus); + statusBar()->insertPermanentWidget(0, tas_label); + // Setup Dock button dock_status_button = new QPushButton(); dock_status_button->setObjectName(QStringLiteral("TogglableStatusBarButton")); @@ -840,7 +848,7 @@ void GMainWindow::InitializeDebugWidgets() { waitTreeWidget->hide(); debug_menu->addAction(waitTreeWidget->toggleViewAction()); - controller_dialog = new ControllerDialog(this); + controller_dialog = new ControllerDialog(this, input_subsystem.get()); controller_dialog->hide(); debug_menu->addAction(controller_dialog->toggleViewAction()); @@ -1013,6 +1021,28 @@ void GMainWindow::InitializeHotkeys() { render_window->setAttribute(Qt::WA_Hover, true); } }); + connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("TAS Start/Stop"), this), + &QShortcut::activated, this, [&] { + if (!emulation_running) { + return; + } + input_subsystem->GetTas()->StartStop(); + }); + connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("TAS Reset"), this), + &QShortcut::activated, this, [&] { input_subsystem->GetTas()->Reset(); }); + connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("TAS Record"), this), + &QShortcut::activated, this, [&] { + if (!emulation_running) { + return; + } + bool is_recording = input_subsystem->GetTas()->Record(); + if (!is_recording) { + const auto res = QMessageBox::question(this, tr("TAS Recording"), + tr("Overwrite file of player 1?"), + QMessageBox::Yes | QMessageBox::No); + input_subsystem->GetTas()->SaveRecording(res == QMessageBox::Yes); + } + }); } void GMainWindow::SetDefaultUIGeometry() { @@ -1131,6 +1161,7 @@ void GMainWindow::ConnectMenuEvents() { connect(ui.action_Open_FAQ, &QAction::triggered, this, &GMainWindow::OnOpenFAQ); connect(ui.action_Restart, &QAction::triggered, this, [this] { BootGame(QString(game_path)); }); connect(ui.action_Configure, &QAction::triggered, this, &GMainWindow::OnConfigure); + connect(ui.action_Configure_Tas, &QAction::triggered, this, &GMainWindow::OnConfigureTas); connect(ui.action_Configure_Current_Game, &QAction::triggered, this, &GMainWindow::OnConfigurePerGame); @@ -1353,6 +1384,9 @@ void GMainWindow::BootGame(const QString& filename, u64 program_id, std::size_t system.RegisterExecuteProgramCallback( [this](std::size_t program_index) { render_window->ExecuteProgram(program_index); }); + // Register an Exit callback such that Core can exit the currently running application. + system.RegisterExitCallback([this]() { render_window->Exit(); }); + connect(render_window, &GRenderWindow::Closed, this, &GMainWindow::OnStopGame); connect(render_window, &GRenderWindow::MouseActivity, this, &GMainWindow::OnMouseActivity); // BlockingQueuedConnection is important here, it makes sure we've finished refreshing our views @@ -1463,6 +1497,8 @@ void GMainWindow::ShutdownGame() { game_list->show(); } game_list->SetFilterFocus(); + tas_label->clear(); + input_subsystem->GetTas()->Stop(); render_window->removeEventFilter(render_window); render_window->setAttribute(Qt::WA_Hover, false); @@ -2436,6 +2472,10 @@ void GMainWindow::OnExecuteProgram(std::size_t program_index) { BootGame(last_filename_booted, 0, program_index); } +void GMainWindow::OnExit() { + OnStopGame(); +} + void GMainWindow::ErrorDisplayDisplayError(QString error_code, QString error_text) { OverlayDialog dialog(render_window, Core::System::GetInstance(), error_code, error_text, QString{}, tr("OK"), Qt::AlignLeft | Qt::AlignVCenter); @@ -2697,6 +2737,19 @@ void GMainWindow::OnConfigure() { UpdateStatusButtons(); } +void GMainWindow::OnConfigureTas() { + const auto& system = Core::System::GetInstance(); + ConfigureTasDialog dialog(this); + const auto result = dialog.exec(); + + if (result != QDialog::Accepted && !UISettings::values.configuration_applied) { + Settings::RestoreGlobalState(system.IsPoweredOn()); + return; + } else if (result == QDialog::Accepted) { + dialog.ApplyConfiguration(); + } +} + void GMainWindow::OnConfigurePerGame() { const u64 title_id = Core::System::GetInstance().CurrentProcess()->GetTitleID(); OpenPerGameConfiguration(title_id, game_path.toStdString()); @@ -2873,12 +2926,32 @@ void GMainWindow::UpdateWindowTitle(std::string_view title_name, std::string_vie } } +QString GMainWindow::GetTasStateDescription() const { + auto [tas_status, current_tas_frame, total_tas_frames] = input_subsystem->GetTas()->GetStatus(); + switch (tas_status) { + case TasInput::TasState::Running: + return tr("TAS state: Running %1/%2").arg(current_tas_frame).arg(total_tas_frames); + case TasInput::TasState::Recording: + return tr("TAS state: Recording %1").arg(total_tas_frames); + case TasInput::TasState::Stopped: + return tr("TAS state: Idle %1/%2").arg(current_tas_frame).arg(total_tas_frames); + default: + return tr("TAS State: Invalid"); + } +} + void GMainWindow::UpdateStatusBar() { if (emu_thread == nullptr) { status_bar_update_timer.stop(); return; } + if (Settings::values.tas_enable) { + tas_label->setText(GetTasStateDescription()); + } else { + tas_label->clear(); + } + auto& system = Core::System::GetInstance(); auto results = system.GetAndResetPerfStats(); auto& shader_notify = system.GPU().ShaderNotify(); @@ -3174,12 +3247,11 @@ std::optional<u64> GMainWindow::SelectRomFSDumpTarget(const FileSys::ContentProv } bool GMainWindow::ConfirmClose() { - if (emu_thread == nullptr || !UISettings::values.confirm_before_closing) + if (emu_thread == nullptr || !UISettings::values.confirm_before_closing) { return true; - - QMessageBox::StandardButton answer = - QMessageBox::question(this, tr("yuzu"), tr("Are you sure you want to close yuzu?"), - QMessageBox::Yes | QMessageBox::No, QMessageBox::No); + } + const auto text = tr("Are you sure you want to close yuzu?"); + const auto answer = QMessageBox::question(this, tr("yuzu"), text); return answer != QMessageBox::No; } @@ -3261,14 +3333,13 @@ bool GMainWindow::ConfirmChangeGame() { } bool GMainWindow::ConfirmForceLockedExit() { - if (emu_thread == nullptr) + if (emu_thread == nullptr || !UISettings::values.confirm_before_closing) { return true; + } + const auto text = tr("The currently running application has requested yuzu to not exit.\n\n" + "Would you like to bypass this and exit anyway?"); - const auto answer = - QMessageBox::question(this, tr("yuzu"), - tr("The currently running application has requested yuzu to not " - "exit.\n\nWould you like to bypass this and exit anyway?"), - QMessageBox::Yes | QMessageBox::No, QMessageBox::No); + const auto answer = QMessageBox::question(this, tr("yuzu"), text); return answer != QMessageBox::No; } |