Android: Added gamepad support.

This commit is contained in:
Branimir Karadžić 2014-12-29 13:53:44 -08:00
parent 37f5903f12
commit 527adf3c28

View file

@ -28,6 +28,48 @@ extern "C"
namespace entry
{
struct GamepadRemap
{
uint16_t m_keyCode;
Key::Enum m_key;
};
static GamepadRemap s_gamepadRemap[] =
{
{ AKEYCODE_DPAD_UP, Key::GamepadUp },
{ AKEYCODE_DPAD_DOWN, Key::GamepadDown },
{ AKEYCODE_DPAD_LEFT, Key::GamepadLeft },
{ AKEYCODE_DPAD_RIGHT, Key::GamepadRight },
{ AKEYCODE_BUTTON_START, Key::GamepadStart },
{ AKEYCODE_BACK, Key::GamepadBack },
{ AKEYCODE_BUTTON_THUMBL, Key::GamepadThumbL },
{ AKEYCODE_BUTTON_THUMBR, Key::GamepadThumbR },
{ AKEYCODE_BUTTON_L1, Key::GamepadShoulderL },
{ AKEYCODE_BUTTON_R1, Key::GamepadShoulderR },
{ AKEYCODE_GUIDE, Key::GamepadGuide },
{ AKEYCODE_BUTTON_A, Key::GamepadA },
{ AKEYCODE_BUTTON_B, Key::GamepadB },
{ AKEYCODE_BUTTON_X, Key::GamepadX },
{ AKEYCODE_BUTTON_Y, Key::GamepadY },
};
struct GamepadAxisRemap
{
int32_t m_event;
GamepadAxis::Enum m_axis;
bool m_convert;
};
static GamepadAxisRemap s_translateAxis[] =
{
{ AMOTION_EVENT_AXIS_X, GamepadAxis::LeftX, false },
{ AMOTION_EVENT_AXIS_Y, GamepadAxis::LeftY, false },
{ AMOTION_EVENT_AXIS_LTRIGGER, GamepadAxis::LeftZ, false },
{ AMOTION_EVENT_AXIS_Z, GamepadAxis::RightX, true },
{ AMOTION_EVENT_AXIS_RZ, GamepadAxis::RightY, false },
{ AMOTION_EVENT_AXIS_RTRIGGER, GamepadAxis::RightZ, false },
};
struct MainThreadEntry
{
int m_argc;
@ -42,6 +84,15 @@ namespace entry
: m_window(NULL)
, m_count(0)
{
memset(m_value, 0, sizeof(m_value) );
// Deadzone values from xinput.h
m_deadzone[GamepadAxis::LeftX ] =
m_deadzone[GamepadAxis::LeftY ] = 7849;
m_deadzone[GamepadAxis::RightX] =
m_deadzone[GamepadAxis::RightY] = 8689;
m_deadzone[GamepadAxis::LeftZ ] =
m_deadzone[GamepadAxis::RightZ] = 30;
}
void run(android_app* _app)
@ -180,86 +231,138 @@ namespace entry
}
}
bool filter(GamepadAxis::Enum _axis, int32_t* _value)
{
const int32_t old = m_value[_axis];
const int32_t deadzone = m_deadzone[_axis];
int32_t value = *_value;
value = value > deadzone || value < -deadzone ? value : 0;
m_value[_axis] = value;
*_value = value;
return old != value;
}
int32_t onInputEvent(AInputEvent* _event)
{
int32_t type = AInputEvent_getType(_event);
WindowHandle defaultWindow = { 0 };
GamepadHandle handle = { 0 };
const int32_t type = AInputEvent_getType(_event);
const int32_t source = AInputEvent_getSource(_event);
const int32_t actionBits = AMotionEvent_getAction(_event);
switch (type)
{
case AINPUT_EVENT_TYPE_MOTION:
{
float mx = AMotionEvent_getX(_event, 0);
float my = AMotionEvent_getY(_event, 0);
int32_t count = AMotionEvent_getPointerCount(_event);
int32_t actionBits = AMotionEvent_getAction(_event);
int32_t action = (actionBits & AMOTION_EVENT_ACTION_MASK);
int32_t index = (actionBits & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
WindowHandle defaultWindow = { 0 };
count = m_count;
switch (action)
if (0 != (source & (AINPUT_SOURCE_GAMEPAD|AINPUT_SOURCE_JOYSTICK) ) )
{
case AMOTION_EVENT_ACTION_DOWN:
case AMOTION_EVENT_ACTION_POINTER_DOWN:
m_count++;
break;
for (uint32_t ii = 0; ii < BX_COUNTOF(s_translateAxis); ++ii)
{
const float fval = AMotionEvent_getAxisValue(_event, s_translateAxis[ii].m_event, 0);
int32_t value = int32_t( (s_translateAxis[ii].m_convert ? fval * 2.0f + 1.0f : fval) * INT16_MAX);
GamepadAxis::Enum axis = s_translateAxis[ii].m_axis;
if (filter(axis, &value) )
{
m_eventQueue.postAxisEvent(defaultWindow, handle, axis, value);
}
}
case AMOTION_EVENT_ACTION_UP:
case AMOTION_EVENT_ACTION_POINTER_UP:
m_count--;
break;
default:
break;
return 1;
}
if (count != m_count)
else
{
m_eventQueue.postMouseEvent(defaultWindow
, (int32_t)mx
, (int32_t)my
, 0
, 1 == count ? MouseButton::Left : MouseButton::Right
, false
);
float mx = AMotionEvent_getX(_event, 0);
float my = AMotionEvent_getY(_event, 0);
int32_t count = AMotionEvent_getPointerCount(_event);
if (0 != m_count)
int32_t action = (actionBits & AMOTION_EVENT_ACTION_MASK);
int32_t index = (actionBits & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
count = m_count;
switch (action)
{
case AMOTION_EVENT_ACTION_DOWN:
case AMOTION_EVENT_ACTION_POINTER_DOWN:
m_count++;
break;
case AMOTION_EVENT_ACTION_UP:
case AMOTION_EVENT_ACTION_POINTER_UP:
m_count--;
break;
default:
break;
}
if (count != m_count)
{
m_eventQueue.postMouseEvent(defaultWindow
, (int32_t)mx
, (int32_t)my
, 0
, 1 == m_count ? MouseButton::Left : MouseButton::Right
, true
, 1 == count ? MouseButton::Left : MouseButton::Right
, false
);
}
}
switch (action)
{
case AMOTION_EVENT_ACTION_MOVE:
if (0 == index)
if (0 != m_count)
{
m_eventQueue.postMouseEvent(defaultWindow
, (int32_t)mx
, (int32_t)my
, 0
, 1 == m_count ? MouseButton::Left : MouseButton::Right
, true
);
}
}
switch (action)
{
m_eventQueue.postMouseEvent(defaultWindow
, (int32_t)mx
, (int32_t)my
, 0
);
}
break;
case AMOTION_EVENT_ACTION_MOVE:
if (0 == index)
{
m_eventQueue.postMouseEvent(defaultWindow
, (int32_t)mx
, (int32_t)my
, 0
);
}
break;
default:
break;
default:
break;
}
}
}
break;
case AINPUT_EVENT_TYPE_KEY:
{
int32_t keyCode = AKeyEvent_getKeyCode(_event);
if (0 != (source & (AINPUT_SOURCE_GAMEPAD|AINPUT_SOURCE_JOYSTICK) ) )
{
for (uint32_t jj = 0; jj < BX_COUNTOF(s_gamepadRemap); ++jj)
{
if (keyCode == s_gamepadRemap[jj].m_keyCode)
{
m_eventQueue.postKeyEvent(defaultWindow, s_gamepadRemap[jj].m_key, 0, actionBits == AKEY_EVENT_ACTION_DOWN);
break;
}
}
}
return 1;
}
break;
default:
DBG("type %d", type);
break;
}
return 0;
}
@ -284,6 +387,8 @@ namespace entry
android_app* m_app;
int32_t m_count;
int32_t m_value[GamepadAxis::Count];
int32_t m_deadzone[GamepadAxis::Count];
};
static Context s_ctx;