From 3636f909023ea3b133b3341fcd7ed8c2f9f9bf80 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 17 Aug 2013 10:34:38 +0200 Subject: [PATCH] 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