Factorize input hooks into reusable monitor classes

Those monitors will need some context so this will be useful
in the nearby future.
This commit is contained in:
Silent 2020-11-14 00:32:35 +01:00
parent 3f9ba4acb6
commit 99ec667b20
No known key found for this signature in database
GPG key ID: AE53149BB0C45AF1
7 changed files with 118 additions and 93 deletions

View file

@ -55,6 +55,8 @@ set(SRCS
inputbindingdialog.cpp inputbindingdialog.cpp
inputbindingdialog.h inputbindingdialog.h
inputbindingdialog.ui inputbindingdialog.ui
inputbindingmonitor.cpp
inputbindingmonitor.h
inputbindingwidgets.cpp inputbindingwidgets.cpp
inputbindingwidgets.h inputbindingwidgets.h
main.cpp main.cpp

View file

@ -66,6 +66,7 @@
<ClCompile Include="displaysettingswidget.cpp" /> <ClCompile Include="displaysettingswidget.cpp" />
<ClCompile Include="hotkeysettingswidget.cpp" /> <ClCompile Include="hotkeysettingswidget.cpp" />
<ClCompile Include="inputbindingdialog.cpp" /> <ClCompile Include="inputbindingdialog.cpp" />
<ClCompile Include="inputbindingmonitor.cpp" />
<ClCompile Include="inputbindingwidgets.cpp" /> <ClCompile Include="inputbindingwidgets.cpp" />
<ClCompile Include="qtdisplaywidget.cpp" /> <ClCompile Include="qtdisplaywidget.cpp" />
<ClCompile Include="gamelistsettingswidget.cpp" /> <ClCompile Include="gamelistsettingswidget.cpp" />
@ -105,6 +106,7 @@
<QtMoc Include="gamelistmodel.h" /> <QtMoc Include="gamelistmodel.h" />
<QtMoc Include="gamelistsearchdirectoriesmodel.h" /> <QtMoc Include="gamelistsearchdirectoriesmodel.h" />
<QtMoc Include="autoupdaterdialog.h" /> <QtMoc Include="autoupdaterdialog.h" />
<ClInclude Include="inputbindingmonitor.h" />
<ClInclude Include="resource.h" /> <ClInclude Include="resource.h" />
<ClInclude Include="settingwidgetbinder.h" /> <ClInclude Include="settingwidgetbinder.h" />
<QtMoc Include="consolesettingswidget.h" /> <QtMoc Include="consolesettingswidget.h" />

View file

@ -60,11 +60,13 @@
<ClCompile Include="$(IntDir)moc_postprocessingchainconfigwidget.cpp" /> <ClCompile Include="$(IntDir)moc_postprocessingchainconfigwidget.cpp" />
<ClCompile Include="$(IntDir)moc_postprocessingshaderconfigwidget.cpp" /> <ClCompile Include="$(IntDir)moc_postprocessingshaderconfigwidget.cpp" />
<ClCompile Include="$(IntDir)moc_postprocessingsettingswidget.cpp" /> <ClCompile Include="$(IntDir)moc_postprocessingsettingswidget.cpp" />
<ClCompile Include="inputbindingmonitor.cpp" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="qtutils.h" /> <ClInclude Include="qtutils.h" />
<ClInclude Include="settingwidgetbinder.h" /> <ClInclude Include="settingwidgetbinder.h" />
<ClInclude Include="resource.h" /> <ClInclude Include="resource.h" />
<ClInclude Include="inputbindingmonitor.h" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Filter Include="resources"> <Filter Include="resources">

View file

@ -3,6 +3,7 @@
#include "common/string_util.h" #include "common/string_util.h"
#include "core/settings.h" #include "core/settings.h"
#include "frontend-common/controller_interface.h" #include "frontend-common/controller_interface.h"
#include "inputbindingmonitor.h"
#include "qthostinterface.h" #include "qthostinterface.h"
#include "qtutils.h" #include "qtutils.h"
#include <QtCore/QTimer> #include <QtCore/QTimer>
@ -210,27 +211,7 @@ void InputButtonBindingDialog::hookControllerInput()
if (!controller_interface) if (!controller_interface)
return; return;
controller_interface->SetHook([this](const ControllerInterface::Hook& ei) { controller_interface->SetHook(InputButtonBindingMonitor(this));
if (ei.type == ControllerInterface::Hook::Type::Axis)
{
// wait until it's at least half pushed so we don't get confused between axises with small movement
if (std::abs(ei.value) < 0.5f)
return ControllerInterface::Hook::CallbackResult::ContinueMonitoring;
// TODO: this probably should consider the "last value"
QMetaObject::invokeMethod(this, "bindToControllerAxis", Q_ARG(int, ei.controller_index),
Q_ARG(int, ei.button_or_axis_number), Q_ARG(std::optional<bool>, ei.value > 0));
return ControllerInterface::Hook::CallbackResult::StopMonitoring;
}
else if (ei.type == ControllerInterface::Hook::Type::Button && ei.value > 0.0f)
{
QMetaObject::invokeMethod(this, "bindToControllerButton", Q_ARG(int, ei.controller_index),
Q_ARG(int, ei.button_or_axis_number));
return ControllerInterface::Hook::CallbackResult::StopMonitoring;
}
return ControllerInterface::Hook::CallbackResult::ContinueMonitoring;
});
} }
void InputButtonBindingDialog::unhookControllerInput() void InputButtonBindingDialog::unhookControllerInput()
@ -274,27 +255,7 @@ void InputAxisBindingDialog::hookControllerInput()
if (!controller_interface) if (!controller_interface)
return; return;
controller_interface->SetHook([this](const ControllerInterface::Hook& ei) { controller_interface->SetHook(InputAxisBindingMonitor(this, m_axis_type));
if (ei.type == ControllerInterface::Hook::Type::Axis)
{
// wait until it's at least half pushed so we don't get confused between axises with small movement
if (std::abs(ei.value) < 0.5f)
return ControllerInterface::Hook::CallbackResult::ContinueMonitoring;
QMetaObject::invokeMethod(this, "bindToControllerAxis", Q_ARG(int, ei.controller_index),
Q_ARG(int, ei.button_or_axis_number), Q_ARG(std::optional<bool>, std::nullopt));
return ControllerInterface::Hook::CallbackResult::StopMonitoring;
}
else if (ei.type == ControllerInterface::Hook::Type::Button && m_axis_type == Controller::AxisType::Half &&
ei.value > 0.0f)
{
QMetaObject::invokeMethod(this, "bindToControllerButton", Q_ARG(int, ei.controller_index),
Q_ARG(int, ei.button_or_axis_number));
return ControllerInterface::Hook::CallbackResult::StopMonitoring;
}
return ControllerInterface::Hook::CallbackResult::ContinueMonitoring;
});
} }
void InputAxisBindingDialog::unhookControllerInput() void InputAxisBindingDialog::unhookControllerInput()

