Skip to content

Commit

Permalink
Qt: Make "Ignore Inversion" a global mapping setting
Browse files Browse the repository at this point in the history
Instead of being specific to DInput.
  • Loading branch information
stenzek committed Jan 26, 2024
1 parent 22037e7 commit 850b839
Show file tree
Hide file tree
Showing 16 changed files with 177 additions and 30 deletions.
1 change: 1 addition & 0 deletions pcsx2-qt/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ target_sources(pcsx2-qt PRIVATE
Settings/ControllerGlobalSettingsWidget.ui
Settings/ControllerMacroEditWidget.ui
Settings/ControllerMacroWidget.ui
Settings/ControllerMappingSettingsDialog.ui
Settings/ControllerMouseSettingsDialog.ui
Settings/ControllerSettingsWindow.cpp
Settings/ControllerSettingsWindow.h
Expand Down
19 changes: 17 additions & 2 deletions pcsx2-qt/Settings/ControllerGlobalSettingsWidget.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2002-2023 PCSX2 Dev Team
// SPDX-FileCopyrightText: 2002-2024 PCSX2 Dev Team
// SPDX-License-Identifier: LGPL-3.0+

#include "Settings/ControllerGlobalSettingsWidget.h"
Expand Down Expand Up @@ -40,7 +40,6 @@ ControllerGlobalSettingsWidget::ControllerGlobalSettingsWidget(QWidget* parent,
#ifdef _WIN32
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.enableXInputSource, "InputSources", "XInput", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.enableDInputSource, "InputSources", "DInput", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.ignoreDInputInversion, "InputSources", "IgnoreDInputInversion", false);
#else
m_ui.mainLayout->removeWidget(m_ui.xinputGroup);
m_ui.xinputGroup->deleteLater();
Expand Down Expand Up @@ -176,3 +175,19 @@ ControllerMouseSettingsDialog::ControllerMouseSettingsDialog(QWidget* parent, Co
}

ControllerMouseSettingsDialog::~ControllerMouseSettingsDialog() = default;

ControllerMappingSettingsDialog::ControllerMappingSettingsDialog(ControllerSettingsWindow* parent)
: QDialog(parent)
{
m_ui.setupUi(this);

SettingsInterface* sif = parent->getProfileSettingsInterface();

m_ui.icon->setPixmap(QIcon::fromTheme(QStringLiteral("settings-3-line")).pixmap(32, 32));

SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.ignoreInversion, "InputSources", "IgnoreInversion", false);

connect(m_ui.buttonBox->button(QDialogButtonBox::Close), &QPushButton::clicked, this, &QDialog::accept);
}

ControllerMappingSettingsDialog::~ControllerMappingSettingsDialog() = default;
15 changes: 14 additions & 1 deletion pcsx2-qt/Settings/ControllerGlobalSettingsWidget.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2002-2023 PCSX2 Dev Team
// SPDX-FileCopyrightText: 2002-2024 PCSX2 Dev Team
// SPDX-License-Identifier: LGPL-3.0+

#pragma once
Expand All @@ -12,6 +12,7 @@

#include "ui_ControllerGlobalSettingsWidget.h"
#include "ui_ControllerLEDSettingsDialog.h"
#include "ui_ControllerMappingSettingsDialog.h"
#include "ui_ControllerMouseSettingsDialog.h"

class ControllerSettingsWindow;
Expand Down Expand Up @@ -66,3 +67,15 @@ class ControllerMouseSettingsDialog : public QDialog
private:
Ui::ControllerMouseSettingsDialog m_ui;
};

