Browse Source

Reviewed Android inputs and gestures system

Corrected Android processing for some inputs (BACK button, VOLUME
buttons)
Redesigned Gestures system (some work still required)
SetEnabledGestures() - Only support desired gestures (requires some
review)
raysan5 9 years ago
parent
commit
d32feaa668
4 changed files with 294 additions and 303 deletions
  1. 186 38
      src/core.c
  2. 83 249
      src/gestures.c
  3. 12 9
      src/gestures.h
  4. 13 7
      src/raylib.h

+ 186 - 38
src/core.c

@@ -66,7 +66,7 @@
     #include <jni.h>                        // Java native interface
     #include <jni.h>                        // Java native interface
     #include <android/sensor.h>             // Android sensors functions
     #include <android/sensor.h>             // Android sensors functions
     #include <android/window.h>             // Defines AWINDOW_FLAG_FULLSCREEN and others
     #include <android/window.h>             // Defines AWINDOW_FLAG_FULLSCREEN and others
-    //#include <android_native_app_glue.h>    // Defines basic app state struct and manages activity
+    #include <android_native_app_glue.h>    // Defines basic app state struct and manages activity
 
 
     #include <EGL/egl.h>        // Khronos EGL library - Native platform display device control functions
     #include <EGL/egl.h>        // Khronos EGL library - Native platform display device control functions
     #include <GLES2/gl2.h>      // Khronos OpenGL ES 2.0 library
     #include <GLES2/gl2.h>      // Khronos OpenGL ES 2.0 library
@@ -103,7 +103,6 @@
 //----------------------------------------------------------------------------------
 //----------------------------------------------------------------------------------
 // Defines and Macros
 // Defines and Macros
 //----------------------------------------------------------------------------------
 //----------------------------------------------------------------------------------
-#define MAX_TOUCH_POINTS 256
 
 
 //----------------------------------------------------------------------------------
 //----------------------------------------------------------------------------------
 // Types and Structures Definition
 // Types and Structures Definition
@@ -121,7 +120,8 @@ static struct android_app *app;                 // Android activity
 static struct android_poll_source *source;      // Android events polling source
 static struct android_poll_source *source;      // Android events polling source
 static int ident, events;
 static int ident, events;
 static bool windowReady = false;                // Used to detect display initialization
 static bool windowReady = false;                // Used to detect display initialization
-
+static bool appEnabled = true;                  // Used to detec if app is active
+static bool contextRebindRequired = false;      // Used to know context rebind required
 #elif defined(PLATFORM_RPI)
 #elif defined(PLATFORM_RPI)
 static EGL_DISPMANX_WINDOW_T nativeWindow;      // Native window (graphic device)
 static EGL_DISPMANX_WINDOW_T nativeWindow;      // Native window (graphic device)
 
 
@@ -149,6 +149,7 @@ static int gamepadStream = -1;                  // Gamepad device file descripto
 static EGLDisplay display;          // Native display device (physical screen connection)
 static EGLDisplay display;          // Native display device (physical screen connection)
 static EGLSurface surface;          // Surface to draw on, framebuffers (connected to context)
 static EGLSurface surface;          // Surface to draw on, framebuffers (connected to context)
 static EGLContext context;          // Graphic context, mode in which drawing can be done
 static EGLContext context;          // Graphic context, mode in which drawing can be done
+static EGLConfig config;            // Graphic config
 static uint64_t baseTime;                   // Base time measure for hi-res timer
 static uint64_t baseTime;                   // Base time measure for hi-res timer
 static bool windowShouldClose = false;      // Flag to set window for closing
 static bool windowShouldClose = false;      // Flag to set window for closing
 #endif
 #endif
@@ -254,10 +255,12 @@ static void TakeScreenshot(void);
 
 
 #if defined(PLATFORM_ANDROID)
 #if defined(PLATFORM_ANDROID)
 static void AndroidCommandCallback(struct android_app *app, int32_t cmd);                  // Process Android activity lifecycle commands
 static void AndroidCommandCallback(struct android_app *app, int32_t cmd);                  // Process Android activity lifecycle commands
+static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event);          // Process Android inputs
 #endif
 #endif
 
 
 #if defined(PLATFORM_WEB)
 #if defined(PLATFORM_WEB)
 static EM_BOOL EmscriptenFullscreenChangeCallback(int eventType, const EmscriptenFullscreenChangeEvent *e, void *userData);
 static EM_BOOL EmscriptenFullscreenChangeCallback(int eventType, const EmscriptenFullscreenChangeEvent *e, void *userData);
+static EM_BOOL EmscriptenInputCallback(int eventType, const EmscriptenTouchEvent *touchEvent, void *userData);
 #endif
 #endif
 
 
 //----------------------------------------------------------------------------------
 //----------------------------------------------------------------------------------
@@ -293,9 +296,15 @@ void InitWindow(int width, int height, const char *title)
 #endif
 #endif
 
 
 #if defined(PLATFORM_WEB)
 #if defined(PLATFORM_WEB)
-    InitGesturesSystem();
-    
     emscripten_set_fullscreenchange_callback(0, 0, 1, EmscriptenFullscreenChangeCallback);
     emscripten_set_fullscreenchange_callback(0, 0, 1, EmscriptenFullscreenChangeCallback);
