Skip to content

Commit

Permalink
Added Mouse Functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
Sage-King committed May 14, 2022
1 parent fcb3f9e commit 23f33fe
Show file tree
Hide file tree
Showing 21 changed files with 1,046 additions and 32 deletions.
2 changes: 2 additions & 0 deletions Source/Core/Core/CMakeLists.txt
Expand Up @@ -28,6 +28,8 @@ add_library(core
Config/GraphicsSettings.h
Config/MainSettings.cpp
Config/MainSettings.h
Config/MouseSettings.cpp
Config/MouseSettings.h
Config/NetplaySettings.cpp
Config/NetplaySettings.h
Config/SessionSettings.cpp
Expand Down
14 changes: 14 additions & 0 deletions Source/Core/Core/Config/MouseSettings.cpp
@@ -0,0 +1,14 @@
// Copyright 2018 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#include "Core/Config/MouseSettings.h"

namespace Config
{
const Info<double> MOUSE_SENSITIVITY{{System::Main, "Input", "MouseSensitivity"}, 1.0};
const Info<double> SNAPPING_DISTANCE{{System::Main, "Input", "SnappingDistance"}, 0.0};
const Info<unsigned short> CENTER_MOUSE_KEY{{System::Main, "Input", "CenterMouseKey"},
CENTER_MOUSE_KEY_UNBOUND_VALUE};
const Info<bool> OCTAGONAL_MOUSE_JAIL_ENABLED{{System::Main, "Input", "OctagonalMouseJailEnabled"},
false};
} // namespace Config
16 changes: 16 additions & 0 deletions Source/Core/Core/Config/MouseSettings.h
@@ -0,0 +1,16 @@
// Copyright 2018 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#pragma once

#include "Common/Config/Config.h"

namespace Config
{
extern const Info<double> MOUSE_SENSITIVITY;
static constexpr double scaling_factor_to_make_mouse_sensitivity_one_for_fullscreen = 2.0;
extern const Info<double> SNAPPING_DISTANCE;
extern const Info<unsigned short> CENTER_MOUSE_KEY;
static constexpr unsigned short CENTER_MOUSE_KEY_UNBOUND_VALUE = 0xFFFF;
extern const Info<bool> OCTAGONAL_MOUSE_JAIL_ENABLED;
} // namespace Config
4 changes: 4 additions & 0 deletions Source/Core/Core/Host.h
Expand Up @@ -8,6 +8,7 @@
#include <vector>

#include "Common/CommonTypes.h"
#include "Common/WindowSystemInfo.h"

// Host - defines an interface for the emulator core to communicate back to the
// OS-specific layer
Expand Down Expand Up @@ -63,5 +64,8 @@ void Host_UpdateMainFrame();
void Host_UpdateTitle(const std::string& title);
void Host_YieldToUI();
void Host_TitleChanged();
std::pair<double, double> Host_GetRendererDimensions();
void* Host_GetRendererHandle();
std::pair<double, double> Host_GetRendererLocation();

std::unique_ptr<GBAHostInterface> Host_CreateGBAHost(std::weak_ptr<HW::GBA::Core> core);
8 changes: 8 additions & 0 deletions Source/Core/DolphinLib.vcxproj
Expand Up @@ -27,6 +27,14 @@
<Project>{41279555-f94f-4ebc-99de-af863c10c5c4}</Project>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Core\Config\MouseSettings.h" />
<ClInclude Include="InputCommon\ControllerInterface\OctagonalMouseJail.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="Core\Config\MouseSettings.cpp" />
<ClCompile Include="InputCommon\ControllerInterface\OctagonalMouseJail.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets" />
</Project>
4 changes: 4 additions & 0 deletions Source/Core/DolphinQt/CMakeLists.txt
Expand Up @@ -194,6 +194,8 @@ add_executable(dolphin-emu
Config/Mapping/WiimoteEmuMotionControl.h
Config/Mapping/WiimoteEmuMotionControlIMU.cpp
Config/Mapping/WiimoteEmuMotionControlIMU.h
Config/MouseSettingsWidget.cpp
Config/MouseSettingsWidget.h
Config/NewPatchDialog.cpp
Config/NewPatchDialog.h
Config/PatchesWidget.cpp
Expand Down Expand Up @@ -285,6 +287,8 @@ add_executable(dolphin-emu
QtUtils/FileOpenEventFilter.h
QtUtils/FlowLayout.cpp
QtUtils/FlowLayout.h
QtUtils/MultiClickSignalButton.cpp
QtUtils/MultiClickSignalButton.h
QtUtils/ModalMessageBox.cpp
QtUtils/ModalMessageBox.h
QtUtils/ParallelProgressDialog.h
Expand Down
1 change: 1 addition & 0 deletions Source/Core/DolphinQt/Config/ControllersWindow.h
Expand Up @@ -9,6 +9,7 @@ class CommonControllersWidget;
class GamecubeControllersWidget;
class QDialogButtonBox;
class WiimoteControllersWidget;
class MouseSettingsWidget;

class ControllersWindow final : public QDialog
{
Expand Down
227 changes: 227 additions & 0 deletions Source/Core/DolphinQt/Config/MouseSettingsWidget.cpp
@@ -0,0 +1,227 @@
#include "DolphinQt/Config/MouseSettingsWidget.h"
#ifdef _WIN32
#include <Windows.h>
#endif

#include <memory>

#include <QApplication>
#include <QCheckBox>
#include <QDoubleSpinBox>
#include <QLabel>
#include <QVBoxLayout>

#include "Core/Config/MouseSettings.h"
#include "DolphinQt/QtUtils/MultiClickSignalButton.h"
#include "InputCommon/ControllerInterface/OctagonalMouseJail.h"

MouseSettingsWidget::MouseSettingsWidget(QWidget* parent) : QGroupBox(parent)
{
CreateLayout();
LoadSettings();
ConnectWidgets();
}

void MouseSettingsWidget::CreateLayout()
{
QVBoxLayout* primary_layout = new QVBoxLayout{};

QHBoxLayout* sensitivity_layout = CreateSensitivityLayout();
QHBoxLayout* snapping_distance_layout = CreateSnappingDistanceLayout();
QHBoxLayout* center_mouse_key_layout = CreateCenterMouseKeyLayout();

QHBoxLayout* octagonal_mouse_jail_is_enabled = CreateOctagonalMouseJailIsEnabledLayout();

primary_layout->addLayout(octagonal_mouse_jail_is_enabled);
primary_layout->addLayout(sensitivity_layout);
primary_layout->addLayout(snapping_distance_layout);
primary_layout->addLayout(center_mouse_key_layout);

this->setLayout(primary_layout);
}

void MouseSettingsWidget::ConnectWidgets()
{
// I'm not sure what QOverland does in this, but it was in the example in the
// qt documentation and it doesn't work without it.
connect(m_sensitivity_control, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this,
&MouseSettingsWidget::SaveSettings);
connect(m_snapping_distance_control, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this,
&MouseSettingsWidget::SaveSettings);
connect(m_center_mouse_key_control, &MultiClickSignalButton::LeftClick, [this]() {
m_center_mouse_key_control->setText(QString{tr("...")});

unsigned short temp_center_mouse_key = GetNextKeyCode();

Config::SetBaseOrCurrent(Config::CENTER_MOUSE_KEY, temp_center_mouse_key);
Config::Save();
ciface::OctagonalMouseJail::GetInstance().RefreshConfigValues();

if (temp_center_mouse_key == Config::CENTER_MOUSE_KEY_UNBOUND_VALUE)
{
m_center_mouse_key_control->setText(QString{tr(" ")});
}
else
{
m_center_mouse_key_control->setText(tr(std::string{(char)temp_center_mouse_key}.c_str()));
}
});
connect(m_center_mouse_key_control, &MultiClickSignalButton::MiddleClick, [this]() {
m_center_mouse_key_control->setText(QString{tr(" ")});
Config::SetBaseOrCurrent(Config::CENTER_MOUSE_KEY, Config::CENTER_MOUSE_KEY_UNBOUND_VALUE);
Config::Save();
ciface::OctagonalMouseJail::GetInstance().RefreshConfigValues();
});
connect(m_octagonal_mouse_jail_is_enabled_control, &QCheckBox::stateChanged, [this](int state) {
Config::SetBaseOrCurrent(Config::OCTAGONAL_MOUSE_JAIL_ENABLED, (bool)state);
SaveSettings();
});
}

void MouseSettingsWidget::LoadSettings()
{
m_sensitivity_control->setValue(Config::Get(Config::MOUSE_SENSITIVITY));
m_snapping_distance_control->setValue(Config::Get(Config::SNAPPING_DISTANCE));

unsigned short temp_center_mouse_key = Config::Get(Config::CENTER_MOUSE_KEY);
if (temp_center_mouse_key == Config::CENTER_MOUSE_KEY_UNBOUND_VALUE)
{
m_center_mouse_key_control->setText(QString{});
}
else
{
m_center_mouse_key_control->setText(tr(std::string{(char)temp_center_mouse_key}.c_str()));
}

m_octagonal_mouse_jail_is_enabled_control->setChecked(
Config::Get(Config::OCTAGONAL_MOUSE_JAIL_ENABLED));
}

void MouseSettingsWidget::SaveSettings()
{
Config::SetBaseOrCurrent(Config::MOUSE_SENSITIVITY, m_sensitivity_control->value());
Config::SetBaseOrCurrent(Config::SNAPPING_DISTANCE, m_snapping_distance_control->value());
// CenterMouseKeyHandled in lambda attached to m_center_mouse_key_control
Config::SetBaseOrCurrent(Config::OCTAGONAL_MOUSE_JAIL_ENABLED,
m_octagonal_mouse_jail_is_enabled_control->isChecked());
Config::Save();
ciface::OctagonalMouseJail::GetInstance().RefreshConfigValues();
}

QHBoxLayout* MouseSettingsWidget::CreateSensitivityLayout()
{
QHBoxLayout* sensitivity_layout = new QHBoxLayout{};

m_sensitivity_control = new QDoubleSpinBox{};
m_sensitivity_control->setRange(1.00, 9999.50);
m_sensitivity_control->setDecimals(2);
m_sensitivity_control->setSingleStep(0.5);
m_sensitivity_control->setWrapping(true);
QString sensitivity_tool_tip{
tr("Adjusts how quickly the mouse cursor moves the Cursor X/Y +/- inputs."
"\nChanges the distance at which your mouse snaps to notches. May make your snapping feel "
"weird."
"\n\n1.0(default) sensitivity maps the mouse to the full screen"
"\n\nRecommended value: 7.5")};
m_sensitivity_control->setToolTip(sensitivity_tool_tip);

QLabel* sensitivity_label = new QLabel{};
sensitivity_label->setToolTip(sensitivity_tool_tip);
sensitivity_label->setText(tr("Sensitivity"));

sensitivity_layout->addWidget(sensitivity_label);
sensitivity_layout->addWidget(m_sensitivity_control);

return sensitivity_layout;
}

QHBoxLayout* MouseSettingsWidget::CreateSnappingDistanceLayout()
{
QHBoxLayout* snapping_distance_layout = new QHBoxLayout{};
m_snapping_distance_control = new QDoubleSpinBox{};

m_snapping_distance_control->setRange(0.00, 9999.50);
m_snapping_distance_control->setDecimals(2);
m_snapping_distance_control->setSingleStep(0.5);
m_snapping_distance_control->setWrapping(true);
QString snapping_distance_tool_tip{
tr("Distance (in pixels, can do partial pixels) around notches where cursor snaps to notch."
"\nMouse is only locked into notches and snapping will "
"only occur when the game is started and has focus."
"\n\n0.0(default) disables snapping"
"\n\nRecommended Value: 4.5")};
m_snapping_distance_control->setToolTip(snapping_distance_tool_tip);

QLabel* snapping_distance_label = new QLabel{};
snapping_distance_label->setText(tr("Snapping Distance"));
snapping_distance_label->setToolTip(snapping_distance_tool_tip);

snapping_distance_layout->addWidget(snapping_distance_label);
snapping_distance_layout->addWidget(m_snapping_distance_control);
return snapping_distance_layout;
}

QHBoxLayout* MouseSettingsWidget::CreateCenterMouseKeyLayout()
{
QHBoxLayout* center_mouse_key_layout = new QHBoxLayout{};
m_center_mouse_key_control = new MultiClickSignalButton{};
QString center_mouse_key_tool_tip{tr("Centers the cursor after 2 frames."
"\nLeft-click to detect. Middle-click to clear")};
m_center_mouse_key_control->setToolTip(center_mouse_key_tool_tip);

QLabel* center_mouse_key_label = new QLabel{};
center_mouse_key_label->setText(tr("Center Mouse Key"));
center_mouse_key_label->setToolTip(center_mouse_key_tool_tip);

center_mouse_key_layout->addWidget(center_mouse_key_label);
center_mouse_key_layout->addWidget(m_center_mouse_key_control);
return center_mouse_key_layout;
}

QHBoxLayout* MouseSettingsWidget::CreateOctagonalMouseJailIsEnabledLayout()
{
QHBoxLayout* octagonal_mouse_jail_is_enabled_layout = new QHBoxLayout{};
m_octagonal_mouse_jail_is_enabled_control = new QCheckBox{};
QString octagonal_mouse_jail_is_enabled_tool_tip = {tr(
"Locks the mouse cursor into a simulated octagonal gate. \n(Think of the edge around a "
"gamecube controller stick)\nLow sensitivity(under 2.0ish) may not feel like anything is "
"happening. \nSomething is happening, the mouse gate is just REALLY big. \n(Try moving your "
"mouse to the edge of the screen)"
"\n\nSnapping is disabled if this is disabled"
"\n\nLocking and snapping only occur when a game is started and focused"
"\n\nYou can make the mouse cursor invisible at:"
"\nConfig->Interface Tab->Mouse Cursor Visibility->Never"
"\n(Lock Mouse Cursor locks mouse into the game window. \nDifferent and unreleated to the "
"mouse notches)")};
m_octagonal_mouse_jail_is_enabled_control->setToolTip(octagonal_mouse_jail_is_enabled_tool_tip);
QLabel* octagonal_mouse_jail_is_enabled_text = new QLabel{};
octagonal_mouse_jail_is_enabled_text->setText(tr("Mouse Notches"));
octagonal_mouse_jail_is_enabled_text->setToolTip(octagonal_mouse_jail_is_enabled_tool_tip);
octagonal_mouse_jail_is_enabled_layout->addWidget(octagonal_mouse_jail_is_enabled_text);
octagonal_mouse_jail_is_enabled_layout->addWidget(m_octagonal_mouse_jail_is_enabled_control);
return octagonal_mouse_jail_is_enabled_layout;
}

unsigned short MouseSettingsWidget::GetNextKeyCode()
{
#ifdef _WIN32
static constexpr unsigned short highest_virtual_key_hex = 0xFE;
while (true)
{
QApplication::processEvents();
for (unsigned short i = 0; i < highest_virtual_key_hex; i++)
{
if (GetAsyncKeyState(i) & 0x8000)
{
if (i == VK_LBUTTON)
{
continue;
}
return i;
}
}
}
#else
return 0xFFFF;
#endif
}
38 changes: 38 additions & 0 deletions Source/Core/DolphinQt/Config/MouseSettingsWidget.h
@@ -0,0 +1,38 @@
#pragma once

#include <QGroupBox>
class QDoubleSpinBox;
class MultiClickSignalButton;
class QCheckBox;
class QHBoxLayout;

class MouseSettingsWidget final : public QGroupBox
{
Q_OBJECT
public:
MouseSettingsWidget(QWidget* parent);

private:
void CreateLayout();
void ConnectWidgets();

void LoadSettings();
void SaveSettings();

QHBoxLayout* CreateSensitivityLayout();
QHBoxLayout* CreateSnappingDistanceLayout();
QHBoxLayout* CreateCenterMouseKeyLayout();
QHBoxLayout* CreateOctagonalMouseJailIsEnabledLayout();

// Gets the next key code pressed.
// Returns 0xFFFF if unimplemented for the current build target.
//
// @return Next key code pressed as an unsigned short or 0xFFFF if unimplemented for current build
// target
unsigned short GetNextKeyCode();

QDoubleSpinBox* m_sensitivity_control = nullptr;
QDoubleSpinBox* m_snapping_distance_control = nullptr;
MultiClickSignalButton* m_center_mouse_key_control = nullptr;
QCheckBox* m_octagonal_mouse_jail_is_enabled_control = nullptr;
};
4 changes: 4 additions & 0 deletions Source/Core/DolphinQt/DolphinQt.vcxproj
Expand Up @@ -103,6 +103,7 @@
<ClCompile Include="Config\Mapping\WiimoteEmuGeneral.cpp" />
<ClCompile Include="Config\Mapping\WiimoteEmuMotionControl.cpp" />
<ClCompile Include="Config\Mapping\WiimoteEmuMotionControlIMU.cpp" />
<ClCompile Include="Config\MouseSettingsWidget.cpp" />
<ClCompile Include="Config\NewPatchDialog.cpp" />
<ClCompile Include="Config\PatchesWidget.cpp" />
<ClCompile Include="Config\PropertiesDialog.cpp" />
Expand Down Expand Up @@ -166,6 +167,7 @@
<ClCompile Include="QtUtils\ModalMessageBox.cpp" />
<ClCompile Include="QtUtils\NonDefaultQPushButton.cpp" />
<ClCompile Include="QtUtils\PartiallyClosableTabWidget.cpp" />
<ClCompile Include="QtUtils\MultiClickSignalButton.cpp" />
<ClCompile Include="QtUtils\UTF8CodePointCountValidator.cpp" />
<ClCompile Include="QtUtils\WindowActivationEventFilter.cpp" />
<ClCompile Include="QtUtils\WinIconHelper.cpp" />
Expand Down Expand Up @@ -208,6 +210,7 @@
<ClInclude Include="Config\Mapping\MappingCommon.h" />
<ClInclude Include="Config\Mapping\MappingIndicator.h" />
<ClInclude Include="Config\Mapping\MappingNumeric.h" />
<QtMoc Include="Config\MouseSettingsWidget.h" />
<ClInclude Include="Config\NewPatchDialog.h" />
<ClInclude Include="Config\PatchesWidget.h" />
<ClInclude Include="Debugger\RegisterColumn.h" />
Expand All @@ -219,6 +222,7 @@
<ClInclude Include="QtUtils\ModalMessageBox.h" />
<ClInclude Include="QtUtils\NonDefaultQPushButton.h" />
<ClInclude Include="QtUtils\QueueOnObject.h" />
<QtMoc Include="QtUtils\MultiClickSignalButton.h" />
<ClInclude Include="QtUtils\RunOnObject.h" />
<ClInclude Include="QtUtils\SignalBlocking.h" />
<ClInclude Include="QtUtils\WinIconHelper.h" />
Expand Down

0 comments on commit 23f33fe

Please sign in to comment.