Browse Source

Redesigned gestures module to header-only

raysan5 9 years ago
parent
commit
3b80e2c1e0
6 changed files with 458 additions and 494 deletions
  1. 1 5
      src/Makefile
  2. 9 7
      src/core.c
  3. 0 423
      src/gestures.c
  4. 446 34
      src/gestures.h
  5. 1 16
      src/raylib.h
  6. 1 9
      src/rlua.h

+ 1 - 5
src/Makefile

@@ -168,7 +168,7 @@ endif
 # compile all modules with their prerequisites
 # compile all modules with their prerequisites
 
 
 # compile core module
 # compile core module
-core.o : core.c raylib.h rlgl.h utils.h raymath.h
+core.o : core.c raylib.h rlgl.h utils.h raymath.h gestures.h
 	$(CC) -c $< $(CFLAGS) $(INCLUDES) -D$(PLATFORM)
 	$(CC) -c $< $(CFLAGS) $(INCLUDES) -D$(PLATFORM)
 
 
 # compile rlgl module
 # compile rlgl module
@@ -207,10 +207,6 @@ utils.o : utils.c utils.h
 camera.o : camera.c raylib.h
 camera.o : camera.c raylib.h
 	$(CC) -c $< $(CFLAGS) $(INCLUDES)
 	$(CC) -c $< $(CFLAGS) $(INCLUDES)
 
 
-#compile gestures module
-gestures.o : gestures.c raylib.h
-	$(CC) -c $< $(CFLAGS) $(INCLUDES)
-
 # It installs generated and needed files to compile projects using raylib.
 # It installs generated and needed files to compile projects using raylib.
 # The installation works manually.
 # The installation works manually.
 # TODO: add other platforms.
 # TODO: add other platforms.

+ 9 - 7
src/core.c

@@ -39,13 +39,15 @@
 
 
 #include "raylib.h"         // raylib main header
 #include "raylib.h"         // raylib main header
 #include "rlgl.h"           // raylib OpenGL abstraction layer to OpenGL 1.1, 3.3+ or ES2
 #include "rlgl.h"           // raylib OpenGL abstraction layer to OpenGL 1.1, 3.3+ or ES2
-#include "utils.h"          // TraceLog() function
-                            // NOTE: Includes Android fopen map, InitAssetManager()
-                            
+#include "utils.h"          // Includes Android fopen map, InitAssetManager(), TraceLog()
+
 #define RAYMATH_IMPLEMENTATION  // Use raymath as a header-only library (includes implementation)
 #define RAYMATH_IMPLEMENTATION  // Use raymath as a header-only library (includes implementation)
 #define RAYMATH_EXTERN_INLINE   // Compile raymath functions as static inline (remember, it's a compiler hint)
 #define RAYMATH_EXTERN_INLINE   // Compile raymath functions as static inline (remember, it's a compiler hint)
 #include "raymath.h"            // Required for Vector3 and Matrix functions
 #include "raymath.h"            // Required for Vector3 and Matrix functions
 
 
+#define GESTURES_IMPLEMENTATION
+#include "gestures.h"       // Gestures detection functionality
+
 #include <stdio.h>          // Standard input / output lib
 #include <stdio.h>          // Standard input / output lib
 #include <stdlib.h>         // Declares malloc() and free() for memory management, rand(), atexit()
 #include <stdlib.h>         // Declares malloc() and free() for memory management, rand(), atexit()
 #include <stdint.h>         // Required for typedef unsigned long long int uint64_t, used by hi-res timer
 #include <stdint.h>         // Required for typedef unsigned long long int uint64_t, used by hi-res timer
@@ -234,6 +236,9 @@ static bool showLogo = false;               // Track if showing logo at init is
 extern void LoadDefaultFont(void);          // [Module: text] Loads default font on InitWindow()
 extern void LoadDefaultFont(void);          // [Module: text] Loads default font on InitWindow()
 extern void UnloadDefaultFont(void);        // [Module: text] Unloads default font from GPU memory
 extern void UnloadDefaultFont(void);        // [Module: text] Unloads default font from GPU memory
 
 
+extern void ProcessGestureEvent(GestureEvent event);    // [Module: gestures] Process gesture event and translate it into gestures
+extern void UpdateGestures(void);                       // [Module: gestures] Update gestures detected (called in PollInputEvents())
+
 //----------------------------------------------------------------------------------
 //----------------------------------------------------------------------------------
 // Module specific Functions Declaration
 // Module specific Functions Declaration
 //----------------------------------------------------------------------------------
 //----------------------------------------------------------------------------------
@@ -2052,10 +2057,7 @@ static void KeyCallback(GLFWwindow *window, int key, int scancode, int action, i
         // NOTE: Before closing window, while loop must be left!
         // NOTE: Before closing window, while loop must be left!
     }
     }
 #if defined(PLATFORM_DESKTOP)
 #if defined(PLATFORM_DESKTOP)