+
+    // NOTE: Some code examples
+    //emscripten_set_touchstart_callback(0, NULL, 1, Emscripten_HandleTouch);
+    //emscripten_set_touchend_callback("#canvas", data, 0, Emscripten_HandleTouch);
+    emscripten_set_touchstart_callback("#canvas", NULL, 1, EmscriptenInputCallback);
+    emscripten_set_touchend_callback("#canvas", NULL, 1, EmscriptenInputCallback);
+    emscripten_set_touchmove_callback("#canvas", NULL, 1, EmscriptenInputCallback);
+    emscripten_set_touchcancel_callback("#canvas", NULL, 1, EmscriptenInputCallback);
 #endif
 #endif
 
 
     mousePosition.x = screenWidth/2;
     mousePosition.x = screenWidth/2;
@@ -350,24 +359,23 @@ void InitWindow(int width, int height, struct android_app *state)
 
 
     //state->userData = &engine;
     //state->userData = &engine;
     app->onAppCmd = AndroidCommandCallback;
     app->onAppCmd = AndroidCommandCallback;
-
-    InitAssetManager(app->activity->assetManager);
+    app->onInputEvent = AndroidInputCallback;
     
     
-    InitGesturesSystem(app);
+    InitAssetManager(app->activity->assetManager);
 
 
     TraceLog(INFO, "Android app initialized successfully");
     TraceLog(INFO, "Android app initialized successfully");
 
 
+    // Wait for window to be initialized (display and context)
     while (!windowReady)
     while (!windowReady)
     {
     {
-        // Wait for window to be initialized (display and context)
         // Process events loop
         // Process events loop
         while ((ident = ALooper_pollAll(0, NULL, &events,(void**)&source)) >= 0)
         while ((ident = ALooper_pollAll(0, NULL, &events,(void**)&source)) >= 0)
         {
         {
             // Process this event
             // Process this event
             if (source != NULL) source->process(app, source);
             if (source != NULL) source->process(app, source);
 
 
-            // Check if we are exiting
-            if (app->destroyRequested != 0) windowShouldClose = true;
+            // NOTE: Never close window, native activity is controlled by the system!
+            //if (app->destroyRequested != 0) windowShouldClose = true;
         }
         }
     }
     }
 }
 }
@@ -1221,7 +1229,6 @@ static void InitDisplay(int width, int height)
     };
     };
 
 
     EGLint numConfigs;
     EGLint numConfigs;
-    EGLConfig config;
 
 
     // Get an EGL display connection
     // Get an EGL display connection
     display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
     display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
@@ -1455,30 +1462,62 @@ static void AndroidCommandCallback(struct android_app *app, int32_t cmd)
 
 
             if (app->window != NULL)
             if (app->window != NULL)
             {
             {
-                // Init device display (monitor, LCD, ...)
-                InitDisplay(screenWidth, screenHeight);
+                if (contextRebindRequired)
+                {
+                    // Reset screen scaling to full display size
+                    EGLint displayFormat;
+                    eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &displayFormat);
+                    ANativeWindow_setBuffersGeometry(app->window, renderWidth, renderHeight, displayFormat);
 
 
-                // Init OpenGL graphics
-                InitGraphics();
+                    // Recreate display surface and re-attach OpenGL context
+                    surface = eglCreateWindowSurface(display, config, app->window, NULL);
+                    eglMakeCurrent(display, surface, surface, context);
 
 
-                // Load default font for convenience
-                // NOTE: External function (defined in module: text)
-                LoadDefaultFont();
+                    contextRebindRequired = false;
+                }
+                else
+                {
+                    // Init device display (monitor, LCD, ...)
+                    InitDisplay(screenWidth, screenHeight);
+
+                    // Init OpenGL graphics
+                    InitGraphics();
+
+                    // Load default font for convenience
+                    // NOTE: External function (defined in module: text)
+                    LoadDefaultFont();
+                    
+                    // TODO: GPU assets reload in case of lost focus (lost context)
+                    // NOTE: This problem has been solved just unbinding and rebinding context from display
+					/*
+                    if (assetsReloadRequired)
+                    {
+                        for (int i = 0; i < assetsCount; i++)
+                        {
+                            // TODO: Unload old asset if required
+                            
+                            // Load texture again to pointed texture
+                            (*textureAsset + i) = LoadTexture(assetPath[i]);
+                        }
+                    }
+                    */
 
 
-                // Init hi-res timer
-                InitTimer();
+                    // Init hi-res timer
+                    InitTimer();
 
 
-                // raylib logo appearing animation (if enabled)
-                if (showLogo)
-                {
-                    SetTargetFPS(60);
-                    LogoAnimation();
+                    // raylib logo appearing animation (if enabled)
+                    if (showLogo)
+                    {
+                        SetTargetFPS(60);   // Not required on Android
+                        LogoAnimation();
+                    }
                 }
                 }
             }
             }
         } break;
         } break;
         case APP_CMD_GAINED_FOCUS:
         case APP_CMD_GAINED_FOCUS:
         {
         {
             TraceLog(INFO, "APP_CMD_GAINED_FOCUS");
             TraceLog(INFO, "APP_CMD_GAINED_FOCUS");
+            appEnabled = true;
             //ResumeMusicStream();
             //ResumeMusicStream();
         } break;
         } break;
         case APP_CMD_PAUSE:
         case APP_CMD_PAUSE:
@@ -1489,11 +1528,18 @@ static void AndroidCommandCallback(struct android_app *app, int32_t cmd)
         {
         {
             //DrawFrame();
             //DrawFrame();
             TraceLog(INFO, "APP_CMD_LOST_FOCUS");
             TraceLog(INFO, "APP_CMD_LOST_FOCUS");
+            appEnabled = false;
             //PauseMusicStream();
             //PauseMusicStream();
         } break;
         } break;
         case APP_CMD_TERM_WINDOW:
         case APP_CMD_TERM_WINDOW:
         {
         {
-            // TODO: Do display destruction here? -> Yes but only display, don't free buffers!
+            // Dettach OpenGL context and destroy display surface
+            // NOTE 1: Detaching context before destroying display surface avoids losing our resources (textures, shaders, VBOs...)
+            // NOTE 2: In some cases (too many context loaded), OS could unload context automatically... :(
+            eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+            eglDestroySurface(display, surface);
+            
+            contextRebindRequired = true;
 
 
             TraceLog(INFO, "APP_CMD_TERM_WINDOW");
             TraceLog(INFO, "APP_CMD_TERM_WINDOW");
         } break;
         } break;
