From c389d68186ea7fa95d763d7bb55bc09e5a45c4cd Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Wed, 27 Feb 2019 18:10:18 -0600 Subject: ControllerInterface/DolphinQt: Make mapping "all devices" way less hacky. --- .../ControlReference/ControlReference.cpp | 89 ---------------------- .../ControlReference/ControlReference.h | 6 -- .../InputCommon/ControllerInterface/Device.cpp | 87 +++++++++++++++++++-- .../Core/InputCommon/ControllerInterface/Device.h | 3 + 4 files changed, 85 insertions(+), 100 deletions(-) (limited to 'Source/Core/InputCommon') diff --git a/Source/Core/InputCommon/ControlReference/ControlReference.cpp b/Source/Core/InputCommon/ControlReference/ControlReference.cpp index 3132baf07b..1f392c4e3a 100644 --- a/Source/Core/InputCommon/ControlReference/ControlReference.cpp +++ b/Source/Core/InputCommon/ControlReference/ControlReference.cpp @@ -4,9 +4,6 @@ #include "InputCommon/ControlReference/ControlReference.h" -#include - -#include "Common/Thread.h" // For InputGateOn() // This is a bad layering violation, but it's the cleanest // place I could find to put it. @@ -15,12 +12,6 @@ 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() { return SConfig::GetInstance().m_BackgroundInput || Host_RendererHasFocus() || @@ -115,83 +106,3 @@ ControlState OutputReference::State(const ControlState state) m_parsed_expression->SetValue(state * range); return 0.0; } - -// 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) -{ - struct InputState - { - ciface::Core::Device::Input& input; - ControlState initial_state; - }; - - std::vector 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()}); - } - - if (input_states.empty()) - return nullptr; - - unsigned int time = 0; - while (time < ms) - { - Common::SleepCurrentThread(10); - time += 10; - - device->UpdateInput(); - for (auto& input_state : input_states) - { - // 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; - } - } - - // No input was detected. :'( - return nullptr; -} - -// -// OutputReference :: Detect -// -// Totally different from the inputReference detect / I have them combined so it was simpler to make -// the GUI. -// The GUI doesn't know the difference between an input and an output / it's odd but I was lazy and -// it was easy -// -// set all binded outputs to power for x milliseconds return false -// -ciface::Core::Device::Control* OutputReference::Detect(const unsigned int ms, - ciface::Core::Device* const device) -{ - // ignore device - - // don't hang if we don't even have any controls mapped - if (BoundCount() > 0) - { - State(1); - unsigned int slept = 0; - - // this loop is to make stuff like flashing keyboard LEDs work - while (ms > (slept += 10)) - Common::SleepCurrentThread(10); - - State(0); - } - return nullptr; -} diff --git a/Source/Core/InputCommon/ControlReference/ControlReference.h b/Source/Core/InputCommon/ControlReference/ControlReference.h index 6740ed8be0..83fa288676 100644 --- a/Source/Core/InputCommon/ControlReference/ControlReference.h +++ b/Source/Core/InputCommon/ControlReference/ControlReference.h @@ -26,8 +26,6 @@ public: virtual ~ControlReference(); virtual ControlState State(const ControlState state = 0) = 0; - virtual ciface::Core::Device::Control* Detect(const unsigned int ms, - ciface::Core::Device* const device) = 0; virtual bool IsInput() const = 0; int BoundCount() const; @@ -57,8 +55,6 @@ public: InputReference(); bool IsInput() const override; ControlState State(const ControlState state) override; - ciface::Core::Device::Control* Detect(const unsigned int ms, - ciface::Core::Device* const device) override; }; // @@ -72,6 +68,4 @@ public: OutputReference(); bool IsInput() const override; ControlState State(const ControlState state) override; - ciface::Core::Device::Control* Detect(const unsigned int ms, - ciface::Core::Device* const device) override; }; diff --git a/Source/Core/InputCommon/ControllerInterface/Device.cpp b/Source/Core/InputCommon/ControllerInterface/Device.cpp index efe1372711..14f5cb23d9 100644 --- a/Source/Core/InputCommon/ControllerInterface/Device.cpp +++ b/Source/Core/InputCommon/ControllerInterface/Device.cpp @@ -11,16 +11,15 @@ #include #include "Common/StringUtil.h" +#include "Common/Thread.h" namespace ciface { namespace Core { -// -// Device :: ~Device -// -// Destructor, delete all inputs/outputs on device destruction -// +// Compared to an input's current state (ideally 1.0) minus abs(initial_state) (ideally 0.0). +constexpr ControlState INPUT_DETECT_THRESHOLD = 0.55; + Device::~Device() { // delete inputs @@ -220,5 +219,83 @@ bool DeviceContainer::HasConnectedDevice(const DeviceQualifier& qualifier) const const auto device = FindDevice(qualifier); return device != nullptr && device->IsValid(); } + +// 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 the detected Device and Input, else return nullptrs +std::pair, Device::Input*> +DeviceContainer::DetectInput(u32 wait_ms, std::vector device_strings) +{ + struct InputState + { + ciface::Core::Device::Input& input; + ControlState initial_state; + }; + + struct DeviceState + { + std::shared_ptr device; + + std::vector input_states; + }; + + // Acquire devices and initial input states. + std::vector device_states; + for (auto& device_string : device_strings) + { + DeviceQualifier dq; + dq.FromString(device_string); + auto device = FindDevice(dq); + + if (!device) + continue; + + std::vector 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()}); + } + + if (!input_states.empty()) + device_states.emplace_back(DeviceState{std::move(device), std::move(input_states)}); + } + + if (device_states.empty()) + return {}; + + u32 time = 0; + while (time < wait_ms) + { + Common::SleepCurrentThread(10); + time += 10; + + for (auto& device_state : device_states) + { + device_state.device->UpdateInput(); + for (auto& input_state : device_state.input_states) + { + // 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 {device_state.device, &input_state.input}; + } + } + } + + // No input was detected. :'( + return {}; +} + } // namespace Core } // namespace ciface diff --git a/Source/Core/InputCommon/ControllerInterface/Device.h b/Source/Core/InputCommon/ControllerInterface/Device.h index 0ee2b31444..7d7623ba03 100644 --- a/Source/Core/InputCommon/ControllerInterface/Device.h +++ b/Source/Core/InputCommon/ControllerInterface/Device.h @@ -172,6 +172,9 @@ public: bool HasConnectedDevice(const DeviceQualifier& qualifier) const; + std::pair, Device::Input*> + DetectInput(u32 wait_ms, std::vector device_strings); + protected: mutable std::mutex m_devices_mutex; std::vector> m_devices; -- cgit v1.2.3