mirror of
https://github.com/libretro/ppsspp.git
synced 2024-11-23 16:19:44 +00:00
Remove legacy key mapping and associate devices with keys (DInput has been left behind for now, will be fixed up soon). Saving is broken, will be fixed soon.
This commit is contained in:
parent
ab6133e419
commit
cc58e34cf8
@ -19,39 +19,110 @@
|
||||
#include "../Core/Config.h"
|
||||
#include "KeyMap.h"
|
||||
|
||||
using namespace KeyMap;
|
||||
|
||||
// Platform specific
|
||||
// default
|
||||
std::map<int,int> *platform_keymap = NULL;
|
||||
namespace KeyMap {
|
||||
|
||||
// TODO: Make use const_map.h from native
|
||||
struct DefaultKeyMap {
|
||||
static std::map<int,int> init()
|
||||
static KeyMapping defaultKeyboardMap()
|
||||
{
|
||||
std::map<int,int> m;
|
||||
m[KEYCODE_A] = CTRL_SQUARE;
|
||||
m[KEYCODE_S] = CTRL_TRIANGLE;
|
||||
m[KEYCODE_X] = CTRL_CIRCLE;
|
||||
m[KEYCODE_Z] = CTRL_CROSS;
|
||||
m[KEYCODE_Q] = CTRL_LTRIGGER;
|
||||
m[KEYCODE_W] = CTRL_RTRIGGER;
|
||||
m[KEYCODE_SPACE] = CTRL_START;
|
||||
KeyMapping m;
|
||||
m[KeyDef(DEVICE_ID_KEYBOARD, KEYCODE_A)] = CTRL_SQUARE;
|
||||
m[KeyDef(DEVICE_ID_KEYBOARD, KEYCODE_S)] = CTRL_TRIANGLE;
|
||||
m[KeyDef(DEVICE_ID_KEYBOARD, KEYCODE_X)] = CTRL_CIRCLE;
|
||||
m[KeyDef(DEVICE_ID_KEYBOARD, KEYCODE_Z)] = CTRL_CROSS;
|
||||
m[KeyDef(DEVICE_ID_KEYBOARD, KEYCODE_Q)] = CTRL_LTRIGGER;
|
||||
m[KeyDef(DEVICE_ID_KEYBOARD, KEYCODE_W)] = CTRL_RTRIGGER;
|
||||
m[KeyDef(DEVICE_ID_KEYBOARD, KEYCODE_SPACE)] = CTRL_START;
|
||||
#ifdef _WIN32
|
||||
m[KEYCODE_V] = CTRL_SELECT;
|
||||
m[KeyDef(DEVICE_ID_KEYBOARD, KEYCODE_V)] = CTRL_SELECT;
|
||||
#else
|
||||
m[KEYCODE_ENTER] = CTRL_SELECT;
|
||||
m[KeyDef(DEVICE_ID_KEYBOARD, KEYCODE_ENTER)] = CTRL_SELECT;
|
||||
#endif
|
||||
m[KEYCODE_DPAD_UP] = CTRL_UP;
|
||||
m[KEYCODE_DPAD_DOWN] = CTRL_DOWN;
|
||||
m[KEYCODE_DPAD_LEFT] = CTRL_LEFT;
|
||||
m[KEYCODE_DPAD_RIGHT] = CTRL_RIGHT;
|
||||
m[KeyDef(DEVICE_ID_KEYBOARD, KEYCODE_DPAD_UP)] = CTRL_UP;
|
||||
m[KeyDef(DEVICE_ID_KEYBOARD, KEYCODE_DPAD_DOWN)] = CTRL_DOWN;
|
||||
m[KeyDef(DEVICE_ID_KEYBOARD, KEYCODE_DPAD_LEFT)] = CTRL_LEFT;
|
||||
m[KeyDef(DEVICE_ID_KEYBOARD, KEYCODE_DPAD_RIGHT)] = CTRL_RIGHT;
|
||||
return m;
|
||||
}
|
||||
static std::map<int,int> KeyMap;
|
||||
|
||||
static KeyMapping default360Map()
|
||||
{
|
||||
KeyMapping m;
|
||||
m[KeyDef(DEVICE_ID_X360_0, KEYCODE_BUTTON_A)] = CTRL_CROSS;
|
||||
m[KeyDef(DEVICE_ID_X360_0, KEYCODE_BUTTON_B)] = CTRL_CIRCLE;
|
||||
m[KeyDef(DEVICE_ID_X360_0, KEYCODE_BUTTON_X)] = CTRL_SQUARE;
|
||||
m[KeyDef(DEVICE_ID_X360_0, KEYCODE_BUTTON_Y)] = CTRL_TRIANGLE;
|
||||
m[KeyDef(DEVICE_ID_X360_0, KEYCODE_DPAD_UP)] = CTRL_UP;
|
||||
m[KeyDef(DEVICE_ID_X360_0, KEYCODE_DPAD_RIGHT)] = CTRL_RIGHT;
|
||||
m[KeyDef(DEVICE_ID_X360_0, KEYCODE_DPAD_DOWN)] = CTRL_DOWN;
|
||||
m[KeyDef(DEVICE_ID_X360_0, KEYCODE_DPAD_LEFT)] = CTRL_LEFT;
|
||||
m[KeyDef(DEVICE_ID_X360_0, KEYCODE_BUTTON_START)] = CTRL_START;
|
||||
m[KeyDef(DEVICE_ID_X360_0, KEYCODE_BACK)] = CTRL_SELECT;
|
||||
m[KeyDef(DEVICE_ID_X360_0, KEYCODE_BUTTON_L1)] = CTRL_LTRIGGER;
|
||||
m[KeyDef(DEVICE_ID_X360_0, KEYCODE_BUTTON_R1)] = CTRL_RTRIGGER;
|
||||
return m;
|
||||
}
|
||||
|
||||
static KeyMapping defaultPadMap()
|
||||
{
|
||||
KeyMapping m;
|
||||
m[KeyDef(DEVICE_ID_PAD_0, KEYCODE_BUTTON_A)] = CTRL_CROSS;
|
||||
m[KeyDef(DEVICE_ID_PAD_0, KEYCODE_BUTTON_B)] = CTRL_CIRCLE;
|
||||
m[KeyDef(DEVICE_ID_PAD_0, KEYCODE_BUTTON_X)] = CTRL_SQUARE;
|
||||
m[KeyDef(DEVICE_ID_PAD_0, KEYCODE_BUTTON_Y)] = CTRL_TRIANGLE;
|
||||
m[KeyDef(DEVICE_ID_PAD_0, KEYCODE_DPAD_UP)] = CTRL_UP;
|
||||
m[KeyDef(DEVICE_ID_PAD_0, KEYCODE_DPAD_RIGHT)] = CTRL_RIGHT;
|
||||
m[KeyDef(DEVICE_ID_PAD_0, KEYCODE_DPAD_DOWN)] = CTRL_DOWN;
|
||||
m[KeyDef(DEVICE_ID_PAD_0, KEYCODE_DPAD_LEFT)] = CTRL_LEFT;
|
||||
m[KeyDef(DEVICE_ID_PAD_0, KEYCODE_BUTTON_START)] = CTRL_START;
|
||||
m[KeyDef(DEVICE_ID_PAD_0, KEYCODE_BACK)] = CTRL_SELECT;
|
||||
m[KeyDef(DEVICE_ID_PAD_0, KEYCODE_BUTTON_L1)] = CTRL_LTRIGGER;
|
||||
m[KeyDef(DEVICE_ID_PAD_0, KEYCODE_BUTTON_R1)] = CTRL_RTRIGGER;
|
||||
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.
|
||||
ControllerMap pad;
|
||||
pad.keys = defaultPadMap();
|
||||
pad.name = "Pad";
|
||||
m.push_back(pad);
|
||||
|
||||
ControllerMap kbd;
|
||||
kbd.keys = defaultKeyboardMap();
|
||||
kbd.name = "Keyboard";
|
||||
m.push_back(kbd);
|
||||
#else
|
||||
ControllerMap kbd;
|
||||
kbd.keys = defaultKeyboardMap();
|
||||
kbd.name = "Keyboard";
|
||||
m.push_back(kbd);
|
||||
|
||||
#ifdef _WIN32
|
||||
ControllerMap x360;
|
||||
x360.keys = default360Map();
|
||||
x360.name = "360";
|
||||
m.push_back(x360);
|
||||
#endif
|
||||
// Keyboard and pad maps.
|
||||
ControllerMap pad;
|
||||
pad.keys = defaultPadMap();
|
||||
pad.name = "Pad";
|
||||
pad.active = false;
|
||||
m.push_back(pad);
|
||||
#endif
|
||||
return m;
|
||||
}
|
||||
|
||||
static std::vector<ControllerMap> KeyMap;
|
||||
};
|
||||
|
||||
std::map<int,int> DefaultKeyMap::KeyMap = DefaultKeyMap::init();
|
||||
std::vector<ControllerMap> DefaultKeyMap::KeyMap = DefaultKeyMap::init();
|
||||
|
||||
|
||||
// Key & Button names
|
||||
struct KeyMap_IntStrPair {
|
||||
@ -86,6 +157,7 @@ const KeyMap_IntStrPair key_names[] = {
|
||||
{KEYCODE_Y, "Y"},
|
||||
{KEYCODE_Z, "Z"},
|
||||
|
||||
{KEYCODE_0, "0"},
|
||||
{KEYCODE_1, "1"},
|
||||
{KEYCODE_2, "2"},
|
||||
{KEYCODE_3, "3"},
|
||||
@ -95,39 +167,96 @@ const KeyMap_IntStrPair key_names[] = {
|
||||
{KEYCODE_7, "7"},
|
||||
{KEYCODE_8, "8"},
|
||||
{KEYCODE_9, "9"},
|
||||
{KEYCODE_0, "0"},
|
||||
|
||||
{KEYCODE_F1, "F1"},
|
||||
{KEYCODE_F2, "F2"},
|
||||
{KEYCODE_F3, "F3"},
|
||||
{KEYCODE_F4, "F4"},
|
||||
{KEYCODE_F5, "F5"},
|
||||
{KEYCODE_F6, "F6"},
|
||||
{KEYCODE_F7, "F7"},
|
||||
{KEYCODE_F8, "F8"},
|
||||
{KEYCODE_F9, "F9"},
|
||||
{KEYCODE_F10, "F10"},
|
||||
{KEYCODE_F11, "F11"},
|
||||
{KEYCODE_F12, "F12"},
|
||||
|
||||
{KEYCODE_COMMA, ","},
|
||||
{KEYCODE_PERIOD, "."},
|
||||
|
||||
{KEYCODE_BACK, "Back"},
|
||||
{KEYCODE_TAB, "Tab"},
|
||||
{KEYCODE_ENTER, "Enter"},
|
||||
{KEYCODE_SHIFT_LEFT, "Shift"},
|
||||
{KEYCODE_SHIFT_RIGHT, "Shift"},
|
||||
{KEYCODE_CTRL_LEFT, "Ctrl"},
|
||||
{KEYCODE_CTRL_RIGHT, "Ctrl"},
|
||||
{KEYCODE_ALT_LEFT, "Alt"},
|
||||
{KEYCODE_ALT_RIGHT, "Alt"},
|
||||
{KEYCODE_SHIFT_LEFT, "LShift"},
|
||||
{KEYCODE_SHIFT_RIGHT, "RShift"},
|
||||
{KEYCODE_CTRL_LEFT, "LCtrl"},
|
||||
{KEYCODE_CTRL_RIGHT, "RCtrl"},
|
||||
{KEYCODE_ALT_LEFT, "LAlt"},
|
||||
{KEYCODE_ALT_RIGHT, "RAlt"},
|
||||
{KEYCODE_SPACE, "Space"},
|
||||
{KEYCODE_WINDOW, "Windows"},
|
||||
{KEYCODE_DEL, "Del"},
|
||||
{KEYCODE_MOVE_HOME, "Home"},
|
||||
{KEYCODE_MOVE_END, "End"},
|
||||
|
||||
{KEYCODE_VOLUME_UP, "Vol Up"},
|
||||
{KEYCODE_VOLUME_DOWN, "Vol Down"},
|
||||
{KEYCODE_VOLUME_UP, "Vol +"},
|
||||
{KEYCODE_VOLUME_DOWN, "Vol -"},
|
||||
{KEYCODE_HOME, "Home"},
|
||||
{KEYCODE_CALL, "Start Call"},
|
||||
{KEYCODE_CALL, "Call"},
|
||||
{KEYCODE_ENDCALL, "End Call"},
|
||||
|
||||
{KEYCODE_DPAD_LEFT, "Left"},
|
||||
{KEYCODE_DPAD_UP, "Up"},
|
||||
{KEYCODE_DPAD_RIGHT, "Right"},
|
||||
{KEYCODE_DPAD_DOWN, "Down"},
|
||||
|
||||
{KEYCODE_BUTTON_L1, "L1"},
|
||||
{KEYCODE_BUTTON_L2, "L2"},
|
||||
{KEYCODE_BUTTON_R1, "R1"},
|
||||
{KEYCODE_BUTTON_R2, "R2"},
|
||||
|
||||
{KEYCODE_BUTTON_A, "[A]"},
|
||||
{KEYCODE_BUTTON_B, "[B]"},
|
||||
{KEYCODE_BUTTON_C, "[C]"},
|
||||
{KEYCODE_BUTTON_X, "[X]"},
|
||||
{KEYCODE_BUTTON_Y, "[Y]"},
|
||||
{KEYCODE_BUTTON_Z, "[Z]"},
|
||||
{KEYCODE_BUTTON_1, "b1"},
|
||||
{KEYCODE_BUTTON_2, "b2"},
|
||||
{KEYCODE_BUTTON_3, "b3"},
|
||||
{KEYCODE_BUTTON_4, "b4"},
|
||||
{KEYCODE_BUTTON_5, "b5"},
|
||||
{KEYCODE_BUTTON_6, "b6"},
|
||||
{KEYCODE_BUTTON_7, "b7"},
|
||||
{KEYCODE_BUTTON_8, "b8"},
|
||||
{KEYCODE_BUTTON_9, "b9"},
|
||||
{KEYCODE_BUTTON_10, "b10"},
|
||||
{KEYCODE_BUTTON_11, "b11"},
|
||||
{KEYCODE_BUTTON_12, "b12"},
|
||||
{KEYCODE_BUTTON_13, "b13"},
|
||||
{KEYCODE_BUTTON_14, "b14"},
|
||||
{KEYCODE_BUTTON_15, "b15"},
|
||||
{KEYCODE_BUTTON_16, "b16"},
|
||||
{KEYCODE_BUTTON_START, "Start"},
|
||||
{KEYCODE_BUTTON_SELECT, "Select"},
|
||||
{KEYCODE_BUTTON_CIRCLE, "Circle"},
|
||||
{KEYCODE_BUTTON_CIRCLE_PS3, "Circle3"},
|
||||
{KEYCODE_BUTTON_CROSS, "Cross"},
|
||||
{KEYCODE_BUTTON_CROSS_PS3, "Cross3"},
|
||||
{KEYCODE_BUTTON_TRIANGLE, "Triangle"},
|
||||
{KEYCODE_BUTTON_SQUARE, "Square"},
|
||||
{KEYCODE_BUTTON_THUMBL, "ThumbL"},
|
||||
{KEYCODE_BUTTON_THUMBR, "ThumbR"},
|
||||
{KEYCODE_BUTTON_MODE, "Mode"},
|
||||
};
|
||||
|
||||
static int key_names_count = sizeof(key_names) / sizeof(key_names[0]);
|
||||
static std::string unknown_key_name = "Unknown";
|
||||
const KeyMap_IntStrPair psp_button_names[] = {
|
||||
{CTRL_CIRCLE, "○"},
|
||||
{CTRL_CROSS, "⨯"},
|
||||
{CTRL_SQUARE, "□"},
|
||||
{CTRL_TRIANGLE, "△"},
|
||||
{CTRL_CIRCLE, "O"},
|
||||
{CTRL_CROSS, "X"},
|
||||
{CTRL_SQUARE, "[ ]"},
|
||||
{CTRL_TRIANGLE, "/\\"},
|
||||
{CTRL_LTRIGGER, "L"},
|
||||
{CTRL_RTRIGGER, "R"},
|
||||
{CTRL_START, "Start"},
|
||||
@ -139,7 +268,6 @@ const KeyMap_IntStrPair psp_button_names[] = {
|
||||
};
|
||||
static int psp_button_names_count = sizeof(psp_button_names) / sizeof(psp_button_names[0]);
|
||||
|
||||
|
||||
static std::string FindName(int key, const KeyMap_IntStrPair list[], int size)
|
||||
{
|
||||
for (int i = 0; i < size; i++)
|
||||
@ -149,125 +277,96 @@ static std::string FindName(int key, const KeyMap_IntStrPair list[], int size)
|
||||
return unknown_key_name;
|
||||
}
|
||||
|
||||
std::string KeyMap::GetKeyName(int key)
|
||||
std::string GetKeyName(int keyCode)
|
||||
{
|
||||
return FindName(key, key_names, key_names_count);
|
||||
return FindName(keyCode, key_names, key_names_count);
|
||||
}
|
||||
|
||||
std::string KeyMap::GetPspButtonName(int btn)
|
||||
std::string GetPspButtonName(int btn)
|
||||
{
|
||||
return FindName(btn, psp_button_names, psp_button_names_count);
|
||||
}
|
||||
|
||||
static bool FindKeyMapping(int key, int *map_id, int *psp_button)
|
||||
static bool FindKeyMapping(int deviceId, int key, int *psp_button)
|
||||
{
|
||||
std::map<int,int>::iterator it;
|
||||
if (*map_id <= 0) {
|
||||
// check user configuration
|
||||
std::map<int,int> user_map = g_Config.iMappingMap;
|
||||
it = user_map.find(key);
|
||||
if (it != user_map.end()) {
|
||||
*map_id = 0;
|
||||
*psp_button = it->second;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
if (*map_id <= 1 && platform_keymap != NULL) {
|
||||
// check optional platform specific keymap
|
||||
std::map<int,int> port_map = *platform_keymap;
|
||||
it = port_map.find(key);
|
||||
if (it != port_map.end()) {
|
||||
*map_id = 1;
|
||||
*psp_button = it->second;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (*map_id <= 2) {
|
||||
// check default keymap
|
||||
const std::map<int,int> default_map = DefaultKeyMap::KeyMap;
|
||||
const std::map<int,int>::const_iterator const_it = default_map.find(key);
|
||||
if (const_it != default_map.end()) {
|
||||
*map_id = 2;
|
||||
*psp_button = const_it->second;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
*map_id = -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int KeyMap::KeyToPspButton(int key)
|
||||
int KeyToPspButton(int deviceId, int key)
|
||||
{
|
||||
int search_start_layer = 0;
|
||||
int psp_button;
|
||||
|
||||
if (FindKeyMapping(key, &search_start_layer, &psp_button))
|
||||
if (FindKeyMapping(deviceId, key, &psp_button))
|
||||
return psp_button;
|
||||
|
||||
return KEYMAP_ERROR_UNKNOWN_KEY;
|
||||
}
|
||||
|
||||
bool KeyMap::IsMappedKey(int key)
|
||||
bool KeyFromPspButton(int controllerMap, int btn, int *deviceId, int *keyCode)
|
||||
{
|
||||
return KeyMap::KeyToPspButton(key) != KEYMAP_ERROR_UNKNOWN_KEY;
|
||||
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;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool KeyMap::IsUserDefined(int key)
|
||||
{
|
||||
int layer = 0;
|
||||
int ignored;
|
||||
FindKeyMapping(key, &layer, &ignored);
|
||||
return layer == 0; // key found in user settings
|
||||
std::string NameKeyFromPspButton(int controllerMap, int btn) {
|
||||
int deviceId;
|
||||
int keyCode;
|
||||
if (KeyFromPspButton(controllerMap, btn, &deviceId, &keyCode)) {
|
||||
return GetKeyName(keyCode);
|
||||
}
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
|
||||
std::string KeyMap::NamePspButtonFromKey(int key)
|
||||
{
|
||||
return KeyMap::GetPspButtonName(KeyMap::KeyToPspButton(key));
|
||||
std::string NameDeviceFromPspButton(int controllerMap, int btn) {
|
||||
int deviceId;
|
||||
int keyCode;
|
||||
if (KeyFromPspButton(controllerMap, btn, &deviceId, &keyCode)) {
|
||||
return GetDeviceName(deviceId);
|
||||
}
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
std::string KeyMap::NameKeyFromPspButton(int btn)
|
||||
bool IsMappedKey(int deviceId, int key)
|
||||
{
|
||||
// We drive our iteration
|
||||
// with the list of key names.
|
||||
for (int i = 0; i < key_names_count; i++) {
|
||||
const struct KeyMap_IntStrPair key_name = key_names[i];
|
||||
if (btn == KeyMap::KeyToPspButton(key_name.key))
|
||||
return key_name.name;
|
||||
return KeyToPspButton(deviceId, key) != KEYMAP_ERROR_UNKNOWN_KEY;
|
||||
}
|
||||
|
||||
std::string NamePspButtonFromKey(int deviceId, int key)
|
||||
{
|
||||
return GetPspButtonName(KeyToPspButton(deviceId, key));
|
||||
}
|
||||
|
||||
int SetKeyMapping(int map, int deviceId, int key, int btn)
|
||||
{
|
||||
if (IsMappedKey(deviceId, key)) {
|
||||
// TODO: Remove the existing mapping instead, less annoying.
|
||||
return KEYMAP_ERROR_KEY_ALREADY_USED;
|
||||
} else {
|
||||
controllerMaps[map].keys[KeyDef(deviceId, key)] = btn;
|
||||
}
|
||||
|
||||
// all psp buttons are mapped from some key
|
||||
// but it appears we do not have a name
|
||||
// for this key.
|
||||
return unknown_key_name;
|
||||
}
|
||||
|
||||
int KeyMap::SetKeyMapping(int key, int btn)
|
||||
{
|
||||
if (KeyMap::IsMappedKey(key))
|
||||
return KEYMAP_ERROR_KEY_ALREADY_USED;
|
||||
|
||||
g_Config.iMappingMap[key] = btn;
|
||||
return btn;
|
||||
}
|
||||
|
||||
int KeyMap::RegisterPlatformDefaultKeyMap(std::map<int,int> *overriding_map)
|
||||
{
|
||||
if (overriding_map == NULL)
|
||||
return 1;
|
||||
platform_keymap = overriding_map;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void KeyMap::DeregisterPlatformDefaultKeyMap()
|
||||
{
|
||||
platform_keymap = NULL;
|
||||
return;
|
||||
}
|
||||
} // KeyMap
|
||||
|
||||
std::vector<ControllerMap> controllerMaps = KeyMap::DefaultKeyMap::KeyMap;
|
||||
|
125
Common/KeyMap.h
125
Common/KeyMap.h
@ -25,73 +25,80 @@
|
||||
#define KEYMAP_ERROR_KEY_ALREADY_USED -1
|
||||
#define KEYMAP_ERROR_UNKNOWN_KEY 0
|
||||
|
||||
class KeyDef {
|
||||
public:
|
||||
KeyDef(int devId, int k) : deviceId(devId), keyCode(k) {}
|
||||
int deviceId;
|
||||
int keyCode;
|
||||
|
||||
bool operator < (const KeyDef &other) const {
|
||||
if (deviceId < other.deviceId) return true;
|
||||
if (deviceId > other.deviceId) return false;
|
||||
if (keyCode < other.keyCode) return true;
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
struct AxisPos {
|
||||
int axis;
|
||||
float 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;
|
||||
|
||||
// KeyMap
|
||||
// A translation layer for
|
||||
// key assignment. Provides
|
||||
// integration with Core's
|
||||
// config state.
|
||||
// A translation layer for key assignment. Provides
|
||||
// integration with Core's config state.
|
||||
//
|
||||
// Does not handle input
|
||||
// state managment.
|
||||
// Does not handle input state managment.
|
||||
//
|
||||
// Platform ports should
|
||||
// map their platform's
|
||||
// keys to KeyMap's keys.
|
||||
// Then have KeyMap transform
|
||||
// those into psp buttons.
|
||||
// Platform ports should map their platform's keys to KeyMap's keys (KEYCODE_*).
|
||||
//
|
||||
// Then have KeyMap transform those into psp buttons.
|
||||
|
||||
namespace KeyMap {
|
||||
// Use if you need to
|
||||
// display the textual
|
||||
// name
|
||||
// These functions are not
|
||||
// fast, do not call them
|
||||
// a million times.
|
||||
std::string GetKeyName(int key);
|
||||
std::string GetPspButtonName(int btn);
|
||||
// Use if you need to display the textual name
|
||||
std::string GetKeyName(int keyCode);
|
||||
std::string GetPspButtonName(int btn);
|
||||
|
||||
// Use if to translate
|
||||
// KeyMap Keys to PSP
|
||||
// buttons.
|
||||
// You should have
|
||||
// already translated
|
||||
// your platform's keys
|
||||
// to KeyMap keys.
|
||||
//
|
||||
// Returns KEYMAP_ERROR_UNKNOWN_KEY
|
||||
// for any unmapped key
|
||||
int KeyToPspButton(int key);
|
||||
// Use if to translate KeyMap Keys to PSP
|
||||
// buttons. You should have already translated
|
||||
// your platform's keys to KeyMap keys.
|
||||
//
|
||||
// Returns KEYMAP_ERROR_UNKNOWN_KEY
|
||||
// for any unmapped key
|
||||
int KeyToPspButton(int deviceId, int key);
|
||||
|
||||
bool IsMappedKey(int key);
|
||||
bool IsUserDefined(int key);
|
||||
bool IsMappedKey(int deviceId, int key);
|
||||
|
||||
// Might be usful if you want
|
||||
// to provide hints to users
|
||||
// upon mapping conflicts
|
||||
std::string NamePspButtonFromKey(int key);
|
||||
// Might be useful if you want to provide hints to users
|
||||
// about mapping conflicts
|
||||
std::string NamePspButtonFromKey(int deviceId, int key);
|
||||
|
||||
// Use for showing the existing
|
||||
// key mapping.
|
||||
std::string NameKeyFromPspButton(int btn);
|
||||
bool KeyFromPspButton(int controllerMap, int btn, int *deviceId, int *keyCode);
|
||||
std::string NameKeyFromPspButton(int controllerMap, int btn);
|
||||
std::string NameDeviceFromPspButton(int controllerMap, int btn);
|
||||
|
||||
// Configure the key mapping.
|
||||
// Any configuration will
|
||||
// be saved to the Core
|
||||
// config.
|
||||
//
|
||||
// Returns KEYMAP_ERROR_KEY_ALREADY_USED
|
||||
// for mapping conflicts. 0 otherwise.
|
||||
int SetKeyMapping(int kb_key, int psp_key);
|
||||
|
||||
// Platform specific keymaps
|
||||
// override KeyMap's defaults.
|
||||
// They do not override user's
|
||||
// configuration.
|
||||
// A platform default keymap
|
||||
// does not need to cover
|
||||
// all psp buttons.
|
||||
// Any buttons missing will
|
||||
// fallback to KeyMap's keymap.
|
||||
int RegisterPlatformDefaultKeyMap(std::map<int,int> *overriding_map);
|
||||
void DeregisterPlatformDefaultKeyMap();
|
||||
// Configure the key mapping.
|
||||
// Any configuration will be saved to the Core config.
|
||||
//
|
||||
// Returns KEYMAP_ERROR_KEY_ALREADY_USED
|
||||
// for mapping conflicts. 0 otherwise.
|
||||
int SetKeyMapping(int map, int deviceId, int keyCode, int psp_key);
|
||||
}
|
||||
|
||||
|
@ -138,7 +138,7 @@ void Config::Load(const char *iniFileName)
|
||||
control->Get("ShowTouchControls", &bShowTouchControls,false);
|
||||
#endif
|
||||
control->Get("LargeControls", &bLargeControls, false);
|
||||
control->Get("KeyMapping",iMappingMap);
|
||||
// control->Get("KeyMapping",iMappingMap);
|
||||
control->Get("AccelerometerToAnalogHoriz", &bAccelerometerToAnalogHoriz, false);
|
||||
control->Get("ForceInputDevice", &iForceInputDevice, -1);
|
||||
control->Get("RightStickBind", &iRightStickBind, 0);
|
||||
@ -246,7 +246,7 @@ void Config::Save()
|
||||
control->Set("ShowStick", bShowAnalogStick);
|
||||
control->Set("ShowTouchControls", bShowTouchControls);
|
||||
control->Set("LargeControls", bLargeControls);
|
||||
control->Set("KeyMapping",iMappingMap);
|
||||
// control->Set("KeyMapping",iMappingMap);
|
||||
control->Set("AccelerometerToAnalogHoriz", bAccelerometerToAnalogHoriz);
|
||||
control->Set("ForceInputDevice", iForceInputDevice);
|
||||
control->Set("RightStickBind", iRightStickBind);
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
#include "CommonTypes.h"
|
||||
|
||||
extern const char *PPSSPP_GIT_VERSION;
|
||||
@ -114,7 +115,6 @@ public:
|
||||
int iSwapRightAxes;
|
||||
|
||||
// Control
|
||||
std::map<int,int> iMappingMap; // Can be used differently depending on systems
|
||||
int iForceInputDevice;
|
||||
int iTouchButtonOpacity;
|
||||
float fButtonScale;
|
||||
|
@ -357,7 +357,7 @@ int __AudioMix(short *outstereo, int numFrames)
|
||||
|
||||
if (sz1 + sz2 < (size_t)numFrames) {
|
||||
underrun = (int)(sz1 + sz2) / 2;
|
||||
DEBUG_LOG(HLE, "Audio out buffer UNDERRUN at %i of %i", underrun, numFrames);
|
||||
VERBOSE_LOG(HLE, "Audio out buffer UNDERRUN at %i of %i", underrun, numFrames);
|
||||
}
|
||||
return underrun >= 0 ? underrun : numFrames;
|
||||
}
|
||||
|
@ -612,7 +612,7 @@ u32 _AtracDecodeData(int atracID, u8* outbuf, u32 *SamplesNum, u32* finish, int
|
||||
|
||||
if (atrac->decoder_context) {
|
||||
static u8 buf[0x8000];
|
||||
if (atrac->sampleQueue.getQueueSize() < ATRAC3PLUS_MAX_SAMPLES * sizeof(s16) * atrac->atracChannels) {
|
||||
if ((size_t)atrac->sampleQueue.getQueueSize() < ATRAC3PLUS_MAX_SAMPLES * sizeof(s16) * atrac->atracChannels) {
|
||||
int decodebytes = 0;
|
||||
atrac->decodePos = atrac->getDecodePosBySample(atrac->currentSample);
|
||||
int inbytes = std::max((int)atrac->first.size - (int)atrac->decodePos, 0);
|
||||
@ -658,7 +658,7 @@ u32 _AtracDecodeData(int atracID, u8* outbuf, u32 *SamplesNum, u32* finish, int
|
||||
atrac->decodePos = atrac->getDecodePosBySample(atrac->currentSample);
|
||||
|
||||
int finishFlag = 0;
|
||||
if (atrac->loopNum != 0 && (atrac->currentSample + atracSamplesPerFrame > atrac->loopEndSample ||
|
||||
if (atrac->loopNum != 0 && (atrac->currentSample + (int)atracSamplesPerFrame > atrac->loopEndSample ||
|
||||
(numSamples == 0 && atrac->first.size >= atrac->first.filesize))) {
|
||||
atrac->currentSample = atrac->loopStartSample;
|
||||
if (atrac->loopNum > 0)
|
||||
@ -1702,7 +1702,7 @@ int sceAtracLowLevelDecode(int atracID, u32 sourceAddr, u32 sourceBytesConsumedA
|
||||
}
|
||||
numSamples = ATRAC3PLUS_MAX_SAMPLES;
|
||||
Memory::Write_U32(numSamples * sizeof(s16) * atrac->atracOutputChannels, sampleBytesAddr);
|
||||
int space = atrac->sampleQueue.getQueueSize();
|
||||
size_t space = atrac->sampleQueue.getQueueSize();
|
||||
if (space < ATRAC3PLUS_MAX_SAMPLES * sizeof(s16) * atrac->atracChannels)
|
||||
atrac->first.writableBytes = atrac->atracBytesPerFrame;
|
||||
else
|
||||
|
@ -157,14 +157,22 @@ void __CtrlButtonUp(u32 buttonBit)
|
||||
ctrlCurrent.buttons &= ~buttonBit;
|
||||
}
|
||||
|
||||
void __CtrlSetAnalog(float x, float y, int stick)
|
||||
void __CtrlSetAnalogX(float x, int stick)
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> guard(ctrlMutex);
|
||||
if (stick == 0) {
|
||||
ctrlCurrent.analog[0] = (u8)ceilf(x * 127.5f + 127.5f);
|
||||
ctrlCurrent.analog[1] = (u8)ceilf(-y * 127.5f + 127.5f);
|
||||
} else {
|
||||
ctrlCurrent.analogRight[0] = (u8)ceilf(x * 127.5f + 127.5f);
|
||||
}
|
||||
}
|
||||
|
||||
void __CtrlSetAnalogY(float y, int stick)
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> guard(ctrlMutex);
|
||||
if (stick == 0) {
|
||||
ctrlCurrent.analog[1] = (u8)ceilf(-y * 127.5f + 127.5f);
|
||||
} else {
|
||||
ctrlCurrent.analogRight[1] = (u8)ceilf(-y * 127.5f + 127.5f);
|
||||
}
|
||||
}
|
||||
|
@ -43,7 +43,8 @@ void __CtrlShutdown();
|
||||
void __CtrlButtonDown(u32 buttonBit);
|
||||
void __CtrlButtonUp(u32 buttonBit);
|
||||
// -1 to 1, try to keep it in the circle
|
||||
void __CtrlSetAnalog(float x, float y, int stick = 0);
|
||||
void __CtrlSetAnalogX(float value, int stick = 0);
|
||||
void __CtrlSetAnalogY(float value, int stick = 0);
|
||||
|
||||
// For use by internal UI like MsgDialog
|
||||
u32 __CtrlPeekButtons();
|
||||
|
@ -842,7 +842,7 @@ void ConvertFromRGBA8888(u8 *dst, u8 *src, u32 stride, u32 height, int format) {
|
||||
memcpy(dst, src, stride * height * 4);
|
||||
}
|
||||
} else { // But here it shouldn't matter if they do
|
||||
u32 size = height * stride;
|
||||
int size = height * stride;
|
||||
const u32 *src32 = (const u32 *)src;
|
||||
u16 *dst16 = (u16 *)dst;
|
||||
switch (format) {
|
||||
@ -1034,8 +1034,8 @@ void FramebufferManager::PackFramebufferGLES_(VirtualFramebuffer *vfb) {
|
||||
}
|
||||
|
||||
if(packed) {
|
||||
DEBUG_LOG(HLE, "Reading framebuffer to mem, bufSize = %u, packed = %08x, fb_address = %08x",
|
||||
bufSize, packed, fb_address);
|
||||
DEBUG_LOG(HLE, "Reading framebuffer to mem, bufSize = %u, packed = %p, fb_address = %08x",
|
||||
(u32)bufSize, packed, fb_address);
|
||||
|
||||
glPixelStorei(GL_PACK_ALIGNMENT, 4);
|
||||
glReadPixels(0, 0, vfb->fb_stride, vfb->height, GL_RGBA, GL_UNSIGNED_BYTE, packed);
|
||||
|
13
GPU/Math3D.h
13
GPU/Math3D.h
@ -30,11 +30,15 @@ public:
|
||||
float x,y,z;
|
||||
};
|
||||
};
|
||||
Vec3(unsigned int rgb) { x=(rgb&0xFF)/255.0f; y=((rgb>>8)&0xFF)/255.0f; z=((rgb>>16)&0xFF)/255.0f;}
|
||||
Vec3(unsigned int rgb) {
|
||||
x = (rgb & 0xFF) * (1.0f/255.0f);
|
||||
y = ((rgb >> 8) & 0xFF) * (1.0f/255.0f);
|
||||
z = ((rgb >> 16) & 0xFF) * (1.0f/255.0f);
|
||||
}
|
||||
Vec3(const float a[3]) {
|
||||
v[0]=a[0];
|
||||
v[1]=a[1];
|
||||
v[2]=a[2];
|
||||
v[0] = a[0];
|
||||
v[1] = a[1];
|
||||
v[2] = a[2];
|
||||
}
|
||||
Vec3(float _x, float _y, float _z) : x(_x), y(_y), z(_z) {}
|
||||
Vec3() {}
|
||||
@ -92,7 +96,6 @@ public:
|
||||
{
|
||||
return Vec3(y*v.z-z*v.y, z*v.x-x*v.z, x*v.y-y*v.x);
|
||||
}
|
||||
|
||||
float Length2() const
|
||||
{
|
||||
return x*x + y*y + z*z;
|
||||
|
126
UI/EmuScreen.cpp
126
UI/EmuScreen.cpp
@ -15,6 +15,7 @@
|
||||
// Official git repository and contact information can be found at
|
||||
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
|
||||
|
||||
#include "android/app-android.h"
|
||||
#include "base/logging.h"
|
||||
|
||||
#include "gfx_es2/glsl_program.h"
|
||||
@ -106,7 +107,7 @@ EmuScreen::EmuScreen(const std::string &filename) : invalid_(true) {
|
||||
osm.Show(s->T("PressESC", "Press ESC to open the pause menu"), 3.0f);
|
||||
}
|
||||
#endif
|
||||
pressedLastUpdate = 0;
|
||||
memset(analog_, 0, sizeof(analog_));
|
||||
}
|
||||
|
||||
EmuScreen::~EmuScreen() {
|
||||
@ -175,6 +176,48 @@ inline float clamp1(float x) {
|
||||
return x;
|
||||
}
|
||||
|
||||
void EmuScreen::touch(const TouchInput &touch) {
|
||||
|
||||
}
|
||||
|
||||
void EmuScreen::key(const KeyInput &key) {
|
||||
int result = KeyMap::KeyToPspButton(key.deviceId, key.keyCode);
|
||||
if (result == KEYMAP_ERROR_UNKNOWN_KEY)
|
||||
return;
|
||||
|
||||
if (key.flags & KEY_DOWN)
|
||||
__CtrlButtonDown(result);
|
||||
if (key.flags & KEY_UP)
|
||||
__CtrlButtonUp(result);
|
||||
}
|
||||
|
||||
void EmuScreen::axis(const AxisInput &axis) {
|
||||
// TODO: Apply some form of axis mapping
|
||||
switch (axis.axisId) {
|
||||
case JOYSTICK_AXIS_X: analog_[0].x = axis.value; break;
|
||||
case JOYSTICK_AXIS_Y: analog_[0].y = axis.value; break;
|
||||
case JOYSTICK_AXIS_Z: analog_[1].x = axis.value; break;
|
||||
case JOYSTICK_AXIS_RZ: analog_[1].y = axis.value; break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// TODO: Get rid of this.
|
||||
static const struct { int from, to; } legacy_touch_mapping[12] = {
|
||||
{PAD_BUTTON_A, CTRL_CROSS},
|
||||
{PAD_BUTTON_B, CTRL_CIRCLE},
|
||||
{PAD_BUTTON_X, CTRL_SQUARE},
|
||||
{PAD_BUTTON_Y, CTRL_TRIANGLE},
|
||||
{PAD_BUTTON_START, CTRL_START},
|
||||
{PAD_BUTTON_BACK, CTRL_SELECT},
|
||||
{PAD_BUTTON_LBUMPER, CTRL_LTRIGGER},
|
||||
{PAD_BUTTON_RBUMPER, CTRL_RTRIGGER},
|
||||
{PAD_BUTTON_UP, CTRL_UP},
|
||||
{PAD_BUTTON_RIGHT, CTRL_RIGHT},
|
||||
{PAD_BUTTON_DOWN, CTRL_DOWN},
|
||||
{PAD_BUTTON_LEFT, CTRL_LEFT},
|
||||
};
|
||||
|
||||
void EmuScreen::update(InputState &input) {
|
||||
globalUIState = UISTATE_INGAME;
|
||||
if (errorMessage_.size()) {
|
||||
@ -196,72 +239,47 @@ void EmuScreen::update(InputState &input) {
|
||||
#ifdef _WIN32
|
||||
if(g_Config.bShowTouchControls) {
|
||||
#endif
|
||||
UpdateGamepad(input);
|
||||
// TODO: Make new better touch buttons so we don't have to do this crap.
|
||||
|
||||
// Copy over the mouse data from the real inputstate.
|
||||
fakeInputState.mouse_valid = input.mouse_valid;
|
||||
fakeInputState.pad_last_buttons = fakeInputState.pad_buttons;
|
||||
fakeInputState.pad_buttons = 0;
|
||||
memcpy(fakeInputState.pointer_down, input.pointer_down, sizeof(input.pointer_down));
|
||||
memcpy(fakeInputState.pointer_x, input.pointer_x, sizeof(input.pointer_x));
|
||||
memcpy(fakeInputState.pointer_y, input.pointer_y, sizeof(input.pointer_y));
|
||||
UpdateGamepad(fakeInputState);
|
||||
UpdateInputState(&fakeInputState);
|
||||
|
||||
for (int i = 0; i < ARRAY_SIZE(legacy_touch_mapping); i++) {
|
||||
if (fakeInputState.pad_buttons_down & legacy_touch_mapping[i].from)
|
||||
__CtrlButtonDown(legacy_touch_mapping[i].to);
|
||||
if (fakeInputState.pad_buttons_up & legacy_touch_mapping[i].from)
|
||||
__CtrlButtonUp(legacy_touch_mapping[i].to);
|
||||
}
|
||||
|
||||
UpdateInputState(&input);
|
||||
#ifdef _WIN32
|
||||
}
|
||||
#endif
|
||||
|
||||
// Set Keys ----
|
||||
|
||||
// Legacy key mapping
|
||||
// Then translate pad input into PSP pad input. Also, add in tilt.
|
||||
static const int mapping[12][2] = {
|
||||
{PAD_BUTTON_A, CTRL_CROSS},
|
||||
{PAD_BUTTON_B, CTRL_CIRCLE},
|
||||
{PAD_BUTTON_X, CTRL_SQUARE},
|
||||
{PAD_BUTTON_Y, CTRL_TRIANGLE},
|
||||
{PAD_BUTTON_UP, CTRL_UP},
|
||||
{PAD_BUTTON_DOWN, CTRL_DOWN},
|
||||
{PAD_BUTTON_LEFT, CTRL_LEFT},
|
||||
{PAD_BUTTON_RIGHT, CTRL_RIGHT},
|
||||
{PAD_BUTTON_LBUMPER, CTRL_LTRIGGER},
|
||||
{PAD_BUTTON_RBUMPER, CTRL_RTRIGGER},
|
||||
{PAD_BUTTON_START, CTRL_START},
|
||||
{PAD_BUTTON_SELECT, CTRL_SELECT},
|
||||
};
|
||||
|
||||
for (int i = 0; i < 12; i++) {
|
||||
if (input.pad_buttons_down & mapping[i][0]) {
|
||||
__CtrlButtonDown(mapping[i][1]);
|
||||
}
|
||||
if (input.pad_buttons_up & mapping[i][0]) {
|
||||
__CtrlButtonUp(mapping[i][1]);
|
||||
}
|
||||
}
|
||||
|
||||
// Modern key mapping
|
||||
uint32_t pressed = 0;
|
||||
for (int i = 0; i < MAX_KEYQUEUESIZE; i++) {
|
||||
int key = input.key_queue[i];
|
||||
if (key == 0)
|
||||
break;
|
||||
|
||||
// TODO: Add virt_sce_* codes for analog sticks
|
||||
pressed |= KeyMap::KeyToPspButton(key);
|
||||
}
|
||||
__CtrlButtonDown(pressed);
|
||||
__CtrlButtonUp(pressedLastUpdate & ~pressed);
|
||||
pressedLastUpdate = pressed;
|
||||
// End Set Keys --
|
||||
|
||||
float stick_x = input.pad_lstick_x;
|
||||
float stick_y = input.pad_lstick_y;
|
||||
float rightstick_x = input.pad_rstick_x;
|
||||
float rightstick_y = input.pad_rstick_y;
|
||||
float leftstick_x = analog_[0].x;
|
||||
float leftstick_y = analog_[0].y;
|
||||
float rightstick_x = analog_[1].x;
|
||||
float rightstick_y = analog_[1].y;
|
||||
|
||||
I18NCategory *s = GetI18NCategory("Screen");
|
||||
|
||||
// Apply tilt to left stick
|
||||
if (g_Config.bAccelerometerToAnalogHoriz) {
|
||||
// TODO: Deadzone, etc.
|
||||
stick_x += clamp1(curve1(input.acc.y) * 2.0f);
|
||||
stick_x = clamp1(stick_x);
|
||||
leftstick_x += clamp1(curve1(input.acc.y) * 2.0f);
|
||||
leftstick_x = clamp1(leftstick_x);
|
||||
}
|
||||
|
||||
__CtrlSetAnalog(stick_x, stick_y, 0);
|
||||
__CtrlSetAnalog(rightstick_x, rightstick_x, 1);
|
||||
__CtrlSetAnalogX(leftstick_x, 0);
|
||||
__CtrlSetAnalogY(leftstick_y, 0);
|
||||
__CtrlSetAnalogX(rightstick_x, 1);
|
||||
__CtrlSetAnalogY(rightstick_y, 1);
|
||||
|
||||
if (PSP_CoreParameter().fpsLimit != 2) {
|
||||
// Don't really need to show these, it's pretty obvious what unthrottle does,
|
||||
|
@ -34,9 +34,19 @@ public:
|
||||
virtual void dialogFinished(const Screen *dialog, DialogResult result);
|
||||
virtual void sendMessage(const char *msg, const char *value);
|
||||
|
||||
virtual void touch(const TouchInput &touch);
|
||||
virtual void key(const KeyInput &key);
|
||||
virtual void axis(const AxisInput &axis);
|
||||
|
||||
private:
|
||||
// Something invalid was loaded, don't try to emulate
|
||||
bool invalid_;
|
||||
std::string errorMessage_;
|
||||
uint32_t pressedLastUpdate;
|
||||
|
||||
// For the virtual touch buttons, that currently can't send key events.
|
||||
InputState fakeInputState;
|
||||
|
||||
|
||||
// Analog is still buffered.
|
||||
struct {float x, y;} analog_[2];
|
||||
};
|
||||
|
@ -686,19 +686,14 @@ void ControlsScreen::update(InputState &input) {
|
||||
}
|
||||
}
|
||||
|
||||
void KeyMappingScreen::update(InputState &input) {
|
||||
if (input.pad_buttons_down & PAD_BUTTON_BACK) {
|
||||
g_Config.Save();
|
||||
screenManager()->finishDialog(this, DR_OK);
|
||||
void KeyMappingNewKeyDialog::key(const KeyInput &key) {
|
||||
if (key.flags & KEY_DOWN) {
|
||||
last_kb_deviceid = key.deviceId;
|
||||
last_kb_key = key.keyCode;
|
||||
}
|
||||
}
|
||||
|
||||
void KeyMappingNewKeyDialog::update(InputState &input) {
|
||||
int new_key = input.key_queue[0];
|
||||
|
||||
if (new_key != 0)
|
||||
last_kb_key = new_key;
|
||||
|
||||
if (input.pad_buttons_down & PAD_BUTTON_BACK) {
|
||||
g_Config.Save();
|
||||
screenManager()->finishDialog(this, DR_OK);
|
||||
@ -1527,6 +1522,13 @@ void ControlsScreen::render() {
|
||||
UIEnd();
|
||||
}
|
||||
|
||||
void KeyMappingScreen::update(InputState &input) {
|
||||
if (input.pad_buttons_down & PAD_BUTTON_BACK) {
|
||||
g_Config.Save();
|
||||
screenManager()->finishDialog(this, DR_OK);
|
||||
}
|
||||
}
|
||||
|
||||
void KeyMappingScreen::render() {
|
||||
UIShader_Prepare();
|
||||
UIBegin(UIShader_Get());
|
||||
@ -1537,20 +1539,22 @@ void KeyMappingScreen::render() {
|
||||
|
||||
|
||||
#define KeyBtn(x, y, symbol) \
|
||||
if (UIButton(GEN_ID, Pos(x, y), 50, 0, (KeyMap::GetPspButtonName(symbol)).c_str(), \
|
||||
if (UIButton(GEN_ID, Pos(x, y), 60, 0, KeyMap::NameKeyFromPspButton(currentMap_, symbol).c_str(), \
|
||||
ALIGN_TOPLEFT)) {\
|
||||
screenManager()->push(new KeyMappingNewKeyDialog(symbol), 0); \
|
||||
screenManager()->push(new KeyMappingNewKeyDialog(symbol, currentMap_), 0); \
|
||||
UIReset(); \
|
||||
}
|
||||
} \
|
||||
UIText(0, Pos(x+30, y+50), KeyMap::NameDeviceFromPspButton(currentMap_, symbol).c_str(), 0xFFFFFFFF, 0.78f, ALIGN_HCENTER); \
|
||||
UIText(0, Pos(x+30, y+80), KeyMap::GetPspButtonName(symbol).c_str(), 0xFFFFFFFF, 0.5f, ALIGN_HCENTER); \
|
||||
|
||||
KeyMap::DeregisterPlatformDefaultKeyMap();
|
||||
// \
|
||||
// UIText(0, Pos(x, y+50), controllerMaps[currentMap_].name.c_str(), 0xFFFFFFFF, 0.5f, ALIGN_HCENTER);
|
||||
|
||||
int pad = 150;
|
||||
int pad = 130;
|
||||
int hlfpad = pad / 2;
|
||||
|
||||
int left = 30;
|
||||
KeyBtn(left, 30, CTRL_LTRIGGER);
|
||||
KeyBtn(dp_yres, 30, CTRL_RTRIGGER);
|
||||
|
||||
int top = 100;
|
||||
KeyBtn(left+hlfpad, top, CTRL_UP); // ^
|
||||
@ -1558,21 +1562,35 @@ void KeyMappingScreen::render() {
|
||||
KeyBtn(left+pad, top+hlfpad, CTRL_RIGHT); // >
|
||||
KeyBtn(left+hlfpad, top+pad, CTRL_DOWN); // <
|
||||
|
||||
left = dp_yres;
|
||||
left = 500;
|
||||
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
|
||||
KeyBtn(left, 30, CTRL_RTRIGGER);
|
||||
|
||||
top += pad;
|
||||
left = dp_yres /2;
|
||||
KeyBtn(left, top, CTRL_START);
|
||||
KeyBtn(left + pad, top, CTRL_SELECT);
|
||||
left = 250;
|
||||
KeyBtn(left, top, CTRL_SELECT);
|
||||
KeyBtn(left + pad, top, CTRL_START);
|
||||
#undef KeyBtn
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
if (UIButton(GEN_ID, Pos(10, dp_yres-10), LARGE_BUTTON_WIDTH, 0, generalI18N->T("Prev"), ALIGN_BOTTOMLEFT)) {
|
||||
currentMap_--;
|
||||
if (currentMap_ < 0)
|
||||
currentMap_ = controllerMaps.size() - 1;
|
||||
}
|
||||
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_ >= controllerMaps.size())
|
||||
currentMap_ = 0;
|
||||
}
|
||||
UIText(0, Pos(10, dp_yres-170), controllerMaps[currentMap_].name.c_str(), 0xFFFFFFFF, 1.0f, ALIGN_BOTTOMLEFT);
|
||||
UICheckBox(GEN_ID,10, dp_yres - 80, "Mapping Active", ALIGN_BOTTOMLEFT, &controllerMaps[currentMap_].active);
|
||||
UIEnd();
|
||||
}
|
||||
|
||||
@ -1598,22 +1616,26 @@ void KeyMappingNewKeyDialog::render() {
|
||||
KeyScale(1.3f);
|
||||
KeyText(left, top += stride, keyI18N->T("Current key"));
|
||||
KeyScale(2.0f);
|
||||
KeyText(left, top + stride, (KeyMap::NameKeyFromPspButton(this->pspBtn)).c_str());
|
||||
KeyText(left, top += stride, (KeyMap::NameKeyFromPspButton(currentMap_, this->pspBtn)).c_str());
|
||||
KeyScale(1.4f);
|
||||
KeyText(left, top + stride, (KeyMap::NameDeviceFromPspButton(currentMap_, this->pspBtn)).c_str());
|
||||
|
||||
int right = dp_yres;
|
||||
KeyScale(1.4f);
|
||||
KeyText(right, top, keyI18N->T("New Key"));
|
||||
KeyScale(2.0f);
|
||||
if (last_kb_key != 0) {
|
||||
bool key_used = KeyMap::IsMappedKey(last_kb_key);
|
||||
bool key_used = KeyMap::IsMappedKey(last_kb_deviceid, last_kb_key);
|
||||
if (!key_used) {
|
||||
KeyText(right, top + stride, KeyMap::GetKeyName(last_kb_key).c_str());
|
||||
KeyText(right, top += stride, KeyMap::GetKeyName(last_kb_key).c_str());
|
||||
KeyScale(1.4f);
|
||||
KeyText(right, top + stride, GetDeviceName(last_kb_deviceid));
|
||||
} else {
|
||||
KeyScale(1.0f);
|
||||
KeyText(left + stride, top + 2*stride,
|
||||
keyI18N->T("Error: Key is already used by"));
|
||||
KeyText(left + stride, top + 3*stride,
|
||||
(KeyMap::NamePspButtonFromKey(last_kb_key)).c_str());
|
||||
//KeyText(left + stride, top + 3*stride,
|
||||
// (KeyMap::NamePspButtonFromKey(last_kb_key)).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
@ -1623,7 +1645,7 @@ void KeyMappingNewKeyDialog::render() {
|
||||
|
||||
// Save & cancel buttons
|
||||
if (UIButton(GEN_ID, Pos(10, dp_yres - 10), LARGE_BUTTON_WIDTH, 0, keyI18N->T("Save Mapping"), ALIGN_LEFT | ALIGN_BOTTOM)) {
|
||||
KeyMap::SetKeyMapping(this->last_kb_key, this->pspBtn);
|
||||
KeyMap::SetKeyMapping(currentMap_, this->last_kb_deviceid, this->last_kb_key, this->pspBtn);
|
||||
g_Config.Save();
|
||||
screenManager()->finishDialog(this, DR_OK);
|
||||
}
|
||||
@ -1879,6 +1901,14 @@ void CreditsScreen::render() {
|
||||
screenManager()->finishDialog(this, DR_OK);
|
||||
}
|
||||
|
||||
#ifdef ANDROID
|
||||
#ifndef GOLD
|
||||
if (UIButton(GEN_ID, Pos(10, dp_yres - 10), 200, 0, g->T("Buy PPSSPP Gold"), ALIGN_BOTTOMLEFT)) {
|
||||
sendMessage("launchBrowser", "market://details?id=org.ppsspp.ppssppgold");
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
UIEnd();
|
||||
}
|
||||
|
||||
|
@ -135,23 +135,32 @@ public:
|
||||
class KeyMappingScreen : public Screen
|
||||
{
|
||||
public:
|
||||
KeyMappingScreen() : currentMap_(0) {}
|
||||
void update(InputState &input);
|
||||
void render();
|
||||
private:
|
||||
int currentMap_;
|
||||
};
|
||||
|
||||
// Dialog box, meant to be pushed
|
||||
class KeyMappingNewKeyDialog : public Screen
|
||||
{
|
||||
private:
|
||||
int pspBtn;
|
||||
int last_kb_key;
|
||||
public:
|
||||
KeyMappingNewKeyDialog(int btn) {
|
||||
KeyMappingNewKeyDialog(int btn, int currentMap) {
|
||||
pspBtn = btn;
|
||||
last_kb_deviceid = 0;
|
||||
last_kb_key = 0;
|
||||
currentMap_ = currentMap;
|
||||
}
|
||||
void update(InputState &input);
|
||||
void render();
|
||||
void key(const KeyInput &key);
|
||||
|
||||
private:
|
||||
int pspBtn;
|
||||
int last_kb_deviceid;
|
||||
int last_kb_key;
|
||||
int currentMap_;
|
||||
};
|
||||
|
||||
struct FileSelectScreenOptions {
|
||||
|
@ -542,8 +542,7 @@ void NativeDeviceLost() {
|
||||
}
|
||||
|
||||
bool NativeIsAtTopLevel() {
|
||||
// TODO
|
||||
return false;
|
||||
return globalUIState == UISTATE_MENU;
|
||||
}
|
||||
|
||||
void NativeTouch(const TouchInput &touch) {
|
||||
@ -551,6 +550,16 @@ void NativeTouch(const TouchInput &touch) {
|
||||
screenManager->touch(touch);
|
||||
}
|
||||
|
||||
void NativeKey(const KeyInput &key) {
|
||||
if (screenManager)
|
||||
screenManager->key(key);
|
||||
}
|
||||
|
||||
void NativeAxis(const AxisInput &key) {
|
||||
if (screenManager)
|
||||
screenManager->axis(key);
|
||||
}
|
||||
|
||||
void NativeMessageReceived(const char *message, const char *value) {
|
||||
// We can only have one message queued.
|
||||
lock_guard lock(pendingMutex);
|
||||
|
@ -15,235 +15,7 @@
|
||||
// Official git repository and contact information can be found at
|
||||
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
|
||||
|
||||
#include "Common/KeyMap.h"
|
||||
#include "ControlMapping.h"
|
||||
#include "DinputDevice.h"
|
||||
#include "XinputDevice.h"
|
||||
|
||||
extern unsigned int key_pad_map[];
|
||||
extern unsigned short analog_ctrl_map[];
|
||||
extern unsigned int dinput_ctrl_map[];
|
||||
extern unsigned int xinput_ctrl_map[];
|
||||
|
||||
inline UINT* ControlMapping::GetDeviceButtonsMap(UINT curDevice)
|
||||
{
|
||||
switch (curDevice)
|
||||
{
|
||||
case CONTROLS_KEYBOARD_INDEX:
|
||||
return pButtonsMap;
|
||||
case CONTROLS_DIRECT_INPUT_INDEX:
|
||||
return pButtonsMap + buttonsCount;
|
||||
case CONTROLS_XINPUT_INDEX:
|
||||
return pButtonsMap + (buttonsCount * 2);
|
||||
case CONTROLS_KEYBOARD_ANALOG_INDEX:
|
||||
return pButtonsMap + (buttonsCount * 3);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ControlMapping * ControlMapping::CreateInstance(UINT nButtons)
|
||||
{
|
||||
if (nButtons != (key_pad_map_size / sizeof(key_pad_map[0]) / 2))
|
||||
return FALSE;
|
||||
if (nButtons != (dinput_ctrl_map_size / sizeof(dinput_ctrl_map[0]) / 2))
|
||||
return FALSE;
|
||||
if (nButtons != (xinput_ctrl_map_size / sizeof(xinput_ctrl_map[0]) / 2))
|
||||
return FALSE;
|
||||
if (4 != (analog_ctrl_map_size / sizeof(analog_ctrl_map[0]) / 2))
|
||||
return FALSE;
|
||||
auto inst = new ControlMapping(nButtons);
|
||||
if (!inst->pButtonsMap)
|
||||
return FALSE;
|
||||
return inst;
|
||||
}
|
||||
|
||||
ControlMapping::ControlMapping(UINT nButtons) :
|
||||
currentDevicePage(-1),
|
||||
currentButtonIndex(-1),
|
||||
pButtonsMap(0),
|
||||
buttonsCount(nButtons),
|
||||
dinput(0),
|
||||
xinput(0)
|
||||
{
|
||||
dinput = std::shared_ptr<DinputDevice>(new DinputDevice());
|
||||
xinput = std::shared_ptr<XinputDevice>(new XinputDevice());
|
||||
|
||||
pButtonsMap = new UINT[CONTROLS_DEVICE_NUM * nButtons];
|
||||
ZeroMemory(pButtonsMap, sizeof(UINT) * CONTROLS_DEVICE_NUM * nButtons);
|
||||
for (UINT i = 0; i < nButtons; i++) {
|
||||
*(GetDeviceButtonsMap(CONTROLS_KEYBOARD_INDEX) + i) = key_pad_map[i * 2];
|
||||
*(GetDeviceButtonsMap(CONTROLS_DIRECT_INPUT_INDEX) + i) = dinput_ctrl_map[i * 2];
|
||||
*(GetDeviceButtonsMap(CONTROLS_XINPUT_INDEX) + i) = xinput_ctrl_map[i * 2];
|
||||
}
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
*(GetDeviceButtonsMap(CONTROLS_KEYBOARD_ANALOG_INDEX) + i) = (UINT)analog_ctrl_map[i * 2];
|
||||
}
|
||||
}
|
||||
|
||||
ControlMapping::~ControlMapping()
|
||||
{
|
||||
if (pButtonsMap) {
|
||||
delete [] pButtonsMap;
|
||||
pButtonsMap = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void ControlMapping::UpdateState()
|
||||
{
|
||||
rawState.button = -1;
|
||||
switch(currentDevicePage)
|
||||
{
|
||||
case CONTROLS_KEYBOARD_INDEX:
|
||||
case CONTROLS_KEYBOARD_ANALOG_INDEX:
|
||||
{
|
||||
; // leave it to KeyboardProc.
|
||||
}
|
||||
break;
|
||||
case CONTROLS_DIRECT_INPUT_INDEX:
|
||||
{
|
||||
|
||||
dinput->UpdateRawStateSingle(rawState);
|
||||
UINT newButton = (rawState.button != rawState.prevButton && rawState.prevButton == -1)
|
||||
? rawState.button : -1;
|
||||
if (newButton != -1) {
|
||||
SetBindCode(newButton);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CONTROLS_XINPUT_INDEX:
|
||||
{
|
||||
xinput->UpdateRawStateSingle(rawState);
|
||||
UINT newButton = (rawState.button != rawState.prevButton && rawState.prevButton == -1)
|
||||
? rawState.button : -1;
|
||||
if (newButton != -1) {
|
||||
SetBindCode(newButton);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
rawState.prevButton = rawState.button;
|
||||
}
|
||||
|
||||
void ControlMapping::BindToDevices()
|
||||
{
|
||||
for (UINT i = 0; i < buttonsCount; i++) {
|
||||
key_pad_map[i * 2] = *(GetDeviceButtonsMap(CONTROLS_KEYBOARD_INDEX) + i);
|
||||
dinput_ctrl_map[i * 2] = *(GetDeviceButtonsMap(CONTROLS_DIRECT_INPUT_INDEX) + i);
|
||||
xinput_ctrl_map[i * 2] = *(GetDeviceButtonsMap(CONTROLS_XINPUT_INDEX) + i);
|
||||
}
|
||||
for (UINT i = 0; i < 4; i++) {
|
||||
analog_ctrl_map[i * 2] = (USHORT)*(GetDeviceButtonsMap(CONTROLS_KEYBOARD_ANALOG_INDEX) + i);
|
||||
}
|
||||
}
|
||||
|
||||
void ControlMapping::SetBindCode(UINT newCode)
|
||||
{
|
||||
SetBindCode(newCode, currentDevicePage, currentButtonIndex);
|
||||
}
|
||||
|
||||
void ControlMapping::SetBindCode(UINT newCode, UINT buttonIdx)
|
||||
{
|
||||
SetBindCode(newCode, currentDevicePage, buttonIdx);
|
||||
}
|
||||
|
||||
void ControlMapping::SetBindCode(UINT newCode, UINT deviceIdx, UINT buttonIdx)
|
||||
{
|
||||
if (deviceIdx < CONTROLS_DEVICE_NUM && buttonIdx < buttonsCount)
|
||||
*(GetDeviceButtonsMap(deviceIdx) + buttonIdx) = newCode;
|
||||
}
|
||||
|
||||
UINT ControlMapping::GetBindCode(UINT deviceIdx, UINT buttonIdx)
|
||||
{
|
||||
if (deviceIdx < CONTROLS_DEVICE_NUM && buttonIdx < buttonsCount)
|
||||
return *(GetDeviceButtonsMap(deviceIdx) + buttonIdx);
|
||||
return -1;
|
||||
}
|
||||
|
||||
UINT ControlMapping::GetBindCode(UINT buttonIdx)
|
||||
{
|
||||
return GetBindCode(currentDevicePage, buttonIdx);
|
||||
}
|
||||
|
||||
UINT ControlMapping::GetBindCode()
|
||||
{
|
||||
return GetBindCode(currentDevicePage, currentButtonIndex);
|
||||
}
|
||||
|
||||
void ControlMapping::SetDisableBind(UINT deviceIdx, UINT buttonIdx)
|
||||
{
|
||||
u32 disableCode = 0;
|
||||
if (deviceIdx == CONTROLS_DIRECT_INPUT_INDEX) {
|
||||
disableCode = 0xFFFFFFFF;
|
||||
}
|
||||
SetBindCode(disableCode, deviceIdx, buttonIdx);
|
||||
}
|
||||
|
||||
void ControlMapping::SetDisableBind(UINT buttonIdx)
|
||||
{
|
||||
SetDisableBind(currentDevicePage, buttonIdx);
|
||||
}
|
||||
|
||||
void ControlMapping::SetDisableBind()
|
||||
{
|
||||
SetDisableBind(currentDevicePage, currentButtonIndex);
|
||||
}
|
||||
|
||||
UINT ControlMapping::GetTargetDevice()
|
||||
{
|
||||
return currentDevicePage;
|
||||
}
|
||||
|
||||
void ControlMapping::SetTargetDevice(UINT deviceIdx)
|
||||
{
|
||||
rawState.prevButton = -1;
|
||||
currentDevicePage = deviceIdx;
|
||||
}
|
||||
|
||||
UINT ControlMapping::GetTargetButton()
|
||||
{
|
||||
return currentButtonIndex;
|
||||
}
|
||||
|
||||
void ControlMapping::SetTargetButton(UINT buttonIdx)
|
||||
{
|
||||
currentButtonIndex = buttonIdx;
|
||||
}
|
||||
|
||||
bool saveControlsToFile() {
|
||||
FILE *wfp = fopen("PPSSPPControls.dat", "wb");
|
||||
if (!wfp)
|
||||
return false;
|
||||
|
||||
fwrite(key_pad_map, 1, key_pad_map_size, wfp);
|
||||
fwrite(analog_ctrl_map, 1, analog_ctrl_map_size, wfp);
|
||||
fwrite(dinput_ctrl_map, 1, dinput_ctrl_map_size, wfp);
|
||||
fwrite(xinput_ctrl_map, 1, xinput_ctrl_map_size, wfp);
|
||||
fclose(wfp);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool loadControlsFromFile() {
|
||||
FILE *rfp = fopen("PPSSPPControls.dat", "rb");
|
||||
if (!rfp)
|
||||
return false;
|
||||
|
||||
fseek(rfp, 0, SEEK_END);
|
||||
fpos_t fsize = 0;
|
||||
fgetpos(rfp, &fsize);
|
||||
|
||||
if (fsize != (key_pad_map_size + analog_ctrl_map_size + dinput_ctrl_map_size + xinput_ctrl_map_size))
|
||||
{
|
||||
fclose(rfp);
|
||||
return false;
|
||||
}
|
||||
|
||||
fseek(rfp, 0, SEEK_SET);
|
||||
fread(key_pad_map, 1, key_pad_map_size, rfp);
|
||||
fread(analog_ctrl_map, 1, analog_ctrl_map_size, rfp);
|
||||
fread(dinput_ctrl_map, 1, dinput_ctrl_map_size, rfp);
|
||||
fread(xinput_ctrl_map, 1, xinput_ctrl_map_size, rfp);
|
||||
fclose(rfp);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -33,8 +33,8 @@ struct RawInputState
|
||||
#define POV_CODE_DOWN 0x0200
|
||||
#define POV_CODE_LEFT 0x0400
|
||||
#define POV_CODE_RIGHT 0x0800
|
||||
#define XBOX_CODE_LEFTTRIGER 0x00010000
|
||||
#define XBOX_CODE_RIGHTTRIGER 0x00020000
|
||||
#define XBOX_CODE_LEFTTRIGGER 0x00010000
|
||||
#define XBOX_CODE_RIGHTTRIGGER 0x00020000
|
||||
|
||||
#define CONTROLS_KEYBOARD_INDEX 0
|
||||
#define CONTROLS_DIRECT_INPUT_INDEX 1
|
||||
@ -42,51 +42,3 @@ struct RawInputState
|
||||
#define CONTROLS_KEYBOARD_ANALOG_INDEX 3
|
||||
#define CONTROLS_DEVICE_NUM 4
|
||||
|
||||
|
||||
extern bool saveControlsToFile();
|
||||
extern bool loadControlsFromFile();
|
||||
|
||||
extern const unsigned int xinput_ctrl_map_size;
|
||||
extern const unsigned int key_pad_map_size;
|
||||
extern const unsigned int analog_ctrl_map_size;
|
||||
extern const unsigned int dinput_ctrl_map_size;
|
||||
|
||||
struct RawInputState;
|
||||
class DinputDevice;
|
||||
class XinputDevice;
|
||||
|
||||
class ControlMapping
|
||||
{
|
||||
public:
|
||||
static ControlMapping * CreateInstance(UINT nButtons);
|
||||
virtual ~ControlMapping();
|
||||
void UpdateState();
|
||||
void BindToDevices();
|
||||
void SetTargetDevice(UINT deviceIdx);
|
||||
UINT GetTargetDevice();
|
||||
void SetTargetButton(UINT buttonIdx);
|
||||
UINT GetTargetButton();
|
||||
void SetBindCode(UINT newCode);
|
||||
void SetBindCode(UINT newCode, UINT buttonIdx);
|
||||
void SetBindCode(UINT newCode, UINT deviceIdx, UINT buttonIdx);
|
||||
UINT GetBindCode();
|
||||
UINT GetBindCode(UINT buttonIdx);
|
||||
UINT GetBindCode(UINT deviceIdx, UINT buttonIdx);
|
||||
void SetDisableBind();
|
||||
void SetDisableBind(UINT buttonIdx);
|
||||
void SetDisableBind(UINT deviceIdx, UINT buttonIdx);
|
||||
|
||||
private:
|
||||
ControlMapping(UINT nButtons);
|
||||
ControlMapping();
|
||||
inline UINT* GetDeviceButtonsMap(UINT curDevice);
|
||||
|
||||
private:
|
||||
std::shared_ptr<DinputDevice> dinput;
|
||||
std::shared_ptr<XinputDevice> xinput;
|
||||
UINT currentDevicePage;
|
||||
UINT currentButtonIndex;
|
||||
UINT buttonsCount;
|
||||
RawInputState rawState;
|
||||
UINT *pButtonsMap;
|
||||
};
|
||||
|
@ -5,11 +5,3 @@
|
||||
#include <list>
|
||||
#include <memory>
|
||||
|
||||
#define PUSH_BACK(Cls) do { list.push_back(std::shared_ptr<InputDevice>(new Cls())); } while (0)
|
||||
std::list<std::shared_ptr<InputDevice>> getInputDevices() {
|
||||
std::list<std::shared_ptr<InputDevice>> list;
|
||||
PUSH_BACK(XinputDevice);
|
||||
PUSH_BACK(DinputDevice);
|
||||
PUSH_BACK(KeyboardDevice);
|
||||
return list;
|
||||
}
|
||||
|
@ -14,5 +14,3 @@ public:
|
||||
virtual int UpdateState(InputState &input_state) = 0;
|
||||
virtual bool IsPad() = 0;
|
||||
};
|
||||
|
||||
std::list<std::shared_ptr<InputDevice>> getInputDevices();
|
||||
|
@ -1,4 +1,6 @@
|
||||
#include "base/NativeApp.h"
|
||||
#include "input/input_state.h"
|
||||
#include "input/keycodes.h"
|
||||
#include "util/const_map.h"
|
||||
#include "KeyMap.h"
|
||||
#include "ControlMapping.h"
|
||||
@ -26,6 +28,7 @@ unsigned int key_pad_map[] = {
|
||||
VK_LEFT, PAD_BUTTON_LEFT,
|
||||
VK_RIGHT, PAD_BUTTON_RIGHT,
|
||||
};
|
||||
|
||||
const unsigned int key_pad_map_size = sizeof(key_pad_map);
|
||||
|
||||
unsigned short analog_ctrl_map[] = {
|
||||
@ -123,7 +126,7 @@ const unsigned int analog_ctrl_map_size = sizeof(analog_ctrl_map);
|
||||
int KeyboardDevice::UpdateState(InputState &input_state) {
|
||||
if (MainWindow::GetHWND() != GetForegroundWindow()) return -1;
|
||||
bool alternate = GetAsyncKeyState(VK_SHIFT) != 0;
|
||||
KeyQueueBlank(input_state.key_queue);
|
||||
|
||||
static u32 alternator = 0;
|
||||
bool doAlternate = alternate && (alternator++ % 10) < 5;
|
||||
|
||||
@ -139,19 +142,37 @@ int KeyboardDevice::UpdateState(InputState &input_state) {
|
||||
|
||||
if (!doAlternate || key_pad_map[i + 1] > PAD_BUTTON_SELECT) {
|
||||
// TODO: remove once EmuScreen supports virtual keys
|
||||
switch (key_pad_map[i]) {
|
||||
case VK_ESCAPE:
|
||||
case VK_F3:
|
||||
case VK_PAUSE:
|
||||
case VK_BACK:
|
||||
switch (key_pad_map[i + 1]) {
|
||||
case PAD_BUTTON_MENU:
|
||||
case PAD_BUTTON_BACK:
|
||||
case PAD_BUTTON_RIGHT_THUMB:
|
||||
input_state.pad_buttons |= key_pad_map[i + 1];
|
||||
break;
|
||||
}
|
||||
|
||||
KeyQueueAttemptTranslatedAdd(input_state.key_queue, windowsTransTable, key_pad_map[i]);
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < downKeys.size(); i++) {
|
||||
KeyInput key;
|
||||
key.deviceId = DEVICE_ID_KEYBOARD;
|
||||
key.flags = KEY_DOWN;
|
||||
key.keyCode = windowsTransTable[downKeys[i]];
|
||||
if (key.keyCode)
|
||||
NativeKey(key);
|
||||
}
|
||||
downKeys.clear();
|
||||
|
||||
for (size_t i = 0; i < upKeys.size(); i++) {
|
||||
KeyInput key;
|
||||
key.deviceId = DEVICE_ID_KEYBOARD;
|
||||
key.flags = KEY_UP;
|
||||
key.keyCode = windowsTransTable[upKeys[i]];
|
||||
if (key.keyCode)
|
||||
NativeKey(key);
|
||||
}
|
||||
upKeys.clear();
|
||||
|
||||
// TODO: Better axis mapping
|
||||
float analogX = 0;
|
||||
float analogY = 0;
|
||||
for (int i = 0; i < sizeof(analog_ctrl_map)/sizeof(analog_ctrl_map[0]); i += 2) {
|
||||
@ -175,9 +196,14 @@ int KeyboardDevice::UpdateState(InputState &input_state) {
|
||||
}
|
||||
}
|
||||
|
||||
// keyboard device
|
||||
input_state.pad_lstick_x += analogX;
|
||||
input_state.pad_lstick_y += analogY;
|
||||
AxisInput axis;
|
||||
axis.deviceId = DEVICE_ID_KEYBOARD;
|
||||
axis.axisId = JOYSTICK_AXIS_X;
|
||||
axis.value = analogX;
|
||||
NativeAxis(axis);
|
||||
axis.axisId = JOYSTICK_AXIS_Y;
|
||||
axis.value = analogY;
|
||||
NativeAxis(axis);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include "base/mutex.h"
|
||||
#include "InputDevice.h"
|
||||
|
||||
class KeyboardDevice : public InputDevice {
|
||||
public:
|
||||
virtual int UpdateState(InputState &input_state);
|
||||
virtual bool IsPad() { return false; }
|
||||
|
||||
virtual void KeyDown(int keycode) {
|
||||
downKeys.push_back(keycode);
|
||||
}
|
||||
virtual void KeyUp(int keycode) {
|
||||
upKeys.push_back(keycode);
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<int> downKeys;
|
||||
std::vector<int> upKeys;
|
||||
};
|
||||
|
@ -28,6 +28,11 @@
|
||||
#include "Windows/Debugger/DebuggerShared.h"
|
||||
#include "Windows/Debugger/Debugger_Disasm.h"
|
||||
#include "Windows/Debugger/Debugger_MemoryDlg.h"
|
||||
|
||||
#include "Windows/DinputDevice.h"
|
||||
#include "Windows/XinputDevice.h"
|
||||
#include "Windows/KeyboardDevice.h"
|
||||
|
||||
#include "Core/Debugger/SymbolMap.h"
|
||||
|
||||
#include "main.h"
|
||||
@ -51,6 +56,21 @@ static BOOL PostDialogMessage(Dialog *dialog, UINT message, WPARAM wParam = 0, L
|
||||
return PostMessage(dialog->GetDlgHandle(), message, wParam, lParam);
|
||||
}
|
||||
|
||||
WindowsHost::WindowsHost(HWND mainWindow, HWND displayWindow)
|
||||
{
|
||||
mainWindow_ = mainWindow;
|
||||
displayWindow_ = displayWindow;
|
||||
|
||||
#define PUSH_BACK(Cls) do { list.push_back(std::shared_ptr<InputDevice>(new Cls())); } while (0)
|
||||
|
||||
input.push_back(std::shared_ptr<InputDevice>(new XinputDevice()));
|
||||
input.push_back(std::shared_ptr<InputDevice>(new DinputDevice()));
|
||||
keyboard = std::shared_ptr<KeyboardDevice>(new KeyboardDevice());
|
||||
input.push_back(keyboard);
|
||||
|
||||
SetConsolePosition();
|
||||
}
|
||||
|
||||
bool WindowsHost::InitGL(std::string *error_message)
|
||||
{
|
||||
return GL_Init(MainWindow::GetDisplayHWND(), error_message);
|
||||
|
@ -17,19 +17,15 @@
|
||||
|
||||
#include "../Core/Host.h"
|
||||
#include "InputDevice.h"
|
||||
#include "KeyboardDevice.h"
|
||||
#include <list>
|
||||
#include <memory>
|
||||
|
||||
class WindowsHost : public Host
|
||||
{
|
||||
public:
|
||||
WindowsHost(HWND mainWindow, HWND displayWindow)
|
||||
{
|
||||
mainWindow_ = mainWindow;
|
||||
displayWindow_ = displayWindow;
|
||||
input = getInputDevices();
|
||||
SetConsolePosition();
|
||||
}
|
||||
WindowsHost(HWND mainWindow, HWND displayWindow);
|
||||
|
||||
~WindowsHost()
|
||||
{
|
||||
UpdateConsolePosition();
|
||||
@ -56,11 +52,14 @@ public:
|
||||
void SaveSymbolMap();
|
||||
void SetWindowTitle(const char *message);
|
||||
|
||||
std::shared_ptr<KeyboardDevice> keyboard;
|
||||
|
||||
private:
|
||||
void SetConsolePosition();
|
||||
void UpdateConsolePosition();
|
||||
|
||||
HWND displayWindow_;
|
||||
HWND mainWindow_;
|
||||
|
||||
std::list<std::shared_ptr<InputDevice>> input;
|
||||
};
|
@ -26,6 +26,7 @@
|
||||
#include "resource.h"
|
||||
|
||||
#include "Windows/WndMainWindow.h"
|
||||
#include "Windows/WindowsHost.h"
|
||||
#include "Common/LogManager.h"
|
||||
#include "Common/ConsoleListener.h"
|
||||
#include "Windows/W32Util/DialogManager.h"
|
||||
@ -80,7 +81,6 @@ namespace MainWindow
|
||||
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
|
||||
LRESULT CALLBACK DisplayProc(HWND, UINT, WPARAM, LPARAM);
|
||||
LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM);
|
||||
LRESULT CALLBACK Controls(HWND, UINT, WPARAM, LPARAM);
|
||||
|
||||
HWND GetHWND()
|
||||
{
|
||||
@ -446,7 +446,6 @@ namespace MainWindow
|
||||
switch (message)
|
||||
{
|
||||
case WM_CREATE:
|
||||
loadControlsFromFile();
|
||||
break;
|
||||
|
||||
case WM_MOVE:
|
||||
@ -768,10 +767,9 @@ namespace MainWindow
|
||||
ResizeDisplay(true);
|
||||
break;
|
||||
case ID_OPTIONS_CONTROLS:
|
||||
DialogManager::EnableAll(FALSE);
|
||||
DialogBox(hInst, (LPCTSTR)IDD_CONTROLS, hWnd, (DLGPROC)Controls);
|
||||
DialogManager::EnableAll(TRUE);
|
||||
MessageBox(hWnd, "Control mapping has been moved to the in-window Settings menu.\n", "Sorry", 0);
|
||||
break;
|
||||
|
||||
case ID_EMULATION_SOUND:
|
||||
g_Config.bEnableSound = !g_Config.bEnableSound;
|
||||
break;
|
||||
@ -799,7 +797,23 @@ namespace MainWindow
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_KEYDOWN:
|
||||
{
|
||||
// Ugly
|
||||
WindowsHost *whost = static_cast<WindowsHost *>(host);
|
||||
int vkey = wParam;
|
||||
whost->keyboard->KeyDown(vkey);
|
||||
}
|
||||
return 0;
|
||||
|
||||
case WM_KEYUP:
|
||||
{
|
||||
// Ugly
|
||||
WindowsHost *whost = static_cast<WindowsHost *>(host);
|
||||
int vkey = wParam;
|
||||
whost->keyboard->KeyUp(vkey);
|
||||
}
|
||||
return 0;
|
||||
|
||||
case WM_DROPFILES:
|
||||
@ -1002,7 +1016,6 @@ namespace MainWindow
|
||||
EnableMenuItem(menu,ID_EMULATION_STOP, !menuEnable);
|
||||
}
|
||||
|
||||
|
||||
// Message handler for about box.
|
||||
LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
@ -1029,540 +1042,6 @@ namespace MainWindow
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#define CONTROLS_IDC_EDIT_BEGIN IDC_EDIT_KEY_MENU
|
||||
#define CONTROLS_IDC_EDIT_END IDC_EDIT_KEY_ANALOG_RIGHT
|
||||
#define CONTROLS_BUTTONS_COUNT (IDC_EDIT_KEYRIGHT - CONTROLS_IDC_EDIT_BEGIN + 1)
|
||||
#define CONTROLS_BUTTONNAME_MAX 16
|
||||
// for controls dialog device polling and bind update.
|
||||
#define TIMER_CONTROLS_BINDUPDATE 1
|
||||
#define BINDUPDATE_INTERVAL_MS 50
|
||||
|
||||
static const char *controllist[] = {
|
||||
"Menu", // Open PauseScreen
|
||||
"Back", // Toggle PauseScreen & Back Setting Page.
|
||||
"Triangle",
|
||||
"Rectangle",
|
||||
"Cross",
|
||||
"Circle",
|
||||
"Select",
|
||||
"Start",
|
||||
"Left Trigger",
|
||||
"Right Trigger",
|
||||
"Turbo", // LBUMPER (Turbo)
|
||||
"Reserved", // RBUMPER (Open PauseScreen)
|
||||
"Up",
|
||||
"Down",
|
||||
"Left",
|
||||
"Right",
|
||||
"LY+",
|
||||
"LY-",
|
||||
"LX-",
|
||||
"LX+",
|
||||
};
|
||||
|
||||
struct ControlsDlgState {
|
||||
HHOOK pKeydownHook;
|
||||
HBITMAP hbmPspImage;
|
||||
HWND hCtrlTab;
|
||||
UINT_PTR timerId;
|
||||
WNDPROC orgPSPImageProc;
|
||||
WNDPROC orgEditProc;
|
||||
ControlMapping *pCtrlMap;
|
||||
HWND hStaticPspImage;
|
||||
};
|
||||
static ControlsDlgState *pCtrlDlgState;
|
||||
|
||||
RECT getRedrawRect(HWND hWnd) {
|
||||
RECT rc;
|
||||
HWND hDlg = GetParent(hWnd);
|
||||
GetWindowRect(hWnd, &rc);
|
||||
POINT pt = {0, 0};
|
||||
ScreenToClient(hDlg, &pt);
|
||||
rc.left += pt.x;
|
||||
rc.right += pt.x;
|
||||
rc.top += pt.y;
|
||||
rc.bottom += pt.y;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
if (pCtrlDlgState->pCtrlMap->GetTargetDevice() == CONTROLS_KEYBOARD_INDEX) {
|
||||
HWND hEdit = GetFocus();
|
||||
UINT nCtrlID = GetDlgCtrlID(hEdit);
|
||||
if (nCtrlID < CONTROLS_IDC_EDIT_BEGIN || nCtrlID > CONTROLS_IDC_EDIT_END) {
|
||||
return CallNextHookEx(pCtrlDlgState->pKeydownHook, nCode, wParam, lParam);
|
||||
}
|
||||
if (!(lParam&(1<<31))) {
|
||||
// key down
|
||||
HWND hDlg = GetParent(hEdit);
|
||||
const char *str = getVirtualKeyName(wParam);
|
||||
if (str) {
|
||||
if (nCtrlID >= IDC_EDIT_KEY_ANALOG_UP) {
|
||||
pCtrlDlgState->pCtrlMap->SetBindCode(wParam, CONTROLS_KEYBOARD_ANALOG_INDEX,
|
||||
nCtrlID - IDC_EDIT_KEY_ANALOG_UP);
|
||||
} else {
|
||||
pCtrlDlgState->pCtrlMap->SetBindCode(wParam);
|
||||
}
|
||||
SetWindowTextA(hEdit, str);
|
||||
RECT rc = getRedrawRect(hEdit);
|
||||
InvalidateRect(hDlg, &rc, false);
|
||||
}
|
||||
else
|
||||
MessageBoxA(hDlg, "Not supported!", "controller", MB_OK);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
HBITMAP LoadImageFromResource(HINSTANCE hInstance,LPCTSTR pszResourceName, LPCTSTR lpType)
|
||||
{
|
||||
HRSRC hrsrc = FindResource(hInstance, pszResourceName, lpType);
|
||||
if (!hrsrc)
|
||||
return FALSE;
|
||||
DWORD dwlen = SizeofResource(hInstance, hrsrc);
|
||||
BYTE *lpRsrc = (BYTE*)LoadResource(hInstance, hrsrc);
|
||||
if (!lpRsrc)
|
||||
return FALSE;
|
||||
int width, height;
|
||||
unsigned char *image_data = 0;
|
||||
bool bResult = pngLoadPtr(lpRsrc, dwlen, &width, &height, &image_data, false) != 0;
|
||||
FreeResource(lpRsrc);
|
||||
if (!bResult)
|
||||
return 0;
|
||||
HBITMAP hbm = CreateBitmap(width, height, 1, 32, image_data);
|
||||
free(image_data);
|
||||
return hbm;
|
||||
}
|
||||
void BitBlt(HBITMAP hbm, HDC dstDC, int dstX, int dstY, int width, int height, int srcX, int srcY)
|
||||
{
|
||||
HDC hCompDC = CreateCompatibleDC(dstDC);
|
||||
HBITMAP oldbm = (HBITMAP)SelectObject(hCompDC, hbm);
|
||||
BitBlt(dstDC, dstX, dstY, width, height, hCompDC, srcX, srcY, SRCCOPY);
|
||||
SelectObject(hCompDC, oldbm);
|
||||
DeleteObject(hCompDC);
|
||||
}
|
||||
|
||||
inline void SetWindowTextForButton(HWND hEdit, u32 buttonCode, const char *pszButtonName)
|
||||
{
|
||||
if (buttonCode == 0) {
|
||||
SetWindowTextA(hEdit, "Disable");
|
||||
} else {
|
||||
SetWindowTextA(hEdit, pszButtonName);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw background image of Controls Dialog (pspmode.png) by use static control.
|
||||
LRESULT CALLBACK PSPImageProc(HWND hStatic, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
|
||||
switch(message) {
|
||||
case WM_PAINT:
|
||||
{
|
||||
PAINTSTRUCT pst;
|
||||
HDC hdc = BeginPaint(hStatic, &pst);
|
||||
|
||||
BITMAP bm;
|
||||
GetObject(pCtrlDlgState->hbmPspImage, sizeof(BITMAP), &bm);
|
||||
BitBlt(pCtrlDlgState->hbmPspImage, hdc, 0, 0, bm.bmWidth, bm.bmHeight, 0 , 0);
|
||||
EndPaint(hStatic, &pst);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return CallWindowProc(pCtrlDlgState->orgPSPImageProc, hStatic, message, wParam, lParam);
|
||||
}
|
||||
|
||||
LRESULT CALLBACK ButtonsEditProc(HWND hEdit, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
switch (message) {
|
||||
case WM_RBUTTONUP:
|
||||
{
|
||||
UINT nCtrlID = GetDlgCtrlID(hEdit);
|
||||
int deviceIdx = TabCtrl_GetCurSel(pCtrlDlgState->hCtrlTab);
|
||||
if (deviceIdx != CONTROLS_KEYBOARD_INDEX && nCtrlID >= IDC_EDIT_KEY_ANALOG_UP)
|
||||
return TRUE;
|
||||
|
||||
HMENU hSubMenu = GetSubMenu(g_hPopupMenus, 4);
|
||||
POINT pos;
|
||||
pos.x = LOWORD(lParam);
|
||||
pos.y = HIWORD(lParam);
|
||||
ClientToScreen(hEdit, &pos);
|
||||
switch(TrackPopupMenuEx(GetSubMenu(g_hPopupMenus, 4), TPM_RETURNCMD, pos.x, pos.y, hEdit, NULL))
|
||||
{
|
||||
case ID_CONTROLS_KEY_DISABLE:
|
||||
{
|
||||
if (nCtrlID < IDC_EDIT_KEY_ANALOG_UP) {
|
||||
pCtrlDlgState->pCtrlMap->SetDisableBind(deviceIdx, nCtrlID - CONTROLS_IDC_EDIT_BEGIN);
|
||||
}
|
||||
else if (deviceIdx == CONTROLS_KEYBOARD_INDEX) {
|
||||
pCtrlDlgState->pCtrlMap->SetDisableBind(
|
||||
CONTROLS_KEYBOARD_ANALOG_INDEX, nCtrlID - IDC_EDIT_KEY_ANALOG_UP);
|
||||
}
|
||||
SetWindowTextA(hEdit, "Disable");
|
||||
RECT rc = getRedrawRect(hEdit);
|
||||
HWND hDlg = GetParent(hEdit);
|
||||
InvalidateRect(hDlg, &rc, false);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
default :
|
||||
break;
|
||||
}
|
||||
return CallWindowProc(pCtrlDlgState->orgEditProc, hEdit, message, wParam, lParam);
|
||||
}
|
||||
|
||||
// Message handler for control box.
|
||||
LRESULT CALLBACK Controls(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
switch (message)
|
||||
{
|
||||
case WM_INITDIALOG:
|
||||
W32Util::CenterWindow(hDlg);
|
||||
{
|
||||
// IDC_EDIT_xxx is need continuous value to IDC_EDIT_KEY_ANALOG_RIGHT from IDC_EDIT_KEY_MENU.
|
||||
// it is total 16.
|
||||
// it is need the same order as the dinput_ctrl_map(and xinput/keyboard).
|
||||
if (CONTROLS_BUTTONS_COUNT != 16) {
|
||||
char mes[100];
|
||||
snprintf(mes, 100, "CONTROLS_BUTTONS_COUNT(%d) is need 16.", CONTROLS_BUTTONS_COUNT);
|
||||
MessageBoxA(hDlg, mes, "Controls dialog init error.", MB_OK);
|
||||
}
|
||||
pCtrlDlgState = new ControlsDlgState();
|
||||
ZeroMemory(pCtrlDlgState, sizeof(ControlsDlgState));
|
||||
pCtrlDlgState->pCtrlMap = ControlMapping::CreateInstance(CONTROLS_BUTTONS_COUNT);
|
||||
if (!pCtrlDlgState->pCtrlMap) {
|
||||
MessageBoxA(hDlg, "Cannot Created ControlMapping instance.", "Controls dialog init error.", MB_OK);
|
||||
}
|
||||
pCtrlDlgState->pCtrlMap->SetTargetDevice(CONTROLS_KEYBOARD_INDEX);
|
||||
|
||||
pCtrlDlgState->hCtrlTab = GetDlgItem(hDlg, IDC_TAB_INPUT_DEVICE);
|
||||
TCITEM tcItem;
|
||||
ZeroMemory(&tcItem, sizeof(tcItem));
|
||||
tcItem.mask = TCIF_TEXT;
|
||||
tcItem.dwState = 0;
|
||||
tcItem.pszText = "Keyboard";
|
||||
tcItem.cchTextMax = (int)strlen(tcItem.pszText)+1;
|
||||
tcItem.iImage = 0;
|
||||
TabCtrl_InsertItem(pCtrlDlgState->hCtrlTab, TabCtrl_GetItemCount(pCtrlDlgState->hCtrlTab),&tcItem);
|
||||
tcItem.pszText = "DirectInput";
|
||||
tcItem.cchTextMax = (int)strlen(tcItem.pszText)+1;
|
||||
TabCtrl_InsertItem(pCtrlDlgState->hCtrlTab, TabCtrl_GetItemCount(pCtrlDlgState->hCtrlTab),&tcItem);
|
||||
tcItem.pszText = "XInput";
|
||||
tcItem.cchTextMax = (int)strlen(tcItem.pszText)+1;
|
||||
TabCtrl_InsertItem(pCtrlDlgState->hCtrlTab, TabCtrl_GetItemCount(pCtrlDlgState->hCtrlTab),&tcItem);
|
||||
int tp_w = 0, tp_h = 0;
|
||||
// TODO: connect to keyboard device instead
|
||||
{
|
||||
|
||||
HBITMAP hResBM = LoadImageFromResource(hInst, MAKEINTRESOURCE(IDB_IMAGE_PSP), "IMAGE");
|
||||
pCtrlDlgState->hStaticPspImage = GetDlgItem(hDlg,IDC_STATIC_IMAGE_PSP);
|
||||
RECT clientRect, tabPageRect, imgRect;
|
||||
|
||||
GetClientRect(hDlg, &clientRect);
|
||||
memcpy(&tabPageRect, &clientRect, sizeof(RECT));
|
||||
TabCtrl_AdjustRect(pCtrlDlgState->hCtrlTab, FALSE, &tabPageRect);
|
||||
tp_w = tabPageRect.right - tabPageRect.left;
|
||||
tp_h = tabPageRect.bottom - tabPageRect.top;
|
||||
MoveWindow(pCtrlDlgState->hStaticPspImage, tabPageRect.left, tabPageRect.top, tp_w, tp_h, FALSE);
|
||||
|
||||
HDC hDC = GetDC(pCtrlDlgState->hStaticPspImage);
|
||||
HBITMAP hMemBM = CreateCompatibleBitmap(hDC, tp_w, tp_h);
|
||||
HDC hResDC = CreateCompatibleDC(hDC);
|
||||
HDC hMemDC = CreateCompatibleDC(hDC);
|
||||
SelectObject(hResDC, hResBM);
|
||||
SelectObject(hMemDC, hMemBM);
|
||||
|
||||
BITMAP bm;
|
||||
GetObject(hResBM, sizeof(BITMAP), &bm);
|
||||
SetStretchBltMode(hMemDC, HALFTONE);
|
||||
float scaleX = (float)bm.bmWidth / clientRect.right;
|
||||
float scaleY = (float)bm.bmHeight / clientRect.bottom;
|
||||
imgRect.left = (int)(tabPageRect.left * scaleX);
|
||||
imgRect.top = (int)(tabPageRect.top * scaleY);
|
||||
imgRect.right= (int)(bm.bmWidth - ((clientRect.right - tabPageRect.right) * scaleX));
|
||||
imgRect.bottom = (int)(bm.bmHeight - ((clientRect.bottom - tabPageRect.bottom) * scaleY));
|
||||
StretchBlt(hMemDC, 0, 0, tp_w, tp_h, hResDC, imgRect.left, imgRect.top,
|
||||
imgRect.right - imgRect.left, imgRect.bottom - imgRect.top, SRCCOPY);
|
||||
if (pCtrlDlgState->hbmPspImage)
|
||||
DeleteObject(pCtrlDlgState->hbmPspImage);
|
||||
pCtrlDlgState->hbmPspImage = hMemBM;
|
||||
|
||||
DeleteDC(hMemDC);
|
||||
DeleteDC(hResDC);
|
||||
ReleaseDC(pCtrlDlgState->hStaticPspImage, hDC);
|
||||
DeleteObject(hResBM);
|
||||
}
|
||||
|
||||
pCtrlDlgState->orgEditProc = (WNDPROC)GetWindowLongPtr(
|
||||
GetDlgItem(hDlg, CONTROLS_IDC_EDIT_BEGIN), GWLP_WNDPROC);
|
||||
for (int i = 0; i <= CONTROLS_IDC_EDIT_END - CONTROLS_IDC_EDIT_BEGIN; i++) {
|
||||
HWND hEdit = GetDlgItem(hDlg, CONTROLS_IDC_EDIT_BEGIN + i);
|
||||
if (i < CONTROLS_BUTTONS_COUNT) {
|
||||
u32 keyCode = pCtrlDlgState->pCtrlMap->GetBindCode(CONTROLS_KEYBOARD_INDEX, i);
|
||||
SetWindowTextForButton(hEdit, keyCode, getVirtualKeyName(keyCode));
|
||||
} else {
|
||||
u32 analogCode = pCtrlDlgState->pCtrlMap->GetBindCode(
|
||||
CONTROLS_KEYBOARD_ANALOG_INDEX, i - CONTROLS_BUTTONS_COUNT);
|
||||
SetWindowTextForButton(hEdit, analogCode, getVirtualKeyName(analogCode));
|
||||
}
|
||||
if (pCtrlDlgState->orgEditProc != (WNDPROC)GetWindowLongPtr(hEdit, GWLP_WNDPROC)) {
|
||||
MessageBoxA(hDlg,
|
||||
"Can not hook to the inherited Edit control. need wndproc of original edit control.",
|
||||
"Controls dialog init error.", MB_OK);
|
||||
break;
|
||||
}
|
||||
SetWindowLongPtr(hEdit, GWLP_WNDPROC, (LONG_PTR)ButtonsEditProc);
|
||||
}
|
||||
|
||||
ComboBox_AddString(GetDlgItem(hDlg, IDC_FORCE_INPUT_DEVICE), "None");
|
||||
ComboBox_AddString(GetDlgItem(hDlg, IDC_FORCE_INPUT_DEVICE), "XInput");
|
||||
ComboBox_AddString(GetDlgItem(hDlg, IDC_FORCE_INPUT_DEVICE), "DirectInput");
|
||||
if ((g_Config.iForceInputDevice < 0) || (g_Config.iForceInputDevice > 1))
|
||||
{
|
||||
ComboBox_SetCurSel(GetDlgItem(hDlg, IDC_FORCE_INPUT_DEVICE), 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
ComboBox_SetCurSel(GetDlgItem(hDlg, IDC_FORCE_INPUT_DEVICE), (g_Config.iForceInputDevice + 1));
|
||||
}
|
||||
pCtrlDlgState->orgPSPImageProc = (WNDPROC)GetWindowLongPtr(pCtrlDlgState->hStaticPspImage, GWLP_WNDPROC);
|
||||
SetWindowLongPtr(pCtrlDlgState->hStaticPspImage, GWLP_WNDPROC, (LONG_PTR)PSPImageProc);
|
||||
DWORD dwThreadID = GetWindowThreadProcessId(hDlg, NULL);
|
||||
pCtrlDlgState->pKeydownHook = SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, NULL, dwThreadID);
|
||||
|
||||
pCtrlDlgState->timerId = SetTimer(hDlg, TIMER_CONTROLS_BINDUPDATE, BINDUPDATE_INTERVAL_MS, 0);
|
||||
}
|
||||
return TRUE;
|
||||
case WM_TIMER:
|
||||
{
|
||||
if (wParam == TIMER_CONTROLS_BINDUPDATE &&
|
||||
pCtrlDlgState->pCtrlMap->GetTargetDevice() != CONTROLS_KEYBOARD_INDEX) {
|
||||
HWND hEdit = GetFocus();
|
||||
UINT nCtrlID = GetDlgCtrlID(hEdit);
|
||||
if (nCtrlID < CONTROLS_IDC_EDIT_BEGIN || nCtrlID > IDC_EDIT_KEYRIGHT) {
|
||||
break;
|
||||
}
|
||||
// device polling and update.
|
||||
int prevButton = pCtrlDlgState->pCtrlMap->GetBindCode();
|
||||
pCtrlDlgState->pCtrlMap->UpdateState();
|
||||
char str[CONTROLS_BUTTONNAME_MAX];
|
||||
ZeroMemory(str, CONTROLS_BUTTONNAME_MAX * sizeof(char));
|
||||
int buttonCode = pCtrlDlgState->pCtrlMap->GetBindCode();
|
||||
if (buttonCode == -1 || prevButton == buttonCode)
|
||||
break;
|
||||
|
||||
switch(pCtrlDlgState->pCtrlMap->GetTargetDevice())
|
||||
{
|
||||
case CONTROLS_KEYBOARD_INDEX:
|
||||
{
|
||||
; // leave it to KeyboardProc.
|
||||
}
|
||||
break;
|
||||
case CONTROLS_DIRECT_INPUT_INDEX:
|
||||
{
|
||||
if (buttonCode > 0xFF) {
|
||||
int n = 1;
|
||||
for (int i = buttonCode >> 8; i > 1; i >>= 1) {
|
||||
n++;
|
||||
}
|
||||
snprintf(str, CONTROLS_BUTTONNAME_MAX, "%s",
|
||||
controllist[(IDC_EDIT_KEYUP - CONTROLS_IDC_EDIT_BEGIN - 1) + n]);
|
||||
} else {
|
||||
snprintf(str, CONTROLS_BUTTONNAME_MAX, "%d", buttonCode + 1);
|
||||
}
|
||||
SetWindowTextA(hEdit, str);
|
||||
RECT rc = getRedrawRect(hEdit);
|
||||
InvalidateRect(hDlg, &rc, FALSE);
|
||||
}
|
||||
break;
|
||||
case CONTROLS_XINPUT_INDEX:
|
||||
{
|
||||
SetWindowTextA(hEdit, getXinputButtonName(buttonCode));
|
||||
RECT rc = getRedrawRect(hEdit);
|
||||
InvalidateRect(hDlg, &rc, FALSE);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case WM_NOTIFY:
|
||||
{
|
||||
switch (((NMHDR *)lParam)->code)
|
||||
{
|
||||
case TCN_SELCHANGE:
|
||||
{
|
||||
int cursel = TabCtrl_GetCurSel(pCtrlDlgState->hCtrlTab);
|
||||
pCtrlDlgState->pCtrlMap->SetTargetDevice(cursel);
|
||||
switch (cursel)
|
||||
{
|
||||
case CONTROLS_KEYBOARD_INDEX:
|
||||
{
|
||||
for (u32 i = 0; i <= IDC_EDIT_KEYRIGHT - CONTROLS_IDC_EDIT_BEGIN; i++) {
|
||||
HWND hEdit = GetDlgItem(hDlg, CONTROLS_IDC_EDIT_BEGIN + i);
|
||||
u32 keyCode = pCtrlDlgState->pCtrlMap->GetBindCode(i);
|
||||
SetWindowTextForButton(hEdit, keyCode, getVirtualKeyName(keyCode));
|
||||
}
|
||||
for (u32 i = 0; i <= CONTROLS_IDC_EDIT_END - IDC_EDIT_KEY_ANALOG_UP; i++) {
|
||||
HWND hEdit = GetDlgItem(hDlg, IDC_EDIT_KEY_ANALOG_UP + i);
|
||||
Edit_SetReadOnly(hEdit, FALSE);
|
||||
u32 analogCode = pCtrlDlgState->pCtrlMap->GetBindCode(
|
||||
CONTROLS_KEYBOARD_ANALOG_INDEX, i);
|
||||
SetWindowTextForButton(hEdit, analogCode, getVirtualKeyName(analogCode));
|
||||
}
|
||||
InvalidateRect(hDlg, 0, 0);
|
||||
}
|
||||
break;
|
||||
case CONTROLS_DIRECT_INPUT_INDEX:
|
||||
{
|
||||
|
||||
for (u32 i = 0; i <= CONTROLS_IDC_EDIT_END - CONTROLS_IDC_EDIT_BEGIN; i++) {
|
||||
HWND hEdit = GetDlgItem(hDlg, CONTROLS_IDC_EDIT_BEGIN + i);
|
||||
int buttonCode = (int)pCtrlDlgState->pCtrlMap->GetBindCode(i);
|
||||
char str[16];
|
||||
if (i >= IDC_EDIT_KEYUP - CONTROLS_IDC_EDIT_BEGIN) {
|
||||
if (i >= IDC_EDIT_KEY_ANALOG_UP - CONTROLS_IDC_EDIT_BEGIN) {
|
||||
Edit_SetReadOnly(hEdit, TRUE);
|
||||
SetWindowTextA(hEdit, controllist[i]);
|
||||
} else {
|
||||
int n = 1;
|
||||
if (buttonCode != -1) {
|
||||
for (int j = buttonCode >> 8; j > 1; j >>= 1) {
|
||||
n++;
|
||||
}
|
||||
snprintf(str, CONTROLS_BUTTONNAME_MAX, "%s",
|
||||
controllist[(IDC_EDIT_KEYUP - CONTROLS_IDC_EDIT_BEGIN - 1) + n]);
|
||||
}
|
||||
SetWindowTextForButton(hEdit, buttonCode + 1, str);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
snprintf(str, CONTROLS_BUTTONNAME_MAX, "%d", pCtrlDlgState->pCtrlMap->GetBindCode(i) + 1);
|
||||
SetWindowTextForButton(hEdit, buttonCode + 1, str);
|
||||
}
|
||||
InvalidateRect(hDlg, 0, 0);
|
||||
}
|
||||
break;
|
||||
case CONTROLS_XINPUT_INDEX:
|
||||
{
|
||||
for (u32 i = 0; i <= CONTROLS_IDC_EDIT_END - CONTROLS_IDC_EDIT_BEGIN; i++) {
|
||||
HWND hEdit = GetDlgItem(hDlg, CONTROLS_IDC_EDIT_BEGIN + i);
|
||||
if (i >= IDC_EDIT_KEY_ANALOG_UP - CONTROLS_IDC_EDIT_BEGIN) {
|
||||
Edit_SetReadOnly(hEdit, TRUE);
|
||||
SetWindowTextA(hEdit, controllist[i]);
|
||||
continue;
|
||||
}
|
||||
u32 button = pCtrlDlgState->pCtrlMap->GetBindCode(i);
|
||||
SetWindowTextForButton(hEdit, button, getXinputButtonName(button));
|
||||
}
|
||||
InvalidateRect(hDlg, 0, 0);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
} // pCtrlDlgState->curDevice
|
||||
} // TCN_SELCHANGING:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
} // ((NMHDR *)lParam)->code
|
||||
} // WM_NOTIFY:
|
||||
break;
|
||||
case WM_PAINT:
|
||||
{
|
||||
return DefWindowProc(hDlg, message, wParam, lParam);
|
||||
}
|
||||
case WM_CTLCOLORSTATIC:
|
||||
{
|
||||
HDC hdc=(HDC)wParam;
|
||||
HWND hCtrl = (HWND)lParam;
|
||||
SetBkMode(hdc, TRANSPARENT);
|
||||
int ctrlId = GetDlgCtrlID(hCtrl);
|
||||
if (ctrlId >= IDC_EDIT_KEY_ANALOG_UP && ctrlId <= IDC_EDIT_KEY_ANALOG_RIGHT) {
|
||||
SetTextColor(hdc, RGB(128,128,128));
|
||||
RECT rc = getRedrawRect(hCtrl);
|
||||
TabCtrl_AdjustRect(pCtrlDlgState->hCtrlTab, TRUE, &rc);
|
||||
RECT clientrc;
|
||||
GetClientRect(hCtrl, &clientrc);
|
||||
TabCtrl_AdjustRect(pCtrlDlgState->hCtrlTab, TRUE, &clientrc);
|
||||
BitBlt(pCtrlDlgState->hbmPspImage, hdc, 0, 0, rc.right - rc.left, rc.bottom - rc.top, rc.left, rc.top);
|
||||
char str[11];
|
||||
GetWindowTextA(hCtrl, str, 10);
|
||||
DrawTextA(hdc, str, (int)strlen(str), &clientrc, DT_CENTER|DT_SINGLELINE);
|
||||
}
|
||||
return (LRESULT)GetStockObject(NULL_BRUSH);
|
||||
}
|
||||
case WM_CTLCOLOREDIT:
|
||||
{
|
||||
if ((HWND)lParam == GetDlgItem(hDlg, IDC_FORCE_INPUT_DEVICE))
|
||||
return FALSE;
|
||||
HDC hdc = (HDC)wParam;
|
||||
SetBkMode(hdc, TRANSPARENT);
|
||||
SetTextColor(hdc, RGB(255, 0, 0));
|
||||
HWND hEdit = (HWND)lParam;
|
||||
RECT rc = getRedrawRect(hEdit);
|
||||
TabCtrl_AdjustRect(pCtrlDlgState->hCtrlTab, TRUE, &rc);
|
||||
RECT clientrc;
|
||||
GetClientRect(hEdit, &clientrc);
|
||||
TabCtrl_AdjustRect(pCtrlDlgState->hCtrlTab, TRUE, &clientrc);
|
||||
BitBlt(pCtrlDlgState->hbmPspImage, hdc, 0, 0, rc.right - rc.left, rc.bottom - rc.top, rc.left, rc.top);
|
||||
char str[11];
|
||||
GetWindowTextA(hEdit, str, 10);
|
||||
DrawTextA(hdc, str, (int)strlen(str), &clientrc, DT_CENTER|DT_SINGLELINE);
|
||||
return (LRESULT)GetStockObject(NULL_BRUSH);
|
||||
}
|
||||
case WM_COMMAND:
|
||||
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
|
||||
{
|
||||
if (LOWORD(wParam) == IDOK) {
|
||||
g_Config.iForceInputDevice = (ComboBox_GetCurSel(GetDlgItem(hDlg, IDC_FORCE_INPUT_DEVICE)) - 1);
|
||||
pCtrlDlgState->pCtrlMap->BindToDevices();
|
||||
saveControlsToFile();
|
||||
}
|
||||
UnhookWindowsHookEx(pCtrlDlgState->pKeydownHook);
|
||||
KillTimer(hDlg, pCtrlDlgState->timerId);
|
||||
SetWindowLongPtr(pCtrlDlgState->hStaticPspImage, GWLP_WNDPROC, (LONG_PTR)pCtrlDlgState->orgPSPImageProc);
|
||||
for (u32 i = CONTROLS_IDC_EDIT_BEGIN; i <= CONTROLS_IDC_EDIT_END; i++) {
|
||||
HWND hEdit = GetDlgItem(hDlg, i);
|
||||
SetWindowLongPtr(hEdit, GWLP_WNDPROC, (LONG_PTR)pCtrlDlgState->orgEditProc);
|
||||
}
|
||||
EndDialog(hDlg, LOWORD(wParam));
|
||||
if (pCtrlDlgState->hbmPspImage) {
|
||||
DeleteObject(pCtrlDlgState->hbmPspImage);
|
||||
pCtrlDlgState->hbmPspImage = 0;
|
||||
}
|
||||
if (pCtrlDlgState->pCtrlMap) {
|
||||
delete pCtrlDlgState->pCtrlMap;
|
||||
pCtrlDlgState->pCtrlMap = NULL;
|
||||
}
|
||||
if (pCtrlDlgState) {
|
||||
delete pCtrlDlgState;
|
||||
pCtrlDlgState = NULL;
|
||||
}
|
||||
return TRUE;
|
||||
} else if (LOWORD(wParam) >= CONTROLS_IDC_EDIT_BEGIN &&
|
||||
LOWORD(wParam) <= IDC_EDIT_KEYRIGHT &&
|
||||
HIWORD(wParam) == EN_SETFOCUS) {
|
||||
// send about buttonsMap-index of current focus Edit-Control to ControlMapping instance.
|
||||
UINT nCtrlID = LOWORD(wParam);
|
||||
if (nCtrlID < CONTROLS_IDC_EDIT_BEGIN || nCtrlID > IDC_EDIT_KEYRIGHT) {
|
||||
break;
|
||||
}
|
||||
pCtrlDlgState->pCtrlMap->SetTargetButton(nCtrlID - CONTROLS_IDC_EDIT_BEGIN);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
InvalidateRect(hwndDisplay,0,0);
|
||||
|
@ -1,6 +1,8 @@
|
||||
#include <limits.h>
|
||||
#include "base/NativeApp.h"
|
||||
#include "Core/Config.h"
|
||||
#include "input/input_state.h"
|
||||
#include "input/keycodes.h"
|
||||
#include "XinputDevice.h"
|
||||
#include "ControlMapping.h"
|
||||
|
||||
@ -9,27 +11,27 @@
|
||||
#define XUSER_MAX_COUNT 4
|
||||
#endif
|
||||
|
||||
// Yes, this maps more than the PSP has, but that's fine as this lets us
|
||||
// map buttons to extra functionality like speedup.
|
||||
unsigned int xinput_ctrl_map[] = {
|
||||
XBOX_CODE_LEFTTRIGER, PAD_BUTTON_UNTHROTTLE,
|
||||
XBOX_CODE_RIGHTTRIGER, PAD_BUTTON_BACK,
|
||||
XINPUT_GAMEPAD_A, PAD_BUTTON_A,
|
||||
XINPUT_GAMEPAD_B, PAD_BUTTON_B,
|
||||
XINPUT_GAMEPAD_X, PAD_BUTTON_X,
|
||||
XINPUT_GAMEPAD_Y, PAD_BUTTON_Y,
|
||||
XINPUT_GAMEPAD_BACK, PAD_BUTTON_SELECT,
|
||||
XINPUT_GAMEPAD_START, PAD_BUTTON_START,
|
||||
XINPUT_GAMEPAD_LEFT_SHOULDER, PAD_BUTTON_LBUMPER,
|
||||
XINPUT_GAMEPAD_RIGHT_SHOULDER, PAD_BUTTON_RBUMPER,
|
||||
XINPUT_GAMEPAD_LEFT_THUMB, PAD_BUTTON_LEFT_THUMB, // Turbo
|
||||
XINPUT_GAMEPAD_RIGHT_THUMB, PAD_BUTTON_RIGHT_THUMB, // Open PauseScreen
|
||||
XINPUT_GAMEPAD_DPAD_UP, PAD_BUTTON_UP,
|
||||
XINPUT_GAMEPAD_DPAD_DOWN, PAD_BUTTON_DOWN,
|
||||
XINPUT_GAMEPAD_DPAD_LEFT, PAD_BUTTON_LEFT,
|
||||
XINPUT_GAMEPAD_DPAD_RIGHT, PAD_BUTTON_RIGHT,
|
||||
// Permanent map. Actual mapping happens elsewhere.
|
||||
static const struct {int from, to;} xinput_ctrl_map[] = {
|
||||
{XBOX_CODE_LEFTTRIGGER, KEYCODE_BUTTON_L2},
|
||||
{XBOX_CODE_RIGHTTRIGGER, KEYCODE_BUTTON_R2},
|
||||
{XINPUT_GAMEPAD_A, KEYCODE_BUTTON_A},
|
||||
{XINPUT_GAMEPAD_B, KEYCODE_BUTTON_B},
|
||||
{XINPUT_GAMEPAD_X, KEYCODE_BUTTON_X},
|
||||
{XINPUT_GAMEPAD_Y, KEYCODE_BUTTON_Y},
|
||||
{XINPUT_GAMEPAD_BACK, KEYCODE_BACK},
|
||||
{XINPUT_GAMEPAD_START, KEYCODE_BUTTON_START},
|
||||
{XINPUT_GAMEPAD_LEFT_SHOULDER, KEYCODE_BUTTON_L1},
|
||||
{XINPUT_GAMEPAD_RIGHT_SHOULDER, KEYCODE_BUTTON_R1},
|
||||
{XINPUT_GAMEPAD_LEFT_THUMB, KEYCODE_BUTTON_THUMBL},
|
||||
{XINPUT_GAMEPAD_RIGHT_THUMB, KEYCODE_BUTTON_THUMBR},
|
||||
{XINPUT_GAMEPAD_DPAD_UP, KEYCODE_DPAD_UP},
|
||||
{XINPUT_GAMEPAD_DPAD_DOWN, KEYCODE_DPAD_DOWN},
|
||||
{XINPUT_GAMEPAD_DPAD_LEFT, KEYCODE_DPAD_LEFT},
|
||||
{XINPUT_GAMEPAD_DPAD_RIGHT, KEYCODE_DPAD_RIGHT},
|
||||
};
|
||||
static const unsigned int xinput_ctrl_map_size = sizeof(xinput_ctrl_map);
|
||||
|
||||
static const unsigned int xinput_ctrl_map_size = sizeof(xinput_ctrl_map) / sizeof(xinput_ctrl_map[0]);
|
||||
|
||||
XinputDevice::XinputDevice() {
|
||||
ZeroMemory( &this->prevState, sizeof(this->prevState) );
|
||||
@ -64,7 +66,7 @@ int XinputDevice::UpdateState(InputState &input_state) {
|
||||
}
|
||||
|
||||
if ( dwResult == ERROR_SUCCESS ) {
|
||||
ApplyDiff(state, input_state);
|
||||
ApplyButtons(state, input_state);
|
||||
Stick left = NormalizedDeadzoneFilter(state.Gamepad.sThumbLX, state.Gamepad.sThumbLY);
|
||||
Stick right = NormalizedDeadzoneFilter(state.Gamepad.sThumbRX, state.Gamepad.sThumbRY);
|
||||
input_state.pad_lstick_x += left.x;
|
||||
@ -79,6 +81,21 @@ int XinputDevice::UpdateState(InputState &input_state) {
|
||||
this->prevState = state;
|
||||
this->check_delay = 0;
|
||||
|
||||
AxisInput axis;
|
||||
axis.deviceId = DEVICE_ID_KEYBOARD;
|
||||
axis.axisId = JOYSTICK_AXIS_X;
|
||||
axis.value = left.x;
|
||||
NativeAxis(axis);
|
||||
axis.axisId = JOYSTICK_AXIS_Y;
|
||||
axis.value = left.y;
|
||||
NativeAxis(axis);
|
||||
axis.axisId = JOYSTICK_AXIS_Z;
|
||||
axis.value = right.x;
|
||||
NativeAxis(axis);
|
||||
axis.axisId = JOYSTICK_AXIS_RZ;
|
||||
axis.value = right.y;
|
||||
NativeAxis(axis);
|
||||
|
||||
// If there's an XInput pad, skip following pads. This prevents DInput and XInput
|
||||
// from colliding.
|
||||
return UPDATESTATE_SKIP_PAD;
|
||||
@ -128,8 +145,8 @@ struct xinput_button_name {
|
||||
};
|
||||
|
||||
const xinput_button_name xinput_name_map[] = {
|
||||
{XBOX_CODE_LEFTTRIGER, "LT"},
|
||||
{XBOX_CODE_RIGHTTRIGER, "RT"},
|
||||
{XBOX_CODE_LEFTTRIGGER, "LT"},
|
||||
{XBOX_CODE_RIGHTTRIGGER, "RT"},
|
||||
{XINPUT_GAMEPAD_A, "A"},
|
||||
{XINPUT_GAMEPAD_B, "B"},
|
||||
{XINPUT_GAMEPAD_X, "X"},
|
||||
@ -145,6 +162,7 @@ const xinput_button_name xinput_name_map[] = {
|
||||
{XINPUT_GAMEPAD_DPAD_LEFT, "Left"},
|
||||
{XINPUT_GAMEPAD_DPAD_RIGHT, "Right"},
|
||||
};
|
||||
|
||||
static const int xbutton_name_map_size = sizeof(xinput_name_map) / sizeof(xinput_button_name);
|
||||
|
||||
const char * getXinputButtonName(unsigned int button) {
|
||||
@ -155,22 +173,14 @@ const char * getXinputButtonName(unsigned int button) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void XinputDevice::ApplyDiff(XINPUT_STATE &state, InputState &input_state) {
|
||||
// Skip XBOX_CODE_LIFT/RIGHT TRIGER. it's virtual code for Mapping.
|
||||
for (int i = 0; i < sizeof(xinput_ctrl_map)/sizeof(xinput_ctrl_map[0]); i += 2) {
|
||||
if (state.Gamepad.wButtons & (WORD)(xinput_ctrl_map[i])) {
|
||||
input_state.pad_buttons |= (int)xinput_ctrl_map[i + 1];
|
||||
}
|
||||
// Effective use of triggers that are not used.
|
||||
if (xinput_ctrl_map[i] == XBOX_CODE_LEFTTRIGER &&
|
||||
state.Gamepad.bLeftTrigger > XINPUT_GAMEPAD_TRIGGER_THRESHOLD) {
|
||||
input_state.pad_buttons |= xinput_ctrl_map[i + 1];
|
||||
}
|
||||
if (xinput_ctrl_map[i] == XBOX_CODE_RIGHTTRIGER &&
|
||||
state.Gamepad.bRightTrigger > XINPUT_GAMEPAD_TRIGGER_THRESHOLD) {
|
||||
input_state.pad_buttons |= xinput_ctrl_map[i + 1];
|
||||
}
|
||||
}
|
||||
void XinputDevice::ApplyButtons(XINPUT_STATE &state, InputState &input_state) {
|
||||
u32 buttons = state.Gamepad.wButtons;
|
||||
// Simulate some extra buttons from axes. This should be done elsewhere really.
|
||||
|
||||
if (state.Gamepad.bLeftTrigger > XINPUT_GAMEPAD_TRIGGER_THRESHOLD)
|
||||
buttons |= XBOX_CODE_LEFTTRIGGER;
|
||||
if (state.Gamepad.bLeftTrigger > XINPUT_GAMEPAD_TRIGGER_THRESHOLD)
|
||||
buttons |= XBOX_CODE_RIGHTTRIGGER;
|
||||
|
||||
const SHORT rthreshold = 22000;
|
||||
|
||||
@ -178,32 +188,53 @@ void XinputDevice::ApplyDiff(XINPUT_STATE &state, InputState &input_state) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
if (state.Gamepad.sThumbRX > rthreshold) input_state.pad_buttons |= PAD_BUTTON_RIGHT;
|
||||
else if (state.Gamepad.sThumbRX < -rthreshold) input_state.pad_buttons |= PAD_BUTTON_LEFT;
|
||||
if (state.Gamepad.sThumbRY > rthreshold) input_state.pad_buttons |= PAD_BUTTON_UP;
|
||||
else if (state.Gamepad.sThumbRY < -rthreshold) input_state.pad_buttons |= PAD_BUTTON_DOWN;
|
||||
if (state.Gamepad.sThumbRX > rthreshold) buttons |= XINPUT_GAMEPAD_DPAD_RIGHT;
|
||||
else if (state.Gamepad.sThumbRX < -rthreshold) buttons |= XINPUT_GAMEPAD_DPAD_LEFT;
|
||||
if (state.Gamepad.sThumbRY > rthreshold) buttons |= XINPUT_GAMEPAD_DPAD_UP;
|
||||
else if (state.Gamepad.sThumbRY < -rthreshold) buttons |= XINPUT_GAMEPAD_DPAD_DOWN;
|
||||
break;
|
||||
case 2:
|
||||
if (state.Gamepad.sThumbRX > rthreshold) input_state.pad_buttons |= PAD_BUTTON_B;
|
||||
else if (state.Gamepad.sThumbRX < -rthreshold) input_state.pad_buttons |= PAD_BUTTON_X;
|
||||
if (state.Gamepad.sThumbRY > rthreshold) input_state.pad_buttons |= PAD_BUTTON_Y;
|
||||
else if (state.Gamepad.sThumbRY < -rthreshold) input_state.pad_buttons |= PAD_BUTTON_A;
|
||||
if (state.Gamepad.sThumbRX > rthreshold) buttons |= XINPUT_GAMEPAD_B;
|
||||
else if (state.Gamepad.sThumbRX < -rthreshold) buttons |= XINPUT_GAMEPAD_X;
|
||||
if (state.Gamepad.sThumbRY > rthreshold) buttons |= XINPUT_GAMEPAD_Y;
|
||||
else if (state.Gamepad.sThumbRY < -rthreshold) buttons |= XINPUT_GAMEPAD_A;
|
||||
break;
|
||||
case 3:
|
||||
if (state.Gamepad.sThumbRX > rthreshold) input_state.pad_buttons |= PAD_BUTTON_RBUMPER;
|
||||
else if (state.Gamepad.sThumbRX < -rthreshold) input_state.pad_buttons |= PAD_BUTTON_LBUMPER;
|
||||
if (state.Gamepad.sThumbRX > rthreshold) buttons |= XINPUT_GAMEPAD_RIGHT_SHOULDER;
|
||||
else if (state.Gamepad.sThumbRX < -rthreshold) buttons |= XINPUT_GAMEPAD_LEFT_SHOULDER;
|
||||
break;
|
||||
case 4:
|
||||
if (state.Gamepad.sThumbRX > rthreshold) input_state.pad_buttons |= PAD_BUTTON_RBUMPER;
|
||||
else if (state.Gamepad.sThumbRX < -rthreshold) input_state.pad_buttons |= PAD_BUTTON_LBUMPER;
|
||||
if (state.Gamepad.sThumbRY > rthreshold) input_state.pad_buttons |= PAD_BUTTON_Y;
|
||||
else if (state.Gamepad.sThumbRY < -rthreshold) input_state.pad_buttons |= PAD_BUTTON_A;
|
||||
if (state.Gamepad.sThumbRX > rthreshold) buttons |= XINPUT_GAMEPAD_RIGHT_SHOULDER;
|
||||
else if (state.Gamepad.sThumbRX < -rthreshold) buttons |= XINPUT_GAMEPAD_LEFT_SHOULDER;
|
||||
if (state.Gamepad.sThumbRY > rthreshold) buttons |= XINPUT_GAMEPAD_Y;
|
||||
else if (state.Gamepad.sThumbRY < -rthreshold) buttons |= XINPUT_GAMEPAD_A;
|
||||
break;
|
||||
case 5:
|
||||
if (state.Gamepad.sThumbRX > rthreshold) input_state.pad_buttons |= PAD_BUTTON_RIGHT;
|
||||
else if (state.Gamepad.sThumbRX < -rthreshold) input_state.pad_buttons |= PAD_BUTTON_LEFT;
|
||||
if (state.Gamepad.sThumbRX > rthreshold) buttons |= XINPUT_GAMEPAD_DPAD_RIGHT;
|
||||
else if (state.Gamepad.sThumbRX < -rthreshold) buttons |= XINPUT_GAMEPAD_DPAD_LEFT;
|
||||
break;
|
||||
}
|
||||
|
||||
u32 downMask = buttons & (~prevState.Gamepad.wButtons);
|
||||
u32 upMask = (~buttons) & prevState.Gamepad.wButtons;
|
||||
prevButtons = buttons;
|
||||
|
||||
for (int i = 0; i < xinput_ctrl_map_size; i++) {
|
||||
if (downMask & xinput_ctrl_map[i].from) {
|
||||
KeyInput key;
|
||||
key.deviceId = DEVICE_ID_X360_0;
|
||||
key.flags = KEY_DOWN;
|
||||
key.keyCode = xinput_ctrl_map[i].to;
|
||||
NativeKey(key);
|
||||
}
|
||||
if (upMask & xinput_ctrl_map[i].from) {
|
||||
KeyInput key;
|
||||
key.deviceId = DEVICE_ID_X360_0;
|
||||
key.flags = KEY_UP;
|
||||
key.keyCode = xinput_ctrl_map[i].to;
|
||||
NativeKey(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int XinputDevice::UpdateRawStateSingle(RawInputState &rawState)
|
||||
@ -235,9 +266,9 @@ int XinputDevice::UpdateRawStateSingle(RawInputState &rawState)
|
||||
}
|
||||
}
|
||||
if (state.Gamepad.bLeftTrigger > XINPUT_GAMEPAD_TRIGGER_THRESHOLD) {
|
||||
rawState.button = XBOX_CODE_LEFTTRIGER;
|
||||
rawState.button = XBOX_CODE_LEFTTRIGGER;
|
||||
} else if (state.Gamepad.bRightTrigger > XINPUT_GAMEPAD_TRIGGER_THRESHOLD) {
|
||||
rawState.button = XBOX_CODE_RIGHTTRIGER;
|
||||
rawState.button = XBOX_CODE_RIGHTTRIGGER;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -13,9 +13,10 @@ public:
|
||||
virtual bool IsPad() { return true; }
|
||||
int UpdateRawStateSingle(RawInputState &rawState);
|
||||
private:
|
||||
void ApplyDiff(XINPUT_STATE &state, InputState &input_state);
|
||||
void ApplyButtons(XINPUT_STATE &state, InputState &input_state);
|
||||
int gamepad_idx;
|
||||
int check_delay;
|
||||
XINPUT_STATE prevState;
|
||||
u32 prevButtons;
|
||||
};
|
||||
|
||||
|
Binary file not shown.
2
lang
2
lang
@ -1 +1 @@
|
||||
Subproject commit c670a27517d34cd4119d1139d4aec3546866f40d
|
||||
Subproject commit 92e5e45e316f73710882bf82ef8fe43f5192d0f2
|
2
native
2
native
@ -1 +1 @@
|
||||
Subproject commit e9a261ea9dd34e077560dae152aa94539a1b14d7
|
||||
Subproject commit 1dec6e8154610699e99a479a01e26ed03ea044df
|
@ -1 +1 @@
|
||||
Subproject commit d1038e00bdcf48e2ab057616bb2ec973980a7b3f
|
||||
Subproject commit 8b0c30efe52e0c799a99a632e5e743a56375d3ec
|
Loading…
Reference in New Issue
Block a user