@@ -1524,6 +1570,61 @@ static void AndroidCommandCallback(struct android_app *app, int32_t cmd)
         default: break;
         default: break;
     }
     }
 }
 }
+
+// Android: Get input events
+static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event)
+{
+    //http://developer.android.com/ndk/reference/index.html
+    
+    int type = AInputEvent_getType(event);
+
+    if (type == AINPUT_EVENT_TYPE_MOTION)
+    {
+        touchPosition.x = AMotionEvent_getX(event, 0);
+        touchPosition.y = AMotionEvent_getY(event, 0);
+    }
+    else if (type == AINPUT_EVENT_TYPE_KEY)
+    {
+        int32_t keycode = AKeyEvent_getKeyCode(event);
+        //int32_t AKeyEvent_getMetaState(event);
+
+        //if (keycode == AKEYCODE_HOME) { }
+        //if (keycode == AKEYCODE_POWER) { }
+        if (keycode == AKEYCODE_BACK)
+        {
+            // Eat BACK_BUTTON, just do nothing... and don't let to be handled by OS!
+            return 1;
+        }
+        else if ((keycode == AKEYCODE_VOLUME_UP) || (keycode == AKEYCODE_VOLUME_DOWN))
+        {
+            // Set default OS behaviour
+            return 0;
+        }
+    }
+    
+    int32_t action = AMotionEvent_getAction(event);
+    unsigned int flags = action & AMOTION_EVENT_ACTION_MASK;
+    
+    GestureEvent gestureEvent;
+    
+    // Register touch actions
+    if (flags == AMOTION_EVENT_ACTION_DOWN) gestureEvent.touchAction = TOUCH_DOWN;
+    else if (flags == AMOTION_EVENT_ACTION_UP) gestureEvent.touchAction = TOUCH_UP;
+    else if (flags == AMOTION_EVENT_ACTION_MOVE) gestureEvent.touchAction = TOUCH_MOVE;
+    
+    // Register touch points count
+    gestureEvent.pointCount = AMotionEvent_getPointerCount(event);
+    
+    // Register touch points position
+    // NOTE: Only two points registered
+    gestureEvent.position[0] = (Vector2){ AMotionEvent_getX(event, 0), AMotionEvent_getY(event, 0) };
+    gestureEvent.position[1] = (Vector2){ AMotionEvent_getX(event, 1), AMotionEvent_getY(event, 1) };
+    
+    // Gesture data is sent to gestures system for processing
+    ProcessGestureEvent(gestureEvent);
+
+    return 0;   // return 1;
+}
 #endif
 #endif
 
 
 #if defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI)
 #if defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI)
