Răsfoiți Sursa

Merge pull request #1573 from seanpaultaylor/next

Next
Sean Taylor 11 ani în urmă
părinte
comite
574b2b5ffc

+ 4 - 22
gameplay/android/build.xml

@@ -3,10 +3,10 @@
 
     <property file="local.properties" />
     <property file="ant.properties" />
-    
+   
     <loadproperties srcFile="project.properties" />
     
-    <fail message="sdk.dir is missing. Make sure to generate local.properties using 'android update project'" unless="sdk.dir" />
+    <fail message="sdk.dir is missing. Make sure to generate local.properties using 'android update project -t 1 -p . -s'" unless="sdk.dir" />
     <fail message="OS not supported. Supported platforms: Windows, MacOS X or Linux.">
         <condition>
             <not>
@@ -20,26 +20,8 @@
     <macrodef name="build-native">
         <attribute name="location"/>
         <sequential>
-            <exec osfamily="unix" dir="@{location}/android" executable="android">
-                <arg value="update"/>
-                <arg value="project"/>
-                <arg value="-t"/>
-                <arg value="1"/>
-                <arg value="-p"/>
-                <arg value="."/>
-                <arg value="-s"/>
-            </exec>
-            <exec osfamily="unix" dir="@{location}/android" executable="ndk-build"/>
-            <exec osfamily="windows" dir="@{location}/android" executable="cmd">
-                <arg value="/c"/>
-                <arg value="android.bat"/>
-                <arg value="update"/>
-                <arg value="project"/>
-                <arg value="-t"/>
-                <arg value="1"/>
-                <arg value="-p"/>
-                <arg value="."/>
-                <arg value="-s"/>
+            <exec osfamily="unix" dir="@{location}/android" executable="ndk-build">
+                <arg value="-j4"/>
             </exec>
             <exec osfamily="windows" dir="@{location}/android" executable="cmd">
                 <arg value="/c"/>

+ 5 - 2
gameplay/src/Base.h

@@ -278,9 +278,12 @@ typedef GLuint FrameBufferHandle;
 /** Render buffer handle. */
 typedef GLuint RenderBufferHandle;
 
-/** Gamepad handle definitions vary by platform. */
+/** Gamepad handle */
+#ifdef __ANDROID__
+typedef unsigned int GamepadHandle;
+#else
 typedef unsigned long GamepadHandle;
-
+#endif
 }
 
 /**

+ 11 - 1
gameplay/src/Control.cpp

@@ -1078,7 +1078,17 @@ bool Control::mouseEvent(Mouse::MouseEvent evt, int x, int y, int wheelDelta)
     return false;
 }
 
-bool Control::gamepadEvent(Gamepad::GamepadEvent evt, Gamepad* gamepad, unsigned int analogIndex)
+bool Control::gamepadButtonEvent(Gamepad* gamepad)
+{
+    return false;
+}
+
+bool Control::gamepadTriggerEvent(Gamepad* gamepad, unsigned int index)
+{
+    return false;
+}
+
+bool Control::gamepadJoystickEvent(Gamepad* gamepad, unsigned int index)
 {
     return false;
 }

+ 19 - 5
gameplay/src/Control.h

@@ -1096,13 +1096,27 @@ protected:
     virtual bool mouseEvent(Mouse::MouseEvent evt, int x, int y, int wheelDelta);
 
     /**
-     * Gamepad callback on gamepad events.
+     * Gamepad callback on gamepad button changes.
      *
-     * @param gamepad The gamepad whose state changed.
-     * @param evt The gamepad event that occurred.
-     * @param analogIndex If evt is JOYSTICK_EVENT or TRIGGER_EVENT, this will be the index of the corresponding control.
+     * @param gamepad The gamepad whose one or more buttons have changed.
      */
-    virtual bool gamepadEvent(Gamepad::GamepadEvent evt, Gamepad* gamepad, unsigned int analogIndex);
+    virtual bool gamepadButtonEvent(Gamepad* gamepad);
+
+    /**
+     * Gamepad callback on gamepad trigger changes.
+     *
+     * @param gamepad The gamepad whose one or more buttons have changed.
+     * @param index The index of the trigger that changed. 
+     */
+    virtual bool gamepadTriggerEvent(Gamepad* gamepad, unsigned int index);
+
+    /**
+     * Gamepad callback on gamepad analog joystick changes.
+     *
+     * @param gamepad The gamepad whose one or more buttons have changed.
+     * @param index The index of the joystick that changed.
+     */
+    virtual bool gamepadJoystickEvent(Gamepad* gamepad, unsigned int index);
 
     /**
      * Called each frame to update this control and its children.

+ 59 - 32
gameplay/src/Form.cpp

@@ -10,8 +10,8 @@
 #include "CheckBox.h"
 #include "Scene.h"
 
-// Scroll speed when using a DPad -- max scroll speed when using a joystick.
-static const float GAMEPAD_SCROLL_SPEED = 500.0f;
+// Scroll speed when using a joystick.
+static const float GAMEPAD_SCROLL_SPEED = 600.0f;
 // Distance a joystick must be pushed in order to trigger focus-change and/or scrolling.
 static const float JOYSTICK_THRESHOLD = 0.75f;
 // If the DPad or joystick is held down, this is the initial delay in milliseconds between focus changes.
@@ -903,7 +903,7 @@ bool Form::pollGamepad(Gamepad* gamepad)
     return focusPressed || scrolling;
 }
 
-bool Form::gamepadEventInternal(Gamepad::GamepadEvent evt, Gamepad* gamepad, unsigned int analogIndex)
+bool Form::gamepadButtonEventInternal(Gamepad* gamepad)
 {
     if (!__focusControl)
         return false;
@@ -911,56 +911,83 @@ bool Form::gamepadEventInternal(Gamepad::GamepadEvent evt, Gamepad* gamepad, uns
     bool selectButtonPressed = gamepad->isButtonDown(Gamepad::BUTTON_A) || gamepad->isButtonDown(Gamepad::BUTTON_X);
 
     // Fire press, release and click events to focused controls
-    switch (evt)
+    if (selectButtonPressed && __focusControl->_state != ACTIVE)
     {
-    case Gamepad::BUTTON_EVENT:
-        if (selectButtonPressed && __focusControl->_state != ACTIVE)
-        {
-            if (__activeControl[0])
-                __activeControl[0]->setDirty(DIRTY_STATE);
+        if (__activeControl[0])
+            __activeControl[0]->setDirty(DIRTY_STATE);
 
-            __activeControl[0] = __focusControl;
-            __focusControl->_state = ACTIVE;
-            __focusControl->notifyListeners(Control::Listener::PRESS);
-            return true;
-        }
-        else if (!selectButtonPressed && __focusControl->_state == ACTIVE)
-        {
-            if (__activeControl[0])
-                __activeControl[0]->setDirty(DIRTY_STATE);
+        __activeControl[0] = __focusControl;
+        __focusControl->_state = ACTIVE;
+        __focusControl->notifyListeners(Control::Listener::PRESS);
+        return true;
+    }
+    else if (!selectButtonPressed && __focusControl->_state == ACTIVE)
+    {
+        if (__activeControl[0])
+            __activeControl[0]->setDirty(DIRTY_STATE);
 
-            for (unsigned int i = 0; i < Touch::MAX_TOUCH_POINTS; ++i)
+        for (unsigned int i = 0; i < Touch::MAX_TOUCH_POINTS; ++i)
+        {
+            if (__activeControl[i] == __focusControl)
             {
-                if (__activeControl[i] == __focusControl)
-                {
-                    __activeControl[i] = NULL;
-                }
+                __activeControl[i] = NULL;
             }
-
-            __focusControl->_state = NORMAL;
-            __focusControl->notifyListeners(Control::Listener::RELEASE);
-            __focusControl->notifyListeners(Control::Listener::CLICK);
-            return true;
         }
-        break;
+
+        __focusControl->_state = NORMAL;
+        __focusControl->notifyListeners(Control::Listener::RELEASE);
+        __focusControl->notifyListeners(Control::Listener::CLICK);
+        return true;
     }
 
-    // Dispatch gamepad events to focused controls (or their parents)
-    Control * ctrl = __focusControl;
+    // Dispatch gamepad button events to focused controls (or their parents)
+    Control* ctrl = __focusControl;
     while (ctrl)
     {
         if (ctrl->isEnabled() && ctrl->isVisible())
         {
-            if (ctrl->gamepadEvent(evt, gamepad, analogIndex))
+            if (ctrl->gamepadButtonEvent(gamepad))
                 return true;
         }
 
         ctrl = ctrl->getParent();
     }
+    return false;
+}
+
+bool Form::gamepadTriggerEventInternal(Gamepad* gamepad, unsigned int index)
+{
+    // Dispatch gamepad trigger events to focused controls (or their parents)
+    Control* ctrl = __focusControl;
+    while (ctrl)
+    {
+        if (ctrl->isEnabled() && ctrl->isVisible())
+        {
+            if (ctrl->gamepadTriggerEvent(gamepad, index))
+                return true;
+        }
 
+        ctrl = ctrl->getParent();
+    }
     return false;
 }
 
+bool Form::gamepadJoystickEventInternal(Gamepad* gamepad, unsigned int index)
+{
+    // Dispatch gamepad joystick events to focused controls (or their parents)
+    Control* ctrl = __focusControl;
+    while (ctrl)
+    {
+        if (ctrl->isEnabled() && ctrl->isVisible())
+        {
+            if (ctrl->gamepadJoystickEvent(gamepad, index))
+                return true;
+        }
+
+        ctrl = ctrl->getParent();
+    }
+    return false;
+}
 void Form::resizeEventInternal(unsigned int width, unsigned int height)
 {
     for (size_t i = 0, size = __forms.size(); i < size; ++i)

+ 17 - 3
gameplay/src/Form.h

@@ -201,11 +201,25 @@ private:
     static bool mouseEventInternal(Mouse::MouseEvent evt, int x, int y, int wheelDelta);
 
     /**
-     * Propagate gamepad events to enabled forms.
+     * Propagate gamepad button events to enabled forms.
      *
-     * @see Control::gamepadEvent
+     * @see Control::gamepadButtonEventInternal
      */
