From ad0fcc99678c13c6f6ebacead6ba2d573294163d Mon Sep 17 00:00:00 2001 From: Andrei Karas Date: Sun, 8 Apr 2012 02:53:09 +0300 Subject: Allow assign 3 keys to any action. --- src/CMakeLists.txt | 1 + src/Makefile.am | 1 + src/inputmanager.cpp | 3 +- src/inputmanager.h | 5 +- src/keyboardconfig.cpp | 310 ++++++++++++++++++++++++++++++++++++------------- src/keyboardconfig.h | 38 +++--- src/keyboarddata.h | 12 +- src/keydata.h | 40 +++++++ 8 files changed, 305 insertions(+), 105 deletions(-) create mode 100644 src/keydata.h (limited to 'src') diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0318d2fc2..959c1d5c6 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -568,6 +568,7 @@ SET(SRCS keyboardconfig.cpp keyboardconfig.h keyboarddata.h + keydata.h listener.cpp listener.h localconsts.h diff --git a/src/Makefile.am b/src/Makefile.am index 54911f281..90688a620 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -575,6 +575,7 @@ manaplus_SOURCES += gui/widgets/avatarlistbox.cpp \ keyboardconfig.cpp \ keyboardconfig.h \ keyboarddata.h \ + keydata.h \ listener.cpp \ listener.h \ localconsts.h \ diff --git a/src/inputmanager.cpp b/src/inputmanager.cpp index 5e30f3894..32c4ac1f1 100644 --- a/src/inputmanager.cpp +++ b/src/inputmanager.cpp @@ -22,6 +22,7 @@ #include "game.h" #include "keyboardconfig.h" +#include "keydata.h" #include "localplayer.h" #include "gui/chatwindow.h" @@ -150,7 +151,7 @@ int InputManager::getInputConditionMask() return mask; } -bool InputManager::checkKey(KeyFunction *key, int mask) +bool InputManager::checkKey(const KeyData *key, int mask) { // logger->log("mask=%d, condition=%d", mask, key->condition); if (!key || (key->condition & mask) != key->condition) diff --git a/src/inputmanager.h b/src/inputmanager.h index 7a6ac6d05..635e27a33 100644 --- a/src/inputmanager.h +++ b/src/inputmanager.h @@ -26,7 +26,8 @@ #include #include -struct KeyFunction; +struct KeyData; +//struct KeyFunction; enum KeyCondition { @@ -56,7 +57,7 @@ class InputManager int getInputConditionMask(); - bool checkKey(KeyFunction *key, int mask); + bool checkKey(const KeyData *key, int mask); }; extern InputManager inputManager; diff --git a/src/keyboardconfig.cpp b/src/keyboardconfig.cpp index 67d31f7a8..e2b226b5d 100644 --- a/src/keyboardconfig.cpp +++ b/src/keyboardconfig.cpp @@ -48,7 +48,7 @@ class KeyFunctor return keys[key1].priority >= keys[key2].priority; } - KeyFunction *keys; + const KeyData *keys; } keySorter; @@ -56,32 +56,17 @@ void KeyboardConfig::init() { for (int i = 0; i < KEY_TOTAL; i++) { - mKey[i].configField = keyData[i].configField; - mKey[i].defaultValue = keyData[i].defaultValue; -// mKey[i].caption = gettext(keyData[i].caption.c_str()); - mKey[i].value = KEY_NO_VALUE; - mKey[i].grp = keyData[i].grp; - mKey[i].action = keyData[i].action; - mKey[i].modKeyIndex = keyData[i].modKeyIndex; - mKey[i].priority = keyData[i].priority; - mKey[i].condition = keyData[i].condition; - } -/* - for (int i = KEY_EMOTE_1; i <= KEY_EMOTE_48; i ++) - { - mKey[i].caption = strprintf( - _("Emote Shortcut %d"), i - KEY_EMOTE_1 + 1); - } - for (int i = KEY_SHORTCUT_1; i <= KEY_SHORTCUT_20; i ++) - { - mKey[i].caption = strprintf( - _("Item Shortcut %d"), i - KEY_SHORTCUT_1 + 1); + for (int f = 0; f < KeyFunctionSize; f ++) + { + mKey[i].values[f].type = INPUT_UNKNOWN; + mKey[i].values[f].value = -1; + } } -*/ mNewKeyIndex = KEY_NO_VALUE; mEnabled = true; + makeDefault(); retrieve(); updateKeyActionMap(); } @@ -90,12 +75,45 @@ void KeyboardConfig::retrieve() { for (int i = 0; i < KEY_TOTAL; i++) { - if (*mKey[i].configField) + if (*keyData[i].configField) { - mKey[i].value = static_cast(config.getValue( - mKey[i].configField, mKey[i].defaultValue)); - if (mKey[i].value < -255 || mKey[i].value >= SDLK_LAST) - mKey[i].value = KEY_NO_VALUE; + KeyFunction &kf = mKey[i]; + std::string keyStr = config.getValue(keyData[i].configField, + toString(keyData[i].defaultValue)); + StringVect keys; + splitToStringVector(keys, keyStr, ','); + StringVectCIter it = keys.begin(); + StringVectCIter it_end = keys.end(); + int i2 = 0; + for (; it != it_end && i2 < KeyFunctionSize; ++ it) + { + std::string keyStr2 = *it; + if (keyStr.size() < 2) + continue; + int type = INPUT_KEYBOARD; + if ((keyStr2[0] < '0' || keyStr2[0] > '9') + && keyStr2[0] != '-') + { + switch (keyStr2[0]) + { + case 'm': + type = INPUT_MOUSE; + break; + case 'j': + type = INPUT_JOYSTICK; + break; + default: + break; + } + keyStr2 = keyStr2.substr(1); + } + int key = atoi(keyStr2.c_str()); + if (key >= -255 && key < SDLK_LAST) + { + kf.values[i2] = KeyItem(type, key); + i2 ++; + } + } } } } @@ -104,42 +122,102 @@ void KeyboardConfig::store() { for (int i = 0; i < KEY_TOTAL; i++) { - if (*mKey[i].configField) - config.setValue(mKey[i].configField, mKey[i].value); + if (*keyData[i].configField) + { + std::string keyStr; + + for (size_t i2 = 0; i2 < KeyFunctionSize; i2 ++) + { + const KeyItem &key = mKey[i].values[i2]; + if (key.type != INPUT_UNKNOWN) + { + std::string tmp = "k"; + switch(key.type) + { + case INPUT_MOUSE: + tmp = "m"; + break; + case INPUT_JOYSTICK: + tmp = "j"; + break; + default: + break; + } + if (key.value >= 0) + { + if (keyStr.empty()) + { + keyStr = tmp + toString(key.value); + } + else + { + keyStr += strprintf(",%s%d", tmp.c_str(), key.value); + } + } + } + } + if (keyStr.empty()) + keyStr = "-1"; + + config.setValue(keyData[i].configField, keyStr); + } } } void KeyboardConfig::makeDefault() { for (int i = 0; i < KEY_TOTAL; i++) - mKey[i].value = mKey[i].defaultValue; + { + for (size_t i2 = 1; i2 < KeyFunctionSize; i2 ++) + { + mKey[i].values[i2].type = INPUT_UNKNOWN; + mKey[i].values[i2].value = -1; + } + mKey[i].values[0].type = INPUT_KEYBOARD; + mKey[i].values[0].value = keyData[i].defaultValue; + } } bool KeyboardConfig::hasConflicts(int &key1, int &key2) { - int i, j; + size_t i; + size_t j; /** * No need to parse the square matrix: only check one triangle * that's enough to detect conflicts */ for (i = 0; i < KEY_TOTAL; i++) { - if (mKey[i].value == KEY_NO_VALUE || !*mKey[i].configField) + if (!*keyData[i].configField) continue; - for (j = i, j++; j < KEY_TOTAL; j++) + for (size_t i2 = 0; i2 < KeyFunctionSize; i2 ++) { - // Allow for item shortcut and emote keys to overlap - // as well as emote and ignore keys, but no other keys - if (mKey[j].value != KEY_NO_VALUE && - mKey[i].value == mKey[j].value && - ((mKey[i].grp & mKey[j].grp) != 0 && - *mKey[i].configField) - ) + if (mKey[i].values[i2].value == KEY_NO_VALUE) + continue; + + for (j = i, j++; j < KEY_TOTAL; j++) { - key1 = i; - key2 = j; - return true; + + if ((keyData[i].grp & keyData[j].grp) == 0 || + !*keyData[i].configField) + { + continue; + } + + for (size_t j2 = 0; j2 < KeyFunctionSize; j2 ++) + { + // Allow for item shortcut and emote keys to overlap + // as well as emote and ignore keys, but no other keys + if (mKey[j].values[j2].type != INPUT_UNKNOWN + && mKey[i].values[i2].value == mKey[j].values[j2].value + && mKey[i].values[i2].type == mKey[j].values[j2].type) + { + key1 = i; + key2 = j; + return true; + } + } } } } @@ -163,12 +241,16 @@ int KeyboardConfig::getKeyValueFromEvent(const SDL_Event &event) const int KeyboardConfig::getKeyIndex(const SDL_Event &event, int grp) const { const int keyValue = getKeyValueFromEvent(event); - for (int i = 0; i < KEY_TOTAL; i++) + for (size_t i = 0; i < KEY_TOTAL; i++) { - if (keyValue == mKey[i].value && - (grp & mKey[i].grp) != 0) + for (size_t i2 = 0; i2 < KeyFunctionSize; i2 ++) { - return i; + if (keyValue == mKey[i].values[i2].value + && (grp & keyData[i].grp) != 0 + && mKey[i].values[i2].type == INPUT_KEYBOARD) + { + return i; + } } } return KEY_NO_VALUE; @@ -178,11 +260,14 @@ bool KeyboardConfig::isActionActive(int index) const { if (!mActiveKeys) return false; - const int value = mKey[index].value; - if (value >= 0) - return mActiveKeys[value]; - else - return false; // scan codes active state now not implimented + + for (size_t i = 0; i < KeyFunctionSize; i ++) + { + const int value = mKey[index].values[i].value; + if (value >= 0 && mActiveKeys[value]) + return true; + } + return false; } void KeyboardConfig::refreshActiveKeys() @@ -192,32 +277,61 @@ void KeyboardConfig::refreshActiveKeys() std::string KeyboardConfig::getKeyStringLong(int index) const { - const int keyValue = getKeyValue(index); - if (keyValue >= 0) - return SDL_GetKeyName(static_cast(keyValue)); - else if (keyValue < -1) - return strprintf(_("key_%d"), -keyValue); - else + std::string keyStr; + + for (size_t i = 0; i < KeyFunctionSize; i ++) + { + const KeyItem &key = mKey[index].values[i]; + if (key.type == INPUT_KEYBOARD) + { + if (key.value >= 0) + { + if (keyStr.empty()) + { + keyStr = SDL_GetKeyName(static_cast(key.value)); + } + else + { + keyStr += std::string(" ") + SDL_GetKeyName( + static_cast(key.value)); + } + } + } + } + + if (keyStr.empty()) return _("unknown key"); + return keyStr; } std::string KeyboardConfig::getKeyValueString(int index) const { - const int keyValue = getKeyValue(index); - if (keyValue >= 0) - { - std::string key = SDL_GetKeyName(static_cast(keyValue)); - return getKeyShortString(key); - } - else if (keyValue < -1) + std::string keyStr; + + for (size_t i = 0; i < KeyFunctionSize; i ++) { - return strprintf("#%d", -keyValue); + const KeyItem &key = mKey[index].values[i]; + if (key.type == INPUT_KEYBOARD) + { + if (key.value >= 0) + { + if (keyStr.empty()) + { + keyStr = getKeyShortString(SDL_GetKeyName( + static_cast(key.value))); + } + else + { + keyStr += " " + getKeyShortString(SDL_GetKeyName( + static_cast(key.value))); + } + } + } } - else - { - // TRANSLATORS: Unknown key short string. This string must be maximum 5 chars + + if (keyStr.empty()) return _("u key"); - } + return keyStr; } std::string KeyboardConfig::getKeyShortString(const std::string &key) const @@ -241,13 +355,42 @@ SDLKey KeyboardConfig::getKeyFromEvent(const SDL_Event &event) const void KeyboardConfig::setNewKey(const SDL_Event &event) { - mKey[mNewKeyIndex].value = getKeyValueFromEvent(event); + int idx = -1; + KeyFunction &key = mKey[mNewKeyIndex]; + int val = getKeyValueFromEvent(event); + + for (size_t i = 0; i < KeyFunctionSize; i ++) + { + if (key.values[i].type == INPUT_UNKNOWN + || (key.values[i].type == INPUT_KEYBOARD + && key.values[i].value == val)) + { + idx = i; + break; + } + } + if (idx == -1) + { + for (size_t i = 1; i < KeyFunctionSize; i ++) + { + key.values[i - 1].type = key.values[i].type; + key.values[i - 1].value = key.values[i].value; + } + idx = KeyFunctionSize - 1; + } + + key.values[idx] = KeyItem(INPUT_KEYBOARD, val); updateKeyActionMap(); } void KeyboardConfig::unassignKey() { - mKey[mNewKeyIndex].value = KEY_NO_VALUE; + KeyFunction &key = mKey[mNewKeyIndex]; + for (size_t i = 0; i < KeyFunctionSize; i ++) + { + key.values[i].type = INPUT_UNKNOWN; + key.values[i].value = -1; + } updateKeyActionMap(); } @@ -255,13 +398,19 @@ void KeyboardConfig::updateKeyActionMap() { mKeyToAction.clear(); - for (int i = 0; i < KEY_TOTAL; i++) + for (size_t i = 0; i < KEY_TOTAL; i++) { - if (mKey[i].value != KEY_NO_VALUE && mKey[i].action) - mKeyToAction[mKey[i].value].push_back(i); + if (keyData[i].action) + { + for (size_t i2 = 0; i2 < KeyFunctionSize; i2 ++) + { + if (mKey[i].values[i2].type == INPUT_KEYBOARD) + mKeyToAction[mKey[i].values[i2].value].push_back(i); + } + } } - keySorter.keys = &mKey[0]; + keySorter.keys = &keyData[0]; KeyToActionMapIter it = mKeyToAction.begin(); KeyToActionMapIter it_end = mKeyToAction.end(); for (; it != it_end; ++ it) @@ -291,10 +440,10 @@ bool KeyboardConfig::triggerAction(const SDL_Event &event) if (keyNum < 0 || keyNum >= KEY_TOTAL) continue; - if (inputManager.checkKey(&mKey[keyNum], mask)) + if (inputManager.checkKey(&keyData[keyNum], mask)) { InputEvent evt(keyNum, mask); - if ((*(mKey[keyNum].action))(evt)) + if ((*(keyData[keyNum].action))(evt)) { return true; } @@ -303,3 +452,8 @@ bool KeyboardConfig::triggerAction(const SDL_Event &event) } return false; } + +int KeyboardConfig::getKeyValue(int index) const +{ + return mKey[index].values[0].value; +} diff --git a/src/keyboardconfig.h b/src/keyboardconfig.h index 3299dcf51..5ebbe075e 100644 --- a/src/keyboardconfig.h +++ b/src/keyboardconfig.h @@ -41,19 +41,35 @@ typedef KeysVector::const_iterator KeysVectorCIter; typedef std::map KeyToActionMap; typedef KeyToActionMap::iterator KeyToActionMapIter; +enum KeyTypes +{ + INPUT_UNKNOWN = 0, + INPUT_KEYBOARD = 1, + INPUT_MOUSE = 2, + INPUT_JOYSTICK = 3 +}; + +struct KeyItem +{ + KeyItem() : type(-1), value(-1) + { } + + KeyItem(int type0, int value0) : type(type0), value(value0) + { } + + int type; + + int value; +}; + +#define KeyFunctionSize 3 + /** * Each key represents a key function. Such as 'Move up', 'Attack' etc. */ struct KeyFunction { - const char* configField; /** Field index that is in the config file. */ - int defaultValue; /** The default key value used. */ - int value; /** The actual value that is used. */ - int grp; /** The key group */ - ActionFuncPtr action; /** The key action function */ - int modKeyIndex; /** Modifier what enable this key action */ - int priority; /** Action priority */ - int condition; /** Condition for allow use key */ + KeyItem values[KeyFunctionSize]; }; class Setup_Keyboard; @@ -94,11 +110,7 @@ class KeyboardConfig /** * Obtain the value stored in memory. */ - int getKeyValue(int index) const - { return mKey[index].value; } - - bool isSeparator(int index) const - { return !*mKey[index].configField; } + int getKeyValue(int index) const; /** * Get the index of the new key to be assigned. diff --git a/src/keyboarddata.h b/src/keyboarddata.h index b6ae17815..7ade46d6e 100644 --- a/src/keyboarddata.h +++ b/src/keyboarddata.h @@ -26,6 +26,7 @@ #include "actionmanager.h" #include "inputmanager.h" #include "keyboardconfig.h" +#include "keydata.h" #include "localconsts.h" #include "utils/gettext.h" @@ -33,17 +34,6 @@ #include -struct KeyData -{ - const char *configField; - int defaultValue; - int grp; - ActionFuncPtr action; - int modKeyIndex; - int priority; - int condition; -}; - // keyData must be in same order as enum keyAction. static KeyData const keyData[KeyboardConfig::KEY_TOTAL] = { {"keyMoveUp", SDLK_UP, diff --git a/src/keydata.h b/src/keydata.h new file mode 100644 index 000000000..841e0adaa --- /dev/null +++ b/src/keydata.h @@ -0,0 +1,40 @@ +/* + * Custom keyboard shortcuts configuration + * Copyright (C) 2007 Joshua Langley + * Copyright (C) 2009-2010 The Mana Developers + * Copyright (C) 2011-2012 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef KEYDATA_H +#define KEYDATA_H + +#include "actionmanager.h" + +#include + +struct KeyData +{ + const char *configField; + int defaultValue; + int grp; + ActionFuncPtr action; + int modKeyIndex; + int priority; + int condition; +}; +#endif -- cgit v1.2.3-60-g2f50