@@ -1613,9 +1714,8 @@ static bool GetMouseButtonStatus(int button)
 static void PollInputEvents(void)
 static void PollInputEvents(void)
 {
 {
 #if defined(PLATFORM_ANDROID) || defined(PLATFORM_WEB)
 #if defined(PLATFORM_ANDROID) || defined(PLATFORM_WEB)
-    // Touch events reading (requires gestures module)
-    touchPosition = GetRawTouchPosition();
-    
+
+    // TODO: Remove this requirement...
     UpdateGestures();
     UpdateGestures();
 #endif
 #endif
     
     
@@ -1645,23 +1745,18 @@ static void PollInputEvents(void)
     glfwPollEvents();       // Register keyboard/mouse events... and window events!
     glfwPollEvents();       // Register keyboard/mouse events... and window events!
 #elif defined(PLATFORM_ANDROID)
 #elif defined(PLATFORM_ANDROID)
 
 
-    // TODO: Check virtual keyboard (?)
-
     // Poll Events (registered events)
     // Poll Events (registered events)
-    // TODO: Enable/disable activityMinimized to block activity if minimized
-    //while ((ident = ALooper_pollAll(activityMinimized ? 0 : -1, NULL, &events,(void**)&source)) >= 0)
-    while ((ident = ALooper_pollAll(0, NULL, &events, (void**)&source)) >= 0)
+    // NOTE: Activity is paused if not enabled (appEnabled)
+    while ((ident = ALooper_pollAll(appEnabled ? 0 : -1, NULL, &events,(void**)&source)) >= 0)
     {
     {
         // Process this event
         // Process this event
         if (source != NULL) source->process(app, source);
         if (source != NULL) source->process(app, source);
 
 
-        // Check if we are exiting
+        // NOTE: Never close window, native activity is controlled by the system!
         if (app->destroyRequested != 0)
         if (app->destroyRequested != 0)
         {
         {
-            // NOTE: Never close window, native activity is controlled by the system!
             //TraceLog(INFO, "Closing Window...");
             //TraceLog(INFO, "Closing Window...");
             //windowShouldClose = true;
             //windowShouldClose = true;
-
             //ANativeActivity_finish(app->activity);
             //ANativeActivity_finish(app->activity);
         }
         }
     }
     }
@@ -2035,6 +2130,59 @@ static EM_BOOL EmscriptenFullscreenChangeCallback(int eventType, const Emscripte
 
 
     return 0;
     return 0;
 }
 }
+
+// Web: Get input events
+static EM_BOOL EmscriptenInputCallback(int eventType, const EmscriptenTouchEvent *touchEvent, void *userData)
+{
+    /*
+    for (int i = 0; i < touchEvent->numTouches; i++)
+    {
+        long x, y, id;
+
+        if (!touchEvent->touches[i].isChanged) continue;
+
+        id = touchEvent->touches[i].identifier;
+        x = touchEvent->touches[i].canvasX;
+        y = touchEvent->touches[i].canvasY;
+    }
+    
+    printf("%s, numTouches: %d %s%s%s%s\n", emscripten_event_type_to_string(eventType), event->numTouches,
+           event->ctrlKey ? " CTRL" : "", event->shiftKey ? " SHIFT" : "", event->altKey ? " ALT" : "", event->metaKey ? " META" : "");
+
+    for(int i = 0; i < event->numTouches; ++i)
+    {
+        const EmscriptenTouchPoint *t = &event->touches[i];
+        
+        printf("  %ld: screen: (%ld,%ld), client: (%ld,%ld), page: (%ld,%ld), isChanged: %d, onTarget: %d, canvas: (%ld, %ld)\n",
+          t->identifier, t->screenX, t->screenY, t->clientX, t->clientY, t->pageX, t->pageY, t->isChanged, t->onTarget, t->canvasX, t->canvasY);
+    }
+    */
+    
+    GestureEvent gestureEvent;
+
+    // Register touch actions
+    if (eventType == EMSCRIPTEN_EVENT_TOUCHSTART) gestureEvent.touchAction = TOUCH_DOWN;
+    else if (eventType == EMSCRIPTEN_EVENT_TOUCHEND) gestureEvent.touchAction = TOUCH_UP;
+    else if (eventType == EMSCRIPTEN_EVENT_TOUCHMOVE) gestureEvent.touchAction = TOUCH_MOVE;
+    
+    // Register touch points count
+    gestureEvent.pointCount = touchEvent->numTouches;
+    
+    // Register touch points position
+    // NOTE: Only two points registered
+    // TODO: Touch data should be scaled accordingly!
+    //gestureEvent.position[0] = (Vector2){ touchEvent->touches[0].canvasX, touchEvent->touches[0].canvasY };
+    //gestureEvent.position[1] = (Vector2){ touchEvent->touches[1].canvasX, touchEvent->touches[1].canvasY };
+    gestureEvent.position[0] = (Vector2){ touchEvent->touches[0].targetX, touchEvent->touches[0].targetY };
+    gestureEvent.position[1] = (Vector2){ touchEvent->touches[1].targetX, touchEvent->touches[1].targetY };
+
+    touchPosition = gestureEvent.position[0];
+    
+    // Gesture data is sent to gestures system for processing
+    ProcessGestureEvent(gestureEvent);   // Process obtained gestures data
+
+    return 1;
+}
 #endif
 #endif
 
 
 // Plays raylib logo appearing animation
 // Plays raylib logo appearing animation

+ 83 - 249
src/gestures.c

@@ -42,23 +42,12 @@
     #include <time.h>           // Used for clock functions
     #include <time.h>           // Used for clock functions
 #endif
 #endif
 
 
-#if defined(PLATFORM_ANDROID)
-    #include <jni.h>                        // Java native interface
-    #include <android/sensor.h>             // Android sensors functions
-    #include <android/window.h>             // Defines AWINDOW_FLAG_FULLSCREEN and others
-#endif
-
-#if defined(PLATFORM_WEB)
-    #include <emscripten/emscripten.h>
-    #include <emscripten/html5.h>
-#endif
-
 //----------------------------------------------------------------------------------
 //----------------------------------------------------------------------------------
 // Defines and Macros
 // Defines and Macros
 //----------------------------------------------------------------------------------
 //----------------------------------------------------------------------------------
 #define FORCE_TO_SWIPE          20
 #define FORCE_TO_SWIPE          20
 #define TAP_TIMEOUT             300
 #define TAP_TIMEOUT             300
-#define MAX_TOUCH_POINTS        4
+//#define MAX_TOUCH_POINTS        4
 
 
 //----------------------------------------------------------------------------------
 //----------------------------------------------------------------------------------
 // Types and Structures Definition
 // Types and Structures Definition
@@ -69,20 +58,6 @@ typedef enum {
     TYPE_DUAL_INPUT
     TYPE_DUAL_INPUT
 } GestureType;
 } GestureType;
 
 
-typedef enum {
-    UP,
-    DOWN,
-    MOVE
-} ActionType;
-
-typedef struct {
-    ActionType action;
-    int pointCount;
-    int pointerId[MAX_TOUCH_POINTS];
-    Vector2 position[MAX_TOUCH_POINTS];
-} GestureEvent;
-
-
 //----------------------------------------------------------------------------------
 //----------------------------------------------------------------------------------
 // Global Variables Definition
 // Global Variables Definition
 //----------------------------------------------------------------------------------
 //----------------------------------------------------------------------------------
@@ -119,133 +94,24 @@ static float pinchDelta = 0;            // Pinch delta displacement
 static int previousGesture = GESTURE_NONE;
 static int previousGesture = GESTURE_NONE;
 static int currentGesture = GESTURE_NONE;
 static int currentGesture = GESTURE_NONE;
 
 
-static unsigned int enabledGestures = 0;       // TODO: Currently not in use...
-
-static Vector2 rawTouchPosition;
+// Enabled gestures flags, all gestures enabled by default 
+static unsigned int enabledGestures = 0b0000011111111111;   
 
 
 //----------------------------------------------------------------------------------
 //----------------------------------------------------------------------------------
 // Module specific Functions Declaration
 // Module specific Functions Declaration
 //----------------------------------------------------------------------------------
 //----------------------------------------------------------------------------------