-    static bool gamepadEventInternal(Gamepad::GamepadEvent evt, Gamepad* gamepad, unsigned int analogIndex);
+    static bool gamepadButtonEventInternal(Gamepad* gamepad);
+
+    /**
+     * Propagate gamepad trigger events to enabled forms.
+     *
+     * @see Control::gamepadTriggerEventInternal
+     */
+    static bool gamepadTriggerEventInternal(Gamepad* gamepad, unsigned int index);
+
+    /**
+     * Propagate gamepad button events to enabled forms.
+     *
+     * @see Control::gamepadJoystickEventInternal
+     */
+    static bool gamepadJoystickEventInternal(Gamepad* gamepad, unsigned int index);
 
     /**
      * Fired by the platform when the game window resizes.

+ 3 - 3
gameplay/src/Gamepad.cpp

@@ -389,7 +389,7 @@ void Gamepad::setButtons(unsigned int buttons)
     if (buttons != _buttons)
     {
         _buttons = buttons;
-        Platform::gamepadEventInternal(BUTTON_EVENT, this);
+        Form::gamepadButtonEventInternal(this);
     }
 }
 
@@ -398,7 +398,7 @@ void Gamepad::setJoystickValue(unsigned int index, float x, float y)
     if (_joysticks[index].x != x || _joysticks[index].y != y)
     {
         _joysticks[index].set(x, y);
-        Platform::gamepadEventInternal(JOYSTICK_EVENT, this, index);
+        Form::gamepadJoystickEventInternal(this, index);
     }
 }
 
@@ -407,7 +407,7 @@ void Gamepad::setTriggerValue(unsigned int index, float value)
     if (_triggers[index] != value)
     {
         _triggers[index] = value;
-        Platform::gamepadEventInternal(TRIGGER_EVENT, this, index);
+        Form::gamepadTriggerEventInternal(this, index);
     }
 }
 

+ 9 - 12
gameplay/src/Gamepad.h

@@ -32,17 +32,14 @@ public:
     enum GamepadEvent
     {
         CONNECTED_EVENT,
-        DISCONNECTED_EVENT,
-        BUTTON_EVENT,
-        JOYSTICK_EVENT,
-        TRIGGER_EVENT
+        DISCONNECTED_EVENT
     };
 
     /**
      * Gamepad buttons.
      */
     enum ButtonMapping