-    else if (key == GLFW_KEY_F12 && action == GLFW_PRESS)
-    {
-        TakeScreenshot();
-    }
+    else if (key == GLFW_KEY_F12 && action == GLFW_PRESS) TakeScreenshot();
 #endif
 #endif
     else 
     else 
     {
     {

+ 0 - 423
src/gestures.c

@@ -1,423 +0,0 @@
-/**********************************************************************************************
-*
-*   raylib Gestures System - Gestures Processing based on input gesture events (touch/mouse)
-*
-*   Initial design by Marc Palau
-*   Redesigned by Albert Martos and Ian Eito
-*   Reviewed by Ramon Santamaria (@raysan5)
-*
-*   This software is provided "as-is", without any express or implied warranty. In no event
-*   will the authors be held liable for any damages arising from the use of this software.
-*
-*   Permission is granted to anyone to use this software for any purpose, including commercial
-*   applications, and to alter it and redistribute it freely, subject to the following restrictions:
-*
-*     1. The origin of this software must not be misrepresented; you must not claim that you
-*     wrote the original software. If you use this software in a product, an acknowledgment
-*     in the product documentation would be appreciated but is not required.
-*
-*     2. Altered source versions must be plainly marked as such, and must not be misrepresented
-*     as being the original software.
-*
-*     3. This notice may not be removed or altered from any source distribution.
-*
-**********************************************************************************************/
-
-//#define GESTURES_STANDALONE     // NOTE: To use the gestures module as standalone lib, just uncomment this line
-
-#if defined(GESTURES_STANDALONE)
-    #include "gestures.h"
-#else
-    #include "raylib.h"         // Required for: Vector2, Gestures
-#endif
-
-#include <math.h>               // Required for: atan2(), sqrt()
-#include <stdint.h>             // Required for: uint64_t
-
-#if defined(_WIN32)
-    // Functions required to query time on Windows
-    int __stdcall QueryPerformanceCounter(unsigned long long int *lpPerformanceCount);
-    int __stdcall QueryPerformanceFrequency(unsigned long long int *lpFrequency);
-#elif defined(__linux)
-    #include <sys/time.h>       // Required for: timespec
-    #include <time.h>           // Required for: clock_gettime()
-#endif
-
-//----------------------------------------------------------------------------------
-// Defines and Macros
-//----------------------------------------------------------------------------------
-#define FORCE_TO_SWIPE          0.0005f     // Measured in normalized screen units/time
-#define MINIMUM_DRAG            0.015f      // Measured in normalized screen units (0.0f to 1.0f)
-#define MINIMUM_PINCH           0.005f      // Measured in normalized screen units (0.0f to 1.0f)
-#define TAP_TIMEOUT             300         // Time in milliseconds
-#define PINCH_TIMEOUT           300         // Time in milliseconds
-#define DOUBLETAP_RANGE         0.03f       // Measured in normalized screen units (0.0f to 1.0f)
-
-//----------------------------------------------------------------------------------
-// Types and Structures Definition
-//----------------------------------------------------------------------------------
-// ...
-
-//----------------------------------------------------------------------------------
-// Global Variables Definition
-//----------------------------------------------------------------------------------
-
-// Touch gesture variables
-static Vector2 touchDownPosition = { 0.0f, 0.0f };
-static Vector2 touchDownPosition2 = { 0.0f, 0.0f };
-static Vector2 touchDownDragPosition = { 0.0f, 0.0f };
-static Vector2 touchUpPosition = { 0.0f, 0.0f };
-static Vector2 moveDownPosition = { 0.0f, 0.0f };
-static Vector2 moveDownPosition2 = { 0.0f, 0.0f };
-static int numTap = 0;
-
-static int pointCount = 0;
-static int firstTouchId = -1;
-
-static double eventTime = 0.0;
-static double swipeTime = 0.0;
-
-// Hold gesture variables
-static int numHold = 0;
-static float timeHold = 0.0f;
-
-// Drag gesture variables
-static Vector2 dragVector = { 0.0f , 0.0f };    // DRAG vector (between initial and current position)
-static float dragAngle = 0.0f;                  // DRAG angle (relative to x-axis)
-static float dragDistance = 0.0f;               // DRAG distance (from initial touch point to final) (normalized [0..1])
-static float dragIntensity = 0.0f;              // DRAG intensity, how far why did the DRAG (pixels per frame)
-static bool startMoving = false;                // SWIPE used to define when start measuring swipeTime
-
-// Pinch gesture variables
-static Vector2 pinchVector = { 0.0f , 0.0f };   // PINCH vector (between first and second touch points)
-static float pinchAngle = 0.0f;                 // PINCH angle (relative to x-axis)
-static float pinchDistance = 0.0f;              // PINCH displacement distance (normalized [0..1])
-
-// Detected gestures
-static int previousGesture = GESTURE_NONE;
-static int currentGesture = GESTURE_NONE;
-
-// Enabled gestures flags, all gestures enabled by default 
-static unsigned int enabledGestures = 0b0000001111111111;   
-
-//----------------------------------------------------------------------------------
-// Module specific Functions Declaration
-//----------------------------------------------------------------------------------
-static float Vector2Angle(Vector2 initialPosition, Vector2 finalPosition);
-static float Vector2Distance(Vector2 v1, Vector2 v2);
-static double GetCurrentTime(void);
-
-//----------------------------------------------------------------------------------
-// Module Functions Definition
-//----------------------------------------------------------------------------------
-
-// Enable only desired getures to be detected
-void SetGesturesEnabled(unsigned int gestureFlags)
-{
-    enabledGestures = gestureFlags;
-}
-
-// Check if a gesture have been detected
-bool IsGestureDetected(int gesture)
-{
-    if ((enabledGestures & currentGesture) == gesture) return true;
-    else return false;
-}
-
-// Process gesture event and translate it into gestures
-void ProcessGestureEvent(GestureEvent event)
-{
-    // Reset required variables
-    previousGesture = currentGesture;
-    
-    pointCount = event.pointCount;      // Required on UpdateGestures()
-    
-    if (pointCount < 2)
-    {
-        if (event.touchAction == TOUCH_DOWN)
-        {
-            numTap++;    // Tap counter
-            
-            // Detect GESTURE_DOUBLE_TAP
-            if ((currentGesture == GESTURE_NONE) && (numTap >= 2) && ((GetCurrentTime() - eventTime) < TAP_TIMEOUT) && (Vector2Distance(touchDownPosition, event.position[0]) < DOUBLETAP_RANGE))
-            {
-                currentGesture = GESTURE_DOUBLETAP;
-                numTap = 0;
-            }
-            else    // Detect GESTURE_TAP
-            {
-                numTap = 1;
-                currentGesture = GESTURE_TAP;
-            }
-            
-            touchDownPosition = event.position[0];
-            touchDownDragPosition = event.position[0];
-            
-            touchUpPosition = touchDownPosition;
-            eventTime = GetCurrentTime();
-            
-            firstTouchId = event.pointerId[0];
-            
-            dragVector = (Vector2){ 0.0f, 0.0f };
-        }
-        else if (event.touchAction == TOUCH_UP)
-        {
-            if (currentGesture == GESTURE_DRAG) touchUpPosition = event.position[0];
-
-            // NOTE: dragIntensity dependend on the resolution of the screen
-            dragDistance = Vector2Distance(touchDownPosition, touchUpPosition);
-            dragIntensity = dragDistance/(float)((GetCurrentTime() - swipeTime));
-            
-            startMoving = false;
-            
-            // Detect GESTURE_SWIPE
-            if ((dragIntensity > FORCE_TO_SWIPE) && firstTouchId == event.pointerId[0])
-            {
-                // NOTE: Angle should be inverted in Y
-                dragAngle = 360.0f - Vector2Angle(touchDownPosition, touchUpPosition);
-                
-                if ((dragAngle < 30) || (dragAngle > 330)) currentGesture = GESTURE_SWIPE_RIGHT;        // Right
-                else if ((dragAngle > 30) && (dragAngle < 120)) currentGesture = GESTURE_SWIPE_UP;      // Up
-                else if ((dragAngle > 120) && (dragAngle < 210)) currentGesture = GESTURE_SWIPE_LEFT;   // Left
-                else if ((dragAngle > 210) && (dragAngle < 300)) currentGesture = GESTURE_SWIPE_DOWN;   // Down
-                else currentGesture = GESTURE_NONE;
-            }
-            else
-            {
-                dragDistance = 0.0f;
-                dragIntensity = 0.0f;
-                dragAngle = 0.0f;
-                
-                currentGesture = GESTURE_NONE;
-            }
-            
-            touchDownDragPosition = (Vector2){ 0.0f, 0.0f };
-            pointCount = 0;
-        }
-        else if (event.touchAction == TOUCH_MOVE)
-        {
-            if (currentGesture == GESTURE_DRAG) eventTime = GetCurrentTime();
-            
-            if (!startMoving)
-            {
-                swipeTime = GetCurrentTime();
-                startMoving = true;
-            }
-            
-            moveDownPosition = event.position[0];
-            
-            if (currentGesture == GESTURE_HOLD)
-            {
-                if (numHold == 1) touchDownPosition = event.position[0];
-                
-                numHold = 2;
-                
-                // Detect GESTURE_DRAG
-                if (Vector2Distance(touchDownPosition, moveDownPosition) >= MINIMUM_DRAG)
-                {
-                    eventTime = GetCurrentTime();
-                    currentGesture = GESTURE_DRAG;
-                }
-            }
-        
-            dragVector.x = moveDownPosition.x - touchDownDragPosition.x;
-            dragVector.y = moveDownPosition.y - touchDownDragPosition.y;
-        }
-    }
-    else    // Two touch points
-    {
-        if (event.touchAction == TOUCH_DOWN)
-        {
-            touchDownPosition = event.position[0];
-            touchDownPosition2 = event.position[1];
-            
-            //pinchDistance = Vector2Distance(touchDownPosition, touchDownPosition2);
-            
-            pinchVector.x = touchDownPosition2.x - touchDownPosition.x;
-            pinchVector.y = touchDownPosition2.y - touchDownPosition.y;
-            
-            currentGesture = GESTURE_HOLD;
-            timeHold = GetCurrentTime();
-        }
-        else if (event.touchAction == TOUCH_MOVE)
-        {
-            pinchDistance = Vector2Distance(moveDownPosition, moveDownPosition2);
-            
-            touchDownPosition = moveDownPosition;
-            touchDownPosition2 = moveDownPosition2;
-            
-            moveDownPosition = event.position[0];
-            moveDownPosition2 = event.position[1];
-            
-            pinchVector.x = moveDownPosition2.x - moveDownPosition.x;
-            pinchVector.y = moveDownPosition2.y - moveDownPosition.y;
-                        
-            if ((Vector2Distance(touchDownPosition, moveDownPosition) >= MINIMUM_PINCH) || (Vector2Distance(touchDownPosition2, moveDownPosition2) >= MINIMUM_PINCH))
-            {
-                if ((Vector2Distance(moveDownPosition, moveDownPosition2) - pinchDistance) < 0) currentGesture = GESTURE_PINCH_IN;
-                else currentGesture = GESTURE_PINCH_OUT;
-            }
-            else
-            {
-                currentGesture = GESTURE_HOLD;
-                timeHold = GetCurrentTime();
-            }
-            
-            // NOTE: Angle should be inverted in Y
-            pinchAngle = 360.0f - Vector2Angle(moveDownPosition, moveDownPosition2);
-        }
-        else if (event.touchAction == TOUCH_UP)
-        {
-            pinchDistance = 0.0f;
-            pinchAngle = 0.0f;
-            pinchVector = (Vector2){ 0.0f, 0.0f };
-            pointCount = 0;
-            
-            currentGesture = GESTURE_NONE;
-        }
-    }
-}
-
-// Update gestures detected (must be called every frame)
-void UpdateGestures(void)
-{
-    // NOTE: Gestures are processed through system callbacks on touch events
-
-    // Detect GESTURE_HOLD
-    if (((currentGesture == GESTURE_TAP) || (currentGesture == GESTURE_DOUBLETAP)) && (pointCount < 2))
-    {
-        currentGesture = GESTURE_HOLD;
-        timeHold = GetCurrentTime();
-    }
-    
-    if (((GetCurrentTime() - eventTime) > TAP_TIMEOUT) && (currentGesture == GESTURE_DRAG) && (pointCount < 2))
-    {
-        currentGesture = GESTURE_HOLD;
-        timeHold = GetCurrentTime();
-        numHold = 1;
-    }
-   
-    // Detect GESTURE_NONE
-    if ((currentGesture == GESTURE_SWIPE_RIGHT) || (currentGesture == GESTURE_SWIPE_UP) || (currentGesture == GESTURE_SWIPE_LEFT) || (currentGesture == GESTURE_SWIPE_DOWN))
-    {
-        currentGesture = GESTURE_NONE;
-    }
-}
-
-// Get number of touch points
-int GetTouchPointsCount(void)
-{
-    // NOTE: point count is calculated when ProcessGestureEvent(GestureEvent event) is called
-    
-    return pointCount;
-}
-
-// Get latest detected gesture
-int GetGestureDetected(void)
-{
-    // Get current gesture only if enabled
-    return (enabledGestures & currentGesture);
-}
-
-// Hold time measured in ms
-float GetGestureHoldDuration(void)
-{
-    // NOTE: time is calculated on current gesture HOLD
-    
-    float time = 0.0f;
-    
-    if (currentGesture == GESTURE_HOLD) time = (float)GetCurrentTime() - timeHold;
-    
-    return time;
-}
-
-// Get drag vector (between initial touch point to current)
-Vector2 GetGestureDragVector(void)
-{
-    // NOTE: drag vector is calculated on one touch points TOUCH_MOVE
-    
-    return dragVector;
-}
-
-// Get drag angle
-// NOTE: Angle in degrees, horizontal-right is 0, counterclock-wise
-float GetGestureDragAngle(void)
-{
-    // NOTE: drag angle is calculated on one touch points TOUCH_UP
-    
-    return dragAngle;
-}
-
-// Get distance between two pinch points
-Vector2 GetGesturePinchVector(void)
-{
-    // NOTE: The position values used for pinchDistance are not modified like the position values of [core.c]-->GetTouchPosition(int index)
-    // NOTE: pinch distance is calculated on two touch points TOUCH_MOVE
-    
-    return pinchVector;
-}
-
-// Get angle beween two pinch points
-// NOTE: Angle in degrees, horizontal-right is 0, counterclock-wise
-float GetGesturePinchAngle(void)
-{
-    // NOTE: pinch angle is calculated on two touch points TOUCH_MOVE
-    
-    return pinchAngle;
-}
-
-//----------------------------------------------------------------------------------
-// Module specific Functions Definition
-//----------------------------------------------------------------------------------
-
-// Returns angle from two-points vector with X-axis
-static float Vector2Angle(Vector2 initialPosition, Vector2 finalPosition)
-{
-    float angle;
-
-    angle = atan2(finalPosition.y - initialPosition.y, finalPosition.x - initialPosition.x);
-    angle *= RAD2DEG;
-    
-    if (angle < 0) angle += 360.0f;
-
-    return angle;
-}
-
-// Calculate distance between two Vector2
-static float Vector2Distance(Vector2 v1, Vector2 v2)
-{
-    float result;
-
-    float dx = v2.x - v1.x;
-    float dy = v2.y - v1.y;
-
-    result = sqrt(dx*dx + dy*dy);
-
-    return result;
-}
-
-// Time measure returned are milliseconds
-static double GetCurrentTime(void)
-{
-    double time = 0;
-    
-#if defined(_WIN32)
-    unsigned long long int clockFrequency, currentTime;
-    
-    QueryPerformanceFrequency(&clockFrequency);
-    QueryPerformanceCounter(&currentTime);
-    
-    time = (double)currentTime/clockFrequency*1000.0f;  // Time in miliseconds
-#endif
-
-#if defined(__linux)
-    // NOTE: Only for Linux-based systems
-    struct timespec now;
-    clock_gettime(CLOCK_MONOTONIC, &now);
-    uint64_t nowTime = (uint64_t)now.tv_sec*1000000000LLU + (uint64_t)now.tv_nsec;     // Time in nanoseconds
-    
-    time = ((double)nowTime/1000000.0);     // Time in miliseconds
-#endif
-
-    return time;
-}

+ 446 - 34
src/gestures.h

@@ -1,8 +1,21 @@
 /**********************************************************************************************
 /**********************************************************************************************
 *
 *
-*   raylib Gestures System - Gestures Detection and Usage Functions (Android and HTML5)
+*   raylib Gestures System - Gestures Processing based on input gesture events (touch/mouse)
 *
 *
-*   Copyright (c) 2015 Marc Palau and Ramon Santamaria
+*   #define GESTURES_IMPLEMENTATION
+*       Generates the implementation of the library into the included file.
+*       If not defined, the library is in header only mode and can be included in other headers 
+*       or source files without problems. But only ONE file should hold the implementation.
+*
+*   #define GESTURES_STANDALONE
+*       If defined, the library can be used as standalone to process gesture events with
+*       no external dependencies.
+*
+*   NOTE: Memory footprint of this library is aproximately 128 bytes
+*
+*   Initial design by Marc Palau
+*   Redesigned by Albert Martos and Ian Eito
+*   Reviewed by Ramon Santamaria (@raysan5)
 *
 *
 *   This software is provided "as-is", without any express or implied warranty. In no event
 *   This software is provided "as-is", without any express or implied warranty. In no event
 *   will the authors be held liable for any damages arising from the use of this software.
 *   will the authors be held liable for any damages arising from the use of this software.
@@ -28,9 +41,6 @@
     #define PI 3.14159265358979323846
     #define PI 3.14159265358979323846
 #endif
 #endif
 
 
-#define DEG2RAD (PI / 180.0f)
-#define RAD2DEG (180.0f / PI)
-
 //----------------------------------------------------------------------------------
 //----------------------------------------------------------------------------------
 // Defines and Macros
 // Defines and Macros
 //----------------------------------------------------------------------------------
 //----------------------------------------------------------------------------------
@@ -40,32 +50,34 @@
 // Types and Structures Definition
 // Types and Structures Definition
 // NOTE: Below types are required for GESTURES_STANDALONE usage
 // NOTE: Below types are required for GESTURES_STANDALONE usage
 //----------------------------------------------------------------------------------
 //----------------------------------------------------------------------------------
-#ifndef __cplusplus
-    // Boolean type
-    typedef enum { false, true } bool;
-#endif
+#if defined(GESTURES_STANDALONE)
+    #ifndef __cplusplus
+        // Boolean type
+        typedef enum { false, true } bool;
+    #endif
+
+    // Vector2 type
+    typedef struct Vector2 {
+        float x;
+        float y;
+    } Vector2;
 
 
-// Vector2 type
-typedef struct Vector2 {
-    float x;
-    float y;
-} Vector2;
-
-// Gestures type
-// NOTE: It could be used as flags to enable only some gestures
-typedef enum {
-    GESTURE_NONE        = 1,
-    GESTURE_TAP         = 2,
-    GESTURE_DOUBLETAP   = 4,
-    GESTURE_HOLD        = 8,
-    GESTURE_DRAG        = 16,
-    GESTURE_SWIPE_RIGHT = 32,
-    GESTURE_SWIPE_LEFT  = 64,
-    GESTURE_SWIPE_UP    = 128,
-    GESTURE_SWIPE_DOWN  = 256,
-    GESTURE_PINCH_IN    = 512,
-    GESTURE_PINCH_OUT   = 1024
-} Gestures;
+    // Gestures type
+    // NOTE: It could be used as flags to enable only some gestures
+    typedef enum {
+        GESTURE_NONE        = 1,
+        GESTURE_TAP         = 2,
+        GESTURE_DOUBLETAP   = 4,
+        GESTURE_HOLD        = 8,
+        GESTURE_DRAG        = 16,
+        GESTURE_SWIPE_RIGHT = 32,
+        GESTURE_SWIPE_LEFT  = 64,
+        GESTURE_SWIPE_UP    = 128,
+        GESTURE_SWIPE_DOWN  = 256,
+        GESTURE_PINCH_IN    = 512,
+        GESTURE_PINCH_OUT   = 1024
+    } Gestures;
+#endif
 
 
 typedef enum { TOUCH_UP, TOUCH_DOWN, TOUCH_MOVE } TouchAction;
 typedef enum { TOUCH_UP, TOUCH_DOWN, TOUCH_MOVE } TouchAction;
 
 
@@ -90,22 +102,422 @@ extern "C" {            // Prevents name mangling of functions
 //----------------------------------------------------------------------------------
 //----------------------------------------------------------------------------------
 // Module Functions Declaration
 // Module Functions Declaration
 //----------------------------------------------------------------------------------
 //----------------------------------------------------------------------------------
-void SetGesturesEnabled(unsigned int gestureFlags);     // Enable a set of gestures using flags
-bool IsGestureDetected(int gesture);                    // Check if a gesture have been detected
 void ProcessGestureEvent(GestureEvent event);           // Process gesture event and translate it into gestures
 void ProcessGestureEvent(GestureEvent event);           // Process gesture event and translate it into gestures
 void UpdateGestures(void);                              // Update gestures detected (must be called every frame)
 void UpdateGestures(void);                              // Update gestures detected (must be called every frame)
 
 
-int GetTouchPointsCount(void);                          // Get touch points count
+#if defined(GESTURES_STANDALONE)
+void SetGesturesEnabled(unsigned int gestureFlags);     // Enable a set of gestures using flags
+bool IsGestureDetected(int gesture);                    // Check if a gesture have been detected
 int GetGestureDetected(void);                           // Get latest detected gesture
 int GetGestureDetected(void);                           // Get latest detected gesture
+int GetTouchPointsCount(void);                          // Get touch points count
 float GetGestureHoldDuration(void);                     // Get gesture hold time in milliseconds
 float GetGestureHoldDuration(void);                     // Get gesture hold time in milliseconds
 Vector2 GetGestureDragVector(void);                     // Get gesture drag vector
 Vector2 GetGestureDragVector(void);                     // Get gesture drag vector
 float GetGestureDragAngle(void);                        // Get gesture drag angle
 float GetGestureDragAngle(void);                        // Get gesture drag angle
 Vector2 GetGesturePinchVector(void);                    // Get gesture pinch delta
 Vector2 GetGesturePinchVector(void);                    // Get gesture pinch delta
 float GetGesturePinchAngle(void);                       // Get gesture pinch angle
 float GetGesturePinchAngle(void);                       // Get gesture pinch angle
-
+#endif
 
 
 #ifdef __cplusplus
 #ifdef __cplusplus
 }
 }
 #endif
 #endif
 
 
 #endif // GESTURES_H
 #endif // GESTURES_H
+
+/***********************************************************************************
+*
+*   GESTURES IMPLEMENTATION
+*
+************************************************************************************/
+
+#if defined(GESTURES_IMPLEMENTATION)
+
+#include <math.h>               // Required for: atan2(), sqrt()
+#include <stdint.h>             // Required for: uint64_t
+
+#if defined(_WIN32)
+    // Functions required to query time on Windows
+    int __stdcall QueryPerformanceCounter(unsigned long long int *lpPerformanceCount);
+    int __stdcall QueryPerformanceFrequency(unsigned long long int *lpFrequency);
+#elif defined(__linux)
+    #include <sys/time.h>       // Required for: timespec
+    #include <time.h>           // Required for: clock_gettime()
+#endif
+
+//----------------------------------------------------------------------------------
+// Defines and Macros
+//----------------------------------------------------------------------------------
+#define FORCE_TO_SWIPE          0.0005f     // Measured in normalized screen units/time
+#define MINIMUM_DRAG            0.015f      // Measured in normalized screen units (0.0f to 1.0f)
+#define MINIMUM_PINCH           0.005f      // Measured in normalized screen units (0.0f to 1.0f)
+#define TAP_TIMEOUT             300         // Time in milliseconds
+#define PINCH_TIMEOUT           300         // Time in milliseconds
+#define DOUBLETAP_RANGE         0.03f       // Measured in normalized screen units (0.0f to 1.0f)
+
+//----------------------------------------------------------------------------------
+// Types and Structures Definition
+//----------------------------------------------------------------------------------
+// ...
+
+//----------------------------------------------------------------------------------
+// Global Variables Definition
+//----------------------------------------------------------------------------------
+
+// Touch gesture variables
+static Vector2 touchDownPosition = { 0.0f, 0.0f };
+static Vector2 touchDownPosition2 = { 0.0f, 0.0f };
+static Vector2 touchDownDragPosition = { 0.0f, 0.0f };
+static Vector2 touchUpPosition = { 0.0f, 0.0f };
+static Vector2 moveDownPosition = { 0.0f, 0.0f };
+static Vector2 moveDownPosition2 = { 0.0f, 0.0f };
+
+static int pointCount = 0;                      // Touch points counter
+static int firstTouchId = -1;                   // Touch id for first touch point
+static double eventTime = 0.0;                  // Time stamp when an event happened
+
+// Tap gesture variables
+static int tapCounter = 0;                      // TAP counter (one tap implies TOUCH_DOWN and TOUCH_UP actions)
+
+// Hold gesture variables
+static bool resetHold = false;                  // HOLD reset to get first touch point again
+static float timeHold = 0.0f;                   // HOLD duration in milliseconds
+
+// Drag gesture variables
+static Vector2 dragVector = { 0.0f , 0.0f };    // DRAG vector (between initial and current position)
+static float dragAngle = 0.0f;                  // DRAG angle (relative to x-axis)
+static float dragDistance = 0.0f;               // DRAG distance (from initial touch point to final) (normalized [0..1])
+static float dragIntensity = 0.0f;              // DRAG intensity, how far why did the DRAG (pixels per frame)
+
+// Swipe gestures variables
+static bool startMoving = false;                // SWIPE used to define when start measuring swipeTime
+static double swipeTime = 0.0;                  // SWIPE time to calculate drag intensity
+
+// Pinch gesture variables
+static Vector2 pinchVector = { 0.0f , 0.0f };   // PINCH vector (between first and second touch points)
+static float pinchAngle = 0.0f;                 // PINCH angle (relative to x-axis)
+static float pinchDistance = 0.0f;              // PINCH displacement distance (normalized [0..1])
+
+static int currentGesture = GESTURE_NONE;       // Current detected gesture
+
+// Enabled gestures flags, all gestures enabled by default 
+static unsigned int enabledGestures = 0b0000001111111111;   
+
+//----------------------------------------------------------------------------------
+// Module specific Functions Declaration
+//----------------------------------------------------------------------------------
+static float Vector2Angle(Vector2 initialPosition, Vector2 finalPosition);
+static float Vector2Distance(Vector2 v1, Vector2 v2);
+static double GetCurrentTime(void);
+
+//----------------------------------------------------------------------------------
+// Module Functions Definition
+//----------------------------------------------------------------------------------
+
+// Enable only desired getures to be detected
+void SetGesturesEnabled(unsigned int gestureFlags)
+{
+    enabledGestures = gestureFlags;
+}
+
+// Check if a gesture have been detected
+bool IsGestureDetected(int gesture)
+{
+    if ((enabledGestures & currentGesture) == gesture) return true;
+    else return false;
+}
+
+// Process gesture event and translate it into gestures
+void ProcessGestureEvent(GestureEvent event)
+{
+    // Reset required variables
+    pointCount = event.pointCount;      // Required on UpdateGestures()
+    
+    if (pointCount < 2)
+    {
+        if (event.touchAction == TOUCH_DOWN)
+        {
+            tapCounter++;    // Tap counter
+            
+            // Detect GESTURE_DOUBLE_TAP
+            if ((currentGesture == GESTURE_NONE) && (tapCounter >= 2) && ((GetCurrentTime() - eventTime) < TAP_TIMEOUT) && (Vector2Distance(touchDownPosition, event.position[0]) < DOUBLETAP_RANGE))
+            {
+                currentGesture = GESTURE_DOUBLETAP;
+                tapCounter = 0;
+            }
+            else    // Detect GESTURE_TAP
+            {
+                tapCounter = 1;
+                currentGesture = GESTURE_TAP;
+            }
+            
+            touchDownPosition = event.position[0];
+            touchDownDragPosition = event.position[0];
+            
+            touchUpPosition = touchDownPosition;
+            eventTime = GetCurrentTime();
+            
+            firstTouchId = event.pointerId[0];
+            
+            dragVector = (Vector2){ 0.0f, 0.0f };
+        }
+        else if (event.touchAction == TOUCH_UP)
+        {
+            if (currentGesture == GESTURE_DRAG) touchUpPosition = event.position[0];
+
+            // NOTE: dragIntensity dependend on the resolution of the screen
+            dragDistance = Vector2Distance(touchDownPosition, touchUpPosition);
+            dragIntensity = dragDistance/(float)((GetCurrentTime() - swipeTime));
+            
+            startMoving = false;
+            
+            // Detect GESTURE_SWIPE
+            if ((dragIntensity > FORCE_TO_SWIPE) && (firstTouchId == event.pointerId[0]))
+            {
+                // NOTE: Angle should be inverted in Y
+                dragAngle = 360.0f - Vector2Angle(touchDownPosition, touchUpPosition);
+                
+                if ((dragAngle < 30) || (dragAngle > 330)) currentGesture = GESTURE_SWIPE_RIGHT;        // Right
+                else if ((dragAngle > 30) && (dragAngle < 120)) currentGesture = GESTURE_SWIPE_UP;      // Up
+                else if ((dragAngle > 120) && (dragAngle < 210)) currentGesture = GESTURE_SWIPE_LEFT;   // Left
+                else if ((dragAngle > 210) && (dragAngle < 300)) currentGesture = GESTURE_SWIPE_DOWN;   // Down
+                else currentGesture = GESTURE_NONE;
+            }
+            else
+            {
+                dragDistance = 0.0f;
+                dragIntensity = 0.0f;
+                dragAngle = 0.0f;
+                
+                currentGesture = GESTURE_NONE;
+            }
+            
+            touchDownDragPosition = (Vector2){ 0.0f, 0.0f };
+            pointCount = 0;
+        }
+        else if (event.touchAction == TOUCH_MOVE)
+        {
+            if (currentGesture == GESTURE_DRAG) eventTime = GetCurrentTime();
+            
+            if (!startMoving)
+            {
+                swipeTime = GetCurrentTime();
+                startMoving = true;
+            }
+            
+            moveDownPosition = event.position[0];
+            
+            if (currentGesture == GESTURE_HOLD)
+            {
+                if (resetHold) touchDownPosition = event.position[0];
+                
+                resetHold = false;
+                
+                // Detect GESTURE_DRAG
+                if (Vector2Distance(touchDownPosition, moveDownPosition) >= MINIMUM_DRAG)
+                {
+                    eventTime = GetCurrentTime();
+                    currentGesture = GESTURE_DRAG;
+                }
+            }
+        
+            dragVector.x = moveDownPosition.x - touchDownDragPosition.x;
+            dragVector.y = moveDownPosition.y - touchDownDragPosition.y;
+        }
+    }
+    else    // Two touch points
+    {
+        if (event.touchAction == TOUCH_DOWN)
+        {
+            touchDownPosition = event.position[0];
+            touchDownPosition2 = event.position[1];
+            
+            //pinchDistance = Vector2Distance(touchDownPosition, touchDownPosition2);
+            
+            pinchVector.x = touchDownPosition2.x - touchDownPosition.x;
+            pinchVector.y = touchDownPosition2.y - touchDownPosition.y;
+            
+            currentGesture = GESTURE_HOLD;
+            timeHold = GetCurrentTime();
+        }
+        else if (event.touchAction == TOUCH_MOVE)
+        {
+            pinchDistance = Vector2Distance(moveDownPosition, moveDownPosition2);
+            
+            touchDownPosition = moveDownPosition;
+            touchDownPosition2 = moveDownPosition2;
+            
+            moveDownPosition = event.position[0];
+            moveDownPosition2 = event.position[1];
+            
+            pinchVector.x = moveDownPosition2.x - moveDownPosition.x;
+            pinchVector.y = moveDownPosition2.y - moveDownPosition.y;
+                        
+            if ((Vector2Distance(touchDownPosition, moveDownPosition) >= MINIMUM_PINCH) || (Vector2Distance(touchDownPosition2, moveDownPosition2) >= MINIMUM_PINCH))
+            {
+                if ((Vector2Distance(moveDownPosition, moveDownPosition2) - pinchDistance) < 0) currentGesture = GESTURE_PINCH_IN;
+                else currentGesture = GESTURE_PINCH_OUT;
+            }
+            else
+            {
+                currentGesture = GESTURE_HOLD;
+                timeHold = GetCurrentTime();
+            }
+            
+            // NOTE: Angle should be inverted in Y
+            pinchAngle = 360.0f - Vector2Angle(moveDownPosition, moveDownPosition2);
+        }
+        else if (event.touchAction == TOUCH_UP)
+        {
+            pinchDistance = 0.0f;
+            pinchAngle = 0.0f;
+            pinchVector = (Vector2){ 0.0f, 0.0f };
+            pointCount = 0;
+            
+            currentGesture = GESTURE_NONE;
+        }
+    }
+}
+
+// Update gestures detected (must be called every frame)
+void UpdateGestures(void)
+{
+    // NOTE: Gestures are processed through system callbacks on touch events
+
+    // Detect GESTURE_HOLD
+    if (((currentGesture == GESTURE_TAP) || (currentGesture == GESTURE_DOUBLETAP)) && (pointCount < 2))
+    {
+        currentGesture = GESTURE_HOLD;
+        timeHold = GetCurrentTime();
+    }
+    
+    if (((GetCurrentTime() - eventTime) > TAP_TIMEOUT) && (currentGesture == GESTURE_DRAG) && (pointCount < 2))
+    {
+        currentGesture = GESTURE_HOLD;
+        timeHold = GetCurrentTime();
+        resetHold = true;
+    }
+   
+    // Detect GESTURE_NONE
+    if ((currentGesture == GESTURE_SWIPE_RIGHT) || (currentGesture == GESTURE_SWIPE_UP) || (currentGesture == GESTURE_SWIPE_LEFT) || (currentGesture == GESTURE_SWIPE_DOWN))
+    {
+        currentGesture = GESTURE_NONE;
+    }
+}
+
+// Get number of touch points
+int GetTouchPointsCount(void)
+{
+    // NOTE: point count is calculated when ProcessGestureEvent(GestureEvent event) is called
+    
+    return pointCount;
+}
+
+// Get latest detected gesture
+int GetGestureDetected(void)
+{
+    // Get current gesture only if enabled
+    return (enabledGestures & currentGesture);
+}
+
+// Hold time measured in ms
+float GetGestureHoldDuration(void)
+{
+    // NOTE: time is calculated on current gesture HOLD
+    
+    float time = 0.0f;
+    
+    if (currentGesture == GESTURE_HOLD) time = (float)GetCurrentTime() - timeHold;
+    
+    return time;
+}
+
+// Get drag vector (between initial touch point to current)
+Vector2 GetGestureDragVector(void)
+{
+    // NOTE: drag vector is calculated on one touch points TOUCH_MOVE
+    
+    return dragVector;
+}
+
+// Get drag angle
+// NOTE: Angle in degrees, horizontal-right is 0, counterclock-wise
+float GetGestureDragAngle(void)
+{
+    // NOTE: drag angle is calculated on one touch points TOUCH_UP
+    
+    return dragAngle;
+}
+
+// Get distance between two pinch points
+Vector2 GetGesturePinchVector(void)
+{
+    // NOTE: The position values used for pinchDistance are not modified like the position values of [core.c]-->GetTouchPosition(int index)
+    // NOTE: pinch distance is calculated on two touch points TOUCH_MOVE
+    
+    return pinchVector;
+}
+
+// Get angle beween two pinch points
+// NOTE: Angle in degrees, horizontal-right is 0, counterclock-wise
+float GetGesturePinchAngle(void)
+{
+    // NOTE: pinch angle is calculated on two touch points TOUCH_MOVE
+    
+    return pinchAngle;
+}
+
+//----------------------------------------------------------------------------------
+// Module specific Functions Definition
+//----------------------------------------------------------------------------------
+
+// Returns angle from two-points vector with X-axis
+static float Vector2Angle(Vector2 initialPosition, Vector2 finalPosition)
+{
+    float angle;
+
+    angle = atan2(finalPosition.y - initialPosition.y, finalPosition.x - initialPosition.x)*(180.0f/PI);
+    
+    if (angle < 0) angle += 360.0f;
+
+    return angle;
+}
+
+// Calculate distance between two Vector2
+static float Vector2Distance(Vector2 v1, Vector2 v2)
+{
+    float result;
+
+    float dx = v2.x - v1.x;
+    float dy = v2.y - v1.y;
+
+    result = sqrt(dx*dx + dy*dy);
+
+    return result;
+}
+
+// Time measure returned are milliseconds
+static double GetCurrentTime(void)
+{
+    double time = 0;
+    
+#if defined(_WIN32)
+    unsigned long long int clockFrequency, currentTime;
+    
+    QueryPerformanceFrequency(&clockFrequency);
+    QueryPerformanceCounter(&currentTime);
+    
+    time = (double)currentTime/clockFrequency*1000.0f;  // Time in miliseconds
+#endif
+
+#if defined(__linux)
+    // NOTE: Only for Linux-based systems
+    struct timespec now;
+    clock_gettime(CLOCK_MONOTONIC, &now);
+    uint64_t nowTime = (uint64_t)now.tv_sec*1000000000LLU + (uint64_t)now.tv_nsec;     // Time in nanoseconds
+    
+    time = ((double)nowTime/1000000.0);     // Time in miliseconds
+#endif
+
+    return time;
+}
+
+#endif // GESTURES_IMPLEMENTATION

+ 1 - 16
src/raylib.h

@@ -570,18 +570,6 @@ typedef enum {
     GESTURE_PINCH_OUT   = 512
     GESTURE_PINCH_OUT   = 512
 } Gestures;
 } Gestures;
 
 
-// Touch action (fingers or mouse)
-typedef enum { TOUCH_UP, TOUCH_DOWN, TOUCH_MOVE } TouchAction;
-
-// Gesture events
-// NOTE: MAX_TOUCH_POINTS fixed to 2
-typedef struct GestureEvent {
-    int touchAction;
-    int pointCount;
-    int pointerId[MAX_TOUCH_POINTS];
-    Vector2 position[MAX_TOUCH_POINTS];
-} 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;
 
 
@@ -711,11 +699,8 @@ bool IsButtonReleased(int button);                      // Detect if an android
 //------------------------------------------------------------------------------------
 //------------------------------------------------------------------------------------
 void SetGesturesEnabled(unsigned int gestureFlags);     // Enable a set of gestures using flags
 void SetGesturesEnabled(unsigned int gestureFlags);     // Enable a set of gestures using flags
 bool IsGestureDetected(int gesture);                    // Check if a gesture have been detected
 bool IsGestureDetected(int gesture);                    // Check if a gesture have been detected
-void ProcessGestureEvent(GestureEvent event);           // Process gesture event and translate it into gestures
-void UpdateGestures(void);                              // Update gestures detected (called automatically in PollInputEvents())
-
-int GetTouchPointsCount(void);                          // Get touch points count
 int GetGestureDetected(void);                           // Get latest detected gesture
 int GetGestureDetected(void);                           // Get latest detected gesture
+int GetTouchPointsCount(void);                          // Get touch points count
 float GetGestureHoldDuration(void);                     // Get gesture hold time in milliseconds
 float GetGestureHoldDuration(void);                     // Get gesture hold time in milliseconds
 Vector2 GetGestureDragVector(void);                     // Get gesture drag vector
 Vector2 GetGestureDragVector(void);                     // Get gesture drag vector
 float GetGestureDragAngle(void);                        // Get gesture drag angle
 float GetGestureDragAngle(void);                        // Get gesture drag angle

+ 1 - 9
src/rlua.h

@@ -1313,12 +1313,6 @@ int lua_IsGestureDetected(lua_State* L)
 	return 1;
 	return 1;
 }
 }
 
 
-int lua_UpdateGestures(lua_State* L)
-{
-	UpdateGestures();
-	return 0;
-}
-
 int lua_GetTouchPointsCount(lua_State* L)
 int lua_GetTouchPointsCount(lua_State* L)
 {
 {
 	int result = GetTouchPointsCount();
 	int result = GetTouchPointsCount();
@@ -3576,10 +3570,8 @@ static luaL_Reg raylib_functions[] = {
 
 
 	REG(SetGesturesEnabled)
 	REG(SetGesturesEnabled)
 	REG(IsGestureDetected)
 	REG(IsGestureDetected)
-	//REG(ProcessGestureEvent)
-	REG(UpdateGestures)
-	REG(GetTouchPointsCount)
 	REG(GetGestureDetected)
 	REG(GetGestureDetected)
+    REG(GetTouchPointsCount)
 	REG(GetGestureHoldDuration)
 	REG(GetGestureHoldDuration)
 	REG(GetGestureDragVector)
 	REG(GetGestureDragVector)
 	REG(GetGestureDragAngle)
 	REG(GetGestureDragAngle)