Got through parsing raylib.h, started to do some major refactors.

This commit is contained in:
Edward R. Gonzalez 2023-10-25 03:26:25 -04:00
parent d0f3b6187e
commit 041671762b
14 changed files with 8592 additions and 7039 deletions

View File

@ -1,89 +1,89 @@
/********************************************************************************************** /**********************************************************************************************
* *
* raylib configuration flags * raylib configuration flags
* *
* This file defines all the configuration flags for the different raylib modules * This file defines all the configuration flags for the different raylib modules
* *
* LICENSE: zlib/libpng * LICENSE: zlib/libpng
* *
* Copyright (c) 2018-2023 Ahmad Fatoum & Ramon Santamaria (@raysan5) * Copyright (c) 2018-2023 Ahmad Fatoum & 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.
* *
* Permission is granted to anyone to use this software for any purpose, including commercial * 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: * 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 * 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 * 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. * 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 * 2. Altered source versions must be plainly marked as such, and must not be misrepresented
* as being the original software. * as being the original software.
* *
* 3. This notice may not be removed or altered from any source distribution. * 3. This notice may not be removed or altered from any source distribution.
* *
**********************************************************************************************/ **********************************************************************************************/
#ifndef CONFIG_H #ifndef CONFIG_H
#define RL_CONFIG_H #define RL_CONFIG_H
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
// Module selection - Some modules could be avoided // Module selection - Some modules could be avoided
// Mandatory modules: rcore, rlgl, utils // Mandatory modules: rcore, rlgl, utils
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
#define RL_SUPPORT_MODULE_RSHAPES 1 #define RL_SUPPORT_MODULE_RSHAPES 1
#define RL_SUPPORT_MODULE_RTEXTURES 1 #define RL_SUPPORT_MODULE_RTEXTURES 1
#define RL_SUPPORT_MODULE_RTEXT 1 // WARNING: It requires SUPPORT_MODULE_RTEXTURES to load sprite font textures #define RL_SUPPORT_MODULE_RTEXT 1 // WARNING: It requires SUPPORT_MODULE_RTEXTURES to load sprite font textures
#define RL_SUPPORT_MODULE_RMODELS 1 #define RL_SUPPORT_MODULE_RMODELS 1
#define RL_SUPPORT_MODULE_RAUDIO 1 #define RL_SUPPORT_MODULE_RAUDIO 1
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
// Module: rcore - Configuration Flags // Module: rcore - Configuration Flags
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
// Camera module is included (rcamera.h) and multiple predefined cameras are available: free, 1st/3rd person, orbital // Camera module is included (rcamera.h) and multiple predefined cameras are available: free, 1st/3rd person, orbital
#define RL_SUPPORT_CAMERA_SYSTEM 1 #define RL_SUPPORT_CAMERA_SYSTEM 1
// Gestures module is included (rgestures.h) to support gestures detection: tap, hold, swipe, drag // Gestures module is included (rgestures.h) to support gestures detection: tap, hold, swipe, drag
#define RL_SUPPORT_GESTURES_SYSTEM 1 #define RL_SUPPORT_GESTURES_SYSTEM 1
// Mouse gestures are directly mapped like touches and processed by gestures system // Mouse gestures are directly mapped like touches and processed by gestures system
#define RL_SUPPORT_MOUSE_GESTURES 1 #define RL_SUPPORT_MOUSE_GESTURES 1
// Reconfigure standard input to receive key inputs, works with SSH connection. // Reconfigure standard input to receive key inputs, works with SSH connection.
#define RL_SUPPORT_SSH_KEYBOARD_RPI 1 #define RL_SUPPORT_SSH_KEYBOARD_RPI 1
// Setting a higher resolution can improve the accuracy of time-out intervals in wait functions. // Setting a higher resolution can improve the accuracy of time-out intervals in wait functions.
// However, it can also reduce overall system performance, because the thread scheduler switches tasks more often. // However, it can also reduce overall system performance, because the thread scheduler switches tasks more often.
#define RL_SUPPORT_WINMM_HIGHRES_TIMER 1 #define RL_SUPPORT_WINMM_HIGHRES_TIMER 1
// Use busy wait loop for timing sync, if not defined, a high-resolution timer is set up and used // Use busy wait loop for timing sync, if not defined, a high-resolution timer is set up and used
//#define SUPPORT_BUSY_WAIT_LOOP 1 // #define SUPPORT_BUSY_WAIT_LOOP 1
// Use a partial-busy wait loop, in this case frame sleeps for most of the time, but then runs a busy loop at the end for accuracy // Use a partial-busy wait loop, in this case frame sleeps for most of the time, but then runs a busy loop at the end for accuracy
#define RL_SUPPORT_PARTIALBUSY_WAIT_LOOP 1 #define RL_SUPPORT_PARTIALBUSY_WAIT_LOOP 1
// Allow automatic screen capture of current screen pressing F12, defined in KeyCallback() // Allow automatic screen capture of current screen pressing F12, defined in KeyCallback()
#define RL_SUPPORT_SCREEN_CAPTURE 1 #define RL_SUPPORT_SCREEN_CAPTURE 1
// Allow automatic gif recording of current screen pressing CTRL+F12, defined in KeyCallback() // Allow automatic gif recording of current screen pressing CTRL+F12, defined in KeyCallback()
#define RL_SUPPORT_GIF_RECORDING 1 #define RL_SUPPORT_GIF_RECORDING 1
// Support CompressData() and DecompressData() functions // Support CompressData() and DecompressData() functions
#define RL_SUPPORT_COMPRESSION_API 1 #define RL_SUPPORT_COMPRESSION_API 1
// Support automatic generated events, loading and recording of those events when required // Support automatic generated events, loading and recording of those events when required
//#define SUPPORT_EVENTS_AUTOMATION 1 // #define SUPPORT_EVENTS_AUTOMATION 1
// Support custom frame control, only for advance users // Support custom frame control, only for advance users
// By default EndDrawing() does this job: draws everything + SwapScreenBuffer() + manage frame timing + PollInputEvents() // By default EndDrawing() does this job: draws everything + SwapScreenBuffer() + manage frame timing + PollInputEvents()
// Enabling this flag allows manual control of the frame processes, use at your own risk // Enabling this flag allows manual control of the frame processes, use at your own risk
//#define SUPPORT_CUSTOM_FRAME_CONTROL 1 // #define SUPPORT_CUSTOM_FRAME_CONTROL 1
// rcore: Configuration values // rcore: Configuration values
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
#define RL_MAX_FILEPATH_CAPACITY 8192 // Maximum file paths capacity #define RL_MAX_FILEPATH_CAPACITY 8192 // Maximum file paths capacity
#define RL_MAX_FILEPATH_LENGTH 4096 // Maximum length for filepaths (Linux PATH_MAX default value) #define RL_MAX_FILEPATH_LENGTH 4096 // Maximum length for filepaths (Linux PATH_MAX default value)
#define RL_MAX_KEYBOARD_KEYS 512 // Maximum number of keyboard keys supported #define RL_MAX_KEYBOARD_KEYS 512 // Maximum number of keyboard keys supported
#define RL_MAX_MOUSE_BUTTONS 8 // Maximum number of mouse buttons supported #define RL_MAX_MOUSE_BUTTONS 8 // Maximum number of mouse buttons supported
#define RL_MAX_GAMEPADS 4 // Maximum number of gamepads supported #define RL_MAX_GAMEPADS 4 // Maximum number of gamepads supported
#define RL_MAX_GAMEPAD_AXIS 8 // Maximum number of axis supported (per gamepad) #define RL_MAX_GAMEPAD_AXIS 8 // Maximum number of axis supported (per gamepad)
#define RL_MAX_GAMEPAD_BUTTONS 32 // Maximum number of buttons supported (per gamepad) #define RL_MAX_GAMEPAD_BUTTONS 32 // Maximum number of buttons supported (per gamepad)
#define RL_MAX_TOUCH_POINTS 8 // Maximum number of touch points supported #define RL_MAX_TOUCH_POINTS 8 // Maximum number of touch points supported
#define RL_MAX_KEY_PRESSED_QUEUE 16 // Maximum number of keys in the key input queue #define RL_MAX_KEY_PRESSED_QUEUE 16 // Maximum number of keys in the key input queue
#define RL_MAX_CHAR_PRESSED_QUEUE 16 // Maximum number of characters in the char input queue #define RL_MAX_CHAR_PRESSED_QUEUE 16 // Maximum number of characters in the char input queue
#define RL_MAX_DECOMPRESSION_SIZE 64 // Max size allocated for decompression in MB #define RL_MAX_DECOMPRESSION_SIZE 64 // Max size allocated for decompression in MB
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
@ -91,41 +91,19 @@
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
// Enable OpenGL Debug Context (only available on OpenGL 4.3) // Enable OpenGL Debug Context (only available on OpenGL 4.3)
//#define RLGL_ENABLE_OPENGL_DEBUG_CONTEXT 1 // #define RLGL_ENABLE_OPENGL_DEBUG_CONTEXT 1
// Show OpenGL extensions and capabilities detailed logs on init // Show OpenGL extensions and capabilities detailed logs on init
//#define RLGL_SHOW_GL_DETAILS_INFO 1 // #define RLGL_SHOW_GL_DETAILS_INFO 1
//#define RL_DEFAULT_BATCH_BUFFER_ELEMENTS 4096 // Default internal render batch elements limits // #define RL_DEFAULT_BATCH_BUFFER_ELEMENTS 4096 // Default internal render batch elements limits
#define RL_DEFAULT_BATCH_BUFFERS 1 // Default number of batch buffers (multi-buffering)
#define RL_DEFAULT_BATCH_DRAWCALLS 256 // Default number of batch draw calls (by state changes: mode, texture)
#define RL_DEFAULT_BATCH_MAX_TEXTURE_UNITS 4 // Maximum number of textures units that can be activated on batch drawing (SetShaderValueTexture())
#define RL_MAX_MATRIX_STACK_SIZE 32 // Maximum size of internal Matrix stack
#define RL_MAX_SHADER_LOCATIONS 32 // Maximum number of shader locations supported
#define RL_CULL_DISTANCE_NEAR 0.01 // Default projection matrix near cull distance
#define RL_CULL_DISTANCE_FAR 1000.0 // Default projection matrix far cull distance
// Default shader vertex attribute names to set location points // Default shader vertex attribute names to set location points
// NOTE: When a new shader is loaded, the following locations are tried to be set for convenience // NOTE: When a new shader is loaded, the following locations are tried to be set for convenience
#define RL_DEFAULT_SHADER_ATTRIB_NAME_POSITION "vertexPosition" // Bound by default to shader location: 0
#define RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD "vertexTexCoord" // Bound by default to shader location: 1
#define RL_DEFAULT_SHADER_ATTRIB_NAME_NORMAL "vertexNormal" // Bound by default to shader location: 2
#define RL_DEFAULT_SHADER_ATTRIB_NAME_COLOR "vertexColor" // Bound by default to shader location: 3
#define RL_DEFAULT_SHADER_ATTRIB_NAME_TANGENT "vertexTangent" // Bound by default to shader location: 4
#define RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2 "vertexTexCoord2" // Bound by default to shader location: 5
#define RL_DEFAULT_SHADER_UNIFORM_NAME_MVP "mvp" // model-view-projection matrix
#define RL_DEFAULT_SHADER_UNIFORM_NAME_VIEW "matView" // view matrix
#define RL_DEFAULT_SHADER_UNIFORM_NAME_PROJECTION "matProjection" // projection matrix
#define RL_DEFAULT_SHADER_UNIFORM_NAME_MODEL "matModel" // model matrix
#define RL_DEFAULT_SHADER_UNIFORM_NAME_NORMAL "matNormal" // normal matrix (transpose(inverse(matModelView))
#define RL_DEFAULT_SHADER_UNIFORM_NAME_COLOR "colDiffuse" // color diffuse (base tint color, multiplied by texture color)
#define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE0 "texture0" // texture0 (texture slot active 0)
#define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE1 "texture1" // texture1 (texture slot active 1)
#define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE2 "texture2" // texture2 (texture slot active 2)
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
@ -133,36 +111,36 @@
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
// Use QUADS instead of TRIANGLES for drawing when possible // Use QUADS instead of TRIANGLES for drawing when possible
// Some lines-based shapes could still use lines // Some lines-based shapes could still use lines
#define RL_SUPPORT_QUADS_DRAW_MODE 1 #define RL_SUPPORT_QUADS_DRAW_MODE 1
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
// Module: rtextures - Configuration Flags // Module: rtextures - Configuration Flags
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
// Selecte desired fileformats to be supported for image data loading // Selecte desired fileformats to be supported for image data loading
#define RL_SUPPORT_FILEFORMAT_PNG 1 #define RL_SUPPORT_FILEFORMAT_PNG 1
//#define SUPPORT_FILEFORMAT_BMP 1 // #define SUPPORT_FILEFORMAT_BMP 1
//#define SUPPORT_FILEFORMAT_TGA 1 // #define SUPPORT_FILEFORMAT_TGA 1
//#define SUPPORT_FILEFORMAT_JPG 1 // #define SUPPORT_FILEFORMAT_JPG 1
#define RL_SUPPORT_FILEFORMAT_GIF 1 #define RL_SUPPORT_FILEFORMAT_GIF 1
#define RL_SUPPORT_FILEFORMAT_QOI 1 #define RL_SUPPORT_FILEFORMAT_QOI 1
//#define SUPPORT_FILEFORMAT_PSD 1 // #define SUPPORT_FILEFORMAT_PSD 1
#define RL_SUPPORT_FILEFORMAT_DDS 1 #define RL_SUPPORT_FILEFORMAT_DDS 1
//#define SUPPORT_FILEFORMAT_HDR 1 // #define SUPPORT_FILEFORMAT_HDR 1
//#define SUPPORT_FILEFORMAT_PIC 1 // #define SUPPORT_FILEFORMAT_PIC 1
//#define SUPPORT_FILEFORMAT_KTX 1 // #define SUPPORT_FILEFORMAT_KTX 1
//#define SUPPORT_FILEFORMAT_ASTC 1 // #define SUPPORT_FILEFORMAT_ASTC 1
//#define SUPPORT_FILEFORMAT_PKM 1 // #define SUPPORT_FILEFORMAT_PKM 1
//#define SUPPORT_FILEFORMAT_PVR 1 // #define SUPPORT_FILEFORMAT_PVR 1
//#define SUPPORT_FILEFORMAT_SVG 1 // #define SUPPORT_FILEFORMAT_SVG 1
// Support image export functionality (.png, .bmp, .tga, .jpg, .qoi) // Support image export functionality (.png, .bmp, .tga, .jpg, .qoi)
#define RL_SUPPORT_IMAGE_EXPORT 1 #define RL_SUPPORT_IMAGE_EXPORT 1
// Support procedural image generation functionality (gradient, spot, perlin-noise, cellular) // Support procedural image generation functionality (gradient, spot, perlin-noise, cellular)
#define RL_SUPPORT_IMAGE_GENERATION 1 #define RL_SUPPORT_IMAGE_GENERATION 1
// Support multiple image editing functions to scale, adjust colors, flip, draw on images, crop... // Support multiple image editing functions to scale, adjust colors, flip, draw on images, crop...
// If not defined, still some functions are supported: ImageFormat(), ImageCrop(), ImageToPOT() // If not defined, still some functions are supported: ImageFormat(), ImageCrop(), ImageToPOT()
#define RL_SUPPORT_IMAGE_MANIPULATION 1 #define RL_SUPPORT_IMAGE_MANIPULATION 1
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
@ -170,25 +148,25 @@
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
// Default font is loaded on window initialization to be available for the user to render simple text // Default font is loaded on window initialization to be available for the user to render simple text
// NOTE: If enabled, uses external module functions to load default raylib font // NOTE: If enabled, uses external module functions to load default raylib font
#define RL_SUPPORT_DEFAULT_FONT 1 #define RL_SUPPORT_DEFAULT_FONT 1
// Selected desired font fileformats to be supported for loading // Selected desired font fileformats to be supported for loading
#define RL_SUPPORT_FILEFORMAT_FNT 1 #define RL_SUPPORT_FILEFORMAT_FNT 1
#define RL_SUPPORT_FILEFORMAT_TTF 1 #define RL_SUPPORT_FILEFORMAT_TTF 1
// Support text management functions // Support text management functions
// If not defined, still some functions are supported: TextLength(), TextFormat() // If not defined, still some functions are supported: TextLength(), TextFormat()
#define RL_SUPPORT_TEXT_MANIPULATION 1 #define RL_SUPPORT_TEXT_MANIPULATION 1
// On font atlas image generation [GenImageFontAtlas()], add a 3x3 pixels white rectangle // On font atlas image generation [GenImageFontAtlas()], add a 3x3 pixels white rectangle
// at the bottom-right corner of the atlas. It can be useful to for shapes drawing, to allow // at the bottom-right corner of the atlas. It can be useful to for shapes drawing, to allow
// drawing text and shapes with a single draw call [SetShapesTexture()]. // drawing text and shapes with a single draw call [SetShapesTexture()].
#define RL_SUPPORT_FONT_ATLAS_WHITE_REC 1 #define RL_SUPPORT_FONT_ATLAS_WHITE_REC 1
// rtext: Configuration values // rtext: Configuration values
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
#define RL_MAX_TEXT_BUFFER_LENGTH 1024 // Size of internal static buffers used on some functions: #define RL_MAX_TEXT_BUFFER_LENGTH 1024 // Size of internal static buffers used on some functions:
// TextFormat(), TextSubtext(), TextToUpper(), TextToLower(), TextToPascal(), TextSplit() // TextFormat(), TextSubtext(), TextToUpper(), TextToLower(), TextToPascal(), TextSplit()
#define RL_MAX_TEXTSPLIT_COUNT 128 // Maximum number of substrings to split: TextSplit() #define RL_MAX_TEXTSPLIT_COUNT 128 // Maximum number of substrings to split: TextSplit()
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
@ -198,51 +176,51 @@
#define RL_SUPPORT_FILEFORMAT_OBJ 1 #define RL_SUPPORT_FILEFORMAT_OBJ 1
#define RL_SUPPORT_FILEFORMAT_MTL 1 #define RL_SUPPORT_FILEFORMAT_MTL 1
#define RL_SUPPORT_FILEFORMAT_IQM 1 #define RL_SUPPORT_FILEFORMAT_IQM 1
#define RL_SUPPORT_FILEFORMAT_GLTF 1 #define RL_SUPPORT_FILEFORMAT_GLTF 1
#define RL_SUPPORT_FILEFORMAT_VOX 1 #define RL_SUPPORT_FILEFORMAT_VOX 1
#define RL_SUPPORT_FILEFORMAT_M3D 1 #define RL_SUPPORT_FILEFORMAT_M3D 1
// Support procedural mesh generation functions, uses external par_shapes.h library // Support procedural mesh generation functions, uses external par_shapes.h library
// NOTE: Some generated meshes DO NOT include generated texture coordinates // NOTE: Some generated meshes DO NOT include generated texture coordinates
#define RL_SUPPORT_MESH_GENERATION 1 #define RL_SUPPORT_MESH_GENERATION 1
// rmodels: Configuration values // rmodels: Configuration values
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
#define RL_MAX_MATERIAL_MAPS 12 // Maximum number of shader maps supported #define RL_MAX_MATERIAL_MAPS 12 // Maximum number of shader maps supported
#define RL_MAX_MESH_VERTEX_BUFFERS 7 // Maximum vertex buffers (VBO) per mesh #define RL_MAX_MESH_VERTEX_BUFFERS 7 // Maximum vertex buffers (VBO) per mesh
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
// Module: raudio - Configuration Flags // Module: raudio - Configuration Flags
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
// Desired audio fileformats to be supported for loading // Desired audio fileformats to be supported for loading
#define RL_SUPPORT_FILEFORMAT_WAV 1 #define RL_SUPPORT_FILEFORMAT_WAV 1
#define RL_SUPPORT_FILEFORMAT_OGG 1 #define RL_SUPPORT_FILEFORMAT_OGG 1
#define RL_SUPPORT_FILEFORMAT_MP3 1 #define RL_SUPPORT_FILEFORMAT_MP3 1
#define RL_SUPPORT_FILEFORMAT_QOA 1 #define RL_SUPPORT_FILEFORMAT_QOA 1
//#define SUPPORT_FILEFORMAT_FLAC 1 // #define SUPPORT_FILEFORMAT_FLAC 1
#define RL_SUPPORT_FILEFORMAT_XM 1 #define RL_SUPPORT_FILEFORMAT_XM 1
#define RL_SUPPORT_FILEFORMAT_MOD 1 #define RL_SUPPORT_FILEFORMAT_MOD 1
// raudio: Configuration values // raudio: Configuration values
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
#define RL_AUDIO_DEVICE_FORMAT ma_format_f32 // Device output format (miniaudio: float-32bit) #define RL_AUDIO_DEVICE_FORMAT ma_format_f32 // Device output format (miniaudio: float-32bit)
#define RL_AUDIO_DEVICE_CHANNELS 2 // Device output channels: stereo #define RL_AUDIO_DEVICE_CHANNELS 2 // Device output channels: stereo
#define RL_AUDIO_DEVICE_SAMPLE_RATE 0 // Device sample rate (device default) #define RL_AUDIO_DEVICE_SAMPLE_RATE 0 // Device sample rate (device default)
#define RL_MAX_AUDIO_BUFFER_POOL_CHANNELS 16 // Maximum number of audio pool channels #define RL_MAX_AUDIO_BUFFER_POOL_CHANNELS 16 // Maximum number of audio pool channels
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
// Module: utils - Configuration Flags // Module: utils - Configuration Flags
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
// Standard file io library (stdio.h) included // Standard file io library (stdio.h) included
#define RL_SUPPORT_STANDARD_FILEIO 1 #define RL_SUPPORT_STANDARD_FILEIO 1
// Show TRACELOG() output messages // Show TRACELOG() output messages
// NOTE: By default LOG_DEBUG traces not shown // NOTE: By default LOG_DEBUG traces not shown
#define RL_SUPPORT_TRACELOG 1 #define RL_SUPPORT_TRACELOG 1
//#define SUPPORT_TRACELOG_DEBUG 1 // #define SUPPORT_TRACELOG_DEBUG 1
// utils: Configuration values // utils: Configuration values
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
#define RL_MAX_TRACELOG_MSG_LENGTH 256 // Max length of one trace-log message #define RL_MAX_TRACELOG_MSG_LENGTH 256 // Max length of one trace-log message
#endif #endif
// CONFIG_H // CONFIG_H

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,43 +1,43 @@
/******************************************************************************************* /*******************************************************************************************
* *
* rcamera - Basic camera system with support for multiple camera modes * rcamera - Basic camera system with support for multiple camera modes
* *
* CONFIGURATION: * CONFIGURATION:
* #define RCAMERA_IMPLEMENTATION * #define RCAMERA_IMPLEMENTATION
* Generates the implementation of the library into the included file. * 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 * 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. * or source files without problems. But only ONE file should hold the implementation.
* *
* #define RCAMERA_STANDALONE * #define RCAMERA_STANDALONE
* If defined, the library can be used as standalone as a camera system but some * If defined, the library can be used as standalone as a camera system but some
* functions must be redefined to manage inputs accordingly. * functions must be redefined to manage inputs accordingly.
* *
* CONTRIBUTORS: * CONTRIBUTORS:
* Ramon Santamaria: Supervision, review, update and maintenance * Ramon Santamaria: Supervision, review, update and maintenance
* Christoph Wagner: Complete redesign, using raymath (2022) * Christoph Wagner: Complete redesign, using raymath (2022)
* Marc Palau: Initial implementation (2014) * Marc Palau: Initial implementation (2014)
* *
* *
* LICENSE: zlib/libpng * LICENSE: zlib/libpng
* *
* Copyright (c) 2022-2023 Christoph Wagner (@Crydsch) & Ramon Santamaria (@raysan5) * Copyright (c) 2022-2023 Christoph Wagner (@Crydsch) & 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.
* *
* Permission is granted to anyone to use this software for any purpose, including commercial * 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: * 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 * 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 * 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. * 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 * 2. Altered source versions must be plainly marked as such, and must not be misrepresented
* as being the original software. * as being the original software.
* *
* 3. This notice may not be removed or altered from any source distribution. * 3. This notice may not be removed or altered from any source distribution.
* *
**********************************************************************************************/ **********************************************************************************************/
#ifndef RCAMERA_H #ifndef RCAMERA_H
#define RCAMERA_H #define RCAMERA_H
@ -49,80 +49,86 @@
// Function specifiers in case library is build/used as a shared library (Windows) // Function specifiers in case library is build/used as a shared library (Windows)
// NOTE: Microsoft specifiers to tell compiler that symbols are imported/exported from a .dll // NOTE: Microsoft specifiers to tell compiler that symbols are imported/exported from a .dll
#if defined(_WIN32) #if defined( _WIN32 )
#if defined(BUILD_LIBTYPE_SHARED) #if defined( BUILD_LIBTYPE_SHARED )
#if defined(__TINYC__) #if defined( __TINYC__ )
#define __declspec(x) __attribute__((x)) #define __declspec( x ) __attribute__( ( x ) )
#endif #endif
#define RLAPI __declspec(dllexport) // We are building the library as a Win32 shared library (.dll) #define RLAPI __declspec( dllexport ) // We are building the library as a Win32 shared library (.dll)
#elif defined(USE_LIBTYPE_SHARED) #elif defined( USE_LIBTYPE_SHARED )
#define RLAPI __declspec(dllimport) // We are using the library as a Win32 shared library (.dll) #define RLAPI __declspec( dllimport ) // We are using the library as a Win32 shared library (.dll)
#endif #endif
#endif #endif
#ifndef RLAPI #ifndef RLAPI
#define RLAPI // Functions defined as 'extern' by default (implicit specifiers) #define RLAPI // Functions defined as 'extern' by default (implicit specifiers)
#endif #endif
#if defined(RCAMERA_STANDALONE) #if defined( RCAMERA_STANDALONE )
#define CAMERA_CULL_DISTANCE_NEAR 0.01 #define CAMERA_CULL_DISTANCE_NEAR 0.01
#define CAMERA_CULL_DISTANCE_FAR 1000.0 #define CAMERA_CULL_DISTANCE_FAR 1000.0
#else #else
#define CAMERA_CULL_DISTANCE_NEAR RL_CULL_DISTANCE_NEAR #define CAMERA_CULL_DISTANCE_NEAR RL_CULL_DISTANCE_NEAR
#define CAMERA_CULL_DISTANCE_FAR RL_CULL_DISTANCE_FAR #define CAMERA_CULL_DISTANCE_FAR RL_CULL_DISTANCE_FAR
#endif #endif
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Types and Structures Definition // Types and Structures Definition
// NOTE: Below types are required for standalone usage // NOTE: Below types are required for standalone usage
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
#if defined(RCAMERA_STANDALONE) #if defined( RCAMERA_STANDALONE )
// Vector2, 2 components // Vector2, 2 components
typedef struct Vector2 { typedef struct Vector2
float x; // Vector x component {
float y; // Vector y component float x; // Vector x component
} Vector2; float y; // Vector y component
} Vector2;
// Vector3, 3 components // Vector3, 3 components
typedef struct Vector3 { typedef struct Vector3
float x; // Vector x component {
float y; // Vector y component float x; // Vector x component
float z; // Vector z component float y; // Vector y component
} Vector3; float z; // Vector z component
} Vector3;
// Matrix, 4x4 components, column major, OpenGL style, right-handed // Matrix, 4x4 components, column major, OpenGL style, right-handed
typedef struct Matrix { typedef struct Matrix
float m0, m4, m8, m12; // Matrix first row (4 components) {
float m1, m5, m9, m13; // Matrix second row (4 components) float m0, m4, m8, m12; // Matrix first row (4 components)
float m2, m6, m10, m14; // Matrix third row (4 components) float m1, m5, m9, m13; // Matrix second row (4 components)
float m3, m7, m11, m15; // Matrix fourth row (4 components) float m2, m6, m10, m14; // Matrix third row (4 components)
} Matrix; float m3, m7, m11, m15; // Matrix fourth row (4 components)
} Matrix;
// Camera type, defines a camera position/orientation in 3d space // Camera type, defines a camera position/orientation in 3d space
typedef struct Camera3D { typedef struct Camera3D
Vector3 position; // Camera position {
Vector3 target; // Camera target it looks-at Vector3 position; // Camera position
Vector3 up; // Camera up vector (rotation over its axis) Vector3 target; // Camera target it looks-at
float fovy; // Camera field-of-view apperture in Y (degrees) in perspective, used as near plane width in orthographic Vector3 up; // Camera up vector (rotation over its axis)
int projection; // Camera projection type: CAMERA_PERSPECTIVE or CAMERA_ORTHOGRAPHIC float fovy; // Camera field-of-view apperture in Y (degrees) in perspective, used as near plane width in orthographic
} Camera3D; int projection; // Camera projection type: CAMERA_PERSPECTIVE or CAMERA_ORTHOGRAPHIC
} Camera3D;
typedef Camera3D Camera; // Camera type fallback, defaults to Camera3D typedef Camera3D Camera; // Camera type fallback, defaults to Camera3D
// Camera projection // Camera projection
typedef enum { typedef enum
CAMERA_PERSPECTIVE = 0, // Perspective projection {
CAMERA_ORTHOGRAPHIC // Orthographic projection CAMERA_PERSPECTIVE = 0, // Perspective projection
} CameraProjection; CAMERA_ORTHOGRAPHIC // Orthographic projection
} CameraProjection;
// Camera system modes // Camera system modes
typedef enum { typedef enum
CAMERA_CUSTOM = 0, // Camera custom, controlled by user (UpdateCamera() does nothing) {
CAMERA_FREE, // Camera free mode CAMERA_CUSTOM = 0, // Camera custom, controlled by user (UpdateCamera() does nothing)
CAMERA_ORBITAL, // Camera orbital, around target, zoom supported CAMERA_FREE, // Camera free mode
CAMERA_FIRST_PERSON, // Camera first person CAMERA_ORBITAL, // Camera orbital, around target, zoom supported
CAMERA_THIRD_PERSON // Camera third person CAMERA_FIRST_PERSON, // Camera first person
} CameraMode; CAMERA_THIRD_PERSON // Camera third person
} CameraMode;
#endif #endif
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
@ -134,85 +140,86 @@
// Module Functions Declaration // Module Functions Declaration
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
#if defined(__cplusplus) #if defined( __cplusplus )
extern "C" { // Prevents name mangling of functions extern "C"
{ // Prevents name mangling of functions
#endif #endif
RLAPI Vector3 GetCameraForward(Camera *camera); RLAPI Vector3 GetCameraForward( Camera* camera );
RLAPI Vector3 GetCameraUp(Camera *camera); RLAPI Vector3 GetCameraUp( Camera* camera );
RLAPI Vector3 GetCameraRight(Camera *camera); RLAPI Vector3 GetCameraRight( Camera* camera );
// Camera movement // Camera movement
RLAPI void CameraMoveForward(Camera *camera, float distance, bool moveInWorldPlane); RLAPI void CameraMoveForward( Camera* camera, float distance, bool moveInWorldPlane );
RLAPI void CameraMoveUp(Camera *camera, float distance); RLAPI void CameraMoveUp( Camera* camera, float distance );
RLAPI void CameraMoveRight(Camera *camera, float distance, bool moveInWorldPlane); RLAPI void CameraMoveRight( Camera* camera, float distance, bool moveInWorldPlane );
RLAPI void CameraMoveToTarget(Camera *camera, float delta); RLAPI void CameraMoveToTarget( Camera* camera, float delta );
// Camera rotation // Camera rotation
RLAPI void CameraYaw(Camera *camera, float angle, bool rotateAroundTarget); RLAPI void CameraYaw( Camera* camera, float angle, bool rotateAroundTarget );
RLAPI void CameraPitch(Camera *camera, float angle, bool lockView, bool rotateAroundTarget, bool rotateUp); RLAPI void CameraPitch( Camera* camera, float angle, bool lockView, bool rotateAroundTarget, bool rotateUp );
RLAPI void CameraRoll(Camera *camera, float angle); RLAPI void CameraRoll( Camera* camera, float angle );
RLAPI Matrix GetCameraViewMatrix(Camera *camera); RLAPI Matrix GetCameraViewMatrix( Camera* camera );
RLAPI Matrix GetCameraProjectionMatrix(Camera* camera, float aspect); RLAPI Matrix GetCameraProjectionMatrix( Camera* camera, float aspect );
#if defined(__cplusplus) #if defined( __cplusplus )
} }
#endif #endif
#endif // RCAMERA_H #endif // RCAMERA_H
/*********************************************************************************** /***********************************************************************************
* *
* CAMERA IMPLEMENTATION * CAMERA IMPLEMENTATION
* *
************************************************************************************/ ************************************************************************************/
#if defined(RCAMERA_IMPLEMENTATION) #if defined( RCAMERA_IMPLEMENTATION )
#include "raymath.h" // Required for vector maths: #include "raymath.h" // Required for vector maths:
// Vector3Add() // Vector3Add()
// Vector3Subtract() // Vector3Subtract()
// Vector3Scale() // Vector3Scale()
// Vector3Normalize() // Vector3Normalize()
// Vector3Distance() // Vector3Distance()
// Vector3CrossProduct() // Vector3CrossProduct()
// Vector3RotateByAxisAngle() // Vector3RotateByAxisAngle()
// Vector3Angle() // Vector3Angle()
// Vector3Negate() // Vector3Negate()
// MatrixLookAt() // MatrixLookAt()
// MatrixPerspective() // MatrixPerspective()
// MatrixOrtho() // MatrixOrtho()
// MatrixIdentity() // MatrixIdentity()
// raylib required functionality: // raylib required functionality:
// GetMouseDelta() // GetMouseDelta()
// GetMouseWheelMove() // GetMouseWheelMove()
// IsKeyDown() // IsKeyDown()
// IsKeyPressed() // IsKeyPressed()
// GetFrameTime() // GetFrameTime()
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Defines and Macros // Defines and Macros
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
#define CAMERA_MOVE_SPEED 0.09f #define CAMERA_MOVE_SPEED 0.09f
#define CAMERA_ROTATION_SPEED 0.03f #define CAMERA_ROTATION_SPEED 0.03f
#define CAMERA_PAN_SPEED 0.2f #define CAMERA_PAN_SPEED 0.2f
// Camera mouse movement sensitivity // Camera mouse movement sensitivity
#define CAMERA_MOUSE_MOVE_SENSITIVITY 0.003f // TODO: it should be independant of framerate #define CAMERA_MOUSE_MOVE_SENSITIVITY 0.003f // TODO: it should be independant of framerate
#define CAMERA_MOUSE_SCROLL_SENSITIVITY 1.5f #define CAMERA_MOUSE_SCROLL_SENSITIVITY 1.5f
#define CAMERA_ORBITAL_SPEED 0.5f // Radians per second #define CAMERA_ORBITAL_SPEED 0.5f // Radians per second
#define CAMERA_FIRST_PERSON_STEP_TRIGONOMETRIC_DIVIDER 8.0f #define CAMERA_FIRST_PERSON_STEP_TRIGONOMETRIC_DIVIDER 8.0f
#define CAMERA_FIRST_PERSON_STEP_DIVIDER 30.0f #define CAMERA_FIRST_PERSON_STEP_DIVIDER 30.0f
#define CAMERA_FIRST_PERSON_WAVING_DIVIDER 200.0f #define CAMERA_FIRST_PERSON_WAVING_DIVIDER 200.0f
// PLAYER (used by camera) // PLAYER (used by camera)
#define PLAYER_MOVEMENT_SENSITIVITY 20.0f #define PLAYER_MOVEMENT_SENSITIVITY 20.0f
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Types and Structures Definition // Types and Structures Definition
@ -233,121 +240,122 @@ RLAPI Matrix GetCameraProjectionMatrix(Camera* camera, float aspect);
// Module Functions Definition // Module Functions Definition
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Returns the cameras forward vector (normalized) // Returns the cameras forward vector (normalized)
Vector3 GetCameraForward(Camera *camera) Vector3 GetCameraForward( Camera* camera )
{ {
return Vector3Normalize(Vector3Subtract(camera->target, camera->position)); return Vector3Normalize( Vector3Subtract( camera->target, camera->position ) );
} }
// Returns the cameras up vector (normalized) // Returns the cameras up vector (normalized)
// Note: The up vector might not be perpendicular to the forward vector // Note: The up vector might not be perpendicular to the forward vector
Vector3 GetCameraUp(Camera *camera) Vector3 GetCameraUp( Camera* camera )
{ {
return Vector3Normalize(camera->up); return Vector3Normalize( camera->up );
} }
// Returns the cameras right vector (normalized) // Returns the cameras right vector (normalized)
Vector3 GetCameraRight(Camera *camera) Vector3 GetCameraRight( Camera* camera )
{ {
Vector3 forward = GetCameraForward(camera); Vector3 forward = GetCameraForward( camera );
Vector3 up = GetCameraUp(camera); Vector3 up = GetCameraUp( camera );
return Vector3CrossProduct(forward, up); return Vector3CrossProduct( forward, up );
} }
// Moves the camera in its forward direction // Moves the camera in its forward direction
void CameraMoveForward(Camera *camera, float distance, bool moveInWorldPlane) void CameraMoveForward( Camera* camera, float distance, bool moveInWorldPlane )
{ {
Vector3 forward = GetCameraForward(camera); Vector3 forward = GetCameraForward( camera );
if (moveInWorldPlane) if ( moveInWorldPlane )
{ {
// Project vector onto world plane // Project vector onto world plane
forward.y = 0; forward.y = 0;
forward = Vector3Normalize(forward); forward = Vector3Normalize( forward );
} }
// Scale by distance // Scale by distance
forward = Vector3Scale(forward, distance); forward = Vector3Scale( forward, distance );
// Move position and target // Move position and target
camera->position = Vector3Add(camera->position, forward); camera->position = Vector3Add( camera->position, forward );
camera->target = Vector3Add(camera->target, forward); camera->target = Vector3Add( camera->target, forward );
} }
// Moves the camera in its up direction // Moves the camera in its up direction
void CameraMoveUp(Camera *camera, float distance) void CameraMoveUp( Camera* camera, float distance )
{ {
Vector3 up = GetCameraUp(camera); Vector3 up = GetCameraUp( camera );
// Scale by distance // Scale by distance
up = Vector3Scale(up, distance); up = Vector3Scale( up, distance );
// Move position and target // Move position and target
camera->position = Vector3Add(camera->position, up); camera->position = Vector3Add( camera->position, up );
camera->target = Vector3Add(camera->target, up); camera->target = Vector3Add( camera->target, up );
} }
// Moves the camera target in its current right direction // Moves the camera target in its current right direction
void CameraMoveRight(Camera *camera, float distance, bool moveInWorldPlane) void CameraMoveRight( Camera* camera, float distance, bool moveInWorldPlane )
{ {
Vector3 right = GetCameraRight(camera); Vector3 right = GetCameraRight( camera );
if (moveInWorldPlane) if ( moveInWorldPlane )
{ {
// Project vector onto world plane // Project vector onto world plane
right.y = 0; right.y = 0;
right = Vector3Normalize(right); right = Vector3Normalize( right );
} }
// Scale by distance // Scale by distance
right = Vector3Scale(right, distance); right = Vector3Scale( right, distance );
// Move position and target // Move position and target
camera->position = Vector3Add(camera->position, right); camera->position = Vector3Add( camera->position, right );
camera->target = Vector3Add(camera->target, right); camera->target = Vector3Add( camera->target, right );
} }
// Moves the camera position closer/farther to/from the camera target // Moves the camera position closer/farther to/from the camera target
void CameraMoveToTarget(Camera *camera, float delta) void CameraMoveToTarget( Camera* camera, float delta )
{ {
float distance = Vector3Distance(camera->position, camera->target); float distance = Vector3Distance( camera->position, camera->target );
// Apply delta // Apply delta
distance += delta; distance += delta;
// Distance must be greater than 0 // Distance must be greater than 0
if (distance <= 0) distance = 0.001f; if ( distance <= 0 )
distance = 0.001f;
// Set new distance by moving the position along the forward vector // Set new distance by moving the position along the forward vector
Vector3 forward = GetCameraForward(camera); Vector3 forward = GetCameraForward( camera );
camera->position = Vector3Add(camera->target, Vector3Scale(forward, -distance)); camera->position = Vector3Add( camera->target, Vector3Scale( forward, -distance ) );
} }
// Rotates the camera around its up vector // Rotates the camera around its up vector
// Yaw is "looking left and right" // Yaw is "looking left and right"
// If rotateAroundTarget is false, the camera rotates around its position // If rotateAroundTarget is false, the camera rotates around its position
// Note: angle must be provided in radians // Note: angle must be provided in radians
void CameraYaw(Camera *camera, float angle, bool rotateAroundTarget) void CameraYaw( Camera* camera, float angle, bool rotateAroundTarget )
{ {
// Rotation axis // Rotation axis
Vector3 up = GetCameraUp(camera); Vector3 up = GetCameraUp( camera );
// View vector // View vector
Vector3 targetPosition = Vector3Subtract(camera->target, camera->position); Vector3 targetPosition = Vector3Subtract( camera->target, camera->position );
// Rotate view vector around up axis // Rotate view vector around up axis
targetPosition = Vector3RotateByAxisAngle(targetPosition, up, angle); targetPosition = Vector3RotateByAxisAngle( targetPosition, up, angle );
if (rotateAroundTarget) if ( rotateAroundTarget )
{ {
// Move position relative to target // Move position relative to target
camera->position = Vector3Subtract(camera->target, targetPosition); camera->position = Vector3Subtract( camera->target, targetPosition );
} }
else // rotate around camera.position else // rotate around camera.position
{ {
// Move target relative to position // Move target relative to position
camera->target = Vector3Add(camera->position, targetPosition); camera->target = Vector3Add( camera->position, targetPosition );
} }
} }
// Rotates the camera around its right vector, pitch is "looking up and down" // Rotates the camera around its right vector, pitch is "looking up and down"
@ -355,204 +363,234 @@ void CameraYaw(Camera *camera, float angle, bool rotateAroundTarget)
// - rotateAroundTarget defines if rotation is around target or around its position // - rotateAroundTarget defines if rotation is around target or around its position
// - rotateUp rotates the up direction as well (typically only usefull in CAMERA_FREE) // - rotateUp rotates the up direction as well (typically only usefull in CAMERA_FREE)
// NOTE: angle must be provided in radians // NOTE: angle must be provided in radians
void CameraPitch(Camera *camera, float angle, bool lockView, bool rotateAroundTarget, bool rotateUp) void CameraPitch( Camera* camera, float angle, bool lockView, bool rotateAroundTarget, bool rotateUp )
{ {
// Up direction // Up direction
Vector3 up = GetCameraUp(camera); Vector3 up = GetCameraUp( camera );
// View vector // View vector
Vector3 targetPosition = Vector3Subtract(camera->target, camera->position); Vector3 targetPosition = Vector3Subtract( camera->target, camera->position );
if (lockView) if ( lockView )
{ {
// In these camera modes we clamp the Pitch angle // In these camera modes we clamp the Pitch angle
// to allow only viewing straight up or down. // to allow only viewing straight up or down.
// Clamp view up // Clamp view up
float maxAngleUp = Vector3Angle(up, targetPosition); float maxAngleUp = Vector3Angle( up, targetPosition );
maxAngleUp -= 0.001f; // avoid numerical errors maxAngleUp -= 0.001f; // avoid numerical errors
if (angle > maxAngleUp) angle = maxAngleUp; if ( angle > maxAngleUp )
angle = maxAngleUp;
// Clamp view down // Clamp view down
float maxAngleDown = Vector3Angle(Vector3Negate(up), targetPosition); float maxAngleDown = Vector3Angle( Vector3Negate( up ), targetPosition );
maxAngleDown *= -1.0f; // downwards angle is negative maxAngleDown *= -1.0f; // downwards angle is negative
maxAngleDown += 0.001f; // avoid numerical errors maxAngleDown += 0.001f; // avoid numerical errors
if (angle < maxAngleDown) angle = maxAngleDown; if ( angle < maxAngleDown )
} angle = maxAngleDown;
}
// Rotation axis // Rotation axis
Vector3 right = GetCameraRight(camera); Vector3 right = GetCameraRight( camera );
// Rotate view vector around right axis // Rotate view vector around right axis
targetPosition = Vector3RotateByAxisAngle(targetPosition, right, angle); targetPosition = Vector3RotateByAxisAngle( targetPosition, right, angle );
if (rotateAroundTarget) if ( rotateAroundTarget )
{ {
// Move position relative to target // Move position relative to target
camera->position = Vector3Subtract(camera->target, targetPosition); camera->position = Vector3Subtract( camera->target, targetPosition );
} }
else // rotate around camera.position else // rotate around camera.position
{ {
// Move target relative to position // Move target relative to position
camera->target = Vector3Add(camera->position, targetPosition); camera->target = Vector3Add( camera->position, targetPosition );
} }
if (rotateUp) if ( rotateUp )
{ {
// Rotate up direction around right axis // Rotate up direction around right axis
camera->up = Vector3RotateByAxisAngle(camera->up, right, angle); camera->up = Vector3RotateByAxisAngle( camera->up, right, angle );
} }
} }
// Rotates the camera around its forward vector // Rotates the camera around its forward vector
// Roll is "turning your head sideways to the left or right" // Roll is "turning your head sideways to the left or right"
// Note: angle must be provided in radians // Note: angle must be provided in radians
void CameraRoll(Camera *camera, float angle) void CameraRoll( Camera* camera, float angle )
{ {
// Rotation axis // Rotation axis
Vector3 forward = GetCameraForward(camera); Vector3 forward = GetCameraForward( camera );
// Rotate up direction around forward axis // Rotate up direction around forward axis
camera->up = Vector3RotateByAxisAngle(camera->up, forward, angle); camera->up = Vector3RotateByAxisAngle( camera->up, forward, angle );
} }
// Returns the camera view matrix // Returns the camera view matrix
Matrix GetCameraViewMatrix(Camera *camera) Matrix GetCameraViewMatrix( Camera* camera )
{ {
return MatrixLookAt(camera->position, camera->target, camera->up); return MatrixLookAt( camera->position, camera->target, camera->up );
} }
// Returns the camera projection matrix // Returns the camera projection matrix
Matrix GetCameraProjectionMatrix(Camera *camera, float aspect) Matrix GetCameraProjectionMatrix( Camera* camera, float aspect )
{ {
if (camera->projection == CAMERA_PERSPECTIVE) if ( camera->projection == CAMERA_PERSPECTIVE )
{ {
return MatrixPerspective(camera->fovy*DEG2RAD, aspect, CAMERA_CULL_DISTANCE_NEAR, CAMERA_CULL_DISTANCE_FAR); return MatrixPerspective( camera->fovy * DEG2RAD, aspect, CAMERA_CULL_DISTANCE_NEAR, CAMERA_CULL_DISTANCE_FAR );
} }
else if (camera->projection == CAMERA_ORTHOGRAPHIC) else if ( camera->projection == CAMERA_ORTHOGRAPHIC )
{ {
double top = camera->fovy/2.0; double top = camera->fovy / 2.0;
double right = top*aspect; double right = top * aspect;
return MatrixOrtho(-right, right, -top, top, CAMERA_CULL_DISTANCE_NEAR, CAMERA_CULL_DISTANCE_FAR); return MatrixOrtho( -right, right, -top, top, CAMERA_CULL_DISTANCE_NEAR, CAMERA_CULL_DISTANCE_FAR );
} }
return MatrixIdentity(); return MatrixIdentity();
} }
#if !defined(RCAMERA_STANDALONE) #if ! defined( RCAMERA_STANDALONE )
// Update camera position for selected mode // Update camera position for selected mode
// Camera mode: CAMERA_FREE, CAMERA_FIRST_PERSON, CAMERA_THIRD_PERSON, CAMERA_ORBITAL or CUSTOM // Camera mode: CAMERA_FREE, CAMERA_FIRST_PERSON, CAMERA_THIRD_PERSON, CAMERA_ORBITAL or CUSTOM
void UpdateCamera(Camera *camera, int mode) void UpdateCamera( Camera* camera, int mode )
{ {
Vector2 mousePositionDelta = GetMouseDelta(); Vector2 mousePositionDelta = GetMouseDelta();
bool moveInWorldPlane = ((mode == CAMERA_FIRST_PERSON) || (mode == CAMERA_THIRD_PERSON)); bool moveInWorldPlane = ( ( mode == CAMERA_FIRST_PERSON ) || ( mode == CAMERA_THIRD_PERSON ) );
bool rotateAroundTarget = ((mode == CAMERA_THIRD_PERSON) || (mode == CAMERA_ORBITAL)); bool rotateAroundTarget = ( ( mode == CAMERA_THIRD_PERSON ) || ( mode == CAMERA_ORBITAL ) );
bool lockView = ((mode == CAMERA_FIRST_PERSON) || (mode == CAMERA_THIRD_PERSON) || (mode == CAMERA_ORBITAL)); bool lockView = ( ( mode == CAMERA_FIRST_PERSON ) || ( mode == CAMERA_THIRD_PERSON ) || ( mode == CAMERA_ORBITAL ) );
bool rotateUp = false; bool rotateUp = false;
if (mode == CAMERA_ORBITAL) if ( mode == CAMERA_ORBITAL )
{ {
// Orbital can just orbit // Orbital can just orbit
Matrix rotation = MatrixRotate(GetCameraUp(camera), CAMERA_ORBITAL_SPEED*GetFrameTime()); Matrix rotation = MatrixRotate( GetCameraUp( camera ), CAMERA_ORBITAL_SPEED * GetFrameTime() );
Vector3 view = Vector3Subtract(camera->position, camera->target); Vector3 view = Vector3Subtract( camera->position, camera->target );
view = Vector3Transform(view, rotation); view = Vector3Transform( view, rotation );
camera->position = Vector3Add(camera->target, view); camera->position = Vector3Add( camera->target, view );
} }
else else
{ {
// Camera rotation // Camera rotation
if (IsKeyDown(KEY_DOWN)) CameraPitch(camera, -CAMERA_ROTATION_SPEED, lockView, rotateAroundTarget, rotateUp); if ( IsKeyDown( KEY_DOWN ) )
if (IsKeyDown(KEY_UP)) CameraPitch(camera, CAMERA_ROTATION_SPEED, lockView, rotateAroundTarget, rotateUp); CameraPitch( camera, -CAMERA_ROTATION_SPEED, lockView, rotateAroundTarget, rotateUp );
if (IsKeyDown(KEY_RIGHT)) CameraYaw(camera, -CAMERA_ROTATION_SPEED, rotateAroundTarget); if ( IsKeyDown( KEY_UP ) )
if (IsKeyDown(KEY_LEFT)) CameraYaw(camera, CAMERA_ROTATION_SPEED, rotateAroundTarget); CameraPitch( camera, CAMERA_ROTATION_SPEED, lockView, rotateAroundTarget, rotateUp );
if (IsKeyDown(KEY_Q)) CameraRoll(camera, -CAMERA_ROTATION_SPEED); if ( IsKeyDown( KEY_RIGHT ) )
if (IsKeyDown(KEY_E)) CameraRoll(camera, CAMERA_ROTATION_SPEED); CameraYaw( camera, -CAMERA_ROTATION_SPEED, rotateAroundTarget );
if ( IsKeyDown( KEY_LEFT ) )
CameraYaw( camera, CAMERA_ROTATION_SPEED, rotateAroundTarget );
if ( IsKeyDown( KEY_Q ) )
CameraRoll( camera, -CAMERA_ROTATION_SPEED );
if ( IsKeyDown( KEY_E ) )
CameraRoll( camera, CAMERA_ROTATION_SPEED );
// Camera movement // Camera movement
if (!IsGamepadAvailable(0)) if ( ! IsGamepadAvailable( 0 ) )
{ {
// Camera pan (for CAMERA_FREE) // Camera pan (for CAMERA_FREE)
if ((mode == CAMERA_FREE) && (IsMouseButtonDown(MOUSE_BUTTON_MIDDLE))) if ( ( mode == CAMERA_FREE ) && ( IsMouseButtonDown( MOUSE_BUTTON_MIDDLE ) ) )
{ {
const Vector2 mouseDelta = GetMouseDelta(); const Vector2 mouseDelta = GetMouseDelta();
if (mouseDelta.x > 0.0f) CameraMoveRight(camera, CAMERA_PAN_SPEED, moveInWorldPlane); if ( mouseDelta.x > 0.0f )
if (mouseDelta.x < 0.0f) CameraMoveRight(camera, -CAMERA_PAN_SPEED, moveInWorldPlane); CameraMoveRight( camera, CAMERA_PAN_SPEED, moveInWorldPlane );
if (mouseDelta.y > 0.0f) CameraMoveUp(camera, -CAMERA_PAN_SPEED); if ( mouseDelta.x < 0.0f )
if (mouseDelta.y < 0.0f) CameraMoveUp(camera, CAMERA_PAN_SPEED); CameraMoveRight( camera, -CAMERA_PAN_SPEED, moveInWorldPlane );
} if ( mouseDelta.y > 0.0f )
else CameraMoveUp( camera, -CAMERA_PAN_SPEED );
{ if ( mouseDelta.y < 0.0f )
// Mouse support CameraMoveUp( camera, CAMERA_PAN_SPEED );
CameraYaw(camera, -mousePositionDelta.x*CAMERA_MOUSE_MOVE_SENSITIVITY, rotateAroundTarget); }
CameraPitch(camera, -mousePositionDelta.y*CAMERA_MOUSE_MOVE_SENSITIVITY, lockView, rotateAroundTarget, rotateUp); else
} {
// Mouse support
CameraYaw( camera, -mousePositionDelta.x * CAMERA_MOUSE_MOVE_SENSITIVITY, rotateAroundTarget );
CameraPitch( camera, -mousePositionDelta.y * CAMERA_MOUSE_MOVE_SENSITIVITY, lockView, rotateAroundTarget, rotateUp );
}
// Keyboard support // Keyboard support
if (IsKeyDown(KEY_W)) CameraMoveForward(camera, CAMERA_MOVE_SPEED, moveInWorldPlane); if ( IsKeyDown( KEY_W ) )
if (IsKeyDown(KEY_A)) CameraMoveRight(camera, -CAMERA_MOVE_SPEED, moveInWorldPlane); CameraMoveForward( camera, CAMERA_MOVE_SPEED, moveInWorldPlane );
if (IsKeyDown(KEY_S)) CameraMoveForward(camera, -CAMERA_MOVE_SPEED, moveInWorldPlane); if ( IsKeyDown( KEY_A ) )
if (IsKeyDown(KEY_D)) CameraMoveRight(camera, CAMERA_MOVE_SPEED, moveInWorldPlane); CameraMoveRight( camera, -CAMERA_MOVE_SPEED, moveInWorldPlane );
} if ( IsKeyDown( KEY_S ) )
else CameraMoveForward( camera, -CAMERA_MOVE_SPEED, moveInWorldPlane );
{ if ( IsKeyDown( KEY_D ) )
// Gamepad controller support CameraMoveRight( camera, CAMERA_MOVE_SPEED, moveInWorldPlane );
CameraYaw(camera, -(GetGamepadAxisMovement(0, GAMEPAD_AXIS_RIGHT_X) * 2)*CAMERA_MOUSE_MOVE_SENSITIVITY, rotateAroundTarget); }
CameraPitch(camera, -(GetGamepadAxisMovement(0, GAMEPAD_AXIS_RIGHT_Y) * 2)*CAMERA_MOUSE_MOVE_SENSITIVITY, lockView, rotateAroundTarget, rotateUp); else
{
// Gamepad controller support
CameraYaw( camera, -( GetGamepadAxisMovement( 0, GAMEPAD_AXIS_RIGHT_X ) * 2 ) * CAMERA_MOUSE_MOVE_SENSITIVITY, rotateAroundTarget );
CameraPitch(
camera,
-( GetGamepadAxisMovement( 0, GAMEPAD_AXIS_RIGHT_Y ) * 2 ) * CAMERA_MOUSE_MOVE_SENSITIVITY,
lockView,
rotateAroundTarget,
rotateUp
);
if (GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_Y) <= -0.25f) CameraMoveForward(camera, CAMERA_MOVE_SPEED, moveInWorldPlane); if ( GetGamepadAxisMovement( 0, GAMEPAD_AXIS_LEFT_Y ) <= -0.25f )
if (GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_X) <= -0.25f) CameraMoveRight(camera, -CAMERA_MOVE_SPEED, moveInWorldPlane); CameraMoveForward( camera, CAMERA_MOVE_SPEED, moveInWorldPlane );
if (GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_Y) >= 0.25f) CameraMoveForward(camera, -CAMERA_MOVE_SPEED, moveInWorldPlane); if ( GetGamepadAxisMovement( 0, GAMEPAD_AXIS_LEFT_X ) <= -0.25f )
if (GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_X) >= 0.25f) CameraMoveRight(camera, CAMERA_MOVE_SPEED, moveInWorldPlane); CameraMoveRight( camera, -CAMERA_MOVE_SPEED, moveInWorldPlane );
} if ( GetGamepadAxisMovement( 0, GAMEPAD_AXIS_LEFT_Y ) >= 0.25f )
CameraMoveForward( camera, -CAMERA_MOVE_SPEED, moveInWorldPlane );
if ( GetGamepadAxisMovement( 0, GAMEPAD_AXIS_LEFT_X ) >= 0.25f )
CameraMoveRight( camera, CAMERA_MOVE_SPEED, moveInWorldPlane );
}
if (mode == CAMERA_FREE) if ( mode == CAMERA_FREE )
{ {
if (IsKeyDown(KEY_SPACE)) CameraMoveUp(camera, CAMERA_MOVE_SPEED); if ( IsKeyDown( KEY_SPACE ) )
if (IsKeyDown(KEY_LEFT_CONTROL)) CameraMoveUp(camera, -CAMERA_MOVE_SPEED); CameraMoveUp( camera, CAMERA_MOVE_SPEED );
} if ( IsKeyDown( KEY_LEFT_CONTROL ) )
} CameraMoveUp( camera, -CAMERA_MOVE_SPEED );
}
}
if ((mode == CAMERA_THIRD_PERSON) || (mode == CAMERA_ORBITAL) || (mode == CAMERA_FREE)) if ( ( mode == CAMERA_THIRD_PERSON ) || ( mode == CAMERA_ORBITAL ) || ( mode == CAMERA_FREE ) )
{ {
// Zoom target distance // Zoom target distance
CameraMoveToTarget(camera, -GetMouseWheelMove()); CameraMoveToTarget( camera, -GetMouseWheelMove() );
if (IsKeyPressed(KEY_KP_SUBTRACT)) CameraMoveToTarget(camera, 2.0f); if ( IsKeyPressed( KEY_KP_SUBTRACT ) )
if (IsKeyPressed(KEY_KP_ADD)) CameraMoveToTarget(camera, -2.0f); CameraMoveToTarget( camera, 2.0f );
} if ( IsKeyPressed( KEY_KP_ADD ) )
CameraMoveToTarget( camera, -2.0f );
}
} }
#endif // !RCAMERA_STANDALONE #endif // !RCAMERA_STANDALONE
// Update camera movement, movement/rotation values should be provided by user // Update camera movement, movement/rotation values should be provided by user
void UpdateCameraPro(Camera *camera, Vector3 movement, Vector3 rotation, float zoom) void UpdateCameraPro( Camera* camera, Vector3 movement, Vector3 rotation, float zoom )
{ {
// Required values // Required values
// movement.x - Move forward/backward // movement.x - Move forward/backward
// movement.y - Move right/left // movement.y - Move right/left
// movement.z - Move up/down // movement.z - Move up/down
// rotation.x - yaw // rotation.x - yaw
// rotation.y - pitch // rotation.y - pitch
// rotation.z - roll // rotation.z - roll
// zoom - Move towards target // zoom - Move towards target
bool lockView = true; bool lockView = true;
bool rotateAroundTarget = false; bool rotateAroundTarget = false;
bool rotateUp = false; bool rotateUp = false;
bool moveInWorldPlane = true; bool moveInWorldPlane = true;
// Camera rotation // Camera rotation
CameraPitch(camera, -rotation.y*DEG2RAD, lockView, rotateAroundTarget, rotateUp); CameraPitch( camera, -rotation.y * DEG2RAD, lockView, rotateAroundTarget, rotateUp );
CameraYaw(camera, -rotation.x*DEG2RAD, rotateAroundTarget); CameraYaw( camera, -rotation.x * DEG2RAD, rotateAroundTarget );
CameraRoll(camera, rotation.z*DEG2RAD); CameraRoll( camera, rotation.z * DEG2RAD );
// Camera movement // Camera movement
CameraMoveForward(camera, movement.x, moveInWorldPlane); CameraMoveForward( camera, movement.x, moveInWorldPlane );
CameraMoveRight(camera, movement.y, moveInWorldPlane); CameraMoveRight( camera, movement.y, moveInWorldPlane );
CameraMoveUp(camera, movement.z); CameraMoveUp( camera, movement.z );
// Zoom target distance // Zoom target distance
CameraMoveToTarget(camera, zoom); CameraMoveToTarget( camera, zoom );
} }
#endif // RCAMERA_IMPLEMENTATION #endif // RCAMERA_IMPLEMENTATION