-    {
+    {        
         BUTTON_A,
         BUTTON_B,
         BUTTON_C,
@@ -192,9 +189,9 @@ private:
      * @param vendorString The vendor string/name.
      * @param productString The product string/name.
      */
-    Gamepad(GamepadHandle handle, 
-            unsigned int buttonCount, unsigned int joystickCount, unsigned int triggerCount,
-            unsigned int vendorId, unsigned int productId, const char* vendorString, const char* productString);
+    Gamepad(GamepadHandle handle, unsigned int buttonCount, unsigned int joystickCount, unsigned int triggerCount,
+            unsigned int vendorId, unsigned int productId, 
+            const char* vendorString, const char* productString);
 
     /**
      * Copy constructor.
@@ -208,9 +205,9 @@ private:
 
     static void updateInternal(float elapsedTime);
 
-    static Gamepad* add(GamepadHandle handle, 
-                        unsigned int buttonCount, unsigned int joystickCount, unsigned int triggerCount,
-                        unsigned int vendorId, unsigned int productId, const char* vendorString, const char* productString);
+    static Gamepad* add(GamepadHandle handle, unsigned int buttonCount, unsigned int joystickCount, unsigned int triggerCount,
+                        unsigned int vendorId, unsigned int productId, 
+                        const char* vendorString, const char* productString);
 
     static Gamepad* add(const char* formPath);
 
@@ -220,7 +217,7 @@ private:
 
     static unsigned int getGamepadCount();
 
-    static Gamepad* getGamepad(unsigned int index, bool preferPhysical = true);
+    static Gamepad* getGamepad(unsigned int index, bool preferPhysical);
 
     static Gamepad* getGamepad(GamepadHandle handle);
 

+ 30 - 17
gameplay/src/Platform.cpp

@@ -44,49 +44,42 @@ bool Platform::mouseEventInternal(Mouse::MouseEvent evt, int x, int y, int wheel
 
 void Platform::gestureSwipeEventInternal(int x, int y, int direction)
 {
-    // TODO: Add support to Form for gestures
     Game::getInstance()->gestureSwipeEvent(x, y, direction);
     Game::getInstance()->getScriptController()->gestureSwipeEvent(x, y, direction);
 }
 
 void Platform::gesturePinchEventInternal(int x, int y, float scale)
 {
-    // TODO: Add support to Form for gestures
     Game::getInstance()->gesturePinchEvent(x, y, scale);
     Game::getInstance()->getScriptController()->gesturePinchEvent(x, y, scale);
 }
 
 void Platform::gestureTapEventInternal(int x, int y)
 {
-    // TODO: Add support to Form for gestures
     Game::getInstance()->gestureTapEvent(x, y);
     Game::getInstance()->getScriptController()->gestureTapEvent(x, y);
 }
 
 void Platform::gestureLongTapEventInternal(int x, int y, float duration)
 {
-    // TODO: Add support to Form for gestures
 	Game::getInstance()->gestureLongTapEvent(x, y, duration);
 	Game::getInstance()->getScriptController()->gestureLongTapEvent(x, y, duration);
 }
 
 void Platform::gestureDragEventInternal(int x, int y)
 {
-    // TODO: Add support to Form for gestures
 	Game::getInstance()->gestureDragEvent(x, y);
 	Game::getInstance()->getScriptController()->gestureDragEvent(x, y);
 }
 
 void Platform::gestureDropEventInternal(int x, int y)
 {
-    // TODO: Add support to Form for gestures
 	Game::getInstance()->gestureDropEvent(x, y);
 	Game::getInstance()->getScriptController()->gestureDropEvent(x, y);
 }
 
 void Platform::resizeEventInternal(unsigned int width, unsigned int height)
 {
-    // Update the width and height of the game
     Game* game = Game::getInstance();
     if (game->_width != width || game->_height != height)
     {
@@ -95,19 +88,9 @@ void Platform::resizeEventInternal(unsigned int width, unsigned int height)
         game->resizeEvent(width, height);
         game->getScriptController()->resizeEvent(width, height);
     }
-
     Form::resizeEventInternal(width, height);
 }
 
-void Platform::gamepadEventInternal(Gamepad::GamepadEvent evt, Gamepad* gamepad, unsigned int analogIndex)
-{
-    if (!Form::gamepadEventInternal(evt, gamepad, analogIndex))
-    {
-        Game::getInstance()->gamepadEvent(evt, gamepad);
-        Game::getInstance()->getScriptController()->gamepadEvent(evt, gamepad);
-    }
-}
-
 void Platform::gamepadEventConnectedInternal(GamepadHandle handle,  unsigned int buttonCount, unsigned int joystickCount, unsigned int triggerCount,
                                              unsigned int vendorId, unsigned int productId, const char* vendorString, const char* productString)
 {
@@ -119,4 +102,34 @@ void Platform::gamepadEventDisconnectedInternal(GamepadHandle handle)
     Gamepad::remove(handle);
 }
 
+void Platform::gamepadButtonPressedEventInternal(GamepadHandle handle, Gamepad::ButtonMapping mapping)
+{
+    Gamepad* gamepad = Gamepad::getGamepad(handle);
+    unsigned int newButtons = gamepad->_buttons | (1 << mapping);
+    gamepad->setButtons(newButtons);
+    Form::gamepadButtonEventInternal(gamepad);
+}
+
+void Platform::gamepadButtonReleasedEventInternal(GamepadHandle handle, Gamepad::ButtonMapping mapping)
+{
+    Gamepad* gamepad = Gamepad::getGamepad(handle);
+    unsigned int newButtons = gamepad->_buttons & ~(1 << mapping);
+    gamepad->setButtons(newButtons);
+    Form::gamepadButtonEventInternal(gamepad);
+}
+
+void Platform::gamepadTriggerChangedEventInternal(GamepadHandle handle, unsigned int index, float value)
+{
+    Gamepad* gamepad = Gamepad::getGamepad(handle);
+    gamepad->setTriggerValue(index, value);
+    Form::gamepadTriggerEventInternal(gamepad, index);
+}
+
+void Platform::gamepadJoystickChangedEventInternal(GamepadHandle handle, unsigned int index, float x, float y)
+{
+    Gamepad* gamepad = Gamepad::getGamepad(handle);
+    gamepad->setJoystickValue(index, x, y);
+    Form::gamepadJoystickEventInternal(gamepad, index);
+}
+
 }

+ 30 - 7
gameplay/src/Platform.h

@@ -370,27 +370,50 @@ public:
      *
      * @script{ignore}
      */
-    static void gamepadEventInternal(Gamepad::GamepadEvent evt, Gamepad* gamepad, unsigned int analogIndex = 0);
+    static void gamepadEventConnectedInternal(GamepadHandle handle, unsigned int buttonCount, unsigned int joystickCount, unsigned int triggerCount,
+                                              unsigned int vendorId, unsigned int productId,
+                                              const char* vendorString, const char* productString);
 
     /**
      * Internal method used only from static code in various platform implementation.
      *
      * @script{ignore}
      */
-    static void gamepadEventConnectedInternal(GamepadHandle handle, unsigned int buttonCount, unsigned int joystickCount, unsigned int triggerCount,
-                                              unsigned int vendorId, unsigned int productId,
-                                              const char* vendorString, const char* productString);
+    static void gamepadEventDisconnectedInternal(GamepadHandle handle);
 
     /**
      * Internal method used only from static code in various platform implementation.
      *
      * @script{ignore}
      */
-    static void gamepadEventDisconnectedInternal(GamepadHandle handle);
+    static void gamepadButtonPressedEventInternal(GamepadHandle handle, Gamepad::ButtonMapping mapping);
+
+    /**
+     * Internal method used only from static code in various platform implementation.
+     *
+     * @script{ignore}
+     */
+    static void gamepadButtonReleasedEventInternal(GamepadHandle handle, Gamepad::ButtonMapping button);
 
     /**
-     * Internal method used by Gamepad that polls the platform for the updated Gamepad
-     * states such as joysticks, buttons and trigger values.
+     * Internal method used only from static code in various platform implementation.
+     *
+     * @script{ignore}
+     */
+    static void gamepadTriggerChangedEventInternal(GamepadHandle handle, unsigned int index, float value);
+
+    /**
+     * Internal method used only from static code in various platform implementation.
+     *
+     * @script{ignore}
+     */
+    static void gamepadJoystickChangedEventInternal(GamepadHandle handle, unsigned int index, float x, float y);
+
+    /**
+     * Internal method used to poll the platform for the updated Gamepad
+     * states such as buttons, joytick and trigger values.
+     *
+     * Some platforms require to poll the gamepad system to get deltas. 
      *
      * @param gamepad The gamepad to be returned with the latest polled values populated.
      * @script{ignore}

+ 408 - 282
gameplay/src/PlatformAndroid.cpp

@@ -4,6 +4,7 @@
 #include "Platform.h"
 #include "FileSystem.h"
 #include "Game.h"
+#include "Gamepad.h"
 #include "Form.h"
 #include "ScriptController.h"
 #include <unistd.h>
@@ -701,9 +702,69 @@ static int getUnicode(int keycode, int metastate)
     }
 }
 
+Gamepad::ButtonMapping getGamepadButtonMapping(jint keycode)
+{
+    switch (keycode)
+    {
+    case AKEYCODE_BUTTON_X:
+        return Gamepad::BUTTON_X;
+    case AKEYCODE_BUTTON_Y:
+        return Gamepad::BUTTON_Y;
+    case AKEYCODE_BUTTON_Z:
+        return Gamepad::BUTTON_Z;
+    case AKEYCODE_BUTTON_A:
+    case AKEYCODE_DPAD_CENTER:
+        return Gamepad::BUTTON_A;
+    case AKEYCODE_BUTTON_B:
+        return Gamepad::BUTTON_B;
+    case AKEYCODE_BUTTON_C:
+        return Gamepad::BUTTON_C;
+    case AKEYCODE_BUTTON_L1:
+        return Gamepad::BUTTON_L1;
+    case AKEYCODE_BUTTON_L2:
+        return Gamepad::BUTTON_L2;
+    case AKEYCODE_BUTTON_THUMBL:
+        return Gamepad::BUTTON_L3;
+    case AKEYCODE_BUTTON_R1:
+        return Gamepad::BUTTON_R1;
+    case AKEYCODE_BUTTON_R2:
+        return Gamepad::BUTTON_R2;
+    case AKEYCODE_BUTTON_THUMBR:
+        return Gamepad::BUTTON_R3;
+    case AKEYCODE_BUTTON_SELECT:
+    case AKEYCODE_BACK:
+        return Gamepad::BUTTON_MENU1;
+    case AKEYCODE_BUTTON_START:
+        return Gamepad::BUTTON_MENU2;
+    case AKEYCODE_BUTTON_MODE:
+        return Gamepad::BUTTON_MENU3;
+    case AKEYCODE_DPAD_UP:
+        return Gamepad::BUTTON_UP;
+    case AKEYCODE_DPAD_DOWN:
+        return Gamepad::BUTTON_DOWN;
+    case AKEYCODE_DPAD_LEFT:
+        return Gamepad::BUTTON_LEFT;
+    case AKEYCODE_DPAD_RIGHT:
+        return Gamepad::BUTTON_RIGHT;
+    default:
+        break;
+    }
+    return Gamepad::BUTTON_MENU4;
+}
+
+static float clampFuzz(float value, float fuzz)
+{
+    if (std::fabs(value) <= fuzz)
+        return 0.0f;
+    return value;
+}
+
 // Process the next input event.
 static int32_t engine_handle_input(struct android_app* app, AInputEvent* event)
 {
+    int32_t deviceId = AInputEvent_getDeviceId(event);
+    int32_t source = AInputEvent_getSource(event);
+
     if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION)
     {
         int32_t action = AMotionEvent_getAction(event);
@@ -713,305 +774,364 @@ static int32_t engine_handle_input(struct android_app* app, AInputEvent* event)
         int x;
         int y;
         
-        switch (action & AMOTION_EVENT_ACTION_MASK)
+        if (source & AINPUT_SOURCE_JOYSTICK)
         {
-            case AMOTION_EVENT_ACTION_DOWN:
-                {
-                    pointerId = AMotionEvent_getPointerId(event, 0);
-                    x = AMotionEvent_getX(event, 0);
-                    y = AMotionEvent_getY(event, 0);
-
-                    // Gesture handling
-                    if ( __gestureEventsProcessed.test(Gesture::GESTURE_TAP) ||
-                         __gestureEventsProcessed.test(Gesture::GESTURE_SWIPE) ||
-                         __gestureEventsProcessed.test(Gesture::GESTURE_DRAG) ||
-                         __gestureEventsProcessed.test(Gesture::GESTURE_DROP) ||
-                         __gestureEventsProcessed.test(Gesture::GESTURE_PINCH) ||
-                         __gestureEventsProcessed.test(Gesture::GESTURE_LONG_TAP))
+            // DPAD handling (axis hats)
+            float xaxis = AMotionEvent_getAxisValue(event, AMOTION_EVENT_AXIS_HAT_X, 0);
+            float yaxis = AMotionEvent_getAxisValue(event, AMOTION_EVENT_AXIS_HAT_Y, 0);        
+            if (xaxis == -1.0f)
+            {
+                gameplay::Platform::gamepadButtonPressedEventInternal(deviceId, gameplay::Gamepad::BUTTON_LEFT);
+            }
+            else if(xaxis == 1.0f)
+            {
+                gameplay::Platform::gamepadButtonPressedEventInternal(deviceId, gameplay::Gamepad::BUTTON_RIGHT);
+            }
+            else if (xaxis == 0.0f)
+            {
+                gameplay::Platform::gamepadButtonReleasedEventInternal(deviceId, gameplay::Gamepad::BUTTON_LEFT);
+                gameplay::Platform::gamepadButtonReleasedEventInternal(deviceId, gameplay::Gamepad::BUTTON_RIGHT);
+            }
+
+            if(yaxis == -1.0f)
+            {
+                gameplay::Platform::gamepadButtonPressedEventInternal(deviceId, gameplay::Gamepad::BUTTON_UP);
+            }
+            else if(yaxis == 1.0f)
+            {
+                gameplay::Platform::gamepadButtonPressedEventInternal(deviceId, gameplay::Gamepad::BUTTON_DOWN);
+            }
+            else if (yaxis == 0.0f)
+            {
+                gameplay::Platform::gamepadButtonReleasedEventInternal(deviceId, gameplay::Gamepad::BUTTON_UP);
+                gameplay::Platform::gamepadButtonReleasedEventInternal(deviceId, gameplay::Gamepad::BUTTON_DOWN);
+            }
+
+            // Trigger handling
+            float leftTrigger = AMotionEvent_getAxisValue(event, AMOTION_EVENT_AXIS_BRAKE, 0);
+            gameplay::Platform::gamepadTriggerChangedEventInternal(deviceId, 0, leftTrigger);
+            float rightTrigger = AMotionEvent_getAxisValue(event, AMOTION_EVENT_AXIS_GAS, 0);
+            gameplay::Platform::gamepadTriggerChangedEventInternal(deviceId, 1, rightTrigger);
+
+            // jJoystick handling
+            float fuzz = 0.15f;
+            float x = AMotionEvent_getAxisValue(event, AMOTION_EVENT_AXIS_X, 0);
+            float y = AMotionEvent_getAxisValue(event, AMOTION_EVENT_AXIS_Y, 0);
+            gameplay::Platform::gamepadJoystickChangedEventInternal(deviceId, 0, clampFuzz(x, fuzz), clampFuzz(y, fuzz));
+            float z = AMotionEvent_getAxisValue(event, AMOTION_EVENT_AXIS_Z, 0);
+            float rz = AMotionEvent_getAxisValue(event, AMOTION_EVENT_AXIS_RZ, 0);
+            gameplay::Platform::gamepadJoystickChangedEventInternal(deviceId, 1, clampFuzz(z, fuzz), clampFuzz(rz, fuzz));
+        }
+        else
+        {
+            switch (action & AMOTION_EVENT_ACTION_MASK)
+            {
+                case AMOTION_EVENT_ACTION_DOWN:
                     {
-                        __pointer0.pressed = true;
-                        __pointer0.time = Game::getInstance()->getAbsoluteTime();
-                        __pointer0.pointerId = pointerId;
-                        __pointer0.x = x;
-                        __pointer0.y = y;
-						__gesturePointer0CurrentPosition = __gesturePointer0LastPosition = std::pair<int, int>(x, y);
-                    }
+                        pointerId = AMotionEvent_getPointerId(event, 0);
+                        x = AMotionEvent_getX(event, 0);
+                        y = AMotionEvent_getY(event, 0);
+
+                        // Gesture handling
+                        if ( __gestureEventsProcessed.test(Gesture::GESTURE_TAP) ||
+                             __gestureEventsProcessed.test(Gesture::GESTURE_SWIPE) ||
+                             __gestureEventsProcessed.test(Gesture::GESTURE_DRAG) ||
+                             __gestureEventsProcessed.test(Gesture::GESTURE_DROP) ||
+                             __gestureEventsProcessed.test(Gesture::GESTURE_PINCH) ||
+                             __gestureEventsProcessed.test(Gesture::GESTURE_LONG_TAP))
+                        {
+                            __pointer0.pressed = true;
+                            __pointer0.time = Game::getInstance()->getAbsoluteTime();
+                            __pointer0.pointerId = pointerId;
+                            __pointer0.x = x;
+                            __pointer0.y = y;
+						    __gesturePointer0CurrentPosition = __gesturePointer0LastPosition = std::pair<int, int>(x, y);
+                        }
 
-                    // Primary pointer down.
-                    gameplay::Platform::touchEventInternal(Touch::TOUCH_PRESS, x, y, pointerId);
-                    __primaryTouchId = pointerId;
-                }
-                break;
+                        // Primary pointer down.
+                        gameplay::Platform::touchEventInternal(Touch::TOUCH_PRESS, x, y, pointerId);
+                        __primaryTouchId = pointerId;
+                    }
+                    break;
 
-            case AMOTION_EVENT_ACTION_UP:
-                {
-                    pointerId = AMotionEvent_getPointerId(event, 0);
-                    x = AMotionEvent_getX(event, 0);
-                    y = AMotionEvent_getY(event, 0);
-                    
-                    // Gestures
-                    bool gestureDetected = false;
-					if (__pointer0.pressed &&  __pointer0.pointerId == pointerId)
+                case AMOTION_EVENT_ACTION_UP:
                     {
-                        int deltaX = x - __pointer0.x;
-                        int deltaY = y - __pointer0.y;
-						
-                        // Test for drop
-                      	if (__gesturePinching)
-						{
-							__gesturePinching = false;
-							gestureDetected = true;
-						}
-						else if (__gestureDraging)
+                        pointerId = AMotionEvent_getPointerId(event, 0);
+                        x = AMotionEvent_getX(event, 0);
+                        y = AMotionEvent_getY(event, 0);
+                        
+                        // Gestures
+                        bool gestureDetected = false;
+					    if (__pointer0.pressed &&  __pointer0.pointerId == pointerId)
                         {
-                            if (__gestureEventsProcessed.test(Gesture::GESTURE_DROP))
+                            int deltaX = x - __pointer0.x;
+                            int deltaY = y - __pointer0.y;
+						
+                            // Test for drop
+                          	if (__gesturePinching)
+						    {
+							    __gesturePinching = false;
+							    gestureDetected = true;
+						    }
+						    else if (__gestureDraging)
                             {
-                                gameplay::Platform::gestureDropEventInternal(x, y);
-                                gestureDetected = true;
+                                if (__gestureEventsProcessed.test(Gesture::GESTURE_DROP))
+                                {
+                                    gameplay::Platform::gestureDropEventInternal(x, y);
+                                    gestureDetected = true;
+                                }
+                                __gestureDraging = false;
                             }
-                            __gestureDraging = false;
-                        }
-                        // Test for swipe
-                        else if (__gestureEventsProcessed.test(Gesture::GESTURE_SWIPE) &&
-                            gameplay::Game::getInstance()->getAbsoluteTime() - __pointer0.time < GESTURE_SWIPE_DURATION_MAX && 
-                            (abs(deltaX) > GESTURE_SWIPE_DISTANCE_MIN || abs(deltaY) > GESTURE_SWIPE_DISTANCE_MIN) )
-                        {
-                            int direction = 0;
-                            if ( abs(deltaX) > abs(deltaY) )
+                            // Test for swipe
+                            else if (__gestureEventsProcessed.test(Gesture::GESTURE_SWIPE) &&
+                                gameplay::Game::getInstance()->getAbsoluteTime() - __pointer0.time < GESTURE_SWIPE_DURATION_MAX && 
+                                (abs(deltaX) > GESTURE_SWIPE_DISTANCE_MIN || abs(deltaY) > GESTURE_SWIPE_DISTANCE_MIN) )
                             {
-                                if (deltaX > 0)
-                                    direction = gameplay::Gesture::SWIPE_DIRECTION_RIGHT;
-                                else if (deltaX < 0)
-                                    direction = gameplay::Gesture::SWIPE_DIRECTION_LEFT;
+                                int direction = 0;
+                                if ( abs(deltaX) > abs(deltaY) )
+                                {
+                                    if (deltaX > 0)
+                                        direction = gameplay::Gesture::SWIPE_DIRECTION_RIGHT;
+                                    else if (deltaX < 0)
+                                        direction = gameplay::Gesture::SWIPE_DIRECTION_LEFT;
+                                }
+                                else
+                                {
+                                    if (deltaY > 0)
+                                        direction = gameplay::Gesture::SWIPE_DIRECTION_DOWN;
+                                    else if (deltaY < 0)
+                                        direction = gameplay::Gesture::SWIPE_DIRECTION_UP;
+                                }
+                                gameplay::Platform::gestureSwipeEventInternal(x, y, direction);
+                                gestureDetected = true;
                             }
-                            else
+                            // Test for tap
+                            else if(__gestureEventsProcessed.test(Gesture::GESTURE_TAP) &&
+                                   gameplay::Game::getInstance()->getAbsoluteTime() - __pointer0.time < GESTURE_TAP_DURATION_MAX)
                             {
-                                if (deltaY > 0)
-                                    direction = gameplay::Gesture::SWIPE_DIRECTION_DOWN;
-                                else if (deltaY < 0)
-                                    direction = gameplay::Gesture::SWIPE_DIRECTION_UP;
+                                gameplay::Platform::gestureTapEventInternal(x, y);
+                                gestureDetected = true;
                             }
-                            gameplay::Platform::gestureSwipeEventInternal(x, y, direction);
-                            gestureDetected = true;
+                            // Test for long tap
+                            else if(__gestureEventsProcessed.test(Gesture::GESTURE_LONG_TAP) &&
+                                   gameplay::Game::getInstance()->getAbsoluteTime() - __pointer0.time >= GESTURE_LONG_TAP_DURATION_MIN)
+                            {
+                                gameplay::Platform::gestureLongTapEventInternal(x, y, gameplay::Game::getInstance()->getAbsoluteTime() - __pointer0.time);
+                                gestureDetected = true;
+                            }    
                         }
-                        // Test for tap
-                        else if(__gestureEventsProcessed.test(Gesture::GESTURE_TAP) &&
-                               gameplay::Game::getInstance()->getAbsoluteTime() - __pointer0.time < GESTURE_TAP_DURATION_MAX)
+					    __pointer0.pressed = false;
+
+                        if (!gestureDetected && (__multiTouch || __primaryTouchId == pointerId) )
                         {
-                            gameplay::Platform::gestureTapEventInternal(x, y);
-                            gestureDetected = true;
+                            gameplay::Platform::touchEventInternal(Touch::TOUCH_RELEASE, x, y, pointerId);
                         }
-                        // Test for long tap
-                        else if(__gestureEventsProcessed.test(Gesture::GESTURE_LONG_TAP) &&
-                               gameplay::Game::getInstance()->getAbsoluteTime() - __pointer0.time >= GESTURE_LONG_TAP_DURATION_MIN)
-                        {
-                            gameplay::Platform::gestureLongTapEventInternal(x, y, gameplay::Game::getInstance()->getAbsoluteTime() - __pointer0.time);
-                            gestureDetected = true;
-                        }    
+                        __primaryTouchId = -1;
                     }
-					__pointer0.pressed = false;
+                    break;
 
-                    if (!gestureDetected && (__multiTouch || __primaryTouchId == pointerId) )
+                case AMOTION_EVENT_ACTION_POINTER_DOWN:
                     {
-                        gameplay::Platform::touchEventInternal(Touch::TOUCH_RELEASE, x, y, pointerId);
+                        pointerIndex = (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
+                        pointerId = AMotionEvent_getPointerId(event, pointerIndex);
+                        x = AMotionEvent_getX(event, pointerIndex);
+                        y = AMotionEvent_getY(event, pointerIndex);
+
+                        // Gesture handling
+                        if ( __gestureEventsProcessed.test(Gesture::GESTURE_TAP) ||
+                             __gestureEventsProcessed.test(Gesture::GESTURE_SWIPE) ||
+                             __gestureEventsProcessed.test(Gesture::GESTURE_DRAG) ||
+                             __gestureEventsProcessed.test(Gesture::GESTURE_DROP) ||
+                             __gestureEventsProcessed.test(Gesture::GESTURE_PINCH) ||
+                             __gestureEventsProcessed.test(Gesture::GESTURE_LONG_TAP))
+                        {
+                            __pointer1.pressed = true;
+                            __pointer1.time = Game::getInstance()->getAbsoluteTime();
+                            __pointer1.pointerId = pointerId;
+                            __pointer1.x = x;
+                            __pointer1.y = y;
+                        	__gesturePointer1CurrentPosition = __gesturePointer1LastPosition = std::pair<int, int>(x, y);
+					    }
+
+                        // Non-primary pointer down.
+                        if (__multiTouch)
+                        {
+                            gameplay::Platform::touchEventInternal(Touch::TOUCH_PRESS, 
+                                                                   AMotionEvent_getX(event, pointerIndex), 
+                                                                   AMotionEvent_getY(event, pointerIndex), pointerId);
+                        }
                     }
-                    __primaryTouchId = -1;
-                }
-                break;
+                    break;
 
-            case AMOTION_EVENT_ACTION_POINTER_DOWN:
-                {
-                    pointerIndex = (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
-                    pointerId = AMotionEvent_getPointerId(event, pointerIndex);
-                    x = AMotionEvent_getX(event, pointerIndex);
-                    y = AMotionEvent_getY(event, pointerIndex);
-
-                    // Gesture handling
-                    if ( __gestureEventsProcessed.test(Gesture::GESTURE_TAP) ||
-                         __gestureEventsProcessed.test(Gesture::GESTURE_SWIPE) ||
-                         __gestureEventsProcessed.test(Gesture::GESTURE_DRAG) ||
-                         __gestureEventsProcessed.test(Gesture::GESTURE_DROP) ||
-                         __gestureEventsProcessed.test(Gesture::GESTURE_PINCH) ||
-                         __gestureEventsProcessed.test(Gesture::GESTURE_LONG_TAP))
+                case AMOTION_EVENT_ACTION_POINTER_UP:
                     {
-                        __pointer1.pressed = true;
-                        __pointer1.time = Game::getInstance()->getAbsoluteTime();
-                        __pointer1.pointerId = pointerId;
-                        __pointer1.x = x;
-                        __pointer1.y = y;
-                    	__gesturePointer1CurrentPosition = __gesturePointer1LastPosition = std::pair<int, int>(x, y);
-					}
-
-                    // Non-primary pointer down.
-                    if (__multiTouch)
-                    {
-                        gameplay::Platform::touchEventInternal(Touch::TOUCH_PRESS, AMotionEvent_getX(event, pointerIndex), AMotionEvent_getY(event, pointerIndex), pointerId);
-                    }
-                }
-                break;
+                        pointerIndex = (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
+                        pointerId = AMotionEvent_getPointerId(event, pointerIndex);
+                        x = AMotionEvent_getX(event, pointerIndex);
+                        y = AMotionEvent_getY(event, pointerIndex);
 
-            case AMOTION_EVENT_ACTION_POINTER_UP:
-                {
-                    pointerIndex = (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
-                    pointerId = AMotionEvent_getPointerId(event, pointerIndex);
-                    x = AMotionEvent_getX(event, pointerIndex);
-                    y = AMotionEvent_getY(event, pointerIndex);
-
-                    bool gestureDetected = false;
-                    if (__pointer1.pressed &&  __pointer1.pointerId == pointerId)
-                    {
-                        int deltaX = x - __pointer1.x;
-                        int deltaY = y - __pointer1.y;
-						
-						if (__gesturePinching)
-						{
-							__gesturePinching = false;
-							gestureDetected = true;
-						}
-						// Test for swipe
-						else if (__gestureEventsProcessed.test(Gesture::GESTURE_SWIPE) &&
-                            gameplay::Game::getInstance()->getAbsoluteTime() - __pointer1.time < GESTURE_SWIPE_DURATION_MAX && 
-                            (abs(deltaX) > GESTURE_SWIPE_DISTANCE_MIN || abs(deltaY) > GESTURE_SWIPE_DISTANCE_MIN) )
+                        bool gestureDetected = false;
+                        if (__pointer1.pressed &&  __pointer1.pointerId == pointerId)
                         {
-                            int direction = 0;
-                            if (deltaX > 0)
-                                direction |= gameplay::Gesture::SWIPE_DIRECTION_RIGHT;
-                            else if (deltaX < 0)
-                                direction |= gameplay::Gesture::SWIPE_DIRECTION_LEFT;
-                            
-                            if (deltaY > 0)
-                                direction |= gameplay::Gesture::SWIPE_DIRECTION_DOWN;
-                            else if (deltaY < 0)
-                                direction |= gameplay::Gesture::SWIPE_DIRECTION_UP;
+                            int deltaX = x - __pointer1.x;
+                            int deltaY = y - __pointer1.y;
+						
+						    if (__gesturePinching)
+						    {
+							    __gesturePinching = false;
+							    gestureDetected = true;
+						    }
+						    // Test for swipe
+						    else if (__gestureEventsProcessed.test(Gesture::GESTURE_SWIPE) &&
+                                gameplay::Game::getInstance()->getAbsoluteTime() - __pointer1.time < GESTURE_SWIPE_DURATION_MAX && 
+                                (abs(deltaX) > GESTURE_SWIPE_DISTANCE_MIN || abs(deltaY) > GESTURE_SWIPE_DISTANCE_MIN) )
+                            {
+                                int direction = 0;
+                                if (deltaX > 0)
+                                    direction |= gameplay::Gesture::SWIPE_DIRECTION_RIGHT;
+                                else if (deltaX < 0)
+                                    direction |= gameplay::Gesture::SWIPE_DIRECTION_LEFT;
+                                
+                                if (deltaY > 0)
+                                    direction |= gameplay::Gesture::SWIPE_DIRECTION_DOWN;
+                                else if (deltaY < 0)
+                                    direction |= gameplay::Gesture::SWIPE_DIRECTION_UP;
 
-                            gameplay::Platform::gestureSwipeEventInternal(x, y, direction);
-                            gestureDetected = true;
+                                gameplay::Platform::gestureSwipeEventInternal(x, y, direction);
+                                gestureDetected = true;
+                            }
+                            else if(__gestureEventsProcessed.test(Gesture::GESTURE_TAP) &&
+                                   gameplay::Game::getInstance()->getAbsoluteTime() - __pointer1.time < GESTURE_TAP_DURATION_MAX)
+                            {
+                                gameplay::Platform::gestureTapEventInternal(x, y);
+                                gestureDetected = true;
+                            }
+                            else if(__gestureEventsProcessed.test(Gesture::GESTURE_LONG_TAP) &&
+                                   gameplay::Game::getInstance()->getAbsoluteTime() - __pointer1.time >= GESTURE_LONG_TAP_DURATION_MIN)
+                            {
+                                gameplay::Platform::gestureLongTapEventInternal(x, y, gameplay::Game::getInstance()->getAbsoluteTime() - __pointer1.time);
+                                gestureDetected = true;
+                            }    
                         }
-                        else if(__gestureEventsProcessed.test(Gesture::GESTURE_TAP) &&
-                               gameplay::Game::getInstance()->getAbsoluteTime() - __pointer1.time < GESTURE_TAP_DURATION_MAX)
+					    __pointer1.pressed = false;
+
+                        if (!gestureDetected && (__multiTouch || __primaryTouchId == pointerId) )
                         {
-                            gameplay::Platform::gestureTapEventInternal(x, y);
-                            gestureDetected = true;
+                            gameplay::Platform::touchEventInternal(Touch::TOUCH_RELEASE, 
+                                                                   AMotionEvent_getX(event, pointerIndex), 
+                                                                   AMotionEvent_getY(event, pointerIndex), pointerId);
                         }
-                        else if(__gestureEventsProcessed.test(Gesture::GESTURE_LONG_TAP) &&
-                               gameplay::Game::getInstance()->getAbsoluteTime() - __pointer1.time >= GESTURE_LONG_TAP_DURATION_MIN)
-                        {
-                            gameplay::Platform::gestureLongTapEventInternal(x, y, gameplay::Game::getInstance()->getAbsoluteTime() - __pointer1.time);
-                            gestureDetected = true;
-                        }    
+                        if (__primaryTouchId == pointerId)
+                            __primaryTouchId = -1;
                     }
-					__pointer1.pressed = false;
-
-                    if (!gestureDetected && (__multiTouch || __primaryTouchId == pointerId) )
-                    {
-                        gameplay::Platform::touchEventInternal(Touch::TOUCH_RELEASE, AMotionEvent_getX(event, pointerIndex), AMotionEvent_getY(event, pointerIndex), pointerId);
-                    }
-                    if (__primaryTouchId == pointerId)
-                        __primaryTouchId = -1;
-                }
-                break;
+                    break;
 
-            case AMOTION_EVENT_ACTION_MOVE:
-                {
-                    // ACTION_MOVE events are batched, unlike the other events.
-                    pointerCount = AMotionEvent_getPointerCount(event);
-                    for (size_t i = 0; i < pointerCount; ++i)
+                case AMOTION_EVENT_ACTION_MOVE:
                     {
-                        pointerId = AMotionEvent_getPointerId(event, i);
-                        x = AMotionEvent_getX(event, i);
-                        y = AMotionEvent_getY(event, i);
-                        
-                        bool gestureDetected = false;
-						if (__pointer0.pressed)
-						{
-							//The two pointers are pressed and the event was done by one of it
-							if (__pointer1.pressed && (pointerId == __pointer0.pointerId || pointerId == __pointer1.pointerId))
-							{
-								if (__pointer0.pointerId == __pointer1.pointerId)
-								{
-									__gesturePinching = false;
-									break;
-								}
-								//Test for pinch
-								if (__gestureEventsProcessed.test(Gesture::GESTURE_PINCH))
-								{
-									int pointer0Distance, pointer1Distance;
-
-									if (__pointer0.pointerId == pointerId)
-									{
-										__gesturePointer0LastPosition = __gesturePointer0CurrentPosition;
-										__gesturePointer0CurrentPosition = std::pair<int, int>(x, y);
-										__gesturePointer0Delta = sqrt(pow(static_cast<float>(x - __pointer0.x), 2) +
-																	pow(static_cast<float>(y - __pointer0.y), 2));
-									}
-									else
-									{
-										__gesturePointer1LastPosition = __gesturePointer1CurrentPosition;
-										__gesturePointer1CurrentPosition = std::pair<int, int>(x, y);
-										__gesturePointer1Delta = sqrt(pow(static_cast<float>(x - __pointer1.x), 2) +
-																	pow(static_cast<float>(y - __pointer1.y), 2));
-									}
-									if (!__gesturePinching &&
-										__gesturePointer0Delta >= GESTURE_PINCH_DISTANCE_MIN &&
-										__gesturePointer1Delta >= GESTURE_PINCH_DISTANCE_MIN)
-									{
-										__gesturePinching = true;
-										__gesturePinchCentroid = std::pair<int, int>((__pointer0.x + __pointer1.x) / 2,
-																					(__pointer0.y + __pointer1.y) / 2);
-									}
-									if (__gesturePinching)
-									{
-										int currentDistancePointer0, currentDistancePointer1;
-										int lastDistancePointer0, lastDistancePointer1;
-										float scale;
-
-										currentDistancePointer0 = sqrt(pow(static_cast<float>(__gesturePinchCentroid.first - __gesturePointer0CurrentPosition.first), 2) + pow(static_cast<float>(__gesturePinchCentroid.second - __gesturePointer0CurrentPosition.second), 2));
-										lastDistancePointer0 = sqrt(pow(static_cast<float>(__gesturePinchCentroid.first - __gesturePointer0LastPosition.first), 2) + pow(static_cast<float>(__gesturePinchCentroid.second - __gesturePointer0LastPosition.second), 2));
-										currentDistancePointer1 = sqrt(pow(static_cast<float>(__gesturePinchCentroid.first - __gesturePointer1CurrentPosition.first), 2) + pow(static_cast<float>(__gesturePinchCentroid.second - __gesturePointer1CurrentPosition.second), 2));
-										lastDistancePointer1 = sqrt(pow(static_cast<float>(__gesturePinchCentroid.first - __gesturePointer1LastPosition.first), 2) + pow(static_cast<float>(__gesturePinchCentroid.second - __gesturePointer1LastPosition.second), 2));
-										if (pointerId == __pointer0.pointerId)
-											scale = ((float) currentDistancePointer0) / ((float) lastDistancePointer0);
-										else
-											scale = ((float) currentDistancePointer1) / ((float) lastDistancePointer1);
-										if (((currentDistancePointer0 >= lastDistancePointer0) && (currentDistancePointer1 >= lastDistancePointer1)) ||
-											((currentDistancePointer0 <= lastDistancePointer0) && (currentDistancePointer1 <= lastDistancePointer1)))
-										{
-											gameplay::Platform::gesturePinchEventInternal(__gesturePinchCentroid.first, __gesturePinchCentroid.second, scale);	
-											gestureDetected = true;
-										}
-										else
-											__gesturePinching = false;
-									}
-								}
-							}
-							//Only the primary pointer is done and the event was done by it
-							else if (!gestureDetected && pointerId == __pointer0.pointerId)
-							{
-								//Test for drag
-								if (__gestureEventsProcessed.test(Gesture::GESTURE_DRAG))
-								{
-                            		int delta = sqrt(pow(static_cast<float>(x - __pointer0.x), 2) +
-													pow(static_cast<float>(y - __pointer0.y), 2));
-                            
-                            		if ((__gestureDraging || __gestureEventsProcessed.test(Gesture::GESTURE_DRAG)) &&
-                                 		(gameplay::Game::getInstance()->getAbsoluteTime() - __pointer0.time >= GESTURE_DRAG_START_DURATION_MIN) &&
-                                		(delta >= GESTURE_DRAG_DISTANCE_MIN))
-                            		{
-                                		gameplay::Platform::gestureDragEventInternal(x, y);
-                                		__gestureDraging = true;
-                                		gestureDetected = true;
-                            		}
-								}
-							}
-						}
-
-                        if (!gestureDetected && (__multiTouch || __primaryTouchId == pointerId))
+                        // ACTION_MOVE events are batched, unlike the other events.
+                        pointerCount = AMotionEvent_getPointerCount(event);
+                        for (size_t i = 0; i < pointerCount; ++i)
                         {
-                            gameplay::Platform::touchEventInternal(Touch::TOUCH_MOVE, AMotionEvent_getX(event, i), AMotionEvent_getY(event, i), pointerId);
-                        }
-                    }
-                }
-                break;
+                            pointerId = AMotionEvent_getPointerId(event, i);
+                            x = AMotionEvent_getX(event, i);
+                            y = AMotionEvent_getY(event, i);
+                            
+                            bool gestureDetected = false;
+						    if (__pointer0.pressed)
+						    {
+							    //The two pointers are pressed and the event was done by one of it
+							    if (__pointer1.pressed && (pointerId == __pointer0.pointerId || pointerId == __pointer1.pointerId))
+							    {
+								    if (__pointer0.pointerId == __pointer1.pointerId)
+								    {
+									    __gesturePinching = false;
+									    break;
+								    }
+								    //Test for pinch
+								    if (__gestureEventsProcessed.test(Gesture::GESTURE_PINCH))
+								    {
+									    int pointer0Distance, pointer1Distance;
+
+									    if (__pointer0.pointerId == pointerId)
+									    {
+										    __gesturePointer0LastPosition = __gesturePointer0CurrentPosition;
+										    __gesturePointer0CurrentPosition = std::pair<int, int>(x, y);
+										    __gesturePointer0Delta = sqrt(pow(static_cast<float>(x - __pointer0.x), 2) +
+																	    pow(static_cast<float>(y - __pointer0.y), 2));
+									    }
+									    else
+									    {
+										    __gesturePointer1LastPosition = __gesturePointer1CurrentPosition;
+										    __gesturePointer1CurrentPosition = std::pair<int, int>(x, y);
+										    __gesturePointer1Delta = sqrt(pow(static_cast<float>(x - __pointer1.x), 2) +
+																	    pow(static_cast<float>(y - __pointer1.y), 2));
+									    }
+									    if (!__gesturePinching &&
+										    __gesturePointer0Delta >= GESTURE_PINCH_DISTANCE_MIN &&
+										    __gesturePointer1Delta >= GESTURE_PINCH_DISTANCE_MIN)
+									    {
+										    __gesturePinching = true;
+										    __gesturePinchCentroid = std::pair<int, int>((__pointer0.x + __pointer1.x) / 2,
+																					    (__pointer0.y + __pointer1.y) / 2);
+									    }
+									    if (__gesturePinching)
+									    {
+										    int currentDistancePointer0, currentDistancePointer1;
+										    int lastDistancePointer0, lastDistancePointer1;
+										    float scale;
+
+										    currentDistancePointer0 = sqrt(pow(static_cast<float>(__gesturePinchCentroid.first - __gesturePointer0CurrentPosition.first), 2) + 
+                                                                           pow(static_cast<float>(__gesturePinchCentroid.second - __gesturePointer0CurrentPosition.second), 2));
+										    lastDistancePointer0 = sqrt(pow(static_cast<float>(__gesturePinchCentroid.first - __gesturePointer0LastPosition.first), 2) + 
+                                                                        pow(static_cast<float>(__gesturePinchCentroid.second - __gesturePointer0LastPosition.second), 2));
+										    currentDistancePointer1 = sqrt(pow(static_cast<float>(__gesturePinchCentroid.first - __gesturePointer1CurrentPosition.first), 2) + 
+                                                                           pow(static_cast<float>(__gesturePinchCentroid.second - __gesturePointer1CurrentPosition.second), 2));
+										    lastDistancePointer1 = sqrt(pow(static_cast<float>(__gesturePinchCentroid.first - __gesturePointer1LastPosition.first), 2) + 
+                                                                        pow(static_cast<float>(__gesturePinchCentroid.second - __gesturePointer1LastPosition.second), 2));
+										    if (pointerId == __pointer0.pointerId)
+											    scale = ((float) currentDistancePointer0) / ((float) lastDistancePointer0);
+										    else
+											    scale = ((float) currentDistancePointer1) / ((float) lastDistancePointer1);
+										    if (((currentDistancePointer0 >= lastDistancePointer0) && (currentDistancePointer1 >= lastDistancePointer1)) ||
+											    ((currentDistancePointer0 <= lastDistancePointer0) && (currentDistancePointer1 <= lastDistancePointer1)))
+										    {
+											    gameplay::Platform::gesturePinchEventInternal(__gesturePinchCentroid.first, __gesturePinchCentroid.second, scale);	
+											    gestureDetected = true;
+										    }
+										    else
+											    __gesturePinching = false;
+									    }
+								    }
+							    }
+							    // Only the primary pointer is done and the event was done by it
+							    else if (!gestureDetected && pointerId == __pointer0.pointerId)
+							    {
+								    //Test for drag
+								    if (__gestureEventsProcessed.test(Gesture::GESTURE_DRAG))
+								    {
+                                		int delta = sqrt(pow(static_cast<float>(x - __pointer0.x), 2) +
+													    pow(static_cast<float>(y - __pointer0.y), 2));
+                                
+                                		if ((__gestureDraging || __gestureEventsProcessed.test(Gesture::GESTURE_DRAG)) &&
+                                     		(gameplay::Game::getInstance()->getAbsoluteTime() - __pointer0.time >= GESTURE_DRAG_START_DURATION_MIN) &&
+                                    		(delta >= GESTURE_DRAG_DISTANCE_MIN))
+                                		{
+                                    		gameplay::Platform::gestureDragEventInternal(x, y);
+                                    		__gestureDraging = true;
+                                    		gestureDetected = true;
+                                		}
+								    }
+							    }
+						    }
+
+                            if (!gestureDetected && (__multiTouch || __primaryTouchId == pointerId))
+                            {
+                                gameplay::Platform::touchEventInternal(Touch::TOUCH_MOVE, AMotionEvent_getX(event, i), AMotionEvent_getY(event, i), pointerId);
+                            }
+                       }
+                   }
+                   break;
+            }
         }
         return 1;
     } 
@@ -1028,17 +1148,27 @@ static int32_t engine_handle_input(struct android_app* app, AInputEvent* event)
         switch(action)
         {
             case AKEY_EVENT_ACTION_DOWN:
-                gameplay::Platform::keyEventInternal(Keyboard::KEY_PRESS, getKey(keycode, metastate));
-                if (int character = getUnicode(keycode, metastate))
-                    gameplay::Platform::keyEventInternal(Keyboard::KEY_CHAR, character);
-                if (keycode == AKEYCODE_BACK)
-                	return 1;
+                if ((source & AINPUT_SOURCE_GAMEPAD) || (source & AINPUT_SOURCE_JOYSTICK))
+                {
+                    gameplay::Platform::gamepadButtonPressedEventInternal(deviceId, gameplay::getGamepadButtonMapping(keycode));
+                }
+                else
+                {
+                    gameplay::Platform::keyEventInternal(Keyboard::KEY_PRESS, getKey(keycode, metastate));
+                    if (int character = getUnicode(keycode, metastate))
+                        gameplay::Platform::keyEventInternal(Keyboard::KEY_CHAR, character);
+                }
                 break;
                     
             case AKEY_EVENT_ACTION_UP:
-                gameplay::Platform::keyEventInternal(Keyboard::KEY_RELEASE, getKey(keycode, metastate));
-                if (keycode == AKEYCODE_BACK)
-                	return 1;
+                if ((source & AINPUT_SOURCE_GAMEPAD) || (source & AINPUT_SOURCE_JOYSTICK) )
+                {
+                    gameplay::Platform::gamepadButtonReleasedEventInternal(deviceId, gameplay::getGamepadButtonMapping(keycode));
+                }
+                else
+                {
+                    gameplay::Platform::keyEventInternal(Keyboard::KEY_RELEASE, getKey(keycode, metastate));
+                }
                 break;
         }
         return 1;
@@ -1344,8 +1474,6 @@ void Platform::setMultiSampling(bool enabled)
     {
         return;
     }
-
-    // TODO
     __multiSampling = enabled;
 }
 
@@ -1644,14 +1772,12 @@ extern "C"
 
 JNIEXPORT void JNICALL Java_org_gameplay3d_GameNativeActivity_gamepadEventConnectedImpl(JNIEnv* env, jclass clazz, jint deviceId, jint buttonCount, jint joystickCount, jint triggerCount, jint vendorId, jint productId, jstring vendorIdStr, jstring productIdStr)
 {
-	// TODO
-	//gameplay::Platform::gamepadEventConnectedInternal(deviceId, buttonCount, joystickCount, triggerCount, vendorId, productId, "", "");
+	gameplay::Platform::gamepadEventConnectedInternal(deviceId, buttonCount, joystickCount, triggerCount, vendorId, productId, "", "");
 }
 
 JNIEXPORT void JNICALL Java_org_gameplay3d_GameNativeActivity_gamepadEventDisconnectedImpl(JNIEnv* env, jclass clazz, jint deviceId)
 {
-	// TODO
-	//gameplay::Platform::gamepadEventDisconnectedInternal(deviceId);
+	gameplay::Platform::gamepadEventDisconnectedInternal(deviceId);
 }
 
 }

+ 0 - 9
gameplay/src/ScriptController.cpp

@@ -885,13 +885,6 @@ void ScriptController::gestureDropEvent(int x, int y)
 {
 }
 
-void ScriptController::gamepadEvent(Gamepad::GamepadEvent evt, Gamepad* gamepad, unsigned int analogIndex)
-{
-    std::vector<std::string>& list = _callbacks[GAMEPAD_EVENT];
-    for (size_t i = 0; i < list.size(); ++i)
-        executeFunction<void>(list[i].c_str(), "[Gamepad::GamepadEvent]<Gamepad>", evt, gamepad);
-}
-
 void ScriptController::executeFunctionHelper(int resultCount, const char* func, const char* args, va_list* list)
 {
 	if (!_lua)
@@ -1073,8 +1066,6 @@ ScriptController::ScriptCallback ScriptController::toCallback(const char* name)
         return ScriptController::GESTURE_PINCH_EVENT;
     else if (strcmp(name, "gestureTapEvent") == 0)
         return ScriptController::GESTURE_TAP_EVENT;
-    else if (strcmp(name, "gamepadEvent") == 0)
-        return ScriptController::GAMEPAD_EVENT;
     else
         return ScriptController::INVALID_CALLBACK;
 }

+ 1 - 9
gameplay/src/ScriptController.h

@@ -372,7 +372,7 @@ public:
      *
      * The 'callback' parameter must be one of the supported global callback
      * event functions. The following strings are accepted: initialize, finalize,
-     * update, render, resizeEvent, keyEvent, touchEvent, mouseEvent, gamepadEvent.
+     * update, render, resizeEvent, keyEvent, touchEvent, mouseEvent
      * Signatures for the registered script function must match that of the
      * corresponding signatures of these events on the Game class.
      *
@@ -925,14 +925,6 @@ private:
 	 */
 	void gestureDropEvent(int x, int y);
 
-    /**
-     * Script gamepad callback on gamepad events.
-     *
-     * @param evt The gamepad event that occurred.
-     * @param gamepad the gamepad the event occurred on
-     */
-    void gamepadEvent(Gamepad::GamepadEvent evt, Gamepad* gamepad, unsigned int analogIndex = 0);
-
     /**
      * Calls the specified Lua function using the given parameters.
      * 

+ 9 - 17
gameplay/src/Slider.cpp

@@ -252,26 +252,18 @@ bool Slider::mouseEvent(Mouse::MouseEvent evt, int x, int y, int wheelDelta)
     return false;
 }
 
-bool Slider::gamepadEvent(Gamepad::GamepadEvent evt, Gamepad* gamepad, unsigned int analogIndex)
+bool Slider::gamepadJoystickEvent(Gamepad* gamepad, unsigned int index)
 {
-    switch (evt)
+    // The right analog stick can be used to change a slider's value.
+    if (index == 1)
     {
-        case Gamepad::JOYSTICK_EVENT:
-        {
-            // The right analog stick can be used to change a slider's value.
-            if (analogIndex == 1)
-            {
-                Vector2 joy;
-                gamepad->getJoystickValues(analogIndex, &joy);
-                _gamepadValue = _value;
-                _delta = joy.x;
-                return true;
-            }
-            break;
-        }
+        Vector2 joy;
+        gamepad->getJoystickValues(index, &joy);
+        _gamepadValue = _value;
+        _delta = joy.x;
+        return true;
     }
-
-    return Label::gamepadEvent(evt, gamepad, analogIndex);
+    return Label::gamepadJoystickEvent(gamepad, index);
 }
 
 bool Slider::keyEvent(Keyboard::KeyEvent evt, int key)

+ 8 - 31
gameplay/src/Slider.h

@@ -180,47 +180,24 @@ protected:
     void initialize(const char* typeName, Theme::Style* style, Properties* properties);
 
     /**
-     * Touch callback on touch events.  Controls return true if they consume the touch event.
-     *
-     * @param evt The touch event that occurred.
-     * @param x The x position of the touch in pixels. Left edge is zero.
-     * @param y The y position of the touch in pixels. Top edge is zero.
-     * @param contactIndex The order of occurrence for multiple touch contacts starting at zero.
-     *
-     * @return Whether the touch event was consumed by the control.
-     *
-     * @see Touch::TouchEvent
+     * @see Control::KeyEvent
      */
-    bool touchEvent(Touch::TouchEvent evt, int x, int y, unsigned int contactIndex);
+    bool keyEvent(Keyboard::KeyEvent evt, int key);
 
     /**
-     * Mouse callback on mouse events.
-     *
-     * @param evt The mouse event that occurred.
-     * @param x The x position of the mouse in pixels. Left edge is zero.
-     * @param y The y position of the mouse in pixels. Top edge is zero.
-     * @param wheelDelta The number of mouse wheel ticks. Positive is up (forward), negative is down (backward).
-     *
-     * @return True if the mouse event is consumed or false if it is not consumed.
-     *
-     * @see Mouse::MouseEvent
+     * @see Control::TouchEvent
      */
-    bool mouseEvent(Mouse::MouseEvent evt, int x, int y, int wheelDelta);
+    bool touchEvent(Touch::TouchEvent evt, int x, int y, unsigned int contactIndex);
 
     /**
-     * Gamepad callback on gamepad events.
-     *
-     * @see Control::gamepadEvent
+     * @see Control::MouseEvent
      */
-    bool gamepadEvent(Gamepad::GamepadEvent evt, Gamepad* gamepad, unsigned int analogIndex);
+    bool mouseEvent(Mouse::MouseEvent evt, int x, int y, int wheelDelta);
 
     /**
-     * Keyboard callback on key events.
-     *
-     * @see Keyboard::KeyEvent
-     * @see Keyboard::Key
+     * @see Control::gamepadJoystickEvent
      */
-    bool keyEvent(Keyboard::KeyEvent evt, int key);
+    bool gamepadJoystickEvent(Gamepad* gamepad, unsigned int index);
 
     /**
      * @see Control::drawImages

+ 0 - 15
gameplay/src/lua/lua_GamepadGamepadEvent.cpp

@@ -8,9 +8,6 @@ static const char* enumStringEmpty = "";
 
 static const char* luaEnumString_GamepadGamepadEvent_CONNECTED_EVENT = "CONNECTED_EVENT";
 static const char* luaEnumString_GamepadGamepadEvent_DISCONNECTED_EVENT = "DISCONNECTED_EVENT";
-static const char* luaEnumString_GamepadGamepadEvent_BUTTON_EVENT = "BUTTON_EVENT";
-static const char* luaEnumString_GamepadGamepadEvent_JOYSTICK_EVENT = "JOYSTICK_EVENT";
-static const char* luaEnumString_GamepadGamepadEvent_TRIGGER_EVENT = "TRIGGER_EVENT";
 
 Gamepad::GamepadEvent lua_enumFromString_GamepadGamepadEvent(const char* s)
 {
@@ -18,12 +15,6 @@ Gamepad::GamepadEvent lua_enumFromString_GamepadGamepadEvent(const char* s)
         return Gamepad::CONNECTED_EVENT;
     if (strcmp(s, luaEnumString_GamepadGamepadEvent_DISCONNECTED_EVENT) == 0)
         return Gamepad::DISCONNECTED_EVENT;
-    if (strcmp(s, luaEnumString_GamepadGamepadEvent_BUTTON_EVENT) == 0)
-        return Gamepad::BUTTON_EVENT;
-    if (strcmp(s, luaEnumString_GamepadGamepadEvent_JOYSTICK_EVENT) == 0)
-        return Gamepad::JOYSTICK_EVENT;
-    if (strcmp(s, luaEnumString_GamepadGamepadEvent_TRIGGER_EVENT) == 0)
-        return Gamepad::TRIGGER_EVENT;
     return Gamepad::CONNECTED_EVENT;
 }
 
@@ -33,12 +24,6 @@ const char* lua_stringFromEnum_GamepadGamepadEvent(Gamepad::GamepadEvent e)
         return luaEnumString_GamepadGamepadEvent_CONNECTED_EVENT;
     if (e == Gamepad::DISCONNECTED_EVENT)
         return luaEnumString_GamepadGamepadEvent_DISCONNECTED_EVENT;
-    if (e == Gamepad::BUTTON_EVENT)
-        return luaEnumString_GamepadGamepadEvent_BUTTON_EVENT;
-    if (e == Gamepad::JOYSTICK_EVENT)
-        return luaEnumString_GamepadGamepadEvent_JOYSTICK_EVENT;
-    if (e == Gamepad::TRIGGER_EVENT)
-        return luaEnumString_GamepadGamepadEvent_TRIGGER_EVENT;
     return enumStringEmpty;
 }
 

+ 56 - 51
gameplay/src/org/gameplay3d/GameNativeActivity.java

@@ -10,6 +10,7 @@ import android.util.Log;
 import android.util.SparseArray;
 import android.view.InputDevice;
 import android.view.KeyEvent;
+import android.view.MotionEvent;
 import android.view.View;
 
 /**
@@ -22,97 +23,101 @@ import android.view.View;
  * android user-interface, life-cycle events for saving game state and custom plug-ins/extensions.
  */
 public class GameNativeActivity extends NativeActivity
-	implements InputManager.InputDeviceListener {
-	
-	static {
-		System.loadLibrary("gameplay");
-	}
-	
-	private static final String TAG = "GameNativeActivity";
-	
-	@Override
-	protected void onCreate(Bundle savedInstanceState) {
-		super.onCreate(savedInstanceState);
-		
-		_gamepadDevices = new SparseArray<InputDevice>();
-		_inputManager = (InputManager)getSystemService(Context.INPUT_SERVICE);
+    implements InputManager.InputDeviceListener {
+    
+    static {
+        System.loadLibrary("gameplay");
+    }
+    
+    private static final String TAG = "GameNativeActivity";
+    
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        Log.i(TAG, "onCreate");
+        super.onCreate(savedInstanceState);
+        _gamepadDevices = new SparseArray<InputDevice>();
+        _inputManager = (InputManager)getSystemService(Context.INPUT_SERVICE);
 
-		View decorView = getWindow().getDecorView();
-		int uiOptions = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN;
-		if (Build.VERSION.SDK_INT >= 18) 
-			uiOptions ^= 0x00000800; //View.SYSTEM_UI_FLAG_IMMERSIVE;
-		decorView.setSystemUiVisibility(uiOptions);
-	}
-	
-	@Override
-	public void onSaveInstanceState(Bundle outState) {
-	    super.onSaveInstanceState(outState);
-	}
-	
-	@Override
+        View decorView = getWindow().getDecorView();
+        int uiOptions = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN;
+        if (Build.VERSION.SDK_INT >= 18) 
+            uiOptions ^= 0x00000800; // View.SYSTEM_UI_FLAG_IMMERSIVE;
+        decorView.setSystemUiVisibility(uiOptions);
+    }
+    
+    @Override
+    public void onSaveInstanceState(Bundle outState) {
+        Log.i(TAG, "onSaveInstanceState");
+        super.onSaveInstanceState(outState);
+    }
+    
+    @Override
     public void onConfigurationChanged(Configuration newConfig) {
-    	super.onConfigurationChanged(newConfig);
+        super.onConfigurationChanged(newConfig);
     } 
-	
+    
     @Override
     protected void onResume() {
-    	super.onResume();
+        Log.i(TAG, "onResume");
+        super.onResume();
         _inputManager.registerInputDeviceListener(this, null);
-        int[] ids = _inputManager.getInputDeviceIds();
+        int[] ids = InputDevice.getDeviceIds();
         for (int i = 0; i < ids.length; i++) {
-        	getGamepadDevice(ids[i]);
+            Log.i(TAG, "getGamepadDevice: " + ids[i]);
+            getGamepadDevice(ids[i]);
         }
     }
     
     @Override
     protected void onPause() {
+        Log.i(TAG, "onPause");
         _inputManager.unregisterInputDeviceListener(this);
-    	super.onPause();
+        super.onPause();
     }
     
     @Override
     public void onInputDeviceAdded(int deviceId) {
-    	Log.v(TAG, "Input Device added: " + deviceId);
+        Log.i(TAG, "onInputDeviceAdded: " + deviceId);
         getGamepadDevice(deviceId);
     }
 
     @Override
     public void onInputDeviceRemoved(int deviceId) {
-    	Log.v(TAG, "Input Device removed: " + deviceId);
+        Log.i(TAG, "onInputDeviceRemoved: " + deviceId);
         InputDevice device = _gamepadDevices.get(deviceId);
         if (device != null) {
-        	_gamepadDevices.remove(deviceId);
-        	//gamepadEventDisconnectedImpl(deviceId);
+            _gamepadDevices.remove(deviceId);
+            gamepadEventDisconnectedImpl(deviceId);
         }
     }
     
     @Override
     public void onInputDeviceChanged(int deviceId) {
-    	Log.v(TAG, "Input Device changed: " + deviceId);
+        Log.i(TAG, "onInputDeviceChanged: " + deviceId);
     }
     
     private InputDevice getGamepadDevice(int deviceId) {
-    	InputDevice device = _gamepadDevices.get(deviceId);
+        InputDevice device = _gamepadDevices.get(deviceId);
         if (device == null) {
-            device = _inputManager.getInputDevice(deviceId);
+            device = InputDevice.getDevice(deviceId);
             if (device == null)
-            	return null;
-            if ((device.getSources() & InputDevice.SOURCE_GAMEPAD) != 0) {
-            	_gamepadDevices.put(deviceId, device);
-            	gamepadEventConnectedImpl(deviceId, 26, 2, 2, 0, 0, "", "");
-            }
-            if ((device.getSources() & InputDevice.SOURCE_JOYSTICK) != 0) {
-            	_gamepadDevices.put(deviceId, device);
-            	gamepadEventConnectedImpl(deviceId, 10, 0, 0, 0, 0, "", "");
+                return null;
+            int sources = device.getSources();
+            if (((sources & InputDevice.SOURCE_GAMEPAD) == InputDevice.SOURCE_GAMEPAD) || 
+                ((sources & InputDevice.SOURCE_JOYSTICK) == InputDevice.SOURCE_JOYSTICK)) {
+                _gamepadDevices.put(deviceId, device);
+                Log.i(TAG, "gamepadEventConnectedImpl: " + device.toString());
+                gamepadEventConnectedImpl(deviceId, 26, 2, 2, 0, 0, "", device.getName());
             }
         }
         return device;
     }
-	
+    
+    
     // JNI calls to PlatformAndroid.cpp
     private static native void gamepadEventConnectedImpl(int deviceId, int buttonCount, int joystickCount, int triggerCount, int vendorId, int productId, String vendorString, String productString);
     private static native void gamepadEventDisconnectedImpl(int deviceId);
     
-	private InputManager _inputManager;
-	private SparseArray<InputDevice> _gamepadDevices;
+    private InputManager _inputManager;
+    private SparseArray<InputDevice> _gamepadDevices;
 }

+ 4 - 22
samples/browser/android/build.xml

@@ -6,7 +6,7 @@
     
     <loadproperties srcFile="project.properties" />
     
-    <fail message="sdk.dir is missing. Make sure to generate local.properties using 'android update project'" unless="sdk.dir" />
+    <fail message="sdk.dir is missing. Make sure to generate local.properties using 'android update project -t 1 -p . -s'" unless="sdk.dir" />
 	<fail message="OS not supported. Supported platforms: Windows, MacOS X or Linux.">
 	    <condition>
 	      <not>
@@ -20,27 +20,9 @@
 	<macrodef name="build-native">
 		<attribute name="location"/>
 	     <sequential>
-		 	<exec osfamily="unix" dir="@{location}/android" executable="android">
-			    <arg value="update"/>
-				<arg value="project"/>
-				<arg value="-t"/>
-				<arg value="1"/>
-				<arg value="-p"/>
-				<arg value="."/>
-				<arg value="-s"/>
-			</exec>
-			<exec osfamily="unix" dir="@{location}/android" executable="ndk-build"/>
-			<exec osfamily="windows" dir="@{location}/android" executable="cmd">
-				<arg value="/c"/>
-				<arg value="android.bat"/>
-				<arg value="update"/>
-				<arg value="project"/>
-				<arg value="-t"/>
-				<arg value="1"/>
-				<arg value="-p"/>
-				<arg value="."/>
-				<arg value="-s"/>
-			</exec>
+            <exec osfamily="unix" dir="@{location}/android" executable="ndk-build">
+                <arg value="-j4"/>
+            </exec>
 			<exec osfamily="windows" dir="@{location}/android" executable="cmd">
 				<arg value="/c"/>
 				<arg value="ndk-build -j4"/>

+ 4 - 22
samples/character/android/build.xml

@@ -6,7 +6,7 @@
     
     <loadproperties srcFile="project.properties" />
 
-    <fail message="sdk.dir is missing. Make sure to generate local.properties using 'android update project'" unless="sdk.dir" />
+    <fail message="sdk.dir is missing. Make sure to generate local.properties using 'android update project -t 1 -p . -s'" unless="sdk.dir" />
 	<fail message="OS not supported. Supported platforms: Windows, MacOS X or Linux.">
 	    <condition>
 	      <not>
@@ -20,27 +20,9 @@
 	<macrodef name="build-native">
 		<attribute name="location"/>
 	     <sequential>
-		 	<exec osfamily="unix" dir="@{location}/android" executable="android">
-			    <arg value="update"/>
-				<arg value="project"/>
-				<arg value="-t"/>
-				<arg value="1"/>
-				<arg value="-p"/>
-				<arg value="."/>
-				<arg value="-s"/>
-			</exec>
-			<exec osfamily="unix" dir="@{location}/android" executable="ndk-build"/>
-			<exec osfamily="windows" dir="@{location}/android" executable="cmd">
-				<arg value="/c"/>
-				<arg value="android.bat"/>
-				<arg value="update"/>
-				<arg value="project"/>
-				<arg value="-t"/>
-				<arg value="1"/>
-				<arg value="-p"/>
-				<arg value="."/>
-				<arg value="-s"/>
-			</exec>
+            <exec osfamily="unix" dir="@{location}/android" executable="ndk-build">
+                <arg value="-j4"/>
+            </exec>
 			<exec osfamily="windows" dir="@{location}/android" executable="cmd">
 				<arg value="/c"/>
 				<arg value="ndk-build -j4"/>

+ 4 - 22
samples/lua/android/build.xml

@@ -6,7 +6,7 @@
 
     <loadproperties srcFile="project.properties" />
 
-    <fail message="sdk.dir is missing. Make sure to generate local.properties using 'android update project'" unless="sdk.dir" />
+    <fail message="sdk.dir is missing. Make sure to generate local.properties using 'android update project -t 1 -p . -s'" unless="sdk.dir" />
 	<fail message="OS not supported. Supported platforms: Windows, MacOS X or Linux.">
 	    <condition>
 	      <not>
@@ -20,27 +20,9 @@
 	<macrodef name="build-native">
 		<attribute name="location"/>
 	     <sequential>
-		 	<exec osfamily="unix" dir="@{location}/android" executable="android">
-			    <arg value="update"/>
-				<arg value="project"/>
-				<arg value="-t"/>
-				<arg value="1"/>
-				<arg value="-p"/>
-				<arg value="."/>
-				<arg value="-s"/>
-			</exec>
-			<exec osfamily="unix" dir="@{location}/android" executable="ndk-build"/>
-			<exec osfamily="windows" dir="@{location}/android" executable="cmd">
-				<arg value="/c"/>
-				<arg value="android.bat"/>
-				<arg value="update"/>
-				<arg value="project"/>
-				<arg value="-t"/>
-				<arg value="1"/>
-				<arg value="-p"/>
-				<arg value="."/>
-				<arg value="-s"/>
-			</exec>
+            <exec osfamily="unix" dir="@{location}/android" executable="ndk-build">
+                <arg value="-j4"/>
+            </exec>
 			<exec osfamily="windows" dir="@{location}/android" executable="cmd">
 				<arg value="/c"/>
 				<arg value="ndk-build -j4"/>

+ 5 - 23
samples/mesh/android/build.xml

@@ -3,10 +3,10 @@
 
     <property file="local.properties" />
     <property file="ant.properties" />
-    
+
     <loadproperties srcFile="project.properties" />
 
-    <fail message="sdk.dir is missing. Make sure to generate local.properties using 'android update project'" unless="sdk.dir" />
+    <fail message="sdk.dir is missing. Make sure to generate local.properties using 'android update project -t 1 -p . -s'" unless="sdk.dir" />
 	<fail message="OS not supported. Supported platforms: Windows, MacOS X or Linux.">
 	    <condition>
 	      <not>
@@ -20,27 +20,9 @@
 	<macrodef name="build-native">
 		<attribute name="location"/>
 	     <sequential>
-		 	<exec osfamily="unix" dir="@{location}/android" executable="android">
-			    <arg value="update"/>
-				<arg value="project"/>
-				<arg value="-t"/>
-				<arg value="1"/>
-				<arg value="-p"/>
-				<arg value="."/>
-				<arg value="-s"/>
-			</exec>
-			<exec osfamily="unix" dir="@{location}/android" executable="ndk-build"/>
-			<exec osfamily="windows" dir="@{location}/android" executable="cmd">
-				<arg value="/c"/>
-				<arg value="android.bat"/>
-				<arg value="update"/>
-				<arg value="project"/>
-				<arg value="-t"/>
-				<arg value="1"/>
-				<arg value="-p"/>
-				<arg value="."/>
-				<arg value="-s"/>
-			</exec>
+            <exec osfamily="unix" dir="@{location}/android" executable="ndk-build">
+                <arg value="-j4"/>
+            </exec>
 			<exec osfamily="windows" dir="@{location}/android" executable="cmd">
 				<arg value="/c"/>
 				<arg value="ndk-build -j4"/>

+ 4 - 22
samples/particles/android/build.xml

@@ -6,7 +6,7 @@
     
     <loadproperties srcFile="project.properties" />
     
-    <fail message="sdk.dir is missing. Make sure to generate local.properties using 'android update project'" unless="sdk.dir" />
+    <fail message="sdk.dir is missing. Make sure to generate local.properties using 'android update project -t 1 -p . -s'" unless="sdk.dir" />
 	<fail message="OS not supported. Supported platforms: Windows, MacOS X or Linux.">
 	    <condition>
 	      <not>
@@ -20,27 +20,9 @@
 	<macrodef name="build-native">
 		<attribute name="location"/>
 	     <sequential>
-		 	<exec osfamily="unix" dir="@{location}/android" executable="android">
-			    <arg value="update"/>
-				<arg value="project"/>
-				<arg value="-t"/>
-				<arg value="1"/>
-				<arg value="-p"/>
-				<arg value="."/>
-				<arg value="-s"/>
-			</exec>
-			<exec osfamily="unix" dir="@{location}/android" executable="ndk-build"/>
-			<exec osfamily="windows" dir="@{location}/android" executable="cmd">
-				<arg value="/c"/>
-				<arg value="android.bat"/>
-				<arg value="update"/>
-				<arg value="project"/>
-				<arg value="-t"/>
-				<arg value="1"/>
-				<arg value="-p"/>
-				<arg value="."/>
-				<arg value="-s"/>
-			</exec>
+            <exec osfamily="unix" dir="@{location}/android" executable="ndk-build">
+                <arg value="-j4"/>
+            </exec>
 			<exec osfamily="windows" dir="@{location}/android" executable="cmd">
 				<arg value="/c"/>
 				<arg value="ndk-build -j4"/>

+ 4 - 22
samples/racer/android/build.xml

@@ -6,7 +6,7 @@
     
     <loadproperties srcFile="project.properties" />
     
-    <fail message="sdk.dir is missing. Make sure to generate local.properties using 'android update project'" unless="sdk.dir" />
+    <fail message="sdk.dir is missing. Make sure to generate local.properties using 'android update project -t 1 -p . -s'" unless="sdk.dir" />
 	<fail message="OS not supported. Supported platforms: Windows, MacOS X or Linux.">
 	    <condition>
 	      <not>
@@ -20,27 +20,9 @@
 	<macrodef name="build-native">
 		<attribute name="location"/>
 	     <sequential>
-		 	<exec osfamily="unix" dir="@{location}/android" executable="android">
-			    <arg value="update"/>
-				<arg value="project"/>
-				<arg value="-t"/>
-				<arg value="1"/>
-				<arg value="-p"/>
-				<arg value="."/>
-				<arg value="-s"/>
-			</exec>
-			<exec osfamily="unix" dir="@{location}/android" executable="ndk-build"/>
-			<exec osfamily="windows" dir="@{location}/android" executable="cmd">
-				<arg value="/c"/>
-				<arg value="android.bat"/>
-				<arg value="update"/>
-				<arg value="project"/>
-				<arg value="-t"/>
-				<arg value="1"/>
-				<arg value="-p"/>
-				<arg value="."/>
-				<arg value="-s"/>
-			</exec>
+            <exec osfamily="unix" dir="@{location}/android" executable="ndk-build">
+                <arg value="-j4"/>
+            </exec>
 			<exec osfamily="windows" dir="@{location}/android" executable="cmd">
 				<arg value="/c"/>
 				<arg value="ndk-build -j4"/>

+ 4 - 22
samples/spaceship/android/build.xml

@@ -6,7 +6,7 @@
     
     <loadproperties srcFile="project.properties" />
     
-    <fail message="sdk.dir is missing. Make sure to generate local.properties using 'android update project'" unless="sdk.dir" />
+    <fail message="sdk.dir is missing. Make sure to generate local.properties using 'android update project -t 1 -p . -s'" unless="sdk.dir" />
 	<fail message="OS not supported. Supported platforms: Windows, MacOS X or Linux.">
 	    <condition>
 	      <not>
@@ -20,27 +20,9 @@
 	<macrodef name="build-native">
 		<attribute name="location"/>
 	     <sequential>
-		 	<exec osfamily="unix" dir="@{location}/android" executable="android">
-			    <arg value="update"/>
-				<arg value="project"/>
-				<arg value="-t"/>
-				<arg value="1"/>
-				<arg value="-p"/>
-				<arg value="."/>
-				<arg value="-s"/>
-			</exec>
-			<exec osfamily="unix" dir="@{location}/android" executable="ndk-build"/>
-			<exec osfamily="windows" dir="@{location}/android" executable="cmd">
-				<arg value="/c"/>
-				<arg value="android.bat"/>
-				<arg value="update"/>
-				<arg value="project"/>
-				<arg value="-t"/>
-				<arg value="1"/>
-				<arg value="-p"/>
-				<arg value="."/>
-				<arg value="-s"/>
-			</exec>
+            <exec osfamily="unix" dir="@{location}/android" executable="ndk-build">
+                <arg value="-j4"/>
+            </exec>
 			<exec osfamily="windows" dir="@{location}/android" executable="cmd">
 				<arg value="/c"/>
 				<arg value="ndk-build -j4"/>

+ 33 - 5
template/android/build.xml

@@ -6,10 +6,41 @@
     
     <loadproperties srcFile="project.properties" />
 
-    <fail message="sdk.dir is missing. Make sure to generate local.properties using 'android update project'" unless="sdk.dir"/>
+    <fail message="sdk.dir is missing. Make sure to generate local.properties using 'android update project -t 1 -p . -s'" unless="sdk.dir"/>
+	<fail message="OS not supported. Supported platforms: Windows, MacOS X or Linux.">
+	    <condition>
+	      <not>
+	        <or>
+	          <os family="unix"/>
+	          <os family="windows"/>
+	        </or>
+	      </not>
+	    </condition>
+	</fail>
+
+	<macrodef name="build-native">
+		<attribute name="location"/>
+	     <sequential>
+            <exec osfamily="unix" dir="@{location}/android" executable="ndk-build">
+                <arg value="-j4"/>
+            </exec>
+			<exec osfamily="windows" dir="@{location}/android" executable="cmd">
+				<arg value="/c"/>
+				<arg value="ndk-build -j4"/>
+			</exec> 
+	    </sequential>
+	</macrodef>
 
     <target name="-pre-build">
-	<mkdir dir="src"/>
+        <build-native location="../GAMEPLAY_PATH/gameplay"/>
+    	<build-native location=".."/>
+        <mkdir dir="../src/org/gameplay3d"/>
+	    <copy todir="../src/org/gameplay3d">
+            <fileset dir="../GAMEPLAY_PATH/gameplay/src/org/gameplay3d"/>
+	    </copy>
+    </target>
+
+    <target name="-post-compile">
         <copy todir="assets/res">
             <fileset dir="../res" />
         </copy>
@@ -21,9 +52,6 @@
        </copy>
     </target>
 
-    <target name="-post-compile">
-    </target>
-
     <!-- version-tag: 1 -->
     <import file="${sdk.dir}/tools/ant/build.xml" />