diff --git a/Source/Core/DolphinQt2/CMakeLists.txt b/Source/Core/DolphinQt2/CMakeLists.txt index feaac4a090b5..73724b1971a0 100644 --- a/Source/Core/DolphinQt2/CMakeLists.txt +++ b/Source/Core/DolphinQt2/CMakeLists.txt @@ -9,6 +9,7 @@ set(CMAKE_AUTOMOC ON) set(SRCS AboutDialog.cpp + HotkeyScheduler.cpp Host.cpp InDevelopmentWarning.cpp Main.cpp @@ -24,6 +25,12 @@ set(SRCS Config/Mapping/GCKeyboardEmu.cpp Config/Mapping/GCPadEmu.cpp Config/Mapping/GCPadWiiU.cpp + Config/Mapping/Hotkey3D.cpp + Config/Mapping/HotkeyGeneral.cpp + Config/Mapping/HotkeyGraphics.cpp + Config/Mapping/HotkeyStates.cpp + Config/Mapping/HotkeyTAS.cpp + Config/Mapping/HotkeyWii.cpp Config/Mapping/MappingBool.cpp Config/Mapping/MappingButton.cpp Config/Mapping/MappingNumeric.cpp @@ -41,6 +48,7 @@ set(SRCS GameList/GameTracker.cpp GameList/ListProxyModel.cpp QtUtils/ElidedButton.cpp + QtUtils/QInputDialog.cpp Settings/GeneralPane.cpp Settings/InterfacePane.cpp ) diff --git a/Source/Core/DolphinQt2/Config/Mapping/Hotkey3D.cpp b/Source/Core/DolphinQt2/Config/Mapping/Hotkey3D.cpp new file mode 100644 index 000000000000..c144d53f7695 --- /dev/null +++ b/Source/Core/DolphinQt2/Config/Mapping/Hotkey3D.cpp @@ -0,0 +1,42 @@ +// Copyright 2017 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include "DolphinQt2/Config/Mapping/Hotkey3D.h" + +#include +#include + +#include "Core/HotkeyManager.h" + +Hotkey3D::Hotkey3D(MappingWindow* window) : MappingWidget(window) +{ + CreateMainLayout(); +} + +void Hotkey3D::CreateMainLayout() +{ + m_main_layout = new QHBoxLayout(); + + m_main_layout->addWidget( + CreateGroupBox(tr("3D"), HotkeyManagerEmu::GetHotkeyGroup(HKGP_3D_TOGGLE))); + m_main_layout->addWidget( + CreateGroupBox(tr("3D Depth"), HotkeyManagerEmu::GetHotkeyGroup(HKGP_3D_DEPTH))); + + setLayout(m_main_layout); +} + +InputConfig* Hotkey3D::GetConfig() +{ + return HotkeyManagerEmu::GetConfig(); +} + +void Hotkey3D::LoadSettings() +{ + HotkeyManagerEmu::LoadConfig(); +} + +void Hotkey3D::SaveSettings() +{ + HotkeyManagerEmu::GetConfig()->SaveConfig(); +} diff --git a/Source/Core/DolphinQt2/Config/Mapping/Hotkey3D.h b/Source/Core/DolphinQt2/Config/Mapping/Hotkey3D.h new file mode 100644 index 000000000000..b7e78822f28f --- /dev/null +++ b/Source/Core/DolphinQt2/Config/Mapping/Hotkey3D.h @@ -0,0 +1,25 @@ +// Copyright 2017 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#pragma once + +#include "DolphinQt2/Config/Mapping/MappingWidget.h" + +class QHBoxLayout; + +class Hotkey3D final : public MappingWidget +{ +public: + explicit Hotkey3D(MappingWindow* window); + + InputConfig* GetConfig() override; + +private: + void LoadSettings() override; + void SaveSettings() override; + void CreateMainLayout(); + + // Main + QHBoxLayout* m_main_layout; +}; diff --git a/Source/Core/DolphinQt2/Config/Mapping/HotkeyGeneral.cpp b/Source/Core/DolphinQt2/Config/Mapping/HotkeyGeneral.cpp new file mode 100644 index 000000000000..fc111f745caf --- /dev/null +++ b/Source/Core/DolphinQt2/Config/Mapping/HotkeyGeneral.cpp @@ -0,0 +1,47 @@ +// Copyright 2017 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include "DolphinQt2/Config/Mapping/HotkeyGeneral.h" + +#include +#include +#include + +#include "Core/HotkeyManager.h" + +HotkeyGeneral::HotkeyGeneral(MappingWindow* window) : MappingWidget(window) +{ + CreateMainLayout(); +} + +void HotkeyGeneral::CreateMainLayout() +{ + m_main_layout = new QHBoxLayout(); + + m_main_layout->addWidget( + CreateGroupBox(tr("General"), HotkeyManagerEmu::GetHotkeyGroup(HKGP_GENERAL))); + + auto* vbox = new QVBoxLayout(); + vbox->addWidget(CreateGroupBox(tr("Volume"), HotkeyManagerEmu::GetHotkeyGroup(HKGP_VOLUME))); + vbox->addWidget( + CreateGroupBox(tr("Emulation Speed"), HotkeyManagerEmu::GetHotkeyGroup(HKGP_SPEED))); + m_main_layout->addItem(vbox); + + setLayout(m_main_layout); +} + +InputConfig* HotkeyGeneral::GetConfig() +{ + return HotkeyManagerEmu::GetConfig(); +} + +void HotkeyGeneral::LoadSettings() +{ + HotkeyManagerEmu::LoadConfig(); +} + +void HotkeyGeneral::SaveSettings() +{ + HotkeyManagerEmu::GetConfig()->SaveConfig(); +} diff --git a/Source/Core/DolphinQt2/Config/Mapping/HotkeyGeneral.h b/Source/Core/DolphinQt2/Config/Mapping/HotkeyGeneral.h new file mode 100644 index 000000000000..15c6dd04b3a8 --- /dev/null +++ b/Source/Core/DolphinQt2/Config/Mapping/HotkeyGeneral.h @@ -0,0 +1,25 @@ +// Copyright 2017 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#pragma once + +#include "DolphinQt2/Config/Mapping/MappingWidget.h" + +class QHBoxLayout; + +class HotkeyGeneral final : public MappingWidget +{ +public: + explicit HotkeyGeneral(MappingWindow* window); + + InputConfig* GetConfig() override; + +private: + void LoadSettings() override; + void SaveSettings() override; + void CreateMainLayout(); + + // Main + QHBoxLayout* m_main_layout; +}; diff --git a/Source/Core/DolphinQt2/Config/Mapping/HotkeyGraphics.cpp b/Source/Core/DolphinQt2/Config/Mapping/HotkeyGraphics.cpp new file mode 100644 index 000000000000..fe4cc8cdbaaf --- /dev/null +++ b/Source/Core/DolphinQt2/Config/Mapping/HotkeyGraphics.cpp @@ -0,0 +1,48 @@ +// Copyright 2017 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include "DolphinQt2/Config/Mapping/HotkeyGraphics.h" + +#include +#include +#include + +#include "Core/HotkeyManager.h" + +HotkeyGraphics::HotkeyGraphics(MappingWindow* window) : MappingWidget(window) +{ + CreateMainLayout(); +} + +void HotkeyGraphics::CreateMainLayout() +{ + m_main_layout = new QHBoxLayout(); + + m_main_layout->addWidget( + CreateGroupBox(tr("Freelook"), HotkeyManagerEmu::GetHotkeyGroup(HKGP_FREELOOK))); + + auto* vbox = new QVBoxLayout(); + vbox->addWidget(CreateGroupBox(tr("Graphics Toggles"), + HotkeyManagerEmu::GetHotkeyGroup(HKGP_GRAPHICS_TOGGLES))); + vbox->addWidget( + CreateGroupBox(tr("Internal Resolution"), HotkeyManagerEmu::GetHotkeyGroup(HKGP_IR))); + m_main_layout->addItem(vbox); + + setLayout(m_main_layout); +} + +InputConfig* HotkeyGraphics::GetConfig() +{ + return HotkeyManagerEmu::GetConfig(); +} + +void HotkeyGraphics::LoadSettings() +{ + HotkeyManagerEmu::LoadConfig(); +} + +void HotkeyGraphics::SaveSettings() +{ + HotkeyManagerEmu::GetConfig()->SaveConfig(); +} diff --git a/Source/Core/DolphinQt2/Config/Mapping/HotkeyGraphics.h b/Source/Core/DolphinQt2/Config/Mapping/HotkeyGraphics.h new file mode 100644 index 000000000000..63837202b369 --- /dev/null +++ b/Source/Core/DolphinQt2/Config/Mapping/HotkeyGraphics.h @@ -0,0 +1,25 @@ +// Copyright 2017 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#pragma once + +#include "DolphinQt2/Config/Mapping/MappingWidget.h" + +class QHBoxLayout; + +class HotkeyGraphics final : public MappingWidget +{ +public: + explicit HotkeyGraphics(MappingWindow* window); + + InputConfig* GetConfig() override; + +private: + void LoadSettings() override; + void SaveSettings() override; + void CreateMainLayout(); + + // Main + QHBoxLayout* m_main_layout; +}; diff --git a/Source/Core/DolphinQt2/Config/Mapping/HotkeyStates.cpp b/Source/Core/DolphinQt2/Config/Mapping/HotkeyStates.cpp new file mode 100644 index 000000000000..20d85cd544e6 --- /dev/null +++ b/Source/Core/DolphinQt2/Config/Mapping/HotkeyStates.cpp @@ -0,0 +1,42 @@ +// Copyright 2017 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include "DolphinQt2/Config/Mapping/HotkeyStates.h" + +#include +#include + +#include "Core/HotkeyManager.h" + +HotkeyStates::HotkeyStates(MappingWindow* window) : MappingWidget(window) +{ + CreateMainLayout(); +} + +void HotkeyStates::CreateMainLayout() +{ + m_main_layout = new QHBoxLayout(); + + m_main_layout->addWidget( + CreateGroupBox(tr("Save"), HotkeyManagerEmu::GetHotkeyGroup(HKGP_SAVE_STATE))); + m_main_layout->addWidget( + CreateGroupBox(tr("Load"), HotkeyManagerEmu::GetHotkeyGroup(HKGP_LOAD_STATE))); + + setLayout(m_main_layout); +} + +InputConfig* HotkeyStates::GetConfig() +{ + return HotkeyManagerEmu::GetConfig(); +} + +void HotkeyStates::LoadSettings() +{ + HotkeyManagerEmu::LoadConfig(); +} + +void HotkeyStates::SaveSettings() +{ + HotkeyManagerEmu::GetConfig()->SaveConfig(); +} diff --git a/Source/Core/DolphinQt2/Config/Mapping/HotkeyStates.h b/Source/Core/DolphinQt2/Config/Mapping/HotkeyStates.h new file mode 100644 index 000000000000..bf36ec96f323 --- /dev/null +++ b/Source/Core/DolphinQt2/Config/Mapping/HotkeyStates.h @@ -0,0 +1,25 @@ +// Copyright 2017 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#pragma once + +#include "DolphinQt2/Config/Mapping/MappingWidget.h" + +class QHBoxLayout; + +class HotkeyStates final : public MappingWidget +{ +public: + explicit HotkeyStates(MappingWindow* window); + + InputConfig* GetConfig() override; + +private: + void LoadSettings() override; + void SaveSettings() override; + void CreateMainLayout(); + + // Main + QHBoxLayout* m_main_layout; +}; diff --git a/Source/Core/DolphinQt2/Config/Mapping/HotkeyTAS.cpp b/Source/Core/DolphinQt2/Config/Mapping/HotkeyTAS.cpp new file mode 100644 index 000000000000..2586ff2d2a0f --- /dev/null +++ b/Source/Core/DolphinQt2/Config/Mapping/HotkeyTAS.cpp @@ -0,0 +1,42 @@ +// Copyright 2017 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include "DolphinQt2/Config/Mapping/HotkeyTAS.h" + +#include +#include + +#include "Core/HotkeyManager.h" + +HotkeyTAS::HotkeyTAS(MappingWindow* window) : MappingWidget(window) +{ + CreateMainLayout(); +} + +void HotkeyTAS::CreateMainLayout() +{ + m_main_layout = new QHBoxLayout(); + + m_main_layout->addWidget( + CreateGroupBox(tr("Frame Advance"), HotkeyManagerEmu::GetHotkeyGroup(HKGP_FRAME_ADVANCE))); + m_main_layout->addWidget( + CreateGroupBox(tr("Movie"), HotkeyManagerEmu::GetHotkeyGroup(HKGP_MOVIE))); + + setLayout(m_main_layout); +} + +InputConfig* HotkeyTAS::GetConfig() +{ + return HotkeyManagerEmu::GetConfig(); +} + +void HotkeyTAS::LoadSettings() +{ + HotkeyManagerEmu::LoadConfig(); +} + +void HotkeyTAS::SaveSettings() +{ + HotkeyManagerEmu::GetConfig()->SaveConfig(); +} diff --git a/Source/Core/DolphinQt2/Config/Mapping/HotkeyTAS.h b/Source/Core/DolphinQt2/Config/Mapping/HotkeyTAS.h new file mode 100644 index 000000000000..d6fabc129428 --- /dev/null +++ b/Source/Core/DolphinQt2/Config/Mapping/HotkeyTAS.h @@ -0,0 +1,25 @@ +// Copyright 2017 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#pragma once + +#include "DolphinQt2/Config/Mapping/MappingWidget.h" + +class QHBoxLayout; + +class HotkeyTAS final : public MappingWidget +{ +public: + explicit HotkeyTAS(MappingWindow* window); + + InputConfig* GetConfig() override; + +private: + void LoadSettings() override; + void SaveSettings() override; + void CreateMainLayout(); + + // Main + QHBoxLayout* m_main_layout; +}; diff --git a/Source/Core/DolphinQt2/Config/Mapping/HotkeyWii.cpp b/Source/Core/DolphinQt2/Config/Mapping/HotkeyWii.cpp new file mode 100644 index 000000000000..7cfebf5705d4 --- /dev/null +++ b/Source/Core/DolphinQt2/Config/Mapping/HotkeyWii.cpp @@ -0,0 +1,39 @@ +// Copyright 2017 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include "DolphinQt2/Config/Mapping/HotkeyWii.h" + +#include +#include + +#include "Core/HotkeyManager.h" + +HotkeyWii::HotkeyWii(MappingWindow* window) : MappingWidget(window) +{ + CreateMainLayout(); +} + +void HotkeyWii::CreateMainLayout() +{ + m_main_layout = new QHBoxLayout(); + + m_main_layout->addWidget(CreateGroupBox(tr("Wii"), HotkeyManagerEmu::GetHotkeyGroup(HKGP_WII))); + + setLayout(m_main_layout); +} + +InputConfig* HotkeyWii::GetConfig() +{ + return HotkeyManagerEmu::GetConfig(); +} + +void HotkeyWii::LoadSettings() +{ + HotkeyManagerEmu::LoadConfig(); +} + +void HotkeyWii::SaveSettings() +{ + HotkeyManagerEmu::GetConfig()->SaveConfig(); +} diff --git a/Source/Core/DolphinQt2/Config/Mapping/HotkeyWii.h b/Source/Core/DolphinQt2/Config/Mapping/HotkeyWii.h new file mode 100644 index 000000000000..56906e877085 --- /dev/null +++ b/Source/Core/DolphinQt2/Config/Mapping/HotkeyWii.h @@ -0,0 +1,25 @@ +// Copyright 2017 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#pragma once + +#include "DolphinQt2/Config/Mapping/MappingWidget.h" + +class QHBoxLayout; + +class HotkeyWii final : public MappingWidget +{ +public: + explicit HotkeyWii(MappingWindow* window); + + InputConfig* GetConfig() override; + +private: + void LoadSettings() override; + void SaveSettings() override; + void CreateMainLayout(); + + // Main + QHBoxLayout* m_main_layout; +}; diff --git a/Source/Core/DolphinQt2/Config/Mapping/MappingWindow.cpp b/Source/Core/DolphinQt2/Config/Mapping/MappingWindow.cpp index 7b24f1c67814..6d074c430dcd 100644 --- a/Source/Core/DolphinQt2/Config/Mapping/MappingWindow.cpp +++ b/Source/Core/DolphinQt2/Config/Mapping/MappingWindow.cpp @@ -20,6 +20,12 @@ #include "DolphinQt2/Config/Mapping/GCKeyboardEmu.h" #include "DolphinQt2/Config/Mapping/GCPadEmu.h" #include "DolphinQt2/Config/Mapping/GCPadWiiU.h" +#include "DolphinQt2/Config/Mapping/Hotkey3D.h" +#include "DolphinQt2/Config/Mapping/HotkeyGeneral.h" +#include "DolphinQt2/Config/Mapping/HotkeyGraphics.h" +#include "DolphinQt2/Config/Mapping/HotkeyStates.h" +#include "DolphinQt2/Config/Mapping/HotkeyTAS.h" +#include "DolphinQt2/Config/Mapping/HotkeyWii.h" #include "DolphinQt2/Config/Mapping/WiimoteEmuExtension.h" #include "DolphinQt2/Config/Mapping/WiimoteEmuGeneral.h" #include "DolphinQt2/Config/Mapping/WiimoteEmuMotionControl.h" @@ -30,7 +36,7 @@ #include "InputCommon/ControllerInterface/ControllerInterface.h" -MappingWindow::MappingWindow(QWidget* parent, int port_num) : QDialog(parent), m_port(port_num) +MappingWindow::MappingWindow(QWidget* parent, int port_num) : QInputDialog(parent), m_port(port_num) { setWindowTitle(tr("Port %1").arg(port_num + 1)); @@ -282,6 +288,18 @@ void MappingWindow::ChangeMappingType(MappingWindow::Type type) AddWidget(tr("Extension"), extension); break; } + case Type::MAPPING_HOTKEYS: + { + widget = new HotkeyGeneral(this); + AddWidget(tr("General"), widget); + AddWidget(tr("TAS Tools"), new HotkeyTAS(this)); + AddWidget(tr("Wii (Remote)"), new HotkeyWii(this)); + AddWidget(tr("Graphics"), new HotkeyGraphics(this)); + AddWidget(tr("3D"), new Hotkey3D(this)); + AddWidget(tr("Save States"), new HotkeyStates(this)); + setWindowTitle(tr("Hotkey Settings")); + break; + } default: return; } diff --git a/Source/Core/DolphinQt2/Config/Mapping/MappingWindow.h b/Source/Core/DolphinQt2/Config/Mapping/MappingWindow.h index c181f642b3f6..7be6c49c40c4 100644 --- a/Source/Core/DolphinQt2/Config/Mapping/MappingWindow.h +++ b/Source/Core/DolphinQt2/Config/Mapping/MappingWindow.h @@ -4,10 +4,10 @@ #pragma once -#include #include #include +#include "DolphinQt2/QtUtils/QInputDialog.h" #include "InputCommon/ControllerInterface/Device.h" namespace ControllerEmu @@ -26,7 +26,7 @@ class QPushButton; class QTabWidget; class QWidget; -class MappingWindow final : public QDialog +class MappingWindow final : public QInputDialog { Q_OBJECT public: @@ -41,7 +41,9 @@ class MappingWindow final : public QDialog MAPPING_GC_STEERINGWHEEL, // Wii MAPPING_WIIMOTE_EMU, - MAPPING_WIIMOTE_HYBRID + MAPPING_WIIMOTE_HYBRID, + // Hotkeys + MAPPING_HOTKEYS }; explicit MappingWindow(QWidget* parent, int port_num); diff --git a/Source/Core/DolphinQt2/Config/SettingsWindow.cpp b/Source/Core/DolphinQt2/Config/SettingsWindow.cpp index fb1a8190fe59..c4975af93d7f 100644 --- a/Source/Core/DolphinQt2/Config/SettingsWindow.cpp +++ b/Source/Core/DolphinQt2/Config/SettingsWindow.cpp @@ -7,7 +7,7 @@ #include "DolphinQt2/Settings/GeneralPane.h" #include "DolphinQt2/Settings/InterfacePane.h" -SettingsWindow::SettingsWindow(QWidget* parent) : QDialog(parent) +SettingsWindow::SettingsWindow(QWidget* parent) : QInputDialog(parent) { // Set Window Properties setWindowTitle(tr("Settings")); diff --git a/Source/Core/DolphinQt2/Config/SettingsWindow.h b/Source/Core/DolphinQt2/Config/SettingsWindow.h index 6187ba5ab8cb..d042e4c26c03 100644 --- a/Source/Core/DolphinQt2/Config/SettingsWindow.h +++ b/Source/Core/DolphinQt2/Config/SettingsWindow.h @@ -4,7 +4,6 @@ #pragma once -#include #include #include #include @@ -17,7 +16,9 @@ #include #include -class SettingsWindow final : public QDialog +#include "DolphinQt2/QtUtils/QInputDialog.h" + +class SettingsWindow final : public QInputDialog { Q_OBJECT public: diff --git a/Source/Core/DolphinQt2/DolphinQt2.vcxproj b/Source/Core/DolphinQt2/DolphinQt2.vcxproj index 113637506c83..b14156b66804 100644 --- a/Source/Core/DolphinQt2/DolphinQt2.vcxproj +++ b/Source/Core/DolphinQt2/DolphinQt2.vcxproj @@ -84,6 +84,7 @@ + @@ -104,6 +105,7 @@ + @@ -125,6 +127,12 @@ + + + + + + @@ -141,12 +149,14 @@ + + diff --git a/Source/Core/DolphinQt2/HotkeyScheduler.cpp b/Source/Core/DolphinQt2/HotkeyScheduler.cpp new file mode 100644 index 000000000000..94fa8d640cf8 --- /dev/null +++ b/Source/Core/DolphinQt2/HotkeyScheduler.cpp @@ -0,0 +1,353 @@ +// Copyright 2017 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include "DolphinQt2/HotkeyScheduler.h" + +#include +#include + +#include + +#include "AudioCommon/AudioCommon.h" +#include "Common/Thread.h" +#include "Core/Core.h" +#include "Core/HotkeyManager.h" +#include "Core/IOS/IOS.h" +#include "Core/IOS/USB/Bluetooth/BTBase.h" +#include "Core/State.h" +#include "DolphinQt2/MainWindow.h" +#include "DolphinQt2/Settings.h" +#include "InputCommon/ControllerInterface/ControllerInterface.h" +#include "VideoCommon/VertexShaderManager.h" +#include "VideoCommon/VideoConfig.h" + +constexpr const char* DUBOIS_ALGORITHM_SHADER = "dubois"; + +HotkeyScheduler::HotkeyScheduler() : m_stop_requested(false) +{ + HotkeyManagerEmu::Initialize(); + HotkeyManagerEmu::LoadConfig(); + HotkeyManagerEmu::Enable(true); +} + +void HotkeyScheduler::Start() +{ + m_stop_requested.Set(false); + m_thread = std::thread(&HotkeyScheduler::Run, this); +} + +void HotkeyScheduler::Stop() +{ + m_stop_requested.Set(true); +} + +static bool IsHotkey(int id, bool held = false) +{ + return HotkeyManagerEmu::IsPressed(id, held); +} + +static void HandleFrameskipHotkeys() +{ + constexpr int MAX_FRAME_SKIP_DELAY = 60; + constexpr int FRAME_STEP_DELAY = 30; + + static int frame_step_count = 0; + static int frame_step_delay = 1; + static int frame_step_delay_count = 0; + static bool frame_step_hold = false; + + if (IsHotkey(HK_FRAME_ADVANCE_INCREASE_SPEED)) + { + frame_step_delay = std::min(frame_step_delay + 1, MAX_FRAME_SKIP_DELAY); + return; + } + + if (IsHotkey(HK_FRAME_ADVANCE_DECREASE_SPEED)) + { + frame_step_delay = std::max(frame_step_delay - 1, 0); + return; + } + + if (IsHotkey(HK_FRAME_ADVANCE_RESET_SPEED)) + { + frame_step_delay = 1; + return; + } + + if (IsHotkey(HK_FRAME_ADVANCE, true)) + { + if (frame_step_delay_count < frame_step_delay && frame_step_hold) + frame_step_delay_count++; + + // TODO GUI Update (Depends on an unimplemented feature) + // if ((frame_step_count == 0 || frame_step_count == FRAME_STEP_DELAY) && !frame_step_hold) + + if (frame_step_count < FRAME_STEP_DELAY) + { + ++frame_step_count; + if (frame_step_hold) + frame_step_hold = false; + } + + if (frame_step_count == FRAME_STEP_DELAY && frame_step_hold && + frame_step_delay_count >= frame_step_delay) + { + frame_step_hold = false; + frame_step_delay_count = 0; + } + + return; + } + + if (frame_step_count > 0) + { + // Reset frame advance + frame_step_count = 0; + frame_step_hold = false; + frame_step_delay_count = 0; + } +} + +void HotkeyScheduler::Run() +{ + while (!m_stop_requested.IsSet()) + { + if (!HotkeyManagerEmu::IsEnabled()) + continue; + + if (Core::GetState() == Core::State::Uninitialized || Core::GetState() == Core::State::Paused) + g_controller_interface.UpdateInput(); + + if (Core::GetState() != Core::State::Stopping) + { + HotkeyManagerEmu::GetStatus(); + + if (!Core::IsRunningAndStarted()) + continue; + + // Fullscreen + if (IsHotkey(HK_FULLSCREEN)) + emit FullScreenHotkey(); + + // Pause and Unpause + if (IsHotkey(HK_PLAY_PAUSE)) + emit PauseHotkey(); + + // Stop + if (IsHotkey(HK_STOP)) + emit StopHotkey(); + + // Frameskipping + HandleFrameskipHotkeys(); + + // Screenshot + if (IsHotkey(HK_SCREENSHOT)) + emit ScreenShotHotkey(); + + // Exit + if (IsHotkey(HK_EXIT)) + emit ExitHotkey(); + + // Volume + if (IsHotkey(HK_VOLUME_DOWN)) + AudioCommon::DecreaseVolume(3); + + if (IsHotkey(HK_VOLUME_UP)) + AudioCommon::IncreaseVolume(3); + + if (IsHotkey(HK_VOLUME_TOGGLE_MUTE)) + AudioCommon::ToggleMuteVolume(); + + // Wiimote + if (Settings().IsBluetoothPassthroughEnabled()) + { + const auto ios = IOS::HLE::GetIOS(); + auto device = ios ? ios->GetDeviceByName("/dev/usb/oh1/57e/305") : nullptr; + + if (device != nullptr) + std::static_pointer_cast(device)->UpdateSyncButtonState( + IsHotkey(HK_TRIGGER_SYNC_BUTTON, true)); + } + + // TODO Debugging shortcuts (Separate PR) + + if (Settings().IsWiiGameRunning()) + { + int wiimote_id = -1; + if (IsHotkey(HK_WIIMOTE1_CONNECT)) + wiimote_id = 0; + if (IsHotkey(HK_WIIMOTE2_CONNECT)) + wiimote_id = 1; + if (IsHotkey(HK_WIIMOTE3_CONNECT)) + wiimote_id = 2; + if (IsHotkey(HK_WIIMOTE4_CONNECT)) + wiimote_id = 3; + if (IsHotkey(HK_BALANCEBOARD_CONNECT)) + wiimote_id = 4; + + // TODO Implement Wiimote connecting / disconnecting (Separate PR) + // if (wiimote_id > -1) + } + + // Graphics + if (IsHotkey(HK_INCREASE_IR)) + ++g_Config.iEFBScale; + if (IsHotkey(HK_DECREASE_IR)) + g_Config.iEFBScale = std::max(g_Config.iEFBScale - 1, static_cast(SCALE_AUTO)); + if (IsHotkey(HK_TOGGLE_CROP)) + g_Config.bCrop = !g_Config.bCrop; + if (IsHotkey(HK_TOGGLE_AR)) + g_Config.iAspectRatio = (g_Config.iAspectRatio + 1) & 3; + if (IsHotkey(HK_TOGGLE_EFBCOPIES)) + g_Config.bSkipEFBCopyToRam = !g_Config.bSkipEFBCopyToRam; + if (IsHotkey(HK_TOGGLE_FOG)) + g_Config.bDisableFog = !g_Config.bDisableFog; + if (IsHotkey(HK_TOGGLE_DUMPTEXTURES)) + g_Config.bDumpTextures = !g_Config.bDumpTextures; + if (IsHotkey(HK_TOGGLE_TEXTURES)) + g_Config.bHiresTextures = !g_Config.bHiresTextures; + + Core::SetIsThrottlerTempDisabled(IsHotkey(HK_TOGGLE_THROTTLE, true)); + + if (IsHotkey(HK_DECREASE_EMULATION_SPEED)) + { + auto speed = Settings().GetEmulationSpeed() - 0.1; + speed = (speed <= 0 || (speed >= 0.95 && speed <= 1.05)) ? 1.0 : speed; + Settings().SetEmulationSpeed(speed); + } + + if (IsHotkey(HK_INCREASE_EMULATION_SPEED)) + { + auto speed = Settings().GetEmulationSpeed() + 0.1; + speed = (speed >= 0.95 && speed <= 1.05) ? 1.0 : speed; + Settings().SetEmulationSpeed(speed); + } + + // Slot Saving / Loading + if (IsHotkey(HK_SAVE_STATE_SLOT_SELECTED)) + emit StateSaveSlotHotkey(); + + if (IsHotkey(HK_LOAD_STATE_SLOT_SELECTED)) + emit StateLoadSlotHotkey(); + + // Stereoscopy + if (IsHotkey(HK_TOGGLE_STEREO_SBS) || IsHotkey(HK_TOGGLE_STEREO_TAB)) + { + if (g_Config.iStereoMode != STEREO_SBS) + { + // Disable post-processing shader, as stereoscopy itself is currently a shader + if (g_Config.sPostProcessingShader == DUBOIS_ALGORITHM_SHADER) + g_Config.sPostProcessingShader = ""; + + g_Config.iStereoMode = IsHotkey(HK_TOGGLE_STEREO_SBS) ? STEREO_SBS : STEREO_TAB; + } + else + { + g_Config.iStereoMode = STEREO_OFF; + } + } + + if (IsHotkey(HK_TOGGLE_STEREO_ANAGLYPH)) + { + if (g_Config.iStereoMode != STEREO_ANAGLYPH) + { + g_Config.iStereoMode = STEREO_ANAGLYPH; + g_Config.sPostProcessingShader = DUBOIS_ALGORITHM_SHADER; + } + else + { + g_Config.iStereoMode = STEREO_OFF; + g_Config.sPostProcessingShader = ""; + } + } + + if (IsHotkey(HK_TOGGLE_STEREO_3DVISION)) + { + if (g_Config.iStereoMode != STEREO_3DVISION) + { + if (g_Config.sPostProcessingShader == DUBOIS_ALGORITHM_SHADER) + g_Config.sPostProcessingShader = ""; + + g_Config.iStereoMode = STEREO_3DVISION; + } + else + { + g_Config.iStereoMode = STEREO_OFF; + } + } + } + + if (IsHotkey(HK_DECREASE_DEPTH, true)) + g_Config.iStereoDepth = std::max(g_Config.iStereoDepth - 1, 0); + + if (IsHotkey(HK_INCREASE_DEPTH, true)) + g_Config.iStereoDepth = std::min(g_Config.iStereoDepth + 1, 100); + + if (IsHotkey(HK_DECREASE_CONVERGENCE, true)) + g_Config.iStereoConvergence = std::max(g_Config.iStereoConvergence - 5, 0); + + if (IsHotkey(HK_INCREASE_CONVERGENCE, true)) + g_Config.iStereoConvergence = std::min(g_Config.iStereoConvergence + 5, 500); + + // Freelook + static float fl_speed = 1.0; + + if (IsHotkey(HK_FREELOOK_DECREASE_SPEED, true)) + fl_speed /= 1.1f; + + if (IsHotkey(HK_FREELOOK_INCREASE_SPEED, true)) + fl_speed *= 1.1f; + + if (IsHotkey(HK_FREELOOK_RESET_SPEED, true)) + fl_speed = 1.0; + + if (IsHotkey(HK_FREELOOK_UP, true)) + VertexShaderManager::TranslateView(0.0, 0.0, -fl_speed); + + if (IsHotkey(HK_FREELOOK_DOWN, true)) + VertexShaderManager::TranslateView(0.0, 0.0, fl_speed); + + if (IsHotkey(HK_FREELOOK_LEFT, true)) + VertexShaderManager::TranslateView(fl_speed, 0.0); + + if (IsHotkey(HK_FREELOOK_RIGHT, true)) + VertexShaderManager::TranslateView(-fl_speed, 0.0); + + if (IsHotkey(HK_FREELOOK_ZOOM_IN, true)) + VertexShaderManager::TranslateView(0.0, fl_speed); + + if (IsHotkey(HK_FREELOOK_ZOOM_OUT, true)) + VertexShaderManager::TranslateView(0.0, -fl_speed); + + if (IsHotkey(HK_FREELOOK_RESET, true)) + VertexShaderManager::ResetView(); + + // Savestates + for (u32 i = 0; i < State::NUM_STATES; i++) + { + if (IsHotkey(HK_LOAD_STATE_SLOT_1 + i)) + State::Load(i + 1); + + if (IsHotkey(HK_SAVE_STATE_SLOT_1 + i)) + State::Save(i + 1); + + if (IsHotkey(HK_LOAD_LAST_STATE_1 + i)) + State::LoadLastSaved(i + 1); + + if (IsHotkey(HK_SELECT_STATE_SLOT_1 + i)) + emit SetStateSlotHotkey(i + 1); + } + + if (IsHotkey(HK_SAVE_FIRST_STATE)) + State::SaveFirstSaved(); + + if (IsHotkey(HK_UNDO_LOAD_STATE)) + State::UndoLoadState(); + + if (IsHotkey(HK_UNDO_SAVE_STATE)) + State::UndoSaveState(); + } + + Common::SleepCurrentThread(1000 / 60); +} diff --git a/Source/Core/DolphinQt2/HotkeyScheduler.h b/Source/Core/DolphinQt2/HotkeyScheduler.h new file mode 100644 index 000000000000..c2e7749b4cfd --- /dev/null +++ b/Source/Core/DolphinQt2/HotkeyScheduler.h @@ -0,0 +1,36 @@ +// Copyright 2017 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#pragma once + +#include + +#include + +#include "Common/Flag.h" + +class HotkeyScheduler : public QObject +{ + Q_OBJECT +public: + explicit HotkeyScheduler(); + + void Start(); + void Stop(); +signals: + void ExitHotkey(); + void FullScreenHotkey(); + void StopHotkey(); + void PauseHotkey(); + void ScreenShotHotkey(); + void SetStateSlotHotkey(int slot); + void StateLoadSlotHotkey(); + void StateSaveSlotHotkey(); + +private: + void Run(); + + Common::Flag m_stop_requested; + std::thread m_thread; +}; diff --git a/Source/Core/DolphinQt2/MainWindow.cpp b/Source/Core/DolphinQt2/MainWindow.cpp index 3382cee4c03c..7d0c136d6586 100644 --- a/Source/Core/DolphinQt2/MainWindow.cpp +++ b/Source/Core/DolphinQt2/MainWindow.cpp @@ -22,9 +22,11 @@ #include "DolphinQt2/AboutDialog.h" #include "DolphinQt2/Config/ControllersWindow.h" +#include "DolphinQt2/Config/Mapping/MappingWindow.h" #include "DolphinQt2/Config/PathDialog.h" #include "DolphinQt2/Config/SettingsWindow.h" #include "DolphinQt2/Host.h" +#include "DolphinQt2/HotkeyScheduler.h" #include "DolphinQt2/MainWindow.h" #include "DolphinQt2/Resources.h" #include "DolphinQt2/Settings.h" @@ -64,16 +66,23 @@ void MainWindow::InitControllers() Pad::Initialize(); Keyboard::Initialize(); Wiimote::Initialize(Wiimote::InitializeMode::DO_NOT_WAIT_FOR_WIIMOTES); - HotkeyManagerEmu::Initialize(); + m_hotkey_scheduler = new HotkeyScheduler(); + m_hotkey_scheduler->Start(); + + ConnectHotkeys(); } void MainWindow::ShutdownControllers() { + m_hotkey_scheduler->Stop(); + g_controller_interface.Shutdown(); Pad::Shutdown(); Keyboard::Shutdown(); Wiimote::Shutdown(); HotkeyManagerEmu::Shutdown(); + + delete m_hotkey_scheduler; } void MainWindow::CreateComponents() @@ -86,6 +95,7 @@ void MainWindow::CreateComponents() m_paths_dialog = new PathDialog(this); m_controllers_window = new ControllersWindow(this); m_settings_window = new SettingsWindow(this); + m_hotkey_window = new MappingWindow(this, 0); } void MainWindow::ConnectMenuBar() @@ -114,6 +124,9 @@ void MainWindow::ConnectMenuBar() connect(m_menu_bar, &MenuBar::StateSaveOldest, this, &MainWindow::StateSaveOldest); connect(m_menu_bar, &MenuBar::SetStateSlot, this, &MainWindow::SetStateSlot); + // Options + connect(m_menu_bar, &MenuBar::ConfigureHotkeys, this, &MainWindow::ShowHotkeyDialog); + // View connect(m_menu_bar, &MenuBar::ShowTable, m_game_list, &GameList::SetTableView); connect(m_menu_bar, &MenuBar::ShowList, m_game_list, &GameList::SetListView); @@ -131,6 +144,22 @@ void MainWindow::ConnectMenuBar() [=]() { m_controllers_window->OnEmulationStateChanged(false); }); } +void MainWindow::ConnectHotkeys() +{ + connect(m_hotkey_scheduler, &HotkeyScheduler::ExitHotkey, this, &MainWindow::close); + connect(m_hotkey_scheduler, &HotkeyScheduler::PauseHotkey, this, &MainWindow::Pause); + connect(m_hotkey_scheduler, &HotkeyScheduler::StopHotkey, this, &MainWindow::Stop); + connect(m_hotkey_scheduler, &HotkeyScheduler::ScreenShotHotkey, this, &MainWindow::ScreenShot); + connect(m_hotkey_scheduler, &HotkeyScheduler::FullScreenHotkey, this, &MainWindow::FullScreen); + + connect(m_hotkey_scheduler, &HotkeyScheduler::StateLoadSlotHotkey, this, + &MainWindow::StateLoadSlot); + connect(m_hotkey_scheduler, &HotkeyScheduler::StateSaveSlotHotkey, this, + &MainWindow::StateSaveSlot); + connect(m_hotkey_scheduler, &HotkeyScheduler::SetStateSlotHotkey, this, + &MainWindow::SetStateSlot); +} + void MainWindow::ConnectToolBar() { addToolBar(m_tool_bar); @@ -379,6 +408,14 @@ void MainWindow::ShowAboutDialog() about->show(); } +void MainWindow::ShowHotkeyDialog() +{ + m_hotkey_window->ChangeMappingType(MappingWindow::Type::MAPPING_HOTKEYS); + m_hotkey_window->show(); + m_hotkey_window->raise(); + m_hotkey_window->activateWindow(); +} + void MainWindow::StateLoad() { QString path = QFileDialog::getOpenFileName(this, tr("Select a File"), QDir::currentPath(), diff --git a/Source/Core/DolphinQt2/MainWindow.h b/Source/Core/DolphinQt2/MainWindow.h index cc617c3ac090..5774051bd151 100644 --- a/Source/Core/DolphinQt2/MainWindow.h +++ b/Source/Core/DolphinQt2/MainWindow.h @@ -14,6 +14,8 @@ #include "DolphinQt2/RenderWidget.h" #include "DolphinQt2/ToolBar.h" +class HotkeyScheduler; +class MappingWindow; class PathDialog; class SettingsWindow; class ControllersWindow; @@ -59,6 +61,7 @@ private slots: void CreateComponents(); void ConnectGameList(); + void ConnectHotkeys(); void ConnectMenuBar(); void ConnectRenderWidget(); void ConnectStack(); @@ -76,6 +79,7 @@ private slots: void ShowSettingsWindow(); void ShowControllersWindow(); void ShowAboutDialog(); + void ShowHotkeyDialog(); QStackedWidget* m_stack; ToolBar* m_tool_bar; @@ -85,7 +89,9 @@ private slots: bool m_rendering_to_main; int m_state_slot = 1; + HotkeyScheduler* m_hotkey_scheduler; PathDialog* m_paths_dialog; ControllersWindow* m_controllers_window; SettingsWindow* m_settings_window; + MappingWindow* m_hotkey_window; }; diff --git a/Source/Core/DolphinQt2/MenuBar.cpp b/Source/Core/DolphinQt2/MenuBar.cpp index f387b6864d2d..046c06db4bda 100644 --- a/Source/Core/DolphinQt2/MenuBar.cpp +++ b/Source/Core/DolphinQt2/MenuBar.cpp @@ -20,7 +20,7 @@ MenuBar::MenuBar(QWidget* parent) : QMenuBar(parent) AddFileMenu(); AddEmulationMenu(); addMenu(tr("Movie")); - addMenu(tr("Options")); + AddOptionsMenu(); AddToolsMenu(); AddViewMenu(); AddHelpMenu(); @@ -171,6 +171,12 @@ void MenuBar::AddViewMenu() AddTableColumnsMenu(view_menu); } +void MenuBar::AddOptionsMenu() +{ + QMenu* options_menu = addMenu(tr("Options")); + options_menu->addAction(tr("Hotkey Settings"), this, &MenuBar::ConfigureHotkeys); +} + void MenuBar::AddHelpMenu() { QMenu* help_menu = addMenu(tr("Help")); diff --git a/Source/Core/DolphinQt2/MenuBar.h b/Source/Core/DolphinQt2/MenuBar.h index fa8c67cc384d..a0346f427774 100644 --- a/Source/Core/DolphinQt2/MenuBar.h +++ b/Source/Core/DolphinQt2/MenuBar.h @@ -38,6 +38,9 @@ class MenuBar final : public QMenuBar void StateSaveOldest(); void SetStateSlot(int slot); + // Options + void ConfigureHotkeys(); + // View void ShowTable(); void ShowList(); @@ -66,6 +69,7 @@ public slots: void AddGameListTypeSection(QMenu* view_menu); void AddTableColumnsMenu(QMenu* view_menu); + void AddOptionsMenu(); void AddToolsMenu(); void AddHelpMenu(); diff --git a/Source/Core/DolphinQt2/QtUtils/QInputDialog.cpp b/Source/Core/DolphinQt2/QtUtils/QInputDialog.cpp new file mode 100644 index 000000000000..ef5967e1f924 --- /dev/null +++ b/Source/Core/DolphinQt2/QtUtils/QInputDialog.cpp @@ -0,0 +1,24 @@ +// Copyright 2017 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include "DolphinQt2/QtUtils/QInputDialog.h" + +#include "Core/HotkeyManager.h" + +QInputDialog::QInputDialog(QWidget* parent) : QDialog(parent) +{ +} + +void QInputDialog::focusInEvent(QFocusEvent* event) +{ + HotkeyManagerEmu::Enable(false); + QDialog::focusInEvent(event); +} + +void QInputDialog::focusOutEvent(QFocusEvent* event) +{ + HotkeyManagerEmu::Enable(true); + QDialog::focusOutEvent(event); +} + diff --git a/Source/Core/DolphinQt2/QtUtils/QInputDialog.h b/Source/Core/DolphinQt2/QtUtils/QInputDialog.h new file mode 100644 index 000000000000..eb54d1114450 --- /dev/null +++ b/Source/Core/DolphinQt2/QtUtils/QInputDialog.h @@ -0,0 +1,21 @@ +// Copyright 2017 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#pragma once + +#include + +class QFocusEvent; + +class QInputDialog : public QDialog +{ +public: + explicit QInputDialog(QWidget* parent); +protected: + void focusInEvent(QFocusEvent* event) override; + void focusOutEvent(QFocusEvent* event) override; +}; + + +