|
@@ -28,6 +28,48 @@ extern "C"
|
|
|
|
|
|
|
|
namespace entry
|
|
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
|
|
struct MainThreadEntry
|
|
|
{
|
|
{
|
|
|
int m_argc;
|
|
int m_argc;
|
|
@@ -42,6 +84,15 @@ namespace entry
|
|
|
: m_window(NULL)
|
|
: m_window(NULL)
|
|
|
, m_count(0)
|
|
, 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)
|
|
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 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)
|
|
switch (type)
|
|
|
{
|
|
{
|
|
|
case AINPUT_EVENT_TYPE_MOTION:
|
|
case AINPUT_EVENT_TYPE_MOTION:
|
|
|
{
|
|
{
|
|
|
- float mx = AMotionEvent_getX(_event, 0);
|
|
|
|
|
- float my = AMotionEvent_getY(_event, 0);
|
|
|
|
|
- int32_t count = AMotionEvent_getPointerCount(_event);
|
|
|
|
|
|
|
+ if (0 != (source & (AINPUT_SOURCE_GAMEPAD|AINPUT_SOURCE_JOYSTICK) ) )
|
|
|
|
|
+ {
|
|
|
|
|
+ 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);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- 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;
|
|
|
|
|
|
|
+ return 1;
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ float mx = AMotionEvent_getX(_event, 0);
|
|
|
|
|
+ float my = AMotionEvent_getY(_event, 0);
|
|
|
|
|
+ int32_t count = AMotionEvent_getPointerCount(_event);
|
|
|
|
|
|
|
|
- WindowHandle defaultWindow = { 0 };
|
|
|
|
|
|
|
+ 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;
|
|
|
|
|
|
|
+ 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;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ 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 == count ? MouseButton::Left : MouseButton::Right
|
|
|
|
|
- , false
|
|
|
|
|
- );
|
|
|
|
|
-
|
|
|
|
|
- if (0 != m_count)
|
|
|
|
|
|
|
+ if (count != m_count)
|
|
|
{
|
|
{
|
|
|
m_eventQueue.postMouseEvent(defaultWindow
|
|
m_eventQueue.postMouseEvent(defaultWindow
|
|
|
, (int32_t)mx
|
|
, (int32_t)mx
|
|
|
, (int32_t)my
|
|
, (int32_t)my
|
|
|
, 0
|
|
, 0
|
|
|
- , 1 == m_count ? MouseButton::Left : MouseButton::Right
|
|
|
|
|
- , true
|
|
|
|
|
|
|
+ , 1 == count ? MouseButton::Left : MouseButton::Right
|
|
|
|
|
+ , false
|
|
|
);
|
|
);
|
|
|
|
|
+
|
|
|
|
|
+ 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)
|
|
|
|
|
+ {
|
|
|
|
|
+ case AMOTION_EVENT_ACTION_MOVE:
|
|
|
|
|
+ if (0 == index)
|
|
|
|
|
+ {
|
|
|
|
|
+ m_eventQueue.postMouseEvent(defaultWindow
|
|
|
|
|
+ , (int32_t)mx
|
|
|
|
|
+ , (int32_t)my
|
|
|
|
|
+ , 0
|
|
|
|
|
+ );
|
|
|
|
|
+ }
|
|
|
|
|
+ break;
|
|
|
|
|
+
|
|
|
|
|
+ default:
|
|
|
|
|
+ break;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+ }
|
|
|
|
|
+ break;
|
|
|
|
|
|
|
|
- switch (action)
|
|
|
|
|
|
|
+ case AINPUT_EVENT_TYPE_KEY:
|
|
|
|
|
+ {
|
|
|
|
|
+ int32_t keyCode = AKeyEvent_getKeyCode(_event);
|
|
|
|
|
+
|
|
|
|
|
+ if (0 != (source & (AINPUT_SOURCE_GAMEPAD|AINPUT_SOURCE_JOYSTICK) ) )
|
|
|
{
|
|
{
|
|
|
- case AMOTION_EVENT_ACTION_MOVE:
|
|
|
|
|
- if (0 == index)
|
|
|
|
|
|
|
+ for (uint32_t jj = 0; jj < BX_COUNTOF(s_gamepadRemap); ++jj)
|
|
|
{
|
|
{
|
|
|
- m_eventQueue.postMouseEvent(defaultWindow
|
|
|
|
|
- , (int32_t)mx
|
|
|
|
|
- , (int32_t)my
|
|
|
|
|
- , 0
|
|
|
|
|
- );
|
|
|
|
|
|
|
+ if (keyCode == s_gamepadRemap[jj].m_keyCode)
|
|
|
|
|
+ {
|
|
|
|
|
+ m_eventQueue.postKeyEvent(defaultWindow, s_gamepadRemap[jj].m_key, 0, actionBits == AKEY_EVENT_ACTION_DOWN);
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
- break;
|
|
|
|
|
-
|
|
|
|
|
- default:
|
|
|
|
|
- break;
|
|
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ return 1;
|
|
|
}
|
|
}
|
|
|
break;
|
|
break;
|
|
|
|
|
|
|
|
- case AINPUT_EVENT_TYPE_KEY:
|
|
|
|
|
|
|
+ default:
|
|
|
|
|
+ DBG("type %d", type);
|
|
|
break;
|
|
break;
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
return 0;
|
|
return 0;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -284,6 +387,8 @@ namespace entry
|
|
|
android_app* m_app;
|
|
android_app* m_app;
|
|
|
|
|
|
|
|
int32_t m_count;
|
|
int32_t m_count;
|
|
|
|
|
+ int32_t m_value[GamepadAxis::Count];
|
|
|
|
|
+ int32_t m_deadzone[GamepadAxis::Count];
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
static Context s_ctx;
|
|
static Context s_ctx;
|