View File

@ -1,204 +1,228 @@
/********************************************************************************************** /**********************************************************************************************
* *
* rcore - Common types and globals (all platforms) * rcore - Common types and globals (all platforms)
* *
* LIMITATIONS: * LIMITATIONS:
* - Limitation 01 * - Limitation 01
* - Limitation 02 * - Limitation 02
* *
* POSSIBLE IMPROVEMENTS: * POSSIBLE IMPROVEMENTS:
* - Improvement 01 * - Improvement 01
* - Improvement 02 * - Improvement 02
* *
* *
* LICENSE: zlib/libpng * LICENSE: zlib/libpng
* *
* Copyright (c) 2013-2023 Ramon Santamaria (@raysan5) and contributors * Copyright (c) 2013-2023 Ramon Santamaria (@raysan5) and contributors
* *
* 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.
* *
* Permission is granted to anyone to use this software for any purpose, including commercial * 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: * 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 * 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 * 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. * 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 * 2. Altered source versions must be plainly marked as such, and must not be misrepresented
* as being the original software. * as being the original software.
* *
* 3. This notice may not be removed or altered from any source distribution. * 3. This notice may not be removed or altered from any source distribution.
* *
**********************************************************************************************/ **********************************************************************************************/
#ifndef RCORE_H #ifndef RCORE_H
#define RCORE_H #define RCORE_H
#include "raylib.h" #include "raylib.h"
#include "utils.h" // Required for: TRACELOG() macros #include "utils.h" // Required for: TRACELOG() macros
#include "rlgl.h" // Required for: graphics layer functionality #include "rlgl.h" // Required for: graphics layer functionality
#define RAYMATH_IMPLEMENTATION #define RAYMATH_IMPLEMENTATION
#include "raymath.h" // Required for: Vector2/Vector3/Matrix functionality #include "raymath.h" // Required for: Vector2/Vector3/Matrix functionality
#include <stdlib.h> // Required for: srand(), rand(), atexit() #include <stdlib.h> // Required for: srand(), rand(), atexit()
#include <stdio.h> // Required for: sprintf() [Used in OpenURL()] #include <stdio.h> // Required for: sprintf() [Used in OpenURL()]
#include <string.h> // Required for: strrchr(), strcmp(), strlen(), memset() #include <string.h> // Required for: strrchr(), strcmp(), strlen(), memset()
#include <time.h> // Required for: time() [Used in InitTimer()] #include <time.h> // Required for: time() [Used in InitTimer()]
#include <math.h> // Required for: tan() [Used in BeginMode3D()], atan2f() [Used in LoadVrStereoConfig()] #include <math.h> // Required for: tan() [Used in BeginMode3D()], atan2f() [Used in LoadVrStereoConfig()]
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Defines and Macros // Defines and Macros
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
#ifndef MAX_FILEPATH_CAPACITY #ifndef MAX_FILEPATH_CAPACITY
#define MAX_FILEPATH_CAPACITY 8192 // Maximum capacity for filepath #define MAX_FILEPATH_CAPACITY 8192 // Maximum capacity for filepath
#endif #endif
#ifndef MAX_FILEPATH_LENGTH #ifndef MAX_FILEPATH_LENGTH
#define MAX_FILEPATH_LENGTH 4096 // Maximum length for filepaths (Linux PATH_MAX default value) #define MAX_FILEPATH_LENGTH 4096 // Maximum length for filepaths (Linux PATH_MAX default value)
#endif #endif
#ifndef MAX_KEYBOARD_KEYS #ifndef MAX_KEYBOARD_KEYS
#define MAX_KEYBOARD_KEYS 512 // Maximum number of keyboard keys supported #define MAX_KEYBOARD_KEYS 512 // Maximum number of keyboard keys supported
#endif #endif
#ifndef MAX_MOUSE_BUTTONS #ifndef MAX_MOUSE_BUTTONS
#define MAX_MOUSE_BUTTONS 8 // Maximum number of mouse buttons supported #define MAX_MOUSE_BUTTONS 8 // Maximum number of mouse buttons supported
#endif #endif
#ifndef MAX_GAMEPADS #ifndef MAX_GAMEPADS
#define MAX_GAMEPADS 4 // Maximum number of gamepads supported #define MAX_GAMEPADS 4 // Maximum number of gamepads supported
#endif #endif
#ifndef MAX_GAMEPAD_AXIS #ifndef MAX_GAMEPAD_AXIS
#define MAX_GAMEPAD_AXIS 8 // Maximum number of axis supported (per gamepad) #define MAX_GAMEPAD_AXIS 8 // Maximum number of axis supported (per gamepad)
#endif #endif
#ifndef MAX_GAMEPAD_BUTTONS #ifndef MAX_GAMEPAD_BUTTONS
#define MAX_GAMEPAD_BUTTONS 32 // Maximum number of buttons supported (per gamepad) #define MAX_GAMEPAD_BUTTONS 32 // Maximum number of buttons supported (per gamepad)
#endif #endif
#ifndef MAX_TOUCH_POINTS #ifndef MAX_TOUCH_POINTS
#define MAX_TOUCH_POINTS 8 // Maximum number of touch points supported #define MAX_TOUCH_POINTS 8 // Maximum number of touch points supported
#endif #endif
#ifndef MAX_KEY_PRESSED_QUEUE #ifndef MAX_KEY_PRESSED_QUEUE
#define MAX_KEY_PRESSED_QUEUE 16 // Maximum number of keys in the key input queue #define MAX_KEY_PRESSED_QUEUE 16 // Maximum number of keys in the key input queue
#endif #endif
#ifndef MAX_CHAR_PRESSED_QUEUE #ifndef MAX_CHAR_PRESSED_QUEUE
#define MAX_CHAR_PRESSED_QUEUE 16 // Maximum number of characters in the char input queue #define MAX_CHAR_PRESSED_QUEUE 16 // Maximum number of characters in the char input queue
#endif #endif
#ifndef MAX_DECOMPRESSION_SIZE #ifndef MAX_DECOMPRESSION_SIZE
#define MAX_DECOMPRESSION_SIZE 64 // Maximum size allocated for decompression in MB #define MAX_DECOMPRESSION_SIZE 64 // Maximum size allocated for decompression in MB
#endif #endif
// Flags operation macros // Flags operation macros
#define FLAG_SET(n, f) ((n) |= (f)) #define FLAG_SET( n, f ) ( ( n ) |= ( f ) )
#define FLAG_CLEAR(n, f) ((n) &= ~(f)) #define FLAG_CLEAR( n, f ) ( ( n ) &= ~( f ) )
#define FLAG_TOGGLE(n, f) ((n) ^= (f)) #define FLAG_TOGGLE( n, f ) ( ( n ) ^= ( f ) )
#define FLAG_CHECK(n, f) ((n) & (f)) #define FLAG_CHECK( n, f ) ( ( n ) & ( f ) )
#if (defined(__linux__) || defined(PLATFORM_WEB)) && (_POSIX_C_SOURCE < 199309L) #if ( defined( __linux__ ) || defined( PLATFORM_WEB ) ) && ( _POSIX_C_SOURCE < 199309L )
#undef _POSIX_C_SOURCE #undef _POSIX_C_SOURCE
#define _POSIX_C_SOURCE 199309L // Required for: CLOCK_MONOTONIC if compiled with c99 without gnu ext. #define _POSIX_C_SOURCE 199309L // Required for: CLOCK_MONOTONIC if compiled with c99 without gnu ext.
#endif #endif
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Types and Structures Definition // Types and Structures Definition
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
typedef struct { int x; int y; } Point; typedef struct
typedef struct { unsigned int width; unsigned int height; } Size; {
int x;
int y;
} Point;
typedef struct
{
unsigned int width;
unsigned int height;
} Size;
// Core global state context data // Core global state context data
typedef struct CoreData { typedef struct CoreData
struct { {
const char *title; // Window text title const pointer struct
unsigned int flags; // Configuration flags (bit based), keeps window state {
bool ready; // Check if window has been initialized successfully const char* title; // Window text title const pointer
bool fullscreen; // Check if fullscreen mode is enabled unsigned int flags; // Configuration flags (bit based), keeps window state
bool shouldClose; // Check if window set for closing bool ready; // Check if window has been initialized successfully
bool resizedLastFrame; // Check if window has been resized last frame bool fullscreen; // Check if fullscreen mode is enabled
bool eventWaiting; // Wait for events before ending frame bool shouldClose; // Check if window set for closing
bool resizedLastFrame; // Check if window has been resized last frame
bool eventWaiting; // Wait for events before ending frame
Point position; // Window position (required on fullscreen toggle) Point position; // Window position (required on fullscreen toggle)
Point previousPosition; // Window previous position (required on borderless windowed toggle) Point previousPosition; // Window previous position (required on borderless windowed toggle)
Size display; // Display width and height (monitor, device-screen, LCD, ...) Size display; // Display width and height (monitor, device-screen, LCD, ...)
Size screen; // Screen width and height (used render area) Size screen; // Screen width and height (used render area)
Size previousScreen; // Screen previous width and height (required on borderless windowed toggle) Size previousScreen; // Screen previous width and height (required on borderless windowed toggle)
Size currentFbo; // Current render width and height (depends on active fbo) Size currentFbo; // Current render width and height (depends on active fbo)
Size render; // Framebuffer width and height (render area, including black bars if required) Size render; // Framebuffer width and height (render area, including black bars if required)
Point renderOffset; // Offset from render area (must be divided by 2) Point renderOffset; // Offset from render area (must be divided by 2)
Size screenMin; // Screen minimum width and height (for resizable window) Size screenMin; // Screen minimum width and height (for resizable window)
Size screenMax; // Screen maximum width and height (for resizable window) Size screenMax; // Screen maximum width and height (for resizable window)
Matrix screenScale; // Matrix to scale screen (framebuffer rendering) Matrix screenScale; // Matrix to scale screen (framebuffer rendering)
char **dropFilepaths; // Store dropped files paths pointers (provided by GLFW) char** dropFilepaths; // Store dropped files paths pointers (provided by GLFW)
unsigned int dropFileCount; // Count dropped files strings unsigned int dropFileCount; // Count dropped files strings
} Window; } Window;
struct {
const char *basePath; // Base path for data storage
} Storage; struct
struct { {
struct { const char* basePath; // Base path for data storage
int exitKey; // Default exit key
char currentKeyState[MAX_KEYBOARD_KEYS]; // Registers current frame key state
char previousKeyState[MAX_KEYBOARD_KEYS]; // Registers previous frame key state
// NOTE: Since key press logic involves comparing prev vs cur key state, we need to handle key repeats specially } Storage;
char keyRepeatInFrame[MAX_KEYBOARD_KEYS]; // Registers key repeats for current frame.
int keyPressedQueue[MAX_KEY_PRESSED_QUEUE]; // Input keys queue struct
int keyPressedQueueCount; // Input keys queue count {
struct
{
int exitKey; // Default exit key
char currentKeyState[ MAX_KEYBOARD_KEYS ]; // Registers current frame key state
char previousKeyState[ MAX_KEYBOARD_KEYS ]; // Registers previous frame key state
int charPressedQueue[MAX_CHAR_PRESSED_QUEUE]; // Input characters queue (unicode) // NOTE: Since key press logic involves comparing prev vs cur key state, we need to handle key repeats specially
int charPressedQueueCount; // Input characters queue count char keyRepeatInFrame[ MAX_KEYBOARD_KEYS ]; // Registers key repeats for current frame.
} Keyboard; int keyPressedQueue[ MAX_KEY_PRESSED_QUEUE ]; // Input keys queue
struct { int keyPressedQueueCount; // Input keys queue count
Vector2 offset; // Mouse offset
Vector2 scale; // Mouse scaling
Vector2 currentPosition; // Mouse position on screen
Vector2 previousPosition; // Previous mouse position
int cursor; // Tracks current mouse cursor int charPressedQueue[ MAX_CHAR_PRESSED_QUEUE ]; // Input characters queue (unicode)
bool cursorHidden; // Track if cursor is hidden int charPressedQueueCount; // Input characters queue count
bool cursorOnScreen; // Tracks if cursor is inside client area
char currentButtonState[MAX_MOUSE_BUTTONS]; // Registers current mouse button state } Keyboard;
char previousButtonState[MAX_MOUSE_BUTTONS]; // Registers previous mouse button state
Vector2 currentWheelMove; // Registers current mouse wheel variation
Vector2 previousWheelMove; // Registers previous mouse wheel variation
} Mouse; struct
struct { {
int pointCount; // Number of touch points active Vector2 offset; // Mouse offset
int pointId[MAX_TOUCH_POINTS]; // Point identifiers Vector2 scale; // Mouse scaling
Vector2 position[MAX_TOUCH_POINTS]; // Touch position on screen Vector2 currentPosition; // Mouse position on screen
char currentTouchState[MAX_TOUCH_POINTS]; // Registers current touch state Vector2 previousPosition; // Previous mouse position
char previousTouchState[MAX_TOUCH_POINTS]; // Registers previous touch state
} Touch; int cursor; // Tracks current mouse cursor
struct { bool cursorHidden; // Track if cursor is hidden
int lastButtonPressed; // Register last gamepad button pressed bool cursorOnScreen; // Tracks if cursor is inside client area
int axisCount[MAX_GAMEPADS]; // Register number of available gamepad axis
bool ready[MAX_GAMEPADS]; // Flag to know if gamepad is ready
char name[MAX_GAMEPADS][64]; // Gamepad name holder
char currentButtonState[MAX_GAMEPADS][MAX_GAMEPAD_BUTTONS]; // Current gamepad buttons state
char previousButtonState[MAX_GAMEPADS][MAX_GAMEPAD_BUTTONS]; // Previous gamepad buttons state
float axisState[MAX_GAMEPADS][MAX_GAMEPAD_AXIS]; // Gamepad axis state
} Gamepad; char currentButtonState[ MAX_MOUSE_BUTTONS ]; // Registers current mouse button state
} Input; char previousButtonState[ MAX_MOUSE_BUTTONS ]; // Registers previous mouse button state
struct { Vector2 currentWheelMove; // Registers current mouse wheel variation
double current; // Current time measure Vector2 previousWheelMove; // Registers previous mouse wheel variation
double previous; // Previous time measure
double update; // Time measure for frame update
double draw; // Time measure for frame draw
double frame; // Time measure for one frame
double target; // Desired time for one frame, if 0 not applied
unsigned long long int base; // Base time measure for hi-res timer (PLATFORM_ANDROID, PLATFORM_DRM)
unsigned int frameCounter; // Frame counter
} Time; } Mouse;
struct
{
int pointCount; // Number of touch points active
int pointId[ MAX_TOUCH_POINTS ]; // Point identifiers
Vector2 position[ MAX_TOUCH_POINTS ]; // Touch position on screen
char currentTouchState[ MAX_TOUCH_POINTS ]; // Registers current touch state
char previousTouchState[ MAX_TOUCH_POINTS ]; // Registers previous touch state
} Touch;
struct
{
int lastButtonPressed; // Register last gamepad button pressed
int axisCount[ MAX_GAMEPADS ]; // Register number of available gamepad axis
bool ready[ MAX_GAMEPADS ]; // Flag to know if gamepad is ready
char name[ MAX_GAMEPADS ][ 64 ]; // Gamepad name holder
char currentButtonState[ MAX_GAMEPADS ][ MAX_GAMEPAD_BUTTONS ]; // Current gamepad buttons state
char previousButtonState[ MAX_GAMEPADS ][ MAX_GAMEPAD_BUTTONS ]; // Previous gamepad buttons state
float axisState[ MAX_GAMEPADS ][ MAX_GAMEPAD_AXIS ]; // Gamepad axis state
} Gamepad;
} Input;
struct
{
double current; // Current time measure
double previous; // Previous time measure
double update; // Time measure for frame update
double draw; // Time measure for frame draw
double frame; // Time measure for one frame
double target; // Desired time for one frame, if 0 not applied
unsigned long long int base; // Base time measure for hi-res timer (PLATFORM_ANDROID, PLATFORM_DRM)
unsigned int frameCounter; // Frame counter
} Time;
} CoreData; } CoreData;
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------

View File

@ -1,57 +1,57 @@
/********************************************************************************************** /**********************************************************************************************
* *
* rgestures - Gestures system, gestures processing based on input events (touch/mouse) * rgestures - Gestures system, gestures processing based on input events (touch/mouse)
* *
* CONFIGURATION: * CONFIGURATION:
* #define RGESTURES_IMPLEMENTATION * #define RGESTURES_IMPLEMENTATION
* Generates the implementation of the library into the included file. * 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 * 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. * or source files without problems. But only ONE file should hold the implementation.
* *
* #define RGESTURES_STANDALONE * #define RGESTURES_STANDALONE
* If defined, the library can be used as standalone to process gesture events with * If defined, the library can be used as standalone to process gesture events with
* no external dependencies. * no external dependencies.
* *
* CONTRIBUTORS: * CONTRIBUTORS:
* Marc Palau: Initial implementation (2014) * Marc Palau: Initial implementation (2014)
* Albert Martos: Complete redesign and testing (2015) * Albert Martos: Complete redesign and testing (2015)
* Ian Eito: Complete redesign and testing (2015) * Ian Eito: Complete redesign and testing (2015)
* Ramon Santamaria: Supervision, review, update and maintenance * Ramon Santamaria: Supervision, review, update and maintenance
* *
* *
* LICENSE: zlib/libpng * LICENSE: zlib/libpng
* *
* Copyright (c) 2014-2023 Ramon Santamaria (@raysan5) * Copyright (c) 2014-2023 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.
* *
* Permission is granted to anyone to use this software for any purpose, including commercial * 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: * 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 * 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 * 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. * 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 * 2. Altered source versions must be plainly marked as such, and must not be misrepresented
* as being the original software. * as being the original software.
* *
* 3. This notice may not be removed or altered from any source distribution. * 3. This notice may not be removed or altered from any source distribution.
* *
**********************************************************************************************/ **********************************************************************************************/
#ifndef RGESTURES_H #ifndef RGESTURES_H
#define RGESTURES_H #define RGESTURES_H
#ifndef PI #ifndef PI
#define PI 3.14159265358979323846 #define PI 3.14159265358979323846
#endif #endif
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Defines and Macros // Defines and Macros
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
#ifndef MAX_TOUCH_POINTS #ifndef MAX_TOUCH_POINTS
#define MAX_TOUCH_POINTS 8 // Maximum number of touch points supported #define MAX_TOUCH_POINTS 8 // Maximum number of touch points supported
#endif #endif
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
@ -59,51 +59,59 @@
// NOTE: Below types are required for standalone usage // NOTE: Below types are required for standalone usage
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Boolean type // Boolean type
#if (defined(__STDC__) && __STDC_VERSION__ >= 199901L) || (defined(_MSC_VER) && _MSC_VER >= 1800) #if ( defined( __STDC__ ) && __STDC_VERSION__ >= 199901L ) || ( defined( _MSC_VER ) && _MSC_VER >= 1800 )
#include <stdbool.h> #include <stdbool.h>
#elif !defined(__cplusplus) && !defined(bool) && !defined(RL_BOOL_TYPE) #elif ! defined( __cplusplus ) && ! defined( bool ) && ! defined( RL_BOOL_TYPE )
typedef enum bool { false = 0, true = !false } bool; typedef enum bool
{
false = 0,
true = ! false
} bool;
#endif #endif
#if !defined(RL_VECTOR2_TYPE) #if ! defined( RL_VECTOR2_TYPE )
// Vector2 type // Vector2 type
typedef struct Vector2 { typedef struct Vector2
float x; {
float y; float x;
float y;
} Vector2; } Vector2;
#endif #endif
#if defined(RGESTURES_STANDALONE) #if defined( RGESTURES_STANDALONE )
// Gestures type // Gestures type
// NOTE: It could be used as flags to enable only some gestures // NOTE: It could be used as flags to enable only some gestures
typedef enum { typedef enum
GESTURE_NONE = 0, {
GESTURE_TAP = 1, GESTURE_NONE = 0,
GESTURE_DOUBLETAP = 2, GESTURE_TAP = 1,
GESTURE_HOLD = 4, GESTURE_DOUBLETAP = 2,
GESTURE_DRAG = 8, GESTURE_HOLD = 4,
GESTURE_SWIPE_RIGHT = 16, GESTURE_DRAG = 8,
GESTURE_SWIPE_LEFT = 32, GESTURE_SWIPE_RIGHT = 16,
GESTURE_SWIPE_UP = 64, GESTURE_SWIPE_LEFT = 32,
GESTURE_SWIPE_DOWN = 128, GESTURE_SWIPE_UP = 64,
GESTURE_PINCH_IN = 256, GESTURE_SWIPE_DOWN = 128,
GESTURE_PINCH_OUT = 512 GESTURE_PINCH_IN = 256,
GESTURE_PINCH_OUT = 512
} Gesture; } Gesture;
#endif #endif
typedef enum { typedef enum
TOUCH_ACTION_UP = 0, {
TOUCH_ACTION_DOWN, TOUCH_ACTION_UP = 0,
TOUCH_ACTION_MOVE, TOUCH_ACTION_DOWN,
TOUCH_ACTION_CANCEL TOUCH_ACTION_MOVE,
TOUCH_ACTION_CANCEL
} TouchAction; } TouchAction;
// Gesture event // Gesture event
typedef struct { typedef struct
int touchAction; {
int pointCount; int touchAction;
int pointId[MAX_TOUCH_POINTS]; int pointCount;
Vector2 position[MAX_TOUCH_POINTS]; int pointId[ MAX_TOUCH_POINTS ];
Vector2 position[ MAX_TOUCH_POINTS ];
} GestureEvent; } GestureEvent;
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
@ -115,441 +123,472 @@ typedef struct {
// Module Functions Declaration // Module Functions Declaration
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
#if defined(__cplusplus) #if defined( __cplusplus )
extern "C" { // Prevents name mangling of functions extern "C"
{ // Prevents name mangling of functions
#endif #endif
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)
#if defined(RGESTURES_STANDALONE) #if defined( RGESTURES_STANDALONE )
void SetGesturesEnabled(unsigned int flags); // Enable a set of gestures using flags void SetGesturesEnabled( unsigned int flags ); // 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
int GetGestureDetected(void); // Get latest detected gesture int GetGestureDetected( void ); // Get latest detected gesture
float GetGestureHoldDuration(void); // Get gesture hold time in seconds float GetGestureHoldDuration( void ); // Get gesture hold time in seconds
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 #endif
#if defined(__cplusplus) #if defined( __cplusplus )
} }
#endif #endif
#endif // RGESTURES_H #endif // RGESTURES_H
/*********************************************************************************** /***********************************************************************************
* *
* RGESTURES IMPLEMENTATION * RGESTURES IMPLEMENTATION
* *
************************************************************************************/ ************************************************************************************/
#if defined(RGESTURES_IMPLEMENTATION) #if defined( RGESTURES_IMPLEMENTATION )
#if defined(RGESTURES_STANDALONE) #if defined( RGESTURES_STANDALONE )
#if defined(_WIN32) #if defined( _WIN32 )
#if defined(__cplusplus) #if defined( __cplusplus )
extern "C" { // Prevents name mangling of functions extern "C"
#endif { // Prevents name mangling of functions
// 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 #endif
#if defined(__APPLE__) // macOS also defines __MACH__ // Functions required to query time on Windows
#include <mach/clock.h> // Required for: clock_get_time() int __stdcall QueryPerformanceCounter( unsigned long long int* lpPerformanceCount );
#include <mach/mach.h> // Required for: mach_timespec_t 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 #endif
#endif #endif
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Defines and Macros // Defines and Macros
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
#define FORCE_TO_SWIPE 0.2f // Swipe force, measured in normalized screen units/time #define FORCE_TO_SWIPE 0.2f // 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_DRAG 0.015f // Drag minimum force, measured in normalized screen units (0.0f to 1.0f)
#define DRAG_TIMEOUT 0.3f // Drag minimum time for web, measured in seconds #define DRAG_TIMEOUT 0.3f // Drag minimum time for web, measured in seconds
#define MINIMUM_PINCH 0.005f // Pinch 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 0.3f // Tap minimum time, measured in seconds #define TAP_TIMEOUT 0.3f // Tap minimum time, measured in seconds
#define PINCH_TIMEOUT 0.3f // Pinch minimum time, measured in seconds #define PINCH_TIMEOUT 0.3f // Pinch minimum time, measured in seconds
#define DOUBLETAP_RANGE 0.03f // DoubleTap range, measured in normalized screen units (0.0f to 1.0f) #define DOUBLETAP_RANGE 0.03f // DoubleTap range, measured in normalized screen units (0.0f to 1.0f)
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Types and Structures Definition // Types and Structures Definition
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Gestures module state context [136 bytes] // Gestures module state context [136 bytes]
typedef struct { typedef struct
unsigned int current; // Current detected gesture {
unsigned int enabledFlags; // Enabled gestures flags unsigned int current; // Current detected gesture
struct { unsigned int enabledFlags; // Enabled gestures flags
int firstId; // Touch id for first touch point
int pointCount; // Touch points counter struct
double eventTime; // Time stamp when an event happened {
Vector2 upPosition; // Touch up position int firstId; // Touch id for first touch point
Vector2 downPositionA; // First touch down position int pointCount; // Touch points counter
Vector2 downPositionB; // Second touch down position double eventTime; // Time stamp when an event happened
Vector2 downDragPosition; // Touch drag position Vector2 upPosition; // Touch up position
Vector2 moveDownPositionA; // First touch down position on move Vector2 downPositionA; // First touch down position
Vector2 moveDownPositionB; // Second touch down position on move Vector2 downPositionB; // Second touch down position
Vector2 previousPositionA; // Previous position A to compare for pinch gestures Vector2 downDragPosition; // Touch drag position
Vector2 previousPositionB; // Previous position B to compare for pinch gestures Vector2 moveDownPositionA; // First touch down position on move
int tapCounter; // TAP counter (one tap implies TOUCH_ACTION_DOWN and TOUCH_ACTION_UP actions) Vector2 moveDownPositionB; // Second touch down position on move
} Touch; Vector2 previousPositionA; // Previous position A to compare for pinch gestures
struct { Vector2 previousPositionB; // Previous position B to compare for pinch gestures
bool resetRequired; // HOLD reset to get first touch point again int tapCounter; // TAP counter (one tap implies TOUCH_ACTION_DOWN and TOUCH_ACTION_UP actions)
double timeDuration; // HOLD duration in seconds } Touch;
} Hold;
struct { struct
Vector2 vector; // DRAG vector (between initial and current position) {
float angle; // DRAG angle (relative to x-axis) bool resetRequired; // HOLD reset to get first touch point again
float distance; // DRAG distance (from initial touch point to final) (normalized [0..1]) double timeDuration; // HOLD duration in seconds
float intensity; // DRAG intensity, how far why did the DRAG (pixels per frame) } Hold;
} Drag;
struct { struct
double startTime; // SWIPE start time to calculate drag intensity {
} Swipe; Vector2 vector; // DRAG vector (between initial and current position)
struct { float angle; // DRAG angle (relative to x-axis)
Vector2 vector; // PINCH vector (between first and second touch points) float distance; // DRAG distance (from initial touch point to final) (normalized [0..1])
float angle; // PINCH angle (relative to x-axis) float intensity; // DRAG intensity, how far why did the DRAG (pixels per frame)
float distance; // PINCH displacement distance (normalized [0..1]) } Drag;
} Pinch;
struct
{
double startTime; // SWIPE start 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; } GesturesData;
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Global Variables Definition // Global Variables Definition
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
static GesturesData GESTURES = { static GesturesData GESTURES = {
.Touch.firstId = -1, .Touch.firstId = -1,
.current = GESTURE_NONE, // No current gesture detected .current = GESTURE_NONE, // No current gesture detected
.enabledFlags = 0b0000001111111111 // All gestures supported by default .enabledFlags = 0b0000001111111111 // All gestures supported by default
}; };
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Module specific Functions Declaration // Module specific Functions Declaration
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
static float rgVector2Angle(Vector2 initialPosition, Vector2 finalPosition); static float rgVector2Angle( Vector2 initialPosition, Vector2 finalPosition );
static float rgVector2Distance(Vector2 v1, Vector2 v2); static float rgVector2Distance( Vector2 v1, Vector2 v2 );
static double rgGetCurrentTime(void); static double rgGetCurrentTime( void );
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Module Functions Definition // Module Functions Definition
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Enable only desired gestures to be detected // Enable only desired gestures to be detected
void SetGesturesEnabled(unsigned int flags) void SetGesturesEnabled( unsigned int flags )
{ {
GESTURES.enabledFlags = flags; GESTURES.enabledFlags = flags;
} }
// Check if a gesture have been detected // Check if a gesture have been detected
bool IsGestureDetected(unsigned int gesture) bool IsGestureDetected( unsigned int gesture )
{ {
if ((GESTURES.enabledFlags & GESTURES.current) == gesture) return true; if ( ( GESTURES.enabledFlags & GESTURES.current ) == gesture )
else return false; return true;
else
return false;
} }
// Process gesture event and translate it into gestures // Process gesture event and translate it into gestures
void ProcessGestureEvent(GestureEvent event) void ProcessGestureEvent( GestureEvent event )
{ {
// Reset required variables // Reset required variables
GESTURES.Touch.pointCount = event.pointCount; // Required on UpdateGestures() GESTURES.Touch.pointCount = event.pointCount; // Required on UpdateGestures()
if (GESTURES.Touch.pointCount == 1) // One touch point if ( GESTURES.Touch.pointCount == 1 ) // One touch point
{ {
if (event.touchAction == TOUCH_ACTION_DOWN) if ( event.touchAction == TOUCH_ACTION_DOWN )
{ {
GESTURES.Touch.tapCounter++; // Tap counter GESTURES.Touch.tapCounter++; // Tap counter
// Detect GESTURE_DOUBLE_TAP // 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)) if ( ( GESTURES.current == GESTURE_NONE ) && ( GESTURES.Touch.tapCounter >= 2 )
{ && ( ( rgGetCurrentTime() - GESTURES.Touch.eventTime ) < TAP_TIMEOUT )
GESTURES.current = GESTURE_DOUBLETAP; && ( rgVector2Distance( GESTURES.Touch.downPositionA, event.position[ 0 ] ) < DOUBLETAP_RANGE ) )
GESTURES.Touch.tapCounter = 0; {
} GESTURES.current = GESTURE_DOUBLETAP;
else // Detect GESTURE_TAP GESTURES.Touch.tapCounter = 0;
{ }
GESTURES.Touch.tapCounter = 1; else // Detect GESTURE_TAP
GESTURES.current = GESTURE_TAP; {
} GESTURES.Touch.tapCounter = 1;
GESTURES.current = GESTURE_TAP;
}
GESTURES.Touch.downPositionA = event.position[0]; GESTURES.Touch.downPositionA = event.position[ 0 ];
GESTURES.Touch.downDragPosition = event.position[0]; GESTURES.Touch.downDragPosition = event.position[ 0 ];
GESTURES.Touch.upPosition = GESTURES.Touch.downPositionA; GESTURES.Touch.upPosition = GESTURES.Touch.downPositionA;
GESTURES.Touch.eventTime = rgGetCurrentTime(); GESTURES.Touch.eventTime = rgGetCurrentTime();
GESTURES.Swipe.startTime = rgGetCurrentTime(); GESTURES.Swipe.startTime = rgGetCurrentTime();
GESTURES.Drag.vector = (Vector2){ 0.0f, 0.0f }; GESTURES.Drag.vector = ( Vector2 ) { 0.0f, 0.0f };
} }
else if (event.touchAction == TOUCH_ACTION_UP) else if ( event.touchAction == TOUCH_ACTION_UP )
{ {
// A swipe can happen while the current gesture is drag, but (specially for web) also hold, so set upPosition for both cases // A swipe can happen while the current gesture is drag, but (specially for web) also hold, so set upPosition for both cases
if (GESTURES.current == GESTURE_DRAG || GESTURES.current == GESTURE_HOLD) GESTURES.Touch.upPosition = event.position[0]; if ( GESTURES.current == GESTURE_DRAG || GESTURES.current == GESTURE_HOLD )
GESTURES.Touch.upPosition = event.position[ 0 ];
// NOTE: GESTURES.Drag.intensity dependent on the resolution of the screen // NOTE: GESTURES.Drag.intensity dependent on the resolution of the screen
GESTURES.Drag.distance = rgVector2Distance(GESTURES.Touch.downPositionA, GESTURES.Touch.upPosition); GESTURES.Drag.distance = rgVector2Distance( GESTURES.Touch.downPositionA, GESTURES.Touch.upPosition );
GESTURES.Drag.intensity = GESTURES.Drag.distance/(float)((rgGetCurrentTime() - GESTURES.Swipe.startTime)); GESTURES.Drag.intensity = GESTURES.Drag.distance / ( float )( ( rgGetCurrentTime() - GESTURES.Swipe.startTime ) );
// Detect GESTURE_SWIPE // Detect GESTURE_SWIPE
if ((GESTURES.Drag.intensity > FORCE_TO_SWIPE) && (GESTURES.current != GESTURE_DRAG)) if ( ( GESTURES.Drag.intensity > FORCE_TO_SWIPE ) && ( GESTURES.current != GESTURE_DRAG ) )
{ {
// NOTE: Angle should be inverted in Y // NOTE: Angle should be inverted in Y
GESTURES.Drag.angle = 360.0f - rgVector2Angle(GESTURES.Touch.downPositionA, GESTURES.Touch.upPosition); 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 if ( ( GESTURES.Drag.angle < 30 ) || ( GESTURES.Drag.angle > 330 ) )
else if ((GESTURES.Drag.angle >= 30) && (GESTURES.Drag.angle <= 150)) GESTURES.current = GESTURE_SWIPE_UP; // Up GESTURES.current = GESTURE_SWIPE_RIGHT; // Right
else if ((GESTURES.Drag.angle > 150) && (GESTURES.Drag.angle < 210)) GESTURES.current = GESTURE_SWIPE_LEFT; // Left else if ( ( GESTURES.Drag.angle >= 30 ) && ( GESTURES.Drag.angle <= 150 ) )
else if ((GESTURES.Drag.angle >= 210) && (GESTURES.Drag.angle <= 330)) GESTURES.current = GESTURE_SWIPE_DOWN; // Down GESTURES.current = GESTURE_SWIPE_UP; // Up
else GESTURES.current = GESTURE_NONE; else if ( ( GESTURES.Drag.angle > 150 ) && ( GESTURES.Drag.angle < 210 ) )
} GESTURES.current = GESTURE_SWIPE_LEFT; // Left
else else if ( ( GESTURES.Drag.angle >= 210 ) && ( GESTURES.Drag.angle <= 330 ) )
{ GESTURES.current = GESTURE_SWIPE_DOWN; // Down
GESTURES.Drag.distance = 0.0f; else
GESTURES.Drag.intensity = 0.0f; GESTURES.current = GESTURE_NONE;
GESTURES.Drag.angle = 0.0f; }
else
{
GESTURES.Drag.distance = 0.0f;
GESTURES.Drag.intensity = 0.0f;
GESTURES.Drag.angle = 0.0f;
GESTURES.current = GESTURE_NONE; GESTURES.current = GESTURE_NONE;
} }
GESTURES.Touch.downDragPosition = (Vector2){ 0.0f, 0.0f }; GESTURES.Touch.downDragPosition = ( Vector2 ) { 0.0f, 0.0f };
GESTURES.Touch.pointCount = 0; GESTURES.Touch.pointCount = 0;
} }
else if (event.touchAction == TOUCH_ACTION_MOVE) else if ( event.touchAction == TOUCH_ACTION_MOVE )
{ {
GESTURES.Touch.moveDownPositionA = event.position[0]; GESTURES.Touch.moveDownPositionA = event.position[ 0 ];
if (GESTURES.current == GESTURE_HOLD) if ( GESTURES.current == GESTURE_HOLD )
{ {
if (GESTURES.Hold.resetRequired) GESTURES.Touch.downPositionA = event.position[0]; if ( GESTURES.Hold.resetRequired )
GESTURES.Touch.downPositionA = event.position[ 0 ];
GESTURES.Hold.resetRequired = false; GESTURES.Hold.resetRequired = false;
// Detect GESTURE_DRAG // Detect GESTURE_DRAG
if ((rgGetCurrentTime() - GESTURES.Touch.eventTime) > DRAG_TIMEOUT) if ( ( rgGetCurrentTime() - GESTURES.Touch.eventTime ) > DRAG_TIMEOUT )
{ {
GESTURES.Touch.eventTime = rgGetCurrentTime(); GESTURES.Touch.eventTime = rgGetCurrentTime();
GESTURES.current = GESTURE_DRAG; GESTURES.current = GESTURE_DRAG;
} }
} }
GESTURES.Drag.vector.x = GESTURES.Touch.moveDownPositionA.x - GESTURES.Touch.downDragPosition.x; GESTURES.Drag.vector.x = GESTURES.Touch.moveDownPositionA.x - GESTURES.Touch.downDragPosition.x;
GESTURES.Drag.vector.y = GESTURES.Touch.moveDownPositionA.y - GESTURES.Touch.downDragPosition.y; GESTURES.Drag.vector.y = GESTURES.Touch.moveDownPositionA.y - GESTURES.Touch.downDragPosition.y;
} }
} }
else if (GESTURES.Touch.pointCount == 2) // Two touch points else if ( GESTURES.Touch.pointCount == 2 ) // Two touch points
{ {
if (event.touchAction == TOUCH_ACTION_DOWN) if ( event.touchAction == TOUCH_ACTION_DOWN )
{ {
GESTURES.Touch.downPositionA = event.position[0]; GESTURES.Touch.downPositionA = event.position[ 0 ];
GESTURES.Touch.downPositionB = event.position[1]; GESTURES.Touch.downPositionB = event.position[ 1 ];
GESTURES.Touch.previousPositionA = GESTURES.Touch.downPositionA; GESTURES.Touch.previousPositionA = GESTURES.Touch.downPositionA;
GESTURES.Touch.previousPositionB = GESTURES.Touch.downPositionB; GESTURES.Touch.previousPositionB = GESTURES.Touch.downPositionB;
//GESTURES.Pinch.distance = rgVector2Distance(GESTURES.Touch.downPositionA, GESTURES.Touch.downPositionB); // 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.x = GESTURES.Touch.downPositionB.x - GESTURES.Touch.downPositionA.x;
GESTURES.Pinch.vector.y = GESTURES.Touch.downPositionB.y - GESTURES.Touch.downPositionA.y; GESTURES.Pinch.vector.y = GESTURES.Touch.downPositionB.y - GESTURES.Touch.downPositionA.y;
GESTURES.current = GESTURE_HOLD; GESTURES.current = GESTURE_HOLD;
GESTURES.Hold.timeDuration = rgGetCurrentTime(); GESTURES.Hold.timeDuration = rgGetCurrentTime();
} }
else if (event.touchAction == TOUCH_ACTION_MOVE) else if ( event.touchAction == TOUCH_ACTION_MOVE )
{ {
GESTURES.Pinch.distance = rgVector2Distance(GESTURES.Touch.moveDownPositionA, GESTURES.Touch.moveDownPositionB); GESTURES.Pinch.distance = rgVector2Distance( GESTURES.Touch.moveDownPositionA, GESTURES.Touch.moveDownPositionB );
GESTURES.Touch.moveDownPositionA = event.position[0]; GESTURES.Touch.moveDownPositionA = event.position[ 0 ];
GESTURES.Touch.moveDownPositionB = event.position[1]; GESTURES.Touch.moveDownPositionB = event.position[ 1 ];
GESTURES.Pinch.vector.x = GESTURES.Touch.moveDownPositionB.x - GESTURES.Touch.moveDownPositionA.x; GESTURES.Pinch.vector.x = GESTURES.Touch.moveDownPositionB.x - GESTURES.Touch.moveDownPositionA.x;
GESTURES.Pinch.vector.y = GESTURES.Touch.moveDownPositionB.y - GESTURES.Touch.moveDownPositionA.y; GESTURES.Pinch.vector.y = GESTURES.Touch.moveDownPositionB.y - GESTURES.Touch.moveDownPositionA.y;
if ((rgVector2Distance(GESTURES.Touch.previousPositionA, GESTURES.Touch.moveDownPositionA) >= MINIMUM_PINCH) || (rgVector2Distance(GESTURES.Touch.previousPositionB, GESTURES.Touch.moveDownPositionB) >= MINIMUM_PINCH)) if ( ( rgVector2Distance( GESTURES.Touch.previousPositionA, GESTURES.Touch.moveDownPositionA ) >= MINIMUM_PINCH )
{ || ( rgVector2Distance( GESTURES.Touch.previousPositionB, GESTURES.Touch.moveDownPositionB ) >= MINIMUM_PINCH ) )
if ( rgVector2Distance(GESTURES.Touch.previousPositionA, GESTURES.Touch.previousPositionB) > rgVector2Distance(GESTURES.Touch.moveDownPositionA, GESTURES.Touch.moveDownPositionB) ) GESTURES.current = GESTURE_PINCH_IN; {
else GESTURES.current = GESTURE_PINCH_OUT; if ( rgVector2Distance( GESTURES.Touch.previousPositionA, GESTURES.Touch.previousPositionB )
} > rgVector2Distance( GESTURES.Touch.moveDownPositionA, GESTURES.Touch.moveDownPositionB ) )
else GESTURES.current = GESTURE_PINCH_IN;
{ else
GESTURES.current = GESTURE_HOLD; GESTURES.current = GESTURE_PINCH_OUT;
GESTURES.Hold.timeDuration = rgGetCurrentTime(); }
} else
{
GESTURES.current = GESTURE_HOLD;
GESTURES.Hold.timeDuration = rgGetCurrentTime();
}
// NOTE: Angle should be inverted in Y // NOTE: Angle should be inverted in Y
GESTURES.Pinch.angle = 360.0f - rgVector2Angle(GESTURES.Touch.moveDownPositionA, GESTURES.Touch.moveDownPositionB); GESTURES.Pinch.angle = 360.0f - rgVector2Angle( GESTURES.Touch.moveDownPositionA, GESTURES.Touch.moveDownPositionB );
} }
else if (event.touchAction == TOUCH_ACTION_UP) else if ( event.touchAction == TOUCH_ACTION_UP )
{ {
GESTURES.Pinch.distance = 0.0f; GESTURES.Pinch.distance = 0.0f;
GESTURES.Pinch.angle = 0.0f; GESTURES.Pinch.angle = 0.0f;
GESTURES.Pinch.vector = (Vector2){ 0.0f, 0.0f }; GESTURES.Pinch.vector = ( Vector2 ) { 0.0f, 0.0f };
GESTURES.Touch.pointCount = 0; GESTURES.Touch.pointCount = 0;
GESTURES.current = GESTURE_NONE; GESTURES.current = GESTURE_NONE;
} }
} }
else if (GESTURES.Touch.pointCount > 2) // More than two touch points else if ( GESTURES.Touch.pointCount > 2 ) // More than two touch points
{ {
// TODO: Process gesture events for more than two points // TODO: Process gesture events for more than two points
} }
} }
// Update gestures detected (must be called every frame) // Update gestures detected (must be called every frame)
void UpdateGestures(void) void UpdateGestures( void )
{ {
// NOTE: Gestures are processed through system callbacks on touch events // NOTE: Gestures are processed through system callbacks on touch events
// Detect GESTURE_HOLD // Detect GESTURE_HOLD
if (((GESTURES.current == GESTURE_TAP) || (GESTURES.current == GESTURE_DOUBLETAP)) && (GESTURES.Touch.pointCount < 2)) if ( ( ( GESTURES.current == GESTURE_TAP ) || ( GESTURES.current == GESTURE_DOUBLETAP ) ) && ( GESTURES.Touch.pointCount < 2 ) )
{ {
GESTURES.current = GESTURE_HOLD; GESTURES.current = GESTURE_HOLD;
GESTURES.Hold.timeDuration = rgGetCurrentTime(); GESTURES.Hold.timeDuration = rgGetCurrentTime();
} }
// Detect GESTURE_NONE // Detect GESTURE_NONE
if ((GESTURES.current == GESTURE_SWIPE_RIGHT) || (GESTURES.current == GESTURE_SWIPE_UP) || (GESTURES.current == GESTURE_SWIPE_LEFT) || (GESTURES.current == GESTURE_SWIPE_DOWN)) 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; {
} GESTURES.current = GESTURE_NONE;
}
} }
// Get latest detected gesture // Get latest detected gesture
int GetGestureDetected(void) int GetGestureDetected( void )
{ {
// Get current gesture only if enabled // Get current gesture only if enabled
return (GESTURES.enabledFlags & GESTURES.current); return ( GESTURES.enabledFlags & GESTURES.current );
} }
// Hold time measured in ms // Hold time measured in ms
float GetGestureHoldDuration(void) float GetGestureHoldDuration( void )
{ {
// NOTE: time is calculated on current gesture HOLD // NOTE: time is calculated on current gesture HOLD
double time = 0.0; double time = 0.0;
if (GESTURES.current == GESTURE_HOLD) time = rgGetCurrentTime() - GESTURES.Hold.timeDuration; if ( GESTURES.current == GESTURE_HOLD )
time = rgGetCurrentTime() - GESTURES.Hold.timeDuration;
return (float)time; return ( float )time;
} }
// Get drag vector (between initial touch point to current) // Get drag vector (between initial touch point to current)
Vector2 GetGestureDragVector(void) Vector2 GetGestureDragVector( void )
{ {
// NOTE: drag vector is calculated on one touch points TOUCH_ACTION_MOVE // NOTE: drag vector is calculated on one touch points TOUCH_ACTION_MOVE
return GESTURES.Drag.vector; return GESTURES.Drag.vector;
} }
// Get drag angle // Get drag angle
// NOTE: Angle in degrees, horizontal-right is 0, counterclockwise // NOTE: Angle in degrees, horizontal-right is 0, counterclockwise
float GetGestureDragAngle(void) float GetGestureDragAngle( void )
{ {
// NOTE: drag angle is calculated on one touch points TOUCH_ACTION_UP // NOTE: drag angle is calculated on one touch points TOUCH_ACTION_UP
return GESTURES.Drag.angle; return GESTURES.Drag.angle;
} }
// Get distance between two pinch points // Get distance between two pinch points
Vector2 GetGesturePinchVector(void) Vector2 GetGesturePinchVector( void )
{ {
// NOTE: Pinch distance is calculated on two touch points TOUCH_ACTION_MOVE // NOTE: Pinch distance is calculated on two touch points TOUCH_ACTION_MOVE
return GESTURES.Pinch.vector; return GESTURES.Pinch.vector;
} }
// Get angle between two pinch points // Get angle between two pinch points
// NOTE: Angle in degrees, horizontal-right is 0, counterclockwise // NOTE: Angle in degrees, horizontal-right is 0, counterclockwise
float GetGesturePinchAngle(void) float GetGesturePinchAngle( void )
{ {
// NOTE: pinch angle is calculated on two touch points TOUCH_ACTION_MOVE // NOTE: pinch angle is calculated on two touch points TOUCH_ACTION_MOVE
return GESTURES.Pinch.angle; return GESTURES.Pinch.angle;
} }
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Module specific Functions Definition // Module specific Functions Definition
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Get angle from two-points vector with X-axis // Get angle from two-points vector with X-axis
static float rgVector2Angle(Vector2 v1, Vector2 v2) static float rgVector2Angle( Vector2 v1, Vector2 v2 )
{ {
float angle = atan2f(v2.y - v1.y, v2.x - v1.x)*(180.0f/PI); float angle = atan2f( v2.y - v1.y, v2.x - v1.x ) * ( 180.0f / PI );
if (angle < 0) angle += 360.0f; if ( angle < 0 )
angle += 360.0f;
return angle; return angle;
} }
// Calculate distance between two Vector2 // Calculate distance between two Vector2
static float rgVector2Distance(Vector2 v1, Vector2 v2) static float rgVector2Distance( Vector2 v1, Vector2 v2 )
{ {
float result; float result;
float dx = v2.x - v1.x; float dx = v2.x - v1.x;
float dy = v2.y - v1.y; float dy = v2.y - v1.y;
result = (float)sqrt(dx*dx + dy*dy); result = ( float )sqrt( dx * dx + dy * dy );
return result; return result;
} }
// Time measure returned are seconds // Time measure returned are seconds
static double rgGetCurrentTime(void) static double rgGetCurrentTime( void )
{ {
double time = 0; double time = 0;
#if !defined(RGESTURES_STANDALONE) #if ! defined( RGESTURES_STANDALONE )
time = GetTime(); time = GetTime();
#else #else
#if defined(_WIN32) #if defined( _WIN32 )
unsigned long long int clockFrequency, currentTime; unsigned long long int clockFrequency, currentTime;
QueryPerformanceFrequency(&clockFrequency); // BE CAREFUL: Costly operation! QueryPerformanceFrequency( &clockFrequency ); // BE CAREFUL: Costly operation!
QueryPerformanceCounter(&currentTime); QueryPerformanceCounter( &currentTime );
time = (double)currentTime/clockFrequency; // Time in seconds time = ( double )currentTime / clockFrequency; // Time in seconds
#endif #endif
#if defined(__linux__) #if defined( __linux__ )
// NOTE: Only for Linux-based systems // NOTE: Only for Linux-based systems
struct timespec now; struct timespec now;
clock_gettime(CLOCK_MONOTONIC, &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 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*1e-9); // Time in seconds time = ( ( double )nowTime * 1e-9 ); // Time in seconds
#endif #endif
#if defined(__APPLE__) #if defined( __APPLE__ )
//#define CLOCK_REALTIME CALENDAR_CLOCK // returns UTC time since 1970-01-01 // #define CLOCK_REALTIME CALENDAR_CLOCK // returns UTC time since 1970-01-01
//#define CLOCK_MONOTONIC SYSTEM_CLOCK // returns the time since boot time // #define CLOCK_MONOTONIC SYSTEM_CLOCK // returns the time since boot time
clock_serv_t cclock; clock_serv_t cclock;
mach_timespec_t now; mach_timespec_t now;
host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &cclock); host_get_clock_service( mach_host_self(), SYSTEM_CLOCK, &cclock );
// NOTE: OS X does not have clock_gettime(), using clock_get_time() // NOTE: OS X does not have clock_gettime(), using clock_get_time()
clock_get_time(cclock, &now); clock_get_time( cclock, &now );
mach_port_deallocate(mach_task_self(), cclock); 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 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*1e-9); // Time in seconds time = ( ( double )nowTime * 1e-9 ); // Time in seconds
#endif #endif
#endif #endif
return time; return time;
} }
#endif // RGESTURES_IMPLEMENTATION #endif // RGESTURES_IMPLEMENTATION

File diff suppressed because it is too large Load Diff

View File

@ -1,55 +1,55 @@
/********************************************************************************************** /**********************************************************************************************
* *
* raylib.utils - Some common utility functions * raylib.utils - Some common utility functions
* *
* *
* LICENSE: zlib/libpng * LICENSE: zlib/libpng
* *
* Copyright (c) 2014-2023 Ramon Santamaria (@raysan5) * Copyright (c) 2014-2023 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.
* *
* Permission is granted to anyone to use this software for any purpose, including commercial * 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: * 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 * 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 * 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. * 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 * 2. Altered source versions must be plainly marked as such, and must not be misrepresented
* as being the original software. * as being the original software.
* *
* 3. This notice may not be removed or altered from any source distribution. * 3. This notice may not be removed or altered from any source distribution.
* *
**********************************************************************************************/ **********************************************************************************************/
#ifndef UTILS_H #ifndef UTILS_H
#define UTILS_H #define UTILS_H
#if defined(PLATFORM_ANDROID) #if defined( PLATFORM_ANDROID )
#include <stdio.h> // Required for: FILE #include <stdio.h> // Required for: FILE
#include <android/asset_manager.h> // Required for: AAssetManager #include <android/asset_manager.h> // Required for: AAssetManager
#endif #endif
#if defined(SUPPORT_TRACELOG) #if defined( SUPPORT_TRACELOG )
#define TRACELOG(level, ...) TraceLog(level, __VA_ARGS__) #define TRACELOG( level, ... ) TraceLog( level, __VA_ARGS__ )
#if defined(SUPPORT_TRACELOG_DEBUG) #if defined( SUPPORT_TRACELOG_DEBUG )
#define TRACELOGD(...) TraceLog(LOG_DEBUG, __VA_ARGS__) #define TRACELOGD( ... ) TraceLog( LOG_DEBUG, __VA_ARGS__ )
#else
#define TRACELOGD(...) (void)0
#endif
#else #else
#define TRACELOG(level, ...) (void)0 #define TRACELOGD( ... ) ( void )0
#define TRACELOGD(...) (void)0 #endif
#else
#define TRACELOG( level, ... ) ( void )0
#define TRACELOGD( ... ) ( void )0
#endif #endif
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Some basic Defines // Some basic Defines
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
#if defined(PLATFORM_ANDROID) #if defined( PLATFORM_ANDROID )
#define fopen(name, mode) android_fopen(name, mode) #define fopen( name, mode ) android_fopen( name, mode )
#endif #endif
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
@ -65,17 +65,18 @@
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Module Functions Declaration // Module Functions Declaration
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
#if defined(__cplusplus) #if defined( __cplusplus )
extern "C" { // Prevents name mangling of functions extern "C"
{ // Prevents name mangling of functions
#endif #endif
#if defined(PLATFORM_ANDROID) #if defined( PLATFORM_ANDROID )
void InitAssetManager(AAssetManager *manager, const char *dataPath); // Initialize asset manager from android app void InitAssetManager( AAssetManager* manager, const char* dataPath ); // Initialize asset manager from android app
FILE *android_fopen(const char *fileName, const char *mode); // Replacement for fopen() -> Read-only! FILE* android_fopen( const char* fileName, const char* mode ); // Replacement for fopen() -> Read-only!
#endif #endif
#if defined(__cplusplus) #if defined( __cplusplus )
} }
#endif #endif
#endif // UTILS_H #endif // UTILS_H

View File

@ -0,0 +1,9 @@
__VERSION 1
word SUPPORT_MODULE_RSHAPES, RL_SUPPORT_MODULE_RSHAPES
word SUPPORT_MODULE_RTEXTURES, RL_SUPPORT_MODULE_RTEXTURES
word SUPPORT_MODULE_RTEXT, RL_SUPPORT_MODULE_RTEXT
word SUPPORT_MODULE_RMODELS, RL_SUPPORT_MODULE_RMODELS
word SUPPORT_MODULE_RAUDIO, RL_SUPPORT_MODULE_RAUDIO

View File

@ -17,41 +17,272 @@ constexpr char const* path_rtext = "rtext.h";
using namespace gen; using namespace gen;
StringCached upper_snake_to_mixed_snake(StringCached str)
void refactor_file( CodeBody code_file )
{ {
local_persist String scratch = String::make_reserve(GlobalAllocator, kilobytes(1));
scratch.clear();
bool capitalizeNext = true;
for (s32 index = 0; index < str.length(); ++index)
{
char c = str[index];
if (c == '_')
{
scratch.append(c);
capitalizeNext = true;
}
else if (capitalizeNext)
{
if (c >= 'a' && c <= 'z')
{
scratch.append(c - 32); // Convert to uppercase
}
else
{
scratch.append(c);
}
capitalizeNext = false;
}
else
{
if (c >= 'A' && c <= 'Z')
{
scratch.append(c + 32); // Convert to lowercase
}
else
{
scratch.append(c);
}
}
}
StringCached result = get_cached_string(scratch);
return result;
}
StringCached pascal_to_lower_snake(StringCached str)
{
local_persist String scratch = String::make_reserve(GlobalAllocator, kilobytes(1));
scratch.clear();
for (s32 index = 0; index < str.length(); ++index)
{
char c = str[index];
char next = (index + 1 < str.length()) ? str[index + 1] : '\0'; // Ensure we don't go out of bounds
// Whitelist check for "2D" and "3D"
if ((c == '2' || c == '3' | c == '4') && (next == 'D' || next == 'd'))
{
if (index > 0) // If it's not the start of the string, append an underscore
{
char* prev = str.Data + index - 1;
if (*prev != '_') // Avoid double underscores
{
scratch.append('_');
}
}
scratch.append(c);
scratch.append('d'); // Convert to lowercase
index++; // Skip the next character since we've already processed it
continue;
}
if (c >= 'A' && c <= 'Z')
{
char* prev = (index > 0) ? str.Data + index - 1 : nullptr;
if ((index > 0 && prev && *prev >= 'a' && *prev <= 'z') ||
(prev && char_is_digit(*prev) && (next >= 'A' && next <= 'Z')))
{
scratch.append('_');
}
scratch.append(c + 32);
}
else if (char_is_digit(c) && (next >= 'A' && next <= 'Z')) // Check for a number followed by an uppercase letter
{
scratch.append(c);
scratch.append('_');
}
else
{
scratch.append(c);
}
}
StringCached result = get_cached_string(scratch);
return result;
}
void refactor_enum( CodeEnum& code )
{
for ( Code elem : code->Body )
{
if ( elem->Type == ECode::Untyped )
{
elem->Content = upper_snake_to_mixed_snake( elem->Content );
}
}
}
void refactor_typename( CodeType& type )
{
local_persist CodeType t_unsigned_char = parse_type( code(unsigned char) );
local_persist CodeType t_unsigned_char_ptr = parse_type( code(unsigned char*) );
local_persist CodeType t_unsigned_short_ptr = parse_type( code(unsigned short*) );
local_persist CodeType t_int = parse_type( code(int) );
local_persist CodeType t_int_ptr = parse_type( code(int*) );
local_persist CodeType t_unsigned_int = parse_type( code(unsigned int) );
local_persist CodeType t_float = parse_type( code(float) );
local_persist CodeType t_float_ptr = parse_type( code(float*) );
local_persist CodeType t_f32_ptr = parse_type( code(f32*) );
local_persist CodeType t_u8_ptr = parse_type( code(u8*) );
local_persist CodeType t_s32_ptr = parse_type( code(s32*) );
String type_str = type.to_string();
if ( str_compare( type_str, t_unsigned_char.to_string() ) == 0 )
{
type.ast = t_u8.ast;
}
if ( str_compare( type_str, t_unsigned_char_ptr.to_string() ) == 0 )
{
type.ast = t_u8_ptr.ast;
}
if ( str_compare( type_str, t_unsigned_short_ptr.to_string() ) == 0 )
{
type.ast = t_u8_ptr.ast;
}
if ( str_compare( type_str, t_int.to_string() ) == 0 )
{
type.ast = t_s32.ast;
}
if ( str_compare( type_str, t_int_ptr.to_string() ) == 0 )
{
type.ast = t_s32_ptr.ast;
}
if ( str_compare( type_str, t_unsigned_int.to_string() ) == 0 )
{
type.ast = t_u32.ast;
}
if ( str_compare( type_str, t_float.to_string() ) == 0 )
{
type.ast = t_f32.ast;
}
if ( str_compare( type_str, t_float_ptr.to_string() ) == 0 )
{
type.ast = t_f32_ptr.ast;
}
}
void refactor_fn( CodeFn& fn )
{
fn->Name = pascal_to_lower_snake( fn->Name );
for ( CodeParam param : fn->Params )
{
refactor_typename( param->ValueType );
}
}
void refactor_struct( CodeStruct& code )
{
for ( Code field : code->Body )
{
if ( field->Type == ECode::Variable )
{
CodeVar var = field.cast<CodeVar>();
refactor_typename( var->ValueType );
}
}
}
void refactor_file( char const* path )
{
FileContents contents = file_read_contents( GlobalAllocator, true, path );
CodeBody code = parse_global_body( { contents.size, rcast(char const*, contents.data) } );
String name_scratch = String::make_reserve( GlobalAllocator, kilobytes(1) ); String name_scratch = String::make_reserve( GlobalAllocator, kilobytes(1) );
for ( Code elem : code_file )
// CodeBody includes
// CodeBody nspace_body = def_body( ECode::Namespace );
CodeBody new_code = def_body( ECode::Global_Body );
for ( Code elem : code )
{ {
if ( elem->Type == ECode::Preprocess_Define ) if ( elem->Type == ECode::Preprocess_Define )
{ {
if ( str_compare( elem->Name, txt("RL_"), 2 ) == 0 ) if ( str_compare( elem->Name, txt("RL"), 2 ) == 0 || str_compare( elem->Name, txt("RAYLIB"), 6 ) == 0 )
continue; continue;
name_scratch.append_fmt( "%RL_%S", elem->Name ); name_scratch.append_fmt( "%RL_%S", elem->Name );
elem->Name = get_cached_string( name_scratch ); elem->Name = get_cached_string( name_scratch );
name_scratch.clear(); name_scratch.clear();
} }
if ( elem->Type == ECode::Enum )
{
refactor_enum( elem.cast<CodeEnum>() );
}
if ( elem->Type == ECode::Typedef )
{
CodeTypedef td = elem.cast<CodeTypedef>();
if ( td->UnderlyingType->Type == ECode::Enum )
{
CodeEnum code = td->UnderlyingType.cast<CodeEnum>();
refactor_enum( code );
}
if ( td->UnderlyingType->Type == ECode::Struct )
{
CodeStruct code = td->UnderlyingType.cast<CodeStruct>();
refactor_struct( code );
}
}
if ( elem->Type == ECode::Struct )
{
refactor_struct( elem.cast<CodeStruct>() );
}
if ( elem->Type == ECode::Function || elem->Type == ECode::Function_Fwd )
{
refactor_fn( elem.cast<CodeFn>() );
}
if ( elem->Type == ECode::Extern_Linkage )
{
CodeBody body = elem.cast<CodeExtern>()->Body;
for ( Code elem : body )
{
if ( elem->Type == ECode::Function || elem->Type == ECode::Function_Fwd )
{
refactor_fn( elem.cast<CodeFn>() );
}
}
Code nspace = def_namespace( txt("raylib"), def_namespace_body( args(elem) ) );
elem = nspace;
}
new_code.append( elem );
} }
Builder builder = Builder::open( path );
builder.print( new_code );
builder.write();
} }
int gen_main() int gen_main()
{ {
gen::init(); gen::init();
FileContents config_file_content = file_read_contents( GlobalAllocator, true, path_config ); refactor_file( path_config );
CodeBody config_code = parse_global_body( { config_file_content.size, rcast(char const*, config_file_content.data) } ); refactor_file( path_raylib );
refactor_file( config_code ); refactor_file( path_raymath );
Builder config_builder = Builder::open( path_config );
config_builder.print( config_code );
config_builder.write();
FileContents raylib_file_content = file_read_contents( GlobalAllocator, true, path_raylib );
CodeBody raylib_code = parse_global_body( { raylib_file_content.size, rcast(char const*, raylib_file_content.data) } );
refactor_file( raylib_code );
Builder raylib_builder = Builder::open( path_raylib );
config_builder.print( raylib_code );
config_builder.write();
return 0; return 0;
} }

View File

@ -85,8 +85,12 @@ function setup-raylib {
New-Item $path_build -ItemType Directory New-Item $path_build -ItemType Directory
} }
$raylib_headers = Get-ChildItem -Path $path_raylib_src -Filter "*.h" -File
$raylib_modules = get-childitem -path $path_raylib_src -filter "*.c" -file
# Refactor raylib # Refactor raylib
if ( $true ) { if ( $true ) {
# if ( $false ) {
$path_gencpp = join-path $path_root 'project/gen' $path_gencpp = join-path $path_root 'project/gen'
$includes = @( $includes = @(
@ -114,6 +118,18 @@ function setup-raylib {
} }
} }
Pop-Location Pop-Location
push-location $path_scripts
# Time to format
$fmt_includes = @()
foreach ( $header in $raylib_headers ) {
$fmt_includes += split-path $header -leaf
}
foreach ( $module in $raylib_modules ) {
$fmt_includes += split-path $module -leaf
}
format-cpp $path_raylib_src $fmt_includes $null
pop-location
} }
# Build raylib # Build raylib
@ -151,12 +167,10 @@ function setup-raylib {
$dll = join-path $path_raylib_lib 'raylib.dll' $dll = join-path $path_raylib_lib 'raylib.dll'
# $build_result = build-simple $path_build $includes $compiler_args $linker_args $unit $dll # $build_result = build-simple $path_build $includes $compiler_args $linker_args $unit $dll
$raylib_modules = get-childitem -path $path_raylib_src -filter "*.c" -file
$build_result = build $path_build $includes $compiler_args $linker_args $raylib_modules $dll $build_result = build $path_build $includes $compiler_args $linker_args $raylib_modules $dll
} }
# Move headers to used include # Move headers to used include
$raylib_headers = Get-ChildItem -Path $path_raylib_src -Filter "*.h" -File
foreach ($header in $raylib_headers) { foreach ($header in $raylib_headers) {
Copy-Item -Path $header -Destination (join-path $path_raylib_inc (split-path $header -Leaf)) Copy-Item -Path $header -Destination (join-path $path_raylib_inc (split-path $header -Leaf))
} }

View File

@ -475,7 +475,8 @@ struct CodeParam
} }
CodeParam end() CodeParam end()
{ {
return { (AST_Param*) rcast( AST*, ast)->Last }; // return { (AST_Param*) rcast( AST*, ast)->Last };
return { nullptr }
} }
CodeParam& operator++(); CodeParam& operator++();
CodeParam operator*() CodeParam operator*()

View File

@ -7,7 +7,7 @@
#pragma region Constants #pragma region Constants
#ifndef GEN_GLOBAL_BUCKET_SIZE #ifndef GEN_GLOBAL_BUCKET_SIZE
# define GEN_GLOBAL_BUCKET_SIZE megabytes(4) # define GEN_GLOBAL_BUCKET_SIZE megabytes(8)
#endif #endif
#ifndef GEN_CODEPOOL_NUM_BLOCKS #ifndef GEN_CODEPOOL_NUM_BLOCKS
# define GEN_CODEPOOL_NUM_BLOCKS kilobytes(16) # define GEN_CODEPOOL_NUM_BLOCKS kilobytes(16)
@ -31,7 +31,7 @@
# define GEN_LEX_ALLOCATOR_SIZE megabytes(4) # define GEN_LEX_ALLOCATOR_SIZE megabytes(4)
#endif #endif
#ifndef GEN_BUILDER_STR_BUFFER_RESERVE #ifndef GEN_BUILDER_STR_BUFFER_RESERVE
# define GEN_BUILDER_STR_BUFFER_RESERVE megabytes(1) # define GEN_BUILDER_STR_BUFFER_RESERVE megabytes(2)
#endif #endif
// These constexprs are used for allocation behavior of data structures // These constexprs are used for allocation behavior of data structures

View File

@ -1294,7 +1294,7 @@ internal Code parse_compilcated_definition ();
internal CodeBody parse_class_struct_body ( Parser::TokType which, Parser::Token name = Parser::NullToken ); internal CodeBody parse_class_struct_body ( Parser::TokType which, Parser::Token name = Parser::NullToken );
internal Code parse_class_struct ( Parser::TokType which, bool inplace_def ); internal Code parse_class_struct ( Parser::TokType which, bool inplace_def );
internal CodeDefine parse_define (); internal CodeDefine parse_define ();
internal Code parse_foward_or_definition ( Parser::TokType which, bool is_inplace ); internal Code parse_forward_or_definition ( Parser::TokType which, bool is_inplace );
internal CodeFn parse_function_after_name ( ModuleFlag mflags, CodeAttributes attributes, CodeSpecifiers specifiers, CodeType ret_type, Parser::Token name ); internal CodeFn parse_function_after_name ( ModuleFlag mflags, CodeAttributes attributes, CodeSpecifiers specifiers, CodeType ret_type, Parser::Token name );
internal Code parse_function_body (); internal Code parse_function_body ();
internal Code parse_global_nspace (); internal Code parse_global_nspace ();
@ -1317,7 +1317,7 @@ internal CodeDestructor parse_destructor ( CodeSpecifiers specifiers = NoC
internal CodeEnum parse_enum ( bool inplace_def = false ); internal CodeEnum parse_enum ( bool inplace_def = false );
internal CodeBody parse_export_body (); internal CodeBody parse_export_body ();
internal CodeBody parse_extern_link_body(); internal CodeBody parse_extern_link_body();
internal CodeExtern parse_exten_link (); internal CodeExtern parse_extern_link ();
internal CodeFriend parse_friend (); internal CodeFriend parse_friend ();
internal CodeFn parse_function (); internal CodeFn parse_function ();
internal CodeNS parse_namespace (); internal CodeNS parse_namespace ();
@ -1784,7 +1784,7 @@ Code parse_complicated_definition( Parser::TokType which )
if ( (idx - 2 ) == tokens.Idx ) if ( (idx - 2 ) == tokens.Idx )
{ {
// Its a forward declaration only // Its a forward declaration only
Code result = parse_foward_or_definition( which, is_inplace ); Code result = parse_forward_or_definition( which, is_inplace );
Context.pop(); Context.pop();
return result; return result;
} }
@ -1834,7 +1834,7 @@ Code parse_complicated_definition( Parser::TokType which )
{ {
// Its a definition // Its a definition
// <which> { ... }; // <which> { ... };
Code result = parse_foward_or_definition( which, is_inplace ); Code result = parse_forward_or_definition( which, is_inplace );
Context.pop(); Context.pop();
return result; return result;
} }
@ -2267,7 +2267,7 @@ CodeDefine parse_define()
} }
internal inline internal inline
Code parse_foward_or_definition( Parser::TokType which, bool is_inplace ) Code parse_forward_or_definition( Parser::TokType which, bool is_inplace )
{ {
using namespace Parser; using namespace Parser;
@ -2499,7 +2499,7 @@ CodeBody parse_global_nspace( CodeT which )
if ( which == Extern_Linkage_Body ) if ( which == Extern_Linkage_Body )
log_failure( "Nested extern linkage\n%s", Context.to_string() ); log_failure( "Nested extern linkage\n%s", Context.to_string() );
member = parse_extern_link_body(); member = parse_extern_link();
break; break;
case TokType::Decl_Namespace: case TokType::Decl_Namespace:
@ -3693,7 +3693,10 @@ CodeVar parse_variable_after_name(
result->InlineCmt = inline_cmt; result->InlineCmt = inline_cmt;
if ( next_var ) if ( next_var )
result->NextVar = next_var; {
result->NextVar = next_var;
result->NextVar->Parent = result;
}
Context.pop(); Context.pop();
return result; return result;
@ -3758,15 +3761,18 @@ internal CodeVar parse_variable_declaration_list()
eat( TokType::Identifier ); eat( TokType::Identifier );
CodeVar var = parse_variable_after_name( ModuleFlag::None, NoCode, specifiers, NoCode, name ); CodeVar var = parse_variable_after_name( ModuleFlag::None, NoCode, specifiers, NoCode, name );
// TODO(Ed) : CodeVar is going to need a procedure to append comma-defined vars to itself.
if ( ! result ) if ( ! result )
{ {
result = var; result.ast = var.ast;
last_var = var; last_var.ast = var.ast;
} }
else else
{ {
last_var->NextVar = var; last_var->NextVar.ast = var.ast;
last_var = var; last_var->NextVar->Parent.ast = rcast(AST*, var.ast);
last_var.ast = var.ast;
} }
} }
@ -5319,7 +5325,7 @@ CodeTypedef parse_typedef()
if ( (idx - 2 ) == tokens.Idx ) if ( (idx - 2 ) == tokens.Idx )
{ {
// Its a forward declaration only // Its a forward declaration only
type = parse_foward_or_definition( currtok.Type, from_typedef ); type = parse_forward_or_definition( currtok.Type, from_typedef );
} }
Token tok = tokens[ idx - 1 ]; Token tok = tokens[ idx - 1 ];
@ -5360,13 +5366,13 @@ CodeTypedef parse_typedef()
// TODO(Ed) : I'm not sure if I have to use parse_type here, I'd rather not as that would complicate parse_type. // TODO(Ed) : I'm not sure if I have to use parse_type here, I'd rather not as that would complicate parse_type.
// type = parse_type(); // type = parse_type();
type = parse_foward_or_definition( currtok.Type, from_typedef ); type = parse_forward_or_definition( currtok.Type, from_typedef );
} }
else if ( tok.Type == TokType::BraceCurly_Close ) else if ( tok.Type == TokType::BraceCurly_Close )
{ {
// Its a definition // Its a definition
// <which> { ... }; // <which> { ... };
type = parse_foward_or_definition( currtok.Type, from_typedef ); type = parse_forward_or_definition( currtok.Type, from_typedef );
} }
else if ( tok.Type == TokType::BraceSquare_Close) else if ( tok.Type == TokType::BraceSquare_Close)
{ {