#pragma once
#include <unordered_map>
#include <vector>
#include <string>
#include "Common/Input/KeyCodes.h"
#include "Common/Log.h"
enum InputDeviceID {
DEVICE_ID_ANY = -1,
DEVICE_ID_DEFAULT = 0,
DEVICE_ID_KEYBOARD = 1,
DEVICE_ID_MOUSE = 2,
DEVICE_ID_PAD_0 = 10,
DEVICE_ID_PAD_1 = 11,
DEVICE_ID_PAD_2 = 12,
DEVICE_ID_PAD_3 = 13,
DEVICE_ID_PAD_4 = 14,
DEVICE_ID_PAD_5 = 15,
DEVICE_ID_PAD_6 = 16,
DEVICE_ID_PAD_7 = 17,
DEVICE_ID_PAD_8 = 18,
DEVICE_ID_PAD_9 = 19,
DEVICE_ID_XINPUT_0 = 20,
DEVICE_ID_XINPUT_1 = 21,
DEVICE_ID_XINPUT_2 = 22,
DEVICE_ID_XINPUT_3 = 23,
DEVICE_ID_ACCELEROMETER = 30,
DEVICE_ID_XR_CONTROLLER_LEFT = 40,
DEVICE_ID_XR_CONTROLLER_RIGHT = 41,
DEVICE_ID_TOUCH = 42,
DEVICE_ID_COUNT,
};
inline InputDeviceID operator +(InputDeviceID deviceID, int addend) {
return (InputDeviceID)((int)deviceID + addend);
}
const int MAX_NUM_PADS = 10;
const char *GetDeviceName(int deviceId);
#ifndef MAX_KEYQUEUESIZE
#define MAX_KEYQUEUESIZE 20
#endif
static const int AXIS_BIND_NKCODE_START = 4000;
inline int TranslateKeyCodeToAxis(int keyCode, int *direction) {
if (keyCode < AXIS_BIND_NKCODE_START)
return 0;
int k = keyCode - AXIS_BIND_NKCODE_START;
if (direction)
*direction = k & 1 ? -1 : 1;
return k / 2;
}
class InputMapping {
private:
static inline int TranslateKeyCodeFromAxis(int axisId, int direction) {
return AXIS_BIND_NKCODE_START + axisId * 2 + (direction < 0 ? 1 : 0);
}
public:
InputMapping() : deviceId(DEVICE_ID_DEFAULT), keyCode(0) {}
InputMapping(InputDeviceID _deviceId, int key) : deviceId(_deviceId), keyCode(key) {}
InputMapping(InputDeviceID _deviceId, int axis, int direction) : deviceId(_deviceId), keyCode(TranslateKeyCodeFromAxis(axis, direction)) {
_dbg_assert_(direction != 0);
}
static InputMapping FromConfigString(std::string_view str);
std::string ToConfigString() const;
InputDeviceID deviceId;
int keyCode;
bool IsAxis() const {
return keyCode >= AXIS_BIND_NKCODE_START;
}
int Axis(int *direction) const {
_dbg_assert_(IsAxis());
return TranslateKeyCodeToAxis(keyCode, direction);
}
InputMapping FlipDirection() const {
_dbg_assert_(IsAxis());
InputMapping other = *this;
other.keyCode ^= 1;
return other;
}
bool operator < (const InputMapping &other) const {
if (deviceId < other.deviceId) return true;
if (deviceId > other.deviceId) return false;
if (keyCode < other.keyCode) return true;
return false;
}
bool operator > (const InputMapping &other) const {
if (deviceId > other.deviceId) return true;
if (deviceId < other.deviceId) return false;
if (keyCode > other.keyCode) return true;
return false;
}
bool operator == (const InputMapping &other) const {
if (deviceId != other.deviceId && deviceId != DEVICE_ID_ANY && other.deviceId != DEVICE_ID_ANY) return false;
if (keyCode != other.keyCode) return false;
return true;
}
bool operator != (const InputMapping &other) const {
return !(*this == other);
}
void FormatDebug(char *buffer, size_t bufSize) const;
};
enum {
TOUCH_MOVE = 1 << 0,
TOUCH_DOWN = 1 << 1,
TOUCH_UP = 1 << 2,
TOUCH_CANCEL = 1 << 3,
TOUCH_WHEEL = 1 << 4,
TOUCH_MOUSE = 1 << 5,
TOUCH_RELEASE_ALL = 1 << 6,
TOUCH_HOVER = 1 << 7,
TOUCH_TOOL_MASK = 7 << 10,
TOUCH_TOOL_UNKNOWN = 0 << 10,
TOUCH_TOOL_FINGER = 1 << 10,
TOUCH_TOOL_STYLUS = 2 << 10,
TOUCH_TOOL_MOUSE = 3 << 10,
TOUCH_TOOL_ERASER = 4 << 10,
TOUCH_MAX_POINTERS = 10,
};
struct TouchInput {
float x;
float y;
int id;
int buttons;
int flags;
double timestamp;
};
#undef KEY_DOWN
#undef KEY_UP
enum {
KEY_DOWN = 1 << 0,
KEY_UP = 1 << 1,
KEY_HASWHEELDELTA = 1 << 2,
KEY_IS_REPEAT = 1 << 3,
KEY_CHAR = 1 << 4,
};
struct KeyInput {
KeyInput() {}
KeyInput(InputDeviceID devId, InputKeyCode code, int fl) : deviceId(devId), keyCode(code), flags(fl) {}
KeyInput(InputDeviceID devId, int unicode) : deviceId(devId), unicodeChar(unicode), flags(KEY_CHAR) {}
InputDeviceID deviceId;
union {
InputKeyCode keyCode;
int unicodeChar;
};
int flags;
int Delta() const {
return flags >> 16;
}
};
struct AxisInput {
InputDeviceID deviceId;
InputAxis axisId;
float value;
};
extern std::vector<InputMapping> dpadKeys;
extern std::vector<InputMapping> confirmKeys;
extern std::vector<InputMapping> cancelKeys;
extern std::vector<InputMapping> infoKeys;
extern std::vector<InputMapping> tabLeftKeys;
extern std::vector<InputMapping> tabRightKeys;
void SetDPadKeys(const std::vector<InputMapping> &leftKey, const std::vector<InputMapping> &rightKey,
const std::vector<InputMapping> &upKey, const std::vector<InputMapping> &downKey);
void SetConfirmCancelKeys(const std::vector<InputMapping> &confirm, const std::vector<InputMapping> &cancel);
void SetTabLeftRightKeys(const std::vector<InputMapping> &tabLeft, const std::vector<InputMapping> &tabRight);
void SetInfoKeys(const std::vector<InputMapping> &info);
void SetAnalogFlipY(const std::unordered_map<InputDeviceID, int> &flipYByDeviceId);
int GetAnalogYDirection(InputDeviceID deviceId);
extern bool g_IsMappingMouseInput;