class ControllerMappingSettingsDialog : public QDialog
{
Q_OBJECT

public:
ControllerMappingSettingsDialog(ControllerSettingsWindow* parent);
~ControllerMappingSettingsDialog();

private:
Ui::ControllerMappingSettingsDialog m_ui;
};
10 changes: 0 additions & 10 deletions pcsx2-qt/Settings/ControllerGlobalSettingsWidget.ui
Original file line number Diff line number Diff line change
Expand Up @@ -82,16 +82,6 @@
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QCheckBox" name="ignoreDInputInversion">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Some third party controllers incorrectly flag their analog sticks as inverted on the positive component, but not negative.&lt;/p&gt;&lt;p&gt;As a result, the analog stick will be &amp;quot;stuck on&amp;quot; even while resting at neutral position. &lt;/p&gt;&lt;p&gt;Enabling this setting will tell PCSX2 to ignore inversion flags when creating mappings, allowing such controllers to function normally.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Ignore Inversion</string>
</property>
</widget>
</item>
<item row="1" column="0" colspan="2">
<widget class="QLabel" name="label_9">
<property name="text">
Expand Down
105 changes: 105 additions & 0 deletions pcsx2-qt/Settings/ControllerMappingSettingsDialog.ui
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ControllerMappingSettingsDialog</class>
<widget class="QDialog" name="ControllerMappingSettingsDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>654</width>
<height>275</height>
</rect>
</property>
<property name="windowTitle">
<string>Controller Mapping Settings</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="icon">
<property name="minimumSize">
<size>
<width>32</width>
<height>32</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>32</width>
<height>32</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_4">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:700;&quot;&gt;Controller Mapping Settings&lt;/span&gt;&lt;br/&gt;These settings fine-tune the behavior when mapping physical controllers to the emulated controllers.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="textFormat">
<enum>Qt::RichText</enum>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string/>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QCheckBox" name="ignoreInversion">
<property name="text">
<string>Ignore Inversion</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Some third party controllers incorrectly flag their analog sticks as inverted on the positive component, but not negative.&lt;/p&gt;&lt;p&gt;As a result, the analog stick will be &amp;quot;stuck on&amp;quot; even while resting at neutral position. &lt;/p&gt;&lt;p&gt;Enabling this setting will tell PCSX2 to ignore inversion flags when creating mappings, allowing such controllers to function normally.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>28</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Close</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources>
<include location="../resources/resources.qrc"/>
</resources>
<connections/>
</ui>
7 changes: 7 additions & 0 deletions pcsx2-qt/Settings/ControllerSettingsWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ ControllerSettingsWindow::ControllerSettingsWindow()
connect(m_ui.newProfile, &QPushButton::clicked, this, &ControllerSettingsWindow::onNewProfileClicked);
connect(m_ui.loadProfile, &QPushButton::clicked, this, &ControllerSettingsWindow::onLoadProfileClicked);
connect(m_ui.deleteProfile, &QPushButton::clicked, this, &ControllerSettingsWindow::onDeleteProfileClicked);
connect(m_ui.mappingSettings, &QPushButton::clicked, this, &ControllerSettingsWindow::onMappingSettingsClicked);
connect(m_ui.restoreDefaults, &QPushButton::clicked, this, &ControllerSettingsWindow::onRestoreDefaultsClicked);

connect(g_emu_thread, &EmuThread::onInputDevicesEnumerated, this, &ControllerSettingsWindow::onInputDevicesEnumerated);
Expand Down Expand Up @@ -186,6 +187,12 @@ void ControllerSettingsWindow::onDeleteProfileClicked()
switchProfile({});
}

void ControllerSettingsWindow::onMappingSettingsClicked()
{
ControllerMappingSettingsDialog dialog(this);
dialog.exec();
}

