InputManager: Switch InputEventHandler to std::variant

This commit is contained in:
Connor McLaughlin 2022-04-25 15:37:54 +10:00 committed by refractionpcsx2
parent a524410b0a
commit f13ad4fcb3
1 changed files with 20 additions and 100 deletions

View File

@ -25,6 +25,7 @@
#include <mutex>
#include <sstream>
#include <unordered_map>
#include <variant>
#include <vector>
// ------------------------------------------------------------------------
@ -45,102 +46,7 @@ enum : u32
// This class acts as an adapter to convert from normalized values to
// binary values when the callback is a binary/button handler. That way
// you don't need to convert float->bool in your callbacks.
class InputEventHandler
{
public:
InputEventHandler()
{
new (&u.button) InputButtonEventHandler;
is_axis = false;
}
InputEventHandler(InputButtonEventHandler button)
{
new (&u.button) InputButtonEventHandler(std::move(button));
is_axis = false;
}
InputEventHandler(InputAxisEventHandler axis)
{
new (&u.axis) InputAxisEventHandler(std::move(axis));
is_axis = true;
}
InputEventHandler(const InputEventHandler& copy)
{
if (copy.is_axis)
new (&u.axis) InputAxisEventHandler(copy.u.axis);
else
new (&u.button) InputButtonEventHandler(copy.u.button);
is_axis = copy.is_axis;
}
InputEventHandler(InputEventHandler&& move)
{
if (move.is_axis)
new (&u.axis) InputAxisEventHandler(std::move(move.u.axis));
else
new (&u.button) InputButtonEventHandler(std::move(move.u.button));
is_axis = move.is_axis;
}
~InputEventHandler()
{
// call the right destructor... :D
if (is_axis)
u.axis.InputAxisEventHandler::~InputAxisEventHandler();
else
u.button.InputButtonEventHandler::~InputButtonEventHandler();
}
InputEventHandler& operator=(const InputEventHandler& copy)
{
InputEventHandler::~InputEventHandler();
if (copy.is_axis)
new (&u.axis) InputAxisEventHandler(copy.u.axis);
else
new (&u.button) InputButtonEventHandler(copy.u.button);
is_axis = copy.is_axis;
return *this;
}
InputEventHandler& operator=(InputEventHandler&& move)
{
InputEventHandler::~InputEventHandler();
if (move.is_axis)
new (&u.axis) InputAxisEventHandler(std::move(move.u.axis));
else
new (&u.button) InputButtonEventHandler(std::move(move.u.button));
is_axis = move.is_axis;
return *this;
}
__fi bool IsAxis() const { return is_axis; }
__fi void Invoke(float value) const
{
if (is_axis)
u.axis(value);
else
u.button(value > 0.0f);
}
private:
union HandlerUnion
{
// constructor/destructor needs to be declared
HandlerUnion() {}
~HandlerUnion() {}
InputButtonEventHandler button;
InputAxisEventHandler axis;
} u;
bool is_axis;
};
using InputEventHandler = std::variant<InputAxisEventHandler, InputButtonEventHandler>;
// ------------------------------------------------------------------------
// Binding Type
@ -194,6 +100,8 @@ namespace InputManager
static void AddBindings(const std::vector<std::string>& bindings, const InputEventHandler& handler);
static bool ParseBindingAndGetSource(const std::string_view& binding, InputBindingKey* key, InputSource** source);
static bool IsAxisHandler(const InputEventHandler& handler);
static void AddHotkeyBindings(SettingsInterface& si);
static void AddPadBindings(SettingsInterface& si, u32 pad, const char* default_type);
static void UpdateContinuedVibration();
@ -639,6 +547,11 @@ bool InputManager::HasAnyBindingsForKey(InputBindingKey key)
return (s_binding_map.find(key.MaskDirection()) != s_binding_map.end());
}
bool InputManager::IsAxisHandler(const InputEventHandler& handler)
{
return std::holds_alternative<InputAxisEventHandler>(handler);
}
bool InputManager::InvokeEvents(InputBindingKey key, float value)
{
if (DoEventHook(key, value))
@ -658,7 +571,7 @@ bool InputManager::InvokeEvents(InputBindingKey key, float value)
for (auto it = range.first; it != range.second; ++it)
{
InputBinding* binding = it->second.get();
if (binding->handler.IsAxis())
if (IsAxisHandler(binding->handler))
continue;
// find the key which matches us
@ -702,7 +615,7 @@ bool InputManager::InvokeEvents(InputBindingKey key, float value)
// Don't register the key press when we're part of a longer chord. That way,
// the state won't change, and it won't get the released event either.
if (longest_hotkey_binding && new_state && !binding->handler.IsAxis() &&
if (longest_hotkey_binding && new_state && !IsAxisHandler(binding->handler) &&
binding->num_keys != longest_hotkey_binding->num_keys)
{
continue;
@ -719,11 +632,18 @@ bool InputManager::InvokeEvents(InputBindingKey key, float value)
0.0f);
// axes are fired regardless of a state change, unless they're zero
// (but going from not-zero to zero will still fire, because of the full state)
// for buttons, we can use the state of the last chord key, because it'll be 1 on press,
// and 0 on release (when the full state changes).
if (prev_full_state != new_full_state || (binding->handler.IsAxis() && value_to_pass > 0.0f))
if (IsAxisHandler(binding->handler))
{
binding->handler.Invoke(value_to_pass);
if (prev_full_state != new_full_state || value_to_pass >= 0.0f)
std::get<InputAxisEventHandler>(binding->handler)(value_to_pass);
}
else
{
if (prev_full_state != new_full_state)
std::get<InputButtonEventHandler>(binding->handler)(value_to_pass > 0.0f);
}
// bail out, since we shouldn't have the same key twice in the chord