View file

@ -0,0 +1,60 @@
#include "inputbindingmonitor.h"
ControllerInterface::Hook::CallbackResult
InputButtonBindingMonitor::operator()(const ControllerInterface::Hook& ei) const
{
if (ei.type == ControllerInterface::Hook::Type::Axis)
{
// wait until it's at least half pushed so we don't get confused between axises with small movement
if (std::abs(ei.value) < 0.5f)
return ControllerInterface::Hook::CallbackResult::ContinueMonitoring;
// TODO: this probably should consider the "last value"
QMetaObject::invokeMethod(m_parent, "bindToControllerAxis", Q_ARG(int, ei.controller_index),
Q_ARG(int, ei.button_or_axis_number), Q_ARG(std::optional<bool>, ei.value > 0));
return ControllerInterface::Hook::CallbackResult::StopMonitoring;
}
else if (ei.type == ControllerInterface::Hook::Type::Button && ei.value > 0.0f)
{
QMetaObject::invokeMethod(m_parent, "bindToControllerButton", Q_ARG(int, ei.controller_index),
Q_ARG(int, ei.button_or_axis_number));
return ControllerInterface::Hook::CallbackResult::StopMonitoring;
}
return ControllerInterface::Hook::CallbackResult::ContinueMonitoring;
}
ControllerInterface::Hook::CallbackResult InputAxisBindingMonitor::operator()(const ControllerInterface::Hook& ei) const
{
if (ei.type == ControllerInterface::Hook::Type::Axis)
{
// wait until it's at least half pushed so we don't get confused between axises with small movement
if (std::abs(ei.value) < 0.5f)
return ControllerInterface::Hook::CallbackResult::ContinueMonitoring;
QMetaObject::invokeMethod(m_parent, "bindToControllerAxis", Q_ARG(int, ei.controller_index),
Q_ARG(int, ei.button_or_axis_number), Q_ARG(std::optional<bool>, std::nullopt));
return ControllerInterface::Hook::CallbackResult::StopMonitoring;
}
else if (ei.type == ControllerInterface::Hook::Type::Button && m_axis_type == Controller::AxisType::Half &&
ei.value > 0.0f)
{
QMetaObject::invokeMethod(m_parent, "bindToControllerButton", Q_ARG(int, ei.controller_index),
Q_ARG(int, ei.button_or_axis_number));
return ControllerInterface::Hook::CallbackResult::StopMonitoring;
}
return ControllerInterface::Hook::CallbackResult::ContinueMonitoring;
}
ControllerInterface::Hook::CallbackResult
InputRumbleBindingMonitor::operator()(const ControllerInterface::Hook& ei) const
{
if (ei.type == ControllerInterface::Hook::Type::Button && ei.value > 0.0f)
{
QMetaObject::invokeMethod(m_parent, "bindToControllerRumble", Q_ARG(int, ei.controller_index));
return ControllerInterface::Hook::CallbackResult::StopMonitoring;
}
return ControllerInterface::Hook::CallbackResult::ContinueMonitoring;
}