void ControllerSettingsWindow::onRestoreDefaultsClicked()
{
if (QMessageBox::question(this, tr("Restore Defaults"),
Expand Down
1 change: 1 addition & 0 deletions pcsx2-qt/Settings/ControllerSettingsWindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ private Q_SLOTS:
void onNewProfileClicked();
void onLoadProfileClicked();
void onDeleteProfileClicked();
void onMappingSettingsClicked();
void onRestoreDefaultsClicked();

void onInputDevicesEnumerated(const QList<QPair<QString, QString>>& devices);
Expand Down
10 changes: 10 additions & 0 deletions pcsx2-qt/Settings/ControllerSettingsWindow.ui
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,16 @@
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="mappingSettings">
<property name="text">
<string>Mapping Settings</string>
</property>
<property name="icon">
<iconset theme="settings-3-line"/>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="restoreDefaults">
<property name="text">
Expand Down
1 change: 1 addition & 0 deletions pcsx2-qt/pcsx2-qt.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,7 @@
<FileType>Document</FileType>
</QtUi>
<None Include="Settings\ControllerBindingWidget_Popn.ui" />
<None Include="Settings\ControllerMappingSettingsDialog.ui" />
<None Include="Settings\FolderSettingsWidget.ui" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
Expand Down
3 changes: 3 additions & 0 deletions pcsx2-qt/pcsx2-qt.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -661,6 +661,9 @@
<None Include="Settings\ControllerBindingWidget_Popn.ui">
<Filter>Settings</Filter>
</None>
<None Include="Settings\ControllerMappingSettingsDialog.ui">
<Filter>Settings</Filter>
</None>
</ItemGroup>
<ItemGroup>
<QtTs Include="Translations\pcsx2-qt_en.ts">
Expand Down
12 changes: 2 additions & 10 deletions pcsx2/Input/DInputSource.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2002-2023 PCSX2 Dev Team
// SPDX-FileCopyrightText: 2002-2024 PCSX2 Dev Team
// SPDX-License-Identifier: LGPL-3.0+

#define INITGUID
Expand Down Expand Up @@ -49,8 +49,6 @@ static constexpr std::array<const char*, DInputSource::NUM_HAT_DIRECTIONS> s_hat

bool DInputSource::Initialize(SettingsInterface& si, std::unique_lock<std::mutex>& settings_lock)
{
LoadSettings(si);

m_dinput_module.reset(LoadLibraryW(L"dinput8"));
if (!m_dinput_module)
{
Expand Down Expand Up @@ -91,12 +89,6 @@ bool DInputSource::Initialize(SettingsInterface& si, std::unique_lock<std::mutex

void DInputSource::UpdateSettings(SettingsInterface& si, std::unique_lock<std::mutex>& settings_lock)
{
LoadSettings(si);
}

void DInputSource::LoadSettings(SettingsInterface& si)
{
m_ignore_inversion = si.GetBoolValue("InputSources", "IgnoreDInputInversion", false);
}

static BOOL CALLBACK EnumCallback(LPCDIDEVICEINSTANCEW lpddi, LPVOID pvRef)
Expand Down Expand Up @@ -392,7 +384,7 @@ TinyString DInputSource::ConvertKeyToString(InputBindingKey key)
if (key.source_subtype == InputSubclass::ControllerAxis)
{
const char* modifier = (key.modifier == InputModifier::FullAxis ? "Full" : (key.modifier == InputModifier::Negate ? "-" : "+"));
ret.fmt("DInput-{}/{}Axis{}{}", u32(key.source_index), modifier, u32(key.data), (key.invert && !m_ignore_inversion) ? "~" : "");
ret.fmt("DInput-{}/{}Axis{}{}", u32(key.source_index), modifier, u32(key.data), (key.invert && !ShouldIgnoreInversion()) ? "~" : "");
}
else if (key.source_subtype == InputSubclass::ControllerButton && key.data >= MAX_NUM_BUTTONS)
{
Expand Down
4 changes: 1 addition & 3 deletions pcsx2/Input/DInputSource.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2002-2023 PCSX2 Dev Team
// SPDX-FileCopyrightText: 2002-2024 PCSX2 Dev Team
// SPDX-License-Identifier: LGPL-3.0+

#pragma once
Expand Down Expand Up @@ -36,7 +36,6 @@ class DInputSource final : public InputSource

bool Initialize(SettingsInterface& si, std::unique_lock<std::mutex>& settings_lock) override;
void UpdateSettings(SettingsInterface& si, std::unique_lock<std::mutex>& settings_lock) override;
void LoadSettings(SettingsInterface& si);
bool ReloadDevices() override;
void Shutdown() override;

Expand Down Expand Up @@ -81,5 +80,4 @@ class DInputSource final : public InputSource
HWND m_toplevel_window = nullptr;

ControllerDataArray m_controllers;
bool m_ignore_inversion = false;
};
10 changes: 9 additions & 1 deletion pcsx2/Input/InputSource.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
// SPDX-FileCopyrightText: 2002-2023 PCSX2 Dev Team
// SPDX-FileCopyrightText: 2002-2024 PCSX2 Dev Team
// SPDX-License-Identifier: LGPL-3.0+

#include "Input/InputSource.h"
#include "Host.h"

#include "common/StringUtil.h"

InputSource::InputSource() = default;
Expand Down Expand Up @@ -144,3 +146,9 @@ std::string InputSource::ConvertGenericControllerKeyToString(InputBindingKey key
return {};
}
}

bool InputSource::ShouldIgnoreInversion()
{
// This is only called when binding controllers, so the lookup is fine.
return Host::GetBaseBoolSettingValue("InputSources", "IgnoreInversion", false);
}
3 changes: 3 additions & 0 deletions pcsx2/Input/InputSource.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,4 +66,7 @@ class InputSource

/// Converts a generic controller key to a string.
static std::string ConvertGenericControllerKeyToString(InputBindingKey key);

/// Returns true if inversion/negation should be ignored when binding axes.
static bool ShouldIgnoreInversion();
};
4 changes: 2 additions & 2 deletions pcsx2/Input/SDLInputSource.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2002-2023 PCSX2 Dev Team
// SPDX-FileCopyrightText: 2002-2024 PCSX2 Dev Team
// SPDX-License-Identifier: LGPL-3.0+

#include "Config.h"
Expand Down Expand Up @@ -452,7 +452,7 @@ TinyString SDLInputSource::ConvertKeyToString(InputBindingKey key)
if (key.data < std::size(s_sdl_axis_names))
ret.fmt("SDL-{}/{}{}", static_cast<u32>(key.source_index), modifier, s_sdl_axis_names[key.data]);
else
ret.fmt("SDL-{}/{}Axis{}{}", static_cast<u32>(key.source_index), modifier, key.data, key.invert ? "~" : "");
ret.fmt("SDL-{}/{}Axis{}{}", static_cast<u32>(key.source_index), modifier, key.data, (key.invert && !ShouldIgnoreInversion()) ? "~" : "");
}
else if (key.source_subtype == InputSubclass::ControllerButton)
{
Expand Down
2 changes: 1 addition & 1 deletion pcsx2/Input/SDLInputSource.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2002-2023 PCSX2 Dev Team
// SPDX-FileCopyrightText: 2002-2024 PCSX2 Dev Team
// SPDX-License-Identifier: LGPL-3.0+

#pragma once
Expand Down

0 comments on commit 850b839

Please sign in to comment.