From f1bc751eb9cddc9239a1f7e750919ac17313ec5d Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 16 Aug 2013 19:34:44 +0200 Subject: [PATCH 1/6] Step 1: Go back to a single control map. Break save/load for now, it will be redone. --- Common/KeyMap.cpp | 228 ++++++++++++++++++------------------ Common/KeyMap.h | 46 +++++--- Core/Config.cpp | 32 ++++- Core/Config.h | 3 +- UI/ControlMappingScreen.cpp | 34 ++---- UI/ControlMappingScreen.h | 8 +- UI/GameSettingsScreen.cpp | 17 +-- 7 files changed, 195 insertions(+), 173 deletions(-) diff --git a/Common/KeyMap.cpp b/Common/KeyMap.cpp index f40fa81710..ceca63ba12 100644 --- a/Common/KeyMap.cpp +++ b/Common/KeyMap.cpp @@ -29,58 +29,60 @@ 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; + m[CTRL_SQUARE] = KeyDef(DEVICE_ID_KEYBOARD, NKCODE_A); + m[CTRL_TRIANGLE] = KeyDef(DEVICE_ID_KEYBOARD, NKCODE_S); + m[CTRL_CIRCLE] = KeyDef(DEVICE_ID_KEYBOARD, NKCODE_X); + m[CTRL_CROSS] = KeyDef(DEVICE_ID_KEYBOARD, NKCODE_Z); + m[CTRL_LTRIGGER] = KeyDef(DEVICE_ID_KEYBOARD, NKCODE_Q); + m[CTRL_RTRIGGER] = KeyDef(DEVICE_ID_KEYBOARD, NKCODE_W); + + m[CTRL_START] = KeyDef(DEVICE_ID_KEYBOARD, NKCODE_SPACE); #ifdef _WIN32 - m[KeyDef(DEVICE_ID_KEYBOARD, NKCODE_V)] = CTRL_SELECT; + m[CTRL_SELECT] = KeyDef(DEVICE_ID_KEYBOARD, NKCODE_V); #else - m[KeyDef(DEVICE_ID_KEYBOARD, NKCODE_ENTER)] = CTRL_SELECT; + m[CTRL_SELECT]; = KeyDef(DEVICE_ID_KEYBOARD, NKCODE_ENTER); #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; + m[CTRL_UP ] = KeyDef(DEVICE_ID_KEYBOARD, NKCODE_DPAD_UP) ; + m[CTRL_DOWN ] = KeyDef(DEVICE_ID_KEYBOARD, NKCODE_DPAD_DOWN) ; + m[CTRL_LEFT ] = KeyDef(DEVICE_ID_KEYBOARD, NKCODE_DPAD_LEFT) ; + m[CTRL_RIGHT] = KeyDef(DEVICE_ID_KEYBOARD, NKCODE_DPAD_RIGHT); + m[VIRTKEY_AXIS_Y_MAX] = KeyDef(DEVICE_ID_KEYBOARD, NKCODE_I); + m[VIRTKEY_AXIS_Y_MIN] = KeyDef(DEVICE_ID_KEYBOARD, NKCODE_K); + m[VIRTKEY_AXIS_X_MIN] = KeyDef(DEVICE_ID_KEYBOARD, NKCODE_J); + m[VIRTKEY_AXIS_X_MAX] = KeyDef(DEVICE_ID_KEYBOARD, NKCODE_L); + m[VIRTKEY_RAPID_FIRE ] = KeyDef(DEVICE_ID_KEYBOARD, NKCODE_SHIFT_LEFT); + m[VIRTKEY_UNTHROTTLE ] = KeyDef(DEVICE_ID_KEYBOARD, NKCODE_TAB) ; + m[VIRTKEY_SPEED_TOGGLE] = KeyDef(DEVICE_ID_KEYBOARD, NKCODE_GRAVE) ; + m[VIRTKEY_PAUSE ] = KeyDef(DEVICE_ID_KEYBOARD, NKCODE_ESCAPE) ; 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; + m[CTRL_CROSS ] = KeyDef(DEVICE_ID_X360_0, NKCODE_BUTTON_A) ; + m[CTRL_CIRCLE ] = KeyDef(DEVICE_ID_X360_0, NKCODE_BUTTON_B) ; + m[CTRL_SQUARE ] = KeyDef(DEVICE_ID_X360_0, NKCODE_BUTTON_X) ; + m[CTRL_TRIANGLE ] = KeyDef(DEVICE_ID_X360_0, NKCODE_BUTTON_Y) ; + m[CTRL_UP ] = KeyDef(DEVICE_ID_X360_0, NKCODE_DPAD_UP) ; + m[CTRL_RIGHT ] = KeyDef(DEVICE_ID_X360_0, NKCODE_DPAD_RIGHT) ; + m[CTRL_DOWN ] = KeyDef(DEVICE_ID_X360_0, NKCODE_DPAD_DOWN) ; + m[CTRL_LEFT ] = KeyDef(DEVICE_ID_X360_0, NKCODE_DPAD_LEFT) ; + m[CTRL_START ] = KeyDef(DEVICE_ID_X360_0, NKCODE_BUTTON_START) ; + m[CTRL_SELECT ] = KeyDef(DEVICE_ID_X360_0, NKCODE_BUTTON_SELECT); + m[CTRL_LTRIGGER ] = KeyDef(DEVICE_ID_X360_0, NKCODE_BUTTON_L1) ; + m[CTRL_RTRIGGER ] = KeyDef(DEVICE_ID_X360_0, NKCODE_BUTTON_R1) ; + m[VIRTKEY_UNTHROTTLE ] = KeyDef(DEVICE_ID_X360_0, NKCODE_BUTTON_R2) ; + m[VIRTKEY_PAUSE ] = KeyDef(DEVICE_ID_X360_0, NKCODE_BUTTON_THUMBR); + m[VIRTKEY_SPEED_TOGGLE] = KeyDef(DEVICE_ID_X360_0, NKCODE_BUTTON_L2) ; + m[VIRTKEY_AXIS_X_MIN ] = AxisDef(DEVICE_ID_X360_0, JOYSTICK_AXIS_X, -1); + m[VIRTKEY_AXIS_X_MAX ] = AxisDef(DEVICE_ID_X360_0, JOYSTICK_AXIS_X, +1); + m[VIRTKEY_AXIS_Y_MIN ] = AxisDef(DEVICE_ID_X360_0, JOYSTICK_AXIS_Y, -1); + m[VIRTKEY_AXIS_Y_MAX ] = AxisDef(DEVICE_ID_X360_0, JOYSTICK_AXIS_Y, +1); return m; } + /* // Not used yet, will autodetect later static KeyMapping defaultShieldMap() { @@ -172,11 +174,15 @@ struct DefaultKeyMap { m[AxisDef(DEVICE_ID_DEFAULT, JOYSTICK_AXIS_Y, +1)] = VIRTKEY_AXIS_Y_MAX; return m; } + */ - static std::vector init() + + static ControllerMap init() { - std::vector m; + ControllerMap m; + m.keys = defaultKeyboardMap(); + /* #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'?) @@ -217,13 +223,17 @@ struct DefaultKeyMap { pad.active = false; m.push_back(pad); #endif + */ + return m; } - static std::vector KeyMap; + static ControllerMap KeyMap; }; -std::vector DefaultKeyMap::KeyMap = DefaultKeyMap::init(); +ControllerMap DefaultKeyMap::KeyMap = DefaultKeyMap::init(); + +ControllerMap g_controllerMap; // Key & Button names @@ -231,6 +241,7 @@ struct KeyMap_IntStrPair { int key; std::string name; }; + const KeyMap_IntStrPair key_names[] = { {NKCODE_A, "A"}, {NKCODE_B, "B"}, @@ -433,6 +444,7 @@ const KeyMap_IntStrPair axis_names[] = { }; static std::string unknown_key_name = "??"; + const KeyMap_IntStrPair psp_button_names[] = { {CTRL_CIRCLE, "O"}, {CTRL_CROSS, "X"}, @@ -465,8 +477,7 @@ const KeyMap_IntStrPair psp_button_names[] = { 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,18 +485,23 @@ 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 GetPspButtonName(int btn) { return FindName(btn, psp_button_names, ARRAY_SIZE(psp_button_names)); } -int TranslateKeyCodeToAxis(int keyCode, int &direction) -{ +std::vector GetMappableKeys() { + std::vector 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; @@ -495,8 +511,7 @@ int TranslateKeyCodeToAxis(int keyCode, int &direction) 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,16 +520,11 @@ 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; +static bool FindKeyMapping(int deviceId, int key, int *psp_button) { + // Brute force, let's optimize later + for (auto iter = g_controllerMap.keys.begin(); iter != g_controllerMap.keys.end(); ++iter) { + if (iter->second == KeyDef(deviceId, key)) { + *psp_button = iter->first; return true; } } @@ -532,130 +542,126 @@ 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, int *deviceId, int *keyCode) { 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; + for (auto iter = g_controllerMap.keys.begin(); iter != g_controllerMap.keys.end(); ++iter) { + if (iter->first == btn) { + *deviceId = iter->second.deviceId; + *keyCode = iter->second.keyCode; return true; } } 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); + for (auto iter = g_controllerMap.keys.begin(); iter != g_controllerMap.keys.end(); ++iter) { + if (iter->first == btn && iter->second.keyCode >= AXIS_BIND_NKCODE_START) { + *deviceId = iter->second.deviceId; + *axisId = TranslateKeyCodeToAxis(iter->second.keyCode, *direction); return true; } } return false; } -std::string NameKeyFromPspButton(int controllerMap, int btn) { +std::string NameKeyFromPspButton(int btn) { int deviceId; int axisId; int direction; int keyCode; - if (AxisFromPspButton(controllerMap, btn, &deviceId, &axisId, &direction)) { + if (AxisFromPspButton(btn, &deviceId, &axisId, &direction)) { return GetAxisName(axisId) + (direction < 0 ? "-" : "+"); } - if (KeyFromPspButton(controllerMap, btn, &deviceId, &keyCode)) { + if (KeyFromPspButton(btn, &deviceId, &keyCode)) { return GetKeyName(keyCode); } return "unknown"; } -std::string NameDeviceFromPspButton(int controllerMap, int btn) { +std::string NameDeviceFromPspButton(int btn) { int deviceId; int axisId; int direction; int keyCode; - if (AxisFromPspButton(controllerMap, btn, &deviceId, &axisId, &direction)) { + if (AxisFromPspButton(btn, &deviceId, &axisId, &direction)) { return GetDeviceName(deviceId); } - if (KeyFromPspButton(controllerMap, btn, &deviceId, &keyCode)) { + if (KeyFromPspButton(btn, &deviceId, &keyCode)) { return GetDeviceName(deviceId); } return "unknown"; } -bool IsMappedKey(int deviceId, int key) -{ +bool IsMappedKey(int deviceId, int key) { return KeyToPspButton(deviceId, key) != KEYMAP_ERROR_UNKNOWN_KEY; } -std::string NamePspButtonFromKey(int deviceId, int 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.keys.begin(); iter != g_controllerMap.keys.end(); ++iter) { + if (iter->first == btn) { + g_controllerMap.keys.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 deviceId, int key, int btn) { + RemoveButtonMapping(btn); + g_controllerMap.keys[btn] = KeyDef(deviceId, key); } -std::string GetAxisName(int axisId) -{ +std::string GetAxisName(int axisId) { return FindName(axisId, axis_names, ARRAY_SIZE(axis_names)); } -bool IsMappedAxis(int deviceId, int axisId, int direction) -{ +bool IsMappedAxis(int deviceId, int axisId, int direction) { int key = TranslateKeyCodeFromAxis(axisId, direction); return KeyToPspButton(deviceId, key) != KEYMAP_ERROR_UNKNOWN_KEY; } -std::string NamePspButtonFromAxis(int deviceId, int axisId, int direction) -{ +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) -{ +void SetAxisMapping(int deviceId, int axisId, int direction, int btn) { int key = TranslateKeyCodeFromAxis(axisId, direction); - SetKeyMapping(map, deviceId, key, btn); + SetKeyMapping(deviceId, key, btn); } void RestoreDefault() { - controllerMaps = DefaultKeyMap::KeyMap; + g_controllerMap = DefaultKeyMap::KeyMap; } // TODO: Make the ini format nicer. void LoadFromIni(IniFile &file) { if (!file.HasSection("ControlMapping")) { - controllerMaps = DefaultKeyMap::KeyMap; + g_controllerMap = DefaultKeyMap::KeyMap; return; } - controllerMaps.clear(); + g_controllerMap.keys.clear(); IniFile::Section *controls = file.GetOrCreateSection("ControlMapping"); + + /* + + std::vector maps; controls->Get("ControllerMaps", maps); if (!maps.size()) { @@ -680,11 +686,13 @@ void LoadFromIni(IniFile &file) { newMap.keys[KeyDef(deviceId, keyCode)] = atoi(x->second.c_str()); } controllerMaps.push_back(newMap); - } + }*/ + } void SaveToIni(IniFile &file) { IniFile::Section *controls = file.GetOrCreateSection("ControlMapping"); + /* std::vector maps; for (auto x = controllerMaps.begin(); x != controllerMaps.end(); ++x) { maps.push_back(x->name); @@ -702,9 +710,7 @@ void SaveToIni(IniFile &file) { sprintf(value, "%i", iter->second); map->Set(key, value); } - } + }*/ } } // KeyMap - -std::vector controllerMaps = KeyMap::DefaultKeyMap::KeyMap; diff --git a/Common/KeyMap.h b/Common/KeyMap.h index 6cbc28ff61..21c025033b 100644 --- a/Common/KeyMap.h +++ b/Common/KeyMap.h @@ -48,6 +48,7 @@ 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 +59,40 @@ 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 KeyMapping; -typedef std::map AxisMapping; +typedef std::map KeyMapping; + + +// These are for speed only, built from the regular ones. For the future. +// typedef std::map KeyMapping; // Multiple maps can be active at the same time. -class ControllerMap { -public: - ControllerMap() : active(true) {} - bool active; +struct ControllerMap { KeyMapping keys; - AxisMapping axis; // TODO - std::string name; }; - -extern std::vector controllerMaps; +extern ControllerMap g_controllerMap; // KeyMap // A translation layer for key assignment. Provides @@ -113,26 +125,28 @@ namespace KeyMap { // 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); + bool KeyFromPspButton(int btn, int *deviceId, int *keyCode); + std::string NameKeyFromPspButton(int btn); + std::string NameDeviceFromPspButton(int btn); // Configure the key mapping. // Any configuration will be saved to the Core config. - void SetKeyMapping(int map, int deviceId, int keyCode, int psp_key); + void SetKeyMapping(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 AxisFromPspButton(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); // 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 deviceId, int axisId, int direction, int btn); void LoadFromIni(IniFile &iniFile); void SaveToIni(IniFile &iniFile); + void RestoreDefault(); + void QuickMap(int device); } diff --git a/Core/Config.cpp b/Core/Config.cpp index 15b2b37558..015584edfd 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -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; @@ -188,7 +189,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(); } @@ -305,14 +315,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"); } diff --git a/Core/Config.h b/Core/Config.h index bf8d893670..303ab63852 100644 --- a/Core/Config.h +++ b/Core/Config.h @@ -162,7 +162,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 @@ -171,6 +171,7 @@ public: private: std::string iniFilename_; + std::string controllerIniFilename_; }; extern Config g_Config; diff --git a/UI/ControlMappingScreen.cpp b/UI/ControlMappingScreen.cpp index f3251e3b79..af04b133eb 100644 --- a/UI/ControlMappingScreen.cpp +++ b/UI/ControlMappingScreen.cpp @@ -51,18 +51,14 @@ void KeyMappingScreen::render() { #define KeyBtn(x, y, symbol) \ - if (UIButton(GEN_ID, Pos(x, y), 90, 0, KeyMap::NameKeyFromPspButton(currentMap_, symbol).c_str(), \ + if (UIButton(GEN_ID, Pos(x, y), 90, 0, KeyMap::NameKeyFromPspButton(symbol).c_str(), \ ALIGN_TOPLEFT)) {\ - screenManager()->push(new KeyMappingNewKeyDialog(symbol, currentMap_), 0); \ + screenManager()->push(new KeyMappingNewKeyDialog(symbol), 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+50), KeyMap::NameDeviceFromPspButton(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); \ - - // \ - // UIText(0, Pos(x, y+50), controllerMaps[currentMap_].name.c_str(), 0xFFFFFFFF, 0.5f, ALIGN_HCENTER); - int pad = 130; int hlfpad = pad / 2; @@ -114,20 +110,6 @@ void KeyMappingScreen::render() { 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_ = (int)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_ >= (int)controllerMaps.size()) - currentMap_ = 0; - } - 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(); } @@ -141,8 +123,8 @@ void KeyMappingNewKeyDialog::CreatePopupContents(UI::ViewGroup *parent) { 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_); + std::string buttonKey = KeyMap::NameKeyFromPspButton(this->pspBtn_); + std::string buttonDevice = KeyMap::NameDeviceFromPspButton(this->pspBtn_); parent->Add(new TextView(std::string(keyI18N->T("Previous:")) + " " + buttonKey + " - " + buttonDevice)); } @@ -156,7 +138,7 @@ void KeyMappingNewKeyDialog::key(const KeyInput &key) { last_kb_key_ = key.keyCode; last_axis_id_ = -1; - KeyMap::SetKeyMapping(currentMap_, last_kb_deviceid_, last_kb_key_, pspBtn_); + KeyMap::SetKeyMapping(last_kb_deviceid_, last_kb_key_, pspBtn_); screenManager()->finishDialog(this, DR_OK); } } @@ -167,7 +149,7 @@ void KeyMappingNewKeyDialog::axis(const AxisInput &axis) { 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_); + KeyMap::SetAxisMapping(last_axis_deviceid_, last_axis_id_, last_axis_direction_, pspBtn_); screenManager()->finishDialog(this, DR_OK); } @@ -176,7 +158,7 @@ void KeyMappingNewKeyDialog::axis(const AxisInput &axis) { 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_); + KeyMap::SetAxisMapping(last_axis_deviceid_, last_axis_id_, last_axis_direction_, pspBtn_); screenManager()->finishDialog(this, DR_OK); } } diff --git a/UI/ControlMappingScreen.h b/UI/ControlMappingScreen.h index f8c3287b22..4b7e57cb85 100644 --- a/UI/ControlMappingScreen.h +++ b/UI/ControlMappingScreen.h @@ -20,23 +20,20 @@ class KeyMappingScreen : public Screen { public: - KeyMappingScreen() : currentMap_(0) {} + KeyMappingScreen() : Screen() {} void update(InputState &input); void render(); -private: - int currentMap_; }; // Dialog box, meant to be pushed class KeyMappingNewKeyDialog : public PopupScreen { public: - KeyMappingNewKeyDialog(int btn, int currentMap) : PopupScreen("Map Key") { + explicit KeyMappingNewKeyDialog(int btn) : PopupScreen("Map Key") { 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); @@ -56,5 +53,4 @@ private: int last_axis_deviceid_; int last_axis_id_; int last_axis_direction_; - int currentMap_; }; diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp index 4393ac65fd..7ca1dfdac8 100644 --- a/UI/GameSettingsScreen.cpp +++ b/UI/GameSettingsScreen.cpp @@ -260,22 +260,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 +284,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); From 3a8432373de02a088a2ebbdacb0968cdc9f7568d Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 16 Aug 2013 21:25:01 +0200 Subject: [PATCH 2/6] Step 2: Multiple inputs can be mapped per psp key now, and save load works. --- .gitignore | 1 + Common/KeyMap.cpp | 549 +++++++++++++++++------------------- Common/KeyMap.h | 14 +- UI/ControlMappingScreen.cpp | 22 +- UI/ControlMappingScreen.h | 13 +- 5 files changed, 277 insertions(+), 322 deletions(-) diff --git a/.gitignore b/.gitignore index ef982616ff..2e1d833dbd 100644 --- a/.gitignore +++ b/.gitignore @@ -18,6 +18,7 @@ *.aps *.exp *.qdact +controls.ini Debug Release Windows/x64 diff --git a/Common/KeyMap.cpp b/Common/KeyMap.cpp index ceca63ba12..ae88d7a879 100644 --- a/Common/KeyMap.cpp +++ b/Common/KeyMap.cpp @@ -24,218 +24,177 @@ 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[CTRL_SQUARE] = KeyDef(DEVICE_ID_KEYBOARD, NKCODE_A); - m[CTRL_TRIANGLE] = KeyDef(DEVICE_ID_KEYBOARD, NKCODE_S); - m[CTRL_CIRCLE] = KeyDef(DEVICE_ID_KEYBOARD, NKCODE_X); - m[CTRL_CROSS] = KeyDef(DEVICE_ID_KEYBOARD, NKCODE_Z); - m[CTRL_LTRIGGER] = KeyDef(DEVICE_ID_KEYBOARD, NKCODE_Q); - m[CTRL_RTRIGGER] = KeyDef(DEVICE_ID_KEYBOARD, NKCODE_W); - - m[CTRL_START] = KeyDef(DEVICE_ID_KEYBOARD, NKCODE_SPACE); -#ifdef _WIN32 - m[CTRL_SELECT] = KeyDef(DEVICE_ID_KEYBOARD, NKCODE_V); -#else - m[CTRL_SELECT]; = KeyDef(DEVICE_ID_KEYBOARD, NKCODE_ENTER); -#endif - m[CTRL_UP ] = KeyDef(DEVICE_ID_KEYBOARD, NKCODE_DPAD_UP) ; - m[CTRL_DOWN ] = KeyDef(DEVICE_ID_KEYBOARD, NKCODE_DPAD_DOWN) ; - m[CTRL_LEFT ] = KeyDef(DEVICE_ID_KEYBOARD, NKCODE_DPAD_LEFT) ; - m[CTRL_RIGHT] = KeyDef(DEVICE_ID_KEYBOARD, NKCODE_DPAD_RIGHT); - m[VIRTKEY_AXIS_Y_MAX] = KeyDef(DEVICE_ID_KEYBOARD, NKCODE_I); - m[VIRTKEY_AXIS_Y_MIN] = KeyDef(DEVICE_ID_KEYBOARD, NKCODE_K); - m[VIRTKEY_AXIS_X_MIN] = KeyDef(DEVICE_ID_KEYBOARD, NKCODE_J); - m[VIRTKEY_AXIS_X_MAX] = KeyDef(DEVICE_ID_KEYBOARD, NKCODE_L); - m[VIRTKEY_RAPID_FIRE ] = KeyDef(DEVICE_ID_KEYBOARD, NKCODE_SHIFT_LEFT); - m[VIRTKEY_UNTHROTTLE ] = KeyDef(DEVICE_ID_KEYBOARD, NKCODE_TAB) ; - m[VIRTKEY_SPEED_TOGGLE] = KeyDef(DEVICE_ID_KEYBOARD, NKCODE_GRAVE) ; - m[VIRTKEY_PAUSE ] = KeyDef(DEVICE_ID_KEYBOARD, NKCODE_ESCAPE) ; - return m; - } - - static KeyMapping default360Map() - { - KeyMapping m; - m[CTRL_CROSS ] = KeyDef(DEVICE_ID_X360_0, NKCODE_BUTTON_A) ; - m[CTRL_CIRCLE ] = KeyDef(DEVICE_ID_X360_0, NKCODE_BUTTON_B) ; - m[CTRL_SQUARE ] = KeyDef(DEVICE_ID_X360_0, NKCODE_BUTTON_X) ; - m[CTRL_TRIANGLE ] = KeyDef(DEVICE_ID_X360_0, NKCODE_BUTTON_Y) ; - m[CTRL_UP ] = KeyDef(DEVICE_ID_X360_0, NKCODE_DPAD_UP) ; - m[CTRL_RIGHT ] = KeyDef(DEVICE_ID_X360_0, NKCODE_DPAD_RIGHT) ; - m[CTRL_DOWN ] = KeyDef(DEVICE_ID_X360_0, NKCODE_DPAD_DOWN) ; - m[CTRL_LEFT ] = KeyDef(DEVICE_ID_X360_0, NKCODE_DPAD_LEFT) ; - m[CTRL_START ] = KeyDef(DEVICE_ID_X360_0, NKCODE_BUTTON_START) ; - m[CTRL_SELECT ] = KeyDef(DEVICE_ID_X360_0, NKCODE_BUTTON_SELECT); - m[CTRL_LTRIGGER ] = KeyDef(DEVICE_ID_X360_0, NKCODE_BUTTON_L1) ; - m[CTRL_RTRIGGER ] = KeyDef(DEVICE_ID_X360_0, NKCODE_BUTTON_R1) ; - m[VIRTKEY_UNTHROTTLE ] = KeyDef(DEVICE_ID_X360_0, NKCODE_BUTTON_R2) ; - m[VIRTKEY_PAUSE ] = KeyDef(DEVICE_ID_X360_0, NKCODE_BUTTON_THUMBR); - m[VIRTKEY_SPEED_TOGGLE] = KeyDef(DEVICE_ID_X360_0, NKCODE_BUTTON_L2) ; - m[VIRTKEY_AXIS_X_MIN ] = AxisDef(DEVICE_ID_X360_0, JOYSTICK_AXIS_X, -1); - m[VIRTKEY_AXIS_X_MAX ] = AxisDef(DEVICE_ID_X360_0, JOYSTICK_AXIS_X, +1); - m[VIRTKEY_AXIS_Y_MIN ] = AxisDef(DEVICE_ID_X360_0, JOYSTICK_AXIS_Y, -1); - m[VIRTKEY_AXIS_Y_MAX ] = AxisDef(DEVICE_ID_X360_0, JOYSTICK_AXIS_Y, +1); - 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 ControllerMap init() - { - ControllerMap m; - m.keys = defaultKeyboardMap(); - - /* -#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 ControllerMap KeyMap; +struct DefMappingStruct { + int pspKey; + int key; + int direction; }; -ControllerMap DefaultKeyMap::KeyMap = DefaultKeyMap::init(); +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[] = { + {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}, +}; + +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}, +}; + +enum DefaultMaps { + DEFAULT_MAPPING_KEYBOARD, + DEFAULT_MAPPING_X360, + DEFAULT_MAPPING_PAD, + DEFAULT_MAPPING_SHIELD, + DEFAULT_MAPPING_OUYA, +}; + + +static void AddDefaultKeyMap(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 AddDefaultKeyMap(DefaultMaps dmap, bool replace) { + switch (dmap) { + case DEFAULT_MAPPING_KEYBOARD: + AddDefaultKeyMap(DEVICE_ID_KEYBOARD, defaultKeyboardKeyMap, ARRAY_SIZE(defaultKeyboardKeyMap), replace); + break; + case DEFAULT_MAPPING_X360: + AddDefaultKeyMap(DEVICE_ID_X360_0, default360KeyMap, ARRAY_SIZE(default360KeyMap), replace); + break; + case DEFAULT_MAPPING_SHIELD: + AddDefaultKeyMap(DEVICE_ID_X360_0, defaultShieldKeyMap, ARRAY_SIZE(defaultShieldKeyMap), replace); + break; + } +} ControllerMap g_controllerMap; - // Key & Button names struct KeyMap_IntStrPair { int key; @@ -446,10 +405,10 @@ 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_CIRCLE, "Circle"}, + {CTRL_CROSS, "Cross"}, + {CTRL_SQUARE, "Square"}, + {CTRL_TRIANGLE, "Triangle"}, {CTRL_LTRIGGER, "L"}, {CTRL_RTRIGGER, "R"}, {CTRL_START, "Start"}, @@ -523,9 +482,11 @@ KeyDef AxisDef(int deviceId, int axisId, int direction) { static bool FindKeyMapping(int deviceId, int key, int *psp_button) { // Brute force, let's optimize later for (auto iter = g_controllerMap.keys.begin(); iter != g_controllerMap.keys.end(); ++iter) { - if (iter->second == KeyDef(deviceId, key)) { - *psp_button = iter->first; - return true; + for (auto iter2 = iter->second.begin(); iter2 != iter->second.end(); ++iter2) { + if (*iter2 == KeyDef(deviceId, key)) { + *psp_button = iter->first; + return true; + } } } return false; @@ -543,15 +504,17 @@ int KeyToPspButton(int deviceId, int key) } // TODO: vector output -bool KeyFromPspButton(int btn, int *deviceId, int *keyCode) -{ +bool KeyFromPspButton(int btn, std::vector *devices, std::vector *keyCodes) { int search_start_layer = 0; for (auto iter = g_controllerMap.keys.begin(); iter != g_controllerMap.keys.end(); ++iter) { if (iter->first == btn) { - *deviceId = iter->second.deviceId; - *keyCode = iter->second.keyCode; - return true; + for (auto iter2 = iter->second.begin(); iter2 != iter->second.end(); ++iter2) { + // For now: Grab the first one. + devices->push_back(iter2->deviceId); + keyCodes->push_back(iter2->keyCode); + return true; + } } } return false; @@ -566,10 +529,12 @@ bool AxisFromPspButton(int btn, int *deviceId, int *axisId, int *direction) { int search_start_layer = 0; for (auto iter = g_controllerMap.keys.begin(); iter != g_controllerMap.keys.end(); ++iter) { - if (iter->first == btn && iter->second.keyCode >= AXIS_BIND_NKCODE_START) { - *deviceId = iter->second.deviceId; - *axisId = TranslateKeyCodeToAxis(iter->second.keyCode, *direction); - return true; + 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; @@ -579,12 +544,13 @@ std::string NameKeyFromPspButton(int btn) { int deviceId; int axisId; int direction; - int keyCode; if (AxisFromPspButton(btn, &deviceId, &axisId, &direction)) { return GetAxisName(axisId) + (direction < 0 ? "-" : "+"); } - if (KeyFromPspButton(btn, &deviceId, &keyCode)) { - return GetKeyName(keyCode); + std::vector deviceIds; + std::vector keyCodes; + if (KeyFromPspButton(btn, &deviceIds, &keyCodes)) { + return GetKeyName(keyCodes[0]); } return "unknown"; } @@ -593,12 +559,13 @@ std::string NameDeviceFromPspButton(int btn) { int deviceId; int axisId; int direction; - int keyCode; if (AxisFromPspButton(btn, &deviceId, &axisId, &direction)) { return GetDeviceName(deviceId); } - if (KeyFromPspButton(btn, &deviceId, &keyCode)) { - return GetDeviceName(deviceId); + std::vector deviceIds; + std::vector keyCodes; + if (KeyFromPspButton(btn, &deviceIds, &keyCodes)) { + return GetDeviceName(deviceIds[0]); } return "unknown"; } @@ -620,97 +587,107 @@ void RemoveButtonMapping(int btn) { } } -void SetKeyMapping(int deviceId, int key, int btn) { - RemoveButtonMapping(btn); - g_controllerMap.keys[btn] = KeyDef(deviceId, key); +void SetKeyMapping(int btn, KeyDef key, bool replace) { + if (replace) { + RemoveButtonMapping(btn); + g_controllerMap.keys[btn].clear(); + g_controllerMap.keys[btn].push_back(key); + } else { + for (auto iter = g_controllerMap.keys[btn].begin(); iter != g_controllerMap.keys[btn].end(); ++iter) { + if (*iter == key) + return; + } + g_controllerMap.keys[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) { - 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 deviceId, int axisId, int direction, int btn) { +void SetAxisMapping(int deviceId, int axisId, int direction, int btn, bool replace) { int key = TranslateKeyCodeFromAxis(axisId, direction); - SetKeyMapping(deviceId, key, btn); + SetKeyMapping(btn, KeyDef(deviceId, key), replace); } +// Note that it's easy to add other defaults if desired. void RestoreDefault() { - g_controllerMap = DefaultKeyMap::KeyMap; +#if defined(_WIN32) + AddDefaultKeyMap(DEFAULT_MAPPING_KEYBOARD, true); + AddDefaultKeyMap(DEFAULT_MAPPING_X360, false); +#elif defined(ANDROID) + AddDefaultKeyMap(DEFAULT_MAPPING_PAD, true); +#else + AddDefaultKeyMap(DEFAULT_MAPPING_KEYBOARD, true); + AddDefaultKeyMap(DEFAULT_MAPPING_PAD, false); +#endif } +// BEGIN unused code to delete + +bool IsMappedAxis(int deviceId, int axisId, int direction) { + int key = TranslateKeyCodeFromAxis(axisId, direction); + return KeyToPspButton(deviceId, key) != KEYMAP_ERROR_UNKNOWN_KEY; +} + +// END unused code + // TODO: Make the ini format nicer. void LoadFromIni(IniFile &file) { + RestoreDefault(); if (!file.HasSection("ControlMapping")) { - g_controllerMap = DefaultKeyMap::KeyMap; return; } - g_controllerMap.keys.clear(); - IniFile::Section *controls = file.GetOrCreateSection("ControlMapping"); + 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.keys.erase(psp_button_names[i].key); - /* + std::vector mappings; + SplitString(value, ',', mappings); + for (size_t j = 0; j < mappings.size(); j++) { + std::vector parts; + SplitString(mappings[j], '-', parts); + int deviceId = atoi(parts[0].c_str()); + int keyCode = atoi(parts[1].c_str()); - std::vector maps; - controls->Get("ControllerMaps", maps); - if (!maps.size()) { - controllerMaps = DefaultKeyMap::KeyMap; - return; - } - - 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 strmap = map->ToMap(); - - for (auto x = strmap.begin(); x != strmap.end(); ++x) { - std::vector 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()); + SetKeyMapping(psp_button_names[i].key, KeyDef(deviceId, keyCode), false); } - controllerMaps.push_back(newMap); - }*/ - + } } void SaveToIni(IniFile &file) { IniFile::Section *controls = file.GetOrCreateSection("ControlMapping"); - /* - std::vector 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 devices; + std::vector keycodes; + KeyFromPspButton(psp_button_names[i].key, &devices, &keycodes); + + std::string value; + for (size_t j = 0; j < devices.size(); j++) { + char temp[128]; + sprintf(temp, "%i-%i", devices[j], keycodes[j]); + value += temp; + if (j != devices.size() - 1) + value += ","; } - }*/ + + controls->Set(psp_button_names[i].name.c_str(), value, ""); + } } } // KeyMap diff --git a/Common/KeyMap.h b/Common/KeyMap.h index 21c025033b..a0dd5ac645 100644 --- a/Common/KeyMap.h +++ b/Common/KeyMap.h @@ -80,7 +80,7 @@ struct AxisPos { } }; -typedef std::map KeyMapping; +typedef std::map> KeyMapping; // These are for speed only, built from the regular ones. For the future. @@ -125,13 +125,17 @@ namespace KeyMap { // about mapping conflicts std::string NamePspButtonFromKey(int deviceId, int key); - bool KeyFromPspButton(int btn, int *deviceId, int *keyCode); + bool KeyFromPspButton(int btn, std::vector *devices, std::vector *keyCodes); std::string NameKeyFromPspButton(int btn); std::string NameDeviceFromPspButton(int btn); // Configure the key mapping. // Any configuration will be saved to the Core config. - void SetKeyMapping(int deviceId, int keyCode, int psp_key); + void SetKeyMapping(int psp_key, KeyDef key, bool replace); + + // Configure an axis mapping, saves the configuration. + // Direction is negative or positive. + void SetAxisMapping(int deviceId, int axisId, int direction, int btn, bool replace); std::string GetAxisName(int axisId); int AxisToPspButton(int deviceId, int axisId, int direction); @@ -139,10 +143,6 @@ namespace KeyMap { bool IsMappedAxis(int deviceId, int axisId, int direction); std::string NamePspButtonFromAxis(int deviceId, int axisId, int direction); - // Configure an axis mapping, saves the configuration. - // Direction is negative or positive. - void SetAxisMapping(int deviceId, int axisId, int direction, int btn); - void LoadFromIni(IniFile &iniFile); void SaveToIni(IniFile &iniFile); diff --git a/UI/ControlMappingScreen.cpp b/UI/ControlMappingScreen.cpp index af04b133eb..73c94f00d1 100644 --- a/UI/ControlMappingScreen.cpp +++ b/UI/ControlMappingScreen.cpp @@ -49,7 +49,6 @@ void KeyMappingScreen::render() { I18NCategory *keyI18N = GetI18NCategory("KeyMapping"); I18NCategory *generalI18N = GetI18NCategory("General"); - #define KeyBtn(x, y, symbol) \ if (UIButton(GEN_ID, Pos(x, y), 90, 0, KeyMap::NameKeyFromPspButton(symbol).c_str(), \ ALIGN_TOPLEFT)) {\ @@ -103,7 +102,6 @@ void KeyMappingScreen::render() { 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)) { @@ -133,32 +131,20 @@ 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(last_kb_deviceid_, last_kb_key_, pspBtn_); + + KeyMap::SetKeyMapping(pspBtn_, KeyDef(key.deviceId, key.keyCode), replace_); screenManager()->finishDialog(this, DR_OK); } } 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(last_axis_deviceid_, last_axis_id_, last_axis_direction_, pspBtn_); + KeyMap::SetAxisMapping(axis.deviceId, axis.axisId, 1, pspBtn_, replace_); screenManager()->finishDialog(this, DR_OK); } 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(last_axis_deviceid_, last_axis_id_, last_axis_direction_, pspBtn_); + KeyMap::SetAxisMapping(axis.deviceId, axis.axisId, -1, pspBtn_, replace_); screenManager()->finishDialog(this, DR_OK); } } diff --git a/UI/ControlMappingScreen.h b/UI/ControlMappingScreen.h index 4b7e57cb85..04ee782cb4 100644 --- a/UI/ControlMappingScreen.h +++ b/UI/ControlMappingScreen.h @@ -28,12 +28,8 @@ public: // Dialog box, meant to be pushed class KeyMappingNewKeyDialog : public PopupScreen { public: - explicit KeyMappingNewKeyDialog(int btn) : PopupScreen("Map Key") { + explicit KeyMappingNewKeyDialog(int btn, bool replace = false) : PopupScreen("Map Key") { pspBtn_ = btn; - last_kb_deviceid_ = 0; - last_kb_key_ = 0; - last_axis_deviceid_ = 0; - last_axis_id_ = -1; } void key(const KeyInput &key); @@ -45,12 +41,7 @@ protected: virtual bool FillVertical() { return false; } virtual bool ShowButtons() { return false; } virtual void OnCompleted(DialogResult result) {} - private: int pspBtn_; - int last_kb_deviceid_; - int last_kb_key_; - int last_axis_deviceid_; - int last_axis_id_; - int last_axis_direction_; + bool replace_; }; From 3636f909023ea3b133b3341fcd7ed8c2f9f9bf80 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 17 Aug 2013 10:34:38 +0200 Subject: [PATCH 3/6] Step 3: Replace current key mapping dialog with a list-based one which is much more workable. --- Common/KeyMap.cpp | 154 +++++++----------------- Common/KeyMap.h | 43 +++---- UI/ControlMappingScreen.cpp | 230 ++++++++++++++++++++++++------------ UI/ControlMappingScreen.h | 19 ++- UI/GameSettingsScreen.cpp | 8 +- UI/MenuScreens.cpp | 3 +- native | 2 +- 7 files changed, 243 insertions(+), 216 deletions(-) diff --git a/Common/KeyMap.cpp b/Common/KeyMap.cpp index ae88d7a879..4c245eaed4 100644 --- a/Common/KeyMap.cpp +++ b/Common/KeyMap.cpp @@ -30,6 +30,8 @@ struct DefMappingStruct { int direction; }; +KeyMapping g_controllerMap; + static const DefMappingStruct defaultKeyboardKeyMap[] = { {CTRL_SQUARE, NKCODE_A}, {CTRL_TRIANGLE, NKCODE_S}, @@ -59,6 +61,10 @@ static const DefMappingStruct defaultKeyboardKeyMap[] = { }; 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}, @@ -74,10 +80,6 @@ static const DefMappingStruct default360KeyMap[] = { {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}, }; static const DefMappingStruct defaultShieldKeyMap[] = { @@ -161,16 +163,7 @@ static const DefMappingStruct defaultXperiaPlay[] = { {VIRTKEY_AXIS_Y_MAX, JOYSTICK_AXIS_Y, +1}, }; -enum DefaultMaps { - DEFAULT_MAPPING_KEYBOARD, - DEFAULT_MAPPING_X360, - DEFAULT_MAPPING_PAD, - DEFAULT_MAPPING_SHIELD, - DEFAULT_MAPPING_OUYA, -}; - - -static void AddDefaultKeyMap(int deviceId, const DefMappingStruct *array, int count, bool replace) { +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); @@ -179,27 +172,20 @@ static void AddDefaultKeyMap(int deviceId, const DefMappingStruct *array, int co } } -void AddDefaultKeyMap(DefaultMaps dmap, bool replace) { +void SetDefaultKeyMap(DefaultMaps dmap, bool replace) { switch (dmap) { case DEFAULT_MAPPING_KEYBOARD: - AddDefaultKeyMap(DEVICE_ID_KEYBOARD, defaultKeyboardKeyMap, ARRAY_SIZE(defaultKeyboardKeyMap), replace); + SetDefaultKeyMap(DEVICE_ID_KEYBOARD, defaultKeyboardKeyMap, ARRAY_SIZE(defaultKeyboardKeyMap), replace); break; case DEFAULT_MAPPING_X360: - AddDefaultKeyMap(DEVICE_ID_X360_0, default360KeyMap, ARRAY_SIZE(default360KeyMap), replace); + SetDefaultKeyMap(DEVICE_ID_X360_0, default360KeyMap, ARRAY_SIZE(default360KeyMap), replace); break; case DEFAULT_MAPPING_SHIELD: - AddDefaultKeyMap(DEVICE_ID_X360_0, defaultShieldKeyMap, ARRAY_SIZE(defaultShieldKeyMap), replace); + SetDefaultKeyMap(DEVICE_ID_X360_0, defaultShieldKeyMap, ARRAY_SIZE(defaultShieldKeyMap), replace); break; } } -ControllerMap g_controllerMap; - -// Key & Button names -struct KeyMap_IntStrPair { - int key; - std::string name; -}; const KeyMap_IntStrPair key_names[] = { {NKCODE_A, "A"}, @@ -448,6 +434,10 @@ std::string GetKeyName(int keyCode) { 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)); } @@ -463,8 +453,8 @@ std::vector GetMappableKeys() { 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; @@ -481,7 +471,7 @@ KeyDef AxisDef(int deviceId, int axisId, int direction) { static bool FindKeyMapping(int deviceId, int key, int *psp_button) { // Brute force, let's optimize later - for (auto iter = g_controllerMap.keys.begin(); iter != g_controllerMap.keys.end(); ++iter) { + 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; @@ -492,8 +482,7 @@ static bool FindKeyMapping(int deviceId, int key, int *psp_button) { return false; } -int KeyToPspButton(int deviceId, int key) -{ +int KeyToPspButton(int deviceId, int key) { int search_start_layer = 0; int psp_button; @@ -504,16 +493,13 @@ int KeyToPspButton(int deviceId, int key) } // TODO: vector output -bool KeyFromPspButton(int btn, std::vector *devices, std::vector *keyCodes) { +bool KeyFromPspButton(int btn, std::vector *keys) { int search_start_layer = 0; - for (auto iter = g_controllerMap.keys.begin(); iter != g_controllerMap.keys.end(); ++iter) { + 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) { - // For now: Grab the first one. - devices->push_back(iter2->deviceId); - keyCodes->push_back(iter2->keyCode); - return true; + keys->push_back(*iter2); } } } @@ -528,7 +514,7 @@ int AxisToPspButton(int deviceId, int axisId, int direction) { bool AxisFromPspButton(int btn, int *deviceId, int *axisId, int *direction) { int search_start_layer = 0; - for (auto iter = g_controllerMap.keys.begin(); iter != g_controllerMap.keys.end(); ++iter) { + 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; @@ -540,77 +526,32 @@ bool AxisFromPspButton(int btn, int *deviceId, int *axisId, int *direction) { return false; } -std::string NameKeyFromPspButton(int btn) { - int deviceId; - int axisId; - int direction; - if (AxisFromPspButton(btn, &deviceId, &axisId, &direction)) { - return GetAxisName(axisId) + (direction < 0 ? "-" : "+"); - } - std::vector deviceIds; - std::vector keyCodes; - if (KeyFromPspButton(btn, &deviceIds, &keyCodes)) { - return GetKeyName(keyCodes[0]); - } - return "unknown"; -} - -std::string NameDeviceFromPspButton(int btn) { - int deviceId; - int axisId; - int direction; - if (AxisFromPspButton(btn, &deviceId, &axisId, &direction)) { - return GetDeviceName(deviceId); - } - std::vector deviceIds; - std::vector keyCodes; - if (KeyFromPspButton(btn, &deviceIds, &keyCodes)) { - return GetDeviceName(deviceIds[0]); - } - 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 btn) { - for (auto iter = g_controllerMap.keys.begin(); iter != g_controllerMap.keys.end(); ++iter) { + for (auto iter = g_controllerMap.begin(); iter != g_controllerMap.end(); ++iter) { if (iter->first == btn) { - g_controllerMap.keys.erase(iter); + g_controllerMap.erase(iter); return; } } } void SetKeyMapping(int btn, KeyDef key, bool replace) { + if (key.keyCode < 0) + return; if (replace) { RemoveButtonMapping(btn); - g_controllerMap.keys[btn].clear(); - g_controllerMap.keys[btn].push_back(key); + g_controllerMap[btn].clear(); + g_controllerMap[btn].push_back(key); } else { - for (auto iter = g_controllerMap.keys[btn].begin(); iter != g_controllerMap.keys[btn].end(); ++iter) { + for (auto iter = g_controllerMap[btn].begin(); iter != g_controllerMap[btn].end(); ++iter) { if (*iter == key) return; } - g_controllerMap.keys[btn].push_back(key); + g_controllerMap[btn].push_back(key); } } -std::string GetAxisName(int axisId) { - return FindName(axisId, axis_names, ARRAY_SIZE(axis_names)); -} - -std::string NamePspButtonFromAxis(int deviceId, int axisId, int direction) { - int key = TranslateKeyCodeFromAxis(axisId, direction); - return GetPspButtonName(KeyToPspButton(deviceId, key)); -} - -void SetAxisMapping(int deviceId, int axisId, int direction, int btn, bool replace) { +void SetAxisMapping(int btn, int deviceId, int axisId, int direction, bool replace) { int key = TranslateKeyCodeFromAxis(axisId, direction); SetKeyMapping(btn, KeyDef(deviceId, key), replace); } @@ -618,25 +559,16 @@ void SetAxisMapping(int deviceId, int axisId, int direction, int btn, bool repla // Note that it's easy to add other defaults if desired. void RestoreDefault() { #if defined(_WIN32) - AddDefaultKeyMap(DEFAULT_MAPPING_KEYBOARD, true); - AddDefaultKeyMap(DEFAULT_MAPPING_X360, false); + SetDefaultKeyMap(DEFAULT_MAPPING_KEYBOARD, true); + SetDefaultKeyMap(DEFAULT_MAPPING_X360, false); #elif defined(ANDROID) - AddDefaultKeyMap(DEFAULT_MAPPING_PAD, true); + SetDefaultKeyMap(DEFAULT_MAPPING_PAD, true); #else - AddDefaultKeyMap(DEFAULT_MAPPING_KEYBOARD, true); - AddDefaultKeyMap(DEFAULT_MAPPING_PAD, false); + SetDefaultKeyMap(DEFAULT_MAPPING_KEYBOARD, true); + SetDefaultKeyMap(DEFAULT_MAPPING_PAD, false); #endif } -// BEGIN unused code to delete - -bool IsMappedAxis(int deviceId, int axisId, int direction) { - int key = TranslateKeyCodeFromAxis(axisId, direction); - return KeyToPspButton(deviceId, key) != KEYMAP_ERROR_UNKNOWN_KEY; -} - -// END unused code - // TODO: Make the ini format nicer. void LoadFromIni(IniFile &file) { RestoreDefault(); @@ -653,7 +585,7 @@ void LoadFromIni(IniFile &file) { if (value.empty()) continue; // Erase default mapping - g_controllerMap.keys.erase(psp_button_names[i].key); + g_controllerMap.erase(psp_button_names[i].key); std::vector mappings; SplitString(value, ',', mappings); @@ -667,22 +599,22 @@ void LoadFromIni(IniFile &file) { SetKeyMapping(psp_button_names[i].key, KeyDef(deviceId, keyCode), false); } } + return; } void SaveToIni(IniFile &file) { IniFile::Section *controls = file.GetOrCreateSection("ControlMapping"); for (int i = 0; i < ARRAY_SIZE(psp_button_names); i++) { - std::vector devices; - std::vector keycodes; - KeyFromPspButton(psp_button_names[i].key, &devices, &keycodes); + std::vector keys; + KeyFromPspButton(psp_button_names[i].key, &keys); std::string value; - for (size_t j = 0; j < devices.size(); j++) { + for (size_t j = 0; j < keys.size(); j++) { char temp[128]; - sprintf(temp, "%i-%i", devices[j], keycodes[j]); + sprintf(temp, "%i-%i", keys[j].deviceId, keys[j].keyCode); value += temp; - if (j != devices.size() - 1) + if (j != keys.size() - 1) value += ","; } diff --git a/Common/KeyMap.h b/Common/KeyMap.h index a0dd5ac645..dbbeb5c5c9 100644 --- a/Common/KeyMap.h +++ b/Common/KeyMap.h @@ -44,6 +44,14 @@ 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 { @@ -82,18 +90,6 @@ struct AxisPos { typedef std::map> KeyMapping; - -// These are for speed only, built from the regular ones. For the future. -// typedef std::map KeyMapping; - - -// Multiple maps can be active at the same time. -struct ControllerMap { - KeyMapping keys; -}; - -extern ControllerMap g_controllerMap; - // KeyMap // A translation layer for key assignment. Provides // integration with Core's config state. @@ -107,10 +103,20 @@ extern ControllerMap g_controllerMap; 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 GetPspButtonName(int btn); + std::vector GetMappableKeys(); + // Use if to translate KeyMap Keys to PSP // buttons. You should have already translated // your platform's keys to KeyMap keys. @@ -119,13 +125,9 @@ namespace KeyMap { // for any unmapped key int KeyToPspButton(int deviceId, int key); - bool IsMappedKey(int deviceId, int key); + int TranslateKeyCodeFromAxis(int axisId, int direction); - // Might be useful if you want to provide hints to users - // about mapping conflicts - std::string NamePspButtonFromKey(int deviceId, int key); - - bool KeyFromPspButton(int btn, std::vector *devices, std::vector *keyCodes); + bool KeyFromPspButton(int btn, std::vector *keys); std::string NameKeyFromPspButton(int btn); std::string NameDeviceFromPspButton(int btn); @@ -135,17 +137,18 @@ namespace KeyMap { // Configure an axis mapping, saves the configuration. // Direction is negative or positive. - void SetAxisMapping(int deviceId, int axisId, int direction, int btn, bool replace); + void SetAxisMapping(int btn, int deviceId, int axisId, int direction, bool replace); std::string GetAxisName(int axisId); int AxisToPspButton(int deviceId, int axisId, int direction); bool AxisFromPspButton(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 LoadFromIni(IniFile &iniFile); void SaveToIni(IniFile &iniFile); + void SetDefaultKeyMap(DefaultMaps dmap, bool replace); + void RestoreDefault(); void QuickMap(int device); } diff --git a/UI/ControlMappingScreen.cpp b/UI/ControlMappingScreen.cpp index 73c94f00d1..96b1f0d226 100644 --- a/UI/ControlMappingScreen.cpp +++ b/UI/ControlMappingScreen.cpp @@ -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,84 +33,162 @@ 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 ¶ms); + UI::EventReturn OnDelete(UI::EventParams ¶ms); + UI::EventReturn OnReplace(UI::EventParams ¶ms); + UI::EventReturn OnReplaceAll(UI::EventParams ¶ms); + + 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))); -#define KeyBtn(x, y, symbol) \ - if (UIButton(GEN_ID, Pos(x, y), 90, 0, KeyMap::NameKeyFromPspButton(symbol).c_str(), \ - ALIGN_TOPLEFT)) {\ - screenManager()->push(new KeyMappingNewKeyDialog(symbol), 0); \ - UIReset(); \ - } \ - UIText(0, Pos(x+30, y+50), KeyMap::NameDeviceFromPspButton(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); \ + std::vector mappings; + KeyMap::KeyFromPspButton(pspKey_, &mappings); - int pad = 130; - int hlfpad = pad / 2; + for (size_t i = 0; i < mappings.size(); i++) { + std::string deviceName = GetDeviceName(mappings[i].deviceId); + std::string keyName = KeyMap::GetKeyName(mappings[i].keyCode); + int image = -1; - int left = 30; - KeyBtn(left, 30, CTRL_LTRIGGER); + LinearLayout *row = rightColumn->Add(new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT))); - 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); } - UIEnd(); + if (mappings.size() == 0) { + // look like an empty line + rightColumn->Add(new Choice("", new LinearLayoutParams(WRAP_CONTENT, WRAP_CONTENT)))->OnClick.Handle(this, &ControlMapper::OnAdd); + } +} + +void ControlMapper::MappedCallback(KeyDef kdf) { + switch (action_) { + case REPLACEALL: + KeyMap::SetKeyMapping(pspKey_, kdf, true); + break; + case REPLACEONE: + KeyMap::g_controllerMap[pspKey_][actionIndex_] = kdf; + break; + } + refresh_ = true; +} + +UI::EventReturn ControlMapper::OnReplace(UI::EventParams ¶ms) { + 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 ¶ms) { + 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 ¶ms) { + KeyMap::g_controllerMap[pspKey_].push_back(KeyDef(0, 0)); + refresh_ = true; + return UI::EVENT_DONE; +} + +UI::EventReturn ControlMapper::OnDelete(UI::EventParams ¶ms) { + actionIndex_ = atoi(params.v->Tag().c_str()); + KeyMap::g_controllerMap[pspKey_].erase(KeyMap::g_controllerMap[pspKey_].begin() + actionIndex_); + 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(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 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 ¶ms) { + KeyMap::g_controllerMap.clear(); + + RecreateViews(); + return UI::EVENT_DONE; } void KeyMappingNewKeyDialog::CreatePopupContents(UI::ViewGroup *parent) { @@ -120,10 +200,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(this->pspBtn_); - std::string buttonDevice = KeyMap::NameDeviceFromPspButton(this->pspBtn_); - parent->Add(new TextView(std::string(keyI18N->T("Previous:")) + " " + buttonKey + " - " + buttonDevice)); } void KeyMappingNewKeyDialog::key(const KeyInput &key) { @@ -132,19 +208,25 @@ void KeyMappingNewKeyDialog::key(const KeyInput &key) { return; } - KeyMap::SetKeyMapping(pspBtn_, KeyDef(key.deviceId, key.keyCode), replace_); + 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) { - KeyMap::SetAxisMapping(axis.deviceId, axis.axisId, 1, pspBtn_, replace_); + KeyDef kdf(axis.deviceId, KeyMap::TranslateKeyCodeFromAxis(axis.axisId, 1)); screenManager()->finishDialog(this, DR_OK); + if (callback_) + callback_(kdf); } if (axis.value < -AXIS_BIND_THRESHOLD) { - KeyMap::SetAxisMapping(axis.deviceId, axis.axisId, -1, pspBtn_, replace_); + KeyDef kdf(axis.deviceId, KeyMap::TranslateKeyCodeFromAxis(axis.axisId, -1)); screenManager()->finishDialog(this, DR_OK); + if (callback_) + callback_(kdf); } } diff --git a/UI/ControlMappingScreen.h b/UI/ControlMappingScreen.h index 04ee782cb4..a27976a63c 100644 --- a/UI/ControlMappingScreen.h +++ b/UI/ControlMappingScreen.h @@ -15,20 +15,25 @@ // 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 UIScreenWithBackground { public: - KeyMappingScreen() : Screen() {} - void update(InputState &input); - void render(); + ControlMappingScreen() {} +protected: + virtual void CreateViews(); + +private: + UI::EventReturn OnClearMapping(UI::EventParams ¶ms); }; -// Dialog box, meant to be pushed class KeyMappingNewKeyDialog : public PopupScreen { public: - explicit KeyMappingNewKeyDialog(int btn, bool replace = false) : PopupScreen("Map Key") { + explicit KeyMappingNewKeyDialog(int btn, bool replace, std::function callback) : PopupScreen("Map Key"), callback_(callback) { pspBtn_ = btn; } @@ -41,7 +46,9 @@ protected: virtual bool FillVertical() { return false; } virtual bool ShowButtons() { return false; } virtual void OnCompleted(DialogResult result) {} + private: int pspBtn_; bool replace_; + std::function callback_; }; diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp index 7ca1dfdac8..26baeabdd4 100644 --- a/UI/GameSettingsScreen.cpp +++ b/UI/GameSettingsScreen.cpp @@ -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) { @@ -386,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; } diff --git a/UI/MenuScreens.cpp b/UI/MenuScreens.cpp index b5ea4b063d..fc6b134245 100644 --- a/UI/MenuScreens.cpp +++ b/UI/MenuScreens.cpp @@ -711,10 +711,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(); diff --git a/native b/native index 4a1c3c4f83..5422dead6a 160000 --- a/native +++ b/native @@ -1 +1 @@ -Subproject commit 4a1c3c4f83ee1f3ba4b0bc63d3d82b7a698df519 +Subproject commit 5422dead6ab36cd450bf02c4d2ec9350a5943b8c From edb0614a5912c968a80c4d94932504673154bebe Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 17 Aug 2013 11:18:45 +0200 Subject: [PATCH 4/6] Fix analog axis names. Make L2/R2 on x360 controllers analog. Also slightly nicer behaviour - don't create empty mapping, instead ask for mappings immediately. --- Common/KeyMap.cpp | 43 +++++++++++++++++++++++++------------ Common/KeyMap.h | 11 +++++----- UI/ControlMappingScreen.cpp | 13 ++++++----- Windows/ControlMapping.h | 3 --- Windows/XinputDevice.cpp | 23 ++++++++++++++------ 5 files changed, 58 insertions(+), 35 deletions(-) diff --git a/Common/KeyMap.cpp b/Common/KeyMap.cpp index 4c245eaed4..c082b1c173 100644 --- a/Common/KeyMap.cpp +++ b/Common/KeyMap.cpp @@ -77,9 +77,10 @@ static const DefMappingStruct default360KeyMap[] = { {CTRL_SELECT , NKCODE_BUTTON_SELECT}, {CTRL_LTRIGGER , NKCODE_BUTTON_L1}, {CTRL_RTRIGGER , NKCODE_BUTTON_R1}, - {VIRTKEY_UNTHROTTLE , NKCODE_BUTTON_R2}, + {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[] = { @@ -391,33 +392,33 @@ const KeyMap_IntStrPair axis_names[] = { static std::string unknown_key_name = "??"; const KeyMap_IntStrPair psp_button_names[] = { - {CTRL_CIRCLE, "Circle"}, - {CTRL_CROSS, "Cross"}, - {CTRL_SQUARE, "Square"}, - {CTRL_TRIANGLE, "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_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_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"}, }; const int AXIS_BIND_NKCODE_START = 4000; @@ -434,6 +435,20 @@ std::string GetKeyName(int keyCode) { return FindName(keyCode, key_names, ARRAY_SIZE(key_names)); } +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)); } diff --git a/Common/KeyMap.h b/Common/KeyMap.h index dbbeb5c5c9..40a7cbc3cf 100644 --- a/Common/KeyMap.h +++ b/Common/KeyMap.h @@ -113,6 +113,8 @@ namespace KeyMap { // 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 GetMappableKeys(); @@ -124,12 +126,10 @@ namespace KeyMap { // Returns KEYMAP_ERROR_UNKNOWN_KEY // for any unmapped key int KeyToPspButton(int deviceId, int key); - - int TranslateKeyCodeFromAxis(int axisId, int direction); - bool KeyFromPspButton(int btn, std::vector *keys); - std::string NameKeyFromPspButton(int btn); - std::string NameDeviceFromPspButton(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. @@ -139,7 +139,6 @@ namespace KeyMap { // Direction is negative or positive. void SetAxisMapping(int btn, int deviceId, int axisId, int direction, bool replace); - std::string GetAxisName(int axisId); 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); diff --git a/UI/ControlMappingScreen.cpp b/UI/ControlMappingScreen.cpp index 96b1f0d226..fd853e51f7 100644 --- a/UI/ControlMappingScreen.cpp +++ b/UI/ControlMappingScreen.cpp @@ -92,7 +92,7 @@ void ControlMapper::Refresh() { for (size_t i = 0; i < mappings.size(); i++) { std::string deviceName = GetDeviceName(mappings[i].deviceId); - std::string keyName = KeyMap::GetKeyName(mappings[i].keyCode); + 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))); @@ -117,6 +117,9 @@ void ControlMapper::Refresh() { void ControlMapper::MappedCallback(KeyDef kdf) { switch (action_) { + case ADD: + KeyMap::SetKeyMapping(pspKey_, kdf, false); + break; case REPLACEALL: KeyMap::SetKeyMapping(pspKey_, kdf, true); break; @@ -141,14 +144,14 @@ UI::EventReturn ControlMapper::OnReplaceAll(UI::EventParams ¶ms) { } UI::EventReturn ControlMapper::OnAdd(UI::EventParams ¶ms) { - KeyMap::g_controllerMap[pspKey_].push_back(KeyDef(0, 0)); - refresh_ = true; + 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 ¶ms) { - actionIndex_ = atoi(params.v->Tag().c_str()); - KeyMap::g_controllerMap[pspKey_].erase(KeyMap::g_controllerMap[pspKey_].begin() + actionIndex_); + 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; } diff --git a/Windows/ControlMapping.h b/Windows/ControlMapping.h index ce495c5899..933a254a07 100644 --- a/Windows/ControlMapping.h +++ b/Windows/ControlMapping.h @@ -19,6 +19,3 @@ #include "InputDevice.h" -#define XBOX_CODE_LEFTTRIGGER 0x00010000 -#define XBOX_CODE_RIGHTTRIGGER 0x00020000 - diff --git a/Windows/XinputDevice.cpp b/Windows/XinputDevice.cpp index 5ab1781eff..a92790a34a 100644 --- a/Windows/XinputDevice.cpp +++ b/Windows/XinputDevice.cpp @@ -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; From 82b59a7e9dec7cff239a7a0034d287ae69aa163e Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 17 Aug 2013 11:47:56 +0200 Subject: [PATCH 5/6] Fix up/down/left/right ordering for analog sticks --- Common/KeyMap.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Common/KeyMap.cpp b/Common/KeyMap.cpp index c082b1c173..ff62589e60 100644 --- a/Common/KeyMap.cpp +++ b/Common/KeyMap.cpp @@ -405,20 +405,20 @@ const KeyMap_IntStrPair psp_button_names[] = { {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_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"}, - {VIRTKEY_AXIS_RIGHT_Y_MIN, "RightAn.Down"}, - {VIRTKEY_AXIS_RIGHT_Y_MAX, "RightAn.Up"}, }; const int AXIS_BIND_NKCODE_START = 4000; From f990df6af806f42e707a890b0bb0da6bf3b03c70 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 17 Aug 2013 12:09:50 +0200 Subject: [PATCH 6/6] Let the user escape the controls dialog with the global back button (Esc on PC) --- UI/ControlMappingScreen.h | 2 +- UI/GameScreen.h | 2 +- UI/MiscScreens.h | 4 ++-- native | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/UI/ControlMappingScreen.h b/UI/ControlMappingScreen.h index a27976a63c..4b8f709ff0 100644 --- a/UI/ControlMappingScreen.h +++ b/UI/ControlMappingScreen.h @@ -21,7 +21,7 @@ #include "UI/MiscScreens.h" -class ControlMappingScreen : public UIScreenWithBackground { +class ControlMappingScreen : public UIDialogScreenWithBackground { public: ControlMappingScreen() {} protected: diff --git a/UI/GameScreen.h b/UI/GameScreen.h index cd0ae57b7b..0e27495453 100644 --- a/UI/GameScreen.h +++ b/UI/GameScreen.h @@ -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) {} diff --git a/UI/MiscScreens.h b/UI/MiscScreens.h index 6d960aa247..cca70edd7c 100644 --- a/UI/MiscScreens.h +++ b/UI/MiscScreens.h @@ -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); }; diff --git a/native b/native index 5422dead6a..17996ccd4c 160000 --- a/native +++ b/native @@ -1 +1 @@ -Subproject commit 5422dead6ab36cd450bf02c4d2ec9350a5943b8c +Subproject commit 17996ccd4c133e2f930e9b7141875a6ed5e24558