InputCommon: Clean up modifier ignoring logic.

This commit is contained in:
Jordan Woyak 2019-11-02 09:55:45 -05:00
parent f7bf26cd60
commit aae913fbc6
1 changed files with 32 additions and 39 deletions

View File

@ -14,6 +14,7 @@
#include <vector> #include <vector>
#include "Common/Common.h" #include "Common/Common.h"
#include "Common/Logging/Log.h"
#include "Common/ScopeGuard.h" #include "Common/ScopeGuard.h"
#include "Common/StringUtil.h" #include "Common/StringUtil.h"
@ -29,24 +30,22 @@ class ControlExpression;
class HotkeySuppressions class HotkeySuppressions
{ {
public: public:
using Modifiers = std::vector<std::unique_ptr<ControlExpression>>;
using Suppressor = std::unique_ptr<Common::ScopeGuard>; using Suppressor = std::unique_ptr<Common::ScopeGuard>;
bool IsSuppressed(Device::Input* input) const bool IsSuppressed(Device::Input* input) const
{ {
// An input is suppressed if it exists in the map (with any modifier). // Input is suppressed if it exists in the map at all.
auto it = m_suppressions.lower_bound({input, nullptr}); return m_suppressions.lower_bound({input, nullptr}) !=
return it != m_suppressions.end() && (it->first.first == input); m_suppressions.lower_bound({input + 1, nullptr});
} }
bool IsSuppressedIgnoringModifiers(Device::Input* input, const Modifiers& ignore_modifiers) const;
// Suppresses each input + modifier pair. // Suppresses each input + modifier pair.
// The returned object removes the suppression on destruction. // The returned object removes the suppression on destruction.
Suppressor MakeSuppressor(const std::vector<std::unique_ptr<ControlExpression>>& modifiers, Suppressor MakeSuppressor(const Modifiers* modifiers,
const std::unique_ptr<ControlExpression>& final_input); const std::unique_ptr<ControlExpression>* final_input);
// Removes suppression for each input + modifier pair.
// The returned object restores the original suppression on destruction.
Suppressor MakeAntiSuppressor(const std::vector<std::unique_ptr<ControlExpression>>& modifiers,
const std::unique_ptr<ControlExpression>& final_input);
private: private:
using Suppression = std::pair<Device::Input*, Device::Input*>; using Suppression = std::pair<Device::Input*, Device::Input*>;
@ -285,32 +284,29 @@ private:
Device::Output* output = nullptr; Device::Output* output = nullptr;
}; };
HotkeySuppressions::Suppressor bool HotkeySuppressions::IsSuppressedIgnoringModifiers(Device::Input* input,
HotkeySuppressions::MakeSuppressor(const std::vector<std::unique_ptr<ControlExpression>>& modifiers, const Modifiers& ignore_modifiers) const
const std::unique_ptr<ControlExpression>& final_input)
{ {
for (auto& modifier : modifiers) // Input is suppressed if it exists in the map with a modifier that we aren't ignoring.
++m_suppressions[{final_input->GetInput(), modifier->GetInput()}]; auto it = m_suppressions.lower_bound({input, nullptr});
auto it_end = m_suppressions.lower_bound({input + 1, nullptr});
return std::make_unique<Common::ScopeGuard>([this, &modifiers, &final_input]() { return std::any_of(it, it_end, [&](auto& s) {
for (auto& modifier : modifiers) return std::none_of(begin(ignore_modifiers), end(ignore_modifiers),
RemoveSuppression(modifier->GetInput(), final_input->GetInput()); [&](auto& m) { return m->GetInput() == s.first.second; });
}); });
} }
HotkeySuppressions::Suppressor HotkeySuppressions::MakeAntiSuppressor( HotkeySuppressions::Suppressor
const std::vector<std::unique_ptr<ControlExpression>>& modifiers, HotkeySuppressions::MakeSuppressor(const Modifiers* modifiers,
const std::unique_ptr<ControlExpression>& final_input) const std::unique_ptr<ControlExpression>* final_input)
{ {
decltype(m_suppressions) unsuppressed_modifiers; for (auto& modifier : *modifiers)
++m_suppressions[{(*final_input)->GetInput(), modifier->GetInput()}];
for (auto& modifier : modifiers) return std::make_unique<Common::ScopeGuard>([this, modifiers, final_input]() {
unsuppressed_modifiers.insert( for (auto& modifier : *modifiers)
m_suppressions.extract({final_input->GetInput(), modifier->GetInput()})); RemoveSuppression(modifier->GetInput(), (*final_input)->GetInput());
return std::make_unique<Common::ScopeGuard>(
[this, unsuppressed_modifiers{std::move(unsuppressed_modifiers)}]() mutable {
m_suppressions.merge(unsuppressed_modifiers);
}); });
} }
@ -474,15 +470,14 @@ public:
{ {
const bool modifiers_pressed = std::all_of(m_modifiers.begin(), m_modifiers.end(), const bool modifiers_pressed = std::all_of(m_modifiers.begin(), m_modifiers.end(),
[](const std::unique_ptr<ControlExpression>& input) { [](const std::unique_ptr<ControlExpression>& input) {
// TODO: kill magic number. return input->GetValue() > CONDITION_THRESHOLD;
return input->GetValue() > 0.5;
}); });
const auto final_input_state = m_final_input->GetValueIgnoringSuppression(); const auto final_input_state = m_final_input->GetValueIgnoringSuppression();
if (modifiers_pressed) if (modifiers_pressed)
{ {
if (final_input_state < 0.5) if (final_input_state < CONDITION_THRESHOLD)
{ {
if (!m_suppressor) if (!m_suppressor)
EnableSuppression(); EnableSuppression();
@ -491,10 +486,8 @@ public:
} }
// Ignore suppression of our own modifiers. This also allows superset modifiers to function. // Ignore suppression of our own modifiers. This also allows superset modifiers to function.
const auto anti_suppression = const bool is_suppressed = s_hotkey_suppressions.IsSuppressedIgnoringModifiers(
s_hotkey_suppressions.MakeAntiSuppressor(m_modifiers, m_final_input); m_final_input->GetInput(), m_modifiers);
const bool is_suppressed = s_hotkey_suppressions.IsSuppressed(m_final_input->GetInput());
// If some other hotkey suppressed us, require a release of final input to be ready again. // If some other hotkey suppressed us, require a release of final input to be ready again.
if (is_suppressed) if (is_suppressed)
@ -538,10 +531,10 @@ public:
private: private:
void EnableSuppression() const void EnableSuppression() const
{ {
m_suppressor = s_hotkey_suppressions.MakeSuppressor(m_modifiers, m_final_input); m_suppressor = s_hotkey_suppressions.MakeSuppressor(&m_modifiers, &m_final_input);
} }
std::vector<std::unique_ptr<ControlExpression>> m_modifiers; HotkeySuppressions::Modifiers m_modifiers;
std::unique_ptr<ControlExpression> m_final_input; std::unique_ptr<ControlExpression> m_final_input;
mutable HotkeySuppressions::Suppressor m_suppressor; mutable HotkeySuppressions::Suppressor m_suppressor;
mutable bool m_is_ready = false; mutable bool m_is_ready = false;