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.
This commit is contained in:
Deve 2017-02-07 13:48:08 +01:00
parent a40fd4cde9
commit 4852664143
7 changed files with 183 additions and 28 deletions

View File

@ -3,22 +3,18 @@
<div x="2%" y="1%" width="96%" height="98%" layout="vertical-row" >
<header id="title" width="100%" height="fit" text_align="center" word_wrap="true" text="Touch Device Settings" />
<spacer height="30" width="10" />
<spacer height="35" width="10" />
<label width="100%" I18N="In the multitouch settings screen" text="General"/>
<spacer height="15" width="10"/>
<div width="75%" height="fit" layout="horizontal-row" >
<label proportion="1" height="100%" text_align="right" I18N="In the multitouch settings screen" text="Device enabled"/>
<div proportion="1" height="fit" layout="horizontal-row" >
<spacer width="40" height="100%" />
<checkbox id="buttons_enabled" width="40" height="40"/>
<checkbox id="buttons_enabled"/>
</div>
</div>
<spacer height="15" width="10"/>
<div width="75%" height="fit" layout="horizontal-row" >
<label proportion="1" height="100%" text_align="right" I18N="In the multitouch settings screen" text="Buttons scale"/>
<div proportion="1" height="fit" layout="horizontal-row" >
@ -26,13 +22,35 @@
<gauge id="scale" proportion="1" min_value="50" max_value="150"/>
</div>
</div>
<label width="100%" I18N="In the multitouch settings screen" text="Accelerometer"/>
<spacer height="45" width="10"/>
<div width="75%" height="fit" layout="horizontal-row" >
<label proportion="1" height="100%" text_align="right" I18N="In the multitouch settings screen" text="Disabled"/>
<div proportion="1" height="fit" layout="horizontal-row" >
<spacer width="40" height="100%" />
<checkbox id="accelerometer_disabled"/>
</div>
</div>
<div width="75%" height="fit" layout="horizontal-row" >
<label proportion="1" height="100%" text_align="right" I18N="In the multitouch settings screen" text="Phone"/>
<div proportion="1" height="fit" layout="horizontal-row" >
<spacer width="40" height="100%" />
<checkbox id="accelerometer_phone"/>
</div>
</div>
<div width="75%" height="fit" layout="horizontal-row" >
<label proportion="1" height="100%" text_align="right" I18N="In the multitouch settings screen" text="Tablet"/>
<div proportion="1" height="fit" layout="horizontal-row" >
<spacer width="40" height="100%" />
<checkbox id="accelerometer_tablet"/>
</div>
</div>
<label width="100%" I18N="In the multitouch settings screen" text="Advanced"/>
<spacer height="15" width="10"/>
<div width="75%" height="fit" layout="horizontal-row" >
<label proportion="1" height="100%" text_align="right" I18N="In the multitouch settings screen" text="Deadzone center"/>
<div proportion="1" height="fit" layout="horizontal-row" >
@ -41,8 +59,6 @@
</div>
</div>
<spacer height="15" width="10"/>
<div width="75%" height="fit" layout="horizontal-row" >
<label proportion="1" height="100%" text_align="right" I18N="In the multitouch settings screen" text="Deadzone edge"/>
<div proportion="1" height="fit" layout="horizontal-row" >
@ -51,12 +67,13 @@
</div>
</div>
<spacer height="45" width="10"/>
<spacer height="35" width="10"/>
<button id="restore" text="Restore defaults" align="center"/>
<spacer height="15" width="10"/>
<button id="close" text="Apply" align="center"/>
<div width="fit" height="fit" layout="horizontal-row" align="center">
<button id="restore" text="Restore defaults"/>
<spacer width="40" height="100%" />
<button id="close" text="Apply"/>
</div>
</div>
</stkgui>

View File

@ -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",

View File

@ -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 &&

View File

@ -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)

View File

@ -36,6 +36,11 @@ MultitouchDevice::MultitouchDevice()
m_type = DT_MULTITOUCH;
m_name = "Multitouch";
m_player = NULL;
#ifdef ANDROID
m_android_device = dynamic_cast<CIrrDeviceAndroid*>(
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.

View File

@ -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 */

View File

@ -78,7 +78,25 @@ GUIEngine::EventPropagation MultitouchSettingsDialog::processEvent(
CheckBoxWidget* buttons_en = getWidget<CheckBoxWidget>("buttons_enabled");
assert(buttons_en != NULL);
UserConfigParams::m_multitouch_mode = buttons_en->getState() ? 1 : 0;
CheckBoxWidget* accel = getWidget<CheckBoxWidget>("accelerometer_tablet");
assert(accel != NULL);
CheckBoxWidget* accel2 = getWidget<CheckBoxWidget>("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<CheckBoxWidget>("accelerometer_disabled");
assert(accel != NULL);
accel->setState(eventSource == accel->m_properties[PROP_ID]);
accel = getWidget<CheckBoxWidget>("accelerometer_tablet");
assert(accel != NULL);
accel->setState(eventSource == accel->m_properties[PROP_ID]);
accel = getWidget<CheckBoxWidget>("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<CheckBoxWidget>("buttons_enabled");
assert(buttons_en != NULL);
buttons_en->setState(UserConfigParams::m_multitouch_mode);
CheckBoxWidget* accelerometer;
accelerometer = getWidget<CheckBoxWidget>("accelerometer_disabled");
assert(accelerometer != NULL);
accelerometer->setState(UserConfigParams::m_multitouch_accelerometer == 0);
accelerometer = getWidget<CheckBoxWidget>("accelerometer_tablet");
assert(accelerometer != NULL);
accelerometer->setState(UserConfigParams::m_multitouch_accelerometer == 1);
accelerometer = getWidget<CheckBoxWidget>("accelerometer_phone");
assert(accelerometer != NULL);
accelerometer->setState(UserConfigParams::m_multitouch_accelerometer == 2);
}
// -----------------------------------------------------------------------------