From 485266414360c063de73f1657bc51c191d999805 Mon Sep 17 00:00:00 2001 From: Deve Date: Tue, 7 Feb 2017 13:48:08 +0100 Subject: [PATCH] Allow to use accelerometer for turning left/right. It should be much more comfortable on small devices. Though it's not possible to get default screen orientation (and real device orientation) using NDK functions, so at this stage user has to manually choose if he needs "tablet" or "phone" accelerometer. --- data/gui/multitouch_settings.stkgui | 51 ++++++++++----- src/config/user_config.hpp | 7 +- src/guiengine/event_handler.cpp | 3 +- src/input/input_manager.cpp | 26 ++++++++ src/input/multitouch_device.cpp | 64 ++++++++++++++++--- src/input/multitouch_device.hpp | 10 +++ .../dialogs/multitouch_settings_dialog.cpp | 50 ++++++++++++++- 7 files changed, 183 insertions(+), 28 deletions(-) diff --git a/data/gui/multitouch_settings.stkgui b/data/gui/multitouch_settings.stkgui index ba83af681..1cf3857bf 100644 --- a/data/gui/multitouch_settings.stkgui +++ b/data/gui/multitouch_settings.stkgui @@ -3,22 +3,18 @@
- +
+ diff --git a/src/config/user_config.hpp b/src/config/user_config.hpp index ecca0133a..d91ca73f6 100644 --- a/src/config/user_config.hpp +++ b/src/config/user_config.hpp @@ -412,7 +412,12 @@ namespace UserConfigParams PARAM_PREFIX IntUserConfigParam m_multitouch_mode PARAM_DEFAULT( IntUserConfigParam(1, "multitouch_mode", &m_multitouch_group, - "Steering mode: 0 = off, 1 = buttons, 2 = accelerometer") ); + "Steering mode: 0 = off, 1 = buttons")); + + PARAM_PREFIX IntUserConfigParam m_multitouch_accelerometer + PARAM_DEFAULT( IntUserConfigParam(0, "multitouch_accelerometer", + &m_multitouch_group, + "Accelerometer mode: 0 = off, 1 = tablet, 2 = phone")); PARAM_PREFIX FloatUserConfigParam m_multitouch_deadzone_center PARAM_DEFAULT( FloatUserConfigParam(0.1f, "multitouch_deadzone_center", diff --git a/src/guiengine/event_handler.cpp b/src/guiengine/event_handler.cpp index 0f9fe440e..b083e5cfa 100644 --- a/src/guiengine/event_handler.cpp +++ b/src/guiengine/event_handler.cpp @@ -199,7 +199,8 @@ bool EventHandler::OnEvent (const SEvent &event) else if (event.EventType == EET_MOUSE_INPUT_EVENT || event.EventType == EET_TOUCH_INPUT_EVENT || event.EventType == EET_KEY_INPUT_EVENT || - event.EventType == EET_JOYSTICK_INPUT_EVENT) + event.EventType == EET_JOYSTICK_INPUT_EVENT || + event.EventType == EET_ACCELEROMETER_EVENT) { // Remember the mouse position if (event.EventType == EET_MOUSE_INPUT_EVENT && diff --git a/src/input/input_manager.cpp b/src/input/input_manager.cpp index 5d4366169..e7ac0a737 100644 --- a/src/input/input_manager.cpp +++ b/src/input/input_manager.cpp @@ -1165,6 +1165,32 @@ EventPropagation InputManager::input(const SEvent& event) how fast. */ } + else if (event.EventType == EET_ACCELEROMETER_EVENT) + { + MultitouchDevice* device = m_device_manager->getMultitouchDevice(); + + if (device) + { + for (unsigned int i = 0; i < device->getButtonsCount(); i++) + { + MultitouchButton* button = device->getButton(i); + + if (button->type != BUTTON_STEERING) + continue; + + if (UserConfigParams::m_multitouch_accelerometer == 1) + { + button->axis_x = -event.AccelerometerEvent.X / 6.0f; + device->handleControls(button); + } + else if (UserConfigParams::m_multitouch_accelerometer == 2) + { + button->axis_x = event.AccelerometerEvent.Y / 6.0f; + device->handleControls(button); + } + } + } + } // block events in all modes but initial menus (except in text boxes to // allow typing, and except in modal dialogs in-game) diff --git a/src/input/multitouch_device.cpp b/src/input/multitouch_device.cpp index fea305662..7dc2db7af 100644 --- a/src/input/multitouch_device.cpp +++ b/src/input/multitouch_device.cpp @@ -36,6 +36,11 @@ MultitouchDevice::MultitouchDevice() m_type = DT_MULTITOUCH; m_name = "Multitouch"; m_player = NULL; +#ifdef ANDROID + m_android_device = dynamic_cast( + irr_driver->getDevice()); + assert(m_android_device != NULL); +#endif for (MultitouchEvent& event : m_events) { @@ -53,6 +58,13 @@ MultitouchDevice::MultitouchDevice() */ MultitouchDevice::~MultitouchDevice() { +#ifdef ANDROID + if (m_android_device->isAccelerometerActive()) + { + m_android_device->deactivateAccelerometer(); + } +#endif + clearButtons(); } @@ -177,8 +189,7 @@ void MultitouchDevice::updateDeviceState(unsigned int event_id) { button->pressed = false; button->event_id = 0; - button->axis_x = 0.0f; - button->axis_y = 0.0f; + updateButtonAxes(button, 0.0f, 0.0f); } } else @@ -190,15 +201,13 @@ void MultitouchDevice::updateDeviceState(unsigned int event_id) { if (button->pressed == true) { - button->axis_x = (float)(event.x - button->x) / - (button->width/2) - 1; - button->axis_y = (float)(event.y - button->y) / - (button->height/2) - 1; + updateButtonAxes(button, + (float)(event.x - button->x) / (button->width/2) - 1, + (float)(event.y - button->y) / (button->height/2) - 1); } else { - button->axis_x = 0.0f; - button->axis_y = 0.0f; + updateButtonAxes(button, 0.0f, 0.0f); } if (prev_axis_x != button->axis_x || @@ -232,6 +241,25 @@ void MultitouchDevice::updateConfigParams() m_deadzone_edge = UserConfigParams::m_multitouch_deadzone_edge; m_deadzone_edge = std::min(std::max(m_deadzone_edge, 0.0f), 0.5f); + +#ifdef ANDROID + if (UserConfigParams::m_multitouch_accelerometer > 0 && + !m_android_device->isAccelerometerActive()) + { + m_android_device->activateAccelerometer(1.0f / 30); + + // Disable accelerometer if it couldn't be activated + if (!m_android_device->isAccelerometerActive()) + { + UserConfigParams::m_multitouch_accelerometer = 0; + } + } + else if (UserConfigParams::m_multitouch_accelerometer == 0 && + m_android_device->isAccelerometerActive()) + { + m_android_device->deactivateAccelerometer(); + } +#endif } // updateConfigParams // ---------------------------------------------------------------------------- @@ -249,6 +277,26 @@ float MultitouchDevice::getSteeringFactor(float value) m_deadzone_center), 1.0f); } +/** Updates the button axes. It leaves X axis untouched if the accelerometer is + * used for turning left/right + * \param button A button that should be updated + * \param x A value from 0 to 1 + * \param y A value from 0 to 1 + */ +void MultitouchDevice::updateButtonAxes(MultitouchButton* button, float x, + float y) +{ + if (UserConfigParams::m_multitouch_accelerometer == 0) + { + button->axis_x = x; + } + + button->axis_y = y; +} + +// ---------------------------------------------------------------------------- + + // ---------------------------------------------------------------------------- /** Sends proper action for player controller depending on the button type * and state. diff --git a/src/input/multitouch_device.hpp b/src/input/multitouch_device.hpp index 580554dbf..63f0376f8 100644 --- a/src/input/multitouch_device.hpp +++ b/src/input/multitouch_device.hpp @@ -25,6 +25,10 @@ #include "input/input_device.hpp" #include "IEventReceiver.h" +#ifdef ANDROID +#include "../../../lib/irrlicht/source/Irrlicht/CIrrDeviceAndroid.h" +#endif + #define NUMBER_OF_MULTI_TOUCHES 10 enum MultitouchButtonType @@ -77,8 +81,14 @@ private: /** The parameter that is used for steering button and determines dead area * at the edge of button */ float m_deadzone_edge; + +#ifdef ANDROID + /** Pointer to the Android irrlicht device */ + CIrrDeviceAndroid* m_android_device; +#endif float getSteeringFactor(float value); + void updateButtonAxes(MultitouchButton* button, float x, float y); public: /** The array that contains data for all multitouch input events */ diff --git a/src/states_screens/dialogs/multitouch_settings_dialog.cpp b/src/states_screens/dialogs/multitouch_settings_dialog.cpp index 814f19091..7eea08379 100644 --- a/src/states_screens/dialogs/multitouch_settings_dialog.cpp +++ b/src/states_screens/dialogs/multitouch_settings_dialog.cpp @@ -78,7 +78,25 @@ GUIEngine::EventPropagation MultitouchSettingsDialog::processEvent( CheckBoxWidget* buttons_en = getWidget("buttons_enabled"); assert(buttons_en != NULL); UserConfigParams::m_multitouch_mode = buttons_en->getState() ? 1 : 0; - + + CheckBoxWidget* accel = getWidget("accelerometer_tablet"); + assert(accel != NULL); + CheckBoxWidget* accel2 = getWidget("accelerometer_phone"); + assert(accel2 != NULL); + + if (accel->getState()) + { + UserConfigParams::m_multitouch_accelerometer = 1; + } + else if (accel2->getState()) + { + UserConfigParams::m_multitouch_accelerometer = 2; + } + else + { + UserConfigParams::m_multitouch_accelerometer = 0; + } + MultitouchDevice* touch_device = input_manager->getDeviceManager()-> getMultitouchDevice(); @@ -98,11 +116,28 @@ 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(); updateValues(); return GUIEngine::EVENT_BLOCK; } + else if (eventSource == "accelerometer_disabled" || + eventSource == "accelerometer_tablet" || + eventSource == "accelerometer_phone") + { + CheckBoxWidget* accel = getWidget("accelerometer_disabled"); + assert(accel != NULL); + accel->setState(eventSource == accel->m_properties[PROP_ID]); + accel = getWidget("accelerometer_tablet"); + assert(accel != NULL); + accel->setState(eventSource == accel->m_properties[PROP_ID]); + accel = getWidget("accelerometer_phone"); + assert(accel != NULL); + accel->setState(eventSource == accel->m_properties[PROP_ID]); + + return GUIEngine::EVENT_BLOCK; + } return GUIEngine::EVENT_LET; } // processEvent @@ -128,6 +163,19 @@ void MultitouchSettingsDialog::updateValues() CheckBoxWidget* buttons_en = getWidget("buttons_enabled"); assert(buttons_en != NULL); buttons_en->setState(UserConfigParams::m_multitouch_mode); + + CheckBoxWidget* accelerometer; + accelerometer = getWidget("accelerometer_disabled"); + assert(accelerometer != NULL); + accelerometer->setState(UserConfigParams::m_multitouch_accelerometer == 0); + + accelerometer = getWidget("accelerometer_tablet"); + assert(accelerometer != NULL); + accelerometer->setState(UserConfigParams::m_multitouch_accelerometer == 1); + + accelerometer = getWidget("accelerometer_phone"); + assert(accelerometer != NULL); + accelerometer->setState(UserConfigParams::m_multitouch_accelerometer == 2); } // -----------------------------------------------------------------------------