#pragma once
#include "irrlichttypes.h"
#include "keys.h"
#include <Keycodes.h>
#include <IEventReceiver.h>
#include <string>
#include <variant>
#include <vector>
* This fits into 64 bits, so prefer passing this by value.
*/
class KeyPress
{
public:
* The type of the input value.
*
* When constructing the KeyPress object from an Irrilcht event, the direction of the gamepad axis is
* determined by the value along the axis. 0 is mapped to the positive direction.
*/
enum class InputType {
KEYBOARD,
MOUSE_BUTTON,
GAME_ACTION,
GAMEPAD_BUTTON,
GAMEPAD_AXIS_PLUS,
GAMEPAD_AXIS_MINUS,
};
enum class InputSourceType {
INVALID,
KEYBOARD,
MOUSE,
TOUCHSCREEN,
GAMEPAD
};
KeyPress() = default;
KeyPress(const std::string &name);
KeyPress(const SEvent::SKeyInput &in);
KeyPress(const SEvent::SMouseInput &in);
KeyPress(const SEvent::SGamepadButtonEvent &in);
KeyPress(const SEvent::SGamepadAxisEvent &in);
KeyPress(GameKeyType key) : value(key) {}
std::string sym() const;
std::string name() const;
u32 getScancode() const
{
if (auto pv = getIf<InputType::KEYBOARD>())
return *pv;
return 0;
}
bool operator==(KeyPress o) const {
return value == o.value;
}
bool operator!=(KeyPress o) const {
return !(*this == o);
}
bool operator<(KeyPress o) const {
return value < o.value;
}
InputType getType() const {
return static_cast<InputType>(value.index());
}
InputSourceType getSourceType() const;
KeyPress getOppositeAxisDirection() const;
operator bool() const;
static KeyPress getSpecialKey(const std::string &name);
private:
using value_type = std::variant<u32, u32, GameKeyType, GamepadButton, GamepadAxis, GamepadAxis>;
template<InputType I>
using value_alternative_t = std::variant_alternative_t<static_cast<size_t>(I), value_type>;
template<InputType I>
bool loadUnsignedFromPrefix(const std::string &name, const std::string &prefix);
bool loadFromScancode(const std::string &name);
void loadFromKey(EKEY_CODE keycode, wchar_t keychar);
value_type value;
template<InputType I>
value_alternative_t<I> get() const {
return std::get<static_cast<size_t>(I)>(value);
}
template<InputType I, typename T>
T getCast() const {
return static_cast<T>(get<I>());
}
template<InputType I>
std::add_pointer_t<const value_alternative_t<I>> getIf() const {
return std::get_if<static_cast<size_t>(I)>(&value);
}
template<InputType I>
void emplace(value_alternative_t<I> newValue) {
value.emplace<static_cast<size_t>(I)>(newValue);
}
friend std::hash<KeyPress>;
};
template <>
struct std::hash<KeyPress>
{
size_t operator()(KeyPress kp) const noexcept {
return std::hash<KeyPress::value_type>{}(kp.value);
}
};
#define EscapeKey KeyPress::getSpecialKey("KEY_ESCAPE")
const std::vector<KeyPress> &getKeySetting(const std::string &settingname);
bool keySettingHasMatch(const std::string &settingname, KeyPress kp);
void clearKeyCache();
struct KeyPressEvent {
KeyPress key;
float analog_value = 0;
KeyPressEvent(const SEvent &event);
operator bool() const {
return key;
}
bool isPressed() const {
return analog_value > 0;
}
};