summaryrefslogtreecommitdiff
path: root/src/inputmanager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/inputmanager.cpp')
-rw-r--r--src/inputmanager.cpp803
1 files changed, 0 insertions, 803 deletions
diff --git a/src/inputmanager.cpp b/src/inputmanager.cpp
deleted file mode 100644
index c04185f50..000000000
--- a/src/inputmanager.cpp
+++ /dev/null
@@ -1,803 +0,0 @@
-/*
- * The ManaPlus Client
- * Copyright (C) 2012-2013 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 <http://www.gnu.org/licenses/>.
- */
-
-#include "inputmanager.h"
-
-#include "client.h"
-#include "configuration.h"
-#include "game.h"
-#include "joystick.h"
-#include "keyboardconfig.h"
-#include "keyboarddata.h"
-#include "localplayer.h"
-#include "touchmanager.h"
-
-#include "gui/chatwindow.h"
-#include "gui/gui.h"
-#include "gui/inventorywindow.h"
-#include "gui/npcdialog.h"
-#include "gui/npcpostdialog.h"
-#include "gui/sdlinput.h"
-#include "gui/setup.h"
-#include "gui/setup_input.h"
-#include "gui/textdialog.h"
-#include "gui/tradewindow.h"
-
-#include <guichan/exception.hpp>
-#include <guichan/focushandler.hpp>
-
-#include <algorithm>
-
-#include "debug.h"
-
-InputManager inputManager;
-
-extern QuitDialog *quitDialog;
-
-static class KeyFunctor final
-{
- public:
- bool operator() (const int key1, const int key2) const
- {
- return keys[key1].priority >= keys[key2].priority;
- }
-
- const KeyData *keys;
-} keyDataSorter;
-
-
-InputManager::InputManager() :
- mSetupInput(nullptr),
- mNewKeyIndex(Input::KEY_NO_VALUE),
- mMask(1),
- mNameMap()
-{
-}
-
-void InputManager::init()
-{
- for (unsigned int i = 0; i < Input::KEY_TOTAL; i++)
- {
- KeyFunction &kf = mKey[i];
- for (unsigned int f = 0; f < KeyFunctionSize; f ++)
- {
- KeyItem &ki = kf.values[f];
- ki.type = INPUT_UNKNOWN;
- ki.value = -1;
- }
- }
-
- mNewKeyIndex = Input::KEY_NO_VALUE;
-
- resetKeys();
- retrieve();
- update();
-}
-
-void InputManager::update() const
-{
- keyboard.update();
- if (joystick)
- joystick->update();
-}
-
-void InputManager::retrieve()
-{
- for (int i = 0; i < Input::KEY_TOTAL; i++)
- {
-#ifdef USE_SDL2
- const std::string cf = std::string("sdl2") + keyData[i].configField;
-#else
- const std::string cf = keyData[i].configField;
-#endif
- if (!cf.empty())
- {
- mNameMap[cf] = i;
- KeyFunction &kf = mKey[i];
- const std::string keyStr = config.getValue(cf, "");
- const int keyStrSize = keyStr.size();
- if (keyStr.empty())
- continue;
-
- StringVect keys;
- splitToStringVector(keys, keyStr, ',');
- unsigned int i2 = 0;
- for (StringVectCIter it = keys.begin(), it_end = keys.end();
- it != it_end && i2 < KeyFunctionSize; ++ it)
- {
- std::string keyStr2 = *it;
- if (keyStrSize < 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);
- }
- const int key = atoi(keyStr2.c_str());
- if (key >= -255 && key < SDLK_LAST)
- {
- kf.values[i2] = KeyItem(type, key);
- i2 ++;
- }
- }
- }
- }
-}
-
-void InputManager::store() const
-{
- for (int i = 0; i < Input::KEY_TOTAL; i++)
- {
-#ifdef USE_SDL2
- const std::string cf = std::string("sdl2") + keyData[i].configField;
-#else
- const std::string cf = keyData[i].configField;
-#endif
- if (!cf.empty())
- {
- std::string keyStr;
- const KeyFunction &kf = mKey[i];
-
- for (size_t i2 = 0; i2 < KeyFunctionSize; i2 ++)
- {
- const KeyItem &key = kf.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 != -1)
- {
- if (keyStr.empty())
- {
- keyStr.append(tmp).append(toString(key.value));
- }
- else
- {
- keyStr.append(strprintf(",%s%d",
- tmp.c_str(), key.value));
- }
- }
- }
- }
- if (keyStr.empty())
- keyStr = "-1";
-
- config.setValue(cf, keyStr);
- }
- }
-}
-
-void InputManager::resetKeys()
-{
- for (int i = 0; i < Input::KEY_TOTAL; i++)
- {
- KeyFunction &key = mKey[i];
- for (size_t i2 = 1; i2 < KeyFunctionSize; i2 ++)
- {
- KeyItem &ki2 = key.values[i2];
- ki2.type = INPUT_UNKNOWN;
- ki2.value = -1;
- }
- const KeyData &kd = keyData[i];
- KeyItem &val0 = key.values[0];
- val0.type = kd.defaultType1;
- KeyItem &val1 = key.values[1];
- val1.type = kd.defaultType2;
-#ifdef USE_SDL2
- if (kd.defaultType1 == INPUT_KEYBOARD)
- val0.value = SDL_GetScancodeFromKey(kd.defaultValue1);
- else
- val0.value = kd.defaultValue1;
- if (kd.defaultType2 == INPUT_KEYBOARD)
- val1.value = SDL_GetScancodeFromKey(kd.defaultValue2);
- else
- val1.value = kd.defaultValue2;
-#else
- val0.value = kd.defaultValue1;
- val1.value = kd.defaultValue2;
-#endif
- }
-}
-
-void InputManager::makeDefault(const int i)
-{
- if (i >= 0 && i < Input::KEY_TOTAL)
- {
- KeyFunction &key = mKey[i];
- for (size_t i2 = 1; i2 < KeyFunctionSize; i2 ++)
- {
- KeyItem &ki2 = key.values[i2];
- ki2.type = INPUT_UNKNOWN;
- ki2.value = -1;
- }
- const KeyData &kd = keyData[i];
- KeyItem &val0 = key.values[0];
- val0.type = kd.defaultType1;
- KeyItem &val1 = key.values[1];
- val1.type = kd.defaultType2;
-
-#ifdef USE_SDL2
- if (kd.defaultType1 == INPUT_KEYBOARD)
- val0.value = SDL_GetScancodeFromKey(kd.defaultValue1);
- else
- val0.value = kd.defaultValue1;
- if (kd.defaultType2 == INPUT_KEYBOARD)
- val1.value = SDL_GetScancodeFromKey(kd.defaultValue2);
- else
- val1.value = kd.defaultValue2;
-#else
- val0.value = kd.defaultValue1;
- val1.value = kd.defaultValue2;
-#endif
-
- update();
- }
-}
-
-bool InputManager::hasConflicts(int &key1, int &key2) const
-{
- /**
- * No need to parse the square matrix: only check one triangle
- * that's enough to detect conflicts
- */
- for (int i = 0; i < Input::KEY_TOTAL; i++)
- {
- const KeyData &kdi = keyData[i];
- if (!*kdi.configField)
- continue;
-
- const KeyFunction &ki = mKey[i];
- for (size_t i2 = 0; i2 < KeyFunctionSize; i2 ++)
- {
- const KeyItem &vali2 = ki.values[i2];
- if (vali2.value == Input::KEY_NO_VALUE)
- continue;
-
- size_t j;
- for (j = i, j++; j < Input::KEY_TOTAL; j++)
- {
- if ((kdi.grp & keyData[j].grp) == 0 || !*kdi.configField)
- continue;
-
- for (size_t j2 = 0; j2 < KeyFunctionSize; j2 ++)
- {
- const KeyItem &valj2 = mKey[j].values[j2];
- // Allow for item shortcut and emote keys to overlap
- // as well as emote and ignore keys, but no other keys
- if (valj2.type != INPUT_UNKNOWN
- && vali2.value == valj2.value
- && vali2.type == valj2.type)
- {
- key1 = static_cast<int>(i);
- key2 = static_cast<int>(j);
- return true;
- }
- }
- }
- }
- }
- return false;
-}
-
-void InputManager::callbackNewKey()
-{
- mSetupInput->newKeyCallback(mNewKeyIndex);
-}
-
-bool InputManager::isActionActive(const int index)
-{
- if (keyboard.isActionActive(index))
- return true;
- if (joystick && joystick->isActionActive(index))
- return true;
- return touchManager.isActionActive(index);
-}
-
-KeyFunction &InputManager::getKey(int index)
-{
- if (index < 0 || index >= Input::KEY_TOTAL)
- index = 0;
- return mKey[index];
-}
-
-std::string InputManager::getKeyStringLong(const int index) const
-{
- std::string keyStr;
- const KeyFunction &ki = mKey[index];
-
- for (size_t i = 0; i < KeyFunctionSize; i ++)
- {
- const KeyItem &key = ki.values[i];
- std::string str;
- if (key.type == INPUT_KEYBOARD)
- {
- if (key.value >= 0)
- {
- str = keyboard.getKeyName(key.value);
- }
- else if (key.value < -1)
- {
- // TRANSLATORS: long key name. must be short.
- str = strprintf(_("key_%d"), -key.value);
- }
- }
- else if (key.type == INPUT_JOYSTICK)
- {
- // TRANSLATORS: long joystick button name. must be short.
- str = strprintf(_("JButton%d"), key.value + 1);
- }
- if (!str.empty())
- {
- if (keyStr.empty())
- keyStr = str;
- else
- keyStr.append(" ").append(str);
- }
- }
-
- if (keyStr.empty())
- {
- // TRANSLATORS: unknown long key type
- return _("unknown key");
- }
- return keyStr;
-}
-
-std::string InputManager::getKeyValueString(const int index) const
-{
- std::string keyStr;
- const KeyFunction &ki = mKey[index];
-
- for (size_t i = 0; i < KeyFunctionSize; i ++)
- {
- const KeyItem &key = ki.values[i];
- std::string str;
- if (key.type == INPUT_KEYBOARD)
- {
- if (key.value >= 0)
- {
- str = keyboard.getKeyShortString(
- keyboard.getKeyName(key.value));
- }
- else if (key.value < -1)
- {
- // TRANSLATORS: short key name. must be very short.
- str = strprintf(_("key_%d"), -key.value);
- }
- }
- else if (key.type == INPUT_JOYSTICK)
- {
- // TRANSLATORS: short joystick button name. muse be very short
- str = strprintf(_("JB%d"), key.value + 1);
- }
- if (!str.empty())
- {
- if (keyStr.empty())
- keyStr = str;
- else
- keyStr.append(" ").append(str);
- }
- }
-
- if (keyStr.empty())
- {
- // TRANSLATORS: unknown short key type. must be short
- return _("u key");
- }
- return keyStr;
-}
-
-std::string InputManager::getKeyValueByName(const std::string &keyName)
-{
- const std::map<std::string, int>::const_iterator
- it = mNameMap.find(keyName);
-
- if (it == mNameMap.end())
- return std::string();
- return getKeyValueString((*it).second);
-}
-
-void InputManager::addActionKey(const int action, const int type,
- const int val)
-{
- if (action < 0 || action >= Input::KEY_TOTAL)
- return;
-
- int idx = -1;
- KeyFunction &key = mKey[action];
- for (size_t i = 0; i < KeyFunctionSize; i ++)
- {
- const KeyItem &val2 = key.values[i];
- if (val2.type == INPUT_UNKNOWN || (val2.type == type
- && val2.value == val))
- {
- idx = static_cast<int>(i);
- break;
- }
- }
- if (idx == -1)
- {
- for (size_t i = 1; i < KeyFunctionSize; i ++)
- {
- KeyItem &val1 = key.values[i - 1];
- KeyItem &val2 = key.values[i];
- val1.type = val2.type;
- val1.value = val2.value;
- }
- idx = KeyFunctionSize - 1;
- }
-
- key.values[idx] = KeyItem(type, val);
-}
-
-void InputManager::setNewKey(const SDL_Event &event, const int type)
-{
- int val = -1;
- if (type == INPUT_KEYBOARD)
- val = keyboard.getKeyValueFromEvent(event);
- else if (type == INPUT_JOYSTICK && joystick)
- val = joystick->getButtonFromEvent(event);
-
- if (val != -1)
- {
- addActionKey(mNewKeyIndex, type, val);
- update();
- }
-}
-
-void InputManager::unassignKey()
-{
- KeyFunction &key = mKey[mNewKeyIndex];
- for (size_t i = 0; i < KeyFunctionSize; i ++)
- {
- KeyItem &val = key.values[i];
- val.type = INPUT_UNKNOWN;
- val.value = -1;
- }
- update();
-}
-
-bool InputManager::handleAssignKey(const SDL_Event &event, const int type)
-{
- if (setupWindow && setupWindow->isWindowVisible() &&
- getNewKeyIndex() > Input::KEY_NO_VALUE)
- {
- setNewKey(event, type);
- callbackNewKey();
- setNewKeyIndex(Input::KEY_NO_VALUE);
- return true;
- }
- return false;
-}
-
-bool InputManager::handleEvent(const SDL_Event &event)
-{
- switch (event.type)
- {
- case SDL_KEYDOWN:
- {
- updateConditionMask();
- if (handleAssignKey(event, INPUT_KEYBOARD))
- return true;
-
- keyboard.handleActicateKey(event);
- // send straight to gui for certain windows
- if (quitDialog || TextDialog::isActive() ||
- NpcPostDialog::isActive())
- {
- try
- {
- if (guiInput)
- guiInput->pushInput(event);
- if (gui)
- gui->handleInput();
- }
- catch (const gcn::Exception &e)
- {
- const char *const err = e.getMessage().c_str();
- logger->log("Warning: guichan input exception: %s", err);
- }
- return true;
- }
- break;
- }
- case SDL_KEYUP:
- {
- updateConditionMask();
- keyboard.handleDeActicateKey(event);
- break;
- }
- case SDL_JOYBUTTONDOWN:
- {
- updateConditionMask();
-// joystick.handleActicateButton(event);
- if (handleAssignKey(event, INPUT_JOYSTICK))
- return true;
- break;
- }
- case SDL_JOYBUTTONUP:
- {
- updateConditionMask();
-// joystick.handleDeActicateButton(event);
- break;
- }
-#ifdef ANDROID
- case SDL_ACCELEROMETER:
- {
- break;
- }
-#endif
- default:
- break;
- }
-
- try
- {
- if (guiInput)
- guiInput->pushInput(event);
- }
- catch (const gcn::Exception &e)
- {
- const char *const err = e.getMessage().c_str();
- logger->log("Warning: guichan input exception: %s", err);
- }
- if (gui)
- {
- const bool res = gui->handleInput();
- if (res && event.type == SDL_KEYDOWN)
- return true;
- }
-
- switch (event.type)
- {
- case SDL_KEYDOWN:
- if (triggerAction(keyboard.getActionVector(event)))
- return true;
- break;
-
- case SDL_JOYBUTTONDOWN:
- if (joystick && joystick->validate())
- {
- if (triggerAction(joystick->getActionVector(event)))
- return true;
- }
- break;
-#ifdef ANDROID
- case SDL_ACCELEROMETER:
- {
- break;
- }
-#endif
- default:
- break;
- }
-
- return false;
-}
-
-void InputManager::handleRepeat() const
-{
- const int time = tick_time;
- keyboard.handleRepeat(time);
- if (joystick)
- joystick->handleRepeat(time);
-}
-
-void InputManager::updateConditionMask()
-{
- mMask = 1;
- if (keyboard.isEnabled())
- mMask |= COND_ENABLED;
- if ((!chatWindow || !chatWindow->isInputFocused()) &&
- !NpcDialog::isAnyInputFocused() &&
- !InventoryWindow::isAnyInputFocused() &&
- (!tradeWindow || !tradeWindow->isInpupFocused()))
- {
- mMask |= COND_NOINPUT;
- }
-
- if (!player_node || !player_node->getAway())
- mMask |= COND_NOAWAY;
-
- if (!setupWindow || !setupWindow->isWindowVisible())
- mMask |= COND_NOSETUP;
-
- if (Game::instance() && Game::instance()->getValidSpeed())
- mMask |= COND_VALIDSPEED;
-
- if (gui && !gui->getFocusHandler()->getModalFocused())
- mMask |= COND_NOMODAL;
-
- const NpcDialog *const dialog = NpcDialog::getActive();
- if (!dialog || !dialog->isTextInputFocused())
- mMask |= COND_NONPCINPUT;
-
- if (!player_node || !player_node->getDisableGameModifiers())
- mMask |= COND_EMODS;
-
- if (!isActionActive(Input::KEY_STOP_ATTACK)
- && !isActionActive(Input::KEY_UNTARGET))
- {
- mMask |= COND_NOTARGET;
- }
- if (Game::instance())
- mMask |= COND_INGAME;
-
- if (!player_node || player_node->getFollow().empty())
- mMask |= COND_NOFOLLOW;
-}
-
-bool InputManager::checkKey(const KeyData *const key) const
-{
-// logger->log("mask=%d, condition=%d", mMask, key->condition);
- if (!key || (key->condition & mMask) != key->condition)
- return false;
-
- return (key->modKeyIndex == Input::KEY_NO_VALUE
- || isActionActive(key->modKeyIndex));
-}
-
-bool InputManager::invokeKey(const KeyData *const key, const int keyNum)
-{
- // no validation to keyNum because it validated in caller
-
- if (checkKey(key))
- {
- InputEvent evt(keyNum, mMask);
- ActionFuncPtr func = *(keyData[keyNum].action);
- if (func && func(evt))
- return true;
- }
- return false;
-}
-
-void InputManager::executeAction(const int keyNum)
-{
- if (keyNum < 0 || keyNum >= Input::KEY_TOTAL)
- return;
-
- InputEvent evt(keyNum, mMask);
- ActionFuncPtr func = *(keyData[keyNum].action);
- if (func)
- func(evt);
-}
-
-void InputManager::updateKeyActionMap(KeyToActionMap &actionMap,
- KeyToIdMap &idMap,
- KeyTimeMap &keyTimeMap,
- const int type) const
-{
- actionMap.clear();
- keyTimeMap.clear();
-
- for (size_t i = 0; i < Input::KEY_TOTAL; i ++)
- {
- const KeyFunction &key = mKey[i];
- const KeyData &kd = keyData[i];
- if (kd.action)
- {
- for (size_t i2 = 0; i2 < KeyFunctionSize; i2 ++)
- {
- const KeyItem &ki = key.values[i2];
- if (ki.type == type && ki.value != -1)
- actionMap[ki.value].push_back(static_cast<int>(i));
- }
- }
- if (kd.configField && (kd.grp & Input::GRP_GUICHAN))
- {
- for (size_t i2 = 0; i2 < KeyFunctionSize; i2 ++)
- {
- const KeyItem &ki = key.values[i2];
- if (ki.type == type && ki.value != -1)
- idMap[ki.value] = static_cast<int>(i);
- }
- }
- if (kd.configField && (kd.grp & Input::GRP_REPEAT))
- {
- for (size_t i2 = 0; i2 < KeyFunctionSize; i2 ++)
- {
- const KeyItem &ki = key.values[i2];
- if (ki.type == type && ki.value != -1)
- keyTimeMap[ki.value] = 0;
- }
- }
- }
-
- keyDataSorter.keys = &keyData[0];
- FOR_EACH (KeyToActionMapIter, it, actionMap)
- {
- KeysVector *const keys = &it->second;
- if (keys && keys->size() > 1)
- std::sort(keys->begin(), keys->end(), keyDataSorter);
- }
-}
-
-bool InputManager::triggerAction(const KeysVector *const ptrs)
-{
- if (!ptrs)
- return false;
-
-// logger->log("ptrs: %d", (int)ptrs.size());
-
- FOR_EACHP (KeysVectorCIter, it, ptrs)
- {
- const int keyNum = *it;
- if (keyNum < 0 || keyNum >= Input::KEY_TOTAL)
- continue;
-
- if (invokeKey(&keyData[keyNum], keyNum))
- return true;
- }
- return false;
-}
-
-int InputManager::getKeyIndex(const int value, const int grp,
- const int type) const
-{
- for (size_t i = 0; i < Input::KEY_TOTAL; i++)
- {
- const KeyFunction &key = mKey[i];
- const KeyData &kd = keyData[i];
- for (size_t i2 = 0; i2 < KeyFunctionSize; i2 ++)
- {
- const KeyItem &vali2 = key.values[i2];
- if (value == vali2.value && (grp & kd.grp) != 0
- && vali2.type == type)
- {
- return static_cast<int>(i);
- }
- }
- }
- return Input::KEY_NO_VALUE;
-}
-
-int InputManager::getActionByKey(const SDL_Event &event) const
-{
- // for now support only keyboard events
- if (event.type == SDL_KEYDOWN || event.type == SDL_KEYUP)
- {
- const int idx = keyboard.getActionId(event);
- if (idx >= 0 && checkKey(&keyData[idx]))
- return idx;
- }
- return Input::KEY_NO_VALUE;
-}