From 07e0b105156b08718500fe4e2c74e583361278a8 Mon Sep 17 00:00:00 2001 From: Ray Date: Sat, 7 Aug 2021 11:28:35 +0200 Subject: [PATCH 01/23] Added rayex, elixir binding --- BINDINGS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/BINDINGS.md b/BINDINGS.md index 87a076b00..b154dc7b2 100644 --- a/BINDINGS.md +++ b/BINDINGS.md @@ -96,6 +96,7 @@ Some people ported raylib to other languages in form of bindings or wrappers to | raylib-never | 3.0 | [Never](https://github.com/never-lang/never) | https://github.com/never-lang/raylib-never | | hb-raylib | 3.5 | [Harbour](https://harbour.github.io) | https://github.com/MarcosLeonardoMendezGerencir/hb-raylib | | Relib | 3.5 | [ReCT](https://github.com/RedCubeDev-ByteSpace/ReCT) | https://github.com/RedCubeDev-ByteSpace/Relib | +| rayex | 3.7 | [elixir](https://elixir-lang.org/) | https://github.com/shiryel/rayex | | raylib.cbl | 2.0 | [COBOL](https://en.wikipedia.org/wiki/COBOL) | *[code examples](https://github.com/Martinfx/Cobol/tree/master/OpenCobol/Games/raylib)* | ### Utility Wrapers From 7ca9131fd46e6928910cd995f4dc4240f36e2560 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sat, 7 Aug 2021 11:58:39 +0200 Subject: [PATCH 02/23] Update rlgl_standalone.c --- examples/others/rlgl_standalone.c | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/examples/others/rlgl_standalone.c b/examples/others/rlgl_standalone.c index c8c0b0deb..cc0eda2db 100644 --- a/examples/others/rlgl_standalone.c +++ b/examples/others/rlgl_standalone.c @@ -2,18 +2,17 @@ * * raylib [rlgl] example - Using rlgl module as standalone module * -* NOTE: This example requires OpenGL 3.3 or ES2 versions for shaders support, +* rlgl library is an abstraction layer for multiple OpenGL versions (1.1, 2.1, 3.3 Core, ES 2.0) +* that provides a pseudo-OpenGL 1.1 immediate-mode style API (rlVertex, rlTranslate, rlRotate...) +* +* NOTE: This example requires OpenGL 3.3 or OpenGL ES 2.0 for shaders support, * OpenGL 1.1 does not support shaders but it can also be used. * * DEPENDENCIES: -* rlgl.h - OpenGL 1.1 immediate-mode style coding translation layer -* glad.h - OpenGL extensions initialization library (required by rlgl) -* raymath.h - 3D math library (required by rlgl) * glfw3 - Windows and context initialization library -* -* rlgl library is provided as a single-file header-only library, this library -* allows coding in a pseudo-OpenGL 1.1 style while translating calls to multiple -* OpenGL versions backends (1.1, 2.1, 3.3, ES 2.0). +* rlgl.h - OpenGL abstraction layer to OpenGL 1.1, 3.3 or ES2 +* glad.h - OpenGL extensions initialization library (required by rlgl) +* raymath.h - 3D math library * * WINDOWS COMPILATION: * gcc -o rlgl_standalone.exe rlgl_standalone.c -s -Iexternal\include -I..\..\src \ @@ -21,15 +20,16 @@ * * APPLE COMPILATION: * gcc -o rlgl_standalone rlgl_standalone.c -I../../src -Iexternal/include -Lexternal/lib \ -* -lglfw3 -std=c99 -framework CoreVideo -framework OpenGL -framework OpenAL \ -* -framework IOKit -framework Cocoa -Wno-deprecated-declarations +* -lglfw3 -framework CoreVideo -framework OpenGL -framework IOKit -framework Cocoa +* -Wno-deprecated-declarations -std=c99 -DGRAPHICS_API_OPENGL_33 +* * * LICENSE: zlib/libpng * * This example is licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software: * -* Copyright (c) 2014-2019 Ramon Santamaria (@raysan5) +* Copyright (c) 2014-2021 Ramon Santamaria (@raysan5) * * This software is provided "as-is", without any express or implied warranty. In no event * will the authors be held liable for any damages arising from the use of this software. @@ -107,7 +107,7 @@ static void DrawCube(Vector3 position, float width, float height, float length, static void DrawCubeWires(Vector3 position, float width, float height, float length, Color color); static void DrawRectangleV(Vector2 position, Vector2 size, Color color); -// NOTE: We used raymath to get this functionality but it can be implemented here +// NOTE: We use raymath to get this functionality but it could be implemented in this module //static Matrix MatrixIdentity(void); //static Matrix MatrixOrtho(double left, double right, double bottom, double top, double near, double far); //static Matrix MatrixPerspective(double fovy, double aspect, double near, double far); @@ -144,7 +144,6 @@ int main(void) glfwWindowHint( GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE ); #endif - GLFWwindow *window = glfwCreateWindow(screenWidth, screenHeight, "rlgl standalone", NULL, NULL); if (!window) @@ -219,8 +218,8 @@ int main(void) // Draw '2D' elements in the scene (GUI) //----------------------------------------------- -#define RLGL_CREATE_MATRIX_MANUALLY -#if defined(RLGL_CREATE_MATRIX_MANUALLY) +#define RLGL_SET_MATRIX_MANUALLY +#if defined(RLGL_SET_MATRIX_MANUALLY) matProj = MatrixOrtho(0.0, screenWidth, screenHeight, 0.0, 0.0, 1.0); matView = MatrixIdentity(); @@ -237,7 +236,7 @@ int main(void) #endif DrawRectangleV((Vector2){ 10.0f, 10.0f }, (Vector2){ 780.0f, 20.0f }, DARKGRAY); - // Draw internal render batch buffers (3D data) + // Draw internal render batch buffers (2D data) rlDrawRenderBatchActive(); //----------------------------------------------- From e6fe8169c27825580e9b0e73ae633e89dc83b786 Mon Sep 17 00:00:00 2001 From: Ryan Roden-Corrent Date: Sat, 7 Aug 2021 17:30:48 -0400 Subject: [PATCH 03/23] Fix Makefile to build WASM examples. (#1906) * Fix Makefile to build WASM examples. - Add --preload-file flag before specifying the resource dir - Add empty resource dir to `shapes/` (otherwise wasm-ld will fail) - Add wasm outputs to .gitigore * Delete .gitignore Co-authored-by: Ray --- .gitignore | 6 ++++++ examples/Makefile | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 9153a03ea..00c9bdcec 100644 --- a/.gitignore +++ b/.gitignore @@ -58,6 +58,12 @@ packages/ *.bc *.so +# Ignore wasm data in examples/ +examples/**/*.wasm +examples/**/*.data +examples/**/*.js +examples/**/*.html + # Ignore files build by xcode *.mode*v* *.pbxuser diff --git a/examples/Makefile b/examples/Makefile index bded27e53..5abf0c708 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -244,7 +244,7 @@ ifeq ($(PLATFORM),PLATFORM_WEB) # --memory-init-file 0 # to avoid an external memory initialization code file (.mem) # --preload-file resources # specify a resources folder for data compilation # --source-map-base # allow debugging in browser with source map - CFLAGS += -s USE_GLFW=3 -s ASYNCIFY -s TOTAL_MEMORY=67108864 -s FORCE_FILESYSTEM=1 $(dir $<)resources@resources + CFLAGS += -s USE_GLFW=3 -s ASYNCIFY -s TOTAL_MEMORY=67108864 -s FORCE_FILESYSTEM=1 --preload-file $(dir $<)resources@resources # NOTE: Simple raylib examples are compiled to be interpreter with asyncify, that way, # we can compile same code for ALL platforms with no change required, but, working on bigger From 5e63cd3c97a8b45c5effa961b00b533223c4e44f Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sun, 8 Aug 2021 11:29:24 +0200 Subject: [PATCH 04/23] ADDED: GenMeshCone() #1903 --- src/external/par_shapes.h | 163 ++++++++++++++++++++++++++++++-------- src/models.c | 55 +++++++++++++ src/raylib.h | 1 + 3 files changed, 188 insertions(+), 31 deletions(-) diff --git a/src/external/par_shapes.h b/src/external/par_shapes.h index 8b65e384a..f44987a30 100644 --- a/src/external/par_shapes.h +++ b/src/external/par_shapes.h @@ -21,8 +21,7 @@ // coordinates (one per vertex). That's it! If you need something fancier, // look elsewhere. // -// The MIT License -// Copyright (c) 2015 Philip Rideout +// Distributed under the MIT License, see bottom of file. #ifndef PAR_SHAPES_H #define PAR_SHAPES_H @@ -32,21 +31,17 @@ extern "C" { #endif #include - -// Ray: commented to avoid conflict with raylib bool -/* #if !defined(_MSC_VER) # include #else // MSVC # if _MSC_VER >= 1800 # include # else // stdbool.h missing prior to MSVC++ 12.0 (VS2013) -//# define bool int -//# define true 1 -//# define false 0 +# define bool int +# define true 1 +# define false 0 # endif #endif -*/ #ifndef PAR_SHAPES_T #define PAR_SHAPES_T uint16_t @@ -71,6 +66,14 @@ void par_shapes_free_mesh(par_shapes_mesh*); // both 1.0, but they can easily be changed with par_shapes_scale. par_shapes_mesh* par_shapes_create_cylinder(int slices, int stacks); +// Cone is similar to cylinder but the radius diminishes to zero as Z increases. +// Again, height and radius are 1.0, but can be changed with par_shapes_scale. +par_shapes_mesh* par_shapes_create_cone(int slices, int stacks); + +// Create a disk of radius 1.0 with texture coordinates and normals by squashing +// a cone flat on the Z=0 plane. +par_shapes_mesh* par_shapes_create_parametric_disk(int slices, int stacks); + // Create a donut that sits on the Z=0 plane with the specified inner radius. // The outer radius can be controlled with par_shapes_scale. par_shapes_mesh* par_shapes_create_torus(int slices, int stacks, float radius); @@ -172,6 +175,17 @@ par_shapes_mesh* par_shapes_weld(par_shapes_mesh const*, float epsilon, // Compute smooth normals by averaging adjacent facet normals. void par_shapes_compute_normals(par_shapes_mesh* m); +// Global Config --------------------------------------------------------------- + +void par_shapes_set_epsilon_welded_normals(float epsilon); +void par_shapes_set_epsilon_degenerate_sphere(float epsilon); + +// Advanced -------------------------------------------------------------------- + +void par_shapes__compute_welded_normals(par_shapes_mesh* m); +void par_shapes__connect(par_shapes_mesh* scene, par_shapes_mesh* cylinder, + int slices); + #ifndef PAR_PI #define PAR_PI (3.14159265359) #define PAR_MIN(a, b) (a > b ? b : a) @@ -205,11 +219,15 @@ void par_shapes_compute_normals(par_shapes_mesh* m); #include #include +static float par_shapes__epsilon_welded_normals = 0.001; +static float par_shapes__epsilon_degenerate_sphere = 0.0001; + static void par_shapes__sphere(float const* uv, float* xyz, void*); static void par_shapes__hemisphere(float const* uv, float* xyz, void*); static void par_shapes__plane(float const* uv, float* xyz, void*); static void par_shapes__klein(float const* uv, float* xyz, void*); static void par_shapes__cylinder(float const* uv, float* xyz, void*); +static void par_shapes__cone(float const* uv, float* xyz, void*); static void par_shapes__torus(float const* uv, float* xyz, void*); static void par_shapes__trefoil(float const* uv, float* xyz, void*); @@ -298,11 +316,12 @@ static float par_shapes__sqrdist3(float const* a, float const* b) return dx * dx + dy * dy + dz * dz; } -static void par_shapes__compute_welded_normals(par_shapes_mesh* m) +void par_shapes__compute_welded_normals(par_shapes_mesh* m) { + const float epsilon = par_shapes__epsilon_welded_normals; m->normals = PAR_MALLOC(float, m->npoints * 3); PAR_SHAPES_T* weldmap = PAR_MALLOC(PAR_SHAPES_T, m->npoints); - par_shapes_mesh* welded = par_shapes_weld(m, 0.01, weldmap); + par_shapes_mesh* welded = par_shapes_weld(m, epsilon, weldmap); par_shapes_compute_normals(welded); float* pdst = m->normals; for (int i = 0; i < m->npoints; i++, pdst += 3) { @@ -325,6 +344,24 @@ par_shapes_mesh* par_shapes_create_cylinder(int slices, int stacks) stacks, 0); } +par_shapes_mesh* par_shapes_create_cone(int slices, int stacks) +{ + if (slices < 3 || stacks < 1) { + return 0; + } + return par_shapes_create_parametric(par_shapes__cone, slices, + stacks, 0); +} + +par_shapes_mesh* par_shapes_create_parametric_disk(int slices, int stacks) +{ + par_shapes_mesh* m = par_shapes_create_cone(slices, stacks); + if (m) { + par_shapes_scale(m, 1.0f, 1.0f, 0.0f); + } + return m; +} + par_shapes_mesh* par_shapes_create_parametric_sphere(int slices, int stacks) { if (slices < 3 || stacks < 3) { @@ -332,7 +369,7 @@ par_shapes_mesh* par_shapes_create_parametric_sphere(int slices, int stacks) } par_shapes_mesh* m = par_shapes_create_parametric(par_shapes__sphere, slices, stacks, 0); - par_shapes_remove_degenerate(m, 0.0001); + par_shapes_remove_degenerate(m, par_shapes__epsilon_degenerate_sphere); return m; } @@ -343,7 +380,7 @@ par_shapes_mesh* par_shapes_create_hemisphere(int slices, int stacks) } par_shapes_mesh* m = par_shapes_create_parametric(par_shapes__hemisphere, slices, stacks, 0); - par_shapes_remove_degenerate(m, 0.0001); + par_shapes_remove_degenerate(m, par_shapes__epsilon_degenerate_sphere); return m; } @@ -579,6 +616,15 @@ static void par_shapes__cylinder(float const* uv, float* xyz, void* userdata) xyz[2] = uv[0]; } +static void par_shapes__cone(float const* uv, float* xyz, void* userdata) +{ + float r = 1.0f - uv[0]; + float theta = uv[1] * 2 * PAR_PI; + xyz[0] = r * sinf(theta); + xyz[1] = r * cosf(theta); + xyz[2] = uv[0]; +} + static void par_shapes__torus(float const* uv, float* xyz, void* userdata) { float major = 1; @@ -620,6 +666,14 @@ static void par_shapes__trefoil(float const* uv, float* xyz, void* userdata) xyz[2] = z + d * ww[2] * sin(v); } +void par_shapes_set_epsilon_welded_normals(float epsilon) { + par_shapes__epsilon_welded_normals = epsilon; +} + +void par_shapes_set_epsilon_degenerate_sphere(float epsilon) { + par_shapes__epsilon_degenerate_sphere = epsilon; +} + void par_shapes_merge(par_shapes_mesh* dst, par_shapes_mesh const* src) { PAR_SHAPES_T offset = dst->npoints; @@ -744,15 +798,15 @@ void par_shapes_rotate(par_shapes_mesh* mesh, float radians, float const* axis) p[1] = y; p[2] = z; } - p = mesh->normals; - if (p) { - for (int i = 0; i < mesh->npoints; i++, p += 3) { - float x = col0[0] * p[0] + col1[0] * p[1] + col2[0] * p[2]; - float y = col0[1] * p[0] + col1[1] * p[1] + col2[1] * p[2]; - float z = col0[2] * p[0] + col1[2] * p[1] + col2[2] * p[2]; - p[0] = x; - p[1] = y; - p[2] = z; + float* n = mesh->normals; + if (n) { + for (int i = 0; i < mesh->npoints; i++, n += 3) { + float x = col0[0] * n[0] + col1[0] * n[1] + col2[0] * n[2]; + float y = col0[1] * n[0] + col1[1] * n[1] + col2[1] * n[2]; + float z = col0[2] * n[0] + col1[2] * n[1] + col2[2] * n[2]; + n[0] = x; + n[1] = y; + n[2] = z; } } } @@ -765,6 +819,27 @@ void par_shapes_scale(par_shapes_mesh* m, float x, float y, float z) *points++ *= y; *points++ *= z; } + float* n = m->normals; + if (n && !(x == y && y == z)) { + bool x_zero = x == 0; + bool y_zero = y == 0; + bool z_zero = z == 0; + if (!x_zero && !y_zero && !z_zero) { + x = 1.0f / x; + y = 1.0f / y; + z = 1.0f / z; + } else { + x = x_zero && !y_zero && !z_zero; + y = y_zero && !x_zero && !z_zero; + z = z_zero && !x_zero && !y_zero; + } + for (int i = 0; i < m->npoints; i++, n += 3) { + n[0] *= x; + n[1] *= y; + n[2] *= z; + par_shapes__normalize3(n); + } + } } void par_shapes_merge_and_free(par_shapes_mesh* dst, par_shapes_mesh* src) @@ -1098,8 +1173,8 @@ static par_shapes_mesh* par_shapes__apply_turtle(par_shapes_mesh* mesh, return m; } -static void par_shapes__connect(par_shapes_mesh* scene, - par_shapes_mesh* cylinder, int slices) +void par_shapes__connect(par_shapes_mesh* scene, par_shapes_mesh* cylinder, + int slices) { int stacks = 1; int npoints = (slices + 1) * (stacks + 1); @@ -1118,7 +1193,8 @@ static void par_shapes__connect(par_shapes_mesh* scene, // Create the new triangle list. int ntriangles = scene->ntriangles + 2 * slices * stacks; PAR_SHAPES_T* triangles = PAR_MALLOC(PAR_SHAPES_T, ntriangles * 3); - memcpy(triangles, scene->triangles, 2 * scene->ntriangles * 3); + memcpy(triangles, scene->triangles, + sizeof(PAR_SHAPES_T) * scene->ntriangles * 3); int v = scene->npoints - (slices + 1); PAR_SHAPES_T* face = triangles + scene->ntriangles * 3; for (int stack = 0; stack < stacks; stack++) { @@ -1154,7 +1230,7 @@ par_shapes_mesh* par_shapes_create_lsystem(char const* text, int slices, while (cmd) { char *arg = strtok(0, " "); if (!arg) { - //puts("lsystem error: unexpected end of program."); + puts("lsystem error: unexpected end of program."); break; } if (!strcmp(cmd, "rule")) { @@ -1208,7 +1284,6 @@ par_shapes_mesh* par_shapes_create_lsystem(char const* text, int slices, // For testing purposes, dump out the parsed program. #ifdef TEST_PARSE - /* for (int i = 0; i < nrules; i++) { par_shapes__rule rule = rules[i]; printf("rule %s.%d\n", rule.name, rule.weight); @@ -1217,7 +1292,6 @@ par_shapes_mesh* par_shapes_create_lsystem(char const* text, int slices, printf("\t%s %s\n", cmd.cmd, cmd.arg); } } - */ #endif // Instantiate the aggregated shape and the template shapes. @@ -1258,7 +1332,8 @@ par_shapes_mesh* par_shapes_create_lsystem(char const* text, int slices, par_shapes__command* cmd = rule->commands + (frame->pc++); #ifdef DUMP_TRACE - //printf("%5s %5s %5s:%d %03d\n", cmd->cmd, cmd->arg, rule->name, frame->pc - 1, stackptr); + printf("%5s %5s %5s:%d %03d\n", cmd->cmd, cmd->arg, rule->name, + frame->pc - 1, stackptr); #endif float value; @@ -1620,7 +1695,7 @@ static void par_shapes__weld_points(par_shapes_mesh* mesh, int gridsize, PAR_SHAPES_T binvalue = *(bins + binindex); if (binvalue > 0) { if (nbins == 8) { - //printf("Epsilon value is too large.\n"); + printf("Epsilon value is too large.\n"); break; } nearby[nbins++] = binindex; @@ -1632,8 +1707,9 @@ static void par_shapes__weld_points(par_shapes_mesh* mesh, int gridsize, // Check for colocated points in each nearby bin. for (int b = 0; b < nbins; b++) { int binindex = nearby[b]; - PAR_SHAPES_T binvalue = *(bins + binindex); + PAR_SHAPES_T binvalue = bins[binindex]; PAR_SHAPES_T nindex = binvalue - 1; + assert(nindex < mesh->npoints); while (true) { // If this isn't "self" and it's colocated, then weld it! @@ -1699,6 +1775,9 @@ static void par_shapes__weld_points(par_shapes_mesh* mesh, int gridsize, PAR_SHAPES_T b = weldmap[tsrc[1]]; PAR_SHAPES_T c = weldmap[tsrc[2]]; if (a != b && a != c && b != c) { + assert(a < mesh->npoints); + assert(b < mesh->npoints); + assert(c < mesh->npoints); *tdst++ = a; *tdst++ = b; *tdst++ = c; @@ -2049,3 +2128,25 @@ void par_shapes_remove_degenerate(par_shapes_mesh* mesh, float mintriarea) #endif // PAR_SHAPES_IMPLEMENTATION #endif // PAR_SHAPES_H + +// par_shapes is distributed under the MIT license: +// +// Copyright (c) 2019 Philip Rideout +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. diff --git a/src/models.c b/src/models.c index bce9c8d82..2b6f9a589 100644 --- a/src/models.c +++ b/src/models.c @@ -2084,6 +2084,61 @@ Mesh GenMeshCylinder(float radius, float height, int slices) return mesh; } +// Generate cone/pyramid mesh +Mesh GenMeshCone(float radius, float height, int slices) +{ + Mesh mesh = { 0 }; + + if (slices >= 3) + { + // Instance a cone that sits on the Z=0 plane using the given tessellation + // levels across the UV domain. Think of "slices" like a number of pizza + // slices, and "stacks" like a number of stacked rings. + // Height and radius are both 1.0, but they can easily be changed with par_shapes_scale + par_shapes_mesh *cone = par_shapes_create_cone(slices, 8); + par_shapes_scale(cone, radius, radius, height); + par_shapes_rotate(cone, -PI/2.0f, (float[]){ 1, 0, 0 }); + par_shapes_rotate(cone, PI/2.0f, (float[]){ 0, 1, 0 }); + + // Generate an orientable disk shape (bottom cap) + par_shapes_mesh *capBottom = par_shapes_create_disk(radius, slices, (float[]){ 0, 0, 0 }, (float[]){ 0, 0, -1 }); + capBottom->tcoords = PAR_MALLOC(float, 2*capBottom->npoints); + for (int i = 0; i < 2*capBottom->npoints; i++) capBottom->tcoords[i] = 0.95f; + par_shapes_rotate(capBottom, PI/2.0f, (float[]){ 1, 0, 0 }); + + par_shapes_merge_and_free(cone, capBottom); + + mesh.vertices = (float *)RL_MALLOC(cone->ntriangles*3*3*sizeof(float)); + mesh.texcoords = (float *)RL_MALLOC(cone->ntriangles*3*2*sizeof(float)); + mesh.normals = (float *)RL_MALLOC(cone->ntriangles*3*3*sizeof(float)); + + mesh.vertexCount = cone->ntriangles*3; + mesh.triangleCount = cone->ntriangles; + + for (int k = 0; k < mesh.vertexCount; k++) + { + mesh.vertices[k*3] = cone->points[cone->triangles[k]*3]; + mesh.vertices[k*3 + 1] = cone->points[cone->triangles[k]*3 + 1]; + mesh.vertices[k*3 + 2] = cone->points[cone->triangles[k]*3 + 2]; + + mesh.normals[k*3] = cone->normals[cone->triangles[k]*3]; + mesh.normals[k*3 + 1] = cone->normals[cone->triangles[k]*3 + 1]; + mesh.normals[k*3 + 2] = cone->normals[cone->triangles[k]*3 + 2]; + + mesh.texcoords[k*2] = cone->tcoords[cone->triangles[k]*2]; + mesh.texcoords[k*2 + 1] = cone->tcoords[cone->triangles[k]*2 + 1]; + } + + par_shapes_free_mesh(cone); + + // Upload vertex data to GPU (static mesh) + UploadMesh(&mesh, false); + } + else TRACELOG(LOG_WARNING, "MESH: Failed to generate mesh: cone"); + + return mesh; +} + // Generate torus mesh Mesh GenMeshTorus(float radius, float size, int radSeg, int sides) { diff --git a/src/raylib.h b/src/raylib.h index 781c14202..92e592e90 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -1428,6 +1428,7 @@ RLAPI Mesh GenMeshCube(float width, float height, float length); RLAPI Mesh GenMeshSphere(float radius, int rings, int slices); // Generate sphere mesh (standard sphere) RLAPI Mesh GenMeshHemiSphere(float radius, int rings, int slices); // Generate half-sphere mesh (no bottom cap) RLAPI Mesh GenMeshCylinder(float radius, float height, int slices); // Generate cylinder mesh +RLAPI Mesh GenMeshCone(float radius, float height, int slices); // Generate cone/pyramid mesh RLAPI Mesh GenMeshTorus(float radius, float size, int radSeg, int sides); // Generate torus mesh RLAPI Mesh GenMeshKnot(float radius, float size, int radSeg, int sides); // Generate trefoil knot mesh RLAPI Mesh GenMeshHeightmap(Image heightmap, Vector3 size); // Generate heightmap mesh from image data From ee72497eef324aaac0abede3bfe6a89b0e1d8fb7 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sun, 8 Aug 2021 13:02:51 +0200 Subject: [PATCH 05/23] REVIEWED: Some warnings... --- src/models.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/models.c b/src/models.c index 2b6f9a589..68785347e 100644 --- a/src/models.c +++ b/src/models.c @@ -79,6 +79,7 @@ #define PAR_SHAPES_IMPLEMENTATION #include "external/par_shapes.h" // Shapes 3d parametric generation + #undef bool #endif #if defined(_WIN32) @@ -3178,11 +3179,10 @@ RayCollision GetRayCollisionBox(Ray ray, BoundingBox box) collision.normal = Vector3Scale(collision.normal, 2.01f); collision.normal = Vector3Divide(collision.normal, Vector3Subtract(box.max, box.min)); // The relevant elemets of the vector are now slightly larger than 1.0f (or smaller than -1.0f) - // and the others are somewhere between -1.0 and 1.0 - // casting to int is exactly our wanted normal! - collision.normal.x = (int)collision.normal.x; - collision.normal.y = (int)collision.normal.y; - collision.normal.z = (int)collision.normal.z; + // and the others are somewhere between -1.0 and 1.0 casting to int is exactly our wanted normal! + collision.normal.x = (float)((int)collision.normal.x); + collision.normal.y = (float)((int)collision.normal.y); + collision.normal.z = (float)((int)collision.normal.z); collision.normal = Vector3Normalize(collision.normal); @@ -4992,7 +4992,7 @@ static ModelAnimation *LoadGLTFModelAnimations(const char *fileName, int *animCo { output->framePoses[frame] = RL_MALLOC(output->boneCount*sizeof(Transform)); - for (unsigned int i = 0; i < output->boneCount; i++) + for (int i = 0; i < output->boneCount; i++) { if (data->nodes[i].has_translation) memcpy(&output->framePoses[frame][i].translation, data->nodes[i].translation, 3*sizeof(float)); else output->framePoses[frame][i].translation = Vector3Zero(); @@ -5185,7 +5185,7 @@ void LoadGLTFMesh(cgltf_data* data, cgltf_mesh* mesh, Model* outModel, Matrix cu outModel->meshes[(*primitiveIndex)].vertices = ReadGLTFValuesAs(acc, cgltf_component_type_r_32f, false); // Transform using the nodes matrix attributes - for (unsigned int v = 0; v < outModel->meshes[(*primitiveIndex)].vertexCount; v++) + for (int v = 0; v < outModel->meshes[(*primitiveIndex)].vertexCount; v++) { Vector3 vertex = { outModel->meshes[(*primitiveIndex)].vertices[(v*3 + 0)], @@ -5211,7 +5211,7 @@ void LoadGLTFMesh(cgltf_data* data, cgltf_mesh* mesh, Model* outModel, Matrix cu outModel->meshes[(*primitiveIndex)].normals = ReadGLTFValuesAs(acc, cgltf_component_type_r_32f, false); // Transform using the nodes matrix attributes - for (unsigned int v = 0; v < outModel->meshes[(*primitiveIndex)].vertexCount; v++) + for (int v = 0; v < outModel->meshes[(*primitiveIndex)].vertexCount; v++) { Vector3 normal = { outModel->meshes[(*primitiveIndex)].normals[(v*3 + 0)], From a135d9c25d668640c43bbaffa54903b2c55f80f4 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sun, 8 Aug 2021 13:23:04 +0200 Subject: [PATCH 06/23] REVIEWED: Avoid conflict with bool --- src/external/par_shapes.h | 3 +++ src/models.c | 1 - 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/external/par_shapes.h b/src/external/par_shapes.h index f44987a30..994a605a9 100644 --- a/src/external/par_shapes.h +++ b/src/external/par_shapes.h @@ -31,6 +31,8 @@ extern "C" { #endif #include +// Ray (@raysan5): Commented to avoid conflict with raylib bool +/* #if !defined(_MSC_VER) # include #else // MSVC @@ -42,6 +44,7 @@ extern "C" { # define false 0 # endif #endif +*/ #ifndef PAR_SHAPES_T #define PAR_SHAPES_T uint16_t diff --git a/src/models.c b/src/models.c index 68785347e..329d8d4a8 100644 --- a/src/models.c +++ b/src/models.c @@ -79,7 +79,6 @@ #define PAR_SHAPES_IMPLEMENTATION #include "external/par_shapes.h" // Shapes 3d parametric generation - #undef bool #endif #if defined(_WIN32) From 311fe8f35b8dbe79af162b10ea980824b92115b4 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sun, 8 Aug 2021 21:09:11 +0200 Subject: [PATCH 07/23] Replaced TABS by spaces --- src/raymath.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/raymath.h b/src/raymath.h index 2eb7bbd0d..0909eb7e5 100644 --- a/src/raymath.h +++ b/src/raymath.h @@ -138,11 +138,11 @@ typedef struct Matrix { // NOTE: Helper types to be used instead of array return types for *ToFloat functions typedef struct float3 { - float v[3]; + float v[3]; } float3; typedef struct float16 { - float v[16]; + float v[16]; } float16; #include // Required for: sinf(), cosf(), tan(), atan2f(), sqrtf(), fminf(), fmaxf(), fabs() From e3f0a11053beae4c21249e814b2714a717f9bdb2 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Tue, 10 Aug 2021 17:48:31 +0200 Subject: [PATCH 08/23] Update CHANGELOG --- CHANGELOG | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index c37aa3162..54bf0db61 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -3,6 +3,17 @@ changelog Current Release: raylib 3.7.0 (26 April 2021) +------------------------------------------------------------------------- +Release: raylib 4.0 (November? 2021) +------------------------------------------------------------------------- +KEY CHANGES: + - + - + - + +Detailed changes: + + ------------------------------------------------------------------------- Release: raylib 3.7 (26 April 2021) ------------------------------------------------------------------------- From ef9fdd0fa5dcfbf4c3c538b56d285230e8d6af1e Mon Sep 17 00:00:00 2001 From: Ryan Roden-Corrent Date: Tue, 10 Aug 2021 12:38:32 -0400 Subject: [PATCH 09/23] Document Get{Key,Char}Pressed return value. (#1909) I think it is useful to know what the empty behavior is in cases where you are enumerating key presses (e.g. implementing "press any key to continue"). --- src/raylib.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/raylib.h b/src/raylib.h index 92e592e90..f02f46f66 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -1077,8 +1077,8 @@ RLAPI bool IsKeyDown(int key); // Check if a key RLAPI bool IsKeyReleased(int key); // Check if a key has been released once RLAPI bool IsKeyUp(int key); // Check if a key is NOT being pressed RLAPI void SetExitKey(int key); // Set a custom key to exit program (default is ESC) -RLAPI int GetKeyPressed(void); // Get key pressed (keycode), call it multiple times for keys queued -RLAPI int GetCharPressed(void); // Get char pressed (unicode), call it multiple times for chars queued +RLAPI int GetKeyPressed(void); // Get key pressed (keycode), call it multiple times for keys queued. Returns 0 when the queue is empty. +RLAPI int GetCharPressed(void); // Get char pressed (unicode), call it multiple times for chars queued. Returns 0 when the queue is empty. // Input-related functions: gamepads RLAPI bool IsGamepadAvailable(int gamepad); // Check if a gamepad is available From 0ba49cce45405a688f7e7893e203f7d3f0bc780c Mon Sep 17 00:00:00 2001 From: Tommi Sinivuo <600815+TommiSinivuo@users.noreply.github.com> Date: Wed, 11 Aug 2021 12:56:05 +0300 Subject: [PATCH 10/23] Add *.so.* to .gitignore to ignore build artifacts (#1912) When building a shared Raylib library on Linux, the build process produces 3 files: libraylib.so (symlink), libraylib.so.381 (symlink) and libraylib.so.3.8.1 (the library). Only the first one of these (.so) is currently ignored by Git. Adding *.so.* to .gitinore makes Git ignore the rest of them as well. --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 00c9bdcec..dcfa5bce2 100644 --- a/.gitignore +++ b/.gitignore @@ -57,6 +57,7 @@ packages/ *.a *.bc *.so +*.so.* # Ignore wasm data in examples/ examples/**/*.wasm From 5a259fa10ffb1ad44528d2678d3781cddd0bb1c0 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Wed, 11 Aug 2021 18:31:32 +0200 Subject: [PATCH 11/23] WARNING: REMOVED: DrawTextRec() and DrawTextRecEx() - DrawTextRec() and DrawTextRecEx() have been moved to example, those functions could be very specific depending on user needs so it's better to give the user the full source in case of special requirements instead of allowing a function with +10 input parameters. --- examples/text/text_rectangle_bounds.c | 144 +++++++++++++++++++++++++ examples/text/text_unicode.c | 146 ++++++++++++++++++++++++++ src/raylib.h | 3 - src/text.c | 133 ----------------------- 4 files changed, 290 insertions(+), 136 deletions(-) diff --git a/examples/text/text_rectangle_bounds.c b/examples/text/text_rectangle_bounds.c index 9754cd456..c763fb2ec 100644 --- a/examples/text/text_rectangle_bounds.c +++ b/examples/text/text_rectangle_bounds.c @@ -13,6 +13,10 @@ #include "raylib.h" +static void DrawTextRec(Font font, const char *text, Rectangle rec, float fontSize, float spacing, bool wordWrap, Color tint); // Draw text using font inside rectangle limits +static void DrawTextRecEx(Font font, const char *text, Rectangle rec, float fontSize, float spacing, bool wordWrap, Color tint, int selectStart, int selectLength, Color selectTint, Color selectBackTint); // Draw text using font inside rectangle limits with support for text selection + +// Main entry point int main(void) { // Initialization @@ -119,4 +123,144 @@ tempor incididunt ut labore et dolore magna aliqua. Nec ullamcorper sit amet ris //-------------------------------------------------------------------------------------- return 0; +} + +//-------------------------------------------------------------------------------------- +// Module functions definition +//-------------------------------------------------------------------------------------- + +// Draw text using font inside rectangle limits +static void DrawTextRec(Font font, const char *text, Rectangle rec, float fontSize, float spacing, bool wordWrap, Color tint) +{ + DrawTextRecEx(font, text, rec, fontSize, spacing, wordWrap, tint, 0, 0, WHITE, WHITE); +} + +// Draw text using font inside rectangle limits with support for text selection +static void DrawTextRecEx(Font font, const char *text, Rectangle rec, float fontSize, float spacing, bool wordWrap, Color tint, int selectStart, int selectLength, Color selectTint, Color selectBackTint) +{ + int length = TextLength(text); // Total length in bytes of the text, scanned by codepoints in loop + + float textOffsetY = 0; // Offset between lines (on line break '\n') + float textOffsetX = 0.0f; // Offset X to next character to draw + + float scaleFactor = fontSize/(float)font.baseSize; // Character rectangle scaling factor + + // Word/character wrapping mechanism variables + enum { MEASURE_STATE = 0, DRAW_STATE = 1 }; + int state = wordWrap? MEASURE_STATE : DRAW_STATE; + + int startLine = -1; // Index where to begin drawing (where a line begins) + int endLine = -1; // Index where to stop drawing (where a line ends) + int lastk = -1; // Holds last value of the character position + + for (int i = 0, k = 0; i < length; i++, k++) + { + // Get next codepoint from byte string and glyph index in font + int codepointByteCount = 0; + int codepoint = GetCodepoint(&text[i], &codepointByteCount); + int index = GetGlyphIndex(font, codepoint); + + // NOTE: Normally we exit the decoding sequence as soon as a bad byte is found (and return 0x3f) + // but we need to draw all of the bad bytes using the '?' symbol moving one byte + if (codepoint == 0x3f) codepointByteCount = 1; + i += (codepointByteCount - 1); + + float glyphWidth = 0; + if (codepoint != '\n') + { + glyphWidth = (font.chars[index].advanceX == 0) ? font.recs[index].width*scaleFactor : font.chars[index].advanceX*scaleFactor; + + if (i + 1 < length) glyphWidth = glyphWidth + spacing; + } + + // NOTE: When wordWrap is ON we first measure how much of the text we can draw before going outside of the rec container + // We store this info in startLine and endLine, then we change states, draw the text between those two variables + // and change states again and again recursively until the end of the text (or until we get outside of the container). + // When wordWrap is OFF we don't need the measure state so we go to the drawing state immediately + // and begin drawing on the next line before we can get outside the container. + if (state == MEASURE_STATE) + { + // TODO: There are multiple types of spaces in UNICODE, maybe it's a good idea to add support for more + // Ref: http://jkorpela.fi/chars/spaces.html + if ((codepoint == ' ') || (codepoint == '\t') || (codepoint == '\n')) endLine = i; + + if ((textOffsetX + glyphWidth) > rec.width) + { + endLine = (endLine < 1)? i : endLine; + if (i == endLine) endLine -= codepointByteCount; + if ((startLine + codepointByteCount) == endLine) endLine = (i - codepointByteCount); + + state = !state; + } + else if ((i + 1) == length) + { + endLine = i; + state = !state; + } + else if (codepoint == '\n') state = !state; + + if (state == DRAW_STATE) + { + textOffsetX = 0; + i = startLine; + glyphWidth = 0; + + // Save character position when we switch states + int tmp = lastk; + lastk = k - 1; + k = tmp; + } + } + else + { + if (codepoint == '\n') + { + if (!wordWrap) + { + textOffsetY += (font.baseSize + font.baseSize/2)*scaleFactor; + textOffsetX = 0; + } + } + else + { + if (!wordWrap && ((textOffsetX + glyphWidth) > rec.width)) + { + textOffsetY += (font.baseSize + font.baseSize/2)*scaleFactor; + textOffsetX = 0; + } + + // When text overflows rectangle height limit, just stop drawing + if ((textOffsetY + font.baseSize*scaleFactor) > rec.height) break; + + // Draw selection background + bool isGlyphSelected = false; + if ((selectStart >= 0) && (k >= selectStart) && (k < (selectStart + selectLength))) + { + DrawRectangleRec((Rectangle){ rec.x + textOffsetX - 1, rec.y + textOffsetY, glyphWidth, (float)font.baseSize*scaleFactor }, selectBackTint); + isGlyphSelected = true; + } + + // Draw current character glyph + if ((codepoint != ' ') && (codepoint != '\t')) + { + DrawTextCodepoint(font, codepoint, (Vector2){ rec.x + textOffsetX, rec.y + textOffsetY }, fontSize, isGlyphSelected? selectTint : tint); + } + } + + if (wordWrap && (i == endLine)) + { + textOffsetY += (font.baseSize + font.baseSize/2)*scaleFactor; + textOffsetX = 0; + startLine = endLine; + endLine = -1; + glyphWidth = 0; + selectStart += lastk - k; + k = lastk; + + state = !state; + } + } + + textOffsetX += glyphWidth; + } } \ No newline at end of file diff --git a/examples/text/text_unicode.c b/examples/text/text_unicode.c index fa336de7f..2954a28e1 100644 --- a/examples/text/text_unicode.c +++ b/examples/text/text_unicode.c @@ -133,6 +133,9 @@ struct { //-------------------------------------------------------------------------------------- static void RandomizeEmoji(void); // Fills the emoji array with random emojis +static void DrawTextRec(Font font, const char *text, Rectangle rec, float fontSize, float spacing, bool wordWrap, Color tint); // Draw text using font inside rectangle limits +static void DrawTextRecEx(Font font, const char *text, Rectangle rec, float fontSize, float spacing, bool wordWrap, Color tint, int selectStart, int selectLength, Color selectTint, Color selectBackTint); // Draw text using font inside rectangle limits with support for text selection + //-------------------------------------------------------------------------------------- // Global variables //-------------------------------------------------------------------------------------- @@ -145,6 +148,9 @@ struct { static int hovered = -1, selected = -1; +//-------------------------------------------------------------------------------------- +// Main entry point +//-------------------------------------------------------------------------------------- int main(int argc, char **argv) { // Initialization @@ -317,3 +323,143 @@ static void RandomizeEmoji(void) emoji[i].message = GetRandomValue(0, SIZEOF(messages) - 1); } } + +//-------------------------------------------------------------------------------------- +// Module functions definition +//-------------------------------------------------------------------------------------- + +// Draw text using font inside rectangle limits +static void DrawTextRec(Font font, const char *text, Rectangle rec, float fontSize, float spacing, bool wordWrap, Color tint) +{ + DrawTextRecEx(font, text, rec, fontSize, spacing, wordWrap, tint, 0, 0, WHITE, WHITE); +} + +// Draw text using font inside rectangle limits with support for text selection +static void DrawTextRecEx(Font font, const char *text, Rectangle rec, float fontSize, float spacing, bool wordWrap, Color tint, int selectStart, int selectLength, Color selectTint, Color selectBackTint) +{ + int length = TextLength(text); // Total length in bytes of the text, scanned by codepoints in loop + + float textOffsetY = 0; // Offset between lines (on line break '\n') + float textOffsetX = 0.0f; // Offset X to next character to draw + + float scaleFactor = fontSize/(float)font.baseSize; // Character rectangle scaling factor + + // Word/character wrapping mechanism variables + enum { MEASURE_STATE = 0, DRAW_STATE = 1 }; + int state = wordWrap? MEASURE_STATE : DRAW_STATE; + + int startLine = -1; // Index where to begin drawing (where a line begins) + int endLine = -1; // Index where to stop drawing (where a line ends) + int lastk = -1; // Holds last value of the character position + + for (int i = 0, k = 0; i < length; i++, k++) + { + // Get next codepoint from byte string and glyph index in font + int codepointByteCount = 0; + int codepoint = GetCodepoint(&text[i], &codepointByteCount); + int index = GetGlyphIndex(font, codepoint); + + // NOTE: Normally we exit the decoding sequence as soon as a bad byte is found (and return 0x3f) + // but we need to draw all of the bad bytes using the '?' symbol moving one byte + if (codepoint == 0x3f) codepointByteCount = 1; + i += (codepointByteCount - 1); + + float glyphWidth = 0; + if (codepoint != '\n') + { + glyphWidth = (font.chars[index].advanceX == 0) ? font.recs[index].width*scaleFactor : font.chars[index].advanceX*scaleFactor; + + if (i + 1 < length) glyphWidth = glyphWidth + spacing; + } + + // NOTE: When wordWrap is ON we first measure how much of the text we can draw before going outside of the rec container + // We store this info in startLine and endLine, then we change states, draw the text between those two variables + // and change states again and again recursively until the end of the text (or until we get outside of the container). + // When wordWrap is OFF we don't need the measure state so we go to the drawing state immediately + // and begin drawing on the next line before we can get outside the container. + if (state == MEASURE_STATE) + { + // TODO: There are multiple types of spaces in UNICODE, maybe it's a good idea to add support for more + // Ref: http://jkorpela.fi/chars/spaces.html + if ((codepoint == ' ') || (codepoint == '\t') || (codepoint == '\n')) endLine = i; + + if ((textOffsetX + glyphWidth) > rec.width) + { + endLine = (endLine < 1)? i : endLine; + if (i == endLine) endLine -= codepointByteCount; + if ((startLine + codepointByteCount) == endLine) endLine = (i - codepointByteCount); + + state = !state; + } + else if ((i + 1) == length) + { + endLine = i; + state = !state; + } + else if (codepoint == '\n') state = !state; + + if (state == DRAW_STATE) + { + textOffsetX = 0; + i = startLine; + glyphWidth = 0; + + // Save character position when we switch states + int tmp = lastk; + lastk = k - 1; + k = tmp; + } + } + else + { + if (codepoint == '\n') + { + if (!wordWrap) + { + textOffsetY += (font.baseSize + font.baseSize/2)*scaleFactor; + textOffsetX = 0; + } + } + else + { + if (!wordWrap && ((textOffsetX + glyphWidth) > rec.width)) + { + textOffsetY += (font.baseSize + font.baseSize/2)*scaleFactor; + textOffsetX = 0; + } + + // When text overflows rectangle height limit, just stop drawing + if ((textOffsetY + font.baseSize*scaleFactor) > rec.height) break; + + // Draw selection background + bool isGlyphSelected = false; + if ((selectStart >= 0) && (k >= selectStart) && (k < (selectStart + selectLength))) + { + DrawRectangleRec((Rectangle){ rec.x + textOffsetX - 1, rec.y + textOffsetY, glyphWidth, (float)font.baseSize*scaleFactor }, selectBackTint); + isGlyphSelected = true; + } + + // Draw current character glyph + if ((codepoint != ' ') && (codepoint != '\t')) + { + DrawTextCodepoint(font, codepoint, (Vector2){ rec.x + textOffsetX, rec.y + textOffsetY }, fontSize, isGlyphSelected? selectTint : tint); + } + } + + if (wordWrap && (i == endLine)) + { + textOffsetY += (font.baseSize + font.baseSize/2)*scaleFactor; + textOffsetX = 0; + startLine = endLine; + endLine = -1; + glyphWidth = 0; + selectStart += lastk - k; + k = lastk; + + state = !state; + } + } + + textOffsetX += glyphWidth; + } +} \ No newline at end of file diff --git a/src/raylib.h b/src/raylib.h index f02f46f66..fc64858ea 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -1329,9 +1329,6 @@ RLAPI void UnloadFont(Font font); RLAPI void DrawFPS(int posX, int posY); // Draw current FPS RLAPI void DrawText(const char *text, int posX, int posY, int fontSize, Color color); // Draw text (using default font) RLAPI void DrawTextEx(Font font, const char *text, Vector2 position, float fontSize, float spacing, Color tint); // Draw text using font and additional parameters -//RLAPI void DrawTextPro(Font font, const char *text, Vector2 position, Vector2 origin, float rotation, float fontSize, float spacing, Color tint); -RLAPI void DrawTextRec(Font font, const char *text, Rectangle rec, float fontSize, float spacing, bool wordWrap, Color tint); // Draw text using font inside rectangle limits -RLAPI void DrawTextRecEx(Font font, const char *text, Rectangle rec, float fontSize, float spacing, bool wordWrap, Color tint, int selectStart, int selectLength, Color selectTint, Color selectBackTint); // Draw text using font inside rectangle limits with support for text selection RLAPI void DrawTextCodepoint(Font font, int codepoint, Vector2 position, float fontSize, Color tint); // Draw one character (codepoint) // Text misc. functions diff --git a/src/text.c b/src/text.c index 0371a0cec..f12518f46 100644 --- a/src/text.c +++ b/src/text.c @@ -890,140 +890,7 @@ void DrawTextEx(Font font, const char *text, Vector2 position, float fontSize, f } } -// Draw text using font inside rectangle limits -void DrawTextRec(Font font, const char *text, Rectangle rec, float fontSize, float spacing, bool wordWrap, Color tint) { - DrawTextRecEx(font, text, rec, fontSize, spacing, wordWrap, tint, 0, 0, WHITE, WHITE); -} - -// Draw text using font inside rectangle limits with support for text selection -void DrawTextRecEx(Font font, const char *text, Rectangle rec, float fontSize, float spacing, bool wordWrap, Color tint, int selectStart, int selectLength, Color selectTint, Color selectBackTint) -{ - int length = TextLength(text); // Total length in bytes of the text, scanned by codepoints in loop - - float textOffsetY = 0; // Offset between lines (on line break '\n') - float textOffsetX = 0.0f; // Offset X to next character to draw - - float scaleFactor = fontSize/(float)font.baseSize; // Character quad scaling factor - - // Word/character wrapping mechanism variables - enum { MEASURE_STATE = 0, DRAW_STATE = 1 }; - int state = wordWrap? MEASURE_STATE : DRAW_STATE; - - int startLine = -1; // Index where to begin drawing (where a line begins) - int endLine = -1; // Index where to stop drawing (where a line ends) - int lastk = -1; // Holds last value of the character position - - for (int i = 0, k = 0; i < length; i++, k++) - { - // Get next codepoint from byte string and glyph index in font - int codepointByteCount = 0; - int codepoint = GetCodepoint(&text[i], &codepointByteCount); - int index = GetGlyphIndex(font, codepoint); - - // NOTE: Normally we exit the decoding sequence as soon as a bad byte is found (and return 0x3f) - // but we need to draw all of the bad bytes using the '?' symbol moving one byte - if (codepoint == 0x3f) codepointByteCount = 1; - i += (codepointByteCount - 1); - - float glyphWidth = 0; - if (codepoint != '\n') - { - glyphWidth = (font.chars[index].advanceX == 0) ? font.recs[index].width*scaleFactor : font.chars[index].advanceX*scaleFactor; - - if (i + 1 < length) glyphWidth = glyphWidth + spacing; - } - - // NOTE: When wordWrap is ON we first measure how much of the text we can draw before going outside of the rec container - // We store this info in startLine and endLine, then we change states, draw the text between those two variables - // and change states again and again recursively until the end of the text (or until we get outside of the container). - // When wordWrap is OFF we don't need the measure state so we go to the drawing state immediately - // and begin drawing on the next line before we can get outside the container. - if (state == MEASURE_STATE) - { - // TODO: There are multiple types of spaces in UNICODE, maybe it's a good idea to add support for more - // Ref: http://jkorpela.fi/chars/spaces.html - if ((codepoint == ' ') || (codepoint == '\t') || (codepoint == '\n')) endLine = i; - - if ((textOffsetX + glyphWidth) > rec.width) - { - endLine = (endLine < 1)? i : endLine; - if (i == endLine) endLine -= codepointByteCount; - if ((startLine + codepointByteCount) == endLine) endLine = (i - codepointByteCount); - - state = !state; - } - else if ((i + 1) == length) - { - endLine = i; - state = !state; - } - else if (codepoint == '\n') state = !state; - - if (state == DRAW_STATE) - { - textOffsetX = 0; - i = startLine; - glyphWidth = 0; - - // Save character position when we switch states - int tmp = lastk; - lastk = k - 1; - k = tmp; - } - } - else - { - if (codepoint == '\n') - { - if (!wordWrap) - { - textOffsetY += (font.baseSize + font.baseSize/2)*scaleFactor; - textOffsetX = 0; - } - } - else - { - if (!wordWrap && ((textOffsetX + glyphWidth) > rec.width)) - { - textOffsetY += (font.baseSize + font.baseSize/2)*scaleFactor; - textOffsetX = 0; - } - - // When text overflows rectangle height limit, just stop drawing - if ((textOffsetY + font.baseSize*scaleFactor) > rec.height) break; - - // Draw selection background - bool isGlyphSelected = false; - if ((selectStart >= 0) && (k >= selectStart) && (k < (selectStart + selectLength))) - { - DrawRectangleRec((Rectangle){ rec.x + textOffsetX - 1, rec.y + textOffsetY, glyphWidth, (float)font.baseSize*scaleFactor }, selectBackTint); - isGlyphSelected = true; - } - - // Draw current character glyph - if ((codepoint != ' ') && (codepoint != '\t')) - { - DrawTextCodepoint(font, codepoint, (Vector2){ rec.x + textOffsetX, rec.y + textOffsetY }, fontSize, isGlyphSelected? selectTint : tint); - } - } - - if (wordWrap && (i == endLine)) - { - textOffsetY += (font.baseSize + font.baseSize/2)*scaleFactor; - textOffsetX = 0; - startLine = endLine; - endLine = -1; - glyphWidth = 0; - selectStart += lastk - k; - k = lastk; - - state = !state; - } - } - - textOffsetX += glyphWidth; - } } // Draw one character (codepoint) From b55418effd288d9989b86d34831c8d60a5c6c7a7 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Wed, 11 Aug 2021 18:31:56 +0200 Subject: [PATCH 12/23] ADDED: DrawTextPro() with text rotation support --- src/raylib.h | 3 ++- src/text.c | 10 ++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/raylib.h b/src/raylib.h index fc64858ea..438a079dc 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -1328,7 +1328,8 @@ RLAPI void UnloadFont(Font font); // Text drawing functions RLAPI void DrawFPS(int posX, int posY); // Draw current FPS RLAPI void DrawText(const char *text, int posX, int posY, int fontSize, Color color); // Draw text (using default font) -RLAPI void DrawTextEx(Font font, const char *text, Vector2 position, float fontSize, float spacing, Color tint); // Draw text using font and additional parameters +RLAPI void DrawTextEx(Font font, const char *text, Vector2 position, float fontSize, float spacing, Color tint); // Draw text using font and additional parameters +RLAPI void DrawTextPro(Font font, const char *text, Vector2 position, Vector2 origin, float rotation, float fontSize, float spacing, Color tint); // Draw text using Font and pro parameters (rotation) RLAPI void DrawTextCodepoint(Font font, int codepoint, Vector2 position, float fontSize, Color tint); // Draw one character (codepoint) // Text misc. functions diff --git a/src/text.c b/src/text.c index f12518f46..d8c3a6b7f 100644 --- a/src/text.c +++ b/src/text.c @@ -890,7 +890,17 @@ void DrawTextEx(Font font, const char *text, Vector2 position, float fontSize, f } } +// Draw text using Font and pro parameters (rotation) +void DrawTextPro(Font font, const char *text, Vector2 position, Vector2 origin, float rotation, float fontSize, float spacing, Color tint) { + rlPushMatrix(); + + rlTranslatef(origin.x, origin.y, 0.0f); + rlRotatef(rotation, 0.0f, 0.0f, 1.0f); + + DrawTextEx(font, text, position, fontSize, spacing, tint); + + rlPopMatrix(); } // Draw one character (codepoint) From 7e27c2ffa82337c6b4649295b4df1c7e1829c7fc Mon Sep 17 00:00:00 2001 From: raysan5 Date: Wed, 11 Aug 2021 18:53:06 +0200 Subject: [PATCH 13/23] TODO: DrawTextPro() rotation not working? --- src/text.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/text.c b/src/text.c index d8c3a6b7f..891c5497c 100644 --- a/src/text.c +++ b/src/text.c @@ -893,12 +893,15 @@ void DrawTextEx(Font font, const char *text, Vector2 position, float fontSize, f // Draw text using Font and pro parameters (rotation) void DrawTextPro(Font font, const char *text, Vector2 position, Vector2 origin, float rotation, float fontSize, float spacing, Color tint) { + // TODO: Not working... why??? + rlPushMatrix(); - rlTranslatef(origin.x, origin.y, 0.0f); + //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, position, fontSize, spacing, tint); + DrawTextEx(font, text, (Vector2){ position.x, position.y }, fontSize, spacing, tint); rlPopMatrix(); } From b6541b7a558304f8a6e27533195c898ea728b712 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Wed, 11 Aug 2021 19:02:15 +0200 Subject: [PATCH 14/23] REVIEWED: DrawTextPro() WARNING: DrawTextPro() requires including `rlgl.h`, before it was only dependant on `textures` module. --- src/text.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/text.c b/src/text.c index 891c5497c..1724153f9 100644 --- a/src/text.c +++ b/src/text.c @@ -53,6 +53,8 @@ #include "config.h" // Defines module configuration flags #endif +#include "rlgl.h" // OpenGL abstraction layer to OpenGL 1.1, 2.1, 3.3+ or ES2 -> Only DrawTextPro() + #include // Required for: malloc(), free() #include // Required for: vsprintf() #include // Required for: strcmp(), strstr(), strcpy(), strncpy() [Used in TextReplace()], sscanf() [Used in LoadBMFont()] @@ -893,15 +895,13 @@ void DrawTextEx(Font font, const char *text, Vector2 position, float fontSize, f // Draw text using Font and pro parameters (rotation) void DrawTextPro(Font font, const char *text, Vector2 position, Vector2 origin, float rotation, float fontSize, float spacing, Color tint) { - // TODO: Not working... why??? - rlPushMatrix(); - //rlTranslatef(position.x, position.y, 0.0f); + 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){ position.x, position.y }, fontSize, spacing, tint); + DrawTextEx(font, text, (Vector2){ 0.0f, 0.0f }, fontSize, spacing, tint); rlPopMatrix(); } From 621a8766a812e508037e580c4e5d8419d12977be Mon Sep 17 00:00:00 2001 From: raysan5 Date: Wed, 11 Aug 2021 21:16:39 +0200 Subject: [PATCH 15/23] WARNING: BREAKING: Renamed `CharInfo` to `GlyphInfo` and more... This commit introduces some breaking changes for library consistency, hopefully not too dramatic... Here the full list: - RENAMED: struct `CharInfo` to `GlyphInfo`, actually that's the correct naming for the data contained. It contains the character glyph metrics and the glyph image; in the past it also contained rectangle within the font atlas but that data has been moved to `Font` struct directly, so, `GlyphInfo` is a more correct name. - RENAMED: `CodepointToUtf8()` to `CodepointToUTF8()`, capitalization of UTF-8 is the correct form, it would also require de hyphen but it can be omitted in this case. - RENAMED: `TextToUtf8()` to `TextCodepointsToUTF8` for consistency and more detail on the functionality. - ADDED: `GetGlyphInfo()` to get glyph info for a specific codepoint - ADDED: `GetGlyphAtlasRec()` to get glyph rectangle within the generated font atlas - Some additional tweaks for consistency --- src/raylib.h | 52 ++++++++++++++++++++-------------------- src/text.c | 67 +++++++++++++++++++++++++++++++++++----------------- 2 files changed, 72 insertions(+), 47 deletions(-) diff --git a/src/raylib.h b/src/raylib.h index 438a079dc..7f8728137 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -282,23 +282,23 @@ typedef struct NPatchInfo { int layout; // Layout of the n-patch: 3x3, 1x3 or 3x1 } NPatchInfo; -// CharInfo, font character info -typedef struct CharInfo { +// GlyphInfo, font characters glyphs info +typedef struct GlyphInfo { int value; // Character value (Unicode) int offsetX; // Character offset X when drawing int offsetY; // Character offset Y when drawing int advanceX; // Character advance position X Image image; // Character image data -} CharInfo; +} GlyphInfo; -// Font, font texture and CharInfo array data +// Font, font texture and GlyphInfo array data typedef struct Font { int baseSize; // Base size (default chars height) int charsCount; // Number of characters int charsPadding; // Padding around the chars Texture2D texture; // Characters texture atlas Rectangle *recs; // Characters rectangles in texture - CharInfo *chars; // Characters info data + GlyphInfo *chars; // Characters glyphs info data } Font; // Camera, defines position/orientation in 3d space @@ -1077,8 +1077,8 @@ RLAPI bool IsKeyDown(int key); // Check if a key RLAPI bool IsKeyReleased(int key); // Check if a key has been released once RLAPI bool IsKeyUp(int key); // Check if a key is NOT being pressed RLAPI void SetExitKey(int key); // Set a custom key to exit program (default is ESC) -RLAPI int GetKeyPressed(void); // Get key pressed (keycode), call it multiple times for keys queued. Returns 0 when the queue is empty. -RLAPI int GetCharPressed(void); // Get char pressed (unicode), call it multiple times for chars queued. Returns 0 when the queue is empty. +RLAPI int GetKeyPressed(void); // Get key pressed (keycode), call it multiple times for keys queued, returns 0 when the queue is empty +RLAPI int GetCharPressed(void); // Get char pressed (unicode), call it multiple times for chars queued, returns 0 when the queue is empty // Input-related functions: gamepads RLAPI bool IsGamepadAvailable(int gamepad); // Check if a gamepad is available @@ -1217,7 +1217,7 @@ RLAPI Image GenImageGradientRadial(int width, int height, float density, Color i RLAPI Image GenImageChecked(int width, int height, int checksX, int checksY, Color col1, Color col2); // Generate image: checked RLAPI Image GenImageWhiteNoise(int width, int height, float factor); // Generate image: white noise RLAPI Image GenImagePerlinNoise(int width, int height, int offsetX, int offsetY, float scale); // Generate image: perlin noise -RLAPI Image GenImageCellular(int width, int height, int tileSize); // Generate image: cellular algorithm. Bigger tileSize means bigger cells +RLAPI Image GenImageCellular(int width, int height, int tileSize); // Generate image: cellular algorithm, bigger tileSize means bigger cells // Image manipulation functions RLAPI Image ImageCopy(Image image); // Create an image duplicate (useful for transformations) @@ -1320,9 +1320,9 @@ RLAPI Font LoadFont(const char *fileName); RLAPI Font LoadFontEx(const char *fileName, int fontSize, int *fontChars, int charsCount); // Load font from file with extended parameters RLAPI Font LoadFontFromImage(Image image, Color key, int firstChar); // Load font from Image (XNA style) RLAPI Font LoadFontFromMemory(const char *fileType, const unsigned char *fileData, int dataSize, int fontSize, int *fontChars, int charsCount); // Load font from memory buffer, fileType refers to extension: i.e. '.ttf' -RLAPI CharInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSize, int *fontChars, int charsCount, int type); // Load font data for further use -RLAPI Image GenImageFontAtlas(const CharInfo *chars, Rectangle **recs, int charsCount, int fontSize, int padding, int packMethod); // Generate image font atlas using chars info -RLAPI void UnloadFontData(CharInfo *chars, int charsCount); // Unload font chars info data (RAM) +RLAPI GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSize, int *fontChars, int charsCount, int type); // Load font data for further use +RLAPI Image GenImageFontAtlas(const GlyphInfo *chars, Rectangle **recs, int charsCount, int fontSize, int padding, int packMethod); // Generate image font atlas using chars info +RLAPI void UnloadFontData(GlyphInfo *chars, int charsCount); // Unload font chars info data (RAM) RLAPI void UnloadFont(Font font); // Unload Font from GPU memory (VRAM) // Text drawing functions @@ -1332,20 +1332,30 @@ RLAPI void DrawTextEx(Font font, const char *text, Vector2 position, float fontS RLAPI void DrawTextPro(Font font, const char *text, Vector2 position, Vector2 origin, float rotation, float fontSize, float spacing, Color tint); // Draw text using Font and pro parameters (rotation) RLAPI void DrawTextCodepoint(Font font, int codepoint, Vector2 position, float fontSize, Color tint); // Draw one character (codepoint) -// Text misc. functions +// Text font info functions RLAPI int MeasureText(const char *text, int fontSize); // Measure string width for default font RLAPI Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing); // Measure string size for Font -RLAPI int GetGlyphIndex(Font font, int codepoint); // Get index position for a unicode character on font +RLAPI int GetGlyphIndex(Font font, int codepoint); // Get glyph index position in font for a codepoint (unicode character), fallback to '?' if not found +RLAPI GlyphInfo GetGlyphInfo(Font font, int codepoint); // Get glyph font info data for a codepoint (unicode character), fallback to '?' if not found +RLAPI Rectangle GetGlyphAtlasRec(Font font, int codepoint); // Get glyph rectangle in font atlas for a codepoint (unicode character), fallback to '?' if not found -// Text strings management functions (no utf8 strings, only byte chars) +// Text codepoints management functions (unicode characters) +RLAPI int *LoadCodepoints(const char *text, int *count); // Load all codepoints from a UTF-8 text string, codepoints count returned by parameter +RLAPI void UnloadCodepoints(int *codepoints); // Unload codepoints data from memory +RLAPI int GetCodepointsCount(const char *text); // Get total number of codepoints in a UTF-8 encoded string +RLAPI int GetCodepoint(const char *text, int *bytesProcessed); // Get next codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure +RLAPI const char *CodepointToUTF8(int codepoint, int *byteLength); // Encode one codepoint into UTF-8 byte array (array length returned as parameter) +RLAPI char *TextCodepointsToUTF8(int *codepoints, int length); // Encode text as codepoints array into UTF-8 text string (WARNING: memory must be freed!) + +// Text strings management functions (no UTF-8 strings, only byte chars) // NOTE: Some strings allocate memory internally for returned strings, just be careful! RLAPI int TextCopy(char *dst, const char *src); // Copy one string to another, returns bytes copied RLAPI bool TextIsEqual(const char *text1, const char *text2); // Check if two text string are equal RLAPI unsigned int TextLength(const char *text); // Get text length, checks for '\0' ending -RLAPI const char *TextFormat(const char *text, ...); // Text formatting with variables (sprintf style) +RLAPI const char *TextFormat(const char *text, ...); // Text formatting with variables (sprintf() style) RLAPI const char *TextSubtext(const char *text, int position, int length); // Get a piece of a text string -RLAPI char *TextReplace(char *text, const char *replace, const char *by); // Replace text string (memory must be freed!) -RLAPI char *TextInsert(const char *text, const char *insert, int position); // Insert text in a position (memory must be freed!) +RLAPI char *TextReplace(char *text, const char *replace, const char *by); // Replace text string (WARNING: memory must be freed!) +RLAPI char *TextInsert(const char *text, const char *insert, int position); // Insert text in a position (WARNING: memory must be freed!) RLAPI const char *TextJoin(const char **textList, int count, const char *delimiter); // Join text strings with delimiter RLAPI const char **TextSplit(const char *text, char delimiter, int *count); // Split text into multiple strings RLAPI void TextAppend(char *text, const char *append, int *position); // Append text at specific position and move cursor! @@ -1354,14 +1364,6 @@ RLAPI const char *TextToUpper(const char *text); // Get upp RLAPI const char *TextToLower(const char *text); // Get lower case version of provided string RLAPI const char *TextToPascal(const char *text); // Get Pascal case notation version of provided string RLAPI int TextToInteger(const char *text); // Get integer value from text (negative values not supported) -RLAPI char *TextToUtf8(int *codepoints, int length); // Encode text codepoint into utf8 text (memory must be freed!) - -// UTF8 text strings management functions -RLAPI int *LoadCodepoints(const char *text, int *count); // Load all codepoints from a UTF8 text string, codepoints count returned by parameter -RLAPI void UnloadCodepoints(int *codepoints); // Unload codepoints data from memory -RLAPI int GetCodepointsCount(const char *text); // Get total number of characters (codepoints) in a UTF8 encoded string -RLAPI int GetCodepoint(const char *text, int *bytesProcessed); // Get next codepoint in a UTF8 encoded string, 0x3f('?') is returned on failure -RLAPI const char *CodepointToUtf8(int codepoint, int *byteLength); // Encode codepoint into utf8 text (char array length returned as parameter) //------------------------------------------------------------------------------------ // Basic 3d Shapes Drawing Functions (Module: models) diff --git a/src/text.c b/src/text.c index 1724153f9..9d336f218 100644 --- a/src/text.c +++ b/src/text.c @@ -53,6 +53,7 @@ #include "config.h" // Defines module configuration flags #endif +#include "utils.h" // Required for: LoadFileText() #include "rlgl.h" // OpenGL abstraction layer to OpenGL 1.1, 2.1, 3.3+ or ES2 -> Only DrawTextPro() #include // Required for: malloc(), free() @@ -61,8 +62,6 @@ #include // Required for: va_list, va_start(), vsprintf(), va_end() [Used in TextFormat()] #include // Requried for: toupper(), tolower() [Used in TextToUpper(), TextToLower()] -#include "utils.h" // Required for: LoadFileText() - #if defined(SUPPORT_FILEFORMAT_TTF) #define STB_RECT_PACK_IMPLEMENTATION #include "external/stb_rect_pack.h" // Required for: ttf font rectangles packaging @@ -127,7 +126,7 @@ extern void LoadFontDefault(void) { #define BIT_CHECK(a,b) ((a) & (1u << (b))) - // NOTE: Using UTF8 encoding table for Unicode U+0000..U+00FF Basic Latin + Latin-1 Supplement + // NOTE: Using UTF-8 encoding table for Unicode U+0000..U+00FF Basic Latin + Latin-1 Supplement // Ref: http://www.utf8-chartable.de/unicode-utf8-table.pl defaultFont.charsCount = 224; // Number of chars included in our default font @@ -226,7 +225,7 @@ extern void LoadFontDefault(void) // Allocate space for our characters info data // NOTE: This memory should be freed at end! --> CloseWindow() - defaultFont.chars = (CharInfo *)RL_MALLOC(defaultFont.charsCount*sizeof(CharInfo)); + defaultFont.chars = (GlyphInfo *)RL_MALLOC(defaultFont.charsCount*sizeof(GlyphInfo)); defaultFont.recs = (Rectangle *)RL_MALLOC(defaultFont.charsCount*sizeof(Rectangle)); int currentLine = 0; @@ -455,7 +454,7 @@ Font LoadFontFromImage(Image image, Color key, int firstChar) // We got tempCharValues and tempCharsRecs populated with chars data // Now we move temp data to sized charValues and charRecs arrays - font.chars = (CharInfo *)RL_MALLOC(font.charsCount*sizeof(CharInfo)); + font.chars = (GlyphInfo *)RL_MALLOC(font.charsCount*sizeof(GlyphInfo)); font.recs = (Rectangle *)RL_MALLOC(font.charsCount*sizeof(Rectangle)); for (int i = 0; i < font.charsCount; i++) @@ -525,7 +524,7 @@ Font LoadFontFromMemory(const char *fileType, const unsigned char *fileData, int // Load font data for further use // NOTE: Requires TTF font memory data and can generate SDF data -CharInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSize, int *fontChars, int charsCount, int type) +GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSize, int *fontChars, int charsCount, int type) { // NOTE: Using some SDF generation default values, // trades off precision with ability to handle *smaller* sizes @@ -542,7 +541,7 @@ CharInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSize #define FONT_BITMAP_ALPHA_THRESHOLD 80 // Bitmap (B&W) font generation alpha threshold #endif - CharInfo *chars = NULL; + GlyphInfo *chars = NULL; #if defined(SUPPORT_FILEFORMAT_TTF) // Load font data (including pixel data) from TTF memory file @@ -575,7 +574,7 @@ CharInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSize genFontChars = true; } - chars = (CharInfo *)RL_MALLOC(charsCount*sizeof(CharInfo)); + chars = (GlyphInfo *)RL_MALLOC(charsCount*sizeof(GlyphInfo)); // NOTE: Using simple packaging, one char after another for (int i = 0; i < charsCount; i++) @@ -651,7 +650,7 @@ CharInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSize // Generate image font atlas using chars info // NOTE: Packing method: 0-Default, 1-Skyline #if defined(SUPPORT_FILEFORMAT_TTF) -Image GenImageFontAtlas(const CharInfo *chars, Rectangle **charRecs, int charsCount, int fontSize, int padding, int packMethod) +Image GenImageFontAtlas(const GlyphInfo *chars, Rectangle **charRecs, int charsCount, int fontSize, int padding, int packMethod) { Image atlas = { 0 }; @@ -794,7 +793,7 @@ Image GenImageFontAtlas(const CharInfo *chars, Rectangle **charRecs, int charsCo #endif // Unload font chars info data (RAM) -void UnloadFontData(CharInfo *chars, int charsCount) +void UnloadFontData(GlyphInfo *chars, int charsCount) { for (int i = 0; i < charsCount; i++) UnloadImage(chars[i].image); @@ -1003,6 +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 '?' int GetGlyphIndex(Font font, int codepoint) { #ifndef GLYPH_NOTFOUND_CHAR_FALLBACK @@ -1029,6 +1029,28 @@ int GetGlyphIndex(Font font, int codepoint) #endif } +// Get glyph font info data for a codepoint (unicode character) +// 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 '?' +Rectangle GetGlyphAtlasRec(Font font, int codepoint) +{ + Rectangle rec = { 0 }; + + rec = font.recs[GetGlyphIndex(font, codepoint)]; + + return rec; +} + //---------------------------------------------------------------------------------- // Text strings management functions //---------------------------------------------------------------------------------- @@ -1326,7 +1348,7 @@ const char *TextToUpper(const char *text) buffer[i] = (char)toupper(text[i]); //if ((text[i] >= 'a') && (text[i] <= 'z')) buffer[i] = text[i] - 32; - // TODO: Support Utf8 diacritics! + // TODO: Support UTF-8 diacritics! //if ((text[i] >= 'à') && (text[i] <= 'ý')) buffer[i] = text[i] - 32; } else { buffer[i] = '\0'; break; } @@ -1379,10 +1401,10 @@ const char *TextToPascal(const char *text) return buffer; } -// Encode text codepoint into utf8 text +// Encode text codepoint into UTF-8 text // REQUIRES: memcpy() // WARNING: Allocated memory should be manually freed -char *TextToUtf8(int *codepoints, int length) +char *TextCodepointsToUTF8(int *codepoints, int length) { // We allocate enough memory fo fit all possible codepoints // NOTE: 5 bytes for every codepoint should be enough @@ -1392,7 +1414,7 @@ char *TextToUtf8(int *codepoints, int length) for (int i = 0, bytes = 0; i < length; i++) { - utf8 = CodepointToUtf8(codepoints[i], &bytes); + utf8 = CodepointToUTF8(codepoints[i], &bytes); memcpy(text + size, utf8, bytes); size += bytes; } @@ -1406,7 +1428,8 @@ char *TextToUtf8(int *codepoints, int length) } // Encode codepoint into utf8 text (char array length returned as parameter) -RLAPI const char *CodepointToUtf8(int codepoint, int *byteLength) +// NOTE: It uses a static array to store UTF-8 bytes +RLAPI const char *CodepointToUTF8(int codepoint, int *byteLength) { static char utf8[6] = { 0 }; int length = 0; @@ -1443,7 +1466,7 @@ RLAPI const char *CodepointToUtf8(int codepoint, int *byteLength) return utf8; } -// Load all codepoints from a UTF8 text string, codepoints count returned by parameter +// Load all codepoints from a UTF-8 text string, codepoints count returned by parameter int *LoadCodepoints(const char *text, int *count) { int textLength = TextLength(text); @@ -1475,8 +1498,8 @@ void UnloadCodepoints(int *codepoints) RL_FREE(codepoints); } -// Get total number of characters(codepoints) in a UTF8 encoded text, until '\0' is found -// NOTE: If an invalid UTF8 sequence is encountered a '?'(0x3f) codepoint is counted instead +// Get total number of characters(codepoints) in a UTF-8 encoded text, until '\0' is found +// NOTE: If an invalid UTF-8 sequence is encountered a '?'(0x3f) codepoint is counted instead int GetCodepointsCount(const char *text) { unsigned int len = 0; @@ -1497,8 +1520,8 @@ int GetCodepointsCount(const char *text) } #endif // SUPPORT_TEXT_MANIPULATION -// Get next codepoint in a UTF8 encoded text, scanning until '\0' is found -// When a invalid UTF8 byte is encountered we exit as soon as possible and a '?'(0x3f) codepoint is returned +// Get next codepoint in a UTF-8 encoded text, scanning until '\0' is found +// When a invalid UTF-8 byte is encountered we exit as soon as possible and a '?'(0x3f) codepoint is returned // Total number of bytes processed are returned as a parameter // NOTE: the standard says U+FFFD should be returned in case of errors // but that character is not supported by the default font in raylib @@ -1506,7 +1529,7 @@ int GetCodepointsCount(const char *text) int GetCodepoint(const char *text, int *bytesProcessed) { /* - UTF8 specs from https://www.ietf.org/rfc/rfc3629.txt + UTF-8 specs from https://www.ietf.org/rfc/rfc3629.txt Char. number range | UTF-8 octet sequence (hexadecimal) | (binary) @@ -1725,7 +1748,7 @@ static Font LoadBMFont(const char *fileName) font.baseSize = fontSize; font.charsCount = charsCount; font.charsPadding = 0; - font.chars = (CharInfo *)RL_MALLOC(charsCount*sizeof(CharInfo)); + font.chars = (GlyphInfo *)RL_MALLOC(charsCount*sizeof(GlyphInfo)); font.recs = (Rectangle *)RL_MALLOC(charsCount*sizeof(Rectangle)); int charId, charX, charY, charWidth, charHeight, charOffsetX, charOffsetY, charAdvanceX; From ce3214b82d95165f18a9273ffa1b106947b1d33b Mon Sep 17 00:00:00 2001 From: 630Studios Date: Thu, 12 Aug 2021 02:47:00 -0500 Subject: [PATCH 16/23] [rlgl] rlUpdateVertexBuffer (#1914) * GenMeshTangents Fix * GenMeshTangents Fix - Comment Update * GenMeshTangents Fix - Comment Update final * Code Style Changes * Code Style Changes Final * Code Style Changes Final 2 * GenMeshTangents better handling for issue #1876 * GenMeshTangents better handling for issue #1876 * GenMeshTangents: Better fix for issue #1876 * vboId location fix * rlUpdateVertexBuffer - bufferId is an unsigned int --- src/rlgl.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rlgl.h b/src/rlgl.h index 76b5114af..b6203ae87 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -584,7 +584,7 @@ RLAPI void rlSetTexture(unsigned int id); // Set current texture for r RLAPI unsigned int rlLoadVertexArray(void); // Load vertex array (vao) if supported RLAPI unsigned int rlLoadVertexBuffer(void *buffer, int size, bool dynamic); // Load a vertex buffer attribute RLAPI unsigned int rlLoadVertexBufferElement(void *buffer, int size, bool dynamic); // Load a new attributes element buffer -RLAPI void rlUpdateVertexBuffer(int bufferId, void *data, int dataSize, int offset); // Update GPU buffer with new data +RLAPI void rlUpdateVertexBuffer(unsigned int bufferId, void *data, int dataSize, int offset); // Update GPU buffer with new data RLAPI void rlUnloadVertexArray(unsigned int vaoId); RLAPI void rlUnloadVertexBuffer(unsigned int vboId); RLAPI void rlSetVertexAttribute(unsigned int index, int compSize, int type, bool normalized, int stride, void *pointer); @@ -3209,7 +3209,7 @@ void rlDisableVertexBufferElement(void) // Update GPU buffer with new data // NOTE: dataSize and offset must be provided in bytes -void rlUpdateVertexBuffer(int bufferId, void *data, int dataSize, int offset) +void rlUpdateVertexBuffer(unsigned int bufferId, void *data, int dataSize, int offset) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) glBindBuffer(GL_ARRAY_BUFFER, bufferId); From 26db3915760179c4985a335196d4e8299da2eb6d Mon Sep 17 00:00:00 2001 From: raysan5 Date: Thu, 12 Aug 2021 20:38:57 +0200 Subject: [PATCH 17/23] ADDED: `rlActiveDrawBuffers()` #1911 - ADDED: rlEnableColorBlend()/rlDisableColorBlend() --- src/rlgl.h | 56 ++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 50 insertions(+), 6 deletions(-) diff --git a/src/rlgl.h b/src/rlgl.h index b6203ae87..9cb1a2d89 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -525,8 +525,11 @@ RLAPI void rlDisableShader(void); // Disable shader progra // Framebuffer state RLAPI void rlEnableFramebuffer(unsigned int id); // Enable render texture (fbo) RLAPI void rlDisableFramebuffer(void); // Disable render texture (fbo), return to default framebuffer +RLAPI void rlActiveDrawBuffers(int count); // Activate multiple draw color buffers // General render state +RLAPI void rlEnableColorBlend(void); // Enable color blending +RLAPI void rlDisableColorBlend(void); // Disable color blending RLAPI void rlEnableDepthTest(void); // Enable depth test RLAPI void rlDisableDepthTest(void); // Disable depth test RLAPI void rlEnableDepthMask(void); // Enable depth write @@ -1544,6 +1547,49 @@ void rlDisableFramebuffer(void) #endif } +// Activate multiple draw color buffers +// NOTE: One color buffer is always active by default +void rlActiveDrawBuffers(int count) +{ +#if (defined(GRAPHICS_API_OPENGL_33) && defined(SUPPORT_RENDER_TEXTURES_HINT)) + // NOTE: Maximum number of draw buffers supported is implementation dependant, + // 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 + { + unsigned int buffers[8] = { + GL_COLOR_ATTACHMENT0, + GL_COLOR_ATTACHMENT1, + GL_COLOR_ATTACHMENT2, + GL_COLOR_ATTACHMENT3, + GL_COLOR_ATTACHMENT4, + GL_COLOR_ATTACHMENT5, + GL_COLOR_ATTACHMENT6, + GL_COLOR_ATTACHMENT7, + }; + + glDrawBuffers(count, buffers); + } + } + else TRACELOG(LOG_WARNING, "GL: One color buffer active by default"); +#endif +} + +//---------------------------------------------------------------------------------- +// General render state configuration +//---------------------------------------------------------------------------------- + +// Enable color blending +void rlEnableColorBlend(void) { glEnable(GL_BLEND); } + +// Disable color blending +void rlDisableColorBlend(void) { glDisable(GL_BLEND); } + // Enable depth test void rlEnableDepthTest(void) { glEnable(GL_DEPTH_TEST); } @@ -1588,11 +1634,9 @@ void rlDisableWireMode(void) glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); #endif } + // Set the line drawing width -void rlSetLineWidth(float width) -{ - glLineWidth(width); -} +void rlSetLineWidth(float width) { glLineWidth(width); } // Get the line drawing width float rlGetLineWidth(void) @@ -3209,10 +3253,10 @@ void rlDisableVertexBufferElement(void) // Update GPU buffer with new data // NOTE: dataSize and offset must be provided in bytes -void rlUpdateVertexBuffer(unsigned int bufferId, void *data, int dataSize, int offset) +void rlUpdateVertexBuffer(unsigned int id, void *data, int dataSize, int offset) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - glBindBuffer(GL_ARRAY_BUFFER, bufferId); + glBindBuffer(GL_ARRAY_BUFFER, id); glBufferSubData(GL_ARRAY_BUFFER, offset, dataSize, data); #endif } From 1dff5814be140a69de77b634f2d3e3ddac73243f Mon Sep 17 00:00:00 2001 From: raysan5 Date: Thu, 12 Aug 2021 21:01:09 +0200 Subject: [PATCH 18/23] ADDED: rlUpdateVertexBufferElements() #1915 --- src/rlgl.h | 35 ++++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/src/rlgl.h b/src/rlgl.h index 9cb1a2d89..6d18638db 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -506,8 +506,8 @@ RLAPI void rlDisableVertexBufferElement(void); // Disable vertex buffer RLAPI void rlEnableVertexAttribute(unsigned int index); // Enable vertex attribute index RLAPI void rlDisableVertexAttribute(unsigned int index);// Disable vertex attribute index #if defined(GRAPHICS_API_OPENGL_11) -RLAPI void rlEnableStatePointer(int vertexAttribType, void *buffer); -RLAPI void rlDisableStatePointer(int vertexAttribType); +RLAPI void rlEnableStatePointer(int vertexAttribType, void *buffer); // Enable attribute state pointer +RLAPI void rlDisableStatePointer(int vertexAttribType); // Disable attribute state pointer #endif // Textures state @@ -3223,6 +3223,7 @@ unsigned int rlLoadVertexBufferElement(void *buffer, int size, bool dynamic) return id; } +// Enable vertex buffer (VBO) void rlEnableVertexBuffer(unsigned int id) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) @@ -3230,6 +3231,7 @@ void rlEnableVertexBuffer(unsigned int id) #endif } +// Disable vertex buffer (VBO) void rlDisableVertexBuffer(void) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) @@ -3237,6 +3239,7 @@ void rlDisableVertexBuffer(void) #endif } +// Enable vertex buffer element (VBO element) void rlEnableVertexBufferElement(unsigned int id) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) @@ -3244,6 +3247,7 @@ void rlEnableVertexBufferElement(unsigned int id) #endif } +// Disable vertex buffer element (VBO element) void rlDisableVertexBufferElement(void) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) @@ -3251,7 +3255,7 @@ void rlDisableVertexBufferElement(void) #endif } -// Update GPU buffer with new data +// Update vertex buffer with new data // NOTE: dataSize and offset must be provided in bytes void rlUpdateVertexBuffer(unsigned int id, void *data, int dataSize, int offset) { @@ -3261,6 +3265,17 @@ void rlUpdateVertexBuffer(unsigned int id, void *data, int dataSize, int offset) #endif } +// Update vertex buffer elements with new data +// NOTE: dataSize and offset must be provided in bytes +void rlUpdateVertexBufferElements(unsigned int id, void *data, int dataSize, int offset) +{ +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, id); + glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, offset, dataSize, data); +#endif +} + +// Enable vertex array object (VAO) bool rlEnableVertexArray(unsigned int vaoId) { bool result = false; @@ -3274,6 +3289,7 @@ bool rlEnableVertexArray(unsigned int vaoId) return result; } +// Disable vertex array object (VAO) void rlDisableVertexArray(void) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) @@ -3281,6 +3297,7 @@ void rlDisableVertexArray(void) #endif } +// Enable vertex attribute index void rlEnableVertexAttribute(unsigned int index) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) @@ -3288,6 +3305,7 @@ void rlEnableVertexAttribute(unsigned int index) #endif } +// Disable vertex attribute index void rlDisableVertexAttribute(unsigned int index) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) @@ -3295,16 +3313,19 @@ void rlDisableVertexAttribute(unsigned int index) #endif } +// Draw vertex array void rlDrawVertexArray(int offset, int count) { glDrawArrays(GL_TRIANGLES, offset, count); } +// Draw vertex array elements void rlDrawVertexArrayElements(int offset, int count, void *buffer) { glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_SHORT, (unsigned short *)buffer + offset); } +// Draw vertex array instanced void rlDrawVertexArrayInstanced(int offset, int count, int instances) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) @@ -3312,6 +3333,7 @@ void rlDrawVertexArrayInstanced(int offset, int count, int instances) #endif } +// Draw vertex array elements instanced void rlDrawVertexArrayElementsInstanced(int offset, int count, void *buffer, int instances) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) @@ -3320,6 +3342,7 @@ void rlDrawVertexArrayElementsInstanced(int offset, int count, void *buffer, int } #if defined(GRAPHICS_API_OPENGL_11) +// Enable vertex state pointer void rlEnableStatePointer(int vertexAttribType, void *buffer) { if (buffer != NULL) glEnableClientState(vertexAttribType); @@ -3334,12 +3357,14 @@ void rlEnableStatePointer(int vertexAttribType, void *buffer) } } +// Disable vertex state pointer void rlDisableStatePointer(int vertexAttribType) { glDisableClientState(vertexAttribType); } #endif +// Load vertex array object (VAO) unsigned int rlLoadVertexArray(void) { unsigned int vaoId = 0; @@ -3352,6 +3377,7 @@ unsigned int rlLoadVertexArray(void) return vaoId; } +// Set vertex attribute void rlSetVertexAttribute(unsigned int index, int compSize, int type, bool normalized, int stride, void *pointer) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) @@ -3359,6 +3385,7 @@ void rlSetVertexAttribute(unsigned int index, int compSize, int type, bool norma #endif } +// Set vertex attribute divisor void rlSetVertexAttributeDivisor(unsigned int index, int divisor) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) @@ -3366,6 +3393,7 @@ void rlSetVertexAttributeDivisor(unsigned int index, int divisor) #endif } +// Unload vertex array object (VAO) void rlUnloadVertexArray(unsigned int vaoId) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) @@ -3378,6 +3406,7 @@ void rlUnloadVertexArray(unsigned int vaoId) #endif } +// Unload vertex buffer (VBO) void rlUnloadVertexBuffer(unsigned int vboId) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) From 092435d51c7cbb94105d0b2b34156e0bf28d5980 Mon Sep 17 00:00:00 2001 From: 630Studios Date: Thu, 12 Aug 2021 14:01:40 -0500 Subject: [PATCH 19/23] [Models] Fix for issue #1809 (#1917) * GenMeshTangents Fix * GenMeshTangents Fix - Comment Update * GenMeshTangents Fix - Comment Update final * Code Style Changes * Code Style Changes Final * Code Style Changes Final 2 * GenMeshTangents better handling for issue #1876 * GenMeshTangents better handling for issue #1876 * GenMeshTangents: Better fix for issue #1876 * vboId location fix * rlUpdateVertexBuffer - bufferId is an unsigned int * Fix for issue#1809 - Obj with more materials then mesh caused crash * Fix for issue#1809 - Formatting Update --- src/models.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/models.c b/src/models.c index 329d8d4a8..fd7daee6f 100644 --- a/src/models.c +++ b/src/models.c @@ -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; // TODO: REVIEW!!! + model.meshCount = materialCount; // Init model materials array if (materialCount > 0) @@ -3389,7 +3389,7 @@ static Model LoadOBJ(const char *fileName) model.meshMaterial = (int *)RL_CALLOC(model.meshCount, sizeof(int)); // Count the faces for each material - int *matFaces = RL_CALLOC(meshCount, sizeof(int)); + int *matFaces = RL_CALLOC(materialCount, sizeof(int)); for (unsigned int mi = 0; mi < meshCount; mi++) { @@ -3400,7 +3400,6 @@ static Model LoadOBJ(const char *fileName) matFaces[idx]++; } } - //-------------------------------------- // Create the material meshes From 760cfd361e055326cf459812855d8dd83129c132 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sun, 15 Aug 2021 12:52:12 +0200 Subject: [PATCH 20/23] 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 21/23] 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 22/23] 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 23/23] 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)