From 760cfd361e055326cf459812855d8dd83129c132 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sun, 15 Aug 2021 12:52:12 +0200 Subject: [PATCH 01/10] REVIEWED: `PHYSACDEF` definition and C++ issues #1918 --- src/extras/physac.h | 359 +++++++++++++++++++++----------------------- 1 file changed, 175 insertions(+), 184 deletions(-) diff --git a/src/extras/physac.h b/src/extras/physac.h index 7bcdb0f47..642c25a72 100644 --- a/src/extras/physac.h +++ b/src/extras/physac.h @@ -16,16 +16,9 @@ * If not defined, the library is in header only mode and can be included in other headers * or source files without problems. But only ONE file should hold the implementation. * -* #define PHYSAC_STATIC (defined by default) -* The generated implementation will stay private inside implementation file and all -* internal symbols and functions will only be visible inside that file. -* * #define PHYSAC_DEBUG * Show debug traces log messages about physic bodies creation/destruction, physic system errors, -* some calculations results and NULL reference exceptions -* -* #define PHYSAC_DEFINE_VECTOR2_TYPE -* Forces library to define struct Vector2 data type (float x; float y) +* some calculations results and NULL reference exceptions. * * #define PHYSAC_AVOID_TIMMING_SYSTEM * Disables internal timming system, used by UpdatePhysics() to launch timmed physic steps, @@ -79,14 +72,8 @@ #if !defined(PHYSAC_H) #define PHYSAC_H -#if defined(PHYSAC_STATIC) - #define PHYSACDEF static // Functions just visible to module including this file -#else - #if defined(__cplusplus) - #define PHYSACDEF extern "C" // Functions visible from other files (no name mangling of functions in C++) - #else - #define PHYSACDEF extern // Functions visible from other files - #endif +#ifndef PHYSACDEF + #define PHYSACDEF // We are building or using physac as a static library #endif // Allow custom memory allocators @@ -127,7 +114,7 @@ typedef enum PhysicsShapeType { PHYSICS_CIRCLE = 0, PHYSICS_POLYGON } PhysicsSha // Previously defined to be used in PhysicsShape struct as circular dependencies typedef struct PhysicsBodyData *PhysicsBody; -#if defined(PHYSAC_DEFINE_VECTOR2_TYPE) +#if !defined(RL_VECTOR2_TYPE) // Vector2 type typedef struct Vector2 { float x; @@ -192,13 +179,13 @@ typedef struct PhysicsManifoldData { float staticFriction; // Mixed static friction during collision } PhysicsManifoldData, *PhysicsManifold; -#if defined(__cplusplus) -extern "C" { // Prevents name mangling of functions -#endif - //---------------------------------------------------------------------------------- // Module Functions Declaration //---------------------------------------------------------------------------------- + +#if defined(__cplusplus) +extern "C" { // Prevents name mangling of functions +#endif // Physics system management PHYSACDEF void InitPhysics(void); // Initializes physics system PHYSACDEF void UpdatePhysics(void); // Update physics system @@ -225,7 +212,6 @@ PHYSACDEF int GetPhysicsBodiesCount(void); PHYSACDEF int GetPhysicsShapeType(int index); // Returns the physics body shape type (PHYSICS_CIRCLE or PHYSICS_POLYGON) PHYSACDEF int GetPhysicsShapeVerticesCount(int index); // Returns the amount of vertices of a physics body shape PHYSACDEF Vector2 GetPhysicsShapeVertex(PhysicsBody body, int vertex); // Returns transformed position of a body shape (body position + vertex transformed position) - #if defined(__cplusplus) } #endif @@ -253,11 +239,17 @@ PHYSACDEF Vector2 GetPhysicsShapeVertex(PhysicsBody body, int vertex); #if !defined(PHYSAC_AVOID_TIMMING_SYSTEM) // Time management functionality - #include // Required for: time(), clock_gettime() + #include // Required for: time(), clock_gettime() #if defined(_WIN32) + #if defined(__cplusplus) + extern "C" { // Prevents name mangling of functions + #endif // Functions required to query time on Windows int __stdcall QueryPerformanceCounter(unsigned long long int *lpPerformanceCount); int __stdcall QueryPerformanceFrequency(unsigned long long int *lpFrequency); + #if defined(__cplusplus) + } + #endif #endif #if defined(__linux__) || defined(__FreeBSD__) #if _POSIX_C_SOURCE < 199309L @@ -366,7 +358,7 @@ static Vector2 MathTriangleBarycenter(Vector2 v1, Vector2 v2, Vector2 v3); //---------------------------------------------------------------------------------- // Initializes physics values, pointers and creates physics loop thread -PHYSACDEF void InitPhysics(void) +void InitPhysics(void) { #if !defined(PHYSAC_AVOID_TIMMING_SYSTEM) // Initialize high resolution timer @@ -377,21 +369,21 @@ PHYSACDEF void InitPhysics(void) } // Sets physics global gravity force -PHYSACDEF void SetPhysicsGravity(float x, float y) +void SetPhysicsGravity(float x, float y) { gravityForce.x = x; gravityForce.y = y; } // Creates a new circle physics body with generic parameters -PHYSACDEF PhysicsBody CreatePhysicsBodyCircle(Vector2 pos, float radius, float density) +PhysicsBody CreatePhysicsBodyCircle(Vector2 pos, float radius, float density) { PhysicsBody body = CreatePhysicsBodyPolygon(pos, radius, PHYSAC_DEFAULT_CIRCLE_VERTICES, density); return body; } // Creates a new rectangle physics body with generic parameters -PHYSACDEF PhysicsBody CreatePhysicsBodyRectangle(Vector2 pos, float width, float height, float density) +PhysicsBody CreatePhysicsBodyRectangle(Vector2 pos, float width, float height, float density) { // NOTE: Make sure body data is initialized to 0 PhysicsBody body = (PhysicsBody)PHYSAC_CALLOC(sizeof(PhysicsBodyData), 1); @@ -469,7 +461,7 @@ PHYSACDEF PhysicsBody CreatePhysicsBodyRectangle(Vector2 pos, float width, float } // Creates a new polygon physics body with generic parameters -PHYSACDEF PhysicsBody CreatePhysicsBodyPolygon(Vector2 pos, float radius, int sides, float density) +PhysicsBody CreatePhysicsBodyPolygon(Vector2 pos, float radius, int sides, float density) { PhysicsBody body = (PhysicsBody)PHYSAC_MALLOC(sizeof(PhysicsBodyData)); usedMemory += sizeof(PhysicsBodyData); @@ -551,19 +543,19 @@ PHYSACDEF PhysicsBody CreatePhysicsBodyPolygon(Vector2 pos, float radius, int si } // Adds a force to a physics body -PHYSACDEF void PhysicsAddForce(PhysicsBody body, Vector2 force) +void PhysicsAddForce(PhysicsBody body, Vector2 force) { if (body != NULL) body->force = MathVector2Add(body->force, force); } // Adds an angular force to a physics body -PHYSACDEF void PhysicsAddTorque(PhysicsBody body, float amount) +void PhysicsAddTorque(PhysicsBody body, float amount) { if (body != NULL) body->torque += amount; } // Shatters a polygon shape physics body to little physics bodies with explosion force -PHYSACDEF void PhysicsShatter(PhysicsBody body, Vector2 position, float force) +void PhysicsShatter(PhysicsBody body, Vector2 position, float force) { if (body != NULL) { @@ -700,13 +692,13 @@ PHYSACDEF void PhysicsShatter(PhysicsBody body, Vector2 position, float force) } // Returns the current amount of created physics bodies -PHYSACDEF int GetPhysicsBodiesCount(void) +int GetPhysicsBodiesCount(void) { return physicsBodiesCount; } // Returns a physics body of the bodies pool at a specific index -PHYSACDEF PhysicsBody GetPhysicsBody(int index) +PhysicsBody GetPhysicsBody(int index) { PhysicsBody body = NULL; @@ -722,7 +714,7 @@ PHYSACDEF PhysicsBody GetPhysicsBody(int index) } // Returns the physics body shape type (PHYSICS_CIRCLE or PHYSICS_POLYGON) -PHYSACDEF int GetPhysicsShapeType(int index) +int GetPhysicsShapeType(int index) { int result = -1; @@ -739,7 +731,7 @@ PHYSACDEF int GetPhysicsShapeType(int index) } // Returns the amount of vertices of a physics body shape -PHYSACDEF int GetPhysicsShapeVerticesCount(int index) +int GetPhysicsShapeVerticesCount(int index) { int result = 0; @@ -764,7 +756,7 @@ PHYSACDEF int GetPhysicsShapeVerticesCount(int index) } // Returns transformed position of a body shape (body position + vertex transformed position) -PHYSACDEF Vector2 GetPhysicsShapeVertex(PhysicsBody body, int vertex) +Vector2 GetPhysicsShapeVertex(PhysicsBody body, int vertex) { Vector2 position = { 0.0f, 0.0f }; @@ -791,7 +783,7 @@ PHYSACDEF Vector2 GetPhysicsShapeVertex(PhysicsBody body, int vertex) } // Sets physics body shape transform based on radians parameter -PHYSACDEF void SetPhysicsBodyRotation(PhysicsBody body, float radians) +void SetPhysicsBodyRotation(PhysicsBody body, float radians) { if (body != NULL) { @@ -802,7 +794,7 @@ PHYSACDEF void SetPhysicsBodyRotation(PhysicsBody body, float radians) } // Unitializes and destroys a physics body -PHYSACDEF void DestroyPhysicsBody(PhysicsBody body) +void DestroyPhysicsBody(PhysicsBody body) { if (body != NULL) { @@ -844,7 +836,7 @@ PHYSACDEF void DestroyPhysicsBody(PhysicsBody body) } // Destroys created physics bodies and manifolds and resets global values -PHYSACDEF void ResetPhysics(void) +void ResetPhysics(void) { if (physicsBodiesCount > 0) { @@ -886,7 +878,7 @@ PHYSACDEF void ResetPhysics(void) } // Unitializes physics pointers and exits physics loop thread -PHYSACDEF void ClosePhysics(void) +void ClosePhysics(void) { // Unitialize physics manifolds dynamic memory allocations if (physicsManifoldsCount > 0) @@ -912,91 +904,98 @@ PHYSACDEF void ClosePhysics(void) else TRACELOG("[PHYSAC] Physics module closed successfully\n"); } +// Update physics system +// Physics steps are launched at a fixed time step if enabled +void UpdatePhysics(void) +{ +#if !defined(PHYSAC_AVOID_TIMMING_SYSTEM) + static double deltaTimeAccumulator = 0.0; + + // Calculate current time (ms) + currentTime = GetCurrentTime(); + + // Calculate current delta time (ms) + const double delta = currentTime - startTime; + + // Store the time elapsed since the last frame began + deltaTimeAccumulator += delta; + + // Fixed time stepping loop + while (deltaTimeAccumulator >= deltaTime) + { + UpdatePhysicsStep(); + deltaTimeAccumulator -= deltaTime; + } + + // Record the starting of this frame + startTime = currentTime; +#else + UpdatePhysicsStep(); +#endif +} + +void SetPhysicsTimeStep(double delta) +{ + deltaTime = delta; +} + //---------------------------------------------------------------------------------- // Module Internal Functions Definition //---------------------------------------------------------------------------------- -// Finds a valid index for a new physics body initialization -static int FindAvailableBodyIndex() +#if !defined(PHYSAC_AVOID_TIMMING_SYSTEM) +// Initializes hi-resolution MONOTONIC timer +static void InitTimerHiRes(void) { - int index = -1; - for (int i = 0; i < PHYSAC_MAX_BODIES; i++) - { - int currentId = i; +#if defined(_WIN32) + QueryPerformanceFrequency((unsigned long long int *) &frequency); +#endif - // Check if current id already exist in other physics body - for (unsigned int k = 0; k < physicsBodiesCount; k++) - { - if (bodies[k]->id == currentId) - { - currentId++; - break; - } - } +#if defined(__EMSCRIPTEN__) || defined(__linux__) + struct timespec now; + if (clock_gettime(CLOCK_MONOTONIC, &now) == 0) frequency = 1000000000; +#endif - // If it is not used, use it as new physics body id - if (currentId == (int)i) - { - index = (int)i; - break; - } - } +#if defined(__APPLE__) + mach_timebase_info_data_t timebase; + mach_timebase_info(&timebase); + frequency = (timebase.denom*1e9)/timebase.numer; +#endif - return index; + baseClockTicks = (double)GetClockTicks(); // Get MONOTONIC clock time offset + startTime = GetCurrentTime(); // Get current time in milliseconds } -// Creates a default polygon shape with max vertex distance from polygon pivot -static PhysicsVertexData CreateDefaultPolygon(float radius, int sides) +// Get hi-res MONOTONIC time measure in clock ticks +static unsigned long long int GetClockTicks(void) { - PhysicsVertexData data = { 0 }; - data.vertexCount = sides; + unsigned long long int value = 0; - // Calculate polygon vertices positions - for (unsigned int i = 0; i < data.vertexCount; i++) - { - data.positions[i].x = (float)cosf(360.0f/sides*i*PHYSAC_DEG2RAD)*radius; - data.positions[i].y = (float)sinf(360.0f/sides*i*PHYSAC_DEG2RAD)*radius; - } +#if defined(_WIN32) + QueryPerformanceCounter((unsigned long long int *) &value); +#endif - // Calculate polygon faces normals - for (int i = 0; i < (int)data.vertexCount; i++) - { - int nextIndex = (((i + 1) < sides) ? (i + 1) : 0); - Vector2 face = MathVector2Subtract(data.positions[nextIndex], data.positions[i]); +#if defined(__linux__) + struct timespec now; + clock_gettime(CLOCK_MONOTONIC, &now); + value = (unsigned long long int)now.tv_sec*(unsigned long long int)1000000000 + (unsigned long long int)now.tv_nsec; +#endif - data.normals[i] = CLITERAL(Vector2){ face.y, -face.x }; - MathVector2Normalize(&data.normals[i]); - } +#if defined(__APPLE__) + value = mach_absolute_time(); +#endif - return data; + return value; } -// Creates a rectangle polygon shape based on a min and max positions -static PhysicsVertexData CreateRectanglePolygon(Vector2 pos, Vector2 size) +// Get current time in milliseconds +static double GetCurrentTime(void) { - PhysicsVertexData data = { 0 }; - data.vertexCount = 4; - - // Calculate polygon vertices positions - data.positions[0] = CLITERAL(Vector2){ pos.x + size.x/2, pos.y - size.y/2 }; - data.positions[1] = CLITERAL(Vector2){ pos.x + size.x/2, pos.y + size.y/2 }; - data.positions[2] = CLITERAL(Vector2){ pos.x - size.x/2, pos.y + size.y/2 }; - data.positions[3] = CLITERAL(Vector2){ pos.x - size.x/2, pos.y - size.y/2 }; - - // Calculate polygon faces normals - for (unsigned int i = 0; i < data.vertexCount; i++) - { - int nextIndex = (((i + 1) < data.vertexCount) ? (i + 1) : 0); - Vector2 face = MathVector2Subtract(data.positions[nextIndex], data.positions[i]); - - data.normals[i] = CLITERAL(Vector2){ face.y, -face.x }; - MathVector2Normalize(&data.normals[i]); - } - - return data; + return (double)(GetClockTicks() - baseClockTicks)/frequency*1000; } +#endif // !PHYSAC_AVOID_TIMMING_SYSTEM // Update physics step (dynamics, collisions and position corrections) -void UpdatePhysicsStep(void) +static void UpdatePhysicsStep(void) { // Clear previous generated collisions information for (int i = (int)physicsManifoldsCount - 1; i >= 0; i--) @@ -1098,39 +1097,84 @@ void UpdatePhysicsStep(void) } } -// Update physics system -// Physics steps are launched at a fixed time step if enabled -PHYSACDEF void UpdatePhysics(void) +// Finds a valid index for a new physics body initialization +static int FindAvailableBodyIndex() { -#if !defined(PHYSAC_AVOID_TIMMING_SYSTEM) - static double deltaTimeAccumulator = 0.0; - - // Calculate current time (ms) - currentTime = GetCurrentTime(); - - // Calculate current delta time (ms) - const double delta = currentTime - startTime; - - // Store the time elapsed since the last frame began - deltaTimeAccumulator += delta; - - // Fixed time stepping loop - while (deltaTimeAccumulator >= deltaTime) + int index = -1; + for (int i = 0; i < PHYSAC_MAX_BODIES; i++) { - UpdatePhysicsStep(); - deltaTimeAccumulator -= deltaTime; + int currentId = i; + + // Check if current id already exist in other physics body + for (unsigned int k = 0; k < physicsBodiesCount; k++) + { + if (bodies[k]->id == currentId) + { + currentId++; + break; + } + } + + // If it is not used, use it as new physics body id + if (currentId == (int)i) + { + index = (int)i; + break; + } } - // Record the starting of this frame - startTime = currentTime; -#else - UpdatePhysicsStep(); -#endif + return index; } -PHYSACDEF void SetPhysicsTimeStep(double delta) +// Creates a default polygon shape with max vertex distance from polygon pivot +static PhysicsVertexData CreateDefaultPolygon(float radius, int sides) { - deltaTime = delta; + PhysicsVertexData data = { 0 }; + data.vertexCount = sides; + + // Calculate polygon vertices positions + for (unsigned int i = 0; i < data.vertexCount; i++) + { + data.positions[i].x = (float)cosf(360.0f/sides*i*PHYSAC_DEG2RAD)*radius; + data.positions[i].y = (float)sinf(360.0f/sides*i*PHYSAC_DEG2RAD)*radius; + } + + // Calculate polygon faces normals + for (int i = 0; i < (int)data.vertexCount; i++) + { + int nextIndex = (((i + 1) < sides) ? (i + 1) : 0); + Vector2 face = MathVector2Subtract(data.positions[nextIndex], data.positions[i]); + + data.normals[i] = CLITERAL(Vector2){ face.y, -face.x }; + MathVector2Normalize(&data.normals[i]); + } + + return data; +} + +// Creates a rectangle polygon shape based on a min and max positions +static PhysicsVertexData CreateRectanglePolygon(Vector2 pos, Vector2 size) +{ + PhysicsVertexData data = { 0 }; + data.vertexCount = 4; + + // Calculate polygon vertices positions + data.positions[0] = CLITERAL(Vector2){ pos.x + size.x/2, pos.y - size.y/2 }; + data.positions[1] = CLITERAL(Vector2){ pos.x + size.x/2, pos.y + size.y/2 }; + data.positions[2] = CLITERAL(Vector2){ pos.x - size.x/2, pos.y + size.y/2 }; + data.positions[3] = CLITERAL(Vector2){ pos.x - size.x/2, pos.y - size.y/2 }; + + // Calculate polygon faces normals + for (unsigned int i = 0; i < data.vertexCount; i++) + { + int nextIndex = (((i + 1) < data.vertexCount) ? (i + 1) : 0); + Vector2 face = MathVector2Subtract(data.positions[nextIndex], data.positions[i]); + + data.normals[i] = CLITERAL(Vector2){ face.y, -face.x }; + MathVector2Normalize(&data.normals[i]); + } + + return data; } // Finds a valid index for a new manifold initialization @@ -1844,59 +1888,6 @@ static Vector2 MathTriangleBarycenter(Vector2 v1, Vector2 v2, Vector2 v3) return result; } -#if !defined(PHYSAC_AVOID_TIMMING_SYSTEM) -// Initializes hi-resolution MONOTONIC timer -static void InitTimerHiRes(void) -{ -#if defined(_WIN32) - QueryPerformanceFrequency((unsigned long long int *) &frequency); -#endif - -#if defined(__EMSCRIPTEN__) || defined(__linux__) - struct timespec now; - if (clock_gettime(CLOCK_MONOTONIC, &now) == 0) frequency = 1000000000; -#endif - -#if defined(__APPLE__) - mach_timebase_info_data_t timebase; - mach_timebase_info(&timebase); - frequency = (timebase.denom*1e9)/timebase.numer; -#endif - - baseClockTicks = (double)GetClockTicks(); // Get MONOTONIC clock time offset - startTime = GetCurrentTime(); // Get current time in milliseconds -} - -// Get hi-res MONOTONIC time measure in clock ticks -static unsigned long long int GetClockTicks(void) -{ - unsigned long long int value = 0; - -#if defined(_WIN32) - QueryPerformanceCounter((unsigned long long int *) &value); -#endif - -#if defined(__linux__) - struct timespec now; - clock_gettime(CLOCK_MONOTONIC, &now); - value = (unsigned long long int)now.tv_sec*(unsigned long long int)1000000000 + (unsigned long long int)now.tv_nsec; -#endif - -#if defined(__APPLE__) - value = mach_absolute_time(); -#endif - - return value; -} - -// Get current time in milliseconds -static double GetCurrentTime(void) -{ - return (double)(GetClockTicks() - baseClockTicks)/frequency*1000; -} -#endif // !PHYSAC_AVOID_TIMMING_SYSTEM - - // Returns the cross product of a vector and a value static inline Vector2 MathVector2Product(Vector2 vector, float value) { From 848cdb267a7cc52ee0084185eacffdca2e9b3a31 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sun, 15 Aug 2021 12:58:34 +0200 Subject: [PATCH 02/10] Support C++ usage as standalone library --- src/gestures.h | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/gestures.h b/src/gestures.h index 2ed9f8fd9..355f60817 100644 --- a/src/gestures.h +++ b/src/gestures.h @@ -99,10 +99,6 @@ typedef struct { Vector2 position[4]; } GestureEvent; -#ifdef __cplusplus -extern "C" { // Prevents name mangling of functions -#endif - //---------------------------------------------------------------------------------- // Global Variables Definition //---------------------------------------------------------------------------------- @@ -111,11 +107,15 @@ extern "C" { // Prevents name mangling of functions //---------------------------------------------------------------------------------- // Module Functions Declaration //---------------------------------------------------------------------------------- + +#ifdef __cplusplus +extern "C" { // Prevents name mangling of functions +#endif + void ProcessGestureEvent(GestureEvent event); // Process gesture event and translate it into gestures void UpdateGestures(void); // Update gestures detected (must be called every frame) - #if defined(GESTURES_STANDALONE) -void SetGesturesEnabled(unsigned int flags); // Enable a set of gestures using flags +void SetGesturesEnabled(unsigned int flags); // Enable a set of gestures using flags bool IsGestureDetected(int gesture); // Check if a gesture have been detected int GetGestureDetected(void); // Get latest detected gesture int GetTouchPointsCount(void); // Get touch points count @@ -141,9 +141,15 @@ float GetGesturePinchAngle(void); // Get gesture pinch ang #if defined(GESTURES_IMPLEMENTATION) #if defined(_WIN32) + #if defined(__cplusplus) + extern "C" { // Prevents name mangling of functions + #endif // Functions required to query time on Windows int __stdcall QueryPerformanceCounter(unsigned long long int *lpPerformanceCount); int __stdcall QueryPerformanceFrequency(unsigned long long int *lpFrequency); + #if defined(__cplusplus) + } + #endif #elif defined(__linux__) #if _POSIX_C_SOURCE < 199309L #undef _POSIX_C_SOURCE From aae60e1e440ebd38573195ae81226f01d30f272b Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sun, 15 Aug 2021 13:02:53 +0200 Subject: [PATCH 03/10] REVIEWED: `extern "C"` definition position for consistency Note that `extern "C"` calling convention only affects objects that need to be seen by the linker, in our case only functions... but it would also be required by global variables exposed, if any. --- src/camera.h | 9 +++++---- src/raylib.h | 18 ++++++++---------- src/rlgl.h | 8 +++++--- src/utils.h | 8 +++++--- 4 files changed, 23 insertions(+), 20 deletions(-) diff --git a/src/camera.h b/src/camera.h index 35eda8310..084480894 100644 --- a/src/camera.h +++ b/src/camera.h @@ -94,10 +94,6 @@ } CameraProjection; #endif -#ifdef __cplusplus -extern "C" { // Prevents name mangling of functions -#endif - //---------------------------------------------------------------------------------- // Global Variables Definition //---------------------------------------------------------------------------------- @@ -106,6 +102,11 @@ extern "C" { // Prevents name mangling of functions //---------------------------------------------------------------------------------- // Module Functions Declaration //---------------------------------------------------------------------------------- + +#ifdef __cplusplus +extern "C" { // Prevents name mangling of functions +#endif + #if defined(CAMERA_STANDALONE) void SetCameraMode(Camera camera, int mode); // Set camera mode (multiple camera modes available) void UpdateCamera(Camera *camera); // Update camera position for selected mode diff --git a/src/raylib.h b/src/raylib.h index 7f8728137..4c05aeed8 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -83,17 +83,16 @@ #define RAYLIB_VERSION "3.8-dev" +#ifndef RLAPI + #define RLAPI // We are building or using rlgl as a static library (or Linux shared library) +#endif + #if defined(_WIN32) - // Microsoft attibutes to tell compiler that symbols are imported/exported from a .dll #if defined(BUILD_LIBTYPE_SHARED) #define RLAPI __declspec(dllexport) // We are building raylib as a Win32 shared library (.dll) #elif defined(USE_LIBTYPE_SHARED) #define RLAPI __declspec(dllimport) // We are using raylib as a Win32 shared library (.dll) - #else - #define RLAPI // We are building or using raylib as a static library #endif -#else - #define RLAPI // We are building or using raylib as a static library (or Linux shared library) #endif //---------------------------------------------------------------------------------- @@ -894,11 +893,6 @@ typedef bool (*SaveFileDataCallback)(const char *fileName, void *data, unsigned typedef char *(*LoadFileTextCallback)(const char *fileName); // FileIO: Load text data typedef bool (*SaveFileTextCallback)(const char *fileName, char *text); // FileIO: Save text data - -#if defined(__cplusplus) -extern "C" { // Prevents name mangling of functions -#endif - //------------------------------------------------------------------------------------ // Global Variables Definition //------------------------------------------------------------------------------------ @@ -908,6 +902,10 @@ extern "C" { // Prevents name mangling of functions // Window and Graphics Device Functions (Module: core) //------------------------------------------------------------------------------------ +#if defined(__cplusplus) +extern "C" { // Prevents name mangling of functions +#endif + // Window-related functions RLAPI void InitWindow(int width, int height, const char *title); // Initialize window and OpenGL context RLAPI bool WindowShouldClose(void); // Check if KEY_ESCAPE pressed or Close icon pressed diff --git a/src/rlgl.h b/src/rlgl.h index 6d18638db..3c995c79e 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -457,13 +457,14 @@ typedef enum { RL_SHADER_ATTRIB_VEC4 // Shader attribute type: vec4 (4 float) } rlShaderAttributeDataType; +//------------------------------------------------------------------------------------ +// Functions Declaration - Matrix operations +//------------------------------------------------------------------------------------ + #if defined(__cplusplus) extern "C" { // Prevents name mangling of functions #endif -//------------------------------------------------------------------------------------ -// Functions Declaration - Matrix operations -//------------------------------------------------------------------------------------ RLAPI void rlMatrixMode(int mode); // Choose the current matrix to be transformed RLAPI void rlPushMatrix(void); // Push the current matrix to stack RLAPI void rlPopMatrix(void); // Pop lattest inserted matrix from stack @@ -642,6 +643,7 @@ RLAPI void rlSetMatrixViewOffsetStereo(Matrix right, Matrix left); // Set e // Quick and dirty cube/quad buffers load->draw->unload RLAPI void rlLoadDrawCube(void); // Load and draw a cube RLAPI void rlLoadDrawQuad(void); // Load and draw a quad + #if defined(__cplusplus) } #endif diff --git a/src/utils.h b/src/utils.h index 50f704201..c9b331815 100644 --- a/src/utils.h +++ b/src/utils.h @@ -55,9 +55,7 @@ //---------------------------------------------------------------------------------- // Types and Structures Definition //---------------------------------------------------------------------------------- -#ifdef __cplusplus -extern "C" { // Prevents name mangling of functions -#endif +//... //---------------------------------------------------------------------------------- // Global Variables Definition @@ -67,6 +65,10 @@ extern "C" { // Prevents name mangling of functions //---------------------------------------------------------------------------------- // Module Functions Declaration //---------------------------------------------------------------------------------- +#ifdef __cplusplus +extern "C" { // Prevents name mangling of functions +#endif + #if defined(PLATFORM_ANDROID) 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! From 462e7aec526ca2efe45b5d6066964b1f5ed251bb Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sun, 15 Aug 2021 13:25:14 +0200 Subject: [PATCH 04/10] Updated `RAYLIB_VERSION` to `4.0-dev` Several breaking changes have been done lately so I think it's better to mark raylib for next release as 4.0. --- src/raylib.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/raylib.h b/src/raylib.h index 4c05aeed8..2e963ddc5 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -81,7 +81,7 @@ #include // Required for: va_list - Only used by TraceLogCallback -#define RAYLIB_VERSION "3.8-dev" +#define RAYLIB_VERSION "4.0-dev" #ifndef RLAPI #define RLAPI // We are building or using rlgl as a static library (or Linux shared library) From e203fb58c6025e28acec1f7340e185c00a1d3e2a Mon Sep 17 00:00:00 2001 From: "Dennis E. Hamilton" Date: Mon, 16 Aug 2021 00:53:14 -0700 Subject: [PATCH 05/10] Match build-windows.bat changes (#1923) The location for manual setting of the vcvarsall.bat location moved to line 38 in the latest change. --- projects/scripts/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/scripts/README.md b/projects/scripts/README.md index abb65b77c..b60e0ec88 100644 --- a/projects/scripts/README.md +++ b/projects/scripts/README.md @@ -6,7 +6,7 @@ exception to this however, and that is Windows, because Windows doesn't have a built-in C compiler. On Windows, you'll need to install [Visual Studio][visual-studio] or the [build tools][vs-tools]. If you didn't install them in the default location, write your changes around -line 101 of [`build-windows.bat`](build-windows.bat). +line 38 of [`build-windows.bat`](build-windows.bat). ## Script customization First of all, the scripts have a few variables at the very top, which From 1b4c58b66f670b521d2f707b3fa1be860738b33a Mon Sep 17 00:00:00 2001 From: Ray Date: Mon, 16 Aug 2021 11:06:31 +0200 Subject: [PATCH 06/10] WARNING: BREAKING: Use `frameCount` on audio This is a big change for optimization and a more professional understanding of audio. Instead of dealing with samples, now we deal with frames, like miniaudio does, so, avoiding continuous conversions from samples to frames. --- src/raudio.c | 160 ++++++++++++++++++++++++--------------------------- src/raudio.h | 51 ++++++++-------- src/raylib.h | 12 ++-- 3 files changed, 105 insertions(+), 118 deletions(-) diff --git a/src/raudio.c b/src/raudio.c index 9a4a6c944..072dc5d33 100644 --- a/src/raudio.c +++ b/src/raudio.c @@ -728,11 +728,11 @@ Wave LoadWaveFromMemory(const char *fileType, const unsigned char *fileData, int if (success) { - wave.sampleCount = (unsigned int)wav.totalPCMFrameCount*wav.channels; + wave.frameCount = (unsigned int)wav.totalPCMFrameCount; wave.sampleRate = wav.sampleRate; wave.sampleSize = 16; wave.channels = wav.channels; - wave.data = (short *)RL_MALLOC(wave.sampleCount*sizeof(short)); + wave.data = (short *)RL_MALLOC(wave.frameCount*wave.channels*sizeof(short)); // NOTE: We are forcing conversion to 16bit sample size on reading drwav_read_pcm_frames_s16(&wav, wav.totalPCMFrameCount, wave.data); @@ -754,11 +754,11 @@ Wave LoadWaveFromMemory(const char *fileType, const unsigned char *fileData, int wave.sampleRate = info.sample_rate; wave.sampleSize = 16; // By default, ogg data is 16 bit per sample (short) wave.channels = info.channels; - wave.sampleCount = (unsigned int)stb_vorbis_stream_length_in_samples(oggData)*info.channels; // Independent by channel - wave.data = (short *)RL_MALLOC(wave.sampleCount*sizeof(short)); + wave.frameCount = (unsigned int)stb_vorbis_stream_length_in_samples(oggData); // NOTE: It returns frames! + wave.data = (short *)RL_MALLOC(wave.frameCount*wave.channels*sizeof(short)); - // NOTE: Get the number of samples to process (be careful! we ask for number of shorts!) - stb_vorbis_get_samples_short_interleaved(oggData, info.channels, (short *)wave.data, wave.sampleCount); + // NOTE: Get the number of samples to process (be careful! we ask for number of shorts, not bytes!) + stb_vorbis_get_samples_short_interleaved(oggData, info.channels, (short *)wave.data, wave.frameCount*wave.channels); stb_vorbis_close(oggData); } else TRACELOG(LOG_WARNING, "WAVE: Failed to load OGG data"); @@ -773,7 +773,7 @@ Wave LoadWaveFromMemory(const char *fileType, const unsigned char *fileData, int wave.data = drflac_open_memory_and_read_pcm_frames_s16(fileData, dataSize, &wave.channels, &wave.sampleRate, &totalFrameCount, NULL); wave.sampleSize = 16; - if (wave.data != NULL) wave.sampleCount = (unsigned int)totalFrameCount*wave.channels; + if (wave.data != NULL) wave.frameCount = (unsigned int)totalFrameCount; else TRACELOG(LOG_WARNING, "WAVE: Failed to load FLAC data"); } #endif @@ -791,7 +791,7 @@ Wave LoadWaveFromMemory(const char *fileType, const unsigned char *fileData, int { wave.channels = config.channels; wave.sampleRate = config.sampleRate; - wave.sampleCount = (int)totalFrameCount*wave.channels; + wave.frameCount = (int)totalFrameCount; } else TRACELOG(LOG_WARNING, "WAVE: Failed to load MP3 data"); @@ -835,7 +835,7 @@ Sound LoadSoundFromWave(Wave wave) // First option has been selected, format conversion is done on the loading stage. // The downside is that it uses more memory if the original sound is u8 or s16. ma_format formatIn = ((wave.sampleSize == 8)? ma_format_u8 : ((wave.sampleSize == 16)? ma_format_s16 : ma_format_f32)); - ma_uint32 frameCountIn = wave.sampleCount/wave.channels; + ma_uint32 frameCountIn = wave.frameCount; ma_uint32 frameCount = (ma_uint32)ma_convert_frames(NULL, 0, AUDIO_DEVICE_FORMAT, AUDIO_DEVICE_CHANNELS, AUDIO.System.device.sampleRate, NULL, frameCountIn, formatIn, wave.channels, wave.sampleRate); if (frameCount == 0) TRACELOG(LOG_WARNING, "SOUND: Failed to get frame count for format conversion"); @@ -850,7 +850,7 @@ Sound LoadSoundFromWave(Wave wave) frameCount = (ma_uint32)ma_convert_frames(audioBuffer->data, frameCount, AUDIO_DEVICE_FORMAT, AUDIO_DEVICE_CHANNELS, AUDIO.System.device.sampleRate, wave.data, frameCountIn, formatIn, wave.channels, wave.sampleRate); if (frameCount == 0) TRACELOG(LOG_WARNING, "SOUND: Failed format conversion"); - sound.sampleCount = frameCount*AUDIO_DEVICE_CHANNELS; + sound.frameCount = frameCount; sound.stream.sampleRate = AUDIO.System.device.sampleRate; sound.stream.sampleSize = 32; sound.stream.channels = AUDIO_DEVICE_CHANNELS; @@ -908,7 +908,7 @@ bool ExportWave(Wave wave, const char *fileName) void *fileData = NULL; size_t fileDataSize = 0; success = drwav_init_memory_write(&wav, &fileData, &fileDataSize, &format, NULL); - if (success) success = (int)drwav_write_pcm_frames(&wav, wave.sampleCount/wave.channels, wave.data); + if (success) success = (int)drwav_write_pcm_frames(&wav, wave.frameCount, wave.data); drwav_result result = drwav_uninit(&wav); if (result == DRWAV_SUCCESS) success = SaveFileData(fileName, (unsigned char *)fileData, (unsigned int)fileDataSize); @@ -920,7 +920,7 @@ bool ExportWave(Wave wave, const char *fileName) { // Export raw sample data (without header) // NOTE: It's up to the user to track wave parameters - success = SaveFileData(fileName, wave.data, wave.sampleCount*wave.sampleSize/8); + success = SaveFileData(fileName, wave.data, wave.frameCount*wave.channels*wave.sampleSize/8); } if (success) TRACELOG(LOG_INFO, "FILEIO: [%s] Wave data exported successfully", fileName); @@ -938,7 +938,7 @@ bool ExportWaveAsCode(Wave wave, const char *fileName) #define TEXT_BYTES_PER_LINE 20 #endif - int waveDataSize = wave.sampleCount*wave.channels*wave.sampleSize/8; + int waveDataSize = wave.frameCount*wave.channels*wave.sampleSize/8; // NOTE: Text data buffer size is estimated considering wave data size in bytes // and requiring 6 char bytes for every byte: "0x00, " @@ -966,7 +966,8 @@ bool ExportWaveAsCode(Wave wave, const char *fileName) #endif bytesCount += sprintf(txtData + bytesCount, "// Wave data information\n"); - bytesCount += sprintf(txtData + bytesCount, "#define %s_SAMPLE_COUNT %u\n", varFileName, wave.sampleCount); + bytesCount += sprintf(txtData + bytesCount, "#define %s_FRAME_COUNT %u\n", varFileName, wave.frameCount); + bytesCount += sprintf(txtData + bytesCount, "#define %s_SAMPLE_COUNT %u\n", varFileName, wave.frameCount*wave.channels); bytesCount += sprintf(txtData + bytesCount, "#define %s_SAMPLE_RATE %u\n", varFileName, wave.sampleRate); bytesCount += sprintf(txtData + bytesCount, "#define %s_SAMPLE_SIZE %u\n", varFileName, wave.sampleSize); bytesCount += sprintf(txtData + bytesCount, "#define %s_CHANNELS %u\n\n", varFileName, wave.channels); @@ -1111,7 +1112,7 @@ void WaveFormat(Wave *wave, int sampleRate, int sampleSize, int channels) ma_format formatIn = ((wave->sampleSize == 8)? ma_format_u8 : ((wave->sampleSize == 16)? ma_format_s16 : ma_format_f32)); ma_format formatOut = ((sampleSize == 8)? ma_format_u8 : ((sampleSize == 16)? ma_format_s16 : ma_format_f32)); - ma_uint32 frameCountIn = wave->sampleCount/wave->channels; + ma_uint32 frameCountIn = wave->frameCount; ma_uint32 frameCount = (ma_uint32)ma_convert_frames(NULL, 0, formatOut, channels, sampleRate, NULL, frameCountIn, formatIn, wave->channels, wave->sampleRate); if (frameCount == 0) @@ -1129,7 +1130,7 @@ void WaveFormat(Wave *wave, int sampleRate, int sampleSize, int channels) return; } - wave->sampleCount = frameCount*channels; + wave->frameCount = frameCount; wave->sampleSize = sampleSize; wave->sampleRate = sampleRate; wave->channels = channels; @@ -1142,14 +1143,14 @@ Wave WaveCopy(Wave wave) { Wave newWave = { 0 }; - newWave.data = RL_MALLOC(wave.sampleCount*wave.sampleSize/8); + newWave.data = RL_MALLOC(wave.frameCount*wave.channels*wave.sampleSize/8); if (newWave.data != NULL) { // NOTE: Size must be provided in bytes - memcpy(newWave.data, wave.data, wave.sampleCount*wave.sampleSize/8); + memcpy(newWave.data, wave.data, wave.frameCount*wave.channels*wave.sampleSize/8); - newWave.sampleCount = wave.sampleCount; + newWave.frameCount = wave.frameCount; newWave.sampleRate = wave.sampleRate; newWave.sampleSize = wave.sampleSize; newWave.channels = wave.channels; @@ -1163,7 +1164,7 @@ Wave WaveCopy(Wave wave) void WaveCrop(Wave *wave, int initSample, int finalSample) { if ((initSample >= 0) && (initSample < finalSample) && - (finalSample > 0) && ((unsigned int)finalSample < wave->sampleCount)) + (finalSample > 0) && ((unsigned int)finalSample < (wave->frameCount*wave->channels))) { int sampleCount = finalSample - initSample; @@ -1182,11 +1183,11 @@ void WaveCrop(Wave *wave, int initSample, int finalSample) // NOTE 2: Sample data allocated should be freed with UnloadWaveSamples() float *LoadWaveSamples(Wave wave) { - float *samples = (float *)RL_MALLOC(wave.sampleCount*sizeof(float)); + float *samples = (float *)RL_MALLOC(wave.frameCount*wave.channels*sizeof(float)); // NOTE: sampleCount is the total number of interlaced samples (including channels) - for (unsigned int i = 0; i < wave.sampleCount; i++) + for (unsigned int i = 0; i < wave.frameCount*wave.channels; i++) { if (wave.sampleSize == 8) samples[i] = (float)(((unsigned char *)wave.data)[i] - 127)/256.0f; else if (wave.sampleSize == 16) samples[i] = (float)(((short *)wave.data)[i])/32767.0f; @@ -1228,7 +1229,7 @@ Music LoadMusicStream(const char *fileName) if (ctxWav->bitsPerSample == 24) sampleSize = 16; // Forcing conversion to s16 on UpdateMusicStream() music.stream = LoadAudioStream(ctxWav->sampleRate, sampleSize, ctxWav->channels); - music.sampleCount = (unsigned int)ctxWav->totalPCMFrameCount*ctxWav->channels; + music.frameCount = (unsigned int)ctxWav->totalPCMFrameCount; music.looping = true; // Looping enabled by default musicLoaded = true; } @@ -1249,7 +1250,7 @@ Music LoadMusicStream(const char *fileName) music.stream = LoadAudioStream(info.sample_rate, 16, info.channels); // WARNING: It seems this function returns length in frames, not samples, so we multiply by channels - music.sampleCount = (unsigned int)stb_vorbis_stream_length_in_samples((stb_vorbis *)music.ctxData)*info.channels; + music.frameCount = (unsigned int)stb_vorbis_stream_length_in_samples((stb_vorbis *)music.ctxData); music.looping = true; // Looping enabled by default musicLoaded = true; } @@ -1266,7 +1267,7 @@ Music LoadMusicStream(const char *fileName) drflac *ctxFlac = (drflac *)music.ctxData; music.stream = LoadAudioStream(ctxFlac->sampleRate, ctxFlac->bitsPerSample, ctxFlac->channels); - music.sampleCount = (unsigned int)ctxFlac->totalPCMFrameCount*ctxFlac->channels; + music.frameCount = (unsigned int)ctxFlac->totalPCMFrameCount; music.looping = true; // Looping enabled by default musicLoaded = true; } @@ -1284,7 +1285,7 @@ Music LoadMusicStream(const char *fileName) if (result > 0) { music.stream = LoadAudioStream(ctxMp3->sampleRate, 32, ctxMp3->channels); - music.sampleCount = (unsigned int)drmp3_get_pcm_frame_count(ctxMp3)*ctxMp3->channels; + music.frameCount = (unsigned int)drmp3_get_pcm_frame_count(ctxMp3); music.looping = true; // Looping enabled by default musicLoaded = true; } @@ -1309,9 +1310,9 @@ Music LoadMusicStream(const char *fileName) // NOTE: Only stereo is supported for XM music.stream = LoadAudioStream(AUDIO.System.device.sampleRate, bits, AUDIO_DEVICE_CHANNELS); - music.sampleCount = (unsigned int)jar_xm_get_remaining_samples(ctxXm)*2; // 2 channels + music.frameCount = (unsigned int)jar_xm_get_remaining_samples(ctxXm); // NOTE: Always 2 channels (stereo) music.looping = true; // Looping enabled by default - jar_xm_reset(ctxXm); // make sure we start at the beginning of the song + jar_xm_reset(ctxXm); // make sure we start at the beginning of the song musicLoaded = true; } } @@ -1330,7 +1331,7 @@ Music LoadMusicStream(const char *fileName) { // NOTE: Only stereo is supported for MOD music.stream = LoadAudioStream(AUDIO.System.device.sampleRate, 16, AUDIO_DEVICE_CHANNELS); - music.sampleCount = (unsigned int)jar_mod_max_samples(ctxMod)*2; // 2 channels + music.frameCount = (unsigned int)jar_mod_max_samples(ctxMod); // NOTE: Always 2 channels (stereo) music.looping = true; // Looping enabled by default musicLoaded = true; } @@ -1367,10 +1368,10 @@ Music LoadMusicStream(const char *fileName) { // Show some music stream info TRACELOG(LOG_INFO, "FILEIO: [%s] Music file loaded successfully", fileName); - TRACELOG(LOG_INFO, " > Total samples: %i", music.sampleCount); TRACELOG(LOG_INFO, " > Sample rate: %i Hz", music.stream.sampleRate); TRACELOG(LOG_INFO, " > Sample size: %i bits", music.stream.sampleSize); TRACELOG(LOG_INFO, " > Channels: %i (%s)", music.stream.channels, (music.stream.channels == 1)? "Mono" : (music.stream.channels == 2)? "Stereo" : "Multi"); + TRACELOG(LOG_INFO, " > Total frames: %i", music.frameCount); } return music; @@ -1402,7 +1403,7 @@ Music LoadMusicStreamFromMemory(const char *fileType, unsigned char *data, int d if (ctxWav->bitsPerSample == 24) sampleSize = 16; // Forcing conversion to s16 on UpdateMusicStream() music.stream = LoadAudioStream(ctxWav->sampleRate, sampleSize, ctxWav->channels); - music.sampleCount = (unsigned int)ctxWav->totalPCMFrameCount*ctxWav->channels; + music.frameCount = (unsigned int)ctxWav->totalPCMFrameCount; music.looping = true; // Looping enabled by default musicLoaded = true; } @@ -1419,7 +1420,7 @@ Music LoadMusicStreamFromMemory(const char *fileType, unsigned char *data, int d drflac *ctxFlac = (drflac *)music.ctxData; music.stream = LoadAudioStream(ctxFlac->sampleRate, ctxFlac->bitsPerSample, ctxFlac->channels); - music.sampleCount = (unsigned int)ctxFlac->totalPCMFrameCount*ctxFlac->channels; + music.frameCount = (unsigned int)ctxFlac->totalPCMFrameCount; music.looping = true; // Looping enabled by default musicLoaded = true; } @@ -1437,7 +1438,7 @@ Music LoadMusicStreamFromMemory(const char *fileType, unsigned char *data, int d if (success) { music.stream = LoadAudioStream(ctxMp3->sampleRate, 32, ctxMp3->channels); - music.sampleCount = (unsigned int)drmp3_get_pcm_frame_count(ctxMp3)*ctxMp3->channels; + music.frameCount = (unsigned int)drmp3_get_pcm_frame_count(ctxMp3); music.looping = true; // Looping enabled by default musicLoaded = true; } @@ -1459,7 +1460,7 @@ Music LoadMusicStreamFromMemory(const char *fileType, unsigned char *data, int d music.stream = LoadAudioStream(info.sample_rate, 16, info.channels); // WARNING: It seems this function returns length in frames, not samples, so we multiply by channels - music.sampleCount = (unsigned int)stb_vorbis_stream_length_in_samples((stb_vorbis *)music.ctxData)*info.channels; + music.frameCount = (unsigned int)stb_vorbis_stream_length_in_samples((stb_vorbis *)music.ctxData); music.looping = true; // Looping enabled by default musicLoaded = true; } @@ -1483,7 +1484,7 @@ Music LoadMusicStreamFromMemory(const char *fileType, unsigned char *data, int d // NOTE: Only stereo is supported for XM music.stream = LoadAudioStream(AUDIO.System.device.sampleRate, bits, 2); - music.sampleCount = (unsigned int)jar_xm_get_remaining_samples(ctxXm)*2; // 2 channels + music.frameCount = (unsigned int)jar_xm_get_remaining_samples(ctxXm); // NOTE: Always 2 channels (stereo) music.looping = true; // Looping enabled by default jar_xm_reset(ctxXm); // make sure we start at the beginning of the song @@ -1521,7 +1522,7 @@ Music LoadMusicStreamFromMemory(const char *fileType, unsigned char *data, int d // NOTE: Only stereo is supported for MOD music.stream = LoadAudioStream(AUDIO.System.device.sampleRate, 16, 2); - music.sampleCount = (unsigned int)jar_mod_max_samples(ctxMod)*2; // 2 channels + music.frameCount = (unsigned int)jar_mod_max_samples(ctxMod); // NOTE: Always 2 channels (stereo) music.looping = true; // Looping enabled by default musicLoaded = true; @@ -1561,10 +1562,10 @@ Music LoadMusicStreamFromMemory(const char *fileType, unsigned char *data, int d { // Show some music stream info TRACELOG(LOG_INFO, "FILEIO: Music data loaded successfully"); - TRACELOG(LOG_INFO, " > Total samples: %i", music.sampleCount); TRACELOG(LOG_INFO, " > Sample rate: %i Hz", music.stream.sampleRate); TRACELOG(LOG_INFO, " > Sample size: %i bits", music.stream.sampleSize); TRACELOG(LOG_INFO, " > Channels: %i (%s)", music.stream.channels, (music.stream.channels == 1)? "Mono" : (music.stream.channels == 2)? "Stereo" : "Multi"); + TRACELOG(LOG_INFO, " > Total frames: %i", music.frameCount); } return music; @@ -1660,29 +1661,22 @@ void UpdateMusicStream(Music music) { if (music.stream.buffer == NULL) return; -#if defined(SUPPORT_FILEFORMAT_XM) - if (music.ctxType == MUSIC_MODULE_XM) jar_xm_set_max_loop_count(music.ctxData, music.looping ? 0 : 1); -#endif - bool streamEnding = false; - unsigned int subBufferSizeInFrames = music.stream.buffer->sizeInFrames/2; // NOTE: Using dynamic allocation because it could require more than 16KB void *pcm = RL_CALLOC(subBufferSizeInFrames*music.stream.channels*music.stream.sampleSize/8, 1); - int samplesCount = 0; // Total size of data streamed in L+R samples for xm floats, individual L or R for ogg shorts + int frameCountToStream = 0; // Total size of data in frames to be streamed - // TODO: Get the sampleLeft using framesProcessed... but first, get total frames processed correctly... + // TODO: Get the framesLeft using framesProcessed... but first, get total frames processed correctly... //ma_uint32 frameSizeInBytes = ma_get_bytes_per_sample(music.stream.buffer->dsp.formatConverterIn.config.formatIn)*music.stream.buffer->dsp.formatConverterIn.config.channels; - int sampleLeft = music.sampleCount - (music.stream.buffer->framesProcessed*music.stream.channels); - - if (music.ctxType == MUSIC_MODULE_XM && music.looping) sampleLeft = subBufferSizeInFrames*4; + int framesLeft = music.frameCount - music.stream.buffer->framesProcessed; while (IsAudioStreamProcessed(music.stream)) { - if ((sampleLeft/music.stream.channels) >= subBufferSizeInFrames) samplesCount = subBufferSizeInFrames*music.stream.channels; - else samplesCount = sampleLeft; + if (framesLeft >= subBufferSizeInFrames) frameCountToStream = subBufferSizeInFrames; + else frameCountToStream = framesLeft; switch (music.ctxType) { @@ -1690,8 +1684,8 @@ void UpdateMusicStream(Music music) case MUSIC_AUDIO_WAV: { // NOTE: Returns the number of samples to process (not required) - if (music.stream.sampleSize == 16) drwav_read_pcm_frames_s16((drwav *)music.ctxData, samplesCount/music.stream.channels, (short *)pcm); - else if (music.stream.sampleSize == 32) drwav_read_pcm_frames_f32((drwav *)music.ctxData, samplesCount/music.stream.channels, (float *)pcm); + if (music.stream.sampleSize == 16) drwav_read_pcm_frames_s16((drwav *)music.ctxData, frameCountToStream, (short *)pcm); + else if (music.stream.sampleSize == 32) drwav_read_pcm_frames_f32((drwav *)music.ctxData, frameCountToStream, (float *)pcm); } break; #endif @@ -1699,7 +1693,7 @@ void UpdateMusicStream(Music music) case MUSIC_AUDIO_OGG: { // NOTE: Returns the number of samples to process (be careful! we ask for number of shorts!) - stb_vorbis_get_samples_short_interleaved((stb_vorbis *)music.ctxData, music.stream.channels, (short *)pcm, samplesCount); + stb_vorbis_get_samples_short_interleaved((stb_vorbis *)music.ctxData, music.stream.channels, (short *)pcm, frameCountToStream*music.stream.channels); } break; #endif @@ -1707,15 +1701,14 @@ void UpdateMusicStream(Music music) case MUSIC_AUDIO_FLAC: { // NOTE: Returns the number of samples to process (not required) - drflac_read_pcm_frames_s16((drflac *)music.ctxData, samplesCount, (short *)pcm); + drflac_read_pcm_frames_s16((drflac *)music.ctxData, frameCountToStream*music.stream.channels, (short *)pcm); } break; #endif #if defined(SUPPORT_FILEFORMAT_MP3) case MUSIC_AUDIO_MP3: { - // NOTE: samplesCount, actually refers to framesCount and returns the number of frames processed - drmp3_read_pcm_frames_f32((drmp3 *)music.ctxData, samplesCount/music.stream.channels, (float *)pcm); + drmp3_read_pcm_frames_f32((drmp3 *)music.ctxData, frameCountToStream, (float *)pcm); } break; #endif @@ -1723,9 +1716,9 @@ void UpdateMusicStream(Music music) case MUSIC_MODULE_XM: { // NOTE: Internally we consider 2 channels generation, so samplesCount/2 - if (AUDIO_DEVICE_FORMAT == ma_format_f32) jar_xm_generate_samples((jar_xm_context_t *)music.ctxData, (float *)pcm, samplesCount/2); - else if (AUDIO_DEVICE_FORMAT == ma_format_s16) jar_xm_generate_samples_16bit((jar_xm_context_t *)music.ctxData, (short *)pcm, samplesCount/2); - else if (AUDIO_DEVICE_FORMAT == ma_format_u8) jar_xm_generate_samples_8bit((jar_xm_context_t *)music.ctxData, (char *)pcm, samplesCount/2); + if (AUDIO_DEVICE_FORMAT == ma_format_f32) jar_xm_generate_samples((jar_xm_context_t *)music.ctxData, (float *)pcm, frameCountToStream); + else if (AUDIO_DEVICE_FORMAT == ma_format_s16) jar_xm_generate_samples_16bit((jar_xm_context_t *)music.ctxData, (short *)pcm, frameCountToStream); + else if (AUDIO_DEVICE_FORMAT == ma_format_u8) jar_xm_generate_samples_8bit((jar_xm_context_t *)music.ctxData, (char *)pcm, frameCountToStream); } break; #endif @@ -1733,22 +1726,17 @@ void UpdateMusicStream(Music music) case MUSIC_MODULE_MOD: { // NOTE: 3rd parameter (nbsample) specify the number of stereo 16bits samples you want, so sampleCount/2 - jar_mod_fillbuffer((jar_mod_context_t *)music.ctxData, (short *)pcm, samplesCount/2, 0); + jar_mod_fillbuffer((jar_mod_context_t *)music.ctxData, (short *)pcm, frameCountToStream, 0); } break; #endif default: break; } - UpdateAudioStream(music.stream, pcm, samplesCount); + UpdateAudioStream(music.stream, pcm, frameCountToStream); + + framesLeft -= frameCountToStream; - if ((music.ctxType == MUSIC_MODULE_XM) || music.ctxType == MUSIC_MODULE_MOD) - { - if (samplesCount > 1) sampleLeft -= samplesCount/2; - else sampleLeft -= samplesCount; - } - else sampleLeft -= samplesCount; - - if (sampleLeft <= 0) + if (framesLeft <= 0) { streamEnding = true; break; @@ -1795,7 +1783,7 @@ float GetMusicTimeLength(Music music) { float totalSeconds = 0.0f; - totalSeconds = (float)music.sampleCount/(music.stream.sampleRate*music.stream.channels); + totalSeconds = (float)music.frameCount/music.stream.sampleRate; return totalSeconds; } @@ -1803,22 +1791,24 @@ float GetMusicTimeLength(Music music) // Get current music time played (in seconds) float GetMusicTimePlayed(Music music) { -#if defined(SUPPORT_FILEFORMAT_XM) - if (music.ctxType == MUSIC_MODULE_XM) - { - uint64_t samples = 0; - jar_xm_get_position(music.ctxData, NULL, NULL, NULL, &samples); - samples = samples % (music.sampleCount); - - return (float)(samples)/(music.stream.sampleRate*music.stream.channels); - } -#endif float secondsPlayed = 0.0f; if (music.stream.buffer != NULL) { - //ma_uint32 frameSizeInBytes = ma_get_bytes_per_sample(music.stream.buffer->dsp.formatConverterIn.config.formatIn)*music.stream.buffer->dsp.formatConverterIn.config.channels; - unsigned int samplesPlayed = music.stream.buffer->framesProcessed*music.stream.channels; - secondsPlayed = (float)samplesPlayed/(music.stream.sampleRate*music.stream.channels); + #if defined(SUPPORT_FILEFORMAT_XM) + if (music.ctxType == MUSIC_MODULE_XM) + { + uint64_t framesPlayed = 0; + + jar_xm_get_position(music.ctxData, NULL, NULL, NULL, &framesPlayed); + secondsPlayed = (float)framesPlayed/music.stream.sampleRate; + } + else + #endif + { + //ma_uint32 frameSizeInBytes = ma_get_bytes_per_sample(music.stream.buffer->dsp.formatConverterIn.config.formatIn)*music.stream.buffer->dsp.formatConverterIn.config.channels; + unsigned int framesPlayed = music.stream.buffer->framesProcessed; + secondsPlayed = (float)framesPlayed/music.stream.sampleRate; + } } return secondsPlayed; @@ -1867,7 +1857,7 @@ void UnloadAudioStream(AudioStream stream) // Update audio stream buffers with data // NOTE 1: Only updates one buffer of the stream source: unqueue -> update -> queue // NOTE 2: To unqueue a buffer it needs to be processed: IsAudioStreamProcessed() -void UpdateAudioStream(AudioStream stream, const void *data, int samplesCount) +void UpdateAudioStream(AudioStream stream, const void *data, int frameCount) { if (stream.buffer != NULL) { @@ -1896,11 +1886,11 @@ void UpdateAudioStream(AudioStream stream, const void *data, int samplesCount) // Does this API expect a whole buffer to be updated in one go? // Assuming so, but if not will need to change this logic. - if (subBufferSizeInFrames >= (ma_uint32)samplesCount/stream.channels) + if (subBufferSizeInFrames >= (ma_uint32)frameCount) { ma_uint32 framesToWrite = subBufferSizeInFrames; - if (framesToWrite > ((ma_uint32)samplesCount/stream.channels)) framesToWrite = (ma_uint32)samplesCount/stream.channels; + if (framesToWrite > (ma_uint32)frameCount) framesToWrite = (ma_uint32)frameCount; ma_uint32 bytesToWrite = framesToWrite*stream.channels*(stream.sampleSize/8); memcpy(subBuffer, data, bytesToWrite); diff --git a/src/raudio.h b/src/raudio.h index e8a1ebaff..cddb35681 100644 --- a/src/raudio.h +++ b/src/raudio.h @@ -78,49 +78,42 @@ #endif #endif -// Wave type, defines audio wave data +// Wave, audio wave data typedef struct Wave { - unsigned int sampleCount; // Total number of samples - unsigned int sampleRate; // Frequency (samples per second) - unsigned int sampleSize; // Bit depth (bits per sample): 8, 16, 32 (24 not supported) - unsigned int channels; // Number of channels (1-mono, 2-stereo) - void *data; // Buffer data pointer + unsigned int frameCount; // Total number of frames (considering channels) + unsigned int sampleRate; // Frequency (samples per second) + unsigned int sampleSize; // Bit depth (bits per sample): 8, 16, 32 (24 not supported) + unsigned int channels; // Number of channels (1-mono, 2-stereo, ...) + void *data; // Buffer data pointer } Wave; typedef struct rAudioBuffer rAudioBuffer; -// Audio stream type -// NOTE: Useful to create custom audio streams not bound to a specific file +// AudioStream, custom audio stream typedef struct AudioStream { - unsigned int sampleRate; // Frequency (samples per second) - unsigned int sampleSize; // Bit depth (bits per sample): 8, 16, 32 (24 not supported) - unsigned int channels; // Number of channels (1-mono, 2-stereo) + rAudioBuffer *buffer; // Pointer to internal data used by the audio system - rAudioBuffer *buffer; // Pointer to internal data used by the audio system + unsigned int sampleRate; // Frequency (samples per second) + unsigned int sampleSize; // Bit depth (bits per sample): 8, 16, 32 (24 not supported) + unsigned int channels; // Number of channels (1-mono, 2-stereo, ...) } AudioStream; -// Sound source type +// Sound typedef struct Sound { - unsigned int sampleCount; // Total number of samples - AudioStream stream; // Audio stream + AudioStream stream; // Audio stream + unsigned int frameCount; // Total number of frames (considering channels) } Sound; -// Music stream type (audio file streaming from memory) -// NOTE: Anything longer than ~10 seconds should be streamed +// Music, audio stream, anything longer than ~10 seconds should be streamed typedef struct Music { - int ctxType; // Type of music context (audio filetype) - void *ctxData; // Audio context data, depends on type + AudioStream stream; // Audio stream + unsigned int frameCount; // Total number of frames (considering channels) + bool looping; // Music looping enable - bool looping; // Music looping enable - unsigned int sampleCount; // Total number of samples - - AudioStream stream; // Audio stream + int ctxType; // Type of music context (audio filetype) + void *ctxData; // Audio context data, depends on type } Music; -#ifdef __cplusplus -extern "C" { // Prevents name mangling of functions -#endif - //---------------------------------------------------------------------------------- // Global Variables Definition //---------------------------------------------------------------------------------- @@ -130,6 +123,10 @@ extern "C" { // Prevents name mangling of functions // Module Functions Declaration //---------------------------------------------------------------------------------- +#ifdef __cplusplus +extern "C" { // Prevents name mangling of functions +#endif + // Audio device management functions void InitAudioDevice(void); // Initialize audio device and context void CloseAudioDevice(void); // Close the audio device and context diff --git a/src/raylib.h b/src/raylib.h index 2e963ddc5..c7b4b282b 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -423,10 +423,10 @@ typedef struct BoundingBox { // Wave, audio wave data typedef struct Wave { - unsigned int sampleCount; // Total number of samples (considering channels!) + unsigned int frameCount; // Total number of frames (considering channels) unsigned int sampleRate; // Frequency (samples per second) unsigned int sampleSize; // Bit depth (bits per sample): 8, 16, 32 (24 not supported) - unsigned int channels; // Number of channels (1-mono, 2-stereo) + unsigned int channels; // Number of channels (1-mono, 2-stereo, ...) void *data; // Buffer data pointer } Wave; @@ -438,19 +438,19 @@ typedef struct AudioStream { unsigned int sampleRate; // Frequency (samples per second) unsigned int sampleSize; // Bit depth (bits per sample): 8, 16, 32 (24 not supported) - unsigned int channels; // Number of channels (1-mono, 2-stereo) + unsigned int channels; // Number of channels (1-mono, 2-stereo, ...) } AudioStream; // Sound typedef struct Sound { AudioStream stream; // Audio stream - unsigned int sampleCount; // Total number of samples + unsigned int frameCount; // Total number of frames (considering channels) } Sound; // Music, audio stream, anything longer than ~10 seconds should be streamed typedef struct Music { AudioStream stream; // Audio stream - unsigned int sampleCount; // Total number of samples + unsigned int frameCount; // Total number of frames (considering channels) bool looping; // Music looping enable int ctxType; // Type of music context (audio filetype) @@ -1513,7 +1513,7 @@ RLAPI float GetMusicTimePlayed(Music music); // Get cur // AudioStream management functions RLAPI AudioStream LoadAudioStream(unsigned int sampleRate, unsigned int sampleSize, unsigned int channels); // Load audio stream (to stream raw audio pcm data) RLAPI void UnloadAudioStream(AudioStream stream); // Unload audio stream and free memory -RLAPI void UpdateAudioStream(AudioStream stream, const void *data, int samplesCount); // Update audio stream buffers with data +RLAPI void UpdateAudioStream(AudioStream stream, const void *data, int framesCount); // Update audio stream buffers with data RLAPI bool IsAudioStreamProcessed(AudioStream stream); // Check if any audio stream buffers requires refill RLAPI void PlayAudioStream(AudioStream stream); // Play audio stream RLAPI void PauseAudioStream(AudioStream stream); // Pause audio stream From 92a13878dce2962fa0c701ff69ea2de3cbeeaeab Mon Sep 17 00:00:00 2001 From: Ray Date: Mon, 16 Aug 2021 19:23:06 +0200 Subject: [PATCH 07/10] Add some comments --- src/rlgl.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/rlgl.h b/src/rlgl.h index 3c995c79e..45d44b16f 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -3431,6 +3431,10 @@ unsigned int rlLoadShaderCode(const char *vsCode, const char *fsCode) if (vsCode != NULL) vertexShaderId = rlCompileShader(vsCode, GL_VERTEX_SHADER); if (fsCode != NULL) fragmentShaderId = rlCompileShader(fsCode, GL_FRAGMENT_SHADER); + + // Get the size of compiled shaders (not available on OpenGL ES 2.0) + //GLint binarySize = 0; + //glGetProgramiv(programId, GL_PROGRAM_BINARY_LENGTH, &binarySize); if ((vertexShaderId == RLGL.State.defaultVShaderId) && (fragmentShaderId == RLGL.State.defaultFShaderId)) id = RLGL.State.defaultShaderId; else @@ -3467,7 +3471,7 @@ unsigned int rlLoadShaderCode(const char *vsCode, const char *fsCode) { int namelen = -1; int num = -1; - char name[256]; // Assume no variable names longer than 256 + char name[256] = { 0 }; // Assume no variable names longer than 256 GLenum type = GL_ZERO; // Get the name of the uniforms From ef8526ae36df83f876b1175d8eccb2b3187a66e3 Mon Sep 17 00:00:00 2001 From: Ray Date: Mon, 16 Aug 2021 19:26:10 +0200 Subject: [PATCH 08/10] Update rlgl.h --- src/rlgl.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/rlgl.h b/src/rlgl.h index 45d44b16f..df9b63b66 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -3432,14 +3432,15 @@ unsigned int rlLoadShaderCode(const char *vsCode, const char *fsCode) if (vsCode != NULL) vertexShaderId = rlCompileShader(vsCode, GL_VERTEX_SHADER); if (fsCode != NULL) fragmentShaderId = rlCompileShader(fsCode, GL_FRAGMENT_SHADER); - // Get the size of compiled shaders (not available on OpenGL ES 2.0) - //GLint binarySize = 0; - //glGetProgramiv(programId, GL_PROGRAM_BINARY_LENGTH, &binarySize); - if ((vertexShaderId == RLGL.State.defaultVShaderId) && (fragmentShaderId == RLGL.State.defaultFShaderId)) id = RLGL.State.defaultShaderId; else { id = rlLoadShaderProgram(vertexShaderId, fragmentShaderId); + + // Get the size of compiled shader program (not available on OpenGL ES 2.0) + // NOTE: If GL_LINK_STATUS is GL_FALSE, program binary length is zero. + //GLint binarySize = 0; + //glGetProgramiv(id, GL_PROGRAM_BINARY_LENGTH, &binarySize); if (vertexShaderId != RLGL.State.defaultVShaderId) { From f3385b6ad22af53245e20ab3dda10853e1ee95a4 Mon Sep 17 00:00:00 2001 From: Ray Date: Mon, 16 Aug 2021 19:52:57 +0200 Subject: [PATCH 09/10] Update rlgl.h --- src/rlgl.h | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/rlgl.h b/src/rlgl.h index df9b63b66..9b705473f 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -3436,11 +3436,6 @@ unsigned int rlLoadShaderCode(const char *vsCode, const char *fsCode) else { id = rlLoadShaderProgram(vertexShaderId, fragmentShaderId); - - // Get the size of compiled shader program (not available on OpenGL ES 2.0) - // NOTE: If GL_LINK_STATUS is GL_FALSE, program binary length is zero. - //GLint binarySize = 0; - //glGetProgramiv(id, GL_PROGRAM_BINARY_LENGTH, &binarySize); if (vertexShaderId != RLGL.State.defaultVShaderId) { @@ -3587,7 +3582,15 @@ unsigned int rlLoadShaderProgram(unsigned int vShaderId, unsigned int fShaderId) program = 0; } - else TRACELOG(RL_LOG_INFO, "SHADER: [ID %i] Program shader loaded successfully", program); + else + { + // Get the size of compiled shader program (not available on OpenGL ES 2.0) + // NOTE: If GL_LINK_STATUS is GL_FALSE, program binary length is zero. + //GLint binarySize = 0; + //glGetProgramiv(id, GL_PROGRAM_BINARY_LENGTH, &binarySize); + + TRACELOG(RL_LOG_INFO, "SHADER: [ID %i] Program shader loaded successfully", program); + } #endif return program; } From a5beb940f8f08d91b33634ca7dc056f07f60f20c Mon Sep 17 00:00:00 2001 From: Ray Date: Mon, 16 Aug 2021 23:23:16 +0200 Subject: [PATCH 10/10] Remove trailing spaces --- src/external/jar_xm.h | 52 +++++++++++++++++++++---------------------- src/models.c | 28 +++++++++++------------ src/raudio.c | 2 +- src/raymath.h | 2 +- src/rlgl.h | 52 +++++++++++++++++++++---------------------- src/text.c | 18 +++++++-------- src/textures.c | 40 ++++++++++++++++----------------- 7 files changed, 97 insertions(+), 97 deletions(-) diff --git a/src/external/jar_xm.h b/src/external/jar_xm.h index ea7a32831..82170f54d 100644 --- a/src/external/jar_xm.h +++ b/src/external/jar_xm.h @@ -75,7 +75,7 @@ struct jar_xm_context_s; typedef struct jar_xm_context_s jar_xm_context_t; #ifdef __cplusplus -extern "C" { +extern "C" { #endif //** Create a XM context. @@ -363,7 +363,7 @@ struct jar_xm_sample_s { uint16_t num_patterns; uint16_t num_instruments; uint16_t linear_interpolation; - uint16_t ramping; + uint16_t ramping; jar_xm_frequency_type_t frequency_type; uint8_t pattern_table[PATTERN_ORDER_TABLE_LENGTH]; @@ -457,7 +457,7 @@ struct jar_xm_sample_s { uint16_t default_tempo; // Number of ticks per row uint16_t default_bpm; float default_global_volume; - + uint16_t tempo; // Number of ticks per row uint16_t bpm; float global_volume; @@ -708,7 +708,7 @@ int jar_xm_check_sanity_postload(jar_xm_context_t* ctx) { if(ctx->module.pattern_table[i] >= ctx->module.num_patterns) { if(i+1 == ctx->module.length && ctx->module.length > 1) { DEBUG("trimming invalid POT at pos %X", i); - --ctx->module.length; + --ctx->module.length; } else { DEBUG("module has invalid POT, pos %X references nonexistent pattern %X", i, ctx->module.pattern_table[i]); return 1; @@ -823,7 +823,7 @@ char* jar_xm_load_module(jar_xm_context_t* ctx, const char* moddata, size_t modd pat->slots = (jar_xm_pattern_slot_t*)mempool; mempool += mod->num_channels * pat->num_rows * sizeof(jar_xm_pattern_slot_t); offset += READ_U32(offset); /* Pattern header length */ - + if(packed_patterndata_size == 0) { /* No pattern data is present */ memset(pat->slots, 0, sizeof(jar_xm_pattern_slot_t) * pat->num_rows * mod->num_channels); } else { @@ -1236,7 +1236,7 @@ static void jar_xm_post_pattern_change(jar_xm_context_t* ctx) { /* Loop if necessary */ if(ctx->current_table_index >= ctx->module.length) { ctx->current_table_index = ctx->module.restart_position; - ctx->tempo =ctx->default_tempo; // reset to file default value + ctx->tempo =ctx->default_tempo; // reset to file default value ctx->bpm = ctx->default_bpm; // reset to file default value ctx->global_volume = ctx->default_global_volume; // reset to file default value } @@ -1586,7 +1586,7 @@ static void jar_xm_trigger_note(jar_xm_context_t* ctx, jar_xm_channel_context_t* ch->sample_position = 0.f; ch->ping = true; }; - + if (!(flags & jar_xm_TRIGGER_KEEP_VOLUME)) { if(ch->sample != NULL) { ch->volume = ch->sample->volume; @@ -1665,7 +1665,7 @@ static void jar_xm_row(jar_xm_context_t* ctx) { /* No E6y loop is in effect (or we are in the first pass) */ ctx->loop_count = (ctx->row_loop_count[MAX_NUM_ROWS * ctx->current_table_index + ctx->current_row]++); } - + /// Move to next row ctx->current_row++; /* uint8 warning: can increment from 255 to 0, in which case it is still necessary to go the next pattern. */ if (!ctx->position_jump && !ctx->pattern_break && (ctx->current_row >= cur->num_rows || ctx->current_row == 0)) { @@ -1721,7 +1721,7 @@ static void jar_xm_tick(jar_xm_context_t* ctx) { if(ctx->current_tick == 0) { jar_xm_row(ctx); // We have processed all ticks and we run the row } - + jar_xm_module_t* mod = &(ctx->module); for(uint8_t i = 0; i < ctx->module.num_channels; ++i) { jar_xm_channel_context_t* ch = ctx->channels + i; @@ -1885,7 +1885,7 @@ static void jar_xm_tick(jar_xm_context_t* ctx) { } break; case 16: /* Fxy: Set tempo/BPM */ - break; + break; case 17: /* Hxy: Global volume slide */ if(ctx->current_tick == 0) break; if((ch->global_volume_slide_param & 0xF0) && (ch->global_volume_slide_param & 0x0F)) { break; }; /* Invalid state */ @@ -1904,7 +1904,7 @@ static void jar_xm_tick(jar_xm_context_t* ctx) { if(ctx->current_tick == ch->current->effect_param) { jar_xm_key_off(ch); }; break; case 21: /* Lxx: Set envelope position */ - break; + break; case 25: /* Pxy: Panning slide */ if(ctx->current_tick == 0) break; jar_xm_panning_slide(ch, ch->panning_slide_param); @@ -2105,7 +2105,7 @@ static void jar_xm_next_of_sample(jar_xm_context_t* ctx, jar_xm_channel_context_ // gather all channel audio into stereo float static void jar_xm_mixdown(jar_xm_context_t* ctx, float* left, float* right) { jar_xm_module_t* mod = &(ctx->module); - + if(ctx->remaining_samples_in_tick <= 0) { jar_xm_tick(ctx); }; @@ -2142,7 +2142,7 @@ static void jar_xm_mixdown(jar_xm_context_t* ctx, float* left, float* right) { // apply brick wall limiter when audio goes beyond bounderies if(*left < -1.0) {*left = -1.0;} else if(*left > 1.0) {*left = 1.0;}; - if(*right < -1.0) {*right = -1.0;} else if(*right > 1.0) {*right = 1.0;}; + if(*right < -1.0) {*right = -1.0;} else if(*right > 1.0) {*right = 1.0;}; }; void jar_xm_generate_samples(jar_xm_context_t* ctx, float* output, size_t numsamples) { @@ -2244,7 +2244,7 @@ int jar_xm_create_context_from_file(jar_xm_context_t** ctx, uint32_t rate, const return 6; break; } - + return 0; } @@ -2256,7 +2256,7 @@ void jar_xm_reset(jar_xm_context_t* ctx) { ctx->current_row = 0; ctx->current_table_index = 0; ctx->current_tick = 0; - ctx->tempo =ctx->default_tempo; // reset to file default value + ctx->tempo =ctx->default_tempo; // reset to file default value ctx->bpm = ctx->default_bpm; // reset to file default value ctx->global_volume = ctx->default_global_volume; // reset to file default value } @@ -2282,7 +2282,7 @@ void jar_xm_table_jump(jar_xm_context_t* ctx, int table_ptr) { } else { ctx->current_table_index = 0; ctx->module.restart_position = 0; // The reason to jump is to start a new loop or track - ctx->tempo =ctx->default_tempo; // reset to file default value + ctx->tempo =ctx->default_tempo; // reset to file default value ctx->bpm = ctx->default_bpm; // reset to file default value ctx->global_volume = ctx->default_global_volume; // reset to file default value }; @@ -2383,31 +2383,31 @@ void jar_xm_debug(jar_xm_context_t *ctx) { y += size; DrawText(TextFormat("LCT = %i", ctx->loop_count), x, y, size, WHITE); y += size; DrawText(TextFormat("MAX LCT = %i", ctx->max_loop_count), x, y, size, WHITE); x = size * 12; y = 0; - + y += size; DrawText(TextFormat("CUR TCK = %i", ctx->current_tick), x, y, size, WHITE); y += size; DrawText(TextFormat("XTR TCK = %i", ctx->extra_ticks), x, y, size, WHITE); y += size; DrawText(TextFormat("TCK/ROW = %i", ctx->tempo), x, y, size, ORANGE); y += size; DrawText(TextFormat("SPL TCK = %f", ctx->remaining_samples_in_tick), x, y, size, WHITE); y += size; DrawText(TextFormat("GEN SPL = %i", ctx->generated_samples), x, y, size, WHITE); y += size * 7; - + x = 0; size=16; // TIMELINE OF MODULE for (int i=0; i < ctx->module.length; i++) { if (i == ctx->jump_dest) { if (ctx->position_jump) { - DrawRectangle(i * size * 2, y - size, size * 2, size, GOLD); + DrawRectangle(i * size * 2, y - size, size * 2, size, GOLD); } else { - DrawRectangle(i * size * 2, y - size, size * 2, size, BROWN); + DrawRectangle(i * size * 2, y - size, size * 2, size, BROWN); }; }; if (i == ctx->current_table_index) { // DrawText(TextFormat("%02X", ctx->current_tick), i * size * 2, y - size, size, WHITE); - DrawRectangle(i * size * 2, y, size * 2, size, RED); + DrawRectangle(i * size * 2, y, size * 2, size, RED); DrawText(TextFormat("%02X", ctx->current_row), i * size * 2, y - size, size, YELLOW); } else { - DrawRectangle(i * size * 2, y, size * 2, size, ORANGE); + DrawRectangle(i * size * 2, y, size * 2, size, ORANGE); }; DrawText(TextFormat("%02X", ctx->module.pattern_table[i]), i * size * 2, y, size, WHITE); }; @@ -2426,19 +2426,19 @@ void jar_xm_debug(jar_xm_context_t *ctx) { DrawText("FX", x + size * 6, y, size, YELLOW); x += 9 * size; }; - x += size; + x += size; for (int j=(ctx->current_row - 14); j<(ctx->current_row + 15); j++) { y += size; x = 0; if (j >=0 && j < (cur->num_rows)) { - DrawRectangle(x, y, size * 2, size, BROWN); + DrawRectangle(x, y, size * 2, size, BROWN); DrawText(TextFormat("%02X",j), x, y, size, WHITE); x += 2 * size; for(uint8_t i = 0; i < ctx->module.num_channels; i++) { if (j==(ctx->current_row)) { - DrawRectangle(x, y, 8 * size, size, DARKGREEN); + DrawRectangle(x, y, 8 * size, size, DARKGREEN); } else { - DrawRectangle(x, y, 8 * size, size, DARKGRAY); + DrawRectangle(x, y, 8 * size, size, DARKGRAY); }; jar_xm_pattern_slot_t *s = cur->slots + j * ctx->module.num_channels + i; // jar_xm_channel_context_t *ch = ctx->channels + i; diff --git a/src/models.c b/src/models.c index fd7daee6f..bd200d5f7 100644 --- a/src/models.c +++ b/src/models.c @@ -828,16 +828,16 @@ void UnloadModelKeepMeshes(Model model) BoundingBox GetModelBoundingBox(Model model) { BoundingBox bounds = { 0 }; - + if (model.meshCount > 0) - { + { Vector3 temp = { 0 }; bounds = GetMeshBoundingBox(model.meshes[0]); - + for (int i = 1; i < model.meshCount; i++) { BoundingBox tempBounds = GetMeshBoundingBox(model.meshes[i]); - + temp.x = (bounds.min.x < tempBounds.min.x)? bounds.min.x : tempBounds.min.x; temp.y = (bounds.min.y < tempBounds.min.y)? bounds.min.y : tempBounds.min.y; temp.z = (bounds.min.z < tempBounds.min.z)? bounds.min.z : tempBounds.min.z; @@ -849,7 +849,7 @@ BoundingBox GetModelBoundingBox(Model model) bounds.max = temp; } } - + return bounds; } @@ -1105,7 +1105,7 @@ void DrawMeshInstanced(Mesh mesh, Material material, Matrix *transforms, int ins // transforms[0]: model transformation provided (includes DrawModel() params combined with model.transform) // rlGetMatrixTransform(): rlgl internal transform matrix due to push/pop matrix stack matModel = MatrixMultiply(transforms[0], rlGetMatrixTransform()); - + // Get model-view matrix matModelView = MatrixMultiply(matModel, matView); } @@ -1376,7 +1376,7 @@ Material *LoadMaterials(const char *fileName, int *materialCount) // Set materials shader to default (DIFFUSE, SPECULAR, NORMAL) if (materials != NULL) { - for (unsigned int i = 0; i < count; i++) + for (unsigned int i = 0; i < count; i++) { materials[i].shader.id = rlGetShaderIdDefault(); materials[i].shader.locs = rlGetShaderLocsDefault(); @@ -1396,7 +1396,7 @@ Material LoadMaterialDefault(void) // Using rlgl default shader material.shader.id = rlGetShaderIdDefault(); material.shader.locs = rlGetShaderLocsDefault(); - + // Using rlgl default texture (1x1 pixel, UNCOMPRESSED_R8G8B8A8, 1 mipmap) material.maps[MATERIAL_MAP_DIFFUSE].texture = (Texture2D){ rlGetTextureIdDefault(), 1, 1, 1, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8 }; //material.maps[MATERIAL_MAP_NORMAL].texture; // NOTE: By default, not set @@ -2825,7 +2825,7 @@ void GenMeshTangents(Mesh *mesh) RL_FREE(tan2); if (mesh->vboId != NULL) - { + { if (mesh->vboId[SHADER_LOC_VERTEX_TANGENT] != 0) { // Upate existing vertex buffer @@ -2834,15 +2834,15 @@ void GenMeshTangents(Mesh *mesh) else { // Load a new tangent attributes buffer - mesh->vboId[SHADER_LOC_VERTEX_TANGENT] = rlLoadVertexBuffer(mesh->tangents, mesh->vertexCount*4*sizeof(float), false); + mesh->vboId[SHADER_LOC_VERTEX_TANGENT] = rlLoadVertexBuffer(mesh->tangents, mesh->vertexCount*4*sizeof(float), false); } - + rlEnableVertexArray(mesh->vaoId); rlSetVertexAttribute(4, 4, RL_FLOAT, 0, 0, 0); rlEnableVertexAttribute(4); rlDisableVertexArray(); } - + TRACELOG(LOG_INFO, "MESH: Tangents data computed and uploaded for provided mesh"); } @@ -3370,7 +3370,7 @@ static Model LoadOBJ(const char *fileName) if (ret != TINYOBJ_SUCCESS) TRACELOG(LOG_WARNING, "MODEL: [%s] Failed to load OBJ data", fileName); else TRACELOG(LOG_INFO, "MODEL: [%s] OBJ data loaded successfully: %i meshes/%i materials", fileName, meshCount, materialCount); - model.meshCount = materialCount; + model.meshCount = materialCount; // Init model materials array if (materialCount > 0) @@ -3468,7 +3468,7 @@ static Model LoadOBJ(const char *fileName) // Get default texture, in case no texture is defined // NOTE: rlgl default texture is a 1x1 pixel UNCOMPRESSED_R8G8B8A8 - model.materials[m].maps[MATERIAL_MAP_DIFFUSE].texture = (Texture2D){ rlGetTextureIdDefault(), 1, 1, 1, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8 }; + model.materials[m].maps[MATERIAL_MAP_DIFFUSE].texture = (Texture2D){ rlGetTextureIdDefault(), 1, 1, 1, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8 }; if (materials[m].diffuse_texname != NULL) model.materials[m].maps[MATERIAL_MAP_DIFFUSE].texture = LoadTexture(materials[m].diffuse_texname); //char *diffuse_texname; // map_Kd diff --git a/src/raudio.c b/src/raudio.c index 072dc5d33..f48888a98 100644 --- a/src/raudio.c +++ b/src/raudio.c @@ -1733,7 +1733,7 @@ void UpdateMusicStream(Music music) } UpdateAudioStream(music.stream, pcm, frameCountToStream); - + framesLeft -= frameCountToStream; if (framesLeft <= 0) diff --git a/src/raymath.h b/src/raymath.h index 0909eb7e5..3addc25de 100644 --- a/src/raymath.h +++ b/src/raymath.h @@ -1432,7 +1432,7 @@ RMDEF Quaternion QuaternionFromAxisAngle(Vector3 axis, float angle) { Quaternion result = { 0.0f, 0.0f, 0.0f, 1.0f }; float axisLength = sqrtf(axis.x*axis.x + axis.y*axis.y + axis.z*axis.z); - + if (axisLength != 0.0f) { angle *= 0.5f; diff --git a/src/rlgl.h b/src/rlgl.h index 9b705473f..7d9b8d140 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -41,7 +41,7 @@ * #define SUPPORT_GL_DETAILS_INFO * Show OpenGL extensions and capabilities detailed logs on init * -* rlgl capabilities could be customized just defining some internal +* rlgl capabilities could be customized just defining some internal * values before library inclusion (default values listed): * * #define RL_DEFAULT_BATCH_BUFFER_ELEMENTS 8192 // Default internal render batch elements limits @@ -54,7 +54,7 @@ * #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 * -* When loading a shader, the following vertex attribute and uniform +* When loading a shader, the following vertex attribute and uniform * location names are tried to be set automatically: * * #define RL_DEFAULT_SHADER_ATTRIB_NAME_POSITION "vertexPosition" // Binded by default to shader location: 0 @@ -246,11 +246,11 @@ //---------------------------------------------------------------------------------- // Types and Structures Definition //---------------------------------------------------------------------------------- -typedef enum { - OPENGL_11 = 1, - OPENGL_21, - OPENGL_33, - OPENGL_ES_20 +typedef enum { + OPENGL_11 = 1, + OPENGL_21, + OPENGL_33, + OPENGL_ES_20 } rlGlVersion; typedef enum { @@ -1025,7 +1025,7 @@ void rlLoadIdentity(void) // Multiply the current matrix by a translation matrix void rlTranslatef(float x, float y, float z) { - Matrix matTranslation = { + Matrix matTranslation = { 1.0f, 0.0f, 0.0f, x, 0.0f, 1.0f, 0.0f, y, 0.0f, 0.0f, 1.0f, z, @@ -1041,7 +1041,7 @@ void rlTranslatef(float x, float y, float z) void rlRotatef(float angle, float x, float y, float z) { Matrix matRotation = rlMatrixIdentity(); - + // Axis vector (x, y, z) normalization float lengthSquared = x*x + y*y + z*z; if ((lengthSquared != 1.0f) && (lengthSquared != 0.0f)) @@ -1051,7 +1051,7 @@ void rlRotatef(float angle, float x, float y, float z) y *= inverseLength; z *= inverseLength; } - + // Rotation matrix generation float sinres = sinf(DEG2RAD*angle); float cosres = cosf(DEG2RAD*angle); @@ -1084,11 +1084,11 @@ void rlRotatef(float angle, float x, float y, float z) // Multiply the current matrix by a scaling matrix void rlScalef(float x, float y, float z) { - Matrix matScale = { + Matrix matScale = { x, 0.0f, 0.0f, 0.0f, 0.0f, y, 0.0f, 0.0f, 0.0f, 0.0f, z, 0.0f, - 0.0f, 0.0f, 0.0f, 1.0f + 0.0f, 0.0f, 0.0f, 1.0f }; // NOTE: We transpose matrix with multiplication order @@ -1145,7 +1145,7 @@ void rlOrtho(double left, double right, double bottom, double top, double znear, // NOTE: If left-right and top-botton values are equal it could create a division by zero, // response to it is platform/compiler dependant Matrix matOrtho = { 0 }; - + float rl = (float)(right - left); float tb = (float)(top - bottom); float fn = (float)(zfar - znear); @@ -1558,11 +1558,11 @@ void rlActiveDrawBuffers(int count) // it can be queried with glGet*() but it must be at least 8 //GLint maxDrawBuffers = 0; //glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers); - + if (count > 0) { if (count > 8) TRACELOG(LOG_WARNING, "GL: Max color buffers limited to 8"); - else + else { unsigned int buffers[8] = { GL_COLOR_ATTACHMENT0, @@ -2399,10 +2399,10 @@ void rlDrawRenderBatch(rlRenderBatch *batch) // Create modelview-projection matrix and upload to shader Matrix matMVP = rlMatrixMultiply(RLGL.State.modelview, RLGL.State.projection); - float matMVPfloat[16] = { - matMVP.m0, matMVP.m1, matMVP.m2, matMVP.m3, - matMVP.m4, matMVP.m5, matMVP.m6, matMVP.m7, - matMVP.m8, matMVP.m9, matMVP.m10, matMVP.m11, + float matMVPfloat[16] = { + matMVP.m0, matMVP.m1, matMVP.m2, matMVP.m3, + matMVP.m4, matMVP.m5, matMVP.m6, matMVP.m7, + matMVP.m8, matMVP.m9, matMVP.m10, matMVP.m11, matMVP.m12, matMVP.m13, matMVP.m14, matMVP.m15 }; glUniformMatrix4fv(RLGL.State.currentShaderLocs[RL_SHADER_LOC_MATRIX_MVP], 1, false, matMVPfloat); @@ -3431,7 +3431,7 @@ unsigned int rlLoadShaderCode(const char *vsCode, const char *fsCode) if (vsCode != NULL) vertexShaderId = rlCompileShader(vsCode, GL_VERTEX_SHADER); if (fsCode != NULL) fragmentShaderId = rlCompileShader(fsCode, GL_FRAGMENT_SHADER); - + if ((vertexShaderId == RLGL.State.defaultVShaderId) && (fragmentShaderId == RLGL.State.defaultFShaderId)) id = RLGL.State.defaultShaderId; else { @@ -3582,13 +3582,13 @@ unsigned int rlLoadShaderProgram(unsigned int vShaderId, unsigned int fShaderId) program = 0; } - else + else { // Get the size of compiled shader program (not available on OpenGL ES 2.0) // NOTE: If GL_LINK_STATUS is GL_FALSE, program binary length is zero. //GLint binarySize = 0; //glGetProgramiv(id, GL_PROGRAM_BINARY_LENGTH, &binarySize); - + TRACELOG(RL_LOG_INFO, "SHADER: [ID %i] Program shader loaded successfully", program); } #endif @@ -3670,10 +3670,10 @@ void rlSetVertexAttributeDefault(int locIndex, const void *value, int attribType void rlSetUniformMatrix(int locIndex, Matrix mat) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - float matfloat[16] = { - mat.m0, mat.m1, mat.m2, mat.m3, - mat.m4, mat.m5, mat.m6, mat.m7, - mat.m8, mat.m9, mat.m10, mat.m11, + float matfloat[16] = { + mat.m0, mat.m1, mat.m2, mat.m3, + mat.m4, mat.m5, mat.m6, mat.m7, + mat.m8, mat.m9, mat.m10, mat.m11, mat.m12, mat.m13, mat.m14, mat.m15 }; glUniformMatrix4fv(locIndex, 1, false, matfloat); diff --git a/src/text.c b/src/text.c index 9d336f218..66a08eb19 100644 --- a/src/text.c +++ b/src/text.c @@ -899,9 +899,9 @@ void DrawTextPro(Font font, const char *text, Vector2 position, Vector2 origin, rlTranslatef(position.x, position.y, 0.0f); rlRotatef(rotation, 0.0f, 0.0f, 1.0f); rlTranslatef(-origin.x, -origin.y, 0.0f); - + DrawTextEx(font, text, (Vector2){ 0.0f, 0.0f }, fontSize, spacing, tint); - + rlPopMatrix(); } @@ -1002,7 +1002,7 @@ Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing } // Get index position for a unicode character on font -// NOTE: If codepoint is not found in the font it fallbacks to '?' +// NOTE: If codepoint is not found in the font it fallbacks to '?' int GetGlyphIndex(Font font, int codepoint) { #ifndef GLYPH_NOTFOUND_CHAR_FALLBACK @@ -1030,24 +1030,24 @@ int GetGlyphIndex(Font font, int codepoint) } // Get glyph font info data for a codepoint (unicode character) -// NOTE: If codepoint is not found in the font it fallbacks to '?' +// NOTE: If codepoint is not found in the font it fallbacks to '?' GlyphInfo GetGlyphInfo(Font font, int codepoint) { GlyphInfo info = { 0 }; - + info = font.chars[GetGlyphIndex(font, codepoint)]; - + return info; } // Get glyph rectangle in font atlas for a codepoint (unicode character) -// NOTE: If codepoint is not found in the font it fallbacks to '?' +// NOTE: If codepoint is not found in the font it fallbacks to '?' Rectangle GetGlyphAtlasRec(Font font, int codepoint) { Rectangle rec = { 0 }; - + rec = font.recs[GetGlyphIndex(font, codepoint)]; - + return rec; } diff --git a/src/textures.c b/src/textures.c index 2480bcfcc..6d5c2c5f4 100644 --- a/src/textures.c +++ b/src/textures.c @@ -382,7 +382,7 @@ Image LoadImageFromMemory(const char *fileType, const unsigned char *fileData, i if (image.data != NULL) TRACELOG(LOG_INFO, "IMAGE: Data loaded successfully (%ix%i | %s | %i mipmaps)", image.width, image.height, rlGetPixelFormatName(image.format), image.mipmaps); else TRACELOG(LOG_WARNING, "IMAGE: Failed to load image data"); - + return image; } @@ -2419,28 +2419,28 @@ void ImageDrawPixelV(Image *dst, Vector2 position, Color color) // Draw line within an image void ImageDrawLine(Image *dst, int startPosX, int startPosY, int endPosX, int endPosY, Color color) { - // Using Bresenham's algorithm as described in + // Using Bresenham's algorithm as described in // Drawing Lines with Pixels - Joshua Scott - March 2012 // https://classic.csunplugged.org/wp-content/uploads/2014/12/Lines.pdf - + int changeInX = (endPosX - startPosX); int absChangeInX = (changeInX < 0)? -changeInX : changeInX; int changeInY = (endPosY - startPosY); int absChangeInY = (changeInY < 0)? -changeInY : changeInY; - + int startU, startV, endU, stepV; // Substitutions, either U = X, V = Y or vice versa. See loop at end of function //int endV; // Not needed but left for better understanding, check code below int A, B, P; // See linked paper above, explained down in the main loop int reversedXY = (absChangeInY < absChangeInX); - - if (reversedXY) + + if (reversedXY) { A = 2*absChangeInY; B = A - 2*absChangeInX; P = A - absChangeInX; if (changeInX > 0) - { + { startU = startPosX; startV = startPosY; endU = endPosX; @@ -2452,23 +2452,23 @@ void ImageDrawLine(Image *dst, int startPosX, int startPosY, int endPosX, int en startV = endPosY; endU = startPosX; //endV = startPosY; - + // Since start and end are reversed changeInX = -changeInX; changeInY = -changeInY; } - + stepV = (changeInY < 0)? -1 : 1; - + ImageDrawPixel(dst, startU, startV, color); // At this point they are correctly ordered... } else { - A = 2*absChangeInX; + A = 2*absChangeInX; B = A - 2*absChangeInY; P = A - absChangeInY; - - if (changeInY > 0) + + if (changeInY > 0) { startU = startPosY; startV = startPosX; @@ -2481,21 +2481,21 @@ void ImageDrawLine(Image *dst, int startPosX, int startPosY, int endPosX, int en startV = endPosX; endU = startPosY; //endV = startPosX; - + // Since start and end are reversed changeInX = -changeInX; changeInY = -changeInY; } - + stepV = (changeInX < 0)? -1 : 1; - + ImageDrawPixel(dst, startV, startU, color); // ... but need to be reversed here. Repeated in the main loop below - } - + } + // We already drew the start point. If we started at startU + 0, the line would be crooked and too short - for (int u = startU + 1, v = startV; u <= endU; u++) + for (int u = startU + 1, v = startV; u <= endU; u++) { - if (P >= 0) + if (P >= 0) { v += stepV; // Adjusts whenever we stray too far from the direct line. Details in the linked paper above P += B; // Remembers that we corrected our path