View file

@ -0,0 +1,45 @@
#pragma once
#include "frontend-common/controller_interface.h"
#include <QtCore/QObject>
// NOTE: Those Monitor classes must be copyable to meet the requirements of std::function, but at the same time we want
// copies to be opaque to the caling code and share context. Therefore, all mutable context of the monitor (if required)
// must be enclosed in a std::shared_ptr. m_parent/m_axis_type don't mutate so they don't need to be stored as such.
class InputButtonBindingMonitor
{
public:
explicit InputButtonBindingMonitor(QObject* parent) : m_parent(parent) {}
ControllerInterface::Hook::CallbackResult operator()(const ControllerInterface::Hook& ei) const;
private:
QObject* m_parent;
};
class InputAxisBindingMonitor
{
public:
explicit InputAxisBindingMonitor(QObject* parent, Controller::AxisType axis_type)
: m_parent(parent), m_axis_type(axis_type)
{
}
ControllerInterface::Hook::CallbackResult operator()(const ControllerInterface::Hook& ei) const;
private:
QObject* m_parent;
Controller::AxisType m_axis_type;
};
class InputRumbleBindingMonitor
{
public:
explicit InputRumbleBindingMonitor(QObject* parent) : m_parent(parent) {}
ControllerInterface::Hook::CallbackResult operator()(const ControllerInterface::Hook& ei) const;
private:
QObject* m_parent;
};

View file

