diff options
| author | Jordan Woyak <jordan.woyak@gmail.com> | 2019-02-26 19:46:21 -0600 |
|---|---|---|
| committer | Jordan Woyak <jordan.woyak@gmail.com> | 2019-03-03 18:36:16 -0600 |
| commit | 48b69ca01841ba724049895a83d8d88ec95d66de (patch) | |
| tree | 43fda39dfdccc0999afdb0aaa4e2ab1fd5874c39 /Source/Core/InputCommon/ControlReference | |
| parent | 13b2b93d3d12e4c8491ed82c63d52a24a4849476 (diff) | |
ControllerInterface: Input detection improvements.
Diffstat (limited to 'Source/Core/InputCommon/ControlReference')
| -rw-r--r-- | Source/Core/InputCommon/ControlReference/ControlReference.cpp | 81 | ||||
| -rw-r--r-- | Source/Core/InputCommon/ControlReference/ExpressionParser.cpp | 14 |
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) |
