mirror of
https://github.com/scratchfoundation/bgfx.git
synced 2024-11-28 10:35:43 -05:00
Android: Added gamepad support.
This commit is contained in:
parent
37f5903f12
commit
527adf3c28
1 changed files with 157 additions and 52 deletions
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue