WARNING: MODULES RENAMING!!!

raylib modules have been slightly renamed to add some identity and note that they are independent modules that can be used as standalone separate parts of raylib if required.

The renamed modules are:
 - `core` -> `rcore`
 - `shapes` -> `rshapes`
 - `textures` -> `rtextures`
 - `text` -> `rtext`
 - `models` -> `rmodels`
 - `camera` -> `rcamera`
 - `gestures` -> `rgestures`
 - `core` -> `rcore`

All the build systems has been adapted to this change.
This commit is contained in:
Ray
2021-09-22 00:15:06 +02:00
parent 8b3d054408
commit 99ab4d6cb8
20 changed files with 57 additions and 58 deletions

566
src/rgestures.h Normal file
View File

@ -0,0 +1,566 @@
/**********************************************************************************************
*
* rgestures - Gestures system, gestures processing based on input events (touch/mouse)
*
* NOTE: Memory footprint of this library is aproximately 128 bytes (global variables)
*
* CONFIGURATION:
*
* #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.
*
* CONTRIBUTORS:
* Marc Palau: Initial implementation (2014)
* Albert Martos: Complete redesign and testing (2015)
* Ian Eito: Complete redesign and testing (2015)
* Ramon Santamaria: Supervision, review, update and maintenance
*
*
* LICENSE: zlib/libpng
*
* Copyright (c) 2014-2021 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.
*
**********************************************************************************************/
#ifndef RGESTURES_H
#define RGESTURES_H
#ifndef PI
#define PI 3.14159265358979323846
#endif
//----------------------------------------------------------------------------------
// Defines and Macros
//----------------------------------------------------------------------------------
#ifndef MAX_TOUCH_POINTS
#define MAX_TOUCH_POINTS 8 // Maximum number of touch points supported
#endif
//----------------------------------------------------------------------------------
// Types and Structures Definition
// NOTE: Below types are required for GESTURES_STANDALONE usage
//----------------------------------------------------------------------------------
// Boolean type
#if defined(__STDC__) && __STDC_VERSION__ >= 199901L
#include <stdbool.h>
#elif !defined(__cplusplus) && !defined(bool) && !defined(RL_BOOL_TYPE)
typedef enum bool { false, true } bool;
#endif
#if !defined(RL_VECTOR2_TYPE)
// Vector2 type
typedef struct Vector2 {
float x;
float y;
} Vector2;
#endif
#if defined(GESTURES_STANDALONE)
// Gestures type
// NOTE: It could be used as flags to enable only some gestures
typedef enum {
GESTURE_NONE = 0,
GESTURE_TAP = 1,
GESTURE_DOUBLETAP = 2,
GESTURE_HOLD = 4,
GESTURE_DRAG = 8,
GESTURE_SWIPE_RIGHT = 16,
GESTURE_SWIPE_LEFT = 32,
GESTURE_SWIPE_UP = 64,
GESTURE_SWIPE_DOWN = 128,
GESTURE_PINCH_IN = 256,
GESTURE_PINCH_OUT = 512
} Gesture;
#endif
typedef enum {
TOUCH_ACTION_UP = 0,
TOUCH_ACTION_DOWN,
TOUCH_ACTION_MOVE,
TOUCH_ACTION_CANCEL
} TouchAction;
// Gesture event
typedef struct {
int touchAction;
int pointCount;
int pointId[MAX_TOUCH_POINTS];
Vector2 position[MAX_TOUCH_POINTS];
} GestureEvent;
//----------------------------------------------------------------------------------
// Global Variables Definition
//----------------------------------------------------------------------------------
//...
//----------------------------------------------------------------------------------
// Module Functions Declaration
//----------------------------------------------------------------------------------
#ifdef __cplusplus
extern "C" { // Prevents name mangling of functions
#endif
void ProcessGestureEvent(GestureEvent event); // Process gesture event and translate it into gestures
void UpdateGestures(void); // Update gestures detected (must be called every frame)
#if defined(GESTURES_STANDALONE)
void SetGesturesEnabled(unsigned int flags); // 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
float GetGestureHoldDuration(void); // Get gesture hold time in milliseconds
Vector2 GetGestureDragVector(void); // Get gesture drag vector
float GetGestureDragAngle(void); // Get gesture drag angle
Vector2 GetGesturePinchVector(void); // Get gesture pinch delta
float GetGesturePinchAngle(void); // Get gesture pinch angle
#endif
#ifdef __cplusplus
}
#endif
#endif // GESTURES_H
/***********************************************************************************
*
* GESTURES IMPLEMENTATION
*
************************************************************************************/
#if defined(GESTURES_IMPLEMENTATION)
#if defined(_WIN32)
#if defined(__cplusplus)
extern "C" { // Prevents name mangling of functions
#endif
// Functions required to query time on Windows
int __stdcall QueryPerformanceCounter(unsigned long long int *lpPerformanceCount);
int __stdcall QueryPerformanceFrequency(unsigned long long int *lpFrequency);
#if defined(__cplusplus)
}
#endif
#elif defined(__linux__)
#if _POSIX_C_SOURCE < 199309L
#undef _POSIX_C_SOURCE
#define _POSIX_C_SOURCE 199309L // Required for CLOCK_MONOTONIC if compiled with c99 without gnu ext.
#endif
#include <sys/time.h> // Required for: timespec
#include <time.h> // Required for: clock_gettime()
#include <math.h> // Required for: sqrtf(), atan2f()
#endif
#if defined(__APPLE__) // macOS also defines __MACH__
#include <mach/clock.h> // Required for: clock_get_time()
#include <mach/mach.h> // Required for: mach_timespec_t
#endif
//----------------------------------------------------------------------------------
// Defines and Macros
//----------------------------------------------------------------------------------
#define FORCE_TO_SWIPE 0.0005f // Swipe force, measured in normalized screen units/time
#define MINIMUM_DRAG 0.015f // Drag minimum force, measured in normalized screen units (0.0f to 1.0f)
#define MINIMUM_PINCH 0.005f // Pinch minimum force, measured in normalized screen units (0.0f to 1.0f)
#define TAP_TIMEOUT 300 // Tap minimum time, measured in milliseconds
#define PINCH_TIMEOUT 300 // Pinch minimum time, measured in milliseconds
#define DOUBLETAP_RANGE 0.03f // DoubleTap range, measured in normalized screen units (0.0f to 1.0f)
//----------------------------------------------------------------------------------
// Types and Structures Definition
//----------------------------------------------------------------------------------
// Gestures module state context [136 bytes]
typedef struct {
unsigned int current; // Current detected gesture
unsigned int enabledFlags; // Enabled gestures flags
struct {
int firstId; // Touch id for first touch point
int pointCount; // Touch points counter
double eventTime; // Time stamp when an event happened
Vector2 upPosition; // Touch up position
Vector2 downPositionA; // First touch down position
Vector2 downPositionB; // Second touch down position
Vector2 downDragPosition; // Touch drag position
Vector2 moveDownPositionA; // First touch down position on move
Vector2 moveDownPositionB; // Second touch down position on move
int tapCounter; // TAP counter (one tap implies TOUCH_ACTION_DOWN and TOUCH_ACTION_UP actions)
} Touch;
struct {
bool resetRequired; // HOLD reset to get first touch point again
double timeDuration; // HOLD duration in milliseconds
} Hold;
struct {
Vector2 vector; // DRAG vector (between initial and current position)
float angle; // DRAG angle (relative to x-axis)
float distance; // DRAG distance (from initial touch point to final) (normalized [0..1])
float intensity; // DRAG intensity, how far why did the DRAG (pixels per frame)
} Drag;
struct {
bool start; // SWIPE used to define when start measuring GESTURES.Swipe.timeDuration
double timeDuration; // SWIPE time to calculate drag intensity
} Swipe;
struct {
Vector2 vector; // PINCH vector (between first and second touch points)
float angle; // PINCH angle (relative to x-axis)
float distance; // PINCH displacement distance (normalized [0..1])
} Pinch;
} GesturesData;
//----------------------------------------------------------------------------------
// Global Variables Definition
//----------------------------------------------------------------------------------
static GesturesData GESTURES = {
.Touch.firstId = -1,
.current = GESTURE_NONE, // No current gesture detected
.enabledFlags = 0b0000001111111111 // All gestures supported by default
};
//----------------------------------------------------------------------------------
// Module specific Functions Declaration
//----------------------------------------------------------------------------------
static float rgVector2Angle(Vector2 initialPosition, Vector2 finalPosition);
static float rgVector2Distance(Vector2 v1, Vector2 v2);
static double rgGetCurrentTime(void);
//----------------------------------------------------------------------------------
// Module Functions Definition
//----------------------------------------------------------------------------------
// Enable only desired getures to be detected
void SetGesturesEnabled(unsigned int flags)
{
GESTURES.enabledFlags = flags;
}
// Check if a gesture have been detected
bool IsGestureDetected(int gesture)
{
if ((GESTURES.enabledFlags & GESTURES.current) == gesture) return true;
else return false;
}
// Process gesture event and translate it into gestures
void ProcessGestureEvent(GestureEvent event)
{
// Reset required variables
GESTURES.Touch.pointCount = event.pointCount; // Required on UpdateGestures()
if (GESTURES.Touch.pointCount == 1) // One touch point
{
if (event.touchAction == TOUCH_ACTION_DOWN)
{
GESTURES.Touch.tapCounter++; // Tap counter
// Detect GESTURE_DOUBLE_TAP
if ((GESTURES.current == GESTURE_NONE) && (GESTURES.Touch.tapCounter >= 2) && ((rgGetCurrentTime() - GESTURES.Touch.eventTime) < TAP_TIMEOUT) && (rgVector2Distance(GESTURES.Touch.downPositionA, event.position[0]) < DOUBLETAP_RANGE))
{
GESTURES.current = GESTURE_DOUBLETAP;
GESTURES.Touch.tapCounter = 0;
}
else // Detect GESTURE_TAP
{
GESTURES.Touch.tapCounter = 1;
GESTURES.current = GESTURE_TAP;
}
GESTURES.Touch.downPositionA = event.position[0];
GESTURES.Touch.downDragPosition = event.position[0];
GESTURES.Touch.upPosition = GESTURES.Touch.downPositionA;
GESTURES.Touch.eventTime = rgGetCurrentTime();
GESTURES.Touch.firstId = event.pointId[0];
GESTURES.Drag.vector = (Vector2){ 0.0f, 0.0f };
}
else if (event.touchAction == TOUCH_ACTION_UP)
{
if (GESTURES.current == GESTURE_DRAG) GESTURES.Touch.upPosition = event.position[0];
// NOTE: GESTURES.Drag.intensity dependend on the resolution of the screen
GESTURES.Drag.distance = rgVector2Distance(GESTURES.Touch.downPositionA, GESTURES.Touch.upPosition);
GESTURES.Drag.intensity = GESTURES.Drag.distance/(float)((rgGetCurrentTime() - GESTURES.Swipe.timeDuration));
GESTURES.Swipe.start = false;
// Detect GESTURE_SWIPE
if ((GESTURES.Drag.intensity > FORCE_TO_SWIPE) && (GESTURES.Touch.firstId == event.pointId[0]))
{
// NOTE: Angle should be inverted in Y
GESTURES.Drag.angle = 360.0f - rgVector2Angle(GESTURES.Touch.downPositionA, GESTURES.Touch.upPosition);
if ((GESTURES.Drag.angle < 30) || (GESTURES.Drag.angle > 330)) GESTURES.current = GESTURE_SWIPE_RIGHT; // Right
else if ((GESTURES.Drag.angle > 30) && (GESTURES.Drag.angle < 120)) GESTURES.current = GESTURE_SWIPE_UP; // Up
else if ((GESTURES.Drag.angle > 120) && (GESTURES.Drag.angle < 210)) GESTURES.current = GESTURE_SWIPE_LEFT; // Left
else if ((GESTURES.Drag.angle > 210) && (GESTURES.Drag.angle < 300)) GESTURES.current = GESTURE_SWIPE_DOWN; // Down
else GESTURES.current = GESTURE_NONE;
}
else
{
GESTURES.Drag.distance = 0.0f;
GESTURES.Drag.intensity = 0.0f;
GESTURES.Drag.angle = 0.0f;
GESTURES.current = GESTURE_NONE;
}
GESTURES.Touch.downDragPosition = (Vector2){ 0.0f, 0.0f };
GESTURES.Touch.pointCount = 0;
}
else if (event.touchAction == TOUCH_ACTION_MOVE)
{
if (GESTURES.current == GESTURE_DRAG) GESTURES.Touch.eventTime = rgGetCurrentTime();
if (!GESTURES.Swipe.start)
{
GESTURES.Swipe.timeDuration = rgGetCurrentTime();
GESTURES.Swipe.start = true;
}
GESTURES.Touch.moveDownPositionA = event.position[0];
if (GESTURES.current == GESTURE_HOLD)
{
if (GESTURES.Hold.resetRequired) GESTURES.Touch.downPositionA = event.position[0];
GESTURES.Hold.resetRequired = false;
// Detect GESTURE_DRAG
if (rgVector2Distance(GESTURES.Touch.downPositionA, GESTURES.Touch.moveDownPositionA) >= MINIMUM_DRAG)
{
GESTURES.Touch.eventTime = rgGetCurrentTime();
GESTURES.current = GESTURE_DRAG;
}
}
GESTURES.Drag.vector.x = GESTURES.Touch.moveDownPositionA.x - GESTURES.Touch.downDragPosition.x;
GESTURES.Drag.vector.y = GESTURES.Touch.moveDownPositionA.y - GESTURES.Touch.downDragPosition.y;
}
}
else if (GESTURES.Touch.pointCount == 2) // Two touch points
{
if (event.touchAction == TOUCH_ACTION_DOWN)
{
GESTURES.Touch.downPositionA = event.position[0];
GESTURES.Touch.downPositionB = event.position[1];
//GESTURES.Pinch.distance = rgVector2Distance(GESTURES.Touch.downPositionA, GESTURES.Touch.downPositionB);
GESTURES.Pinch.vector.x = GESTURES.Touch.downPositionB.x - GESTURES.Touch.downPositionA.x;
GESTURES.Pinch.vector.y = GESTURES.Touch.downPositionB.y - GESTURES.Touch.downPositionA.y;
GESTURES.current = GESTURE_HOLD;
GESTURES.Hold.timeDuration = rgGetCurrentTime();
}
else if (event.touchAction == TOUCH_ACTION_MOVE)
{
GESTURES.Pinch.distance = rgVector2Distance(GESTURES.Touch.moveDownPositionA, GESTURES.Touch.moveDownPositionB);
GESTURES.Touch.downPositionA = GESTURES.Touch.moveDownPositionA;
GESTURES.Touch.downPositionB = GESTURES.Touch.moveDownPositionB;
GESTURES.Touch.moveDownPositionA = event.position[0];
GESTURES.Touch.moveDownPositionB = event.position[1];
GESTURES.Pinch.vector.x = GESTURES.Touch.moveDownPositionB.x - GESTURES.Touch.moveDownPositionA.x;
GESTURES.Pinch.vector.y = GESTURES.Touch.moveDownPositionB.y - GESTURES.Touch.moveDownPositionA.y;
if ((rgVector2Distance(GESTURES.Touch.downPositionA, GESTURES.Touch.moveDownPositionA) >= MINIMUM_PINCH) || (rgVector2Distance(GESTURES.Touch.downPositionB, GESTURES.Touch.moveDownPositionB) >= MINIMUM_PINCH))
{
if ((rgVector2Distance(GESTURES.Touch.moveDownPositionA, GESTURES.Touch.moveDownPositionB) - GESTURES.Pinch.distance) < 0) GESTURES.current = GESTURE_PINCH_IN;
else GESTURES.current = GESTURE_PINCH_OUT;
}
else
{
GESTURES.current = GESTURE_HOLD;
GESTURES.Hold.timeDuration = rgGetCurrentTime();
}
// NOTE: Angle should be inverted in Y
GESTURES.Pinch.angle = 360.0f - rgVector2Angle(GESTURES.Touch.moveDownPositionA, GESTURES.Touch.moveDownPositionB);
}
else if (event.touchAction == TOUCH_ACTION_UP)
{
GESTURES.Pinch.distance = 0.0f;
GESTURES.Pinch.angle = 0.0f;
GESTURES.Pinch.vector = (Vector2){ 0.0f, 0.0f };
GESTURES.Touch.pointCount = 0;
GESTURES.current = GESTURE_NONE;
}
}
else if (GESTURES.Touch.pointCount > 2) // More than two touch points
{
// TODO.
}
}
// 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 (((GESTURES.current == GESTURE_TAP) || (GESTURES.current == GESTURE_DOUBLETAP)) && (GESTURES.Touch.pointCount < 2))
{
GESTURES.current = GESTURE_HOLD;
GESTURES.Hold.timeDuration = rgGetCurrentTime();
}
if (((rgGetCurrentTime() - GESTURES.Touch.eventTime) > TAP_TIMEOUT) && (GESTURES.current == GESTURE_DRAG) && (GESTURES.Touch.pointCount < 2))
{
GESTURES.current = GESTURE_HOLD;
GESTURES.Hold.timeDuration = rgGetCurrentTime();
GESTURES.Hold.resetRequired = true;
}
// Detect GESTURE_NONE
if ((GESTURES.current == GESTURE_SWIPE_RIGHT) || (GESTURES.current == GESTURE_SWIPE_UP) || (GESTURES.current == GESTURE_SWIPE_LEFT) || (GESTURES.current == GESTURE_SWIPE_DOWN))
{
GESTURES.current = GESTURE_NONE;
}
}
// Get latest detected gesture
int GetGestureDetected(void)
{
// Get current gesture only if enabled
return (GESTURES.enabledFlags & GESTURES.current);
}
// Hold time measured in ms
float GetGestureHoldDuration(void)
{
// NOTE: time is calculated on current gesture HOLD
double time = 0.0;
if (GESTURES.current == GESTURE_HOLD) time = rgGetCurrentTime() - GESTURES.Hold.timeDuration;
return (float)time;
}
// Get drag vector (between initial touch point to current)
Vector2 GetGestureDragVector(void)
{
// NOTE: drag vector is calculated on one touch points TOUCH_ACTION_MOVE
return GESTURES.Drag.vector;
}
// 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_ACTION_UP
return GESTURES.Drag.angle;
}
// Get distance between two pinch points
Vector2 GetGesturePinchVector(void)
{
// NOTE: Pinch distance is calculated on two touch points TOUCH_ACTION_MOVE
return GESTURES.Pinch.vector;
}
// 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_ACTION_MOVE
return GESTURES.Pinch.angle;
}
//----------------------------------------------------------------------------------
// Module specific Functions Definition
//----------------------------------------------------------------------------------
// Get angle from two-points vector with X-axis
static float rgVector2Angle(Vector2 v1, Vector2 v2)
{
float angle = atan2f(v2.y - v1.y, v2.x - v1.x)*(180.0f/PI);
if (angle < 0) angle += 360.0f;
return angle;
}
// Calculate distance between two Vector2
static float rgVector2Distance(Vector2 v1, Vector2 v2)
{
float result;
float dx = v2.x - v1.x;
float dy = v2.y - v1.y;
result = (float)sqrt(dx*dx + dy*dy);
return result;
}
// Time measure returned are milliseconds
static double rgGetCurrentTime(void)
{
double time = 0;
#if defined(_WIN32)
unsigned long long int clockFrequency, currentTime;
QueryPerformanceFrequency(&clockFrequency); // BE CAREFUL: Costly operation!
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);
unsigned long long int nowTime = (unsigned long long int)now.tv_sec*1000000000LLU + (unsigned long long int)now.tv_nsec; // Time in nanoseconds
time = ((double)nowTime/1000000.0); // Time in miliseconds
#endif
#if defined(__APPLE__)
//#define CLOCK_REALTIME CALENDAR_CLOCK // returns UTC time since 1970-01-01
//#define CLOCK_MONOTONIC SYSTEM_CLOCK // returns the time since boot time
clock_serv_t cclock;
mach_timespec_t now;
host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &cclock);
// NOTE: OS X does not have clock_gettime(), using clock_get_time()
clock_get_time(cclock, &now);
mach_port_deallocate(mach_task_self(), cclock);
unsigned long long int nowTime = (unsigned long long int)now.tv_sec*1000000000LLU + (unsigned long long int)now.tv_nsec; // Time in nanoseconds
time = ((double)nowTime/1000000.0); // Time in miliseconds
#endif
return time;
}
#endif // GESTURES_IMPLEMENTATION