diff --git a/examples/common/entry/entry_android.cpp b/examples/common/entry/entry_android.cpp index 95b1a479..7bc8f61c 100644 --- a/examples/common/entry/entry_android.cpp +++ b/examples/common/entry/entry_android.cpp @@ -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;