-static void ProcessMotionEvent(GestureEvent event);
-
 static void InitPinchGesture(Vector2 posA, Vector2 posB);
 static void InitPinchGesture(Vector2 posA, Vector2 posB);
 static float CalculateAngle(Vector2 initialPosition, Vector2 actualPosition, float magnitude);
 static float CalculateAngle(Vector2 initialPosition, Vector2 actualPosition, float magnitude);
 static float VectorDistance(Vector2 v1, Vector2 v2);
 static float VectorDistance(Vector2 v1, Vector2 v2);
 static float VectorDotProduct(Vector2 v1, Vector2 v2);
 static float VectorDotProduct(Vector2 v1, Vector2 v2);
 static double GetCurrentTime();
 static double GetCurrentTime();
 
 
-#if defined(PLATFORM_WEB)
-static EM_BOOL EmscriptenInputCallback(int eventType, const EmscriptenTouchEvent *touchEvent, void *userData);
-#endif
-
-#if defined(PLATFORM_ANDROID)
-static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event);
-#endif
-
 //----------------------------------------------------------------------------------
 //----------------------------------------------------------------------------------
 // Module Functions Definition
 // Module Functions Definition
 //----------------------------------------------------------------------------------
 //----------------------------------------------------------------------------------
 
 
-// Get touch position (could require further processing depending on display size)
-Vector2 GetRawTouchPosition(void)
-{
-    return rawTouchPosition;
-}
-
-// Check if a gesture have been detected
-bool IsGestureDetected(void)
-{
-    if (currentGesture != GESTURE_NONE) return true;
-    else return false;
-}
-
-// Check gesture type
-int GetGestureType(void)
-{
-    return currentGesture;
-}
-
-void SetGesturesEnabled(unsigned int gestureFlags)
-{
-    enabledGestures = gestureFlags;
-}
-
-// Get drag intensity (pixels per frame)
-float GetGestureDragIntensity(void)
-{
-    return intensity;
-}
-
-// Get drag angle
-// NOTE: Angle in degrees, horizontal-right is 0, counterclock-wise
-float GetGestureDragAngle(void)
-{
-    return angle;
-}
-
-// Get drag vector (between initial and final position)
-Vector2 GetGestureDragVector(void)
-{
-    return dragVector;
-}
-
-// Hold time measured in frames
-int GetGestureHoldDuration(void)
-{
-    return 0;
-}
-
-// Get magnitude between two pinch points
-float GetGesturePinchDelta(void)
-{
-    return pinchDelta;
-}
-
-// Get angle beween two pinch points
-// NOTE: Angle in degrees, horizontal-right is 0, counterclock-wise
-float GetGesturePinchAngle(void)
-{
-    return 0;
-}
-
-#if defined(PLATFORM_WEB)
-// Init gestures system (web)
-void InitGesturesSystem(void)
-{
-    // Init gestures system web (emscripten)
-    
-    // NOTE: Some code examples
-    //emscripten_set_touchstart_callback(0, NULL, 1, Emscripten_HandleTouch);
-    //emscripten_set_touchend_callback("#canvas", data, 0, Emscripten_HandleTouch);
-    
-    emscripten_set_touchstart_callback("#canvas", NULL, 1, EmscriptenInputCallback);
-    emscripten_set_touchend_callback("#canvas", NULL, 1, EmscriptenInputCallback);
-    emscripten_set_touchmove_callback("#canvas", NULL, 1, EmscriptenInputCallback);
-    emscripten_set_touchcancel_callback("#canvas", NULL, 1, EmscriptenInputCallback);
-}
-#elif defined(PLATFORM_ANDROID)
-// Init gestures system (android)
-void InitGesturesSystem(struct android_app *app)
-{
-    app->onInputEvent = AndroidInputCallback;
-    
-    // TODO: Receive frameBuffer data: displayWidth/displayHeight, renderWidth/renderHeight, screenWidth/screenHeight
-}
-#endif
-
-// Update gestures detected (must be called every frame)
-void UpdateGestures(void)
-{
-    // NOTE: Gestures are processed through system callbacks on touch events
-    
-    if ((previousGesture == GESTURE_TAP) && (currentGesture == GESTURE_TAP)) currentGesture = GESTURE_HOLD;
-    else if (currentGesture != GESTURE_HOLD) currentGesture = GESTURE_NONE;
-}
-
-//----------------------------------------------------------------------------------
-// Module specific Functions Definition
-//----------------------------------------------------------------------------------
-static void ProcessMotionEvent(GestureEvent event)
+// Process gesture event and translate it into gestures
+void ProcessGestureEvent(GestureEvent event)
 {
 {
     // Resets
     // Resets
     dragVector = (Vector2){ 0, 0 };
     dragVector = (Vector2){ 0, 0 };
@@ -257,7 +123,7 @@ static void ProcessMotionEvent(GestureEvent event)
     {
     {
         case TYPE_MOTIONLESS: // Detect TAP, DOUBLE_TAP and HOLD events
         case TYPE_MOTIONLESS: // Detect TAP, DOUBLE_TAP and HOLD events
         {
         {
-            if (event.action == DOWN)
+            if (event.touchAction == TOUCH_DOWN)
             {
             {
                 if (event.pointCount > 1) InitPinchGesture(event.position[0], event.position[1]);
                 if (event.pointCount > 1) InitPinchGesture(event.position[0], event.position[1]);
                 else
                 else
@@ -279,7 +145,7 @@ static void ProcessMotionEvent(GestureEvent event)
                     else currentGesture = GESTURE_TAP;
                     else currentGesture = GESTURE_TAP;
                 }
                 }
             }
             }
-            else if (event.action == UP)
+            else if (event.touchAction == TOUCH_UP)
             {
             {
 			    currentGesture = GESTURE_NONE;
 			    currentGesture = GESTURE_NONE;
 
 
@@ -297,7 +163,7 @@ static void ProcessMotionEvent(GestureEvent event)
                 eventTime = GetCurrentTime();
                 eventTime = GetCurrentTime();
             }
             }
             // Begin dragging
             // Begin dragging
-            else if (event.action == MOVE)
+            else if (event.touchAction == TOUCH_MOVE)
             {
             {
                 if (event.pointCount > 1) InitPinchGesture(event.position[0], event.position[1]);
                 if (event.pointCount > 1) InitPinchGesture(event.position[0], event.position[1]);
                 else
                 else
@@ -316,7 +182,7 @@ static void ProcessMotionEvent(GestureEvent event)
         case TYPE_DRAG: // Detect DRAG and SWIPE events 
         case TYPE_DRAG: // Detect DRAG and SWIPE events 
         {
         {
             // end of the drag
             // end of the drag
-            if (event.action == UP)
+            if (event.touchAction == TOUCH_UP)
             {
             {
                 // Return Swipe if we have enough sensitivity
                 // Return Swipe if we have enough sensitivity
                 if (intensity > FORCE_TO_SWIPE)
                 if (intensity > FORCE_TO_SWIPE)
@@ -334,14 +200,13 @@ static void ProcessMotionEvent(GestureEvent event)
                 gestureType = TYPE_MOTIONLESS;
                 gestureType = TYPE_MOTIONLESS;
             }
             }
             // Update while we are dragging
             // Update while we are dragging
-            else if (event.action == MOVE)
+            else if (event.touchAction == TOUCH_MOVE)
             {
             {
                 if (event.pointCount > 1) InitPinchGesture(event.position[0], event.position[1]);
                 if (event.pointCount > 1) InitPinchGesture(event.position[0], event.position[1]);
                 else
                 else
                 {
                 {
                     lastDragPosition = endDragPosition;
                     lastDragPosition = endDragPosition;
-                    
-                    endDragPosition = rawTouchPosition;
+                    endDragPosition = event.position[0];
                     
                     
                     //endDragPosition.x = AMotionEvent_getX(event, 0);
                     //endDragPosition.x = AMotionEvent_getX(event, 0);
                     //endDragPosition.y = AMotionEvent_getY(event, 0);
                     //endDragPosition.y = AMotionEvent_getY(event, 0);
@@ -359,7 +224,7 @@ static void ProcessMotionEvent(GestureEvent event)
         } break;
         } break;
         case TYPE_DUAL_INPUT:
         case TYPE_DUAL_INPUT:
         {
         {
-            if (event.action == UP)
+            if (event.touchAction == TOUCH_UP)
             {
             {
                 if (event.pointCount == 1)
                 if (event.pointCount == 1)
                 {
                 {
@@ -368,7 +233,7 @@ static void ProcessMotionEvent(GestureEvent event)
                 }
                 }
                 gestureType = TYPE_MOTIONLESS;
                 gestureType = TYPE_MOTIONLESS;
             }
             }
-            else if (event.action == MOVE)
+            else if (event.touchAction == TOUCH_MOVE)
             {
             {
                 // Adapt the ending position of the inputs
                 // Adapt the ending position of the inputs
                 firstEndPinchPosition = event.position[0];
                 firstEndPinchPosition = event.position[0];
@@ -410,9 +275,78 @@ static void ProcessMotionEvent(GestureEvent event)
             }
             }
         } break;
         } break;
     }
     }
-    //--------------------------------------------------------------------
 }
 }
 
 
+// Check if a gesture have been detected
+bool IsGestureDetected(void)
+{
+    if (currentGesture != GESTURE_NONE) return true;
+    else return false;
+}
+
+// Check gesture type
+int GetGestureType(void)
+{
+    // Get current gesture only if enabled
+    return (enabledGestures & currentGesture);
+}
+
+void SetGesturesEnabled(unsigned int gestureFlags)
+{
+    enabledGestures = enabledGestures | gestureFlags;
+}
+
+// Get drag intensity (pixels per frame)
+float GetGestureDragIntensity(void)
+{
+    return intensity;
+}
+
+// Get drag angle
+// NOTE: Angle in degrees, horizontal-right is 0, counterclock-wise
+float GetGestureDragAngle(void)
+{
+    return angle;
+}
+
+// Get drag vector (between initial and final position)
+Vector2 GetGestureDragVector(void)
+{
+    return dragVector;
+}
+
+// Hold time measured in frames
+int GetGestureHoldDuration(void)
+{
+    return 0;
+}
+
+// Get magnitude between two pinch points
+float GetGesturePinchDelta(void)
+{
+    return pinchDelta;
+}
+
+// Get angle beween two pinch points
+// NOTE: Angle in degrees, horizontal-right is 0, counterclock-wise
+float GetGesturePinchAngle(void)
+{
+    return 0;
+}
+
+// Update gestures detected (must be called every frame)
+void UpdateGestures(void)
+{
+    // NOTE: Gestures are processed through system callbacks on touch events
+    
+    if ((previousGesture == GESTURE_TAP) && (currentGesture == GESTURE_TAP)) currentGesture = GESTURE_HOLD;
+    else if (currentGesture != GESTURE_HOLD) currentGesture = GESTURE_NONE;
+}
+
+//----------------------------------------------------------------------------------
+// Module specific Functions Definition
+//----------------------------------------------------------------------------------
+
 static float CalculateAngle(Vector2 initialPosition, Vector2 finalPosition, float magnitude)
 static float CalculateAngle(Vector2 initialPosition, Vector2 finalPosition, float magnitude)
 {
 {
     float angle;
     float angle;
@@ -520,103 +454,3 @@ static double GetCurrentTime()
 
 
     return time;
     return time;
 }
 }
-
-#if defined(PLATFORM_ANDROID)
-// Android: Get input events
-static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event)
-{
-    int type = AInputEvent_getType(event);
-
-    if (type == AINPUT_EVENT_TYPE_MOTION)
-    {
-        rawTouchPosition.x = AMotionEvent_getX(event, 0);
-        rawTouchPosition.y = AMotionEvent_getY(event, 0);
-    }
-    else if (type == AINPUT_EVENT_TYPE_KEY)
-    {
-        int32_t keycode = AKeyEvent_getKeyCode(event);
-        int32_t AKeyEvent_getMetaState(event);
-
-        // If we are in active mode, we eat the back button and move into pause mode.  
-        // If we are already in pause mode, we allow the back button to be handled by the OS, which means we'll be shut down.
-        if ((keycode == AKEYCODE_BACK)) // && mActiveMode)
-        {
-            //setActiveMode(false);
-            //return 1;
-        }
-    }
-    
-    int32_t action = AMotionEvent_getAction(event);
-    unsigned int flags = action & AMOTION_EVENT_ACTION_MASK;
-    
-    GestureEvent gestureEvent;
-    
-    // Action
-    if (flags == AMOTION_EVENT_ACTION_DOWN) gestureEvent.action = DOWN;
-    else if (flags == AMOTION_EVENT_ACTION_UP) gestureEvent.action = UP;
-    else if (flags == AMOTION_EVENT_ACTION_MOVE) gestureEvent.action = MOVE;
-    
-    // Points
-    gestureEvent.pointCount = AMotionEvent_getPointerCount(event);
-    
-    // Position
-    gestureEvent.position[0] = (Vector2){ AMotionEvent_getX(event, 0), AMotionEvent_getY(event, 0) };
-    gestureEvent.position[1] = (Vector2){ AMotionEvent_getX(event, 1), AMotionEvent_getY(event, 1) };
-    
-    ProcessMotionEvent(gestureEvent);
-
-    return 0;   // return 1;
-}
-#endif
-
-#if defined(PLATFORM_WEB)
-// Web: Get input events
-static EM_BOOL EmscriptenInputCallback(int eventType, const EmscriptenTouchEvent *touchEvent, void *userData)
-{
-    /*
-    for (int i = 0; i < touchEvent->numTouches; i++)
-    {
-        long x, y, id;
-
-        if (!touchEvent->touches[i].isChanged) continue;
-
-        id = touchEvent->touches[i].identifier;
-        x = touchEvent->touches[i].canvasX;
-        y = touchEvent->touches[i].canvasY;
-    }
-    
-    printf("%s, numTouches: %d %s%s%s%s\n", emscripten_event_type_to_string(eventType), event->numTouches,
-           event->ctrlKey ? " CTRL" : "", event->shiftKey ? " SHIFT" : "", event->altKey ? " ALT" : "", event->metaKey ? " META" : "");
-
-    for(int i = 0; i < event->numTouches; ++i)
-    {
-        const EmscriptenTouchPoint *t = &event->touches[i];
-        
-        printf("  %ld: screen: (%ld,%ld), client: (%ld,%ld), page: (%ld,%ld), isChanged: %d, onTarget: %d, canvas: (%ld, %ld)\n",
-          t->identifier, t->screenX, t->screenY, t->clientX, t->clientY, t->pageX, t->pageY, t->isChanged, t->onTarget, t->canvasX, t->canvasY);
-    }
-    */
-    GestureEvent gestureEvent;
-    
-    // Action
-    if (eventType == EMSCRIPTEN_EVENT_TOUCHSTART) gestureEvent.action = DOWN;
-    else if (eventType == EMSCRIPTEN_EVENT_TOUCHEND) gestureEvent.action = UP;
-    else if (eventType == EMSCRIPTEN_EVENT_TOUCHMOVE) gestureEvent.action = MOVE;
-    
-    // Points
-    gestureEvent.pointCount = touchEvent->numTouches;
-    
-    // Position
-    //gestureEvent.position[0] = (Vector2){ touchEvent->touches[0].canvasX, touchEvent->touches[0].canvasY };
-    //gestureEvent.position[1] = (Vector2){ touchEvent->touches[1].canvasX, touchEvent->touches[1].canvasY };
-    gestureEvent.position[0] = (Vector2){ touchEvent->touches[0].targetX, touchEvent->touches[0].targetY };
-    gestureEvent.position[1] = (Vector2){ touchEvent->touches[1].targetX, touchEvent->touches[1].targetY };
-    printf("EVENT DETECTED!\n");
-    
-    rawTouchPosition = gestureEvent.position[0];
-    
-    ProcessMotionEvent(gestureEvent);
-
-    return 1;
-}
-#endif

+ 12 - 9
src/gestures.h

@@ -67,6 +67,17 @@ typedef enum {
     GESTURE_PINCH_OUT   = 1024
     GESTURE_PINCH_OUT   = 1024
 } Gestures;
 } Gestures;
 
 
+typedef enum { TOUCH_UP, TOUCH_DOWN, TOUCH_MOVE } TouchAction;
+
+// Gesture events
+// NOTE: MAX_TOUCH_POINTS fixed to 4
+typedef struct {
+    int touchAction;
+    int pointCount;
+    int pointerId[4];
+    Vector2 position[4];
+} GestureEvent;
+
 #ifdef __cplusplus
 #ifdef __cplusplus
 extern "C" {            // Prevents name mangling of functions
 extern "C" {            // Prevents name mangling of functions
 #endif
 #endif
@@ -79,19 +90,11 @@ extern "C" {            // Prevents name mangling of functions
 //----------------------------------------------------------------------------------
 //----------------------------------------------------------------------------------
 // Module Functions Declaration
 // Module Functions Declaration
 //----------------------------------------------------------------------------------
 //----------------------------------------------------------------------------------
-int GetTouchX(void);                                    // Returns touch position X (relative to screen size)
-int GetTouchY(void);                                    // Returns touch position Y (relative to screen size)
-Vector2 GetTouchPosition(void);                         // Returns touch position XY (relative to screen size)
-
-#if defined(PLATFORM_WEB)
-void InitGesturesSystem(void);                          // Init gestures system (web)
-#elif defined(PLATFORM_ANDROID)
-void InitGesturesSystem(struct android_app *app);       // Init gestures system (android)
-#endif
 void UpdateGestures(void);                              // Update gestures detected (must be called every frame)
 void UpdateGestures(void);                              // Update gestures detected (must be called every frame)
 bool IsGestureDetected(void);                           // Check if a gesture have been detected
 bool IsGestureDetected(void);                           // Check if a gesture have been detected
 int GetGestureType(void);                               // Get latest detected gesture
 int GetGestureType(void);                               // Get latest detected gesture
 void SetGesturesEnabled(unsigned int gestureFlags);     // Enable a set of gestures using flags
 void SetGesturesEnabled(unsigned int gestureFlags);     // Enable a set of gestures using flags
+void ProcessGestureEvent(GestureEvent event);           // Process gesture event and translate it into gestures
 
 
 float GetGestureDragIntensity(void);                    // Get gesture drag intensity
 float GetGestureDragIntensity(void);                    // Get gesture drag intensity
 float GetGestureDragAngle(void);                        // Get gesture drag angle
 float GetGestureDragAngle(void);                        // Get gesture drag angle

+ 13 - 7
src/raylib.h

@@ -70,7 +70,7 @@
 #endif
 #endif
 
 
 #if defined(PLATFORM_ANDROID)
 #if defined(PLATFORM_ANDROID)
-    #include <android_native_app_glue.h>    // Defines android_app struct
+    typedef struct android_app;     // Define android_app struct (android_native_app_glue.h)
 #endif
 #endif
 
 
 //----------------------------------------------------------------------------------
 //----------------------------------------------------------------------------------
@@ -432,6 +432,17 @@ typedef enum {
     GESTURE_PINCH_OUT   = 1024
     GESTURE_PINCH_OUT   = 1024
 } Gestures;
 } Gestures;
 
 
+typedef enum { TOUCH_UP, TOUCH_DOWN, TOUCH_MOVE } TouchAction;
+
+// Gesture events
+// NOTE: MAX_TOUCH_POINTS fixed to 4
+typedef struct {
+    int touchAction;
+    int pointCount;
+    int pointerId[4];
+    Vector2 position[4];
+} GestureEvent;
+
 // Camera system modes
 // Camera system modes
 typedef enum { CAMERA_CUSTOM = 0, CAMERA_FREE, CAMERA_ORBITAL, CAMERA_FIRST_PERSON, CAMERA_THIRD_PERSON } CameraMode;
 typedef enum { CAMERA_CUSTOM = 0, CAMERA_FREE, CAMERA_ORBITAL, CAMERA_FIRST_PERSON, CAMERA_THIRD_PERSON } CameraMode;
 
 
@@ -571,16 +582,11 @@ Vector2 GetTouchPosition(void);                         // Returns touch positio
 //------------------------------------------------------------------------------------
 //------------------------------------------------------------------------------------
 // Gestures and Touch Handling Functions (Module: gestures)
 // Gestures and Touch Handling Functions (Module: gestures)
 //------------------------------------------------------------------------------------
 //------------------------------------------------------------------------------------
-Vector2 GetRawTouchPosition(void);                      // Get touch position (raw)
-#if defined(PLATFORM_WEB)
-void InitGesturesSystem(void);                          // Init gestures system (web)
-#elif defined(PLATFORM_ANDROID)
-void InitGesturesSystem(struct android_app *app);       // Init gestures system (android)
-#endif
 void UpdateGestures(void);                              // Update gestures detected (must be called every frame)
 void UpdateGestures(void);                              // Update gestures detected (must be called every frame)
 bool IsGestureDetected(void);                           // Check if a gesture have been detected
 bool IsGestureDetected(void);                           // Check if a gesture have been detected
 int GetGestureType(void);                               // Get latest detected gesture
 int GetGestureType(void);                               // Get latest detected gesture
 void SetGesturesEnabled(unsigned int gestureFlags);     // Enable a set of gestures using flags
 void SetGesturesEnabled(unsigned int gestureFlags);     // Enable a set of gestures using flags
+void ProcessGestureEvent(GestureEvent event);           // Process gesture event and translate it into gestures
 
 
 float GetGestureDragIntensity(void);                    // Get gesture drag intensity
 float GetGestureDragIntensity(void);                    // Get gesture drag intensity
 float GetGestureDragAngle(void);                        // Get gesture drag angle
 float GetGestureDragAngle(void);                        // Get gesture drag angle