summaryrefslogtreecommitdiff
path: root/Source/Core/InputCommon/ControllerEmu
diff options
context:
space:
mode:
authorJosJuice <josjuice@gmail.com>2021-03-21 20:27:00 +0100
committerJosJuice <josjuice@gmail.com>2022-10-03 22:00:21 +0200
commitcb16d20f2d4ed1ebf150b6ba4d64fe469c1263f1 (patch)
tree4cf6bf751dd1cdea3d199f5885571598325d44d7 /Source/Core/InputCommon/ControllerEmu
parentcb6d476538afe85c25d30e8679b6f15abe5d1760 (diff)
ControllerEmu: Add new "input override" system
Diffstat (limited to 'Source/Core/InputCommon/ControllerEmu')
-rw-r--r--Source/Core/InputCommon/ControllerEmu/ControlGroup/AnalogStick.cpp29
-rw-r--r--Source/Core/InputCommon/ControllerEmu/ControlGroup/AnalogStick.h2
-rw-r--r--Source/Core/InputCommon/ControllerEmu/ControlGroup/Buttons.h17
-rw-r--r--Source/Core/InputCommon/ControllerEmu/ControlGroup/ControlGroup.h7
-rw-r--r--Source/Core/InputCommon/ControllerEmu/ControlGroup/Cursor.cpp25
-rw-r--r--Source/Core/InputCommon/ControllerEmu/ControlGroup/Cursor.h3
-rw-r--r--Source/Core/InputCommon/ControllerEmu/ControlGroup/MixedTriggers.cpp48
-rw-r--r--Source/Core/InputCommon/ControllerEmu/ControlGroup/MixedTriggers.h2
-rw-r--r--Source/Core/InputCommon/ControllerEmu/ControlGroup/Slider.cpp17
-rw-r--r--Source/Core/InputCommon/ControllerEmu/ControlGroup/Slider.h3
-rw-r--r--Source/Core/InputCommon/ControllerEmu/ControlGroup/Triggers.cpp22
-rw-r--r--Source/Core/InputCommon/ControllerEmu/ControlGroup/Triggers.h1
-rw-r--r--Source/Core/InputCommon/ControllerEmu/ControllerEmu.cpp12
-rw-r--r--Source/Core/InputCommon/ControllerEmu/ControllerEmu.h6
-rw-r--r--Source/Core/InputCommon/ControllerEmu/StickGate.h4
15 files changed, 192 insertions, 6 deletions
diff --git a/Source/Core/InputCommon/ControllerEmu/ControlGroup/AnalogStick.cpp b/Source/Core/InputCommon/ControllerEmu/ControlGroup/AnalogStick.cpp
index 539e02b449..0f30b50f63 100644
--- a/Source/Core/InputCommon/ControllerEmu/ControlGroup/AnalogStick.cpp
+++ b/Source/Core/InputCommon/ControllerEmu/ControlGroup/AnalogStick.cpp
@@ -4,6 +4,7 @@
#include "InputCommon/ControllerEmu/ControlGroup/AnalogStick.h"
#include <cmath>
+#include <optional>
#include "Common/Common.h"
#include "Common/MathUtil.h"
@@ -48,6 +49,34 @@ AnalogStick::StateData AnalogStick::GetState() const
return GetReshapableState(true);
}
+AnalogStick::StateData AnalogStick::GetState(const InputOverrideFunction& override_func) const
+{
+ bool override_occurred = false;
+ return GetState(override_func, &override_occurred);
+}
+
+AnalogStick::StateData AnalogStick::GetState(const InputOverrideFunction& override_func,
+ bool* override_occurred) const
+{
+ StateData state = GetState();
+ if (!override_func)
+ return state;
+
+ if (const std::optional<ControlState> x_override = override_func(name, X_INPUT_OVERRIDE, state.x))
+ {
+ state.x = *x_override;
+ *override_occurred = true;
+ }
+
+ if (const std::optional<ControlState> y_override = override_func(name, Y_INPUT_OVERRIDE, state.y))
+ {
+ state.y = *y_override;
+ *override_occurred = true;
+ }
+
+ return state;
+}
+
ControlState AnalogStick::GetGateRadiusAtAngle(double ang) const
{
return m_stick_gate->GetRadiusAtAngle(ang);
diff --git a/Source/Core/InputCommon/ControllerEmu/ControlGroup/AnalogStick.h b/Source/Core/InputCommon/ControllerEmu/ControlGroup/AnalogStick.h
index 47e3ad5743..377e63251d 100644
--- a/Source/Core/InputCommon/ControllerEmu/ControlGroup/AnalogStick.h
+++ b/Source/Core/InputCommon/ControllerEmu/ControlGroup/AnalogStick.h
@@ -21,6 +21,8 @@ public:
ControlState GetGateRadiusAtAngle(double ang) const override;
StateData GetState() const;
+ StateData GetState(const InputOverrideFunction& override_func) const;
+ StateData GetState(const InputOverrideFunction& override_func, bool* override_occurred) const;
private:
Control* GetModifierInput() const override;
diff --git a/Source/Core/InputCommon/ControllerEmu/ControlGroup/Buttons.h b/Source/Core/InputCommon/ControllerEmu/ControlGroup/Buttons.h
index 2d02adabf1..652f64ae5f 100644
--- a/Source/Core/InputCommon/ControllerEmu/ControlGroup/Buttons.h
+++ b/Source/Core/InputCommon/ControllerEmu/ControlGroup/Buttons.h
@@ -3,6 +3,7 @@
#pragma once
+#include <cmath>
#include <string>
#include "InputCommon/ControlReference/ControlReference.h"
@@ -24,5 +25,21 @@ public:
for (auto& control : controls)
*buttons |= *(bitmasks++) * control->GetState<bool>();
}
+
+ template <typename C>
+ void GetState(C* const buttons, const C* bitmasks,
+ const InputOverrideFunction& override_func) const
+ {
+ if (!override_func)
+ return GetState(buttons, bitmasks);
+
+ for (auto& control : controls)
+ {
+ ControlState state = control->GetState();
+ if (std::optional<ControlState> state_override = override_func(name, control->name, state))
+ state = *state_override;
+ *buttons |= *(bitmasks++) * (std::lround(state) > 0);
+ }
+ }
};
} // namespace ControllerEmu
diff --git a/Source/Core/InputCommon/ControllerEmu/ControlGroup/ControlGroup.h b/Source/Core/InputCommon/ControllerEmu/ControlGroup/ControlGroup.h
index c08c072aba..fb10bab074 100644
--- a/Source/Core/InputCommon/ControllerEmu/ControlGroup/ControlGroup.h
+++ b/Source/Core/InputCommon/ControllerEmu/ControlGroup/ControlGroup.h
@@ -5,14 +5,18 @@
#include <algorithm>
#include <cmath>
+#include <functional>
#include <memory>
+#include <optional>
#include <string>
+#include <string_view>
#include <type_traits>
#include <vector>
#include "Common/CommonTypes.h"
#include "Common/IniFile.h"
#include "InputCommon/ControllerEmu/Control/Control.h"
+#include "InputCommon/ControllerInterface/CoreDevice.h"
namespace ControllerEmu
{
@@ -27,6 +31,9 @@ class NumericSetting;
template <typename T>
class SettingValue;
+using InputOverrideFunction = std::function<std::optional<ControlState>(
+ const std::string_view group_name, const std::string_view control_name, ControlState state)>;
+
enum class GroupType
{
Other,
diff --git a/Source/Core/InputCommon/ControllerEmu/ControlGroup/Cursor.cpp b/Source/Core/InputCommon/ControllerEmu/ControlGroup/Cursor.cpp
index 043ef37356..7359a4e66d 100644
--- a/Source/Core/InputCommon/ControllerEmu/ControlGroup/Cursor.cpp
+++ b/Source/Core/InputCommon/ControllerEmu/ControlGroup/Cursor.cpp
@@ -82,15 +82,28 @@ ControlState Cursor::GetGateRadiusAtAngle(double ang) const
Cursor::StateData Cursor::GetState(const bool adjusted)
{
- if (!adjusted)
- {
- const auto raw_input = GetReshapableState(false);
+ const ReshapeData input = GetReshapableState(adjusted);
+ const StateData state = adjusted ? UpdateState(input) : StateData{input.x, input.y};
+ return state;
+}
- return {raw_input.x, raw_input.y};
- }
+Cursor::StateData Cursor::GetState(const bool adjusted,
+ const ControllerEmu::InputOverrideFunction& override_func)
+{
+ StateData state = GetState(adjusted);
+ if (!override_func)
+ return state;
+
+ if (const std::optional<ControlState> x_override = override_func(name, X_INPUT_OVERRIDE, state.x))
+ state.x = *x_override;
+ if (const std::optional<ControlState> y_override = override_func(name, Y_INPUT_OVERRIDE, state.y))
+ state.y = *y_override;
- const auto input = GetReshapableState(true);
+ return state;
+}
+Cursor::StateData Cursor::UpdateState(Cursor::ReshapeData input)
+{
// TODO: Using system time is ugly.
// Kill this after state is moved into wiimote rather than this class.
const auto now = Clock::now();
diff --git a/Source/Core/InputCommon/ControllerEmu/ControlGroup/Cursor.h b/Source/Core/InputCommon/ControllerEmu/ControlGroup/Cursor.h
index 5e64ce86dc..3710a40d92 100644
--- a/Source/Core/InputCommon/ControllerEmu/ControlGroup/Cursor.h
+++ b/Source/Core/InputCommon/ControllerEmu/ControlGroup/Cursor.h
@@ -29,6 +29,7 @@ public:
// Modifies the state
StateData GetState(bool adjusted);
+ StateData GetState(bool adjusted, const ControllerEmu::InputOverrideFunction& override_func);
// Yaw movement in radians.
ControlState GetTotalYaw() const;
@@ -40,6 +41,8 @@ public:
ControlState GetVerticalOffset() const;
private:
+ Cursor::StateData UpdateState(Cursor::ReshapeData input);
+
// This is used to reduce the cursor speed for relative input
// to something that makes sense with the default range.
static constexpr double STEP_PER_SEC = 0.01 * 200;
diff --git a/Source/Core/InputCommon/ControllerEmu/ControlGroup/MixedTriggers.cpp b/Source/Core/InputCommon/ControllerEmu/ControlGroup/MixedTriggers.cpp
index 8c2f4cbac5..8783087650 100644
--- a/Source/Core/InputCommon/ControllerEmu/ControlGroup/MixedTriggers.cpp
+++ b/Source/Core/InputCommon/ControllerEmu/ControlGroup/MixedTriggers.cpp
@@ -4,6 +4,7 @@
#include "InputCommon/ControllerEmu/ControlGroup/MixedTriggers.h"
#include <algorithm>
+#include <cmath>
#include <cstddef>
#include <memory>
#include <string>
@@ -63,6 +64,53 @@ void MixedTriggers::GetState(u16* const digital, const u16* bitmasks, ControlSta
}
}
+void MixedTriggers::GetState(u16* digital, const u16* bitmasks, ControlState* analog,
+ const InputOverrideFunction& override_func, bool adjusted) const
+{
+ if (!override_func)
+ return GetState(digital, bitmasks, analog, adjusted);
+
+ const ControlState threshold = GetThreshold();
+ ControlState deadzone = GetDeadzone();
+
+ // Return raw values. (used in UI)
+ if (!adjusted)
+ {
+ deadzone = 0.0;
+ }
+
+ const int trigger_count = int(controls.size() / 2);
+ for (int i = 0; i != trigger_count; ++i)
+ {
+ bool button_bool = false;
+ const ControlState button_value = ApplyDeadzone(controls[i]->GetState(), deadzone);
+ ControlState analog_value = ApplyDeadzone(controls[trigger_count + i]->GetState(), deadzone);
+
+ // Apply threshold:
+ if (button_value > threshold)
+ {
+ analog_value = 1.0;
+ button_bool = true;
+ }
+
+ if (const std::optional<ControlState> button_override =
+ override_func(name, controls[i]->name, static_cast<ControlState>(button_bool)))
+ {
+ button_bool = std::lround(*button_override) > 0;
+ }
+
+ if (const std::optional<ControlState> analog_override =
+ override_func(name, controls[trigger_count + i]->name, analog_value))
+ {
+ analog_value = *analog_override;
+ }
+
+ if (button_bool)
+ *digital |= bitmasks[i];
+ analog[i] = std::min(analog_value, 1.0);
+ }
+}
+
ControlState MixedTriggers::GetDeadzone() const
{
return m_deadzone_setting.GetValue() / 100;
diff --git a/Source/Core/InputCommon/ControllerEmu/ControlGroup/MixedTriggers.h b/Source/Core/InputCommon/ControllerEmu/ControlGroup/MixedTriggers.h
index fcd98b279e..2e1014d047 100644
--- a/Source/Core/InputCommon/ControllerEmu/ControlGroup/MixedTriggers.h
+++ b/Source/Core/InputCommon/ControllerEmu/ControlGroup/MixedTriggers.h
@@ -17,6 +17,8 @@ public:
void GetState(u16* digital, const u16* bitmasks, ControlState* analog,
bool adjusted = true) const;
+ void GetState(u16* digital, const u16* bitmasks, ControlState* analog,
+ const InputOverrideFunction& override_func, bool adjusted = true) const;
ControlState GetDeadzone() const;
ControlState GetThreshold() const;
diff --git a/Source/Core/InputCommon/ControllerEmu/ControlGroup/Slider.cpp b/Source/Core/InputCommon/ControllerEmu/ControlGroup/Slider.cpp
index f0516a567f..708831a4c3 100644
--- a/Source/Core/InputCommon/ControllerEmu/ControlGroup/Slider.cpp
+++ b/Source/Core/InputCommon/ControllerEmu/ControlGroup/Slider.cpp
@@ -35,4 +35,21 @@ Slider::StateData Slider::GetState() const
return {std::clamp(ApplyDeadzone(state, deadzone), -1.0, 1.0)};
}
+
+Slider::StateData Slider::GetState(const InputOverrideFunction& override_func) const
+{
+ if (!override_func)
+ return GetState();
+
+ const ControlState deadzone = m_deadzone_setting.GetValue() / 100;
+ ControlState state = controls[1]->GetState() - controls[0]->GetState();
+
+ state = ApplyDeadzone(state, deadzone);
+
+ if (std::optional<ControlState> state_override = override_func(name, X_INPUT_OVERRIDE, state))
+ state = *state_override;
+
+ return {std::clamp(state, -1.0, 1.0)};
+}
+
} // namespace ControllerEmu
diff --git a/Source/Core/InputCommon/ControllerEmu/ControlGroup/Slider.h b/Source/Core/InputCommon/ControllerEmu/ControlGroup/Slider.h
index 9d1bf697a5..0e635da235 100644
--- a/Source/Core/InputCommon/ControllerEmu/ControlGroup/Slider.h
+++ b/Source/Core/InputCommon/ControllerEmu/ControlGroup/Slider.h
@@ -23,6 +23,9 @@ public:
explicit Slider(const std::string& name_);
StateData GetState() const;
+ StateData GetState(const InputOverrideFunction& override_func) const;
+
+ static constexpr const char* X_INPUT_OVERRIDE = "X";
private:
SettingValue<double> m_deadzone_setting;
diff --git a/Source/Core/InputCommon/ControllerEmu/ControlGroup/Triggers.cpp b/Source/Core/InputCommon/ControllerEmu/ControlGroup/Triggers.cpp
index 17e64d2a8b..321c9272d0 100644
--- a/Source/Core/InputCommon/ControllerEmu/ControlGroup/Triggers.cpp
+++ b/Source/Core/InputCommon/ControllerEmu/ControlGroup/Triggers.cpp
@@ -6,6 +6,7 @@
#include <algorithm>
#include <cstddef>
#include <memory>
+#include <optional>
#include <string>
#include "Common/Common.h"
@@ -31,4 +32,25 @@ Triggers::StateData Triggers::GetState() const
return result;
}
+
+Triggers::StateData Triggers::GetState(const InputOverrideFunction& override_func) const
+{
+ if (!override_func)
+ return GetState();
+
+ const size_t trigger_count = controls.size();
+ const ControlState deadzone = m_deadzone_setting.GetValue() / 100;
+
+ StateData result(trigger_count);
+ for (size_t i = 0; i < trigger_count; ++i)
+ {
+ ControlState state = ApplyDeadzone(controls[i]->GetState(), deadzone);
+ if (std::optional<ControlState> state_override = override_func(name, controls[i]->name, state))
+ state = *state_override;
+ result.data[i] = std::min(state, 1.0);
+ }
+
+ return result;
+}
+
} // namespace ControllerEmu
diff --git a/Source/Core/InputCommon/ControllerEmu/ControlGroup/Triggers.h b/Source/Core/InputCommon/ControllerEmu/ControlGroup/Triggers.h
index 2ea02bedb5..c73dee9cfa 100644
--- a/Source/Core/InputCommon/ControllerEmu/ControlGroup/Triggers.h
+++ b/Source/Core/InputCommon/ControllerEmu/ControlGroup/Triggers.h
@@ -26,6 +26,7 @@ public:
explicit Triggers(const std::string& name);
StateData GetState() const;
+ StateData GetState(const InputOverrideFunction& override_func) const;
private:
SettingValue<double> m_deadzone_setting;
diff --git a/Source/Core/InputCommon/ControllerEmu/ControllerEmu.cpp b/Source/Core/InputCommon/ControllerEmu/ControllerEmu.cpp
index 0a3de3e391..dc9830de3f 100644
--- a/Source/Core/InputCommon/ControllerEmu/ControllerEmu.cpp
+++ b/Source/Core/InputCommon/ControllerEmu/ControllerEmu.cpp
@@ -6,6 +6,7 @@
#include <memory>
#include <mutex>
#include <string>
+#include <utility>
#include "Common/IniFile.h"
@@ -176,4 +177,15 @@ void EmulatedController::LoadDefaults(const ControllerInterface& ciface)
SetDefaultDevice(default_device_string);
}
}
+
+void EmulatedController::SetInputOverrideFunction(InputOverrideFunction override_func)
+{
+ m_input_override_function = std::move(override_func);
+}
+
+void EmulatedController::ClearInputOverrideFunction()
+{
+ m_input_override_function = {};
+}
+
} // namespace ControllerEmu
diff --git a/Source/Core/InputCommon/ControllerEmu/ControllerEmu.h b/Source/Core/InputCommon/ControllerEmu/ControllerEmu.h
index 2db991eb82..b0e514d20a 100644
--- a/Source/Core/InputCommon/ControllerEmu/ControllerEmu.h
+++ b/Source/Core/InputCommon/ControllerEmu/ControllerEmu.h
@@ -15,6 +15,7 @@
#include "Common/IniFile.h"
#include "Common/MathUtil.h"
#include "InputCommon/ControlReference/ExpressionParser.h"
+#include "InputCommon/ControllerEmu/ControlGroup/ControlGroup.h"
#include "InputCommon/ControllerInterface/CoreDevice.h"
class ControllerInterface;
@@ -184,6 +185,9 @@ public:
void SetDefaultDevice(const std::string& device);
void SetDefaultDevice(ciface::Core::DeviceQualifier devq);
+ void SetInputOverrideFunction(InputOverrideFunction override_func);
+ void ClearInputOverrideFunction();
+
void UpdateReferences(const ControllerInterface& devi);
void UpdateSingleControlReference(const ControllerInterface& devi, ControlReference* ref);
@@ -228,6 +232,8 @@ protected:
// so theirs won't be used (and thus shouldn't even exist).
ciface::ExpressionParser::ControlEnvironment::VariableContainer m_expression_vars;
+ InputOverrideFunction m_input_override_function;
+
void UpdateReferences(ciface::ExpressionParser::ControlEnvironment& env);
private:
diff --git a/Source/Core/InputCommon/ControllerEmu/StickGate.h b/Source/Core/InputCommon/ControllerEmu/StickGate.h
index 528aa4a5c8..831762fda3 100644
--- a/Source/Core/InputCommon/ControllerEmu/StickGate.h
+++ b/Source/Core/InputCommon/ControllerEmu/StickGate.h
@@ -106,6 +106,10 @@ public:
const ReshapeData& GetCenter() const;
void SetCenter(ReshapeData center);
+ static constexpr const char* X_INPUT_OVERRIDE = "X";
+ static constexpr const char* Y_INPUT_OVERRIDE = "Y";
+ static constexpr const char* Z_INPUT_OVERRIDE = "Z";
+
protected:
ReshapeData Reshape(ControlState x, ControlState y, ControlState modifier = 0.0,
ControlState clamp = 1.0) const;