diff --git a/data/gui/init_android.stkgui b/data/gui/init_android.stkgui new file mode 100644 index 000000000..c8b8cb1db --- /dev/null +++ b/data/gui/init_android.stkgui @@ -0,0 +1,26 @@ + + +
+ + + + + + + + + + + + + + + +
+
+ +
+
diff --git a/lib/irrlicht/include/Keycodes.h b/lib/irrlicht/include/Keycodes.h index 568451baf..5b2f36afa 100644 --- a/lib/irrlicht/include/Keycodes.h +++ b/lib/irrlicht/include/Keycodes.h @@ -179,7 +179,27 @@ namespace irr IRR_KEY_PA1 = 0xFD, // PA1 key IRR_KEY_OEM_CLEAR = 0xFE, // Clear key - IRR_KEY_CODES_COUNT = 0xFF // this is not a key, but the amount of keycodes there are. + IRR_KEY_BUTTON_LEFT = 0x100, + IRR_KEY_BUTTON_RIGHT = 0x101, + IRR_KEY_BUTTON_UP = 0x102, + IRR_KEY_BUTTON_DOWN = 0x103, + IRR_KEY_BUTTON_A = 0x104, + IRR_KEY_BUTTON_B = 0x105, + IRR_KEY_BUTTON_C = 0x106, + IRR_KEY_BUTTON_X = 0x107, + IRR_KEY_BUTTON_Y = 0x108, + IRR_KEY_BUTTON_Z = 0x109, + IRR_KEY_BUTTON_L1 = 0x10A, + IRR_KEY_BUTTON_R1 = 0x10B, + IRR_KEY_BUTTON_L2 = 0x10C, + IRR_KEY_BUTTON_R2 = 0x10D, + IRR_KEY_BUTTON_THUMBL = 0x10E, + IRR_KEY_BUTTON_THUMBR = 0x10F, + IRR_KEY_BUTTON_START = 0x110, + IRR_KEY_BUTTON_SELECT = 0x111, + IRR_KEY_BUTTON_MODE = 0x112, + + IRR_KEY_CODES_COUNT = 0x113 // this is not a key, but the amount of keycodes there are. }; } // end namespace irr diff --git a/lib/irrlicht/source/Irrlicht/CIrrDeviceAndroid.cpp b/lib/irrlicht/source/Irrlicht/CIrrDeviceAndroid.cpp index 4e0c8d6d3..f717129ee 100644 --- a/lib/irrlicht/source/Irrlicht/CIrrDeviceAndroid.cpp +++ b/lib/irrlicht/source/Irrlicht/CIrrDeviceAndroid.cpp @@ -51,7 +51,7 @@ CIrrDeviceAndroid::CIrrDeviceAndroid(const SIrrlichtCreationParameters& param) IsMousePressed(false), GamepadAxisX(0), GamepadAxisY(0), - DefaultOrientation(0) + DefaultOrientation(ORIENTATION_UNKNOWN) { #ifdef _DEBUG setDebugName("CIrrDeviceAndroid"); @@ -64,8 +64,6 @@ CIrrDeviceAndroid::CIrrDeviceAndroid(const SIrrlichtCreationParameters& param) Android->onAppCmd = handleAndroidCommand; Android->onInputEvent = handleInput; - DefaultOrientation = getDefaultRotation(); - printConfig(); createKeyMap(); @@ -159,22 +157,6 @@ void CIrrDeviceAndroid::printConfig() os::Printer::log(" touch:", core::stringc(touch).c_str(), ELL_DEBUG); os::Printer::log(" ui_mode_type:", core::stringc(ui_mode_type).c_str(), ELL_DEBUG); os::Printer::log(" ui_mode_night:", core::stringc(ui_mode_night).c_str(), ELL_DEBUG); - - int rotation = getRotation(); - int deg[4] = {0, 90, 180, 270}; - - os::Printer::log("Rotation: ", core::stringc(deg[rotation]).c_str(), ELL_DEBUG); - - int default_rotation = getDefaultRotation(); - - if (default_rotation == 1) - { - os::Printer::log("Default rotation: landscape", ELL_DEBUG); - } - else - { - os::Printer::log("Default rotation: portrait", ELL_DEBUG); - } } void CIrrDeviceAndroid::createVideoModeList() @@ -254,16 +236,16 @@ bool CIrrDeviceAndroid::run() SEvent accEvent; accEvent.EventType = EET_ACCELEROMETER_EVENT; - if (DefaultOrientation == 0) - { - accEvent.AccelerometerEvent.X = event.acceleration.x; - accEvent.AccelerometerEvent.Y = event.acceleration.y; - } - else + if (DefaultOrientation == ORIENTATION_LANDSCAPE) { accEvent.AccelerometerEvent.X = event.acceleration.y; accEvent.AccelerometerEvent.Y = -event.acceleration.x; } + else + { + accEvent.AccelerometerEvent.X = event.acceleration.x; + accEvent.AccelerometerEvent.Y = event.acceleration.y; + } accEvent.AccelerometerEvent.Z = event.acceleration.z; if (accEvent.AccelerometerEvent.X < 0) @@ -778,15 +760,16 @@ s32 CIrrDeviceAndroid::handleGamepad(AInputEvent* androidEvent) if (GamepadAxisX != 0) { event.KeyInput.PressedDown = false; - event.KeyInput.Key = GamepadAxisX < 0 ? IRR_KEY_LEFT - : IRR_KEY_RIGHT; + event.KeyInput.Key = GamepadAxisX < 0 ? IRR_KEY_BUTTON_LEFT + : IRR_KEY_BUTTON_RIGHT; postEventFromUser(event); } if (axis_x != 0) { event.KeyInput.PressedDown = true; - event.KeyInput.Key = axis_x < 0 ? IRR_KEY_LEFT : IRR_KEY_RIGHT; + event.KeyInput.Key = axis_x < 0 ? IRR_KEY_BUTTON_LEFT + : IRR_KEY_BUTTON_RIGHT; postEventFromUser(event); } @@ -798,15 +781,16 @@ s32 CIrrDeviceAndroid::handleGamepad(AInputEvent* androidEvent) if (GamepadAxisY != 0) { event.KeyInput.PressedDown = false; - event.KeyInput.Key = GamepadAxisY < 0 ? IRR_KEY_UP - : IRR_KEY_DOWN; + event.KeyInput.Key = GamepadAxisY < 0 ? IRR_KEY_BUTTON_UP + : IRR_KEY_BUTTON_DOWN; postEventFromUser(event); } if (axis_y != 0) { event.KeyInput.PressedDown = true; - event.KeyInput.Key = axis_y < 0 ? IRR_KEY_UP : IRR_KEY_DOWN; + event.KeyInput.Key = axis_y < 0 ? IRR_KEY_BUTTON_UP + : IRR_KEY_BUTTON_DOWN; postEventFromUser(event); } @@ -962,21 +946,21 @@ void CIrrDeviceAndroid::createKeyMap() KeyMap[AKEYCODE_SWITCH_CHARSET] = IRR_KEY_UNKNOWN; // following look like controller inputs - KeyMap[AKEYCODE_BUTTON_A] = IRR_KEY_RETURN; - KeyMap[AKEYCODE_BUTTON_B] = IRR_KEY_ESCAPE; - KeyMap[AKEYCODE_BUTTON_C] = IRR_KEY_2; - KeyMap[AKEYCODE_BUTTON_X] = IRR_KEY_3; - KeyMap[AKEYCODE_BUTTON_Y] = IRR_KEY_4; - KeyMap[AKEYCODE_BUTTON_Z] = IRR_KEY_5; - KeyMap[AKEYCODE_BUTTON_L1] = IRR_KEY_6; - KeyMap[AKEYCODE_BUTTON_R1] = IRR_KEY_7; - KeyMap[AKEYCODE_BUTTON_L2] = IRR_KEY_8; - KeyMap[AKEYCODE_BUTTON_R2] = IRR_KEY_9; - KeyMap[AKEYCODE_BUTTON_THUMBL] = IRR_KEY_RETURN; - KeyMap[AKEYCODE_BUTTON_THUMBR] = IRR_KEY_RETURN; - KeyMap[AKEYCODE_BUTTON_START] = IRR_KEY_RETURN; - KeyMap[AKEYCODE_BUTTON_SELECT] = IRR_KEY_ESCAPE; - KeyMap[AKEYCODE_BUTTON_MODE] = IRR_KEY_MENU; + KeyMap[AKEYCODE_BUTTON_A] = IRR_KEY_BUTTON_A; + KeyMap[AKEYCODE_BUTTON_B] = IRR_KEY_BUTTON_B; + KeyMap[AKEYCODE_BUTTON_C] = IRR_KEY_BUTTON_C; + KeyMap[AKEYCODE_BUTTON_X] = IRR_KEY_BUTTON_X; + KeyMap[AKEYCODE_BUTTON_Y] = IRR_KEY_BUTTON_Y; + KeyMap[AKEYCODE_BUTTON_Z] = IRR_KEY_BUTTON_Z; + KeyMap[AKEYCODE_BUTTON_L1] = IRR_KEY_BUTTON_L1; + KeyMap[AKEYCODE_BUTTON_R1] = IRR_KEY_BUTTON_R1; + KeyMap[AKEYCODE_BUTTON_L2] = IRR_KEY_BUTTON_L2; + KeyMap[AKEYCODE_BUTTON_R2] = IRR_KEY_BUTTON_R2; + KeyMap[AKEYCODE_BUTTON_THUMBL] = IRR_KEY_BUTTON_THUMBL; + KeyMap[AKEYCODE_BUTTON_THUMBR] = IRR_KEY_BUTTON_THUMBR; + KeyMap[AKEYCODE_BUTTON_START] = IRR_KEY_BUTTON_START; + KeyMap[AKEYCODE_BUTTON_SELECT] = IRR_KEY_BUTTON_SELECT; + KeyMap[AKEYCODE_BUTTON_MODE] = IRR_KEY_BUTTON_MODE; KeyMap[AKEYCODE_ESCAPE] = IRR_KEY_ESCAPE; KeyMap[AKEYCODE_FORWARD_DEL] = IRR_KEY_DELETE; @@ -1197,7 +1181,7 @@ int CIrrDeviceAndroid::getRotation() return rotation; } -int CIrrDeviceAndroid::getDefaultRotation() +DeviceOrientation CIrrDeviceAndroid::getDefaultOrientation() { int rotation = getRotation(); @@ -1208,11 +1192,11 @@ int CIrrDeviceAndroid::getDefaultRotation() ((rotation == 1 || rotation == 3) && orientation == ACONFIGURATION_ORIENTATION_PORT)) { - return 1; + return ORIENTATION_LANDSCAPE; } else { - return 0; + return ORIENTATION_PORTRAIT; } } @@ -1220,6 +1204,11 @@ bool CIrrDeviceAndroid::activateAccelerometer(float updateInterval) { if (!isAccelerometerAvailable()) return false; + + if (DefaultOrientation == ORIENTATION_UNKNOWN) + { + DefaultOrientation = getDefaultOrientation(); + } ASensorEventQueue_enableSensor(SensorEventQueue, Accelerometer); ASensorEventQueue_setEventRate(SensorEventQueue, Accelerometer, diff --git a/lib/irrlicht/source/Irrlicht/CIrrDeviceAndroid.h b/lib/irrlicht/source/Irrlicht/CIrrDeviceAndroid.h index 97ce5da71..33ce575b9 100644 --- a/lib/irrlicht/source/Irrlicht/CIrrDeviceAndroid.h +++ b/lib/irrlicht/source/Irrlicht/CIrrDeviceAndroid.h @@ -23,7 +23,13 @@ namespace irr { - + enum DeviceOrientation + { + ORIENTATION_UNKNOWN, + ORIENTATION_PORTRAIT, + ORIENTATION_LANDSCAPE + }; + class CIrrDeviceAndroid : public CIrrDeviceStub, video::IImagePresenter { public: @@ -123,7 +129,7 @@ namespace irr bool IsMousePressed; float GamepadAxisX; float GamepadAxisY; - int DefaultOrientation; + DeviceOrientation DefaultOrientation; video::SExposedVideoData ExposedVideoData; @@ -135,7 +141,7 @@ namespace irr void createVideoModeList(); void getKeyChar(SEvent& event); int getRotation(); - int getDefaultRotation(); + DeviceOrientation getDefaultOrientation(); video::SExposedVideoData& getExposedVideoData(); static void handleAndroidCommand(android_app* app, int32_t cmd); diff --git a/src/config/user_config.hpp b/src/config/user_config.hpp index 8ea445e00..fec3f916a 100644 --- a/src/config/user_config.hpp +++ b/src/config/user_config.hpp @@ -468,10 +468,10 @@ namespace UserConfigParams &m_multitouch_group, "Draw steering wheel on right side.") ); - PARAM_PREFIX IntUserConfigParam m_multitouch_accelerometer - PARAM_DEFAULT( IntUserConfigParam(0, "multitouch_accelerometer", + PARAM_PREFIX IntUserConfigParam m_multitouch_controls + PARAM_DEFAULT( IntUserConfigParam(0, "multitouch_controls", &m_multitouch_group, - "Accelerometer mode: 0 = off, 1 = tablet, 2 = phone")); + "Multitouch mode: 0 = undefined, 1 = steering wheel, 2 = accelerometer")); PARAM_PREFIX FloatUserConfigParam m_multitouch_deadzone_center PARAM_DEFAULT( FloatUserConfigParam(0.1f, "multitouch_deadzone_center", diff --git a/src/guiengine/widgets/CGUIEditBox.cpp b/src/guiengine/widgets/CGUIEditBox.cpp index 013bff741..d4f06013a 100644 --- a/src/guiengine/widgets/CGUIEditBox.cpp +++ b/src/guiengine/widgets/CGUIEditBox.cpp @@ -23,6 +23,10 @@ #include "../../../lib/irrlicht/include/IrrCompileConfig.h" #include "../../../lib/irrlicht/source/Irrlicht/CIrrDeviceLinux.h" +#ifdef ANDROID +#include "../../../lib/irrlicht/source/Irrlicht/CIrrDeviceAndroid.h" +#endif + /* todo: optional scrollbars @@ -1258,12 +1262,24 @@ bool CGUIEditBox::processMouse(const SEvent& event) } else if (!m_rtl) { + bool use_screen_keyboard = UserConfigParams::m_screen_keyboard; + + #ifdef ANDROID + int32_t keyboard = AConfiguration_getKeyboard( + global_android_app->config); + + if (keyboard == ACONFIGURATION_KEYBOARD_QWERTY) + { + use_screen_keyboard = false; + } + #endif + if (!AbsoluteClippingRect.isPointInside( core::position2d(event.MouseInput.X, event.MouseInput.Y))) { return false; } - else if (UserConfigParams::m_screen_keyboard) + else if (use_screen_keyboard) { CursorPos = Text.size(); setTextMarkers(CursorPos, CursorPos); diff --git a/src/input/device_config.cpp b/src/input/device_config.cpp index 04b6cc8ff..5e89a337e 100644 --- a/src/input/device_config.cpp +++ b/src/input/device_config.cpp @@ -20,6 +20,7 @@ #include "input/device_config.hpp" #include "input/gamepad_config.hpp" +#include "input/gamepad_android_config.hpp" #include "input/keyboard_config.hpp" #include "io/xml_node.hpp" #include "utils/log.hpp" @@ -47,6 +48,10 @@ DeviceConfig* DeviceConfig::create(const XMLNode *config) { device_config = new GamepadConfig(); } + else if(config->getName()=="gamepad_android") + { + device_config = new GamepadAndroidConfig(); + } else { Log::error("DeviceConfig", "Incorrect type: '%s'.", diff --git a/src/input/device_config.hpp b/src/input/device_config.hpp index 844eb6c01..bbc727c1e 100644 --- a/src/input/device_config.hpp +++ b/src/input/device_config.hpp @@ -95,6 +95,7 @@ public: irr::core::stringw getMappingIdString (const PlayerAction action) const; virtual irr::core::stringw getBindingAsString(const PlayerAction action) const; virtual bool isGamePad() const = 0; + virtual bool isGamePadAndroid() const = 0; virtual bool isKeyboard() const = 0; virtual void save(std::ofstream& stream); diff --git a/src/input/device_manager.cpp b/src/input/device_manager.cpp index eb5f77d06..ebb2c5ea0 100644 --- a/src/input/device_manager.cpp +++ b/src/input/device_manager.cpp @@ -23,6 +23,7 @@ #include "config/user_config.hpp" #include "graphics/irr_driver.hpp" +#include "input/gamepad_android_config.hpp" #include "input/gamepad_device.hpp" #include "input/keyboard_device.hpp" #include "input/multitouch_device.hpp" @@ -80,8 +81,27 @@ bool DeviceManager::initialize() if(UserConfigParams::logMisc()) Log::info("Device manager","No keyboard configuration exists, creating one."); m_keyboard_configs.push_back(new KeyboardConfig()); + created = true; } + +#ifdef ANDROID + bool has_gamepad_android_config = false; + + for (unsigned int i = 0; i < m_keyboard_configs.size(); i++) + { + if (m_keyboard_configs[i].isGamePadAndroid()) + { + has_gamepad_android_config = true; + } + } + + if (!has_gamepad_android_config) + { + m_keyboard_configs.push_back(new GamepadAndroidConfig()); + created = true; + } +#endif const int keyboard_amount = m_keyboard_configs.size(); for (int n = 0; n < keyboard_amount; n++) @@ -568,12 +588,13 @@ bool DeviceManager::load() config->getName().c_str()); continue; } - if(config->getName()=="keyboard") + if (config->getName() == "keyboard" || + config->getName() == "gamepad_android") { KeyboardConfig *kc = static_cast(device_config); m_keyboard_configs.push_back(kc); } - else if (config->getName()=="gamepad") + else if (config->getName() == "gamepad") { GamepadConfig *gc = static_cast(device_config); m_gamepad_configs.push_back(gc); diff --git a/src/input/gamepad_android_config.cpp b/src/input/gamepad_android_config.cpp new file mode 100644 index 000000000..d87296777 --- /dev/null +++ b/src/input/gamepad_android_config.cpp @@ -0,0 +1,145 @@ +// +// SuperTuxKart - a fun racing game with go-kart +// Copyright (C) 2010-2015 SuperTuxKart-Team +// +// 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 3 +// of the License, or (at your option) 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + +#include "input/gamepad_android_config.hpp" +#include "utils/translation.hpp" + +#include + +using namespace irr; + +GamepadAndroidConfig::GamepadAndroidConfig() +{ + setDefaultBinds(); +} + +// ---------------------------------------------------------------------------- +/** Saves the configuration to a file. It writes the name for a gamepad + * config, saves the device specific parameters, and calls + * DeviceConfig::save() to save the rest. + * \param stream The stream to save to. + */ +void GamepadAndroidConfig::save(std::ofstream& stream) +{ + stream << "\n\n"; +} // save + +// ---------------------------------------------------------------------------- + +irr::core::stringw GamepadAndroidConfig::getBindingAsString(const PlayerAction action) const +{ + const Binding &b = getBinding(action); + int id = b.getId(); + + irr::core::stringw button_name; + + switch (id) + { + case IRR_KEY_BUTTON_LEFT: + button_name = _C("input_key", "Left"); + break; + case IRR_KEY_BUTTON_RIGHT: + button_name = _C("input_key", "Right"); + break; + case IRR_KEY_BUTTON_UP: + button_name = _C("input_key", "Up"); + break; + case IRR_KEY_BUTTON_DOWN: + button_name = _C("input_key", "Down"); + break; + case IRR_KEY_BUTTON_A: + button_name = "A"; + break; + case IRR_KEY_BUTTON_B: + button_name = "B"; + break; + case IRR_KEY_BUTTON_C: + button_name = "C"; + break; + case IRR_KEY_BUTTON_X: + button_name = "X"; + break; + case IRR_KEY_BUTTON_Y: + button_name = "Y"; + break; + case IRR_KEY_BUTTON_Z: + button_name = "Z"; + break; + case IRR_KEY_BUTTON_L1: + button_name = "L1"; + break; + case IRR_KEY_BUTTON_R1: + button_name = "R1"; + break; + case IRR_KEY_BUTTON_L2: + button_name = "L2"; + break; + case IRR_KEY_BUTTON_R2: + button_name = "R2"; + break; + case IRR_KEY_BUTTON_THUMBL: + button_name = _C("input_key", "Thumb Left"); + break; + case IRR_KEY_BUTTON_THUMBR: + button_name = _C("input_key", "Thumb Right"); + break; + case IRR_KEY_BUTTON_START: + button_name = _C("input_key", "Start"); + break; + case IRR_KEY_BUTTON_SELECT: + button_name = _C("input_key", "Select"); + break; + case IRR_KEY_BUTTON_MODE: + button_name = _C("input_key", "Mode"); + break; + default: + button_name = DeviceConfig::getBindingAsString(action); + break; + } + + return button_name; +} + +// ---------------------------------------------------------------------------- + +void GamepadAndroidConfig::setDefaultBinds() +{ + setBinding(PA_NITRO, Input::IT_KEYBOARD, IRR_KEY_BUTTON_X); + setBinding(PA_ACCEL, Input::IT_KEYBOARD, IRR_KEY_BUTTON_UP); + setBinding(PA_BRAKE, Input::IT_KEYBOARD, IRR_KEY_BUTTON_DOWN); + setBinding(PA_STEER_LEFT, Input::IT_KEYBOARD, IRR_KEY_BUTTON_LEFT); + setBinding(PA_STEER_RIGHT, Input::IT_KEYBOARD, IRR_KEY_BUTTON_RIGHT); + setBinding(PA_DRIFT, Input::IT_KEYBOARD, IRR_KEY_BUTTON_Y); + setBinding(PA_RESCUE, Input::IT_KEYBOARD, IRR_KEY_BUTTON_L1); + setBinding(PA_FIRE, Input::IT_KEYBOARD, IRR_KEY_BUTTON_A); + setBinding(PA_LOOK_BACK, Input::IT_KEYBOARD, IRR_KEY_BUTTON_R1); + setBinding(PA_PAUSE_RACE, Input::IT_KEYBOARD, IRR_KEY_BUTTON_B); + + setBinding(PA_MENU_UP, Input::IT_KEYBOARD, IRR_KEY_BUTTON_UP); + setBinding(PA_MENU_DOWN, Input::IT_KEYBOARD, IRR_KEY_BUTTON_DOWN); + setBinding(PA_MENU_LEFT, Input::IT_KEYBOARD, IRR_KEY_BUTTON_LEFT); + setBinding(PA_MENU_RIGHT, Input::IT_KEYBOARD, IRR_KEY_BUTTON_RIGHT); + setBinding(PA_MENU_SELECT, Input::IT_KEYBOARD, IRR_KEY_BUTTON_A); + setBinding(PA_MENU_CANCEL, Input::IT_KEYBOARD, IRR_KEY_BUTTON_B); +} + +//------------------------------------------------------------------------------ + diff --git a/src/input/gamepad_android_config.hpp b/src/input/gamepad_android_config.hpp new file mode 100644 index 000000000..324af98cf --- /dev/null +++ b/src/input/gamepad_android_config.hpp @@ -0,0 +1,55 @@ +// +// SuperTuxKart - a fun racing game with go-kart +// Copyright (C) 2010-2015 SuperTuxKart-Team +// +// 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 3 +// of the License, or (at your option) 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#ifndef HEADER_GAMEPAD_ANDROID_CONFIG_HPP +#define HEADER_GAMEPAD_ANDROID_CONFIG_HPP + +#include "input/binding.hpp" +#include "input/keyboard_config.hpp" +#include "input/input.hpp" +#include "utils/no_copy.hpp" +#include "utils/cpp2011.hpp" + +#include + +/** + * \brief specialisation of DeviceConfig for android gamepad devices + * \ingroup config + */ +class GamepadAndroidConfig : public KeyboardConfig +{ + +public: + + GamepadAndroidConfig(); + virtual ~GamepadAndroidConfig() {} + + virtual void setDefaultBinds(); + virtual void save(std::ofstream& stream); + virtual irr::core::stringw getBindingAsString(const PlayerAction action) const; + + // ------------------------------------------------------------------------ + virtual bool isGamePad() const { return false; } + // ------------------------------------------------------------------------ + virtual bool isGamePadAndroid() const { return true; } + // ------------------------------------------------------------------------ + virtual bool isKeyboard() const { return true; } + +}; // class GamepadAndroidConfig + +#endif diff --git a/src/input/gamepad_config.hpp b/src/input/gamepad_config.hpp index b62c77d57..f056fc68a 100644 --- a/src/input/gamepad_config.hpp +++ b/src/input/gamepad_config.hpp @@ -105,6 +105,8 @@ public: // ------------------------------------------------------------------------ virtual bool isGamePad() const OVERRIDE { return true; } // ------------------------------------------------------------------------ + virtual bool isGamePadAndroid() const OVERRIDE { return false; } + // ------------------------------------------------------------------------ virtual bool isKeyboard() const OVERRIDE { return false; } }; // class GamepadConfig diff --git a/src/input/input_manager.cpp b/src/input/input_manager.cpp index ab596fc60..4241cb182 100644 --- a/src/input/input_manager.cpp +++ b/src/input/input_manager.cpp @@ -109,7 +109,8 @@ void InputManager::handleStaticAction(int key, int value) // When no players... a cutscene if (race_manager->getNumPlayers() == 0 && world != NULL && value > 0 && - (key == IRR_KEY_SPACE || key == IRR_KEY_RETURN)) + (key == IRR_KEY_SPACE || key == IRR_KEY_RETURN || + key == IRR_KEY_BUTTON_A)) { world->onFirePressed(NULL); } @@ -658,12 +659,17 @@ void InputManager::dispatchInput(Input::InputType type, int deviceID, { action = PA_BEFORE_FIRST; - if (button == IRR_KEY_UP) action = PA_MENU_UP; - else if (button == IRR_KEY_DOWN) action = PA_MENU_DOWN; - else if (button == IRR_KEY_LEFT) action = PA_MENU_LEFT; - else if (button == IRR_KEY_RIGHT) action = PA_MENU_RIGHT; - else if (button == IRR_KEY_SPACE) action = PA_MENU_SELECT; - else if (button == IRR_KEY_RETURN) action = PA_MENU_SELECT; + if (button == IRR_KEY_UP) action = PA_MENU_UP; + else if (button == IRR_KEY_DOWN) action = PA_MENU_DOWN; + else if (button == IRR_KEY_LEFT) action = PA_MENU_LEFT; + else if (button == IRR_KEY_RIGHT) action = PA_MENU_RIGHT; + else if (button == IRR_KEY_SPACE) action = PA_MENU_SELECT; + else if (button == IRR_KEY_RETURN) action = PA_MENU_SELECT; + else if (button == IRR_KEY_BUTTON_UP) action = PA_MENU_DOWN; + else if (button == IRR_KEY_BUTTON_DOWN) action = PA_MENU_UP; + else if (button == IRR_KEY_BUTTON_LEFT) action = PA_MENU_LEFT; + else if (button == IRR_KEY_BUTTON_RIGHT) action = PA_MENU_RIGHT; + else if (button == IRR_KEY_BUTTON_A) action = PA_MENU_SELECT; else if (button == IRR_KEY_TAB) { if (shift_mask) @@ -676,7 +682,7 @@ void InputManager::dispatchInput(Input::InputType type, int deviceID, } } - if (button == IRR_KEY_RETURN) + if (button == IRR_KEY_RETURN || button == IRR_KEY_BUTTON_A) { if (GUIEngine::ModalDialog::isADialogActive() && !GUIEngine::ScreenKeyboard::isActive()) diff --git a/src/input/keyboard_config.hpp b/src/input/keyboard_config.hpp index 7d3dc264e..e43cc47ee 100644 --- a/src/input/keyboard_config.hpp +++ b/src/input/keyboard_config.hpp @@ -39,12 +39,14 @@ public: KeyboardConfig(); virtual ~KeyboardConfig() {} - void setDefaultBinds (); + virtual void setDefaultBinds(); virtual void save(std::ofstream& stream); // ------------------------------------------------------------------------ virtual bool isGamePad() const { return false; } // ------------------------------------------------------------------------ + virtual bool isGamePadAndroid() const { return false; } + // ------------------------------------------------------------------------ virtual bool isKeyboard() const { return true; } }; // class KeyboardConfig diff --git a/src/input/multitouch_device.cpp b/src/input/multitouch_device.cpp index 9d1c8e4eb..7ce754fcf 100644 --- a/src/input/multitouch_device.cpp +++ b/src/input/multitouch_device.cpp @@ -140,7 +140,7 @@ void MultitouchDevice::addButton(MultitouchButtonType type, int x, int y, #ifdef ANDROID if (button->type == MultitouchButtonType::BUTTON_STEERING) { - if (UserConfigParams::m_multitouch_accelerometer > 0 && + if (UserConfigParams::m_multitouch_controls == 2 && !m_android_device->isAccelerometerActive()) { m_android_device->activateAccelerometer(1.0f / 30); diff --git a/src/items/item.cpp b/src/items/item.cpp index 8d1688a31..dc3f7512a 100644 --- a/src/items/item.cpp +++ b/src/items/item.cpp @@ -28,6 +28,7 @@ #include "modes/easter_egg_hunt.hpp" #include "modes/three_strikes_battle.hpp" #include "modes/world.hpp" +#include "network/rewind_manager.hpp" #include "tracks/arena_graph.hpp" #include "tracks/drive_graph.hpp" #include "tracks/drive_node.hpp" @@ -336,7 +337,8 @@ void Item::update(float dt) if(!m_rotate || m_node == NULL) return; // have it rotate - m_rotation_angle += dt * M_PI ; + if(!RewindManager::get()->isRewinding()) + m_rotation_angle += dt * M_PI; if (m_rotation_angle > M_PI * 2) m_rotation_angle -= M_PI * 2; btMatrix3x3 m; diff --git a/src/karts/kart.cpp b/src/karts/kart.cpp index 809fbed55..cb737dbfd 100644 --- a/src/karts/kart.cpp +++ b/src/karts/kart.cpp @@ -1269,6 +1269,7 @@ void Kart::update(float dt) if(!history->replayHistory() || !history->dontDoPhysics()) m_controller->update(dt); +#ifndef SERVER_ONLY #undef DEBUG_CAMERA_SHAKE #ifdef DEBUG_CAMERA_SHAKE Log::verbose("camera", "%s t %f %f xyz %f %f %f v %f %f %f d3 %f d2 %f", @@ -1280,6 +1281,7 @@ void Kart::update(float dt) (Camera::getCamera(0)->getXYZ()-getXYZ()).length_2d() ); #endif +#endif #undef DEBUG_TO_COMPARE_KART_PHYSICS #ifdef DEBUG_TO_COMPARE_KART_PHYSICS diff --git a/src/main.cpp b/src/main.cpp index ba6767533..ce5f1b3db 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -230,6 +230,7 @@ #include "states_screens/register_screen.hpp" #include "states_screens/state_manager.hpp" #include "states_screens/user_screen.hpp" +#include "states_screens/dialogs/init_android_dialog.hpp" #include "states_screens/dialogs/message_dialog.hpp" #include "tracks/arena_graph.hpp" #include "tracks/track.hpp" @@ -1718,6 +1719,21 @@ int main(int argc, char *argv[] ) } Log::warn("main", "Screen size is too small!"); } + + #ifdef ANDROID + if (UserConfigParams::m_multitouch_controls == 0) + { + int32_t touch = AConfiguration_getTouchscreen( + global_android_app->config); + + if (touch != ACONFIGURATION_TOUCHSCREEN_NOTOUCH) + { + InitAndroidDialog* init_android = new InitAndroidDialog( + 0.6f, 0.6f); + GUIEngine::DialogQueue::get()->pushDialog(init_android); + } + } + #endif if (GraphicsRestrictions::isDisabled( GraphicsRestrictions::GR_DRIVER_RECENT_ENOUGH)) @@ -1734,6 +1750,7 @@ int main(int argc, char *argv[] ) } else if (!CVS->isGLSL()) { + #if !defined(ANDROID) if (UserConfigParams::m_old_driver_popup) { #ifdef USE_GLES2 @@ -1750,6 +1767,7 @@ int main(int argc, char *argv[] ) /*from queue*/ true); GUIEngine::DialogQueue::get()->pushDialog(dialog); } + #endif Log::warn("OpenGL", "OpenGL version is too old!"); } } diff --git a/src/modes/world.cpp b/src/modes/world.cpp index cbdcccbd1..8ba3046e5 100644 --- a/src/modes/world.cpp +++ b/src/modes/world.cpp @@ -1006,12 +1006,17 @@ void World::update(float dt) } PROFILER_POP_CPU_MARKER(); - PROFILER_PUSH_CPU_MARKER("World::update (camera)", 0x60, 0x7F, 0x00); - for(unsigned int i=0; iisRewinding()) { - Camera::getCamera(i)->update(dt); - } - PROFILER_POP_CPU_MARKER(); + PROFILER_PUSH_CPU_MARKER("World::update (camera)", 0x60, 0x7F, 0x00); + + for (unsigned int i = 0; i < Camera::getNumCameras(); i++) + { + Camera::getCamera(i)->update(dt); + } + PROFILER_POP_CPU_MARKER(); + } // if !rewind if(race_manager->isRecordingRace()) ReplayRecorder::get()->update(dt); Scripting::ScriptEngine *script_engine = Scripting::ScriptEngine::getInstance(); diff --git a/src/modes/world_status.cpp b/src/modes/world_status.cpp index 670479816..dddbe69d1 100644 --- a/src/modes/world_status.cpp +++ b/src/modes/world_status.cpp @@ -313,6 +313,7 @@ void WorldStatus::updateTime(const float dt) // In artist debug mode, when without opponents, // skip the ready/set/go counter faster if (UserConfigParams::m_artist_debug_mode && + !NetworkConfig::get()->isNetworking() && race_manager->getNumberOfKarts() - race_manager->getNumSpareTireKarts() == 1 && race_manager->getTrackName() != "tutorial") @@ -483,6 +484,7 @@ void WorldStatus::startReadySetGo() */ void WorldStatus::setTime(const float time) { + m_count_up_timer += (time - m_time); m_time = time; } // setTime diff --git a/src/states_screens/dialogs/init_android_dialog.cpp b/src/states_screens/dialogs/init_android_dialog.cpp new file mode 100644 index 000000000..d446d47dc --- /dev/null +++ b/src/states_screens/dialogs/init_android_dialog.cpp @@ -0,0 +1,158 @@ +// SuperTuxKart - a fun racing game with go-kart +// Copyright (C) 2014-2015 SuperTuxKart-Team +// +// 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 3 +// of the License, or (at your option) 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#include "states_screens/dialogs/init_android_dialog.hpp" + +#include "config/user_config.hpp" +#include "graphics/irr_driver.hpp" +#include "guiengine/widgets/check_box_widget.hpp" +#include "guiengine/widgets/spinner_widget.hpp" +#include "guiengine/widgets/ribbon_widget.hpp" +#include "input/device_manager.hpp" +#include "input/input_manager.hpp" +#include "input/multitouch_device.hpp" +#include "utils/translation.hpp" + +#ifdef ANDROID +#include "../../../lib/irrlicht/source/Irrlicht/CIrrDeviceAndroid.h" +#endif + +#include + + +using namespace GUIEngine; +using namespace irr; +using namespace irr::core; +using namespace irr::gui; + +// ----------------------------------------------------------------------------- + +InitAndroidDialog::InitAndroidDialog(const float w, const float h) + : ModalDialog(w, h) +{ +} + +// ----------------------------------------------------------------------------- + +InitAndroidDialog::~InitAndroidDialog() +{ +} + +// ----------------------------------------------------------------------------- + +void InitAndroidDialog::load() +{ + loadFromFile("init_android.stkgui"); +} + +// ----------------------------------------------------------------------------- + +void InitAndroidDialog::beforeAddingWidgets() +{ + bool accelerometer_available = false; + +#ifdef ANDROID + CIrrDeviceAndroid* android_device = dynamic_cast( + irr_driver->getDevice()); + assert(android_device != NULL); + accelerometer_available = android_device->isAccelerometerAvailable(); +#endif + + if (!accelerometer_available) + { + RibbonWidget* control_type = getWidget("control_type"); + assert(control_type != NULL); + + int index = control_type->findItemNamed("accelerometer"); + Widget* accelerometer = &control_type->getChildren()[index]; + accelerometer->setActive(false); + + if (UserConfigParams::m_multitouch_controls = 2) + { + UserConfigParams::m_multitouch_controls = 1; + } + } + + updateValues(); +} + +// ----------------------------------------------------------------------------- + +GUIEngine::EventPropagation InitAndroidDialog::processEvent( + const std::string& eventSource) +{ + if (eventSource == "close") + { + RibbonWidget* control_type = getWidget("control_type"); + assert(control_type != NULL); + + const std::string& selected = control_type->getSelectionIDString( + PLAYER_ID_GAME_MASTER); + int index = control_type->getSelection(PLAYER_ID_GAME_MASTER); + Widget* selected_widget = &control_type->getChildren()[index]; + + if (!selected_widget->isActivated()) + return GUIEngine::EVENT_BLOCK; + + if (selected == "steering_wheel") + { + UserConfigParams::m_multitouch_controls = 1; + } + else if (selected == "accelerometer") + { + UserConfigParams::m_multitouch_controls = 2; + } + + user_config->saveConfig(); + + ModalDialog::dismiss(); + return GUIEngine::EVENT_BLOCK; + } + + return GUIEngine::EVENT_LET; +} // processEvent + +// ----------------------------------------------------------------------------- + +void InitAndroidDialog::updateValues() +{ + RibbonWidget* control_type = getWidget("control_type"); + assert(control_type != NULL); + + if (UserConfigParams::m_multitouch_controls == 2) + { + int id = control_type->findItemNamed("accelerometer"); + control_type->setSelection(id, PLAYER_ID_GAME_MASTER); + } + else + { + int id = control_type->findItemNamed("steering_wheel"); + control_type->setSelection(id, PLAYER_ID_GAME_MASTER); + } +} + +// ----------------------------------------------------------------------------- + +bool InitAndroidDialog::onEscapePressed() +{ + UserConfigParams::m_multitouch_controls = 1; + user_config->saveConfig(); + ModalDialog::dismiss(); + return true; +} // onEscapePressed + +// ----------------------------------------------------------------------------- diff --git a/src/states_screens/dialogs/init_android_dialog.hpp b/src/states_screens/dialogs/init_android_dialog.hpp new file mode 100644 index 000000000..0fc10cff0 --- /dev/null +++ b/src/states_screens/dialogs/init_android_dialog.hpp @@ -0,0 +1,48 @@ +// SuperTuxKart - a fun racing game with go-kart +// Copyright (C) 2014-2015 SuperTuxKart-Team +// +// 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 3 +// of the License, or (at your option) 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + +#ifndef HEADER_INIT_ANDROID_DIALOG_HPP +#define HEADER_INIT_ANDROID_DIALOG_HPP + +#include "guiengine/modaldialog.hpp" + +/** + * \brief Dialog that allows the player to adjust multitouch steering settings + * \ingroup states_screens + */ +class InitAndroidDialog : public GUIEngine::ModalDialog +{ +private: + void updateValues(); + +public: + /** + * Creates a modal dialog with given percentage of screen width and height + */ + InitAndroidDialog(const float percentWidth, const float percentHeight); + ~InitAndroidDialog(); + + virtual void beforeAddingWidgets(); + virtual void load(); + virtual bool onEscapePressed(); + + GUIEngine::EventPropagation processEvent(const std::string& eventSource); + +}; + +#endif diff --git a/src/states_screens/dialogs/multitouch_settings_dialog.cpp b/src/states_screens/dialogs/multitouch_settings_dialog.cpp index 62970be6f..0fb2cbe85 100644 --- a/src/states_screens/dialogs/multitouch_settings_dialog.cpp +++ b/src/states_screens/dialogs/multitouch_settings_dialog.cpp @@ -18,6 +18,7 @@ #include "states_screens/dialogs/multitouch_settings_dialog.hpp" #include "config/user_config.hpp" +#include "graphics/irr_driver.hpp" #include "guiengine/widgets/check_box_widget.hpp" #include "guiengine/widgets/spinner_widget.hpp" #include "input/device_manager.hpp" @@ -25,6 +26,10 @@ #include "input/multitouch_device.hpp" #include "utils/translation.hpp" +#ifdef ANDROID +#include "../../../lib/irrlicht/source/Irrlicht/CIrrDeviceAndroid.h" +#endif + #include @@ -51,6 +56,22 @@ MultitouchSettingsDialog::~MultitouchSettingsDialog() void MultitouchSettingsDialog::beforeAddingWidgets() { + bool accelerometer_available = false; + +#ifdef ANDROID + CIrrDeviceAndroid* android_device = dynamic_cast( + irr_driver->getDevice()); + assert(android_device != NULL); + accelerometer_available = android_device->isAccelerometerAvailable(); +#endif + + if (!accelerometer_available) + { + CheckBoxWidget* accelerometer = getWidget("accelerometer"); + assert(accelerometer != NULL); + accelerometer->setActive(false); + } + updateValues(); } @@ -86,8 +107,8 @@ GUIEngine::EventPropagation MultitouchSettingsDialog::processEvent( CheckBoxWidget* accelerometer = getWidget("accelerometer"); assert(accelerometer != NULL); - UserConfigParams::m_multitouch_accelerometer = accelerometer-> - getState() ? 1 : 0; + UserConfigParams::m_multitouch_controls = accelerometer-> + getState() ? 2 : 1; MultitouchDevice* touch_device = input_manager->getDeviceManager()-> getMultitouchDevice(); @@ -108,7 +129,7 @@ GUIEngine::EventPropagation MultitouchSettingsDialog::processEvent( UserConfigParams::m_multitouch_deadzone_edge.revertToDefaults(); UserConfigParams::m_multitouch_deadzone_center.revertToDefaults(); UserConfigParams::m_multitouch_mode.revertToDefaults(); - UserConfigParams::m_multitouch_accelerometer.revertToDefaults(); + UserConfigParams::m_multitouch_controls.revertToDefaults(); updateValues(); @@ -146,7 +167,7 @@ void MultitouchSettingsDialog::updateValues() CheckBoxWidget* accelerometer = getWidget("accelerometer"); assert(accelerometer != NULL); - accelerometer->setState(UserConfigParams::m_multitouch_accelerometer != 0); + accelerometer->setState(UserConfigParams::m_multitouch_controls == 2); } // ----------------------------------------------------------------------------- diff --git a/src/states_screens/options_screen_device.cpp b/src/states_screens/options_screen_device.cpp index 94132a3f5..040507e4a 100644 --- a/src/states_screens/options_screen_device.cpp +++ b/src/states_screens/options_screen_device.cpp @@ -106,6 +106,11 @@ void OptionsScreenDevice::init() delete_button->setLabel(label); } + else if (m_config->isGamePadAndroid()) + { + delete_button->setLabel(_("Delete Configuration")); + delete_button->setActive(false); + } else { delete_button->setLabel(_("Delete Configuration")); @@ -160,7 +165,11 @@ void OptionsScreenDevice::init() // Disable deletion keyboard configurations bool in_game = StateManager::get()->getGameState() == GUIEngine::INGAME_MENU; - getWidget("delete")->setActive(!in_game); + + if (in_game) + { + getWidget("delete")->setActive(false); + } } // init // ----------------------------------------------------------------------------- diff --git a/src/states_screens/options_screen_input.cpp b/src/states_screens/options_screen_input.cpp index 92ea2599c..b86b00e79 100644 --- a/src/states_screens/options_screen_input.cpp +++ b/src/states_screens/options_screen_input.cpp @@ -89,15 +89,26 @@ void OptionsScreenInput::buildDeviceList() for (int i=0; igetDeviceList()->getKeyboardConfig(i); - + KeyboardConfig *config = device_manager->getKeyboardConfig(i); + std::ostringstream kbname; kbname << "keyboard" << i; const std::string internal_name = kbname.str(); - - // since irrLicht's list widget has the nasty tendency to put the - // icons very close to the text, I'm adding spaces to compensate. - devices->addItem(internal_name, (core::stringw(" ") + _("Keyboard %i", i)).c_str(), 0 /* icon */); + + if (config->isGamePadAndroid()) + { + // since irrLicht's list widget has the nasty tendency to put the + // icons very close to the text, I'm adding spaces to compensate. + devices->addItem(internal_name, (core::stringw(" ") + + _("Gamepad")).c_str(), 1 /* icon */); + } + else + { + // since irrLicht's list widget has the nasty tendency to put the + // icons very close to the text, I'm adding spaces to compensate. + devices->addItem(internal_name, (core::stringw(" ") + + _("Keyboard %i", i)).c_str(), 0 /* icon */); + } } const int gpad_config_count = device_manager->getGamePadConfigAmount();