@ -4,6 +4,7 @@
#include "core/settings.h" #include "core/settings.h"
#include "frontend-common/controller_interface.h" #include "frontend-common/controller_interface.h"
#include "inputbindingdialog.h" #include "inputbindingdialog.h"
#include "inputbindingmonitor.h"
#include "qthostinterface.h" #include "qthostinterface.h"
#include "qtutils.h" #include "qtutils.h"
#include <QtCore/QTimer> #include <QtCore/QTimer>
@ -236,27 +237,7 @@ void InputButtonBindingWidget::hookControllerInput()
if (!controller_interface) if (!controller_interface)
return; return;
controller_interface->SetHook([this](const ControllerInterface::Hook& ei) { controller_interface->SetHook(InputButtonBindingMonitor(this));
if (ei.type == ControllerInterface::Hook::Type::Axis)
{
// wait until it's at least half pushed so we don't get confused between axises with small movement
if (std::abs(ei.value) < 0.5f)
return ControllerInterface::Hook::CallbackResult::ContinueMonitoring;
// TODO: this probably should consider the "last value"
QMetaObject::invokeMethod(this, "bindToControllerAxis", Q_ARG(int, ei.controller_index),
Q_ARG(int, ei.button_or_axis_number), Q_ARG(std::optional<bool>, ei.value > 0));
return ControllerInterface::Hook::CallbackResult::StopMonitoring;
}
else if (ei.type == ControllerInterface::Hook::Type::Button && ei.value > 0.0f)
{
QMetaObject::invokeMethod(this, "bindToControllerButton", Q_ARG(int, ei.controller_index),
Q_ARG(int, ei.button_or_axis_number));
return ControllerInterface::Hook::CallbackResult::StopMonitoring;
}
return ControllerInterface::Hook::CallbackResult::ContinueMonitoring;
});
} }
void InputButtonBindingWidget::unhookControllerInput() void InputButtonBindingWidget::unhookControllerInput()
@ -306,27 +287,7 @@ void InputAxisBindingWidget::hookControllerInput()
if (!controller_interface) if (!controller_interface)
return; return;
controller_interface->SetHook([this](const ControllerInterface::Hook& ei) { controller_interface->SetHook(InputAxisBindingMonitor(this, m_axis_type));
if (ei.type == ControllerInterface::Hook::Type::Axis)
{
// wait until it's at least half pushed so we don't get confused between axises with small movement
if (std::abs(ei.value) < 0.5f)
return ControllerInterface::Hook::CallbackResult::ContinueMonitoring;
QMetaObject::invokeMethod(this, "bindToControllerAxis", Q_ARG(int, ei.controller_index),
Q_ARG(int, ei.button_or_axis_number), Q_ARG(std::optional<bool>, std::nullopt));
return ControllerInterface::Hook::CallbackResult::StopMonitoring;
}
else if (ei.type == ControllerInterface::Hook::Type::Button && m_axis_type == Controller::AxisType::Half &&
ei.value > 0.0f)
{
QMetaObject::invokeMethod(this, "bindToControllerButton", Q_ARG(int, ei.controller_index),
Q_ARG(int, ei.button_or_axis_number));
return ControllerInterface::Hook::CallbackResult::StopMonitoring;
}
return ControllerInterface::Hook::CallbackResult::ContinueMonitoring;
});
} }
void InputAxisBindingWidget::unhookControllerInput() void InputAxisBindingWidget::unhookControllerInput()
@ -391,15 +352,7 @@ void InputRumbleBindingWidget::hookControllerInput()
if (!controller_interface) if (!controller_interface)
return; return;
controller_interface->SetHook([this](const ControllerInterface::Hook& ei) { controller_interface->SetHook(InputRumbleBindingMonitor(this));
if (ei.type == ControllerInterface::Hook::Type::Button && ei.value > 0.0f)
{
QMetaObject::invokeMethod(this, "bindToControllerRumble", Q_ARG(int, ei.controller_index));
return ControllerInterface::Hook::CallbackResult::StopMonitoring;
}
return ControllerInterface::Hook::CallbackResult::ContinueMonitoring;
});
} }
void InputRumbleBindingWidget::unhookControllerInput() void InputRumbleBindingWidget::unhookControllerInput()