summaryrefslogtreecommitdiff
path: root/Source/Core/InputCommon/ControlReference
diff options
context:
space:
mode:
authorJordan Woyak <jordan.woyak@gmail.com>2019-02-26 19:46:21 -0600
committerJordan Woyak <jordan.woyak@gmail.com>2019-03-03 18:36:16 -0600
commit48b69ca01841ba724049895a83d8d88ec95d66de (patch)
tree43fda39dfdccc0999afdb0aaa4e2ab1fd5874c39 /Source/Core/InputCommon/ControlReference
parent13b2b93d3d12e4c8491ed82c63d52a24a4849476 (diff)
ControllerInterface: Input detection improvements.
Diffstat (limited to 'Source/Core/InputCommon/ControlReference')
-rw-r--r--Source/Core/InputCommon/ControlReference/ControlReference.cpp81
-rw-r--r--Source/Core/InputCommon/ControlReference/ExpressionParser.cpp14
2 files changed, 55 insertions, 40 deletions
diff --git a/Source/Core/InputCommon/ControlReference/ControlReference.cpp b/Source/Core/InputCommon/ControlReference/ControlReference.cpp
index b3355418e2..3132baf07b 100644
--- a/Source/Core/InputCommon/ControlReference/ControlReference.cpp
+++ b/Source/Core/InputCommon/ControlReference/ControlReference.cpp
@@ -2,6 +2,10 @@
// Licensed under GPLv2+
// Refer to the license.txt file included.
+#include "InputCommon/ControlReference/ControlReference.h"
+
+#include <vector>
+
#include "Common/Thread.h"
// For InputGateOn()
// This is a bad layering violation, but it's the cleanest
@@ -9,11 +13,13 @@
#include "Core/ConfigManager.h"
#include "Core/Host.h"
-#include "InputCommon/ControlReference/ControlReference.h"
-
using namespace ciface::ExpressionParser;
+namespace
+{
+// Compared to an input's current state (ideally 1.0) minus abs(initial_state) (ideally 0.0).
constexpr ControlState INPUT_DETECT_THRESHOLD = 0.55;
+} // namespace
bool ControlReference::InputGateOn()
{
@@ -110,56 +116,53 @@ ControlState OutputReference::State(const ControlState state)
return 0.0;
}
-//
-// InputReference :: Detect
-//
-// Wait for input on all binded devices
-// supports not detecting inputs that were held down at the time of Detect start,
-// which is useful for those crazy flightsticks that have certain buttons that are always held down
-// or some crazy axes or something
-// upon input, return pointer to detected Control
-// else return nullptr
-//
+// Wait for input on a particular device.
+// Inputs are considered if they are first seen in a neutral state.
+// This is useful for crazy flightsticks that have certain buttons that are always held down
+// and also properly handles detection when using "FullAnalogSurface" inputs.
+// Upon input, return a pointer to the detected Control, else return nullptr.
ciface::Core::Device::Control* InputReference::Detect(const unsigned int ms,
ciface::Core::Device* const device)
{
- unsigned int time = 0;
- std::vector<bool> states(device->Inputs().size());
+ struct InputState
+ {
+ ciface::Core::Device::Input& input;
+ ControlState initial_state;
+ };
- if (device->Inputs().empty())
- return nullptr;
+ std::vector<InputState> input_states;
+ for (auto* input : device->Inputs())
+ {
+ // Don't detect things like absolute cursor position.
+ if (!input->IsDetectable())
+ continue;
+
+ // Undesirable axes will have negative values here when trying to map a "FullAnalogSurface".
+ input_states.push_back({*input, input->GetState()});
+ }
- // get starting state of all inputs,
- // so we can ignore those that were activated at time of Detect start
- std::vector<ciface::Core::Device::Input*>::const_iterator i = device->Inputs().begin(),
- e = device->Inputs().end();
- for (std::vector<bool>::iterator state = states.begin(); i != e; ++i)
- *state++ = ((*i)->GetState() > (1 - INPUT_DETECT_THRESHOLD));
+ if (input_states.empty())
+ return nullptr;
+ unsigned int time = 0;
while (time < ms)
{
+ Common::SleepCurrentThread(10);
+ time += 10;
+
device->UpdateInput();
- i = device->Inputs().begin();
- for (std::vector<bool>::iterator state = states.begin(); i != e; ++i, ++state)
+ for (auto& input_state : input_states)
{
- // detected an input
- if ((*i)->IsDetectable() && (*i)->GetState() > INPUT_DETECT_THRESHOLD)
- {
- // input was released at some point during Detect call
- // return the detected input
- if (false == *state)
- return *i;
- }
- else if ((*i)->GetState() < (1 - INPUT_DETECT_THRESHOLD))
- {
- *state = false;
- }
+ // We want an input that was initially 0.0 and currently 1.0.
+ const auto detection_score =
+ (input_state.input.GetState() - std::abs(input_state.initial_state));
+
+ if (detection_score > INPUT_DETECT_THRESHOLD)
+ return &input_state.input;
}
- Common::SleepCurrentThread(10);
- time += 10;
}
- // no input was detected
+ // No input was detected. :'(
return nullptr;
}
diff --git a/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp b/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp
index ba3f78170d..a73b1c94cf 100644
--- a/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp
+++ b/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp
@@ -217,7 +217,19 @@ public:
std::shared_ptr<Device> m_device;
explicit ControlExpression(ControlQualifier qualifier_) : qualifier(qualifier_) {}
- ControlState GetValue() const override { return control ? control->ToInput()->GetState() : 0.0; }
+ ControlState GetValue() const override
+ {
+ if (!control)
+ return 0.0;
+
+ // Note: Inputs may return negative values in situations where opposing directions are
+ // activated. We clamp off the negative values here.
+
+ // FYI: Clamping values greater than 1.0 is purposely not done to support unbounded values in
+ // the future. (e.g. raw accelerometer/gyro data)
+
+ return std::max(0.0, control->ToInput()->GetState());
+ }
void SetValue(ControlState value) override
{
if (control)