Merge pull request #3202 from hrydgard/better-controlmap

Better control mapping
This commit is contained in:
Henrik Rydgård 2013-08-17 03:11:52 -07:00
commit d83a6e74a6
14 changed files with 583 additions and 556 deletions

1
.gitignore vendored
View file

@ -18,6 +18,7 @@
*.aps
*.exp
*.qdact
controls.ini
Debug
Release
Windows/x64

View file

@ -24,213 +24,170 @@ namespace KeyMap {
KeyDef AxisDef(int deviceId, int axisId, int direction);
// TODO: Make use const_map.h from native
struct DefaultKeyMap {
static KeyMapping defaultKeyboardMap()
{
KeyMapping m;
m[KeyDef(DEVICE_ID_KEYBOARD, NKCODE_A)] = CTRL_SQUARE;
m[KeyDef(DEVICE_ID_KEYBOARD, NKCODE_S)] = CTRL_TRIANGLE;
m[KeyDef(DEVICE_ID_KEYBOARD, NKCODE_X)] = CTRL_CIRCLE;
m[KeyDef(DEVICE_ID_KEYBOARD, NKCODE_Z)] = CTRL_CROSS;
m[KeyDef(DEVICE_ID_KEYBOARD, NKCODE_Q)] = CTRL_LTRIGGER;
m[KeyDef(DEVICE_ID_KEYBOARD, NKCODE_W)] = CTRL_RTRIGGER;
m[KeyDef(DEVICE_ID_KEYBOARD, NKCODE_SPACE)] = CTRL_START;
#ifdef _WIN32
m[KeyDef(DEVICE_ID_KEYBOARD, NKCODE_V)] = CTRL_SELECT;
#else
m[KeyDef(DEVICE_ID_KEYBOARD, NKCODE_ENTER)] = CTRL_SELECT;
#endif
m[KeyDef(DEVICE_ID_KEYBOARD, NKCODE_DPAD_UP)] = CTRL_UP;
m[KeyDef(DEVICE_ID_KEYBOARD, NKCODE_DPAD_DOWN)] = CTRL_DOWN;
m[KeyDef(DEVICE_ID_KEYBOARD, NKCODE_DPAD_LEFT)] = CTRL_LEFT;
m[KeyDef(DEVICE_ID_KEYBOARD, NKCODE_DPAD_RIGHT)] = CTRL_RIGHT;
m[KeyDef(DEVICE_ID_KEYBOARD, NKCODE_I)] = VIRTKEY_AXIS_Y_MAX;
m[KeyDef(DEVICE_ID_KEYBOARD, NKCODE_K)] = VIRTKEY_AXIS_Y_MIN;
m[KeyDef(DEVICE_ID_KEYBOARD, NKCODE_J)] = VIRTKEY_AXIS_X_MIN;
m[KeyDef(DEVICE_ID_KEYBOARD, NKCODE_L)] = VIRTKEY_AXIS_X_MAX;
m[KeyDef(DEVICE_ID_KEYBOARD, NKCODE_SHIFT_LEFT)] = VIRTKEY_RAPID_FIRE;
m[KeyDef(DEVICE_ID_KEYBOARD, NKCODE_TAB)] = VIRTKEY_UNTHROTTLE;
m[KeyDef(DEVICE_ID_KEYBOARD, NKCODE_GRAVE)] = VIRTKEY_SPEED_TOGGLE;
m[KeyDef(DEVICE_ID_KEYBOARD, NKCODE_ESCAPE)] = VIRTKEY_PAUSE;
return m;
}
static KeyMapping default360Map()
{
KeyMapping m;
m[KeyDef(DEVICE_ID_X360_0, NKCODE_BUTTON_A)] = CTRL_CROSS;
m[KeyDef(DEVICE_ID_X360_0, NKCODE_BUTTON_B)] = CTRL_CIRCLE;
m[KeyDef(DEVICE_ID_X360_0, NKCODE_BUTTON_X)] = CTRL_SQUARE;
m[KeyDef(DEVICE_ID_X360_0, NKCODE_BUTTON_Y)] = CTRL_TRIANGLE;
m[KeyDef(DEVICE_ID_X360_0, NKCODE_DPAD_UP)] = CTRL_UP;
m[KeyDef(DEVICE_ID_X360_0, NKCODE_DPAD_RIGHT)] = CTRL_RIGHT;
m[KeyDef(DEVICE_ID_X360_0, NKCODE_DPAD_DOWN)] = CTRL_DOWN;
m[KeyDef(DEVICE_ID_X360_0, NKCODE_DPAD_LEFT)] = CTRL_LEFT;
m[KeyDef(DEVICE_ID_X360_0, NKCODE_BUTTON_START)] = CTRL_START;
m[KeyDef(DEVICE_ID_X360_0, NKCODE_BUTTON_SELECT)] = CTRL_SELECT;
m[KeyDef(DEVICE_ID_X360_0, NKCODE_BUTTON_L1)] = CTRL_LTRIGGER;
m[KeyDef(DEVICE_ID_X360_0, NKCODE_BUTTON_R1)] = CTRL_RTRIGGER;
m[KeyDef(DEVICE_ID_X360_0, NKCODE_BUTTON_R2)] = VIRTKEY_UNTHROTTLE;
m[KeyDef(DEVICE_ID_X360_0, NKCODE_BUTTON_THUMBR)] = VIRTKEY_PAUSE;
m[KeyDef(DEVICE_ID_X360_0, NKCODE_BUTTON_L2)] = VIRTKEY_SPEED_TOGGLE;
m[AxisDef(DEVICE_ID_X360_0, JOYSTICK_AXIS_X, -1)] = VIRTKEY_AXIS_X_MIN;
m[AxisDef(DEVICE_ID_X360_0, JOYSTICK_AXIS_X, +1)] = VIRTKEY_AXIS_X_MAX;
m[AxisDef(DEVICE_ID_X360_0, JOYSTICK_AXIS_Y, -1)] = VIRTKEY_AXIS_Y_MIN;
m[AxisDef(DEVICE_ID_X360_0, JOYSTICK_AXIS_Y, +1)] = VIRTKEY_AXIS_Y_MAX;
return m;
}
// Not used yet, will autodetect later
static KeyMapping defaultShieldMap()
{
KeyMapping m;
m[KeyDef(DEVICE_ID_PAD_0, NKCODE_BUTTON_A)] = CTRL_CROSS;
m[KeyDef(DEVICE_ID_PAD_0, NKCODE_BUTTON_B)] = CTRL_CIRCLE;
m[KeyDef(DEVICE_ID_PAD_0, NKCODE_BUTTON_X)] = CTRL_SQUARE;
m[KeyDef(DEVICE_ID_PAD_0, NKCODE_BUTTON_Y)] = CTRL_TRIANGLE;
m[KeyDef(DEVICE_ID_PAD_0, NKCODE_BUTTON_START)] = CTRL_START;
m[KeyDef(DEVICE_ID_PAD_0, NKCODE_BUTTON_SELECT)] = CTRL_SELECT;
m[KeyDef(DEVICE_ID_PAD_0, NKCODE_BUTTON_L1)] = CTRL_LTRIGGER;
m[KeyDef(DEVICE_ID_PAD_0, NKCODE_BUTTON_R1)] = CTRL_RTRIGGER;
m[KeyDef(DEVICE_ID_PAD_0, NKCODE_BUTTON_R2)] = VIRTKEY_UNTHROTTLE;
m[KeyDef(DEVICE_ID_PAD_0, NKCODE_BUTTON_THUMBR)] = VIRTKEY_PAUSE;
m[KeyDef(DEVICE_ID_PAD_0, NKCODE_BUTTON_L2)] = VIRTKEY_SPEED_TOGGLE;
m[AxisDef(DEVICE_ID_PAD_0, JOYSTICK_AXIS_X, -1)] = VIRTKEY_AXIS_X_MIN;
m[AxisDef(DEVICE_ID_PAD_0, JOYSTICK_AXIS_X, +1)] = VIRTKEY_AXIS_X_MAX;
m[AxisDef(DEVICE_ID_PAD_0, JOYSTICK_AXIS_Y, -1)] = VIRTKEY_AXIS_Y_MIN;
m[AxisDef(DEVICE_ID_PAD_0, JOYSTICK_AXIS_Y, +1)] = VIRTKEY_AXIS_Y_MAX;
m[AxisDef(DEVICE_ID_PAD_0, JOYSTICK_AXIS_HAT_X, -1)] = CTRL_LEFT;
m[AxisDef(DEVICE_ID_PAD_0, JOYSTICK_AXIS_HAT_X, +1)] = CTRL_RIGHT;
m[AxisDef(DEVICE_ID_PAD_0, JOYSTICK_AXIS_HAT_Y, -1)] = CTRL_UP;
m[AxisDef(DEVICE_ID_PAD_0, JOYSTICK_AXIS_HAT_Y, +1)] = CTRL_DOWN;
return m;
}
static KeyMapping defaultPadMap()
{
KeyMapping m;
#ifdef ANDROID
m[KeyDef(DEVICE_ID_X360_0, NKCODE_BUTTON_A)] = CTRL_CROSS;
m[KeyDef(DEVICE_ID_X360_0, NKCODE_BUTTON_B)] = CTRL_CIRCLE;
m[KeyDef(DEVICE_ID_X360_0, NKCODE_BUTTON_X)] = CTRL_SQUARE;
m[KeyDef(DEVICE_ID_X360_0, NKCODE_BUTTON_Y)] = CTRL_TRIANGLE;
m[KeyDef(DEVICE_ID_X360_0, NKCODE_DPAD_UP)] = CTRL_UP;
m[KeyDef(DEVICE_ID_X360_0, NKCODE_DPAD_RIGHT)] = CTRL_RIGHT;
m[KeyDef(DEVICE_ID_X360_0, NKCODE_DPAD_DOWN)] = CTRL_DOWN;
m[KeyDef(DEVICE_ID_X360_0, NKCODE_DPAD_LEFT)] = CTRL_LEFT;
m[KeyDef(DEVICE_ID_X360_0, NKCODE_BUTTON_START)] = CTRL_START;
m[KeyDef(DEVICE_ID_X360_0, NKCODE_BUTTON_SELECT)] = CTRL_SELECT;
m[KeyDef(DEVICE_ID_X360_0, NKCODE_BUTTON_L1)] = CTRL_LTRIGGER;
m[KeyDef(DEVICE_ID_X360_0, NKCODE_BUTTON_R1)] = CTRL_RTRIGGER;
m[KeyDef(DEVICE_ID_X360_0, NKCODE_BUTTON_R2)] = VIRTKEY_UNTHROTTLE;
m[KeyDef(DEVICE_ID_X360_0, NKCODE_BUTTON_THUMBR)] = VIRTKEY_PAUSE;
m[KeyDef(DEVICE_ID_X360_0, NKCODE_BUTTON_L2)] = VIRTKEY_SPEED_TOGGLE;
m[AxisDef(DEVICE_ID_X360_0, JOYSTICK_AXIS_X, -1)] = VIRTKEY_AXIS_X_MIN;
m[AxisDef(DEVICE_ID_X360_0, JOYSTICK_AXIS_X, +1)] = VIRTKEY_AXIS_X_MAX;
m[AxisDef(DEVICE_ID_X360_0, JOYSTICK_AXIS_Y, -1)] = VIRTKEY_AXIS_Y_MIN;
m[AxisDef(DEVICE_ID_X360_0, JOYSTICK_AXIS_Y, +1)] = VIRTKEY_AXIS_Y_MAX;
#else
m[KeyDef(DEVICE_ID_PAD_0, NKCODE_BUTTON_2)] = CTRL_CROSS;
m[KeyDef(DEVICE_ID_PAD_0, NKCODE_BUTTON_3)] = CTRL_CIRCLE;
m[KeyDef(DEVICE_ID_PAD_0, NKCODE_BUTTON_4)] = CTRL_SQUARE;
m[KeyDef(DEVICE_ID_PAD_0, NKCODE_BUTTON_1)] = CTRL_TRIANGLE;
m[KeyDef(DEVICE_ID_PAD_0, NKCODE_DPAD_UP)] = CTRL_UP;
m[KeyDef(DEVICE_ID_PAD_0, NKCODE_DPAD_RIGHT)] = CTRL_RIGHT;
m[KeyDef(DEVICE_ID_PAD_0, NKCODE_DPAD_DOWN)] = CTRL_DOWN;
m[KeyDef(DEVICE_ID_PAD_0, NKCODE_DPAD_LEFT)] = CTRL_LEFT;
m[KeyDef(DEVICE_ID_PAD_0, NKCODE_BUTTON_10)] = CTRL_START;
m[KeyDef(DEVICE_ID_PAD_0, NKCODE_BUTTON_9)] = CTRL_SELECT;
m[KeyDef(DEVICE_ID_PAD_0, NKCODE_BUTTON_7)] = CTRL_LTRIGGER;
m[KeyDef(DEVICE_ID_PAD_0, NKCODE_BUTTON_8)] = CTRL_RTRIGGER;
m[AxisDef(DEVICE_ID_PAD_0, JOYSTICK_AXIS_X, -1)] = VIRTKEY_AXIS_X_MIN;
m[AxisDef(DEVICE_ID_PAD_0, JOYSTICK_AXIS_X, +1)] = VIRTKEY_AXIS_X_MAX;
m[AxisDef(DEVICE_ID_PAD_0, JOYSTICK_AXIS_Y, +1)] = VIRTKEY_AXIS_Y_MIN;
m[AxisDef(DEVICE_ID_PAD_0, JOYSTICK_AXIS_Y, -1)] = VIRTKEY_AXIS_Y_MAX;
#endif
return m;
}
static KeyMapping defaultXperiaPlay()
{
KeyMapping m;
m[KeyDef(DEVICE_ID_DEFAULT, NKCODE_BUTTON_CROSS)] = CTRL_CROSS;
m[KeyDef(DEVICE_ID_DEFAULT, NKCODE_BUTTON_CIRCLE)] = CTRL_CIRCLE;
m[KeyDef(DEVICE_ID_DEFAULT, NKCODE_BUTTON_X)] = CTRL_SQUARE;
m[KeyDef(DEVICE_ID_DEFAULT, NKCODE_BUTTON_Y)] = CTRL_TRIANGLE;
m[KeyDef(DEVICE_ID_DEFAULT, NKCODE_DPAD_UP)] = CTRL_UP;
m[KeyDef(DEVICE_ID_DEFAULT, NKCODE_DPAD_RIGHT)] = CTRL_RIGHT;
m[KeyDef(DEVICE_ID_DEFAULT, NKCODE_DPAD_DOWN)] = CTRL_DOWN;
m[KeyDef(DEVICE_ID_DEFAULT, NKCODE_DPAD_LEFT)] = CTRL_LEFT;
m[KeyDef(DEVICE_ID_DEFAULT, NKCODE_BUTTON_START)] = CTRL_START;
m[KeyDef(DEVICE_ID_DEFAULT, NKCODE_BACK)] = CTRL_SELECT;
m[KeyDef(DEVICE_ID_DEFAULT, NKCODE_BUTTON_L1)] = CTRL_LTRIGGER;
m[KeyDef(DEVICE_ID_DEFAULT, NKCODE_BUTTON_R1)] = CTRL_RTRIGGER;
m[AxisDef(DEVICE_ID_DEFAULT, JOYSTICK_AXIS_X, -1)] = VIRTKEY_AXIS_X_MIN;
m[AxisDef(DEVICE_ID_DEFAULT, JOYSTICK_AXIS_X, +1)] = VIRTKEY_AXIS_X_MAX;
m[AxisDef(DEVICE_ID_DEFAULT, JOYSTICK_AXIS_Y, -1)] = VIRTKEY_AXIS_Y_MIN;
m[AxisDef(DEVICE_ID_DEFAULT, JOYSTICK_AXIS_Y, +1)] = VIRTKEY_AXIS_Y_MAX;
return m;
}
static std::vector<ControllerMap> init()
{
std::vector<ControllerMap> m;
#if defined(USING_GLES2)
// Mobile! Only a pad map required, some can use a keyboard map though.
// Currently no way to distinguish between external keyboard and qwerty keyboard ('pad'?)
ControllerMap pad;
pad.keys = defaultPadMap();
pad.name = "Pad";
m.push_back(pad);
ControllerMap kbd;
kbd.keys = defaultKeyboardMap();
kbd.name = "Keyboard";
m.push_back(kbd);
#ifdef ANDROID
ControllerMap xperia;
xperia.keys = defaultXperiaPlay();
xperia.name = "Xperia Play";
xperia.active = false;
m.push_back(xperia);
#endif
#else
ControllerMap kbd;
kbd.keys = defaultKeyboardMap();
kbd.name = "Keyboard";
m.push_back(kbd);
#ifdef _WIN32
ControllerMap x360;
x360.keys = default360Map();
x360.name = "Xbox 360 Pad";
m.push_back(x360);
#endif
// Keyboard and pad maps.
ControllerMap pad;
pad.keys = defaultPadMap();
pad.name = "DirectInput Pad";
pad.active = false;
m.push_back(pad);
#endif
return m;
}
static std::vector<ControllerMap> KeyMap;
};
std::vector<ControllerMap> DefaultKeyMap::KeyMap = DefaultKeyMap::init();
// Key & Button names
struct KeyMap_IntStrPair {
struct DefMappingStruct {
int pspKey;
int key;
std::string name;
int direction;
};
KeyMapping g_controllerMap;
static const DefMappingStruct defaultKeyboardKeyMap[] = {
{CTRL_SQUARE, NKCODE_A},
{CTRL_TRIANGLE, NKCODE_S},
{CTRL_CIRCLE, NKCODE_X},
{CTRL_CROSS, NKCODE_Z},
{CTRL_LTRIGGER, NKCODE_Q},
{CTRL_RTRIGGER, NKCODE_W},
{CTRL_START, NKCODE_SPACE},
#ifdef _WIN32
{CTRL_SELECT, NKCODE_V},
#else
{CTRL_SELECT, NKCODE_ENTER},
#endif
{CTRL_UP , NKCODE_DPAD_UP},
{CTRL_DOWN , NKCODE_DPAD_DOWN},
{CTRL_LEFT , NKCODE_DPAD_LEFT},
{CTRL_RIGHT, NKCODE_DPAD_RIGHT},
{VIRTKEY_AXIS_Y_MAX, NKCODE_I},
{VIRTKEY_AXIS_Y_MIN, NKCODE_K},
{VIRTKEY_AXIS_X_MIN, NKCODE_J},
{VIRTKEY_AXIS_X_MAX, NKCODE_L},
{VIRTKEY_RAPID_FIRE , NKCODE_SHIFT_LEFT},
{VIRTKEY_UNTHROTTLE , NKCODE_TAB},
{VIRTKEY_SPEED_TOGGLE, NKCODE_GRAVE},
{VIRTKEY_PAUSE , NKCODE_ESCAPE},
};
static const DefMappingStruct default360KeyMap[] = {
{VIRTKEY_AXIS_X_MIN, JOYSTICK_AXIS_X, -1},
{VIRTKEY_AXIS_X_MAX, JOYSTICK_AXIS_X, +1},
{VIRTKEY_AXIS_Y_MIN, JOYSTICK_AXIS_Y, -1},
{VIRTKEY_AXIS_Y_MAX, JOYSTICK_AXIS_Y, +1},
{CTRL_CROSS , NKCODE_BUTTON_A},
{CTRL_CIRCLE , NKCODE_BUTTON_B},
{CTRL_SQUARE , NKCODE_BUTTON_X},
{CTRL_TRIANGLE , NKCODE_BUTTON_Y},
{CTRL_UP , NKCODE_DPAD_UP},
{CTRL_RIGHT , NKCODE_DPAD_RIGHT},
{CTRL_DOWN , NKCODE_DPAD_DOWN},
{CTRL_LEFT , NKCODE_DPAD_LEFT},
{CTRL_START , NKCODE_BUTTON_START},
{CTRL_SELECT , NKCODE_BUTTON_SELECT},
{CTRL_LTRIGGER , NKCODE_BUTTON_L1},
{CTRL_RTRIGGER , NKCODE_BUTTON_R1},
{VIRTKEY_UNTHROTTLE , JOYSTICK_AXIS_RTRIGGER, +1},
{VIRTKEY_PAUSE , NKCODE_BUTTON_THUMBR},
{VIRTKEY_SPEED_TOGGLE, NKCODE_BUTTON_L2},
{VIRTKEY_PAUSE, NKCODE_HOME},
};
static const DefMappingStruct defaultShieldKeyMap[] = {
{CTRL_CROSS, NKCODE_BUTTON_A},
{CTRL_CIRCLE ,NKCODE_BUTTON_B},
{CTRL_SQUARE ,NKCODE_BUTTON_X},
{CTRL_TRIANGLE ,NKCODE_BUTTON_Y},
{CTRL_START, NKCODE_BUTTON_START},
{CTRL_SELECT, NKCODE_BUTTON_L2},
{CTRL_LTRIGGER, NKCODE_BUTTON_L1},
{CTRL_RTRIGGER, NKCODE_BUTTON_R1},
{VIRTKEY_AXIS_X_MIN, JOYSTICK_AXIS_X, -1},
{VIRTKEY_AXIS_X_MAX, JOYSTICK_AXIS_X, +1},
{VIRTKEY_AXIS_Y_MIN, JOYSTICK_AXIS_Y, -1},
{VIRTKEY_AXIS_Y_MAX, JOYSTICK_AXIS_Y, +1},
{CTRL_LEFT, JOYSTICK_AXIS_HAT_X, -1},
{CTRL_RIGHT, JOYSTICK_AXIS_HAT_X, +1},
{CTRL_UP, JOYSTICK_AXIS_HAT_Y, -1},
{CTRL_DOWN, JOYSTICK_AXIS_HAT_Y, +1},
{VIRTKEY_UNTHROTTLE, NKCODE_BUTTON_R2 },
{VIRTKEY_PAUSE, NKCODE_BACK },
};
static const DefMappingStruct defaultPadMap[] = {
#ifdef ANDROID
{CTRL_CROSS , NKCODE_BUTTON_A},
{CTRL_CIRCLE , NKCODE_BUTTON_B},
{CTRL_SQUARE , NKCODE_BUTTON_X},
{CTRL_TRIANGLE , NKCODE_BUTTON_Y},
{CTRL_UP , NKCODE_DPAD_UP},
{CTRL_RIGHT , NKCODE_DPAD_RIGHT},
{CTRL_DOWN , NKCODE_DPAD_DOWN},
{CTRL_LEFT , NKCODE_DPAD_LEFT},
{CTRL_START , NKCODE_BUTTON_START},
{CTRL_SELECT , NKCODE_BUTTON_SELECT},
{CTRL_LTRIGGER , NKCODE_BUTTON_L1},
{CTRL_RTRIGGER , NKCODE_BUTTON_R1},
{VIRTKEY_UNTHROTTLE , NKCODE_BUTTON_R2},
{VIRTKEY_PAUSE , NKCODE_BUTTON_THUMBR},
{VIRTKEY_SPEED_TOGGLE, NKCODE_BUTTON_L2},
{VIRTKEY_AXIS_X_MIN, JOYSTICK_AXIS_X, -1},
{VIRTKEY_AXIS_X_MAX, JOYSTICK_AXIS_X, +1},
{VIRTKEY_AXIS_Y_MIN, JOYSTICK_AXIS_Y, -1},
{VIRTKEY_AXIS_Y_MAX, JOYSTICK_AXIS_Y, +1},
#else
{CTRL_CROSS , NKCODE_BUTTON_2},
{CTRL_CIRCLE , NKCODE_BUTTON_3},
{CTRL_SQUARE , NKCODE_BUTTON_4},
{CTRL_TRIANGLE , NKCODE_BUTTON_1},
{CTRL_UP , NKCODE_DPAD_UP},
{CTRL_RIGHT , NKCODE_DPAD_RIGHT},
{CTRL_DOWN , NKCODE_DPAD_DOWN},
{CTRL_LEFT , NKCODE_DPAD_LEFT},
{CTRL_START , NKCODE_BUTTON_10},
{CTRL_SELECT , NKCODE_BUTTON_9},
{CTRL_LTRIGGER , NKCODE_BUTTON_7},
{CTRL_RTRIGGER , NKCODE_BUTTON_8},
{VIRTKEY_AXIS_X_MIN, JOYSTICK_AXIS_X, -1},
{VIRTKEY_AXIS_X_MAX, JOYSTICK_AXIS_X, +1},
{VIRTKEY_AXIS_Y_MIN, JOYSTICK_AXIS_Y, +1},
{VIRTKEY_AXIS_Y_MAX, JOYSTICK_AXIS_Y, -1},
#endif
};
static const DefMappingStruct defaultXperiaPlay[] = {
{CTRL_CROSS , NKCODE_BUTTON_CROSS},
{CTRL_CIRCLE , NKCODE_BUTTON_CIRCLE},
{CTRL_SQUARE , NKCODE_BUTTON_X},
{CTRL_TRIANGLE , NKCODE_BUTTON_Y},
{CTRL_UP , NKCODE_DPAD_UP},
{CTRL_RIGHT , NKCODE_DPAD_RIGHT},
{CTRL_DOWN , NKCODE_DPAD_DOWN},
{CTRL_LEFT , NKCODE_DPAD_LEFT},
{CTRL_START , NKCODE_BUTTON_START},
{CTRL_SELECT , NKCODE_BACK},
{CTRL_LTRIGGER , NKCODE_BUTTON_L1},
{CTRL_RTRIGGER , NKCODE_BUTTON_R1},
{VIRTKEY_AXIS_X_MIN, JOYSTICK_AXIS_X, -1},
{VIRTKEY_AXIS_X_MAX, JOYSTICK_AXIS_X, +1},
{VIRTKEY_AXIS_Y_MIN, JOYSTICK_AXIS_Y, -1},
{VIRTKEY_AXIS_Y_MAX, JOYSTICK_AXIS_Y, +1},
};
static void SetDefaultKeyMap(int deviceId, const DefMappingStruct *array, int count, bool replace) {
for (size_t i = 0; i < count; i++) {
if (array[i].direction == 0)
SetKeyMapping(array[i].pspKey, KeyDef(deviceId, array[i].key), replace);
else
SetAxisMapping(array[i].pspKey, deviceId, array[i].key, array[i].direction, replace);
}
}
void SetDefaultKeyMap(DefaultMaps dmap, bool replace) {
switch (dmap) {
case DEFAULT_MAPPING_KEYBOARD:
SetDefaultKeyMap(DEVICE_ID_KEYBOARD, defaultKeyboardKeyMap, ARRAY_SIZE(defaultKeyboardKeyMap), replace);
break;
case DEFAULT_MAPPING_X360:
SetDefaultKeyMap(DEVICE_ID_X360_0, default360KeyMap, ARRAY_SIZE(default360KeyMap), replace);
break;
case DEFAULT_MAPPING_SHIELD:
SetDefaultKeyMap(DEVICE_ID_X360_0, defaultShieldKeyMap, ARRAY_SIZE(defaultShieldKeyMap), replace);
break;
}
}
const KeyMap_IntStrPair key_names[] = {
{NKCODE_A, "A"},
{NKCODE_B, "B"},
@ -433,40 +390,40 @@ const KeyMap_IntStrPair axis_names[] = {
};
static std::string unknown_key_name = "??";
const KeyMap_IntStrPair psp_button_names[] = {
{CTRL_CIRCLE, "O"},
{CTRL_CROSS, "X"},
{CTRL_SQUARE, "[ ]"},
{CTRL_TRIANGLE, "/\\"},
{CTRL_LTRIGGER, "L"},
{CTRL_RTRIGGER, "R"},
{CTRL_START, "Start"},
{CTRL_SELECT, "Select"},
{CTRL_UP, "Up"},
{CTRL_DOWN, "Down"},
{CTRL_LEFT, "Left"},
{CTRL_RIGHT, "Right"},
{CTRL_CIRCLE, "Circle"},
{CTRL_CROSS, "Cross"},
{CTRL_SQUARE, "Square"},
{CTRL_TRIANGLE, "Triangle"},
{CTRL_START, "Start"},
{CTRL_SELECT, "Select"},
{CTRL_LTRIGGER, "L"},
{CTRL_RTRIGGER, "R"},
{VIRTKEY_AXIS_Y_MAX, "An.Up"},
{VIRTKEY_AXIS_Y_MIN, "An.Down"},
{VIRTKEY_AXIS_X_MIN, "An.Left"},
{VIRTKEY_AXIS_X_MAX, "An.Right"},
{VIRTKEY_AXIS_Y_MIN, "An.Down"},
{VIRTKEY_AXIS_Y_MAX, "An.Up"},
{VIRTKEY_AXIS_RIGHT_X_MIN, "RightAn.Left"},
{VIRTKEY_AXIS_RIGHT_X_MAX, "RightAn.Right"},
{VIRTKEY_AXIS_RIGHT_Y_MIN, "RightAn.Down"},
{VIRTKEY_AXIS_RIGHT_Y_MAX, "RightAn.Up"},
{VIRTKEY_RAPID_FIRE, "RapidFire"},
{VIRTKEY_UNTHROTTLE, "Unthrottle"},
{VIRTKEY_SPEED_TOGGLE, "SpeedToggle"},
{VIRTKEY_PAUSE, "Pause"},
{VIRTKEY_AXIS_RIGHT_Y_MAX, "RightAn.Up"},
{VIRTKEY_AXIS_RIGHT_Y_MIN, "RightAn.Down"},
{VIRTKEY_AXIS_RIGHT_X_MIN, "RightAn.Left"},
{VIRTKEY_AXIS_RIGHT_X_MAX, "RightAn.Right"},
};
const int AXIS_BIND_NKCODE_START = 4000;
static std::string FindName(int key, const KeyMap_IntStrPair list[], size_t size)
{
static std::string FindName(int key, const KeyMap_IntStrPair list[], size_t size) {
for (size_t i = 0; i < size; i++)
if (list[i].key == key)
return list[i].name;
@ -474,29 +431,51 @@ static std::string FindName(int key, const KeyMap_IntStrPair list[], size_t size
return unknown_key_name;
}
std::string GetKeyName(int keyCode)
{
std::string GetKeyName(int keyCode) {
return FindName(keyCode, key_names, ARRAY_SIZE(key_names));
}
std::string GetPspButtonName(int btn)
{
std::string GetKeyOrAxisName(int keyCode) {
if (keyCode >= AXIS_BIND_NKCODE_START) {
int direction;
int axis = TranslateKeyCodeToAxis(keyCode, direction);
std::string temp = GetAxisName(axis);
if (direction == 1)
temp += "+";
else if (direction == -1)
temp += "-";
return temp;
}
return FindName(keyCode, key_names, ARRAY_SIZE(key_names));
}
std::string GetAxisName(int axisId) {
return FindName(axisId, axis_names, ARRAY_SIZE(axis_names));
}
std::string GetPspButtonName(int btn) {
return FindName(btn, psp_button_names, ARRAY_SIZE(psp_button_names));
}
int TranslateKeyCodeToAxis(int keyCode, int &direction)
{
std::vector<KeyMap_IntStrPair> GetMappableKeys() {
std::vector<KeyMap_IntStrPair> temp;
for (size_t i = 0; i < ARRAY_SIZE(psp_button_names); i++) {
temp.push_back(psp_button_names[i]);
}
return temp;
}
int TranslateKeyCodeToAxis(int keyCode, int &direction) {
if (keyCode < AXIS_BIND_NKCODE_START)
return 0;
int v = keyCode - AXIS_BIND_NKCODE_START;
int v = keyCode - AXIS_BIND_NKCODE_START;
// Even/odd for direction.
direction = v & 1 ? -1 : 1;
return v / 2;
}
int TranslateKeyCodeFromAxis(int axisId, int direction)
{
int TranslateKeyCodeFromAxis(int axisId, int direction) {
direction = direction < 0 ? 1 : 0;
return AXIS_BIND_NKCODE_START + axisId * 2 + direction;
}
@ -505,24 +484,20 @@ KeyDef AxisDef(int deviceId, int axisId, int direction) {
return KeyDef(deviceId, TranslateKeyCodeFromAxis(axisId, direction));
}
static bool FindKeyMapping(int deviceId, int key, int *psp_button)
{
for (size_t i = 0; i < controllerMaps.size(); i++) {
if (!controllerMaps[i].active)
continue;
auto iter = controllerMaps[i].keys.find(KeyDef(deviceId, key));
if (iter != controllerMaps[i].keys.end()) {
*psp_button = iter->second;
return true;
static bool FindKeyMapping(int deviceId, int key, int *psp_button) {
// Brute force, let's optimize later
for (auto iter = g_controllerMap.begin(); iter != g_controllerMap.end(); ++iter) {
for (auto iter2 = iter->second.begin(); iter2 != iter->second.end(); ++iter2) {
if (*iter2 == KeyDef(deviceId, key)) {
*psp_button = iter->first;
return true;
}
}
}
return false;
}
int KeyToPspButton(int deviceId, int key)
{
int KeyToPspButton(int deviceId, int key) {
int search_start_layer = 0;
int psp_button;
@ -532,179 +507,134 @@ int KeyToPspButton(int deviceId, int key)
return KEYMAP_ERROR_UNKNOWN_KEY;
}
bool KeyFromPspButton(int controllerMap, int btn, int *deviceId, int *keyCode)
{
// TODO: vector output
bool KeyFromPspButton(int btn, std::vector<KeyDef> *keys) {
int search_start_layer = 0;
for (auto iter = controllerMaps[controllerMap].keys.begin(); iter != controllerMaps[controllerMap].keys.end(); ++iter) {
if (iter->second == btn) {
*deviceId = iter->first.deviceId;
*keyCode = iter->first.keyCode;
return true;
for (auto iter = g_controllerMap.begin(); iter != g_controllerMap.end(); ++iter) {
if (iter->first == btn) {
for (auto iter2 = iter->second.begin(); iter2 != iter->second.end(); ++iter2) {
keys->push_back(*iter2);
}
}
}
return false;
}
int AxisToPspButton(int deviceId, int axisId, int direction)
{
int AxisToPspButton(int deviceId, int axisId, int direction) {
int key = TranslateKeyCodeFromAxis(axisId, direction);
return KeyToPspButton(deviceId, key);
}
bool AxisFromPspButton(int controllerMap, int btn, int *deviceId, int *axisId, int *direction)
{
bool AxisFromPspButton(int btn, int *deviceId, int *axisId, int *direction) {
int search_start_layer = 0;
for (auto iter = controllerMaps[controllerMap].keys.begin(); iter != controllerMaps[controllerMap].keys.end(); ++iter) {
if (iter->second == btn && iter->first.keyCode >= AXIS_BIND_NKCODE_START) {
*deviceId = iter->first.deviceId;
*axisId = TranslateKeyCodeToAxis(iter->first.keyCode, *direction);
return true;
for (auto iter = g_controllerMap.begin(); iter != g_controllerMap.end(); ++iter) {
for (auto iter2 = iter->second.begin(); iter2 != iter->second.end(); ++iter2) {
if (iter->first == btn && iter2->keyCode >= AXIS_BIND_NKCODE_START) {
*deviceId = iter2->deviceId;
*axisId = TranslateKeyCodeToAxis(iter2->keyCode, *direction);
return true;
}
}
}
return false;
}
std::string NameKeyFromPspButton(int controllerMap, int btn) {
int deviceId;
int axisId;
int direction;
int keyCode;
if (AxisFromPspButton(controllerMap, btn, &deviceId, &axisId, &direction)) {
return GetAxisName(axisId) + (direction < 0 ? "-" : "+");
}
if (KeyFromPspButton(controllerMap, btn, &deviceId, &keyCode)) {
return GetKeyName(keyCode);
}
return "unknown";
}
std::string NameDeviceFromPspButton(int controllerMap, int btn) {
int deviceId;
int axisId;
int direction;
int keyCode;
if (AxisFromPspButton(controllerMap, btn, &deviceId, &axisId, &direction)) {
return GetDeviceName(deviceId);
}
if (KeyFromPspButton(controllerMap, btn, &deviceId, &keyCode)) {
return GetDeviceName(deviceId);
}
return "unknown";
}
bool IsMappedKey(int deviceId, int key)
{
return KeyToPspButton(deviceId, key) != KEYMAP_ERROR_UNKNOWN_KEY;
}
std::string NamePspButtonFromKey(int deviceId, int key)
{
return GetPspButtonName(KeyToPspButton(deviceId, key));
}
void RemoveButtonMapping(int map, int btn) {
for (auto iter = controllerMaps[map].keys.begin(); iter != controllerMaps[map].keys.end(); ++iter) {
if (iter->second == btn) {
controllerMaps[map].keys.erase(iter);
void RemoveButtonMapping(int btn) {
for (auto iter = g_controllerMap.begin(); iter != g_controllerMap.end(); ++iter) {
if (iter->first == btn) {
g_controllerMap.erase(iter);
return;
}
}
}
void SetKeyMapping(int map, int deviceId, int key, int btn)
{
RemoveButtonMapping(map, btn);
controllerMaps[map].keys[KeyDef(deviceId, key)] = btn;
void SetKeyMapping(int btn, KeyDef key, bool replace) {
if (key.keyCode < 0)
return;
if (replace) {
RemoveButtonMapping(btn);
g_controllerMap[btn].clear();
g_controllerMap[btn].push_back(key);
} else {
for (auto iter = g_controllerMap[btn].begin(); iter != g_controllerMap[btn].end(); ++iter) {
if (*iter == key)
return;
}
g_controllerMap[btn].push_back(key);
}
}
std::string GetAxisName(int axisId)
{
return FindName(axisId, axis_names, ARRAY_SIZE(axis_names));
}
bool IsMappedAxis(int deviceId, int axisId, int direction)
{
void SetAxisMapping(int btn, int deviceId, int axisId, int direction, bool replace) {
int key = TranslateKeyCodeFromAxis(axisId, direction);
return KeyToPspButton(deviceId, key) != KEYMAP_ERROR_UNKNOWN_KEY;
}
std::string NamePspButtonFromAxis(int deviceId, int axisId, int direction)
{
int key = TranslateKeyCodeFromAxis(axisId, direction);
return GetPspButtonName(KeyToPspButton(deviceId, key));
}
void SetAxisMapping(int map, int deviceId, int axisId, int direction, int btn)
{
int key = TranslateKeyCodeFromAxis(axisId, direction);
SetKeyMapping(map, deviceId, key, btn);
SetKeyMapping(btn, KeyDef(deviceId, key), replace);
}
// Note that it's easy to add other defaults if desired.
void RestoreDefault() {
controllerMaps = DefaultKeyMap::KeyMap;
#if defined(_WIN32)
SetDefaultKeyMap(DEFAULT_MAPPING_KEYBOARD, true);
SetDefaultKeyMap(DEFAULT_MAPPING_X360, false);
#elif defined(ANDROID)
SetDefaultKeyMap(DEFAULT_MAPPING_PAD, true);
#else
SetDefaultKeyMap(DEFAULT_MAPPING_KEYBOARD, true);
SetDefaultKeyMap(DEFAULT_MAPPING_PAD, false);
#endif
}
// TODO: Make the ini format nicer.
void LoadFromIni(IniFile &file) {
RestoreDefault();
if (!file.HasSection("ControlMapping")) {
controllerMaps = DefaultKeyMap::KeyMap;
return;
}
controllerMaps.clear();
IniFile::Section *controls = file.GetOrCreateSection("ControlMapping");
std::vector<std::string> maps;
controls->Get("ControllerMaps", maps);
if (!maps.size()) {
controllerMaps = DefaultKeyMap::KeyMap;
return;
}
for (int i = 0; i < ARRAY_SIZE(psp_button_names); i++) {
if (!controls->Exists(psp_button_names[i].name.c_str()))
continue;
std::string value;
controls->Get(psp_button_names[i].name.c_str(), &value, "");
if (value.empty())
continue;
// Erase default mapping
g_controllerMap.erase(psp_button_names[i].key);
for (auto x = maps.begin(); x != maps.end(); ++x) {
ControllerMap newMap;
newMap.name = *x;
IniFile::Section *map = file.GetOrCreateSection(newMap.name.c_str());
map->Get("Active", &newMap.active, true);
std::map<std::string, std::string> strmap = map->ToMap();
std::vector<std::string> mappings;
SplitString(value, ',', mappings);
for (auto x = strmap.begin(); x != strmap.end(); ++x) {
std::vector<std::string> keyParts;
SplitString(x->first, '-', keyParts);
if (keyParts.size() != 2)
continue;
int deviceId = atoi(keyParts[0].c_str());
int keyCode = atoi(keyParts[1].c_str());
newMap.keys[KeyDef(deviceId, keyCode)] = atoi(x->second.c_str());
for (size_t j = 0; j < mappings.size(); j++) {
std::vector<std::string> parts;
SplitString(mappings[j], '-', parts);
int deviceId = atoi(parts[0].c_str());
int keyCode = atoi(parts[1].c_str());
SetKeyMapping(psp_button_names[i].key, KeyDef(deviceId, keyCode), false);
}
controllerMaps.push_back(newMap);
}
return;
}
void SaveToIni(IniFile &file) {
IniFile::Section *controls = file.GetOrCreateSection("ControlMapping");
std::vector<std::string> maps;
for (auto x = controllerMaps.begin(); x != controllerMaps.end(); ++x) {
maps.push_back(x->name);
}
controls->Set("ControllerMaps", maps);
for (auto x = controllerMaps.begin(); x != controllerMaps.end(); ++x) {
IniFile::Section *map = file.GetOrCreateSection(x->name.c_str());
map->Clear();
map->Set("Active", x->active);
for (auto iter = x->keys.begin(); iter != x->keys.end(); ++iter) {
char key[128];
sprintf(key, "%i-%i", iter->first.deviceId, iter->first.keyCode);
char value[128];
sprintf(value, "%i", iter->second);
map->Set(key, value);
for (int i = 0; i < ARRAY_SIZE(psp_button_names); i++) {
std::vector<KeyDef> keys;
KeyFromPspButton(psp_button_names[i].key, &keys);
std::string value;
for (size_t j = 0; j < keys.size(); j++) {
char temp[128];
sprintf(temp, "%i-%i", keys[j].deviceId, keys[j].keyCode);
value += temp;
if (j != keys.size() - 1)
value += ",";
}
controls->Set(psp_button_names[i].name.c_str(), value, "");
}
}
} // KeyMap
std::vector<ControllerMap> controllerMaps = KeyMap::DefaultKeyMap::KeyMap;

View file

@ -44,10 +44,19 @@ enum {
VIRTKEY_COUNT = VIRTKEY_LAST - VIRTKEY_FIRST
};
enum DefaultMaps {
DEFAULT_MAPPING_KEYBOARD,
DEFAULT_MAPPING_PAD,
DEFAULT_MAPPING_X360,
DEFAULT_MAPPING_SHIELD,
DEFAULT_MAPPING_OUYA,
};
const float AXIS_BIND_THRESHOLD = 0.75f;
class KeyDef {
public:
KeyDef() : deviceId(0), keyCode(0) {}
KeyDef(int devId, int k) : deviceId(devId), keyCode(k) {}
int deviceId;
int keyCode;
@ -58,29 +67,28 @@ public:
if (keyCode < other.keyCode) return true;
return false;
}
bool operator == (const KeyDef &other) const {
if (deviceId != other.deviceId) return false;
if (keyCode != other.keyCode) return false;
return true;
}
};
struct AxisPos {
int axis;
float position;
bool operator < (const AxisPos &other) const {
if (axis < other.axis) return true;
if (axis > other.axis) return false;
return position < other.position;
}
bool operator == (const AxisPos &other) const {
return axis == other.axis && position == other.position;
}
};
typedef std::map<KeyDef, int> KeyMapping;
typedef std::map<KeyDef, AxisPos> AxisMapping;
// Multiple maps can be active at the same time.
class ControllerMap {
public:
ControllerMap() : active(true) {}
bool active;
KeyMapping keys;
AxisMapping axis; // TODO
std::string name;
};
extern std::vector<ControllerMap> controllerMaps;
typedef std::map<int, std::vector<KeyDef>> KeyMapping;
// KeyMap
// A translation layer for key assignment. Provides
@ -95,10 +103,22 @@ extern std::vector<ControllerMap> controllerMaps;
class IniFile;
namespace KeyMap {
extern KeyMapping g_controllerMap;
// Key & Button names
struct KeyMap_IntStrPair {
int key;
std::string name;
};
// Use if you need to display the textual name
std::string GetKeyName(int keyCode);
std::string GetKeyOrAxisName(int keyCode);
std::string GetAxisName(int axisId);
std::string GetPspButtonName(int btn);
std::vector<KeyMap_IntStrPair> GetMappableKeys();
// Use if to translate KeyMap Keys to PSP
// buttons. You should have already translated
// your platform's keys to KeyMap keys.
@ -106,33 +126,29 @@ namespace KeyMap {
// Returns KEYMAP_ERROR_UNKNOWN_KEY
// for any unmapped key
int KeyToPspButton(int deviceId, int key);
bool KeyFromPspButton(int btn, std::vector<KeyDef> *keys);
bool IsMappedKey(int deviceId, int key);
// Might be useful if you want to provide hints to users
// about mapping conflicts
std::string NamePspButtonFromKey(int deviceId, int key);
bool KeyFromPspButton(int controllerMap, int btn, int *deviceId, int *keyCode);
std::string NameKeyFromPspButton(int controllerMap, int btn);
std::string NameDeviceFromPspButton(int controllerMap, int btn);
int TranslateKeyCodeToAxis(int keyCode, int &direction);
int TranslateKeyCodeFromAxis(int axisId, int direction);
// Configure the key mapping.
// Any configuration will be saved to the Core config.
void SetKeyMapping(int map, int deviceId, int keyCode, int psp_key);
std::string GetAxisName(int axisId);
int AxisToPspButton(int deviceId, int axisId, int direction);
bool AxisFromPspButton(int controllerMap, int btn, int *deviceId, int *axisId, int *direction);
bool IsMappedAxis(int deviceId, int axisId, int direction);
std::string NamePspButtonFromAxis(int deviceId, int axisId, int direction);
void SetKeyMapping(int psp_key, KeyDef key, bool replace);
// Configure an axis mapping, saves the configuration.
// Direction is negative or positive.
void SetAxisMapping(int map, int deviceId, int axisId, int direction, int btn);
void SetAxisMapping(int btn, int deviceId, int axisId, int direction, bool replace);
int AxisToPspButton(int deviceId, int axisId, int direction);
bool AxisFromPspButton(int btn, int *deviceId, int *axisId, int *direction);
std::string NamePspButtonFromAxis(int deviceId, int axisId, int direction);
void LoadFromIni(IniFile &iniFile);
void SaveToIni(IniFile &iniFile);
void SetDefaultKeyMap(DefaultMaps dmap, bool replace);
void RestoreDefault();
void QuickMap(int device);
}

View file

@ -33,9 +33,10 @@ extern bool isJailed;
Config::Config() { }
Config::~Config() { }
void Config::Load(const char *iniFileName)
void Config::Load(const char *iniFileName, const char *controllerIniFilename)
{
iniFilename_ = iniFileName;
controllerIniFilename_ = controllerIniFilename;
INFO_LOG(LOADER, "Loading config: %s", iniFileName);
bSaveSettings = true;
@ -189,7 +190,16 @@ void Config::Load(const char *iniFileName)
IniFile::Section *gleshacks = iniFile.GetOrCreateSection("GLESHacks");
gleshacks->Get("PrescaleUV", &bPrescaleUV, false);
KeyMap::LoadFromIni(iniFile);
INFO_LOG(LOADER, "Loading controller config: %s", controllerIniFilename);
bSaveSettings = true;
IniFile controllerIniFile;
if (!controllerIniFile.Load(controllerIniFilename)) {
ERROR_LOG(LOADER, "Failed to read %s. Setting controller config to default.", controllerIniFilename);
}
// Continue anyway to initialize the config. It will just restore the defaults.
KeyMap::LoadFromIni(controllerIniFile);
CleanRecent();
}
@ -307,14 +317,26 @@ void Config::Save()
debugConfig->Set("FontWidth", iFontWidth);
debugConfig->Set("FontHeight", iFontHeight);
debugConfig->Set("DisplayStatusBar", bDisplayStatusBar);
KeyMap::SaveToIni(iniFile);
if (!iniFile.Save(iniFilename_.c_str())) {
ERROR_LOG(LOADER, "Error saving config - can't write ini %s", iniFilename_.c_str());
return;
}
INFO_LOG(LOADER, "Config saved: %s", iniFilename_.c_str());
IniFile controllerIniFile;
if (!controllerIniFile.Load(controllerIniFilename_.c_str())) {
ERROR_LOG(LOADER, "Error saving config - can't read ini %s", controllerIniFilename_.c_str());
} else {
KeyMap::SaveToIni(controllerIniFile);
}
if (!controllerIniFile.Save(controllerIniFilename_.c_str())) {
ERROR_LOG(LOADER, "Error saving config - can't write ini %s", controllerIniFilename_.c_str());
return;
}
INFO_LOG(LOADER, "Controller config saved: %s", controllerIniFilename_.c_str());
} else {
INFO_LOG(LOADER, "Not saving config");
}

View file

@ -163,7 +163,7 @@ public:
std::string flashDirectory;
std::string internalDataDirectory;
void Load(const char *iniFileName = "ppsspp.ini");
void Load(const char *iniFileName = "ppsspp.ini", const char *controllerIniFilename = "controls.ini");
void Save();
// Utility functions for "recent" management
@ -172,6 +172,7 @@ public:
private:
std::string iniFilename_;
std::string controllerIniFilename_;
};
extern Config g_Config;

View file

@ -21,6 +21,8 @@
#include "input/input_state.h"
#include "ui/ui.h"
#include "ui/ui_context.h"
#include "ui/view.h"
#include "ui/viewgroup.h"
#include "Core/HLE/sceCtrl.h"
#include "Common/KeyMap.h"
@ -31,104 +33,165 @@
extern void DrawBackground(float alpha);
void KeyMappingScreen::update(InputState &input) {
if (input.pad_buttons_down & PAD_BUTTON_BACK) {
g_Config.Save();
screenManager()->finishDialog(this, DR_OK);
class ControlMapper : public UI::LinearLayout {
public:
ControlMapper(int pspKey, std::string keyName, ScreenManager *scrm, UI::LinearLayoutParams *layoutParams = 0);
virtual void Update(const InputState &input);
private:
void Refresh();
UI::EventReturn OnAdd(UI::EventParams &params);
UI::EventReturn OnDelete(UI::EventParams &params);
UI::EventReturn OnReplace(UI::EventParams &params);
UI::EventReturn OnReplaceAll(UI::EventParams &params);
void MappedCallback(KeyDef key);
enum Action {
NONE,
REPLACEONE,
REPLACEALL,
ADD,
};
Action action_;
int actionIndex_;
int pspKey_;
std::string keyName_;
ScreenManager *scrm_;
bool refresh_;
};
ControlMapper::ControlMapper(int pspKey, std::string keyName, ScreenManager *scrm, UI::LinearLayoutParams *layoutParams)
: UI::LinearLayout(UI::ORIENT_VERTICAL, layoutParams), action_(NONE), pspKey_(pspKey), keyName_(keyName), scrm_(scrm), refresh_(false) {
Refresh();
}
void ControlMapper::Update(const InputState &input) {
if (refresh_) {
refresh_ = false;
Refresh();
}
}
void KeyMappingScreen::render() {
UIShader_Prepare();
UIBegin(UIShader_Get());
DrawBackground(1.0f);
void ControlMapper::Refresh() {
Clear();
UIContext *ctx = screenManager()->getUIContext();
UIFlush();
using namespace UI;
I18NCategory *keyI18N = GetI18NCategory("KeyMapping");
I18NCategory *generalI18N = GetI18NCategory("General");
LinearLayout *root = Add(new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT)));
root->Add(new Choice(keyName_, new LinearLayoutParams(200, WRAP_CONTENT)))->OnClick.Handle(this, &ControlMapper::OnReplaceAll);
LinearLayout *rightColumn = root->Add(new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(1.0f)));
std::vector<KeyDef> mappings;
KeyMap::KeyFromPspButton(pspKey_, &mappings);
#define KeyBtn(x, y, symbol) \
if (UIButton(GEN_ID, Pos(x, y), 90, 0, KeyMap::NameKeyFromPspButton(currentMap_, symbol).c_str(), \
ALIGN_TOPLEFT)) {\
screenManager()->push(new KeyMappingNewKeyDialog(symbol, currentMap_), 0); \
UIReset(); \
} \
UIText(0, Pos(x+30, y+50), KeyMap::NameDeviceFromPspButton(currentMap_, symbol).c_str(), 0xFFFFFFFF, 0.7f, ALIGN_HCENTER); \
UIText(0, Pos(x+30, y+80), KeyMap::GetPspButtonName(symbol).c_str(), 0xFFFFFFFF, 0.5f, ALIGN_HCENTER); \
for (size_t i = 0; i < mappings.size(); i++) {
std::string deviceName = GetDeviceName(mappings[i].deviceId);
std::string keyName = KeyMap::GetKeyOrAxisName(mappings[i].keyCode);
int image = -1;
LinearLayout *row = rightColumn->Add(new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT)));
// \
// UIText(0, Pos(x, y+50), controllerMaps[currentMap_].name.c_str(), 0xFFFFFFFF, 0.5f, ALIGN_HCENTER);
int pad = 130;
int hlfpad = pad / 2;
int left = 30;
KeyBtn(left, 30, CTRL_LTRIGGER);
int top = 120;
KeyBtn(left+hlfpad, top, CTRL_UP); // Up
KeyBtn(left, top+hlfpad, CTRL_LEFT);// Left
KeyBtn(left+pad, top+hlfpad, CTRL_RIGHT); // Right
KeyBtn(left+hlfpad, top+pad, CTRL_DOWN); // Down
top = 10;
left = 250;
KeyBtn(left+hlfpad, top, VIRTKEY_AXIS_Y_MAX); // Analog Up
KeyBtn(left, top+hlfpad, VIRTKEY_AXIS_X_MIN);// Analog Left
KeyBtn(left+pad, top+hlfpad, VIRTKEY_AXIS_X_MAX); // Analog Right
KeyBtn(left+hlfpad, top+pad, VIRTKEY_AXIS_Y_MIN); // Analog Down
top = 120;
left = 480;
KeyBtn(left+hlfpad, top, CTRL_TRIANGLE); // Triangle
KeyBtn(left, top+hlfpad, CTRL_SQUARE); // Square
KeyBtn(left+pad, top+hlfpad, CTRL_CIRCLE); // Circle
KeyBtn(left+hlfpad, top+pad, CTRL_CROSS); // Cross
left = 610;
KeyBtn(left, 30, CTRL_RTRIGGER);
top += pad + 50;
left = 250;
KeyBtn(left, top, CTRL_SELECT); // Select
KeyBtn(left + pad, top, CTRL_START); //Start
top = 10;
left = 720;
KeyBtn(left, top, VIRTKEY_UNTHROTTLE);
top += 100;
KeyBtn(left, top, VIRTKEY_SPEED_TOGGLE);
top += 100;
KeyBtn(left, top, VIRTKEY_PAUSE);
top += 100;
KeyBtn(left, top, VIRTKEY_RAPID_FIRE);
#undef KeyBtn
// TODO: Add rapid fire somewhere?
if (UIButton(GEN_ID, Pos(dp_xres - 10, dp_yres - 10), LARGE_BUTTON_WIDTH, 0, generalI18N->T("Back"), ALIGN_RIGHT | ALIGN_BOTTOM)) {
screenManager()->finishDialog(this, DR_OK);
Choice *c = row->Add(new Choice(deviceName + "." + keyName, new LinearLayoutParams(1.0f)));
char buf[10];
c->SetTag(itoa(i, buf, 10));
c->OnClick.Handle(this, &ControlMapper::OnReplace);
Choice *d = row->Add(new Choice("X"));
d->SetTag(itoa(i, buf, 10));
d->OnClick.Handle(this, &ControlMapper::OnDelete);
row->Add(new Choice("+"))->OnClick.Handle(this, &ControlMapper::OnAdd);
}
if (UIButton(GEN_ID, Pos(10, dp_yres-10), LARGE_BUTTON_WIDTH, 0, generalI18N->T("Prev"), ALIGN_BOTTOMLEFT)) {
currentMap_--;
if (currentMap_ < 0)
currentMap_ = (int)controllerMaps.size() - 1;
if (mappings.size() == 0) {
// look like an empty line
rightColumn->Add(new Choice("", new LinearLayoutParams(WRAP_CONTENT, WRAP_CONTENT)))->OnClick.Handle(this, &ControlMapper::OnAdd);
}
if (UIButton(GEN_ID, Pos(10 + 10 + LARGE_BUTTON_WIDTH, dp_yres-10), LARGE_BUTTON_WIDTH, 0, generalI18N->T("Next"), ALIGN_BOTTOMLEFT)) {
currentMap_++;
if (currentMap_ >= (int)controllerMaps.size())
currentMap_ = 0;
}
void ControlMapper::MappedCallback(KeyDef kdf) {
switch (action_) {
case ADD:
KeyMap::SetKeyMapping(pspKey_, kdf, false);
break;
case REPLACEALL:
KeyMap::SetKeyMapping(pspKey_, kdf, true);
break;
case REPLACEONE:
KeyMap::g_controllerMap[pspKey_][actionIndex_] = kdf;
break;
}
char temp[256];
sprintf(temp, "%s (%i/%i)", controllerMaps[currentMap_].name.c_str(), currentMap_ + 1, (int)controllerMaps.size());
UIText(0, Pos(10, dp_yres-170), temp, 0xFFFFFFFF, 1.0f, ALIGN_BOTTOMLEFT);
UICheckBox(GEN_ID,10, dp_yres - 80, keyI18N->T("Mapping Active"), ALIGN_BOTTOMLEFT, &controllerMaps[currentMap_].active);
UIEnd();
refresh_ = true;
}
UI::EventReturn ControlMapper::OnReplace(UI::EventParams &params) {
actionIndex_ = atoi(params.v->Tag().c_str());
action_ = REPLACEONE;
scrm_->push(new KeyMappingNewKeyDialog(pspKey_, true, std::bind(&ControlMapper::MappedCallback, this, placeholder::_1)));
return UI::EVENT_DONE;
}
UI::EventReturn ControlMapper::OnReplaceAll(UI::EventParams &params) {
action_ = REPLACEALL;
scrm_->push(new KeyMappingNewKeyDialog(pspKey_, true, std::bind(&ControlMapper::MappedCallback, this, placeholder::_1)));
return UI::EVENT_DONE;
}
UI::EventReturn ControlMapper::OnAdd(UI::EventParams &params) {
action_ = ADD;
scrm_->push(new KeyMappingNewKeyDialog(pspKey_, true, std::bind(&ControlMapper::MappedCallback, this, placeholder::_1)));
return UI::EVENT_DONE;
}
UI::EventReturn ControlMapper::OnDelete(UI::EventParams &params) {
int index = atoi(params.v->Tag().c_str());
KeyMap::g_controllerMap[pspKey_].erase(KeyMap::g_controllerMap[pspKey_].begin() + index);
refresh_ = true;
return UI::EVENT_DONE;
}
void ControlMappingScreen::CreateViews() {
using namespace UI;
I18NCategory *k = GetI18NCategory("KeyMapping");
I18NCategory *g = GetI18NCategory("General");
root_ = new LinearLayout(ORIENT_HORIZONTAL);
LinearLayout *leftColumn = new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(200, FILL_PARENT));
leftColumn->Add(new Choice(k->T("Clear All")))->OnClick.Handle(this, &ControlMappingScreen::OnClearMapping);
leftColumn->Add(new Spacer(new LinearLayoutParams(1.0f)));
leftColumn->Add(new Choice(g->T("Back")))->OnClick.Handle<UIScreen>(this, &UIScreen::OnBack);
/*
ChoiceStrip *mode = leftColumn->Add(new ChoiceStrip(ORIENT_VERTICAL));
mode->AddChoice("Replace");
mode->AddChoice("Add");
*/
ScrollView *rightScroll = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(1.0f));
LinearLayout *rightColumn = new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(1.0f));
rightScroll->Add(rightColumn);
root_->Add(leftColumn);
root_->Add(rightScroll);
std::vector<KeyMap::KeyMap_IntStrPair> mappableKeys = KeyMap::GetMappableKeys();
for (size_t i = 0; i < mappableKeys.size(); i++) {
rightColumn->Add(new ControlMapper(mappableKeys[i].key, mappableKeys[i].name, screenManager(), new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT)));
}
}
UI::EventReturn ControlMappingScreen::OnClearMapping(UI::EventParams &params) {
KeyMap::g_controllerMap.clear();
RecreateViews();
return UI::EVENT_DONE;
}
void KeyMappingNewKeyDialog::CreatePopupContents(UI::ViewGroup *parent) {
@ -140,10 +203,6 @@ void KeyMappingNewKeyDialog::CreatePopupContents(UI::ViewGroup *parent) {
std::string pspButtonName = KeyMap::GetPspButtonName(this->pspBtn_);
parent->Add(new TextView(std::string(keyI18N->T("Map a new key for ")) + pspButtonName));
std::string buttonKey = KeyMap::NameKeyFromPspButton(currentMap_, this->pspBtn_);
std::string buttonDevice = KeyMap::NameDeviceFromPspButton(currentMap_, this->pspBtn_);
parent->Add(new TextView(std::string(keyI18N->T("Previous:")) + " " + buttonKey + " - " + buttonDevice));
}
void KeyMappingNewKeyDialog::key(const KeyInput &key) {
@ -151,32 +210,26 @@ void KeyMappingNewKeyDialog::key(const KeyInput &key) {
if (key.keyCode == NKCODE_EXT_MOUSEBUTTON_1) {
return;
}
last_kb_deviceid_ = key.deviceId;
last_kb_key_ = key.keyCode;
last_axis_id_ = -1;
KeyMap::SetKeyMapping(currentMap_, last_kb_deviceid_, last_kb_key_, pspBtn_);
KeyDef kdf(key.deviceId, key.keyCode);
screenManager()->finishDialog(this, DR_OK);
if (callback_)
callback_(kdf);
}
}
void KeyMappingNewKeyDialog::axis(const AxisInput &axis) {
if (axis.value > AXIS_BIND_THRESHOLD) {
last_axis_deviceid_ = axis.deviceId;
last_axis_id_ = axis.axisId;
last_axis_direction_ = 1;
last_kb_key_ = 0;
KeyMap::SetAxisMapping(currentMap_, last_axis_deviceid_, last_axis_id_, last_axis_direction_, pspBtn_);
KeyDef kdf(axis.deviceId, KeyMap::TranslateKeyCodeFromAxis(axis.axisId, 1));
screenManager()->finishDialog(this, DR_OK);
if (callback_)
callback_(kdf);
}
if (axis.value < -AXIS_BIND_THRESHOLD) {
last_axis_deviceid_ = axis.deviceId;
last_axis_id_ = axis.axisId;
last_axis_direction_ = -1;
last_kb_key_ = 0;
KeyMap::SetAxisMapping(currentMap_, last_axis_deviceid_, last_axis_id_, last_axis_direction_, pspBtn_);
KeyDef kdf(axis.deviceId, KeyMap::TranslateKeyCodeFromAxis(axis.axisId, -1));
screenManager()->finishDialog(this, DR_OK);
if (callback_)
callback_(kdf);
}
}

View file

@ -15,28 +15,26 @@
// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
#include "base/functional.h"
#include "ui/view.h"
#include "ui/ui_screen.h"
class KeyMappingScreen : public Screen {
#include "UI/MiscScreens.h"
class ControlMappingScreen : public UIDialogScreenWithBackground {
public:
KeyMappingScreen() : currentMap_(0) {}
void update(InputState &input);
void render();
ControlMappingScreen() {}
protected:
virtual void CreateViews();
private:
int currentMap_;
UI::EventReturn OnClearMapping(UI::EventParams &params);
};
// Dialog box, meant to be pushed
class KeyMappingNewKeyDialog : public PopupScreen {
public:
KeyMappingNewKeyDialog(int btn, int currentMap) : PopupScreen("Map Key") {
explicit KeyMappingNewKeyDialog(int btn, bool replace, std::function<void(KeyDef)> callback) : PopupScreen("Map Key"), callback_(callback) {
pspBtn_ = btn;
last_kb_deviceid_ = 0;
last_kb_key_ = 0;
last_axis_deviceid_ = 0;
last_axis_id_ = -1;
currentMap_ = currentMap;
}
void key(const KeyInput &key);
@ -51,10 +49,6 @@ protected:
private:
int pspBtn_;
int last_kb_deviceid_;
int last_kb_key_;
int last_axis_deviceid_;
int last_axis_id_;
int last_axis_direction_;
int currentMap_;
bool replace_;
std::function<void(KeyDef)> callback_;
};

View file

@ -24,7 +24,7 @@
// set game specific settings, etc.
// Uses GameInfoCache heavily to implement the functionality.
class GameScreen : public DialogScreen {
class GameScreen : public UIDialogScreen {
public:
GameScreen(std::string gamePath) : gamePath_(gamePath) {}

View file

@ -91,8 +91,10 @@ void PopupMultiChoice::UpdateText() {
}
void PopupMultiChoice::ChoiceCallback(int num) {
*value_ = num + minVal_;
UpdateText();
if (num != -1) {
*value_ = num + minVal_;
UpdateText();
}
}
void PopupMultiChoice::Draw(UIContext &dc) {
@ -260,22 +262,23 @@ void GameSettingsScreen::CreateViews() {
atracString.assign(Atrac3plus_Decoder::IsInstalled() ? "Redownload Atrac3+ plugin" : "Download Atrac3+ plugin");
audioSettings->Add(new Choice(a->T(atracString.c_str())))->OnClick.Handle(this, &GameSettingsScreen::OnDownloadPlugin);
audioSettings->Add(new CheckBox(&g_Config.bEnableSound, a->T("Enable Sound")));
audioSettings->Add(new CheckBox(&g_Config.bEnableAtrac3plus, a->T("Enable Atrac3+")));
audioSettings->Add(new PopupSliderChoice(&g_Config.iSFXVolume, 0, 8, a->T("SFX volume"), screenManager()));
audioSettings->Add(new PopupSliderChoice(&g_Config.iBGMVolume, 0, 8, a->T("BGM volume"), screenManager()));
audioSettings->Add(new CheckBox(&g_Config.bEnableSound, a->T("Enable Sound")));
audioSettings->Add(new CheckBox(&g_Config.bEnableAtrac3plus, a->T("Enable Atrac3+")));
// Control
ViewGroup *controlsSettingsScroll = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, FILL_PARENT));
ViewGroup *controlsSettings = new LinearLayout(ORIENT_VERTICAL);
controlsSettingsScroll->Add(controlsSettings);
tabHolder->AddTab(ms->T("Controls"), controlsSettingsScroll);
controlsSettings->Add(new CheckBox(&g_Config.bShowTouchControls, c->T("OnScreen", "On-Screen Touch Controls")));
controlsSettings->Add(new CheckBox(&g_Config.bShowAnalogStick, c->T("Show Left Analog Stick")));
controlsSettings->Add(new CheckBox(&g_Config.bAccelerometerToAnalogHoriz, c->T("Tilt", "Tilt to Analog (horizontal)")));
controlsSettings->Add(new Choice(gs->T("Control Mapping")))->OnClick.Handle(this, &GameSettingsScreen::OnControlMapping);
controlsSettings->Add(new CheckBox(&g_Config.bShowTouchControls, c->T("OnScreen", "On-Screen Touch Controls")));
controlsSettings->Add(new PopupSliderChoice(&g_Config.iTouchButtonOpacity, 0, 85, c->T("Button Opacity"), screenManager()));
controlsSettings->Add(new PopupSliderChoiceFloat(&g_Config.fButtonScale, 1.15, 2.05, c->T("Button Scaling"), screenManager()));
controlsSettings->Add(new CheckBox(&g_Config.bShowAnalogStick, c->T("Show Left Analog Stick")));
controlsSettings->Add(new CheckBox(&g_Config.bAccelerometerToAnalogHoriz, c->T("Tilt", "Tilt to Analog (horizontal)")));
// System
ViewGroup *systemSettingsScroll = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, FILL_PARENT));
@ -283,16 +286,16 @@ void GameSettingsScreen::CreateViews() {
systemSettingsScroll->Add(systemSettings);
tabHolder->AddTab(ms->T("System"), systemSettingsScroll);
systemSettings->Add(new CheckBox(&g_Config.bJit, s->T("Dynarec", "Dynarec (JIT)")));
systemSettings->Add(new CheckBox(&g_Config.bSeparateCPUThread, s->T("Multithreaded (experimental)")));
systemSettings->Add(new CheckBox(&g_Config.bFastMemory, s->T("Fast Memory", "Fast Memory (Unstable)")));
systemSettings->Add(new PopupSliderChoice(&g_Config.iLockedCPUSpeed, 0, 1000, gs->T("Unlock CPU Clock"), screenManager()));
systemSettings->Add(new CheckBox(&g_Config.bSeparateCPUThread, s->T("Multithreaded (experimental)")));
systemSettings->Add(new PopupSliderChoice(&g_Config.iLockedCPUSpeed, 0, 1000, gs->T("Change CPU Clock", "Change CPU Clock (0 = default)"), screenManager()));
systemSettings->Add(new CheckBox(&g_Config.bDayLightSavings, s->T("Day Light Saving")));
static const char *dateFormat[] = { "YYYYMMDD", "MMDDYYYY", "DDMMYYYY"};
systemSettings->Add(new PopupMultiChoice(&g_Config.iDateFormat, gs->T("Date Format"), dateFormat, 1, 3, s, screenManager()));
static const char *timeFormat[] = { "12HR", "24HR"};
systemSettings->Add(new PopupMultiChoice(&g_Config.iTimeFormat, gs->T("Time Format"), timeFormat, 1, 2, s, screenManager()));
static const char *buttonPref[] = { "Use X to confirm", "Use O to confirm"};
systemSettings->Add(new PopupMultiChoice(&g_Config.iButtonPreference, gs->T("Button Preference"), buttonPref, 1, 2, s, screenManager()));
systemSettings->Add(new PopupMultiChoice(&g_Config.iButtonPreference, gs->T("Confirmation Button"), buttonPref, 1, 2, s, screenManager()));
}
void DrawBackground(float alpha);
@ -385,7 +388,7 @@ UI::EventReturn GlobalSettingsScreen::OnDeveloperTools(UI::EventParams &e) {
}
UI::EventReturn GameSettingsScreen::OnControlMapping(UI::EventParams &e) {
screenManager()->push(new KeyMappingScreen());
screenManager()->push(new ControlMappingScreen());
return UI::EVENT_DONE;
}

View file

@ -712,10 +712,11 @@ void ControlsScreen::render() {
g_Config.iTouchButtonOpacity = bTransparent ? 15 : 65;
}
y += 10;
// Button to KeyMapping screen
HLinear hlinear(x, y += stride, 20);
if (UIButton(GEN_ID, hlinear, 250, 0, c->T("Key Mapping"), ALIGN_LEFT)) {
screenManager()->push(new KeyMappingScreen());
screenManager()->push(new ControlMappingScreen());
}
if (UIButton(GEN_ID, hlinear, 250, 0, c->T("Default Mapping"), ALIGN_LEFT)) {
KeyMap::RestoreDefault();

View file

@ -34,9 +34,9 @@ protected:
virtual void DrawBackground(UIContext &dc);
};
class UIDialogScreenWithBackground : public DialogScreen {
class UIDialogScreenWithBackground : public UIDialogScreen {
public:
UIDialogScreenWithBackground() : DialogScreen() {}
UIDialogScreenWithBackground() : UIDialogScreen() {}
protected:
virtual void DrawBackground(UIContext &dc);
};

View file

@ -19,6 +19,3 @@
#include "InputDevice.h"
#define XBOX_CODE_LEFTTRIGGER 0x00010000
#define XBOX_CODE_RIGHTTRIGGER 0x00020000

View file

@ -74,8 +74,6 @@ static void UnloadXInputDLL() {
// Permanent map. Actual mapping happens elsewhere.
static const struct {int from, to;} xinput_ctrl_map[] = {
{XBOX_CODE_LEFTTRIGGER, NKCODE_BUTTON_L2},
{XBOX_CODE_RIGHTTRIGGER, NKCODE_BUTTON_R2},
{XINPUT_GAMEPAD_A, NKCODE_BUTTON_A},
{XINPUT_GAMEPAD_B, NKCODE_BUTTON_B},
{XINPUT_GAMEPAD_X, NKCODE_BUTTON_X},
@ -165,6 +163,22 @@ int XinputDevice::UpdateState(InputState &input_state) {
NativeAxis(axis);
}
if (prevState.Gamepad.bLeftTrigger != state.Gamepad.bLeftTrigger) {
AxisInput axis;
axis.deviceId = DEVICE_ID_X360_0;
axis.axisId = JOYSTICK_AXIS_LTRIGGER;
axis.value = (float)state.Gamepad.bLeftTrigger / 255.0f;
NativeAxis(axis);
}
if (prevState.Gamepad.bRightTrigger != state.Gamepad.bRightTrigger) {
AxisInput axis;
axis.deviceId = DEVICE_ID_X360_0;
axis.axisId = JOYSTICK_AXIS_RTRIGGER;
axis.value = (float)state.Gamepad.bRightTrigger / 255.0f;
NativeAxis(axis);
}
this->prevState = state;
this->check_delay = 0;
@ -212,11 +226,6 @@ static Stick NormalizedDeadzoneFilter(short x, short y) {
void XinputDevice::ApplyButtons(XINPUT_STATE &state, InputState &input_state) {
u32 buttons = state.Gamepad.wButtons;
if (state.Gamepad.bLeftTrigger > XINPUT_GAMEPAD_TRIGGER_THRESHOLD)
buttons |= XBOX_CODE_LEFTTRIGGER;
if (state.Gamepad.bRightTrigger > XINPUT_GAMEPAD_TRIGGER_THRESHOLD)
buttons |= XBOX_CODE_RIGHTTRIGGER;
u32 downMask = buttons & (~prevButtons);
u32 upMask = (~buttons) & prevButtons;
prevButtons = buttons;

2
native

@ -1 +1 @@
Subproject commit 5422dead6ab36cd450bf02c4d2ec9350a5943b8c
Subproject commit 17996ccd4c133e2f930e9b7141875a6ed5e24558