50 #define PI 3.14159265358979323846
56#ifndef MAX_TOUCH_POINTS
57 #define MAX_TOUCH_POINTS 8
65#if defined(__STDC__) && __STDC_VERSION__ >= 199901L
67#elif !defined(__cplusplus) && !defined(bool) && !defined(RL_BOOL_TYPE)
68 typedef enum bool {
false,
true }
bool;
71#if !defined(RL_VECTOR2_TYPE)
79#if defined(GESTURES_STANDALONE)
128#if defined(GESTURES_STANDALONE)
152#if defined(GESTURES_IMPLEMENTATION)
155 #if defined(__cplusplus)
159 int __stdcall QueryPerformanceCounter(
unsigned long long int *lpPerformanceCount);
160 int __stdcall QueryPerformanceFrequency(
unsigned long long int *lpFrequency);
161 #if defined(__cplusplus)
164#elif defined(__linux__)
165 #if _POSIX_C_SOURCE < 199309L
166 #undef _POSIX_C_SOURCE
167 #define _POSIX_C_SOURCE 199309L
169 #include <sys/time.h>
174#if defined(__APPLE__)
175 #include <mach/clock.h>
176 #include <mach/mach.h>
182#define FORCE_TO_SWIPE 0.0005f
183#define MINIMUM_DRAG 0.015f
184#define MINIMUM_PINCH 0.005f
185#define TAP_TIMEOUT 300
186#define PINCH_TIMEOUT 300
187#define DOUBLETAP_RANGE 0.03f
195 unsigned int current;
196 unsigned int enabledFlags;
233static GesturesData GESTURES = {
236 .enabledFlags = 0b0000001111111111
242static float rgVector2Angle(
Vector2 initialPosition,
Vector2 finalPosition);
244static double rgGetCurrentTime(
void);
253 GESTURES.enabledFlags = flags;
259 if ((GESTURES.enabledFlags & GESTURES.current) == gesture)
return true;
267 GESTURES.Touch.pointCount =
event.pointCount;
269 if (GESTURES.Touch.pointCount == 1)
273 GESTURES.Touch.tapCounter++;
276 if ((GESTURES.current ==
GESTURE_NONE) && (GESTURES.Touch.tapCounter >= 2) && ((rgGetCurrentTime() - GESTURES.Touch.eventTime) < TAP_TIMEOUT) && (rgVector2Distance(GESTURES.Touch.downPositionA, event.
position[0]) < DOUBLETAP_RANGE))
279 GESTURES.Touch.tapCounter = 0;
283 GESTURES.Touch.tapCounter = 1;
287 GESTURES.Touch.downPositionA =
event.position[0];
288 GESTURES.Touch.downDragPosition =
event.position[0];
290 GESTURES.Touch.upPosition = GESTURES.Touch.downPositionA;
291 GESTURES.Touch.eventTime = rgGetCurrentTime();
293 GESTURES.Touch.firstId =
event.pointId[0];
295 GESTURES.Drag.vector = (
Vector2){ 0.0f, 0.0f };
299 if (GESTURES.current ==
GESTURE_DRAG) GESTURES.Touch.upPosition =
event.position[0];
302 GESTURES.Drag.distance = rgVector2Distance(GESTURES.Touch.downPositionA, GESTURES.Touch.upPosition);
303 GESTURES.Drag.intensity = GESTURES.Drag.distance/(float)((rgGetCurrentTime() - GESTURES.Swipe.timeDuration));
305 GESTURES.Swipe.start =
false;
308 if ((GESTURES.Drag.intensity > FORCE_TO_SWIPE) && (GESTURES.Touch.firstId ==
event.pointId[0]))
311 GESTURES.Drag.angle = 360.0f - rgVector2Angle(GESTURES.Touch.downPositionA, GESTURES.Touch.upPosition);
313 if ((GESTURES.Drag.angle < 30) || (GESTURES.Drag.angle > 330)) GESTURES.current =
GESTURE_SWIPE_RIGHT;
314 else if ((GESTURES.Drag.angle > 30) && (GESTURES.Drag.angle < 120)) GESTURES.current =
GESTURE_SWIPE_UP;
315 else if ((GESTURES.Drag.angle > 120) && (GESTURES.Drag.angle < 210)) GESTURES.current =
GESTURE_SWIPE_LEFT;
316 else if ((GESTURES.Drag.angle > 210) && (GESTURES.Drag.angle < 300)) GESTURES.current =
GESTURE_SWIPE_DOWN;
321 GESTURES.Drag.distance = 0.0f;
322 GESTURES.Drag.intensity = 0.0f;
323 GESTURES.Drag.angle = 0.0f;
328 GESTURES.Touch.downDragPosition = (
Vector2){ 0.0f, 0.0f };
329 GESTURES.Touch.pointCount = 0;
333 if (GESTURES.current ==
GESTURE_DRAG) GESTURES.Touch.eventTime = rgGetCurrentTime();
335 if (!GESTURES.Swipe.start)
337 GESTURES.Swipe.timeDuration = rgGetCurrentTime();
338 GESTURES.Swipe.start =
true;
341 GESTURES.Touch.moveDownPositionA =
event.position[0];
345 if (GESTURES.Hold.resetRequired) GESTURES.Touch.downPositionA =
event.position[0];
347 GESTURES.Hold.resetRequired =
false;
350 if (rgVector2Distance(GESTURES.Touch.downPositionA, GESTURES.Touch.moveDownPositionA) >= MINIMUM_DRAG)
352 GESTURES.Touch.eventTime = rgGetCurrentTime();
357 GESTURES.Drag.vector.x = GESTURES.Touch.moveDownPositionA.x - GESTURES.Touch.downDragPosition.x;
358 GESTURES.Drag.vector.y = GESTURES.Touch.moveDownPositionA.y - GESTURES.Touch.downDragPosition.y;
361 else if (GESTURES.Touch.pointCount == 2)
365 GESTURES.Touch.downPositionA =
event.position[0];
366 GESTURES.Touch.downPositionB =
event.position[1];
370 GESTURES.Pinch.vector.x = GESTURES.Touch.downPositionB.x - GESTURES.Touch.downPositionA.x;
371 GESTURES.Pinch.vector.y = GESTURES.Touch.downPositionB.y - GESTURES.Touch.downPositionA.y;
374 GESTURES.Hold.timeDuration = rgGetCurrentTime();
378 GESTURES.Pinch.distance = rgVector2Distance(GESTURES.Touch.moveDownPositionA, GESTURES.Touch.moveDownPositionB);
380 GESTURES.Touch.downPositionA = GESTURES.Touch.moveDownPositionA;
381 GESTURES.Touch.downPositionB = GESTURES.Touch.moveDownPositionB;
383 GESTURES.Touch.moveDownPositionA =
event.position[0];
384 GESTURES.Touch.moveDownPositionB =
event.position[1];
386 GESTURES.Pinch.vector.x = GESTURES.Touch.moveDownPositionB.x - GESTURES.Touch.moveDownPositionA.x;
387 GESTURES.Pinch.vector.y = GESTURES.Touch.moveDownPositionB.y - GESTURES.Touch.moveDownPositionA.y;
389 if ((rgVector2Distance(GESTURES.Touch.downPositionA, GESTURES.Touch.moveDownPositionA) >= MINIMUM_PINCH) || (rgVector2Distance(GESTURES.Touch.downPositionB, GESTURES.Touch.moveDownPositionB) >= MINIMUM_PINCH))
391 if ((rgVector2Distance(GESTURES.Touch.moveDownPositionA, GESTURES.Touch.moveDownPositionB) - GESTURES.Pinch.distance) < 0) GESTURES.current =
GESTURE_PINCH_IN;
397 GESTURES.Hold.timeDuration = rgGetCurrentTime();
401 GESTURES.Pinch.angle = 360.0f - rgVector2Angle(GESTURES.Touch.moveDownPositionA, GESTURES.Touch.moveDownPositionB);
405 GESTURES.Pinch.distance = 0.0f;
406 GESTURES.Pinch.angle = 0.0f;
407 GESTURES.Pinch.vector = (
Vector2){ 0.0f, 0.0f };
408 GESTURES.Touch.pointCount = 0;
413 else if (GESTURES.Touch.pointCount > 2)
428 GESTURES.Hold.timeDuration = rgGetCurrentTime();
431 if (((rgGetCurrentTime() - GESTURES.Touch.eventTime) > TAP_TIMEOUT) && (GESTURES.current ==
GESTURE_DRAG) && (GESTURES.Touch.pointCount < 2))
434 GESTURES.Hold.timeDuration = rgGetCurrentTime();
435 GESTURES.Hold.resetRequired =
true;
449 return (GESTURES.enabledFlags & GESTURES.current);
459 if (GESTURES.current ==
GESTURE_HOLD) time = rgGetCurrentTime() - GESTURES.Hold.timeDuration;
469 return GESTURES.Drag.vector;
478 return GESTURES.Drag.angle;
486 return GESTURES.Pinch.vector;
495 return GESTURES.Pinch.angle;
504 float angle = atan2f(v2.
y - v1.
y, v2.
x - v1.
x)*(180.0f/
PI);
506 if (angle < 0) angle += 360.0f;
516 float dx = v2.
x - v1.
x;
517 float dy = v2.
y - v1.
y;
519 result = (float)sqrt(dx*dx + dy*dy);
525static double rgGetCurrentTime(
void)
530 unsigned long long int clockFrequency, currentTime;
532 QueryPerformanceFrequency(&clockFrequency);
533 QueryPerformanceCounter(¤tTime);
535 time = (double)currentTime/clockFrequency*1000.0f;
538#if defined(__linux__)
541 clock_gettime(CLOCK_MONOTONIC, &now);
542 unsigned long long int nowTime = (
unsigned long long int)now.tv_sec*1000000000LLU + (
unsigned long long int)now.tv_nsec;
544 time = ((double)nowTime/1000000.0);
547#if defined(__APPLE__)
553 host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &cclock);
556 clock_get_time(cclock, &now);
557 mach_port_deallocate(mach_task_self(), cclock);
558 unsigned long long int nowTime = (
unsigned long long int)now.tv_sec*1000000000LLU + (
unsigned long long int)now.tv_nsec;
560 time = ((double)nowTime/1000000.0);
RLAPI int GetGestureDetected(void)
RLAPI float GetGestureHoldDuration(void)
RLAPI float GetGesturePinchAngle(void)
RLAPI Vector2 GetGesturePinchVector(void)
RLAPI Vector2 GetGestureDragVector(void)
RLAPI float GetGestureDragAngle(void)
RLAPI void SetGesturesEnabled(unsigned int flags)
RLAPI bool IsGestureDetected(int gesture)
#define PI
rgestures - Gestures system, gestures processing based on input events (touch/mouse)
void ProcessGestureEvent(GestureEvent event)
void UpdateGestures(void)
Vector2 position[MAX_TOUCH_POINTS]