From 13642a6cddd8657ec84a2bfa94c6ac7d34545dba Mon Sep 17 00:00:00 2001 From: Andrei Karas Date: Wed, 14 Nov 2012 16:55:35 +0300 Subject: Add support for on screen joystick for moving. --- data/graphics/gui/CMakeLists.txt | 1 + data/graphics/gui/Makefile.am | 1 + data/graphics/gui/dpad.xml | 9 ++++ data/graphics/gui/window.png | Bin 20056 -> 22491 bytes src/defaults.cpp | 2 + src/game.cpp | 45 ++++++++-------- src/game.h | 2 + src/gui/gui.cpp | 3 ++ src/gui/setup_input.cpp | 7 +++ src/gui/setup_input.h | 3 ++ src/inputmanager.cpp | 7 +-- src/keyboardconfig.cpp | 14 +++++ src/keyboardconfig.h | 4 ++ src/touchactions.cpp | 81 +++++++++++++++++++++++++++- src/touchactions.h | 8 +++ src/touchmanager.cpp | 113 ++++++++++++++++++++++++++++----------- src/touchmanager.h | 28 ++++++++-- 17 files changed, 270 insertions(+), 58 deletions(-) create mode 100644 data/graphics/gui/dpad.xml diff --git a/data/graphics/gui/CMakeLists.txt b/data/graphics/gui/CMakeLists.txt index ea3312600..9f2f847da 100644 --- a/data/graphics/gui/CMakeLists.txt +++ b/data/graphics/gui/CMakeLists.txt @@ -13,6 +13,7 @@ SET (FILES circle-on.xml colors.xml complete_icon.xml + dpad.xml dropdown.xml dropdown_background.xml dropdown_pressed.xml diff --git a/data/graphics/gui/Makefile.am b/data/graphics/gui/Makefile.am index cd3f80397..69c07bda1 100644 --- a/data/graphics/gui/Makefile.am +++ b/data/graphics/gui/Makefile.am @@ -16,6 +16,7 @@ gui_DATA = \ circle-on.xml \ colors.xml \ complete_icon.xml \ + dpad.xml \ dropdown.xml \ dropdown_background.xml \ dropdown_pressed.xml \ diff --git a/data/graphics/gui/dpad.xml b/data/graphics/gui/dpad.xml new file mode 100644 index 000000000..79ba00907 --- /dev/null +++ b/data/graphics/gui/dpad.xml @@ -0,0 +1,9 @@ + + + + diff --git a/data/graphics/gui/window.png b/data/graphics/gui/window.png index 54455fa9d..e98b2aae9 100644 Binary files a/data/graphics/gui/window.png and b/data/graphics/gui/window.png differ diff --git a/src/defaults.cpp b/src/defaults.cpp index 8411b06da..9a639d3c5 100644 --- a/src/defaults.cpp +++ b/src/defaults.cpp @@ -107,9 +107,11 @@ DefaultsData* getConfigDefaults() #ifdef ANDROID AddDEF("screenwidth", 0); AddDEF("screenheight", 0); + AddDEF("showScreenJoystick", true); #else AddDEF("screenwidth", defaultScreenWidth); AddDEF("screenheight", defaultScreenHeight); + AddDEF("showScreenJoystick", false); #endif AddDEF("screen", false); AddDEF("hwaccel", false); diff --git a/src/game.cpp b/src/game.cpp index df23a0146..3ed71efcb 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -828,27 +828,30 @@ void Game::handleMove() } if (!inputManager.isActionActive(Input::KEY_EMOTE) || direction == 0) - { - if (!viewport->getCameraMode()) - { - player_node->specialMove(direction); - } - else - { - int dx = 0; - int dy = 0; - if (direction & Being::LEFT) - dx = -5; - else if (direction & Being::RIGHT) - dx = 5; - - if (direction & Being::UP) - dy = -5; - else if (direction & Being::DOWN) - dy = 5; - viewport->moveCamera(dx, dy); - } - } + moveInDirection(direction); + } +} + +void Game::moveInDirection(const unsigned char direction) +{ + if (!viewport->getCameraMode()) + { + player_node->specialMove(direction); + } + else + { + int dx = 0; + int dy = 0; + if (direction & Being::LEFT) + dx = -5; + else if (direction & Being::RIGHT) + dx = 5; + + if (direction & Being::UP) + dy = -5; + else if (direction & Being::DOWN) + dy = 5; + viewport->moveCamera(dx, dy); } } diff --git a/src/game.h b/src/game.h index 59fa68012..353729091 100644 --- a/src/game.h +++ b/src/game.h @@ -114,6 +114,8 @@ class Game final bool getValidSpeed() const A_WARN_UNUSED { return mValidSpeed; } + void moveInDirection(const unsigned char direction); + static bool createScreenshot(); static bool saveScreenshot(SDL_Surface *const screenshot); diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index f0171ede4..8d26acea8 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -661,7 +661,10 @@ void Gui::handleMouseInput() const gcn::MouseInput mouseInput = mInput->dequeueMouseInput(); if (touchManager.processEvent(mouseInput)) + { + mMouseInactivityTimer = 0; continue; + } // Save the current mouse state. It will be needed if modal focus // changes or modal mouse input focus changes. diff --git a/src/gui/setup_input.cpp b/src/gui/setup_input.cpp index 77c4fdb2a..ff3c1f49b 100644 --- a/src/gui/setup_input.cpp +++ b/src/gui/setup_input.cpp @@ -31,6 +31,7 @@ #include "gui/setupactiondata.h" #include "gui/widgets/button.h" +#include "gui/widgets/checkbox.h" #include "gui/widgets/layouthelper.h" #include "gui/widgets/listbox.h" #include "gui/widgets/scrollarea.h" @@ -98,6 +99,9 @@ Setup_Input::Setup_Input(const Widget2 *const widget) : mDefaultButton(new Button(this, _("Default"), "default", this)), mResetKeysButton(new Button(this, _("Reset all keys"), "resetkeys", this)), mTabs(new TabStrip(this, config.getIntValue("fontSize") + 10)), + mShowJoystick(config.getBoolValue("showScreenJoystick")), + mJoystickCheckBox(new CheckBox(this, + _("Show onscreen joystick"), mShowJoystick)), mKeySetting(false), mActionDataSize(new int [9]) { @@ -155,6 +159,7 @@ Setup_Input::Setup_Input(const Widget2 *const widget) : place(2, 6, mAssignKeyButton); place(3, 6, mUnassignKeyButton); place(4, 6, mDefaultButton); + place(0, 7, mJoystickCheckBox); int width = 600; if (config.getIntValue("screenwidth") >= 730) @@ -195,6 +200,8 @@ void Setup_Input::apply() "Resolve them, or gameplay may result in strange behaviour."), gettext(str1.c_str()), gettext(str2.c_str())), DIALOG_ERROR); } + mShowJoystick = mJoystickCheckBox->isSelected(); + config.setValue("showScreenJoystick", mShowJoystick); keyboard.setEnabled(true); inputManager.store(); } diff --git a/src/gui/setup_input.h b/src/gui/setup_input.h index 186c094be..6accafe27 100644 --- a/src/gui/setup_input.h +++ b/src/gui/setup_input.h @@ -31,6 +31,7 @@ #include class Button; +class CheckBox; class ListBox; class KeyListModel; class TabStrip; @@ -97,6 +98,8 @@ class Setup_Input final : public SetupTab Button *mDefaultButton; Button *mResetKeysButton; TabStrip *mTabs; + bool mShowJoystick; + CheckBox *mJoystickCheckBox; bool mKeySetting; /**< flag to check if key being set. */ diff --git a/src/inputmanager.cpp b/src/inputmanager.cpp index 244f9a9dd..9cf456143 100644 --- a/src/inputmanager.cpp +++ b/src/inputmanager.cpp @@ -27,6 +27,7 @@ #include "keyboardconfig.h" #include "keyboarddata.h" #include "localplayer.h" +#include "touchmanager.h" #include "gui/chatwindow.h" #include "gui/gui.h" @@ -280,9 +281,9 @@ bool InputManager::isActionActive(const int index) const { if (keyboard.isActionActive(index)) return true; - if (joystick) - return joystick->isActionActive(index); - return false; + if (joystick && joystick->isActionActive(index)) + return true; + return touchManager.isActionActive(index); } KeyFunction &InputManager::getKey(int index) diff --git a/src/keyboardconfig.cpp b/src/keyboardconfig.cpp index 043024796..1ee73471a 100644 --- a/src/keyboardconfig.cpp +++ b/src/keyboardconfig.cpp @@ -170,6 +170,13 @@ void KeyboardConfig::handleActicateKey(const SDL_Event &event) resetRepeat(key); } +void KeyboardConfig::handleActicateKey(const int key) +{ + if (key < -1 && key > -500) + mActiveKeys2[-key] = 1; + resetRepeat(key); +} + void KeyboardConfig::handleDeActicateKey(const SDL_Event &event) { const int key = getKeyValueFromEvent(event); @@ -178,6 +185,13 @@ void KeyboardConfig::handleDeActicateKey(const SDL_Event &event) resetRepeat(key); } +void KeyboardConfig::handleDeActicateKey(const int key) +{ + if (key < -1 && key > -500) + mActiveKeys2[-key] = 0; + resetRepeat(key); +} + void KeyboardConfig::handleRepeat(const int time) { for (KeyTimeMapIter it = mKeyTimeMap.begin(), it_end = mKeyTimeMap.end(); diff --git a/src/keyboardconfig.h b/src/keyboardconfig.h index e101a65e0..69d3b9db5 100644 --- a/src/keyboardconfig.h +++ b/src/keyboardconfig.h @@ -90,8 +90,12 @@ class KeyboardConfig final void handleActicateKey(const SDL_Event &event); + void handleActicateKey(const int key); + void handleDeActicateKey(const SDL_Event &event); + void handleDeActicateKey(const int key); + int getActionId(const SDL_Event &event) A_WARN_UNUSED; void handleRepeat(const int time); diff --git a/src/touchactions.cpp b/src/touchactions.cpp index 5fcaa1802..e201a7efb 100644 --- a/src/touchactions.cpp +++ b/src/touchactions.cpp @@ -20,7 +20,11 @@ #include "touchactions.h" +#include "being.h" +#include "game.h" +#include "keydata.h" #include "logger.h" +#include "touchmanager.h" #ifdef ANDROID #include @@ -28,9 +32,84 @@ #include "debug.h" +bool padClicked(false); + +#ifdef ANDROID void showKeyboard(const gcn::MouseInput &mouseInput) { -#ifdef ANDROID SDL_ANDROID_ToggleScreenKeyboardTextInput(nullptr); +} +#else +void showKeyboard(const gcn::MouseInput &mouseInput A_UNUSED) +{ +} #endif + +static void moveChar(int x, int y) +{ + Game *const game = Game::instance(); + if (!game) + return; + + static const int lim = 10; + x -= 50; + y -= 50; + + if (x > lim) + { + touchManager.setActionActive(Input::KEY_MOVE_LEFT, false); + touchManager.setActionActive(Input::KEY_MOVE_RIGHT, true); + } + else if (x < -lim) + { + touchManager.setActionActive(Input::KEY_MOVE_LEFT, true); + touchManager.setActionActive(Input::KEY_MOVE_RIGHT, false); + } + else + { + touchManager.setActionActive(Input::KEY_MOVE_LEFT, false); + touchManager.setActionActive(Input::KEY_MOVE_RIGHT, false); + } + if (y > lim) + { + touchManager.setActionActive(Input::KEY_MOVE_DOWN, true); + touchManager.setActionActive(Input::KEY_MOVE_UP, false); + } + else if (y < -lim) + { + touchManager.setActionActive(Input::KEY_MOVE_DOWN, false); + touchManager.setActionActive(Input::KEY_MOVE_UP, true); + } + else + { + touchManager.setActionActive(Input::KEY_MOVE_DOWN, false); + touchManager.setActionActive(Input::KEY_MOVE_UP, false); + } +} + +void padClick(const gcn::MouseInput &mouseInput) +{ + moveChar(mouseInput.getX(), mouseInput.getY()); + padClicked = true; +} + +void padEvents(const gcn::MouseInput &mouseInput) +{ + if (mouseInput.getType() == gcn::MouseInput::MOVED) + { + if (padClicked) + moveChar(mouseInput.getX(), mouseInput.getY()); + } +} + +void padOut(const gcn::MouseInput &mouseInput A_UNUSED) +{ + padClicked = false; + moveChar(50, 50); +} + +void padUp(const gcn::MouseInput &mouseInput A_UNUSED) +{ + padClicked = false; + moveChar(50, 50); } diff --git a/src/touchactions.h b/src/touchactions.h index 0c9cdd23a..b6d10dfc4 100644 --- a/src/touchactions.h +++ b/src/touchactions.h @@ -27,4 +27,12 @@ void showKeyboard(const gcn::MouseInput &mouseInput); +void padClick(const gcn::MouseInput &mouseInput); + +void padEvents(const gcn::MouseInput &mouseInput); + +void padOut(const gcn::MouseInput &mouseInput); + +void padUp(const gcn::MouseInput &mouseInput); + #endif diff --git a/src/touchmanager.cpp b/src/touchmanager.cpp index c2fd1ff00..4a992244c 100644 --- a/src/touchmanager.cpp +++ b/src/touchmanager.cpp @@ -20,6 +20,7 @@ #include "touchmanager.h" +#include "configuration.h" #include "graphics.h" #include "touchactions.h" @@ -29,7 +30,9 @@ TouchManager touchManager; -TouchManager::TouchManager() +TouchManager::TouchManager() : + mKeyboard(nullptr), + mPad(nullptr) { } @@ -41,10 +44,26 @@ TouchManager::~TouchManager() void TouchManager::init() { #ifdef ANDROID + loadTouchItem(&mKeyboard, "keyboard_icon.xml", false, + nullptr, nullptr, &showKeyboard, nullptr); +#endif + + if (config.getBoolValue("showScreenJoystick")) + { + loadTouchItem(&mPad, "dpad.xml", true, + &padEvents, &padClick, &padUp, &padOut); + } +} + +void TouchManager::loadTouchItem(TouchItem **item, std::string name, bool type, + TouchFuncPtr fAll, TouchFuncPtr fPressed, + TouchFuncPtr fReleased, TouchFuncPtr fOut) +{ + *item = nullptr; Theme *theme = Theme::instance(); if (!theme) return; - Skin *skin = theme->load("keyboard_icon.xml", ""); + Skin *const skin = theme->load(name, ""); if (skin) { const ImageRect &images = skin->getBorder(); @@ -53,44 +72,65 @@ void TouchManager::init() { image->incRef(); const int x = skin->getOption("x", 10); - const int y = skin->getOption("y", 10); + const int y = type ? (mainGraphics->mHeight - image->mBounds.h) / 2 + + skin->getOption("y", 10) : skin->getOption("y", 10); const int pad = skin->getPadding(); const int pad2 = 2 * pad; - TouchItem *keyboard = new TouchItem(gcn::Rectangle(x, y, + *item = new TouchItem(gcn::Rectangle(x, y, image->getWidth() + pad2, image->getHeight() + pad2), - image, x + pad, y + pad, nullptr, nullptr, &showKeyboard); - mObjects.push_back(keyboard); + image, x + pad, y + pad, fAll, fPressed, fReleased, fOut); + mObjects.push_back(*item); } theme->unload(skin); } -#endif } void TouchManager::clear() { +// unloadTouchItem(&mPad); +// unloadTouchItem(&mKeyboard); + for (TouchItemVectorCIter it = mObjects.begin(), it_end = mObjects.end(); it != it_end; ++ it) { - const TouchItem *const item = *it; + TouchItem *item = *it; if (item) { if (item->image) item->image->decRef(); - delete *it; + delete item; } } mObjects.clear(); } +void TouchManager::unloadTouchItem(TouchItem **item0) +{ + TouchItem *item = *item0; + if (item) + { + if (item->image) + item->image->decRef(); + delete item; + *item0 = nullptr; + } +} + void TouchManager::draw() { +// drawTouchItem(mPad); for (TouchItemVectorCIter it = mObjects.begin(), it_end = mObjects.end(); it != it_end; ++ it) { - const TouchItem *const item = *it; - if (item && item->image) - mainGraphics->drawImage(item->image, item->x, item->y); + drawTouchItem(*it); } +// drawTouchItem(mKeyboard); +} + +void TouchManager::drawTouchItem(const TouchItem *const item) const +{ + if (item && item->image) + mainGraphics->drawImage(item->image, item->x, item->y); } bool TouchManager::processEvent(const gcn::MouseInput &mouseInput) @@ -102,30 +142,43 @@ bool TouchManager::processEvent(const gcn::MouseInput &mouseInput) it != it_end; ++ it) { const TouchItem *const item = *it; - if (item && item->rect.isPointInRect(x, y)) + if (!item) + continue; + const gcn::Rectangle &rect = item->rect; + if (rect.isPointInRect(x, y)) { + gcn::MouseInput event = mouseInput; + event.setX(event.getX() - item->x); + event.setY(event.getY() - item->y); if (item->funcAll) + item->funcAll(event); + + switch (mouseInput.getType()) { - item->funcAll(mouseInput); - } - else - { - switch (mouseInput.getType()) - { - case gcn::MouseInput::PRESSED: - if (item->funcPressed) - item->funcPressed(mouseInput); - break; - case gcn::MouseInput::RELEASED: - if (item->funcReleased) - item->funcReleased(mouseInput); - break; - default: - break; - } + case gcn::MouseInput::PRESSED: + if (item->funcPressed) + item->funcPressed(event); + break; + case gcn::MouseInput::RELEASED: + if (item->funcReleased) + item->funcReleased(event); + break; + default: + break; } return true; } + else if (item->funcOut) + { + item->funcOut(mouseInput); + } } return false; } + +bool TouchManager::isActionActive(const int index) const +{ + if (index < 0 || index > actionsSize) + return false; + return mActions[index]; +} diff --git a/src/touchmanager.h b/src/touchmanager.h index 97d7d5625..ae25d9a8c 100644 --- a/src/touchmanager.h +++ b/src/touchmanager.h @@ -34,18 +34,21 @@ typedef void (*TouchFuncPtr) (const gcn::MouseInput &mouseInput); +const int actionsSize = 10; + struct TouchItem final { TouchItem(const gcn::Rectangle rect0, Image *const img, int x0, int y0, TouchFuncPtr ptrAll, TouchFuncPtr ptrPressed, - TouchFuncPtr ptrReleased) : + TouchFuncPtr ptrReleased, TouchFuncPtr ptrOut) : rect(rect0), image(img), x(x0), y(y0), funcAll(ptrAll), funcPressed(ptrPressed), - funcReleased(ptrReleased) + funcReleased(ptrReleased), + funcOut(ptrOut) { } @@ -58,6 +61,7 @@ struct TouchItem final TouchFuncPtr funcAll; TouchFuncPtr funcPressed; TouchFuncPtr funcReleased; + TouchFuncPtr funcOut; }; typedef std::vector TouchItemVector; @@ -74,15 +78,33 @@ class TouchManager final void init(); + void loadTouchItem(TouchItem **item, std::string name, bool type, + TouchFuncPtr fAll, TouchFuncPtr fPressed, + TouchFuncPtr fReleased, TouchFuncPtr fOut); + void clear(); + void unloadTouchItem(TouchItem **item0); + void draw(); + void drawTouchItem(const TouchItem *const item) const; + bool processEvent(const gcn::MouseInput &mouseInput); + bool isActionActive(const int index) const; + + void setActionActive(const int index, const bool value) + { + if (index >= 0 && index < actionsSize) + mActions[index] = value; + } + private: + TouchItem *mKeyboard; + TouchItem *mPad; TouchItemVector mObjects; -// std::map mNameToRect; + bool mActions[actionsSize]; }; extern TouchManager touchManager; -- cgit v1.2.3-70-g09d2