From 8b714e9dd9fb7ddeb13f21a13d61bd77eed2e2a9 Mon Sep 17 00:00:00 2001 From: lnc3l0t Date: Tue, 6 Aug 2024 18:28:33 +0200 Subject: [PATCH 001/208] [build.zig] check if wayland-scanner is installed (#4217) #4150 introduced a default value for linux_display_backend, which makes X11-only systems fail to build. --- src/build.zig | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/build.zig b/src/build.zig index 2c9519a0e..65379c03b 100644 --- a/src/build.zig +++ b/src/build.zig @@ -155,6 +155,13 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std. } if (options.linux_display_backend == .Wayland or options.linux_display_backend == .Both) { + _ = b.findProgram(&.{"wayland-scanner"}, &.{}) catch { + std.log.err( + \\ Wayland may not be installed on the system. + \\ You can switch to X11 in your `build.zig` by changing `Options.linux_display_backend` + , .{}); + @panic("No Wayland"); + }; raylib.defineCMacro("_GLFW_WAYLAND", null); raylib.linkSystemLibrary("wayland-client"); raylib.linkSystemLibrary("wayland-cursor"); From 4b84b5563e53d6ef2c37795bc91f7088313c8d9e Mon Sep 17 00:00:00 2001 From: Anthony Carbajal <5776225+CrackedPixel@users.noreply.github.com> Date: Tue, 6 Aug 2024 11:29:10 -0500 Subject: [PATCH 002/208] Update audio mixed processor (#4214) * updated audio mixed processor * remove float cast, better parenthesis --- examples/audio/audio_mixed_processor.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/audio/audio_mixed_processor.c b/examples/audio/audio_mixed_processor.c index fd970dd19..2df381b26 100644 --- a/examples/audio/audio_mixed_processor.c +++ b/examples/audio/audio_mixed_processor.c @@ -97,7 +97,7 @@ int main(void) DrawRectangle(199, 199, 402, 34, LIGHTGRAY); for (int i = 0; i < 400; i++) { - DrawLine(201 + i, 232 - (int)averageVolume[i] * 32, 201 + i, 232, MAROON); + DrawLine(201 + i, 232 - (averageVolume[i] * 32), 201 + i, 232, MAROON); } DrawRectangleLines(199, 199, 402, 34, GRAY); From b44b759b8f646dfd7823978b59d2cf0f700e14a7 Mon Sep 17 00:00:00 2001 From: CDM15y Date: Tue, 6 Aug 2024 17:30:15 +0100 Subject: [PATCH 003/208] [examples][shaders_raymarching] Add `raymarching.fs` for GLSL120 (#4183) * Create raymarching.fs * Update raymarching.fs * Update raymarching.fs * Update raymarching.fs Remove `fragColor` as it is unused Move the license to the top of the code to improve readability. --- .../resources/shaders/glsl120/raymarching.fs | 451 ++++++++++++++++++ 1 file changed, 451 insertions(+) create mode 100644 examples/shaders/resources/shaders/glsl120/raymarching.fs diff --git a/examples/shaders/resources/shaders/glsl120/raymarching.fs b/examples/shaders/resources/shaders/glsl120/raymarching.fs new file mode 100644 index 000000000..d3180ac12 --- /dev/null +++ b/examples/shaders/resources/shaders/glsl120/raymarching.fs @@ -0,0 +1,451 @@ +// The MIT License +// Copyright © 2013 Inigo Quilez +// 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. + +// A list of useful distance function to simple primitives, and an example on how to +// do some interesting boolean operations, repetition and displacement. +// +// More info here: http://www.iquilezles.org/www/articles/distfunctions/distfunctions.htm + +#version 120 + +// Input vertex attributes (from vertex shader) +varying vec2 fragTexCoord; + +uniform vec3 viewEye; +uniform vec3 viewCenter; +uniform float runTime; +uniform vec2 resolution; + +// The MIT License +// Copyright © 2013 Inigo Quilez +// 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. + +// A list of useful distance function to simple primitives, and an example on how to +// do some interesting boolean operations, repetition and displacement. +// +// More info here: http://www.iquilezles.org/www/articles/distfunctions/distfunctions.htm + +#define AA 1 // make this 1 if your machine is too slow + +//------------------------------------------------------------------ + +float sdPlane( vec3 p ) +{ + return p.y; +} + +float sdSphere( vec3 p, float s ) +{ + return length(p)-s; +} + +float sdBox( vec3 p, vec3 b ) +{ + vec3 d = abs(p) - b; + return min(max(d.x,max(d.y,d.z)),0.0) + length(max(d,0.0)); +} + +float sdEllipsoid( in vec3 p, in vec3 r ) +{ + return (length( p/r ) - 1.0) * min(min(r.x,r.y),r.z); +} + +float udRoundBox( vec3 p, vec3 b, float r ) +{ + return length(max(abs(p)-b,0.0))-r; +} + +float sdTorus( vec3 p, vec2 t ) +{ + return length( vec2(length(p.xz)-t.x,p.y) )-t.y; +} + +float sdHexPrism( vec3 p, vec2 h ) +{ + vec3 q = abs(p); +#if 0 + return max(q.z-h.y,max((q.x*0.866025+q.y*0.5),q.y)-h.x); +#else + float d1 = q.z-h.y; + float d2 = max((q.x*0.866025+q.y*0.5),q.y)-h.x; + return length(max(vec2(d1,d2),0.0)) + min(max(d1,d2), 0.); +#endif +} + +float sdCapsule( vec3 p, vec3 a, vec3 b, float r ) +{ + vec3 pa = p-a, ba = b-a; + float h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 ); + return length( pa - ba*h ) - r; +} + +float sdEquilateralTriangle( in vec2 p ) +{ + const float k = sqrt(3.0); + p.x = abs(p.x) - 1.0; + p.y = p.y + 1.0/k; + if( p.x + k*p.y > 0.0 ) p = vec2( p.x - k*p.y, -k*p.x - p.y )/2.0; + p.x += 2.0 - 2.0*clamp( (p.x+2.0)/2.0, 0.0, 1.0 ); + return -length(p)*sign(p.y); +} + +float sdTriPrism( vec3 p, vec2 h ) +{ + vec3 q = abs(p); + float d1 = q.z-h.y; +#if 1 + // distance bound + float d2 = max(q.x*0.866025+p.y*0.5,-p.y)-h.x*0.5; +#else + // correct distance + h.x *= 0.866025; + float d2 = sdEquilateralTriangle(p.xy/h.x)*h.x; +#endif + return length(max(vec2(d1,d2),0.0)) + min(max(d1,d2), 0.); +} + +float sdCylinder( vec3 p, vec2 h ) +{ + vec2 d = abs(vec2(length(p.xz),p.y)) - h; + return min(max(d.x,d.y),0.0) + length(max(d,0.0)); +} + +float sdCone( in vec3 p, in vec3 c ) +{ + vec2 q = vec2( length(p.xz), p.y ); + float d1 = -q.y-c.z; + float d2 = max( dot(q,c.xy), q.y); + return length(max(vec2(d1,d2),0.0)) + min(max(d1,d2), 0.); +} + +float sdConeSection( in vec3 p, in float h, in float r1, in float r2 ) +{ + float d1 = -p.y - h; + float q = p.y - h; + float si = 0.5*(r1-r2)/h; + float d2 = max( sqrt( dot(p.xz,p.xz)*(1.0-si*si)) + q*si - r2, q ); + return length(max(vec2(d1,d2),0.0)) + min(max(d1,d2), 0.); +} + +float sdPryamid4(vec3 p, vec3 h ) // h = { cos a, sin a, height } +{ + // Tetrahedron = Octahedron - Cube + float box = sdBox( p - vec3(0,-2.0*h.z,0), vec3(2.0*h.z) ); + + float d = 0.0; + d = max( d, abs( dot(p, vec3( -h.x, h.y, 0 )) )); + d = max( d, abs( dot(p, vec3( h.x, h.y, 0 )) )); + d = max( d, abs( dot(p, vec3( 0, h.y, h.x )) )); + d = max( d, abs( dot(p, vec3( 0, h.y,-h.x )) )); + float octa = d - h.z; + return max(-box,octa); // Subtraction + } + +float length2( vec2 p ) +{ + return sqrt( p.x*p.x + p.y*p.y ); +} + +float length6( vec2 p ) +{ + p = p*p*p; p = p*p; + return pow( p.x + p.y, 1.0/6.0 ); +} + +float length8( vec2 p ) +{ + p = p*p; p = p*p; p = p*p; + return pow( p.x + p.y, 1.0/8.0 ); +} + +float sdTorus82( vec3 p, vec2 t ) +{ + vec2 q = vec2(length2(p.xz)-t.x,p.y); + return length8(q)-t.y; +} + +float sdTorus88( vec3 p, vec2 t ) +{ + vec2 q = vec2(length8(p.xz)-t.x,p.y); + return length8(q)-t.y; +} + +float sdCylinder6( vec3 p, vec2 h ) +{ + return max( length6(p.xz)-h.x, abs(p.y)-h.y ); +} + +//------------------------------------------------------------------ + +float opS( float d1, float d2 ) +{ + return max(-d2,d1); +} + +vec2 opU( vec2 d1, vec2 d2 ) +{ + return (d1.x0.0 ) tmax = min( tmax, tp1 ); + float tp2 = (1.6-ro.y)/rd.y; if( tp2>0.0 ) { if( ro.y>1.6 ) tmin = max( tmin, tp2 ); + else tmax = min( tmax, tp2 ); } +#endif + + float t = tmin; + float m = -1.0; + for( int i=0; i<64; i++ ) + { + float precis = 0.0005*t; + vec2 res = map( ro+rd*t ); + if( res.xtmax ) break; + t += res.x; + m = res.y; + } + + if( t>tmax ) m=-1.0; + return vec2( t, m ); +} + + +float calcSoftshadow( in vec3 ro, in vec3 rd, in float mint, in float tmax ) +{ + float res = 1.0; + float t = mint; + for( int i=0; i<16; i++ ) + { + float h = map( ro + rd*t ).x; + res = min( res, 8.0*h/t ); + t += clamp( h, 0.02, 0.10 ); + if( h<0.001 || t>tmax ) break; + } + return clamp( res, 0.0, 1.0 ); +} + +vec3 calcNormal( in vec3 pos ) +{ + vec2 e = vec2(1.0,-1.0)*0.5773*0.0005; + return normalize( e.xyy*map( pos + e.xyy ).x + + e.yyx*map( pos + e.yyx ).x + + e.yxy*map( pos + e.yxy ).x + + e.xxx*map( pos + e.xxx ).x ); + /* + vec3 eps = vec3( 0.0005, 0.0, 0.0 ); + vec3 nor = vec3( + map(pos+eps.xyy).x - map(pos-eps.xyy).x, + map(pos+eps.yxy).x - map(pos-eps.yxy).x, + map(pos+eps.yyx).x - map(pos-eps.yyx).x ); + return normalize(nor); + */ +} + +float calcAO( in vec3 pos, in vec3 nor ) +{ + float occ = 0.0; + float sca = 1.0; + for( int i=0; i<5; i++ ) + { + float hr = 0.01 + 0.12*float(i)/4.0; + vec3 aopos = nor * hr + pos; + float dd = map( aopos ).x; + occ += -(dd-hr)*sca; + sca *= 0.95; + } + return clamp( 1.0 - 3.0*occ, 0.0, 1.0 ); +} + +// http://iquilezles.org/www/articles/checkerfiltering/checkerfiltering.htm +float checkersGradBox( in vec2 p ) +{ + // filter kernel + vec2 w = fwidth(p) + 0.001; + // analytical integral (box filter) + vec2 i = 2.0*(abs(fract((p-0.5*w)*0.5)-0.5)-abs(fract((p+0.5*w)*0.5)-0.5))/w; + // xor pattern + return 0.5 - 0.5*i.x*i.y; +} + +vec3 render( in vec3 ro, in vec3 rd ) +{ + vec3 col = vec3(0.7, 0.9, 1.0) +rd.y*0.8; + vec2 res = castRay(ro,rd); + float t = res.x; + float m = res.y; + if( m>-0.5 ) + { + vec3 pos = ro + t*rd; + vec3 nor = calcNormal( pos ); + vec3 ref = reflect( rd, nor ); + + // material + col = 0.45 + 0.35*sin( vec3(0.05,0.08,0.10)*(m-1.0) ); + if( m<1.5 ) + { + + float f = checkersGradBox( 5.0*pos.xz ); + col = 0.3 + f*vec3(0.1); + } + + // lighting + float occ = calcAO( pos, nor ); + vec3 lig = normalize( vec3(cos(-0.4 * runTime), sin(0.7 * runTime), -0.6) ); + vec3 hal = normalize( lig-rd ); + float amb = clamp( 0.5+0.5*nor.y, 0.0, 1.0 ); + float dif = clamp( dot( nor, lig ), 0.0, 1.0 ); + float bac = clamp( dot( nor, normalize(vec3(-lig.x,0.0,-lig.z))), 0.0, 1.0 )*clamp( 1.0-pos.y,0.0,1.0); + float dom = smoothstep( -0.1, 0.1, ref.y ); + float fre = pow( clamp(1.0+dot(nor,rd),0.0,1.0), 2.0 ); + + dif *= calcSoftshadow( pos, lig, 0.02, 2.5 ); + dom *= calcSoftshadow( pos, ref, 0.02, 2.5 ); + + float spe = pow( clamp( dot( nor, hal ), 0.0, 1.0 ),16.0)* + dif * + (0.04 + 0.96*pow( clamp(1.0+dot(hal,rd),0.0,1.0), 5.0 )); + + vec3 lin = vec3(0.0); + lin += 1.30*dif*vec3(1.00,0.80,0.55); + lin += 0.40*amb*vec3(0.40,0.60,1.00)*occ; + lin += 0.50*dom*vec3(0.40,0.60,1.00)*occ; + lin += 0.50*bac*vec3(0.25,0.25,0.25)*occ; + lin += 0.25*fre*vec3(1.00,1.00,1.00)*occ; + col = col*lin; + col += 10.00*spe*vec3(1.00,0.90,0.70); + + col = mix( col, vec3(0.8,0.9,1.0), 1.0-exp( -0.0002*t*t*t ) ); + } + + return vec3( clamp(col,0.0,1.0) ); +} + +mat3 setCamera( in vec3 ro, in vec3 ta, float cr ) +{ + vec3 cw = normalize(ta-ro); + vec3 cp = vec3(sin(cr), cos(cr),0.0); + vec3 cu = normalize( cross(cw,cp) ); + vec3 cv = normalize( cross(cu,cw) ); + return mat3( cu, cv, cw ); +} + +void main() +{ + vec3 tot = vec3(0.0); +#if AA>1 + for( int m=0; m1 + } + tot /= float(AA*AA); +#endif + + gl_FragColor = vec4( tot, 1.0 ); +} From db8b1993632c909f7ad98138e54ebcc09d80e9f6 Mon Sep 17 00:00:00 2001 From: Ray Date: Tue, 6 Aug 2024 18:32:14 +0200 Subject: [PATCH 004/208] Reviewed shader --- .../resources/shaders/glsl100/raymarching.fs | 2 +- .../resources/shaders/glsl120/raymarching.fs | 26 +------------------ 2 files changed, 2 insertions(+), 26 deletions(-) diff --git a/examples/shaders/resources/shaders/glsl100/raymarching.fs b/examples/shaders/resources/shaders/glsl100/raymarching.fs index d58d9d331..a7339d216 100644 --- a/examples/shaders/resources/shaders/glsl100/raymarching.fs +++ b/examples/shaders/resources/shaders/glsl100/raymarching.fs @@ -38,7 +38,7 @@ uniform vec2 resolution; // // More info here: http://www.iquilezles.org/www/articles/distfunctions/distfunctions.htm -#define AA 1 // make this 1 is your machine is too slow +#define AA 1 // make this 1 if your machine is too slow //------------------------------------------------------------------ diff --git a/examples/shaders/resources/shaders/glsl120/raymarching.fs b/examples/shaders/resources/shaders/glsl120/raymarching.fs index d3180ac12..efe4fa108 100644 --- a/examples/shaders/resources/shaders/glsl120/raymarching.fs +++ b/examples/shaders/resources/shaders/glsl120/raymarching.fs @@ -1,32 +1,8 @@ -// The MIT License -// Copyright © 2013 Inigo Quilez -// 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. - -// A list of useful distance function to simple primitives, and an example on how to -// do some interesting boolean operations, repetition and displacement. -// -// More info here: http://www.iquilezles.org/www/articles/distfunctions/distfunctions.htm - #version 120 // Input vertex attributes (from vertex shader) varying vec2 fragTexCoord; +varying vec4 fragColor; uniform vec3 viewEye; uniform vec3 viewCenter; From 5af331d708e0fb4d0a978893aa035e72488cf0e5 Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 7 Aug 2024 01:01:45 +0200 Subject: [PATCH 005/208] REVIEWED #4206 --- src/rlgl.h | 2 +- src/rtextures.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rlgl.h b/src/rlgl.h index 3ff6d7e2a..8ee602644 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -4993,7 +4993,7 @@ static int rlGetPixelDataSize(int width, int height, int format) default: break; } - float bytesPerPixel = (float)bpp/8.0f; + double bytesPerPixel = (double)bpp/8.0; dataSize = (int)(bytesPerPixel*width*height); // Total data size in bytes // Most compressed formats works on 4x4 blocks, diff --git a/src/rtextures.c b/src/rtextures.c index 9359f9219..5fa01c9df 100644 --- a/src/rtextures.c +++ b/src/rtextures.c @@ -5403,7 +5403,7 @@ int GetPixelDataSize(int width, int height, int format) default: break; } - float bytesPerPixel = (float)bpp/8.0f; + double bytesPerPixel = (double)bpp/8.0; dataSize = (int)(bytesPerPixel*width*height); // Total data size in bytes // Most compressed formats works on 4x4 blocks, From 97c02b2425225982da6f3569d50fb490fab53c10 Mon Sep 17 00:00:00 2001 From: kai-z99 <147789796+kai-z99@users.noreply.github.com> Date: Tue, 6 Aug 2024 16:05:53 -0700 Subject: [PATCH 006/208] [examples] Fix some examples (#4211) * Add text * small typo --- examples/shapes/shapes_draw_circle_sector.c | 8 ++++---- examples/shapes/shapes_draw_rectangle_rounded.c | 10 +++++----- examples/shapes/shapes_draw_ring.c | 10 +++++----- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/examples/shapes/shapes_draw_circle_sector.c b/examples/shapes/shapes_draw_circle_sector.c index 30eaaf4bd..cb9ab859b 100644 --- a/examples/shapes/shapes_draw_circle_sector.c +++ b/examples/shapes/shapes_draw_circle_sector.c @@ -63,11 +63,11 @@ int main(void) // Draw GUI controls //------------------------------------------------------------------------------ - GuiSliderBar((Rectangle){ 600, 40, 120, 20}, "StartAngle", NULL, &startAngle, 0, 720); - GuiSliderBar((Rectangle){ 600, 70, 120, 20}, "EndAngle", NULL, &endAngle, 0, 720); + GuiSliderBar((Rectangle){ 600, 40, 120, 20}, "StartAngle", TextFormat("%.2f", startAngle), &startAngle, 0, 720); + GuiSliderBar((Rectangle){ 600, 70, 120, 20}, "EndAngle", TextFormat("%.2f", endAngle), &endAngle, 0, 720); - GuiSliderBar((Rectangle){ 600, 140, 120, 20}, "Radius", NULL, &outerRadius, 0, 200); - GuiSliderBar((Rectangle){ 600, 170, 120, 20}, "Segments", NULL, &segments, 0, 100); + GuiSliderBar((Rectangle){ 600, 140, 120, 20}, "Radius", TextFormat("%.2f", outerRadius), &outerRadius, 0, 200); + GuiSliderBar((Rectangle){ 600, 170, 120, 20}, "Segments", TextFormat("%.2f", segments), &segments, 0, 100); //------------------------------------------------------------------------------ minSegments = truncf(ceilf((endAngle - startAngle) / 90)); diff --git a/examples/shapes/shapes_draw_rectangle_rounded.c b/examples/shapes/shapes_draw_rectangle_rounded.c index 19280ed00..58991884c 100644 --- a/examples/shapes/shapes_draw_rectangle_rounded.c +++ b/examples/shapes/shapes_draw_rectangle_rounded.c @@ -66,11 +66,11 @@ int main(void) // Draw GUI controls //------------------------------------------------------------------------------ - GuiSliderBar((Rectangle){ 640, 40, 105, 20 }, "Width", NULL, &width, 0, (float)GetScreenWidth() - 300); - GuiSliderBar((Rectangle){ 640, 70, 105, 20 }, "Height", NULL, &height, 0, (float)GetScreenHeight() - 50); - GuiSliderBar((Rectangle){ 640, 140, 105, 20 }, "Roundness", NULL, &roundness, 0.0f, 1.0f); - GuiSliderBar((Rectangle){ 640, 170, 105, 20 }, "Thickness", NULL, &lineThick, 0, 20); - GuiSliderBar((Rectangle){ 640, 240, 105, 20}, "Segments", NULL, &segments, 0, 60); + GuiSliderBar((Rectangle){ 640, 40, 105, 20 }, "Width", TextFormat("%.2f", width), &width, 0, (float)GetScreenWidth() - 300); + GuiSliderBar((Rectangle){ 640, 70, 105, 20 }, "Height", TextFormat("%.2f", height), &height, 0, (float)GetScreenHeight() - 50); + GuiSliderBar((Rectangle){ 640, 140, 105, 20 }, "Roundness", TextFormat("%.2f", roundness), &roundness, 0.0f, 1.0f); + GuiSliderBar((Rectangle){ 640, 170, 105, 20 }, "Thickness", TextFormat("%.2f", lineThick), &lineThick, 0, 20); + GuiSliderBar((Rectangle){ 640, 240, 105, 20}, "Segments", TextFormat("%.2f", segments), &segments, 0, 60); GuiCheckBox((Rectangle){ 640, 320, 20, 20 }, "DrawRoundedRect", &drawRoundedRect); GuiCheckBox((Rectangle){ 640, 350, 20, 20 }, "DrawRoundedLines", &drawRoundedLines); diff --git a/examples/shapes/shapes_draw_ring.c b/examples/shapes/shapes_draw_ring.c index 60c95a4c0..8bccdf729 100644 --- a/examples/shapes/shapes_draw_ring.c +++ b/examples/shapes/shapes_draw_ring.c @@ -69,13 +69,13 @@ int main(void) // Draw GUI controls //------------------------------------------------------------------------------ - GuiSliderBar((Rectangle){ 600, 40, 120, 20 }, "StartAngle", NULL, &startAngle, -450, 450); - GuiSliderBar((Rectangle){ 600, 70, 120, 20 }, "EndAngle", NULL, &endAngle, -450, 450); + GuiSliderBar((Rectangle){ 600, 40, 120, 20 }, "StartAngle", TextFormat("%.2f", startAngle), &startAngle, -450, 450); + GuiSliderBar((Rectangle){ 600, 70, 120, 20 }, "EndAngle", TextFormat("%.2f", endAngle), &endAngle, -450, 450); - GuiSliderBar((Rectangle){ 600, 140, 120, 20 }, "InnerRadius", NULL, &innerRadius, 0, 100); - GuiSliderBar((Rectangle){ 600, 170, 120, 20 }, "OuterRadius", NULL, &outerRadius, 0, 200); + GuiSliderBar((Rectangle){ 600, 140, 120, 20 }, "InnerRadius", TextFormat("%.2f", innerRadius), &innerRadius, 0, 100); + GuiSliderBar((Rectangle){ 600, 170, 120, 20 }, "OuterRadius", TextFormat("%.2f", outerRadius), &outerRadius, 0, 200); - GuiSliderBar((Rectangle){ 600, 240, 120, 20 }, "Segments", NULL, &segments, 0, 100); + GuiSliderBar((Rectangle){ 600, 240, 120, 20 }, "Segments", TextFormat("%.2f", segments), &segments, 0, 100); GuiCheckBox((Rectangle){ 600, 320, 20, 20 }, "Draw Ring", &drawRing); GuiCheckBox((Rectangle){ 600, 350, 20, 20 }, "Draw RingLines", &drawRingLines); From cae0946764a7ef81e92decd5ae279a48ff22fd04 Mon Sep 17 00:00:00 2001 From: freakmangd <53349189+freakmangd@users.noreply.github.com> Date: Fri, 9 Aug 2024 02:53:29 -0400 Subject: [PATCH 007/208] Fix build.zig and use zig fmt (#4242) + `std.mem.split` is deprecated, `splitScalar` seems like the intended choice here + zig files should be formatted according to `zig fmt` --- src/build.zig | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/build.zig b/src/build.zig index 65379c03b..4e112d78f 100644 --- a/src/build.zig +++ b/src/build.zig @@ -59,15 +59,15 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std. const content = try std.fs.cwd().readFileAlloc(b.allocator, file, std.math.maxInt(usize)); defer b.allocator.free(content); - var lines = std.mem.split(u8, content, "\n"); + var lines = std.mem.splitScalar(u8, content, '\n'); while (lines.next()) |line| { if (!std.mem.containsAtLeast(u8, line, 1, "SUPPORT")) continue; if (std.mem.startsWith(u8, line, "//")) continue; - var flag = std.mem.trimLeft(u8, line, " \t"); // Trim whitespace - flag = flag["#define ".len - 1 ..]; // Remove #define - flag = std.mem.trimLeft(u8, flag, " \t"); // Trim whitespace - flag = flag[0..std.mem.indexOf(u8, flag, " ").?]; // Flag is only one word, so capture till space + var flag = std.mem.trimLeft(u8, line, " \t"); // Trim whitespace + flag = flag["#define ".len - 1 ..]; // Remove #define + flag = std.mem.trimLeft(u8, flag, " \t"); // Trim whitespace + flag = flag[0..std.mem.indexOf(u8, flag, " ").?]; // Flag is only one word, so capture till space flag = try std.fmt.allocPrint(b.allocator, "-D{s}", .{flag}); // Prepend with -D // If user specifies the flag skip it @@ -149,9 +149,8 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std. raylib.addLibraryPath(.{ .cwd_relative = "/usr/lib" }); raylib.addIncludePath(.{ .cwd_relative = "/usr/include" }); if (options.linux_display_backend == .X11 or options.linux_display_backend == .Both) { - - raylib.defineCMacro("_GLFW_X11", null); - raylib.linkSystemLibrary("X11"); + raylib.defineCMacro("_GLFW_X11", null); + raylib.linkSystemLibrary("X11"); } if (options.linux_display_backend == .Wayland or options.linux_display_backend == .Both) { From 9ef678d90ae3973113eace62425508fe267bed5d Mon Sep 17 00:00:00 2001 From: Jeffery Myers Date: Thu, 8 Aug 2024 23:54:22 -0700 Subject: [PATCH 008/208] Fix warnings (#4239) * Update raylib_api.* by CI * Fix typecast warnings --------- Co-authored-by: github-actions[bot] --- examples/audio/audio_mixed_processor.c | 2 +- src/rcore.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/audio/audio_mixed_processor.c b/examples/audio/audio_mixed_processor.c index 2df381b26..df46edc4e 100644 --- a/examples/audio/audio_mixed_processor.c +++ b/examples/audio/audio_mixed_processor.c @@ -97,7 +97,7 @@ int main(void) DrawRectangle(199, 199, 402, 34, LIGHTGRAY); for (int i = 0; i < 400; i++) { - DrawLine(201 + i, 232 - (averageVolume[i] * 32), 201 + i, 232, MAROON); + DrawLine(201 + i, 232 - (int)(averageVolume[i] * 32), 201 + i, 232, MAROON); } DrawRectangleLines(199, 199, 402, 34, GRAY); diff --git a/src/rcore.c b/src/rcore.c index b4bc19f34..93ae4f3bb 100644 --- a/src/rcore.c +++ b/src/rcore.c @@ -2955,7 +2955,7 @@ float GetGamepadAxisMovement(int gamepad, int axis) float value = (axis == GAMEPAD_AXIS_LEFT_TRIGGER || axis == GAMEPAD_AXIS_RIGHT_TRIGGER)? -1.0f : 0.0f; if ((gamepad < MAX_GAMEPADS) && CORE.Input.Gamepad.ready[gamepad] && (axis < MAX_GAMEPAD_AXIS)) { - float movement = value < 0.0f ? CORE.Input.Gamepad.axisState[gamepad][axis] : fabs(CORE.Input.Gamepad.axisState[gamepad][axis]); + float movement = value < 0.0f ? CORE.Input.Gamepad.axisState[gamepad][axis] : fabsf(CORE.Input.Gamepad.axisState[gamepad][axis]); // 0.1f = GAMEPAD_AXIS_MINIMUM_DRIFT/DELTA if (movement > value + 0.1f) value = CORE.Input.Gamepad.axisState[gamepad][axis]; From 5233b80fb73c557c6836153c4db525c1ffe6c36f Mon Sep 17 00:00:00 2001 From: Anthony Carbajal <5776225+CrackedPixel@users.noreply.github.com> Date: Fri, 9 Aug 2024 01:55:16 -0500 Subject: [PATCH 009/208] update raygui (#4238) --- examples/shapes/raygui.h | 670 +++++++++++++++++++++++++-------------- 1 file changed, 434 insertions(+), 236 deletions(-) diff --git a/examples/shapes/raygui.h b/examples/shapes/raygui.h index 623115fce..16e01a28f 100644 --- a/examples/shapes/raygui.h +++ b/examples/shapes/raygui.h @@ -1,6 +1,6 @@ /******************************************************************************************* * -* raygui v4.0 - A simple and easy-to-use immediate-mode gui library +* raygui v4.5-dev - A simple and easy-to-use immediate-mode gui library * * DESCRIPTION: * raygui is a tools-dev-focused immediate-mode-gui library based on raylib but also @@ -26,7 +26,7 @@ * NOTES: * - WARNING: GuiLoadStyle() and GuiLoadStyle{Custom}() functions, allocate memory for * font atlas recs and glyphs, freeing that memory is (usually) up to the user, -* no unload function is explicitly provided... but note that GuiLoadStyleDefaulf() unloads +* no unload function is explicitly provided... but note that GuiLoadStyleDefault() unloads * by default any previously loaded font (texture, recs, glyphs). * - Global UI alpha (guiAlpha) is applied inside GuiDrawRectangle() and GuiDrawText() functions * @@ -141,6 +141,24 @@ * Draw text bounds rectangles for debug * * VERSIONS HISTORY: +* 4.5-dev (Sep-2024) Current dev version... +* ADDED: guiControlExclusiveMode and guiControlExclusiveRec for exclusive modes +* ADDED: GuiValueBoxFloat() +* ADDED: GuiDropdonwBox() properties: DROPDOWN_ARROW_HIDDEN, DROPDOWN_ROLL_UP +* ADDED: GuiListView() property: LIST_ITEMS_BORDER_WIDTH +* ADDED: Multiple new icons +* REVIEWED: GuiTabBar(), close tab with mouse middle button +* REVIEWED: GuiScrollPanel(), scroll speed proportional to content +* REVIEWED: GuiDropdownBox(), support roll up and hidden arrow +* REVIEWED: GuiTextBox(), cursor position initialization +* REVIEWED: GuiSliderPro(), control value change check +* REVIEWED: GuiGrid(), simplified implementation +* REVIEWED: GuiIconText(), increase buffer size and reviewed padding +* REVIEWED: GuiDrawText(), improved wrap mode drawing +* REVIEWED: GuiScrollBar(), minor tweaks +* REVIEWED: Functions descriptions, removed wrong return value reference +* REDESIGNED: GuiColorPanel(), improved HSV <-> RGBA convertion +* * 4.0 (12-Sep-2023) ADDED: GuiToggleSlider() * ADDED: GuiColorPickerHSV() and GuiColorPanelHSV() * ADDED: Multiple new icons, mostly compiler related @@ -314,9 +332,9 @@ #define RAYGUI_H #define RAYGUI_VERSION_MAJOR 4 -#define RAYGUI_VERSION_MINOR 0 +#define RAYGUI_VERSION_MINOR 5 #define RAYGUI_VERSION_PATCH 0 -#define RAYGUI_VERSION "4.0" +#define RAYGUI_VERSION "4.5-dev" #if !defined(RAYGUI_STANDALONE) #include "raylib.h" @@ -441,7 +459,6 @@ } Font; #endif - // Style property // NOTE: Used when exporting style as code for convenience typedef struct GuiStyleProp { @@ -546,7 +563,6 @@ typedef enum { // TEXT_SIZE, TEXT_SPACING, TEXT_LINE_SPACING, TEXT_ALIGNMENT_VERTICAL, TEXT_WRAP_MODE are global and // should be configured by user as needed while defining the UI layout - // Gui extended properties depend on control // NOTE: RAYGUI_MAX_PROPS_EXTENDED properties (by default, max 8 properties) //---------------------------------------------------------------------------------- @@ -562,12 +578,12 @@ typedef enum { TEXT_ALIGNMENT_VERTICAL, // Text vertical alignment inside text bounds (after border and padding) TEXT_WRAP_MODE // Text wrap-mode inside text bounds //TEXT_DECORATION // Text decoration: 0-None, 1-Underline, 2-Line-through, 3-Overline - //TEXT_DECORATION_THICK // Text decoration line thikness + //TEXT_DECORATION_THICK // Text decoration line thickness } GuiDefaultProperty; // Other possible text properties: // TEXT_WEIGHT // Normal, Italic, Bold -> Requires specific font change -// TEXT_INDENT // Text indentation -> Now using TEXT_PADDING... +// TEXT_INDENT // Text indentation -> Now using TEXT_PADDING... // Label //typedef enum { } GuiLabelProperty; @@ -615,7 +631,9 @@ typedef enum { // DropdownBox typedef enum { ARROW_PADDING = 16, // DropdownBox arrow separation from border and items - DROPDOWN_ITEMS_SPACING // DropdownBox items separation + DROPDOWN_ITEMS_SPACING, // DropdownBox items separation + DROPDOWN_ARROW_HIDDEN, // DropdownBox arrow hidden + DROPDOWN_ROLL_UP // DropdownBox roll up flag (default rolls down) } GuiDropdownBoxProperty; // TextBox/TextBoxMulti/ValueBox/Spinner @@ -635,6 +653,7 @@ typedef enum { LIST_ITEMS_SPACING, // ListView items separation SCROLLBAR_WIDTH, // ListView scrollbar size (usually width) SCROLLBAR_SIDE, // ListView scrollbar side (0-SCROLLBAR_LEFT_SIDE, 1-SCROLLBAR_RIGHT_SIDE) + LIST_ITEMS_BORDER_WIDTH // ListView items border width } GuiListViewProperty; // ColorPicker @@ -698,7 +717,6 @@ RAYGUIAPI char **GuiLoadIcons(const char *fileName, bool loadIconsName); // Load RAYGUIAPI void GuiDrawIcon(int iconId, int posX, int posY, int pixelSize, Color color); // Draw icon using pixel size at specified position #endif - // Controls //---------------------------------------------------------------------------------------------------------- // Container/separator controls, useful for controls organization @@ -710,29 +728,30 @@ RAYGUIAPI int GuiTabBar(Rectangle bounds, const char **text, int count, int *act RAYGUIAPI int GuiScrollPanel(Rectangle bounds, const char *text, Rectangle content, Vector2 *scroll, Rectangle *view); // Scroll Panel control // Basic controls set -RAYGUIAPI int GuiLabel(Rectangle bounds, const char *text); // Label control, shows text +RAYGUIAPI int GuiLabel(Rectangle bounds, const char *text); // Label control RAYGUIAPI int GuiButton(Rectangle bounds, const char *text); // Button control, returns true when clicked -RAYGUIAPI int GuiLabelButton(Rectangle bounds, const char *text); // Label button control, show true when clicked -RAYGUIAPI int GuiToggle(Rectangle bounds, const char *text, bool *active); // Toggle Button control, returns true when active -RAYGUIAPI int GuiToggleGroup(Rectangle bounds, const char *text, int *active); // Toggle Group control, returns active toggle index -RAYGUIAPI int GuiToggleSlider(Rectangle bounds, const char *text, int *active); // Toggle Slider control, returns true when clicked +RAYGUIAPI int GuiLabelButton(Rectangle bounds, const char *text); // Label button control, returns true when clicked +RAYGUIAPI int GuiToggle(Rectangle bounds, const char *text, bool *active); // Toggle Button control +RAYGUIAPI int GuiToggleGroup(Rectangle bounds, const char *text, int *active); // Toggle Group control +RAYGUIAPI int GuiToggleSlider(Rectangle bounds, const char *text, int *active); // Toggle Slider control RAYGUIAPI int GuiCheckBox(Rectangle bounds, const char *text, bool *checked); // Check Box control, returns true when active -RAYGUIAPI int GuiComboBox(Rectangle bounds, const char *text, int *active); // Combo Box control, returns selected item index +RAYGUIAPI int GuiComboBox(Rectangle bounds, const char *text, int *active); // Combo Box control -RAYGUIAPI int GuiDropdownBox(Rectangle bounds, const char *text, int *active, bool editMode); // Dropdown Box control, returns selected item -RAYGUIAPI int GuiSpinner(Rectangle bounds, const char *text, int *value, int minValue, int maxValue, bool editMode); // Spinner control, returns selected value +RAYGUIAPI int GuiDropdownBox(Rectangle bounds, const char *text, int *active, bool editMode); // Dropdown Box control +RAYGUIAPI int GuiSpinner(Rectangle bounds, const char *text, int *value, int minValue, int maxValue, bool editMode); // Spinner control RAYGUIAPI int GuiValueBox(Rectangle bounds, const char *text, int *value, int minValue, int maxValue, bool editMode); // Value Box control, updates input text with numbers +RAYGUIAPI int GuiValueBoxFloat(Rectangle bounds, const char *text, char *textValue, float *value, bool editMode); // Value box control for float values RAYGUIAPI int GuiTextBox(Rectangle bounds, char *text, int textSize, bool editMode); // Text Box control, updates input text -RAYGUIAPI int GuiSlider(Rectangle bounds, const char *textLeft, const char *textRight, float *value, float minValue, float maxValue); // Slider control, returns selected value -RAYGUIAPI int GuiSliderBar(Rectangle bounds, const char *textLeft, const char *textRight, float *value, float minValue, float maxValue); // Slider Bar control, returns selected value -RAYGUIAPI int GuiProgressBar(Rectangle bounds, const char *textLeft, const char *textRight, float *value, float minValue, float maxValue); // Progress Bar control, shows current progress value +RAYGUIAPI int GuiSlider(Rectangle bounds, const char *textLeft, const char *textRight, float *value, float minValue, float maxValue); // Slider control +RAYGUIAPI int GuiSliderBar(Rectangle bounds, const char *textLeft, const char *textRight, float *value, float minValue, float maxValue); // Slider Bar control +RAYGUIAPI int GuiProgressBar(Rectangle bounds, const char *textLeft, const char *textRight, float *value, float minValue, float maxValue); // Progress Bar control RAYGUIAPI int GuiStatusBar(Rectangle bounds, const char *text); // Status Bar control, shows info text RAYGUIAPI int GuiDummyRec(Rectangle bounds, const char *text); // Dummy control for placeholders -RAYGUIAPI int GuiGrid(Rectangle bounds, const char *text, float spacing, int subdivs, Vector2 *mouseCell); // Grid control, returns mouse cell position +RAYGUIAPI int GuiGrid(Rectangle bounds, const char *text, float spacing, int subdivs, Vector2 *mouseCell); // Grid control // Advance controls set -RAYGUIAPI int GuiListView(Rectangle bounds, const char *text, int *scrollIndex, int *active); // List View control, returns selected list item index +RAYGUIAPI int GuiListView(Rectangle bounds, const char *text, int *scrollIndex, int *active); // List View control RAYGUIAPI int GuiListViewEx(Rectangle bounds, const char **text, int count, int *scrollIndex, int *active, int *focus); // List View with extended parameters RAYGUIAPI int GuiMessageBox(Rectangle bounds, const char *title, const char *message, const char *buttons); // Message Box control, displays a message RAYGUIAPI int GuiTextInputBox(Rectangle bounds, const char *title, const char *message, const char *buttons, char *text, int textMaxSize, bool *secretViewActive); // Text Input Box control, ask for text, supports secret @@ -741,10 +760,9 @@ RAYGUIAPI int GuiColorPanel(Rectangle bounds, const char *text, Color *color); RAYGUIAPI int GuiColorBarAlpha(Rectangle bounds, const char *text, float *alpha); // Color Bar Alpha control RAYGUIAPI int GuiColorBarHue(Rectangle bounds, const char *text, float *value); // Color Bar Hue control RAYGUIAPI int GuiColorPickerHSV(Rectangle bounds, const char *text, Vector3 *colorHsv); // Color Picker control that avoids conversion to RGB on each call (multiple color controls) -RAYGUIAPI int GuiColorPanelHSV(Rectangle bounds, const char *text, Vector3 *colorHsv); // Color Panel control that returns HSV color value, used by GuiColorPickerHSV() +RAYGUIAPI int GuiColorPanelHSV(Rectangle bounds, const char *text, Vector3 *colorHsv); // Color Panel control that updates Hue-Saturation-Value color value, used by GuiColorPickerHSV() //---------------------------------------------------------------------------------------------------------- - #if !defined(RAYGUI_NO_ICONS) #if !defined(RAYGUI_CUSTOM_ICONS) @@ -972,14 +990,14 @@ typedef enum { ICON_FOLDER = 217, ICON_FILE = 218, ICON_SAND_TIMER = 219, - ICON_220 = 220, - ICON_221 = 221, - ICON_222 = 222, - ICON_223 = 223, - ICON_224 = 224, - ICON_225 = 225, - ICON_226 = 226, - ICON_227 = 227, + ICON_WARNING = 220, + ICON_HELP_BOX = 221, + ICON_INFO_BOX = 222, + ICON_PRIORITY = 223, + ICON_LAYERS_ISO = 224, + ICON_LAYERS2 = 225, + ICON_MLAYERS = 226, + ICON_MAPS = 227, ICON_228 = 228, ICON_229 = 229, ICON_230 = 230, @@ -1290,14 +1308,14 @@ static unsigned int guiIcons[RAYGUI_ICON_MAX_ICONS*RAYGUI_ICON_DATA_ELEMENTS] = 0x00000000, 0x0042007e, 0x40027fc2, 0x40024002, 0x40024002, 0x40024002, 0x7ffe4002, 0x00000000, // ICON_FOLDER 0x3ff00000, 0x201c2010, 0x20042004, 0x20042004, 0x20042004, 0x20042004, 0x20042004, 0x00003ffc, // ICON_FILE 0x1ff00000, 0x20082008, 0x17d02fe8, 0x05400ba0, 0x09200540, 0x23881010, 0x2fe827c8, 0x00001ff0, // ICON_SAND_TIMER - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_220 - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_221 - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_222 - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_223 - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_224 - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_225 - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_226 - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_227 + 0x01800000, 0x02400240, 0x05a00420, 0x09900990, 0x11881188, 0x21842004, 0x40024182, 0x00003ffc, // ICON_WARNING + 0x7ffe0000, 0x4ff24002, 0x4c324ff2, 0x4f824c02, 0x41824f82, 0x41824002, 0x40024182, 0x00007ffe, // ICON_HELP_BOX + 0x7ffe0000, 0x41824002, 0x40024182, 0x41824182, 0x41824182, 0x41824182, 0x40024182, 0x00007ffe, // ICON_INFO_BOX + 0x01800000, 0x04200240, 0x10080810, 0x7bde2004, 0x0a500a50, 0x08500bd0, 0x08100850, 0x00000ff0, // ICON_PRIORITY + 0x01800000, 0x18180660, 0x80016006, 0x98196006, 0x99996666, 0x19986666, 0x01800660, 0x00000000, // ICON_LAYERS_ISO + 0x07fe0000, 0x1c020402, 0x74021402, 0x54025402, 0x54025402, 0x500857fe, 0x40205ff8, 0x00007fe0, // ICON_LAYERS2 + 0x0ffe0000, 0x3ffa0802, 0x7fea200a, 0x402a402a, 0x422a422a, 0x422e422a, 0x40384e28, 0x00007fe0, // ICON_MLAYERS + 0x0ffe0000, 0x3ffa0802, 0x7fea200a, 0x402a402a, 0x5b2a512a, 0x512e552a, 0x40385128, 0x00007fe0, // ICON_MAPS 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_228 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_229 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_230 @@ -1328,7 +1346,7 @@ static unsigned int guiIcons[RAYGUI_ICON_MAX_ICONS*RAYGUI_ICON_DATA_ELEMENTS] = 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_255 }; -// NOTE: We keep a pointer to the icons array, useful to point to other sets if required +// NOTE: A pointer to current icons array should be defined static unsigned int *guiIconsPtr = guiIcons; #endif // !RAYGUI_NO_ICONS && !RAYGUI_CUSTOM_ICONS @@ -1363,8 +1381,8 @@ static unsigned int guiIconScale = 1; // Gui icon default scale (if ic static bool guiTooltip = false; // Tooltip enabled/disabled static const char *guiTooltipPtr = NULL; // Tooltip string pointer (string provided by user) -static bool guiSliderDragging = false; // Gui slider drag state (no inputs processed except dragged slider) -static Rectangle guiSliderActive = { 0 }; // Gui slider active bounds rectangle, used as an unique identifier +static bool guiControlExclusiveMode = false; // Gui control exclusive mode (no inputs processed except current control) +static Rectangle guiControlExclusiveRec = { 0 }; // Gui control exclusive bounds rectangle, used as an unique identifier static int textBoxCursorIndex = 0; // Cursor index, shared by all GuiTextBox*() //static int blinkCursorFrameCounter = 0; // Frame counter for cursor blinking @@ -1450,6 +1468,7 @@ static bool CheckCollisionPointRec(Vector2 point, Rectangle rec); // Check if static const char *TextFormat(const char *text, ...); // Formatting of text with variables to 'embed' static const char **TextSplit(const char *text, char delimiter, int *count); // Split text into multiple strings static int TextToInteger(const char *text); // Get integer value from text +static float TextToFloat(const char *text); // Get float value from text static int GetCodepointNext(const char *text, int *codepointSize); // Get next codepoint in a UTF-8 encoded text static const char *CodepointToUTF8(int codepoint, int *byteSize); // Encode codepoint into UTF-8 text (char array size returned as parameter) @@ -1744,6 +1763,9 @@ int GuiTabBar(Rectangle bounds, const char **text, int count, int *active) if (toggle) *active = i; } + // Close tab with middle mouse button pressed + if (CheckCollisionPointRec(GetMousePosition(), tabBounds) && IsMouseButtonPressed(MOUSE_MIDDLE_BUTTON)) result = i; + GuiSetStyle(TOGGLE, TEXT_PADDING, textPadding); GuiSetStyle(TOGGLE, TEXT_ALIGNMENT, textAlignment); @@ -1775,10 +1797,10 @@ int GuiScrollPanel(Rectangle bounds, const char *text, Rectangle content, Vector { #define RAYGUI_MIN_SCROLLBAR_WIDTH 40 #define RAYGUI_MIN_SCROLLBAR_HEIGHT 40 + #define RAYGUI_MIN_MOUSE_WHEEL_SPEED 20 int result = 0; GuiState state = guiState; - float mouseWheelSpeed = 20.0f; // Default movement speed with mouse wheel Rectangle temp = { 0 }; if (view == NULL) view = &temp; @@ -1820,17 +1842,8 @@ int GuiScrollPanel(Rectangle bounds, const char *text, Rectangle content, Vector }; // Make sure scroll bars have a minimum width/height - // NOTE: If content >>> bounds, size could be very small or even 0 - if (horizontalScrollBar.width < RAYGUI_MIN_SCROLLBAR_WIDTH) - { - horizontalScrollBar.width = RAYGUI_MIN_SCROLLBAR_WIDTH; - mouseWheelSpeed = 30.0f; // TODO: Calculate speed increment based on content.height vs bounds.height - } - if (verticalScrollBar.height < RAYGUI_MIN_SCROLLBAR_HEIGHT) - { - verticalScrollBar.height = RAYGUI_MIN_SCROLLBAR_HEIGHT; - mouseWheelSpeed = 30.0f; // TODO: Calculate speed increment based on content.width vs bounds.width - } + if (horizontalScrollBar.width < RAYGUI_MIN_SCROLLBAR_WIDTH) horizontalScrollBar.width = RAYGUI_MIN_SCROLLBAR_WIDTH; + if (verticalScrollBar.height < RAYGUI_MIN_SCROLLBAR_HEIGHT) verticalScrollBar.height = RAYGUI_MIN_SCROLLBAR_HEIGHT; // Calculate view area (area without the scrollbars) *view = (GuiGetStyle(LISTVIEW, SCROLLBAR_SIDE) == SCROLLBAR_LEFT_SIDE)? @@ -1873,9 +1886,14 @@ int GuiScrollPanel(Rectangle bounds, const char *text, Rectangle content, Vector #endif float wheelMove = GetMouseWheelMove(); + // Set scrolling speed with mouse wheel based on ratio between bounds and content + Vector2 mouseWheelSpeed = { content.width/bounds.width, content.height/bounds.height }; + if (mouseWheelSpeed.x < RAYGUI_MIN_MOUSE_WHEEL_SPEED) mouseWheelSpeed.x = RAYGUI_MIN_MOUSE_WHEEL_SPEED; + if (mouseWheelSpeed.y < RAYGUI_MIN_MOUSE_WHEEL_SPEED) mouseWheelSpeed.y = RAYGUI_MIN_MOUSE_WHEEL_SPEED; + // Horizontal and vertical scrolling with mouse wheel - if (hasHorizontalScrollBar && (IsKeyDown(KEY_LEFT_CONTROL) || IsKeyDown(KEY_LEFT_SHIFT))) scrollPos.x += wheelMove*mouseWheelSpeed; - else scrollPos.y += wheelMove*mouseWheelSpeed; // Vertical scroll + if (hasHorizontalScrollBar && (IsKeyDown(KEY_LEFT_CONTROL) || IsKeyDown(KEY_LEFT_SHIFT))) scrollPos.x += wheelMove*mouseWheelSpeed.x; + else scrollPos.y += wheelMove*mouseWheelSpeed.y; // Vertical scroll } } @@ -1921,7 +1939,7 @@ int GuiScrollPanel(Rectangle bounds, const char *text, Rectangle content, Vector } // Draw scrollbar lines depending on current state - GuiDrawRectangle(bounds, GuiGetStyle(DEFAULT, BORDER_WIDTH), GetColor(GuiGetStyle(LISTVIEW, BORDER + (state*3))), BLANK); + GuiDrawRectangle(bounds, GuiGetStyle(LISTVIEW, BORDER_WIDTH), GetColor(GuiGetStyle(LISTVIEW, BORDER + (state*3))), BLANK); // Set scrollbar slider size back to the way it was before GuiSetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE, slider); @@ -1959,7 +1977,7 @@ int GuiButton(Rectangle bounds, const char *text) // Update control //-------------------------------------------------------------------- - if ((state != STATE_DISABLED) && !guiLocked && !guiSliderDragging) + if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode) { Vector2 mousePoint = GetMousePosition(); @@ -1997,7 +2015,7 @@ int GuiLabelButton(Rectangle bounds, const char *text) // Update control //-------------------------------------------------------------------- - if ((state != STATE_DISABLED) && !guiLocked && !guiSliderDragging) + if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode) { Vector2 mousePoint = GetMousePosition(); @@ -2020,7 +2038,7 @@ int GuiLabelButton(Rectangle bounds, const char *text) return pressed; } -// Toggle Button control, returns true when active +// Toggle Button control int GuiToggle(Rectangle bounds, const char *text, bool *active) { int result = 0; @@ -2031,7 +2049,7 @@ int GuiToggle(Rectangle bounds, const char *text, bool *active) // Update control //-------------------------------------------------------------------- - if ((state != STATE_DISABLED) && !guiLocked && !guiSliderDragging) + if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode) { Vector2 mousePoint = GetMousePosition(); @@ -2068,7 +2086,7 @@ int GuiToggle(Rectangle bounds, const char *text, bool *active) return result; } -// Toggle Group control, returns toggled button codepointIndex +// Toggle Group control int GuiToggleGroup(Rectangle bounds, const char *text, int *active) { #if !defined(RAYGUI_TOGGLEGROUP_MAX_ITEMS) @@ -2117,7 +2135,7 @@ int GuiToggleGroup(Rectangle bounds, const char *text, int *active) return result; } -// Toggle Slider control extended, returns true when clicked +// Toggle Slider control extended int GuiToggleSlider(Rectangle bounds, const char *text, int *active) { int result = 0; @@ -2211,7 +2229,7 @@ int GuiCheckBox(Rectangle bounds, const char *text, bool *checked) // Update control //-------------------------------------------------------------------- - if ((state != STATE_DISABLED) && !guiLocked && !guiSliderDragging) + if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode) { Vector2 mousePoint = GetMousePosition(); @@ -2256,7 +2274,7 @@ int GuiCheckBox(Rectangle bounds, const char *text, bool *checked) return result; } -// Combo Box control, returns selected item codepointIndex +// Combo Box control int GuiComboBox(Rectangle bounds, const char *text, int *active) { int result = 0; @@ -2279,7 +2297,7 @@ int GuiComboBox(Rectangle bounds, const char *text, int *active) // Update control //-------------------------------------------------------------------- - if ((state != STATE_DISABLED) && !guiLocked && (itemCount > 1) && !guiSliderDragging) + if ((state != STATE_DISABLED) && !guiLocked && (itemCount > 1) && !guiControlExclusiveMode) { Vector2 mousePoint = GetMousePosition(); @@ -2327,21 +2345,28 @@ int GuiDropdownBox(Rectangle bounds, const char *text, int *active, bool editMod int result = 0; GuiState state = guiState; + int temp = 0; + if (active == NULL) active = &temp; + int itemSelected = *active; int itemFocused = -1; + int direction = 0; // Dropdown box open direction: down (default) + if (GuiGetStyle(DROPDOWNBOX, DROPDOWN_ROLL_UP) == 1) direction = 1; // Up + // Get substrings items from text (items pointers, lengths and count) int itemCount = 0; const char **items = GuiTextSplit(text, ';', &itemCount, NULL); Rectangle boundsOpen = bounds; boundsOpen.height = (itemCount + 1)*(bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING)); + if (direction == 1) boundsOpen.y -= itemCount*(bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING)) + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING); Rectangle itemBounds = bounds; // Update control //-------------------------------------------------------------------- - if ((state != STATE_DISABLED) && (editMode || !guiLocked) && (itemCount > 1) && !guiSliderDragging) + if ((state != STATE_DISABLED) && (editMode || !guiLocked) && (itemCount > 1) && !guiControlExclusiveMode) { Vector2 mousePoint = GetMousePosition(); @@ -2362,7 +2387,8 @@ int GuiDropdownBox(Rectangle bounds, const char *text, int *active, bool editMod for (int i = 0; i < itemCount; i++) { // Update item rectangle y position for next item - itemBounds.y += (bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING)); + if (direction == 0) itemBounds.y += (bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING)); + else itemBounds.y -= (bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING)); if (CheckCollisionPointRec(mousePoint, itemBounds)) { @@ -2406,7 +2432,8 @@ int GuiDropdownBox(Rectangle bounds, const char *text, int *active, bool editMod for (int i = 0; i < itemCount; i++) { // Update item rectangle y position for next item - itemBounds.y += (bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING)); + if (direction == 0) itemBounds.y += (bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING)); + else itemBounds.y -= (bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING)); if (i == itemSelected) { @@ -2422,14 +2449,17 @@ int GuiDropdownBox(Rectangle bounds, const char *text, int *active, bool editMod } } - // Draw arrows (using icon if available) + if (!GuiGetStyle(DROPDOWNBOX, DROPDOWN_ARROW_HIDDEN)) + { + // Draw arrows (using icon if available) #if defined(RAYGUI_NO_ICONS) - GuiDrawText("v", RAYGUI_CLITERAL(Rectangle){ bounds.x + bounds.width - GuiGetStyle(DROPDOWNBOX, ARROW_PADDING), bounds.y + bounds.height/2 - 2, 10, 10 }, - TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(DROPDOWNBOX, TEXT + (state*3)))); + GuiDrawText("v", RAYGUI_CLITERAL(Rectangle){ bounds.x + bounds.width - GuiGetStyle(DROPDOWNBOX, ARROW_PADDING), bounds.y + bounds.height/2 - 2, 10, 10 }, + TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(DROPDOWNBOX, TEXT + (state*3)))); #else - GuiDrawText("#120#", RAYGUI_CLITERAL(Rectangle){ bounds.x + bounds.width - GuiGetStyle(DROPDOWNBOX, ARROW_PADDING), bounds.y + bounds.height/2 - 6, 10, 10 }, - TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(DROPDOWNBOX, TEXT + (state*3)))); // ICON_ARROW_DOWN_FILL + GuiDrawText(direction? "#121#" : "#120#", RAYGUI_CLITERAL(Rectangle){ bounds.x + bounds.width - GuiGetStyle(DROPDOWNBOX, ARROW_PADDING), bounds.y + bounds.height/2 - 6, 10, 10 }, + TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(DROPDOWNBOX, TEXT + (state*3)))); // ICON_ARROW_DOWN_FILL #endif + } //-------------------------------------------------------------------- *active = itemSelected; @@ -2440,7 +2470,7 @@ int GuiDropdownBox(Rectangle bounds, const char *text, int *active, bool editMod // Text Box control // NOTE: Returns true on ENTER pressed (useful for data validation) -int GuiTextBox(Rectangle bounds, char *text, int bufferSize, bool editMode) +int GuiTextBox(Rectangle bounds, char *text, int textSize, bool editMode) { #if !defined(RAYGUI_TEXTBOX_AUTO_CURSOR_COOLDOWN) #define RAYGUI_TEXTBOX_AUTO_CURSOR_COOLDOWN 40 // Frames to wait for autocursor movement @@ -2456,7 +2486,10 @@ int GuiTextBox(Rectangle bounds, char *text, int bufferSize, bool editMode) int wrapMode = GuiGetStyle(DEFAULT, TEXT_WRAP_MODE); Rectangle textBounds = GetTextBounds(TEXTBOX, bounds); - int textWidth = GetTextWidth(text) - GetTextWidth(text + textBoxCursorIndex); + int textLength = (int)strlen(text); // Get current text length + int thisCursorIndex = textBoxCursorIndex; + if (thisCursorIndex > textLength) thisCursorIndex = textLength; + int textWidth = GetTextWidth(text) - GetTextWidth(text + thisCursorIndex); int textIndexOffset = 0; // Text index offset to start drawing in the box // Cursor rectangle @@ -2496,7 +2529,7 @@ int GuiTextBox(Rectangle bounds, char *text, int bufferSize, bool editMode) if ((state != STATE_DISABLED) && // Control not disabled !GuiGetStyle(TEXTBOX, TEXT_READONLY) && // TextBox not on read-only mode !guiLocked && // Gui not locked - !guiSliderDragging && // No gui slider on dragging + !guiControlExclusiveMode && // No gui slider on dragging (wrapMode == TEXT_WRAP_NONE)) // No wrap mode { Vector2 mousePosition = GetMousePosition(); @@ -2505,6 +2538,8 @@ int GuiTextBox(Rectangle bounds, char *text, int bufferSize, bool editMode) { state = STATE_PRESSED; + if (textBoxCursorIndex > textLength) textBoxCursorIndex = textLength; + // If text does not fit in the textbox and current cursor position is out of bounds, // we add an index offset to text for drawing only what requires depending on cursor while (textWidth >= textBounds.width) @@ -2517,19 +2552,16 @@ int GuiTextBox(Rectangle bounds, char *text, int bufferSize, bool editMode) textWidth = GetTextWidth(text + textIndexOffset) - GetTextWidth(text + textBoxCursorIndex); } - int textLength = (int)strlen(text); // Get current text length int codepoint = GetCharPressed(); // Get Unicode codepoint if (multiline && IsKeyPressed(KEY_ENTER)) codepoint = (int)'\n'; - if (textBoxCursorIndex > textLength) textBoxCursorIndex = textLength; - // Encode codepoint as UTF-8 int codepointSize = 0; const char *charEncoded = CodepointToUTF8(codepoint, &codepointSize); // Add codepoint to text, at current cursor position // NOTE: Make sure we do not overflow buffer size - if (((multiline && (codepoint == (int)'\n')) || (codepoint >= 32)) && ((textLength + codepointSize) < bufferSize)) + if (((multiline && (codepoint == (int)'\n')) || (codepoint >= 32)) && ((textLength + codepointSize) < textSize)) { // Move forward data from cursor position for (int i = (textLength + codepointSize); i > textBoxCursorIndex; i--) text[i] = text[i - codepointSize]; @@ -2564,6 +2596,7 @@ int GuiTextBox(Rectangle bounds, char *text, int bufferSize, bool editMode) for (int i = textBoxCursorIndex; i < textLength; i++) text[i] = text[i + nextCodepointSize]; textLength -= codepointSize; + if (textBoxCursorIndex > textLength) textBoxCursorIndex = textLength; // Make sure text last character is EOL text[textLength] = '\0'; @@ -2583,6 +2616,8 @@ int GuiTextBox(Rectangle bounds, char *text, int bufferSize, bool editMode) // Move backward text from cursor position for (int i = (textBoxCursorIndex - prevCodepointSize); i < textLength; i++) text[i] = text[i + prevCodepointSize]; + // TODO Check: >= cursor+codepointsize and <= length-codepointsize + // Prevent cursor index from decrementing past 0 if (textBoxCursorIndex > 0) { @@ -2653,7 +2688,7 @@ int GuiTextBox(Rectangle bounds, char *text, int bufferSize, bool editMode) if (GetMousePosition().x >= (textBounds.x + textEndWidth - glyphWidth/2)) { mouseCursor.x = textBounds.x + textEndWidth; - mouseCursorIndex = (int)strlen(text); + mouseCursorIndex = textLength; } // Place cursor at required index on mouse click @@ -2685,7 +2720,7 @@ int GuiTextBox(Rectangle bounds, char *text, int bufferSize, bool editMode) if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) { - textBoxCursorIndex = (int)strlen(text); // GLOBAL: Place cursor index to the end of current text + textBoxCursorIndex = textLength; // GLOBAL: Place cursor index to the end of current text result = 1; } } @@ -2727,7 +2762,7 @@ int GuiTextBox(Rectangle bounds, char *text, int bufferSize, bool editMode) /* // Text Box control with multiple lines and word-wrap // NOTE: This text-box is readonly, no editing supported by default -bool GuiTextBoxMulti(Rectangle bounds, char *text, int bufferSize, bool editMode) +bool GuiTextBoxMulti(Rectangle bounds, char *text, int textSize, bool editMode) { bool pressed = false; @@ -2736,7 +2771,7 @@ bool GuiTextBoxMulti(Rectangle bounds, char *text, int bufferSize, bool editMode GuiSetStyle(DEFAULT, TEXT_ALIGNMENT_VERTICAL, TEXT_ALIGN_TOP); // TODO: Implement methods to calculate cursor position properly - pressed = GuiTextBox(bounds, text, bufferSize, editMode); + pressed = GuiTextBox(bounds, text, textSize, editMode); GuiSetStyle(DEFAULT, TEXT_ALIGNMENT_VERTICAL, TEXT_ALIGN_MIDDLE); GuiSetStyle(DEFAULT, TEXT_WRAP_MODE, TEXT_WRAP_NONE); @@ -2771,7 +2806,7 @@ int GuiSpinner(Rectangle bounds, const char *text, int *value, int minValue, int // Update control //-------------------------------------------------------------------- - if ((state != STATE_DISABLED) && !guiLocked && !guiSliderDragging) + if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode) { Vector2 mousePoint = GetMousePosition(); @@ -2846,7 +2881,7 @@ int GuiValueBox(Rectangle bounds, const char *text, int *value, int minValue, in // Update control //-------------------------------------------------------------------- - if ((state != STATE_DISABLED) && !guiLocked && !guiSliderDragging) + if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode) { Vector2 mousePoint = GetMousePosition(); @@ -2890,7 +2925,13 @@ int GuiValueBox(Rectangle bounds, const char *text, int *value, int minValue, in //if (*value > maxValue) *value = maxValue; //else if (*value < minValue) *value = minValue; - if (IsKeyPressed(KEY_ENTER) || (!CheckCollisionPointRec(mousePoint, bounds) && IsMouseButtonPressed(MOUSE_LEFT_BUTTON))) result = 1; + if ((IsKeyPressed(KEY_ENTER) || IsKeyPressed(KEY_KP_ENTER)) || (!CheckCollisionPointRec(mousePoint, bounds) && IsMouseButtonPressed(MOUSE_LEFT_BUTTON))) + { + if (*value > maxValue) *value = maxValue; + else if (*value < minValue) *value = minValue; + + result = 1; + } } else { @@ -2930,55 +2971,152 @@ int GuiValueBox(Rectangle bounds, const char *text, int *value, int minValue, in return result; } +// Floating point Value Box control, updates input val_str with numbers +// NOTE: Requires static variables: frameCounter +int GuiValueBoxFloat(Rectangle bounds, const char *text, char *textValue, float *value, bool editMode) +{ + #if !defined(RAYGUI_VALUEBOX_MAX_CHARS) + #define RAYGUI_VALUEBOX_MAX_CHARS 32 + #endif + + int result = 0; + GuiState state = guiState; + + //char textValue[RAYGUI_VALUEBOX_MAX_CHARS + 1] = "\0"; + //sprintf(textValue, "%2.2f", *value); + + Rectangle textBounds = {0}; + if (text != NULL) + { + textBounds.width = (float)GetTextWidth(text) + 2; + textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE); + textBounds.x = bounds.x + bounds.width + GuiGetStyle(VALUEBOX, TEXT_PADDING); + textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2; + if (GuiGetStyle(VALUEBOX, TEXT_ALIGNMENT) == TEXT_ALIGN_LEFT) textBounds.x = bounds.x - textBounds.width - GuiGetStyle(VALUEBOX, TEXT_PADDING); + } + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode) + { + Vector2 mousePoint = GetMousePosition(); + + bool valueHasChanged = false; + + if (editMode) + { + state = STATE_PRESSED; + + int keyCount = (int)strlen(textValue); + + // Only allow keys in range [48..57] + if (keyCount < RAYGUI_VALUEBOX_MAX_CHARS) + { + if (GetTextWidth(textValue) < bounds.width) + { + int key = GetCharPressed(); + if (((key >= 48) && (key <= 57)) || + (key == '.') || + ((keyCount == 0) && (key == '+')) || // NOTE: Sign can only be in first position + ((keyCount == 0) && (key == '-'))) + { + textValue[keyCount] = (char)key; + keyCount++; + + valueHasChanged = true; + } + } + } + + // Pressed backspace + if (IsKeyPressed(KEY_BACKSPACE)) + { + if (keyCount > 0) + { + keyCount--; + textValue[keyCount] = '\0'; + valueHasChanged = true; + } + } + + if (valueHasChanged) *value = TextToFloat(textValue); + + if ((IsKeyPressed(KEY_ENTER) || IsKeyPressed(KEY_KP_ENTER)) || (!CheckCollisionPointRec(mousePoint, bounds) && IsMouseButtonPressed(MOUSE_LEFT_BUTTON))) result = 1; + } + else + { + if (CheckCollisionPointRec(mousePoint, bounds)) + { + state = STATE_FOCUSED; + if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) result = 1; + } + } + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + Color baseColor = BLANK; + if (state == STATE_PRESSED) baseColor = GetColor(GuiGetStyle(VALUEBOX, BASE_COLOR_PRESSED)); + else if (state == STATE_DISABLED) baseColor = GetColor(GuiGetStyle(VALUEBOX, BASE_COLOR_DISABLED)); + + GuiDrawRectangle(bounds, GuiGetStyle(VALUEBOX, BORDER_WIDTH), GetColor(GuiGetStyle(VALUEBOX, BORDER + (state*3))), baseColor); + GuiDrawText(textValue, GetTextBounds(VALUEBOX, bounds), TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(VALUEBOX, TEXT + (state*3)))); + + // Draw cursor + if (editMode) + { + // NOTE: ValueBox internal text is always centered + Rectangle cursor = {bounds.x + GetTextWidth(textValue)/2 + bounds.width/2 + 1, + bounds.y + 2*GuiGetStyle(VALUEBOX, BORDER_WIDTH), 4, + bounds.height - 4*GuiGetStyle(VALUEBOX, BORDER_WIDTH)}; + GuiDrawRectangle(cursor, 0, BLANK, GetColor(GuiGetStyle(VALUEBOX, BORDER_COLOR_PRESSED))); + } + + // Draw text label if provided + GuiDrawText(text, textBounds, + (GuiGetStyle(VALUEBOX, TEXT_ALIGNMENT) == TEXT_ALIGN_RIGHT)? TEXT_ALIGN_LEFT : TEXT_ALIGN_RIGHT, + GetColor(GuiGetStyle(LABEL, TEXT + (state*3)))); + //-------------------------------------------------------------------- + + return result; +} + // Slider control with pro parameters // NOTE: Other GuiSlider*() controls use this one int GuiSliderPro(Rectangle bounds, const char *textLeft, const char *textRight, float *value, float minValue, float maxValue, int sliderWidth) { int result = 0; - float oldValue = *value; GuiState state = guiState; float temp = (maxValue - minValue)/2.0f; if (value == NULL) value = &temp; - - int sliderValue = (int)(((*value - minValue)/(maxValue - minValue))*(bounds.width - 2*GuiGetStyle(SLIDER, BORDER_WIDTH))); + float oldValue = *value; Rectangle slider = { bounds.x, bounds.y + GuiGetStyle(SLIDER, BORDER_WIDTH) + GuiGetStyle(SLIDER, SLIDER_PADDING), 0, bounds.height - 2*GuiGetStyle(SLIDER, BORDER_WIDTH) - 2*GuiGetStyle(SLIDER, SLIDER_PADDING) }; - if (sliderWidth > 0) // Slider - { - slider.x += (sliderValue - sliderWidth/2); - slider.width = (float)sliderWidth; - } - else if (sliderWidth == 0) // SliderBar - { - slider.x += GuiGetStyle(SLIDER, BORDER_WIDTH); - slider.width = (float)sliderValue; - } - // Update control //-------------------------------------------------------------------- if ((state != STATE_DISABLED) && !guiLocked) { Vector2 mousePoint = GetMousePosition(); - if (guiSliderDragging) // Keep dragging outside of bounds + if (guiControlExclusiveMode) // Allows to keep dragging outside of bounds { if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) { - if (CHECK_BOUNDS_ID(bounds, guiSliderActive)) + if (CHECK_BOUNDS_ID(bounds, guiControlExclusiveRec)) { state = STATE_PRESSED; - // Get equivalent value and slider position from mousePosition.x - *value = ((maxValue - minValue)*(mousePoint.x - (float)(bounds.x + sliderWidth/2)))/(float)(bounds.width - sliderWidth) + minValue; + *value = (maxValue - minValue)*((mousePoint.x - bounds.x - sliderWidth/2)/(bounds.width-sliderWidth)) + minValue; } } else { - guiSliderDragging = false; - guiSliderActive = RAYGUI_CLITERAL(Rectangle){ 0, 0, 0, 0 }; + guiControlExclusiveMode = false; + guiControlExclusiveRec = RAYGUI_CLITERAL(Rectangle){ 0, 0, 0, 0 }; } } else if (CheckCollisionPointRec(mousePoint, bounds)) @@ -2986,16 +3124,13 @@ int GuiSliderPro(Rectangle bounds, const char *textLeft, const char *textRight, if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) { state = STATE_PRESSED; - guiSliderDragging = true; - guiSliderActive = bounds; // Store bounds as an identifier when dragging starts + guiControlExclusiveMode = true; + guiControlExclusiveRec = bounds; // Store bounds as an identifier when dragging starts if (!CheckCollisionPointRec(mousePoint, slider)) { // Get equivalent value and slider position from mousePosition.x - *value = ((maxValue - minValue)*(mousePoint.x - (float)(bounds.x + sliderWidth/2)))/(float)(bounds.width - sliderWidth) + minValue; - - if (sliderWidth > 0) slider.x = mousePoint.x - slider.width/2; // Slider - else if (sliderWidth == 0) slider.width = (float)sliderValue; // SliderBar + *value = (maxValue - minValue)*((mousePoint.x - bounds.x - sliderWidth/2)/(bounds.width-sliderWidth)) + minValue; } } else state = STATE_FOCUSED; @@ -3006,17 +3141,22 @@ int GuiSliderPro(Rectangle bounds, const char *textLeft, const char *textRight, } // Control value change check - if(oldValue == *value) result = 0; + if (oldValue == *value) result = 0; else result = 1; - // Bar limits check + // Slider bar limits check + float sliderValue = (((*value - minValue)/(maxValue - minValue))*(bounds.width - sliderWidth - 2*GuiGetStyle(SLIDER, BORDER_WIDTH))); if (sliderWidth > 0) // Slider { + slider.x += sliderValue; + slider.width = (float)sliderWidth; if (slider.x <= (bounds.x + GuiGetStyle(SLIDER, BORDER_WIDTH))) slider.x = bounds.x + GuiGetStyle(SLIDER, BORDER_WIDTH); else if ((slider.x + slider.width) >= (bounds.x + bounds.width)) slider.x = bounds.x + bounds.width - slider.width - GuiGetStyle(SLIDER, BORDER_WIDTH); } else if (sliderWidth == 0) // SliderBar { + slider.x += GuiGetStyle(SLIDER, BORDER_WIDTH); + slider.width = sliderValue; if (slider.width > bounds.width) slider.width = bounds.width - 2*GuiGetStyle(SLIDER, BORDER_WIDTH); } //-------------------------------------------------------------------- @@ -3171,7 +3311,7 @@ int GuiDummyRec(Rectangle bounds, const char *text) // Update control //-------------------------------------------------------------------- - if ((state != STATE_DISABLED) && !guiLocked && !guiSliderDragging) + if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode) { Vector2 mousePoint = GetMousePosition(); @@ -3238,7 +3378,7 @@ int GuiListViewEx(Rectangle bounds, const char **text, int count, int *scrollInd // Update control //-------------------------------------------------------------------- - if ((state != STATE_DISABLED) && !guiLocked && !guiSliderDragging) + if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode) { Vector2 mousePoint = GetMousePosition(); @@ -3291,6 +3431,8 @@ int GuiListViewEx(Rectangle bounds, const char **text, int count, int *scrollInd // Draw visible items for (int i = 0; ((i < visibleItems) && (text != NULL)); i++) { + GuiDrawRectangle(itemBounds, GuiGetStyle(LISTVIEW, LIST_ITEMS_BORDER_WIDTH), GetColor(GuiGetStyle(LISTVIEW, BORDER_COLOR_NORMAL)), BLANK); + if (state == STATE_DISABLED) { if ((startIndex + i) == itemSelected) GuiDrawRectangle(itemBounds, GuiGetStyle(LISTVIEW, BORDER_WIDTH), GetColor(GuiGetStyle(LISTVIEW, BORDER_COLOR_DISABLED)), GetColor(GuiGetStyle(LISTVIEW, BASE_COLOR_DISABLED))); @@ -3353,83 +3495,32 @@ int GuiListViewEx(Rectangle bounds, const char **text, int count, int *scrollInd return result; } -// Color Panel control +// Color Panel control - Color (RGBA) variant. int GuiColorPanel(Rectangle bounds, const char *text, Color *color) { int result = 0; - GuiState state = guiState; - Vector2 pickerSelector = { 0 }; - - const Color colWhite = { 255, 255, 255, 255 }; - const Color colBlack = { 0, 0, 0, 255 }; Vector3 vcolor = { (float)color->r/255.0f, (float)color->g/255.0f, (float)color->b/255.0f }; Vector3 hsv = ConvertRGBtoHSV(vcolor); + Vector3 prevHsv = hsv; // workaround to see if GuiColorPanelHSV modifies the hsv. - pickerSelector.x = bounds.x + (float)hsv.y*bounds.width; // HSV: Saturation - pickerSelector.y = bounds.y + (1.0f - (float)hsv.z)*bounds.height; // HSV: Value + GuiColorPanelHSV(bounds, text, &hsv); - Vector3 maxHue = { hsv.x, 1.0f, 1.0f }; - Vector3 rgbHue = ConvertHSVtoRGB(maxHue); - Color maxHueCol = { (unsigned char)(255.0f*rgbHue.x), - (unsigned char)(255.0f*rgbHue.y), - (unsigned char)(255.0f*rgbHue.z), 255 }; - - // Update control - //-------------------------------------------------------------------- - if ((state != STATE_DISABLED) && !guiLocked && !guiSliderDragging) + // Check if the hsv was changed, only then change the color. + // This is required, because the Color->HSV->Color conversion has precision errors. + // Thus the assignment from HSV to Color should only be made, if the HSV has a new user-entered value. + // Otherwise GuiColorPanel would often modify it's color without user input. + // TODO: GuiColorPanelHSV could return 1 if the slider was dragged, to simplify this check. + if (hsv.x != prevHsv.x || hsv.y != prevHsv.y || hsv.z != prevHsv.z) { - Vector2 mousePoint = GetMousePosition(); + Vector3 rgb = ConvertHSVtoRGB(hsv); - if (CheckCollisionPointRec(mousePoint, bounds)) - { - if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) - { - state = STATE_PRESSED; - pickerSelector = mousePoint; - - // Calculate color from picker - Vector2 colorPick = { pickerSelector.x - bounds.x, pickerSelector.y - bounds.y }; - - colorPick.x /= (float)bounds.width; // Get normalized value on x - colorPick.y /= (float)bounds.height; // Get normalized value on y - - hsv.y = colorPick.x; - hsv.z = 1.0f - colorPick.y; - - Vector3 rgb = ConvertHSVtoRGB(hsv); - - // NOTE: Vector3ToColor() only available on raylib 1.8.1 - *color = RAYGUI_CLITERAL(Color){ (unsigned char)(255.0f*rgb.x), - (unsigned char)(255.0f*rgb.y), - (unsigned char)(255.0f*rgb.z), - (unsigned char)(255.0f*(float)color->a/255.0f) }; - - } - else state = STATE_FOCUSED; - } + // NOTE: Vector3ToColor() only available on raylib 1.8.1 + *color = RAYGUI_CLITERAL(Color){ (unsigned char)(255.0f*rgb.x), + (unsigned char)(255.0f*rgb.y), + (unsigned char)(255.0f*rgb.z), + color->a }; } - //-------------------------------------------------------------------- - - // Draw control - //-------------------------------------------------------------------- - if (state != STATE_DISABLED) - { - DrawRectangleGradientEx(bounds, Fade(colWhite, guiAlpha), Fade(colWhite, guiAlpha), Fade(maxHueCol, guiAlpha), Fade(maxHueCol, guiAlpha)); - DrawRectangleGradientEx(bounds, Fade(colBlack, 0), Fade(colBlack, guiAlpha), Fade(colBlack, guiAlpha), Fade(colBlack, 0)); - - // Draw color picker: selector - Rectangle selector = { pickerSelector.x - GuiGetStyle(COLORPICKER, COLOR_SELECTOR_SIZE)/2, pickerSelector.y - GuiGetStyle(COLORPICKER, COLOR_SELECTOR_SIZE)/2, (float)GuiGetStyle(COLORPICKER, COLOR_SELECTOR_SIZE), (float)GuiGetStyle(COLORPICKER, COLOR_SELECTOR_SIZE) }; - GuiDrawRectangle(selector, 0, BLANK, colWhite); - } - else - { - DrawRectangleGradientEx(bounds, Fade(Fade(GetColor(GuiGetStyle(COLORPICKER, BASE_COLOR_DISABLED)), 0.1f), guiAlpha), Fade(Fade(colBlack, 0.6f), guiAlpha), Fade(Fade(colBlack, 0.6f), guiAlpha), Fade(Fade(GetColor(GuiGetStyle(COLORPICKER, BORDER_COLOR_DISABLED)), 0.6f), guiAlpha)); - } - - GuiDrawRectangle(bounds, GuiGetStyle(COLORPICKER, BORDER_WIDTH), GetColor(GuiGetStyle(COLORPICKER, BORDER + state*3)), BLANK); - //-------------------------------------------------------------------- - return result; } @@ -3451,11 +3542,11 @@ int GuiColorBarAlpha(Rectangle bounds, const char *text, float *alpha) { Vector2 mousePoint = GetMousePosition(); - if (guiSliderDragging) // Keep dragging outside of bounds + if (guiControlExclusiveMode) // Allows to keep dragging outside of bounds { if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) { - if (CHECK_BOUNDS_ID(bounds, guiSliderActive)) + if (CHECK_BOUNDS_ID(bounds, guiControlExclusiveRec)) { state = STATE_PRESSED; @@ -3466,8 +3557,8 @@ int GuiColorBarAlpha(Rectangle bounds, const char *text, float *alpha) } else { - guiSliderDragging = false; - guiSliderActive = RAYGUI_CLITERAL(Rectangle){ 0, 0, 0, 0 }; + guiControlExclusiveMode = false; + guiControlExclusiveRec = RAYGUI_CLITERAL(Rectangle){ 0, 0, 0, 0 }; } } else if (CheckCollisionPointRec(mousePoint, bounds) || CheckCollisionPointRec(mousePoint, selector)) @@ -3475,8 +3566,8 @@ int GuiColorBarAlpha(Rectangle bounds, const char *text, float *alpha) if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) { state = STATE_PRESSED; - guiSliderDragging = true; - guiSliderActive = bounds; // Store bounds as an identifier when dragging starts + guiControlExclusiveMode = true; + guiControlExclusiveRec = bounds; // Store bounds as an identifier when dragging starts *alpha = (mousePoint.x - bounds.x)/bounds.width; if (*alpha <= 0.0f) *alpha = 0.0f; @@ -3537,11 +3628,11 @@ int GuiColorBarHue(Rectangle bounds, const char *text, float *hue) { Vector2 mousePoint = GetMousePosition(); - if (guiSliderDragging) // Keep dragging outside of bounds + if (guiControlExclusiveMode) // Allows to keep dragging outside of bounds { if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) { - if (CHECK_BOUNDS_ID(bounds, guiSliderActive)) + if (CHECK_BOUNDS_ID(bounds, guiControlExclusiveRec)) { state = STATE_PRESSED; @@ -3552,8 +3643,8 @@ int GuiColorBarHue(Rectangle bounds, const char *text, float *hue) } else { - guiSliderDragging = false; - guiSliderActive = RAYGUI_CLITERAL(Rectangle){ 0, 0, 0, 0 }; + guiControlExclusiveMode = false; + guiControlExclusiveRec = RAYGUI_CLITERAL(Rectangle){ 0, 0, 0, 0 }; } } else if (CheckCollisionPointRec(mousePoint, bounds) || CheckCollisionPointRec(mousePoint, selector)) @@ -3561,8 +3652,8 @@ int GuiColorBarHue(Rectangle bounds, const char *text, float *hue) if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) { state = STATE_PRESSED; - guiSliderDragging = true; - guiSliderActive = bounds; // Store bounds as an identifier when dragging starts + guiControlExclusiveMode = true; + guiControlExclusiveRec = bounds; // Store bounds as an identifier when dragging starts *hue = (mousePoint.y - bounds.y)*360/bounds.height; if (*hue <= 0.0f) *hue = 0.0f; @@ -3615,6 +3706,7 @@ int GuiColorBarHue(Rectangle bounds, const char *text, float *hue) // float GuiColorBarAlpha(Rectangle bounds, float alpha) // float GuiColorBarHue(Rectangle bounds, float value) // NOTE: bounds define GuiColorPanel() size +// NOTE: this picker converts RGB to HSV, which can cause the Hue control to jump. If you have this problem, consider using the HSV variant instead int GuiColorPicker(Rectangle bounds, const char *text, Color *color) { int result = 0; @@ -3627,6 +3719,7 @@ int GuiColorPicker(Rectangle bounds, const char *text, Color *color) Rectangle boundsHue = { (float)bounds.x + bounds.width + GuiGetStyle(COLORPICKER, HUEBAR_PADDING), (float)bounds.y, (float)GuiGetStyle(COLORPICKER, HUEBAR_WIDTH), (float)bounds.height }; //Rectangle boundsAlpha = { bounds.x, bounds.y + bounds.height + GuiGetStyle(COLORPICKER, BARS_PADDING), bounds.width, GuiGetStyle(COLORPICKER, BARS_THICK) }; + // NOTE: this conversion can cause low hue-resolution, if the r, g and b value are very similar, which causes the hue bar to shift around when only the GuiColorPanel is used. Vector3 hsv = ConvertRGBtoHSV(RAYGUI_CLITERAL(Vector3){ (*color).r/255.0f, (*color).g/255.0f, (*color).b/255.0f }); GuiColorBarHue(boundsHue, NULL, &hsv.x); @@ -3668,8 +3761,7 @@ int GuiColorPickerHSV(Rectangle bounds, const char *text, Vector3 *colorHsv) return result; } -// Color Panel control, returns HSV color value in *colorHsv. -// Used by GuiColorPickerHSV() +// Color Panel control - HSV variant int GuiColorPanelHSV(Rectangle bounds, const char *text, Vector3 *colorHsv) { int result = 0; @@ -3690,15 +3782,47 @@ int GuiColorPanelHSV(Rectangle bounds, const char *text, Vector3 *colorHsv) // Update control //-------------------------------------------------------------------- - if ((state != STATE_DISABLED) && !guiLocked && !guiSliderDragging) + if ((state != STATE_DISABLED) && !guiLocked) { Vector2 mousePoint = GetMousePosition(); - if (CheckCollisionPointRec(mousePoint, bounds)) + if (guiControlExclusiveMode) // Allows to keep dragging outside of bounds + { + if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) + { + if (CHECK_BOUNDS_ID(bounds, guiControlExclusiveRec)) + { + pickerSelector = mousePoint; + + if (pickerSelector.x < bounds.x) pickerSelector.x = bounds.x; + if (pickerSelector.x > bounds.x + bounds.width) pickerSelector.x = bounds.x + bounds.width; + if (pickerSelector.y < bounds.y) pickerSelector.y = bounds.y; + if (pickerSelector.y > bounds.y + bounds.height) pickerSelector.y = bounds.y + bounds.height; + + // Calculate color from picker + Vector2 colorPick = { pickerSelector.x - bounds.x, pickerSelector.y - bounds.y }; + + colorPick.x /= (float)bounds.width; // Get normalized value on x + colorPick.y /= (float)bounds.height; // Get normalized value on y + + colorHsv->y = colorPick.x; + colorHsv->z = 1.0f - colorPick.y; + + } + } + else + { + guiControlExclusiveMode = false; + guiControlExclusiveRec = RAYGUI_CLITERAL(Rectangle){ 0, 0, 0, 0 }; + } + } + else if (CheckCollisionPointRec(mousePoint, bounds)) { if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) { state = STATE_PRESSED; + guiControlExclusiveMode = true; + guiControlExclusiveRec = bounds; pickerSelector = mousePoint; // Calculate color from picker @@ -3760,9 +3884,9 @@ int GuiMessageBox(Rectangle bounds, const char *title, const char *message, cons int textWidth = GetTextWidth(message) + 2; Rectangle textBounds = { 0 }; - textBounds.x = bounds.x + bounds.width/2 - textWidth/2; + textBounds.x = bounds.x + RAYGUI_MESSAGEBOX_BUTTON_PADDING; textBounds.y = bounds.y + RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT + RAYGUI_MESSAGEBOX_BUTTON_PADDING; - textBounds.width = (float)textWidth; + textBounds.width = bounds.width - RAYGUI_MESSAGEBOX_BUTTON_PADDING*2; textBounds.height = bounds.height - RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT - 3*RAYGUI_MESSAGEBOX_BUTTON_PADDING - RAYGUI_MESSAGEBOX_BUTTON_HEIGHT; // Draw control @@ -3905,7 +4029,7 @@ int GuiGrid(Rectangle bounds, const char *text, float spacing, int subdivs, Vect // Update control //-------------------------------------------------------------------- - if ((state != STATE_DISABLED) && !guiLocked && !guiSliderDragging) + if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode) { if (CheckCollisionPointRec(mousePoint, bounds)) { @@ -3925,14 +4049,14 @@ int GuiGrid(Rectangle bounds, const char *text, float spacing, int subdivs, Vect // Draw vertical grid lines for (int i = 0; i < linesV; i++) { - Rectangle lineV = { bounds.x + spacing*i/subdivs, bounds.y, 1, bounds.height }; + Rectangle lineV = { bounds.x + spacing*i/subdivs, bounds.y, 1, bounds.height + 1 }; GuiDrawRectangle(lineV, 0, BLANK, ((i%subdivs) == 0)? GuiFade(GetColor(color), RAYGUI_GRID_ALPHA*4) : GuiFade(GetColor(color), RAYGUI_GRID_ALPHA)); } // Draw horizontal grid lines for (int i = 0; i < linesH; i++) { - Rectangle lineH = { bounds.x, bounds.y + spacing*i/subdivs, bounds.width, 1 }; + Rectangle lineH = { bounds.x, bounds.y + spacing*i/subdivs, bounds.width + 1, 1 }; GuiDrawRectangle(lineH, 0, BLANK, ((i%subdivs) == 0)? GuiFade(GetColor(color), RAYGUI_GRID_ALPHA*4) : GuiFade(GetColor(color), RAYGUI_GRID_ALPHA)); } } @@ -3954,7 +4078,6 @@ void GuiDisableTooltip(void) { guiTooltip = false; } // Set tooltip string void GuiSetTooltip(const char *tooltip) { guiTooltipPtr = tooltip; } - //---------------------------------------------------------------------------------- // Styles loading functions //---------------------------------------------------------------------------------- @@ -3967,6 +4090,7 @@ void GuiLoadStyle(const char *fileName) #define MAX_LINE_BUFFER_SIZE 256 bool tryBinary = false; + if (!guiStyleLoaded) GuiLoadStyleDefault(); // Try reading the files as text file first FILE *rgsFile = fopen(fileName, "rt"); @@ -4600,7 +4724,7 @@ static int GetTextWidth(const char *text) } } - if (textIconOffset > 0) textSize.x += (RAYGUI_ICON_SIZE - ICON_TEXT_PADDING); + if (textIconOffset > 0) textSize.x += (RAYGUI_ICON_SIZE + ICON_TEXT_PADDING); } return (int)textSize.x; @@ -4773,6 +4897,7 @@ static void GuiDrawText(const char *text, Rectangle textBounds, int alignment, C // Get text position depending on alignment and iconId //--------------------------------------------------------------------------------- Vector2 textBoundsPosition = { textBounds.x, textBounds.y }; + float textBoundsWidthOffset = 0.0f; // NOTE: We get text size after icon has been processed // WARNING: GetTextWidth() also processes text icon to get width! -> Really needed? @@ -4798,6 +4923,8 @@ static void GuiDrawText(const char *text, Rectangle textBounds, int alignment, C default: break; } + if (textSizeX > textBounds.width && (lines[i] != NULL) && (lines[i][0] != '\0')) textBoundsPosition.x = textBounds.x; + switch (alignmentVertical) { // Only valid in case of wordWrap = 0; @@ -4820,7 +4947,8 @@ static void GuiDrawText(const char *text, Rectangle textBounds, int alignment, C { // NOTE: We consider icon height, probably different than text size GuiDrawIcon(iconId, (int)textBoundsPosition.x, (int)(textBounds.y + textBounds.height/2 - RAYGUI_ICON_SIZE*guiIconScale/2 + TEXT_VALIGN_PIXEL_OFFSET(textBounds.height)), guiIconScale, tint); - textBoundsPosition.x += (RAYGUI_ICON_SIZE*guiIconScale + ICON_TEXT_PADDING); + textBoundsPosition.x += (float)(RAYGUI_ICON_SIZE*guiIconScale + ICON_TEXT_PADDING); + textBoundsWidthOffset = (float)(RAYGUI_ICON_SIZE*guiIconScale + ICON_TEXT_PADDING); } #endif // Get size in bytes of text, @@ -4829,9 +4957,15 @@ static void GuiDrawText(const char *text, Rectangle textBounds, int alignment, C for (int c = 0; (lines[i][c] != '\0') && (lines[i][c] != '\n') && (lines[i][c] != '\r'); c++, lineSize++){ } float scaleFactor = (float)GuiGetStyle(DEFAULT, TEXT_SIZE)/guiFont.baseSize; + int lastSpaceIndex = 0; + bool tempWrapCharMode = false; + int textOffsetY = 0; float textOffsetX = 0.0f; float glyphWidth = 0; + + int ellipsisWidth = GetTextWidth("..."); + bool textOverflow = false; for (int c = 0, codepointSize = 0; c < lineSize; c += codepointSize) { int codepoint = GetCodepointNext(&lines[i][c], &codepointSize); @@ -4839,36 +4973,51 @@ static void GuiDrawText(const char *text, Rectangle textBounds, int alignment, C // 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) codepointSize = 1; // TODO: Review not recognized codepoints size + if (codepoint == 0x3f) codepointSize = 1; // TODO: Review not recognized codepoints size - // Wrap mode text measuring to space to validate if it can be drawn or - // a new line is required + // Get glyph width to check if it goes out of bounds + if (guiFont.glyphs[index].advanceX == 0) glyphWidth = ((float)guiFont.recs[index].width*scaleFactor); + else glyphWidth = (float)guiFont.glyphs[index].advanceX*scaleFactor; + + // Wrap mode text measuring, to validate if + // it can be drawn or a new line is required if (wrapMode == TEXT_WRAP_CHAR) { - // Get glyph width to check if it goes out of bounds - if (guiFont.glyphs[index].advanceX == 0) glyphWidth = ((float)guiFont.recs[index].width*scaleFactor); - else glyphWidth = (float)guiFont.glyphs[index].advanceX*scaleFactor; - // Jump to next line if current character reach end of the box limits - if ((textOffsetX + glyphWidth) > textBounds.width) + if ((textOffsetX + glyphWidth) > textBounds.width - textBoundsWidthOffset) { textOffsetX = 0.0f; textOffsetY += GuiGetStyle(DEFAULT, TEXT_LINE_SPACING); + + if (tempWrapCharMode) // Wrap at char level when too long words + { + wrapMode = TEXT_WRAP_WORD; + tempWrapCharMode = false; + } } } else if (wrapMode == TEXT_WRAP_WORD) { + if (codepoint == 32) lastSpaceIndex = c; + // Get width to next space in line int nextSpaceIndex = 0; float nextSpaceWidth = GetNextSpaceWidth(lines[i] + c, &nextSpaceIndex); - if ((textOffsetX + nextSpaceWidth) > textBounds.width) + int nextSpaceIndex2 = 0; + float nextWordSize = GetNextSpaceWidth(lines[i] + lastSpaceIndex + 1, &nextSpaceIndex2); + + if (nextWordSize > textBounds.width - textBoundsWidthOffset) + { + // Considering the case the next word is longer than bounds + tempWrapCharMode = true; + wrapMode = TEXT_WRAP_CHAR; + } + else if ((textOffsetX + nextSpaceWidth) > textBounds.width - textBoundsWidthOffset) { textOffsetX = 0.0f; textOffsetY += GuiGetStyle(DEFAULT, TEXT_LINE_SPACING); } - - // TODO: Consider case: (nextSpaceWidth >= textBounds.width) } if (codepoint == '\n') break; // WARNING: Lines are already processed manually, no need to keep drawing after this codepoint @@ -4881,7 +5030,23 @@ static void GuiDrawText(const char *text, Rectangle textBounds, int alignment, C if (wrapMode == TEXT_WRAP_NONE) { // Draw only required text glyphs fitting the textBounds.width - if (textOffsetX <= (textBounds.width - glyphWidth)) + if (textSizeX > textBounds.width) + { + if (textOffsetX <= (textBounds.width - glyphWidth - textBoundsWidthOffset - ellipsisWidth)) + { + DrawTextCodepoint(guiFont, codepoint, RAYGUI_CLITERAL(Vector2){ textBoundsPosition.x + textOffsetX, textBoundsPosition.y + textOffsetY }, (float)GuiGetStyle(DEFAULT, TEXT_SIZE), GuiFade(tint, guiAlpha)); + } + else if (!textOverflow) + { + textOverflow = true; + + for (int j = 0; j < ellipsisWidth; j += ellipsisWidth/3) + { + DrawTextCodepoint(guiFont, '.', RAYGUI_CLITERAL(Vector2){ textBoundsPosition.x + textOffsetX + j, textBoundsPosition.y + textOffsetY }, (float)GuiGetStyle(DEFAULT, TEXT_SIZE), GuiFade(tint, guiAlpha)); + } + } + } + else { DrawTextCodepoint(guiFont, codepoint, RAYGUI_CLITERAL(Vector2){ textBoundsPosition.x + textOffsetX, textBoundsPosition.y + textOffsetY }, (float)GuiGetStyle(DEFAULT, TEXT_SIZE), GuiFade(tint, guiAlpha)); } @@ -4937,7 +5102,7 @@ static void GuiDrawRectangle(Rectangle rec, int borderWidth, Color borderColor, // Draw tooltip using control bounds static void GuiTooltip(Rectangle controlRec) { - if (!guiLocked && guiTooltip && (guiTooltipPtr != NULL) && !guiSliderDragging) + if (!guiLocked && guiTooltip && (guiTooltipPtr != NULL) && !guiControlExclusiveMode) { Vector2 textSize = MeasureTextEx(GuiGetFont(), guiTooltipPtr, (float)GuiGetStyle(DEFAULT, TEXT_SIZE), (float)GuiGetStyle(DEFAULT, TEXT_SPACING)); @@ -5003,7 +5168,7 @@ static const char **GuiTextSplit(const char *text, char delimiter, int *count, i buffer[i] = '\0'; // Set an end of string at this point counter++; - if (counter == RAYGUI_TEXTSPLIT_MAX_ITEMS) break; + if (counter > RAYGUI_TEXTSPLIT_MAX_ITEMS) break; } } @@ -5163,8 +5328,11 @@ static int GuiScrollBar(Rectangle bounds, int value, int minValue, int maxValue) if (value > maxValue) value = maxValue; if (value < minValue) value = minValue; - const int valueRange = maxValue - minValue; + int valueRange = maxValue - minValue; + if (valueRange <= 0) valueRange = 1; + int sliderSize = GuiGetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE); + if (sliderSize < 1) sliderSize = 1; // TODO: Consider a minimum slider size // Calculate rectangles for all of the components arrowUpLeft = RAYGUI_CLITERAL(Rectangle){ @@ -5205,13 +5373,13 @@ static int GuiScrollBar(Rectangle bounds, int value, int minValue, int maxValue) { Vector2 mousePoint = GetMousePosition(); - if (guiSliderDragging) // Keep dragging outside of bounds + if (guiControlExclusiveMode) // Allows to keep dragging outside of bounds { if (IsMouseButtonDown(MOUSE_LEFT_BUTTON) && !CheckCollisionPointRec(mousePoint, arrowUpLeft) && !CheckCollisionPointRec(mousePoint, arrowDownRight)) { - if (CHECK_BOUNDS_ID(bounds, guiSliderActive)) + if (CHECK_BOUNDS_ID(bounds, guiControlExclusiveRec)) { state = STATE_PRESSED; @@ -5221,8 +5389,8 @@ static int GuiScrollBar(Rectangle bounds, int value, int minValue, int maxValue) } else { - guiSliderDragging = false; - guiSliderActive = RAYGUI_CLITERAL(Rectangle){ 0, 0, 0, 0 }; + guiControlExclusiveMode = false; + guiControlExclusiveRec = RAYGUI_CLITERAL(Rectangle){ 0, 0, 0, 0 }; } } else if (CheckCollisionPointRec(mousePoint, bounds)) @@ -5236,8 +5404,8 @@ static int GuiScrollBar(Rectangle bounds, int value, int minValue, int maxValue) // Handle mouse button down if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) { - guiSliderDragging = true; - guiSliderActive = bounds; // Store bounds as an identifier when dragging starts + guiControlExclusiveMode = true; + guiControlExclusiveRec = bounds; // Store bounds as an identifier when dragging starts // Check arrows click if (CheckCollisionPointRec(mousePoint, arrowUpLeft)) value -= valueRange/GuiGetStyle(SCROLLBAR, SCROLL_SPEED); @@ -5437,6 +5605,37 @@ static int TextToInteger(const char *text) return value*sign; } +// Get float value from text +// NOTE: This function replaces atof() [stdlib.h] +// WARNING: Only '.' character is understood as decimal point +static float TextToFloat(const char *text) +{ + float value = 0.0f; + float sign = 1.0f; + + if ((text[0] == '+') || (text[0] == '-')) + { + if (text[0] == '-') sign = -1.0f; + text++; + } + + int i = 0; + for (; ((text[i] >= '0') && (text[i] <= '9')); i++) value = value*10.0f + (float)(text[i] - '0'); + + if (text[i++] != '.') value *= sign; + else + { + float divisor = 10.0f; + for (; ((text[i] >= '0') && (text[i] <= '9')); i++) + { + value += ((float)(text[i] - '0'))/divisor; + divisor = divisor*10.0f; + } + } + + return value; +} + // Encode codepoint into UTF-8 text (char array size returned as parameter) static const char *CodepointToUTF8(int codepoint, int *byteSize) { @@ -5490,21 +5689,21 @@ static int GetCodepointNext(const char *text, int *codepointSize) if (0xf0 == (0xf8 & ptr[0])) { // 4 byte UTF-8 codepoint - if(((ptr[1] & 0xC0) ^ 0x80) || ((ptr[2] & 0xC0) ^ 0x80) || ((ptr[3] & 0xC0) ^ 0x80)) { return codepoint; } //10xxxxxx checks + if (((ptr[1] & 0xC0) ^ 0x80) || ((ptr[2] & 0xC0) ^ 0x80) || ((ptr[3] & 0xC0) ^ 0x80)) { return codepoint; } //10xxxxxx checks codepoint = ((0x07 & ptr[0]) << 18) | ((0x3f & ptr[1]) << 12) | ((0x3f & ptr[2]) << 6) | (0x3f & ptr[3]); *codepointSize = 4; } else if (0xe0 == (0xf0 & ptr[0])) { // 3 byte UTF-8 codepoint */ - if(((ptr[1] & 0xC0) ^ 0x80) || ((ptr[2] & 0xC0) ^ 0x80)) { return codepoint; } //10xxxxxx checks + if (((ptr[1] & 0xC0) ^ 0x80) || ((ptr[2] & 0xC0) ^ 0x80)) { return codepoint; } //10xxxxxx checks codepoint = ((0x0f & ptr[0]) << 12) | ((0x3f & ptr[1]) << 6) | (0x3f & ptr[2]); *codepointSize = 3; } else if (0xc0 == (0xe0 & ptr[0])) { // 2 byte UTF-8 codepoint - if((ptr[1] & 0xC0) ^ 0x80) { return codepoint; } //10xxxxxx checks + if ((ptr[1] & 0xC0) ^ 0x80) { return codepoint; } //10xxxxxx checks codepoint = ((0x1f & ptr[0]) << 6) | (0x3f & ptr[1]); *codepointSize = 2; } @@ -5515,9 +5714,8 @@ static int GetCodepointNext(const char *text, int *codepointSize) *codepointSize = 1; } - return codepoint; } #endif // RAYGUI_STANDALONE -#endif // RAYGUI_IMPLEMENTATION +#endif // RAYGUI_IMPLEMENTATION \ No newline at end of file From 070c1c9d6357e07672db6e2fc36e37a2a30ee146 Mon Sep 17 00:00:00 2001 From: Anthony Carbajal <5776225+CrackedPixel@users.noreply.github.com> Date: Fri, 9 Aug 2024 02:03:27 -0500 Subject: [PATCH 010/208] update examples missing unloadtexture (#4234) --- examples/models/models_yaw_pitch_roll.c | 1 + examples/shaders/shaders_lightmap.c | 2 ++ examples/shaders/shaders_texture_drawing.c | 1 + examples/shaders/shaders_vertex_displacement.c | 1 + 4 files changed, 5 insertions(+) diff --git a/examples/models/models_yaw_pitch_roll.c b/examples/models/models_yaw_pitch_roll.c index 91a11f73c..5374c035e 100644 --- a/examples/models/models_yaw_pitch_roll.c +++ b/examples/models/models_yaw_pitch_roll.c @@ -114,6 +114,7 @@ int main(void) // De-Initialization //-------------------------------------------------------------------------------------- UnloadModel(model); // Unload model data + UnloadTexture(texture); // Unload texture data CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- diff --git a/examples/shaders/shaders_lightmap.c b/examples/shaders/shaders_lightmap.c index 01b80a6fb..91ed8bfd2 100644 --- a/examples/shaders/shaders_lightmap.c +++ b/examples/shaders/shaders_lightmap.c @@ -164,6 +164,8 @@ int main(void) //-------------------------------------------------------------------------------------- UnloadMesh(mesh); // Unload the mesh UnloadShader(shader); // Unload shader + UnloadTexture(texture); // Unload texture + UnloadTexture(light); // Unload texture CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- diff --git a/examples/shaders/shaders_texture_drawing.c b/examples/shaders/shaders_texture_drawing.c index 52b8967f6..ada44299d 100644 --- a/examples/shaders/shaders_texture_drawing.c +++ b/examples/shaders/shaders_texture_drawing.c @@ -77,6 +77,7 @@ int main(void) // De-Initialization //-------------------------------------------------------------------------------------- UnloadShader(shader); + UnloadTexture(texture); CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- diff --git a/examples/shaders/shaders_vertex_displacement.c b/examples/shaders/shaders_vertex_displacement.c index c211d349f..207a237d0 100644 --- a/examples/shaders/shaders_vertex_displacement.c +++ b/examples/shaders/shaders_vertex_displacement.c @@ -110,6 +110,7 @@ int main(void) //-------------------------------------------------------------------------------------- UnloadShader(shader); UnloadModel(planeModel); + UnloadTexture(perlinNoiseMap); CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- From fe9e371f277f8f906f2b4ed9485437fa68f53058 Mon Sep 17 00:00:00 2001 From: NishiOwO <89888985+NishiOwO@users.noreply.github.com> Date: Fri, 9 Aug 2024 16:04:18 +0900 Subject: [PATCH 011/208] [miniaudio] Fixing miniaudio and Makefile for NetBSD (#4212) * fixing miniaudio * another fix for NetBSD * adding wl-r. should not affect other bsd --- src/Makefile | 4 ++-- src/external/miniaudio.h | 10 ++++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/Makefile b/src/Makefile index c68a03797..4740f1f01 100644 --- a/src/Makefile +++ b/src/Makefile @@ -467,7 +467,7 @@ INCLUDE_PATHS = -I. ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW) INCLUDE_PATHS += -Iexternal/glfw/include ifeq ($(PLATFORM_OS),BSD) - INCLUDE_PATHS += -I/usr/local/include + INCLUDE_PATHS += -I/usr/local/include -I/usr/pkg/include -I/usr/X11R7/include endif endif ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_SDL) @@ -522,7 +522,7 @@ ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW) LDFLAGS += -Wl,-soname,lib$(RAYLIB_LIB_NAME).so.$(RAYLIB_API_VERSION) endif ifeq ($(PLATFORM_OS),BSD) - LDFLAGS += -Wl,-soname,lib$(RAYLIB_LIB_NAME).$(RAYLIB_API_VERSION).so -Lsrc -L/usr/local/lib + LDFLAGS += -Wl,-soname,lib$(RAYLIB_LIB_NAME).$(RAYLIB_API_VERSION).so -Lsrc -L/usr/local/lib -L/usr/pkg/lib -Wl,-R/usr/pkg/lib endif endif ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_SDL) diff --git a/src/external/miniaudio.h b/src/external/miniaudio.h index 787c626ad..ad113337e 100644 --- a/src/external/miniaudio.h +++ b/src/external/miniaudio.h @@ -36078,9 +36078,15 @@ static ma_result ma_context_get_device_info_from_fd__audio4(ma_context* pContext ma_uint32 channels; ma_uint32 sampleRate; +#ifdef __NetBSD__ + if (ioctl(fd, AUDIO_GETFORMAT, &fdInfo) < 0) { + return MA_ERROR; + } +#else if (ioctl(fd, AUDIO_GETINFO, &fdInfo) < 0) { return MA_ERROR; } +#endif if (deviceType == ma_device_type_playback) { channels = fdInfo.play.channels; @@ -36358,7 +36364,11 @@ static ma_result ma_device_init_fd__audio4(ma_device* pDevice, const ma_device_c /* We're using a default device. Get the info from the /dev/audioctl file instead of /dev/audio. */ int fdctl = open(pDefaultDeviceCtlNames[iDefaultDevice], fdFlags, 0); if (fdctl != -1) { +#ifdef __NetBSD__ + fdInfoResult = ioctl(fdctl, AUDIO_GETFORMAT, &fdInfo); +#else fdInfoResult = ioctl(fdctl, AUDIO_GETINFO, &fdInfo); +#endif close(fdctl); } } From 2590a30d04b4aa4d35787052af55fb96bd699c42 Mon Sep 17 00:00:00 2001 From: Maxim Knyazkin <42771130+MaximKn1@users.noreply.github.com> Date: Fri, 9 Aug 2024 10:05:46 +0300 Subject: [PATCH 012/208] [rlgl] Adding warnings in case OpenGL 4.3 is not enabled (#4202) * Adding warnings for OpenGL 4.3 * Removed logging from frequently called functions --- src/rlgl.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/rlgl.h b/src/rlgl.h index 8ee602644..baf89a782 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -4083,6 +4083,8 @@ unsigned int rlCompileShader(const char *shaderCode, int type) //case GL_GEOMETRY_SHADER: #if defined(GRAPHICS_API_OPENGL_43) case GL_COMPUTE_SHADER: TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Failed to compile compute shader code", shader); break; + #else + case GL_COMPUTE_SHADER: TRACELOG(RL_LOG_WARNING, "SHADER: Compute shaders not enabled. Define GRAPHICS_API_OPENGL_43", shader); break; #endif default: break; } @@ -4108,6 +4110,8 @@ unsigned int rlCompileShader(const char *shaderCode, int type) //case GL_GEOMETRY_SHADER: #if defined(GRAPHICS_API_OPENGL_43) case GL_COMPUTE_SHADER: TRACELOG(RL_LOG_INFO, "SHADER: [ID %i] Compute shader compiled successfully", shader); break; + #else + case GL_COMPUTE_SHADER: TRACELOG(RL_LOG_WARNING, "SHADER: Compute shaders not enabled. Define GRAPHICS_API_OPENGL_43", shader); break; #endif default: break; } @@ -4348,6 +4352,8 @@ unsigned int rlLoadComputeShaderProgram(unsigned int shaderId) TRACELOG(RL_LOG_INFO, "SHADER: [ID %i] Compute shader program loaded successfully", program); } +#else + TRACELOG(RL_LOG_WARNING, "SHADER: Compute shaders not enabled. Define GRAPHICS_API_OPENGL_43"); #endif return program; @@ -4372,6 +4378,8 @@ unsigned int rlLoadShaderBuffer(unsigned int size, const void *data, int usageHi glBufferData(GL_SHADER_STORAGE_BUFFER, size, data, usageHint? usageHint : RL_STREAM_COPY); if (data == NULL) glClearBufferData(GL_SHADER_STORAGE_BUFFER, GL_R8UI, GL_RED_INTEGER, GL_UNSIGNED_BYTE, NULL); // Clear buffer data to 0 glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); +#else + TRACELOG(RL_LOG_WARNING, "SSBO: SSBO not enabled. Define GRAPHICS_API_OPENGL_43"); #endif return ssbo; @@ -4382,7 +4390,10 @@ void rlUnloadShaderBuffer(unsigned int ssboId) { #if defined(GRAPHICS_API_OPENGL_43) glDeleteBuffers(1, &ssboId); +#else + TRACELOG(RL_LOG_WARNING, "SSBO: SSBO not enabled. Define GRAPHICS_API_OPENGL_43"); #endif + } // Update SSBO buffer data @@ -4442,6 +4453,8 @@ void rlBindImageTexture(unsigned int id, unsigned int index, int format, bool re rlGetGlTextureFormats(format, &glInternalFormat, &glFormat, &glType); glBindImageTexture(index, id, 0, 0, 0, readonly? GL_READ_ONLY : GL_READ_WRITE, glInternalFormat); +#else + TRACELOG(RL_LOG_WARNING, "TEXTURE: Image texture binding not enabled. Define GRAPHICS_API_OPENGL_43"); #endif } From 243801c2d1592910669ff11bc6e9b45c2e7507d9 Mon Sep 17 00:00:00 2001 From: Anthony Carbajal <5776225+CrackedPixel@users.noreply.github.com> Date: Fri, 9 Aug 2024 02:07:56 -0500 Subject: [PATCH 013/208] update text writing anim (#4230) --- examples/text/text_writing_anim.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/text/text_writing_anim.c b/examples/text/text_writing_anim.c index 1e7cd569f..8e2820fc9 100644 --- a/examples/text/text_writing_anim.c +++ b/examples/text/text_writing_anim.c @@ -52,7 +52,7 @@ int main(void) DrawText(TextSubtext(message, 0, framesCounter/10), 210, 160, 20, MAROON); DrawText("PRESS [ENTER] to RESTART!", 240, 260, 20, LIGHTGRAY); - DrawText("PRESS [SPACE] to SPEED UP!", 239, 300, 20, LIGHTGRAY); + DrawText("HOLD [SPACE] to SPEED UP!", 239, 300, 20, LIGHTGRAY); EndDrawing(); //---------------------------------------------------------------------------------- From 85c6489d811fc7f5de4d379ad10b4bb071bc871c Mon Sep 17 00:00:00 2001 From: Anthony Carbajal <5776225+CrackedPixel@users.noreply.github.com> Date: Fri, 9 Aug 2024 02:12:26 -0500 Subject: [PATCH 014/208] update models box collisions (#4224) --- examples/models/models_box_collisions.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/models/models_box_collisions.c b/examples/models/models_box_collisions.c index 936f65f38..4d98a776a 100644 --- a/examples/models/models_box_collisions.c +++ b/examples/models/models_box_collisions.c @@ -109,7 +109,7 @@ int main(void) EndMode3D(); - DrawText("Move player with cursors to collide", 220, 40, 20, GRAY); + DrawText("Move player with arrow keys to collide", 220, 40, 20, GRAY); DrawFPS(10, 10); From 06aeb214296a9c51660e4695114244d4acfc58b1 Mon Sep 17 00:00:00 2001 From: Anthony Carbajal <5776225+CrackedPixel@users.noreply.github.com> Date: Fri, 9 Aug 2024 02:15:07 -0500 Subject: [PATCH 015/208] update shaders basic pbr (#4225) --- examples/shaders/shaders_basic_pbr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/shaders/shaders_basic_pbr.c b/examples/shaders/shaders_basic_pbr.c index d025ab8a9..c3f2bad88 100644 --- a/examples/shaders/shaders_basic_pbr.c +++ b/examples/shaders/shaders_basic_pbr.c @@ -236,7 +236,7 @@ int main() float emissiveIntensity = 0.01f; SetShaderValue(shader, emissiveIntensityLoc, &emissiveIntensity, SHADER_UNIFORM_FLOAT); - DrawModel(car, (Vector3){ 0.0f, 0.0f, 0.0f }, 0.005f, WHITE); // Draw car model + DrawModel(car, (Vector3){ 0.0f, 0.0f, 0.0f }, 0.25f, WHITE); // Draw car model // Draw spheres to show the lights positions for (int i = 0; i < MAX_LIGHTS; i++) From 3c5bdae7abffeefe90d927572b5ea443ea50411b Mon Sep 17 00:00:00 2001 From: Anthony Carbajal <5776225+CrackedPixel@users.noreply.github.com> Date: Fri, 9 Aug 2024 02:16:05 -0500 Subject: [PATCH 016/208] update shapes bouncing ball (#4226) --- examples/shapes/shapes_bouncing_ball.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/shapes/shapes_bouncing_ball.c b/examples/shapes/shapes_bouncing_ball.c index 7a3068163..df0c37c1c 100644 --- a/examples/shapes/shapes_bouncing_ball.c +++ b/examples/shapes/shapes_bouncing_ball.c @@ -62,7 +62,7 @@ int main(void) ClearBackground(RAYWHITE); DrawCircleV(ballPosition, (float)ballRadius, MAROON); - //DrawText("PRESS SPACE to PAUSE BALL MOVEMENT", 10, GetScreenHeight() - 25, 20, LIGHTGRAY); + DrawText("PRESS SPACE to PAUSE BALL MOVEMENT", 10, GetScreenHeight() - 25, 20, LIGHTGRAY); // On pause, we draw a blinking message if (pause && ((framesCounter/30)%2)) DrawText("PAUSED", 350, 200, 30, GRAY); From e4529ff8f9d2e03f29e5271fa3eea0c603174925 Mon Sep 17 00:00:00 2001 From: Anthony Carbajal <5776225+CrackedPixel@users.noreply.github.com> Date: Fri, 9 Aug 2024 02:18:00 -0500 Subject: [PATCH 017/208] update text input box (#4229) --- examples/text/text_input_box.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/text/text_input_box.c b/examples/text/text_input_box.c index eeb338f1f..c53057711 100644 --- a/examples/text/text_input_box.c +++ b/examples/text/text_input_box.c @@ -35,7 +35,7 @@ int main(void) int framesCounter = 0; - SetTargetFPS(10); // Set our game to run at 10 frames-per-second + SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop From 13491a485a5f29d00f8fe23e796501bec67a7378 Mon Sep 17 00:00:00 2001 From: Maxim Knyazkin <42771130+MaximKn1@users.noreply.github.com> Date: Fri, 9 Aug 2024 20:02:18 +0300 Subject: [PATCH 018/208] Fixed compilation for OpenGL ES (#4243) --- src/rlgl.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rlgl.h b/src/rlgl.h index baf89a782..19c529398 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -4083,7 +4083,7 @@ unsigned int rlCompileShader(const char *shaderCode, int type) //case GL_GEOMETRY_SHADER: #if defined(GRAPHICS_API_OPENGL_43) case GL_COMPUTE_SHADER: TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Failed to compile compute shader code", shader); break; - #else + #elif defined(GRAPHICS_API_OPENGL_33) case GL_COMPUTE_SHADER: TRACELOG(RL_LOG_WARNING, "SHADER: Compute shaders not enabled. Define GRAPHICS_API_OPENGL_43", shader); break; #endif default: break; @@ -4110,7 +4110,7 @@ unsigned int rlCompileShader(const char *shaderCode, int type) //case GL_GEOMETRY_SHADER: #if defined(GRAPHICS_API_OPENGL_43) case GL_COMPUTE_SHADER: TRACELOG(RL_LOG_INFO, "SHADER: [ID %i] Compute shader compiled successfully", shader); break; - #else + #elif defined(GRAPHICS_API_OPENGL_33) case GL_COMPUTE_SHADER: TRACELOG(RL_LOG_WARNING, "SHADER: Compute shaders not enabled. Define GRAPHICS_API_OPENGL_43", shader); break; #endif default: break; From 46cb6af4375da00563c68c6bbe4c24dcdf885b60 Mon Sep 17 00:00:00 2001 From: Asdqwe Date: Fri, 9 Aug 2024 14:03:14 -0300 Subject: [PATCH 019/208] Fix core_input_gamepad_info example so all buttons are displayed within the window (#4241) --- examples/core/core_input_gamepad_info.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/examples/core/core_input_gamepad_info.c b/examples/core/core_input_gamepad_info.c index 66fedda90..096294681 100644 --- a/examples/core/core_input_gamepad_info.c +++ b/examples/core/core_input_gamepad_info.c @@ -47,25 +47,25 @@ int main(void) ClearBackground(RAYWHITE); - for (int i = 0, y = 10; i < 4; i++) // MAX_GAMEPADS = 4 + for (int i = 0, y = 5; i < 4; i++) // MAX_GAMEPADS = 4 { if (IsGamepadAvailable(i)) { - DrawText(TextFormat("Gamepad name: %s", GetGamepadName(i)), 10, y, 20, BLACK); - y += 30; - DrawText(TextFormat("\tAxis count: %d", GetGamepadAxisCount(i)), 10, y, 20, BLACK); - y += 30; + DrawText(TextFormat("Gamepad name: %s", GetGamepadName(i)), 10, y, 10, BLACK); + y += 11; + DrawText(TextFormat("\tAxis count: %d", GetGamepadAxisCount(i)), 10, y, 10, BLACK); + y += 11; for (int axis = 0; axis < GetGamepadAxisCount(i); axis++) { - DrawText(TextFormat("\tAxis %d = %f", axis, GetGamepadAxisMovement(i, axis)), 10, y, 20, BLACK); - y += 30; + DrawText(TextFormat("\tAxis %d = %f", axis, GetGamepadAxisMovement(i, axis)), 10, y, 10, BLACK); + y += 11; } for (int button = 0; button < 32; button++) { - DrawText(TextFormat("\tButton %d = %d", button, IsGamepadButtonDown(i, button)), 10, y, 20, BLACK); - y += 30; + DrawText(TextFormat("\tButton %d = %d", button, IsGamepadButtonDown(i, button)), 10, y, 10, BLACK); + y += 11; } } } @@ -80,4 +80,4 @@ int main(void) //-------------------------------------------------------------------------------------- CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- -} \ No newline at end of file +} From 418b8780533e6d7822aefcd1a1dd3cb6cca95fa5 Mon Sep 17 00:00:00 2001 From: Anthony Carbajal <5776225+CrackedPixel@users.noreply.github.com> Date: Sat, 10 Aug 2024 13:07:23 -0500 Subject: [PATCH 020/208] [Examples] set FPS to 60 (#4235) * set FPS to 60 * remove extra commented lines --- examples/core/core_vr_simulator.c | 2 +- examples/textures/textures_blend_modes.c | 3 +++ examples/textures/textures_image_rotate.c | 2 ++ examples/textures/textures_logo_raylib.c | 2 ++ examples/textures/textures_raw_data.c | 2 ++ examples/textures/textures_sprite_explosion.c | 4 ++-- examples/textures/textures_to_image.c | 2 ++ 7 files changed, 14 insertions(+), 3 deletions(-) diff --git a/examples/core/core_vr_simulator.c b/examples/core/core_vr_simulator.c index c98fce931..021698edb 100644 --- a/examples/core/core_vr_simulator.c +++ b/examples/core/core_vr_simulator.c @@ -100,7 +100,7 @@ int main(void) DisableCursor(); // Limit cursor to relative movement inside the window - SetTargetFPS(90); // Set our game to run at 90 frames-per-second + SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop diff --git a/examples/textures/textures_blend_modes.c b/examples/textures/textures_blend_modes.c index 660aa57a7..d97432cb2 100644 --- a/examples/textures/textures_blend_modes.c +++ b/examples/textures/textures_blend_modes.c @@ -43,6 +43,9 @@ int main(void) const int blendCountMax = 4; BlendMode blendMode = 0; + SetTargetFPS(60); // Set our game to run at 60 frames-per-second + //--------------------------------------------------------------------------------------- + // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { diff --git a/examples/textures/textures_image_rotate.c b/examples/textures/textures_image_rotate.c index 51724e037..94c42034b 100644 --- a/examples/textures/textures_image_rotate.c +++ b/examples/textures/textures_image_rotate.c @@ -43,6 +43,8 @@ int main(void) textures[2] = LoadTextureFromImage(imageNeg90); int currentTexture = 0; + + SetTargetFPS(60); // Set our game to run at 60 frames-per-second //--------------------------------------------------------------------------------------- // Main game loop diff --git a/examples/textures/textures_logo_raylib.c b/examples/textures/textures_logo_raylib.c index f170dab48..35baa1223 100644 --- a/examples/textures/textures_logo_raylib.c +++ b/examples/textures/textures_logo_raylib.c @@ -27,6 +27,8 @@ int main(void) // NOTE: Textures MUST be loaded after Window initialization (OpenGL context is required) Texture2D texture = LoadTexture("resources/raylib_logo.png"); // Texture loading + + SetTargetFPS(60); // Set our game to run at 60 frames-per-second //--------------------------------------------------------------------------------------- // Main game loop diff --git a/examples/textures/textures_raw_data.c b/examples/textures/textures_raw_data.c index 38229f1ba..6fb41b143 100644 --- a/examples/textures/textures_raw_data.c +++ b/examples/textures/textures_raw_data.c @@ -63,6 +63,8 @@ int main(void) Texture2D checked = LoadTextureFromImage(checkedIm); UnloadImage(checkedIm); // Unload CPU (RAM) image data (pixels) + + SetTargetFPS(60); // Set our game to run at 60 frames-per-second //--------------------------------------------------------------------------------------- // Main game loop diff --git a/examples/textures/textures_sprite_explosion.c b/examples/textures/textures_sprite_explosion.c index 06b4f1dad..a65426cb6 100644 --- a/examples/textures/textures_sprite_explosion.c +++ b/examples/textures/textures_sprite_explosion.c @@ -48,8 +48,8 @@ int main(void) bool active = false; int framesCounter = 0; - SetTargetFPS(120); - //-------------------------------------------------------------------------------------- + SetTargetFPS(60); // Set our game to run at 60 frames-per-second + //--------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key diff --git a/examples/textures/textures_to_image.c b/examples/textures/textures_to_image.c index 2d09623eb..e1d88c4cd 100644 --- a/examples/textures/textures_to_image.c +++ b/examples/textures/textures_to_image.c @@ -38,6 +38,8 @@ int main(void) texture = LoadTextureFromImage(image); // Recreate texture from retrieved image data (RAM -> VRAM) UnloadImage(image); // Unload retrieved image data from CPU memory (RAM) + + SetTargetFPS(60); // Set our game to run at 60 frames-per-second //--------------------------------------------------------------------------------------- // Main game loop From 65c400354646fd43f54b9f832acc80ee6f63d1e2 Mon Sep 17 00:00:00 2001 From: hanaxars <156359933+hanaxars@users.noreply.github.com> Date: Mon, 12 Aug 2024 19:47:52 +0300 Subject: [PATCH 021/208] Make camera movement independant of framerate (#4247) Instead of moving camera with constant speed per frame, speed is multiplied with delta time before movement. --- src/rcamera.h | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/src/rcamera.h b/src/rcamera.h index d3042d306..c7f6fed3a 100644 --- a/src/rcamera.h +++ b/src/rcamera.h @@ -196,12 +196,12 @@ RLAPI Matrix GetCameraProjectionMatrix(Camera* camera, float aspect); //---------------------------------------------------------------------------------- // Defines and Macros //---------------------------------------------------------------------------------- -#define CAMERA_MOVE_SPEED 0.09f +#define CAMERA_MOVE_SPEED 5.4f // Units per second #define CAMERA_ROTATION_SPEED 0.03f #define CAMERA_PAN_SPEED 0.2f // Camera mouse movement sensitivity -#define CAMERA_MOUSE_MOVE_SENSITIVITY 0.003f // TODO: it should be independant of framerate +#define CAMERA_MOUSE_MOVE_SENSITIVITY 0.003f // Camera orbital speed in CAMERA_ORBITAL mode #define CAMERA_ORBITAL_SPEED 0.5f // Radians per second @@ -481,10 +481,11 @@ void UpdateCamera(Camera *camera, int mode) } // Keyboard support - if (IsKeyDown(KEY_W)) CameraMoveForward(camera, CAMERA_MOVE_SPEED, moveInWorldPlane); - if (IsKeyDown(KEY_A)) CameraMoveRight(camera, -CAMERA_MOVE_SPEED, moveInWorldPlane); - if (IsKeyDown(KEY_S)) CameraMoveForward(camera, -CAMERA_MOVE_SPEED, moveInWorldPlane); - if (IsKeyDown(KEY_D)) CameraMoveRight(camera, CAMERA_MOVE_SPEED, moveInWorldPlane); + float cameraMoveSpeed = CAMERA_MOVE_SPEED*GetFrameTime(); + if (IsKeyDown(KEY_W)) CameraMoveForward(camera, cameraMoveSpeed, moveInWorldPlane); + if (IsKeyDown(KEY_A)) CameraMoveRight(camera, -cameraMoveSpeed, moveInWorldPlane); + if (IsKeyDown(KEY_S)) CameraMoveForward(camera, -cameraMoveSpeed, moveInWorldPlane); + if (IsKeyDown(KEY_D)) CameraMoveRight(camera, cameraMoveSpeed, moveInWorldPlane); // Gamepad movement if (IsGamepadAvailable(0)) @@ -493,16 +494,16 @@ void UpdateCamera(Camera *camera, int mode) CameraYaw(camera, -(GetGamepadAxisMovement(0, GAMEPAD_AXIS_RIGHT_X)*2)*CAMERA_MOUSE_MOVE_SENSITIVITY, rotateAroundTarget); CameraPitch(camera, -(GetGamepadAxisMovement(0, GAMEPAD_AXIS_RIGHT_Y)*2)*CAMERA_MOUSE_MOVE_SENSITIVITY, lockView, rotateAroundTarget, rotateUp); - if (GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_Y) <= -0.25f) CameraMoveForward(camera, CAMERA_MOVE_SPEED, moveInWorldPlane); - if (GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_X) <= -0.25f) CameraMoveRight(camera, -CAMERA_MOVE_SPEED, moveInWorldPlane); - if (GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_Y) >= 0.25f) CameraMoveForward(camera, -CAMERA_MOVE_SPEED, moveInWorldPlane); - if (GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_X) >= 0.25f) CameraMoveRight(camera, CAMERA_MOVE_SPEED, moveInWorldPlane); + if (GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_Y) <= -0.25f) CameraMoveForward(camera, cameraMoveSpeed, moveInWorldPlane); + if (GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_X) <= -0.25f) CameraMoveRight(camera, -cameraMoveSpeed, moveInWorldPlane); + if (GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_Y) >= 0.25f) CameraMoveForward(camera, -cameraMoveSpeed, moveInWorldPlane); + if (GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_X) >= 0.25f) CameraMoveRight(camera, cameraMoveSpeed, moveInWorldPlane); } if (mode == CAMERA_FREE) { - if (IsKeyDown(KEY_SPACE)) CameraMoveUp(camera, CAMERA_MOVE_SPEED); - if (IsKeyDown(KEY_LEFT_CONTROL)) CameraMoveUp(camera, -CAMERA_MOVE_SPEED); + if (IsKeyDown(KEY_SPACE)) CameraMoveUp(camera, cameraMoveSpeed); + if (IsKeyDown(KEY_LEFT_CONTROL)) CameraMoveUp(camera, -cameraMoveSpeed); } } From 6e644a27fc1c3d3499750a0e58a0ba5c2a4a0ed2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A1zaro=20Albuquerque?= <33807434+lzralbu@users.noreply.github.com> Date: Tue, 13 Aug 2024 13:16:07 -0400 Subject: [PATCH 022/208] Change some global variables to have internal linkage (#4252) * Change some global variables to have internal linkage * Update rcore.c * Update rcore.c --- src/rcore.c | 6 +++--- src/rshapes.c | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/rcore.c b/src/rcore.c index 93ae4f3bb..5485ce8ce 100644 --- a/src/rcore.c +++ b/src/rcore.c @@ -367,9 +367,9 @@ static int screenshotCounter = 0; // Screenshots counter #endif #if defined(SUPPORT_GIF_RECORDING) -unsigned int gifFrameCounter = 0; // GIF frames counter -bool gifRecording = false; // GIF recording state -MsfGifState gifState = { 0 }; // MSGIF context state +static unsigned int gifFrameCounter = 0; // GIF frames counter +static bool gifRecording = false; // GIF recording state +static MsfGifState gifState = { 0 }; // MSGIF context state #endif #if defined(SUPPORT_AUTOMATION_EVENTS) diff --git a/src/rshapes.c b/src/rshapes.c index 89339708a..676b2521a 100644 --- a/src/rshapes.c +++ b/src/rshapes.c @@ -79,8 +79,8 @@ //---------------------------------------------------------------------------------- // Global Variables Definition //---------------------------------------------------------------------------------- -Texture2D texShapes = { 1, 1, 1, 1, 7 }; // Texture used on shapes drawing (white pixel loaded by rlgl) -Rectangle texShapesRec = { 0.0f, 0.0f, 1.0f, 1.0f }; // Texture source rectangle used on shapes drawing +static Texture2D texShapes = { 1, 1, 1, 1, 7 }; // Texture used on shapes drawing (white pixel loaded by rlgl) +static Rectangle texShapesRec = { 0.0f, 0.0f, 1.0f, 1.0f }; // Texture source rectangle used on shapes drawing //---------------------------------------------------------------------------------- // Module specific Functions Declaration From 63ae57d2e31afa8bc8cab7f17f0e44afa4e7552d Mon Sep 17 00:00:00 2001 From: Brian E <72316548+Brian-ED@users.noreply.github.com> Date: Thu, 15 Aug 2024 09:05:34 +0100 Subject: [PATCH 023/208] Added raylib-APL to BINDINGS.md (#4253) * Added raylib-APL to BINDINGS.md * added back the newline * Made APL binding be version 5.0 instead of auto Also alligned the bars of the new entry. --- BINDINGS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/BINDINGS.md b/BINDINGS.md index 3e840d587..7fd0dfd93 100644 --- a/BINDINGS.md +++ b/BINDINGS.md @@ -83,6 +83,7 @@ Some people ported raylib to other languages in the form of bindings or wrappers | [raylib-raku](https://github.com/vushu/raylib-raku) | **auto** | [Raku](https://www.raku.org) | Artistic License 2.0 | | [Raylib.lean](https://github.com/KislyjKisel/Raylib.lean) | 4.5 | [Lean4](https://lean-lang.org) | BSD-3-Clause | | [raylib-cobol](https://codeberg.org/glowiak/raylib-cobol) | **auto** | [COBOL](https://gnucobol.sourceforge.io) | Public domain | +| [raylib-apl](https://github.com/Brian-ED/raylib-apl) | **5.0** | [Dyalog APL](https://www.dyalog.com/) | MIT | ### Utility Wrapers From fa374f9cc902a37836cc66ea7d958d9be87057a3 Mon Sep 17 00:00:00 2001 From: Ray Date: Sat, 17 Aug 2024 00:44:33 +0200 Subject: [PATCH 024/208] Update webassembly.yml --- .github/workflows/webassembly.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/webassembly.yml b/.github/workflows/webassembly.yml index f9e51680d..f676877fd 100644 --- a/.github/workflows/webassembly.yml +++ b/.github/workflows/webassembly.yml @@ -29,7 +29,7 @@ jobs: - name: Setup emsdk uses: mymindstorm/setup-emsdk@v14 with: - version: 3.1.54 + version: 3.1.64 actions-cache-folder: 'emsdk-cache' - name: Setup Release Version From f70d8a33cb8a3cefe0cc261e945d4f6715c6c0bc Mon Sep 17 00:00:00 2001 From: Ray Date: Sat, 17 Aug 2024 00:46:08 +0200 Subject: [PATCH 025/208] REVIEWED: Shader load failing returns 0, instead of fallback --- src/rlgl.h | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/rlgl.h b/src/rlgl.h index 19c529398..5fb9497cd 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -3994,18 +3994,18 @@ unsigned int rlLoadShaderCode(const char *vsCode, const char *fsCode) unsigned int fragmentShaderId = 0; // Compile vertex shader (if provided) + // NOTE: If not vertex shader is provided, use default one if (vsCode != NULL) vertexShaderId = rlCompileShader(vsCode, GL_VERTEX_SHADER); - // In case no vertex shader was provided or compilation failed, we use default vertex shader - if (vertexShaderId == 0) vertexShaderId = RLGL.State.defaultVShaderId; + else vertexShaderId = RLGL.State.defaultVShaderId; // Compile fragment shader (if provided) + // NOTE: If not vertex shader is provided, use default one if (fsCode != NULL) fragmentShaderId = rlCompileShader(fsCode, GL_FRAGMENT_SHADER); - // In case no fragment shader was provided or compilation failed, we use default fragment shader - if (fragmentShaderId == 0) fragmentShaderId = RLGL.State.defaultFShaderId; + else fragmentShaderId = RLGL.State.defaultFShaderId; // In case vertex and fragment shader are the default ones, no need to recompile, we can just assign the default shader program id if ((vertexShaderId == RLGL.State.defaultVShaderId) && (fragmentShaderId == RLGL.State.defaultFShaderId)) id = RLGL.State.defaultShaderId; - else + else if ((vertexShaderId > 0) && (fragmentShaderId > 0)) { // One of or both shader are new, we need to compile a new shader program id = rlLoadShaderProgram(vertexShaderId, fragmentShaderId); @@ -4100,6 +4100,8 @@ unsigned int rlCompileShader(const char *shaderCode, int type) TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Compile error: %s", shader, log); RL_FREE(log); } + + shader = 0; } else { From 308b77cd42c42406a3bd4eac250761476ff0407e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A1zaro=20Albuquerque?= <33807434+lzralbu@users.noreply.github.com> Date: Fri, 16 Aug 2024 19:07:23 -0400 Subject: [PATCH 026/208] Fix warnings (#4251) * Update rmodels.c fix these warnings: ``` /src/rmodels.c:5744:17: warning: missing initializer for field 'w' of 'Vector4' [-Wmissing-field-initializers] [build] 5744 | Vector4 outTangent1 = {tmp[0], tmp[1], tmp[2]}; [build] | ^~~~~~~ ``` * Update rcore_web.c fix warnings --- src/platforms/rcore_web.c | 22 +++++++++++----------- src/rmodels.c | 4 ++-- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/platforms/rcore_web.c b/src/platforms/rcore_web.c index 937e15acd..ff7a92dbc 100644 --- a/src/platforms/rcore_web.c +++ b/src/platforms/rcore_web.c @@ -129,7 +129,7 @@ static void CursorEnterCallback(GLFWwindow *window, int enter); // Emscripten window callback events static EM_BOOL EmscriptenFullscreenChangeCallback(int eventType, const EmscriptenFullscreenChangeEvent *event, void *userData); -static EM_BOOL EmscriptenWindowResizedCallback(int eventType, const EmscriptenUiEvent *event, void *userData); +// static EM_BOOL EmscriptenWindowResizedCallback(int eventType, const EmscriptenUiEvent *event, void *userData); static EM_BOOL EmscriptenResizeCallback(int eventType, const EmscriptenUiEvent *event, void *userData); // Emscripten input callback events @@ -981,7 +981,7 @@ void PollInputEvents(void) default: break; } - if (button != -1) // Check for valid button + if (button + 1 != 0) // Check for valid button { if (gamepadState.digitalButton[j] == 1) { @@ -1572,12 +1572,12 @@ static EM_BOOL EmscriptenFullscreenChangeCallback(int eventType, const Emscripte } // Register window resize event -static EM_BOOL EmscriptenWindowResizedCallback(int eventType, const EmscriptenUiEvent *event, void *userData) -{ - // TODO: Implement EmscriptenWindowResizedCallback()? +// static EM_BOOL EmscriptenWindowResizedCallback(int eventType, const EmscriptenUiEvent *event, void *userData) +// { +// // TODO: Implement EmscriptenWindowResizedCallback()? - return 1; // The event was consumed by the callback handler -} +// return 1; // The event was consumed by the callback handler +// } EM_JS(int, GetWindowInnerWidth, (), { return window.innerWidth; }); EM_JS(int, GetWindowInnerHeight, (), { return window.innerHeight; }); @@ -1593,11 +1593,11 @@ static EM_BOOL EmscriptenResizeCallback(int eventType, const EmscriptenUiEvent * int width = GetWindowInnerWidth(); int height = GetWindowInnerHeight(); - if (width < CORE.Window.screenMin.width) width = CORE.Window.screenMin.width; - else if (width > CORE.Window.screenMax.width && CORE.Window.screenMax.width > 0) width = CORE.Window.screenMax.width; + if (width < (int)CORE.Window.screenMin.width) width = CORE.Window.screenMin.width; + else if (width > (int)CORE.Window.screenMax.width && CORE.Window.screenMax.width > 0) width = CORE.Window.screenMax.width; - if (height < CORE.Window.screenMin.height) height = CORE.Window.screenMin.height; - else if (height > CORE.Window.screenMax.height && CORE.Window.screenMax.height > 0) height = CORE.Window.screenMax.height; + if (height < (int)CORE.Window.screenMin.height) height = CORE.Window.screenMin.height; + else if (height > (int)CORE.Window.screenMax.height && CORE.Window.screenMax.height > 0) height = CORE.Window.screenMax.height; emscripten_set_canvas_element_size("#canvas", width, height); diff --git a/src/rmodels.c b/src/rmodels.c index c1d56765e..36a7e254d 100644 --- a/src/rmodels.c +++ b/src/rmodels.c @@ -5741,11 +5741,11 @@ static bool GetPoseAtTimeGLTF(cgltf_interpolation_type interpolationType, cgltf_ cgltf_accessor_read_float(output, 3*keyframe+1, tmp, 4); Vector4 v1 = {tmp[0], tmp[1], tmp[2], tmp[3]}; cgltf_accessor_read_float(output, 3*keyframe+2, tmp, 4); - Vector4 outTangent1 = {tmp[0], tmp[1], tmp[2]}; + Vector4 outTangent1 = {tmp[0], tmp[1], tmp[2], 0.0f}; cgltf_accessor_read_float(output, 3*(keyframe+1)+1, tmp, 4); Vector4 v2 = {tmp[0], tmp[1], tmp[2], tmp[3]}; cgltf_accessor_read_float(output, 3*(keyframe+1), tmp, 4); - Vector4 inTangent2 = {tmp[0], tmp[1], tmp[2]}; + Vector4 inTangent2 = {tmp[0], tmp[1], tmp[2], 0.0f}; Vector4 *r = data; v1 = QuaternionNormalize(v1); From b432aa2b9cd5eb35391636b6e147db8d9a9cf1cc Mon Sep 17 00:00:00 2001 From: Colleague Riley Date: Sat, 17 Aug 2024 08:00:54 -0400 Subject: [PATCH 027/208] Update RGFW (#4259) * update RGFW * fix bug with GetCurrentMonitor * update RGFW * update RGFW * clean up merge * update RGFW --- src/external/RGFW.h | 3074 ++++++++++++++++++++-------- src/platforms/rcore_desktop_rgfw.c | 6 +- 2 files changed, 2222 insertions(+), 858 deletions(-) diff --git a/src/external/RGFW.h b/src/external/RGFW.h index 5420ccab1..367a46fa6 100644 --- a/src/external/RGFW.h +++ b/src/external/RGFW.h @@ -57,6 +57,8 @@ #define RGFW_EXPORT - Use when building RGFW #define RGFW_IMPORT - Use when linking with RGFW (not as a single-header) + + #define RGFW_STD_INT - force the use stdint.h (for systems that might not have stdint.h (msvc)) */ /* @@ -81,6 +83,7 @@ Code-Nycticebus -> bug fixes Rob Rohan -> X11 bugs and missing features, MacOS/Cocoa fixing memory issues/bugs AICDG (@THISISAGOODNAME) -> vulkan support (example) + @Easymode -> support, testing/debugging, bug fixes and reviews */ #if _MSC_VER @@ -93,6 +96,11 @@ #ifndef RGFW_MALLOC #include + + #ifndef __USE_POSIX199309 + #define __USE_POSIX199309 + #endif + #include #define RGFW_MALLOC malloc #define RGFW_CALLOC calloc @@ -131,7 +139,7 @@ #endif #ifndef RGFWDEF - #ifdef __APPLE__ + #ifdef __clang__ #define RGFWDEF static inline #else #define RGFWDEF inline @@ -146,7 +154,7 @@ #define RGFW_UNUSED(x) (void)(x); #endif -#ifdef __cplusplus +#if defined(__cplusplus) && !defined(__EMSCRIPTEN__) extern "C" { #endif @@ -156,7 +164,7 @@ #define RGFW_HEADER #if !defined(u8) - #if defined(_MSC_VER) || defined(__SYMBIAN32__) /* MSVC might not have stdint.h */ + #if ((defined(_MSC_VER) || defined(__SYMBIAN32__)) && !defined(RGFW_STD_INT)) /* MSVC might not have stdint.h */ typedef unsigned char u8; typedef signed char i8; typedef unsigned short u16; @@ -182,10 +190,11 @@ #if !defined(b8) /* RGFW bool type */ typedef u8 b8; typedef u32 b32; - #define RGFW_TRUE 1 - #define RGFW_FALSE 0 #endif +#define RGFW_TRUE 1 +#define RGFW_FALSE 0 + /* thse OS macros looks better & are standardized */ /* plus it helps with cross-compiling */ @@ -242,6 +251,14 @@ #endif #endif +#elif defined(RGFW_WAYLAND) + #if !defined(RGFW_NO_API) && (!defined(RGFW_BUFFER) || defined(RGFW_OPENGL)) + #define RGFW_EGL + #define RGFW_OPENGL + #include + #endif + + #include #elif (defined(__unix__) || defined(RGFW_MACOS_X11) || defined(RGFW_X11)) && !defined(RGFW_WEBASM) #define RGFW_MACOS_X11 #define RGFW_X11 @@ -299,65 +316,65 @@ #define RGFW_NO_GPU_RENDER (1L<<14) /* don't render (using the GPU based API)*/ #define RGFW_NO_CPU_RENDER (1L<<15) /* don't render (using the CPU based buffer rendering)*/ +#define RGFW_WINDOW_HIDE (1L << 16)/* the window is hidden */ -/*! event codes */ -#define RGFW_keyPressed 2 /* a key has been pressed */ -#define RGFW_keyReleased 3 /*!< a key has been released*/ -/*! key event note - the code of the key pressed is stored in - RGFW_Event.keyCode - !!Keycodes defined at the bottom of the RGFW_HEADER part of this file!! +typedef RGFW_ENUM(u8, RGFW_event_types) { + /*! event codes */ + RGFW_keyPressed = 1, /* a key has been pressed */ + RGFW_keyReleased, /*!< a key has been released*/ + /*! key event note + the code of the key pressed is stored in + RGFW_Event.keyCode + !!Keycodes defined at the bottom of the RGFW_HEADER part of this file!! - while a string version is stored in - RGFW_Event.KeyString + while a string version is stored in + RGFW_Event.KeyString - RGFW_Event.lockState holds the current lockState - this means if CapsLock, NumLock are active or not -*/ -#define RGFW_mouseButtonPressed 4 /*!< a mouse button has been pressed (left,middle,right)*/ -#define RGFW_mouseButtonReleased 5 /*!< a mouse button has been released (left,middle,right)*/ -#define RGFW_mousePosChanged 6 /*!< the position of the mouse has been changed*/ -/*! mouse event note - the x and y of the mouse can be found in the vector, RGFW_Event.point + RGFW_Event.lockState holds the current lockState + this means if CapsLock, NumLock are active or not + */ + RGFW_mouseButtonPressed, /*!< a mouse button has been pressed (left,middle,right)*/ + RGFW_mouseButtonReleased, /*!< a mouse button has been released (left,middle,right)*/ + RGFW_mousePosChanged, /*!< the position of the mouse has been changed*/ + /*! mouse event note + the x and y of the mouse can be found in the vector, RGFW_Event.point - RGFW_Event.button holds which mouse button was pressed -*/ -#define RGFW_jsButtonPressed 7 /*!< a joystick button was pressed */ -#define RGFW_jsButtonReleased 8 /*!< a joystick button was released */ -#define RGFW_jsAxisMove 9 /*!< an axis of a joystick was moved*/ -/*! joystick event note - RGFW_Event.joystick holds which joystick was altered, if any - RGFW_Event.button holds which joystick button was pressed + RGFW_Event.button holds which mouse button was pressed + */ + RGFW_jsButtonPressed, /*!< a joystick button was pressed */ + RGFW_jsButtonReleased, /*!< a joystick button was released */ + RGFW_jsAxisMove, /*!< an axis of a joystick was moved*/ + /*! joystick event note + RGFW_Event.joystick holds which joystick was altered, if any + RGFW_Event.button holds which joystick button was pressed - RGFW_Event.axis holds the data of all the axis - RGFW_Event.axisCount says how many axis there are -*/ -#define RGFW_windowMoved 10 /*!< the window was moved (by the user) */ -#define RGFW_windowResized 11 /*!< the window was resized (by the user), [on webASM this means the browser was resized] */ + RGFW_Event.axis holds the data of all the axis + RGFW_Event.axisCount says how many axis there are + */ + RGFW_windowMoved, /*!< the window was moved (by the user) */ + RGFW_windowResized, /*!< the window was resized (by the user), [on webASM this means the browser was resized] */ + RGFW_focusIn, /*!< window is in focus now */ + RGFW_focusOut, /*!< window is out of focus now */ + RGFW_mouseEnter, /* mouse entered the window */ + RGFW_mouseLeave, /* mouse left the window */ + RGFW_windowRefresh, /* The window content needs to be refreshed */ -#define RGFW_focusIn 12 /*!< window is in focus now */ -#define RGFW_focusOut 13 /*!< window is out of focus now */ + /* attribs change event note + The event data is sent straight to the window structure + with win->r.x, win->r.y, win->r.w and win->r.h + */ + RGFW_quit, /*!< the user clicked the quit button*/ + RGFW_dnd, /*!< a file has been dropped into the window*/ + RGFW_dnd_init /*!< the start of a dnd event, when the place where the file drop is known */ + /* dnd data note + The x and y coords of the drop are stored in the vector RGFW_Event.point -#define RGFW_mouseEnter 14 /* mouse entered the window */ -#define RGFW_mouseLeave 15 /* mouse left the window */ + RGFW_Event.droppedFilesCount holds how many files were dropped -#define RGFW_windowRefresh 16 /* The window content needs to be refreshed */ - -/* attribs change event note - The event data is sent straight to the window structure - with win->r.x, win->r.y, win->r.w and win->r.h -*/ -#define RGFW_quit 33 /*!< the user clicked the quit button*/ -#define RGFW_dnd 34 /*!< a file has been dropped into the window*/ -#define RGFW_dnd_init 35 /*!< the start of a dnd event, when the place where the file drop is known */ -/* dnd data note - The x and y coords of the drop are stored in the vector RGFW_Event.point - - RGFW_Event.droppedFilesCount holds how many files were dropped - - This is also the size of the array which stores all the dropped file string, - RGFW_Event.droppedFiles -*/ + This is also the size of the array which stores all the dropped file string, + RGFW_Event.droppedFiles + */ +}; /*! mouse button codes (RGFW_Event.button) */ #define RGFW_mouseLeft 1 /*!< left mouse button is pressed*/ @@ -381,64 +398,72 @@ /*! joystick button codes (based on xbox/playstation), you may need to change these values per controller */ #ifndef RGFW_joystick_codes typedef RGFW_ENUM(u8, RGFW_joystick_codes) { - RGFW_JS_A = 0, /* or PS X button */ - RGFW_JS_B = 1, /* or PS circle button */ - RGFW_JS_Y = 2, /* or PS triangle button */ - RGFW_JS_X = 3, /* or PS square button */ - RGFW_JS_START = 9, /* start button */ - RGFW_JS_SELECT = 8, /* select button */ - RGFW_JS_HOME = 10, /* home button */ - RGFW_JS_UP = 13, /* dpad up */ - RGFW_JS_DOWN = 14, /* dpad down*/ - RGFW_JS_LEFT = 15, /* dpad left */ - RGFW_JS_RIGHT = 16, /* dpad right */ - RGFW_JS_L1 = 4, /* left bump */ - RGFW_JS_L2 = 5, /* left trigger*/ - RGFW_JS_R1 = 6, /* right bumper */ - RGFW_JS_R2 = 7, /* right trigger */ + RGFW_JS_A = 0, /*!< or PS X button */ + RGFW_JS_B = 1, /*!< or PS circle button */ + RGFW_JS_Y = 2, /*!< or PS triangle button */ + RGFW_JS_X = 3, /*!< or PS square button */ + RGFW_JS_START = 9, /*!< start button */ + RGFW_JS_SELECT = 8, /*!< select button */ + RGFW_JS_HOME = 10, /*!< home button */ + RGFW_JS_UP = 13, /*!< dpad up */ + RGFW_JS_DOWN = 14, /*!< dpad down*/ + RGFW_JS_LEFT = 15, /*!< dpad left */ + RGFW_JS_RIGHT = 16, /*!< dpad right */ + RGFW_JS_L1 = 4, /*!< left bump */ + RGFW_JS_L2 = 5, /*!< left trigger*/ + RGFW_JS_R1 = 6, /*!< right bumper */ + RGFW_JS_R2 = 7, /*!< right trigger */ }; #endif -/* basic vector type, if there's not already a point/vector type of choice */ +/*! basic vector type, if there's not already a point/vector type of choice */ #ifndef RGFW_point typedef struct { i32 x, y; } RGFW_point; #endif - /* basic rect type, if there's not already a rect type of choice */ +/*! basic rect type, if there's not already a rect type of choice */ #ifndef RGFW_rect typedef struct { i32 x, y, w, h; } RGFW_rect; #endif - /* basic area type, if there's not already a area type of choice */ +/*! basic area type, if there's not already a area type of choice */ #ifndef RGFW_area typedef struct { u32 w, h; } RGFW_area; #endif -#define RGFW_POINT(x, y) (RGFW_point){x, y} -#define RGFW_RECT(x, y, w, h) (RGFW_rect){x, y, w, h} -#define RGFW_AREA(w, h) (RGFW_area){w, h} +#ifndef __cplusplus +#define RGFW_POINT(x, y) (RGFW_point){(i32)(x), (i32)(y)} +#define RGFW_RECT(x, y, w, h) (RGFW_rect){(i32)(x), (i32)(y), (i32)(w), (i32)(h)} +#define RGFW_AREA(w, h) (RGFW_area){(u32)(w), (u32)(h)} +#else +#define RGFW_POINT(x, y) {(i32)(x), (i32)(y)} +#define RGFW_RECT(x, y, w, h) {(i32)(x), (i32)(y), (i32)(w), (i32)(h)} +#define RGFW_AREA(w, h) {(u32)(w), (u32)(h)} +#endif #ifndef RGFW_NO_MONITOR + /*! structure for monitor data */ typedef struct RGFW_monitor { - char name[128]; /* monitor name */ - RGFW_rect rect; /* monitor Workarea */ - float scaleX, scaleY; /* monitor content scale*/ - float physW, physH; /* monitor physical size */ + char name[128]; /*!< monitor name */ + RGFW_rect rect; /*!< monitor Workarea */ + float scaleX, scaleY; /*!< monitor content scale*/ + float physW, physH; /*!< monitor physical size */ } RGFW_monitor; /* - NOTE : Monitor functions should be ran only as many times as needed (not in a loop) + NOTE : Monitor functions should be ran only as many times as needed (not in a loop) */ - /* get an array of all the monitors (max 6) */ + /*! get an array of all the monitors (max 6) */ RGFWDEF RGFW_monitor* RGFW_getMonitors(void); - /* get the primary monitor */ + /*! get the primary monitor */ RGFWDEF RGFW_monitor RGFW_getPrimaryMonitor(void); #endif /* NOTE: some parts of the data can represent different things based on the event (read comments in RGFW_Event struct) */ +/*! Event structure for checking/getting events */ typedef struct RGFW_Event { - char keyName[16]; /* key name of event*/ + char keyName[16]; /*!< key name of event*/ /*! drag and drop data */ /* 260 max paths with a max length of 260 */ @@ -452,67 +477,85 @@ typedef struct RGFW_Event { u32 type; /*!< which event has been sent?*/ RGFW_point point; /*!< mouse x, y of event (or drop point) */ - u32 fps; /*the current fps of the window [the fps is checked when events are checked]*/ - u64 frameTime, frameTime2; /* this is used for counting the fps */ + u8 keyCode; /*!< keycode of event !!Keycodes defined at the bottom of the RGFW_HEADER part of this file!! */ - u8 keyCode; /*!< keycode of event !!Keycodes defined at the bottom of the RGFW_HEADER part of this file!! */ - - b8 inFocus; /*if the window is in focus or not (this is always true for MacOS windows due to the api being weird) */ + b8 repeat; /*!< key press event repeated (the key is being held) */ + b8 inFocus; /*!< if the window is in focus or not (this is always true for MacOS windows due to the api being weird) */ u8 lockState; + + u8 button; /* !< which mouse button was pressed */ + double scroll; /*!< the raw mouse scroll value */ - u16 joystick; /* which joystick this event applies to (if applicable to any) */ + u16 joystick; /*! which joystick this event applies to (if applicable to any) */ + u8 axisesCount; /*!< number of axises */ + RGFW_point axis[2]; /*!< x, y of axises (-100 to 100) */ - u8 button; /*!< which mouse button has been clicked (0) left (1) middle (2) right OR which joystick button was pressed*/ - double scroll; /* the raw mouse scroll value */ - - u8 axisesCount; /* number of axises */ - RGFW_point axis[2]; /* x, y of axises (-100 to 100) */ -} RGFW_Event; /*!< Event structure for checking/getting events */ - -/* source data for the window (used by the APIs) */ + u64 frameTime, frameTime2; /*!< this is used for counting the fps */ +} RGFW_Event; +/*! source data for the window (used by the APIs) */ typedef struct RGFW_window_src { #ifdef RGFW_WINDOWS HWND window; /*!< source window */ HDC hdc; /*!< source HDC */ u32 hOffset; /*!< height offset for window */ -#if (defined(RGFW_OPENGL)) && !defined(RGFW_OSMESA) && !defined(RGFW_EGL) + #if (defined(RGFW_OPENGL)) && !defined(RGFW_OSMESA) && !defined(RGFW_EGL) HGLRC ctx; /*!< source graphics context */ -#elif defined(RGFW_OSMESA) + #elif defined(RGFW_OSMESA) OSMesaContext ctx; -#elif defined(RGFW_DIRECTX) + #elif defined(RGFW_DIRECTX) IDXGISwapChain* swapchain; ID3D11RenderTargetView* renderTargetView; ID3D11DepthStencilView* pDepthStencilView; -#elif defined(RGFW_EGL) + #elif defined(RGFW_EGL) EGLSurface EGL_surface; EGLDisplay EGL_display; EGLContext EGL_context; -#endif + #endif -#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) + #if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) HDC hdcMem; HBITMAP bitmap; -#endif - RGFW_area maxSize, minSize; /* for setting max/min resize (RGFW_WINDOWS) */ + #endif + RGFW_area maxSize, minSize; /*!< for setting max/min resize (RGFW_WINDOWS) */ #elif defined(RGFW_X11) Display* display; /*!< source display */ Window window; /*!< source window */ -#if (defined(RGFW_OPENGL)) && !defined(RGFW_OSMESA) && !defined(RGFW_EGL) + #if (defined(RGFW_OPENGL)) && !defined(RGFW_OSMESA) && !defined(RGFW_EGL) GLXContext ctx; /*!< source graphics context */ -#elif defined(RGFW_OSMESA) + #elif defined(RGFW_OSMESA) OSMesaContext ctx; -#elif defined(RGFW_EGL) + #elif defined(RGFW_EGL) EGLSurface EGL_surface; EGLDisplay EGL_display; EGLContext EGL_context; -#endif + #endif #if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) XImage* bitmap; GC gc; #endif +#elif defined(RGFW_WAYLAND) + struct wl_display* display; + struct wl_surface* surface; + struct wl_buffer* wl_buffer; + struct wl_keyboard* keyboard; + + struct xdg_surface* xdg_surface; + struct xdg_toplevel* xdg_toplevel; + struct zxdg_toplevel_decoration_v1* decoration; + RGFW_Event events[20]; + i32 eventLen; + size_t eventIndex; + #if defined(RGFW_EGL) + struct wl_egl_window* window; + EGLSurface EGL_surface; + EGLDisplay EGL_display; + EGLContext EGL_context; + #elif defined(RGFW_OSMESA) + OSMesaContext ctx; + #endif #elif defined(RGFW_MACOS) u32 display; void* displayLink; @@ -531,7 +574,7 @@ typedef struct RGFW_window_src { void* view; /*apple viewpoint thingy*/ #if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) - void* bitmap; /* API's bitmap for storing or managing */ + void* bitmap; /*!< API's bitmap for storing or managing */ void* image; #endif #elif defined(RGFW_WEBASM) @@ -542,33 +585,34 @@ typedef struct RGFW_window_src { typedef struct RGFW_window { - RGFW_window_src src; + RGFW_window_src src; /*!< src window data */ #if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) - u8* buffer; /* buffer for non-GPU systems (OSMesa, basic software rendering) */ + u8* buffer; /*!< buffer for non-GPU systems (OSMesa, basic software rendering) */ /* when rendering using RGFW_BUFFER, the buffer is in the RGBA format */ #endif - + void* userPtr; /* ptr for usr data */ + RGFW_Event event; /*!< current event */ - RGFW_rect r; /* the x, y, w and h of the struct */ + RGFW_rect r; /*!< the x, y, w and h of the struct */ - RGFW_point _lastMousePoint; /* last cusor point (for raw mouse data) */ - - u32 fpsCap; /*!< the fps cap of the window should run at (change this var to change the fps cap, 0 = no limit)*/ - /*[the fps is capped when events are checked]*/ - - u32 _winArgs; /* windows args (for RGFW to check) */ + RGFW_point _lastMousePoint; /*!< last cusor point (for raw mouse data) */ + + u32 _winArgs; /*!< windows args (for RGFW to check) */ } RGFW_window; /*!< Window structure for managing the window */ #if defined(RGFW_X11) || defined(RGFW_MACOS) - typedef u64 RGFW_thread; /* thread type unix */ + typedef u64 RGFW_thread; /*!< thread type unix */ #else - typedef void* RGFW_thread; /* thread type for window */ + typedef void* RGFW_thread; /*!< thread type for window */ #endif -/* this has to be set before createWindow is called, else the fulscreen size is used */ -RGFWDEF void RGFW_setBufferSize(RGFW_area size); /* the buffer cannot be resized (by RGFW) */ +/** * @defgroup Window_management +* @{ */ + +/*! this has to be set before createWindow is called, else the fulscreen size is used */ +RGFWDEF void RGFW_setBufferSize(RGFW_area size); /*!< the buffer cannot be resized (by RGFW) */ RGFW_window* RGFW_createWindow( const char* name, /* name of the window */ @@ -576,10 +620,10 @@ RGFW_window* RGFW_createWindow( u16 args /* extra arguments (NULL / (u16)0 means no args used)*/ ); /*!< function to create a window struct */ -/* get the size of the screen to an area struct */ +/*! get the size of the screen to an area struct */ RGFWDEF RGFW_area RGFW_getScreenSize(void); -/* +/*! this function checks an *individual* event (and updates window structure attributes) this means, using this function without a while loop may cause event lag @@ -593,7 +637,7 @@ RGFWDEF RGFW_area RGFW_getScreenSize(void); RGFW_Event* RGFW_window_checkEvent(RGFW_window* win); /*!< check current event (returns a pointer to win->event or NULL if there is no event)*/ -/* +/*! for RGFW_window_eventWait and RGFW_window_checkEvents waitMS -> Allows th e function to keep checking for events even after `RGFW_window_checkEvent == NULL` if waitMS == 0, the loop will not wait for events @@ -605,16 +649,16 @@ typedef RGFW_ENUM(i32, RGFW_eventWait) { RGFW_NO_WAIT = 0 }; -/* sleep until RGFW gets an event or the timer ends (defined by OS) */ +/*! sleep until RGFW gets an event or the timer ends (defined by OS) */ RGFWDEF void RGFW_window_eventWait(RGFW_window* win, i32 waitMS); -/* +/*! check all the events until there are none left, this should only be used if you're using callbacks only */ RGFWDEF void RGFW_window_checkEvents(RGFW_window* win, i32 waitMS); -/* +/*! Tell RGFW_window_eventWait to stop waiting, to be ran from another thread */ RGFWDEF void RGFW_stopCheckEvents(void); @@ -622,42 +666,42 @@ RGFWDEF void RGFW_stopCheckEvents(void); /*! window managment functions*/ RGFWDEF void RGFW_window_close(RGFW_window* win); /*!< close the window and free leftover data */ -/* moves window to a given point */ +/*! moves window to a given point */ RGFWDEF void RGFW_window_move(RGFW_window* win, - RGFW_point v/* new pos*/ + RGFW_point v/*!< new pos*/ ); #ifndef RGFW_NO_MONITOR - /* move to a specific monitor */ + /*! move to a specific monitor */ RGFWDEF void RGFW_window_moveToMonitor(RGFW_window* win, RGFW_monitor m /* monitor */); #endif -/* resize window to a current size/area */ -RGFWDEF void RGFW_window_resize(RGFW_window* win, - RGFW_area a/* new size*/ +/*! resize window to a current size/area */ +RGFWDEF void RGFW_window_resize(RGFW_window* win, /*!< source window */ + RGFW_area a/*!< new size*/ ); -/* set the minimum size a user can shrink a window to a given size/area */ +/*! set the minimum size a user can shrink a window to a given size/area */ RGFWDEF void RGFW_window_setMinSize(RGFW_window* win, RGFW_area a); -/* set the minimum size a user can extend a window to a given size/area */ +/*! set the minimum size a user can extend a window to a given size/area */ RGFWDEF void RGFW_window_setMaxSize(RGFW_window* win, RGFW_area a); -RGFWDEF void RGFW_window_maximize(RGFW_window* win); /* maximize the window size */ -RGFWDEF void RGFW_window_minimize(RGFW_window* win); /* minimize the window (in taskbar (per OS))*/ -RGFWDEF void RGFW_window_restore(RGFW_window* win); /* restore the window from minimized (per OS)*/ +RGFWDEF void RGFW_window_maximize(RGFW_window* win); /*!< maximize the window size */ +RGFWDEF void RGFW_window_minimize(RGFW_window* win); /*!< minimize the window (in taskbar (per OS))*/ +RGFWDEF void RGFW_window_restore(RGFW_window* win); /*!< restore the window from minimized (per OS)*/ -/* if the window should have a border or not (borderless) based on bool value of `border` */ +/*! if the window should have a border or not (borderless) based on bool value of `border` */ RGFWDEF void RGFW_window_setBorder(RGFW_window* win, b8 border); -/* turn on / off dnd (RGFW_ALLOW_DND stil must be passed to the window)*/ +/*! turn on / off dnd (RGFW_ALLOW_DND stil must be passed to the window)*/ RGFWDEF void RGFW_window_setDND(RGFW_window* win, b8 allow); #ifndef RGFW_NO_PASSTHROUGH - /* turn on / off mouse passthrough */ + /*!! turn on / off mouse passthrough */ RGFWDEF void RGFW_window_setMousePassthrough(RGFW_window* win, b8 passthrough); #endif -/* rename window to a given string */ +/*! rename window to a given string */ RGFWDEF void RGFW_window_setName(RGFW_window* win, char* name ); @@ -674,7 +718,7 @@ RGFWDEF void RGFW_window_setMouse(RGFW_window* win, u8* image, RGFW_area a, i32 /*!< sets the mouse to a standard API cursor (based on RGFW_MOUSE, as seen at the end of the RGFW_HEADER part of this file) */ RGFWDEF void RGFW_window_setMouseStandard(RGFW_window* win, u8 mouse); -RGFWDEF void RGFW_window_setMouseDefault(RGFW_window* win); /* sets the mouse to the default mouse icon */ +RGFWDEF void RGFW_window_setMouseDefault(RGFW_window* win); /*!< sets the mouse to the default mouse icon */ /* Locks cursor at the center of the window win->event.point become raw mouse movement data @@ -682,12 +726,12 @@ RGFWDEF void RGFW_window_setMouseDefault(RGFW_window* win); /* sets the mouse to this is useful for a 3D camera */ RGFWDEF void RGFW_window_mouseHold(RGFW_window* win, RGFW_area area); -/* stop holding the mouse and let it move freely */ +/*! stop holding the mouse and let it move freely */ RGFWDEF void RGFW_window_mouseUnhold(RGFW_window* win); -/* hide the window */ +/*! hide the window */ RGFWDEF void RGFW_window_hide(RGFW_window* win); -/* show the window */ +/*! show the window */ RGFWDEF void RGFW_window_show(RGFW_window* win); /* @@ -696,28 +740,32 @@ RGFWDEF void RGFW_window_show(RGFW_window* win); */ RGFWDEF void RGFW_window_setShouldClose(RGFW_window* win); -/* where the mouse is on the screen */ +/*! where the mouse is on the screen */ RGFWDEF RGFW_point RGFW_getGlobalMousePoint(void); -/* where the mouse is on the window */ +/*! where the mouse is on the window */ RGFWDEF RGFW_point RGFW_window_getMousePoint(RGFW_window* win); -/* show the mouse or hide the mouse*/ +/*! show the mouse or hide the mouse*/ RGFWDEF void RGFW_window_showMouse(RGFW_window* win, i8 show); -/* move the mouse to a set x, y pos*/ +/*! move the mouse to a set x, y pos*/ RGFWDEF void RGFW_window_moveMouse(RGFW_window* win, RGFW_point v); -/* if the window should close (RGFW_close was sent or escape was pressed) */ +/*! if the window should close (RGFW_close was sent or escape was pressed) */ RGFWDEF b8 RGFW_window_shouldClose(RGFW_window* win); -/* if window is fullscreen'd */ +/*! if window is fullscreen'd */ RGFWDEF b8 RGFW_window_isFullscreen(RGFW_window* win); -/* if window is hidden */ +/*! if window is hidden */ RGFWDEF b8 RGFW_window_isHidden(RGFW_window* win); -/* if window is minimized */ +/*! if window is minimized */ RGFWDEF b8 RGFW_window_isMinimized(RGFW_window* win); -/* if window is maximized */ +/*! if window is maximized */ RGFWDEF b8 RGFW_window_isMaximized(RGFW_window* win); +/** @} */ + +/** * @defgroup Monitor +* @{ */ #ifndef RGFW_NO_MONITOR /* @@ -725,17 +773,27 @@ scale the window to the monitor, this is run by default if the user uses the arg `RGFW_SCALE_TO_MONITOR` during window creation */ RGFWDEF void RGFW_window_scaleToMonitor(RGFW_window* win); -/* get the struct of the window's monitor */ +/*! get the struct of the window's monitor */ RGFWDEF RGFW_monitor RGFW_window_getMonitor(RGFW_window* win); #endif -/*!< make the window the current opengl drawing context */ -RGFWDEF void RGFW_window_makeCurrent(RGFW_window* win); +/** @} */ + +/** * @defgroup Input +* @{ */ /*error handling*/ -RGFWDEF b8 RGFW_Error(void); /* returns true if an error has occurred (doesn't print errors itself) */ +RGFWDEF b8 RGFW_Error(void); /*!< returns true if an error has occurred (doesn't print errors itself) */ -/*!< if window == NULL, it checks if the key is pressed globally. Otherwise, it checks only if the key is pressed while the window in focus.*/ +/*! returns true if the key should be shifted */ +RGFWDEF b8 RGFW_shouldShift(u32 keycode, u8 lockState); + +/*! get char from RGFW keycode (using a LUT), uses shift'd version if shift = true */ +RGFWDEF char RGFW_keyCodeToChar(u32 keycode, b8 shift); +/*! get char from RGFW keycode (using a LUT), uses lockState for shouldShift) */ +RGFWDEF char RGFW_keyCodeToCharAuto(u32 keycode, u8 lockState); + +/*! if window == NULL, it checks if the key is pressed globally. Otherwise, it checks only if the key is pressed while the window in focus.*/ RGFWDEF b8 RGFW_isPressed(RGFW_window* win, u8 key); /*!< if key is pressed (key code)*/ RGFWDEF b8 RGFW_wasPressed(RGFW_window* win, u8 key); /*!< if key was pressed (checks previous state only) (key code)*/ @@ -744,90 +802,100 @@ RGFWDEF b8 RGFW_isHeld(RGFW_window* win, u8 key); /*!< if key is held (key code) RGFWDEF b8 RGFW_isReleased(RGFW_window* win, u8 key); /*!< if key is released (key code)*/ /* if a key is pressed and then released, pretty much the same as RGFW_isReleased */ -RGFWDEF b8 RGFW_isClicked(RGFW_window* win, u8 key /* key code*/); +RGFWDEF b8 RGFW_isClicked(RGFW_window* win, u8 key /*!< key code*/); -/* if a mouse button is pressed */ -RGFWDEF b8 RGFW_isMousePressed(RGFW_window* win, u8 button /* mouse button code */ ); -/* if a mouse button is held */ -RGFWDEF b8 RGFW_isMouseHeld(RGFW_window* win, u8 button /* mouse button code */ ); -/* if a mouse button was released */ -RGFWDEF b8 RGFW_isMouseReleased(RGFW_window* win, u8 button /* mouse button code */ ); -/* if a mouse button was pressed (checks previous state only) */ -RGFWDEF b8 RGFW_wasMousePressed(RGFW_window* win, u8 button /* mouse button code */ ); +/*! if a mouse button is pressed */ +RGFWDEF b8 RGFW_isMousePressed(RGFW_window* win, u8 button /*!< mouse button code */ ); +/*! if a mouse button is held */ +RGFWDEF b8 RGFW_isMouseHeld(RGFW_window* win, u8 button /*!< mouse button code */ ); +/*! if a mouse button was released */ +RGFWDEF b8 RGFW_isMouseReleased(RGFW_window* win, u8 button /*!< mouse button code */ ); +/*! if a mouse button was pressed (checks previous state only) */ +RGFWDEF b8 RGFW_wasMousePressed(RGFW_window* win, u8 button /*!< mouse button code */ ); +/** @} */ -/*! clipboard functions*/ +/** * @defgroup Clipboard +* @{ */ RGFWDEF char* RGFW_readClipboard(size_t* size); /*!< read clipboard data */ -RGFWDEF void RGFW_clipboardFree(char* str); /* the string returned from RGFW_readClipboard must be freed */ +RGFWDEF void RGFW_clipboardFree(char* str); /*!< the string returned from RGFW_readClipboard must be freed */ RGFWDEF void RGFW_writeClipboard(const char* text, u32 textLen); /*!< write text to the clipboard */ +/** @} */ -/* +/** Event callbacks, these are completely optional, you can use the normal RGFW_checkEvent() method if you prefer that +* @defgroup Callbacks +* @{ */ -/* RGFW_windowMoved, the window and its new rect value */ +/*! RGFW_windowMoved, the window and its new rect value */ typedef void (* RGFW_windowmovefunc)(RGFW_window* win, RGFW_rect r); -/* RGFW_windowResized, the window and its new rect value */ +/*! RGFW_windowResized, the window and its new rect value */ typedef void (* RGFW_windowresizefunc)(RGFW_window* win, RGFW_rect r); -/* RGFW_quit, the window that was closed */ +/*! RGFW_quit, the window that was closed */ typedef void (* RGFW_windowquitfunc)(RGFW_window* win); -/* RGFW_focusIn / RGFW_focusOut, the window who's focus has changed and if its inFocus */ +/*! RGFW_focusIn / RGFW_focusOut, the window who's focus has changed and if its inFocus */ typedef void (* RGFW_focusfunc)(RGFW_window* win, b8 inFocus); -/* RGFW_mouseEnter / RGFW_mouseLeave, the window that changed, the point of the mouse (enter only) and if the mouse has entered */ +/*! RGFW_mouseEnter / RGFW_mouseLeave, the window that changed, the point of the mouse (enter only) and if the mouse has entered */ typedef void (* RGFW_mouseNotifyfunc)(RGFW_window* win, RGFW_point point, b8 status); -/* RGFW_mousePosChanged, the window that the move happened on and the new point of the mouse */ +/*! RGFW_mousePosChanged, the window that the move happened on and the new point of the mouse */ typedef void (* RGFW_mouseposfunc)(RGFW_window* win, RGFW_point point); -/* RGFW_dnd_init, the window, the point of the drop on the windows */ +/*! RGFW_dnd_init, the window, the point of the drop on the windows */ typedef void (* RGFW_dndInitfunc)(RGFW_window* win, RGFW_point point); -/* RGFW_windowRefresh, the window that needs to be refreshed */ +/*! RGFW_windowRefresh, the window that needs to be refreshed */ typedef void (* RGFW_windowrefreshfunc)(RGFW_window* win); -/* RGFW_keyPressed / RGFW_keyReleased, the window that got the event, the keycode, the string version, the state of mod keys, if it was a press (else it's a release) */ +/*! RGFW_keyPressed / RGFW_keyReleased, the window that got the event, the keycode, the string version, the state of mod keys, if it was a press (else it's a release) */ typedef void (* RGFW_keyfunc)(RGFW_window* win, u32 keycode, char keyName[16], u8 lockState, b8 pressed); -/* RGFW_mouseButtonPressed / RGFW_mouseButtonReleased, the window that got the event, the button that was pressed, the scroll value, if it was a press (else it's a release) */ +/*! RGFW_mouseButtonPressed / RGFW_mouseButtonReleased, the window that got the event, the button that was pressed, the scroll value, if it was a press (else it's a release) */ typedef void (* RGFW_mousebuttonfunc)(RGFW_window* win, u8 button, double scroll, b8 pressed); -/* RGFW_jsButtonPressed / RGFW_jsButtonReleased, the window that got the event, the button that was pressed, the scroll value, if it was a press (else it's a release) */ +/*! RGFW_jsButtonPressed / RGFW_jsButtonReleased, the window that got the event, the button that was pressed, the scroll value, if it was a press (else it's a release) */ typedef void (* RGFW_jsButtonfunc)(RGFW_window* win, u16 joystick, u8 button, b8 pressed); -/* RGFW_jsAxisMove, the window that got the event, the joystick in question, the axis values and the amount of axises */ +/*! RGFW_jsAxisMove, the window that got the event, the joystick in question, the axis values and the amount of axises */ typedef void (* RGFW_jsAxisfunc)(RGFW_window* win, u16 joystick, RGFW_point axis[2], u8 axisesCount); -/* RGFW_dnd, the window that had the drop, the drop data and the amount files dropped */ + +/*! RGFW_dnd, the window that had the drop, the drop data and the amount files dropped returns previous callback function (if it was set) */ #ifdef RGFW_ALLOC_DROPFILES typedef void (* RGFW_dndfunc)(RGFW_window* win, char** droppedFiles, u32 droppedFilesCount); #else typedef void (* RGFW_dndfunc)(RGFW_window* win, char droppedFiles[RGFW_MAX_DROPS][RGFW_MAX_PATH], u32 droppedFilesCount); #endif -/* set callback for a window move event */ -RGFWDEF void RGFW_setWindowMoveCallback(RGFW_windowmovefunc func); -/* set callbacksfor a window resize event */ -RGFWDEF void RGFW_setWindowResizeCallback(RGFW_windowresizefunc func); -/* set callbacksfor a window quit event */ -RGFWDEF void RGFW_setWindowQuitCallback(RGFW_windowquitfunc func); -/* set callbacksfor a mouse move event */ -RGFWDEF void RGFW_setMousePosCallback(RGFW_mouseposfunc func); -/* set callbacksfor a window refresh event */ -RGFWDEF void RGFW_setWindowRefreshCallback(RGFW_windowrefreshfunc func); -/* set callbacksfor a window focus change event */ -RGFWDEF void RGFW_setFocusCallback(RGFW_focusfunc func); -/* set callbacksfor a mouse notify event */ -RGFWDEF void RGFW_setMouseNotifyCallBack(RGFW_mouseNotifyfunc func); -/* set callbacksfor a drop event event */ -RGFWDEF void RGFW_setDndCallback(RGFW_dndfunc func); -/* set callbacksfor a start of a drop event */ -RGFWDEF void RGFW_setDndInitCallback(RGFW_dndInitfunc func); -/* set callbacksfor a key (press / release ) event */ -RGFWDEF void RGFW_setKeyCallback(RGFW_keyfunc func); -/* set callbacksfor a mouse button (press / release ) event */ -RGFWDEF void RGFW_setMouseButtonCallback(RGFW_mousebuttonfunc func); -/* set callbacksfor a controller button (press / release ) event */ -RGFWDEF void RGFW_setjsButtonCallback(RGFW_jsButtonfunc func); -/* set callbacksfor a joystick axis mov event */ -RGFWDEF void RGFW_setjsAxisCallback(RGFW_jsAxisfunc func); +/*! set callback for a window move event returns previous callback function (if it was set) */ +RGFWDEF RGFW_windowmovefunc RGFW_setWindowMoveCallback(RGFW_windowmovefunc func); +/*! set callback for a window resize event returns previous callback function (if it was set) */ +RGFWDEF RGFW_windowresizefunc RGFW_setWindowResizeCallback(RGFW_windowresizefunc func); +/*! set callback for a window quit event returns previous callback function (if it was set) */ +RGFWDEF RGFW_windowquitfunc RGFW_setWindowQuitCallback(RGFW_windowquitfunc func); +/*! set callback for a mouse move event returns previous callback function (if it was set) */ +RGFWDEF RGFW_mouseposfunc RGFW_setMousePosCallback(RGFW_mouseposfunc func); +/*! set callback for a window refresh event returns previous callback function (if it was set) */ +RGFWDEF RGFW_windowrefreshfunc RGFW_setWindowRefreshCallback(RGFW_windowrefreshfunc func); +/*! set callback for a window focus change event returns previous callback function (if it was set) */ +RGFWDEF RGFW_focusfunc RGFW_setFocusCallback(RGFW_focusfunc func); +/*! set callback for a mouse notify event returns previous callback function (if it was set) */ +RGFWDEF RGFW_mouseNotifyfunc RGFW_setMouseNotifyCallBack(RGFW_mouseNotifyfunc func); +/*! set callback for a drop event event returns previous callback function (if it was set) */ +RGFWDEF RGFW_dndfunc RGFW_setDndCallback(RGFW_dndfunc func); +/*! set callback for a start of a drop event returns previous callback function (if it was set) */ +RGFWDEF RGFW_dndInitfunc RGFW_setDndInitCallback(RGFW_dndInitfunc func); +/*! set callback for a key (press / release ) event returns previous callback function (if it was set) */ +RGFWDEF RGFW_keyfunc RGFW_setKeyCallback(RGFW_keyfunc func); +/*! set callback for a mouse button (press / release ) event returns previous callback function (if it was set) */ +RGFWDEF RGFW_mousebuttonfunc RGFW_setMouseButtonCallback(RGFW_mousebuttonfunc func); +/*! set callback for a controller button (press / release ) event returns previous callback function (if it was set) */ +RGFWDEF RGFW_jsButtonfunc RGFW_setjsButtonCallback(RGFW_jsButtonfunc func); +/*! set callback for a joystick axis mov event returns previous callback function (if it was set) */ +RGFWDEF RGFW_jsAxisfunc RGFW_setjsAxisCallback(RGFW_jsAxisfunc func); +/** @} */ + +/** * @defgroup Threads +* @{ */ #ifndef RGFW_NO_THREADS /*! threading functions*/ @@ -851,7 +919,10 @@ RGFWDEF void RGFW_setjsAxisCallback(RGFW_jsAxisfunc func); RGFWDEF void RGFW_setThreadPriority(RGFW_thread thread, u8 priority); /*!< sets the priority priority */ #endif -/*! gamepad/joystick functions (linux-only currently) */ +/** @} */ + +/** * @defgroup joystick +* @{ */ /*! joystick count starts at 0*/ /*!< register joystick to window based on a number (the number is based on when it was connected eg. /dev/js0)*/ @@ -860,27 +931,45 @@ RGFWDEF u16 RGFW_registerJoystickF(RGFW_window* win, char* file); RGFWDEF u32 RGFW_isPressedJS(RGFW_window* win, u16 controller, u8 button); +/** @} */ + +/** * @defgroup graphics_API +* @{ */ + +/*!< make the window the current opengl drawing context + + NOTE: + if you want to switch the graphics context's thread, + you have to run RGFW_window_makeCurrent(NULL); on the old thread + then RGFW_window_makeCurrent(valid_window) on the new thread +*/ +RGFWDEF void RGFW_window_makeCurrent(RGFW_window* win); + +/*< updates fps / sets fps to cap (must by ran manually by the user at the end of a frame), returns current fps */ +RGFWDEF u32 RGFW_window_checkFPS(RGFW_window* win, u32 fpsCap); + /* supports openGL, directX, OSMesa, EGL and software rendering */ -RGFWDEF void RGFW_window_swapBuffers(RGFW_window* win); /* swap the rendering buffer */ +RGFWDEF void RGFW_window_swapBuffers(RGFW_window* win); /*!< swap the rendering buffer */ RGFWDEF void RGFW_window_swapInterval(RGFW_window* win, i32 swapInterval); RGFWDEF void RGFW_window_setGPURender(RGFW_window* win, i8 set); RGFWDEF void RGFW_window_setCPURender(RGFW_window* win, i8 set); /*! native API functions */ -#ifdef RGFW_OPENGL - /*! Get max OpenGL version */ - RGFWDEF u8* RGFW_getMaxGLVersion(void); - /* OpenGL init hints */ - RGFWDEF void RGFW_setGLStencil(i32 stencil); /* set stencil buffer bit size (8 by default) */ - RGFWDEF void RGFW_setGLSamples(i32 samples); /* set number of sampiling buffers (4 by default) */ - RGFWDEF void RGFW_setGLStereo(i32 stereo); /* use GL_STEREO (GL_FALSE by default) */ - RGFWDEF void RGFW_setGLAuxBuffers(i32 auxBuffers); /* number of aux buffers (0 by default) */ +#if defined(RGFW_OPENGL) || defined(RGFW_EGL) + /*! OpenGL init hints */ + RGFWDEF void RGFW_setGLStencil(i32 stencil); /*!< set stencil buffer bit size (8 by default) */ + RGFWDEF void RGFW_setGLSamples(i32 samples); /*!< set number of sampiling buffers (4 by default) */ + RGFWDEF void RGFW_setGLStereo(i32 stereo); /*!< use GL_STEREO (GL_FALSE by default) */ + RGFWDEF void RGFW_setGLAuxBuffers(i32 auxBuffers); /*!< number of aux buffers (0 by default) */ - /*! Set OpenGL version hint */ - RGFWDEF void RGFW_setGLVersion(i32 major, i32 minor); - RGFWDEF void* RGFW_getProcAddress(const char* procname); /* get native opengl proc address */ - RGFWDEF void RGFW_window_makeCurrent_OpenGL(RGFW_window* win); /* to be called by RGFW_window_makeCurrent */ + /*! which profile to use for the opengl verion */ + typedef RGFW_ENUM(u8, RGFW_GL_profile) { RGFW_GL_CORE = 0, RGFW_GL_COMPATIBILITY }; + /*! Set OpenGL version hint (core or compatibility profile)*/ + RGFWDEF void RGFW_setGLVersion(RGFW_GL_profile profile, i32 major, i32 minor); + RGFWDEF void RGFW_setDoubleBuffer(b8 useDoubleBuffer); + RGFWDEF void* RGFW_getProcAddress(const char* procname); /*!< get native opengl proc address */ + RGFWDEF void RGFW_window_makeCurrent_OpenGL(RGFW_window* win); /*!< to be called by RGFW_window_makeCurrent */ #elif defined(RGFW_DIRECTX) typedef struct { IDXGIFactory* pFactory; @@ -896,13 +985,15 @@ RGFWDEF void RGFW_window_setCPURender(RGFW_window* win, i8 set); RGFWDEF RGFW_directXinfo* RGFW_getDirectXInfo(void); #endif -/*! Supporting functions */ -RGFWDEF void RGFW_window_checkFPS(RGFW_window* win); /*!< updates fps / sets fps to cap (ran by RGFW_window_checkEvent)*/ -RGFWDEF u64 RGFW_getTime(void); /* get time in seconds */ -RGFWDEF u64 RGFW_getTimeNS(void); /* get time in nanoseconds */ -RGFWDEF void RGFW_sleep(u64 milisecond); /* sleep for a set time */ +/** @} */ -/* +/** * @defgroup Supporting +* @{ */ +RGFWDEF u64 RGFW_getTime(void); /*!< get time in seconds */ +RGFWDEF u64 RGFW_getTimeNS(void); /*!< get time in nanoseconds */ +RGFWDEF void RGFW_sleep(u64 milisecond); /*!< sleep for a set time */ + +/*! key codes and mouse icon enums */ @@ -1019,6 +1110,7 @@ typedef RGFW_ENUM(u8, RGFW_Key) { final_key, }; + typedef RGFW_ENUM(u8, RGFW_mouseIcons) { RGFW_MOUSE_NORMAL = 0, RGFW_MOUSE_ARROW, @@ -1033,6 +1125,8 @@ typedef RGFW_ENUM(u8, RGFW_mouseIcons) { RGFW_MOUSE_NOT_ALLOWED, }; +/** @} */ + #endif /* RGFW_HEADER */ /* @@ -1092,15 +1186,18 @@ int main() { */ #ifdef RGFW_X11 - #define RGFW_OS_BASED_VALUE(l, w, m, a) l + #define RGFW_OS_BASED_VALUE(l, w, m, h, ww) l #elif defined(RGFW_WINDOWS) - #define RGFW_OS_BASED_VALUE(l, w, m, a) w + #define RGFW_OS_BASED_VALUE(l, w, m, h, ww) w #elif defined(RGFW_MACOS) - #define RGFW_OS_BASED_VALUE(l, w, m, a) m + #define RGFW_OS_BASED_VALUE(l, w, m, h, ww) m #elif defined(RGFW_WEBASM) - #define RGFW_OS_BASED_VALUE(l, w, m, a) a + #define RGFW_OS_BASED_VALUE(l, w, m, h, ww) h +#elif defined(RGFW_WAYLAND) + #define RGFW_OS_BASED_VALUE(l, w, m, h, ww) ww #endif + #ifdef RGFW_IMPLEMENTATION #include @@ -1119,120 +1216,147 @@ This is the start of keycode data MacOS -> windows and linux already don't have keycodes as macros, so there's no point */ -u8 RGFW_keycodes[] = { - [RGFW_OS_BASED_VALUE(49, 192, 50, DOM_VK_BACK_QUOTE)] = RGFW_Backtick, - [RGFW_OS_BASED_VALUE(19, 0x30, 29, DOM_VK_0)] = RGFW_0, - [RGFW_OS_BASED_VALUE(10, 0x31, 18, DOM_VK_1)] = RGFW_1, - [RGFW_OS_BASED_VALUE(11, 0x32, 19, DOM_VK_2)] = RGFW_2, - [RGFW_OS_BASED_VALUE(12, 0x33, 20, DOM_VK_3)] = RGFW_3, - [RGFW_OS_BASED_VALUE(13, 0x34, 21, DOM_VK_4)] = RGFW_4, - [RGFW_OS_BASED_VALUE(14, 0x35, 23, DOM_VK_5)] = RGFW_5, - [RGFW_OS_BASED_VALUE(15, 0x36, 22, DOM_VK_6)] = RGFW_6, - [RGFW_OS_BASED_VALUE(16, 0x37, 26, DOM_VK_7)] = RGFW_7, - [RGFW_OS_BASED_VALUE(17, 0x38, 28, DOM_VK_8)] = RGFW_8, - [RGFW_OS_BASED_VALUE(18, 0x39, 25, DOM_VK_9)] = RGFW_9, - [RGFW_OS_BASED_VALUE(65, 0x20, 49, DOM_VK_SPACE)] = RGFW_Space, +/* + the c++ compiler doesn't support setting up an array like, + we'll have to do it during runtime using a function & this messy setup +*/ +#ifndef __cplusplus +#define RGFW_NEXT , +#define RGFW_MAP +#else +#define RGFW_NEXT ; +#define RGFW_MAP RGFW_keycodes +#endif - [RGFW_OS_BASED_VALUE(38, 0x41, 0, DOM_VK_A)] = RGFW_a, - [RGFW_OS_BASED_VALUE(56, 0x42, 11, DOM_VK_B)] = RGFW_b, - [RGFW_OS_BASED_VALUE(54, 0x43, 8, DOM_VK_C)] = RGFW_c, - [RGFW_OS_BASED_VALUE(40, 0x44, 2, DOM_VK_D)] = RGFW_d, - [RGFW_OS_BASED_VALUE(26, 0x45, 14, DOM_VK_E)] = RGFW_e, - [RGFW_OS_BASED_VALUE(41, 0x46, 3, DOM_VK_F)] = RGFW_f, - [RGFW_OS_BASED_VALUE(42, 0x47, 5, DOM_VK_G)] = RGFW_g, - [RGFW_OS_BASED_VALUE(43, 0x48, 4, DOM_VK_H)] = RGFW_h, - [RGFW_OS_BASED_VALUE(31, 0x49, 34, DOM_VK_I)] = RGFW_i, - [RGFW_OS_BASED_VALUE(44, 0x4A, 38, DOM_VK_J)] = RGFW_j, - [RGFW_OS_BASED_VALUE(45, 0x4B, 40, DOM_VK_K)] = RGFW_k, - [RGFW_OS_BASED_VALUE(46, 0x4C, 37, DOM_VK_L)] = RGFW_l, - [RGFW_OS_BASED_VALUE(58, 0x4D, 46, DOM_VK_M)] = RGFW_m, - [RGFW_OS_BASED_VALUE(57, 0x4E, 45, DOM_VK_N)] = RGFW_n, - [RGFW_OS_BASED_VALUE(32, 0x4F, 31, DOM_VK_O)] = RGFW_o, - [RGFW_OS_BASED_VALUE(33, 0x50, 35, DOM_VK_P)] = RGFW_p, - [RGFW_OS_BASED_VALUE(24, 0x51, 12, DOM_VK_Q)] = RGFW_q, - [RGFW_OS_BASED_VALUE(27, 0x52, 15, DOM_VK_R)] = RGFW_r, - [RGFW_OS_BASED_VALUE(39, 0x53, 1, DOM_VK_S)] = RGFW_s, - [RGFW_OS_BASED_VALUE(28, 0x54, 17, DOM_VK_T)] = RGFW_t, - [RGFW_OS_BASED_VALUE(30, 0x55, 32, DOM_VK_U)] = RGFW_u, - [RGFW_OS_BASED_VALUE(55, 0x56, 9, DOM_VK_V)] = RGFW_v, - [RGFW_OS_BASED_VALUE(25, 0x57, 13, DOM_VK_W)] = RGFW_w, - [RGFW_OS_BASED_VALUE(53, 0x58, 7, DOM_VK_X)] = RGFW_x, - [RGFW_OS_BASED_VALUE(29, 0x59, 16, DOM_VK_Y)] = RGFW_y, - [RGFW_OS_BASED_VALUE(52, 0x5A, 6, DOM_VK_Z)] = RGFW_z, +#ifdef RGFW_WAYLAND +#include +#endif - [RGFW_OS_BASED_VALUE(60, 190, 47, DOM_VK_PERIOD)] = RGFW_Period, - [RGFW_OS_BASED_VALUE(59, 188, 43, DOM_VK_COMMA)] = RGFW_Comma, - [RGFW_OS_BASED_VALUE(61, 191, 44, DOM_VK_SLASH)] = RGFW_Slash, - [RGFW_OS_BASED_VALUE(34, 219, 33, DOM_VK_OPEN_BRACKET)] = RGFW_Bracket, - [RGFW_OS_BASED_VALUE(35, 221, 30, DOM_VK_CLOSE_BRACKET)] = RGFW_CloseBracket, - [RGFW_OS_BASED_VALUE(47, 186, 41, DOM_VK_SEMICOLON)] = RGFW_Semicolon, - [RGFW_OS_BASED_VALUE(48, 222, 39, DOM_VK_QUOTE)] = RGFW_Quote, - [RGFW_OS_BASED_VALUE(51, 322, 42, DOM_VK_BACK_SLASH)] = RGFW_BackSlash, +u8 RGFW_keycodes [RGFW_OS_BASED_VALUE(136, 337, 128, DOM_VK_WIN_OEM_CLEAR + 1, 130)] = { +#ifdef __cplusplus + 0 +}; +void RGFW_init_keys(void) { +#endif + RGFW_MAP [RGFW_OS_BASED_VALUE(49, 192, 50, DOM_VK_BACK_QUOTE, KEY_GRAVE)] = RGFW_Backtick RGFW_NEXT + + RGFW_MAP [RGFW_OS_BASED_VALUE(19, 0x30, 29, DOM_VK_0, KEY_0)] = RGFW_0 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(10, 0x31, 18, DOM_VK_1, KEY_1)] = RGFW_1 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(11, 0x32, 19, DOM_VK_2, KEY_2)] = RGFW_2 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(12, 0x33, 20, DOM_VK_3, KEY_3)] = RGFW_3 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(13, 0x34, 21, DOM_VK_4, KEY_4)] = RGFW_4 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(14, 0x35, 23, DOM_VK_5, KEY_5)] = RGFW_5 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(15, 0x36, 22, DOM_VK_6, KEY_6)] = RGFW_6 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(16, 0x37, 26, DOM_VK_7, KEY_7)] = RGFW_7 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(17, 0x38, 28, DOM_VK_8, KEY_8)] = RGFW_8 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(18, 0x39, 25, DOM_VK_9, KEY_9)] = RGFW_9, + + RGFW_MAP [RGFW_OS_BASED_VALUE(65, 0x20, 49, DOM_VK_SPACE, KEY_SPACE)] = RGFW_Space, + + RGFW_MAP [RGFW_OS_BASED_VALUE(38, 0x41, 0, DOM_VK_A, KEY_A)] = RGFW_a RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(56, 0x42, 11, DOM_VK_B, KEY_B)] = RGFW_b RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(54, 0x43, 8, DOM_VK_C, KEY_C)] = RGFW_c RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(40, 0x44, 2, DOM_VK_D, KEY_D)] = RGFW_d RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(26, 0x45, 14, DOM_VK_E, KEY_E)] = RGFW_e RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(41, 0x46, 3, DOM_VK_F, KEY_F)] = RGFW_f RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(42, 0x47, 5, DOM_VK_G, KEY_G)] = RGFW_g RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(43, 0x48, 4, DOM_VK_H, KEY_H)] = RGFW_h RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(31, 0x49, 34, DOM_VK_I, KEY_I)] = RGFW_i RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(44, 0x4A, 38, DOM_VK_J, KEY_J)] = RGFW_j RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(45, 0x4B, 40, DOM_VK_K, KEY_K)] = RGFW_k RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(46, 0x4C, 37, DOM_VK_L, KEY_L)] = RGFW_l RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(58, 0x4D, 46, DOM_VK_M, KEY_M)] = RGFW_m RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(57, 0x4E, 45, DOM_VK_N, KEY_N)] = RGFW_n RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(32, 0x4F, 31, DOM_VK_O, KEY_O)] = RGFW_o RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(33, 0x50, 35, DOM_VK_P, KEY_P)] = RGFW_p RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(24, 0x51, 12, DOM_VK_Q, KEY_Q)] = RGFW_q RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(27, 0x52, 15, DOM_VK_R, KEY_R)] = RGFW_r RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(39, 0x53, 1, DOM_VK_S, KEY_S)] = RGFW_s RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(28, 0x54, 17, DOM_VK_T, KEY_T)] = RGFW_t RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(30, 0x55, 32, DOM_VK_U, KEY_U)] = RGFW_u RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(55, 0x56, 9, DOM_VK_V, KEY_V)] = RGFW_v RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(25, 0x57, 13, DOM_VK_W, KEY_W)] = RGFW_w RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(53, 0x58, 7, DOM_VK_X, KEY_X)] = RGFW_x RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(29, 0x59, 16, DOM_VK_Y, KEY_Y)] = RGFW_y RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(52, 0x5A, 6, DOM_VK_Z, KEY_Z)] = RGFW_z, + + RGFW_MAP [RGFW_OS_BASED_VALUE(60, 190, 47, DOM_VK_PERIOD, KEY_DOT)] = RGFW_Period RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(59, 188, 43, DOM_VK_COMMA, KEY_COMMA)] = RGFW_Comma RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(61, 191, 44, DOM_VK_SLASH, KEY_SLASH)] = RGFW_Slash RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(34, 219, 33, DOM_VK_OPEN_BRACKET, KEY_LEFTBRACE)] = RGFW_Bracket RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(35, 221, 30, DOM_VK_CLOSE_BRACKET, KEY_RIGHTBRACE)] = RGFW_CloseBracket RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(47, 186, 41, DOM_VK_SEMICOLON, KEY_SEMICOLON)] = RGFW_Semicolon RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(48, 222, 39, DOM_VK_QUOTE, KEY_APOSTROPHE)] = RGFW_Quote RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(51, 322, 42, DOM_VK_BACK_SLASH, KEY_BACKSLASH)] = RGFW_BackSlash, - [RGFW_OS_BASED_VALUE(36, 0x0D, 36, DOM_VK_RETURN)] = RGFW_Return, - [RGFW_OS_BASED_VALUE(119, 0x2E, 118, DOM_VK_DELETE)] = RGFW_Delete, - [RGFW_OS_BASED_VALUE(77, 0x90, 72, DOM_VK_NUM_LOCK)] = RGFW_Numlock, - [RGFW_OS_BASED_VALUE(106, 0x6F, 82, DOM_VK_DIVIDE)] = RGFW_KP_Slash, - [RGFW_OS_BASED_VALUE(63, 0x6A, 76, DOM_VK_MULTIPLY)] = RGFW_Multiply, - [RGFW_OS_BASED_VALUE(82, 0x6D, 67, DOM_VK_SUBTRACT)] = RGFW_KP_Minus, - [RGFW_OS_BASED_VALUE(87, 0x61, 84, DOM_VK_NUMPAD1)] = RGFW_KP_1, - [RGFW_OS_BASED_VALUE(88, 0x62, 85, DOM_VK_NUMPAD2)] = RGFW_KP_2, - [RGFW_OS_BASED_VALUE(89, 0x63, 86, DOM_VK_NUMPAD3)] = RGFW_KP_3, - [RGFW_OS_BASED_VALUE(83, 0x64, 87, DOM_VK_NUMPAD4)] = RGFW_KP_4, - [RGFW_OS_BASED_VALUE(84, 0x65, 88, DOM_VK_NUMPAD5)] = RGFW_KP_5, - [RGFW_OS_BASED_VALUE(85, 0x66, 89, DOM_VK_NUMPAD6)] = RGFW_KP_6, - [RGFW_OS_BASED_VALUE(79, 0x67, 90, DOM_VK_NUMPAD7)] = RGFW_KP_7, - [RGFW_OS_BASED_VALUE(80, 0x68, 92, DOM_VK_NUMPAD8)] = RGFW_KP_8, - [RGFW_OS_BASED_VALUE(81, 0x69, 93, DOM_VK_NUMPAD9)] = RGFW_KP_9, - [RGFW_OS_BASED_VALUE(90, 0x60, 83, DOM_VK_NUMPAD0)] = RGFW_KP_0, - [RGFW_OS_BASED_VALUE(91, 0x6E, 65, DOM_VK_DECIMAL)] = RGFW_KP_Period, - [RGFW_OS_BASED_VALUE(104, 0x92, 77, 0)] = RGFW_KP_Return, + RGFW_MAP [RGFW_OS_BASED_VALUE(36, 0x0D, 36, DOM_VK_RETURN, KEY_ENTER)] = RGFW_Return RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(119, 0x2E, 118, DOM_VK_DELETE, KEY_DELETE)] = RGFW_Delete RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(77, 0x90, 72, DOM_VK_NUM_LOCK, KEY_NUMLOCK)] = RGFW_Numlock RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(106, 0x6F, 82, DOM_VK_DIVIDE, KEY_KPSLASH)] = RGFW_KP_Slash RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(63, 0x6A, 76, DOM_VK_MULTIPLY, KEY_KPASTERISK)] = RGFW_Multiply RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(82, 0x6D, 67, DOM_VK_SUBTRACT, KEY_KPMINUS)] = RGFW_KP_Minus RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(87, 0x61, 84, DOM_VK_NUMPAD1, KEY_KP1)] = RGFW_KP_1 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(88, 0x62, 85, DOM_VK_NUMPAD2, KEY_KP2)] = RGFW_KP_2 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(89, 0x63, 86, DOM_VK_NUMPAD3, KEY_KP3)] = RGFW_KP_3 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(83, 0x64, 87, DOM_VK_NUMPAD4, KEY_KP4)] = RGFW_KP_4 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(84, 0x65, 88, DOM_VK_NUMPAD5, KEY_KP5)] = RGFW_KP_5 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(85, 0x66, 89, DOM_VK_NUMPAD6, KEY_KP6)] = RGFW_KP_6 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(79, 0x67, 90, DOM_VK_NUMPAD7, KEY_KP7)] = RGFW_KP_7 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(80, 0x68, 92, DOM_VK_NUMPAD8, KEY_KP8)] = RGFW_KP_8 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(81, 0x69, 93, DOM_VK_NUMPAD9, KEY_KP9)] = RGFW_KP_9 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(90, 0x60, 83, DOM_VK_NUMPAD0, KEY_KP0)] = RGFW_KP_0 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(91, 0x6E, 65, DOM_VK_DECIMAL, KEY_KPDOT)] = RGFW_KP_Period RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(104, 0x92, 77, 0, KEY_KPENTER)] = RGFW_KP_Return, - [RGFW_OS_BASED_VALUE(20, 189, 27, DOM_VK_HYPHEN_MINUS)] = RGFW_Minus, - [RGFW_OS_BASED_VALUE(21, 187, 24, DOM_VK_EQUALS)] = RGFW_Equals, - [RGFW_OS_BASED_VALUE(22, 8, 51, DOM_VK_BACK_SPACE)] = RGFW_BackSpace, - [RGFW_OS_BASED_VALUE(23, 0x09, 48, DOM_VK_TAB)] = RGFW_Tab, - [RGFW_OS_BASED_VALUE(66, 20, 57, DOM_VK_CAPS_LOCK)] = RGFW_CapsLock, - [RGFW_OS_BASED_VALUE(50, 0xA0, 56, DOM_VK_SHIFT)] = RGFW_ShiftL, - [RGFW_OS_BASED_VALUE(37, 0x11, 59, DOM_VK_CONTROL)] = RGFW_ControlL, - [RGFW_OS_BASED_VALUE(64, 164, 58, DOM_VK_ALT)] = RGFW_AltL, - [RGFW_OS_BASED_VALUE(133, 0x5B, 55, DOM_VK_WIN)] = RGFW_SuperL, + RGFW_MAP [RGFW_OS_BASED_VALUE(20, 189, 27, DOM_VK_HYPHEN_MINUS, KEY_MINUS)] = RGFW_Minus RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(21, 187, 24, DOM_VK_EQUALS, KEY_EQUAL)] = RGFW_Equals RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(22, 8, 51, DOM_VK_BACK_SPACE, KEY_BACKSPACE)] = RGFW_BackSpace RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(23, 0x09, 48, DOM_VK_TAB, KEY_TAB)] = RGFW_Tab RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(66, 20, 57, DOM_VK_CAPS_LOCK, KEY_CAPSLOCK)] = RGFW_CapsLock RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(50, 0x10, 56, DOM_VK_SHIFT, KEY_LEFTSHIFT)] = RGFW_ShiftL RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(37, 0x11, 59, DOM_VK_CONTROL, KEY_LEFTCTRL)] = RGFW_ControlL RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(64,0x12, 58, DOM_VK_ALT, KEY_LEFTALT)] = RGFW_AltL RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(133, 0x5B, 55, DOM_VK_WIN, KEY_LEFTMETA)] = RGFW_SuperL, #if !defined(RGFW_WINDOWS) && !defined(RGFW_MACOS) && !defined(RGFW_WEBASM) - [RGFW_OS_BASED_VALUE(105, 0x11, 59, 0)] = RGFW_ControlR, - [RGFW_OS_BASED_VALUE(135, 0xA4, 55, 0)] = RGFW_SuperR, + RGFW_MAP [RGFW_OS_BASED_VALUE(105, 0x11, 59, 0, KEY_RIGHTCTRL)] = RGFW_ControlR RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(135, 0xA4, 55, 0, KEY_RIGHTMETA)] = RGFW_SuperR, + RGFW_MAP [RGFW_OS_BASED_VALUE(62, 0x5C, 56, 0, KEY_RIGHTSHIFT)] = RGFW_ShiftR RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(108, 165, 58, 0, KEY_RIGHTALT)] = RGFW_AltR, #endif - #if !defined(RGFW_MACOS) && !defined(RGFW_WEBASM) - [RGFW_OS_BASED_VALUE(62, 0x5C, 56, 0)] = RGFW_ShiftR, - [RGFW_OS_BASED_VALUE(108, 165, 58, 0)] = RGFW_AltR, - #endif - - [RGFW_OS_BASED_VALUE(67, 0x70, 127, DOM_VK_F1)] = RGFW_F1, - [RGFW_OS_BASED_VALUE(68, 0x71, 121, DOM_VK_F2)] = RGFW_F2, - [RGFW_OS_BASED_VALUE(69, 0x72, 100, DOM_VK_F3)] = RGFW_F3, - [RGFW_OS_BASED_VALUE(70, 0x73, 119, DOM_VK_F4)] = RGFW_F4, - [RGFW_OS_BASED_VALUE(71, 0x74, 97, DOM_VK_F5)] = RGFW_F5, - [RGFW_OS_BASED_VALUE(72, 0x75, 98, DOM_VK_F6)] = RGFW_F6, - [RGFW_OS_BASED_VALUE(73, 0x76, 99, DOM_VK_F7)] = RGFW_F7, - [RGFW_OS_BASED_VALUE(74, 0x77, 101, DOM_VK_F8)] = RGFW_F8, - [RGFW_OS_BASED_VALUE(75, 0x78, 102, DOM_VK_F9)] = RGFW_F9, - [RGFW_OS_BASED_VALUE(76, 0x79, 110, DOM_VK_F10)] = RGFW_F10, - [RGFW_OS_BASED_VALUE(95, 0x7A, 104, DOM_VK_F11)] = RGFW_F11, - [RGFW_OS_BASED_VALUE(96, 0x7B, 112, DOM_VK_F12)] = RGFW_F12, - [RGFW_OS_BASED_VALUE(111, 0x26, 126, DOM_VK_UP)] = RGFW_Up, - [RGFW_OS_BASED_VALUE(116, 0x28, 125, DOM_VK_DOWN)] = RGFW_Down, - [RGFW_OS_BASED_VALUE(113, 0x25, 123, DOM_VK_LEFT)] = RGFW_Left, - [RGFW_OS_BASED_VALUE(114, 0x27, 124, DOM_VK_RIGHT)] = RGFW_Right, - [RGFW_OS_BASED_VALUE(118, 0x2D, 115, DOM_VK_INSERT)] = RGFW_Insert, - [RGFW_OS_BASED_VALUE(115, 0x23, 120, DOM_VK_END)] = RGFW_End, - [RGFW_OS_BASED_VALUE(112, 336, 117, DOM_VK_PAGE_UP)] = RGFW_PageUp, - [RGFW_OS_BASED_VALUE(117, 325, 122, DOM_VK_PAGE_DOWN)] = RGFW_PageDown, - [RGFW_OS_BASED_VALUE(9, 0x1B, 53, DOM_VK_ESCAPE)] = RGFW_Escape, - [RGFW_OS_BASED_VALUE(110, 0x24, 116, DOM_VK_HOME)] = RGFW_Home, + RGFW_MAP [RGFW_OS_BASED_VALUE(67, 0x70, 127, DOM_VK_F1, KEY_F1)] = RGFW_F1 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(68, 0x71, 121, DOM_VK_F2, KEY_F2)] = RGFW_F2 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(69, 0x72, 100, DOM_VK_F3, KEY_F3)] = RGFW_F3 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(70, 0x73, 119, DOM_VK_F4, KEY_F4)] = RGFW_F4 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(71, 0x74, 97, DOM_VK_F5, KEY_F5)] = RGFW_F5 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(72, 0x75, 98, DOM_VK_F6, KEY_F6)] = RGFW_F6 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(73, 0x76, 99, DOM_VK_F7, KEY_F7)] = RGFW_F7 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(74, 0x77, 101, DOM_VK_F8, KEY_F8)] = RGFW_F8 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(75, 0x78, 102, DOM_VK_F9, KEY_F9)] = RGFW_F9 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(76, 0x79, 110, DOM_VK_F10, KEY_F10)] = RGFW_F10 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(95, 0x7A, 104, DOM_VK_F11, KEY_F11)] = RGFW_F11 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(96, 0x7B, 112, DOM_VK_F12, KEY_F12)] = RGFW_F12 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(111, 0x26, 126, DOM_VK_UP, KEY_UP)] = RGFW_Up RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(116, 0x28, 125, DOM_VK_DOWN, KEY_DOWN)] = RGFW_Down RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(113, 0x25, 123, DOM_VK_LEFT, KEY_LEFT)] = RGFW_Left RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(114, 0x27, 124, DOM_VK_RIGHT, KEY_RIGHT)] = RGFW_Right RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(118, 0x2D, 115, DOM_VK_INSERT, KEY_INSERT)] = RGFW_Insert RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(115, 0x23, 120, DOM_VK_END, KEY_END)] = RGFW_End RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(112, 336, 117, DOM_VK_PAGE_UP, KEY_PAGEUP)] = RGFW_PageUp RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(117, 325, 122, DOM_VK_PAGE_DOWN, KEY_PAGEDOWN)] = RGFW_PageDown RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(9, 0x1B, 53, DOM_VK_ESCAPE, KEY_ESC)] = RGFW_Escape RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(110, 0x24, 116, DOM_VK_HOME, KEY_HOME)] = RGFW_Home RGFW_NEXT +#ifndef __cplusplus }; +#else +} +#endif + +#undef RGFW_NEXT +#undef RGFW_MAP typedef struct { b8 current : 1; @@ -1244,6 +1368,12 @@ RGFW_keyState RGFW_keyboard[final_key] = { {0, 0} }; RGFWDEF u32 RGFW_apiKeyCodeToRGFW(u32 keycode); u32 RGFW_apiKeyCodeToRGFW(u32 keycode) { + #ifdef __cplusplus + if (RGFW_OS_BASED_VALUE(49, 192, 50, DOM_VK_BACK_QUOTE, KEY_GRAVE) != RGFW_Backtick) { + RGFW_init_keys(); + } + #endif + /* make sure the key isn't out of bounds */ if (keycode > sizeof(RGFW_keycodes) / sizeof(u8)) return 0; @@ -1253,22 +1383,54 @@ u32 RGFW_apiKeyCodeToRGFW(u32 keycode) { RGFWDEF void RGFW_resetKey(void); void RGFW_resetKey(void) { - size_t len = final_key; /* last_key == length */ + size_t len = final_key; /*!< last_key == length */ - size_t i; /* reset each previous state */ + size_t i; /*!< reset each previous state */ for (i = 0; i < len; i++) RGFW_keyboard[i].prev = 0; } +b8 RGFW_shouldShift(u32 keycode, u8 lockState) { + #define RGFW_xor(x, y) (( (x) && (!(y)) ) || ((y) && (!(x)) )) + b8 caps4caps = (lockState & RGFW_CAPSLOCK) && ((keycode >= RGFW_a) && (keycode <= RGFW_z)); + b8 shouldShift = RGFW_xor((RGFW_isPressed(NULL, RGFW_ShiftL) || RGFW_isPressed(NULL, RGFW_ShiftR)), caps4caps); + #undef RGFW_xor + + return shouldShift; +} + +char RGFW_keyCodeToChar(u32 keycode, b8 shift) { + static const char map[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '`', '0', '1', '2', '3', '4', '5', '6', '7', '8', + '9', '-', '=', 0, '\t', 0, 0, 0, 0, 0, 0, 0, 0, 0, ' ', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', + 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '.', ',', '/', '[', ']', ';', '\n', '\'', '\\', + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '/', '*', '-', '1', '2', '3', '3', '5', '6', '7', '8', '9', '0', '\n' + }; + + static const char mapCaps[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '~', ')', '!', '@', '#', '$', '%', '^', '&', '*', + '(', '_', '+', 0, '0', 0, 0, 0, 0, 0, 0, 0, 0, 0, ' ', 'A', 'B', 'C', 'D', 'E', 'F', 'G', + 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', + 'X', 'Y', 'Z', '>', '<', '?', '{', '}', ':', '\n', '"', '|', + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '?', '*', '-', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + + if (shift == RGFW_FALSE) + return map[keycode]; + return mapCaps[keycode]; +} + +char RGFW_keyCodeToCharAuto(u32 keycode, u8 lockState) { return RGFW_keyCodeToChar(keycode, RGFW_shouldShift(keycode, lockState)); } + /* this is the end of keycode data */ /* joystick data */ -u8 RGFW_jsPressed[4][16]; /* if a key is currently pressed or not (per joystick) */ +u8 RGFW_jsPressed[4][16]; /*!< if a key is currently pressed or not (per joystick) */ -i32 RGFW_joysticks[4]; /* limit of 4 joysticks at a time */ -u16 RGFW_joystickCount; /* the actual amount of joysticks */ +i32 RGFW_joysticks[4]; /*!< limit of 4 joysticks at a time */ +u16 RGFW_joystickCount; /*!< the actual amount of joysticks */ /* event callback defines start here @@ -1325,19 +1487,73 @@ void RGFW_window_checkEvents(RGFW_window* win, i32 waitMS) { #endif } -void RGFW_setWindowMoveCallback(RGFW_windowmovefunc func) { RGFW_windowMoveCallback = func; } -void RGFW_setWindowResizeCallback(RGFW_windowresizefunc func) { RGFW_windowResizeCallback = func; } -void RGFW_setWindowQuitCallback(RGFW_windowquitfunc func) { RGFW_windowQuitCallback = func; } -void RGFW_setMousePosCallback(RGFW_mouseposfunc func) { RGFW_mousePosCallback = func; } -void RGFW_setWindowRefreshCallback(RGFW_windowrefreshfunc func) { RGFW_windowRefreshCallback = func; } -void RGFW_setFocusCallback(RGFW_focusfunc func) { RGFW_focusCallback = func; } -void RGFW_setMouseNotifyCallBack(RGFW_mouseNotifyfunc func) { RGFW_mouseNotifyCallBack = func; } -void RGFW_setDndCallback(RGFW_dndfunc func) { RGFW_dndCallback = func; } -void RGFW_setDndInitCallback(RGFW_dndInitfunc func) { RGFW_dndInitCallback = func; } -void RGFW_setKeyCallback(RGFW_keyfunc func) { RGFW_keyCallback = func; } -void RGFW_setMouseButtonCallback(RGFW_mousebuttonfunc func) { RGFW_mouseButtonCallback = func; } -void RGFW_setjsButtonCallback(RGFW_jsButtonfunc func) { RGFW_jsButtonCallback = func; } -void RGFW_setjsAxisCallback(RGFW_jsAxisfunc func) { RGFW_jsAxisCallback = func; } +RGFW_windowmovefunc RGFW_setWindowMoveCallback(RGFW_windowmovefunc func) { + RGFW_windowmovefunc prev = (RGFW_windowMoveCallback == RGFW_windowmovefuncEMPTY) ? NULL : RGFW_windowMoveCallback; + RGFW_windowMoveCallback = func; + return prev; +} +RGFW_windowresizefunc RGFW_setWindowResizeCallback(RGFW_windowresizefunc func) { + RGFW_windowresizefunc prev = (RGFW_windowResizeCallback == RGFW_windowresizefuncEMPTY) ? NULL : RGFW_windowResizeCallback; + RGFW_windowResizeCallback = func; + return prev; +} +RGFW_windowquitfunc RGFW_setWindowQuitCallback(RGFW_windowquitfunc func) { + RGFW_windowquitfunc prev = (RGFW_windowQuitCallback == RGFW_windowquitfuncEMPTY) ? NULL : RGFW_windowQuitCallback; + RGFW_windowQuitCallback = func; + return prev; +} + +RGFW_mouseposfunc RGFW_setMousePosCallback(RGFW_mouseposfunc func) { + RGFW_mouseposfunc prev = (RGFW_mousePosCallback == RGFW_mouseposfuncEMPTY) ? NULL : RGFW_mousePosCallback; + RGFW_mousePosCallback = func; + return prev; +} +RGFW_windowrefreshfunc RGFW_setWindowRefreshCallback(RGFW_windowrefreshfunc func) { + RGFW_windowrefreshfunc prev = (RGFW_windowRefreshCallback == RGFW_windowrefreshfuncEMPTY) ? NULL : RGFW_windowRefreshCallback; + RGFW_windowRefreshCallback = func; + return prev; +} +RGFW_focusfunc RGFW_setFocusCallback(RGFW_focusfunc func) { + RGFW_focusfunc prev = (RGFW_focusCallback == RGFW_focusfuncEMPTY) ? NULL : RGFW_focusCallback; + RGFW_focusCallback = func; + return prev; +} + +RGFW_mouseNotifyfunc RGFW_setMouseNotifyCallBack(RGFW_mouseNotifyfunc func) { + RGFW_mouseNotifyfunc prev = (RGFW_mouseNotifyCallBack == RGFW_mouseNotifyfuncEMPTY) ? NULL : RGFW_mouseNotifyCallBack; + RGFW_mouseNotifyCallBack = func; + return prev; +} +RGFW_dndfunc RGFW_setDndCallback(RGFW_dndfunc func) { + RGFW_dndfunc prev = (RGFW_dndCallback == RGFW_dndfuncEMPTY) ? NULL : RGFW_dndCallback; + RGFW_dndCallback = func; + return prev; +} +RGFW_dndInitfunc RGFW_setDndInitCallback(RGFW_dndInitfunc func) { + RGFW_dndInitfunc prev = (RGFW_dndInitCallback == RGFW_dndInitfuncEMPTY) ? NULL : RGFW_dndInitCallback; + RGFW_dndInitCallback = func; + return prev; +} +RGFW_keyfunc RGFW_setKeyCallback(RGFW_keyfunc func) { + RGFW_keyfunc prev = (RGFW_keyCallback == RGFW_keyfuncEMPTY) ? NULL : RGFW_keyCallback; + RGFW_keyCallback = func; + return prev; +} +RGFW_mousebuttonfunc RGFW_setMouseButtonCallback(RGFW_mousebuttonfunc func) { + RGFW_mousebuttonfunc prev = (RGFW_mouseButtonCallback == RGFW_mousebuttonfuncEMPTY) ? NULL : RGFW_mouseButtonCallback; + RGFW_mouseButtonCallback = func; + return prev; +} +RGFW_jsButtonfunc RGFW_setjsButtonCallback(RGFW_jsButtonfunc func) { + RGFW_jsButtonfunc prev = (RGFW_jsButtonCallback == RGFW_jsButtonfuncEMPTY) ? NULL : RGFW_jsButtonCallback; + RGFW_jsButtonCallback = func; + return prev; +} +RGFW_jsAxisfunc RGFW_setjsAxisCallback(RGFW_jsAxisfunc func) { + RGFW_jsAxisfunc prev = (RGFW_jsAxisCallback == RGFW_jsAxisfuncEMPTY) ? NULL : RGFW_jsAxisCallback; + RGFW_jsAxisCallback = func; + return prev; +} /* no more event call back defines */ @@ -1368,7 +1584,7 @@ RGFWDEF RGFW_window* RGFW_window_basic_init(RGFW_rect rect, u16 args); /* do a basic initialization for RGFW_window, this is to standard it for each OS */ RGFW_window* RGFW_window_basic_init(RGFW_rect rect, u16 args) { - RGFW_window* win = (RGFW_window*) RGFW_MALLOC(sizeof(RGFW_window)); /* make a new RGFW struct */ + RGFW_window* win = (RGFW_window*) RGFW_MALLOC(sizeof(RGFW_window)); /*!< make a new RGFW struct */ /* clear out dnd info */ #ifdef RGFW_ALLOC_DROPFILES @@ -1386,7 +1602,7 @@ RGFW_window* RGFW_window_basic_init(RGFW_rect rect, u16 args) { assert(win->src.display != NULL); Screen* scrn = DefaultScreenOfDisplay((Display*)win->src.display); - RGFW_area screenR = RGFW_AREA(scrn->width, scrn->height); + RGFW_area screenR = RGFW_AREA((u32)scrn->width, (u32)scrn->height); #endif /* rect based the requested args */ @@ -1398,7 +1614,6 @@ RGFW_window* RGFW_window_basic_init(RGFW_rect rect, u16 args) { /* set and init the new window's data */ win->r = rect; - win->fpsCap = 0; win->event.inFocus = 1; win->event.droppedFilesCount = 0; RGFW_joystickCount = 0; @@ -1424,7 +1639,7 @@ RGFW_window* RGFW_root = NULL; void RGFW_clipboardFree(char* str) { RGFW_FREE(str); } -RGFW_keyState RGFW_mouseButtons[5] = { 0 }; +RGFW_keyState RGFW_mouseButtons[5] = { {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0} }; b8 RGFW_isMousePressed(RGFW_window* win, u8 button) { assert(win != NULL); @@ -1461,20 +1676,28 @@ b8 RGFW_isReleased(RGFW_window* win, u8 key) { return (!RGFW_isPressed(win, key) && RGFW_wasPressed(win, key)); } -void RGFW_window_makeCurrent(RGFW_window* win) { - assert(win != NULL); +#if defined(RGFW_WINDOWS) && defined(RGFW_DIRECTX) /* defines for directX context*/ + RGFW_directXinfo RGFW_dxInfo; + RGFW_directXinfo* RGFW_getDirectXInfo(void) { return &RGFW_dxInfo; } +#endif +void RGFW_window_makeCurrent(RGFW_window* win) { #if defined(RGFW_WINDOWS) && defined(RGFW_DIRECTX) - RGFW_dxInfo.pDeviceContext->lpVtbl->OMSetRenderTargets(RGFW_dxInfo.pDeviceContext, 1, &win->src.renderTargetView, NULL); + if (win == NULL) + RGFW_dxInfo.pDeviceContext->lpVtbl->OMSetRenderTargets(RGFW_dxInfo.pDeviceContext, 1, NULL, NULL); + else + RGFW_dxInfo.pDeviceContext->lpVtbl->OMSetRenderTargets(RGFW_dxInfo.pDeviceContext, 1, &win->src.renderTargetView, NULL); #elif defined(RGFW_OPENGL) RGFW_window_makeCurrent_OpenGL(win); +#else + RGFW_UNUSED(win) #endif } void RGFW_window_setGPURender(RGFW_window* win, i8 set) { if (!set && !(win->_winArgs & RGFW_NO_GPU_RENDER)) win->_winArgs |= RGFW_NO_GPU_RENDER; - + else if (set && win->_winArgs & RGFW_NO_GPU_RENDER) win->_winArgs ^= RGFW_NO_GPU_RENDER; } @@ -1510,6 +1733,7 @@ void RGFW_window_setShouldClose(RGFW_window* win) { win->event.type = RGFW_quit; #endif RGFWDEF void RGFW_captureCursor(RGFW_window* win, RGFW_rect); +RGFWDEF void RGFW_releaseCursor(RGFW_window* win); void RGFW_window_mouseHold(RGFW_window* win, RGFW_area area) { if ((win->_winArgs & RGFW_HOLD_MOUSE)) @@ -1521,25 +1745,26 @@ void RGFW_window_mouseHold(RGFW_window* win, RGFW_area area) { win->_winArgs |= RGFW_HOLD_MOUSE; RGFW_captureCursor(win, win->r); - RGFW_window_moveMouse(win, RGFW_POINT(win->r.x + (area.w), win->r.y + (area.h))); + RGFW_window_moveMouse(win, RGFW_POINT(win->r.x + (win->r.w / 2), win->r.y + (win->r.h / 2))); } void RGFW_window_mouseUnhold(RGFW_window* win) { if ((win->_winArgs & RGFW_HOLD_MOUSE)) { win->_winArgs ^= RGFW_HOLD_MOUSE; - RGFW_captureCursor(win, RGFW_RECT(0, 0, 0, 0)); + RGFW_releaseCursor(win); } } -void RGFW_window_checkFPS(RGFW_window* win) { +u32 RGFW_window_checkFPS(RGFW_window* win, u32 fpsCap) { u64 deltaTime = RGFW_getTimeNS() - win->event.frameTime; + u32 output_fps = 0; u64 fps = round(1e+9 / deltaTime); - win->event.fps = fps; + output_fps= fps; - if (win->fpsCap && fps > win->fpsCap) { - u64 frameTimeNS = 1e+9 / win->fpsCap; + if (fpsCap && fps > fpsCap) { + u64 frameTimeNS = 1e+9 / fpsCap; u64 sleepTimeMS = (frameTimeNS - deltaTime) / 1e6; if (sleepTimeMS > 0) { @@ -1550,12 +1775,14 @@ void RGFW_window_checkFPS(RGFW_window* win) { win->event.frameTime = RGFW_getTimeNS(); - if (win->fpsCap == 0) - return; + if (fpsCap == 0) + return (u32) output_fps; deltaTime = RGFW_getTimeNS() - win->event.frameTime2; - win->event.fps = round(1e+9 / deltaTime); + output_fps = round(1e+9 / deltaTime); win->event.frameTime2 = RGFW_getTimeNS(); + + return output_fps; } u32 RGFW_isPressedJS(RGFW_window* win, u16 c, u8 button) { @@ -1586,7 +1813,7 @@ void RGFW_updateLockState(RGFW_window* win, b8 capital, b8 numlock) { win->event.lockState ^= RGFW_NUMLOCK; } -#if defined(RGFW_X11) || defined(RGFW_MACOS) +#if defined(RGFW_X11) || defined(RGFW_MACOS) || defined(RGFW_WEBASM) || defined(RGFW_WAYLAND) struct timespec; int nanosleep(const struct timespec* duration, struct timespec* rem); @@ -1603,7 +1830,7 @@ void RGFW_updateLockState(RGFW_window* win, b8 capital, b8 numlock) { #endif /* - graphics API spcific code (end of generic code) + graphics API specific code (end of generic code) starts here */ @@ -1615,12 +1842,13 @@ void RGFW_updateLockState(RGFW_window* win, b8 capital, b8 numlock) { #if defined(RGFW_OPENGL) || defined(RGFW_EGL) || defined(RGFW_OSMESA) #ifdef RGFW_WINDOWS #define WIN32_LEAN_AND_MEAN + #define OEMRESOURCE #include #endif - #ifndef __APPLE__ + #if !defined(__APPLE__) && !defined(RGFW_NO_GL_HEADER) #include - #else + #elif defined(__APPLE__) #ifndef GL_SILENCE_DEPRECATION #define GL_SILENCE_DEPRECATION #endif @@ -1631,11 +1859,12 @@ void RGFW_updateLockState(RGFW_window* win, b8 capital, b8 numlock) { /* EGL, normal OpenGL only */ #if !defined(RGFW_OSMESA) i32 RGFW_majorVersion = 0, RGFW_minorVersion = 0; + b8 RGFW_profile = RGFW_GL_CORE; #ifndef RGFW_EGL - i32 RGFW_STENCIL = 8, RGFW_SAMPLES = 4, RGFW_STEREO = GL_FALSE, RGFW_AUX_BUFFERS = 0; + i32 RGFW_STENCIL = 8, RGFW_SAMPLES = 4, RGFW_STEREO = 0, RGFW_AUX_BUFFERS = 0, RGFW_DOUBLE_BUFFER = 1; #else - i32 RGFW_STENCIL = 0, RGFW_SAMPLES = 0, RGFW_STEREO = GL_FALSE, RGFW_AUX_BUFFERS = 0; + i32 RGFW_STENCIL = 0, RGFW_SAMPLES = 0, RGFW_STEREO = 0, RGFW_AUX_BUFFERS = 0, RGFW_DOUBLE_BUFFER = 1; #endif @@ -1643,55 +1872,44 @@ void RGFW_updateLockState(RGFW_window* win, b8 capital, b8 numlock) { void RGFW_setGLSamples(i32 samples) { RGFW_SAMPLES = samples; } void RGFW_setGLStereo(i32 stereo) { RGFW_STEREO = stereo; } void RGFW_setGLAuxBuffers(i32 auxBuffers) { RGFW_AUX_BUFFERS = auxBuffers; } + void RGFW_setDoubleBuffer(b8 useDoubleBuffer) { RGFW_DOUBLE_BUFFER = useDoubleBuffer; } - void RGFW_setGLVersion(i32 major, i32 minor) { + void RGFW_setGLVersion(b8 profile, i32 major, i32 minor) { + RGFW_profile = profile; RGFW_majorVersion = major; RGFW_minorVersion = minor; } - u8* RGFW_getMaxGLVersion(void) { - RGFW_window* dummy = RGFW_createWindow("dummy", RGFW_RECT(0, 0, 1, 1), 0); - - const char* versionStr = (const char*) glGetString(GL_VERSION); - - static u8 version[2]; - version[0] = versionStr[0] - '0', - version[1] = versionStr[2] - '0'; - - RGFW_window_close(dummy); - - return version; - } - /* OPENGL normal only (no EGL / OSMesa) */ #ifndef RGFW_EGL -#define RGFW_GL_RENDER_TYPE RGFW_OS_BASED_VALUE(GLX_X_VISUAL_TYPE, 0x2003, 73, 0) - #define RGFW_GL_ALPHA_SIZE RGFW_OS_BASED_VALUE(GLX_ALPHA_SIZE, 0x201b, 11, 0) - #define RGFW_GL_DEPTH_SIZE RGFW_OS_BASED_VALUE(GLX_DEPTH_SIZE, 0x2022, 12, 0) - #define RGFW_GL_DOUBLEBUFFER RGFW_OS_BASED_VALUE(GLX_DOUBLEBUFFER, 0x2011, 5, 0) - #define RGFW_GL_STENCIL_SIZE RGFW_OS_BASED_VALUE(GLX_STENCIL_SIZE, 0x2023, 13, 0) - #define RGFW_GL_SAMPLES RGFW_OS_BASED_VALUE(GLX_SAMPLES, 0x2042, 55, 0) - #define RGFW_GL_STEREO RGFW_OS_BASED_VALUE(GLX_STEREO, 0x2012, 6, 0) - #define RGFW_GL_AUX_BUFFERS RGFW_OS_BASED_VALUE(GLX_AUX_BUFFERS, 0x2024, 7, 0) +#define RGFW_GL_RENDER_TYPE RGFW_OS_BASED_VALUE(GLX_X_VISUAL_TYPE, 0x2003, 73, 0, 0) + #define RGFW_GL_ALPHA_SIZE RGFW_OS_BASED_VALUE(GLX_ALPHA_SIZE, 0x201b, 11, 0, 0) + #define RGFW_GL_DEPTH_SIZE RGFW_OS_BASED_VALUE(GLX_DEPTH_SIZE, 0x2022, 12, 0, 0) + #define RGFW_GL_DOUBLEBUFFER RGFW_OS_BASED_VALUE(GLX_DOUBLEBUFFER, 0x2011, 5, 0, 0) + #define RGFW_GL_STENCIL_SIZE RGFW_OS_BASED_VALUE(GLX_STENCIL_SIZE, 0x2023, 13, 0, 0) + #define RGFW_GL_SAMPLES RGFW_OS_BASED_VALUE(GLX_SAMPLES, 0x2042, 55, 0, 0) + #define RGFW_GL_STEREO RGFW_OS_BASED_VALUE(GLX_STEREO, 0x2012, 6, 0, 0) + #define RGFW_GL_AUX_BUFFERS RGFW_OS_BASED_VALUE(GLX_AUX_BUFFERS, 0x2024, 7, 0, 0) #if defined(RGFW_X11) || defined(RGFW_WINDOWS) - #define RGFW_GL_DRAW RGFW_OS_BASED_VALUE(GLX_X_RENDERABLE, 0x2001, 0, 0) - #define RGFW_GL_DRAW_TYPE RGFW_OS_BASED_VALUE(GLX_RENDER_TYPE, 0x2013, 0, 0) - #define RGFW_GL_USE_OPENGL RGFW_OS_BASED_VALUE(GLX_USE_GL, 0x2010, 0, 0) - #define RGFW_GL_FULL_FORMAT RGFW_OS_BASED_VALUE(GLX_TRUE_COLOR, 0x2027, 0, 0) - #define RGFW_GL_RED_SIZE RGFW_OS_BASED_VALUE(GLX_RED_SIZE, 0x2015, 0, 0) - #define RGFW_GL_GREEN_SIZE RGFW_OS_BASED_VALUE(GLX_GREEN_SIZE, 0x2017, 0, 0) - #define RGFW_GL_BLUE_SIZE RGFW_OS_BASED_VALUE(GLX_BLUE_SIZE, 0x2019, 0, 0) - #define RGFW_GL_USE_RGBA RGFW_OS_BASED_VALUE(GLX_RGBA_BIT, 0x202B, 0, 0) + #define RGFW_GL_DRAW RGFW_OS_BASED_VALUE(GLX_X_RENDERABLE, 0x2001, 0, 0, 0) + #define RGFW_GL_DRAW_TYPE RGFW_OS_BASED_VALUE(GLX_RENDER_TYPE, 0x2013, 0, 0, 0) + #define RGFW_GL_FULL_FORMAT RGFW_OS_BASED_VALUE(GLX_TRUE_COLOR, 0x2027, 0, 0, 0) + #define RGFW_GL_RED_SIZE RGFW_OS_BASED_VALUE(GLX_RED_SIZE, 0x2015, 0, 0, 0) + #define RGFW_GL_GREEN_SIZE RGFW_OS_BASED_VALUE(GLX_GREEN_SIZE, 0x2017, 0, 0, 0) + #define RGFW_GL_BLUE_SIZE RGFW_OS_BASED_VALUE(GLX_BLUE_SIZE, 0x2019, 0, 0, 0) + #define RGFW_GL_USE_RGBA RGFW_OS_BASED_VALUE(GLX_RGBA_BIT, 0x202B, 0, 0, 0) #endif #ifdef RGFW_WINDOWS + #define WGL_SUPPORT_OPENGL_ARB 0x2010 #define WGL_COLOR_BITS_ARB 0x2014 #define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000 #define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091 #define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092 #define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126 + #define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001 #define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002 #define WGL_SAMPLE_BUFFERS_ARB 0x2041 #define WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20a9 @@ -1700,8 +1918,12 @@ void RGFW_updateLockState(RGFW_window* win, b8 capital, b8 numlock) { #define WGL_TRANSPARENT_ARB 0x200A #endif - - static u32* RGFW_initAttribs(u32 useSoftware) { + +/* The window'ing api needs to know how to render the data we (or opengl) give it + MacOS and Windows do this using a structure called a "pixel format" + X11 calls it a "Visual" + This function returns the attributes for the format we want */ + static u32* RGFW_initFormatAttribs(u32 useSoftware) { RGFW_UNUSED(useSoftware); static u32 attribs[] = { #if defined(RGFW_X11) || defined(RGFW_WINDOWS) @@ -1710,13 +1932,7 @@ void RGFW_updateLockState(RGFW_window* win, b8 capital, b8 numlock) { #endif RGFW_GL_ALPHA_SIZE , 8, RGFW_GL_DEPTH_SIZE , 24, - RGFW_GL_DOUBLEBUFFER , - #ifndef RGFW_MACOS - 1, - #endif - #if defined(RGFW_X11) || defined(RGFW_WINDOWS) - RGFW_GL_USE_OPENGL, 1, RGFW_GL_DRAW, 1, RGFW_GL_RED_SIZE , 8, RGFW_GL_GREEN_SIZE , 8, @@ -1726,7 +1942,7 @@ void RGFW_updateLockState(RGFW_window* win, b8 capital, b8 numlock) { #ifdef RGFW_X11 GLX_DRAWABLE_TYPE , GLX_WINDOW_BIT, - #endif + #endif #ifdef RGFW_MACOS 72, @@ -1734,8 +1950,8 @@ void RGFW_updateLockState(RGFW_window* win, b8 capital, b8 numlock) { #endif #ifdef RGFW_WINDOWS + WGL_SUPPORT_OPENGL_ARB, 1, WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB, - WGL_TRANSPARENT_ARB, TRUE, WGL_COLOR_BITS_ARB, 32, #endif @@ -1750,8 +1966,10 @@ void RGFW_updateLockState(RGFW_window* win, b8 capital, b8 numlock) { attribs[index + 1] = attVal;\ index += 2;\ } - - RGFW_GL_ADD_ATTRIB(RGFW_GL_STENCIL_SIZE, RGFW_STENCIL); + + RGFW_GL_ADD_ATTRIB(RGFW_GL_DOUBLEBUFFER, 1); + + RGFW_GL_ADD_ATTRIB(RGFW_GL_STENCIL_SIZE, RGFW_STENCIL); RGFW_GL_ADD_ATTRIB(RGFW_GL_STEREO, RGFW_STEREO); RGFW_GL_ADD_ATTRIB(RGFW_GL_AUX_BUFFERS, RGFW_AUX_BUFFERS); @@ -1769,13 +1987,15 @@ void RGFW_updateLockState(RGFW_window* win, b8 capital, b8 numlock) { #endif #ifdef RGFW_MACOS + /* macOS has the surface attribs and the opengl attribs connected for some reason + maybe this is to give macOS more control to limit openGL/the opengl version? */ + attribs[index] = 99; attribs[index + 1] = 0x1000; if (RGFW_majorVersion >= 4 || RGFW_majorVersion >= 3) { attribs[index + 1] = (u32) ((RGFW_majorVersion >= 4) ? 0x4100 : 0x3200); } - #endif RGFW_GL_ADD_ATTRIB(0, 0); @@ -1894,18 +2114,29 @@ void RGFW_updateLockState(RGFW_window* win, b8 capital, b8 numlock) { #else 2, #endif - EGL_NONE, EGL_NONE, EGL_NONE, EGL_NONE, EGL_NONE, EGL_NONE + EGL_NONE, EGL_NONE, EGL_NONE, EGL_NONE, EGL_NONE, EGL_NONE, EGL_NONE, EGL_NONE, EGL_NONE }; size_t index = 4; RGFW_GL_ADD_ATTRIB(EGL_STENCIL_SIZE, RGFW_STENCIL); RGFW_GL_ADD_ATTRIB(EGL_SAMPLES, RGFW_SAMPLES); + if (RGFW_DOUBLE_BUFFER) + RGFW_GL_ADD_ATTRIB(EGL_RENDER_BUFFER, EGL_BACK_BUFFER); + if (RGFW_majorVersion) { attribs[1] = RGFW_majorVersion; - RGFW_GL_ADD_ATTRIB(EGL_CONTEXT_OPENGL_PROFILE_MASK, EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT); + RGFW_GL_ADD_ATTRIB(EGL_CONTEXT_MAJOR_VERSION, RGFW_majorVersion); RGFW_GL_ADD_ATTRIB(EGL_CONTEXT_MINOR_VERSION, RGFW_minorVersion); + + if (RGFW_profile == RGFW_GL_CORE) { + RGFW_GL_ADD_ATTRIB(EGL_CONTEXT_OPENGL_PROFILE_MASK, EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT); + } + else { + RGFW_GL_ADD_ATTRIB(EGL_CONTEXT_OPENGL_PROFILE_MASK, EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT); + } + } #if defined(RGFW_OPENGL_ES1) || defined(RGFW_OPENGL_ES2) || defined(RGFW_OPENGL_ES3) @@ -1913,13 +2144,20 @@ void RGFW_updateLockState(RGFW_window* win, b8 capital, b8 numlock) { #else eglBindAPI(EGL_OPENGL_API); #endif - - win->src.EGL_context = eglCreateContext(win->src.EGL_display, config, EGL_NO_CONTEXT, attribs); + + win->src.EGL_context = eglCreateContext(win->src.EGL_display, config, EGL_NO_CONTEXT, attribs); + + if (win->src.EGL_context == NULL) + fprintf(stderr, "failed to create an EGL opengl context\n"); eglMakeCurrent(win->src.EGL_display, win->src.EGL_surface, win->src.EGL_surface, win->src.EGL_context); eglSwapBuffers(win->src.EGL_display, win->src.EGL_surface); } + void RGFW_window_makeCurrent_OpenGL(RGFW_window* win) { + eglMakeCurrent(win->src.EGL_display, win->src.EGL_surface, win->src.EGL_surface, win->src.EGL_context); + } + #ifdef RGFW_APPLE void* RGFWnsglFramework = NULL; #elif defined(RGFW_WINDOWS) @@ -1949,8 +2187,6 @@ void RGFW_updateLockState(RGFW_window* win, b8 capital, b8 numlock) { eglSwapInterval(win->src.EGL_display, swapInterval); - win->fpsCap = (swapInterval == 1) ? 0 : swapInterval; - } #endif /* RGFW_EGL */ @@ -1990,6 +2226,62 @@ This is where OS specific stuff starts */ +#if defined(RGFW_WAYLAND) || defined(RGFW_X11) + int RGFW_eventWait_forceStop[] = {0, 0, 0}; /* for wait events */ + + #ifdef __linux__ + #include + #include + #include + + RGFW_Event* RGFW_linux_updateJoystick(RGFW_window* win) { + static int xAxis = 0, yAxis = 0; + u8 i; + for (i = 0; i < RGFW_joystickCount; i++) { + struct js_event e; + + + if (RGFW_joysticks[i] == 0) + continue; + + i32 flags = fcntl(RGFW_joysticks[i], F_GETFL, 0); + fcntl(RGFW_joysticks[i], F_SETFL, flags | O_NONBLOCK); + + ssize_t bytes; + while ((bytes = read(RGFW_joysticks[i], &e, sizeof(e))) > 0) { + switch (e.type) { + case JS_EVENT_BUTTON: + win->event.type = e.value ? RGFW_jsButtonPressed : RGFW_jsButtonReleased; + win->event.button = e.number; + RGFW_jsPressed[i][e.number] = e.value; + RGFW_jsButtonCallback(win, i, e.number, e.value); + return &win->event; + case JS_EVENT_AXIS: + ioctl(RGFW_joysticks[i], JSIOCGAXES, &win->event.axisesCount); + + if ((e.number == 0 || e.number % 2) && e.number != 1) + xAxis = e.value; + else + yAxis = e.value; + + win->event.axis[e.number / 2].x = xAxis; + win->event.axis[e.number / 2].y = yAxis; + win->event.type = RGFW_jsAxisMove; + win->event.joystick = i; + RGFW_jsAxisCallback(win, i, win->event.axis, win->event.axisesCount); + return &win->event; + + default: break; + } + } + } + + return NULL; + } + + #endif +#endif + /* @@ -2021,9 +2313,9 @@ Start of Linux / Unix defines #include #include /* for data limits (mainly used in drag and drop functions) */ -#include #include + #ifdef __linux__ #include #endif @@ -2075,7 +2367,7 @@ Start of Linux / Unix defines if (RGFW_bufferSize.w == 0 && RGFW_bufferSize.h == 0) RGFW_bufferSize = RGFW_getScreenSize(); - win->buffer = RGFW_MALLOC(RGFW_bufferSize.w * RGFW_bufferSize.h * 4); + win->buffer = (u8*)RGFW_MALLOC(RGFW_bufferSize.w * RGFW_bufferSize.h * 4); #ifdef RGFW_OSMESA win->src.ctx = OSMesaCreateContext(OSMESA_RGBA, NULL); @@ -2092,7 +2384,7 @@ Start of Linux / Unix defines win->src.gc = XCreateGC(win->src.display, win->src.window, 0, NULL); #else - RGFW_UNUSED(win); /* if buffer rendering is not being used */ + RGFW_UNUSED(win); /*!< if buffer rendering is not being used */ RGFW_UNUSED(vi) #endif } @@ -2117,30 +2409,30 @@ Start of Linux / Unix defines 32, PropModeReplace, (u8*)&hints, 5 ); } + + void RGFW_releaseCursor(RGFW_window* win) { + XUngrabPointer(win->src.display, CurrentTime); - void RGFW_captureCursor(RGFW_window* win, RGFW_rect r) { + /* disable raw input */ + unsigned char mask[] = { 0 }; XIEventMask em; em.deviceid = XIAllMasterDevices; - - /* grab the cursor if the rect struct isn't zeroed out, else ungrab*/ - if (!r.x && !r.y && r.w && !r.h) { - XUngrabPointer(win->src.display, CurrentTime); - - /* disable raw input */ - unsigned char mask[] = { 0 }; - em.mask_len = sizeof(mask); - em.mask = mask; - XISelectEvents(win->src.display, XDefaultRootWindow(win->src.display), &em, 1); - return; - } - - /* enable raw input */ - unsigned char mask[XIMaskLen(XI_RawMotion)] = { 0 }; - em.mask_len = sizeof(mask); em.mask = mask; + + XISelectEvents(win->src.display, XDefaultRootWindow(win->src.display), &em, 1); + } + + void RGFW_captureCursor(RGFW_window* win, RGFW_rect r) { + /* enable raw input */ + unsigned char mask[XIMaskLen(XI_RawMotion)] = { 0 }; XISetMask(mask, XI_RawMotion); + XIEventMask em; + em.deviceid = XIAllMasterDevices; + em.mask_len = sizeof(mask); + em.mask = mask; + XISelectEvents(win->src.display, XDefaultRootWindow(win->src.display), &em, 1); XGrabPointer(win->src.display, win->src.window, True, PointerMotionMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime); @@ -2179,24 +2471,24 @@ Start of Linux / Unix defines } #endif - XInitThreads(); /* init X11 threading*/ + XInitThreads(); /*!< init X11 threading*/ if (args & RGFW_OPENGL_SOFTWARE) setenv("LIBGL_ALWAYS_SOFTWARE", "1", 1); RGFW_window* win = RGFW_window_basic_init(rect, args); - u64 event_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask | StructureNotifyMask | FocusChangeMask | LeaveWindowMask | EnterWindowMask | ExposureMask; /* X11 events accepted*/ + u64 event_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask | StructureNotifyMask | FocusChangeMask | LeaveWindowMask | EnterWindowMask | ExposureMask; /*!< X11 events accepted*/ #ifdef RGFW_OPENGL - u32* visual_attribs = RGFW_initAttribs(args & RGFW_OPENGL_SOFTWARE); + u32* visual_attribs = RGFW_initFormatAttribs(args & RGFW_OPENGL_SOFTWARE); i32 fbcount; GLXFBConfig* fbc = glXChooseFBConfig((Display*) win->src.display, DefaultScreen(win->src.display), (i32*) visual_attribs, &fbcount); i32 best_fbc = -1; if (fbcount == 0) { - printf("Failed to find any valid GLX configs\n"); + printf("Failed to find any valid GLX visual configs\n"); return NULL; } @@ -2230,7 +2522,7 @@ Start of Linux / Unix defines XFree(fbc); if (args & RGFW_TRANSPARENT_WINDOW) { - XMatchVisualInfo((Display*) win->src.display, DefaultScreen((Display*) win->src.display), 32, TrueColor, vi); /* for RGBA backgrounds*/ + XMatchVisualInfo((Display*) win->src.display, DefaultScreen((Display*) win->src.display), 32, TrueColor, vi); /*!< for RGBA backgrounds*/ } #else @@ -2241,7 +2533,7 @@ Start of Linux / Unix defines viNorm.depth = 0; XVisualInfo* vi = &viNorm; - XMatchVisualInfo((Display*) win->src.display, DefaultScreen((Display*) win->src.display), 32, TrueColor, vi); /* for RGBA backgrounds*/ + XMatchVisualInfo((Display*) win->src.display, DefaultScreen((Display*) win->src.display), 32, TrueColor, vi); /*!< for RGBA backgrounds*/ #endif /* make X window attrubutes*/ XSetWindowAttributes swa; @@ -2273,16 +2565,19 @@ Start of Linux / Unix defines // with your application - robrohan XClassHint *hint = XAllocClassHint(); assert(hint != NULL); - hint->res_class = "RGFW"; + hint->res_class = (char*)"RGFW"; hint->res_name = (char*)name; // just use the window name as the app name XSetClassHint((Display*) win->src.display, win->src.window, hint); XFree(hint); if ((args & RGFW_NO_INIT_API) == 0) { -#ifdef RGFW_OPENGL +#ifdef RGFW_OPENGL /* This is the second part of setting up opengl. This is where we ask OpenGL for a specific version. */ i32 context_attribs[7] = { 0, 0, 0, 0, 0, 0, 0 }; context_attribs[0] = GLX_CONTEXT_PROFILE_MASK_ARB; - context_attribs[1] = GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB; + if (RGFW_profile == RGFW_GL_CORE) + context_attribs[1] = GLX_CONTEXT_CORE_PROFILE_BIT_ARB; + else + context_attribs[1] = GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB; if (RGFW_majorVersion || RGFW_minorVersion) { context_attribs[2] = GLX_CONTEXT_MAJOR_VERSION_ARB; @@ -2328,7 +2623,7 @@ Start of Linux / Unix defines RGFW_window_setBorder(win, 0); } - XSelectInput((Display*) win->src.display, (Drawable) win->src.window, event_mask); /* tell X11 what events we want*/ + XSelectInput((Display*) win->src.display, (Drawable) win->src.window, event_mask); /*!< tell X11 what events we want*/ /* make it so the user can't close the window until the program does*/ if (wm_delete_window == 0) @@ -2343,10 +2638,10 @@ Start of Linux / Unix defines #endif /* set the background*/ - XStoreName((Display*) win->src.display, (Drawable) win->src.window, name); /* set the name*/ + XStoreName((Display*) win->src.display, (Drawable) win->src.window, name); /*!< set the name*/ XMapWindow((Display*) win->src.display, (Drawable) win->src.window); /* draw the window*/ - XMoveWindow((Display*) win->src.display, (Drawable) win->src.window, win->r.x, win->r.y); /* move the window to it's proper cords*/ + XMoveWindow((Display*) win->src.display, (Drawable) win->src.window, win->r.x, win->r.y); /*!< move the window to it's proper cords*/ if (args & RGFW_ALLOW_DND) { /* init drag and drop atoms and turn on drag and drop for this window */ win->_winArgs |= RGFW_ALLOW_DND; @@ -2373,7 +2668,7 @@ Start of Linux / Unix defines XChangeProperty((Display*) win->src.display, (Window) win->src.window, XdndAware, 4, 32, - PropModeReplace, (u8*) &version, 1); /* turns on drag and drop */ + PropModeReplace, (u8*) &version, 1); /*!< turns on drag and drop */ } #ifdef RGFW_EGL @@ -2421,79 +2716,10 @@ Start of Linux / Unix defines return RGFWMouse; } - - int RGFW_eventWait_forceStop[] = {0, 0, 0}; - - void RGFW_stopCheckEvents(void) { - RGFW_eventWait_forceStop[2] = 1; - while (1) { - const char byte = 0; - const ssize_t result = write(RGFW_eventWait_forceStop[1], &byte, 1); - if (result == 1 || result == -1) - break; - } - } - - void RGFW_window_eventWait(RGFW_window* win, i32 waitMS) { - if (waitMS == 0) - return; - - u8 i; - - if (RGFW_eventWait_forceStop[0] == 0 || RGFW_eventWait_forceStop[1] == 0) { - if (pipe(RGFW_eventWait_forceStop) != -1) { - fcntl(RGFW_eventWait_forceStop[0], F_GETFL, 0); - fcntl(RGFW_eventWait_forceStop[0], F_GETFD, 0); - fcntl(RGFW_eventWait_forceStop[1], F_GETFL, 0); - fcntl(RGFW_eventWait_forceStop[1], F_GETFD, 0); - } - } - - struct pollfd fds[] = { - { ConnectionNumber(win->src.display), POLLIN, 0 }, - { RGFW_eventWait_forceStop[0], POLLIN, 0 }, - #ifdef __linux__ /* blank space for 4 joystick files*/ - { -1, POLLIN, 0 }, {-1, POLLIN, 0 }, {-1, POLLIN, 0 }, {-1, POLLIN, 0} - #endif - }; - - u8 index = 2; - - #if defined(__linux__) - for (i = 0; i < RGFW_joystickCount; i++) { - if (RGFW_joysticks[i] == 0) - continue; - - fds[index].fd = RGFW_joysticks[i]; - index++; - } - #endif - - - u64 start = RGFW_getTimeNS(); - - while (XPending(win->src.display) == 0 && waitMS >= -1) { - if (poll(fds, index, waitMS) <= 0) - break; - - if (waitMS > 0) { - waitMS -= (RGFW_getTimeNS() - start) / 1e+6; - } - } - - /* drain any data in the stop request */ - if (RGFW_eventWait_forceStop[2]) { - char data[64]; - read(RGFW_eventWait_forceStop[0], data, sizeof(data)); - - RGFW_eventWait_forceStop[2] = 0; - } - } - typedef struct XDND { long source, version; i32 format; - } XDND; /* data structure for xdnd events */ + } XDND; /*!< data structure for xdnd events */ XDND xdnd; int xAxis = 0, yAxis = 0; @@ -2511,52 +2737,14 @@ Start of Linux / Unix defines win->event.type = 0; #ifdef __linux__ - { - u8 i; - for (i = 0; i < RGFW_joystickCount; i++) { - struct js_event e; - - - if (RGFW_joysticks[i] == 0) - continue; - - i32 flags = fcntl(RGFW_joysticks[i], F_GETFL, 0); - fcntl(RGFW_joysticks[i], F_SETFL, flags | O_NONBLOCK); - - ssize_t bytes; - while ((bytes = read(RGFW_joysticks[i], &e, sizeof(e))) > 0) { - switch (e.type) { - case JS_EVENT_BUTTON: - win->event.type = e.value ? RGFW_jsButtonPressed : RGFW_jsButtonReleased; - win->event.button = e.number; - RGFW_jsPressed[i][e.number] = e.value; - RGFW_jsButtonCallback(win, i, e.number, e.value); - return &win->event; - case JS_EVENT_AXIS: - ioctl(RGFW_joysticks[i], JSIOCGAXES, &win->event.axisesCount); - - if ((e.number == 0 || e.number % 2) && e.number != 1) - xAxis = e.value; - else - yAxis = e.value; - - win->event.axis[e.number / 2].x = xAxis; - win->event.axis[e.number / 2].y = yAxis; - win->event.type = RGFW_jsAxisMove; - win->event.joystick = i; - RGFW_jsAxisCallback(win, i, win->event.axis, win->event.axisesCount); - return &win->event; - - default: break; - } - } - } - } + RGFW_Event* event = RGFW_linux_updateJoystick(win); + if (event != NULL) + return event; #endif XPending(win->src.display); - XEvent E; /* raw X11 event */ + XEvent E; /*!< raw X11 event */ /* if there is no unread qued events, get a new one */ if ((QLength(win->src.display) || XEventsQueued((Display*) win->src.display, QueuedAlready) + XEventsQueued((Display*) win->src.display, QueuedAfterReading)) @@ -2573,21 +2761,22 @@ Start of Linux / Unix defines switch (E.type) { case KeyPress: - case KeyRelease: + case KeyRelease: { + win->event.repeat = RGFW_FALSE; /* check if it's a real key release */ if (E.type == KeyRelease && XEventsQueued((Display*) win->src.display, QueuedAfterReading)) { /* get next event if there is one*/ XEvent NE; XPeekEvent((Display*) win->src.display, &NE); if (E.xkey.time == NE.xkey.time && E.xkey.keycode == NE.xkey.keycode) /* check if the current and next are both the same*/ - break; + win->event.repeat = RGFW_TRUE; } /* set event key data */ - KeySym sym = XkbKeycodeToKeysym((Display*) win->src.display, E.xkey.keycode, 0, E.xkey.state & ShiftMask ? 1 : 0); + KeySym sym = (KeySym)XkbKeycodeToKeysym((Display*) win->src.display, E.xkey.keycode, 0, E.xkey.state & ShiftMask ? 1 : 0); win->event.keyCode = RGFW_apiKeyCodeToRGFW(E.xkey.keycode); - char* str = XKeysymToString(sym); + char* str = (char*)XKeysymToString(sym); if (str != NULL) strncpy(win->event.keyName, str, 16); @@ -2602,14 +2791,13 @@ Start of Linux / Unix defines XGetKeyboardControl((Display*) win->src.display, &keystate); RGFW_updateLockState(win, (keystate.led_mask & 1), (keystate.led_mask & 2)); - RGFW_keyboard[win->event.keyCode].current = (E.type == KeyPress); RGFW_keyCallback(win, win->event.keyCode, win->event.keyName, win->event.lockState, (E.type == KeyPress)); break; - + } case ButtonPress: case ButtonRelease: - win->event.type = E.type; // the events match + win->event.type = RGFW_mouseButtonPressed + (E.type == ButtonRelease); // the events match switch(win->event.button) { case RGFW_mouseScrollUp: @@ -2623,19 +2811,23 @@ Start of Linux / Unix defines win->event.button = E.xbutton.button; RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current; + + if (win->event.repeat == RGFW_FALSE) + win->event.repeat = RGFW_isPressed(win, win->event.keyCode); + RGFW_mouseButtons[win->event.button].current = (E.type == ButtonPress); RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, (E.type == ButtonPress)); break; - case MotionNotify: + case MotionNotify: win->event.point.x = E.xmotion.x; win->event.point.y = E.xmotion.y; if ((win->_winArgs & RGFW_HOLD_MOUSE)) { - win->event.point.x = win->_lastMousePoint.x - win->event.point.x; - win->event.point.y = win->_lastMousePoint.y - win->event.point.y; + win->event.point.y = E.xmotion.y; - RGFW_window_moveMouse(win, RGFW_POINT(win->r.x + (win->r.w / 2), win->r.y + (win->r.h / 2))); + win->event.point.x = win->_lastMousePoint.x - abs(win->event.point.x); + win->event.point.y = win->_lastMousePoint.y - abs(win->event.point.y); } win->_lastMousePoint = RGFW_POINT(E.xmotion.x, E.xmotion.y); @@ -2668,7 +2860,9 @@ Start of Linux / Unix defines if (XIMaskIsSet(raw->valuators.mask, 1) != 0) deltaY += raw->raw_values[1]; - win->event.point = RGFW_POINT((u32)-deltaX, (u32)-deltaY); + win->event.point = RGFW_POINT((i32)deltaX, (i32)deltaY); + + RGFW_window_moveMouse(win, RGFW_POINT(win->r.x + (win->r.w / 2), win->r.y + (win->r.h / 2))); win->event.type = RGFW_mousePosChanged; RGFW_mousePosCallback(win, win->event.point); @@ -2855,7 +3049,7 @@ Start of Linux / Unix defines RGFW_dndInitCallback(win, win->event.point); break; - case SelectionNotify: + case SelectionNotify: { /* this is only for checking for xdnd drops */ if (E.xselection.property != XdndSelection || !(win->_winArgs | RGFW_ALLOW_DND)) break; @@ -2878,7 +3072,7 @@ Start of Linux / Unix defines Copyright (c) 2006-2019 Camilla Löwy */ - const char* prefix = "file://"; + const char* prefix = (const char*)"file://"; char* line; @@ -2945,7 +3139,7 @@ Start of Linux / Unix defines RGFW_dndCallback(win, win->event.droppedFiles, win->event.droppedFilesCount); break; - + } case FocusIn: win->event.inFocus = 1; win->event.type = RGFW_focusIn; @@ -3222,7 +3416,7 @@ Start of Linux / Unix defines void RGFW_window_setMouseStandard(RGFW_window* win, u8 mouse) { assert(win != NULL); - + if (mouse > (sizeof(RGFW_mouseIconSrc) / sizeof(u8))) return; @@ -3286,7 +3480,7 @@ Start of Linux / Unix defines *size = sizeN; return s; - } + } /* almost all of this function is sourced from GLFW @@ -3309,27 +3503,25 @@ Start of Linux / Unix defines ATOM_PAIR = XInternAtom((Display*) RGFW_root->src.display, "ATOM_PAIR", False); CLIPBOARD_MANAGER = XInternAtom((Display*) RGFW_root->src.display, "CLIPBOARD_MANAGER", False); } - + XSetSelectionOwner((Display*) RGFW_root->src.display, CLIPBOARD, (Window) RGFW_root->src.window, CurrentTime); XConvertSelection((Display*) RGFW_root->src.display, CLIPBOARD_MANAGER, SAVE_TARGETS, None, (Window) RGFW_root->src.window, CurrentTime); - for (;;) { XEvent event; XNextEvent((Display*) RGFW_root->src.display, &event); - if (event.type != SelectionRequest) - return; + if (event.type != SelectionRequest) { + break; + } const XSelectionRequestEvent* request = &event.xselectionrequest; XEvent reply = { SelectionNotify }; + reply.xselection.property = 0; - char* selectionString = NULL; const Atom formats[] = { UTF8_STRING, XA_STRING }; const i32 formatCount = sizeof(formats) / sizeof(formats[0]); - - selectionString = (char*) text; if (request->target == TARGETS) { const Atom targets[] = { TARGETS, @@ -3350,11 +3542,11 @@ Start of Linux / Unix defines } if (request->target == MULTIPLE) { - Atom* targets; + Atom* targets = NULL; - Atom actualType; - i32 actualFormat; - unsigned long count, bytesAfter; + Atom actualType = 0; + int actualFormat = 0; + unsigned long count = 0, bytesAfter = 0; XGetWindowProperty((Display*) RGFW_root->src.display, request->requestor, request->property, 0, LONG_MAX, False, ATOM_PAIR, &actualType, &actualFormat, &count, &bytesAfter, (u8**) &targets); @@ -3375,10 +3567,12 @@ Start of Linux / Unix defines targets[i], 8, PropModeReplace, - (u8*) selectionString, + (u8*) text, textLen); - } else + XFlush(RGFW_root->src.display); + } else { targets[i + 1] = None; + } } XChangeProperty((Display*) RGFW_root->src.display, @@ -3390,6 +3584,7 @@ Start of Linux / Unix defines (u8*) targets, count); + XFlush(RGFW_root->src.display); XFree(targets); reply.xselection.property = request->property; @@ -3402,49 +3597,10 @@ Start of Linux / Unix defines reply.xselection.time = request->time; XSendEvent((Display*) RGFW_root->src.display, request->requestor, False, 0, &reply); + XFlush(RGFW_root->src.display); } } - u16 RGFW_registerJoystick(RGFW_window* win, i32 jsNumber) { - assert(win != NULL); - -#ifdef __linux__ - char file[15]; - sprintf(file, "/dev/input/js%i", jsNumber); - - return RGFW_registerJoystickF(win, file); -#endif - } - - u16 RGFW_registerJoystickF(RGFW_window* win, char* file) { - assert(win != NULL); - -#ifdef __linux__ - - i32 js = open(file, O_RDONLY); - - if (js && RGFW_joystickCount < 4) { - RGFW_joystickCount++; - - RGFW_joysticks[RGFW_joystickCount - 1] = open(file, O_RDONLY); - - u8 i; - for (i = 0; i < 16; i++) - RGFW_jsPressed[RGFW_joystickCount - 1][i] = 0; - - } - - else { -#ifdef RGFW_PRINT_ERRORS - RGFW_error = 1; - fprintf(stderr, "Error RGFW_registerJoystickF : Cannot open file %s\n", file); -#endif - } - - return RGFW_joystickCount - 1; -#endif - } - u8 RGFW_window_isFullscreen(RGFW_window* win) { assert(win != NULL); @@ -3648,9 +3804,10 @@ Start of Linux / Unix defines #ifdef RGFW_OPENGL void RGFW_window_makeCurrent_OpenGL(RGFW_window* win) { - assert(win != NULL); - - glXMakeCurrent((Display*) win->src.display, (Drawable) win->src.window, (GLXContext) win->src.ctx); + if (win == NULL) + glXMakeCurrent((Display*) NULL, (Drawable)NULL, (GLXContext) NULL); + else + glXMakeCurrent((Display*) win->src.display, (Drawable) win->src.window, (GLXContext) win->src.ctx); } #endif @@ -3658,8 +3815,6 @@ Start of Linux / Unix defines void RGFW_window_swapBuffers(RGFW_window* win) { assert(win != NULL); - RGFW_window_makeCurrent(win); - /* clear the window*/ if (!(win->_winArgs & RGFW_NO_CPU_RENDER)) { #if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) @@ -3693,8 +3848,6 @@ Start of Linux / Unix defines glXSwapBuffers((Display*) win->src.display, (Window) win->src.window); #endif } - - RGFW_window_checkFPS(win); } #if !defined(RGFW_EGL) @@ -3703,9 +3856,9 @@ Start of Linux / Unix defines #if defined(RGFW_OPENGL) ((PFNGLXSWAPINTERVALEXTPROC) glXGetProcAddress((GLubyte*) "glXSwapIntervalEXT"))((Display*) win->src.display, (Window) win->src.window, swapInterval); + #else + RGFW_UNUSED(swapInterval); #endif - - win->fpsCap = (swapInterval == 1) ? 0 : swapInterval; } #endif @@ -3736,9 +3889,9 @@ Start of Linux / Unix defines RGFW_root = NULL; if ((Drawable) win->src.window) - XDestroyWindow((Display*) win->src.display, (Drawable) win->src.window); /* close the window*/ + XDestroyWindow((Display*) win->src.display, (Drawable) win->src.window); /*!< close the window*/ - XCloseDisplay((Display*) win->src.display); /* kill the display*/ + XCloseDisplay((Display*) win->src.display); /*!< kill the display*/ } #ifdef RGFW_ALLOC_DROPFILES @@ -3788,7 +3941,134 @@ Start of Linux / Unix defines win->src.display = (Display*) 0; win->src.window = (Window) 0; - RGFW_FREE(win); /* free collected window data */ + RGFW_FREE(win); /*!< free collected window data */ + } + + +/* + End of X11 linux / unix defines +*/ + +#endif /* RGFW_X11 */ + + +/* wayland or X11 defines*/ +#if defined(RGFW_WAYLAND) || defined(RGFW_X11) +#include +#include +#include + u16 RGFW_registerJoystickF(RGFW_window* win, char* file) { + assert(win != NULL); + +#ifdef __linux__ + + i32 js = open(file, O_RDONLY); + + if (js && RGFW_joystickCount < 4) { + RGFW_joystickCount++; + + RGFW_joysticks[RGFW_joystickCount - 1] = open(file, O_RDONLY); + + u8 i; + for (i = 0; i < 16; i++) + RGFW_jsPressed[RGFW_joystickCount - 1][i] = 0; + + } + + else { +#ifdef RGFW_PRINT_ERRORS + RGFW_error = 1; + fprintf(stderr, "Error RGFW_registerJoystickF : Cannot open file %s\n", file); +#endif + } + + return RGFW_joystickCount - 1; +#endif + } + + u16 RGFW_registerJoystick(RGFW_window* win, i32 jsNumber) { + assert(win != NULL); + +#ifdef __linux__ + char file[15]; + sprintf(file, "/dev/input/js%i", jsNumber); + + return RGFW_registerJoystickF(win, file); +#endif + } + + void RGFW_stopCheckEvents(void) { + RGFW_eventWait_forceStop[2] = 1; + while (1) { + const char byte = 0; + const ssize_t result = write(RGFW_eventWait_forceStop[1], &byte, 1); + if (result == 1 || result == -1) + break; + } + } + + void RGFW_window_eventWait(RGFW_window* win, i32 waitMS) { + if (waitMS == 0) + return; + + u8 i; + + if (RGFW_eventWait_forceStop[0] == 0 || RGFW_eventWait_forceStop[1] == 0) { + if (pipe(RGFW_eventWait_forceStop) != -1) { + fcntl(RGFW_eventWait_forceStop[0], F_GETFL, 0); + fcntl(RGFW_eventWait_forceStop[0], F_GETFD, 0); + fcntl(RGFW_eventWait_forceStop[1], F_GETFL, 0); + fcntl(RGFW_eventWait_forceStop[1], F_GETFD, 0); + } + } + + struct pollfd fds[] = { + #ifdef RGFW_WAYLAND + { wl_display_get_fd(win->src.display), POLLIN, 0 }, + #else + { ConnectionNumber(win->src.display), POLLIN, 0 }, + #endif + { RGFW_eventWait_forceStop[0], POLLIN, 0 }, + #ifdef __linux__ /* blank space for 4 joystick files*/ + { -1, POLLIN, 0 }, {-1, POLLIN, 0 }, {-1, POLLIN, 0 }, {-1, POLLIN, 0} + #endif + }; + + u8 index = 2; + + #if defined(__linux__) + for (i = 0; i < RGFW_joystickCount; i++) { + if (RGFW_joysticks[i] == 0) + continue; + + fds[index].fd = RGFW_joysticks[i]; + index++; + } + #endif + + + u64 start = RGFW_getTimeNS(); + + #ifdef RGFW_WAYLAND + while (wl_display_dispatch(win->src.display) <= 0 && waitMS >= -1) { + #else + while (XPending(win->src.display) == 0 && waitMS >= -1) { + #endif + if (poll(fds, index, waitMS) <= 0) + break; + + if (waitMS > 0) { + waitMS -= (RGFW_getTimeNS() - start) / 1e+6; + } + } + + /* drain any data in the stop request */ + if (RGFW_eventWait_forceStop[2]) { + char data[64]; + (void)!read(RGFW_eventWait_forceStop[0], data, sizeof(data)); + + RGFW_eventWait_forceStop[2] = 0; + } } u64 RGFW_getTimeNS(void) { @@ -3806,11 +4086,906 @@ Start of Linux / Unix defines return (double)(nanoSeconds) * 1e-9; } -/* - End of linux / unix defines +#endif /* end of wayland or X11 time defines*/ + + +/* + + Start of Wayland defines + + */ -#endif /* RGFW_X11 */ +#ifdef RGFW_WAYLAND +/* +Wayland TODO: +- fix RGFW_keyPressed lock state + + RGFW_windowMoved, the window was moved (by the user) + RGFW_windowResized the window was resized (by the user), [on webASM this means the browser was resized] + RGFW_windowRefresh The window content needs to be refreshed + + RGFW_dnd a file has been dropped into the window + RGFW_dnd_init + +- window args: + #define RGFW_NO_RESIZE the window cannot be resized by the user + #define RGFW_ALLOW_DND the window supports drag and drop + #define RGFW_SCALE_TO_MONITOR scale the window to the screen + +- other missing functions functions ("TODO wayland") (~30 functions) +- fix buffer rendering weird behavior +*/ + #include + #include + #include + #include + #include + #include + #include + #include + +RGFW_window* RGFW_key_win = NULL; + +void RGFW_eventPipe_push(RGFW_window* win, RGFW_Event event) { + if (win == NULL) { + win = RGFW_key_win; + + if (win == NULL) return; + } + + if (win->src.eventLen >= (i32)(sizeof(win->src.events) / sizeof(win->src.events[0]))) + return; + + win->src.events[win->src.eventLen] = event; + win->src.eventLen += 1; +} + +RGFW_Event RGFW_eventPipe_pop(RGFW_window* win) { + RGFW_Event ev; + ev.type = 0; + + if (win->src.eventLen > -1) + win->src.eventLen -= 1; + + if (win->src.eventLen >= 0) + ev = win->src.events[win->src.eventLen]; + else { + printf("H2\n"); + } + + return ev; +} + +/* wayland global garbage (wayland bad, X11 is fine (ish) (not really)) */ +#include "xdg-shell.h" +#include "xdg-decoration-unstable-v1.h" + +struct xdg_wm_base *xdg_wm_base; +struct wl_compositor* RGFW_compositor = NULL; +struct wl_shm* shm = NULL; +struct wl_shell* RGFW_shell = NULL; +static struct wl_seat *seat = NULL; +static struct xkb_context *xkb_context; +static struct xkb_keymap *keymap = NULL; +static struct xkb_state *xkb_state = NULL; +enum zxdg_toplevel_decoration_v1_mode client_preferred_mode, RGFW_current_mode; +static struct zxdg_decoration_manager_v1 *decoration_manager = NULL; + +struct wl_cursor_theme* RGFW_wl_cursor_theme = NULL; +struct wl_surface* RGFW_cursor_surface = NULL; +struct wl_cursor_image* RGFW_cursor_image = NULL; + +static void xdg_wm_base_ping_handler(void *data, + struct xdg_wm_base *wm_base, uint32_t serial) +{ + RGFW_UNUSED(data); + xdg_wm_base_pong(wm_base, serial); +} + +static const struct xdg_wm_base_listener xdg_wm_base_listener = { + .ping = xdg_wm_base_ping_handler, +}; + +b8 RGFW_wl_configured = 0; + +static void xdg_surface_configure_handler(void *data, + struct xdg_surface *xdg_surface, uint32_t serial) +{ + RGFW_UNUSED(data); + xdg_surface_ack_configure(xdg_surface, serial); + #ifdef RGFW_DEBUG + printf("Surface configured\n"); + #endif + RGFW_wl_configured = 1; +} + +static const struct xdg_surface_listener xdg_surface_listener = { + .configure = xdg_surface_configure_handler, +}; + +static void xdg_toplevel_configure_handler(void *data, + struct xdg_toplevel *toplevel, int32_t width, int32_t height, + struct wl_array *states) +{ + RGFW_UNUSED(data); RGFW_UNUSED(toplevel); RGFW_UNUSED(states) + fprintf(stderr, "XDG toplevel configure: %dx%d\n", width, height); +} + +static void xdg_toplevel_close_handler(void *data, + struct xdg_toplevel *toplevel) +{ + RGFW_UNUSED(data); + RGFW_window* win = (RGFW_window*)xdg_toplevel_get_user_data(toplevel); + if (win == NULL) + win = RGFW_key_win; + + RGFW_Event ev; + ev.type = RGFW_quit; + + RGFW_eventPipe_push(win, ev); + + RGFW_windowQuitCallback(win); +} + +static void shm_format_handler(void *data, + struct wl_shm *shm, uint32_t format) +{ + RGFW_UNUSED(data); RGFW_UNUSED(shm); + fprintf(stderr, "Format %d\n", format); +} + +static const struct wl_shm_listener shm_listener = { + .format = shm_format_handler, +}; + +static const struct xdg_toplevel_listener xdg_toplevel_listener = { + .configure = xdg_toplevel_configure_handler, + .close = xdg_toplevel_close_handler, +}; + +RGFW_window* RGFW_mouse_win = NULL; + +static void pointer_enter(void *data, struct wl_pointer *pointer, uint32_t serial, struct wl_surface *surface, wl_fixed_t surface_x, wl_fixed_t surface_y) { + RGFW_UNUSED(data); RGFW_UNUSED(pointer); RGFW_UNUSED(serial); RGFW_UNUSED(surface_x); RGFW_UNUSED(surface_y); + RGFW_window* win = (RGFW_window*)wl_surface_get_user_data(surface); + RGFW_mouse_win = win; + + RGFW_Event ev; + ev.type = RGFW_mouseEnter; + ev.point = win->event.point; + + RGFW_eventPipe_push(win, ev); + + RGFW_mouseNotifyCallBack(win, win->event.point, RGFW_TRUE); +} +static void pointer_leave(void *data, struct wl_pointer *pointer, uint32_t serial, struct wl_surface *surface) { + RGFW_UNUSED(data); RGFW_UNUSED(pointer); RGFW_UNUSED(serial); RGFW_UNUSED(surface); + RGFW_window* win = (RGFW_window*)wl_surface_get_user_data(surface); + if (RGFW_mouse_win == win) + RGFW_mouse_win = NULL; + + RGFW_Event ev; + ev.type = RGFW_mouseLeave; + ev.point = win->event.point; + RGFW_eventPipe_push(win, ev); + + RGFW_mouseNotifyCallBack(win, win->event.point, RGFW_FALSE); +} +static void pointer_motion(void *data, struct wl_pointer *pointer, uint32_t time, wl_fixed_t x, wl_fixed_t y) { + RGFW_UNUSED(data); RGFW_UNUSED(pointer); RGFW_UNUSED(time); RGFW_UNUSED(x); RGFW_UNUSED(y); + + assert(RGFW_mouse_win != NULL); + + RGFW_Event ev; + ev.type = RGFW_mousePosChanged; + ev.point = RGFW_POINT(wl_fixed_to_double(x), wl_fixed_to_double(y)); + RGFW_eventPipe_push(RGFW_mouse_win, ev); + + RGFW_mousePosCallback(RGFW_mouse_win, RGFW_POINT(wl_fixed_to_double(x), wl_fixed_to_double(y))); +} +static void pointer_button(void *data, struct wl_pointer *pointer, uint32_t serial, uint32_t time, uint32_t button, uint32_t state) { + RGFW_UNUSED(data); RGFW_UNUSED(pointer); RGFW_UNUSED(time); RGFW_UNUSED(serial); + assert(RGFW_mouse_win != NULL); + + u32 b = (button - 0x110) + 1; + + /* flip right and middle button codes */ + if (b == 2) b = 3; + else if (b == 3) b = 2; + + RGFW_mouseButtons[b].prev = RGFW_mouseButtons[b].current; + RGFW_mouseButtons[b].current = state; + + RGFW_Event ev; + ev.type = RGFW_mouseButtonPressed + state; + ev.button = b; + RGFW_eventPipe_push(RGFW_mouse_win, ev); + + RGFW_mouseButtonCallback(RGFW_mouse_win, b, 0, state); +} +static void pointer_axis(void *data, struct wl_pointer *pointer, uint32_t time, uint32_t axis, wl_fixed_t value) { + RGFW_UNUSED(data); RGFW_UNUSED(pointer); RGFW_UNUSED(time); RGFW_UNUSED(axis); + assert(RGFW_mouse_win != NULL); + + double scroll = wl_fixed_to_double(value); + + RGFW_Event ev; + ev.type = RGFW_mouseButtonPressed; + ev.button = RGFW_mouseScrollUp + (scroll < 0); + RGFW_eventPipe_push(RGFW_mouse_win, ev); + + RGFW_mouseButtonCallback(RGFW_mouse_win, RGFW_mouseScrollUp + (scroll < 0), scroll, 1); +} + +void RGFW_doNothing(void) { } +static struct wl_pointer_listener pointer_listener = (struct wl_pointer_listener){&pointer_enter, &pointer_leave, &pointer_motion, &pointer_button, &pointer_axis, (void*)&RGFW_doNothing, (void*)&RGFW_doNothing, (void*)&RGFW_doNothing, (void*)&RGFW_doNothing, (void*)&RGFW_doNothing, (void*)&RGFW_doNothing}; + +static void keyboard_keymap (void *data, struct wl_keyboard *keyboard, uint32_t format, int32_t fd, uint32_t size) { + RGFW_UNUSED(data); RGFW_UNUSED(keyboard); RGFW_UNUSED(format); + + char *keymap_string = mmap (NULL, size, PROT_READ, MAP_SHARED, fd, 0); + xkb_keymap_unref (keymap); + keymap = xkb_keymap_new_from_string (xkb_context, keymap_string, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS); + + munmap (keymap_string, size); + close (fd); + xkb_state_unref (xkb_state); + xkb_state = xkb_state_new (keymap); +} +static void keyboard_enter (void *data, struct wl_keyboard *keyboard, uint32_t serial, struct wl_surface *surface, struct wl_array *keys) { + RGFW_UNUSED(data); RGFW_UNUSED(keyboard); RGFW_UNUSED(serial); RGFW_UNUSED(keys); + + RGFW_key_win = (RGFW_window*)wl_surface_get_user_data(surface); + + RGFW_Event ev; + ev.type = RGFW_focusIn; + ev.inFocus = RGFW_TRUE; + RGFW_key_win->event.inFocus = RGFW_TRUE; + + RGFW_eventPipe_push((RGFW_window*)RGFW_mouse_win, ev); + + RGFW_focusCallback(RGFW_key_win, RGFW_TRUE); +} +static void keyboard_leave (void *data, struct wl_keyboard *keyboard, uint32_t serial, struct wl_surface *surface) { + RGFW_UNUSED(data); RGFW_UNUSED(keyboard); RGFW_UNUSED(serial); + + RGFW_window* win = (RGFW_window*)wl_surface_get_user_data(surface); + if (RGFW_key_win == win) + RGFW_key_win = NULL; + + RGFW_Event ev; + ev.type = RGFW_focusOut; + ev.inFocus = RGFW_FALSE; + win->event.inFocus = RGFW_FALSE; + RGFW_eventPipe_push(win, ev); + + RGFW_focusCallback(win, RGFW_FALSE); +} +static void keyboard_key (void *data, struct wl_keyboard *keyboard, uint32_t serial, uint32_t time, uint32_t key, uint32_t state) { + RGFW_UNUSED(data); RGFW_UNUSED(keyboard); RGFW_UNUSED(serial); RGFW_UNUSED(time); + + assert(RGFW_key_win != NULL); + + xkb_keysym_t keysym = xkb_state_key_get_one_sym (xkb_state, key+8); + char name[16]; + xkb_keysym_get_name(keysym, name, 16); + + u32 RGFW_key = RGFW_apiKeyCodeToRGFW(key); + RGFW_keyboard[RGFW_key].prev = RGFW_keyboard[RGFW_key].current; + RGFW_keyboard[RGFW_key].current = state; + RGFW_Event ev; + ev.type = RGFW_keyPressed + state; + ev.keyCode = RGFW_key; + strcpy(ev.keyName, name); + ev.repeat = RGFW_isHeld(RGFW_key_win, RGFW_key); + RGFW_eventPipe_push(RGFW_key_win, ev); + + RGFW_updateLockState(RGFW_key_win, xkb_keymap_mod_get_index(keymap, "Lock"), xkb_keymap_mod_get_index(keymap, "Mod2")); + + RGFW_keyCallback(RGFW_key_win, RGFW_key, name, RGFW_key_win->event.lockState, state); +} +static void keyboard_modifiers (void *data, struct wl_keyboard *keyboard, uint32_t serial, uint32_t mods_depressed, uint32_t mods_latched, uint32_t mods_locked, uint32_t group) { + RGFW_UNUSED(data); RGFW_UNUSED(keyboard); RGFW_UNUSED(serial); RGFW_UNUSED(time); + xkb_state_update_mask (xkb_state, mods_depressed, mods_latched, mods_locked, 0, 0, group); +} +static struct wl_keyboard_listener keyboard_listener = {&keyboard_keymap, &keyboard_enter, &keyboard_leave, &keyboard_key, &keyboard_modifiers, (void*)&RGFW_doNothing}; + +static void seat_capabilities (void *data, struct wl_seat *seat, uint32_t capabilities) { + RGFW_UNUSED(data); + + if (capabilities & WL_SEAT_CAPABILITY_POINTER) { + struct wl_pointer *pointer = wl_seat_get_pointer (seat); + wl_pointer_add_listener (pointer, &pointer_listener, NULL); + } + if (capabilities & WL_SEAT_CAPABILITY_KEYBOARD) { + struct wl_keyboard *keyboard = wl_seat_get_keyboard (seat); + wl_keyboard_add_listener (keyboard, &keyboard_listener, NULL); + } +} +static struct wl_seat_listener seat_listener = {&seat_capabilities, (void*)&RGFW_doNothing}; + +static void wl_global_registry_handler(void *data, + struct wl_registry *registry, uint32_t id, const char *interface, + uint32_t version) +{ + RGFW_UNUSED(data); RGFW_UNUSED(version); + + if (strcmp(interface, "wl_compositor") == 0) { + RGFW_compositor = wl_registry_bind(registry, + id, &wl_compositor_interface, 4); + } else if (strcmp(interface, "xdg_wm_base") == 0) { + xdg_wm_base = wl_registry_bind(registry, + id, &xdg_wm_base_interface, 1); + } else if (strcmp(interface, zxdg_decoration_manager_v1_interface.name) == 0) { + decoration_manager = wl_registry_bind(registry, id, &zxdg_decoration_manager_v1_interface, 1); + } else if (strcmp(interface, "wl_shm") == 0) { + shm = wl_registry_bind(registry, + id, &wl_shm_interface, 1); + wl_shm_add_listener(shm, &shm_listener, NULL); + } else if (strcmp(interface,"wl_seat") == 0) { + seat = wl_registry_bind(registry, id, &wl_seat_interface, 1); + wl_seat_add_listener(seat, &seat_listener, NULL); + } + + else { + #ifdef RGFW_DEBUG + printf("did not register %s\n", interface); + return; + #endif + } + + #ifdef RGFW_DEBUG + printf("registered %s\n", interface); + #endif +} + +static void wl_global_registry_remove(void *data, struct wl_registry *registry, uint32_t name) { RGFW_UNUSED(data); RGFW_UNUSED(registry); RGFW_UNUSED(name); } +static const struct wl_registry_listener registry_listener = { + .global = wl_global_registry_handler, + .global_remove = wl_global_registry_remove, +}; + +static const char *get_mode_name(enum zxdg_toplevel_decoration_v1_mode mode) { + switch (mode) { + case ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE: + return "client-side decorations"; + case ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE: + return "server-side decorations"; + } + abort(); +} + + +static void decoration_handle_configure(void *data, + struct zxdg_toplevel_decoration_v1 *decoration, + enum zxdg_toplevel_decoration_v1_mode mode) { + RGFW_UNUSED(data); RGFW_UNUSED(decoration); + printf("Using %s\n", get_mode_name(mode)); + RGFW_current_mode = mode; +} + +static const struct zxdg_toplevel_decoration_v1_listener decoration_listener = { + .configure = decoration_handle_configure, +}; + +static void randname(char *buf) { + struct timespec ts; + clock_gettime(CLOCK_REALTIME, &ts); + long r = ts.tv_nsec; + for (int i = 0; i < 6; ++i) { + buf[i] = 'A'+(r&15)+(r&16)*2; + r >>= 5; + } +} + +static int anonymous_shm_open(void) { + char name[] = "/RGFW-wayland-XXXXXX"; + int retries = 100; + + do { + randname(name + strlen(name) - 6); + + --retries; + // shm_open guarantees that O_CLOEXEC is set + int fd = shm_open(name, O_RDWR | O_CREAT | O_EXCL, 0600); + if (fd >= 0) { + shm_unlink(name); + return fd; + } + } while (retries > 0 && errno == EEXIST); + + return -1; +} + +int create_shm_file(off_t size) { + int fd = anonymous_shm_open(); + if (fd < 0) { + return fd; + } + + if (ftruncate(fd, size) < 0) { + close(fd); + return -1; + } + + return fd; +} + +static void wl_surface_frame_done(void *data, struct wl_callback *cb, uint32_t time) { + #ifdef RGFW_BUFFER + RGFW_window* win = (RGFW_window*)data; + if ((win->_winArgs & RGFW_NO_CPU_RENDER)) + return; + + #ifndef RGFW_X11_DONT_CONVERT_BGR + u32 x, y; + for (y = 0; y < (u32)win->r.h; y++) { + for (x = 0; x < (u32)win->r.w; x++) { + u32 index = (y * 4 * win->r.w) + x * 4; + + u8 red = win->buffer[index]; + win->buffer[index] = win->buffer[index + 2]; + win->buffer[index + 2] = red; + + } + } + #endif + + wl_surface_attach(win->src.surface, win->src.wl_buffer, 0, 0); + wl_surface_damage_buffer(win->src.surface, 0, 0, win->r.w, win->r.h); + wl_surface_commit(win->src.surface); + #endif +} + +static const struct wl_callback_listener wl_surface_frame_listener = { + .done = wl_surface_frame_done, +}; + + + /* normal wayland RGFW stuff */ + + RGFW_area RGFW_getScreenSize(void) { + RGFW_area area = {}; + + if (RGFW_root != NULL) + /* this isn't right but it's here for buffers */ + area = RGFW_AREA(RGFW_root->r.w, RGFW_root->r.h); + + /* TODO wayland */ + return area; + } + + void RGFW_releaseCursor(RGFW_window* win) { + RGFW_UNUSED(win); + } + + void RGFW_captureCursor(RGFW_window* win, RGFW_rect r) { + RGFW_UNUSED(win); RGFW_UNUSED(r); + + /* TODO wayland */ + } + + + RGFWDEF void RGFW_init_buffer(RGFW_window* win); + void RGFW_init_buffer(RGFW_window* win) { + #if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) + size_t size = win->r.w * win->r.h * 4; + int fd = create_shm_file(size); + if (fd < 0) { + fprintf(stderr, "Failed to create a buffer. size: %ld\n", size); + exit(1); + } + + win->buffer = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (win->buffer == MAP_FAILED) { + fprintf(stderr, "mmap failed!\n"); + close(fd); + exit(1); + } + + struct wl_shm_pool* pool = wl_shm_create_pool(shm, fd, size); + win->src.wl_buffer = wl_shm_pool_create_buffer(pool, 0, win->r.w, win->r.h, win->r.w * 4, + WL_SHM_FORMAT_ARGB8888); + wl_shm_pool_destroy(pool); + + close(fd); + + wl_surface_attach(win->src.surface, win->src.wl_buffer, 0, 0); + wl_surface_commit(win->src.surface); + + u8 color[] = {0x00, 0x00, 0x00, 0xFF}; + + size_t i; + for (i = 0; i < size; i += 4) { + memcpy(&win->buffer[i], color, 4); + } + + #if defined(RGFW_OSMESA) + win->src.ctx = OSMesaCreateContext(OSMESA_RGBA, NULL); + OSMesaMakeCurrent(win->src.ctx, win->buffer, GL_UNSIGNED_BYTE, win->r.w, win->r.h); + #endif + #else + RGFW_UNUSED(win); + #endif + } + + + RGFW_window* RGFW_createWindow(const char* name, RGFW_rect rect, u16 args) { + RGFW_window* win = RGFW_window_basic_init(rect, args); + + fprintf(stderr, "Warning: RGFW Wayland support is experimental\n"); + + win->src.display = wl_display_connect(NULL); + if (win->src.display == NULL) { + #ifdef RGFW_DEBUG + fprintf(stderr, "Failed to load Wayland display\n"); + #endif + return NULL; + } + + struct wl_registry *registry = wl_display_get_registry(win->src.display); + wl_registry_add_listener(registry, ®istry_listener, NULL); + + wl_display_dispatch(win->src.display); + wl_display_roundtrip(win->src.display); + + if (RGFW_compositor == NULL) { + #ifdef RGFW_DEBUG + fprintf(stderr, "Can't find compositor.\n"); + #endif + + return NULL; + } + + if (RGFW_wl_cursor_theme == NULL) { + RGFW_wl_cursor_theme = wl_cursor_theme_load(NULL, 24, shm); + RGFW_cursor_surface = wl_compositor_create_surface(RGFW_compositor); + + struct wl_cursor* cursor = wl_cursor_theme_get_cursor(RGFW_wl_cursor_theme, "left_ptr"); + RGFW_cursor_image = cursor->images[0]; + struct wl_buffer* cursor_buffer = wl_cursor_image_get_buffer(RGFW_cursor_image); + + wl_surface_attach(RGFW_cursor_surface, cursor_buffer, 0, 0); + wl_surface_commit(RGFW_cursor_surface); + } + + if (RGFW_root == NULL) + xdg_wm_base_add_listener(xdg_wm_base, &xdg_wm_base_listener, NULL); + + xkb_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); + + win->src.surface = wl_compositor_create_surface(RGFW_compositor); + wl_surface_set_user_data(win->src.surface, win); + + win->src.xdg_surface = xdg_wm_base_get_xdg_surface(xdg_wm_base, win->src.surface); + xdg_surface_add_listener(win->src.xdg_surface, &xdg_surface_listener, NULL); + + xdg_wm_base_set_user_data(xdg_wm_base, win); + + win->src.xdg_toplevel = xdg_surface_get_toplevel(win->src.xdg_surface); + xdg_toplevel_set_user_data(win->src.xdg_toplevel, win); + xdg_toplevel_set_title(win->src.xdg_toplevel, name); + xdg_toplevel_add_listener(win->src.xdg_toplevel, &xdg_toplevel_listener, NULL); + + xdg_surface_set_window_geometry(win->src.xdg_surface, 0, 0, win->r.w, win->r.h); + + if (!(args & RGFW_NO_BORDER)) { + win->src.decoration = zxdg_decoration_manager_v1_get_toplevel_decoration( + decoration_manager, win->src.xdg_toplevel); + } + + + if (args & RGFW_OPENGL_SOFTWARE) + setenv("LIBGL_ALWAYS_SOFTWARE", "1", 1); + + wl_display_roundtrip(win->src.display); + + wl_surface_commit(win->src.surface); + + /* wait for the surface to be configured */ + while (wl_display_dispatch(win->src.display) != -1 && !RGFW_wl_configured) { } + + + #ifdef RGFW_OPENGL + if ((args & RGFW_NO_INIT_API) == 0) { + win->src.window = wl_egl_window_create(win->src.surface, win->r.w, win->r.h); + RGFW_createOpenGLContext(win); + } + #endif + + RGFW_init_buffer(win); + + struct wl_callback* callback = wl_surface_frame(win->src.surface); + wl_callback_add_listener(callback, &wl_surface_frame_listener, win); + wl_surface_commit(win->src.surface); + + if (args & RGFW_HIDE_MOUSE) { + RGFW_window_showMouse(win, 0); + } + + if (RGFW_root == NULL) { + RGFW_root = win; + } + + win->src.eventIndex = 0; + win->src.eventLen = 0; + + return win; + } + + RGFW_Event* RGFW_window_checkEvent(RGFW_window* win) { + if (win->_winArgs & RGFW_WINDOW_HIDE) + return NULL; + + if (win->src.eventIndex == 0) { + if (wl_display_roundtrip(win->src.display) == -1) { + return NULL; + } + RGFW_resetKey(); + } + + #ifdef __linux__ + RGFW_Event* event = RGFW_linux_updateJoystick(win); + if (event != NULL) + return event; + #endif + + if (win->src.eventLen == 0) { + return NULL; + } + + RGFW_Event ev = RGFW_eventPipe_pop(win); + + if (ev.type == 0 || win->event.type == RGFW_quit) { + return NULL; + } + + ev.frameTime = win->event.frameTime; + ev.frameTime2 = win->event.frameTime2; + ev.inFocus = win->event.inFocus; + win->event = ev; + + return &win->event; + } + + + void RGFW_window_resize(RGFW_window* win, RGFW_area a) { + RGFW_UNUSED(win); RGFW_UNUSED(a); + + /* TODO wayland */ + } + + void RGFW_window_move(RGFW_window* win, RGFW_point v) { + RGFW_UNUSED(win); RGFW_UNUSED(v); + + /* TODO wayland */ + } + + void RGFW_window_setIcon(RGFW_window* win, u8* src, RGFW_area a, i32 channels) { + RGFW_UNUSED(win); RGFW_UNUSED(src); RGFW_UNUSED(a); RGFW_UNUSED(channels) + /* TODO wayland */ + } + + void RGFW_window_moveMouse(RGFW_window* win, RGFW_point v) { + RGFW_UNUSED(win); RGFW_UNUSED(v); + + /* TODO wayland */ + } + + void RGFW_window_showMouse(RGFW_window* win, i8 show) { + RGFW_UNUSED(win); + + if (show) { + + } + else { + + } + + /* TODO wayland */ + } + + b8 RGFW_window_isMaximized(RGFW_window* win) { + RGFW_UNUSED(win); + /* TODO wayland */ + return 0; + } + + b8 RGFW_window_isMinimized(RGFW_window* win) { + RGFW_UNUSED(win); + /* TODO wayland */ + return 0; + } + + b8 RGFW_window_isHidden(RGFW_window* win) { + RGFW_UNUSED(win); + /* TODO wayland */ + return 0; + } + + b8 RGFW_window_isFullscreen(RGFW_window* win) { + RGFW_UNUSED(win); + /* TODO wayland */ + return 0; + } + + RGFW_point RGFW_window_getMousePoint(RGFW_window* win) { + RGFW_UNUSED(win); + /* TODO wayland */ + return RGFW_POINT(0, 0); + } + + RGFW_point RGFW_getGlobalMousePoint(void) { + /* TODO wayland */ + return RGFW_POINT(0, 0); + } + + void RGFW_window_show(RGFW_window* win) { + //wl_surface_attach(win->src.surface, win->rc., 0, 0); + wl_surface_commit(win->src.surface); + + if (win->_winArgs & RGFW_WINDOW_HIDE) + win->_winArgs ^= RGFW_WINDOW_HIDE; + } + + void RGFW_window_hide(RGFW_window* win) { + wl_surface_attach(win->src.surface, NULL, 0, 0); + wl_surface_commit(win->src.surface); + win->_winArgs |= RGFW_WINDOW_HIDE; + } + + void RGFW_window_setMouseDefault(RGFW_window* win) { + RGFW_UNUSED(win); + + RGFW_window_setMouseStandard(win, RGFW_MOUSE_NORMAL); + } + + void RGFW_window_setMouseStandard(RGFW_window* win, u8 mouse) { + RGFW_UNUSED(win); + + static const char* iconStrings[] = { "left_ptr", "left_ptr", "text", "cross", "pointer", "e-resize", "n-resize", "nw-resize", "ne-resize", "all-resize", "not-allowed" }; + + struct wl_cursor* cursor = wl_cursor_theme_get_cursor(RGFW_wl_cursor_theme, iconStrings[mouse]); + RGFW_cursor_image = cursor->images[0]; + struct wl_buffer* cursor_buffer = wl_cursor_image_get_buffer(RGFW_cursor_image); + + wl_surface_attach(RGFW_cursor_surface, cursor_buffer, 0, 0); + wl_surface_commit(RGFW_cursor_surface); + } + + void RGFW_window_setMouse(RGFW_window* win, u8* image, RGFW_area a, i32 channels) { + RGFW_UNUSED(win); RGFW_UNUSED(image); RGFW_UNUSED(a); RGFW_UNUSED(channels) + //struct wl_cursor* cursor = wl_cursor_theme_get_cursor(RGFW_wl_cursor_theme, iconStrings[mouse]); + //RGFW_cursor_image = image; + struct wl_buffer* cursor_buffer = wl_cursor_image_get_buffer(RGFW_cursor_image); + + wl_surface_attach(RGFW_cursor_surface, cursor_buffer, 0, 0); + wl_surface_commit(RGFW_cursor_surface); + } + + void RGFW_window_setName(RGFW_window* win, char* name) { + xdg_toplevel_set_title(win->src.xdg_toplevel, name); + } + + void RGFW_window_setMousePassthrough(RGFW_window* win, b8 passthrough) { + RGFW_UNUSED(win); RGFW_UNUSED(passthrough); + + /* TODO wayland */ + } + + void RGFW_window_setBorder(RGFW_window* win, b8 border) { + RGFW_UNUSED(win); RGFW_UNUSED(border); + + /* TODO wayland */ + } + + void RGFW_window_restore(RGFW_window* win) { + RGFW_UNUSED(win); + + /* TODO wayland */ + } + + void RGFW_window_minimize(RGFW_window* win) { + RGFW_UNUSED(win); + + /* TODO wayland */ + } + + void RGFW_window_setMaxSize(RGFW_window* win, RGFW_area a) { + RGFW_UNUSED(win); RGFW_UNUSED(a); + + /* TODO wayland */ + } + + void RGFW_window_setMinSize(RGFW_window* win, RGFW_area a) { + RGFW_UNUSED(win); RGFW_UNUSED(a); + + /* TODO wayland */ + } + + RGFW_monitor RGFW_window_getMonitor(RGFW_window* win) { + RGFW_monitor m = {}; + RGFW_UNUSED(win); + RGFW_UNUSED(m); + /* TODO wayland */ + + return m; + } + + + #ifndef RGFW_EGL + void RGFW_window_swapInterval(RGFW_window* win, i32 swapInterval) { RGFW_UNUSED(win); RGFW_UNUSED(swapInterval); } + #endif + + void RGFW_window_swapBuffers(RGFW_window* win) { + assert(win != NULL); + + /* clear the window*/ + #ifdef RGFW_BUFFER + wl_surface_frame_done(win, NULL, 0); + if (!(win->_winArgs & RGFW_NO_GPU_RENDER)) + #endif + { + #ifdef RGFW_OPENGL + eglSwapBuffers(win->src.EGL_display, win->src.EGL_surface); + #endif + } + + wl_display_flush(win->src.display); + } + + void RGFW_window_close(RGFW_window* win) { + #ifdef RGFW_EGL + RGFW_closeEGL(win); + #endif + + if (RGFW_root == win) { + RGFW_root = NULL; + } + + xdg_toplevel_destroy(win->src.xdg_toplevel); + xdg_surface_destroy(win->src.xdg_surface); + wl_surface_destroy(win->src.surface); + + #ifdef RGFW_BUFFER + wl_buffer_destroy(win->src.wl_buffer); + #endif + + wl_display_disconnect(win->src.display); + RGFW_FREE(win); + } + + RGFW_monitor RGFW_getPrimaryMonitor(void) { + /* TODO wayland */ + + return (RGFW_monitor){}; + } + + RGFW_monitor* RGFW_getMonitors(void) { + /* TODO wayland */ + + return NULL; + } + + void RGFW_writeClipboard(const char* text, u32 textLen) { + RGFW_UNUSED(text); RGFW_UNUSED(textLen); + + /* TODO wayland */ + } + + char* RGFW_readClipboard(size_t* size) { + RGFW_UNUSED(size); + + /* TODO wayland */ + + return NULL; + } +#endif /* RGFW_WAYLAND */ + +/* + End of Wayland defines +*/ /* @@ -3822,6 +4997,8 @@ Start of Linux / Unix defines #ifdef RGFW_WINDOWS #define WIN32_LEAN_AND_MEAN + #define OEMRESOURCE + #include #include #include @@ -3829,8 +5006,6 @@ Start of Linux / Unix defines #include #include #include - #include - #include #ifndef RGFW_NO_XINPUT typedef DWORD (WINAPI * PFN_XInputGetState)(DWORD,XINPUT_STATE*); @@ -3873,13 +5048,6 @@ Start of Linux / Unix defines #define wglGetSwapIntervalEXT wglGetSwapIntervalEXTSrc - -#if defined(RGFW_DIRECTX) - RGFW_directXinfo RGFW_dxInfo; - - RGFW_directXinfo* RGFW_getDirectXInfo(void) { return &RGFW_dxInfo; } -#endif - void* RGFWjoystickApi = NULL; /* these two wgl functions need to be preloaded */ @@ -3893,7 +5061,6 @@ Start of Linux / Unix defines #define WGL_DRAW_TO_WINDOW_ARB 0x2001 #define WGL_ACCELERATION_ARB 0x2003 #define WGL_NO_ACCELERATION_ARB 0x2025 -#define WGL_SUPPORT_OPENGL_ARB 0x2010 #define WGL_DOUBLE_BUFFER_ARB 0x2011 #define WGL_COLOR_BITS_ARB 0x2014 #define WGL_RED_BITS_ARB 0x2015 @@ -3990,7 +5157,7 @@ static HMODULE wglinstance = NULL; #endif __declspec(dllimport) u32 __stdcall timeBeginPeriod(u32 uPeriod); - + #ifndef RGFW_NO_XINPUT void RGFW_loadXInput(void) { u32 i; @@ -4048,7 +5215,7 @@ static HMODULE wglinstance = NULL; OSMesaMakeCurrent(win->src.ctx, win->buffer, GL_UNSIGNED_BYTE, win->r.w, win->r.h); #endif #else -RGFW_UNUSED(win); /* if buffer rendering is not being used */ +RGFW_UNUSED(win); /*!< if buffer rendering is not being used */ #endif } @@ -4056,16 +5223,14 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ DragAcceptFiles(win->src.window, allow); } + void RGFW_releaseCursor(RGFW_window* win) { + ClipCursor(NULL); + const RAWINPUTDEVICE id = { 0x01, 0x02, RIDEV_REMOVE, NULL }; + RegisterRawInputDevices(&id, 1, sizeof(id)); + } + void RGFW_captureCursor(RGFW_window* win, RGFW_rect rect) { RGFW_UNUSED(win) - - if (!rect.x && !rect.y && rect.w && !rect.h) { - ClipCursor(NULL); - const RAWINPUTDEVICE id = { 0x01, 0x02, RIDEV_REMOVE, NULL }; - RegisterRawInputDevices(&id, 1, sizeof(id)); - - return; - } RECT clipRect; GetClientRect(win->src.window, &clipRect); @@ -4101,9 +5266,7 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ wglGetCurrentContextSRC = (PFN_wglGetCurrentContext) GetProcAddress(wglinstance, "wglGetCurrentContext"); #endif } - - timeBeginPeriod(1); - + if (name[0] == 0) name = (char*) " "; RGFW_eventWindow.r = RGFW_RECT(-1, -1, -1, -1); @@ -4117,7 +5280,12 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ HINSTANCE inh = GetModuleHandleA(NULL); - WNDCLASSA Class = { 0 }; /* Setup the Window class. */ + #ifndef __cplusplus + WNDCLASSA Class = { 0 }; /*!< Setup the Window class. */ + #else + WNDCLASSA Class = { }; + #endif + Class.lpszClassName = name; Class.hInstance = inh; Class.hCursor = LoadCursor(NULL, IDC_ARROW); @@ -4130,7 +5298,7 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ RECT windowRect, clientRect; if (!(args & RGFW_NO_BORDER)) { - window_style |= WS_CAPTION | WS_SYSMENU | WS_BORDER | WS_VISIBLE | WS_MINIMIZEBOX; + window_style |= WS_CAPTION | WS_SYSMENU | WS_BORDER | WS_MINIMIZEBOX; if (!(args & RGFW_NO_RESIZE)) window_style |= WS_SIZEBOX | WS_MAXIMIZEBOX | WS_THICKFRAME; @@ -4215,17 +5383,26 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ #ifdef RGFW_OPENGL HDC dummy_dc = GetDC(dummyWin); - - PIXELFORMATDESCRIPTOR pfd = { - .nSize = sizeof(pfd), - .nVersion = 1, - .iPixelType = PFD_TYPE_RGBA, - .dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, - .cColorBits = 24, - .cAlphaBits = 8, - .iLayerType = PFD_MAIN_PLANE, - .cDepthBits = 32, - .cStencilBits = 8, + + u32 pfd_flags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL; + + //if (RGFW_DOUBLE_BUFFER) + pfd_flags |= PFD_DOUBLEBUFFER; + + PIXELFORMATDESCRIPTOR pfd = { + sizeof(pfd), + 1, /* version */ + pfd_flags, + PFD_TYPE_RGBA, /* ipixel type */ + 24, /* color bits */ + 0, 0, 0, 0, 0, 0, + 8, /* alpha bits */ + 0, 0, 0, 0, 0, 0, + 32, /* depth bits */ + 8, /* stencil bits */ + 0, + PFD_MAIN_PLANE, /* Layer type */ + 0, 0, 0, 0 }; int pixel_format = ChoosePixelFormat(dummy_dc, &pfd); @@ -4242,41 +5419,41 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ wglMakeCurrent(dummy_dc, 0); wglDeleteContext(dummy_context); ReleaseDC(dummyWin, dummy_dc); - + + /* try to create the pixel format we want for opengl and then try to create an opengl context for the specified version */ if (wglCreateContextAttribsARB != NULL) { - PIXELFORMATDESCRIPTOR pfd = (PIXELFORMATDESCRIPTOR){ sizeof(pfd), 1, PFD_TYPE_RGBA, PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, 32, 8, PFD_MAIN_PLANE, 24, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + PIXELFORMATDESCRIPTOR pfd = {sizeof(pfd), 1, pfd_flags, PFD_TYPE_RGBA, 32, 8, PFD_MAIN_PLANE, 24, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; if (args & RGFW_OPENGL_SOFTWARE) pfd.dwFlags |= PFD_GENERIC_FORMAT | PFD_GENERIC_ACCELERATED; if (wglChoosePixelFormatARB != NULL) { - i32* pixel_format_attribs = (i32*)RGFW_initAttribs(args & RGFW_OPENGL_SOFTWARE); + i32* pixel_format_attribs = (i32*)RGFW_initFormatAttribs(args & RGFW_OPENGL_SOFTWARE); int pixel_format; UINT num_formats; wglChoosePixelFormatARB(win->src.hdc, pixel_format_attribs, 0, 1, &pixel_format, &num_formats); if (!num_formats) { - printf("Failed to set the OpenGL 3.3 pixel format.\n"); + printf("Failed to create a pixel format for WGL.\n"); } DescribePixelFormat(win->src.hdc, pixel_format, sizeof(pfd), &pfd); if (!SetPixelFormat(win->src.hdc, pixel_format, &pfd)) { - printf("Failed to set the OpenGL 3.3 pixel format.\n"); + printf("Failed to set the WGL pixel format.\n"); } } - + + /* create opengl/WGL context for the specified version */ u32 index = 0; i32 attribs[40]; - SET_ATTRIB(WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB); - - if (RGFW_majorVersion || RGFW_minorVersion) { - SET_ATTRIB(WGL_CONTEXT_MAJOR_VERSION_ARB, RGFW_majorVersion); - SET_ATTRIB(WGL_CONTEXT_MINOR_VERSION_ARB, RGFW_minorVersion); + if (RGFW_profile == RGFW_GL_CORE) { + SET_ATTRIB(WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB); } - - SET_ATTRIB(WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB); - + else { + SET_ATTRIB(WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB); + } + if (RGFW_majorVersion || RGFW_minorVersion) { SET_ATTRIB(WGL_CONTEXT_MAJOR_VERSION_ARB, RGFW_majorVersion); SET_ATTRIB(WGL_CONTEXT_MINOR_VERSION_ARB, RGFW_minorVersion); @@ -4285,7 +5462,7 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ SET_ATTRIB(0, 0); win->src.ctx = (HGLRC)wglCreateContextAttribsARB(win->src.hdc, NULL, attribs); - } else { + } else { /* fall back to a default context (probably opengl 2 or something) */ fprintf(stderr, "Failed to create an accelerated OpenGL Context\n"); int pixel_format = ChoosePixelFormat(win->src.hdc, &pfd); @@ -4659,7 +5836,7 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ CharLowerBuffA(keyName, 16); } } - + RGFW_updateLockState(win, (GetKeyState(VK_CAPITAL) & 0x0001), (GetKeyState(VK_NUMLOCK) & 0x0001)); strncpy(win->event.keyName, keyName, 16); @@ -4670,6 +5847,7 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ } win->event.type = RGFW_keyPressed; + win->event.repeat = RGFW_isPressed(win, win->event.keyCode); RGFW_keyboard[win->event.keyCode].current = 1; RGFW_keyCallback(win, win->event.keyCode, win->event.keyName, win->event.lockState, 1); break; @@ -4706,8 +5884,8 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ break; win->event.type = RGFW_mousePosChanged; - win->event.point.x = -raw->data.mouse.lLastX; - win->event.point.y = -raw->data.mouse.lLastY; + win->event.point.x = raw->data.mouse.lLastX; + win->event.point.y = raw->data.mouse.lLastY; break; } @@ -4830,7 +6008,11 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ u8 RGFW_window_isFullscreen(RGFW_window* win) { assert(win != NULL); + #ifndef __cplusplus WINDOWPLACEMENT placement = { 0 }; + #else + WINDOWPLACEMENT placement = { }; + #endif GetWindowPlacement(win->src.window, &placement); return placement.showCmd == SW_SHOWMAXIMIZED; } @@ -4844,7 +6026,11 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ u8 RGFW_window_isMinimized(RGFW_window* win) { assert(win != NULL); + #ifndef __cplusplus WINDOWPLACEMENT placement = { 0 }; + #else + WINDOWPLACEMENT placement = { }; + #endif GetWindowPlacement(win->src.window, &placement); return placement.showCmd == SW_SHOWMINIMIZED; } @@ -4852,7 +6038,11 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ u8 RGFW_window_isMaximized(RGFW_window* win) { assert(win != NULL); + #ifndef __cplusplus WINDOWPLACEMENT placement = { 0 }; + #else + WINDOWPLACEMENT placement = { }; + #endif GetWindowPlacement(win->src.window, &placement); return placement.showCmd == SW_SHOWMAXIMIZED; } @@ -4892,7 +6082,7 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ for (deviceIndex = 0; EnumDisplayDevicesA(0, (DWORD) deviceIndex, &dd, 0); deviceIndex++) { char* deviceName = dd.DeviceName; if (EnumDisplayDevicesA(deviceName, info.iIndex, &dd, 0)) { - strncpy(monitor.name, dd.DeviceString, 128); /* copy the monitor's name */ + strncpy(monitor.name, dd.DeviceString, 128); /*!< copy the monitor's name */ break; } } @@ -4904,6 +6094,10 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ monitor.rect.h = monitorInfo.rcWork.bottom - monitorInfo.rcWork.top; #ifndef RGFW_NO_DPI + #ifndef USER_DEFAULT_SCREEN_DPI + #define USER_DEFAULT_SCREEN_DPI 96 + #endif + if (GetDpiForMonitor != NULL) { u32 x, y; GetDpiForMonitor(src, MDT_ANGULAR_DPI, &x, &y); @@ -4945,8 +6139,12 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ } RGFW_monitor RGFW_getPrimaryMonitor(void) { + #ifdef __cplusplus + return win32CreateMonitor(MonitorFromPoint({ 0, 0 }, MONITOR_DEFAULTTOPRIMARY)); + #else return win32CreateMonitor(MonitorFromPoint((POINT) { 0, 0 }, MONITOR_DEFAULTTOPRIMARY)); - } + #endif + } RGFW_monitor* RGFW_getMonitors(void) { RGFW_mInfo info; @@ -5102,10 +6300,10 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ #endif #ifdef RGFW_OPENGL - wglDeleteContext((HGLRC) win->src.ctx); /* delete opengl context */ + wglDeleteContext((HGLRC) win->src.ctx); /*!< delete opengl context */ #endif - DeleteDC(win->src.hdc); /* delete device context */ - DestroyWindow(win->src.window); /* delete window */ + DeleteDC(win->src.hdc); /*!< delete device context */ + DestroyWindow(win->src.window); /*!< delete window */ #if defined(RGFW_OSMESA) if (win->buffer != NULL) @@ -5292,8 +6490,10 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ #ifdef RGFW_OPENGL void RGFW_window_makeCurrent_OpenGL(RGFW_window* win) { - assert(win != NULL); - wglMakeCurrent(win->src.hdc, (HGLRC) win->src.ctx); + if (win == NULL) + wglMakeCurrent(NULL, NULL); + else + wglMakeCurrent(win->src.hdc, (HGLRC) win->src.ctx); } #endif @@ -5308,7 +6508,6 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ if (loadSwapFunc == NULL) { fprintf(stderr, "wglSwapIntervalEXT not supported\n"); - win->fpsCap = (swapInterval == 1) ? 0 : swapInterval; return; } @@ -5319,18 +6518,15 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ if (wglSwapIntervalEXT(swapInterval) == FALSE) fprintf(stderr, "Failed to set swap interval\n"); - #endif - - win->fpsCap = (swapInterval == 1) ? 0 : swapInterval; + #else + RGFW_UNUSED(swapInterval); + #endif } #endif void RGFW_window_swapBuffers(RGFW_window* win) { - assert(win != NULL); - - RGFW_window_makeCurrent(win); - + //assert(win != NULL); /* clear the window*/ if (!(win->_winArgs & RGFW_NO_CPU_RENDER)) { @@ -5356,8 +6552,6 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ win->src.swapchain->lpVtbl->Present(win->src.swapchain, 0, 0); #endif } - - RGFW_window_checkFPS(win); } char* createUTF8FromWideStringWin32(const WCHAR* source) { @@ -5378,20 +6572,28 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ return target; } + + static inline LARGE_INTEGER RGFW_win32_initTimer(void) { + static LARGE_INTEGER frequency = {{0, 0}}; + if (frequency.QuadPart == 0) { + timeBeginPeriod(1); + QueryPerformanceFrequency(&frequency); + } + + return frequency; + } u64 RGFW_getTimeNS(void) { - LARGE_INTEGER frequency; - QueryPerformanceFrequency(&frequency); + LARGE_INTEGER frequency = RGFW_win32_initTimer(); LARGE_INTEGER counter; QueryPerformanceCounter(&counter); - return (u64) (counter.QuadPart * 1e9 / frequency.QuadPart); + return (u64) ((counter.QuadPart * 1e9) / frequency.QuadPart); } u64 RGFW_getTime(void) { - LARGE_INTEGER frequency; - QueryPerformanceFrequency(&frequency); + LARGE_INTEGER frequency = RGFW_win32_initTimer(); LARGE_INTEGER counter; QueryPerformanceCounter(&counter); @@ -5720,11 +6922,9 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ NSWindowStyleMaskHUDWindow = 1 << 13 }; - typedef const char* NSPasteboardType; NSPasteboardType const NSPasteboardTypeString = "public.utf8-plain-text"; // Replaces NSStringPboardType - typedef NS_ENUM(i32, NSDragOperation) { NSDragOperationNone = 0, NSDragOperationCopy = 1, @@ -6002,7 +7202,7 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ OSMesaMakeCurrent(win->src.ctx, win->buffer, GL_UNSIGNED_BYTE, win->r.w, win->r.h); #endif #else - RGFW_UNUSED(win); /* if buffer rendering is not being used */ + RGFW_UNUSED(win); /*!< if buffer rendering is not being used */ #endif } @@ -6063,20 +7263,22 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ #ifdef RGFW_OPENGL if ((args & RGFW_NO_INIT_API) == 0) { - void* attrs = RGFW_initAttribs(args & RGFW_OPENGL_SOFTWARE); + void* attrs = RGFW_initFormatAttribs(args & RGFW_OPENGL_SOFTWARE); void* format = NSOpenGLPixelFormat_initWithAttributes(attrs); if (format == NULL) { - printf("Failed to load pixel format "); + printf("Failed to load pixel format for OpenGL\n"); - void* attrs = RGFW_initAttribs(1); + void* attrs = RGFW_initFormatAttribs(1); format = NSOpenGLPixelFormat_initWithAttributes(attrs); if (format == NULL) printf("and loading software rendering OpenGL failed\n"); else printf("Switching to software rendering\n"); } - + + /* the pixel format can be passed directly to opengl context creation to create a context + this is because the format also includes information about the opengl version (which may be a bad thing) */ win->src.view = NSOpenGLView_initWithFrame((NSRect){{0, 0}, {win->r.w, win->r.h}}, format); objc_msgSend_void(win->src.view, sel_registerName("prepareOpenGL")); win->src.ctx = objc_msgSend_id(win->src.view, sel_registerName("openGLContext")); @@ -6164,6 +7366,7 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ } // Show the window + objc_msgSend_void_bool(NSApp, sel_registerName("activateIgnoringOtherApps:"), true); ((id(*)(id, SEL, SEL))objc_msgSend)(win->src.window, sel_registerName("makeKeyAndOrderFront:"), NULL); objc_msgSend_void_bool(win->src.window, sel_registerName("setIsVisible:"), true); @@ -6216,7 +7419,7 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ CGPoint point = CGEventGetLocation(e); CFRelease(e); - return RGFW_POINT((u32) point.x, (u32) point.y); /* the point is loaded during event checks */ + return RGFW_POINT((u32) point.x, (u32) point.y); /*!< the point is loaded during event checks */ } RGFW_point RGFW_window_getMousePoint(RGFW_window* win) { @@ -6340,7 +7543,7 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ id eventPool = objc_msgSend_class(objc_getClass("NSAutoreleasePool"), sel_registerName("alloc")); eventPool = objc_msgSend_id(eventPool, sel_registerName("init")); - void* date = (void*) ((id(*)(id, SEL, double))objc_msgSend) + void* date = (void*) ((id(*)(Class, SEL, double))objc_msgSend) (objc_getClass("NSDate"), sel_registerName("dateWithTimeIntervalSinceNow:"), waitMS); NSEvent* e = (NSEvent*) ((id(*)(id, SEL, NSEventMask, void*, NSString*, bool))objc_msgSend) @@ -6411,7 +7614,7 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ win->event.type = RGFW_mouseEnter; NSPoint p = ((NSPoint(*)(id, SEL)) objc_msgSend)(e, sel_registerName("locationInWindow")); - win->event.point = RGFW_POINT((u32) p.x, (u32) (win->r.h - p.y)); + win->event.point = RGFW_POINT((i32) p.x, (i32) (win->r.h - p.y)); RGFW_mouseNotifyCallBack(win, win->event.point, 1); break; } @@ -6429,6 +7632,7 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ win->event.type = RGFW_keyPressed; char* str = (char*)(const char*) NSString_to_char(objc_msgSend_id(e, sel_registerName("characters"))); strncpy(win->event.keyName, str, 16); + win->event.repeat = RGFW_isPressed(win, win->event.keyCode); RGFW_keyboard[win->event.keyCode].current = 1; RGFW_keyCallback(win, win->event.keyCode, win->event.keyName, win->event.lockState, 1); @@ -6501,7 +7705,7 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ p.x = ((CGFloat(*)(id, SEL))abi_objc_msgSend_fpret)(e, sel_registerName("deltaX")); p.y = ((CGFloat(*)(id, SEL))abi_objc_msgSend_fpret)(e, sel_registerName("deltaY")); - win->event.point = RGFW_POINT((u32) p.x, (u32) (p.y)); + win->event.point = RGFW_POINT((i32)p.x, (i32)p.y); } RGFW_mousePosCallback(win, win->event.point); @@ -6727,12 +7931,16 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ CGDisplayShowCursor(kCGDirectMainDisplay); objc_msgSend_void(mouse, sel_registerName("set")); } + + void RGFW_releaseCursor(RGFW_window* win) { + CGAssociateMouseAndMouseCursorPosition(1); + } void RGFW_captureCursor(RGFW_window* win, RGFW_rect r) { RGFW_UNUSED(win) CGWarpMouseCursorPosition(CGPointMake(r.x + (r.w / 2), r.y + (r.h / 2))); - CGAssociateMouseAndMouseCursorPosition((!r.x && !r.y && r.w && !r.h)); + CGAssociateMouseAndMouseCursorPosition(0); } void RGFW_window_moveMouse(RGFW_window* win, RGFW_point v) { @@ -6881,8 +8089,6 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ NSOpenGLContext_setValues(win->src.ctx, &swapInterval, 222); #endif - - win->fpsCap = (swapInterval == 1) ? 0 : swapInterval; } #endif @@ -6910,9 +8116,6 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ void RGFW_window_swapBuffers(RGFW_window* win) { assert(win != NULL); - - RGFW_window_makeCurrent(win); - /* clear the window*/ if (!(win->_winArgs & RGFW_NO_CPU_RENDER)) { @@ -6953,8 +8156,6 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ objc_msgSend_void(win->src.ctx, sel_registerName("flushBuffer")); #endif } - - RGFW_window_checkFPS(win); } void RGFW_window_close(RGFW_window* win) { @@ -7005,23 +8206,14 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ */ /* - Start of Web ASM defines + WEBASM defines */ #ifdef RGFW_WEBASM - - -#define RGFW_jsButtonPressed 7 /*!< a joystick button was pressed */ -#define RGFW_jsButtonReleased 8 /*!< a joystick button was released */ -#define RGFW_jsAxisMove 9 /*!< an axis of a joystick was moved*/ - -#define RGFW_mouseEnter 14 /* mouse entered the window */ -#define RGFW_mouseLeave 15 /* mouse left the window */ - RGFW_Event RGFW_events[20]; size_t RGFW_eventLen = 0; -EM_BOOL on_keydown(int eventType, const EmscriptenKeyboardEvent* e, void* userData) { +EM_BOOL Emscripten_on_keydown(int eventType, const EmscriptenKeyboardEvent* e, void* userData) { RGFW_UNUSED(eventType); RGFW_UNUSED(userData); RGFW_events[RGFW_eventLen].type = RGFW_keyPressed; @@ -7032,12 +8224,12 @@ EM_BOOL on_keydown(int eventType, const EmscriptenKeyboardEvent* e, void* userDa RGFW_keyboard[RGFW_apiKeyCodeToRGFW(e->keyCode)].prev = RGFW_keyboard[RGFW_apiKeyCodeToRGFW(e->keyCode)].current; RGFW_keyboard[RGFW_apiKeyCodeToRGFW(e->keyCode)].current = 1; - RGFW_keyCallback(RGFW_root, e->keyCode, RGFW_events[RGFW_eventLen].keyName, 0, 1); - + RGFW_keyCallback(RGFW_root, RGFW_apiKeyCodeToRGFW(e->keyCode), RGFW_events[RGFW_eventLen].keyName, 0, 1); + return EM_TRUE; } -EM_BOOL on_keyup(int eventType, const EmscriptenKeyboardEvent* e, void* userData) { +EM_BOOL Emscripten_on_keyup(int eventType, const EmscriptenKeyboardEvent* e, void* userData) { RGFW_UNUSED(eventType); RGFW_UNUSED(userData); RGFW_events[RGFW_eventLen].type = RGFW_keyReleased; @@ -7049,12 +8241,12 @@ EM_BOOL on_keyup(int eventType, const EmscriptenKeyboardEvent* e, void* userData RGFW_keyboard[RGFW_apiKeyCodeToRGFW(e->keyCode)].prev = RGFW_keyboard[RGFW_apiKeyCodeToRGFW(e->keyCode)].current; RGFW_keyboard[RGFW_apiKeyCodeToRGFW(e->keyCode)].current = 0; - RGFW_keyCallback(RGFW_root, e->keyCode, RGFW_events[RGFW_eventLen].keyName, 0, 0); + RGFW_keyCallback(RGFW_root, RGFW_apiKeyCodeToRGFW(e->keyCode), RGFW_events[RGFW_eventLen].keyName, 0, 0); return EM_TRUE; } -EM_BOOL on_resize(int eventType, const EmscriptenUiEvent* e, void* userData) { +EM_BOOL Emscripten_on_resize(int eventType, const EmscriptenUiEvent* e, void* userData) { RGFW_UNUSED(eventType); RGFW_UNUSED(userData); RGFW_events[RGFW_eventLen].type = RGFW_windowResized; @@ -7064,7 +8256,7 @@ EM_BOOL on_resize(int eventType, const EmscriptenUiEvent* e, void* userData) { return EM_TRUE; } -EM_BOOL on_fullscreenchange(int eventType, const EmscriptenFullscreenChangeEvent* e, void* userData) { +EM_BOOL Emscripten_on_fullscreenchange(int eventType, const EmscriptenFullscreenChangeEvent* e, void* userData) { RGFW_UNUSED(eventType); RGFW_UNUSED(userData); RGFW_events[RGFW_eventLen].type = RGFW_windowResized; @@ -7075,7 +8267,7 @@ EM_BOOL on_fullscreenchange(int eventType, const EmscriptenFullscreenChangeEvent return EM_TRUE; } -EM_BOOL on_focusin(int eventType, const EmscriptenFocusEvent* e, void* userData) { +EM_BOOL Emscripten_on_focusin(int eventType, const EmscriptenFocusEvent* e, void* userData) { RGFW_UNUSED(eventType); RGFW_UNUSED(userData); RGFW_UNUSED(e); RGFW_events[RGFW_eventLen].type = RGFW_focusIn; @@ -7086,7 +8278,7 @@ EM_BOOL on_focusin(int eventType, const EmscriptenFocusEvent* e, void* userData) return EM_TRUE; } -EM_BOOL on_focusout(int eventType, const EmscriptenFocusEvent* e, void* userData) { +EM_BOOL Emscripten_on_focusout(int eventType, const EmscriptenFocusEvent* e, void* userData) { RGFW_UNUSED(eventType); RGFW_UNUSED(userData); RGFW_UNUSED(e); RGFW_events[RGFW_eventLen].type = RGFW_focusOut; @@ -7097,13 +8289,13 @@ EM_BOOL on_focusout(int eventType, const EmscriptenFocusEvent* e, void* userData return EM_TRUE; } -EM_BOOL on_mousemove(int eventType, const EmscriptenMouseEvent* e, void* userData) { +EM_BOOL Emscripten_on_mousemove(int eventType, const EmscriptenMouseEvent* e, void* userData) { RGFW_UNUSED(eventType); RGFW_UNUSED(userData); RGFW_events[RGFW_eventLen].type = RGFW_mousePosChanged; if ((RGFW_root->_winArgs & RGFW_HOLD_MOUSE)) { - RGFW_point p = RGFW_POINT(-e->movementX, -e->movementY); + RGFW_point p = RGFW_POINT(e->movementX, e->movementY); RGFW_events[RGFW_eventLen].point = p; } else @@ -7114,7 +8306,7 @@ EM_BOOL on_mousemove(int eventType, const EmscriptenMouseEvent* e, void* userDat return EM_TRUE; } -EM_BOOL on_mousedown(int eventType, const EmscriptenMouseEvent* e, void* userData) { +EM_BOOL Emscripten_on_mousedown(int eventType, const EmscriptenMouseEvent* e, void* userData) { RGFW_UNUSED(eventType); RGFW_UNUSED(userData); RGFW_events[RGFW_eventLen].type = RGFW_mouseButtonPressed; @@ -7131,7 +8323,7 @@ EM_BOOL on_mousedown(int eventType, const EmscriptenMouseEvent* e, void* userDat return EM_TRUE; } -EM_BOOL on_mouseup(int eventType, const EmscriptenMouseEvent* e, void* userData) { +EM_BOOL Emscripten_on_mouseup(int eventType, const EmscriptenMouseEvent* e, void* userData) { RGFW_UNUSED(eventType); RGFW_UNUSED(userData); RGFW_events[RGFW_eventLen].type = RGFW_mouseButtonReleased; @@ -7147,7 +8339,7 @@ EM_BOOL on_mouseup(int eventType, const EmscriptenMouseEvent* e, void* userData) return EM_TRUE; } -EM_BOOL on_wheel(int eventType, const EmscriptenWheelEvent* e, void* userData) { +EM_BOOL Emscripten_on_wheel(int eventType, const EmscriptenWheelEvent* e, void* userData) { RGFW_UNUSED(eventType); RGFW_UNUSED(userData); RGFW_events[RGFW_eventLen].type = RGFW_mouseButtonPressed; @@ -7164,54 +8356,82 @@ EM_BOOL on_wheel(int eventType, const EmscriptenWheelEvent* e, void* userData) { return EM_TRUE; } -EM_BOOL on_touchstart(int eventType, const EmscriptenTouchEvent* e, void* userData) { +EM_BOOL Emscripten_on_touchstart(int eventType, const EmscriptenTouchEvent* e, void* userData) { RGFW_UNUSED(eventType); RGFW_UNUSED(userData); - RGFW_events[RGFW_eventLen].type = RGFW_mouseButtonPressed; - RGFW_events[RGFW_eventLen].point = RGFW_POINT(e->touches[0].targetX, e->touches[0].targetY); - RGFW_events[RGFW_eventLen].button = 1; - RGFW_events[RGFW_eventLen].scroll = 0; + size_t i; + for (i = 0; i < (size_t)e->numTouches; i++) { + RGFW_events[RGFW_eventLen].type = RGFW_mouseButtonPressed; + RGFW_events[RGFW_eventLen].point = RGFW_POINT(e->touches[i].targetX, e->touches[i].targetY); + RGFW_events[RGFW_eventLen].button = 1; + RGFW_events[RGFW_eventLen].scroll = 0; - RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].prev = RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current; - RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current = 1; + RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].prev = RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current; + RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current = 1; - RGFW_mouseButtonCallback(RGFW_root, RGFW_events[RGFW_eventLen].button, RGFW_events[RGFW_eventLen].scroll, 1); - RGFW_eventLen++; + RGFW_mousePosCallback(RGFW_root, RGFW_events[RGFW_eventLen].point); + + RGFW_mouseButtonCallback(RGFW_root, RGFW_events[RGFW_eventLen].button, RGFW_events[RGFW_eventLen].scroll, 1); + RGFW_eventLen++; + } return EM_TRUE; } -EM_BOOL on_touchmove(int eventType, const EmscriptenTouchEvent* e, void* userData) { +EM_BOOL Emscripten_on_touchmove(int eventType, const EmscriptenTouchEvent* e, void* userData) { RGFW_UNUSED(eventType); RGFW_UNUSED(userData); + + size_t i; + for (i = 0; i < (size_t)e->numTouches; i++) { + RGFW_events[RGFW_eventLen].type = RGFW_mousePosChanged; + RGFW_events[RGFW_eventLen].point = RGFW_POINT(e->touches[i].targetX, e->touches[i].targetY); - RGFW_events[RGFW_eventLen].type = RGFW_mousePosChanged; - RGFW_events[RGFW_eventLen].point = RGFW_POINT(e->touches[0].targetX, e->touches[0].targetY); - - RGFW_mousePosCallback(RGFW_root, RGFW_events[RGFW_eventLen].point); - RGFW_eventLen++; - - return EM_TRUE; + RGFW_mousePosCallback(RGFW_root, RGFW_events[RGFW_eventLen].point); + RGFW_eventLen++; + } + return EM_TRUE; } -EM_BOOL on_touchend(int eventType, const EmscriptenTouchEvent* e, void* userData) { +EM_BOOL Emscripten_on_touchend(int eventType, const EmscriptenTouchEvent* e, void* userData) { RGFW_UNUSED(eventType); RGFW_UNUSED(userData); - RGFW_events[RGFW_eventLen].type = RGFW_mouseButtonReleased; - RGFW_events[RGFW_eventLen].point = RGFW_POINT(e->touches[0].targetX, e->touches[0].targetY); - RGFW_events[RGFW_eventLen].button = 1; - RGFW_events[RGFW_eventLen].scroll = 0; - - RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].prev = RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current; - RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current = 0; - - RGFW_mouseButtonCallback(RGFW_root, RGFW_events[RGFW_eventLen].button, RGFW_events[RGFW_eventLen].scroll, 0); - RGFW_eventLen++; + size_t i; + for (i = 0; i < (size_t)e->numTouches; i++) { + RGFW_events[RGFW_eventLen].type = RGFW_mouseButtonReleased; + RGFW_events[RGFW_eventLen].point = RGFW_POINT(e->touches[i].targetX, e->touches[i].targetY); + RGFW_events[RGFW_eventLen].button = 1; + RGFW_events[RGFW_eventLen].scroll = 0; + RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].prev = RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current; + RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current = 0; + + RGFW_mouseButtonCallback(RGFW_root, RGFW_events[RGFW_eventLen].button, RGFW_events[RGFW_eventLen].scroll, 0); + RGFW_eventLen++; + } return EM_TRUE; } -EM_BOOL on_touchcancel(int eventType, const EmscriptenTouchEvent* e, void* userData) { RGFW_UNUSED(eventType); RGFW_UNUSED(userData); RGFW_UNUSED(e); return EM_TRUE; } +EM_BOOL Emscripten_on_touchcancel(int eventType, const EmscriptenTouchEvent* e, void* userData) { RGFW_UNUSED(eventType); RGFW_UNUSED(userData); RGFW_UNUSED(e); return EM_TRUE; } +EM_BOOL Emscripten_on_gamepad(int eventType, const EmscriptenGamepadEvent *gamepadEvent, void *userData) { + RGFW_UNUSED(eventType); RGFW_UNUSED(userData); + + if (gamepadEvent->index >= 4) + return 0; + + RGFW_joysticks[gamepadEvent->index] = gamepadEvent->connected; + + return 1; // The event was consumed by the callback handler +} + +void EMSCRIPTEN_KEEPALIVE Emscripten_onDrop(size_t count) { + if (!(RGFW_root->_winArgs & RGFW_ALLOW_DND)) + return; + + RGFW_events[RGFW_eventLen].droppedFilesCount = count; + RGFW_dndCallback(RGFW_root, RGFW_events[RGFW_eventLen].droppedFiles, count); + RGFW_eventLen++; +} b8 RGFW_stopCheckEvents_bool = RGFW_FALSE; void RGFW_stopCheckEvents(void) { @@ -7221,6 +8441,9 @@ void RGFW_stopCheckEvents(void) { void RGFW_window_eventWait(RGFW_window* win, i32 waitMS) { RGFW_UNUSED(win); + if (waitMS == 0) + return; + u32 start = (u32)(((u64)RGFW_getTimeNS()) / 1e+6); while ((RGFW_eventLen == 0) && RGFW_stopCheckEvents_bool == RGFW_FALSE && @@ -7244,25 +8467,57 @@ void RGFW_init_buffer(RGFW_window* win) { OSMesaMakeCurrent(win->src.ctx, win->buffer, GL_UNSIGNED_BYTE, win->r.w, win->r.h); #endif #else - RGFW_UNUSED(win); /* if buffer rendering is not being used */ + RGFW_UNUSED(win); /*!< if buffer rendering is not being used */ #endif } +void EMSCRIPTEN_KEEPALIVE RGFW_makeSetValue(size_t index, char* file) { + /* This seems like a terrible idea, don't replicate this unless you hate yourself or the OS */ + /* TODO: find a better way to do this, + strcpy doesn't seem to work, maybe because of asyncio + */ + + RGFW_events[RGFW_eventLen].type = RGFW_dnd; + char** arr = (char**)&RGFW_events[RGFW_eventLen].droppedFiles[index]; + *arr = file; +} + +#include +#include +#include + +void EMSCRIPTEN_KEEPALIVE RGFW_mkdir(char* name) { mkdir(name, 0755); } + +void EMSCRIPTEN_KEEPALIVE RGFW_writeFile(const char *path, const char *data, size_t len) { + FILE* file = fopen(path, "w+"); + if (file == NULL) + return; + + fwrite(data, sizeof(char), len, file); + fclose(file); +} + RGFW_window* RGFW_createWindow(const char* name, RGFW_rect rect, u16 args) { RGFW_UNUSED(name) - RGFW_UNUSED(RGFW_initAttribs); - + RGFW_UNUSED(RGFW_initFormatAttribs); + RGFW_window* win = RGFW_window_basic_init(rect, args); EmscriptenWebGLContextAttributes attrs; attrs.alpha = EM_TRUE; attrs.depth = EM_TRUE; + attrs.alpha = EM_TRUE; attrs.stencil = RGFW_STENCIL; attrs.antialias = RGFW_SAMPLES; attrs.premultipliedAlpha = EM_TRUE; attrs.preserveDrawingBuffer = EM_FALSE; - attrs.renderViaOffscreenBackBuffer = RGFW_AUX_BUFFERS; + + if (RGFW_DOUBLE_BUFFER == 0) + attrs.renderViaOffscreenBackBuffer = 0; + else + attrs.renderViaOffscreenBackBuffer = RGFW_AUX_BUFFERS; + attrs.failIfMajorPerformanceCaveat = EM_FALSE; attrs.majorVersion = (RGFW_majorVersion == 0) ? 1 : RGFW_majorVersion; attrs.minorVersion = RGFW_minorVersion; @@ -7279,22 +8534,79 @@ RGFW_window* RGFW_createWindow(const char* name, RGFW_rect rect, u16 args) { #endif emscripten_set_canvas_element_size("#canvas", rect.w, rect.h); + emscripten_set_window_title(name); /* load callbacks */ - emscripten_set_keydown_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, EM_FALSE, on_keydown); - emscripten_set_keyup_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, EM_FALSE, on_keyup); - emscripten_set_resize_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, EM_FALSE, on_resize); - emscripten_set_fullscreenchange_callback(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, NULL, EM_FALSE, on_fullscreenchange); - emscripten_set_mousemove_callback("#canvas", NULL, EM_FALSE, on_mousemove); - emscripten_set_touchstart_callback("#canvas", NULL, EM_FALSE, on_touchstart); - emscripten_set_touchend_callback("#canvas", NULL, EM_FALSE, on_touchend); - emscripten_set_touchmove_callback("#canvas", NULL, EM_FALSE, on_touchmove); - emscripten_set_touchcancel_callback("#canvas", NULL, EM_FALSE, on_touchcancel); - emscripten_set_mousedown_callback("#canvas", NULL, EM_FALSE, on_mousedown); - emscripten_set_mouseup_callback("#canvas", NULL, EM_FALSE, on_mouseup); - emscripten_set_wheel_callback("#canvas", NULL, EM_FALSE, on_wheel); - emscripten_set_focusin_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, EM_FALSE, on_focusin); - emscripten_set_focusout_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, EM_FALSE, on_focusout); + emscripten_set_keydown_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, EM_FALSE, Emscripten_on_keydown); + emscripten_set_keyup_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, EM_FALSE, Emscripten_on_keyup); + emscripten_set_resize_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, EM_FALSE, Emscripten_on_resize); + emscripten_set_fullscreenchange_callback(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, NULL, EM_FALSE, Emscripten_on_fullscreenchange); + emscripten_set_mousemove_callback("#canvas", NULL, EM_FALSE, Emscripten_on_mousemove); + emscripten_set_touchstart_callback("#canvas", NULL, EM_FALSE, Emscripten_on_touchstart); + emscripten_set_touchend_callback("#canvas", NULL, EM_FALSE, Emscripten_on_touchend); + emscripten_set_touchmove_callback("#canvas", NULL, EM_FALSE, Emscripten_on_touchmove); + emscripten_set_touchcancel_callback("#canvas", NULL, EM_FALSE, Emscripten_on_touchcancel); + emscripten_set_mousedown_callback("#canvas", NULL, EM_FALSE, Emscripten_on_mousedown); + emscripten_set_mouseup_callback("#canvas", NULL, EM_FALSE, Emscripten_on_mouseup); + emscripten_set_wheel_callback("#canvas", NULL, EM_FALSE, Emscripten_on_wheel); + emscripten_set_focusin_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, EM_FALSE, Emscripten_on_focusin); + emscripten_set_focusout_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, EM_FALSE, Emscripten_on_focusout); + emscripten_set_gamepadconnected_callback(NULL, 1, Emscripten_on_gamepad); + emscripten_set_gamepaddisconnected_callback(NULL, 1, Emscripten_on_gamepad); + + if (args & RGFW_ALLOW_DND) { + win->_winArgs |= RGFW_ALLOW_DND; + } + + EM_ASM({ + var canvas = document.getElementById('canvas'); + canvas.addEventListener('drop', function(e) { + e.preventDefault(); + if (e.dataTransfer.file < 0) + return; + + var filenamesArray = []; + var count = e.dataTransfer.files.length; + + /* Read and save the files to emscripten's files */ + var drop_dir = '.rgfw_dropped_files'; + Module._RGFW_mkdir(drop_dir); + + for (var i = 0; i < count; i++) { + var file = e.dataTransfer.files[i]; + + var path = '/' + drop_dir + '/' + file.name.replace("//", '_'); + var reader = new FileReader(); + + reader.onloadend = (e) => { + if (reader.readyState != 2) { + out('failed to read dropped file: '+file.name+': '+reader.error); + } + else { + var data = e.target.result; + + _RGFW_writeFile(path, new Uint8Array(data), file.size); + } + }; + + reader.readAsArrayBuffer(file); + // This works weird on modern opengl + var filename = stringToNewUTF8(path); + + filenamesArray.push(filename); + + Module._RGFW_makeSetValue(i, filename); + } + + Module._Emscripten_onDrop(count); + + for (var i = 0; i < count; ++i) { + _free(filenamesArray[i]); + } + }, true); + + canvas.addEventListener('dragover', function(e) { e.preventDefault(); return false; }, true); + }); RGFW_init_buffer(win); glViewport(0, 0, rect.w, rect.h); @@ -7314,14 +8626,59 @@ RGFW_window* RGFW_createWindow(const char* name, RGFW_rect rect, u16 args) { RGFW_Event* RGFW_window_checkEvent(RGFW_window* win) { static u8 index = 0; - + if (index == 0) RGFW_resetKey(); + /* check gamepads */ + for (int i = 0; (i < emscripten_get_num_gamepads()) && (i < 4); i++) { + if (RGFW_joysticks[i] == 0) + continue;; + + EmscriptenGamepadEvent gamepadState; + + if (emscripten_get_gamepad_status(i, &gamepadState) != EMSCRIPTEN_RESULT_SUCCESS) + break; + + // Register buttons data for every connected gamepad + for (int j = 0; (j < gamepadState.numButtons) && (j < 16); j++) { + u32 map[] = { + RGFW_JS_A, RGFW_JS_X, RGFW_JS_B, RGFW_JS_Y, + RGFW_JS_L1, RGFW_JS_R1, RGFW_JS_L2, RGFW_JS_R2, + RGFW_JS_SELECT, RGFW_JS_START, + 0, 0, + RGFW_JS_UP, RGFW_JS_DOWN, RGFW_JS_LEFT, RGFW_JS_RIGHT + }; + + u32 button = map[j]; + if (RGFW_jsPressed[i][button] != gamepadState.digitalButton[j]) { + win->event.type = RGFW_jsButtonPressed; + win->event.joystick = i; + win->event.button = map[j]; + return &win->event; + } + + RGFW_jsPressed[i][button] = gamepadState.digitalButton[j]; + } + + for (int j = 0; (j < gamepadState.numAxes) && (j < 4); j += 2) { + win->event.axisesCount = gamepadState.numAxes; + if (win->event.axis[j].x != gamepadState.axis[j] || + win->event.axis[j].y != gamepadState.axis[j + 1] + ) { + win->event.axis[j].x = gamepadState.axis[j]; + win->event.axis[j].y = gamepadState.axis[j + 1]; + win->event.type = RGFW_jsAxisMove; + win->event.joystick = i; + return &win->event; + } + } + } + + /* check queued events */ if (RGFW_eventLen == 0) return NULL; - RGFW_events[index].fps = win->event.fps; RGFW_events[index].frameTime = win->event.frameTime; RGFW_events[index].frameTime2 = win->event.frameTime2; RGFW_events[index].inFocus = win->event.inFocus; @@ -7389,6 +8746,14 @@ RGFW_point RGFW_getGlobalMousePoint(void) { return point; } +RGFW_point RGFW_window_getMousePoint(RGFW_window* win) { + RGFW_UNUSED(win); + + EmscriptenMouseEvent mouseEvent; + emscripten_get_mouse_status(&mouseEvent); + return RGFW_POINT( mouseEvent.targetX, mouseEvent.targetY); +} + void RGFW_window_setMousePassthrough(RGFW_window* win, b8 passthrough) { RGFW_UNUSED(win); @@ -7417,13 +8782,15 @@ char* RGFW_readClipboard(size_t* size) { if (size != NULL) *size = 0; - char* str = malloc(1); + char* str = (char*)malloc(1); str[0] = '\0'; return str; } void RGFW_window_swapBuffers(RGFW_window* win) { + RGFW_UNUSED(win); + #ifdef RGFW_BUFFER if (!(win->_winArgs & RGFW_NO_CPU_RENDER)) { glEnable(GL_TEXTURE_2D); @@ -7431,9 +8798,6 @@ void RGFW_window_swapBuffers(RGFW_window* win) { GLuint texture; glGenTextures(1,&texture); - //glPixelStorei( GL_PACK_ROW_LENGTH, RGFW_bufferSize.w); - //glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, RGFW_bufferSize.h); - glBindTexture(GL_TEXTURE_2D,texture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); @@ -7464,23 +8828,19 @@ void RGFW_window_swapBuffers(RGFW_window* win) { #endif emscripten_webgl_commit_frame(); - - if (win->fpsCap == 0 || win->fpsCap < 100) { - emscripten_sleep(0); - } - - RGFW_window_checkFPS(win); + emscripten_sleep(0); } void RGFW_window_makeCurrent_OpenGL(RGFW_window* win) { - emscripten_webgl_make_context_current(win->src.ctx); + if (win == NULL) + emscripten_webgl_make_context_current(0); + else + emscripten_webgl_make_context_current(win->src.ctx); } #ifndef RGFW_EGL -void RGFW_window_swapInterval(RGFW_window* win, i32 swapInterval) { - win->fpsCap = (swapInterval == 1) ? 0 : swapInterval; -} +void RGFW_window_swapInterval(RGFW_window* win, i32 swapInterval) { RGFW_UNUSED(win); RGFW_UNUSED(swapInterval); } #endif void RGFW_window_close(RGFW_window* win) { @@ -7512,16 +8872,22 @@ u64 RGFW_getTime(void) { return emscripten_get_now() * 1000; } +void RGFW_releaseCursor(RGFW_window* win) { + emscripten_exit_pointerlock(); +} + void RGFW_captureCursor(RGFW_window* win, RGFW_rect r) { RGFW_UNUSED(win) - if (!r.x && !r.y && !r.w && !r.h) { - emscripten_exit_pointerlock(); - return; - } emscripten_request_pointerlock("#canvas", 1); } + +void RGFW_window_setName(RGFW_window* win, char* name) { + RGFW_UNUSED(win); + emscripten_set_window_title(name); +} + /* unsupported functions */ RGFW_monitor* RGFW_getMonitors(void) { return NULL; } RGFW_monitor RGFW_getPrimaryMonitor(void) { return (RGFW_monitor){}; } @@ -7531,8 +8897,6 @@ void RGFW_window_setMaxSize(RGFW_window* win, RGFW_area a) { RGFW_UNUSED(win) RG void RGFW_window_minimize(RGFW_window* win) { RGFW_UNUSED(win)} void RGFW_window_restore(RGFW_window* win) { RGFW_UNUSED(win) } void RGFW_window_setBorder(RGFW_window* win, b8 border) { RGFW_UNUSED(win) RGFW_UNUSED(border) } -void RGFW_window_setDND(RGFW_window* win, b8 allow) { RGFW_UNUSED(win) RGFW_UNUSED(allow) } -void RGFW_window_setName(RGFW_window* win, char* name) { RGFW_UNUSED(win) RGFW_UNUSED(name) } void RGFW_window_setIcon(RGFW_window* win, u8* icon, RGFW_area a, i32 channels) { RGFW_UNUSED(win) RGFW_UNUSED(icon) RGFW_UNUSED(a) RGFW_UNUSED(channels) } void RGFW_window_hide(RGFW_window* win) { RGFW_UNUSED(win) } void RGFW_window_show(RGFW_window* win) {RGFW_UNUSED(win) } @@ -7546,7 +8910,7 @@ RGFW_monitor RGFW_window_getMonitor(RGFW_window* win) { RGFW_UNUSED(win) return /* end of web asm defines */ /* unix (macOS, linux, web asm) only stuff */ -#if defined(RGFW_X11) || defined(RGFW_MACOS) || defined(RGFW_WEBASM) +#if defined(RGFW_X11) || defined(RGFW_MACOS) || defined(RGFW_WEBASM) || defined(RGFW_WAYLAND) /* unix threading */ #ifndef RGFW_NO_THREADS #include @@ -7561,7 +8925,7 @@ RGFW_monitor RGFW_window_getMonitor(RGFW_window* win) { RGFW_UNUSED(win) return void RGFW_cancelThread(RGFW_thread thread) { pthread_cancel((pthread_t) thread); } void RGFW_joinThread(RGFW_thread thread) { pthread_join((pthread_t) thread, NULL); } #ifdef __linux__ - void RGFW_setThreadPriority(RGFW_thread thread, u8 priority) { pthread_setschedprio(thread, priority); } + void RGFW_setThreadPriority(RGFW_thread thread, u8 priority) { pthread_setschedprio((pthread_t)thread, priority); } #endif #endif @@ -7579,6 +8943,6 @@ RGFW_monitor RGFW_window_getMonitor(RGFW_window* win) { RGFW_UNUSED(win) return #endif /* end of unix / mac stuff*/ #endif /*RGFW_IMPLEMENTATION*/ -#ifdef __cplusplus +#if defined(__cplusplus) && !defined(__EMSCRIPTEN__) } #endif diff --git a/src/platforms/rcore_desktop_rgfw.c b/src/platforms/rcore_desktop_rgfw.c index d98c6391d..afea0c2e6 100644 --- a/src/platforms/rcore_desktop_rgfw.c +++ b/src/platforms/rcore_desktop_rgfw.c @@ -1239,15 +1239,15 @@ int InitPlatform(void) // Check selection OpenGL version if (rlGetVersion() == RL_OPENGL_21) { - RGFW_setGLVersion(2, 1); + RGFW_setGLVersion(RGFW_GL_CORE, 2, 1); } else if (rlGetVersion() == RL_OPENGL_33) { - RGFW_setGLVersion(3, 3); + RGFW_setGLVersion(RGFW_GL_CORE, 3, 3); } else if (rlGetVersion() == RL_OPENGL_43) { - RGFW_setGLVersion(4, 1); + RGFW_setGLVersion(RGFW_GL_CORE, 4, 1); } if (CORE.Window.flags & FLAG_MSAA_4X_HINT) From 7fab03c0b4f079a6450f03d82ca17f2e18be3477 Mon Sep 17 00:00:00 2001 From: hanaxars <156359933+hanaxars@users.noreply.github.com> Date: Mon, 19 Aug 2024 14:41:20 +0300 Subject: [PATCH 028/208] Fix warnings (#4264) Fix following gcc warnings when SVG enabled: rtextures.c: In function 'LoadImageSvg': rtextures.c:374:52: warning: pointer targets in passing argument 1 of 'nsvgParse' differ in signedness [-Wpointer-sign] 374 | struct NSVGimage *svgImage = nsvgParse(fileData, "px", 96.0f); | ^~~~~~~~ | | | unsigned char * In file included from rtextures.c:230: external/nanosvg.h:2952:28: note: expected 'char *' but argument is of type 'unsigned char *' 2952 | NSVGimage* nsvgParse(char* input, const char* units, float dpi) | ~~~~~~^~~~~ rtextures.c:407:43: warning: comparison of distinct pointer types lacks a cast [-Wcompare-distinct-pointer-types] 407 | if (isSvgStringValid && (fileData != fileNameOrString)) UnloadFileData(fileData); | ^~ rtextures.c: In function 'LoadImageFromMemory': rtextures.c:614:52: warning: passing argument 1 of 'nsvgParse' discards 'const' qualifier from pointer target type [-Wdiscarded-qualifiers] 614 | struct NSVGimage *svgImage = nsvgParse(fileData, "px", 96.0f); | ^~~~~~~~ external/nanosvg.h:2952:28: note: expected 'char *' but argument is of type 'const unsigned char *' 2952 | NSVGimage* nsvgParse(char* input, const char* units, float dpi) | ~~~~~~^~~~~ --- src/rtextures.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/rtextures.c b/src/rtextures.c index 5fa01c9df..f2faa1850 100644 --- a/src/rtextures.c +++ b/src/rtextures.c @@ -371,7 +371,7 @@ Image LoadImageSvg(const char *fileNameOrString, int width, int height) if (isSvgStringValid) { - struct NSVGimage *svgImage = nsvgParse(fileData, "px", 96.0f); + struct NSVGimage *svgImage = nsvgParse((char *)fileData, "px", 96.0f); unsigned char *img = RL_MALLOC(width*height*4); @@ -404,7 +404,7 @@ Image LoadImageSvg(const char *fileNameOrString, int width, int height) nsvgDeleteRasterizer(rast); } - if (isSvgStringValid && (fileData != fileNameOrString)) UnloadFileData(fileData); + if (isSvgStringValid && (fileData != (unsigned char *)fileNameOrString)) UnloadFileData(fileData); } #else TRACELOG(LOG_WARNING, "SVG image support not enabled, image can not be loaded"); @@ -611,7 +611,7 @@ Image LoadImageFromMemory(const char *fileType, const unsigned char *fileData, i (fileData[2] == 'v') && (fileData[3] == 'g')) { - struct NSVGimage *svgImage = nsvgParse(fileData, "px", 96.0f); + struct NSVGimage *svgImage = nsvgParse((char *)fileData, "px", 96.0f); unsigned char *img = RL_MALLOC(svgImage->width*svgImage->height*4); // Rasterize From 039df36f4b73cfd685c143f47e71abf93270e709 Mon Sep 17 00:00:00 2001 From: Ray Date: Tue, 20 Aug 2024 19:13:18 +0200 Subject: [PATCH 029/208] REVIEWED: Automation events mouse wheel #4263 --- examples/core/core_automation_events.c | 70 +++++++++++++------------- src/rcore.c | 7 +-- 2 files changed, 40 insertions(+), 37 deletions(-) diff --git a/examples/core/core_automation_events.c b/examples/core/core_automation_events.c index 319b013ba..64ca51fda 100644 --- a/examples/core/core_automation_events.c +++ b/examples/core/core_automation_events.c @@ -88,7 +88,7 @@ int main(void) // Update //---------------------------------------------------------------------------------- float deltaTime = 0.015f;//GetFrameTime(); - + // Dropped files logic //---------------------------------------------------------------------------------- if (IsFileDropped()) @@ -157,11 +157,6 @@ int main(void) } else player.canJump = true; - camera.zoom += ((float)GetMouseWheelMove()*0.05f); - - if (camera.zoom > 3.0f) camera.zoom = 3.0f; - else if (camera.zoom < 0.25f) camera.zoom = 0.25f; - if (IsKeyPressed(KEY_R)) { // Reset game state @@ -176,12 +171,44 @@ int main(void) } //---------------------------------------------------------------------------------- + // Events playing + // NOTE: Logic must be before Camera update because it depends on mouse-wheel value, + // that can be set by the played event... but some other inputs could be affected + //---------------------------------------------------------------------------------- + if (eventPlaying) + { + // NOTE: Multiple events could be executed in a single frame + while (playFrameCounter == aelist.events[currentPlayFrame].frame) + { + PlayAutomationEvent(aelist.events[currentPlayFrame]); + currentPlayFrame++; + + if (currentPlayFrame == aelist.count) + { + eventPlaying = false; + currentPlayFrame = 0; + playFrameCounter = 0; + + TraceLog(LOG_INFO, "FINISH PLAYING!"); + break; + } + } + + playFrameCounter++; + } + //---------------------------------------------------------------------------------- + // Update camera //---------------------------------------------------------------------------------- camera.target = player.position; camera.offset = (Vector2){ screenWidth/2.0f, screenHeight/2.0f }; float minX = 1000, minY = 1000, maxX = -1000, maxY = -1000; + // WARNING: On event replay, mouse-wheel internal value is set + camera.zoom += ((float)GetMouseWheelMove()*0.05f); + if (camera.zoom > 3.0f) camera.zoom = 3.0f; + else if (camera.zoom < 0.25f) camera.zoom = 0.25f; + for (int i = 0; i < MAX_ENVIRONMENT_ELEMENTS; i++) { EnvElement *element = &envElements[i]; @@ -200,8 +227,8 @@ int main(void) if (min.y > 0) camera.offset.y = screenHeight/2 - min.y; //---------------------------------------------------------------------------------- - // Toggle events recording - if (IsKeyPressed(KEY_S)) + // Events management + if (IsKeyPressed(KEY_S)) // Toggle events recording { if (!eventPlaying) { @@ -222,7 +249,7 @@ int main(void) } } } - else if (IsKeyPressed(KEY_A)) + else if (IsKeyPressed(KEY_A)) // Toggle events playing (WARNING: Starts next frame) { if (!eventRecording && (aelist.count > 0)) { @@ -241,32 +268,7 @@ int main(void) camera.zoom = 1.0f; } } - - if (eventPlaying) - { - // NOTE: Multiple events could be executed in a single frame - while (playFrameCounter == aelist.events[currentPlayFrame].frame) - { - TraceLog(LOG_INFO, "PLAYING: PlayFrameCount: %i | currentPlayFrame: %i | Event Frame: %i, param: %i", - playFrameCounter, currentPlayFrame, aelist.events[currentPlayFrame].frame, aelist.events[currentPlayFrame].params[0]); - - PlayAutomationEvent(aelist.events[currentPlayFrame]); - currentPlayFrame++; - if (currentPlayFrame == aelist.count) - { - eventPlaying = false; - currentPlayFrame = 0; - playFrameCounter = 0; - - TraceLog(LOG_INFO, "FINISH PLAYING!"); - break; - } - } - - playFrameCounter++; - } - if (eventRecording || eventPlaying) frameCounter++; else frameCounter = 0; //---------------------------------------------------------------------------------- diff --git a/src/rcore.c b/src/rcore.c index 5485ce8ce..e8041ea41 100644 --- a/src/rcore.c +++ b/src/rcore.c @@ -669,7 +669,6 @@ void InitWindow(int width, int height, const char *title) #endif #endif - CORE.Time.frameCounter = 0; CORE.Window.shouldClose = false; @@ -2707,8 +2706,8 @@ void PlayAutomationEvent(AutomationEvent event) } break; case INPUT_MOUSE_WHEEL_MOTION: // param[0]: x delta, param[1]: y delta { - CORE.Input.Mouse.currentWheelMove.x = (float)event.params[0]; break; - CORE.Input.Mouse.currentWheelMove.y = (float)event.params[1]; break; + CORE.Input.Mouse.currentWheelMove.x = (float)event.params[0]; + CORE.Input.Mouse.currentWheelMove.y = (float)event.params[1]; } break; case INPUT_TOUCH_UP: CORE.Input.Touch.currentTouchState[event.params[0]] = false; break; // param[0]: id case INPUT_TOUCH_DOWN: CORE.Input.Touch.currentTouchState[event.params[0]] = true; break; // param[0]: id @@ -2745,6 +2744,8 @@ void PlayAutomationEvent(AutomationEvent event) case ACTION_SETTARGETFPS: SetTargetFPS(event.params[0]); break; default: break; } + + TRACELOG(LOG_INFO, "AUTOMATION PLAY: Frame: %i | Event type: %i | Event parameters: %i, %i, %i", event.frame, event.type, event.params[0], event.params[1], event.params[2]); } #endif } From fa3f73d88174fb66d9b275e2970e4d201e6a9ecb Mon Sep 17 00:00:00 2001 From: Paperdomo101 <38697390+Paperdomo101@users.noreply.github.com> Date: Wed, 21 Aug 2024 20:07:52 +0800 Subject: [PATCH 030/208] [rshapes] Review DrawGradient color parameter names (#4270) void DrawCircleGradient(int centerX, int centerY, float radius, Color color1, Color color2); void DrawRectangleGradientV(int posX, int posY, int width, int height, Color color1, Color color2); void DrawRectangleGradientH(int posX, int posY, int width, int height, Color color1, Color color2); void DrawRectangleGradientEx(Rectangle rec, Color col1, Color col2, Color col3, Color col4); Have been changed to: void DrawCircleGradient(int centerX, int centerY, float radius, Color inner, Color outer); void DrawRectangleGradientV(int posX, int posY, int width, int height, Color top, Color bottom); void DrawRectangleGradientH(int posX, int posY, int width, int height, Color left, Color right); void DrawRectangleGradientEx(Rectangle rec, Color topLeft, Color bottomLeft, Color topRight, Color bottomRight); --- src/raylib.h | 8 ++++---- src/rshapes.c | 30 +++++++++++++----------------- 2 files changed, 17 insertions(+), 21 deletions(-) diff --git a/src/raylib.h b/src/raylib.h index 1cf34f004..0759c259f 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -1238,7 +1238,7 @@ RLAPI void DrawLineBezier(Vector2 startPos, Vector2 endPos, float thick, Color c RLAPI void DrawCircle(int centerX, int centerY, float radius, Color color); // Draw a color-filled circle RLAPI void DrawCircleSector(Vector2 center, float radius, float startAngle, float endAngle, int segments, Color color); // Draw a piece of a circle RLAPI void DrawCircleSectorLines(Vector2 center, float radius, float startAngle, float endAngle, int segments, Color color); // Draw circle sector outline -RLAPI void DrawCircleGradient(int centerX, int centerY, float radius, Color color1, Color color2); // Draw a gradient-filled circle +RLAPI void DrawCircleGradient(int centerX, int centerY, float radius, Color inner, Color outer); // Draw a gradient-filled circle RLAPI void DrawCircleV(Vector2 center, float radius, Color color); // Draw a color-filled circle (Vector version) RLAPI void DrawCircleLines(int centerX, int centerY, float radius, Color color); // Draw circle outline RLAPI void DrawCircleLinesV(Vector2 center, float radius, Color color); // Draw circle outline (Vector version) @@ -1250,9 +1250,9 @@ RLAPI void DrawRectangle(int posX, int posY, int width, int height, Color color) RLAPI void DrawRectangleV(Vector2 position, Vector2 size, Color color); // Draw a color-filled rectangle (Vector version) RLAPI void DrawRectangleRec(Rectangle rec, Color color); // Draw a color-filled rectangle RLAPI void DrawRectanglePro(Rectangle rec, Vector2 origin, float rotation, Color color); // Draw a color-filled rectangle with pro parameters -RLAPI void DrawRectangleGradientV(int posX, int posY, int width, int height, Color color1, Color color2);// Draw a vertical-gradient-filled rectangle -RLAPI void DrawRectangleGradientH(int posX, int posY, int width, int height, Color color1, Color color2);// Draw a horizontal-gradient-filled rectangle -RLAPI void DrawRectangleGradientEx(Rectangle rec, Color col1, Color col2, Color col3, Color col4); // Draw a gradient-filled rectangle with custom vertex colors +RLAPI void DrawRectangleGradientV(int posX, int posY, int width, int height, Color top, Color bottom); // Draw a vertical-gradient-filled rectangle +RLAPI void DrawRectangleGradientH(int posX, int posY, int width, int height, Color left, Color right); // Draw a horizontal-gradient-filled rectangle +RLAPI void DrawRectangleGradientEx(Rectangle rec, Color topLeft, Color bottomLeft, Color topRight, Color bottomRight); // Draw a gradient-filled rectangle with custom vertex colors RLAPI void DrawRectangleLines(int posX, int posY, int width, int height, Color color); // Draw rectangle outline RLAPI void DrawRectangleLinesEx(Rectangle rec, float lineThick, Color color); // Draw rectangle outline with extended parameters RLAPI void DrawRectangleRounded(Rectangle rec, float roundness, int segments, Color color); // Draw rectangle with rounded edges diff --git a/src/rshapes.c b/src/rshapes.c index 676b2521a..66dfbf3b6 100644 --- a/src/rshapes.c +++ b/src/rshapes.c @@ -430,17 +430,16 @@ void DrawCircleSectorLines(Vector2 center, float radius, float startAngle, float } // Draw a gradient-filled circle -// NOTE: Gradient goes from center (color1) to border (color2) -void DrawCircleGradient(int centerX, int centerY, float radius, Color color1, Color color2) +void DrawCircleGradient(int centerX, int centerY, float radius, Color inner, Color outer) { rlBegin(RL_TRIANGLES); for (int i = 0; i < 360; i += 10) { - rlColor4ub(color1.r, color1.g, color1.b, color1.a); + rlColor4ub(inner.r, inner.g, inner.b, inner.a); rlVertex2f((float)centerX, (float)centerY); - rlColor4ub(color2.r, color2.g, color2.b, color2.a); + rlColor4ub(outer.r, outer.g, outer.b, outer.a); rlVertex2f((float)centerX + cosf(DEG2RAD*(i + 10))*radius, (float)centerY + sinf(DEG2RAD*(i + 10))*radius); - rlColor4ub(color2.r, color2.g, color2.b, color2.a); + rlColor4ub(outer.r, outer.g, outer.b, outer.a); rlVertex2f((float)centerX + cosf(DEG2RAD*i)*radius, (float)centerY + sinf(DEG2RAD*i)*radius); } rlEnd(); @@ -761,22 +760,19 @@ void DrawRectanglePro(Rectangle rec, Vector2 origin, float rotation, Color color } // Draw a vertical-gradient-filled rectangle -// NOTE: Gradient goes from bottom (color1) to top (color2) -void DrawRectangleGradientV(int posX, int posY, int width, int height, Color color1, Color color2) +void DrawRectangleGradientV(int posX, int posY, int width, int height, Color top, Color bottom) { - DrawRectangleGradientEx((Rectangle){ (float)posX, (float)posY, (float)width, (float)height }, color1, color2, color2, color1); + DrawRectangleGradientEx((Rectangle){ (float)posX, (float)posY, (float)width, (float)height }, top, bottom, bottom, top); } // Draw a horizontal-gradient-filled rectangle -// NOTE: Gradient goes from bottom (color1) to top (color2) -void DrawRectangleGradientH(int posX, int posY, int width, int height, Color color1, Color color2) +void DrawRectangleGradientH(int posX, int posY, int width, int height, Color left, Color right) { - DrawRectangleGradientEx((Rectangle){ (float)posX, (float)posY, (float)width, (float)height }, color1, color1, color2, color2); + DrawRectangleGradientEx((Rectangle){ (float)posX, (float)posY, (float)width, (float)height }, left, left, right, right); } // Draw a gradient-filled rectangle -// NOTE: Colors refer to corners, starting at top-lef corner and counter-clockwise -void DrawRectangleGradientEx(Rectangle rec, Color col1, Color col2, Color col3, Color col4) +void DrawRectangleGradientEx(Rectangle rec, Color topLeft, Color bottomLeft, Color topRight, Color bottomRight) { rlSetTexture(GetShapesTexture().id); Rectangle shapeRect = GetShapesTextureRectangle(); @@ -785,19 +781,19 @@ void DrawRectangleGradientEx(Rectangle rec, Color col1, Color col2, Color col3, rlNormal3f(0.0f, 0.0f, 1.0f); // NOTE: Default raylib font character 95 is a white square - rlColor4ub(col1.r, col1.g, col1.b, col1.a); + rlColor4ub(topLeft.r, topLeft.g, topLeft.b, topLeft.a); rlTexCoord2f(shapeRect.x/texShapes.width, shapeRect.y/texShapes.height); rlVertex2f(rec.x, rec.y); - rlColor4ub(col2.r, col2.g, col2.b, col2.a); + rlColor4ub(bottomLeft.r, bottomLeft.g, bottomLeft.b, bottomLeft.a); rlTexCoord2f(shapeRect.x/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height); rlVertex2f(rec.x, rec.y + rec.height); - rlColor4ub(col3.r, col3.g, col3.b, col3.a); + rlColor4ub(topRight.r, topRight.g, topRight.b, topRight.a); rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height); rlVertex2f(rec.x + rec.width, rec.y + rec.height); - rlColor4ub(col4.r, col4.g, col4.b, col4.a); + rlColor4ub(bottomRight.r, bottomRight.g, bottomRight.b, bottomRight.a); rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, shapeRect.y/texShapes.height); rlVertex2f(rec.x + rec.width, rec.y); rlEnd(); From bae0af241ed8ecf0b8107d3d3c43fef297e038d3 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 21 Aug 2024 12:08:09 +0000 Subject: [PATCH 031/208] Update raylib_api.* by CI --- parser/output/raylib_api.json | 20 ++++++++++---------- parser/output/raylib_api.lua | 20 ++++++++++---------- parser/output/raylib_api.txt | 20 ++++++++++---------- parser/output/raylib_api.xml | 20 ++++++++++---------- 4 files changed, 40 insertions(+), 40 deletions(-) diff --git a/parser/output/raylib_api.json b/parser/output/raylib_api.json index f149d628f..c4ce91e87 100644 --- a/parser/output/raylib_api.json +++ b/parser/output/raylib_api.json @@ -5485,11 +5485,11 @@ }, { "type": "Color", - "name": "color1" + "name": "inner" }, { "type": "Color", - "name": "color2" + "name": "outer" } ] }, @@ -5785,11 +5785,11 @@ }, { "type": "Color", - "name": "color1" + "name": "top" }, { "type": "Color", - "name": "color2" + "name": "bottom" } ] }, @@ -5816,11 +5816,11 @@ }, { "type": "Color", - "name": "color1" + "name": "left" }, { "type": "Color", - "name": "color2" + "name": "right" } ] }, @@ -5835,19 +5835,19 @@ }, { "type": "Color", - "name": "col1" + "name": "topLeft" }, { "type": "Color", - "name": "col2" + "name": "bottomLeft" }, { "type": "Color", - "name": "col3" + "name": "topRight" }, { "type": "Color", - "name": "col4" + "name": "bottomRight" } ] }, diff --git a/parser/output/raylib_api.lua b/parser/output/raylib_api.lua index 7c00fff33..3a9e2f04f 100644 --- a/parser/output/raylib_api.lua +++ b/parser/output/raylib_api.lua @@ -4697,8 +4697,8 @@ return { {type = "int", name = "centerX"}, {type = "int", name = "centerY"}, {type = "float", name = "radius"}, - {type = "Color", name = "color1"}, - {type = "Color", name = "color2"} + {type = "Color", name = "inner"}, + {type = "Color", name = "outer"} } }, { @@ -4835,8 +4835,8 @@ return { {type = "int", name = "posY"}, {type = "int", name = "width"}, {type = "int", name = "height"}, - {type = "Color", name = "color1"}, - {type = "Color", name = "color2"} + {type = "Color", name = "top"}, + {type = "Color", name = "bottom"} } }, { @@ -4848,8 +4848,8 @@ return { {type = "int", name = "posY"}, {type = "int", name = "width"}, {type = "int", name = "height"}, - {type = "Color", name = "color1"}, - {type = "Color", name = "color2"} + {type = "Color", name = "left"}, + {type = "Color", name = "right"} } }, { @@ -4858,10 +4858,10 @@ return { returnType = "void", params = { {type = "Rectangle", name = "rec"}, - {type = "Color", name = "col1"}, - {type = "Color", name = "col2"}, - {type = "Color", name = "col3"}, - {type = "Color", name = "col4"} + {type = "Color", name = "topLeft"}, + {type = "Color", name = "bottomLeft"}, + {type = "Color", name = "topRight"}, + {type = "Color", name = "bottomRight"} } }, { diff --git a/parser/output/raylib_api.txt b/parser/output/raylib_api.txt index 73170c860..afa9b525d 100644 --- a/parser/output/raylib_api.txt +++ b/parser/output/raylib_api.txt @@ -2176,8 +2176,8 @@ Function 217: DrawCircleGradient() (5 input parameters) Param[1]: centerX (type: int) Param[2]: centerY (type: int) Param[3]: radius (type: float) - Param[4]: color1 (type: Color) - Param[5]: color2 (type: Color) + Param[4]: inner (type: Color) + Param[5]: outer (type: Color) Function 218: DrawCircleV() (3 input parameters) Name: DrawCircleV Return type: void @@ -2278,8 +2278,8 @@ Function 229: DrawRectangleGradientV() (6 input parameters) Param[2]: posY (type: int) Param[3]: width (type: int) Param[4]: height (type: int) - Param[5]: color1 (type: Color) - Param[6]: color2 (type: Color) + Param[5]: top (type: Color) + Param[6]: bottom (type: Color) Function 230: DrawRectangleGradientH() (6 input parameters) Name: DrawRectangleGradientH Return type: void @@ -2288,17 +2288,17 @@ Function 230: DrawRectangleGradientH() (6 input parameters) Param[2]: posY (type: int) Param[3]: width (type: int) Param[4]: height (type: int) - Param[5]: color1 (type: Color) - Param[6]: color2 (type: Color) + Param[5]: left (type: Color) + Param[6]: right (type: Color) Function 231: DrawRectangleGradientEx() (5 input parameters) Name: DrawRectangleGradientEx Return type: void Description: Draw a gradient-filled rectangle with custom vertex colors Param[1]: rec (type: Rectangle) - Param[2]: col1 (type: Color) - Param[3]: col2 (type: Color) - Param[4]: col3 (type: Color) - Param[5]: col4 (type: Color) + Param[2]: topLeft (type: Color) + Param[3]: bottomLeft (type: Color) + Param[4]: topRight (type: Color) + Param[5]: bottomRight (type: Color) Function 232: DrawRectangleLines() (5 input parameters) Name: DrawRectangleLines Return type: void diff --git a/parser/output/raylib_api.xml b/parser/output/raylib_api.xml index 474bc0473..8a6560f48 100644 --- a/parser/output/raylib_api.xml +++ b/parser/output/raylib_api.xml @@ -1353,8 +1353,8 @@ - - + + @@ -1431,23 +1431,23 @@ - - + + - - + + - - - - + + + + From c8bee7c439d3a49d63ab0e67441fffb56ea4bf2a Mon Sep 17 00:00:00 2001 From: Jeffery Myers Date: Wed, 21 Aug 2024 08:11:59 -0700 Subject: [PATCH 032/208] [rmodels] Add a warning when loading an OBJ with multiple materials. (#4271) * Update raylib_api.* by CI * Add a temp warning about material assignments during OBJ loading if the file has more than one material. To be replaced when the OBJ translation code is fixed. --------- Co-authored-by: github-actions[bot] --- src/rmodels.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/rmodels.c b/src/rmodels.c index 36a7e254d..8afa3df57 100644 --- a/src/rmodels.c +++ b/src/rmodels.c @@ -4092,6 +4092,12 @@ static Model LoadOBJ(const char *fileName) model.materialCount = 1; TRACELOG(LOG_INFO, "MODEL: No materials provided, setting one default material for all meshes"); } + else if (model.materialCount > 1 && model.meshCount > 1) + { + // TEMP warning about multiple materials, to be removed when proper splitting code is implemented + // any obj with multiple materials will need to have it's materials assigned by the user in code to work at this time + TRACELOG(LOG_INFO, "MODEL: OBJ has multiple materials, manual material assignment will be required."); + } // Init model meshes and materials model.meshes = (Mesh *)RL_CALLOC(model.meshCount, sizeof(Mesh)); From cc88e0b780a7cc265e60a2e0842e587dd9b1c293 Mon Sep 17 00:00:00 2001 From: listeria <56203103+ListeriaM@users.noreply.github.com> Date: Wed, 21 Aug 2024 12:45:14 -0300 Subject: [PATCH 033/208] rtext: always multiply by sign in TextToFloat() (#4273) Co-authored-by: Listeria monocytogenes --- src/rtext.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/rtext.c b/src/rtext.c index 755b15efd..8c1dc3c5e 100644 --- a/src/rtext.c +++ b/src/rtext.c @@ -1467,8 +1467,7 @@ float TextToFloat(const char *text) int i = 0; for (; ((text[i] >= '0') && (text[i] <= '9')); i++) value = value*10.0f + (float)(text[i] - '0'); - if (text[i++] != '.') value *= sign; - else + if (text[i++] == '.') { float divisor = 10.0f; for (; ((text[i] >= '0') && (text[i] <= '9')); i++) @@ -1478,7 +1477,7 @@ float TextToFloat(const char *text) } } - return value; + return value*sign; } #if defined(SUPPORT_TEXT_MANIPULATION) From 74350fa7cf89f7e04e532a4cb89ff036f98fe59c Mon Sep 17 00:00:00 2001 From: Peter0x44 Date: Fri, 23 Aug 2024 21:21:22 +0100 Subject: [PATCH 034/208] [build] CMake: Delete BuildOptions.cmake (#4277) This file seems to not do anything useful. From what I can tell the OSX_FATLIB option sets CMAKE_OSX_ARCHITECTURES to "x86_64;i386". This doesn't account for the arm that apple now has, as well as 32 bit support being completely removed, and I think it's entirely reasonable to expect users to pass the necessary architectures they want themselves. It's possible this could break some users who rely on this, but I sincerely doubt anyone does. The solution is trivial either way (put -DCMAKE_OSX_ARCHITECTURES="i386;x86_64" on the command line yourself) The second part of BuildOptions.cmake claims to set PLATFORM to "Web" if the emscripten toolchain file is used (if (EMSCRIPTEN)), but it does not work correctly anyway. Currently, glfw searches for wayland and x11 libraries and fails likeso: CMake Error at /usr/share/cmake/Modules/FindPkgConfig.cmake:645 (message): The following required packages were not found: - wayland-client>=0.2.7 - wayland-cursor>=0.2.7 - wayland-egl>=0.2.7 - xkbcommon>=0.5.0 Call Stack (most recent call first): /usr/share/cmake/Modules/FindPkgConfig.cmake:873 (_pkg_check_modules_internal) src/external/glfw/src/CMakeLists.txt:163 (pkg_check_modules) Considering this code doesn't work as described, it's okay to delete it. I think a better check should be implemented, but that is for a different PR. --- CMakeLists.txt | 3 --- CMakeOptions.txt | 1 - cmake/BuildOptions.cmake | 18 ------------------ 3 files changed, 22 deletions(-) delete mode 100644 cmake/BuildOptions.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index a5e3408c8..678d8e372 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,9 +36,6 @@ include(CompilerFlags) # Registers build options that are exposed to cmake include(CMakeOptions.txt) -# Enforces a few environment and compiler configurations -include(BuildOptions) - if (UNIX AND NOT APPLE) if (NOT GLFW_BUILD_WAYLAND AND NOT GLFW_BUILD_X11) MESSAGE(FATAL_ERROR "Cannot disable both Wayland and X11") diff --git a/CMakeOptions.txt b/CMakeOptions.txt index b063f02a1..ce9141e22 100644 --- a/CMakeOptions.txt +++ b/CMakeOptions.txt @@ -16,7 +16,6 @@ option(ENABLE_MSAN "Enable MemorySanitizer (MSan) for debugging (not recommended # Shared library is always PIC. Static library should be PIC too if linked into a shared library option(WITH_PIC "Compile static library as position-independent code" OFF) option(BUILD_SHARED_LIBS "Build raylib as a shared library" OFF) -option(MACOS_FATLIB "Build fat library for both i386 and x86_64 on macOS" OFF) cmake_dependent_option(USE_AUDIO "Build raylib with audio module" ON CUSTOMIZE_BUILD ON) enum_option(USE_EXTERNAL_GLFW "OFF;IF_POSSIBLE;ON" "Link raylib against system GLFW instead of embedded one") diff --git a/cmake/BuildOptions.cmake b/cmake/BuildOptions.cmake deleted file mode 100644 index 0fce64292..000000000 --- a/cmake/BuildOptions.cmake +++ /dev/null @@ -1,18 +0,0 @@ -if(${PLATFORM} MATCHES "Desktop" AND APPLE) - if(MACOS_FATLIB) - if (CMAKE_OSX_ARCHITECTURES) - message(FATAL_ERROR "User supplied -DCMAKE_OSX_ARCHITECTURES overrides -DMACOS_FATLIB=ON") - else() - set(CMAKE_OSX_ARCHITECTURES "x86_64;i386") - endif() - endif() -endif() - -# This helps support the case where emsdk toolchain file is used -# either by setting it with -DCMAKE_TOOLCHAIN_FILE=/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake -# or by using "emcmake cmake -B build -S ." as described in https://emscripten.org/docs/compiling/Building-Projects.html -if(EMSCRIPTEN) - SET(PLATFORM Web CACHE STRING "Forcing PLATFORM_WEB because EMSCRIPTEN was detected") -endif() - -# vim: ft=cmake From 77172e34db5d27bb5413f9232215321b8cceac67 Mon Sep 17 00:00:00 2001 From: Bugsia <74007012+Bugsia@users.noreply.github.com> Date: Fri, 23 Aug 2024 22:22:36 +0200 Subject: [PATCH 035/208] Fixing GenImagePerlinNoise() being stretched, if Image is not rectangular (#4276) --- src/rtextures.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/rtextures.c b/src/rtextures.c index f2faa1850..867add38e 100644 --- a/src/rtextures.c +++ b/src/rtextures.c @@ -1112,6 +1112,7 @@ Image GenImagePerlinNoise(int width, int height, int offsetX, int offsetY, float { Color *pixels = (Color *)RL_MALLOC(width*height*sizeof(Color)); + float aspectRatio = (float)width / (float)height; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) @@ -1119,6 +1120,10 @@ Image GenImagePerlinNoise(int width, int height, int offsetX, int offsetY, float float nx = (float)(x + offsetX)*(scale/(float)width); float ny = (float)(y + offsetY)*(scale/(float)height); + // Apply aspect ratio compensation to wider side + if (width > height) nx *= aspectRatio; + else ny /= aspectRatio; + // Basic perlin noise implementation (not used) //float p = (stb_perlin_noise3(nx, ny, 0.0f, 0, 0, 0); From ecf863969c2ca0cf903acb5bef0d403f611943b4 Mon Sep 17 00:00:00 2001 From: Peter0x44 Date: Fri, 23 Aug 2024 21:29:40 +0100 Subject: [PATCH 036/208] [build] CMake: Fix warnings in projects/CMake/CMakeLists.txt (#4278) Currently, when building, the cmake example in projects/CMake gives this warning, with CMake 3.30.2 CMake Warning (dev) at /usr/share/cmake/Modules/FetchContent.cmake:1953 (message): Calling FetchContent_Populate(raylib) is deprecated, call FetchContent_MakeAvailable(raylib) instead. Policy CMP0169 can be set to OLD to allow FetchContent_Populate(raylib) to be called directly for now, but the ability to call it with declared details will be removed completely in a future version. Call Stack (most recent call first): CMakeLists.txt:20 (FetchContent_Populate) This warning is for project developers. Use -Wno-dev to suppress it. Changing FetchContent_Populate to FetchContent_MakeAvailable didn't cause any issues I could observe when building. I'm not sure why it wasn't like that to begin with. --- projects/CMake/CMakeLists.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/projects/CMake/CMakeLists.txt b/projects/CMake/CMakeLists.txt index 3b22964c5..a95d68a4f 100644 --- a/projects/CMake/CMakeLists.txt +++ b/projects/CMake/CMakeLists.txt @@ -17,9 +17,8 @@ if (NOT raylib_FOUND) # If there's none, fetch and build raylib FetchContent_GetProperties(raylib) if (NOT raylib_POPULATED) # Have we downloaded raylib yet? set(FETCHCONTENT_QUIET NO) - FetchContent_Populate(raylib) + FetchContent_MakeAvailable(raylib) set(BUILD_EXAMPLES OFF CACHE BOOL "" FORCE) # don't build the supplied examples - add_subdirectory(${raylib_SOURCE_DIR} ${raylib_BINARY_DIR}) endif() endif() From 3079c69725b3e4f07f6984dc2f67262bba48b153 Mon Sep 17 00:00:00 2001 From: Menno van der Graaf Date: Fri, 23 Aug 2024 22:32:20 +0200 Subject: [PATCH 037/208] Replace deprecated Android function ALooper_pollAll with ALooper_pollOnce (#4275) --- src/platforms/rcore_android.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/platforms/rcore_android.c b/src/platforms/rcore_android.c index 68ae979ee..7a2162025 100644 --- a/src/platforms/rcore_android.c +++ b/src/platforms/rcore_android.c @@ -281,14 +281,15 @@ void android_main(struct android_app *app) // Request to end the native activity ANativeActivity_finish(app->activity); - // Android ALooper_pollAll() variables + // Android ALooper_pollOnce() variables int pollResult = 0; int pollEvents = 0; // Waiting for application events before complete finishing while (!app->destroyRequested) { - while ((pollResult = ALooper_pollAll(0, NULL, &pollEvents, (void **)&platform.source)) >= 0) + // Poll all events until we reach return value TIMEOUT, meaning no events left to process + while ((pollResult = ALooper_pollOnce(0, NULL, &pollEvents, (void **)&platform.source)) > ALOOPER_POLL_TIMEOUT) { if (platform.source != NULL) platform.source->process(app, platform.source); } @@ -682,13 +683,13 @@ void PollInputEvents(void) CORE.Input.Keyboard.keyRepeatInFrame[i] = 0; } - // Android ALooper_pollAll() variables + // Android ALooper_pollOnce() variables int pollResult = 0; int pollEvents = 0; - // Poll Events (registered events) + // Poll Events (registered events) until we reach TIMEOUT which indicates there are no events left to poll // NOTE: Activity is paused if not enabled (platform.appEnabled) - while ((pollResult = ALooper_pollAll(platform.appEnabled? 0 : -1, NULL, &pollEvents, (void**)&platform.source)) >= 0) + while ((pollResult = ALooper_pollOnce(platform.appEnabled? 0 : -1, NULL, &pollEvents, (void**)&platform.source)) > ALOOPER_POLL_TIMEOUT) { // Process this event if (platform.source != NULL) platform.source->process(platform.app, platform.source); @@ -767,15 +768,15 @@ int InitPlatform(void) TRACELOG(LOG_INFO, "PLATFORM: ANDROID: Initialized successfully"); - // Android ALooper_pollAll() variables + // Android ALooper_pollOnce() variables int pollResult = 0; int pollEvents = 0; // Wait for window to be initialized (display and context) while (!CORE.Window.ready) { - // Process events loop - while ((pollResult = ALooper_pollAll(0, NULL, &pollEvents, (void**)&platform.source)) >= 0) + // Process events until we reach TIMEOUT, which indicates no more events queued. + while ((pollResult = ALooper_pollOnce(0, NULL, &pollEvents, (void**)&platform.source)) > ALOOPER_POLL_TIMEOUT) { // Process this event if (platform.source != NULL) platform.source->process(platform.app, platform.source); From b0c3013b51c5dbb03e584aad04fe00d89e121946 Mon Sep 17 00:00:00 2001 From: konstruktor227 Date: Fri, 23 Aug 2024 22:51:29 +0200 Subject: [PATCH 038/208] [raudio] Support 24-bit FLACs in `LoadMusicStreamFromMemory` (#4279) Force conversion to 16-bit, same as how it is done in `LoadMusicStream`. This fixes the problem where 24-bit FLACs play silence or broken sound. --- src/raudio.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/raudio.c b/src/raudio.c index 21d1adae3..79d53b565 100644 --- a/src/raudio.c +++ b/src/raudio.c @@ -1626,7 +1626,9 @@ Music LoadMusicStreamFromMemory(const char *fileType, const unsigned char *data, { music.ctxType = MUSIC_AUDIO_FLAC; music.ctxData = ctxFlac; - music.stream = LoadAudioStream(ctxFlac->sampleRate, ctxFlac->bitsPerSample, ctxFlac->channels); + int sampleSize = ctxFlac->bitsPerSample; + if (ctxFlac->bitsPerSample == 24) sampleSize = 16; // Forcing conversion to s16 on UpdateMusicStream() + music.stream = LoadAudioStream(ctxFlac->sampleRate, sampleSize, ctxFlac->channels); music.frameCount = (unsigned int)ctxFlac->totalPCMFrameCount; music.looping = true; // Looping enabled by default musicLoaded = true; From 7bde76ca2c649213546f412c28b7b05260338ad4 Mon Sep 17 00:00:00 2001 From: Reese Gallagher Date: Sat, 24 Aug 2024 12:42:38 -0400 Subject: [PATCH 039/208] [rmodels] More performant point cloud rendering with `DrawModelPoints()` (#4203) * Added the ability to draw a model as a point cloud * Added example to demonstrate drawing a model as a point cloud * polished the demo a bit * picture for example * adhere to conventions for example * update png to match aspect ratio * minor changes * address code convention comments * added point rendering to makefiles * added point rendering to readme and renumbered examples * comment formatting --------- Co-authored-by: Reese Gallagher Co-authored-by: Ray --- examples/Makefile | 1 + examples/Makefile.Web | 1 + examples/README.md | 50 +++--- examples/models/models_point_rendering.c | 171 +++++++++++++++++++++ examples/models/models_point_rendering.png | Bin 0 -> 130183 bytes src/raylib.h | 2 + src/rmodels.c | 24 +++ 7 files changed, 224 insertions(+), 25 deletions(-) create mode 100644 examples/models/models_point_rendering.c create mode 100644 examples/models/models_point_rendering.png diff --git a/examples/Makefile b/examples/Makefile index 93b05a0c7..904917f7c 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -582,6 +582,7 @@ MODELS = \ models/models_mesh_generation \ models/models_mesh_picking \ models/models_orthographic_projection \ + models/models_point_rendering \ models/models_rlgl_solar_system \ models/models_skybox \ models/models_waving_cubes \ diff --git a/examples/Makefile.Web b/examples/Makefile.Web index 46a8a98ea..7057da1c0 100644 --- a/examples/Makefile.Web +++ b/examples/Makefile.Web @@ -447,6 +447,7 @@ MODELS = \ models/models_mesh_generation \ models/models_mesh_picking \ models/models_orthographic_projection \ + models/models_point_rendering \ models/models_rlgl_solar_system \ models/models_skybox \ models/models_waving_cubes \ diff --git a/examples/README.md b/examples/README.md index 317f43c89..d573ff23e 100644 --- a/examples/README.md +++ b/examples/README.md @@ -147,11 +147,12 @@ Examples using raylib models functionality, including models loading/generation | 91 | [models_loading_vox](models/models_loading_vox.c) | models_loading_vox | ⭐️☆☆☆ | **4.0** | **4.0** | [Johann Nadalutti](https://github.com/procfxgen) | | 92 | [models_loading_m3d](models/models_loading_m3d.c) | models_loading_m3d | ⭐️☆☆☆ | **4.2** | **4.2** | [bzt](https://bztsrc.gitlab.io/model3d) | | 93 | [models_orthographic_projection](models/models_orthographic_projection.c) | models_orthographic_projection | ⭐️☆☆☆ | 2.0 | 3.7 | [Max Danielsson](https://github.com/autious) | -| 94 | [models_rlgl_solar_system](models/models_rlgl_solar_system.c) | models_rlgl_solar_system | ⭐️⭐️⭐️⭐️ | 2.5 | **4.0** | [Ray](https://github.com/raysan5) | -| 95 | [models_yaw_pitch_roll](models/models_yaw_pitch_roll.c) | models_yaw_pitch_roll | ⭐️⭐️☆☆ | 1.8 | **4.0** | [Berni](https://github.com/Berni8k) | -| 96 | [models_waving_cubes](models/models_waving_cubes.c) | models_waving_cubes | ⭐️⭐️⭐️☆ | 2.5 | 3.7 | [codecat](https://github.com/codecat) | -| 97 | [models_heightmap](models/models_heightmap.c) | models_heightmap | ⭐️☆☆☆ | 1.8 | 3.5 | [Ray](https://github.com/raysan5) | -| 98 | [models_skybox](models/models_skybox.c) | models_skybox | ⭐️⭐️☆☆ | 1.8 | **4.0** | [Ray](https://github.com/raysan5) | +| 94 | [models_point_rendering](models/models_point_rendering.c) | models_point_rendering | ⭐️⭐️☆☆ | 5.0 | 5.0 | [Reese Gallagher](https://github.com/satchelfrost) | +| 95 | [models_rlgl_solar_system](models/models_rlgl_solar_system.c) | models_rlgl_solar_system | ⭐️⭐️⭐️⭐️ | 2.5 | **4.0** | [Ray](https://github.com/raysan5) | +| 96 | [models_yaw_pitch_roll](models/models_yaw_pitch_roll.c) | models_yaw_pitch_roll | ⭐️⭐️☆☆ | 1.8 | **4.0** | [Berni](https://github.com/Berni8k) | +| 97 | [models_waving_cubes](models/models_waving_cubes.c) | models_waving_cubes | ⭐️⭐️⭐️☆ | 2.5 | 3.7 | [codecat](https://github.com/codecat) | +| 98 | [models_heightmap](models/models_heightmap.c) | models_heightmap | ⭐️☆☆☆ | 1.8 | 3.5 | [Ray](https://github.com/raysan5) | +| 99 | [models_skybox](models/models_skybox.c) | models_skybox | ⭐️⭐️☆☆ | 1.8 | **4.0** | [Ray](https://github.com/raysan5) | ### category: shaders @@ -159,26 +160,25 @@ Examples using raylib shaders functionality, including shaders loading, paramete | ## | example | image | difficulty
level | version
created | last version
updated | original
developer | |----|----------|--------|:-------------------:|:------------------:|:------------------:|:----------| -| 99 | [shaders_basic_lighting](shaders/shaders_basic_lighting.c) | shaders_basic_lighting | ⭐️⭐️⭐️⭐️ | 3.0 | **4.2** | [Chris Camacho](https://github.com/codifies) | -| 100 | [shaders_model_shader](shaders/shaders_model_shader.c) | shaders_model_shader | ⭐️⭐️☆☆ | 1.3 | 3.7 | [Ray](https://github.com/raysan5) | -| 101 | [shaders_shapes_textures](shaders/shaders_shapes_textures.c) | shaders_shapes_textures | ⭐️⭐️☆☆ | 1.7 | 3.7 | [Ray](https://github.com/raysan5) | -| 102 | [shaders_custom_uniform](shaders/shaders_custom_uniform.c) | shaders_custom_uniform | ⭐️⭐️☆☆ | 1.3 | **4.0** | [Ray](https://github.com/raysan5) | -| 103 | [shaders_postprocessing](shaders/shaders_postprocessing.c) | shaders_postprocessing | ⭐️⭐️⭐️☆ | 1.3 | **4.0** | [Ray](https://github.com/raysan5) | -| 104 | [shaders_palette_switch](shaders/shaders_palette_switch.c) | shaders_palette_switch | ⭐️⭐️⭐️☆ | 2.5 | 3.7 | [Marco Lizza](https://github.com/MarcoLizza) | -| 105 | [shaders_raymarching](shaders/shaders_raymarching.c) | shaders_raymarching | ⭐️⭐️⭐️⭐️ | 2.0 | **4.2** | [Ray](https://github.com/raysan5) | -| 106 | [shaders_texture_drawing](shaders/shaders_texture_drawing.c) | shaders_texture_drawing | ⭐️⭐️☆☆ | 2.0 | 3.7 | [Michał Ciesielski](https://github.com/) | -| 107 | [shaders_texture_outline](shaders/shaders_texture_outline.c) | shaders_texture_outline | ⭐️⭐️⭐️☆ | **4.0** | **4.0** | [Samuel Skiff](https://github.com/GoldenThumbs) | -| 108 | [shaders_texture_waves](shaders/shaders_texture_waves.c) | shaders_texture_waves | ⭐️⭐️☆☆ | 2.5 | 3.7 | [Anata](https://github.com/anatagawa) | -| 109 | [shaders_julia_set](shaders/shaders_julia_set.c) | shaders_julia_set | ⭐️⭐️⭐️☆ | 2.5 | **4.0** | [eggmund](https://github.com/eggmund) | -| 110 | [shaders_eratosthenes](shaders/shaders_eratosthenes.c) | shaders_eratosthenes | ⭐️⭐️⭐️☆ | 2.5 | **4.0** | [ProfJski](https://github.com/ProfJski) | -| 111 | [shaders_fog](shaders/shaders_fog.c) | shaders_fog | ⭐️⭐️⭐️☆ | 2.5 | 3.7 | [Chris Camacho](https://github.com/codifies) | -| 112 | [shaders_simple_mask](shaders/shaders_simple_mask.c) | shaders_simple_mask | ⭐️⭐️☆☆ | 2.5 | 3.7 | [Chris Camacho](https://github.com/codifies) | -| 113 | [shaders_hot_reloading](shaders/shaders_hot_reloading.c) | shaders_hot_reloading | ⭐️⭐️⭐️☆ | 3.0 | 3.5 | [Ray](https://github.com/raysan5) | -| 114 | [shaders_mesh_instancing](shaders/shaders_mesh_instancing.c) | shaders_mesh_instancing | ⭐️⭐️⭐️⭐️ | 3.7 | **4.2** | [seanpringle](https://github.com/seanpringle) | -| 115 | [shaders_multi_sample2d](shaders/shaders_multi_sample2d.c) | shaders_multi_sample2d | ⭐️⭐️☆☆ | 3.5 | 3.5 | [Ray](https://github.com/raysan5) | -| 116 | [shaders_spotlight](shaders/shaders_spotlight.c) | shaders_spotlight | ⭐️⭐️☆☆ | 2.5 | 3.7 | [Chris Camacho](https://github.com/codifies) | -| 117 | [shaders_deferred_render](shaders/shaders_deferred_render.c) | shaders_deferred_render | ⭐️⭐️⭐️⭐️ | 4.5 | 4.5 | [Justin Andreas Lacoste](https://github.com/27justin) | -| 118 | [shaders_vertex_displacement](shaders/shaders_vertex_displacement.c) | shaders_deferred_render | ⭐️☆☆☆ | 1.5 | 1.5 | [Alex ZH](https://github.com/ZzzhHe) | +| 100 | [shaders_basic_lighting](shaders/shaders_basic_lighting.c) | shaders_basic_lighting | ⭐️⭐️⭐️⭐️ | 3.0 | **4.2** | [Chris Camacho](https://github.com/codifies) | +| 101 | [shaders_model_shader](shaders/shaders_model_shader.c) | shaders_model_shader | ⭐️⭐️☆☆ | 1.3 | 3.7 | [Ray](https://github.com/raysan5) | +| 102 | [shaders_shapes_textures](shaders/shaders_shapes_textures.c) | shaders_shapes_textures | ⭐️⭐️☆☆ | 1.7 | 3.7 | [Ray](https://github.com/raysan5) | +| 103 | [shaders_custom_uniform](shaders/shaders_custom_uniform.c) | shaders_custom_uniform | ⭐️⭐️☆☆ | 1.3 | **4.0** | [Ray](https://github.com/raysan5) | +| 104 | [shaders_postprocessing](shaders/shaders_postprocessing.c) | shaders_postprocessing | ⭐️⭐️⭐️☆ | 1.3 | **4.0** | [Ray](https://github.com/raysan5) | +| 105 | [shaders_palette_switch](shaders/shaders_palette_switch.c) | shaders_palette_switch | ⭐️⭐️⭐️☆ | 2.5 | 3.7 | [Marco Lizza](https://github.com/MarcoLizza) | +| 106 | [shaders_raymarching](shaders/shaders_raymarching.c) | shaders_raymarching | ⭐️⭐️⭐️⭐️ | 2.0 | **4.2** | [Ray](https://github.com/raysan5) | +| 107 | [shaders_texture_drawing](shaders/shaders_texture_drawing.c) | shaders_texture_drawing | ⭐️⭐️☆☆ | 2.0 | 3.7 | [Michał Ciesielski](https://github.com/) | +| 108 | [shaders_texture_outline](shaders/shaders_texture_outline.c) | shaders_texture_outline | ⭐️⭐️⭐️☆ | **4.0** | **4.0** | [Samuel Skiff](https://github.com/GoldenThumbs) | +| 109 | [shaders_texture_waves](shaders/shaders_texture_waves.c) | shaders_texture_waves | ⭐️⭐️☆☆ | 2.5 | 3.7 | [Anata](https://github.com/anatagawa) | +| 110 | [shaders_julia_set](shaders/shaders_julia_set.c) | shaders_julia_set | ⭐️⭐️⭐️☆ | 2.5 | **4.0** | [eggmund](https://github.com/eggmund) | +| 111 | [shaders_eratosthenes](shaders/shaders_eratosthenes.c) | shaders_eratosthenes | ⭐️⭐️⭐️☆ | 2.5 | **4.0** | [ProfJski](https://github.com/ProfJski) | +| 112 | [shaders_fog](shaders/shaders_fog.c) | shaders_fog | ⭐️⭐️⭐️☆ | 2.5 | 3.7 | [Chris Camacho](https://github.com/codifies) | +| 113 | [shaders_simple_mask](shaders/shaders_simple_mask.c) | shaders_simple_mask | ⭐️⭐️☆☆ | 2.5 | 3.7 | [Chris Camacho](https://github.com/codifies) | +| 114 | [shaders_hot_reloading](shaders/shaders_hot_reloading.c) | shaders_hot_reloading | ⭐️⭐️⭐️☆ | 3.0 | 3.5 | [Ray](https://github.com/raysan5) | +| 115 | [shaders_mesh_instancing](shaders/shaders_mesh_instancing.c) | shaders_mesh_instancing | ⭐️⭐️⭐️⭐️ | 3.7 | **4.2** | [seanpringle](https://github.com/seanpringle) | +| 116 | [shaders_multi_sample2d](shaders/shaders_multi_sample2d.c) | shaders_multi_sample2d | ⭐️⭐️☆☆ | 3.5 | 3.5 | [Ray](https://github.com/raysan5) | +| 117 | [shaders_spotlight](shaders/shaders_spotlight.c) | shaders_spotlight | ⭐️⭐️☆☆ | 2.5 | 3.7 | [Chris Camacho](https://github.com/codifies) | +| 118 | [shaders_deferred_render](shaders/shaders_deferred_render.c) | shaders_deferred_render | ⭐️⭐️⭐️⭐️ | 4.5 | 4.5 | [Justin Andreas Lacoste](https://github.com/27justin) | ### category: audio diff --git a/examples/models/models_point_rendering.c b/examples/models/models_point_rendering.c new file mode 100644 index 000000000..128a70f57 --- /dev/null +++ b/examples/models/models_point_rendering.c @@ -0,0 +1,171 @@ +/******************************************************************************************* +* +* raylib example - point rendering +* +* Example originally created with raylib 5.0, last time updated with raylib 5.0 +* +* Example contributed by Reese Gallagher (@satchelfrost) and reviewed by Ramon Santamaria (@raysan5) +* +* Example 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) 2024 Reese Gallagher (@satchelfrost) +* +********************************************************************************************/ + +#include "raylib.h" +#include // Required for: rand() +#include // Required for: cos(), sin() + +#define MAX_POINTS 10000000 // 10 million +#define MIN_POINTS 1000 // 1 thousand + +static float RandFloat(); + +//------------------------------------------------------------------------------------ +// Program main entry point +//------------------------------------------------------------------------------------ +int main() +{ + // Initialization + //-------------------------------------------------------------------------------------- + const int screenWidth = 800; + const int screenHeight = 450; + InitWindow(screenWidth, screenHeight, "raylib [models] example - point rendering"); + SetTargetFPS(60); + + Camera camera = { + .position = {3.0f, 3.0f, 3.0f}, + .target = {0.0f, 0.0f, 0.0f}, + .up = {0.0f, 1.0f, 0.0f}, + .fovy = 45.0f, + .projection = CAMERA_PERSPECTIVE, + }; + + Vector3 position = {0.0f, 0.0f, 0.0f}; + bool useDrawModelPoints = true; + bool numPointsChanged = false; + int numPoints = 1000; + Mesh mesh = GenPoints(numPoints); + Model model = LoadModelFromMesh(mesh); + //-------------------------------------------------------------------------------------- + + // Main game loop + while(!WindowShouldClose()) + { + // Update + //---------------------------------------------------------------------------------- + UpdateCamera(&camera, CAMERA_ORBITAL); + + if (IsKeyPressed(KEY_SPACE)) useDrawModelPoints = !useDrawModelPoints; + if (IsKeyPressed(KEY_UP)) + { + numPoints = (numPoints * 10 > MAX_POINTS) ? MAX_POINTS : numPoints * 10; + numPointsChanged = true; + TraceLog(LOG_INFO, "num points %d", numPoints); + } + if (IsKeyPressed(KEY_DOWN)) + { + numPoints = (numPoints / 10 < MIN_POINTS) ? MIN_POINTS : numPoints / 10; + numPointsChanged = true; + TraceLog(LOG_INFO, "num points %d", numPoints); + } + + // upload a different point cloud size + if (numPointsChanged) + { + UnloadModel(model); + mesh = GenPoints(numPoints); + model = LoadModelFromMesh(mesh); + numPointsChanged = false; + } + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + ClearBackground(BLACK); + BeginMode3D(camera); + + // The new method only uploads the points once to the GPU + if (useDrawModelPoints) + { + DrawModelPoints(model, position, 1.0f, WHITE); + } + // The old method must continually draw the "points" (lines) + else + { + for (int i = 0; i < numPoints; i++) + { + Vector3 pos = { + .x = mesh.vertices[i * 3 + 0], + .y = mesh.vertices[i * 3 + 1], + .z = mesh.vertices[i * 3 + 2], + }; + Color color = { + .r = mesh.colors[i * 4 + 0], + .g = mesh.colors[i * 4 + 1], + .b = mesh.colors[i * 4 + 2], + .a = mesh.colors[i * 4 + 3], + }; + DrawPoint3D(pos, color); + } + } + + // Draw a unit sphere for reference + DrawSphereWires(position, 1.0f, 10, 10, YELLOW); + EndMode3D(); + + // Text formatting + Color color = WHITE; + int fps = GetFPS(); + if ((fps < 30) && (fps >= 15)) color = ORANGE; + else if (fps < 15) color = RED; + DrawText(TextFormat("%2i FPS", fps), 20, 20, 40, color); + DrawText(TextFormat("Point Count: %d", numPoints), 20, screenHeight - 50, 40, WHITE); + DrawText("Up - increase points", 20, 70, 20, WHITE); + DrawText("Down - decrease points", 20, 100, 20, WHITE); + DrawText("Space - drawing function", 20, 130, 20, WHITE); + if (useDrawModelPoints) DrawText("DrawModelPoints()", 20, 160, 20, GREEN); + else DrawText("DrawPoint3D()", 20, 160, 20, RED); + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + UnloadModel(model); + CloseWindow(); + //-------------------------------------------------------------------------------------- + return 0; +} + +// Generate a spherical point cloud +Mesh GenPoints(int numPoints) +{ + Mesh mesh = { + .triangleCount = 1, + .vertexCount = numPoints, + .vertices = (float *)MemAlloc(numPoints * 3 * sizeof(float)), + .colors = (unsigned char*)MemAlloc(numPoints * 4 * sizeof(unsigned char)), + }; + + // https://en.wikipedia.org/wiki/Spherical_coordinate_system + for (int i = 0; i < numPoints; i++) + { + float theta = PI * rand() / RAND_MAX; + float phi = 2.0f * PI * rand() / RAND_MAX; + float r = 10.0f * rand() / RAND_MAX; + mesh.vertices[i * 3 + 0] = r * sin(theta) * cos(phi); + mesh.vertices[i * 3 + 1] = r * sin(theta) * sin(phi); + mesh.vertices[i * 3 + 2] = r * cos(theta); + Color color = ColorFromHSV(r * 360.0f, 1.0f, 1.0f); + mesh.colors[i * 4 + 0] = color.r; + mesh.colors[i * 4 + 1] = color.g; + mesh.colors[i * 4 + 2] = color.b; + mesh.colors[i * 4 + 3] = color.a; + } + + // Upload mesh data from CPU (RAM) to GPU (VRAM) memory + UploadMesh(&mesh, false); + return mesh; +} diff --git a/examples/models/models_point_rendering.png b/examples/models/models_point_rendering.png new file mode 100644 index 0000000000000000000000000000000000000000..a1fc718e4dd508ba6768abb6f7a0c02a1fabaf9f GIT binary patch literal 130183 zcmV)5K*_&}P)EX>4Tx04R}tkv&MmKpe$iKcqz}4i*$~$WWcEh>AFB6^c+H)C#RSm|Xe=O&XFE z7e~Rh;NZt%)xpJCR|i)?5c~jfc5qU3krMxx6k5c1aNLh~_a1le0Dq&xR5LgZsG4P@ zlL;Z4TNOgD2qTDo0Ams}^*K>Y!E=1w!^hXVIM4Dv_vh$Q@+Jd(0`V-<4U2e#czV;) zIqwrkSxHie&xuD3x*+i**JYRAI2RrE^USD`NzW5UiG^YZ%N@*0hDtm|98*+{^8Hzt z70z3n)k=-E?#W*m$!jaiT&FpNBo?s*5dvh?P(}q7;kXx44}``EUdCqUpCxYFAGY6F=0B)#6& zVn;ylHgIv>*5p0lat9cA(j`N3qySBSp#Z#}(KqFQzFVMs&F!tVkJASrLtUkAfP+I| zq)6H89`6o!_V(|YR)0S}d~%ZJlJa!`000JJOGiWi{{a60|De66lK=n!32;bRa{vG? zBLDy{BLR4&KXw2B00(qQO+^Rj2m}`b1f}Erw*UYD8FWQhbVF}#ZDnqB07G(RVRU6= zAa`kWXdp*PO;A^X4i^9bAOJ~3K~#9!>|J^I4%HVwiHM3yBq7-=62Gh!sVGZSXc3C2 zq_SoyA?+wFij*wLk|K(bC|Q!MWhWJ-g*GBfpWh#IXXeh#y)$>Vcl*BY^W5j1xpS9u z_jB&qh=`yRa5a?Eh79*3rn0LeVQo+ipbO$FAC-gU>*BAUoA^tx%969)&r*bQ z=F<4*A9id1EA%lzD`&bnCLFmyph^H?C9sLi}%5Nd*ma0vnE%J*$cfL00mysF2T z%w+#7jkx-(Z$G#9F;3$0odUuG+H-zenfnMRrPePGb93|t_Iy79gyGh-r-0R4#m749 z1|q_8+d9AmzWraae{&zj-R%E4O1XV0&QMLTU!Zh+^<5ugf5P;T^)Euok4GDYJr37q z#@wqCWIxB|n9iy8IcnX*ENk4?Ce!baU+0!v%-`3}M` z2QhF7aF4v)e+ih&&D)zSaPP6C9YZ>D|BoxIf7sUn>R8tY%Hm}9{8R$g40`kZ^?Wqt zu1t}+Jwgr#u8g4k+2Zn-*on1k+}2BB_c|_ASaYA6&l_xYcTUhg11cCl7 zZ%DPX1=;gH8~laSvU4WoLm$LQfTSh`Tq89oz|92Q>5Ly0@^EYJXFzek^xHK^6-v3G zzdXlS|20(WN8Cpk>C)DT`gr)^=sgIJHuZP?K2Zh_4oTwYi4m*v3W(OddKuMx_48Jv zUz!3`6*xe^IKrm{bOV9FZtK2sfdTiLa4aI=AORl{K>0xB5G^MN4M51}jDG_fM~A(a z;ro6^Vi3)Nw((vO1%iunaXg|md{i%I9U};PvG>^ZigaM0G*C)?f!OU51pz2?@q#P5@DIpg|<*x&Ji`FxV3oJ-*(no*rV z1JVSkJk5p6MXg=N_b%zTB@Qm-+tzaL3=Z$IuxH8QG(`4)@(=SQy`PE!pq~EgY?+{b z!arGLTOpiH$Pyq%=pBD&j01t1^CBBJfr#*X!~-!WL6rG&9iiKqT}+5yYQK|Oz& zh{nGr2q4B;z}H56Pkr3mi4OR0oE#G5VgF}HkxjLYy#hd8{pGm{z)-^bB02mw`LYLd zZ5RxC0H{g;O=hs}bK`_8Hwh-MwTzy?8oi#wEbey2_7`%-&0u3O(If8^e&1;>Pj@0P z4A!y_599y9|jZT-{T-d}H;@3$EuY)3Gh0MHyqeT^07I>so@mBTTf z0XSdYW+G5q5doGTSYeA>5e^QX_&N!EUB_HtuPKNdk@0)>#wgFx_S*QaN|gB9?NMD6 zev$+!kG5i17A5=Av~P-C;ttEvI2Fnyq0WX0Nv%B; zg%#5^Q%iSNn#sFAro)>rzHxcq5EDH&dx7T>CZ@s}g^51%BoF4hK)?$L+AE$<@ZMBg z!w-Dt%@g~0gcQL-(MSO4k^#y^Smq=B67PY%K7otzOl3R;!oB3BNAisIX1)U>EFN~Lv!b)iQT$k<3H$#IM1=V& zx8qa}v|2yty92b?A-ZGHvH9GiUG-)4yeiEzT_zIrA{lb`AOdEw_hVd|elD;qB!gJ9 zd>hZ&@ENrB;2bm0O50vVz&ko8;%iAg>$U&tf_9uv0M60JXOqu$R*ZXoLD)C`_U}Ov zUE+M8n67j*d)9896C^gyfZO6B9DVgk+Youb(Ei8r^XEU?I@_l}5Wbb5GaQe`b~aV= zfgAJ-b7t1m_q@wP!P_Z8=XO;|JvmT}Co{Mgi!-Y|gAgMD@@^Uu3~ghExnK3U(3z{Ju0wo7CA=Dj>XS;1jZNMmFfk_*;D67ZKLI2AW8d5qD$A!}5Ms_u~Zm zT6_M*ji9BAZSMsmK)%a@h;Vb92mg}*4tS^22_DdmigTf`V!9KZasLKruYJ646Np(| zYCh+cT6($+|Ao=}Xd#IIO_f0r_NF5o5jN9&o*!*rUc}7}!`vq7TGMS&uXCQ_hFZ-~ z?p+wV4HXsZ1l2d+_xtZhbW%w79q(gh38;+rK7?O`r@|_}G#J2#=J(&AS;@)|0^vsx z5q@QDe3bygE7)krX5Zr9xL!v`U>iC%>4bT7t zR0_Jc&58+0%oP9@tHS;-ULu^|ML>`xiSRfp>)*j;?yLxyua;+;rKv(_at2)-?O2)| zm@W$0H`tn;yLxc(ADA=D@Mbna&@Np5)d}#6!80b_xUI4V>B8B(50+@ZUW6k zaAe^dfEqzvmY>M*)dH#^<;0kEF7(C4JJ)57y#c~V(b(7Li5II0>Z(xF+fnMjdNJ)M z?KqBJl;w8k-med_|4xzQ{XP7ie!6YEYiELpl0;P4Z|IodzW6la`Ybw|#r&7uB`1ih zVM5aCUXXJL@|X#bfhlIGgdU1%vL1HGVH1g+c|{S1s7z428{H=5_;x&DV>T+L&2BLP z+hbhl7VpZ_6+~}(>U}%gM9@K)X1RfGAikktp6F4MAOF#UaT|ertj(+WoBFN#_n+Mr zA3<2FbBnsLJh?d~ew*pk$91u#SN$0{06nNF?#FHc@1V=K%N=Vwx_Vo>I*P>*GcYzYa@g6mxvbhy9qq-mW9iIYxJ9Q1%hS?t7eiA418tW zj)QiDyK%)I=KEpMSYKn97v2QIX7>Cdm?KZ*0_rlkcvLeL0~rSn^rl7hMa3w?6o`pT zR3Ox2-%cX{^f7Rwpp4cb#sy*m;3Ec0K8pyn2>%so;oLHmG>hF zhZD3mQ6Pm05QoFGjFF>^-hat7$%HA9;R_PACEune$hQZ5ybZC!&?+fD!FE1P=88de35A%Y<(!2)|n6 zL{^ag6~Va98F$EQ>`Q@~!O-7WOwi0t!?X~E@$COSTi*V%GRtu7>FZH{w3b_{=*apA z#_9MKN_rF0%ayy-*Xzgj`7@Un!FF;kC;_9oZ^Qt8zLFAk0XQ2(Pw!RcP{WE zm$LA6itKHF201U$1h+*EKQ2lCv$=2z!i5@%?}v?9f+j11l`!JsoE$fBn?S&pAblma zIP+(On>li2k{H7I0q3NNR(5zbUhUm2QbVHCu5vbl4a zhtlj40#!HDoJ=s3<_$BYyzU0UA~FQphK1n7jBt}9kHcvu-qZ5l$;T=Brg&J!rMO+W z%_<>}q(9s1ZTZ-vU)#&(6amiDBo^ivIL7=^^SsQfi z7iKA{jIVjgUAi=urz`8*!dS_WxZ8Bgd)GA8eTYQt(9yT18R<|S@9}V!00|m42APl} zoeQ&az|DVumc1yvVFA6TIQiH6D}P-uneyQtCwXW%#lEY_Xy1NZF^#dy-~!dPzF(p+e@_;`8AKdOI1ev(TMuumm2rf8d$m^zg@OKtC|5bh z_v%XeauHeWYUT$i{0W4W^6&Li`z&b8^=k{C`|Du>+C;P`*YxEZsuVZo2W)fT%N&2c zk540f2eY&In0PO1?V0B0)EVbA=YU|dWTUw-ttZjxP~A`q`#)@B2zv=mA`cZ3F#Zjd z(oG1_FW1H4V6v53y7>{;jjn{6o*vmxwV43@+o4~y0UDPFO_oi|S?X6Py$L~!mO zXt-yZErto|HsUl@c?Ij+JnDNT-ZeNf*kSfVGV~GXSr8Gng>f!8(rvDVH*&I&AS9|m zzbcneKEViv;TRP~eCIvO*G+!Ekmto)KI$qNP5-pYS(ligt!WFp#kUVWOFQ__Nk0x! z2m%B})hFdU=|T9}}|hAP5Ae|Fq0bAWj7322QY#(;4>hwjn+kWtb+_2@G6o75^!~kcwU~6^e0$ z(1?H%AW%NITAu+;_2{Fc-hFwm`OGY*v4BWoa=$WU8#@n z^AXHZthK>jKofNfvCr`Y@p}ZIyh5Md7?FMh+(jj2zEPrC=Ox^~{~o@M?~VPUPevoX zxe{>BigeQ);SLBnbaoTeIU$@AmI&rJ@j=7P94x^yI6c~)0XiUKQ-x^xB*lrUHzGJR zt0V>X*_v7auqKJ~Y=M&-VD^hs&JukER%nz=(9UU6LGBxb)O8XH^HF)g0*+16OM_J_W0rW z^t6a^_QNqQ?{8U$fr9aikGMNC3MBGeq+y@-OeuISjzbEfNe)^kUm}GGki1zvi{vcw zl`)t9R;=aM3!}99g5=vrKEwh3vT+*(@btECT#LlzKj+n!j{$m$Lkt>t_5G><<5iA( zKHGf0Qu{9kr&8lBEUqZQAWj_w4GYKYrgmvFKp)BB$#09>!HXSzj^|~4c7-4wzlEQ3 zUj%U)`KRmm*F{8F74EsWPf@`AFvP>!xum}aLDq9EPzl=@zHaYlXTF_&Wb|JOH%1pA z=w2oFYlLBHWqc$W%U+T)CrIM^q`=wmhHkcbRYsk6ccdBd)WWjg?scX)40lO|kfC@6 z5t}0v+R{9k?Y$#2ao{c9eVTj%0tdO113z;} zb-%9oy}~_xH~v<04uSfZ?`vGv-x|#q9h<+SEZ+vf^aTWZ5p*ViJbJ&pY*p&iy*Wv6as0YTO_uigWdc(Yh<~##|}MyqxS!*hoZa6T0S6J-&XU` z_)q)aEtyAM0ucc%Z1eAOP+8zPM6o{!{P3Wd_U%hEuDgn#kNp8*xF=D2aYys{8x;=M zx3>KCGf500foI_OK>2Qo+ac)!71;ky?f!jQV1&ZMchrh3M=Kj7;nBp*4Fv+^G4De3rr&|)oaEYOPpj8Q@6%7bu+mcKC%tNwkoLv#SN7ND8N`v)%l zF~mZs^gt6^+FKzPIkAU!I)TUg)u8V|*d&xc#|<`fw#p)0&kHXWih=-It~eJrd8et$ z{`2zrc=55k=o)a%6!x2MR_g54I3|uaEQ{6EiSYLmBraRY5!WHWysE93XPe^K9g7et z;cuK1&7IhiMZC@Mfx_6I;cu%0%B!~csF}#~W z1jBj|K)d3V8^xIHhDijvNjz^h3FgxR5n|roJ|4qd#_EVQZb`5?J3q)=pT{HN9kl;L z`g<|sTPwbegXHy`47s?7L9lS5kvGBJq22@#XazKm2N4Kgqb~uVW1z_<935HP+p>D! zg;-J)|2zcgpLmqz>O&ejHChM2Gw9;`j^6qMHDES&;WeU&!Ye z#C0*D>DO4C(xMQketMmEeLVU{U$3G1YD;FEN!Z}>{g;sY%iJ(X_}S67^S){Y!ZH&xBlN*ePe8h=ZoHbf4$e-JkJ*QXo42< zZnK_O2&Ut@ZT{H&6vg59>sP z265k}Zwlh%uai=`mpItZSM57Y3xNzj=RTf`wf}qk_GzcoLCW&@@=LNkL!>6Icf|ef z(ht)izGRCsRE~Qu_#rE8;}!ZxsRPnP#ez?o6Ci}Qvjj*A)n|kv@^7cOA#%Jz@AqWb zWUs*TtkqNk61Pzw@c8}#KNlxCzU%h(@AO*Os4j?mk{uRZE!+rax^`Bj`SQRmFmIq| zfU)gy2fh#zDlb^xuQLdsF4nYXvAiAO)RDp(SA~DoaFMKy9D#ej-3;-QV%-vZm@S$& zj{$`HB>lQKnt7BbEVssHrn{DVdF@p8{YTxu4?=i70KZEApeG&Q2ZSXSYJ2yEFJDYw z0$Axo%uPfPR}Ml5l(m-8Hmd#?5GS}Yw(*|i=ERjo##3*8n0`-0_1Y}ojU`xp7bQF3 zc>Hw~OVFA6R`Q8}%d%qs(Q-iUMCu^mi7MaXA=O^z$*DoyR@P{3S|2fjmu_NP5#{={b9%JyX;^)JM zgyTAaajs@a;dcT?j2DYwr{GTt(g&w}YJi zPz2#+y^SO7YfkgTZueBKeJkKv=J#AX%KF%2uTGG>`aXn3J}>gEY!BL&S~s~rs#~T3 z6^yiQUVIcCJ<|8_p2NAMVwQ!SaZd=+4o*B`)h$WL+~H*FgghHhyRS}0f1ajR=RFja z$mTPS%ZGFh7U=_=lJf|VRN??6oC9JE{Ca2Ir)N1JsX&0Z-AWry_X36)AvQ&sPX^)P z?h|MJJEB9dnR)Cq2#WX{2g>WYOXSd*mfVnyW z(~mHU@56=s1%cBf=#?NGAz1ZabOL1$zlqle=xLAk^l~L84JF|3prmuLfrII=3I~CC zzCK-&_Dg#k`-;o?&vJN;^EIaTkr%?vtbASILyXJI4@w&V)Jy#BJ-?!J?bV2^4l*Am zZw9zcKG9R`EjD85wwUXfAa2uUHW$06z|F58{|vPf32zw7l#|l)M*YIjjt9@nas-kX ziXj6D5bFm2YOLiaB7fNOt3|vCit3YDbPTY71+EE>9G~VZSN7Adu%6Y*VWwEKE=%F^51((khHpl{scS^0u^Ox{*WPb zRZ$*Vdi^%;B(}+|ap~)l;5ZMDGXq#epuMml_PW<~tKWbR6TNsH>!^{>Zp^+l23uB-T_lzOpxS zeS5wxuDUe3@*m1v5u!}9c7}CX4oKt({yaoizD!9rECC`C6#(^52!S&ei6f}|azLVJ zUty4eI4Z%|!)=^eM>Cgo57}sLh)mgi0mK%%!ByPjA(izq8A21mTR@cd+4T?~<30cI)~{XOb@(HS?$<(BwN zvwuJI=*!tcF}cyUKKV&)TxUah9!o^~X735cJlOaY!|o_6Xu^Viq2zxeZanz%UF@Pn%DJrIcX&j}eedwLk8M)Cp@w z1?JZ%8shL-L7aBkRW&m4rR%b{|51mjS)GuSB|!Y@m;BBa+94<+$S?X7k$P5=_L(4F zk4r^@pzHn@lEKkQ1_9!Q*pBgKxo38Oy4fxF$-q{Ery&AN3*TNpUffZa0J=l?t&W30 zxY(gcZGP+F(r*`P{{uz&7IWzuD~TNux^a2lHwbu~A{&F^+V?L+-%fB?HMyR9zFD-V zFnjaEl&vY53jhDX)B~|tsTu7Yv#ALZ>i|uVf4>&M(>}|~9}=GJLEEuQJ^fsdzQwh+ zvJVD=>4T_mN%6Z_L?sh$V_U1u_t7rvVx?csUC6mwmVh_oT&K7zz&hBYkmhqA(+$ShkM2O4$AZul0|^% z;lm`|9$>1EwD+)$t0IU9BNHWCd=fyo3>ZhC%M|nqsFNV>FU$Li5U}GWlfd{}BOxVl zbksb?{|Be_9Xf3G=~MvQxNn8{K7R{Dga>ta@sdAS-{cPJ%V3Cz>D(700{y1e7eDgK z!qmgztHU7X1`!C>8%7+K_0a;Qx=Z>p@wr=Fyz4f%z3MH`y4G-TH45b6eXHgDH3A4X zflx!LFY|>;JqfyXe^j3nSK8_uF5;lQ7ILqu;re~IbRCuiEy#@9S>*BCXX|5uV?i?X zV9+M|G8^!^WA_UUkz|53DIvGKm>^w;3=`ejo#lW8Tx^Fkj{t%ArtWS^etQBFAi6m` zsF~RGS3EKj%jRy$K*qF%dItb^j!` zgyMgHDI!$b*S-yw=KGBRY}V6N@iDiCI^rh7o0ErJnvO}BdA7%A{>gUzFme}#6Y0cv z78(EmAOJ~3K~$uu_+Z%%!XQrtc+GdtbcdC;4?wt2TSLUmHLsMHwLb`w1I~ZW+l+WU zu78{5qbz%W2ET-o`eRuuJ9A!+9a%y5fR?Wiu}*NK^RC1EXxp5g=HhR^M@pC7yn^Lw6I11kRc;*B!QR0MN=9Zba(Z;OJ`ozEGiz zi;}Z=7jykw&?5en*Ve|quHrM(KzIb^EvbR@zr}R4Jobd1w(r{n=`Uw-XIbV(9`kva z$K1V!eXrz9w-p4!GQ-n3;XV)sqmxiHYoEt_7-Kwtt+E$>%5y{B6{cBjX>+YmW4;-t zZ<~rTB=jA@#lgQ$t6iArbFB>5%q#oJQ%aTSIhrU@wra|va~2~9jPtdZYY%TWw{2Xv zw{LrwJ0i)}s4z7B5us}Y^YlSkzfSfN4ZJ6OpNhO~>-vash91$+r6*I!PsZgTU}cfbzDyb_-c3gM}`e-X0L}E9c1@13=AT zAcHbp3_iH|W6?QO-x>}N$4QZlZ!~|3hK~|wzbpYxQ{X1(b@gF!$KBUnFFX7w0?<5R zT2(LLx)nByNJ>R(J)3Ry_EkZ=?@z>9cp`KefADR20~oB*wp|gx{)LaUz3gK)B8I+H zlmGu6LCfzK+dO#HCrtST>6b=?aE*1W(bUlm_&9Bx(r1g#UPhiAOz|o@gx;@+BQ=#(f zVD+4A7d`pUndUzq2h7zFcnM$1-R76FaW)>2h>t*yNd9aue+)qL0qPE5nO;tFZ%a#V zp%H>9_oI&4mOh+F4d2FQ?766m@0GS5h%phygNX{U_u?My#00`~1YijlcfM@B{E)D@ z{*7M*rdj;^-`5F3sLKAN*W^q^A;kga~omj_{;#EK4wfz&ueW+A&|I zIwF)g@B0q~(B>o^)W)}uloA~e)t{@K=V3q9oitJrQRAr>#v5b+;P zu{3<_{Jz|2y#;iydt2|;>S{w!x&`)QN?H^?BcP<@@Dl1$=;n1dMStKO3yHiObvuOd zndN;BuVXb;fy*P zSp-O`h+sw8evv2FoahN%HN0$JaLr-0dgM3E^p|%48?S5lanliKtZ|=5Q}_*pd3eTJ z=lVk&o1tl?=WGyeGvhqquE)N2 z2rw6}a?69=z6>0Q2r3mAsu2KE1 zR7Qs=zo|Vhv);BoBA9RUQBLImb>11p?fCF$&dCB{EFk{iwnmGmzoPgYzn7E6BR+%w z;+}`a(#EaG00JbXI3Spr(F90N;($aMo{QYhzgXrPC9R6#zSy>kFgEAPZy?BXo*s9v zI~=F$<&+cMtgkkn%c=I=DuCXAsed}>O|TkbL*Ed_Ap zR~)}-7SqC&LMb6`gLR(Tm8Flc|24|GE|)m#t;57{!mjP>V-%NI$I2coGQ~@QE<=h) zb(cyhmoY1mh=&ggaj}FY@V=M|de%=OfE28YMdfL{s<@m#DQgvr$TZI_3q_;urx^6P zGHN{N+xQ8P0!U2}tV|<7K(}QH5IyXJMeI#|!+6s2UPy66!Xc|Th0xo#OE?qO8#>UI zNaos0Ae@T;n<6d&=m8KB>T`YIbt85R1j4Tdhh``^QLOPS??GJ={2(p>0d%e*TBFrn zNweOBvWA&n!gSzP0u^)->!7Ocx1pSu`fp((`4+Jt&9E*&XR7t_NLZ{sfxZAP_HU_< zi159pGVWV3un_@-*Fp8UyYez!noI+)pB?pV8*8qXH4 zBVA$3{|EcuBq)1yxP9e3AMIRg?Y9Q-HlpGh-gOhpx*}Y=Wa6Hv4;o~X;@Cl;mS)^Z zF6}CW%tIU(Wni1mQdz$OJ)iwKfVlfCx#MjTAO{dV0v>h#L=YgTn|v!^csMnc-s2|N z0^L&Jp%hp0bb4p+r%L?LWJla^!`f35r7{kHfFag6q4)4k0384bZN(e~Jg5Di$m(y! z!+EBrq+A;y%#g!#5=@;CX`AbSK9a1>hJ3np*6#y#g60!5?jWqr!Z@$RXArPO|F+p> zJVe~29|0Pm*SF7e3`#RjP#)!5e{Br@A{ahFbUhdMe20ws+^lzr`@Nawtd1DhD&gzo z!br+F92R!8cj!V`_NBQ*V{vRbfh(R}T$8_WOkEB<|Tc zhPpMR<}Qo17=wLwP(%lJ1nAGzmiK>@37D}O@o|et)M||Ny(Iu@=SXJ|E7t)ajRSH5 ztojXFUA7w}X0Gpi?Xnha^)cT>*a-rm0vdDWG}PNP0~Y6!FMx2bt*<-lWi?RjzhwkE z1fw0|ap{c%1T1mu+f}OlJ{&}Zx`MLmxawVOb6O6wrFqp=fmhq~ab=Ksc^U`5)kJV9 zp%VOq0Buy#6KpNWznK8gjh483Wo_d;j5`$d@fe5*w|fz`^9UF4oX8P`P6jdmI#=Eb zXWlQZ?>#*AP4*^b-)%xLbkE`?7JI0rD-ne?r2OuEUDEb`UrcT8DsIaeD(Are5_~q} z7o~JZvf^6-`&WJ$w8?89DncNr`80bb3F8C0Cz187CcG#D;v>a@_%v|@LIr`y&SAuh zuwz$b<>T$lAV5I7QU?BlAb?DSeoRa^xA;r7Zxm#){Wzn;SYL2%QE2~n1b{v_WXJKY zJA!?Kj-;(5fHqhOubOa(Nns}s|JnGGfWokvh-_>Z-Mm6i-x8=Mv02Z_xu5HLlfT>< zcdvRM-tV^QpA01<0JB*cx-+xRwlbG^94tn;k8=GxLDpW4XvB*I`he&5j7-kuL-i2( z2aEgVYyv<7o!@!^yOoLY&%M)}tL_Q>ZH?wO-d_u&)XNh<%6T5Ktq*2S7addL#x)hg zOeEtnu6Y9M`X7)hK{`&6A@gdu=2m10pRjtWsTArX%K=GUf}kQ&mH=@LB8xunAaU@2 zorD{Me){JBz3nh?ieBMD!iSQLw7uUA_A9Nee-i*Y!O9UTt~h_5bm15{4!1WzIG}lx z#X+E&zS$iFk-$VS=ljBpJMI*D;s^^+BM_bf=ra5W0<8e3FAVEiABl7Vz9tYfQMK2= zWYV#UE3<(Urit;)6THrDAHNX5d7CN{(bRYzYwyz*@mXE66Fio%Rium2&{x?V*`z<*Er&&aQWNE zcg9xADIA&E32tZoXzIJ#Ha?}pk5`reNoS6Pus)m@eO(RJ+Hw^kas7pHq1)9W$%nO@ zlPAm}4awJ$mq8M}h(QWB_e4NJ0?x4?gsrsyiMDv=wS0rEf7aUS_z?s`T|@js*E0Z_ z1i(ZGVY1Bd?2C&C+BMxH0Id`D#~(0F%@Pr)5G)p-EN!xHv`kSPP0Y9n1iWNxM>PU= z7|QE&958eT0o~lkvJC-*O`+$+I|O{{F)x4eZ43SdU+EWwJy@=Q)c6AtArHY-6tP)= z`lFJK$5`()c0Va7nwb5fhNu3Nw^gPejCuaHtKOl0A!1&zh;QX6JJTD% zY@b2Io!y62Dul3Rid%*qpCf=-xnhx1e;XB5FLVZS56fW#ap@O|C!IXb93m3&yBHYq7J&v zG9MJ&`)P1hNL>I8ffvbTgT7|}d)WV#<_+N4aEOK(@1p?FcEf?9z7K#3V;?Wae*xhM z0??a4XK87_mzmR55FNb1W!?YjF(w5Kt6ujxxdylzPwNQXT!BLSXK>6PQD_}-U-IL< z8#{EEH%PgPj|G^YYhevB68`nk?yH5SJ)d``Ws2L+*l#=6ieQv;V_GVi0Gw&) z3tSG8D)(*-BWFI!e16e_1pZ+>|H9gO5(wDF!*?%MSn|APDf@4cxz&88P5|$;&h#?@ z6Di+GhCKZ|uAWz+DedVu`1-u!E!Bbgn>T1uB(1h-o^}Q_MQ||3a{bl&bS%$#Q9TGa z^QwAyU#R0^t`pwcmzQEStro-oLBxB(X?}>9THa~O$Oy%GA@`?u$Z6u11&ep&^JV)@ zkwEoc64&0lG)CeFw?t6J3D*8=tuRJU+v4u9U0}Qv4W}x-hztql7-0toCB#vAkZ1U;8gLeffg=$4z~P_TrGpqqu04CFpO|z1R{G+!Q{rh8$o&c zrH!zjfMu@s3)f5Wox`pk)MF!VoW=o(#4#OO#aq5&=;E;nbRd`VpN>iCHOV?B zi5d@d)e(f}B0~1hH4brfH{){~Vl+;l1o+JQ{(MNHu9MAcIgY5q?Z$zD{rd+3LjDSs z4f_IxG&dUD3?r_iDBWbx4!v)Saq%5NSdB|HngCJFd_N6ev%Y+TgG1yM z9lvV-lX)?&^UY^I{vn6%Nr}&1j0mVpHg>(M3B@js_Z6#RWEzo_m$5Q@7Z}|u>P|6xRIH~hPM~y`VlKUKkBDE zXa*e6E`G5fU965;B!}B@bHH=*(lk~`zddWQOET{tNJ9c7f#v%NO$jMS5UA!;(s5~+ zVxG|Ptl}hpE%CQ2-;q_P0rljv>Kr%22oG_{;}W;FjS?U(N7%P^A&{Tkp!)$rUEnnC z@ZvVoHT<0E!6UmLI*?e9fKbE=fH%q3K<~4%FJa%yi27j@Ks}B3SEPC$ z@8ByPab7{1=VR{X)RF#1J>L%Yucbd?@l5@*%lK5~(%t3YoRk+FOzj9*$P+|#FCMeC zCy#8s-p0lE6Qns;hM+YEUS-d@ooPl%McH-)Ja{%5p4a^Z&CK=;@3e{@ysP*{4C+R+ zhuf8F?P8@#_oyxLYZXHo6Luckn>F8t&&;Cy+$<3 z@Io=-E5et32(F^v2@jV5l`|Nb2L*5=OECJ%#rhQ?pQmwNp zGW%um8k2Q^)%pk`Ab3tkQpYz+f^EG0kT0&#o<{O-E2CI+s1QoTql@0A2<^EaQ)m|+ z<2XG8%@P;P!*de>xJY}R1NR%ij|K4yEeO4f!Ydy2wnl?HfLRgjT^v_vm!13ZC;NZJ z4j*Uz2b%RP^wr)!m-TZ&$yf$3%?Mgy(bMrOMi+j5uaJH#L9qCV;lt3Nx0`*u8~~cm z6saZ*al9rn^(^*(?F#7Dgn}tZWqhO*5Sis`Rv%q^}5;a*+8? zX%NOqSZnirkjt$@Y3us~5iRIqhFDl#9JSmE<~780T;U(hw`HcJja$4qX6R(5AHaQo z)`V#X$RRGJ!D{;YXad4$4(7%Lpe%t_0-$4{2U-4u0P2zEn*zU^b(eB)?@Ysz&(p3J z&3N$~hxnV_kH<`?jgcfw1mS)a!tZ@|BOL~}N@3nKRGoj7;mYC2qlCQYb;Nbm$Kh!Y zV-Gq}8sPyr(hhThfa@P6K!w~q&tInD@A@ZeWN<~>s#I%fB>2v+qqQJkHG@6 zA=qf*ooBI+wpU9a;@K$fI+DnZ@Zt3NSTcy87jm$<+(%+)I|O*-@yP25Mu6Ztee-A% zONZ`7Vko&4Ip~&PW(=Db&Wm9aU(KA$Nxlz(RT=fQxHsioFl2Ux4*tsW2;2l;Wq%15 znb%?Rb``Xx{fNTKpL-oRb{kJ_RTjz=1~Cvbh&$9>sGFY0-YVo_11ZJAqT7Oz5F-A@vYI7Cll?i6ZWD^96vfkJ*ewW zK&|VjNR|MhpMnke_Z}1FG0FEyNcY8EI)g16+;4mTH@3Q7=H|x`uQ@TzuOFIew)blT z_QwezTmvG)TQ(S9mn!%6a+y2F<#p*MXYKkfk1HT+Q~5d$a?dXVG|YFq&t`4A4Cak5 zXgn$iEQ=YON1UX|LT%UIPX?j2%|xzKp&fUaO7|NGxRBrwGYPd`KR2JhX7K+fn{RJ& zeZ5Jh^zGsZjCZidg~dW&AyYue&5czXfH>m==c~>6YgG^I+ClVEE)v9j>7IxA4O!&^ zSAW~LuWaM77~Y&hN4OFe5vzwC%Hmc%khTd#bU^obr>hnYp1TrtuHxzF`)5jkJTBh9 zaYHm#${b-AfKSxZzZlh+lumP`{3XP^zN{B2t5bl8(K*sM**)E}$Z!G#7v|7gfV1oy zr`&e*Xpc#-Gm(eYBDc+dB$gn`MPf78*dbs$ONG1*nQm{VKPyl-Cu76GVoyZN(#GK~ z-_Hcllt3F4h>e0Wcpmi3Ta>|iDF`pKdGwSn_x`<^?p+W-jA$$GglRwA=2SgUN#HCH zXblVn=fNO+NWef%3j{=(?~p}&|83+&uF3$!5c;>w_!D$^?-bQ-`T(iHmHUw6w)}I; zn({U7J#C0BM_>(O?V7Fk&rQ~}k9*9Ot$N!oCEUuM|0T%vp-`5!`ztOk8tXh5;%?E# zNY_XE|1=8U3Dg*%Jdwyy>)ysKga@{(m2nRooG;h#Z-V!qTN7I!mJ>iHL{e67B%Tnpj_IF-L2^~*M=iH0wjv?UpjQ&-t@jD@H*^3Z7lzR z>Nq(@`2TkK{-eU!ECtYzG(=pcGorBhNgd3=MAC3j0DpT4rw@dm1!Yz?6r@izobeG6 zuuDx(#Naj<<#gs?EnsqO&=e?Vrr$2*yf_{3p$r-3ey;}sRh*VtX4u-+6i$5%hsSx5 zS?8XF7hLv<20B8xl!=jmKzP{YaJd*C!9>cnHvS2`V7>XjK<~d*&RcZd=gdeQu9M(6 zOfk`01g@Ibyu&-7xppGQTYk8nz1%C~-^0#SL?9}FK-ldd03+EeP7hher5^Bfh^HSL z2R#Sv1~2d?H>Wpw?EBYAzqR%OPhmGxp9;me#@R%dJ zlEVGIO50AA=jQ1Nz$Jdp5>lyt$=o8Vgf0wcC3q39O*U~dNikjdFq_odiEr1EL~q2U z(r%%g<2KiA-mi_Y2cQ|iDd5B{@DK?39BB_49F5PUH=OvGfSbbI2wU_8Jk!31fwp$P zD!ge~YK{8>pf0xl8o(j6`v`+ThF5odL!h>B)NMTfX?48ygU7z}sLMVvM(aZ0F9M+h zH-=wZ2z$bBPF)CgL*5QzOD#f$L6>kxqV~`EW<7Nrh7WFY&wCn>-HTzKkxfbI{}_A4VgGs;GM_MC!v^aT?o>H@0gvLE_GoRK@Zd%MVAMze^= zyE#|hzlp?~?0Su|@N;TQf*5-WPZ&qkkFMuQ0RRJ&(B3Bg^YDgdo=hL5{M6!rBr4oy z-(ao~DSUR09gbU~yv@5bSiZP!gV2hAN->Y64==6#5n_IXJ_rg(;)i0MTV43TWmB$> zYgyhK2tY?p6h^4PTvh#M1s>)P@3bL^^F21reQ-D*dys&QAd6RZYx_Pjodezq&HBe4 zfPRN*hE@;E%Ql9x_g?J16alo%)xsC(M~OMb;vmvYeTwrPwCX+RB0ev3i20lBTRkoA zWQDbc?t1xymFCuWAb_4p_#Qgj)-PjyTR~fAc`xQSe=mh}J%9n^<-E|T2W5CJAE93i z^w*}+v0!^;eHR$|#Bi~Os|bYufc#PKV`{!bMn}=6e8Kx$tu1FpUgn923jsF?aNJFx zqlrN<%OvvBm+9Mr_5f5stG}clPWeQNBmA5wdFl}$A*tVILLjg_OAwwM%N2ibp#|U<~yaPM|0?70d zZ-`&jfUCZiE)L`{guv%vjUWi!GSI!OzQNjm5kWZ{ zqgto?^!4yU;4)5)_^evW%9|MBUUZ3SS^c7GOIy*NchF_*zg0!rwkH=kD<7^2;|6P+xDjE+P=>der@JLi*f~ z+-l3H7yX|B%z#QP@rZ807eGzP4)h4n#`%4Mo08^Q`*`iQe(&LJndc$D1S&D-Y~R9a z()vF)5wf!YYKIR&09_yz$Fj%SbtRhE`(iYJ$Jp}>?c1L$&HEsnVM~7}2p@teXItv7 zq&+VIkk=`a30eiv_ZA`yH*;3#FxysMH>*wowA=LKAnYT6;B4zh_HkI_)SEy603ZNK zL_t)jm)*!goP(H!tlQxq=_bPO1dFJX74}=S=duCTSu0?R%6z)shn)IW(R{L5-RW%= zzvGQBBq|IKiezK8q5SGcytIUH>{^=debvf5;;_UvnUyt?D|di0d@Eu?$|n0Pw~t%; zGm>*DSkJ|{gec^d8ZJ4MnaEG9MsKp}Gknk7J7k)Pb|X~ra% z+i+6?DB?u1EH?*ii`0{J1M_*Hr0nvMn9S_zovwNCdKTDWoZwe1;U5cUU^J)-|9+2D&tx7*=u~P1*VaZL406cw zYu4CwbG|PUOf!*aVNE;FBo;u-(J6{)K7sHs=sSIUdIJr$JpU6qT>RItK4uTMlkAdU zo<*DurR`-F66RCoI$9L)@o6BWj`vkUM4YK5PtZB>y2WoirEhmolSTqX(ci6}KgVZ03@4e)_zqh?_ z_17l@<=g`!jiT3Q5t1xYVCK0=qTBFE1ndYh|0+V`G#G8@<1N!|+mL5+`CCa~sP3j{ zJDmV(25gah|B{IsIS813KzRX@0M3i=4&Ws2yU35mESMICB^}Ojg1P*pUjK^#G0y0HEZxuu*8Lih4opQy+(0S8 zc3JSc_p>t3i{gUgQ|Y(9I>B+hTx``+)&$#aW<-doE{5kP6!1~^B$Q(@`j{uC8G&$4y7+SV!biWhON}x3F9CC*M$pUNPhxKWt?982 zK!0VG(6b@L1RClueJu-e`$OpZFNkOZ$2p1FP)#r2d9Y5fc{$kp&_pNCV)Bcupl*{ z^#)?z!szqoB%9!HfJzwh`1qSZ80}1Z9W>eR_VB*->F>fJn8ThcX=!$Q^zT1j{r?N_ zsxMI>yBOOh=`Em)2()l^SlxbnNQ?-J9Q1VNml*`0yX1A9Ct8EGq81IV8ZN)U=MnyL zrW1K~$0nCGds{LPjsod(zRgMu61U%Rk#b=q%BT zy`ou*;`J@g0SH|{TY+i3XKP%7-1asX0Z^NJ@8;c)y@X<30|ounT@yR44p4V^b0A#C zyp++7qJnyUVlZq@Ad;Eikb_tC{QVOFYrN)ZA6RvxbnXata&@n<=J~@~=A|IuK{wd% z^Ip@;H1PQZ3o-1;5!ctpa+h?qfH?~5^{b#auk?yj=frmzJ>0+NO{1Ir1chD-<2Bc> zrMIoJ@wv!&zBdIC-76Gf0e#@nQK7g|>-Cskf@EWXK8yBt>h&dlbNA_P$ z+}M0Re;^ zSpp+!0_3ESlMVBnapl}B34Ii1;Y`ihqEpPNoe@fh*wjWKiS20ZFHhT`H-|PN>N$Bi z$Aen8m~XH1Ebly<{LcG)Krg~nizwX5I0gcmi`soIKsCL~wd*E$iCx)D(AtA;?TOYv z^Gc6~0Bw+S0Sv-KyTQJZ08lZj4gy{^917wE0%54d3F1apMlX%Ih#3|_X@OV-hBL)0 zQn=HEggXI$+WWPYWS-d$^bU&i^#a~N!0W)%npGqGK!&BS^(3~=i zSF|65+pCYT`qa|bOatVVH_+l1x(DT0ofi+>-3h?4m^cL(m4I`hQ zj6uA_?%nbj@>!o`jnt+)NKG+{ZXI36NhR zo|vu*$SEZTHQdMMbwZK}rV-JU^M3N$PzX`;hK?2ylQ!yGHlW%b=Af#W|AN=v?p z#q0Jc%j%9(O7}hixY`=`x`mk0h=wQmejg-*U@nXyMX6b&&kA5SG2 z)ao&hhk}{m=lmjIRx_3R^f{i_ET>!`eX0)LY3>ex6Xqu@K$>^}X4%qqfz?_POau;jOt$$xg2e*SFdZh{r_4rJ z=0iou5lYZt;4^!?)r`634CXEn5qbvQ3(uGLo88>+1c)zubo0KTv4(L0kSTtK3p_3i zcIkw~QStW$@Kl`ELmQ8IaEIi(i>c3tD1+{!$Z!VP3XxyRTnKm3%;fIl z`8@WvG7<0V@I!)ah48klw{ zqZ(#FiyAD@gF}w}MbsIh# zwpsPZ?3Wn%L8!u<8D1x7cQ<7YPdVo;eJ>rMJ`Epogw-;GBPEzuS8Lz)6HEpD?*YQ2 zo}7^>4F1_5v{!)}4NOjqLlIw{z&tAi!c@mCZ%>{G?P}5|T^NHCnBmjdNGnuv+-a?9GE0MI3_$iPYVgJOuJ zJP${h!TPm=MbE(R_)gSCZT50`HwT*^y3Y!fWpUT3=YInPY}B6b(vkFqq(rD%MCNb+ z_?$4n%iFdU$-aV9np9!SJ+RN+WYcKN1AU{5w%YQ=@dn<_KWJM8hrmWypP{vpA#FR+aDf* zLCl)v*9}#slI6a2;xyasdwC5Q4m0CHs&0yCk3FoM_O2M(gF90LXLvKBwzczH4z5Tk z+-VB|^l^&gcpnEfSkpI4JmgdYRQ*HCfDPMk$%AXO&3i&-LIbj8YL$D z10kYIfc#w9-PQ8l=ZmX35rk*u-)}bOx)Z+tMYryoDyHQus9F5i@TSRsjeh^EY3xBg zqTlo03bOw;$BS`^7JY&gJa6i7^KMqs;OOjUZ4FOxWOJ^hE!Rae{y$`bLVJmL+JHuB zLV&CdIf$9Y0f}2N$t$ROIvt;c#kVC1b>cljN8={DZLD?ecbFsPOq=2{&v{(b&Ajx> zK8-SHo>o9uBRDL-S67C;pM&Wd^Z5k31I%MiB<&2Z@&3SjK76kC>Di2+s_C=@G>1Je zF~k8&0`KwTP}a0K#f7^;z#p1k2#A?m%?F&zkK=e)oG20z&_etF&E5wth}trHUtG`Y z9;{;jXE68$;(j;lZF|-iV#X_-j@JpRss!|9&ma0lv^3)7e!pto~I3~gEyC3QBv<{MR>k2(+viJI)~dQi~GHBJLX? zh0A}5*w1eTKrO^$H#2Q);yT&DF5H4$7}d#gKvIPO z$#IMM)C`r~+yKyF_~v+kZn4I>D0m8QU@_Wbv7hESkGl)zV0r#Gjyn`Vwhemb{u`x)J{kBOY8F^x+x3uQlTErx3`UisQReS(?g1FYRZ=aA@`kmbarza6X&TLU)jnmEIbe}fY6SW{}sq|#y40+NxL_?a|+#{Y6d|FYT`WX zkqdMHz^{_>hI8Xy*!pcg0rV7{#GcK<6X;JHjC-x`CE+Ao1$qMxbGgSo`eU05H*Tm7 z+lBu3$j^L=jE!*{uP?O!{xE#V%tUZy=SZA(;V=k4TibAX$TI)Y;QG-8J~yX!%K9Jz zj?E~zJN^w4`i6B*+#>#ST=(^b4^jyE+9VRuESp726RK2h<%(TPIZG-3p16ozlt?cQ zNR|Le|MX8Fc?8H@9kEOm0^|ZjM}Ua>3~;Hhk}52?)BStj_~)G;!vq-_ZqHg7Gv-3u zG$262l-r-w5y`LwNL1-%`L9LTn{$BX zXMExqU(h@&$FBy9A4ed}wxn$!I9#3xd-$QB?>t*w#apI=?qO{yMkwtEJ`~ivr`zK> zj>b+9K&8Fs{u|~^FX$dyJzapuMX(pKTG_&WF%gBCLPXcFV0NP!Kf2b|8z-0%1{Nf~jesgS0fGwvR~|DG4;+XZcI=}0%4aAT9#yWZX& zYi*Xsm5csH&veXoK8c9h1LpH~ALnIh(HtEBw3MV*@TmNr&-Ql`&QAryExMrw$zIEc zdB$8XZ*9-pE_zn5)uTY%ysFyv?-X#9qfyM81F<4?U#8=YJu?#GhDW5YKF5A<-M$P8 zi^A`e3)y0~wvC0O%8PlL4>O_Rcpt3P8(*B>)-@Ai|(AchcJ=L18C!9{6>ajfSL8wna zHxNKgL3R1|-EZD{^wHuw8=_bb8@G68K*p)D!gU@rLQa3@tz&5>$R5Ia0tlMV2uvnm zf=hoqVSTSE)SZ}TeQykaj%fL-*vjL~72nBVd%(>I!8AE+GXE>vf+8EJhjk8v3QQ~v z6@+;nCIIxKMVVeT?6a7&eb@uGK_D=%+2{-!W47^7l*kqC;9xr4w2B6&Ip5|n-FB~6 zXbg2Z6ry1oyN5(ulUT-HMrn2?fx3*iId<`@wSj~j5^2aWm->wki{Rl&~cyR0IZ zD%{JIymg-C)?d+jng&(HPw7f{aeHBq@J*^9;^i`fAn3tg)LffYLRSj?klqAHR5~D8 z0wnna$N@wiVKm`GiW|CQRN>PWkrxZ|~K!r6==~W4!lVHlC zB9AeSMtB{d=E3%vYF>NeI6-_HX#Qr5an?l1Ug68CtgxT{BbqaR8TusU2%5=oyO_gc zQRun6>LYEj1dBxM0X@OmxI`!LZDwFsK<+&qpNq?#Xs_p@kjP;*pY7@$OMmgE!*OcJ z@`fhpyv7d-{dJpSSyMEJv$Ar&i^gi1sBhC+YzM!^SoXas)z(KdnDf^%@kFKv0dg-w zA?#TKL=El>ZA#Sk?=SEN!>$-aw#Fb*kuBs-3`dRso`>X!{1n8?0Xf}OXQH0Jc0LZ= z=&}*$O0Ac&|Fhw=qNEbeu{%EOs-~2CmH@V!S=<=?+rrM>GW_U7h!4KVAS6Gug~}GuMgRL3)2T@ql%) zxPOoNJ?wPzxkOIqmHqYj=fr*0#`@kyuwJVY4ADqo86u9}hUDMIf?o2`hpmM1E4)Nu zsed>aOC+gp$~gU=ghPho;R3zn+qtrnVE!P&cAf(NIx|5+SMp)ikO+iZQ&jh3P7H+C zb!kkHo}D-y5dOv>6$lVe&&UZ7Y>J-)vInWDGvX#P5tid)4>bt@%}#j{tOww)z4h#( zIbSREJ52>>m~CNSsnn12d>%&S2ms|X<@gDjB`60(FqV@#P>%cLC z)6q!tBeGY2-wirwg@^YQfghZ5@yMfjg0C-t>l^|I%kiXxFcLU*d;s{`k!~pPypuGj|z?o{t+8-OD>h z32)>;w_9Y0QN(Hu3be!t>o)Dbj$|`LRl<7y^5QYV6$FP_Q;_BavKs+}$pBRWs1J@2 zEH~M9t~?tkShmpSsUVxM;ds7Q#t z3g>gr1H3I{S^DNri^Dt|XIvyz)5!F9G-pO-IOg()vNjy>(Ai0#XW*V(Kk;)oFMFEEi(q*-te9u{xGw{B zK%R%Il3OAPknuJSl<4*@5d?_8b=X22f2m{+o$h}P%;Y%@16|h210H2Prfk3S!YkZ1=$PWRapKN6xQf$YTv_hKlXQIshTZnO< zP7Rdrh6HnuKr|PegpOg!y?IEIjz=bKlqV2yaf)oVI9 zl+oSzHdxSy56SwKi8o!q>NP!--voMrzg)PK{r}{Ubw*Y8zuyjHFA40|gSJ@V*{0E9 zTz&TeO$B*>B@i@3{7s|nPFd``cmj=zq6HCA<`Pgc$ic0d z-klEtSHzyS0ek*Aq*KHz3EvWc`oZ#_r}t$ybvSA%^nVx0{;@+SPWXmoUI(;N_KwR% zRu7eN9N zg6pduQ`xiAZyn&xh&doAlO;fMRG7lXWw`tJ+~*~~-O_FI8y4HVI60=n>qXH4x=u%` zn>fBrit`Y~esTXbkR4)$1;~b#>o7#~4Hr4AMFjo!Kh`%>?Yc5`ne#wFIW0W;a~25n zAeZJUar%A)JY^B(s?PQ6a1ar$wj=A!-P>3a1kgswSnXr~cX}WiM-z8Qv{cjIu+JH9 zWa%%t_?iB^S9_l6f{<23SfsZt*Z&P%(>@FWp}ED^jCdRyx_{@_4)aeFC~$@Xwnufr zG{L=Xx__Y7Fg zAYAOQ0tE6Wk1BFLwMgbvl4dyxy*|KiD(eFk(VLZ9#kk%7i02+YJ1hisl{vlum0Y9<#8p2!eZ!w90%XL_q0-#a0w)`hN(o z;E~W;AnfpGD1-UVa1FIg?jh(>P*bzcfp)^l%S@>5PlI_>7mxc8DN=N+t~c|L0J(E; zk9?S(UF0Tiw#MUto}xW>gxsv|T&uONu)bH&K8br(1yzee8wHs*T4>0S!P@N+2%HoMIkIkGY&BKr$jY6f*A#HVzj>L6LLH z%I8EoFFs4*MTL=3-fCRo@@&%_t0pBXRA6(l`Hliwnhov*8E;D32&Dn- zc)U#WokHgd{Z!m%u{5PAFTc#yksC}A@Q6tO+yG9jilzHVv#e^o_a}fl1E8lgSV}=N zg@^}zneu#rVD;nS+LuoY`p^_Zw1|e`M9}*>!F7wXtlb3KrV}IiQO*l_oWmpBdCmBi zKrRqK(b(VLD^y@E1Zv>d64D^!`C?C9iE6+EF7DNkB4j)#5#>A(dyV_)c2UzN>?I8z z0+G{h{}KLuTH?;r>m==Y-=&?uBw;VdOYHeQHz%5%6AssGWO0~mNUH$?dxQm9YAwZbww;HHi{6lG&)n)MA-#n77o03ZNKL_t)u*L6sMbpNi3 zXdN-k)2fD|1j7$TkZ=G5ssxKewL`oJ#KRsiZ?`F$p9s(;&~z|}Kq#X=_pnfEZ3CSJ zal9W2$h|`APE?=Z+jW#c`{57=L<@dA7&ibD06K}qm9)Yzfc^L5^DU8#Z#QdPZAcZ0 z^-$Ln;ofD9I|BJlqSs9`N($nRd*pds+Y5?oW%mUEPpi!J4$w4+Rjt_><1_& zfYmy;az(-Eg_`rZMt#8hufxB0Oy^7-M{ zysJn*EE(b36w-r1sVssXW%wpS0`$}L(wE9X1c+s0dpRZG;BTy2QFIDuU+_p)PlY_& zqMx+7!Y~mD9pu@4C_O zxz(X5TpOluaV+w7s2TSdYe60vE@IHJ%7r<+8v->I;Y^UhL}DH5Skla z&_5>tG~VHL94O%YtK{Y4N!4He)n#rpWTvN+KUkf;8MaJfi>sBc3-H>nnZ1oFIbbW|q@4+~jd1BlDh$+l=QxN^%&VxrEiW3}{ECs26S@ zQ~rFeV%arWx`kZ&)y}+kdEHD87RS%E<+}w0x?2IZu3VabfLe<4zrUWYEF3qlQ}l!8 zSD9GWR^#~+a2AOyX(}0r$9xb7r9Fup&<=b`0KVYknI9PRa#*h-BHTm(s3HhExw;!^ zo@jRggt8za?BQXo2^?naFHFD^5Y`ZIkN{M4f$>-1A_71&Ey}5=NdWZ#;ZG}!+ug)E zzPG^ZxsH#!e6Oh0vz)c*0*eCuUPt<~;pbxJD&x5)6hx9Z5xIs@A9x;0`cBvfDshlR z+yp!x_CjlB1eao+qB#TpAdsCX*bsIs=KD-P*nb@&Z`<~>`d4^!YCLp;j3Ds7ja&&j zLYQ`{6%~ATg6X z$hqEJL*tRU_J3;oOa`#!JOTCjgB$Dl$S zjzvWvfUGDlL4mz8DQ9w??XOXSi*?uh+Em|$mZhZb)Gb7RW>7}QsQynf=i4}0JzXpp z>HUOsTP3m!zcM(Vsn6%bUcOELns__5?AJkpog+T@dj;rP94tLMLWgvv@#7HvJT~)p z1P>s%7GLyZbUaStw;+P~r;hoPTxH7z3C8(&TCEp8S{07q%R>D(hLEb{=<-Las9K-GL0^mQ?-fP- zo@^ZW5&^t1$M3>aPz&pOs%>z|sP*Np3^sqz$uiwXd^c-G@lBmZk&Ff76o5h(FZ1>`o9=H75+=v zBVnG#`nL3pTBrmwx8UCUDHf1=7PQ_W=J}{h=(d?=PCgk)bL~ui)&bBnG^jm1*eBY7dnKX=| zUt?Ycni&t?%3nc(Z%GdDrsH&Jm;OY3I+J7i+a4{CmhM+q#=jLvVxeIU{TWue^Wq*w9(Z+30 zn;80x5zZYmvI{^G=LvNTCHQM_?fPsq015ULP`b{d6KtZBFI;fEuFb1>h0x#k-8u0n zNU#|(-JK&3xM>9By~8A5jd;PZnw$O{#-jxV?Gqx$ZxH=%cyUz@kzkFhN=~MPtJxZ9 zE~}O99h@Q1McdB(2)-fRJ4BgB_i6>X<=L+oqz?%NRxFvx1N5h!OL-F3G`t>!Zy??1x?tl31Jr(BuA7NULD3^&_6m&R57CY?p3G zR6p*m6j&;c90d^7RESulPrG~ROvIKISy1U;ytcD;c4ZxxlIEM_Fji4WIskaRvY7zt|@|Bu7IU$~wKZeacWLnSD-e0PW zYX{Y22Omp;8i@%GavD$fozTzo{X_zXZ(ar-3zE1;F7IcrPgg1R{Ez%liQmH0H2rXB zvBdX9QOp3-h?B@=3M^e!TD}+X@@9ddu_SV<;*omV{=03_I1sS z15zr-1K#2^J=+N~xP&I$ACcw_17q|5Y84;lb!n$K^5f00sgceO+IS3)V5+~*j&8fs zV3!OK?C+aI#g+4S8fN!83lkqeHg{4SsQrl1+&vt857E)y!4HUeB%W4NL;u34&qNq`KL(p z;cDMGU4mkMz`6I6WV-U2LXUP1tm-UJVA#fawopUYpX}$(r>da1t|9H$G-|j`(#+Lc zHS`^BqInEl?42NqjLfFkG&sMMW^ekuV}{J``eL1% zFf<1jsCE6DHnvI5W^CWd?V4V!Z{wZW*K-C76&9+M1W(WpBynmv2xFU9c%HFWfpg&E zA_&Bz8JOW#cmaeMP${fr?JpC7S`=IE*(KQD%NXrYcYgfKFd-`L0X~h+-;{h>YqLJs zT;^MX-^C=RQgM4nJ)dd4kHqcLv*Rf^c%LEri=3$W7(Z*VK5xVE zRg_=GXU>0fp)b=I_!3Av!zXa^NDzP!eExHOOrgXjt*Qr6|mtMQ~65 z`bS?Q5X9zqD5TAa7JwRu%uZbG4KKE2?tU>o`wa|C*)De4^_kGVkqH^K2Q1Q$kR0M2 z4cN7|h*5&iPw{*g#uEU)2Ls>%*ZE&=o8TwHp3!CAP8q&8$=cgcIKLpreh(#alg4E4 z%M$(89a>=i%Sz#U-MO^rN;~AbQE@QjSidOd-o-i|U4wmHa?qwl3m{unIu;dofR~w{ zot(p1yr0MTa#88gb*iqN&uG&g6ctCLKnF)|>F!iYJJchL{u&S4jL+13-%$>fuWRet z^gjJ4;(Jrs9R~QC)ZYyYm|K5G`x@}tz|07a-XnOX@y}p0r%iW*U=tF;4mt<9?G1wS z9RQNpg2W;c<4BA)Bj{+`_fl|ve9XALEz>ih^lp~r@QA4KYi2oDU$K}AJqr8& z99zj3CVTgGsYvZjt^pxVG(WTaRctBnnw%%lc_DhLX&y5yGRLSNdv2Dl4b@3bFUHFf z?9le1%s`m(%u)JyevU#i@ucijXJZaFKSBAz_9v;nKCHOGGsXPhf4+K|vWqeGs5x7+x zz1(;cMsye@|DjQuwvpgUhRvAx8TdXyu$A-dNU!}5#hcO)>>!k>jrTNweuVZWp2qAz zb*!^9ncx!l{C*O=L!sx0NFRvvHTTz|6BJUt|Gbwr2HtnDgTk9&-O|UN$RhSo>~Uqp z2Fa+DWzLS;baDKioSm6g1+J%aQs@0yGd>Lnf{$l6FB=)2T@lp1ERCQLvqtFiY!ySx zctp5m8GIXmR{Gmdxb9rJLA}NtUGo|1Kmaj@ndb&tbB~HFfV@{h;*=z%mnm*Uc^~J3 zcEJq|yNZ)jE&6{Gd_i(*<_iL?re)K&70zCHaIZB(+6iY{{^f$lH(G!h6^02FkI$nt z2lLEzG#1m{FF)_7FLRuvdC)Viyj=fIE_MH(k<4`ta3hLe&v~His6I|O|C18p9kHPl zVclc4)wa9^@=Q9+zZ2Q;V&dkQabW|uj(es19;EA6pdWu^cRKC#P^pMsyagoZDKyzi zxIU2~CvBB; z4s+={5KW59t6Zw-d#yDs*xiklLQV9#F|}xQ^~rzkIReN@8A&&`4AttO35m1YJi~&f zZR0-Zw)EU6Zql9}vU4T&Ty0*;ois1XXK7!ald_wagHpEPc2J7PkV*pr4J0RjCGn*` zee;<5+_(~)Yhg#tO`ZSc$!K{hK}=BnBt9bhI9fmA9pV1Z+Fk1=ARW6Ry~ClmD}EM8 zaBHE>=M#^S_(~LD`g1#i{90p{%I`=V?woH$Zq2}yf@o+qBLelpFF){wg^u3X_tVgC zQ}^C)B+=Sf&q5+($L|Re0EmC|WAjYHZvkg${2+AcdS{aPJjR3hpKadCc-S%5C3|;GY>VDFZ9OPC8LPS^7F4 z@khn}whq>rnGGf0EuHZa<6o@SN1r$-@B@SM0~4105VgWhll>- zb*z(K;E23;Qsys<_lWyCWqlg66DzfOUm^cm%Cm#Qc^X-)2?NA3-s5DD6Gd%C3x|PT zF5D{vxiRQ7?5wZLo-2XDM9n(o1#B~XRTRIvaRSN`=7m4&7=KeqJ z?8po8Nwxt=lv$aS?F+KIqy;*KIEs=M&$;g+FTE7=fx68BJ^(L>Om{@ge7&6@Uyhqo zEuz~}Gu{v7Snu8X$bs9nozD__+&8B6u6lGiy=g>^A-Y+vGhd{57f*{%Q`7!^Zvgs% zETzL`AWa(cR6$T}j|By2e6f(kpnMtHQ!97bt!XvCk_N>(dY6(WOwNvqt!;!S#mFcrd@8^55e8(s2`T#i^YM%374BSV|ke_Ly z*mGQTd9_UMOg~B}R+7NT);^@O7le#Bnc%&#?O#t_*vF8LhiL#0%G^-T{vWNem&;K9SQo0Co*A%>gKY2mQ_0W$hNH zL}*=HGdAKYJ7;6oiD0tpXa(0{2|lnYwD;QX^<&6Kdr8Rl__ZmFUql&~<+X#TbAbLR zU#8>s3>Y9{-S{;3R%G*->!j;q`bhklMP1w^VR~n?B}uH4@j9sOBG75)Lh9hIt36mx z(fxUDXX$7_vJyb}Qt<_l4^g-cf2Dv>z5>W|hB3^mevhHaQvk`tH>=FuDLofq=vO6x z=u@IL;W4?K*&zRLu#_U0lWj=oHE~r5;w?{2{J(JCH+2jAP6R&)JFi|qaz5Beg~aV8 z=Wk9B`;f$A&b>$IYbH#6_|$fzX5Vz{#aDFVN)S$z@1tCL{^kD1M(kde&w{fD4%f_6ZX4C^iKVske~kYAsJxgsK3CNK9b80a^sJ;>e_Us{zeQ$k8e1f7!}Qg} zzo$d``I4Og!ZC#lAZgQ^uFv(<_zBBL-@-H(>70mb$>te3(8;N1MJ6UaH$vav>M+#* ze75uA7$#`Hi?mb7_=KL_Z_(aaENmXXk)A%=(|%l!GCB)CrqEF^-|3>1*McNwM$>ak zvFuL16F-hf5iIdN5F4rvu>oq?mWDp5zBQ&Gl-s)L?)J484{@Or*UwKg8YI|6=u;3p zurAGxybU5gJRTe;-!%vTepz$LM`Z!*@Q8AsjQiLvr55Q1fE;7Rno-zZ8Jp-h2YgoX zQ31%w?*Chw^dBbwMs+jJ^H<&T0ydKd7(UJ^n2e7SWlY&kHeWJGk#s zBaqb+jMKL|+RTskXM+PtoEvSbFhl11!RY5_B`@=!QWCa!b1vmZ1|^=PYsY>9&EGFt z|BtEoFvvNZV7f6d($Lj|NmM7)3EhY&GVb6M@;dLXY|kZ^bw_8tz1)g z?(U*5N9T;p4tie`0OS_#`2lX=d4S-j0&V_w?*+(54vz0}?)^DLGqNQ?)(iX${&CCt z#z8rC%i6~WAlR4SBsxyOuMz~GVj0NcLGx&Wher)MnH@vCvf?m*?<4_k*{gE5zMwg~qJ;gHnkDSZCB+v&7BZy( zQqCq=o;g9GJN2T3YaW;j3lrG*zL~+Vmx96OLz!zdRI{Rz5h(U$Y5}B_G*rg?k1(}{ zi)fUNE?%I(-^q_%rp8vqez;?eE2l_PGJ!tcDhOr$Bq8EdJdm0or0GzK1rEdI@P7DMR<8gO__eBT$dZwKJ z2eI!jliV4^T&0e;vtbbH>3j{afUo-+tHPkj>l9+LwSL$KD&z#u@D9Am(cXu$<@q6$ zKD?sSe!gePpiGjlYZcFH|-Jrge{oM9lqXc_5n1ZYmx^<@Ehn?*Zz&u{(Xt@``BhsOCE zt`8ENn<3L8LmhXFj0tmUf`&xOvP@Rv9MXx0N&>_qeRbbgHW&9T*u0o;hjigUq!7T25PdGi3;4${)FEKnn zgt^RP+x*?=>@+{1E|}by+z|v%C%BHK;CD0G4+J+Nc(#=8Z*ix62ncp@=_u?>DY)QQ zNFTWGB0d@exnY#B+Z5!cAb75jXD<>L@Dn%R1v+!0@7(|PAkGroa-g=JY6f(yk?#G# zcO#6(b)@^ODP?Eza9@{&c7#KI7+*7t%)-{3rMB<70D+5WqIHIr;YRZf6a==c-|d} zIOx*3SN;t4g(b$s@1bdr8Wi*#q=lsas_6Y0ON77sMLL?N6f*Cng#f}Y@`sfzwkc00 z0*D*1Y;XpHUaBy*d9+!W8j9O>H4 zOHi%L3I1brtPaxMO0X**ay&Skd!C8c{(=2}!MnPA)HlCS1D+9sh+Rmo=UtyizzHrG zCq0AGBkrOUJ$FXsJ!nb3I69 z9-T8hD?uJ5()&rPeEoDn=lhO%S?K-~$zXd!`OgV6z{J7X(&Bz^BcQFm4G*~Izj)~` z=dRuy^z&XD!zi7dX`9mo+bsk!$@AOGD`+5bnc37cl=d%9F2~*e#ctg*D=4I^iriPX zocgg{iEBG_pfrDIXtmro;l0+b?DCCjKL@AV3^?~$V+D|DhKbovbN@%KW&#L@SBUl# zZ3}0#mz4j!%sRkks&;Wk;G7NcCmkcV7{s$CO+q#ktg&RWxPQ@XeYOAF9Vi zZAAcfK#9LSO+7ux<4g?1j|9N_k-LEF5$n0a#y2Y+m4F=F|%5)t^~m= z{CG>gpAa2}Ed=$;rmPQ2@iKftm49pNINIdcE$mj`fhcnxJ#rB?*U|jw$o_Vgw0Fl_ z(Wt4dza(xcP*`5UF_{Dh+*>L4t57|`xd3T;DoM0+@7GIR|JELj%fjPxe+K4=u`o146Ec8Y)OHHWesE6bm`^NL7Qmk+ zar!g3f2d5Ky@h!Y0F#+0T2lEE=Iqs9B&49a;nO&QN;VBUo{ibwN9 z49w0bjflr6Z5PKi@znEG8k?VT32tw^EM#hSVDA$|8xU)+v43~e25ZzpH zw$vSe#?9ZmQrgQ76Z}J1pTpd~?w#a)xs*iJsCm(v`*}3%M-n|l(1XN9z;KWB@NB`b#)R|}vkL}MmrF~~6c3kgBLXL4VURMU!k;mJD3Em)zcH=VI zMB?wc>;Q|9%6I0p;We>TH~&V^sIjZa$NOL!%x0v#e@&yA2HLDFsPWS44z|fxOBFl7OMKw<7 zCol*WxwHF!RMf6(YqxE}4zAMgb_Bn7`{0>HZpttWU{}dm{H>5_ipo${_pVQJOtc<# z>v(`J+MXsl_mv@^fm?&~U-f-FA7pcH3^pXeJIN{FZ@Tx-2UK{4Y?*K_o)Ph^x^P}K z-Ub~2`Er;!ZJKa>;%tx?8J_hQt}O$$`R{vIC4EQLVR}Ji)bMvL*1j^3dn6G;_@f@{7$B@z*^f49DaVssN%UuOv z)-NrUzK_qgyd$F+-TMTXWEp+OGjYk}UAZIPk@KpQAGD1m2kAQQ|5M?#lWcd-^>+LC ziy?>5JCgcCeF|T&;0|!(cwFE>7_aLIM28XFoEP~fQD?-K>qp<_HN?5(VFa-?^}@T( zWPyju*K50Z-XQUa6N~R5ki_l2uL~BCs1uaEk3fr)L2gD6ofz*t%I%G2405_5b_~mW zC;tegoD~F#4|o?ChRkh1q8e2zXix*2rf)oEPQe)WVkWu3~()tFHX-Ny5UMbue>&m$`Zo6vf5Yy~sH+9LZ&BJLF5 zTMmoiw^<-)onW8#uDmecC)oLCtfO_hZJtY;K8zU8sX{xBjPALBFCn-Fk_T=|} zob2P$owC!e7Zao!eZiu=Tju_%X2^|~;KP>QMgKYR1-E7xA&m8-1kZ2C;{~VO<<7As z=%1J8;W5Fd2yH&!?c<+}aa=YC!!}I&2A1po$(nR`YK0FcvOGSN>#u8QYwr+b?Pm$s zmHjQ>&HW8kiNQ{%>An{--*yaklDDa+@RBsxXV?E5vE z(O#_Oc^-+)_W;)n`ix^m5kS%&mu2+g)=bJQh8Nv55p#bjB+4%O>z`d0!K^JQ?)a>m z%kpEryj zAP7!2%o!IRluHOcqXjeg6C}7&Mgp=C1O)B0e~))3-b|U`UVFlYcl4mWKoYe>PaK|| zxhWfjpIh#VHcR@xzn8A9>rkHG`x3-+X_>|ZJF*KBn$E2)U%#EzTE+?G%SSX)1;yQ+ zjfkwuKRWw0|JfvSb7loMMY=9|`&U&+%a<2dM?O7!0mK#^LU%lx^ThCicBwYF%WZ7# zC$B+jvWGSIGl1P|lVE($Vp`$L*>!H8*IbHl4wTGSHp$91`3qV7Y%^Ee>+N}$_((MS z8tq|;=>)*}KA!kkzDDo}kSqgnnw$0`lGrBYV)~=@{yUm6+c?&jXczgqp^*Lz>6Kcm9^QFw&ud2~P(k z6F}Zbz`T8@q`jm9N|zVMOzgMR-QgRH)V3`d>5!cV($xtG7v~4FUd%Zl8=KowK7Mp) z_LuvvT%o)(-p9EX?d`Q=k6I*}G9T#Ys|zgiEgHcCc(>UUMxxCa;oSX5d&o*}#pS&~ zFrk4ARlL5JcdD`m)CIwF2u}5dfO)>q7VNB>;#zpxE>YMgUL)o?s9GL$tx>=ffCzL9 zy@|mmT9DWwk{-1+=2`z}&5n)>-SdS8ZX5WYJYW`@Yy}acFeDz=kQ38xT!;|C?~&lQ z{`G7|$4=qQbah7U#GXYE+}fq{Dduv%kNQUJCY;x`WF&u$^fiox8c%5RuEwsxj;c@A z#ZH~$3SXm=1`FgyUK<3|!$Xs;bCXi6wNnjwb}BW#io-H1Yknff`dy0BzmL~Y)Gi(X zqD|5IJ_p376-biW*RUuCff8+YzKIR;8^9*zK$mSro9_clPd&;DB#6swc3c`L*DE8^ z{z0&pb3MGY7M6B8#%@zfD zs6$>n32!%;vz`BYREDV)!4Xcp2^UKHVS?a#{*JbG?w;xXuZVUuUJ}E&M=|tbzNQQ# zA`z#{*XM#?faGTJ0)gY1zo{eOT;bjmV&~i%vnKmx^<`n&5nFrx1hJb2Fa_h-t`PHC z2Y7({>%j#6wT*kRpEoB1$m!cf!TxQv-d$o%?sm<5v#E{t{%sjD+xJNECw3{{_5S;c z%hVG0Dc29%=hvW#6=Er4o=;m8T*juWo8V#a0VUQgEfcIpDPQ_aau_h~9lm#8R*RB_ zU30OHYlJ>EE3b*qd&^-l8)}zs3pHPYXtjJW9*h7C*)A7)Y?EM~4vt8>Fu{Bv780*V z2oRgvw`qA4vQ9s6q%8w93cOS-%j7K1BMCP0ukR+<#ZU*Y76KWvA&G&`7%F}gU~ggx zSq0>QKGR=SD(e}7;A_tHNdl8%h+T8A*q4@W`Yt4~rCa_H{`2li`^ESdx4O@c)W&;Q zMcm;DIS#DpETyav1Mcn!S~2QuC!7x?cej~aosH&Lrn)`@NmSRDIgM83tXvNA%@o4O z-sH|n0(-s`lcpNUfzfdcuA_{W^>xN;`Ng{a?4i{0Mw~Vz72H#?kQ;B zJGsv(a|rZUoepGvsr!IL4!{$o$K>Wy_x8oFbH{kw*9w0eu9(4mmAs5d=h13RC%D#= z^R)xXUxMr1nPv{n%+!`#cmI$KK9W(ULZM@z4jCkfc)ywOf$i-H4ts%XQP75X`Br-4 zQib3E5`BYc!#q69O!O0XLS-bgk16g2DKWGd0KhUH;EjX5o%>EpW!?_vhYBRE_ z;rRlOfDIXq+9w?&Jpneuh~uXkHUv;L@CnliW?CemofFml6sTPbAC6hO_KHR5 za$vK6$`kklU7|JJNleSWA;C*Bi~IG9iGE6~CZb6SrumKX;}HtAaJX*uHN7fN)Hyzx zrvNe~$3eTHG$zCJpk zMB&_sId&{aB8+^*t=;pDNbnKjEZs-HmvY@F`orxqNpVq#yK0`-1RYJ4ZNNwlAXtr^ z2uTxSdn{nI22I_uBpj0z9_Bcmt9kZy%UkOHkBXuJxAGB#hzrT*9G?ym=39hpeMeVT z8sr@x?d1)^`OB8`@LiATKgr4WY7j}CcWQ(U!<@RoaQ}QMHp&Oq@5b5|eI8-+ zU3(zv9r(p?e^mup|7B2v6-Dy3INpzCv{8a@&N;=U&lamEGk*OV0(Bcb@7FJdcC5xQ zygs29SE%-WUdRqde|_G@Ai?4O^$w_v0=f_+ySvCzngywe3OukNVI2qRY1}-DVHP53 zPZa8}DcLbcIN`sd)Y+0+umzqNAVUG*OZ@S(24fXw8Cw#A}W0J1leT+D&N7?i?7tWhG|2rx)n935KM|?iS7!w!g z`hg_cDc1)&@fM|f4?3n!yPIkMg^pQk4PrAAPt)iit=$piM56#M9-eoJb_!Q2@cTsJ5C(-KvSgF}(%&1nmZP12X;xj{FJ;C&W-9B+K)`Mg}4kSXh4 zq<-^9c|)f{Fw-xj%XbIJ$Kp``CI!Ar>AyS2rOsO~mXThIW1QI!5&)7kKCWm0<%X%oplKkO~VXE(spvsvKH%r&Mo1DS%9>JrPyj_Inza~OdaqjJ=xmQyt z|FBrPb%JY#rrf`lGT=jG+s<|oUUn7*po@HabU*F4ioo?*aPGx3+8T5m@#*-STnLi4 z+c5G?c^K7u+ec~)qRVTn?Pn5mFUbdl^|U@IX|yK*_@V1b5!D}6tAS;-a)|eW_<5TP z9`J^gW)fK+u zC?R2XaT36d&ZRDZEU7fjSzV6x)R%;7XRETLY_6eojx$8WjxT#$L46-szyk5N7fo98 ztXJI5(%ZU^iJf1`&2%GipB?oPd`P zFO{ZrHbI{EP1ouY9Ln!N@_hu3?Vo|Tijj=H*0*7(+P%K?V#Tn}cg--9Z3^~IS67ST^B%;rtL^uHx12T{tL31bPgAYvLvRnM^X8ph}E5?_MK6{I2=IP-rXsGen5w%;E#+(Uy6P)hsa1je2*u@ z2_Ly3A8x)?5Bc@m9qCD0PY>7t-}Xa zz8)d%&U$8H3vf){;sh3R)b+hmy$73v{@lss{hzJ)msqW7W3>0zw{7QiQG@!XMSb7r z)AzOp4QayTy(Htq_9e@(u3yMJQ#Q1M`&*YZlm16spZk_$r27&D>EUZ?I|r_QPUwXS zAgiAP{GUas=LnBc66o3{%Gnt`%;hNzpv2t%Vn1d&e+Tck%xKzkhh6zUFtW|5#%dGg z-is_qMQw_{U7dotgO&!1(mU%~{ zXyde`?OMB{f4A!pzdCd}OZ)CGs}TL@uNmuGS0ex#Z(}3&*gU&FN5$uQq7o#aGz5^W z8@kNjiTu*AfY*pF>DXU3zKml|Z!;+$Zs$)8HT69hgu8)teqYu*y%yDJE z?Uwz1q_B6b6Q5#ZCP%E{jxr;!5j4{rZ-XRe$oHo(8%-F%R!FLG+BEX{17HAo3lLwr zbT~hp_H@How5Nk;1%SBJTTi}rqJqQm5fOLc)sGE77u(y3=;@Wwod>z;R{22>2m9tU zB2zEHEOSq8;imsFWG=aPm?{25VCI|1T8H%Jy) zaQ=hACnK+85o5nMI?#{kwdn!jT#oy2w>JLAJHq+pX8Nt~{#Q%do~4P>zgU5p#mjRP zB0NMlR=3Y{N(l-z{#tA42csTWF)yL%t=KfLvQhvk9s^8+9VQjW$u}$gQ%XtzX^=#P z{fA|`;py5^w=jXtD1cCAxFqG*6>meY~CS1M@(f$=xL( zKOmx?bAB$hK1o5|C9zsO0Q}TzR|nBy{0x2iPgN%WPP6t3ByJ{KfNUT#(;J#mve+>= z9|>{>BI@y2W$_LaL1SH`a5UgDCe7o80dBeSlZ?q=G`gdQG$a4zl+cZ@i4#q zP^=6dNM5QDNLJY)RMk+*TR@QbP6;}=jUOn`R1N@ct`U~Jm`ieOl-I0%M|ir@uLJez zP6Gqs6(D#XiG$@fw$}N;{SY~S8xma47h10q`Vg2Eegl#hx_NqJ^v+)rE~k@LOW7jk z9dA_F_v+GozD@UAFvPqhzi;C}hBrSd6fbe0PJpal{_SEv`?=LR%X&u^UdF^q{#87V zW(jFPlA3IlTKd#S2NL`}b2@cVcFOanQ*3)NN}E2f_U&x5BeT$c9Bunq-t$x1^+tj9 zbWdPQd3m(&kM{mh5(hEbX7>h?s2#e$Nz@1ZVETdHo~P{pF*7nQ$=fj>p)Z7w@&7^y zMV{FezY)x(E^!dQJZAQ1FmU{1YlG>~S;igt$soZ?wT!wKEbxX%ZQPDLT+t+inEiV0 z+Hr;11d8~QE0=@!`ONd@#EBYT5YI1)$2-@zfy4rh1N{-P!VH=+tZk_s5ibQtYoEm- ze8riwbxIPqs>QshBz@%`o<#tYB}eJr`$n*I-{L;&xa~Z zv(utYoFd+}hB;~l`uY|jQ2Q)-nJj8gS)uu$Ir5_jeiWT0FyN8rsVY z@KX9d9~>?+<@*QbF_=Jfp|3IVk;Yst3;)vzBnv`je0;>wxcT+pM=Mjh#th2-#t`JM zH9NdIhS&Wvz!EwN3+^VNa=*0l)+2NFxuq*hRD4=Nf|ieMS`meW`r{b z8Tbr|1dQ10&P>%Gj!Hf*d?}oMTc0_6AyWY)uW{0)KT&*#H&rxXs1nNOz4N>$yMAZ^ z64EScd@|MioTAoM-DBG8b1q1tH}7_Vt9;Zy)hD5j`VO{rOqjguG2k-eCdu zv4prj!CQznH12$hU;;oiJSyK%--Gq7=~z!K_e5F=fAalS<~nXv%G<{h>T`;F{*06U zGlG{@Fq0(W!qRiRza?UPmsDyFxFBJk?X%PhwyKac+q}F4kn%>s%7oz;5N*Wt8-kfI zc;z90tmCH8-+ zSi*g_0!UsOiY!fqJ_0inq)N@nJeID?V!jizF@^JXx{S|9CKo6iPu+<6G#`qr1Vi;h z7+LP|%#_g=cLz5i*b5Bp<`~Ow!OY&Xv&4Q2TDTTe z)Q+ljoG^R3eLRccD+Gye2p%bwcb&4^&u>BEOlc=tb=2fFfwp5ukjn^y?`pIkim<{} zTDpsQeh2kV;5R$|BPM%!G5zn5&ASGK(6qJ*)$R9x0SE>G9Cz`wO8e+FFDsXWJyqyl z*3b%6^*v4E-UeWYxOpG3Tdg|hr)R2v%>CQcrBEvh?nD6Gs2mZMOhQ5p8>Y@C%|YeU zw<{_DQ%c-hesvEi9XecUIaWU;Mw)C~?tNRvA_yR2q~1~#K=N>kuP_2gPGA68TYo?+JX9|KPS?&SlL=ycv#@^3^t~lqZ!<&smf>~|r3~Y1Y{xbFcCF>+A0(7> zy(j>T49DL95CphnZOuo2;~@XL%CqfA)-N6>bBKz0VFm^4=nynIg)tRp+_`en8u*hjejA;d&q%fP{waM8#(%|Mg? z9IX<;UqFI0d6(z=u?~qQavNR%Nvt3ME_K^C&uiyJ244^t`Aro@>V&itlL(H`nn^j& zkC)R6u(sSp5fXS;q!wlX!^m1DKM?7ktw~Ia`4%1-0x&S9t!1}nt;&#@+zcdmZGqqW zlQiS}lrjDD844JwDGPmB001BWNklL#V?OUJC{82>A> z5c9sQsV%f05lD#u$lpL5!JPZlxzY(eo=E>>ssUk3L;CwzR7PCA|7OJEc}X5SH#|mi zk}GPz6%z(NhvJ!FB}_kvh4pu4WQ69cjpZ(7jDU=DEChqm^7a1Nq0M=}+hXX${>kXg z8LnnP_nhzeJ}7&}eE__j;${iooy9D0y}HGRKLy)60q`1;JOadzbeuT_lQ$naIL5@t zJD-Rk&WMi4hK081Rx-E0(%N?4t&0+ThkG06UElIyaIdOl@?{2E4$^mfshN(Q zngP$p+bhSpRGrW(Gz{;Y6q9o!=0e}ZJLM-8AGX)oa?aQEE{VW3i#gMMh2i;z*}pHL zdIlwr3-h>;ym^e1J3mzJ-{`2OStr=ZZ5qcYFo@KBvo{t47-^^df@aK~vt>vGI9p<| z1Um~>^_{>y?GW~+eh1v-cYtU7h~%oN$eoH$M6BTQolcn9K2aHZfoL&_KMO8LU-rQ8 zy(*@(7bOz79+iZnJ`!zTrQ`6A7&zaM0HK)psX~>Qryt{mkYB~Q`5`5rA}=sqZz2dX zSTJLAU&OOn{`pibutMzw^)yM%P-b;Veb|{HUoczqFHS24Q~g1H0?Z3)T}x7z^^{@V zdX)kkvWvm# z9(*BR!H>V>;?rcC?(zZyQvx6!B00GLpBpZ87&8aCR(|#`qiuS513|}}iPge*=vRwc zpVkhH?=#9+w{`2BW?HmG#){YYP}5#41wI}yoWBcZJ?x$i+Lix-{}5~^naZq3ehK1r z5~q^<5kzD6`8X1fh-vF-82O*ve+Mz=HIT%!(#KUwe~p<*^ZN3NhF&8;3BDNs2OH@6 zv&*cH0|_t9wlr!I&Q-KHf6^?Bm}7-hCHPa=jBJN^gfC(sSuean-{)P@o2Y4^ zQqvwMXcnd2-G1#5v9qyUlkWkKN&a29UoGMtIWRci4&;4Cru?DUegu9CHyg^Z*j*hX z)c=rRrUgctmPqa9FnzjZB)cg6-v^v8nXd?rxa<>XV8#YP97RTRCot0d%CF~VCw>K3 zD-4qgvY+etzAl}(EL;h49dIg0P6ELRzC$RnO3|?V8)C$XJ;RJKA5`YBYa&NkL(zyJ zC&n=L5oj!)xgsD7RlcD1KRfd!j?)VVUY z7A}gT_4>tOh9xvLgngDO`4;o>T@sDJ{soR_>u~zey_l9&~~f2c|DLm#tKEYH-(2B|0RE+1zHCF(+T0w5NUL@(#r93kC(;Qk=j zww*KWqMu(Qm`efRn*?zsxf8=X@u!1Gw#(jHj=Q37D`+c1NCH%Scfof>x}I3%G-nBShM$@7@#{I%oLtc>|Av-7um z%+o;pN+yA9PCjU^yCIVaB60pdLA___=i4!cd3c|2zJ>7Ybi4KGyCmPbPU5>ao5YD4 z0p#ui*86Sq{YLI+rpbfl;hT9bxOEcx9~<4qJy$0|gXg8r`mW$T~p@4LqV)M)q$`&^wcye&QfzDi| znQXhSV|VUx_{FX) zml>O3xnM~e6A?8^toz?ENPyh7VbS&6!5rS(TMhRGGbxsF9UWtjH~qP?K@$9X93fvX z3nO?r^$xL^ucr|JYel>V!yVuxa&P^vyUg6WekthS2qX(-lZ_z+%RusQftlwh;uDfv ziG7^FDt;vMS?>R{A@rh^%fX>S+xJoYHSU!BNnVljk91MV5Dz81mO`JZ1c@!2a%u{i zh1Z<(GikPMSIfRfNBg<)P{TSuE=M?9X!Plb)WBFcQwN%*i?wC@Y1?~a*ENwjmvPR! z+OP2z?}-=j{AW$tiOllduaTX(lQ;+dW8xr&w^##BbkW}LlIJ&m7D@Ere&xix{;!;w zW}@Y4ptU(GdB596JinN0j9_0OO|VMw=vb<1y3;jJGS?JWS7Bm1`Z+2Fu*@%jIY1#F>oE@@O2RY3LxDTAkvb zZ{kDj&P_%a&93^MYQL6{V0E|re+eE*;wt;G>;)&d#?HdMe-t#L8))3&cIe{zRj@aS z1|f#@ByZg2i}SS?`-3FDHESOFk%Z#_%(@_Vm(wi}Y4JD7Kh$<@Ob&O?n*{W{PUDji zbp-^@Tg>=^1Ko3-dd_QwEG<^H`+0r+7tNnvFC1?)?-lr;$+imc{sm{z-^qb+YTrhg>G+&iMc`C2>4`1AN83Lim?9X=7cSEL;N{Fg0I60gswQr@8asTqO_Y9Vc~5v+>}2r#eCl4}^nHk7UT&>pwl8r1 zxAWSzbtXF-_Vjv|BP`ydahBuiMVXfCP$JvDAEmvSY*EKCdO_$_$-)qTc%3eP1-?CRDv(YaqQ%+&hPt$7e}H;G|%K7QMf#N}MM9NfZ9bG+J@4t6{4 zYMn>=?R<>H=h6NQE_BNdBfKCaN<>b$?PyurMY!E`(SDtLnt!O3u(msv#ZJ&n(53Vj+8 z(?6n0#bXFpo&cvG+h6CGMJDb9Rt$wc=?Y2I9Xs~ z`B+$}dr1lS*PS4EBmuC4DFS%kXl5T*(FYsw@^0q|XO9|8s5}~;4_-yDkN-t$MW&0| zvvZX>{6&avZ+J96ojc86|Gi}qOAdgD8 zyL6_-xYah5d5b6{3Fc30DP{Ju95*o<@g#y`8u@&-X-+pG zSr-LqgrWoz({U$3@N&29L-pxenFKZ`fMXkpsX0i7P3Bl$n1K119+B3MroIl@TBu_V z;X8F-YrAF)5c{#n$UG9;IrqM{D_3GVU!aey6x8(>0dNaRU~;tuT*PxcP0HcU^Ex0O z^!hrQWNnb=h~>?R_B~(&eqk~_uy^ILeqYKGXKwrCR(2f=dM?$XWHl1bACaHkoFP4bs?^$)=P@?4In+Cw zvL9zT2_WOjXF~m5!C}ydHW>;6ca&WJyd8sIt%B%`E4aRP7i4oW_|U`*^|BitlK~IM~_0DAu8L<6Ot~W}*IRR^xk}a^2dhp4PGb45HM3Aj$qn~G_#{WUo82v5u zcV`FuGkE@qo0kop>m4XP1FH~p82Zzw-(~lm_T4xX#5V-M#_s(~-F)Ndpmy;%u%D*Q z!=lDzDt+Js8#5zfilY&sD(rNL$@g)P_LAWK{c#`)xR}JXyxT_>J5wtp8G|8W6p2f% zG#aLRK2jOuX^1ckOU3#0?L&(8mI%`k~NDn89`l|CR2Atsl8hm7i{ zf$1mpwmGYgy+CNh!^Sl2Y!-%3lDD%J!w5$CIZ5uCI8VXIF#OD=?WH*{BwaQ4_96I7 zq{_6WX>K)h?za%0f04yUlH=lIity#a>sg2XuJEx0u|VCCIZ2>X^&ID1;AG!~vL;1@ zsWqBi0R*RL>938O@g^e7epZk;%sn4WR`Ko+k@N62f^S)CS)QO8yW=*phmIBvL#8`> z(}o!zt7ZH)XV_0BP8it;VR+tk=?HCJgx?F8P6MKEdrzYY)m7B^aj4M880QKw53+6q zk{AyJ5238>352ZvX8QCb@ew60TnKdrnp+2Ua*U@t4TsW=~@_c0||89cMCJkze_Mv;n#h@&CnkSK&zEJW< zIFm#VBa=PGN6

&p4mxJQrhFpay+(u`!+oqA!V$>1bNmjaWpU1v+zRcv#!;m%>Dg zFsF50BwvX(0|PCRN&^wW?O`3toS@q1Yn;him#Ur(@0y@w=x5EsNU(;OGBqmQpqJdXTaEdM{=FOI=nl6Z-DjY6Hb z5)J8VzjXC?qwE7fbPKoZRPb<+tl`Et>F++PN^V34ajlU-%fKpNJ=puYY;Bfz`9QTAIg3x3kB^?dq;jUI}LMZ>E5jligS==kX-M!j5o&$-II{;E>{GY9ltxVCK=u8wTguUDlrDJ5Ups*rLwOq; z%3NQ`-_dJFJ0seWw5z>E6pdaK&W|Q|Jpu4Mki-%ve`7IyHObjt%ZMH#J9_^>u!A47 z<7M9mq7%rQT_*Yxg8K_&TMgui40diksAw3a4tr` z-c;j@5uVH4wdOf1mxI{PJm;=+WJgVToe6GcWv1mhXA&nVnv!P|%-07=oXcrSTi#ZY zybht2gZi~GW>{R`-V{w0LWl;5-U-mRP%^ycE;N%1D9DCL^E>ZK`W}1WSN`7Vb2k`Gb>eRQMuv@Pl#7o-y z5}ikhJ|;u?G)Q8aEPS+5^79IQE@_L}u`vUm1hWszQZ1?tF_CDb-kVP1esXOKCvOq; z%QrPTR1So`=_rKo15)H^ znX(_^y)Bt6eI9gG@2|(g^4pGA!v2L+@rL}{5zfwa+V-bnY9BS1djqZ7!MmdthBxHv z`Y9aG0pbltB70@-(BCuNLfbfz7Uf~GuY7NhSl^BIV^XXP=J_M#jA($eIeR zh?kW7zx(GWDdq3zZxU_8g%-?16N>fBNF2TV13Iv{YM#63`1P1f&LVwcLhrz44Ohoatf;#kY}jR?+XFa_hathAUY&g9|*OzKHV8QMZXNED&b_Sn6Y1P;DZX+5Jm zCNW3hX0u8GBp#TgIImx@&~+5`z213?I=< zMEm(zm=8aJBxZ-`aff1lMf~Q#LGMN>GVm~u7S&xpj6F#117atV(*gmRI6YFUag9a4 z!h+yh+P+`w$VcQn5c`ls4{q!`Ulmw zlX5Z4!45-0$jOvoo26$;%o^K`2Ca5C)pzo-g7Uwa_qyb1w|_Eexi50*xUw91jTgiB zPP56kOTO*8$};WgIfozUTIjdtGh$-0Hf~x${W^#bljo^fUTwYJ{Or>L1Q097XIqBO zHeI7~nlQEkQ%pL}%})c;j2Q|bMbJQ;5VBc5r{MN;4v2N=xZoB;uv5~n)GTOoEXU;) zf2Z~#>-zslx`1+_`F&oH0+EJWNzeWi+f$dm6E*QI^XNp6!J`v z8!~JL<FxJS1rX`z%uMLonHi3YiLu8z#ThT^gWVj@Z01W#tuyR! z>vD;ycI|MrLPXPW878RRdl)hi`OV+W9jUbADt-IzbRDmsOg6Xn0SP`#aESK#1|eU9 zGYH%-lQxl3Pl+_YTDjaYt1T$_;>+e|$LZeB zLEgOhD6@6Fi`MK;4%XU@=59`kq zTv~}dmF!*bR_OzhjR2C=bSq_g{+F;lgNNN6xb(^lZNsjK@f<+_SV zfV|Gw{>>A9Oa@z~kAfNXv}`K8vy7xvo9~38htG3&qHovqalFh>@!}AwA6vkOpbg4= zhqyYPnUd*4U;qFh07*naR1_KEE-np@rM#;gVwiUT@h90u=m+m|=7pbb2Ul4Fkagrb zR|xs4tMqIyw3$Z`aG-ge>n)t}bWxZ2I=LH&`^d48^Lm_?X*4nKZ-V4C=5)j+v6=&K zK18NtL%nvQm2C2OhZcH$ilEK7I=Ej;5abpcOtFNz?xnen3ly3Ta<5O&ZL*||Z?KzF z)?8+_p|`ID0uf5{vB}TPi35YaEb<2AzvXDY8aBm6`@;IqJ1RDVdJyGrT!lV(PX2YA zTVw%_-)r8X*@*;@Dk#q%+ZVOEvT8YZ=fV`3jwUL95x+mniZBnKK^fje8RlRl!u4H> z_%@Vb6Nj}@e~Z+cR{|@}L)kuCVjRjqbTO3I1lXA1+d$b{0Ls1%p8YK*d>sI=1Ij@3 z7V@`L`uMN=V2)A`fB^(JH@K%{EnB5DZn)d0vVKN-Ec9r0o!oz7LU6HyW*RRgI7Q6Z z69CXyNXEjU1 zcN5ij>a1SYBN&3N&i^vEJu9b`;j|hAjwev|1OVV+mzF5|253Q)og{SW3-9bTlzm6w z)H3`}oeUEw%(v5k;|L6J8_(T=)12o|g1~-mJC*}gYCMe=%ga!9rJM92;NrEMXLH>m zcft3#p$5^wy}xofuqy~+mS4`Q+u_fHsx=HtK-r?uy_aebt6mJ|PHhfAcimD@cAU^Z zVbGVAp=u3)Xo9lMxtt1n;fE)b<^|@gM)LiY>p4k-z@`c z13QTC*dqmeZ!rs?OYpLL!U=XXtgB@Wod1ErbG9r3e}L-gGrwv6j=w_Pc)XxgeqA`x z)5*Sl9IF)BUB2Eg4XeQs!D;hkS#L&Ryv_4v@;9zLe)}UM{;X`Y9l3WbppM(iic6fb zO*QXOi{w+RWHca&C9pxs%jcH%JM_QXp*h+1XEUbke*x*aDhCv-wC(L2)+98taXJ^T zzYWrVT&Ss5-svNdokF|!3LVB%aq1LfAl#L3r{j4#(2iUjn|8L=Z0)~TWESE*=lm=B zyY~k;zL+Fh8|$m0sn3T@)O_*-khg$5%xr(pYb+yPd*#j+92glN zNt&o0S?)03#I7d$8?*#re~|{{HK4N{Jc`7|j`_+h;Q5}J&^;vB*wH$5CXeyT-iCT} zra?}=St7dERZ4sBC-J;#hkAvX4(i-Ik5Y^b;#~Rp@r*Z1QZ!4f25Zfdqm>vFi`eIt zcLeML3Ibp!3cg%1njFzwO^1fX?GYKIk!MHX>}!sRHd+kV1a_J(?Xxl+HjOCn5$&4s z8^H_RdJ;rT|37TQ3z2_TCe#XRYsB-}k;>25znJkwi`2JA7_= zr|g>vIIBE>dD=0igk_g`ry{qYI&$Z#zIE)yY0t&$!fDL~3x}nOb_E8WJ9D`4As^90btz)|M;d7}Mycrt$C zD=+UJo~zY7=psUlX2wNvOSZ`pY-x)&$rv-sMz4jLpkjjgpmZ0uM+E3*bAA2nI39W8 zd$`xGkGV6Bily-+Ch}xfI-b(d)EK85Po(7CmsF}=&-Ke6pV9XqA&!Vg+swEev44gV zqG2@~7Bl64zbA&%|FIG`t}^0W{X3<8TU0QIQQ>^Ie@Tk*Yn;4xisU`I#IwC?s7P#F z{F#^P7r${*3t&sUm{a-3+OYaiI<}q)Fd*z#V+%;NFbLHyPjf32&4mFe`dqo~%UwAv zSbrou_g%4eITJ(4Y5z}A1@Tlk#{YeSAs6!h_pQ>zw@zdsTiZ)_k;>C|qgJ!GJ0V75 zFMR9OcWAz}d*=*{n1gl_ogHHu+t5`cesb;~m9V4!s>9IKJ}B4E0@TJ)7TP#@M)>C$ zZq7$ylCV*{&6*m;6$tb$;vWC{Tf~Lp0VXIi-JNTl1^N-t`=I4){v8h`EhbO~#1Q)M(;gXmikWHsIg;ZaSO#LP!U}BzKHhAhqtnw-z8v zW^g>HYjVH$_nD_Uax-Fa)7(4~!Mgkyu}CyE3VnpZ1#BEn`+dO{QTDBS^IJx~Lg;*3 z|E;o>e|ksC^l;Ly|CC67%pWKq2ZjCm)7Y^}MPyGp`uP^awdgGn$J_rWS65(oJY46W zsxiM|iC^d$Y0F!yCsgf{asAoibvUF{y_4FV6h<|Rvr0Q|Yfj;r+HJ1Qn^BJr<<{|% z>7ezxP+InwS}Y)SsDOB`632_FLjmz(5r7)dIf?phPeF`1%Von`C67Z7Xe8c4B zDUOTzg76W3@Hf7+p!Fydm93)}S=|>9^-w-m5jFsALu1B#(9{@2Lf^m_4i^dwn4duR z*iQSJj2FpPp(Vp0*%&arr_hC7J8bMTt)V5+`6+?(%UM^xaJDt+!`eiSk{k$k`~WpNC{!)R?^(GdWHe_5>Gkz zu1CCl=DA_HEN@v>mn7vQ%@s=$tQ`E_+b0P4n6XZIPoT)|Yd(PN?d1rH^s?XGGdC5I zpZ%pGa*IQYls5;JJK8329rYFJor?=>3yM+x^D~z(Z}qPa0et;t4qUiHD`3kyiD_IZ z=`$@TAl2G|&r=@uuYZ@SD$($^hy~>MxU1U$VW?e03RGk1@;ylT?YMAtBHoAm>tByw zpQ+#^I$WR)0KHz`yZMB>i`}E_cYMJLCsuSHdO2SA7kxo$jf&@?GyxFJRvH7cIG{HI z7mC4de2Q^4oflH$Ab9aHqUjHC+_H8TaDITjSi-x%XVR|vCTK0^{9>>*0{!gcYyx5U z=5)biIUHr{TeQ0^&-@_P3YFCt+#Yntj8POH5NM6?b&>?^u}*-wN zcN~&3`9#jQNn6ktuI*$yv>KE7Cr%op3Ap1El&ql5N9IcVy3kJfp7D0POeQ#(2M~2# zuFgmjbS}&-{23v9L;Kud|DN#(O)`190TSm$h{KV@V*=hvHaj;p3YIqRTdqL+ypf6G zW$rG{K)&!PiJzQ&2VueB76ZVWM!9&wv-os1!Sp1-K5-%XEZ;J;he>mFBS3%T;!U0+ z6u$-i3U3JYv%@O=N24v5^pQi8&mq>!8{a*eS#aJ~yojX~d@ApCelfo1NWL@S6#Y)~{dNZCqB zrS3<~a9mS`-Q|A@)FUglO0AE{HQGskFH-+OtwH$bwCO_oRHlG5*dNvTe6dQt`xY6K z{9N>Wwel(V{zb+}EF(3H%U7OC^J}jAlj<4ytRgffjefS0_RQ1YMccC){Va*IrG^ue zAK64`@_tRc#h)`vUg`|eB!lyL58uY9G|4pQo+-Btisi8}1QNIzIU$v#zdl6~v zoLL+ubY-MGsJj~UfOBF#so`7a{}`zu=$jEpn@96I8l8DjgHDc|XQ0&3PvTCgVYl$L zQ;^P>72W@PgLZ6?Xp*M&$OXwv@OKB4|Xq3Jd zT0jlboT%xW;J!BP*HeR@7g|CMvK+j8D;f+HwfC7B>CXm9ZIGr!DsljZ|M@z5eh;ME z8>Cy2_G*YxC%0`c%`UWqq@fIz^pDhVKx$vP&wYT@xuKsLRytpLvmtRDWPLg#y+1j* zE!%7)>4mq|pcO)SCZ(O0SK4z;jZ&NAq$w9T|Hn%WD>`!$(#VYWb~U7PByHIsiLO$^ z|Ef1>u(H%JHgsw>pZ`7A3$38~ZvPs7-e^kUFAd4l!lc<|2I!cVo+T9kgW2thNFD&mw)Yy21$PyO#p~+D`m|3T~`MqwGkL&EYPTsYj z_Hzvr+Ev|zR`<)%rhQ*OK1N9J{Wyp-($pw@-`JqejSZU8I7&^8(!4e%iK~1_(v-&M zO>B+EkAvqY&!;Jk^M%s;!;8x?DV$GJqttX|gPI0A=Wn#XcL@|HS71jk=~p#qs2Ze( z9#X>rYLeHVKg7mN+b-yA8(XDIgVdmb(u^{Wb19!ao%Y|@`Td~|QrmVD)waE~b2~|V z?3Z!MQ&NLg@caHBo2UC(P6$10%Q`%_0@SvBSovt%UYfF0aQzMuRz4=9WxZlg!W%|L z`H-rsd`L0nLy~?|gBsLEZPgGcAKN4}dWP~Lr6?bB+jQkpJw=7~8> z%nMYEJ4k14;yC4xIG^{ox^6-S=%i-O(WU%?Ey7 z>EJ>-1!*r}=%?cCw|!=82tTc5g6mhtV$=Zph_(XsY53ZT_%Vt+|NaNGv|*fs1nA`$!$hPiV=h%B88nd6&1Y;JxO<)`|g1I)>MN!0~bA zY201JCsY@<{D5oMd@u5<&B^FM8|QZoCvUDm5*vz`qA@WVza$NV@>bgTSgz{j%?n=i zSljjyh-b>r(*mE*%8dIk2@x>p48hRVV!{IZ^uhd+@a&-xQ1FcA`>-SisA~nco8JeK zgHb4L&N+cp1|six+DU&u`@2zwd@BhTkjPS`^$R7*p8^>&*8@VN-*z98KbA|nWE#qB#T7WvI zDhNjLm>6o4z1_Gl@5v`1@Xu{4(D5dg#{&_iYZRFQ3Pa=WSoz?4MZoq!|E`^T4*0o- z^Zr={*4yvvkWuKvIuN9JdpeF_`cWUpZ%OYcgQ~B9FsXuqZkQu5+QzN30~l4KbO&c# z+pq=ddV1|A-Z%Um`15lr6VE5N&(ZEZ1D!>ANR^bBdFlk5=fnoFf~rejySh6$G)CEg zmMDJ3H^67JZ zVRs?>+zsJ$7DqIN#?XV#?@{sC7(8sQon}GR@8x5X@{SD=H%DT4xN}RIz`cJ;yZX_o z&$8DKPoVeZeqOeDvS8Zg!F+ML>QKE`aPFPUN&DMW5PP7Qykeg_Hq#=KcCD#VXgdl6 z(n}q~BP0nUG6eoJ?X@FND8hY_<2x_?e~QrL9u+4zu$E?zsKM`-8G_&MR9R7YtX7H# z*Vky5zh8ME^=44|mdInh|92!_Oohja&8*DwRjt}?VXpZ3A&1Trfm4<^!R76}? zzK~Vs>cEvUOMxq*;ECTOeX?KX{a+WHyN-#D2QG{J&uIlFUj*m}v&zS831jea|M&kA zp7kt|7iXl4rnEkx&a$ah`xrL0$F(@589a3~xf$}fysp}Ho9ua|gaShQ#Pc&!Jcv(i z8vEy(rXLC%$M}L}d#81CS?dF*?#Gv%PLC>2Tt#^5y#RIZ#K!A?Tm6Lj4g%fn^jCxV z&WQTEcF737fzZ&|w%ML!jgcKf|9h6`o0}rnmyVXlVmAEr{}V}L0)=*sQC}DkId_+d z%8j}vx>NbWX_vG*Z<|83dIgJwsD&?u_1)_~1;00l>`c-C>v_L-LkD4{>=jdY)p61l~(XatDc zlXod4baJwlsjE*3{F-Amh;K45OG1B4${4pxV3d-xGw!i*QJ!*K)Vc`Y?i(S(x(>I)k4bGSV)I>KX1m3$0oet<6 zbM7-hBhAj|;)FL2_5xNC=R3l%UnbA$@CacSJqhu5=>PJ#%4r;j}cffQ|Z_n%aR$zJTE!L z7qQKUQ|Ty#?C1@AALF9H^0K;zygXuErI;vx$>VqtIoVfBAaZ}_|dWo$W(LC zq4Yh=wcv}u{LQDBT~ocZVmtN|ink%!sQ5D{C7c@~(7t8YWu1%(`uBtdb)kfF2URf1 zhuU(0E1+#%^4YygQ_lp%T{ge<654A34!GZoB+fBtS3s6Q?w}MQwG*HNf_#@3Xa%$z zzM$&~vL z657ZLno7s)`2T-}S&dODa0|?G z%{fkJdFT2TUi;rlQ==FrK(oV^afQdLQzrx(YTV(swD$`TySk^ zXTImHY<(ME4FQ(@n$bgG)~coTd5S`{Mh->m;4BMu_hxE~l~UZcrlP3tJ&M%j)O`0| zT2G8%|4dgvGLNN0(Rv?18#Qm|p<0?MFRtkMfr$~RpPjB4N^I}%dM{m3I^PRKn2vSf zBx_aMYK^zy@$<(d_46UkKUrNLv@QCiq&YXJQ{1JKo4tBCG|&HyVykw7nF|PD2})>G zu#ZKYp3Axaq2#H#`iyf!$dA9#z(Y*BZ&fzeCbiEmUc0n)uHTjJ zVkZeL6S@9plC^lpcp0{f;4~a7t)F*~a9XD%jpI4O_gv~RnLVCf=B7qNkC~*1l%rgr z`BU%PrA7kHOhwW?*&FXi)qXDOT0wms(tuLO+tjxLlXhHIrSZV8@pCKtl;(3+zwAp_ zZya+;@n=R)MT%2d$BDJ6|Bvx@oo)e1Iu4x%2jDEV0GZLHz`eUCo}a(Wa&6{4_rA;Q zbCT~5UJfC_4+1^s>_%TvaGcO7wln1Jeoo4$>-D4vMVWPRSj6nkuurMFR2Hc7P5<|4 z?z=EkzWSbk0T3r$>thf&p>vBAeBXS*%Tg&P*L|Isa?llnb4d~c&rWFD8AAQ^I8BXW zDSzQT!oT)mM46aR3Gp}9HRr}gU2$Bu7smRGK6J`EroKn~h-SCXogcU}p^w?tbHCy# zkX1_lW!TED4Q=Y&PETK1$`)u>^PaObw>}*;=OLWkeEk>x^sX7qiywD_AO?&_4ZM2< zH?d>nKf1@@(axl>+eJvA?*iJ21pG$FxHU)yzp`1PYwQV`WAyf@CCB;A>GpfEVr*E2 zEFsbIK3!@oy;L%dr<3NOt0HZ4eRbB)Rg=cwye+pjf08x-PB!H_&wq!~Hvk6|na4kk zZpOS0eac;r`#b53t3ywc4Vxj4Ckne;PA$hbdDqzn*F$2*@|C}@Yi$APU!@MC!hkRi zC^F4W=E_#6RG>a(w8cGD$~zk**I4cLOkgs(Ps9Vdl}sldbZ`l(v_L04b5QZ5oi`9@vlhvUhx*?m#Z^Y z0^vPO>)TUCIrN3R71M>gtD+!b+Oja|E?~j#`AVVlYYG0g&y5j5kUt5rLn?^eJ7zZV z7~=}d&OjTd43`n=`_%+X3Zqc+Jz@sm6>cRrxFEkdY-W*qZ3)^8#G!#p7@wfQupvV1 z6t*ld46%8_xZ4R~1sXO>7mPW`e)md$pU%#(EPV#zv%=$LtV&SV?iR6-%w2kJb6qmL zSUFsnu1FXKXHDPjFU>71P=+qEV|+rc_n~N;99d*u{ejfY6iLvvjQ4n7LdtK;ueI62 z?{ArGS=ox)I?c@>)i1rQ!--R`|5@wuv1PN=`?+ahc1Io*md^!_FN?UyIp1(7tuPxo~qq)GD zCYHwqRh+Du)&AbI0BC)J^ZPXO?M83q2Dg3&P|92hAm&pNgjG+_O%m+ZQzjM`ntkK@7N{hYgB zuJuKn&XGT9=cC-;WuI0*bIqX}Gtoh<}5PHRpA7ui0sPe(! zy9PAN;Mt-EO3b5GPjk}{jp*_%tfUpNit$){LG~7F2O!5%m6T__(Epbbtr>fknf5VZ zKx=3CJm(_AuIBs1G8Q&Y&s)BAKszN~J3S*`9}mJ{+de7GQoI&&Kl65!eI%YfnH8bMQ|_*hADh#L@$z{8ou1>JLfEv7j z!W{nZ*>X(GrQEO3uI07a;e^2AClb)725E;QrO#I7oh$SdlGqO+{#X3@og5d&w8<;t zauhGa02zbG{O=u`SbI!L>^)DVTY7tdEaD_xe_oo#72lm;V!Q)-brr9>%B6pW&~l`STWoi+J)Y$nj1`$H=D{F+xmU=fo70 zrvxaz(Xt_>aUgT&6=2!NXZf1T$2wUGRG!M0#`+24`FEi)=KS?7ynD~;@pDf&W%>yr zM%GY>j1Wr98C^5FwP^d?#dJBa8pn=V<9vf=2zofSrIn>zjC9i$2z`$%hMschW8cj; zkTz_|mwHfhvxUt|-)MaY7bt_vYmafG;Qo}nYT%l6TBUu(z~*i5Z|v`X6Whs6E?>Lw zE@*}MZx%`8gIsQ4KZIDGqQ{tw2-aDLpZ@q{;cgfT1qX}@et(d%GkrUm0%hp1u0l83 zIy{TuRD10ibM92HeilRbo7Z(Un2lRrch|G;v05M}Aj5@9)fif@-v3Fq6z_R1qL(KAg zS;*3AV@j}>DT9RQV-|2;PX%TF%{E0 zQQ6o#9W-C+^;Zf`7HD#=`_3+f=h?P}$rbWMRbCg)6KrhDwTb=SH!1Mo{n=^x!QOri zcD>nMFt4{zTnO#NjR^5eAtfd3g0*I%-+o)-!h9CM-|!@lpmQEeUiTCRA&L2X;d%;9 zjSdspTY!GI*Zx2ZgIR2uPqFuWf=|S-vfXKKFHk#-at|2o$A|bB z!%AiH`pQH>4=vIM_-%ELTVGcZ<{!iIgyctC4;%^_^GvOlu*<^q+8Fhx2V<6#1-VtGM;;p4``0h)kv`bYkjw)E1Of zK-^%FnF?{No=3F!{5m|+&KKu+U!JXiIjW+yU`X+2dL;%~ZLC>)zLJ+@<#Vqr3zoe1 z29zrvQ(0|#YBR3o|4f%>rcMmV%F}^R&2?N{6N=pVrnhamN5toxt&6n#29-^yjTMyp zqnz*T+_g&&b96FI53GaOF9NJYkyS$8Z&+X!;^DX%- zDq&!IyAbXLt&8|16yT9jPJT-VK?093@-fI#P5+1qNNDeUCqY=9Y(k{i`mT?Z5U^}H z5O;B&2pHUUfd)axh?`GSqfjr*j`x?K**rzy2}Ec6d!`_$Di4S8cGg926M@*nPx~Q( zSQPYTtnb>}@{TjaPflOhm`eNva$Hc^240Vpd2tf019ViF8kdR5c%iRKkNGbJr;-ht zMz8rUe*2}o2jh|74q@C!uWSW)pJZ#_F$s93R7N=G`kc{?vOZoNp7hV{>fH0N2#;L} zwWrL@n*#1jG-X_SzR(<;U8bW8*JHhuKK^++0K6n#P%qX&8!K%x%31Euern$Jnff+@=-M-+tpwTz52k-cL8DiPAI8H~Zx9P!+8e)#VQNK;2bM z^ZtDItyo|}`k}-)DHW8Aow8ji){0;dOuvorf4i|e+Q%$|JF$8qNWTq|=-><1Gl#F= zmOhb2g)Fp+?_xNFAn+O5BlgVwr0>4@Lfx^Hx1$_A(xTvQN)U&`tz$=_V~n!!cT%6d z1{`jcG0R?sM%lVPMt^}gKT&}4%RkVj+Xv7|=KOo0m%X5cJq@ObEyFH^>_!_bi2$#_ zt3kVXRLlQDphW|ra2JA|_B9B6-SZF~w2d%TF$ArW;7Y{>j$-&UybxfrVtsoNKGT;z z4BxY>A@(Z7YLzu6_D{iMWX1I;LVS?sn$S7_zBKUOV;wAY{8B&`ImowcPAa2)I#;j$@7doEf_|xU*^@`= zz}sW58r5xLow{IcR6m2_#1`1iK;PFi{mBLE)TSm;ULUDK8b4%Te^ZE6bEGpvAb@%2 zmMvD6DAUu`K0tG({1alROpf(w+w#YtODQYm=Rv=x=(uMUBbd@q)p625vdfBh9D?Ap z1R*YgEMi2+0`gMW^=9jAq0(az`&MCL_p1ntQ4CkZ1ehZ|?JJ1j9qiG=SHMp2U2gP_ zSuocW=mHbpqn&@><$=X{4-#YjG&PFR2osJ`c%paf6pAK0fRxmCc_S|d;(S;*~@lp4piRX!Se5+UgmmP(}_~5gE zYn>V$QeKi>mL`Uk2nT$Bid+7>^MT64X%7u49{UJCuw~eCcPvefhWkqrxBC72L2hLy zNNcoDvf;iPo@J0OGM28a`D5`g-opeglCqe-1*$W2C#7r*VpjQ^>rELo!QoV z?a16Se+6>E0%=y_S+mN#Xv+$r5k}D71?&G?E3gW&X!GW`Heu^yeYu#=Q~fm0pUN;G zrlHyvynjgb@?Nu+^(x>GT4~IXYm1nwd-}gU-uKAeNe7-t-BQ)pM4c?4U9)4osec%;p?C!Y7eynD7FBzz3?7NE}d-irX;k5(cD6R=F! zO~7Ld;|Cv4@jqc)p?DK9g$V+5PS_$46;@ft;4Bzx(^(MBfKM2}qJgm6Qy^BgR*#+e zw?Mq?UtbsFinb0m9o9B!&g_+SMn7gt(4Wt+fj~{f0PN=a>Y%p~bEOK~>j=c1*s1Xj&W+>spxS=$4n3 zTm>UH^M0#!clxKoxwuaq1H$h}>u;`ZChJ7MR)kr7qiSg_8fo`i%8-%JE>njB((K1| z>5V-_@x`v9LDSj!zeVv*{x~fyTg~J3+i&A-SwD>_1^d<}&x!fk zah|mH?gPx=y{re7@q!ni+?|ra{PRdO-M%@-#_REODQ+w)k^%b7ahydyMxeORy+Wj3 z7u)YY!xloi(bOnDLFiF(yRnpX(dwSg;`KyiOxz)?fc>~RH_8Q8FNc0lXxr(4@l&CPlx_hSqv{S6Kfl=$qq7BNCX) zK7W50lplL{24(l>YGkuF6>!mOY81>N__Xx+4U`pQfijxycDb-0tBG9iM&i-VDrFCa zEdk?NQaHUW$NV|~pP=H!sR);W1{V;LkE&w6#h9Pgufh13+!Fm*zy;HdDOT#Zs2S_R z-qlaDNAr}wj#;oiufE%kd1;FWN&2S-ol)v#t0Z{g_T>bnd#23xEXRkG9iUs4$IA;@ zZ8>x1vujq^zsF`ge|f^S(+c(vJ1R96MYx^`m<|U#9X@|=D1vViZEvCYKx9)~@@&q! zu9460T@uV9m?=q!`>*+aBdfgK5l=YJJWW%hSi$M9L6N>Y$pxHi$&euUhI8%LB=#)r z#=tc941MCiYpiU}dG1#l4SLf4J{Yt&h^L);7U+lm+y<>to_YUlZ&;G6%~b&_i@5aM#)y8_k|2xX&Bohj``Mop}*rsYu;F zN^FzcTm^)U5W^y|G6Ik?O{S~^9T&PRcf{=?*M=$`|MQxH&4Q4%W4?5Oe}AX!=;2%n zbkaSp+fv+Owuil^Taee>UY~_soVKjBGVwh=S;3}Rd2Q=h%4#h`Y@BaS|5ugPcJx98 z&sHC68f8pGwb{|1(|05MX(|WTcg@%CgQsugH?IQ14aJ{1tHPK5z{)3$e^**gUJ7lYF38>GTLtTOg{Z93+L4@Pd}vu)LcIn zDDmx#vaJ}7bHlUtcNybkJx}nsFxVZB_1AXcbGwsYV4Fzco!_%V%EXAoeEM5qs#~fH zNnc+`Ok&UaGTK%yjq&TCwc!#21wnL!ON1B$IyQt6@bEDHvpa#-$0%A%MC@kDzE47% zu?6S^bTZaOYK)1y@U0W)gFfc>)4)g0vwOj^0<@>S_W=$^23YRlfw1gXE*^`ZFIhTl zg-tp-x^=T)@{6q^li258tRM^GyjmbGXLVQbztHQWpE=iS$Je6cf9}ZtHRJhh6}ZfW zHYyGPbY(6#sHVmMaQ&DlZ3THhzmk%~5GDmNEj)IsiB!p=9zFKVn%_3gch2pDy{fgY zlxH3II!8PFT5E-FLcTfn&yt&%x5duwo$*YX>+^DT=BkCJB=q-~s^`w3O}&m%$8u?PS+Y8L{hi@b!gqG}_hlmx`#Z*m zn_c#_bVriuQuT7u{KNH5{Vz4ZR(sz=-u+$44vg3)_`Pxn|8OC1h%gA+ZG*Ry`e5-G zi`@D?)>^;-v@U4=g!Eqr@g(8~1CZr>zud0N)DZ~%W~g?Tx7H39aELbb?>ib( zzL~u`Uf`DLW)|^;;z-cf9??GQnIfdKs-sx-%FQ12WTbtEl~`xyiI5LSqO)_3JsePW ziFhB;GNJdgu^qZEcKs}WmwER@>`9jLW7_H%|M%P_>OMo}hDk6_ZB{2jX%qmx972!4 z%@vj}ivM!0#aYKox!s)CO@8NhnhIotH{;m3PYM&CY#3i_7#J6vmn(DqJFWuq7rj5# z%5+7Jg@|D6n%x4jS;h|h=zR2}Jza{-UP2!f92kdC9bq=94nwki=BFRkJ7%gx`TR5G z+0XK)`Fjl()Ws6&G=H9at}9XQuEF&&3F&R<=6ihQ3d&Ac_ao1Ok*DpgRc+gH+tpeW z!@}D~VPUOje!urq2$M2+@h8x8+5Y_e9OQ2)nqMRczUMu=4zg6coieck{KtGBFIWk| zaQP9^qsKsD6(H9V^+c-ReXHD{eG4NF3-1V9CFN&^u$Wd3Rd!*ndk<=u}Gb&$|5fCh)I4>QEK zg)mZC%5Ac+bwdb;lbe*IjzQQ}v$A-WgDTaX*CPLyZ0&AKi??_gc9_QEwlFF9JxBdV zoiC<ZWM&jZXlEpP3|4dFR&bG%_5<`qKGx&{ggBNn5bOC-+AnwT zEuVtM2kdin<~ah!v{~%g<*hIMK^(~Oh2HZyWBqEz$#YyO@{i#JcPh3E zU%w)PAz8Id3y36isB2l9-}xP2Z=R`Dv}T=EV(mV+WEx`&mTj@b;HZ-#|M#q*PUUX` zuH(K_`ls|WD-@`^6OhltMpeB(cWI3-xg z2tSp$XYST(4vPvcMUI85IM7(78S1;xv}Ly3r;xDGsd|06fB66XY2`Qq-f$ME$D=~K zrDdf{Ud7z{GqXVG{97mpc$aZ}As9vw(YS1YrZdjit+asFE|05F814@0=|vJ#l}s0W#LCSmxPYaBA773^j^M2!#=kShy@}F zh$q||D&o~GIc{Jjxs(oqGi}84MX?}Qc1A4AHCQ&gMer5Qq%v)7)4YlBe0Q2b4zMu> zNbkAA?QZYc&X6WM<$cuzEaZv6h4PDdpZ(@rVs1T`9c_jr{u>4O$J)Cz z15Q+NaF0l&pT{{9lkiT%E) zt&4cT2PW?gGOk$PhunX@p}SYEQ}KP@y?nfQ8Yfy#EA+FWP-QL?#hW)-0wMYtN?khn z@7DncHn&mU-!bQILWnkj!odC9W|a@gM1_A6W6e8`IQGFi#$)2L7zLp(Gf=>4FcHM5 z;rmx1RZ!36R=ifww_h6%s`xz%TMAlxZLLzk^d(am-nNDlB9YB!NKss~a7LkfP6Yav zsN)`$&zn8-u7fv#wj&j5$yuf5uP;;9)1f)%zZ8;@Ihm&A7<6HQH6$Z|Br8uV8??K#_M$z*0o2K-+>MxA$!XzEO^%>pI@l70#cIoC-)dU%nG^-+A{4D zO7FPDo!mLltZrM(8^7mZ5G(OWv=2Iv>_`6{*#hPIp3=7$qJKzO`c4>DK9+G@#AY|x zkL~S!!(mxZuw^a=IQgG%W15=?A)B%bLY&N!Hhkd_!LC@4G0)Ol7)zObexz@ScoNBA zM9#&KN;EYJ%?fwf5_zs=Zu^H>!S0FR8ibg@2MEy-E$dh{<_OZ6nTR#BpVwYDL@XX3 zfi5xE&dz?njz#oJc?WNfC>X3FW*~W&I~)tfU}~Q7mB&Guj98_{Ki|fcac_sSsWFT< z3B6-adhPv4{Mw&F%m5k?oIk((xoCVf<{^gE^*n!Zovllgoi-m@p#48BQjdS8ZH29x z%6s$5U6rv^&RSi$V(PPi{EZmtyhvj!oE*@OiP3OdT)5pJa;_g$-Vu4U!h!x^oxg~0 z#m;RWjsC79Ljp;5dS5s1E>wwQb&_`m(IasR$gH?LYmy4Y<-ZBmnG{BsT=nl77ql)+ zVGiP+;M}cgaXQ|#-*?CdY;$E?$a`MNG`gjfn}zJ$;<-Yxz7V&=R^q4}6E#n#xT$hg zSa4oR0qtyb2bhj#S9$B84xMe@DSIiX|U;igbY20xig(#p#EQN z+TofE|M*{W%-nDLx>#t*8+_{g&d+w*OlbMZi$ zFITW2+%Mp(ls-BpUmB&rwYOyibt}b2l?WP^KqqJ3-zOnPL=@P0nqk{b2HpPR3D}lP zo{4B-=qLC>gxwWaOrd?XfOqr~;yJ`RJ{Z}%XEubm&kE;v#I0=1iB^KW2rL-~Sb+En zhWrz@j-`)j)u~jjXFPc1HQXtWg=?omMa-PZq(LHnkpE^ug&Cker?R zZpFg%wC5ArtHsN(XH87!~D#I>ZCKtgyirAKt9d!+!Y|siJfHjV-R8R;lqfo-v736j)@|}NW@*3I3G=o;!+bXk*fu$eYijWGSS<8w^we7_xCIy z_I4~RJ)E|k5XP-ZhFJm>Z& zu*~>{m{Ed|wx3pVE32x#<>=q~k|ne4=wrqWkB& zZ?77g7xib$zr@X{9PCr3h3EXp|3xD}c~-CAN%F7AVwY#)DJN2Tul&y(nzB&(g6qQx z^|&}az1}1XU#rL5<916F)*hjRAm*?pH8lpidwF(@cl658l*E*@S1NYLFUKXI?;{oz zXQ!Bkr1`~y-#s8bJ0MoK!uE#tdqF>+9jxHHmY^d-zrtFA0SI*?w2S?vKy1&hen3I! z;=4yJ!=s2h5jqf>5d3Bs*t`XA4a6B16EY4VI`bm|3)y8(pN%5VGc*7IAOJ~3K~%G< z&DJL32=`(w56sCPX;iZGL^xJd#-rEpUBY60Jb;kU$Ty zTP7wZGpZq;RYhQ;Ke8ryS#c zF5`ifEHKUm>hF~C-(K|ZEeyt?hig4K!UxhPxs=tzAx_V@c0=XqOXy=yIqPn)G8|ZX z&S11HLnG+9e1i2dq%f~Nl{toQ&xqB*=?UlBB;!D$Y0N{mMI~gV>5?`VtQP)XgywxW zLecB<%{^bHUYjrSK5f;EvPK@4e z)}T+fPE*bfGG*T(er>jd^1bSu>+k!;2hq4EBE)}FCmfy?+A*okH%t}Y!f_I|D~ahy z+p+bSYG$)S+e4B19pMObi`r|uMeg}daJcW1G%%qaC!w7|eG}UIP0-!u{Awt;=fS9p zP$Zz@&R9j`jEL~QLkYqEqgWh)jsybp2u#cd@7(p67%pRNJM=eBXYjM395!j5#~KJR z8&4n@Yk(_aW|-vVdlvctzOa~(rbY!p54nlw4djxhMiXIu7sBN}#lQChGzx>e;3c#m zW#JsQ5b+?9D!`)VS_2*IiGPfZVtqOwiO&<>pCgsSZ7{=aD_dy}V@r4{N8RqVn<71n z&nW{VV{3SZKyqj($lfeLOdMv8-8;ON0x}UranstapXGq6xuCXd@4(0S7}&oYix{7HP(s-!n_+QiS%6%M>Tr}tNl zj+shMt`~*=UsS8b-3n=p3-7ExSv0?ifM!T$0pgo%g@X%dY82}kTxg;ofQBb3D);08 zvv-QL^^MN|wM$Rj%p~->z3*2L-=({=agzD&f$wLWq-6Xqm=Pfs59)O%h)p8O$U6S- z3nK#m=L8IIU9Ez3IO16hj)V7&q9KVp1dKD0bFW2+?cr;&8G#!SU&e6+w>#tDEBpIJ zUxD2)78Sds#luobruEnQAvUT<(BI@DCP=*g-_lBhI|u*bjHMq!)YX6cj99r`s&s9l z!qqK@660RGm!j+OhN;&&B+^oMOTkU*SBs7 zIc>SBrq?cEob)O%cAjcY_!2Ev|K%hHUg){1D=7ICknvNg+3xM;^1ox7__>yd?cuN< zWgcJA!Y}L^=J&U0JNFAl{;!mh&R@-jHk2)EMA_&{}NbTM^E;V_{c=U*RUuDgN_Mn>}b>F!~b9 z%EJltLcEWSAWmBtEk+1vv`Wbbg69RhiXjL_3b6;gC@#ma(Jf0@_*}E`@cH~V@rtyK|McFV1BUV*hv!@@{B(g2;Y0O5^yKyQ^*RE zCnks~_bY|Vn_7>5+&25H*z-G-9_t^MV;x9};=FtH)+%Olem`6tR-o@%C`JfcC44R| zfZhf)W0^YEr5rdZWBsB>`n8ii3?hIYvfo7Dz%wnF?e z7(ngz7-15<&dvxi6Ym%vE=E|8d6RLfgSV^&G8k zgfL!whM}2~JWI*K+=PvmZtJrj27rGwVMXOSUwL|uA$~;kqay9w!&rVMx{=>^K)f6o zPv;=sNgr=V5o59mTh-o(0K$X5+}L{`9?w!_mX5KWdDliMSqY(!O0#FtC-K?kDX1{r z97VunF^eLi;a9AnzhT z3)}qvurW5)Ml!(#-*eis116B;J0`>&e;HCC$WL#~6QJ#!o znD|Mc4}qryFPb#{Ig)n%PGgg0*Lu$WzaO!*{e5GELilh8o3n+nW194iC)+x}g`n>F z-?>+uzI;9S-6hFAZ{^Z1UBUeHOrSve3UcR?)|GJVkoU~@mnEz+r^bm5KDF(&198@^ zXj+~tUaA{aDN6{~CZ3-sDLsc$IsaULa;j_G@!0FD#rtOGoNK~TDf8h^Ra#T#r!x01 zzOIk8X|dKOB=>9H@*b_}QQ}*@0+Kwz{S}#z9%vpRw+5WyHKSj1=m*B%5n@ z=oMz5n#0Y?qS%%2HTiwo-jWz z0vVEyAy#Sl)+!==ZYYqMAed~y$7~DdnSP~{i9aqGDpwvc_n~=w1}YyL#8~rxinSQp z=k`S`U|q73`pNyjn$u3R6R{9*M8r~%fG^};bSHG!_)nq4w2?Fiw%U;?pea z^~CgRha{|54`q~b{+19XS-0Ri7`H;xCw|{b(;2Xu_1JVOX>Z@?e^^!*Vk64CSHl*u*hr+hoLP)y=M6!}?&qUrLT`93voogb^&n03g* zd3Y{N?-K`FqkCdI*jEa~cKjf0l=n9yEKm!hli^IK-9Cwej$d)gG6EQ6tT^%cWvTYE?Q{N-p}+Bf?e{dL+J!ZTG`@3v08wqYy~=jpyB#iI=8u<3FX$6L%!3o8vA zn77X_MiPrxQ%+~r=@yWdwXif_^zVzy80a(Q8EiZf{y$6UXRd9gmyS1TknVD1?szrZ zF@eMd_e-bGdPL$;WTiKskGZHYz@+N}R0TZH_Gx3~_JTnA{mNh^S~?|$$C-defL3;P z!*>U5pPRCEeX@nRP9h*jka$s)1PFTz{0#*b2`@sp#(~DTY)&J50ZuY>xvs0KSB3@M z*bw&G(HP3xQTG3ig10fQaeN=_a`B~6IQYu!UTbF1WZ+@JX(na`7YcL$^cP(a^c7rd z(|A+tBj9$USV)$7S%%_w7(&eA*Wp~Rtbb#ox$|SJEw@InmHmI5r@+na$3roFy;Mms zzjrPQJXg#vDN+cL7D!zN}wyvMbUQY>)u=2#Om{b` z>!TaiHMRsLp2_R86{dM97`_Vrz`p7VE_V+vAaLHjMo0{3-^d%hswPVzSy!33ki=c^(?DC`6p zncI&))w+?y_QSHMhmp%sFC+F#pmDK#CkVt!p>$8SZ7|k%!}=ESv-v$^B)@I(se79m z#TY>cL4ORk#ft-S4#pkxA;GmazQ-Sysp@xxSP}kbtQ98eSG>} zqi`&dA!u7lTy{uTM&9(4`%jU?1zuZQ1&4bw0N_c-aQtAQi57`H;$v&9`#$%fq!Myl zMA7tujy5%l14N8%3z;_BHI2#boACcD4YH|f^I=b8Tno;vX@2i*%d<8mHqIDdGLMl( z=355)zyF>0xlTE0a}(a}+~EI8jyC{pSG7L7vPA!TSiWDTBBkS_I#gnBt5*B|R`>nX zJPHUeOxHxK=U%jWv*uTh5AOl?1zILC&|iStxu9AvKjT9Hzp~nOV9t9NN?Fj8a2kA@ zqd)h{m+u#me7~)5av?(BH{Oj|uvY4X=P%O>6{c8&ZU|~PMk3cuX1RwY4k%HM6 ziA-QR3A9lzYf0R#CoIscgFsF!j&sRYHe&5(qNP6)iuLeeYTecna7g6*j}hf)Sx@OW zznIr8v%0G~W-}=`)O5 z74Heo6`XC^bm#{A2zD~myX<6w&v9KKuyeWK80*Hsn{bVIOu(Ino$Y`q#$!A_*}}4d zfsXa&ax5_4GPm)NTkj|A_m6>4{+Dsq937f?R;j;+deoHfi>X2L_jXfr9!pib&MaE^na5IA7d|S%6Z@w?LROHp&FUzz93bpO>%=B=9gt# z&^KXa+&T92o?SRd|Cuxkg~lf<5~sSyI(b zUx%k!g!rJTN*mUhpgDo*mZhXFkMFYEVV#5*cT5%9j`flT&doUn*YYjWP7k_u zzNo_b&zJxCkxu)sK>#efu$~miy~-=geR&s!TVPN*3rMM`-rtl{?)Wo%3)ms)z3*Dc z{ly~-DCsU$#JVAY-ilq1GU)J${eG~tJ3~{W(D#IP?oB=cMkfYv{?ogEpt*OSFlj-D z$jlBFz&)ceJANRv+j*_^>NCo2u7Y>anIIe$#Z%AA}$8-Ozx-5Km ztK95%d9 z+h?Qd2^wY2U*TPU5_E)v3AoI43kqT>?3^@yyAUV}oE*Nk8K95M`-i=EWh*$(6Qs3) zrLsa z2ifm?L-)@vOcWGl3;knASBj(O{Q2=Ga*eHIx50}-_x_!O*)3*a+thw{OncY5*zc=o zTdsipQbHa7?Rqt=Q-d8_vnDO#wevE?=9%5gt*fWJGNJXa?YGxx4L_J1>+vtGv(35{ zkU2_i0-OSBKTU)9TV4U-z3Qj=Sdqzv60Q?D1eK&?|LL6DvEy4u;94O^`)ppy*LHkb zpB_+#l66XmHWr1cS^db?5@SatzanBYNPw!@YA=WQ; z|0w%=i09A!1?cU{%d&2<3F0i0O|EF}jCPIs%J(Rg=VsMhO!v-CYa>tLe>Tk-i2&opeb*-)=iTz#SaTW|n zIWgUXIS7GnGv`K->7w$aJ$E-k%tIS&oF6)(Pi>xT7FU9}nj?&{gVV57v!3f8Gceg& zLKrLfNt{mH_nTfaK=V^gya6T|_bbr`4ls;X-7rdukGVO*L{#V5a14YtgoXWgvCL;Y z%y>k1CtnlraJE2kli1a{zBodSAeM|MAzRtwAY%bxZ^WTa+XupSKNDmeE#W91k0a~b9l`abnc5N+=+BZZJ@m+DMTxq`Y?So=2&4Li=8m=Uz2_6^M1cFf zOdMaYTC6!cHe0>_5WWj$?(#XnY%h>y)iF6K$3oK;rrgKk8NgS5Fq+F+-SKMC|yc07gi$-m=_ z_Cut&?#+?XwkLr&mQ#}2p34z`hNzysV1**^<)7#VyR%GXj}k;3zX0(hVjBW%8b2C= z_Xa^HV?Q(&jlmXxezsss8wX@%!Ggwp>Q)S1#23yFFweY$;AZ0n#)B4UE^!`$|9SP< z8BM`5W?5_FWdxXp(}=e>`>W3?Yxu3&iFgTsBh`}Cr^8m567lW_`jBZwr7s?=T##3H{S#` zB>CErCHiT5e3qPdtFfSLAEa?Xb1YCUW`^BT+Qvlmog8wVN%oP>6}YM`=|288u0)#9 zwquH$Oikpkr-Ca|4r0)Qu`;nY9d&E@d${~zOZ{?yCE(kYJ;fzrl+jQ&_D*u`fg zO^rb?LP@;syJB^+0%{oZ^s{wgx)*`YXDlXwAdd<@w-(}$Ow?~aHLPOjDHHIszYvGP zt6~V|{-#D_9eG@sSRp5w_#&JlxY)M&b>{m`L4z&dtayxA9Srl5uQXlfmvsSw&JmFHmB9b|6!cSSe9?JT&oM^l&nz?& zUDJ-H9|Kxmx`eGVx!tew%yVm(nh&}roZGj|x#g&YbLUhjNM=WKcB#Hk$T1hOPNjnF z^)&%KqkY2XE=pKqIJS7&&lX%$)<`3J_-ndiQ{&@IrYj&BlgqlzUZHLRbbeho`c5S# zy^E?esJ1LMxt>&C3eF9bUZAqLy`S?1uk8|9mC_f8M=M_RiY-V7f(9mDd!SUG^$xC& z6ER7N(ngtzfmE+ijdlTBd%0Guz0`GpT2ZfcYt72Mo2 zikU44eI|qsgJpeCws9W|9+1)w6cs&?>}qh=qrr! z;R!_ZlmLV~e&OBnD);ldn3ofLm$5@ktaQ-I5hZq5q<@#n#rBq@sAMT1>=k*hmWZbC1}p(jeXq@A9AZNr#y z)5!spFX;UKF;OtPQXuB?-Dt|)1$KqF3FO;ZMmq=p|K+s7tDxOHOp(DeobJbr7!cq+ zu8OqVcn~{*x>;y;Hze_^fCr7`YoRDshTjkYv&@Co9j700-{ML3?#~5$W|@Rooof(0 zDTX5$DtN}y@%Av0&>weQeE8kCXdP$SvaS}RFs@uYXB36IkRL#kpTz9gI(%rXA0G%l z#kd{}z?As}#D8o#k9Er4i-2-@d3UV*99Td$^<2{IIWJnc=#$*vPX?Hs`BCaS?~_e< z3jcwCCS;C{yq1U}_hm6={p={mN$zJwj=2&ygZ3&(CgV~9ZzvMoEpyE!XIM{(Y5;66 zDH1KcdO?2U@qtRSX2q05l^DPF80xXaxeR~rCf|E%xe5h$#>=}?mDlI4)L^~;#(pnW zU-H=n`RckrOISHxsbW85vxe0V24wrzt_(ce^5ti->ZbQja}0hSj!YQCOV{(aJQL4L zpucS%BMO5S8Jj){+}E6A_1u)aR!uL%PYUl4&sm@!StS3xk5Jri)eCm_dyY0t1NlmZ zyFXna7-rp8!n@?&&im~G9ZquD?}BYboWgf@65}%j3cxA(+o2Ko&0)&pc63|3J^m8> z*S6ERkZZ+RNMb*$5VR2i^B=F+?*_kYj}Yc$e+MB>wBL{Wg8huH0P}~zcU+8N0rcwn z3D(W(Icpg?+gLI9#V9y8A$Z*M&#^MpzLNMqduJVYMbX9aV|ObG77BvhiLKa*frW@- zD`H{?CKjTAih&9$Dk5TG7dC>t3MSZCC?=xvppW18kD1+_-JRLEckg}f1J57(*?V_q zC(hJ4bI$pl=_tWxD8gIg$9bBIbPcby}0XD5)o`;h>Z|2k*ua zfD}Z1Lq-dn5I0eb-hV`y5HUR~vv$8#183o($*%waAOJ~3K~!J27p=^CH`qnIifr3&lyKMlag@LieOsG2x1y{PuZ zLtVF$?zCL~q+1>2O*NxHcWCRfILF@ zWS3vvw7=7&)ghWGydL?&6h4+mzJmD>q&_&oHzVEOC4js_eVwusJ^?`(frv0tMHhjW zHB#00$}H>=RBR5vE?+9g=Z7^7KEXIWeGY|=b&`s7F6RS(3DO3*SlC6y9*0K-VOga~ z87uI2Um(MZ zW);i0eOx~~kHGodCLjk$SvzF{tWascEemA9W{y=~ry$BXFfO#0w#H5!FQ>Z1-Wx>vy-d>MtxmyD1mJ1YsEbDs2J1uQ`lT7 zRK|R`BU5if+^_1ZxT7+%8$t*5?Ns`d`^p+?wo%oIo@67&6}HJ+QIQyKo%S( zIwFGnKnV09*L7B&K(o``?~MrPR-UGny_`d&6y(OUGp0)ryi&CE2USqJk=RemHXY_x zh9_DoWvrZA;{MuF{k|*ei?c{c`CU@{xSRbVq0e&H_xUHY-RtjV}6X;h4PJ*O00_h7EtZ$B3+$`mG7`>BE+?tz}FdiO@2$R>J?^g_wy6 za;4FyTl;8Z;WUdm8Ae2zWpJ8$f0T-m$g2kA=|7^iGmaB)zkV9pl()idI5N_|JDC4> zfh#3JxcLVqprB*gT&liZz|aD%M_BXZ(}ZEj#U4y=Cqz_44CFF|a}^^gO0ywbgK#q= zwD1rJ9&@WapVt};FE$0MD2Maj3eAdNRLl?L8Rd7u_VAK2%i=TPTLOf%0UnwaxA3VF zZP*Nzk4dNInoiDuuIz989>G2yLw*`661}8rt-N4?G8PpRM1<3g{y8>Mc5jIbmfje* z2|vhS)|B)}=>Aw;S7_@A&Dzm;3V{~E|Kq)M;nf1QMRrckM6rDey|9j(oQ&5y=VTPxfSUC{Po>uWY zgdXs&z`X)L3dk@OxbSIVB3jGwkTM;+NIQ`KtH*?J7)%uSO%OV8p90AB(fR7MkoN@2 zq^rIz?5843ybwlSY*_5FAzbAD?Juxt?YPcd@4I1z(}c*4l?%I4opXD-?<(}JhOEqrW&*dvTv zG#r7jaH#Jm;S|85WinWqVMPKI-lwd`5D8#m1MST{)Yl2!41wis0ii9YB3xk7Zxh28 z&H#OwK=d?ULBdW#1(M`>VJZScg!NIUr(CZ>{|T*NmUtSS0h0)L3S<#t}2{GaF2FUuRFz~5i5~Z1V^I*X+mvb@U z>qOv}LxRpWTBusiJ&w#6MfG*U<(dY!STuH%1(3Jk;Ba31;5IR{Y0$V#X~&U2GdXT^ zsSzYnn@w?zxRI!|;5To^b?OgO7$22!eYr^2SI|K=$J2$GcB}X zF8%u`Oa9FZ*t1qEc5gVXWYnxr3$4dSO_9`_G$6$@c>7tO-#Lp7HsqsjYj` zz9Htxb`(9!-v4tsO)yq6>h>6-;AC|W!#4$W5b_?$J`W6~J#l(mYI$~62v)ZxyCCq1 zGE-5{c84z%s#SfRI!QefZOZksHveL2n6BRch`_vpu$PA7-C1eNIEDKKkb|kO(?TN~ zQeP*$tjoFsg-&*un%TYvk~h5HXCNHJ`Undm&|1$69Kzx8IGJ^o-zx|+!|=~9k?83C zwl@d&A>>zpyl7}6w7J}UcC$UtMDCW5wr8vophM&0OXK~%i9Rka;YdVy!#p53+RN{_ zAk7D*A3kiBus(m|z3YUpvCMjX5u(kUnZ6lW$-}ZcfCCd?avS)H9{RAkYt1h`-qkay z=x`^OxF7aP1&Ki(DRCc92t{ydlRrz7306%B31Mx;;WB#-&`XW>Zdt{)^HAl>xT>N0 z(iNM7S5n5}+~H?7CgEuP?5C_gK=lcd6U5Bzz}%U_aB0s%B7@iphk4zISk=!g($tb zHB28JsIVu3tRB{++@-`zW*|(~@V2)RXcWIknOu3n*?2~vUIi39870s$L&bq%tU9S| zfglg6;OYZW0_|x8AQ-;C5Y5;`U<69oQP0*7V00P8ZV2)aY=c7A6454Dzk#e3?wc`& zM#a@1=L(68v$gMDhzNbloBgQFyH>P}llc&YCvwO7uxU>j=Z)*(N;rL(RA+eCwNFS0 zZxtCk_wl=a-#j+1)=(H~<*pekm9`$AFe~iIQB4``vVFIFdfVr=(C0LYrYht7voXRf&g5M=f05O9a$8v0rRM0>qL8iY@E%&y8Xx>FMtjVG%= zDQu`QRM5eVeH+IFkHUc_;EMOJ-~w>J04u8CaMm%iow~nNVjWhA&}*ZFd=?_vG{hNu zw)^4U)ohys3#~I}^;dhX8AsbRwdEK(smteuH&#be5T-?( z+^>qw7xVpJq?-=f`gBnNL~ASebNiLp?tyvPR*|}oF7tq=xpkiT*BLO)we~TB?X8U0 zx!L>%9AGEoGVRR^mbg|9cD~yyE0cOo0sA!*sioPcDChp zjWNkT&OM&^s)Y7#n2`6qd4;J3@|VAQhE2V1hO*z!QP2I%#WWmUnU~zB&gQe8WJeRq zb+X+aRuDkuL^wY4X}AydX^ZO2h9QQredyHtcYW6p+_?;vQm0=x2}nJ@ZGC;6_H($! zj4ASN;4|bi40oyb5tOVOwJ_kDnxQTcfqxYw@j3ec<@!Dk0`f9U5`^E7BR$9V9eG>} z8cY-JM-(QOs2C+G5Mo!>MUd}NUL2+mfq4puVsiFI*u$XBufAW(Rv>T3kapPC(I?y# ze|D4&PIn&v*^<6MxeG|&aDR8jX?llz$@~IrBV6l%ZVuJsJ2H={BmpFg`4wxq-<@8@ z-okC}chjrLFCcTLo?s_wVxvBGHy5?v&eO=v#?qkb>q}_gL5+td9so*dv|G4IK&n*@ z$h_rDa9UKQj$_KH<8c%`5k?f=zAYRJ_WV>=MO&(qS!20|N5_#Fe`SZLDbd5h@1NuF zccyyOPRkx8%%}Nd&$i9c_m`)o-TJO+5x24<9qGg+G}q=wiYrmaGog&(knEd zyl=V+ATvVWbV^tQY-Noma_aMJdVo3m$-fd*{u5HaL7tA8jcqRQ5%&CVCeXk}A!$F0 z(ElF=IRJkN59zoaY$fo8aFBvj@J~lCLTRvmN4Q8}N0h(E_B#6d4hYvFJfhP-gf?Sa z285mHh4Lj)b-4~fjpfdQGAUy`LNon-SL7;B0P2VI19>wL#@dAr>tmCvgsnRrD7k2@{E0&Q|ZVvlk9nYlFk zLz3qDeKw8i!0;NDXHR`4@1e_O4ale-*ThhkM7J8MPs_>+M*9k}Py*3wm}8Exj7PJD zn*@;D<`x-)+BNzKH9BAVsd<_F;Z=@KFX0Wkdr3}R2Z#ROYE{XvR@HV5YXlml7@e9Y z)Y*bE^`4`R-pTjFDKt3Hct3B^^kP{=gvB%D8)c%0qnwq4ybjc3_4Wv3K7;2XH2lRs z-BvdCCJe8661=03=`g}KXX>x+FNQQ4`c(aD)XBa`9CrLLhj|wDTox(wA;F1uq}sGI zTStVBmWIZ}(~6vi(7~s}kv_uBMKP!2bs0y%2+lyo?@;f$!%XcT#gQtne}pYjrewz> zDv%);B5cH9gi#p&0lcjcz}Sez1&#|jM(ar155U_*d}FS#m{+lbzIR71Q#AUY_Jctl z58|&FblzXn(ns0)3}j-EZck4ew5~zx&V;mMNy3A@f4=wMJ(o6~WP;Kb8Fil<^_=wF@-(0rJ;V=$Pmlfo49GKZ{O(rP(Jxpb*h?+!Ws~ zpZ$$EDc$vbRb&EAUm~W44<)t`V({?wb>c%V|BA4=7d<}3Jj%Y7+~jR9?P@_+Y)w391FgZZ*JPfkyw(Z2})xqXRvq5OIGaseBCLjOHtzH6Nw zp(@H~g_-iZZj?x519y=@4F!IRyh6E3QLa55H2A=ejADengP~C=Mui>BgpR4p1%!42^2qSID!=ZZZj{$$qX(|f37-)W<;RiNUX$*(x3sJaRX{cW| zp}_?BID(KLkKH`ZKqq4zeSawI;Qwm)^!xM}XoB*Q**K&zGlh)i2#Z)vRh-ChmiDbq z`1E*&EjXUEPn>%nWZg5kIuNEj$Yj4i&&<7sv?|)4aP55Qm$Iw{9aH&_@-_M2_%u`F zd4da7Y`$`t@%jw==6^~HS}M)=POHP8h4k(6t~wfXsHm%^LNqK?yTa_?bUHOs4G1@+ zOq%s`<#%4C2h{Ne<Gd`bvQm*KuDSJ>w4e)Sw2k;cP-5KCykAPj^|&d zjH!Dv)#-Btq*?g+1yzizA{&(a?GgyDlsFeyA^iVwBcH#0hBJF0EWR`Tk1}oc*LR*Y zb7k;s9;OJihBMy2nU0l5Ej~fhG0cx-=JOVdCxmUPOcZQ*uozx$d1ADi@k5n zxB&b_eO-X6C7+Ur1m@pc<0BP4W6*tF<(*)qm8k*TiePO)R;0d8IqZ5tF%d&+%2Y&9 zCRTsLI8@L%LmxFs_0cGV2s)h+ zywt^v2jgX=ojHGtz+d7Je82-akkCO1vNPLeMMLD4KmfT_-OtJCLlic{3W8Lg@8z=w z&bA`!>F-K6MdG*O)}oUV=HP1;I0$=ZR*c=H{c2dc^gMc4=rRWqHgBx)>(H`%hHnX> z0v2&ynzKIB8fa|NuQvLxBPjw1rxjDsMg2cPSBD zlboo7h46|B3+AtZtW$nI5j%S?GIbxrem`7p#yBjjs+f2YMjFn`N!P2SYeA6fn3!h1 z!l=NEs0_3$|7xXa)K)na*4Ks6l@iC)C|mueIqTHZaH#&7bf&vjF7~oKyS~^mWB`fd zL(%r}(7Py--EM@x@jw-p_tJHW_vl{-|!-M@Ad(E!+pJL{Jqr%KgntjfK%3*A$)GK3A@GJnz^t9gN*&IM$&8XdDi($dCbVmh- zdsDw3rIbj1wBaXFSJ*j^l;(WSY7j1QrLd2Q%~pgfe$2=*R60@*`(lz46YB23FS z1^6dIk3|v$QSHFW$q`e%MI!=7q<(40QgqMe|Do#etwj@87c;{Pv>-1UYgW71n28~x z9WQXM{@p6iy4kWy)(a=cp50{Kn|e6=Jvn~^3G30wcLvNj+oS_bgy?f%ZLakbvcke& zSHfPpOR0T4hxPd;rS1byG?4aSmm>L+eu?kjOQFs9MtXS7z71f4W4$c(y! zv|KBdi@=V|9ZS=p6qJw(`XXdoNS=y4`j@l>RsZaV#0--8g2#y}V1Bn6V7pWUbL7ibi$TM>|nhzNIif{tc3FU0Vj z-~@yz9O%dO*bZTJRuB-*P(sl#d}Ol_Q;)%<&!_soj}A>DN8=v^g@l0V0iAw8K=$?- zAvK;}qQUVvdp|xpt+&`|1Et6b12AN zjy9EnWV0Dg<|`}ukZ-~yfNTKWb-f<4r=2@xLH47g^Hf-X*iZ{bJGyQ4Wu#)5`7I1} zEF#FSAX5n2ZSO$Hhso|3eT}`Yo$aUki+KXzx56hY*$3Z|9@!l>6ok_`SODpxgg)lbdY2vj zK#kF8?%s*^+7{-WNgjPBs`AV+sRNL*j35tqpafsX@;FxK`w8kBV6Q7l@B|kf`ZVf*t*%!*8$9u{B$D_KrU&r zi_A75jo-IrooLS#R{oMzo**HV8Rnby`}hvv(FOoesKWJNjs&PPkd?kH2cO9Th|QE? z)?wH`EMp>eDzVIS3U0&FDfR4Ab-KQnFp;0D#3W~*GU(SVHO*HAF!&wHY4>)z{4+At z$|xpDZJH zB%=O!-*wlH@ec{e9+8vCVeMTi0l8D1)# zx;CD+Hj}0U?ozIkN*x<)RRs+Q{VLMvmzt#123U-~s^Pj>?1h;cAQaVVz26RgA7)zs z2jvKo_^|%{dYWzbEusHibh$%KbCHFkw0yVtw!e}w-IoHbvuQzW8j)NM+z!7jA+XJ5 zZHd9LK5m#{C6(=uOS8QG(X#$P?$R2N@AYYWtUe#<`}Fv`@wzS(L3lYR=V?LuhNEc< zYqGSUf(7mXHy}JL(8XI{H^hg!^#Wsd6jV^bzd?2aVS_{4F3r^^(JUA2&RRD!?It`?2UT!qfpU-Rs_ zy^C3Q7fSW7(0%}RK#9L9KO5z}TaHQCw)W@WS90%qt@``UI~mf=T{;~H)(|rvHPOmz z)>kXnxGK;zYQnD8p9LGY2^Ml?Me=>4+CoT1_*Ewz7A}&ed$`|C5kEj!rLKK6YEDB= z$ev`O)29W{+J3Uen&JPS;dYcvIzfv1n(%Zy%>}7Juf7gH`#DG7?46ePMZqb#;~JZF zyxnOj>&BG2o|qm#AxR4&tPO1`Ea6B103ZNKL_t*I>C{pA{gJkg(DzPU;@gGy5BfM1 zEbcU?CPhS$dBUbbg9Hcj_*1-XzY_N|VY0pbgP@N9J-vFJhkOIbO$zZ!`GmvYg0KgI zp)oiz9MF%ABlVaRyj#{6vNn#-{dOR4f}D#oy&4;S-x6Ut1mP+b&H6|XdIxQo39`SJ z|Hybh(msAN&k@1@Kh(EJnB#C6K$>eB|7;yUTRY}eeVrh!NHuM$uZtrmArn%C6LU=2 z#-B@=M$VwVP6-1vH=pkw2uTsdE0(Fo-grm@0;JrYzE_oyZ?1R^+FUDjFL`P!K%{+EA|8Im)7i)x&n%qZJ* zz=oQHEC5U7p=;6RQtReS|5WK^J(|?6R;l0jP6^;fyTA{@r2(S2b*YLGpd-#IYx761Oi()WG$G`>%h_dls77v~3I{nSt%7=uN5w21~jsd57kHG#2 zo1>kpBT%!#AbsB%;Y$@r_6gMgMU;>gqJgjXIhC+LE0+#q52 zY-S3K4(GjsS)QqBWhy@y=ydTeP<-B;O}Wm=ymsfT`C{Mm^^= zejlB;{!GicnEhJXBDig~bZxDuDlKRG1;BGWW=Daea?t&U(#o4BQ5*AJ=zr@{#yT5*CD|O4!WiK#)54u%Q+p;*flMS%X{IvDsNf5Z<@v-3uR;hTG%s z_llhqE|=2B(=)Yc6#@AxXJ14$dr7$X?3_8@T?^<}PS!pZJRLmyR0p$jeRsJ&DPGXd zF!mC-Rw5=d7m;Afk{q%9cZ<1{h;|~+h|tAh!TZI&q20XAVJVjl2z=L(s7cfc%ZHCEcysx&`(9b%ei=LkN}GM(ME-n$c1}Ux5H! zNtOoTM`$JpM+VFp{~|mR(07=p(fG#c0DYc-ED3Tg$UPv#ZF74V+!bNg`5q+DB7R|s zcOoLlsw%%Wju;$1?N?0h|HW~eU?CB6FrKrT4Ea}e1-;rF5T0Zs5?@CVa2!0b5Mo=QwvPPOI z_Pka`;io5*_piX(N%UZSqh0g)Ot5*KnP4(wMG!I&xm>WhF6VUQlFYP>eS4_oeGl|W zzuK_nH9%Tt^W*77ocSE**27T z$z-lS3=4zDc+bza(_%xyr~R5KHfg%7WxVYrz&P!b=rEy*kL@5RDsx5!M{ZS2zswF_Mu zqekSl>hMeN<`^$KNnk2GTWCNyG9yY%B~Bh5sDjtO{EF-hi{@N39xG#!nYYI5BRRd4 zji9tKutbK1s7)I3$&P}Is16MebM+NvL@fQ2m|cHW97SCWbI7s!?eP0u!*yLO>)748 zvi-x_#{c!PGG!~KnM&0~{4V$aE=(@>n3&1YNRX>SF$lae`;nj>(GKDwqE7P7w%y<; ze|c0Kj06VP?&Q8dJnq%EyWK2{Q}k~m`ZWsLn{V8)eO5q_olvHt?CGOd%^yv_B*@>u zXkDj{fJ|0G1LIVhf6Z|?QQwbJ!hzP{akPGanYR(Yqw;&7FoVn&AkQLQ^%(dVZW5(6 z@eX39Mogu)6OaoP=$gu7D`Y>IJCcr>c7}f&oAzik1!xd`zPjO`69~vZ#59;mK?&2) z+`{{u@(E$TAf`v{ot}@%xM#mv+&Z#zT3J`uF4MN5WxO5XXvbOh=TU7LyVcTo=vC$N zcFOH1ylx|g?nRz!GQldGsJ%p~=L^W|{Mpcsk;@yP%%e*9=A<&q-Q7M$S|bRLH*7yF z9jV(NAe*?y^c9Jkgy9JDTm7Ms?Sf|?+e}&R%N)RJ@kqL-q8r=8@o&yV_}FwPbp~(w7oCHn7ENKKeWl2gkv+0sLvKB2wRYhjwB+;-GJ;DLy}6>w(zhI zM~h5_DG_>bL#*6QJRyzK5H`^H%n!?}_g&5QjyCGEoQ|XM73xsIGp$Ofrz&S}gaK^f zl{*zbpjHEqt{$epog{|U;>k!G|EfLejL#dh%3G!&>wCfu*8k*Rz+45UA(G2aL%C`H)g!j*7qx*%q0R#R_e!pym z52dD7e*7SxRjv&iSrm$(me#tV%>g$98_0t*^){u0cbq>j^qXFsBz$&ZnE7)Om8QQjeTAB+BqL0mfeD4f-PpD4+ zAP+Uz7&w`1wzd_g!OJP{UyUx_bEIkl{Ojths7O~>`lhEP-J1wUr{_05T{5Uhsv~P-~z0c`1M7OXeCN|-LKXxx{`CPLT)rP2 zC{JJ(&P{xOYau>sN?X<66Z&tnrP-vcG75pvC8JMk8|a!)-m?|vZ(?zJDrnU(kz_y0 zqe&)hqOwZUsYu0yh2e$gd6J&=XVmKCr(@0b z$0`{YjlD?_W^&Wxh|vEnQE)`5LOF3qJN^(RyZU`qm(R_M;W2qxWQ?vV$l-u&A7g-B zs6fa&nY0>7Ox`I1$nUZD?Q$&aF;klyNL!o49Epv%6nw7lHwO09BT(jc457X*fZ2_< zaSo^N)A8Z|15l3iXW^SA#b|XPA+tVJ>H{iWe-x}QkE#Dxf;?%ae_1)RKckiPra*%MpB2*op+Yw?zdd{1Vm_QiV|DKHo$mi#8){Dz_#N`C7Q6Qq8WAE@5=6 zyE6KJaCTUuWNXK}#jZ`qmb;$wYqB3pR%9LmZRiP(u{?K@nbrT2^WUvpZBU!w_l+T~ z-jGl3h`mj#3NlAl z?a4ms-Y=5=VBCGIVN*T-grsX};+tU1X;PY}I_T!3`LU7wmr2!%M4v4$VXeo8Sx&rT zW9#AI|FIw(tbYH31>I`|!vDBkK=@d<O0h|t3m2Cgi@ zq|T;^>gE`OQKUH=IKg#pM7PZ7R~^;;G?deM$T!27KU*On7nS4?>;y`%ttpcXjc5kp znqI;0^U5{pmYEetvs$~6@g~to^+-y!nkn1U699)+8{@p68EeA!*GtI7^k2*^?3;q8t zsjfZq2DaRzvSWW>`2Rj6Y(SwLl-Apy-Hmp4PTky*_8?DTR43pJVCIC zYs-x7K|Zbl#`wO{%;O#F?JycMPxnY^-yUG;?@epp$M<;KIPFc70Mg(CaplIUK{=#) zG&&&9#4aBVVu)i=pU3J%J=XZW64U*Y{1da)_vZ5HGt`D8^Q>2=^~%nFJF170QtGv5 zsgagfti z^8TM3An;5R!st#BM|2OSG;aEHi|?Z#BFrS2b}sXe@TvYmalCwX*Z0*FW&H%wk+%epNr(s+34A9gpPWH}jQ77^$}8_# z=wp`6w#ezatP=n^$KJ-~D$QdEte?Zw%0kO7mignEDe`EL{%zvI#?NFEK=SP`U2{1h zdzJ`~5cExY85@P+on!AiC4PUn(;P4k(;5p9YXn{_+yC_ZJkHw+!urRuH8{J6*N_A9 zeZOJ_4$Hb`6-d5Fvmn?EWXBT6?aWz+HpxO8A}&*yUIHsv#-JC>jvj(+6M5e)d{W=u zH$m%}9d&DR*bn1*1kMiL&p^k!XknU1-RM4r?*RWG2!~k&n!S+@fSijwY{2G93xw%0 zQ!d}s!viz8A;CmS2PYh)z>*LV`g!!62(pm+y`17XgSNaV3TAXkl!@fXa2W>)$PIw( zrpsA8D6?}uc-wU?z9OM-X2jb!Ua#`9JKRjK>TZz?vF*XGIiHyNHeIo z`FefB?t`~T9)aSw3LP*Wm}-XRx~dV-m(SAZG7u4AnHtiPbj;eX7i8sMHYu)tUor~` zP8%7&FVFw|-&GbsuBXxjS*&I|>-P!?IiAC0lv&C|uY(GXe(P3k2I%$;8N}KqrCLffk~x zz?}lZFyGgvxlLPowyy6=nr^E^1O(4CYrcqpd6b>e-`~?vtYq&iGgi)p%9X_K-ytKD zeMe-8SosVRrKQoxWaVlGC*~Z=B`?{&5;}yhJJ!wqV7DV*BZ}+y+7y$2ZsL`)VbW z_jAtl=N5zd#cql3zp26r*@C8t${0e-8q(2WUUYd5TJ4L7a3{&kUz9oY&~{pgOH-sA z&Uf^LpceYwl|lOEVwe?Oi<=q!50EzTa!vvInC-sQ|J}i7)Rxo&+AxO`^+(E-%3+$e zcu2UpB+P7%i8#;GH`X633q0ZFF_4f`zbp!JCPBn=5eAFH3I0w%>Vvo+85s7CTA(ze zY{vzJlMp6>9258f-4xI3s%Sr3d{E?6PpI6&$p1B`ARVOHChUjQTLPMCGcgh25U)=U zRv;vv7HoiJ9{N%4yTRE-&(lhyQ+hFwB7RjYm+;L{*F0P|Q<>LQLI5Gz6p5DE{JpAm zJyi%q^G>CG*DitnY~MhP`v>tumm0q|$k>Nlxzcf*d%U)9@&R!&5Dj_l*of@*qHzhb zUTusvzS>ajrFBiv@XRzJYD$fdfrl!@J{cep&pDze%FkIY7c!}4mU*_&M8V3LYZN0fL zcLVbnof@|M3uX2`ByXfw6AD&?UB}N_6K17SPDgA(_6odCE7f^gMi(d)y%5ejYk(*^ z#GdV7w5M$IzQ47=7w#&I-8jy0unLh;g$S-c4Gzybo#m(xLYj&5>Ynb&j`5~ zKU!K&=$C^91dy%O|3$;)J!L^wlI!pp=tPL&N3nwjtgi1LnnJ`!xg7S9KI+}yaB-$F z7o<5R+NQp#@dcSR(3p`1Eoia`1J^k#)aQk0I2d*88+i~3p)W{^ae^c|c`N*O< z)~M|{%aY%7`q?~5Wn~GXYiP><3~CbGV&}6cUw~e z)GuCt+}*@~HC?qKfH1U5ga5upLX>~1D;PA#eOg)^6MR7~^r*GSsS3_`z1PT2DUjbQ zm-jx^(hB{p?{it+?N@ktKMM#$Oa8unWb7T9L-2_*o>3;RH?Gs@y&e5OC#&dh{`1Ce z*KA{WRe|3Swii+Y$32;RGJiSwoa)yGnOC3qQy2Jfh#>rc(9y5Yl4%j$pG3uQ;fa7* z-$4)_bDnnZqud_U|Mj7pA-w$yc?j?~m=OIHVT1fx?DJqmOpOqem3W2~BwOOA6$Y8^C?bL7}L2V92C*#>c z0m@lyOg`b(qU>VxfjLrG-go#{KoFd08Pj*W1^8_1$(&`ZMK_nWR$h?|d=U~5KF+zv z%m*7d_9Zj6*;S>$94DF6p4z~B;ZbmJ1^44DX4fp-fbH)d1smBor7yQGxvaF3nq9pig4NaeK%Y5!*gW}d^X9Dric68HdPXo5Cd*`p@ay%ujCmY zBUGR_i3GMQ^I9i0_Degrt$m5M!;JRwzAkt+L*KQdGKaZMZxl1xGM71(f_Ym%pXrsA z9*>7LDwrqgyM)Y9&Jz?K|0xlKrF|R`zC&nMGeVjW&d|S~A*Lm92C-X55GDl?#V1F; z{Ro5+A!qJs0>b1V&6Sq%;RPD}!xMo1Kty=QrtR@!L0Do!-0AtrylD2*%Iq&7bY>3$ zY=OY_|F?-dw0ovn z*1nueIe*us%>7%53Nyo<i<_}|FzWpyiLaOxCd5XmC&_aC7i9d zaMN_(67#$?5BSPGv{aOu6=bqvJgNvePUFrF(>4b~jEhlX+sU9t# zcLnvjp<-n|Sqig0KIQ$f$?vC-9tY%e1mu@Bn&tE}k2J&7A#Nlc^PCcI; zy2pi$`AyTTXe@?n`rbzX z`GC9hyBP|Aj`LBBt=IlPOpVJ%>i4q=V`Xc>324#Vhi?8NHujKtoW3>4^Qp*Jb^&DP z@-%T7t`!92L_#O-Q@r1vZq$XL9#f%n+y8P_@2 zDR|dXOuJ^3vX?JfJ3LfYG|n2jT9L*RHe8TIFJNtx6MEBCkbv`M{%k9&^leUY{^ig@#*3ZM0sayuFn$0K4&u45r z{W2&iAX>jRhTqZ>E=cEN1@r1<#Q( zORzXq&W9y3uLFEM{nYC^NmIBB-4qqh#);wJG&=*gZvDOmFE18{Ay)xw~EZGjkMpw{`&bGDT0dsPWMw+OFWGF zI%RfooPh9>5)OLla{mV>q#`GMZ}$QL}<2xn;~bWisxYhe0Zi+N9p?< z`18;|UDj=kZvGtUmH7jGqmJ|o<7=^8W^O^92l>G$MFf@&%#)%Fqi5b_2I1R6fNO0g zeG4aO*dDNsyPwfcR!DT!Ueh>Pv|~9)`MjpBnS(r-xIQp-+zp8(Kj#J-L}Gt z#8KVSoLP}q5iV?`2ZZa@WW8Rl(4mz##>_(uMTZ+JL*G|tk%QziQP|kD3UwS6_EXF@ z{<|i=A4(Ylh!^yz=&O5?lY<{>+6g*F(_xi7T`4#S4+pFJmo}XK4Jx#tSN5c5C#Ts| z{y==6+s4J?@n<*Y7(aKGIMx<5nWxWjT47HlYhO1&)f{D3H3yXH70dcAV}o!5ES zE`%uCdsz~8j}8w203ZNKL_t)iu;E?bqGJRQFrJ--m_s$)lIFnksS&ST&uq*pvPR6G zZ>#|43&K^w^N$If#Emlcjxmgz$2A#K0)L38z{Z(@2`cink0scy(UEF z!7>6u`(pRMyNcMidt@u?Ecd&MD2E4bran ziN(Zg(tuR#TD|hxW_SoWtBbX6B7*de)T9!Rw~KS^@=Q4GR{}Jz{QBFuihIH$Im`OALUlui z*4{oSE0vwcX+^EQT$I25CpPhdjYF$9I6Y0PCKId%?xaU^PS`ficNa!uZQO2_v+nFk zW1jVYUzcIgT%d@JXx%)voi97;y+iu9Q*+j9DVObZ+f3i5p|bFDL5zygPxp9?*@!R$ zUZj7KpH83d$AZFftd$8&b|zmBe;UdvX_c~k~jwI?7|1~sY3vH#I4P`&k;m%q{TnxiSYkD5u`J$YtwrC zn`iw!JM@1&BfnE|uSLlC$n!^w*$@6}LNT)U)09TUGg-8WU2CjgSIKGSEUk;D(^oan zR~>822ZTABCVSeoQVnPikaKdRjYl8<$hx^StZMSwkpIZzIoh{q3G_QE*GWMB{I`ee z($hVVhhcxrW5DXmuj47Djp18S9k2IJ%ZIpp4|?+*HrxNXEq(NG zqUnnjlmBPq*^Q(FGVp}&3&JDmCSrjGP1#!0#!|lx2{aQN;eUIqz{@6Whv_uE;B7(q zhum(1%zY_dpMHcKD0!oT@l7cCTcP}ZUAWk7bdx4$>Y)o`xZeRcde4*Pnvc?Dro zh$elJa9og>fN+P=Cwqn7-D3;#CubSI2PQh4dyeqPlj$)(^nr_2=+ZGyJcP(wOW9|* zwuH4R60DZ=y=4KTk3P;&&)v${GqVKGL*~lf-ftQKpK*7FHV-JaOchWz(Ab^gtwjZv z^JBu=e?Zg(bdHp~njm+pdo76q6ylI34M@#g%N9Ec=u^%q$tJUy_G$N!jdFVWX3lp< zy3k}^aO9OEYB_u6Y}e2B=QE5tHZ$vcM~2Pl#!|c>42K+C}7$y{H z{dlZ=(tDX??F?I6nCC0_Tk;`w zAzL8~^tA?7Qz32(Jzvwcq2B^*rhgA62JxJvapDz0+6C!95O;9CSj?64Ni=oZEkz)T zK6~3T2KNsMS(}GURDF16hp$Gck9ISD{}C?ZV=wLpYX#qSjs!x~5yO)Z;XFZ%+rrNW zIQs1p)8}PMiQ_rRbkvIzVR{Kn;FdmH=BBk;YnNY%@I(QE;ja(Kq#V0t>sD#(APOW2DL+k}M>uW_pDJb+83pnSbK!8JKM9cYLZ@dUf()?Jx3hqphSJQji_&}h z!+E?<=)fYXkr5HNIE<=wd_{4*>9xCxF1LWS3X(ck|81- zTEzZ7t+MOz!K4U1AAn2>$A}RTWWC10yRbiJMHcW%1?V536Y?&dA1Lu2nKrXP9T>yL~7t}<*zlb2LUWh#`(#^^6^)&qi zCgVh#3I~CEGf_JdlzSVc^eOv|&2KQw{!HT`xI6Q9O(`&&x-s$3p zf-otbhY@jnbI*KAKCt*>^bF{*D99tk0xP<-O=p_x?;4&^vs|og+Y5|S{fQ2lPL1VQ0W-)a6YkYnKD@c2<&uwgTfMPqWX9nmZ{ zCRQqCp0CVzruIV)vm#_!0YI$zJ*gOvv^{3yjQiVaj&w&7#6seW24HA4#4M95#LtY) zSD#%R&$U0$61BAFb4=3#wB?%AbeNwYfRq?Nq3N2%uc0|6&8O9wV1+oJlg-iJ#QATy z)17n6`o4V*daaiwZH53@$3*fuyxa}4K1ZKFmCY>ZWs=Ra>gz1XPYyw(PXgVLIS~nB zH$>}&?4DVp1WUJewk!O8zGr(6x(zeED5?%FtGZLpHYQBRE^U=TL z;<$NL)ZfMP`!FGWy^~#JL6B!bF7X9++QsS7iKvfIm(ct3JuS(~%JH3E7GY;c6-C`N z$wHn>@rc0UiAgM{Jkx6V*z%wht^*yhjV zygte}-vdd#qjvkp#u56M%#0J!9Fq{%w{HiFC?f!L#Lc!d-cs@ zW2kTBe*|84gu_Q>oV{!>+VTAfo5}^wSS-IOrb`E6yB&3!?!RxZ9HYz8{AD$332gA& zWnu*D>%@1Kwzlm%_qRO+kSCq*mrL_$(56Z22}s)@?Fz~qC;v`=iPOV* zJf_?u!tFfA^4*FiV|IS19Ok$9C|Ck34)W^wAU@=+U4Z+^>cH>6-@-s@qAj~yd{3h7 ze_HUFWY00*Iv!d^oc&V-3r`E<@@L61?l@QAN=f&}V6lu0!m43E5>iZk=*Wgy_y6%p zej`Ib7RtQ-T_W*dmEN_az)J=4Bo900^>hIqNMmHbNd!76oslcf6pHcHVCaoQZ5~VAWFS`Elueu}{Od`vz*j1dF-ypF+=4OyrED0X91Ff2qSrU1mUmp=G>HQ>(`~Yg{x|;O9Kl!flu1cYx#P&L}Be5 zPiwNh!~)jZuDPnD>9{AYoOP+Nu=Q?%dF^Wa{<4aiim}xmht(56_{{xod=04MW|Ufo zeQMaQ&lYj^_R7_FZ~_fisF22t#S^r2WsEB(dkes^{vi+=dA@9Z6e2uj_%yg2lXt;wmUWZ)O;@`%Bh6Ig zXR?q8s6ko)4^=l)tyy-8*tqW4e&{DIh56G;nbyy<#eV^Fr z*83r8zuMPk8OvR-p!)q)OZJ#Ag7CRzfttHy^{wstrQkOIAn?$v;AF;^A@dyPN;tnXmDN+I=LGi5wXB*Nr*XfHcBpkQ0L9iVUaH4y)^GNrx9?#p3bi|c$( z5S*r#d61FLO$gA3d~fvmgwS_$>Uw-CWG|0X{W8Y+^!bXHg^;GkM$f||4(!tjA08l= z!ul@rtKUQG_M?8;U-)VE_Ma_fq&*_!816BT(K@n?m%c5?^C6Tivpzi|ZFtfmobtY5 z@|c8xMMq8~E;vOYcg^dmg7>PqlJX;L;>lS_X*(g^vZCgF+X&E>dQ`v6rA-J7Ef*)(yf z-#na;7KaOT*8dlBn+8pAFx9C+;}U!&!hJF#F`fDRsuI>f^VGeo&sg_K^=q-Ccg=`t z8KR87l{UKu^`1AXbzy!L>thG6ZePbuk`@$Xfw)8dbe-2w0oIF{fVuoX7B}0oA;_ls zcZVR&*N(p0F);gyY9P!uZ-S+Yv3?r zU&r&o8Nc7zsyR3(g$DCW5hlSMEzkB${N`UNMN_o5zAv5gyX%wFSmw?*m0bTHih>XH zil^z9lRn&90zDfUA6K+SjG;By#wE)aK)Agc6}_Z}2g>~wFJpYQ7(|8?lh4591%>Y$ zu+P>YN8g5FZMi|;&n|_wn?Tpn>fAcXRBAi-cWnzCHwPs`TCZ2Z`8C>)?(SWkQ#SN1 zE$<)qOh+Eo&u%3Z!HQdLkgcaW8Sns-_A?`W3+^KwEzA4AQzY%1f-~@(=WlSb1L`)Y zPfL)I{9r_XUtUOOZhuuY+RE1VTd41sHE7*8LiY*!|Nbt&4lnI;ZozP7#4((S`mTfe z@wd=Qr@1_7p7hc2Rb;0iuf^1TMg84JDadBteR@5QMBQvXcU)A^2YMypaDuza{H^2#fEdGcDj-zI9IrZ#Jmd#m5MrB!4 z9inSY3su2%x<|Fmvoppi zo27g})~+%Gxz{Wj*ag|45!YQgNb;m>V)U~-%jS6Xhrk8}_PI?pxUG@@rm;xbuNif| zw}LcWJUNYtNMu9z7)2&^ZxovE5ru4AVx13*J-Z>tdN3g+?MdaVEzFUqnFuk7Jq6~> z=X((__JJQkl<`*Yr#mzky+cr_AA5c9oM*1q5qz{L z|LS1r`}G`7+EVXEeQFiSV;=mI#Zfv>{AkxiWLwsd@K+4#dGGuB(7HLLP6le9=2q z;#L1BVQh7(;&}9|OL7SyW2-jd7@W?cH+7CsYx9dA@ConuM^%%GVK~~wDl1J)GrH7jzgJ_DPeIF z^?icSGS+l7KUUvQ%feJzP^Q=*)z9Mo$h?{_I?sM5ac^j5q+iMxg!fD|SB`0#xsPQL zHg?hc=n~e>t*`=KWcl`-3~P1UqW9rn?fDID00HI7O7R#4fs8a=O(<9mcBML*4=(Z4 zc0^_BdvD&!%*Yx?M*6SJ@5dA;AdO2;^GQbfr#dUnou1F+k{k~=2|F)lwda+e!Zy7T zKNaMJ(rNoR2sbA5;eiUNDWR^vA-tMK4_aEEU!~k!+-?8D{(Nx4H#d5W>UNUJ=KmHi zubu=*bQi@n0Gwyi{9NPrTY-?Upic8)a=Z!KY59Oin_f?W*EO$Uk+f$b$YD60Y`wCt zN*aSZk?Jh1nC-r_kqnOGa*A)W?K&Am_K5r+mPrUi_C#94jHr+&E5k{KAkxNGFTe)F_y#1|kN@28^S5<+nllWPI~L1~}aMIzfIgwH|$q{MyIT-|39#9%k$w z&?oOVVP{O=PjH0x(_cyg6Th>i4r_2t#P?%6OMOje&5I?jq1lUkC{5<`Gj)C^qhfJ{ zOw_Ike>X-zsdsmB=G)&Pe3^bIzA4!mfzZL3o>24=td?w!<~jMN38=J)(7Shp2CNoN z-!r?mjN=8?h@?9&q7fS-$S>;II*~qFz_I3JI<;S2rP)32$$N?~rAeRoSiL&_{7Vq- zPA_-mNSk&q9#XyV^=^ZV>9&~#d5xDVrCnJrbJ{dO6UJ1g?PG-0Fc8`Hwi|2cK)Os9 z0p6&-2IQ;ROR{UQYhD5RXB^abCBGjMwLNZ=zdlzW@M7@)&_qYcm$FYtM+90fsPyDh zIPkkvcszG6BmZbL^@)Yl)nw8;S?Dr0+4sju&!zMN+b%4Kx)}XQ8OFvv$?r#yU^11# znf%bS&1}yIgS&Tnpt-euGpZjFnSP(SJwIDrL-o2-5T1n&whiueSkmstz=P`93My`8 zw852&2&Yz)&pnhfg_D7y6=k4G?%$UtUZE-mx?K?+CC@7~CP2FZGGO zL9V(bp{ohnQU7r4T8~fNj>2aW_=98{>unR?KaJfyv81`ZqFHWs=zLETB_cjrW8(F6 z<<_X<3k5S7k^7qv8X;ka_TzHQ5AJNB{rK%!??Cz3T0JDcrxFhRJI~%eAjn#c0MY4K zgn24k&P6Upv1bhkRNLmHmqJ;3G|xo-1ZI}NaB{Wf*+!+c^V?9=k*P|y10 zXy-r4X$O_dbUOkeo|`2|rzDK=k-_)ZI`aB77qoA8dmYX%t=)Oy4PAluY?qx@r&yld zX>|rxjQly-oYloJ!TCwGX_9W+K?uk+kc(q=yvcFG-ohNy-QsDElmx#HuJzwVkp`C* zXzub!VX|S?)B{8z#nE0sCi|vFy9*%S8T5OQ(E3S!1rjXisXj0ilB zW=PYo2Bhz-Oz79_2J=(00Y+gY@T6U?rnKCq4@D1MaJSPLHIoNyTuWN+sm(m>o8{sA=4`F z+A?9yJqdvWZ0lMvhn{1~(H_aN)m_(Yz6~rI*NXe^Hdgn;sPg)&BB%3Ka=I8q@Uq7L zbE}9Jx`zGv83pg-KA1^W`e1m&YCs;K(haPwz%^w_sg_9FV>8e%6j-Yvu3j_{gSSHP z|7)sL=5aM*n)jhmrynzYvrhpF8LoG~kyyv7^v$;EX-41{fPLSxXqplNslG{eQzvU2 zk1d5aGRC=ZG46_qeJ+;nZ6n{0LyYlXhzJ`JWrW-5`$jRur*!Sk1poJTq0_gPRv{;( zC3rvC={Sv!CmN_#*V~|ne-x0XU=v5(FBOnKLv_0vVf`q5ZnDHJ`A%SMd*2LBF)KsX za0a&wmGNgb1V53m`CKrrdm{`o{;w9)VHYiQA_#3l-@Tm6Ph+z%47F?Sj*36)m+;+D z3GdEwy`wY}k-Ialo6%sJQ4`R25Tvs`uT@LY*q>UdJ#Ncf=~t|fnGy1!`n`^^ZY55%8M11>Ho|ACFpEG}6ClG~wlR=sX4SgM_xF5jI9YIqLZ_mi+m!fcBl1QtzF~hddLx?kHhAT!1!d;_2!MKDX!dJ8&T< zWf4rw_oi8*vSFGUv&qfkCftCQeP)bMVTR5A!>ER?2ZDR zb^hH14vUm!%lmS{M@Zo$dwXqx<&f1Q5!l<=Ba$-#eiFDPxgV40ek}qr7yQqSn3aW& z%@e^m_K&nLjQHr8*YRuq@&92gxN6r(*$c!>PBUFcxlD=wjz6DN=H9UsAlV|je;Zks zhSZ3i|C~i0_7c~i{(&H@SOunfXWz83iC1j8(yrymV}kWbH3Q%^OHH$Uj>V&|z~3}= zxOY`LpyK?qF|EfTAQx12ejK0h?$bQ;Y;@@VXiLBGb#2hqtXn%5DpnNY@MJ;(?X0%7 zUI4nY1X(7S7n5*nDDnsaS%s1?<30`KNA?#oL*9xAPY8*oW6|#~jGTs#+JS( ze_vvsU(!(fG$$39*G@IlhkKXESIrY!hsWoikBg}L$i~Zi83IV>5(s&526gSJP0W9u zYq3%S+f6F3%(Z4A;bGMr^owrXyEO3W*k)<)t{avKs1SSBIu&i>4$IhhH+Q^%1Y2?v zVv?*1vIQ*WF?vTDb$`4B8oVYxEGe%GEwaW5iTp<9$t)m5ol9-Z`mK(Bj|vgj6VLzo zh(q|{Mw&?iUy=+Up!#5`$hf#t-|tV=^qe9<=V*TG!2nr6roY|Z?*oJ9S7l^KHEj32 z(Fp9!mC2c3TB+~&Hrj7veFs#f5$PT_&w5DU7o#5k1>f2Za7H5tFT#m7RINRHEuV;R zoO`3r001BWNklJU`w1?+j#!)vk6g6sYbzgAAj@vcK?C_p$$eUg$3PL9P+Hh}g$0ue#b>3B7{_S$OTz;@cJCzoOz?FIAWB4p>I8shINGpo4M7cnj|uplGhR5o5wdJT{9?RV zL?;FiFoDq5W4DxLtgZrqV0hxg2OQY7uuGP*-ozH!>b*xP4n{A|-dFyCXrqj62}+99spGul+k??oqe477Df}#%0vnLX26wpXVtp@l z6ZAnry-Qt9OSJhM9x|xTPwe+=!_3o4pM&$s?DJ|kRkDJ#Crvb*ZX-ZC^KXb*X&cXu zhL(z9ijC&~-3&tIY#%1I6z9FbLmjfW?+#b9Fo`91kSs=8ZyT%q#@7Ke_n14#NjB_+ zXDf^Fe#P>_)LO|H8`Ky71Azv@S6aejI)V`AVG=!y&~>bZIy3Q$ODY1|(=+}{togvH z4%Mb|@XqBsN^Z@Ioi{;B2H3hhHOJGB1BElzvxjdc#dJY*KeImkB zJUfU=;b8Ht9}Z57%5%zS7WN9_#pYapqTf?)e;%_pO=wRda?h$_G@g;j zoJ64EkYskNJ*_p=gtsw%>vE>}&-ooa#bFZ}BJ67-sLjO9(7c|fF&^boJUQQ6-wnDzy9 zpw~WR89=WAPfG=V9BO+$LYg_?5$7G?Weh~d@@K*69nDV2Pi6GKJ_w-eK&YL0x1E6J zO=e(@LJf^*&YIBiy1DrK`!6T@LnKXlC8Tf0UHS~ndLu& z)5Yu?;Cn_BF@B>p?liP~|M-dB|ZhQCEdhx|eBNglEE=ycp;LUdj>(Z!;XpLPM zU{7A5f1kfW@a+ZF{{5$x|KIrL*4IIZ_5OBEu)RQlOS_^!S6`E&L%e4p%BN8x*Q+1_ z(MQ;Y6aiyo%EuRxN*bC6FMC{yx%S&3HVnfWXE3HvbMv+DK~ULmV}AiD!nKY*-`CsV zSWT_&vjg;J3jbS2_kqAs@v>av;y>H_9i74(=cNhsX;Kl^u84y1)Y7k)l4MGj z1cYV9qRoIro(?R63)L+)eS{}U|6Z+LjW-onb2iZBP#hZ(P?JC?7GgtV+`esQ^lz@L z@q87}yGNmRLxw|Ks(knipc9NBXUsOMr3wdYL*6dy7+2o6z>#PWp{$2-+0O`GP6S+K zzAF!auJ<+0_Vv(YPko&R);#HMRvNIxQyrt0$~VnE(=$T zAb>A|KrmG6sybl4#jMv@7e5k!(FC-y7`SSn^#Jy?GexhNWoMfIXSmv|ks0@=92d%< zM%m|YZOp_}#ynxE@7MtdZE3p$p5F#rM-o9` zair~cTNXoly5Tf}Ro9w0UH4bzycb^}qLHB93GiG_@$z~u3^2vN&o%OlaQ`VjTj1Co z!f?_=0+t1p4poN7L5Yk693=`WSlm>e(sW~6H`(@!OXfRJY+P(l*GHs6G&kXS!vHlE zK1*jjJ-GI{w4}hu(>>&k#BXZ-b4wV|SHAp_0dWHtMho{&0KT{VK18ygd&=b-?pkYA zB-V&QKp%w7E`qf#Sb_THOGyyC48$}ai9?nk#j9e~AxAleox)D06l4X~*xt8*{1}Y# zXZhN*5D`8C%g$n#queVXTuM#`5re#a7{Kcz>Um&ex$Iqo?4^ioP(jByueXo62cFJ& z+bZkH`=qUZXE6GD3k&zG7zkJM@$z5-2qom#)LjU6Ikb(1CueIVU_s-2z8?h|2-Hsr z4Wi`f9RA9G__(iJB3IZBOh(qm2-GF-qB#gyj z5asW?<6T(9aVh!Wd-mH}86$Pjf1pVKVG)Q3H-VTz?<~UEU5CY_Yytr^OO6TYWD@(o z%S(+cuVgY_vi<{m%y?JMfFEaY)ax$x!`Xc@&of*wyhQ;ovDH7%Nlbf>b^sl$jMrs! ztQicF%2&4FJVjgT9OYh@YqZHt`teFAAuFVU4TwiKHl>?e7m3AO!s>fR)@|3^(0v#y z3!4!fm8#Cs!f0F!8(t~v7V<#?=#h{I?*F9nv4V@)Ri@nTfqN<9usd!65#eiH>j3LP z_{n%KCaCj$#rD7n40V!Q?O`A@-;w6{8rcn=Tlm0fiShrX%uO^$iiGx|VAfF(ufl4d zNBn|10ratNJc$fJyhcojpUyDK#s%&+Yr$|yw9WW^Dxnkue|8GIQVAtCT@@q<_&W2Q z6-e|15YB;o`&SFRR&isd;5Os`Lh#kp&@_uzZy5WD0n0z7`nEt}uWK3AzK9Lpcb#R7 zX>SE>Og|F=It6s5T0fT)uvm8Qyj!jAe_&J1OXNc5E2g6c58Q6HJwK>vE*7)qr%8eE z4vpjQoB!LVs$V@(L>Um>iRJ3^#TYk{BLWhVgB@-VTf`2xVDD&+5VDm;y6hd5_Y!&b#M;6ara0tN9`J zek^zW?x$goTvecrMCn>&qnYVjR28I-I`T9-xnYKJDvS zbsiIN{9OW+!<(7sy$mxNPo6s?_dW3)Ldwv0(zCLIyKfP>#IW6gJnn1OUP*8 zPQyj6gUOi34;BeJ!}woM%&@!*r+Z{8waqXGX1|&keZDRuRbvMQLstev;YxoJfcb>? zKp;ZKhT?t38m|ii;Zb3Iy!G;y!k+P_dkyhi-{X06{1*w067-p`@Pu zQH+<0l_lE3RRqul#_zL3o0x~^M7Sj{y z9tY?F5T0_qdm&t%v-I|H1s^Tb8&w0l;#5C-S}@*?)l>J^{&{+9 zxOf7!1C8a^^N7c5)&zcib~Uos(og?9o22>Af8^EG5WsK( z=w>BGgcs;eM0_8`^j4KsrIQWNXEBYtcN!7H?XH}Ic!FZJXD}Ya@G1mSq2G)?T;X80 zE_K%X2b35od;OO)+J42>Rx|g_|1iRd_IIt_wn}UQ*=~d5h~0r2=9u>Lw}}JaR&5Fg z_r}QHJ`R;!XAP{r^s$Y>ClIOWhWAk7xoMxC0@`9OKzo|wc~ncCvalzV)NWVdP%lMz zSRa?C+99|t<$b)$2kx6K7rw3YWlqu|0l68Jmk6JxR6Aub9O0eA*v@7e zIs(n*T;dvY_$uc0QoCC~HrRdve12XJAd3nZ0yGXA}U=zS^yo2e}fQNVKf~3pO zh9T@cH5z>!w}zw@>=LBrvXSLEz4 z*j}Bghf<4T#=!W==`D!Ij97#+=uxFM1HoxAymnWn$!``o!Dbjk@DuRUpu3z$9zUulBaN)*~g$+K@D0?G-I->*d%Wmvwc4 zi3EC6K`K$o^=@Yh309n*d7f94r0HiFbForI$}}Q>#@`_(x(PJN`ObCzfkx+s3fy~9 zG9Xb$Kvqm!G;9P)zSzq~h>RLtwu0{Ayl)`cmuJ-4tb_;`=8)tT(-Z9X+fsO=g98M& z6)qfq-QNF85!}niPY7gei@g=4k2uZuP{4Iw1NTFiQKqlt;Jj03|7WXgU1+yq%iPo# z<1i>Cosx>BHaEF{!F$_nmD>=&nAbBl@L=KtLw{1MIKKb~{b zPgy;9zdD}Rv@!4Dw;}$9!1}tV9fmNf6R_OAQu%(7ag#Zm^KGKOL$RU>+hZ8thE5 z-8aATzWO6`bBe(z`4xcuO7 z>QNzKI^d0H>Ma+6cTwx2^7e#W)i=)5%Vg}x4+#hkbT9B?sQ_^6eAMAw6MPZA0|HKo zv9B%QAwVL*zm^32=z70hqftNIU>nEfAr}1FjIk-Eu;(WgIQ9$!b`P=P`2*8aSzX8P z`jSN15k9VHwc^b4{(0{3=+&?E=(A%k;ai8h%vT&`%7V{u5D{>`A@QmW0-=PELGe?u z0+n{WYY56jg(o6>#`Hkd+57G@S3}6VSk^N1UmrI|AFp z$gM$kH1b&>BXTz?flyiL;s_++DjSnQSO6lzbAt8IMP{wsZR8mofMM#cagPDL?0tWW zxKD?MmG0sU*YC07K6a6>yDHCF#xv1Mszart-FwvH2nkj`1KeK#i&$w6*1RS)PnBY7 z*Jih*yoR@=nE@Fc4FD(P7-O)??rG%tl=icJ__-SIdqaL?3b^(f!3~}x5n1k=AS{06 zye}hJ{z&#sD|f8VN!I(i)^Toi9U#>Rm~6gVmWj1+m%cfDz&-8<)XEQ0vk{R|H?qEC zvK!XtaT$^i;q@9c419Gw&^CU5&x5?jES4S2Zu9?M&hLLhK6?C5mgM6vm-ihIP*Q<_ zMPFOop0oM$xQ|t)o9EkT!CqN{fG!~Z+CtWA6y3*(v9V4thHnyZG-674#CcBUjMpo1 zI9oQ(37sI<$EKD~QxHTxP6ZDTxz&b8S7)R;^A+3ws7R=Pk4}J*m{bTWQLq6C zl70+{tir?COq1hU5Gdx;*ZZ`$IXl3@dj`=m0ADHg30LTY$IJvaqKw;6iTT07jC@Zg zctdx(dfOReN%N-IN`vg{Y>@`wGy$)w)zl}FhWSW?@*WfU7p7z_8!tqT9WYr*s)DSs%4(`R@#`ViwJ~jz-0vV zWbJ=j)V%Vbo%dTGLz0Q1gj*fqT* zhXkHv@R2iuxO|;MY~!@utm8><8+MnZ)tv$NKnMA%An}aXMMk3|LHLVdlfqV$>Igzp zZu@mX7*2rUkGZbV@2O%b1|}2eUGtW=1)D)pQky+lye2M!>F@xxlmh%!Fkv)Sa-H`T z)IHSojpdE;d>#|KcQ_m$%v6t@=J^NT5IxZMe8*p3|Fpo zoKLFduaqP+gw3&fdiYNFSTQ9!*lg7mD6p~u>^SH2Y-b2kTV5@ z_plsU$%c+p3|ZADm2x7rCXlHHiI+ngu!HK!oe7H&3k{hkiO0Q31vCxeaeh3)(S0&TKXWwPp^cwA+@-6Q_KSsaBN^sC1GX9GCF854(wBJm?Ja z&+}izhife!@ki0BZ(vxo^Q48L1l!0Mz3g!6C?03+Y=A&vsso`46Uy?X7x-3|@i;Pe zuUjPva^A9tfHpF7VvA!jLvn4P4p(g!bhDXfB&at#UtVF8LY0Sa|;hFZ+*f% zmqbB#K31>+Ng^E=F~N#|^wl*zCgM8dvJ|a?jk&#lo)Z#g6lO+!s}=GFkd-P%2(vqL zU8IeJq?w;Esj2R0)T0BGyG6p~vde`m8o6$%W+Ga5ymWW4a_t%Kt`Qrj<7GAsZh@rj z6RKf*X3xt8#>DG{R~#yY`*4Xjp@a)vK)4@xpFnU%EVkmX5D`w4#I0FzuT}KQJU0)4 z|07iUjn5pv2iVF#ZF@e~)u$GWcD^CtX`jA7!1!J^Dp;G0E=W!#>c)WmI3Zpm`JjrTK;NG9WlE`a$iP;+yQMA^O&jfNLN-v0rl*Z2x$4J25{2WFDrJ zf1O~1eTo5Rdk`j;YDN>pF~;Z(M?1wyq+pD1o;U0s-za#n#vWnjXR!p~{;+#&?|@1G zgzipal#>iEMFL;^=lJvi$9vx03&P(Z;8tFl8CgT=Ao%#T`8+V70ce28@B*Q6b#}`+?uIe#?CyUk9)n`%x~*;*YArI#p36Mz^y0TWmRuP`zXNl zdjEU_+3hzAisbJrRLEbzK;duWKI1Upmk27Dh;jo`5?!g&4&(u>L zzjqJ-dRnrqgd+u95n?|)Cj9tDAznsHJI(V>4xL}7%lKts0&ZTc_44yJ5I|;ZmzB1D zb@29aZQ7*&$LR0Rv$?C`5K;vT(b`(L4WAFx3}~%}c~bCNBcJzG#IU)n1iEXiZ+`eX z4zkVh=#(=tA8W$L+d;V0E=BMmnCRDR-q(EkaI(YO#XWk)&Wa|#lksj3fbgwDrGnmu zv~9}%w!Uvvfc2h?ycK=QTY(R8mh-*cSXL&w?Ft{9%}5Qf)Z;q%D3MF*F9qKOfuYdI zYOiGqZoy9Fe#>~A!Yke}T*2GFzTmgD+nmoe1k~}Flda~n8L=C)ym`jKML1y~Q+YXnp`U}LDk;+3fO_0*bqRY&gw2+)e;224lJXJ+?aX)C;k%w*g;m$I*}7ifi=8j(q1-001BWNkl_w!VNbTKG1>W(D- zo&vM<2?58N1REN7^VF~ym%WY1^_b4qJ%1ml41vwxYRe^WJM;hHS;8N?Y-JRqWp{J0 zohKqBcwH9~Eu+{w{Z;NVHcokzJ`I5T8~h}%bWQg8OxE|d%5Cl;Y7_q}&`z<@7-JG? z_lxishQS$-X(^B*@x3{r|G}iHAX;{H6@dw)*GUDt2b!RvTGD0PYn_RD|g(DD6d?Wnt6MU&Ry4&HtS#6MXJXPW^7z z@Be}Y-{LsQr+=jhsKd!~E(nBu*=1kx;@3SgXVZHBJXfda_8QbUV{;OHTQ?}-XQtdi zI{Wa7`1@-6dYq79a;S58?fPg;I-pKoKd66jqJzc4MLW>DYLX}sEID0Y!@0z9r7w0gEq3Q~U;0kFQ z98gW>`@?nHRvknDUErU$fuGl?Q85utT^a9=3y9Z;fQWFNrPf5v1$n1%je4iJ@ZxL5 zIRZUuJWr7;hs*5!avIj(0=E5{bqQ6H>se~F>vs*aZ=Hbq?0s$Ex%I|%oJ%Fnx}ER0 zo)tX_RwMw&*cc1~2){Gx-P`=XC=iojNlJ<{Bak;{&sALlVYr#+&FuSm&V1wH^b9ED z$bu!k0}WNgy&wJaRbs>DF$tLU^u)&aMBjdJQ-QeDnXV*&`WY}iM)Aybdj_1WP~K9j zys@azocKBVbMmd2jL@+vsT-87@wWF_Q4r7d3|&WURRXm?QVfrV3X57!)v2yS3h`#h z{sl8UY$l^~O_iBOv!H=lDTByU&t?MXG8=rd&%Z*=>rb|h@yzI}{QRw4eYZ&_Iw4~y zo-tYv68sW-d2aS5nB!|q*=5df)x_9!9?{DFbLLaF0*h z1I+)WgB++^&30zW@7*Zwl(ryyOTIM79IzPRl??cA257s;rb6uDtr!TGFy?i72G)PF z87Q3P`rSv$_JZ5b@oXujCw-#I3}-!X6$gj;zzF~iV3u!dAJfZ%wyWxLZTloZg_D@nTxHW_40+dY~yI@i_WFj=Nmt zcH}if9Kr?!Lkb*zL}^}{M11&HI`6}tn<;<)-Z;-RM3=N97^{Jp8_jxN-1U!9lk@ z^?Si0H~f$AlNuf8U?!D`AABQTueT9Eqs4iahzKZ~H!ggdecywCQQ3UsRBubC5ipKV zVA<2JLf!RS@HfaXR7X{&y@Mld03IM1-n-@*ZC@1Ett-Bg&ig{pJAl8RW6f6G5HKbVh$LoBXgniu9=YoqwqH}4Ok1<+Tb zUr)>T{nk`5XB!pq^gdhJa$5WHwrCFKbKLEH6)}7^XqYQ}AGqvhOAYE8g*mF>pQnZo z4odlDcL$b}NL)26mV4Vuyu8gpr-Yan@b$UzE8$3~vG3(9_W(cd%?!Nm0>5xi?Auw~XLt#CG<|sRmh%+6pvE7A`KdU{75&3)*uW$b=8tQ3H3Z?=H zOF&M^Pefz+ch7D0s!R3P`w;;0>N<~1;iAM->7AQHkQ7cdlgjrb0r=idT)kzh+W7yXTk>(5T={4Cd)=jsIUFi6uPxoTnajob+kk+T60mw)4kj!^_~ynv ze&+WYM*zZ+aogXR!v(Nlv4)BiNIUg9RzeYTx0cIU%`4RJHhQQli!OJcW9rQFSExa29 z!lgo69p&_czV-Z~4uzab(a8h2kN1kAV3)*b@t3K4UBu)YUcc zo|FVfCjUnfd<&*%wv-8@;@ha*C7*3#5z5Q$y6(fz=uHPqys_zsgbFy2| z{xcv9R&M8Rvz_yp?OlQr*87(XSngJVUrzu(lVMX(7R))7PL(yEZ4A}CpQP;0$_T$- zuImhzm`hX;^|QRVY}dG@>r45PT^(!k_5!i5_ag1G1lsHX`cNQIyeb{A*@UPVkW_mG zSmv6n>CAjxBVs~8ts@;@|A=qc&nUQ>3pnp(@^fq<4lKK*sxkv_%i7;(xit}!BKl!WN7}mL9QBHA9cW128KS3ar^4zLpJ;&fuXb+({&#zkLT;A3u zA;U0%rb?;Yy-Ywe57YUoR6okYxj$Mim#t{)y+K&d7~79w_SBEqbKU|3DhB;G^V;^S zcQVf_1MK-8M+8lcI;yc?`M0QfVKy6pk`w^+xxjup(~QvW%=#^(Ta z$FrD{GRAHTbm8zc=erXbM)U2}>)jyJKRm8y486VYngtGs*T(y9aj?0cXzzo0;?aL7`JxZysLuFcQbd;!#^TqlALolo#61;6{yY^BI;}VxEaVF zbA~R%ilTZcd0fQxpBB$J>}r_%A%_?c4q;q0kgr;Sv)7!SikYF(sa6PDrme223jM;7 zjQ7Xq&`sAeSzXnOL(I()l5LbW%w&i_N5S{fgXOLke;EHK*)N6e&VZl@RM zZwJjd@9jS1vA?qJJjfP@d^MQn!~H_hDC-9?l?#LidW zZX@Cszu+&~@vP$4(MV8ku|0myQYM2I)?Q&B`#jb5hvj%jl;>ldDwXYQ<*yXf)e(j? ztua6?-O?S?u)eqby=(5iArRgKb`c0IY-P7{Rhigu_=T}=j|b>kt?T+Wf}H0!SNfk~ znYR;Wjt-2leFx*}JFgu>wza@k*Pi}mB)l0OA&eukFtHeC{kY_B zU4G@QjlFH}akQ|GbIf_;MQX0)p4T7k#C1)^{I<&2BdEBcHu`!1=oZB?qfH(2wa&g; zM$)gdaL|mb{e_I4{zkt(j|e@FLRZuFAd6{A&vRh+sO0=L1?YbXpHy$L!376 z4-(k()ewZ$Bg%~Z9#Jp~ILP&Tq2~Ip(@2a?j^T1{we$CMHJBfj6fiFFWggrIx8TYzx^aTMQ zhfB_Lj=P>wuT?4MY6R!Mq{_uO*y|GQ#5tQsx&+WV8`=PvYS0%8X-v!+hV9b6-*}JVn ztqng<19lw~2>`w5BuHKJbhHE4CSz|HF;M)+`>|&Dt<`o*TAf2=&E^nE?F7UVeo-Gw z*r>dd<0j@_a}yKK)ku|vE{24Q z%GJ*1oM4U zkP#VNCbBcj6CUoiJ>TZBt;tAFFy3I!Idxm!zph}cyJ!5?BF1H(e*ortq)w0e&(*88 z-@U!qT<-jRdBl4*in(E)_0EQi1oTf16Z#94oFc5?yl=-|a;|M1K0i9Cd@&du_#k@6ilJW9{cWuw_C=i0Kv@R`-Zm)3t zct56bRARufqwU>=p>Oz}H~t@xeRr*B!n>UnciskJA|B6}9XR+t;H(TB_Jg#BKaNFo2=+h7o2>!%19c1+BAYE&#I~3!J|%apFyr6chAy)6h4J$`Koo ze`6xz@Rwr#2@w<1SB9(OVL7;cK){$HAQAdAXE z`JT_XyGY%}2 zKV|Khcpj~MnK@POGx%H^epUg2c6j@=i{Ma&v*O}3w*s+EAP}DNt-r0qTUCFQ$uI$f zvhSC9%N?e$wvY13d$Q0dehdt&1Jm8F-D$wt;=QhA7$Ti^3BDOjA2tyVv$ugIYHc*& z)&GHJnnCS?b4`N#wxK$lf^+^-gxdpRwvF?o;b{oYd3lVCLchrB-XFQZfW*|;P>sOA zn>k3NAFOv_{inFu?c(LHpM(M3u5dRhKGBqA!Zmf9`%N@7;+tgt7GYA9?PAD{Zo07TJTNGwLm%a2tY0mre1!WlC<4ijScPxO; zAW%(sB}?48_vd;+|b^zR17?h{g%T;izcdf=jkZJ3DMcmz@ zFplXl5Tb{vV5(_#DHXw zq)$NwOaDgsr9>XdV34&GH@+Dt%t4N&WrU0eCY7|_MfjAm-$MW3%70Dn;04o#^_|dX zZzYqy_10gR8IZ5L;@(h!`TnawsvRF-wYyw9XTP_|xa^&8{x9kM_NlA>8JvDT&3IqT z-u7PZo8SsQV_T=`z;En*H#Q>NL2vK7*}(S%&?>V{TkM?&Gg4uH7qY7a_|b%PIN5N< z=Xp9$E;rCsF5jb3+pky*8otXZ_^k|s2Ycx9ym+ss_4!!z__i&l*GvAz0m180Eardm zlNfcoPW#e2pkD9>gliDS;JtmIa=j3p-mYhkr%K*ZJI3`@=DB7JeQd^6*XhkK*B7`o zfx~@Rjt~_6!}im>)z1Dd7u!KeL_ihi?}h?A4CV^euyYw}ulMkEUKP4wO@$!L^2`BYR!r!8Op%Fg1r+d*)SqcekA6womy21lnwum}EWSSqAi* zICHqm*N&q&aH;+GndblI-g-NPwFNsd;S0HtUNZ3ohzNZ>Zd+&T@9RqWyxeHsxC1y& zlfw>$bTkU~!G$DRN39eX5S&%Cfpw(MrhBDcf@&ibBnLUg*v@dhyEeJ`n-h?5!(D3m zb;pz8`r*gu7&gPXsBat3z97)Zu!QtuiiFWcf^W0&LkxSu8@4&<52s`c!&BfPrUn}Z z=laIwV8lIPdE3E$7)`F21gz@fLiMlUlym#STGatAQ@|k~JXM65O096S9&#HoNJ#5eYBc0dx zLf~Kn&HLyeU*^7bfkrAwKq4kU4=3Q3IBsuljA7GmqTSnqL$yw1L^?IQn9q?oQ1?!Q ze&$Tq2J{Cwb9a-L_Ey9&=7XV%m-{N_ZxF7Jdxk$mn06hQm(Xp{mFe5l>JhHs;lX`g z*u4Zf=OCaLKtxVyfKWFYg9JkD9E@=Df{G_XHx1@*n#?szXT2u#( z3kH-Z(8Q53AULT2oEEt#p_p5cs<_kNd1PRQKjiFvl1>9t;f9bC@C}2|Q=xwgJZg95 z&7aNF7HDVY`5K3Jp>d$eKDTERLy55EQ*UuUwsZEospk6(G4(2Z9c|cy8{VJ*Yy1}l z9{g^5J`?}C#X4JnP0NtMX{R$!L zj@8W!1W64dAXePB-nQuGB^do>svcpg`TuxhE|$x;|1Z>}Z)j`$pQ#CV@9?XqAEX!; z^dnGh9#Ql*2$PKGxcAFmhBC2t>~m5hT6Tg;h4%10HfyYuvx z9W@FFK?Hg;x8`>b4F?)NSHY8R`ue{WwvAKK<>P^J`PTbJR6f9fqf!Liwd`BosECV) z6U52q!`cRTeaeq!!1@jj{4Y_2X*&=I??(@pXJm+hP1)bq0rabz`P$+5J;DxyfOD=K zco5B)@7uHLnH~-oEESN}t~tG3)aP~CZ+5r5=)}nT1NgQHHXDzyX$t}Lu0Je3R|-6L zvkhr;1^&I0vUKpfDfoL#r$QTWiLFl__@9KV5xlBeJ#D@2l#njGV;`7s@2qsL^bjht_QSUxWe9#uR_F# zsG=E%S%EQ44@0cKHm_AKvrYgz8A;)eaO+IKfVkaD>ewi{YpUxdIfQ#TEcZPU5fhpH zQh>BCtMz$0ubv6P4Ck;~>VT1{>&6iC{Xd7k^qJgzYlAE}^abh@@ITG#AP~;o%6J#d zSNtdeygyQ$i|5=r?JTJjBVzLd?wiFAql2BtyNaFB83G1ee@SqjO;@D&88l48K86w? zaNL{L0RDEv#+0Of>YmpyjywiHFy8l~hwEa?9^+HVIdFLjY6PwXjF(EQtfLV=dCP^v z19$A0G6W?zvTPW=#d*KYBaOmGhV{0E-#Sdpk7gQ)sMBI(#H_$gHvrE`_OEpsRS6d;!1q|-h3NaV z&hJouR@0%g(OHibt=Woopcl@6DdasT3-e{!_Z@t1ILCP2$;4MVM{*CeN3+JALD#6i zSFAOhKHubi|7QfmM;V^Sx&@r~hAQN97HkFqgz@HlT*4*HPP3~=(fH`s`80o6^$J1^ z7YBY*QOCSUBG0w*cAt2fhiBire(w|WzS=8P`4=K}p}b$ZX$x#lWxpoG$t=E?JB*dx z(_Q*(K!`x-oWrUu!4|`-IdZdcR-W9zl#Gdy+)7}&W*r0q;e3ACF%e70CdsLNL`Cd? z%4@6ZVCx1`L)6y!68L?Y${KjxF8P|v%rj1=zGnV;p45fY7^zpX1M_ygi){>DeAFOj z=o-s_^qv(giTn0iQli6jLXhHg3um8b8PS>8ybzNtUHi^l);{@}_I73q=KaBV za6+>U2x`ZEvtUnE1q<}UpuyX8sZp%)pU{a#&>q59%7M#@hI51~qv=0-gjvtuYVFIh zegU0+WZ_58*yiAC_xiij+20KWfKC?Hu{_Ae%`kL-M@9Glez|a;&E7dd659eeh+7|-FU3Kjxz{BC%;(+`r z_-0cNEf4+n9SNjyX8%69KS`!W4gV5EpZyWFnATgGdIj#Y(8 zh?aO?liU42B77Ycl{~GC3f#`68gB$1_3QI5YHiK-sjqGfw;5GMw<&%uRp~|J`36oM z>qG(DjGG~}^J`eXO4me4b_9>^g$| zT^kOsswv>5!=`gk2$F-vOR(#hze zVPyUMGM5-~RE&WEc~4c0TRP?idbMKy!)?!7vLffu{TOae%Bu-&R1+i+rg3r`sf??_ zXQSVgx=HyTzug75HZd&b=)G@<)TaE@zgUEgpFwgd%WfmAaqE*TcpWcS{!w$jABY&Y zaJFxr3p5-qJW>0W3_(3jtU?E|B)N+Ho!v;-w8@e3HbrDa7JpAiv|^VhGMpN`zGagA z`H-FO(GX_^h#`SI1i~O|*e5H!yWDKst(N;^M&;`nP3Oq_5_zJPWTIz0XVMr1xcDN% zA*}r4?CPKYc)zzOs78rWpMnQXEvamBaE#au@5~e~pcO`+jtLulaflyrQ3!|=oG_~y zsNC0nDn2y7$ilP|2R6MWH=luF)=P13+5Iv^&?e8ftITg#yW4yOS>`|`{R%@@U!}|* zuKat4AtVKi##b8l$ekhTs3%|cx0r4qizjg)%D~|n#qpc=Mc)%Z9kXS>6u@yA0o!0i zI=@GdZxjJ%E8A<_&sI;i$0xa7EmAtDlC6HjX@Znn)RkaHZ}&@gM~E9T-pTr;&|U(w zS??q6=kc8ScNdtZsM0dGN5PRH>iZ=X^Q4ynxhqdN()%19O@6i!#>uEW$-1FUBynym zy9dApGzd!Iee8L+Idi-F1c%8{sDGY%pPFi33o2`CVTi+LOo*~0lnJ6z#`9tF<=%I1 z!o+d+JP^JP8CF=|pMq9qd4i$pzNgLFwc;)hx{V3i&qcr5DoM;C^{XA5k z{Rf~orI-?G?t=p@EM~qKsG>9P>x%o(a&EktGeeJgsc4LEM?(;mPl#doD&+ouNv_gT z_{97_G}3n7v*6P|{R|J*6__U}1_XU_ZxAv!xS)%2Zd|8HZk)doK&X>vhjZ23>+_tD zf)F@QymO*1)x>1KI{q_(1|`5_iIjwL*fbmv|F5~H!C2Z$=skx_T4Ewm#n`D zb=i4(`B)>i8Q_*RRgz{AWFyAf#&sp|7yFw#qBb5OfNGfKf<;F!;j_OUK*;97YuRrX z1e^2oeWjR-_}>?Wz_VR$d!JV%=i?m-T-j&=)j2B0{%dOLG5`P|07*naRR5iyuZgYw zc|ausKv|~pG-32^wqpc*YR}{J=x2|!1KL|q_fh8msd$wDJSzi}gKgy-GcSQMco{HR z0c>%CWEqyK?hDZouUH#geMr_58R)FY&$Yh^>cN8lvh{yS_IWP?DqCag8XWfj24yNs zB1JUL$kg=ZpX8)^d*1wW@+b%+oe+PUw-s>-NUUkk+(y<7 z1p_GmwAk-9^Lx#k#@_&KNF5xGa~SFFpTf=d>uBqL-Q8Z-?C+8C`@roQ2_GrXLhe*6 zsD$XWkbPySSC#NvTjd1A%1-XLZ9(=mbapV1I@7@s)Z133&bj`1o{+t%evSb0w+Z}4 z1pAH%O`v?p>n~by`)x@wLHDZT?F|~%Y4Nb@{2+(TSy(li^$9Uw8|@b~2eR`Vlpsw~ zJD*~Sv@2YM=RE^bJxv5Wx`nP|0#b526gE`}69xUw{9iQqMsIx|CWJ3@G`EYkz(@kl zbrS$3K}47$xi0q9xqd{q_4ASVp}Zu_9*B{S7zzJ|s_SikV{BY&dp;I~VczJ}+X?g> zf6Px3aH<89eL0e}G1=!PHuzPDVqe`qT%8L{6*|ic6lh{rszb<1MLUFWU@#zS)5QAz zrvNTvpo>}mG6ZhT5!5?Ny1dM2GINHH<@#TWZJce4?N>!u)D!gQ&G7K%L{Ua1peboV5zSfaaU#x4X;WZ+7bx0*tlv15bdWCPf&_$lnr_zV+?LL7I$AL zFw;whL}cqJ!FfMdqU_zA_w70FE%h_l_P~jSTk_DUw_X_H!kFoU`U$}7dr?fR zr()@YMk!!|Dp;D63bFkF70u0KLlGMH(JEf9S|!Qk)YMwvz09CpN2sZc5pZKz=5TxDr3~Y ziqTHX0DZeRAdG8!-u)0{zwE{+(+2W5xCH5Uz|3} zV->8y_S=zqxoTi^qvj1NoC{Ap!s?^fsO-d)F%Y{L8^sYhY#Rew!kF8=Kt$LP(YVlD z2mTF=A6^Yogo{|jna|sCvCw=^}p<uk^6+2!_?VfGfQ?NRUY zza6e&U&OeW_V>Hk@8=|Nu1<;SJfTaNjtAIz8)3J*AJ_rHjL@oy*7GRMumwGl&>6Et zYkfcaz@?f1KkmsN`{Q^eAo#B!c1)DO?o3`!Q<#(j0&&u{WsU|wNmB&vb^N%YkPmQf=WjHq?yj%zIpyjV8h==kY{x6kBNXnFY))w zc=jVJLOH9D>sw<@_+YxEMV3gf#$*_W^KWon`GdQ+9$Dte4{P%$iliAw^ND<4?D{?EuHB(d*ZXU26tcVWLbRV=>?vp?RQTUr@XZm2^@ zUA6c3^&DhCK${B$yN)zJ#fuBK`m3s?h0`8p!tqF1|LA)rX8(~%;{ebE5D}V3cH1>p zA@3-S?QUVdf7DKltP|;~X6NS{tITTn8~Nk!?DJHY3(2X`z<7T`<~ASX42UOV3>)v7 z9v%^%y&OsfD)8LkC(tJnH~KFJsk@d&_*9WHM*f4v4BStiz?AjL!nY4VW#G%41jm;j z0~uxiVqH3%>IavOY}=r)X?yhN>OKU(4xZO@V{^Jm zj0byhaA>SW9GSu2jAxV3`jSBa9sG~e)`KfCyV5=Zn&*LC(OCiKV6tG7Gr3FD&p;7mK$Ir8 ze}VJM9h-;_nhAV89#H6TKi%nn@&o?;qnOi|LB9exN^`xRrUz~lLJ*svm3kuPnkq2Z zTd`bOw~FMLXmRW%jYhh6OXhzfJH{h)Gi*%&>IB?s*4u^vH1#icwsmlSf{6FjmO=*P zD3Y<^INSC-lb`oG21C@F0P>fVt+e&y?T~Y{U!d4Bw`+iP8LzZSrrgA6_ouR9iNxnb z(&Z=F?*{-l-!{f3Vc>eR&-b^q!|W;@wnmLr$N3lY{o>GShxr$-pf#dqK(I-RE;N3K zk$~H**V~I~s*wf>LVT%rcGy-V!8P7fTuivSJ`dRVUn1iK3e93*Xz80j%9 z``oY)!JTWfkqW8Dedhl*n(N)@cVLMP{c)pWdk@76w`Kv>P(=s9eTbpfF(@P+@a(>- za+u|p`dq#*OA=*_bRVZ16qQ`E7&6EWQ-rpq|cn zCkQ5nH?q&wCHh_mAbe>AFed`&Iko;>uZ}}J4~NZ}YF(}5)?g!bquAw&>qw@Jt94vl z(pCI#w*;tjvflmvE5$M19^}lw*1t?+QN4H&m>KMHCtJtW=6qClzF(QEK?sYdyO00o zb?5|x0eRTHc*+B31tp4cEZ?Bh)lS&>3!p;^gmZ{AkW>Oly&R~G`%-9!0$OQ%z8Ijl zL)WP+9mM<0_bqnx|VW}-aCw^stp(c@{2!SfJ6 zc#;1-fXiX5igPUs>=#^Q>Ru8Nr!+~(&{W1Fq6RrnLU`RFe{cSpPXSTa>aTwlf*U&+A>yvAYn9v?!RKjK?b7vMZ;#uG`g@Rr)q0^!QdsMZ{g1 zznkAIJs>@F=B6ArLeFQyzL0qElkoM9m8t7@2VJ)Z z_(DldP70=@{BQVzx)Pots~>;8M13ztb1=!;S7BUM{b_d-km!^9e1qLMT=~tT*Jdq;U{w$&TbAb8$mp}!E zK6Cuui$r<%@R{rJpg9rWzSb1iZ^bt$##2kXoB*npeRr>2TC;yf%6OBjd@BNQtnu7k zM(wJTqLY%6ECcy@Qe{_I@j32d^dqJKpLjH&{a%_A=S);f$*bna!+@M5Sm2pW_oN7k-Ro0`I1AE=&}}@oZ2_VyGh9Xr zeV3<^`3gI~^Grj=7)8s+DIBB@9sJM2#Lf6e^M-m^pmJ3Rm_$hNL19LZzgxbKr9r@F zwmSC6rNdFfT*3;QvJd6&k`i9tkgBWvsPQwH96`;Q6TLez9D=BW&$gBw&#B8w}4%mqd)GaH&UORwDDV z$#Hw>GRQXF_ww}Hk8{r_y6Ej+NFo>Xk>}m{EH}3s!|SxO=lD{ij!^491tk5J0h<~Oe2M@PgYZ-z%T2sBI$K8)anH|TIbJjxHJ?hdgY zn&gbeM3^);qH_jRKJva-N=Q0aAG%?+v|t0`N!{#+?YYwBu1>qi7GAF?&uUzR_%}eA zXL5*9{4kn&xr_?_$Rj5EUZwn>63|NmH>YYoM1+A7@j&ppPv-aYk)$tq){EPJI*82z zm5|C;!anw?0pW0kpxoQGZz$)}=l{I6Z#5&7z*7}~YD(n0)%E)bMxIh2BHZtTOHT;q zat|3i#J4_ut>~*-n9X~l?fDcX*tu25YOAcF+Y!Tlcb~(KMmCj;doQ>uM0=Yo>w5C2`E zo_X&)z~dScdG1uI^E&O(poeL#FB534i8a12v4GL%uY!yNWu#$)hN602W8TW5u|i+w z0<_Qv?`em)ju(+Jwiex@KBQyL4+~Jo+nRChHn62&M>^mC1;W9$F@NchAT7|lM)#4+ zH<94*!ozYKi;g^e%f?4RTl+j$mumYFh;Xb0^S!Dh6px35<)ml`%qwB@s>VqV#zov> zDC6DHiJmc+r+~1JJ3y|Uvw2M7eVCzeIW+<)Wk5jtMp*ZcdB@xgk88n}Ngv0*GHp^O z+-1YH&FRD$)758FAK2B^fLEYK#{UvJ*6t?mw+BGLrT*SweuCVsUr!3F#&Z#uAsOPw z-0~bR6bsR(6M+jgt`(+B*wy;?hqiWD{U94z{WQ==?7V|)^)cg?V1(!0hqCc$XtDIT zdI!L-Hj-ubib|E_JjVMzc1Egd^m|u3@bSYlm(B9-tk<0)vxke=Ept&wBOI3$a^VM1 z+2?z2@%N_blbZNE#1Bw$nh>$)SJKFh{OsT%Y^vO9cOq*g~Q&3n-_)|oVzaFp$Rai4K6 z3DGByi(eef%y*PeA3Sr0R~Y-`rmKPi&#FlCXiR>I){qRQu z)&(S7w&tC~3=QLXO&?4S1py1q-xn#=JKI0+RtB;8qDyV*VikA{iNIsg!RG&Z{(1Yx zfQw5*5a_=%%Esvx^0qMW`3nw*0KZ4cs8F5gZT&I~$;rtOnU4l5_g+5iw>Kp_27H|Y zCS!iwS|h&|7?8Y5cq5W}uQ4~6H*#d7X|AE4B|#uG_q=bCfW%0~{z5jL>F$4jfN)lz zx|X}@Di#3ls2DdapLG5%n_fIFANP9ekAN^WZxS(6@C-Chi zl*aRG8gAA#+ER3~!G3stUbw9k+E2Dmq)!XNp7RUx`*QRx5D0tgSuZW~gaH{BHWKhz z>Sfk~FjFI;uvMd*28dmmvig*`Cy&kO|~0j^hH`^P(8x*Vg&_TLO9zMiPJ{e99jS;1t6-gSXyS<=U?n&p7+} z%=e)Vm8g$}d3$m8@~2VQcT=4nV&lN8xp;n_?{dN2+W7xWe&HaS0YUMIH^sXPizUf) zfx?39V$18+RmQRujq8)5N2IH$W?-uG_boa%vJL?xBMhJZ*v=*p7AYPetf;>gliawg z`S-sh0fg)P;l_vu^A`wc9znm|l8TLXqWqcg=fL!UWp4Dx1g}9A<|#T=8wJ;GpOhs*Q7VkU0F9f=Wfd z*4vkFbMO2HwJFe(X|MrVA9Ue0Rg?xaR+{-#IfM&uN;EEv&VK zFVis}y9jtyKL1e~4rHGGvD-nz6$1Eoker*|h#SAl3#A|Er&8B}!talX#x@9rZ_-!)|VB?B{Oya>@Sp%RV1Um<*>%5fNdnjFiO{+r#ty2T6D)q)MpE zUZkAF+CpiCIynwlK2X&#Sfz^Be@f@AN&w+S&#zvu+jwFd)w$hd9v2=7O!FUiJn1f^VA&BeA?q8`FhTOLZ;2Yjn7? zU1dDKNx*6r%&pmO}S&ray} z)YonSFA2XdW*Irt^OI{gKIt9lI|CIV{v-Q``K3S?J^9zI?ptA^`1lEc98S>-b&jM)L8(oGGNLgsf^* z(7An<{r*D&Kx=&t?1rJoFexl?zXkHrnKPo@f0h!^PI8X}edKw!$%I8~8%(}2pErr@ zU%F(Uhf*97roWQP_XpH%{y?20?RyoeedvjV9GM&gB0}AOYvO%(xeI}LOsVbbO7(UW z^rt}_XFArI|9cg!J$`Z=u>CRQUQjXOy{4@B{}bsl^HM}--j=&GuN(u?K55-Xv`aq& zw5vd@%B0_nK(@I*7Diw*d%8%cem8B;0eD;;xNLO>thPFgfIESRFeYxii6Q8gw7nf9 zjDCLvt_=vI$9?vAyQ+}orZ$rrI@_$ws;if`U-wA#^$5lBbeBD=6x4rlvuJIu;LO*P zvEk__0nTR}&w2lQ3}@vZjCUuq^Ioqow&iiqDOi~7K3iPF9vFqaBwD!E#m}MZe6w(w zT(l)1zvq+1J>K>q@(vAEf8!Wo^?C{xCa6NB_5WqT^DRq-<*fv8X1{3bpDTHjy@vh% z&bZg-N!kAXn6|?K_Xot|;(CobBc78_dG#+$|6$zbS@8LN(az>uS~-^NSjfW3$ht6__l#(^kh!fcA2J-z~ciH-}!6?sS62y{1zX z>k}8rT@>Ib|GJ)17%QFvEpyvU&5C>-9~u;fSQ)I`efiIbxNVE#^puy^Dp+{m_PbVr zqb(!?sFAUe6_Fc`J(0#ac*u4z$QxE3EE}(Y4ob&3KTSa&j+C<}C>L-&e6MpI^#$J` z+%dmXvcK!3V;%2FP`aGC%Fy%*-ERE=@b6{CFlm*2m+{nu6BP-&EMa?rw0d4K5D_k9 z+VBk4HYZ0zzs-(41&#@YQW_bMD(`c7so@)HY8rzc&l=&5D7;{4pCkoTl; zV|g+pAt5sIJA_mBt_-2J6NI0H_3vTrOK29Xe_dt9@RU-WV~h)~7^Fgm(QadrZO3l+ zSl$%YxwojUy*cGhV|e%?MFQ~L0PsRj5D{*)^;uT^lLa%-KivGY9V&xa_nf#r#M;>3 zCYeArS6|k}fIl5TMA#7KY{v@z_!^1JJ{C7kftsB4eX05VMq&BWbBve=H4uL11xm$T zI{R>swz?v>|HXSD#(7DowlBy9+>(*-C253?f6@!QX)#amid?>VD3xNSVsSe9hHrCR zO0~%Oo9CV9ODh8M-{~Do8|E#qzmD>wJ_p)hZ7yriZW*x<|@-JOyD;|=A zNpHFO%13$Tzl)SJJ9nk8PdR=@r)z$DBqRaB%xotj{)-xjJzX0_-0gcNHLmuHAy9vE zYJPDC=lyByv0fRry?yvMWx5F0nBXTe!VS}3zy3#!UxoUUt>2Suf&W%9)`-XEsl1H0 zsp>_80NBs`Z@Q93dqG~)s~tY^-}lgmwYRlb?%y`J92DSN*E}7TeeP^;t6Qqzd`Of` z1kQ``w)*st1n2KXo8YdKB(eW+K?N)C2-E}!JUpSN{W(FSna(QO^Xo{v5R#Eu9B?za zELQx~VI+-m5i%fHS|H#Ptlusf%Ek3P-yOrEM3RKUQQ_-&z^P8=kZeV0TnzFL0EvU- z>OF!0ste#+*1oxf@$MtR{(F|=cUaF?U2<6y0S9ECdt~wcL;D&ir+3|*$ADJ}f|j7O zg(O&O#p7>tERtkEuqpo;ki(G<2}FqYN5^Q$otpW@5)?mGBA5qB zZ3TE}*>a?Uz>UgY6f?P=9Q>BC*-z>-_Mr{Em4?X)pS7=KGUB}96!;JKzl^3_O@6Je|p780Apk%^>?%zBj*@{ z(9|tGh^YTJCUgkzDM5Tp=H$7}VPyV?=lj$g^XRu3gstX0d~MlrEg)d6@yv{H-!Q-) zb*SGS5zGy?+eS?}O^k59M7ATA_q#Wd*yUFww9>iRfTpRE99-=DJwe(_+<2*c7l#~k z=RA-cWn5chRJs_Da0{z$ZV;%FX#_OD6LYwE`)fP^KjnG9&^#YH>$@Zg0sxOB>S= z|MK@Kxx*Y`8_$Q{_BN`)^XnjoecUk!P%LoS%S6(Pp^SF}jsM+9C0>XE{+aY z8q8|*0QI>%2n0e6+x*M}=t3oLe$w!IF#Ft87G~RG)PQ&-OckqB@xg{HwRneDP}-YpaPXR_wGj^&~4nZ=LBJR=&GVOzc@)g?{V^dJU3#7=ptw! zaJL6ECD|iu`mcvN#IAA`m2Vlza05UV8(juZ{#CEQNfKTn4Y~J zRZN)W?GvnR6 zGwLDt>ToT82KQUXwB1toP#o{;xko##Oo>Dh7euLASt9#c+KP+%bIo4CP!(TJJ^%n2tVu*cR6ZdF1YbrzS3e>p__0|Ij?akt z`)v5R*grx78zpmJLSauc6eNzI7RLW!xi7)df1t~`>fHvNZMKom|7bvGA*80ViAe-d zy?FMa?Z%kiU<2ZqU zhvIK{3R1*?1YNXgy&=bQ2>|yb2?A_$u<=id)9`!-VXdUfM&$F`F+`iZ=%%O@5z{jz zd>wN`I7yIjv-p+DI)@n$Z6;!2uxEvo@EnZXQo#c4(8r)18cqLOf-n#1Wk9679$9@D9a;4r+#jY7A9KI`FR2?>jP|}8tD@p} zs3Eya!HqHgwLPa)1?btZ`29a|`9Vd+lNK5k7}d0@V9iGG12SqO&$N4?$wj05IE~(u zCP34UAA#XfL(;JCq}-HH=&XM_WC-3@#PwrVWc|NfU__rwDwfzH`2K59NyK*M`{F^= zUAy^wf6DlOl1Htpk9u2;ZO;P;PeRQe<_}ih*#Ky*uQo$ziFSGw2v0})IL90sG>>5Z zK+k5M=fpiv)naMqG@ds)dOpQCTnZN)Zt$Opo&W}|@_s)Pu`)Q=CqGok-T*tAySD-_!HPke_NHaV{~nH5 z7B>pL;!FuZ=z-1vM%aG0aj%89Ktxz!d6uFV6zlJ2{_hp3f$(DvI32GHhk61cWW4L! z2VgrXNQ<)<@!qx|0^<6b@H90RKMhrADzf|Jrgn|Twh(H^n zJ>Yc_czdJ3fP^AY@lMf|fIJnQ8`gKB5kDBZ+1l_4&obV1GdII#u@KnUuBZMrghUtw zoT#~e%l&7F{-16*JTvFUCNPT~r4#Gl*yW17se2aiBszfFRhd8{Q!31A(^zTi8 z+S-2ql+8PzJ>KW+eQzB?t(b=KFLiQ(D0(3NHhphyaes8A zQ&0UkGV}aq#0MsTpa>VuvK7x^x{sxyE!KbivqWuW}%J{HH4JCv{jJ(Q2#3UU|zkzFS!1 zRgYs}mix{2Ts{>1eo3MF)zGN+f4V-Wq)X@&yew~@uU@nx$mez-!caGi<4HRMk~ST6 zrrWm{&(=lkaEQJSCJt zx8~J&wxwa7?m&S7iA9Gy%>>LOZ~jW8ITCuiqQih(ffNy-r$pnGjPA1Cu5&!*umXI^ zded^d&y50ppd|tugpUHM6y7W^@wKVpq;-GjuQ3oIo)6IffnXAtM1->x56~kJC$Vx) zMD-r-^SulE{kQf!hlKCPGZHtsHh2$l!G3|{TpZ8K_h}X3Zrj}{Zu*AXHU>B2^aXZufLJG5509!jyW5!t0*3>r|$&@M5_vxgunKM z(9`~c1dul{yn7($8IY*!XAvQu^5vkl|NM>S*Hqw>JcICK>gFHxZDRN}Sc8NDbc1sL zpVS;T$e#%4hN&8>sT>2nn{jIYV3yr2Mrn!5am;mqb-s(YwHaq)GyU z?WtC=VX8O0n0sEglENQUi>`j`n>>De8to#Zb_9AIEdHC z=N%e`pgoiE?mgdfi;xt7vOD`coS*Lz8R8e?eDk~$mWUoNF3*hfvL;}g81H0O-F2JZ z)U?dQlfldO3y3@a+HKWNFA(d6q{4vQX*bAxq+lZuHvupak;9V}ZL@;g%`yF%?)mkJ za2{sqAjCPp#R;jO-#F?Aog7>LdxXWGgH)t^zeNJSm;Kh(AJ7Ls^vynRi}r#7 zm!<=Mt)O+!2XLdS#fE1kfv^ljgb%|oD&G?51V6RM`vUBnlQiwWS&w9!RETQy3)ya2 zb;6kGF{(92fj|%0*4yCh_d{gIbXWK@?PIg8K??X{1<&gm6EiqdrJXMXc~6Y6zr|b^ zIG@G9*qu^fqzV#{0s~ScykNx%ZxG{F;5u=cEfn0w0l%e$0l^-T)_(?K#19-39%p_i zs4%6me$dXu`_D~lVmLcYNlIhc%OaZVd3P|Q><*r7!)>anL{XmT3cMr@3F{1p-YgLB1qP(R zfTW&)*%~ptAJjC*^N?-{2-@ne{~mUGHxMGh4{RfRAK>uO;?@syl;KwgdG02+cDVXW zD!>Pm37ag{n@-We2UI*&7bu|Fj^Cv-szZ&i&9=@;WTKWI7O0&T5!|8=&IEjH?)`qb zx4qsVP%DW!S{M`Tw?^Cs_RM<%4fH|0ZB~`U;|c|}u(;E08qVR_C@>)E>1f43V69MK zKxEU+j5epoH@}4&YDK3GE{Kl;9tk zTACOg#{YJlWWO(x%eTR1i-0n&@%EGJ?;bG_0xPUG$~wojN`YAtods4p69hu#1oiLx zI)3*t$9=dR#u$z!L0}GnS4(U)U{polSfUO}XI((y7y>o$!GocaDwFH{n5bXW9Gp;r zxe0ZqZp<+W$eBnv1Ck;M$V1381|;G6%@qQ44k0fIXd*(lFp;%iG@tiDa`S(JzDVVE zZ#9mJ|V+95zuNe^B1tP*^ zO&bcgKNSpbaS^r${=dB|jk2P+!gqpb*c^lrS;YlBm%CX+oO@n(buG85Zr!@KmV2|!V{yt1@a%v#ni-dJfTJXY*Iikzlq>~p7B~v`AWwT< zz?a`}cDaK>(7`pl1|05Yhd&^49I({1F*Z3%c)@VcKr{FkW05dA1*CxntvYT;hfxa{ zGWFTzU>4Vdhf&to+TObBZ(9C@S?)Ns%%Be^OqCQ&Sbk=rt{>Zx-eoyUUuxQCcVzf8 z;XH|XVp7^JR=dn^E0X8mzesDp#xYLFoqUcC`gjAcIrbQ2p$dI!-Ww+B-hp+@kKAT` z2MU=5eo}ec^hoyAdusA466IxhMj-A0ci1N9j`oYu&{P{a8S5NXGTQOrGO%DF``~G1 z_x5V*S3nx+T3zV{tAMDQ@VQrQzO)L6V)_xLkAdlT6n@Z4ALBi~Z$l&t7FI!sH~(IQ zcoYy0*ev58q?1CPI6yAF==|6jse3az=GA9}6p!i^_i{pp>G41~SlxFULdXVpWy4V} zjN^*;9062ixFBBWjo-Df!Z-`gvhCsv?K63ImK?!CKf41GvjSpwKm_y0o}8i&RC+0< zzZIvY5&+cLjn6Vz1tE{}Cn8ij4SUdjOlBw;qd@>|6s9#lK?#(3#{qNr@@yWZkm0cE zc&Sg>!+4LxOip_q;{INjkW^s&rtyS?9}p>gX9&^@_Uq#p zqksxn0X`oT5MBuM7Vcq!8uS)0GmC_cMF6Ha>TtHoo$Q9dZjWzU-Ogau%-uT`;JqX5 zx!T%RDUYCql^k)74TV!N2!s*7ab_7T#Fr)7?+t@+1a;0|g9W2}zC9l;E{`D#6%c-g z)HlA4ekq2*_C#8lThoux6mks6JK5nk6R5dep-93*cC{ulI7c&cx)B82AfE0&SxN)R z`wE~nK78PX5R-ZLQ25;BvdUJQKmD&c{RgyS;rp;>{I?x6_p1z($z=)zpF3Sv)|5hL zFfXp|hyT4hzuiZ^xwf8oTTBSb^UUgad&KfxoK9D`%zf-@V{Y*9Wjy?GUl!FB=X->o zYCi65;&11qVG?}C7;AfEc-9I2-1j}!IRo};CZ?t{QE^g zj~L?r{V)NGPD^q?o@gx=zg?U>104)j?!*@eoJJ0a2raU6@l8$vnd(>RBILM0-!aGP z^HJo2W;VhY=jw1_h_Mk8Ch+D7hV6M=9GGs40M2hHm{1Pd3wvD9)b}34RgU*=8hFFJ zfbU&H=l#!+G=Pl+y2OKC@kjCet~0m)H&%NgN`-ZWYy4put6%n2|KG>>w#AEg90wvo z|3v-`c>4!uNeW`K{f}qz7b_lXGBPKO5gDT!bI>TBO`=u~o9) zm&G{ty2+(qpu@Sf&tl0|zrI|TqYLDhYpvHB%1dE!sohPfW|9GC8u7DjBU1#WRWb^} zh{*8V>w90J(l_mZq^(#STAQWjO#t^D8d3b4kuD z_LTwDIKuLBpv|5&4ksT4F_6WocFg=!<9GH z&dXd-tcQl;-2u5T;(_stOnK1nAg8TkFkBFJa4ZR~Cz_Z~^nIa`nZ*E8v-pBNrn$pD zFpzm;Cr6x1RIZFI44-yF$aFV_<2nSuBF zg7suvmd6p{>scNU=ijM%RT(rUu7d)>j`KV@_bw}Tv%@;x z`g-t~?5m53C%uNNR9*vx;g-3}gL+bE#nX8t41Y>JH<0ar%&&PKDw-EgbA>(0D}0U> zpKoqds%Wkcj>CI-cUj_o*k8lp(!iQ`k4O&aogKK&i;f<8lT|=+WBc|3 z+XivKtRN+zz|l|dx#JB|#B^{&&2!y|8QE-w!pNH-V0-HQUkdB8&cLH!@3_n-?-ZEC zTV=e@O6G-H(FhSUBG@q`0{xhvfx#hZ;X?6rA8V*ra(C#YBu!(jf0}dr9KemM{vYQ4 z_LXiccoW@Wqm(Kn?ExCCalZV6_qR_p^G?hLJ~xX8eW!@Wf)-@|oIc9Y7C1UpzXAg2 z%sfyIA5=i+cSxlDoKpe8SSy5DPy_!%$iebKf)*!xpHCbnm^V1BW>kWKPqj0q+Y~DS zpRy)+T$Po5t-^^UD#gmdS{Ch`9Kqti+4}NcAm5H-IQyb8g2rL9&^R0rpa-WT$s;l@ zdKb&l)Iy(c!wEC}EVo^h_FmuPxKGl;6n;@JG>rB5Ha_N6)r%eFzoP&jY|w`973s8y zq0zQgp?}-7j$wuTkb~wQPrUb+#Kq}v1+*koKK*iW$7;CUg>%5_8U+N$sG69skh_R& zw@TfU&?GbP*pXmTkA>|cd=Y)yU6fz6azxy_0dve4zg2Pb5gcAkf3-~8RXr#^hTe~3 zweAc}`8MW=^L${O2|QM#y|@!r*^9d>AJqom*+ zhJH@t#0ykE508co!kdQelw)($Z7|PV1tdPgs0f#~k317tW0jrQpi+hzOjoqEydiF3 z@HxhK7-0y*Zj19-;{zebE9QgnK+XH>*8E`&3;}_@7QB2RN9{s?*X zHECrX3gL8+Qb%WTF+0wRux*5`5@UL`dOp!gV?TTo@%;Q38Ha}RLHJQ0ZrzbX%D_mC zb82@5_#I~FrJy$2=Kr13NWv<41w`<;$RyQ*N5W!|N~mWQliV02O>(S0lFA9_Q+D`X zGwN5MbKK#FL>ru{uZ(-t;_v5`*A#fk*=KE`Y&V>UfS)|V>uIdl{(w7RBQ+hX3Psoc zJ4I-ru&n-^^o^pLJ48d$=leqdVU0lDR%O0F9^|8D9)suYigkA!)Fz_EtfMl^?X9am zWAaaqD2lkuZ(-&fsvZ<5Af^#Z7lU!TOCqg+C+y}tMA%54Pz!lIB`1z>pj{TzRySa# zhQa-Kw(SJq$i#nn{!Bo}@E>uDUq5C~-fW5eh2`J;?`Wgqe1Rmm);!~_2+z_&Vt&Kbe+mMi3qiF<>f*M-teGer18 z2|N7iKqsHS$xZ(GbsjH-Vy|5c_J)<}6%aHrm>8;Tr<=50ssnC?=jwhWmy=yIR~CDl z?DLrT<}3B!d~Ce+T4DxddwXCIveOf*DkeVT#C%N)4j@M!T& zI(SW*=>`2Hm0!6)`ya)KyFIBO&h==Y|9a=g@*zUIQ#7((6>W5b` UrvOg;fdBvi07*qoM6N<$g6mpWr2qf` literal 0 HcmV?d00001 diff --git a/src/raylib.h b/src/raylib.h index 0759c259f..f51a444e1 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -1545,6 +1545,8 @@ RLAPI void DrawModel(Model model, Vector3 position, float scale, Color tint); RLAPI void DrawModelEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model with extended parameters RLAPI void DrawModelWires(Model model, Vector3 position, float scale, Color tint); // Draw a model wires (with texture if set) RLAPI void DrawModelWiresEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model wires (with texture if set) with extended parameters +RLAPI void DrawModelPoints(Model model, Vector3 position, float scale, Color tint); // Draw a model as points +RLAPI void DrawModelPointsEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model as points with extended parameters RLAPI void DrawBoundingBox(BoundingBox box, Color color); // Draw bounding box (wires) RLAPI void DrawBillboard(Camera camera, Texture2D texture, Vector3 position, float scale, Color tint); // Draw a billboard texture RLAPI void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle source, Vector3 position, Vector2 size, Color tint); // Draw a billboard texture defined by source diff --git a/src/rmodels.c b/src/rmodels.c index 8afa3df57..966a8665c 100644 --- a/src/rmodels.c +++ b/src/rmodels.c @@ -3631,6 +3631,30 @@ void DrawModelWiresEx(Model model, Vector3 position, Vector3 rotationAxis, float rlDisableWireMode(); } +// Draw a model points +void DrawModelPoints(Model model, Vector3 position, float scale, Color tint) +{ + rlEnablePointMode(); + rlDisableBackfaceCulling(); + + DrawModel(model, position, scale, tint); + + rlEnableBackfaceCulling(); + rlDisableWireMode(); +} + +// Draw a model points +void DrawModelPointsEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint) +{ + rlEnablePointMode(); + rlDisableBackfaceCulling(); + + DrawModelEx(model, position, rotationAxis, rotationAngle, scale, tint); + + rlEnableBackfaceCulling(); + rlDisableWireMode(); +} + // Draw a billboard void DrawBillboard(Camera camera, Texture2D texture, Vector3 position, float scale, Color tint) { From dfd8055270691429076283f407d4176929f56e80 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 24 Aug 2024 16:42:52 +0000 Subject: [PATCH 040/208] Update raylib_api.* by CI --- parser/output/raylib_api.json | 54 ++++++++ parser/output/raylib_api.lua | 24 ++++ parser/output/raylib_api.txt | 238 ++++++++++++++++++---------------- parser/output/raylib_api.xml | 16 ++- 4 files changed, 221 insertions(+), 111 deletions(-) diff --git a/parser/output/raylib_api.json b/parser/output/raylib_api.json index c4ce91e87..dfe37e2fe 100644 --- a/parser/output/raylib_api.json +++ b/parser/output/raylib_api.json @@ -10366,6 +10366,60 @@ } ] }, + { + "name": "DrawModelPoints", + "description": "Draw a model as points", + "returnType": "void", + "params": [ + { + "type": "Model", + "name": "model" + }, + { + "type": "Vector3", + "name": "position" + }, + { + "type": "float", + "name": "scale" + }, + { + "type": "Color", + "name": "tint" + } + ] + }, + { + "name": "DrawModelPointsEx", + "description": "Draw a model as points with extended parameters", + "returnType": "void", + "params": [ + { + "type": "Model", + "name": "model" + }, + { + "type": "Vector3", + "name": "position" + }, + { + "type": "Vector3", + "name": "rotationAxis" + }, + { + "type": "float", + "name": "rotationAngle" + }, + { + "type": "Vector3", + "name": "scale" + }, + { + "type": "Color", + "name": "tint" + } + ] + }, { "name": "DrawBoundingBox", "description": "Draw bounding box (wires)", diff --git a/parser/output/raylib_api.lua b/parser/output/raylib_api.lua index 3a9e2f04f..933b2c704 100644 --- a/parser/output/raylib_api.lua +++ b/parser/output/raylib_api.lua @@ -7213,6 +7213,30 @@ return { {type = "Color", name = "tint"} } }, + { + name = "DrawModelPoints", + description = "Draw a model as points", + returnType = "void", + params = { + {type = "Model", name = "model"}, + {type = "Vector3", name = "position"}, + {type = "float", name = "scale"}, + {type = "Color", name = "tint"} + } + }, + { + name = "DrawModelPointsEx", + description = "Draw a model as points with extended parameters", + returnType = "void", + params = { + {type = "Model", name = "model"}, + {type = "Vector3", name = "position"}, + {type = "Vector3", name = "rotationAxis"}, + {type = "float", name = "rotationAngle"}, + {type = "Vector3", name = "scale"}, + {type = "Color", name = "tint"} + } + }, { name = "DrawBoundingBox", description = "Draw bounding box (wires)", diff --git a/parser/output/raylib_api.txt b/parser/output/raylib_api.txt index afa9b525d..94562d66a 100644 --- a/parser/output/raylib_api.txt +++ b/parser/output/raylib_api.txt @@ -984,7 +984,7 @@ Callback 006: AudioCallback() (2 input parameters) Param[1]: bufferData (type: void *) Param[2]: frames (type: unsigned int) -Functions found: 573 +Functions found: 575 Function 001: InitWindow() (3 input parameters) Name: InitWindow @@ -3955,13 +3955,31 @@ Function 464: DrawModelWiresEx() (6 input parameters) Param[4]: rotationAngle (type: float) Param[5]: scale (type: Vector3) Param[6]: tint (type: Color) -Function 465: DrawBoundingBox() (2 input parameters) +Function 465: DrawModelPoints() (4 input parameters) + Name: DrawModelPoints + Return type: void + Description: Draw a model as points + Param[1]: model (type: Model) + Param[2]: position (type: Vector3) + Param[3]: scale (type: float) + Param[4]: tint (type: Color) +Function 466: DrawModelPointsEx() (6 input parameters) + Name: DrawModelPointsEx + Return type: void + Description: Draw a model as points with extended parameters + Param[1]: model (type: Model) + Param[2]: position (type: Vector3) + Param[3]: rotationAxis (type: Vector3) + Param[4]: rotationAngle (type: float) + Param[5]: scale (type: Vector3) + Param[6]: tint (type: Color) +Function 467: DrawBoundingBox() (2 input parameters) Name: DrawBoundingBox Return type: void Description: Draw bounding box (wires) Param[1]: box (type: BoundingBox) Param[2]: color (type: Color) -Function 466: DrawBillboard() (5 input parameters) +Function 468: DrawBillboard() (5 input parameters) Name: DrawBillboard Return type: void Description: Draw a billboard texture @@ -3970,7 +3988,7 @@ Function 466: DrawBillboard() (5 input parameters) Param[3]: position (type: Vector3) Param[4]: scale (type: float) Param[5]: tint (type: Color) -Function 467: DrawBillboardRec() (6 input parameters) +Function 469: DrawBillboardRec() (6 input parameters) Name: DrawBillboardRec Return type: void Description: Draw a billboard texture defined by source @@ -3980,7 +3998,7 @@ Function 467: DrawBillboardRec() (6 input parameters) Param[4]: position (type: Vector3) Param[5]: size (type: Vector2) Param[6]: tint (type: Color) -Function 468: DrawBillboardPro() (9 input parameters) +Function 470: DrawBillboardPro() (9 input parameters) Name: DrawBillboardPro Return type: void Description: Draw a billboard texture defined by source and rotation @@ -3993,13 +4011,13 @@ Function 468: DrawBillboardPro() (9 input parameters) Param[7]: origin (type: Vector2) Param[8]: rotation (type: float) Param[9]: tint (type: Color) -Function 469: UploadMesh() (2 input parameters) +Function 471: UploadMesh() (2 input parameters) Name: UploadMesh Return type: void Description: Upload mesh vertex data in GPU and provide VAO/VBO ids Param[1]: mesh (type: Mesh *) Param[2]: dynamic (type: bool) -Function 470: UpdateMeshBuffer() (5 input parameters) +Function 472: UpdateMeshBuffer() (5 input parameters) Name: UpdateMeshBuffer Return type: void Description: Update mesh vertex data in GPU for a specific buffer index @@ -4008,19 +4026,19 @@ Function 470: UpdateMeshBuffer() (5 input parameters) Param[3]: data (type: const void *) Param[4]: dataSize (type: int) Param[5]: offset (type: int) -Function 471: UnloadMesh() (1 input parameters) +Function 473: UnloadMesh() (1 input parameters) Name: UnloadMesh Return type: void Description: Unload mesh data from CPU and GPU Param[1]: mesh (type: Mesh) -Function 472: DrawMesh() (3 input parameters) +Function 474: DrawMesh() (3 input parameters) Name: DrawMesh Return type: void Description: Draw a 3d mesh with material and transform Param[1]: mesh (type: Mesh) Param[2]: material (type: Material) Param[3]: transform (type: Matrix) -Function 473: DrawMeshInstanced() (4 input parameters) +Function 475: DrawMeshInstanced() (4 input parameters) Name: DrawMeshInstanced Return type: void Description: Draw multiple mesh instances with material and different transforms @@ -4028,35 +4046,35 @@ Function 473: DrawMeshInstanced() (4 input parameters) Param[2]: material (type: Material) Param[3]: transforms (type: const Matrix *) Param[4]: instances (type: int) -Function 474: GetMeshBoundingBox() (1 input parameters) +Function 476: GetMeshBoundingBox() (1 input parameters) Name: GetMeshBoundingBox Return type: BoundingBox Description: Compute mesh bounding box limits Param[1]: mesh (type: Mesh) -Function 475: GenMeshTangents() (1 input parameters) +Function 477: GenMeshTangents() (1 input parameters) Name: GenMeshTangents Return type: void Description: Compute mesh tangents Param[1]: mesh (type: Mesh *) -Function 476: ExportMesh() (2 input parameters) +Function 478: ExportMesh() (2 input parameters) Name: ExportMesh Return type: bool Description: Export mesh data to file, returns true on success Param[1]: mesh (type: Mesh) Param[2]: fileName (type: const char *) -Function 477: ExportMeshAsCode() (2 input parameters) +Function 479: ExportMeshAsCode() (2 input parameters) Name: ExportMeshAsCode Return type: bool Description: Export mesh as code file (.h) defining multiple arrays of vertex attributes Param[1]: mesh (type: Mesh) Param[2]: fileName (type: const char *) -Function 478: GenMeshPoly() (2 input parameters) +Function 480: GenMeshPoly() (2 input parameters) Name: GenMeshPoly Return type: Mesh Description: Generate polygonal mesh Param[1]: sides (type: int) Param[2]: radius (type: float) -Function 479: GenMeshPlane() (4 input parameters) +Function 481: GenMeshPlane() (4 input parameters) Name: GenMeshPlane Return type: Mesh Description: Generate plane mesh (with subdivisions) @@ -4064,42 +4082,42 @@ Function 479: GenMeshPlane() (4 input parameters) Param[2]: length (type: float) Param[3]: resX (type: int) Param[4]: resZ (type: int) -Function 480: GenMeshCube() (3 input parameters) +Function 482: GenMeshCube() (3 input parameters) Name: GenMeshCube Return type: Mesh Description: Generate cuboid mesh Param[1]: width (type: float) Param[2]: height (type: float) Param[3]: length (type: float) -Function 481: GenMeshSphere() (3 input parameters) +Function 483: GenMeshSphere() (3 input parameters) Name: GenMeshSphere Return type: Mesh Description: Generate sphere mesh (standard sphere) Param[1]: radius (type: float) Param[2]: rings (type: int) Param[3]: slices (type: int) -Function 482: GenMeshHemiSphere() (3 input parameters) +Function 484: GenMeshHemiSphere() (3 input parameters) Name: GenMeshHemiSphere Return type: Mesh Description: Generate half-sphere mesh (no bottom cap) Param[1]: radius (type: float) Param[2]: rings (type: int) Param[3]: slices (type: int) -Function 483: GenMeshCylinder() (3 input parameters) +Function 485: GenMeshCylinder() (3 input parameters) Name: GenMeshCylinder Return type: Mesh Description: Generate cylinder mesh Param[1]: radius (type: float) Param[2]: height (type: float) Param[3]: slices (type: int) -Function 484: GenMeshCone() (3 input parameters) +Function 486: GenMeshCone() (3 input parameters) Name: GenMeshCone Return type: Mesh Description: Generate cone/pyramid mesh Param[1]: radius (type: float) Param[2]: height (type: float) Param[3]: slices (type: int) -Function 485: GenMeshTorus() (4 input parameters) +Function 487: GenMeshTorus() (4 input parameters) Name: GenMeshTorus Return type: Mesh Description: Generate torus mesh @@ -4107,7 +4125,7 @@ Function 485: GenMeshTorus() (4 input parameters) Param[2]: size (type: float) Param[3]: radSeg (type: int) Param[4]: sides (type: int) -Function 486: GenMeshKnot() (4 input parameters) +Function 488: GenMeshKnot() (4 input parameters) Name: GenMeshKnot Return type: Mesh Description: Generate trefoil knot mesh @@ -4115,84 +4133,84 @@ Function 486: GenMeshKnot() (4 input parameters) Param[2]: size (type: float) Param[3]: radSeg (type: int) Param[4]: sides (type: int) -Function 487: GenMeshHeightmap() (2 input parameters) +Function 489: GenMeshHeightmap() (2 input parameters) Name: GenMeshHeightmap Return type: Mesh Description: Generate heightmap mesh from image data Param[1]: heightmap (type: Image) Param[2]: size (type: Vector3) -Function 488: GenMeshCubicmap() (2 input parameters) +Function 490: GenMeshCubicmap() (2 input parameters) Name: GenMeshCubicmap Return type: Mesh Description: Generate cubes-based map mesh from image data Param[1]: cubicmap (type: Image) Param[2]: cubeSize (type: Vector3) -Function 489: LoadMaterials() (2 input parameters) +Function 491: LoadMaterials() (2 input parameters) Name: LoadMaterials Return type: Material * Description: Load materials from model file Param[1]: fileName (type: const char *) Param[2]: materialCount (type: int *) -Function 490: LoadMaterialDefault() (0 input parameters) +Function 492: LoadMaterialDefault() (0 input parameters) Name: LoadMaterialDefault Return type: Material Description: Load default material (Supports: DIFFUSE, SPECULAR, NORMAL maps) No input parameters -Function 491: IsMaterialReady() (1 input parameters) +Function 493: IsMaterialReady() (1 input parameters) Name: IsMaterialReady Return type: bool Description: Check if a material is ready Param[1]: material (type: Material) -Function 492: UnloadMaterial() (1 input parameters) +Function 494: UnloadMaterial() (1 input parameters) Name: UnloadMaterial Return type: void Description: Unload material from GPU memory (VRAM) Param[1]: material (type: Material) -Function 493: SetMaterialTexture() (3 input parameters) +Function 495: SetMaterialTexture() (3 input parameters) Name: SetMaterialTexture Return type: void Description: Set texture for a material map type (MATERIAL_MAP_DIFFUSE, MATERIAL_MAP_SPECULAR...) Param[1]: material (type: Material *) Param[2]: mapType (type: int) Param[3]: texture (type: Texture2D) -Function 494: SetModelMeshMaterial() (3 input parameters) +Function 496: SetModelMeshMaterial() (3 input parameters) Name: SetModelMeshMaterial Return type: void Description: Set material for a mesh Param[1]: model (type: Model *) Param[2]: meshId (type: int) Param[3]: materialId (type: int) -Function 495: LoadModelAnimations() (2 input parameters) +Function 497: LoadModelAnimations() (2 input parameters) Name: LoadModelAnimations Return type: ModelAnimation * Description: Load model animations from file Param[1]: fileName (type: const char *) Param[2]: animCount (type: int *) -Function 496: UpdateModelAnimation() (3 input parameters) +Function 498: UpdateModelAnimation() (3 input parameters) Name: UpdateModelAnimation Return type: void Description: Update model animation pose Param[1]: model (type: Model) Param[2]: anim (type: ModelAnimation) Param[3]: frame (type: int) -Function 497: UnloadModelAnimation() (1 input parameters) +Function 499: UnloadModelAnimation() (1 input parameters) Name: UnloadModelAnimation Return type: void Description: Unload animation data Param[1]: anim (type: ModelAnimation) -Function 498: UnloadModelAnimations() (2 input parameters) +Function 500: UnloadModelAnimations() (2 input parameters) Name: UnloadModelAnimations Return type: void Description: Unload animation array data Param[1]: animations (type: ModelAnimation *) Param[2]: animCount (type: int) -Function 499: IsModelAnimationValid() (2 input parameters) +Function 501: IsModelAnimationValid() (2 input parameters) Name: IsModelAnimationValid Return type: bool Description: Check model animation skeleton match Param[1]: model (type: Model) Param[2]: anim (type: ModelAnimation) -Function 500: CheckCollisionSpheres() (4 input parameters) +Function 502: CheckCollisionSpheres() (4 input parameters) Name: CheckCollisionSpheres Return type: bool Description: Check collision between two spheres @@ -4200,40 +4218,40 @@ Function 500: CheckCollisionSpheres() (4 input parameters) Param[2]: radius1 (type: float) Param[3]: center2 (type: Vector3) Param[4]: radius2 (type: float) -Function 501: CheckCollisionBoxes() (2 input parameters) +Function 503: CheckCollisionBoxes() (2 input parameters) Name: CheckCollisionBoxes Return type: bool Description: Check collision between two bounding boxes Param[1]: box1 (type: BoundingBox) Param[2]: box2 (type: BoundingBox) -Function 502: CheckCollisionBoxSphere() (3 input parameters) +Function 504: CheckCollisionBoxSphere() (3 input parameters) Name: CheckCollisionBoxSphere Return type: bool Description: Check collision between box and sphere Param[1]: box (type: BoundingBox) Param[2]: center (type: Vector3) Param[3]: radius (type: float) -Function 503: GetRayCollisionSphere() (3 input parameters) +Function 505: GetRayCollisionSphere() (3 input parameters) Name: GetRayCollisionSphere Return type: RayCollision Description: Get collision info between ray and sphere Param[1]: ray (type: Ray) Param[2]: center (type: Vector3) Param[3]: radius (type: float) -Function 504: GetRayCollisionBox() (2 input parameters) +Function 506: GetRayCollisionBox() (2 input parameters) Name: GetRayCollisionBox Return type: RayCollision Description: Get collision info between ray and box Param[1]: ray (type: Ray) Param[2]: box (type: BoundingBox) -Function 505: GetRayCollisionMesh() (3 input parameters) +Function 507: GetRayCollisionMesh() (3 input parameters) Name: GetRayCollisionMesh Return type: RayCollision Description: Get collision info between ray and mesh Param[1]: ray (type: Ray) Param[2]: mesh (type: Mesh) Param[3]: transform (type: Matrix) -Function 506: GetRayCollisionTriangle() (4 input parameters) +Function 508: GetRayCollisionTriangle() (4 input parameters) Name: GetRayCollisionTriangle Return type: RayCollision Description: Get collision info between ray and triangle @@ -4241,7 +4259,7 @@ Function 506: GetRayCollisionTriangle() (4 input parameters) Param[2]: p1 (type: Vector3) Param[3]: p2 (type: Vector3) Param[4]: p3 (type: Vector3) -Function 507: GetRayCollisionQuad() (5 input parameters) +Function 509: GetRayCollisionQuad() (5 input parameters) Name: GetRayCollisionQuad Return type: RayCollision Description: Get collision info between ray and quad @@ -4250,158 +4268,158 @@ Function 507: GetRayCollisionQuad() (5 input parameters) Param[3]: p2 (type: Vector3) Param[4]: p3 (type: Vector3) Param[5]: p4 (type: Vector3) -Function 508: InitAudioDevice() (0 input parameters) +Function 510: InitAudioDevice() (0 input parameters) Name: InitAudioDevice Return type: void Description: Initialize audio device and context No input parameters -Function 509: CloseAudioDevice() (0 input parameters) +Function 511: CloseAudioDevice() (0 input parameters) Name: CloseAudioDevice Return type: void Description: Close the audio device and context No input parameters -Function 510: IsAudioDeviceReady() (0 input parameters) +Function 512: IsAudioDeviceReady() (0 input parameters) Name: IsAudioDeviceReady Return type: bool Description: Check if audio device has been initialized successfully No input parameters -Function 511: SetMasterVolume() (1 input parameters) +Function 513: SetMasterVolume() (1 input parameters) Name: SetMasterVolume Return type: void Description: Set master volume (listener) Param[1]: volume (type: float) -Function 512: GetMasterVolume() (0 input parameters) +Function 514: GetMasterVolume() (0 input parameters) Name: GetMasterVolume Return type: float Description: Get master volume (listener) No input parameters -Function 513: LoadWave() (1 input parameters) +Function 515: LoadWave() (1 input parameters) Name: LoadWave Return type: Wave Description: Load wave data from file Param[1]: fileName (type: const char *) -Function 514: LoadWaveFromMemory() (3 input parameters) +Function 516: LoadWaveFromMemory() (3 input parameters) Name: LoadWaveFromMemory Return type: Wave Description: Load wave from memory buffer, fileType refers to extension: i.e. '.wav' Param[1]: fileType (type: const char *) Param[2]: fileData (type: const unsigned char *) Param[3]: dataSize (type: int) -Function 515: IsWaveReady() (1 input parameters) +Function 517: IsWaveReady() (1 input parameters) Name: IsWaveReady Return type: bool Description: Checks if wave data is ready Param[1]: wave (type: Wave) -Function 516: LoadSound() (1 input parameters) +Function 518: LoadSound() (1 input parameters) Name: LoadSound Return type: Sound Description: Load sound from file Param[1]: fileName (type: const char *) -Function 517: LoadSoundFromWave() (1 input parameters) +Function 519: LoadSoundFromWave() (1 input parameters) Name: LoadSoundFromWave Return type: Sound Description: Load sound from wave data Param[1]: wave (type: Wave) -Function 518: LoadSoundAlias() (1 input parameters) +Function 520: LoadSoundAlias() (1 input parameters) Name: LoadSoundAlias Return type: Sound Description: Create a new sound that shares the same sample data as the source sound, does not own the sound data Param[1]: source (type: Sound) -Function 519: IsSoundReady() (1 input parameters) +Function 521: IsSoundReady() (1 input parameters) Name: IsSoundReady Return type: bool Description: Checks if a sound is ready Param[1]: sound (type: Sound) -Function 520: UpdateSound() (3 input parameters) +Function 522: UpdateSound() (3 input parameters) Name: UpdateSound Return type: void Description: Update sound buffer with new data Param[1]: sound (type: Sound) Param[2]: data (type: const void *) Param[3]: sampleCount (type: int) -Function 521: UnloadWave() (1 input parameters) +Function 523: UnloadWave() (1 input parameters) Name: UnloadWave Return type: void Description: Unload wave data Param[1]: wave (type: Wave) -Function 522: UnloadSound() (1 input parameters) +Function 524: UnloadSound() (1 input parameters) Name: UnloadSound Return type: void Description: Unload sound Param[1]: sound (type: Sound) -Function 523: UnloadSoundAlias() (1 input parameters) +Function 525: UnloadSoundAlias() (1 input parameters) Name: UnloadSoundAlias Return type: void Description: Unload a sound alias (does not deallocate sample data) Param[1]: alias (type: Sound) -Function 524: ExportWave() (2 input parameters) +Function 526: ExportWave() (2 input parameters) Name: ExportWave Return type: bool Description: Export wave data to file, returns true on success Param[1]: wave (type: Wave) Param[2]: fileName (type: const char *) -Function 525: ExportWaveAsCode() (2 input parameters) +Function 527: ExportWaveAsCode() (2 input parameters) Name: ExportWaveAsCode Return type: bool Description: Export wave sample data to code (.h), returns true on success Param[1]: wave (type: Wave) Param[2]: fileName (type: const char *) -Function 526: PlaySound() (1 input parameters) +Function 528: PlaySound() (1 input parameters) Name: PlaySound Return type: void Description: Play a sound Param[1]: sound (type: Sound) -Function 527: StopSound() (1 input parameters) +Function 529: StopSound() (1 input parameters) Name: StopSound Return type: void Description: Stop playing a sound Param[1]: sound (type: Sound) -Function 528: PauseSound() (1 input parameters) +Function 530: PauseSound() (1 input parameters) Name: PauseSound Return type: void Description: Pause a sound Param[1]: sound (type: Sound) -Function 529: ResumeSound() (1 input parameters) +Function 531: ResumeSound() (1 input parameters) Name: ResumeSound Return type: void Description: Resume a paused sound Param[1]: sound (type: Sound) -Function 530: IsSoundPlaying() (1 input parameters) +Function 532: IsSoundPlaying() (1 input parameters) Name: IsSoundPlaying Return type: bool Description: Check if a sound is currently playing Param[1]: sound (type: Sound) -Function 531: SetSoundVolume() (2 input parameters) +Function 533: SetSoundVolume() (2 input parameters) Name: SetSoundVolume Return type: void Description: Set volume for a sound (1.0 is max level) Param[1]: sound (type: Sound) Param[2]: volume (type: float) -Function 532: SetSoundPitch() (2 input parameters) +Function 534: SetSoundPitch() (2 input parameters) Name: SetSoundPitch Return type: void Description: Set pitch for a sound (1.0 is base level) Param[1]: sound (type: Sound) Param[2]: pitch (type: float) -Function 533: SetSoundPan() (2 input parameters) +Function 535: SetSoundPan() (2 input parameters) Name: SetSoundPan Return type: void Description: Set pan for a sound (0.5 is center) Param[1]: sound (type: Sound) Param[2]: pan (type: float) -Function 534: WaveCopy() (1 input parameters) +Function 536: WaveCopy() (1 input parameters) Name: WaveCopy Return type: Wave Description: Copy a wave to a new wave Param[1]: wave (type: Wave) -Function 535: WaveCrop() (3 input parameters) +Function 537: WaveCrop() (3 input parameters) Name: WaveCrop Return type: void Description: Crop a wave to defined frames range Param[1]: wave (type: Wave *) Param[2]: initFrame (type: int) Param[3]: finalFrame (type: int) -Function 536: WaveFormat() (4 input parameters) +Function 538: WaveFormat() (4 input parameters) Name: WaveFormat Return type: void Description: Convert wave data to desired format @@ -4409,203 +4427,203 @@ Function 536: WaveFormat() (4 input parameters) Param[2]: sampleRate (type: int) Param[3]: sampleSize (type: int) Param[4]: channels (type: int) -Function 537: LoadWaveSamples() (1 input parameters) +Function 539: LoadWaveSamples() (1 input parameters) Name: LoadWaveSamples Return type: float * Description: Load samples data from wave as a 32bit float data array Param[1]: wave (type: Wave) -Function 538: UnloadWaveSamples() (1 input parameters) +Function 540: UnloadWaveSamples() (1 input parameters) Name: UnloadWaveSamples Return type: void Description: Unload samples data loaded with LoadWaveSamples() Param[1]: samples (type: float *) -Function 539: LoadMusicStream() (1 input parameters) +Function 541: LoadMusicStream() (1 input parameters) Name: LoadMusicStream Return type: Music Description: Load music stream from file Param[1]: fileName (type: const char *) -Function 540: LoadMusicStreamFromMemory() (3 input parameters) +Function 542: LoadMusicStreamFromMemory() (3 input parameters) Name: LoadMusicStreamFromMemory Return type: Music Description: Load music stream from data Param[1]: fileType (type: const char *) Param[2]: data (type: const unsigned char *) Param[3]: dataSize (type: int) -Function 541: IsMusicReady() (1 input parameters) +Function 543: IsMusicReady() (1 input parameters) Name: IsMusicReady Return type: bool Description: Checks if a music stream is ready Param[1]: music (type: Music) -Function 542: UnloadMusicStream() (1 input parameters) +Function 544: UnloadMusicStream() (1 input parameters) Name: UnloadMusicStream Return type: void Description: Unload music stream Param[1]: music (type: Music) -Function 543: PlayMusicStream() (1 input parameters) +Function 545: PlayMusicStream() (1 input parameters) Name: PlayMusicStream Return type: void Description: Start music playing Param[1]: music (type: Music) -Function 544: IsMusicStreamPlaying() (1 input parameters) +Function 546: IsMusicStreamPlaying() (1 input parameters) Name: IsMusicStreamPlaying Return type: bool Description: Check if music is playing Param[1]: music (type: Music) -Function 545: UpdateMusicStream() (1 input parameters) +Function 547: UpdateMusicStream() (1 input parameters) Name: UpdateMusicStream Return type: void Description: Updates buffers for music streaming Param[1]: music (type: Music) -Function 546: StopMusicStream() (1 input parameters) +Function 548: StopMusicStream() (1 input parameters) Name: StopMusicStream Return type: void Description: Stop music playing Param[1]: music (type: Music) -Function 547: PauseMusicStream() (1 input parameters) +Function 549: PauseMusicStream() (1 input parameters) Name: PauseMusicStream Return type: void Description: Pause music playing Param[1]: music (type: Music) -Function 548: ResumeMusicStream() (1 input parameters) +Function 550: ResumeMusicStream() (1 input parameters) Name: ResumeMusicStream Return type: void Description: Resume playing paused music Param[1]: music (type: Music) -Function 549: SeekMusicStream() (2 input parameters) +Function 551: SeekMusicStream() (2 input parameters) Name: SeekMusicStream Return type: void Description: Seek music to a position (in seconds) Param[1]: music (type: Music) Param[2]: position (type: float) -Function 550: SetMusicVolume() (2 input parameters) +Function 552: SetMusicVolume() (2 input parameters) Name: SetMusicVolume Return type: void Description: Set volume for music (1.0 is max level) Param[1]: music (type: Music) Param[2]: volume (type: float) -Function 551: SetMusicPitch() (2 input parameters) +Function 553: SetMusicPitch() (2 input parameters) Name: SetMusicPitch Return type: void Description: Set pitch for a music (1.0 is base level) Param[1]: music (type: Music) Param[2]: pitch (type: float) -Function 552: SetMusicPan() (2 input parameters) +Function 554: SetMusicPan() (2 input parameters) Name: SetMusicPan Return type: void Description: Set pan for a music (0.5 is center) Param[1]: music (type: Music) Param[2]: pan (type: float) -Function 553: GetMusicTimeLength() (1 input parameters) +Function 555: GetMusicTimeLength() (1 input parameters) Name: GetMusicTimeLength Return type: float Description: Get music time length (in seconds) Param[1]: music (type: Music) -Function 554: GetMusicTimePlayed() (1 input parameters) +Function 556: GetMusicTimePlayed() (1 input parameters) Name: GetMusicTimePlayed Return type: float Description: Get current music time played (in seconds) Param[1]: music (type: Music) -Function 555: LoadAudioStream() (3 input parameters) +Function 557: LoadAudioStream() (3 input parameters) Name: LoadAudioStream Return type: AudioStream Description: Load audio stream (to stream raw audio pcm data) Param[1]: sampleRate (type: unsigned int) Param[2]: sampleSize (type: unsigned int) Param[3]: channels (type: unsigned int) -Function 556: IsAudioStreamReady() (1 input parameters) +Function 558: IsAudioStreamReady() (1 input parameters) Name: IsAudioStreamReady Return type: bool Description: Checks if an audio stream is ready Param[1]: stream (type: AudioStream) -Function 557: UnloadAudioStream() (1 input parameters) +Function 559: UnloadAudioStream() (1 input parameters) Name: UnloadAudioStream Return type: void Description: Unload audio stream and free memory Param[1]: stream (type: AudioStream) -Function 558: UpdateAudioStream() (3 input parameters) +Function 560: UpdateAudioStream() (3 input parameters) Name: UpdateAudioStream Return type: void Description: Update audio stream buffers with data Param[1]: stream (type: AudioStream) Param[2]: data (type: const void *) Param[3]: frameCount (type: int) -Function 559: IsAudioStreamProcessed() (1 input parameters) +Function 561: IsAudioStreamProcessed() (1 input parameters) Name: IsAudioStreamProcessed Return type: bool Description: Check if any audio stream buffers requires refill Param[1]: stream (type: AudioStream) -Function 560: PlayAudioStream() (1 input parameters) +Function 562: PlayAudioStream() (1 input parameters) Name: PlayAudioStream Return type: void Description: Play audio stream Param[1]: stream (type: AudioStream) -Function 561: PauseAudioStream() (1 input parameters) +Function 563: PauseAudioStream() (1 input parameters) Name: PauseAudioStream Return type: void Description: Pause audio stream Param[1]: stream (type: AudioStream) -Function 562: ResumeAudioStream() (1 input parameters) +Function 564: ResumeAudioStream() (1 input parameters) Name: ResumeAudioStream Return type: void Description: Resume audio stream Param[1]: stream (type: AudioStream) -Function 563: IsAudioStreamPlaying() (1 input parameters) +Function 565: IsAudioStreamPlaying() (1 input parameters) Name: IsAudioStreamPlaying Return type: bool Description: Check if audio stream is playing Param[1]: stream (type: AudioStream) -Function 564: StopAudioStream() (1 input parameters) +Function 566: StopAudioStream() (1 input parameters) Name: StopAudioStream Return type: void Description: Stop audio stream Param[1]: stream (type: AudioStream) -Function 565: SetAudioStreamVolume() (2 input parameters) +Function 567: SetAudioStreamVolume() (2 input parameters) Name: SetAudioStreamVolume Return type: void Description: Set volume for audio stream (1.0 is max level) Param[1]: stream (type: AudioStream) Param[2]: volume (type: float) -Function 566: SetAudioStreamPitch() (2 input parameters) +Function 568: SetAudioStreamPitch() (2 input parameters) Name: SetAudioStreamPitch Return type: void Description: Set pitch for audio stream (1.0 is base level) Param[1]: stream (type: AudioStream) Param[2]: pitch (type: float) -Function 567: SetAudioStreamPan() (2 input parameters) +Function 569: SetAudioStreamPan() (2 input parameters) Name: SetAudioStreamPan Return type: void Description: Set pan for audio stream (0.5 is centered) Param[1]: stream (type: AudioStream) Param[2]: pan (type: float) -Function 568: SetAudioStreamBufferSizeDefault() (1 input parameters) +Function 570: SetAudioStreamBufferSizeDefault() (1 input parameters) Name: SetAudioStreamBufferSizeDefault Return type: void Description: Default size for new audio streams Param[1]: size (type: int) -Function 569: SetAudioStreamCallback() (2 input parameters) +Function 571: SetAudioStreamCallback() (2 input parameters) Name: SetAudioStreamCallback Return type: void Description: Audio thread callback to request new data Param[1]: stream (type: AudioStream) Param[2]: callback (type: AudioCallback) -Function 570: AttachAudioStreamProcessor() (2 input parameters) +Function 572: AttachAudioStreamProcessor() (2 input parameters) Name: AttachAudioStreamProcessor Return type: void Description: Attach audio stream processor to stream, receives the samples as 'float' Param[1]: stream (type: AudioStream) Param[2]: processor (type: AudioCallback) -Function 571: DetachAudioStreamProcessor() (2 input parameters) +Function 573: DetachAudioStreamProcessor() (2 input parameters) Name: DetachAudioStreamProcessor Return type: void Description: Detach audio stream processor from stream Param[1]: stream (type: AudioStream) Param[2]: processor (type: AudioCallback) -Function 572: AttachAudioMixedProcessor() (1 input parameters) +Function 574: AttachAudioMixedProcessor() (1 input parameters) Name: AttachAudioMixedProcessor Return type: void Description: Attach audio stream processor to the entire audio pipeline, receives the samples as 'float' Param[1]: processor (type: AudioCallback) -Function 573: DetachAudioMixedProcessor() (1 input parameters) +Function 575: DetachAudioMixedProcessor() (1 input parameters) Name: DetachAudioMixedProcessor Return type: void Description: Detach audio stream processor from the entire audio pipeline diff --git a/parser/output/raylib_api.xml b/parser/output/raylib_api.xml index 8a6560f48..02cfd02d0 100644 --- a/parser/output/raylib_api.xml +++ b/parser/output/raylib_api.xml @@ -670,7 +670,7 @@ - + @@ -2637,6 +2637,20 @@ + + + + + + + + + + + + + + From bc0bd98763bba496836c5cfc1418949256bc6f4d Mon Sep 17 00:00:00 2001 From: Colleague Riley Date: Sat, 24 Aug 2024 12:43:46 -0400 Subject: [PATCH 041/208] (rcore_desktop_rgfw.c) fix errors when compiling with mingw (#4282) * (rcore_desktop_rgfw.c) fix errors when compiling with mingw * define WideCharToMultiByte --- src/external/RGFW.h | 4 +++- src/platforms/rcore_desktop_rgfw.c | 6 +----- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/external/RGFW.h b/src/external/RGFW.h index 367a46fa6..35e782d4a 100644 --- a/src/external/RGFW.h +++ b/src/external/RGFW.h @@ -4999,7 +4999,9 @@ static const struct wl_callback_listener wl_surface_frame_listener = { #define WIN32_LEAN_AND_MEAN #define OEMRESOURCE #include - + + __declspec(dllimport) int __stdcall WideCharToMultiByte( UINT CodePage, DWORD dwFlags, const WCHAR* lpWideCharStr, int cchWideChar, LPSTR lpMultiByteStr, int cbMultiByte, LPCCH lpDefaultChar, LPBOOL lpUsedDefaultChar); + #include #include #include diff --git a/src/platforms/rcore_desktop_rgfw.c b/src/platforms/rcore_desktop_rgfw.c index afea0c2e6..64ab432e6 100644 --- a/src/platforms/rcore_desktop_rgfw.c +++ b/src/platforms/rcore_desktop_rgfw.c @@ -76,9 +76,7 @@ void CloseWindow(void); #define Size NSSIZE #endif -#if defined(_MSC_VER) __declspec(dllimport) int __stdcall MultiByteToWideChar(unsigned int CodePage, unsigned long dwFlags, const char *lpMultiByteStr, int cbMultiByte, wchar_t *lpWideCharStr, int cchWideChar); -#endif #include "../external/RGFW.h" @@ -538,10 +536,8 @@ void *GetWindowHandle(void) { #ifdef RGFW_WEBASM return (void*)platform.window->src.ctx; -#elif !defined(RGFW_WINDOWS) - return (void *)platform.window->src.window; #else - return platform.window->src.hwnd; + return (void*)platform.window->src.window; #endif } From 414133dbe7b063566a338d9c4ef1c9eb0651dec4 Mon Sep 17 00:00:00 2001 From: Ray Date: Sat, 24 Aug 2024 18:56:06 +0200 Subject: [PATCH 042/208] Update models_point_rendering.c --- examples/models/models_point_rendering.c | 107 +++++++++++++---------- 1 file changed, 59 insertions(+), 48 deletions(-) diff --git a/examples/models/models_point_rendering.c b/examples/models/models_point_rendering.c index 128a70f57..68d498453 100644 --- a/examples/models/models_point_rendering.c +++ b/examples/models/models_point_rendering.c @@ -14,13 +14,15 @@ ********************************************************************************************/ #include "raylib.h" -#include // Required for: rand() -#include // Required for: cos(), sin() -#define MAX_POINTS 10000000 // 10 million -#define MIN_POINTS 1000 // 1 thousand +#include // Required for: rand() +#include // Required for: cos(), sin() -static float RandFloat(); +#define MAX_POINTS 10000000 // 10 million +#define MIN_POINTS 1000 // 1 thousand + +// Generate mesh using points +Mesh GenMeshPoints(int numPoints); //------------------------------------------------------------------------------------ // Program main entry point @@ -31,23 +33,26 @@ int main() //-------------------------------------------------------------------------------------- const int screenWidth = 800; const int screenHeight = 450; + InitWindow(screenWidth, screenHeight, "raylib [models] example - point rendering"); - SetTargetFPS(60); Camera camera = { - .position = {3.0f, 3.0f, 3.0f}, - .target = {0.0f, 0.0f, 0.0f}, - .up = {0.0f, 1.0f, 0.0f}, + .position = { 3.0f, 3.0f, 3.0f }, + .target = { 0.0f, 0.0f, 0.0f }, + .up = { 0.0f, 1.0f, 0.0f }, .fovy = 45.0f, - .projection = CAMERA_PERSPECTIVE, + .projection = CAMERA_PERSPECTIVE }; - Vector3 position = {0.0f, 0.0f, 0.0f}; + Vector3 position = { 0.0f, 0.0f, 0.0f }; bool useDrawModelPoints = true; bool numPointsChanged = false; int numPoints = 1000; - Mesh mesh = GenPoints(numPoints); + + Mesh mesh = GenMeshPoints(numPoints); Model model = LoadModelFromMesh(mesh); + + //SetTargetFPS(60); //-------------------------------------------------------------------------------------- // Main game loop @@ -60,30 +65,30 @@ int main() if (IsKeyPressed(KEY_SPACE)) useDrawModelPoints = !useDrawModelPoints; if (IsKeyPressed(KEY_UP)) { - numPoints = (numPoints * 10 > MAX_POINTS) ? MAX_POINTS : numPoints * 10; + numPoints = (numPoints*10 > MAX_POINTS)? MAX_POINTS : numPoints*10; numPointsChanged = true; - TraceLog(LOG_INFO, "num points %d", numPoints); } if (IsKeyPressed(KEY_DOWN)) { - numPoints = (numPoints / 10 < MIN_POINTS) ? MIN_POINTS : numPoints / 10; + numPoints = (numPoints/10 < MIN_POINTS)? MIN_POINTS : numPoints/10; numPointsChanged = true; - TraceLog(LOG_INFO, "num points %d", numPoints); } - // upload a different point cloud size + // Upload a different point cloud size if (numPointsChanged) { UnloadModel(model); - mesh = GenPoints(numPoints); + mesh = GenMeshPoints(numPoints); model = LoadModelFromMesh(mesh); numPointsChanged = false; } + //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(BLACK); + BeginMode3D(camera); // The new method only uploads the points once to the GPU @@ -91,42 +96,43 @@ int main() { DrawModelPoints(model, position, 1.0f, WHITE); } - // The old method must continually draw the "points" (lines) else { + // The old method must continually draw the "points" (lines) for (int i = 0; i < numPoints; i++) { Vector3 pos = { - .x = mesh.vertices[i * 3 + 0], - .y = mesh.vertices[i * 3 + 1], - .z = mesh.vertices[i * 3 + 2], + .x = mesh.vertices[i*3 + 0], + .y = mesh.vertices[i*3 + 1], + .z = mesh.vertices[i*3 + 2], }; Color color = { - .r = mesh.colors[i * 4 + 0], - .g = mesh.colors[i * 4 + 1], - .b = mesh.colors[i * 4 + 2], - .a = mesh.colors[i * 4 + 3], + .r = mesh.colors[i*4 + 0], + .g = mesh.colors[i*4 + 1], + .b = mesh.colors[i*4 + 2], + .a = mesh.colors[i*4 + 3], }; + DrawPoint3D(pos, color); } } // Draw a unit sphere for reference DrawSphereWires(position, 1.0f, 10, 10, YELLOW); + EndMode3D(); - // Text formatting - Color color = WHITE; - int fps = GetFPS(); - if ((fps < 30) && (fps >= 15)) color = ORANGE; - else if (fps < 15) color = RED; - DrawText(TextFormat("%2i FPS", fps), 20, 20, 40, color); + // Draw UI text DrawText(TextFormat("Point Count: %d", numPoints), 20, screenHeight - 50, 40, WHITE); DrawText("Up - increase points", 20, 70, 20, WHITE); DrawText("Down - decrease points", 20, 100, 20, WHITE); DrawText("Space - drawing function", 20, 130, 20, WHITE); - if (useDrawModelPoints) DrawText("DrawModelPoints()", 20, 160, 20, GREEN); - else DrawText("DrawPoint3D()", 20, 160, 20, RED); + + if (useDrawModelPoints) DrawText("Using: DrawModelPoints()", 20, 160, 20, GREEN); + else DrawText("Using: DrawPoint3D()", 20, 160, 20, RED); + + DrawFPS(10, 10); + EndDrawing(); //---------------------------------------------------------------------------------- } @@ -134,38 +140,43 @@ int main() // De-Initialization //-------------------------------------------------------------------------------------- UnloadModel(model); + CloseWindow(); //-------------------------------------------------------------------------------------- return 0; } // Generate a spherical point cloud -Mesh GenPoints(int numPoints) +Mesh GenMeshPoints(int numPoints) { Mesh mesh = { .triangleCount = 1, .vertexCount = numPoints, - .vertices = (float *)MemAlloc(numPoints * 3 * sizeof(float)), - .colors = (unsigned char*)MemAlloc(numPoints * 4 * sizeof(unsigned char)), + .vertices = (float *)MemAlloc(numPoints*3*sizeof(float)), + .colors = (unsigned char*)MemAlloc(numPoints*4*sizeof(unsigned char)), }; // https://en.wikipedia.org/wiki/Spherical_coordinate_system for (int i = 0; i < numPoints; i++) { - float theta = PI * rand() / RAND_MAX; - float phi = 2.0f * PI * rand() / RAND_MAX; - float r = 10.0f * rand() / RAND_MAX; - mesh.vertices[i * 3 + 0] = r * sin(theta) * cos(phi); - mesh.vertices[i * 3 + 1] = r * sin(theta) * sin(phi); - mesh.vertices[i * 3 + 2] = r * cos(theta); - Color color = ColorFromHSV(r * 360.0f, 1.0f, 1.0f); - mesh.colors[i * 4 + 0] = color.r; - mesh.colors[i * 4 + 1] = color.g; - mesh.colors[i * 4 + 2] = color.b; - mesh.colors[i * 4 + 3] = color.a; + float theta = PI*rand()/RAND_MAX; + float phi = 2.0f*PI*rand()/RAND_MAX; + float r = 10.0f*rand()/RAND_MAX; + + mesh.vertices[i*3 + 0] = r*sin(theta)*cos(phi); + mesh.vertices[i*3 + 1] = r*sin(theta)*sin(phi); + mesh.vertices[i*3 + 2] = r*cos(theta); + + Color color = ColorFromHSV(r*360.0f, 1.0f, 1.0f); + + mesh.colors[i*4 + 0] = color.r; + mesh.colors[i*4 + 1] = color.g; + mesh.colors[i*4 + 2] = color.b; + mesh.colors[i*4 + 3] = color.a; } // Upload mesh data from CPU (RAM) to GPU (VRAM) memory UploadMesh(&mesh, false); + return mesh; } From 78e86b6ea5824699f9fdaf708f532e5215ea9e7f Mon Sep 17 00:00:00 2001 From: Ray Date: Sat, 24 Aug 2024 18:58:43 +0200 Subject: [PATCH 043/208] Update rlgl.h --- src/rlgl.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/rlgl.h b/src/rlgl.h index 5fb9497cd..2f8515ee2 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -665,7 +665,7 @@ RLAPI void rlDisableScissorTest(void); // Disable scissor test RLAPI void rlScissor(int x, int y, int width, int height); // Scissor test RLAPI void rlEnableWireMode(void); // Enable wire mode RLAPI void rlEnablePointMode(void); // Enable point mode -RLAPI void rlDisableWireMode(void); // Disable wire mode ( and point ) maybe rename +RLAPI void rlDisableWireMode(void); // Disable wire (and point) mode RLAPI void rlSetLineWidth(float width); // Set the line drawing width RLAPI float rlGetLineWidth(void); // Get the line drawing width RLAPI void rlEnableSmoothLines(void); // Enable line aliasing @@ -1948,6 +1948,7 @@ void rlEnableWireMode(void) #endif } +// Enable point mode void rlEnablePointMode(void) { #if defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_33) @@ -1956,6 +1957,7 @@ void rlEnablePointMode(void) glEnable(GL_PROGRAM_POINT_SIZE); #endif } + // Disable wire mode void rlDisableWireMode(void) { @@ -4236,6 +4238,8 @@ void rlSetUniform(int locIndex, const void *value, int uniformType, int count) case RL_SHADER_UNIFORM_IVEC4: glUniform4iv(locIndex, count, (int *)value); break; case RL_SHADER_UNIFORM_SAMPLER2D: glUniform1iv(locIndex, count, (int *)value); break; default: TRACELOG(RL_LOG_WARNING, "SHADER: Failed to set uniform value, data type not recognized"); + + // TODO: Support glUniform1uiv(), glUniform2uiv(), glUniform3uiv(), glUniform4uiv() } #endif } From 4c9282b09025677a90e5e54ffe142824560163b6 Mon Sep 17 00:00:00 2001 From: Ray Date: Sat, 24 Aug 2024 18:59:24 +0200 Subject: [PATCH 044/208] ADDED: `isGpuReady` flag, allow font loading with no GPU acceleration --- src/rcore.c | 48 ++++++++++++++++++++++++++++-------------------- src/rtext.c | 32 ++++++++++++++++++-------------- 2 files changed, 46 insertions(+), 34 deletions(-) diff --git a/src/rcore.c b/src/rcore.c index e8041ea41..972d58600 100644 --- a/src/rcore.c +++ b/src/rcore.c @@ -360,10 +360,15 @@ typedef struct CoreData { //---------------------------------------------------------------------------------- RLAPI const char *raylib_version = RAYLIB_VERSION; // raylib version exported symbol, required for some bindings -CoreData CORE = { 0 }; // Global CORE state context +CoreData CORE = { 0 }; // Global CORE state context + +// Flag to note GPU acceleration is available, +// referenced from other modules to support GPU data loading +// NOTE: Useful to allow Texture, RenderTexture, Font.texture, Mesh.vaoId/vboId, Shader loading +bool isGpuReady = false; #if defined(SUPPORT_SCREEN_CAPTURE) -static int screenshotCounter = 0; // Screenshots counter +static int screenshotCounter = 0; // Screenshots counter #endif #if defined(SUPPORT_GIF_RECORDING) @@ -637,28 +642,31 @@ void InitWindow(int width, int height, const char *title) // Initialize rlgl default data (buffers and shaders) // NOTE: CORE.Window.currentFbo.width and CORE.Window.currentFbo.height not used, just stored as globals in rlgl rlglInit(CORE.Window.currentFbo.width, CORE.Window.currentFbo.height); + isGpuReady = true; // Flag to note GPU has been initialized successfully // Setup default viewport SetupViewport(CORE.Window.currentFbo.width, CORE.Window.currentFbo.height); -#if defined(SUPPORT_MODULE_RTEXT) && defined(SUPPORT_DEFAULT_FONT) - // Load default font - // WARNING: External function: Module required: rtext - LoadFontDefault(); - #if defined(SUPPORT_MODULE_RSHAPES) - // Set font white rectangle for shapes drawing, so shapes and text can be batched together - // WARNING: rshapes module is required, if not available, default internal white rectangle is used - Rectangle rec = GetFontDefault().recs[95]; - if (CORE.Window.flags & FLAG_MSAA_4X_HINT) - { - // NOTE: We try to maxime rec padding to avoid pixel bleeding on MSAA filtering - SetShapesTexture(GetFontDefault().texture, (Rectangle){ rec.x + 2, rec.y + 2, 1, 1 }); - } - else - { - // NOTE: We set up a 1px padding on char rectangle to avoid pixel bleeding - SetShapesTexture(GetFontDefault().texture, (Rectangle){ rec.x + 1, rec.y + 1, rec.width - 2, rec.height - 2 }); - } +#if defined(SUPPORT_MODULE_RTEXT) + #if defined(SUPPORT_DEFAULT_FONT) + // Load default font + // WARNING: External function: Module required: rtext + LoadFontDefault(); + #if defined(SUPPORT_MODULE_RSHAPES) + // Set font white rectangle for shapes drawing, so shapes and text can be batched together + // WARNING: rshapes module is required, if not available, default internal white rectangle is used + Rectangle rec = GetFontDefault().recs[95]; + if (CORE.Window.flags & FLAG_MSAA_4X_HINT) + { + // NOTE: We try to maxime rec padding to avoid pixel bleeding on MSAA filtering + SetShapesTexture(GetFontDefault().texture, (Rectangle){ rec.x + 2, rec.y + 2, 1, 1 }); + } + else + { + // NOTE: We set up a 1px padding on char rectangle to avoid pixel bleeding + SetShapesTexture(GetFontDefault().texture, (Rectangle){ rec.x + 1, rec.y + 1, rec.width - 2, rec.height - 2 }); + } + #endif #endif #else #if defined(SUPPORT_MODULE_RSHAPES) diff --git a/src/rtext.c b/src/rtext.c index 8c1dc3c5e..4f1be2cd7 100644 --- a/src/rtext.c +++ b/src/rtext.c @@ -124,6 +124,7 @@ //---------------------------------------------------------------------------------- // Global variables //---------------------------------------------------------------------------------- +extern bool isGpuReady; #if defined(SUPPORT_DEFAULT_FONT) // Default font provided by raylib // NOTE: Default font is loaded on InitWindow() and disposed on CloseWindow() [module: core] @@ -252,7 +253,7 @@ extern void LoadFontDefault(void) counter++; } - defaultFont.texture = LoadTextureFromImage(imFont); + if (isGpuReady) defaultFont.texture = LoadTextureFromImage(imFont); // Reconstruct charSet using charsWidth[], charsHeight, charsDivisor, glyphCount //------------------------------------------------------------------------------ @@ -308,7 +309,7 @@ extern void LoadFontDefault(void) extern void UnloadFontDefault(void) { for (int i = 0; i < defaultFont.glyphCount; i++) UnloadImage(defaultFont.glyphs[i].image); - UnloadTexture(defaultFont.texture); + if (isGpuReady) UnloadTexture(defaultFont.texture); RL_FREE(defaultFont.glyphs); RL_FREE(defaultFont.recs); } @@ -362,11 +363,14 @@ Font LoadFont(const char *fileName) UnloadImage(image); } - if (font.texture.id == 0) TRACELOG(LOG_WARNING, "FONT: [%s] Failed to load font texture -> Using default font", fileName); - else + if (isGpuReady) { - SetTextureFilter(font.texture, TEXTURE_FILTER_POINT); // By default, we set point filter (the best performance) - TRACELOG(LOG_INFO, "FONT: Data loaded successfully (%i pixel size | %i glyphs)", FONT_TTF_DEFAULT_SIZE, FONT_TTF_DEFAULT_NUMCHARS); + if (font.texture.id == 0) TRACELOG(LOG_WARNING, "FONT: [%s] Failed to load font texture -> Using default font", fileName); + else + { + SetTextureFilter(font.texture, TEXTURE_FILTER_POINT); // By default, we set point filter (the best performance) + TRACELOG(LOG_INFO, "FONT: Data loaded successfully (%i pixel size | %i glyphs)", FONT_TTF_DEFAULT_SIZE, FONT_TTF_DEFAULT_NUMCHARS); + } } return font; @@ -487,7 +491,7 @@ Font LoadFontFromImage(Image image, Color key, int firstChar) }; // Set font with all data parsed from image - font.texture = LoadTextureFromImage(fontClear); // Convert processed image to OpenGL texture + if (isGpuReady) font.texture = LoadTextureFromImage(fontClear); // Convert processed image to OpenGL texture font.glyphCount = index; font.glyphPadding = 0; @@ -556,7 +560,7 @@ Font LoadFontFromMemory(const char *fileType, const unsigned char *fileData, int font.glyphPadding = FONT_TTF_DEFAULT_CHARS_PADDING; Image atlas = GenImageFontAtlas(font.glyphs, &font.recs, font.glyphCount, font.baseSize, font.glyphPadding, 0); - font.texture = LoadTextureFromImage(atlas); + if (isGpuReady) font.texture = LoadTextureFromImage(atlas); // Update glyphs[i].image to use alpha, required to be used on ImageDrawText() for (int i = 0; i < font.glyphCount; i++) @@ -580,7 +584,7 @@ Font LoadFontFromMemory(const char *fileType, const unsigned char *fileData, int // Check if a font is ready bool IsFontReady(Font font) { - return ((font.texture.id > 0) && // Validate OpenGL id fot font texture atlas + return ((font.texture.id > 0) && // Validate OpenGL id for font texture atlas (font.baseSize > 0) && // Validate font size (font.glyphCount > 0) && // Validate font contains some glyph (font.recs != NULL) && // Validate font recs defining glyphs on texture atlas @@ -946,7 +950,7 @@ void UnloadFont(Font font) if (font.texture.id != GetFontDefault().texture.id) { UnloadFontData(font.glyphs, font.glyphCount); - UnloadTexture(font.texture); + if (isGpuReady) UnloadTexture(font.texture); RL_FREE(font.recs); TRACELOGD("FONT: Unloaded font data from RAM and VRAM"); @@ -1066,7 +1070,7 @@ bool ExportFontAsCode(Font font, const char *fileName) byteCount += sprintf(txtData + byteCount, " Image imFont = { fontImageData_%s, %i, %i, 1, %i };\n\n", styleName, image.width, image.height, image.format); #endif byteCount += sprintf(txtData + byteCount, " // Load texture from image\n"); - byteCount += sprintf(txtData + byteCount, " font.texture = LoadTextureFromImage(imFont);\n"); + byteCount += sprintf(txtData + byteCount, " if (isGpuReady) font.texture = LoadTextureFromImage(imFont);\n"); #if defined(SUPPORT_COMPRESSED_FONT_ATLAS) byteCount += sprintf(txtData + byteCount, " UnloadImage(imFont); // Uncompressed data can be unloaded from memory\n\n"); #endif @@ -1277,7 +1281,7 @@ Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing { Vector2 textSize = { 0 }; - if ((font.texture.id == 0) || (text == NULL)) return textSize; // Security check + if ((isGpuReady && (font.texture.id == 0)) || (text == NULL)) return textSize; // Security check int size = TextLength(text); // Get size in bytes of text int tempByteCounter = 0; // Used to count longer text line num chars @@ -2257,7 +2261,7 @@ static Font LoadBMFont(const char *fileName) RL_FREE(imFonts); - font.texture = LoadTextureFromImage(fullFont); + if (isGpuReady) font.texture = LoadTextureFromImage(fullFont); // Fill font characters info data font.baseSize = fontSize; @@ -2299,7 +2303,7 @@ static Font LoadBMFont(const char *fileName) UnloadImage(fullFont); UnloadFileText(fileText); - if (font.texture.id == 0) + if (isGpuReady && (font.texture.id == 0)) { UnloadFont(font); font = GetFontDefault(); From 0aba21f71c30f3375fa898f8c733089528617639 Mon Sep 17 00:00:00 2001 From: Jeffery Myers Date: Sat, 24 Aug 2024 11:31:28 -0700 Subject: [PATCH 045/208] [RCORE] Update comments on fullscreen and boderless window to describe what they do (#4280) * Update raylib_api.* by CI * update fullscreen and borderless comments to better describe what they do. * Update raylib_api.* by CI --------- Co-authored-by: github-actions[bot] --- parser/output/raylib_api.json | 4 ++-- parser/output/raylib_api.lua | 4 ++-- parser/output/raylib_api.txt | 4 ++-- parser/output/raylib_api.xml | 4 ++-- src/raylib.h | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/parser/output/raylib_api.json b/parser/output/raylib_api.json index dfe37e2fe..03b19325a 100644 --- a/parser/output/raylib_api.json +++ b/parser/output/raylib_api.json @@ -3215,12 +3215,12 @@ }, { "name": "ToggleFullscreen", - "description": "Toggle window state: fullscreen/windowed (only PLATFORM_DESKTOP)", + "description": "Toggle window state: fullscreen/windowed [resizes monitor to match window resolution] (only PLATFORM_DESKTOP)", "returnType": "void" }, { "name": "ToggleBorderlessWindowed", - "description": "Toggle window state: borderless windowed (only PLATFORM_DESKTOP)", + "description": "Toggle window state: borderless windowed [resizes window to match monitor resolution] (only PLATFORM_DESKTOP)", "returnType": "void" }, { diff --git a/parser/output/raylib_api.lua b/parser/output/raylib_api.lua index 933b2c704..7d74c9a41 100644 --- a/parser/output/raylib_api.lua +++ b/parser/output/raylib_api.lua @@ -3158,12 +3158,12 @@ return { }, { name = "ToggleFullscreen", - description = "Toggle window state: fullscreen/windowed (only PLATFORM_DESKTOP)", + description = "Toggle window state: fullscreen/windowed [resizes monitor to match window resolution] (only PLATFORM_DESKTOP)", returnType = "void" }, { name = "ToggleBorderlessWindowed", - description = "Toggle window state: borderless windowed (only PLATFORM_DESKTOP)", + description = "Toggle window state: borderless windowed [resizes window to match monitor resolution] (only PLATFORM_DESKTOP)", returnType = "void" }, { diff --git a/parser/output/raylib_api.txt b/parser/output/raylib_api.txt index 94562d66a..fb30ebe5f 100644 --- a/parser/output/raylib_api.txt +++ b/parser/output/raylib_api.txt @@ -1056,12 +1056,12 @@ Function 013: ClearWindowState() (1 input parameters) Function 014: ToggleFullscreen() (0 input parameters) Name: ToggleFullscreen Return type: void - Description: Toggle window state: fullscreen/windowed (only PLATFORM_DESKTOP) + Description: Toggle window state: fullscreen/windowed [resizes monitor to match window resolution] (only PLATFORM_DESKTOP) No input parameters Function 015: ToggleBorderlessWindowed() (0 input parameters) Name: ToggleBorderlessWindowed Return type: void - Description: Toggle window state: borderless windowed (only PLATFORM_DESKTOP) + Description: Toggle window state: borderless windowed [resizes window to match monitor resolution] (only PLATFORM_DESKTOP) No input parameters Function 016: MaximizeWindow() (0 input parameters) Name: MaximizeWindow diff --git a/parser/output/raylib_api.xml b/parser/output/raylib_api.xml index 02cfd02d0..532b9e3b9 100644 --- a/parser/output/raylib_api.xml +++ b/parser/output/raylib_api.xml @@ -703,9 +703,9 @@ - + - + diff --git a/src/raylib.h b/src/raylib.h index f51a444e1..7e9af7ada 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -968,8 +968,8 @@ RLAPI bool IsWindowResized(void); // Check if wi RLAPI bool IsWindowState(unsigned int flag); // Check if one specific window flag is enabled RLAPI void SetWindowState(unsigned int flags); // Set window configuration state using flags (only PLATFORM_DESKTOP) RLAPI void ClearWindowState(unsigned int flags); // Clear window configuration state flags -RLAPI void ToggleFullscreen(void); // Toggle window state: fullscreen/windowed (only PLATFORM_DESKTOP) -RLAPI void ToggleBorderlessWindowed(void); // Toggle window state: borderless windowed (only PLATFORM_DESKTOP) +RLAPI void ToggleFullscreen(void); // Toggle window state: fullscreen/windowed [resizes monitor to match window resolution] (only PLATFORM_DESKTOP) +RLAPI void ToggleBorderlessWindowed(void); // Toggle window state: borderless windowed [resizes window to match monitor resolution] (only PLATFORM_DESKTOP) RLAPI void MaximizeWindow(void); // Set window state: maximized, if resizable (only PLATFORM_DESKTOP) RLAPI void MinimizeWindow(void); // Set window state: minimized, if resizable (only PLATFORM_DESKTOP) RLAPI void RestoreWindow(void); // Set window state: not minimized/maximized (only PLATFORM_DESKTOP) From 0c06a08e0738a5777d150b7b4562cd8595680271 Mon Sep 17 00:00:00 2001 From: Dave Green <34277803+SoloByte@users.noreply.github.com> Date: Sat, 24 Aug 2024 20:33:21 +0200 Subject: [PATCH 046/208] [rcore][desktop_glfw] Keeping CORE.Window.position properly in sync with glfw window position (#4190) * WindowPosCallback added. CORE.Window.position is now properly kept in sync with the glfw window position. * Update rcore_desktop_glfw.c Comments updated. * Setting CORE.Window.position correctly in InitPlatform() as well. This also fixes not centering the window correctly when the high dpi flag was enabled. * Fixes centering the window in the SetWindowMonitor() function. Here the render size has to be used again in case the high dpi flag is enabled. * Update Window Position Update Window Position right away in ToggleFullscreen() & ToggleBorderlessWindowed() functions --- src/platforms/rcore_desktop_glfw.c | 47 ++++++++++++++++++++++-------- 1 file changed, 35 insertions(+), 12 deletions(-) diff --git a/src/platforms/rcore_desktop_glfw.c b/src/platforms/rcore_desktop_glfw.c index d64bf60db..c6685846c 100644 --- a/src/platforms/rcore_desktop_glfw.c +++ b/src/platforms/rcore_desktop_glfw.c @@ -109,6 +109,7 @@ static void ErrorCallback(int error, const char *description); // Window callbacks events static void WindowSizeCallback(GLFWwindow *window, int width, int height); // GLFW3 WindowSize Callback, runs when window is resized +static void WindowPosCallback(GLFWwindow* window, int x, int y); // GLFW3 WindowPos Callback, runs when window is moved static void WindowIconifyCallback(GLFWwindow *window, int iconified); // GLFW3 WindowIconify Callback, runs when window is minimized/restored static void WindowMaximizeCallback(GLFWwindow* window, int maximized); // GLFW3 Window Maximize Callback, runs when window is maximized static void WindowFocusCallback(GLFWwindow *window, int focused); // GLFW3 WindowFocus Callback, runs when window get/lose focus @@ -147,8 +148,8 @@ void ToggleFullscreen(void) if (!CORE.Window.fullscreen) { // Store previous window position (in case we exit fullscreen) - glfwGetWindowPos(platform.handle, &CORE.Window.position.x, &CORE.Window.position.y); - + CORE.Window.previousPosition = CORE.Window.position; + int monitorCount = 0; int monitorIndex = GetCurrentMonitor(); GLFWmonitor **monitors = glfwGetMonitors(&monitorCount); @@ -179,7 +180,11 @@ void ToggleFullscreen(void) CORE.Window.fullscreen = false; CORE.Window.flags &= ~FLAG_FULLSCREEN_MODE; - glfwSetWindowMonitor(platform.handle, NULL, CORE.Window.position.x, CORE.Window.position.y, CORE.Window.screen.width, CORE.Window.screen.height, GLFW_DONT_CARE); + glfwSetWindowMonitor(platform.handle, NULL, CORE.Window.previousPosition.x, CORE.Window.previousPosition.y, CORE.Window.screen.width, CORE.Window.screen.height, GLFW_DONT_CARE); + + // we update the window position right away + CORE.Window.position.x = CORE.Window.previousPosition.x; + CORE.Window.position.y = CORE.Window.previousPosition.y; } // Try to enable GPU V-Sync, so frames are limited to screen refresh rate (60Hz -> 60 FPS) @@ -190,11 +195,11 @@ void ToggleFullscreen(void) // Toggle borderless windowed mode void ToggleBorderlessWindowed(void) { - // Leave fullscreen before attempting to set borderless windowed mode and get screen position from it + // Leave fullscreen before attempting to set borderless windowed mode bool wasOnFullscreen = false; if (CORE.Window.fullscreen) { - CORE.Window.previousPosition = CORE.Window.position; + // fullscreen already saves the previous position so it does not need to be set here again ToggleFullscreen(); wasOnFullscreen = true; } @@ -213,7 +218,7 @@ void ToggleBorderlessWindowed(void) { // Store screen position and size // NOTE: If it was on fullscreen, screen position was already stored, so skip setting it here - if (!wasOnFullscreen) glfwGetWindowPos(platform.handle, &CORE.Window.previousPosition.x, &CORE.Window.previousPosition.y); + if (!wasOnFullscreen) CORE.Window.previousPosition = CORE.Window.position; CORE.Window.previousScreen = CORE.Window.screen; // Set undecorated and topmost modes and flags @@ -255,6 +260,9 @@ void ToggleBorderlessWindowed(void) glfwFocusWindow(platform.handle); CORE.Window.flags &= ~FLAG_BORDERLESS_WINDOWED_MODE; + + CORE.Window.position.x = CORE.Window.previousPosition.x; + CORE.Window.position.y = CORE.Window.previousPosition.y; } } else TRACELOG(LOG_WARNING, "GLFW: Failed to find video mode for selected monitor"); @@ -592,6 +600,9 @@ void SetWindowTitle(const char *title) // Set window position on screen (windowed mode) void SetWindowPosition(int x, int y) { + // Update CORE.Window.position as well + CORE.Window.position.x = x; + CORE.Window.position.y = y; glfwSetWindowPos(platform.handle, x, y); } @@ -614,8 +625,9 @@ void SetWindowMonitor(int monitor) { TRACELOG(LOG_INFO, "GLFW: Selected monitor: [%i] %s", monitor, glfwGetMonitorName(monitors[monitor])); - const int screenWidth = CORE.Window.screen.width; - const int screenHeight = CORE.Window.screen.height; + // Here the render width has to be used again in case high dpi flag is enabled + const int screenWidth = CORE.Window.render.width; + const int screenHeight = CORE.Window.render.height; int monitorWorkareaX = 0; int monitorWorkareaY = 0; int monitorWorkareaWidth = 0; @@ -1568,12 +1580,17 @@ int InitPlatform(void) int monitorWidth = 0; int monitorHeight = 0; glfwGetMonitorWorkarea(monitor, &monitorX, &monitorY, &monitorWidth, &monitorHeight); - - int posX = monitorX + (monitorWidth - (int)CORE.Window.screen.width)/2; - int posY = monitorY + (monitorHeight - (int)CORE.Window.screen.height)/2; + + // Here CORE.Window.render.width/height should be used instead of CORE.Window.screen.width/height to center the window correctly when the high dpi flag is enabled. + int posX = monitorX + (monitorWidth - (int)CORE.Window.render.width)/2; + int posY = monitorY + (monitorHeight - (int)CORE.Window.render.height)/2; if (posX < monitorX) posX = monitorX; if (posY < monitorY) posY = monitorY; SetWindowPosition(posX, posY); + + // Update CORE.Window.position here so it is correct from the start + CORE.Window.position.x = posX; + CORE.Window.position.y = posY; } // Load OpenGL extensions @@ -1585,6 +1602,7 @@ int InitPlatform(void) //---------------------------------------------------------------------------- // Set window callback events glfwSetWindowSizeCallback(platform.handle, WindowSizeCallback); // NOTE: Resizing not allowed by default! + glfwSetWindowPosCallback(platform.handle, WindowPosCallback); glfwSetWindowMaximizeCallback(platform.handle, WindowMaximizeCallback); glfwSetWindowIconifyCallback(platform.handle, WindowIconifyCallback); glfwSetWindowFocusCallback(platform.handle, WindowFocusCallback); @@ -1681,7 +1699,12 @@ static void WindowSizeCallback(GLFWwindow *window, int width, int height) // NOTE: Postprocessing texture is not scaled to new size } - +static void WindowPosCallback(GLFWwindow* window, int x, int y) +{ + // Set current window position + CORE.Window.position.x = x; + CORE.Window.position.y = y; +} static void WindowContentScaleCallback(GLFWwindow *window, float scalex, float scaley) { CORE.Window.screenScale = MatrixScale(scalex, scaley, 1.0f); From d314afc451e4b0ed6fe69249dffccb65bd1e0582 Mon Sep 17 00:00:00 2001 From: Tchan0 <61758157+Tchan0@users.noreply.github.com> Date: Sat, 24 Aug 2024 20:35:49 +0200 Subject: [PATCH 047/208] rlgl.h: glint64 did not exist before OpenGL 3.2 (#4284) Compilation breaks on rlgl.h for early OpenGL versions. Glint64 did not exist on those versions (< OpenGL 3.2) --- src/rlgl.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/rlgl.h b/src/rlgl.h index 2f8515ee2..3efed736a 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -4414,14 +4414,14 @@ void rlUpdateShaderBuffer(unsigned int id, const void *data, unsigned int dataSi // Get SSBO buffer size unsigned int rlGetShaderBufferSize(unsigned int id) { - GLint64 size = 0; - #if defined(GRAPHICS_API_OPENGL_43) + GLint64 size = 0; glBindBuffer(GL_SHADER_STORAGE_BUFFER, id); glGetBufferParameteri64v(GL_SHADER_STORAGE_BUFFER, GL_BUFFER_SIZE, &size); -#endif - return (size > 0)? (unsigned int)size : 0; +#else + return 0; +#endif } // Read SSBO buffer data (GPU->CPU) From 8dbf3712445c27e86bebf1b82e1de04cf1099a91 Mon Sep 17 00:00:00 2001 From: Tchan0 <61758157+Tchan0@users.noreply.github.com> Date: Sun, 25 Aug 2024 11:23:08 +0200 Subject: [PATCH 048/208] Examples makefiles: align /usr/local with /src Makefile (#4286) * align /usr/local with src Makefile Align /usr/local with the /src Makefile, where it can be overriden. * /usr/local: allow override align /usr/local with the /src Makefile, where it can be overriden --- examples/Makefile | 5 +++-- examples/Makefile.Web | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/examples/Makefile b/examples/Makefile index 904917f7c..bdbb6e351 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -70,8 +70,9 @@ RAYLIB_SRC_PATH ?= ../src # Locations of raylib.h and libraylib.a/libraylib.so # NOTE: Those variables are only used for PLATFORM_OS: LINUX, BSD -RAYLIB_INCLUDE_PATH ?= /usr/local/include -RAYLIB_LIB_PATH ?= /usr/local/lib +DESTDIR ?= /usr/local +RAYLIB_INCLUDE_PATH ?= $(DESTDIR)/include +RAYLIB_LIB_PATH ?= $(DESTDIR)/lib # Library type compilation: STATIC (.a) or SHARED (.so/.dll) RAYLIB_LIBTYPE ?= STATIC diff --git a/examples/Makefile.Web b/examples/Makefile.Web index 7057da1c0..bd48c2a4a 100644 --- a/examples/Makefile.Web +++ b/examples/Makefile.Web @@ -35,8 +35,9 @@ RAYLIB_PATH ?= .. # Locations of raylib.h and libraylib.a/libraylib.so # NOTE: Those variables are only used for PLATFORM_OS: LINUX, BSD -RAYLIB_INCLUDE_PATH ?= /usr/local/include -RAYLIB_LIB_PATH ?= /usr/local/lib +DESTDIR ?= /usr/local +RAYLIB_INCLUDE_PATH ?= $(DESTDIR)/include +RAYLIB_LIB_PATH ?= $(DESTDIR)/lib # Library type compilation: STATIC (.a) or SHARED (.so/.dll) RAYLIB_LIBTYPE ?= STATIC From dec7f12b148ea4383c166d42812e19e0c793bdb0 Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 25 Aug 2024 12:51:55 +0200 Subject: [PATCH 049/208] Update raylib.h --- src/raylib.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/raylib.h b/src/raylib.h index 7e9af7ada..30ba8bd2a 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -1443,7 +1443,7 @@ RLAPI int GetPixelDataSize(int width, int height, int format); // G // Font loading/unloading functions RLAPI Font GetFontDefault(void); // Get the default Font RLAPI Font LoadFont(const char *fileName); // Load font from file into GPU memory (VRAM) -RLAPI Font LoadFontEx(const char *fileName, int fontSize, int *codepoints, int codepointCount); // Load font from file with extended parameters, use NULL for codepoints and 0 for codepointCount to load the default character set +RLAPI Font LoadFontEx(const char *fileName, int fontSize, int *codepoints, int codepointCount); // Load font from file with extended parameters, use NULL for codepoints and 0 for codepointCount to load the default character set, font size is provided in pixels height 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 *codepoints, int codepointCount); // Load font from memory buffer, fileType refers to extension: i.e. '.ttf' RLAPI bool IsFontReady(Font font); // Check if a font is ready From 157c7c21d451e022f8227ee5b756a99689a1d3a3 Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 25 Aug 2024 12:52:27 +0200 Subject: [PATCH 050/208] ADDED: more uniform data type options #4137 --- src/rlgl.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/rlgl.h b/src/rlgl.h index 3efed736a..34fabe45e 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -527,6 +527,10 @@ typedef enum { RL_SHADER_UNIFORM_IVEC2, // Shader uniform type: ivec2 (2 int) RL_SHADER_UNIFORM_IVEC3, // Shader uniform type: ivec3 (3 int) RL_SHADER_UNIFORM_IVEC4, // Shader uniform type: ivec4 (4 int) + RL_SHADER_UNIFORM_UINT, // Shader uniform type: unsigned int + RL_SHADER_UNIFORM_UIVEC2, // Shader uniform type: uivec2 (2 unsigned int) + RL_SHADER_UNIFORM_UIVEC3, // Shader uniform type: uivec3 (3 unsigned int) + RL_SHADER_UNIFORM_UIVEC4, // Shader uniform type: uivec4 (4 unsigned int) RL_SHADER_UNIFORM_SAMPLER2D // Shader uniform type: sampler2d } rlShaderUniformDataType; @@ -4236,6 +4240,10 @@ void rlSetUniform(int locIndex, const void *value, int uniformType, int count) case RL_SHADER_UNIFORM_IVEC2: glUniform2iv(locIndex, count, (int *)value); break; case RL_SHADER_UNIFORM_IVEC3: glUniform3iv(locIndex, count, (int *)value); break; case RL_SHADER_UNIFORM_IVEC4: glUniform4iv(locIndex, count, (int *)value); break; + case RL_SHADER_UNIFORM_UINT: glUniform1uiv(locIndex, count, (unsigned int *)value); break; + case RL_SHADER_UNIFORM_UIVEC2: glUniform2uiv(locIndex, count, (unsigned int *)value); break; + case RL_SHADER_UNIFORM_UIVEC3: glUniform3uiv(locIndex, count, (unsigned int *)value); break; + case RL_SHADER_UNIFORM_UIVEC4: glUniform4uiv(locIndex, count, (unsigned int *)value); break; case RL_SHADER_UNIFORM_SAMPLER2D: glUniform1iv(locIndex, count, (int *)value); break; default: TRACELOG(RL_LOG_WARNING, "SHADER: Failed to set uniform value, data type not recognized"); From 5604f6d8a34b94118a9f24e433eb06e771d8378c Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 25 Aug 2024 12:57:05 +0200 Subject: [PATCH 051/208] Update rlgl.h --- src/rlgl.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/rlgl.h b/src/rlgl.h index 34fabe45e..9b94d402c 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -4240,10 +4240,12 @@ void rlSetUniform(int locIndex, const void *value, int uniformType, int count) case RL_SHADER_UNIFORM_IVEC2: glUniform2iv(locIndex, count, (int *)value); break; case RL_SHADER_UNIFORM_IVEC3: glUniform3iv(locIndex, count, (int *)value); break; case RL_SHADER_UNIFORM_IVEC4: glUniform4iv(locIndex, count, (int *)value); break; + #if !defined(GRAPHICS_API_OPENGL_ES2) case RL_SHADER_UNIFORM_UINT: glUniform1uiv(locIndex, count, (unsigned int *)value); break; case RL_SHADER_UNIFORM_UIVEC2: glUniform2uiv(locIndex, count, (unsigned int *)value); break; case RL_SHADER_UNIFORM_UIVEC3: glUniform3uiv(locIndex, count, (unsigned int *)value); break; case RL_SHADER_UNIFORM_UIVEC4: glUniform4uiv(locIndex, count, (unsigned int *)value); break; + #endif case RL_SHADER_UNIFORM_SAMPLER2D: glUniform1iv(locIndex, count, (int *)value); break; default: TRACELOG(RL_LOG_WARNING, "SHADER: Failed to set uniform value, data type not recognized"); From f5ef3578100ff06dc1ad3752076e5771de4717f9 Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 25 Aug 2024 13:55:53 +0200 Subject: [PATCH 052/208] Update rtext.c --- src/rtext.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/rtext.c b/src/rtext.c index 4f1be2cd7..34b6fcedb 100644 --- a/src/rtext.c +++ b/src/rtext.c @@ -677,6 +677,8 @@ GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSiz { stbtt_GetCodepointHMetrics(&fontInfo, ch, &chars[i].advanceX, NULL); chars[i].advanceX = (int)((float)chars[i].advanceX*scaleFactor); + + if (chh > fontSize) TRACELOG(LOG_WARNING, "FONT: Character [0x%08x] size is bigger than expected font size", ch); // Load characters images chars[i].image.width = chw; From 91a9888baa61e221cb6e68a5fd8fc005fffcbca8 Mon Sep 17 00:00:00 2001 From: Jeffery Myers Date: Sun, 25 Aug 2024 09:49:52 -0700 Subject: [PATCH 053/208] [rModels] Correctly split obj meshes by material (#4285) * Correctly split meshes from tinyobj by material so they can be represented by raylib correctly * PR Feedback --- src/rmodels.c | 304 ++++++++++++++++++++++++++++++++++---------------- 1 file changed, 206 insertions(+), 98 deletions(-) diff --git a/src/rmodels.c b/src/rmodels.c index 966a8665c..5fb512403 100644 --- a/src/rmodels.c +++ b/src/rmodels.c @@ -2016,6 +2016,8 @@ static void ProcessMaterialsOBJ(Material *materials, tinyobj_material_t *mats, i // NOTE: Uses default shader, which only supports MATERIAL_MAP_DIFFUSE materials[m] = LoadMaterialDefault(); + if (mats == NULL) continue; + // Get default texture, in case no texture is defined // NOTE: rlgl default texture is a 1x1 pixel UNCOMPRESSED_R8G8B8A8 materials[m].maps[MATERIAL_MAP_DIFFUSE].texture = (Texture2D){ rlGetTextureIdDefault(), 1, 1, 1, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8 }; @@ -4073,130 +4075,236 @@ static void BuildPoseFromParentJoints(BoneInfo *bones, int boneCount, Transform // - the mesh is automatically triangulated by tinyobj static Model LoadOBJ(const char *fileName) { + tinyobj_attrib_t objAttributes = { 0 }; + tinyobj_shape_t* objShapes = NULL; + unsigned int objShapeCount = 0; + + tinyobj_material_t* objMaterials = NULL; + unsigned int objMaterialCount = 0; + Model model = { 0 }; + model.transform = MatrixIdentity(); - tinyobj_attrib_t attrib = { 0 }; - tinyobj_shape_t *meshes = NULL; - unsigned int meshCount = 0; + char* fileText = LoadFileText(fileName); - tinyobj_material_t *materials = NULL; - unsigned int materialCount = 0; - - char *fileText = LoadFileText(fileName); - - if (fileText != NULL) + if (fileText == NULL) { - unsigned int dataSize = (unsigned int)strlen(fileText); + TRACELOG(LOG_ERROR, "MODEL Unable to read obj file %s", fileName); + return model; + } - char currentDir[1024] = { 0 }; - strcpy(currentDir, GetWorkingDirectory()); // Save current working directory - const char *workingDir = GetDirectoryPath(fileName); // Switch to OBJ directory for material path correctness - if (CHDIR(workingDir) != 0) + char currentDir[1024] = { 0 }; + strcpy(currentDir, GetWorkingDirectory()); // Save current working directory + const char* workingDir = GetDirectoryPath(fileName); // Switch to OBJ directory for material path correctness + if (CHDIR(workingDir) != 0) + { + TRACELOG(LOG_WARNING, "MODEL: [%s] Failed to change working directory", workingDir); + } + + unsigned int dataSize = (unsigned int)strlen(fileText); + + unsigned int flags = TINYOBJ_FLAG_TRIANGULATE; + int ret = tinyobj_parse_obj(&objAttributes, &objShapes, &objShapeCount, &objMaterials, &objMaterialCount, fileText, dataSize, flags); + + if (ret != TINYOBJ_SUCCESS) + { + TRACELOG(LOG_ERROR, "MODEL Unable to read obj data %s", fileName); + return model; + } + + UnloadFileText(fileText); + + unsigned int faceVertIndex = 0; + unsigned int nextShape = 1; + int lastMaterial = -1; + unsigned int meshIndex = 0; + + // count meshes + unsigned int nextShapeEnd = objAttributes.num_face_num_verts; + + // see how many verts till the next shape + + if (objShapeCount > 1) nextShapeEnd = objShapes[nextShape].face_offset; + + // walk all the faces + for (unsigned int faceId = 0; faceId < objAttributes.num_faces; faceId++) + { + if (faceVertIndex >= nextShapeEnd) { - TRACELOG(LOG_WARNING, "MODEL: [%s] Failed to change working directory", workingDir); + // try to find the last vert in the next shape + nextShape++; + if (nextShape < objShapeCount) nextShapeEnd = objShapes[nextShape].face_offset; + else nextShapeEnd = objAttributes.num_face_num_verts; // this is actually the total number of face verts in the file, not faces + meshIndex++; + } + else if (lastMaterial != -1 && objAttributes.material_ids[faceId] != lastMaterial) + { + meshIndex++;// if this is a new material, we need to allocate a new mesh } - unsigned int flags = TINYOBJ_FLAG_TRIANGULATE; - int ret = tinyobj_parse_obj(&attrib, &meshes, &meshCount, &materials, &materialCount, fileText, dataSize, flags); + lastMaterial = objAttributes.material_ids[faceId]; + faceVertIndex += objAttributes.face_num_verts[faceId]; + } - 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); + // allocate the base meshes and materials + model.meshCount = meshIndex + 1; + model.meshes = (Mesh*)MemAlloc(sizeof(Mesh) * model.meshCount); - // WARNING: We are not splitting meshes by materials (previous implementation) - // Depending on the provided OBJ that was not the best option and it just crashed - // so, implementation was simplified to prioritize parsed meshes - model.meshCount = meshCount; + if (objMaterialCount > 0) + { + model.materialCount = objMaterialCount; + model.materials = (Material*)MemAlloc(sizeof(Material) * objMaterialCount); + } + else // we must allocate at least one material + { + model.materialCount = 1; + model.materials = (Material*)MemAlloc(sizeof(Material) * 1); + } - // Set number of materials available - // NOTE: There could be more materials available than meshes but it will be resolved at - // model.meshMaterial, just assigning the right material to corresponding mesh - model.materialCount = materialCount; - if (model.materialCount == 0) + model.meshMaterial = (int*)MemAlloc(sizeof(int) * model.meshCount); + + // see how many verts are in each mesh + unsigned int* localMeshVertexCounts = (unsigned int*)MemAlloc(sizeof(unsigned int) * model.meshCount); + + faceVertIndex = 0; + nextShapeEnd = objAttributes.num_face_num_verts; + lastMaterial = -1; + meshIndex = 0; + unsigned int localMeshVertexCount = 0; + + nextShape = 1; + if (objShapeCount > 1) + nextShapeEnd = objShapes[nextShape].face_offset; + + // walk all the faces + for (unsigned int faceId = 0; faceId < objAttributes.num_faces; faceId++) + { + bool newMesh = false; // do we need a new mesh? + if (faceVertIndex >= nextShapeEnd) { - model.materialCount = 1; - TRACELOG(LOG_INFO, "MODEL: No materials provided, setting one default material for all meshes"); + // try to find the last vert in the next shape + nextShape++; + if (nextShape < objShapeCount) nextShapeEnd = objShapes[nextShape].face_offset; + else nextShapeEnd = objAttributes.num_face_num_verts; // this is actually the total number of face verts in the file, not faces + + newMesh = true; } - else if (model.materialCount > 1 && model.meshCount > 1) + else if (lastMaterial != -1 && objAttributes.material_ids[faceId] != lastMaterial) { - // TEMP warning about multiple materials, to be removed when proper splitting code is implemented - // any obj with multiple materials will need to have it's materials assigned by the user in code to work at this time - TRACELOG(LOG_INFO, "MODEL: OBJ has multiple materials, manual material assignment will be required."); + newMesh = true; } - // Init model meshes and materials - model.meshes = (Mesh *)RL_CALLOC(model.meshCount, sizeof(Mesh)); - model.meshMaterial = (int *)RL_CALLOC(model.meshCount, sizeof(int)); // Material index assigned to each mesh - model.materials = (Material *)RL_CALLOC(model.materialCount, sizeof(Material)); + lastMaterial = objAttributes.material_ids[faceId]; - // Process each provided mesh - for (int i = 0; i < model.meshCount; i++) + if (newMesh) { - // WARNING: We need to calculate the mesh triangles manually using meshes[i].face_offset - // because in case of triangulated quads, meshes[i].length actually report quads, - // despite the triangulation that is efectively considered on attrib.num_faces - unsigned int tris = 0; - if (i == model.meshCount - 1) tris = attrib.num_faces - meshes[i].face_offset; - else tris = meshes[i + 1].face_offset; + localMeshVertexCounts[meshIndex] = localMeshVertexCount; - model.meshes[i].vertexCount = tris*3; - model.meshes[i].triangleCount = tris; // Face count (triangulated) - model.meshes[i].vertices = (float *)RL_CALLOC(model.meshes[i].vertexCount*3, sizeof(float)); - model.meshes[i].texcoords = (float *)RL_CALLOC(model.meshes[i].vertexCount*2, sizeof(float)); - model.meshes[i].normals = (float *)RL_CALLOC(model.meshes[i].vertexCount*3, sizeof(float)); - model.meshMaterial[i] = 0; // By default, assign material 0 to each mesh - - // Process all mesh faces - for (unsigned int face = 0, f = meshes[i].face_offset, v = 0, vt = 0, vn = 0; face < tris; face++, f++, v += 3, vt += 3, vn += 3) - { - // Get indices for the face - tinyobj_vertex_index_t idx0 = attrib.faces[f*3 + 0]; - tinyobj_vertex_index_t idx1 = attrib.faces[f*3 + 1]; - tinyobj_vertex_index_t idx2 = attrib.faces[f*3 + 2]; - - // Fill vertices buffer (float) using vertex index of the face - for (int n = 0; n < 3; n++) { model.meshes[i].vertices[v*3 + n] = attrib.vertices[idx0.v_idx*3 + n]; } - for (int n = 0; n < 3; n++) { model.meshes[i].vertices[(v + 1)*3 + n] = attrib.vertices[idx1.v_idx*3 + n]; } - for (int n = 0; n < 3; n++) { model.meshes[i].vertices[(v + 2)*3 + n] = attrib.vertices[idx2.v_idx*3 + n]; } - - if (attrib.num_texcoords > 0) - { - // Fill texcoords buffer (float) using vertex index of the face - // NOTE: Y-coordinate must be flipped upside-down - model.meshes[i].texcoords[vt*2 + 0] = attrib.texcoords[idx0.vt_idx*2 + 0]; - model.meshes[i].texcoords[vt*2 + 1] = 1.0f - attrib.texcoords[idx0.vt_idx*2 + 1]; - - model.meshes[i].texcoords[(vt + 1)*2 + 0] = attrib.texcoords[idx1.vt_idx*2 + 0]; - model.meshes[i].texcoords[(vt + 1)*2 + 1] = 1.0f - attrib.texcoords[idx1.vt_idx*2 + 1]; - - model.meshes[i].texcoords[(vt + 2)*2 + 0] = attrib.texcoords[idx2.vt_idx*2 + 0]; - model.meshes[i].texcoords[(vt + 2)*2 + 1] = 1.0f - attrib.texcoords[idx2.vt_idx*2 + 1]; - } - - if (attrib.num_normals > 0) - { - // Fill normals buffer (float) using vertex index of the face - for (int n = 0; n < 3; n++) { model.meshes[i].normals[vn*3 + n] = attrib.normals[idx0.vn_idx*3 + n]; } - for (int n = 0; n < 3; n++) { model.meshes[i].normals[(vn + 1)*3 + n] = attrib.normals[idx1.vn_idx*3 + n]; } - for (int n = 0; n < 3; n++) { model.meshes[i].normals[(vn + 2)*3 + n] = attrib.normals[idx2.vn_idx*3 + n]; } - } - } + localMeshVertexCount = 0; + meshIndex++; } - // Init model materials - if (materialCount > 0) ProcessMaterialsOBJ(model.materials, materials, materialCount); - else model.materials[0] = LoadMaterialDefault(); // Set default material for the mesh + faceVertIndex += objAttributes.face_num_verts[faceId]; + localMeshVertexCount += objAttributes.face_num_verts[faceId]; + } + localMeshVertexCounts[meshIndex] = localMeshVertexCount; - tinyobj_attrib_free(&attrib); - tinyobj_shapes_free(meshes, model.meshCount); - tinyobj_materials_free(materials, materialCount); + for (int i = 0; i < model.meshCount; i++) + { + // allocate the buffers for each mesh + unsigned int vertexCount = localMeshVertexCounts[i]; - UnloadFileText(fileText); + model.meshes[i].vertexCount = vertexCount; + model.meshes[i].triangleCount = vertexCount / 3; - // Restore current working directory - if (CHDIR(currentDir) != 0) + model.meshes[i].vertices = (float*)MemAlloc(sizeof(float) * vertexCount * 3); + model.meshes[i].normals = (float*)MemAlloc(sizeof(float) * vertexCount * 3); + model.meshes[i].texcoords = (float*)MemAlloc(sizeof(float) * vertexCount * 2); + model.meshes[i].colors = (unsigned char*)MemAlloc(sizeof(unsigned char) * vertexCount * 4); + } + + MemFree(localMeshVertexCounts); + localMeshVertexCounts = NULL; + + // fill meshes + faceVertIndex = 0; + + nextShapeEnd = objAttributes.num_face_num_verts; + + // see how many verts till the next shape + nextShape = 1; + if (objShapeCount > 1) nextShapeEnd = objShapes[nextShape].face_offset; + lastMaterial = -1; + meshIndex = 0; + localMeshVertexCount = 0; + + // walk all the faces + for (unsigned int faceId = 0; faceId < objAttributes.num_faces; faceId++) + { + bool newMesh = false; // do we need a new mesh? + if (faceVertIndex >= nextShapeEnd) { - TRACELOG(LOG_WARNING, "MODEL: [%s] Failed to change working directory", currentDir); + // try to find the last vert in the next shape + nextShape++; + if (nextShape < objShapeCount) nextShapeEnd = objShapes[nextShape].face_offset; + else nextShapeEnd = objAttributes.num_face_num_verts; // this is actually the total number of face verts in the file, not faces + newMesh = true; } + // if this is a new material, we need to allocate a new mesh + if (lastMaterial != -1 && objAttributes.material_ids[faceId] != lastMaterial) newMesh = true; + lastMaterial = objAttributes.material_ids[faceId];; + + if (newMesh) + { + localMeshVertexCount = 0; + meshIndex++; + } + + int matId = 0; + if (lastMaterial >= 0 && lastMaterial < (int)objMaterialCount) + matId = lastMaterial; + + model.meshMaterial[meshIndex] = matId; + + for (int f = 0; f < objAttributes.face_num_verts[faceId]; f++) + { + int vertIndex = objAttributes.faces[faceVertIndex].v_idx; + int normalIndex = objAttributes.faces[faceVertIndex].vn_idx; + int texcordIndex = objAttributes.faces[faceVertIndex].vt_idx; + + for (int i = 0; i < 3; i++) + model.meshes[meshIndex].vertices[localMeshVertexCount * 3 + i] = objAttributes.vertices[vertIndex * 3 + i]; + + for (int i = 0; i < 3; i++) + model.meshes[meshIndex].normals[localMeshVertexCount * 3 + i] = objAttributes.normals[normalIndex * 3 + i]; + + for (int i = 0; i < 2; i++) + model.meshes[meshIndex].texcoords[localMeshVertexCount * 2 + i] = objAttributes.texcoords[texcordIndex * 2 + i]; + + model.meshes[meshIndex].texcoords[localMeshVertexCount * 2 + 1] = 1.0f - model.meshes[meshIndex].texcoords[localMeshVertexCount * 2 + 1]; + + for (int i = 0; i < 4; i++) + model.meshes[meshIndex].colors[localMeshVertexCount * 4 + i] = 255; + + faceVertIndex++; + localMeshVertexCount++; + } + } + + if (objMaterialCount > 0) ProcessMaterialsOBJ(model.materials, objMaterials, objMaterialCount); + else model.materials[0] = LoadMaterialDefault(); // Set default material for the mesh + + tinyobj_attrib_free(&objAttributes); + tinyobj_shapes_free(objShapes, objShapeCount); + tinyobj_materials_free(objMaterials, objMaterialCount); + + for (int i = 0; i < model.meshCount; i++) + UploadMesh(model.meshes + i, true); + + // Restore current working directory + if (CHDIR(currentDir) != 0) + { + TRACELOG(LOG_WARNING, "MODEL: [%s] Failed to change working directory", currentDir); } return model; From 8ea5db3ec43d1fa702b29df9066307d0d337b229 Mon Sep 17 00:00:00 2001 From: Hesham Abourgheba Date: Sun, 25 Aug 2024 19:51:08 +0300 Subject: [PATCH 054/208] fix(rcore/android): Allow main() to return it its caller on configuration changes. (#4288) --- src/platforms/rcore_android.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/platforms/rcore_android.c b/src/platforms/rcore_android.c index 7a2162025..55706c591 100644 --- a/src/platforms/rcore_android.c +++ b/src/platforms/rcore_android.c @@ -694,11 +694,12 @@ void PollInputEvents(void) // Process this event if (platform.source != NULL) platform.source->process(platform.app, platform.source); - // NOTE: Never close window, native activity is controlled by the system! + // NOTE: Allow closing the window in case a configuration change happened. + // The android_main function should be allowed to return to its caller in order for the + // Android OS to relaunch the activity. if (platform.app->destroyRequested != 0) { - //CORE.Window.shouldClose = true; - //ANativeActivity_finish(platform.app->activity); + CORE.Window.shouldClose = true; } } } @@ -781,7 +782,7 @@ int InitPlatform(void) // Process this event if (platform.source != NULL) platform.source->process(platform.app, platform.source); - // NOTE: Never close window, native activity is controlled by the system! + // NOTE: It's highly likely destroyRequested will never be non-zero at the start of the activity lifecycle. //if (platform.app->destroyRequested != 0) CORE.Window.shouldClose = true; } } @@ -812,6 +813,12 @@ void ClosePlatform(void) eglTerminate(platform.device); platform.device = EGL_NO_DISPLAY; } + + // NOTE: Reset global state in case the activity is being relaunched. + if (platform.app->destroyRequested != 0) { + CORE = (CoreData){0}; + platform = (PlatformData){0}; + } } // Initialize display device and framebuffer From 5f49ec3d6448502d798d4d404e08e354ec48012a Mon Sep 17 00:00:00 2001 From: hanaxars <156359933+hanaxars@users.noreply.github.com> Date: Wed, 28 Aug 2024 19:35:35 +0300 Subject: [PATCH 055/208] Fix missing equal sign (#4294) I just noticed there is a missing equal sign. This PR fixes this. --- src/platforms/rcore_drm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platforms/rcore_drm.c b/src/platforms/rcore_drm.c index 291fd93c7..43dc19c71 100644 --- a/src/platforms/rcore_drm.c +++ b/src/platforms/rcore_drm.c @@ -206,7 +206,7 @@ static const short linuxToRaylibMap[KEYMAP_SIZE] = { [BTN_TL] = GAMEPAD_BUTTON_LEFT_TRIGGER_1, [BTN_TL2] = GAMEPAD_BUTTON_LEFT_TRIGGER_2, [BTN_TR] = GAMEPAD_BUTTON_RIGHT_TRIGGER_1, - [BTN_TR2] GAMEPAD_BUTTON_RIGHT_TRIGGER_2, + [BTN_TR2] = GAMEPAD_BUTTON_RIGHT_TRIGGER_2, [BTN_SELECT] = GAMEPAD_BUTTON_MIDDLE_LEFT, [BTN_MODE] = GAMEPAD_BUTTON_MIDDLE, [BTN_START] = GAMEPAD_BUTTON_MIDDLE_RIGHT, From 59b44a4908e830bca755af3d83d25a64f6d54bd2 Mon Sep 17 00:00:00 2001 From: carverdamien Date: Mon, 2 Sep 2024 10:01:30 +0200 Subject: [PATCH 056/208] Add uConsole mapping (#4297) --- src/external/glfw/src/mappings.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/external/glfw/src/mappings.h b/src/external/glfw/src/mappings.h index 270fa4cd8..7b0f35a26 100644 --- a/src/external/glfw/src/mappings.h +++ b/src/external/glfw/src/mappings.h @@ -996,6 +996,7 @@ const char* _glfwDefaultMappings[] = "03000000c0160000e105000001010000,Xin-Mo Xin-Mo Dual Arcade,a:b4,b:b3,back:b6,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b9,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b1,y:b0,platform:Linux,", "03000000120c0000100e000011010000,ZEROPLUS P4 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,", "03000000120c0000101e000011010000,ZEROPLUS P4 Wired Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,", +"03000000af1e00002400000010010000,Clockwork Pi DevTerm,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b9,x:b3,y:b0,platform:Linux,", #endif // GLFW_BUILD_LINUX_JOYSTICK }; From 42022c3531e4ca6739fd0ecc760c882eabf4493a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Jask=C3=B3lski?= Date: Tue, 3 Sep 2024 14:38:12 +0200 Subject: [PATCH 057/208] fix: In certain cases the connector status is reported UNKNOWN, should be conisdered as CONNECTED (#4305) Co-authored-by: Michal Jaskolski --- src/platforms/rcore_drm.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/platforms/rcore_drm.c b/src/platforms/rcore_drm.c index 43dc19c71..ee2875838 100644 --- a/src/platforms/rcore_drm.c +++ b/src/platforms/rcore_drm.c @@ -763,8 +763,10 @@ int InitPlatform(void) drmModeConnector *con = drmModeGetConnector(platform.fd, res->connectors[i]); TRACELOG(LOG_TRACE, "DISPLAY: Connector modes detected: %i", con->count_modes); - - if ((con->connection == DRM_MODE_CONNECTED) && (con->encoder_id)) + + // In certain cases the status of the conneciton is reported as UKNOWN, but it is still connected. + // This might be a hardware or software limitation like on Raspberry Pi Zero with composite output. + if (((con->connection == DRM_MODE_CONNECTED) || (con->connection == DRM_MODE_UNKNOWNCONNECTION)) && (con->encoder_id)) { TRACELOG(LOG_TRACE, "DISPLAY: DRM mode connected"); platform.connector = con; From ed61bdb568046e80e6fd30485375433c4231fd46 Mon Sep 17 00:00:00 2001 From: Chris Warren-Smith Date: Wed, 4 Sep 2024 20:37:00 +0930 Subject: [PATCH 058/208] Fix seg fault with long comment lines (#4306) #4304 --- parser/raylib_parser.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parser/raylib_parser.c b/parser/raylib_parser.c index cfb0133c3..83991c003 100644 --- a/parser/raylib_parser.c +++ b/parser/raylib_parser.c @@ -139,7 +139,7 @@ typedef struct EnumInfo { // Function info data typedef struct FunctionInfo { char name[64]; // Function name - char desc[128]; // Function description (comment at the end) + char desc[256]; // Function description (comment at the end) char retType[32]; // Return value type int paramCount; // Number of function parameters char paramType[MAX_FUNCTION_PARAMETERS][32]; // Parameters type From 10b01ba7c2139b9203045bb56aa8403ca810cc6b Mon Sep 17 00:00:00 2001 From: masnm <49545838+masnm@users.noreply.github.com> Date: Sat, 7 Sep 2024 03:16:17 +0600 Subject: [PATCH 059/208] Change implicit conversion to explicit conversion to remove warning (#4308) --- src/external/par_shapes.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/external/par_shapes.h b/src/external/par_shapes.h index 994a605a9..d5309137b 100644 --- a/src/external/par_shapes.h +++ b/src/external/par_shapes.h @@ -1130,7 +1130,7 @@ static par_shapes__rule* par_shapes__pick_rule(const char* name, total += rule->weight; } } - float r = (float) rand() / RAND_MAX; + float r = (float) rand() / (float) RAND_MAX; float t = 0; for (int i = 0; i < nrules; i++) { rule = rules + i; From 0656440e38208e4d57201706520eb0571fb13bd9 Mon Sep 17 00:00:00 2001 From: masnm <49545838+masnm@users.noreply.github.com> Date: Mon, 9 Sep 2024 00:24:53 +0600 Subject: [PATCH 060/208] fix vld1q_f16 undeclared in arm on stb_image_resize2.h v2.10 (#4309) --- src/external/stb_image_resize2.h | 1657 +++++++++++++++++------------- 1 file changed, 963 insertions(+), 694 deletions(-) diff --git a/src/external/stb_image_resize2.h b/src/external/stb_image_resize2.h index e0c428246..ae8d730bf 100644 --- a/src/external/stb_image_resize2.h +++ b/src/external/stb_image_resize2.h @@ -1,9 +1,9 @@ -/* stb_image_resize2 - v2.01 - public domain image resizing - - by Jeff Roberts (v2) and Jorge L Rodriguez +/* stb_image_resize2 - v2.10 - public domain image resizing + + by Jeff Roberts (v2) and Jorge L Rodriguez http://github.com/nothings/stb - Can be threaded with the extended API. SSE2, AVX, Neon and WASM SIMD support. Only + Can be threaded with the extended API. SSE2, AVX, Neon and WASM SIMD support. Only scaling and translation is supported, no rotations or shears. COMPILING & LINKING @@ -67,60 +67,60 @@ ADDITIONAL DOCUMENTATION MEMORY ALLOCATION - By default, we use malloc and free for memory allocation. To override the + By default, we use malloc and free for memory allocation. To override the memory allocation, before the implementation #include, add a: #define STBIR_MALLOC(size,user_data) ... #define STBIR_FREE(ptr,user_data) ... - Each resize makes exactly one call to malloc/free (unless you use the + Each resize makes exactly one call to malloc/free (unless you use the extended API where you can do one allocation for many resizes). Under address sanitizer, we do separate allocations to find overread/writes. PERFORMANCE This library was written with an emphasis on performance. When testing - stb_image_resize with RGBA, the fastest mode is STBIR_4CHANNEL with + stb_image_resize with RGBA, the fastest mode is STBIR_4CHANNEL with STBIR_TYPE_UINT8 pixels and CLAMPed edges (which is what many other resize - libs do by default). Also, make sure SIMD is turned on of course (default + libs do by default). Also, make sure SIMD is turned on of course (default for 64-bit targets). Avoid WRAP edge mode if you want the fastest speed. This library also comes with profiling built-in. If you define STBIR_PROFILE, - you can use the advanced API and get low-level profiling information by + you can use the advanced API and get low-level profiling information by calling stbir_resize_extended_profile_info() or stbir_resize_split_profile_info() after a resize. SIMD - Most of the routines have optimized SSE2, AVX, NEON and WASM versions. + Most of the routines have optimized SSE2, AVX, NEON and WASM versions. - On Microsoft compilers, we automatically turn on SIMD for 64-bit x64 and - ARM; for 32-bit x86 and ARM, you select SIMD mode by defining STBIR_SSE2 or + On Microsoft compilers, we automatically turn on SIMD for 64-bit x64 and + ARM; for 32-bit x86 and ARM, you select SIMD mode by defining STBIR_SSE2 or STBIR_NEON. For AVX and AVX2, we auto-select it by detecting the /arch:AVX - or /arch:AVX2 switches. You can also always manually turn SSE2, AVX or AVX2 + or /arch:AVX2 switches. You can also always manually turn SSE2, AVX or AVX2 support on by defining STBIR_SSE2, STBIR_AVX or STBIR_AVX2. On Linux, SSE2 and Neon is on by default for 64-bit x64 or ARM64. For 32-bit, we select x86 SIMD mode by whether you have -msse2, -mavx or -mavx2 enabled on the command line. For 32-bit ARM, you must pass -mfpu=neon-vfpv4 for both - clang and GCC, but GCC also requires an additional -mfp16-format=ieee to + clang and GCC, but GCC also requires an additional -mfp16-format=ieee to automatically enable NEON. On x86 platforms, you can also define STBIR_FP16C to turn on FP16C instructions for converting back and forth to half-floats. This is autoselected when we - are using AVX2. Clang and GCC also require the -mf16c switch. ARM always uses - the built-in half float hardware NEON instructions. + are using AVX2. Clang and GCC also require the -mf16c switch. ARM always uses + the built-in half float hardware NEON instructions. - You can also tell us to use multiply-add instructions with STBIR_USE_FMA. + You can also tell us to use multiply-add instructions with STBIR_USE_FMA. Because x86 doesn't always have fma, we turn it off by default to maintain determinism across all platforms. If you don't care about non-FMA determinism - and are willing to restrict yourself to more recent x86 CPUs (around the AVX + and are willing to restrict yourself to more recent x86 CPUs (around the AVX timeframe), then fma will give you around a 15% speedup. You can force off SIMD in all cases by defining STBIR_NO_SIMD. You can turn off AVX or AVX2 specifically with STBIR_NO_AVX or STBIR_NO_AVX2. AVX is 10% to 40% faster, and AVX2 is generally another 12%. - + ALPHA CHANNEL - Most of the resizing functions provide the ability to control how the alpha + Most of the resizing functions provide the ability to control how the alpha channel of an image is processed. When alpha represents transparency, it is important that when combining @@ -167,33 +167,33 @@ stb_image_resize expects case #1 by default, applying alpha weighting to images, expecting the input images to be unpremultiplied. This is what the - COLOR+ALPHA buffer types tell the resizer to do. + COLOR+ALPHA buffer types tell the resizer to do. - When you use the pixel layouts STBIR_RGBA, STBIR_BGRA, STBIR_ARGB, - STBIR_ABGR, STBIR_RX, or STBIR_XR you are telling us that the pixels are - non-premultiplied. In these cases, the resizer will alpha weight the colors - (effectively creating the premultiplied image), do the filtering, and then + When you use the pixel layouts STBIR_RGBA, STBIR_BGRA, STBIR_ARGB, + STBIR_ABGR, STBIR_RX, or STBIR_XR you are telling us that the pixels are + non-premultiplied. In these cases, the resizer will alpha weight the colors + (effectively creating the premultiplied image), do the filtering, and then convert back to non-premult on exit. When you use the pixel layouts STBIR_RGBA_PM, STBIR_RGBA_PM, STBIR_RGBA_PM, - STBIR_RGBA_PM, STBIR_RX_PM or STBIR_XR_PM, you are telling that the pixels - ARE premultiplied. In this case, the resizer doesn't have to do the - premultipling - it can filter directly on the input. This about twice as - fast as the non-premultiplied case, so it's the right option if your data is + STBIR_RGBA_PM, STBIR_RX_PM or STBIR_XR_PM, you are telling that the pixels + ARE premultiplied. In this case, the resizer doesn't have to do the + premultipling - it can filter directly on the input. This about twice as + fast as the non-premultiplied case, so it's the right option if your data is already setup correctly. - When you use the pixel layout STBIR_4CHANNEL or STBIR_2CHANNEL, you are - telling us that there is no channel that represents transparency; it may be - RGB and some unrelated fourth channel that has been stored in the alpha - channel, but it is actually not alpha. No special processing will be - performed. + When you use the pixel layout STBIR_4CHANNEL or STBIR_2CHANNEL, you are + telling us that there is no channel that represents transparency; it may be + RGB and some unrelated fourth channel that has been stored in the alpha + channel, but it is actually not alpha. No special processing will be + performed. - The difference between the generic 4 or 2 channel layouts, and the + The difference between the generic 4 or 2 channel layouts, and the specialized _PM versions is with the _PM versions you are telling us that the data *is* alpha, just don't premultiply it. That's important when using SRGB pixel formats, we need to know where the alpha is, because it is converted linearly (rather than with the SRGB converters). - + Because alpha weighting produces the same effect as premultiplying, you even have the option with non-premultiplied inputs to let the resizer produce a premultiplied output. Because the intially computed alpha-weighted @@ -201,10 +201,10 @@ than the normal path which un-premultiplies the output image as a final step. Finally, when converting both in and out of non-premulitplied space (for - example, when using STBIR_RGBA), we go to somewhat heroic measures to - ensure that areas with zero alpha value pixels get something reasonable - in the RGB values. If you don't care about the RGB values of zero alpha - pixels, you can call the stbir_set_non_pm_alpha_speed_over_quality() + example, when using STBIR_RGBA), we go to somewhat heroic measures to + ensure that areas with zero alpha value pixels get something reasonable + in the RGB values. If you don't care about the RGB values of zero alpha + pixels, you can call the stbir_set_non_pm_alpha_speed_over_quality() function - this runs a premultiplied resize about 25% faster. That said, when you really care about speed, using premultiplied pixels for both in and out (STBIR_RGBA_PM, etc) much faster than both of these premultiplied @@ -218,38 +218,38 @@ layouts with the same number of channels. DETERMINISM - We commit to being deterministic (from x64 to ARM to scalar to SIMD, etc). - This requires compiling with fast-math off (using at least /fp:precise). + We commit to being deterministic (from x64 to ARM to scalar to SIMD, etc). + This requires compiling with fast-math off (using at least /fp:precise). Also, you must turn off fp-contracting (which turns mult+adds into fmas)! - We attempt to do this with pragmas, but with Clang, you usually want to add + We attempt to do this with pragmas, but with Clang, you usually want to add -ffp-contract=off to the command line as well. - For 32-bit x86, you must use SSE and SSE2 codegen for determinism. That is, - if the scalar x87 unit gets used at all, we immediately lose determinism. + For 32-bit x86, you must use SSE and SSE2 codegen for determinism. That is, + if the scalar x87 unit gets used at all, we immediately lose determinism. On Microsoft Visual Studio 2008 and earlier, from what we can tell there is - no way to be deterministic in 32-bit x86 (some x87 always leaks in, even - with fp:strict). On 32-bit x86 GCC, determinism requires both -msse2 and + no way to be deterministic in 32-bit x86 (some x87 always leaks in, even + with fp:strict). On 32-bit x86 GCC, determinism requires both -msse2 and -fpmath=sse. Note that we will not be deterministic with float data containing NaNs - - the NaNs will propagate differently on different SIMD and platforms. + the NaNs will propagate differently on different SIMD and platforms. - If you turn on STBIR_USE_FMA, then we will be deterministic with other - fma targets, but we will differ from non-fma targets (this is unavoidable, - because a fma isn't simply an add with a mult - it also introduces a - rounding difference compared to non-fma instruction sequences. + If you turn on STBIR_USE_FMA, then we will be deterministic with other + fma targets, but we will differ from non-fma targets (this is unavoidable, + because a fma isn't simply an add with a mult - it also introduces a + rounding difference compared to non-fma instruction sequences. FLOAT PIXEL FORMAT RANGE - Any range of values can be used for the non-alpha float data that you pass - in (0 to 1, -1 to 1, whatever). However, if you are inputting float values - but *outputting* bytes or shorts, you must use a range of 0 to 1 so that we - scale back properly. The alpha channel must also be 0 to 1 for any format - that does premultiplication prior to resizing. + Any range of values can be used for the non-alpha float data that you pass + in (0 to 1, -1 to 1, whatever). However, if you are inputting float values + but *outputting* bytes or shorts, you must use a range of 0 to 1 so that we + scale back properly. The alpha channel must also be 0 to 1 for any format + that does premultiplication prior to resizing. - Note also that with float output, using filters with negative lobes, the - output filtered values might go slightly out of range. You can define - STBIR_FLOAT_LOW_CLAMP and/or STBIR_FLOAT_HIGH_CLAMP to specify the range - to clamp to on output, if that's important. + Note also that with float output, using filters with negative lobes, the + output filtered values might go slightly out of range. You can define + STBIR_FLOAT_LOW_CLAMP and/or STBIR_FLOAT_HIGH_CLAMP to specify the range + to clamp to on output, if that's important. MAX/MIN SCALE FACTORS The input pixel resolutions are in integers, and we do the internal pointer @@ -263,13 +263,13 @@ buffers). FLIPPED IMAGES - Stride is just the delta from one scanline to the next. This means you can - use a negative stride to handle inverted images (point to the final + Stride is just the delta from one scanline to the next. This means you can + use a negative stride to handle inverted images (point to the final scanline and use a negative stride). You can invert the input or output, using negative strides. DEFAULT FILTERS - For functions which don't provide explicit control over what filters to + For functions which don't provide explicit control over what filters to use, you can change the compile-time defaults with: #define STBIR_DEFAULT_FILTER_UPSAMPLE STBIR_FILTER_something @@ -278,18 +278,18 @@ See stbir_filter in the header-file section for the list of filters. NEW FILTERS - A number of 1D filter kernels are supplied. For a list of supported - filters, see the stbir_filter enum. You can install your own filters by + A number of 1D filter kernels are supplied. For a list of supported + filters, see the stbir_filter enum. You can install your own filters by using the stbir_set_filter_callbacks function. PROGRESS - For interactive use with slow resize operations, you can use the the - scanline callbacks in the extended API. It would have to be a *very* large + For interactive use with slow resize operations, you can use the the + scanline callbacks in the extended API. It would have to be a *very* large image resample to need progress though - we're very fast. CEIL and FLOOR - In scalar mode, the only functions we use from math.h are ceilf and floorf, - but if you have your own versions, you can define the STBIR_CEILF(v) and + In scalar mode, the only functions we use from math.h are ceilf and floorf, + but if you have your own versions, you can define the STBIR_CEILF(v) and STBIR_FLOORF(v) macros and we'll use them instead. In SIMD, we just use our own versions. @@ -304,7 +304,7 @@ * For SIMD encode and decode scanline routines, do any pre-aligning for bad input/output buffer alignments and pitch? * For very wide scanlines, we should we do vertical strips to stay within - L2 cache. Maybe do chunks of 1K pixels at a time. There would be + L2 cache. Maybe do chunks of 1K pixels at a time. There would be some pixel reconversion, but probably dwarfed by things falling out of cache. Probably also something possible with alternating between scattering and gathering at high resize scales? @@ -316,21 +316,38 @@ the pivot cost and the extra memory touches). Need to buffer the whole image so have to balance memory use. * Most of our code is internally function pointers, should we compile - all the SIMD stuff always and dynamically dispatch? + all the SIMD stuff always and dynamically dispatch? CONTRIBUTORS Jeff Roberts: 2.0 implementation, optimizations, SIMD - Martins Mozeiko: NEON simd, WASM simd, clang and GCC whisperer. + Martins Mozeiko: NEON simd, WASM simd, clang and GCC whisperer Fabian Giesen: half float and srgb converters Sean Barrett: API design, optimizations Jorge L Rodriguez: Original 1.0 implementation - Aras Pranckevicius: bugfixes for 1.0 + Aras Pranckevicius: bugfixes Nathan Reed: warning fixes for 1.0 REVISIONS - 2.00 (2022-02-20) mostly new source: new api, optimizations, simd, vertical-first, etc - (2x-5x faster without simd, 4x-12x faster with simd) - (in some cases, 20x to 40x faster - resizing to very small for example) + 2.10 (2024-07-27) fix the defines GCC and mingw for loop unroll control, + fix MSVC 32-bit arm half float routines. + 2.09 (2024-06-19) fix the defines for 32-bit ARM GCC builds (was selecting + hardware half floats). + 2.08 (2024-06-10) fix for RGB->BGR three channel flips and add SIMD (thanks + to Ryan Salsbury), fix for sub-rect resizes, use the + pragmas to control unrolling when they are available. + 2.07 (2024-05-24) fix for slow final split during threaded conversions of very + wide scanlines when downsampling (caused by extra input + converting), fix for wide scanline resamples with many + splits (int overflow), fix GCC warning. + 2.06 (2024-02-10) fix for identical width/height 3x or more down-scaling + undersampling a single row on rare resize ratios (about 1%). + 2.05 (2024-02-07) fix for 2 pixel to 1 pixel resizes with wrap (thanks Aras), + fix for output callback (thanks Julien Koenen). + 2.04 (2023-11-17) fix for rare AVX bug, shadowed symbol (thanks Nikola Smiljanic). + 2.03 (2023-11-01) ASAN and TSAN warnings fixed, minor tweaks. + 2.00 (2023-10-10) mostly new source: new api, optimizations, simd, vertical-first, etc + 2x-5x faster without simd, 4x-12x faster with simd, + in some cases, 20x to 40x faster esp resizing large to very small. 0.96 (2019-03-04) fixed warnings 0.95 (2017-07-23) fixed warnings 0.94 (2017-03-18) fixed warnings @@ -368,7 +385,7 @@ typedef uint64_t stbir_uint64; #define STBIR_SSE #endif #endif -#endif +#endif #if defined(_x86_64) || defined( __x86_64__ ) || defined( _M_X64 ) || defined(__x86_64) || defined(_M_AMD64) || defined(__SSE2__) || defined(STBIR_SSE) || defined(STBIR_SSE2) #ifndef STBIR_SSE2 @@ -383,7 +400,7 @@ typedef uint64_t stbir_uint64; #endif #if defined(__AVX2__) || defined(STBIR_AVX2) #ifndef STBIR_NO_AVX2 - #ifndef STBIR_AVX2 + #ifndef STBIR_AVX2 #define STBIR_AVX2 #endif #if defined( _MSC_VER ) && !defined(__clang__) @@ -400,15 +417,15 @@ typedef uint64_t stbir_uint64; #endif #endif -#if defined( _M_ARM64 ) || defined( __aarch64__ ) || defined( __arm64__ ) || defined(_M_ARM) || (__ARM_NEON_FP & 4) != 0 && __ARM_FP16_FORMAT_IEEE != 0 +#if defined( _M_ARM64 ) || defined( __aarch64__ ) || defined( __arm64__ ) || ((__ARM_NEON_FP & 4) != 0) || defined(__ARM_NEON__) #ifndef STBIR_NEON #define STBIR_NEON #endif #endif -#if defined(_M_ARM) +#if defined(_M_ARM) || defined(__arm__) #ifdef STBIR_USE_FMA -#undef STBIR_USE_FMA // no FMA for 32-bit arm on MSVC +#undef STBIR_USE_FMA // no FMA for 32-bit arm on MSVC #endif #endif @@ -435,7 +452,7 @@ typedef uint64_t stbir_uint64; // // Easy-to-use API: // -// * stride is the offset between successive rows of image data +// * stride is the offset between successive rows of image data // in memory, in bytes. specify 0 for packed continuously in memory // * colorspace is linear or sRGB as specified by function name // * Uses the default filters @@ -448,27 +465,35 @@ typedef uint64_t stbir_uint64; // order of channels // whether color is premultiplied by alpha // for back compatibility, you can cast the old channel count to an stbir_pixel_layout -typedef enum +typedef enum { - STBIR_BGR = 0, // 3-chan, with order specified (for channel flipping) - STBIR_1CHANNEL = 1, + STBIR_1CHANNEL = 1, STBIR_2CHANNEL = 2, - STBIR_RGB = 3, // 3-chan, with order specified (for channel flipping) - STBIR_RGBA = 4, // alpha formats, alpha is NOT premultiplied into color channels - + STBIR_RGB = 3, // 3-chan, with order specified (for channel flipping) + STBIR_BGR = 0, // 3-chan, with order specified (for channel flipping) STBIR_4CHANNEL = 5, + + STBIR_RGBA = 4, // alpha formats, where alpha is NOT premultiplied into color channels STBIR_BGRA = 6, STBIR_ARGB = 7, STBIR_ABGR = 8, STBIR_RA = 9, STBIR_AR = 10, - STBIR_RGBA_PM = 11, // alpha formats, alpha is premultiplied into color channels + STBIR_RGBA_PM = 11, // alpha formats, where alpha is premultiplied into color channels STBIR_BGRA_PM = 12, STBIR_ARGB_PM = 13, STBIR_ABGR_PM = 14, STBIR_RA_PM = 15, STBIR_AR_PM = 16, + + STBIR_RGBA_NO_AW = 11, // alpha formats, where NO alpha weighting is applied at all! + STBIR_BGRA_NO_AW = 12, // these are just synonyms for the _PM flags (which also do + STBIR_ARGB_NO_AW = 13, // no alpha weighting). These names just make it more clear + STBIR_ABGR_NO_AW = 14, // for some folks). + STBIR_RA_NO_AW = 15, + STBIR_AR_NO_AW = 16, + } stbir_pixel_layout; //=============================================================== @@ -549,8 +574,8 @@ STBIRDEF void * stbir_resize( const void *input_pixels , int input_w , int inpu // * Separate input and output data types // * Can specify regions with subpixel correctness // * Can specify alpha flags -// * Can specify a memory callback -// * Can specify a callback data type for pixel input and output +// * Can specify a memory callback +// * Can specify a callback data type for pixel input and output // * Can be threaded for a single resize // * Can be used to resize many frames without recalculating the sampler info // @@ -577,7 +602,7 @@ typedef float stbir__kernel_callback( float x, float scale, void * user_data ); typedef float stbir__support_callback( float scale, void * user_data ); // internal structure with precomputed scaling -typedef struct stbir__info stbir__info; +typedef struct stbir__info stbir__info; typedef struct STBIR_RESIZE // use the stbir_resize_init and stbir_override functions to set these values for future compatibility { @@ -604,7 +629,7 @@ typedef struct STBIR_RESIZE // use the stbir_resize_init and stbir_override fun stbir_edge horizontal_edge, vertical_edge; stbir__kernel_callback * horizontal_filter_kernel; stbir__support_callback * horizontal_filter_support; stbir__kernel_callback * vertical_filter_kernel; stbir__support_callback * vertical_filter_support; - stbir__info * samplers; + stbir__info * samplers; } STBIR_RESIZE; // extended complexity api @@ -620,7 +645,7 @@ STBIRDEF void stbir_resize_init( STBIR_RESIZE * resize, // You can update these parameters any time after resize_init and there is no cost //-------------------------------- -STBIRDEF void stbir_set_datatypes( STBIR_RESIZE * resize, stbir_datatype input_type, stbir_datatype output_type ); +STBIRDEF void stbir_set_datatypes( STBIR_RESIZE * resize, stbir_datatype input_type, stbir_datatype output_type ); STBIRDEF void stbir_set_pixel_callbacks( STBIR_RESIZE * resize, stbir_input_callback * input_cb, stbir_output_callback * output_cb ); // no callbacks by default STBIRDEF void stbir_set_user_data( STBIR_RESIZE * resize, void * user_data ); // pass back STBIR_RESIZE* by default STBIRDEF void stbir_set_buffer_ptrs( STBIR_RESIZE * resize, const void * input_pixels, int input_stride_in_bytes, void * output_pixels, int output_stride_in_bytes ); @@ -636,7 +661,7 @@ STBIRDEF int stbir_set_pixel_layouts( STBIR_RESIZE * resize, stbir_pixel_layout STBIRDEF int stbir_set_edgemodes( STBIR_RESIZE * resize, stbir_edge horizontal_edge, stbir_edge vertical_edge ); // CLAMP by default STBIRDEF int stbir_set_filters( STBIR_RESIZE * resize, stbir_filter horizontal_filter, stbir_filter vertical_filter ); // STBIR_DEFAULT_FILTER_UPSAMPLE/DOWNSAMPLE by default -STBIRDEF int stbir_set_filter_callbacks( STBIR_RESIZE * resize, stbir__kernel_callback * horizontal_filter, stbir__support_callback * horizontal_support, stbir__kernel_callback * vertical_filter, stbir__support_callback * vertical_support ); +STBIRDEF int stbir_set_filter_callbacks( STBIR_RESIZE * resize, stbir__kernel_callback * horizontal_filter, stbir__support_callback * horizontal_support, stbir__kernel_callback * vertical_filter, stbir__support_callback * vertical_support ); STBIRDEF int stbir_set_pixel_subrect( STBIR_RESIZE * resize, int subx, int suby, int subw, int subh ); // sets both sub-regions (full regions by default) STBIRDEF int stbir_set_input_subrect( STBIR_RESIZE * resize, double s0, double t0, double s1, double t1 ); // sets input sub-region (full region by default) @@ -658,7 +683,7 @@ STBIRDEF int stbir_set_non_pm_alpha_speed_over_quality( STBIR_RESIZE * resize, i //-------------------------------- // This builds the samplers and does one allocation -STBIRDEF int stbir_build_samplers( STBIR_RESIZE * resize ); +STBIRDEF int stbir_build_samplers( STBIR_RESIZE * resize ); // You MUST call this, if you call stbir_build_samplers or stbir_build_samplers_with_splits STBIRDEF void stbir_free_samplers( STBIR_RESIZE * resize ); @@ -681,7 +706,7 @@ STBIRDEF int stbir_resize_extended( STBIR_RESIZE * resize ); // It returns the number of splits (threads) that you can call it with. /// It might be less if the image resize can't be split up that many ways. -STBIRDEF int stbir_build_samplers_with_splits( STBIR_RESIZE * resize, int try_splits ); +STBIRDEF int stbir_build_samplers_with_splits( STBIR_RESIZE * resize, int try_splits ); // This function does a split of the resizing (you call this fuction for each // split, on multiple threads). A split is a piece of the output resize pixel space. @@ -691,10 +716,10 @@ STBIRDEF int stbir_build_samplers_with_splits( STBIR_RESIZE * resize, int try_sp // Usually, you will always call stbir_resize_split with split_start as the thread_index // and "1" for the split_count. // But, if you have a weird situation where you MIGHT want 8 threads, but sometimes -// only 4 threads, you can use 0,2,4,6 for the split_start's and use "2" for the +// only 4 threads, you can use 0,2,4,6 for the split_start's and use "2" for the // split_count each time to turn in into a 4 thread resize. (This is unusual). -STBIRDEF int stbir_resize_extended_split( STBIR_RESIZE * resize, int split_start, int split_count ); +STBIRDEF int stbir_resize_extended_split( STBIR_RESIZE * resize, int split_start, int split_count ); //=============================================================== @@ -705,10 +730,10 @@ STBIRDEF int stbir_resize_extended_split( STBIR_RESIZE * resize, int split_start // The input callback is super flexible - it calls you with the input address // (based on the stride and base pointer), it gives you an optional_output // pointer that you can fill, or you can just return your own pointer into -// your own data. +// your own data. // -// You can also do conversion from non-supported data types if necessary - in -// this case, you ignore the input_ptr and just use the x and y parameters to +// You can also do conversion from non-supported data types if necessary - in +// this case, you ignore the input_ptr and just use the x and y parameters to // calculate your own input_ptr based on the size of each non-supported pixel. // (Something like the third example below.) // @@ -722,14 +747,14 @@ STBIRDEF int stbir_resize_extended_split( STBIR_RESIZE * resize, int split_start // return input_ptr; // use buffer from call // } // -// Next example, copying: (copy from some other buffer or stream): +// Next example, copying: (copy from some other buffer or stream): // void const * my_callback( void * optional_output, void const * input_ptr, int num_pixels, int x, int y, void * context ) // { // CopyOrStreamData( optional_output, other_data_src, num_pixels * pixel_width_in_bytes ); // return optional_output; // return the optional buffer that we filled // } // -// Third example, input another buffer without copying: (zero-copy from other buffer): +// Third example, input another buffer without copying: (zero-copy from other buffer): // void const * my_callback( void * optional_output, void const * input_ptr, int num_pixels, int x, int y, void * context ) // { // void * pixels = ( (char*) other_image_base ) + ( y * other_image_stride ) + ( x * other_pixel_width_in_bytes ); @@ -758,7 +783,7 @@ STBIRDEF int stbir_resize_extended_split( STBIR_RESIZE * resize, int split_start #ifdef STBIR_PROFILE -typedef struct STBIR_PROFILE_INFO +typedef struct STBIR_PROFILE_INFO { stbir_uint64 total_clocks; @@ -766,7 +791,7 @@ typedef struct STBIR_PROFILE_INFO // there are "resize_count" number of zones stbir_uint64 clocks[ 8 ]; char const ** descriptions; - + // count of clocks and descriptions stbir_uint32 count; } STBIR_PROFILE_INFO; @@ -865,15 +890,15 @@ STBIRDEF void stbir_resize_split_profile_info( STBIR_PROFILE_INFO * out_info, ST #endif // the internal pixel layout enums are in a different order, so we can easily do range comparisons of types -// the public pixel layout is ordered in a way that if you cast num_channels (1-4) to the enum, you get something sensible -typedef enum +// the public pixel layout is ordered in a way that if you cast num_channels (1-4) to the enum, you get something sensible +typedef enum { STBIRI_1CHANNEL = 0, STBIRI_2CHANNEL = 1, STBIRI_RGB = 2, STBIRI_BGR = 3, STBIRI_4CHANNEL = 4, - + STBIRI_RGBA = 5, STBIRI_BGRA = 6, STBIRI_ARGB = 7, @@ -979,7 +1004,7 @@ typedef struct stbir__span spans[2]; // can be two spans, if doing input subrect with clamp mode WRAP } stbir__extents; -typedef struct +typedef struct { #ifdef STBIR_PROFILE union @@ -1010,7 +1035,7 @@ typedef struct typedef void stbir__decode_pixels_func( float * decode, int width_times_channels, void const * input ); typedef void stbir__alpha_weight_func( float * decode_buffer, int width_times_channels ); -typedef void stbir__horizontal_gather_channels_func( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, +typedef void stbir__horizontal_gather_channels_func( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width ); typedef void stbir__alpha_unweight_func(float * encode_buffer, int width_times_channels ); typedef void stbir__encode_pixels_func( void * output, int width_times_channels, float const * encode ); @@ -1053,10 +1078,10 @@ struct stbir__info stbir__horizontal_gather_channels_func * horizontal_gather_channels; stbir__alpha_unweight_func * alpha_unweight; stbir__encode_pixels_func * encode_pixels; - - int alloced_total; + + int alloc_ring_buffer_num_entries; // Number of entries in the ring buffer that will be allocated int splits; // count of splits - + stbir_internal_pixel_layout input_pixel_layout_internal; stbir_internal_pixel_layout output_pixel_layout_internal; @@ -1065,7 +1090,7 @@ struct stbir__info int vertical_first; int channels; int effective_channels; // same as channels, except on RGBA/ARGB (7), or XA/AX (3) - int alloc_ring_buffer_num_entries; // Number of entries in the ring buffer that will be allocated + size_t alloced_total; }; @@ -1076,10 +1101,11 @@ struct stbir__info #define stbir__small_float ((float)1 / (1 << 20) / (1 << 20) / (1 << 20) / (1 << 20) / (1 << 20) / (1 << 20)) // min/max friendly -#define STBIR_CLAMP(x, xmin, xmax) do { \ +#define STBIR_CLAMP(x, xmin, xmax) for(;;) { \ if ( (x) < (xmin) ) (x) = (xmin); \ if ( (x) > (xmax) ) (x) = (xmax); \ -} while (0) + break; \ +} static stbir__inline int stbir__min(int a, int b) { @@ -1141,7 +1167,7 @@ static const stbir_uint32 fp32_to_srgb8_tab4[104] = { 0x44c20798, 0x488e071e, 0x4c1c06b6, 0x4f76065d, 0x52a50610, 0x55ac05cc, 0x5892058f, 0x5b590559, 0x5e0c0a23, 0x631c0980, 0x67db08f6, 0x6c55087f, 0x70940818, 0x74a007bd, 0x787d076c, 0x7c330723, }; - + static stbir__inline stbir_uint8 stbir__linear_to_srgb_uchar(float in) { static const stbir__FP32 almostone = { 0x3f7fffff }; // 1-eps @@ -1172,19 +1198,44 @@ static stbir__inline stbir_uint8 stbir__linear_to_srgb_uchar(float in) #define STBIR_FORCE_GATHER_FILTER_SCANLINES_AMOUNT 32 // when downsampling and <= 32 scanlines of buffering, use gather. gather used down to 1/8th scaling for 25% win. #endif -// restrict pointers for the output pointers +#ifndef STBIR_FORCE_MINIMUM_SCANLINES_FOR_SPLITS +#define STBIR_FORCE_MINIMUM_SCANLINES_FOR_SPLITS 4 // when threading, what is the minimum number of scanlines for a split? +#endif + +// restrict pointers for the output pointers, other loop and unroll control #if defined( _MSC_VER ) && !defined(__clang__) #define STBIR_STREAMOUT_PTR( star ) star __restrict #define STBIR_NO_UNROLL( ptr ) __assume(ptr) // this oddly keeps msvc from unrolling a loop -#elif defined( __clang__ ) - #define STBIR_STREAMOUT_PTR( star ) star __restrict__ - #define STBIR_NO_UNROLL( ptr ) __asm__ (""::"r"(ptr)) -#elif defined( __GNUC__ ) + #if _MSC_VER >= 1900 + #define STBIR_NO_UNROLL_LOOP_START __pragma(loop( no_vector )) + #else + #define STBIR_NO_UNROLL_LOOP_START + #endif +#elif defined( __clang__ ) + #define STBIR_STREAMOUT_PTR( star ) star __restrict__ + #define STBIR_NO_UNROLL( ptr ) __asm__ (""::"r"(ptr)) + #if ( __clang_major__ >= 4 ) || ( ( __clang_major__ >= 3 ) && ( __clang_minor__ >= 5 ) ) + #define STBIR_NO_UNROLL_LOOP_START _Pragma("clang loop unroll(disable)") _Pragma("clang loop vectorize(disable)") + #else + #define STBIR_NO_UNROLL_LOOP_START + #endif +#elif defined( __GNUC__ ) #define STBIR_STREAMOUT_PTR( star ) star __restrict__ #define STBIR_NO_UNROLL( ptr ) __asm__ (""::"r"(ptr)) + #if __GNUC__ >= 14 + #define STBIR_NO_UNROLL_LOOP_START _Pragma("GCC unroll 0") _Pragma("GCC novector") + #else + #define STBIR_NO_UNROLL_LOOP_START + #endif + #define STBIR_NO_UNROLL_LOOP_START_INF_FOR #else #define STBIR_STREAMOUT_PTR( star ) star #define STBIR_NO_UNROLL( ptr ) + #define STBIR_NO_UNROLL_LOOP_START +#endif + +#ifndef STBIR_NO_UNROLL_LOOP_START_INF_FOR +#define STBIR_NO_UNROLL_LOOP_START_INF_FOR STBIR_NO_UNROLL_LOOP_START #endif #ifdef STBIR_NO_SIMD // force simd off for whatever reason @@ -1223,7 +1274,7 @@ static stbir__inline stbir_uint8 stbir__linear_to_srgb_uchar(float in) #ifdef STBIR_SSE2 #include - + #define stbir__simdf __m128 #define stbir__simdi __m128i @@ -1254,7 +1305,7 @@ static stbir__inline stbir_uint8 stbir__linear_to_srgb_uchar(float in) #define stbir__simdi_store2( ptr, reg ) _mm_storel_epi64( (__m128i*)(ptr), (reg) ) #define stbir__prefetch( ptr ) _mm_prefetch((char*)(ptr), _MM_HINT_T0 ) - + #define stbir__simdi_expand_u8_to_u32(out0,out1,out2,out3,ireg) \ { \ stbir__simdi zero = _mm_setzero_si128(); \ @@ -1285,7 +1336,7 @@ static stbir__inline stbir_uint8 stbir__linear_to_srgb_uchar(float in) #define stbir__simdf_convert_float_to_uint8( f ) ((unsigned char)_mm_cvtsi128_si32(_mm_cvttps_epi32(_mm_max_ps(_mm_min_ps(f,STBIR__CONSTF(STBIR_max_uint8_as_float)),_mm_setzero_ps())))) #define stbir__simdf_convert_float_to_short( f ) ((unsigned short)_mm_cvtsi128_si32(_mm_cvttps_epi32(_mm_max_ps(_mm_min_ps(f,STBIR__CONSTF(STBIR_max_uint16_as_float)),_mm_setzero_ps())))) - #define stbir__simdi_to_int( i ) _mm_cvtsi128_si32(i) + #define stbir__simdi_to_int( i ) _mm_cvtsi128_si32(i) #define stbir__simdi_convert_i32_to_float(out, ireg) (out) = _mm_cvtepi32_ps( ireg ) #define stbir__simdf_add( out, reg0, reg1 ) (out) = _mm_add_ps( reg0, reg1 ) #define stbir__simdf_mult( out, reg0, reg1 ) (out) = _mm_mul_ps( reg0, reg1 ) @@ -1440,10 +1491,10 @@ static stbir__inline stbir_uint8 stbir__linear_to_srgb_uchar(float in) #define stbir__simdi8_convert_i32_to_float(out, ireg) (out) = _mm256_cvtepi32_ps( ireg ) #define stbir__simdf8_convert_float_to_i32( i, f ) (i) = _mm256_cvttps_epi32(f) - + #define stbir__simdf8_bot4s( out, a, b ) (out) = _mm256_permute2f128_ps(a,b, (0<<0)+(2<<4) ) #define stbir__simdf8_top4s( out, a, b ) (out) = _mm256_permute2f128_ps(a,b, (1<<0)+(3<<4) ) - + #define stbir__simdf8_gettop4( reg ) _mm256_extractf128_ps(reg,1) #ifdef STBIR_AVX2 @@ -1471,8 +1522,8 @@ static stbir__inline stbir_uint8 stbir__linear_to_srgb_uchar(float in) out = _mm256_castsi256_si128( _mm256_permute4x64_epi64( _mm256_packus_epi16( t, t ), (0<<0)+(2<<2)+(1<<4)+(3<<6) ) ); \ } - #define stbir__simdi8_expand_u16_to_u32(out,ireg) out = _mm256_unpacklo_epi16( _mm256_permute4x64_epi64(_mm256_castsi128_si256(ireg),(0<<0)+(2<<2)+(1<<4)+(3<<6)), _mm256_setzero_si256() ); - + #define stbir__simdi8_expand_u16_to_u32(out,ireg) out = _mm256_unpacklo_epi16( _mm256_permute4x64_epi64(_mm256_castsi128_si256(ireg),(0<<0)+(2<<2)+(1<<4)+(3<<6)), _mm256_setzero_si256() ); + #define stbir__simdf8_pack_to_16words(out,aa,bb) \ { \ stbir__simdf8 af,bf; \ @@ -1496,7 +1547,7 @@ static stbir__inline stbir_uint8 stbir__linear_to_srgb_uchar(float in) a = _mm_unpackhi_epi8( ireg, zero ); \ out1 = _mm256_setr_m128i( _mm_unpacklo_epi16( a, zero ), _mm_unpackhi_epi16( a, zero ) ); \ } - + #define stbir__simdf8_pack_to_16bytes(out,aa,bb) \ { \ stbir__simdi t; \ @@ -1514,7 +1565,7 @@ static stbir__inline stbir_uint8 stbir__linear_to_srgb_uchar(float in) t = _mm_packus_epi16( t, t ); \ out = _mm_castps_si128( _mm_shuffle_ps( _mm_castsi128_ps(out), _mm_castsi128_ps(t), (0<<0)+(1<<2)+(0<<4)+(1<<6) ) ); \ } - + #define stbir__simdi8_expand_u16_to_u32(out,ireg) \ { \ stbir__simdi a,b,zero = _mm_setzero_si128(); \ @@ -1549,7 +1600,6 @@ static stbir__inline stbir_uint8 stbir__linear_to_srgb_uchar(float in) #define stbir__simdf8_0123to2222( out, in ) (out) = stbir__simdf_swiz(_mm256_castps256_ps128(in), 2,2,2,2 ) - #define stbir__simdf8_load2( out, ptr ) (out) = _mm256_castsi256_ps(_mm256_castsi128_si256( _mm_loadl_epi64( (__m128i*)(ptr)) )) // top values can be random (not denormal or nan for perf) #define stbir__simdf8_load4b( out, ptr ) (out) = _mm256_broadcast_ps( (__m128 const *)(ptr) ) static __m256i stbir_00112233 = { STBIR__CONST_4d_32i( 0, 0, 1, 1 ), STBIR__CONST_4d_32i( 2, 2, 3, 3 ) }; @@ -1582,11 +1632,11 @@ static stbir__inline stbir_uint8 stbir__linear_to_srgb_uchar(float in) #ifdef STBIR_USE_FMA // not on by default to maintain bit identical simd to non-simd #define stbir__simdf8_madd( out, add, mul1, mul2 ) (out) = _mm256_fmadd_ps( mul1, mul2, add ) #define stbir__simdf8_madd_mem( out, add, mul, ptr ) (out) = _mm256_fmadd_ps( mul, _mm256_loadu_ps( (float const*)(ptr) ), add ) - #define stbir__simdf8_madd_mem4( out, add, mul, ptr ) (out) = _mm256_fmadd_ps( _mm256_castps128_ps256( mul ), _mm256_castps128_ps256( _mm_loadu_ps( (float const*)(ptr) ) ), add ) + #define stbir__simdf8_madd_mem4( out, add, mul, ptr )(out) = _mm256_fmadd_ps( _mm256_setr_m128( mul, _mm_setzero_ps() ), _mm256_setr_m128( _mm_loadu_ps( (float const*)(ptr) ), _mm_setzero_ps() ), add ) #else #define stbir__simdf8_madd( out, add, mul1, mul2 ) (out) = _mm256_add_ps( add, _mm256_mul_ps( mul1, mul2 ) ) #define stbir__simdf8_madd_mem( out, add, mul, ptr ) (out) = _mm256_add_ps( add, _mm256_mul_ps( mul, _mm256_loadu_ps( (float const*)(ptr) ) ) ) - #define stbir__simdf8_madd_mem4( out, add, mul, ptr ) (out) = _mm256_add_ps( add, _mm256_castps128_ps256( _mm_mul_ps( mul, _mm_loadu_ps( (float const*)(ptr) ) ) ) ) + #define stbir__simdf8_madd_mem4( out, add, mul, ptr ) (out) = _mm256_add_ps( add, _mm256_setr_m128( _mm_mul_ps( mul, _mm_loadu_ps( (float const*)(ptr) ) ), _mm_setzero_ps() ) ) #endif #define stbir__if_simdf8_cast_to_simdf4( val ) _mm256_castps256_ps128( val ) @@ -1627,7 +1677,7 @@ static stbir__inline stbir_uint8 stbir__linear_to_srgb_uchar(float in) } #elif defined(STBIR_NEON) - + #include #define stbir__simdf float32x4_t @@ -1686,7 +1736,7 @@ static stbir__inline stbir_uint8 stbir__linear_to_srgb_uchar(float in) #define stbir__simdf_convert_float_to_i32( i, f ) (i) = vreinterpretq_u32_s32( vcvtq_s32_f32(f) ) #define stbir__simdf_convert_float_to_int( f ) vgetq_lane_s32(vcvtq_s32_f32(f), 0) - #define stbir__simdi_to_int( i ) (int)vgetq_lane_u32(i, 0) + #define stbir__simdi_to_int( i ) (int)vgetq_lane_u32(i, 0) #define stbir__simdf_convert_float_to_uint8( f ) ((unsigned char)vgetq_lane_s32(vcvtq_s32_f32(vmaxq_f32(vminq_f32(f,STBIR__CONSTF(STBIR_max_uint8_as_float)),vdupq_n_f32(0))), 0)) #define stbir__simdf_convert_float_to_short( f ) ((unsigned short)vgetq_lane_s32(vcvtq_s32_f32(vmaxq_f32(vminq_f32(f,STBIR__CONSTF(STBIR_max_uint16_as_float)),vdupq_n_f32(0))), 0)) #define stbir__simdi_convert_i32_to_float(out, ireg) (out) = vcvtq_f32_s32( vreinterpretq_s32_u32(ireg) ) @@ -1737,12 +1787,20 @@ static stbir__inline stbir_uint8 stbir__linear_to_srgb_uchar(float in) ((stbir_uint64)(4*b+0)<<32) | ((stbir_uint64)(4*b+1)<<40) | ((stbir_uint64)(4*b+2)<<48) | ((stbir_uint64)(4*b+3)<<56)), \ vcreate_u8( (4*c+0) | ((4*c+1)<<8) | ((4*c+2)<<16) | ((4*c+3)<<24) | \ ((stbir_uint64)(4*d+0)<<32) | ((stbir_uint64)(4*d+1)<<40) | ((stbir_uint64)(4*d+2)<<48) | ((stbir_uint64)(4*d+3)<<56) ) ) + + static stbir__inline uint8x16x2_t stbir_make16x2(float32x4_t rega,float32x4_t regb) + { + uint8x16x2_t r = { vreinterpretq_u8_f32(rega), vreinterpretq_u8_f32(regb) }; + return r; + } #else #define stbir_make16(a,b,c,d) (uint8x16_t){4*a+0,4*a+1,4*a+2,4*a+3,4*b+0,4*b+1,4*b+2,4*b+3,4*c+0,4*c+1,4*c+2,4*c+3,4*d+0,4*d+1,4*d+2,4*d+3} + #define stbir_make16x2(a,b) (uint8x16x2_t){{vreinterpretq_u8_f32(a),vreinterpretq_u8_f32(b)}} #endif #define stbir__simdf_swiz( reg, one, two, three, four ) vreinterpretq_f32_u8( vqtbl1q_u8( vreinterpretq_u8_f32(reg), stbir_make16(one, two, three, four) ) ) - + #define stbir__simdf_swiz2( rega, regb, one, two, three, four ) vreinterpretq_f32_u8( vqtbl2q_u8( stbir_make16x2(rega,regb), stbir_make16(one, two, three, four) ) ) + #define stbir__simdi_16madd( out, reg0, reg1 ) \ { \ int16x8_t r0 = vreinterpretq_s16_u32(reg0); \ @@ -1942,7 +2000,7 @@ static stbir__inline stbir_uint8 stbir__linear_to_srgb_uchar(float in) #define stbir__simdf_convert_float_to_i32( i, f ) (i) = wasm_i32x4_trunc_sat_f32x4(f) #define stbir__simdf_convert_float_to_int( f ) wasm_i32x4_extract_lane(wasm_i32x4_trunc_sat_f32x4(f), 0) - #define stbir__simdi_to_int( i ) wasm_i32x4_extract_lane(i, 0) + #define stbir__simdi_to_int( i ) wasm_i32x4_extract_lane(i, 0) #define stbir__simdf_convert_float_to_uint8( f ) ((unsigned char)wasm_i32x4_extract_lane(wasm_i32x4_trunc_sat_f32x4(wasm_f32x4_max(wasm_f32x4_min(f,STBIR_max_uint8_as_float),wasm_f32x4_const_splat(0))), 0)) #define stbir__simdf_convert_float_to_short( f ) ((unsigned short)wasm_i32x4_extract_lane(wasm_i32x4_trunc_sat_f32x4(wasm_f32x4_max(wasm_f32x4_min(f,STBIR_max_uint16_as_float),wasm_f32x4_const_splat(0))), 0)) #define stbir__simdi_convert_i32_to_float(out, ireg) (out) = wasm_f32x4_convert_i32x4(ireg) @@ -2125,7 +2183,7 @@ static stbir__inline stbir_uint8 stbir__linear_to_srgb_uchar(float in) #endif -#if defined(STBIR_NEON) && !defined(_M_ARM) +#if defined(STBIR_NEON) && !defined(_M_ARM) && !defined(__arm__) #if defined( _MSC_VER ) && !defined(__clang__) typedef __int16 stbir__FP16; @@ -2142,7 +2200,7 @@ static stbir__inline stbir_uint8 stbir__linear_to_srgb_uchar(float in) #endif -#if !defined(STBIR_NEON) && !defined(STBIR_FP16C) || defined(STBIR_NEON) && defined(_M_ARM) +#if (!defined(STBIR_NEON) && !defined(STBIR_FP16C)) || (defined(STBIR_NEON) && defined(_M_ARM)) || (defined(STBIR_NEON) && defined(__arm__)) // Fabian's half float routines, see: https://gist.github.com/rygorous/2156668 @@ -2168,7 +2226,7 @@ static stbir__inline stbir_uint8 stbir__linear_to_srgb_uchar(float in) unsigned int sign_mask = 0x80000000u; stbir__FP16 o = { 0 }; stbir__FP32 f; - unsigned int sign; + unsigned int sign; f.f = val; sign = f.u & sign_mask; @@ -2369,24 +2427,6 @@ static stbir__inline stbir_uint8 stbir__linear_to_srgb_uchar(float in) stbir__simdi_store( output,final ); } -#elif defined(STBIR_WASM) || (defined(STBIR_NEON) && defined(_MSC_VER) && defined(_M_ARM)) // WASM or 32-bit ARM on MSVC/clang - - static stbir__inline void stbir__half_to_float_SIMD(float * output, stbir__FP16 const * input) - { - for (int i=0; i<8; i++) - { - output[i] = stbir__half_to_float(input[i]); - } - } - - static stbir__inline void stbir__float_to_half_SIMD(stbir__FP16 * output, float const * input) - { - for (int i=0; i<8; i++) - { - output[i] = stbir__float_to_half(input[i]); - } - } - #elif defined(STBIR_NEON) && defined(_MSC_VER) && defined(_M_ARM64) && !defined(__clang__) // 64-bit ARM on MSVC (not clang) static stbir__inline void stbir__half_to_float_SIMD(float * output, stbir__FP16 const * input) @@ -2415,7 +2455,7 @@ static stbir__inline stbir_uint8 stbir__linear_to_srgb_uchar(float in) return vget_lane_f16(vcvt_f16_f32(vdupq_n_f32(f)), 0).n16_u16[0]; } -#elif defined(STBIR_NEON) // 64-bit ARM +#elif defined(STBIR_NEON) && ( defined( _M_ARM64 ) || defined( __aarch64__ ) || defined( __arm64__ ) ) // 64-bit ARM static stbir__inline void stbir__half_to_float_SIMD(float * output, stbir__FP16 const * input) { @@ -2441,6 +2481,23 @@ static stbir__inline stbir_uint8 stbir__linear_to_srgb_uchar(float in) return vget_lane_f16(vcvt_f16_f32(vdupq_n_f32(f)), 0); } +#elif defined(STBIR_WASM) || (defined(STBIR_NEON) && (defined(_MSC_VER) || defined(_M_ARM) || defined(__arm__))) // WASM or 32-bit ARM on MSVC/clang + + static stbir__inline void stbir__half_to_float_SIMD(float * output, stbir__FP16 const * input) + { + for (int i=0; i<8; i++) + { + output[i] = stbir__half_to_float(input[i]); + } + } + static stbir__inline void stbir__float_to_half_SIMD(stbir__FP16 * output, float const * input) + { + for (int i=0; i<8; i++) + { + output[i] = stbir__float_to_half(input[i]); + } + } + #endif @@ -2462,10 +2519,10 @@ static stbir__inline stbir_uint8 stbir__linear_to_srgb_uchar(float in) #define stbir__simdf_0123to3012( out, reg ) (out) = stbir__simdf_swiz( reg, 3,0,1,2 ) #define stbir__simdf_0123to0011( out, reg ) (out) = stbir__simdf_swiz( reg, 0,0,1,1 ) #define stbir__simdf_0123to1100( out, reg ) (out) = stbir__simdf_swiz( reg, 1,1,0,0 ) -#define stbir__simdf_0123to2233( out, reg ) (out) = stbir__simdf_swiz( reg, 2,2,3,3 ) -#define stbir__simdf_0123to1133( out, reg ) (out) = stbir__simdf_swiz( reg, 1,1,3,3 ) -#define stbir__simdf_0123to0022( out, reg ) (out) = stbir__simdf_swiz( reg, 0,0,2,2 ) -#define stbir__simdf_0123to1032( out, reg ) (out) = stbir__simdf_swiz( reg, 1,0,3,2 ) +#define stbir__simdf_0123to2233( out, reg ) (out) = stbir__simdf_swiz( reg, 2,2,3,3 ) +#define stbir__simdf_0123to1133( out, reg ) (out) = stbir__simdf_swiz( reg, 1,1,3,3 ) +#define stbir__simdf_0123to0022( out, reg ) (out) = stbir__simdf_swiz( reg, 0,0,2,2 ) +#define stbir__simdf_0123to1032( out, reg ) (out) = stbir__simdf_swiz( reg, 1,0,3,2 ) typedef union stbir__simdi_u32 { @@ -2493,14 +2550,16 @@ static const STBIR__SIMDI_CONST(STBIR_topscale, 0x02000000); // Adding this switch saves about 5K on clang which is Captain Unroll the 3rd. #define STBIR_SIMD_STREAMOUT_PTR( star ) STBIR_STREAMOUT_PTR( star ) #define STBIR_SIMD_NO_UNROLL(ptr) STBIR_NO_UNROLL(ptr) +#define STBIR_SIMD_NO_UNROLL_LOOP_START STBIR_NO_UNROLL_LOOP_START +#define STBIR_SIMD_NO_UNROLL_LOOP_START_INF_FOR STBIR_NO_UNROLL_LOOP_START_INF_FOR #ifdef STBIR_MEMCPY #undef STBIR_MEMCPY -#define STBIR_MEMCPY stbir_simd_memcpy #endif +#define STBIR_MEMCPY stbir_simd_memcpy // override normal use of memcpy with much simpler copy (faster and smaller with our sized copies) -static void stbir_simd_memcpy( void * dest, void const * src, size_t bytes ) +static void stbir_simd_memcpy( void * dest, void const * src, size_t bytes ) { char STBIR_SIMD_STREAMOUT_PTR (*) d = (char*) dest; char STBIR_SIMD_STREAMOUT_PTR( * ) d_end = ((char*) dest) + bytes; @@ -2513,8 +2572,9 @@ static void stbir_simd_memcpy( void * dest, void const * src, size_t bytes ) { if ( bytes < 16 ) { - if ( bytes ) + if ( bytes ) { + STBIR_SIMD_NO_UNROLL_LOOP_START do { STBIR_SIMD_NO_UNROLL(d); @@ -2529,8 +2589,9 @@ static void stbir_simd_memcpy( void * dest, void const * src, size_t bytes ) // do one unaligned to get us aligned for the stream out below stbir__simdf_load( x, ( d + ofs_to_src ) ); stbir__simdf_store( d, x ); - d = (char*)( ( ( (ptrdiff_t)d ) + 16 ) & ~15 ); + d = (char*)( ( ( (size_t)d ) + 16 ) & ~15 ); + STBIR_SIMD_NO_UNROLL_LOOP_START_INF_FOR for(;;) { STBIR_SIMD_NO_UNROLL(d); @@ -2561,12 +2622,13 @@ static void stbir_simd_memcpy( void * dest, void const * src, size_t bytes ) stbir__simdfX_store( d + 4*stbir__simdfX_float_count, x1 ); stbir__simdfX_store( d + 8*stbir__simdfX_float_count, x2 ); stbir__simdfX_store( d + 12*stbir__simdfX_float_count, x3 ); - d = (char*)( ( ( (ptrdiff_t)d ) + (16*stbir__simdfX_float_count) ) & ~((16*stbir__simdfX_float_count)-1) ); + d = (char*)( ( ( (size_t)d ) + (16*stbir__simdfX_float_count) ) & ~((16*stbir__simdfX_float_count)-1) ); + STBIR_SIMD_NO_UNROLL_LOOP_START_INF_FOR for(;;) { STBIR_SIMD_NO_UNROLL(d); - + if ( d > ( d_end - (16*stbir__simdfX_float_count) ) ) { if ( d == d_end ) @@ -2590,7 +2652,7 @@ static void stbir_simd_memcpy( void * dest, void const * src, size_t bytes ) // memcpy that is specically intentionally overlapping (src is smaller then dest, so can be // a normal forward copy, bytes is divisible by 4 and bytes is greater than or equal to // the diff between dest and src) -static void stbir_overlapping_memcpy( void * dest, void const * src, size_t bytes ) +static void stbir_overlapping_memcpy( void * dest, void const * src, size_t bytes ) { char STBIR_SIMD_STREAMOUT_PTR (*) sd = (char*) src; char STBIR_SIMD_STREAMOUT_PTR( * ) s_end = ((char*) src) + bytes; @@ -2599,6 +2661,7 @@ static void stbir_overlapping_memcpy( void * dest, void const * src, size_t byte if ( ofs_to_dest >= 16 ) // is the overlap more than 16 away? { char STBIR_SIMD_STREAMOUT_PTR( * ) s_end16 = ((char*) src) + (bytes&~15); + STBIR_SIMD_NO_UNROLL_LOOP_START do { stbir__simdf x; @@ -2615,7 +2678,7 @@ static void stbir_overlapping_memcpy( void * dest, void const * src, size_t byte do { STBIR_SIMD_NO_UNROLL(sd); - *(int*)( sd + ofs_to_dest ) = *(int*) sd; + *(int*)( sd + ofs_to_dest ) = *(int*) sd; sd += 4; } while ( sd < s_end ); } @@ -2624,13 +2687,17 @@ static void stbir_overlapping_memcpy( void * dest, void const * src, size_t byte // when in scalar mode, we let unrolling happen, so this macro just does the __restrict #define STBIR_SIMD_STREAMOUT_PTR( star ) STBIR_STREAMOUT_PTR( star ) -#define STBIR_SIMD_NO_UNROLL(ptr) +#define STBIR_SIMD_NO_UNROLL(ptr) +#define STBIR_SIMD_NO_UNROLL_LOOP_START +#define STBIR_SIMD_NO_UNROLL_LOOP_START_INF_FOR #endif // SSE2 #ifdef STBIR_PROFILE +#ifndef STBIR_PROFILE_FUNC + #if defined(_x86_64) || defined( __x86_64__ ) || defined( _M_X64 ) || defined(__x86_64) || defined(__SSE2__) || defined(STBIR_SSE) || defined( _M_IX86_FP ) || defined(__i386) || defined( __i386__ ) || defined( _M_IX86 ) || defined( _X86_ ) #ifdef _MSC_VER @@ -2640,7 +2707,7 @@ static void stbir_overlapping_memcpy( void * dest, void const * src, size_t byte #else // non msvc - static stbir__inline stbir_uint64 STBIR_PROFILE_FUNC() + static stbir__inline stbir_uint64 STBIR_PROFILE_FUNC() { stbir_uint32 lo, hi; asm volatile ("rdtsc" : "=a" (lo), "=d" (hi) ); @@ -2649,7 +2716,7 @@ static void stbir_overlapping_memcpy( void * dest, void const * src, size_t byte #endif // msvc -#elif defined( _M_ARM64 ) || defined( __aarch64__ ) || defined( __arm64__ ) || defined(__ARM_NEON__) +#elif defined( _M_ARM64 ) || defined( __aarch64__ ) || defined( __arm64__ ) || defined(__ARM_NEON__) #if defined( _MSC_VER ) && !defined(__clang__) @@ -2670,8 +2737,9 @@ static void stbir_overlapping_memcpy( void * dest, void const * src, size_t byte #error Unknown platform for profiling. -#endif //x64 and +#endif // x64, arm +#endif // STBIR_PROFILE_FUNC #define STBIR_ONLY_PROFILE_GET_SPLIT_INFO ,stbir__per_split_info * split_info #define STBIR_ONLY_PROFILE_SET_SPLIT_INFO ,split_info @@ -2680,7 +2748,7 @@ static void stbir_overlapping_memcpy( void * dest, void const * src, size_t byte #define STBIR_ONLY_PROFILE_BUILD_SET_INFO ,profile_info // super light-weight micro profiler -#define STBIR_PROFILE_START_ll( info, wh ) { stbir_uint64 wh##thiszonetime = STBIR_PROFILE_FUNC(); stbir_uint64 * wh##save_parent_excluded_ptr = info->current_zone_excluded_ptr; stbir_uint64 wh##current_zone_excluded = 0; info->current_zone_excluded_ptr = &wh##current_zone_excluded; +#define STBIR_PROFILE_START_ll( info, wh ) { stbir_uint64 wh##thiszonetime = STBIR_PROFILE_FUNC(); stbir_uint64 * wh##save_parent_excluded_ptr = info->current_zone_excluded_ptr; stbir_uint64 wh##current_zone_excluded = 0; info->current_zone_excluded_ptr = &wh##current_zone_excluded; #define STBIR_PROFILE_END_ll( info, wh ) wh##thiszonetime = STBIR_PROFILE_FUNC() - wh##thiszonetime; info->profile.named.wh += wh##thiszonetime - wh##current_zone_excluded; *wh##save_parent_excluded_ptr += wh##thiszonetime; info->current_zone_excluded_ptr = wh##save_parent_excluded_ptr; } #define STBIR_PROFILE_FIRST_START_ll( info, wh ) { int i; info->current_zone_excluded_ptr = &info->profile.named.total; for(i=0;iprofile.array);i++) info->profile.array[i]=0; } STBIR_PROFILE_START_ll( info, wh ); #define STBIR_PROFILE_CLEAR_EXTRAS_ll( info, num ) { int extra; for(extra=1;extra<(num);extra++) { int i; for(i=0;iprofile.array);i++) (info)[extra].profile.array[i]=0; } } @@ -2710,8 +2778,8 @@ static void stbir_overlapping_memcpy( void * dest, void const * src, size_t byte #define STBIR_PROFILE_FIRST_START( wh ) #define STBIR_PROFILE_CLEAR_EXTRAS( ) -#define STBIR_PROFILE_BUILD_START( wh ) -#define STBIR_PROFILE_BUILD_END( wh ) +#define STBIR_PROFILE_BUILD_START( wh ) +#define STBIR_PROFILE_BUILD_END( wh ) #define STBIR_PROFILE_BUILD_FIRST_START( wh ) #define STBIR_PROFILE_BUILD_CLEAR( info ) @@ -2736,10 +2804,10 @@ static void stbir_overlapping_memcpy( void * dest, void const * src, size_t byte #ifndef STBIR_SIMD -// memcpy that is specically intentionally overlapping (src is smaller then dest, so can be +// memcpy that is specifically intentionally overlapping (src is smaller then dest, so can be // a normal forward copy, bytes is divisible by 4 and bytes is greater than or equal to // the diff between dest and src) -static void stbir_overlapping_memcpy( void * dest, void const * src, size_t bytes ) +static void stbir_overlapping_memcpy( void * dest, void const * src, size_t bytes ) { char STBIR_SIMD_STREAMOUT_PTR (*) sd = (char*) src; char STBIR_SIMD_STREAMOUT_PTR( * ) s_end = ((char*) src) + bytes; @@ -2748,10 +2816,11 @@ static void stbir_overlapping_memcpy( void * dest, void const * src, size_t byte if ( ofs_to_dest >= 8 ) // is the overlap more than 8 away? { char STBIR_SIMD_STREAMOUT_PTR( * ) s_end8 = ((char*) src) + (bytes&~7); + STBIR_NO_UNROLL_LOOP_START do { STBIR_NO_UNROLL(sd); - *(stbir_uint64*)( sd + ofs_to_dest ) = *(stbir_uint64*) sd; + *(stbir_uint64*)( sd + ofs_to_dest ) = *(stbir_uint64*) sd; sd += 8; } while ( sd < s_end8 ); @@ -2759,10 +2828,11 @@ static void stbir_overlapping_memcpy( void * dest, void const * src, size_t byte return; } + STBIR_NO_UNROLL_LOOP_START do { STBIR_NO_UNROLL(sd); - *(int*)( sd + ofs_to_dest ) = *(int*) sd; + *(int*)( sd + ofs_to_dest ) = *(int*) sd; sd += 4; } while ( sd < s_end ); } @@ -2863,13 +2933,6 @@ static float stbir__filter_mitchell(float x, float s, void * user_data) return (0.0f); } -static float stbir__support_zero(float s, void * user_data) -{ - STBIR__UNUSED(s); - STBIR__UNUSED(user_data); - return 0; -} - static float stbir__support_zeropoint5(float s, void * user_data) { STBIR__UNUSED(s); @@ -2884,7 +2947,7 @@ static float stbir__support_one(float s, void * user_data) return 1; } -static float stbir__support_two(float s, void * user_data) +static float stbir__support_two(float s, void * user_data) { STBIR__UNUSED(s); STBIR__UNUSED(user_data); @@ -2903,7 +2966,7 @@ static int stbir__get_filter_pixel_width(stbir__support_callback * support, floa return (int)STBIR_CEILF(support(scale,user_data) * 2.0f / scale); } -// this is how many coefficents per run of the filter (which is different +// this is how many coefficents per run of the filter (which is different // from the filter_pixel_width depending on if we are scattering or gathering) static int stbir__get_coefficient_width(stbir__sampler * samp, int is_gather, void * user_data) { @@ -2924,7 +2987,7 @@ static int stbir__get_coefficient_width(stbir__sampler * samp, int is_gather, vo } } -static int stbir__get_contributors(stbir__sampler * samp, int is_gather) +static int stbir__get_contributors(stbir__sampler * samp, int is_gather) { if (is_gather) return samp->scale_info.output_sub_size; @@ -2954,7 +3017,7 @@ static int stbir__edge_reflect_full( int n, int max ) { if (n < 0) { - if (n > -max) + if (n > -max) return -n; else return max - 1; @@ -3056,7 +3119,7 @@ static void stbir__get_extents( stbir__sampler * samp, stbir__extents * scanline left_margin = -min_n; min_n = 0; } - + right_margin = 0; if ( max_n >= input_full_size ) { @@ -3081,7 +3144,7 @@ static void stbir__get_extents( stbir__sampler * samp, stbir__extents * scanline // don't have to do edge calc for zero clamp if ( edge == STBIR_EDGE_ZERO ) return; - + // convert margin pixels to the pixels within the input (min and max) for( j = -left_margin ; j < 0 ; j++ ) { @@ -3179,20 +3242,20 @@ static void stbir__calculate_in_pixel_range( int * first_pixel, int * last_pixel float out_pixel_influence_lowerbound = out_pixel_center - out_filter_radius; float out_pixel_influence_upperbound = out_pixel_center + out_filter_radius; - float in_pixel_influence_lowerbound = (out_pixel_influence_lowerbound + out_shift) * inv_scale; - float in_pixel_influence_upperbound = (out_pixel_influence_upperbound + out_shift) * inv_scale; + float in_pixel_influence_lowerbound = (out_pixel_influence_lowerbound + out_shift) * inv_scale; + float in_pixel_influence_upperbound = (out_pixel_influence_upperbound + out_shift) * inv_scale; first = (int)(STBIR_FLOORF(in_pixel_influence_lowerbound + 0.5f)); last = (int)(STBIR_FLOORF(in_pixel_influence_upperbound - 0.5f)); if ( edge == STBIR_EDGE_WRAP ) { - if ( first <= -input_size ) - first = -(input_size-1); + if ( first < -input_size ) + first = -input_size; if ( last >= (input_size*2)) last = (input_size*2) - 1; } - + *first_pixel = first; *last_pixel = last; } @@ -3213,10 +3276,10 @@ static void stbir__calculate_coefficients_for_gather_upsample( float out_filter_ int i; int last_non_zero; float out_pixel_center = (float)n + 0.5f; - float in_center_of_out = (out_pixel_center + out_shift) * inv_scale; + float in_center_of_out = (out_pixel_center + out_shift) * inv_scale; int in_first_pixel, in_last_pixel; - + stbir__calculate_in_pixel_range( &in_first_pixel, &in_last_pixel, out_pixel_center, out_filter_radius, inv_scale, out_shift, input_size, edge ); last_non_zero = -1; @@ -3229,7 +3292,7 @@ static void stbir__calculate_coefficients_for_gather_upsample( float out_filter_ if ( ( ( coeff < stbir__small_float ) && ( coeff > -stbir__small_float ) ) ) { if ( i == 0 ) // if we're at the front, just eat zero contributors - { + { STBIR_ASSERT ( ( in_last_pixel - in_first_pixel ) != 0 ); // there should be at least one contrib ++in_first_pixel; i--; @@ -3239,10 +3302,10 @@ static void stbir__calculate_coefficients_for_gather_upsample( float out_filter_ } else last_non_zero = i; - + coefficient_group[i] = coeff; } - + in_last_pixel = last_non_zero+in_first_pixel; // kills trailing zeros contributors->n0 = in_first_pixel; contributors->n1 = in_last_pixel; @@ -3354,7 +3417,7 @@ static void stbir__calculate_coefficients_for_gather_downsample( int start, int stbir__contributors * contribs = contributors + out; // is this the first time this output pixel has been seen? Init it. - if ( out > first_out_inited ) + if ( out > first_out_inited ) { STBIR_ASSERT( out == ( first_out_inited + 1 ) ); // ensure we have only advanced one at time first_out_inited = out; @@ -3362,7 +3425,7 @@ static void stbir__calculate_coefficients_for_gather_downsample( int start, int contribs->n1 = in_pixel; coeffs[0] = coeff; } - else + else { // insert on end (always in order) if ( coeffs[0] == 0.0f ) // if the first coefficent is zero, then zap it for this coeffs @@ -3379,10 +3442,16 @@ static void stbir__calculate_coefficients_for_gather_downsample( int start, int } } +#ifdef STBIR_RENORMALIZE_IN_FLOAT +#define STBIR_RENORM_TYPE float +#else +#define STBIR_RENORM_TYPE double +#endif + static void stbir__cleanup_gathered_coefficients( stbir_edge edge, stbir__filter_extent_info* filter_info, stbir__scale_info * scale_info, int num_contributors, stbir__contributors* contributors, float * coefficient_group, int coefficient_width ) { int input_size = scale_info->input_full_size; - int input_last_n1 = input_size - 1; + int input_last_n1 = input_size - 1; int n, end; int lowest = 0x7fffffff; int highest = -0x7fffffff; @@ -3400,14 +3469,14 @@ static void stbir__cleanup_gathered_coefficients( stbir_edge edge, stbir__filter for (n = 0; n < end; n++) { int i; - float filter_scale, total_filter = 0; + STBIR_RENORM_TYPE filter_scale, total_filter = 0; int e; // add all contribs e = contribs->n1 - contribs->n0; for( i = 0 ; i <= e ; i++ ) { - total_filter += coeffs[i]; + total_filter += (STBIR_RENORM_TYPE) coeffs[i]; STBIR_ASSERT( ( coeffs[i] >= -2.0f ) && ( coeffs[i] <= 2.0f ) ); // check for wonky weights } @@ -3423,10 +3492,11 @@ static void stbir__cleanup_gathered_coefficients( stbir_edge edge, stbir__filter // if the total isn't 1.0, rescale everything if ( ( total_filter < (1.0f-stbir__small_float) ) || ( total_filter > (1.0f+stbir__small_float) ) ) { - filter_scale = 1.0f / total_filter; + filter_scale = ((STBIR_RENORM_TYPE)1.0) / total_filter; + // scale them all for (i = 0; i <= e; i++) - coeffs[i] *= filter_scale; + coeffs[i] = (float) ( coeffs[i] * filter_scale ); } } ++contribs; @@ -3483,13 +3553,13 @@ static void stbir__cleanup_gathered_coefficients( stbir_edge edge, stbir__filter else if ( ( edge == STBIR_EDGE_CLAMP ) || ( edge == STBIR_EDGE_REFLECT ) ) { // for clamp and reflect, calculate the true inbounds position (based on edge type) and just add that to the existing weight - + // right hand side first if ( contribs->n1 > input_last_n1 ) { int start = contribs->n0; int endi = contribs->n1; - contribs->n1 = input_last_n1; + contribs->n1 = input_last_n1; for( i = input_size; i <= endi; i++ ) stbir__insert_coeff( contribs, coeffs, stbir__edge_wrap_slow[edge]( i, input_size ), coeffs[i-start] ); } @@ -3500,18 +3570,18 @@ static void stbir__cleanup_gathered_coefficients( stbir_edge edge, stbir__filter int save_n0; float save_n0_coeff; float * c = coeffs - ( contribs->n0 + 1 ); - + // reinsert the coeffs with it reflected or clamped (insert accumulates, if the coeffs exist) - for( i = -1 ; i > contribs->n0 ; i-- ) + for( i = -1 ; i > contribs->n0 ; i-- ) stbir__insert_coeff( contribs, coeffs, stbir__edge_wrap_slow[edge]( i, input_size ), *c-- ); save_n0 = contribs->n0; save_n0_coeff = c[0]; // save it, since we didn't do the final one (i==n0), because there might be too many coeffs to hold (before we resize)! // now slide all the coeffs down (since we have accumulated them in the positive contribs) and reset the first contrib - contribs->n0 = 0; + contribs->n0 = 0; for(i = 0 ; i <= contribs->n1 ; i++ ) coeffs[i] = coeffs[i-save_n0]; - + // now that we have shrunk down the contribs, we insert the first one safely stbir__insert_coeff( contribs, coeffs, stbir__edge_wrap_slow[edge]( save_n0, input_size ), save_n0_coeff ); } @@ -3547,7 +3617,9 @@ static void stbir__cleanup_gathered_coefficients( stbir_edge edge, stbir__filter filter_info->widest = widest; } -static int stbir__pack_coefficients( int num_contributors, stbir__contributors* contributors, float * coefficents, int coefficient_width, int widest, int row_width ) +#undef STBIR_RENORM_TYPE + +static int stbir__pack_coefficients( int num_contributors, stbir__contributors* contributors, float * coefficents, int coefficient_width, int widest, int row0, int row1 ) { #define STBIR_MOVE_1( dest, src ) { STBIR_NO_UNROLL(dest); ((stbir_uint32*)(dest))[0] = ((stbir_uint32*)(src))[0]; } #define STBIR_MOVE_2( dest, src ) { STBIR_NO_UNROLL(dest); ((stbir_uint64*)(dest))[0] = ((stbir_uint64*)(src))[0]; } @@ -3556,6 +3628,10 @@ static int stbir__pack_coefficients( int num_contributors, stbir__contributors* #else #define STBIR_MOVE_4( dest, src ) { STBIR_NO_UNROLL(dest); ((stbir_uint64*)(dest))[0] = ((stbir_uint64*)(src))[0]; ((stbir_uint64*)(dest))[1] = ((stbir_uint64*)(src))[1]; } #endif + + int row_end = row1 + 1; + STBIR__UNUSED( row0 ); // only used in an assert + if ( coefficient_width != widest ) { float * pc = coefficents; @@ -3564,6 +3640,7 @@ static int stbir__pack_coefficients( int num_contributors, stbir__contributors* switch( widest ) { case 1: + STBIR_NO_UNROLL_LOOP_START do { STBIR_MOVE_1( pc, coeffs ); ++pc; @@ -3571,6 +3648,7 @@ static int stbir__pack_coefficients( int num_contributors, stbir__contributors* } while ( pc < pc_end ); break; case 2: + STBIR_NO_UNROLL_LOOP_START do { STBIR_MOVE_2( pc, coeffs ); pc += 2; @@ -3578,6 +3656,7 @@ static int stbir__pack_coefficients( int num_contributors, stbir__contributors* } while ( pc < pc_end ); break; case 3: + STBIR_NO_UNROLL_LOOP_START do { STBIR_MOVE_2( pc, coeffs ); STBIR_MOVE_1( pc+2, coeffs+2 ); @@ -3586,6 +3665,7 @@ static int stbir__pack_coefficients( int num_contributors, stbir__contributors* } while ( pc < pc_end ); break; case 4: + STBIR_NO_UNROLL_LOOP_START do { STBIR_MOVE_4( pc, coeffs ); pc += 4; @@ -3593,6 +3673,7 @@ static int stbir__pack_coefficients( int num_contributors, stbir__contributors* } while ( pc < pc_end ); break; case 5: + STBIR_NO_UNROLL_LOOP_START do { STBIR_MOVE_4( pc, coeffs ); STBIR_MOVE_1( pc+4, coeffs+4 ); @@ -3601,6 +3682,7 @@ static int stbir__pack_coefficients( int num_contributors, stbir__contributors* } while ( pc < pc_end ); break; case 6: + STBIR_NO_UNROLL_LOOP_START do { STBIR_MOVE_4( pc, coeffs ); STBIR_MOVE_2( pc+4, coeffs+4 ); @@ -3609,6 +3691,7 @@ static int stbir__pack_coefficients( int num_contributors, stbir__contributors* } while ( pc < pc_end ); break; case 7: + STBIR_NO_UNROLL_LOOP_START do { STBIR_MOVE_4( pc, coeffs ); STBIR_MOVE_2( pc+4, coeffs+4 ); @@ -3618,6 +3701,7 @@ static int stbir__pack_coefficients( int num_contributors, stbir__contributors* } while ( pc < pc_end ); break; case 8: + STBIR_NO_UNROLL_LOOP_START do { STBIR_MOVE_4( pc, coeffs ); STBIR_MOVE_4( pc+4, coeffs+4 ); @@ -3626,6 +3710,7 @@ static int stbir__pack_coefficients( int num_contributors, stbir__contributors* } while ( pc < pc_end ); break; case 9: + STBIR_NO_UNROLL_LOOP_START do { STBIR_MOVE_4( pc, coeffs ); STBIR_MOVE_4( pc+4, coeffs+4 ); @@ -3635,6 +3720,7 @@ static int stbir__pack_coefficients( int num_contributors, stbir__contributors* } while ( pc < pc_end ); break; case 10: + STBIR_NO_UNROLL_LOOP_START do { STBIR_MOVE_4( pc, coeffs ); STBIR_MOVE_4( pc+4, coeffs+4 ); @@ -3644,6 +3730,7 @@ static int stbir__pack_coefficients( int num_contributors, stbir__contributors* } while ( pc < pc_end ); break; case 11: + STBIR_NO_UNROLL_LOOP_START do { STBIR_MOVE_4( pc, coeffs ); STBIR_MOVE_4( pc+4, coeffs+4 ); @@ -3654,6 +3741,7 @@ static int stbir__pack_coefficients( int num_contributors, stbir__contributors* } while ( pc < pc_end ); break; case 12: + STBIR_NO_UNROLL_LOOP_START do { STBIR_MOVE_4( pc, coeffs ); STBIR_MOVE_4( pc+4, coeffs+4 ); @@ -3663,6 +3751,7 @@ static int stbir__pack_coefficients( int num_contributors, stbir__contributors* } while ( pc < pc_end ); break; default: + STBIR_NO_UNROLL_LOOP_START do { float * copy_end = pc + widest - 4; float * c = coeffs; @@ -3673,6 +3762,7 @@ static int stbir__pack_coefficients( int num_contributors, stbir__contributors* c += 4; } while ( pc <= copy_end ); copy_end += 4; + STBIR_NO_UNROLL_LOOP_START while ( pc < copy_end ) { STBIR_MOVE_1( pc, c ); @@ -3688,7 +3778,7 @@ static int stbir__pack_coefficients( int num_contributors, stbir__contributors* coefficents[ widest * num_contributors ] = 8888.0f; // the minimum we might read for unrolled filters widths is 12. So, we need to - // make sure we never read outside the decode buffer, by possibly moving + // make sure we never read outside the decode buffer, by possibly moving // the sample area back into the scanline, and putting zeros weights first. // we start on the right edge and check until we're well past the possible // clip area (2*widest). @@ -3697,13 +3787,13 @@ static int stbir__pack_coefficients( int num_contributors, stbir__contributors* float * coeffs = coefficents + widest * ( num_contributors - 1 ); // go until no chance of clipping (this is usually less than 8 lops) - while ( ( ( contribs->n0 + widest*2 ) >= row_width ) && ( contribs >= contributors ) ) + while ( ( contribs >= contributors ) && ( ( contribs->n0 + widest*2 ) >= row_end ) ) { // might we clip?? - if ( ( contribs->n0 + widest ) > row_width ) + if ( ( contribs->n0 + widest ) > row_end ) { int stop_range = widest; - + // if range is larger than 12, it will be handled by generic loops that can terminate on the exact length // of this contrib n1, instead of a fixed widest amount - so calculate this if ( widest > 12 ) @@ -3712,22 +3802,22 @@ static int stbir__pack_coefficients( int num_contributors, stbir__contributors* // how far will be read in the n_coeff loop (which depends on the widest count mod4); mod = widest & 3; - stop_range = ( ( ( contribs->n1 - contribs->n0 + 1 ) - mod + 3 ) & ~3 ) + mod; + stop_range = ( ( ( contribs->n1 - contribs->n0 + 1 ) - mod + 3 ) & ~3 ) + mod; // the n_coeff loops do a minimum amount of coeffs, so factor that in! if ( stop_range < ( 8 + mod ) ) stop_range = 8 + mod; } // now see if we still clip with the refined range - if ( ( contribs->n0 + stop_range ) > row_width ) + if ( ( contribs->n0 + stop_range ) > row_end ) { - int new_n0 = row_width - stop_range; + int new_n0 = row_end - stop_range; int num = contribs->n1 - contribs->n0 + 1; int backup = contribs->n0 - new_n0; float * from_co = coeffs + num - 1; float * to_co = from_co + backup; - STBIR_ASSERT( ( new_n0 >= 0 ) && ( new_n0 < contribs->n0 ) ); + STBIR_ASSERT( ( new_n0 >= row0 ) && ( new_n0 < contribs->n0 ) ); // move the coeffs over while( num ) @@ -3746,7 +3836,7 @@ static int stbir__pack_coefficients( int num_contributors, stbir__contributors* // how far will be read in the n_coeff loop (which depends on the widest count mod4); mod = widest & 3; - stop_range = ( ( ( contribs->n1 - contribs->n0 + 1 ) - mod + 3 ) & ~3 ) + mod; + stop_range = ( ( ( contribs->n1 - contribs->n0 + 1 ) - mod + 3 ) & ~3 ) + mod; // the n_coeff loops do a minimum amount of coeffs, so factor that in! if ( stop_range < ( 8 + mod ) ) stop_range = 8 + mod; @@ -3774,7 +3864,7 @@ static void stbir__calculate_filters( stbir__sampler * samp, stbir__sampler * ot int input_full_size = samp->scale_info.input_full_size; int gather_num_contributors = samp->num_contributors; stbir__contributors* gather_contributors = samp->contributors; - float * gather_coeffs = samp->coefficients; + float * gather_coeffs = samp->coefficients; int gather_coefficient_width = samp->coefficient_width; switch ( samp->is_gather ) @@ -3792,16 +3882,16 @@ static void stbir__calculate_filters( stbir__sampler * samp, stbir__sampler * ot break; case 0: // scatter downsample (only on vertical) - case 2: // gather downsample + case 2: // gather downsample { float in_pixels_radius = support(scale,user_data) * inv_scale; int filter_pixel_margin = samp->filter_pixel_margin; int input_end = input_full_size + filter_pixel_margin; - + // if this is a scatter, we do a downsample gather to get the coeffs, and then pivot after if ( !samp->is_gather ) { - // check if we are using the same gather downsample on the horizontal as this vertical, + // check if we are using the same gather downsample on the horizontal as this vertical, // if so, then we don't have to generate them, we can just pivot from the horizontal. if ( other_axis_for_pivot ) { @@ -3846,30 +3936,37 @@ static void stbir__calculate_filters( stbir__sampler * samp, stbir__sampler * ot float * scatter_coeffs = samp->coefficients + ( gn0 + filter_pixel_margin ) * scatter_coefficient_width; float * g_coeffs = gather_coeffs; scatter_contributors = samp->contributors + ( gn0 + filter_pixel_margin ); - + for (k = gn0 ; k <= gn1 ; k++ ) { float gc = *g_coeffs++; - if ( ( k > highest_set ) || ( scatter_contributors->n0 > scatter_contributors->n1 ) ) + + // skip zero and denormals - must skip zeros to avoid adding coeffs beyond scatter_coefficient_width + // (which happens when pivoting from horizontal, which might have dummy zeros) + if ( ( ( gc >= stbir__small_float ) || ( gc <= -stbir__small_float ) ) ) { + if ( ( k > highest_set ) || ( scatter_contributors->n0 > scatter_contributors->n1 ) ) { - // if we are skipping over several contributors, we need to clear the skipped ones - stbir__contributors * clear_contributors = samp->contributors + ( highest_set + filter_pixel_margin + 1); - while ( clear_contributors < scatter_contributors ) { - clear_contributors->n0 = 0; - clear_contributors->n1 = -1; - ++clear_contributors; + // if we are skipping over several contributors, we need to clear the skipped ones + stbir__contributors * clear_contributors = samp->contributors + ( highest_set + filter_pixel_margin + 1); + while ( clear_contributors < scatter_contributors ) + { + clear_contributors->n0 = 0; + clear_contributors->n1 = -1; + ++clear_contributors; + } } + scatter_contributors->n0 = n; + scatter_contributors->n1 = n; + scatter_coeffs[0] = gc; + highest_set = k; } - scatter_contributors->n0 = n; - scatter_contributors->n1 = n; - scatter_coeffs[0] = gc; - highest_set = k; - } - else - { - stbir__insert_coeff( scatter_contributors, scatter_coeffs, n, gc ); + else + { + stbir__insert_coeff( scatter_contributors, scatter_coeffs, n, gc ); + } + STBIR_ASSERT( ( scatter_contributors->n1 - scatter_contributors->n0 + 1 ) <= scatter_coefficient_width ); } ++scatter_contributors; scatter_coeffs += scatter_coefficient_width; @@ -3908,11 +4005,11 @@ static void stbir__calculate_filters( stbir__sampler * samp, stbir__sampler * ot #define stbir__decode_suffix BGRA #define stbir__decode_swizzle -#define stbir__decode_order0 2 +#define stbir__decode_order0 2 #define stbir__decode_order1 1 #define stbir__decode_order2 0 #define stbir__decode_order3 3 -#define stbir__encode_order0 2 +#define stbir__encode_order0 2 #define stbir__encode_order1 1 #define stbir__encode_order2 0 #define stbir__encode_order3 3 @@ -3922,11 +4019,11 @@ static void stbir__calculate_filters( stbir__sampler * samp, stbir__sampler * ot #define stbir__decode_suffix ARGB #define stbir__decode_swizzle -#define stbir__decode_order0 1 +#define stbir__decode_order0 1 #define stbir__decode_order1 2 #define stbir__decode_order2 3 #define stbir__decode_order3 0 -#define stbir__encode_order0 3 +#define stbir__encode_order0 3 #define stbir__encode_order1 0 #define stbir__encode_order2 1 #define stbir__encode_order3 2 @@ -3936,11 +4033,11 @@ static void stbir__calculate_filters( stbir__sampler * samp, stbir__sampler * ot #define stbir__decode_suffix ABGR #define stbir__decode_swizzle -#define stbir__decode_order0 3 +#define stbir__decode_order0 3 #define stbir__decode_order1 2 #define stbir__decode_order2 1 #define stbir__decode_order3 0 -#define stbir__encode_order0 3 +#define stbir__encode_order0 3 #define stbir__encode_order1 2 #define stbir__encode_order2 1 #define stbir__encode_order3 0 @@ -3950,12 +4047,12 @@ static void stbir__calculate_filters( stbir__sampler * samp, stbir__sampler * ot #define stbir__decode_suffix AR #define stbir__decode_swizzle -#define stbir__decode_order0 1 -#define stbir__decode_order1 0 +#define stbir__decode_order0 1 +#define stbir__decode_order1 0 #define stbir__decode_order2 3 #define stbir__decode_order3 2 -#define stbir__encode_order0 1 -#define stbir__encode_order1 0 +#define stbir__encode_order0 1 +#define stbir__encode_order1 0 #define stbir__encode_order2 3 #define stbir__encode_order3 2 #define stbir__coder_min_num 2 @@ -3973,9 +4070,10 @@ static void stbir__fancy_alpha_weight_4ch( float * out_buffer, int width_times_c // fancy alpha is stored internally as R G B A Rpm Gpm Bpm #ifdef STBIR_SIMD - + #ifdef STBIR_SIMD8 decode += 16; + STBIR_NO_UNROLL_LOOP_START while ( decode <= end_decode ) { stbir__simdf8 d0,d1,a0,a1,p0,p1; @@ -3998,8 +4096,9 @@ static void stbir__fancy_alpha_weight_4ch( float * out_buffer, int width_times_c out += 28; } decode -= 16; - #else + #else decode += 8; + STBIR_NO_UNROLL_LOOP_START while ( decode <= end_decode ) { stbir__simdf d0,a0,d1,a1,p0,p1; @@ -4022,12 +4121,14 @@ static void stbir__fancy_alpha_weight_4ch( float * out_buffer, int width_times_c // might be one last odd pixel #ifdef STBIR_SIMD8 + STBIR_NO_UNROLL_LOOP_START while ( decode < end_decode ) #else if ( decode < end_decode ) #endif { stbir__simdf d,a,p; + STBIR_NO_UNROLL(decode); stbir__simdf_load( d, decode ); stbir__simdf_0123to3333( a, d ); stbir__simdf_mult( p, a, d ); @@ -4069,6 +4170,7 @@ static void stbir__fancy_alpha_weight_2ch( float * out_buffer, int width_times_c decode += 8; if ( decode <= end_decode ) { + STBIR_NO_UNROLL_LOOP_START do { #ifdef STBIR_SIMD8 stbir__simdf8 d0,a0,p0; @@ -4077,11 +4179,11 @@ static void stbir__fancy_alpha_weight_2ch( float * out_buffer, int width_times_c stbir__simdf8_0123to11331133( p0, d0 ); stbir__simdf8_0123to00220022( a0, d0 ); stbir__simdf8_mult( p0, p0, a0 ); - + stbir__simdf_store2( out, stbir__if_simdf8_cast_to_simdf4( d0 ) ); stbir__simdf_store( out+2, stbir__if_simdf8_cast_to_simdf4( p0 ) ); stbir__simdf_store2h( out+3, stbir__if_simdf8_cast_to_simdf4( d0 ) ); - + stbir__simdf_store2( out+6, stbir__simdf8_gettop4( d0 ) ); stbir__simdf_store( out+8, stbir__simdf8_gettop4( p0 ) ); stbir__simdf_store2h( out+9, stbir__simdf8_gettop4( d0 ) ); @@ -4112,6 +4214,7 @@ static void stbir__fancy_alpha_weight_2ch( float * out_buffer, int width_times_c decode -= 8; #endif + STBIR_SIMD_NO_UNROLL_LOOP_START while( decode < end_decode ) { float x = decode[0], y = decode[1]; @@ -4132,6 +4235,7 @@ static void stbir__fancy_alpha_unweight_4ch( float * encode_buffer, int width_ti // fancy RGBA is stored internally as R G B A Rpm Gpm Bpm + STBIR_SIMD_NO_UNROLL_LOOP_START do { float alpha = input[3]; #ifdef STBIR_SIMD @@ -4199,6 +4303,7 @@ static void stbir__simple_alpha_weight_4ch( float * decode_buffer, int width_tim #ifdef STBIR_SIMD { decode += 2 * stbir__simdfX_float_count; + STBIR_NO_UNROLL_LOOP_START while ( decode <= end_decode ) { stbir__simdfX d0,a0,d1,a1; @@ -4217,6 +4322,7 @@ static void stbir__simple_alpha_weight_4ch( float * decode_buffer, int width_tim // few last pixels remnants #ifdef STBIR_SIMD8 + STBIR_NO_UNROLL_LOOP_START while ( decode < end_decode ) #else if ( decode < end_decode ) @@ -4252,6 +4358,7 @@ static void stbir__simple_alpha_weight_2ch( float * decode_buffer, int width_tim #ifdef STBIR_SIMD decode += 2 * stbir__simdfX_float_count; + STBIR_NO_UNROLL_LOOP_START while ( decode <= end_decode ) { stbir__simdfX d0,a0,d1,a1; @@ -4269,6 +4376,7 @@ static void stbir__simple_alpha_weight_2ch( float * decode_buffer, int width_tim decode -= 2 * stbir__simdfX_float_count; #endif + STBIR_SIMD_NO_UNROLL_LOOP_START while( decode < end_decode ) { float alpha = decode[1]; @@ -4283,6 +4391,7 @@ static void stbir__simple_alpha_unweight_4ch( float * encode_buffer, int width_t float STBIR_SIMD_STREAMOUT_PTR(*) encode = encode_buffer; float const * end_output = encode_buffer + width_times_channels; + STBIR_SIMD_NO_UNROLL_LOOP_START do { float alpha = encode[3]; @@ -4330,9 +4439,77 @@ static void stbir__simple_flip_3ch( float * decode_buffer, int width_times_chann float STBIR_STREAMOUT_PTR(*) decode = decode_buffer; float const * end_decode = decode_buffer + width_times_channels; - decode += 12; +#ifdef STBIR_SIMD + #ifdef stbir__simdf_swiz2 // do we have two argument swizzles? + end_decode -= 12; + STBIR_NO_UNROLL_LOOP_START + while( decode <= end_decode ) + { + // on arm64 8 instructions, no overlapping stores + stbir__simdf a,b,c,na,nb; + STBIR_SIMD_NO_UNROLL(decode); + stbir__simdf_load( a, decode ); + stbir__simdf_load( b, decode+4 ); + stbir__simdf_load( c, decode+8 ); + + na = stbir__simdf_swiz2( a, b, 2, 1, 0, 5 ); + b = stbir__simdf_swiz2( a, b, 4, 3, 6, 7 ); + nb = stbir__simdf_swiz2( b, c, 0, 1, 4, 3 ); + c = stbir__simdf_swiz2( b, c, 2, 7, 6, 5 ); + + stbir__simdf_store( decode, na ); + stbir__simdf_store( decode+4, nb ); + stbir__simdf_store( decode+8, c ); + decode += 12; + } + end_decode += 12; + #else + end_decode -= 24; + STBIR_NO_UNROLL_LOOP_START + while( decode <= end_decode ) + { + // 26 instructions on x64 + stbir__simdf a,b,c,d,e,f,g; + float i21, i23; + STBIR_SIMD_NO_UNROLL(decode); + stbir__simdf_load( a, decode ); + stbir__simdf_load( b, decode+3 ); + stbir__simdf_load( c, decode+6 ); + stbir__simdf_load( d, decode+9 ); + stbir__simdf_load( e, decode+12 ); + stbir__simdf_load( f, decode+15 ); + stbir__simdf_load( g, decode+18 ); + + a = stbir__simdf_swiz( a, 2, 1, 0, 3 ); + b = stbir__simdf_swiz( b, 2, 1, 0, 3 ); + c = stbir__simdf_swiz( c, 2, 1, 0, 3 ); + d = stbir__simdf_swiz( d, 2, 1, 0, 3 ); + e = stbir__simdf_swiz( e, 2, 1, 0, 3 ); + f = stbir__simdf_swiz( f, 2, 1, 0, 3 ); + g = stbir__simdf_swiz( g, 2, 1, 0, 3 ); + + // stores overlap, need to be in order, + stbir__simdf_store( decode, a ); + i21 = decode[21]; + stbir__simdf_store( decode+3, b ); + i23 = decode[23]; + stbir__simdf_store( decode+6, c ); + stbir__simdf_store( decode+9, d ); + stbir__simdf_store( decode+12, e ); + stbir__simdf_store( decode+15, f ); + stbir__simdf_store( decode+18, g ); + decode[21] = i23; + decode[23] = i21; + decode += 24; + } + end_decode += 24; + #endif +#else + end_decode -= 12; + STBIR_NO_UNROLL_LOOP_START while( decode <= end_decode ) { + // 16 instructions float t0,t1,t2,t3; STBIR_NO_UNROLL(decode); t0 = decode[0]; t1 = decode[3]; t2 = decode[6]; t3 = decode[9]; @@ -4340,8 +4517,10 @@ static void stbir__simple_flip_3ch( float * decode_buffer, int width_times_chann decode[2] = t0; decode[5] = t1; decode[8] = t2; decode[11] = t3; decode += 12; } - decode -= 12; + end_decode += 12; +#endif + STBIR_NO_UNROLL_LOOP_START while( decode < end_decode ) { float t = decode[0]; @@ -4362,14 +4541,14 @@ static void stbir__decode_scanline(stbir__info const * stbir_info, int n, float stbir_edge edge_horizontal = stbir_info->horizontal.edge; stbir_edge edge_vertical = stbir_info->vertical.edge; int row = stbir__edge_wrap(edge_vertical, n, stbir_info->vertical.scale_info.input_full_size); - const void* input_plane_data = ( (char *) stbir_info->input_data ) + (ptrdiff_t)row * (ptrdiff_t) stbir_info->input_stride_bytes; + const void* input_plane_data = ( (char *) stbir_info->input_data ) + (size_t)row * (size_t) stbir_info->input_stride_bytes; stbir__span const * spans = stbir_info->scanline_extents.spans; float* full_decode_buffer = output_buffer - stbir_info->scanline_extents.conservative.n0 * effective_channels; // if we are on edge_zero, and we get in here with an out of bounds n, then the calculate filters has failed STBIR_ASSERT( !(edge_vertical == STBIR_EDGE_ZERO && (n < 0 || n >= stbir_info->vertical.scale_info.input_full_size)) ); - do + do { float * decode_buffer; void const * input_data; @@ -4377,7 +4556,7 @@ static void stbir__decode_scanline(stbir__info const * stbir_info, int n, float int width_times_channels; int width; - if ( spans->n1 < spans->n0 ) + if ( spans->n1 < spans->n0 ) break; width = spans->n1 + 1 - spans->n0; @@ -4394,7 +4573,7 @@ static void stbir__decode_scanline(stbir__info const * stbir_info, int n, float // call the callback with a temp buffer (that they can choose to use or not). the temp is just right aligned memory in the decode_buffer itself input_data = stbir_info->in_pixels_cb( ( (char*) end_decode ) - ( width * input_sample_in_bytes ), input_plane_data, width, spans->pixel_offset_for_input, row, stbir_info->user_data ); } - + STBIR_PROFILE_START( decode ); // convert the pixels info the float decode_buffer, (we index from end_decode, so that when channelsdecode_pixels( (float*)end_decode - width_times_channels, width_times_channels, input_data ); @@ -4418,7 +4597,7 @@ static void stbir__decode_scanline(stbir__info const * stbir_info, int n, float // this code only runs if we're in edge_wrap, and we're doing the entire scanline int e, start_x[2]; int input_full_size = stbir_info->horizontal.scale_info.input_full_size; - + start_x[0] = -stbir_info->scanline_extents.edge_sizes[0]; // left edge start x start_x[1] = input_full_size; // right edge @@ -4447,7 +4626,7 @@ static void stbir__decode_scanline(stbir__info const * stbir_info, int n, float stbir__simdf tot,c; \ STBIR_SIMD_NO_UNROLL(decode); \ stbir__simdf_load1( c, hc ); \ - stbir__simdf_mult1_mem( tot, c, decode ); + stbir__simdf_mult1_mem( tot, c, decode ); #define stbir__2_coeff_only() \ stbir__simdf tot,c,d; \ @@ -4456,7 +4635,7 @@ static void stbir__decode_scanline(stbir__info const * stbir_info, int n, float stbir__simdf_load2( d, decode ); \ stbir__simdf_mult( tot, c, d ); \ stbir__simdf_0123to1230( c, tot ); \ - stbir__simdf_add1( tot, tot, c ); + stbir__simdf_add1( tot, tot, c ); #define stbir__3_coeff_only() \ stbir__simdf tot,c,t; \ @@ -4466,7 +4645,7 @@ static void stbir__decode_scanline(stbir__info const * stbir_info, int n, float stbir__simdf_0123to1230( c, tot ); \ stbir__simdf_0123to2301( t, tot ); \ stbir__simdf_add1( tot, tot, c ); \ - stbir__simdf_add1( tot, tot, t ); + stbir__simdf_add1( tot, tot, t ); #define stbir__store_output_tiny() \ stbir__simdf_store1( output, tot ); \ @@ -4483,7 +4662,7 @@ static void stbir__decode_scanline(stbir__info const * stbir_info, int n, float #define stbir__4_coeff_continue_from_4( ofs ) \ STBIR_SIMD_NO_UNROLL(decode); \ stbir__simdf_load( c, hc + (ofs) ); \ - stbir__simdf_madd_mem( tot, tot, c, decode+(ofs) ); + stbir__simdf_madd_mem( tot, tot, c, decode+(ofs) ); #define stbir__1_coeff_remnant( ofs ) \ { stbir__simdf d; \ @@ -4495,7 +4674,7 @@ static void stbir__decode_scanline(stbir__info const * stbir_info, int n, float { stbir__simdf d; \ stbir__simdf_load2z( c, hc+(ofs) ); \ stbir__simdf_load2( d, decode+(ofs) ); \ - stbir__simdf_madd( tot, tot, d, c ); } + stbir__simdf_madd( tot, tot, d, c ); } #define stbir__3_coeff_setup() \ stbir__simdf mask; \ @@ -4520,18 +4699,18 @@ static void stbir__decode_scanline(stbir__info const * stbir_info, int n, float #define stbir__1_coeff_only() \ float tot; \ - tot = decode[0]*hc[0]; + tot = decode[0]*hc[0]; #define stbir__2_coeff_only() \ float tot; \ tot = decode[0] * hc[0]; \ - tot += decode[1] * hc[1]; + tot += decode[1] * hc[1]; #define stbir__3_coeff_only() \ float tot; \ tot = decode[0] * hc[0]; \ tot += decode[1] * hc[1]; \ - tot += decode[2] * hc[2]; + tot += decode[2] * hc[2]; #define stbir__store_output_tiny() \ output[0] = tot; \ @@ -4544,16 +4723,16 @@ static void stbir__decode_scanline(stbir__info const * stbir_info, int n, float tot0 = decode[0] * hc[0]; \ tot1 = decode[1] * hc[1]; \ tot2 = decode[2] * hc[2]; \ - tot3 = decode[3] * hc[3]; + tot3 = decode[3] * hc[3]; #define stbir__4_coeff_continue_from_4( ofs ) \ tot0 += decode[0+(ofs)] * hc[0+(ofs)]; \ tot1 += decode[1+(ofs)] * hc[1+(ofs)]; \ tot2 += decode[2+(ofs)] * hc[2+(ofs)]; \ - tot3 += decode[3+(ofs)] * hc[3+(ofs)]; + tot3 += decode[3+(ofs)] * hc[3+(ofs)]; #define stbir__1_coeff_remnant( ofs ) \ - tot0 += decode[0+(ofs)] * hc[0+(ofs)]; + tot0 += decode[0+(ofs)] * hc[0+(ofs)]; #define stbir__2_coeff_remnant( ofs ) \ tot0 += decode[0+(ofs)] * hc[0+(ofs)]; \ @@ -4562,7 +4741,7 @@ static void stbir__decode_scanline(stbir__info const * stbir_info, int n, float #define stbir__3_coeff_remnant( ofs ) \ tot0 += decode[0+(ofs)] * hc[0+(ofs)]; \ tot1 += decode[1+(ofs)] * hc[1+(ofs)]; \ - tot2 += decode[2+(ofs)] * hc[2+(ofs)]; + tot2 += decode[2+(ofs)] * hc[2+(ofs)]; #define stbir__store_output() \ output[0] = (tot0+tot2)+(tot1+tot3); \ @@ -4570,7 +4749,7 @@ static void stbir__decode_scanline(stbir__info const * stbir_info, int n, float ++horizontal_contributors; \ output += 1; -#endif +#endif #define STBIR__horizontal_channels 1 #define STB_IMAGE_RESIZE_DO_HORIZONTALS @@ -4588,14 +4767,14 @@ static void stbir__decode_scanline(stbir__info const * stbir_info, int n, float stbir__simdf_load1z( c, hc ); \ stbir__simdf_0123to0011( c, c ); \ stbir__simdf_load2( d, decode ); \ - stbir__simdf_mult( tot, d, c ); + stbir__simdf_mult( tot, d, c ); #define stbir__2_coeff_only() \ stbir__simdf tot,c; \ STBIR_SIMD_NO_UNROLL(decode); \ stbir__simdf_load2( c, hc ); \ stbir__simdf_0123to0011( c, c ); \ - stbir__simdf_mult_mem( tot, c, decode ); + stbir__simdf_mult_mem( tot, c, decode ); #define stbir__3_coeff_only() \ stbir__simdf tot,c,cs,d; \ @@ -4605,7 +4784,7 @@ static void stbir__decode_scanline(stbir__info const * stbir_info, int n, float stbir__simdf_mult_mem( tot, c, decode ); \ stbir__simdf_0123to2222( c, cs ); \ stbir__simdf_load2z( d, decode+4 ); \ - stbir__simdf_madd( tot, tot, d, c ); + stbir__simdf_madd( tot, tot, d, c ); #define stbir__store_output_tiny() \ stbir__simdf_0123to2301( c, tot ); \ @@ -4628,7 +4807,7 @@ static void stbir__decode_scanline(stbir__info const * stbir_info, int n, float STBIR_SIMD_NO_UNROLL(decode); \ stbir__simdf8_load4b( cs, hc + (ofs) ); \ stbir__simdf8_0123to00112233( c, cs ); \ - stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*2 ); + stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*2 ); #define stbir__1_coeff_remnant( ofs ) \ { stbir__simdf t; \ @@ -4649,13 +4828,13 @@ static void stbir__decode_scanline(stbir__info const * stbir_info, int n, float stbir__simdf8_load4b( cs, hc + (ofs) ); \ stbir__simdf8_0123to00112233( c, cs ); \ stbir__simdf8_load6z( d, decode+(ofs)*2 ); \ - stbir__simdf8_madd( tot0, tot0, c, d ); } + stbir__simdf8_madd( tot0, tot0, c, d ); } #define stbir__store_output() \ - { stbir__simdf t,c; \ + { stbir__simdf t,d; \ stbir__simdf8_add4halves( t, stbir__if_simdf8_cast_to_simdf4(tot0), tot0 ); \ - stbir__simdf_0123to2301( c, t ); \ - stbir__simdf_add( t, t, c ); \ + stbir__simdf_0123to2301( d, t ); \ + stbir__simdf_add( t, t, d ); \ stbir__simdf_store2( output, t ); \ horizontal_coefficients += coefficient_width; \ ++horizontal_contributors; \ @@ -4670,7 +4849,7 @@ static void stbir__decode_scanline(stbir__info const * stbir_info, int n, float stbir__simdf_0123to0011( c, cs ); \ stbir__simdf_mult_mem( tot0, c, decode ); \ stbir__simdf_0123to2233( c, cs ); \ - stbir__simdf_mult_mem( tot1, c, decode+4 ); + stbir__simdf_mult_mem( tot1, c, decode+4 ); #define stbir__4_coeff_continue_from_4( ofs ) \ STBIR_SIMD_NO_UNROLL(decode); \ @@ -4678,7 +4857,7 @@ static void stbir__decode_scanline(stbir__info const * stbir_info, int n, float stbir__simdf_0123to0011( c, cs ); \ stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*2 ); \ stbir__simdf_0123to2233( c, cs ); \ - stbir__simdf_madd_mem( tot1, tot1, c, decode+(ofs)*2+4 ); + stbir__simdf_madd_mem( tot1, tot1, c, decode+(ofs)*2+4 ); #define stbir__1_coeff_remnant( ofs ) \ { stbir__simdf d; \ @@ -4690,7 +4869,7 @@ static void stbir__decode_scanline(stbir__info const * stbir_info, int n, float #define stbir__2_coeff_remnant( ofs ) \ stbir__simdf_load2( cs, hc + (ofs) ); \ stbir__simdf_0123to0011( c, cs ); \ - stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*2 ); + stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*2 ); #define stbir__3_coeff_remnant( ofs ) \ { stbir__simdf d; \ @@ -4699,7 +4878,7 @@ static void stbir__decode_scanline(stbir__info const * stbir_info, int n, float stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*2 ); \ stbir__simdf_0123to2222( c, cs ); \ stbir__simdf_load2z( d, decode + (ofs) * 2 + 4 ); \ - stbir__simdf_madd( tot1, tot1, d, c ); } + stbir__simdf_madd( tot1, tot1, d, c ); } #define stbir__store_output() \ stbir__simdf_add( tot0, tot0, tot1 ); \ @@ -4718,7 +4897,7 @@ static void stbir__decode_scanline(stbir__info const * stbir_info, int n, float float tota,totb,c; \ c = hc[0]; \ tota = decode[0]*c; \ - totb = decode[1]*c; + totb = decode[1]*c; #define stbir__2_coeff_only() \ float tota,totb,c; \ @@ -4727,7 +4906,7 @@ static void stbir__decode_scanline(stbir__info const * stbir_info, int n, float totb = decode[1]*c; \ c = hc[1]; \ tota += decode[2]*c; \ - totb += decode[3]*c; + totb += decode[3]*c; // this weird order of add matches the simd #define stbir__3_coeff_only() \ @@ -4740,7 +4919,7 @@ static void stbir__decode_scanline(stbir__info const * stbir_info, int n, float totb += decode[5]*c; \ c = hc[1]; \ tota += decode[2]*c; \ - totb += decode[3]*c; + totb += decode[3]*c; #define stbir__store_output_tiny() \ output[0] = tota; \ @@ -4762,7 +4941,7 @@ static void stbir__decode_scanline(stbir__info const * stbir_info, int n, float totb2 = decode[5]*c; \ c = hc[3]; \ tota3 = decode[6]*c; \ - totb3 = decode[7]*c; + totb3 = decode[7]*c; #define stbir__4_coeff_continue_from_4( ofs ) \ c = hc[0+(ofs)]; \ @@ -4776,12 +4955,12 @@ static void stbir__decode_scanline(stbir__info const * stbir_info, int n, float totb2 += decode[5+(ofs)*2]*c; \ c = hc[3+(ofs)]; \ tota3 += decode[6+(ofs)*2]*c; \ - totb3 += decode[7+(ofs)*2]*c; + totb3 += decode[7+(ofs)*2]*c; #define stbir__1_coeff_remnant( ofs ) \ c = hc[0+(ofs)]; \ tota0 += decode[0+(ofs)*2] * c; \ - totb0 += decode[1+(ofs)*2] * c; + totb0 += decode[1+(ofs)*2] * c; #define stbir__2_coeff_remnant( ofs ) \ c = hc[0+(ofs)]; \ @@ -4789,7 +4968,7 @@ static void stbir__decode_scanline(stbir__info const * stbir_info, int n, float totb0 += decode[1+(ofs)*2] * c; \ c = hc[1+(ofs)]; \ tota1 += decode[2+(ofs)*2] * c; \ - totb1 += decode[3+(ofs)*2] * c; + totb1 += decode[3+(ofs)*2] * c; #define stbir__3_coeff_remnant( ofs ) \ c = hc[0+(ofs)]; \ @@ -4800,7 +4979,7 @@ static void stbir__decode_scanline(stbir__info const * stbir_info, int n, float totb1 += decode[3+(ofs)*2] * c; \ c = hc[2+(ofs)]; \ tota2 += decode[4+(ofs)*2] * c; \ - totb2 += decode[5+(ofs)*2] * c; + totb2 += decode[5+(ofs)*2] * c; #define stbir__store_output() \ output[0] = (tota0+tota2)+(tota1+tota3); \ @@ -4809,7 +4988,7 @@ static void stbir__decode_scanline(stbir__info const * stbir_info, int n, float ++horizontal_contributors; \ output += 2; -#endif +#endif #define STBIR__horizontal_channels 2 #define STB_IMAGE_RESIZE_DO_HORIZONTALS @@ -4827,7 +5006,7 @@ static void stbir__decode_scanline(stbir__info const * stbir_info, int n, float stbir__simdf_load1z( c, hc ); \ stbir__simdf_0123to0001( c, c ); \ stbir__simdf_load( d, decode ); \ - stbir__simdf_mult( tot, d, c ); + stbir__simdf_mult( tot, d, c ); #define stbir__2_coeff_only() \ stbir__simdf tot,c,cs,d; \ @@ -4838,7 +5017,7 @@ static void stbir__decode_scanline(stbir__info const * stbir_info, int n, float stbir__simdf_mult( tot, d, c ); \ stbir__simdf_0123to1111( c, cs ); \ stbir__simdf_load( d, decode+3 ); \ - stbir__simdf_madd( tot, tot, d, c ); + stbir__simdf_madd( tot, tot, d, c ); #define stbir__3_coeff_only() \ stbir__simdf tot,c,d,cs; \ @@ -4852,7 +5031,7 @@ static void stbir__decode_scanline(stbir__info const * stbir_info, int n, float stbir__simdf_madd( tot, tot, d, c ); \ stbir__simdf_0123to2222( c, cs ); \ stbir__simdf_load( d, decode+6 ); \ - stbir__simdf_madd( tot, tot, d, c ); + stbir__simdf_madd( tot, tot, d, c ); #define stbir__store_output_tiny() \ stbir__simdf_store2( output, tot ); \ @@ -4872,7 +5051,7 @@ static void stbir__decode_scanline(stbir__info const * stbir_info, int n, float stbir__simdf8_0123to00001111( c, cs ); \ stbir__simdf8_mult_mem( tot0, c, decode - 1 ); \ stbir__simdf8_0123to22223333( c, cs ); \ - stbir__simdf8_mult_mem( tot1, c, decode+6 - 1 ); + stbir__simdf8_mult_mem( tot1, c, decode+6 - 1 ); #define stbir__4_coeff_continue_from_4( ofs ) \ STBIR_SIMD_NO_UNROLL(decode); \ @@ -4880,26 +5059,26 @@ static void stbir__decode_scanline(stbir__info const * stbir_info, int n, float stbir__simdf8_0123to00001111( c, cs ); \ stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*3 - 1 ); \ stbir__simdf8_0123to22223333( c, cs ); \ - stbir__simdf8_madd_mem( tot1, tot1, c, decode+(ofs)*3 + 6 - 1 ); + stbir__simdf8_madd_mem( tot1, tot1, c, decode+(ofs)*3 + 6 - 1 ); #define stbir__1_coeff_remnant( ofs ) \ STBIR_SIMD_NO_UNROLL(decode); \ stbir__simdf_load1rep4( t, hc + (ofs) ); \ - stbir__simdf8_madd_mem4( tot0, tot0, t, decode+(ofs)*3 - 1 ); + stbir__simdf8_madd_mem4( tot0, tot0, t, decode+(ofs)*3 - 1 ); #define stbir__2_coeff_remnant( ofs ) \ STBIR_SIMD_NO_UNROLL(decode); \ stbir__simdf8_load4b( cs, hc + (ofs) - 2 ); \ stbir__simdf8_0123to22223333( c, cs ); \ - stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*3 - 1 ); - + stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*3 - 1 ); + #define stbir__3_coeff_remnant( ofs ) \ STBIR_SIMD_NO_UNROLL(decode); \ stbir__simdf8_load4b( cs, hc + (ofs) ); \ stbir__simdf8_0123to00001111( c, cs ); \ stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*3 - 1 ); \ stbir__simdf8_0123to2222( t, cs ); \ - stbir__simdf8_madd_mem4( tot1, tot1, t, decode+(ofs)*3 + 6 - 1 ); + stbir__simdf8_madd_mem4( tot1, tot1, t, decode+(ofs)*3 + 6 - 1 ); #define stbir__store_output() \ stbir__simdf8_add( tot0, tot0, tot1 ); \ @@ -4930,7 +5109,7 @@ static void stbir__decode_scanline(stbir__info const * stbir_info, int n, float stbir__simdf_0123to1122( c, cs ); \ stbir__simdf_mult_mem( tot1, c, decode+4 ); \ stbir__simdf_0123to2333( c, cs ); \ - stbir__simdf_mult_mem( tot2, c, decode+8 ); + stbir__simdf_mult_mem( tot2, c, decode+8 ); #define stbir__4_coeff_continue_from_4( ofs ) \ STBIR_SIMD_NO_UNROLL(decode); \ @@ -4940,13 +5119,13 @@ static void stbir__decode_scanline(stbir__info const * stbir_info, int n, float stbir__simdf_0123to1122( c, cs ); \ stbir__simdf_madd_mem( tot1, tot1, c, decode+(ofs)*3+4 ); \ stbir__simdf_0123to2333( c, cs ); \ - stbir__simdf_madd_mem( tot2, tot2, c, decode+(ofs)*3+8 ); + stbir__simdf_madd_mem( tot2, tot2, c, decode+(ofs)*3+8 ); #define stbir__1_coeff_remnant( ofs ) \ STBIR_SIMD_NO_UNROLL(decode); \ stbir__simdf_load1z( c, hc + (ofs) ); \ stbir__simdf_0123to0001( c, c ); \ - stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*3 ); + stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*3 ); #define stbir__2_coeff_remnant( ofs ) \ { stbir__simdf d; \ @@ -4956,7 +5135,7 @@ static void stbir__decode_scanline(stbir__info const * stbir_info, int n, float stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*3 ); \ stbir__simdf_0123to1122( c, cs ); \ stbir__simdf_load2z( d, decode+(ofs)*3+4 ); \ - stbir__simdf_madd( tot1, tot1, c, d ); } + stbir__simdf_madd( tot1, tot1, c, d ); } #define stbir__3_coeff_remnant( ofs ) \ { stbir__simdf d; \ @@ -4968,7 +5147,7 @@ static void stbir__decode_scanline(stbir__info const * stbir_info, int n, float stbir__simdf_madd_mem( tot1, tot1, c, decode+(ofs)*3+4 ); \ stbir__simdf_0123to2222( c, cs ); \ stbir__simdf_load1z( d, decode+(ofs)*3+8 ); \ - stbir__simdf_madd( tot2, tot2, c, d ); } + stbir__simdf_madd( tot2, tot2, c, d ); } #define stbir__store_output() \ stbir__simdf_0123ABCDto3ABx( c, tot0, tot1 ); \ @@ -4999,7 +5178,7 @@ static void stbir__decode_scanline(stbir__info const * stbir_info, int n, float c = hc[0]; \ tot0 = decode[0]*c; \ tot1 = decode[1]*c; \ - tot2 = decode[2]*c; + tot2 = decode[2]*c; #define stbir__2_coeff_only() \ float tot0, tot1, tot2, c; \ @@ -5010,7 +5189,7 @@ static void stbir__decode_scanline(stbir__info const * stbir_info, int n, float c = hc[1]; \ tot0 += decode[3]*c; \ tot1 += decode[4]*c; \ - tot2 += decode[5]*c; + tot2 += decode[5]*c; #define stbir__3_coeff_only() \ float tot0, tot1, tot2, c; \ @@ -5025,7 +5204,7 @@ static void stbir__decode_scanline(stbir__info const * stbir_info, int n, float c = hc[2]; \ tot0 += decode[6]*c; \ tot1 += decode[7]*c; \ - tot2 += decode[8]*c; + tot2 += decode[8]*c; #define stbir__store_output_tiny() \ output[0] = tot0; \ @@ -5052,7 +5231,7 @@ static void stbir__decode_scanline(stbir__info const * stbir_info, int n, float c = hc[3]; \ totd0 = decode[9]*c; \ totd1 = decode[10]*c; \ - totd2 = decode[11]*c; + totd2 = decode[11]*c; #define stbir__4_coeff_continue_from_4( ofs ) \ c = hc[0+(ofs)]; \ @@ -5070,7 +5249,7 @@ static void stbir__decode_scanline(stbir__info const * stbir_info, int n, float c = hc[3+(ofs)]; \ totd0 += decode[9+(ofs)*3]*c; \ totd1 += decode[10+(ofs)*3]*c; \ - totd2 += decode[11+(ofs)*3]*c; + totd2 += decode[11+(ofs)*3]*c; #define stbir__1_coeff_remnant( ofs ) \ c = hc[0+(ofs)]; \ @@ -5100,7 +5279,7 @@ static void stbir__decode_scanline(stbir__info const * stbir_info, int n, float c = hc[2+(ofs)]; \ totc0 += decode[6+(ofs)*3]*c; \ totc1 += decode[7+(ofs)*3]*c; \ - totc2 += decode[8+(ofs)*3]*c; + totc2 += decode[8+(ofs)*3]*c; #define stbir__store_output() \ output[0] = (tota0+totc0)+(totb0+totd0); \ @@ -5110,7 +5289,7 @@ static void stbir__decode_scanline(stbir__info const * stbir_info, int n, float ++horizontal_contributors; \ output += 3; -#endif +#endif #define STBIR__horizontal_channels 3 #define STB_IMAGE_RESIZE_DO_HORIZONTALS @@ -5126,7 +5305,7 @@ static void stbir__decode_scanline(stbir__info const * stbir_info, int n, float STBIR_SIMD_NO_UNROLL(decode); \ stbir__simdf_load1( c, hc ); \ stbir__simdf_0123to0000( c, c ); \ - stbir__simdf_mult_mem( tot, c, decode ); + stbir__simdf_mult_mem( tot, c, decode ); #define stbir__2_coeff_only() \ stbir__simdf tot,c,cs; \ @@ -5135,7 +5314,7 @@ static void stbir__decode_scanline(stbir__info const * stbir_info, int n, float stbir__simdf_0123to0000( c, cs ); \ stbir__simdf_mult_mem( tot, c, decode ); \ stbir__simdf_0123to1111( c, cs ); \ - stbir__simdf_madd_mem( tot, tot, c, decode+4 ); + stbir__simdf_madd_mem( tot, tot, c, decode+4 ); #define stbir__3_coeff_only() \ stbir__simdf tot,c,cs; \ @@ -5146,7 +5325,7 @@ static void stbir__decode_scanline(stbir__info const * stbir_info, int n, float stbir__simdf_0123to1111( c, cs ); \ stbir__simdf_madd_mem( tot, tot, c, decode+4 ); \ stbir__simdf_0123to2222( c, cs ); \ - stbir__simdf_madd_mem( tot, tot, c, decode+8 ); + stbir__simdf_madd_mem( tot, tot, c, decode+8 ); #define stbir__store_output_tiny() \ stbir__simdf_store( output, tot ); \ @@ -5163,7 +5342,7 @@ static void stbir__decode_scanline(stbir__info const * stbir_info, int n, float stbir__simdf8_0123to00001111( c, cs ); \ stbir__simdf8_mult_mem( tot0, c, decode ); \ stbir__simdf8_0123to22223333( c, cs ); \ - stbir__simdf8_madd_mem( tot0, tot0, c, decode+8 ); + stbir__simdf8_madd_mem( tot0, tot0, c, decode+8 ); #define stbir__4_coeff_continue_from_4( ofs ) \ STBIR_SIMD_NO_UNROLL(decode); \ @@ -5171,26 +5350,26 @@ static void stbir__decode_scanline(stbir__info const * stbir_info, int n, float stbir__simdf8_0123to00001111( c, cs ); \ stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*4 ); \ stbir__simdf8_0123to22223333( c, cs ); \ - stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*4+8 ); + stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*4+8 ); #define stbir__1_coeff_remnant( ofs ) \ STBIR_SIMD_NO_UNROLL(decode); \ stbir__simdf_load1rep4( t, hc + (ofs) ); \ - stbir__simdf8_madd_mem4( tot0, tot0, t, decode+(ofs)*4 ); + stbir__simdf8_madd_mem4( tot0, tot0, t, decode+(ofs)*4 ); #define stbir__2_coeff_remnant( ofs ) \ STBIR_SIMD_NO_UNROLL(decode); \ stbir__simdf8_load4b( cs, hc + (ofs) - 2 ); \ stbir__simdf8_0123to22223333( c, cs ); \ - stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*4 ); - + stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*4 ); + #define stbir__3_coeff_remnant( ofs ) \ STBIR_SIMD_NO_UNROLL(decode); \ stbir__simdf8_load4b( cs, hc + (ofs) ); \ stbir__simdf8_0123to00001111( c, cs ); \ stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*4 ); \ stbir__simdf8_0123to2222( t, cs ); \ - stbir__simdf8_madd_mem4( tot0, tot0, t, decode+(ofs)*4+8 ); + stbir__simdf8_madd_mem4( tot0, tot0, t, decode+(ofs)*4+8 ); #define stbir__store_output() \ stbir__simdf8_add4halves( t, stbir__if_simdf8_cast_to_simdf4(tot0), tot0 ); \ @@ -5199,7 +5378,7 @@ static void stbir__decode_scanline(stbir__info const * stbir_info, int n, float ++horizontal_contributors; \ output += 4; -#else +#else #define stbir__4_coeff_start() \ stbir__simdf tot0,tot1,c,cs; \ @@ -5212,7 +5391,7 @@ static void stbir__decode_scanline(stbir__info const * stbir_info, int n, float stbir__simdf_0123to2222( c, cs ); \ stbir__simdf_madd_mem( tot0, tot0, c, decode+8 ); \ stbir__simdf_0123to3333( c, cs ); \ - stbir__simdf_madd_mem( tot1, tot1, c, decode+12 ); + stbir__simdf_madd_mem( tot1, tot1, c, decode+12 ); #define stbir__4_coeff_continue_from_4( ofs ) \ STBIR_SIMD_NO_UNROLL(decode); \ @@ -5224,13 +5403,13 @@ static void stbir__decode_scanline(stbir__info const * stbir_info, int n, float stbir__simdf_0123to2222( c, cs ); \ stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*4+8 ); \ stbir__simdf_0123to3333( c, cs ); \ - stbir__simdf_madd_mem( tot1, tot1, c, decode+(ofs)*4+12 ); + stbir__simdf_madd_mem( tot1, tot1, c, decode+(ofs)*4+12 ); #define stbir__1_coeff_remnant( ofs ) \ STBIR_SIMD_NO_UNROLL(decode); \ stbir__simdf_load1( c, hc + (ofs) ); \ stbir__simdf_0123to0000( c, c ); \ - stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*4 ); + stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*4 ); #define stbir__2_coeff_remnant( ofs ) \ STBIR_SIMD_NO_UNROLL(decode); \ @@ -5238,8 +5417,8 @@ static void stbir__decode_scanline(stbir__info const * stbir_info, int n, float stbir__simdf_0123to0000( c, cs ); \ stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*4 ); \ stbir__simdf_0123to1111( c, cs ); \ - stbir__simdf_madd_mem( tot1, tot1, c, decode+(ofs)*4+4 ); - + stbir__simdf_madd_mem( tot1, tot1, c, decode+(ofs)*4+4 ); + #define stbir__3_coeff_remnant( ofs ) \ STBIR_SIMD_NO_UNROLL(decode); \ stbir__simdf_load( cs, hc + (ofs) ); \ @@ -5365,7 +5544,7 @@ static void stbir__decode_scanline(stbir__info const * stbir_info, int n, float x0 += decode[0+(ofs)*4] * c; \ x1 += decode[1+(ofs)*4] * c; \ x2 += decode[2+(ofs)*4] * c; \ - x3 += decode[3+(ofs)*4] * c; + x3 += decode[3+(ofs)*4] * c; #define stbir__2_coeff_remnant( ofs ) \ STBIR_SIMD_NO_UNROLL(decode); \ @@ -5378,8 +5557,8 @@ static void stbir__decode_scanline(stbir__info const * stbir_info, int n, float y0 += decode[4+(ofs)*4] * c; \ y1 += decode[5+(ofs)*4] * c; \ y2 += decode[6+(ofs)*4] * c; \ - y3 += decode[7+(ofs)*4] * c; - + y3 += decode[7+(ofs)*4] * c; + #define stbir__3_coeff_remnant( ofs ) \ STBIR_SIMD_NO_UNROLL(decode); \ c = hc[0+(ofs)]; \ @@ -5396,7 +5575,7 @@ static void stbir__decode_scanline(stbir__info const * stbir_info, int n, float x0 += decode[8+(ofs)*4] * c; \ x1 += decode[9+(ofs)*4] * c; \ x2 += decode[10+(ofs)*4] * c; \ - x3 += decode[11+(ofs)*4] * c; + x3 += decode[11+(ofs)*4] * c; #define stbir__store_output() \ output[0] = x0 + y0; \ @@ -5407,7 +5586,7 @@ static void stbir__decode_scanline(stbir__info const * stbir_info, int n, float ++horizontal_contributors; \ output += 4; -#endif +#endif #define STBIR__horizontal_channels 4 #define STB_IMAGE_RESIZE_DO_HORIZONTALS @@ -5426,7 +5605,7 @@ static void stbir__decode_scanline(stbir__info const * stbir_info, int n, float stbir__simdf_load1( c, hc ); \ stbir__simdf_0123to0000( c, c ); \ stbir__simdf_mult_mem( tot0, c, decode ); \ - stbir__simdf_mult_mem( tot1, c, decode+3 ); + stbir__simdf_mult_mem( tot1, c, decode+3 ); #define stbir__2_coeff_only() \ stbir__simdf tot0,tot1,c,cs; \ @@ -5437,7 +5616,7 @@ static void stbir__decode_scanline(stbir__info const * stbir_info, int n, float stbir__simdf_mult_mem( tot1, c, decode+3 ); \ stbir__simdf_0123to1111( c, cs ); \ stbir__simdf_madd_mem( tot0, tot0, c, decode+7 ); \ - stbir__simdf_madd_mem( tot1, tot1, c,decode+10 ); + stbir__simdf_madd_mem( tot1, tot1, c,decode+10 ); #define stbir__3_coeff_only() \ stbir__simdf tot0,tot1,c,cs; \ @@ -5451,7 +5630,7 @@ static void stbir__decode_scanline(stbir__info const * stbir_info, int n, float stbir__simdf_madd_mem( tot1, tot1, c, decode+10 ); \ stbir__simdf_0123to2222( c, cs ); \ stbir__simdf_madd_mem( tot0, tot0, c, decode+14 ); \ - stbir__simdf_madd_mem( tot1, tot1, c, decode+17 ); + stbir__simdf_madd_mem( tot1, tot1, c, decode+17 ); #define stbir__store_output_tiny() \ stbir__simdf_store( output+3, tot1 ); \ @@ -5473,7 +5652,7 @@ static void stbir__decode_scanline(stbir__info const * stbir_info, int n, float stbir__simdf8_0123to22222222( c, cs ); \ stbir__simdf8_madd_mem( tot0, tot0, c, decode+14 ); \ stbir__simdf8_0123to33333333( c, cs ); \ - stbir__simdf8_madd_mem( tot1, tot1, c, decode+21 ); + stbir__simdf8_madd_mem( tot1, tot1, c, decode+21 ); #define stbir__4_coeff_continue_from_4( ofs ) \ STBIR_SIMD_NO_UNROLL(decode); \ @@ -5485,19 +5664,19 @@ static void stbir__decode_scanline(stbir__info const * stbir_info, int n, float stbir__simdf8_0123to22222222( c, cs ); \ stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*7+14 ); \ stbir__simdf8_0123to33333333( c, cs ); \ - stbir__simdf8_madd_mem( tot1, tot1, c, decode+(ofs)*7+21 ); + stbir__simdf8_madd_mem( tot1, tot1, c, decode+(ofs)*7+21 ); #define stbir__1_coeff_remnant( ofs ) \ STBIR_SIMD_NO_UNROLL(decode); \ stbir__simdf8_load1b( c, hc + (ofs) ); \ - stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*7 ); + stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*7 ); #define stbir__2_coeff_remnant( ofs ) \ STBIR_SIMD_NO_UNROLL(decode); \ stbir__simdf8_load1b( c, hc + (ofs) ); \ stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*7 ); \ stbir__simdf8_load1b( c, hc + (ofs)+1 ); \ - stbir__simdf8_madd_mem( tot1, tot1, c, decode+(ofs)*7+7 ); + stbir__simdf8_madd_mem( tot1, tot1, c, decode+(ofs)*7+7 ); #define stbir__3_coeff_remnant( ofs ) \ STBIR_SIMD_NO_UNROLL(decode); \ @@ -5507,7 +5686,7 @@ static void stbir__decode_scanline(stbir__info const * stbir_info, int n, float stbir__simdf8_0123to11111111( c, cs ); \ stbir__simdf8_madd_mem( tot1, tot1, c, decode+(ofs)*7+7 ); \ stbir__simdf8_0123to22222222( c, cs ); \ - stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*7+14 ); + stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*7+14 ); #define stbir__store_output() \ stbir__simdf8_add( tot0, tot0, tot1 ); \ @@ -5540,7 +5719,7 @@ static void stbir__decode_scanline(stbir__info const * stbir_info, int n, float stbir__simdf_madd_mem( tot1, tot1, c, decode+17 ); \ stbir__simdf_0123to3333( c, cs ); \ stbir__simdf_madd_mem( tot2, tot2, c, decode+21 ); \ - stbir__simdf_madd_mem( tot3, tot3, c, decode+24 ); + stbir__simdf_madd_mem( tot3, tot3, c, decode+24 ); #define stbir__4_coeff_continue_from_4( ofs ) \ STBIR_SIMD_NO_UNROLL(decode); \ @@ -5556,7 +5735,7 @@ static void stbir__decode_scanline(stbir__info const * stbir_info, int n, float stbir__simdf_madd_mem( tot1, tot1, c, decode+(ofs)*7+17 ); \ stbir__simdf_0123to3333( c, cs ); \ stbir__simdf_madd_mem( tot2, tot2, c, decode+(ofs)*7+21 ); \ - stbir__simdf_madd_mem( tot3, tot3, c, decode+(ofs)*7+24 ); + stbir__simdf_madd_mem( tot3, tot3, c, decode+(ofs)*7+24 ); #define stbir__1_coeff_remnant( ofs ) \ STBIR_SIMD_NO_UNROLL(decode); \ @@ -5573,8 +5752,8 @@ static void stbir__decode_scanline(stbir__info const * stbir_info, int n, float stbir__simdf_madd_mem( tot1, tot1, c, decode+(ofs)*7+3 ); \ stbir__simdf_0123to1111( c, cs ); \ stbir__simdf_madd_mem( tot2, tot2, c, decode+(ofs)*7+7 ); \ - stbir__simdf_madd_mem( tot3, tot3, c, decode+(ofs)*7+10 ); - + stbir__simdf_madd_mem( tot3, tot3, c, decode+(ofs)*7+10 ); + #define stbir__3_coeff_remnant( ofs ) \ STBIR_SIMD_NO_UNROLL(decode); \ stbir__simdf_load( cs, hc + (ofs) ); \ @@ -5586,7 +5765,7 @@ static void stbir__decode_scanline(stbir__info const * stbir_info, int n, float stbir__simdf_madd_mem( tot3, tot3, c, decode+(ofs)*7+10 ); \ stbir__simdf_0123to2222( c, cs ); \ stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*7+14 ); \ - stbir__simdf_madd_mem( tot1, tot1, c, decode+(ofs)*7+17 ); + stbir__simdf_madd_mem( tot1, tot1, c, decode+(ofs)*7+17 ); #define stbir__store_output() \ stbir__simdf_add( tot0, tot0, tot2 ); \ @@ -5610,7 +5789,7 @@ static void stbir__decode_scanline(stbir__info const * stbir_info, int n, float tot3 = decode[3]*c; \ tot4 = decode[4]*c; \ tot5 = decode[5]*c; \ - tot6 = decode[6]*c; + tot6 = decode[6]*c; #define stbir__2_coeff_only() \ float tot0, tot1, tot2, tot3, tot4, tot5, tot6, c; \ @@ -5704,7 +5883,7 @@ static void stbir__decode_scanline(stbir__info const * stbir_info, int n, float y3 += decode[24] * c; \ y4 += decode[25] * c; \ y5 += decode[26] * c; \ - y6 += decode[27] * c; + y6 += decode[27] * c; #define stbir__4_coeff_continue_from_4( ofs ) \ STBIR_SIMD_NO_UNROLL(decode); \ @@ -5739,7 +5918,7 @@ static void stbir__decode_scanline(stbir__info const * stbir_info, int n, float y3 += decode[24+(ofs)*7] * c; \ y4 += decode[25+(ofs)*7] * c; \ y5 += decode[26+(ofs)*7] * c; \ - y6 += decode[27+(ofs)*7] * c; + y6 += decode[27+(ofs)*7] * c; #define stbir__1_coeff_remnant( ofs ) \ STBIR_SIMD_NO_UNROLL(decode); \ @@ -5770,7 +5949,7 @@ static void stbir__decode_scanline(stbir__info const * stbir_info, int n, float y4 += decode[11+(ofs)*7] * c; \ y5 += decode[12+(ofs)*7] * c; \ y6 += decode[13+(ofs)*7] * c; \ - + #define stbir__3_coeff_remnant( ofs ) \ STBIR_SIMD_NO_UNROLL(decode); \ c = hc[0+(ofs)]; \ @@ -5810,7 +5989,7 @@ static void stbir__decode_scanline(stbir__info const * stbir_info, int n, float ++horizontal_contributors; \ output += 7; -#endif +#endif #define STBIR__horizontal_channels 7 #define STB_IMAGE_RESIZE_DO_HORIZONTALS @@ -5937,7 +6116,7 @@ static void stbir__encode_scanline( stbir__info const * stbir_info, void *output // if we have an output callback, we first convert the decode buffer in place (and then hand that to the callback) if ( stbir_info->out_pixels_cb ) output_buffer = encode_buffer; - + STBIR_PROFILE_START( encode ); // convert into the output buffer stbir_info->encode_pixels( output_buffer, width_times_channels, encode_buffer ); @@ -5945,7 +6124,7 @@ static void stbir__encode_scanline( stbir__info const * stbir_info, void *output // if we have an output callback, call it to send the data if ( stbir_info->out_pixels_cb ) - stbir_info->out_pixels_cb( output_buffer_data, num_pixels, row, stbir_info->user_data ); + stbir_info->out_pixels_cb( output_buffer, num_pixels, row, stbir_info->user_data ); } @@ -6015,7 +6194,7 @@ static void stbir__resample_vertical_gather(stbir__info const * stbir_info, stbi stbir__resample_horizontal_gather(stbir_info, encode_buffer, decode_buffer STBIR_ONLY_PROFILE_SET_SPLIT_INFO ); } - stbir__encode_scanline( stbir_info, ( (char *) stbir_info->output_data ) + ((ptrdiff_t)n * (ptrdiff_t)stbir_info->output_stride_bytes), + stbir__encode_scanline( stbir_info, ( (char *) stbir_info->output_data ) + ((size_t)n * (size_t)stbir_info->output_stride_bytes), encode_buffer, n STBIR_ONLY_PROFILE_SET_SPLIT_INFO ); } @@ -6030,7 +6209,7 @@ static void stbir__decode_and_resample_for_vertical_gather_loop(stbir__info cons // update new end scanline split_info->ring_buffer_last_scanline = n; - // get ring buffer + // get ring buffer ring_buffer_index = (split_info->ring_buffer_begin_index + (split_info->ring_buffer_last_scanline - split_info->ring_buffer_first_scanline)) % stbir_info->ring_buffer_num_entries; ring_buffer = stbir__get_ring_buffer_entry(stbir_info, split_info, ring_buffer_index); @@ -6056,7 +6235,7 @@ static void stbir__vertical_gather_loop( stbir__info const * stbir_info, stbir__ // initialize the ring buffer for gathering split_info->ring_buffer_begin_index = 0; - split_info->ring_buffer_first_scanline = stbir_info->vertical.extent_info.lowest; + split_info->ring_buffer_first_scanline = vertical_contributors->n0; split_info->ring_buffer_last_scanline = split_info->ring_buffer_first_scanline - 1; // means "empty" for (y = start_output_y; y < end_output_y; y++) @@ -6080,12 +6259,12 @@ static void stbir__vertical_gather_loop( stbir__info const * stbir_info, stbir__ split_info->ring_buffer_first_scanline++; split_info->ring_buffer_begin_index++; } - + if ( stbir_info->vertical_first ) { float * ring_buffer = stbir__get_ring_buffer_scanline( stbir_info, split_info, ++split_info->ring_buffer_last_scanline ); // Decode the nth scanline from the source image into the decode buffer. - stbir__decode_scanline( stbir_info, split_info->ring_buffer_last_scanline, ring_buffer STBIR_ONLY_PROFILE_SET_SPLIT_INFO ); + stbir__decode_scanline( stbir_info, split_info->ring_buffer_last_scanline, ring_buffer STBIR_ONLY_PROFILE_SET_SPLIT_INFO ); } else { @@ -6108,10 +6287,10 @@ static void stbir__encode_first_scanline_from_scatter(stbir__info const * stbir_ { // evict a scanline out into the output buffer float* ring_buffer_entry = stbir__get_ring_buffer_entry(stbir_info, split_info, split_info->ring_buffer_begin_index ); - + // dump the scanline out - stbir__encode_scanline( stbir_info, ( (char *)stbir_info->output_data ) + ( (ptrdiff_t)split_info->ring_buffer_first_scanline * (ptrdiff_t)stbir_info->output_stride_bytes ), ring_buffer_entry, split_info->ring_buffer_first_scanline STBIR_ONLY_PROFILE_SET_SPLIT_INFO ); - + stbir__encode_scanline( stbir_info, ( (char *)stbir_info->output_data ) + ( (size_t)split_info->ring_buffer_first_scanline * (size_t)stbir_info->output_stride_bytes ), ring_buffer_entry, split_info->ring_buffer_first_scanline STBIR_ONLY_PROFILE_SET_SPLIT_INFO ); + // mark it as empty ring_buffer_entry[ 0 ] = STBIR__FLOAT_EMPTY_MARKER; @@ -6129,10 +6308,10 @@ static void stbir__horizontal_resample_and_encode_first_scanline_from_scatter(st // Now resample it into the buffer. stbir__resample_horizontal_gather( stbir_info, split_info->vertical_buffer, ring_buffer_entry STBIR_ONLY_PROFILE_SET_SPLIT_INFO ); - + // dump the scanline out - stbir__encode_scanline( stbir_info, ( (char *)stbir_info->output_data ) + ( (ptrdiff_t)split_info->ring_buffer_first_scanline * (ptrdiff_t)stbir_info->output_stride_bytes ), split_info->vertical_buffer, split_info->ring_buffer_first_scanline STBIR_ONLY_PROFILE_SET_SPLIT_INFO ); - + stbir__encode_scanline( stbir_info, ( (char *)stbir_info->output_data ) + ( (size_t)split_info->ring_buffer_first_scanline * (size_t)stbir_info->output_stride_bytes ), split_info->vertical_buffer, split_info->ring_buffer_first_scanline STBIR_ONLY_PROFILE_SET_SPLIT_INFO ); + // mark it as empty ring_buffer_entry[ 0 ] = STBIR__FLOAT_EMPTY_MARKER; @@ -6172,7 +6351,7 @@ static void stbir__resample_vertical_scatter(stbir__info const * stbir_info, stb STBIR_PROFILE_END( vertical ); } -typedef void stbir__handle_scanline_for_scatter_func(stbir__info const * stbir_info, stbir__per_split_info* split_info); +typedef void stbir__handle_scanline_for_scatter_func(stbir__info const * stbir_info, stbir__per_split_info* split_info); static void stbir__vertical_scatter_loop( stbir__info const * stbir_info, stbir__per_split_info* split_info, int split_count ) { @@ -6193,7 +6372,7 @@ static void stbir__vertical_scatter_loop( stbir__info const * stbir_info, stbir_ end_input_y = split_info[split_count-1].end_input_y; // adjust for starting offset start_input_y - y = start_input_y + stbir_info->vertical.filter_pixel_margin; + y = start_input_y + stbir_info->vertical.filter_pixel_margin; vertical_contributors += y ; vertical_coefficients += stbir_info->vertical.coefficient_width * y; @@ -6240,7 +6419,7 @@ static void stbir__vertical_scatter_loop( stbir__info const * stbir_info, stbir_ split_info->start_input_y = y; on_first_input_y = 0; - // clip the region + // clip the region if ( out_first_scanline < start_output_y ) { vc += start_output_y - out_first_scanline; @@ -6253,11 +6432,11 @@ static void stbir__vertical_scatter_loop( stbir__info const * stbir_info, stbir_ // if very first scanline, init the index if (split_info->ring_buffer_begin_index < 0) split_info->ring_buffer_begin_index = out_first_scanline - start_output_y; - + STBIR_ASSERT( split_info->ring_buffer_begin_index <= out_first_scanline ); // Decode the nth scanline from the source image into the decode buffer. - stbir__decode_scanline( stbir_info, y, split_info->decode_buffer STBIR_ONLY_PROFILE_SET_SPLIT_INFO ); + stbir__decode_scanline( stbir_info, y, split_info->decode_buffer STBIR_ONLY_PROFILE_SET_SPLIT_INFO ); // When horizontal first, we resample horizontally into the vertical buffer before we scatter it out if ( !stbir_info->vertical_first ) @@ -6269,7 +6448,7 @@ static void stbir__vertical_scatter_loop( stbir__info const * stbir_info, stbir_ if ( ( ( split_info->ring_buffer_last_scanline - split_info->ring_buffer_first_scanline + 1 ) == stbir_info->ring_buffer_num_entries ) && ( out_last_scanline > split_info->ring_buffer_last_scanline ) ) handle_scanline_for_scatter( stbir_info, split_info ); - + // Now the horizontal buffer is ready to write to all ring buffer rows, so do it. stbir__resample_vertical_scatter(stbir_info, split_info, out_first_scanline, out_last_scanline, vc, (float*)scanline_scatter_buffer, (float*)scanline_scatter_buffer_end ); @@ -6305,7 +6484,7 @@ static void stbir__set_sampler(stbir__sampler * samp, stbir_filter filter, stbir if (scale_info->scale >= ( 1.0f - stbir__small_float ) ) { if ( (scale_info->scale <= ( 1.0f + stbir__small_float ) ) && ( STBIR_CEILF(scale_info->pixel_shift) == scale_info->pixel_shift ) ) - filter = STBIR_FILTER_POINT_SAMPLE; + filter = STBIR_FILTER_POINT_SAMPLE; else filter = STBIR_DEFAULT_FILTER_UPSAMPLE; } @@ -6313,7 +6492,7 @@ static void stbir__set_sampler(stbir__sampler * samp, stbir_filter filter, stbir samp->filter_enum = filter; STBIR_ASSERT(samp->filter_enum != 0); - STBIR_ASSERT((unsigned)samp->filter_enum < STBIR_FILTER_OTHER); + STBIR_ASSERT((unsigned)samp->filter_enum < STBIR_FILTER_OTHER); samp->filter_kernel = stbir__builtin_kernels[ filter ]; samp->filter_support = stbir__builtin_supports[ filter ]; @@ -6339,15 +6518,31 @@ static void stbir__set_sampler(stbir__sampler * samp, stbir_filter filter, stbir // pre calculate stuff based on the above samp->coefficient_width = stbir__get_coefficient_width(samp, samp->is_gather, user_data); + // filter_pixel_width is the conservative size in pixels of input that affect an output pixel. + // In rare cases (only with 2 pix to 1 pix with the default filters), it's possible that the + // filter will extend before or after the scanline beyond just one extra entire copy of the + // scanline (we would hit the edge twice). We don't let you do that, so we clamp the total + // width to 3x the total of input pixel (once for the scanline, once for the left side + // overhang, and once for the right side). We only do this for edge mode, since the other + // modes can just re-edge clamp back in again. if ( edge == STBIR_EDGE_WRAP ) - if ( samp->filter_pixel_width > ( scale_info->input_full_size * 2 ) ) // this can only happen when shrinking to a single pixel - samp->filter_pixel_width = scale_info->input_full_size * 2; + if ( samp->filter_pixel_width > ( scale_info->input_full_size * 3 ) ) + samp->filter_pixel_width = scale_info->input_full_size * 3; // This is how much to expand buffers to account for filters seeking outside // the image boundaries. samp->filter_pixel_margin = samp->filter_pixel_width / 2; + + // filter_pixel_margin is the amount that this filter can overhang on just one side of either + // end of the scanline (left or the right). Since we only allow you to overhang 1 scanline's + // worth of pixels, we clamp this one side of overhang to the input scanline size. Again, + // this clamping only happens in rare cases with the default filters (2 pix to 1 pix). + if ( edge == STBIR_EDGE_WRAP ) + if ( samp->filter_pixel_margin > scale_info->input_full_size ) + samp->filter_pixel_margin = scale_info->input_full_size; samp->num_contributors = stbir__get_contributors(samp, samp->is_gather); + samp->contributors_size = samp->num_contributors * sizeof(stbir__contributors); samp->coefficients_size = samp->num_contributors * samp->coefficient_width * sizeof(float) + sizeof(float); // extra sizeof(float) is padding @@ -6397,8 +6592,8 @@ static void stbir__get_conservative_extents( stbir__sampler * samp, stbir__contr range->n0 = in_first_pixel; stbir__calculate_in_pixel_range( &in_first_pixel, &in_last_pixel, (float)output_sub_size, 0, inv_scale, out_shift, input_full_size, edge ); range->n1 = in_last_pixel; - - // now go through the margin to the start of area to find bottom + + // now go through the margin to the start of area to find bottom n = range->n0 + 1; input_end = -filter_pixel_margin; while( n >= input_end ) @@ -6413,7 +6608,7 @@ static void stbir__get_conservative_extents( stbir__sampler * samp, stbir__contr --n; } - // now go through the end of the area through the margin to find top + // now go through the end of the area through the margin to find top n = range->n1 - 1; input_end = n + 1 + filter_pixel_margin; while( n <= input_end ) @@ -6462,7 +6657,7 @@ static void stbir__get_split_info( stbir__per_split_info* split_info, int splits cur = 0; for( i = 0 ; i < splits ; i++ ) { - int each; + int each; split_info[i].start_output_y = cur; each = left / ( splits - i ); split_info[i].end_output_y = cur + each; @@ -6478,7 +6673,7 @@ static void stbir__get_split_info( stbir__per_split_info* split_info, int splits static void stbir__free_internal_mem( stbir__info *info ) { #define STBIR__FREE_AND_CLEAR( ptr ) { if ( ptr ) { void * p = (ptr); (ptr) = 0; STBIR_FREE( p, info->user_data); } } - + if ( info ) { #ifndef STBIR__SEPARATE_ALLOCATIONS @@ -6496,16 +6691,16 @@ static void stbir__free_internal_mem( stbir__info *info ) for( j = 0 ; j < info->alloc_ring_buffer_num_entries ; j++ ) { #ifdef STBIR_SIMD8 - if ( info->effective_channels == 3 ) + if ( info->effective_channels == 3 ) --info->split_info[i].ring_buffers[j]; // avx in 3 channel mode needs one float at the start of the buffer - #endif + #endif STBIR__FREE_AND_CLEAR( info->split_info[i].ring_buffers[j] ); } #ifdef STBIR_SIMD8 - if ( info->effective_channels == 3 ) + if ( info->effective_channels == 3 ) --info->split_info[i].decode_buffer; // avx in 3 channel mode needs one float at the start of the buffer - #endif + #endif STBIR__FREE_AND_CLEAR( info->split_info[i].decode_buffer ); STBIR__FREE_AND_CLEAR( info->split_info[i].ring_buffers ); STBIR__FREE_AND_CLEAR( info->split_info[i].vertical_buffer ); @@ -6522,7 +6717,7 @@ static void stbir__free_internal_mem( stbir__info *info ) STBIR__FREE_AND_CLEAR( info ); #endif } - + #undef STBIR__FREE_AND_CLEAR } @@ -6534,20 +6729,20 @@ static int stbir__get_max_split( int splits, int height ) for( i = 0 ; i < splits ; i++ ) { int each = height / ( splits - i ); - if ( each > max ) + if ( each > max ) max = each; height -= each; } return max; } -static stbir__horizontal_gather_channels_func ** stbir__horizontal_gather_n_coeffs_funcs[8] = -{ +static stbir__horizontal_gather_channels_func ** stbir__horizontal_gather_n_coeffs_funcs[8] = +{ 0, stbir__horizontal_gather_1_channels_with_n_coeffs_funcs, stbir__horizontal_gather_2_channels_with_n_coeffs_funcs, stbir__horizontal_gather_3_channels_with_n_coeffs_funcs, stbir__horizontal_gather_4_channels_with_n_coeffs_funcs, 0,0, stbir__horizontal_gather_7_channels_with_n_coeffs_funcs }; -static stbir__horizontal_gather_channels_func ** stbir__horizontal_gather_channels_funcs[8] = -{ +static stbir__horizontal_gather_channels_func ** stbir__horizontal_gather_channels_funcs[8] = +{ 0, stbir__horizontal_gather_1_channels_funcs, stbir__horizontal_gather_2_channels_funcs, stbir__horizontal_gather_3_channels_funcs, stbir__horizontal_gather_4_channels_funcs, 0,0, stbir__horizontal_gather_7_channels_funcs }; @@ -6622,28 +6817,28 @@ static STBIR__V_FIRST_INFO STBIR__V_FIRST_INFO_BUFFER = {0}; #endif // Figure out whether to scale along the horizontal or vertical first. -// This only *super* important when you are scaling by a massively -// different amount in the vertical vs the horizontal (for example, if -// you are scaling by 2x in the width, and 0.5x in the height, then you -// want to do the vertical scale first, because it's around 3x faster +// This only *super* important when you are scaling by a massively +// different amount in the vertical vs the horizontal (for example, if +// you are scaling by 2x in the width, and 0.5x in the height, then you +// want to do the vertical scale first, because it's around 3x faster // in that order. // -// In more normal circumstances, this makes a 20-40% differences, so +// In more normal circumstances, this makes a 20-40% differences, so // it's good to get right, but not critical. The normal way that you -// decide which direction goes first is just figuring out which -// direction does more multiplies. But with modern CPUs with their +// decide which direction goes first is just figuring out which +// direction does more multiplies. But with modern CPUs with their // fancy caches and SIMD and high IPC abilities, so there's just a lot -// more that goes into it. +// more that goes into it. // -// My handwavy sort of solution is to have an app that does a whole +// My handwavy sort of solution is to have an app that does a whole // bunch of timing for both vertical and horizontal first modes, // and then another app that can read lots of these timing files // and try to search for the best weights to use. Dotimings.c // is the app that does a bunch of timings, and vf_train.c is the -// app that solves for the best weights (and shows how well it +// app that solves for the best weights (and shows how well it // does currently). -static int stbir__should_do_vertical_first( float weights_table[STBIR_RESIZE_CLASSIFICATIONS][4], int horizontal_filter_pixel_width, float horizontal_scale, int horizontal_output_size, int vertical_filter_pixel_width, float vertical_scale, int vertical_output_size, int is_gather, STBIR__V_FIRST_INFO * info ) +static int stbir__should_do_vertical_first( float weights_table[STBIR_RESIZE_CLASSIFICATIONS][4], int horizontal_filter_pixel_width, float horizontal_scale, int horizontal_output_size, int vertical_filter_pixel_width, float vertical_scale, int vertical_output_size, int is_gather, STBIR__V_FIRST_INFO * info ) { double v_cost, h_cost; float * weights; @@ -6655,15 +6850,15 @@ static int stbir__should_do_vertical_first( float weights_table[STBIR_RESIZE_CLA v_classification = ( vertical_output_size < horizontal_output_size ) ? 6 : 7; else if ( vertical_scale <= 1.0f ) v_classification = ( is_gather ) ? 1 : 0; - else if ( vertical_scale <= 2.0f) + else if ( vertical_scale <= 2.0f) v_classification = 2; - else if ( vertical_scale <= 3.0f) + else if ( vertical_scale <= 3.0f) v_classification = 3; - else if ( vertical_scale <= 4.0f) + else if ( vertical_scale <= 4.0f) v_classification = 5; - else + else v_classification = 6; - + // use the right weights weights = weights_table[ v_classification ]; @@ -6684,10 +6879,10 @@ static int stbir__should_do_vertical_first( float weights_table[STBIR_RESIZE_CLA info->is_gather = is_gather; } - // and this allows us to override everything for testing (see dotiming.c) - if ( ( info ) && ( info->control_v_first ) ) + // and this allows us to override everything for testing (see dotiming.c) + if ( ( info ) && ( info->control_v_first ) ) vertical_first = ( info->control_v_first == 2 ) ? 1 : 0; - + return vertical_first; } @@ -6699,9 +6894,9 @@ static unsigned char stbir__pixel_channels[] = { }; // the internal pixel layout enums are in a different order, so we can easily do range comparisons of types -// the public pixel layout is ordered in a way that if you cast num_channels (1-4) to the enum, you get something sensible +// the public pixel layout is ordered in a way that if you cast num_channels (1-4) to the enum, you get something sensible static stbir_internal_pixel_layout stbir__pixel_layout_convert_public_to_internal[] = { - STBIRI_BGR, STBIRI_1CHANNEL, STBIRI_2CHANNEL, STBIRI_RGB, STBIRI_RGBA, + STBIRI_BGR, STBIRI_1CHANNEL, STBIRI_2CHANNEL, STBIRI_RGB, STBIRI_RGBA, STBIRI_4CHANNEL, STBIRI_BGRA, STBIRI_ARGB, STBIRI_ABGR, STBIRI_RA, STBIRI_AR, STBIRI_RGBA_PM, STBIRI_BGRA_PM, STBIRI_ARGB_PM, STBIRI_ABGR_PM, STBIRI_RA_PM, STBIRI_AR_PM, }; @@ -6712,17 +6907,17 @@ static stbir__info * stbir__alloc_internal_mem_and_build_samplers( stbir__sample stbir__info * info = 0; void * alloced = 0; - int alloced_total = 0; + size_t alloced_total = 0; int vertical_first; int decode_buffer_size, ring_buffer_length_bytes, ring_buffer_size, vertical_buffer_size, alloc_ring_buffer_num_entries; int alpha_weighting_type = 0; // 0=none, 1=simple, 2=fancy - int conservative_split_output_size = stbir__get_max_split( splits, vertical->scale_info.output_sub_size ); - stbir_internal_pixel_layout input_pixel_layout = stbir__pixel_layout_convert_public_to_internal[ input_pixel_layout_public ]; + int conservative_split_output_size = stbir__get_max_split( splits, vertical->scale_info.output_sub_size ); + stbir_internal_pixel_layout input_pixel_layout = stbir__pixel_layout_convert_public_to_internal[ input_pixel_layout_public ]; stbir_internal_pixel_layout output_pixel_layout = stbir__pixel_layout_convert_public_to_internal[ output_pixel_layout_public ]; - int channels = stbir__pixel_channels[ input_pixel_layout ]; + int channels = stbir__pixel_channels[ input_pixel_layout ]; int effective_channels = channels; - + // first figure out what type of alpha weighting to use (if any) if ( ( horizontal->filter_enum != STBIR_FILTER_POINT_SAMPLE ) || ( vertical->filter_enum != STBIR_FILTER_POINT_SAMPLE ) ) // no alpha weighting on point sampling { @@ -6760,11 +6955,11 @@ static stbir__info * stbir__alloc_internal_mem_and_build_samplers( stbir__sample // sometimes read one float off in some of the unrolled loops (with a weight of zero coeff, so it doesn't have an effect) decode_buffer_size = ( conservative->n1 - conservative->n0 + 1 ) * effective_channels * sizeof(float) + sizeof(float); // extra float for padding - + #if defined( STBIR__SEPARATE_ALLOCATIONS ) && defined(STBIR_SIMD8) if ( effective_channels == 3 ) decode_buffer_size += sizeof(float); // avx in 3 channel mode needs one float at the start of the buffer (only with separate allocations) -#endif +#endif ring_buffer_length_bytes = horizontal->scale_info.output_sub_size * effective_channels * sizeof(float) + sizeof(float); // extra float for padding @@ -6803,9 +6998,9 @@ static stbir__info * stbir__alloc_internal_mem_and_build_samplers( stbir__sample #define STBIR__NEXT_PTR( ptr, size, ntype ) advance_mem = (void*) ( ( ((size_t)advance_mem) + 15 ) & ~15 ); if ( alloced ) ptr = (ntype*)advance_mem; advance_mem = ((char*)advance_mem) + (size); #endif - STBIR__NEXT_PTR( info, sizeof( stbir__info ), stbir__info ); + STBIR__NEXT_PTR( info, sizeof( stbir__info ), stbir__info ); - STBIR__NEXT_PTR( info->split_info, sizeof( stbir__per_split_info ) * splits, stbir__per_split_info ); + STBIR__NEXT_PTR( info->split_info, sizeof( stbir__per_split_info ) * splits, stbir__per_split_info ); if ( info ) { @@ -6820,39 +7015,39 @@ static stbir__info * stbir__alloc_internal_mem_and_build_samplers( stbir__sample info->channels = channels; info->effective_channels = effective_channels; - + info->offset_x = new_x; info->offset_y = new_y; info->alloc_ring_buffer_num_entries = alloc_ring_buffer_num_entries; - info->ring_buffer_num_entries = 0; + info->ring_buffer_num_entries = 0; info->ring_buffer_length_bytes = ring_buffer_length_bytes; info->splits = splits; info->vertical_first = vertical_first; - info->input_pixel_layout_internal = input_pixel_layout; + info->input_pixel_layout_internal = input_pixel_layout; info->output_pixel_layout_internal = output_pixel_layout; // setup alpha weight functions info->alpha_weight = 0; info->alpha_unweight = 0; - + // handle alpha weighting functions and overrides if ( alpha_weighting_type == 2 ) { // high quality alpha multiplying on the way in, dividing on the way out - info->alpha_weight = fancy_alpha_weights[ input_pixel_layout - STBIRI_RGBA ]; + info->alpha_weight = fancy_alpha_weights[ input_pixel_layout - STBIRI_RGBA ]; info->alpha_unweight = fancy_alpha_unweights[ output_pixel_layout - STBIRI_RGBA ]; } else if ( alpha_weighting_type == 4 ) { // fast alpha multiplying on the way in, dividing on the way out - info->alpha_weight = simple_alpha_weights[ input_pixel_layout - STBIRI_RGBA ]; + info->alpha_weight = simple_alpha_weights[ input_pixel_layout - STBIRI_RGBA ]; info->alpha_unweight = simple_alpha_unweights[ output_pixel_layout - STBIRI_RGBA ]; } else if ( alpha_weighting_type == 1 ) { // fast alpha on the way in, leave in premultiplied form on way out - info->alpha_weight = simple_alpha_weights[ input_pixel_layout - STBIRI_RGBA ]; + info->alpha_weight = simple_alpha_weights[ input_pixel_layout - STBIRI_RGBA ]; } else if ( alpha_weighting_type == 3 ) { @@ -6871,7 +7066,7 @@ static stbir__info * stbir__alloc_internal_mem_and_build_samplers( stbir__sample info->alpha_weight = stbir__simple_flip_3ch; } - } + } // get all the per-split buffers for( i = 0 ; i < splits ; i++ ) @@ -6883,7 +7078,7 @@ static stbir__info * stbir__alloc_internal_mem_and_build_samplers( stbir__sample #ifdef STBIR_SIMD8 if ( ( info ) && ( effective_channels == 3 ) ) ++info->split_info[i].decode_buffer; // avx in 3 channel mode needs one float at the start of the buffer - #endif + #endif STBIR__NEXT_PTR( info->split_info[i].ring_buffers, alloc_ring_buffer_num_entries * sizeof(float*), float* ); { @@ -6894,7 +7089,7 @@ static stbir__info * stbir__alloc_internal_mem_and_build_samplers( stbir__sample #ifdef STBIR_SIMD8 if ( ( info ) && ( effective_channels == 3 ) ) ++info->split_info[i].ring_buffers[j]; // avx in 3 channel mode needs one float at the start of the buffer - #endif + #endif } } #else @@ -6922,10 +7117,10 @@ static stbir__info * stbir__alloc_internal_mem_and_build_samplers( stbir__sample #endif if ( temp_mem_amt >= both ) { - if ( info ) - { - vertical->gather_prescatter_contributors = (stbir__contributors*)info->split_info[0].decode_buffer; - vertical->gather_prescatter_coefficients = (float*) ( ( (char*)info->split_info[0].decode_buffer ) + vertical->gather_prescatter_contributors_size ); + if ( info ) + { + vertical->gather_prescatter_contributors = (stbir__contributors*)info->split_info[0].decode_buffer; + vertical->gather_prescatter_coefficients = (float*) ( ( (char*)info->split_info[0].decode_buffer ) + vertical->gather_prescatter_contributors_size ); } } else @@ -6948,7 +7143,7 @@ static stbir__info * stbir__alloc_internal_mem_and_build_samplers( stbir__sample if ( diff_shift < 0.0f ) diff_shift = -diff_shift; if ( ( diff_scale <= stbir__small_float ) && ( diff_shift <= stbir__small_float ) ) { - if ( horizontal->is_gather == vertical->is_gather ) + if ( horizontal->is_gather == vertical->is_gather ) { copy_horizontal = 1; goto no_vert_alloc; @@ -6975,16 +7170,16 @@ static stbir__info * stbir__alloc_internal_mem_and_build_samplers( stbir__sample // but if the number of coeffs <= 12, use another set of special cases. <=12 coeffs is any enlarging resize, or shrinking resize down to about 1/3 size if ( horizontal->extent_info.widest <= 12 ) info->horizontal_gather_channels = stbir__horizontal_gather_channels_funcs[ effective_channels ][ horizontal->extent_info.widest - 1 ]; - + info->scanline_extents.conservative.n0 = conservative->n0; info->scanline_extents.conservative.n1 = conservative->n1; - + // get exact extents stbir__get_extents( horizontal, &info->scanline_extents ); // pack the horizontal coeffs - horizontal->coefficient_width = stbir__pack_coefficients(horizontal->num_contributors, horizontal->contributors, horizontal->coefficients, horizontal->coefficient_width, horizontal->extent_info.widest, info->scanline_extents.conservative.n1 + 1 ); - + horizontal->coefficient_width = stbir__pack_coefficients(horizontal->num_contributors, horizontal->contributors, horizontal->coefficients, horizontal->coefficient_width, horizontal->extent_info.widest, info->scanline_extents.conservative.n0, info->scanline_extents.conservative.n1 ); + STBIR_MEMCPY( &info->horizontal, horizontal, sizeof( stbir__sampler ) ); STBIR_PROFILE_BUILD_END( horizontal ); @@ -7014,36 +7209,27 @@ static stbir__info * stbir__alloc_internal_mem_and_build_samplers( stbir__sample info->ring_buffer_num_entries = conservative_split_output_size; STBIR_ASSERT( info->ring_buffer_num_entries <= info->alloc_ring_buffer_num_entries ); - // a few of the horizontal gather functions read one dword past the end (but mask it out), so put in a normal value so no snans or denormals accidentally sneak in + // a few of the horizontal gather functions read past the end of the decode (but mask it out), + // so put in normal values so no snans or denormals accidentally sneak in (also, in the ring + // buffer for vertical first) for( i = 0 ; i < splits ; i++ ) { - int width, ofs; - - // find the right most span - if ( info->scanline_extents.spans[0].n1 > info->scanline_extents.spans[1].n1 ) - width = info->scanline_extents.spans[0].n1 - info->scanline_extents.spans[0].n0; - else - width = info->scanline_extents.spans[1].n1 - info->scanline_extents.spans[1].n0; - - // this calc finds the exact end of the decoded scanline for all filter modes. - // usually this is just the width * effective channels. But we have to account - // for the area to the left of the scanline for wrap filtering and alignment, this - // is stored as a negative value in info->scanline_extents.conservative.n0. Next, - // we need to skip the exact size of the right hand size filter area (again for - // wrap mode), this is in info->scanline_extents.edge_sizes[1]). - ofs = ( width + 1 - info->scanline_extents.conservative.n0 + info->scanline_extents.edge_sizes[1] ) * effective_channels; - - // place a known, but numerically valid value in the decode buffer - info->split_info[i].decode_buffer[ ofs ] = 9999.0f; + int t, ofs, start; + + ofs = decode_buffer_size / 4; + start = ofs - 4; + if ( start < 0 ) start = 0; + + for( t = start ; t < ofs; t++ ) + info->split_info[i].decode_buffer[ t ] = 9999.0f; - // if vertical filtering first, place a known, but numerically valid value in the all - // of the ring buffer accumulators if ( vertical_first ) { - int j; + int j; for( j = 0; j < info->ring_buffer_num_entries ; j++ ) { - stbir__get_ring_buffer_entry( info, info->split_info + i, j )[ ofs ] = 9999.0f; + for( t = start ; t < ofs; t++ ) + stbir__get_ring_buffer_entry( info, info->split_info + i, j )[ t ] = 9999.0f; } } } @@ -7055,7 +7241,7 @@ static stbir__info * stbir__alloc_internal_mem_and_build_samplers( stbir__sample // is this the first time through loop? if ( info == 0 ) { - alloced_total = (int) ( 15 + (size_t)advance_mem ); + alloced_total = ( 15 + (size_t)advance_mem ); alloced = STBIR_MALLOC( alloced_total, user_data ); if ( alloced == 0 ) return 0; @@ -7065,7 +7251,7 @@ static stbir__info * stbir__alloc_internal_mem_and_build_samplers( stbir__sample } } -static int stbir__perform_resize( stbir__info const * info, int split_start, int split_count ) +static int stbir__perform_resize( stbir__info const * info, int split_start, int split_count ) { stbir__per_split_info * split_info = info->split_info + split_start; @@ -7085,7 +7271,7 @@ static void stbir__update_info_from_resize( stbir__info * info, STBIR_RESIZE * r { static stbir__decode_pixels_func * decode_simple[STBIR_TYPE_HALF_FLOAT-STBIR_TYPE_UINT8_SRGB+1]= { - /* 1ch-4ch */ stbir__decode_uint8_srgb, stbir__decode_uint8_srgb, 0, stbir__decode_float_linear, stbir__decode_half_float_linear, + /* 1ch-4ch */ stbir__decode_uint8_srgb, stbir__decode_uint8_srgb, 0, stbir__decode_float_linear, stbir__decode_half_float_linear, }; static stbir__decode_pixels_func * decode_alphas[STBIRI_AR-STBIRI_RGBA+1][STBIR_TYPE_HALF_FLOAT-STBIR_TYPE_UINT8_SRGB+1]= @@ -7148,7 +7334,7 @@ static void stbir__update_info_from_resize( stbir__info * info, STBIR_RESIZE * r stbir_datatype input_type, output_type; input_type = resize->input_data_type; - output_type = resize->output_data_type; + output_type = resize->output_data_type; info->input_data = resize->input_pixels; info->input_stride_bytes = resize->input_stride_in_bytes; info->output_stride_bytes = resize->output_stride_in_bytes; @@ -7156,7 +7342,7 @@ static void stbir__update_info_from_resize( stbir__info * info, STBIR_RESIZE * r // if we're completely point sampling, then we can turn off SRGB if ( ( info->horizontal.filter_enum == STBIR_FILTER_POINT_SAMPLE ) && ( info->vertical.filter_enum == STBIR_FILTER_POINT_SAMPLE ) ) { - if ( ( ( input_type == STBIR_TYPE_UINT8_SRGB ) || ( input_type == STBIR_TYPE_UINT8_SRGB_ALPHA ) ) && + if ( ( ( input_type == STBIR_TYPE_UINT8_SRGB ) || ( input_type == STBIR_TYPE_UINT8_SRGB_ALPHA ) ) && ( ( output_type == STBIR_TYPE_UINT8_SRGB ) || ( output_type == STBIR_TYPE_UINT8_SRGB_ALPHA ) ) ) { input_type = STBIR_TYPE_UINT8; @@ -7164,7 +7350,7 @@ static void stbir__update_info_from_resize( stbir__info * info, STBIR_RESIZE * r } } - // recalc the output and input strides + // recalc the output and input strides if ( info->input_stride_bytes == 0 ) info->input_stride_bytes = info->channels * info->horizontal.scale_info.input_full_size * stbir__type_size[input_type]; @@ -7172,7 +7358,7 @@ static void stbir__update_info_from_resize( stbir__info * info, STBIR_RESIZE * r info->output_stride_bytes = info->channels * info->horizontal.scale_info.output_sub_size * stbir__type_size[output_type]; // calc offset - info->output_data = ( (char*) resize->output_pixels ) + ( (ptrdiff_t) info->offset_y * (ptrdiff_t) resize->output_stride_in_bytes ) + ( info->offset_x * info->channels * stbir__type_size[output_type] ); + info->output_data = ( (char*) resize->output_pixels ) + ( (size_t) info->offset_y * (size_t) resize->output_stride_in_bytes ) + ( info->offset_x * info->channels * stbir__type_size[output_type] ); info->in_pixels_cb = resize->input_cb; info->user_data = resize->user_data; @@ -7205,7 +7391,7 @@ static void stbir__update_info_from_resize( stbir__info * info, STBIR_RESIZE * r if ( ( output_type == STBIR_TYPE_UINT8 ) || ( output_type == STBIR_TYPE_UINT16 ) ) { int non_scaled = 0; - + // check if we can run unscaled - 0-255.0/0-65535.0 instead of 0-1.0 (which is a tiny bit faster when doing linear 8->8 or 16->16) if ( ( !info->alpha_weight ) && ( !info->alpha_unweight ) ) // don't short circuit when alpha weighting (get everything to 0-1.0 as usual) if ( ( ( input_type == STBIR_TYPE_UINT8 ) && ( output_type == STBIR_TYPE_UINT8 ) ) || ( ( input_type == STBIR_TYPE_UINT16 ) && ( output_type == STBIR_TYPE_UINT16 ) ) ) @@ -7225,16 +7411,16 @@ static void stbir__update_info_from_resize( stbir__info * info, STBIR_RESIZE * r } info->input_type = input_type; - info->output_type = output_type; + info->output_type = output_type; info->decode_pixels = decode_pixels; - info->encode_pixels = encode_pixels; + info->encode_pixels = encode_pixels; } static void stbir__clip( int * outx, int * outsubw, int outw, double * u0, double * u1 ) { double per, adj; int over; - + // do left/top edge if ( *outx < 0 ) { @@ -7253,7 +7439,7 @@ static void stbir__clip( int * outx, int * outsubw, int outw, double * u0, doubl *u1 += adj; // decrease u1 *outsubw = outw - *outx; } -} +} // converts a double to a rational that has less than one float bit of error (returns 0 if unable to do so) static int stbir__double_to_rational(double f, stbir_uint32 limit, stbir_uint32 *numer, stbir_uint32 *denom, int limit_denom ) // limit_denom (1) or limit numer (0) @@ -7270,7 +7456,7 @@ static int stbir__double_to_rational(double f, stbir_uint32 limit, stbir_uint32 bot = 1 << 25; // keep refining, but usually stops in a few loops - usually 5 for bad cases - for(;;) + for(;;) { stbir_uint64 est, temp; @@ -7303,13 +7489,13 @@ static int stbir__double_to_rational(double f, stbir_uint32 limit, stbir_uint32 bot = temp; // move remainders - temp = est * denom_estimate + denom_last; - denom_last = denom_estimate; + temp = est * denom_estimate + denom_last; + denom_last = denom_estimate; denom_estimate = temp; // move remainders - temp = est * numer_estimate + numer_last; - numer_last = numer_estimate; + temp = est * numer_estimate + numer_last; + numer_last = numer_estimate; numer_estimate = temp; } @@ -7353,11 +7539,11 @@ static int stbir__calculate_region_transform( stbir__scale_info * scale_info, in output_s = ( (double)output_sub_range) / output_range; - // figure out the scaling to use - ratio = output_s / input_s; + // figure out the scaling to use + ratio = output_s / input_s; // save scale before clipping - scale = ( output_range / input_range ) * ratio; + scale = ( output_range / input_range ) * ratio; scale_info->scale = (float)scale; scale_info->inv_scale = (float)( 1.0 / scale ); @@ -7368,11 +7554,11 @@ static int stbir__calculate_region_transform( stbir__scale_info * scale_info, in input_s = input_s1 - input_s0; // after clipping do we have zero input area? - if ( input_s <= stbir__small_float ) + if ( input_s <= stbir__small_float ) return 0; - // calculate and store the starting source offsets in output pixel space - scale_info->pixel_shift = (float) ( input_s0 * ratio * output_range ); + // calculate and store the starting source offsets in output pixel space + scale_info->pixel_shift = (float) ( input_s0 * ratio * output_range ); scale_info->scale_is_rational = stbir__double_to_rational( scale, ( scale <= 1.0 ) ? output_full_range : input_full_range, &scale_info->scale_numerator, &scale_info->scale_denominator, ( scale >= 1.0 ) ); @@ -7389,7 +7575,6 @@ static void stbir__init_and_set_layout( STBIR_RESIZE * resize, stbir_pixel_layou resize->output_cb = 0; resize->user_data = resize; resize->samplers = 0; - resize->needs_rebuild = 1; resize->called_alloc = 0; resize->horizontal_filter = STBIR_FILTER_DEFAULT; resize->horizontal_filter_kernel = 0; resize->horizontal_filter_support = 0; @@ -7403,9 +7588,10 @@ static void stbir__init_and_set_layout( STBIR_RESIZE * resize, stbir_pixel_layou resize->output_data_type = data_type; resize->input_pixel_layout_public = pixel_layout; resize->output_pixel_layout_public = pixel_layout; + resize->needs_rebuild = 1; } -STBIRDEF void stbir_resize_init( STBIR_RESIZE * resize, +STBIRDEF void stbir_resize_init( STBIR_RESIZE * resize, const void *input_pixels, int input_w, int input_h, int input_stride_in_bytes, // stride can be zero void *output_pixels, int output_w, int output_h, int output_stride_in_bytes, // stride can be zero stbir_pixel_layout pixel_layout, stbir_datatype data_type ) @@ -7428,17 +7614,27 @@ STBIRDEF void stbir_set_datatypes( STBIR_RESIZE * resize, stbir_datatype input_t { resize->input_data_type = input_type; resize->output_data_type = output_type; + if ( ( resize->samplers ) && ( !resize->needs_rebuild ) ) + stbir__update_info_from_resize( resize->samplers, resize ); } STBIRDEF void stbir_set_pixel_callbacks( STBIR_RESIZE * resize, stbir_input_callback * input_cb, stbir_output_callback * output_cb ) // no callbacks by default { resize->input_cb = input_cb; resize->output_cb = output_cb; + + if ( ( resize->samplers ) && ( !resize->needs_rebuild ) ) + { + resize->samplers->in_pixels_cb = input_cb; + resize->samplers->out_pixels_cb = output_cb; + } } STBIRDEF void stbir_set_user_data( STBIR_RESIZE * resize, void * user_data ) // pass back STBIR_RESIZE* by default { resize->user_data = user_data; + if ( ( resize->samplers ) && ( !resize->needs_rebuild ) ) + resize->samplers->user_data = user_data; } STBIRDEF void stbir_set_buffer_ptrs( STBIR_RESIZE * resize, const void * input_pixels, int input_stride_in_bytes, void * output_pixels, int output_stride_in_bytes ) @@ -7447,6 +7643,8 @@ STBIRDEF void stbir_set_buffer_ptrs( STBIR_RESIZE * resize, const void * input_p resize->input_stride_in_bytes = input_stride_in_bytes; resize->output_pixels = output_pixels; resize->output_stride_in_bytes = output_stride_in_bytes; + if ( ( resize->samplers ) && ( !resize->needs_rebuild ) ) + stbir__update_info_from_resize( resize->samplers, resize ); } @@ -7549,7 +7747,7 @@ STBIRDEF int stbir_set_pixel_subrect( STBIR_RESIZE * resize, int subx, int suby, return 1; } -static int stbir__perform_build( STBIR_RESIZE * resize, int splits ) +static int stbir__perform_build( STBIR_RESIZE * resize, int splits ) { stbir__contributors conservative = { 0, 0 }; stbir__sampler horizontal, vertical; @@ -7563,13 +7761,13 @@ static int stbir__perform_build( STBIR_RESIZE * resize, int splits ) // have we already built the samplers? if ( resize->samplers ) return 0; - + #define STBIR_RETURN_ERROR_AND_ASSERT( exp ) STBIR_ASSERT( !(exp) ); if (exp) return 0; STBIR_RETURN_ERROR_AND_ASSERT( (unsigned)resize->horizontal_filter >= STBIR_FILTER_OTHER) STBIR_RETURN_ERROR_AND_ASSERT( (unsigned)resize->vertical_filter >= STBIR_FILTER_OTHER) #undef STBIR_RETURN_ERROR_AND_ASSERT - if ( splits <= 0 ) + if ( splits <= 0 ) return 0; STBIR_PROFILE_BUILD_FIRST_START( build ); @@ -7593,9 +7791,9 @@ static int stbir__perform_build( STBIR_RESIZE * resize, int splits ) stbir__get_conservative_extents( &horizontal, &conservative, resize->user_data ); stbir__set_sampler(&vertical, resize->vertical_filter, resize->horizontal_filter_kernel, resize->vertical_filter_support, resize->vertical_edge, &vertical.scale_info, 0, resize->user_data ); - if ( ( vertical.scale_info.output_sub_size / splits ) < 4 ) // each split should be a minimum of 4 scanlines (handwavey choice) + if ( ( vertical.scale_info.output_sub_size / splits ) < STBIR_FORCE_MINIMUM_SCANLINES_FOR_SPLITS ) // each split should be a minimum of 4 scanlines (handwavey choice) { - splits = vertical.scale_info.output_sub_size / 4; + splits = vertical.scale_info.output_sub_size / STBIR_FORCE_MINIMUM_SCANLINES_FOR_SPLITS; if ( splits == 0 ) splits = 1; } @@ -7603,7 +7801,7 @@ static int stbir__perform_build( STBIR_RESIZE * resize, int splits ) out_info = stbir__alloc_internal_mem_and_build_samplers( &horizontal, &vertical, &conservative, resize->input_pixel_layout_public, resize->output_pixel_layout_public, splits, new_output_subx, new_output_suby, resize->fast_alpha, resize->user_data STBIR_ONLY_PROFILE_BUILD_SET_INFO ); STBIR_PROFILE_BUILD_END( alloc ); STBIR_PROFILE_BUILD_END( build ); - + if ( out_info ) { resize->splits = splits; @@ -7612,6 +7810,10 @@ static int stbir__perform_build( STBIR_RESIZE * resize, int splits ) #ifdef STBIR_PROFILE STBIR_MEMCPY( &out_info->profile, &profile_infod.profile, sizeof( out_info->profile ) ); #endif + + // update anything that can be changed without recalcing samplers + stbir__update_info_from_resize( out_info, resize ); + return splits; } @@ -7640,7 +7842,7 @@ STBIRDEF int stbir_build_samplers_with_splits( STBIR_RESIZE * resize, int splits } STBIR_PROFILE_BUILD_CLEAR( resize->samplers ); - + return 1; } @@ -7652,7 +7854,7 @@ STBIRDEF int stbir_build_samplers( STBIR_RESIZE * resize ) STBIRDEF int stbir_resize_extended( STBIR_RESIZE * resize ) { int result; - + if ( ( resize->samplers == 0 ) || ( resize->needs_rebuild ) ) { int alloc_state = resize->called_alloc; // remember allocated state @@ -7665,10 +7867,10 @@ STBIRDEF int stbir_resize_extended( STBIR_RESIZE * resize ) if ( !stbir_build_samplers( resize ) ) return 0; - + resize->called_alloc = alloc_state; - // if build_samplers succeeded (above), but there are no samplers set, then + // if build_samplers succeeded (above), but there are no samplers set, then // the area to stretch into was zero pixels, so don't do anything and return // success if ( resize->samplers == 0 ) @@ -7680,10 +7882,6 @@ STBIRDEF int stbir_resize_extended( STBIR_RESIZE * resize ) STBIR_PROFILE_BUILD_CLEAR( resize->samplers ); } - - // update anything that can be changed without recalcing samplers - stbir__update_info_from_resize( resize->samplers, resize ); - // do resize result = stbir__perform_resize( resize->samplers, 0, resize->splits ); @@ -7692,7 +7890,7 @@ STBIRDEF int stbir_resize_extended( STBIR_RESIZE * resize ) { stbir_free_samplers( resize ); resize->samplers = 0; - } + } return result; } @@ -7707,14 +7905,11 @@ STBIRDEF int stbir_resize_extended_split( STBIR_RESIZE * resize, int split_start // you **must** build samplers first when using split resize if ( ( resize->samplers == 0 ) || ( resize->needs_rebuild ) ) - return 0; - + return 0; + if ( ( split_start >= resize->splits ) || ( split_start < 0 ) || ( ( split_start + split_count ) > resize->splits ) || ( split_count <= 0 ) ) return 0; - - // update anything that can be changed without recalcing samplers - stbir__update_info_from_resize( resize->samplers, resize ); - + // do resize return stbir__perform_resize( resize->samplers, split_start, split_count ); } @@ -7735,7 +7930,7 @@ static int stbir__check_output_stuff( void ** ret_ptr, int * ret_pitch, void * o if ( output_stride_in_bytes < pitch ) return 0; - size = output_stride_in_bytes * output_h; + size = (size_t)output_stride_in_bytes * (size_t)output_h; if ( size == 0 ) return 0; @@ -7752,7 +7947,7 @@ static int stbir__check_output_stuff( void ** ret_ptr, int * ret_pitch, void * o *ret_pitch = pitch; } - return 1; + return 1; } @@ -7767,9 +7962,9 @@ STBIRDEF unsigned char * stbir_resize_uint8_linear( const unsigned char *input_p if ( !stbir__check_output_stuff( (void**)&optr, &opitch, output_pixels, sizeof( unsigned char ), output_w, output_h, output_stride_in_bytes, stbir__pixel_layout_convert_public_to_internal[ pixel_layout ] ) ) return 0; - stbir_resize_init( &resize, - input_pixels, input_w, input_h, input_stride_in_bytes, - (optr) ? optr : output_pixels, output_w, output_h, opitch, + stbir_resize_init( &resize, + input_pixels, input_w, input_h, input_stride_in_bytes, + (optr) ? optr : output_pixels, output_w, output_h, opitch, pixel_layout, STBIR_TYPE_UINT8 ); if ( !stbir_resize_extended( &resize ) ) @@ -7793,9 +7988,9 @@ STBIRDEF unsigned char * stbir_resize_uint8_srgb( const unsigned char *input_pix if ( !stbir__check_output_stuff( (void**)&optr, &opitch, output_pixels, sizeof( unsigned char ), output_w, output_h, output_stride_in_bytes, stbir__pixel_layout_convert_public_to_internal[ pixel_layout ] ) ) return 0; - stbir_resize_init( &resize, - input_pixels, input_w, input_h, input_stride_in_bytes, - (optr) ? optr : output_pixels, output_w, output_h, opitch, + stbir_resize_init( &resize, + input_pixels, input_w, input_h, input_stride_in_bytes, + (optr) ? optr : output_pixels, output_w, output_h, opitch, pixel_layout, STBIR_TYPE_UINT8_SRGB ); if ( !stbir_resize_extended( &resize ) ) @@ -7820,9 +8015,9 @@ STBIRDEF float * stbir_resize_float_linear( const float *input_pixels , int inpu if ( !stbir__check_output_stuff( (void**)&optr, &opitch, output_pixels, sizeof( float ), output_w, output_h, output_stride_in_bytes, stbir__pixel_layout_convert_public_to_internal[ pixel_layout ] ) ) return 0; - stbir_resize_init( &resize, - input_pixels, input_w, input_h, input_stride_in_bytes, - (optr) ? optr : output_pixels, output_w, output_h, opitch, + stbir_resize_init( &resize, + input_pixels, input_w, input_h, input_stride_in_bytes, + (optr) ? optr : output_pixels, output_w, output_h, opitch, pixel_layout, STBIR_TYPE_FLOAT ); if ( !stbir_resize_extended( &resize ) ) @@ -7838,7 +8033,7 @@ STBIRDEF float * stbir_resize_float_linear( const float *input_pixels , int inpu STBIRDEF void * stbir_resize( const void *input_pixels , int input_w , int input_h, int input_stride_in_bytes, void *output_pixels, int output_w, int output_h, int output_stride_in_bytes, - stbir_pixel_layout pixel_layout, stbir_datatype data_type, + stbir_pixel_layout pixel_layout, stbir_datatype data_type, stbir_edge edge, stbir_filter filter ) { STBIR_RESIZE resize; @@ -7848,9 +8043,9 @@ STBIRDEF void * stbir_resize( const void *input_pixels , int input_w , int input if ( !stbir__check_output_stuff( (void**)&optr, &opitch, output_pixels, stbir__type_size[data_type], output_w, output_h, output_stride_in_bytes, stbir__pixel_layout_convert_public_to_internal[ pixel_layout ] ) ) return 0; - stbir_resize_init( &resize, - input_pixels, input_w, input_h, input_stride_in_bytes, - (optr) ? optr : output_pixels, output_w, output_h, output_stride_in_bytes, + stbir_resize_init( &resize, + input_pixels, input_w, input_h, input_stride_in_bytes, + (optr) ? optr : output_pixels, output_w, output_h, output_stride_in_bytes, pixel_layout, data_type ); resize.horizontal_edge = edge; @@ -7958,7 +8153,7 @@ STBIRDEF void stbir_resize_extended_profile_info( STBIR_PROFILE_INFO * info, STB #else // STB_IMAGE_RESIZE_HORIZONTALS&STB_IMAGE_RESIZE_DO_VERTICALS // we reinclude the header file to define all the horizontal functions -// specializing each function for the number of coeffs is 20-40% faster *OVERALL* +// specializing each function for the number of coeffs is 20-40% faster *OVERALL* // by including the header file again this way, we can still debug the functions @@ -7991,16 +8186,16 @@ STBIRDEF void stbir_resize_extended_profile_info( STBIR_PROFILE_INFO * info, STB #define stbir__encode_order2 2 #define stbir__encode_order3 3 #define stbir__decode_simdf8_flip(reg) -#define stbir__decode_simdf4_flip(reg) +#define stbir__decode_simdf4_flip(reg) #define stbir__encode_simdf8_unflip(reg) -#define stbir__encode_simdf4_unflip(reg) +#define stbir__encode_simdf4_unflip(reg) #endif #ifdef STBIR_SIMD8 #define stbir__encode_simdfX_unflip stbir__encode_simdf8_unflip #else #define stbir__encode_simdfX_unflip stbir__encode_simdf4_unflip -#endif +#endif static void STBIR__CODER_NAME( stbir__decode_uint8_linear_scaled )( float * decodep, int width_times_channels, void const * inputp ) { @@ -8013,6 +8208,7 @@ static void STBIR__CODER_NAME( stbir__decode_uint8_linear_scaled )( float * deco if ( width_times_channels >= 16 ) { decode_end -= 16; + STBIR_NO_UNROLL_LOOP_START_INF_FOR for(;;) { #ifdef STBIR_SIMD8 @@ -8054,7 +8250,7 @@ static void STBIR__CODER_NAME( stbir__decode_uint8_linear_scaled )( float * deco #endif decode += 16; input += 16; - if ( decode <= decode_end ) + if ( decode <= decode_end ) continue; if ( decode == ( decode_end + 16 ) ) break; @@ -8068,6 +8264,7 @@ static void STBIR__CODER_NAME( stbir__decode_uint8_linear_scaled )( float * deco // try to do blocks of 4 when you can #if stbir__coder_min_num != 3 // doesn't divide cleanly by four decode += 4; + STBIR_SIMD_NO_UNROLL_LOOP_START while( decode <= decode_end ) { STBIR_SIMD_NO_UNROLL(decode); @@ -8083,6 +8280,7 @@ static void STBIR__CODER_NAME( stbir__decode_uint8_linear_scaled )( float * deco // do the remnants #if stbir__coder_min_num < 4 + STBIR_NO_UNROLL_LOOP_START while( decode < decode_end ) { STBIR_NO_UNROLL(decode); @@ -8109,6 +8307,7 @@ static void STBIR__CODER_NAME( stbir__encode_uint8_linear_scaled )( void * outpu { float const * end_encode_m8 = encode + width_times_channels - stbir__simdfX_float_count*2; end_output -= stbir__simdfX_float_count*2; + STBIR_NO_UNROLL_LOOP_START_INF_FOR for(;;) { stbir__simdfX e0, e1; @@ -8119,15 +8318,15 @@ static void STBIR__CODER_NAME( stbir__encode_uint8_linear_scaled )( void * outpu stbir__encode_simdfX_unflip( e0 ); stbir__encode_simdfX_unflip( e1 ); #ifdef STBIR_SIMD8 - stbir__simdf8_pack_to_16bytes( i, e0, e1 ); + stbir__simdf8_pack_to_16bytes( i, e0, e1 ); stbir__simdi_store( output, i ); #else - stbir__simdf_pack_to_8bytes( i, e0, e1 ); + stbir__simdf_pack_to_8bytes( i, e0, e1 ); stbir__simdi_store2( output, i ); #endif encode += stbir__simdfX_float_count*2; output += stbir__simdfX_float_count*2; - if ( output <= end_output ) + if ( output <= end_output ) continue; if ( output == ( end_output + stbir__simdfX_float_count*2 ) ) break; @@ -8140,6 +8339,7 @@ static void STBIR__CODER_NAME( stbir__encode_uint8_linear_scaled )( void * outpu // try to do blocks of 4 when you can #if stbir__coder_min_num != 3 // doesn't divide cleanly by four output += 4; + STBIR_NO_UNROLL_LOOP_START while( output <= end_output ) { stbir__simdf e0; @@ -8158,9 +8358,10 @@ static void STBIR__CODER_NAME( stbir__encode_uint8_linear_scaled )( void * outpu // do the remnants #if stbir__coder_min_num < 4 + STBIR_NO_UNROLL_LOOP_START while( output < end_output ) { - stbir__simdf e0; + stbir__simdf e0; STBIR_NO_UNROLL(encode); stbir__simdf_madd1_mem( e0, STBIR__CONSTF(STBIR_simd_point5), STBIR__CONSTF(STBIR_max_uint8_as_float), encode+stbir__encode_order0 ); output[0] = stbir__simdf_convert_float_to_uint8( e0 ); #if stbir__coder_min_num >= 2 @@ -8173,7 +8374,7 @@ static void STBIR__CODER_NAME( stbir__encode_uint8_linear_scaled )( void * outpu encode += stbir__coder_min_num; } #endif - + #else // try to do blocks of 4 when you can @@ -8194,6 +8395,7 @@ static void STBIR__CODER_NAME( stbir__encode_uint8_linear_scaled )( void * outpu // do the remnants #if stbir__coder_min_num < 4 + STBIR_NO_UNROLL_LOOP_START while( output < end_output ) { float f; @@ -8223,6 +8425,7 @@ static void STBIR__CODER_NAME(stbir__decode_uint8_linear)( float * decodep, int if ( width_times_channels >= 16 ) { decode_end -= 16; + STBIR_NO_UNROLL_LOOP_START_INF_FOR for(;;) { #ifdef STBIR_SIMD8 @@ -8258,7 +8461,7 @@ static void STBIR__CODER_NAME(stbir__decode_uint8_linear)( float * decodep, int #endif decode += 16; input += 16; - if ( decode <= decode_end ) + if ( decode <= decode_end ) continue; if ( decode == ( decode_end + 16 ) ) break; @@ -8272,6 +8475,7 @@ static void STBIR__CODER_NAME(stbir__decode_uint8_linear)( float * decodep, int // try to do blocks of 4 when you can #if stbir__coder_min_num != 3 // doesn't divide cleanly by four decode += 4; + STBIR_SIMD_NO_UNROLL_LOOP_START while( decode <= decode_end ) { STBIR_SIMD_NO_UNROLL(decode); @@ -8287,6 +8491,7 @@ static void STBIR__CODER_NAME(stbir__decode_uint8_linear)( float * decodep, int // do the remnants #if stbir__coder_min_num < 4 + STBIR_NO_UNROLL_LOOP_START while( decode < decode_end ) { STBIR_NO_UNROLL(decode); @@ -8313,6 +8518,7 @@ static void STBIR__CODER_NAME( stbir__encode_uint8_linear )( void * outputp, int { float const * end_encode_m8 = encode + width_times_channels - stbir__simdfX_float_count*2; end_output -= stbir__simdfX_float_count*2; + STBIR_SIMD_NO_UNROLL_LOOP_START_INF_FOR for(;;) { stbir__simdfX e0, e1; @@ -8323,15 +8529,15 @@ static void STBIR__CODER_NAME( stbir__encode_uint8_linear )( void * outputp, int stbir__encode_simdfX_unflip( e0 ); stbir__encode_simdfX_unflip( e1 ); #ifdef STBIR_SIMD8 - stbir__simdf8_pack_to_16bytes( i, e0, e1 ); + stbir__simdf8_pack_to_16bytes( i, e0, e1 ); stbir__simdi_store( output, i ); #else - stbir__simdf_pack_to_8bytes( i, e0, e1 ); + stbir__simdf_pack_to_8bytes( i, e0, e1 ); stbir__simdi_store2( output, i ); #endif encode += stbir__simdfX_float_count*2; output += stbir__simdfX_float_count*2; - if ( output <= end_output ) + if ( output <= end_output ) continue; if ( output == ( end_output + stbir__simdfX_float_count*2 ) ) break; @@ -8344,6 +8550,7 @@ static void STBIR__CODER_NAME( stbir__encode_uint8_linear )( void * outputp, int // try to do blocks of 4 when you can #if stbir__coder_min_num != 3 // doesn't divide cleanly by four output += 4; + STBIR_NO_UNROLL_LOOP_START while( output <= end_output ) { stbir__simdf e0; @@ -8382,6 +8589,7 @@ static void STBIR__CODER_NAME( stbir__encode_uint8_linear )( void * outputp, int // do the remnants #if stbir__coder_min_num < 4 + STBIR_NO_UNROLL_LOOP_START while( output < end_output ) { float f; @@ -8422,6 +8630,7 @@ static void STBIR__CODER_NAME(stbir__decode_uint8_srgb)( float * decodep, int wi // do the remnants #if stbir__coder_min_num < 4 + STBIR_NO_UNROLL_LOOP_START while( decode < decode_end ) { STBIR_NO_UNROLL(decode); @@ -8441,7 +8650,7 @@ static void STBIR__CODER_NAME(stbir__decode_uint8_srgb)( float * decodep, int wi #define stbir__min_max_shift20( i, f ) \ stbir__simdf_max( f, f, stbir_simdf_casti(STBIR__CONSTI( STBIR_almost_zero )) ); \ stbir__simdf_min( f, f, stbir_simdf_casti(STBIR__CONSTI( STBIR_almost_one )) ); \ - stbir__simdi_32shr( i, stbir_simdi_castf( f ), 20 ); + stbir__simdi_32shr( i, stbir_simdi_castf( f ), 20 ); #define stbir__scale_and_convert( i, f ) \ stbir__simdf_madd( f, STBIR__CONSTF( STBIR_simd_point5 ), STBIR__CONSTF( STBIR_max_uint8_as_float ), f ); \ @@ -8468,7 +8677,7 @@ static void STBIR__CODER_NAME(stbir__decode_uint8_srgb)( float * decodep, int wi temp1.m128i_u32[0] = table[temp1.m128i_i32[0]]; temp1.m128i_u32[1] = table[temp1.m128i_i32[1]]; temp1.m128i_u32[2] = table[temp1.m128i_i32[2]]; temp1.m128i_u32[3] = table[temp1.m128i_i32[3]]; \ v0 = temp0.m128i_i128; \ v1 = temp1.m128i_i128; \ -} +} #define stbir__simdi_table_lookup3( v0,v1,v2, table ) \ { \ @@ -8499,7 +8708,7 @@ static void STBIR__CODER_NAME(stbir__decode_uint8_srgb)( float * decodep, int wi v1 = temp1.m128i_i128; \ v2 = temp2.m128i_i128; \ v3 = temp3.m128i_i128; \ -} +} static void STBIR__CODER_NAME( stbir__encode_uint8_srgb )( void * outputp, int width_times_channels, float const * encode ) { @@ -8507,16 +8716,16 @@ static void STBIR__CODER_NAME( stbir__encode_uint8_srgb )( void * outputp, int w unsigned char * end_output = ( (unsigned char*) output ) + width_times_channels; #ifdef STBIR_SIMD - stbir_uint32 const * to_srgb = fp32_to_srgb8_tab4 - (127-13)*8; if ( width_times_channels >= 16 ) { float const * end_encode_m16 = encode + width_times_channels - 16; end_output -= 16; + STBIR_SIMD_NO_UNROLL_LOOP_START_INF_FOR for(;;) { stbir__simdf f0, f1, f2, f3; - stbir__simdi i0, i1, i2, i3; + stbir__simdi i0, i1, i2, i3; STBIR_SIMD_NO_UNROLL(encode); stbir__simdf_load4_transposed( f0, f1, f2, f3, encode ); @@ -8525,9 +8734,9 @@ static void STBIR__CODER_NAME( stbir__encode_uint8_srgb )( void * outputp, int w stbir__min_max_shift20( i1, f1 ); stbir__min_max_shift20( i2, f2 ); stbir__min_max_shift20( i3, f3 ); - - stbir__simdi_table_lookup4( i0, i1, i2, i3, to_srgb ); - + + stbir__simdi_table_lookup4( i0, i1, i2, i3, ( fp32_to_srgb8_tab4 - (127-13)*8 ) ); + stbir__linear_to_srgb_finish( i0, f0 ); stbir__linear_to_srgb_finish( i1, f1 ); stbir__linear_to_srgb_finish( i2, f2 ); @@ -8537,7 +8746,7 @@ static void STBIR__CODER_NAME( stbir__encode_uint8_srgb )( void * outputp, int w encode += 16; output += 16; - if ( output <= end_output ) + if ( output <= end_output ) continue; if ( output == ( end_output + 16 ) ) break; @@ -8551,6 +8760,7 @@ static void STBIR__CODER_NAME( stbir__encode_uint8_srgb )( void * outputp, int w // try to do blocks of 4 when you can #if stbir__coder_min_num != 3 // doesn't divide cleanly by four output += 4; + STBIR_SIMD_NO_UNROLL_LOOP_START while ( output <= end_output ) { STBIR_SIMD_NO_UNROLL(encode); @@ -8568,7 +8778,8 @@ static void STBIR__CODER_NAME( stbir__encode_uint8_srgb )( void * outputp, int w // do the remnants #if stbir__coder_min_num < 4 - while( output < end_output ) + STBIR_NO_UNROLL_LOOP_START + while( output < end_output ) { STBIR_NO_UNROLL(encode); output[0] = stbir__linear_to_srgb_uchar( encode[stbir__encode_order0] ); @@ -8608,12 +8819,12 @@ static void STBIR__CODER_NAME( stbir__encode_uint8_srgb4_linearalpha )( void * o unsigned char * end_output = ( (unsigned char*) output ) + width_times_channels; #ifdef STBIR_SIMD - stbir_uint32 const * to_srgb = fp32_to_srgb8_tab4 - (127-13)*8; if ( width_times_channels >= 16 ) { float const * end_encode_m16 = encode + width_times_channels - 16; end_output -= 16; + STBIR_SIMD_NO_UNROLL_LOOP_START_INF_FOR for(;;) { stbir__simdf f0, f1, f2, f3; @@ -8625,10 +8836,10 @@ static void STBIR__CODER_NAME( stbir__encode_uint8_srgb4_linearalpha )( void * o stbir__min_max_shift20( i0, f0 ); stbir__min_max_shift20( i1, f1 ); stbir__min_max_shift20( i2, f2 ); - stbir__scale_and_convert( i3, f3 ); - - stbir__simdi_table_lookup3( i0, i1, i2, to_srgb ); - + stbir__scale_and_convert( i3, f3 ); + + stbir__simdi_table_lookup3( i0, i1, i2, ( fp32_to_srgb8_tab4 - (127-13)*8 ) ); + stbir__linear_to_srgb_finish( i0, f0 ); stbir__linear_to_srgb_finish( i1, f1 ); stbir__linear_to_srgb_finish( i2, f2 ); @@ -8638,7 +8849,7 @@ static void STBIR__CODER_NAME( stbir__encode_uint8_srgb4_linearalpha )( void * o output += 16; encode += 16; - if ( output <= end_output ) + if ( output <= end_output ) continue; if ( output == ( end_output + 16 ) ) break; @@ -8649,9 +8860,10 @@ static void STBIR__CODER_NAME( stbir__encode_uint8_srgb4_linearalpha )( void * o } #endif + STBIR_SIMD_NO_UNROLL_LOOP_START do { float f; - STBIR_SIMD_NO_UNROLL(encode); + STBIR_SIMD_NO_UNROLL(encode); output[stbir__decode_order0] = stbir__linear_to_srgb_uchar( encode[0] ); output[stbir__decode_order1] = stbir__linear_to_srgb_uchar( encode[1] ); @@ -8686,7 +8898,7 @@ static void STBIR__CODER_NAME(stbir__decode_uint8_srgb2_linearalpha)( float * de decode += 4; } decode -= 4; - if( decode < decode_end ) + if( decode < decode_end ) { decode[0] = stbir__srgb_uchar_to_linear_float[ stbir__decode_order0 ]; decode[1] = ( (float) input[stbir__decode_order1] ) * stbir__max_uint8_as_float_inverted; @@ -8699,16 +8911,16 @@ static void STBIR__CODER_NAME( stbir__encode_uint8_srgb2_linearalpha )( void * o unsigned char * end_output = ( (unsigned char*) output ) + width_times_channels; #ifdef STBIR_SIMD - stbir_uint32 const * to_srgb = fp32_to_srgb8_tab4 - (127-13)*8; if ( width_times_channels >= 16 ) { float const * end_encode_m16 = encode + width_times_channels - 16; end_output -= 16; + STBIR_SIMD_NO_UNROLL_LOOP_START_INF_FOR for(;;) { stbir__simdf f0, f1, f2, f3; - stbir__simdi i0, i1, i2, i3; + stbir__simdi i0, i1, i2, i3; STBIR_SIMD_NO_UNROLL(encode); stbir__simdf_load4_transposed( f0, f1, f2, f3, encode ); @@ -8717,9 +8929,9 @@ static void STBIR__CODER_NAME( stbir__encode_uint8_srgb2_linearalpha )( void * o stbir__scale_and_convert( i1, f1 ); stbir__min_max_shift20( i2, f2 ); stbir__scale_and_convert( i3, f3 ); - - stbir__simdi_table_lookup2( i0, i2, to_srgb ); - + + stbir__simdi_table_lookup2( i0, i2, ( fp32_to_srgb8_tab4 - (127-13)*8 ) ); + stbir__linear_to_srgb_finish( i0, f0 ); stbir__linear_to_srgb_finish( i2, f2 ); @@ -8727,7 +8939,7 @@ static void STBIR__CODER_NAME( stbir__encode_uint8_srgb2_linearalpha )( void * o output += 16; encode += 16; - if ( output <= end_output ) + if ( output <= end_output ) continue; if ( output == ( end_output + 16 ) ) break; @@ -8738,6 +8950,7 @@ static void STBIR__CODER_NAME( stbir__encode_uint8_srgb2_linearalpha )( void * o } #endif + STBIR_SIMD_NO_UNROLL_LOOP_START do { float f; STBIR_SIMD_NO_UNROLL(encode); @@ -8766,6 +8979,7 @@ static void STBIR__CODER_NAME(stbir__decode_uint16_linear_scaled)( float * decod if ( width_times_channels >= 8 ) { decode_end -= 8; + STBIR_NO_UNROLL_LOOP_START_INF_FOR for(;;) { #ifdef STBIR_SIMD8 @@ -8793,9 +9007,9 @@ static void STBIR__CODER_NAME(stbir__decode_uint16_linear_scaled)( float * decod stbir__simdf_store( decode + 0, of0 ); stbir__simdf_store( decode + 4, of1 ); #endif - decode += 8; + decode += 8; input += 8; - if ( decode <= decode_end ) + if ( decode <= decode_end ) continue; if ( decode == ( decode_end + 8 ) ) break; @@ -8809,6 +9023,7 @@ static void STBIR__CODER_NAME(stbir__decode_uint16_linear_scaled)( float * decod // try to do blocks of 4 when you can #if stbir__coder_min_num != 3 // doesn't divide cleanly by four decode += 4; + STBIR_SIMD_NO_UNROLL_LOOP_START while( decode <= decode_end ) { STBIR_SIMD_NO_UNROLL(decode); @@ -8824,6 +9039,7 @@ static void STBIR__CODER_NAME(stbir__decode_uint16_linear_scaled)( float * decod // do the remnants #if stbir__coder_min_num < 4 + STBIR_NO_UNROLL_LOOP_START while( decode < decode_end ) { STBIR_NO_UNROLL(decode); @@ -8852,6 +9068,7 @@ static void STBIR__CODER_NAME(stbir__encode_uint16_linear_scaled)( void * output { float const * end_encode_m8 = encode + width_times_channels - stbir__simdfX_float_count*2; end_output -= stbir__simdfX_float_count*2; + STBIR_SIMD_NO_UNROLL_LOOP_START_INF_FOR for(;;) { stbir__simdfX e0, e1; @@ -8865,7 +9082,7 @@ static void STBIR__CODER_NAME(stbir__encode_uint16_linear_scaled)( void * output stbir__simdiX_store( output, i ); encode += stbir__simdfX_float_count*2; output += stbir__simdfX_float_count*2; - if ( output <= end_output ) + if ( output <= end_output ) continue; if ( output == ( end_output + stbir__simdfX_float_count*2 ) ) break; @@ -8879,6 +9096,7 @@ static void STBIR__CODER_NAME(stbir__encode_uint16_linear_scaled)( void * output // try to do blocks of 4 when you can #if stbir__coder_min_num != 3 // doesn't divide cleanly by four output += 4; + STBIR_NO_UNROLL_LOOP_START while( output <= end_output ) { stbir__simdf e; @@ -8897,6 +9115,7 @@ static void STBIR__CODER_NAME(stbir__encode_uint16_linear_scaled)( void * output // do the remnants #if stbir__coder_min_num < 4 + STBIR_NO_UNROLL_LOOP_START while( output < end_output ) { stbir__simdf e; @@ -8912,12 +9131,13 @@ static void STBIR__CODER_NAME(stbir__encode_uint16_linear_scaled)( void * output encode += stbir__coder_min_num; } #endif - + #else // try to do blocks of 4 when you can #if stbir__coder_min_num != 3 // doesn't divide cleanly by four output += 4; + STBIR_SIMD_NO_UNROLL_LOOP_START while( output <= end_output ) { float f; @@ -8934,6 +9154,7 @@ static void STBIR__CODER_NAME(stbir__encode_uint16_linear_scaled)( void * output // do the remnants #if stbir__coder_min_num < 4 + STBIR_NO_UNROLL_LOOP_START while( output < end_output ) { float f; @@ -8963,6 +9184,7 @@ static void STBIR__CODER_NAME(stbir__decode_uint16_linear)( float * decodep, int if ( width_times_channels >= 8 ) { decode_end -= 8; + STBIR_NO_UNROLL_LOOP_START_INF_FOR for(;;) { #ifdef STBIR_SIMD8 @@ -8989,7 +9211,7 @@ static void STBIR__CODER_NAME(stbir__decode_uint16_linear)( float * decodep, int #endif decode += 8; input += 8; - if ( decode <= decode_end ) + if ( decode <= decode_end ) continue; if ( decode == ( decode_end + 8 ) ) break; @@ -9003,6 +9225,7 @@ static void STBIR__CODER_NAME(stbir__decode_uint16_linear)( float * decodep, int // try to do blocks of 4 when you can #if stbir__coder_min_num != 3 // doesn't divide cleanly by four decode += 4; + STBIR_SIMD_NO_UNROLL_LOOP_START while( decode <= decode_end ) { STBIR_SIMD_NO_UNROLL(decode); @@ -9018,6 +9241,7 @@ static void STBIR__CODER_NAME(stbir__decode_uint16_linear)( float * decodep, int // do the remnants #if stbir__coder_min_num < 4 + STBIR_NO_UNROLL_LOOP_START while( decode < decode_end ) { STBIR_NO_UNROLL(decode); @@ -9045,6 +9269,7 @@ static void STBIR__CODER_NAME(stbir__encode_uint16_linear)( void * outputp, int { float const * end_encode_m8 = encode + width_times_channels - stbir__simdfX_float_count*2; end_output -= stbir__simdfX_float_count*2; + STBIR_SIMD_NO_UNROLL_LOOP_START_INF_FOR for(;;) { stbir__simdfX e0, e1; @@ -9058,7 +9283,7 @@ static void STBIR__CODER_NAME(stbir__encode_uint16_linear)( void * outputp, int stbir__simdiX_store( output, i ); encode += stbir__simdfX_float_count*2; output += stbir__simdfX_float_count*2; - if ( output <= end_output ) + if ( output <= end_output ) continue; if ( output == ( end_output + stbir__simdfX_float_count*2 ) ) break; @@ -9072,6 +9297,7 @@ static void STBIR__CODER_NAME(stbir__encode_uint16_linear)( void * outputp, int // try to do blocks of 4 when you can #if stbir__coder_min_num != 3 // doesn't divide cleanly by four output += 4; + STBIR_NO_UNROLL_LOOP_START while( output <= end_output ) { stbir__simdf e; @@ -9093,6 +9319,7 @@ static void STBIR__CODER_NAME(stbir__encode_uint16_linear)( void * outputp, int // try to do blocks of 4 when you can #if stbir__coder_min_num != 3 // doesn't divide cleanly by four output += 4; + STBIR_SIMD_NO_UNROLL_LOOP_START while( output <= end_output ) { float f; @@ -9111,6 +9338,7 @@ static void STBIR__CODER_NAME(stbir__encode_uint16_linear)( void * outputp, int // do the remnants #if stbir__coder_min_num < 4 + STBIR_NO_UNROLL_LOOP_START while( output < end_output ) { float f; @@ -9139,6 +9367,7 @@ static void STBIR__CODER_NAME(stbir__decode_half_float_linear)( float * decodep, { stbir__FP16 const * end_input_m8 = input + width_times_channels - 8; decode_end -= 8; + STBIR_NO_UNROLL_LOOP_START_INF_FOR for(;;) { STBIR_NO_UNROLL(decode); @@ -9166,7 +9395,7 @@ static void STBIR__CODER_NAME(stbir__decode_half_float_linear)( float * decodep, #endif decode += 8; input += 8; - if ( decode <= decode_end ) + if ( decode <= decode_end ) continue; if ( decode == ( decode_end + 8 ) ) break; @@ -9180,6 +9409,7 @@ static void STBIR__CODER_NAME(stbir__decode_half_float_linear)( float * decodep, // try to do blocks of 4 when you can #if stbir__coder_min_num != 3 // doesn't divide cleanly by four decode += 4; + STBIR_SIMD_NO_UNROLL_LOOP_START while( decode <= decode_end ) { STBIR_SIMD_NO_UNROLL(decode); @@ -9195,6 +9425,7 @@ static void STBIR__CODER_NAME(stbir__decode_half_float_linear)( float * decodep, // do the remnants #if stbir__coder_min_num < 4 + STBIR_NO_UNROLL_LOOP_START while( decode < decode_end ) { STBIR_NO_UNROLL(decode); @@ -9221,6 +9452,7 @@ static void STBIR__CODER_NAME( stbir__encode_half_float_linear )( void * outputp { float const * end_encode_m8 = encode + width_times_channels - 8; end_output -= 8; + STBIR_SIMD_NO_UNROLL_LOOP_START_INF_FOR for(;;) { STBIR_SIMD_NO_UNROLL(encode); @@ -9247,7 +9479,7 @@ static void STBIR__CODER_NAME( stbir__encode_half_float_linear )( void * outputp #endif encode += 8; output += 8; - if ( output <= end_output ) + if ( output <= end_output ) continue; if ( output == ( end_output + 8 ) ) break; @@ -9261,6 +9493,7 @@ static void STBIR__CODER_NAME( stbir__encode_half_float_linear )( void * outputp // try to do blocks of 4 when you can #if stbir__coder_min_num != 3 // doesn't divide cleanly by four output += 4; + STBIR_SIMD_NO_UNROLL_LOOP_START while( output <= end_output ) { STBIR_SIMD_NO_UNROLL(output); @@ -9276,6 +9509,7 @@ static void STBIR__CODER_NAME( stbir__encode_half_float_linear )( void * outputp // do the remnants #if stbir__coder_min_num < 4 + STBIR_NO_UNROLL_LOOP_START while( output < end_output ) { STBIR_NO_UNROLL(output); @@ -9304,6 +9538,7 @@ static void STBIR__CODER_NAME(stbir__decode_float_linear)( float * decodep, int { float const * end_input_m16 = input + width_times_channels - 16; decode_end -= 16; + STBIR_NO_UNROLL_LOOP_START_INF_FOR for(;;) { STBIR_NO_UNROLL(decode); @@ -9338,7 +9573,7 @@ static void STBIR__CODER_NAME(stbir__decode_float_linear)( float * decodep, int #endif decode += 16; input += 16; - if ( decode <= decode_end ) + if ( decode <= decode_end ) continue; if ( decode == ( decode_end + 16 ) ) break; @@ -9352,6 +9587,7 @@ static void STBIR__CODER_NAME(stbir__decode_float_linear)( float * decodep, int // try to do blocks of 4 when you can #if stbir__coder_min_num != 3 // doesn't divide cleanly by four decode += 4; + STBIR_SIMD_NO_UNROLL_LOOP_START while( decode <= decode_end ) { STBIR_SIMD_NO_UNROLL(decode); @@ -9367,6 +9603,7 @@ static void STBIR__CODER_NAME(stbir__decode_float_linear)( float * decodep, int // do the remnants #if stbir__coder_min_num < 4 + STBIR_NO_UNROLL_LOOP_START while( decode < decode_end ) { STBIR_NO_UNROLL(decode); @@ -9383,10 +9620,10 @@ static void STBIR__CODER_NAME(stbir__decode_float_linear)( float * decodep, int #endif #else - + if ( (void*)decodep != inputp ) STBIR_MEMCPY( decodep, inputp, width_times_channels * sizeof( float ) ); - + #endif } @@ -9426,6 +9663,7 @@ static void STBIR__CODER_NAME( stbir__encode_float_linear )( void * outputp, int { float const * end_encode_m8 = encode + width_times_channels - ( stbir__simdfX_float_count * 2 ); end_output -= ( stbir__simdfX_float_count * 2 ); + STBIR_SIMD_NO_UNROLL_LOOP_START_INF_FOR for(;;) { stbir__simdfX e0, e1; @@ -9435,18 +9673,18 @@ static void STBIR__CODER_NAME( stbir__encode_float_linear )( void * outputp, int #ifdef STBIR_FLOAT_HIGH_CLAMP stbir__simdfX_min( e0, e0, high_clamp ); stbir__simdfX_min( e1, e1, high_clamp ); -#endif +#endif #ifdef STBIR_FLOAT_LOW_CLAMP stbir__simdfX_max( e0, e0, low_clamp ); stbir__simdfX_max( e1, e1, low_clamp ); -#endif +#endif stbir__encode_simdfX_unflip( e0 ); stbir__encode_simdfX_unflip( e1 ); stbir__simdfX_store( output, e0 ); stbir__simdfX_store( output+stbir__simdfX_float_count, e1 ); encode += stbir__simdfX_float_count * 2; output += stbir__simdfX_float_count * 2; - if ( output < end_output ) + if ( output < end_output ) continue; if ( output == ( end_output + ( stbir__simdfX_float_count * 2 ) ) ) break; @@ -9459,6 +9697,7 @@ static void STBIR__CODER_NAME( stbir__encode_float_linear )( void * outputp, int // try to do blocks of 4 when you can #if stbir__coder_min_num != 3 // doesn't divide cleanly by four output += 4; + STBIR_NO_UNROLL_LOOP_START while( output <= end_output ) { stbir__simdf e0; @@ -9466,10 +9705,10 @@ static void STBIR__CODER_NAME( stbir__encode_float_linear )( void * outputp, int stbir__simdf_load( e0, encode ); #ifdef STBIR_FLOAT_HIGH_CLAMP stbir__simdf_min( e0, e0, high_clamp ); -#endif +#endif #ifdef STBIR_FLOAT_LOW_CLAMP stbir__simdf_max( e0, e0, low_clamp ); -#endif +#endif stbir__encode_simdf4_unflip( e0 ); stbir__simdf_store( output-4, e0 ); output += 4; @@ -9483,6 +9722,7 @@ static void STBIR__CODER_NAME( stbir__encode_float_linear )( void * outputp, int // try to do blocks of 4 when you can #if stbir__coder_min_num != 3 // doesn't divide cleanly by four output += 4; + STBIR_SIMD_NO_UNROLL_LOOP_START while( output <= end_output ) { float e; @@ -9502,6 +9742,7 @@ static void STBIR__CODER_NAME( stbir__encode_float_linear )( void * outputp, int // do the remnants #if stbir__coder_min_num < 4 + STBIR_NO_UNROLL_LOOP_START while( output < end_output ) { float e; @@ -9517,18 +9758,18 @@ static void STBIR__CODER_NAME( stbir__encode_float_linear )( void * outputp, int encode += stbir__coder_min_num; } #endif - + #endif } -#undef stbir__decode_suffix +#undef stbir__decode_suffix #undef stbir__decode_simdf8_flip #undef stbir__decode_simdf4_flip -#undef stbir__decode_order0 +#undef stbir__decode_order0 #undef stbir__decode_order1 #undef stbir__decode_order2 #undef stbir__decode_order3 -#undef stbir__encode_order0 +#undef stbir__encode_order0 #undef stbir__encode_order1 #undef stbir__encode_order2 #undef stbir__encode_order3 @@ -9612,7 +9853,8 @@ static void STBIR_chans( stbir__vertical_scatter_with_,_coeffs)( float ** output stbIF5(stbir__simdfX c5 = stbir__simdf_frepX( c5s ); ) stbIF6(stbir__simdfX c6 = stbir__simdf_frepX( c6s ); ) stbIF7(stbir__simdfX c7 = stbir__simdf_frepX( c7s ); ) - while ( ( (char*)input_end - (char*) input ) >= (16*stbir__simdfX_float_count) ) + STBIR_SIMD_NO_UNROLL_LOOP_START + while ( ( (char*)input_end - (char*) input ) >= (16*stbir__simdfX_float_count) ) { stbir__simdfX o0, o1, o2, o3, r0, r1, r2, r3; STBIR_SIMD_NO_UNROLL(output0); @@ -9621,52 +9863,53 @@ static void STBIR_chans( stbir__vertical_scatter_with_,_coeffs)( float ** output #ifdef STB_IMAGE_RESIZE_VERTICAL_CONTINUE stbIF0( stbir__simdfX_load( o0, output0 ); stbir__simdfX_load( o1, output0+stbir__simdfX_float_count ); stbir__simdfX_load( o2, output0+(2*stbir__simdfX_float_count) ); stbir__simdfX_load( o3, output0+(3*stbir__simdfX_float_count) ); - stbir__simdfX_madd( o0, o0, r0, c0 ); stbir__simdfX_madd( o1, o1, r1, c0 ); stbir__simdfX_madd( o2, o2, r2, c0 ); stbir__simdfX_madd( o3, o3, r3, c0 ); + stbir__simdfX_madd( o0, o0, r0, c0 ); stbir__simdfX_madd( o1, o1, r1, c0 ); stbir__simdfX_madd( o2, o2, r2, c0 ); stbir__simdfX_madd( o3, o3, r3, c0 ); stbir__simdfX_store( output0, o0 ); stbir__simdfX_store( output0+stbir__simdfX_float_count, o1 ); stbir__simdfX_store( output0+(2*stbir__simdfX_float_count), o2 ); stbir__simdfX_store( output0+(3*stbir__simdfX_float_count), o3 ); ) stbIF1( stbir__simdfX_load( o0, output1 ); stbir__simdfX_load( o1, output1+stbir__simdfX_float_count ); stbir__simdfX_load( o2, output1+(2*stbir__simdfX_float_count) ); stbir__simdfX_load( o3, output1+(3*stbir__simdfX_float_count) ); - stbir__simdfX_madd( o0, o0, r0, c1 ); stbir__simdfX_madd( o1, o1, r1, c1 ); stbir__simdfX_madd( o2, o2, r2, c1 ); stbir__simdfX_madd( o3, o3, r3, c1 ); + stbir__simdfX_madd( o0, o0, r0, c1 ); stbir__simdfX_madd( o1, o1, r1, c1 ); stbir__simdfX_madd( o2, o2, r2, c1 ); stbir__simdfX_madd( o3, o3, r3, c1 ); stbir__simdfX_store( output1, o0 ); stbir__simdfX_store( output1+stbir__simdfX_float_count, o1 ); stbir__simdfX_store( output1+(2*stbir__simdfX_float_count), o2 ); stbir__simdfX_store( output1+(3*stbir__simdfX_float_count), o3 ); ) stbIF2( stbir__simdfX_load( o0, output2 ); stbir__simdfX_load( o1, output2+stbir__simdfX_float_count ); stbir__simdfX_load( o2, output2+(2*stbir__simdfX_float_count) ); stbir__simdfX_load( o3, output2+(3*stbir__simdfX_float_count) ); - stbir__simdfX_madd( o0, o0, r0, c2 ); stbir__simdfX_madd( o1, o1, r1, c2 ); stbir__simdfX_madd( o2, o2, r2, c2 ); stbir__simdfX_madd( o3, o3, r3, c2 ); + stbir__simdfX_madd( o0, o0, r0, c2 ); stbir__simdfX_madd( o1, o1, r1, c2 ); stbir__simdfX_madd( o2, o2, r2, c2 ); stbir__simdfX_madd( o3, o3, r3, c2 ); stbir__simdfX_store( output2, o0 ); stbir__simdfX_store( output2+stbir__simdfX_float_count, o1 ); stbir__simdfX_store( output2+(2*stbir__simdfX_float_count), o2 ); stbir__simdfX_store( output2+(3*stbir__simdfX_float_count), o3 ); ) stbIF3( stbir__simdfX_load( o0, output3 ); stbir__simdfX_load( o1, output3+stbir__simdfX_float_count ); stbir__simdfX_load( o2, output3+(2*stbir__simdfX_float_count) ); stbir__simdfX_load( o3, output3+(3*stbir__simdfX_float_count) ); - stbir__simdfX_madd( o0, o0, r0, c3 ); stbir__simdfX_madd( o1, o1, r1, c3 ); stbir__simdfX_madd( o2, o2, r2, c3 ); stbir__simdfX_madd( o3, o3, r3, c3 ); + stbir__simdfX_madd( o0, o0, r0, c3 ); stbir__simdfX_madd( o1, o1, r1, c3 ); stbir__simdfX_madd( o2, o2, r2, c3 ); stbir__simdfX_madd( o3, o3, r3, c3 ); stbir__simdfX_store( output3, o0 ); stbir__simdfX_store( output3+stbir__simdfX_float_count, o1 ); stbir__simdfX_store( output3+(2*stbir__simdfX_float_count), o2 ); stbir__simdfX_store( output3+(3*stbir__simdfX_float_count), o3 ); ) stbIF4( stbir__simdfX_load( o0, output4 ); stbir__simdfX_load( o1, output4+stbir__simdfX_float_count ); stbir__simdfX_load( o2, output4+(2*stbir__simdfX_float_count) ); stbir__simdfX_load( o3, output4+(3*stbir__simdfX_float_count) ); - stbir__simdfX_madd( o0, o0, r0, c4 ); stbir__simdfX_madd( o1, o1, r1, c4 ); stbir__simdfX_madd( o2, o2, r2, c4 ); stbir__simdfX_madd( o3, o3, r3, c4 ); + stbir__simdfX_madd( o0, o0, r0, c4 ); stbir__simdfX_madd( o1, o1, r1, c4 ); stbir__simdfX_madd( o2, o2, r2, c4 ); stbir__simdfX_madd( o3, o3, r3, c4 ); stbir__simdfX_store( output4, o0 ); stbir__simdfX_store( output4+stbir__simdfX_float_count, o1 ); stbir__simdfX_store( output4+(2*stbir__simdfX_float_count), o2 ); stbir__simdfX_store( output4+(3*stbir__simdfX_float_count), o3 ); ) stbIF5( stbir__simdfX_load( o0, output5 ); stbir__simdfX_load( o1, output5+stbir__simdfX_float_count ); stbir__simdfX_load( o2, output5+(2*stbir__simdfX_float_count)); stbir__simdfX_load( o3, output5+(3*stbir__simdfX_float_count) ); - stbir__simdfX_madd( o0, o0, r0, c5 ); stbir__simdfX_madd( o1, o1, r1, c5 ); stbir__simdfX_madd( o2, o2, r2, c5 ); stbir__simdfX_madd( o3, o3, r3, c5 ); + stbir__simdfX_madd( o0, o0, r0, c5 ); stbir__simdfX_madd( o1, o1, r1, c5 ); stbir__simdfX_madd( o2, o2, r2, c5 ); stbir__simdfX_madd( o3, o3, r3, c5 ); stbir__simdfX_store( output5, o0 ); stbir__simdfX_store( output5+stbir__simdfX_float_count, o1 ); stbir__simdfX_store( output5+(2*stbir__simdfX_float_count), o2 ); stbir__simdfX_store( output5+(3*stbir__simdfX_float_count), o3 ); ) stbIF6( stbir__simdfX_load( o0, output6 ); stbir__simdfX_load( o1, output6+stbir__simdfX_float_count ); stbir__simdfX_load( o2, output6+(2*stbir__simdfX_float_count) ); stbir__simdfX_load( o3, output6+(3*stbir__simdfX_float_count) ); - stbir__simdfX_madd( o0, o0, r0, c6 ); stbir__simdfX_madd( o1, o1, r1, c6 ); stbir__simdfX_madd( o2, o2, r2, c6 ); stbir__simdfX_madd( o3, o3, r3, c6 ); + stbir__simdfX_madd( o0, o0, r0, c6 ); stbir__simdfX_madd( o1, o1, r1, c6 ); stbir__simdfX_madd( o2, o2, r2, c6 ); stbir__simdfX_madd( o3, o3, r3, c6 ); stbir__simdfX_store( output6, o0 ); stbir__simdfX_store( output6+stbir__simdfX_float_count, o1 ); stbir__simdfX_store( output6+(2*stbir__simdfX_float_count), o2 ); stbir__simdfX_store( output6+(3*stbir__simdfX_float_count), o3 ); ) stbIF7( stbir__simdfX_load( o0, output7 ); stbir__simdfX_load( o1, output7+stbir__simdfX_float_count ); stbir__simdfX_load( o2, output7+(2*stbir__simdfX_float_count) ); stbir__simdfX_load( o3, output7+(3*stbir__simdfX_float_count) ); - stbir__simdfX_madd( o0, o0, r0, c7 ); stbir__simdfX_madd( o1, o1, r1, c7 ); stbir__simdfX_madd( o2, o2, r2, c7 ); stbir__simdfX_madd( o3, o3, r3, c7 ); + stbir__simdfX_madd( o0, o0, r0, c7 ); stbir__simdfX_madd( o1, o1, r1, c7 ); stbir__simdfX_madd( o2, o2, r2, c7 ); stbir__simdfX_madd( o3, o3, r3, c7 ); stbir__simdfX_store( output7, o0 ); stbir__simdfX_store( output7+stbir__simdfX_float_count, o1 ); stbir__simdfX_store( output7+(2*stbir__simdfX_float_count), o2 ); stbir__simdfX_store( output7+(3*stbir__simdfX_float_count), o3 ); ) #else - stbIF0( stbir__simdfX_mult( o0, r0, c0 ); stbir__simdfX_mult( o1, r1, c0 ); stbir__simdfX_mult( o2, r2, c0 ); stbir__simdfX_mult( o3, r3, c0 ); + stbIF0( stbir__simdfX_mult( o0, r0, c0 ); stbir__simdfX_mult( o1, r1, c0 ); stbir__simdfX_mult( o2, r2, c0 ); stbir__simdfX_mult( o3, r3, c0 ); stbir__simdfX_store( output0, o0 ); stbir__simdfX_store( output0+stbir__simdfX_float_count, o1 ); stbir__simdfX_store( output0+(2*stbir__simdfX_float_count), o2 ); stbir__simdfX_store( output0+(3*stbir__simdfX_float_count), o3 ); ) - stbIF1( stbir__simdfX_mult( o0, r0, c1 ); stbir__simdfX_mult( o1, r1, c1 ); stbir__simdfX_mult( o2, r2, c1 ); stbir__simdfX_mult( o3, r3, c1 ); + stbIF1( stbir__simdfX_mult( o0, r0, c1 ); stbir__simdfX_mult( o1, r1, c1 ); stbir__simdfX_mult( o2, r2, c1 ); stbir__simdfX_mult( o3, r3, c1 ); stbir__simdfX_store( output1, o0 ); stbir__simdfX_store( output1+stbir__simdfX_float_count, o1 ); stbir__simdfX_store( output1+(2*stbir__simdfX_float_count), o2 ); stbir__simdfX_store( output1+(3*stbir__simdfX_float_count), o3 ); ) - stbIF2( stbir__simdfX_mult( o0, r0, c2 ); stbir__simdfX_mult( o1, r1, c2 ); stbir__simdfX_mult( o2, r2, c2 ); stbir__simdfX_mult( o3, r3, c2 ); + stbIF2( stbir__simdfX_mult( o0, r0, c2 ); stbir__simdfX_mult( o1, r1, c2 ); stbir__simdfX_mult( o2, r2, c2 ); stbir__simdfX_mult( o3, r3, c2 ); stbir__simdfX_store( output2, o0 ); stbir__simdfX_store( output2+stbir__simdfX_float_count, o1 ); stbir__simdfX_store( output2+(2*stbir__simdfX_float_count), o2 ); stbir__simdfX_store( output2+(3*stbir__simdfX_float_count), o3 ); ) - stbIF3( stbir__simdfX_mult( o0, r0, c3 ); stbir__simdfX_mult( o1, r1, c3 ); stbir__simdfX_mult( o2, r2, c3 ); stbir__simdfX_mult( o3, r3, c3 ); + stbIF3( stbir__simdfX_mult( o0, r0, c3 ); stbir__simdfX_mult( o1, r1, c3 ); stbir__simdfX_mult( o2, r2, c3 ); stbir__simdfX_mult( o3, r3, c3 ); stbir__simdfX_store( output3, o0 ); stbir__simdfX_store( output3+stbir__simdfX_float_count, o1 ); stbir__simdfX_store( output3+(2*stbir__simdfX_float_count), o2 ); stbir__simdfX_store( output3+(3*stbir__simdfX_float_count), o3 ); ) - stbIF4( stbir__simdfX_mult( o0, r0, c4 ); stbir__simdfX_mult( o1, r1, c4 ); stbir__simdfX_mult( o2, r2, c4 ); stbir__simdfX_mult( o3, r3, c4 ); + stbIF4( stbir__simdfX_mult( o0, r0, c4 ); stbir__simdfX_mult( o1, r1, c4 ); stbir__simdfX_mult( o2, r2, c4 ); stbir__simdfX_mult( o3, r3, c4 ); stbir__simdfX_store( output4, o0 ); stbir__simdfX_store( output4+stbir__simdfX_float_count, o1 ); stbir__simdfX_store( output4+(2*stbir__simdfX_float_count), o2 ); stbir__simdfX_store( output4+(3*stbir__simdfX_float_count), o3 ); ) - stbIF5( stbir__simdfX_mult( o0, r0, c5 ); stbir__simdfX_mult( o1, r1, c5 ); stbir__simdfX_mult( o2, r2, c5 ); stbir__simdfX_mult( o3, r3, c5 ); + stbIF5( stbir__simdfX_mult( o0, r0, c5 ); stbir__simdfX_mult( o1, r1, c5 ); stbir__simdfX_mult( o2, r2, c5 ); stbir__simdfX_mult( o3, r3, c5 ); stbir__simdfX_store( output5, o0 ); stbir__simdfX_store( output5+stbir__simdfX_float_count, o1 ); stbir__simdfX_store( output5+(2*stbir__simdfX_float_count), o2 ); stbir__simdfX_store( output5+(3*stbir__simdfX_float_count), o3 ); ) - stbIF6( stbir__simdfX_mult( o0, r0, c6 ); stbir__simdfX_mult( o1, r1, c6 ); stbir__simdfX_mult( o2, r2, c6 ); stbir__simdfX_mult( o3, r3, c6 ); + stbIF6( stbir__simdfX_mult( o0, r0, c6 ); stbir__simdfX_mult( o1, r1, c6 ); stbir__simdfX_mult( o2, r2, c6 ); stbir__simdfX_mult( o3, r3, c6 ); stbir__simdfX_store( output6, o0 ); stbir__simdfX_store( output6+stbir__simdfX_float_count, o1 ); stbir__simdfX_store( output6+(2*stbir__simdfX_float_count), o2 ); stbir__simdfX_store( output6+(3*stbir__simdfX_float_count), o3 ); ) - stbIF7( stbir__simdfX_mult( o0, r0, c7 ); stbir__simdfX_mult( o1, r1, c7 ); stbir__simdfX_mult( o2, r2, c7 ); stbir__simdfX_mult( o3, r3, c7 ); + stbIF7( stbir__simdfX_mult( o0, r0, c7 ); stbir__simdfX_mult( o1, r1, c7 ); stbir__simdfX_mult( o2, r2, c7 ); stbir__simdfX_mult( o3, r3, c7 ); stbir__simdfX_store( output7, o0 ); stbir__simdfX_store( output7+stbir__simdfX_float_count, o1 ); stbir__simdfX_store( output7+(2*stbir__simdfX_float_count), o2 ); stbir__simdfX_store( output7+(3*stbir__simdfX_float_count), o3 ); ) #endif input += (4*stbir__simdfX_float_count); stbIF0( output0 += (4*stbir__simdfX_float_count); ) stbIF1( output1 += (4*stbir__simdfX_float_count); ) stbIF2( output2 += (4*stbir__simdfX_float_count); ) stbIF3( output3 += (4*stbir__simdfX_float_count); ) stbIF4( output4 += (4*stbir__simdfX_float_count); ) stbIF5( output5 += (4*stbir__simdfX_float_count); ) stbIF6( output6 += (4*stbir__simdfX_float_count); ) stbIF7( output7 += (4*stbir__simdfX_float_count); ) } - while ( ( (char*)input_end - (char*) input ) >= 16 ) + STBIR_SIMD_NO_UNROLL_LOOP_START + while ( ( (char*)input_end - (char*) input ) >= 16 ) { stbir__simdf o0, r0; STBIR_SIMD_NO_UNROLL(output0); @@ -9692,13 +9935,14 @@ static void STBIR_chans( stbir__vertical_scatter_with_,_coeffs)( float ** output stbIF6( stbir__simdf_mult( o0, r0, stbir__if_simdf8_cast_to_simdf4( c6 ) ); stbir__simdf_store( output6, o0 ); ) stbIF7( stbir__simdf_mult( o0, r0, stbir__if_simdf8_cast_to_simdf4( c7 ) ); stbir__simdf_store( output7, o0 ); ) #endif - + input += 4; stbIF0( output0 += 4; ) stbIF1( output1 += 4; ) stbIF2( output2 += 4; ) stbIF3( output3 += 4; ) stbIF4( output4 += 4; ) stbIF5( output5 += 4; ) stbIF6( output6 += 4; ) stbIF7( output7 += 4; ) } } #else - while ( ( (char*)input_end - (char*) input ) >= 16 ) + STBIR_NO_UNROLL_LOOP_START + while ( ( (char*)input_end - (char*) input ) >= 16 ) { float r0, r1, r2, r3; STBIR_NO_UNROLL(input); @@ -9729,7 +9973,8 @@ static void STBIR_chans( stbir__vertical_scatter_with_,_coeffs)( float ** output stbIF0( output0 += 4; ) stbIF1( output1 += 4; ) stbIF2( output2 += 4; ) stbIF3( output3 += 4; ) stbIF4( output4 += 4; ) stbIF5( output5 += 4; ) stbIF6( output6 += 4; ) stbIF7( output7 += 4; ) } #endif - while ( input < input_end ) + STBIR_NO_UNROLL_LOOP_START + while ( input < input_end ) { float r = input[0]; STBIR_NO_UNROLL(output0); @@ -9779,7 +10024,7 @@ static void STBIR_chans( stbir__vertical_gather_with_,_coeffs)( float * outputp, STBIR_MEMCPY( output, input0, (char*)input0_end - (char*)input0 ); return; } -#endif +#endif #ifdef STBIR_SIMD { @@ -9791,14 +10036,15 @@ static void STBIR_chans( stbir__vertical_gather_with_,_coeffs)( float * outputp, stbIF5(stbir__simdfX c5 = stbir__simdf_frepX( c5s ); ) stbIF6(stbir__simdfX c6 = stbir__simdf_frepX( c6s ); ) stbIF7(stbir__simdfX c7 = stbir__simdf_frepX( c7s ); ) - - while ( ( (char*)input0_end - (char*) input0 ) >= (16*stbir__simdfX_float_count) ) + + STBIR_SIMD_NO_UNROLL_LOOP_START + while ( ( (char*)input0_end - (char*) input0 ) >= (16*stbir__simdfX_float_count) ) { stbir__simdfX o0, o1, o2, o3, r0, r1, r2, r3; STBIR_SIMD_NO_UNROLL(output); // prefetch four loop iterations ahead (doesn't affect much for small resizes, but helps with big ones) - stbIF0( stbir__prefetch( input0 + (16*stbir__simdfX_float_count) ); ) + stbIF0( stbir__prefetch( input0 + (16*stbir__simdfX_float_count) ); ) stbIF1( stbir__prefetch( input1 + (16*stbir__simdfX_float_count) ); ) stbIF2( stbir__prefetch( input2 + (16*stbir__simdfX_float_count) ); ) stbIF3( stbir__prefetch( input3 + (16*stbir__simdfX_float_count) ); ) @@ -9836,7 +10082,8 @@ static void STBIR_chans( stbir__vertical_gather_with_,_coeffs)( float * outputp, stbIF0( input0 += (4*stbir__simdfX_float_count); ) stbIF1( input1 += (4*stbir__simdfX_float_count); ) stbIF2( input2 += (4*stbir__simdfX_float_count); ) stbIF3( input3 += (4*stbir__simdfX_float_count); ) stbIF4( input4 += (4*stbir__simdfX_float_count); ) stbIF5( input5 += (4*stbir__simdfX_float_count); ) stbIF6( input6 += (4*stbir__simdfX_float_count); ) stbIF7( input7 += (4*stbir__simdfX_float_count); ) } - while ( ( (char*)input0_end - (char*) input0 ) >= 16 ) + STBIR_SIMD_NO_UNROLL_LOOP_START + while ( ( (char*)input0_end - (char*) input0 ) >= 16 ) { stbir__simdf o0, r0; STBIR_SIMD_NO_UNROLL(output); @@ -9860,7 +10107,8 @@ static void STBIR_chans( stbir__vertical_gather_with_,_coeffs)( float * outputp, } } #else - while ( ( (char*)input0_end - (char*) input0 ) >= 16 ) + STBIR_NO_UNROLL_LOOP_START + while ( ( (char*)input0_end - (char*) input0 ) >= 16 ) { float o0, o1, o2, o3; STBIR_NO_UNROLL(output); @@ -9881,7 +10129,8 @@ static void STBIR_chans( stbir__vertical_gather_with_,_coeffs)( float * outputp, stbIF0( input0 += 4; ) stbIF1( input1 += 4; ) stbIF2( input2 += 4; ) stbIF3( input3 += 4; ) stbIF4( input4 += 4; ) stbIF5( input5 += 4; ) stbIF6( input6 += 4; ) stbIF7( input7 += 4; ) } #endif - while ( input0 < input0_end ) + STBIR_NO_UNROLL_LOOP_START + while ( input0 < input0_end ) { float o0; STBIR_NO_UNROLL(output); @@ -9897,7 +10146,7 @@ static void STBIR_chans( stbir__vertical_gather_with_,_coeffs)( float * outputp, stbIF5( o0 += input5[0] * c5s; ) stbIF6( o0 += input6[0] * c6s; ) stbIF7( o0 += input7[0] * c7s; ) - output[0] = o0; + output[0] = o0; ++output; stbIF0( ++input0; ) stbIF1( ++input1; ) stbIF2( ++input2; ) stbIF3( ++input3; ) stbIF4( ++input4; ) stbIF5( ++input5; ) stbIF6( ++input6; ) stbIF7( ++input7; ) } @@ -9928,25 +10177,25 @@ static void STBIR_chans( stbir__vertical_gather_with_,_coeffs)( float * outputp, #ifndef stbir__2_coeff_only #define stbir__2_coeff_only() \ stbir__1_coeff_only(); \ - stbir__1_coeff_remnant(1); + stbir__1_coeff_remnant(1); #endif #ifndef stbir__2_coeff_remnant #define stbir__2_coeff_remnant( ofs ) \ stbir__1_coeff_remnant(ofs); \ - stbir__1_coeff_remnant((ofs)+1); + stbir__1_coeff_remnant((ofs)+1); #endif - + #ifndef stbir__3_coeff_only #define stbir__3_coeff_only() \ stbir__2_coeff_only(); \ - stbir__1_coeff_remnant(2); + stbir__1_coeff_remnant(2); #endif - + #ifndef stbir__3_coeff_remnant #define stbir__3_coeff_remnant( ofs ) \ stbir__2_coeff_remnant(ofs); \ - stbir__1_coeff_remnant((ofs)+2); + stbir__1_coeff_remnant((ofs)+2); #endif #ifndef stbir__3_coeff_setup @@ -9956,13 +10205,13 @@ static void STBIR_chans( stbir__vertical_gather_with_,_coeffs)( float * outputp, #ifndef stbir__4_coeff_start #define stbir__4_coeff_start() \ stbir__2_coeff_only(); \ - stbir__2_coeff_remnant(2); + stbir__2_coeff_remnant(2); #endif - + #ifndef stbir__4_coeff_continue_from_4 #define stbir__4_coeff_continue_from_4( ofs ) \ stbir__2_coeff_remnant(ofs); \ - stbir__2_coeff_remnant((ofs)+2); + stbir__2_coeff_remnant((ofs)+2); #endif #ifndef stbir__store_output_tiny @@ -9973,8 +10222,9 @@ static void STBIR_chans( stbir__horizontal_gather_,_channels_with_1_coeff)( floa { float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels; float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer; + STBIR_SIMD_NO_UNROLL_LOOP_START do { - float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; + float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; float const * hc = horizontal_coefficients; stbir__1_coeff_only(); stbir__store_output_tiny(); @@ -9985,8 +10235,9 @@ static void STBIR_chans( stbir__horizontal_gather_,_channels_with_2_coeffs)( flo { float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels; float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer; + STBIR_SIMD_NO_UNROLL_LOOP_START do { - float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; + float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; float const * hc = horizontal_coefficients; stbir__2_coeff_only(); stbir__store_output_tiny(); @@ -9997,8 +10248,9 @@ static void STBIR_chans( stbir__horizontal_gather_,_channels_with_3_coeffs)( flo { float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels; float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer; + STBIR_SIMD_NO_UNROLL_LOOP_START do { - float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; + float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; float const * hc = horizontal_coefficients; stbir__3_coeff_only(); stbir__store_output_tiny(); @@ -10009,8 +10261,9 @@ static void STBIR_chans( stbir__horizontal_gather_,_channels_with_4_coeffs)( flo { float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels; float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer; + STBIR_SIMD_NO_UNROLL_LOOP_START do { - float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; + float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; float const * hc = horizontal_coefficients; stbir__4_coeff_start(); stbir__store_output(); @@ -10021,8 +10274,9 @@ static void STBIR_chans( stbir__horizontal_gather_,_channels_with_5_coeffs)( flo { float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels; float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer; + STBIR_SIMD_NO_UNROLL_LOOP_START do { - float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; + float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; float const * hc = horizontal_coefficients; stbir__4_coeff_start(); stbir__1_coeff_remnant(4); @@ -10034,8 +10288,9 @@ static void STBIR_chans( stbir__horizontal_gather_,_channels_with_6_coeffs)( flo { float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels; float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer; + STBIR_SIMD_NO_UNROLL_LOOP_START do { - float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; + float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; float const * hc = horizontal_coefficients; stbir__4_coeff_start(); stbir__2_coeff_remnant(4); @@ -10048,10 +10303,11 @@ static void STBIR_chans( stbir__horizontal_gather_,_channels_with_7_coeffs)( flo float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels; float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer; stbir__3_coeff_setup(); + STBIR_SIMD_NO_UNROLL_LOOP_START do { - float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; + float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; float const * hc = horizontal_coefficients; - + stbir__4_coeff_start(); stbir__3_coeff_remnant(4); stbir__store_output(); @@ -10062,8 +10318,9 @@ static void STBIR_chans( stbir__horizontal_gather_,_channels_with_8_coeffs)( flo { float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels; float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer; + STBIR_SIMD_NO_UNROLL_LOOP_START do { - float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; + float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; float const * hc = horizontal_coefficients; stbir__4_coeff_start(); stbir__4_coeff_continue_from_4(4); @@ -10075,8 +10332,9 @@ static void STBIR_chans( stbir__horizontal_gather_,_channels_with_9_coeffs)( flo { float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels; float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer; + STBIR_SIMD_NO_UNROLL_LOOP_START do { - float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; + float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; float const * hc = horizontal_coefficients; stbir__4_coeff_start(); stbir__4_coeff_continue_from_4(4); @@ -10089,8 +10347,9 @@ static void STBIR_chans( stbir__horizontal_gather_,_channels_with_10_coeffs)( fl { float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels; float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer; + STBIR_SIMD_NO_UNROLL_LOOP_START do { - float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; + float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; float const * hc = horizontal_coefficients; stbir__4_coeff_start(); stbir__4_coeff_continue_from_4(4); @@ -10104,8 +10363,9 @@ static void STBIR_chans( stbir__horizontal_gather_,_channels_with_11_coeffs)( fl float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels; float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer; stbir__3_coeff_setup(); + STBIR_SIMD_NO_UNROLL_LOOP_START do { - float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; + float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; float const * hc = horizontal_coefficients; stbir__4_coeff_start(); stbir__4_coeff_continue_from_4(4); @@ -10118,8 +10378,9 @@ static void STBIR_chans( stbir__horizontal_gather_,_channels_with_12_coeffs)( fl { float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels; float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer; + STBIR_SIMD_NO_UNROLL_LOOP_START do { - float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; + float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; float const * hc = horizontal_coefficients; stbir__4_coeff_start(); stbir__4_coeff_continue_from_4(4); @@ -10132,12 +10393,14 @@ static void STBIR_chans( stbir__horizontal_gather_,_channels_with_n_coeffs_mod0 { float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels; float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer; + STBIR_SIMD_NO_UNROLL_LOOP_START do { - float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; - int n = ( ( horizontal_contributors->n1 - horizontal_contributors->n0 + 1 ) - 4 + 3 ) >> 2; + float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; + int n = ( ( horizontal_contributors->n1 - horizontal_contributors->n0 + 1 ) - 4 + 3 ) >> 2; float const * hc = horizontal_coefficients; stbir__4_coeff_start(); + STBIR_SIMD_NO_UNROLL_LOOP_START do { hc += 4; decode += STBIR__horizontal_channels * 4; @@ -10152,19 +10415,21 @@ static void STBIR_chans( stbir__horizontal_gather_,_channels_with_n_coeffs_mod1 { float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels; float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer; + STBIR_SIMD_NO_UNROLL_LOOP_START do { - float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; - int n = ( ( horizontal_contributors->n1 - horizontal_contributors->n0 + 1 ) - 5 + 3 ) >> 2; + float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; + int n = ( ( horizontal_contributors->n1 - horizontal_contributors->n0 + 1 ) - 5 + 3 ) >> 2; float const * hc = horizontal_coefficients; stbir__4_coeff_start(); + STBIR_SIMD_NO_UNROLL_LOOP_START do { hc += 4; decode += STBIR__horizontal_channels * 4; stbir__4_coeff_continue_from_4( 0 ); --n; } while ( n > 0 ); - stbir__1_coeff_remnant( 4 ); + stbir__1_coeff_remnant( 4 ); stbir__store_output(); } while ( output < output_end ); } @@ -10173,19 +10438,21 @@ static void STBIR_chans( stbir__horizontal_gather_,_channels_with_n_coeffs_mod2 { float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels; float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer; + STBIR_SIMD_NO_UNROLL_LOOP_START do { - float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; - int n = ( ( horizontal_contributors->n1 - horizontal_contributors->n0 + 1 ) - 6 + 3 ) >> 2; + float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; + int n = ( ( horizontal_contributors->n1 - horizontal_contributors->n0 + 1 ) - 6 + 3 ) >> 2; float const * hc = horizontal_coefficients; stbir__4_coeff_start(); + STBIR_SIMD_NO_UNROLL_LOOP_START do { hc += 4; decode += STBIR__horizontal_channels * 4; stbir__4_coeff_continue_from_4( 0 ); --n; } while ( n > 0 ); - stbir__2_coeff_remnant( 4 ); + stbir__2_coeff_remnant( 4 ); stbir__store_output(); } while ( output < output_end ); @@ -10196,19 +10463,21 @@ static void STBIR_chans( stbir__horizontal_gather_,_channels_with_n_coeffs_mod3 float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels; float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer; stbir__3_coeff_setup(); + STBIR_SIMD_NO_UNROLL_LOOP_START do { - float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; - int n = ( ( horizontal_contributors->n1 - horizontal_contributors->n0 + 1 ) - 7 + 3 ) >> 2; + float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; + int n = ( ( horizontal_contributors->n1 - horizontal_contributors->n0 + 1 ) - 7 + 3 ) >> 2; float const * hc = horizontal_coefficients; stbir__4_coeff_start(); + STBIR_SIMD_NO_UNROLL_LOOP_START do { hc += 4; decode += STBIR__horizontal_channels * 4; stbir__4_coeff_continue_from_4( 0 ); --n; } while ( n > 0 ); - stbir__3_coeff_remnant( 4 ); + stbir__3_coeff_remnant( 4 ); stbir__store_output(); } while ( output < output_end ); @@ -10216,26 +10485,26 @@ static void STBIR_chans( stbir__horizontal_gather_,_channels_with_n_coeffs_mod3 static stbir__horizontal_gather_channels_func * STBIR_chans(stbir__horizontal_gather_,_channels_with_n_coeffs_funcs)[4]= { - STBIR_chans(stbir__horizontal_gather_,_channels_with_n_coeffs_mod0), - STBIR_chans(stbir__horizontal_gather_,_channels_with_n_coeffs_mod1), - STBIR_chans(stbir__horizontal_gather_,_channels_with_n_coeffs_mod2), - STBIR_chans(stbir__horizontal_gather_,_channels_with_n_coeffs_mod3), + STBIR_chans(stbir__horizontal_gather_,_channels_with_n_coeffs_mod0), + STBIR_chans(stbir__horizontal_gather_,_channels_with_n_coeffs_mod1), + STBIR_chans(stbir__horizontal_gather_,_channels_with_n_coeffs_mod2), + STBIR_chans(stbir__horizontal_gather_,_channels_with_n_coeffs_mod3), }; static stbir__horizontal_gather_channels_func * STBIR_chans(stbir__horizontal_gather_,_channels_funcs)[12]= { - STBIR_chans(stbir__horizontal_gather_,_channels_with_1_coeff), - STBIR_chans(stbir__horizontal_gather_,_channels_with_2_coeffs), + STBIR_chans(stbir__horizontal_gather_,_channels_with_1_coeff), + STBIR_chans(stbir__horizontal_gather_,_channels_with_2_coeffs), STBIR_chans(stbir__horizontal_gather_,_channels_with_3_coeffs), - STBIR_chans(stbir__horizontal_gather_,_channels_with_4_coeffs), - STBIR_chans(stbir__horizontal_gather_,_channels_with_5_coeffs), - STBIR_chans(stbir__horizontal_gather_,_channels_with_6_coeffs), + STBIR_chans(stbir__horizontal_gather_,_channels_with_4_coeffs), + STBIR_chans(stbir__horizontal_gather_,_channels_with_5_coeffs), + STBIR_chans(stbir__horizontal_gather_,_channels_with_6_coeffs), STBIR_chans(stbir__horizontal_gather_,_channels_with_7_coeffs), - STBIR_chans(stbir__horizontal_gather_,_channels_with_8_coeffs), - STBIR_chans(stbir__horizontal_gather_,_channels_with_9_coeffs), - STBIR_chans(stbir__horizontal_gather_,_channels_with_10_coeffs), - STBIR_chans(stbir__horizontal_gather_,_channels_with_11_coeffs), - STBIR_chans(stbir__horizontal_gather_,_channels_with_12_coeffs), + STBIR_chans(stbir__horizontal_gather_,_channels_with_8_coeffs), + STBIR_chans(stbir__horizontal_gather_,_channels_with_9_coeffs), + STBIR_chans(stbir__horizontal_gather_,_channels_with_10_coeffs), + STBIR_chans(stbir__horizontal_gather_,_channels_with_11_coeffs), + STBIR_chans(stbir__horizontal_gather_,_channels_with_12_coeffs), }; #undef STBIR__horizontal_channels @@ -10266,38 +10535,38 @@ This software is available under 2 licenses -- choose whichever you prefer. ------------------------------------------------------------------------------ ALTERNATIVE A - MIT License Copyright (c) 2017 Sean Barrett -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 +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 +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 +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. ------------------------------------------------------------------------------ ALTERNATIVE B - Public Domain (www.unlicense.org) This is free and unencumbered software released into the public domain. -Anyone is free to copy, modify, publish, use, compile, sell, or distribute this -software, either in source code form or as a compiled binary, for any purpose, +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, commercial or non-commercial, and by any means. -In jurisdictions that recognize copyright laws, the author or authors of this -software dedicate any and all copyright interest in the software to the public -domain. We make this dedication for the benefit of the public at large and to -the detriment of our heirs and successors. We intend this dedication to be an -overt act of relinquishment in perpetuity of all present and future rights to +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to this software under copyright law. -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 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 +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 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. ------------------------------------------------------------------------------ */ From fd961deba76c7c4939440fa6e6574eb86e68c5fb Mon Sep 17 00:00:00 2001 From: Alex Date: Tue, 10 Sep 2024 00:44:25 -0500 Subject: [PATCH 061/208] Update BINDINGS.md (#4311) I've updated the bindings --- BINDINGS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BINDINGS.md b/BINDINGS.md index 7fd0dfd93..2c986f236 100644 --- a/BINDINGS.md +++ b/BINDINGS.md @@ -9,7 +9,7 @@ Some people ported raylib to other languages in the form of bindings or wrappers | [raylib](https://github.com/raysan5/raylib) | **5.0** | [C/C++](https://en.wikipedia.org/wiki/C_(programming_language)) | Zlib | | [raylib-beef](https://github.com/Starpelly/raylib-beef) | **5.0** | [Beef](https://www.beeflang.org) | MIT | | [raylib-boo](https://github.com/Rabios/raylib-boo) | 3.7 | [Boo](http://boo-language.github.io) | MIT | -| [raybit](https://github.com/Alex-Velez/raybit) | 3.7 | [Brainfuck](https://en.wikipedia.org/wiki/Brainfuck) | MIT | +| [raybit](https://github.com/Alex-Velez/raybit) | **5.0** | [Brainfuck](https://en.wikipedia.org/wiki/Brainfuck) | MIT | | [Raylib-cs](https://github.com/ChrisDill/Raylib-cs) | **5.0** | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) | Zlib | | [Raylib-CsLo](https://github.com/NotNotTech/Raylib-CsLo) | 4.2 | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) | MPL-2.0 | | [Raylib-CSharp-Vinculum](https://github.com/ZeroElectric/Raylib-CSharp-Vinculum) | **5.0** | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) | MPL-2.0 | From ed702673ea0ff49da2ca494686814376ad040941 Mon Sep 17 00:00:00 2001 From: Jett <30197659+JettMonstersGoBoom@users.noreply.github.com> Date: Wed, 11 Sep 2024 16:57:19 -0400 Subject: [PATCH 062/208] fix for hardcoded index values in vboID array (#4312) changing any of the #defines in CONFIG.H would cause issues when rendering. --- src/config.h | 1 + src/rmodels.c | 60 +++++++++++++++++++++++++-------------------------- 2 files changed, 31 insertions(+), 30 deletions(-) diff --git a/src/config.h b/src/config.h index c54583e74..9cbe90e35 100644 --- a/src/config.h +++ b/src/config.h @@ -119,6 +119,7 @@ #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR 3 #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT 4 #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2 5 +#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_INDICES 6 // Default shader vertex attribute names to set location points // NOTE: When a new shader is loaded, the following locations are tried to be set for convenience diff --git a/src/rmodels.c b/src/rmodels.c index 5fb512403..9994ddb76 100644 --- a/src/rmodels.c +++ b/src/rmodels.c @@ -1246,13 +1246,13 @@ void UploadMesh(Mesh *mesh, bool dynamic) mesh->vboId = (unsigned int *)RL_CALLOC(MAX_MESH_VERTEX_BUFFERS, sizeof(unsigned int)); mesh->vaoId = 0; // Vertex Array Object - mesh->vboId[0] = 0; // Vertex buffer: positions - mesh->vboId[1] = 0; // Vertex buffer: texcoords - mesh->vboId[2] = 0; // Vertex buffer: normals - mesh->vboId[3] = 0; // Vertex buffer: colors - mesh->vboId[4] = 0; // Vertex buffer: tangents - mesh->vboId[5] = 0; // Vertex buffer: texcoords2 - mesh->vboId[6] = 0; // Vertex buffer: indices + mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION] = 0; // Vertex buffer: positions + mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD] = 0; // Vertex buffer: texcoords + mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL] = 0; // Vertex buffer: normals + mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR] = 0; // Vertex buffer: colors + mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT] = 0; // Vertex buffer: tangents + mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2] = 0; // Vertex buffer: texcoords2 + mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_INDICES] = 0; // Vertex buffer: indices #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) mesh->vaoId = rlLoadVertexArray(); @@ -1262,12 +1262,12 @@ void UploadMesh(Mesh *mesh, bool dynamic) // Enable vertex attributes: position (shader-location = 0) void *vertices = (mesh->animVertices != NULL)? mesh->animVertices : mesh->vertices; - mesh->vboId[0] = rlLoadVertexBuffer(vertices, mesh->vertexCount*3*sizeof(float), dynamic); + mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION] = rlLoadVertexBuffer(vertices, mesh->vertexCount*3*sizeof(float), dynamic); rlSetVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION, 3, RL_FLOAT, 0, 0, 0); rlEnableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION); // Enable vertex attributes: texcoords (shader-location = 1) - mesh->vboId[1] = rlLoadVertexBuffer(mesh->texcoords, mesh->vertexCount*2*sizeof(float), dynamic); + mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD] = rlLoadVertexBuffer(mesh->texcoords, mesh->vertexCount*2*sizeof(float), dynamic); rlSetVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD, 2, RL_FLOAT, 0, 0, 0); rlEnableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD); @@ -1278,7 +1278,7 @@ void UploadMesh(Mesh *mesh, bool dynamic) { // Enable vertex attributes: normals (shader-location = 2) void *normals = (mesh->animNormals != NULL)? mesh->animNormals : mesh->normals; - mesh->vboId[2] = rlLoadVertexBuffer(normals, mesh->vertexCount*3*sizeof(float), dynamic); + mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL] = rlLoadVertexBuffer(normals, mesh->vertexCount*3*sizeof(float), dynamic); rlSetVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL, 3, RL_FLOAT, 0, 0, 0); rlEnableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL); } @@ -1294,7 +1294,7 @@ void UploadMesh(Mesh *mesh, bool dynamic) if (mesh->colors != NULL) { // Enable vertex attribute: color (shader-location = 3) - mesh->vboId[3] = rlLoadVertexBuffer(mesh->colors, mesh->vertexCount*4*sizeof(unsigned char), dynamic); + mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR] = rlLoadVertexBuffer(mesh->colors, mesh->vertexCount*4*sizeof(unsigned char), dynamic); rlSetVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR, 4, RL_UNSIGNED_BYTE, 1, 0, 0); rlEnableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR); } @@ -1310,7 +1310,7 @@ void UploadMesh(Mesh *mesh, bool dynamic) if (mesh->tangents != NULL) { // Enable vertex attribute: tangent (shader-location = 4) - mesh->vboId[4] = rlLoadVertexBuffer(mesh->tangents, mesh->vertexCount*4*sizeof(float), dynamic); + mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT] = rlLoadVertexBuffer(mesh->tangents, mesh->vertexCount*4*sizeof(float), dynamic); rlSetVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT, 4, RL_FLOAT, 0, 0, 0); rlEnableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT); } @@ -1326,7 +1326,7 @@ void UploadMesh(Mesh *mesh, bool dynamic) if (mesh->texcoords2 != NULL) { // Enable vertex attribute: texcoord2 (shader-location = 5) - mesh->vboId[5] = rlLoadVertexBuffer(mesh->texcoords2, mesh->vertexCount*2*sizeof(float), dynamic); + mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2] = rlLoadVertexBuffer(mesh->texcoords2, mesh->vertexCount*2*sizeof(float), dynamic); rlSetVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2, 2, RL_FLOAT, 0, 0, 0); rlEnableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2); } @@ -1341,7 +1341,7 @@ void UploadMesh(Mesh *mesh, bool dynamic) if (mesh->indices != NULL) { - mesh->vboId[6] = rlLoadVertexBufferElement(mesh->indices, mesh->triangleCount*3*sizeof(unsigned short), dynamic); + mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_INDICES] = rlLoadVertexBufferElement(mesh->indices, mesh->triangleCount*3*sizeof(unsigned short), dynamic); } if (mesh->vaoId > 0) TRACELOG(LOG_INFO, "VAO: [ID %i] Mesh uploaded successfully to VRAM (GPU)", mesh->vaoId); @@ -1478,19 +1478,19 @@ void DrawMesh(Mesh mesh, Material material, Matrix transform) if (!rlEnableVertexArray(mesh.vaoId)) { // Bind mesh VBO data: vertex position (shader-location = 0) - rlEnableVertexBuffer(mesh.vboId[0]); + rlEnableVertexBuffer(mesh.vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION]); rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_POSITION], 3, RL_FLOAT, 0, 0, 0); rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_POSITION]); // Bind mesh VBO data: vertex texcoords (shader-location = 1) - rlEnableVertexBuffer(mesh.vboId[1]); + rlEnableVertexBuffer(mesh.vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD]); rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD01], 2, RL_FLOAT, 0, 0, 0); rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD01]); if (material.shader.locs[SHADER_LOC_VERTEX_NORMAL] != -1) { // Bind mesh VBO data: vertex normals (shader-location = 2) - rlEnableVertexBuffer(mesh.vboId[2]); + rlEnableVertexBuffer(mesh.vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL]); rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_NORMAL], 3, RL_FLOAT, 0, 0, 0); rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_NORMAL]); } @@ -1498,9 +1498,9 @@ void DrawMesh(Mesh mesh, Material material, Matrix transform) // Bind mesh VBO data: vertex colors (shader-location = 3, if available) if (material.shader.locs[SHADER_LOC_VERTEX_COLOR] != -1) { - if (mesh.vboId[3] != 0) + if (mesh.vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR] != 0) { - rlEnableVertexBuffer(mesh.vboId[3]); + rlEnableVertexBuffer(mesh.vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR]); rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_COLOR], 4, RL_UNSIGNED_BYTE, 1, 0, 0); rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_COLOR]); } @@ -1517,7 +1517,7 @@ void DrawMesh(Mesh mesh, Material material, Matrix transform) // Bind mesh VBO data: vertex tangents (shader-location = 4, if available) if (material.shader.locs[SHADER_LOC_VERTEX_TANGENT] != -1) { - rlEnableVertexBuffer(mesh.vboId[4]); + rlEnableVertexBuffer(mesh.vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT]); rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TANGENT], 4, RL_FLOAT, 0, 0, 0); rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TANGENT]); } @@ -1525,12 +1525,12 @@ void DrawMesh(Mesh mesh, Material material, Matrix transform) // Bind mesh VBO data: vertex texcoords2 (shader-location = 5, if available) if (material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD02] != -1) { - rlEnableVertexBuffer(mesh.vboId[5]); + rlEnableVertexBuffer(mesh.vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2]); rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD02], 2, RL_FLOAT, 0, 0, 0); rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD02]); } - if (mesh.indices != NULL) rlEnableVertexBufferElement(mesh.vboId[6]); + if (mesh.indices != NULL) rlEnableVertexBufferElement(mesh.vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_INDICES]); } int eyeCount = 1; @@ -1696,19 +1696,19 @@ void DrawMeshInstanced(Mesh mesh, Material material, const Matrix *transforms, i if (!rlEnableVertexArray(mesh.vaoId)) { // Bind mesh VBO data: vertex position (shader-location = 0) - rlEnableVertexBuffer(mesh.vboId[0]); + rlEnableVertexBuffer(mesh.vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION]); rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_POSITION], 3, RL_FLOAT, 0, 0, 0); rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_POSITION]); // Bind mesh VBO data: vertex texcoords (shader-location = 1) - rlEnableVertexBuffer(mesh.vboId[1]); + rlEnableVertexBuffer(mesh.vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD]); rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD01], 2, RL_FLOAT, 0, 0, 0); rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD01]); if (material.shader.locs[SHADER_LOC_VERTEX_NORMAL] != -1) { // Bind mesh VBO data: vertex normals (shader-location = 2) - rlEnableVertexBuffer(mesh.vboId[2]); + rlEnableVertexBuffer(mesh.vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL]); rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_NORMAL], 3, RL_FLOAT, 0, 0, 0); rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_NORMAL]); } @@ -1716,9 +1716,9 @@ void DrawMeshInstanced(Mesh mesh, Material material, const Matrix *transforms, i // Bind mesh VBO data: vertex colors (shader-location = 3, if available) if (material.shader.locs[SHADER_LOC_VERTEX_COLOR] != -1) { - if (mesh.vboId[3] != 0) + if (mesh.vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR] != 0) { - rlEnableVertexBuffer(mesh.vboId[3]); + rlEnableVertexBuffer(mesh.vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR]); rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_COLOR], 4, RL_UNSIGNED_BYTE, 1, 0, 0); rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_COLOR]); } @@ -1735,7 +1735,7 @@ void DrawMeshInstanced(Mesh mesh, Material material, const Matrix *transforms, i // Bind mesh VBO data: vertex tangents (shader-location = 4, if available) if (material.shader.locs[SHADER_LOC_VERTEX_TANGENT] != -1) { - rlEnableVertexBuffer(mesh.vboId[4]); + rlEnableVertexBuffer(mesh.vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT]); rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TANGENT], 4, RL_FLOAT, 0, 0, 0); rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TANGENT]); } @@ -1743,12 +1743,12 @@ void DrawMeshInstanced(Mesh mesh, Material material, const Matrix *transforms, i // Bind mesh VBO data: vertex texcoords2 (shader-location = 5, if available) if (material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD02] != -1) { - rlEnableVertexBuffer(mesh.vboId[5]); + rlEnableVertexBuffer(mesh.vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2]); rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD02], 2, RL_FLOAT, 0, 0, 0); rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD02]); } - if (mesh.indices != NULL) rlEnableVertexBufferElement(mesh.vboId[6]); + if (mesh.indices != NULL) rlEnableVertexBufferElement(mesh.vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_INDICES]); } int eyeCount = 1; From d02fcc5262f5b359b3645614a90d1e613f7e7f53 Mon Sep 17 00:00:00 2001 From: base Date: Sun, 15 Sep 2024 07:51:20 -0300 Subject: [PATCH 063/208] chore: GetApplicationDirectory definition for FreeBSD (#4318) --- src/rcore.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/rcore.c b/src/rcore.c index 972d58600..44dfd746f 100644 --- a/src/rcore.c +++ b/src/rcore.c @@ -165,6 +165,10 @@ unsigned int __stdcall timeBeginPeriod(unsigned int uPeriod); unsigned int __stdcall timeEndPeriod(unsigned int uPeriod); #elif defined(__linux__) #include +#elif defined(__FreeBSD__) + #include + #include + #include #elif defined(__APPLE__) #include #include @@ -2161,6 +2165,28 @@ const char *GetApplicationDirectory(void) appDir[0] = '.'; appDir[1] = '/'; } +#elif defined(__FreeBSD__) + size_t size = sizeof(appDir); + int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1}; + + if (sysctl(mib, 4, appDir, &size, NULL, 0) == 0) + { + int len = strlen(appDir); + for (int i = len; i >= 0; --i) + { + if (appDir[i] == '/') + { + appDir[i + 1] = '\0'; + break; + } + } + } + else + { + appDir[0] = '.'; + appDir[1] = '/'; + } + #endif return appDir; From ddc523ffbe8a0af2e4783d947cdff6c9c53f7048 Mon Sep 17 00:00:00 2001 From: SusgUY446 <129160115+SusgUY446@users.noreply.github.com> Date: Sun, 15 Sep 2024 12:55:45 +0200 Subject: [PATCH 064/208] [rtextures] add MixColors. a function to mix 2 colors together (#4310) * added MixColors function to mix 2 colors together (Line 1428 raylib.h and Line 4995 in rtextures.c) * renamed MixColors to ColorLerp (https://github.com/raysan5/raylib/pull/4310#issuecomment-2340121038) * changed ColorLerp to be more like other functions --------- Co-authored-by: CI <-ci@not-real.com> --- src/raylib.h | 1 + src/rtextures.c | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/src/raylib.h b/src/raylib.h index 30ba8bd2a..a9cdbe94b 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -1435,6 +1435,7 @@ RLAPI Color GetColor(unsigned int hexValue); // G RLAPI Color GetPixelColor(void *srcPtr, int format); // Get Color from a source pixel pointer of certain format RLAPI void SetPixelColor(void *dstPtr, Color color, int format); // Set color formatted into destination pixel pointer RLAPI int GetPixelDataSize(int width, int height, int format); // Get pixel data size in bytes for certain format +RLAPI Color ColorLerp(Color color1, Color color2, float d); // Mix 2 Colors Together //------------------------------------------------------------------------------------ // Font Loading and Text Drawing Functions (Module: text) diff --git a/src/rtextures.c b/src/rtextures.c index 867add38e..f391b0d91 100644 --- a/src/rtextures.c +++ b/src/rtextures.c @@ -4985,6 +4985,8 @@ Vector3 ColorToHSV(Color color) return hsv; } + + // Get a Color from HSV values // Implementation reference: https://en.wikipedia.org/wiki/HSL_and_HSV#Alternative_HSV_conversion // NOTE: Color->HSV->Color conversion will not yield exactly the same color due to rounding errors @@ -5422,6 +5424,24 @@ int GetPixelDataSize(int width, int height, int format) return dataSize; } + +// Mix 2 Colors togehter. +// d = dominance. 0.5 for equal +Color ColorLerp(Color color1, Color color2, float d) +{ + Color newColor = { 0, 0, 0, 0 }; + if (d < 0) {d=0.0f;} + else if(d>1) {d=1.0f;} + + newColor.r = (unsigned char)((1.0f-d) * color1.r + d * color2.r); + newColor.g = (unsigned char)((1.0f-d) * color1.g + d * color2.g); + newColor.b = (unsigned char)((1.0f-d) * color1.b + d * color2.b); + newColor.a = (unsigned char)((1.0f-d) * color1.a + d * color2.a); + + return newColor; +} + + //---------------------------------------------------------------------------------- // Module specific Functions Definition //---------------------------------------------------------------------------------- From 68e7cadabcc4966c38251f59cb1bddb66f72bbeb Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 15 Sep 2024 10:56:01 +0000 Subject: [PATCH 065/208] Update raylib_api.* by CI --- parser/output/raylib_api.json | 21 +- parser/output/raylib_api.lua | 12 +- parser/output/raylib_api.txt | 393 +++++++++++++++++----------------- parser/output/raylib_api.xml | 9 +- 4 files changed, 238 insertions(+), 197 deletions(-) diff --git a/parser/output/raylib_api.json b/parser/output/raylib_api.json index 03b19325a..48096a951 100644 --- a/parser/output/raylib_api.json +++ b/parser/output/raylib_api.json @@ -8844,6 +8844,25 @@ } ] }, + { + "name": "ColorLerp", + "description": "Mix 2 Colors Together", + "returnType": "Color", + "params": [ + { + "type": "Color", + "name": "color1" + }, + { + "type": "Color", + "name": "color2" + }, + { + "type": "float", + "name": "d" + } + ] + }, { "name": "GetFontDefault", "description": "Get the default Font", @@ -8862,7 +8881,7 @@ }, { "name": "LoadFontEx", - "description": "Load font from file with extended parameters, use NULL for codepoints and 0 for codepointCount to load the default character setFont", + "description": "Load font from file with extended parameters, use NULL for codepoints and 0 for codepointCount to load the default character set, font size is provided in pixels height", "returnType": "Font", "params": [ { diff --git a/parser/output/raylib_api.lua b/parser/output/raylib_api.lua index 7d74c9a41..66095be61 100644 --- a/parser/output/raylib_api.lua +++ b/parser/output/raylib_api.lua @@ -6414,6 +6414,16 @@ return { {type = "int", name = "format"} } }, + { + name = "ColorLerp", + description = "Mix 2 Colors Together", + returnType = "Color", + params = { + {type = "Color", name = "color1"}, + {type = "Color", name = "color2"}, + {type = "float", name = "d"} + } + }, { name = "GetFontDefault", description = "Get the default Font", @@ -6429,7 +6439,7 @@ return { }, { name = "LoadFontEx", - description = "Load font from file with extended parameters, use NULL for codepoints and 0 for codepointCount to load the default character setFont", + description = "Load font from file with extended parameters, use NULL for codepoints and 0 for codepointCount to load the default character set, font size is provided in pixels height", returnType = "Font", params = { {type = "const char *", name = "fileName"}, diff --git a/parser/output/raylib_api.txt b/parser/output/raylib_api.txt index fb30ebe5f..6c489498b 100644 --- a/parser/output/raylib_api.txt +++ b/parser/output/raylib_api.txt @@ -984,7 +984,7 @@ Callback 006: AudioCallback() (2 input parameters) Param[1]: bufferData (type: void *) Param[2]: frames (type: unsigned int) -Functions found: 575 +Functions found: 576 Function 001: InitWindow() (3 input parameters) Name: InitWindow @@ -3393,32 +3393,39 @@ Function 384: GetPixelDataSize() (3 input parameters) Param[1]: width (type: int) Param[2]: height (type: int) Param[3]: format (type: int) -Function 385: GetFontDefault() (0 input parameters) +Function 385: ColorLerp() (3 input parameters) + Name: ColorLerp + Return type: Color + Description: Mix 2 Colors Together + Param[1]: color1 (type: Color) + Param[2]: color2 (type: Color) + Param[3]: d (type: float) +Function 386: GetFontDefault() (0 input parameters) Name: GetFontDefault Return type: Font Description: Get the default Font No input parameters -Function 386: LoadFont() (1 input parameters) +Function 387: LoadFont() (1 input parameters) Name: LoadFont Return type: Font Description: Load font from file into GPU memory (VRAM) Param[1]: fileName (type: const char *) -Function 387: LoadFontEx() (4 input parameters) +Function 388: LoadFontEx() (4 input parameters) Name: LoadFontEx Return type: Font - Description: Load font from file with extended parameters, use NULL for codepoints and 0 for codepointCount to load the default character setFont + Description: Load font from file with extended parameters, use NULL for codepoints and 0 for codepointCount to load the default character set, font size is provided in pixels height Param[1]: fileName (type: const char *) Param[2]: fontSize (type: int) Param[3]: codepoints (type: int *) Param[4]: codepointCount (type: int) -Function 388: LoadFontFromImage() (3 input parameters) +Function 389: LoadFontFromImage() (3 input parameters) Name: LoadFontFromImage Return type: Font Description: Load font from Image (XNA style) Param[1]: image (type: Image) Param[2]: key (type: Color) Param[3]: firstChar (type: int) -Function 389: LoadFontFromMemory() (6 input parameters) +Function 390: LoadFontFromMemory() (6 input parameters) Name: LoadFontFromMemory Return type: Font Description: Load font from memory buffer, fileType refers to extension: i.e. '.ttf' @@ -3428,12 +3435,12 @@ Function 389: LoadFontFromMemory() (6 input parameters) Param[4]: fontSize (type: int) Param[5]: codepoints (type: int *) Param[6]: codepointCount (type: int) -Function 390: IsFontReady() (1 input parameters) +Function 391: IsFontReady() (1 input parameters) Name: IsFontReady Return type: bool Description: Check if a font is ready Param[1]: font (type: Font) -Function 391: LoadFontData() (6 input parameters) +Function 392: LoadFontData() (6 input parameters) Name: LoadFontData Return type: GlyphInfo * Description: Load font data for further use @@ -3443,7 +3450,7 @@ Function 391: LoadFontData() (6 input parameters) Param[4]: codepoints (type: int *) Param[5]: codepointCount (type: int) Param[6]: type (type: int) -Function 392: GenImageFontAtlas() (6 input parameters) +Function 393: GenImageFontAtlas() (6 input parameters) Name: GenImageFontAtlas Return type: Image Description: Generate image font atlas using chars info @@ -3453,30 +3460,30 @@ Function 392: GenImageFontAtlas() (6 input parameters) Param[4]: fontSize (type: int) Param[5]: padding (type: int) Param[6]: packMethod (type: int) -Function 393: UnloadFontData() (2 input parameters) +Function 394: UnloadFontData() (2 input parameters) Name: UnloadFontData Return type: void Description: Unload font chars info data (RAM) Param[1]: glyphs (type: GlyphInfo *) Param[2]: glyphCount (type: int) -Function 394: UnloadFont() (1 input parameters) +Function 395: UnloadFont() (1 input parameters) Name: UnloadFont Return type: void Description: Unload font from GPU memory (VRAM) Param[1]: font (type: Font) -Function 395: ExportFontAsCode() (2 input parameters) +Function 396: ExportFontAsCode() (2 input parameters) Name: ExportFontAsCode Return type: bool Description: Export font as code file, returns true on success Param[1]: font (type: Font) Param[2]: fileName (type: const char *) -Function 396: DrawFPS() (2 input parameters) +Function 397: DrawFPS() (2 input parameters) Name: DrawFPS Return type: void Description: Draw current FPS Param[1]: posX (type: int) Param[2]: posY (type: int) -Function 397: DrawText() (5 input parameters) +Function 398: DrawText() (5 input parameters) Name: DrawText Return type: void Description: Draw text (using default font) @@ -3485,7 +3492,7 @@ Function 397: DrawText() (5 input parameters) Param[3]: posY (type: int) Param[4]: fontSize (type: int) Param[5]: color (type: Color) -Function 398: DrawTextEx() (6 input parameters) +Function 399: DrawTextEx() (6 input parameters) Name: DrawTextEx Return type: void Description: Draw text using font and additional parameters @@ -3495,7 +3502,7 @@ Function 398: DrawTextEx() (6 input parameters) Param[4]: fontSize (type: float) Param[5]: spacing (type: float) Param[6]: tint (type: Color) -Function 399: DrawTextPro() (8 input parameters) +Function 400: DrawTextPro() (8 input parameters) Name: DrawTextPro Return type: void Description: Draw text using Font and pro parameters (rotation) @@ -3507,7 +3514,7 @@ Function 399: DrawTextPro() (8 input parameters) Param[6]: fontSize (type: float) Param[7]: spacing (type: float) Param[8]: tint (type: Color) -Function 400: DrawTextCodepoint() (5 input parameters) +Function 401: DrawTextCodepoint() (5 input parameters) Name: DrawTextCodepoint Return type: void Description: Draw one character (codepoint) @@ -3516,7 +3523,7 @@ Function 400: DrawTextCodepoint() (5 input parameters) Param[3]: position (type: Vector2) Param[4]: fontSize (type: float) Param[5]: tint (type: Color) -Function 401: DrawTextCodepoints() (7 input parameters) +Function 402: DrawTextCodepoints() (7 input parameters) Name: DrawTextCodepoints Return type: void Description: Draw multiple character (codepoint) @@ -3527,18 +3534,18 @@ Function 401: DrawTextCodepoints() (7 input parameters) Param[5]: fontSize (type: float) Param[6]: spacing (type: float) Param[7]: tint (type: Color) -Function 402: SetTextLineSpacing() (1 input parameters) +Function 403: SetTextLineSpacing() (1 input parameters) Name: SetTextLineSpacing Return type: void Description: Set vertical line spacing when drawing with line-breaks Param[1]: spacing (type: int) -Function 403: MeasureText() (2 input parameters) +Function 404: MeasureText() (2 input parameters) Name: MeasureText Return type: int Description: Measure string width for default font Param[1]: text (type: const char *) Param[2]: fontSize (type: int) -Function 404: MeasureTextEx() (4 input parameters) +Function 405: MeasureTextEx() (4 input parameters) Name: MeasureTextEx Return type: Vector2 Description: Measure string size for Font @@ -3546,195 +3553,195 @@ Function 404: MeasureTextEx() (4 input parameters) Param[2]: text (type: const char *) Param[3]: fontSize (type: float) Param[4]: spacing (type: float) -Function 405: GetGlyphIndex() (2 input parameters) +Function 406: GetGlyphIndex() (2 input parameters) Name: GetGlyphIndex Return type: int Description: Get glyph index position in font for a codepoint (unicode character), fallback to '?' if not found Param[1]: font (type: Font) Param[2]: codepoint (type: int) -Function 406: GetGlyphInfo() (2 input parameters) +Function 407: GetGlyphInfo() (2 input parameters) Name: GetGlyphInfo Return type: GlyphInfo Description: Get glyph font info data for a codepoint (unicode character), fallback to '?' if not found Param[1]: font (type: Font) Param[2]: codepoint (type: int) -Function 407: GetGlyphAtlasRec() (2 input parameters) +Function 408: GetGlyphAtlasRec() (2 input parameters) Name: GetGlyphAtlasRec Return type: Rectangle Description: Get glyph rectangle in font atlas for a codepoint (unicode character), fallback to '?' if not found Param[1]: font (type: Font) Param[2]: codepoint (type: int) -Function 408: LoadUTF8() (2 input parameters) +Function 409: LoadUTF8() (2 input parameters) Name: LoadUTF8 Return type: char * Description: Load UTF-8 text encoded from codepoints array Param[1]: codepoints (type: const int *) Param[2]: length (type: int) -Function 409: UnloadUTF8() (1 input parameters) +Function 410: UnloadUTF8() (1 input parameters) Name: UnloadUTF8 Return type: void Description: Unload UTF-8 text encoded from codepoints array Param[1]: text (type: char *) -Function 410: LoadCodepoints() (2 input parameters) +Function 411: LoadCodepoints() (2 input parameters) Name: LoadCodepoints Return type: int * Description: Load all codepoints from a UTF-8 text string, codepoints count returned by parameter Param[1]: text (type: const char *) Param[2]: count (type: int *) -Function 411: UnloadCodepoints() (1 input parameters) +Function 412: UnloadCodepoints() (1 input parameters) Name: UnloadCodepoints Return type: void Description: Unload codepoints data from memory Param[1]: codepoints (type: int *) -Function 412: GetCodepointCount() (1 input parameters) +Function 413: GetCodepointCount() (1 input parameters) Name: GetCodepointCount Return type: int Description: Get total number of codepoints in a UTF-8 encoded string Param[1]: text (type: const char *) -Function 413: GetCodepoint() (2 input parameters) +Function 414: GetCodepoint() (2 input parameters) Name: GetCodepoint Return type: int Description: Get next codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure Param[1]: text (type: const char *) Param[2]: codepointSize (type: int *) -Function 414: GetCodepointNext() (2 input parameters) +Function 415: GetCodepointNext() (2 input parameters) Name: GetCodepointNext Return type: int Description: Get next codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure Param[1]: text (type: const char *) Param[2]: codepointSize (type: int *) -Function 415: GetCodepointPrevious() (2 input parameters) +Function 416: GetCodepointPrevious() (2 input parameters) Name: GetCodepointPrevious Return type: int Description: Get previous codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure Param[1]: text (type: const char *) Param[2]: codepointSize (type: int *) -Function 416: CodepointToUTF8() (2 input parameters) +Function 417: CodepointToUTF8() (2 input parameters) Name: CodepointToUTF8 Return type: const char * Description: Encode one codepoint into UTF-8 byte array (array length returned as parameter) Param[1]: codepoint (type: int) Param[2]: utf8Size (type: int *) -Function 417: TextCopy() (2 input parameters) +Function 418: TextCopy() (2 input parameters) Name: TextCopy Return type: int Description: Copy one string to another, returns bytes copied Param[1]: dst (type: char *) Param[2]: src (type: const char *) -Function 418: TextIsEqual() (2 input parameters) +Function 419: TextIsEqual() (2 input parameters) Name: TextIsEqual Return type: bool Description: Check if two text string are equal Param[1]: text1 (type: const char *) Param[2]: text2 (type: const char *) -Function 419: TextLength() (1 input parameters) +Function 420: TextLength() (1 input parameters) Name: TextLength Return type: unsigned int Description: Get text length, checks for '\0' ending Param[1]: text (type: const char *) -Function 420: TextFormat() (2 input parameters) +Function 421: TextFormat() (2 input parameters) Name: TextFormat Return type: const char * Description: Text formatting with variables (sprintf() style) Param[1]: text (type: const char *) Param[2]: args (type: ...) -Function 421: TextSubtext() (3 input parameters) +Function 422: TextSubtext() (3 input parameters) Name: TextSubtext Return type: const char * Description: Get a piece of a text string Param[1]: text (type: const char *) Param[2]: position (type: int) Param[3]: length (type: int) -Function 422: TextReplace() (3 input parameters) +Function 423: TextReplace() (3 input parameters) Name: TextReplace Return type: char * Description: Replace text string (WARNING: memory must be freed!) Param[1]: text (type: const char *) Param[2]: replace (type: const char *) Param[3]: by (type: const char *) -Function 423: TextInsert() (3 input parameters) +Function 424: TextInsert() (3 input parameters) Name: TextInsert Return type: char * Description: Insert text in a position (WARNING: memory must be freed!) Param[1]: text (type: const char *) Param[2]: insert (type: const char *) Param[3]: position (type: int) -Function 424: TextJoin() (3 input parameters) +Function 425: TextJoin() (3 input parameters) Name: TextJoin Return type: const char * Description: Join text strings with delimiter Param[1]: textList (type: const char **) Param[2]: count (type: int) Param[3]: delimiter (type: const char *) -Function 425: TextSplit() (3 input parameters) +Function 426: TextSplit() (3 input parameters) Name: TextSplit Return type: const char ** Description: Split text into multiple strings Param[1]: text (type: const char *) Param[2]: delimiter (type: char) Param[3]: count (type: int *) -Function 426: TextAppend() (3 input parameters) +Function 427: TextAppend() (3 input parameters) Name: TextAppend Return type: void Description: Append text at specific position and move cursor! Param[1]: text (type: char *) Param[2]: append (type: const char *) Param[3]: position (type: int *) -Function 427: TextFindIndex() (2 input parameters) +Function 428: TextFindIndex() (2 input parameters) Name: TextFindIndex Return type: int Description: Find first text occurrence within a string Param[1]: text (type: const char *) Param[2]: find (type: const char *) -Function 428: TextToUpper() (1 input parameters) +Function 429: TextToUpper() (1 input parameters) Name: TextToUpper Return type: const char * Description: Get upper case version of provided string Param[1]: text (type: const char *) -Function 429: TextToLower() (1 input parameters) +Function 430: TextToLower() (1 input parameters) Name: TextToLower Return type: const char * Description: Get lower case version of provided string Param[1]: text (type: const char *) -Function 430: TextToPascal() (1 input parameters) +Function 431: TextToPascal() (1 input parameters) Name: TextToPascal Return type: const char * Description: Get Pascal case notation version of provided string Param[1]: text (type: const char *) -Function 431: TextToSnake() (1 input parameters) +Function 432: TextToSnake() (1 input parameters) Name: TextToSnake Return type: const char * Description: Get Snake case notation version of provided string Param[1]: text (type: const char *) -Function 432: TextToCamel() (1 input parameters) +Function 433: TextToCamel() (1 input parameters) Name: TextToCamel Return type: const char * Description: Get Camel case notation version of provided string Param[1]: text (type: const char *) -Function 433: TextToInteger() (1 input parameters) +Function 434: TextToInteger() (1 input parameters) Name: TextToInteger Return type: int Description: Get integer value from text (negative values not supported) Param[1]: text (type: const char *) -Function 434: TextToFloat() (1 input parameters) +Function 435: TextToFloat() (1 input parameters) Name: TextToFloat Return type: float Description: Get float value from text (negative values not supported) Param[1]: text (type: const char *) -Function 435: DrawLine3D() (3 input parameters) +Function 436: DrawLine3D() (3 input parameters) Name: DrawLine3D Return type: void Description: Draw a line in 3D world space Param[1]: startPos (type: Vector3) Param[2]: endPos (type: Vector3) Param[3]: color (type: Color) -Function 436: DrawPoint3D() (2 input parameters) +Function 437: DrawPoint3D() (2 input parameters) Name: DrawPoint3D Return type: void Description: Draw a point in 3D space, actually a small line Param[1]: position (type: Vector3) Param[2]: color (type: Color) -Function 437: DrawCircle3D() (5 input parameters) +Function 438: DrawCircle3D() (5 input parameters) Name: DrawCircle3D Return type: void Description: Draw a circle in 3D world space @@ -3743,7 +3750,7 @@ Function 437: DrawCircle3D() (5 input parameters) Param[3]: rotationAxis (type: Vector3) Param[4]: rotationAngle (type: float) Param[5]: color (type: Color) -Function 438: DrawTriangle3D() (4 input parameters) +Function 439: DrawTriangle3D() (4 input parameters) Name: DrawTriangle3D Return type: void Description: Draw a color-filled triangle (vertex in counter-clockwise order!) @@ -3751,14 +3758,14 @@ Function 438: DrawTriangle3D() (4 input parameters) Param[2]: v2 (type: Vector3) Param[3]: v3 (type: Vector3) Param[4]: color (type: Color) -Function 439: DrawTriangleStrip3D() (3 input parameters) +Function 440: DrawTriangleStrip3D() (3 input parameters) Name: DrawTriangleStrip3D Return type: void Description: Draw a triangle strip defined by points Param[1]: points (type: const Vector3 *) Param[2]: pointCount (type: int) Param[3]: color (type: Color) -Function 440: DrawCube() (5 input parameters) +Function 441: DrawCube() (5 input parameters) Name: DrawCube Return type: void Description: Draw cube @@ -3767,14 +3774,14 @@ Function 440: DrawCube() (5 input parameters) Param[3]: height (type: float) Param[4]: length (type: float) Param[5]: color (type: Color) -Function 441: DrawCubeV() (3 input parameters) +Function 442: DrawCubeV() (3 input parameters) Name: DrawCubeV Return type: void Description: Draw cube (Vector version) Param[1]: position (type: Vector3) Param[2]: size (type: Vector3) Param[3]: color (type: Color) -Function 442: DrawCubeWires() (5 input parameters) +Function 443: DrawCubeWires() (5 input parameters) Name: DrawCubeWires Return type: void Description: Draw cube wires @@ -3783,21 +3790,21 @@ Function 442: DrawCubeWires() (5 input parameters) Param[3]: height (type: float) Param[4]: length (type: float) Param[5]: color (type: Color) -Function 443: DrawCubeWiresV() (3 input parameters) +Function 444: DrawCubeWiresV() (3 input parameters) Name: DrawCubeWiresV Return type: void Description: Draw cube wires (Vector version) Param[1]: position (type: Vector3) Param[2]: size (type: Vector3) Param[3]: color (type: Color) -Function 444: DrawSphere() (3 input parameters) +Function 445: DrawSphere() (3 input parameters) Name: DrawSphere Return type: void Description: Draw sphere Param[1]: centerPos (type: Vector3) Param[2]: radius (type: float) Param[3]: color (type: Color) -Function 445: DrawSphereEx() (5 input parameters) +Function 446: DrawSphereEx() (5 input parameters) Name: DrawSphereEx Return type: void Description: Draw sphere with extended parameters @@ -3806,7 +3813,7 @@ Function 445: DrawSphereEx() (5 input parameters) Param[3]: rings (type: int) Param[4]: slices (type: int) Param[5]: color (type: Color) -Function 446: DrawSphereWires() (5 input parameters) +Function 447: DrawSphereWires() (5 input parameters) Name: DrawSphereWires Return type: void Description: Draw sphere wires @@ -3815,7 +3822,7 @@ Function 446: DrawSphereWires() (5 input parameters) Param[3]: rings (type: int) Param[4]: slices (type: int) Param[5]: color (type: Color) -Function 447: DrawCylinder() (6 input parameters) +Function 448: DrawCylinder() (6 input parameters) Name: DrawCylinder Return type: void Description: Draw a cylinder/cone @@ -3825,7 +3832,7 @@ Function 447: DrawCylinder() (6 input parameters) Param[4]: height (type: float) Param[5]: slices (type: int) Param[6]: color (type: Color) -Function 448: DrawCylinderEx() (6 input parameters) +Function 449: DrawCylinderEx() (6 input parameters) Name: DrawCylinderEx Return type: void Description: Draw a cylinder with base at startPos and top at endPos @@ -3835,7 +3842,7 @@ Function 448: DrawCylinderEx() (6 input parameters) Param[4]: endRadius (type: float) Param[5]: sides (type: int) Param[6]: color (type: Color) -Function 449: DrawCylinderWires() (6 input parameters) +Function 450: DrawCylinderWires() (6 input parameters) Name: DrawCylinderWires Return type: void Description: Draw a cylinder/cone wires @@ -3845,7 +3852,7 @@ Function 449: DrawCylinderWires() (6 input parameters) Param[4]: height (type: float) Param[5]: slices (type: int) Param[6]: color (type: Color) -Function 450: DrawCylinderWiresEx() (6 input parameters) +Function 451: DrawCylinderWiresEx() (6 input parameters) Name: DrawCylinderWiresEx Return type: void Description: Draw a cylinder wires with base at startPos and top at endPos @@ -3855,7 +3862,7 @@ Function 450: DrawCylinderWiresEx() (6 input parameters) Param[4]: endRadius (type: float) Param[5]: sides (type: int) Param[6]: color (type: Color) -Function 451: DrawCapsule() (6 input parameters) +Function 452: DrawCapsule() (6 input parameters) Name: DrawCapsule Return type: void Description: Draw a capsule with the center of its sphere caps at startPos and endPos @@ -3865,7 +3872,7 @@ Function 451: DrawCapsule() (6 input parameters) Param[4]: slices (type: int) Param[5]: rings (type: int) Param[6]: color (type: Color) -Function 452: DrawCapsuleWires() (6 input parameters) +Function 453: DrawCapsuleWires() (6 input parameters) Name: DrawCapsuleWires Return type: void Description: Draw capsule wireframe with the center of its sphere caps at startPos and endPos @@ -3875,51 +3882,51 @@ Function 452: DrawCapsuleWires() (6 input parameters) Param[4]: slices (type: int) Param[5]: rings (type: int) Param[6]: color (type: Color) -Function 453: DrawPlane() (3 input parameters) +Function 454: DrawPlane() (3 input parameters) Name: DrawPlane Return type: void Description: Draw a plane XZ Param[1]: centerPos (type: Vector3) Param[2]: size (type: Vector2) Param[3]: color (type: Color) -Function 454: DrawRay() (2 input parameters) +Function 455: DrawRay() (2 input parameters) Name: DrawRay Return type: void Description: Draw a ray line Param[1]: ray (type: Ray) Param[2]: color (type: Color) -Function 455: DrawGrid() (2 input parameters) +Function 456: DrawGrid() (2 input parameters) Name: DrawGrid Return type: void Description: Draw a grid (centered at (0, 0, 0)) Param[1]: slices (type: int) Param[2]: spacing (type: float) -Function 456: LoadModel() (1 input parameters) +Function 457: LoadModel() (1 input parameters) Name: LoadModel Return type: Model Description: Load model from files (meshes and materials) Param[1]: fileName (type: const char *) -Function 457: LoadModelFromMesh() (1 input parameters) +Function 458: LoadModelFromMesh() (1 input parameters) Name: LoadModelFromMesh Return type: Model Description: Load model from generated mesh (default material) Param[1]: mesh (type: Mesh) -Function 458: IsModelReady() (1 input parameters) +Function 459: IsModelReady() (1 input parameters) Name: IsModelReady Return type: bool Description: Check if a model is ready Param[1]: model (type: Model) -Function 459: UnloadModel() (1 input parameters) +Function 460: UnloadModel() (1 input parameters) Name: UnloadModel Return type: void Description: Unload model (including meshes) from memory (RAM and/or VRAM) Param[1]: model (type: Model) -Function 460: GetModelBoundingBox() (1 input parameters) +Function 461: GetModelBoundingBox() (1 input parameters) Name: GetModelBoundingBox Return type: BoundingBox Description: Compute model bounding box limits (considers all meshes) Param[1]: model (type: Model) -Function 461: DrawModel() (4 input parameters) +Function 462: DrawModel() (4 input parameters) Name: DrawModel Return type: void Description: Draw a model (with texture if set) @@ -3927,7 +3934,7 @@ Function 461: DrawModel() (4 input parameters) Param[2]: position (type: Vector3) Param[3]: scale (type: float) Param[4]: tint (type: Color) -Function 462: DrawModelEx() (6 input parameters) +Function 463: DrawModelEx() (6 input parameters) Name: DrawModelEx Return type: void Description: Draw a model with extended parameters @@ -3937,7 +3944,7 @@ Function 462: DrawModelEx() (6 input parameters) Param[4]: rotationAngle (type: float) Param[5]: scale (type: Vector3) Param[6]: tint (type: Color) -Function 463: DrawModelWires() (4 input parameters) +Function 464: DrawModelWires() (4 input parameters) Name: DrawModelWires Return type: void Description: Draw a model wires (with texture if set) @@ -3945,7 +3952,7 @@ Function 463: DrawModelWires() (4 input parameters) Param[2]: position (type: Vector3) Param[3]: scale (type: float) Param[4]: tint (type: Color) -Function 464: DrawModelWiresEx() (6 input parameters) +Function 465: DrawModelWiresEx() (6 input parameters) Name: DrawModelWiresEx Return type: void Description: Draw a model wires (with texture if set) with extended parameters @@ -3955,7 +3962,7 @@ Function 464: DrawModelWiresEx() (6 input parameters) Param[4]: rotationAngle (type: float) Param[5]: scale (type: Vector3) Param[6]: tint (type: Color) -Function 465: DrawModelPoints() (4 input parameters) +Function 466: DrawModelPoints() (4 input parameters) Name: DrawModelPoints Return type: void Description: Draw a model as points @@ -3963,7 +3970,7 @@ Function 465: DrawModelPoints() (4 input parameters) Param[2]: position (type: Vector3) Param[3]: scale (type: float) Param[4]: tint (type: Color) -Function 466: DrawModelPointsEx() (6 input parameters) +Function 467: DrawModelPointsEx() (6 input parameters) Name: DrawModelPointsEx Return type: void Description: Draw a model as points with extended parameters @@ -3973,13 +3980,13 @@ Function 466: DrawModelPointsEx() (6 input parameters) Param[4]: rotationAngle (type: float) Param[5]: scale (type: Vector3) Param[6]: tint (type: Color) -Function 467: DrawBoundingBox() (2 input parameters) +Function 468: DrawBoundingBox() (2 input parameters) Name: DrawBoundingBox Return type: void Description: Draw bounding box (wires) Param[1]: box (type: BoundingBox) Param[2]: color (type: Color) -Function 468: DrawBillboard() (5 input parameters) +Function 469: DrawBillboard() (5 input parameters) Name: DrawBillboard Return type: void Description: Draw a billboard texture @@ -3988,7 +3995,7 @@ Function 468: DrawBillboard() (5 input parameters) Param[3]: position (type: Vector3) Param[4]: scale (type: float) Param[5]: tint (type: Color) -Function 469: DrawBillboardRec() (6 input parameters) +Function 470: DrawBillboardRec() (6 input parameters) Name: DrawBillboardRec Return type: void Description: Draw a billboard texture defined by source @@ -3998,7 +4005,7 @@ Function 469: DrawBillboardRec() (6 input parameters) Param[4]: position (type: Vector3) Param[5]: size (type: Vector2) Param[6]: tint (type: Color) -Function 470: DrawBillboardPro() (9 input parameters) +Function 471: DrawBillboardPro() (9 input parameters) Name: DrawBillboardPro Return type: void Description: Draw a billboard texture defined by source and rotation @@ -4011,13 +4018,13 @@ Function 470: DrawBillboardPro() (9 input parameters) Param[7]: origin (type: Vector2) Param[8]: rotation (type: float) Param[9]: tint (type: Color) -Function 471: UploadMesh() (2 input parameters) +Function 472: UploadMesh() (2 input parameters) Name: UploadMesh Return type: void Description: Upload mesh vertex data in GPU and provide VAO/VBO ids Param[1]: mesh (type: Mesh *) Param[2]: dynamic (type: bool) -Function 472: UpdateMeshBuffer() (5 input parameters) +Function 473: UpdateMeshBuffer() (5 input parameters) Name: UpdateMeshBuffer Return type: void Description: Update mesh vertex data in GPU for a specific buffer index @@ -4026,19 +4033,19 @@ Function 472: UpdateMeshBuffer() (5 input parameters) Param[3]: data (type: const void *) Param[4]: dataSize (type: int) Param[5]: offset (type: int) -Function 473: UnloadMesh() (1 input parameters) +Function 474: UnloadMesh() (1 input parameters) Name: UnloadMesh Return type: void Description: Unload mesh data from CPU and GPU Param[1]: mesh (type: Mesh) -Function 474: DrawMesh() (3 input parameters) +Function 475: DrawMesh() (3 input parameters) Name: DrawMesh Return type: void Description: Draw a 3d mesh with material and transform Param[1]: mesh (type: Mesh) Param[2]: material (type: Material) Param[3]: transform (type: Matrix) -Function 475: DrawMeshInstanced() (4 input parameters) +Function 476: DrawMeshInstanced() (4 input parameters) Name: DrawMeshInstanced Return type: void Description: Draw multiple mesh instances with material and different transforms @@ -4046,35 +4053,35 @@ Function 475: DrawMeshInstanced() (4 input parameters) Param[2]: material (type: Material) Param[3]: transforms (type: const Matrix *) Param[4]: instances (type: int) -Function 476: GetMeshBoundingBox() (1 input parameters) +Function 477: GetMeshBoundingBox() (1 input parameters) Name: GetMeshBoundingBox Return type: BoundingBox Description: Compute mesh bounding box limits Param[1]: mesh (type: Mesh) -Function 477: GenMeshTangents() (1 input parameters) +Function 478: GenMeshTangents() (1 input parameters) Name: GenMeshTangents Return type: void Description: Compute mesh tangents Param[1]: mesh (type: Mesh *) -Function 478: ExportMesh() (2 input parameters) +Function 479: ExportMesh() (2 input parameters) Name: ExportMesh Return type: bool Description: Export mesh data to file, returns true on success Param[1]: mesh (type: Mesh) Param[2]: fileName (type: const char *) -Function 479: ExportMeshAsCode() (2 input parameters) +Function 480: ExportMeshAsCode() (2 input parameters) Name: ExportMeshAsCode Return type: bool Description: Export mesh as code file (.h) defining multiple arrays of vertex attributes Param[1]: mesh (type: Mesh) Param[2]: fileName (type: const char *) -Function 480: GenMeshPoly() (2 input parameters) +Function 481: GenMeshPoly() (2 input parameters) Name: GenMeshPoly Return type: Mesh Description: Generate polygonal mesh Param[1]: sides (type: int) Param[2]: radius (type: float) -Function 481: GenMeshPlane() (4 input parameters) +Function 482: GenMeshPlane() (4 input parameters) Name: GenMeshPlane Return type: Mesh Description: Generate plane mesh (with subdivisions) @@ -4082,42 +4089,42 @@ Function 481: GenMeshPlane() (4 input parameters) Param[2]: length (type: float) Param[3]: resX (type: int) Param[4]: resZ (type: int) -Function 482: GenMeshCube() (3 input parameters) +Function 483: GenMeshCube() (3 input parameters) Name: GenMeshCube Return type: Mesh Description: Generate cuboid mesh Param[1]: width (type: float) Param[2]: height (type: float) Param[3]: length (type: float) -Function 483: GenMeshSphere() (3 input parameters) +Function 484: GenMeshSphere() (3 input parameters) Name: GenMeshSphere Return type: Mesh Description: Generate sphere mesh (standard sphere) Param[1]: radius (type: float) Param[2]: rings (type: int) Param[3]: slices (type: int) -Function 484: GenMeshHemiSphere() (3 input parameters) +Function 485: GenMeshHemiSphere() (3 input parameters) Name: GenMeshHemiSphere Return type: Mesh Description: Generate half-sphere mesh (no bottom cap) Param[1]: radius (type: float) Param[2]: rings (type: int) Param[3]: slices (type: int) -Function 485: GenMeshCylinder() (3 input parameters) +Function 486: GenMeshCylinder() (3 input parameters) Name: GenMeshCylinder Return type: Mesh Description: Generate cylinder mesh Param[1]: radius (type: float) Param[2]: height (type: float) Param[3]: slices (type: int) -Function 486: GenMeshCone() (3 input parameters) +Function 487: GenMeshCone() (3 input parameters) Name: GenMeshCone Return type: Mesh Description: Generate cone/pyramid mesh Param[1]: radius (type: float) Param[2]: height (type: float) Param[3]: slices (type: int) -Function 487: GenMeshTorus() (4 input parameters) +Function 488: GenMeshTorus() (4 input parameters) Name: GenMeshTorus Return type: Mesh Description: Generate torus mesh @@ -4125,7 +4132,7 @@ Function 487: GenMeshTorus() (4 input parameters) Param[2]: size (type: float) Param[3]: radSeg (type: int) Param[4]: sides (type: int) -Function 488: GenMeshKnot() (4 input parameters) +Function 489: GenMeshKnot() (4 input parameters) Name: GenMeshKnot Return type: Mesh Description: Generate trefoil knot mesh @@ -4133,84 +4140,84 @@ Function 488: GenMeshKnot() (4 input parameters) Param[2]: size (type: float) Param[3]: radSeg (type: int) Param[4]: sides (type: int) -Function 489: GenMeshHeightmap() (2 input parameters) +Function 490: GenMeshHeightmap() (2 input parameters) Name: GenMeshHeightmap Return type: Mesh Description: Generate heightmap mesh from image data Param[1]: heightmap (type: Image) Param[2]: size (type: Vector3) -Function 490: GenMeshCubicmap() (2 input parameters) +Function 491: GenMeshCubicmap() (2 input parameters) Name: GenMeshCubicmap Return type: Mesh Description: Generate cubes-based map mesh from image data Param[1]: cubicmap (type: Image) Param[2]: cubeSize (type: Vector3) -Function 491: LoadMaterials() (2 input parameters) +Function 492: LoadMaterials() (2 input parameters) Name: LoadMaterials Return type: Material * Description: Load materials from model file Param[1]: fileName (type: const char *) Param[2]: materialCount (type: int *) -Function 492: LoadMaterialDefault() (0 input parameters) +Function 493: LoadMaterialDefault() (0 input parameters) Name: LoadMaterialDefault Return type: Material Description: Load default material (Supports: DIFFUSE, SPECULAR, NORMAL maps) No input parameters -Function 493: IsMaterialReady() (1 input parameters) +Function 494: IsMaterialReady() (1 input parameters) Name: IsMaterialReady Return type: bool Description: Check if a material is ready Param[1]: material (type: Material) -Function 494: UnloadMaterial() (1 input parameters) +Function 495: UnloadMaterial() (1 input parameters) Name: UnloadMaterial Return type: void Description: Unload material from GPU memory (VRAM) Param[1]: material (type: Material) -Function 495: SetMaterialTexture() (3 input parameters) +Function 496: SetMaterialTexture() (3 input parameters) Name: SetMaterialTexture Return type: void Description: Set texture for a material map type (MATERIAL_MAP_DIFFUSE, MATERIAL_MAP_SPECULAR...) Param[1]: material (type: Material *) Param[2]: mapType (type: int) Param[3]: texture (type: Texture2D) -Function 496: SetModelMeshMaterial() (3 input parameters) +Function 497: SetModelMeshMaterial() (3 input parameters) Name: SetModelMeshMaterial Return type: void Description: Set material for a mesh Param[1]: model (type: Model *) Param[2]: meshId (type: int) Param[3]: materialId (type: int) -Function 497: LoadModelAnimations() (2 input parameters) +Function 498: LoadModelAnimations() (2 input parameters) Name: LoadModelAnimations Return type: ModelAnimation * Description: Load model animations from file Param[1]: fileName (type: const char *) Param[2]: animCount (type: int *) -Function 498: UpdateModelAnimation() (3 input parameters) +Function 499: UpdateModelAnimation() (3 input parameters) Name: UpdateModelAnimation Return type: void Description: Update model animation pose Param[1]: model (type: Model) Param[2]: anim (type: ModelAnimation) Param[3]: frame (type: int) -Function 499: UnloadModelAnimation() (1 input parameters) +Function 500: UnloadModelAnimation() (1 input parameters) Name: UnloadModelAnimation Return type: void Description: Unload animation data Param[1]: anim (type: ModelAnimation) -Function 500: UnloadModelAnimations() (2 input parameters) +Function 501: UnloadModelAnimations() (2 input parameters) Name: UnloadModelAnimations Return type: void Description: Unload animation array data Param[1]: animations (type: ModelAnimation *) Param[2]: animCount (type: int) -Function 501: IsModelAnimationValid() (2 input parameters) +Function 502: IsModelAnimationValid() (2 input parameters) Name: IsModelAnimationValid Return type: bool Description: Check model animation skeleton match Param[1]: model (type: Model) Param[2]: anim (type: ModelAnimation) -Function 502: CheckCollisionSpheres() (4 input parameters) +Function 503: CheckCollisionSpheres() (4 input parameters) Name: CheckCollisionSpheres Return type: bool Description: Check collision between two spheres @@ -4218,40 +4225,40 @@ Function 502: CheckCollisionSpheres() (4 input parameters) Param[2]: radius1 (type: float) Param[3]: center2 (type: Vector3) Param[4]: radius2 (type: float) -Function 503: CheckCollisionBoxes() (2 input parameters) +Function 504: CheckCollisionBoxes() (2 input parameters) Name: CheckCollisionBoxes Return type: bool Description: Check collision between two bounding boxes Param[1]: box1 (type: BoundingBox) Param[2]: box2 (type: BoundingBox) -Function 504: CheckCollisionBoxSphere() (3 input parameters) +Function 505: CheckCollisionBoxSphere() (3 input parameters) Name: CheckCollisionBoxSphere Return type: bool Description: Check collision between box and sphere Param[1]: box (type: BoundingBox) Param[2]: center (type: Vector3) Param[3]: radius (type: float) -Function 505: GetRayCollisionSphere() (3 input parameters) +Function 506: GetRayCollisionSphere() (3 input parameters) Name: GetRayCollisionSphere Return type: RayCollision Description: Get collision info between ray and sphere Param[1]: ray (type: Ray) Param[2]: center (type: Vector3) Param[3]: radius (type: float) -Function 506: GetRayCollisionBox() (2 input parameters) +Function 507: GetRayCollisionBox() (2 input parameters) Name: GetRayCollisionBox Return type: RayCollision Description: Get collision info between ray and box Param[1]: ray (type: Ray) Param[2]: box (type: BoundingBox) -Function 507: GetRayCollisionMesh() (3 input parameters) +Function 508: GetRayCollisionMesh() (3 input parameters) Name: GetRayCollisionMesh Return type: RayCollision Description: Get collision info between ray and mesh Param[1]: ray (type: Ray) Param[2]: mesh (type: Mesh) Param[3]: transform (type: Matrix) -Function 508: GetRayCollisionTriangle() (4 input parameters) +Function 509: GetRayCollisionTriangle() (4 input parameters) Name: GetRayCollisionTriangle Return type: RayCollision Description: Get collision info between ray and triangle @@ -4259,7 +4266,7 @@ Function 508: GetRayCollisionTriangle() (4 input parameters) Param[2]: p1 (type: Vector3) Param[3]: p2 (type: Vector3) Param[4]: p3 (type: Vector3) -Function 509: GetRayCollisionQuad() (5 input parameters) +Function 510: GetRayCollisionQuad() (5 input parameters) Name: GetRayCollisionQuad Return type: RayCollision Description: Get collision info between ray and quad @@ -4268,158 +4275,158 @@ Function 509: GetRayCollisionQuad() (5 input parameters) Param[3]: p2 (type: Vector3) Param[4]: p3 (type: Vector3) Param[5]: p4 (type: Vector3) -Function 510: InitAudioDevice() (0 input parameters) +Function 511: InitAudioDevice() (0 input parameters) Name: InitAudioDevice Return type: void Description: Initialize audio device and context No input parameters -Function 511: CloseAudioDevice() (0 input parameters) +Function 512: CloseAudioDevice() (0 input parameters) Name: CloseAudioDevice Return type: void Description: Close the audio device and context No input parameters -Function 512: IsAudioDeviceReady() (0 input parameters) +Function 513: IsAudioDeviceReady() (0 input parameters) Name: IsAudioDeviceReady Return type: bool Description: Check if audio device has been initialized successfully No input parameters -Function 513: SetMasterVolume() (1 input parameters) +Function 514: SetMasterVolume() (1 input parameters) Name: SetMasterVolume Return type: void Description: Set master volume (listener) Param[1]: volume (type: float) -Function 514: GetMasterVolume() (0 input parameters) +Function 515: GetMasterVolume() (0 input parameters) Name: GetMasterVolume Return type: float Description: Get master volume (listener) No input parameters -Function 515: LoadWave() (1 input parameters) +Function 516: LoadWave() (1 input parameters) Name: LoadWave Return type: Wave Description: Load wave data from file Param[1]: fileName (type: const char *) -Function 516: LoadWaveFromMemory() (3 input parameters) +Function 517: LoadWaveFromMemory() (3 input parameters) Name: LoadWaveFromMemory Return type: Wave Description: Load wave from memory buffer, fileType refers to extension: i.e. '.wav' Param[1]: fileType (type: const char *) Param[2]: fileData (type: const unsigned char *) Param[3]: dataSize (type: int) -Function 517: IsWaveReady() (1 input parameters) +Function 518: IsWaveReady() (1 input parameters) Name: IsWaveReady Return type: bool Description: Checks if wave data is ready Param[1]: wave (type: Wave) -Function 518: LoadSound() (1 input parameters) +Function 519: LoadSound() (1 input parameters) Name: LoadSound Return type: Sound Description: Load sound from file Param[1]: fileName (type: const char *) -Function 519: LoadSoundFromWave() (1 input parameters) +Function 520: LoadSoundFromWave() (1 input parameters) Name: LoadSoundFromWave Return type: Sound Description: Load sound from wave data Param[1]: wave (type: Wave) -Function 520: LoadSoundAlias() (1 input parameters) +Function 521: LoadSoundAlias() (1 input parameters) Name: LoadSoundAlias Return type: Sound Description: Create a new sound that shares the same sample data as the source sound, does not own the sound data Param[1]: source (type: Sound) -Function 521: IsSoundReady() (1 input parameters) +Function 522: IsSoundReady() (1 input parameters) Name: IsSoundReady Return type: bool Description: Checks if a sound is ready Param[1]: sound (type: Sound) -Function 522: UpdateSound() (3 input parameters) +Function 523: UpdateSound() (3 input parameters) Name: UpdateSound Return type: void Description: Update sound buffer with new data Param[1]: sound (type: Sound) Param[2]: data (type: const void *) Param[3]: sampleCount (type: int) -Function 523: UnloadWave() (1 input parameters) +Function 524: UnloadWave() (1 input parameters) Name: UnloadWave Return type: void Description: Unload wave data Param[1]: wave (type: Wave) -Function 524: UnloadSound() (1 input parameters) +Function 525: UnloadSound() (1 input parameters) Name: UnloadSound Return type: void Description: Unload sound Param[1]: sound (type: Sound) -Function 525: UnloadSoundAlias() (1 input parameters) +Function 526: UnloadSoundAlias() (1 input parameters) Name: UnloadSoundAlias Return type: void Description: Unload a sound alias (does not deallocate sample data) Param[1]: alias (type: Sound) -Function 526: ExportWave() (2 input parameters) +Function 527: ExportWave() (2 input parameters) Name: ExportWave Return type: bool Description: Export wave data to file, returns true on success Param[1]: wave (type: Wave) Param[2]: fileName (type: const char *) -Function 527: ExportWaveAsCode() (2 input parameters) +Function 528: ExportWaveAsCode() (2 input parameters) Name: ExportWaveAsCode Return type: bool Description: Export wave sample data to code (.h), returns true on success Param[1]: wave (type: Wave) Param[2]: fileName (type: const char *) -Function 528: PlaySound() (1 input parameters) +Function 529: PlaySound() (1 input parameters) Name: PlaySound Return type: void Description: Play a sound Param[1]: sound (type: Sound) -Function 529: StopSound() (1 input parameters) +Function 530: StopSound() (1 input parameters) Name: StopSound Return type: void Description: Stop playing a sound Param[1]: sound (type: Sound) -Function 530: PauseSound() (1 input parameters) +Function 531: PauseSound() (1 input parameters) Name: PauseSound Return type: void Description: Pause a sound Param[1]: sound (type: Sound) -Function 531: ResumeSound() (1 input parameters) +Function 532: ResumeSound() (1 input parameters) Name: ResumeSound Return type: void Description: Resume a paused sound Param[1]: sound (type: Sound) -Function 532: IsSoundPlaying() (1 input parameters) +Function 533: IsSoundPlaying() (1 input parameters) Name: IsSoundPlaying Return type: bool Description: Check if a sound is currently playing Param[1]: sound (type: Sound) -Function 533: SetSoundVolume() (2 input parameters) +Function 534: SetSoundVolume() (2 input parameters) Name: SetSoundVolume Return type: void Description: Set volume for a sound (1.0 is max level) Param[1]: sound (type: Sound) Param[2]: volume (type: float) -Function 534: SetSoundPitch() (2 input parameters) +Function 535: SetSoundPitch() (2 input parameters) Name: SetSoundPitch Return type: void Description: Set pitch for a sound (1.0 is base level) Param[1]: sound (type: Sound) Param[2]: pitch (type: float) -Function 535: SetSoundPan() (2 input parameters) +Function 536: SetSoundPan() (2 input parameters) Name: SetSoundPan Return type: void Description: Set pan for a sound (0.5 is center) Param[1]: sound (type: Sound) Param[2]: pan (type: float) -Function 536: WaveCopy() (1 input parameters) +Function 537: WaveCopy() (1 input parameters) Name: WaveCopy Return type: Wave Description: Copy a wave to a new wave Param[1]: wave (type: Wave) -Function 537: WaveCrop() (3 input parameters) +Function 538: WaveCrop() (3 input parameters) Name: WaveCrop Return type: void Description: Crop a wave to defined frames range Param[1]: wave (type: Wave *) Param[2]: initFrame (type: int) Param[3]: finalFrame (type: int) -Function 538: WaveFormat() (4 input parameters) +Function 539: WaveFormat() (4 input parameters) Name: WaveFormat Return type: void Description: Convert wave data to desired format @@ -4427,203 +4434,203 @@ Function 538: WaveFormat() (4 input parameters) Param[2]: sampleRate (type: int) Param[3]: sampleSize (type: int) Param[4]: channels (type: int) -Function 539: LoadWaveSamples() (1 input parameters) +Function 540: LoadWaveSamples() (1 input parameters) Name: LoadWaveSamples Return type: float * Description: Load samples data from wave as a 32bit float data array Param[1]: wave (type: Wave) -Function 540: UnloadWaveSamples() (1 input parameters) +Function 541: UnloadWaveSamples() (1 input parameters) Name: UnloadWaveSamples Return type: void Description: Unload samples data loaded with LoadWaveSamples() Param[1]: samples (type: float *) -Function 541: LoadMusicStream() (1 input parameters) +Function 542: LoadMusicStream() (1 input parameters) Name: LoadMusicStream Return type: Music Description: Load music stream from file Param[1]: fileName (type: const char *) -Function 542: LoadMusicStreamFromMemory() (3 input parameters) +Function 543: LoadMusicStreamFromMemory() (3 input parameters) Name: LoadMusicStreamFromMemory Return type: Music Description: Load music stream from data Param[1]: fileType (type: const char *) Param[2]: data (type: const unsigned char *) Param[3]: dataSize (type: int) -Function 543: IsMusicReady() (1 input parameters) +Function 544: IsMusicReady() (1 input parameters) Name: IsMusicReady Return type: bool Description: Checks if a music stream is ready Param[1]: music (type: Music) -Function 544: UnloadMusicStream() (1 input parameters) +Function 545: UnloadMusicStream() (1 input parameters) Name: UnloadMusicStream Return type: void Description: Unload music stream Param[1]: music (type: Music) -Function 545: PlayMusicStream() (1 input parameters) +Function 546: PlayMusicStream() (1 input parameters) Name: PlayMusicStream Return type: void Description: Start music playing Param[1]: music (type: Music) -Function 546: IsMusicStreamPlaying() (1 input parameters) +Function 547: IsMusicStreamPlaying() (1 input parameters) Name: IsMusicStreamPlaying Return type: bool Description: Check if music is playing Param[1]: music (type: Music) -Function 547: UpdateMusicStream() (1 input parameters) +Function 548: UpdateMusicStream() (1 input parameters) Name: UpdateMusicStream Return type: void Description: Updates buffers for music streaming Param[1]: music (type: Music) -Function 548: StopMusicStream() (1 input parameters) +Function 549: StopMusicStream() (1 input parameters) Name: StopMusicStream Return type: void Description: Stop music playing Param[1]: music (type: Music) -Function 549: PauseMusicStream() (1 input parameters) +Function 550: PauseMusicStream() (1 input parameters) Name: PauseMusicStream Return type: void Description: Pause music playing Param[1]: music (type: Music) -Function 550: ResumeMusicStream() (1 input parameters) +Function 551: ResumeMusicStream() (1 input parameters) Name: ResumeMusicStream Return type: void Description: Resume playing paused music Param[1]: music (type: Music) -Function 551: SeekMusicStream() (2 input parameters) +Function 552: SeekMusicStream() (2 input parameters) Name: SeekMusicStream Return type: void Description: Seek music to a position (in seconds) Param[1]: music (type: Music) Param[2]: position (type: float) -Function 552: SetMusicVolume() (2 input parameters) +Function 553: SetMusicVolume() (2 input parameters) Name: SetMusicVolume Return type: void Description: Set volume for music (1.0 is max level) Param[1]: music (type: Music) Param[2]: volume (type: float) -Function 553: SetMusicPitch() (2 input parameters) +Function 554: SetMusicPitch() (2 input parameters) Name: SetMusicPitch Return type: void Description: Set pitch for a music (1.0 is base level) Param[1]: music (type: Music) Param[2]: pitch (type: float) -Function 554: SetMusicPan() (2 input parameters) +Function 555: SetMusicPan() (2 input parameters) Name: SetMusicPan Return type: void Description: Set pan for a music (0.5 is center) Param[1]: music (type: Music) Param[2]: pan (type: float) -Function 555: GetMusicTimeLength() (1 input parameters) +Function 556: GetMusicTimeLength() (1 input parameters) Name: GetMusicTimeLength Return type: float Description: Get music time length (in seconds) Param[1]: music (type: Music) -Function 556: GetMusicTimePlayed() (1 input parameters) +Function 557: GetMusicTimePlayed() (1 input parameters) Name: GetMusicTimePlayed Return type: float Description: Get current music time played (in seconds) Param[1]: music (type: Music) -Function 557: LoadAudioStream() (3 input parameters) +Function 558: LoadAudioStream() (3 input parameters) Name: LoadAudioStream Return type: AudioStream Description: Load audio stream (to stream raw audio pcm data) Param[1]: sampleRate (type: unsigned int) Param[2]: sampleSize (type: unsigned int) Param[3]: channels (type: unsigned int) -Function 558: IsAudioStreamReady() (1 input parameters) +Function 559: IsAudioStreamReady() (1 input parameters) Name: IsAudioStreamReady Return type: bool Description: Checks if an audio stream is ready Param[1]: stream (type: AudioStream) -Function 559: UnloadAudioStream() (1 input parameters) +Function 560: UnloadAudioStream() (1 input parameters) Name: UnloadAudioStream Return type: void Description: Unload audio stream and free memory Param[1]: stream (type: AudioStream) -Function 560: UpdateAudioStream() (3 input parameters) +Function 561: UpdateAudioStream() (3 input parameters) Name: UpdateAudioStream Return type: void Description: Update audio stream buffers with data Param[1]: stream (type: AudioStream) Param[2]: data (type: const void *) Param[3]: frameCount (type: int) -Function 561: IsAudioStreamProcessed() (1 input parameters) +Function 562: IsAudioStreamProcessed() (1 input parameters) Name: IsAudioStreamProcessed Return type: bool Description: Check if any audio stream buffers requires refill Param[1]: stream (type: AudioStream) -Function 562: PlayAudioStream() (1 input parameters) +Function 563: PlayAudioStream() (1 input parameters) Name: PlayAudioStream Return type: void Description: Play audio stream Param[1]: stream (type: AudioStream) -Function 563: PauseAudioStream() (1 input parameters) +Function 564: PauseAudioStream() (1 input parameters) Name: PauseAudioStream Return type: void Description: Pause audio stream Param[1]: stream (type: AudioStream) -Function 564: ResumeAudioStream() (1 input parameters) +Function 565: ResumeAudioStream() (1 input parameters) Name: ResumeAudioStream Return type: void Description: Resume audio stream Param[1]: stream (type: AudioStream) -Function 565: IsAudioStreamPlaying() (1 input parameters) +Function 566: IsAudioStreamPlaying() (1 input parameters) Name: IsAudioStreamPlaying Return type: bool Description: Check if audio stream is playing Param[1]: stream (type: AudioStream) -Function 566: StopAudioStream() (1 input parameters) +Function 567: StopAudioStream() (1 input parameters) Name: StopAudioStream Return type: void Description: Stop audio stream Param[1]: stream (type: AudioStream) -Function 567: SetAudioStreamVolume() (2 input parameters) +Function 568: SetAudioStreamVolume() (2 input parameters) Name: SetAudioStreamVolume Return type: void Description: Set volume for audio stream (1.0 is max level) Param[1]: stream (type: AudioStream) Param[2]: volume (type: float) -Function 568: SetAudioStreamPitch() (2 input parameters) +Function 569: SetAudioStreamPitch() (2 input parameters) Name: SetAudioStreamPitch Return type: void Description: Set pitch for audio stream (1.0 is base level) Param[1]: stream (type: AudioStream) Param[2]: pitch (type: float) -Function 569: SetAudioStreamPan() (2 input parameters) +Function 570: SetAudioStreamPan() (2 input parameters) Name: SetAudioStreamPan Return type: void Description: Set pan for audio stream (0.5 is centered) Param[1]: stream (type: AudioStream) Param[2]: pan (type: float) -Function 570: SetAudioStreamBufferSizeDefault() (1 input parameters) +Function 571: SetAudioStreamBufferSizeDefault() (1 input parameters) Name: SetAudioStreamBufferSizeDefault Return type: void Description: Default size for new audio streams Param[1]: size (type: int) -Function 571: SetAudioStreamCallback() (2 input parameters) +Function 572: SetAudioStreamCallback() (2 input parameters) Name: SetAudioStreamCallback Return type: void Description: Audio thread callback to request new data Param[1]: stream (type: AudioStream) Param[2]: callback (type: AudioCallback) -Function 572: AttachAudioStreamProcessor() (2 input parameters) +Function 573: AttachAudioStreamProcessor() (2 input parameters) Name: AttachAudioStreamProcessor Return type: void Description: Attach audio stream processor to stream, receives the samples as 'float' Param[1]: stream (type: AudioStream) Param[2]: processor (type: AudioCallback) -Function 573: DetachAudioStreamProcessor() (2 input parameters) +Function 574: DetachAudioStreamProcessor() (2 input parameters) Name: DetachAudioStreamProcessor Return type: void Description: Detach audio stream processor from stream Param[1]: stream (type: AudioStream) Param[2]: processor (type: AudioCallback) -Function 574: AttachAudioMixedProcessor() (1 input parameters) +Function 575: AttachAudioMixedProcessor() (1 input parameters) Name: AttachAudioMixedProcessor Return type: void Description: Attach audio stream processor to the entire audio pipeline, receives the samples as 'float' Param[1]: processor (type: AudioCallback) -Function 575: DetachAudioMixedProcessor() (1 input parameters) +Function 576: DetachAudioMixedProcessor() (1 input parameters) Name: DetachAudioMixedProcessor Return type: void Description: Detach audio stream processor from the entire audio pipeline diff --git a/parser/output/raylib_api.xml b/parser/output/raylib_api.xml index 532b9e3b9..1cd645651 100644 --- a/parser/output/raylib_api.xml +++ b/parser/output/raylib_api.xml @@ -670,7 +670,7 @@ - + @@ -2236,12 +2236,17 @@ + + + + + - + From b807f633d95d8aa762565362b9df1034287fd1b1 Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 15 Sep 2024 13:01:59 +0200 Subject: [PATCH 066/208] REVIEWED: `ColorLerp()` formatting #4310 --- src/raylib.h | 2 +- src/rtextures.c | 34 ++++++++++++++++------------------ 2 files changed, 17 insertions(+), 19 deletions(-) diff --git a/src/raylib.h b/src/raylib.h index a9cdbe94b..84f136355 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -1431,11 +1431,11 @@ RLAPI Color ColorBrightness(Color color, float factor); // G RLAPI Color ColorContrast(Color color, float contrast); // Get color with contrast correction, contrast values between -1.0f and 1.0f RLAPI Color ColorAlpha(Color color, float alpha); // Get color with alpha applied, alpha goes from 0.0f to 1.0f RLAPI Color ColorAlphaBlend(Color dst, Color src, Color tint); // Get src alpha-blended into dst color with tint +RLAPI Color ColorLerp(Color color1, Color color2, float factor); // Get color lerp interpolation between two colors, factor [0.0f..1.0f] RLAPI Color GetColor(unsigned int hexValue); // Get Color structure from hexadecimal value RLAPI Color GetPixelColor(void *srcPtr, int format); // Get Color from a source pixel pointer of certain format RLAPI void SetPixelColor(void *dstPtr, Color color, int format); // Set color formatted into destination pixel pointer RLAPI int GetPixelDataSize(int width, int height, int format); // Get pixel data size in bytes for certain format -RLAPI Color ColorLerp(Color color1, Color color2, float d); // Mix 2 Colors Together //------------------------------------------------------------------------------------ // Font Loading and Text Drawing Functions (Module: text) diff --git a/src/rtextures.c b/src/rtextures.c index f391b0d91..0a5ab793e 100644 --- a/src/rtextures.c +++ b/src/rtextures.c @@ -5185,6 +5185,22 @@ Color ColorAlphaBlend(Color dst, Color src, Color tint) return out; } +// Get color lerp interpolation between two colors, factor [0.0f..1.0f] +Color ColorLerp(Color color1, Color color2, float factor) +{ + Color color = { 0 }; + + if (d < 0) d = 0.0f; + else if (d > 1) d = 1.0f; + + color.r = (unsigned char)((1.0f - factor)*color1.r + factor*color2.r); + color.g = (unsigned char)((1.0f - factor)*color1.g + factor*color2.g); + color.b = (unsigned char)((1.0f - factor)*color1.b + factor*color2.b); + color.a = (unsigned char)((1.0f - factor)*color1.a + factor*color2.a); + + return color; +} + // Get a Color struct from hexadecimal value Color GetColor(unsigned int hexValue) { @@ -5424,24 +5440,6 @@ int GetPixelDataSize(int width, int height, int format) return dataSize; } - -// Mix 2 Colors togehter. -// d = dominance. 0.5 for equal -Color ColorLerp(Color color1, Color color2, float d) -{ - Color newColor = { 0, 0, 0, 0 }; - if (d < 0) {d=0.0f;} - else if(d>1) {d=1.0f;} - - newColor.r = (unsigned char)((1.0f-d) * color1.r + d * color2.r); - newColor.g = (unsigned char)((1.0f-d) * color1.g + d * color2.g); - newColor.b = (unsigned char)((1.0f-d) * color1.b + d * color2.b); - newColor.a = (unsigned char)((1.0f-d) * color1.a + d * color2.a); - - return newColor; -} - - //---------------------------------------------------------------------------------- // Module specific Functions Definition //---------------------------------------------------------------------------------- From 8d92e65773019fa48fe1fe56cf3a247e4e11ac14 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 15 Sep 2024 11:02:18 +0000 Subject: [PATCH 067/208] Update raylib_api.* by CI --- parser/output/raylib_api.json | 38 +++++++++++++++++------------------ parser/output/raylib_api.lua | 20 +++++++++--------- parser/output/raylib_api.txt | 22 ++++++++++---------- parser/output/raylib_api.xml | 10 ++++----- 4 files changed, 45 insertions(+), 45 deletions(-) diff --git a/parser/output/raylib_api.json b/parser/output/raylib_api.json index 48096a951..423b55282 100644 --- a/parser/output/raylib_api.json +++ b/parser/output/raylib_api.json @@ -8780,6 +8780,25 @@ } ] }, + { + "name": "ColorLerp", + "description": "Get color lerp interpolation between two colors, factor [0.0f..1.0f]", + "returnType": "Color", + "params": [ + { + "type": "Color", + "name": "color1" + }, + { + "type": "Color", + "name": "color2" + }, + { + "type": "float", + "name": "factor" + } + ] + }, { "name": "GetColor", "description": "Get Color structure from hexadecimal value", @@ -8844,25 +8863,6 @@ } ] }, - { - "name": "ColorLerp", - "description": "Mix 2 Colors Together", - "returnType": "Color", - "params": [ - { - "type": "Color", - "name": "color1" - }, - { - "type": "Color", - "name": "color2" - }, - { - "type": "float", - "name": "d" - } - ] - }, { "name": "GetFontDefault", "description": "Get the default Font", diff --git a/parser/output/raylib_api.lua b/parser/output/raylib_api.lua index 66095be61..0aad16644 100644 --- a/parser/output/raylib_api.lua +++ b/parser/output/raylib_api.lua @@ -6377,6 +6377,16 @@ return { {type = "Color", name = "tint"} } }, + { + name = "ColorLerp", + description = "Get color lerp interpolation between two colors, factor [0.0f..1.0f]", + returnType = "Color", + params = { + {type = "Color", name = "color1"}, + {type = "Color", name = "color2"}, + {type = "float", name = "factor"} + } + }, { name = "GetColor", description = "Get Color structure from hexadecimal value", @@ -6414,16 +6424,6 @@ return { {type = "int", name = "format"} } }, - { - name = "ColorLerp", - description = "Mix 2 Colors Together", - returnType = "Color", - params = { - {type = "Color", name = "color1"}, - {type = "Color", name = "color2"}, - {type = "float", name = "d"} - } - }, { name = "GetFontDefault", description = "Get the default Font", diff --git a/parser/output/raylib_api.txt b/parser/output/raylib_api.txt index 6c489498b..55420d158 100644 --- a/parser/output/raylib_api.txt +++ b/parser/output/raylib_api.txt @@ -3368,38 +3368,38 @@ Function 380: ColorAlphaBlend() (3 input parameters) Param[1]: dst (type: Color) Param[2]: src (type: Color) Param[3]: tint (type: Color) -Function 381: GetColor() (1 input parameters) +Function 381: ColorLerp() (3 input parameters) + Name: ColorLerp + Return type: Color + Description: Get color lerp interpolation between two colors, factor [0.0f..1.0f] + Param[1]: color1 (type: Color) + Param[2]: color2 (type: Color) + Param[3]: factor (type: float) +Function 382: GetColor() (1 input parameters) Name: GetColor Return type: Color Description: Get Color structure from hexadecimal value Param[1]: hexValue (type: unsigned int) -Function 382: GetPixelColor() (2 input parameters) +Function 383: GetPixelColor() (2 input parameters) Name: GetPixelColor Return type: Color Description: Get Color from a source pixel pointer of certain format Param[1]: srcPtr (type: void *) Param[2]: format (type: int) -Function 383: SetPixelColor() (3 input parameters) +Function 384: SetPixelColor() (3 input parameters) Name: SetPixelColor Return type: void Description: Set color formatted into destination pixel pointer Param[1]: dstPtr (type: void *) Param[2]: color (type: Color) Param[3]: format (type: int) -Function 384: GetPixelDataSize() (3 input parameters) +Function 385: GetPixelDataSize() (3 input parameters) Name: GetPixelDataSize Return type: int Description: Get pixel data size in bytes for certain format Param[1]: width (type: int) Param[2]: height (type: int) Param[3]: format (type: int) -Function 385: ColorLerp() (3 input parameters) - Name: ColorLerp - Return type: Color - Description: Mix 2 Colors Together - Param[1]: color1 (type: Color) - Param[2]: color2 (type: Color) - Param[3]: d (type: float) Function 386: GetFontDefault() (0 input parameters) Name: GetFontDefault Return type: Font diff --git a/parser/output/raylib_api.xml b/parser/output/raylib_api.xml index 1cd645651..3f8f65b13 100644 --- a/parser/output/raylib_api.xml +++ b/parser/output/raylib_api.xml @@ -2219,6 +2219,11 @@ + + + + + @@ -2236,11 +2241,6 @@ - - - - - From e9bbf02b2b450269c08ba348d352159f4658024b Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 15 Sep 2024 13:03:12 +0200 Subject: [PATCH 068/208] Update rtextures.c --- src/rtextures.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rtextures.c b/src/rtextures.c index 0a5ab793e..8bda75ad8 100644 --- a/src/rtextures.c +++ b/src/rtextures.c @@ -5190,8 +5190,8 @@ Color ColorLerp(Color color1, Color color2, float factor) { Color color = { 0 }; - if (d < 0) d = 0.0f; - else if (d > 1) d = 1.0f; + if (factor < 0.0f) factor = 0.0f; + else if (factor > 1.0f) factor = 1.0f; color.r = (unsigned char)((1.0f - factor)*color1.r + factor*color2.r); color.g = (unsigned char)((1.0f - factor)*color1.g + factor*color2.g); From 16e9317220bcede380873d2000c1ccd5062e3f07 Mon Sep 17 00:00:00 2001 From: foxblock Date: Sun, 15 Sep 2024 13:05:01 +0200 Subject: [PATCH 069/208] [rcore] Add filtering folders to `LoadDirectoryFilesEx()`/`ScanDirectoryFiles()` (#4302) * Add filtering folders in ScanDirectoryFiles and ScanDirectoryFilesRecursively Add define FILTER_FOLDER for that purpose Fix folder names matching filter being added to result * Move FILTER_FOLDER define to internals of rcore and document option in comment --- src/raylib.h | 2 +- src/rcore.c | 38 ++++++++++++++++++++++++++++++++++---- 2 files changed, 35 insertions(+), 5 deletions(-) diff --git a/src/raylib.h b/src/raylib.h index 84f136355..a1514e32c 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -1126,7 +1126,7 @@ RLAPI bool ChangeDirectory(const char *dir); // Change work RLAPI bool IsPathFile(const char *path); // Check if a given path is a file or a directory RLAPI bool IsFileNameValid(const char *fileName); // Check if fileName is valid for the platform/OS RLAPI FilePathList LoadDirectoryFiles(const char *dirPath); // Load directory filepaths -RLAPI FilePathList LoadDirectoryFilesEx(const char *basePath, const char *filter, bool scanSubdirs); // Load directory filepaths with extension filtering and recursive directory scan +RLAPI FilePathList LoadDirectoryFilesEx(const char *basePath, const char *filter, bool scanSubdirs); // Load directory filepaths with extension filtering and recursive directory scan. Use "/DIR" in the filter string to include directories in the result RLAPI void UnloadDirectoryFiles(FilePathList files); // Unload filepaths RLAPI bool IsFileDropped(void); // Check if a file has been dropped into window RLAPI FilePathList LoadDroppedFiles(void); // Load dropped filepaths diff --git a/src/rcore.c b/src/rcore.c index 44dfd746f..50e26423b 100644 --- a/src/rcore.c +++ b/src/rcore.c @@ -251,6 +251,10 @@ unsigned int __stdcall timeEndPeriod(unsigned int uPeriod); #define MAX_AUTOMATION_EVENTS 16384 // Maximum number of automation events to record #endif +#ifndef FILTER_FOLDER + #define FILTER_FOLDER "/DIR" // Filter string used in ScanDirectoryFiles, ScanDirectoryFilesRecursively and LoadDirectoryFilesEx to include directories in the result array +#endif + // Flags operation macros #define FLAG_SET(n, f) ((n) |= (f)) #define FLAG_CLEAR(n, f) ((n) &= ~(f)) @@ -3339,10 +3343,21 @@ static void ScanDirectoryFiles(const char *basePath, FilePathList *files, const if (filter != NULL) { - if (IsFileExtension(path, filter)) + if (IsPathFile(path)) { - strcpy(files->paths[files->count], path); - files->count++; + if (IsFileExtension(path, filter)) + { + strcpy(files->paths[files->count], path); + files->count++; + } + } + else + { + if (TextFindIndex(filter, FILTER_FOLDER) >= 0) + { + strcpy(files->paths[files->count], path); + files->count++; + } } } else @@ -3402,7 +3417,22 @@ static void ScanDirectoryFilesRecursively(const char *basePath, FilePathList *fi break; } } - else ScanDirectoryFilesRecursively(path, files, filter); + else + { + if (filter != NULL && TextFindIndex(filter, FILTER_FOLDER) >= 0) + { + strcpy(files->paths[files->count], path); + files->count++; + } + + if (files->count >= files->capacity) + { + TRACELOG(LOG_WARNING, "FILEIO: Maximum filepath scan capacity reached (%i files)", files->capacity); + break; + } + + ScanDirectoryFilesRecursively(path, files, filter); + } } } From 7ec1c288beb633a1e3fade91b0c7e348a2c24431 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 15 Sep 2024 11:05:15 +0000 Subject: [PATCH 070/208] Update raylib_api.* by CI --- parser/output/raylib_api.json | 2 +- parser/output/raylib_api.lua | 2 +- parser/output/raylib_api.txt | 2 +- parser/output/raylib_api.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/parser/output/raylib_api.json b/parser/output/raylib_api.json index 423b55282..7e9ad9c12 100644 --- a/parser/output/raylib_api.json +++ b/parser/output/raylib_api.json @@ -4523,7 +4523,7 @@ }, { "name": "LoadDirectoryFilesEx", - "description": "Load directory filepaths with extension filtering and recursive directory scan", + "description": "Load directory filepaths with extension filtering and recursive directory scan. Use "/DIR" in the filter string to include directories in the result", "returnType": "FilePathList", "params": [ { diff --git a/parser/output/raylib_api.lua b/parser/output/raylib_api.lua index 0aad16644..5a644a3ad 100644 --- a/parser/output/raylib_api.lua +++ b/parser/output/raylib_api.lua @@ -4076,7 +4076,7 @@ return { }, { name = "LoadDirectoryFilesEx", - description = "Load directory filepaths with extension filtering and recursive directory scan", + description = "Load directory filepaths with extension filtering and recursive directory scan. Use "/DIR" in the filter string to include directories in the result", returnType = "FilePathList", params = { {type = "const char *", name = "basePath"}, diff --git a/parser/output/raylib_api.txt b/parser/output/raylib_api.txt index 55420d158..19181328f 100644 --- a/parser/output/raylib_api.txt +++ b/parser/output/raylib_api.txt @@ -1722,7 +1722,7 @@ Function 137: LoadDirectoryFiles() (1 input parameters) Function 138: LoadDirectoryFilesEx() (3 input parameters) Name: LoadDirectoryFilesEx Return type: FilePathList - Description: Load directory filepaths with extension filtering and recursive directory scan + Description: Load directory filepaths with extension filtering and recursive directory scan. Use "/DIR" in the filter string to include directories in the result Param[1]: basePath (type: const char *) Param[2]: filter (type: const char *) Param[3]: scanSubdirs (type: bool) diff --git a/parser/output/raylib_api.xml b/parser/output/raylib_api.xml index 3f8f65b13..f73e9241b 100644 --- a/parser/output/raylib_api.xml +++ b/parser/output/raylib_api.xml @@ -1081,7 +1081,7 @@ - + From 0e4ebaf89df19a3cbf3fb8c9215e94dfb1344d9b Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 15 Sep 2024 13:20:43 +0200 Subject: [PATCH 071/208] REVIEWED: `DrawTexturePro()` to avoid negative dest rec #4316 --- src/rtextures.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/rtextures.c b/src/rtextures.c index 8bda75ad8..6d3c21cf4 100644 --- a/src/rtextures.c +++ b/src/rtextures.c @@ -4565,6 +4565,9 @@ void DrawTexturePro(Texture2D texture, Rectangle source, Rectangle dest, Vector2 if (source.width < 0) { flipX = true; source.width *= -1; } if (source.height < 0) source.y -= source.height; + + if (dest.width < 0) dest.width *= -1; + if (dest.height < 0) dest.height *= -1; Vector2 topLeft = { 0 }; Vector2 topRight = { 0 }; From 627e76cf7b82786d7e8a69b5bb1d5e7d023e7976 Mon Sep 17 00:00:00 2001 From: Ray Date: Tue, 17 Sep 2024 10:26:32 +0200 Subject: [PATCH 072/208] REVIEWED: Directory filter tag #4323 --- src/rcore.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/rcore.c b/src/rcore.c index 50e26423b..5de1fc721 100644 --- a/src/rcore.c +++ b/src/rcore.c @@ -251,9 +251,9 @@ unsigned int __stdcall timeEndPeriod(unsigned int uPeriod); #define MAX_AUTOMATION_EVENTS 16384 // Maximum number of automation events to record #endif -#ifndef FILTER_FOLDER - #define FILTER_FOLDER "/DIR" // Filter string used in ScanDirectoryFiles, ScanDirectoryFilesRecursively and LoadDirectoryFilesEx to include directories in the result array -#endif +#ifndef DIRECTORY_FILTER_TAG + #define DIRECTORY_FILTER_TAG "DIR" // Name tag used to request directory inclusion on directory scan +#endif // NOTE: Used in ScanDirectoryFiles(), ScanDirectoryFilesRecursively() and LoadDirectoryFilesEx() // Flags operation macros #define FLAG_SET(n, f) ((n) |= (f)) @@ -3353,7 +3353,7 @@ static void ScanDirectoryFiles(const char *basePath, FilePathList *files, const } else { - if (TextFindIndex(filter, FILTER_FOLDER) >= 0) + if (TextFindIndex(filter, DIRECTORY_FILTER_TAG) >= 0) { strcpy(files->paths[files->count], path); files->count++; @@ -3419,7 +3419,7 @@ static void ScanDirectoryFilesRecursively(const char *basePath, FilePathList *fi } else { - if (filter != NULL && TextFindIndex(filter, FILTER_FOLDER) >= 0) + if ((filter != NULL) && (TextFindIndex(filter, DIRECTORY_FILTER_TAG) >= 0)) { strcpy(files->paths[files->count], path); files->count++; From c2bd1845eb65dedcce4dff519b2c2dc20336a3cf Mon Sep 17 00:00:00 2001 From: Ray Date: Tue, 17 Sep 2024 10:30:26 +0200 Subject: [PATCH 073/208] Reviewed #4323 --- parser/raylib_parser.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/parser/raylib_parser.c b/parser/raylib_parser.c index 83991c003..94a715562 100644 --- a/parser/raylib_parser.c +++ b/parser/raylib_parser.c @@ -72,7 +72,7 @@ #define MAX_CALLBACKS_TO_PARSE 64 // Maximum number of callbacks to parse #define MAX_FUNCS_TO_PARSE 1024 // Maximum number of functions to parse -#define MAX_LINE_LENGTH 512 // Maximum length of one line (including comments) +#define MAX_LINE_LENGTH 1024 // Maximum length of one line (including comments) #define MAX_STRUCT_FIELDS 64 // Maximum number of struct fields #define MAX_ENUM_VALUES 512 // Maximum number of enum values @@ -139,7 +139,7 @@ typedef struct EnumInfo { // Function info data typedef struct FunctionInfo { char name[64]; // Function name - char desc[256]; // Function description (comment at the end) + char desc[512]; // Function description (comment at the end) char retType[32]; // Return value type int paramCount; // Number of function parameters char paramType[MAX_FUNCTION_PARAMETERS][32]; // Parameters type From 0a03ed913beb8a3d7555c5e9b804a0a327fceb9c Mon Sep 17 00:00:00 2001 From: Ray Date: Tue, 17 Sep 2024 17:30:40 +0200 Subject: [PATCH 074/208] Update raylib.h --- src/raylib.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/raylib.h b/src/raylib.h index a1514e32c..08474b5e5 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -1126,7 +1126,7 @@ RLAPI bool ChangeDirectory(const char *dir); // Change work RLAPI bool IsPathFile(const char *path); // Check if a given path is a file or a directory RLAPI bool IsFileNameValid(const char *fileName); // Check if fileName is valid for the platform/OS RLAPI FilePathList LoadDirectoryFiles(const char *dirPath); // Load directory filepaths -RLAPI FilePathList LoadDirectoryFilesEx(const char *basePath, const char *filter, bool scanSubdirs); // Load directory filepaths with extension filtering and recursive directory scan. Use "/DIR" in the filter string to include directories in the result +RLAPI FilePathList LoadDirectoryFilesEx(const char *basePath, const char *filter, bool scanSubdirs); // Load directory filepaths with extension filtering and recursive directory scan. Use 'DIR' in the filter string to include directories in the result RLAPI void UnloadDirectoryFiles(FilePathList files); // Unload filepaths RLAPI bool IsFileDropped(void); // Check if a file has been dropped into window RLAPI FilePathList LoadDroppedFiles(void); // Load dropped filepaths From c762a99bd57c4e19551967451b42b195ac71b4bb Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 17 Sep 2024 15:30:59 +0000 Subject: [PATCH 075/208] Update raylib_api.* by CI --- parser/output/raylib_api.json | 2 +- parser/output/raylib_api.lua | 2 +- parser/output/raylib_api.txt | 2 +- parser/output/raylib_api.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/parser/output/raylib_api.json b/parser/output/raylib_api.json index 7e9ad9c12..781454dc2 100644 --- a/parser/output/raylib_api.json +++ b/parser/output/raylib_api.json @@ -4523,7 +4523,7 @@ }, { "name": "LoadDirectoryFilesEx", - "description": "Load directory filepaths with extension filtering and recursive directory scan. Use "/DIR" in the filter string to include directories in the result", + "description": "Load directory filepaths with extension filtering and recursive directory scan. Use 'DIR' in the filter string to include directories in the result", "returnType": "FilePathList", "params": [ { diff --git a/parser/output/raylib_api.lua b/parser/output/raylib_api.lua index 5a644a3ad..9cf39855e 100644 --- a/parser/output/raylib_api.lua +++ b/parser/output/raylib_api.lua @@ -4076,7 +4076,7 @@ return { }, { name = "LoadDirectoryFilesEx", - description = "Load directory filepaths with extension filtering and recursive directory scan. Use "/DIR" in the filter string to include directories in the result", + description = "Load directory filepaths with extension filtering and recursive directory scan. Use 'DIR' in the filter string to include directories in the result", returnType = "FilePathList", params = { {type = "const char *", name = "basePath"}, diff --git a/parser/output/raylib_api.txt b/parser/output/raylib_api.txt index 19181328f..07b34c0ce 100644 --- a/parser/output/raylib_api.txt +++ b/parser/output/raylib_api.txt @@ -1722,7 +1722,7 @@ Function 137: LoadDirectoryFiles() (1 input parameters) Function 138: LoadDirectoryFilesEx() (3 input parameters) Name: LoadDirectoryFilesEx Return type: FilePathList - Description: Load directory filepaths with extension filtering and recursive directory scan. Use "/DIR" in the filter string to include directories in the result + Description: Load directory filepaths with extension filtering and recursive directory scan. Use 'DIR' in the filter string to include directories in the result Param[1]: basePath (type: const char *) Param[2]: filter (type: const char *) Param[3]: scanSubdirs (type: bool) diff --git a/parser/output/raylib_api.xml b/parser/output/raylib_api.xml index f73e9241b..6bd5a4581 100644 --- a/parser/output/raylib_api.xml +++ b/parser/output/raylib_api.xml @@ -1081,7 +1081,7 @@ - + From 2f0cf8fbe1c389e99c1cc97bb163cbc8f92b9327 Mon Sep 17 00:00:00 2001 From: Brian E <72316548+Brian-ED@users.noreply.github.com> Date: Fri, 20 Sep 2024 09:01:15 +0200 Subject: [PATCH 076/208] [BINDINGS.md] Added raylib-bqn, moved rayed-bqn (#4331) * [BINDINGS.md] Added raylib-bqn, moved rayed-bqn rayed-bqn has had a lot of progress and I've realized it has diverged too much from raylib, and so I made raylib-bqn to be a simple binding, while rayed-bqn will be a utility wrapper. * removed accidental newline --- BINDINGS.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/BINDINGS.md b/BINDINGS.md index 2c986f236..6ac54498e 100644 --- a/BINDINGS.md +++ b/BINDINGS.md @@ -78,7 +78,7 @@ Some people ported raylib to other languages in the form of bindings or wrappers | [raylib-zig-bindings](https://github.com/L-Briand/raylib-zig-bindings) | **5.0** | [Zig](https://ziglang.org) | Zlib | | [hare-raylib](https://git.sr.ht/~evantj/hare-raylib) | **auto** | [Hare](https://harelang.org) | Zlib | | [raylib-sunder](https://github.com/ashn-dot-dev/raylib-sunder) | **auto** | [Sunder](https://github.com/ashn-dot-dev/sunder) | 0BSD | -| [rayed-bqn](https://github.com/Brian-ED/rayed-bqn) | **auto** | [BQN](https://mlochbaum.github.io/BQN) | MIT | +| [raylib-bqn](https://github.com/Brian-ED/raylib-bqn) | **5.0** | [BQN](https://mlochbaum.github.io/BQN) | MIT | | [rayjs](https://github.com/mode777/rayjs) | 4.6-dev | [QuickJS](https://bellard.org/quickjs) | MIT | | [raylib-raku](https://github.com/vushu/raylib-raku) | **auto** | [Raku](https://www.raku.org) | Artistic License 2.0 | | [Raylib.lean](https://github.com/KislyjKisel/Raylib.lean) | 4.5 | [Lean4](https://lean-lang.org) | BSD-3-Clause | @@ -92,6 +92,7 @@ These are utility wrappers for specific languages, they are not required to use | ---------------------------------------------------- | :------------: | :------------------------------------------: | :-----: | | [raylib-cpp](https://github.com/robloach/raylib-cpp) | **5.0** | [C++](https://en.wikipedia.org/wiki/C%2B%2B) | Zlib | | [claylib](https://github.com/defun-games/claylib) | 4.5 | [Common Lisp](https://common-lisp.net) | Zlib | +| [rayed-bqn](https://github.com/Brian-ED/rayed-bqn) | **5.0** | [BQN](https://mlochbaum.github.io/BQN) | MIT | ### Older or Unmaintained Language Bindings From 86ead962633f5ee819829550dc8acdd9cd07f667 Mon Sep 17 00:00:00 2001 From: Daniel Holden Date: Fri, 20 Sep 2024 11:30:37 -0400 Subject: [PATCH 077/208] [rmodels] Optional GPU skinning (#4321) * Added optional GPU skinning * Added skinned bone matrices support for different file formats. * Moved new shader locations to end of enum to avoid breaking existing examples. Added gpu skinning on drawing of instanced meshes. * Added GPU skinning example. * Removed variable declaration to avoid shadowing warning. --- examples/Makefile | 3 +- examples/models/models_gpu_skinning.c | 117 +++++++++++++ .../resources/shaders/glsl100/skinning.fs | 17 ++ .../resources/shaders/glsl100/skinning.vs | 34 ++++ .../resources/shaders/glsl330/skinning.fs | 17 ++ .../resources/shaders/glsl330/skinning.vs | 34 ++++ src/config.h | 16 +- src/raylib.h | 12 +- src/rcore.c | 5 + src/rlgl.h | 41 ++++- src/rmodels.c | 164 +++++++++++++++++- 11 files changed, 437 insertions(+), 23 deletions(-) create mode 100644 examples/models/models_gpu_skinning.c create mode 100644 examples/models/resources/shaders/glsl100/skinning.fs create mode 100644 examples/models/resources/shaders/glsl100/skinning.vs create mode 100644 examples/models/resources/shaders/glsl330/skinning.fs create mode 100644 examples/models/resources/shaders/glsl330/skinning.vs diff --git a/examples/Makefile b/examples/Makefile index bdbb6e351..c17258427 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -587,7 +587,8 @@ MODELS = \ models/models_rlgl_solar_system \ models/models_skybox \ models/models_waving_cubes \ - models/models_yaw_pitch_roll + models/models_yaw_pitch_roll \ + models/models_gpu_skinning SHADERS = \ shaders/shaders_basic_lighting \ diff --git a/examples/models/models_gpu_skinning.c b/examples/models/models_gpu_skinning.c new file mode 100644 index 000000000..e9cd73f4b --- /dev/null +++ b/examples/models/models_gpu_skinning.c @@ -0,0 +1,117 @@ +/******************************************************************************************* +* +* raylib [core] example - Doing skinning on the gpu using a vertex shader +* +* Example originally created with raylib 4.5, last time updated with raylib 4.5 +* +* Example contributed by Daniel Holden (@orangeduck) and reviewed by Ramon Santamaria (@raysan5) +* +* Example 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) 2024 Daniel Holden (@orangeduck) +* +********************************************************************************************/ + +#include "raylib.h" + +#include "raymath.h" + +#if defined(PLATFORM_DESKTOP) + #define GLSL_VERSION 330 +#else // PLATFORM_ANDROID, PLATFORM_WEB + #define GLSL_VERSION 100 +#endif + +//------------------------------------------------------------------------------------ +// Program main entry point +//------------------------------------------------------------------------------------ +int main(void) +{ + // Initialization + //-------------------------------------------------------------------------------------- + const int screenWidth = 800; + const int screenHeight = 450; + + InitWindow(screenWidth, screenHeight, "raylib [models] example - GPU skinning"); + + // Define the camera to look into our 3d world + Camera camera = { 0 }; + camera.position = (Vector3){ 5.0f, 5.0f, 5.0f }; // Camera position + camera.target = (Vector3){ 0.0f, 2.0f, 0.0f }; // Camera looking at point + camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector (rotation towards target) + camera.fovy = 45.0f; // Camera field-of-view Y + camera.projection = CAMERA_PERSPECTIVE; // Camera projection type + + // Load gltf model + Model characterModel = LoadModel("resources/models/gltf/greenman.glb"); // Load character model + + // Load skinning shader + Shader skinningShader = LoadShader(TextFormat("resources/shaders/glsl%i/skinning.vs", GLSL_VERSION), + TextFormat("resources/shaders/glsl%i/skinning.fs", GLSL_VERSION)); + + characterModel.materials[1].shader = skinningShader; + + // Load gltf model animations + int animsCount = 0; + unsigned int animIndex = 0; + unsigned int animCurrentFrame = 0; + ModelAnimation *modelAnimations = LoadModelAnimations("resources/models/gltf/greenman.glb", &animsCount); + + Vector3 position = { 0.0f, 0.0f, 0.0f }; // Set model position + + DisableCursor(); // Limit cursor to relative movement inside the window + + SetTargetFPS(60); // Set our game to run at 60 frames-per-second + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + UpdateCamera(&camera, CAMERA_THIRD_PERSON); + + // Select current animation + if (IsKeyPressed(KEY_T)) animIndex = (animIndex + 1)%animsCount; + else if (IsKeyPressed(KEY_G)) animIndex = (animIndex + animsCount - 1)%animsCount; + + // Update model animation + ModelAnimation anim = modelAnimations[animIndex]; + animCurrentFrame = (animCurrentFrame + 1)%anim.frameCount; + UpdateModelAnimationBoneMatrices(characterModel, anim, animCurrentFrame); + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + + ClearBackground(RAYWHITE); + + BeginMode3D(camera); + + // Draw character + characterModel.transform = MatrixTranslate(position.x, position.y, position.z); + UpdateModelAnimationBoneMatrices(characterModel, anim, animCurrentFrame); + DrawMesh(characterModel.meshes[0], characterModel.materials[1], characterModel.transform); + + DrawGrid(10, 1.0f); + EndMode3D(); + + DrawText("Use the T/G to switch animation", 10, 10, 20, GRAY); + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + UnloadModelAnimations(modelAnimations, animsCount); + UnloadModel(characterModel); // Unload character model and meshes/material + UnloadShader(skinningShader); + + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} \ No newline at end of file diff --git a/examples/models/resources/shaders/glsl100/skinning.fs b/examples/models/resources/shaders/glsl100/skinning.fs new file mode 100644 index 000000000..ef6568036 --- /dev/null +++ b/examples/models/resources/shaders/glsl100/skinning.fs @@ -0,0 +1,17 @@ +#version 100 + +// Input vertex attributes (from vertex shader) +in vec2 fragTexCoord; +in vec4 fragColor; + +// Output fragment color +out vec4 finalColor; + +uniform sampler2D texture0; +uniform vec4 colDiffuse; + +void main() +{ + vec4 texelColor = texture(texture0, fragTexCoord); + finalColor = texelColor*colDiffuse*fragColor; +} diff --git a/examples/models/resources/shaders/glsl100/skinning.vs b/examples/models/resources/shaders/glsl100/skinning.vs new file mode 100644 index 000000000..9c92e2a8c --- /dev/null +++ b/examples/models/resources/shaders/glsl100/skinning.vs @@ -0,0 +1,34 @@ +#version 100 + +in vec3 vertexPosition; +in vec2 vertexTexCoord; +in vec4 vertexColor; +in vec4 vertexBoneIds; +in vec4 vertexBoneWeights; + +#define MAX_BONE_NUM 128 +uniform mat4 boneMatrices[MAX_BONE_NUM]; + +uniform mat4 mvp; + +out vec2 fragTexCoord; +out vec4 fragColor; + +void main() +{ + int boneIndex0 = int(vertexBoneIds.x); + int boneIndex1 = int(vertexBoneIds.y); + int boneIndex2 = int(vertexBoneIds.z); + int boneIndex3 = int(vertexBoneIds.w); + + vec4 skinnedPosition = + vertexBoneWeights.x * (boneMatrices[boneIndex0] * vec4(vertexPosition, 1.0f)) + + vertexBoneWeights.y * (boneMatrices[boneIndex1] * vec4(vertexPosition, 1.0f)) + + vertexBoneWeights.z * (boneMatrices[boneIndex2] * vec4(vertexPosition, 1.0f)) + + vertexBoneWeights.w * (boneMatrices[boneIndex3] * vec4(vertexPosition, 1.0f)); + + fragTexCoord = vertexTexCoord; + fragColor = vertexColor; + + gl_Position = mvp * skinnedPosition; +} \ No newline at end of file diff --git a/examples/models/resources/shaders/glsl330/skinning.fs b/examples/models/resources/shaders/glsl330/skinning.fs new file mode 100644 index 000000000..d4311ffcc --- /dev/null +++ b/examples/models/resources/shaders/glsl330/skinning.fs @@ -0,0 +1,17 @@ +#version 330 + +// Input vertex attributes (from vertex shader) +in vec2 fragTexCoord; +in vec4 fragColor; + +// Output fragment color +out vec4 finalColor; + +uniform sampler2D texture0; +uniform vec4 colDiffuse; + +void main() +{ + vec4 texelColor = texture(texture0, fragTexCoord); + finalColor = texelColor*colDiffuse*fragColor; +} diff --git a/examples/models/resources/shaders/glsl330/skinning.vs b/examples/models/resources/shaders/glsl330/skinning.vs new file mode 100644 index 000000000..2dc976c48 --- /dev/null +++ b/examples/models/resources/shaders/glsl330/skinning.vs @@ -0,0 +1,34 @@ +#version 330 + +in vec3 vertexPosition; +in vec2 vertexTexCoord; +in vec4 vertexColor; +in vec4 vertexBoneIds; +in vec4 vertexBoneWeights; + +#define MAX_BONE_NUM 128 +uniform mat4 boneMatrices[MAX_BONE_NUM]; + +uniform mat4 mvp; + +out vec2 fragTexCoord; +out vec4 fragColor; + +void main() +{ + int boneIndex0 = int(vertexBoneIds.x); + int boneIndex1 = int(vertexBoneIds.y); + int boneIndex2 = int(vertexBoneIds.z); + int boneIndex3 = int(vertexBoneIds.w); + + vec4 skinnedPosition = + vertexBoneWeights.x * (boneMatrices[boneIndex0] * vec4(vertexPosition, 1.0f)) + + vertexBoneWeights.y * (boneMatrices[boneIndex1] * vec4(vertexPosition, 1.0f)) + + vertexBoneWeights.z * (boneMatrices[boneIndex2] * vec4(vertexPosition, 1.0f)) + + vertexBoneWeights.w * (boneMatrices[boneIndex3] * vec4(vertexPosition, 1.0f)); + + fragTexCoord = vertexTexCoord; + fragColor = vertexColor; + + gl_Position = mvp * skinnedPosition; +} \ No newline at end of file diff --git a/src/config.h b/src/config.h index 9cbe90e35..f6e3fe304 100644 --- a/src/config.h +++ b/src/config.h @@ -113,13 +113,15 @@ #define RL_CULL_DISTANCE_FAR 1000.0 // Default projection matrix far cull distance // Default shader vertex attribute locations -#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION 0 -#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD 1 -#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL 2 -#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR 3 -#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT 4 -#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2 5 -#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_INDICES 6 +#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION 0 +#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD 1 +#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL 2 +#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR 3 +#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT 4 +#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2 5 +#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS 6 +#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS 7 +#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_INDICES 8 // Default shader vertex attribute names to set location points // NOTE: When a new shader is loaded, the following locations are tried to be set for convenience diff --git a/src/raylib.h b/src/raylib.h index 08474b5e5..ee34b6441 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -352,8 +352,10 @@ typedef struct Mesh { // Animation vertex data float *animVertices; // Animated vertex positions (after bones transformations) float *animNormals; // Animated normals (after bones transformations) - unsigned char *boneIds; // Vertex bone ids, max 255 bone ids, up to 4 bones influence by vertex (skinning) - float *boneWeights; // Vertex bone weight, up to 4 bones influence by vertex (skinning) + unsigned char *boneIds; // Vertex bone ids, max 255 bone ids, up to 4 bones influence by vertex (skinning) (shader-location = 6) + float *boneWeights; // Vertex bone weight, up to 4 bones influence by vertex (skinning) (shader-location = 7) + Matrix *boneMatrices; // Bones animated transformation matrices + int boneCount; // Number of bones // OpenGL identifiers unsigned int vaoId; // OpenGL Vertex Array Object id @@ -790,7 +792,10 @@ typedef enum { SHADER_LOC_MAP_CUBEMAP, // Shader location: samplerCube texture: cubemap SHADER_LOC_MAP_IRRADIANCE, // Shader location: samplerCube texture: irradiance SHADER_LOC_MAP_PREFILTER, // Shader location: samplerCube texture: prefilter - SHADER_LOC_MAP_BRDF // Shader location: sampler2d texture: brdf + SHADER_LOC_MAP_BRDF, // Shader location: sampler2d texture: brdf + SHADER_LOC_VERTEX_BONEIDS, // Shader location: vertex attribute: boneIds + SHADER_LOC_VERTEX_BONEWEIGHTS, // Shader location: vertex attribute: boneWeights + SHADER_LOC_BONE_MATRICES // Shader location: array of matrices uniform: boneMatrices } ShaderLocationIndex; #define SHADER_LOC_MAP_DIFFUSE SHADER_LOC_MAP_ALBEDO @@ -1591,6 +1596,7 @@ RLAPI void UpdateModelAnimation(Model model, ModelAnimation anim, int frame); RLAPI void UnloadModelAnimation(ModelAnimation anim); // Unload animation data RLAPI void UnloadModelAnimations(ModelAnimation *animations, int animCount); // Unload animation array data RLAPI bool IsModelAnimationValid(Model model, ModelAnimation anim); // Check model animation skeleton match +RLAPI void UpdateModelAnimationBoneMatrices(Model model, ModelAnimation anim, int frame); // Update model animation mesh bone matrices // Collision detection functions RLAPI bool CheckCollisionSpheres(Vector3 center1, float radius1, Vector3 center2, float radius2); // Check collision between two spheres diff --git a/src/rcore.c b/src/rcore.c index 5de1fc721..2fd79f5c9 100644 --- a/src/rcore.c +++ b/src/rcore.c @@ -1303,6 +1303,8 @@ Shader LoadShaderFromMemory(const char *vsCode, const char *fsCode) // vertex color location = 3 // vertex tangent location = 4 // vertex texcoord2 location = 5 + // vertex boneIds location = 6 + // vertex boneWeights location = 7 // NOTE: If any location is not found, loc point becomes -1 @@ -1318,6 +1320,8 @@ Shader LoadShaderFromMemory(const char *vsCode, const char *fsCode) shader.locs[SHADER_LOC_VERTEX_NORMAL] = rlGetLocationAttrib(shader.id, RL_DEFAULT_SHADER_ATTRIB_NAME_NORMAL); shader.locs[SHADER_LOC_VERTEX_TANGENT] = rlGetLocationAttrib(shader.id, RL_DEFAULT_SHADER_ATTRIB_NAME_TANGENT); shader.locs[SHADER_LOC_VERTEX_COLOR] = rlGetLocationAttrib(shader.id, RL_DEFAULT_SHADER_ATTRIB_NAME_COLOR); + shader.locs[SHADER_LOC_VERTEX_BONEIDS] = rlGetLocationAttrib(shader.id, RL_DEFAULT_SHADER_ATTRIB_NAME_BONEIDS); + shader.locs[SHADER_LOC_VERTEX_BONEWEIGHTS] = rlGetLocationAttrib(shader.id, RL_DEFAULT_SHADER_ATTRIB_NAME_BONEWEIGHTS); // Get handles to GLSL uniform locations (vertex shader) shader.locs[SHADER_LOC_MATRIX_MVP] = rlGetLocationUniform(shader.id, RL_DEFAULT_SHADER_UNIFORM_NAME_MVP); @@ -1325,6 +1329,7 @@ Shader LoadShaderFromMemory(const char *vsCode, const char *fsCode) shader.locs[SHADER_LOC_MATRIX_PROJECTION] = rlGetLocationUniform(shader.id, RL_DEFAULT_SHADER_UNIFORM_NAME_PROJECTION); shader.locs[SHADER_LOC_MATRIX_MODEL] = rlGetLocationUniform(shader.id, RL_DEFAULT_SHADER_UNIFORM_NAME_MODEL); shader.locs[SHADER_LOC_MATRIX_NORMAL] = rlGetLocationUniform(shader.id, RL_DEFAULT_SHADER_UNIFORM_NAME_NORMAL); + shader.locs[SHADER_LOC_BONE_MATRICES] = rlGetLocationUniform(shader.id, RL_DEFAULT_SHADER_UNIFORM_NAME_BONE_MATRICES); // Get handles to GLSL uniform locations (fragment shader) shader.locs[SHADER_LOC_COLOR_DIFFUSE] = rlGetLocationUniform(shader.id, RL_DEFAULT_SHADER_UNIFORM_NAME_COLOR); diff --git a/src/rlgl.h b/src/rlgl.h index 9b94d402c..b98934a11 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -68,12 +68,15 @@ * #define RL_DEFAULT_SHADER_ATTRIB_NAME_COLOR "vertexColor" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR * #define RL_DEFAULT_SHADER_ATTRIB_NAME_TANGENT "vertexTangent" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT * #define RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2 "vertexTexCoord2" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2 +* #define RL_DEFAULT_SHADER_ATTRIB_NAME_BONEIDS "vertexBoneIds" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS +* #define RL_DEFAULT_SHADER_ATTRIB_NAME_BONEWEIGHTS "vertexBoneWeights" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS * #define RL_DEFAULT_SHADER_UNIFORM_NAME_MVP "mvp" // model-view-projection matrix * #define RL_DEFAULT_SHADER_UNIFORM_NAME_VIEW "matView" // view matrix * #define RL_DEFAULT_SHADER_UNIFORM_NAME_PROJECTION "matProjection" // projection matrix * #define RL_DEFAULT_SHADER_UNIFORM_NAME_MODEL "matModel" // model matrix * #define RL_DEFAULT_SHADER_UNIFORM_NAME_NORMAL "matNormal" // normal matrix (transpose(inverse(matModelView))) * #define RL_DEFAULT_SHADER_UNIFORM_NAME_COLOR "colDiffuse" // color diffuse (base tint color, multiplied by texture color) +* #define RL_DEFAULT_SHADER_UNIFORM_NAME_BONE_MATRICES "boneMatrices" // bone matrices * #define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE0 "texture0" // texture0 (texture slot active 0) * #define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE1 "texture1" // texture1 (texture slot active 1) * #define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE2 "texture2" // texture2 (texture slot active 2) @@ -324,22 +327,28 @@ // Default shader vertex attribute locations #ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION - #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION 0 + #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION 0 #endif #ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD - #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD 1 + #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD 1 #endif #ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL - #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL 2 + #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL 2 #endif #ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR - #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR 3 + #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR 3 #endif #ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT -#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT 4 +#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT 4 #endif #ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2 - #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2 5 + #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2 5 +#endif +#ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS + #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS 6 +#endif +#ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS + #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS 7 #endif //---------------------------------------------------------------------------------- @@ -759,6 +768,7 @@ RLAPI int rlGetLocationUniform(unsigned int shaderId, const char *uniformName); RLAPI int rlGetLocationAttrib(unsigned int shaderId, const char *attribName); // Get shader location attribute RLAPI void rlSetUniform(int locIndex, const void *value, int uniformType, int count); // Set shader value uniform RLAPI void rlSetUniformMatrix(int locIndex, Matrix mat); // Set shader value matrix +RLAPI void rlSetUniformMatrices(int locIndex, const Matrix *mat, int count); // Set shader value matrices RLAPI void rlSetUniformSampler(int locIndex, unsigned int textureId); // Set shader value sampler RLAPI void rlSetShader(unsigned int id, int *locs); // Set shader currently active (id and locations) @@ -977,6 +987,12 @@ RLAPI void rlLoadDrawQuad(void); // Load and draw a quad #ifndef RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2 #define RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2 "vertexTexCoord2" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2 #endif +#ifndef RL_DEFAULT_SHADER_ATTRIB_NAME_BONEIDS + #define RL_DEFAULT_SHADER_ATTRIB_NAME_BONEIDS "vertexBoneIds" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_NAME_BONEIDS +#endif +#ifndef RL_DEFAULT_SHADER_ATTRIB_NAME_BONEWEIGHTS + #define RL_DEFAULT_SHADER_ATTRIB_NAME_BONEWEIGHTS "vertexBoneWeights" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_NAME_BONEWEIGHTS +#endif #ifndef RL_DEFAULT_SHADER_UNIFORM_NAME_MVP #define RL_DEFAULT_SHADER_UNIFORM_NAME_MVP "mvp" // model-view-projection matrix @@ -996,6 +1012,9 @@ RLAPI void rlLoadDrawQuad(void); // Load and draw a quad #ifndef RL_DEFAULT_SHADER_UNIFORM_NAME_COLOR #define RL_DEFAULT_SHADER_UNIFORM_NAME_COLOR "colDiffuse" // color diffuse (base tint color, multiplied by texture color) #endif +#ifndef RL_DEFAULT_SHADER_UNIFORM_NAME_BONE_MATRICES + #define RL_DEFAULT_SHADER_UNIFORM_NAME_BONE_MATRICES "boneMatrices" // bone matrices +#endif #ifndef RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE0 #define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE0 "texture0" // texture0 (texture slot active 0) #endif @@ -4148,6 +4167,8 @@ unsigned int rlLoadShaderProgram(unsigned int vShaderId, unsigned int fShaderId) glBindAttribLocation(program, RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR, RL_DEFAULT_SHADER_ATTRIB_NAME_COLOR); glBindAttribLocation(program, RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT, RL_DEFAULT_SHADER_ATTRIB_NAME_TANGENT); glBindAttribLocation(program, RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2, RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2); + glBindAttribLocation(program, RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS, RL_DEFAULT_SHADER_ATTRIB_NAME_BONEIDS); + glBindAttribLocation(program, RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS, RL_DEFAULT_SHADER_ATTRIB_NAME_BONEWEIGHTS); // NOTE: If some attrib name is no found on the shader, it locations becomes -1 @@ -4283,6 +4304,14 @@ void rlSetUniformMatrix(int locIndex, Matrix mat) #endif } +// Set shader value uniform matrix +void rlSetUniformMatrices(int locIndex, const Matrix *matrices, int count) +{ +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + glUniformMatrix4fv(locIndex, count, true, (const float*)matrices); +#endif +} + // Set shader value uniform sampler void rlSetUniformSampler(int locIndex, unsigned int textureId) { diff --git a/src/rmodels.c b/src/rmodels.c index 9994ddb76..055fb1b1c 100644 --- a/src/rmodels.c +++ b/src/rmodels.c @@ -130,7 +130,7 @@ #define MAX_MATERIAL_MAPS 12 // Maximum number of maps supported #endif #ifndef MAX_MESH_VERTEX_BUFFERS - #define MAX_MESH_VERTEX_BUFFERS 7 // Maximum vertex buffers (VBO) per mesh + #define MAX_MESH_VERTEX_BUFFERS 9 // Maximum vertex buffers (VBO) per mesh #endif //---------------------------------------------------------------------------------- @@ -1248,11 +1248,13 @@ void UploadMesh(Mesh *mesh, bool dynamic) mesh->vaoId = 0; // Vertex Array Object mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION] = 0; // Vertex buffer: positions mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD] = 0; // Vertex buffer: texcoords - mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL] = 0; // Vertex buffer: normals - mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR] = 0; // Vertex buffer: colors - mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT] = 0; // Vertex buffer: tangents - mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2] = 0; // Vertex buffer: texcoords2 - mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_INDICES] = 0; // Vertex buffer: indices + mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL] = 0; // Vertex buffer: normals + mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR] = 0; // Vertex buffer: colors + mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT] = 0; // Vertex buffer: tangents + mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2] = 0; // Vertex buffer: texcoords2 + mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS] = 0; // Vertex buffer: boneIds + mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS] = 0; // Vertex buffer: boneWeights + mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_INDICES] = 0; // Vertex buffer: indices #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) mesh->vaoId = rlLoadVertexArray(); @@ -1338,6 +1340,38 @@ void UploadMesh(Mesh *mesh, bool dynamic) rlSetVertexAttributeDefault(RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2, value, SHADER_ATTRIB_VEC2, 2); rlDisableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2); } + + if (mesh->boneIds != NULL) + { + // Enable vertex attribute: boneIds (shader-location = 6) + mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS] = rlLoadVertexBuffer(mesh->boneIds, mesh->vertexCount*4*sizeof(unsigned char), dynamic); + rlSetVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS, 4, RL_UNSIGNED_BYTE, 0, 0, 0); + rlEnableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS); + } + else + { + // Default vertex attribute: boneIds + // WARNING: Default value provided to shader if location available + float value[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + rlSetVertexAttributeDefault(RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS, value, SHADER_ATTRIB_VEC4, 4); + rlDisableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS); + } + + if (mesh->boneWeights != NULL) + { + // Enable vertex attribute: boneWeights (shader-location = 7) + mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS] = rlLoadVertexBuffer(mesh->boneWeights, mesh->vertexCount*4*sizeof(float), dynamic); + rlSetVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS, 4, RL_FLOAT, 0, 0, 0); + rlEnableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS); + } + else + { + // Default vertex attribute: boneWeights + // WARNING: Default value provided to shader if location available + float value[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + rlSetVertexAttributeDefault(RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS, value, SHADER_ATTRIB_VEC4, 2); + rlDisableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS); + } if (mesh->indices != NULL) { @@ -1451,6 +1485,13 @@ void DrawMesh(Mesh mesh, Material material, Matrix transform) // Upload model normal matrix (if locations available) if (material.shader.locs[SHADER_LOC_MATRIX_NORMAL] != -1) rlSetUniformMatrix(material.shader.locs[SHADER_LOC_MATRIX_NORMAL], MatrixTranspose(MatrixInvert(matModel))); + + // Upload Bone Transforms + if (material.shader.locs[SHADER_LOC_BONE_MATRICES] != -1 && mesh.boneMatrices) + { + rlSetUniformMatrices(material.shader.locs[SHADER_LOC_BONE_MATRICES], mesh.boneMatrices, mesh.boneCount); + } + //----------------------------------------------------- // Bind active texture maps (if available) @@ -1529,6 +1570,22 @@ void DrawMesh(Mesh mesh, Material material, Matrix transform) rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD02], 2, RL_FLOAT, 0, 0, 0); rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD02]); } + + // Bind mesh VBO data: vertex bone ids (shader-location = 6, if available) + if (material.shader.locs[SHADER_LOC_VERTEX_BONEIDS] != -1) + { + rlEnableVertexBuffer(mesh.vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS]); + rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_BONEIDS], 4, RL_UNSIGNED_BYTE, 0, 0, 0); + rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_BONEIDS]); + } + + // Bind mesh VBO data: vertex bone weights (shader-location = 7, if available) + if (material.shader.locs[SHADER_LOC_VERTEX_BONEWEIGHTS] != -1) + { + rlEnableVertexBuffer(mesh.vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS]); + rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_BONEWEIGHTS], 4, RL_FLOAT, 0, 0, 0); + rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_BONEWEIGHTS]); + } if (mesh.indices != NULL) rlEnableVertexBufferElement(mesh.vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_INDICES]); } @@ -1671,6 +1728,13 @@ void DrawMeshInstanced(Mesh mesh, Material material, const Matrix *transforms, i // Upload model normal matrix (if locations available) if (material.shader.locs[SHADER_LOC_MATRIX_NORMAL] != -1) rlSetUniformMatrix(material.shader.locs[SHADER_LOC_MATRIX_NORMAL], MatrixTranspose(MatrixInvert(matModel))); + + // Upload Bone Transforms + if (material.shader.locs[SHADER_LOC_BONE_MATRICES] != -1 && mesh.boneMatrices) + { + rlSetUniformMatrices(material.shader.locs[SHADER_LOC_BONE_MATRICES], mesh.boneMatrices, mesh.boneCount); + } + //----------------------------------------------------- // Bind active texture maps (if available) @@ -1747,6 +1811,22 @@ void DrawMeshInstanced(Mesh mesh, Material material, const Matrix *transforms, i rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD02], 2, RL_FLOAT, 0, 0, 0); rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD02]); } + + // Bind mesh VBO data: vertex bone ids (shader-location = 6, if available) + if (material.shader.locs[SHADER_LOC_VERTEX_BONEIDS] != -1) + { + rlEnableVertexBuffer(mesh.vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS]); + rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_BONEIDS], 4, RL_UNSIGNED_BYTE, 0, 0, 0); + rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_BONEIDS]); + } + + // Bind mesh VBO data: vertex bone weights (shader-location = 7, if available) + if (material.shader.locs[SHADER_LOC_VERTEX_BONEWEIGHTS] != -1) + { + rlEnableVertexBuffer(mesh.vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS]); + rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_BONEWEIGHTS], 4, RL_FLOAT, 0, 0, 0); + rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_BONEWEIGHTS]); + } if (mesh.indices != NULL) rlEnableVertexBufferElement(mesh.vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_INDICES]); } @@ -1825,6 +1905,7 @@ void UnloadMesh(Mesh mesh) RL_FREE(mesh.animNormals); RL_FREE(mesh.boneWeights); RL_FREE(mesh.boneIds); + RL_FREE(mesh.boneMatrices); } // Export mesh data to file @@ -2255,6 +2336,50 @@ void UpdateModelAnimation(Model model, ModelAnimation anim, int frame) } } +void UpdateModelAnimationBoneMatrices(Model model, ModelAnimation anim, int frame) +{ + if ((anim.frameCount > 0) && (anim.bones != NULL) && (anim.framePoses != NULL)) + { + if (frame >= anim.frameCount) frame = frame%anim.frameCount; + + for (int i = 0; i < model.meshCount; i++) + { + if (model.meshes[i].boneMatrices) + { + assert(model.meshes[i].boneCount == anim.boneCount); + + for (int boneId = 0; boneId < model.meshes[i].boneCount; boneId++) + { + Vector3 inTranslation = model.bindPose[boneId].translation; + Quaternion inRotation = model.bindPose[boneId].rotation; + Vector3 inScale = model.bindPose[boneId].scale; + + Vector3 outTranslation = anim.framePoses[frame][boneId].translation; + Quaternion outRotation = anim.framePoses[frame][boneId].rotation; + Vector3 outScale = anim.framePoses[frame][boneId].scale; + + Vector3 invTranslation = Vector3RotateByQuaternion(Vector3Negate(inTranslation), QuaternionInvert(inRotation)); + Quaternion invRotation = QuaternionInvert(inRotation); + Vector3 invScale = Vector3Divide((Vector3){ 1.0f, 1.0f, 1.0f }, inScale); + + Vector3 boneTranslation = Vector3Add( + Vector3RotateByQuaternion(Vector3Multiply(outScale, invTranslation), + outRotation), outTranslation); + Quaternion boneRotation = QuaternionMultiply(outRotation, invRotation); + Vector3 boneScale = Vector3Multiply(outScale, invScale); + + Matrix boneMatrix = MatrixMultiply(MatrixMultiply( + QuaternionToMatrix(boneRotation), + MatrixTranslate(boneTranslation.x, boneTranslation.y, boneTranslation.z)), + MatrixScale(boneScale.x, boneScale.y, boneScale.z)); + + model.meshes[i].boneMatrices[boneId] = boneMatrix; + } + } + } + } +} + // Unload animation array data void UnloadModelAnimations(ModelAnimation *animations, int animCount) { @@ -4671,6 +4796,17 @@ static Model LoadIQM(const char *fileName) } BuildPoseFromParentJoints(model.bones, model.boneCount, model.bindPose); + + for (int i = 0; i < model.meshCount; i++) + { + model.meshes[i].boneCount = model.boneCount; + model.meshes[i].boneMatrices = RL_CALLOC(model.meshes[i].boneCount, sizeof(Matrix)); + + for (int j = 0; j < model.meshes[i].boneCount; j++) + { + model.meshes[i].boneMatrices[j] = MatrixIdentity(); + } + } UnloadFileData(fileData); @@ -5754,6 +5890,15 @@ static Model LoadGLTF(const char *fileName) { memcpy(model.meshes[meshIndex].animNormals, model.meshes[meshIndex].normals, model.meshes[meshIndex].vertexCount*3*sizeof(float)); } + + // Bone Transform Matrices + model.meshes[meshIndex].boneCount = model.boneCount; + model.meshes[meshIndex].boneMatrices = RL_CALLOC(model.meshes[meshIndex].boneCount, sizeof(Matrix)); + + for (int j = 0; j < model.meshes[meshIndex].boneCount; j++) + { + model.meshes[meshIndex].boneMatrices[j] = MatrixIdentity(); + } meshIndex++; // Move to next mesh } @@ -6522,6 +6667,13 @@ static Model LoadM3D(const char *fileName) { memcpy(model.meshes[i].animVertices, model.meshes[i].vertices, model.meshes[i].vertexCount*3*sizeof(float)); memcpy(model.meshes[i].animNormals, model.meshes[i].normals, model.meshes[i].vertexCount*3*sizeof(float)); + + model.meshes[i].boneCount = model.boneCount; + model.meshes[i].boneMatrices = RL_CALLOC(model.meshes[i].boneCount, sizeof(Matrix)); + for (j = 0; j < model.meshes[i].boneCount; j++) + { + model.meshes[i].boneMatrices[j] = MatrixIdentity(); + } } } From c09dadd9b5e347d6b6393a7274fef6db553dbd25 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 20 Sep 2024 15:30:53 +0000 Subject: [PATCH 078/208] Update raylib_api.* by CI --- parser/output/raylib_api.json | 48 +++++++++- parser/output/raylib_api.lua | 39 +++++++- parser/output/raylib_api.txt | 174 ++++++++++++++++++---------------- parser/output/raylib_api.xml | 20 +++- 4 files changed, 191 insertions(+), 90 deletions(-) diff --git a/parser/output/raylib_api.json b/parser/output/raylib_api.json index 781454dc2..d1c58757b 100644 --- a/parser/output/raylib_api.json +++ b/parser/output/raylib_api.json @@ -850,12 +850,22 @@ { "type": "unsigned char *", "name": "boneIds", - "description": "Vertex bone ids, max 255 bone ids, up to 4 bones influence by vertex (skinning)" + "description": "Vertex bone ids, max 255 bone ids, up to 4 bones influence by vertex (skinning) (shader-location = 6)" }, { "type": "float *", "name": "boneWeights", - "description": "Vertex bone weight, up to 4 bones influence by vertex (skinning)" + "description": "Vertex bone weight, up to 4 bones influence by vertex (skinning) (shader-location = 7)" + }, + { + "type": "Matrix *", + "name": "boneMatrices", + "description": "Bones animated transformation matrices" + }, + { + "type": "int", + "name": "boneCount", + "description": "Number of bones" }, { "type": "unsigned int", @@ -2518,6 +2528,21 @@ "name": "SHADER_LOC_MAP_BRDF", "value": 25, "description": "Shader location: sampler2d texture: brdf" + }, + { + "name": "SHADER_LOC_VERTEX_BONEIDS", + "value": 26, + "description": "Shader location: vertex attribute: boneIds" + }, + { + "name": "SHADER_LOC_VERTEX_BONEWEIGHTS", + "value": 27, + "description": "Shader location: vertex attribute: boneWeights" + }, + { + "name": "SHADER_LOC_BONE_MATRICES", + "value": 28, + "description": "Shader location: array of matrices uniform: boneMatrices" } ] }, @@ -11066,6 +11091,25 @@ } ] }, + { + "name": "UpdateModelAnimationBoneMatrices", + "description": "Update model animation mesh bone matrices", + "returnType": "void", + "params": [ + { + "type": "Model", + "name": "model" + }, + { + "type": "ModelAnimation", + "name": "anim" + }, + { + "type": "int", + "name": "frame" + } + ] + }, { "name": "CheckCollisionSpheres", "description": "Check collision between two spheres", diff --git a/parser/output/raylib_api.lua b/parser/output/raylib_api.lua index 9cf39855e..0d99407b7 100644 --- a/parser/output/raylib_api.lua +++ b/parser/output/raylib_api.lua @@ -850,12 +850,22 @@ return { { type = "unsigned char *", name = "boneIds", - description = "Vertex bone ids, max 255 bone ids, up to 4 bones influence by vertex (skinning)" + description = "Vertex bone ids, max 255 bone ids, up to 4 bones influence by vertex (skinning) (shader-location = 6)" }, { type = "float *", name = "boneWeights", - description = "Vertex bone weight, up to 4 bones influence by vertex (skinning)" + description = "Vertex bone weight, up to 4 bones influence by vertex (skinning) (shader-location = 7)" + }, + { + type = "Matrix *", + name = "boneMatrices", + description = "Bones animated transformation matrices" + }, + { + type = "int", + name = "boneCount", + description = "Number of bones" }, { type = "unsigned int", @@ -2518,6 +2528,21 @@ return { name = "SHADER_LOC_MAP_BRDF", value = 25, description = "Shader location: sampler2d texture: brdf" + }, + { + name = "SHADER_LOC_VERTEX_BONEIDS", + value = 26, + description = "Shader location: vertex attribute: boneIds" + }, + { + name = "SHADER_LOC_VERTEX_BONEWEIGHTS", + value = 27, + description = "Shader location: vertex attribute: boneWeights" + }, + { + name = "SHADER_LOC_BONE_MATRICES", + value = 28, + description = "Shader location: array of matrices uniform: boneMatrices" } } }, @@ -7586,6 +7611,16 @@ return { {type = "ModelAnimation", name = "anim"} } }, + { + name = "UpdateModelAnimationBoneMatrices", + description = "Update model animation mesh bone matrices", + returnType = "void", + params = { + {type = "Model", name = "model"}, + {type = "ModelAnimation", name = "anim"}, + {type = "int", name = "frame"} + } + }, { name = "CheckCollisionSpheres", description = "Check collision between two spheres", diff --git a/parser/output/raylib_api.txt b/parser/output/raylib_api.txt index 07b34c0ce..9c92906e0 100644 --- a/parser/output/raylib_api.txt +++ b/parser/output/raylib_api.txt @@ -403,7 +403,7 @@ Struct 14: Camera2D (4 fields) Field[2]: Vector2 target // Camera target (rotation and zoom origin) Field[3]: float rotation // Camera rotation in degrees Field[4]: float zoom // Camera zoom (scaling), should be 1.0f by default -Struct 15: Mesh (15 fields) +Struct 15: Mesh (17 fields) Name: Mesh Description: Mesh, vertex data and vao/vbo Field[1]: int vertexCount // Number of vertices stored in arrays @@ -417,10 +417,12 @@ Struct 15: Mesh (15 fields) Field[9]: unsigned short * indices // Vertex indices (in case vertex data comes indexed) Field[10]: float * animVertices // Animated vertex positions (after bones transformations) Field[11]: float * animNormals // Animated normals (after bones transformations) - Field[12]: unsigned char * boneIds // Vertex bone ids, max 255 bone ids, up to 4 bones influence by vertex (skinning) - Field[13]: float * boneWeights // Vertex bone weight, up to 4 bones influence by vertex (skinning) - Field[14]: unsigned int vaoId // OpenGL Vertex Array Object id - Field[15]: unsigned int * vboId // OpenGL Vertex Buffer Objects id (default vertex data) + Field[12]: unsigned char * boneIds // Vertex bone ids, max 255 bone ids, up to 4 bones influence by vertex (skinning) (shader-location = 6) + Field[13]: float * boneWeights // Vertex bone weight, up to 4 bones influence by vertex (skinning) (shader-location = 7) + Field[14]: Matrix * boneMatrices // Bones animated transformation matrices + Field[15]: int boneCount // Number of bones + Field[16]: unsigned int vaoId // OpenGL Vertex Array Object id + Field[17]: unsigned int * vboId // OpenGL Vertex Buffer Objects id (default vertex data) Struct 16: Shader (2 fields) Name: Shader Description: Shader @@ -793,7 +795,7 @@ Enum 08: MaterialMapIndex (11 values) Value[MATERIAL_MAP_IRRADIANCE]: 8 Value[MATERIAL_MAP_PREFILTER]: 9 Value[MATERIAL_MAP_BRDF]: 10 -Enum 09: ShaderLocationIndex (26 values) +Enum 09: ShaderLocationIndex (29 values) Name: ShaderLocationIndex Description: Shader location index Value[SHADER_LOC_VERTEX_POSITION]: 0 @@ -822,6 +824,9 @@ Enum 09: ShaderLocationIndex (26 values) Value[SHADER_LOC_MAP_IRRADIANCE]: 23 Value[SHADER_LOC_MAP_PREFILTER]: 24 Value[SHADER_LOC_MAP_BRDF]: 25 + Value[SHADER_LOC_VERTEX_BONEIDS]: 26 + Value[SHADER_LOC_VERTEX_BONEWEIGHTS]: 27 + Value[SHADER_LOC_BONE_MATRICES]: 28 Enum 10: ShaderUniformDataType (9 values) Name: ShaderUniformDataType Description: Shader uniform data type @@ -984,7 +989,7 @@ Callback 006: AudioCallback() (2 input parameters) Param[1]: bufferData (type: void *) Param[2]: frames (type: unsigned int) -Functions found: 576 +Functions found: 577 Function 001: InitWindow() (3 input parameters) Name: InitWindow @@ -4217,7 +4222,14 @@ Function 502: IsModelAnimationValid() (2 input parameters) Description: Check model animation skeleton match Param[1]: model (type: Model) Param[2]: anim (type: ModelAnimation) -Function 503: CheckCollisionSpheres() (4 input parameters) +Function 503: UpdateModelAnimationBoneMatrices() (3 input parameters) + Name: UpdateModelAnimationBoneMatrices + Return type: void + Description: Update model animation mesh bone matrices + Param[1]: model (type: Model) + Param[2]: anim (type: ModelAnimation) + Param[3]: frame (type: int) +Function 504: CheckCollisionSpheres() (4 input parameters) Name: CheckCollisionSpheres Return type: bool Description: Check collision between two spheres @@ -4225,40 +4237,40 @@ Function 503: CheckCollisionSpheres() (4 input parameters) Param[2]: radius1 (type: float) Param[3]: center2 (type: Vector3) Param[4]: radius2 (type: float) -Function 504: CheckCollisionBoxes() (2 input parameters) +Function 505: CheckCollisionBoxes() (2 input parameters) Name: CheckCollisionBoxes Return type: bool Description: Check collision between two bounding boxes Param[1]: box1 (type: BoundingBox) Param[2]: box2 (type: BoundingBox) -Function 505: CheckCollisionBoxSphere() (3 input parameters) +Function 506: CheckCollisionBoxSphere() (3 input parameters) Name: CheckCollisionBoxSphere Return type: bool Description: Check collision between box and sphere Param[1]: box (type: BoundingBox) Param[2]: center (type: Vector3) Param[3]: radius (type: float) -Function 506: GetRayCollisionSphere() (3 input parameters) +Function 507: GetRayCollisionSphere() (3 input parameters) Name: GetRayCollisionSphere Return type: RayCollision Description: Get collision info between ray and sphere Param[1]: ray (type: Ray) Param[2]: center (type: Vector3) Param[3]: radius (type: float) -Function 507: GetRayCollisionBox() (2 input parameters) +Function 508: GetRayCollisionBox() (2 input parameters) Name: GetRayCollisionBox Return type: RayCollision Description: Get collision info between ray and box Param[1]: ray (type: Ray) Param[2]: box (type: BoundingBox) -Function 508: GetRayCollisionMesh() (3 input parameters) +Function 509: GetRayCollisionMesh() (3 input parameters) Name: GetRayCollisionMesh Return type: RayCollision Description: Get collision info between ray and mesh Param[1]: ray (type: Ray) Param[2]: mesh (type: Mesh) Param[3]: transform (type: Matrix) -Function 509: GetRayCollisionTriangle() (4 input parameters) +Function 510: GetRayCollisionTriangle() (4 input parameters) Name: GetRayCollisionTriangle Return type: RayCollision Description: Get collision info between ray and triangle @@ -4266,7 +4278,7 @@ Function 509: GetRayCollisionTriangle() (4 input parameters) Param[2]: p1 (type: Vector3) Param[3]: p2 (type: Vector3) Param[4]: p3 (type: Vector3) -Function 510: GetRayCollisionQuad() (5 input parameters) +Function 511: GetRayCollisionQuad() (5 input parameters) Name: GetRayCollisionQuad Return type: RayCollision Description: Get collision info between ray and quad @@ -4275,158 +4287,158 @@ Function 510: GetRayCollisionQuad() (5 input parameters) Param[3]: p2 (type: Vector3) Param[4]: p3 (type: Vector3) Param[5]: p4 (type: Vector3) -Function 511: InitAudioDevice() (0 input parameters) +Function 512: InitAudioDevice() (0 input parameters) Name: InitAudioDevice Return type: void Description: Initialize audio device and context No input parameters -Function 512: CloseAudioDevice() (0 input parameters) +Function 513: CloseAudioDevice() (0 input parameters) Name: CloseAudioDevice Return type: void Description: Close the audio device and context No input parameters -Function 513: IsAudioDeviceReady() (0 input parameters) +Function 514: IsAudioDeviceReady() (0 input parameters) Name: IsAudioDeviceReady Return type: bool Description: Check if audio device has been initialized successfully No input parameters -Function 514: SetMasterVolume() (1 input parameters) +Function 515: SetMasterVolume() (1 input parameters) Name: SetMasterVolume Return type: void Description: Set master volume (listener) Param[1]: volume (type: float) -Function 515: GetMasterVolume() (0 input parameters) +Function 516: GetMasterVolume() (0 input parameters) Name: GetMasterVolume Return type: float Description: Get master volume (listener) No input parameters -Function 516: LoadWave() (1 input parameters) +Function 517: LoadWave() (1 input parameters) Name: LoadWave Return type: Wave Description: Load wave data from file Param[1]: fileName (type: const char *) -Function 517: LoadWaveFromMemory() (3 input parameters) +Function 518: LoadWaveFromMemory() (3 input parameters) Name: LoadWaveFromMemory Return type: Wave Description: Load wave from memory buffer, fileType refers to extension: i.e. '.wav' Param[1]: fileType (type: const char *) Param[2]: fileData (type: const unsigned char *) Param[3]: dataSize (type: int) -Function 518: IsWaveReady() (1 input parameters) +Function 519: IsWaveReady() (1 input parameters) Name: IsWaveReady Return type: bool Description: Checks if wave data is ready Param[1]: wave (type: Wave) -Function 519: LoadSound() (1 input parameters) +Function 520: LoadSound() (1 input parameters) Name: LoadSound Return type: Sound Description: Load sound from file Param[1]: fileName (type: const char *) -Function 520: LoadSoundFromWave() (1 input parameters) +Function 521: LoadSoundFromWave() (1 input parameters) Name: LoadSoundFromWave Return type: Sound Description: Load sound from wave data Param[1]: wave (type: Wave) -Function 521: LoadSoundAlias() (1 input parameters) +Function 522: LoadSoundAlias() (1 input parameters) Name: LoadSoundAlias Return type: Sound Description: Create a new sound that shares the same sample data as the source sound, does not own the sound data Param[1]: source (type: Sound) -Function 522: IsSoundReady() (1 input parameters) +Function 523: IsSoundReady() (1 input parameters) Name: IsSoundReady Return type: bool Description: Checks if a sound is ready Param[1]: sound (type: Sound) -Function 523: UpdateSound() (3 input parameters) +Function 524: UpdateSound() (3 input parameters) Name: UpdateSound Return type: void Description: Update sound buffer with new data Param[1]: sound (type: Sound) Param[2]: data (type: const void *) Param[3]: sampleCount (type: int) -Function 524: UnloadWave() (1 input parameters) +Function 525: UnloadWave() (1 input parameters) Name: UnloadWave Return type: void Description: Unload wave data Param[1]: wave (type: Wave) -Function 525: UnloadSound() (1 input parameters) +Function 526: UnloadSound() (1 input parameters) Name: UnloadSound Return type: void Description: Unload sound Param[1]: sound (type: Sound) -Function 526: UnloadSoundAlias() (1 input parameters) +Function 527: UnloadSoundAlias() (1 input parameters) Name: UnloadSoundAlias Return type: void Description: Unload a sound alias (does not deallocate sample data) Param[1]: alias (type: Sound) -Function 527: ExportWave() (2 input parameters) +Function 528: ExportWave() (2 input parameters) Name: ExportWave Return type: bool Description: Export wave data to file, returns true on success Param[1]: wave (type: Wave) Param[2]: fileName (type: const char *) -Function 528: ExportWaveAsCode() (2 input parameters) +Function 529: ExportWaveAsCode() (2 input parameters) Name: ExportWaveAsCode Return type: bool Description: Export wave sample data to code (.h), returns true on success Param[1]: wave (type: Wave) Param[2]: fileName (type: const char *) -Function 529: PlaySound() (1 input parameters) +Function 530: PlaySound() (1 input parameters) Name: PlaySound Return type: void Description: Play a sound Param[1]: sound (type: Sound) -Function 530: StopSound() (1 input parameters) +Function 531: StopSound() (1 input parameters) Name: StopSound Return type: void Description: Stop playing a sound Param[1]: sound (type: Sound) -Function 531: PauseSound() (1 input parameters) +Function 532: PauseSound() (1 input parameters) Name: PauseSound Return type: void Description: Pause a sound Param[1]: sound (type: Sound) -Function 532: ResumeSound() (1 input parameters) +Function 533: ResumeSound() (1 input parameters) Name: ResumeSound Return type: void Description: Resume a paused sound Param[1]: sound (type: Sound) -Function 533: IsSoundPlaying() (1 input parameters) +Function 534: IsSoundPlaying() (1 input parameters) Name: IsSoundPlaying Return type: bool Description: Check if a sound is currently playing Param[1]: sound (type: Sound) -Function 534: SetSoundVolume() (2 input parameters) +Function 535: SetSoundVolume() (2 input parameters) Name: SetSoundVolume Return type: void Description: Set volume for a sound (1.0 is max level) Param[1]: sound (type: Sound) Param[2]: volume (type: float) -Function 535: SetSoundPitch() (2 input parameters) +Function 536: SetSoundPitch() (2 input parameters) Name: SetSoundPitch Return type: void Description: Set pitch for a sound (1.0 is base level) Param[1]: sound (type: Sound) Param[2]: pitch (type: float) -Function 536: SetSoundPan() (2 input parameters) +Function 537: SetSoundPan() (2 input parameters) Name: SetSoundPan Return type: void Description: Set pan for a sound (0.5 is center) Param[1]: sound (type: Sound) Param[2]: pan (type: float) -Function 537: WaveCopy() (1 input parameters) +Function 538: WaveCopy() (1 input parameters) Name: WaveCopy Return type: Wave Description: Copy a wave to a new wave Param[1]: wave (type: Wave) -Function 538: WaveCrop() (3 input parameters) +Function 539: WaveCrop() (3 input parameters) Name: WaveCrop Return type: void Description: Crop a wave to defined frames range Param[1]: wave (type: Wave *) Param[2]: initFrame (type: int) Param[3]: finalFrame (type: int) -Function 539: WaveFormat() (4 input parameters) +Function 540: WaveFormat() (4 input parameters) Name: WaveFormat Return type: void Description: Convert wave data to desired format @@ -4434,203 +4446,203 @@ Function 539: WaveFormat() (4 input parameters) Param[2]: sampleRate (type: int) Param[3]: sampleSize (type: int) Param[4]: channels (type: int) -Function 540: LoadWaveSamples() (1 input parameters) +Function 541: LoadWaveSamples() (1 input parameters) Name: LoadWaveSamples Return type: float * Description: Load samples data from wave as a 32bit float data array Param[1]: wave (type: Wave) -Function 541: UnloadWaveSamples() (1 input parameters) +Function 542: UnloadWaveSamples() (1 input parameters) Name: UnloadWaveSamples Return type: void Description: Unload samples data loaded with LoadWaveSamples() Param[1]: samples (type: float *) -Function 542: LoadMusicStream() (1 input parameters) +Function 543: LoadMusicStream() (1 input parameters) Name: LoadMusicStream Return type: Music Description: Load music stream from file Param[1]: fileName (type: const char *) -Function 543: LoadMusicStreamFromMemory() (3 input parameters) +Function 544: LoadMusicStreamFromMemory() (3 input parameters) Name: LoadMusicStreamFromMemory Return type: Music Description: Load music stream from data Param[1]: fileType (type: const char *) Param[2]: data (type: const unsigned char *) Param[3]: dataSize (type: int) -Function 544: IsMusicReady() (1 input parameters) +Function 545: IsMusicReady() (1 input parameters) Name: IsMusicReady Return type: bool Description: Checks if a music stream is ready Param[1]: music (type: Music) -Function 545: UnloadMusicStream() (1 input parameters) +Function 546: UnloadMusicStream() (1 input parameters) Name: UnloadMusicStream Return type: void Description: Unload music stream Param[1]: music (type: Music) -Function 546: PlayMusicStream() (1 input parameters) +Function 547: PlayMusicStream() (1 input parameters) Name: PlayMusicStream Return type: void Description: Start music playing Param[1]: music (type: Music) -Function 547: IsMusicStreamPlaying() (1 input parameters) +Function 548: IsMusicStreamPlaying() (1 input parameters) Name: IsMusicStreamPlaying Return type: bool Description: Check if music is playing Param[1]: music (type: Music) -Function 548: UpdateMusicStream() (1 input parameters) +Function 549: UpdateMusicStream() (1 input parameters) Name: UpdateMusicStream Return type: void Description: Updates buffers for music streaming Param[1]: music (type: Music) -Function 549: StopMusicStream() (1 input parameters) +Function 550: StopMusicStream() (1 input parameters) Name: StopMusicStream Return type: void Description: Stop music playing Param[1]: music (type: Music) -Function 550: PauseMusicStream() (1 input parameters) +Function 551: PauseMusicStream() (1 input parameters) Name: PauseMusicStream Return type: void Description: Pause music playing Param[1]: music (type: Music) -Function 551: ResumeMusicStream() (1 input parameters) +Function 552: ResumeMusicStream() (1 input parameters) Name: ResumeMusicStream Return type: void Description: Resume playing paused music Param[1]: music (type: Music) -Function 552: SeekMusicStream() (2 input parameters) +Function 553: SeekMusicStream() (2 input parameters) Name: SeekMusicStream Return type: void Description: Seek music to a position (in seconds) Param[1]: music (type: Music) Param[2]: position (type: float) -Function 553: SetMusicVolume() (2 input parameters) +Function 554: SetMusicVolume() (2 input parameters) Name: SetMusicVolume Return type: void Description: Set volume for music (1.0 is max level) Param[1]: music (type: Music) Param[2]: volume (type: float) -Function 554: SetMusicPitch() (2 input parameters) +Function 555: SetMusicPitch() (2 input parameters) Name: SetMusicPitch Return type: void Description: Set pitch for a music (1.0 is base level) Param[1]: music (type: Music) Param[2]: pitch (type: float) -Function 555: SetMusicPan() (2 input parameters) +Function 556: SetMusicPan() (2 input parameters) Name: SetMusicPan Return type: void Description: Set pan for a music (0.5 is center) Param[1]: music (type: Music) Param[2]: pan (type: float) -Function 556: GetMusicTimeLength() (1 input parameters) +Function 557: GetMusicTimeLength() (1 input parameters) Name: GetMusicTimeLength Return type: float Description: Get music time length (in seconds) Param[1]: music (type: Music) -Function 557: GetMusicTimePlayed() (1 input parameters) +Function 558: GetMusicTimePlayed() (1 input parameters) Name: GetMusicTimePlayed Return type: float Description: Get current music time played (in seconds) Param[1]: music (type: Music) -Function 558: LoadAudioStream() (3 input parameters) +Function 559: LoadAudioStream() (3 input parameters) Name: LoadAudioStream Return type: AudioStream Description: Load audio stream (to stream raw audio pcm data) Param[1]: sampleRate (type: unsigned int) Param[2]: sampleSize (type: unsigned int) Param[3]: channels (type: unsigned int) -Function 559: IsAudioStreamReady() (1 input parameters) +Function 560: IsAudioStreamReady() (1 input parameters) Name: IsAudioStreamReady Return type: bool Description: Checks if an audio stream is ready Param[1]: stream (type: AudioStream) -Function 560: UnloadAudioStream() (1 input parameters) +Function 561: UnloadAudioStream() (1 input parameters) Name: UnloadAudioStream Return type: void Description: Unload audio stream and free memory Param[1]: stream (type: AudioStream) -Function 561: UpdateAudioStream() (3 input parameters) +Function 562: UpdateAudioStream() (3 input parameters) Name: UpdateAudioStream Return type: void Description: Update audio stream buffers with data Param[1]: stream (type: AudioStream) Param[2]: data (type: const void *) Param[3]: frameCount (type: int) -Function 562: IsAudioStreamProcessed() (1 input parameters) +Function 563: IsAudioStreamProcessed() (1 input parameters) Name: IsAudioStreamProcessed Return type: bool Description: Check if any audio stream buffers requires refill Param[1]: stream (type: AudioStream) -Function 563: PlayAudioStream() (1 input parameters) +Function 564: PlayAudioStream() (1 input parameters) Name: PlayAudioStream Return type: void Description: Play audio stream Param[1]: stream (type: AudioStream) -Function 564: PauseAudioStream() (1 input parameters) +Function 565: PauseAudioStream() (1 input parameters) Name: PauseAudioStream Return type: void Description: Pause audio stream Param[1]: stream (type: AudioStream) -Function 565: ResumeAudioStream() (1 input parameters) +Function 566: ResumeAudioStream() (1 input parameters) Name: ResumeAudioStream Return type: void Description: Resume audio stream Param[1]: stream (type: AudioStream) -Function 566: IsAudioStreamPlaying() (1 input parameters) +Function 567: IsAudioStreamPlaying() (1 input parameters) Name: IsAudioStreamPlaying Return type: bool Description: Check if audio stream is playing Param[1]: stream (type: AudioStream) -Function 567: StopAudioStream() (1 input parameters) +Function 568: StopAudioStream() (1 input parameters) Name: StopAudioStream Return type: void Description: Stop audio stream Param[1]: stream (type: AudioStream) -Function 568: SetAudioStreamVolume() (2 input parameters) +Function 569: SetAudioStreamVolume() (2 input parameters) Name: SetAudioStreamVolume Return type: void Description: Set volume for audio stream (1.0 is max level) Param[1]: stream (type: AudioStream) Param[2]: volume (type: float) -Function 569: SetAudioStreamPitch() (2 input parameters) +Function 570: SetAudioStreamPitch() (2 input parameters) Name: SetAudioStreamPitch Return type: void Description: Set pitch for audio stream (1.0 is base level) Param[1]: stream (type: AudioStream) Param[2]: pitch (type: float) -Function 570: SetAudioStreamPan() (2 input parameters) +Function 571: SetAudioStreamPan() (2 input parameters) Name: SetAudioStreamPan Return type: void Description: Set pan for audio stream (0.5 is centered) Param[1]: stream (type: AudioStream) Param[2]: pan (type: float) -Function 571: SetAudioStreamBufferSizeDefault() (1 input parameters) +Function 572: SetAudioStreamBufferSizeDefault() (1 input parameters) Name: SetAudioStreamBufferSizeDefault Return type: void Description: Default size for new audio streams Param[1]: size (type: int) -Function 572: SetAudioStreamCallback() (2 input parameters) +Function 573: SetAudioStreamCallback() (2 input parameters) Name: SetAudioStreamCallback Return type: void Description: Audio thread callback to request new data Param[1]: stream (type: AudioStream) Param[2]: callback (type: AudioCallback) -Function 573: AttachAudioStreamProcessor() (2 input parameters) +Function 574: AttachAudioStreamProcessor() (2 input parameters) Name: AttachAudioStreamProcessor Return type: void Description: Attach audio stream processor to stream, receives the samples as 'float' Param[1]: stream (type: AudioStream) Param[2]: processor (type: AudioCallback) -Function 574: DetachAudioStreamProcessor() (2 input parameters) +Function 575: DetachAudioStreamProcessor() (2 input parameters) Name: DetachAudioStreamProcessor Return type: void Description: Detach audio stream processor from stream Param[1]: stream (type: AudioStream) Param[2]: processor (type: AudioCallback) -Function 575: AttachAudioMixedProcessor() (1 input parameters) +Function 576: AttachAudioMixedProcessor() (1 input parameters) Name: AttachAudioMixedProcessor Return type: void Description: Attach audio stream processor to the entire audio pipeline, receives the samples as 'float' Param[1]: processor (type: AudioCallback) -Function 576: DetachAudioMixedProcessor() (1 input parameters) +Function 577: DetachAudioMixedProcessor() (1 input parameters) Name: DetachAudioMixedProcessor Return type: void Description: Detach audio stream processor from the entire audio pipeline diff --git a/parser/output/raylib_api.xml b/parser/output/raylib_api.xml index 6bd5a4581..13ea5b7ab 100644 --- a/parser/output/raylib_api.xml +++ b/parser/output/raylib_api.xml @@ -160,7 +160,7 @@ - + @@ -172,8 +172,10 @@ - - + + + + @@ -505,7 +507,7 @@ - + @@ -532,6 +534,9 @@ + + + @@ -670,7 +675,7 @@ - + @@ -2822,6 +2827,11 @@ + + + + + From e5d0cc978ae933ccccd41758d50d1cd57e3474d1 Mon Sep 17 00:00:00 2001 From: Ray Date: Fri, 20 Sep 2024 17:32:01 +0200 Subject: [PATCH 079/208] Some minor tweaks --- src/platforms/rcore_desktop_rgfw.c | 2 +- src/rlgl.h | 3 +++ src/rmodels.c | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/platforms/rcore_desktop_rgfw.c b/src/platforms/rcore_desktop_rgfw.c index 64ab432e6..ef01820cb 100644 --- a/src/platforms/rcore_desktop_rgfw.c +++ b/src/platforms/rcore_desktop_rgfw.c @@ -940,7 +940,7 @@ void PollInputEvents(void) SetupViewport(platform.window->r.w, platform.window->r.h); CORE.Window.screen.width = platform.window->r.w; CORE.Window.screen.height = platform.window->r.h; - CORE.Window.currentFbo.width = platform.window->r.w;; + CORE.Window.currentFbo.width = platform.window->r.w; CORE.Window.currentFbo.height = platform.window->r.h; CORE.Window.resizedLastFrame = true; } break; diff --git a/src/rlgl.h b/src/rlgl.h index b98934a11..83ef966ce 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -350,6 +350,9 @@ #ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS 7 #endif +#ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_INDICES + #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_INDICES 6 +#endif //---------------------------------------------------------------------------------- // Types and Structures Definition diff --git a/src/rmodels.c b/src/rmodels.c index 055fb1b1c..ebdd178fd 100644 --- a/src/rmodels.c +++ b/src/rmodels.c @@ -4377,7 +4377,7 @@ static Model LoadOBJ(const char *fileName) } // if this is a new material, we need to allocate a new mesh if (lastMaterial != -1 && objAttributes.material_ids[faceId] != lastMaterial) newMesh = true; - lastMaterial = objAttributes.material_ids[faceId];; + lastMaterial = objAttributes.material_ids[faceId]; if (newMesh) { From 212b1e5fe7a898729a5b24d6f4c1720c508cb0be Mon Sep 17 00:00:00 2001 From: Asdqwe Date: Sat, 21 Sep 2024 18:11:40 -0300 Subject: [PATCH 080/208] Fix rlgl standalone defaults (#4334) --- src/rlgl.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rlgl.h b/src/rlgl.h index 83ef966ce..875b568f5 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -351,7 +351,7 @@ #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS 7 #endif #ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_INDICES - #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_INDICES 6 + #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_INDICES 8 #endif //---------------------------------------------------------------------------------- @@ -4272,7 +4272,7 @@ void rlSetUniform(int locIndex, const void *value, int uniformType, int count) #endif case RL_SHADER_UNIFORM_SAMPLER2D: glUniform1iv(locIndex, count, (int *)value); break; default: TRACELOG(RL_LOG_WARNING, "SHADER: Failed to set uniform value, data type not recognized"); - + // TODO: Support glUniform1uiv(), glUniform2uiv(), glUniform3uiv(), glUniform4uiv() } #endif From 93379137664b33f7245cccf9542e0a4a0b9e30a8 Mon Sep 17 00:00:00 2001 From: Ridge3Dproductions <78836162+Ridge3Dproductions@users.noreply.github.com> Date: Sat, 21 Sep 2024 17:12:48 -0400 Subject: [PATCH 081/208] Projects: Fix CMake example project (#4332) * Update CMakeLists.txt Add missing link flags * Update README.md Remove unneeded flag because this flag is defined in the updated CMakeList file * Update CMakeLists.txt --- projects/CMake/CMakeLists.txt | 4 ++-- projects/CMake/README.md | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/projects/CMake/CMakeLists.txt b/projects/CMake/CMakeLists.txt index a95d68a4f..96e33f344 100644 --- a/projects/CMake/CMakeLists.txt +++ b/projects/CMake/CMakeLists.txt @@ -30,8 +30,8 @@ target_link_libraries(${PROJECT_NAME} raylib) # Web Configurations if (${PLATFORM} STREQUAL "Web") - # Tell Emscripten to build an example.html file. - set_target_properties(${PROJECT_NAME} PROPERTIES SUFFIX ".html") + set_target_properties(${PROJECT_NAME} PROPERTIES SUFFIX ".html") # Tell Emscripten to build an example.html file. + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s USE_GLFW=3 -s ASSERTIONS=1 -s WASM=1 -s ASYNCIFY -s GL_ENABLE_GET_PROC_ADDRESS=1") endif() # Checks if OSX and links appropriate frameworks (Only required on MacOS) diff --git a/projects/CMake/README.md b/projects/CMake/README.md index f7873c30f..fc4fe5542 100644 --- a/projects/CMake/README.md +++ b/projects/CMake/README.md @@ -22,6 +22,6 @@ Compiling for the web requires the [Emscripten SDK](https://emscripten.org/docs/ ``` bash mkdir build cd build -emcmake cmake .. -DPLATFORM=Web -DCMAKE_BUILD_TYPE=Release -DCMAKE_EXE_LINKER_FLAGS="-s USE_GLFW=3" -DCMAKE_EXECUTABLE_SUFFIX=".html" +emcmake cmake .. -DPLATFORM=Web -DCMAKE_BUILD_TYPE=Release -DCMAKE_EXECUTABLE_SUFFIX=".html" emmake make -``` \ No newline at end of file +``` From daaca40416f4d1006382ecd51457df89ace0e21d Mon Sep 17 00:00:00 2001 From: Daniil Kisel <56605335+KislyjKisel@users.noreply.github.com> Date: Sun, 22 Sep 2024 14:45:10 +0300 Subject: [PATCH 082/208] Update parser's readme to mirror fixed help text (#4336) --- parser/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/parser/README.md b/parser/README.md index 45a2689a0..6616cdc51 100644 --- a/parser/README.md +++ b/parser/README.md @@ -41,7 +41,7 @@ OPTIONS: -f, --format : Define output format for parser data. Supported types: DEFAULT, JSON, XML, LUA - -d, --define : Define functions specifiers (i.e. RLAPI for raylib.h, RMDEF for raymath.h, etc.) + -d, --define : Define functions specifiers (i.e. RLAPI for raylib.h, RMAPI for raymath.h, etc.) NOTE: If no specifier defined, defaults to: RLAPI -t, --truncate : Define string to truncate input after (i.e. "RLGL IMPLEMENTATION" for rlgl.h) @@ -56,7 +56,7 @@ EXAMPLES: > raylib_parser --output raylib_data.info --format XML Process to generate as XML text data - > raylib_parser --input raymath.h --output raymath_data.info --format XML + > raylib_parser --input raymath.h --output raymath_data.info --format XML --define RMAPI Process to generate as XML text data ``` From 7d3f04ca356c9a088e0901c7a179955683e66207 Mon Sep 17 00:00:00 2001 From: Daniil Kisel <56605335+KislyjKisel@users.noreply.github.com> Date: Sun, 22 Sep 2024 15:36:06 +0300 Subject: [PATCH 083/208] Update BINDINGS.md (#4337) Updated Lean4 bindings --- BINDINGS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BINDINGS.md b/BINDINGS.md index 6ac54498e..e79d39c36 100644 --- a/BINDINGS.md +++ b/BINDINGS.md @@ -81,7 +81,7 @@ Some people ported raylib to other languages in the form of bindings or wrappers | [raylib-bqn](https://github.com/Brian-ED/raylib-bqn) | **5.0** | [BQN](https://mlochbaum.github.io/BQN) | MIT | | [rayjs](https://github.com/mode777/rayjs) | 4.6-dev | [QuickJS](https://bellard.org/quickjs) | MIT | | [raylib-raku](https://github.com/vushu/raylib-raku) | **auto** | [Raku](https://www.raku.org) | Artistic License 2.0 | -| [Raylib.lean](https://github.com/KislyjKisel/Raylib.lean) | 4.5 | [Lean4](https://lean-lang.org) | BSD-3-Clause | +| [Raylib.lean](https://github.com/KislyjKisel/Raylib.lean) | **5.5-dev** | [Lean4](https://lean-lang.org) | BSD-3-Clause | | [raylib-cobol](https://codeberg.org/glowiak/raylib-cobol) | **auto** | [COBOL](https://gnucobol.sourceforge.io) | Public domain | | [raylib-apl](https://github.com/Brian-ED/raylib-apl) | **5.0** | [Dyalog APL](https://www.dyalog.com/) | MIT | From 1eb8ff5e54d73365997fec442103e686aaed1d90 Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 22 Sep 2024 18:05:58 +0200 Subject: [PATCH 084/208] `LoadFontDefault()`: Initialize glyphs and recs to zero #4319 --- src/rtext.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rtext.c b/src/rtext.c index 34b6fcedb..e4c89d5f1 100644 --- a/src/rtext.c +++ b/src/rtext.c @@ -260,8 +260,8 @@ extern void LoadFontDefault(void) // Allocate space for our characters info data // NOTE: This memory must be freed at end! --> Done by CloseWindow() - defaultFont.glyphs = (GlyphInfo *)RL_MALLOC(defaultFont.glyphCount*sizeof(GlyphInfo)); - defaultFont.recs = (Rectangle *)RL_MALLOC(defaultFont.glyphCount*sizeof(Rectangle)); + defaultFont.glyphs = (GlyphInfo *)RL_CALLOC(defaultFont.glyphCount, sizeof(GlyphInfo)); + defaultFont.recs = (Rectangle *)RL_CALLOC(defaultFont.glyphCount, sizeof(Rectangle)); int currentLine = 0; int currentPosX = charsDivisor; From 55a25ac04bb448fcc17e9347314b56d5b6881ae0 Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 22 Sep 2024 22:11:08 +0200 Subject: [PATCH 085/208] ADDED: `MakeDirectory()` --- src/raylib.h | 1 + src/rcore.c | 47 +++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/src/raylib.h b/src/raylib.h index ee34b6441..f298fd731 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -1127,6 +1127,7 @@ RLAPI const char *GetDirectoryPath(const char *filePath); // Get full pa RLAPI const char *GetPrevDirectoryPath(const char *dirPath); // Get previous directory path for a given path (uses static string) RLAPI const char *GetWorkingDirectory(void); // Get current working directory (uses static string) RLAPI const char *GetApplicationDirectory(void); // Get the directory of the running application (uses static string) +RLAPI int MakeDirectory(const char *dirPath); // Create directories (including full path requested), returns 0 on success RLAPI bool ChangeDirectory(const char *dir); // Change working directory, return true on success RLAPI bool IsPathFile(const char *path); // Check if a given path is a file or a directory RLAPI bool IsFileNameValid(const char *fileName); // Check if fileName is valid for the platform/OS diff --git a/src/rcore.c b/src/rcore.c index 2fd79f5c9..1501aced1 100644 --- a/src/rcore.c +++ b/src/rcore.c @@ -191,16 +191,25 @@ unsigned int __stdcall timeEndPeriod(unsigned int uPeriod); #endif #if defined(_WIN32) - #include // Required for: _getch(), _chdir() + #include // Required for: _access() [Used in FileExists()] + #include // Required for: _getch(), _chdir(), _mkdir() #define GETCWD _getcwd // NOTE: MSDN recommends not to use getcwd(), chdir() #define CHDIR _chdir - #include // Required for: _access() [Used in FileExists()] #else #include // Required for: getch(), chdir() (POSIX), access() #define GETCWD getcwd #define CHDIR chdir #endif +#if defined(_MSC_VER) && ((defined(WIN32) || defined(_WIN32) || defined(__WIN32)) && !defined(__CYGWIN__)) + #include // Required for: _mkdir() + #define MKDIR(dir) _mkdir(dir) +#elif defined __GNUC__ + #include + #include // Required for: mkdir() + #define MKDIR(dir) mkdir(dir) // OLD: mkdir(dir, 0777) -> w64devkit complaints! +#endif + //---------------------------------------------------------------------------------- // Defines and Macros //---------------------------------------------------------------------------------- @@ -2267,6 +2276,40 @@ void UnloadDirectoryFiles(FilePathList files) RL_FREE(files.paths); } +// Create directories (including full path requested), returns 0 on success +int MakeDirectory(const char *dirPath) +{ + if ((dirPath == NULL) || (dirPath[0] == '\0')) return 1; // Path is not valid + if (DirectoryExists(dirPath)) return 0; // Path already exists (is valid) + + // Copy path string to avoid modifying original + int len = (int)strlen(dirPath) + 1; + char *pathcpy = (char *)RL_CALLOC(len, 1); + memcpy(pathcpy, dirPath, len); + + // Iterate over pathcpy, create each subdirectory as needed + for (int i = 0; (i < len) && (pathcpy[i] != '\0'); i++) + { + if (pathcpy[i] == ':') i++; + else + { + if ((pathcpy[i] == '\\') || (pathcpy[i] == '/')) + { + pathcpy[i] = '\0'; + if (!DirectoryExists(pathcpy)) MKDIR(pathcpy); + pathcpy[i] = '/'; + } + } + } + + // Create final directory + if (!DirectoryExists(pathcpy)) MKDIR(pathcpy); + + RL_FREE(pathcpy); + + return 0; +} + // Change working directory, returns true on success bool ChangeDirectory(const char *dir) { From 1c7b18923ca05e67309f9d8732fcca9a0b1de8df Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 22 Sep 2024 20:11:24 +0000 Subject: [PATCH 086/208] Update raylib_api.* by CI --- parser/output/raylib_api.json | 11 + parser/output/raylib_api.lua | 8 + parser/output/raylib_api.txt | 895 +++++++++++++++++----------------- parser/output/raylib_api.xml | 5 +- 4 files changed, 473 insertions(+), 446 deletions(-) diff --git a/parser/output/raylib_api.json b/parser/output/raylib_api.json index d1c58757b..2e599496d 100644 --- a/parser/output/raylib_api.json +++ b/parser/output/raylib_api.json @@ -4502,6 +4502,17 @@ "description": "Get the directory of the running application (uses static string)", "returnType": "const char *" }, + { + "name": "MakeDirectory", + "description": "Create directories (including full path requested), returns 0 on success", + "returnType": "int", + "params": [ + { + "type": "const char *", + "name": "dirPath" + } + ] + }, { "name": "ChangeDirectory", "description": "Change working directory, return true on success", diff --git a/parser/output/raylib_api.lua b/parser/output/raylib_api.lua index 0d99407b7..69ae07eda 100644 --- a/parser/output/raylib_api.lua +++ b/parser/output/raylib_api.lua @@ -4067,6 +4067,14 @@ return { description = "Get the directory of the running application (uses static string)", returnType = "const char *" }, + { + name = "MakeDirectory", + description = "Create directories (including full path requested), returns 0 on success", + returnType = "int", + params = { + {type = "const char *", name = "dirPath"} + } + }, { name = "ChangeDirectory", description = "Change working directory, return true on success", diff --git a/parser/output/raylib_api.txt b/parser/output/raylib_api.txt index 9c92906e0..458d12da0 100644 --- a/parser/output/raylib_api.txt +++ b/parser/output/raylib_api.txt @@ -989,7 +989,7 @@ Callback 006: AudioCallback() (2 input parameters) Param[1]: bufferData (type: void *) Param[2]: frames (type: unsigned int) -Functions found: 577 +Functions found: 578 Function 001: InitWindow() (3 input parameters) Name: InitWindow @@ -1704,373 +1704,378 @@ Function 133: GetApplicationDirectory() (0 input parameters) Return type: const char * Description: Get the directory of the running application (uses static string) No input parameters -Function 134: ChangeDirectory() (1 input parameters) +Function 134: MakeDirectory() (1 input parameters) + Name: MakeDirectory + Return type: int + Description: Create directories (including full path requested), returns 0 on success + Param[1]: dirPath (type: const char *) +Function 135: ChangeDirectory() (1 input parameters) Name: ChangeDirectory Return type: bool Description: Change working directory, return true on success Param[1]: dir (type: const char *) -Function 135: IsPathFile() (1 input parameters) +Function 136: IsPathFile() (1 input parameters) Name: IsPathFile Return type: bool Description: Check if a given path is a file or a directory Param[1]: path (type: const char *) -Function 136: IsFileNameValid() (1 input parameters) +Function 137: IsFileNameValid() (1 input parameters) Name: IsFileNameValid Return type: bool Description: Check if fileName is valid for the platform/OS Param[1]: fileName (type: const char *) -Function 137: LoadDirectoryFiles() (1 input parameters) +Function 138: LoadDirectoryFiles() (1 input parameters) Name: LoadDirectoryFiles Return type: FilePathList Description: Load directory filepaths Param[1]: dirPath (type: const char *) -Function 138: LoadDirectoryFilesEx() (3 input parameters) +Function 139: LoadDirectoryFilesEx() (3 input parameters) Name: LoadDirectoryFilesEx Return type: FilePathList Description: Load directory filepaths with extension filtering and recursive directory scan. Use 'DIR' in the filter string to include directories in the result Param[1]: basePath (type: const char *) Param[2]: filter (type: const char *) Param[3]: scanSubdirs (type: bool) -Function 139: UnloadDirectoryFiles() (1 input parameters) +Function 140: UnloadDirectoryFiles() (1 input parameters) Name: UnloadDirectoryFiles Return type: void Description: Unload filepaths Param[1]: files (type: FilePathList) -Function 140: IsFileDropped() (0 input parameters) +Function 141: IsFileDropped() (0 input parameters) Name: IsFileDropped Return type: bool Description: Check if a file has been dropped into window No input parameters -Function 141: LoadDroppedFiles() (0 input parameters) +Function 142: LoadDroppedFiles() (0 input parameters) Name: LoadDroppedFiles Return type: FilePathList Description: Load dropped filepaths No input parameters -Function 142: UnloadDroppedFiles() (1 input parameters) +Function 143: UnloadDroppedFiles() (1 input parameters) Name: UnloadDroppedFiles Return type: void Description: Unload dropped filepaths Param[1]: files (type: FilePathList) -Function 143: GetFileModTime() (1 input parameters) +Function 144: GetFileModTime() (1 input parameters) Name: GetFileModTime Return type: long Description: Get file modification time (last write time) Param[1]: fileName (type: const char *) -Function 144: CompressData() (3 input parameters) +Function 145: CompressData() (3 input parameters) Name: CompressData Return type: unsigned char * Description: Compress data (DEFLATE algorithm), memory must be MemFree() Param[1]: data (type: const unsigned char *) Param[2]: dataSize (type: int) Param[3]: compDataSize (type: int *) -Function 145: DecompressData() (3 input parameters) +Function 146: DecompressData() (3 input parameters) Name: DecompressData Return type: unsigned char * Description: Decompress data (DEFLATE algorithm), memory must be MemFree() Param[1]: compData (type: const unsigned char *) Param[2]: compDataSize (type: int) Param[3]: dataSize (type: int *) -Function 146: EncodeDataBase64() (3 input parameters) +Function 147: EncodeDataBase64() (3 input parameters) Name: EncodeDataBase64 Return type: char * Description: Encode data to Base64 string, memory must be MemFree() Param[1]: data (type: const unsigned char *) Param[2]: dataSize (type: int) Param[3]: outputSize (type: int *) -Function 147: DecodeDataBase64() (2 input parameters) +Function 148: DecodeDataBase64() (2 input parameters) Name: DecodeDataBase64 Return type: unsigned char * Description: Decode Base64 string data, memory must be MemFree() Param[1]: data (type: const unsigned char *) Param[2]: outputSize (type: int *) -Function 148: LoadAutomationEventList() (1 input parameters) +Function 149: LoadAutomationEventList() (1 input parameters) Name: LoadAutomationEventList Return type: AutomationEventList Description: Load automation events list from file, NULL for empty list, capacity = MAX_AUTOMATION_EVENTS Param[1]: fileName (type: const char *) -Function 149: UnloadAutomationEventList() (1 input parameters) +Function 150: UnloadAutomationEventList() (1 input parameters) Name: UnloadAutomationEventList Return type: void Description: Unload automation events list from file Param[1]: list (type: AutomationEventList) -Function 150: ExportAutomationEventList() (2 input parameters) +Function 151: ExportAutomationEventList() (2 input parameters) Name: ExportAutomationEventList Return type: bool Description: Export automation events list as text file Param[1]: list (type: AutomationEventList) Param[2]: fileName (type: const char *) -Function 151: SetAutomationEventList() (1 input parameters) +Function 152: SetAutomationEventList() (1 input parameters) Name: SetAutomationEventList Return type: void Description: Set automation event list to record to Param[1]: list (type: AutomationEventList *) -Function 152: SetAutomationEventBaseFrame() (1 input parameters) +Function 153: SetAutomationEventBaseFrame() (1 input parameters) Name: SetAutomationEventBaseFrame Return type: void Description: Set automation event internal base frame to start recording Param[1]: frame (type: int) -Function 153: StartAutomationEventRecording() (0 input parameters) +Function 154: StartAutomationEventRecording() (0 input parameters) Name: StartAutomationEventRecording Return type: void Description: Start recording automation events (AutomationEventList must be set) No input parameters -Function 154: StopAutomationEventRecording() (0 input parameters) +Function 155: StopAutomationEventRecording() (0 input parameters) Name: StopAutomationEventRecording Return type: void Description: Stop recording automation events No input parameters -Function 155: PlayAutomationEvent() (1 input parameters) +Function 156: PlayAutomationEvent() (1 input parameters) Name: PlayAutomationEvent Return type: void Description: Play a recorded automation event Param[1]: event (type: AutomationEvent) -Function 156: IsKeyPressed() (1 input parameters) +Function 157: IsKeyPressed() (1 input parameters) Name: IsKeyPressed Return type: bool Description: Check if a key has been pressed once Param[1]: key (type: int) -Function 157: IsKeyPressedRepeat() (1 input parameters) +Function 158: IsKeyPressedRepeat() (1 input parameters) Name: IsKeyPressedRepeat Return type: bool Description: Check if a key has been pressed again (Only PLATFORM_DESKTOP) Param[1]: key (type: int) -Function 158: IsKeyDown() (1 input parameters) +Function 159: IsKeyDown() (1 input parameters) Name: IsKeyDown Return type: bool Description: Check if a key is being pressed Param[1]: key (type: int) -Function 159: IsKeyReleased() (1 input parameters) +Function 160: IsKeyReleased() (1 input parameters) Name: IsKeyReleased Return type: bool Description: Check if a key has been released once Param[1]: key (type: int) -Function 160: IsKeyUp() (1 input parameters) +Function 161: IsKeyUp() (1 input parameters) Name: IsKeyUp Return type: bool Description: Check if a key is NOT being pressed Param[1]: key (type: int) -Function 161: GetKeyPressed() (0 input parameters) +Function 162: GetKeyPressed() (0 input parameters) Name: GetKeyPressed Return type: int Description: Get key pressed (keycode), call it multiple times for keys queued, returns 0 when the queue is empty No input parameters -Function 162: GetCharPressed() (0 input parameters) +Function 163: GetCharPressed() (0 input parameters) Name: GetCharPressed Return type: int Description: Get char pressed (unicode), call it multiple times for chars queued, returns 0 when the queue is empty No input parameters -Function 163: SetExitKey() (1 input parameters) +Function 164: SetExitKey() (1 input parameters) Name: SetExitKey Return type: void Description: Set a custom key to exit program (default is ESC) Param[1]: key (type: int) -Function 164: IsGamepadAvailable() (1 input parameters) +Function 165: IsGamepadAvailable() (1 input parameters) Name: IsGamepadAvailable Return type: bool Description: Check if a gamepad is available Param[1]: gamepad (type: int) -Function 165: GetGamepadName() (1 input parameters) +Function 166: GetGamepadName() (1 input parameters) Name: GetGamepadName Return type: const char * Description: Get gamepad internal name id Param[1]: gamepad (type: int) -Function 166: IsGamepadButtonPressed() (2 input parameters) +Function 167: IsGamepadButtonPressed() (2 input parameters) Name: IsGamepadButtonPressed Return type: bool Description: Check if a gamepad button has been pressed once Param[1]: gamepad (type: int) Param[2]: button (type: int) -Function 167: IsGamepadButtonDown() (2 input parameters) +Function 168: IsGamepadButtonDown() (2 input parameters) Name: IsGamepadButtonDown Return type: bool Description: Check if a gamepad button is being pressed Param[1]: gamepad (type: int) Param[2]: button (type: int) -Function 168: IsGamepadButtonReleased() (2 input parameters) +Function 169: IsGamepadButtonReleased() (2 input parameters) Name: IsGamepadButtonReleased Return type: bool Description: Check if a gamepad button has been released once Param[1]: gamepad (type: int) Param[2]: button (type: int) -Function 169: IsGamepadButtonUp() (2 input parameters) +Function 170: IsGamepadButtonUp() (2 input parameters) Name: IsGamepadButtonUp Return type: bool Description: Check if a gamepad button is NOT being pressed Param[1]: gamepad (type: int) Param[2]: button (type: int) -Function 170: GetGamepadButtonPressed() (0 input parameters) +Function 171: GetGamepadButtonPressed() (0 input parameters) Name: GetGamepadButtonPressed Return type: int Description: Get the last gamepad button pressed No input parameters -Function 171: GetGamepadAxisCount() (1 input parameters) +Function 172: GetGamepadAxisCount() (1 input parameters) Name: GetGamepadAxisCount Return type: int Description: Get gamepad axis count for a gamepad Param[1]: gamepad (type: int) -Function 172: GetGamepadAxisMovement() (2 input parameters) +Function 173: GetGamepadAxisMovement() (2 input parameters) Name: GetGamepadAxisMovement Return type: float Description: Get axis movement value for a gamepad axis Param[1]: gamepad (type: int) Param[2]: axis (type: int) -Function 173: SetGamepadMappings() (1 input parameters) +Function 174: SetGamepadMappings() (1 input parameters) Name: SetGamepadMappings Return type: int Description: Set internal gamepad mappings (SDL_GameControllerDB) Param[1]: mappings (type: const char *) -Function 174: SetGamepadVibration() (3 input parameters) +Function 175: SetGamepadVibration() (3 input parameters) Name: SetGamepadVibration Return type: void Description: Set gamepad vibration for both motors Param[1]: gamepad (type: int) Param[2]: leftMotor (type: float) Param[3]: rightMotor (type: float) -Function 175: IsMouseButtonPressed() (1 input parameters) +Function 176: IsMouseButtonPressed() (1 input parameters) Name: IsMouseButtonPressed Return type: bool Description: Check if a mouse button has been pressed once Param[1]: button (type: int) -Function 176: IsMouseButtonDown() (1 input parameters) +Function 177: IsMouseButtonDown() (1 input parameters) Name: IsMouseButtonDown Return type: bool Description: Check if a mouse button is being pressed Param[1]: button (type: int) -Function 177: IsMouseButtonReleased() (1 input parameters) +Function 178: IsMouseButtonReleased() (1 input parameters) Name: IsMouseButtonReleased Return type: bool Description: Check if a mouse button has been released once Param[1]: button (type: int) -Function 178: IsMouseButtonUp() (1 input parameters) +Function 179: IsMouseButtonUp() (1 input parameters) Name: IsMouseButtonUp Return type: bool Description: Check if a mouse button is NOT being pressed Param[1]: button (type: int) -Function 179: GetMouseX() (0 input parameters) +Function 180: GetMouseX() (0 input parameters) Name: GetMouseX Return type: int Description: Get mouse position X No input parameters -Function 180: GetMouseY() (0 input parameters) +Function 181: GetMouseY() (0 input parameters) Name: GetMouseY Return type: int Description: Get mouse position Y No input parameters -Function 181: GetMousePosition() (0 input parameters) +Function 182: GetMousePosition() (0 input parameters) Name: GetMousePosition Return type: Vector2 Description: Get mouse position XY No input parameters -Function 182: GetMouseDelta() (0 input parameters) +Function 183: GetMouseDelta() (0 input parameters) Name: GetMouseDelta Return type: Vector2 Description: Get mouse delta between frames No input parameters -Function 183: SetMousePosition() (2 input parameters) +Function 184: SetMousePosition() (2 input parameters) Name: SetMousePosition Return type: void Description: Set mouse position XY Param[1]: x (type: int) Param[2]: y (type: int) -Function 184: SetMouseOffset() (2 input parameters) +Function 185: SetMouseOffset() (2 input parameters) Name: SetMouseOffset Return type: void Description: Set mouse offset Param[1]: offsetX (type: int) Param[2]: offsetY (type: int) -Function 185: SetMouseScale() (2 input parameters) +Function 186: SetMouseScale() (2 input parameters) Name: SetMouseScale Return type: void Description: Set mouse scaling Param[1]: scaleX (type: float) Param[2]: scaleY (type: float) -Function 186: GetMouseWheelMove() (0 input parameters) +Function 187: GetMouseWheelMove() (0 input parameters) Name: GetMouseWheelMove Return type: float Description: Get mouse wheel movement for X or Y, whichever is larger No input parameters -Function 187: GetMouseWheelMoveV() (0 input parameters) +Function 188: GetMouseWheelMoveV() (0 input parameters) Name: GetMouseWheelMoveV Return type: Vector2 Description: Get mouse wheel movement for both X and Y No input parameters -Function 188: SetMouseCursor() (1 input parameters) +Function 189: SetMouseCursor() (1 input parameters) Name: SetMouseCursor Return type: void Description: Set mouse cursor Param[1]: cursor (type: int) -Function 189: GetTouchX() (0 input parameters) +Function 190: GetTouchX() (0 input parameters) Name: GetTouchX Return type: int Description: Get touch position X for touch point 0 (relative to screen size) No input parameters -Function 190: GetTouchY() (0 input parameters) +Function 191: GetTouchY() (0 input parameters) Name: GetTouchY Return type: int Description: Get touch position Y for touch point 0 (relative to screen size) No input parameters -Function 191: GetTouchPosition() (1 input parameters) +Function 192: GetTouchPosition() (1 input parameters) Name: GetTouchPosition Return type: Vector2 Description: Get touch position XY for a touch point index (relative to screen size) Param[1]: index (type: int) -Function 192: GetTouchPointId() (1 input parameters) +Function 193: GetTouchPointId() (1 input parameters) Name: GetTouchPointId Return type: int Description: Get touch point identifier for given index Param[1]: index (type: int) -Function 193: GetTouchPointCount() (0 input parameters) +Function 194: GetTouchPointCount() (0 input parameters) Name: GetTouchPointCount Return type: int Description: Get number of touch points No input parameters -Function 194: SetGesturesEnabled() (1 input parameters) +Function 195: SetGesturesEnabled() (1 input parameters) Name: SetGesturesEnabled Return type: void Description: Enable a set of gestures using flags Param[1]: flags (type: unsigned int) -Function 195: IsGestureDetected() (1 input parameters) +Function 196: IsGestureDetected() (1 input parameters) Name: IsGestureDetected Return type: bool Description: Check if a gesture have been detected Param[1]: gesture (type: unsigned int) -Function 196: GetGestureDetected() (0 input parameters) +Function 197: GetGestureDetected() (0 input parameters) Name: GetGestureDetected Return type: int Description: Get latest detected gesture No input parameters -Function 197: GetGestureHoldDuration() (0 input parameters) +Function 198: GetGestureHoldDuration() (0 input parameters) Name: GetGestureHoldDuration Return type: float Description: Get gesture hold time in milliseconds No input parameters -Function 198: GetGestureDragVector() (0 input parameters) +Function 199: GetGestureDragVector() (0 input parameters) Name: GetGestureDragVector Return type: Vector2 Description: Get gesture drag vector No input parameters -Function 199: GetGestureDragAngle() (0 input parameters) +Function 200: GetGestureDragAngle() (0 input parameters) Name: GetGestureDragAngle Return type: float Description: Get gesture drag angle No input parameters -Function 200: GetGesturePinchVector() (0 input parameters) +Function 201: GetGesturePinchVector() (0 input parameters) Name: GetGesturePinchVector Return type: Vector2 Description: Get gesture pinch delta No input parameters -Function 201: GetGesturePinchAngle() (0 input parameters) +Function 202: GetGesturePinchAngle() (0 input parameters) Name: GetGesturePinchAngle Return type: float Description: Get gesture pinch angle No input parameters -Function 202: UpdateCamera() (2 input parameters) +Function 203: UpdateCamera() (2 input parameters) Name: UpdateCamera Return type: void Description: Update camera position for selected mode Param[1]: camera (type: Camera *) Param[2]: mode (type: int) -Function 203: UpdateCameraPro() (4 input parameters) +Function 204: UpdateCameraPro() (4 input parameters) Name: UpdateCameraPro Return type: void Description: Update camera movement/rotation @@ -2078,36 +2083,36 @@ Function 203: UpdateCameraPro() (4 input parameters) Param[2]: movement (type: Vector3) Param[3]: rotation (type: Vector3) Param[4]: zoom (type: float) -Function 204: SetShapesTexture() (2 input parameters) +Function 205: SetShapesTexture() (2 input parameters) Name: SetShapesTexture Return type: void Description: Set texture and rectangle to be used on shapes drawing Param[1]: texture (type: Texture2D) Param[2]: source (type: Rectangle) -Function 205: GetShapesTexture() (0 input parameters) +Function 206: GetShapesTexture() (0 input parameters) Name: GetShapesTexture Return type: Texture2D Description: Get texture that is used for shapes drawing No input parameters -Function 206: GetShapesTextureRectangle() (0 input parameters) +Function 207: GetShapesTextureRectangle() (0 input parameters) Name: GetShapesTextureRectangle Return type: Rectangle Description: Get texture source rectangle that is used for shapes drawing No input parameters -Function 207: DrawPixel() (3 input parameters) +Function 208: DrawPixel() (3 input parameters) Name: DrawPixel Return type: void Description: Draw a pixel Param[1]: posX (type: int) Param[2]: posY (type: int) Param[3]: color (type: Color) -Function 208: DrawPixelV() (2 input parameters) +Function 209: DrawPixelV() (2 input parameters) Name: DrawPixelV Return type: void Description: Draw a pixel (Vector version) Param[1]: position (type: Vector2) Param[2]: color (type: Color) -Function 209: DrawLine() (5 input parameters) +Function 210: DrawLine() (5 input parameters) Name: DrawLine Return type: void Description: Draw a line @@ -2116,14 +2121,14 @@ Function 209: DrawLine() (5 input parameters) Param[3]: endPosX (type: int) Param[4]: endPosY (type: int) Param[5]: color (type: Color) -Function 210: DrawLineV() (3 input parameters) +Function 211: DrawLineV() (3 input parameters) Name: DrawLineV Return type: void Description: Draw a line (using gl lines) Param[1]: startPos (type: Vector2) Param[2]: endPos (type: Vector2) Param[3]: color (type: Color) -Function 211: DrawLineEx() (4 input parameters) +Function 212: DrawLineEx() (4 input parameters) Name: DrawLineEx Return type: void Description: Draw a line (using triangles/quads) @@ -2131,14 +2136,14 @@ Function 211: DrawLineEx() (4 input parameters) Param[2]: endPos (type: Vector2) Param[3]: thick (type: float) Param[4]: color (type: Color) -Function 212: DrawLineStrip() (3 input parameters) +Function 213: DrawLineStrip() (3 input parameters) Name: DrawLineStrip Return type: void Description: Draw lines sequence (using gl lines) Param[1]: points (type: const Vector2 *) Param[2]: pointCount (type: int) Param[3]: color (type: Color) -Function 213: DrawLineBezier() (4 input parameters) +Function 214: DrawLineBezier() (4 input parameters) Name: DrawLineBezier Return type: void Description: Draw line segment cubic-bezier in-out interpolation @@ -2146,7 +2151,7 @@ Function 213: DrawLineBezier() (4 input parameters) Param[2]: endPos (type: Vector2) Param[3]: thick (type: float) Param[4]: color (type: Color) -Function 214: DrawCircle() (4 input parameters) +Function 215: DrawCircle() (4 input parameters) Name: DrawCircle Return type: void Description: Draw a color-filled circle @@ -2154,7 +2159,7 @@ Function 214: DrawCircle() (4 input parameters) Param[2]: centerY (type: int) Param[3]: radius (type: float) Param[4]: color (type: Color) -Function 215: DrawCircleSector() (6 input parameters) +Function 216: DrawCircleSector() (6 input parameters) Name: DrawCircleSector Return type: void Description: Draw a piece of a circle @@ -2164,7 +2169,7 @@ Function 215: DrawCircleSector() (6 input parameters) Param[4]: endAngle (type: float) Param[5]: segments (type: int) Param[6]: color (type: Color) -Function 216: DrawCircleSectorLines() (6 input parameters) +Function 217: DrawCircleSectorLines() (6 input parameters) Name: DrawCircleSectorLines Return type: void Description: Draw circle sector outline @@ -2174,7 +2179,7 @@ Function 216: DrawCircleSectorLines() (6 input parameters) Param[4]: endAngle (type: float) Param[5]: segments (type: int) Param[6]: color (type: Color) -Function 217: DrawCircleGradient() (5 input parameters) +Function 218: DrawCircleGradient() (5 input parameters) Name: DrawCircleGradient Return type: void Description: Draw a gradient-filled circle @@ -2183,14 +2188,14 @@ Function 217: DrawCircleGradient() (5 input parameters) Param[3]: radius (type: float) Param[4]: inner (type: Color) Param[5]: outer (type: Color) -Function 218: DrawCircleV() (3 input parameters) +Function 219: DrawCircleV() (3 input parameters) Name: DrawCircleV Return type: void Description: Draw a color-filled circle (Vector version) Param[1]: center (type: Vector2) Param[2]: radius (type: float) Param[3]: color (type: Color) -Function 219: DrawCircleLines() (4 input parameters) +Function 220: DrawCircleLines() (4 input parameters) Name: DrawCircleLines Return type: void Description: Draw circle outline @@ -2198,14 +2203,14 @@ Function 219: DrawCircleLines() (4 input parameters) Param[2]: centerY (type: int) Param[3]: radius (type: float) Param[4]: color (type: Color) -Function 220: DrawCircleLinesV() (3 input parameters) +Function 221: DrawCircleLinesV() (3 input parameters) Name: DrawCircleLinesV Return type: void Description: Draw circle outline (Vector version) Param[1]: center (type: Vector2) Param[2]: radius (type: float) Param[3]: color (type: Color) -Function 221: DrawEllipse() (5 input parameters) +Function 222: DrawEllipse() (5 input parameters) Name: DrawEllipse Return type: void Description: Draw ellipse @@ -2214,7 +2219,7 @@ Function 221: DrawEllipse() (5 input parameters) Param[3]: radiusH (type: float) Param[4]: radiusV (type: float) Param[5]: color (type: Color) -Function 222: DrawEllipseLines() (5 input parameters) +Function 223: DrawEllipseLines() (5 input parameters) Name: DrawEllipseLines Return type: void Description: Draw ellipse outline @@ -2223,7 +2228,7 @@ Function 222: DrawEllipseLines() (5 input parameters) Param[3]: radiusH (type: float) Param[4]: radiusV (type: float) Param[5]: color (type: Color) -Function 223: DrawRing() (7 input parameters) +Function 224: DrawRing() (7 input parameters) Name: DrawRing Return type: void Description: Draw ring @@ -2234,7 +2239,7 @@ Function 223: DrawRing() (7 input parameters) Param[5]: endAngle (type: float) Param[6]: segments (type: int) Param[7]: color (type: Color) -Function 224: DrawRingLines() (7 input parameters) +Function 225: DrawRingLines() (7 input parameters) Name: DrawRingLines Return type: void Description: Draw ring outline @@ -2245,7 +2250,7 @@ Function 224: DrawRingLines() (7 input parameters) Param[5]: endAngle (type: float) Param[6]: segments (type: int) Param[7]: color (type: Color) -Function 225: DrawRectangle() (5 input parameters) +Function 226: DrawRectangle() (5 input parameters) Name: DrawRectangle Return type: void Description: Draw a color-filled rectangle @@ -2254,20 +2259,20 @@ Function 225: DrawRectangle() (5 input parameters) Param[3]: width (type: int) Param[4]: height (type: int) Param[5]: color (type: Color) -Function 226: DrawRectangleV() (3 input parameters) +Function 227: DrawRectangleV() (3 input parameters) Name: DrawRectangleV Return type: void Description: Draw a color-filled rectangle (Vector version) Param[1]: position (type: Vector2) Param[2]: size (type: Vector2) Param[3]: color (type: Color) -Function 227: DrawRectangleRec() (2 input parameters) +Function 228: DrawRectangleRec() (2 input parameters) Name: DrawRectangleRec Return type: void Description: Draw a color-filled rectangle Param[1]: rec (type: Rectangle) Param[2]: color (type: Color) -Function 228: DrawRectanglePro() (4 input parameters) +Function 229: DrawRectanglePro() (4 input parameters) Name: DrawRectanglePro Return type: void Description: Draw a color-filled rectangle with pro parameters @@ -2275,7 +2280,7 @@ Function 228: DrawRectanglePro() (4 input parameters) Param[2]: origin (type: Vector2) Param[3]: rotation (type: float) Param[4]: color (type: Color) -Function 229: DrawRectangleGradientV() (6 input parameters) +Function 230: DrawRectangleGradientV() (6 input parameters) Name: DrawRectangleGradientV Return type: void Description: Draw a vertical-gradient-filled rectangle @@ -2285,7 +2290,7 @@ Function 229: DrawRectangleGradientV() (6 input parameters) Param[4]: height (type: int) Param[5]: top (type: Color) Param[6]: bottom (type: Color) -Function 230: DrawRectangleGradientH() (6 input parameters) +Function 231: DrawRectangleGradientH() (6 input parameters) Name: DrawRectangleGradientH Return type: void Description: Draw a horizontal-gradient-filled rectangle @@ -2295,7 +2300,7 @@ Function 230: DrawRectangleGradientH() (6 input parameters) Param[4]: height (type: int) Param[5]: left (type: Color) Param[6]: right (type: Color) -Function 231: DrawRectangleGradientEx() (5 input parameters) +Function 232: DrawRectangleGradientEx() (5 input parameters) Name: DrawRectangleGradientEx Return type: void Description: Draw a gradient-filled rectangle with custom vertex colors @@ -2304,7 +2309,7 @@ Function 231: DrawRectangleGradientEx() (5 input parameters) Param[3]: bottomLeft (type: Color) Param[4]: topRight (type: Color) Param[5]: bottomRight (type: Color) -Function 232: DrawRectangleLines() (5 input parameters) +Function 233: DrawRectangleLines() (5 input parameters) Name: DrawRectangleLines Return type: void Description: Draw rectangle outline @@ -2313,14 +2318,14 @@ Function 232: DrawRectangleLines() (5 input parameters) Param[3]: width (type: int) Param[4]: height (type: int) Param[5]: color (type: Color) -Function 233: DrawRectangleLinesEx() (3 input parameters) +Function 234: DrawRectangleLinesEx() (3 input parameters) Name: DrawRectangleLinesEx Return type: void Description: Draw rectangle outline with extended parameters Param[1]: rec (type: Rectangle) Param[2]: lineThick (type: float) Param[3]: color (type: Color) -Function 234: DrawRectangleRounded() (4 input parameters) +Function 235: DrawRectangleRounded() (4 input parameters) Name: DrawRectangleRounded Return type: void Description: Draw rectangle with rounded edges @@ -2328,7 +2333,7 @@ Function 234: DrawRectangleRounded() (4 input parameters) Param[2]: roundness (type: float) Param[3]: segments (type: int) Param[4]: color (type: Color) -Function 235: DrawRectangleRoundedLines() (4 input parameters) +Function 236: DrawRectangleRoundedLines() (4 input parameters) Name: DrawRectangleRoundedLines Return type: void Description: Draw rectangle lines with rounded edges @@ -2336,7 +2341,7 @@ Function 235: DrawRectangleRoundedLines() (4 input parameters) Param[2]: roundness (type: float) Param[3]: segments (type: int) Param[4]: color (type: Color) -Function 236: DrawRectangleRoundedLinesEx() (5 input parameters) +Function 237: DrawRectangleRoundedLinesEx() (5 input parameters) Name: DrawRectangleRoundedLinesEx Return type: void Description: Draw rectangle with rounded edges outline @@ -2345,7 +2350,7 @@ Function 236: DrawRectangleRoundedLinesEx() (5 input parameters) Param[3]: segments (type: int) Param[4]: lineThick (type: float) Param[5]: color (type: Color) -Function 237: DrawTriangle() (4 input parameters) +Function 238: DrawTriangle() (4 input parameters) Name: DrawTriangle Return type: void Description: Draw a color-filled triangle (vertex in counter-clockwise order!) @@ -2353,7 +2358,7 @@ Function 237: DrawTriangle() (4 input parameters) Param[2]: v2 (type: Vector2) Param[3]: v3 (type: Vector2) Param[4]: color (type: Color) -Function 238: DrawTriangleLines() (4 input parameters) +Function 239: DrawTriangleLines() (4 input parameters) Name: DrawTriangleLines Return type: void Description: Draw triangle outline (vertex in counter-clockwise order!) @@ -2361,21 +2366,21 @@ Function 238: DrawTriangleLines() (4 input parameters) Param[2]: v2 (type: Vector2) Param[3]: v3 (type: Vector2) Param[4]: color (type: Color) -Function 239: DrawTriangleFan() (3 input parameters) +Function 240: DrawTriangleFan() (3 input parameters) Name: DrawTriangleFan Return type: void Description: Draw a triangle fan defined by points (first vertex is the center) Param[1]: points (type: const Vector2 *) Param[2]: pointCount (type: int) Param[3]: color (type: Color) -Function 240: DrawTriangleStrip() (3 input parameters) +Function 241: DrawTriangleStrip() (3 input parameters) Name: DrawTriangleStrip Return type: void Description: Draw a triangle strip defined by points Param[1]: points (type: const Vector2 *) Param[2]: pointCount (type: int) Param[3]: color (type: Color) -Function 241: DrawPoly() (5 input parameters) +Function 242: DrawPoly() (5 input parameters) Name: DrawPoly Return type: void Description: Draw a regular polygon (Vector version) @@ -2384,7 +2389,7 @@ Function 241: DrawPoly() (5 input parameters) Param[3]: radius (type: float) Param[4]: rotation (type: float) Param[5]: color (type: Color) -Function 242: DrawPolyLines() (5 input parameters) +Function 243: DrawPolyLines() (5 input parameters) Name: DrawPolyLines Return type: void Description: Draw a polygon outline of n sides @@ -2393,7 +2398,7 @@ Function 242: DrawPolyLines() (5 input parameters) Param[3]: radius (type: float) Param[4]: rotation (type: float) Param[5]: color (type: Color) -Function 243: DrawPolyLinesEx() (6 input parameters) +Function 244: DrawPolyLinesEx() (6 input parameters) Name: DrawPolyLinesEx Return type: void Description: Draw a polygon outline of n sides with extended parameters @@ -2403,7 +2408,7 @@ Function 243: DrawPolyLinesEx() (6 input parameters) Param[4]: rotation (type: float) Param[5]: lineThick (type: float) Param[6]: color (type: Color) -Function 244: DrawSplineLinear() (4 input parameters) +Function 245: DrawSplineLinear() (4 input parameters) Name: DrawSplineLinear Return type: void Description: Draw spline: Linear, minimum 2 points @@ -2411,7 +2416,7 @@ Function 244: DrawSplineLinear() (4 input parameters) Param[2]: pointCount (type: int) Param[3]: thick (type: float) Param[4]: color (type: Color) -Function 245: DrawSplineBasis() (4 input parameters) +Function 246: DrawSplineBasis() (4 input parameters) Name: DrawSplineBasis Return type: void Description: Draw spline: B-Spline, minimum 4 points @@ -2419,7 +2424,7 @@ Function 245: DrawSplineBasis() (4 input parameters) Param[2]: pointCount (type: int) Param[3]: thick (type: float) Param[4]: color (type: Color) -Function 246: DrawSplineCatmullRom() (4 input parameters) +Function 247: DrawSplineCatmullRom() (4 input parameters) Name: DrawSplineCatmullRom Return type: void Description: Draw spline: Catmull-Rom, minimum 4 points @@ -2427,7 +2432,7 @@ Function 246: DrawSplineCatmullRom() (4 input parameters) Param[2]: pointCount (type: int) Param[3]: thick (type: float) Param[4]: color (type: Color) -Function 247: DrawSplineBezierQuadratic() (4 input parameters) +Function 248: DrawSplineBezierQuadratic() (4 input parameters) Name: DrawSplineBezierQuadratic Return type: void Description: Draw spline: Quadratic Bezier, minimum 3 points (1 control point): [p1, c2, p3, c4...] @@ -2435,7 +2440,7 @@ Function 247: DrawSplineBezierQuadratic() (4 input parameters) Param[2]: pointCount (type: int) Param[3]: thick (type: float) Param[4]: color (type: Color) -Function 248: DrawSplineBezierCubic() (4 input parameters) +Function 249: DrawSplineBezierCubic() (4 input parameters) Name: DrawSplineBezierCubic Return type: void Description: Draw spline: Cubic Bezier, minimum 4 points (2 control points): [p1, c2, c3, p4, c5, c6...] @@ -2443,7 +2448,7 @@ Function 248: DrawSplineBezierCubic() (4 input parameters) Param[2]: pointCount (type: int) Param[3]: thick (type: float) Param[4]: color (type: Color) -Function 249: DrawSplineSegmentLinear() (4 input parameters) +Function 250: DrawSplineSegmentLinear() (4 input parameters) Name: DrawSplineSegmentLinear Return type: void Description: Draw spline segment: Linear, 2 points @@ -2451,7 +2456,7 @@ Function 249: DrawSplineSegmentLinear() (4 input parameters) Param[2]: p2 (type: Vector2) Param[3]: thick (type: float) Param[4]: color (type: Color) -Function 250: DrawSplineSegmentBasis() (6 input parameters) +Function 251: DrawSplineSegmentBasis() (6 input parameters) Name: DrawSplineSegmentBasis Return type: void Description: Draw spline segment: B-Spline, 4 points @@ -2461,7 +2466,7 @@ Function 250: DrawSplineSegmentBasis() (6 input parameters) Param[4]: p4 (type: Vector2) Param[5]: thick (type: float) Param[6]: color (type: Color) -Function 251: DrawSplineSegmentCatmullRom() (6 input parameters) +Function 252: DrawSplineSegmentCatmullRom() (6 input parameters) Name: DrawSplineSegmentCatmullRom Return type: void Description: Draw spline segment: Catmull-Rom, 4 points @@ -2471,7 +2476,7 @@ Function 251: DrawSplineSegmentCatmullRom() (6 input parameters) Param[4]: p4 (type: Vector2) Param[5]: thick (type: float) Param[6]: color (type: Color) -Function 252: DrawSplineSegmentBezierQuadratic() (5 input parameters) +Function 253: DrawSplineSegmentBezierQuadratic() (5 input parameters) Name: DrawSplineSegmentBezierQuadratic Return type: void Description: Draw spline segment: Quadratic Bezier, 2 points, 1 control point @@ -2480,7 +2485,7 @@ Function 252: DrawSplineSegmentBezierQuadratic() (5 input parameters) Param[3]: p3 (type: Vector2) Param[4]: thick (type: float) Param[5]: color (type: Color) -Function 253: DrawSplineSegmentBezierCubic() (6 input parameters) +Function 254: DrawSplineSegmentBezierCubic() (6 input parameters) Name: DrawSplineSegmentBezierCubic Return type: void Description: Draw spline segment: Cubic Bezier, 2 points, 2 control points @@ -2490,14 +2495,14 @@ Function 253: DrawSplineSegmentBezierCubic() (6 input parameters) Param[4]: p4 (type: Vector2) Param[5]: thick (type: float) Param[6]: color (type: Color) -Function 254: GetSplinePointLinear() (3 input parameters) +Function 255: GetSplinePointLinear() (3 input parameters) Name: GetSplinePointLinear Return type: Vector2 Description: Get (evaluate) spline point: Linear Param[1]: startPos (type: Vector2) Param[2]: endPos (type: Vector2) Param[3]: t (type: float) -Function 255: GetSplinePointBasis() (5 input parameters) +Function 256: GetSplinePointBasis() (5 input parameters) Name: GetSplinePointBasis Return type: Vector2 Description: Get (evaluate) spline point: B-Spline @@ -2506,7 +2511,7 @@ Function 255: GetSplinePointBasis() (5 input parameters) Param[3]: p3 (type: Vector2) Param[4]: p4 (type: Vector2) Param[5]: t (type: float) -Function 256: GetSplinePointCatmullRom() (5 input parameters) +Function 257: GetSplinePointCatmullRom() (5 input parameters) Name: GetSplinePointCatmullRom Return type: Vector2 Description: Get (evaluate) spline point: Catmull-Rom @@ -2515,7 +2520,7 @@ Function 256: GetSplinePointCatmullRom() (5 input parameters) Param[3]: p3 (type: Vector2) Param[4]: p4 (type: Vector2) Param[5]: t (type: float) -Function 257: GetSplinePointBezierQuad() (4 input parameters) +Function 258: GetSplinePointBezierQuad() (4 input parameters) Name: GetSplinePointBezierQuad Return type: Vector2 Description: Get (evaluate) spline point: Quadratic Bezier @@ -2523,7 +2528,7 @@ Function 257: GetSplinePointBezierQuad() (4 input parameters) Param[2]: c2 (type: Vector2) Param[3]: p3 (type: Vector2) Param[4]: t (type: float) -Function 258: GetSplinePointBezierCubic() (5 input parameters) +Function 259: GetSplinePointBezierCubic() (5 input parameters) Name: GetSplinePointBezierCubic Return type: Vector2 Description: Get (evaluate) spline point: Cubic Bezier @@ -2532,13 +2537,13 @@ Function 258: GetSplinePointBezierCubic() (5 input parameters) Param[3]: c3 (type: Vector2) Param[4]: p4 (type: Vector2) Param[5]: t (type: float) -Function 259: CheckCollisionRecs() (2 input parameters) +Function 260: CheckCollisionRecs() (2 input parameters) Name: CheckCollisionRecs Return type: bool Description: Check collision between two rectangles Param[1]: rec1 (type: Rectangle) Param[2]: rec2 (type: Rectangle) -Function 260: CheckCollisionCircles() (4 input parameters) +Function 261: CheckCollisionCircles() (4 input parameters) Name: CheckCollisionCircles Return type: bool Description: Check collision between two circles @@ -2546,27 +2551,27 @@ Function 260: CheckCollisionCircles() (4 input parameters) Param[2]: radius1 (type: float) Param[3]: center2 (type: Vector2) Param[4]: radius2 (type: float) -Function 261: CheckCollisionCircleRec() (3 input parameters) +Function 262: CheckCollisionCircleRec() (3 input parameters) Name: CheckCollisionCircleRec Return type: bool Description: Check collision between circle and rectangle Param[1]: center (type: Vector2) Param[2]: radius (type: float) Param[3]: rec (type: Rectangle) -Function 262: CheckCollisionPointRec() (2 input parameters) +Function 263: CheckCollisionPointRec() (2 input parameters) Name: CheckCollisionPointRec Return type: bool Description: Check if point is inside rectangle Param[1]: point (type: Vector2) Param[2]: rec (type: Rectangle) -Function 263: CheckCollisionPointCircle() (3 input parameters) +Function 264: CheckCollisionPointCircle() (3 input parameters) Name: CheckCollisionPointCircle Return type: bool Description: Check if point is inside circle Param[1]: point (type: Vector2) Param[2]: center (type: Vector2) Param[3]: radius (type: float) -Function 264: CheckCollisionPointTriangle() (4 input parameters) +Function 265: CheckCollisionPointTriangle() (4 input parameters) Name: CheckCollisionPointTriangle Return type: bool Description: Check if point is inside a triangle @@ -2574,14 +2579,14 @@ Function 264: CheckCollisionPointTriangle() (4 input parameters) Param[2]: p1 (type: Vector2) Param[3]: p2 (type: Vector2) Param[4]: p3 (type: Vector2) -Function 265: CheckCollisionPointPoly() (3 input parameters) +Function 266: CheckCollisionPointPoly() (3 input parameters) Name: CheckCollisionPointPoly Return type: bool Description: Check if point is within a polygon described by array of vertices Param[1]: point (type: Vector2) Param[2]: points (type: const Vector2 *) Param[3]: pointCount (type: int) -Function 266: CheckCollisionLines() (5 input parameters) +Function 267: CheckCollisionLines() (5 input parameters) Name: CheckCollisionLines Return type: bool Description: Check the collision between two lines defined by two points each, returns collision point by reference @@ -2590,7 +2595,7 @@ Function 266: CheckCollisionLines() (5 input parameters) Param[3]: startPos2 (type: Vector2) Param[4]: endPos2 (type: Vector2) Param[5]: collisionPoint (type: Vector2 *) -Function 267: CheckCollisionPointLine() (4 input parameters) +Function 268: CheckCollisionPointLine() (4 input parameters) Name: CheckCollisionPointLine Return type: bool Description: Check if point belongs to line created between two points [p1] and [p2] with defined margin in pixels [threshold] @@ -2598,7 +2603,7 @@ Function 267: CheckCollisionPointLine() (4 input parameters) Param[2]: p1 (type: Vector2) Param[3]: p2 (type: Vector2) Param[4]: threshold (type: int) -Function 268: CheckCollisionCircleLine() (4 input parameters) +Function 269: CheckCollisionCircleLine() (4 input parameters) Name: CheckCollisionCircleLine Return type: bool Description: Check if circle collides with a line created betweeen two points [p1] and [p2] @@ -2606,18 +2611,18 @@ Function 268: CheckCollisionCircleLine() (4 input parameters) Param[2]: radius (type: float) Param[3]: p1 (type: Vector2) Param[4]: p2 (type: Vector2) -Function 269: GetCollisionRec() (2 input parameters) +Function 270: GetCollisionRec() (2 input parameters) Name: GetCollisionRec Return type: Rectangle Description: Get collision rectangle for two rectangles collision Param[1]: rec1 (type: Rectangle) Param[2]: rec2 (type: Rectangle) -Function 270: LoadImage() (1 input parameters) +Function 271: LoadImage() (1 input parameters) Name: LoadImage Return type: Image Description: Load image from file into CPU memory (RAM) Param[1]: fileName (type: const char *) -Function 271: LoadImageRaw() (5 input parameters) +Function 272: LoadImageRaw() (5 input parameters) Name: LoadImageRaw Return type: Image Description: Load image from RAW file data @@ -2626,20 +2631,20 @@ Function 271: LoadImageRaw() (5 input parameters) Param[3]: height (type: int) Param[4]: format (type: int) Param[5]: headerSize (type: int) -Function 272: LoadImageSvg() (3 input parameters) +Function 273: LoadImageSvg() (3 input parameters) Name: LoadImageSvg Return type: Image Description: Load image from SVG file data or string with specified size Param[1]: fileNameOrString (type: const char *) Param[2]: width (type: int) Param[3]: height (type: int) -Function 273: LoadImageAnim() (2 input parameters) +Function 274: LoadImageAnim() (2 input parameters) Name: LoadImageAnim Return type: Image Description: Load image sequence from file (frames appended to image.data) Param[1]: fileName (type: const char *) Param[2]: frames (type: int *) -Function 274: LoadImageAnimFromMemory() (4 input parameters) +Function 275: LoadImageAnimFromMemory() (4 input parameters) Name: LoadImageAnimFromMemory Return type: Image Description: Load image sequence from memory buffer @@ -2647,60 +2652,60 @@ Function 274: LoadImageAnimFromMemory() (4 input parameters) Param[2]: fileData (type: const unsigned char *) Param[3]: dataSize (type: int) Param[4]: frames (type: int *) -Function 275: LoadImageFromMemory() (3 input parameters) +Function 276: LoadImageFromMemory() (3 input parameters) Name: LoadImageFromMemory Return type: Image Description: Load image from memory buffer, fileType refers to extension: i.e. '.png' Param[1]: fileType (type: const char *) Param[2]: fileData (type: const unsigned char *) Param[3]: dataSize (type: int) -Function 276: LoadImageFromTexture() (1 input parameters) +Function 277: LoadImageFromTexture() (1 input parameters) Name: LoadImageFromTexture Return type: Image Description: Load image from GPU texture data Param[1]: texture (type: Texture2D) -Function 277: LoadImageFromScreen() (0 input parameters) +Function 278: LoadImageFromScreen() (0 input parameters) Name: LoadImageFromScreen Return type: Image Description: Load image from screen buffer and (screenshot) No input parameters -Function 278: IsImageReady() (1 input parameters) +Function 279: IsImageReady() (1 input parameters) Name: IsImageReady Return type: bool Description: Check if an image is ready Param[1]: image (type: Image) -Function 279: UnloadImage() (1 input parameters) +Function 280: UnloadImage() (1 input parameters) Name: UnloadImage Return type: void Description: Unload image from CPU memory (RAM) Param[1]: image (type: Image) -Function 280: ExportImage() (2 input parameters) +Function 281: ExportImage() (2 input parameters) Name: ExportImage Return type: bool Description: Export image data to file, returns true on success Param[1]: image (type: Image) Param[2]: fileName (type: const char *) -Function 281: ExportImageToMemory() (3 input parameters) +Function 282: ExportImageToMemory() (3 input parameters) Name: ExportImageToMemory Return type: unsigned char * Description: Export image to memory buffer Param[1]: image (type: Image) Param[2]: fileType (type: const char *) Param[3]: fileSize (type: int *) -Function 282: ExportImageAsCode() (2 input parameters) +Function 283: ExportImageAsCode() (2 input parameters) Name: ExportImageAsCode Return type: bool Description: Export image as code file defining an array of bytes, returns true on success Param[1]: image (type: Image) Param[2]: fileName (type: const char *) -Function 283: GenImageColor() (3 input parameters) +Function 284: GenImageColor() (3 input parameters) Name: GenImageColor Return type: Image Description: Generate image: plain color Param[1]: width (type: int) Param[2]: height (type: int) Param[3]: color (type: Color) -Function 284: GenImageGradientLinear() (5 input parameters) +Function 285: GenImageGradientLinear() (5 input parameters) Name: GenImageGradientLinear Return type: Image Description: Generate image: linear gradient, direction in degrees [0..360], 0=Vertical gradient @@ -2709,7 +2714,7 @@ Function 284: GenImageGradientLinear() (5 input parameters) Param[3]: direction (type: int) Param[4]: start (type: Color) Param[5]: end (type: Color) -Function 285: GenImageGradientRadial() (5 input parameters) +Function 286: GenImageGradientRadial() (5 input parameters) Name: GenImageGradientRadial Return type: Image Description: Generate image: radial gradient @@ -2718,7 +2723,7 @@ Function 285: GenImageGradientRadial() (5 input parameters) Param[3]: density (type: float) Param[4]: inner (type: Color) Param[5]: outer (type: Color) -Function 286: GenImageGradientSquare() (5 input parameters) +Function 287: GenImageGradientSquare() (5 input parameters) Name: GenImageGradientSquare Return type: Image Description: Generate image: square gradient @@ -2727,7 +2732,7 @@ Function 286: GenImageGradientSquare() (5 input parameters) Param[3]: density (type: float) Param[4]: inner (type: Color) Param[5]: outer (type: Color) -Function 287: GenImageChecked() (6 input parameters) +Function 288: GenImageChecked() (6 input parameters) Name: GenImageChecked Return type: Image Description: Generate image: checked @@ -2737,14 +2742,14 @@ Function 287: GenImageChecked() (6 input parameters) Param[4]: checksY (type: int) Param[5]: col1 (type: Color) Param[6]: col2 (type: Color) -Function 288: GenImageWhiteNoise() (3 input parameters) +Function 289: GenImageWhiteNoise() (3 input parameters) Name: GenImageWhiteNoise Return type: Image Description: Generate image: white noise Param[1]: width (type: int) Param[2]: height (type: int) Param[3]: factor (type: float) -Function 289: GenImagePerlinNoise() (5 input parameters) +Function 290: GenImagePerlinNoise() (5 input parameters) Name: GenImagePerlinNoise Return type: Image Description: Generate image: perlin noise @@ -2753,45 +2758,45 @@ Function 289: GenImagePerlinNoise() (5 input parameters) Param[3]: offsetX (type: int) Param[4]: offsetY (type: int) Param[5]: scale (type: float) -Function 290: GenImageCellular() (3 input parameters) +Function 291: GenImageCellular() (3 input parameters) Name: GenImageCellular Return type: Image Description: Generate image: cellular algorithm, bigger tileSize means bigger cells Param[1]: width (type: int) Param[2]: height (type: int) Param[3]: tileSize (type: int) -Function 291: GenImageText() (3 input parameters) +Function 292: GenImageText() (3 input parameters) Name: GenImageText Return type: Image Description: Generate image: grayscale image from text data Param[1]: width (type: int) Param[2]: height (type: int) Param[3]: text (type: const char *) -Function 292: ImageCopy() (1 input parameters) +Function 293: ImageCopy() (1 input parameters) Name: ImageCopy Return type: Image Description: Create an image duplicate (useful for transformations) Param[1]: image (type: Image) -Function 293: ImageFromImage() (2 input parameters) +Function 294: ImageFromImage() (2 input parameters) Name: ImageFromImage Return type: Image Description: Create an image from another image piece Param[1]: image (type: Image) Param[2]: rec (type: Rectangle) -Function 294: ImageFromChannel() (2 input parameters) +Function 295: ImageFromChannel() (2 input parameters) Name: ImageFromChannel Return type: Image Description: Create an image from a selected channel of another image (GRAYSCALE) Param[1]: image (type: Image) Param[2]: selectedChannel (type: int) -Function 295: ImageText() (3 input parameters) +Function 296: ImageText() (3 input parameters) Name: ImageText Return type: Image Description: Create an image from text (default font) Param[1]: text (type: const char *) Param[2]: fontSize (type: int) Param[3]: color (type: Color) -Function 296: ImageTextEx() (5 input parameters) +Function 297: ImageTextEx() (5 input parameters) Name: ImageTextEx Return type: Image Description: Create an image from text (custom sprite font) @@ -2800,76 +2805,76 @@ Function 296: ImageTextEx() (5 input parameters) Param[3]: fontSize (type: float) Param[4]: spacing (type: float) Param[5]: tint (type: Color) -Function 297: ImageFormat() (2 input parameters) +Function 298: ImageFormat() (2 input parameters) Name: ImageFormat Return type: void Description: Convert image data to desired format Param[1]: image (type: Image *) Param[2]: newFormat (type: int) -Function 298: ImageToPOT() (2 input parameters) +Function 299: ImageToPOT() (2 input parameters) Name: ImageToPOT Return type: void Description: Convert image to POT (power-of-two) Param[1]: image (type: Image *) Param[2]: fill (type: Color) -Function 299: ImageCrop() (2 input parameters) +Function 300: ImageCrop() (2 input parameters) Name: ImageCrop Return type: void Description: Crop an image to a defined rectangle Param[1]: image (type: Image *) Param[2]: crop (type: Rectangle) -Function 300: ImageAlphaCrop() (2 input parameters) +Function 301: ImageAlphaCrop() (2 input parameters) Name: ImageAlphaCrop Return type: void Description: Crop image depending on alpha value Param[1]: image (type: Image *) Param[2]: threshold (type: float) -Function 301: ImageAlphaClear() (3 input parameters) +Function 302: ImageAlphaClear() (3 input parameters) Name: ImageAlphaClear Return type: void Description: Clear alpha channel to desired color Param[1]: image (type: Image *) Param[2]: color (type: Color) Param[3]: threshold (type: float) -Function 302: ImageAlphaMask() (2 input parameters) +Function 303: ImageAlphaMask() (2 input parameters) Name: ImageAlphaMask Return type: void Description: Apply alpha mask to image Param[1]: image (type: Image *) Param[2]: alphaMask (type: Image) -Function 303: ImageAlphaPremultiply() (1 input parameters) +Function 304: ImageAlphaPremultiply() (1 input parameters) Name: ImageAlphaPremultiply Return type: void Description: Premultiply alpha channel Param[1]: image (type: Image *) -Function 304: ImageBlurGaussian() (2 input parameters) +Function 305: ImageBlurGaussian() (2 input parameters) Name: ImageBlurGaussian Return type: void Description: Apply Gaussian blur using a box blur approximation Param[1]: image (type: Image *) Param[2]: blurSize (type: int) -Function 305: ImageKernelConvolution() (3 input parameters) +Function 306: ImageKernelConvolution() (3 input parameters) Name: ImageKernelConvolution Return type: void Description: Apply custom square convolution kernel to image Param[1]: image (type: Image *) Param[2]: kernel (type: const float *) Param[3]: kernelSize (type: int) -Function 306: ImageResize() (3 input parameters) +Function 307: ImageResize() (3 input parameters) Name: ImageResize Return type: void Description: Resize image (Bicubic scaling algorithm) Param[1]: image (type: Image *) Param[2]: newWidth (type: int) Param[3]: newHeight (type: int) -Function 307: ImageResizeNN() (3 input parameters) +Function 308: ImageResizeNN() (3 input parameters) Name: ImageResizeNN Return type: void Description: Resize image (Nearest-Neighbor scaling algorithm) Param[1]: image (type: Image *) Param[2]: newWidth (type: int) Param[3]: newHeight (type: int) -Function 308: ImageResizeCanvas() (6 input parameters) +Function 309: ImageResizeCanvas() (6 input parameters) Name: ImageResizeCanvas Return type: void Description: Resize canvas and fill with color @@ -2879,12 +2884,12 @@ Function 308: ImageResizeCanvas() (6 input parameters) Param[4]: offsetX (type: int) Param[5]: offsetY (type: int) Param[6]: fill (type: Color) -Function 309: ImageMipmaps() (1 input parameters) +Function 310: ImageMipmaps() (1 input parameters) Name: ImageMipmaps Return type: void Description: Compute all mipmap levels for a provided image Param[1]: image (type: Image *) -Function 310: ImageDither() (5 input parameters) +Function 311: ImageDither() (5 input parameters) Name: ImageDither Return type: void Description: Dither image data to 16bpp or lower (Floyd-Steinberg dithering) @@ -2893,109 +2898,109 @@ Function 310: ImageDither() (5 input parameters) Param[3]: gBpp (type: int) Param[4]: bBpp (type: int) Param[5]: aBpp (type: int) -Function 311: ImageFlipVertical() (1 input parameters) +Function 312: ImageFlipVertical() (1 input parameters) Name: ImageFlipVertical Return type: void Description: Flip image vertically Param[1]: image (type: Image *) -Function 312: ImageFlipHorizontal() (1 input parameters) +Function 313: ImageFlipHorizontal() (1 input parameters) Name: ImageFlipHorizontal Return type: void Description: Flip image horizontally Param[1]: image (type: Image *) -Function 313: ImageRotate() (2 input parameters) +Function 314: ImageRotate() (2 input parameters) Name: ImageRotate Return type: void Description: Rotate image by input angle in degrees (-359 to 359) Param[1]: image (type: Image *) Param[2]: degrees (type: int) -Function 314: ImageRotateCW() (1 input parameters) +Function 315: ImageRotateCW() (1 input parameters) Name: ImageRotateCW Return type: void Description: Rotate image clockwise 90deg Param[1]: image (type: Image *) -Function 315: ImageRotateCCW() (1 input parameters) +Function 316: ImageRotateCCW() (1 input parameters) Name: ImageRotateCCW Return type: void Description: Rotate image counter-clockwise 90deg Param[1]: image (type: Image *) -Function 316: ImageColorTint() (2 input parameters) +Function 317: ImageColorTint() (2 input parameters) Name: ImageColorTint Return type: void Description: Modify image color: tint Param[1]: image (type: Image *) Param[2]: color (type: Color) -Function 317: ImageColorInvert() (1 input parameters) +Function 318: ImageColorInvert() (1 input parameters) Name: ImageColorInvert Return type: void Description: Modify image color: invert Param[1]: image (type: Image *) -Function 318: ImageColorGrayscale() (1 input parameters) +Function 319: ImageColorGrayscale() (1 input parameters) Name: ImageColorGrayscale Return type: void Description: Modify image color: grayscale Param[1]: image (type: Image *) -Function 319: ImageColorContrast() (2 input parameters) +Function 320: ImageColorContrast() (2 input parameters) Name: ImageColorContrast Return type: void Description: Modify image color: contrast (-100 to 100) Param[1]: image (type: Image *) Param[2]: contrast (type: float) -Function 320: ImageColorBrightness() (2 input parameters) +Function 321: ImageColorBrightness() (2 input parameters) Name: ImageColorBrightness Return type: void Description: Modify image color: brightness (-255 to 255) Param[1]: image (type: Image *) Param[2]: brightness (type: int) -Function 321: ImageColorReplace() (3 input parameters) +Function 322: ImageColorReplace() (3 input parameters) Name: ImageColorReplace Return type: void Description: Modify image color: replace color Param[1]: image (type: Image *) Param[2]: color (type: Color) Param[3]: replace (type: Color) -Function 322: LoadImageColors() (1 input parameters) +Function 323: LoadImageColors() (1 input parameters) Name: LoadImageColors Return type: Color * Description: Load color data from image as a Color array (RGBA - 32bit) Param[1]: image (type: Image) -Function 323: LoadImagePalette() (3 input parameters) +Function 324: LoadImagePalette() (3 input parameters) Name: LoadImagePalette Return type: Color * Description: Load colors palette from image as a Color array (RGBA - 32bit) Param[1]: image (type: Image) Param[2]: maxPaletteSize (type: int) Param[3]: colorCount (type: int *) -Function 324: UnloadImageColors() (1 input parameters) +Function 325: UnloadImageColors() (1 input parameters) Name: UnloadImageColors Return type: void Description: Unload color data loaded with LoadImageColors() Param[1]: colors (type: Color *) -Function 325: UnloadImagePalette() (1 input parameters) +Function 326: UnloadImagePalette() (1 input parameters) Name: UnloadImagePalette Return type: void Description: Unload colors palette loaded with LoadImagePalette() Param[1]: colors (type: Color *) -Function 326: GetImageAlphaBorder() (2 input parameters) +Function 327: GetImageAlphaBorder() (2 input parameters) Name: GetImageAlphaBorder Return type: Rectangle Description: Get image alpha border rectangle Param[1]: image (type: Image) Param[2]: threshold (type: float) -Function 327: GetImageColor() (3 input parameters) +Function 328: GetImageColor() (3 input parameters) Name: GetImageColor Return type: Color Description: Get image pixel color at (x, y) position Param[1]: image (type: Image) Param[2]: x (type: int) Param[3]: y (type: int) -Function 328: ImageClearBackground() (2 input parameters) +Function 329: ImageClearBackground() (2 input parameters) Name: ImageClearBackground Return type: void Description: Clear image background with given color Param[1]: dst (type: Image *) Param[2]: color (type: Color) -Function 329: ImageDrawPixel() (4 input parameters) +Function 330: ImageDrawPixel() (4 input parameters) Name: ImageDrawPixel Return type: void Description: Draw pixel within an image @@ -3003,14 +3008,14 @@ Function 329: ImageDrawPixel() (4 input parameters) Param[2]: posX (type: int) Param[3]: posY (type: int) Param[4]: color (type: Color) -Function 330: ImageDrawPixelV() (3 input parameters) +Function 331: ImageDrawPixelV() (3 input parameters) Name: ImageDrawPixelV Return type: void Description: Draw pixel within an image (Vector version) Param[1]: dst (type: Image *) Param[2]: position (type: Vector2) Param[3]: color (type: Color) -Function 331: ImageDrawLine() (6 input parameters) +Function 332: ImageDrawLine() (6 input parameters) Name: ImageDrawLine Return type: void Description: Draw line within an image @@ -3020,7 +3025,7 @@ Function 331: ImageDrawLine() (6 input parameters) Param[4]: endPosX (type: int) Param[5]: endPosY (type: int) Param[6]: color (type: Color) -Function 332: ImageDrawLineV() (4 input parameters) +Function 333: ImageDrawLineV() (4 input parameters) Name: ImageDrawLineV Return type: void Description: Draw line within an image (Vector version) @@ -3028,7 +3033,7 @@ Function 332: ImageDrawLineV() (4 input parameters) Param[2]: start (type: Vector2) Param[3]: end (type: Vector2) Param[4]: color (type: Color) -Function 333: ImageDrawLineEx() (5 input parameters) +Function 334: ImageDrawLineEx() (5 input parameters) Name: ImageDrawLineEx Return type: void Description: Draw a line defining thickness within an image @@ -3037,7 +3042,7 @@ Function 333: ImageDrawLineEx() (5 input parameters) Param[3]: end (type: Vector2) Param[4]: thick (type: int) Param[5]: color (type: Color) -Function 334: ImageDrawCircle() (5 input parameters) +Function 335: ImageDrawCircle() (5 input parameters) Name: ImageDrawCircle Return type: void Description: Draw a filled circle within an image @@ -3046,7 +3051,7 @@ Function 334: ImageDrawCircle() (5 input parameters) Param[3]: centerY (type: int) Param[4]: radius (type: int) Param[5]: color (type: Color) -Function 335: ImageDrawCircleV() (4 input parameters) +Function 336: ImageDrawCircleV() (4 input parameters) Name: ImageDrawCircleV Return type: void Description: Draw a filled circle within an image (Vector version) @@ -3054,7 +3059,7 @@ Function 335: ImageDrawCircleV() (4 input parameters) Param[2]: center (type: Vector2) Param[3]: radius (type: int) Param[4]: color (type: Color) -Function 336: ImageDrawCircleLines() (5 input parameters) +Function 337: ImageDrawCircleLines() (5 input parameters) Name: ImageDrawCircleLines Return type: void Description: Draw circle outline within an image @@ -3063,7 +3068,7 @@ Function 336: ImageDrawCircleLines() (5 input parameters) Param[3]: centerY (type: int) Param[4]: radius (type: int) Param[5]: color (type: Color) -Function 337: ImageDrawCircleLinesV() (4 input parameters) +Function 338: ImageDrawCircleLinesV() (4 input parameters) Name: ImageDrawCircleLinesV Return type: void Description: Draw circle outline within an image (Vector version) @@ -3071,7 +3076,7 @@ Function 337: ImageDrawCircleLinesV() (4 input parameters) Param[2]: center (type: Vector2) Param[3]: radius (type: int) Param[4]: color (type: Color) -Function 338: ImageDrawRectangle() (6 input parameters) +Function 339: ImageDrawRectangle() (6 input parameters) Name: ImageDrawRectangle Return type: void Description: Draw rectangle within an image @@ -3081,7 +3086,7 @@ Function 338: ImageDrawRectangle() (6 input parameters) Param[4]: width (type: int) Param[5]: height (type: int) Param[6]: color (type: Color) -Function 339: ImageDrawRectangleV() (4 input parameters) +Function 340: ImageDrawRectangleV() (4 input parameters) Name: ImageDrawRectangleV Return type: void Description: Draw rectangle within an image (Vector version) @@ -3089,14 +3094,14 @@ Function 339: ImageDrawRectangleV() (4 input parameters) Param[2]: position (type: Vector2) Param[3]: size (type: Vector2) Param[4]: color (type: Color) -Function 340: ImageDrawRectangleRec() (3 input parameters) +Function 341: ImageDrawRectangleRec() (3 input parameters) Name: ImageDrawRectangleRec Return type: void Description: Draw rectangle within an image Param[1]: dst (type: Image *) Param[2]: rec (type: Rectangle) Param[3]: color (type: Color) -Function 341: ImageDrawRectangleLines() (4 input parameters) +Function 342: ImageDrawRectangleLines() (4 input parameters) Name: ImageDrawRectangleLines Return type: void Description: Draw rectangle lines within an image @@ -3104,7 +3109,7 @@ Function 341: ImageDrawRectangleLines() (4 input parameters) Param[2]: rec (type: Rectangle) Param[3]: thick (type: int) Param[4]: color (type: Color) -Function 342: ImageDrawTriangle() (5 input parameters) +Function 343: ImageDrawTriangle() (5 input parameters) Name: ImageDrawTriangle Return type: void Description: Draw triangle within an image @@ -3113,7 +3118,7 @@ Function 342: ImageDrawTriangle() (5 input parameters) Param[3]: v2 (type: Vector2) Param[4]: v3 (type: Vector2) Param[5]: color (type: Color) -Function 343: ImageDrawTriangleEx() (7 input parameters) +Function 344: ImageDrawTriangleEx() (7 input parameters) Name: ImageDrawTriangleEx Return type: void Description: Draw triangle with interpolated colors within an image @@ -3124,7 +3129,7 @@ Function 343: ImageDrawTriangleEx() (7 input parameters) Param[5]: c1 (type: Color) Param[6]: c2 (type: Color) Param[7]: c3 (type: Color) -Function 344: ImageDrawTriangleLines() (5 input parameters) +Function 345: ImageDrawTriangleLines() (5 input parameters) Name: ImageDrawTriangleLines Return type: void Description: Draw triangle outline within an image @@ -3133,7 +3138,7 @@ Function 344: ImageDrawTriangleLines() (5 input parameters) Param[3]: v2 (type: Vector2) Param[4]: v3 (type: Vector2) Param[5]: color (type: Color) -Function 345: ImageDrawTriangleFan() (4 input parameters) +Function 346: ImageDrawTriangleFan() (4 input parameters) Name: ImageDrawTriangleFan Return type: void Description: Draw a triangle fan defined by points within an image (first vertex is the center) @@ -3141,7 +3146,7 @@ Function 345: ImageDrawTriangleFan() (4 input parameters) Param[2]: points (type: Vector2 *) Param[3]: pointCount (type: int) Param[4]: color (type: Color) -Function 346: ImageDrawTriangleStrip() (4 input parameters) +Function 347: ImageDrawTriangleStrip() (4 input parameters) Name: ImageDrawTriangleStrip Return type: void Description: Draw a triangle strip defined by points within an image @@ -3149,7 +3154,7 @@ Function 346: ImageDrawTriangleStrip() (4 input parameters) Param[2]: points (type: Vector2 *) Param[3]: pointCount (type: int) Param[4]: color (type: Color) -Function 347: ImageDraw() (5 input parameters) +Function 348: ImageDraw() (5 input parameters) Name: ImageDraw Return type: void Description: Draw a source image within a destination image (tint applied to source) @@ -3158,7 +3163,7 @@ Function 347: ImageDraw() (5 input parameters) Param[3]: srcRec (type: Rectangle) Param[4]: dstRec (type: Rectangle) Param[5]: tint (type: Color) -Function 348: ImageDrawText() (6 input parameters) +Function 349: ImageDrawText() (6 input parameters) Name: ImageDrawText Return type: void Description: Draw text (using default font) within an image (destination) @@ -3168,7 +3173,7 @@ Function 348: ImageDrawText() (6 input parameters) Param[4]: posY (type: int) Param[5]: fontSize (type: int) Param[6]: color (type: Color) -Function 349: ImageDrawTextEx() (7 input parameters) +Function 350: ImageDrawTextEx() (7 input parameters) Name: ImageDrawTextEx Return type: void Description: Draw text (custom sprite font) within an image (destination) @@ -3179,79 +3184,79 @@ Function 349: ImageDrawTextEx() (7 input parameters) Param[5]: fontSize (type: float) Param[6]: spacing (type: float) Param[7]: tint (type: Color) -Function 350: LoadTexture() (1 input parameters) +Function 351: LoadTexture() (1 input parameters) Name: LoadTexture Return type: Texture2D Description: Load texture from file into GPU memory (VRAM) Param[1]: fileName (type: const char *) -Function 351: LoadTextureFromImage() (1 input parameters) +Function 352: LoadTextureFromImage() (1 input parameters) Name: LoadTextureFromImage Return type: Texture2D Description: Load texture from image data Param[1]: image (type: Image) -Function 352: LoadTextureCubemap() (2 input parameters) +Function 353: LoadTextureCubemap() (2 input parameters) Name: LoadTextureCubemap Return type: TextureCubemap Description: Load cubemap from image, multiple image cubemap layouts supported Param[1]: image (type: Image) Param[2]: layout (type: int) -Function 353: LoadRenderTexture() (2 input parameters) +Function 354: LoadRenderTexture() (2 input parameters) Name: LoadRenderTexture Return type: RenderTexture2D Description: Load texture for rendering (framebuffer) Param[1]: width (type: int) Param[2]: height (type: int) -Function 354: IsTextureReady() (1 input parameters) +Function 355: IsTextureReady() (1 input parameters) Name: IsTextureReady Return type: bool Description: Check if a texture is ready Param[1]: texture (type: Texture2D) -Function 355: UnloadTexture() (1 input parameters) +Function 356: UnloadTexture() (1 input parameters) Name: UnloadTexture Return type: void Description: Unload texture from GPU memory (VRAM) Param[1]: texture (type: Texture2D) -Function 356: IsRenderTextureReady() (1 input parameters) +Function 357: IsRenderTextureReady() (1 input parameters) Name: IsRenderTextureReady Return type: bool Description: Check if a render texture is ready Param[1]: target (type: RenderTexture2D) -Function 357: UnloadRenderTexture() (1 input parameters) +Function 358: UnloadRenderTexture() (1 input parameters) Name: UnloadRenderTexture Return type: void Description: Unload render texture from GPU memory (VRAM) Param[1]: target (type: RenderTexture2D) -Function 358: UpdateTexture() (2 input parameters) +Function 359: UpdateTexture() (2 input parameters) Name: UpdateTexture Return type: void Description: Update GPU texture with new data Param[1]: texture (type: Texture2D) Param[2]: pixels (type: const void *) -Function 359: UpdateTextureRec() (3 input parameters) +Function 360: UpdateTextureRec() (3 input parameters) Name: UpdateTextureRec Return type: void Description: Update GPU texture rectangle with new data Param[1]: texture (type: Texture2D) Param[2]: rec (type: Rectangle) Param[3]: pixels (type: const void *) -Function 360: GenTextureMipmaps() (1 input parameters) +Function 361: GenTextureMipmaps() (1 input parameters) Name: GenTextureMipmaps Return type: void Description: Generate GPU mipmaps for a texture Param[1]: texture (type: Texture2D *) -Function 361: SetTextureFilter() (2 input parameters) +Function 362: SetTextureFilter() (2 input parameters) Name: SetTextureFilter Return type: void Description: Set texture scaling filter mode Param[1]: texture (type: Texture2D) Param[2]: filter (type: int) -Function 362: SetTextureWrap() (2 input parameters) +Function 363: SetTextureWrap() (2 input parameters) Name: SetTextureWrap Return type: void Description: Set texture wrapping mode Param[1]: texture (type: Texture2D) Param[2]: wrap (type: int) -Function 363: DrawTexture() (4 input parameters) +Function 364: DrawTexture() (4 input parameters) Name: DrawTexture Return type: void Description: Draw a Texture2D @@ -3259,14 +3264,14 @@ Function 363: DrawTexture() (4 input parameters) Param[2]: posX (type: int) Param[3]: posY (type: int) Param[4]: tint (type: Color) -Function 364: DrawTextureV() (3 input parameters) +Function 365: DrawTextureV() (3 input parameters) Name: DrawTextureV Return type: void Description: Draw a Texture2D with position defined as Vector2 Param[1]: texture (type: Texture2D) Param[2]: position (type: Vector2) Param[3]: tint (type: Color) -Function 365: DrawTextureEx() (5 input parameters) +Function 366: DrawTextureEx() (5 input parameters) Name: DrawTextureEx Return type: void Description: Draw a Texture2D with extended parameters @@ -3275,7 +3280,7 @@ Function 365: DrawTextureEx() (5 input parameters) Param[3]: rotation (type: float) Param[4]: scale (type: float) Param[5]: tint (type: Color) -Function 366: DrawTextureRec() (4 input parameters) +Function 367: DrawTextureRec() (4 input parameters) Name: DrawTextureRec Return type: void Description: Draw a part of a texture defined by a rectangle @@ -3283,7 +3288,7 @@ Function 366: DrawTextureRec() (4 input parameters) Param[2]: source (type: Rectangle) Param[3]: position (type: Vector2) Param[4]: tint (type: Color) -Function 367: DrawTexturePro() (6 input parameters) +Function 368: DrawTexturePro() (6 input parameters) Name: DrawTexturePro Return type: void Description: Draw a part of a texture defined by a rectangle with 'pro' parameters @@ -3293,7 +3298,7 @@ Function 367: DrawTexturePro() (6 input parameters) Param[4]: origin (type: Vector2) Param[5]: rotation (type: float) Param[6]: tint (type: Color) -Function 368: DrawTextureNPatch() (6 input parameters) +Function 369: DrawTextureNPatch() (6 input parameters) Name: DrawTextureNPatch Return type: void Description: Draws a texture (or part of it) that stretches or shrinks nicely @@ -3303,119 +3308,119 @@ Function 368: DrawTextureNPatch() (6 input parameters) Param[4]: origin (type: Vector2) Param[5]: rotation (type: float) Param[6]: tint (type: Color) -Function 369: ColorIsEqual() (2 input parameters) +Function 370: ColorIsEqual() (2 input parameters) Name: ColorIsEqual Return type: bool Description: Check if two colors are equal Param[1]: col1 (type: Color) Param[2]: col2 (type: Color) -Function 370: Fade() (2 input parameters) +Function 371: Fade() (2 input parameters) Name: Fade Return type: Color Description: Get color with alpha applied, alpha goes from 0.0f to 1.0f Param[1]: color (type: Color) Param[2]: alpha (type: float) -Function 371: ColorToInt() (1 input parameters) +Function 372: ColorToInt() (1 input parameters) Name: ColorToInt Return type: int Description: Get hexadecimal value for a Color (0xRRGGBBAA) Param[1]: color (type: Color) -Function 372: ColorNormalize() (1 input parameters) +Function 373: ColorNormalize() (1 input parameters) Name: ColorNormalize Return type: Vector4 Description: Get Color normalized as float [0..1] Param[1]: color (type: Color) -Function 373: ColorFromNormalized() (1 input parameters) +Function 374: ColorFromNormalized() (1 input parameters) Name: ColorFromNormalized Return type: Color Description: Get Color from normalized values [0..1] Param[1]: normalized (type: Vector4) -Function 374: ColorToHSV() (1 input parameters) +Function 375: ColorToHSV() (1 input parameters) Name: ColorToHSV Return type: Vector3 Description: Get HSV values for a Color, hue [0..360], saturation/value [0..1] Param[1]: color (type: Color) -Function 375: ColorFromHSV() (3 input parameters) +Function 376: ColorFromHSV() (3 input parameters) Name: ColorFromHSV Return type: Color Description: Get a Color from HSV values, hue [0..360], saturation/value [0..1] Param[1]: hue (type: float) Param[2]: saturation (type: float) Param[3]: value (type: float) -Function 376: ColorTint() (2 input parameters) +Function 377: ColorTint() (2 input parameters) Name: ColorTint Return type: Color Description: Get color multiplied with another color Param[1]: color (type: Color) Param[2]: tint (type: Color) -Function 377: ColorBrightness() (2 input parameters) +Function 378: ColorBrightness() (2 input parameters) Name: ColorBrightness Return type: Color Description: Get color with brightness correction, brightness factor goes from -1.0f to 1.0f Param[1]: color (type: Color) Param[2]: factor (type: float) -Function 378: ColorContrast() (2 input parameters) +Function 379: ColorContrast() (2 input parameters) Name: ColorContrast Return type: Color Description: Get color with contrast correction, contrast values between -1.0f and 1.0f Param[1]: color (type: Color) Param[2]: contrast (type: float) -Function 379: ColorAlpha() (2 input parameters) +Function 380: ColorAlpha() (2 input parameters) Name: ColorAlpha Return type: Color Description: Get color with alpha applied, alpha goes from 0.0f to 1.0f Param[1]: color (type: Color) Param[2]: alpha (type: float) -Function 380: ColorAlphaBlend() (3 input parameters) +Function 381: ColorAlphaBlend() (3 input parameters) Name: ColorAlphaBlend Return type: Color Description: Get src alpha-blended into dst color with tint Param[1]: dst (type: Color) Param[2]: src (type: Color) Param[3]: tint (type: Color) -Function 381: ColorLerp() (3 input parameters) +Function 382: ColorLerp() (3 input parameters) Name: ColorLerp Return type: Color Description: Get color lerp interpolation between two colors, factor [0.0f..1.0f] Param[1]: color1 (type: Color) Param[2]: color2 (type: Color) Param[3]: factor (type: float) -Function 382: GetColor() (1 input parameters) +Function 383: GetColor() (1 input parameters) Name: GetColor Return type: Color Description: Get Color structure from hexadecimal value Param[1]: hexValue (type: unsigned int) -Function 383: GetPixelColor() (2 input parameters) +Function 384: GetPixelColor() (2 input parameters) Name: GetPixelColor Return type: Color Description: Get Color from a source pixel pointer of certain format Param[1]: srcPtr (type: void *) Param[2]: format (type: int) -Function 384: SetPixelColor() (3 input parameters) +Function 385: SetPixelColor() (3 input parameters) Name: SetPixelColor Return type: void Description: Set color formatted into destination pixel pointer Param[1]: dstPtr (type: void *) Param[2]: color (type: Color) Param[3]: format (type: int) -Function 385: GetPixelDataSize() (3 input parameters) +Function 386: GetPixelDataSize() (3 input parameters) Name: GetPixelDataSize Return type: int Description: Get pixel data size in bytes for certain format Param[1]: width (type: int) Param[2]: height (type: int) Param[3]: format (type: int) -Function 386: GetFontDefault() (0 input parameters) +Function 387: GetFontDefault() (0 input parameters) Name: GetFontDefault Return type: Font Description: Get the default Font No input parameters -Function 387: LoadFont() (1 input parameters) +Function 388: LoadFont() (1 input parameters) Name: LoadFont Return type: Font Description: Load font from file into GPU memory (VRAM) Param[1]: fileName (type: const char *) -Function 388: LoadFontEx() (4 input parameters) +Function 389: LoadFontEx() (4 input parameters) Name: LoadFontEx Return type: Font Description: Load font from file with extended parameters, use NULL for codepoints and 0 for codepointCount to load the default character set, font size is provided in pixels height @@ -3423,14 +3428,14 @@ Function 388: LoadFontEx() (4 input parameters) Param[2]: fontSize (type: int) Param[3]: codepoints (type: int *) Param[4]: codepointCount (type: int) -Function 389: LoadFontFromImage() (3 input parameters) +Function 390: LoadFontFromImage() (3 input parameters) Name: LoadFontFromImage Return type: Font Description: Load font from Image (XNA style) Param[1]: image (type: Image) Param[2]: key (type: Color) Param[3]: firstChar (type: int) -Function 390: LoadFontFromMemory() (6 input parameters) +Function 391: LoadFontFromMemory() (6 input parameters) Name: LoadFontFromMemory Return type: Font Description: Load font from memory buffer, fileType refers to extension: i.e. '.ttf' @@ -3440,12 +3445,12 @@ Function 390: LoadFontFromMemory() (6 input parameters) Param[4]: fontSize (type: int) Param[5]: codepoints (type: int *) Param[6]: codepointCount (type: int) -Function 391: IsFontReady() (1 input parameters) +Function 392: IsFontReady() (1 input parameters) Name: IsFontReady Return type: bool Description: Check if a font is ready Param[1]: font (type: Font) -Function 392: LoadFontData() (6 input parameters) +Function 393: LoadFontData() (6 input parameters) Name: LoadFontData Return type: GlyphInfo * Description: Load font data for further use @@ -3455,7 +3460,7 @@ Function 392: LoadFontData() (6 input parameters) Param[4]: codepoints (type: int *) Param[5]: codepointCount (type: int) Param[6]: type (type: int) -Function 393: GenImageFontAtlas() (6 input parameters) +Function 394: GenImageFontAtlas() (6 input parameters) Name: GenImageFontAtlas Return type: Image Description: Generate image font atlas using chars info @@ -3465,30 +3470,30 @@ Function 393: GenImageFontAtlas() (6 input parameters) Param[4]: fontSize (type: int) Param[5]: padding (type: int) Param[6]: packMethod (type: int) -Function 394: UnloadFontData() (2 input parameters) +Function 395: UnloadFontData() (2 input parameters) Name: UnloadFontData Return type: void Description: Unload font chars info data (RAM) Param[1]: glyphs (type: GlyphInfo *) Param[2]: glyphCount (type: int) -Function 395: UnloadFont() (1 input parameters) +Function 396: UnloadFont() (1 input parameters) Name: UnloadFont Return type: void Description: Unload font from GPU memory (VRAM) Param[1]: font (type: Font) -Function 396: ExportFontAsCode() (2 input parameters) +Function 397: ExportFontAsCode() (2 input parameters) Name: ExportFontAsCode Return type: bool Description: Export font as code file, returns true on success Param[1]: font (type: Font) Param[2]: fileName (type: const char *) -Function 397: DrawFPS() (2 input parameters) +Function 398: DrawFPS() (2 input parameters) Name: DrawFPS Return type: void Description: Draw current FPS Param[1]: posX (type: int) Param[2]: posY (type: int) -Function 398: DrawText() (5 input parameters) +Function 399: DrawText() (5 input parameters) Name: DrawText Return type: void Description: Draw text (using default font) @@ -3497,7 +3502,7 @@ Function 398: DrawText() (5 input parameters) Param[3]: posY (type: int) Param[4]: fontSize (type: int) Param[5]: color (type: Color) -Function 399: DrawTextEx() (6 input parameters) +Function 400: DrawTextEx() (6 input parameters) Name: DrawTextEx Return type: void Description: Draw text using font and additional parameters @@ -3507,7 +3512,7 @@ Function 399: DrawTextEx() (6 input parameters) Param[4]: fontSize (type: float) Param[5]: spacing (type: float) Param[6]: tint (type: Color) -Function 400: DrawTextPro() (8 input parameters) +Function 401: DrawTextPro() (8 input parameters) Name: DrawTextPro Return type: void Description: Draw text using Font and pro parameters (rotation) @@ -3519,7 +3524,7 @@ Function 400: DrawTextPro() (8 input parameters) Param[6]: fontSize (type: float) Param[7]: spacing (type: float) Param[8]: tint (type: Color) -Function 401: DrawTextCodepoint() (5 input parameters) +Function 402: DrawTextCodepoint() (5 input parameters) Name: DrawTextCodepoint Return type: void Description: Draw one character (codepoint) @@ -3528,7 +3533,7 @@ Function 401: DrawTextCodepoint() (5 input parameters) Param[3]: position (type: Vector2) Param[4]: fontSize (type: float) Param[5]: tint (type: Color) -Function 402: DrawTextCodepoints() (7 input parameters) +Function 403: DrawTextCodepoints() (7 input parameters) Name: DrawTextCodepoints Return type: void Description: Draw multiple character (codepoint) @@ -3539,18 +3544,18 @@ Function 402: DrawTextCodepoints() (7 input parameters) Param[5]: fontSize (type: float) Param[6]: spacing (type: float) Param[7]: tint (type: Color) -Function 403: SetTextLineSpacing() (1 input parameters) +Function 404: SetTextLineSpacing() (1 input parameters) Name: SetTextLineSpacing Return type: void Description: Set vertical line spacing when drawing with line-breaks Param[1]: spacing (type: int) -Function 404: MeasureText() (2 input parameters) +Function 405: MeasureText() (2 input parameters) Name: MeasureText Return type: int Description: Measure string width for default font Param[1]: text (type: const char *) Param[2]: fontSize (type: int) -Function 405: MeasureTextEx() (4 input parameters) +Function 406: MeasureTextEx() (4 input parameters) Name: MeasureTextEx Return type: Vector2 Description: Measure string size for Font @@ -3558,195 +3563,195 @@ Function 405: MeasureTextEx() (4 input parameters) Param[2]: text (type: const char *) Param[3]: fontSize (type: float) Param[4]: spacing (type: float) -Function 406: GetGlyphIndex() (2 input parameters) +Function 407: GetGlyphIndex() (2 input parameters) Name: GetGlyphIndex Return type: int Description: Get glyph index position in font for a codepoint (unicode character), fallback to '?' if not found Param[1]: font (type: Font) Param[2]: codepoint (type: int) -Function 407: GetGlyphInfo() (2 input parameters) +Function 408: GetGlyphInfo() (2 input parameters) Name: GetGlyphInfo Return type: GlyphInfo Description: Get glyph font info data for a codepoint (unicode character), fallback to '?' if not found Param[1]: font (type: Font) Param[2]: codepoint (type: int) -Function 408: GetGlyphAtlasRec() (2 input parameters) +Function 409: GetGlyphAtlasRec() (2 input parameters) Name: GetGlyphAtlasRec Return type: Rectangle Description: Get glyph rectangle in font atlas for a codepoint (unicode character), fallback to '?' if not found Param[1]: font (type: Font) Param[2]: codepoint (type: int) -Function 409: LoadUTF8() (2 input parameters) +Function 410: LoadUTF8() (2 input parameters) Name: LoadUTF8 Return type: char * Description: Load UTF-8 text encoded from codepoints array Param[1]: codepoints (type: const int *) Param[2]: length (type: int) -Function 410: UnloadUTF8() (1 input parameters) +Function 411: UnloadUTF8() (1 input parameters) Name: UnloadUTF8 Return type: void Description: Unload UTF-8 text encoded from codepoints array Param[1]: text (type: char *) -Function 411: LoadCodepoints() (2 input parameters) +Function 412: LoadCodepoints() (2 input parameters) Name: LoadCodepoints Return type: int * Description: Load all codepoints from a UTF-8 text string, codepoints count returned by parameter Param[1]: text (type: const char *) Param[2]: count (type: int *) -Function 412: UnloadCodepoints() (1 input parameters) +Function 413: UnloadCodepoints() (1 input parameters) Name: UnloadCodepoints Return type: void Description: Unload codepoints data from memory Param[1]: codepoints (type: int *) -Function 413: GetCodepointCount() (1 input parameters) +Function 414: GetCodepointCount() (1 input parameters) Name: GetCodepointCount Return type: int Description: Get total number of codepoints in a UTF-8 encoded string Param[1]: text (type: const char *) -Function 414: GetCodepoint() (2 input parameters) +Function 415: GetCodepoint() (2 input parameters) Name: GetCodepoint Return type: int Description: Get next codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure Param[1]: text (type: const char *) Param[2]: codepointSize (type: int *) -Function 415: GetCodepointNext() (2 input parameters) +Function 416: GetCodepointNext() (2 input parameters) Name: GetCodepointNext Return type: int Description: Get next codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure Param[1]: text (type: const char *) Param[2]: codepointSize (type: int *) -Function 416: GetCodepointPrevious() (2 input parameters) +Function 417: GetCodepointPrevious() (2 input parameters) Name: GetCodepointPrevious Return type: int Description: Get previous codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure Param[1]: text (type: const char *) Param[2]: codepointSize (type: int *) -Function 417: CodepointToUTF8() (2 input parameters) +Function 418: CodepointToUTF8() (2 input parameters) Name: CodepointToUTF8 Return type: const char * Description: Encode one codepoint into UTF-8 byte array (array length returned as parameter) Param[1]: codepoint (type: int) Param[2]: utf8Size (type: int *) -Function 418: TextCopy() (2 input parameters) +Function 419: TextCopy() (2 input parameters) Name: TextCopy Return type: int Description: Copy one string to another, returns bytes copied Param[1]: dst (type: char *) Param[2]: src (type: const char *) -Function 419: TextIsEqual() (2 input parameters) +Function 420: TextIsEqual() (2 input parameters) Name: TextIsEqual Return type: bool Description: Check if two text string are equal Param[1]: text1 (type: const char *) Param[2]: text2 (type: const char *) -Function 420: TextLength() (1 input parameters) +Function 421: TextLength() (1 input parameters) Name: TextLength Return type: unsigned int Description: Get text length, checks for '\0' ending Param[1]: text (type: const char *) -Function 421: TextFormat() (2 input parameters) +Function 422: TextFormat() (2 input parameters) Name: TextFormat Return type: const char * Description: Text formatting with variables (sprintf() style) Param[1]: text (type: const char *) Param[2]: args (type: ...) -Function 422: TextSubtext() (3 input parameters) +Function 423: TextSubtext() (3 input parameters) Name: TextSubtext Return type: const char * Description: Get a piece of a text string Param[1]: text (type: const char *) Param[2]: position (type: int) Param[3]: length (type: int) -Function 423: TextReplace() (3 input parameters) +Function 424: TextReplace() (3 input parameters) Name: TextReplace Return type: char * Description: Replace text string (WARNING: memory must be freed!) Param[1]: text (type: const char *) Param[2]: replace (type: const char *) Param[3]: by (type: const char *) -Function 424: TextInsert() (3 input parameters) +Function 425: TextInsert() (3 input parameters) Name: TextInsert Return type: char * Description: Insert text in a position (WARNING: memory must be freed!) Param[1]: text (type: const char *) Param[2]: insert (type: const char *) Param[3]: position (type: int) -Function 425: TextJoin() (3 input parameters) +Function 426: TextJoin() (3 input parameters) Name: TextJoin Return type: const char * Description: Join text strings with delimiter Param[1]: textList (type: const char **) Param[2]: count (type: int) Param[3]: delimiter (type: const char *) -Function 426: TextSplit() (3 input parameters) +Function 427: TextSplit() (3 input parameters) Name: TextSplit Return type: const char ** Description: Split text into multiple strings Param[1]: text (type: const char *) Param[2]: delimiter (type: char) Param[3]: count (type: int *) -Function 427: TextAppend() (3 input parameters) +Function 428: TextAppend() (3 input parameters) Name: TextAppend Return type: void Description: Append text at specific position and move cursor! Param[1]: text (type: char *) Param[2]: append (type: const char *) Param[3]: position (type: int *) -Function 428: TextFindIndex() (2 input parameters) +Function 429: TextFindIndex() (2 input parameters) Name: TextFindIndex Return type: int Description: Find first text occurrence within a string Param[1]: text (type: const char *) Param[2]: find (type: const char *) -Function 429: TextToUpper() (1 input parameters) +Function 430: TextToUpper() (1 input parameters) Name: TextToUpper Return type: const char * Description: Get upper case version of provided string Param[1]: text (type: const char *) -Function 430: TextToLower() (1 input parameters) +Function 431: TextToLower() (1 input parameters) Name: TextToLower Return type: const char * Description: Get lower case version of provided string Param[1]: text (type: const char *) -Function 431: TextToPascal() (1 input parameters) +Function 432: TextToPascal() (1 input parameters) Name: TextToPascal Return type: const char * Description: Get Pascal case notation version of provided string Param[1]: text (type: const char *) -Function 432: TextToSnake() (1 input parameters) +Function 433: TextToSnake() (1 input parameters) Name: TextToSnake Return type: const char * Description: Get Snake case notation version of provided string Param[1]: text (type: const char *) -Function 433: TextToCamel() (1 input parameters) +Function 434: TextToCamel() (1 input parameters) Name: TextToCamel Return type: const char * Description: Get Camel case notation version of provided string Param[1]: text (type: const char *) -Function 434: TextToInteger() (1 input parameters) +Function 435: TextToInteger() (1 input parameters) Name: TextToInteger Return type: int Description: Get integer value from text (negative values not supported) Param[1]: text (type: const char *) -Function 435: TextToFloat() (1 input parameters) +Function 436: TextToFloat() (1 input parameters) Name: TextToFloat Return type: float Description: Get float value from text (negative values not supported) Param[1]: text (type: const char *) -Function 436: DrawLine3D() (3 input parameters) +Function 437: DrawLine3D() (3 input parameters) Name: DrawLine3D Return type: void Description: Draw a line in 3D world space Param[1]: startPos (type: Vector3) Param[2]: endPos (type: Vector3) Param[3]: color (type: Color) -Function 437: DrawPoint3D() (2 input parameters) +Function 438: DrawPoint3D() (2 input parameters) Name: DrawPoint3D Return type: void Description: Draw a point in 3D space, actually a small line Param[1]: position (type: Vector3) Param[2]: color (type: Color) -Function 438: DrawCircle3D() (5 input parameters) +Function 439: DrawCircle3D() (5 input parameters) Name: DrawCircle3D Return type: void Description: Draw a circle in 3D world space @@ -3755,7 +3760,7 @@ Function 438: DrawCircle3D() (5 input parameters) Param[3]: rotationAxis (type: Vector3) Param[4]: rotationAngle (type: float) Param[5]: color (type: Color) -Function 439: DrawTriangle3D() (4 input parameters) +Function 440: DrawTriangle3D() (4 input parameters) Name: DrawTriangle3D Return type: void Description: Draw a color-filled triangle (vertex in counter-clockwise order!) @@ -3763,14 +3768,14 @@ Function 439: DrawTriangle3D() (4 input parameters) Param[2]: v2 (type: Vector3) Param[3]: v3 (type: Vector3) Param[4]: color (type: Color) -Function 440: DrawTriangleStrip3D() (3 input parameters) +Function 441: DrawTriangleStrip3D() (3 input parameters) Name: DrawTriangleStrip3D Return type: void Description: Draw a triangle strip defined by points Param[1]: points (type: const Vector3 *) Param[2]: pointCount (type: int) Param[3]: color (type: Color) -Function 441: DrawCube() (5 input parameters) +Function 442: DrawCube() (5 input parameters) Name: DrawCube Return type: void Description: Draw cube @@ -3779,14 +3784,14 @@ Function 441: DrawCube() (5 input parameters) Param[3]: height (type: float) Param[4]: length (type: float) Param[5]: color (type: Color) -Function 442: DrawCubeV() (3 input parameters) +Function 443: DrawCubeV() (3 input parameters) Name: DrawCubeV Return type: void Description: Draw cube (Vector version) Param[1]: position (type: Vector3) Param[2]: size (type: Vector3) Param[3]: color (type: Color) -Function 443: DrawCubeWires() (5 input parameters) +Function 444: DrawCubeWires() (5 input parameters) Name: DrawCubeWires Return type: void Description: Draw cube wires @@ -3795,21 +3800,21 @@ Function 443: DrawCubeWires() (5 input parameters) Param[3]: height (type: float) Param[4]: length (type: float) Param[5]: color (type: Color) -Function 444: DrawCubeWiresV() (3 input parameters) +Function 445: DrawCubeWiresV() (3 input parameters) Name: DrawCubeWiresV Return type: void Description: Draw cube wires (Vector version) Param[1]: position (type: Vector3) Param[2]: size (type: Vector3) Param[3]: color (type: Color) -Function 445: DrawSphere() (3 input parameters) +Function 446: DrawSphere() (3 input parameters) Name: DrawSphere Return type: void Description: Draw sphere Param[1]: centerPos (type: Vector3) Param[2]: radius (type: float) Param[3]: color (type: Color) -Function 446: DrawSphereEx() (5 input parameters) +Function 447: DrawSphereEx() (5 input parameters) Name: DrawSphereEx Return type: void Description: Draw sphere with extended parameters @@ -3818,7 +3823,7 @@ Function 446: DrawSphereEx() (5 input parameters) Param[3]: rings (type: int) Param[4]: slices (type: int) Param[5]: color (type: Color) -Function 447: DrawSphereWires() (5 input parameters) +Function 448: DrawSphereWires() (5 input parameters) Name: DrawSphereWires Return type: void Description: Draw sphere wires @@ -3827,7 +3832,7 @@ Function 447: DrawSphereWires() (5 input parameters) Param[3]: rings (type: int) Param[4]: slices (type: int) Param[5]: color (type: Color) -Function 448: DrawCylinder() (6 input parameters) +Function 449: DrawCylinder() (6 input parameters) Name: DrawCylinder Return type: void Description: Draw a cylinder/cone @@ -3837,7 +3842,7 @@ Function 448: DrawCylinder() (6 input parameters) Param[4]: height (type: float) Param[5]: slices (type: int) Param[6]: color (type: Color) -Function 449: DrawCylinderEx() (6 input parameters) +Function 450: DrawCylinderEx() (6 input parameters) Name: DrawCylinderEx Return type: void Description: Draw a cylinder with base at startPos and top at endPos @@ -3847,7 +3852,7 @@ Function 449: DrawCylinderEx() (6 input parameters) Param[4]: endRadius (type: float) Param[5]: sides (type: int) Param[6]: color (type: Color) -Function 450: DrawCylinderWires() (6 input parameters) +Function 451: DrawCylinderWires() (6 input parameters) Name: DrawCylinderWires Return type: void Description: Draw a cylinder/cone wires @@ -3857,7 +3862,7 @@ Function 450: DrawCylinderWires() (6 input parameters) Param[4]: height (type: float) Param[5]: slices (type: int) Param[6]: color (type: Color) -Function 451: DrawCylinderWiresEx() (6 input parameters) +Function 452: DrawCylinderWiresEx() (6 input parameters) Name: DrawCylinderWiresEx Return type: void Description: Draw a cylinder wires with base at startPos and top at endPos @@ -3867,7 +3872,7 @@ Function 451: DrawCylinderWiresEx() (6 input parameters) Param[4]: endRadius (type: float) Param[5]: sides (type: int) Param[6]: color (type: Color) -Function 452: DrawCapsule() (6 input parameters) +Function 453: DrawCapsule() (6 input parameters) Name: DrawCapsule Return type: void Description: Draw a capsule with the center of its sphere caps at startPos and endPos @@ -3877,7 +3882,7 @@ Function 452: DrawCapsule() (6 input parameters) Param[4]: slices (type: int) Param[5]: rings (type: int) Param[6]: color (type: Color) -Function 453: DrawCapsuleWires() (6 input parameters) +Function 454: DrawCapsuleWires() (6 input parameters) Name: DrawCapsuleWires Return type: void Description: Draw capsule wireframe with the center of its sphere caps at startPos and endPos @@ -3887,51 +3892,51 @@ Function 453: DrawCapsuleWires() (6 input parameters) Param[4]: slices (type: int) Param[5]: rings (type: int) Param[6]: color (type: Color) -Function 454: DrawPlane() (3 input parameters) +Function 455: DrawPlane() (3 input parameters) Name: DrawPlane Return type: void Description: Draw a plane XZ Param[1]: centerPos (type: Vector3) Param[2]: size (type: Vector2) Param[3]: color (type: Color) -Function 455: DrawRay() (2 input parameters) +Function 456: DrawRay() (2 input parameters) Name: DrawRay Return type: void Description: Draw a ray line Param[1]: ray (type: Ray) Param[2]: color (type: Color) -Function 456: DrawGrid() (2 input parameters) +Function 457: DrawGrid() (2 input parameters) Name: DrawGrid Return type: void Description: Draw a grid (centered at (0, 0, 0)) Param[1]: slices (type: int) Param[2]: spacing (type: float) -Function 457: LoadModel() (1 input parameters) +Function 458: LoadModel() (1 input parameters) Name: LoadModel Return type: Model Description: Load model from files (meshes and materials) Param[1]: fileName (type: const char *) -Function 458: LoadModelFromMesh() (1 input parameters) +Function 459: LoadModelFromMesh() (1 input parameters) Name: LoadModelFromMesh Return type: Model Description: Load model from generated mesh (default material) Param[1]: mesh (type: Mesh) -Function 459: IsModelReady() (1 input parameters) +Function 460: IsModelReady() (1 input parameters) Name: IsModelReady Return type: bool Description: Check if a model is ready Param[1]: model (type: Model) -Function 460: UnloadModel() (1 input parameters) +Function 461: UnloadModel() (1 input parameters) Name: UnloadModel Return type: void Description: Unload model (including meshes) from memory (RAM and/or VRAM) Param[1]: model (type: Model) -Function 461: GetModelBoundingBox() (1 input parameters) +Function 462: GetModelBoundingBox() (1 input parameters) Name: GetModelBoundingBox Return type: BoundingBox Description: Compute model bounding box limits (considers all meshes) Param[1]: model (type: Model) -Function 462: DrawModel() (4 input parameters) +Function 463: DrawModel() (4 input parameters) Name: DrawModel Return type: void Description: Draw a model (with texture if set) @@ -3939,7 +3944,7 @@ Function 462: DrawModel() (4 input parameters) Param[2]: position (type: Vector3) Param[3]: scale (type: float) Param[4]: tint (type: Color) -Function 463: DrawModelEx() (6 input parameters) +Function 464: DrawModelEx() (6 input parameters) Name: DrawModelEx Return type: void Description: Draw a model with extended parameters @@ -3949,7 +3954,7 @@ Function 463: DrawModelEx() (6 input parameters) Param[4]: rotationAngle (type: float) Param[5]: scale (type: Vector3) Param[6]: tint (type: Color) -Function 464: DrawModelWires() (4 input parameters) +Function 465: DrawModelWires() (4 input parameters) Name: DrawModelWires Return type: void Description: Draw a model wires (with texture if set) @@ -3957,7 +3962,7 @@ Function 464: DrawModelWires() (4 input parameters) Param[2]: position (type: Vector3) Param[3]: scale (type: float) Param[4]: tint (type: Color) -Function 465: DrawModelWiresEx() (6 input parameters) +Function 466: DrawModelWiresEx() (6 input parameters) Name: DrawModelWiresEx Return type: void Description: Draw a model wires (with texture if set) with extended parameters @@ -3967,7 +3972,7 @@ Function 465: DrawModelWiresEx() (6 input parameters) Param[4]: rotationAngle (type: float) Param[5]: scale (type: Vector3) Param[6]: tint (type: Color) -Function 466: DrawModelPoints() (4 input parameters) +Function 467: DrawModelPoints() (4 input parameters) Name: DrawModelPoints Return type: void Description: Draw a model as points @@ -3975,7 +3980,7 @@ Function 466: DrawModelPoints() (4 input parameters) Param[2]: position (type: Vector3) Param[3]: scale (type: float) Param[4]: tint (type: Color) -Function 467: DrawModelPointsEx() (6 input parameters) +Function 468: DrawModelPointsEx() (6 input parameters) Name: DrawModelPointsEx Return type: void Description: Draw a model as points with extended parameters @@ -3985,13 +3990,13 @@ Function 467: DrawModelPointsEx() (6 input parameters) Param[4]: rotationAngle (type: float) Param[5]: scale (type: Vector3) Param[6]: tint (type: Color) -Function 468: DrawBoundingBox() (2 input parameters) +Function 469: DrawBoundingBox() (2 input parameters) Name: DrawBoundingBox Return type: void Description: Draw bounding box (wires) Param[1]: box (type: BoundingBox) Param[2]: color (type: Color) -Function 469: DrawBillboard() (5 input parameters) +Function 470: DrawBillboard() (5 input parameters) Name: DrawBillboard Return type: void Description: Draw a billboard texture @@ -4000,7 +4005,7 @@ Function 469: DrawBillboard() (5 input parameters) Param[3]: position (type: Vector3) Param[4]: scale (type: float) Param[5]: tint (type: Color) -Function 470: DrawBillboardRec() (6 input parameters) +Function 471: DrawBillboardRec() (6 input parameters) Name: DrawBillboardRec Return type: void Description: Draw a billboard texture defined by source @@ -4010,7 +4015,7 @@ Function 470: DrawBillboardRec() (6 input parameters) Param[4]: position (type: Vector3) Param[5]: size (type: Vector2) Param[6]: tint (type: Color) -Function 471: DrawBillboardPro() (9 input parameters) +Function 472: DrawBillboardPro() (9 input parameters) Name: DrawBillboardPro Return type: void Description: Draw a billboard texture defined by source and rotation @@ -4023,13 +4028,13 @@ Function 471: DrawBillboardPro() (9 input parameters) Param[7]: origin (type: Vector2) Param[8]: rotation (type: float) Param[9]: tint (type: Color) -Function 472: UploadMesh() (2 input parameters) +Function 473: UploadMesh() (2 input parameters) Name: UploadMesh Return type: void Description: Upload mesh vertex data in GPU and provide VAO/VBO ids Param[1]: mesh (type: Mesh *) Param[2]: dynamic (type: bool) -Function 473: UpdateMeshBuffer() (5 input parameters) +Function 474: UpdateMeshBuffer() (5 input parameters) Name: UpdateMeshBuffer Return type: void Description: Update mesh vertex data in GPU for a specific buffer index @@ -4038,19 +4043,19 @@ Function 473: UpdateMeshBuffer() (5 input parameters) Param[3]: data (type: const void *) Param[4]: dataSize (type: int) Param[5]: offset (type: int) -Function 474: UnloadMesh() (1 input parameters) +Function 475: UnloadMesh() (1 input parameters) Name: UnloadMesh Return type: void Description: Unload mesh data from CPU and GPU Param[1]: mesh (type: Mesh) -Function 475: DrawMesh() (3 input parameters) +Function 476: DrawMesh() (3 input parameters) Name: DrawMesh Return type: void Description: Draw a 3d mesh with material and transform Param[1]: mesh (type: Mesh) Param[2]: material (type: Material) Param[3]: transform (type: Matrix) -Function 476: DrawMeshInstanced() (4 input parameters) +Function 477: DrawMeshInstanced() (4 input parameters) Name: DrawMeshInstanced Return type: void Description: Draw multiple mesh instances with material and different transforms @@ -4058,35 +4063,35 @@ Function 476: DrawMeshInstanced() (4 input parameters) Param[2]: material (type: Material) Param[3]: transforms (type: const Matrix *) Param[4]: instances (type: int) -Function 477: GetMeshBoundingBox() (1 input parameters) +Function 478: GetMeshBoundingBox() (1 input parameters) Name: GetMeshBoundingBox Return type: BoundingBox Description: Compute mesh bounding box limits Param[1]: mesh (type: Mesh) -Function 478: GenMeshTangents() (1 input parameters) +Function 479: GenMeshTangents() (1 input parameters) Name: GenMeshTangents Return type: void Description: Compute mesh tangents Param[1]: mesh (type: Mesh *) -Function 479: ExportMesh() (2 input parameters) +Function 480: ExportMesh() (2 input parameters) Name: ExportMesh Return type: bool Description: Export mesh data to file, returns true on success Param[1]: mesh (type: Mesh) Param[2]: fileName (type: const char *) -Function 480: ExportMeshAsCode() (2 input parameters) +Function 481: ExportMeshAsCode() (2 input parameters) Name: ExportMeshAsCode Return type: bool Description: Export mesh as code file (.h) defining multiple arrays of vertex attributes Param[1]: mesh (type: Mesh) Param[2]: fileName (type: const char *) -Function 481: GenMeshPoly() (2 input parameters) +Function 482: GenMeshPoly() (2 input parameters) Name: GenMeshPoly Return type: Mesh Description: Generate polygonal mesh Param[1]: sides (type: int) Param[2]: radius (type: float) -Function 482: GenMeshPlane() (4 input parameters) +Function 483: GenMeshPlane() (4 input parameters) Name: GenMeshPlane Return type: Mesh Description: Generate plane mesh (with subdivisions) @@ -4094,42 +4099,42 @@ Function 482: GenMeshPlane() (4 input parameters) Param[2]: length (type: float) Param[3]: resX (type: int) Param[4]: resZ (type: int) -Function 483: GenMeshCube() (3 input parameters) +Function 484: GenMeshCube() (3 input parameters) Name: GenMeshCube Return type: Mesh Description: Generate cuboid mesh Param[1]: width (type: float) Param[2]: height (type: float) Param[3]: length (type: float) -Function 484: GenMeshSphere() (3 input parameters) +Function 485: GenMeshSphere() (3 input parameters) Name: GenMeshSphere Return type: Mesh Description: Generate sphere mesh (standard sphere) Param[1]: radius (type: float) Param[2]: rings (type: int) Param[3]: slices (type: int) -Function 485: GenMeshHemiSphere() (3 input parameters) +Function 486: GenMeshHemiSphere() (3 input parameters) Name: GenMeshHemiSphere Return type: Mesh Description: Generate half-sphere mesh (no bottom cap) Param[1]: radius (type: float) Param[2]: rings (type: int) Param[3]: slices (type: int) -Function 486: GenMeshCylinder() (3 input parameters) +Function 487: GenMeshCylinder() (3 input parameters) Name: GenMeshCylinder Return type: Mesh Description: Generate cylinder mesh Param[1]: radius (type: float) Param[2]: height (type: float) Param[3]: slices (type: int) -Function 487: GenMeshCone() (3 input parameters) +Function 488: GenMeshCone() (3 input parameters) Name: GenMeshCone Return type: Mesh Description: Generate cone/pyramid mesh Param[1]: radius (type: float) Param[2]: height (type: float) Param[3]: slices (type: int) -Function 488: GenMeshTorus() (4 input parameters) +Function 489: GenMeshTorus() (4 input parameters) Name: GenMeshTorus Return type: Mesh Description: Generate torus mesh @@ -4137,7 +4142,7 @@ Function 488: GenMeshTorus() (4 input parameters) Param[2]: size (type: float) Param[3]: radSeg (type: int) Param[4]: sides (type: int) -Function 489: GenMeshKnot() (4 input parameters) +Function 490: GenMeshKnot() (4 input parameters) Name: GenMeshKnot Return type: Mesh Description: Generate trefoil knot mesh @@ -4145,91 +4150,91 @@ Function 489: GenMeshKnot() (4 input parameters) Param[2]: size (type: float) Param[3]: radSeg (type: int) Param[4]: sides (type: int) -Function 490: GenMeshHeightmap() (2 input parameters) +Function 491: GenMeshHeightmap() (2 input parameters) Name: GenMeshHeightmap Return type: Mesh Description: Generate heightmap mesh from image data Param[1]: heightmap (type: Image) Param[2]: size (type: Vector3) -Function 491: GenMeshCubicmap() (2 input parameters) +Function 492: GenMeshCubicmap() (2 input parameters) Name: GenMeshCubicmap Return type: Mesh Description: Generate cubes-based map mesh from image data Param[1]: cubicmap (type: Image) Param[2]: cubeSize (type: Vector3) -Function 492: LoadMaterials() (2 input parameters) +Function 493: LoadMaterials() (2 input parameters) Name: LoadMaterials Return type: Material * Description: Load materials from model file Param[1]: fileName (type: const char *) Param[2]: materialCount (type: int *) -Function 493: LoadMaterialDefault() (0 input parameters) +Function 494: LoadMaterialDefault() (0 input parameters) Name: LoadMaterialDefault Return type: Material Description: Load default material (Supports: DIFFUSE, SPECULAR, NORMAL maps) No input parameters -Function 494: IsMaterialReady() (1 input parameters) +Function 495: IsMaterialReady() (1 input parameters) Name: IsMaterialReady Return type: bool Description: Check if a material is ready Param[1]: material (type: Material) -Function 495: UnloadMaterial() (1 input parameters) +Function 496: UnloadMaterial() (1 input parameters) Name: UnloadMaterial Return type: void Description: Unload material from GPU memory (VRAM) Param[1]: material (type: Material) -Function 496: SetMaterialTexture() (3 input parameters) +Function 497: SetMaterialTexture() (3 input parameters) Name: SetMaterialTexture Return type: void Description: Set texture for a material map type (MATERIAL_MAP_DIFFUSE, MATERIAL_MAP_SPECULAR...) Param[1]: material (type: Material *) Param[2]: mapType (type: int) Param[3]: texture (type: Texture2D) -Function 497: SetModelMeshMaterial() (3 input parameters) +Function 498: SetModelMeshMaterial() (3 input parameters) Name: SetModelMeshMaterial Return type: void Description: Set material for a mesh Param[1]: model (type: Model *) Param[2]: meshId (type: int) Param[3]: materialId (type: int) -Function 498: LoadModelAnimations() (2 input parameters) +Function 499: LoadModelAnimations() (2 input parameters) Name: LoadModelAnimations Return type: ModelAnimation * Description: Load model animations from file Param[1]: fileName (type: const char *) Param[2]: animCount (type: int *) -Function 499: UpdateModelAnimation() (3 input parameters) +Function 500: UpdateModelAnimation() (3 input parameters) Name: UpdateModelAnimation Return type: void Description: Update model animation pose Param[1]: model (type: Model) Param[2]: anim (type: ModelAnimation) Param[3]: frame (type: int) -Function 500: UnloadModelAnimation() (1 input parameters) +Function 501: UnloadModelAnimation() (1 input parameters) Name: UnloadModelAnimation Return type: void Description: Unload animation data Param[1]: anim (type: ModelAnimation) -Function 501: UnloadModelAnimations() (2 input parameters) +Function 502: UnloadModelAnimations() (2 input parameters) Name: UnloadModelAnimations Return type: void Description: Unload animation array data Param[1]: animations (type: ModelAnimation *) Param[2]: animCount (type: int) -Function 502: IsModelAnimationValid() (2 input parameters) +Function 503: IsModelAnimationValid() (2 input parameters) Name: IsModelAnimationValid Return type: bool Description: Check model animation skeleton match Param[1]: model (type: Model) Param[2]: anim (type: ModelAnimation) -Function 503: UpdateModelAnimationBoneMatrices() (3 input parameters) +Function 504: UpdateModelAnimationBoneMatrices() (3 input parameters) Name: UpdateModelAnimationBoneMatrices Return type: void Description: Update model animation mesh bone matrices Param[1]: model (type: Model) Param[2]: anim (type: ModelAnimation) Param[3]: frame (type: int) -Function 504: CheckCollisionSpheres() (4 input parameters) +Function 505: CheckCollisionSpheres() (4 input parameters) Name: CheckCollisionSpheres Return type: bool Description: Check collision between two spheres @@ -4237,40 +4242,40 @@ Function 504: CheckCollisionSpheres() (4 input parameters) Param[2]: radius1 (type: float) Param[3]: center2 (type: Vector3) Param[4]: radius2 (type: float) -Function 505: CheckCollisionBoxes() (2 input parameters) +Function 506: CheckCollisionBoxes() (2 input parameters) Name: CheckCollisionBoxes Return type: bool Description: Check collision between two bounding boxes Param[1]: box1 (type: BoundingBox) Param[2]: box2 (type: BoundingBox) -Function 506: CheckCollisionBoxSphere() (3 input parameters) +Function 507: CheckCollisionBoxSphere() (3 input parameters) Name: CheckCollisionBoxSphere Return type: bool Description: Check collision between box and sphere Param[1]: box (type: BoundingBox) Param[2]: center (type: Vector3) Param[3]: radius (type: float) -Function 507: GetRayCollisionSphere() (3 input parameters) +Function 508: GetRayCollisionSphere() (3 input parameters) Name: GetRayCollisionSphere Return type: RayCollision Description: Get collision info between ray and sphere Param[1]: ray (type: Ray) Param[2]: center (type: Vector3) Param[3]: radius (type: float) -Function 508: GetRayCollisionBox() (2 input parameters) +Function 509: GetRayCollisionBox() (2 input parameters) Name: GetRayCollisionBox Return type: RayCollision Description: Get collision info between ray and box Param[1]: ray (type: Ray) Param[2]: box (type: BoundingBox) -Function 509: GetRayCollisionMesh() (3 input parameters) +Function 510: GetRayCollisionMesh() (3 input parameters) Name: GetRayCollisionMesh Return type: RayCollision Description: Get collision info between ray and mesh Param[1]: ray (type: Ray) Param[2]: mesh (type: Mesh) Param[3]: transform (type: Matrix) -Function 510: GetRayCollisionTriangle() (4 input parameters) +Function 511: GetRayCollisionTriangle() (4 input parameters) Name: GetRayCollisionTriangle Return type: RayCollision Description: Get collision info between ray and triangle @@ -4278,7 +4283,7 @@ Function 510: GetRayCollisionTriangle() (4 input parameters) Param[2]: p1 (type: Vector3) Param[3]: p2 (type: Vector3) Param[4]: p3 (type: Vector3) -Function 511: GetRayCollisionQuad() (5 input parameters) +Function 512: GetRayCollisionQuad() (5 input parameters) Name: GetRayCollisionQuad Return type: RayCollision Description: Get collision info between ray and quad @@ -4287,158 +4292,158 @@ Function 511: GetRayCollisionQuad() (5 input parameters) Param[3]: p2 (type: Vector3) Param[4]: p3 (type: Vector3) Param[5]: p4 (type: Vector3) -Function 512: InitAudioDevice() (0 input parameters) +Function 513: InitAudioDevice() (0 input parameters) Name: InitAudioDevice Return type: void Description: Initialize audio device and context No input parameters -Function 513: CloseAudioDevice() (0 input parameters) +Function 514: CloseAudioDevice() (0 input parameters) Name: CloseAudioDevice Return type: void Description: Close the audio device and context No input parameters -Function 514: IsAudioDeviceReady() (0 input parameters) +Function 515: IsAudioDeviceReady() (0 input parameters) Name: IsAudioDeviceReady Return type: bool Description: Check if audio device has been initialized successfully No input parameters -Function 515: SetMasterVolume() (1 input parameters) +Function 516: SetMasterVolume() (1 input parameters) Name: SetMasterVolume Return type: void Description: Set master volume (listener) Param[1]: volume (type: float) -Function 516: GetMasterVolume() (0 input parameters) +Function 517: GetMasterVolume() (0 input parameters) Name: GetMasterVolume Return type: float Description: Get master volume (listener) No input parameters -Function 517: LoadWave() (1 input parameters) +Function 518: LoadWave() (1 input parameters) Name: LoadWave Return type: Wave Description: Load wave data from file Param[1]: fileName (type: const char *) -Function 518: LoadWaveFromMemory() (3 input parameters) +Function 519: LoadWaveFromMemory() (3 input parameters) Name: LoadWaveFromMemory Return type: Wave Description: Load wave from memory buffer, fileType refers to extension: i.e. '.wav' Param[1]: fileType (type: const char *) Param[2]: fileData (type: const unsigned char *) Param[3]: dataSize (type: int) -Function 519: IsWaveReady() (1 input parameters) +Function 520: IsWaveReady() (1 input parameters) Name: IsWaveReady Return type: bool Description: Checks if wave data is ready Param[1]: wave (type: Wave) -Function 520: LoadSound() (1 input parameters) +Function 521: LoadSound() (1 input parameters) Name: LoadSound Return type: Sound Description: Load sound from file Param[1]: fileName (type: const char *) -Function 521: LoadSoundFromWave() (1 input parameters) +Function 522: LoadSoundFromWave() (1 input parameters) Name: LoadSoundFromWave Return type: Sound Description: Load sound from wave data Param[1]: wave (type: Wave) -Function 522: LoadSoundAlias() (1 input parameters) +Function 523: LoadSoundAlias() (1 input parameters) Name: LoadSoundAlias Return type: Sound Description: Create a new sound that shares the same sample data as the source sound, does not own the sound data Param[1]: source (type: Sound) -Function 523: IsSoundReady() (1 input parameters) +Function 524: IsSoundReady() (1 input parameters) Name: IsSoundReady Return type: bool Description: Checks if a sound is ready Param[1]: sound (type: Sound) -Function 524: UpdateSound() (3 input parameters) +Function 525: UpdateSound() (3 input parameters) Name: UpdateSound Return type: void Description: Update sound buffer with new data Param[1]: sound (type: Sound) Param[2]: data (type: const void *) Param[3]: sampleCount (type: int) -Function 525: UnloadWave() (1 input parameters) +Function 526: UnloadWave() (1 input parameters) Name: UnloadWave Return type: void Description: Unload wave data Param[1]: wave (type: Wave) -Function 526: UnloadSound() (1 input parameters) +Function 527: UnloadSound() (1 input parameters) Name: UnloadSound Return type: void Description: Unload sound Param[1]: sound (type: Sound) -Function 527: UnloadSoundAlias() (1 input parameters) +Function 528: UnloadSoundAlias() (1 input parameters) Name: UnloadSoundAlias Return type: void Description: Unload a sound alias (does not deallocate sample data) Param[1]: alias (type: Sound) -Function 528: ExportWave() (2 input parameters) +Function 529: ExportWave() (2 input parameters) Name: ExportWave Return type: bool Description: Export wave data to file, returns true on success Param[1]: wave (type: Wave) Param[2]: fileName (type: const char *) -Function 529: ExportWaveAsCode() (2 input parameters) +Function 530: ExportWaveAsCode() (2 input parameters) Name: ExportWaveAsCode Return type: bool Description: Export wave sample data to code (.h), returns true on success Param[1]: wave (type: Wave) Param[2]: fileName (type: const char *) -Function 530: PlaySound() (1 input parameters) +Function 531: PlaySound() (1 input parameters) Name: PlaySound Return type: void Description: Play a sound Param[1]: sound (type: Sound) -Function 531: StopSound() (1 input parameters) +Function 532: StopSound() (1 input parameters) Name: StopSound Return type: void Description: Stop playing a sound Param[1]: sound (type: Sound) -Function 532: PauseSound() (1 input parameters) +Function 533: PauseSound() (1 input parameters) Name: PauseSound Return type: void Description: Pause a sound Param[1]: sound (type: Sound) -Function 533: ResumeSound() (1 input parameters) +Function 534: ResumeSound() (1 input parameters) Name: ResumeSound Return type: void Description: Resume a paused sound Param[1]: sound (type: Sound) -Function 534: IsSoundPlaying() (1 input parameters) +Function 535: IsSoundPlaying() (1 input parameters) Name: IsSoundPlaying Return type: bool Description: Check if a sound is currently playing Param[1]: sound (type: Sound) -Function 535: SetSoundVolume() (2 input parameters) +Function 536: SetSoundVolume() (2 input parameters) Name: SetSoundVolume Return type: void Description: Set volume for a sound (1.0 is max level) Param[1]: sound (type: Sound) Param[2]: volume (type: float) -Function 536: SetSoundPitch() (2 input parameters) +Function 537: SetSoundPitch() (2 input parameters) Name: SetSoundPitch Return type: void Description: Set pitch for a sound (1.0 is base level) Param[1]: sound (type: Sound) Param[2]: pitch (type: float) -Function 537: SetSoundPan() (2 input parameters) +Function 538: SetSoundPan() (2 input parameters) Name: SetSoundPan Return type: void Description: Set pan for a sound (0.5 is center) Param[1]: sound (type: Sound) Param[2]: pan (type: float) -Function 538: WaveCopy() (1 input parameters) +Function 539: WaveCopy() (1 input parameters) Name: WaveCopy Return type: Wave Description: Copy a wave to a new wave Param[1]: wave (type: Wave) -Function 539: WaveCrop() (3 input parameters) +Function 540: WaveCrop() (3 input parameters) Name: WaveCrop Return type: void Description: Crop a wave to defined frames range Param[1]: wave (type: Wave *) Param[2]: initFrame (type: int) Param[3]: finalFrame (type: int) -Function 540: WaveFormat() (4 input parameters) +Function 541: WaveFormat() (4 input parameters) Name: WaveFormat Return type: void Description: Convert wave data to desired format @@ -4446,203 +4451,203 @@ Function 540: WaveFormat() (4 input parameters) Param[2]: sampleRate (type: int) Param[3]: sampleSize (type: int) Param[4]: channels (type: int) -Function 541: LoadWaveSamples() (1 input parameters) +Function 542: LoadWaveSamples() (1 input parameters) Name: LoadWaveSamples Return type: float * Description: Load samples data from wave as a 32bit float data array Param[1]: wave (type: Wave) -Function 542: UnloadWaveSamples() (1 input parameters) +Function 543: UnloadWaveSamples() (1 input parameters) Name: UnloadWaveSamples Return type: void Description: Unload samples data loaded with LoadWaveSamples() Param[1]: samples (type: float *) -Function 543: LoadMusicStream() (1 input parameters) +Function 544: LoadMusicStream() (1 input parameters) Name: LoadMusicStream Return type: Music Description: Load music stream from file Param[1]: fileName (type: const char *) -Function 544: LoadMusicStreamFromMemory() (3 input parameters) +Function 545: LoadMusicStreamFromMemory() (3 input parameters) Name: LoadMusicStreamFromMemory Return type: Music Description: Load music stream from data Param[1]: fileType (type: const char *) Param[2]: data (type: const unsigned char *) Param[3]: dataSize (type: int) -Function 545: IsMusicReady() (1 input parameters) +Function 546: IsMusicReady() (1 input parameters) Name: IsMusicReady Return type: bool Description: Checks if a music stream is ready Param[1]: music (type: Music) -Function 546: UnloadMusicStream() (1 input parameters) +Function 547: UnloadMusicStream() (1 input parameters) Name: UnloadMusicStream Return type: void Description: Unload music stream Param[1]: music (type: Music) -Function 547: PlayMusicStream() (1 input parameters) +Function 548: PlayMusicStream() (1 input parameters) Name: PlayMusicStream Return type: void Description: Start music playing Param[1]: music (type: Music) -Function 548: IsMusicStreamPlaying() (1 input parameters) +Function 549: IsMusicStreamPlaying() (1 input parameters) Name: IsMusicStreamPlaying Return type: bool Description: Check if music is playing Param[1]: music (type: Music) -Function 549: UpdateMusicStream() (1 input parameters) +Function 550: UpdateMusicStream() (1 input parameters) Name: UpdateMusicStream Return type: void Description: Updates buffers for music streaming Param[1]: music (type: Music) -Function 550: StopMusicStream() (1 input parameters) +Function 551: StopMusicStream() (1 input parameters) Name: StopMusicStream Return type: void Description: Stop music playing Param[1]: music (type: Music) -Function 551: PauseMusicStream() (1 input parameters) +Function 552: PauseMusicStream() (1 input parameters) Name: PauseMusicStream Return type: void Description: Pause music playing Param[1]: music (type: Music) -Function 552: ResumeMusicStream() (1 input parameters) +Function 553: ResumeMusicStream() (1 input parameters) Name: ResumeMusicStream Return type: void Description: Resume playing paused music Param[1]: music (type: Music) -Function 553: SeekMusicStream() (2 input parameters) +Function 554: SeekMusicStream() (2 input parameters) Name: SeekMusicStream Return type: void Description: Seek music to a position (in seconds) Param[1]: music (type: Music) Param[2]: position (type: float) -Function 554: SetMusicVolume() (2 input parameters) +Function 555: SetMusicVolume() (2 input parameters) Name: SetMusicVolume Return type: void Description: Set volume for music (1.0 is max level) Param[1]: music (type: Music) Param[2]: volume (type: float) -Function 555: SetMusicPitch() (2 input parameters) +Function 556: SetMusicPitch() (2 input parameters) Name: SetMusicPitch Return type: void Description: Set pitch for a music (1.0 is base level) Param[1]: music (type: Music) Param[2]: pitch (type: float) -Function 556: SetMusicPan() (2 input parameters) +Function 557: SetMusicPan() (2 input parameters) Name: SetMusicPan Return type: void Description: Set pan for a music (0.5 is center) Param[1]: music (type: Music) Param[2]: pan (type: float) -Function 557: GetMusicTimeLength() (1 input parameters) +Function 558: GetMusicTimeLength() (1 input parameters) Name: GetMusicTimeLength Return type: float Description: Get music time length (in seconds) Param[1]: music (type: Music) -Function 558: GetMusicTimePlayed() (1 input parameters) +Function 559: GetMusicTimePlayed() (1 input parameters) Name: GetMusicTimePlayed Return type: float Description: Get current music time played (in seconds) Param[1]: music (type: Music) -Function 559: LoadAudioStream() (3 input parameters) +Function 560: LoadAudioStream() (3 input parameters) Name: LoadAudioStream Return type: AudioStream Description: Load audio stream (to stream raw audio pcm data) Param[1]: sampleRate (type: unsigned int) Param[2]: sampleSize (type: unsigned int) Param[3]: channels (type: unsigned int) -Function 560: IsAudioStreamReady() (1 input parameters) +Function 561: IsAudioStreamReady() (1 input parameters) Name: IsAudioStreamReady Return type: bool Description: Checks if an audio stream is ready Param[1]: stream (type: AudioStream) -Function 561: UnloadAudioStream() (1 input parameters) +Function 562: UnloadAudioStream() (1 input parameters) Name: UnloadAudioStream Return type: void Description: Unload audio stream and free memory Param[1]: stream (type: AudioStream) -Function 562: UpdateAudioStream() (3 input parameters) +Function 563: UpdateAudioStream() (3 input parameters) Name: UpdateAudioStream Return type: void Description: Update audio stream buffers with data Param[1]: stream (type: AudioStream) Param[2]: data (type: const void *) Param[3]: frameCount (type: int) -Function 563: IsAudioStreamProcessed() (1 input parameters) +Function 564: IsAudioStreamProcessed() (1 input parameters) Name: IsAudioStreamProcessed Return type: bool Description: Check if any audio stream buffers requires refill Param[1]: stream (type: AudioStream) -Function 564: PlayAudioStream() (1 input parameters) +Function 565: PlayAudioStream() (1 input parameters) Name: PlayAudioStream Return type: void Description: Play audio stream Param[1]: stream (type: AudioStream) -Function 565: PauseAudioStream() (1 input parameters) +Function 566: PauseAudioStream() (1 input parameters) Name: PauseAudioStream Return type: void Description: Pause audio stream Param[1]: stream (type: AudioStream) -Function 566: ResumeAudioStream() (1 input parameters) +Function 567: ResumeAudioStream() (1 input parameters) Name: ResumeAudioStream Return type: void Description: Resume audio stream Param[1]: stream (type: AudioStream) -Function 567: IsAudioStreamPlaying() (1 input parameters) +Function 568: IsAudioStreamPlaying() (1 input parameters) Name: IsAudioStreamPlaying Return type: bool Description: Check if audio stream is playing Param[1]: stream (type: AudioStream) -Function 568: StopAudioStream() (1 input parameters) +Function 569: StopAudioStream() (1 input parameters) Name: StopAudioStream Return type: void Description: Stop audio stream Param[1]: stream (type: AudioStream) -Function 569: SetAudioStreamVolume() (2 input parameters) +Function 570: SetAudioStreamVolume() (2 input parameters) Name: SetAudioStreamVolume Return type: void Description: Set volume for audio stream (1.0 is max level) Param[1]: stream (type: AudioStream) Param[2]: volume (type: float) -Function 570: SetAudioStreamPitch() (2 input parameters) +Function 571: SetAudioStreamPitch() (2 input parameters) Name: SetAudioStreamPitch Return type: void Description: Set pitch for audio stream (1.0 is base level) Param[1]: stream (type: AudioStream) Param[2]: pitch (type: float) -Function 571: SetAudioStreamPan() (2 input parameters) +Function 572: SetAudioStreamPan() (2 input parameters) Name: SetAudioStreamPan Return type: void Description: Set pan for audio stream (0.5 is centered) Param[1]: stream (type: AudioStream) Param[2]: pan (type: float) -Function 572: SetAudioStreamBufferSizeDefault() (1 input parameters) +Function 573: SetAudioStreamBufferSizeDefault() (1 input parameters) Name: SetAudioStreamBufferSizeDefault Return type: void Description: Default size for new audio streams Param[1]: size (type: int) -Function 573: SetAudioStreamCallback() (2 input parameters) +Function 574: SetAudioStreamCallback() (2 input parameters) Name: SetAudioStreamCallback Return type: void Description: Audio thread callback to request new data Param[1]: stream (type: AudioStream) Param[2]: callback (type: AudioCallback) -Function 574: AttachAudioStreamProcessor() (2 input parameters) +Function 575: AttachAudioStreamProcessor() (2 input parameters) Name: AttachAudioStreamProcessor Return type: void Description: Attach audio stream processor to stream, receives the samples as 'float' Param[1]: stream (type: AudioStream) Param[2]: processor (type: AudioCallback) -Function 575: DetachAudioStreamProcessor() (2 input parameters) +Function 576: DetachAudioStreamProcessor() (2 input parameters) Name: DetachAudioStreamProcessor Return type: void Description: Detach audio stream processor from stream Param[1]: stream (type: AudioStream) Param[2]: processor (type: AudioCallback) -Function 576: AttachAudioMixedProcessor() (1 input parameters) +Function 577: AttachAudioMixedProcessor() (1 input parameters) Name: AttachAudioMixedProcessor Return type: void Description: Attach audio stream processor to the entire audio pipeline, receives the samples as 'float' Param[1]: processor (type: AudioCallback) -Function 577: DetachAudioMixedProcessor() (1 input parameters) +Function 578: DetachAudioMixedProcessor() (1 input parameters) Name: DetachAudioMixedProcessor Return type: void Description: Detach audio stream processor from the entire audio pipeline diff --git a/parser/output/raylib_api.xml b/parser/output/raylib_api.xml index 13ea5b7ab..140f4910d 100644 --- a/parser/output/raylib_api.xml +++ b/parser/output/raylib_api.xml @@ -675,7 +675,7 @@ - + @@ -1074,6 +1074,9 @@ + + + From 100f6624d62d29638fc7174f41a6cba1548fb3e2 Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 22 Sep 2024 22:36:17 +0200 Subject: [PATCH 087/208] Update rcore.c --- src/rcore.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/rcore.c b/src/rcore.c index 1501aced1..50814443c 100644 --- a/src/rcore.c +++ b/src/rcore.c @@ -205,9 +205,13 @@ unsigned int __stdcall timeEndPeriod(unsigned int uPeriod); #include // Required for: _mkdir() #define MKDIR(dir) _mkdir(dir) #elif defined __GNUC__ - #include - #include // Required for: mkdir() - #define MKDIR(dir) mkdir(dir) // OLD: mkdir(dir, 0777) -> w64devkit complaints! + #if defined(__linux__) + #define MKDIR(dir) mkdir(dir, 0777); + #else + #include + #include // Required for: mkdir() + #define MKDIR(dir) _mkdir(dir) // OLD: mkdir(dir, 0777) -> w64devkit complaints! + #endif #endif //---------------------------------------------------------------------------------- From 352c450ad02b9920110bbaa57171f3a184dc4a22 Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 22 Sep 2024 22:43:35 +0200 Subject: [PATCH 088/208] Update rcore.c --- src/rcore.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rcore.c b/src/rcore.c index 50814443c..03d3d1fb4 100644 --- a/src/rcore.c +++ b/src/rcore.c @@ -210,7 +210,7 @@ unsigned int __stdcall timeEndPeriod(unsigned int uPeriod); #else #include #include // Required for: mkdir() - #define MKDIR(dir) _mkdir(dir) // OLD: mkdir(dir, 0777) -> w64devkit complaints! + #define MKDIR(dir) mkdir(dir) // OLD: mkdir(dir, 0777) -> w64devkit complaints! #endif #endif From 24a1cd8c5b95116c207d8f9189fc6eba245ac40c Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 22 Sep 2024 22:50:47 +0200 Subject: [PATCH 089/208] Update rcore.c --- src/rcore.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/rcore.c b/src/rcore.c index 03d3d1fb4..74659b6fd 100644 --- a/src/rcore.c +++ b/src/rcore.c @@ -205,12 +205,14 @@ unsigned int __stdcall timeEndPeriod(unsigned int uPeriod); #include // Required for: _mkdir() #define MKDIR(dir) _mkdir(dir) #elif defined __GNUC__ - #if defined(__linux__) + #if defined(EMSCRIPTEN) + #define MKDIR(dir) mkdir(dir) + #elif defined(__linux__) #define MKDIR(dir) mkdir(dir, 0777); #else #include #include // Required for: mkdir() - #define MKDIR(dir) mkdir(dir) // OLD: mkdir(dir, 0777) -> w64devkit complaints! + #define MKDIR(dir) _mkdir(dir) // OLD: mkdir(dir, 0777) -> w64devkit complaints! #endif #endif From 291063c98fd9ebcff1e852f0eaeab1deb6e8f028 Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 22 Sep 2024 22:56:21 +0200 Subject: [PATCH 090/208] Update rcore.c --- src/rcore.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/rcore.c b/src/rcore.c index 74659b6fd..ccd58bdb2 100644 --- a/src/rcore.c +++ b/src/rcore.c @@ -195,26 +195,30 @@ unsigned int __stdcall timeEndPeriod(unsigned int uPeriod); #include // Required for: _getch(), _chdir(), _mkdir() #define GETCWD _getcwd // NOTE: MSDN recommends not to use getcwd(), chdir() #define CHDIR _chdir + #define MKDIR(dir) _mkdir(dir) #else #include // Required for: getch(), chdir() (POSIX), access() #define GETCWD getcwd #define CHDIR chdir + #define MKDIR(dir) mkdir(dir, 0777) #endif +/* #if defined(_MSC_VER) && ((defined(WIN32) || defined(_WIN32) || defined(__WIN32)) && !defined(__CYGWIN__)) - #include // Required for: _mkdir() - #define MKDIR(dir) _mkdir(dir) + //#include // Required for: _mkdir() + //#define MKDIR(dir) _mkdir(dir) #elif defined __GNUC__ #if defined(EMSCRIPTEN) - #define MKDIR(dir) mkdir(dir) + #define MKDIR(dir) mkdir(dir, 0777) #elif defined(__linux__) - #define MKDIR(dir) mkdir(dir, 0777); + #define MKDIR(dir) mkdir(dir, 0777) #else #include #include // Required for: mkdir() #define MKDIR(dir) _mkdir(dir) // OLD: mkdir(dir, 0777) -> w64devkit complaints! #endif #endif +*/ //---------------------------------------------------------------------------------- // Defines and Macros From 13178b9373cebffb97a4ff66b734bacbb9d8758d Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 22 Sep 2024 23:01:22 +0200 Subject: [PATCH 091/208] Update rcore.c --- src/rcore.c | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/src/rcore.c b/src/rcore.c index ccd58bdb2..3cdacbd96 100644 --- a/src/rcore.c +++ b/src/rcore.c @@ -197,29 +197,12 @@ unsigned int __stdcall timeEndPeriod(unsigned int uPeriod); #define CHDIR _chdir #define MKDIR(dir) _mkdir(dir) #else - #include // Required for: getch(), chdir() (POSIX), access() + #include // Required for: getch(), chdir(), mkdir(), access() #define GETCWD getcwd #define CHDIR chdir #define MKDIR(dir) mkdir(dir, 0777) #endif -/* -#if defined(_MSC_VER) && ((defined(WIN32) || defined(_WIN32) || defined(__WIN32)) && !defined(__CYGWIN__)) - //#include // Required for: _mkdir() - //#define MKDIR(dir) _mkdir(dir) -#elif defined __GNUC__ - #if defined(EMSCRIPTEN) - #define MKDIR(dir) mkdir(dir, 0777) - #elif defined(__linux__) - #define MKDIR(dir) mkdir(dir, 0777) - #else - #include - #include // Required for: mkdir() - #define MKDIR(dir) _mkdir(dir) // OLD: mkdir(dir, 0777) -> w64devkit complaints! - #endif -#endif -*/ - //---------------------------------------------------------------------------------- // Defines and Macros //---------------------------------------------------------------------------------- From 55e83468c9bb515a5f2725751e5f187a7b9b5afd Mon Sep 17 00:00:00 2001 From: Menno van der Graaf Date: Tue, 24 Sep 2024 20:02:54 +0200 Subject: [PATCH 092/208] Fix isGpuReady flag on android (#4340) --- src/platforms/rcore_android.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/platforms/rcore_android.c b/src/platforms/rcore_android.c index 55706c591..6318931cc 100644 --- a/src/platforms/rcore_android.c +++ b/src/platforms/rcore_android.c @@ -74,7 +74,7 @@ typedef struct { // Global Variables Definition //---------------------------------------------------------------------------------- extern CoreData CORE; // Global CORE state context - +extern bool isGpuReady; // Flag to note GPU has been initialized successfully static PlatformData platform = { 0 }; // Platform specific data //---------------------------------------------------------------------------------- @@ -989,6 +989,7 @@ static void AndroidCommandCallback(struct android_app *app, int32_t cmd) // Initialize OpenGL context (states and resources) // NOTE: CORE.Window.currentFbo.width and CORE.Window.currentFbo.height not used, just stored as globals in rlgl rlglInit(CORE.Window.currentFbo.width, CORE.Window.currentFbo.height); + isGpuReady = true; // Setup default viewport // NOTE: It updated CORE.Window.render.width and CORE.Window.render.height From 0573ef03820f0948b38d52236d15c2f18c871cc7 Mon Sep 17 00:00:00 2001 From: Jeffery Myers Date: Fri, 27 Sep 2024 14:06:54 -0700 Subject: [PATCH 093/208] [SHAPES] Add more detail to comment for DrawPixel (#4344) * Update raylib_api.* by CI * Add comment that draw pixel uses geometry and may be slow * Update raylib_api.* by CI --------- Co-authored-by: github-actions[bot] --- parser/output/raylib_api.json | 4 ++-- parser/output/raylib_api.lua | 4 ++-- parser/output/raylib_api.txt | 4 ++-- parser/output/raylib_api.xml | 4 ++-- src/raylib.h | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/parser/output/raylib_api.json b/parser/output/raylib_api.json index 2e599496d..ca3b276cf 100644 --- a/parser/output/raylib_api.json +++ b/parser/output/raylib_api.json @@ -5274,7 +5274,7 @@ }, { "name": "DrawPixel", - "description": "Draw a pixel", + "description": "Draw a pixel using geometry [Can be slow, use with care]", "returnType": "void", "params": [ { @@ -5293,7 +5293,7 @@ }, { "name": "DrawPixelV", - "description": "Draw a pixel (Vector version)", + "description": "Draw a pixel using geometry (Vector version) [Can be slow, use with care]", "returnType": "void", "params": [ { diff --git a/parser/output/raylib_api.lua b/parser/output/raylib_api.lua index 69ae07eda..b010e19cf 100644 --- a/parser/output/raylib_api.lua +++ b/parser/output/raylib_api.lua @@ -4614,7 +4614,7 @@ return { }, { name = "DrawPixel", - description = "Draw a pixel", + description = "Draw a pixel using geometry [Can be slow, use with care]", returnType = "void", params = { {type = "int", name = "posX"}, @@ -4624,7 +4624,7 @@ return { }, { name = "DrawPixelV", - description = "Draw a pixel (Vector version)", + description = "Draw a pixel using geometry (Vector version) [Can be slow, use with care]", returnType = "void", params = { {type = "Vector2", name = "position"}, diff --git a/parser/output/raylib_api.txt b/parser/output/raylib_api.txt index 458d12da0..19abf2d00 100644 --- a/parser/output/raylib_api.txt +++ b/parser/output/raylib_api.txt @@ -2102,14 +2102,14 @@ Function 207: GetShapesTextureRectangle() (0 input parameters) Function 208: DrawPixel() (3 input parameters) Name: DrawPixel Return type: void - Description: Draw a pixel + Description: Draw a pixel using geometry [Can be slow, use with care] Param[1]: posX (type: int) Param[2]: posY (type: int) Param[3]: color (type: Color) Function 209: DrawPixelV() (2 input parameters) Name: DrawPixelV Return type: void - Description: Draw a pixel (Vector version) + Description: Draw a pixel using geometry (Vector version) [Can be slow, use with care] Param[1]: position (type: Vector2) Param[2]: color (type: Color) Function 210: DrawLine() (5 input parameters) diff --git a/parser/output/raylib_api.xml b/parser/output/raylib_api.xml index 140f4910d..13afbcb64 100644 --- a/parser/output/raylib_api.xml +++ b/parser/output/raylib_api.xml @@ -1297,12 +1297,12 @@ - + - + diff --git a/src/raylib.h b/src/raylib.h index f298fd731..106a96ae5 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -1234,8 +1234,8 @@ RLAPI Texture2D GetShapesTexture(void); // Get t RLAPI Rectangle GetShapesTextureRectangle(void); // Get texture source rectangle that is used for shapes drawing // Basic shapes drawing functions -RLAPI void DrawPixel(int posX, int posY, Color color); // Draw a pixel -RLAPI void DrawPixelV(Vector2 position, Color color); // Draw a pixel (Vector version) +RLAPI void DrawPixel(int posX, int posY, Color color); // Draw a pixel using geometry [Can be slow, use with care] +RLAPI void DrawPixelV(Vector2 position, Color color); // Draw a pixel using geometry (Vector version) [Can be slow, use with care] RLAPI void DrawLine(int startPosX, int startPosY, int endPosX, int endPosY, Color color); // Draw a line RLAPI void DrawLineV(Vector2 startPos, Vector2 endPos, Color color); // Draw a line (using gl lines) RLAPI void DrawLineEx(Vector2 startPos, Vector2 endPos, float thick, Color color); // Draw a line (using triangles/quads) From 84a4d93bc4e421e2fc654b0e4d7c513ac17990e0 Mon Sep 17 00:00:00 2001 From: Ray Date: Mon, 30 Sep 2024 12:06:53 +0200 Subject: [PATCH 094/208] Fix #4349 --- src/config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/config.h b/src/config.h index f6e3fe304..ca9489822 100644 --- a/src/config.h +++ b/src/config.h @@ -228,7 +228,7 @@ // rmodels: Configuration values //------------------------------------------------------------------------------------ #define MAX_MATERIAL_MAPS 12 // Maximum number of shader maps supported -#define MAX_MESH_VERTEX_BUFFERS 7 // Maximum vertex buffers (VBO) per mesh +#define MAX_MESH_VERTEX_BUFFERS 9 // Maximum vertex buffers (VBO) per mesh //------------------------------------------------------------------------------------ // Module: raudio - Configuration Flags From 0e7bcd5639729fac1df19ed2d0622ff3daab59e3 Mon Sep 17 00:00:00 2001 From: Jeffery Myers Date: Mon, 30 Sep 2024 03:10:02 -0700 Subject: [PATCH 095/208] [MODELS] Disable GPU skinning for MacOS platform (#4348) * Update raylib_api.* by CI * Disable GPU skinning on MacOS Add GPU skinning example to MSVC Projects. * Update raylib_api.* by CI --------- Co-authored-by: github-actions[bot] --- examples/models/models_gpu_skinning.c | 2 + parser/output/raylib_api.json | 2 +- parser/output/raylib_api.lua | 2 +- parser/output/raylib_api.txt | 2 +- parser/output/raylib_api.xml | 2 +- .../examples/models_gpu_skinning.vcxproj | 387 ++++++++++++++++++ projects/VS2022/raylib.sln | 19 + src/config.h | 15 +- src/raylib.h | 2 +- src/rlgl.h | 14 +- src/rmodels.c | 18 +- 11 files changed, 447 insertions(+), 18 deletions(-) create mode 100644 projects/VS2022/examples/models_gpu_skinning.vcxproj diff --git a/examples/models/models_gpu_skinning.c b/examples/models/models_gpu_skinning.c index e9cd73f4b..846f0a890 100644 --- a/examples/models/models_gpu_skinning.c +++ b/examples/models/models_gpu_skinning.c @@ -10,6 +10,8 @@ * BSD-like license that allows static linking with closed source software * * Copyright (c) 2024 Daniel Holden (@orangeduck) +* +* Note: Due to limitations in the Apple OpenGL driver, this feature does not work on MacOS * ********************************************************************************************/ diff --git a/parser/output/raylib_api.json b/parser/output/raylib_api.json index ca3b276cf..58fb9d6a8 100644 --- a/parser/output/raylib_api.json +++ b/parser/output/raylib_api.json @@ -11104,7 +11104,7 @@ }, { "name": "UpdateModelAnimationBoneMatrices", - "description": "Update model animation mesh bone matrices", + "description": "Update model animation mesh bone matrices (Note GPU skinning does not work on Mac)", "returnType": "void", "params": [ { diff --git a/parser/output/raylib_api.lua b/parser/output/raylib_api.lua index b010e19cf..bea3813cf 100644 --- a/parser/output/raylib_api.lua +++ b/parser/output/raylib_api.lua @@ -7621,7 +7621,7 @@ return { }, { name = "UpdateModelAnimationBoneMatrices", - description = "Update model animation mesh bone matrices", + description = "Update model animation mesh bone matrices (Note GPU skinning does not work on Mac)", returnType = "void", params = { {type = "Model", name = "model"}, diff --git a/parser/output/raylib_api.txt b/parser/output/raylib_api.txt index 19abf2d00..9a953b768 100644 --- a/parser/output/raylib_api.txt +++ b/parser/output/raylib_api.txt @@ -4230,7 +4230,7 @@ Function 503: IsModelAnimationValid() (2 input parameters) Function 504: UpdateModelAnimationBoneMatrices() (3 input parameters) Name: UpdateModelAnimationBoneMatrices Return type: void - Description: Update model animation mesh bone matrices + Description: Update model animation mesh bone matrices (Note GPU skinning does not work on Mac) Param[1]: model (type: Model) Param[2]: anim (type: ModelAnimation) Param[3]: frame (type: int) diff --git a/parser/output/raylib_api.xml b/parser/output/raylib_api.xml index 13afbcb64..895680f2c 100644 --- a/parser/output/raylib_api.xml +++ b/parser/output/raylib_api.xml @@ -2830,7 +2830,7 @@ - + diff --git a/projects/VS2022/examples/models_gpu_skinning.vcxproj b/projects/VS2022/examples/models_gpu_skinning.vcxproj new file mode 100644 index 000000000..bd596bed6 --- /dev/null +++ b/projects/VS2022/examples/models_gpu_skinning.vcxproj @@ -0,0 +1,387 @@ + + + + + Debug.DLL + Win32 + + + Debug.DLL + x64 + + + Debug + Win32 + + + Debug + x64 + + + Release.DLL + Win32 + + + Release.DLL + x64 + + + Release + Win32 + + + Release + x64 + + + + {8245DAD9-D402-4D5C-8F45-32229CD3B263} + Win32Proj + models_loading + 10.0 + models_gpu_skinning + + + + Application + true + $(DefaultPlatformToolset) + Unicode + + + Application + true + $(DefaultPlatformToolset) + Unicode + + + Application + true + $(DefaultPlatformToolset) + Unicode + + + Application + true + $(DefaultPlatformToolset) + Unicode + + + Application + false + $(DefaultPlatformToolset) + true + Unicode + + + Application + false + $(DefaultPlatformToolset) + true + Unicode + + + Application + false + $(DefaultPlatformToolset) + true + Unicode + + + Application + false + $(DefaultPlatformToolset) + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ + $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ + + + true + $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ + $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ + + + true + $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ + $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ + + + true + $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ + $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ + + + false + $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ + $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ + + + false + $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ + $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ + + + false + $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ + $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ + + + false + $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ + $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ + + + $(SolutionDir)..\..\examples\models + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\models + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\models + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\models + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\models + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\models + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\models + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\models + WindowsLocalDebugger + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions) + CompileAsC + $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories) + + + Console + true + $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\ + raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions) + CompileAsC + $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories) + /FS %(AdditionalOptions) + + + Console + true + $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\ + raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions) + CompileAsC + $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories) + + + Console + true + $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\ + raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)" + Copy Debug DLL to output directory + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions) + CompileAsC + $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories) + + + Console + true + $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\ + raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)" + Copy Debug DLL to output directory + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP + $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories) + CompileAsC + true + + + Console + true + true + true + raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\ + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP + $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories) + CompileAsC + true + + + Console + true + true + true + raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\ + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP + $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories) + CompileAsC + true + + + Console + true + true + true + raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\ + + + xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)" + + + Copy Release DLL to output directory + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP + $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories) + CompileAsC + true + + + Console + true + true + true + raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\ + + + xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)" + + + Copy Release DLL to output directory + + + + + + + + {e89d61ac-55de-4482-afd4-df7242ebc859} + + + + + + \ No newline at end of file diff --git a/projects/VS2022/raylib.sln b/projects/VS2022/raylib.sln index 294d0e84d..2b262bcfe 100644 --- a/projects/VS2022/raylib.sln +++ b/projects/VS2022/raylib.sln @@ -299,6 +299,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shapes_splines_drawing", "e EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shapes_top_down_lights", "examples\shapes_top_down_lights.vcxproj", "{703BE7BA-5B99-4F70-806D-3A259F6A991E}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "models_gpu_skinning", "examples\models_gpu_skinning.vcxproj", "{8245DAD9-D402-4D5C-8F45-32229CD3B263}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug.DLL|x64 = Debug.DLL|x64 @@ -2531,6 +2533,22 @@ Global {703BE7BA-5B99-4F70-806D-3A259F6A991E}.Release|x64.Build.0 = Release|x64 {703BE7BA-5B99-4F70-806D-3A259F6A991E}.Release|x86.ActiveCfg = Release|Win32 {703BE7BA-5B99-4F70-806D-3A259F6A991E}.Release|x86.Build.0 = Release|Win32 + {8245DAD9-D402-4D5C-8F45-32229CD3B263}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 + {8245DAD9-D402-4D5C-8F45-32229CD3B263}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 + {8245DAD9-D402-4D5C-8F45-32229CD3B263}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 + {8245DAD9-D402-4D5C-8F45-32229CD3B263}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 + {8245DAD9-D402-4D5C-8F45-32229CD3B263}.Debug|x64.ActiveCfg = Debug|x64 + {8245DAD9-D402-4D5C-8F45-32229CD3B263}.Debug|x64.Build.0 = Debug|x64 + {8245DAD9-D402-4D5C-8F45-32229CD3B263}.Debug|x86.ActiveCfg = Debug|Win32 + {8245DAD9-D402-4D5C-8F45-32229CD3B263}.Debug|x86.Build.0 = Debug|Win32 + {8245DAD9-D402-4D5C-8F45-32229CD3B263}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 + {8245DAD9-D402-4D5C-8F45-32229CD3B263}.Release.DLL|x64.Build.0 = Release.DLL|x64 + {8245DAD9-D402-4D5C-8F45-32229CD3B263}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 + {8245DAD9-D402-4D5C-8F45-32229CD3B263}.Release.DLL|x86.Build.0 = Release.DLL|Win32 + {8245DAD9-D402-4D5C-8F45-32229CD3B263}.Release|x64.ActiveCfg = Release|x64 + {8245DAD9-D402-4D5C-8F45-32229CD3B263}.Release|x64.Build.0 = Release|x64 + {8245DAD9-D402-4D5C-8F45-32229CD3B263}.Release|x86.ActiveCfg = Release|Win32 + {8245DAD9-D402-4D5C-8F45-32229CD3B263}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -2682,6 +2700,7 @@ Global {D8026C60-CCBC-45DF-9085-BF21569EB414} = {DA049009-21FF-4AC0-84E4-830DD1BCD0CE} {DF25E545-00FF-4E64-844C-7DF98991F901} = {278D8859-20B1-428F-8448-064F46E1F021} {703BE7BA-5B99-4F70-806D-3A259F6A991E} = {278D8859-20B1-428F-8448-064F46E1F021} + {8245DAD9-D402-4D5C-8F45-32229CD3B263} = {AF5BEC5C-1F2B-4DA8-B12D-D09FE569237C} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {E926C768-6307-4423-A1EC-57E95B1FAB29} diff --git a/src/config.h b/src/config.h index ca9489822..8bba37606 100644 --- a/src/config.h +++ b/src/config.h @@ -119,9 +119,18 @@ #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR 3 #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT 4 #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2 5 -#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS 6 -#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS 7 -#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_INDICES 8 +#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_INDICES 6 + +// The mac OpenGL drivers do not support more than 8 VBOs, so we can't support GPU animations +#ifndef __APPLE__ +#define RL_SUPPORT_MESH_ANIMATION_VBO +#endif + +#ifdef RL_SUPPORT_MESH_ANIMATION_VBO +#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS 7 +#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS 8 +#endif + // Default shader vertex attribute names to set location points // NOTE: When a new shader is loaded, the following locations are tried to be set for convenience diff --git a/src/raylib.h b/src/raylib.h index 106a96ae5..08121c50c 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -1597,7 +1597,7 @@ RLAPI void UpdateModelAnimation(Model model, ModelAnimation anim, int frame); RLAPI void UnloadModelAnimation(ModelAnimation anim); // Unload animation data RLAPI void UnloadModelAnimations(ModelAnimation *animations, int animCount); // Unload animation array data RLAPI bool IsModelAnimationValid(Model model, ModelAnimation anim); // Check model animation skeleton match -RLAPI void UpdateModelAnimationBoneMatrices(Model model, ModelAnimation anim, int frame); // Update model animation mesh bone matrices +RLAPI void UpdateModelAnimationBoneMatrices(Model model, ModelAnimation anim, int frame); // Update model animation mesh bone matrices (Note GPU skinning does not work on Mac) // Collision detection functions RLAPI bool CheckCollisionSpheres(Vector3 center1, float radius1, Vector3 center2, float radius2); // Check collision between two spheres diff --git a/src/rlgl.h b/src/rlgl.h index 875b568f5..843c46a2a 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -344,16 +344,17 @@ #ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2 #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2 5 #endif +#ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_INDICES +#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_INDICES 6 +#endif #ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS - #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS 6 + #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS 7 #endif #ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS - #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS 7 -#endif -#ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_INDICES - #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_INDICES 8 + #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS 8 #endif + //---------------------------------------------------------------------------------- // Types and Structures Definition //---------------------------------------------------------------------------------- @@ -4170,8 +4171,11 @@ unsigned int rlLoadShaderProgram(unsigned int vShaderId, unsigned int fShaderId) glBindAttribLocation(program, RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR, RL_DEFAULT_SHADER_ATTRIB_NAME_COLOR); glBindAttribLocation(program, RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT, RL_DEFAULT_SHADER_ATTRIB_NAME_TANGENT); glBindAttribLocation(program, RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2, RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2); + +#ifdef RL_SUPPORT_MESH_ANIMATION_VBO glBindAttribLocation(program, RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS, RL_DEFAULT_SHADER_ATTRIB_NAME_BONEIDS); glBindAttribLocation(program, RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS, RL_DEFAULT_SHADER_ATTRIB_NAME_BONEWEIGHTS); +#endif // NOTE: If some attrib name is no found on the shader, it locations becomes -1 diff --git a/src/rmodels.c b/src/rmodels.c index ebdd178fd..d5c2f9954 100644 --- a/src/rmodels.c +++ b/src/rmodels.c @@ -1252,9 +1252,10 @@ void UploadMesh(Mesh *mesh, bool dynamic) mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR] = 0; // Vertex buffer: colors mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT] = 0; // Vertex buffer: tangents mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2] = 0; // Vertex buffer: texcoords2 + mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_INDICES] = 0; // Vertex buffer: indices mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS] = 0; // Vertex buffer: boneIds mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS] = 0; // Vertex buffer: boneWeights - mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_INDICES] = 0; // Vertex buffer: indices + #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) mesh->vaoId = rlLoadVertexArray(); @@ -1340,7 +1341,8 @@ void UploadMesh(Mesh *mesh, bool dynamic) rlSetVertexAttributeDefault(RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2, value, SHADER_ATTRIB_VEC2, 2); rlDisableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2); } - + +#ifdef RL_SUPPORT_MESH_ANIMATION_VBO if (mesh->boneIds != NULL) { // Enable vertex attribute: boneIds (shader-location = 6) @@ -1372,6 +1374,7 @@ void UploadMesh(Mesh *mesh, bool dynamic) rlSetVertexAttributeDefault(RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS, value, SHADER_ATTRIB_VEC4, 2); rlDisableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS); } +#endif if (mesh->indices != NULL) { @@ -1485,13 +1488,14 @@ void DrawMesh(Mesh mesh, Material material, Matrix transform) // Upload model normal matrix (if locations available) if (material.shader.locs[SHADER_LOC_MATRIX_NORMAL] != -1) rlSetUniformMatrix(material.shader.locs[SHADER_LOC_MATRIX_NORMAL], MatrixTranspose(MatrixInvert(matModel))); - + +#ifdef RL_SUPPORT_MESH_ANIMATION_VBO // Upload Bone Transforms if (material.shader.locs[SHADER_LOC_BONE_MATRICES] != -1 && mesh.boneMatrices) { rlSetUniformMatrices(material.shader.locs[SHADER_LOC_BONE_MATRICES], mesh.boneMatrices, mesh.boneCount); } - +#endif //----------------------------------------------------- // Bind active texture maps (if available) @@ -1570,7 +1574,8 @@ void DrawMesh(Mesh mesh, Material material, Matrix transform) rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD02], 2, RL_FLOAT, 0, 0, 0); rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD02]); } - + +#ifdef RL_SUPPORT_MESH_ANIMATION_VBO // Bind mesh VBO data: vertex bone ids (shader-location = 6, if available) if (material.shader.locs[SHADER_LOC_VERTEX_BONEIDS] != -1) { @@ -1586,6 +1591,7 @@ void DrawMesh(Mesh mesh, Material material, Matrix transform) rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_BONEWEIGHTS], 4, RL_FLOAT, 0, 0, 0); rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_BONEWEIGHTS]); } +#endif if (mesh.indices != NULL) rlEnableVertexBufferElement(mesh.vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_INDICES]); } @@ -1729,11 +1735,13 @@ void DrawMeshInstanced(Mesh mesh, Material material, const Matrix *transforms, i // Upload model normal matrix (if locations available) if (material.shader.locs[SHADER_LOC_MATRIX_NORMAL] != -1) rlSetUniformMatrix(material.shader.locs[SHADER_LOC_MATRIX_NORMAL], MatrixTranspose(MatrixInvert(matModel))); +#ifdef RL_SUPPORT_MESH_ANIMATION_VBO // Upload Bone Transforms if (material.shader.locs[SHADER_LOC_BONE_MATRICES] != -1 && mesh.boneMatrices) { rlSetUniformMatrices(material.shader.locs[SHADER_LOC_BONE_MATRICES], mesh.boneMatrices, mesh.boneCount); } +#endif //----------------------------------------------------- From 282d6478baa51a509bf0a4b1d761a0bd7fd8bbf7 Mon Sep 17 00:00:00 2001 From: Asdqwe Date: Tue, 1 Oct 2024 07:09:06 -0300 Subject: [PATCH 096/208] Complements the #4348 GPU skinning fix (#4352) --- src/rlgl.h | 5 ++++- src/rmodels.c | 7 ++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/rlgl.h b/src/rlgl.h index 843c46a2a..98310c101 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -345,14 +345,17 @@ #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2 5 #endif #ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_INDICES -#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_INDICES 6 + #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_INDICES 6 #endif + +#ifdef RL_SUPPORT_MESH_ANIMATION_VBO #ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS 7 #endif #ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS 8 #endif +#endif //---------------------------------------------------------------------------------- diff --git a/src/rmodels.c b/src/rmodels.c index d5c2f9954..b7f18f307 100644 --- a/src/rmodels.c +++ b/src/rmodels.c @@ -1253,8 +1253,11 @@ void UploadMesh(Mesh *mesh, bool dynamic) mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT] = 0; // Vertex buffer: tangents mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2] = 0; // Vertex buffer: texcoords2 mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_INDICES] = 0; // Vertex buffer: indices + +#ifdef RL_SUPPORT_MESH_ANIMATION_VBO mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS] = 0; // Vertex buffer: boneIds mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS] = 0; // Vertex buffer: boneWeights +#endif #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) @@ -1819,7 +1822,8 @@ void DrawMeshInstanced(Mesh mesh, Material material, const Matrix *transforms, i rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD02], 2, RL_FLOAT, 0, 0, 0); rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD02]); } - + +#ifdef RL_SUPPORT_MESH_ANIMATION_VBO // Bind mesh VBO data: vertex bone ids (shader-location = 6, if available) if (material.shader.locs[SHADER_LOC_VERTEX_BONEIDS] != -1) { @@ -1835,6 +1839,7 @@ void DrawMeshInstanced(Mesh mesh, Material material, const Matrix *transforms, i rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_BONEWEIGHTS], 4, RL_FLOAT, 0, 0, 0); rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_BONEWEIGHTS]); } +#endif if (mesh.indices != NULL) rlEnableVertexBufferElement(mesh.vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_INDICES]); } From d9c10ed2646eea784ba71ae24ef53f67a497fc08 Mon Sep 17 00:00:00 2001 From: Asdqwe Date: Wed, 2 Oct 2024 05:49:06 -0300 Subject: [PATCH 097/208] Fixes GetClipboardText() memory leak for PLATFORM_DESKTOP_SDL (#4354) --- src/platforms/rcore_desktop_sdl.c | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/src/platforms/rcore_desktop_sdl.c b/src/platforms/rcore_desktop_sdl.c index 794f9e6a0..90372c2f6 100644 --- a/src/platforms/rcore_desktop_sdl.c +++ b/src/platforms/rcore_desktop_sdl.c @@ -57,6 +57,13 @@ #include "SDL_opengl.h" // SDL OpenGL functionality (if required, instead of internal renderer) #endif +//---------------------------------------------------------------------------------- +// Defines and Macros +//---------------------------------------------------------------------------------- +#ifndef MAX_CLIPBOARD_BUFFER_LENGTH + #define MAX_CLIPBOARD_BUFFER_LENGTH 1024 // Size of the clipboard buffer used on GetClipboardText() +#endif + //---------------------------------------------------------------------------------- // Types and Structures Definition //---------------------------------------------------------------------------------- @@ -852,10 +859,22 @@ void SetClipboardText(const char *text) } // Get clipboard text content -// NOTE: returned string must be freed with SDL_free() const char *GetClipboardText(void) { - return SDL_GetClipboardText(); + static char buffer[MAX_CLIPBOARD_BUFFER_LENGTH] = { 0 }; + + char *clipboard = SDL_GetClipboardText(); + + int clipboardSize = snprintf(buffer, sizeof(buffer), "%s", clipboard); + if (clipboardSize >= MAX_CLIPBOARD_BUFFER_LENGTH) + { + char *truncate = buffer + MAX_CLIPBOARD_BUFFER_LENGTH - 4; + sprintf(truncate, "..."); + } + + SDL_free(clipboard); + + return buffer; } // Show mouse cursor @@ -1589,8 +1608,8 @@ int InitPlatform(void) // Initialize storage system //---------------------------------------------------------------------------- // Define base path for storage - CORE.Storage.basePath = SDL_GetBasePath(); // Alternative: GetWorkingDirectory(); - CHDIR(CORE.Storage.basePath); + CORE.Storage.basePath = SDL_GetBasePath(); // Alternative: GetWorkingDirectory(); + CHDIR(CORE.Storage.basePath); //---------------------------------------------------------------------------- TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (SDL): Initialized successfully"); From 09987b01cc2c1f4e49d3a2bb11cf235a5a529435 Mon Sep 17 00:00:00 2001 From: Jeffery Myers Date: Wed, 2 Oct 2024 01:49:56 -0700 Subject: [PATCH 098/208] [MODELS] Better fix for GPU skinning issues (#4353) * Make the max VBO match the animation flag. * re-enable GPU skinning for mac, and fix the max buffer to be correct based on the GPU skinning support flag. --- src/config.h | 13 ++++++++----- src/rlgl.h | 2 +- src/rmodels.c | 8 ++++---- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/config.h b/src/config.h index 8bba37606..5504a1823 100644 --- a/src/config.h +++ b/src/config.h @@ -121,12 +121,10 @@ #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2 5 #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_INDICES 6 -// The mac OpenGL drivers do not support more than 8 VBOs, so we can't support GPU animations -#ifndef __APPLE__ -#define RL_SUPPORT_MESH_ANIMATION_VBO -#endif -#ifdef RL_SUPPORT_MESH_ANIMATION_VBO +#define RL_SUPPORT_MESH_GPU_SKINNING // Remove this if your GPU does not support more than 8 VBOs + +#ifdef RL_SUPPORT_MESH_GPU_SKINNING #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS 7 #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS 8 #endif @@ -237,7 +235,12 @@ // rmodels: Configuration values //------------------------------------------------------------------------------------ #define MAX_MATERIAL_MAPS 12 // Maximum number of shader maps supported + +#ifdef RL_SUPPORT_MESH_GPU_SKINNING #define MAX_MESH_VERTEX_BUFFERS 9 // Maximum vertex buffers (VBO) per mesh +#else +#define MAX_MESH_VERTEX_BUFFERS 7 // Maximum vertex buffers (VBO) per mesh +#endif //------------------------------------------------------------------------------------ // Module: raudio - Configuration Flags diff --git a/src/rlgl.h b/src/rlgl.h index 98310c101..95af8e0e7 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -4175,7 +4175,7 @@ unsigned int rlLoadShaderProgram(unsigned int vShaderId, unsigned int fShaderId) glBindAttribLocation(program, RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT, RL_DEFAULT_SHADER_ATTRIB_NAME_TANGENT); glBindAttribLocation(program, RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2, RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2); -#ifdef RL_SUPPORT_MESH_ANIMATION_VBO +#ifdef RL_SUPPORT_MESH_GPU_SKINNING glBindAttribLocation(program, RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS, RL_DEFAULT_SHADER_ATTRIB_NAME_BONEIDS); glBindAttribLocation(program, RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS, RL_DEFAULT_SHADER_ATTRIB_NAME_BONEWEIGHTS); #endif diff --git a/src/rmodels.c b/src/rmodels.c index b7f18f307..7e17386e1 100644 --- a/src/rmodels.c +++ b/src/rmodels.c @@ -1345,7 +1345,7 @@ void UploadMesh(Mesh *mesh, bool dynamic) rlDisableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2); } -#ifdef RL_SUPPORT_MESH_ANIMATION_VBO +#ifdef RL_SUPPORT_MESH_GPU_SKINNING if (mesh->boneIds != NULL) { // Enable vertex attribute: boneIds (shader-location = 6) @@ -1492,7 +1492,7 @@ void DrawMesh(Mesh mesh, Material material, Matrix transform) // Upload model normal matrix (if locations available) if (material.shader.locs[SHADER_LOC_MATRIX_NORMAL] != -1) rlSetUniformMatrix(material.shader.locs[SHADER_LOC_MATRIX_NORMAL], MatrixTranspose(MatrixInvert(matModel))); -#ifdef RL_SUPPORT_MESH_ANIMATION_VBO +#ifdef RL_SUPPORT_MESH_GPU_SKINNING // Upload Bone Transforms if (material.shader.locs[SHADER_LOC_BONE_MATRICES] != -1 && mesh.boneMatrices) { @@ -1578,7 +1578,7 @@ void DrawMesh(Mesh mesh, Material material, Matrix transform) rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD02]); } -#ifdef RL_SUPPORT_MESH_ANIMATION_VBO +#ifdef RL_SUPPORT_MESH_GPU_SKINNING // Bind mesh VBO data: vertex bone ids (shader-location = 6, if available) if (material.shader.locs[SHADER_LOC_VERTEX_BONEIDS] != -1) { @@ -1738,7 +1738,7 @@ void DrawMeshInstanced(Mesh mesh, Material material, const Matrix *transforms, i // Upload model normal matrix (if locations available) if (material.shader.locs[SHADER_LOC_MATRIX_NORMAL] != -1) rlSetUniformMatrix(material.shader.locs[SHADER_LOC_MATRIX_NORMAL], MatrixTranspose(MatrixInvert(matModel))); -#ifdef RL_SUPPORT_MESH_ANIMATION_VBO +#ifdef RL_SUPPORT_MESH_GPU_SKINNING // Upload Bone Transforms if (material.shader.locs[SHADER_LOC_BONE_MATRICES] != -1 && mesh.boneMatrices) { From 96d91a38923094951e481d9fbc26291026e48fea Mon Sep 17 00:00:00 2001 From: Asdqwe Date: Wed, 2 Oct 2024 06:41:21 -0300 Subject: [PATCH 099/208] [rlgl] Fix rlgl standalone defaults (#4357) * Fix rlgl standalone defaults * Fix rmodels --- src/rlgl.h | 2 +- src/rmodels.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/rlgl.h b/src/rlgl.h index 95af8e0e7..43698f63a 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -348,7 +348,7 @@ #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_INDICES 6 #endif -#ifdef RL_SUPPORT_MESH_ANIMATION_VBO +#ifdef RL_SUPPORT_MESH_GPU_SKINNING #ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS 7 #endif diff --git a/src/rmodels.c b/src/rmodels.c index 7e17386e1..d2bf528ff 100644 --- a/src/rmodels.c +++ b/src/rmodels.c @@ -1254,7 +1254,7 @@ void UploadMesh(Mesh *mesh, bool dynamic) mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2] = 0; // Vertex buffer: texcoords2 mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_INDICES] = 0; // Vertex buffer: indices -#ifdef RL_SUPPORT_MESH_ANIMATION_VBO +#ifdef RL_SUPPORT_MESH_GPU_SKINNING mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS] = 0; // Vertex buffer: boneIds mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS] = 0; // Vertex buffer: boneWeights #endif @@ -1823,7 +1823,7 @@ void DrawMeshInstanced(Mesh mesh, Material material, const Matrix *transforms, i rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD02]); } -#ifdef RL_SUPPORT_MESH_ANIMATION_VBO +#ifdef RL_SUPPORT_MESH_GPU_SKINNING // Bind mesh VBO data: vertex bone ids (shader-location = 6, if available) if (material.shader.locs[SHADER_LOC_VERTEX_BONEIDS] != -1) { From 20ce8ba04651502203151f94e4736484fb390b45 Mon Sep 17 00:00:00 2001 From: Ashley Chekhov <70078024+FluxFlu@users.noreply.github.com> Date: Fri, 4 Oct 2024 09:04:26 +0000 Subject: [PATCH 100/208] Typo fix (#4356) Seemed to be a typo. Hope this helps. --- examples/textures/textures_image_drawing.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/textures/textures_image_drawing.c b/examples/textures/textures_image_drawing.c index f49bc9e77..d0eee999d 100644 --- a/examples/textures/textures_image_drawing.c +++ b/examples/textures/textures_image_drawing.c @@ -47,7 +47,7 @@ int main(void) UnloadImage(cat); // Unload image from RAM - // Load custom font for frawing on image + // Load custom font for drawing on image Font font = LoadFont("resources/custom_jupiter_crash.png"); // Draw over image using custom font @@ -93,4 +93,4 @@ int main(void) //-------------------------------------------------------------------------------------- return 0; -} \ No newline at end of file +} From 0ef07918542b17956c63aa5a037a64b6c60bcd46 Mon Sep 17 00:00:00 2001 From: Nikolas Date: Fri, 4 Oct 2024 11:05:19 +0200 Subject: [PATCH 101/208] Allow Zig build script to change desktop backend (#4358) --- src/build.zig | 34 ++++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/src/build.zig b/src/build.zig index 4e112d78f..b08b909de 100644 --- a/src/build.zig +++ b/src/build.zig @@ -40,6 +40,17 @@ pub fn addRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std. return raylib; } +fn setDesktopPlatform(raylib: *std.Build.Step.Compile, platform: PlatformBackend) void { + raylib.defineCMacro("PLATFORM_DESKTOP", null); + + switch (platform) { + .glfw => raylib.defineCMacro("PLATFORM_DESKTOP_GLFW", null), + .rgfw => raylib.defineCMacro("PLATFORM_DESKTOP_RGFW", null), + .sdl => raylib.defineCMacro("PLATFORM_DESKTOP_SDL", null), + else => {} + } +} + fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, options: Options) !*std.Build.Step.Compile { raylib_flags_arr.clearRetainingCapacity(); @@ -102,7 +113,7 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std. raylib.linkLibC(); // No GLFW required on PLATFORM_DRM - if (!options.platform_drm) { + if (options.platform != .drm) { raylib.addIncludePath(b.path("src/external/glfw/include")); } @@ -136,10 +147,10 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std. raylib.linkSystemLibrary("gdi32"); raylib.linkSystemLibrary("opengl32"); - raylib.defineCMacro("PLATFORM_DESKTOP", null); + setDesktopPlatform(raylib, options.platform); }, .linux => { - if (!options.platform_drm) { + if (options.platform != .drm) { try c_source_files.append("rglfw.c"); raylib.linkSystemLibrary("GL"); raylib.linkSystemLibrary("rt"); @@ -177,7 +188,7 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std. waylandGenerate(b, raylib, "xdg-activation-v1.xml", "xdg-activation-v1-client-protocol"); waylandGenerate(b, raylib, "idle-inhibit-unstable-v1.xml", "idle-inhibit-unstable-v1-client-protocol"); } - raylib.defineCMacro("PLATFORM_DESKTOP", null); + setDesktopPlatform(raylib, options.platform); } else { if (options.opengl_version == .auto) { raylib.linkSystemLibrary("GLESv2"); @@ -211,7 +222,7 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std. raylib.linkSystemLibrary("Xxf86vm"); raylib.linkSystemLibrary("Xcursor"); - raylib.defineCMacro("PLATFORM_DESKTOP", null); + setDesktopPlatform(raylib, options.platform); }, .macos => { // On macos rglfw.c include Objective-C files. @@ -227,7 +238,7 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std. raylib.linkFramework("AppKit"); raylib.linkFramework("IOKit"); - raylib.defineCMacro("PLATFORM_DESKTOP", null); + setDesktopPlatform(raylib, options.platform); }, .emscripten => { raylib.defineCMacro("PLATFORM_WEB", null); @@ -286,7 +297,7 @@ pub const Options = struct { rtext: bool = true, rtextures: bool = true, raygui: bool = false, - platform_drm: bool = false, + platform: PlatformBackend = .glfw, shared: bool = false, linux_display_backend: LinuxDisplayBackend = .Both, opengl_version: OpenglVersion = .auto, @@ -323,6 +334,13 @@ pub const LinuxDisplayBackend = enum { Both, }; +pub const PlatformBackend = enum { + glfw, + rgfw, + sdl, + drm +}; + pub fn build(b: *std.Build) !void { // Standard target options allows the person running `zig build` to choose // what target to build for. Here we do not override the defaults, which @@ -336,7 +354,7 @@ pub fn build(b: *std.Build) !void { const defaults = Options{}; const options = Options{ - .platform_drm = b.option(bool, "platform_drm", "Compile raylib in native mode (no X11)") orelse defaults.platform_drm, + .platform = b.option(PlatformBackend, "platform", "Choose the platform backedn for desktop target") orelse defaults.platform, .raudio = b.option(bool, "raudio", "Compile with audio support") orelse defaults.raudio, .rmodels = b.option(bool, "rmodels", "Compile with models support") orelse defaults.rmodels, .rtext = b.option(bool, "rtext", "Compile with text support") orelse defaults.rtext, From cded3782056ab1cb8b83e6fe346be1ea4f9e1aae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kacper=20Zyba=C5=82a?= Date: Fri, 4 Oct 2024 11:08:12 +0200 Subject: [PATCH 102/208] [build] CMake: Fix GRAPHICS check (#4359) --- cmake/LibraryConfigurations.cmake | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/cmake/LibraryConfigurations.cmake b/cmake/LibraryConfigurations.cmake index 6d2250c71..fb7898306 100644 --- a/cmake/LibraryConfigurations.cmake +++ b/cmake/LibraryConfigurations.cmake @@ -100,9 +100,10 @@ elseif ("${PLATFORM}" MATCHES "SDL") endif () if (NOT ${OPENGL_VERSION} MATCHES "OFF") - set(${SUGGESTED_GRAPHICS} "${GRAPHICS}") + set(SUGGESTED_GRAPHICS "${GRAPHICS}") + if (${OPENGL_VERSION} MATCHES "4.3") - set(GRAPHICS "GRAPHICS_API_OPENGL_43") + set(GRAPHICS "GRAPHICS_API_OPENGL_43") elseif (${OPENGL_VERSION} MATCHES "3.3") set(GRAPHICS "GRAPHICS_API_OPENGL_33") elseif (${OPENGL_VERSION} MATCHES "2.1") @@ -114,8 +115,8 @@ if (NOT ${OPENGL_VERSION} MATCHES "OFF") elseif (${OPENGL_VERSION} MATCHES "ES 3.0") set(GRAPHICS "GRAPHICS_API_OPENGL_ES3") endif () - if ("${SUGGESTED_GRAPHICS}" AND NOT "${SUGGESTED_GRAPHICS}" STREQUAL "${GRAPHICS}") - message(WARNING "You are overriding the suggested GRAPHICS=${SUGGESTED_GRAPHICS} with ${GRAPHICS}! This may fail") + if (NOT "${SUGGESTED_GRAPHICS}" STREQUAL "" AND NOT "${SUGGESTED_GRAPHICS}" STREQUAL "${GRAPHICS}") + message(WARNING "You are overriding the suggested GRAPHICS=${SUGGESTED_GRAPHICS} with ${GRAPHICS}! This may fail.") endif () endif () From da95f88c3641f8f27c5d531154fdd92c5232acc6 Mon Sep 17 00:00:00 2001 From: Anthony Carbajal <5776225+CrackedPixel@users.noreply.github.com> Date: Fri, 4 Oct 2024 04:15:43 -0500 Subject: [PATCH 103/208] updated camera speeds with GetFrameTime (#4362) --- src/rcamera.h | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/src/rcamera.h b/src/rcamera.h index c7f6fed3a..ccab549c1 100644 --- a/src/rcamera.h +++ b/src/rcamera.h @@ -444,11 +444,17 @@ void UpdateCamera(Camera *camera, int mode) bool lockView = ((mode == CAMERA_FREE) || (mode == CAMERA_FIRST_PERSON) || (mode == CAMERA_THIRD_PERSON) || (mode == CAMERA_ORBITAL)); bool rotateUp = false; + // Camera speeds based on frame time + float cameraMoveSpeed = CAMERA_MOVE_SPEED*GetFrameTime(); + float cameraRotationSpeed = CAMERA_ROTATION_SPEED*GetFrameTime(); + float cameraPanSpeed = CAMERA_PAN_SPEED*GetFrameTime(); + float cameraOrbitalSpeed = CAMERA_ORBITAL_SPEED*GetFrameTime(); + if (mode == CAMERA_CUSTOM) {} else if (mode == CAMERA_ORBITAL) { // Orbital can just orbit - Matrix rotation = MatrixRotate(GetCameraUp(camera), CAMERA_ORBITAL_SPEED*GetFrameTime()); + Matrix rotation = MatrixRotate(GetCameraUp(camera), cameraOrbitalSpeed); Vector3 view = Vector3Subtract(camera->position, camera->target); view = Vector3Transform(view, rotation); camera->position = Vector3Add(camera->target, view); @@ -456,22 +462,22 @@ void UpdateCamera(Camera *camera, int mode) else { // Camera rotation - if (IsKeyDown(KEY_DOWN)) CameraPitch(camera, -CAMERA_ROTATION_SPEED, lockView, rotateAroundTarget, rotateUp); - if (IsKeyDown(KEY_UP)) CameraPitch(camera, CAMERA_ROTATION_SPEED, lockView, rotateAroundTarget, rotateUp); - if (IsKeyDown(KEY_RIGHT)) CameraYaw(camera, -CAMERA_ROTATION_SPEED, rotateAroundTarget); - if (IsKeyDown(KEY_LEFT)) CameraYaw(camera, CAMERA_ROTATION_SPEED, rotateAroundTarget); - if (IsKeyDown(KEY_Q)) CameraRoll(camera, -CAMERA_ROTATION_SPEED); - if (IsKeyDown(KEY_E)) CameraRoll(camera, CAMERA_ROTATION_SPEED); + if (IsKeyDown(KEY_DOWN)) CameraPitch(camera, -cameraRotationSpeed, lockView, rotateAroundTarget, rotateUp); + if (IsKeyDown(KEY_UP)) CameraPitch(camera, cameraRotationSpeed, lockView, rotateAroundTarget, rotateUp); + if (IsKeyDown(KEY_RIGHT)) CameraYaw(camera, -cameraRotationSpeed, rotateAroundTarget); + if (IsKeyDown(KEY_LEFT)) CameraYaw(camera, cameraRotationSpeed, rotateAroundTarget); + if (IsKeyDown(KEY_Q)) CameraRoll(camera, -cameraRotationSpeed); + if (IsKeyDown(KEY_E)) CameraRoll(camera, cameraRotationSpeed); // Camera movement // Camera pan (for CAMERA_FREE) if ((mode == CAMERA_FREE) && (IsMouseButtonDown(MOUSE_BUTTON_MIDDLE))) { const Vector2 mouseDelta = GetMouseDelta(); - if (mouseDelta.x > 0.0f) CameraMoveRight(camera, CAMERA_PAN_SPEED, moveInWorldPlane); - if (mouseDelta.x < 0.0f) CameraMoveRight(camera, -CAMERA_PAN_SPEED, moveInWorldPlane); - if (mouseDelta.y > 0.0f) CameraMoveUp(camera, -CAMERA_PAN_SPEED); - if (mouseDelta.y < 0.0f) CameraMoveUp(camera, CAMERA_PAN_SPEED); + if (mouseDelta.x > 0.0f) CameraMoveRight(camera, cameraPanSpeed, moveInWorldPlane); + if (mouseDelta.x < 0.0f) CameraMoveRight(camera, -cameraPanSpeed, moveInWorldPlane); + if (mouseDelta.y > 0.0f) CameraMoveUp(camera, -cameraPanSpeed); + if (mouseDelta.y < 0.0f) CameraMoveUp(camera, cameraPanSpeed); } else { @@ -481,7 +487,6 @@ void UpdateCamera(Camera *camera, int mode) } // Keyboard support - float cameraMoveSpeed = CAMERA_MOVE_SPEED*GetFrameTime(); if (IsKeyDown(KEY_W)) CameraMoveForward(camera, cameraMoveSpeed, moveInWorldPlane); if (IsKeyDown(KEY_A)) CameraMoveRight(camera, -cameraMoveSpeed, moveInWorldPlane); if (IsKeyDown(KEY_S)) CameraMoveForward(camera, -cameraMoveSpeed, moveInWorldPlane); From d06287d5624005a4edfe6ea7adbce0b8ce11dc8f Mon Sep 17 00:00:00 2001 From: Anthony Carbajal <5776225+CrackedPixel@users.noreply.github.com> Date: Fri, 4 Oct 2024 04:16:03 -0500 Subject: [PATCH 104/208] taken from FluxFlus PR (#4363) From f9e709915a2c3e9f75d0ad3bb3f55dcfe0fdbe23 Mon Sep 17 00:00:00 2001 From: Ray Date: Fri, 4 Oct 2024 11:24:02 +0200 Subject: [PATCH 105/208] Fix #4355 --- src/platforms/rcore_desktop_glfw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platforms/rcore_desktop_glfw.c b/src/platforms/rcore_desktop_glfw.c index c6685846c..f7b94178c 100644 --- a/src/platforms/rcore_desktop_glfw.c +++ b/src/platforms/rcore_desktop_glfw.c @@ -1447,7 +1447,7 @@ int InitPlatform(void) } } - TRACELOG(LOG_WARNING, "SYSTEM: Closest fullscreen videomode: %i x %i", CORE.Window.display.width, CORE.Window.display.height); + TRACELOG(LOG_INFO, "SYSTEM: Closest fullscreen videomode: %i x %i", CORE.Window.display.width, CORE.Window.display.height); // NOTE: ISSUE: Closest videomode could not match monitor aspect-ratio, for example, // for a desired screen size of 800x450 (16:9), closest supported videomode is 800x600 (4:3), From 74ce90ce671fbcd0d31e26d7b13d142b8425de60 Mon Sep 17 00:00:00 2001 From: Magnus Oblerion <82583559+oblerion@users.noreply.github.com> Date: Sun, 6 Oct 2024 15:47:47 +0200 Subject: [PATCH 106/208] [example] Input virtual controls example (#4342) * Add files via upload * Update core_input_gamepad_virtual.c * Add files via upload * Update and rename core_input_gamepad_virtual.c to core_virtual_Dpad.c * Update and rename core_virtual_Dpad.c to core_input_virtual_controls.c * Delete examples/core/core_input_gamepad_virtual.png * Add files via upload * Update Makefile * Update Makefile.Web * Update README.md * Update README.md * Create core_input_virtual_controls.vcxproj * Delete projects/VS2022/examples/core_input_virtual_controls.vcxproj --- examples/Makefile | 1 + examples/Makefile.Web | 1 + examples/README.md | 245 +++++++++--------- examples/core/core_input_virtual_controls.c | 123 +++++++++ examples/core/core_input_virtual_controls.png | Bin 0 -> 9604 bytes 5 files changed, 248 insertions(+), 122 deletions(-) create mode 100644 examples/core/core_input_virtual_controls.c create mode 100644 examples/core/core_input_virtual_controls.png diff --git a/examples/Makefile b/examples/Makefile index c17258427..01c8e45d7 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -492,6 +492,7 @@ CORE = \ core/core_input_mouse \ core/core_input_mouse_wheel \ core/core_input_multitouch \ + core/core_input_virtual_controls \ core/core_loading_thread \ core/core_random_sequence \ core/core_random_values \ diff --git a/examples/Makefile.Web b/examples/Makefile.Web index bd48c2a4a..b176217ae 100644 --- a/examples/Makefile.Web +++ b/examples/Makefile.Web @@ -359,6 +359,7 @@ CORE = \ core/core_input_mouse \ core/core_input_mouse_wheel \ core/core_input_multitouch \ + core/core_input_virtual_controls \ core/core_loading_thread \ core/core_random_sequence \ core/core_random_values \ diff --git a/examples/README.md b/examples/README.md index d573ff23e..ee528d049 100644 --- a/examples/README.md +++ b/examples/README.md @@ -31,31 +31,32 @@ Examples using raylib core platform functionality like window creation, inputs, | 05 | [core_input_gamepad](core/core_input_gamepad.c) | core_input_gamepad | ⭐️☆☆☆ | 1.1 | **4.2** | [Ray](https://github.com/raysan5) | | 06 | [core_input_multitouch](core/core_input_multitouch.c) | core_input_multitouch | ⭐️☆☆☆ | 2.1 | 2.5 | [Berni](https://github.com/Berni8k) | | 07 | [core_input_gestures](core/core_input_gestures.c) | core_input_gestures | ⭐️⭐️☆☆ | 1.4 | **4.2** | [Ray](https://github.com/raysan5) | -| 08 | [core_2d_camera](core/core_2d_camera.c) | core_2d_camera | ⭐️⭐️☆☆ | 1.5 | 3.0 | [Ray](https://github.com/raysan5) | -| 09 | [core_2d_camera_mouse_zoom](core/core_2d_camera_mouse_zoom.c) | core_2d_camera_mouse_zoom | ⭐️⭐️☆☆ | **4.2** | **4.2** | [Jeffery Myers](https://github.com/JeffM2501) | -| 10 | [core_2d_camera_platformer](core/core_2d_camera_platformer.c) | core_2d_camera_platformer | ⭐️⭐️⭐️☆ | 2.5 | 3.0 | [avyy](https://github.com/avyy) | -| 11 | [core_2d_camera_split_screen](core/core_2d_camera_split_screen.c) | core_2d_camera_split_screen | ⭐️⭐️⭐️⭐️ | **4.5** | **4.5** | [Gabriel dos Santos Sanches](https://github.com/gabrielssanches) | -| 12 | [core_3d_camera_mode](core/core_3d_camera_mode.c) | core_3d_camera_mode | ⭐️☆☆☆ | 1.0 | 1.0 | [Ray](https://github.com/raysan5) | -| 13 | [core_3d_camera_free](core/core_3d_camera_free.c) | core_3d_camera_free | ⭐️☆☆☆ | 1.3 | 1.3 | [Ray](https://github.com/raysan5) | -| 14 | [core_3d_camera_first_person](core/core_3d_camera_first_person.c) | core_3d_camera_first_person | ⭐️⭐️☆☆ | 1.3 | 1.3 | [Ray](https://github.com/raysan5) | -| 15 | [core_3d_camera:split_screen](core/core_3d_camera_split_screen.c) | core_3d_camera_split_screen | ⭐️⭐️⭐️⭐️ | 3.7 | **4.0** | [Jeffery Myers](https://github.com/JeffM2501) | -| 16 | [core_3d_picking](core/core_3d_picking.c) | core_3d_picking | ⭐️⭐️☆☆ | 1.3 | **4.0** | [Ray](https://github.com/raysan5) | -| 17 | [core_world_screen](core/core_world_screen.c) | core_world_screen | ⭐️⭐️☆☆ | 1.3 | 1.4 | [Ray](https://github.com/raysan5) | -| 18 | [core_custom_logging](core/core_custom_logging.c) | core_custom_logging | ⭐️⭐️⭐️☆ | 2.5 | 2.5 | [Pablo Marcos Oltra](https://github.com/pamarcos) | -| 19 | [core_window_flags](core/core_window_flags.c) | core_window_flags | ⭐️⭐️⭐️☆ | 3.5 | 3.5 | [Ray](https://github.com/raysan5) | -| 20 | [core_window_letterbox](core/core_window_letterbox.c) | core_window_letterbox | ⭐️⭐️☆☆ | 2.5 | **4.0** | [Anata](https://github.com/anatagawa) | -| 21 | [core_window_should_close](core/core_window_should_close.c) | core_window_should_close | ⭐️☆☆☆ | **4.2** | **4.2** | [Ray](https://github.com/raysan5) | -| 22 | [core_drop_files](core/core_drop_files.c) | core_drop_files | ⭐️⭐️☆☆ | 1.3 | **4.2** | [Ray](https://github.com/raysan5) | -| 23 | [core_random_values](core/core_random_values.c) | core_random_values | ⭐️☆☆☆ | 1.1 | 1.1 | [Ray](https://github.com/raysan5) | -| 24 | [core_storage_values](core/core_storage_values.c) | core_storage_values | ⭐️⭐️☆☆ | 1.4 | **4.2** | [Ray](https://github.com/raysan5) | -| 25 | [core_vr_simulator](core/core_vr_simulator.c) | core_vr_simulator | ⭐️⭐️⭐️☆ | 2.5 | **4.0** | [Ray](https://github.com/raysan5) | -| 26 | [core_loading_thread](core/core_loading_thread.c) | core_loading_thread | ⭐️⭐️⭐️☆ | 2.5 | 3.0 | [Ray](https://github.com/raysan5) | -| 27 | [core_scissor_test](core/core_scissor_test.c) | core_scissor_test | ⭐️☆☆☆ | 2.5 | 3.0 | [Chris Dill](https://github.com/MysteriousSpace) | -| 28 | [core_basic_screen_manager](core/core_basic_screen_manager.c) | core_basic_screen_manager | ⭐️☆☆☆ | **4.0** | **4.0** | [Ray](https://github.com/raysan5) | -| 29 | [core_custom_frame_control](core/core_custom_frame_control.c) | core_custom_frame_control | ⭐️⭐️⭐️⭐️ | **4.0** | **4.0** | [Ray](https://github.com/raysan5) | -| 30 | [core_smooth_pixelperfect](core/core_smooth_pixelperfect.c) | core_smooth_pixelperfect | ⭐️⭐️⭐️☆ | 3.7 | **4.0** | [Giancamillo Alessandroni](https://github.com/NotManyIdeasDev) | -| 31 | [core_window_should_close](core/core_window_should_close.c) | core_window_should_close | ⭐️⭐️☆☆ | **4.2** | **4.2** | [Ray](https://github.com/raysan5) | -| 32 | [core_random_sequence](core/core_random_sequence.c) | core_random_sequence | ⭐️☆☆☆ | **5.0** | **5.0** | [REDl3east](https://github.com/REDl3east) | +| 08 | [core_input_virtual_controls](core/core_input_virtual_controls.c) | core_input_virtual_controls | ⭐️⭐️☆☆ | **5.0** | **5.0** | [oblerion](https://github.com/oblerion) | +| 09 | [core_2d_camera](core/core_2d_camera.c) | core_2d_camera | ⭐️⭐️☆☆ | 1.5 | 3.0 | [Ray](https://github.com/raysan5) | +| 10 | [core_2d_camera_mouse_zoom](core/core_2d_camera_mouse_zoom.c) | core_2d_camera_mouse_zoom | ⭐️⭐️☆☆ | **4.2** | **4.2** | [Jeffery Myers](https://github.com/JeffM2501) | +| 11 | [core_2d_camera_platformer](core/core_2d_camera_platformer.c) | core_2d_camera_platformer | ⭐️⭐️⭐️☆ | 2.5 | 3.0 | [avyy](https://github.com/avyy) | +| 12 | [core_2d_camera_split_screen](core/core_2d_camera_split_screen.c) | core_2d_camera_split_screen | ⭐️⭐️⭐️⭐️ | **4.5** | **4.5** | [Gabriel dos Santos Sanches](https://github.com/gabrielssanches) | +| 13 | [core_3d_camera_mode](core/core_3d_camera_mode.c) | core_3d_camera_mode | ⭐️☆☆☆ | 1.0 | 1.0 | [Ray](https://github.com/raysan5) | +| 14 | [core_3d_camera_free](core/core_3d_camera_free.c) | core_3d_camera_free | ⭐️☆☆☆ | 1.3 | 1.3 | [Ray](https://github.com/raysan5) | +| 15 | [core_3d_camera_first_person](core/core_3d_camera_first_person.c) | core_3d_camera_first_person | ⭐️⭐️☆☆ | 1.3 | 1.3 | [Ray](https://github.com/raysan5) | +| 16 | [core_3d_camera:split_screen](core/core_3d_camera_split_screen.c) | core_3d_camera_split_screen | ⭐️⭐️⭐️⭐️ | 3.7 | **4.0** | [Jeffery Myers](https://github.com/JeffM2501) | +| 17 | [core_3d_picking](core/core_3d_picking.c) | core_3d_picking | ⭐️⭐️☆☆ | 1.3 | **4.0** | [Ray](https://github.com/raysan5) | +| 18 | [core_world_screen](core/core_world_screen.c) | core_world_screen | ⭐️⭐️☆☆ | 1.3 | 1.4 | [Ray](https://github.com/raysan5) | +| 19 | [core_custom_logging](core/core_custom_logging.c) | core_custom_logging | ⭐️⭐️⭐️☆ | 2.5 | 2.5 | [Pablo Marcos Oltra](https://github.com/pamarcos) | +| 20 | [core_window_flags](core/core_window_flags.c) | core_window_flags | ⭐️⭐️⭐️☆ | 3.5 | 3.5 | [Ray](https://github.com/raysan5) | +| 21 | [core_window_letterbox](core/core_window_letterbox.c) | core_window_letterbox | ⭐️⭐️☆☆ | 2.5 | **4.0** | [Anata](https://github.com/anatagawa) | +| 22 | [core_window_should_close](core/core_window_should_close.c) | core_window_should_close | ⭐️☆☆☆ | **4.2** | **4.2** | [Ray](https://github.com/raysan5) | +| 23 | [core_drop_files](core/core_drop_files.c) | core_drop_files | ⭐️⭐️☆☆ | 1.3 | **4.2** | [Ray](https://github.com/raysan5) | +| 24 | [core_random_values](core/core_random_values.c) | core_random_values | ⭐️☆☆☆ | 1.1 | 1.1 | [Ray](https://github.com/raysan5) | +| 25 | [core_storage_values](core/core_storage_values.c) | core_storage_values | ⭐️⭐️☆☆ | 1.4 | **4.2** | [Ray](https://github.com/raysan5) | +| 26 | [core_vr_simulator](core/core_vr_simulator.c) | core_vr_simulator | ⭐️⭐️⭐️☆ | 2.5 | **4.0** | [Ray](https://github.com/raysan5) | +| 27 | [core_loading_thread](core/core_loading_thread.c) | core_loading_thread | ⭐️⭐️⭐️☆ | 2.5 | 3.0 | [Ray](https://github.com/raysan5) | +| 28 | [core_scissor_test](core/core_scissor_test.c) | core_scissor_test | ⭐️☆☆☆ | 2.5 | 3.0 | [Chris Dill](https://github.com/MysteriousSpace) | +| 29 | [core_basic_screen_manager](core/core_basic_screen_manager.c) | core_basic_screen_manager | ⭐️☆☆☆ | **4.0** | **4.0** | [Ray](https://github.com/raysan5) | +| 30 | [core_custom_frame_control](core/core_custom_frame_control.c) | core_custom_frame_control | ⭐️⭐️⭐️⭐️ | **4.0** | **4.0** | [Ray](https://github.com/raysan5) | +| 31 | [core_smooth_pixelperfect](core/core_smooth_pixelperfect.c) | core_smooth_pixelperfect | ⭐️⭐️⭐️☆ | 3.7 | **4.0** | [Giancamillo Alessandroni](https://github.com/NotManyIdeasDev) | +| 32 | [core_window_should_close](core/core_window_should_close.c) | core_window_should_close | ⭐️⭐️☆☆ | **4.2** | **4.2** | [Ray](https://github.com/raysan5) | +| 33 | [core_random_sequence](core/core_random_sequence.c) | core_random_sequence | ⭐️☆☆☆ | **5.0** | **5.0** | [REDl3east](https://github.com/REDl3east) | ### category: shapes @@ -63,22 +64,22 @@ Examples using raylib shapes drawing functionality, provided by raylib [shapes]( | ## | example | image | difficulty
level | version
created | last version
updated | original
developer | |----|----------|--------|:-------------------:|:------------------:|:------------------:|:----------| -| 31 | [shapes_basic_shapes](shapes/shapes_basic_shapes.c) | shapes_basic_shapes | ⭐️☆☆☆ | 1.0 | **4.0** | [Ray](https://github.com/raysan5) | -| 32 | [shapes_bouncing_ball](shapes/shapes_bouncing_ball.c) | shapes_bouncing_ball | ⭐️☆☆☆ | 2.5 | 2.5 | [Ray](https://github.com/raysan5) | -| 33 | [shapes_colors_palette](shapes/shapes_colors_palette.c) | shapes_colors_palette | ⭐️⭐️☆☆ | 1.0 | 2.5 | [Ray](https://github.com/raysan5) | -| 34 | [shapes_logo_raylib](shapes/shapes_logo_raylib.c) | shapes_logo_raylib | ⭐️☆☆☆ | 1.0 | 1.0 | [Ray](https://github.com/raysan5) | -| 35 | [shapes_logo_raylib_anim](shapes/shapes_logo_raylib_anim.c) | shapes_logo_raylib_anim | ⭐️⭐️☆☆ | 2.5 | **4.0** | [Ray](https://github.com/raysan5) | -| 36 | [shapes_rectangle_scaling](shapes/shapes_rectangle_scaling.c) | shapes_rectangle_scaling | ⭐️⭐️☆☆ | 2.5 | 2.5 | [Vlad Adrian](https://github.com/demizdor) | -| 37 | [shapes_lines_bezier](shapes/shapes_lines_bezier.c) | shapes_lines_bezier | ⭐️☆☆☆ | 1.7 | 1.7 | [Ray](https://github.com/raysan5) | -| 38 | [shapes_collision_area](shapes/shapes_collision_area.c) | shapes_collision_area | ⭐️⭐️☆☆ | 2.5 | 2.5 | [Ray](https://github.com/raysan5) | -| 39 | [shapes_following_eyes](shapes/shapes_following_eyes.c) | shapes_following_eyes | ⭐️⭐️☆☆ | 2.5 | 2.5 | [Ray](https://github.com/raysan5) | -| 40 | [shapes_easings_ball_anim](shapes/shapes_easings_ball_anim.c) | shapes_easings_ball_anim | ⭐️⭐️☆☆ | 2.5 | 2.5 | [Ray](https://github.com/raysan5) | -| 41 | [shapes_easings_box_anim](shapes/shapes_easings_box_anim.c) | shapes_easings_box_anim | ⭐️⭐️☆☆ | 2.5 | 2.5 | [Ray](https://github.com/raysan5) | -| 42 | [shapes_easings_rectangle_array](shapes/shapes_easings_rectangle_array.c) | shapes_easings_rectangle_array | ⭐️⭐️⭐️☆ | 2.5 | 2.5 | [Ray](https://github.com/raysan5) | -| 43 | [shapes_draw_ring](shapes/shapes_draw_ring.c) | shapes_draw_ring | ⭐️⭐️⭐️☆ | 2.5 | 2.5 | [Vlad Adrian](https://github.com/demizdor) | -| 44 | [shapes_draw_circle_sector](shapes/shapes_draw_circle_sector.c) | shapes_draw_circle_sector | ⭐️⭐️⭐️☆ | 2.5 | 2.5 | [Vlad Adrian](https://github.com/demizdor) | -| 45 | [shapes_draw_rectangle_rounded](shapes/shapes_draw_rectangle_rounded.c) | shapes_draw_rectangle_rounded | ⭐️⭐️⭐️☆ | 2.5 | 2.5 | [Vlad Adrian](https://github.com/demizdor) | -| 46 | [shapes_top_down_lights](shapes/shapes_top_down_lights.c) | shapes_top_down_lights | ⭐️⭐️⭐️⭐️ | **4.2** | **4.2** | [Jeffery Myers](https://github.com/JeffM2501) | +| 34 | [shapes_basic_shapes](shapes/shapes_basic_shapes.c) | shapes_basic_shapes | ⭐️☆☆☆ | 1.0 | **4.0** | [Ray](https://github.com/raysan5) | +| 35 | [shapes_bouncing_ball](shapes/shapes_bouncing_ball.c) | shapes_bouncing_ball | ⭐️☆☆☆ | 2.5 | 2.5 | [Ray](https://github.com/raysan5) | +| 36 | [shapes_colors_palette](shapes/shapes_colors_palette.c) | shapes_colors_palette | ⭐️⭐️☆☆ | 1.0 | 2.5 | [Ray](https://github.com/raysan5) | +| 37 | [shapes_logo_raylib](shapes/shapes_logo_raylib.c) | shapes_logo_raylib | ⭐️☆☆☆ | 1.0 | 1.0 | [Ray](https://github.com/raysan5) | +| 38 | [shapes_logo_raylib_anim](shapes/shapes_logo_raylib_anim.c) | shapes_logo_raylib_anim | ⭐️⭐️☆☆ | 2.5 | **4.0** | [Ray](https://github.com/raysan5) | +| 39 | [shapes_rectangle_scaling](shapes/shapes_rectangle_scaling.c) | shapes_rectangle_scaling | ⭐️⭐️☆☆ | 2.5 | 2.5 | [Vlad Adrian](https://github.com/demizdor) | +| 40 | [shapes_lines_bezier](shapes/shapes_lines_bezier.c) | shapes_lines_bezier | ⭐️☆☆☆ | 1.7 | 1.7 | [Ray](https://github.com/raysan5) | +| 41 | [shapes_collision_area](shapes/shapes_collision_area.c) | shapes_collision_area | ⭐️⭐️☆☆ | 2.5 | 2.5 | [Ray](https://github.com/raysan5) | +| 42 | [shapes_following_eyes](shapes/shapes_following_eyes.c) | shapes_following_eyes | ⭐️⭐️☆☆ | 2.5 | 2.5 | [Ray](https://github.com/raysan5) | +| 43 | [shapes_easings_ball_anim](shapes/shapes_easings_ball_anim.c) | shapes_easings_ball_anim | ⭐️⭐️☆☆ | 2.5 | 2.5 | [Ray](https://github.com/raysan5) | +| 44 | [shapes_easings_box_anim](shapes/shapes_easings_box_anim.c) | shapes_easings_box_anim | ⭐️⭐️☆☆ | 2.5 | 2.5 | [Ray](https://github.com/raysan5) | +| 45 | [shapes_easings_rectangle_array](shapes/shapes_easings_rectangle_array.c) | shapes_easings_rectangle_array | ⭐️⭐️⭐️☆ | 2.5 | 2.5 | [Ray](https://github.com/raysan5) | +| 46 | [shapes_draw_ring](shapes/shapes_draw_ring.c) | shapes_draw_ring | ⭐️⭐️⭐️☆ | 2.5 | 2.5 | [Vlad Adrian](https://github.com/demizdor) | +| 47 | [shapes_draw_circle_sector](shapes/shapes_draw_circle_sector.c) | shapes_draw_circle_sector | ⭐️⭐️⭐️☆ | 2.5 | 2.5 | [Vlad Adrian](https://github.com/demizdor) | +| 48 | [shapes_draw_rectangle_rounded](shapes/shapes_draw_rectangle_rounded.c) | shapes_draw_rectangle_rounded | ⭐️⭐️⭐️☆ | 2.5 | 2.5 | [Vlad Adrian](https://github.com/demizdor) | +| 49 | [shapes_top_down_lights](shapes/shapes_top_down_lights.c) | shapes_top_down_lights | ⭐️⭐️⭐️⭐️ | **4.2** | **4.2** | [Jeffery Myers](https://github.com/JeffM2501) | ### category: textures @@ -86,28 +87,28 @@ Examples using raylib textures functionality, including image/textures loading/g | ## | example | image | difficulty
level | version
created | last version
updated | original
developer | |----|----------|--------|:-------------------:|:------------------:|:------------------:|:----------| -| 47 | [textures_logo_raylib](textures/textures_logo_raylib.c) | textures_logo_raylib | ⭐️☆☆☆ | 1.0 | 1.0 | [Ray](https://github.com/raysan5) | -| 48 | [textures_srcrec_dstrec](textures/textures_srcrec_dstrec.c) | textures_srcrec_dstrec | ⭐️⭐️⭐️☆ | 1.3 | 1.3 | [Ray](https://github.com/raysan5) | -| 49 | [textures_image_drawing](textures/textures_image_drawing.c) | textures_image_drawing | ⭐️⭐️☆☆ | 1.4 | 1.4 | [Ray](https://github.com/raysan5) | -| 50 | [textures_image_generation](textures/textures_image_generation.c) | textures_image_generation | ⭐️⭐️☆☆ | 1.8 | 1.8 | [Ray](https://github.com/raysan5) | -| 51 | [textures_image_loading](textures/textures_image_loading.c) | textures_image_loading | ⭐️☆☆☆ | 1.3 | 1.3 | [Ray](https://github.com/raysan5) | -| 52 | [textures_image_processing](textures/textures_image_processing.c) | textures_image_processing | ⭐️⭐️⭐️☆ | 1.4 | 3.5 | [Ray](https://github.com/raysan5) | -| 53 | [textures_image_text](textures/textures_image_text.c) | textures_image_text | ⭐️⭐️☆☆ | 1.8 | **4.0** | [Ray](https://github.com/raysan5) | -| 54 | [textures_to_image](textures/textures_to_image.c) | textures_to_image | ⭐️☆☆☆ | 1.3 | **4.0** | [Ray](https://github.com/raysan5) | -| 55 | [textures_raw_data](textures/textures_raw_data.c) | textures_raw_data | ⭐️⭐️⭐️☆ | 1.3 | 3.5 | [Ray](https://github.com/raysan5) | -| 56 | [textures_particles_blending](textures/textures_particles_blending.c) | textures_particles_blending | ⭐️☆☆☆ | 1.7 | 3.5 | [Ray](https://github.com/raysan5) | -| 57 | [textures_npatch_drawing](textures/textures_npatch_drawing.c) | textures_npatch_drawing | ⭐️⭐️⭐️☆ | 2.0 | 2.5 | [Jorge A. Gomes](https://github.com/overdev) | -| 58 | [textures_background_scrolling](textures/textures_background_scrolling.c) | textures_background_scrolling | ⭐️☆☆☆ | 2.0 | 2.5 | [Ray](https://github.com/raysan5) | -| 59 | [textures_sprite_anim](textures/textures_sprite_anim.c) | textures_sprite_anim | ⭐️⭐️☆☆ | 1.3 | 1.3 | [Ray](https://github.com/raysan5) | -| 60 | [textures_sprite_button](textures/textures_sprite_button.c) | textures_sprite_button | ⭐️⭐️☆☆ | 2.5 | 2.5 | [Ray](https://github.com/raysan5) | -| 61 | [textures_sprite_explosion](textures/textures_sprite_explosion.c) | textures_sprite_explosion | ⭐️⭐️☆☆ | 2.5 | 3.5 | [Ray](https://github.com/raysan5) | -| 62 | [textures_bunnymark](textures/textures_bunnymark.c) | textures_bunnymark | ⭐️⭐️⭐️☆ | 1.6 | 2.5 | [Ray](https://github.com/raysan5) | -| 63 | [textures_mouse_painting](textures/textures_mouse_painting.c) | textures_mouse_painting | ⭐️⭐️⭐️☆ | 3.0 | 3.0 | [Chris Dill](https://github.com/MysteriousSpace) | -| 64 | [textures_blend_modes](textures/textures_blend_modes.c) | textures_blend_modes | ⭐️☆☆☆ | 3.5 | 3.5 | [Karlo Licudine](https://github.com/accidentalrebel) | -| 65 | [textures_draw_tiled](textures/textures_draw_tiled.c) | textures_draw_tiled | ⭐️⭐️⭐️☆ | 3.0 | **4.2** | [Vlad Adrian](https://github.com/demizdor) | -| 66 | [textures_polygon](textures/textures_polygon.c) | textures_polygon | ⭐️☆☆☆ | 3.7 | 3.7 | [Chris Camacho](https://github.com/codifies) | -| 67 | [textures_fog_of_war](textures/textures_fog_of_war.c) | textures_fog_of_war | ⭐️⭐️⭐️☆ | **4.2** | **4.2** | [Ray](https://github.com/raysan5) | -| 68 | [textures_gif_player](textures/textures_gif_player.c) | textures_gif_player | ⭐️⭐️⭐️☆ | **4.2** | **4.2** | [Ray](https://github.com/raysan5) | +| 50 | [textures_logo_raylib](textures/textures_logo_raylib.c) | textures_logo_raylib | ⭐️☆☆☆ | 1.0 | 1.0 | [Ray](https://github.com/raysan5) | +| 51 | [textures_srcrec_dstrec](textures/textures_srcrec_dstrec.c) | textures_srcrec_dstrec | ⭐️⭐️⭐️☆ | 1.3 | 1.3 | [Ray](https://github.com/raysan5) | +| 52 | [textures_image_drawing](textures/textures_image_drawing.c) | textures_image_drawing | ⭐️⭐️☆☆ | 1.4 | 1.4 | [Ray](https://github.com/raysan5) | +| 53 | [textures_image_generation](textures/textures_image_generation.c) | textures_image_generation | ⭐️⭐️☆☆ | 1.8 | 1.8 | [Ray](https://github.com/raysan5) | +| 54 | [textures_image_loading](textures/textures_image_loading.c) | textures_image_loading | ⭐️☆☆☆ | 1.3 | 1.3 | [Ray](https://github.com/raysan5) | +| 55 | [textures_image_processing](textures/textures_image_processing.c) | textures_image_processing | ⭐️⭐️⭐️☆ | 1.4 | 3.5 | [Ray](https://github.com/raysan5) | +| 56 | [textures_image_text](textures/textures_image_text.c) | textures_image_text | ⭐️⭐️☆☆ | 1.8 | **4.0** | [Ray](https://github.com/raysan5) | +| 57 | [textures_to_image](textures/textures_to_image.c) | textures_to_image | ⭐️☆☆☆ | 1.3 | **4.0** | [Ray](https://github.com/raysan5) | +| 58 | [textures_raw_data](textures/textures_raw_data.c) | textures_raw_data | ⭐️⭐️⭐️☆ | 1.3 | 3.5 | [Ray](https://github.com/raysan5) | +| 59 | [textures_particles_blending](textures/textures_particles_blending.c) | textures_particles_blending | ⭐️☆☆☆ | 1.7 | 3.5 | [Ray](https://github.com/raysan5) | +| 60 | [textures_npatch_drawing](textures/textures_npatch_drawing.c) | textures_npatch_drawing | ⭐️⭐️⭐️☆ | 2.0 | 2.5 | [Jorge A. Gomes](https://github.com/overdev) | +| 61 | [textures_background_scrolling](textures/textures_background_scrolling.c) | textures_background_scrolling | ⭐️☆☆☆ | 2.0 | 2.5 | [Ray](https://github.com/raysan5) | +| 62 | [textures_sprite_anim](textures/textures_sprite_anim.c) | textures_sprite_anim | ⭐️⭐️☆☆ | 1.3 | 1.3 | [Ray](https://github.com/raysan5) | +| 63 | [textures_sprite_button](textures/textures_sprite_button.c) | textures_sprite_button | ⭐️⭐️☆☆ | 2.5 | 2.5 | [Ray](https://github.com/raysan5) | +| 64 | [textures_sprite_explosion](textures/textures_sprite_explosion.c) | textures_sprite_explosion | ⭐️⭐️☆☆ | 2.5 | 3.5 | [Ray](https://github.com/raysan5) | +| 65 | [textures_bunnymark](textures/textures_bunnymark.c) | textures_bunnymark | ⭐️⭐️⭐️☆ | 1.6 | 2.5 | [Ray](https://github.com/raysan5) | +| 66 | [textures_mouse_painting](textures/textures_mouse_painting.c) | textures_mouse_painting | ⭐️⭐️⭐️☆ | 3.0 | 3.0 | [Chris Dill](https://github.com/MysteriousSpace) | +| 67 | [textures_blend_modes](textures/textures_blend_modes.c) | textures_blend_modes | ⭐️☆☆☆ | 3.5 | 3.5 | [Karlo Licudine](https://github.com/accidentalrebel) | +| 68 | [textures_draw_tiled](textures/textures_draw_tiled.c) | textures_draw_tiled | ⭐️⭐️⭐️☆ | 3.0 | **4.2** | [Vlad Adrian](https://github.com/demizdor) | +| 69 | [textures_polygon](textures/textures_polygon.c) | textures_polygon | ⭐️☆☆☆ | 3.7 | 3.7 | [Chris Camacho](https://github.com/codifies) | +| 70 | [textures_fog_of_war](textures/textures_fog_of_war.c) | textures_fog_of_war | ⭐️⭐️⭐️☆ | **4.2** | **4.2** | [Ray](https://github.com/raysan5) | +| 71 | [textures_gif_player](textures/textures_gif_player.c) | textures_gif_player | ⭐️⭐️⭐️☆ | **4.2** | **4.2** | [Ray](https://github.com/raysan5) | ### category: text @@ -115,18 +116,18 @@ Examples using raylib text functionality, including sprite fonts loading/generat | ## | example | image | difficulty
level | version
created | last version
updated | original
developer | |----|----------|--------|:-------------------:|:------------------:|:------------------:|:----------| -| 69 | [text_raylib_fonts](text/text_raylib_fonts.c) | text_raylib_fonts | ⭐️☆☆☆ | 1.7 | 3.7 | [Ray](https://github.com/raysan5) | -| 70 | [text_font_spritefont](text/text_font_spritefont.c) | text_font_spritefont | ⭐️☆☆☆ | 1.0 | 1.0 | [Ray](https://github.com/raysan5) | -| 71 | [text_font_filters](text/text_font_filters.c) | text_font_filters | ⭐️⭐️☆☆ | 1.3 | **4.2** | [Ray](https://github.com/raysan5) | -| 72 | [text_font_loading](text/text_font_loading.c) | text_font_loading | ⭐️☆☆☆ | 1.4 | 3.0 | [Ray](https://github.com/raysan5) | -| 73 | [text_font_sdf](text/text_font_sdf.c) | text_font_sdf | ⭐️⭐️⭐️☆ | 1.3 | **4.0** | [Ray](https://github.com/raysan5) | -| 74 | [text_format_text](text/text_format_text.c) | text_format_text | ⭐️☆☆☆ | 1.1 | 3.0 | [Ray](https://github.com/raysan5) | -| 75 | [text_input_box](text/text_input_box.c) | text_input_box | ⭐️⭐️☆☆ | 1.7 | 3.5 | [Ray](https://github.com/raysan5) | -| 76 | [text_writing_anim](text/text_writing_anim.c) | text_writing_anim | ⭐️⭐️☆☆ | 1.4 | 1.4 | [Ray](https://github.com/raysan5) | -| 77 | [text_rectangle_bounds](text/text_rectangle_bounds.c) | text_rectangle_bounds | ⭐️⭐️⭐️⭐️ | 2.5 | **4.0** | [Vlad Adrian](https://github.com/demizdor) | -| 78 | [text_unicode](text/text_unicode.c) | text_unicode | ⭐️⭐️⭐️⭐️ | 2.5 | **4.0** | [Vlad Adrian](https://github.com/demizdor) | -| 79 | [text_draw_3d](text/text_draw_3d.c) | text_draw_3d | ⭐️⭐️⭐️⭐️ | 3.5 | **4.0** | [Vlad Adrian](https://github.com/demizdor) | -| 80 | [text_codepoints_loading](text/text_codepoints_loading.c) | text_codepoints_loading | ⭐️⭐️⭐️☆ | **4.2** | **4.2** | [Ray](https://github.com/raysan5) | +| 72 | [text_raylib_fonts](text/text_raylib_fonts.c) | text_raylib_fonts | ⭐️☆☆☆ | 1.7 | 3.7 | [Ray](https://github.com/raysan5) | +| 73 | [text_font_spritefont](text/text_font_spritefont.c) | text_font_spritefont | ⭐️☆☆☆ | 1.0 | 1.0 | [Ray](https://github.com/raysan5) | +| 74 | [text_font_filters](text/text_font_filters.c) | text_font_filters | ⭐️⭐️☆☆ | 1.3 | **4.2** | [Ray](https://github.com/raysan5) | +| 75 | [text_font_loading](text/text_font_loading.c) | text_font_loading | ⭐️☆☆☆ | 1.4 | 3.0 | [Ray](https://github.com/raysan5) | +| 76 | [text_font_sdf](text/text_font_sdf.c) | text_font_sdf | ⭐️⭐️⭐️☆ | 1.3 | **4.0** | [Ray](https://github.com/raysan5) | +| 77 | [text_format_text](text/text_format_text.c) | text_format_text | ⭐️☆☆☆ | 1.1 | 3.0 | [Ray](https://github.com/raysan5) | +| 78 | [text_input_box](text/text_input_box.c) | text_input_box | ⭐️⭐️☆☆ | 1.7 | 3.5 | [Ray](https://github.com/raysan5) | +| 79 | [text_writing_anim](text/text_writing_anim.c) | text_writing_anim | ⭐️⭐️☆☆ | 1.4 | 1.4 | [Ray](https://github.com/raysan5) | +| 80 | [text_rectangle_bounds](text/text_rectangle_bounds.c) | text_rectangle_bounds | ⭐️⭐️⭐️⭐️ | 2.5 | **4.0** | [Vlad Adrian](https://github.com/demizdor) | +| 81 | [text_unicode](text/text_unicode.c) | text_unicode | ⭐️⭐️⭐️⭐️ | 2.5 | **4.0** | [Vlad Adrian](https://github.com/demizdor) | +| 82 | [text_draw_3d](text/text_draw_3d.c) | text_draw_3d | ⭐️⭐️⭐️⭐️ | 3.5 | **4.0** | [Vlad Adrian](https://github.com/demizdor) | +| 83 | [text_codepoints_loading](text/text_codepoints_loading.c) | text_codepoints_loading | ⭐️⭐️⭐️☆ | **4.2** | **4.2** | [Ray](https://github.com/raysan5) | ### category: models @@ -134,25 +135,25 @@ Examples using raylib models functionality, including models loading/generation | ## | example | image | difficulty
level | version
created | last version
updated | original
developer | |----|----------|--------|:-------------------:|:------------------:|:------------------:|:----------| -| 81 | [models_animation](models/models_animation.c) | models_animation | ⭐️⭐️☆☆ | 2.5 | 3.5 | [culacant](https://github.com/culacant) | -| 82 | [models_billboard](models/models_billboard.c) | models_billboard | ⭐️⭐️⭐️☆ | 1.3 | 3.5 | [Ray](https://github.com/raysan5) | -| 83 | [models_box_collisions](models/models_box_collisions.c) | models_box_collisions | ⭐️☆☆☆ | 1.3 | 3.5 | [Ray](https://github.com/raysan5) | -| 84 | [models_cubicmap](models/models_cubicmap.c) | models_cubicmap | ⭐️⭐️☆☆ | 1.8 | 3.5 | [Ray](https://github.com/raysan5) | -| 85 | [models_first_person_maze](models/models_first_person_maze.c) | models_first_person_maze | ⭐️⭐️☆☆ | 2.5 | 3.5 | [Ray](https://github.com/raysan5) | -| 86 | [models_geometric_shapes](models/models_geometric_shapes.c) | models_geometric_shapes | ⭐️☆☆☆ | 1.0 | 3.5 | [Ray](https://github.com/raysan5) | -| 87 | [models_mesh_generation](models/models_mesh_generation.c) | models_mesh_generation | ⭐️⭐️☆☆ | 1.8 | **4.0** | [Ray](https://github.com/raysan5) | -| 88 | [models_mesh_picking](models/models_mesh_picking.c) | models_mesh_picking | ⭐️⭐️⭐️☆ | 1.7 | **4.0** | [Joel Davis](https://github.com/joeld42) | -| 89 | [models_loading](models/models_loading.c) | models_loading | ⭐️☆☆☆ | 2.5 | **4.0** | [Ray](https://github.com/raysan5) | -| 90 | [models_loading_gltf](models/models_loading_gltf.c) | models_loading_gltf | ⭐️☆☆☆ | 3.7 | **4.2** | [Ray](https://github.com/raysan5) | -| 91 | [models_loading_vox](models/models_loading_vox.c) | models_loading_vox | ⭐️☆☆☆ | **4.0** | **4.0** | [Johann Nadalutti](https://github.com/procfxgen) | -| 92 | [models_loading_m3d](models/models_loading_m3d.c) | models_loading_m3d | ⭐️☆☆☆ | **4.2** | **4.2** | [bzt](https://bztsrc.gitlab.io/model3d) | -| 93 | [models_orthographic_projection](models/models_orthographic_projection.c) | models_orthographic_projection | ⭐️☆☆☆ | 2.0 | 3.7 | [Max Danielsson](https://github.com/autious) | -| 94 | [models_point_rendering](models/models_point_rendering.c) | models_point_rendering | ⭐️⭐️☆☆ | 5.0 | 5.0 | [Reese Gallagher](https://github.com/satchelfrost) | -| 95 | [models_rlgl_solar_system](models/models_rlgl_solar_system.c) | models_rlgl_solar_system | ⭐️⭐️⭐️⭐️ | 2.5 | **4.0** | [Ray](https://github.com/raysan5) | -| 96 | [models_yaw_pitch_roll](models/models_yaw_pitch_roll.c) | models_yaw_pitch_roll | ⭐️⭐️☆☆ | 1.8 | **4.0** | [Berni](https://github.com/Berni8k) | -| 97 | [models_waving_cubes](models/models_waving_cubes.c) | models_waving_cubes | ⭐️⭐️⭐️☆ | 2.5 | 3.7 | [codecat](https://github.com/codecat) | -| 98 | [models_heightmap](models/models_heightmap.c) | models_heightmap | ⭐️☆☆☆ | 1.8 | 3.5 | [Ray](https://github.com/raysan5) | -| 99 | [models_skybox](models/models_skybox.c) | models_skybox | ⭐️⭐️☆☆ | 1.8 | **4.0** | [Ray](https://github.com/raysan5) | +| 84 | [models_animation](models/models_animation.c) | models_animation | ⭐️⭐️☆☆ | 2.5 | 3.5 | [culacant](https://github.com/culacant) | +| 85 | [models_billboard](models/models_billboard.c) | models_billboard | ⭐️⭐️⭐️☆ | 1.3 | 3.5 | [Ray](https://github.com/raysan5) | +| 86 | [models_box_collisions](models/models_box_collisions.c) | models_box_collisions | ⭐️☆☆☆ | 1.3 | 3.5 | [Ray](https://github.com/raysan5) | +| 87 | [models_cubicmap](models/models_cubicmap.c) | models_cubicmap | ⭐️⭐️☆☆ | 1.8 | 3.5 | [Ray](https://github.com/raysan5) | +| 88 | [models_first_person_maze](models/models_first_person_maze.c) | models_first_person_maze | ⭐️⭐️☆☆ | 2.5 | 3.5 | [Ray](https://github.com/raysan5) | +| 89 | [models_geometric_shapes](models/models_geometric_shapes.c) | models_geometric_shapes | ⭐️☆☆☆ | 1.0 | 3.5 | [Ray](https://github.com/raysan5) | +| 90 | [models_mesh_generation](models/models_mesh_generation.c) | models_mesh_generation | ⭐️⭐️☆☆ | 1.8 | **4.0** | [Ray](https://github.com/raysan5) | +| 91 | [models_mesh_picking](models/models_mesh_picking.c) | models_mesh_picking | ⭐️⭐️⭐️☆ | 1.7 | **4.0** | [Joel Davis](https://github.com/joeld42) | +| 92 | [models_loading](models/models_loading.c) | models_loading | ⭐️☆☆☆ | 2.5 | **4.0** | [Ray](https://github.com/raysan5) | +| 93 | [models_loading_gltf](models/models_loading_gltf.c) | models_loading_gltf | ⭐️☆☆☆ | 3.7 | **4.2** | [Ray](https://github.com/raysan5) | +| 94 | [models_loading_vox](models/models_loading_vox.c) | models_loading_vox | ⭐️☆☆☆ | **4.0** | **4.0** | [Johann Nadalutti](https://github.com/procfxgen) | +| 95 | [models_loading_m3d](models/models_loading_m3d.c) | models_loading_m3d | ⭐️☆☆☆ | **4.2** | **4.2** | [bzt](https://bztsrc.gitlab.io/model3d) | +| 96 | [models_orthographic_projection](models/models_orthographic_projection.c) | models_orthographic_projection | ⭐️☆☆☆ | 2.0 | 3.7 | [Max Danielsson](https://github.com/autious) | +| 97 | [models_point_rendering](models/models_point_rendering.c) | models_point_rendering | ⭐️⭐️☆☆ | 5.0 | 5.0 | [Reese Gallagher](https://github.com/satchelfrost) | +| 98 | [models_rlgl_solar_system](models/models_rlgl_solar_system.c) | models_rlgl_solar_system | ⭐️⭐️⭐️⭐️ | 2.5 | **4.0** | [Ray](https://github.com/raysan5) | +| 99 | [models_yaw_pitch_roll](models/models_yaw_pitch_roll.c) | models_yaw_pitch_roll | ⭐️⭐️☆☆ | 1.8 | **4.0** | [Berni](https://github.com/Berni8k) | +| 100 | [models_waving_cubes](models/models_waving_cubes.c) | models_waving_cubes | ⭐️⭐️⭐️☆ | 2.5 | 3.7 | [codecat](https://github.com/codecat) | +| 101 | [models_heightmap](models/models_heightmap.c) | models_heightmap | ⭐️☆☆☆ | 1.8 | 3.5 | [Ray](https://github.com/raysan5) | +| 102 | [models_skybox](models/models_skybox.c) | models_skybox | ⭐️⭐️☆☆ | 1.8 | **4.0** | [Ray](https://github.com/raysan5) | ### category: shaders @@ -160,25 +161,25 @@ Examples using raylib shaders functionality, including shaders loading, paramete | ## | example | image | difficulty
level | version
created | last version
updated | original
developer | |----|----------|--------|:-------------------:|:------------------:|:------------------:|:----------| -| 100 | [shaders_basic_lighting](shaders/shaders_basic_lighting.c) | shaders_basic_lighting | ⭐️⭐️⭐️⭐️ | 3.0 | **4.2** | [Chris Camacho](https://github.com/codifies) | -| 101 | [shaders_model_shader](shaders/shaders_model_shader.c) | shaders_model_shader | ⭐️⭐️☆☆ | 1.3 | 3.7 | [Ray](https://github.com/raysan5) | -| 102 | [shaders_shapes_textures](shaders/shaders_shapes_textures.c) | shaders_shapes_textures | ⭐️⭐️☆☆ | 1.7 | 3.7 | [Ray](https://github.com/raysan5) | -| 103 | [shaders_custom_uniform](shaders/shaders_custom_uniform.c) | shaders_custom_uniform | ⭐️⭐️☆☆ | 1.3 | **4.0** | [Ray](https://github.com/raysan5) | -| 104 | [shaders_postprocessing](shaders/shaders_postprocessing.c) | shaders_postprocessing | ⭐️⭐️⭐️☆ | 1.3 | **4.0** | [Ray](https://github.com/raysan5) | -| 105 | [shaders_palette_switch](shaders/shaders_palette_switch.c) | shaders_palette_switch | ⭐️⭐️⭐️☆ | 2.5 | 3.7 | [Marco Lizza](https://github.com/MarcoLizza) | -| 106 | [shaders_raymarching](shaders/shaders_raymarching.c) | shaders_raymarching | ⭐️⭐️⭐️⭐️ | 2.0 | **4.2** | [Ray](https://github.com/raysan5) | -| 107 | [shaders_texture_drawing](shaders/shaders_texture_drawing.c) | shaders_texture_drawing | ⭐️⭐️☆☆ | 2.0 | 3.7 | [Michał Ciesielski](https://github.com/) | -| 108 | [shaders_texture_outline](shaders/shaders_texture_outline.c) | shaders_texture_outline | ⭐️⭐️⭐️☆ | **4.0** | **4.0** | [Samuel Skiff](https://github.com/GoldenThumbs) | -| 109 | [shaders_texture_waves](shaders/shaders_texture_waves.c) | shaders_texture_waves | ⭐️⭐️☆☆ | 2.5 | 3.7 | [Anata](https://github.com/anatagawa) | -| 110 | [shaders_julia_set](shaders/shaders_julia_set.c) | shaders_julia_set | ⭐️⭐️⭐️☆ | 2.5 | **4.0** | [eggmund](https://github.com/eggmund) | -| 111 | [shaders_eratosthenes](shaders/shaders_eratosthenes.c) | shaders_eratosthenes | ⭐️⭐️⭐️☆ | 2.5 | **4.0** | [ProfJski](https://github.com/ProfJski) | -| 112 | [shaders_fog](shaders/shaders_fog.c) | shaders_fog | ⭐️⭐️⭐️☆ | 2.5 | 3.7 | [Chris Camacho](https://github.com/codifies) | -| 113 | [shaders_simple_mask](shaders/shaders_simple_mask.c) | shaders_simple_mask | ⭐️⭐️☆☆ | 2.5 | 3.7 | [Chris Camacho](https://github.com/codifies) | -| 114 | [shaders_hot_reloading](shaders/shaders_hot_reloading.c) | shaders_hot_reloading | ⭐️⭐️⭐️☆ | 3.0 | 3.5 | [Ray](https://github.com/raysan5) | -| 115 | [shaders_mesh_instancing](shaders/shaders_mesh_instancing.c) | shaders_mesh_instancing | ⭐️⭐️⭐️⭐️ | 3.7 | **4.2** | [seanpringle](https://github.com/seanpringle) | -| 116 | [shaders_multi_sample2d](shaders/shaders_multi_sample2d.c) | shaders_multi_sample2d | ⭐️⭐️☆☆ | 3.5 | 3.5 | [Ray](https://github.com/raysan5) | -| 117 | [shaders_spotlight](shaders/shaders_spotlight.c) | shaders_spotlight | ⭐️⭐️☆☆ | 2.5 | 3.7 | [Chris Camacho](https://github.com/codifies) | -| 118 | [shaders_deferred_render](shaders/shaders_deferred_render.c) | shaders_deferred_render | ⭐️⭐️⭐️⭐️ | 4.5 | 4.5 | [Justin Andreas Lacoste](https://github.com/27justin) | +| 103 | [shaders_basic_lighting](shaders/shaders_basic_lighting.c) | shaders_basic_lighting | ⭐️⭐️⭐️⭐️ | 3.0 | **4.2** | [Chris Camacho](https://github.com/codifies) | +| 104 | [shaders_model_shader](shaders/shaders_model_shader.c) | shaders_model_shader | ⭐️⭐️☆☆ | 1.3 | 3.7 | [Ray](https://github.com/raysan5) | +| 105 | [shaders_shapes_textures](shaders/shaders_shapes_textures.c) | shaders_shapes_textures | ⭐️⭐️☆☆ | 1.7 | 3.7 | [Ray](https://github.com/raysan5) | +| 106 | [shaders_custom_uniform](shaders/shaders_custom_uniform.c) | shaders_custom_uniform | ⭐️⭐️☆☆ | 1.3 | **4.0** | [Ray](https://github.com/raysan5) | +| 107 | [shaders_postprocessing](shaders/shaders_postprocessing.c) | shaders_postprocessing | ⭐️⭐️⭐️☆ | 1.3 | **4.0** | [Ray](https://github.com/raysan5) | +| 108 | [shaders_palette_switch](shaders/shaders_palette_switch.c) | shaders_palette_switch | ⭐️⭐️⭐️☆ | 2.5 | 3.7 | [Marco Lizza](https://github.com/MarcoLizza) | +| 109 | [shaders_raymarching](shaders/shaders_raymarching.c) | shaders_raymarching | ⭐️⭐️⭐️⭐️ | 2.0 | **4.2** | [Ray](https://github.com/raysan5) | +| 110 | [shaders_texture_drawing](shaders/shaders_texture_drawing.c) | shaders_texture_drawing | ⭐️⭐️☆☆ | 2.0 | 3.7 | [Michał Ciesielski](https://github.com/) | +| 111 | [shaders_texture_outline](shaders/shaders_texture_outline.c) | shaders_texture_outline | ⭐️⭐️⭐️☆ | **4.0** | **4.0** | [Samuel Skiff](https://github.com/GoldenThumbs) | +| 112 | [shaders_texture_waves](shaders/shaders_texture_waves.c) | shaders_texture_waves | ⭐️⭐️☆☆ | 2.5 | 3.7 | [Anata](https://github.com/anatagawa) | +| 113 | [shaders_julia_set](shaders/shaders_julia_set.c) | shaders_julia_set | ⭐️⭐️⭐️☆ | 2.5 | **4.0** | [eggmund](https://github.com/eggmund) | +| 114 | [shaders_eratosthenes](shaders/shaders_eratosthenes.c) | shaders_eratosthenes | ⭐️⭐️⭐️☆ | 2.5 | **4.0** | [ProfJski](https://github.com/ProfJski) | +| 115 | [shaders_fog](shaders/shaders_fog.c) | shaders_fog | ⭐️⭐️⭐️☆ | 2.5 | 3.7 | [Chris Camacho](https://github.com/codifies) | +| 116 | [shaders_simple_mask](shaders/shaders_simple_mask.c) | shaders_simple_mask | ⭐️⭐️☆☆ | 2.5 | 3.7 | [Chris Camacho](https://github.com/codifies) | +| 117 | [shaders_hot_reloading](shaders/shaders_hot_reloading.c) | shaders_hot_reloading | ⭐️⭐️⭐️☆ | 3.0 | 3.5 | [Ray](https://github.com/raysan5) | +| 118 | [shaders_mesh_instancing](shaders/shaders_mesh_instancing.c) | shaders_mesh_instancing | ⭐️⭐️⭐️⭐️ | 3.7 | **4.2** | [seanpringle](https://github.com/seanpringle) | +| 119 | [shaders_multi_sample2d](shaders/shaders_multi_sample2d.c) | shaders_multi_sample2d | ⭐️⭐️☆☆ | 3.5 | 3.5 | [Ray](https://github.com/raysan5) | +| 120 | [shaders_spotlight](shaders/shaders_spotlight.c) | shaders_spotlight | ⭐️⭐️☆☆ | 2.5 | 3.7 | [Chris Camacho](https://github.com/codifies) | +| 121 | [shaders_deferred_render](shaders/shaders_deferred_render.c) | shaders_deferred_render | ⭐️⭐️⭐️⭐️ | 4.5 | 4.5 | [Justin Andreas Lacoste](https://github.com/27justin) | ### category: audio @@ -186,10 +187,10 @@ Examples using raylib audio functionality, including sound/music loading and pla | ## | example | image | difficulty
level | version
created | last version
updated | original
developer | |----|----------|--------|:-------------------:|:------------------:|:------------------:|:----------| -| 119 | [audio_module_playing](audio/audio_module_playing.c) | audio_module_playing | ⭐️☆☆☆ | 1.5 | 3.5 | [Ray](https://github.com/raysan5) | -| 120 | [audio_music_stream](audio/audio_music_stream.c) | audio_music_stream | ⭐️☆☆☆ | 1.3 | **4.2** | [Ray](https://github.com/raysan5) | -| 121 | [audio_raw_stream](audio/audio_raw_stream.c) | audio_raw_stream | ⭐️⭐️⭐️☆ | 1.6 | **4.2** | [Ray](https://github.com/raysan5) | -| 122 | [audio_sound_loading](audio/audio_sound_loading.c) | audio_sound_loading | ⭐️☆☆☆ | 1.1 | 3.5 | [Ray](https://github.com/raysan5) | +| 122 | [audio_module_playing](audio/audio_module_playing.c) | audio_module_playing | ⭐️☆☆☆ | 1.5 | 3.5 | [Ray](https://github.com/raysan5) | +| 123 | [audio_music_stream](audio/audio_music_stream.c) | audio_music_stream | ⭐️☆☆☆ | 1.3 | **4.2** | [Ray](https://github.com/raysan5) | +| 124 | [audio_raw_stream](audio/audio_raw_stream.c) | audio_raw_stream | ⭐️⭐️⭐️☆ | 1.6 | **4.2** | [Ray](https://github.com/raysan5) | +| 125 | [audio_sound_loading](audio/audio_sound_loading.c) | audio_sound_loading | ⭐️☆☆☆ | 1.1 | 3.5 | [Ray](https://github.com/raysan5) | ### category: others @@ -197,11 +198,11 @@ Examples showing raylib misc functionality that does not fit in other categories | ## | example | image | difficulty
level | version
created | last version
updated | original
developer | |----|----------|--------|:-------------------:|:------------------:|:------------------:|:----------| -| 123 | [rlgl_standalone](others/rlgl_standalone.c) | rlgl_standalone | ⭐️⭐️⭐️⭐️ | 1.6 | **4.0** | [Ray](https://github.com/raysan5) | -| 124 | [rlgl_compute_shader](others/rlgl_compute_shader.c) | rlgl_compute_shader | ⭐️⭐️⭐️⭐️ | **4.0** | **4.0** | [Teddy Astie](https://github.com/tsnake41) | -| 125 | [easings_testbed](others/easings_testbed.c) | easings_testbed | ⭐️⭐️⭐️☆ | 3.0 | 3.0 | [Juan Miguel López](https://github.com/flashback-fx) | -| 126 | [raylib_opengl_interop](others/raylib_opengl_interop.c) | raylib_opengl_interop | ⭐️⭐️⭐️⭐️ | **4.0** | **4.0** | [Stephan Soller](https://github.com/arkanis) | -| 127 | [embedded_files_loading](others/embedded_files_loading.c) | embedded_files_loading | ⭐️⭐️☆☆ | 3.5 | 3.5 | [Kristian Holmgren](https://github.com/defutura) | +| 126 | [rlgl_standalone](others/rlgl_standalone.c) | rlgl_standalone | ⭐️⭐️⭐️⭐️ | 1.6 | **4.0** | [Ray](https://github.com/raysan5) | +| 127 | [rlgl_compute_shader](others/rlgl_compute_shader.c) | rlgl_compute_shader | ⭐️⭐️⭐️⭐️ | **4.0** | **4.0** | [Teddy Astie](https://github.com/tsnake41) | +| 128 | [easings_testbed](others/easings_testbed.c) | easings_testbed | ⭐️⭐️⭐️☆ | 3.0 | 3.0 | [Juan Miguel López](https://github.com/flashback-fx) | +| 129 | [raylib_opengl_interop](others/raylib_opengl_interop.c) | raylib_opengl_interop | ⭐️⭐️⭐️⭐️ | **4.0** | **4.0** | [Stephan Soller](https://github.com/arkanis) | +| 130 | [embedded_files_loading](others/embedded_files_loading.c) | embedded_files_loading | ⭐️⭐️☆☆ | 3.5 | 3.5 | [Kristian Holmgren](https://github.com/defutura) | As always contributions are welcome, feel free to send new examples! Here is an [examples template](examples_template.c) to start with! diff --git a/examples/core/core_input_virtual_controls.c b/examples/core/core_input_virtual_controls.c new file mode 100644 index 000000000..ae7f770aa --- /dev/null +++ b/examples/core/core_input_virtual_controls.c @@ -0,0 +1,123 @@ +/******************************************************************************************* +* +* raylib [core] example - input virtual controls +* +* Example originally created with raylib 5.0, last time updated with raylib 5.0 +* +* Example create by GreenSnakeLinux (@GreenSnakeLinux), +* lighter by oblerion (@oblerion) and +* reviewed by Ramon Santamaria (@raysan5) +* +* Example 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) 2024 Ramon Santamaria (@raysan5) +* +********************************************************************************************/ + +#include "raylib.h" +#include +//------------------------------------------------------------------------------------ +// Program main entry point +//------------------------------------------------------------------------------------ +int main(void) +{ + // Initialization + //-------------------------------------------------------------------------------------- + const int screenWidth = 800; + const int screenHeight = 450; + + InitWindow(screenWidth, screenHeight, "raylib [core] example - input virtual controls"); + + const int dpadX = 90; + const int dpadY = 300; + const int dpadRad = 25;//radius of each pad + Color dpadColor = BLUE; + int dpadKeydown = -1;//-1 if not down, else 0,1,2,3 + + + const float dpadCollider[4][2]= // collider array with x,y position + { + {dpadX,dpadY-dpadRad*1.5},//up + {dpadX-dpadRad*1.5,dpadY},//left + {dpadX+dpadRad*1.5,dpadY},//right + {dpadX,dpadY+dpadRad*1.5}//down + }; + const char dpadLabel[4]="XYBA";//label of Dpad + + float playerX=100; + float playerY=100; + + SetTargetFPS(60); + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //-------------------------------------------------------------------------- + dpadKeydown = -1; //reset + float inputX=0; + float inputY=0; + if(GetTouchPointCount()>0) + {//use touch pos + inputX = GetTouchX(); + inputY = GetTouchY(); + } + else + {//use mouse pos + inputX = GetMouseX(); + inputY = GetMouseY(); + } + for(int i=0;i<4;i++) + { + //test distance each collider and input < radius + if( fabsf(dpadCollider[i][1]-inputY) + fabsf(dpadCollider[i][0]-inputX) < dpadRad) + { + dpadKeydown = i; + break; + } + } + // move player + switch(dpadKeydown){ + case 0: playerY -= 50*GetFrameTime(); + break; + case 1: playerX -= 50*GetFrameTime(); + break; + case 2: playerX += 50*GetFrameTime(); + break; + case 3: playerY += 50*GetFrameTime(); + default:; + }; + //-------------------------------------------------------------------------- + + // Draw + //-------------------------------------------------------------------------- + BeginDrawing(); + ClearBackground(RAYWHITE); + for(int i=0;i<4;i++) + { + //draw all pad + DrawCircle(dpadCollider[i][0],dpadCollider[i][1],dpadRad,dpadColor); + if(i!=dpadKeydown) + { + //draw label + DrawText(TextSubtext(dpadLabel,i,1), + dpadCollider[i][0]-5, + dpadCollider[i][1]-5,16,BLACK); + } + + } + DrawText("Player",playerX,playerY,16,BLACK); + EndDrawing(); + //-------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} + diff --git a/examples/core/core_input_virtual_controls.png b/examples/core/core_input_virtual_controls.png new file mode 100644 index 0000000000000000000000000000000000000000..a9776e68a3dfdd01f5b8afc51859ace27a150622 GIT binary patch literal 9604 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 bk Date: Sun, 6 Oct 2024 08:52:01 -0500 Subject: [PATCH 107/208] [zig] Fix build.zig bug (#4366) * fixed zig config.h bug * zig fmt --- src/build.zig | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/build.zig b/src/build.zig index b08b909de..71729e4d2 100644 --- a/src/build.zig +++ b/src/build.zig @@ -47,7 +47,7 @@ fn setDesktopPlatform(raylib: *std.Build.Step.Compile, platform: PlatformBackend .glfw => raylib.defineCMacro("PLATFORM_DESKTOP_GLFW", null), .rgfw => raylib.defineCMacro("PLATFORM_DESKTOP_RGFW", null), .sdl => raylib.defineCMacro("PLATFORM_DESKTOP_SDL", null), - else => {} + else => {}, } } @@ -74,11 +74,12 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std. while (lines.next()) |line| { if (!std.mem.containsAtLeast(u8, line, 1, "SUPPORT")) continue; if (std.mem.startsWith(u8, line, "//")) continue; + if (std.mem.startsWith(u8, line, "#if")) continue; var flag = std.mem.trimLeft(u8, line, " \t"); // Trim whitespace flag = flag["#define ".len - 1 ..]; // Remove #define flag = std.mem.trimLeft(u8, flag, " \t"); // Trim whitespace - flag = flag[0..std.mem.indexOf(u8, flag, " ").?]; // Flag is only one word, so capture till space + flag = flag[0 .. std.mem.indexOf(u8, flag, " ") orelse continue]; // Flag is only one word, so capture till space flag = try std.fmt.allocPrint(b.allocator, "-D{s}", .{flag}); // Prepend with -D // If user specifies the flag skip it @@ -301,6 +302,7 @@ pub const Options = struct { shared: bool = false, linux_display_backend: LinuxDisplayBackend = .Both, opengl_version: OpenglVersion = .auto, + /// config should be a list of cflags, eg, "-DSUPPORT_CUSTOM_FRAME_CONTROL" config: ?[]const u8 = null, raygui_dependency_name: []const u8 = "raygui", @@ -338,7 +340,7 @@ pub const PlatformBackend = enum { glfw, rgfw, sdl, - drm + drm, }; pub fn build(b: *std.Build) !void { From 43b109a4e3fa40c03bdf0ea3a45c908c10a2774f Mon Sep 17 00:00:00 2001 From: Anthony Carbajal <5776225+CrackedPixel@users.noreply.github.com> Date: Mon, 7 Oct 2024 02:32:04 -0500 Subject: [PATCH 108/208] removed old comment (#4370) --- src/rcore.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/rcore.c b/src/rcore.c index 3cdacbd96..e154d6173 100644 --- a/src/rcore.c +++ b/src/rcore.c @@ -578,7 +578,6 @@ const char *TextFormat(const char *text, ...); // Formatting of tex //void DisableCursor(void) // Initialize window and OpenGL context -// NOTE: data parameter could be used to pass any kind of required data to the initialization void InitWindow(int width, int height, const char *title) { TRACELOG(LOG_INFO, "Initializing raylib %s", RAYLIB_VERSION); From 89a37cd3151ef2a91643d797941711889bddf0fb Mon Sep 17 00:00:00 2001 From: Ray Date: Mon, 7 Oct 2024 21:03:55 +0200 Subject: [PATCH 109/208] Update CHANGELOG --- CHANGELOG | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index 2141926ce..b5b50e4d7 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -3,6 +3,17 @@ changelog Current Release: raylib 5.0 (18 November 2023) +------------------------------------------------------------------------- +Release: raylib 5.5 - 11th Anniversary Edition? (18 November 2024?) +------------------------------------------------------------------------- +KEY CHANGES: + - + - + - + +Detailed changes: +... + ------------------------------------------------------------------------- Release: raylib 5.0 - 10th Anniversary Edition (18 November 2023) ------------------------------------------------------------------------- From 712ab798d1fbf66310240b1e66f0ad6f5a673a4c Mon Sep 17 00:00:00 2001 From: Anthony Carbajal <5776225+CrackedPixel@users.noreply.github.com> Date: Tue, 8 Oct 2024 11:33:33 -0500 Subject: [PATCH 110/208] updated makefile to disable wayland by default (#4369) --- src/Makefile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Makefile b/src/Makefile index 4740f1f01..137c28b53 100644 --- a/src/Makefile +++ b/src/Makefile @@ -109,8 +109,9 @@ RAYLIB_MODULE_RAYGUI_PATH ?= $(RAYLIB_SRC_PATH)/../../raygui/src # Use external GLFW library instead of rglfw module USE_EXTERNAL_GLFW ?= FALSE -# Enable support for both Wayland and X11 by default on Linux when using GLFW -GLFW_LINUX_ENABLE_WAYLAND ?= TRUE +# Enable support for X11 by default on Linux when using GLFW +# NOTE: Wayland is disabled by default, only enable if you are sure +GLFW_LINUX_ENABLE_WAYLAND ?= FALSE GLFW_LINUX_ENABLE_X11 ?= TRUE # PLATFORM_DESKTOP_SDL: It requires SDL library to be provided externally From 44e37c5f975b024cfea04ec35a1f843315fee7f4 Mon Sep 17 00:00:00 2001 From: Colleague Riley Date: Tue, 8 Oct 2024 12:39:15 -0400 Subject: [PATCH 111/208] Update RGFW (#4372) * (rcore_desktop_rgfw.c) fix errors when compiling with mingw * define WideCharToMultiByte * update RGFW * move stdcall def to windows only * fix raw cursor input --- src/external/RGFW.h | 271 +++++++++++++++++------------ src/platforms/rcore_desktop_rgfw.c | 25 +-- 2 files changed, 165 insertions(+), 131 deletions(-) diff --git a/src/external/RGFW.h b/src/external/RGFW.h index 35e782d4a..fb389d5b4 100644 --- a/src/external/RGFW.h +++ b/src/external/RGFW.h @@ -192,7 +192,7 @@ typedef u32 b32; #endif -#define RGFW_TRUE 1 +#define RGFW_TRUE (!(0)) #define RGFW_FALSE 0 /* thse OS macros looks better & are standardized */ @@ -276,11 +276,6 @@ #endif #ifdef RGFW_EGL - #if defined(__APPLE__) - #warning EGL is not supported for Cocoa, switching back to the native opengl api - #undef RGFW_EGL - #endif - #include #elif defined(RGFW_OSMESA) #ifndef __APPLE__ @@ -611,10 +606,17 @@ typedef struct RGFW_window { /** * @defgroup Window_management * @{ */ + +/*! + * the class name for X11 and WinAPI. apps with the same class will be grouped by the WM + * by default the class name will == the root window's name +*/ +RGFWDEF void RGFW_setClassName(char* name); + /*! this has to be set before createWindow is called, else the fulscreen size is used */ RGFWDEF void RGFW_setBufferSize(RGFW_area size); /*!< the buffer cannot be resized (by RGFW) */ -RGFW_window* RGFW_createWindow( +RGFWDEF RGFW_window* RGFW_createWindow( const char* name, /* name of the window */ RGFW_rect rect, /* rect of window */ u16 args /* extra arguments (NULL / (u16)0 means no args used)*/ @@ -635,7 +637,7 @@ RGFWDEF RGFW_area RGFW_getScreenSize(void); although you still need some way to tell RGFW to process events eg. `RGFW_window_checkEvents` */ -RGFW_Event* RGFW_window_checkEvent(RGFW_window* win); /*!< check current event (returns a pointer to win->event or NULL if there is no event)*/ +RGFWDEF RGFW_Event* RGFW_window_checkEvent(RGFW_window* win); /*!< check current event (returns a pointer to win->event or NULL if there is no event)*/ /*! for RGFW_window_eventWait and RGFW_window_checkEvents @@ -706,7 +708,7 @@ RGFWDEF void RGFW_window_setName(RGFW_window* win, char* name ); -void RGFW_window_setIcon(RGFW_window* win, /*!< source window */ +RGFWDEF void RGFW_window_setIcon(RGFW_window* win, /*!< source window */ u8* icon /*!< icon bitmap */, RGFW_area a /*!< width and height of the bitmap*/, i32 channels /*!< how many channels the bitmap has (rgb : 3, rgba : 4) */ @@ -1609,9 +1611,6 @@ RGFW_window* RGFW_window_basic_init(RGFW_rect rect, u16 args) { if (args & RGFW_FULLSCREEN) rect = RGFW_RECT(0, 0, screenR.w, screenR.h); - if (args & RGFW_CENTER) - rect = RGFW_RECT((screenR.w - rect.w) / 2, (screenR.h - rect.h) / 2, rect.w, rect.h); - /* set and init the new window's data */ win->r = rect; win->event.inFocus = 1; @@ -1627,7 +1626,7 @@ RGFW_window* RGFW_window_basic_init(RGFW_rect rect, u16 args) { void RGFW_window_scaleToMonitor(RGFW_window* win) { RGFW_monitor monitor = RGFW_window_getMonitor(win); - RGFW_window_resize(win, RGFW_AREA(((u32) monitor.scaleX) * win->r.w, ((u32) monitor.scaleX) * win->r.h)); + RGFW_window_resize(win, RGFW_AREA((u32)(monitor.scaleX * (float)win->r.w), (u32)(monitor.scaleX * (float)win->r.h))); } #endif @@ -1637,6 +1636,16 @@ RGFW_window* RGFW_root = NULL; #define RGFW_HOLD_MOUSE (1L<<2) /*!< hold the moues still */ #define RGFW_MOUSE_LEFT (1L<<3) /* if mouse left the window */ +#ifdef RGFW_MACOS +RGFWDEF void RGFW_window_cocoaSetLayer(RGFW_window* win, void* layer); +RGFWDEF void* RGFW_cocoaGetLayer(void); +#endif + +char* RGFW_className = NULL; +void RGFW_setClassName(char* name) { + RGFW_className = name; +} + void RGFW_clipboardFree(char* str) { RGFW_FREE(str); } RGFW_keyState RGFW_mouseButtons[5] = { {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0} }; @@ -2073,6 +2082,8 @@ void RGFW_updateLockState(RGFW_window* win, b8 capital, b8 numlock) { #ifdef RGFW_WINDOWS win->src.EGL_display = eglGetDisplay((EGLNativeDisplayType) win->src.hdc); + #elif defined(RGFW_MACOS) + win->src.EGL_display = eglGetDisplay((EGLNativeDisplayType)0); #else win->src.EGL_display = eglGetDisplay((EGLNativeDisplayType) win->src.display); #endif @@ -2104,8 +2115,15 @@ void RGFW_updateLockState(RGFW_window* win, b8 capital, b8 numlock) { EGLint numConfigs; eglChooseConfig(win->src.EGL_display, egl_config, &config, 1, &numConfigs); - - win->src.EGL_surface = eglCreateWindowSurface(win->src.EGL_display, config, (EGLNativeWindowType) win->src.window, NULL); + #if defined(RGFW_MACOS) + void* layer = RGFW_cocoaGetLayer(); + + RGFW_window_cocoaSetLayer(win, layer); + + win->src.EGL_surface = eglCreateWindowSurface(win->src.EGL_display, config, (EGLNativeWindowType) layer, NULL); + #else + win->src.EGL_surface = eglCreateWindowSurface(win->src.EGL_display, config, (EGLNativeWindowType) win->src.window, NULL); + #endif EGLint attribs[] = { EGL_CONTEXT_CLIENT_VERSION, @@ -2322,7 +2340,7 @@ Start of Linux / Unix defines u8 RGFW_mouseIconSrc[] = { XC_arrow, XC_left_ptr, XC_xterm, XC_crosshair, XC_hand2, XC_sb_h_double_arrow, XC_sb_v_double_arrow, XC_bottom_left_corner, XC_bottom_right_corner, XC_fleur, XC_X_cursor}; /*atoms needed for drag and drop*/ - Atom XdndAware, XdndTypeList, XdndSelection, XdndEnter, XdndPosition, XdndStatus, XdndLeave, XdndDrop, XdndFinished, XdndActionCopy, XdndActionMove, XdndActionLink, XdndActionAsk, XdndActionPrivate; + Atom XdndAware, XdndTypeList, XdndSelection, XdndEnter, XdndPosition, XdndStatus, XdndLeave, XdndDrop, XdndFinished, XdndActionCopy, XtextPlain, XtextUriList; Atom wm_delete_window = 0; @@ -2563,9 +2581,13 @@ Start of Linux / Unix defines // In your .desktop app, if you set the property // StartupWMClass=RGFW that will assoicate the launcher icon // with your application - robrohan + + if (RGFW_className == NULL) + RGFW_className = (char*)name; + XClassHint *hint = XAllocClassHint(); assert(hint != NULL); - hint->res_class = (char*)"RGFW"; + hint->res_class = (char*)RGFW_className; hint->res_name = (char*)name; // just use the window name as the app name XSetClassHint((Display*) win->src.display, win->src.window, hint); XFree(hint); @@ -2609,6 +2631,11 @@ Start of Linux / Unix defines RGFW_window_scaleToMonitor(win); #endif + if (args & RGFW_CENTER) { + RGFW_area screenR = RGFW_getScreenSize(); + RGFW_window_move(win, RGFW_POINT((screenR.w - win->r.w) / 2, (screenR.h - win->r.h) / 2)); + } + if (args & RGFW_NO_RESIZE) { /* make it so the user can't resize the window*/ XSizeHints* sh = XAllocSizeHints(); sh->flags = (1L << 4) | (1L << 5); @@ -2646,7 +2673,6 @@ Start of Linux / Unix defines if (args & RGFW_ALLOW_DND) { /* init drag and drop atoms and turn on drag and drop for this window */ win->_winArgs |= RGFW_ALLOW_DND; - XdndAware = XInternAtom((Display*) win->src.display, "XdndAware", False); XdndTypeList = XInternAtom((Display*) win->src.display, "XdndTypeList", False); XdndSelection = XInternAtom((Display*) win->src.display, "XdndSelection", False); @@ -2660,15 +2686,16 @@ Start of Linux / Unix defines /* actions */ XdndActionCopy = XInternAtom((Display*) win->src.display, "XdndActionCopy", False); - XdndActionMove = XInternAtom((Display*) win->src.display, "XdndActionMove", False); - XdndActionLink = XInternAtom((Display*) win->src.display, "XdndActionLink", False); - XdndActionAsk = XInternAtom((Display*) win->src.display, "XdndActionAsk", False); - XdndActionPrivate = XInternAtom((Display*) win->src.display, "XdndActionPrivate", False); - const Atom version = 5; + + XtextUriList = XInternAtom((Display*) win->src.display, "text/uri-list", False); + XtextPlain = XInternAtom((Display*) win->src.display, "text/plain", False); + + XdndAware = XInternAtom((Display*) win->src.display, "XdndAware", False); + const u8 version = 5; XChangeProperty((Display*) win->src.display, (Window) win->src.window, XdndAware, 4, 32, - PropModeReplace, (u8*) &version, 1); /*!< turns on drag and drop */ + PropModeReplace, &version, 1); /*!< turns on drag and drop */ } #ifdef RGFW_EGL @@ -2716,17 +2743,16 @@ Start of Linux / Unix defines return RGFWMouse; } - typedef struct XDND { - long source, version; - i32 format; - } XDND; /*!< data structure for xdnd events */ - XDND xdnd; - int xAxis = 0, yAxis = 0; RGFW_Event* RGFW_window_checkEvent(RGFW_window* win) { assert(win != NULL); + static struct { + long source, version; + i32 format; + } xdnd; + if (win->event.type == 0) RGFW_resetKey(); @@ -2893,13 +2919,16 @@ Start of Linux / Unix defines win->event.droppedFilesCount = 0; - /* - much of this event (drag and drop code) is source from glfw - */ - if ((win->_winArgs & RGFW_ALLOW_DND) == 0) break; + XEvent reply = { ClientMessage }; + reply.xclient.window = xdnd.source; + reply.xclient.format = 32; + reply.xclient.data.l[0] = (long) win->src.window; + reply.xclient.data.l[1] = 0; + reply.xclient.data.l[2] = None; + if (E.xclient.message_type == XdndEnter) { unsigned long count; Atom* formats; @@ -2944,28 +2973,11 @@ Start of Linux / Unix defines formats = real_formats; } - u32 i; - for (i = 0; i < (u32)count; i++) { - char* name = XGetAtomName((Display*) win->src.display, formats[i]); - - char* links[2] = { (char*) (const char*) "text/uri-list", (char*) (const char*) "text/plain" }; - for (; 1; name++) { - u32 j; - for (j = 0; j < 2; j++) { - if (*links[j] != *name) { - links[j] = (char*) (const char*) "\1"; - continue; - } - - if (*links[j] == '\0' && *name == '\0') - xdnd.format = formats[i]; - - if (*links[j] != '\0' && *links[j] != '\1') - links[j]++; - } - - if (*name == '\0') - break; + unsigned long i; + for (i = 0; i < count; i++) { + if (formats[i] == XtextUriList || formats[i] == XtextPlain) { + xdnd.format = formats[i]; + break; } } @@ -2994,13 +3006,8 @@ Start of Linux / Unix defines win->event.point.x = xpos; win->event.point.y = ypos; - XEvent reply = { ClientMessage }; reply.xclient.window = xdnd.source; reply.xclient.message_type = XdndStatus; - reply.xclient.format = 32; - reply.xclient.data.l[0] = (long) win->src.window; - reply.xclient.data.l[2] = 0; - reply.xclient.data.l[3] = 0; if (xdnd.format) { reply.xclient.data.l[1] = 1; @@ -3035,12 +3042,6 @@ Start of Linux / Unix defines time); } else if (xdnd.version >= 2) { XEvent reply = { ClientMessage }; - reply.xclient.window = xdnd.source; - reply.xclient.message_type = XdndFinished; - reply.xclient.format = 32; - reply.xclient.data.l[0] = (long) win->src.window; - reply.xclient.data.l[1] = 0; - reply.xclient.data.l[2] = None; XSendEvent((Display*) win->src.display, xdnd.source, False, NoEventMask, &reply); @@ -3125,11 +3126,7 @@ Start of Linux / Unix defines XFree(data); if (xdnd.version >= 2) { - XEvent reply = { ClientMessage }; - reply.xclient.window = xdnd.source; reply.xclient.message_type = XdndFinished; - reply.xclient.format = 32; - reply.xclient.data.l[0] = (long) win->src.window; reply.xclient.data.l[1] = result; reply.xclient.data.l[2] = XdndActionCopy; @@ -3480,7 +3477,7 @@ Start of Linux / Unix defines *size = sizeN; return s; - } + } /* almost all of this function is sourced from GLFW @@ -3520,9 +3517,6 @@ Start of Linux / Unix defines XEvent reply = { SelectionNotify }; reply.xselection.property = 0; - const Atom formats[] = { UTF8_STRING, XA_STRING }; - const i32 formatCount = sizeof(formats) / sizeof(formats[0]); - if (request->target == TARGETS) { const Atom targets[] = { TARGETS, MULTIPLE, @@ -3552,15 +3546,7 @@ Start of Linux / Unix defines unsigned long i; for (i = 0; i < (u32)count; i += 2) { - i32 j; - - for (j = 0; j < formatCount; j++) { - if (targets[i] == formats[j]) - break; - } - - if (j < formatCount) - { + if (targets[i] == UTF8_STRING || targets[i] == XA_STRING) { XChangeProperty((Display*) RGFW_root->src.display, request->requestor, targets[i + 1], @@ -3727,32 +3713,54 @@ Start of Linux / Unix defines RGFW_monitor monitor; Display* display = XOpenDisplay(NULL); + + RGFW_area size = RGFW_getScreenSize(); - monitor.rect = RGFW_RECT(0, 0, DisplayWidth(display, screen), DisplayHeight(display, screen)); - monitor.physW = (monitor.rect.w * 25.4f / 96.f); - monitor.physH = (monitor.rect.h * 25.4f / 96.f); - - strncpy(monitor.name, DisplayString(display), 128); - + monitor.rect = RGFW_RECT(0, 0, size.w, size.h); + monitor.physW = DisplayWidthMM(display, screen); + monitor.physH = DisplayHeightMM(display, screen); + XGetSystemContentScale(display, &monitor.scaleX, &monitor.scaleY); - XRRScreenResources* sr = XRRGetScreenResourcesCurrent(display, RootWindow(display, screen)); XRRCrtcInfo* ci = NULL; - int crtc = 0; + int crtc = screen; if (sr->ncrtc > crtc) { ci = XRRGetCrtcInfo(display, sr, sr->crtcs[crtc]); } - + if (ci == NULL) { + float dpi_width = round((double)monitor.rect.w/(((double)monitor.physW)/25.4)); + float dpi_height = round((double)monitor.rect.h/(((double)monitor.physH)/25.4)); + + monitor.scaleX = (float) (dpi_width) / (float) 96; + monitor.scaleY = (float) (dpi_height) / (float) 96; XRRFreeScreenResources(sr); XCloseDisplay(display); return monitor; } + + XRROutputInfo* info = XRRGetOutputInfo (display, sr, sr->outputs[screen]); + monitor.physW = info->mm_width; + monitor.physH = info->mm_height; monitor.rect.x = ci->x; monitor.rect.y = ci->y; + monitor.rect.w = ci->width; + monitor.rect.h = ci->height; + + float dpi_width = round((double)monitor.rect.w/(((double)monitor.physW)/25.4)); + float dpi_height = round((double)monitor.rect.h/(((double)monitor.physH)/25.4)); + + monitor.scaleX = (float) (dpi_width) / (float) 96; + monitor.scaleY = (float) (dpi_height) / (float) 96; + + if (monitor.scaleX > 1 && monitor.scaleX < 1.1) + monitor.scaleX = 1; + + if (monitor.scaleY > 1 && monitor.scaleY < 1.1) + monitor.scaleY = 1; XRRFreeCrtcInfo(ci); XRRFreeScreenResources(sr); @@ -4150,9 +4158,6 @@ RGFW_Event RGFW_eventPipe_pop(RGFW_window* win) { if (win->src.eventLen >= 0) ev = win->src.events[win->src.eventLen]; - else { - printf("H2\n"); - } return ev; } @@ -4675,6 +4680,10 @@ static const struct wl_callback_listener wl_surface_frame_listener = { decoration_manager, win->src.xdg_toplevel); } + if (args & RGFW_CENTER) { + RGFW_area screenR = RGFW_getScreenSize(); + RGFW_window_move(win, RGFW_POINT((screenR.w - win->r.w) / 2, (screenR.h - win->r.h) / 2)); + } if (args & RGFW_OPENGL_SOFTWARE) setenv("LIBGL_ALWAYS_SOFTWARE", "1", 1); @@ -4999,9 +5008,7 @@ static const struct wl_callback_listener wl_surface_frame_listener = { #define WIN32_LEAN_AND_MEAN #define OEMRESOURCE #include - - __declspec(dllimport) int __stdcall WideCharToMultiByte( UINT CodePage, DWORD dwFlags, const WCHAR* lpWideCharStr, int cchWideChar, LPSTR lpMultiByteStr, int cbMultiByte, LPCCH lpDefaultChar, LPBOOL lpUsedDefaultChar); - + #include #include #include @@ -5009,6 +5016,10 @@ static const struct wl_callback_listener wl_surface_frame_listener = { #include #include + #include + + __declspec(dllimport) int __stdcall WideCharToMultiByte( UINT CodePage, DWORD dwFlags, const WCHAR* lpWideCharStr, int cchWideChar, LPSTR lpMultiByteStr, int cbMultiByte, LPCCH lpDefaultChar, LPBOOL lpUsedDefaultChar); + #ifndef RGFW_NO_XINPUT typedef DWORD (WINAPI * PFN_XInputGetState)(DWORD,XINPUT_STATE*); PFN_XInputGetState XInputGetStateSRC = NULL; @@ -5226,14 +5237,15 @@ RGFW_UNUSED(win); /*!< if buffer rendering is not being used */ } void RGFW_releaseCursor(RGFW_window* win) { + RGFW_UNUSED(win); ClipCursor(NULL); const RAWINPUTDEVICE id = { 0x01, 0x02, RIDEV_REMOVE, NULL }; RegisterRawInputDevices(&id, 1, sizeof(id)); } void RGFW_captureCursor(RGFW_window* win, RGFW_rect rect) { - RGFW_UNUSED(win) - + RGFW_UNUSED(win); RGFW_UNUSED(rect); + RECT clipRect; GetClientRect(win->src.window, &clipRect); ClientToScreen(win->src.window, (POINT*) &clipRect.left); @@ -5254,6 +5266,7 @@ RGFW_UNUSED(win); /*!< if buffer rendering is not being used */ if (RGFW_Shcore_dll == NULL) { RGFW_Shcore_dll = LoadLibraryA("shcore.dll"); GetDpiForMonitorSRC = (PFN_GetDpiForMonitor)(void*)GetProcAddress(RGFW_Shcore_dll, "GetDpiForMonitor"); + SetProcessDPIAware(); } #endif @@ -5288,7 +5301,10 @@ RGFW_UNUSED(win); /*!< if buffer rendering is not being used */ WNDCLASSA Class = { }; #endif - Class.lpszClassName = name; + if (RGFW_className == NULL) + RGFW_className = (char*)name; + + Class.lpszClassName = RGFW_className; Class.hInstance = inh; Class.hCursor = LoadCursor(NULL, IDC_ARROW); Class.lpfnWndProc = WndProc; @@ -5501,6 +5517,11 @@ RGFW_UNUSED(win); /*!< if buffer rendering is not being used */ if (args & RGFW_SCALE_TO_MONITOR) RGFW_window_scaleToMonitor(win); #endif + + if (args & RGFW_CENTER) { + RGFW_area screenR = RGFW_getScreenSize(); + RGFW_window_move(win, RGFW_POINT((screenR.w - win->r.w) / 2, (screenR.h - win->r.h) / 2)); + } #ifdef RGFW_EGL if ((args & RGFW_NO_INIT_API) == 0) @@ -6102,7 +6123,8 @@ RGFW_UNUSED(win); /*!< if buffer rendering is not being used */ if (GetDpiForMonitor != NULL) { u32 x, y; - GetDpiForMonitor(src, MDT_ANGULAR_DPI, &x, &y); + GetDpiForMonitor(src, MDT_EFFECTIVE_DPI, &x, &y); + monitor.scaleX = (float) (x) / (float) USER_DEFAULT_SCREEN_DPI; monitor.scaleY = (float) (y) / (float) USER_DEFAULT_SCREEN_DPI; } @@ -6117,7 +6139,7 @@ RGFW_UNUSED(win); /*!< if buffer rendering is not being used */ /* Calculate physical height in inches */ monitor.physW = GetSystemMetrics(SM_CYSCREEN) / (float) ppiX; monitor.physH = GetSystemMetrics(SM_CXSCREEN) / (float) ppiY; - + return monitor; } #endif /* RGFW_NO_MONITOR */ @@ -6152,7 +6174,7 @@ RGFW_UNUSED(win); /*!< if buffer rendering is not being used */ RGFW_mInfo info; info.iIndex = 0; while (EnumDisplayMonitors(NULL, NULL, GetMonitorHandle, (LPARAM) &info)); - + return RGFW_monitors; } @@ -7104,7 +7126,6 @@ RGFW_UNUSED(win); /*!< if buffer rendering is not being used */ for (int i = 0; i < count; i++) { id fileURL = objc_msgSend_arr(fileURLs, sel_registerName("objectAtIndex:"), i); const char *filePath = ((const char* (*)(id, SEL))objc_msgSend)(fileURL, sel_registerName("UTF8String")); - // printf("File: %s\n", filePath); strncpy(win->event.droppedFiles[i], filePath, RGFW_MAX_PATH); win->event.droppedFiles[i][RGFW_MAX_PATH - 1] = '\0'; } @@ -7208,6 +7229,16 @@ RGFW_UNUSED(win); /*!< if buffer rendering is not being used */ #endif } + + void RGFW_window_cocoaSetLayer(RGFW_window* win, void* layer) { + objc_msgSend_void_id(win->src.view, sel_registerName("setLayer"), layer); + } + + void* RGFW_cocoaGetLayer(void) { + return objc_msgSend_class(objc_getClass("CAMetalLayer"), sel_registerName("layer")); + } + + NSPasteboardType const NSPasteboardTypeURL = "public.url"; NSPasteboardType const NSPasteboardTypeFileURL = "public.file-url"; @@ -7263,6 +7294,11 @@ RGFW_UNUSED(win); /*!< if buffer rendering is not being used */ NSString* str = NSString_stringWithUTF8String(name); objc_msgSend_void_id(win->src.window, sel_registerName("setTitle:"), str); +#ifdef RGFW_EGL + if ((args & RGFW_NO_INIT_API) == 0) + RGFW_createOpenGLContext(win); +#endif + #ifdef RGFW_OPENGL if ((args & RGFW_NO_INIT_API) == 0) { void* attrs = RGFW_initFormatAttribs(args & RGFW_OPENGL_SOFTWARE); @@ -7329,6 +7365,11 @@ RGFW_UNUSED(win); /*!< if buffer rendering is not being used */ RGFW_window_scaleToMonitor(win); #endif + if (args & RGFW_CENTER) { + RGFW_area screenR = RGFW_getScreenSize(); + RGFW_window_move(win, RGFW_POINT((screenR.w - win->r.w) / 2, (screenR.h - win->r.h) / 2)); + } + if (args & RGFW_HIDE_MOUSE) RGFW_window_showMouse(win, 0); @@ -7935,6 +7976,7 @@ RGFW_UNUSED(win); /*!< if buffer rendering is not being used */ } void RGFW_releaseCursor(RGFW_window* win) { + RGFW_UNUSED(win); CGAssociateMouseAndMouseCursorPosition(1); } @@ -7994,13 +8036,11 @@ RGFW_UNUSED(win); /*!< if buffer rendering is not being used */ monitor.rect = RGFW_RECT((int) bounds.origin.x, (int) bounds.origin.y, (int) bounds.size.width, (int) bounds.size.height); CGSize screenSizeMM = CGDisplayScreenSize(display); - monitor.physW = screenSizeMM.width / 25.4; - monitor.physH = screenSizeMM.height / 25.4; + monitor.physW = screenSizeMM.width; + monitor.physH = screenSizeMM.height; - monitor.scaleX = (monitor.rect.w / (screenSizeMM.width)) / 2.6; - monitor.scaleY = (monitor.rect.h / (screenSizeMM.height)) / 2.6; - - snprintf(monitor.name, 128, "%i %i %i", CGDisplayModelNumber(display), CGDisplayVendorNumber(display), CGDisplaySerialNumber(display)); + monitor.scaleX = ((monitor.rect.w / (screenSizeMM.width / 25.4)) / 96) + 0.25; + monitor.scaleY = ((monitor.rect.h / (screenSizeMM.height / 25.4)) / 96) + 0.25; return monitor; } @@ -8090,6 +8130,8 @@ RGFW_UNUSED(win); /*!< if buffer rendering is not being used */ #if defined(RGFW_OPENGL) NSOpenGLContext_setValues(win->src.ctx, &swapInterval, 222); + #else + RGFW_UNUSED(swapInterval); #endif } #endif @@ -8532,7 +8574,7 @@ RGFW_window* RGFW_createWindow(const char* name, RGFW_rect rect, u16 args) { emscripten_webgl_make_context_current(win->src.ctx); #ifdef LEGACY_GL_EMULATION - EM_ASM("Module.useWebGL = true; GLImmediate.init();"); + EM_ASM("Module.useWebGL = true; GLImmediate.init();"); #endif emscripten_set_canvas_element_size("#canvas", rect.w, rect.h); @@ -8875,11 +8917,12 @@ u64 RGFW_getTime(void) { } void RGFW_releaseCursor(RGFW_window* win) { + RGFW_UNUSED(win); emscripten_exit_pointerlock(); } void RGFW_captureCursor(RGFW_window* win, RGFW_rect r) { - RGFW_UNUSED(win) + RGFW_UNUSED(win); RGFW_UNUSED(r); emscripten_request_pointerlock("#canvas", 1); } diff --git a/src/platforms/rcore_desktop_rgfw.c b/src/platforms/rcore_desktop_rgfw.c index ef01820cb..76f4cdd0a 100644 --- a/src/platforms/rcore_desktop_rgfw.c +++ b/src/platforms/rcore_desktop_rgfw.c @@ -1,6 +1,6 @@ /********************************************************************************************** * -* rcore_desktop_rgfw template - Functions to manage window, graphics device and inputs +* rcore_desktop_rgfw - Functions to manage window, graphics device and inputs * * PLATFORM: RGFW * - Windows (Win32, Win64) @@ -69,6 +69,7 @@ void CloseWindow(void); #define CloseWindow CloseWindow_win32 #define ShowCursor __imp_ShowCursor #define _APISETSTRING_ + __declspec(dllimport) int __stdcall MultiByteToWideChar(unsigned int CodePage, unsigned long dwFlags, const char *lpMultiByteStr, int cbMultiByte, wchar_t *lpWideCharStr, int cchWideChar); #endif #if defined(__APPLE__) @@ -76,8 +77,6 @@ void CloseWindow(void); #define Size NSSIZE #endif -__declspec(dllimport) int __stdcall MultiByteToWideChar(unsigned int CodePage, unsigned long dwFlags, const char *lpMultiByteStr, int cbMultiByte, wchar_t *lpWideCharStr, int cchWideChar); - #include "../external/RGFW.h" #if defined(__WIN32) || defined(__WIN64) @@ -289,7 +288,6 @@ void SetWindowState(unsigned int flags) } if (flags & FLAG_WINDOW_RESIZABLE) { - printf("%i %i\n", platform.window->r.w, platform.window->r.h); RGFW_window_setMaxSize(platform.window, RGFW_AREA(platform.window->r.w, platform.window->r.h)); RGFW_window_setMinSize(platform.window, RGFW_AREA(platform.window->r.w, platform.window->r.h)); } @@ -688,7 +686,7 @@ void DisableCursor(void) { RGFW_disableCursor = true; - RGFW_window_mouseHold(platform.window, RGFW_AREA(CORE.Window.screen.width / 2, CORE.Window.screen.height / 2)); + RGFW_window_mouseHold(platform.window, RGFW_AREA(0, 0)); HideCursor(); } @@ -873,8 +871,8 @@ void PollInputEvents(void) CORE.Window.resizedLastFrame = false; + CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition; #define RGFW_HOLD_MOUSE (1L<<2) - #if defined(RGFW_X11) //|| defined(RGFW_MACOS) if (platform.window->_winArgs & RGFW_HOLD_MOUSE) { CORE.Input.Mouse.previousPosition = (Vector2){ 0.0f, 0.0f }; @@ -884,9 +882,9 @@ void PollInputEvents(void) { CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition; } -#endif - while (RGFW_window_checkEvent(platform.window)) + + while (RGFW_window_checkEvent(platform.window)) { if ((platform.window->event.type >= RGFW_jsButtonPressed) && (platform.window->event.type <= RGFW_jsAxisMove)) @@ -1030,15 +1028,8 @@ void PollInputEvents(void) { if (platform.window->_winArgs & RGFW_HOLD_MOUSE) { - CORE.Input.Mouse.previousPosition = (Vector2){ 0.0f, 0.0f }; - - if (event->point.x) - CORE.Input.Mouse.previousPosition.x = CORE.Input.Mouse.currentPosition.x; - if (event->point.y) - CORE.Input.Mouse.previousPosition.y = CORE.Input.Mouse.currentPosition.y; - - CORE.Input.Mouse.currentPosition.x = (float)event->point.x; - CORE.Input.Mouse.currentPosition.y = (float)event->point.y; + CORE.Input.Mouse.currentPosition.x += (float)event->point.x; + CORE.Input.Mouse.currentPosition.y += (float)event->point.y; } else { From 3fb1ba25aca0a6b023ca254a0910df36b0744e64 Mon Sep 17 00:00:00 2001 From: Ray Date: Tue, 8 Oct 2024 18:45:52 +0200 Subject: [PATCH 112/208] Removed tabs and triple line-breaks --- src/platforms/rcore_android.c | 1 - src/platforms/rcore_desktop_glfw.c | 1 - src/platforms/rcore_desktop_rgfw.c | 11 +++-------- src/platforms/rcore_drm.c | 1 - src/platforms/rcore_template.c | 1 - src/platforms/rcore_web.c | 1 - src/rcamera.h | 1 - src/rlgl.h | 1 - src/rmodels.c | 5 ----- src/rtextures.c | 2 -- src/utils.c | 1 - 11 files changed, 3 insertions(+), 23 deletions(-) diff --git a/src/platforms/rcore_android.c b/src/platforms/rcore_android.c index 6318931cc..88438c9b0 100644 --- a/src/platforms/rcore_android.c +++ b/src/platforms/rcore_android.c @@ -704,7 +704,6 @@ void PollInputEvents(void) } } - //---------------------------------------------------------------------------------- // Module Internal Functions Definition //---------------------------------------------------------------------------------- diff --git a/src/platforms/rcore_desktop_glfw.c b/src/platforms/rcore_desktop_glfw.c index f7b94178c..d42274d14 100644 --- a/src/platforms/rcore_desktop_glfw.c +++ b/src/platforms/rcore_desktop_glfw.c @@ -1234,7 +1234,6 @@ void PollInputEvents(void) glfwSetWindowShouldClose(platform.handle, GLFW_FALSE); } - //---------------------------------------------------------------------------------- // Module Internal Functions Definition //---------------------------------------------------------------------------------- diff --git a/src/platforms/rcore_desktop_rgfw.c b/src/platforms/rcore_desktop_rgfw.c index 76f4cdd0a..20bff2128 100644 --- a/src/platforms/rcore_desktop_rgfw.c +++ b/src/platforms/rcore_desktop_rgfw.c @@ -69,7 +69,7 @@ void CloseWindow(void); #define CloseWindow CloseWindow_win32 #define ShowCursor __imp_ShowCursor #define _APISETSTRING_ - __declspec(dllimport) int __stdcall MultiByteToWideChar(unsigned int CodePage, unsigned long dwFlags, const char *lpMultiByteStr, int cbMultiByte, wchar_t *lpWideCharStr, int cchWideChar); + __declspec(dllimport) int __stdcall MultiByteToWideChar(unsigned int CodePage, unsigned long dwFlags, const char *lpMultiByteStr, int cbMultiByte, wchar_t *lpWideCharStr, int cchWideChar); #endif #if defined(__APPLE__) @@ -870,9 +870,8 @@ void PollInputEvents(void) //----------------------------------------------------------------------------- CORE.Window.resizedLastFrame = false; - CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition; - #define RGFW_HOLD_MOUSE (1L<<2) + #define RGFW_HOLD_MOUSE (1L<<2) if (platform.window->_winArgs & RGFW_HOLD_MOUSE) { CORE.Input.Mouse.previousPosition = (Vector2){ 0.0f, 0.0f }; @@ -883,10 +882,8 @@ void PollInputEvents(void) CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition; } - - while (RGFW_window_checkEvent(platform.window)) + while (RGFW_window_checkEvent(platform.window)) { - if ((platform.window->event.type >= RGFW_jsButtonPressed) && (platform.window->event.type <= RGFW_jsAxisMove)) { if (!CORE.Input.Gamepad.ready[platform.window->event.joystick]) @@ -1196,7 +1193,6 @@ void PollInputEvents(void) //----------------------------------------------------------------------------- } - //---------------------------------------------------------------------------------- // Module Internal Functions Definition //---------------------------------------------------------------------------------- @@ -1253,7 +1249,6 @@ int InitPlatform(void) */ SetupFramebuffer(CORE.Window.display.width, CORE.Window.display.height); - if (CORE.Window.flags & FLAG_VSYNC_HINT) RGFW_window_swapInterval(platform.window, 1); RGFW_window_makeCurrent(platform.window); diff --git a/src/platforms/rcore_drm.c b/src/platforms/rcore_drm.c index ee2875838..e77457b1b 100644 --- a/src/platforms/rcore_drm.c +++ b/src/platforms/rcore_drm.c @@ -1480,7 +1480,6 @@ static void ConfigureEvdevDevice(char *device) TEST_BIT(keyBits, BTN_MOUSE)) isMouse = true; } - if (TEST_BIT(evBits, EV_KEY)) { // The first 32 keys as defined in input-event-codes.h are pretty much diff --git a/src/platforms/rcore_template.c b/src/platforms/rcore_template.c index 938f4ed7d..6bc3432eb 100644 --- a/src/platforms/rcore_template.c +++ b/src/platforms/rcore_template.c @@ -430,7 +430,6 @@ void PollInputEvents(void) // TODO: Poll input events for current platform } - //---------------------------------------------------------------------------------- // Module Internal Functions Definition //---------------------------------------------------------------------------------- diff --git a/src/platforms/rcore_web.c b/src/platforms/rcore_web.c index ff7a92dbc..35c15a6b6 100644 --- a/src/platforms/rcore_web.c +++ b/src/platforms/rcore_web.c @@ -935,7 +935,6 @@ void PollInputEvents(void) // so, if mouse is not moved it returns a (0, 0) position... this behaviour should be reviewed! //for (int i = 0; i < MAX_TOUCH_POINTS; i++) CORE.Input.Touch.position[i] = (Vector2){ 0, 0 }; - // Gamepad support using emscripten API // NOTE: GLFW3 joystick functionality not available in web diff --git a/src/rcamera.h b/src/rcamera.h index ccab549c1..bd2b36e03 100644 --- a/src/rcamera.h +++ b/src/rcamera.h @@ -162,7 +162,6 @@ RLAPI Matrix GetCameraProjectionMatrix(Camera* camera, float aspect); #endif // RCAMERA_H - /*********************************************************************************** * * CAMERA IMPLEMENTATION diff --git a/src/rlgl.h b/src/rlgl.h index 43698f63a..1695c2f56 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -357,7 +357,6 @@ #endif #endif - //---------------------------------------------------------------------------------- // Types and Structures Definition //---------------------------------------------------------------------------------- diff --git a/src/rmodels.c b/src/rmodels.c index d2bf528ff..c9fa222eb 100644 --- a/src/rmodels.c +++ b/src/rmodels.c @@ -702,7 +702,6 @@ void DrawCylinderWires(Vector3 position, float radiusTop, float radiusBottom, fl rlPopMatrix(); } - // Draw a wired cylinder with base at startPos and top at endPos // NOTE: It could be also used for pyramid and cone void DrawCylinderWiresEx(Vector3 startPos, Vector3 endPos, float startRadius, float endRadius, int sides, Color color) @@ -1259,7 +1258,6 @@ void UploadMesh(Mesh *mesh, bool dynamic) mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS] = 0; // Vertex buffer: boneWeights #endif - #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) mesh->vaoId = rlLoadVertexArray(); rlEnableVertexArray(mesh->vaoId); @@ -2098,7 +2096,6 @@ bool ExportMeshAsCode(Mesh mesh, const char *fileName) return success; } - #if defined(SUPPORT_FILEFORMAT_OBJ) || defined(SUPPORT_FILEFORMAT_MTL) // Process obj materials static void ProcessMaterialsOBJ(Material *materials, tinyobj_material_t *mats, int materialCount) @@ -5680,8 +5677,6 @@ static Model LoadGLTF(const char *fileName) else TRACELOG(LOG_WARNING, "MODEL: [%s] Color attribute data format not supported", fileName); } else TRACELOG(LOG_WARNING, "MODEL: [%s] Color attribute data format not supported", fileName); - - } // NOTE: Attributes related to animations are processed separately diff --git a/src/rtextures.c b/src/rtextures.c index 6d3c21cf4..e81f05fe8 100644 --- a/src/rtextures.c +++ b/src/rtextures.c @@ -4988,8 +4988,6 @@ Vector3 ColorToHSV(Color color) return hsv; } - - // Get a Color from HSV values // Implementation reference: https://en.wikipedia.org/wiki/HSL_and_HSV#Alternative_HSV_conversion // NOTE: Color->HSV->Color conversion will not yield exactly the same color due to rounding errors diff --git a/src/utils.c b/src/utils.c index fcbdba005..c5d9748d4 100644 --- a/src/utils.c +++ b/src/utils.c @@ -76,7 +76,6 @@ void SetSaveFileDataCallback(SaveFileDataCallback callback) { saveFileData = cal void SetLoadFileTextCallback(LoadFileTextCallback callback) { loadFileText = callback; } // Set custom file text loader void SetSaveFileTextCallback(SaveFileTextCallback callback) { saveFileText = callback; } // Set custom file text saver - #if defined(PLATFORM_ANDROID) static AAssetManager *assetManager = NULL; // Android assets manager pointer static const char *internalDataPath = NULL; // Android internal data path From 454acca84be6fbdb8dd57ba848c80ba5f1981b73 Mon Sep 17 00:00:00 2001 From: Harald Scheirich Date: Thu, 10 Oct 2024 12:53:02 -0400 Subject: [PATCH 113/208] Some update to gltf loading (#4373) Only warns when there are more animations than currently implemented Allows mesh indices to be unsigned char --- src/rmodels.c | 46 +++++++++++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 19 deletions(-) diff --git a/src/rmodels.c b/src/rmodels.c index c9fa222eb..92be04fca 100644 --- a/src/rmodels.c +++ b/src/rmodels.c @@ -5226,17 +5226,19 @@ static Model LoadGLTF(const char *fileName) ***********************************************************************************************/ // Macro to simplify attributes loading code - #define LOAD_ATTRIBUTE(accesor, numComp, dataType, dstPtr) \ + #define LOAD_ATTRIBUTE(accesor, numComp, srcType, dstPtr) LOAD_ATTRIBUTE_CAST(accesor, numComp, srcType, dstPtr, srcType) + + #define LOAD_ATTRIBUTE_CAST(accesor, numComp, srcType, dstPtr, dstType) \ { \ int n = 0; \ - dataType *buffer = (dataType *)accesor->buffer_view->buffer->data + accesor->buffer_view->offset/sizeof(dataType) + accesor->offset/sizeof(dataType); \ + srcType *buffer = (srcType *)accesor->buffer_view->buffer->data + accesor->buffer_view->offset/sizeof(srcType) + accesor->offset/sizeof(srcType); \ for (unsigned int k = 0; k < accesor->count; k++) \ {\ for (int l = 0; l < numComp; l++) \ {\ - dstPtr[numComp*k + l] = buffer[n + l];\ + dstPtr[numComp*k + l] = (dstType)buffer[n + l];\ }\ - n += (int)(accesor->stride/sizeof(dataType));\ + n += (int)(accesor->stride/sizeof(srcType));\ }\ } @@ -5697,23 +5699,25 @@ static Model LoadGLTF(const char *fileName) // Load unsigned short data type into mesh.indices LOAD_ATTRIBUTE(attribute, 1, unsigned short, model.meshes[meshIndex].indices) } + else if (attribute->component_type == cgltf_component_type_r_8u) + { + // Init raylib mesh indices to copy glTF attribute data + model.meshes[meshIndex].indices = RL_MALLOC(attribute->count * sizeof(unsigned short)); + LOAD_ATTRIBUTE_CAST(attribute, 1, unsigned char, model.meshes[meshIndex].indices, unsigned short) + + } else if (attribute->component_type == cgltf_component_type_r_32u) { // Init raylib mesh indices to copy glTF attribute data model.meshes[meshIndex].indices = RL_MALLOC(attribute->count*sizeof(unsigned short)); - - // Load data into a temp buffer to be converted to raylib data type - unsigned int *temp = RL_MALLOC(attribute->count*sizeof(unsigned int)); - LOAD_ATTRIBUTE(attribute, 1, unsigned int, temp); - - // Convert data to raylib indices data type (unsigned short) - for (unsigned int d = 0; d < attribute->count; d++) model.meshes[meshIndex].indices[d] = (unsigned short)temp[d]; + LOAD_ATTRIBUTE_CAST(attribute, 1, unsigned int, model.meshes[meshIndex].indices, unsigned short); TRACELOG(LOG_WARNING, "MODEL: [%s] Indices data converted from u32 to u16, possible loss of data", fileName); - - RL_FREE(temp); } - else TRACELOG(LOG_WARNING, "MODEL: [%s] Indices data format not supported, use u16", fileName); + else + { + TRACELOG(LOG_WARNING, "MODEL: [%s] Indices data format not supported, use u16", fileName); + } } else model.meshes[meshIndex].triangleCount = model.meshes[meshIndex].vertexCount/3; // Unindexed mesh @@ -5745,7 +5749,7 @@ static Model LoadGLTF(const char *fileName) // - Only supports linear interpolation (default method in Blender when checked "Always Sample Animations" when exporting a GLTF file) // - Only supports translation/rotation/scale animation channel.path, weights not considered (i.e. morph targets) //---------------------------------------------------------------------------------------------------- - if (data->skins_count == 1) + if (data->skins_count > 0) { cgltf_skin skin = data->skins[0]; model.bones = LoadBoneInfoGLTF(skin, &model.boneCount); @@ -5765,9 +5769,9 @@ static Model LoadGLTF(const char *fileName) MatrixDecompose(worldMatrix, &(model.bindPose[i].translation), &(model.bindPose[i].rotation), &(model.bindPose[i].scale)); } } - else if (data->skins_count > 1) + if (data->skins_count > 1) { - TRACELOG(LOG_ERROR, "MODEL: [%s] can only load one skin (armature) per model, but gltf skins_count == %i", fileName, data->skins_count); + TRACELOG(LOG_WARNING, "MODEL: [%s] can only load one skin (armature) per model, but gltf skins_count == %i", fileName, data->skins_count); } meshIndex = 0; @@ -6088,7 +6092,7 @@ static ModelAnimation *LoadModelAnimationsGLTF(const char *fileName, int *animCo if (result == cgltf_result_success) { - if (data->skins_count == 1) + if (data->skins_count > 0) { cgltf_skin skin = data->skins[0]; *animCount = (int)data->animations_count; @@ -6223,7 +6227,11 @@ static ModelAnimation *LoadModelAnimationsGLTF(const char *fileName, int *animCo RL_FREE(boneChannels); } } - else TRACELOG(LOG_ERROR, "MODEL: [%s] expected exactly one skin to load animation data from, but found %i", fileName, data->skins_count); + + if (data->skins_count > 1) + { + TRACELOG(LOG_WARNING, "MODEL: [%s] expected exactly one skin to load animation data from, but found %i", fileName, data->skins_count); + } cgltf_free(data); } From c4be01329493d0e772a04de08639b4da32905d2a Mon Sep 17 00:00:00 2001 From: William Culver <39485061+cedeon@users.noreply.github.com> Date: Thu, 10 Oct 2024 17:56:29 +0100 Subject: [PATCH 114/208] Fix build.zig (#4374) --- src/build.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/build.zig b/src/build.zig index 71729e4d2..895896269 100644 --- a/src/build.zig +++ b/src/build.zig @@ -24,7 +24,7 @@ pub fn addRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std. .rshapes = options.rshapes, .rtext = options.rtext, .rtextures = options.rtextures, - .platform_drm = options.platform_drm, + .platform = options.platform, .shared = options.shared, .linux_display_backend = options.linux_display_backend, .opengl_version = options.opengl_version, From d3f86eb9573320f87b64882c8b9a33585d3133a7 Mon Sep 17 00:00:00 2001 From: Sage Hane Date: Thu, 10 Oct 2024 16:56:43 +0000 Subject: [PATCH 115/208] build.zig: Improve logic (#4375) * build.zig: Fix `@src` logic * build.zig: Clarify build error * build.zig: Add option for enabling `raygui` * build.zig: Expose `Options` type --- build.zig | 3 +++ src/build.zig | 41 +++++++++++++++++++++++------------------ 2 files changed, 26 insertions(+), 18 deletions(-) diff --git a/build.zig b/build.zig index 01e7b49fb..029482608 100644 --- a/build.zig +++ b/build.zig @@ -9,3 +9,6 @@ pub fn build(b: *std.Build) !void { // expose helper functions to user's build.zig pub const addRaylib = raylib.addRaylib; pub const addRaygui = raylib.addRaygui; + +// expose options for compiling +pub const RaylibOptions = raylib.Options; diff --git a/src/build.zig b/src/build.zig index 895896269..8944c7087 100644 --- a/src/build.zig +++ b/src/build.zig @@ -51,6 +51,10 @@ fn setDesktopPlatform(raylib: *std.Build.Step.Compile, platform: PlatformBackend } } +fn srcDir() []const u8 { + return std.fs.path.dirname(@src().file) orelse "."; +} + fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, options: Options) !*std.Build.Step.Compile { raylib_flags_arr.clearRetainingCapacity(); @@ -65,8 +69,7 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std. "-fno-sanitize=undefined", // https://github.com/raysan5/raylib/issues/3674 }); if (options.config) |config| { - const file = try std.fs.path.join(b.allocator, &.{ std.fs.path.dirname(@src().file) orelse ".", "config.h" }); - defer b.allocator.free(file); + const file = b.pathJoin(&.{ srcDir(), "config.h" }); const content = try std.fs.cwd().readFileAlloc(b.allocator, file, std.math.maxInt(usize)); defer b.allocator.free(content); @@ -115,7 +118,7 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std. // No GLFW required on PLATFORM_DRM if (options.platform != .drm) { - raylib.addIncludePath(b.path("src/external/glfw/include")); + raylib.addIncludePath(b.path(b.pathJoin(&.{ srcDir(), "external/glfw/include" }))); } var c_source_files = try std.ArrayList([]const u8).initCapacity(b.allocator, 2); @@ -168,17 +171,16 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std. if (options.linux_display_backend == .Wayland or options.linux_display_backend == .Both) { _ = b.findProgram(&.{"wayland-scanner"}, &.{}) catch { std.log.err( - \\ Wayland may not be installed on the system. + \\ `wayland-scanner` may not be installed on the system. \\ You can switch to X11 in your `build.zig` by changing `Options.linux_display_backend` , .{}); - @panic("No Wayland"); + @panic("`wayland-scanner` not found"); }; raylib.defineCMacro("_GLFW_WAYLAND", null); raylib.linkSystemLibrary("wayland-client"); raylib.linkSystemLibrary("wayland-cursor"); raylib.linkSystemLibrary("wayland-egl"); raylib.linkSystemLibrary("xkbcommon"); - raylib.addIncludePath(b.path("src")); waylandGenerate(b, raylib, "wayland.xml", "wayland-client-protocol"); waylandGenerate(b, raylib, "xdg-shell.xml", "xdg-shell-client-protocol"); waylandGenerate(b, raylib, "xdg-decoration-unstable-v1.xml", "xdg-decoration-unstable-v1-client-protocol"); @@ -229,7 +231,7 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std. // On macos rglfw.c include Objective-C files. try raylib_flags_arr.append(b.allocator, "-ObjC"); raylib.root_module.addCSourceFile(.{ - .file = b.path("src/rglfw.c"), + .file = b.path(b.pathJoin(&.{ srcDir(), "rglfw.c" })), .flags = raylib_flags_arr.items, }); _ = raylib_flags_arr.pop(); @@ -251,8 +253,7 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std. @panic("Pass '--sysroot \"$EMSDK/upstream/emscripten\"'"); } - const cache_include = std.fs.path.join(b.allocator, &.{ b.sysroot.?, "cache", "sysroot", "include" }) catch @panic("Out of memory"); - defer b.allocator.free(cache_include); + const cache_include = b.pathJoin(&.{ b.sysroot.?, "cache", "sysroot", "include" }); var dir = std.fs.openDirAbsolute(cache_include, std.fs.Dir.OpenDirOptions{ .access_sub_paths = true, .no_follow = true }) catch @panic("No emscripten cache. Generate it!"); dir.close(); @@ -263,9 +264,8 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std. }, } - raylib.addIncludePath(b.path("src")); raylib.root_module.addCSourceFiles(.{ - .root = b.path("src"), + .root = b.path(srcDir()), .files = c_source_files.items, .flags = raylib_flags_arr.items, }); @@ -358,6 +358,7 @@ pub fn build(b: *std.Build) !void { const options = Options{ .platform = b.option(PlatformBackend, "platform", "Choose the platform backedn for desktop target") orelse defaults.platform, .raudio = b.option(bool, "raudio", "Compile with audio support") orelse defaults.raudio, + .raygui = b.option(bool, "raygui", "Compile with raygui support") orelse defaults.raygui, .rmodels = b.option(bool, "rmodels", "Compile with models support") orelse defaults.rmodels, .rtext = b.option(bool, "rtext", "Compile with text support") orelse defaults.rtext, .rtextures = b.option(bool, "rtextures", "Compile with textures support") orelse defaults.rtextures, @@ -370,17 +371,21 @@ pub fn build(b: *std.Build) !void { const lib = try compileRaylib(b, target, optimize, options); - lib.installHeader(b.path("src/raylib.h"), "raylib.h"); - lib.installHeader(b.path("src/raymath.h"), "raymath.h"); - lib.installHeader(b.path("src/rlgl.h"), "rlgl.h"); + lib.installHeader(b.path(b.pathJoin(&.{ srcDir(), "raylib.h" })), "raylib.h"); + lib.installHeader(b.path(b.pathJoin(&.{ srcDir(), "raymath.h" })), "raymath.h"); + lib.installHeader(b.path(b.pathJoin(&.{ srcDir(), "rlgl.h" })), "rlgl.h"); b.installArtifact(lib); } -const waylandDir = "src/external/glfw/deps/wayland"; - -fn waylandGenerate(b: *std.Build, raylib: *std.Build.Step.Compile, comptime protocol: []const u8, comptime basename: []const u8) void { - const protocolDir = waylandDir ++ "/" ++ protocol; +fn waylandGenerate( + b: *std.Build, + raylib: *std.Build.Step.Compile, + comptime protocol: []const u8, + comptime basename: []const u8, +) void { + const waylandDir = b.pathJoin(&.{ srcDir(), "external/glfw/deps/wayland" }); + const protocolDir = b.pathJoin(&.{ waylandDir, protocol }); const clientHeader = basename ++ ".h"; const privateCode = basename ++ "-code.h"; From 1effe921291f5a260ef6e2841f0ed19ccb0c3e7c Mon Sep 17 00:00:00 2001 From: Ray Date: Thu, 10 Oct 2024 20:37:46 +0200 Subject: [PATCH 116/208] `WARNING`: REMOVED: SVG files loading and drawing, moving it to raylib-extras --- examples/Makefile | 1 - examples/Makefile.Web | 5 - examples/textures/resources/test.svg | 1 - examples/textures/textures_svg_loading.c | 72 - examples/textures/textures_svg_loading.png | Bin 13850 -> 0 bytes projects/VS2022/raylib.sln | 2 - src/config.h | 1 - src/external/nanosvg.h | 3053 -------------------- src/external/nanosvgrast.h | 1458 ---------- src/rtextures.c | 116 - 10 files changed, 4709 deletions(-) delete mode 100644 examples/textures/resources/test.svg delete mode 100644 examples/textures/textures_svg_loading.c delete mode 100644 examples/textures/textures_svg_loading.png delete mode 100644 src/external/nanosvg.h delete mode 100644 src/external/nanosvgrast.h diff --git a/examples/Makefile b/examples/Makefile index 01c8e45d7..65ee4fb80 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -549,7 +549,6 @@ TEXTURES = \ textures/textures_sprite_button \ textures/textures_sprite_explosion \ textures/textures_srcrec_dstrec \ - textures/textures_svg_loading \ textures/textures_textured_curve \ textures/textures_to_image diff --git a/examples/Makefile.Web b/examples/Makefile.Web index b176217ae..f6c8b785a 100644 --- a/examples/Makefile.Web +++ b/examples/Makefile.Web @@ -415,7 +415,6 @@ TEXTURES = \ textures/textures_sprite_button \ textures/textures_sprite_explosion \ textures/textures_srcrec_dstrec \ - textures/textures_svg_loading \ textures/textures_textured_curve \ textures/textures_to_image @@ -776,10 +775,6 @@ textures/textures_srcrec_dstrec: textures/textures_srcrec_dstrec.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \ --preload-file textures/resources/scarfy.png@resources/scarfy.png -textures/textures_svg_loading: textures/textures_svg_loading.c - $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \ - --preload-file textures/resources/test.svg - textures/textures_textured_curve: textures/textures_textured_curve.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \ --preload-file textures/resources/road.png@resources/road.png diff --git a/examples/textures/resources/test.svg b/examples/textures/resources/test.svg deleted file mode 100644 index 3d9bbb113..000000000 --- a/examples/textures/resources/test.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/examples/textures/textures_svg_loading.c b/examples/textures/textures_svg_loading.c deleted file mode 100644 index 434ec7602..000000000 --- a/examples/textures/textures_svg_loading.c +++ /dev/null @@ -1,72 +0,0 @@ -/******************************************************************************************* -* -* raylib [textures] example - SVG loading and texture creation -* -* NOTE: Images are loaded in CPU memory (RAM); textures are loaded in GPU memory (VRAM) -* -* Example originally created with raylib 4.2, last time updated with raylib 4.2 -* -* Example 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) 2022 Dennis Meinen (@bixxy#4258 on Discord) -* -********************************************************************************************/ - -#include "raylib.h" - -//------------------------------------------------------------------------------------ -// Program main entry point -//------------------------------------------------------------------------------------ -int main(void) -{ - // Initialization - //-------------------------------------------------------------------------------------- - const int screenWidth = 800; - const int screenHeight = 450; - - InitWindow(screenWidth, screenHeight, "raylib [textures] example - svg loading"); - - // NOTE: Textures MUST be loaded after Window initialization (OpenGL context is required) - - Image image = LoadImageSvg("resources/test.svg", 400, 350); // Loaded in CPU memory (RAM) - Texture2D texture = LoadTextureFromImage(image); // Image converted to texture, GPU memory (VRAM) - UnloadImage(image); // Once image has been converted to texture and uploaded to VRAM, it can be unloaded from RAM - - SetTargetFPS(60); // Set our game to run at 60 frames-per-second - //--------------------------------------------------------------------------------------- - - // Main game loop - while (!WindowShouldClose()) // Detect window close button or ESC key - { - // Update - //---------------------------------------------------------------------------------- - // TODO: Update your variables here - //---------------------------------------------------------------------------------- - - // Draw - //---------------------------------------------------------------------------------- - BeginDrawing(); - - ClearBackground(RAYWHITE); - - DrawTexture(texture, screenWidth/2 - texture.width/2, screenHeight/2 - texture.height/2, WHITE); - - //Red border to illustrate how the SVG is centered within the specified dimensions - DrawRectangleLines((screenWidth / 2 - texture.width / 2) - 1, (screenHeight / 2 - texture.height / 2) - 1, texture.width + 2, texture.height + 2, RED); - - DrawText("this IS a texture loaded from an SVG file!", 300, 410, 10, GRAY); - - EndDrawing(); - //---------------------------------------------------------------------------------- - } - - // De-Initialization - //-------------------------------------------------------------------------------------- - UnloadTexture(texture); // Texture unloading - - CloseWindow(); // Close window and OpenGL context - //-------------------------------------------------------------------------------------- - - return 0; -} \ No newline at end of file diff --git a/examples/textures/textures_svg_loading.png b/examples/textures/textures_svg_loading.png deleted file mode 100644 index fa98605fa8508a068537defae8a8fc960a6a6c08..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13850 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, image->height); - // Use... - for (NSVGshape *shape = image->shapes; shape != NULL; shape = shape->next) { - for (NSVGpath *path = shape->paths; path != NULL; path = path->next) { - for (int i = 0; i < path->npts-1; i += 3) { - float* p = &path->pts[i*2]; - drawCubicBez(p[0],p[1], p[2],p[3], p[4],p[5], p[6],p[7]); - } - } - } - // Delete - nsvgDelete(image); -*/ - -enum NSVGpaintType { - NSVG_PAINT_NONE = 0, - NSVG_PAINT_COLOR = 1, - NSVG_PAINT_LINEAR_GRADIENT = 2, - NSVG_PAINT_RADIAL_GRADIENT = 3 -}; - -enum NSVGspreadType { - NSVG_SPREAD_PAD = 0, - NSVG_SPREAD_REFLECT = 1, - NSVG_SPREAD_REPEAT = 2 -}; - -enum NSVGlineJoin { - NSVG_JOIN_MITER = 0, - NSVG_JOIN_ROUND = 1, - NSVG_JOIN_BEVEL = 2 -}; - -enum NSVGlineCap { - NSVG_CAP_BUTT = 0, - NSVG_CAP_ROUND = 1, - NSVG_CAP_SQUARE = 2 -}; - -enum NSVGfillRule { - NSVG_FILLRULE_NONZERO = 0, - NSVG_FILLRULE_EVENODD = 1 -}; - -enum NSVGflags { - NSVG_FLAGS_VISIBLE = 0x01 -}; - -typedef struct NSVGgradientStop { - unsigned int color; - float offset; -} NSVGgradientStop; - -typedef struct NSVGgradient { - float xform[6]; - char spread; - float fx, fy; - int nstops; - NSVGgradientStop stops[1]; -} NSVGgradient; - -typedef struct NSVGpaint { - char type; - union { - unsigned int color; - NSVGgradient* gradient; - }; -} NSVGpaint; - -typedef struct NSVGpath -{ - float* pts; // Cubic bezier points: x0,y0, [cpx1,cpx1,cpx2,cpy2,x1,y1], ... - int npts; // Total number of bezier points. - char closed; // Flag indicating if shapes should be treated as closed. - float bounds[4]; // Tight bounding box of the shape [minx,miny,maxx,maxy]. - struct NSVGpath* next; // Pointer to next path, or NULL if last element. -} NSVGpath; - -typedef struct NSVGshape -{ - char id[64]; // Optional 'id' attr of the shape or its group - NSVGpaint fill; // Fill paint - NSVGpaint stroke; // Stroke paint - float opacity; // Opacity of the shape. - float strokeWidth; // Stroke width (scaled). - float strokeDashOffset; // Stroke dash offset (scaled). - float strokeDashArray[8]; // Stroke dash array (scaled). - char strokeDashCount; // Number of dash values in dash array. - char strokeLineJoin; // Stroke join type. - char strokeLineCap; // Stroke cap type. - float miterLimit; // Miter limit - char fillRule; // Fill rule, see NSVGfillRule. - unsigned char flags; // Logical or of NSVG_FLAGS_* flags - float bounds[4]; // Tight bounding box of the shape [minx,miny,maxx,maxy]. - NSVGpath* paths; // Linked list of paths in the image. - struct NSVGshape* next; // Pointer to next shape, or NULL if last element. -} NSVGshape; - -typedef struct NSVGimage -{ - float width; // Width of the image. - float height; // Height of the image. - NSVGshape* shapes; // Linked list of shapes in the image. -} NSVGimage; - -// Parses SVG file from a file, returns SVG image as paths. -NSVGimage* nsvgParseFromFile(const char* filename, const char* units, float dpi); - -// Parses SVG file from a null terminated string, returns SVG image as paths. -// Important note: changes the string. -NSVGimage* nsvgParse(char* input, const char* units, float dpi); - -// Duplicates a path. -NSVGpath* nsvgDuplicatePath(NSVGpath* p); - -// Deletes an image. -void nsvgDelete(NSVGimage* image); - -#ifndef NANOSVG_CPLUSPLUS -#ifdef __cplusplus -} -#endif -#endif - -#ifdef NANOSVG_IMPLEMENTATION - -#include -#include -#include -#include - -#define NSVG_PI (3.14159265358979323846264338327f) -#define NSVG_KAPPA90 (0.5522847493f) // Length proportional to radius of a cubic bezier handle for 90deg arcs. - -#define NSVG_ALIGN_MIN 0 -#define NSVG_ALIGN_MID 1 -#define NSVG_ALIGN_MAX 2 -#define NSVG_ALIGN_NONE 0 -#define NSVG_ALIGN_MEET 1 -#define NSVG_ALIGN_SLICE 2 - -#define NSVG_NOTUSED(v) do { (void)(1 ? (void)0 : ( (void)(v) ) ); } while(0) -#define NSVG_RGB(r, g, b) (((unsigned int)r) | ((unsigned int)g << 8) | ((unsigned int)b << 16)) - -#ifdef _MSC_VER - #pragma warning (disable: 4996) // Switch off security warnings - #pragma warning (disable: 4100) // Switch off unreferenced formal parameter warnings - #ifdef __cplusplus - #define NSVG_INLINE inline - #else - #define NSVG_INLINE - #endif -#else - #define NSVG_INLINE inline -#endif - - -static int nsvg__isspace(char c) -{ - return strchr(" \t\n\v\f\r", c) != 0; -} - -static int nsvg__isdigit(char c) -{ - return c >= '0' && c <= '9'; -} - -static NSVG_INLINE float nsvg__minf(float a, float b) { return a < b ? a : b; } -static NSVG_INLINE float nsvg__maxf(float a, float b) { return a > b ? a : b; } - - -// Simple XML parser - -#define NSVG_XML_TAG 1 -#define NSVG_XML_CONTENT 2 -#define NSVG_XML_MAX_ATTRIBS 256 - -static void nsvg__parseContent(char* s, - void (*contentCb)(void* ud, const char* s), - void* ud) -{ - // Trim start white spaces - while (*s && nsvg__isspace(*s)) s++; - if (!*s) return; - - if (contentCb) - (*contentCb)(ud, s); -} - -static void nsvg__parseElement(char* s, - void (*startelCb)(void* ud, const char* el, const char** attr), - void (*endelCb)(void* ud, const char* el), - void* ud) -{ - const char* attr[NSVG_XML_MAX_ATTRIBS]; - int nattr = 0; - char* name; - int start = 0; - int end = 0; - char quote; - - // Skip white space after the '<' - while (*s && nsvg__isspace(*s)) s++; - - // Check if the tag is end tag - if (*s == '/') { - s++; - end = 1; - } else { - start = 1; - } - - // Skip comments, data and preprocessor stuff. - if (!*s || *s == '?' || *s == '!') - return; - - // Get tag name - name = s; - while (*s && !nsvg__isspace(*s)) s++; - if (*s) { *s++ = '\0'; } - - // Get attribs - while (!end && *s && nattr < NSVG_XML_MAX_ATTRIBS-3) { - char* name = NULL; - char* value = NULL; - - // Skip white space before the attrib name - while (*s && nsvg__isspace(*s)) s++; - if (!*s) break; - if (*s == '/') { - end = 1; - break; - } - name = s; - // Find end of the attrib name. - while (*s && !nsvg__isspace(*s) && *s != '=') s++; - if (*s) { *s++ = '\0'; } - // Skip until the beginning of the value. - while (*s && *s != '\"' && *s != '\'') s++; - if (!*s) break; - quote = *s; - s++; - // Store value and find the end of it. - value = s; - while (*s && *s != quote) s++; - if (*s) { *s++ = '\0'; } - - // Store only well formed attributes - if (name && value) { - attr[nattr++] = name; - attr[nattr++] = value; - } - } - - // List terminator - attr[nattr++] = 0; - attr[nattr++] = 0; - - // Call callbacks. - if (start && startelCb) - (*startelCb)(ud, name, attr); - if (end && endelCb) - (*endelCb)(ud, name); -} - -int nsvg__parseXML(char* input, - void (*startelCb)(void* ud, const char* el, const char** attr), - void (*endelCb)(void* ud, const char* el), - void (*contentCb)(void* ud, const char* s), - void* ud) -{ - char* s = input; - char* mark = s; - int state = NSVG_XML_CONTENT; - while (*s) { - if (*s == '<' && state == NSVG_XML_CONTENT) { - // Start of a tag - *s++ = '\0'; - nsvg__parseContent(mark, contentCb, ud); - mark = s; - state = NSVG_XML_TAG; - } else if (*s == '>' && state == NSVG_XML_TAG) { - // Start of a content or new tag. - *s++ = '\0'; - nsvg__parseElement(mark, startelCb, endelCb, ud); - mark = s; - state = NSVG_XML_CONTENT; - } else { - s++; - } - } - - return 1; -} - - -/* Simple SVG parser. */ - -#define NSVG_MAX_ATTR 128 - -enum NSVGgradientUnits { - NSVG_USER_SPACE = 0, - NSVG_OBJECT_SPACE = 1 -}; - -#define NSVG_MAX_DASHES 8 - -enum NSVGunits { - NSVG_UNITS_USER, - NSVG_UNITS_PX, - NSVG_UNITS_PT, - NSVG_UNITS_PC, - NSVG_UNITS_MM, - NSVG_UNITS_CM, - NSVG_UNITS_IN, - NSVG_UNITS_PERCENT, - NSVG_UNITS_EM, - NSVG_UNITS_EX -}; - -typedef struct NSVGcoordinate { - float value; - int units; -} NSVGcoordinate; - -typedef struct NSVGlinearData { - NSVGcoordinate x1, y1, x2, y2; -} NSVGlinearData; - -typedef struct NSVGradialData { - NSVGcoordinate cx, cy, r, fx, fy; -} NSVGradialData; - -typedef struct NSVGgradientData -{ - char id[64]; - char ref[64]; - char type; - union { - NSVGlinearData linear; - NSVGradialData radial; - }; - char spread; - char units; - float xform[6]; - int nstops; - NSVGgradientStop* stops; - struct NSVGgradientData* next; -} NSVGgradientData; - -typedef struct NSVGattrib -{ - char id[64]; - float xform[6]; - unsigned int fillColor; - unsigned int strokeColor; - float opacity; - float fillOpacity; - float strokeOpacity; - char fillGradient[64]; - char strokeGradient[64]; - float strokeWidth; - float strokeDashOffset; - float strokeDashArray[NSVG_MAX_DASHES]; - int strokeDashCount; - char strokeLineJoin; - char strokeLineCap; - float miterLimit; - char fillRule; - float fontSize; - unsigned int stopColor; - float stopOpacity; - float stopOffset; - char hasFill; - char hasStroke; - char visible; -} NSVGattrib; - -typedef struct NSVGparser -{ - NSVGattrib attr[NSVG_MAX_ATTR]; - int attrHead; - float* pts; - int npts; - int cpts; - NSVGpath* plist; - NSVGimage* image; - NSVGgradientData* gradients; - NSVGshape* shapesTail; - float viewMinx, viewMiny, viewWidth, viewHeight; - int alignX, alignY, alignType; - float dpi; - char pathFlag; - char defsFlag; -} NSVGparser; - -static void nsvg__xformIdentity(float* t) -{ - t[0] = 1.0f; t[1] = 0.0f; - t[2] = 0.0f; t[3] = 1.0f; - t[4] = 0.0f; t[5] = 0.0f; -} - -static void nsvg__xformSetTranslation(float* t, float tx, float ty) -{ - t[0] = 1.0f; t[1] = 0.0f; - t[2] = 0.0f; t[3] = 1.0f; - t[4] = tx; t[5] = ty; -} - -static void nsvg__xformSetScale(float* t, float sx, float sy) -{ - t[0] = sx; t[1] = 0.0f; - t[2] = 0.0f; t[3] = sy; - t[4] = 0.0f; t[5] = 0.0f; -} - -static void nsvg__xformSetSkewX(float* t, float a) -{ - t[0] = 1.0f; t[1] = 0.0f; - t[2] = tanf(a); t[3] = 1.0f; - t[4] = 0.0f; t[5] = 0.0f; -} - -static void nsvg__xformSetSkewY(float* t, float a) -{ - t[0] = 1.0f; t[1] = tanf(a); - t[2] = 0.0f; t[3] = 1.0f; - t[4] = 0.0f; t[5] = 0.0f; -} - -static void nsvg__xformSetRotation(float* t, float a) -{ - float cs = cosf(a), sn = sinf(a); - t[0] = cs; t[1] = sn; - t[2] = -sn; t[3] = cs; - t[4] = 0.0f; t[5] = 0.0f; -} - -static void nsvg__xformMultiply(float* t, float* s) -{ - float t0 = t[0] * s[0] + t[1] * s[2]; - float t2 = t[2] * s[0] + t[3] * s[2]; - float t4 = t[4] * s[0] + t[5] * s[2] + s[4]; - t[1] = t[0] * s[1] + t[1] * s[3]; - t[3] = t[2] * s[1] + t[3] * s[3]; - t[5] = t[4] * s[1] + t[5] * s[3] + s[5]; - t[0] = t0; - t[2] = t2; - t[4] = t4; -} - -static void nsvg__xformInverse(float* inv, float* t) -{ - double invdet, det = (double)t[0] * t[3] - (double)t[2] * t[1]; - if (det > -1e-6 && det < 1e-6) { - nsvg__xformIdentity(t); - return; - } - invdet = 1.0 / det; - inv[0] = (float)(t[3] * invdet); - inv[2] = (float)(-t[2] * invdet); - inv[4] = (float)(((double)t[2] * t[5] - (double)t[3] * t[4]) * invdet); - inv[1] = (float)(-t[1] * invdet); - inv[3] = (float)(t[0] * invdet); - inv[5] = (float)(((double)t[1] * t[4] - (double)t[0] * t[5]) * invdet); -} - -static void nsvg__xformPremultiply(float* t, float* s) -{ - float s2[6]; - memcpy(s2, s, sizeof(float)*6); - nsvg__xformMultiply(s2, t); - memcpy(t, s2, sizeof(float)*6); -} - -static void nsvg__xformPoint(float* dx, float* dy, float x, float y, float* t) -{ - *dx = x*t[0] + y*t[2] + t[4]; - *dy = x*t[1] + y*t[3] + t[5]; -} - -static void nsvg__xformVec(float* dx, float* dy, float x, float y, float* t) -{ - *dx = x*t[0] + y*t[2]; - *dy = x*t[1] + y*t[3]; -} - -#define NSVG_EPSILON (1e-12) - -static int nsvg__ptInBounds(float* pt, float* bounds) -{ - return pt[0] >= bounds[0] && pt[0] <= bounds[2] && pt[1] >= bounds[1] && pt[1] <= bounds[3]; -} - - -static double nsvg__evalBezier(double t, double p0, double p1, double p2, double p3) -{ - double it = 1.0-t; - return it*it*it*p0 + 3.0*it*it*t*p1 + 3.0*it*t*t*p2 + t*t*t*p3; -} - -static void nsvg__curveBounds(float* bounds, float* curve) -{ - int i, j, count; - double roots[2], a, b, c, b2ac, t, v; - float* v0 = &curve[0]; - float* v1 = &curve[2]; - float* v2 = &curve[4]; - float* v3 = &curve[6]; - - // Start the bounding box by end points - bounds[0] = nsvg__minf(v0[0], v3[0]); - bounds[1] = nsvg__minf(v0[1], v3[1]); - bounds[2] = nsvg__maxf(v0[0], v3[0]); - bounds[3] = nsvg__maxf(v0[1], v3[1]); - - // Bezier curve fits inside the convex hull of it's control points. - // If control points are inside the bounds, we're done. - if (nsvg__ptInBounds(v1, bounds) && nsvg__ptInBounds(v2, bounds)) - return; - - // Add bezier curve inflection points in X and Y. - for (i = 0; i < 2; i++) { - a = -3.0 * v0[i] + 9.0 * v1[i] - 9.0 * v2[i] + 3.0 * v3[i]; - b = 6.0 * v0[i] - 12.0 * v1[i] + 6.0 * v2[i]; - c = 3.0 * v1[i] - 3.0 * v0[i]; - count = 0; - if (fabs(a) < NSVG_EPSILON) { - if (fabs(b) > NSVG_EPSILON) { - t = -c / b; - if (t > NSVG_EPSILON && t < 1.0-NSVG_EPSILON) - roots[count++] = t; - } - } else { - b2ac = b*b - 4.0*c*a; - if (b2ac > NSVG_EPSILON) { - t = (-b + sqrt(b2ac)) / (2.0 * a); - if (t > NSVG_EPSILON && t < 1.0-NSVG_EPSILON) - roots[count++] = t; - t = (-b - sqrt(b2ac)) / (2.0 * a); - if (t > NSVG_EPSILON && t < 1.0-NSVG_EPSILON) - roots[count++] = t; - } - } - for (j = 0; j < count; j++) { - v = nsvg__evalBezier(roots[j], v0[i], v1[i], v2[i], v3[i]); - bounds[0+i] = nsvg__minf(bounds[0+i], (float)v); - bounds[2+i] = nsvg__maxf(bounds[2+i], (float)v); - } - } -} - -static NSVGparser* nsvg__createParser(void) -{ - NSVGparser* p; - p = (NSVGparser*)malloc(sizeof(NSVGparser)); - if (p == NULL) goto error; - memset(p, 0, sizeof(NSVGparser)); - - p->image = (NSVGimage*)malloc(sizeof(NSVGimage)); - if (p->image == NULL) goto error; - memset(p->image, 0, sizeof(NSVGimage)); - - // Init style - nsvg__xformIdentity(p->attr[0].xform); - memset(p->attr[0].id, 0, sizeof p->attr[0].id); - p->attr[0].fillColor = NSVG_RGB(0,0,0); - p->attr[0].strokeColor = NSVG_RGB(0,0,0); - p->attr[0].opacity = 1; - p->attr[0].fillOpacity = 1; - p->attr[0].strokeOpacity = 1; - p->attr[0].stopOpacity = 1; - p->attr[0].strokeWidth = 1; - p->attr[0].strokeLineJoin = NSVG_JOIN_MITER; - p->attr[0].strokeLineCap = NSVG_CAP_BUTT; - p->attr[0].miterLimit = 4; - p->attr[0].fillRule = NSVG_FILLRULE_NONZERO; - p->attr[0].hasFill = 1; - p->attr[0].visible = 1; - - return p; - -error: - if (p) { - if (p->image) free(p->image); - free(p); - } - return NULL; -} - -static void nsvg__deletePaths(NSVGpath* path) -{ - while (path) { - NSVGpath *next = path->next; - if (path->pts != NULL) - free(path->pts); - free(path); - path = next; - } -} - -static void nsvg__deletePaint(NSVGpaint* paint) -{ - if (paint->type == NSVG_PAINT_LINEAR_GRADIENT || paint->type == NSVG_PAINT_RADIAL_GRADIENT) - free(paint->gradient); -} - -static void nsvg__deleteGradientData(NSVGgradientData* grad) -{ - NSVGgradientData* next; - while (grad != NULL) { - next = grad->next; - free(grad->stops); - free(grad); - grad = next; - } -} - -static void nsvg__deleteParser(NSVGparser* p) -{ - if (p != NULL) { - nsvg__deletePaths(p->plist); - nsvg__deleteGradientData(p->gradients); - nsvgDelete(p->image); - free(p->pts); - free(p); - } -} - -static void nsvg__resetPath(NSVGparser* p) -{ - p->npts = 0; -} - -static void nsvg__addPoint(NSVGparser* p, float x, float y) -{ - if (p->npts+1 > p->cpts) { - p->cpts = p->cpts ? p->cpts*2 : 8; - p->pts = (float*)realloc(p->pts, p->cpts*2*sizeof(float)); - if (!p->pts) return; - } - p->pts[p->npts*2+0] = x; - p->pts[p->npts*2+1] = y; - p->npts++; -} - -static void nsvg__moveTo(NSVGparser* p, float x, float y) -{ - if (p->npts > 0) { - p->pts[(p->npts-1)*2+0] = x; - p->pts[(p->npts-1)*2+1] = y; - } else { - nsvg__addPoint(p, x, y); - } -} - -static void nsvg__lineTo(NSVGparser* p, float x, float y) -{ - float px,py, dx,dy; - if (p->npts > 0) { - px = p->pts[(p->npts-1)*2+0]; - py = p->pts[(p->npts-1)*2+1]; - dx = x - px; - dy = y - py; - nsvg__addPoint(p, px + dx/3.0f, py + dy/3.0f); - nsvg__addPoint(p, x - dx/3.0f, y - dy/3.0f); - nsvg__addPoint(p, x, y); - } -} - -static void nsvg__cubicBezTo(NSVGparser* p, float cpx1, float cpy1, float cpx2, float cpy2, float x, float y) -{ - if (p->npts > 0) { - nsvg__addPoint(p, cpx1, cpy1); - nsvg__addPoint(p, cpx2, cpy2); - nsvg__addPoint(p, x, y); - } -} - -static NSVGattrib* nsvg__getAttr(NSVGparser* p) -{ - return &p->attr[p->attrHead]; -} - -static void nsvg__pushAttr(NSVGparser* p) -{ - if (p->attrHead < NSVG_MAX_ATTR-1) { - p->attrHead++; - memcpy(&p->attr[p->attrHead], &p->attr[p->attrHead-1], sizeof(NSVGattrib)); - } -} - -static void nsvg__popAttr(NSVGparser* p) -{ - if (p->attrHead > 0) - p->attrHead--; -} - -static float nsvg__actualOrigX(NSVGparser* p) -{ - return p->viewMinx; -} - -static float nsvg__actualOrigY(NSVGparser* p) -{ - return p->viewMiny; -} - -static float nsvg__actualWidth(NSVGparser* p) -{ - return p->viewWidth; -} - -static float nsvg__actualHeight(NSVGparser* p) -{ - return p->viewHeight; -} - -static float nsvg__actualLength(NSVGparser* p) -{ - float w = nsvg__actualWidth(p), h = nsvg__actualHeight(p); - return sqrtf(w*w + h*h) / sqrtf(2.0f); -} - -static float nsvg__convertToPixels(NSVGparser* p, NSVGcoordinate c, float orig, float length) -{ - NSVGattrib* attr = nsvg__getAttr(p); - switch (c.units) { - case NSVG_UNITS_USER: return c.value; - case NSVG_UNITS_PX: return c.value; - case NSVG_UNITS_PT: return c.value / 72.0f * p->dpi; - case NSVG_UNITS_PC: return c.value / 6.0f * p->dpi; - case NSVG_UNITS_MM: return c.value / 25.4f * p->dpi; - case NSVG_UNITS_CM: return c.value / 2.54f * p->dpi; - case NSVG_UNITS_IN: return c.value * p->dpi; - case NSVG_UNITS_EM: return c.value * attr->fontSize; - case NSVG_UNITS_EX: return c.value * attr->fontSize * 0.52f; // x-height of Helvetica. - case NSVG_UNITS_PERCENT: return orig + c.value / 100.0f * length; - default: return c.value; - } - return c.value; -} - -static NSVGgradientData* nsvg__findGradientData(NSVGparser* p, const char* id) -{ - NSVGgradientData* grad = p->gradients; - if (id == NULL || *id == '\0') - return NULL; - while (grad != NULL) { - if (strcmp(grad->id, id) == 0) - return grad; - grad = grad->next; - } - return NULL; -} - -static NSVGgradient* nsvg__createGradient(NSVGparser* p, const char* id, const float* localBounds, char* paintType) -{ - NSVGattrib* attr = nsvg__getAttr(p); - NSVGgradientData* data = NULL; - NSVGgradientData* ref = NULL; - NSVGgradientStop* stops = NULL; - NSVGgradient* grad; - float ox, oy, sw, sh, sl; - int nstops = 0; - int refIter; - - data = nsvg__findGradientData(p, id); - if (data == NULL) return NULL; - - // TODO: use ref to fill in all unset values too. - ref = data; - refIter = 0; - while (ref != NULL) { - NSVGgradientData* nextRef = NULL; - if (stops == NULL && ref->stops != NULL) { - stops = ref->stops; - nstops = ref->nstops; - break; - } - nextRef = nsvg__findGradientData(p, ref->ref); - if (nextRef == ref) break; // prevent infite loops on malformed data - ref = nextRef; - refIter++; - if (refIter > 32) break; // prevent infite loops on malformed data - } - if (stops == NULL) return NULL; - - grad = (NSVGgradient*)malloc(sizeof(NSVGgradient) + sizeof(NSVGgradientStop)*(nstops-1)); - if (grad == NULL) return NULL; - - // The shape width and height. - if (data->units == NSVG_OBJECT_SPACE) { - ox = localBounds[0]; - oy = localBounds[1]; - sw = localBounds[2] - localBounds[0]; - sh = localBounds[3] - localBounds[1]; - } else { - ox = nsvg__actualOrigX(p); - oy = nsvg__actualOrigY(p); - sw = nsvg__actualWidth(p); - sh = nsvg__actualHeight(p); - } - sl = sqrtf(sw*sw + sh*sh) / sqrtf(2.0f); - - if (data->type == NSVG_PAINT_LINEAR_GRADIENT) { - float x1, y1, x2, y2, dx, dy; - x1 = nsvg__convertToPixels(p, data->linear.x1, ox, sw); - y1 = nsvg__convertToPixels(p, data->linear.y1, oy, sh); - x2 = nsvg__convertToPixels(p, data->linear.x2, ox, sw); - y2 = nsvg__convertToPixels(p, data->linear.y2, oy, sh); - // Calculate transform aligned to the line - dx = x2 - x1; - dy = y2 - y1; - grad->xform[0] = dy; grad->xform[1] = -dx; - grad->xform[2] = dx; grad->xform[3] = dy; - grad->xform[4] = x1; grad->xform[5] = y1; - } else { - float cx, cy, fx, fy, r; - cx = nsvg__convertToPixels(p, data->radial.cx, ox, sw); - cy = nsvg__convertToPixels(p, data->radial.cy, oy, sh); - fx = nsvg__convertToPixels(p, data->radial.fx, ox, sw); - fy = nsvg__convertToPixels(p, data->radial.fy, oy, sh); - r = nsvg__convertToPixels(p, data->radial.r, 0, sl); - // Calculate transform aligned to the circle - grad->xform[0] = r; grad->xform[1] = 0; - grad->xform[2] = 0; grad->xform[3] = r; - grad->xform[4] = cx; grad->xform[5] = cy; - grad->fx = fx / r; - grad->fy = fy / r; - } - - nsvg__xformMultiply(grad->xform, data->xform); - nsvg__xformMultiply(grad->xform, attr->xform); - - grad->spread = data->spread; - memcpy(grad->stops, stops, nstops*sizeof(NSVGgradientStop)); - grad->nstops = nstops; - - *paintType = data->type; - - return grad; -} - -static float nsvg__getAverageScale(float* t) -{ - float sx = sqrtf(t[0]*t[0] + t[2]*t[2]); - float sy = sqrtf(t[1]*t[1] + t[3]*t[3]); - return (sx + sy) * 0.5f; -} - -static void nsvg__getLocalBounds(float* bounds, NSVGshape *shape, float* xform) -{ - NSVGpath* path; - float curve[4*2], curveBounds[4]; - int i, first = 1; - for (path = shape->paths; path != NULL; path = path->next) { - nsvg__xformPoint(&curve[0], &curve[1], path->pts[0], path->pts[1], xform); - for (i = 0; i < path->npts-1; i += 3) { - nsvg__xformPoint(&curve[2], &curve[3], path->pts[(i+1)*2], path->pts[(i+1)*2+1], xform); - nsvg__xformPoint(&curve[4], &curve[5], path->pts[(i+2)*2], path->pts[(i+2)*2+1], xform); - nsvg__xformPoint(&curve[6], &curve[7], path->pts[(i+3)*2], path->pts[(i+3)*2+1], xform); - nsvg__curveBounds(curveBounds, curve); - if (first) { - bounds[0] = curveBounds[0]; - bounds[1] = curveBounds[1]; - bounds[2] = curveBounds[2]; - bounds[3] = curveBounds[3]; - first = 0; - } else { - bounds[0] = nsvg__minf(bounds[0], curveBounds[0]); - bounds[1] = nsvg__minf(bounds[1], curveBounds[1]); - bounds[2] = nsvg__maxf(bounds[2], curveBounds[2]); - bounds[3] = nsvg__maxf(bounds[3], curveBounds[3]); - } - curve[0] = curve[6]; - curve[1] = curve[7]; - } - } -} - -static void nsvg__addShape(NSVGparser* p) -{ - NSVGattrib* attr = nsvg__getAttr(p); - float scale = 1.0f; - NSVGshape* shape; - NSVGpath* path; - int i; - - if (p->plist == NULL) - return; - - shape = (NSVGshape*)malloc(sizeof(NSVGshape)); - if (shape == NULL) goto error; - memset(shape, 0, sizeof(NSVGshape)); - - memcpy(shape->id, attr->id, sizeof shape->id); - scale = nsvg__getAverageScale(attr->xform); - shape->strokeWidth = attr->strokeWidth * scale; - shape->strokeDashOffset = attr->strokeDashOffset * scale; - shape->strokeDashCount = (char)attr->strokeDashCount; - for (i = 0; i < attr->strokeDashCount; i++) - shape->strokeDashArray[i] = attr->strokeDashArray[i] * scale; - shape->strokeLineJoin = attr->strokeLineJoin; - shape->strokeLineCap = attr->strokeLineCap; - shape->miterLimit = attr->miterLimit; - shape->fillRule = attr->fillRule; - shape->opacity = attr->opacity; - - shape->paths = p->plist; - p->plist = NULL; - - // Calculate shape bounds - shape->bounds[0] = shape->paths->bounds[0]; - shape->bounds[1] = shape->paths->bounds[1]; - shape->bounds[2] = shape->paths->bounds[2]; - shape->bounds[3] = shape->paths->bounds[3]; - for (path = shape->paths->next; path != NULL; path = path->next) { - shape->bounds[0] = nsvg__minf(shape->bounds[0], path->bounds[0]); - shape->bounds[1] = nsvg__minf(shape->bounds[1], path->bounds[1]); - shape->bounds[2] = nsvg__maxf(shape->bounds[2], path->bounds[2]); - shape->bounds[3] = nsvg__maxf(shape->bounds[3], path->bounds[3]); - } - - // Set fill - if (attr->hasFill == 0) { - shape->fill.type = NSVG_PAINT_NONE; - } else if (attr->hasFill == 1) { - shape->fill.type = NSVG_PAINT_COLOR; - shape->fill.color = attr->fillColor; - shape->fill.color |= (unsigned int)(attr->fillOpacity*255) << 24; - } else if (attr->hasFill == 2) { - float inv[6], localBounds[4]; - nsvg__xformInverse(inv, attr->xform); - nsvg__getLocalBounds(localBounds, shape, inv); - shape->fill.gradient = nsvg__createGradient(p, attr->fillGradient, localBounds, &shape->fill.type); - if (shape->fill.gradient == NULL) { - shape->fill.type = NSVG_PAINT_NONE; - } - } - - // Set stroke - if (attr->hasStroke == 0) { - shape->stroke.type = NSVG_PAINT_NONE; - } else if (attr->hasStroke == 1) { - shape->stroke.type = NSVG_PAINT_COLOR; - shape->stroke.color = attr->strokeColor; - shape->stroke.color |= (unsigned int)(attr->strokeOpacity*255) << 24; - } else if (attr->hasStroke == 2) { - float inv[6], localBounds[4]; - nsvg__xformInverse(inv, attr->xform); - nsvg__getLocalBounds(localBounds, shape, inv); - shape->stroke.gradient = nsvg__createGradient(p, attr->strokeGradient, localBounds, &shape->stroke.type); - if (shape->stroke.gradient == NULL) - shape->stroke.type = NSVG_PAINT_NONE; - } - - // Set flags - shape->flags = (attr->visible ? NSVG_FLAGS_VISIBLE : 0x00); - - // Add to tail - if (p->image->shapes == NULL) - p->image->shapes = shape; - else - p->shapesTail->next = shape; - p->shapesTail = shape; - - return; - -error: - if (shape) free(shape); -} - -static void nsvg__addPath(NSVGparser* p, char closed) -{ - NSVGattrib* attr = nsvg__getAttr(p); - NSVGpath* path = NULL; - float bounds[4]; - float* curve; - int i; - - if (p->npts < 4) - return; - - if (closed) - nsvg__lineTo(p, p->pts[0], p->pts[1]); - - // Expect 1 + N*3 points (N = number of cubic bezier segments). - if ((p->npts % 3) != 1) - return; - - path = (NSVGpath*)malloc(sizeof(NSVGpath)); - if (path == NULL) goto error; - memset(path, 0, sizeof(NSVGpath)); - - path->pts = (float*)malloc(p->npts*2*sizeof(float)); - if (path->pts == NULL) goto error; - path->closed = closed; - path->npts = p->npts; - - // Transform path. - for (i = 0; i < p->npts; ++i) - nsvg__xformPoint(&path->pts[i*2], &path->pts[i*2+1], p->pts[i*2], p->pts[i*2+1], attr->xform); - - // Find bounds - for (i = 0; i < path->npts-1; i += 3) { - curve = &path->pts[i*2]; - nsvg__curveBounds(bounds, curve); - if (i == 0) { - path->bounds[0] = bounds[0]; - path->bounds[1] = bounds[1]; - path->bounds[2] = bounds[2]; - path->bounds[3] = bounds[3]; - } else { - path->bounds[0] = nsvg__minf(path->bounds[0], bounds[0]); - path->bounds[1] = nsvg__minf(path->bounds[1], bounds[1]); - path->bounds[2] = nsvg__maxf(path->bounds[2], bounds[2]); - path->bounds[3] = nsvg__maxf(path->bounds[3], bounds[3]); - } - } - - path->next = p->plist; - p->plist = path; - - return; - -error: - if (path != NULL) { - if (path->pts != NULL) free(path->pts); - free(path); - } -} - -// We roll our own string to float because the std library one uses locale and messes things up. -static double nsvg__atof(const char* s) -{ - char* cur = (char*)s; - char* end = NULL; - double res = 0.0, sign = 1.0; - long long intPart = 0, fracPart = 0; - char hasIntPart = 0, hasFracPart = 0; - - // Parse optional sign - if (*cur == '+') { - cur++; - } else if (*cur == '-') { - sign = -1; - cur++; - } - - // Parse integer part - if (nsvg__isdigit(*cur)) { - // Parse digit sequence - intPart = strtoll(cur, &end, 10); - if (cur != end) { - res = (double)intPart; - hasIntPart = 1; - cur = end; - } - } - - // Parse fractional part. - if (*cur == '.') { - cur++; // Skip '.' - if (nsvg__isdigit(*cur)) { - // Parse digit sequence - fracPart = strtoll(cur, &end, 10); - if (cur != end) { - res += (double)fracPart / pow(10.0, (double)(end - cur)); - hasFracPart = 1; - cur = end; - } - } - } - - // A valid number should have integer or fractional part. - if (!hasIntPart && !hasFracPart) - return 0.0; - - // Parse optional exponent - if (*cur == 'e' || *cur == 'E') { - long expPart = 0; - cur++; // skip 'E' - expPart = strtol(cur, &end, 10); // Parse digit sequence with sign - if (cur != end) { - res *= pow(10.0, (double)expPart); - } - } - - return res * sign; -} - - -static const char* nsvg__parseNumber(const char* s, char* it, const int size) -{ - const int last = size-1; - int i = 0; - - // sign - if (*s == '-' || *s == '+') { - if (i < last) it[i++] = *s; - s++; - } - // integer part - while (*s && nsvg__isdigit(*s)) { - if (i < last) it[i++] = *s; - s++; - } - if (*s == '.') { - // decimal point - if (i < last) it[i++] = *s; - s++; - // fraction part - while (*s && nsvg__isdigit(*s)) { - if (i < last) it[i++] = *s; - s++; - } - } - // exponent - if ((*s == 'e' || *s == 'E') && (s[1] != 'm' && s[1] != 'x')) { - if (i < last) it[i++] = *s; - s++; - if (*s == '-' || *s == '+') { - if (i < last) it[i++] = *s; - s++; - } - while (*s && nsvg__isdigit(*s)) { - if (i < last) it[i++] = *s; - s++; - } - } - it[i] = '\0'; - - return s; -} - -static const char* nsvg__getNextPathItem(const char* s, char* it) -{ - it[0] = '\0'; - // Skip white spaces and commas - while (*s && (nsvg__isspace(*s) || *s == ',')) s++; - if (!*s) return s; - if (*s == '-' || *s == '+' || *s == '.' || nsvg__isdigit(*s)) { - s = nsvg__parseNumber(s, it, 64); - } else { - // Parse command - it[0] = *s++; - it[1] = '\0'; - return s; - } - - return s; -} - -static unsigned int nsvg__parseColorHex(const char* str) -{ - unsigned int r=0, g=0, b=0; - if (sscanf(str, "#%2x%2x%2x", &r, &g, &b) == 3 ) // 2 digit hex - return NSVG_RGB(r, g, b); - if (sscanf(str, "#%1x%1x%1x", &r, &g, &b) == 3 ) // 1 digit hex, e.g. #abc -> 0xccbbaa - return NSVG_RGB(r*17, g*17, b*17); // same effect as (r<<4|r), (g<<4|g), .. - return NSVG_RGB(128, 128, 128); -} - -// Parse rgb color. The pointer 'str' must point at "rgb(" (4+ characters). -// This function returns gray (rgb(128, 128, 128) == '#808080') on parse errors -// for backwards compatibility. Note: other image viewers return black instead. - -static unsigned int nsvg__parseColorRGB(const char* str) -{ - int i; - unsigned int rgbi[3]; - float rgbf[3]; - // try decimal integers first - if (sscanf(str, "rgb(%u, %u, %u)", &rgbi[0], &rgbi[1], &rgbi[2]) != 3) { - // integers failed, try percent values (float, locale independent) - const char delimiter[3] = {',', ',', ')'}; - str += 4; // skip "rgb(" - for (i = 0; i < 3; i++) { - while (*str && (nsvg__isspace(*str))) str++; // skip leading spaces - if (*str == '+') str++; // skip '+' (don't allow '-') - if (!*str) break; - rgbf[i] = nsvg__atof(str); - - // Note 1: it would be great if nsvg__atof() returned how many - // bytes it consumed but it doesn't. We need to skip the number, - // the '%' character, spaces, and the delimiter ',' or ')'. - - // Note 2: The following code does not allow values like "33.%", - // i.e. a decimal point w/o fractional part, but this is consistent - // with other image viewers, e.g. firefox, chrome, eog, gimp. - - while (*str && nsvg__isdigit(*str)) str++; // skip integer part - if (*str == '.') { - str++; - if (!nsvg__isdigit(*str)) break; // error: no digit after '.' - while (*str && nsvg__isdigit(*str)) str++; // skip fractional part - } - if (*str == '%') str++; else break; - while (nsvg__isspace(*str)) str++; - if (*str == delimiter[i]) str++; - else break; - } - if (i == 3) { - rgbi[0] = roundf(rgbf[0] * 2.55f); - rgbi[1] = roundf(rgbf[1] * 2.55f); - rgbi[2] = roundf(rgbf[2] * 2.55f); - } else { - rgbi[0] = rgbi[1] = rgbi[2] = 128; - } - } - // clip values as the CSS spec requires - for (i = 0; i < 3; i++) { - if (rgbi[i] > 255) rgbi[i] = 255; - } - return NSVG_RGB(rgbi[0], rgbi[1], rgbi[2]); -} - -typedef struct NSVGNamedColor { - const char* name; - unsigned int color; -} NSVGNamedColor; - -NSVGNamedColor nsvg__colors[] = { - - { "red", NSVG_RGB(255, 0, 0) }, - { "green", NSVG_RGB( 0, 128, 0) }, - { "blue", NSVG_RGB( 0, 0, 255) }, - { "yellow", NSVG_RGB(255, 255, 0) }, - { "cyan", NSVG_RGB( 0, 255, 255) }, - { "magenta", NSVG_RGB(255, 0, 255) }, - { "black", NSVG_RGB( 0, 0, 0) }, - { "grey", NSVG_RGB(128, 128, 128) }, - { "gray", NSVG_RGB(128, 128, 128) }, - { "white", NSVG_RGB(255, 255, 255) }, - -#ifdef NANOSVG_ALL_COLOR_KEYWORDS - { "aliceblue", NSVG_RGB(240, 248, 255) }, - { "antiquewhite", NSVG_RGB(250, 235, 215) }, - { "aqua", NSVG_RGB( 0, 255, 255) }, - { "aquamarine", NSVG_RGB(127, 255, 212) }, - { "azure", NSVG_RGB(240, 255, 255) }, - { "beige", NSVG_RGB(245, 245, 220) }, - { "bisque", NSVG_RGB(255, 228, 196) }, - { "blanchedalmond", NSVG_RGB(255, 235, 205) }, - { "blueviolet", NSVG_RGB(138, 43, 226) }, - { "brown", NSVG_RGB(165, 42, 42) }, - { "burlywood", NSVG_RGB(222, 184, 135) }, - { "cadetblue", NSVG_RGB( 95, 158, 160) }, - { "chartreuse", NSVG_RGB(127, 255, 0) }, - { "chocolate", NSVG_RGB(210, 105, 30) }, - { "coral", NSVG_RGB(255, 127, 80) }, - { "cornflowerblue", NSVG_RGB(100, 149, 237) }, - { "cornsilk", NSVG_RGB(255, 248, 220) }, - { "crimson", NSVG_RGB(220, 20, 60) }, - { "darkblue", NSVG_RGB( 0, 0, 139) }, - { "darkcyan", NSVG_RGB( 0, 139, 139) }, - { "darkgoldenrod", NSVG_RGB(184, 134, 11) }, - { "darkgray", NSVG_RGB(169, 169, 169) }, - { "darkgreen", NSVG_RGB( 0, 100, 0) }, - { "darkgrey", NSVG_RGB(169, 169, 169) }, - { "darkkhaki", NSVG_RGB(189, 183, 107) }, - { "darkmagenta", NSVG_RGB(139, 0, 139) }, - { "darkolivegreen", NSVG_RGB( 85, 107, 47) }, - { "darkorange", NSVG_RGB(255, 140, 0) }, - { "darkorchid", NSVG_RGB(153, 50, 204) }, - { "darkred", NSVG_RGB(139, 0, 0) }, - { "darksalmon", NSVG_RGB(233, 150, 122) }, - { "darkseagreen", NSVG_RGB(143, 188, 143) }, - { "darkslateblue", NSVG_RGB( 72, 61, 139) }, - { "darkslategray", NSVG_RGB( 47, 79, 79) }, - { "darkslategrey", NSVG_RGB( 47, 79, 79) }, - { "darkturquoise", NSVG_RGB( 0, 206, 209) }, - { "darkviolet", NSVG_RGB(148, 0, 211) }, - { "deeppink", NSVG_RGB(255, 20, 147) }, - { "deepskyblue", NSVG_RGB( 0, 191, 255) }, - { "dimgray", NSVG_RGB(105, 105, 105) }, - { "dimgrey", NSVG_RGB(105, 105, 105) }, - { "dodgerblue", NSVG_RGB( 30, 144, 255) }, - { "firebrick", NSVG_RGB(178, 34, 34) }, - { "floralwhite", NSVG_RGB(255, 250, 240) }, - { "forestgreen", NSVG_RGB( 34, 139, 34) }, - { "fuchsia", NSVG_RGB(255, 0, 255) }, - { "gainsboro", NSVG_RGB(220, 220, 220) }, - { "ghostwhite", NSVG_RGB(248, 248, 255) }, - { "gold", NSVG_RGB(255, 215, 0) }, - { "goldenrod", NSVG_RGB(218, 165, 32) }, - { "greenyellow", NSVG_RGB(173, 255, 47) }, - { "honeydew", NSVG_RGB(240, 255, 240) }, - { "hotpink", NSVG_RGB(255, 105, 180) }, - { "indianred", NSVG_RGB(205, 92, 92) }, - { "indigo", NSVG_RGB( 75, 0, 130) }, - { "ivory", NSVG_RGB(255, 255, 240) }, - { "khaki", NSVG_RGB(240, 230, 140) }, - { "lavender", NSVG_RGB(230, 230, 250) }, - { "lavenderblush", NSVG_RGB(255, 240, 245) }, - { "lawngreen", NSVG_RGB(124, 252, 0) }, - { "lemonchiffon", NSVG_RGB(255, 250, 205) }, - { "lightblue", NSVG_RGB(173, 216, 230) }, - { "lightcoral", NSVG_RGB(240, 128, 128) }, - { "lightcyan", NSVG_RGB(224, 255, 255) }, - { "lightgoldenrodyellow", NSVG_RGB(250, 250, 210) }, - { "lightgray", NSVG_RGB(211, 211, 211) }, - { "lightgreen", NSVG_RGB(144, 238, 144) }, - { "lightgrey", NSVG_RGB(211, 211, 211) }, - { "lightpink", NSVG_RGB(255, 182, 193) }, - { "lightsalmon", NSVG_RGB(255, 160, 122) }, - { "lightseagreen", NSVG_RGB( 32, 178, 170) }, - { "lightskyblue", NSVG_RGB(135, 206, 250) }, - { "lightslategray", NSVG_RGB(119, 136, 153) }, - { "lightslategrey", NSVG_RGB(119, 136, 153) }, - { "lightsteelblue", NSVG_RGB(176, 196, 222) }, - { "lightyellow", NSVG_RGB(255, 255, 224) }, - { "lime", NSVG_RGB( 0, 255, 0) }, - { "limegreen", NSVG_RGB( 50, 205, 50) }, - { "linen", NSVG_RGB(250, 240, 230) }, - { "maroon", NSVG_RGB(128, 0, 0) }, - { "mediumaquamarine", NSVG_RGB(102, 205, 170) }, - { "mediumblue", NSVG_RGB( 0, 0, 205) }, - { "mediumorchid", NSVG_RGB(186, 85, 211) }, - { "mediumpurple", NSVG_RGB(147, 112, 219) }, - { "mediumseagreen", NSVG_RGB( 60, 179, 113) }, - { "mediumslateblue", NSVG_RGB(123, 104, 238) }, - { "mediumspringgreen", NSVG_RGB( 0, 250, 154) }, - { "mediumturquoise", NSVG_RGB( 72, 209, 204) }, - { "mediumvioletred", NSVG_RGB(199, 21, 133) }, - { "midnightblue", NSVG_RGB( 25, 25, 112) }, - { "mintcream", NSVG_RGB(245, 255, 250) }, - { "mistyrose", NSVG_RGB(255, 228, 225) }, - { "moccasin", NSVG_RGB(255, 228, 181) }, - { "navajowhite", NSVG_RGB(255, 222, 173) }, - { "navy", NSVG_RGB( 0, 0, 128) }, - { "oldlace", NSVG_RGB(253, 245, 230) }, - { "olive", NSVG_RGB(128, 128, 0) }, - { "olivedrab", NSVG_RGB(107, 142, 35) }, - { "orange", NSVG_RGB(255, 165, 0) }, - { "orangered", NSVG_RGB(255, 69, 0) }, - { "orchid", NSVG_RGB(218, 112, 214) }, - { "palegoldenrod", NSVG_RGB(238, 232, 170) }, - { "palegreen", NSVG_RGB(152, 251, 152) }, - { "paleturquoise", NSVG_RGB(175, 238, 238) }, - { "palevioletred", NSVG_RGB(219, 112, 147) }, - { "papayawhip", NSVG_RGB(255, 239, 213) }, - { "peachpuff", NSVG_RGB(255, 218, 185) }, - { "peru", NSVG_RGB(205, 133, 63) }, - { "pink", NSVG_RGB(255, 192, 203) }, - { "plum", NSVG_RGB(221, 160, 221) }, - { "powderblue", NSVG_RGB(176, 224, 230) }, - { "purple", NSVG_RGB(128, 0, 128) }, - { "rosybrown", NSVG_RGB(188, 143, 143) }, - { "royalblue", NSVG_RGB( 65, 105, 225) }, - { "saddlebrown", NSVG_RGB(139, 69, 19) }, - { "salmon", NSVG_RGB(250, 128, 114) }, - { "sandybrown", NSVG_RGB(244, 164, 96) }, - { "seagreen", NSVG_RGB( 46, 139, 87) }, - { "seashell", NSVG_RGB(255, 245, 238) }, - { "sienna", NSVG_RGB(160, 82, 45) }, - { "silver", NSVG_RGB(192, 192, 192) }, - { "skyblue", NSVG_RGB(135, 206, 235) }, - { "slateblue", NSVG_RGB(106, 90, 205) }, - { "slategray", NSVG_RGB(112, 128, 144) }, - { "slategrey", NSVG_RGB(112, 128, 144) }, - { "snow", NSVG_RGB(255, 250, 250) }, - { "springgreen", NSVG_RGB( 0, 255, 127) }, - { "steelblue", NSVG_RGB( 70, 130, 180) }, - { "tan", NSVG_RGB(210, 180, 140) }, - { "teal", NSVG_RGB( 0, 128, 128) }, - { "thistle", NSVG_RGB(216, 191, 216) }, - { "tomato", NSVG_RGB(255, 99, 71) }, - { "turquoise", NSVG_RGB( 64, 224, 208) }, - { "violet", NSVG_RGB(238, 130, 238) }, - { "wheat", NSVG_RGB(245, 222, 179) }, - { "whitesmoke", NSVG_RGB(245, 245, 245) }, - { "yellowgreen", NSVG_RGB(154, 205, 50) }, -#endif -}; - -static unsigned int nsvg__parseColorName(const char* str) -{ - int i, ncolors = sizeof(nsvg__colors) / sizeof(NSVGNamedColor); - - for (i = 0; i < ncolors; i++) { - if (strcmp(nsvg__colors[i].name, str) == 0) { - return nsvg__colors[i].color; - } - } - - return NSVG_RGB(128, 128, 128); -} - -static unsigned int nsvg__parseColor(const char* str) -{ - size_t len = 0; - while(*str == ' ') ++str; - len = strlen(str); - if (len >= 1 && *str == '#') - return nsvg__parseColorHex(str); - else if (len >= 4 && str[0] == 'r' && str[1] == 'g' && str[2] == 'b' && str[3] == '(') - return nsvg__parseColorRGB(str); - return nsvg__parseColorName(str); -} - -static float nsvg__parseOpacity(const char* str) -{ - float val = nsvg__atof(str); - if (val < 0.0f) val = 0.0f; - if (val > 1.0f) val = 1.0f; - return val; -} - -static float nsvg__parseMiterLimit(const char* str) -{ - float val = nsvg__atof(str); - if (val < 0.0f) val = 0.0f; - return val; -} - -static int nsvg__parseUnits(const char* units) -{ - if (units[0] == 'p' && units[1] == 'x') - return NSVG_UNITS_PX; - else if (units[0] == 'p' && units[1] == 't') - return NSVG_UNITS_PT; - else if (units[0] == 'p' && units[1] == 'c') - return NSVG_UNITS_PC; - else if (units[0] == 'm' && units[1] == 'm') - return NSVG_UNITS_MM; - else if (units[0] == 'c' && units[1] == 'm') - return NSVG_UNITS_CM; - else if (units[0] == 'i' && units[1] == 'n') - return NSVG_UNITS_IN; - else if (units[0] == '%') - return NSVG_UNITS_PERCENT; - else if (units[0] == 'e' && units[1] == 'm') - return NSVG_UNITS_EM; - else if (units[0] == 'e' && units[1] == 'x') - return NSVG_UNITS_EX; - return NSVG_UNITS_USER; -} - -static int nsvg__isCoordinate(const char* s) -{ - // optional sign - if (*s == '-' || *s == '+') - s++; - // must have at least one digit, or start by a dot - return (nsvg__isdigit(*s) || *s == '.'); -} - -static NSVGcoordinate nsvg__parseCoordinateRaw(const char* str) -{ - NSVGcoordinate coord = {0, NSVG_UNITS_USER}; - char buf[64]; - coord.units = nsvg__parseUnits(nsvg__parseNumber(str, buf, 64)); - coord.value = nsvg__atof(buf); - return coord; -} - -static NSVGcoordinate nsvg__coord(float v, int units) -{ - NSVGcoordinate coord = {v, units}; - return coord; -} - -static float nsvg__parseCoordinate(NSVGparser* p, const char* str, float orig, float length) -{ - NSVGcoordinate coord = nsvg__parseCoordinateRaw(str); - return nsvg__convertToPixels(p, coord, orig, length); -} - -static int nsvg__parseTransformArgs(const char* str, float* args, int maxNa, int* na) -{ - const char* end; - const char* ptr; - char it[64]; - - *na = 0; - ptr = str; - while (*ptr && *ptr != '(') ++ptr; - if (*ptr == 0) - return 1; - end = ptr; - while (*end && *end != ')') ++end; - if (*end == 0) - return 1; - - while (ptr < end) { - if (*ptr == '-' || *ptr == '+' || *ptr == '.' || nsvg__isdigit(*ptr)) { - if (*na >= maxNa) return 0; - ptr = nsvg__parseNumber(ptr, it, 64); - args[(*na)++] = (float)nsvg__atof(it); - } else { - ++ptr; - } - } - return (int)(end - str); -} - - -static int nsvg__parseMatrix(float* xform, const char* str) -{ - float t[6]; - int na = 0; - int len = nsvg__parseTransformArgs(str, t, 6, &na); - if (na != 6) return len; - memcpy(xform, t, sizeof(float)*6); - return len; -} - -static int nsvg__parseTranslate(float* xform, const char* str) -{ - float args[2]; - float t[6]; - int na = 0; - int len = nsvg__parseTransformArgs(str, args, 2, &na); - if (na == 1) args[1] = 0.0; - - nsvg__xformSetTranslation(t, args[0], args[1]); - memcpy(xform, t, sizeof(float)*6); - return len; -} - -static int nsvg__parseScale(float* xform, const char* str) -{ - float args[2]; - int na = 0; - float t[6]; - int len = nsvg__parseTransformArgs(str, args, 2, &na); - if (na == 1) args[1] = args[0]; - nsvg__xformSetScale(t, args[0], args[1]); - memcpy(xform, t, sizeof(float)*6); - return len; -} - -static int nsvg__parseSkewX(float* xform, const char* str) -{ - float args[1]; - int na = 0; - float t[6]; - int len = nsvg__parseTransformArgs(str, args, 1, &na); - nsvg__xformSetSkewX(t, args[0]/180.0f*NSVG_PI); - memcpy(xform, t, sizeof(float)*6); - return len; -} - -static int nsvg__parseSkewY(float* xform, const char* str) -{ - float args[1]; - int na = 0; - float t[6]; - int len = nsvg__parseTransformArgs(str, args, 1, &na); - nsvg__xformSetSkewY(t, args[0]/180.0f*NSVG_PI); - memcpy(xform, t, sizeof(float)*6); - return len; -} - -static int nsvg__parseRotate(float* xform, const char* str) -{ - float args[3]; - int na = 0; - float m[6]; - float t[6]; - int len = nsvg__parseTransformArgs(str, args, 3, &na); - if (na == 1) - args[1] = args[2] = 0.0f; - nsvg__xformIdentity(m); - - if (na > 1) { - nsvg__xformSetTranslation(t, -args[1], -args[2]); - nsvg__xformMultiply(m, t); - } - - nsvg__xformSetRotation(t, args[0]/180.0f*NSVG_PI); - nsvg__xformMultiply(m, t); - - if (na > 1) { - nsvg__xformSetTranslation(t, args[1], args[2]); - nsvg__xformMultiply(m, t); - } - - memcpy(xform, m, sizeof(float)*6); - - return len; -} - -static void nsvg__parseTransform(float* xform, const char* str) -{ - float t[6]; - int len; - nsvg__xformIdentity(xform); - while (*str) - { - if (strncmp(str, "matrix", 6) == 0) - len = nsvg__parseMatrix(t, str); - else if (strncmp(str, "translate", 9) == 0) - len = nsvg__parseTranslate(t, str); - else if (strncmp(str, "scale", 5) == 0) - len = nsvg__parseScale(t, str); - else if (strncmp(str, "rotate", 6) == 0) - len = nsvg__parseRotate(t, str); - else if (strncmp(str, "skewX", 5) == 0) - len = nsvg__parseSkewX(t, str); - else if (strncmp(str, "skewY", 5) == 0) - len = nsvg__parseSkewY(t, str); - else{ - ++str; - continue; - } - if (len != 0) { - str += len; - } else { - ++str; - continue; - } - - nsvg__xformPremultiply(xform, t); - } -} - -static void nsvg__parseUrl(char* id, const char* str) -{ - int i = 0; - str += 4; // "url("; - if (*str && *str == '#') - str++; - while (i < 63 && *str && *str != ')') { - id[i] = *str++; - i++; - } - id[i] = '\0'; -} - -static char nsvg__parseLineCap(const char* str) -{ - if (strcmp(str, "butt") == 0) - return NSVG_CAP_BUTT; - else if (strcmp(str, "round") == 0) - return NSVG_CAP_ROUND; - else if (strcmp(str, "square") == 0) - return NSVG_CAP_SQUARE; - // TODO: handle inherit. - return NSVG_CAP_BUTT; -} - -static char nsvg__parseLineJoin(const char* str) -{ - if (strcmp(str, "miter") == 0) - return NSVG_JOIN_MITER; - else if (strcmp(str, "round") == 0) - return NSVG_JOIN_ROUND; - else if (strcmp(str, "bevel") == 0) - return NSVG_JOIN_BEVEL; - // TODO: handle inherit. - return NSVG_JOIN_MITER; -} - -static char nsvg__parseFillRule(const char* str) -{ - if (strcmp(str, "nonzero") == 0) - return NSVG_FILLRULE_NONZERO; - else if (strcmp(str, "evenodd") == 0) - return NSVG_FILLRULE_EVENODD; - // TODO: handle inherit. - return NSVG_FILLRULE_NONZERO; -} - -static const char* nsvg__getNextDashItem(const char* s, char* it) -{ - int n = 0; - it[0] = '\0'; - // Skip white spaces and commas - while (*s && (nsvg__isspace(*s) || *s == ',')) s++; - // Advance until whitespace, comma or end. - while (*s && (!nsvg__isspace(*s) && *s != ',')) { - if (n < 63) - it[n++] = *s; - s++; - } - it[n++] = '\0'; - return s; -} - -static int nsvg__parseStrokeDashArray(NSVGparser* p, const char* str, float* strokeDashArray) -{ - char item[64]; - int count = 0, i; - float sum = 0.0f; - - // Handle "none" - if (str[0] == 'n') - return 0; - - // Parse dashes - while (*str) { - str = nsvg__getNextDashItem(str, item); - if (!*item) break; - if (count < NSVG_MAX_DASHES) - strokeDashArray[count++] = fabsf(nsvg__parseCoordinate(p, item, 0.0f, nsvg__actualLength(p))); - } - - for (i = 0; i < count; i++) - sum += strokeDashArray[i]; - if (sum <= 1e-6f) - count = 0; - - return count; -} - -static void nsvg__parseStyle(NSVGparser* p, const char* str); - -static int nsvg__parseAttr(NSVGparser* p, const char* name, const char* value) -{ - float xform[6]; - NSVGattrib* attr = nsvg__getAttr(p); - if (!attr) return 0; - - if (strcmp(name, "style") == 0) { - nsvg__parseStyle(p, value); - } else if (strcmp(name, "display") == 0) { - if (strcmp(value, "none") == 0) - attr->visible = 0; - // Don't reset ->visible on display:inline, one display:none hides the whole subtree - - } else if (strcmp(name, "fill") == 0) { - if (strcmp(value, "none") == 0) { - attr->hasFill = 0; - } else if (strncmp(value, "url(", 4) == 0) { - attr->hasFill = 2; - nsvg__parseUrl(attr->fillGradient, value); - } else { - attr->hasFill = 1; - attr->fillColor = nsvg__parseColor(value); - } - } else if (strcmp(name, "opacity") == 0) { - attr->opacity = nsvg__parseOpacity(value); - } else if (strcmp(name, "fill-opacity") == 0) { - attr->fillOpacity = nsvg__parseOpacity(value); - } else if (strcmp(name, "stroke") == 0) { - if (strcmp(value, "none") == 0) { - attr->hasStroke = 0; - } else if (strncmp(value, "url(", 4) == 0) { - attr->hasStroke = 2; - nsvg__parseUrl(attr->strokeGradient, value); - } else { - attr->hasStroke = 1; - attr->strokeColor = nsvg__parseColor(value); - } - } else if (strcmp(name, "stroke-width") == 0) { - attr->strokeWidth = nsvg__parseCoordinate(p, value, 0.0f, nsvg__actualLength(p)); - } else if (strcmp(name, "stroke-dasharray") == 0) { - attr->strokeDashCount = nsvg__parseStrokeDashArray(p, value, attr->strokeDashArray); - } else if (strcmp(name, "stroke-dashoffset") == 0) { - attr->strokeDashOffset = nsvg__parseCoordinate(p, value, 0.0f, nsvg__actualLength(p)); - } else if (strcmp(name, "stroke-opacity") == 0) { - attr->strokeOpacity = nsvg__parseOpacity(value); - } else if (strcmp(name, "stroke-linecap") == 0) { - attr->strokeLineCap = nsvg__parseLineCap(value); - } else if (strcmp(name, "stroke-linejoin") == 0) { - attr->strokeLineJoin = nsvg__parseLineJoin(value); - } else if (strcmp(name, "stroke-miterlimit") == 0) { - attr->miterLimit = nsvg__parseMiterLimit(value); - } else if (strcmp(name, "fill-rule") == 0) { - attr->fillRule = nsvg__parseFillRule(value); - } else if (strcmp(name, "font-size") == 0) { - attr->fontSize = nsvg__parseCoordinate(p, value, 0.0f, nsvg__actualLength(p)); - } else if (strcmp(name, "transform") == 0) { - nsvg__parseTransform(xform, value); - nsvg__xformPremultiply(attr->xform, xform); - } else if (strcmp(name, "stop-color") == 0) { - attr->stopColor = nsvg__parseColor(value); - } else if (strcmp(name, "stop-opacity") == 0) { - attr->stopOpacity = nsvg__parseOpacity(value); - } else if (strcmp(name, "offset") == 0) { - attr->stopOffset = nsvg__parseCoordinate(p, value, 0.0f, 1.0f); - } else if (strcmp(name, "id") == 0) { - strncpy(attr->id, value, 63); - attr->id[63] = '\0'; - } else { - return 0; - } - return 1; -} - -static int nsvg__parseNameValue(NSVGparser* p, const char* start, const char* end) -{ - const char* str; - const char* val; - char name[512]; - char value[512]; - int n; - - str = start; - while (str < end && *str != ':') ++str; - - val = str; - - // Right Trim - while (str > start && (*str == ':' || nsvg__isspace(*str))) --str; - ++str; - - n = (int)(str - start); - if (n > 511) n = 511; - if (n) memcpy(name, start, n); - name[n] = 0; - - while (val < end && (*val == ':' || nsvg__isspace(*val))) ++val; - - n = (int)(end - val); - if (n > 511) n = 511; - if (n) memcpy(value, val, n); - value[n] = 0; - - return nsvg__parseAttr(p, name, value); -} - -static void nsvg__parseStyle(NSVGparser* p, const char* str) -{ - const char* start; - const char* end; - - while (*str) { - // Left Trim - while(*str && nsvg__isspace(*str)) ++str; - start = str; - while(*str && *str != ';') ++str; - end = str; - - // Right Trim - while (end > start && (*end == ';' || nsvg__isspace(*end))) --end; - ++end; - - nsvg__parseNameValue(p, start, end); - if (*str) ++str; - } -} - -static void nsvg__parseAttribs(NSVGparser* p, const char** attr) -{ - int i; - for (i = 0; attr[i]; i += 2) - { - if (strcmp(attr[i], "style") == 0) - nsvg__parseStyle(p, attr[i + 1]); - else - nsvg__parseAttr(p, attr[i], attr[i + 1]); - } -} - -static int nsvg__getArgsPerElement(char cmd) -{ - switch (cmd) { - case 'v': - case 'V': - case 'h': - case 'H': - return 1; - case 'm': - case 'M': - case 'l': - case 'L': - case 't': - case 'T': - return 2; - case 'q': - case 'Q': - case 's': - case 'S': - return 4; - case 'c': - case 'C': - return 6; - case 'a': - case 'A': - return 7; - case 'z': - case 'Z': - return 0; - } - return -1; -} - -static void nsvg__pathMoveTo(NSVGparser* p, float* cpx, float* cpy, float* args, int rel) -{ - if (rel) { - *cpx += args[0]; - *cpy += args[1]; - } else { - *cpx = args[0]; - *cpy = args[1]; - } - nsvg__moveTo(p, *cpx, *cpy); -} - -static void nsvg__pathLineTo(NSVGparser* p, float* cpx, float* cpy, float* args, int rel) -{ - if (rel) { - *cpx += args[0]; - *cpy += args[1]; - } else { - *cpx = args[0]; - *cpy = args[1]; - } - nsvg__lineTo(p, *cpx, *cpy); -} - -static void nsvg__pathHLineTo(NSVGparser* p, float* cpx, float* cpy, float* args, int rel) -{ - if (rel) - *cpx += args[0]; - else - *cpx = args[0]; - nsvg__lineTo(p, *cpx, *cpy); -} - -static void nsvg__pathVLineTo(NSVGparser* p, float* cpx, float* cpy, float* args, int rel) -{ - if (rel) - *cpy += args[0]; - else - *cpy = args[0]; - nsvg__lineTo(p, *cpx, *cpy); -} - -static void nsvg__pathCubicBezTo(NSVGparser* p, float* cpx, float* cpy, - float* cpx2, float* cpy2, float* args, int rel) -{ - float x2, y2, cx1, cy1, cx2, cy2; - - if (rel) { - cx1 = *cpx + args[0]; - cy1 = *cpy + args[1]; - cx2 = *cpx + args[2]; - cy2 = *cpy + args[3]; - x2 = *cpx + args[4]; - y2 = *cpy + args[5]; - } else { - cx1 = args[0]; - cy1 = args[1]; - cx2 = args[2]; - cy2 = args[3]; - x2 = args[4]; - y2 = args[5]; - } - - nsvg__cubicBezTo(p, cx1,cy1, cx2,cy2, x2,y2); - - *cpx2 = cx2; - *cpy2 = cy2; - *cpx = x2; - *cpy = y2; -} - -static void nsvg__pathCubicBezShortTo(NSVGparser* p, float* cpx, float* cpy, - float* cpx2, float* cpy2, float* args, int rel) -{ - float x1, y1, x2, y2, cx1, cy1, cx2, cy2; - - x1 = *cpx; - y1 = *cpy; - if (rel) { - cx2 = *cpx + args[0]; - cy2 = *cpy + args[1]; - x2 = *cpx + args[2]; - y2 = *cpy + args[3]; - } else { - cx2 = args[0]; - cy2 = args[1]; - x2 = args[2]; - y2 = args[3]; - } - - cx1 = 2*x1 - *cpx2; - cy1 = 2*y1 - *cpy2; - - nsvg__cubicBezTo(p, cx1,cy1, cx2,cy2, x2,y2); - - *cpx2 = cx2; - *cpy2 = cy2; - *cpx = x2; - *cpy = y2; -} - -static void nsvg__pathQuadBezTo(NSVGparser* p, float* cpx, float* cpy, - float* cpx2, float* cpy2, float* args, int rel) -{ - float x1, y1, x2, y2, cx, cy; - float cx1, cy1, cx2, cy2; - - x1 = *cpx; - y1 = *cpy; - if (rel) { - cx = *cpx + args[0]; - cy = *cpy + args[1]; - x2 = *cpx + args[2]; - y2 = *cpy + args[3]; - } else { - cx = args[0]; - cy = args[1]; - x2 = args[2]; - y2 = args[3]; - } - - // Convert to cubic bezier - cx1 = x1 + 2.0f/3.0f*(cx - x1); - cy1 = y1 + 2.0f/3.0f*(cy - y1); - cx2 = x2 + 2.0f/3.0f*(cx - x2); - cy2 = y2 + 2.0f/3.0f*(cy - y2); - - nsvg__cubicBezTo(p, cx1,cy1, cx2,cy2, x2,y2); - - *cpx2 = cx; - *cpy2 = cy; - *cpx = x2; - *cpy = y2; -} - -static void nsvg__pathQuadBezShortTo(NSVGparser* p, float* cpx, float* cpy, - float* cpx2, float* cpy2, float* args, int rel) -{ - float x1, y1, x2, y2, cx, cy; - float cx1, cy1, cx2, cy2; - - x1 = *cpx; - y1 = *cpy; - if (rel) { - x2 = *cpx + args[0]; - y2 = *cpy + args[1]; - } else { - x2 = args[0]; - y2 = args[1]; - } - - cx = 2*x1 - *cpx2; - cy = 2*y1 - *cpy2; - - // Convert to cubix bezier - cx1 = x1 + 2.0f/3.0f*(cx - x1); - cy1 = y1 + 2.0f/3.0f*(cy - y1); - cx2 = x2 + 2.0f/3.0f*(cx - x2); - cy2 = y2 + 2.0f/3.0f*(cy - y2); - - nsvg__cubicBezTo(p, cx1,cy1, cx2,cy2, x2,y2); - - *cpx2 = cx; - *cpy2 = cy; - *cpx = x2; - *cpy = y2; -} - -static float nsvg__sqr(float x) { return x*x; } -static float nsvg__vmag(float x, float y) { return sqrtf(x*x + y*y); } - -static float nsvg__vecrat(float ux, float uy, float vx, float vy) -{ - return (ux*vx + uy*vy) / (nsvg__vmag(ux,uy) * nsvg__vmag(vx,vy)); -} - -static float nsvg__vecang(float ux, float uy, float vx, float vy) -{ - float r = nsvg__vecrat(ux,uy, vx,vy); - if (r < -1.0f) r = -1.0f; - if (r > 1.0f) r = 1.0f; - return ((ux*vy < uy*vx) ? -1.0f : 1.0f) * acosf(r); -} - -static void nsvg__pathArcTo(NSVGparser* p, float* cpx, float* cpy, float* args, int rel) -{ - // Ported from canvg (https://code.google.com/p/canvg/) - float rx, ry, rotx; - float x1, y1, x2, y2, cx, cy, dx, dy, d; - float x1p, y1p, cxp, cyp, s, sa, sb; - float ux, uy, vx, vy, a1, da; - float x, y, tanx, tany, a, px = 0, py = 0, ptanx = 0, ptany = 0, t[6]; - float sinrx, cosrx; - int fa, fs; - int i, ndivs; - float hda, kappa; - - rx = fabsf(args[0]); // y radius - ry = fabsf(args[1]); // x radius - rotx = args[2] / 180.0f * NSVG_PI; // x rotation angle - fa = fabsf(args[3]) > 1e-6 ? 1 : 0; // Large arc - fs = fabsf(args[4]) > 1e-6 ? 1 : 0; // Sweep direction - x1 = *cpx; // start point - y1 = *cpy; - if (rel) { // end point - x2 = *cpx + args[5]; - y2 = *cpy + args[6]; - } else { - x2 = args[5]; - y2 = args[6]; - } - - dx = x1 - x2; - dy = y1 - y2; - d = sqrtf(dx*dx + dy*dy); - if (d < 1e-6f || rx < 1e-6f || ry < 1e-6f) { - // The arc degenerates to a line - nsvg__lineTo(p, x2, y2); - *cpx = x2; - *cpy = y2; - return; - } - - sinrx = sinf(rotx); - cosrx = cosf(rotx); - - // Convert to center point parameterization. - // http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes - // 1) Compute x1', y1' - x1p = cosrx * dx / 2.0f + sinrx * dy / 2.0f; - y1p = -sinrx * dx / 2.0f + cosrx * dy / 2.0f; - d = nsvg__sqr(x1p)/nsvg__sqr(rx) + nsvg__sqr(y1p)/nsvg__sqr(ry); - if (d > 1) { - d = sqrtf(d); - rx *= d; - ry *= d; - } - // 2) Compute cx', cy' - s = 0.0f; - sa = nsvg__sqr(rx)*nsvg__sqr(ry) - nsvg__sqr(rx)*nsvg__sqr(y1p) - nsvg__sqr(ry)*nsvg__sqr(x1p); - sb = nsvg__sqr(rx)*nsvg__sqr(y1p) + nsvg__sqr(ry)*nsvg__sqr(x1p); - if (sa < 0.0f) sa = 0.0f; - if (sb > 0.0f) - s = sqrtf(sa / sb); - if (fa == fs) - s = -s; - cxp = s * rx * y1p / ry; - cyp = s * -ry * x1p / rx; - - // 3) Compute cx,cy from cx',cy' - cx = (x1 + x2)/2.0f + cosrx*cxp - sinrx*cyp; - cy = (y1 + y2)/2.0f + sinrx*cxp + cosrx*cyp; - - // 4) Calculate theta1, and delta theta. - ux = (x1p - cxp) / rx; - uy = (y1p - cyp) / ry; - vx = (-x1p - cxp) / rx; - vy = (-y1p - cyp) / ry; - a1 = nsvg__vecang(1.0f,0.0f, ux,uy); // Initial angle - da = nsvg__vecang(ux,uy, vx,vy); // Delta angle - -// if (vecrat(ux,uy,vx,vy) <= -1.0f) da = NSVG_PI; -// if (vecrat(ux,uy,vx,vy) >= 1.0f) da = 0; - - if (fs == 0 && da > 0) - da -= 2 * NSVG_PI; - else if (fs == 1 && da < 0) - da += 2 * NSVG_PI; - - // Approximate the arc using cubic spline segments. - t[0] = cosrx; t[1] = sinrx; - t[2] = -sinrx; t[3] = cosrx; - t[4] = cx; t[5] = cy; - - // Split arc into max 90 degree segments. - // The loop assumes an iteration per end point (including start and end), this +1. - ndivs = (int)(fabsf(da) / (NSVG_PI*0.5f) + 1.0f); - hda = (da / (float)ndivs) / 2.0f; - // Fix for ticket #179: division by 0: avoid cotangens around 0 (infinite) - if ((hda < 1e-3f) && (hda > -1e-3f)) - hda *= 0.5f; - else - hda = (1.0f - cosf(hda)) / sinf(hda); - kappa = fabsf(4.0f / 3.0f * hda); - if (da < 0.0f) - kappa = -kappa; - - for (i = 0; i <= ndivs; i++) { - a = a1 + da * ((float)i/(float)ndivs); - dx = cosf(a); - dy = sinf(a); - nsvg__xformPoint(&x, &y, dx*rx, dy*ry, t); // position - nsvg__xformVec(&tanx, &tany, -dy*rx * kappa, dx*ry * kappa, t); // tangent - if (i > 0) - nsvg__cubicBezTo(p, px+ptanx,py+ptany, x-tanx, y-tany, x, y); - px = x; - py = y; - ptanx = tanx; - ptany = tany; - } - - *cpx = x2; - *cpy = y2; -} - -static void nsvg__parsePath(NSVGparser* p, const char** attr) -{ - const char* s = NULL; - char cmd = '\0'; - float args[10]; - int nargs; - int rargs = 0; - char initPoint; - float cpx, cpy, cpx2, cpy2; - const char* tmp[4]; - char closedFlag; - int i; - char item[64]; - - for (i = 0; attr[i]; i += 2) { - if (strcmp(attr[i], "d") == 0) { - s = attr[i + 1]; - } else { - tmp[0] = attr[i]; - tmp[1] = attr[i + 1]; - tmp[2] = 0; - tmp[3] = 0; - nsvg__parseAttribs(p, tmp); - } - } - - if (s) { - nsvg__resetPath(p); - cpx = 0; cpy = 0; - cpx2 = 0; cpy2 = 0; - initPoint = 0; - closedFlag = 0; - nargs = 0; - - while (*s) { - s = nsvg__getNextPathItem(s, item); - if (!*item) break; - if (cmd != '\0' && nsvg__isCoordinate(item)) { - if (nargs < 10) - args[nargs++] = (float)nsvg__atof(item); - if (nargs >= rargs) { - switch (cmd) { - case 'm': - case 'M': - nsvg__pathMoveTo(p, &cpx, &cpy, args, cmd == 'm' ? 1 : 0); - // Moveto can be followed by multiple coordinate pairs, - // which should be treated as linetos. - cmd = (cmd == 'm') ? 'l' : 'L'; - rargs = nsvg__getArgsPerElement(cmd); - cpx2 = cpx; cpy2 = cpy; - initPoint = 1; - break; - case 'l': - case 'L': - nsvg__pathLineTo(p, &cpx, &cpy, args, cmd == 'l' ? 1 : 0); - cpx2 = cpx; cpy2 = cpy; - break; - case 'H': - case 'h': - nsvg__pathHLineTo(p, &cpx, &cpy, args, cmd == 'h' ? 1 : 0); - cpx2 = cpx; cpy2 = cpy; - break; - case 'V': - case 'v': - nsvg__pathVLineTo(p, &cpx, &cpy, args, cmd == 'v' ? 1 : 0); - cpx2 = cpx; cpy2 = cpy; - break; - case 'C': - case 'c': - nsvg__pathCubicBezTo(p, &cpx, &cpy, &cpx2, &cpy2, args, cmd == 'c' ? 1 : 0); - break; - case 'S': - case 's': - nsvg__pathCubicBezShortTo(p, &cpx, &cpy, &cpx2, &cpy2, args, cmd == 's' ? 1 : 0); - break; - case 'Q': - case 'q': - nsvg__pathQuadBezTo(p, &cpx, &cpy, &cpx2, &cpy2, args, cmd == 'q' ? 1 : 0); - break; - case 'T': - case 't': - nsvg__pathQuadBezShortTo(p, &cpx, &cpy, &cpx2, &cpy2, args, cmd == 't' ? 1 : 0); - break; - case 'A': - case 'a': - nsvg__pathArcTo(p, &cpx, &cpy, args, cmd == 'a' ? 1 : 0); - cpx2 = cpx; cpy2 = cpy; - break; - default: - if (nargs >= 2) { - cpx = args[nargs-2]; - cpy = args[nargs-1]; - cpx2 = cpx; cpy2 = cpy; - } - break; - } - nargs = 0; - } - } else { - cmd = item[0]; - if (cmd == 'M' || cmd == 'm') { - // Commit path. - if (p->npts > 0) - nsvg__addPath(p, closedFlag); - // Start new subpath. - nsvg__resetPath(p); - closedFlag = 0; - nargs = 0; - } else if (initPoint == 0) { - // Do not allow other commands until initial point has been set (moveTo called once). - cmd = '\0'; - } - if (cmd == 'Z' || cmd == 'z') { - closedFlag = 1; - // Commit path. - if (p->npts > 0) { - // Move current point to first point - cpx = p->pts[0]; - cpy = p->pts[1]; - cpx2 = cpx; cpy2 = cpy; - nsvg__addPath(p, closedFlag); - } - // Start new subpath. - nsvg__resetPath(p); - nsvg__moveTo(p, cpx, cpy); - closedFlag = 0; - nargs = 0; - } - rargs = nsvg__getArgsPerElement(cmd); - if (rargs == -1) { - // Command not recognized - cmd = '\0'; - rargs = 0; - } - } - } - // Commit path. - if (p->npts) - nsvg__addPath(p, closedFlag); - } - - nsvg__addShape(p); -} - -static void nsvg__parseRect(NSVGparser* p, const char** attr) -{ - float x = 0.0f; - float y = 0.0f; - float w = 0.0f; - float h = 0.0f; - float rx = -1.0f; // marks not set - float ry = -1.0f; - int i; - - for (i = 0; attr[i]; i += 2) { - if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) { - if (strcmp(attr[i], "x") == 0) x = nsvg__parseCoordinate(p, attr[i+1], nsvg__actualOrigX(p), nsvg__actualWidth(p)); - if (strcmp(attr[i], "y") == 0) y = nsvg__parseCoordinate(p, attr[i+1], nsvg__actualOrigY(p), nsvg__actualHeight(p)); - if (strcmp(attr[i], "width") == 0) w = nsvg__parseCoordinate(p, attr[i+1], 0.0f, nsvg__actualWidth(p)); - if (strcmp(attr[i], "height") == 0) h = nsvg__parseCoordinate(p, attr[i+1], 0.0f, nsvg__actualHeight(p)); - if (strcmp(attr[i], "rx") == 0) rx = fabsf(nsvg__parseCoordinate(p, attr[i+1], 0.0f, nsvg__actualWidth(p))); - if (strcmp(attr[i], "ry") == 0) ry = fabsf(nsvg__parseCoordinate(p, attr[i+1], 0.0f, nsvg__actualHeight(p))); - } - } - - if (rx < 0.0f && ry > 0.0f) rx = ry; - if (ry < 0.0f && rx > 0.0f) ry = rx; - if (rx < 0.0f) rx = 0.0f; - if (ry < 0.0f) ry = 0.0f; - if (rx > w/2.0f) rx = w/2.0f; - if (ry > h/2.0f) ry = h/2.0f; - - if (w != 0.0f && h != 0.0f) { - nsvg__resetPath(p); - - if (rx < 0.00001f || ry < 0.0001f) { - nsvg__moveTo(p, x, y); - nsvg__lineTo(p, x+w, y); - nsvg__lineTo(p, x+w, y+h); - nsvg__lineTo(p, x, y+h); - } else { - // Rounded rectangle - nsvg__moveTo(p, x+rx, y); - nsvg__lineTo(p, x+w-rx, y); - nsvg__cubicBezTo(p, x+w-rx*(1-NSVG_KAPPA90), y, x+w, y+ry*(1-NSVG_KAPPA90), x+w, y+ry); - nsvg__lineTo(p, x+w, y+h-ry); - nsvg__cubicBezTo(p, x+w, y+h-ry*(1-NSVG_KAPPA90), x+w-rx*(1-NSVG_KAPPA90), y+h, x+w-rx, y+h); - nsvg__lineTo(p, x+rx, y+h); - nsvg__cubicBezTo(p, x+rx*(1-NSVG_KAPPA90), y+h, x, y+h-ry*(1-NSVG_KAPPA90), x, y+h-ry); - nsvg__lineTo(p, x, y+ry); - nsvg__cubicBezTo(p, x, y+ry*(1-NSVG_KAPPA90), x+rx*(1-NSVG_KAPPA90), y, x+rx, y); - } - - nsvg__addPath(p, 1); - - nsvg__addShape(p); - } -} - -static void nsvg__parseCircle(NSVGparser* p, const char** attr) -{ - float cx = 0.0f; - float cy = 0.0f; - float r = 0.0f; - int i; - - for (i = 0; attr[i]; i += 2) { - if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) { - if (strcmp(attr[i], "cx") == 0) cx = nsvg__parseCoordinate(p, attr[i+1], nsvg__actualOrigX(p), nsvg__actualWidth(p)); - if (strcmp(attr[i], "cy") == 0) cy = nsvg__parseCoordinate(p, attr[i+1], nsvg__actualOrigY(p), nsvg__actualHeight(p)); - if (strcmp(attr[i], "r") == 0) r = fabsf(nsvg__parseCoordinate(p, attr[i+1], 0.0f, nsvg__actualLength(p))); - } - } - - if (r > 0.0f) { - nsvg__resetPath(p); - - nsvg__moveTo(p, cx+r, cy); - nsvg__cubicBezTo(p, cx+r, cy+r*NSVG_KAPPA90, cx+r*NSVG_KAPPA90, cy+r, cx, cy+r); - nsvg__cubicBezTo(p, cx-r*NSVG_KAPPA90, cy+r, cx-r, cy+r*NSVG_KAPPA90, cx-r, cy); - nsvg__cubicBezTo(p, cx-r, cy-r*NSVG_KAPPA90, cx-r*NSVG_KAPPA90, cy-r, cx, cy-r); - nsvg__cubicBezTo(p, cx+r*NSVG_KAPPA90, cy-r, cx+r, cy-r*NSVG_KAPPA90, cx+r, cy); - - nsvg__addPath(p, 1); - - nsvg__addShape(p); - } -} - -static void nsvg__parseEllipse(NSVGparser* p, const char** attr) -{ - float cx = 0.0f; - float cy = 0.0f; - float rx = 0.0f; - float ry = 0.0f; - int i; - - for (i = 0; attr[i]; i += 2) { - if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) { - if (strcmp(attr[i], "cx") == 0) cx = nsvg__parseCoordinate(p, attr[i+1], nsvg__actualOrigX(p), nsvg__actualWidth(p)); - if (strcmp(attr[i], "cy") == 0) cy = nsvg__parseCoordinate(p, attr[i+1], nsvg__actualOrigY(p), nsvg__actualHeight(p)); - if (strcmp(attr[i], "rx") == 0) rx = fabsf(nsvg__parseCoordinate(p, attr[i+1], 0.0f, nsvg__actualWidth(p))); - if (strcmp(attr[i], "ry") == 0) ry = fabsf(nsvg__parseCoordinate(p, attr[i+1], 0.0f, nsvg__actualHeight(p))); - } - } - - if (rx > 0.0f && ry > 0.0f) { - - nsvg__resetPath(p); - - nsvg__moveTo(p, cx+rx, cy); - nsvg__cubicBezTo(p, cx+rx, cy+ry*NSVG_KAPPA90, cx+rx*NSVG_KAPPA90, cy+ry, cx, cy+ry); - nsvg__cubicBezTo(p, cx-rx*NSVG_KAPPA90, cy+ry, cx-rx, cy+ry*NSVG_KAPPA90, cx-rx, cy); - nsvg__cubicBezTo(p, cx-rx, cy-ry*NSVG_KAPPA90, cx-rx*NSVG_KAPPA90, cy-ry, cx, cy-ry); - nsvg__cubicBezTo(p, cx+rx*NSVG_KAPPA90, cy-ry, cx+rx, cy-ry*NSVG_KAPPA90, cx+rx, cy); - - nsvg__addPath(p, 1); - - nsvg__addShape(p); - } -} - -static void nsvg__parseLine(NSVGparser* p, const char** attr) -{ - float x1 = 0.0; - float y1 = 0.0; - float x2 = 0.0; - float y2 = 0.0; - int i; - - for (i = 0; attr[i]; i += 2) { - if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) { - if (strcmp(attr[i], "x1") == 0) x1 = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigX(p), nsvg__actualWidth(p)); - if (strcmp(attr[i], "y1") == 0) y1 = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigY(p), nsvg__actualHeight(p)); - if (strcmp(attr[i], "x2") == 0) x2 = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigX(p), nsvg__actualWidth(p)); - if (strcmp(attr[i], "y2") == 0) y2 = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigY(p), nsvg__actualHeight(p)); - } - } - - nsvg__resetPath(p); - - nsvg__moveTo(p, x1, y1); - nsvg__lineTo(p, x2, y2); - - nsvg__addPath(p, 0); - - nsvg__addShape(p); -} - -static void nsvg__parsePoly(NSVGparser* p, const char** attr, int closeFlag) -{ - int i; - const char* s; - float args[2]; - int nargs, npts = 0; - char item[64]; - - nsvg__resetPath(p); - - for (i = 0; attr[i]; i += 2) { - if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) { - if (strcmp(attr[i], "points") == 0) { - s = attr[i + 1]; - nargs = 0; - while (*s) { - s = nsvg__getNextPathItem(s, item); - args[nargs++] = (float)nsvg__atof(item); - if (nargs >= 2) { - if (npts == 0) - nsvg__moveTo(p, args[0], args[1]); - else - nsvg__lineTo(p, args[0], args[1]); - nargs = 0; - npts++; - } - } - } - } - } - - nsvg__addPath(p, (char)closeFlag); - - nsvg__addShape(p); -} - -static void nsvg__parseSVG(NSVGparser* p, const char** attr) -{ - int i; - for (i = 0; attr[i]; i += 2) { - if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) { - if (strcmp(attr[i], "width") == 0) { - p->image->width = nsvg__parseCoordinate(p, attr[i + 1], 0.0f, 0.0f); - } else if (strcmp(attr[i], "height") == 0) { - p->image->height = nsvg__parseCoordinate(p, attr[i + 1], 0.0f, 0.0f); - } else if (strcmp(attr[i], "viewBox") == 0) { - const char *s = attr[i + 1]; - char buf[64]; - s = nsvg__parseNumber(s, buf, 64); - p->viewMinx = nsvg__atof(buf); - while (*s && (nsvg__isspace(*s) || *s == '%' || *s == ',')) s++; - if (!*s) return; - s = nsvg__parseNumber(s, buf, 64); - p->viewMiny = nsvg__atof(buf); - while (*s && (nsvg__isspace(*s) || *s == '%' || *s == ',')) s++; - if (!*s) return; - s = nsvg__parseNumber(s, buf, 64); - p->viewWidth = nsvg__atof(buf); - while (*s && (nsvg__isspace(*s) || *s == '%' || *s == ',')) s++; - if (!*s) return; - s = nsvg__parseNumber(s, buf, 64); - p->viewHeight = nsvg__atof(buf); - } else if (strcmp(attr[i], "preserveAspectRatio") == 0) { - if (strstr(attr[i + 1], "none") != 0) { - // No uniform scaling - p->alignType = NSVG_ALIGN_NONE; - } else { - // Parse X align - if (strstr(attr[i + 1], "xMin") != 0) - p->alignX = NSVG_ALIGN_MIN; - else if (strstr(attr[i + 1], "xMid") != 0) - p->alignX = NSVG_ALIGN_MID; - else if (strstr(attr[i + 1], "xMax") != 0) - p->alignX = NSVG_ALIGN_MAX; - // Parse X align - if (strstr(attr[i + 1], "yMin") != 0) - p->alignY = NSVG_ALIGN_MIN; - else if (strstr(attr[i + 1], "yMid") != 0) - p->alignY = NSVG_ALIGN_MID; - else if (strstr(attr[i + 1], "yMax") != 0) - p->alignY = NSVG_ALIGN_MAX; - // Parse meet/slice - p->alignType = NSVG_ALIGN_MEET; - if (strstr(attr[i + 1], "slice") != 0) - p->alignType = NSVG_ALIGN_SLICE; - } - } - } - } -} - -static void nsvg__parseGradient(NSVGparser* p, const char** attr, char type) -{ - int i; - NSVGgradientData* grad = (NSVGgradientData*)malloc(sizeof(NSVGgradientData)); - if (grad == NULL) return; - memset(grad, 0, sizeof(NSVGgradientData)); - grad->units = NSVG_OBJECT_SPACE; - grad->type = type; - if (grad->type == NSVG_PAINT_LINEAR_GRADIENT) { - grad->linear.x1 = nsvg__coord(0.0f, NSVG_UNITS_PERCENT); - grad->linear.y1 = nsvg__coord(0.0f, NSVG_UNITS_PERCENT); - grad->linear.x2 = nsvg__coord(100.0f, NSVG_UNITS_PERCENT); - grad->linear.y2 = nsvg__coord(0.0f, NSVG_UNITS_PERCENT); - } else if (grad->type == NSVG_PAINT_RADIAL_GRADIENT) { - grad->radial.cx = nsvg__coord(50.0f, NSVG_UNITS_PERCENT); - grad->radial.cy = nsvg__coord(50.0f, NSVG_UNITS_PERCENT); - grad->radial.r = nsvg__coord(50.0f, NSVG_UNITS_PERCENT); - } - - nsvg__xformIdentity(grad->xform); - - for (i = 0; attr[i]; i += 2) { - if (strcmp(attr[i], "id") == 0) { - strncpy(grad->id, attr[i+1], 63); - grad->id[63] = '\0'; - } else if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) { - if (strcmp(attr[i], "gradientUnits") == 0) { - if (strcmp(attr[i+1], "objectBoundingBox") == 0) - grad->units = NSVG_OBJECT_SPACE; - else - grad->units = NSVG_USER_SPACE; - } else if (strcmp(attr[i], "gradientTransform") == 0) { - nsvg__parseTransform(grad->xform, attr[i + 1]); - } else if (strcmp(attr[i], "cx") == 0) { - grad->radial.cx = nsvg__parseCoordinateRaw(attr[i + 1]); - } else if (strcmp(attr[i], "cy") == 0) { - grad->radial.cy = nsvg__parseCoordinateRaw(attr[i + 1]); - } else if (strcmp(attr[i], "r") == 0) { - grad->radial.r = nsvg__parseCoordinateRaw(attr[i + 1]); - } else if (strcmp(attr[i], "fx") == 0) { - grad->radial.fx = nsvg__parseCoordinateRaw(attr[i + 1]); - } else if (strcmp(attr[i], "fy") == 0) { - grad->radial.fy = nsvg__parseCoordinateRaw(attr[i + 1]); - } else if (strcmp(attr[i], "x1") == 0) { - grad->linear.x1 = nsvg__parseCoordinateRaw(attr[i + 1]); - } else if (strcmp(attr[i], "y1") == 0) { - grad->linear.y1 = nsvg__parseCoordinateRaw(attr[i + 1]); - } else if (strcmp(attr[i], "x2") == 0) { - grad->linear.x2 = nsvg__parseCoordinateRaw(attr[i + 1]); - } else if (strcmp(attr[i], "y2") == 0) { - grad->linear.y2 = nsvg__parseCoordinateRaw(attr[i + 1]); - } else if (strcmp(attr[i], "spreadMethod") == 0) { - if (strcmp(attr[i+1], "pad") == 0) - grad->spread = NSVG_SPREAD_PAD; - else if (strcmp(attr[i+1], "reflect") == 0) - grad->spread = NSVG_SPREAD_REFLECT; - else if (strcmp(attr[i+1], "repeat") == 0) - grad->spread = NSVG_SPREAD_REPEAT; - } else if (strcmp(attr[i], "xlink:href") == 0) { - const char *href = attr[i+1]; - strncpy(grad->ref, href+1, 62); - grad->ref[62] = '\0'; - } - } - } - - grad->next = p->gradients; - p->gradients = grad; -} - -static void nsvg__parseGradientStop(NSVGparser* p, const char** attr) -{ - NSVGattrib* curAttr = nsvg__getAttr(p); - NSVGgradientData* grad; - NSVGgradientStop* stop; - int i, idx; - - curAttr->stopOffset = 0; - curAttr->stopColor = 0; - curAttr->stopOpacity = 1.0f; - - for (i = 0; attr[i]; i += 2) { - nsvg__parseAttr(p, attr[i], attr[i + 1]); - } - - // Add stop to the last gradient. - grad = p->gradients; - if (grad == NULL) return; - - grad->nstops++; - grad->stops = (NSVGgradientStop*)realloc(grad->stops, sizeof(NSVGgradientStop)*grad->nstops); - if (grad->stops == NULL) return; - - // Insert - idx = grad->nstops-1; - for (i = 0; i < grad->nstops-1; i++) { - if (curAttr->stopOffset < grad->stops[i].offset) { - idx = i; - break; - } - } - if (idx != grad->nstops-1) { - for (i = grad->nstops-1; i > idx; i--) - grad->stops[i] = grad->stops[i-1]; - } - - stop = &grad->stops[idx]; - stop->color = curAttr->stopColor; - stop->color |= (unsigned int)(curAttr->stopOpacity*255) << 24; - stop->offset = curAttr->stopOffset; -} - -static void nsvg__startElement(void* ud, const char* el, const char** attr) -{ - NSVGparser* p = (NSVGparser*)ud; - - if (p->defsFlag) { - // Skip everything but gradients in defs - if (strcmp(el, "linearGradient") == 0) { - nsvg__parseGradient(p, attr, NSVG_PAINT_LINEAR_GRADIENT); - } else if (strcmp(el, "radialGradient") == 0) { - nsvg__parseGradient(p, attr, NSVG_PAINT_RADIAL_GRADIENT); - } else if (strcmp(el, "stop") == 0) { - nsvg__parseGradientStop(p, attr); - } - return; - } - - if (strcmp(el, "g") == 0) { - nsvg__pushAttr(p); - nsvg__parseAttribs(p, attr); - } else if (strcmp(el, "path") == 0) { - if (p->pathFlag) // Do not allow nested paths. - return; - nsvg__pushAttr(p); - nsvg__parsePath(p, attr); - nsvg__popAttr(p); - } else if (strcmp(el, "rect") == 0) { - nsvg__pushAttr(p); - nsvg__parseRect(p, attr); - nsvg__popAttr(p); - } else if (strcmp(el, "circle") == 0) { - nsvg__pushAttr(p); - nsvg__parseCircle(p, attr); - nsvg__popAttr(p); - } else if (strcmp(el, "ellipse") == 0) { - nsvg__pushAttr(p); - nsvg__parseEllipse(p, attr); - nsvg__popAttr(p); - } else if (strcmp(el, "line") == 0) { - nsvg__pushAttr(p); - nsvg__parseLine(p, attr); - nsvg__popAttr(p); - } else if (strcmp(el, "polyline") == 0) { - nsvg__pushAttr(p); - nsvg__parsePoly(p, attr, 0); - nsvg__popAttr(p); - } else if (strcmp(el, "polygon") == 0) { - nsvg__pushAttr(p); - nsvg__parsePoly(p, attr, 1); - nsvg__popAttr(p); - } else if (strcmp(el, "linearGradient") == 0) { - nsvg__parseGradient(p, attr, NSVG_PAINT_LINEAR_GRADIENT); - } else if (strcmp(el, "radialGradient") == 0) { - nsvg__parseGradient(p, attr, NSVG_PAINT_RADIAL_GRADIENT); - } else if (strcmp(el, "stop") == 0) { - nsvg__parseGradientStop(p, attr); - } else if (strcmp(el, "defs") == 0) { - p->defsFlag = 1; - } else if (strcmp(el, "svg") == 0) { - nsvg__parseSVG(p, attr); - } -} - -static void nsvg__endElement(void* ud, const char* el) -{ - NSVGparser* p = (NSVGparser*)ud; - - if (strcmp(el, "g") == 0) { - nsvg__popAttr(p); - } else if (strcmp(el, "path") == 0) { - p->pathFlag = 0; - } else if (strcmp(el, "defs") == 0) { - p->defsFlag = 0; - } -} - -static void nsvg__content(void* ud, const char* s) -{ - NSVG_NOTUSED(ud); - NSVG_NOTUSED(s); - // empty -} - -static void nsvg__imageBounds(NSVGparser* p, float* bounds) -{ - NSVGshape* shape; - shape = p->image->shapes; - if (shape == NULL) { - bounds[0] = bounds[1] = bounds[2] = bounds[3] = 0.0; - return; - } - bounds[0] = shape->bounds[0]; - bounds[1] = shape->bounds[1]; - bounds[2] = shape->bounds[2]; - bounds[3] = shape->bounds[3]; - for (shape = shape->next; shape != NULL; shape = shape->next) { - bounds[0] = nsvg__minf(bounds[0], shape->bounds[0]); - bounds[1] = nsvg__minf(bounds[1], shape->bounds[1]); - bounds[2] = nsvg__maxf(bounds[2], shape->bounds[2]); - bounds[3] = nsvg__maxf(bounds[3], shape->bounds[3]); - } -} - -static float nsvg__viewAlign(float content, float container, int type) -{ - if (type == NSVG_ALIGN_MIN) - return 0; - else if (type == NSVG_ALIGN_MAX) - return container - content; - // mid - return (container - content) * 0.5f; -} - -static void nsvg__scaleGradient(NSVGgradient* grad, float tx, float ty, float sx, float sy) -{ - float t[6]; - nsvg__xformSetTranslation(t, tx, ty); - nsvg__xformMultiply (grad->xform, t); - - nsvg__xformSetScale(t, sx, sy); - nsvg__xformMultiply (grad->xform, t); -} - -static void nsvg__scaleToViewbox(NSVGparser* p, const char* units) -{ - NSVGshape* shape; - NSVGpath* path; - float tx, ty, sx, sy, us, bounds[4], t[6], avgs; - int i; - float* pt; - - // Guess image size if not set completely. - nsvg__imageBounds(p, bounds); - - if (p->viewWidth == 0) { - if (p->image->width > 0) { - p->viewWidth = p->image->width; - } else { - p->viewMinx = bounds[0]; - p->viewWidth = bounds[2] - bounds[0]; - } - } - if (p->viewHeight == 0) { - if (p->image->height > 0) { - p->viewHeight = p->image->height; - } else { - p->viewMiny = bounds[1]; - p->viewHeight = bounds[3] - bounds[1]; - } - } - if (p->image->width == 0) - p->image->width = p->viewWidth; - if (p->image->height == 0) - p->image->height = p->viewHeight; - - tx = -p->viewMinx; - ty = -p->viewMiny; - sx = p->viewWidth > 0 ? p->image->width / p->viewWidth : 0; - sy = p->viewHeight > 0 ? p->image->height / p->viewHeight : 0; - // Unit scaling - us = 1.0f / nsvg__convertToPixels(p, nsvg__coord(1.0f, nsvg__parseUnits(units)), 0.0f, 1.0f); - - // Fix aspect ratio - if (p->alignType == NSVG_ALIGN_MEET) { - // fit whole image into viewbox - sx = sy = nsvg__minf(sx, sy); - tx += nsvg__viewAlign(p->viewWidth*sx, p->image->width, p->alignX) / sx; - ty += nsvg__viewAlign(p->viewHeight*sy, p->image->height, p->alignY) / sy; - } else if (p->alignType == NSVG_ALIGN_SLICE) { - // fill whole viewbox with image - sx = sy = nsvg__maxf(sx, sy); - tx += nsvg__viewAlign(p->viewWidth*sx, p->image->width, p->alignX) / sx; - ty += nsvg__viewAlign(p->viewHeight*sy, p->image->height, p->alignY) / sy; - } - - // Transform - sx *= us; - sy *= us; - avgs = (sx+sy) / 2.0f; - for (shape = p->image->shapes; shape != NULL; shape = shape->next) { - shape->bounds[0] = (shape->bounds[0] + tx) * sx; - shape->bounds[1] = (shape->bounds[1] + ty) * sy; - shape->bounds[2] = (shape->bounds[2] + tx) * sx; - shape->bounds[3] = (shape->bounds[3] + ty) * sy; - for (path = shape->paths; path != NULL; path = path->next) { - path->bounds[0] = (path->bounds[0] + tx) * sx; - path->bounds[1] = (path->bounds[1] + ty) * sy; - path->bounds[2] = (path->bounds[2] + tx) * sx; - path->bounds[3] = (path->bounds[3] + ty) * sy; - for (i =0; i < path->npts; i++) { - pt = &path->pts[i*2]; - pt[0] = (pt[0] + tx) * sx; - pt[1] = (pt[1] + ty) * sy; - } - } - - if (shape->fill.type == NSVG_PAINT_LINEAR_GRADIENT || shape->fill.type == NSVG_PAINT_RADIAL_GRADIENT) { - nsvg__scaleGradient(shape->fill.gradient, tx,ty, sx,sy); - memcpy(t, shape->fill.gradient->xform, sizeof(float)*6); - nsvg__xformInverse(shape->fill.gradient->xform, t); - } - if (shape->stroke.type == NSVG_PAINT_LINEAR_GRADIENT || shape->stroke.type == NSVG_PAINT_RADIAL_GRADIENT) { - nsvg__scaleGradient(shape->stroke.gradient, tx,ty, sx,sy); - memcpy(t, shape->stroke.gradient->xform, sizeof(float)*6); - nsvg__xformInverse(shape->stroke.gradient->xform, t); - } - - shape->strokeWidth *= avgs; - shape->strokeDashOffset *= avgs; - for (i = 0; i < shape->strokeDashCount; i++) - shape->strokeDashArray[i] *= avgs; - } -} - -NSVGimage* nsvgParse(char* input, const char* units, float dpi) -{ - NSVGparser* p; - NSVGimage* ret = 0; - - p = nsvg__createParser(); - if (p == NULL) { - return NULL; - } - p->dpi = dpi; - - nsvg__parseXML(input, nsvg__startElement, nsvg__endElement, nsvg__content, p); - - // Scale to viewBox - nsvg__scaleToViewbox(p, units); - - ret = p->image; - p->image = NULL; - - nsvg__deleteParser(p); - - return ret; -} - -NSVGimage* nsvgParseFromFile(const char* filename, const char* units, float dpi) -{ - FILE* fp = NULL; - size_t size; - char* data = NULL; - NSVGimage* image = NULL; - - fp = fopen(filename, "rb"); - if (!fp) goto error; - fseek(fp, 0, SEEK_END); - size = ftell(fp); - fseek(fp, 0, SEEK_SET); - data = (char*)malloc(size+1); - if (data == NULL) goto error; - if (fread(data, 1, size, fp) != size) goto error; - data[size] = '\0'; // Must be null terminated. - fclose(fp); - image = nsvgParse(data, units, dpi); - free(data); - - return image; - -error: - if (fp) fclose(fp); - if (data) free(data); - if (image) nsvgDelete(image); - return NULL; -} - -NSVGpath* nsvgDuplicatePath(NSVGpath* p) -{ - NSVGpath* res = NULL; - - if (p == NULL) - return NULL; - - res = (NSVGpath*)malloc(sizeof(NSVGpath)); - if (res == NULL) goto error; - memset(res, 0, sizeof(NSVGpath)); - - res->pts = (float*)malloc(p->npts*2*sizeof(float)); - if (res->pts == NULL) goto error; - memcpy(res->pts, p->pts, p->npts * sizeof(float) * 2); - res->npts = p->npts; - - memcpy(res->bounds, p->bounds, sizeof(p->bounds)); - - res->closed = p->closed; - - return res; - -error: - if (res != NULL) { - free(res->pts); - free(res); - } - return NULL; -} - -void nsvgDelete(NSVGimage* image) -{ - NSVGshape *snext, *shape; - if (image == NULL) return; - shape = image->shapes; - while (shape != NULL) { - snext = shape->next; - nsvg__deletePaths(shape->paths); - nsvg__deletePaint(&shape->fill); - nsvg__deletePaint(&shape->stroke); - free(shape); - shape = snext; - } - free(image); -} - -#endif // NANOSVG_IMPLEMENTATION - -#endif // NANOSVG_H diff --git a/src/external/nanosvgrast.h b/src/external/nanosvgrast.h deleted file mode 100644 index 6e23acb7b..000000000 --- a/src/external/nanosvgrast.h +++ /dev/null @@ -1,1458 +0,0 @@ -/* - * Copyright (c) 2013-14 Mikko Mononen memon@inside.org - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the authors be held liable for any damages - * arising from the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software - * in a product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - * - * The polygon rasterization is heavily based on stb_truetype rasterizer - * by Sean Barrett - http://nothings.org/ - * - */ - -#ifndef NANOSVGRAST_H -#define NANOSVGRAST_H - -#include "nanosvg.h" - -#ifndef NANOSVGRAST_CPLUSPLUS -#ifdef __cplusplus -extern "C" { -#endif -#endif - -typedef struct NSVGrasterizer NSVGrasterizer; - -/* Example Usage: - // Load SVG - NSVGimage* image; - image = nsvgParseFromFile("test.svg", "px", 96); - - // Create rasterizer (can be used to render multiple images). - struct NSVGrasterizer* rast = nsvgCreateRasterizer(); - // Allocate memory for image - unsigned char* img = malloc(w*h*4); - // Rasterize - nsvgRasterize(rast, image, 0,0,1, img, w, h, w*4); -*/ - -// Allocated rasterizer context. -NSVGrasterizer* nsvgCreateRasterizer(void); - -// Rasterizes SVG image, returns RGBA image (non-premultiplied alpha) -// r - pointer to rasterizer context -// image - pointer to image to rasterize -// tx,ty - image offset (applied after scaling) -// scale - image scale -// dst - pointer to destination image data, 4 bytes per pixel (RGBA) -// w - width of the image to render -// h - height of the image to render -// stride - number of bytes per scaleline in the destination buffer -void nsvgRasterize(NSVGrasterizer* r, - NSVGimage* image, float tx, float ty, float scale, - unsigned char* dst, int w, int h, int stride); - -// Deletes rasterizer context. -void nsvgDeleteRasterizer(NSVGrasterizer*); - - -#ifndef NANOSVGRAST_CPLUSPLUS -#ifdef __cplusplus -} -#endif -#endif - -#ifdef NANOSVGRAST_IMPLEMENTATION - -#include -#include -#include - -#define NSVG__SUBSAMPLES 5 -#define NSVG__FIXSHIFT 10 -#define NSVG__FIX (1 << NSVG__FIXSHIFT) -#define NSVG__FIXMASK (NSVG__FIX-1) -#define NSVG__MEMPAGE_SIZE 1024 - -typedef struct NSVGedge { - float x0,y0, x1,y1; - int dir; - struct NSVGedge* next; -} NSVGedge; - -typedef struct NSVGpoint { - float x, y; - float dx, dy; - float len; - float dmx, dmy; - unsigned char flags; -} NSVGpoint; - -typedef struct NSVGactiveEdge { - int x,dx; - float ey; - int dir; - struct NSVGactiveEdge *next; -} NSVGactiveEdge; - -typedef struct NSVGmemPage { - unsigned char mem[NSVG__MEMPAGE_SIZE]; - int size; - struct NSVGmemPage* next; -} NSVGmemPage; - -typedef struct NSVGcachedPaint { - char type; - char spread; - float xform[6]; - unsigned int colors[256]; -} NSVGcachedPaint; - -struct NSVGrasterizer -{ - float px, py; - - float tessTol; - float distTol; - - NSVGedge* edges; - int nedges; - int cedges; - - NSVGpoint* points; - int npoints; - int cpoints; - - NSVGpoint* points2; - int npoints2; - int cpoints2; - - NSVGactiveEdge* freelist; - NSVGmemPage* pages; - NSVGmemPage* curpage; - - unsigned char* scanline; - int cscanline; - - unsigned char* bitmap; - int width, height, stride; -}; - -NSVGrasterizer* nsvgCreateRasterizer(void) -{ - NSVGrasterizer* r = (NSVGrasterizer*)malloc(sizeof(NSVGrasterizer)); - if (r == NULL) goto error; - memset(r, 0, sizeof(NSVGrasterizer)); - - r->tessTol = 0.25f; - r->distTol = 0.01f; - - return r; - -error: - nsvgDeleteRasterizer(r); - return NULL; -} - -void nsvgDeleteRasterizer(NSVGrasterizer* r) -{ - NSVGmemPage* p; - - if (r == NULL) return; - - p = r->pages; - while (p != NULL) { - NSVGmemPage* next = p->next; - free(p); - p = next; - } - - if (r->edges) free(r->edges); - if (r->points) free(r->points); - if (r->points2) free(r->points2); - if (r->scanline) free(r->scanline); - - free(r); -} - -static NSVGmemPage* nsvg__nextPage(NSVGrasterizer* r, NSVGmemPage* cur) -{ - NSVGmemPage *newp; - - // If using existing chain, return the next page in chain - if (cur != NULL && cur->next != NULL) { - return cur->next; - } - - // Alloc new page - newp = (NSVGmemPage*)malloc(sizeof(NSVGmemPage)); - if (newp == NULL) return NULL; - memset(newp, 0, sizeof(NSVGmemPage)); - - // Add to linked list - if (cur != NULL) - cur->next = newp; - else - r->pages = newp; - - return newp; -} - -static void nsvg__resetPool(NSVGrasterizer* r) -{ - NSVGmemPage* p = r->pages; - while (p != NULL) { - p->size = 0; - p = p->next; - } - r->curpage = r->pages; -} - -static unsigned char* nsvg__alloc(NSVGrasterizer* r, int size) -{ - unsigned char* buf; - if (size > NSVG__MEMPAGE_SIZE) return NULL; - if (r->curpage == NULL || r->curpage->size+size > NSVG__MEMPAGE_SIZE) { - r->curpage = nsvg__nextPage(r, r->curpage); - } - buf = &r->curpage->mem[r->curpage->size]; - r->curpage->size += size; - return buf; -} - -static int nsvg__ptEquals(float x1, float y1, float x2, float y2, float tol) -{ - float dx = x2 - x1; - float dy = y2 - y1; - return dx*dx + dy*dy < tol*tol; -} - -static void nsvg__addPathPoint(NSVGrasterizer* r, float x, float y, int flags) -{ - NSVGpoint* pt; - - if (r->npoints > 0) { - pt = &r->points[r->npoints-1]; - if (nsvg__ptEquals(pt->x,pt->y, x,y, r->distTol)) { - pt->flags = (unsigned char)(pt->flags | flags); - return; - } - } - - if (r->npoints+1 > r->cpoints) { - r->cpoints = r->cpoints > 0 ? r->cpoints * 2 : 64; - r->points = (NSVGpoint*)realloc(r->points, sizeof(NSVGpoint) * r->cpoints); - if (r->points == NULL) return; - } - - pt = &r->points[r->npoints]; - pt->x = x; - pt->y = y; - pt->flags = (unsigned char)flags; - r->npoints++; -} - -static void nsvg__appendPathPoint(NSVGrasterizer* r, NSVGpoint pt) -{ - if (r->npoints+1 > r->cpoints) { - r->cpoints = r->cpoints > 0 ? r->cpoints * 2 : 64; - r->points = (NSVGpoint*)realloc(r->points, sizeof(NSVGpoint) * r->cpoints); - if (r->points == NULL) return; - } - r->points[r->npoints] = pt; - r->npoints++; -} - -static void nsvg__duplicatePoints(NSVGrasterizer* r) -{ - if (r->npoints > r->cpoints2) { - r->cpoints2 = r->npoints; - r->points2 = (NSVGpoint*)realloc(r->points2, sizeof(NSVGpoint) * r->cpoints2); - if (r->points2 == NULL) return; - } - - memcpy(r->points2, r->points, sizeof(NSVGpoint) * r->npoints); - r->npoints2 = r->npoints; -} - -static void nsvg__addEdge(NSVGrasterizer* r, float x0, float y0, float x1, float y1) -{ - NSVGedge* e; - - // Skip horizontal edges - if (y0 == y1) - return; - - if (r->nedges+1 > r->cedges) { - r->cedges = r->cedges > 0 ? r->cedges * 2 : 64; - r->edges = (NSVGedge*)realloc(r->edges, sizeof(NSVGedge) * r->cedges); - if (r->edges == NULL) return; - } - - e = &r->edges[r->nedges]; - r->nedges++; - - if (y0 < y1) { - e->x0 = x0; - e->y0 = y0; - e->x1 = x1; - e->y1 = y1; - e->dir = 1; - } else { - e->x0 = x1; - e->y0 = y1; - e->x1 = x0; - e->y1 = y0; - e->dir = -1; - } -} - -static float nsvg__normalize(float *x, float* y) -{ - float d = sqrtf((*x)*(*x) + (*y)*(*y)); - if (d > 1e-6f) { - float id = 1.0f / d; - *x *= id; - *y *= id; - } - return d; -} - -static float nsvg__absf(float x) { return x < 0 ? -x : x; } - -static void nsvg__flattenCubicBez(NSVGrasterizer* r, - float x1, float y1, float x2, float y2, - float x3, float y3, float x4, float y4, - int level, int type) -{ - float x12,y12,x23,y23,x34,y34,x123,y123,x234,y234,x1234,y1234; - float dx,dy,d2,d3; - - if (level > 10) return; - - x12 = (x1+x2)*0.5f; - y12 = (y1+y2)*0.5f; - x23 = (x2+x3)*0.5f; - y23 = (y2+y3)*0.5f; - x34 = (x3+x4)*0.5f; - y34 = (y3+y4)*0.5f; - x123 = (x12+x23)*0.5f; - y123 = (y12+y23)*0.5f; - - dx = x4 - x1; - dy = y4 - y1; - d2 = nsvg__absf(((x2 - x4) * dy - (y2 - y4) * dx)); - d3 = nsvg__absf(((x3 - x4) * dy - (y3 - y4) * dx)); - - if ((d2 + d3)*(d2 + d3) < r->tessTol * (dx*dx + dy*dy)) { - nsvg__addPathPoint(r, x4, y4, type); - return; - } - - x234 = (x23+x34)*0.5f; - y234 = (y23+y34)*0.5f; - x1234 = (x123+x234)*0.5f; - y1234 = (y123+y234)*0.5f; - - nsvg__flattenCubicBez(r, x1,y1, x12,y12, x123,y123, x1234,y1234, level+1, 0); - nsvg__flattenCubicBez(r, x1234,y1234, x234,y234, x34,y34, x4,y4, level+1, type); -} - -static void nsvg__flattenShape(NSVGrasterizer* r, NSVGshape* shape, float scale) -{ - int i, j; - NSVGpath* path; - - for (path = shape->paths; path != NULL; path = path->next) { - r->npoints = 0; - // Flatten path - nsvg__addPathPoint(r, path->pts[0]*scale, path->pts[1]*scale, 0); - for (i = 0; i < path->npts-1; i += 3) { - float* p = &path->pts[i*2]; - nsvg__flattenCubicBez(r, p[0]*scale,p[1]*scale, p[2]*scale,p[3]*scale, p[4]*scale,p[5]*scale, p[6]*scale,p[7]*scale, 0, 0); - } - // Close path - nsvg__addPathPoint(r, path->pts[0]*scale, path->pts[1]*scale, 0); - // Build edges - for (i = 0, j = r->npoints-1; i < r->npoints; j = i++) - nsvg__addEdge(r, r->points[j].x, r->points[j].y, r->points[i].x, r->points[i].y); - } -} - -enum NSVGpointFlags -{ - NSVG_PT_CORNER = 0x01, - NSVG_PT_BEVEL = 0x02, - NSVG_PT_LEFT = 0x04 -}; - -static void nsvg__initClosed(NSVGpoint* left, NSVGpoint* right, NSVGpoint* p0, NSVGpoint* p1, float lineWidth) -{ - float w = lineWidth * 0.5f; - float dx = p1->x - p0->x; - float dy = p1->y - p0->y; - float len = nsvg__normalize(&dx, &dy); - float px = p0->x + dx*len*0.5f, py = p0->y + dy*len*0.5f; - float dlx = dy, dly = -dx; - float lx = px - dlx*w, ly = py - dly*w; - float rx = px + dlx*w, ry = py + dly*w; - left->x = lx; left->y = ly; - right->x = rx; right->y = ry; -} - -static void nsvg__buttCap(NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p, float dx, float dy, float lineWidth, int connect) -{ - float w = lineWidth * 0.5f; - float px = p->x, py = p->y; - float dlx = dy, dly = -dx; - float lx = px - dlx*w, ly = py - dly*w; - float rx = px + dlx*w, ry = py + dly*w; - - nsvg__addEdge(r, lx, ly, rx, ry); - - if (connect) { - nsvg__addEdge(r, left->x, left->y, lx, ly); - nsvg__addEdge(r, rx, ry, right->x, right->y); - } - left->x = lx; left->y = ly; - right->x = rx; right->y = ry; -} - -static void nsvg__squareCap(NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p, float dx, float dy, float lineWidth, int connect) -{ - float w = lineWidth * 0.5f; - float px = p->x - dx*w, py = p->y - dy*w; - float dlx = dy, dly = -dx; - float lx = px - dlx*w, ly = py - dly*w; - float rx = px + dlx*w, ry = py + dly*w; - - nsvg__addEdge(r, lx, ly, rx, ry); - - if (connect) { - nsvg__addEdge(r, left->x, left->y, lx, ly); - nsvg__addEdge(r, rx, ry, right->x, right->y); - } - left->x = lx; left->y = ly; - right->x = rx; right->y = ry; -} - -#ifndef NSVG_PI -#define NSVG_PI (3.14159265358979323846264338327f) -#endif - -static void nsvg__roundCap(NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p, float dx, float dy, float lineWidth, int ncap, int connect) -{ - int i; - float w = lineWidth * 0.5f; - float px = p->x, py = p->y; - float dlx = dy, dly = -dx; - float lx = 0, ly = 0, rx = 0, ry = 0, prevx = 0, prevy = 0; - - for (i = 0; i < ncap; i++) { - float a = (float)i/(float)(ncap-1)*NSVG_PI; - float ax = cosf(a) * w, ay = sinf(a) * w; - float x = px - dlx*ax - dx*ay; - float y = py - dly*ax - dy*ay; - - if (i > 0) - nsvg__addEdge(r, prevx, prevy, x, y); - - prevx = x; - prevy = y; - - if (i == 0) { - lx = x; ly = y; - } else if (i == ncap-1) { - rx = x; ry = y; - } - } - - if (connect) { - nsvg__addEdge(r, left->x, left->y, lx, ly); - nsvg__addEdge(r, rx, ry, right->x, right->y); - } - - left->x = lx; left->y = ly; - right->x = rx; right->y = ry; -} - -static void nsvg__bevelJoin(NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p0, NSVGpoint* p1, float lineWidth) -{ - float w = lineWidth * 0.5f; - float dlx0 = p0->dy, dly0 = -p0->dx; - float dlx1 = p1->dy, dly1 = -p1->dx; - float lx0 = p1->x - (dlx0 * w), ly0 = p1->y - (dly0 * w); - float rx0 = p1->x + (dlx0 * w), ry0 = p1->y + (dly0 * w); - float lx1 = p1->x - (dlx1 * w), ly1 = p1->y - (dly1 * w); - float rx1 = p1->x + (dlx1 * w), ry1 = p1->y + (dly1 * w); - - nsvg__addEdge(r, lx0, ly0, left->x, left->y); - nsvg__addEdge(r, lx1, ly1, lx0, ly0); - - nsvg__addEdge(r, right->x, right->y, rx0, ry0); - nsvg__addEdge(r, rx0, ry0, rx1, ry1); - - left->x = lx1; left->y = ly1; - right->x = rx1; right->y = ry1; -} - -static void nsvg__miterJoin(NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p0, NSVGpoint* p1, float lineWidth) -{ - float w = lineWidth * 0.5f; - float dlx0 = p0->dy, dly0 = -p0->dx; - float dlx1 = p1->dy, dly1 = -p1->dx; - float lx0, rx0, lx1, rx1; - float ly0, ry0, ly1, ry1; - - if (p1->flags & NSVG_PT_LEFT) { - lx0 = lx1 = p1->x - p1->dmx * w; - ly0 = ly1 = p1->y - p1->dmy * w; - nsvg__addEdge(r, lx1, ly1, left->x, left->y); - - rx0 = p1->x + (dlx0 * w); - ry0 = p1->y + (dly0 * w); - rx1 = p1->x + (dlx1 * w); - ry1 = p1->y + (dly1 * w); - nsvg__addEdge(r, right->x, right->y, rx0, ry0); - nsvg__addEdge(r, rx0, ry0, rx1, ry1); - } else { - lx0 = p1->x - (dlx0 * w); - ly0 = p1->y - (dly0 * w); - lx1 = p1->x - (dlx1 * w); - ly1 = p1->y - (dly1 * w); - nsvg__addEdge(r, lx0, ly0, left->x, left->y); - nsvg__addEdge(r, lx1, ly1, lx0, ly0); - - rx0 = rx1 = p1->x + p1->dmx * w; - ry0 = ry1 = p1->y + p1->dmy * w; - nsvg__addEdge(r, right->x, right->y, rx1, ry1); - } - - left->x = lx1; left->y = ly1; - right->x = rx1; right->y = ry1; -} - -static void nsvg__roundJoin(NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p0, NSVGpoint* p1, float lineWidth, int ncap) -{ - int i, n; - float w = lineWidth * 0.5f; - float dlx0 = p0->dy, dly0 = -p0->dx; - float dlx1 = p1->dy, dly1 = -p1->dx; - float a0 = atan2f(dly0, dlx0); - float a1 = atan2f(dly1, dlx1); - float da = a1 - a0; - float lx, ly, rx, ry; - - if (da < NSVG_PI) da += NSVG_PI*2; - if (da > NSVG_PI) da -= NSVG_PI*2; - - n = (int)ceilf((nsvg__absf(da) / NSVG_PI) * (float)ncap); - if (n < 2) n = 2; - if (n > ncap) n = ncap; - - lx = left->x; - ly = left->y; - rx = right->x; - ry = right->y; - - for (i = 0; i < n; i++) { - float u = (float)i/(float)(n-1); - float a = a0 + u*da; - float ax = cosf(a) * w, ay = sinf(a) * w; - float lx1 = p1->x - ax, ly1 = p1->y - ay; - float rx1 = p1->x + ax, ry1 = p1->y + ay; - - nsvg__addEdge(r, lx1, ly1, lx, ly); - nsvg__addEdge(r, rx, ry, rx1, ry1); - - lx = lx1; ly = ly1; - rx = rx1; ry = ry1; - } - - left->x = lx; left->y = ly; - right->x = rx; right->y = ry; -} - -static void nsvg__straightJoin(NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p1, float lineWidth) -{ - float w = lineWidth * 0.5f; - float lx = p1->x - (p1->dmx * w), ly = p1->y - (p1->dmy * w); - float rx = p1->x + (p1->dmx * w), ry = p1->y + (p1->dmy * w); - - nsvg__addEdge(r, lx, ly, left->x, left->y); - nsvg__addEdge(r, right->x, right->y, rx, ry); - - left->x = lx; left->y = ly; - right->x = rx; right->y = ry; -} - -static int nsvg__curveDivs(float r, float arc, float tol) -{ - float da = acosf(r / (r + tol)) * 2.0f; - int divs = (int)ceilf(arc / da); - if (divs < 2) divs = 2; - return divs; -} - -static void nsvg__expandStroke(NSVGrasterizer* r, NSVGpoint* points, int npoints, int closed, int lineJoin, int lineCap, float lineWidth) -{ - int ncap = nsvg__curveDivs(lineWidth*0.5f, NSVG_PI, r->tessTol); // Calculate divisions per half circle. - NSVGpoint left = {0,0,0,0,0,0,0,0}, right = {0,0,0,0,0,0,0,0}, firstLeft = {0,0,0,0,0,0,0,0}, firstRight = {0,0,0,0,0,0,0,0}; - NSVGpoint* p0, *p1; - int j, s, e; - - // Build stroke edges - if (closed) { - // Looping - p0 = &points[npoints-1]; - p1 = &points[0]; - s = 0; - e = npoints; - } else { - // Add cap - p0 = &points[0]; - p1 = &points[1]; - s = 1; - e = npoints-1; - } - - if (closed) { - nsvg__initClosed(&left, &right, p0, p1, lineWidth); - firstLeft = left; - firstRight = right; - } else { - // Add cap - float dx = p1->x - p0->x; - float dy = p1->y - p0->y; - nsvg__normalize(&dx, &dy); - if (lineCap == NSVG_CAP_BUTT) - nsvg__buttCap(r, &left, &right, p0, dx, dy, lineWidth, 0); - else if (lineCap == NSVG_CAP_SQUARE) - nsvg__squareCap(r, &left, &right, p0, dx, dy, lineWidth, 0); - else if (lineCap == NSVG_CAP_ROUND) - nsvg__roundCap(r, &left, &right, p0, dx, dy, lineWidth, ncap, 0); - } - - for (j = s; j < e; ++j) { - if (p1->flags & NSVG_PT_CORNER) { - if (lineJoin == NSVG_JOIN_ROUND) - nsvg__roundJoin(r, &left, &right, p0, p1, lineWidth, ncap); - else if (lineJoin == NSVG_JOIN_BEVEL || (p1->flags & NSVG_PT_BEVEL)) - nsvg__bevelJoin(r, &left, &right, p0, p1, lineWidth); - else - nsvg__miterJoin(r, &left, &right, p0, p1, lineWidth); - } else { - nsvg__straightJoin(r, &left, &right, p1, lineWidth); - } - p0 = p1++; - } - - if (closed) { - // Loop it - nsvg__addEdge(r, firstLeft.x, firstLeft.y, left.x, left.y); - nsvg__addEdge(r, right.x, right.y, firstRight.x, firstRight.y); - } else { - // Add cap - float dx = p1->x - p0->x; - float dy = p1->y - p0->y; - nsvg__normalize(&dx, &dy); - if (lineCap == NSVG_CAP_BUTT) - nsvg__buttCap(r, &right, &left, p1, -dx, -dy, lineWidth, 1); - else if (lineCap == NSVG_CAP_SQUARE) - nsvg__squareCap(r, &right, &left, p1, -dx, -dy, lineWidth, 1); - else if (lineCap == NSVG_CAP_ROUND) - nsvg__roundCap(r, &right, &left, p1, -dx, -dy, lineWidth, ncap, 1); - } -} - -static void nsvg__prepareStroke(NSVGrasterizer* r, float miterLimit, int lineJoin) -{ - int i, j; - NSVGpoint* p0, *p1; - - p0 = &r->points[r->npoints-1]; - p1 = &r->points[0]; - for (i = 0; i < r->npoints; i++) { - // Calculate segment direction and length - p0->dx = p1->x - p0->x; - p0->dy = p1->y - p0->y; - p0->len = nsvg__normalize(&p0->dx, &p0->dy); - // Advance - p0 = p1++; - } - - // calculate joins - p0 = &r->points[r->npoints-1]; - p1 = &r->points[0]; - for (j = 0; j < r->npoints; j++) { - float dlx0, dly0, dlx1, dly1, dmr2, cross; - dlx0 = p0->dy; - dly0 = -p0->dx; - dlx1 = p1->dy; - dly1 = -p1->dx; - // Calculate extrusions - p1->dmx = (dlx0 + dlx1) * 0.5f; - p1->dmy = (dly0 + dly1) * 0.5f; - dmr2 = p1->dmx*p1->dmx + p1->dmy*p1->dmy; - if (dmr2 > 0.000001f) { - float s2 = 1.0f / dmr2; - if (s2 > 600.0f) { - s2 = 600.0f; - } - p1->dmx *= s2; - p1->dmy *= s2; - } - - // Clear flags, but keep the corner. - p1->flags = (p1->flags & NSVG_PT_CORNER) ? NSVG_PT_CORNER : 0; - - // Keep track of left turns. - cross = p1->dx * p0->dy - p0->dx * p1->dy; - if (cross > 0.0f) - p1->flags |= NSVG_PT_LEFT; - - // Check to see if the corner needs to be beveled. - if (p1->flags & NSVG_PT_CORNER) { - if ((dmr2 * miterLimit*miterLimit) < 1.0f || lineJoin == NSVG_JOIN_BEVEL || lineJoin == NSVG_JOIN_ROUND) { - p1->flags |= NSVG_PT_BEVEL; - } - } - - p0 = p1++; - } -} - -static void nsvg__flattenShapeStroke(NSVGrasterizer* r, NSVGshape* shape, float scale) -{ - int i, j, closed; - NSVGpath* path; - NSVGpoint* p0, *p1; - float miterLimit = shape->miterLimit; - int lineJoin = shape->strokeLineJoin; - int lineCap = shape->strokeLineCap; - float lineWidth = shape->strokeWidth * scale; - - for (path = shape->paths; path != NULL; path = path->next) { - // Flatten path - r->npoints = 0; - nsvg__addPathPoint(r, path->pts[0]*scale, path->pts[1]*scale, NSVG_PT_CORNER); - for (i = 0; i < path->npts-1; i += 3) { - float* p = &path->pts[i*2]; - nsvg__flattenCubicBez(r, p[0]*scale,p[1]*scale, p[2]*scale,p[3]*scale, p[4]*scale,p[5]*scale, p[6]*scale,p[7]*scale, 0, NSVG_PT_CORNER); - } - if (r->npoints < 2) - continue; - - closed = path->closed; - - // If the first and last points are the same, remove the last, mark as closed path. - p0 = &r->points[r->npoints-1]; - p1 = &r->points[0]; - if (nsvg__ptEquals(p0->x,p0->y, p1->x,p1->y, r->distTol)) { - r->npoints--; - p0 = &r->points[r->npoints-1]; - closed = 1; - } - - if (shape->strokeDashCount > 0) { - int idash = 0, dashState = 1; - float totalDist = 0, dashLen, allDashLen, dashOffset; - NSVGpoint cur; - - if (closed) - nsvg__appendPathPoint(r, r->points[0]); - - // Duplicate points -> points2. - nsvg__duplicatePoints(r); - - r->npoints = 0; - cur = r->points2[0]; - nsvg__appendPathPoint(r, cur); - - // Figure out dash offset. - allDashLen = 0; - for (j = 0; j < shape->strokeDashCount; j++) - allDashLen += shape->strokeDashArray[j]; - if (shape->strokeDashCount & 1) - allDashLen *= 2.0f; - // Find location inside pattern - dashOffset = fmodf(shape->strokeDashOffset, allDashLen); - if (dashOffset < 0.0f) - dashOffset += allDashLen; - - while (dashOffset > shape->strokeDashArray[idash]) { - dashOffset -= shape->strokeDashArray[idash]; - idash = (idash + 1) % shape->strokeDashCount; - } - dashLen = (shape->strokeDashArray[idash] - dashOffset) * scale; - - for (j = 1; j < r->npoints2; ) { - float dx = r->points2[j].x - cur.x; - float dy = r->points2[j].y - cur.y; - float dist = sqrtf(dx*dx + dy*dy); - - if ((totalDist + dist) > dashLen) { - // Calculate intermediate point - float d = (dashLen - totalDist) / dist; - float x = cur.x + dx * d; - float y = cur.y + dy * d; - nsvg__addPathPoint(r, x, y, NSVG_PT_CORNER); - - // Stroke - if (r->npoints > 1 && dashState) { - nsvg__prepareStroke(r, miterLimit, lineJoin); - nsvg__expandStroke(r, r->points, r->npoints, 0, lineJoin, lineCap, lineWidth); - } - // Advance dash pattern - dashState = !dashState; - idash = (idash+1) % shape->strokeDashCount; - dashLen = shape->strokeDashArray[idash] * scale; - // Restart - cur.x = x; - cur.y = y; - cur.flags = NSVG_PT_CORNER; - totalDist = 0.0f; - r->npoints = 0; - nsvg__appendPathPoint(r, cur); - } else { - totalDist += dist; - cur = r->points2[j]; - nsvg__appendPathPoint(r, cur); - j++; - } - } - // Stroke any leftover path - if (r->npoints > 1 && dashState) - nsvg__expandStroke(r, r->points, r->npoints, 0, lineJoin, lineCap, lineWidth); - } else { - nsvg__prepareStroke(r, miterLimit, lineJoin); - nsvg__expandStroke(r, r->points, r->npoints, closed, lineJoin, lineCap, lineWidth); - } - } -} - -static int nsvg__cmpEdge(const void *p, const void *q) -{ - const NSVGedge* a = (const NSVGedge*)p; - const NSVGedge* b = (const NSVGedge*)q; - - if (a->y0 < b->y0) return -1; - if (a->y0 > b->y0) return 1; - return 0; -} - - -static NSVGactiveEdge* nsvg__addActive(NSVGrasterizer* r, NSVGedge* e, float startPoint) -{ - NSVGactiveEdge* z; - - if (r->freelist != NULL) { - // Restore from freelist. - z = r->freelist; - r->freelist = z->next; - } else { - // Alloc new edge. - z = (NSVGactiveEdge*)nsvg__alloc(r, sizeof(NSVGactiveEdge)); - if (z == NULL) return NULL; - } - - float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0); -// STBTT_assert(e->y0 <= start_point); - // round dx down to avoid going too far - if (dxdy < 0) - z->dx = (int)(-floorf(NSVG__FIX * -dxdy)); - else - z->dx = (int)floorf(NSVG__FIX * dxdy); - z->x = (int)floorf(NSVG__FIX * (e->x0 + dxdy * (startPoint - e->y0))); -// z->x -= off_x * FIX; - z->ey = e->y1; - z->next = 0; - z->dir = e->dir; - - return z; -} - -static void nsvg__freeActive(NSVGrasterizer* r, NSVGactiveEdge* z) -{ - z->next = r->freelist; - r->freelist = z; -} - -static void nsvg__fillScanline(unsigned char* scanline, int len, int x0, int x1, int maxWeight, int* xmin, int* xmax) -{ - int i = x0 >> NSVG__FIXSHIFT; - int j = x1 >> NSVG__FIXSHIFT; - if (i < *xmin) *xmin = i; - if (j > *xmax) *xmax = j; - if (i < len && j >= 0) { - if (i == j) { - // x0,x1 are the same pixel, so compute combined coverage - scanline[i] = (unsigned char)(scanline[i] + ((x1 - x0) * maxWeight >> NSVG__FIXSHIFT)); - } else { - if (i >= 0) // add antialiasing for x0 - scanline[i] = (unsigned char)(scanline[i] + (((NSVG__FIX - (x0 & NSVG__FIXMASK)) * maxWeight) >> NSVG__FIXSHIFT)); - else - i = -1; // clip - - if (j < len) // add antialiasing for x1 - scanline[j] = (unsigned char)(scanline[j] + (((x1 & NSVG__FIXMASK) * maxWeight) >> NSVG__FIXSHIFT)); - else - j = len; // clip - - for (++i; i < j; ++i) // fill pixels between x0 and x1 - scanline[i] = (unsigned char)(scanline[i] + maxWeight); - } - } -} - -// note: this routine clips fills that extend off the edges... ideally this -// wouldn't happen, but it could happen if the truetype glyph bounding boxes -// are wrong, or if the user supplies a too-small bitmap -static void nsvg__fillActiveEdges(unsigned char* scanline, int len, NSVGactiveEdge* e, int maxWeight, int* xmin, int* xmax, char fillRule) -{ - // non-zero winding fill - int x0 = 0, w = 0; - - if (fillRule == NSVG_FILLRULE_NONZERO) { - // Non-zero - while (e != NULL) { - if (w == 0) { - // if we're currently at zero, we need to record the edge start point - x0 = e->x; w += e->dir; - } else { - int x1 = e->x; w += e->dir; - // if we went to zero, we need to draw - if (w == 0) - nsvg__fillScanline(scanline, len, x0, x1, maxWeight, xmin, xmax); - } - e = e->next; - } - } else if (fillRule == NSVG_FILLRULE_EVENODD) { - // Even-odd - while (e != NULL) { - if (w == 0) { - // if we're currently at zero, we need to record the edge start point - x0 = e->x; w = 1; - } else { - int x1 = e->x; w = 0; - nsvg__fillScanline(scanline, len, x0, x1, maxWeight, xmin, xmax); - } - e = e->next; - } - } -} - -static float nsvg__clampf(float a, float mn, float mx) { return a < mn ? mn : (a > mx ? mx : a); } - -static unsigned int nsvg__RGBA(unsigned char r, unsigned char g, unsigned char b, unsigned char a) -{ - return ((unsigned int)r) | ((unsigned int)g << 8) | ((unsigned int)b << 16) | ((unsigned int)a << 24); -} - -static unsigned int nsvg__lerpRGBA(unsigned int c0, unsigned int c1, float u) -{ - int iu = (int)(nsvg__clampf(u, 0.0f, 1.0f) * 256.0f); - int r = (((c0) & 0xff)*(256-iu) + (((c1) & 0xff)*iu)) >> 8; - int g = (((c0>>8) & 0xff)*(256-iu) + (((c1>>8) & 0xff)*iu)) >> 8; - int b = (((c0>>16) & 0xff)*(256-iu) + (((c1>>16) & 0xff)*iu)) >> 8; - int a = (((c0>>24) & 0xff)*(256-iu) + (((c1>>24) & 0xff)*iu)) >> 8; - return nsvg__RGBA((unsigned char)r, (unsigned char)g, (unsigned char)b, (unsigned char)a); -} - -static unsigned int nsvg__applyOpacity(unsigned int c, float u) -{ - int iu = (int)(nsvg__clampf(u, 0.0f, 1.0f) * 256.0f); - int r = (c) & 0xff; - int g = (c>>8) & 0xff; - int b = (c>>16) & 0xff; - int a = (((c>>24) & 0xff)*iu) >> 8; - return nsvg__RGBA((unsigned char)r, (unsigned char)g, (unsigned char)b, (unsigned char)a); -} - -static inline int nsvg__div255(int x) -{ - return ((x+1) * 257) >> 16; -} - -static void nsvg__scanlineSolid(unsigned char* dst, int count, unsigned char* cover, int x, int y, - float tx, float ty, float scale, NSVGcachedPaint* cache) -{ - - if (cache->type == NSVG_PAINT_COLOR) { - int i, cr, cg, cb, ca; - cr = cache->colors[0] & 0xff; - cg = (cache->colors[0] >> 8) & 0xff; - cb = (cache->colors[0] >> 16) & 0xff; - ca = (cache->colors[0] >> 24) & 0xff; - - for (i = 0; i < count; i++) { - int r,g,b; - int a = nsvg__div255((int)cover[0] * ca); - int ia = 255 - a; - // Premultiply - r = nsvg__div255(cr * a); - g = nsvg__div255(cg * a); - b = nsvg__div255(cb * a); - - // Blend over - r += nsvg__div255(ia * (int)dst[0]); - g += nsvg__div255(ia * (int)dst[1]); - b += nsvg__div255(ia * (int)dst[2]); - a += nsvg__div255(ia * (int)dst[3]); - - dst[0] = (unsigned char)r; - dst[1] = (unsigned char)g; - dst[2] = (unsigned char)b; - dst[3] = (unsigned char)a; - - cover++; - dst += 4; - } - } else if (cache->type == NSVG_PAINT_LINEAR_GRADIENT) { - // TODO: spread modes. - // TODO: plenty of opportunities to optimize. - float fx, fy, dx, gy; - float* t = cache->xform; - int i, cr, cg, cb, ca; - unsigned int c; - - fx = ((float)x - tx) / scale; - fy = ((float)y - ty) / scale; - dx = 1.0f / scale; - - for (i = 0; i < count; i++) { - int r,g,b,a,ia; - gy = fx*t[1] + fy*t[3] + t[5]; - c = cache->colors[(int)nsvg__clampf(gy*255.0f, 0, 255.0f)]; - cr = (c) & 0xff; - cg = (c >> 8) & 0xff; - cb = (c >> 16) & 0xff; - ca = (c >> 24) & 0xff; - - a = nsvg__div255((int)cover[0] * ca); - ia = 255 - a; - - // Premultiply - r = nsvg__div255(cr * a); - g = nsvg__div255(cg * a); - b = nsvg__div255(cb * a); - - // Blend over - r += nsvg__div255(ia * (int)dst[0]); - g += nsvg__div255(ia * (int)dst[1]); - b += nsvg__div255(ia * (int)dst[2]); - a += nsvg__div255(ia * (int)dst[3]); - - dst[0] = (unsigned char)r; - dst[1] = (unsigned char)g; - dst[2] = (unsigned char)b; - dst[3] = (unsigned char)a; - - cover++; - dst += 4; - fx += dx; - } - } else if (cache->type == NSVG_PAINT_RADIAL_GRADIENT) { - // TODO: spread modes. - // TODO: plenty of opportunities to optimize. - // TODO: focus (fx,fy) - float fx, fy, dx, gx, gy, gd; - float* t = cache->xform; - int i, cr, cg, cb, ca; - unsigned int c; - - fx = ((float)x - tx) / scale; - fy = ((float)y - ty) / scale; - dx = 1.0f / scale; - - for (i = 0; i < count; i++) { - int r,g,b,a,ia; - gx = fx*t[0] + fy*t[2] + t[4]; - gy = fx*t[1] + fy*t[3] + t[5]; - gd = sqrtf(gx*gx + gy*gy); - c = cache->colors[(int)nsvg__clampf(gd*255.0f, 0, 255.0f)]; - cr = (c) & 0xff; - cg = (c >> 8) & 0xff; - cb = (c >> 16) & 0xff; - ca = (c >> 24) & 0xff; - - a = nsvg__div255((int)cover[0] * ca); - ia = 255 - a; - - // Premultiply - r = nsvg__div255(cr * a); - g = nsvg__div255(cg * a); - b = nsvg__div255(cb * a); - - // Blend over - r += nsvg__div255(ia * (int)dst[0]); - g += nsvg__div255(ia * (int)dst[1]); - b += nsvg__div255(ia * (int)dst[2]); - a += nsvg__div255(ia * (int)dst[3]); - - dst[0] = (unsigned char)r; - dst[1] = (unsigned char)g; - dst[2] = (unsigned char)b; - dst[3] = (unsigned char)a; - - cover++; - dst += 4; - fx += dx; - } - } -} - -static void nsvg__rasterizeSortedEdges(NSVGrasterizer *r, float tx, float ty, float scale, NSVGcachedPaint* cache, char fillRule) -{ - NSVGactiveEdge *active = NULL; - int y, s; - int e = 0; - int maxWeight = (255 / NSVG__SUBSAMPLES); // weight per vertical scanline - int xmin, xmax; - - for (y = 0; y < r->height; y++) { - memset(r->scanline, 0, r->width); - xmin = r->width; - xmax = 0; - for (s = 0; s < NSVG__SUBSAMPLES; ++s) { - // find center of pixel for this scanline - float scany = (float)(y*NSVG__SUBSAMPLES + s) + 0.5f; - NSVGactiveEdge **step = &active; - - // update all active edges; - // remove all active edges that terminate before the center of this scanline - while (*step) { - NSVGactiveEdge *z = *step; - if (z->ey <= scany) { - *step = z->next; // delete from list -// NSVG__assert(z->valid); - nsvg__freeActive(r, z); - } else { - z->x += z->dx; // advance to position for current scanline - step = &((*step)->next); // advance through list - } - } - - // resort the list if needed - for (;;) { - int changed = 0; - step = &active; - while (*step && (*step)->next) { - if ((*step)->x > (*step)->next->x) { - NSVGactiveEdge* t = *step; - NSVGactiveEdge* q = t->next; - t->next = q->next; - q->next = t; - *step = q; - changed = 1; - } - step = &(*step)->next; - } - if (!changed) break; - } - - // insert all edges that start before the center of this scanline -- omit ones that also end on this scanline - while (e < r->nedges && r->edges[e].y0 <= scany) { - if (r->edges[e].y1 > scany) { - NSVGactiveEdge* z = nsvg__addActive(r, &r->edges[e], scany); - if (z == NULL) break; - // find insertion point - if (active == NULL) { - active = z; - } else if (z->x < active->x) { - // insert at front - z->next = active; - active = z; - } else { - // find thing to insert AFTER - NSVGactiveEdge* p = active; - while (p->next && p->next->x < z->x) - p = p->next; - // at this point, p->next->x is NOT < z->x - z->next = p->next; - p->next = z; - } - } - e++; - } - - // now process all active edges in non-zero fashion - if (active != NULL) - nsvg__fillActiveEdges(r->scanline, r->width, active, maxWeight, &xmin, &xmax, fillRule); - } - // Blit - if (xmin < 0) xmin = 0; - if (xmax > r->width-1) xmax = r->width-1; - if (xmin <= xmax) { - nsvg__scanlineSolid(&r->bitmap[y * r->stride] + xmin*4, xmax-xmin+1, &r->scanline[xmin], xmin, y, tx,ty, scale, cache); - } - } - -} - -static void nsvg__unpremultiplyAlpha(unsigned char* image, int w, int h, int stride) -{ - int x,y; - - // Unpremultiply - for (y = 0; y < h; y++) { - unsigned char *row = &image[y*stride]; - for (x = 0; x < w; x++) { - int r = row[0], g = row[1], b = row[2], a = row[3]; - if (a != 0) { - row[0] = (unsigned char)(r*255/a); - row[1] = (unsigned char)(g*255/a); - row[2] = (unsigned char)(b*255/a); - } - row += 4; - } - } - - // Defringe - for (y = 0; y < h; y++) { - unsigned char *row = &image[y*stride]; - for (x = 0; x < w; x++) { - int r = 0, g = 0, b = 0, a = row[3], n = 0; - if (a == 0) { - if (x-1 > 0 && row[-1] != 0) { - r += row[-4]; - g += row[-3]; - b += row[-2]; - n++; - } - if (x+1 < w && row[7] != 0) { - r += row[4]; - g += row[5]; - b += row[6]; - n++; - } - if (y-1 > 0 && row[-stride+3] != 0) { - r += row[-stride]; - g += row[-stride+1]; - b += row[-stride+2]; - n++; - } - if (y+1 < h && row[stride+3] != 0) { - r += row[stride]; - g += row[stride+1]; - b += row[stride+2]; - n++; - } - if (n > 0) { - row[0] = (unsigned char)(r/n); - row[1] = (unsigned char)(g/n); - row[2] = (unsigned char)(b/n); - } - } - row += 4; - } - } -} - - -static void nsvg__initPaint(NSVGcachedPaint* cache, NSVGpaint* paint, float opacity) -{ - int i, j; - NSVGgradient* grad; - - cache->type = paint->type; - - if (paint->type == NSVG_PAINT_COLOR) { - cache->colors[0] = nsvg__applyOpacity(paint->color, opacity); - return; - } - - grad = paint->gradient; - - cache->spread = grad->spread; - memcpy(cache->xform, grad->xform, sizeof(float)*6); - - if (grad->nstops == 0) { - for (i = 0; i < 256; i++) - cache->colors[i] = 0; - } if (grad->nstops == 1) { - for (i = 0; i < 256; i++) - cache->colors[i] = nsvg__applyOpacity(grad->stops[i].color, opacity); - } else { - unsigned int ca, cb = 0; - float ua, ub, du, u; - int ia, ib, count; - - ca = nsvg__applyOpacity(grad->stops[0].color, opacity); - ua = nsvg__clampf(grad->stops[0].offset, 0, 1); - ub = nsvg__clampf(grad->stops[grad->nstops-1].offset, ua, 1); - ia = (int)(ua * 255.0f); - ib = (int)(ub * 255.0f); - for (i = 0; i < ia; i++) { - cache->colors[i] = ca; - } - - for (i = 0; i < grad->nstops-1; i++) { - ca = nsvg__applyOpacity(grad->stops[i].color, opacity); - cb = nsvg__applyOpacity(grad->stops[i+1].color, opacity); - ua = nsvg__clampf(grad->stops[i].offset, 0, 1); - ub = nsvg__clampf(grad->stops[i+1].offset, 0, 1); - ia = (int)(ua * 255.0f); - ib = (int)(ub * 255.0f); - count = ib - ia; - if (count <= 0) continue; - u = 0; - du = 1.0f / (float)count; - for (j = 0; j < count; j++) { - cache->colors[ia+j] = nsvg__lerpRGBA(ca,cb,u); - u += du; - } - } - - for (i = ib; i < 256; i++) - cache->colors[i] = cb; - } - -} - -/* -static void dumpEdges(NSVGrasterizer* r, const char* name) -{ - float xmin = 0, xmax = 0, ymin = 0, ymax = 0; - NSVGedge *e = NULL; - int i; - if (r->nedges == 0) return; - FILE* fp = fopen(name, "w"); - if (fp == NULL) return; - - xmin = xmax = r->edges[0].x0; - ymin = ymax = r->edges[0].y0; - for (i = 0; i < r->nedges; i++) { - e = &r->edges[i]; - xmin = nsvg__minf(xmin, e->x0); - xmin = nsvg__minf(xmin, e->x1); - xmax = nsvg__maxf(xmax, e->x0); - xmax = nsvg__maxf(xmax, e->x1); - ymin = nsvg__minf(ymin, e->y0); - ymin = nsvg__minf(ymin, e->y1); - ymax = nsvg__maxf(ymax, e->y0); - ymax = nsvg__maxf(ymax, e->y1); - } - - fprintf(fp, "", xmin, ymin, (xmax - xmin), (ymax - ymin)); - - for (i = 0; i < r->nedges; i++) { - e = &r->edges[i]; - fprintf(fp ,"", e->x0,e->y0, e->x1,e->y1); - } - - for (i = 0; i < r->npoints; i++) { - if (i+1 < r->npoints) - fprintf(fp ,"", r->points[i].x, r->points[i].y, r->points[i+1].x, r->points[i+1].y); - fprintf(fp ,"", r->points[i].x, r->points[i].y, r->points[i].flags == 0 ? "#f00" : "#0f0"); - } - - fprintf(fp, ""); - fclose(fp); -} -*/ - -void nsvgRasterize(NSVGrasterizer* r, - NSVGimage* image, float tx, float ty, float scale, - unsigned char* dst, int w, int h, int stride) -{ - NSVGshape *shape = NULL; - NSVGedge *e = NULL; - NSVGcachedPaint cache; - int i; - - r->bitmap = dst; - r->width = w; - r->height = h; - r->stride = stride; - - if (w > r->cscanline) { - r->cscanline = w; - r->scanline = (unsigned char*)realloc(r->scanline, w); - if (r->scanline == NULL) return; - } - - for (i = 0; i < h; i++) - memset(&dst[i*stride], 0, w*4); - - for (shape = image->shapes; shape != NULL; shape = shape->next) { - if (!(shape->flags & NSVG_FLAGS_VISIBLE)) - continue; - - if (shape->fill.type != NSVG_PAINT_NONE) { - nsvg__resetPool(r); - r->freelist = NULL; - r->nedges = 0; - - nsvg__flattenShape(r, shape, scale); - - // Scale and translate edges - for (i = 0; i < r->nedges; i++) { - e = &r->edges[i]; - e->x0 = tx + e->x0; - e->y0 = (ty + e->y0) * NSVG__SUBSAMPLES; - e->x1 = tx + e->x1; - e->y1 = (ty + e->y1) * NSVG__SUBSAMPLES; - } - - // Rasterize edges - if (r->nedges != 0) - qsort(r->edges, r->nedges, sizeof(NSVGedge), nsvg__cmpEdge); - - // now, traverse the scanlines and find the intersections on each scanline, use non-zero rule - nsvg__initPaint(&cache, &shape->fill, shape->opacity); - - nsvg__rasterizeSortedEdges(r, tx,ty,scale, &cache, shape->fillRule); - } - if (shape->stroke.type != NSVG_PAINT_NONE && (shape->strokeWidth * scale) > 0.01f) { - nsvg__resetPool(r); - r->freelist = NULL; - r->nedges = 0; - - nsvg__flattenShapeStroke(r, shape, scale); - -// dumpEdges(r, "edge.svg"); - - // Scale and translate edges - for (i = 0; i < r->nedges; i++) { - e = &r->edges[i]; - e->x0 = tx + e->x0; - e->y0 = (ty + e->y0) * NSVG__SUBSAMPLES; - e->x1 = tx + e->x1; - e->y1 = (ty + e->y1) * NSVG__SUBSAMPLES; - } - - // Rasterize edges - if (r->nedges != 0) - qsort(r->edges, r->nedges, sizeof(NSVGedge), nsvg__cmpEdge); - - // now, traverse the scanlines and find the intersections on each scanline, use non-zero rule - nsvg__initPaint(&cache, &shape->stroke, shape->opacity); - - nsvg__rasterizeSortedEdges(r, tx,ty,scale, &cache, NSVG_FILLRULE_NONZERO); - } - } - - nsvg__unpremultiplyAlpha(dst, w, h, stride); - - r->bitmap = NULL; - r->width = 0; - r->height = 0; - r->stride = 0; -} - -#endif // NANOSVGRAST_IMPLEMENTATION - -#endif // NANOSVGRAST_H diff --git a/src/rtextures.c b/src/rtextures.c index e81f05fe8..43d16dc7b 100644 --- a/src/rtextures.c +++ b/src/rtextures.c @@ -225,14 +225,6 @@ #pragma GCC diagnostic pop #endif -#if defined(SUPPORT_FILEFORMAT_SVG) - #define NANOSVG_IMPLEMENTATION // Expands implementation - #include "external/nanosvg.h" - - #define NANOSVGRAST_IMPLEMENTATION - #include "external/nanosvgrast.h" -#endif - //---------------------------------------------------------------------------------- // Defines and Macros //---------------------------------------------------------------------------------- @@ -335,84 +327,6 @@ Image LoadImageRaw(const char *fileName, int width, int height, int format, int return image; } -// Load an image from a SVG file or string with custom size -Image LoadImageSvg(const char *fileNameOrString, int width, int height) -{ - Image image = { 0 }; - -#if defined(SUPPORT_FILEFORMAT_SVG) - bool isSvgStringValid = false; - - // Validate fileName or string - if (fileNameOrString != NULL) - { - int dataSize = 0; - unsigned char *fileData = NULL; - - if (FileExists(fileNameOrString)) - { - fileData = LoadFileData(fileNameOrString, &dataSize); - isSvgStringValid = true; - } - else - { - // Validate fileData as valid SVG string data - // - if ((fileNameOrString != NULL) && - (fileNameOrString[0] == '<') && - (fileNameOrString[1] == 's') && - (fileNameOrString[2] == 'v') && - (fileNameOrString[3] == 'g')) - { - fileData = (unsigned char *)fileNameOrString; - isSvgStringValid = true; - } - } - - if (isSvgStringValid) - { - struct NSVGimage *svgImage = nsvgParse((char *)fileData, "px", 96.0f); - - unsigned char *img = RL_MALLOC(width*height*4); - - // Calculate scales for both the width and the height - const float scaleWidth = width/svgImage->width; - const float scaleHeight = height/svgImage->height; - - // Set the largest of the 2 scales to be the scale to use - const float scale = (scaleHeight > scaleWidth)? scaleWidth : scaleHeight; - - int offsetX = 0; - int offsetY = 0; - - if (scaleHeight > scaleWidth) offsetY = (height - svgImage->height*scale)/2; - else offsetX = (width - svgImage->width*scale)/2; - - // Rasterize - struct NSVGrasterizer *rast = nsvgCreateRasterizer(); - nsvgRasterize(rast, svgImage, (int)offsetX, (int)offsetY, scale, img, width, height, width*4); - - // Populate image struct with all data - image.data = img; - image.width = width; - image.height = height; - image.mipmaps = 1; - image.format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8; - - // Free used memory - nsvgDelete(svgImage); - nsvgDeleteRasterizer(rast); - } - - if (isSvgStringValid && (fileData != (unsigned char *)fileNameOrString)) UnloadFileData(fileData); - } -#else - TRACELOG(LOG_WARNING, "SVG image support not enabled, image can not be loaded"); -#endif - - return image; -} - // Load animated image data // - Image.data buffer includes all frames: [image#0][image#1][image#2][...] // - Number of frames is returned through 'frames' parameter @@ -600,36 +514,6 @@ Image LoadImageFromMemory(const char *fileType, const unsigned char *fileData, i } } #endif -#if defined(SUPPORT_FILEFORMAT_SVG) - else if ((strcmp(fileType, ".svg") == 0) || (strcmp(fileType, ".SVG") == 0)) - { - // Validate fileData as valid SVG string data - // - if ((fileData != NULL) && - (fileData[0] == '<') && - (fileData[1] == 's') && - (fileData[2] == 'v') && - (fileData[3] == 'g')) - { - struct NSVGimage *svgImage = nsvgParse((char *)fileData, "px", 96.0f); - unsigned char *img = RL_MALLOC(svgImage->width*svgImage->height*4); - - // Rasterize - struct NSVGrasterizer *rast = nsvgCreateRasterizer(); - nsvgRasterize(rast, svgImage, 0, 0, 1.0f, img, svgImage->width, svgImage->height, svgImage->width*4); - - // Populate image struct with all data - image.data = img; - image.width = svgImage->width; - image.height = svgImage->height; - image.mipmaps = 1; - image.format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8; - - nsvgDelete(svgImage); - nsvgDeleteRasterizer(rast); - } - } -#endif #if defined(SUPPORT_FILEFORMAT_DDS) else if ((strcmp(fileType, ".dds") == 0) || (strcmp(fileType, ".DDS") == 0)) { From d29eb34cfb2688ca11d1a84883c849fa0500881d Mon Sep 17 00:00:00 2001 From: Ray Date: Thu, 10 Oct 2024 21:17:31 +0200 Subject: [PATCH 117/208] REMOVED: `LoadImageSvg()` --- src/raylib.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/raylib.h b/src/raylib.h index 08121c50c..e0c74af30 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -1312,7 +1312,6 @@ RLAPI Rectangle GetCollisionRec(Rectangle rec1, Rectangle rec2); // NOTE: These functions do not require GPU access RLAPI Image LoadImage(const char *fileName); // Load image from file into CPU memory (RAM) RLAPI Image LoadImageRaw(const char *fileName, int width, int height, int format, int headerSize); // Load image from RAW file data -RLAPI Image LoadImageSvg(const char *fileNameOrString, int width, int height); // Load image from SVG file data or string with specified size RLAPI Image LoadImageAnim(const char *fileName, int *frames); // Load image sequence from file (frames appended to image.data) RLAPI Image LoadImageAnimFromMemory(const char *fileType, const unsigned char *fileData, int dataSize, int *frames); // Load image sequence from memory buffer RLAPI Image LoadImageFromMemory(const char *fileType, const unsigned char *fileData, int dataSize); // Load image from memory buffer, fileType refers to extension: i.e. '.png' From f5328a9bb63a0e0eca7dead15cfa01a3ec1417c2 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 10 Oct 2024 19:17:48 +0000 Subject: [PATCH 118/208] Update raylib_api.* by CI --- parser/output/raylib_api.json | 19 -- parser/output/raylib_api.lua | 10 - parser/output/raylib_api.txt | 619 +++++++++++++++++----------------- parser/output/raylib_api.xml | 7 +- 4 files changed, 307 insertions(+), 348 deletions(-) diff --git a/parser/output/raylib_api.json b/parser/output/raylib_api.json index 58fb9d6a8..2c8fe31e9 100644 --- a/parser/output/raylib_api.json +++ b/parser/output/raylib_api.json @@ -6815,25 +6815,6 @@ } ] }, - { - "name": "LoadImageSvg", - "description": "Load image from SVG file data or string with specified size", - "returnType": "Image", - "params": [ - { - "type": "const char *", - "name": "fileNameOrString" - }, - { - "type": "int", - "name": "width" - }, - { - "type": "int", - "name": "height" - } - ] - }, { "name": "LoadImageAnim", "description": "Load image sequence from file (frames appended to image.data)", diff --git a/parser/output/raylib_api.lua b/parser/output/raylib_api.lua index bea3813cf..6c287b7a4 100644 --- a/parser/output/raylib_api.lua +++ b/parser/output/raylib_api.lua @@ -5339,16 +5339,6 @@ return { {type = "int", name = "headerSize"} } }, - { - name = "LoadImageSvg", - description = "Load image from SVG file data or string with specified size", - returnType = "Image", - params = { - {type = "const char *", name = "fileNameOrString"}, - {type = "int", name = "width"}, - {type = "int", name = "height"} - } - }, { name = "LoadImageAnim", description = "Load image sequence from file (frames appended to image.data)", diff --git a/parser/output/raylib_api.txt b/parser/output/raylib_api.txt index 9a953b768..9764769a7 100644 --- a/parser/output/raylib_api.txt +++ b/parser/output/raylib_api.txt @@ -989,7 +989,7 @@ Callback 006: AudioCallback() (2 input parameters) Param[1]: bufferData (type: void *) Param[2]: frames (type: unsigned int) -Functions found: 578 +Functions found: 577 Function 001: InitWindow() (3 input parameters) Name: InitWindow @@ -2631,20 +2631,13 @@ Function 272: LoadImageRaw() (5 input parameters) Param[3]: height (type: int) Param[4]: format (type: int) Param[5]: headerSize (type: int) -Function 273: LoadImageSvg() (3 input parameters) - Name: LoadImageSvg - Return type: Image - Description: Load image from SVG file data or string with specified size - Param[1]: fileNameOrString (type: const char *) - Param[2]: width (type: int) - Param[3]: height (type: int) -Function 274: LoadImageAnim() (2 input parameters) +Function 273: LoadImageAnim() (2 input parameters) Name: LoadImageAnim Return type: Image Description: Load image sequence from file (frames appended to image.data) Param[1]: fileName (type: const char *) Param[2]: frames (type: int *) -Function 275: LoadImageAnimFromMemory() (4 input parameters) +Function 274: LoadImageAnimFromMemory() (4 input parameters) Name: LoadImageAnimFromMemory Return type: Image Description: Load image sequence from memory buffer @@ -2652,60 +2645,60 @@ Function 275: LoadImageAnimFromMemory() (4 input parameters) Param[2]: fileData (type: const unsigned char *) Param[3]: dataSize (type: int) Param[4]: frames (type: int *) -Function 276: LoadImageFromMemory() (3 input parameters) +Function 275: LoadImageFromMemory() (3 input parameters) Name: LoadImageFromMemory Return type: Image Description: Load image from memory buffer, fileType refers to extension: i.e. '.png' Param[1]: fileType (type: const char *) Param[2]: fileData (type: const unsigned char *) Param[3]: dataSize (type: int) -Function 277: LoadImageFromTexture() (1 input parameters) +Function 276: LoadImageFromTexture() (1 input parameters) Name: LoadImageFromTexture Return type: Image Description: Load image from GPU texture data Param[1]: texture (type: Texture2D) -Function 278: LoadImageFromScreen() (0 input parameters) +Function 277: LoadImageFromScreen() (0 input parameters) Name: LoadImageFromScreen Return type: Image Description: Load image from screen buffer and (screenshot) No input parameters -Function 279: IsImageReady() (1 input parameters) +Function 278: IsImageReady() (1 input parameters) Name: IsImageReady Return type: bool Description: Check if an image is ready Param[1]: image (type: Image) -Function 280: UnloadImage() (1 input parameters) +Function 279: UnloadImage() (1 input parameters) Name: UnloadImage Return type: void Description: Unload image from CPU memory (RAM) Param[1]: image (type: Image) -Function 281: ExportImage() (2 input parameters) +Function 280: ExportImage() (2 input parameters) Name: ExportImage Return type: bool Description: Export image data to file, returns true on success Param[1]: image (type: Image) Param[2]: fileName (type: const char *) -Function 282: ExportImageToMemory() (3 input parameters) +Function 281: ExportImageToMemory() (3 input parameters) Name: ExportImageToMemory Return type: unsigned char * Description: Export image to memory buffer Param[1]: image (type: Image) Param[2]: fileType (type: const char *) Param[3]: fileSize (type: int *) -Function 283: ExportImageAsCode() (2 input parameters) +Function 282: ExportImageAsCode() (2 input parameters) Name: ExportImageAsCode Return type: bool Description: Export image as code file defining an array of bytes, returns true on success Param[1]: image (type: Image) Param[2]: fileName (type: const char *) -Function 284: GenImageColor() (3 input parameters) +Function 283: GenImageColor() (3 input parameters) Name: GenImageColor Return type: Image Description: Generate image: plain color Param[1]: width (type: int) Param[2]: height (type: int) Param[3]: color (type: Color) -Function 285: GenImageGradientLinear() (5 input parameters) +Function 284: GenImageGradientLinear() (5 input parameters) Name: GenImageGradientLinear Return type: Image Description: Generate image: linear gradient, direction in degrees [0..360], 0=Vertical gradient @@ -2714,7 +2707,7 @@ Function 285: GenImageGradientLinear() (5 input parameters) Param[3]: direction (type: int) Param[4]: start (type: Color) Param[5]: end (type: Color) -Function 286: GenImageGradientRadial() (5 input parameters) +Function 285: GenImageGradientRadial() (5 input parameters) Name: GenImageGradientRadial Return type: Image Description: Generate image: radial gradient @@ -2723,7 +2716,7 @@ Function 286: GenImageGradientRadial() (5 input parameters) Param[3]: density (type: float) Param[4]: inner (type: Color) Param[5]: outer (type: Color) -Function 287: GenImageGradientSquare() (5 input parameters) +Function 286: GenImageGradientSquare() (5 input parameters) Name: GenImageGradientSquare Return type: Image Description: Generate image: square gradient @@ -2732,7 +2725,7 @@ Function 287: GenImageGradientSquare() (5 input parameters) Param[3]: density (type: float) Param[4]: inner (type: Color) Param[5]: outer (type: Color) -Function 288: GenImageChecked() (6 input parameters) +Function 287: GenImageChecked() (6 input parameters) Name: GenImageChecked Return type: Image Description: Generate image: checked @@ -2742,14 +2735,14 @@ Function 288: GenImageChecked() (6 input parameters) Param[4]: checksY (type: int) Param[5]: col1 (type: Color) Param[6]: col2 (type: Color) -Function 289: GenImageWhiteNoise() (3 input parameters) +Function 288: GenImageWhiteNoise() (3 input parameters) Name: GenImageWhiteNoise Return type: Image Description: Generate image: white noise Param[1]: width (type: int) Param[2]: height (type: int) Param[3]: factor (type: float) -Function 290: GenImagePerlinNoise() (5 input parameters) +Function 289: GenImagePerlinNoise() (5 input parameters) Name: GenImagePerlinNoise Return type: Image Description: Generate image: perlin noise @@ -2758,45 +2751,45 @@ Function 290: GenImagePerlinNoise() (5 input parameters) Param[3]: offsetX (type: int) Param[4]: offsetY (type: int) Param[5]: scale (type: float) -Function 291: GenImageCellular() (3 input parameters) +Function 290: GenImageCellular() (3 input parameters) Name: GenImageCellular Return type: Image Description: Generate image: cellular algorithm, bigger tileSize means bigger cells Param[1]: width (type: int) Param[2]: height (type: int) Param[3]: tileSize (type: int) -Function 292: GenImageText() (3 input parameters) +Function 291: GenImageText() (3 input parameters) Name: GenImageText Return type: Image Description: Generate image: grayscale image from text data Param[1]: width (type: int) Param[2]: height (type: int) Param[3]: text (type: const char *) -Function 293: ImageCopy() (1 input parameters) +Function 292: ImageCopy() (1 input parameters) Name: ImageCopy Return type: Image Description: Create an image duplicate (useful for transformations) Param[1]: image (type: Image) -Function 294: ImageFromImage() (2 input parameters) +Function 293: ImageFromImage() (2 input parameters) Name: ImageFromImage Return type: Image Description: Create an image from another image piece Param[1]: image (type: Image) Param[2]: rec (type: Rectangle) -Function 295: ImageFromChannel() (2 input parameters) +Function 294: ImageFromChannel() (2 input parameters) Name: ImageFromChannel Return type: Image Description: Create an image from a selected channel of another image (GRAYSCALE) Param[1]: image (type: Image) Param[2]: selectedChannel (type: int) -Function 296: ImageText() (3 input parameters) +Function 295: ImageText() (3 input parameters) Name: ImageText Return type: Image Description: Create an image from text (default font) Param[1]: text (type: const char *) Param[2]: fontSize (type: int) Param[3]: color (type: Color) -Function 297: ImageTextEx() (5 input parameters) +Function 296: ImageTextEx() (5 input parameters) Name: ImageTextEx Return type: Image Description: Create an image from text (custom sprite font) @@ -2805,76 +2798,76 @@ Function 297: ImageTextEx() (5 input parameters) Param[3]: fontSize (type: float) Param[4]: spacing (type: float) Param[5]: tint (type: Color) -Function 298: ImageFormat() (2 input parameters) +Function 297: ImageFormat() (2 input parameters) Name: ImageFormat Return type: void Description: Convert image data to desired format Param[1]: image (type: Image *) Param[2]: newFormat (type: int) -Function 299: ImageToPOT() (2 input parameters) +Function 298: ImageToPOT() (2 input parameters) Name: ImageToPOT Return type: void Description: Convert image to POT (power-of-two) Param[1]: image (type: Image *) Param[2]: fill (type: Color) -Function 300: ImageCrop() (2 input parameters) +Function 299: ImageCrop() (2 input parameters) Name: ImageCrop Return type: void Description: Crop an image to a defined rectangle Param[1]: image (type: Image *) Param[2]: crop (type: Rectangle) -Function 301: ImageAlphaCrop() (2 input parameters) +Function 300: ImageAlphaCrop() (2 input parameters) Name: ImageAlphaCrop Return type: void Description: Crop image depending on alpha value Param[1]: image (type: Image *) Param[2]: threshold (type: float) -Function 302: ImageAlphaClear() (3 input parameters) +Function 301: ImageAlphaClear() (3 input parameters) Name: ImageAlphaClear Return type: void Description: Clear alpha channel to desired color Param[1]: image (type: Image *) Param[2]: color (type: Color) Param[3]: threshold (type: float) -Function 303: ImageAlphaMask() (2 input parameters) +Function 302: ImageAlphaMask() (2 input parameters) Name: ImageAlphaMask Return type: void Description: Apply alpha mask to image Param[1]: image (type: Image *) Param[2]: alphaMask (type: Image) -Function 304: ImageAlphaPremultiply() (1 input parameters) +Function 303: ImageAlphaPremultiply() (1 input parameters) Name: ImageAlphaPremultiply Return type: void Description: Premultiply alpha channel Param[1]: image (type: Image *) -Function 305: ImageBlurGaussian() (2 input parameters) +Function 304: ImageBlurGaussian() (2 input parameters) Name: ImageBlurGaussian Return type: void Description: Apply Gaussian blur using a box blur approximation Param[1]: image (type: Image *) Param[2]: blurSize (type: int) -Function 306: ImageKernelConvolution() (3 input parameters) +Function 305: ImageKernelConvolution() (3 input parameters) Name: ImageKernelConvolution Return type: void Description: Apply custom square convolution kernel to image Param[1]: image (type: Image *) Param[2]: kernel (type: const float *) Param[3]: kernelSize (type: int) -Function 307: ImageResize() (3 input parameters) +Function 306: ImageResize() (3 input parameters) Name: ImageResize Return type: void Description: Resize image (Bicubic scaling algorithm) Param[1]: image (type: Image *) Param[2]: newWidth (type: int) Param[3]: newHeight (type: int) -Function 308: ImageResizeNN() (3 input parameters) +Function 307: ImageResizeNN() (3 input parameters) Name: ImageResizeNN Return type: void Description: Resize image (Nearest-Neighbor scaling algorithm) Param[1]: image (type: Image *) Param[2]: newWidth (type: int) Param[3]: newHeight (type: int) -Function 309: ImageResizeCanvas() (6 input parameters) +Function 308: ImageResizeCanvas() (6 input parameters) Name: ImageResizeCanvas Return type: void Description: Resize canvas and fill with color @@ -2884,12 +2877,12 @@ Function 309: ImageResizeCanvas() (6 input parameters) Param[4]: offsetX (type: int) Param[5]: offsetY (type: int) Param[6]: fill (type: Color) -Function 310: ImageMipmaps() (1 input parameters) +Function 309: ImageMipmaps() (1 input parameters) Name: ImageMipmaps Return type: void Description: Compute all mipmap levels for a provided image Param[1]: image (type: Image *) -Function 311: ImageDither() (5 input parameters) +Function 310: ImageDither() (5 input parameters) Name: ImageDither Return type: void Description: Dither image data to 16bpp or lower (Floyd-Steinberg dithering) @@ -2898,109 +2891,109 @@ Function 311: ImageDither() (5 input parameters) Param[3]: gBpp (type: int) Param[4]: bBpp (type: int) Param[5]: aBpp (type: int) -Function 312: ImageFlipVertical() (1 input parameters) +Function 311: ImageFlipVertical() (1 input parameters) Name: ImageFlipVertical Return type: void Description: Flip image vertically Param[1]: image (type: Image *) -Function 313: ImageFlipHorizontal() (1 input parameters) +Function 312: ImageFlipHorizontal() (1 input parameters) Name: ImageFlipHorizontal Return type: void Description: Flip image horizontally Param[1]: image (type: Image *) -Function 314: ImageRotate() (2 input parameters) +Function 313: ImageRotate() (2 input parameters) Name: ImageRotate Return type: void Description: Rotate image by input angle in degrees (-359 to 359) Param[1]: image (type: Image *) Param[2]: degrees (type: int) -Function 315: ImageRotateCW() (1 input parameters) +Function 314: ImageRotateCW() (1 input parameters) Name: ImageRotateCW Return type: void Description: Rotate image clockwise 90deg Param[1]: image (type: Image *) -Function 316: ImageRotateCCW() (1 input parameters) +Function 315: ImageRotateCCW() (1 input parameters) Name: ImageRotateCCW Return type: void Description: Rotate image counter-clockwise 90deg Param[1]: image (type: Image *) -Function 317: ImageColorTint() (2 input parameters) +Function 316: ImageColorTint() (2 input parameters) Name: ImageColorTint Return type: void Description: Modify image color: tint Param[1]: image (type: Image *) Param[2]: color (type: Color) -Function 318: ImageColorInvert() (1 input parameters) +Function 317: ImageColorInvert() (1 input parameters) Name: ImageColorInvert Return type: void Description: Modify image color: invert Param[1]: image (type: Image *) -Function 319: ImageColorGrayscale() (1 input parameters) +Function 318: ImageColorGrayscale() (1 input parameters) Name: ImageColorGrayscale Return type: void Description: Modify image color: grayscale Param[1]: image (type: Image *) -Function 320: ImageColorContrast() (2 input parameters) +Function 319: ImageColorContrast() (2 input parameters) Name: ImageColorContrast Return type: void Description: Modify image color: contrast (-100 to 100) Param[1]: image (type: Image *) Param[2]: contrast (type: float) -Function 321: ImageColorBrightness() (2 input parameters) +Function 320: ImageColorBrightness() (2 input parameters) Name: ImageColorBrightness Return type: void Description: Modify image color: brightness (-255 to 255) Param[1]: image (type: Image *) Param[2]: brightness (type: int) -Function 322: ImageColorReplace() (3 input parameters) +Function 321: ImageColorReplace() (3 input parameters) Name: ImageColorReplace Return type: void Description: Modify image color: replace color Param[1]: image (type: Image *) Param[2]: color (type: Color) Param[3]: replace (type: Color) -Function 323: LoadImageColors() (1 input parameters) +Function 322: LoadImageColors() (1 input parameters) Name: LoadImageColors Return type: Color * Description: Load color data from image as a Color array (RGBA - 32bit) Param[1]: image (type: Image) -Function 324: LoadImagePalette() (3 input parameters) +Function 323: LoadImagePalette() (3 input parameters) Name: LoadImagePalette Return type: Color * Description: Load colors palette from image as a Color array (RGBA - 32bit) Param[1]: image (type: Image) Param[2]: maxPaletteSize (type: int) Param[3]: colorCount (type: int *) -Function 325: UnloadImageColors() (1 input parameters) +Function 324: UnloadImageColors() (1 input parameters) Name: UnloadImageColors Return type: void Description: Unload color data loaded with LoadImageColors() Param[1]: colors (type: Color *) -Function 326: UnloadImagePalette() (1 input parameters) +Function 325: UnloadImagePalette() (1 input parameters) Name: UnloadImagePalette Return type: void Description: Unload colors palette loaded with LoadImagePalette() Param[1]: colors (type: Color *) -Function 327: GetImageAlphaBorder() (2 input parameters) +Function 326: GetImageAlphaBorder() (2 input parameters) Name: GetImageAlphaBorder Return type: Rectangle Description: Get image alpha border rectangle Param[1]: image (type: Image) Param[2]: threshold (type: float) -Function 328: GetImageColor() (3 input parameters) +Function 327: GetImageColor() (3 input parameters) Name: GetImageColor Return type: Color Description: Get image pixel color at (x, y) position Param[1]: image (type: Image) Param[2]: x (type: int) Param[3]: y (type: int) -Function 329: ImageClearBackground() (2 input parameters) +Function 328: ImageClearBackground() (2 input parameters) Name: ImageClearBackground Return type: void Description: Clear image background with given color Param[1]: dst (type: Image *) Param[2]: color (type: Color) -Function 330: ImageDrawPixel() (4 input parameters) +Function 329: ImageDrawPixel() (4 input parameters) Name: ImageDrawPixel Return type: void Description: Draw pixel within an image @@ -3008,14 +3001,14 @@ Function 330: ImageDrawPixel() (4 input parameters) Param[2]: posX (type: int) Param[3]: posY (type: int) Param[4]: color (type: Color) -Function 331: ImageDrawPixelV() (3 input parameters) +Function 330: ImageDrawPixelV() (3 input parameters) Name: ImageDrawPixelV Return type: void Description: Draw pixel within an image (Vector version) Param[1]: dst (type: Image *) Param[2]: position (type: Vector2) Param[3]: color (type: Color) -Function 332: ImageDrawLine() (6 input parameters) +Function 331: ImageDrawLine() (6 input parameters) Name: ImageDrawLine Return type: void Description: Draw line within an image @@ -3025,7 +3018,7 @@ Function 332: ImageDrawLine() (6 input parameters) Param[4]: endPosX (type: int) Param[5]: endPosY (type: int) Param[6]: color (type: Color) -Function 333: ImageDrawLineV() (4 input parameters) +Function 332: ImageDrawLineV() (4 input parameters) Name: ImageDrawLineV Return type: void Description: Draw line within an image (Vector version) @@ -3033,7 +3026,7 @@ Function 333: ImageDrawLineV() (4 input parameters) Param[2]: start (type: Vector2) Param[3]: end (type: Vector2) Param[4]: color (type: Color) -Function 334: ImageDrawLineEx() (5 input parameters) +Function 333: ImageDrawLineEx() (5 input parameters) Name: ImageDrawLineEx Return type: void Description: Draw a line defining thickness within an image @@ -3042,7 +3035,7 @@ Function 334: ImageDrawLineEx() (5 input parameters) Param[3]: end (type: Vector2) Param[4]: thick (type: int) Param[5]: color (type: Color) -Function 335: ImageDrawCircle() (5 input parameters) +Function 334: ImageDrawCircle() (5 input parameters) Name: ImageDrawCircle Return type: void Description: Draw a filled circle within an image @@ -3051,7 +3044,7 @@ Function 335: ImageDrawCircle() (5 input parameters) Param[3]: centerY (type: int) Param[4]: radius (type: int) Param[5]: color (type: Color) -Function 336: ImageDrawCircleV() (4 input parameters) +Function 335: ImageDrawCircleV() (4 input parameters) Name: ImageDrawCircleV Return type: void Description: Draw a filled circle within an image (Vector version) @@ -3059,7 +3052,7 @@ Function 336: ImageDrawCircleV() (4 input parameters) Param[2]: center (type: Vector2) Param[3]: radius (type: int) Param[4]: color (type: Color) -Function 337: ImageDrawCircleLines() (5 input parameters) +Function 336: ImageDrawCircleLines() (5 input parameters) Name: ImageDrawCircleLines Return type: void Description: Draw circle outline within an image @@ -3068,7 +3061,7 @@ Function 337: ImageDrawCircleLines() (5 input parameters) Param[3]: centerY (type: int) Param[4]: radius (type: int) Param[5]: color (type: Color) -Function 338: ImageDrawCircleLinesV() (4 input parameters) +Function 337: ImageDrawCircleLinesV() (4 input parameters) Name: ImageDrawCircleLinesV Return type: void Description: Draw circle outline within an image (Vector version) @@ -3076,7 +3069,7 @@ Function 338: ImageDrawCircleLinesV() (4 input parameters) Param[2]: center (type: Vector2) Param[3]: radius (type: int) Param[4]: color (type: Color) -Function 339: ImageDrawRectangle() (6 input parameters) +Function 338: ImageDrawRectangle() (6 input parameters) Name: ImageDrawRectangle Return type: void Description: Draw rectangle within an image @@ -3086,7 +3079,7 @@ Function 339: ImageDrawRectangle() (6 input parameters) Param[4]: width (type: int) Param[5]: height (type: int) Param[6]: color (type: Color) -Function 340: ImageDrawRectangleV() (4 input parameters) +Function 339: ImageDrawRectangleV() (4 input parameters) Name: ImageDrawRectangleV Return type: void Description: Draw rectangle within an image (Vector version) @@ -3094,14 +3087,14 @@ Function 340: ImageDrawRectangleV() (4 input parameters) Param[2]: position (type: Vector2) Param[3]: size (type: Vector2) Param[4]: color (type: Color) -Function 341: ImageDrawRectangleRec() (3 input parameters) +Function 340: ImageDrawRectangleRec() (3 input parameters) Name: ImageDrawRectangleRec Return type: void Description: Draw rectangle within an image Param[1]: dst (type: Image *) Param[2]: rec (type: Rectangle) Param[3]: color (type: Color) -Function 342: ImageDrawRectangleLines() (4 input parameters) +Function 341: ImageDrawRectangleLines() (4 input parameters) Name: ImageDrawRectangleLines Return type: void Description: Draw rectangle lines within an image @@ -3109,7 +3102,7 @@ Function 342: ImageDrawRectangleLines() (4 input parameters) Param[2]: rec (type: Rectangle) Param[3]: thick (type: int) Param[4]: color (type: Color) -Function 343: ImageDrawTriangle() (5 input parameters) +Function 342: ImageDrawTriangle() (5 input parameters) Name: ImageDrawTriangle Return type: void Description: Draw triangle within an image @@ -3118,7 +3111,7 @@ Function 343: ImageDrawTriangle() (5 input parameters) Param[3]: v2 (type: Vector2) Param[4]: v3 (type: Vector2) Param[5]: color (type: Color) -Function 344: ImageDrawTriangleEx() (7 input parameters) +Function 343: ImageDrawTriangleEx() (7 input parameters) Name: ImageDrawTriangleEx Return type: void Description: Draw triangle with interpolated colors within an image @@ -3129,7 +3122,7 @@ Function 344: ImageDrawTriangleEx() (7 input parameters) Param[5]: c1 (type: Color) Param[6]: c2 (type: Color) Param[7]: c3 (type: Color) -Function 345: ImageDrawTriangleLines() (5 input parameters) +Function 344: ImageDrawTriangleLines() (5 input parameters) Name: ImageDrawTriangleLines Return type: void Description: Draw triangle outline within an image @@ -3138,7 +3131,7 @@ Function 345: ImageDrawTriangleLines() (5 input parameters) Param[3]: v2 (type: Vector2) Param[4]: v3 (type: Vector2) Param[5]: color (type: Color) -Function 346: ImageDrawTriangleFan() (4 input parameters) +Function 345: ImageDrawTriangleFan() (4 input parameters) Name: ImageDrawTriangleFan Return type: void Description: Draw a triangle fan defined by points within an image (first vertex is the center) @@ -3146,7 +3139,7 @@ Function 346: ImageDrawTriangleFan() (4 input parameters) Param[2]: points (type: Vector2 *) Param[3]: pointCount (type: int) Param[4]: color (type: Color) -Function 347: ImageDrawTriangleStrip() (4 input parameters) +Function 346: ImageDrawTriangleStrip() (4 input parameters) Name: ImageDrawTriangleStrip Return type: void Description: Draw a triangle strip defined by points within an image @@ -3154,7 +3147,7 @@ Function 347: ImageDrawTriangleStrip() (4 input parameters) Param[2]: points (type: Vector2 *) Param[3]: pointCount (type: int) Param[4]: color (type: Color) -Function 348: ImageDraw() (5 input parameters) +Function 347: ImageDraw() (5 input parameters) Name: ImageDraw Return type: void Description: Draw a source image within a destination image (tint applied to source) @@ -3163,7 +3156,7 @@ Function 348: ImageDraw() (5 input parameters) Param[3]: srcRec (type: Rectangle) Param[4]: dstRec (type: Rectangle) Param[5]: tint (type: Color) -Function 349: ImageDrawText() (6 input parameters) +Function 348: ImageDrawText() (6 input parameters) Name: ImageDrawText Return type: void Description: Draw text (using default font) within an image (destination) @@ -3173,7 +3166,7 @@ Function 349: ImageDrawText() (6 input parameters) Param[4]: posY (type: int) Param[5]: fontSize (type: int) Param[6]: color (type: Color) -Function 350: ImageDrawTextEx() (7 input parameters) +Function 349: ImageDrawTextEx() (7 input parameters) Name: ImageDrawTextEx Return type: void Description: Draw text (custom sprite font) within an image (destination) @@ -3184,79 +3177,79 @@ Function 350: ImageDrawTextEx() (7 input parameters) Param[5]: fontSize (type: float) Param[6]: spacing (type: float) Param[7]: tint (type: Color) -Function 351: LoadTexture() (1 input parameters) +Function 350: LoadTexture() (1 input parameters) Name: LoadTexture Return type: Texture2D Description: Load texture from file into GPU memory (VRAM) Param[1]: fileName (type: const char *) -Function 352: LoadTextureFromImage() (1 input parameters) +Function 351: LoadTextureFromImage() (1 input parameters) Name: LoadTextureFromImage Return type: Texture2D Description: Load texture from image data Param[1]: image (type: Image) -Function 353: LoadTextureCubemap() (2 input parameters) +Function 352: LoadTextureCubemap() (2 input parameters) Name: LoadTextureCubemap Return type: TextureCubemap Description: Load cubemap from image, multiple image cubemap layouts supported Param[1]: image (type: Image) Param[2]: layout (type: int) -Function 354: LoadRenderTexture() (2 input parameters) +Function 353: LoadRenderTexture() (2 input parameters) Name: LoadRenderTexture Return type: RenderTexture2D Description: Load texture for rendering (framebuffer) Param[1]: width (type: int) Param[2]: height (type: int) -Function 355: IsTextureReady() (1 input parameters) +Function 354: IsTextureReady() (1 input parameters) Name: IsTextureReady Return type: bool Description: Check if a texture is ready Param[1]: texture (type: Texture2D) -Function 356: UnloadTexture() (1 input parameters) +Function 355: UnloadTexture() (1 input parameters) Name: UnloadTexture Return type: void Description: Unload texture from GPU memory (VRAM) Param[1]: texture (type: Texture2D) -Function 357: IsRenderTextureReady() (1 input parameters) +Function 356: IsRenderTextureReady() (1 input parameters) Name: IsRenderTextureReady Return type: bool Description: Check if a render texture is ready Param[1]: target (type: RenderTexture2D) -Function 358: UnloadRenderTexture() (1 input parameters) +Function 357: UnloadRenderTexture() (1 input parameters) Name: UnloadRenderTexture Return type: void Description: Unload render texture from GPU memory (VRAM) Param[1]: target (type: RenderTexture2D) -Function 359: UpdateTexture() (2 input parameters) +Function 358: UpdateTexture() (2 input parameters) Name: UpdateTexture Return type: void Description: Update GPU texture with new data Param[1]: texture (type: Texture2D) Param[2]: pixels (type: const void *) -Function 360: UpdateTextureRec() (3 input parameters) +Function 359: UpdateTextureRec() (3 input parameters) Name: UpdateTextureRec Return type: void Description: Update GPU texture rectangle with new data Param[1]: texture (type: Texture2D) Param[2]: rec (type: Rectangle) Param[3]: pixels (type: const void *) -Function 361: GenTextureMipmaps() (1 input parameters) +Function 360: GenTextureMipmaps() (1 input parameters) Name: GenTextureMipmaps Return type: void Description: Generate GPU mipmaps for a texture Param[1]: texture (type: Texture2D *) -Function 362: SetTextureFilter() (2 input parameters) +Function 361: SetTextureFilter() (2 input parameters) Name: SetTextureFilter Return type: void Description: Set texture scaling filter mode Param[1]: texture (type: Texture2D) Param[2]: filter (type: int) -Function 363: SetTextureWrap() (2 input parameters) +Function 362: SetTextureWrap() (2 input parameters) Name: SetTextureWrap Return type: void Description: Set texture wrapping mode Param[1]: texture (type: Texture2D) Param[2]: wrap (type: int) -Function 364: DrawTexture() (4 input parameters) +Function 363: DrawTexture() (4 input parameters) Name: DrawTexture Return type: void Description: Draw a Texture2D @@ -3264,14 +3257,14 @@ Function 364: DrawTexture() (4 input parameters) Param[2]: posX (type: int) Param[3]: posY (type: int) Param[4]: tint (type: Color) -Function 365: DrawTextureV() (3 input parameters) +Function 364: DrawTextureV() (3 input parameters) Name: DrawTextureV Return type: void Description: Draw a Texture2D with position defined as Vector2 Param[1]: texture (type: Texture2D) Param[2]: position (type: Vector2) Param[3]: tint (type: Color) -Function 366: DrawTextureEx() (5 input parameters) +Function 365: DrawTextureEx() (5 input parameters) Name: DrawTextureEx Return type: void Description: Draw a Texture2D with extended parameters @@ -3280,7 +3273,7 @@ Function 366: DrawTextureEx() (5 input parameters) Param[3]: rotation (type: float) Param[4]: scale (type: float) Param[5]: tint (type: Color) -Function 367: DrawTextureRec() (4 input parameters) +Function 366: DrawTextureRec() (4 input parameters) Name: DrawTextureRec Return type: void Description: Draw a part of a texture defined by a rectangle @@ -3288,7 +3281,7 @@ Function 367: DrawTextureRec() (4 input parameters) Param[2]: source (type: Rectangle) Param[3]: position (type: Vector2) Param[4]: tint (type: Color) -Function 368: DrawTexturePro() (6 input parameters) +Function 367: DrawTexturePro() (6 input parameters) Name: DrawTexturePro Return type: void Description: Draw a part of a texture defined by a rectangle with 'pro' parameters @@ -3298,7 +3291,7 @@ Function 368: DrawTexturePro() (6 input parameters) Param[4]: origin (type: Vector2) Param[5]: rotation (type: float) Param[6]: tint (type: Color) -Function 369: DrawTextureNPatch() (6 input parameters) +Function 368: DrawTextureNPatch() (6 input parameters) Name: DrawTextureNPatch Return type: void Description: Draws a texture (or part of it) that stretches or shrinks nicely @@ -3308,119 +3301,119 @@ Function 369: DrawTextureNPatch() (6 input parameters) Param[4]: origin (type: Vector2) Param[5]: rotation (type: float) Param[6]: tint (type: Color) -Function 370: ColorIsEqual() (2 input parameters) +Function 369: ColorIsEqual() (2 input parameters) Name: ColorIsEqual Return type: bool Description: Check if two colors are equal Param[1]: col1 (type: Color) Param[2]: col2 (type: Color) -Function 371: Fade() (2 input parameters) +Function 370: Fade() (2 input parameters) Name: Fade Return type: Color Description: Get color with alpha applied, alpha goes from 0.0f to 1.0f Param[1]: color (type: Color) Param[2]: alpha (type: float) -Function 372: ColorToInt() (1 input parameters) +Function 371: ColorToInt() (1 input parameters) Name: ColorToInt Return type: int Description: Get hexadecimal value for a Color (0xRRGGBBAA) Param[1]: color (type: Color) -Function 373: ColorNormalize() (1 input parameters) +Function 372: ColorNormalize() (1 input parameters) Name: ColorNormalize Return type: Vector4 Description: Get Color normalized as float [0..1] Param[1]: color (type: Color) -Function 374: ColorFromNormalized() (1 input parameters) +Function 373: ColorFromNormalized() (1 input parameters) Name: ColorFromNormalized Return type: Color Description: Get Color from normalized values [0..1] Param[1]: normalized (type: Vector4) -Function 375: ColorToHSV() (1 input parameters) +Function 374: ColorToHSV() (1 input parameters) Name: ColorToHSV Return type: Vector3 Description: Get HSV values for a Color, hue [0..360], saturation/value [0..1] Param[1]: color (type: Color) -Function 376: ColorFromHSV() (3 input parameters) +Function 375: ColorFromHSV() (3 input parameters) Name: ColorFromHSV Return type: Color Description: Get a Color from HSV values, hue [0..360], saturation/value [0..1] Param[1]: hue (type: float) Param[2]: saturation (type: float) Param[3]: value (type: float) -Function 377: ColorTint() (2 input parameters) +Function 376: ColorTint() (2 input parameters) Name: ColorTint Return type: Color Description: Get color multiplied with another color Param[1]: color (type: Color) Param[2]: tint (type: Color) -Function 378: ColorBrightness() (2 input parameters) +Function 377: ColorBrightness() (2 input parameters) Name: ColorBrightness Return type: Color Description: Get color with brightness correction, brightness factor goes from -1.0f to 1.0f Param[1]: color (type: Color) Param[2]: factor (type: float) -Function 379: ColorContrast() (2 input parameters) +Function 378: ColorContrast() (2 input parameters) Name: ColorContrast Return type: Color Description: Get color with contrast correction, contrast values between -1.0f and 1.0f Param[1]: color (type: Color) Param[2]: contrast (type: float) -Function 380: ColorAlpha() (2 input parameters) +Function 379: ColorAlpha() (2 input parameters) Name: ColorAlpha Return type: Color Description: Get color with alpha applied, alpha goes from 0.0f to 1.0f Param[1]: color (type: Color) Param[2]: alpha (type: float) -Function 381: ColorAlphaBlend() (3 input parameters) +Function 380: ColorAlphaBlend() (3 input parameters) Name: ColorAlphaBlend Return type: Color Description: Get src alpha-blended into dst color with tint Param[1]: dst (type: Color) Param[2]: src (type: Color) Param[3]: tint (type: Color) -Function 382: ColorLerp() (3 input parameters) +Function 381: ColorLerp() (3 input parameters) Name: ColorLerp Return type: Color Description: Get color lerp interpolation between two colors, factor [0.0f..1.0f] Param[1]: color1 (type: Color) Param[2]: color2 (type: Color) Param[3]: factor (type: float) -Function 383: GetColor() (1 input parameters) +Function 382: GetColor() (1 input parameters) Name: GetColor Return type: Color Description: Get Color structure from hexadecimal value Param[1]: hexValue (type: unsigned int) -Function 384: GetPixelColor() (2 input parameters) +Function 383: GetPixelColor() (2 input parameters) Name: GetPixelColor Return type: Color Description: Get Color from a source pixel pointer of certain format Param[1]: srcPtr (type: void *) Param[2]: format (type: int) -Function 385: SetPixelColor() (3 input parameters) +Function 384: SetPixelColor() (3 input parameters) Name: SetPixelColor Return type: void Description: Set color formatted into destination pixel pointer Param[1]: dstPtr (type: void *) Param[2]: color (type: Color) Param[3]: format (type: int) -Function 386: GetPixelDataSize() (3 input parameters) +Function 385: GetPixelDataSize() (3 input parameters) Name: GetPixelDataSize Return type: int Description: Get pixel data size in bytes for certain format Param[1]: width (type: int) Param[2]: height (type: int) Param[3]: format (type: int) -Function 387: GetFontDefault() (0 input parameters) +Function 386: GetFontDefault() (0 input parameters) Name: GetFontDefault Return type: Font Description: Get the default Font No input parameters -Function 388: LoadFont() (1 input parameters) +Function 387: LoadFont() (1 input parameters) Name: LoadFont Return type: Font Description: Load font from file into GPU memory (VRAM) Param[1]: fileName (type: const char *) -Function 389: LoadFontEx() (4 input parameters) +Function 388: LoadFontEx() (4 input parameters) Name: LoadFontEx Return type: Font Description: Load font from file with extended parameters, use NULL for codepoints and 0 for codepointCount to load the default character set, font size is provided in pixels height @@ -3428,14 +3421,14 @@ Function 389: LoadFontEx() (4 input parameters) Param[2]: fontSize (type: int) Param[3]: codepoints (type: int *) Param[4]: codepointCount (type: int) -Function 390: LoadFontFromImage() (3 input parameters) +Function 389: LoadFontFromImage() (3 input parameters) Name: LoadFontFromImage Return type: Font Description: Load font from Image (XNA style) Param[1]: image (type: Image) Param[2]: key (type: Color) Param[3]: firstChar (type: int) -Function 391: LoadFontFromMemory() (6 input parameters) +Function 390: LoadFontFromMemory() (6 input parameters) Name: LoadFontFromMemory Return type: Font Description: Load font from memory buffer, fileType refers to extension: i.e. '.ttf' @@ -3445,12 +3438,12 @@ Function 391: LoadFontFromMemory() (6 input parameters) Param[4]: fontSize (type: int) Param[5]: codepoints (type: int *) Param[6]: codepointCount (type: int) -Function 392: IsFontReady() (1 input parameters) +Function 391: IsFontReady() (1 input parameters) Name: IsFontReady Return type: bool Description: Check if a font is ready Param[1]: font (type: Font) -Function 393: LoadFontData() (6 input parameters) +Function 392: LoadFontData() (6 input parameters) Name: LoadFontData Return type: GlyphInfo * Description: Load font data for further use @@ -3460,7 +3453,7 @@ Function 393: LoadFontData() (6 input parameters) Param[4]: codepoints (type: int *) Param[5]: codepointCount (type: int) Param[6]: type (type: int) -Function 394: GenImageFontAtlas() (6 input parameters) +Function 393: GenImageFontAtlas() (6 input parameters) Name: GenImageFontAtlas Return type: Image Description: Generate image font atlas using chars info @@ -3470,30 +3463,30 @@ Function 394: GenImageFontAtlas() (6 input parameters) Param[4]: fontSize (type: int) Param[5]: padding (type: int) Param[6]: packMethod (type: int) -Function 395: UnloadFontData() (2 input parameters) +Function 394: UnloadFontData() (2 input parameters) Name: UnloadFontData Return type: void Description: Unload font chars info data (RAM) Param[1]: glyphs (type: GlyphInfo *) Param[2]: glyphCount (type: int) -Function 396: UnloadFont() (1 input parameters) +Function 395: UnloadFont() (1 input parameters) Name: UnloadFont Return type: void Description: Unload font from GPU memory (VRAM) Param[1]: font (type: Font) -Function 397: ExportFontAsCode() (2 input parameters) +Function 396: ExportFontAsCode() (2 input parameters) Name: ExportFontAsCode Return type: bool Description: Export font as code file, returns true on success Param[1]: font (type: Font) Param[2]: fileName (type: const char *) -Function 398: DrawFPS() (2 input parameters) +Function 397: DrawFPS() (2 input parameters) Name: DrawFPS Return type: void Description: Draw current FPS Param[1]: posX (type: int) Param[2]: posY (type: int) -Function 399: DrawText() (5 input parameters) +Function 398: DrawText() (5 input parameters) Name: DrawText Return type: void Description: Draw text (using default font) @@ -3502,7 +3495,7 @@ Function 399: DrawText() (5 input parameters) Param[3]: posY (type: int) Param[4]: fontSize (type: int) Param[5]: color (type: Color) -Function 400: DrawTextEx() (6 input parameters) +Function 399: DrawTextEx() (6 input parameters) Name: DrawTextEx Return type: void Description: Draw text using font and additional parameters @@ -3512,7 +3505,7 @@ Function 400: DrawTextEx() (6 input parameters) Param[4]: fontSize (type: float) Param[5]: spacing (type: float) Param[6]: tint (type: Color) -Function 401: DrawTextPro() (8 input parameters) +Function 400: DrawTextPro() (8 input parameters) Name: DrawTextPro Return type: void Description: Draw text using Font and pro parameters (rotation) @@ -3524,7 +3517,7 @@ Function 401: DrawTextPro() (8 input parameters) Param[6]: fontSize (type: float) Param[7]: spacing (type: float) Param[8]: tint (type: Color) -Function 402: DrawTextCodepoint() (5 input parameters) +Function 401: DrawTextCodepoint() (5 input parameters) Name: DrawTextCodepoint Return type: void Description: Draw one character (codepoint) @@ -3533,7 +3526,7 @@ Function 402: DrawTextCodepoint() (5 input parameters) Param[3]: position (type: Vector2) Param[4]: fontSize (type: float) Param[5]: tint (type: Color) -Function 403: DrawTextCodepoints() (7 input parameters) +Function 402: DrawTextCodepoints() (7 input parameters) Name: DrawTextCodepoints Return type: void Description: Draw multiple character (codepoint) @@ -3544,18 +3537,18 @@ Function 403: DrawTextCodepoints() (7 input parameters) Param[5]: fontSize (type: float) Param[6]: spacing (type: float) Param[7]: tint (type: Color) -Function 404: SetTextLineSpacing() (1 input parameters) +Function 403: SetTextLineSpacing() (1 input parameters) Name: SetTextLineSpacing Return type: void Description: Set vertical line spacing when drawing with line-breaks Param[1]: spacing (type: int) -Function 405: MeasureText() (2 input parameters) +Function 404: MeasureText() (2 input parameters) Name: MeasureText Return type: int Description: Measure string width for default font Param[1]: text (type: const char *) Param[2]: fontSize (type: int) -Function 406: MeasureTextEx() (4 input parameters) +Function 405: MeasureTextEx() (4 input parameters) Name: MeasureTextEx Return type: Vector2 Description: Measure string size for Font @@ -3563,195 +3556,195 @@ Function 406: MeasureTextEx() (4 input parameters) Param[2]: text (type: const char *) Param[3]: fontSize (type: float) Param[4]: spacing (type: float) -Function 407: GetGlyphIndex() (2 input parameters) +Function 406: GetGlyphIndex() (2 input parameters) Name: GetGlyphIndex Return type: int Description: Get glyph index position in font for a codepoint (unicode character), fallback to '?' if not found Param[1]: font (type: Font) Param[2]: codepoint (type: int) -Function 408: GetGlyphInfo() (2 input parameters) +Function 407: GetGlyphInfo() (2 input parameters) Name: GetGlyphInfo Return type: GlyphInfo Description: Get glyph font info data for a codepoint (unicode character), fallback to '?' if not found Param[1]: font (type: Font) Param[2]: codepoint (type: int) -Function 409: GetGlyphAtlasRec() (2 input parameters) +Function 408: GetGlyphAtlasRec() (2 input parameters) Name: GetGlyphAtlasRec Return type: Rectangle Description: Get glyph rectangle in font atlas for a codepoint (unicode character), fallback to '?' if not found Param[1]: font (type: Font) Param[2]: codepoint (type: int) -Function 410: LoadUTF8() (2 input parameters) +Function 409: LoadUTF8() (2 input parameters) Name: LoadUTF8 Return type: char * Description: Load UTF-8 text encoded from codepoints array Param[1]: codepoints (type: const int *) Param[2]: length (type: int) -Function 411: UnloadUTF8() (1 input parameters) +Function 410: UnloadUTF8() (1 input parameters) Name: UnloadUTF8 Return type: void Description: Unload UTF-8 text encoded from codepoints array Param[1]: text (type: char *) -Function 412: LoadCodepoints() (2 input parameters) +Function 411: LoadCodepoints() (2 input parameters) Name: LoadCodepoints Return type: int * Description: Load all codepoints from a UTF-8 text string, codepoints count returned by parameter Param[1]: text (type: const char *) Param[2]: count (type: int *) -Function 413: UnloadCodepoints() (1 input parameters) +Function 412: UnloadCodepoints() (1 input parameters) Name: UnloadCodepoints Return type: void Description: Unload codepoints data from memory Param[1]: codepoints (type: int *) -Function 414: GetCodepointCount() (1 input parameters) +Function 413: GetCodepointCount() (1 input parameters) Name: GetCodepointCount Return type: int Description: Get total number of codepoints in a UTF-8 encoded string Param[1]: text (type: const char *) -Function 415: GetCodepoint() (2 input parameters) +Function 414: GetCodepoint() (2 input parameters) Name: GetCodepoint Return type: int Description: Get next codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure Param[1]: text (type: const char *) Param[2]: codepointSize (type: int *) -Function 416: GetCodepointNext() (2 input parameters) +Function 415: GetCodepointNext() (2 input parameters) Name: GetCodepointNext Return type: int Description: Get next codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure Param[1]: text (type: const char *) Param[2]: codepointSize (type: int *) -Function 417: GetCodepointPrevious() (2 input parameters) +Function 416: GetCodepointPrevious() (2 input parameters) Name: GetCodepointPrevious Return type: int Description: Get previous codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure Param[1]: text (type: const char *) Param[2]: codepointSize (type: int *) -Function 418: CodepointToUTF8() (2 input parameters) +Function 417: CodepointToUTF8() (2 input parameters) Name: CodepointToUTF8 Return type: const char * Description: Encode one codepoint into UTF-8 byte array (array length returned as parameter) Param[1]: codepoint (type: int) Param[2]: utf8Size (type: int *) -Function 419: TextCopy() (2 input parameters) +Function 418: TextCopy() (2 input parameters) Name: TextCopy Return type: int Description: Copy one string to another, returns bytes copied Param[1]: dst (type: char *) Param[2]: src (type: const char *) -Function 420: TextIsEqual() (2 input parameters) +Function 419: TextIsEqual() (2 input parameters) Name: TextIsEqual Return type: bool Description: Check if two text string are equal Param[1]: text1 (type: const char *) Param[2]: text2 (type: const char *) -Function 421: TextLength() (1 input parameters) +Function 420: TextLength() (1 input parameters) Name: TextLength Return type: unsigned int Description: Get text length, checks for '\0' ending Param[1]: text (type: const char *) -Function 422: TextFormat() (2 input parameters) +Function 421: TextFormat() (2 input parameters) Name: TextFormat Return type: const char * Description: Text formatting with variables (sprintf() style) Param[1]: text (type: const char *) Param[2]: args (type: ...) -Function 423: TextSubtext() (3 input parameters) +Function 422: TextSubtext() (3 input parameters) Name: TextSubtext Return type: const char * Description: Get a piece of a text string Param[1]: text (type: const char *) Param[2]: position (type: int) Param[3]: length (type: int) -Function 424: TextReplace() (3 input parameters) +Function 423: TextReplace() (3 input parameters) Name: TextReplace Return type: char * Description: Replace text string (WARNING: memory must be freed!) Param[1]: text (type: const char *) Param[2]: replace (type: const char *) Param[3]: by (type: const char *) -Function 425: TextInsert() (3 input parameters) +Function 424: TextInsert() (3 input parameters) Name: TextInsert Return type: char * Description: Insert text in a position (WARNING: memory must be freed!) Param[1]: text (type: const char *) Param[2]: insert (type: const char *) Param[3]: position (type: int) -Function 426: TextJoin() (3 input parameters) +Function 425: TextJoin() (3 input parameters) Name: TextJoin Return type: const char * Description: Join text strings with delimiter Param[1]: textList (type: const char **) Param[2]: count (type: int) Param[3]: delimiter (type: const char *) -Function 427: TextSplit() (3 input parameters) +Function 426: TextSplit() (3 input parameters) Name: TextSplit Return type: const char ** Description: Split text into multiple strings Param[1]: text (type: const char *) Param[2]: delimiter (type: char) Param[3]: count (type: int *) -Function 428: TextAppend() (3 input parameters) +Function 427: TextAppend() (3 input parameters) Name: TextAppend Return type: void Description: Append text at specific position and move cursor! Param[1]: text (type: char *) Param[2]: append (type: const char *) Param[3]: position (type: int *) -Function 429: TextFindIndex() (2 input parameters) +Function 428: TextFindIndex() (2 input parameters) Name: TextFindIndex Return type: int Description: Find first text occurrence within a string Param[1]: text (type: const char *) Param[2]: find (type: const char *) -Function 430: TextToUpper() (1 input parameters) +Function 429: TextToUpper() (1 input parameters) Name: TextToUpper Return type: const char * Description: Get upper case version of provided string Param[1]: text (type: const char *) -Function 431: TextToLower() (1 input parameters) +Function 430: TextToLower() (1 input parameters) Name: TextToLower Return type: const char * Description: Get lower case version of provided string Param[1]: text (type: const char *) -Function 432: TextToPascal() (1 input parameters) +Function 431: TextToPascal() (1 input parameters) Name: TextToPascal Return type: const char * Description: Get Pascal case notation version of provided string Param[1]: text (type: const char *) -Function 433: TextToSnake() (1 input parameters) +Function 432: TextToSnake() (1 input parameters) Name: TextToSnake Return type: const char * Description: Get Snake case notation version of provided string Param[1]: text (type: const char *) -Function 434: TextToCamel() (1 input parameters) +Function 433: TextToCamel() (1 input parameters) Name: TextToCamel Return type: const char * Description: Get Camel case notation version of provided string Param[1]: text (type: const char *) -Function 435: TextToInteger() (1 input parameters) +Function 434: TextToInteger() (1 input parameters) Name: TextToInteger Return type: int Description: Get integer value from text (negative values not supported) Param[1]: text (type: const char *) -Function 436: TextToFloat() (1 input parameters) +Function 435: TextToFloat() (1 input parameters) Name: TextToFloat Return type: float Description: Get float value from text (negative values not supported) Param[1]: text (type: const char *) -Function 437: DrawLine3D() (3 input parameters) +Function 436: DrawLine3D() (3 input parameters) Name: DrawLine3D Return type: void Description: Draw a line in 3D world space Param[1]: startPos (type: Vector3) Param[2]: endPos (type: Vector3) Param[3]: color (type: Color) -Function 438: DrawPoint3D() (2 input parameters) +Function 437: DrawPoint3D() (2 input parameters) Name: DrawPoint3D Return type: void Description: Draw a point in 3D space, actually a small line Param[1]: position (type: Vector3) Param[2]: color (type: Color) -Function 439: DrawCircle3D() (5 input parameters) +Function 438: DrawCircle3D() (5 input parameters) Name: DrawCircle3D Return type: void Description: Draw a circle in 3D world space @@ -3760,7 +3753,7 @@ Function 439: DrawCircle3D() (5 input parameters) Param[3]: rotationAxis (type: Vector3) Param[4]: rotationAngle (type: float) Param[5]: color (type: Color) -Function 440: DrawTriangle3D() (4 input parameters) +Function 439: DrawTriangle3D() (4 input parameters) Name: DrawTriangle3D Return type: void Description: Draw a color-filled triangle (vertex in counter-clockwise order!) @@ -3768,14 +3761,14 @@ Function 440: DrawTriangle3D() (4 input parameters) Param[2]: v2 (type: Vector3) Param[3]: v3 (type: Vector3) Param[4]: color (type: Color) -Function 441: DrawTriangleStrip3D() (3 input parameters) +Function 440: DrawTriangleStrip3D() (3 input parameters) Name: DrawTriangleStrip3D Return type: void Description: Draw a triangle strip defined by points Param[1]: points (type: const Vector3 *) Param[2]: pointCount (type: int) Param[3]: color (type: Color) -Function 442: DrawCube() (5 input parameters) +Function 441: DrawCube() (5 input parameters) Name: DrawCube Return type: void Description: Draw cube @@ -3784,14 +3777,14 @@ Function 442: DrawCube() (5 input parameters) Param[3]: height (type: float) Param[4]: length (type: float) Param[5]: color (type: Color) -Function 443: DrawCubeV() (3 input parameters) +Function 442: DrawCubeV() (3 input parameters) Name: DrawCubeV Return type: void Description: Draw cube (Vector version) Param[1]: position (type: Vector3) Param[2]: size (type: Vector3) Param[3]: color (type: Color) -Function 444: DrawCubeWires() (5 input parameters) +Function 443: DrawCubeWires() (5 input parameters) Name: DrawCubeWires Return type: void Description: Draw cube wires @@ -3800,21 +3793,21 @@ Function 444: DrawCubeWires() (5 input parameters) Param[3]: height (type: float) Param[4]: length (type: float) Param[5]: color (type: Color) -Function 445: DrawCubeWiresV() (3 input parameters) +Function 444: DrawCubeWiresV() (3 input parameters) Name: DrawCubeWiresV Return type: void Description: Draw cube wires (Vector version) Param[1]: position (type: Vector3) Param[2]: size (type: Vector3) Param[3]: color (type: Color) -Function 446: DrawSphere() (3 input parameters) +Function 445: DrawSphere() (3 input parameters) Name: DrawSphere Return type: void Description: Draw sphere Param[1]: centerPos (type: Vector3) Param[2]: radius (type: float) Param[3]: color (type: Color) -Function 447: DrawSphereEx() (5 input parameters) +Function 446: DrawSphereEx() (5 input parameters) Name: DrawSphereEx Return type: void Description: Draw sphere with extended parameters @@ -3823,7 +3816,7 @@ Function 447: DrawSphereEx() (5 input parameters) Param[3]: rings (type: int) Param[4]: slices (type: int) Param[5]: color (type: Color) -Function 448: DrawSphereWires() (5 input parameters) +Function 447: DrawSphereWires() (5 input parameters) Name: DrawSphereWires Return type: void Description: Draw sphere wires @@ -3832,7 +3825,7 @@ Function 448: DrawSphereWires() (5 input parameters) Param[3]: rings (type: int) Param[4]: slices (type: int) Param[5]: color (type: Color) -Function 449: DrawCylinder() (6 input parameters) +Function 448: DrawCylinder() (6 input parameters) Name: DrawCylinder Return type: void Description: Draw a cylinder/cone @@ -3842,7 +3835,7 @@ Function 449: DrawCylinder() (6 input parameters) Param[4]: height (type: float) Param[5]: slices (type: int) Param[6]: color (type: Color) -Function 450: DrawCylinderEx() (6 input parameters) +Function 449: DrawCylinderEx() (6 input parameters) Name: DrawCylinderEx Return type: void Description: Draw a cylinder with base at startPos and top at endPos @@ -3852,7 +3845,7 @@ Function 450: DrawCylinderEx() (6 input parameters) Param[4]: endRadius (type: float) Param[5]: sides (type: int) Param[6]: color (type: Color) -Function 451: DrawCylinderWires() (6 input parameters) +Function 450: DrawCylinderWires() (6 input parameters) Name: DrawCylinderWires Return type: void Description: Draw a cylinder/cone wires @@ -3862,7 +3855,7 @@ Function 451: DrawCylinderWires() (6 input parameters) Param[4]: height (type: float) Param[5]: slices (type: int) Param[6]: color (type: Color) -Function 452: DrawCylinderWiresEx() (6 input parameters) +Function 451: DrawCylinderWiresEx() (6 input parameters) Name: DrawCylinderWiresEx Return type: void Description: Draw a cylinder wires with base at startPos and top at endPos @@ -3872,7 +3865,7 @@ Function 452: DrawCylinderWiresEx() (6 input parameters) Param[4]: endRadius (type: float) Param[5]: sides (type: int) Param[6]: color (type: Color) -Function 453: DrawCapsule() (6 input parameters) +Function 452: DrawCapsule() (6 input parameters) Name: DrawCapsule Return type: void Description: Draw a capsule with the center of its sphere caps at startPos and endPos @@ -3882,7 +3875,7 @@ Function 453: DrawCapsule() (6 input parameters) Param[4]: slices (type: int) Param[5]: rings (type: int) Param[6]: color (type: Color) -Function 454: DrawCapsuleWires() (6 input parameters) +Function 453: DrawCapsuleWires() (6 input parameters) Name: DrawCapsuleWires Return type: void Description: Draw capsule wireframe with the center of its sphere caps at startPos and endPos @@ -3892,51 +3885,51 @@ Function 454: DrawCapsuleWires() (6 input parameters) Param[4]: slices (type: int) Param[5]: rings (type: int) Param[6]: color (type: Color) -Function 455: DrawPlane() (3 input parameters) +Function 454: DrawPlane() (3 input parameters) Name: DrawPlane Return type: void Description: Draw a plane XZ Param[1]: centerPos (type: Vector3) Param[2]: size (type: Vector2) Param[3]: color (type: Color) -Function 456: DrawRay() (2 input parameters) +Function 455: DrawRay() (2 input parameters) Name: DrawRay Return type: void Description: Draw a ray line Param[1]: ray (type: Ray) Param[2]: color (type: Color) -Function 457: DrawGrid() (2 input parameters) +Function 456: DrawGrid() (2 input parameters) Name: DrawGrid Return type: void Description: Draw a grid (centered at (0, 0, 0)) Param[1]: slices (type: int) Param[2]: spacing (type: float) -Function 458: LoadModel() (1 input parameters) +Function 457: LoadModel() (1 input parameters) Name: LoadModel Return type: Model Description: Load model from files (meshes and materials) Param[1]: fileName (type: const char *) -Function 459: LoadModelFromMesh() (1 input parameters) +Function 458: LoadModelFromMesh() (1 input parameters) Name: LoadModelFromMesh Return type: Model Description: Load model from generated mesh (default material) Param[1]: mesh (type: Mesh) -Function 460: IsModelReady() (1 input parameters) +Function 459: IsModelReady() (1 input parameters) Name: IsModelReady Return type: bool Description: Check if a model is ready Param[1]: model (type: Model) -Function 461: UnloadModel() (1 input parameters) +Function 460: UnloadModel() (1 input parameters) Name: UnloadModel Return type: void Description: Unload model (including meshes) from memory (RAM and/or VRAM) Param[1]: model (type: Model) -Function 462: GetModelBoundingBox() (1 input parameters) +Function 461: GetModelBoundingBox() (1 input parameters) Name: GetModelBoundingBox Return type: BoundingBox Description: Compute model bounding box limits (considers all meshes) Param[1]: model (type: Model) -Function 463: DrawModel() (4 input parameters) +Function 462: DrawModel() (4 input parameters) Name: DrawModel Return type: void Description: Draw a model (with texture if set) @@ -3944,7 +3937,7 @@ Function 463: DrawModel() (4 input parameters) Param[2]: position (type: Vector3) Param[3]: scale (type: float) Param[4]: tint (type: Color) -Function 464: DrawModelEx() (6 input parameters) +Function 463: DrawModelEx() (6 input parameters) Name: DrawModelEx Return type: void Description: Draw a model with extended parameters @@ -3954,7 +3947,7 @@ Function 464: DrawModelEx() (6 input parameters) Param[4]: rotationAngle (type: float) Param[5]: scale (type: Vector3) Param[6]: tint (type: Color) -Function 465: DrawModelWires() (4 input parameters) +Function 464: DrawModelWires() (4 input parameters) Name: DrawModelWires Return type: void Description: Draw a model wires (with texture if set) @@ -3962,7 +3955,7 @@ Function 465: DrawModelWires() (4 input parameters) Param[2]: position (type: Vector3) Param[3]: scale (type: float) Param[4]: tint (type: Color) -Function 466: DrawModelWiresEx() (6 input parameters) +Function 465: DrawModelWiresEx() (6 input parameters) Name: DrawModelWiresEx Return type: void Description: Draw a model wires (with texture if set) with extended parameters @@ -3972,7 +3965,7 @@ Function 466: DrawModelWiresEx() (6 input parameters) Param[4]: rotationAngle (type: float) Param[5]: scale (type: Vector3) Param[6]: tint (type: Color) -Function 467: DrawModelPoints() (4 input parameters) +Function 466: DrawModelPoints() (4 input parameters) Name: DrawModelPoints Return type: void Description: Draw a model as points @@ -3980,7 +3973,7 @@ Function 467: DrawModelPoints() (4 input parameters) Param[2]: position (type: Vector3) Param[3]: scale (type: float) Param[4]: tint (type: Color) -Function 468: DrawModelPointsEx() (6 input parameters) +Function 467: DrawModelPointsEx() (6 input parameters) Name: DrawModelPointsEx Return type: void Description: Draw a model as points with extended parameters @@ -3990,13 +3983,13 @@ Function 468: DrawModelPointsEx() (6 input parameters) Param[4]: rotationAngle (type: float) Param[5]: scale (type: Vector3) Param[6]: tint (type: Color) -Function 469: DrawBoundingBox() (2 input parameters) +Function 468: DrawBoundingBox() (2 input parameters) Name: DrawBoundingBox Return type: void Description: Draw bounding box (wires) Param[1]: box (type: BoundingBox) Param[2]: color (type: Color) -Function 470: DrawBillboard() (5 input parameters) +Function 469: DrawBillboard() (5 input parameters) Name: DrawBillboard Return type: void Description: Draw a billboard texture @@ -4005,7 +3998,7 @@ Function 470: DrawBillboard() (5 input parameters) Param[3]: position (type: Vector3) Param[4]: scale (type: float) Param[5]: tint (type: Color) -Function 471: DrawBillboardRec() (6 input parameters) +Function 470: DrawBillboardRec() (6 input parameters) Name: DrawBillboardRec Return type: void Description: Draw a billboard texture defined by source @@ -4015,7 +4008,7 @@ Function 471: DrawBillboardRec() (6 input parameters) Param[4]: position (type: Vector3) Param[5]: size (type: Vector2) Param[6]: tint (type: Color) -Function 472: DrawBillboardPro() (9 input parameters) +Function 471: DrawBillboardPro() (9 input parameters) Name: DrawBillboardPro Return type: void Description: Draw a billboard texture defined by source and rotation @@ -4028,13 +4021,13 @@ Function 472: DrawBillboardPro() (9 input parameters) Param[7]: origin (type: Vector2) Param[8]: rotation (type: float) Param[9]: tint (type: Color) -Function 473: UploadMesh() (2 input parameters) +Function 472: UploadMesh() (2 input parameters) Name: UploadMesh Return type: void Description: Upload mesh vertex data in GPU and provide VAO/VBO ids Param[1]: mesh (type: Mesh *) Param[2]: dynamic (type: bool) -Function 474: UpdateMeshBuffer() (5 input parameters) +Function 473: UpdateMeshBuffer() (5 input parameters) Name: UpdateMeshBuffer Return type: void Description: Update mesh vertex data in GPU for a specific buffer index @@ -4043,19 +4036,19 @@ Function 474: UpdateMeshBuffer() (5 input parameters) Param[3]: data (type: const void *) Param[4]: dataSize (type: int) Param[5]: offset (type: int) -Function 475: UnloadMesh() (1 input parameters) +Function 474: UnloadMesh() (1 input parameters) Name: UnloadMesh Return type: void Description: Unload mesh data from CPU and GPU Param[1]: mesh (type: Mesh) -Function 476: DrawMesh() (3 input parameters) +Function 475: DrawMesh() (3 input parameters) Name: DrawMesh Return type: void Description: Draw a 3d mesh with material and transform Param[1]: mesh (type: Mesh) Param[2]: material (type: Material) Param[3]: transform (type: Matrix) -Function 477: DrawMeshInstanced() (4 input parameters) +Function 476: DrawMeshInstanced() (4 input parameters) Name: DrawMeshInstanced Return type: void Description: Draw multiple mesh instances with material and different transforms @@ -4063,35 +4056,35 @@ Function 477: DrawMeshInstanced() (4 input parameters) Param[2]: material (type: Material) Param[3]: transforms (type: const Matrix *) Param[4]: instances (type: int) -Function 478: GetMeshBoundingBox() (1 input parameters) +Function 477: GetMeshBoundingBox() (1 input parameters) Name: GetMeshBoundingBox Return type: BoundingBox Description: Compute mesh bounding box limits Param[1]: mesh (type: Mesh) -Function 479: GenMeshTangents() (1 input parameters) +Function 478: GenMeshTangents() (1 input parameters) Name: GenMeshTangents Return type: void Description: Compute mesh tangents Param[1]: mesh (type: Mesh *) -Function 480: ExportMesh() (2 input parameters) +Function 479: ExportMesh() (2 input parameters) Name: ExportMesh Return type: bool Description: Export mesh data to file, returns true on success Param[1]: mesh (type: Mesh) Param[2]: fileName (type: const char *) -Function 481: ExportMeshAsCode() (2 input parameters) +Function 480: ExportMeshAsCode() (2 input parameters) Name: ExportMeshAsCode Return type: bool Description: Export mesh as code file (.h) defining multiple arrays of vertex attributes Param[1]: mesh (type: Mesh) Param[2]: fileName (type: const char *) -Function 482: GenMeshPoly() (2 input parameters) +Function 481: GenMeshPoly() (2 input parameters) Name: GenMeshPoly Return type: Mesh Description: Generate polygonal mesh Param[1]: sides (type: int) Param[2]: radius (type: float) -Function 483: GenMeshPlane() (4 input parameters) +Function 482: GenMeshPlane() (4 input parameters) Name: GenMeshPlane Return type: Mesh Description: Generate plane mesh (with subdivisions) @@ -4099,42 +4092,42 @@ Function 483: GenMeshPlane() (4 input parameters) Param[2]: length (type: float) Param[3]: resX (type: int) Param[4]: resZ (type: int) -Function 484: GenMeshCube() (3 input parameters) +Function 483: GenMeshCube() (3 input parameters) Name: GenMeshCube Return type: Mesh Description: Generate cuboid mesh Param[1]: width (type: float) Param[2]: height (type: float) Param[3]: length (type: float) -Function 485: GenMeshSphere() (3 input parameters) +Function 484: GenMeshSphere() (3 input parameters) Name: GenMeshSphere Return type: Mesh Description: Generate sphere mesh (standard sphere) Param[1]: radius (type: float) Param[2]: rings (type: int) Param[3]: slices (type: int) -Function 486: GenMeshHemiSphere() (3 input parameters) +Function 485: GenMeshHemiSphere() (3 input parameters) Name: GenMeshHemiSphere Return type: Mesh Description: Generate half-sphere mesh (no bottom cap) Param[1]: radius (type: float) Param[2]: rings (type: int) Param[3]: slices (type: int) -Function 487: GenMeshCylinder() (3 input parameters) +Function 486: GenMeshCylinder() (3 input parameters) Name: GenMeshCylinder Return type: Mesh Description: Generate cylinder mesh Param[1]: radius (type: float) Param[2]: height (type: float) Param[3]: slices (type: int) -Function 488: GenMeshCone() (3 input parameters) +Function 487: GenMeshCone() (3 input parameters) Name: GenMeshCone Return type: Mesh Description: Generate cone/pyramid mesh Param[1]: radius (type: float) Param[2]: height (type: float) Param[3]: slices (type: int) -Function 489: GenMeshTorus() (4 input parameters) +Function 488: GenMeshTorus() (4 input parameters) Name: GenMeshTorus Return type: Mesh Description: Generate torus mesh @@ -4142,7 +4135,7 @@ Function 489: GenMeshTorus() (4 input parameters) Param[2]: size (type: float) Param[3]: radSeg (type: int) Param[4]: sides (type: int) -Function 490: GenMeshKnot() (4 input parameters) +Function 489: GenMeshKnot() (4 input parameters) Name: GenMeshKnot Return type: Mesh Description: Generate trefoil knot mesh @@ -4150,91 +4143,91 @@ Function 490: GenMeshKnot() (4 input parameters) Param[2]: size (type: float) Param[3]: radSeg (type: int) Param[4]: sides (type: int) -Function 491: GenMeshHeightmap() (2 input parameters) +Function 490: GenMeshHeightmap() (2 input parameters) Name: GenMeshHeightmap Return type: Mesh Description: Generate heightmap mesh from image data Param[1]: heightmap (type: Image) Param[2]: size (type: Vector3) -Function 492: GenMeshCubicmap() (2 input parameters) +Function 491: GenMeshCubicmap() (2 input parameters) Name: GenMeshCubicmap Return type: Mesh Description: Generate cubes-based map mesh from image data Param[1]: cubicmap (type: Image) Param[2]: cubeSize (type: Vector3) -Function 493: LoadMaterials() (2 input parameters) +Function 492: LoadMaterials() (2 input parameters) Name: LoadMaterials Return type: Material * Description: Load materials from model file Param[1]: fileName (type: const char *) Param[2]: materialCount (type: int *) -Function 494: LoadMaterialDefault() (0 input parameters) +Function 493: LoadMaterialDefault() (0 input parameters) Name: LoadMaterialDefault Return type: Material Description: Load default material (Supports: DIFFUSE, SPECULAR, NORMAL maps) No input parameters -Function 495: IsMaterialReady() (1 input parameters) +Function 494: IsMaterialReady() (1 input parameters) Name: IsMaterialReady Return type: bool Description: Check if a material is ready Param[1]: material (type: Material) -Function 496: UnloadMaterial() (1 input parameters) +Function 495: UnloadMaterial() (1 input parameters) Name: UnloadMaterial Return type: void Description: Unload material from GPU memory (VRAM) Param[1]: material (type: Material) -Function 497: SetMaterialTexture() (3 input parameters) +Function 496: SetMaterialTexture() (3 input parameters) Name: SetMaterialTexture Return type: void Description: Set texture for a material map type (MATERIAL_MAP_DIFFUSE, MATERIAL_MAP_SPECULAR...) Param[1]: material (type: Material *) Param[2]: mapType (type: int) Param[3]: texture (type: Texture2D) -Function 498: SetModelMeshMaterial() (3 input parameters) +Function 497: SetModelMeshMaterial() (3 input parameters) Name: SetModelMeshMaterial Return type: void Description: Set material for a mesh Param[1]: model (type: Model *) Param[2]: meshId (type: int) Param[3]: materialId (type: int) -Function 499: LoadModelAnimations() (2 input parameters) +Function 498: LoadModelAnimations() (2 input parameters) Name: LoadModelAnimations Return type: ModelAnimation * Description: Load model animations from file Param[1]: fileName (type: const char *) Param[2]: animCount (type: int *) -Function 500: UpdateModelAnimation() (3 input parameters) +Function 499: UpdateModelAnimation() (3 input parameters) Name: UpdateModelAnimation Return type: void Description: Update model animation pose Param[1]: model (type: Model) Param[2]: anim (type: ModelAnimation) Param[3]: frame (type: int) -Function 501: UnloadModelAnimation() (1 input parameters) +Function 500: UnloadModelAnimation() (1 input parameters) Name: UnloadModelAnimation Return type: void Description: Unload animation data Param[1]: anim (type: ModelAnimation) -Function 502: UnloadModelAnimations() (2 input parameters) +Function 501: UnloadModelAnimations() (2 input parameters) Name: UnloadModelAnimations Return type: void Description: Unload animation array data Param[1]: animations (type: ModelAnimation *) Param[2]: animCount (type: int) -Function 503: IsModelAnimationValid() (2 input parameters) +Function 502: IsModelAnimationValid() (2 input parameters) Name: IsModelAnimationValid Return type: bool Description: Check model animation skeleton match Param[1]: model (type: Model) Param[2]: anim (type: ModelAnimation) -Function 504: UpdateModelAnimationBoneMatrices() (3 input parameters) +Function 503: UpdateModelAnimationBoneMatrices() (3 input parameters) Name: UpdateModelAnimationBoneMatrices Return type: void Description: Update model animation mesh bone matrices (Note GPU skinning does not work on Mac) Param[1]: model (type: Model) Param[2]: anim (type: ModelAnimation) Param[3]: frame (type: int) -Function 505: CheckCollisionSpheres() (4 input parameters) +Function 504: CheckCollisionSpheres() (4 input parameters) Name: CheckCollisionSpheres Return type: bool Description: Check collision between two spheres @@ -4242,40 +4235,40 @@ Function 505: CheckCollisionSpheres() (4 input parameters) Param[2]: radius1 (type: float) Param[3]: center2 (type: Vector3) Param[4]: radius2 (type: float) -Function 506: CheckCollisionBoxes() (2 input parameters) +Function 505: CheckCollisionBoxes() (2 input parameters) Name: CheckCollisionBoxes Return type: bool Description: Check collision between two bounding boxes Param[1]: box1 (type: BoundingBox) Param[2]: box2 (type: BoundingBox) -Function 507: CheckCollisionBoxSphere() (3 input parameters) +Function 506: CheckCollisionBoxSphere() (3 input parameters) Name: CheckCollisionBoxSphere Return type: bool Description: Check collision between box and sphere Param[1]: box (type: BoundingBox) Param[2]: center (type: Vector3) Param[3]: radius (type: float) -Function 508: GetRayCollisionSphere() (3 input parameters) +Function 507: GetRayCollisionSphere() (3 input parameters) Name: GetRayCollisionSphere Return type: RayCollision Description: Get collision info between ray and sphere Param[1]: ray (type: Ray) Param[2]: center (type: Vector3) Param[3]: radius (type: float) -Function 509: GetRayCollisionBox() (2 input parameters) +Function 508: GetRayCollisionBox() (2 input parameters) Name: GetRayCollisionBox Return type: RayCollision Description: Get collision info between ray and box Param[1]: ray (type: Ray) Param[2]: box (type: BoundingBox) -Function 510: GetRayCollisionMesh() (3 input parameters) +Function 509: GetRayCollisionMesh() (3 input parameters) Name: GetRayCollisionMesh Return type: RayCollision Description: Get collision info between ray and mesh Param[1]: ray (type: Ray) Param[2]: mesh (type: Mesh) Param[3]: transform (type: Matrix) -Function 511: GetRayCollisionTriangle() (4 input parameters) +Function 510: GetRayCollisionTriangle() (4 input parameters) Name: GetRayCollisionTriangle Return type: RayCollision Description: Get collision info between ray and triangle @@ -4283,7 +4276,7 @@ Function 511: GetRayCollisionTriangle() (4 input parameters) Param[2]: p1 (type: Vector3) Param[3]: p2 (type: Vector3) Param[4]: p3 (type: Vector3) -Function 512: GetRayCollisionQuad() (5 input parameters) +Function 511: GetRayCollisionQuad() (5 input parameters) Name: GetRayCollisionQuad Return type: RayCollision Description: Get collision info between ray and quad @@ -4292,158 +4285,158 @@ Function 512: GetRayCollisionQuad() (5 input parameters) Param[3]: p2 (type: Vector3) Param[4]: p3 (type: Vector3) Param[5]: p4 (type: Vector3) -Function 513: InitAudioDevice() (0 input parameters) +Function 512: InitAudioDevice() (0 input parameters) Name: InitAudioDevice Return type: void Description: Initialize audio device and context No input parameters -Function 514: CloseAudioDevice() (0 input parameters) +Function 513: CloseAudioDevice() (0 input parameters) Name: CloseAudioDevice Return type: void Description: Close the audio device and context No input parameters -Function 515: IsAudioDeviceReady() (0 input parameters) +Function 514: IsAudioDeviceReady() (0 input parameters) Name: IsAudioDeviceReady Return type: bool Description: Check if audio device has been initialized successfully No input parameters -Function 516: SetMasterVolume() (1 input parameters) +Function 515: SetMasterVolume() (1 input parameters) Name: SetMasterVolume Return type: void Description: Set master volume (listener) Param[1]: volume (type: float) -Function 517: GetMasterVolume() (0 input parameters) +Function 516: GetMasterVolume() (0 input parameters) Name: GetMasterVolume Return type: float Description: Get master volume (listener) No input parameters -Function 518: LoadWave() (1 input parameters) +Function 517: LoadWave() (1 input parameters) Name: LoadWave Return type: Wave Description: Load wave data from file Param[1]: fileName (type: const char *) -Function 519: LoadWaveFromMemory() (3 input parameters) +Function 518: LoadWaveFromMemory() (3 input parameters) Name: LoadWaveFromMemory Return type: Wave Description: Load wave from memory buffer, fileType refers to extension: i.e. '.wav' Param[1]: fileType (type: const char *) Param[2]: fileData (type: const unsigned char *) Param[3]: dataSize (type: int) -Function 520: IsWaveReady() (1 input parameters) +Function 519: IsWaveReady() (1 input parameters) Name: IsWaveReady Return type: bool Description: Checks if wave data is ready Param[1]: wave (type: Wave) -Function 521: LoadSound() (1 input parameters) +Function 520: LoadSound() (1 input parameters) Name: LoadSound Return type: Sound Description: Load sound from file Param[1]: fileName (type: const char *) -Function 522: LoadSoundFromWave() (1 input parameters) +Function 521: LoadSoundFromWave() (1 input parameters) Name: LoadSoundFromWave Return type: Sound Description: Load sound from wave data Param[1]: wave (type: Wave) -Function 523: LoadSoundAlias() (1 input parameters) +Function 522: LoadSoundAlias() (1 input parameters) Name: LoadSoundAlias Return type: Sound Description: Create a new sound that shares the same sample data as the source sound, does not own the sound data Param[1]: source (type: Sound) -Function 524: IsSoundReady() (1 input parameters) +Function 523: IsSoundReady() (1 input parameters) Name: IsSoundReady Return type: bool Description: Checks if a sound is ready Param[1]: sound (type: Sound) -Function 525: UpdateSound() (3 input parameters) +Function 524: UpdateSound() (3 input parameters) Name: UpdateSound Return type: void Description: Update sound buffer with new data Param[1]: sound (type: Sound) Param[2]: data (type: const void *) Param[3]: sampleCount (type: int) -Function 526: UnloadWave() (1 input parameters) +Function 525: UnloadWave() (1 input parameters) Name: UnloadWave Return type: void Description: Unload wave data Param[1]: wave (type: Wave) -Function 527: UnloadSound() (1 input parameters) +Function 526: UnloadSound() (1 input parameters) Name: UnloadSound Return type: void Description: Unload sound Param[1]: sound (type: Sound) -Function 528: UnloadSoundAlias() (1 input parameters) +Function 527: UnloadSoundAlias() (1 input parameters) Name: UnloadSoundAlias Return type: void Description: Unload a sound alias (does not deallocate sample data) Param[1]: alias (type: Sound) -Function 529: ExportWave() (2 input parameters) +Function 528: ExportWave() (2 input parameters) Name: ExportWave Return type: bool Description: Export wave data to file, returns true on success Param[1]: wave (type: Wave) Param[2]: fileName (type: const char *) -Function 530: ExportWaveAsCode() (2 input parameters) +Function 529: ExportWaveAsCode() (2 input parameters) Name: ExportWaveAsCode Return type: bool Description: Export wave sample data to code (.h), returns true on success Param[1]: wave (type: Wave) Param[2]: fileName (type: const char *) -Function 531: PlaySound() (1 input parameters) +Function 530: PlaySound() (1 input parameters) Name: PlaySound Return type: void Description: Play a sound Param[1]: sound (type: Sound) -Function 532: StopSound() (1 input parameters) +Function 531: StopSound() (1 input parameters) Name: StopSound Return type: void Description: Stop playing a sound Param[1]: sound (type: Sound) -Function 533: PauseSound() (1 input parameters) +Function 532: PauseSound() (1 input parameters) Name: PauseSound Return type: void Description: Pause a sound Param[1]: sound (type: Sound) -Function 534: ResumeSound() (1 input parameters) +Function 533: ResumeSound() (1 input parameters) Name: ResumeSound Return type: void Description: Resume a paused sound Param[1]: sound (type: Sound) -Function 535: IsSoundPlaying() (1 input parameters) +Function 534: IsSoundPlaying() (1 input parameters) Name: IsSoundPlaying Return type: bool Description: Check if a sound is currently playing Param[1]: sound (type: Sound) -Function 536: SetSoundVolume() (2 input parameters) +Function 535: SetSoundVolume() (2 input parameters) Name: SetSoundVolume Return type: void Description: Set volume for a sound (1.0 is max level) Param[1]: sound (type: Sound) Param[2]: volume (type: float) -Function 537: SetSoundPitch() (2 input parameters) +Function 536: SetSoundPitch() (2 input parameters) Name: SetSoundPitch Return type: void Description: Set pitch for a sound (1.0 is base level) Param[1]: sound (type: Sound) Param[2]: pitch (type: float) -Function 538: SetSoundPan() (2 input parameters) +Function 537: SetSoundPan() (2 input parameters) Name: SetSoundPan Return type: void Description: Set pan for a sound (0.5 is center) Param[1]: sound (type: Sound) Param[2]: pan (type: float) -Function 539: WaveCopy() (1 input parameters) +Function 538: WaveCopy() (1 input parameters) Name: WaveCopy Return type: Wave Description: Copy a wave to a new wave Param[1]: wave (type: Wave) -Function 540: WaveCrop() (3 input parameters) +Function 539: WaveCrop() (3 input parameters) Name: WaveCrop Return type: void Description: Crop a wave to defined frames range Param[1]: wave (type: Wave *) Param[2]: initFrame (type: int) Param[3]: finalFrame (type: int) -Function 541: WaveFormat() (4 input parameters) +Function 540: WaveFormat() (4 input parameters) Name: WaveFormat Return type: void Description: Convert wave data to desired format @@ -4451,203 +4444,203 @@ Function 541: WaveFormat() (4 input parameters) Param[2]: sampleRate (type: int) Param[3]: sampleSize (type: int) Param[4]: channels (type: int) -Function 542: LoadWaveSamples() (1 input parameters) +Function 541: LoadWaveSamples() (1 input parameters) Name: LoadWaveSamples Return type: float * Description: Load samples data from wave as a 32bit float data array Param[1]: wave (type: Wave) -Function 543: UnloadWaveSamples() (1 input parameters) +Function 542: UnloadWaveSamples() (1 input parameters) Name: UnloadWaveSamples Return type: void Description: Unload samples data loaded with LoadWaveSamples() Param[1]: samples (type: float *) -Function 544: LoadMusicStream() (1 input parameters) +Function 543: LoadMusicStream() (1 input parameters) Name: LoadMusicStream Return type: Music Description: Load music stream from file Param[1]: fileName (type: const char *) -Function 545: LoadMusicStreamFromMemory() (3 input parameters) +Function 544: LoadMusicStreamFromMemory() (3 input parameters) Name: LoadMusicStreamFromMemory Return type: Music Description: Load music stream from data Param[1]: fileType (type: const char *) Param[2]: data (type: const unsigned char *) Param[3]: dataSize (type: int) -Function 546: IsMusicReady() (1 input parameters) +Function 545: IsMusicReady() (1 input parameters) Name: IsMusicReady Return type: bool Description: Checks if a music stream is ready Param[1]: music (type: Music) -Function 547: UnloadMusicStream() (1 input parameters) +Function 546: UnloadMusicStream() (1 input parameters) Name: UnloadMusicStream Return type: void Description: Unload music stream Param[1]: music (type: Music) -Function 548: PlayMusicStream() (1 input parameters) +Function 547: PlayMusicStream() (1 input parameters) Name: PlayMusicStream Return type: void Description: Start music playing Param[1]: music (type: Music) -Function 549: IsMusicStreamPlaying() (1 input parameters) +Function 548: IsMusicStreamPlaying() (1 input parameters) Name: IsMusicStreamPlaying Return type: bool Description: Check if music is playing Param[1]: music (type: Music) -Function 550: UpdateMusicStream() (1 input parameters) +Function 549: UpdateMusicStream() (1 input parameters) Name: UpdateMusicStream Return type: void Description: Updates buffers for music streaming Param[1]: music (type: Music) -Function 551: StopMusicStream() (1 input parameters) +Function 550: StopMusicStream() (1 input parameters) Name: StopMusicStream Return type: void Description: Stop music playing Param[1]: music (type: Music) -Function 552: PauseMusicStream() (1 input parameters) +Function 551: PauseMusicStream() (1 input parameters) Name: PauseMusicStream Return type: void Description: Pause music playing Param[1]: music (type: Music) -Function 553: ResumeMusicStream() (1 input parameters) +Function 552: ResumeMusicStream() (1 input parameters) Name: ResumeMusicStream Return type: void Description: Resume playing paused music Param[1]: music (type: Music) -Function 554: SeekMusicStream() (2 input parameters) +Function 553: SeekMusicStream() (2 input parameters) Name: SeekMusicStream Return type: void Description: Seek music to a position (in seconds) Param[1]: music (type: Music) Param[2]: position (type: float) -Function 555: SetMusicVolume() (2 input parameters) +Function 554: SetMusicVolume() (2 input parameters) Name: SetMusicVolume Return type: void Description: Set volume for music (1.0 is max level) Param[1]: music (type: Music) Param[2]: volume (type: float) -Function 556: SetMusicPitch() (2 input parameters) +Function 555: SetMusicPitch() (2 input parameters) Name: SetMusicPitch Return type: void Description: Set pitch for a music (1.0 is base level) Param[1]: music (type: Music) Param[2]: pitch (type: float) -Function 557: SetMusicPan() (2 input parameters) +Function 556: SetMusicPan() (2 input parameters) Name: SetMusicPan Return type: void Description: Set pan for a music (0.5 is center) Param[1]: music (type: Music) Param[2]: pan (type: float) -Function 558: GetMusicTimeLength() (1 input parameters) +Function 557: GetMusicTimeLength() (1 input parameters) Name: GetMusicTimeLength Return type: float Description: Get music time length (in seconds) Param[1]: music (type: Music) -Function 559: GetMusicTimePlayed() (1 input parameters) +Function 558: GetMusicTimePlayed() (1 input parameters) Name: GetMusicTimePlayed Return type: float Description: Get current music time played (in seconds) Param[1]: music (type: Music) -Function 560: LoadAudioStream() (3 input parameters) +Function 559: LoadAudioStream() (3 input parameters) Name: LoadAudioStream Return type: AudioStream Description: Load audio stream (to stream raw audio pcm data) Param[1]: sampleRate (type: unsigned int) Param[2]: sampleSize (type: unsigned int) Param[3]: channels (type: unsigned int) -Function 561: IsAudioStreamReady() (1 input parameters) +Function 560: IsAudioStreamReady() (1 input parameters) Name: IsAudioStreamReady Return type: bool Description: Checks if an audio stream is ready Param[1]: stream (type: AudioStream) -Function 562: UnloadAudioStream() (1 input parameters) +Function 561: UnloadAudioStream() (1 input parameters) Name: UnloadAudioStream Return type: void Description: Unload audio stream and free memory Param[1]: stream (type: AudioStream) -Function 563: UpdateAudioStream() (3 input parameters) +Function 562: UpdateAudioStream() (3 input parameters) Name: UpdateAudioStream Return type: void Description: Update audio stream buffers with data Param[1]: stream (type: AudioStream) Param[2]: data (type: const void *) Param[3]: frameCount (type: int) -Function 564: IsAudioStreamProcessed() (1 input parameters) +Function 563: IsAudioStreamProcessed() (1 input parameters) Name: IsAudioStreamProcessed Return type: bool Description: Check if any audio stream buffers requires refill Param[1]: stream (type: AudioStream) -Function 565: PlayAudioStream() (1 input parameters) +Function 564: PlayAudioStream() (1 input parameters) Name: PlayAudioStream Return type: void Description: Play audio stream Param[1]: stream (type: AudioStream) -Function 566: PauseAudioStream() (1 input parameters) +Function 565: PauseAudioStream() (1 input parameters) Name: PauseAudioStream Return type: void Description: Pause audio stream Param[1]: stream (type: AudioStream) -Function 567: ResumeAudioStream() (1 input parameters) +Function 566: ResumeAudioStream() (1 input parameters) Name: ResumeAudioStream Return type: void Description: Resume audio stream Param[1]: stream (type: AudioStream) -Function 568: IsAudioStreamPlaying() (1 input parameters) +Function 567: IsAudioStreamPlaying() (1 input parameters) Name: IsAudioStreamPlaying Return type: bool Description: Check if audio stream is playing Param[1]: stream (type: AudioStream) -Function 569: StopAudioStream() (1 input parameters) +Function 568: StopAudioStream() (1 input parameters) Name: StopAudioStream Return type: void Description: Stop audio stream Param[1]: stream (type: AudioStream) -Function 570: SetAudioStreamVolume() (2 input parameters) +Function 569: SetAudioStreamVolume() (2 input parameters) Name: SetAudioStreamVolume Return type: void Description: Set volume for audio stream (1.0 is max level) Param[1]: stream (type: AudioStream) Param[2]: volume (type: float) -Function 571: SetAudioStreamPitch() (2 input parameters) +Function 570: SetAudioStreamPitch() (2 input parameters) Name: SetAudioStreamPitch Return type: void Description: Set pitch for audio stream (1.0 is base level) Param[1]: stream (type: AudioStream) Param[2]: pitch (type: float) -Function 572: SetAudioStreamPan() (2 input parameters) +Function 571: SetAudioStreamPan() (2 input parameters) Name: SetAudioStreamPan Return type: void Description: Set pan for audio stream (0.5 is centered) Param[1]: stream (type: AudioStream) Param[2]: pan (type: float) -Function 573: SetAudioStreamBufferSizeDefault() (1 input parameters) +Function 572: SetAudioStreamBufferSizeDefault() (1 input parameters) Name: SetAudioStreamBufferSizeDefault Return type: void Description: Default size for new audio streams Param[1]: size (type: int) -Function 574: SetAudioStreamCallback() (2 input parameters) +Function 573: SetAudioStreamCallback() (2 input parameters) Name: SetAudioStreamCallback Return type: void Description: Audio thread callback to request new data Param[1]: stream (type: AudioStream) Param[2]: callback (type: AudioCallback) -Function 575: AttachAudioStreamProcessor() (2 input parameters) +Function 574: AttachAudioStreamProcessor() (2 input parameters) Name: AttachAudioStreamProcessor Return type: void Description: Attach audio stream processor to stream, receives the samples as 'float' Param[1]: stream (type: AudioStream) Param[2]: processor (type: AudioCallback) -Function 576: DetachAudioStreamProcessor() (2 input parameters) +Function 575: DetachAudioStreamProcessor() (2 input parameters) Name: DetachAudioStreamProcessor Return type: void Description: Detach audio stream processor from stream Param[1]: stream (type: AudioStream) Param[2]: processor (type: AudioCallback) -Function 577: AttachAudioMixedProcessor() (1 input parameters) +Function 576: AttachAudioMixedProcessor() (1 input parameters) Name: AttachAudioMixedProcessor Return type: void Description: Attach audio stream processor to the entire audio pipeline, receives the samples as 'float' Param[1]: processor (type: AudioCallback) -Function 578: DetachAudioMixedProcessor() (1 input parameters) +Function 577: DetachAudioMixedProcessor() (1 input parameters) Name: DetachAudioMixedProcessor Return type: void Description: Detach audio stream processor from the entire audio pipeline diff --git a/parser/output/raylib_api.xml b/parser/output/raylib_api.xml index 895680f2c..73ce0dae7 100644 --- a/parser/output/raylib_api.xml +++ b/parser/output/raylib_api.xml @@ -675,7 +675,7 @@ - + @@ -1699,11 +1699,6 @@ - - - - - From 59417636ca956d64800e7e26d4f4ec331cf1b412 Mon Sep 17 00:00:00 2001 From: Anand Swaroop <72886192+Anut-py@users.noreply.github.com> Date: Sat, 12 Oct 2024 07:14:35 -0400 Subject: [PATCH 119/208] Update BINDINGS.md (#4378) --- BINDINGS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BINDINGS.md b/BINDINGS.md index e79d39c36..576d9b463 100644 --- a/BINDINGS.md +++ b/BINDINGS.md @@ -31,7 +31,7 @@ Some people ported raylib to other languages in the form of bindings or wrappers | [raylib-go](https://github.com/gen2brain/raylib-go) | **5.0** | [Go](https://golang.org) | Zlib | | [raylib-guile](https://github.com/petelliott/raylib-guile) | **auto** | [Guile](https://www.gnu.org/software/guile) | Zlib | | [gforth-raylib](https://github.com/ArnautDaniel/gforth-raylib) | 3.5 | [Gforth](https://gforth.org) | **???** | -| [h-raylib](https://github.com/Anut-py/h-raylib) | **5.1-dev** | [Haskell](https://haskell.org) | Apache-2.0 | +| [h-raylib](https://github.com/Anut-py/h-raylib) | **5.5-dev** | [Haskell](https://haskell.org) | Apache-2.0 | | [raylib-hx](https://github.com/foreignsasquatch/raylib-hx) | 4.2 | [Haxe](https://haxe.org) | Zlib | | [hb-raylib](https://github.com/MarcosLeonardoMendezGerencir/hb-raylib) | 3.5 | [Harbour](https://harbour.github.io) | MIT | | [jaylib](https://github.com/janet-lang/jaylib) | **5.0** | [Janet](https://janet-lang.org) | MIT | From bac3798ad368c7e89edfd7fa647a4e7a2a71b9bd Mon Sep 17 00:00:00 2001 From: Sage Hane Date: Mon, 14 Oct 2024 01:58:42 +0900 Subject: [PATCH 120/208] build.zig: Fix `@src` logic and a few things (#4380) --- src/build.zig | 43 +++++++++++++++++++++++++++++++------------ 1 file changed, 31 insertions(+), 12 deletions(-) diff --git a/src/build.zig b/src/build.zig index 8944c7087..1fdbca8a3 100644 --- a/src/build.zig +++ b/src/build.zig @@ -1,8 +1,14 @@ const std = @import("std"); const builtin = @import("builtin"); +/// Minimum supported version of Zig +const min_ver = "0.12.0"; + comptime { - if (builtin.zig_version.minor < 12) @compileError("Raylib requires zig version 0.12.0"); + const order = std.SemanticVersion.order; + const parse = std.SemanticVersion.parse; + if (order(builtin.zig_version, parse(min_ver) catch unreachable) == .lt) + @compileError("Raylib requires zig version " ++ min_ver); } // NOTE(freakmangd): I don't like using a global here, but it prevents having to @@ -28,6 +34,7 @@ pub fn addRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std. .shared = options.shared, .linux_display_backend = options.linux_display_backend, .opengl_version = options.opengl_version, + // TODO: Fix the type mismatch caused here due to unsupported `?[]const u8`. .config = options.config, }); const raylib = raylib_dep.artifact("raylib"); @@ -51,8 +58,19 @@ fn setDesktopPlatform(raylib: *std.Build.Step.Compile, platform: PlatformBackend } } -fn srcDir() []const u8 { - return std.fs.path.dirname(@src().file) orelse "."; +/// TODO: Once the minimum supported version is bumped to 0.14.0, it can be simplified again: +/// https://github.com/raysan5/raylib/pull/4375#issuecomment-2408998315 +/// https://github.com/raysan5/raylib/blob/9b9c72eb0dc705cde194b053a366a40396acfb67/src/build.zig#L54-L56 +fn srcDir(b: *std.Build) []const u8 { + comptime { + const order = std.SemanticVersion.order; + const parse = std.SemanticVersion.parse; + if (order(min_ver, parse("0.14.0") catch unreachable) != .lt) + @compileError("Please take a look at this function again"); + } + + const src_file = std.fs.path.relative(b.allocator, @src().file, ".") catch @panic("OOM"); + return std.fs.path.dirname(src_file) orelse "."; } fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, options: Options) !*std.Build.Step.Compile { @@ -69,7 +87,7 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std. "-fno-sanitize=undefined", // https://github.com/raysan5/raylib/issues/3674 }); if (options.config) |config| { - const file = b.pathJoin(&.{ srcDir(), "config.h" }); + const file = b.pathJoin(&.{ srcDir(b), "config.h" }); const content = try std.fs.cwd().readFileAlloc(b.allocator, file, std.math.maxInt(usize)); defer b.allocator.free(content); @@ -118,7 +136,8 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std. // No GLFW required on PLATFORM_DRM if (options.platform != .drm) { - raylib.addIncludePath(b.path(b.pathJoin(&.{ srcDir(), "external/glfw/include" }))); + _ = std.debug.print("\n\n{s}\n\n", .{@src().file}); + raylib.addIncludePath(b.path(b.pathJoin(&.{ srcDir(b), "external/glfw/include" }))); } var c_source_files = try std.ArrayList([]const u8).initCapacity(b.allocator, 2); @@ -231,7 +250,7 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std. // On macos rglfw.c include Objective-C files. try raylib_flags_arr.append(b.allocator, "-ObjC"); raylib.root_module.addCSourceFile(.{ - .file = b.path(b.pathJoin(&.{ srcDir(), "rglfw.c" })), + .file = b.path(b.pathJoin(&.{ srcDir(b), "rglfw.c" })), .flags = raylib_flags_arr.items, }); _ = raylib_flags_arr.pop(); @@ -265,7 +284,7 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std. } raylib.root_module.addCSourceFiles(.{ - .root = b.path(srcDir()), + .root = b.path(srcDir(b)), .files = c_source_files.items, .flags = raylib_flags_arr.items, }); @@ -366,14 +385,14 @@ pub fn build(b: *std.Build) !void { .shared = b.option(bool, "shared", "Compile as shared library") orelse defaults.shared, .linux_display_backend = b.option(LinuxDisplayBackend, "linux_display_backend", "Linux display backend to use") orelse defaults.linux_display_backend, .opengl_version = b.option(OpenglVersion, "opengl_version", "OpenGL version to use") orelse defaults.opengl_version, - .config = b.option([]const u8, "config", "Compile with custom define macros overriding config.h") orelse null, + .config = b.option([]const u8, "config", "Compile with custom define macros overriding config.h"), }; const lib = try compileRaylib(b, target, optimize, options); - lib.installHeader(b.path(b.pathJoin(&.{ srcDir(), "raylib.h" })), "raylib.h"); - lib.installHeader(b.path(b.pathJoin(&.{ srcDir(), "raymath.h" })), "raymath.h"); - lib.installHeader(b.path(b.pathJoin(&.{ srcDir(), "rlgl.h" })), "rlgl.h"); + lib.installHeader(b.path(b.pathJoin(&.{ srcDir(b), "raylib.h" })), "raylib.h"); + lib.installHeader(b.path(b.pathJoin(&.{ srcDir(b), "raymath.h" })), "raymath.h"); + lib.installHeader(b.path(b.pathJoin(&.{ srcDir(b), "rlgl.h" })), "rlgl.h"); b.installArtifact(lib); } @@ -384,7 +403,7 @@ fn waylandGenerate( comptime protocol: []const u8, comptime basename: []const u8, ) void { - const waylandDir = b.pathJoin(&.{ srcDir(), "external/glfw/deps/wayland" }); + const waylandDir = b.pathJoin(&.{ srcDir(b), "external/glfw/deps/wayland" }); const protocolDir = b.pathJoin(&.{ waylandDir, protocol }); const clientHeader = basename ++ ".h"; const privateCode = basename ++ "-code.h"; From 735308f8eb7433e9850a28846461a996b6905ae1 Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 13 Oct 2024 20:02:40 +0200 Subject: [PATCH 121/208] REVIEWED: `CodepointToUTF8()`, clean static buffer #4379 --- src/rtext.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/rtext.c b/src/rtext.c index e4c89d5f1..0595e7fbe 100644 --- a/src/rtext.c +++ b/src/rtext.c @@ -1302,15 +1302,15 @@ Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing { byteCounter++; - int next = 0; - letter = GetCodepointNext(&text[i], &next); + int codepointByteCount = 0; + letter = GetCodepointNext(&text[i], &codepointByteCount); index = GetGlyphIndex(font, letter); - i += next; + i += codepointByteCount; if (letter != '\n') { - if (font.glyphs[index].advanceX != 0) textWidth += font.glyphs[index].advanceX; + if (font.glyphs[index].advanceX > 0) textWidth += font.glyphs[index].advanceX; else textWidth += (font.recs[index].width + font.glyphs[index].offsetX); } else @@ -1930,7 +1930,8 @@ int GetCodepointCount(const char *text) const char *CodepointToUTF8(int codepoint, int *utf8Size) { static char utf8[6] = { 0 }; - int size = 0; // Byte size of codepoint + memset(utf8, 0, 6); // Clear static array + int size = 0; // Byte size of codepoint if (codepoint <= 0x7f) { From c18677e70ffc978456262696d66c15443c9f4c41 Mon Sep 17 00:00:00 2001 From: Sage Hane Date: Mon, 14 Oct 2024 03:24:39 +0900 Subject: [PATCH 122/208] build.zig: Very minor fixes (#4381) --- src/build.zig | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/build.zig b/src/build.zig index 1fdbca8a3..40a506fd5 100644 --- a/src/build.zig +++ b/src/build.zig @@ -65,7 +65,7 @@ fn srcDir(b: *std.Build) []const u8 { comptime { const order = std.SemanticVersion.order; const parse = std.SemanticVersion.parse; - if (order(min_ver, parse("0.14.0") catch unreachable) != .lt) + if (order(parse(min_ver) catch unreachable, parse("0.14.0") catch unreachable) != .lt) @compileError("Please take a look at this function again"); } @@ -136,7 +136,6 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std. // No GLFW required on PLATFORM_DRM if (options.platform != .drm) { - _ = std.debug.print("\n\n{s}\n\n", .{@src().file}); raylib.addIncludePath(b.path(b.pathJoin(&.{ srcDir(b), "external/glfw/include" }))); } From 99ff770edce0cf025a77f8bf1923b6a072f8a44e Mon Sep 17 00:00:00 2001 From: yuval_dev <47389924+yuval-herman@users.noreply.github.com> Date: Tue, 15 Oct 2024 20:02:20 +0300 Subject: [PATCH 123/208] Fix the type mismatch caused due to unsupported `?[]const u8` (#4383) Co-authored-by: Yuval Herman --- src/build.zig | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/build.zig b/src/build.zig index 40a506fd5..2a8b88262 100644 --- a/src/build.zig +++ b/src/build.zig @@ -34,7 +34,6 @@ pub fn addRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std. .shared = options.shared, .linux_display_backend = options.linux_display_backend, .opengl_version = options.opengl_version, - // TODO: Fix the type mismatch caused here due to unsupported `?[]const u8`. .config = options.config, }); const raylib = raylib_dep.artifact("raylib"); @@ -86,7 +85,7 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std. "-DGL_SILENCE_DEPRECATION=199309L", "-fno-sanitize=undefined", // https://github.com/raysan5/raylib/issues/3674 }); - if (options.config) |config| { + if (options.config.len > 0) { const file = b.pathJoin(&.{ srcDir(b), "config.h" }); const content = try std.fs.cwd().readFileAlloc(b.allocator, file, std.math.maxInt(usize)); defer b.allocator.free(content); @@ -104,14 +103,14 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std. flag = try std.fmt.allocPrint(b.allocator, "-D{s}", .{flag}); // Prepend with -D // If user specifies the flag skip it - if (std.mem.containsAtLeast(u8, config, 1, flag)) continue; + if (std.mem.containsAtLeast(u8, options.config, 1, flag)) continue; // Append default value from config.h to compile flags try raylib_flags_arr.append(b.allocator, flag); } // Append config flags supplied by user to compile flags - try raylib_flags_arr.append(b.allocator, config); + try raylib_flags_arr.append(b.allocator, options.config); try raylib_flags_arr.append(b.allocator, "-DEXTERNAL_CONFIG_FLAGS"); } @@ -321,7 +320,7 @@ pub const Options = struct { linux_display_backend: LinuxDisplayBackend = .Both, opengl_version: OpenglVersion = .auto, /// config should be a list of cflags, eg, "-DSUPPORT_CUSTOM_FRAME_CONTROL" - config: ?[]const u8 = null, + config: []const u8 = &.{}, raygui_dependency_name: []const u8 = "raygui", }; @@ -384,7 +383,7 @@ pub fn build(b: *std.Build) !void { .shared = b.option(bool, "shared", "Compile as shared library") orelse defaults.shared, .linux_display_backend = b.option(LinuxDisplayBackend, "linux_display_backend", "Linux display backend to use") orelse defaults.linux_display_backend, .opengl_version = b.option(OpenglVersion, "opengl_version", "OpenGL version to use") orelse defaults.opengl_version, - .config = b.option([]const u8, "config", "Compile with custom define macros overriding config.h"), + .config = b.option([]const u8, "config", "Compile with custom define macros overriding config.h") orelse &.{}, }; const lib = try compileRaylib(b, target, optimize, options); From 8d267aaf236fa919b10ea380eac7476d8273936b Mon Sep 17 00:00:00 2001 From: R-YaTian <47445484+R-YaTian@users.noreply.github.com> Date: Wed, 16 Oct 2024 01:03:17 +0800 Subject: [PATCH 124/208] qoi: Added support for image of channels 3 (#4384) --- src/rtextures.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rtextures.c b/src/rtextures.c index 43d16dc7b..84264369d 100644 --- a/src/rtextures.c +++ b/src/rtextures.c @@ -506,10 +506,10 @@ Image LoadImageFromMemory(const char *fileType, const unsigned char *fileData, i if (fileData != NULL) { qoi_desc desc = { 0 }; - image.data = qoi_decode(fileData, dataSize, &desc, 4); + image.data = qoi_decode(fileData, dataSize, &desc, (int) fileData[12]); image.width = desc.width; image.height = desc.height; - image.format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8; + image.format = desc.channels == 4 ? PIXELFORMAT_UNCOMPRESSED_R8G8B8A8 : PIXELFORMAT_UNCOMPRESSED_R8G8B8; image.mipmaps = 1; } } From c9c830cb971d7aa744fe3c7444b768ccd5176c4c Mon Sep 17 00:00:00 2001 From: Jojaby Date: Wed, 16 Oct 2024 04:04:30 +1100 Subject: [PATCH 125/208] Fix rectangle width and height check to account for squares (#4382) --- src/rshapes.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rshapes.c b/src/rshapes.c index 66dfbf3b6..e9b5ca87b 100644 --- a/src/rshapes.c +++ b/src/rshapes.c @@ -828,8 +828,8 @@ void DrawRectangleLinesEx(Rectangle rec, float lineThick, Color color) { if ((lineThick > rec.width) || (lineThick > rec.height)) { - if (rec.width > rec.height) lineThick = rec.height/2; - else if (rec.width < rec.height) lineThick = rec.width/2; + if (rec.width >= rec.height) lineThick = rec.height/2; + else if (rec.width <= rec.height) lineThick = rec.width/2; } // When rec = { x, y, 8.0f, 6.0f } and lineThick = 2, the following From 361b0e85c10fb20e69c35d0304d64d891a8964f2 Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 16 Oct 2024 16:49:50 +0200 Subject: [PATCH 126/208] ADDED: Utility functions: `ComputeCRC32()` and `ComputeMD5()` --- src/raylib.h | 2 + src/rcore.c | 163 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 165 insertions(+) diff --git a/src/raylib.h b/src/raylib.h index e0c74af30..0ac4b603c 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -1144,6 +1144,8 @@ RLAPI unsigned char *CompressData(const unsigned char *data, int dataSize, int * RLAPI unsigned char *DecompressData(const unsigned char *compData, int compDataSize, int *dataSize); // Decompress data (DEFLATE algorithm), memory must be MemFree() RLAPI char *EncodeDataBase64(const unsigned char *data, int dataSize, int *outputSize); // Encode data to Base64 string, memory must be MemFree() RLAPI unsigned char *DecodeDataBase64(const unsigned char *data, int *outputSize); // Decode Base64 string data, memory must be MemFree() +RLAPI unsigned int ComputeCRC32(unsigned char *data, int dataSize); // Compute CRC32 hash code +RLAPI unsigned int *ComputeMD5(unsigned char *data, int dataSize); // Compute MD5 hash code, returns static int[4] (16 bytes) // Automation events functionality RLAPI AutomationEventList LoadAutomationEventList(const char *fileName); // Load automation events list from file, NULL for empty list, capacity = MAX_AUTOMATION_EVENTS diff --git a/src/rcore.c b/src/rcore.c index e154d6173..8ba72f715 100644 --- a/src/rcore.c +++ b/src/rcore.c @@ -2577,6 +2577,169 @@ unsigned char *DecodeDataBase64(const unsigned char *data, int *outputSize) return decodedData; } +// Compute CRC32 hash code +unsigned int ComputeCRC32(unsigned char *data, int dataSize) +{ + static unsigned int crcTable[256] = { + 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, + 0x0eDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, + 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, + 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, + 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, + 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, + 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, + 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, + 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, + 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, + 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, + 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, + 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, + 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, + 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, + 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, + 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, + 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, + 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, + 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, + 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, + 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, + 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, + 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, + 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, + 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, + 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, + 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, + 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, + 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, + 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, + 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D + }; + + unsigned int crc = ~0u; + + for (int i = 0; i < dataSize; i++) crc = (crc >> 8) ^ crcTable[data[i] ^ (crc & 0xff)]; + + return ~crc; +} + +// Compute MD5 hash code +// NOTE: Returns a static int[4] array (16 bytes) +unsigned int *ComputeMD5(unsigned char *data, int dataSize) +{ + #define ROTATE_LEFT(x, c) (((x) << (c)) | ((x) >> (32 - (c)))) + + static unsigned int hash[4] = { 0 }; // Hash to be returned + + // WARNING: All variables are unsigned 32 bit and wrap modulo 2^32 when calculating + + // NOTE: r specifies the per-round shift amounts + unsigned int r[] = { + 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, + 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, + 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, + 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21 + }; + + // Using binary integer part of the sines of integers (in radians) as constants + unsigned int k[] = { + 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, + 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, + 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, + 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, + 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, + 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8, + 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, + 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, + 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, + 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, + 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05, + 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, + 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, + 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, + 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, + 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391 + }; + + hash[0] = 0x67452301; + hash[1] = 0xefcdab89; + hash[2] = 0x98badcfe; + hash[3] = 0x10325476; + + // Pre-processing: adding a single 1 bit + // Append '1' bit to message + // NOTE: The input bytes are considered as bits strings, + // where the first bit is the most significant bit of the byte + + // Pre-processing: padding with zeros + // Append '0' bit until message length in bit 448 (mod 512) + // Append length mod (2 pow 64) to message + + int newDataSize = ((((dataSize + 8)/64) + 1)*64) - 8; + + unsigned char *msg = RL_CALLOC(newDataSize + 64, 1); // Initialize with '0' bits, allocating 64 extra bytes + memcpy(msg, data, dataSize); + msg[dataSize] = 128; // Write the '1' bit + + unsigned int bitsLen = 8*dataSize; + memcpy(msg + newDataSize, &bitsLen, 4); // Append the len in bits at the end of the buffer + + // Process the message in successive 512-bit chunks for each 512-bit chunk of message + for (int offset = 0; offset < newDataSize; offset += (512/8)) + { + // Break chunk into sixteen 32-bit words w[j], 0 <= j <= 15 + unsigned int *w = (unsigned int *)(msg + offset); + + // Initialize hash value for this chunk + unsigned int a = hash[0]; + unsigned int b = hash[1]; + unsigned int c = hash[2]; + unsigned int d = hash[3]; + + for (int i = 0; i < 64; i++) + { + unsigned int f = 0; + unsigned int g = 0; + + if (i < 16) + { + f = (b & c) | ((~b) & d); + g = i; + } + else if (i < 32) + { + f = (d & b) | ((~d) & c); + g = (5*i + 1)%16; + } + else if (i < 48) + { + f = b ^ c ^ d; + g = (3*i + 5)%16; + } + else + { + f = c ^ (b | (~d)); + g = (7*i)%16; + } + + unsigned int temp = d; + d = c; + c = b; + b = b + ROTATE_LEFT((a + f + k[i] + w[g]), r[i]); + a = temp; + } + + // Add chunk's hash to result so far + hash[0] += a; + hash[1] += b; + hash[2] += c; + hash[3] += d; + } + + RL_FREE(msg); + + return hash; +} + //---------------------------------------------------------------------------------- // Module Functions Definition: Automation Events Recording and Playing //---------------------------------------------------------------------------------- From 9b3d0195022012b3d805cd11125f61d2abbb482b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 16 Oct 2024 14:50:42 +0000 Subject: [PATCH 127/208] Update raylib_api.* by CI --- parser/output/raylib_api.json | 30 ++ parser/output/raylib_api.lua | 18 + parser/output/raylib_api.txt | 872 +++++++++++++++++----------------- parser/output/raylib_api.xml | 10 +- 4 files changed, 499 insertions(+), 431 deletions(-) diff --git a/parser/output/raylib_api.json b/parser/output/raylib_api.json index 2c8fe31e9..f735853fb 100644 --- a/parser/output/raylib_api.json +++ b/parser/output/raylib_api.json @@ -4691,6 +4691,36 @@ } ] }, + { + "name": "ComputeCRC32", + "description": "Compute CRC32 hash code", + "returnType": "unsigned int", + "params": [ + { + "type": "unsigned char *", + "name": "data" + }, + { + "type": "int", + "name": "dataSize" + } + ] + }, + { + "name": "ComputeMD5", + "description": "Compute MD5 hash code, returns static int[4] (16 bytes)", + "returnType": "unsigned int *", + "params": [ + { + "type": "unsigned char *", + "name": "data" + }, + { + "type": "int", + "name": "dataSize" + } + ] + }, { "name": "LoadAutomationEventList", "description": "Load automation events list from file, NULL for empty list, capacity = MAX_AUTOMATION_EVENTS", diff --git a/parser/output/raylib_api.lua b/parser/output/raylib_api.lua index 6c287b7a4..4c0dd5a03 100644 --- a/parser/output/raylib_api.lua +++ b/parser/output/raylib_api.lua @@ -4190,6 +4190,24 @@ return { {type = "int *", name = "outputSize"} } }, + { + name = "ComputeCRC32", + description = "Compute CRC32 hash code", + returnType = "unsigned int", + params = { + {type = "unsigned char *", name = "data"}, + {type = "int", name = "dataSize"} + } + }, + { + name = "ComputeMD5", + description = "Compute MD5 hash code, returns static int[4] (16 bytes)", + returnType = "unsigned int *", + params = { + {type = "unsigned char *", name = "data"}, + {type = "int", name = "dataSize"} + } + }, { name = "LoadAutomationEventList", description = "Load automation events list from file, NULL for empty list, capacity = MAX_AUTOMATION_EVENTS", diff --git a/parser/output/raylib_api.txt b/parser/output/raylib_api.txt index 9764769a7..865e5ae78 100644 --- a/parser/output/raylib_api.txt +++ b/parser/output/raylib_api.txt @@ -989,7 +989,7 @@ Callback 006: AudioCallback() (2 input parameters) Param[1]: bufferData (type: void *) Param[2]: frames (type: unsigned int) -Functions found: 577 +Functions found: 579 Function 001: InitWindow() (3 input parameters) Name: InitWindow @@ -1788,294 +1788,306 @@ Function 148: DecodeDataBase64() (2 input parameters) Description: Decode Base64 string data, memory must be MemFree() Param[1]: data (type: const unsigned char *) Param[2]: outputSize (type: int *) -Function 149: LoadAutomationEventList() (1 input parameters) +Function 149: ComputeCRC32() (2 input parameters) + Name: ComputeCRC32 + Return type: unsigned int + Description: Compute CRC32 hash code + Param[1]: data (type: unsigned char *) + Param[2]: dataSize (type: int) +Function 150: ComputeMD5() (2 input parameters) + Name: ComputeMD5 + Return type: unsigned int * + Description: Compute MD5 hash code, returns static int[4] (16 bytes) + Param[1]: data (type: unsigned char *) + Param[2]: dataSize (type: int) +Function 151: LoadAutomationEventList() (1 input parameters) Name: LoadAutomationEventList Return type: AutomationEventList Description: Load automation events list from file, NULL for empty list, capacity = MAX_AUTOMATION_EVENTS Param[1]: fileName (type: const char *) -Function 150: UnloadAutomationEventList() (1 input parameters) +Function 152: UnloadAutomationEventList() (1 input parameters) Name: UnloadAutomationEventList Return type: void Description: Unload automation events list from file Param[1]: list (type: AutomationEventList) -Function 151: ExportAutomationEventList() (2 input parameters) +Function 153: ExportAutomationEventList() (2 input parameters) Name: ExportAutomationEventList Return type: bool Description: Export automation events list as text file Param[1]: list (type: AutomationEventList) Param[2]: fileName (type: const char *) -Function 152: SetAutomationEventList() (1 input parameters) +Function 154: SetAutomationEventList() (1 input parameters) Name: SetAutomationEventList Return type: void Description: Set automation event list to record to Param[1]: list (type: AutomationEventList *) -Function 153: SetAutomationEventBaseFrame() (1 input parameters) +Function 155: SetAutomationEventBaseFrame() (1 input parameters) Name: SetAutomationEventBaseFrame Return type: void Description: Set automation event internal base frame to start recording Param[1]: frame (type: int) -Function 154: StartAutomationEventRecording() (0 input parameters) +Function 156: StartAutomationEventRecording() (0 input parameters) Name: StartAutomationEventRecording Return type: void Description: Start recording automation events (AutomationEventList must be set) No input parameters -Function 155: StopAutomationEventRecording() (0 input parameters) +Function 157: StopAutomationEventRecording() (0 input parameters) Name: StopAutomationEventRecording Return type: void Description: Stop recording automation events No input parameters -Function 156: PlayAutomationEvent() (1 input parameters) +Function 158: PlayAutomationEvent() (1 input parameters) Name: PlayAutomationEvent Return type: void Description: Play a recorded automation event Param[1]: event (type: AutomationEvent) -Function 157: IsKeyPressed() (1 input parameters) +Function 159: IsKeyPressed() (1 input parameters) Name: IsKeyPressed Return type: bool Description: Check if a key has been pressed once Param[1]: key (type: int) -Function 158: IsKeyPressedRepeat() (1 input parameters) +Function 160: IsKeyPressedRepeat() (1 input parameters) Name: IsKeyPressedRepeat Return type: bool Description: Check if a key has been pressed again (Only PLATFORM_DESKTOP) Param[1]: key (type: int) -Function 159: IsKeyDown() (1 input parameters) +Function 161: IsKeyDown() (1 input parameters) Name: IsKeyDown Return type: bool Description: Check if a key is being pressed Param[1]: key (type: int) -Function 160: IsKeyReleased() (1 input parameters) +Function 162: IsKeyReleased() (1 input parameters) Name: IsKeyReleased Return type: bool Description: Check if a key has been released once Param[1]: key (type: int) -Function 161: IsKeyUp() (1 input parameters) +Function 163: IsKeyUp() (1 input parameters) Name: IsKeyUp Return type: bool Description: Check if a key is NOT being pressed Param[1]: key (type: int) -Function 162: GetKeyPressed() (0 input parameters) +Function 164: GetKeyPressed() (0 input parameters) Name: GetKeyPressed Return type: int Description: Get key pressed (keycode), call it multiple times for keys queued, returns 0 when the queue is empty No input parameters -Function 163: GetCharPressed() (0 input parameters) +Function 165: GetCharPressed() (0 input parameters) Name: GetCharPressed Return type: int Description: Get char pressed (unicode), call it multiple times for chars queued, returns 0 when the queue is empty No input parameters -Function 164: SetExitKey() (1 input parameters) +Function 166: SetExitKey() (1 input parameters) Name: SetExitKey Return type: void Description: Set a custom key to exit program (default is ESC) Param[1]: key (type: int) -Function 165: IsGamepadAvailable() (1 input parameters) +Function 167: IsGamepadAvailable() (1 input parameters) Name: IsGamepadAvailable Return type: bool Description: Check if a gamepad is available Param[1]: gamepad (type: int) -Function 166: GetGamepadName() (1 input parameters) +Function 168: GetGamepadName() (1 input parameters) Name: GetGamepadName Return type: const char * Description: Get gamepad internal name id Param[1]: gamepad (type: int) -Function 167: IsGamepadButtonPressed() (2 input parameters) +Function 169: IsGamepadButtonPressed() (2 input parameters) Name: IsGamepadButtonPressed Return type: bool Description: Check if a gamepad button has been pressed once Param[1]: gamepad (type: int) Param[2]: button (type: int) -Function 168: IsGamepadButtonDown() (2 input parameters) +Function 170: IsGamepadButtonDown() (2 input parameters) Name: IsGamepadButtonDown Return type: bool Description: Check if a gamepad button is being pressed Param[1]: gamepad (type: int) Param[2]: button (type: int) -Function 169: IsGamepadButtonReleased() (2 input parameters) +Function 171: IsGamepadButtonReleased() (2 input parameters) Name: IsGamepadButtonReleased Return type: bool Description: Check if a gamepad button has been released once Param[1]: gamepad (type: int) Param[2]: button (type: int) -Function 170: IsGamepadButtonUp() (2 input parameters) +Function 172: IsGamepadButtonUp() (2 input parameters) Name: IsGamepadButtonUp Return type: bool Description: Check if a gamepad button is NOT being pressed Param[1]: gamepad (type: int) Param[2]: button (type: int) -Function 171: GetGamepadButtonPressed() (0 input parameters) +Function 173: GetGamepadButtonPressed() (0 input parameters) Name: GetGamepadButtonPressed Return type: int Description: Get the last gamepad button pressed No input parameters -Function 172: GetGamepadAxisCount() (1 input parameters) +Function 174: GetGamepadAxisCount() (1 input parameters) Name: GetGamepadAxisCount Return type: int Description: Get gamepad axis count for a gamepad Param[1]: gamepad (type: int) -Function 173: GetGamepadAxisMovement() (2 input parameters) +Function 175: GetGamepadAxisMovement() (2 input parameters) Name: GetGamepadAxisMovement Return type: float Description: Get axis movement value for a gamepad axis Param[1]: gamepad (type: int) Param[2]: axis (type: int) -Function 174: SetGamepadMappings() (1 input parameters) +Function 176: SetGamepadMappings() (1 input parameters) Name: SetGamepadMappings Return type: int Description: Set internal gamepad mappings (SDL_GameControllerDB) Param[1]: mappings (type: const char *) -Function 175: SetGamepadVibration() (3 input parameters) +Function 177: SetGamepadVibration() (3 input parameters) Name: SetGamepadVibration Return type: void Description: Set gamepad vibration for both motors Param[1]: gamepad (type: int) Param[2]: leftMotor (type: float) Param[3]: rightMotor (type: float) -Function 176: IsMouseButtonPressed() (1 input parameters) +Function 178: IsMouseButtonPressed() (1 input parameters) Name: IsMouseButtonPressed Return type: bool Description: Check if a mouse button has been pressed once Param[1]: button (type: int) -Function 177: IsMouseButtonDown() (1 input parameters) +Function 179: IsMouseButtonDown() (1 input parameters) Name: IsMouseButtonDown Return type: bool Description: Check if a mouse button is being pressed Param[1]: button (type: int) -Function 178: IsMouseButtonReleased() (1 input parameters) +Function 180: IsMouseButtonReleased() (1 input parameters) Name: IsMouseButtonReleased Return type: bool Description: Check if a mouse button has been released once Param[1]: button (type: int) -Function 179: IsMouseButtonUp() (1 input parameters) +Function 181: IsMouseButtonUp() (1 input parameters) Name: IsMouseButtonUp Return type: bool Description: Check if a mouse button is NOT being pressed Param[1]: button (type: int) -Function 180: GetMouseX() (0 input parameters) +Function 182: GetMouseX() (0 input parameters) Name: GetMouseX Return type: int Description: Get mouse position X No input parameters -Function 181: GetMouseY() (0 input parameters) +Function 183: GetMouseY() (0 input parameters) Name: GetMouseY Return type: int Description: Get mouse position Y No input parameters -Function 182: GetMousePosition() (0 input parameters) +Function 184: GetMousePosition() (0 input parameters) Name: GetMousePosition Return type: Vector2 Description: Get mouse position XY No input parameters -Function 183: GetMouseDelta() (0 input parameters) +Function 185: GetMouseDelta() (0 input parameters) Name: GetMouseDelta Return type: Vector2 Description: Get mouse delta between frames No input parameters -Function 184: SetMousePosition() (2 input parameters) +Function 186: SetMousePosition() (2 input parameters) Name: SetMousePosition Return type: void Description: Set mouse position XY Param[1]: x (type: int) Param[2]: y (type: int) -Function 185: SetMouseOffset() (2 input parameters) +Function 187: SetMouseOffset() (2 input parameters) Name: SetMouseOffset Return type: void Description: Set mouse offset Param[1]: offsetX (type: int) Param[2]: offsetY (type: int) -Function 186: SetMouseScale() (2 input parameters) +Function 188: SetMouseScale() (2 input parameters) Name: SetMouseScale Return type: void Description: Set mouse scaling Param[1]: scaleX (type: float) Param[2]: scaleY (type: float) -Function 187: GetMouseWheelMove() (0 input parameters) +Function 189: GetMouseWheelMove() (0 input parameters) Name: GetMouseWheelMove Return type: float Description: Get mouse wheel movement for X or Y, whichever is larger No input parameters -Function 188: GetMouseWheelMoveV() (0 input parameters) +Function 190: GetMouseWheelMoveV() (0 input parameters) Name: GetMouseWheelMoveV Return type: Vector2 Description: Get mouse wheel movement for both X and Y No input parameters -Function 189: SetMouseCursor() (1 input parameters) +Function 191: SetMouseCursor() (1 input parameters) Name: SetMouseCursor Return type: void Description: Set mouse cursor Param[1]: cursor (type: int) -Function 190: GetTouchX() (0 input parameters) +Function 192: GetTouchX() (0 input parameters) Name: GetTouchX Return type: int Description: Get touch position X for touch point 0 (relative to screen size) No input parameters -Function 191: GetTouchY() (0 input parameters) +Function 193: GetTouchY() (0 input parameters) Name: GetTouchY Return type: int Description: Get touch position Y for touch point 0 (relative to screen size) No input parameters -Function 192: GetTouchPosition() (1 input parameters) +Function 194: GetTouchPosition() (1 input parameters) Name: GetTouchPosition Return type: Vector2 Description: Get touch position XY for a touch point index (relative to screen size) Param[1]: index (type: int) -Function 193: GetTouchPointId() (1 input parameters) +Function 195: GetTouchPointId() (1 input parameters) Name: GetTouchPointId Return type: int Description: Get touch point identifier for given index Param[1]: index (type: int) -Function 194: GetTouchPointCount() (0 input parameters) +Function 196: GetTouchPointCount() (0 input parameters) Name: GetTouchPointCount Return type: int Description: Get number of touch points No input parameters -Function 195: SetGesturesEnabled() (1 input parameters) +Function 197: SetGesturesEnabled() (1 input parameters) Name: SetGesturesEnabled Return type: void Description: Enable a set of gestures using flags Param[1]: flags (type: unsigned int) -Function 196: IsGestureDetected() (1 input parameters) +Function 198: IsGestureDetected() (1 input parameters) Name: IsGestureDetected Return type: bool Description: Check if a gesture have been detected Param[1]: gesture (type: unsigned int) -Function 197: GetGestureDetected() (0 input parameters) +Function 199: GetGestureDetected() (0 input parameters) Name: GetGestureDetected Return type: int Description: Get latest detected gesture No input parameters -Function 198: GetGestureHoldDuration() (0 input parameters) +Function 200: GetGestureHoldDuration() (0 input parameters) Name: GetGestureHoldDuration Return type: float Description: Get gesture hold time in milliseconds No input parameters -Function 199: GetGestureDragVector() (0 input parameters) +Function 201: GetGestureDragVector() (0 input parameters) Name: GetGestureDragVector Return type: Vector2 Description: Get gesture drag vector No input parameters -Function 200: GetGestureDragAngle() (0 input parameters) +Function 202: GetGestureDragAngle() (0 input parameters) Name: GetGestureDragAngle Return type: float Description: Get gesture drag angle No input parameters -Function 201: GetGesturePinchVector() (0 input parameters) +Function 203: GetGesturePinchVector() (0 input parameters) Name: GetGesturePinchVector Return type: Vector2 Description: Get gesture pinch delta No input parameters -Function 202: GetGesturePinchAngle() (0 input parameters) +Function 204: GetGesturePinchAngle() (0 input parameters) Name: GetGesturePinchAngle Return type: float Description: Get gesture pinch angle No input parameters -Function 203: UpdateCamera() (2 input parameters) +Function 205: UpdateCamera() (2 input parameters) Name: UpdateCamera Return type: void Description: Update camera position for selected mode Param[1]: camera (type: Camera *) Param[2]: mode (type: int) -Function 204: UpdateCameraPro() (4 input parameters) +Function 206: UpdateCameraPro() (4 input parameters) Name: UpdateCameraPro Return type: void Description: Update camera movement/rotation @@ -2083,36 +2095,36 @@ Function 204: UpdateCameraPro() (4 input parameters) Param[2]: movement (type: Vector3) Param[3]: rotation (type: Vector3) Param[4]: zoom (type: float) -Function 205: SetShapesTexture() (2 input parameters) +Function 207: SetShapesTexture() (2 input parameters) Name: SetShapesTexture Return type: void Description: Set texture and rectangle to be used on shapes drawing Param[1]: texture (type: Texture2D) Param[2]: source (type: Rectangle) -Function 206: GetShapesTexture() (0 input parameters) +Function 208: GetShapesTexture() (0 input parameters) Name: GetShapesTexture Return type: Texture2D Description: Get texture that is used for shapes drawing No input parameters -Function 207: GetShapesTextureRectangle() (0 input parameters) +Function 209: GetShapesTextureRectangle() (0 input parameters) Name: GetShapesTextureRectangle Return type: Rectangle Description: Get texture source rectangle that is used for shapes drawing No input parameters -Function 208: DrawPixel() (3 input parameters) +Function 210: DrawPixel() (3 input parameters) Name: DrawPixel Return type: void Description: Draw a pixel using geometry [Can be slow, use with care] Param[1]: posX (type: int) Param[2]: posY (type: int) Param[3]: color (type: Color) -Function 209: DrawPixelV() (2 input parameters) +Function 211: DrawPixelV() (2 input parameters) Name: DrawPixelV Return type: void Description: Draw a pixel using geometry (Vector version) [Can be slow, use with care] Param[1]: position (type: Vector2) Param[2]: color (type: Color) -Function 210: DrawLine() (5 input parameters) +Function 212: DrawLine() (5 input parameters) Name: DrawLine Return type: void Description: Draw a line @@ -2121,14 +2133,14 @@ Function 210: DrawLine() (5 input parameters) Param[3]: endPosX (type: int) Param[4]: endPosY (type: int) Param[5]: color (type: Color) -Function 211: DrawLineV() (3 input parameters) +Function 213: DrawLineV() (3 input parameters) Name: DrawLineV Return type: void Description: Draw a line (using gl lines) Param[1]: startPos (type: Vector2) Param[2]: endPos (type: Vector2) Param[3]: color (type: Color) -Function 212: DrawLineEx() (4 input parameters) +Function 214: DrawLineEx() (4 input parameters) Name: DrawLineEx Return type: void Description: Draw a line (using triangles/quads) @@ -2136,14 +2148,14 @@ Function 212: DrawLineEx() (4 input parameters) Param[2]: endPos (type: Vector2) Param[3]: thick (type: float) Param[4]: color (type: Color) -Function 213: DrawLineStrip() (3 input parameters) +Function 215: DrawLineStrip() (3 input parameters) Name: DrawLineStrip Return type: void Description: Draw lines sequence (using gl lines) Param[1]: points (type: const Vector2 *) Param[2]: pointCount (type: int) Param[3]: color (type: Color) -Function 214: DrawLineBezier() (4 input parameters) +Function 216: DrawLineBezier() (4 input parameters) Name: DrawLineBezier Return type: void Description: Draw line segment cubic-bezier in-out interpolation @@ -2151,7 +2163,7 @@ Function 214: DrawLineBezier() (4 input parameters) Param[2]: endPos (type: Vector2) Param[3]: thick (type: float) Param[4]: color (type: Color) -Function 215: DrawCircle() (4 input parameters) +Function 217: DrawCircle() (4 input parameters) Name: DrawCircle Return type: void Description: Draw a color-filled circle @@ -2159,7 +2171,7 @@ Function 215: DrawCircle() (4 input parameters) Param[2]: centerY (type: int) Param[3]: radius (type: float) Param[4]: color (type: Color) -Function 216: DrawCircleSector() (6 input parameters) +Function 218: DrawCircleSector() (6 input parameters) Name: DrawCircleSector Return type: void Description: Draw a piece of a circle @@ -2169,7 +2181,7 @@ Function 216: DrawCircleSector() (6 input parameters) Param[4]: endAngle (type: float) Param[5]: segments (type: int) Param[6]: color (type: Color) -Function 217: DrawCircleSectorLines() (6 input parameters) +Function 219: DrawCircleSectorLines() (6 input parameters) Name: DrawCircleSectorLines Return type: void Description: Draw circle sector outline @@ -2179,7 +2191,7 @@ Function 217: DrawCircleSectorLines() (6 input parameters) Param[4]: endAngle (type: float) Param[5]: segments (type: int) Param[6]: color (type: Color) -Function 218: DrawCircleGradient() (5 input parameters) +Function 220: DrawCircleGradient() (5 input parameters) Name: DrawCircleGradient Return type: void Description: Draw a gradient-filled circle @@ -2188,14 +2200,14 @@ Function 218: DrawCircleGradient() (5 input parameters) Param[3]: radius (type: float) Param[4]: inner (type: Color) Param[5]: outer (type: Color) -Function 219: DrawCircleV() (3 input parameters) +Function 221: DrawCircleV() (3 input parameters) Name: DrawCircleV Return type: void Description: Draw a color-filled circle (Vector version) Param[1]: center (type: Vector2) Param[2]: radius (type: float) Param[3]: color (type: Color) -Function 220: DrawCircleLines() (4 input parameters) +Function 222: DrawCircleLines() (4 input parameters) Name: DrawCircleLines Return type: void Description: Draw circle outline @@ -2203,14 +2215,14 @@ Function 220: DrawCircleLines() (4 input parameters) Param[2]: centerY (type: int) Param[3]: radius (type: float) Param[4]: color (type: Color) -Function 221: DrawCircleLinesV() (3 input parameters) +Function 223: DrawCircleLinesV() (3 input parameters) Name: DrawCircleLinesV Return type: void Description: Draw circle outline (Vector version) Param[1]: center (type: Vector2) Param[2]: radius (type: float) Param[3]: color (type: Color) -Function 222: DrawEllipse() (5 input parameters) +Function 224: DrawEllipse() (5 input parameters) Name: DrawEllipse Return type: void Description: Draw ellipse @@ -2219,7 +2231,7 @@ Function 222: DrawEllipse() (5 input parameters) Param[3]: radiusH (type: float) Param[4]: radiusV (type: float) Param[5]: color (type: Color) -Function 223: DrawEllipseLines() (5 input parameters) +Function 225: DrawEllipseLines() (5 input parameters) Name: DrawEllipseLines Return type: void Description: Draw ellipse outline @@ -2228,7 +2240,7 @@ Function 223: DrawEllipseLines() (5 input parameters) Param[3]: radiusH (type: float) Param[4]: radiusV (type: float) Param[5]: color (type: Color) -Function 224: DrawRing() (7 input parameters) +Function 226: DrawRing() (7 input parameters) Name: DrawRing Return type: void Description: Draw ring @@ -2239,7 +2251,7 @@ Function 224: DrawRing() (7 input parameters) Param[5]: endAngle (type: float) Param[6]: segments (type: int) Param[7]: color (type: Color) -Function 225: DrawRingLines() (7 input parameters) +Function 227: DrawRingLines() (7 input parameters) Name: DrawRingLines Return type: void Description: Draw ring outline @@ -2250,7 +2262,7 @@ Function 225: DrawRingLines() (7 input parameters) Param[5]: endAngle (type: float) Param[6]: segments (type: int) Param[7]: color (type: Color) -Function 226: DrawRectangle() (5 input parameters) +Function 228: DrawRectangle() (5 input parameters) Name: DrawRectangle Return type: void Description: Draw a color-filled rectangle @@ -2259,20 +2271,20 @@ Function 226: DrawRectangle() (5 input parameters) Param[3]: width (type: int) Param[4]: height (type: int) Param[5]: color (type: Color) -Function 227: DrawRectangleV() (3 input parameters) +Function 229: DrawRectangleV() (3 input parameters) Name: DrawRectangleV Return type: void Description: Draw a color-filled rectangle (Vector version) Param[1]: position (type: Vector2) Param[2]: size (type: Vector2) Param[3]: color (type: Color) -Function 228: DrawRectangleRec() (2 input parameters) +Function 230: DrawRectangleRec() (2 input parameters) Name: DrawRectangleRec Return type: void Description: Draw a color-filled rectangle Param[1]: rec (type: Rectangle) Param[2]: color (type: Color) -Function 229: DrawRectanglePro() (4 input parameters) +Function 231: DrawRectanglePro() (4 input parameters) Name: DrawRectanglePro Return type: void Description: Draw a color-filled rectangle with pro parameters @@ -2280,7 +2292,7 @@ Function 229: DrawRectanglePro() (4 input parameters) Param[2]: origin (type: Vector2) Param[3]: rotation (type: float) Param[4]: color (type: Color) -Function 230: DrawRectangleGradientV() (6 input parameters) +Function 232: DrawRectangleGradientV() (6 input parameters) Name: DrawRectangleGradientV Return type: void Description: Draw a vertical-gradient-filled rectangle @@ -2290,7 +2302,7 @@ Function 230: DrawRectangleGradientV() (6 input parameters) Param[4]: height (type: int) Param[5]: top (type: Color) Param[6]: bottom (type: Color) -Function 231: DrawRectangleGradientH() (6 input parameters) +Function 233: DrawRectangleGradientH() (6 input parameters) Name: DrawRectangleGradientH Return type: void Description: Draw a horizontal-gradient-filled rectangle @@ -2300,7 +2312,7 @@ Function 231: DrawRectangleGradientH() (6 input parameters) Param[4]: height (type: int) Param[5]: left (type: Color) Param[6]: right (type: Color) -Function 232: DrawRectangleGradientEx() (5 input parameters) +Function 234: DrawRectangleGradientEx() (5 input parameters) Name: DrawRectangleGradientEx Return type: void Description: Draw a gradient-filled rectangle with custom vertex colors @@ -2309,7 +2321,7 @@ Function 232: DrawRectangleGradientEx() (5 input parameters) Param[3]: bottomLeft (type: Color) Param[4]: topRight (type: Color) Param[5]: bottomRight (type: Color) -Function 233: DrawRectangleLines() (5 input parameters) +Function 235: DrawRectangleLines() (5 input parameters) Name: DrawRectangleLines Return type: void Description: Draw rectangle outline @@ -2318,14 +2330,14 @@ Function 233: DrawRectangleLines() (5 input parameters) Param[3]: width (type: int) Param[4]: height (type: int) Param[5]: color (type: Color) -Function 234: DrawRectangleLinesEx() (3 input parameters) +Function 236: DrawRectangleLinesEx() (3 input parameters) Name: DrawRectangleLinesEx Return type: void Description: Draw rectangle outline with extended parameters Param[1]: rec (type: Rectangle) Param[2]: lineThick (type: float) Param[3]: color (type: Color) -Function 235: DrawRectangleRounded() (4 input parameters) +Function 237: DrawRectangleRounded() (4 input parameters) Name: DrawRectangleRounded Return type: void Description: Draw rectangle with rounded edges @@ -2333,7 +2345,7 @@ Function 235: DrawRectangleRounded() (4 input parameters) Param[2]: roundness (type: float) Param[3]: segments (type: int) Param[4]: color (type: Color) -Function 236: DrawRectangleRoundedLines() (4 input parameters) +Function 238: DrawRectangleRoundedLines() (4 input parameters) Name: DrawRectangleRoundedLines Return type: void Description: Draw rectangle lines with rounded edges @@ -2341,7 +2353,7 @@ Function 236: DrawRectangleRoundedLines() (4 input parameters) Param[2]: roundness (type: float) Param[3]: segments (type: int) Param[4]: color (type: Color) -Function 237: DrawRectangleRoundedLinesEx() (5 input parameters) +Function 239: DrawRectangleRoundedLinesEx() (5 input parameters) Name: DrawRectangleRoundedLinesEx Return type: void Description: Draw rectangle with rounded edges outline @@ -2350,7 +2362,7 @@ Function 237: DrawRectangleRoundedLinesEx() (5 input parameters) Param[3]: segments (type: int) Param[4]: lineThick (type: float) Param[5]: color (type: Color) -Function 238: DrawTriangle() (4 input parameters) +Function 240: DrawTriangle() (4 input parameters) Name: DrawTriangle Return type: void Description: Draw a color-filled triangle (vertex in counter-clockwise order!) @@ -2358,7 +2370,7 @@ Function 238: DrawTriangle() (4 input parameters) Param[2]: v2 (type: Vector2) Param[3]: v3 (type: Vector2) Param[4]: color (type: Color) -Function 239: DrawTriangleLines() (4 input parameters) +Function 241: DrawTriangleLines() (4 input parameters) Name: DrawTriangleLines Return type: void Description: Draw triangle outline (vertex in counter-clockwise order!) @@ -2366,21 +2378,21 @@ Function 239: DrawTriangleLines() (4 input parameters) Param[2]: v2 (type: Vector2) Param[3]: v3 (type: Vector2) Param[4]: color (type: Color) -Function 240: DrawTriangleFan() (3 input parameters) +Function 242: DrawTriangleFan() (3 input parameters) Name: DrawTriangleFan Return type: void Description: Draw a triangle fan defined by points (first vertex is the center) Param[1]: points (type: const Vector2 *) Param[2]: pointCount (type: int) Param[3]: color (type: Color) -Function 241: DrawTriangleStrip() (3 input parameters) +Function 243: DrawTriangleStrip() (3 input parameters) Name: DrawTriangleStrip Return type: void Description: Draw a triangle strip defined by points Param[1]: points (type: const Vector2 *) Param[2]: pointCount (type: int) Param[3]: color (type: Color) -Function 242: DrawPoly() (5 input parameters) +Function 244: DrawPoly() (5 input parameters) Name: DrawPoly Return type: void Description: Draw a regular polygon (Vector version) @@ -2389,7 +2401,7 @@ Function 242: DrawPoly() (5 input parameters) Param[3]: radius (type: float) Param[4]: rotation (type: float) Param[5]: color (type: Color) -Function 243: DrawPolyLines() (5 input parameters) +Function 245: DrawPolyLines() (5 input parameters) Name: DrawPolyLines Return type: void Description: Draw a polygon outline of n sides @@ -2398,7 +2410,7 @@ Function 243: DrawPolyLines() (5 input parameters) Param[3]: radius (type: float) Param[4]: rotation (type: float) Param[5]: color (type: Color) -Function 244: DrawPolyLinesEx() (6 input parameters) +Function 246: DrawPolyLinesEx() (6 input parameters) Name: DrawPolyLinesEx Return type: void Description: Draw a polygon outline of n sides with extended parameters @@ -2408,7 +2420,7 @@ Function 244: DrawPolyLinesEx() (6 input parameters) Param[4]: rotation (type: float) Param[5]: lineThick (type: float) Param[6]: color (type: Color) -Function 245: DrawSplineLinear() (4 input parameters) +Function 247: DrawSplineLinear() (4 input parameters) Name: DrawSplineLinear Return type: void Description: Draw spline: Linear, minimum 2 points @@ -2416,7 +2428,7 @@ Function 245: DrawSplineLinear() (4 input parameters) Param[2]: pointCount (type: int) Param[3]: thick (type: float) Param[4]: color (type: Color) -Function 246: DrawSplineBasis() (4 input parameters) +Function 248: DrawSplineBasis() (4 input parameters) Name: DrawSplineBasis Return type: void Description: Draw spline: B-Spline, minimum 4 points @@ -2424,7 +2436,7 @@ Function 246: DrawSplineBasis() (4 input parameters) Param[2]: pointCount (type: int) Param[3]: thick (type: float) Param[4]: color (type: Color) -Function 247: DrawSplineCatmullRom() (4 input parameters) +Function 249: DrawSplineCatmullRom() (4 input parameters) Name: DrawSplineCatmullRom Return type: void Description: Draw spline: Catmull-Rom, minimum 4 points @@ -2432,7 +2444,7 @@ Function 247: DrawSplineCatmullRom() (4 input parameters) Param[2]: pointCount (type: int) Param[3]: thick (type: float) Param[4]: color (type: Color) -Function 248: DrawSplineBezierQuadratic() (4 input parameters) +Function 250: DrawSplineBezierQuadratic() (4 input parameters) Name: DrawSplineBezierQuadratic Return type: void Description: Draw spline: Quadratic Bezier, minimum 3 points (1 control point): [p1, c2, p3, c4...] @@ -2440,7 +2452,7 @@ Function 248: DrawSplineBezierQuadratic() (4 input parameters) Param[2]: pointCount (type: int) Param[3]: thick (type: float) Param[4]: color (type: Color) -Function 249: DrawSplineBezierCubic() (4 input parameters) +Function 251: DrawSplineBezierCubic() (4 input parameters) Name: DrawSplineBezierCubic Return type: void Description: Draw spline: Cubic Bezier, minimum 4 points (2 control points): [p1, c2, c3, p4, c5, c6...] @@ -2448,7 +2460,7 @@ Function 249: DrawSplineBezierCubic() (4 input parameters) Param[2]: pointCount (type: int) Param[3]: thick (type: float) Param[4]: color (type: Color) -Function 250: DrawSplineSegmentLinear() (4 input parameters) +Function 252: DrawSplineSegmentLinear() (4 input parameters) Name: DrawSplineSegmentLinear Return type: void Description: Draw spline segment: Linear, 2 points @@ -2456,7 +2468,7 @@ Function 250: DrawSplineSegmentLinear() (4 input parameters) Param[2]: p2 (type: Vector2) Param[3]: thick (type: float) Param[4]: color (type: Color) -Function 251: DrawSplineSegmentBasis() (6 input parameters) +Function 253: DrawSplineSegmentBasis() (6 input parameters) Name: DrawSplineSegmentBasis Return type: void Description: Draw spline segment: B-Spline, 4 points @@ -2466,7 +2478,7 @@ Function 251: DrawSplineSegmentBasis() (6 input parameters) Param[4]: p4 (type: Vector2) Param[5]: thick (type: float) Param[6]: color (type: Color) -Function 252: DrawSplineSegmentCatmullRom() (6 input parameters) +Function 254: DrawSplineSegmentCatmullRom() (6 input parameters) Name: DrawSplineSegmentCatmullRom Return type: void Description: Draw spline segment: Catmull-Rom, 4 points @@ -2476,7 +2488,7 @@ Function 252: DrawSplineSegmentCatmullRom() (6 input parameters) Param[4]: p4 (type: Vector2) Param[5]: thick (type: float) Param[6]: color (type: Color) -Function 253: DrawSplineSegmentBezierQuadratic() (5 input parameters) +Function 255: DrawSplineSegmentBezierQuadratic() (5 input parameters) Name: DrawSplineSegmentBezierQuadratic Return type: void Description: Draw spline segment: Quadratic Bezier, 2 points, 1 control point @@ -2485,7 +2497,7 @@ Function 253: DrawSplineSegmentBezierQuadratic() (5 input parameters) Param[3]: p3 (type: Vector2) Param[4]: thick (type: float) Param[5]: color (type: Color) -Function 254: DrawSplineSegmentBezierCubic() (6 input parameters) +Function 256: DrawSplineSegmentBezierCubic() (6 input parameters) Name: DrawSplineSegmentBezierCubic Return type: void Description: Draw spline segment: Cubic Bezier, 2 points, 2 control points @@ -2495,14 +2507,14 @@ Function 254: DrawSplineSegmentBezierCubic() (6 input parameters) Param[4]: p4 (type: Vector2) Param[5]: thick (type: float) Param[6]: color (type: Color) -Function 255: GetSplinePointLinear() (3 input parameters) +Function 257: GetSplinePointLinear() (3 input parameters) Name: GetSplinePointLinear Return type: Vector2 Description: Get (evaluate) spline point: Linear Param[1]: startPos (type: Vector2) Param[2]: endPos (type: Vector2) Param[3]: t (type: float) -Function 256: GetSplinePointBasis() (5 input parameters) +Function 258: GetSplinePointBasis() (5 input parameters) Name: GetSplinePointBasis Return type: Vector2 Description: Get (evaluate) spline point: B-Spline @@ -2511,7 +2523,7 @@ Function 256: GetSplinePointBasis() (5 input parameters) Param[3]: p3 (type: Vector2) Param[4]: p4 (type: Vector2) Param[5]: t (type: float) -Function 257: GetSplinePointCatmullRom() (5 input parameters) +Function 259: GetSplinePointCatmullRom() (5 input parameters) Name: GetSplinePointCatmullRom Return type: Vector2 Description: Get (evaluate) spline point: Catmull-Rom @@ -2520,7 +2532,7 @@ Function 257: GetSplinePointCatmullRom() (5 input parameters) Param[3]: p3 (type: Vector2) Param[4]: p4 (type: Vector2) Param[5]: t (type: float) -Function 258: GetSplinePointBezierQuad() (4 input parameters) +Function 260: GetSplinePointBezierQuad() (4 input parameters) Name: GetSplinePointBezierQuad Return type: Vector2 Description: Get (evaluate) spline point: Quadratic Bezier @@ -2528,7 +2540,7 @@ Function 258: GetSplinePointBezierQuad() (4 input parameters) Param[2]: c2 (type: Vector2) Param[3]: p3 (type: Vector2) Param[4]: t (type: float) -Function 259: GetSplinePointBezierCubic() (5 input parameters) +Function 261: GetSplinePointBezierCubic() (5 input parameters) Name: GetSplinePointBezierCubic Return type: Vector2 Description: Get (evaluate) spline point: Cubic Bezier @@ -2537,13 +2549,13 @@ Function 259: GetSplinePointBezierCubic() (5 input parameters) Param[3]: c3 (type: Vector2) Param[4]: p4 (type: Vector2) Param[5]: t (type: float) -Function 260: CheckCollisionRecs() (2 input parameters) +Function 262: CheckCollisionRecs() (2 input parameters) Name: CheckCollisionRecs Return type: bool Description: Check collision between two rectangles Param[1]: rec1 (type: Rectangle) Param[2]: rec2 (type: Rectangle) -Function 261: CheckCollisionCircles() (4 input parameters) +Function 263: CheckCollisionCircles() (4 input parameters) Name: CheckCollisionCircles Return type: bool Description: Check collision between two circles @@ -2551,27 +2563,27 @@ Function 261: CheckCollisionCircles() (4 input parameters) Param[2]: radius1 (type: float) Param[3]: center2 (type: Vector2) Param[4]: radius2 (type: float) -Function 262: CheckCollisionCircleRec() (3 input parameters) +Function 264: CheckCollisionCircleRec() (3 input parameters) Name: CheckCollisionCircleRec Return type: bool Description: Check collision between circle and rectangle Param[1]: center (type: Vector2) Param[2]: radius (type: float) Param[3]: rec (type: Rectangle) -Function 263: CheckCollisionPointRec() (2 input parameters) +Function 265: CheckCollisionPointRec() (2 input parameters) Name: CheckCollisionPointRec Return type: bool Description: Check if point is inside rectangle Param[1]: point (type: Vector2) Param[2]: rec (type: Rectangle) -Function 264: CheckCollisionPointCircle() (3 input parameters) +Function 266: CheckCollisionPointCircle() (3 input parameters) Name: CheckCollisionPointCircle Return type: bool Description: Check if point is inside circle Param[1]: point (type: Vector2) Param[2]: center (type: Vector2) Param[3]: radius (type: float) -Function 265: CheckCollisionPointTriangle() (4 input parameters) +Function 267: CheckCollisionPointTriangle() (4 input parameters) Name: CheckCollisionPointTriangle Return type: bool Description: Check if point is inside a triangle @@ -2579,14 +2591,14 @@ Function 265: CheckCollisionPointTriangle() (4 input parameters) Param[2]: p1 (type: Vector2) Param[3]: p2 (type: Vector2) Param[4]: p3 (type: Vector2) -Function 266: CheckCollisionPointPoly() (3 input parameters) +Function 268: CheckCollisionPointPoly() (3 input parameters) Name: CheckCollisionPointPoly Return type: bool Description: Check if point is within a polygon described by array of vertices Param[1]: point (type: Vector2) Param[2]: points (type: const Vector2 *) Param[3]: pointCount (type: int) -Function 267: CheckCollisionLines() (5 input parameters) +Function 269: CheckCollisionLines() (5 input parameters) Name: CheckCollisionLines Return type: bool Description: Check the collision between two lines defined by two points each, returns collision point by reference @@ -2595,7 +2607,7 @@ Function 267: CheckCollisionLines() (5 input parameters) Param[3]: startPos2 (type: Vector2) Param[4]: endPos2 (type: Vector2) Param[5]: collisionPoint (type: Vector2 *) -Function 268: CheckCollisionPointLine() (4 input parameters) +Function 270: CheckCollisionPointLine() (4 input parameters) Name: CheckCollisionPointLine Return type: bool Description: Check if point belongs to line created between two points [p1] and [p2] with defined margin in pixels [threshold] @@ -2603,7 +2615,7 @@ Function 268: CheckCollisionPointLine() (4 input parameters) Param[2]: p1 (type: Vector2) Param[3]: p2 (type: Vector2) Param[4]: threshold (type: int) -Function 269: CheckCollisionCircleLine() (4 input parameters) +Function 271: CheckCollisionCircleLine() (4 input parameters) Name: CheckCollisionCircleLine Return type: bool Description: Check if circle collides with a line created betweeen two points [p1] and [p2] @@ -2611,18 +2623,18 @@ Function 269: CheckCollisionCircleLine() (4 input parameters) Param[2]: radius (type: float) Param[3]: p1 (type: Vector2) Param[4]: p2 (type: Vector2) -Function 270: GetCollisionRec() (2 input parameters) +Function 272: GetCollisionRec() (2 input parameters) Name: GetCollisionRec Return type: Rectangle Description: Get collision rectangle for two rectangles collision Param[1]: rec1 (type: Rectangle) Param[2]: rec2 (type: Rectangle) -Function 271: LoadImage() (1 input parameters) +Function 273: LoadImage() (1 input parameters) Name: LoadImage Return type: Image Description: Load image from file into CPU memory (RAM) Param[1]: fileName (type: const char *) -Function 272: LoadImageRaw() (5 input parameters) +Function 274: LoadImageRaw() (5 input parameters) Name: LoadImageRaw Return type: Image Description: Load image from RAW file data @@ -2631,13 +2643,13 @@ Function 272: LoadImageRaw() (5 input parameters) Param[3]: height (type: int) Param[4]: format (type: int) Param[5]: headerSize (type: int) -Function 273: LoadImageAnim() (2 input parameters) +Function 275: LoadImageAnim() (2 input parameters) Name: LoadImageAnim Return type: Image Description: Load image sequence from file (frames appended to image.data) Param[1]: fileName (type: const char *) Param[2]: frames (type: int *) -Function 274: LoadImageAnimFromMemory() (4 input parameters) +Function 276: LoadImageAnimFromMemory() (4 input parameters) Name: LoadImageAnimFromMemory Return type: Image Description: Load image sequence from memory buffer @@ -2645,60 +2657,60 @@ Function 274: LoadImageAnimFromMemory() (4 input parameters) Param[2]: fileData (type: const unsigned char *) Param[3]: dataSize (type: int) Param[4]: frames (type: int *) -Function 275: LoadImageFromMemory() (3 input parameters) +Function 277: LoadImageFromMemory() (3 input parameters) Name: LoadImageFromMemory Return type: Image Description: Load image from memory buffer, fileType refers to extension: i.e. '.png' Param[1]: fileType (type: const char *) Param[2]: fileData (type: const unsigned char *) Param[3]: dataSize (type: int) -Function 276: LoadImageFromTexture() (1 input parameters) +Function 278: LoadImageFromTexture() (1 input parameters) Name: LoadImageFromTexture Return type: Image Description: Load image from GPU texture data Param[1]: texture (type: Texture2D) -Function 277: LoadImageFromScreen() (0 input parameters) +Function 279: LoadImageFromScreen() (0 input parameters) Name: LoadImageFromScreen Return type: Image Description: Load image from screen buffer and (screenshot) No input parameters -Function 278: IsImageReady() (1 input parameters) +Function 280: IsImageReady() (1 input parameters) Name: IsImageReady Return type: bool Description: Check if an image is ready Param[1]: image (type: Image) -Function 279: UnloadImage() (1 input parameters) +Function 281: UnloadImage() (1 input parameters) Name: UnloadImage Return type: void Description: Unload image from CPU memory (RAM) Param[1]: image (type: Image) -Function 280: ExportImage() (2 input parameters) +Function 282: ExportImage() (2 input parameters) Name: ExportImage Return type: bool Description: Export image data to file, returns true on success Param[1]: image (type: Image) Param[2]: fileName (type: const char *) -Function 281: ExportImageToMemory() (3 input parameters) +Function 283: ExportImageToMemory() (3 input parameters) Name: ExportImageToMemory Return type: unsigned char * Description: Export image to memory buffer Param[1]: image (type: Image) Param[2]: fileType (type: const char *) Param[3]: fileSize (type: int *) -Function 282: ExportImageAsCode() (2 input parameters) +Function 284: ExportImageAsCode() (2 input parameters) Name: ExportImageAsCode Return type: bool Description: Export image as code file defining an array of bytes, returns true on success Param[1]: image (type: Image) Param[2]: fileName (type: const char *) -Function 283: GenImageColor() (3 input parameters) +Function 285: GenImageColor() (3 input parameters) Name: GenImageColor Return type: Image Description: Generate image: plain color Param[1]: width (type: int) Param[2]: height (type: int) Param[3]: color (type: Color) -Function 284: GenImageGradientLinear() (5 input parameters) +Function 286: GenImageGradientLinear() (5 input parameters) Name: GenImageGradientLinear Return type: Image Description: Generate image: linear gradient, direction in degrees [0..360], 0=Vertical gradient @@ -2707,7 +2719,7 @@ Function 284: GenImageGradientLinear() (5 input parameters) Param[3]: direction (type: int) Param[4]: start (type: Color) Param[5]: end (type: Color) -Function 285: GenImageGradientRadial() (5 input parameters) +Function 287: GenImageGradientRadial() (5 input parameters) Name: GenImageGradientRadial Return type: Image Description: Generate image: radial gradient @@ -2716,7 +2728,7 @@ Function 285: GenImageGradientRadial() (5 input parameters) Param[3]: density (type: float) Param[4]: inner (type: Color) Param[5]: outer (type: Color) -Function 286: GenImageGradientSquare() (5 input parameters) +Function 288: GenImageGradientSquare() (5 input parameters) Name: GenImageGradientSquare Return type: Image Description: Generate image: square gradient @@ -2725,7 +2737,7 @@ Function 286: GenImageGradientSquare() (5 input parameters) Param[3]: density (type: float) Param[4]: inner (type: Color) Param[5]: outer (type: Color) -Function 287: GenImageChecked() (6 input parameters) +Function 289: GenImageChecked() (6 input parameters) Name: GenImageChecked Return type: Image Description: Generate image: checked @@ -2735,14 +2747,14 @@ Function 287: GenImageChecked() (6 input parameters) Param[4]: checksY (type: int) Param[5]: col1 (type: Color) Param[6]: col2 (type: Color) -Function 288: GenImageWhiteNoise() (3 input parameters) +Function 290: GenImageWhiteNoise() (3 input parameters) Name: GenImageWhiteNoise Return type: Image Description: Generate image: white noise Param[1]: width (type: int) Param[2]: height (type: int) Param[3]: factor (type: float) -Function 289: GenImagePerlinNoise() (5 input parameters) +Function 291: GenImagePerlinNoise() (5 input parameters) Name: GenImagePerlinNoise Return type: Image Description: Generate image: perlin noise @@ -2751,45 +2763,45 @@ Function 289: GenImagePerlinNoise() (5 input parameters) Param[3]: offsetX (type: int) Param[4]: offsetY (type: int) Param[5]: scale (type: float) -Function 290: GenImageCellular() (3 input parameters) +Function 292: GenImageCellular() (3 input parameters) Name: GenImageCellular Return type: Image Description: Generate image: cellular algorithm, bigger tileSize means bigger cells Param[1]: width (type: int) Param[2]: height (type: int) Param[3]: tileSize (type: int) -Function 291: GenImageText() (3 input parameters) +Function 293: GenImageText() (3 input parameters) Name: GenImageText Return type: Image Description: Generate image: grayscale image from text data Param[1]: width (type: int) Param[2]: height (type: int) Param[3]: text (type: const char *) -Function 292: ImageCopy() (1 input parameters) +Function 294: ImageCopy() (1 input parameters) Name: ImageCopy Return type: Image Description: Create an image duplicate (useful for transformations) Param[1]: image (type: Image) -Function 293: ImageFromImage() (2 input parameters) +Function 295: ImageFromImage() (2 input parameters) Name: ImageFromImage Return type: Image Description: Create an image from another image piece Param[1]: image (type: Image) Param[2]: rec (type: Rectangle) -Function 294: ImageFromChannel() (2 input parameters) +Function 296: ImageFromChannel() (2 input parameters) Name: ImageFromChannel Return type: Image Description: Create an image from a selected channel of another image (GRAYSCALE) Param[1]: image (type: Image) Param[2]: selectedChannel (type: int) -Function 295: ImageText() (3 input parameters) +Function 297: ImageText() (3 input parameters) Name: ImageText Return type: Image Description: Create an image from text (default font) Param[1]: text (type: const char *) Param[2]: fontSize (type: int) Param[3]: color (type: Color) -Function 296: ImageTextEx() (5 input parameters) +Function 298: ImageTextEx() (5 input parameters) Name: ImageTextEx Return type: Image Description: Create an image from text (custom sprite font) @@ -2798,76 +2810,76 @@ Function 296: ImageTextEx() (5 input parameters) Param[3]: fontSize (type: float) Param[4]: spacing (type: float) Param[5]: tint (type: Color) -Function 297: ImageFormat() (2 input parameters) +Function 299: ImageFormat() (2 input parameters) Name: ImageFormat Return type: void Description: Convert image data to desired format Param[1]: image (type: Image *) Param[2]: newFormat (type: int) -Function 298: ImageToPOT() (2 input parameters) +Function 300: ImageToPOT() (2 input parameters) Name: ImageToPOT Return type: void Description: Convert image to POT (power-of-two) Param[1]: image (type: Image *) Param[2]: fill (type: Color) -Function 299: ImageCrop() (2 input parameters) +Function 301: ImageCrop() (2 input parameters) Name: ImageCrop Return type: void Description: Crop an image to a defined rectangle Param[1]: image (type: Image *) Param[2]: crop (type: Rectangle) -Function 300: ImageAlphaCrop() (2 input parameters) +Function 302: ImageAlphaCrop() (2 input parameters) Name: ImageAlphaCrop Return type: void Description: Crop image depending on alpha value Param[1]: image (type: Image *) Param[2]: threshold (type: float) -Function 301: ImageAlphaClear() (3 input parameters) +Function 303: ImageAlphaClear() (3 input parameters) Name: ImageAlphaClear Return type: void Description: Clear alpha channel to desired color Param[1]: image (type: Image *) Param[2]: color (type: Color) Param[3]: threshold (type: float) -Function 302: ImageAlphaMask() (2 input parameters) +Function 304: ImageAlphaMask() (2 input parameters) Name: ImageAlphaMask Return type: void Description: Apply alpha mask to image Param[1]: image (type: Image *) Param[2]: alphaMask (type: Image) -Function 303: ImageAlphaPremultiply() (1 input parameters) +Function 305: ImageAlphaPremultiply() (1 input parameters) Name: ImageAlphaPremultiply Return type: void Description: Premultiply alpha channel Param[1]: image (type: Image *) -Function 304: ImageBlurGaussian() (2 input parameters) +Function 306: ImageBlurGaussian() (2 input parameters) Name: ImageBlurGaussian Return type: void Description: Apply Gaussian blur using a box blur approximation Param[1]: image (type: Image *) Param[2]: blurSize (type: int) -Function 305: ImageKernelConvolution() (3 input parameters) +Function 307: ImageKernelConvolution() (3 input parameters) Name: ImageKernelConvolution Return type: void Description: Apply custom square convolution kernel to image Param[1]: image (type: Image *) Param[2]: kernel (type: const float *) Param[3]: kernelSize (type: int) -Function 306: ImageResize() (3 input parameters) +Function 308: ImageResize() (3 input parameters) Name: ImageResize Return type: void Description: Resize image (Bicubic scaling algorithm) Param[1]: image (type: Image *) Param[2]: newWidth (type: int) Param[3]: newHeight (type: int) -Function 307: ImageResizeNN() (3 input parameters) +Function 309: ImageResizeNN() (3 input parameters) Name: ImageResizeNN Return type: void Description: Resize image (Nearest-Neighbor scaling algorithm) Param[1]: image (type: Image *) Param[2]: newWidth (type: int) Param[3]: newHeight (type: int) -Function 308: ImageResizeCanvas() (6 input parameters) +Function 310: ImageResizeCanvas() (6 input parameters) Name: ImageResizeCanvas Return type: void Description: Resize canvas and fill with color @@ -2877,12 +2889,12 @@ Function 308: ImageResizeCanvas() (6 input parameters) Param[4]: offsetX (type: int) Param[5]: offsetY (type: int) Param[6]: fill (type: Color) -Function 309: ImageMipmaps() (1 input parameters) +Function 311: ImageMipmaps() (1 input parameters) Name: ImageMipmaps Return type: void Description: Compute all mipmap levels for a provided image Param[1]: image (type: Image *) -Function 310: ImageDither() (5 input parameters) +Function 312: ImageDither() (5 input parameters) Name: ImageDither Return type: void Description: Dither image data to 16bpp or lower (Floyd-Steinberg dithering) @@ -2891,109 +2903,109 @@ Function 310: ImageDither() (5 input parameters) Param[3]: gBpp (type: int) Param[4]: bBpp (type: int) Param[5]: aBpp (type: int) -Function 311: ImageFlipVertical() (1 input parameters) +Function 313: ImageFlipVertical() (1 input parameters) Name: ImageFlipVertical Return type: void Description: Flip image vertically Param[1]: image (type: Image *) -Function 312: ImageFlipHorizontal() (1 input parameters) +Function 314: ImageFlipHorizontal() (1 input parameters) Name: ImageFlipHorizontal Return type: void Description: Flip image horizontally Param[1]: image (type: Image *) -Function 313: ImageRotate() (2 input parameters) +Function 315: ImageRotate() (2 input parameters) Name: ImageRotate Return type: void Description: Rotate image by input angle in degrees (-359 to 359) Param[1]: image (type: Image *) Param[2]: degrees (type: int) -Function 314: ImageRotateCW() (1 input parameters) +Function 316: ImageRotateCW() (1 input parameters) Name: ImageRotateCW Return type: void Description: Rotate image clockwise 90deg Param[1]: image (type: Image *) -Function 315: ImageRotateCCW() (1 input parameters) +Function 317: ImageRotateCCW() (1 input parameters) Name: ImageRotateCCW Return type: void Description: Rotate image counter-clockwise 90deg Param[1]: image (type: Image *) -Function 316: ImageColorTint() (2 input parameters) +Function 318: ImageColorTint() (2 input parameters) Name: ImageColorTint Return type: void Description: Modify image color: tint Param[1]: image (type: Image *) Param[2]: color (type: Color) -Function 317: ImageColorInvert() (1 input parameters) +Function 319: ImageColorInvert() (1 input parameters) Name: ImageColorInvert Return type: void Description: Modify image color: invert Param[1]: image (type: Image *) -Function 318: ImageColorGrayscale() (1 input parameters) +Function 320: ImageColorGrayscale() (1 input parameters) Name: ImageColorGrayscale Return type: void Description: Modify image color: grayscale Param[1]: image (type: Image *) -Function 319: ImageColorContrast() (2 input parameters) +Function 321: ImageColorContrast() (2 input parameters) Name: ImageColorContrast Return type: void Description: Modify image color: contrast (-100 to 100) Param[1]: image (type: Image *) Param[2]: contrast (type: float) -Function 320: ImageColorBrightness() (2 input parameters) +Function 322: ImageColorBrightness() (2 input parameters) Name: ImageColorBrightness Return type: void Description: Modify image color: brightness (-255 to 255) Param[1]: image (type: Image *) Param[2]: brightness (type: int) -Function 321: ImageColorReplace() (3 input parameters) +Function 323: ImageColorReplace() (3 input parameters) Name: ImageColorReplace Return type: void Description: Modify image color: replace color Param[1]: image (type: Image *) Param[2]: color (type: Color) Param[3]: replace (type: Color) -Function 322: LoadImageColors() (1 input parameters) +Function 324: LoadImageColors() (1 input parameters) Name: LoadImageColors Return type: Color * Description: Load color data from image as a Color array (RGBA - 32bit) Param[1]: image (type: Image) -Function 323: LoadImagePalette() (3 input parameters) +Function 325: LoadImagePalette() (3 input parameters) Name: LoadImagePalette Return type: Color * Description: Load colors palette from image as a Color array (RGBA - 32bit) Param[1]: image (type: Image) Param[2]: maxPaletteSize (type: int) Param[3]: colorCount (type: int *) -Function 324: UnloadImageColors() (1 input parameters) +Function 326: UnloadImageColors() (1 input parameters) Name: UnloadImageColors Return type: void Description: Unload color data loaded with LoadImageColors() Param[1]: colors (type: Color *) -Function 325: UnloadImagePalette() (1 input parameters) +Function 327: UnloadImagePalette() (1 input parameters) Name: UnloadImagePalette Return type: void Description: Unload colors palette loaded with LoadImagePalette() Param[1]: colors (type: Color *) -Function 326: GetImageAlphaBorder() (2 input parameters) +Function 328: GetImageAlphaBorder() (2 input parameters) Name: GetImageAlphaBorder Return type: Rectangle Description: Get image alpha border rectangle Param[1]: image (type: Image) Param[2]: threshold (type: float) -Function 327: GetImageColor() (3 input parameters) +Function 329: GetImageColor() (3 input parameters) Name: GetImageColor Return type: Color Description: Get image pixel color at (x, y) position Param[1]: image (type: Image) Param[2]: x (type: int) Param[3]: y (type: int) -Function 328: ImageClearBackground() (2 input parameters) +Function 330: ImageClearBackground() (2 input parameters) Name: ImageClearBackground Return type: void Description: Clear image background with given color Param[1]: dst (type: Image *) Param[2]: color (type: Color) -Function 329: ImageDrawPixel() (4 input parameters) +Function 331: ImageDrawPixel() (4 input parameters) Name: ImageDrawPixel Return type: void Description: Draw pixel within an image @@ -3001,14 +3013,14 @@ Function 329: ImageDrawPixel() (4 input parameters) Param[2]: posX (type: int) Param[3]: posY (type: int) Param[4]: color (type: Color) -Function 330: ImageDrawPixelV() (3 input parameters) +Function 332: ImageDrawPixelV() (3 input parameters) Name: ImageDrawPixelV Return type: void Description: Draw pixel within an image (Vector version) Param[1]: dst (type: Image *) Param[2]: position (type: Vector2) Param[3]: color (type: Color) -Function 331: ImageDrawLine() (6 input parameters) +Function 333: ImageDrawLine() (6 input parameters) Name: ImageDrawLine Return type: void Description: Draw line within an image @@ -3018,7 +3030,7 @@ Function 331: ImageDrawLine() (6 input parameters) Param[4]: endPosX (type: int) Param[5]: endPosY (type: int) Param[6]: color (type: Color) -Function 332: ImageDrawLineV() (4 input parameters) +Function 334: ImageDrawLineV() (4 input parameters) Name: ImageDrawLineV Return type: void Description: Draw line within an image (Vector version) @@ -3026,7 +3038,7 @@ Function 332: ImageDrawLineV() (4 input parameters) Param[2]: start (type: Vector2) Param[3]: end (type: Vector2) Param[4]: color (type: Color) -Function 333: ImageDrawLineEx() (5 input parameters) +Function 335: ImageDrawLineEx() (5 input parameters) Name: ImageDrawLineEx Return type: void Description: Draw a line defining thickness within an image @@ -3035,7 +3047,7 @@ Function 333: ImageDrawLineEx() (5 input parameters) Param[3]: end (type: Vector2) Param[4]: thick (type: int) Param[5]: color (type: Color) -Function 334: ImageDrawCircle() (5 input parameters) +Function 336: ImageDrawCircle() (5 input parameters) Name: ImageDrawCircle Return type: void Description: Draw a filled circle within an image @@ -3044,7 +3056,7 @@ Function 334: ImageDrawCircle() (5 input parameters) Param[3]: centerY (type: int) Param[4]: radius (type: int) Param[5]: color (type: Color) -Function 335: ImageDrawCircleV() (4 input parameters) +Function 337: ImageDrawCircleV() (4 input parameters) Name: ImageDrawCircleV Return type: void Description: Draw a filled circle within an image (Vector version) @@ -3052,7 +3064,7 @@ Function 335: ImageDrawCircleV() (4 input parameters) Param[2]: center (type: Vector2) Param[3]: radius (type: int) Param[4]: color (type: Color) -Function 336: ImageDrawCircleLines() (5 input parameters) +Function 338: ImageDrawCircleLines() (5 input parameters) Name: ImageDrawCircleLines Return type: void Description: Draw circle outline within an image @@ -3061,7 +3073,7 @@ Function 336: ImageDrawCircleLines() (5 input parameters) Param[3]: centerY (type: int) Param[4]: radius (type: int) Param[5]: color (type: Color) -Function 337: ImageDrawCircleLinesV() (4 input parameters) +Function 339: ImageDrawCircleLinesV() (4 input parameters) Name: ImageDrawCircleLinesV Return type: void Description: Draw circle outline within an image (Vector version) @@ -3069,7 +3081,7 @@ Function 337: ImageDrawCircleLinesV() (4 input parameters) Param[2]: center (type: Vector2) Param[3]: radius (type: int) Param[4]: color (type: Color) -Function 338: ImageDrawRectangle() (6 input parameters) +Function 340: ImageDrawRectangle() (6 input parameters) Name: ImageDrawRectangle Return type: void Description: Draw rectangle within an image @@ -3079,7 +3091,7 @@ Function 338: ImageDrawRectangle() (6 input parameters) Param[4]: width (type: int) Param[5]: height (type: int) Param[6]: color (type: Color) -Function 339: ImageDrawRectangleV() (4 input parameters) +Function 341: ImageDrawRectangleV() (4 input parameters) Name: ImageDrawRectangleV Return type: void Description: Draw rectangle within an image (Vector version) @@ -3087,14 +3099,14 @@ Function 339: ImageDrawRectangleV() (4 input parameters) Param[2]: position (type: Vector2) Param[3]: size (type: Vector2) Param[4]: color (type: Color) -Function 340: ImageDrawRectangleRec() (3 input parameters) +Function 342: ImageDrawRectangleRec() (3 input parameters) Name: ImageDrawRectangleRec Return type: void Description: Draw rectangle within an image Param[1]: dst (type: Image *) Param[2]: rec (type: Rectangle) Param[3]: color (type: Color) -Function 341: ImageDrawRectangleLines() (4 input parameters) +Function 343: ImageDrawRectangleLines() (4 input parameters) Name: ImageDrawRectangleLines Return type: void Description: Draw rectangle lines within an image @@ -3102,7 +3114,7 @@ Function 341: ImageDrawRectangleLines() (4 input parameters) Param[2]: rec (type: Rectangle) Param[3]: thick (type: int) Param[4]: color (type: Color) -Function 342: ImageDrawTriangle() (5 input parameters) +Function 344: ImageDrawTriangle() (5 input parameters) Name: ImageDrawTriangle Return type: void Description: Draw triangle within an image @@ -3111,7 +3123,7 @@ Function 342: ImageDrawTriangle() (5 input parameters) Param[3]: v2 (type: Vector2) Param[4]: v3 (type: Vector2) Param[5]: color (type: Color) -Function 343: ImageDrawTriangleEx() (7 input parameters) +Function 345: ImageDrawTriangleEx() (7 input parameters) Name: ImageDrawTriangleEx Return type: void Description: Draw triangle with interpolated colors within an image @@ -3122,7 +3134,7 @@ Function 343: ImageDrawTriangleEx() (7 input parameters) Param[5]: c1 (type: Color) Param[6]: c2 (type: Color) Param[7]: c3 (type: Color) -Function 344: ImageDrawTriangleLines() (5 input parameters) +Function 346: ImageDrawTriangleLines() (5 input parameters) Name: ImageDrawTriangleLines Return type: void Description: Draw triangle outline within an image @@ -3131,7 +3143,7 @@ Function 344: ImageDrawTriangleLines() (5 input parameters) Param[3]: v2 (type: Vector2) Param[4]: v3 (type: Vector2) Param[5]: color (type: Color) -Function 345: ImageDrawTriangleFan() (4 input parameters) +Function 347: ImageDrawTriangleFan() (4 input parameters) Name: ImageDrawTriangleFan Return type: void Description: Draw a triangle fan defined by points within an image (first vertex is the center) @@ -3139,7 +3151,7 @@ Function 345: ImageDrawTriangleFan() (4 input parameters) Param[2]: points (type: Vector2 *) Param[3]: pointCount (type: int) Param[4]: color (type: Color) -Function 346: ImageDrawTriangleStrip() (4 input parameters) +Function 348: ImageDrawTriangleStrip() (4 input parameters) Name: ImageDrawTriangleStrip Return type: void Description: Draw a triangle strip defined by points within an image @@ -3147,7 +3159,7 @@ Function 346: ImageDrawTriangleStrip() (4 input parameters) Param[2]: points (type: Vector2 *) Param[3]: pointCount (type: int) Param[4]: color (type: Color) -Function 347: ImageDraw() (5 input parameters) +Function 349: ImageDraw() (5 input parameters) Name: ImageDraw Return type: void Description: Draw a source image within a destination image (tint applied to source) @@ -3156,7 +3168,7 @@ Function 347: ImageDraw() (5 input parameters) Param[3]: srcRec (type: Rectangle) Param[4]: dstRec (type: Rectangle) Param[5]: tint (type: Color) -Function 348: ImageDrawText() (6 input parameters) +Function 350: ImageDrawText() (6 input parameters) Name: ImageDrawText Return type: void Description: Draw text (using default font) within an image (destination) @@ -3166,7 +3178,7 @@ Function 348: ImageDrawText() (6 input parameters) Param[4]: posY (type: int) Param[5]: fontSize (type: int) Param[6]: color (type: Color) -Function 349: ImageDrawTextEx() (7 input parameters) +Function 351: ImageDrawTextEx() (7 input parameters) Name: ImageDrawTextEx Return type: void Description: Draw text (custom sprite font) within an image (destination) @@ -3177,79 +3189,79 @@ Function 349: ImageDrawTextEx() (7 input parameters) Param[5]: fontSize (type: float) Param[6]: spacing (type: float) Param[7]: tint (type: Color) -Function 350: LoadTexture() (1 input parameters) +Function 352: LoadTexture() (1 input parameters) Name: LoadTexture Return type: Texture2D Description: Load texture from file into GPU memory (VRAM) Param[1]: fileName (type: const char *) -Function 351: LoadTextureFromImage() (1 input parameters) +Function 353: LoadTextureFromImage() (1 input parameters) Name: LoadTextureFromImage Return type: Texture2D Description: Load texture from image data Param[1]: image (type: Image) -Function 352: LoadTextureCubemap() (2 input parameters) +Function 354: LoadTextureCubemap() (2 input parameters) Name: LoadTextureCubemap Return type: TextureCubemap Description: Load cubemap from image, multiple image cubemap layouts supported Param[1]: image (type: Image) Param[2]: layout (type: int) -Function 353: LoadRenderTexture() (2 input parameters) +Function 355: LoadRenderTexture() (2 input parameters) Name: LoadRenderTexture Return type: RenderTexture2D Description: Load texture for rendering (framebuffer) Param[1]: width (type: int) Param[2]: height (type: int) -Function 354: IsTextureReady() (1 input parameters) +Function 356: IsTextureReady() (1 input parameters) Name: IsTextureReady Return type: bool Description: Check if a texture is ready Param[1]: texture (type: Texture2D) -Function 355: UnloadTexture() (1 input parameters) +Function 357: UnloadTexture() (1 input parameters) Name: UnloadTexture Return type: void Description: Unload texture from GPU memory (VRAM) Param[1]: texture (type: Texture2D) -Function 356: IsRenderTextureReady() (1 input parameters) +Function 358: IsRenderTextureReady() (1 input parameters) Name: IsRenderTextureReady Return type: bool Description: Check if a render texture is ready Param[1]: target (type: RenderTexture2D) -Function 357: UnloadRenderTexture() (1 input parameters) +Function 359: UnloadRenderTexture() (1 input parameters) Name: UnloadRenderTexture Return type: void Description: Unload render texture from GPU memory (VRAM) Param[1]: target (type: RenderTexture2D) -Function 358: UpdateTexture() (2 input parameters) +Function 360: UpdateTexture() (2 input parameters) Name: UpdateTexture Return type: void Description: Update GPU texture with new data Param[1]: texture (type: Texture2D) Param[2]: pixels (type: const void *) -Function 359: UpdateTextureRec() (3 input parameters) +Function 361: UpdateTextureRec() (3 input parameters) Name: UpdateTextureRec Return type: void Description: Update GPU texture rectangle with new data Param[1]: texture (type: Texture2D) Param[2]: rec (type: Rectangle) Param[3]: pixels (type: const void *) -Function 360: GenTextureMipmaps() (1 input parameters) +Function 362: GenTextureMipmaps() (1 input parameters) Name: GenTextureMipmaps Return type: void Description: Generate GPU mipmaps for a texture Param[1]: texture (type: Texture2D *) -Function 361: SetTextureFilter() (2 input parameters) +Function 363: SetTextureFilter() (2 input parameters) Name: SetTextureFilter Return type: void Description: Set texture scaling filter mode Param[1]: texture (type: Texture2D) Param[2]: filter (type: int) -Function 362: SetTextureWrap() (2 input parameters) +Function 364: SetTextureWrap() (2 input parameters) Name: SetTextureWrap Return type: void Description: Set texture wrapping mode Param[1]: texture (type: Texture2D) Param[2]: wrap (type: int) -Function 363: DrawTexture() (4 input parameters) +Function 365: DrawTexture() (4 input parameters) Name: DrawTexture Return type: void Description: Draw a Texture2D @@ -3257,14 +3269,14 @@ Function 363: DrawTexture() (4 input parameters) Param[2]: posX (type: int) Param[3]: posY (type: int) Param[4]: tint (type: Color) -Function 364: DrawTextureV() (3 input parameters) +Function 366: DrawTextureV() (3 input parameters) Name: DrawTextureV Return type: void Description: Draw a Texture2D with position defined as Vector2 Param[1]: texture (type: Texture2D) Param[2]: position (type: Vector2) Param[3]: tint (type: Color) -Function 365: DrawTextureEx() (5 input parameters) +Function 367: DrawTextureEx() (5 input parameters) Name: DrawTextureEx Return type: void Description: Draw a Texture2D with extended parameters @@ -3273,7 +3285,7 @@ Function 365: DrawTextureEx() (5 input parameters) Param[3]: rotation (type: float) Param[4]: scale (type: float) Param[5]: tint (type: Color) -Function 366: DrawTextureRec() (4 input parameters) +Function 368: DrawTextureRec() (4 input parameters) Name: DrawTextureRec Return type: void Description: Draw a part of a texture defined by a rectangle @@ -3281,7 +3293,7 @@ Function 366: DrawTextureRec() (4 input parameters) Param[2]: source (type: Rectangle) Param[3]: position (type: Vector2) Param[4]: tint (type: Color) -Function 367: DrawTexturePro() (6 input parameters) +Function 369: DrawTexturePro() (6 input parameters) Name: DrawTexturePro Return type: void Description: Draw a part of a texture defined by a rectangle with 'pro' parameters @@ -3291,7 +3303,7 @@ Function 367: DrawTexturePro() (6 input parameters) Param[4]: origin (type: Vector2) Param[5]: rotation (type: float) Param[6]: tint (type: Color) -Function 368: DrawTextureNPatch() (6 input parameters) +Function 370: DrawTextureNPatch() (6 input parameters) Name: DrawTextureNPatch Return type: void Description: Draws a texture (or part of it) that stretches or shrinks nicely @@ -3301,119 +3313,119 @@ Function 368: DrawTextureNPatch() (6 input parameters) Param[4]: origin (type: Vector2) Param[5]: rotation (type: float) Param[6]: tint (type: Color) -Function 369: ColorIsEqual() (2 input parameters) +Function 371: ColorIsEqual() (2 input parameters) Name: ColorIsEqual Return type: bool Description: Check if two colors are equal Param[1]: col1 (type: Color) Param[2]: col2 (type: Color) -Function 370: Fade() (2 input parameters) +Function 372: Fade() (2 input parameters) Name: Fade Return type: Color Description: Get color with alpha applied, alpha goes from 0.0f to 1.0f Param[1]: color (type: Color) Param[2]: alpha (type: float) -Function 371: ColorToInt() (1 input parameters) +Function 373: ColorToInt() (1 input parameters) Name: ColorToInt Return type: int Description: Get hexadecimal value for a Color (0xRRGGBBAA) Param[1]: color (type: Color) -Function 372: ColorNormalize() (1 input parameters) +Function 374: ColorNormalize() (1 input parameters) Name: ColorNormalize Return type: Vector4 Description: Get Color normalized as float [0..1] Param[1]: color (type: Color) -Function 373: ColorFromNormalized() (1 input parameters) +Function 375: ColorFromNormalized() (1 input parameters) Name: ColorFromNormalized Return type: Color Description: Get Color from normalized values [0..1] Param[1]: normalized (type: Vector4) -Function 374: ColorToHSV() (1 input parameters) +Function 376: ColorToHSV() (1 input parameters) Name: ColorToHSV Return type: Vector3 Description: Get HSV values for a Color, hue [0..360], saturation/value [0..1] Param[1]: color (type: Color) -Function 375: ColorFromHSV() (3 input parameters) +Function 377: ColorFromHSV() (3 input parameters) Name: ColorFromHSV Return type: Color Description: Get a Color from HSV values, hue [0..360], saturation/value [0..1] Param[1]: hue (type: float) Param[2]: saturation (type: float) Param[3]: value (type: float) -Function 376: ColorTint() (2 input parameters) +Function 378: ColorTint() (2 input parameters) Name: ColorTint Return type: Color Description: Get color multiplied with another color Param[1]: color (type: Color) Param[2]: tint (type: Color) -Function 377: ColorBrightness() (2 input parameters) +Function 379: ColorBrightness() (2 input parameters) Name: ColorBrightness Return type: Color Description: Get color with brightness correction, brightness factor goes from -1.0f to 1.0f Param[1]: color (type: Color) Param[2]: factor (type: float) -Function 378: ColorContrast() (2 input parameters) +Function 380: ColorContrast() (2 input parameters) Name: ColorContrast Return type: Color Description: Get color with contrast correction, contrast values between -1.0f and 1.0f Param[1]: color (type: Color) Param[2]: contrast (type: float) -Function 379: ColorAlpha() (2 input parameters) +Function 381: ColorAlpha() (2 input parameters) Name: ColorAlpha Return type: Color Description: Get color with alpha applied, alpha goes from 0.0f to 1.0f Param[1]: color (type: Color) Param[2]: alpha (type: float) -Function 380: ColorAlphaBlend() (3 input parameters) +Function 382: ColorAlphaBlend() (3 input parameters) Name: ColorAlphaBlend Return type: Color Description: Get src alpha-blended into dst color with tint Param[1]: dst (type: Color) Param[2]: src (type: Color) Param[3]: tint (type: Color) -Function 381: ColorLerp() (3 input parameters) +Function 383: ColorLerp() (3 input parameters) Name: ColorLerp Return type: Color Description: Get color lerp interpolation between two colors, factor [0.0f..1.0f] Param[1]: color1 (type: Color) Param[2]: color2 (type: Color) Param[3]: factor (type: float) -Function 382: GetColor() (1 input parameters) +Function 384: GetColor() (1 input parameters) Name: GetColor Return type: Color Description: Get Color structure from hexadecimal value Param[1]: hexValue (type: unsigned int) -Function 383: GetPixelColor() (2 input parameters) +Function 385: GetPixelColor() (2 input parameters) Name: GetPixelColor Return type: Color Description: Get Color from a source pixel pointer of certain format Param[1]: srcPtr (type: void *) Param[2]: format (type: int) -Function 384: SetPixelColor() (3 input parameters) +Function 386: SetPixelColor() (3 input parameters) Name: SetPixelColor Return type: void Description: Set color formatted into destination pixel pointer Param[1]: dstPtr (type: void *) Param[2]: color (type: Color) Param[3]: format (type: int) -Function 385: GetPixelDataSize() (3 input parameters) +Function 387: GetPixelDataSize() (3 input parameters) Name: GetPixelDataSize Return type: int Description: Get pixel data size in bytes for certain format Param[1]: width (type: int) Param[2]: height (type: int) Param[3]: format (type: int) -Function 386: GetFontDefault() (0 input parameters) +Function 388: GetFontDefault() (0 input parameters) Name: GetFontDefault Return type: Font Description: Get the default Font No input parameters -Function 387: LoadFont() (1 input parameters) +Function 389: LoadFont() (1 input parameters) Name: LoadFont Return type: Font Description: Load font from file into GPU memory (VRAM) Param[1]: fileName (type: const char *) -Function 388: LoadFontEx() (4 input parameters) +Function 390: LoadFontEx() (4 input parameters) Name: LoadFontEx Return type: Font Description: Load font from file with extended parameters, use NULL for codepoints and 0 for codepointCount to load the default character set, font size is provided in pixels height @@ -3421,14 +3433,14 @@ Function 388: LoadFontEx() (4 input parameters) Param[2]: fontSize (type: int) Param[3]: codepoints (type: int *) Param[4]: codepointCount (type: int) -Function 389: LoadFontFromImage() (3 input parameters) +Function 391: LoadFontFromImage() (3 input parameters) Name: LoadFontFromImage Return type: Font Description: Load font from Image (XNA style) Param[1]: image (type: Image) Param[2]: key (type: Color) Param[3]: firstChar (type: int) -Function 390: LoadFontFromMemory() (6 input parameters) +Function 392: LoadFontFromMemory() (6 input parameters) Name: LoadFontFromMemory Return type: Font Description: Load font from memory buffer, fileType refers to extension: i.e. '.ttf' @@ -3438,12 +3450,12 @@ Function 390: LoadFontFromMemory() (6 input parameters) Param[4]: fontSize (type: int) Param[5]: codepoints (type: int *) Param[6]: codepointCount (type: int) -Function 391: IsFontReady() (1 input parameters) +Function 393: IsFontReady() (1 input parameters) Name: IsFontReady Return type: bool Description: Check if a font is ready Param[1]: font (type: Font) -Function 392: LoadFontData() (6 input parameters) +Function 394: LoadFontData() (6 input parameters) Name: LoadFontData Return type: GlyphInfo * Description: Load font data for further use @@ -3453,7 +3465,7 @@ Function 392: LoadFontData() (6 input parameters) Param[4]: codepoints (type: int *) Param[5]: codepointCount (type: int) Param[6]: type (type: int) -Function 393: GenImageFontAtlas() (6 input parameters) +Function 395: GenImageFontAtlas() (6 input parameters) Name: GenImageFontAtlas Return type: Image Description: Generate image font atlas using chars info @@ -3463,30 +3475,30 @@ Function 393: GenImageFontAtlas() (6 input parameters) Param[4]: fontSize (type: int) Param[5]: padding (type: int) Param[6]: packMethod (type: int) -Function 394: UnloadFontData() (2 input parameters) +Function 396: UnloadFontData() (2 input parameters) Name: UnloadFontData Return type: void Description: Unload font chars info data (RAM) Param[1]: glyphs (type: GlyphInfo *) Param[2]: glyphCount (type: int) -Function 395: UnloadFont() (1 input parameters) +Function 397: UnloadFont() (1 input parameters) Name: UnloadFont Return type: void Description: Unload font from GPU memory (VRAM) Param[1]: font (type: Font) -Function 396: ExportFontAsCode() (2 input parameters) +Function 398: ExportFontAsCode() (2 input parameters) Name: ExportFontAsCode Return type: bool Description: Export font as code file, returns true on success Param[1]: font (type: Font) Param[2]: fileName (type: const char *) -Function 397: DrawFPS() (2 input parameters) +Function 399: DrawFPS() (2 input parameters) Name: DrawFPS Return type: void Description: Draw current FPS Param[1]: posX (type: int) Param[2]: posY (type: int) -Function 398: DrawText() (5 input parameters) +Function 400: DrawText() (5 input parameters) Name: DrawText Return type: void Description: Draw text (using default font) @@ -3495,7 +3507,7 @@ Function 398: DrawText() (5 input parameters) Param[3]: posY (type: int) Param[4]: fontSize (type: int) Param[5]: color (type: Color) -Function 399: DrawTextEx() (6 input parameters) +Function 401: DrawTextEx() (6 input parameters) Name: DrawTextEx Return type: void Description: Draw text using font and additional parameters @@ -3505,7 +3517,7 @@ Function 399: DrawTextEx() (6 input parameters) Param[4]: fontSize (type: float) Param[5]: spacing (type: float) Param[6]: tint (type: Color) -Function 400: DrawTextPro() (8 input parameters) +Function 402: DrawTextPro() (8 input parameters) Name: DrawTextPro Return type: void Description: Draw text using Font and pro parameters (rotation) @@ -3517,7 +3529,7 @@ Function 400: DrawTextPro() (8 input parameters) Param[6]: fontSize (type: float) Param[7]: spacing (type: float) Param[8]: tint (type: Color) -Function 401: DrawTextCodepoint() (5 input parameters) +Function 403: DrawTextCodepoint() (5 input parameters) Name: DrawTextCodepoint Return type: void Description: Draw one character (codepoint) @@ -3526,7 +3538,7 @@ Function 401: DrawTextCodepoint() (5 input parameters) Param[3]: position (type: Vector2) Param[4]: fontSize (type: float) Param[5]: tint (type: Color) -Function 402: DrawTextCodepoints() (7 input parameters) +Function 404: DrawTextCodepoints() (7 input parameters) Name: DrawTextCodepoints Return type: void Description: Draw multiple character (codepoint) @@ -3537,18 +3549,18 @@ Function 402: DrawTextCodepoints() (7 input parameters) Param[5]: fontSize (type: float) Param[6]: spacing (type: float) Param[7]: tint (type: Color) -Function 403: SetTextLineSpacing() (1 input parameters) +Function 405: SetTextLineSpacing() (1 input parameters) Name: SetTextLineSpacing Return type: void Description: Set vertical line spacing when drawing with line-breaks Param[1]: spacing (type: int) -Function 404: MeasureText() (2 input parameters) +Function 406: MeasureText() (2 input parameters) Name: MeasureText Return type: int Description: Measure string width for default font Param[1]: text (type: const char *) Param[2]: fontSize (type: int) -Function 405: MeasureTextEx() (4 input parameters) +Function 407: MeasureTextEx() (4 input parameters) Name: MeasureTextEx Return type: Vector2 Description: Measure string size for Font @@ -3556,195 +3568,195 @@ Function 405: MeasureTextEx() (4 input parameters) Param[2]: text (type: const char *) Param[3]: fontSize (type: float) Param[4]: spacing (type: float) -Function 406: GetGlyphIndex() (2 input parameters) +Function 408: GetGlyphIndex() (2 input parameters) Name: GetGlyphIndex Return type: int Description: Get glyph index position in font for a codepoint (unicode character), fallback to '?' if not found Param[1]: font (type: Font) Param[2]: codepoint (type: int) -Function 407: GetGlyphInfo() (2 input parameters) +Function 409: GetGlyphInfo() (2 input parameters) Name: GetGlyphInfo Return type: GlyphInfo Description: Get glyph font info data for a codepoint (unicode character), fallback to '?' if not found Param[1]: font (type: Font) Param[2]: codepoint (type: int) -Function 408: GetGlyphAtlasRec() (2 input parameters) +Function 410: GetGlyphAtlasRec() (2 input parameters) Name: GetGlyphAtlasRec Return type: Rectangle Description: Get glyph rectangle in font atlas for a codepoint (unicode character), fallback to '?' if not found Param[1]: font (type: Font) Param[2]: codepoint (type: int) -Function 409: LoadUTF8() (2 input parameters) +Function 411: LoadUTF8() (2 input parameters) Name: LoadUTF8 Return type: char * Description: Load UTF-8 text encoded from codepoints array Param[1]: codepoints (type: const int *) Param[2]: length (type: int) -Function 410: UnloadUTF8() (1 input parameters) +Function 412: UnloadUTF8() (1 input parameters) Name: UnloadUTF8 Return type: void Description: Unload UTF-8 text encoded from codepoints array Param[1]: text (type: char *) -Function 411: LoadCodepoints() (2 input parameters) +Function 413: LoadCodepoints() (2 input parameters) Name: LoadCodepoints Return type: int * Description: Load all codepoints from a UTF-8 text string, codepoints count returned by parameter Param[1]: text (type: const char *) Param[2]: count (type: int *) -Function 412: UnloadCodepoints() (1 input parameters) +Function 414: UnloadCodepoints() (1 input parameters) Name: UnloadCodepoints Return type: void Description: Unload codepoints data from memory Param[1]: codepoints (type: int *) -Function 413: GetCodepointCount() (1 input parameters) +Function 415: GetCodepointCount() (1 input parameters) Name: GetCodepointCount Return type: int Description: Get total number of codepoints in a UTF-8 encoded string Param[1]: text (type: const char *) -Function 414: GetCodepoint() (2 input parameters) +Function 416: GetCodepoint() (2 input parameters) Name: GetCodepoint Return type: int Description: Get next codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure Param[1]: text (type: const char *) Param[2]: codepointSize (type: int *) -Function 415: GetCodepointNext() (2 input parameters) +Function 417: GetCodepointNext() (2 input parameters) Name: GetCodepointNext Return type: int Description: Get next codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure Param[1]: text (type: const char *) Param[2]: codepointSize (type: int *) -Function 416: GetCodepointPrevious() (2 input parameters) +Function 418: GetCodepointPrevious() (2 input parameters) Name: GetCodepointPrevious Return type: int Description: Get previous codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure Param[1]: text (type: const char *) Param[2]: codepointSize (type: int *) -Function 417: CodepointToUTF8() (2 input parameters) +Function 419: CodepointToUTF8() (2 input parameters) Name: CodepointToUTF8 Return type: const char * Description: Encode one codepoint into UTF-8 byte array (array length returned as parameter) Param[1]: codepoint (type: int) Param[2]: utf8Size (type: int *) -Function 418: TextCopy() (2 input parameters) +Function 420: TextCopy() (2 input parameters) Name: TextCopy Return type: int Description: Copy one string to another, returns bytes copied Param[1]: dst (type: char *) Param[2]: src (type: const char *) -Function 419: TextIsEqual() (2 input parameters) +Function 421: TextIsEqual() (2 input parameters) Name: TextIsEqual Return type: bool Description: Check if two text string are equal Param[1]: text1 (type: const char *) Param[2]: text2 (type: const char *) -Function 420: TextLength() (1 input parameters) +Function 422: TextLength() (1 input parameters) Name: TextLength Return type: unsigned int Description: Get text length, checks for '\0' ending Param[1]: text (type: const char *) -Function 421: TextFormat() (2 input parameters) +Function 423: TextFormat() (2 input parameters) Name: TextFormat Return type: const char * Description: Text formatting with variables (sprintf() style) Param[1]: text (type: const char *) Param[2]: args (type: ...) -Function 422: TextSubtext() (3 input parameters) +Function 424: TextSubtext() (3 input parameters) Name: TextSubtext Return type: const char * Description: Get a piece of a text string Param[1]: text (type: const char *) Param[2]: position (type: int) Param[3]: length (type: int) -Function 423: TextReplace() (3 input parameters) +Function 425: TextReplace() (3 input parameters) Name: TextReplace Return type: char * Description: Replace text string (WARNING: memory must be freed!) Param[1]: text (type: const char *) Param[2]: replace (type: const char *) Param[3]: by (type: const char *) -Function 424: TextInsert() (3 input parameters) +Function 426: TextInsert() (3 input parameters) Name: TextInsert Return type: char * Description: Insert text in a position (WARNING: memory must be freed!) Param[1]: text (type: const char *) Param[2]: insert (type: const char *) Param[3]: position (type: int) -Function 425: TextJoin() (3 input parameters) +Function 427: TextJoin() (3 input parameters) Name: TextJoin Return type: const char * Description: Join text strings with delimiter Param[1]: textList (type: const char **) Param[2]: count (type: int) Param[3]: delimiter (type: const char *) -Function 426: TextSplit() (3 input parameters) +Function 428: TextSplit() (3 input parameters) Name: TextSplit Return type: const char ** Description: Split text into multiple strings Param[1]: text (type: const char *) Param[2]: delimiter (type: char) Param[3]: count (type: int *) -Function 427: TextAppend() (3 input parameters) +Function 429: TextAppend() (3 input parameters) Name: TextAppend Return type: void Description: Append text at specific position and move cursor! Param[1]: text (type: char *) Param[2]: append (type: const char *) Param[3]: position (type: int *) -Function 428: TextFindIndex() (2 input parameters) +Function 430: TextFindIndex() (2 input parameters) Name: TextFindIndex Return type: int Description: Find first text occurrence within a string Param[1]: text (type: const char *) Param[2]: find (type: const char *) -Function 429: TextToUpper() (1 input parameters) +Function 431: TextToUpper() (1 input parameters) Name: TextToUpper Return type: const char * Description: Get upper case version of provided string Param[1]: text (type: const char *) -Function 430: TextToLower() (1 input parameters) +Function 432: TextToLower() (1 input parameters) Name: TextToLower Return type: const char * Description: Get lower case version of provided string Param[1]: text (type: const char *) -Function 431: TextToPascal() (1 input parameters) +Function 433: TextToPascal() (1 input parameters) Name: TextToPascal Return type: const char * Description: Get Pascal case notation version of provided string Param[1]: text (type: const char *) -Function 432: TextToSnake() (1 input parameters) +Function 434: TextToSnake() (1 input parameters) Name: TextToSnake Return type: const char * Description: Get Snake case notation version of provided string Param[1]: text (type: const char *) -Function 433: TextToCamel() (1 input parameters) +Function 435: TextToCamel() (1 input parameters) Name: TextToCamel Return type: const char * Description: Get Camel case notation version of provided string Param[1]: text (type: const char *) -Function 434: TextToInteger() (1 input parameters) +Function 436: TextToInteger() (1 input parameters) Name: TextToInteger Return type: int Description: Get integer value from text (negative values not supported) Param[1]: text (type: const char *) -Function 435: TextToFloat() (1 input parameters) +Function 437: TextToFloat() (1 input parameters) Name: TextToFloat Return type: float Description: Get float value from text (negative values not supported) Param[1]: text (type: const char *) -Function 436: DrawLine3D() (3 input parameters) +Function 438: DrawLine3D() (3 input parameters) Name: DrawLine3D Return type: void Description: Draw a line in 3D world space Param[1]: startPos (type: Vector3) Param[2]: endPos (type: Vector3) Param[3]: color (type: Color) -Function 437: DrawPoint3D() (2 input parameters) +Function 439: DrawPoint3D() (2 input parameters) Name: DrawPoint3D Return type: void Description: Draw a point in 3D space, actually a small line Param[1]: position (type: Vector3) Param[2]: color (type: Color) -Function 438: DrawCircle3D() (5 input parameters) +Function 440: DrawCircle3D() (5 input parameters) Name: DrawCircle3D Return type: void Description: Draw a circle in 3D world space @@ -3753,7 +3765,7 @@ Function 438: DrawCircle3D() (5 input parameters) Param[3]: rotationAxis (type: Vector3) Param[4]: rotationAngle (type: float) Param[5]: color (type: Color) -Function 439: DrawTriangle3D() (4 input parameters) +Function 441: DrawTriangle3D() (4 input parameters) Name: DrawTriangle3D Return type: void Description: Draw a color-filled triangle (vertex in counter-clockwise order!) @@ -3761,14 +3773,14 @@ Function 439: DrawTriangle3D() (4 input parameters) Param[2]: v2 (type: Vector3) Param[3]: v3 (type: Vector3) Param[4]: color (type: Color) -Function 440: DrawTriangleStrip3D() (3 input parameters) +Function 442: DrawTriangleStrip3D() (3 input parameters) Name: DrawTriangleStrip3D Return type: void Description: Draw a triangle strip defined by points Param[1]: points (type: const Vector3 *) Param[2]: pointCount (type: int) Param[3]: color (type: Color) -Function 441: DrawCube() (5 input parameters) +Function 443: DrawCube() (5 input parameters) Name: DrawCube Return type: void Description: Draw cube @@ -3777,14 +3789,14 @@ Function 441: DrawCube() (5 input parameters) Param[3]: height (type: float) Param[4]: length (type: float) Param[5]: color (type: Color) -Function 442: DrawCubeV() (3 input parameters) +Function 444: DrawCubeV() (3 input parameters) Name: DrawCubeV Return type: void Description: Draw cube (Vector version) Param[1]: position (type: Vector3) Param[2]: size (type: Vector3) Param[3]: color (type: Color) -Function 443: DrawCubeWires() (5 input parameters) +Function 445: DrawCubeWires() (5 input parameters) Name: DrawCubeWires Return type: void Description: Draw cube wires @@ -3793,21 +3805,21 @@ Function 443: DrawCubeWires() (5 input parameters) Param[3]: height (type: float) Param[4]: length (type: float) Param[5]: color (type: Color) -Function 444: DrawCubeWiresV() (3 input parameters) +Function 446: DrawCubeWiresV() (3 input parameters) Name: DrawCubeWiresV Return type: void Description: Draw cube wires (Vector version) Param[1]: position (type: Vector3) Param[2]: size (type: Vector3) Param[3]: color (type: Color) -Function 445: DrawSphere() (3 input parameters) +Function 447: DrawSphere() (3 input parameters) Name: DrawSphere Return type: void Description: Draw sphere Param[1]: centerPos (type: Vector3) Param[2]: radius (type: float) Param[3]: color (type: Color) -Function 446: DrawSphereEx() (5 input parameters) +Function 448: DrawSphereEx() (5 input parameters) Name: DrawSphereEx Return type: void Description: Draw sphere with extended parameters @@ -3816,7 +3828,7 @@ Function 446: DrawSphereEx() (5 input parameters) Param[3]: rings (type: int) Param[4]: slices (type: int) Param[5]: color (type: Color) -Function 447: DrawSphereWires() (5 input parameters) +Function 449: DrawSphereWires() (5 input parameters) Name: DrawSphereWires Return type: void Description: Draw sphere wires @@ -3825,7 +3837,7 @@ Function 447: DrawSphereWires() (5 input parameters) Param[3]: rings (type: int) Param[4]: slices (type: int) Param[5]: color (type: Color) -Function 448: DrawCylinder() (6 input parameters) +Function 450: DrawCylinder() (6 input parameters) Name: DrawCylinder Return type: void Description: Draw a cylinder/cone @@ -3835,7 +3847,7 @@ Function 448: DrawCylinder() (6 input parameters) Param[4]: height (type: float) Param[5]: slices (type: int) Param[6]: color (type: Color) -Function 449: DrawCylinderEx() (6 input parameters) +Function 451: DrawCylinderEx() (6 input parameters) Name: DrawCylinderEx Return type: void Description: Draw a cylinder with base at startPos and top at endPos @@ -3845,7 +3857,7 @@ Function 449: DrawCylinderEx() (6 input parameters) Param[4]: endRadius (type: float) Param[5]: sides (type: int) Param[6]: color (type: Color) -Function 450: DrawCylinderWires() (6 input parameters) +Function 452: DrawCylinderWires() (6 input parameters) Name: DrawCylinderWires Return type: void Description: Draw a cylinder/cone wires @@ -3855,7 +3867,7 @@ Function 450: DrawCylinderWires() (6 input parameters) Param[4]: height (type: float) Param[5]: slices (type: int) Param[6]: color (type: Color) -Function 451: DrawCylinderWiresEx() (6 input parameters) +Function 453: DrawCylinderWiresEx() (6 input parameters) Name: DrawCylinderWiresEx Return type: void Description: Draw a cylinder wires with base at startPos and top at endPos @@ -3865,7 +3877,7 @@ Function 451: DrawCylinderWiresEx() (6 input parameters) Param[4]: endRadius (type: float) Param[5]: sides (type: int) Param[6]: color (type: Color) -Function 452: DrawCapsule() (6 input parameters) +Function 454: DrawCapsule() (6 input parameters) Name: DrawCapsule Return type: void Description: Draw a capsule with the center of its sphere caps at startPos and endPos @@ -3875,7 +3887,7 @@ Function 452: DrawCapsule() (6 input parameters) Param[4]: slices (type: int) Param[5]: rings (type: int) Param[6]: color (type: Color) -Function 453: DrawCapsuleWires() (6 input parameters) +Function 455: DrawCapsuleWires() (6 input parameters) Name: DrawCapsuleWires Return type: void Description: Draw capsule wireframe with the center of its sphere caps at startPos and endPos @@ -3885,51 +3897,51 @@ Function 453: DrawCapsuleWires() (6 input parameters) Param[4]: slices (type: int) Param[5]: rings (type: int) Param[6]: color (type: Color) -Function 454: DrawPlane() (3 input parameters) +Function 456: DrawPlane() (3 input parameters) Name: DrawPlane Return type: void Description: Draw a plane XZ Param[1]: centerPos (type: Vector3) Param[2]: size (type: Vector2) Param[3]: color (type: Color) -Function 455: DrawRay() (2 input parameters) +Function 457: DrawRay() (2 input parameters) Name: DrawRay Return type: void Description: Draw a ray line Param[1]: ray (type: Ray) Param[2]: color (type: Color) -Function 456: DrawGrid() (2 input parameters) +Function 458: DrawGrid() (2 input parameters) Name: DrawGrid Return type: void Description: Draw a grid (centered at (0, 0, 0)) Param[1]: slices (type: int) Param[2]: spacing (type: float) -Function 457: LoadModel() (1 input parameters) +Function 459: LoadModel() (1 input parameters) Name: LoadModel Return type: Model Description: Load model from files (meshes and materials) Param[1]: fileName (type: const char *) -Function 458: LoadModelFromMesh() (1 input parameters) +Function 460: LoadModelFromMesh() (1 input parameters) Name: LoadModelFromMesh Return type: Model Description: Load model from generated mesh (default material) Param[1]: mesh (type: Mesh) -Function 459: IsModelReady() (1 input parameters) +Function 461: IsModelReady() (1 input parameters) Name: IsModelReady Return type: bool Description: Check if a model is ready Param[1]: model (type: Model) -Function 460: UnloadModel() (1 input parameters) +Function 462: UnloadModel() (1 input parameters) Name: UnloadModel Return type: void Description: Unload model (including meshes) from memory (RAM and/or VRAM) Param[1]: model (type: Model) -Function 461: GetModelBoundingBox() (1 input parameters) +Function 463: GetModelBoundingBox() (1 input parameters) Name: GetModelBoundingBox Return type: BoundingBox Description: Compute model bounding box limits (considers all meshes) Param[1]: model (type: Model) -Function 462: DrawModel() (4 input parameters) +Function 464: DrawModel() (4 input parameters) Name: DrawModel Return type: void Description: Draw a model (with texture if set) @@ -3937,7 +3949,7 @@ Function 462: DrawModel() (4 input parameters) Param[2]: position (type: Vector3) Param[3]: scale (type: float) Param[4]: tint (type: Color) -Function 463: DrawModelEx() (6 input parameters) +Function 465: DrawModelEx() (6 input parameters) Name: DrawModelEx Return type: void Description: Draw a model with extended parameters @@ -3947,7 +3959,7 @@ Function 463: DrawModelEx() (6 input parameters) Param[4]: rotationAngle (type: float) Param[5]: scale (type: Vector3) Param[6]: tint (type: Color) -Function 464: DrawModelWires() (4 input parameters) +Function 466: DrawModelWires() (4 input parameters) Name: DrawModelWires Return type: void Description: Draw a model wires (with texture if set) @@ -3955,7 +3967,7 @@ Function 464: DrawModelWires() (4 input parameters) Param[2]: position (type: Vector3) Param[3]: scale (type: float) Param[4]: tint (type: Color) -Function 465: DrawModelWiresEx() (6 input parameters) +Function 467: DrawModelWiresEx() (6 input parameters) Name: DrawModelWiresEx Return type: void Description: Draw a model wires (with texture if set) with extended parameters @@ -3965,7 +3977,7 @@ Function 465: DrawModelWiresEx() (6 input parameters) Param[4]: rotationAngle (type: float) Param[5]: scale (type: Vector3) Param[6]: tint (type: Color) -Function 466: DrawModelPoints() (4 input parameters) +Function 468: DrawModelPoints() (4 input parameters) Name: DrawModelPoints Return type: void Description: Draw a model as points @@ -3973,7 +3985,7 @@ Function 466: DrawModelPoints() (4 input parameters) Param[2]: position (type: Vector3) Param[3]: scale (type: float) Param[4]: tint (type: Color) -Function 467: DrawModelPointsEx() (6 input parameters) +Function 469: DrawModelPointsEx() (6 input parameters) Name: DrawModelPointsEx Return type: void Description: Draw a model as points with extended parameters @@ -3983,13 +3995,13 @@ Function 467: DrawModelPointsEx() (6 input parameters) Param[4]: rotationAngle (type: float) Param[5]: scale (type: Vector3) Param[6]: tint (type: Color) -Function 468: DrawBoundingBox() (2 input parameters) +Function 470: DrawBoundingBox() (2 input parameters) Name: DrawBoundingBox Return type: void Description: Draw bounding box (wires) Param[1]: box (type: BoundingBox) Param[2]: color (type: Color) -Function 469: DrawBillboard() (5 input parameters) +Function 471: DrawBillboard() (5 input parameters) Name: DrawBillboard Return type: void Description: Draw a billboard texture @@ -3998,7 +4010,7 @@ Function 469: DrawBillboard() (5 input parameters) Param[3]: position (type: Vector3) Param[4]: scale (type: float) Param[5]: tint (type: Color) -Function 470: DrawBillboardRec() (6 input parameters) +Function 472: DrawBillboardRec() (6 input parameters) Name: DrawBillboardRec Return type: void Description: Draw a billboard texture defined by source @@ -4008,7 +4020,7 @@ Function 470: DrawBillboardRec() (6 input parameters) Param[4]: position (type: Vector3) Param[5]: size (type: Vector2) Param[6]: tint (type: Color) -Function 471: DrawBillboardPro() (9 input parameters) +Function 473: DrawBillboardPro() (9 input parameters) Name: DrawBillboardPro Return type: void Description: Draw a billboard texture defined by source and rotation @@ -4021,13 +4033,13 @@ Function 471: DrawBillboardPro() (9 input parameters) Param[7]: origin (type: Vector2) Param[8]: rotation (type: float) Param[9]: tint (type: Color) -Function 472: UploadMesh() (2 input parameters) +Function 474: UploadMesh() (2 input parameters) Name: UploadMesh Return type: void Description: Upload mesh vertex data in GPU and provide VAO/VBO ids Param[1]: mesh (type: Mesh *) Param[2]: dynamic (type: bool) -Function 473: UpdateMeshBuffer() (5 input parameters) +Function 475: UpdateMeshBuffer() (5 input parameters) Name: UpdateMeshBuffer Return type: void Description: Update mesh vertex data in GPU for a specific buffer index @@ -4036,19 +4048,19 @@ Function 473: UpdateMeshBuffer() (5 input parameters) Param[3]: data (type: const void *) Param[4]: dataSize (type: int) Param[5]: offset (type: int) -Function 474: UnloadMesh() (1 input parameters) +Function 476: UnloadMesh() (1 input parameters) Name: UnloadMesh Return type: void Description: Unload mesh data from CPU and GPU Param[1]: mesh (type: Mesh) -Function 475: DrawMesh() (3 input parameters) +Function 477: DrawMesh() (3 input parameters) Name: DrawMesh Return type: void Description: Draw a 3d mesh with material and transform Param[1]: mesh (type: Mesh) Param[2]: material (type: Material) Param[3]: transform (type: Matrix) -Function 476: DrawMeshInstanced() (4 input parameters) +Function 478: DrawMeshInstanced() (4 input parameters) Name: DrawMeshInstanced Return type: void Description: Draw multiple mesh instances with material and different transforms @@ -4056,35 +4068,35 @@ Function 476: DrawMeshInstanced() (4 input parameters) Param[2]: material (type: Material) Param[3]: transforms (type: const Matrix *) Param[4]: instances (type: int) -Function 477: GetMeshBoundingBox() (1 input parameters) +Function 479: GetMeshBoundingBox() (1 input parameters) Name: GetMeshBoundingBox Return type: BoundingBox Description: Compute mesh bounding box limits Param[1]: mesh (type: Mesh) -Function 478: GenMeshTangents() (1 input parameters) +Function 480: GenMeshTangents() (1 input parameters) Name: GenMeshTangents Return type: void Description: Compute mesh tangents Param[1]: mesh (type: Mesh *) -Function 479: ExportMesh() (2 input parameters) +Function 481: ExportMesh() (2 input parameters) Name: ExportMesh Return type: bool Description: Export mesh data to file, returns true on success Param[1]: mesh (type: Mesh) Param[2]: fileName (type: const char *) -Function 480: ExportMeshAsCode() (2 input parameters) +Function 482: ExportMeshAsCode() (2 input parameters) Name: ExportMeshAsCode Return type: bool Description: Export mesh as code file (.h) defining multiple arrays of vertex attributes Param[1]: mesh (type: Mesh) Param[2]: fileName (type: const char *) -Function 481: GenMeshPoly() (2 input parameters) +Function 483: GenMeshPoly() (2 input parameters) Name: GenMeshPoly Return type: Mesh Description: Generate polygonal mesh Param[1]: sides (type: int) Param[2]: radius (type: float) -Function 482: GenMeshPlane() (4 input parameters) +Function 484: GenMeshPlane() (4 input parameters) Name: GenMeshPlane Return type: Mesh Description: Generate plane mesh (with subdivisions) @@ -4092,42 +4104,42 @@ Function 482: GenMeshPlane() (4 input parameters) Param[2]: length (type: float) Param[3]: resX (type: int) Param[4]: resZ (type: int) -Function 483: GenMeshCube() (3 input parameters) +Function 485: GenMeshCube() (3 input parameters) Name: GenMeshCube Return type: Mesh Description: Generate cuboid mesh Param[1]: width (type: float) Param[2]: height (type: float) Param[3]: length (type: float) -Function 484: GenMeshSphere() (3 input parameters) +Function 486: GenMeshSphere() (3 input parameters) Name: GenMeshSphere Return type: Mesh Description: Generate sphere mesh (standard sphere) Param[1]: radius (type: float) Param[2]: rings (type: int) Param[3]: slices (type: int) -Function 485: GenMeshHemiSphere() (3 input parameters) +Function 487: GenMeshHemiSphere() (3 input parameters) Name: GenMeshHemiSphere Return type: Mesh Description: Generate half-sphere mesh (no bottom cap) Param[1]: radius (type: float) Param[2]: rings (type: int) Param[3]: slices (type: int) -Function 486: GenMeshCylinder() (3 input parameters) +Function 488: GenMeshCylinder() (3 input parameters) Name: GenMeshCylinder Return type: Mesh Description: Generate cylinder mesh Param[1]: radius (type: float) Param[2]: height (type: float) Param[3]: slices (type: int) -Function 487: GenMeshCone() (3 input parameters) +Function 489: GenMeshCone() (3 input parameters) Name: GenMeshCone Return type: Mesh Description: Generate cone/pyramid mesh Param[1]: radius (type: float) Param[2]: height (type: float) Param[3]: slices (type: int) -Function 488: GenMeshTorus() (4 input parameters) +Function 490: GenMeshTorus() (4 input parameters) Name: GenMeshTorus Return type: Mesh Description: Generate torus mesh @@ -4135,7 +4147,7 @@ Function 488: GenMeshTorus() (4 input parameters) Param[2]: size (type: float) Param[3]: radSeg (type: int) Param[4]: sides (type: int) -Function 489: GenMeshKnot() (4 input parameters) +Function 491: GenMeshKnot() (4 input parameters) Name: GenMeshKnot Return type: Mesh Description: Generate trefoil knot mesh @@ -4143,91 +4155,91 @@ Function 489: GenMeshKnot() (4 input parameters) Param[2]: size (type: float) Param[3]: radSeg (type: int) Param[4]: sides (type: int) -Function 490: GenMeshHeightmap() (2 input parameters) +Function 492: GenMeshHeightmap() (2 input parameters) Name: GenMeshHeightmap Return type: Mesh Description: Generate heightmap mesh from image data Param[1]: heightmap (type: Image) Param[2]: size (type: Vector3) -Function 491: GenMeshCubicmap() (2 input parameters) +Function 493: GenMeshCubicmap() (2 input parameters) Name: GenMeshCubicmap Return type: Mesh Description: Generate cubes-based map mesh from image data Param[1]: cubicmap (type: Image) Param[2]: cubeSize (type: Vector3) -Function 492: LoadMaterials() (2 input parameters) +Function 494: LoadMaterials() (2 input parameters) Name: LoadMaterials Return type: Material * Description: Load materials from model file Param[1]: fileName (type: const char *) Param[2]: materialCount (type: int *) -Function 493: LoadMaterialDefault() (0 input parameters) +Function 495: LoadMaterialDefault() (0 input parameters) Name: LoadMaterialDefault Return type: Material Description: Load default material (Supports: DIFFUSE, SPECULAR, NORMAL maps) No input parameters -Function 494: IsMaterialReady() (1 input parameters) +Function 496: IsMaterialReady() (1 input parameters) Name: IsMaterialReady Return type: bool Description: Check if a material is ready Param[1]: material (type: Material) -Function 495: UnloadMaterial() (1 input parameters) +Function 497: UnloadMaterial() (1 input parameters) Name: UnloadMaterial Return type: void Description: Unload material from GPU memory (VRAM) Param[1]: material (type: Material) -Function 496: SetMaterialTexture() (3 input parameters) +Function 498: SetMaterialTexture() (3 input parameters) Name: SetMaterialTexture Return type: void Description: Set texture for a material map type (MATERIAL_MAP_DIFFUSE, MATERIAL_MAP_SPECULAR...) Param[1]: material (type: Material *) Param[2]: mapType (type: int) Param[3]: texture (type: Texture2D) -Function 497: SetModelMeshMaterial() (3 input parameters) +Function 499: SetModelMeshMaterial() (3 input parameters) Name: SetModelMeshMaterial Return type: void Description: Set material for a mesh Param[1]: model (type: Model *) Param[2]: meshId (type: int) Param[3]: materialId (type: int) -Function 498: LoadModelAnimations() (2 input parameters) +Function 500: LoadModelAnimations() (2 input parameters) Name: LoadModelAnimations Return type: ModelAnimation * Description: Load model animations from file Param[1]: fileName (type: const char *) Param[2]: animCount (type: int *) -Function 499: UpdateModelAnimation() (3 input parameters) +Function 501: UpdateModelAnimation() (3 input parameters) Name: UpdateModelAnimation Return type: void Description: Update model animation pose Param[1]: model (type: Model) Param[2]: anim (type: ModelAnimation) Param[3]: frame (type: int) -Function 500: UnloadModelAnimation() (1 input parameters) +Function 502: UnloadModelAnimation() (1 input parameters) Name: UnloadModelAnimation Return type: void Description: Unload animation data Param[1]: anim (type: ModelAnimation) -Function 501: UnloadModelAnimations() (2 input parameters) +Function 503: UnloadModelAnimations() (2 input parameters) Name: UnloadModelAnimations Return type: void Description: Unload animation array data Param[1]: animations (type: ModelAnimation *) Param[2]: animCount (type: int) -Function 502: IsModelAnimationValid() (2 input parameters) +Function 504: IsModelAnimationValid() (2 input parameters) Name: IsModelAnimationValid Return type: bool Description: Check model animation skeleton match Param[1]: model (type: Model) Param[2]: anim (type: ModelAnimation) -Function 503: UpdateModelAnimationBoneMatrices() (3 input parameters) +Function 505: UpdateModelAnimationBoneMatrices() (3 input parameters) Name: UpdateModelAnimationBoneMatrices Return type: void Description: Update model animation mesh bone matrices (Note GPU skinning does not work on Mac) Param[1]: model (type: Model) Param[2]: anim (type: ModelAnimation) Param[3]: frame (type: int) -Function 504: CheckCollisionSpheres() (4 input parameters) +Function 506: CheckCollisionSpheres() (4 input parameters) Name: CheckCollisionSpheres Return type: bool Description: Check collision between two spheres @@ -4235,40 +4247,40 @@ Function 504: CheckCollisionSpheres() (4 input parameters) Param[2]: radius1 (type: float) Param[3]: center2 (type: Vector3) Param[4]: radius2 (type: float) -Function 505: CheckCollisionBoxes() (2 input parameters) +Function 507: CheckCollisionBoxes() (2 input parameters) Name: CheckCollisionBoxes Return type: bool Description: Check collision between two bounding boxes Param[1]: box1 (type: BoundingBox) Param[2]: box2 (type: BoundingBox) -Function 506: CheckCollisionBoxSphere() (3 input parameters) +Function 508: CheckCollisionBoxSphere() (3 input parameters) Name: CheckCollisionBoxSphere Return type: bool Description: Check collision between box and sphere Param[1]: box (type: BoundingBox) Param[2]: center (type: Vector3) Param[3]: radius (type: float) -Function 507: GetRayCollisionSphere() (3 input parameters) +Function 509: GetRayCollisionSphere() (3 input parameters) Name: GetRayCollisionSphere Return type: RayCollision Description: Get collision info between ray and sphere Param[1]: ray (type: Ray) Param[2]: center (type: Vector3) Param[3]: radius (type: float) -Function 508: GetRayCollisionBox() (2 input parameters) +Function 510: GetRayCollisionBox() (2 input parameters) Name: GetRayCollisionBox Return type: RayCollision Description: Get collision info between ray and box Param[1]: ray (type: Ray) Param[2]: box (type: BoundingBox) -Function 509: GetRayCollisionMesh() (3 input parameters) +Function 511: GetRayCollisionMesh() (3 input parameters) Name: GetRayCollisionMesh Return type: RayCollision Description: Get collision info between ray and mesh Param[1]: ray (type: Ray) Param[2]: mesh (type: Mesh) Param[3]: transform (type: Matrix) -Function 510: GetRayCollisionTriangle() (4 input parameters) +Function 512: GetRayCollisionTriangle() (4 input parameters) Name: GetRayCollisionTriangle Return type: RayCollision Description: Get collision info between ray and triangle @@ -4276,7 +4288,7 @@ Function 510: GetRayCollisionTriangle() (4 input parameters) Param[2]: p1 (type: Vector3) Param[3]: p2 (type: Vector3) Param[4]: p3 (type: Vector3) -Function 511: GetRayCollisionQuad() (5 input parameters) +Function 513: GetRayCollisionQuad() (5 input parameters) Name: GetRayCollisionQuad Return type: RayCollision Description: Get collision info between ray and quad @@ -4285,158 +4297,158 @@ Function 511: GetRayCollisionQuad() (5 input parameters) Param[3]: p2 (type: Vector3) Param[4]: p3 (type: Vector3) Param[5]: p4 (type: Vector3) -Function 512: InitAudioDevice() (0 input parameters) +Function 514: InitAudioDevice() (0 input parameters) Name: InitAudioDevice Return type: void Description: Initialize audio device and context No input parameters -Function 513: CloseAudioDevice() (0 input parameters) +Function 515: CloseAudioDevice() (0 input parameters) Name: CloseAudioDevice Return type: void Description: Close the audio device and context No input parameters -Function 514: IsAudioDeviceReady() (0 input parameters) +Function 516: IsAudioDeviceReady() (0 input parameters) Name: IsAudioDeviceReady Return type: bool Description: Check if audio device has been initialized successfully No input parameters -Function 515: SetMasterVolume() (1 input parameters) +Function 517: SetMasterVolume() (1 input parameters) Name: SetMasterVolume Return type: void Description: Set master volume (listener) Param[1]: volume (type: float) -Function 516: GetMasterVolume() (0 input parameters) +Function 518: GetMasterVolume() (0 input parameters) Name: GetMasterVolume Return type: float Description: Get master volume (listener) No input parameters -Function 517: LoadWave() (1 input parameters) +Function 519: LoadWave() (1 input parameters) Name: LoadWave Return type: Wave Description: Load wave data from file Param[1]: fileName (type: const char *) -Function 518: LoadWaveFromMemory() (3 input parameters) +Function 520: LoadWaveFromMemory() (3 input parameters) Name: LoadWaveFromMemory Return type: Wave Description: Load wave from memory buffer, fileType refers to extension: i.e. '.wav' Param[1]: fileType (type: const char *) Param[2]: fileData (type: const unsigned char *) Param[3]: dataSize (type: int) -Function 519: IsWaveReady() (1 input parameters) +Function 521: IsWaveReady() (1 input parameters) Name: IsWaveReady Return type: bool Description: Checks if wave data is ready Param[1]: wave (type: Wave) -Function 520: LoadSound() (1 input parameters) +Function 522: LoadSound() (1 input parameters) Name: LoadSound Return type: Sound Description: Load sound from file Param[1]: fileName (type: const char *) -Function 521: LoadSoundFromWave() (1 input parameters) +Function 523: LoadSoundFromWave() (1 input parameters) Name: LoadSoundFromWave Return type: Sound Description: Load sound from wave data Param[1]: wave (type: Wave) -Function 522: LoadSoundAlias() (1 input parameters) +Function 524: LoadSoundAlias() (1 input parameters) Name: LoadSoundAlias Return type: Sound Description: Create a new sound that shares the same sample data as the source sound, does not own the sound data Param[1]: source (type: Sound) -Function 523: IsSoundReady() (1 input parameters) +Function 525: IsSoundReady() (1 input parameters) Name: IsSoundReady Return type: bool Description: Checks if a sound is ready Param[1]: sound (type: Sound) -Function 524: UpdateSound() (3 input parameters) +Function 526: UpdateSound() (3 input parameters) Name: UpdateSound Return type: void Description: Update sound buffer with new data Param[1]: sound (type: Sound) Param[2]: data (type: const void *) Param[3]: sampleCount (type: int) -Function 525: UnloadWave() (1 input parameters) +Function 527: UnloadWave() (1 input parameters) Name: UnloadWave Return type: void Description: Unload wave data Param[1]: wave (type: Wave) -Function 526: UnloadSound() (1 input parameters) +Function 528: UnloadSound() (1 input parameters) Name: UnloadSound Return type: void Description: Unload sound Param[1]: sound (type: Sound) -Function 527: UnloadSoundAlias() (1 input parameters) +Function 529: UnloadSoundAlias() (1 input parameters) Name: UnloadSoundAlias Return type: void Description: Unload a sound alias (does not deallocate sample data) Param[1]: alias (type: Sound) -Function 528: ExportWave() (2 input parameters) +Function 530: ExportWave() (2 input parameters) Name: ExportWave Return type: bool Description: Export wave data to file, returns true on success Param[1]: wave (type: Wave) Param[2]: fileName (type: const char *) -Function 529: ExportWaveAsCode() (2 input parameters) +Function 531: ExportWaveAsCode() (2 input parameters) Name: ExportWaveAsCode Return type: bool Description: Export wave sample data to code (.h), returns true on success Param[1]: wave (type: Wave) Param[2]: fileName (type: const char *) -Function 530: PlaySound() (1 input parameters) +Function 532: PlaySound() (1 input parameters) Name: PlaySound Return type: void Description: Play a sound Param[1]: sound (type: Sound) -Function 531: StopSound() (1 input parameters) +Function 533: StopSound() (1 input parameters) Name: StopSound Return type: void Description: Stop playing a sound Param[1]: sound (type: Sound) -Function 532: PauseSound() (1 input parameters) +Function 534: PauseSound() (1 input parameters) Name: PauseSound Return type: void Description: Pause a sound Param[1]: sound (type: Sound) -Function 533: ResumeSound() (1 input parameters) +Function 535: ResumeSound() (1 input parameters) Name: ResumeSound Return type: void Description: Resume a paused sound Param[1]: sound (type: Sound) -Function 534: IsSoundPlaying() (1 input parameters) +Function 536: IsSoundPlaying() (1 input parameters) Name: IsSoundPlaying Return type: bool Description: Check if a sound is currently playing Param[1]: sound (type: Sound) -Function 535: SetSoundVolume() (2 input parameters) +Function 537: SetSoundVolume() (2 input parameters) Name: SetSoundVolume Return type: void Description: Set volume for a sound (1.0 is max level) Param[1]: sound (type: Sound) Param[2]: volume (type: float) -Function 536: SetSoundPitch() (2 input parameters) +Function 538: SetSoundPitch() (2 input parameters) Name: SetSoundPitch Return type: void Description: Set pitch for a sound (1.0 is base level) Param[1]: sound (type: Sound) Param[2]: pitch (type: float) -Function 537: SetSoundPan() (2 input parameters) +Function 539: SetSoundPan() (2 input parameters) Name: SetSoundPan Return type: void Description: Set pan for a sound (0.5 is center) Param[1]: sound (type: Sound) Param[2]: pan (type: float) -Function 538: WaveCopy() (1 input parameters) +Function 540: WaveCopy() (1 input parameters) Name: WaveCopy Return type: Wave Description: Copy a wave to a new wave Param[1]: wave (type: Wave) -Function 539: WaveCrop() (3 input parameters) +Function 541: WaveCrop() (3 input parameters) Name: WaveCrop Return type: void Description: Crop a wave to defined frames range Param[1]: wave (type: Wave *) Param[2]: initFrame (type: int) Param[3]: finalFrame (type: int) -Function 540: WaveFormat() (4 input parameters) +Function 542: WaveFormat() (4 input parameters) Name: WaveFormat Return type: void Description: Convert wave data to desired format @@ -4444,203 +4456,203 @@ Function 540: WaveFormat() (4 input parameters) Param[2]: sampleRate (type: int) Param[3]: sampleSize (type: int) Param[4]: channels (type: int) -Function 541: LoadWaveSamples() (1 input parameters) +Function 543: LoadWaveSamples() (1 input parameters) Name: LoadWaveSamples Return type: float * Description: Load samples data from wave as a 32bit float data array Param[1]: wave (type: Wave) -Function 542: UnloadWaveSamples() (1 input parameters) +Function 544: UnloadWaveSamples() (1 input parameters) Name: UnloadWaveSamples Return type: void Description: Unload samples data loaded with LoadWaveSamples() Param[1]: samples (type: float *) -Function 543: LoadMusicStream() (1 input parameters) +Function 545: LoadMusicStream() (1 input parameters) Name: LoadMusicStream Return type: Music Description: Load music stream from file Param[1]: fileName (type: const char *) -Function 544: LoadMusicStreamFromMemory() (3 input parameters) +Function 546: LoadMusicStreamFromMemory() (3 input parameters) Name: LoadMusicStreamFromMemory Return type: Music Description: Load music stream from data Param[1]: fileType (type: const char *) Param[2]: data (type: const unsigned char *) Param[3]: dataSize (type: int) -Function 545: IsMusicReady() (1 input parameters) +Function 547: IsMusicReady() (1 input parameters) Name: IsMusicReady Return type: bool Description: Checks if a music stream is ready Param[1]: music (type: Music) -Function 546: UnloadMusicStream() (1 input parameters) +Function 548: UnloadMusicStream() (1 input parameters) Name: UnloadMusicStream Return type: void Description: Unload music stream Param[1]: music (type: Music) -Function 547: PlayMusicStream() (1 input parameters) +Function 549: PlayMusicStream() (1 input parameters) Name: PlayMusicStream Return type: void Description: Start music playing Param[1]: music (type: Music) -Function 548: IsMusicStreamPlaying() (1 input parameters) +Function 550: IsMusicStreamPlaying() (1 input parameters) Name: IsMusicStreamPlaying Return type: bool Description: Check if music is playing Param[1]: music (type: Music) -Function 549: UpdateMusicStream() (1 input parameters) +Function 551: UpdateMusicStream() (1 input parameters) Name: UpdateMusicStream Return type: void Description: Updates buffers for music streaming Param[1]: music (type: Music) -Function 550: StopMusicStream() (1 input parameters) +Function 552: StopMusicStream() (1 input parameters) Name: StopMusicStream Return type: void Description: Stop music playing Param[1]: music (type: Music) -Function 551: PauseMusicStream() (1 input parameters) +Function 553: PauseMusicStream() (1 input parameters) Name: PauseMusicStream Return type: void Description: Pause music playing Param[1]: music (type: Music) -Function 552: ResumeMusicStream() (1 input parameters) +Function 554: ResumeMusicStream() (1 input parameters) Name: ResumeMusicStream Return type: void Description: Resume playing paused music Param[1]: music (type: Music) -Function 553: SeekMusicStream() (2 input parameters) +Function 555: SeekMusicStream() (2 input parameters) Name: SeekMusicStream Return type: void Description: Seek music to a position (in seconds) Param[1]: music (type: Music) Param[2]: position (type: float) -Function 554: SetMusicVolume() (2 input parameters) +Function 556: SetMusicVolume() (2 input parameters) Name: SetMusicVolume Return type: void Description: Set volume for music (1.0 is max level) Param[1]: music (type: Music) Param[2]: volume (type: float) -Function 555: SetMusicPitch() (2 input parameters) +Function 557: SetMusicPitch() (2 input parameters) Name: SetMusicPitch Return type: void Description: Set pitch for a music (1.0 is base level) Param[1]: music (type: Music) Param[2]: pitch (type: float) -Function 556: SetMusicPan() (2 input parameters) +Function 558: SetMusicPan() (2 input parameters) Name: SetMusicPan Return type: void Description: Set pan for a music (0.5 is center) Param[1]: music (type: Music) Param[2]: pan (type: float) -Function 557: GetMusicTimeLength() (1 input parameters) +Function 559: GetMusicTimeLength() (1 input parameters) Name: GetMusicTimeLength Return type: float Description: Get music time length (in seconds) Param[1]: music (type: Music) -Function 558: GetMusicTimePlayed() (1 input parameters) +Function 560: GetMusicTimePlayed() (1 input parameters) Name: GetMusicTimePlayed Return type: float Description: Get current music time played (in seconds) Param[1]: music (type: Music) -Function 559: LoadAudioStream() (3 input parameters) +Function 561: LoadAudioStream() (3 input parameters) Name: LoadAudioStream Return type: AudioStream Description: Load audio stream (to stream raw audio pcm data) Param[1]: sampleRate (type: unsigned int) Param[2]: sampleSize (type: unsigned int) Param[3]: channels (type: unsigned int) -Function 560: IsAudioStreamReady() (1 input parameters) +Function 562: IsAudioStreamReady() (1 input parameters) Name: IsAudioStreamReady Return type: bool Description: Checks if an audio stream is ready Param[1]: stream (type: AudioStream) -Function 561: UnloadAudioStream() (1 input parameters) +Function 563: UnloadAudioStream() (1 input parameters) Name: UnloadAudioStream Return type: void Description: Unload audio stream and free memory Param[1]: stream (type: AudioStream) -Function 562: UpdateAudioStream() (3 input parameters) +Function 564: UpdateAudioStream() (3 input parameters) Name: UpdateAudioStream Return type: void Description: Update audio stream buffers with data Param[1]: stream (type: AudioStream) Param[2]: data (type: const void *) Param[3]: frameCount (type: int) -Function 563: IsAudioStreamProcessed() (1 input parameters) +Function 565: IsAudioStreamProcessed() (1 input parameters) Name: IsAudioStreamProcessed Return type: bool Description: Check if any audio stream buffers requires refill Param[1]: stream (type: AudioStream) -Function 564: PlayAudioStream() (1 input parameters) +Function 566: PlayAudioStream() (1 input parameters) Name: PlayAudioStream Return type: void Description: Play audio stream Param[1]: stream (type: AudioStream) -Function 565: PauseAudioStream() (1 input parameters) +Function 567: PauseAudioStream() (1 input parameters) Name: PauseAudioStream Return type: void Description: Pause audio stream Param[1]: stream (type: AudioStream) -Function 566: ResumeAudioStream() (1 input parameters) +Function 568: ResumeAudioStream() (1 input parameters) Name: ResumeAudioStream Return type: void Description: Resume audio stream Param[1]: stream (type: AudioStream) -Function 567: IsAudioStreamPlaying() (1 input parameters) +Function 569: IsAudioStreamPlaying() (1 input parameters) Name: IsAudioStreamPlaying Return type: bool Description: Check if audio stream is playing Param[1]: stream (type: AudioStream) -Function 568: StopAudioStream() (1 input parameters) +Function 570: StopAudioStream() (1 input parameters) Name: StopAudioStream Return type: void Description: Stop audio stream Param[1]: stream (type: AudioStream) -Function 569: SetAudioStreamVolume() (2 input parameters) +Function 571: SetAudioStreamVolume() (2 input parameters) Name: SetAudioStreamVolume Return type: void Description: Set volume for audio stream (1.0 is max level) Param[1]: stream (type: AudioStream) Param[2]: volume (type: float) -Function 570: SetAudioStreamPitch() (2 input parameters) +Function 572: SetAudioStreamPitch() (2 input parameters) Name: SetAudioStreamPitch Return type: void Description: Set pitch for audio stream (1.0 is base level) Param[1]: stream (type: AudioStream) Param[2]: pitch (type: float) -Function 571: SetAudioStreamPan() (2 input parameters) +Function 573: SetAudioStreamPan() (2 input parameters) Name: SetAudioStreamPan Return type: void Description: Set pan for audio stream (0.5 is centered) Param[1]: stream (type: AudioStream) Param[2]: pan (type: float) -Function 572: SetAudioStreamBufferSizeDefault() (1 input parameters) +Function 574: SetAudioStreamBufferSizeDefault() (1 input parameters) Name: SetAudioStreamBufferSizeDefault Return type: void Description: Default size for new audio streams Param[1]: size (type: int) -Function 573: SetAudioStreamCallback() (2 input parameters) +Function 575: SetAudioStreamCallback() (2 input parameters) Name: SetAudioStreamCallback Return type: void Description: Audio thread callback to request new data Param[1]: stream (type: AudioStream) Param[2]: callback (type: AudioCallback) -Function 574: AttachAudioStreamProcessor() (2 input parameters) +Function 576: AttachAudioStreamProcessor() (2 input parameters) Name: AttachAudioStreamProcessor Return type: void Description: Attach audio stream processor to stream, receives the samples as 'float' Param[1]: stream (type: AudioStream) Param[2]: processor (type: AudioCallback) -Function 575: DetachAudioStreamProcessor() (2 input parameters) +Function 577: DetachAudioStreamProcessor() (2 input parameters) Name: DetachAudioStreamProcessor Return type: void Description: Detach audio stream processor from stream Param[1]: stream (type: AudioStream) Param[2]: processor (type: AudioCallback) -Function 576: AttachAudioMixedProcessor() (1 input parameters) +Function 578: AttachAudioMixedProcessor() (1 input parameters) Name: AttachAudioMixedProcessor Return type: void Description: Attach audio stream processor to the entire audio pipeline, receives the samples as 'float' Param[1]: processor (type: AudioCallback) -Function 577: DetachAudioMixedProcessor() (1 input parameters) +Function 579: DetachAudioMixedProcessor() (1 input parameters) Name: DetachAudioMixedProcessor Return type: void Description: Detach audio stream processor from the entire audio pipeline diff --git a/parser/output/raylib_api.xml b/parser/output/raylib_api.xml index 73ce0dae7..25b253224 100644 --- a/parser/output/raylib_api.xml +++ b/parser/output/raylib_api.xml @@ -675,7 +675,7 @@ - + @@ -1126,6 +1126,14 @@ + + + + + + + + From 8cbf34ddc495e2bca42245f786915c27210b0507 Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 16 Oct 2024 19:26:12 +0200 Subject: [PATCH 128/208] WARNING: BREAKING: Renamed several functions for data validation #3930 --- src/raudio.c | 16 ++++++++-------- src/raylib.h | 22 +++++++++++----------- src/rcore.c | 6 +++--- src/rlgl.h | 1 - src/rmodels.c | 30 ++++++++++++++++++++++++------ src/rtext.c | 11 +++++------ src/rtextures.c | 30 +++++++++++++++--------------- 7 files changed, 66 insertions(+), 50 deletions(-) diff --git a/src/raudio.c b/src/raudio.c index 79d53b565..15859a661 100644 --- a/src/raudio.c +++ b/src/raudio.c @@ -892,8 +892,8 @@ Wave LoadWaveFromMemory(const char *fileType, const unsigned char *fileData, int return wave; } -// Checks if wave data is ready -bool IsWaveReady(Wave wave) +// Checks if wave data is valid (data loaded and parameters) +bool IsWaveValid(Wave wave) { bool result = false; @@ -993,8 +993,8 @@ Sound LoadSoundAlias(Sound source) } -// Checks if a sound is ready -bool IsSoundReady(Sound sound) +// Checks if a sound is valid (data loaded and buffers initialized) +bool IsSoundValid(Sound sound) { bool result = false; @@ -1726,8 +1726,8 @@ Music LoadMusicStreamFromMemory(const char *fileType, const unsigned char *data, return music; } -// Checks if a music stream is ready -bool IsMusicReady(Music music) +// Checks if a music stream is valid (context and buffers initialized) +bool IsMusicValid(Music music) { return ((music.ctxData != NULL) && // Validate context loaded (music.frameCount > 0) && // Validate audio frame count @@ -2119,8 +2119,8 @@ AudioStream LoadAudioStream(unsigned int sampleRate, unsigned int sampleSize, un return stream; } -// Checks if an audio stream is ready -bool IsAudioStreamReady(AudioStream stream) +// Checks if an audio stream is valid (buffers initialized) +bool IsAudioStreamValid(AudioStream stream) { return ((stream.buffer != NULL) && // Validate stream buffer (stream.sampleRate > 0) && // Validate sample rate is supported diff --git a/src/raylib.h b/src/raylib.h index 0ac4b603c..12a9e9fd2 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -1044,7 +1044,7 @@ RLAPI void UnloadVrStereoConfig(VrStereoConfig config); // Unload VR s // NOTE: Shader functionality is not available on OpenGL 1.1 RLAPI Shader LoadShader(const char *vsFileName, const char *fsFileName); // Load shader from files and bind default locations RLAPI Shader LoadShaderFromMemory(const char *vsCode, const char *fsCode); // Load shader from code strings and bind default locations -RLAPI bool IsShaderReady(Shader shader); // Check if a shader is ready +RLAPI bool IsShaderValid(Shader shader); // Check if a shader is valid (loaded on GPU) RLAPI int GetShaderLocation(Shader shader, const char *uniformName); // Get shader uniform location RLAPI int GetShaderLocationAttrib(Shader shader, const char *attribName); // Get shader attribute location RLAPI void SetShaderValue(Shader shader, int locIndex, const void *value, int uniformType); // Set shader uniform value @@ -1319,7 +1319,7 @@ RLAPI Image LoadImageAnimFromMemory(const char *fileType, const unsigned char *f RLAPI Image LoadImageFromMemory(const char *fileType, const unsigned char *fileData, int dataSize); // Load image from memory buffer, fileType refers to extension: i.e. '.png' RLAPI Image LoadImageFromTexture(Texture2D texture); // Load image from GPU texture data RLAPI Image LoadImageFromScreen(void); // Load image from screen buffer and (screenshot) -RLAPI bool IsImageReady(Image image); // Check if an image is ready +RLAPI bool IsImageValid(Image image); // Check if an image is valid (data and parameters) RLAPI void UnloadImage(Image image); // Unload image from CPU memory (RAM) RLAPI bool ExportImage(Image image, const char *fileName); // Export image data to file, returns true on success RLAPI unsigned char *ExportImageToMemory(Image image, const char *fileType, int *fileSize); // Export image to memory buffer @@ -1405,9 +1405,9 @@ RLAPI Texture2D LoadTexture(const char *fileName); RLAPI Texture2D LoadTextureFromImage(Image image); // Load texture from image data RLAPI TextureCubemap LoadTextureCubemap(Image image, int layout); // Load cubemap from image, multiple image cubemap layouts supported RLAPI RenderTexture2D LoadRenderTexture(int width, int height); // Load texture for rendering (framebuffer) -RLAPI bool IsTextureReady(Texture2D texture); // Check if a texture is ready +RLAPI bool IsTextureValid(Texture2D texture); // Check if a texture is valid (loaded in GPU) RLAPI void UnloadTexture(Texture2D texture); // Unload texture from GPU memory (VRAM) -RLAPI bool IsRenderTextureReady(RenderTexture2D target); // Check if a render texture is ready +RLAPI bool IsRenderTextureValid(RenderTexture2D target); // Check if a render texture is valid (loaded in GPU) RLAPI void UnloadRenderTexture(RenderTexture2D target); // Unload render texture from GPU memory (VRAM) RLAPI void UpdateTexture(Texture2D texture, const void *pixels); // Update GPU texture with new data RLAPI void UpdateTextureRec(Texture2D texture, Rectangle rec, const void *pixels); // Update GPU texture rectangle with new data @@ -1454,7 +1454,7 @@ RLAPI Font LoadFont(const char *fileName); RLAPI Font LoadFontEx(const char *fileName, int fontSize, int *codepoints, int codepointCount); // Load font from file with extended parameters, use NULL for codepoints and 0 for codepointCount to load the default character set, font size is provided in pixels height 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 *codepoints, int codepointCount); // Load font from memory buffer, fileType refers to extension: i.e. '.ttf' -RLAPI bool IsFontReady(Font font); // Check if a font is ready +RLAPI bool IsFontValid(Font font); // Check if a font is valid (font data loaded, WARNING: GPU texture not checked) RLAPI GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSize, int *codepoints, int codepointCount, int type); // Load font data for further use RLAPI Image GenImageFontAtlas(const GlyphInfo *glyphs, Rectangle **glyphRecs, int glyphCount, int fontSize, int padding, int packMethod); // Generate image font atlas using chars info RLAPI void UnloadFontData(GlyphInfo *glyphs, int glyphCount); // Unload font chars info data (RAM) @@ -1544,7 +1544,7 @@ RLAPI void DrawGrid(int slices, float spacing); // Model management functions RLAPI Model LoadModel(const char *fileName); // Load model from files (meshes and materials) RLAPI Model LoadModelFromMesh(Mesh mesh); // Load model from generated mesh (default material) -RLAPI bool IsModelReady(Model model); // Check if a model is ready +RLAPI bool IsModelValid(Model model); // Check if a model is valid (loaded in GPU, VAO/VBOs) RLAPI void UnloadModel(Model model); // Unload model (including meshes) from memory (RAM and/or VRAM) RLAPI BoundingBox GetModelBoundingBox(Model model); // Compute model bounding box limits (considers all meshes) @@ -1587,7 +1587,7 @@ RLAPI Mesh GenMeshCubicmap(Image cubicmap, Vector3 cubeSize); // Material loading/unloading functions RLAPI Material *LoadMaterials(const char *fileName, int *materialCount); // Load materials from model file RLAPI Material LoadMaterialDefault(void); // Load default material (Supports: DIFFUSE, SPECULAR, NORMAL maps) -RLAPI bool IsMaterialReady(Material material); // Check if a material is ready +RLAPI bool IsMaterialValid(Material material); // Check if a material is valid (shader assigned, map textures loaded in GPU) RLAPI void UnloadMaterial(Material material); // Unload material from GPU memory (VRAM) RLAPI void SetMaterialTexture(Material *material, int mapType, Texture2D texture); // Set texture for a material map type (MATERIAL_MAP_DIFFUSE, MATERIAL_MAP_SPECULAR...) RLAPI void SetModelMeshMaterial(Model *model, int meshId, int materialId); // Set material for a mesh @@ -1625,11 +1625,11 @@ RLAPI float GetMasterVolume(void); // Get mas // Wave/Sound loading/unloading functions RLAPI Wave LoadWave(const char *fileName); // Load wave data from file RLAPI Wave LoadWaveFromMemory(const char *fileType, const unsigned char *fileData, int dataSize); // Load wave from memory buffer, fileType refers to extension: i.e. '.wav' -RLAPI bool IsWaveReady(Wave wave); // Checks if wave data is ready +RLAPI bool IsWaveValid(Wave wave); // Checks if wave data is valid (data loaded and parameters) RLAPI Sound LoadSound(const char *fileName); // Load sound from file RLAPI Sound LoadSoundFromWave(Wave wave); // Load sound from wave data RLAPI Sound LoadSoundAlias(Sound source); // Create a new sound that shares the same sample data as the source sound, does not own the sound data -RLAPI bool IsSoundReady(Sound sound); // Checks if a sound is ready +RLAPI bool IsSoundValid(Sound sound); // Checks if a sound is valid (data loaded and buffers initialized) RLAPI void UpdateSound(Sound sound, const void *data, int sampleCount); // Update sound buffer with new data RLAPI void UnloadWave(Wave wave); // Unload wave data RLAPI void UnloadSound(Sound sound); // Unload sound @@ -1655,7 +1655,7 @@ RLAPI void UnloadWaveSamples(float *samples); // Unload // Music management functions RLAPI Music LoadMusicStream(const char *fileName); // Load music stream from file RLAPI Music LoadMusicStreamFromMemory(const char *fileType, const unsigned char *data, int dataSize); // Load music stream from data -RLAPI bool IsMusicReady(Music music); // Checks if a music stream is ready +RLAPI bool IsMusicValid(Music music); // Checks if a music stream is valid (context and buffers initialized) RLAPI void UnloadMusicStream(Music music); // Unload music stream RLAPI void PlayMusicStream(Music music); // Start music playing RLAPI bool IsMusicStreamPlaying(Music music); // Check if music is playing @@ -1672,7 +1672,7 @@ RLAPI float GetMusicTimePlayed(Music music); // Get cur // AudioStream management functions RLAPI AudioStream LoadAudioStream(unsigned int sampleRate, unsigned int sampleSize, unsigned int channels); // Load audio stream (to stream raw audio pcm data) -RLAPI bool IsAudioStreamReady(AudioStream stream); // Checks if an audio stream is ready +RLAPI bool IsAudioStreamValid(AudioStream stream); // Checks if an audio stream is valid (buffers initialized) RLAPI void UnloadAudioStream(AudioStream stream); // Unload audio stream and free memory RLAPI void UpdateAudioStream(AudioStream stream, const void *data, int frameCount); // Update audio stream buffers with data RLAPI bool IsAudioStreamProcessed(AudioStream stream); // Check if any audio stream buffers requires refill diff --git a/src/rcore.c b/src/rcore.c index 8ba72f715..8fa4217fb 100644 --- a/src/rcore.c +++ b/src/rcore.c @@ -1342,10 +1342,10 @@ Shader LoadShaderFromMemory(const char *vsCode, const char *fsCode) return shader; } -// Check if a shader is ready -bool IsShaderReady(Shader shader) +// Check if a shader is valid (loaded on GPU) +bool IsShaderValid(Shader shader) { - return ((shader.id > 0) && // Validate shader id (loaded successfully) + return ((shader.id > 0) && // Validate shader id (GPU loaded successfully) (shader.locs != NULL)); // Validate memory has been allocated for default shader locations // The following locations are tried to be set automatically (locs[i] >= 0), diff --git a/src/rlgl.h b/src/rlgl.h index 1695c2f56..e4e659ac9 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -347,7 +347,6 @@ #ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_INDICES #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_INDICES 6 #endif - #ifdef RL_SUPPORT_MESH_GPU_SKINNING #ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS 7 diff --git a/src/rmodels.c b/src/rmodels.c index 92be04fca..9d9c47519 100644 --- a/src/rmodels.c +++ b/src/rmodels.c @@ -1155,8 +1155,8 @@ Model LoadModelFromMesh(Mesh mesh) return model; } -// Check if a model is ready -bool IsModelReady(Model model) +// Check if a model is valid (loaded in GPU, VAO/VBOs) +bool IsModelValid(Model model) { bool result = false; @@ -1165,8 +1165,24 @@ bool IsModelReady(Model model) (model.meshMaterial != NULL) && // Validate mesh-material linkage (model.meshCount > 0) && // Validate mesh count (model.materialCount > 0)) result = true; // Validate material count - - // NOTE: This is a very general model validation, many elements could be validated from a model... + + // NOTE: Many elements could be validated from a model, including every model mesh VAO/VBOs + // but some VBOs could not be used, it depends on Mesh vertex data + for (int i = 0; i < model.meshCount; i++) + { + if ((model.meshes[i].vertices != NULL) && (model.meshes[i].vboId[0] == 0)) { result = false; break; } // Vertex position buffer not uploaded to GPU + if ((model.meshes[i].texcoords != NULL) && (model.meshes[i].vboId[1] == 0)) { result = false; break; } // Vertex textcoords buffer not uploaded to GPU + if ((model.meshes[i].normals != NULL) && (model.meshes[i].vboId[2] == 0)) { result = false; break; } // Vertex normals buffer not uploaded to GPU + if ((model.meshes[i].colors != NULL) && (model.meshes[i].vboId[3] == 0)) { result = false; break; } // Vertex colors buffer not uploaded to GPU + if ((model.meshes[i].tangents != NULL) && (model.meshes[i].vboId[4] == 0)) { result = false; break; } // Vertex tangents buffer not uploaded to GPU + if ((model.meshes[i].texcoords2 != NULL) && (model.meshes[i].vboId[5] == 0)) { result = false; break; } // Vertex texcoords2 buffer not uploaded to GPU + if ((model.meshes[i].indices != NULL) && (model.meshes[i].vboId[6] == 0)) { result = false; break; } // Vertex indices buffer not uploaded to GPU + if ((model.meshes[i].boneIds != NULL) && (model.meshes[i].vboId[7] == 0)) { result = false; break; } // Vertex boneIds buffer not uploaded to GPU + if ((model.meshes[i].boneWeights != NULL) && (model.meshes[i].vboId[8] == 0)) { result = false; break; } // Vertex boneWeights buffer not uploaded to GPU + + // NOTE: Some OpenGL versions do not support VAO, so we don't check it + //if (model.meshes[i].vaoId == 0) { result = false; break } + } return result; } @@ -2182,13 +2198,15 @@ Material LoadMaterialDefault(void) return material; } -// Check if a material is ready -bool IsMaterialReady(Material material) +// Check if a material is valid (map textures loaded in GPU) +bool IsMaterialValid(Material material) { bool result = false; if ((material.maps != NULL) && // Validate material contain some map (material.shader.id > 0)) result = true; // Validate material shader is valid + + // TODO: Check if available maps contain loaded textures return result; } diff --git a/src/rtext.c b/src/rtext.c index 0595e7fbe..86aeb0047 100644 --- a/src/rtext.c +++ b/src/rtext.c @@ -581,17 +581,16 @@ Font LoadFontFromMemory(const char *fileType, const unsigned char *fileData, int return font; } -// Check if a font is ready -bool IsFontReady(Font font) +// Check if a font is valid (font data loaded) +// WARNING: GPU texture not checked +bool IsFontValid(Font font) { - return ((font.texture.id > 0) && // Validate OpenGL id for font texture atlas - (font.baseSize > 0) && // Validate font size + return ((font.baseSize > 0) && // Validate font size (font.glyphCount > 0) && // Validate font contains some glyph (font.recs != NULL) && // Validate font recs defining glyphs on texture atlas (font.glyphs != NULL)); // Validate glyph data is loaded - // NOTE: Further validations could be done to verify if recs count and glyphs count - // match glyphCount and to verify that data contained is valid (glyphs values, metrics...) + // NOTE: Further validations could be done to verify if recs and glyphs contain valid data (glyphs values, metrics...) } // Load font data for further use diff --git a/src/rtextures.c b/src/rtextures.c index 84264369d..294eeb6ad 100644 --- a/src/rtextures.c +++ b/src/rtextures.c @@ -600,15 +600,15 @@ Image LoadImageFromScreen(void) } // Check if an image is ready -bool IsImageReady(Image image) +bool IsImageValid(Image image) { bool result = false; if ((image.data != NULL) && // Validate pixel data available - (image.width > 0) && - (image.height > 0) && // Validate image size + (image.width > 0) && // Validate image width + (image.height > 0) && // Validate image height (image.format > 0) && // Validate image format - (image.mipmaps > 0)) result = true; // Validate image mipmaps (at least 1 for basic mipmap level) + (image.mipmaps > 0)) result = true; // Validate image mipmaps (at least 1 for basic mipmap level) return result; } @@ -4224,16 +4224,16 @@ RenderTexture2D LoadRenderTexture(int width, int height) return target; } -// Check if a texture is ready -bool IsTextureReady(Texture2D texture) +// Check if a texture is valid (loaded in GPU) +bool IsTextureValid(Texture2D texture) { bool result = false; - // TODO: Validate maximum texture size supported by GPU? + // TODO: Validate maximum texture size supported by GPU - if ((texture.id > 0) && // Validate OpenGL id - (texture.width > 0) && - (texture.height > 0) && // Validate texture size + if ((texture.id > 0) && // Validate OpenGL id (texture uplaoded to GPU) + (texture.width > 0) && // Validate texture width + (texture.height > 0) && // Validate texture height (texture.format > 0) && // Validate texture pixel format (texture.mipmaps > 0)) result = true; // Validate texture mipmaps (at least 1 for basic mipmap level) @@ -4251,14 +4251,14 @@ void UnloadTexture(Texture2D texture) } } -// Check if a render texture is ready -bool IsRenderTextureReady(RenderTexture2D target) +// Check if a render texture is valid (loaded in GPU) +bool IsRenderTextureValid(RenderTexture2D target) { bool result = false; - if ((target.id > 0) && // Validate OpenGL id - IsTextureReady(target.depth) && // Validate FBO depth texture/renderbuffer - IsTextureReady(target.texture)) result = true; // Validate FBO texture + if ((target.id > 0) && // Validate OpenGL id (loaded on GPU) + IsTextureValid(target.depth) && // Validate FBO depth texture/renderbuffer attachment + IsTextureValid(target.texture)) result = true; // Validate FBO texture attachment return result; } From d6399622a0280bc8ea458104b946f1860d928156 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 16 Oct 2024 17:26:49 +0000 Subject: [PATCH 129/208] Update raylib_api.* by CI --- parser/output/raylib_api.json | 44 +++++++++++------------ parser/output/raylib_api.lua | 44 +++++++++++------------ parser/output/raylib_api.txt | 66 +++++++++++++++++------------------ parser/output/raylib_api.xml | 22 ++++++------ 4 files changed, 88 insertions(+), 88 deletions(-) diff --git a/parser/output/raylib_api.json b/parser/output/raylib_api.json index f735853fb..1a2b49259 100644 --- a/parser/output/raylib_api.json +++ b/parser/output/raylib_api.json @@ -3763,8 +3763,8 @@ ] }, { - "name": "IsShaderReady", - "description": "Check if a shader is ready", + "name": "IsShaderValid", + "description": "Check if a shader is valid (loaded on GPU)", "returnType": "bool", "params": [ { @@ -6919,8 +6919,8 @@ "returnType": "Image" }, { - "name": "IsImageReady", - "description": "Check if an image is ready", + "name": "IsImageValid", + "description": "Check if an image is valid (data and parameters)", "returnType": "bool", "params": [ { @@ -8383,8 +8383,8 @@ ] }, { - "name": "IsTextureReady", - "description": "Check if a texture is ready", + "name": "IsTextureValid", + "description": "Check if a texture is valid (loaded in GPU)", "returnType": "bool", "params": [ { @@ -8405,8 +8405,8 @@ ] }, { - "name": "IsRenderTextureReady", - "description": "Check if a render texture is ready", + "name": "IsRenderTextureValid", + "description": "Check if a render texture is valid (loaded in GPU)", "returnType": "bool", "params": [ { @@ -9000,8 +9000,8 @@ ] }, { - "name": "IsFontReady", - "description": "Check if a font is ready", + "name": "IsFontValid", + "description": "Check if a font is valid (font data loaded, WARNING: GPU texture not checked)", "returnType": "bool", "params": [ { @@ -10292,8 +10292,8 @@ ] }, { - "name": "IsModelReady", - "description": "Check if a model is ready", + "name": "IsModelValid", + "description": "Check if a model is valid (loaded in GPU, VAO/VBOs)", "returnType": "bool", "params": [ { @@ -10979,8 +10979,8 @@ "returnType": "Material" }, { - "name": "IsMaterialReady", - "description": "Check if a material is ready", + "name": "IsMaterialValid", + "description": "Check if a material is valid (shader assigned, map textures loaded in GPU)", "returnType": "bool", "params": [ { @@ -11354,8 +11354,8 @@ ] }, { - "name": "IsWaveReady", - "description": "Checks if wave data is ready", + "name": "IsWaveValid", + "description": "Checks if wave data is valid (data loaded and parameters)", "returnType": "bool", "params": [ { @@ -11398,8 +11398,8 @@ ] }, { - "name": "IsSoundReady", - "description": "Checks if a sound is ready", + "name": "IsSoundValid", + "description": "Checks if a sound is valid (data loaded and buffers initialized)", "returnType": "bool", "params": [ { @@ -11696,8 +11696,8 @@ ] }, { - "name": "IsMusicReady", - "description": "Checks if a music stream is ready", + "name": "IsMusicValid", + "description": "Checks if a music stream is valid (context and buffers initialized)", "returnType": "bool", "params": [ { @@ -11885,8 +11885,8 @@ ] }, { - "name": "IsAudioStreamReady", - "description": "Checks if an audio stream is ready", + "name": "IsAudioStreamValid", + "description": "Checks if an audio stream is valid (buffers initialized)", "returnType": "bool", "params": [ { diff --git a/parser/output/raylib_api.lua b/parser/output/raylib_api.lua index 4c0dd5a03..5bb0e3200 100644 --- a/parser/output/raylib_api.lua +++ b/parser/output/raylib_api.lua @@ -3589,8 +3589,8 @@ return { } }, { - name = "IsShaderReady", - description = "Check if a shader is ready", + name = "IsShaderValid", + description = "Check if a shader is valid (loaded on GPU)", returnType = "bool", params = { {type = "Shader", name = "shader"} @@ -5401,8 +5401,8 @@ return { returnType = "Image" }, { - name = "IsImageReady", - description = "Check if an image is ready", + name = "IsImageValid", + description = "Check if an image is valid (data and parameters)", returnType = "bool", params = { {type = "Image", name = "image"} @@ -6166,8 +6166,8 @@ return { } }, { - name = "IsTextureReady", - description = "Check if a texture is ready", + name = "IsTextureValid", + description = "Check if a texture is valid (loaded in GPU)", returnType = "bool", params = { {type = "Texture2D", name = "texture"} @@ -6182,8 +6182,8 @@ return { } }, { - name = "IsRenderTextureReady", - description = "Check if a render texture is ready", + name = "IsRenderTextureValid", + description = "Check if a render texture is valid (loaded in GPU)", returnType = "bool", params = { {type = "RenderTexture2D", name = "target"} @@ -6513,8 +6513,8 @@ return { } }, { - name = "IsFontReady", - description = "Check if a font is ready", + name = "IsFontValid", + description = "Check if a font is valid (font data loaded, WARNING: GPU texture not checked)", returnType = "bool", params = { {type = "Font", name = "font"} @@ -7193,8 +7193,8 @@ return { } }, { - name = "IsModelReady", - description = "Check if a model is ready", + name = "IsModelValid", + description = "Check if a model is valid (loaded in GPU, VAO/VBOs)", returnType = "bool", params = { {type = "Model", name = "model"} @@ -7547,8 +7547,8 @@ return { returnType = "Material" }, { - name = "IsMaterialReady", - description = "Check if a material is ready", + name = "IsMaterialValid", + description = "Check if a material is valid (shader assigned, map textures loaded in GPU)", returnType = "bool", params = { {type = "Material", name = "material"} @@ -7766,8 +7766,8 @@ return { } }, { - name = "IsWaveReady", - description = "Checks if wave data is ready", + name = "IsWaveValid", + description = "Checks if wave data is valid (data loaded and parameters)", returnType = "bool", params = { {type = "Wave", name = "wave"} @@ -7798,8 +7798,8 @@ return { } }, { - name = "IsSoundReady", - description = "Checks if a sound is ready", + name = "IsSoundValid", + description = "Checks if a sound is valid (data loaded and buffers initialized)", returnType = "bool", params = { {type = "Sound", name = "sound"} @@ -7988,8 +7988,8 @@ return { } }, { - name = "IsMusicReady", - description = "Checks if a music stream is ready", + name = "IsMusicValid", + description = "Checks if a music stream is valid (context and buffers initialized)", returnType = "bool", params = { {type = "Music", name = "music"} @@ -8114,8 +8114,8 @@ return { } }, { - name = "IsAudioStreamReady", - description = "Checks if an audio stream is ready", + name = "IsAudioStreamValid", + description = "Checks if an audio stream is valid (buffers initialized)", returnType = "bool", params = { {type = "AudioStream", name = "stream"} diff --git a/parser/output/raylib_api.txt b/parser/output/raylib_api.txt index 865e5ae78..9893eb4c6 100644 --- a/parser/output/raylib_api.txt +++ b/parser/output/raylib_api.txt @@ -1378,10 +1378,10 @@ Function 075: LoadShaderFromMemory() (2 input parameters) Description: Load shader from code strings and bind default locations Param[1]: vsCode (type: const char *) Param[2]: fsCode (type: const char *) -Function 076: IsShaderReady() (1 input parameters) - Name: IsShaderReady +Function 076: IsShaderValid() (1 input parameters) + Name: IsShaderValid Return type: bool - Description: Check if a shader is ready + Description: Check if a shader is valid (loaded on GPU) Param[1]: shader (type: Shader) Function 077: GetShaderLocation() (2 input parameters) Name: GetShaderLocation @@ -2674,10 +2674,10 @@ Function 279: LoadImageFromScreen() (0 input parameters) Return type: Image Description: Load image from screen buffer and (screenshot) No input parameters -Function 280: IsImageReady() (1 input parameters) - Name: IsImageReady +Function 280: IsImageValid() (1 input parameters) + Name: IsImageValid Return type: bool - Description: Check if an image is ready + Description: Check if an image is valid (data and parameters) Param[1]: image (type: Image) Function 281: UnloadImage() (1 input parameters) Name: UnloadImage @@ -3211,20 +3211,20 @@ Function 355: LoadRenderTexture() (2 input parameters) Description: Load texture for rendering (framebuffer) Param[1]: width (type: int) Param[2]: height (type: int) -Function 356: IsTextureReady() (1 input parameters) - Name: IsTextureReady +Function 356: IsTextureValid() (1 input parameters) + Name: IsTextureValid Return type: bool - Description: Check if a texture is ready + Description: Check if a texture is valid (loaded in GPU) Param[1]: texture (type: Texture2D) Function 357: UnloadTexture() (1 input parameters) Name: UnloadTexture Return type: void Description: Unload texture from GPU memory (VRAM) Param[1]: texture (type: Texture2D) -Function 358: IsRenderTextureReady() (1 input parameters) - Name: IsRenderTextureReady +Function 358: IsRenderTextureValid() (1 input parameters) + Name: IsRenderTextureValid Return type: bool - Description: Check if a render texture is ready + Description: Check if a render texture is valid (loaded in GPU) Param[1]: target (type: RenderTexture2D) Function 359: UnloadRenderTexture() (1 input parameters) Name: UnloadRenderTexture @@ -3450,10 +3450,10 @@ Function 392: LoadFontFromMemory() (6 input parameters) Param[4]: fontSize (type: int) Param[5]: codepoints (type: int *) Param[6]: codepointCount (type: int) -Function 393: IsFontReady() (1 input parameters) - Name: IsFontReady +Function 393: IsFontValid() (1 input parameters) + Name: IsFontValid Return type: bool - Description: Check if a font is ready + Description: Check if a font is valid (font data loaded, WARNING: GPU texture not checked) Param[1]: font (type: Font) Function 394: LoadFontData() (6 input parameters) Name: LoadFontData @@ -3926,10 +3926,10 @@ Function 460: LoadModelFromMesh() (1 input parameters) Return type: Model Description: Load model from generated mesh (default material) Param[1]: mesh (type: Mesh) -Function 461: IsModelReady() (1 input parameters) - Name: IsModelReady +Function 461: IsModelValid() (1 input parameters) + Name: IsModelValid Return type: bool - Description: Check if a model is ready + Description: Check if a model is valid (loaded in GPU, VAO/VBOs) Param[1]: model (type: Model) Function 462: UnloadModel() (1 input parameters) Name: UnloadModel @@ -4178,10 +4178,10 @@ Function 495: LoadMaterialDefault() (0 input parameters) Return type: Material Description: Load default material (Supports: DIFFUSE, SPECULAR, NORMAL maps) No input parameters -Function 496: IsMaterialReady() (1 input parameters) - Name: IsMaterialReady +Function 496: IsMaterialValid() (1 input parameters) + Name: IsMaterialValid Return type: bool - Description: Check if a material is ready + Description: Check if a material is valid (shader assigned, map textures loaded in GPU) Param[1]: material (type: Material) Function 497: UnloadMaterial() (1 input parameters) Name: UnloadMaterial @@ -4334,10 +4334,10 @@ Function 520: LoadWaveFromMemory() (3 input parameters) Param[1]: fileType (type: const char *) Param[2]: fileData (type: const unsigned char *) Param[3]: dataSize (type: int) -Function 521: IsWaveReady() (1 input parameters) - Name: IsWaveReady +Function 521: IsWaveValid() (1 input parameters) + Name: IsWaveValid Return type: bool - Description: Checks if wave data is ready + Description: Checks if wave data is valid (data loaded and parameters) Param[1]: wave (type: Wave) Function 522: LoadSound() (1 input parameters) Name: LoadSound @@ -4354,10 +4354,10 @@ Function 524: LoadSoundAlias() (1 input parameters) Return type: Sound Description: Create a new sound that shares the same sample data as the source sound, does not own the sound data Param[1]: source (type: Sound) -Function 525: IsSoundReady() (1 input parameters) - Name: IsSoundReady +Function 525: IsSoundValid() (1 input parameters) + Name: IsSoundValid Return type: bool - Description: Checks if a sound is ready + Description: Checks if a sound is valid (data loaded and buffers initialized) Param[1]: sound (type: Sound) Function 526: UpdateSound() (3 input parameters) Name: UpdateSound @@ -4478,10 +4478,10 @@ Function 546: LoadMusicStreamFromMemory() (3 input parameters) Param[1]: fileType (type: const char *) Param[2]: data (type: const unsigned char *) Param[3]: dataSize (type: int) -Function 547: IsMusicReady() (1 input parameters) - Name: IsMusicReady +Function 547: IsMusicValid() (1 input parameters) + Name: IsMusicValid Return type: bool - Description: Checks if a music stream is ready + Description: Checks if a music stream is valid (context and buffers initialized) Param[1]: music (type: Music) Function 548: UnloadMusicStream() (1 input parameters) Name: UnloadMusicStream @@ -4559,10 +4559,10 @@ Function 561: LoadAudioStream() (3 input parameters) Param[1]: sampleRate (type: unsigned int) Param[2]: sampleSize (type: unsigned int) Param[3]: channels (type: unsigned int) -Function 562: IsAudioStreamReady() (1 input parameters) - Name: IsAudioStreamReady +Function 562: IsAudioStreamValid() (1 input parameters) + Name: IsAudioStreamValid Return type: bool - Description: Checks if an audio stream is ready + Description: Checks if an audio stream is valid (buffers initialized) Param[1]: stream (type: AudioStream) Function 563: UnloadAudioStream() (1 input parameters) Name: UnloadAudioStream diff --git a/parser/output/raylib_api.xml b/parser/output/raylib_api.xml index 25b253224..eb53437eb 100644 --- a/parser/output/raylib_api.xml +++ b/parser/output/raylib_api.xml @@ -871,7 +871,7 @@ - + @@ -1727,7 +1727,7 @@ - + @@ -2112,13 +2112,13 @@ - + - + @@ -2276,7 +2276,7 @@ - + @@ -2616,7 +2616,7 @@ - + @@ -2797,7 +2797,7 @@ - + @@ -2899,7 +2899,7 @@ - + @@ -2911,7 +2911,7 @@ - + @@ -2991,7 +2991,7 @@ - + @@ -3042,7 +3042,7 @@ - + From a2e31c4e1ba7b2ab0c4b87c70e88fa365b02f652 Mon Sep 17 00:00:00 2001 From: Asdqwe Date: Thu, 17 Oct 2024 10:35:49 -0300 Subject: [PATCH 130/208] Fix #4388 (#4392) --- src/platforms/rcore_desktop_sdl.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/platforms/rcore_desktop_sdl.c b/src/platforms/rcore_desktop_sdl.c index 90372c2f6..b4ceb78eb 100644 --- a/src/platforms/rcore_desktop_sdl.c +++ b/src/platforms/rcore_desktop_sdl.c @@ -1609,7 +1609,6 @@ int InitPlatform(void) //---------------------------------------------------------------------------- // Define base path for storage CORE.Storage.basePath = SDL_GetBasePath(); // Alternative: GetWorkingDirectory(); - CHDIR(CORE.Storage.basePath); //---------------------------------------------------------------------------- TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (SDL): Initialized successfully"); From b201b74c3fcc4d146b67dd7f9bbd61a3f490e28e Mon Sep 17 00:00:00 2001 From: Alan Arrecis Date: Thu, 17 Oct 2024 17:08:07 -0600 Subject: [PATCH 131/208] Fix VSCode Makefile to support multiple .c files (#4391) Updated the VSCode Makefile to allow compilation of multiple .c files instead of just one (main.c). - Replaced `SRC` and `OBJS` definitions to dynamically include all .c and .h files in the project. - This change enables automatic handling of any number of source files specifically in the VSCode setup. --- projects/VSCode/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/projects/VSCode/Makefile b/projects/VSCode/Makefile index 2f43c9ead..86febfba0 100644 --- a/projects/VSCode/Makefile +++ b/projects/VSCode/Makefile @@ -352,9 +352,9 @@ SRC_DIR = src OBJ_DIR = obj # Define all object files from source files -SRC = $(call rwildcard, *.c, *.h) +SRC = $(call rwildcard, ./, *.c, *.h) #OBJS = $(SRC:$(SRC_DIR)/%.c=$(OBJ_DIR)/%.o) -OBJS ?= main.c +OBJS = $(patsubst %.c,%.o,$(filter %.c,$(SRC))) # For Android platform we call a custom Makefile.Android ifeq ($(PLATFORM),PLATFORM_ANDROID) From 80393c0fb692f1042ae446a8a06df924cfa0fd70 Mon Sep 17 00:00:00 2001 From: Anthony Carbajal <5776225+CrackedPixel@users.noreply.github.com> Date: Thu, 17 Oct 2024 18:15:19 -0500 Subject: [PATCH 132/208] [rcore] added sha1 implementation (#4390) * added sha1 implementation * added missing part * fixed issue * fix to match other implementations --- src/raylib.h | 2 ++ src/rcore.c | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 98 insertions(+) diff --git a/src/raylib.h b/src/raylib.h index 12a9e9fd2..5ae45fa9d 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -1146,6 +1146,8 @@ RLAPI char *EncodeDataBase64(const unsigned char *data, int dataSize, int *outpu RLAPI unsigned char *DecodeDataBase64(const unsigned char *data, int *outputSize); // Decode Base64 string data, memory must be MemFree() RLAPI unsigned int ComputeCRC32(unsigned char *data, int dataSize); // Compute CRC32 hash code RLAPI unsigned int *ComputeMD5(unsigned char *data, int dataSize); // Compute MD5 hash code, returns static int[4] (16 bytes) +RLAPI unsigned int *ComputeSHA1(unsigned char *data, int dataSize); // Compute SHA1 hash code, returns static int[5] (20 bytes) + // Automation events functionality RLAPI AutomationEventList LoadAutomationEventList(const char *fileName); // Load automation events list from file, NULL for empty list, capacity = MAX_AUTOMATION_EVENTS diff --git a/src/rcore.c b/src/rcore.c index 8fa4217fb..9b3eeee80 100644 --- a/src/rcore.c +++ b/src/rcore.c @@ -2740,6 +2740,102 @@ unsigned int *ComputeMD5(unsigned char *data, int dataSize) return hash; } +// Compute SHA-1 hash code +// NOTE: Returns a static int[5] array (20 bytes) +unsigned int *ComputeSHA1(unsigned char *data, int dataSize) { + #define ROTATE_LEFT(x, c) (((x) << (c)) | ((x) >> (32 - (c)))) + + static unsigned int hash[5] = { 0 }; // Hash to be returned + + // Initialize hash values + hash[0] = 0x67452301; + hash[1] = 0xEFCDAB89; + hash[2] = 0x98BADCFE; + hash[3] = 0x10325476; + hash[4] = 0xC3D2E1F0; + + // Pre-processing: adding a single 1 bit + // Append '1' bit to message + // NOTE: The input bytes are considered as bits strings, + // where the first bit is the most significant bit of the byte + + // Pre-processing: padding with zeros + // Append '0' bit until message length in bit 448 (mod 512) + // Append length mod (2 pow 64) to message + + int newDataSize = ((((dataSize + 8)/64) + 1)*64); + + unsigned char *msg = RL_CALLOC(newDataSize, 1); // Initialize with '0' bits + memcpy(msg, data, dataSize); + msg[dataSize] = 128; // Write the '1' bit + + unsigned int bitsLen = 8*dataSize; + msg[newDataSize-1] = bitsLen; + + // Process the message in successive 512-bit chunks + for (int offset = 0; offset < newDataSize; offset += (512/8)) + { + // Break chunk into sixteen 32-bit words w[j], 0 <= j <= 15 + unsigned int w[80] = {0}; + for (int i = 0; i < 16; i++) { + w[i] = (msg[offset + (i * 4) + 0] << 24) | + (msg[offset + (i * 4) + 1] << 16) | + (msg[offset + (i * 4) + 2] << 8) | + (msg[offset + (i * 4) + 3]); + } + + // Message schedule: extend the sixteen 32-bit words into eighty 32-bit words: + for (int i = 16; i < 80; ++i) { + w[i] = ROTATE_LEFT(w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16], 1); + } + + // Initialize hash value for this chunk + unsigned int a = hash[0]; + unsigned int b = hash[1]; + unsigned int c = hash[2]; + unsigned int d = hash[3]; + unsigned int e = hash[4]; + + for (int i = 0; i < 80; i++) + { + unsigned int f = 0; + unsigned int k = 0; + + if (i < 20) { + f = (b & c) | ((~b) & d); + k = 0x5A827999; + } else if (i < 40) { + f = b ^ c ^ d; + k = 0x6ED9EBA1; + } else if (i < 60) { + f = (b & c) | (b & d) | (c & d); + k = 0x8F1BBCDC; + } else { + f = b ^ c ^ d; + k = 0xCA62C1D6; + } + + unsigned int temp = ROTATE_LEFT(a, 5) + f + e + k + w[i]; + e = d; + d = c; + c = ROTATE_LEFT(b, 30); + b = a; + a = temp; + } + + // Add this chunk's hash to result so far + hash[0] += a; + hash[1] += b; + hash[2] += c; + hash[3] += d; + hash[4] += e; + } + + free(msg); + + return hash; +} + //---------------------------------------------------------------------------------- // Module Functions Definition: Automation Events Recording and Playing //---------------------------------------------------------------------------------- From c6d67f006d05760d69a40ac6bcdc9ecb8e30373f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 17 Oct 2024 23:15:33 +0000 Subject: [PATCH 133/208] Update raylib_api.* by CI --- parser/output/raylib_api.json | 15 + parser/output/raylib_api.lua | 9 + parser/output/raylib_api.txt | 866 +++++++++++++++++----------------- parser/output/raylib_api.xml | 6 +- 4 files changed, 465 insertions(+), 431 deletions(-) diff --git a/parser/output/raylib_api.json b/parser/output/raylib_api.json index 1a2b49259..fca3ef72c 100644 --- a/parser/output/raylib_api.json +++ b/parser/output/raylib_api.json @@ -4721,6 +4721,21 @@ } ] }, + { + "name": "ComputeSHA1", + "description": "Compute SHA1 hash code, returns static int[5] (20 bytes)", + "returnType": "unsigned int *", + "params": [ + { + "type": "unsigned char *", + "name": "data" + }, + { + "type": "int", + "name": "dataSize" + } + ] + }, { "name": "LoadAutomationEventList", "description": "Load automation events list from file, NULL for empty list, capacity = MAX_AUTOMATION_EVENTS", diff --git a/parser/output/raylib_api.lua b/parser/output/raylib_api.lua index 5bb0e3200..572b4332a 100644 --- a/parser/output/raylib_api.lua +++ b/parser/output/raylib_api.lua @@ -4208,6 +4208,15 @@ return { {type = "int", name = "dataSize"} } }, + { + name = "ComputeSHA1", + description = "Compute SHA1 hash code, returns static int[5] (20 bytes)", + returnType = "unsigned int *", + params = { + {type = "unsigned char *", name = "data"}, + {type = "int", name = "dataSize"} + } + }, { name = "LoadAutomationEventList", description = "Load automation events list from file, NULL for empty list, capacity = MAX_AUTOMATION_EVENTS", diff --git a/parser/output/raylib_api.txt b/parser/output/raylib_api.txt index 9893eb4c6..1fd591151 100644 --- a/parser/output/raylib_api.txt +++ b/parser/output/raylib_api.txt @@ -989,7 +989,7 @@ Callback 006: AudioCallback() (2 input parameters) Param[1]: bufferData (type: void *) Param[2]: frames (type: unsigned int) -Functions found: 579 +Functions found: 580 Function 001: InitWindow() (3 input parameters) Name: InitWindow @@ -1800,294 +1800,300 @@ Function 150: ComputeMD5() (2 input parameters) Description: Compute MD5 hash code, returns static int[4] (16 bytes) Param[1]: data (type: unsigned char *) Param[2]: dataSize (type: int) -Function 151: LoadAutomationEventList() (1 input parameters) +Function 151: ComputeSHA1() (2 input parameters) + Name: ComputeSHA1 + Return type: unsigned int * + Description: Compute SHA1 hash code, returns static int[5] (20 bytes) + Param[1]: data (type: unsigned char *) + Param[2]: dataSize (type: int) +Function 152: LoadAutomationEventList() (1 input parameters) Name: LoadAutomationEventList Return type: AutomationEventList Description: Load automation events list from file, NULL for empty list, capacity = MAX_AUTOMATION_EVENTS Param[1]: fileName (type: const char *) -Function 152: UnloadAutomationEventList() (1 input parameters) +Function 153: UnloadAutomationEventList() (1 input parameters) Name: UnloadAutomationEventList Return type: void Description: Unload automation events list from file Param[1]: list (type: AutomationEventList) -Function 153: ExportAutomationEventList() (2 input parameters) +Function 154: ExportAutomationEventList() (2 input parameters) Name: ExportAutomationEventList Return type: bool Description: Export automation events list as text file Param[1]: list (type: AutomationEventList) Param[2]: fileName (type: const char *) -Function 154: SetAutomationEventList() (1 input parameters) +Function 155: SetAutomationEventList() (1 input parameters) Name: SetAutomationEventList Return type: void Description: Set automation event list to record to Param[1]: list (type: AutomationEventList *) -Function 155: SetAutomationEventBaseFrame() (1 input parameters) +Function 156: SetAutomationEventBaseFrame() (1 input parameters) Name: SetAutomationEventBaseFrame Return type: void Description: Set automation event internal base frame to start recording Param[1]: frame (type: int) -Function 156: StartAutomationEventRecording() (0 input parameters) +Function 157: StartAutomationEventRecording() (0 input parameters) Name: StartAutomationEventRecording Return type: void Description: Start recording automation events (AutomationEventList must be set) No input parameters -Function 157: StopAutomationEventRecording() (0 input parameters) +Function 158: StopAutomationEventRecording() (0 input parameters) Name: StopAutomationEventRecording Return type: void Description: Stop recording automation events No input parameters -Function 158: PlayAutomationEvent() (1 input parameters) +Function 159: PlayAutomationEvent() (1 input parameters) Name: PlayAutomationEvent Return type: void Description: Play a recorded automation event Param[1]: event (type: AutomationEvent) -Function 159: IsKeyPressed() (1 input parameters) +Function 160: IsKeyPressed() (1 input parameters) Name: IsKeyPressed Return type: bool Description: Check if a key has been pressed once Param[1]: key (type: int) -Function 160: IsKeyPressedRepeat() (1 input parameters) +Function 161: IsKeyPressedRepeat() (1 input parameters) Name: IsKeyPressedRepeat Return type: bool Description: Check if a key has been pressed again (Only PLATFORM_DESKTOP) Param[1]: key (type: int) -Function 161: IsKeyDown() (1 input parameters) +Function 162: IsKeyDown() (1 input parameters) Name: IsKeyDown Return type: bool Description: Check if a key is being pressed Param[1]: key (type: int) -Function 162: IsKeyReleased() (1 input parameters) +Function 163: IsKeyReleased() (1 input parameters) Name: IsKeyReleased Return type: bool Description: Check if a key has been released once Param[1]: key (type: int) -Function 163: IsKeyUp() (1 input parameters) +Function 164: IsKeyUp() (1 input parameters) Name: IsKeyUp Return type: bool Description: Check if a key is NOT being pressed Param[1]: key (type: int) -Function 164: GetKeyPressed() (0 input parameters) +Function 165: GetKeyPressed() (0 input parameters) Name: GetKeyPressed Return type: int Description: Get key pressed (keycode), call it multiple times for keys queued, returns 0 when the queue is empty No input parameters -Function 165: GetCharPressed() (0 input parameters) +Function 166: GetCharPressed() (0 input parameters) Name: GetCharPressed Return type: int Description: Get char pressed (unicode), call it multiple times for chars queued, returns 0 when the queue is empty No input parameters -Function 166: SetExitKey() (1 input parameters) +Function 167: SetExitKey() (1 input parameters) Name: SetExitKey Return type: void Description: Set a custom key to exit program (default is ESC) Param[1]: key (type: int) -Function 167: IsGamepadAvailable() (1 input parameters) +Function 168: IsGamepadAvailable() (1 input parameters) Name: IsGamepadAvailable Return type: bool Description: Check if a gamepad is available Param[1]: gamepad (type: int) -Function 168: GetGamepadName() (1 input parameters) +Function 169: GetGamepadName() (1 input parameters) Name: GetGamepadName Return type: const char * Description: Get gamepad internal name id Param[1]: gamepad (type: int) -Function 169: IsGamepadButtonPressed() (2 input parameters) +Function 170: IsGamepadButtonPressed() (2 input parameters) Name: IsGamepadButtonPressed Return type: bool Description: Check if a gamepad button has been pressed once Param[1]: gamepad (type: int) Param[2]: button (type: int) -Function 170: IsGamepadButtonDown() (2 input parameters) +Function 171: IsGamepadButtonDown() (2 input parameters) Name: IsGamepadButtonDown Return type: bool Description: Check if a gamepad button is being pressed Param[1]: gamepad (type: int) Param[2]: button (type: int) -Function 171: IsGamepadButtonReleased() (2 input parameters) +Function 172: IsGamepadButtonReleased() (2 input parameters) Name: IsGamepadButtonReleased Return type: bool Description: Check if a gamepad button has been released once Param[1]: gamepad (type: int) Param[2]: button (type: int) -Function 172: IsGamepadButtonUp() (2 input parameters) +Function 173: IsGamepadButtonUp() (2 input parameters) Name: IsGamepadButtonUp Return type: bool Description: Check if a gamepad button is NOT being pressed Param[1]: gamepad (type: int) Param[2]: button (type: int) -Function 173: GetGamepadButtonPressed() (0 input parameters) +Function 174: GetGamepadButtonPressed() (0 input parameters) Name: GetGamepadButtonPressed Return type: int Description: Get the last gamepad button pressed No input parameters -Function 174: GetGamepadAxisCount() (1 input parameters) +Function 175: GetGamepadAxisCount() (1 input parameters) Name: GetGamepadAxisCount Return type: int Description: Get gamepad axis count for a gamepad Param[1]: gamepad (type: int) -Function 175: GetGamepadAxisMovement() (2 input parameters) +Function 176: GetGamepadAxisMovement() (2 input parameters) Name: GetGamepadAxisMovement Return type: float Description: Get axis movement value for a gamepad axis Param[1]: gamepad (type: int) Param[2]: axis (type: int) -Function 176: SetGamepadMappings() (1 input parameters) +Function 177: SetGamepadMappings() (1 input parameters) Name: SetGamepadMappings Return type: int Description: Set internal gamepad mappings (SDL_GameControllerDB) Param[1]: mappings (type: const char *) -Function 177: SetGamepadVibration() (3 input parameters) +Function 178: SetGamepadVibration() (3 input parameters) Name: SetGamepadVibration Return type: void Description: Set gamepad vibration for both motors Param[1]: gamepad (type: int) Param[2]: leftMotor (type: float) Param[3]: rightMotor (type: float) -Function 178: IsMouseButtonPressed() (1 input parameters) +Function 179: IsMouseButtonPressed() (1 input parameters) Name: IsMouseButtonPressed Return type: bool Description: Check if a mouse button has been pressed once Param[1]: button (type: int) -Function 179: IsMouseButtonDown() (1 input parameters) +Function 180: IsMouseButtonDown() (1 input parameters) Name: IsMouseButtonDown Return type: bool Description: Check if a mouse button is being pressed Param[1]: button (type: int) -Function 180: IsMouseButtonReleased() (1 input parameters) +Function 181: IsMouseButtonReleased() (1 input parameters) Name: IsMouseButtonReleased Return type: bool Description: Check if a mouse button has been released once Param[1]: button (type: int) -Function 181: IsMouseButtonUp() (1 input parameters) +Function 182: IsMouseButtonUp() (1 input parameters) Name: IsMouseButtonUp Return type: bool Description: Check if a mouse button is NOT being pressed Param[1]: button (type: int) -Function 182: GetMouseX() (0 input parameters) +Function 183: GetMouseX() (0 input parameters) Name: GetMouseX Return type: int Description: Get mouse position X No input parameters -Function 183: GetMouseY() (0 input parameters) +Function 184: GetMouseY() (0 input parameters) Name: GetMouseY Return type: int Description: Get mouse position Y No input parameters -Function 184: GetMousePosition() (0 input parameters) +Function 185: GetMousePosition() (0 input parameters) Name: GetMousePosition Return type: Vector2 Description: Get mouse position XY No input parameters -Function 185: GetMouseDelta() (0 input parameters) +Function 186: GetMouseDelta() (0 input parameters) Name: GetMouseDelta Return type: Vector2 Description: Get mouse delta between frames No input parameters -Function 186: SetMousePosition() (2 input parameters) +Function 187: SetMousePosition() (2 input parameters) Name: SetMousePosition Return type: void Description: Set mouse position XY Param[1]: x (type: int) Param[2]: y (type: int) -Function 187: SetMouseOffset() (2 input parameters) +Function 188: SetMouseOffset() (2 input parameters) Name: SetMouseOffset Return type: void Description: Set mouse offset Param[1]: offsetX (type: int) Param[2]: offsetY (type: int) -Function 188: SetMouseScale() (2 input parameters) +Function 189: SetMouseScale() (2 input parameters) Name: SetMouseScale Return type: void Description: Set mouse scaling Param[1]: scaleX (type: float) Param[2]: scaleY (type: float) -Function 189: GetMouseWheelMove() (0 input parameters) +Function 190: GetMouseWheelMove() (0 input parameters) Name: GetMouseWheelMove Return type: float Description: Get mouse wheel movement for X or Y, whichever is larger No input parameters -Function 190: GetMouseWheelMoveV() (0 input parameters) +Function 191: GetMouseWheelMoveV() (0 input parameters) Name: GetMouseWheelMoveV Return type: Vector2 Description: Get mouse wheel movement for both X and Y No input parameters -Function 191: SetMouseCursor() (1 input parameters) +Function 192: SetMouseCursor() (1 input parameters) Name: SetMouseCursor Return type: void Description: Set mouse cursor Param[1]: cursor (type: int) -Function 192: GetTouchX() (0 input parameters) +Function 193: GetTouchX() (0 input parameters) Name: GetTouchX Return type: int Description: Get touch position X for touch point 0 (relative to screen size) No input parameters -Function 193: GetTouchY() (0 input parameters) +Function 194: GetTouchY() (0 input parameters) Name: GetTouchY Return type: int Description: Get touch position Y for touch point 0 (relative to screen size) No input parameters -Function 194: GetTouchPosition() (1 input parameters) +Function 195: GetTouchPosition() (1 input parameters) Name: GetTouchPosition Return type: Vector2 Description: Get touch position XY for a touch point index (relative to screen size) Param[1]: index (type: int) -Function 195: GetTouchPointId() (1 input parameters) +Function 196: GetTouchPointId() (1 input parameters) Name: GetTouchPointId Return type: int Description: Get touch point identifier for given index Param[1]: index (type: int) -Function 196: GetTouchPointCount() (0 input parameters) +Function 197: GetTouchPointCount() (0 input parameters) Name: GetTouchPointCount Return type: int Description: Get number of touch points No input parameters -Function 197: SetGesturesEnabled() (1 input parameters) +Function 198: SetGesturesEnabled() (1 input parameters) Name: SetGesturesEnabled Return type: void Description: Enable a set of gestures using flags Param[1]: flags (type: unsigned int) -Function 198: IsGestureDetected() (1 input parameters) +Function 199: IsGestureDetected() (1 input parameters) Name: IsGestureDetected Return type: bool Description: Check if a gesture have been detected Param[1]: gesture (type: unsigned int) -Function 199: GetGestureDetected() (0 input parameters) +Function 200: GetGestureDetected() (0 input parameters) Name: GetGestureDetected Return type: int Description: Get latest detected gesture No input parameters -Function 200: GetGestureHoldDuration() (0 input parameters) +Function 201: GetGestureHoldDuration() (0 input parameters) Name: GetGestureHoldDuration Return type: float Description: Get gesture hold time in milliseconds No input parameters -Function 201: GetGestureDragVector() (0 input parameters) +Function 202: GetGestureDragVector() (0 input parameters) Name: GetGestureDragVector Return type: Vector2 Description: Get gesture drag vector No input parameters -Function 202: GetGestureDragAngle() (0 input parameters) +Function 203: GetGestureDragAngle() (0 input parameters) Name: GetGestureDragAngle Return type: float Description: Get gesture drag angle No input parameters -Function 203: GetGesturePinchVector() (0 input parameters) +Function 204: GetGesturePinchVector() (0 input parameters) Name: GetGesturePinchVector Return type: Vector2 Description: Get gesture pinch delta No input parameters -Function 204: GetGesturePinchAngle() (0 input parameters) +Function 205: GetGesturePinchAngle() (0 input parameters) Name: GetGesturePinchAngle Return type: float Description: Get gesture pinch angle No input parameters -Function 205: UpdateCamera() (2 input parameters) +Function 206: UpdateCamera() (2 input parameters) Name: UpdateCamera Return type: void Description: Update camera position for selected mode Param[1]: camera (type: Camera *) Param[2]: mode (type: int) -Function 206: UpdateCameraPro() (4 input parameters) +Function 207: UpdateCameraPro() (4 input parameters) Name: UpdateCameraPro Return type: void Description: Update camera movement/rotation @@ -2095,36 +2101,36 @@ Function 206: UpdateCameraPro() (4 input parameters) Param[2]: movement (type: Vector3) Param[3]: rotation (type: Vector3) Param[4]: zoom (type: float) -Function 207: SetShapesTexture() (2 input parameters) +Function 208: SetShapesTexture() (2 input parameters) Name: SetShapesTexture Return type: void Description: Set texture and rectangle to be used on shapes drawing Param[1]: texture (type: Texture2D) Param[2]: source (type: Rectangle) -Function 208: GetShapesTexture() (0 input parameters) +Function 209: GetShapesTexture() (0 input parameters) Name: GetShapesTexture Return type: Texture2D Description: Get texture that is used for shapes drawing No input parameters -Function 209: GetShapesTextureRectangle() (0 input parameters) +Function 210: GetShapesTextureRectangle() (0 input parameters) Name: GetShapesTextureRectangle Return type: Rectangle Description: Get texture source rectangle that is used for shapes drawing No input parameters -Function 210: DrawPixel() (3 input parameters) +Function 211: DrawPixel() (3 input parameters) Name: DrawPixel Return type: void Description: Draw a pixel using geometry [Can be slow, use with care] Param[1]: posX (type: int) Param[2]: posY (type: int) Param[3]: color (type: Color) -Function 211: DrawPixelV() (2 input parameters) +Function 212: DrawPixelV() (2 input parameters) Name: DrawPixelV Return type: void Description: Draw a pixel using geometry (Vector version) [Can be slow, use with care] Param[1]: position (type: Vector2) Param[2]: color (type: Color) -Function 212: DrawLine() (5 input parameters) +Function 213: DrawLine() (5 input parameters) Name: DrawLine Return type: void Description: Draw a line @@ -2133,14 +2139,14 @@ Function 212: DrawLine() (5 input parameters) Param[3]: endPosX (type: int) Param[4]: endPosY (type: int) Param[5]: color (type: Color) -Function 213: DrawLineV() (3 input parameters) +Function 214: DrawLineV() (3 input parameters) Name: DrawLineV Return type: void Description: Draw a line (using gl lines) Param[1]: startPos (type: Vector2) Param[2]: endPos (type: Vector2) Param[3]: color (type: Color) -Function 214: DrawLineEx() (4 input parameters) +Function 215: DrawLineEx() (4 input parameters) Name: DrawLineEx Return type: void Description: Draw a line (using triangles/quads) @@ -2148,14 +2154,14 @@ Function 214: DrawLineEx() (4 input parameters) Param[2]: endPos (type: Vector2) Param[3]: thick (type: float) Param[4]: color (type: Color) -Function 215: DrawLineStrip() (3 input parameters) +Function 216: DrawLineStrip() (3 input parameters) Name: DrawLineStrip Return type: void Description: Draw lines sequence (using gl lines) Param[1]: points (type: const Vector2 *) Param[2]: pointCount (type: int) Param[3]: color (type: Color) -Function 216: DrawLineBezier() (4 input parameters) +Function 217: DrawLineBezier() (4 input parameters) Name: DrawLineBezier Return type: void Description: Draw line segment cubic-bezier in-out interpolation @@ -2163,7 +2169,7 @@ Function 216: DrawLineBezier() (4 input parameters) Param[2]: endPos (type: Vector2) Param[3]: thick (type: float) Param[4]: color (type: Color) -Function 217: DrawCircle() (4 input parameters) +Function 218: DrawCircle() (4 input parameters) Name: DrawCircle Return type: void Description: Draw a color-filled circle @@ -2171,7 +2177,7 @@ Function 217: DrawCircle() (4 input parameters) Param[2]: centerY (type: int) Param[3]: radius (type: float) Param[4]: color (type: Color) -Function 218: DrawCircleSector() (6 input parameters) +Function 219: DrawCircleSector() (6 input parameters) Name: DrawCircleSector Return type: void Description: Draw a piece of a circle @@ -2181,7 +2187,7 @@ Function 218: DrawCircleSector() (6 input parameters) Param[4]: endAngle (type: float) Param[5]: segments (type: int) Param[6]: color (type: Color) -Function 219: DrawCircleSectorLines() (6 input parameters) +Function 220: DrawCircleSectorLines() (6 input parameters) Name: DrawCircleSectorLines Return type: void Description: Draw circle sector outline @@ -2191,7 +2197,7 @@ Function 219: DrawCircleSectorLines() (6 input parameters) Param[4]: endAngle (type: float) Param[5]: segments (type: int) Param[6]: color (type: Color) -Function 220: DrawCircleGradient() (5 input parameters) +Function 221: DrawCircleGradient() (5 input parameters) Name: DrawCircleGradient Return type: void Description: Draw a gradient-filled circle @@ -2200,14 +2206,14 @@ Function 220: DrawCircleGradient() (5 input parameters) Param[3]: radius (type: float) Param[4]: inner (type: Color) Param[5]: outer (type: Color) -Function 221: DrawCircleV() (3 input parameters) +Function 222: DrawCircleV() (3 input parameters) Name: DrawCircleV Return type: void Description: Draw a color-filled circle (Vector version) Param[1]: center (type: Vector2) Param[2]: radius (type: float) Param[3]: color (type: Color) -Function 222: DrawCircleLines() (4 input parameters) +Function 223: DrawCircleLines() (4 input parameters) Name: DrawCircleLines Return type: void Description: Draw circle outline @@ -2215,14 +2221,14 @@ Function 222: DrawCircleLines() (4 input parameters) Param[2]: centerY (type: int) Param[3]: radius (type: float) Param[4]: color (type: Color) -Function 223: DrawCircleLinesV() (3 input parameters) +Function 224: DrawCircleLinesV() (3 input parameters) Name: DrawCircleLinesV Return type: void Description: Draw circle outline (Vector version) Param[1]: center (type: Vector2) Param[2]: radius (type: float) Param[3]: color (type: Color) -Function 224: DrawEllipse() (5 input parameters) +Function 225: DrawEllipse() (5 input parameters) Name: DrawEllipse Return type: void Description: Draw ellipse @@ -2231,7 +2237,7 @@ Function 224: DrawEllipse() (5 input parameters) Param[3]: radiusH (type: float) Param[4]: radiusV (type: float) Param[5]: color (type: Color) -Function 225: DrawEllipseLines() (5 input parameters) +Function 226: DrawEllipseLines() (5 input parameters) Name: DrawEllipseLines Return type: void Description: Draw ellipse outline @@ -2240,7 +2246,7 @@ Function 225: DrawEllipseLines() (5 input parameters) Param[3]: radiusH (type: float) Param[4]: radiusV (type: float) Param[5]: color (type: Color) -Function 226: DrawRing() (7 input parameters) +Function 227: DrawRing() (7 input parameters) Name: DrawRing Return type: void Description: Draw ring @@ -2251,7 +2257,7 @@ Function 226: DrawRing() (7 input parameters) Param[5]: endAngle (type: float) Param[6]: segments (type: int) Param[7]: color (type: Color) -Function 227: DrawRingLines() (7 input parameters) +Function 228: DrawRingLines() (7 input parameters) Name: DrawRingLines Return type: void Description: Draw ring outline @@ -2262,7 +2268,7 @@ Function 227: DrawRingLines() (7 input parameters) Param[5]: endAngle (type: float) Param[6]: segments (type: int) Param[7]: color (type: Color) -Function 228: DrawRectangle() (5 input parameters) +Function 229: DrawRectangle() (5 input parameters) Name: DrawRectangle Return type: void Description: Draw a color-filled rectangle @@ -2271,20 +2277,20 @@ Function 228: DrawRectangle() (5 input parameters) Param[3]: width (type: int) Param[4]: height (type: int) Param[5]: color (type: Color) -Function 229: DrawRectangleV() (3 input parameters) +Function 230: DrawRectangleV() (3 input parameters) Name: DrawRectangleV Return type: void Description: Draw a color-filled rectangle (Vector version) Param[1]: position (type: Vector2) Param[2]: size (type: Vector2) Param[3]: color (type: Color) -Function 230: DrawRectangleRec() (2 input parameters) +Function 231: DrawRectangleRec() (2 input parameters) Name: DrawRectangleRec Return type: void Description: Draw a color-filled rectangle Param[1]: rec (type: Rectangle) Param[2]: color (type: Color) -Function 231: DrawRectanglePro() (4 input parameters) +Function 232: DrawRectanglePro() (4 input parameters) Name: DrawRectanglePro Return type: void Description: Draw a color-filled rectangle with pro parameters @@ -2292,7 +2298,7 @@ Function 231: DrawRectanglePro() (4 input parameters) Param[2]: origin (type: Vector2) Param[3]: rotation (type: float) Param[4]: color (type: Color) -Function 232: DrawRectangleGradientV() (6 input parameters) +Function 233: DrawRectangleGradientV() (6 input parameters) Name: DrawRectangleGradientV Return type: void Description: Draw a vertical-gradient-filled rectangle @@ -2302,7 +2308,7 @@ Function 232: DrawRectangleGradientV() (6 input parameters) Param[4]: height (type: int) Param[5]: top (type: Color) Param[6]: bottom (type: Color) -Function 233: DrawRectangleGradientH() (6 input parameters) +Function 234: DrawRectangleGradientH() (6 input parameters) Name: DrawRectangleGradientH Return type: void Description: Draw a horizontal-gradient-filled rectangle @@ -2312,7 +2318,7 @@ Function 233: DrawRectangleGradientH() (6 input parameters) Param[4]: height (type: int) Param[5]: left (type: Color) Param[6]: right (type: Color) -Function 234: DrawRectangleGradientEx() (5 input parameters) +Function 235: DrawRectangleGradientEx() (5 input parameters) Name: DrawRectangleGradientEx Return type: void Description: Draw a gradient-filled rectangle with custom vertex colors @@ -2321,7 +2327,7 @@ Function 234: DrawRectangleGradientEx() (5 input parameters) Param[3]: bottomLeft (type: Color) Param[4]: topRight (type: Color) Param[5]: bottomRight (type: Color) -Function 235: DrawRectangleLines() (5 input parameters) +Function 236: DrawRectangleLines() (5 input parameters) Name: DrawRectangleLines Return type: void Description: Draw rectangle outline @@ -2330,14 +2336,14 @@ Function 235: DrawRectangleLines() (5 input parameters) Param[3]: width (type: int) Param[4]: height (type: int) Param[5]: color (type: Color) -Function 236: DrawRectangleLinesEx() (3 input parameters) +Function 237: DrawRectangleLinesEx() (3 input parameters) Name: DrawRectangleLinesEx Return type: void Description: Draw rectangle outline with extended parameters Param[1]: rec (type: Rectangle) Param[2]: lineThick (type: float) Param[3]: color (type: Color) -Function 237: DrawRectangleRounded() (4 input parameters) +Function 238: DrawRectangleRounded() (4 input parameters) Name: DrawRectangleRounded Return type: void Description: Draw rectangle with rounded edges @@ -2345,7 +2351,7 @@ Function 237: DrawRectangleRounded() (4 input parameters) Param[2]: roundness (type: float) Param[3]: segments (type: int) Param[4]: color (type: Color) -Function 238: DrawRectangleRoundedLines() (4 input parameters) +Function 239: DrawRectangleRoundedLines() (4 input parameters) Name: DrawRectangleRoundedLines Return type: void Description: Draw rectangle lines with rounded edges @@ -2353,7 +2359,7 @@ Function 238: DrawRectangleRoundedLines() (4 input parameters) Param[2]: roundness (type: float) Param[3]: segments (type: int) Param[4]: color (type: Color) -Function 239: DrawRectangleRoundedLinesEx() (5 input parameters) +Function 240: DrawRectangleRoundedLinesEx() (5 input parameters) Name: DrawRectangleRoundedLinesEx Return type: void Description: Draw rectangle with rounded edges outline @@ -2362,7 +2368,7 @@ Function 239: DrawRectangleRoundedLinesEx() (5 input parameters) Param[3]: segments (type: int) Param[4]: lineThick (type: float) Param[5]: color (type: Color) -Function 240: DrawTriangle() (4 input parameters) +Function 241: DrawTriangle() (4 input parameters) Name: DrawTriangle Return type: void Description: Draw a color-filled triangle (vertex in counter-clockwise order!) @@ -2370,7 +2376,7 @@ Function 240: DrawTriangle() (4 input parameters) Param[2]: v2 (type: Vector2) Param[3]: v3 (type: Vector2) Param[4]: color (type: Color) -Function 241: DrawTriangleLines() (4 input parameters) +Function 242: DrawTriangleLines() (4 input parameters) Name: DrawTriangleLines Return type: void Description: Draw triangle outline (vertex in counter-clockwise order!) @@ -2378,21 +2384,21 @@ Function 241: DrawTriangleLines() (4 input parameters) Param[2]: v2 (type: Vector2) Param[3]: v3 (type: Vector2) Param[4]: color (type: Color) -Function 242: DrawTriangleFan() (3 input parameters) +Function 243: DrawTriangleFan() (3 input parameters) Name: DrawTriangleFan Return type: void Description: Draw a triangle fan defined by points (first vertex is the center) Param[1]: points (type: const Vector2 *) Param[2]: pointCount (type: int) Param[3]: color (type: Color) -Function 243: DrawTriangleStrip() (3 input parameters) +Function 244: DrawTriangleStrip() (3 input parameters) Name: DrawTriangleStrip Return type: void Description: Draw a triangle strip defined by points Param[1]: points (type: const Vector2 *) Param[2]: pointCount (type: int) Param[3]: color (type: Color) -Function 244: DrawPoly() (5 input parameters) +Function 245: DrawPoly() (5 input parameters) Name: DrawPoly Return type: void Description: Draw a regular polygon (Vector version) @@ -2401,7 +2407,7 @@ Function 244: DrawPoly() (5 input parameters) Param[3]: radius (type: float) Param[4]: rotation (type: float) Param[5]: color (type: Color) -Function 245: DrawPolyLines() (5 input parameters) +Function 246: DrawPolyLines() (5 input parameters) Name: DrawPolyLines Return type: void Description: Draw a polygon outline of n sides @@ -2410,7 +2416,7 @@ Function 245: DrawPolyLines() (5 input parameters) Param[3]: radius (type: float) Param[4]: rotation (type: float) Param[5]: color (type: Color) -Function 246: DrawPolyLinesEx() (6 input parameters) +Function 247: DrawPolyLinesEx() (6 input parameters) Name: DrawPolyLinesEx Return type: void Description: Draw a polygon outline of n sides with extended parameters @@ -2420,7 +2426,7 @@ Function 246: DrawPolyLinesEx() (6 input parameters) Param[4]: rotation (type: float) Param[5]: lineThick (type: float) Param[6]: color (type: Color) -Function 247: DrawSplineLinear() (4 input parameters) +Function 248: DrawSplineLinear() (4 input parameters) Name: DrawSplineLinear Return type: void Description: Draw spline: Linear, minimum 2 points @@ -2428,7 +2434,7 @@ Function 247: DrawSplineLinear() (4 input parameters) Param[2]: pointCount (type: int) Param[3]: thick (type: float) Param[4]: color (type: Color) -Function 248: DrawSplineBasis() (4 input parameters) +Function 249: DrawSplineBasis() (4 input parameters) Name: DrawSplineBasis Return type: void Description: Draw spline: B-Spline, minimum 4 points @@ -2436,7 +2442,7 @@ Function 248: DrawSplineBasis() (4 input parameters) Param[2]: pointCount (type: int) Param[3]: thick (type: float) Param[4]: color (type: Color) -Function 249: DrawSplineCatmullRom() (4 input parameters) +Function 250: DrawSplineCatmullRom() (4 input parameters) Name: DrawSplineCatmullRom Return type: void Description: Draw spline: Catmull-Rom, minimum 4 points @@ -2444,7 +2450,7 @@ Function 249: DrawSplineCatmullRom() (4 input parameters) Param[2]: pointCount (type: int) Param[3]: thick (type: float) Param[4]: color (type: Color) -Function 250: DrawSplineBezierQuadratic() (4 input parameters) +Function 251: DrawSplineBezierQuadratic() (4 input parameters) Name: DrawSplineBezierQuadratic Return type: void Description: Draw spline: Quadratic Bezier, minimum 3 points (1 control point): [p1, c2, p3, c4...] @@ -2452,7 +2458,7 @@ Function 250: DrawSplineBezierQuadratic() (4 input parameters) Param[2]: pointCount (type: int) Param[3]: thick (type: float) Param[4]: color (type: Color) -Function 251: DrawSplineBezierCubic() (4 input parameters) +Function 252: DrawSplineBezierCubic() (4 input parameters) Name: DrawSplineBezierCubic Return type: void Description: Draw spline: Cubic Bezier, minimum 4 points (2 control points): [p1, c2, c3, p4, c5, c6...] @@ -2460,7 +2466,7 @@ Function 251: DrawSplineBezierCubic() (4 input parameters) Param[2]: pointCount (type: int) Param[3]: thick (type: float) Param[4]: color (type: Color) -Function 252: DrawSplineSegmentLinear() (4 input parameters) +Function 253: DrawSplineSegmentLinear() (4 input parameters) Name: DrawSplineSegmentLinear Return type: void Description: Draw spline segment: Linear, 2 points @@ -2468,7 +2474,7 @@ Function 252: DrawSplineSegmentLinear() (4 input parameters) Param[2]: p2 (type: Vector2) Param[3]: thick (type: float) Param[4]: color (type: Color) -Function 253: DrawSplineSegmentBasis() (6 input parameters) +Function 254: DrawSplineSegmentBasis() (6 input parameters) Name: DrawSplineSegmentBasis Return type: void Description: Draw spline segment: B-Spline, 4 points @@ -2478,7 +2484,7 @@ Function 253: DrawSplineSegmentBasis() (6 input parameters) Param[4]: p4 (type: Vector2) Param[5]: thick (type: float) Param[6]: color (type: Color) -Function 254: DrawSplineSegmentCatmullRom() (6 input parameters) +Function 255: DrawSplineSegmentCatmullRom() (6 input parameters) Name: DrawSplineSegmentCatmullRom Return type: void Description: Draw spline segment: Catmull-Rom, 4 points @@ -2488,7 +2494,7 @@ Function 254: DrawSplineSegmentCatmullRom() (6 input parameters) Param[4]: p4 (type: Vector2) Param[5]: thick (type: float) Param[6]: color (type: Color) -Function 255: DrawSplineSegmentBezierQuadratic() (5 input parameters) +Function 256: DrawSplineSegmentBezierQuadratic() (5 input parameters) Name: DrawSplineSegmentBezierQuadratic Return type: void Description: Draw spline segment: Quadratic Bezier, 2 points, 1 control point @@ -2497,7 +2503,7 @@ Function 255: DrawSplineSegmentBezierQuadratic() (5 input parameters) Param[3]: p3 (type: Vector2) Param[4]: thick (type: float) Param[5]: color (type: Color) -Function 256: DrawSplineSegmentBezierCubic() (6 input parameters) +Function 257: DrawSplineSegmentBezierCubic() (6 input parameters) Name: DrawSplineSegmentBezierCubic Return type: void Description: Draw spline segment: Cubic Bezier, 2 points, 2 control points @@ -2507,14 +2513,14 @@ Function 256: DrawSplineSegmentBezierCubic() (6 input parameters) Param[4]: p4 (type: Vector2) Param[5]: thick (type: float) Param[6]: color (type: Color) -Function 257: GetSplinePointLinear() (3 input parameters) +Function 258: GetSplinePointLinear() (3 input parameters) Name: GetSplinePointLinear Return type: Vector2 Description: Get (evaluate) spline point: Linear Param[1]: startPos (type: Vector2) Param[2]: endPos (type: Vector2) Param[3]: t (type: float) -Function 258: GetSplinePointBasis() (5 input parameters) +Function 259: GetSplinePointBasis() (5 input parameters) Name: GetSplinePointBasis Return type: Vector2 Description: Get (evaluate) spline point: B-Spline @@ -2523,7 +2529,7 @@ Function 258: GetSplinePointBasis() (5 input parameters) Param[3]: p3 (type: Vector2) Param[4]: p4 (type: Vector2) Param[5]: t (type: float) -Function 259: GetSplinePointCatmullRom() (5 input parameters) +Function 260: GetSplinePointCatmullRom() (5 input parameters) Name: GetSplinePointCatmullRom Return type: Vector2 Description: Get (evaluate) spline point: Catmull-Rom @@ -2532,7 +2538,7 @@ Function 259: GetSplinePointCatmullRom() (5 input parameters) Param[3]: p3 (type: Vector2) Param[4]: p4 (type: Vector2) Param[5]: t (type: float) -Function 260: GetSplinePointBezierQuad() (4 input parameters) +Function 261: GetSplinePointBezierQuad() (4 input parameters) Name: GetSplinePointBezierQuad Return type: Vector2 Description: Get (evaluate) spline point: Quadratic Bezier @@ -2540,7 +2546,7 @@ Function 260: GetSplinePointBezierQuad() (4 input parameters) Param[2]: c2 (type: Vector2) Param[3]: p3 (type: Vector2) Param[4]: t (type: float) -Function 261: GetSplinePointBezierCubic() (5 input parameters) +Function 262: GetSplinePointBezierCubic() (5 input parameters) Name: GetSplinePointBezierCubic Return type: Vector2 Description: Get (evaluate) spline point: Cubic Bezier @@ -2549,13 +2555,13 @@ Function 261: GetSplinePointBezierCubic() (5 input parameters) Param[3]: c3 (type: Vector2) Param[4]: p4 (type: Vector2) Param[5]: t (type: float) -Function 262: CheckCollisionRecs() (2 input parameters) +Function 263: CheckCollisionRecs() (2 input parameters) Name: CheckCollisionRecs Return type: bool Description: Check collision between two rectangles Param[1]: rec1 (type: Rectangle) Param[2]: rec2 (type: Rectangle) -Function 263: CheckCollisionCircles() (4 input parameters) +Function 264: CheckCollisionCircles() (4 input parameters) Name: CheckCollisionCircles Return type: bool Description: Check collision between two circles @@ -2563,27 +2569,27 @@ Function 263: CheckCollisionCircles() (4 input parameters) Param[2]: radius1 (type: float) Param[3]: center2 (type: Vector2) Param[4]: radius2 (type: float) -Function 264: CheckCollisionCircleRec() (3 input parameters) +Function 265: CheckCollisionCircleRec() (3 input parameters) Name: CheckCollisionCircleRec Return type: bool Description: Check collision between circle and rectangle Param[1]: center (type: Vector2) Param[2]: radius (type: float) Param[3]: rec (type: Rectangle) -Function 265: CheckCollisionPointRec() (2 input parameters) +Function 266: CheckCollisionPointRec() (2 input parameters) Name: CheckCollisionPointRec Return type: bool Description: Check if point is inside rectangle Param[1]: point (type: Vector2) Param[2]: rec (type: Rectangle) -Function 266: CheckCollisionPointCircle() (3 input parameters) +Function 267: CheckCollisionPointCircle() (3 input parameters) Name: CheckCollisionPointCircle Return type: bool Description: Check if point is inside circle Param[1]: point (type: Vector2) Param[2]: center (type: Vector2) Param[3]: radius (type: float) -Function 267: CheckCollisionPointTriangle() (4 input parameters) +Function 268: CheckCollisionPointTriangle() (4 input parameters) Name: CheckCollisionPointTriangle Return type: bool Description: Check if point is inside a triangle @@ -2591,14 +2597,14 @@ Function 267: CheckCollisionPointTriangle() (4 input parameters) Param[2]: p1 (type: Vector2) Param[3]: p2 (type: Vector2) Param[4]: p3 (type: Vector2) -Function 268: CheckCollisionPointPoly() (3 input parameters) +Function 269: CheckCollisionPointPoly() (3 input parameters) Name: CheckCollisionPointPoly Return type: bool Description: Check if point is within a polygon described by array of vertices Param[1]: point (type: Vector2) Param[2]: points (type: const Vector2 *) Param[3]: pointCount (type: int) -Function 269: CheckCollisionLines() (5 input parameters) +Function 270: CheckCollisionLines() (5 input parameters) Name: CheckCollisionLines Return type: bool Description: Check the collision between two lines defined by two points each, returns collision point by reference @@ -2607,7 +2613,7 @@ Function 269: CheckCollisionLines() (5 input parameters) Param[3]: startPos2 (type: Vector2) Param[4]: endPos2 (type: Vector2) Param[5]: collisionPoint (type: Vector2 *) -Function 270: CheckCollisionPointLine() (4 input parameters) +Function 271: CheckCollisionPointLine() (4 input parameters) Name: CheckCollisionPointLine Return type: bool Description: Check if point belongs to line created between two points [p1] and [p2] with defined margin in pixels [threshold] @@ -2615,7 +2621,7 @@ Function 270: CheckCollisionPointLine() (4 input parameters) Param[2]: p1 (type: Vector2) Param[3]: p2 (type: Vector2) Param[4]: threshold (type: int) -Function 271: CheckCollisionCircleLine() (4 input parameters) +Function 272: CheckCollisionCircleLine() (4 input parameters) Name: CheckCollisionCircleLine Return type: bool Description: Check if circle collides with a line created betweeen two points [p1] and [p2] @@ -2623,18 +2629,18 @@ Function 271: CheckCollisionCircleLine() (4 input parameters) Param[2]: radius (type: float) Param[3]: p1 (type: Vector2) Param[4]: p2 (type: Vector2) -Function 272: GetCollisionRec() (2 input parameters) +Function 273: GetCollisionRec() (2 input parameters) Name: GetCollisionRec Return type: Rectangle Description: Get collision rectangle for two rectangles collision Param[1]: rec1 (type: Rectangle) Param[2]: rec2 (type: Rectangle) -Function 273: LoadImage() (1 input parameters) +Function 274: LoadImage() (1 input parameters) Name: LoadImage Return type: Image Description: Load image from file into CPU memory (RAM) Param[1]: fileName (type: const char *) -Function 274: LoadImageRaw() (5 input parameters) +Function 275: LoadImageRaw() (5 input parameters) Name: LoadImageRaw Return type: Image Description: Load image from RAW file data @@ -2643,13 +2649,13 @@ Function 274: LoadImageRaw() (5 input parameters) Param[3]: height (type: int) Param[4]: format (type: int) Param[5]: headerSize (type: int) -Function 275: LoadImageAnim() (2 input parameters) +Function 276: LoadImageAnim() (2 input parameters) Name: LoadImageAnim Return type: Image Description: Load image sequence from file (frames appended to image.data) Param[1]: fileName (type: const char *) Param[2]: frames (type: int *) -Function 276: LoadImageAnimFromMemory() (4 input parameters) +Function 277: LoadImageAnimFromMemory() (4 input parameters) Name: LoadImageAnimFromMemory Return type: Image Description: Load image sequence from memory buffer @@ -2657,60 +2663,60 @@ Function 276: LoadImageAnimFromMemory() (4 input parameters) Param[2]: fileData (type: const unsigned char *) Param[3]: dataSize (type: int) Param[4]: frames (type: int *) -Function 277: LoadImageFromMemory() (3 input parameters) +Function 278: LoadImageFromMemory() (3 input parameters) Name: LoadImageFromMemory Return type: Image Description: Load image from memory buffer, fileType refers to extension: i.e. '.png' Param[1]: fileType (type: const char *) Param[2]: fileData (type: const unsigned char *) Param[3]: dataSize (type: int) -Function 278: LoadImageFromTexture() (1 input parameters) +Function 279: LoadImageFromTexture() (1 input parameters) Name: LoadImageFromTexture Return type: Image Description: Load image from GPU texture data Param[1]: texture (type: Texture2D) -Function 279: LoadImageFromScreen() (0 input parameters) +Function 280: LoadImageFromScreen() (0 input parameters) Name: LoadImageFromScreen Return type: Image Description: Load image from screen buffer and (screenshot) No input parameters -Function 280: IsImageValid() (1 input parameters) +Function 281: IsImageValid() (1 input parameters) Name: IsImageValid Return type: bool Description: Check if an image is valid (data and parameters) Param[1]: image (type: Image) -Function 281: UnloadImage() (1 input parameters) +Function 282: UnloadImage() (1 input parameters) Name: UnloadImage Return type: void Description: Unload image from CPU memory (RAM) Param[1]: image (type: Image) -Function 282: ExportImage() (2 input parameters) +Function 283: ExportImage() (2 input parameters) Name: ExportImage Return type: bool Description: Export image data to file, returns true on success Param[1]: image (type: Image) Param[2]: fileName (type: const char *) -Function 283: ExportImageToMemory() (3 input parameters) +Function 284: ExportImageToMemory() (3 input parameters) Name: ExportImageToMemory Return type: unsigned char * Description: Export image to memory buffer Param[1]: image (type: Image) Param[2]: fileType (type: const char *) Param[3]: fileSize (type: int *) -Function 284: ExportImageAsCode() (2 input parameters) +Function 285: ExportImageAsCode() (2 input parameters) Name: ExportImageAsCode Return type: bool Description: Export image as code file defining an array of bytes, returns true on success Param[1]: image (type: Image) Param[2]: fileName (type: const char *) -Function 285: GenImageColor() (3 input parameters) +Function 286: GenImageColor() (3 input parameters) Name: GenImageColor Return type: Image Description: Generate image: plain color Param[1]: width (type: int) Param[2]: height (type: int) Param[3]: color (type: Color) -Function 286: GenImageGradientLinear() (5 input parameters) +Function 287: GenImageGradientLinear() (5 input parameters) Name: GenImageGradientLinear Return type: Image Description: Generate image: linear gradient, direction in degrees [0..360], 0=Vertical gradient @@ -2719,7 +2725,7 @@ Function 286: GenImageGradientLinear() (5 input parameters) Param[3]: direction (type: int) Param[4]: start (type: Color) Param[5]: end (type: Color) -Function 287: GenImageGradientRadial() (5 input parameters) +Function 288: GenImageGradientRadial() (5 input parameters) Name: GenImageGradientRadial Return type: Image Description: Generate image: radial gradient @@ -2728,7 +2734,7 @@ Function 287: GenImageGradientRadial() (5 input parameters) Param[3]: density (type: float) Param[4]: inner (type: Color) Param[5]: outer (type: Color) -Function 288: GenImageGradientSquare() (5 input parameters) +Function 289: GenImageGradientSquare() (5 input parameters) Name: GenImageGradientSquare Return type: Image Description: Generate image: square gradient @@ -2737,7 +2743,7 @@ Function 288: GenImageGradientSquare() (5 input parameters) Param[3]: density (type: float) Param[4]: inner (type: Color) Param[5]: outer (type: Color) -Function 289: GenImageChecked() (6 input parameters) +Function 290: GenImageChecked() (6 input parameters) Name: GenImageChecked Return type: Image Description: Generate image: checked @@ -2747,14 +2753,14 @@ Function 289: GenImageChecked() (6 input parameters) Param[4]: checksY (type: int) Param[5]: col1 (type: Color) Param[6]: col2 (type: Color) -Function 290: GenImageWhiteNoise() (3 input parameters) +Function 291: GenImageWhiteNoise() (3 input parameters) Name: GenImageWhiteNoise Return type: Image Description: Generate image: white noise Param[1]: width (type: int) Param[2]: height (type: int) Param[3]: factor (type: float) -Function 291: GenImagePerlinNoise() (5 input parameters) +Function 292: GenImagePerlinNoise() (5 input parameters) Name: GenImagePerlinNoise Return type: Image Description: Generate image: perlin noise @@ -2763,45 +2769,45 @@ Function 291: GenImagePerlinNoise() (5 input parameters) Param[3]: offsetX (type: int) Param[4]: offsetY (type: int) Param[5]: scale (type: float) -Function 292: GenImageCellular() (3 input parameters) +Function 293: GenImageCellular() (3 input parameters) Name: GenImageCellular Return type: Image Description: Generate image: cellular algorithm, bigger tileSize means bigger cells Param[1]: width (type: int) Param[2]: height (type: int) Param[3]: tileSize (type: int) -Function 293: GenImageText() (3 input parameters) +Function 294: GenImageText() (3 input parameters) Name: GenImageText Return type: Image Description: Generate image: grayscale image from text data Param[1]: width (type: int) Param[2]: height (type: int) Param[3]: text (type: const char *) -Function 294: ImageCopy() (1 input parameters) +Function 295: ImageCopy() (1 input parameters) Name: ImageCopy Return type: Image Description: Create an image duplicate (useful for transformations) Param[1]: image (type: Image) -Function 295: ImageFromImage() (2 input parameters) +Function 296: ImageFromImage() (2 input parameters) Name: ImageFromImage Return type: Image Description: Create an image from another image piece Param[1]: image (type: Image) Param[2]: rec (type: Rectangle) -Function 296: ImageFromChannel() (2 input parameters) +Function 297: ImageFromChannel() (2 input parameters) Name: ImageFromChannel Return type: Image Description: Create an image from a selected channel of another image (GRAYSCALE) Param[1]: image (type: Image) Param[2]: selectedChannel (type: int) -Function 297: ImageText() (3 input parameters) +Function 298: ImageText() (3 input parameters) Name: ImageText Return type: Image Description: Create an image from text (default font) Param[1]: text (type: const char *) Param[2]: fontSize (type: int) Param[3]: color (type: Color) -Function 298: ImageTextEx() (5 input parameters) +Function 299: ImageTextEx() (5 input parameters) Name: ImageTextEx Return type: Image Description: Create an image from text (custom sprite font) @@ -2810,76 +2816,76 @@ Function 298: ImageTextEx() (5 input parameters) Param[3]: fontSize (type: float) Param[4]: spacing (type: float) Param[5]: tint (type: Color) -Function 299: ImageFormat() (2 input parameters) +Function 300: ImageFormat() (2 input parameters) Name: ImageFormat Return type: void Description: Convert image data to desired format Param[1]: image (type: Image *) Param[2]: newFormat (type: int) -Function 300: ImageToPOT() (2 input parameters) +Function 301: ImageToPOT() (2 input parameters) Name: ImageToPOT Return type: void Description: Convert image to POT (power-of-two) Param[1]: image (type: Image *) Param[2]: fill (type: Color) -Function 301: ImageCrop() (2 input parameters) +Function 302: ImageCrop() (2 input parameters) Name: ImageCrop Return type: void Description: Crop an image to a defined rectangle Param[1]: image (type: Image *) Param[2]: crop (type: Rectangle) -Function 302: ImageAlphaCrop() (2 input parameters) +Function 303: ImageAlphaCrop() (2 input parameters) Name: ImageAlphaCrop Return type: void Description: Crop image depending on alpha value Param[1]: image (type: Image *) Param[2]: threshold (type: float) -Function 303: ImageAlphaClear() (3 input parameters) +Function 304: ImageAlphaClear() (3 input parameters) Name: ImageAlphaClear Return type: void Description: Clear alpha channel to desired color Param[1]: image (type: Image *) Param[2]: color (type: Color) Param[3]: threshold (type: float) -Function 304: ImageAlphaMask() (2 input parameters) +Function 305: ImageAlphaMask() (2 input parameters) Name: ImageAlphaMask Return type: void Description: Apply alpha mask to image Param[1]: image (type: Image *) Param[2]: alphaMask (type: Image) -Function 305: ImageAlphaPremultiply() (1 input parameters) +Function 306: ImageAlphaPremultiply() (1 input parameters) Name: ImageAlphaPremultiply Return type: void Description: Premultiply alpha channel Param[1]: image (type: Image *) -Function 306: ImageBlurGaussian() (2 input parameters) +Function 307: ImageBlurGaussian() (2 input parameters) Name: ImageBlurGaussian Return type: void Description: Apply Gaussian blur using a box blur approximation Param[1]: image (type: Image *) Param[2]: blurSize (type: int) -Function 307: ImageKernelConvolution() (3 input parameters) +Function 308: ImageKernelConvolution() (3 input parameters) Name: ImageKernelConvolution Return type: void Description: Apply custom square convolution kernel to image Param[1]: image (type: Image *) Param[2]: kernel (type: const float *) Param[3]: kernelSize (type: int) -Function 308: ImageResize() (3 input parameters) +Function 309: ImageResize() (3 input parameters) Name: ImageResize Return type: void Description: Resize image (Bicubic scaling algorithm) Param[1]: image (type: Image *) Param[2]: newWidth (type: int) Param[3]: newHeight (type: int) -Function 309: ImageResizeNN() (3 input parameters) +Function 310: ImageResizeNN() (3 input parameters) Name: ImageResizeNN Return type: void Description: Resize image (Nearest-Neighbor scaling algorithm) Param[1]: image (type: Image *) Param[2]: newWidth (type: int) Param[3]: newHeight (type: int) -Function 310: ImageResizeCanvas() (6 input parameters) +Function 311: ImageResizeCanvas() (6 input parameters) Name: ImageResizeCanvas Return type: void Description: Resize canvas and fill with color @@ -2889,12 +2895,12 @@ Function 310: ImageResizeCanvas() (6 input parameters) Param[4]: offsetX (type: int) Param[5]: offsetY (type: int) Param[6]: fill (type: Color) -Function 311: ImageMipmaps() (1 input parameters) +Function 312: ImageMipmaps() (1 input parameters) Name: ImageMipmaps Return type: void Description: Compute all mipmap levels for a provided image Param[1]: image (type: Image *) -Function 312: ImageDither() (5 input parameters) +Function 313: ImageDither() (5 input parameters) Name: ImageDither Return type: void Description: Dither image data to 16bpp or lower (Floyd-Steinberg dithering) @@ -2903,109 +2909,109 @@ Function 312: ImageDither() (5 input parameters) Param[3]: gBpp (type: int) Param[4]: bBpp (type: int) Param[5]: aBpp (type: int) -Function 313: ImageFlipVertical() (1 input parameters) +Function 314: ImageFlipVertical() (1 input parameters) Name: ImageFlipVertical Return type: void Description: Flip image vertically Param[1]: image (type: Image *) -Function 314: ImageFlipHorizontal() (1 input parameters) +Function 315: ImageFlipHorizontal() (1 input parameters) Name: ImageFlipHorizontal Return type: void Description: Flip image horizontally Param[1]: image (type: Image *) -Function 315: ImageRotate() (2 input parameters) +Function 316: ImageRotate() (2 input parameters) Name: ImageRotate Return type: void Description: Rotate image by input angle in degrees (-359 to 359) Param[1]: image (type: Image *) Param[2]: degrees (type: int) -Function 316: ImageRotateCW() (1 input parameters) +Function 317: ImageRotateCW() (1 input parameters) Name: ImageRotateCW Return type: void Description: Rotate image clockwise 90deg Param[1]: image (type: Image *) -Function 317: ImageRotateCCW() (1 input parameters) +Function 318: ImageRotateCCW() (1 input parameters) Name: ImageRotateCCW Return type: void Description: Rotate image counter-clockwise 90deg Param[1]: image (type: Image *) -Function 318: ImageColorTint() (2 input parameters) +Function 319: ImageColorTint() (2 input parameters) Name: ImageColorTint Return type: void Description: Modify image color: tint Param[1]: image (type: Image *) Param[2]: color (type: Color) -Function 319: ImageColorInvert() (1 input parameters) +Function 320: ImageColorInvert() (1 input parameters) Name: ImageColorInvert Return type: void Description: Modify image color: invert Param[1]: image (type: Image *) -Function 320: ImageColorGrayscale() (1 input parameters) +Function 321: ImageColorGrayscale() (1 input parameters) Name: ImageColorGrayscale Return type: void Description: Modify image color: grayscale Param[1]: image (type: Image *) -Function 321: ImageColorContrast() (2 input parameters) +Function 322: ImageColorContrast() (2 input parameters) Name: ImageColorContrast Return type: void Description: Modify image color: contrast (-100 to 100) Param[1]: image (type: Image *) Param[2]: contrast (type: float) -Function 322: ImageColorBrightness() (2 input parameters) +Function 323: ImageColorBrightness() (2 input parameters) Name: ImageColorBrightness Return type: void Description: Modify image color: brightness (-255 to 255) Param[1]: image (type: Image *) Param[2]: brightness (type: int) -Function 323: ImageColorReplace() (3 input parameters) +Function 324: ImageColorReplace() (3 input parameters) Name: ImageColorReplace Return type: void Description: Modify image color: replace color Param[1]: image (type: Image *) Param[2]: color (type: Color) Param[3]: replace (type: Color) -Function 324: LoadImageColors() (1 input parameters) +Function 325: LoadImageColors() (1 input parameters) Name: LoadImageColors Return type: Color * Description: Load color data from image as a Color array (RGBA - 32bit) Param[1]: image (type: Image) -Function 325: LoadImagePalette() (3 input parameters) +Function 326: LoadImagePalette() (3 input parameters) Name: LoadImagePalette Return type: Color * Description: Load colors palette from image as a Color array (RGBA - 32bit) Param[1]: image (type: Image) Param[2]: maxPaletteSize (type: int) Param[3]: colorCount (type: int *) -Function 326: UnloadImageColors() (1 input parameters) +Function 327: UnloadImageColors() (1 input parameters) Name: UnloadImageColors Return type: void Description: Unload color data loaded with LoadImageColors() Param[1]: colors (type: Color *) -Function 327: UnloadImagePalette() (1 input parameters) +Function 328: UnloadImagePalette() (1 input parameters) Name: UnloadImagePalette Return type: void Description: Unload colors palette loaded with LoadImagePalette() Param[1]: colors (type: Color *) -Function 328: GetImageAlphaBorder() (2 input parameters) +Function 329: GetImageAlphaBorder() (2 input parameters) Name: GetImageAlphaBorder Return type: Rectangle Description: Get image alpha border rectangle Param[1]: image (type: Image) Param[2]: threshold (type: float) -Function 329: GetImageColor() (3 input parameters) +Function 330: GetImageColor() (3 input parameters) Name: GetImageColor Return type: Color Description: Get image pixel color at (x, y) position Param[1]: image (type: Image) Param[2]: x (type: int) Param[3]: y (type: int) -Function 330: ImageClearBackground() (2 input parameters) +Function 331: ImageClearBackground() (2 input parameters) Name: ImageClearBackground Return type: void Description: Clear image background with given color Param[1]: dst (type: Image *) Param[2]: color (type: Color) -Function 331: ImageDrawPixel() (4 input parameters) +Function 332: ImageDrawPixel() (4 input parameters) Name: ImageDrawPixel Return type: void Description: Draw pixel within an image @@ -3013,14 +3019,14 @@ Function 331: ImageDrawPixel() (4 input parameters) Param[2]: posX (type: int) Param[3]: posY (type: int) Param[4]: color (type: Color) -Function 332: ImageDrawPixelV() (3 input parameters) +Function 333: ImageDrawPixelV() (3 input parameters) Name: ImageDrawPixelV Return type: void Description: Draw pixel within an image (Vector version) Param[1]: dst (type: Image *) Param[2]: position (type: Vector2) Param[3]: color (type: Color) -Function 333: ImageDrawLine() (6 input parameters) +Function 334: ImageDrawLine() (6 input parameters) Name: ImageDrawLine Return type: void Description: Draw line within an image @@ -3030,7 +3036,7 @@ Function 333: ImageDrawLine() (6 input parameters) Param[4]: endPosX (type: int) Param[5]: endPosY (type: int) Param[6]: color (type: Color) -Function 334: ImageDrawLineV() (4 input parameters) +Function 335: ImageDrawLineV() (4 input parameters) Name: ImageDrawLineV Return type: void Description: Draw line within an image (Vector version) @@ -3038,7 +3044,7 @@ Function 334: ImageDrawLineV() (4 input parameters) Param[2]: start (type: Vector2) Param[3]: end (type: Vector2) Param[4]: color (type: Color) -Function 335: ImageDrawLineEx() (5 input parameters) +Function 336: ImageDrawLineEx() (5 input parameters) Name: ImageDrawLineEx Return type: void Description: Draw a line defining thickness within an image @@ -3047,7 +3053,7 @@ Function 335: ImageDrawLineEx() (5 input parameters) Param[3]: end (type: Vector2) Param[4]: thick (type: int) Param[5]: color (type: Color) -Function 336: ImageDrawCircle() (5 input parameters) +Function 337: ImageDrawCircle() (5 input parameters) Name: ImageDrawCircle Return type: void Description: Draw a filled circle within an image @@ -3056,7 +3062,7 @@ Function 336: ImageDrawCircle() (5 input parameters) Param[3]: centerY (type: int) Param[4]: radius (type: int) Param[5]: color (type: Color) -Function 337: ImageDrawCircleV() (4 input parameters) +Function 338: ImageDrawCircleV() (4 input parameters) Name: ImageDrawCircleV Return type: void Description: Draw a filled circle within an image (Vector version) @@ -3064,7 +3070,7 @@ Function 337: ImageDrawCircleV() (4 input parameters) Param[2]: center (type: Vector2) Param[3]: radius (type: int) Param[4]: color (type: Color) -Function 338: ImageDrawCircleLines() (5 input parameters) +Function 339: ImageDrawCircleLines() (5 input parameters) Name: ImageDrawCircleLines Return type: void Description: Draw circle outline within an image @@ -3073,7 +3079,7 @@ Function 338: ImageDrawCircleLines() (5 input parameters) Param[3]: centerY (type: int) Param[4]: radius (type: int) Param[5]: color (type: Color) -Function 339: ImageDrawCircleLinesV() (4 input parameters) +Function 340: ImageDrawCircleLinesV() (4 input parameters) Name: ImageDrawCircleLinesV Return type: void Description: Draw circle outline within an image (Vector version) @@ -3081,7 +3087,7 @@ Function 339: ImageDrawCircleLinesV() (4 input parameters) Param[2]: center (type: Vector2) Param[3]: radius (type: int) Param[4]: color (type: Color) -Function 340: ImageDrawRectangle() (6 input parameters) +Function 341: ImageDrawRectangle() (6 input parameters) Name: ImageDrawRectangle Return type: void Description: Draw rectangle within an image @@ -3091,7 +3097,7 @@ Function 340: ImageDrawRectangle() (6 input parameters) Param[4]: width (type: int) Param[5]: height (type: int) Param[6]: color (type: Color) -Function 341: ImageDrawRectangleV() (4 input parameters) +Function 342: ImageDrawRectangleV() (4 input parameters) Name: ImageDrawRectangleV Return type: void Description: Draw rectangle within an image (Vector version) @@ -3099,14 +3105,14 @@ Function 341: ImageDrawRectangleV() (4 input parameters) Param[2]: position (type: Vector2) Param[3]: size (type: Vector2) Param[4]: color (type: Color) -Function 342: ImageDrawRectangleRec() (3 input parameters) +Function 343: ImageDrawRectangleRec() (3 input parameters) Name: ImageDrawRectangleRec Return type: void Description: Draw rectangle within an image Param[1]: dst (type: Image *) Param[2]: rec (type: Rectangle) Param[3]: color (type: Color) -Function 343: ImageDrawRectangleLines() (4 input parameters) +Function 344: ImageDrawRectangleLines() (4 input parameters) Name: ImageDrawRectangleLines Return type: void Description: Draw rectangle lines within an image @@ -3114,7 +3120,7 @@ Function 343: ImageDrawRectangleLines() (4 input parameters) Param[2]: rec (type: Rectangle) Param[3]: thick (type: int) Param[4]: color (type: Color) -Function 344: ImageDrawTriangle() (5 input parameters) +Function 345: ImageDrawTriangle() (5 input parameters) Name: ImageDrawTriangle Return type: void Description: Draw triangle within an image @@ -3123,7 +3129,7 @@ Function 344: ImageDrawTriangle() (5 input parameters) Param[3]: v2 (type: Vector2) Param[4]: v3 (type: Vector2) Param[5]: color (type: Color) -Function 345: ImageDrawTriangleEx() (7 input parameters) +Function 346: ImageDrawTriangleEx() (7 input parameters) Name: ImageDrawTriangleEx Return type: void Description: Draw triangle with interpolated colors within an image @@ -3134,7 +3140,7 @@ Function 345: ImageDrawTriangleEx() (7 input parameters) Param[5]: c1 (type: Color) Param[6]: c2 (type: Color) Param[7]: c3 (type: Color) -Function 346: ImageDrawTriangleLines() (5 input parameters) +Function 347: ImageDrawTriangleLines() (5 input parameters) Name: ImageDrawTriangleLines Return type: void Description: Draw triangle outline within an image @@ -3143,7 +3149,7 @@ Function 346: ImageDrawTriangleLines() (5 input parameters) Param[3]: v2 (type: Vector2) Param[4]: v3 (type: Vector2) Param[5]: color (type: Color) -Function 347: ImageDrawTriangleFan() (4 input parameters) +Function 348: ImageDrawTriangleFan() (4 input parameters) Name: ImageDrawTriangleFan Return type: void Description: Draw a triangle fan defined by points within an image (first vertex is the center) @@ -3151,7 +3157,7 @@ Function 347: ImageDrawTriangleFan() (4 input parameters) Param[2]: points (type: Vector2 *) Param[3]: pointCount (type: int) Param[4]: color (type: Color) -Function 348: ImageDrawTriangleStrip() (4 input parameters) +Function 349: ImageDrawTriangleStrip() (4 input parameters) Name: ImageDrawTriangleStrip Return type: void Description: Draw a triangle strip defined by points within an image @@ -3159,7 +3165,7 @@ Function 348: ImageDrawTriangleStrip() (4 input parameters) Param[2]: points (type: Vector2 *) Param[3]: pointCount (type: int) Param[4]: color (type: Color) -Function 349: ImageDraw() (5 input parameters) +Function 350: ImageDraw() (5 input parameters) Name: ImageDraw Return type: void Description: Draw a source image within a destination image (tint applied to source) @@ -3168,7 +3174,7 @@ Function 349: ImageDraw() (5 input parameters) Param[3]: srcRec (type: Rectangle) Param[4]: dstRec (type: Rectangle) Param[5]: tint (type: Color) -Function 350: ImageDrawText() (6 input parameters) +Function 351: ImageDrawText() (6 input parameters) Name: ImageDrawText Return type: void Description: Draw text (using default font) within an image (destination) @@ -3178,7 +3184,7 @@ Function 350: ImageDrawText() (6 input parameters) Param[4]: posY (type: int) Param[5]: fontSize (type: int) Param[6]: color (type: Color) -Function 351: ImageDrawTextEx() (7 input parameters) +Function 352: ImageDrawTextEx() (7 input parameters) Name: ImageDrawTextEx Return type: void Description: Draw text (custom sprite font) within an image (destination) @@ -3189,79 +3195,79 @@ Function 351: ImageDrawTextEx() (7 input parameters) Param[5]: fontSize (type: float) Param[6]: spacing (type: float) Param[7]: tint (type: Color) -Function 352: LoadTexture() (1 input parameters) +Function 353: LoadTexture() (1 input parameters) Name: LoadTexture Return type: Texture2D Description: Load texture from file into GPU memory (VRAM) Param[1]: fileName (type: const char *) -Function 353: LoadTextureFromImage() (1 input parameters) +Function 354: LoadTextureFromImage() (1 input parameters) Name: LoadTextureFromImage Return type: Texture2D Description: Load texture from image data Param[1]: image (type: Image) -Function 354: LoadTextureCubemap() (2 input parameters) +Function 355: LoadTextureCubemap() (2 input parameters) Name: LoadTextureCubemap Return type: TextureCubemap Description: Load cubemap from image, multiple image cubemap layouts supported Param[1]: image (type: Image) Param[2]: layout (type: int) -Function 355: LoadRenderTexture() (2 input parameters) +Function 356: LoadRenderTexture() (2 input parameters) Name: LoadRenderTexture Return type: RenderTexture2D Description: Load texture for rendering (framebuffer) Param[1]: width (type: int) Param[2]: height (type: int) -Function 356: IsTextureValid() (1 input parameters) +Function 357: IsTextureValid() (1 input parameters) Name: IsTextureValid Return type: bool Description: Check if a texture is valid (loaded in GPU) Param[1]: texture (type: Texture2D) -Function 357: UnloadTexture() (1 input parameters) +Function 358: UnloadTexture() (1 input parameters) Name: UnloadTexture Return type: void Description: Unload texture from GPU memory (VRAM) Param[1]: texture (type: Texture2D) -Function 358: IsRenderTextureValid() (1 input parameters) +Function 359: IsRenderTextureValid() (1 input parameters) Name: IsRenderTextureValid Return type: bool Description: Check if a render texture is valid (loaded in GPU) Param[1]: target (type: RenderTexture2D) -Function 359: UnloadRenderTexture() (1 input parameters) +Function 360: UnloadRenderTexture() (1 input parameters) Name: UnloadRenderTexture Return type: void Description: Unload render texture from GPU memory (VRAM) Param[1]: target (type: RenderTexture2D) -Function 360: UpdateTexture() (2 input parameters) +Function 361: UpdateTexture() (2 input parameters) Name: UpdateTexture Return type: void Description: Update GPU texture with new data Param[1]: texture (type: Texture2D) Param[2]: pixels (type: const void *) -Function 361: UpdateTextureRec() (3 input parameters) +Function 362: UpdateTextureRec() (3 input parameters) Name: UpdateTextureRec Return type: void Description: Update GPU texture rectangle with new data Param[1]: texture (type: Texture2D) Param[2]: rec (type: Rectangle) Param[3]: pixels (type: const void *) -Function 362: GenTextureMipmaps() (1 input parameters) +Function 363: GenTextureMipmaps() (1 input parameters) Name: GenTextureMipmaps Return type: void Description: Generate GPU mipmaps for a texture Param[1]: texture (type: Texture2D *) -Function 363: SetTextureFilter() (2 input parameters) +Function 364: SetTextureFilter() (2 input parameters) Name: SetTextureFilter Return type: void Description: Set texture scaling filter mode Param[1]: texture (type: Texture2D) Param[2]: filter (type: int) -Function 364: SetTextureWrap() (2 input parameters) +Function 365: SetTextureWrap() (2 input parameters) Name: SetTextureWrap Return type: void Description: Set texture wrapping mode Param[1]: texture (type: Texture2D) Param[2]: wrap (type: int) -Function 365: DrawTexture() (4 input parameters) +Function 366: DrawTexture() (4 input parameters) Name: DrawTexture Return type: void Description: Draw a Texture2D @@ -3269,14 +3275,14 @@ Function 365: DrawTexture() (4 input parameters) Param[2]: posX (type: int) Param[3]: posY (type: int) Param[4]: tint (type: Color) -Function 366: DrawTextureV() (3 input parameters) +Function 367: DrawTextureV() (3 input parameters) Name: DrawTextureV Return type: void Description: Draw a Texture2D with position defined as Vector2 Param[1]: texture (type: Texture2D) Param[2]: position (type: Vector2) Param[3]: tint (type: Color) -Function 367: DrawTextureEx() (5 input parameters) +Function 368: DrawTextureEx() (5 input parameters) Name: DrawTextureEx Return type: void Description: Draw a Texture2D with extended parameters @@ -3285,7 +3291,7 @@ Function 367: DrawTextureEx() (5 input parameters) Param[3]: rotation (type: float) Param[4]: scale (type: float) Param[5]: tint (type: Color) -Function 368: DrawTextureRec() (4 input parameters) +Function 369: DrawTextureRec() (4 input parameters) Name: DrawTextureRec Return type: void Description: Draw a part of a texture defined by a rectangle @@ -3293,7 +3299,7 @@ Function 368: DrawTextureRec() (4 input parameters) Param[2]: source (type: Rectangle) Param[3]: position (type: Vector2) Param[4]: tint (type: Color) -Function 369: DrawTexturePro() (6 input parameters) +Function 370: DrawTexturePro() (6 input parameters) Name: DrawTexturePro Return type: void Description: Draw a part of a texture defined by a rectangle with 'pro' parameters @@ -3303,7 +3309,7 @@ Function 369: DrawTexturePro() (6 input parameters) Param[4]: origin (type: Vector2) Param[5]: rotation (type: float) Param[6]: tint (type: Color) -Function 370: DrawTextureNPatch() (6 input parameters) +Function 371: DrawTextureNPatch() (6 input parameters) Name: DrawTextureNPatch Return type: void Description: Draws a texture (or part of it) that stretches or shrinks nicely @@ -3313,119 +3319,119 @@ Function 370: DrawTextureNPatch() (6 input parameters) Param[4]: origin (type: Vector2) Param[5]: rotation (type: float) Param[6]: tint (type: Color) -Function 371: ColorIsEqual() (2 input parameters) +Function 372: ColorIsEqual() (2 input parameters) Name: ColorIsEqual Return type: bool Description: Check if two colors are equal Param[1]: col1 (type: Color) Param[2]: col2 (type: Color) -Function 372: Fade() (2 input parameters) +Function 373: Fade() (2 input parameters) Name: Fade Return type: Color Description: Get color with alpha applied, alpha goes from 0.0f to 1.0f Param[1]: color (type: Color) Param[2]: alpha (type: float) -Function 373: ColorToInt() (1 input parameters) +Function 374: ColorToInt() (1 input parameters) Name: ColorToInt Return type: int Description: Get hexadecimal value for a Color (0xRRGGBBAA) Param[1]: color (type: Color) -Function 374: ColorNormalize() (1 input parameters) +Function 375: ColorNormalize() (1 input parameters) Name: ColorNormalize Return type: Vector4 Description: Get Color normalized as float [0..1] Param[1]: color (type: Color) -Function 375: ColorFromNormalized() (1 input parameters) +Function 376: ColorFromNormalized() (1 input parameters) Name: ColorFromNormalized Return type: Color Description: Get Color from normalized values [0..1] Param[1]: normalized (type: Vector4) -Function 376: ColorToHSV() (1 input parameters) +Function 377: ColorToHSV() (1 input parameters) Name: ColorToHSV Return type: Vector3 Description: Get HSV values for a Color, hue [0..360], saturation/value [0..1] Param[1]: color (type: Color) -Function 377: ColorFromHSV() (3 input parameters) +Function 378: ColorFromHSV() (3 input parameters) Name: ColorFromHSV Return type: Color Description: Get a Color from HSV values, hue [0..360], saturation/value [0..1] Param[1]: hue (type: float) Param[2]: saturation (type: float) Param[3]: value (type: float) -Function 378: ColorTint() (2 input parameters) +Function 379: ColorTint() (2 input parameters) Name: ColorTint Return type: Color Description: Get color multiplied with another color Param[1]: color (type: Color) Param[2]: tint (type: Color) -Function 379: ColorBrightness() (2 input parameters) +Function 380: ColorBrightness() (2 input parameters) Name: ColorBrightness Return type: Color Description: Get color with brightness correction, brightness factor goes from -1.0f to 1.0f Param[1]: color (type: Color) Param[2]: factor (type: float) -Function 380: ColorContrast() (2 input parameters) +Function 381: ColorContrast() (2 input parameters) Name: ColorContrast Return type: Color Description: Get color with contrast correction, contrast values between -1.0f and 1.0f Param[1]: color (type: Color) Param[2]: contrast (type: float) -Function 381: ColorAlpha() (2 input parameters) +Function 382: ColorAlpha() (2 input parameters) Name: ColorAlpha Return type: Color Description: Get color with alpha applied, alpha goes from 0.0f to 1.0f Param[1]: color (type: Color) Param[2]: alpha (type: float) -Function 382: ColorAlphaBlend() (3 input parameters) +Function 383: ColorAlphaBlend() (3 input parameters) Name: ColorAlphaBlend Return type: Color Description: Get src alpha-blended into dst color with tint Param[1]: dst (type: Color) Param[2]: src (type: Color) Param[3]: tint (type: Color) -Function 383: ColorLerp() (3 input parameters) +Function 384: ColorLerp() (3 input parameters) Name: ColorLerp Return type: Color Description: Get color lerp interpolation between two colors, factor [0.0f..1.0f] Param[1]: color1 (type: Color) Param[2]: color2 (type: Color) Param[3]: factor (type: float) -Function 384: GetColor() (1 input parameters) +Function 385: GetColor() (1 input parameters) Name: GetColor Return type: Color Description: Get Color structure from hexadecimal value Param[1]: hexValue (type: unsigned int) -Function 385: GetPixelColor() (2 input parameters) +Function 386: GetPixelColor() (2 input parameters) Name: GetPixelColor Return type: Color Description: Get Color from a source pixel pointer of certain format Param[1]: srcPtr (type: void *) Param[2]: format (type: int) -Function 386: SetPixelColor() (3 input parameters) +Function 387: SetPixelColor() (3 input parameters) Name: SetPixelColor Return type: void Description: Set color formatted into destination pixel pointer Param[1]: dstPtr (type: void *) Param[2]: color (type: Color) Param[3]: format (type: int) -Function 387: GetPixelDataSize() (3 input parameters) +Function 388: GetPixelDataSize() (3 input parameters) Name: GetPixelDataSize Return type: int Description: Get pixel data size in bytes for certain format Param[1]: width (type: int) Param[2]: height (type: int) Param[3]: format (type: int) -Function 388: GetFontDefault() (0 input parameters) +Function 389: GetFontDefault() (0 input parameters) Name: GetFontDefault Return type: Font Description: Get the default Font No input parameters -Function 389: LoadFont() (1 input parameters) +Function 390: LoadFont() (1 input parameters) Name: LoadFont Return type: Font Description: Load font from file into GPU memory (VRAM) Param[1]: fileName (type: const char *) -Function 390: LoadFontEx() (4 input parameters) +Function 391: LoadFontEx() (4 input parameters) Name: LoadFontEx Return type: Font Description: Load font from file with extended parameters, use NULL for codepoints and 0 for codepointCount to load the default character set, font size is provided in pixels height @@ -3433,14 +3439,14 @@ Function 390: LoadFontEx() (4 input parameters) Param[2]: fontSize (type: int) Param[3]: codepoints (type: int *) Param[4]: codepointCount (type: int) -Function 391: LoadFontFromImage() (3 input parameters) +Function 392: LoadFontFromImage() (3 input parameters) Name: LoadFontFromImage Return type: Font Description: Load font from Image (XNA style) Param[1]: image (type: Image) Param[2]: key (type: Color) Param[3]: firstChar (type: int) -Function 392: LoadFontFromMemory() (6 input parameters) +Function 393: LoadFontFromMemory() (6 input parameters) Name: LoadFontFromMemory Return type: Font Description: Load font from memory buffer, fileType refers to extension: i.e. '.ttf' @@ -3450,12 +3456,12 @@ Function 392: LoadFontFromMemory() (6 input parameters) Param[4]: fontSize (type: int) Param[5]: codepoints (type: int *) Param[6]: codepointCount (type: int) -Function 393: IsFontValid() (1 input parameters) +Function 394: IsFontValid() (1 input parameters) Name: IsFontValid Return type: bool Description: Check if a font is valid (font data loaded, WARNING: GPU texture not checked) Param[1]: font (type: Font) -Function 394: LoadFontData() (6 input parameters) +Function 395: LoadFontData() (6 input parameters) Name: LoadFontData Return type: GlyphInfo * Description: Load font data for further use @@ -3465,7 +3471,7 @@ Function 394: LoadFontData() (6 input parameters) Param[4]: codepoints (type: int *) Param[5]: codepointCount (type: int) Param[6]: type (type: int) -Function 395: GenImageFontAtlas() (6 input parameters) +Function 396: GenImageFontAtlas() (6 input parameters) Name: GenImageFontAtlas Return type: Image Description: Generate image font atlas using chars info @@ -3475,30 +3481,30 @@ Function 395: GenImageFontAtlas() (6 input parameters) Param[4]: fontSize (type: int) Param[5]: padding (type: int) Param[6]: packMethod (type: int) -Function 396: UnloadFontData() (2 input parameters) +Function 397: UnloadFontData() (2 input parameters) Name: UnloadFontData Return type: void Description: Unload font chars info data (RAM) Param[1]: glyphs (type: GlyphInfo *) Param[2]: glyphCount (type: int) -Function 397: UnloadFont() (1 input parameters) +Function 398: UnloadFont() (1 input parameters) Name: UnloadFont Return type: void Description: Unload font from GPU memory (VRAM) Param[1]: font (type: Font) -Function 398: ExportFontAsCode() (2 input parameters) +Function 399: ExportFontAsCode() (2 input parameters) Name: ExportFontAsCode Return type: bool Description: Export font as code file, returns true on success Param[1]: font (type: Font) Param[2]: fileName (type: const char *) -Function 399: DrawFPS() (2 input parameters) +Function 400: DrawFPS() (2 input parameters) Name: DrawFPS Return type: void Description: Draw current FPS Param[1]: posX (type: int) Param[2]: posY (type: int) -Function 400: DrawText() (5 input parameters) +Function 401: DrawText() (5 input parameters) Name: DrawText Return type: void Description: Draw text (using default font) @@ -3507,7 +3513,7 @@ Function 400: DrawText() (5 input parameters) Param[3]: posY (type: int) Param[4]: fontSize (type: int) Param[5]: color (type: Color) -Function 401: DrawTextEx() (6 input parameters) +Function 402: DrawTextEx() (6 input parameters) Name: DrawTextEx Return type: void Description: Draw text using font and additional parameters @@ -3517,7 +3523,7 @@ Function 401: DrawTextEx() (6 input parameters) Param[4]: fontSize (type: float) Param[5]: spacing (type: float) Param[6]: tint (type: Color) -Function 402: DrawTextPro() (8 input parameters) +Function 403: DrawTextPro() (8 input parameters) Name: DrawTextPro Return type: void Description: Draw text using Font and pro parameters (rotation) @@ -3529,7 +3535,7 @@ Function 402: DrawTextPro() (8 input parameters) Param[6]: fontSize (type: float) Param[7]: spacing (type: float) Param[8]: tint (type: Color) -Function 403: DrawTextCodepoint() (5 input parameters) +Function 404: DrawTextCodepoint() (5 input parameters) Name: DrawTextCodepoint Return type: void Description: Draw one character (codepoint) @@ -3538,7 +3544,7 @@ Function 403: DrawTextCodepoint() (5 input parameters) Param[3]: position (type: Vector2) Param[4]: fontSize (type: float) Param[5]: tint (type: Color) -Function 404: DrawTextCodepoints() (7 input parameters) +Function 405: DrawTextCodepoints() (7 input parameters) Name: DrawTextCodepoints Return type: void Description: Draw multiple character (codepoint) @@ -3549,18 +3555,18 @@ Function 404: DrawTextCodepoints() (7 input parameters) Param[5]: fontSize (type: float) Param[6]: spacing (type: float) Param[7]: tint (type: Color) -Function 405: SetTextLineSpacing() (1 input parameters) +Function 406: SetTextLineSpacing() (1 input parameters) Name: SetTextLineSpacing Return type: void Description: Set vertical line spacing when drawing with line-breaks Param[1]: spacing (type: int) -Function 406: MeasureText() (2 input parameters) +Function 407: MeasureText() (2 input parameters) Name: MeasureText Return type: int Description: Measure string width for default font Param[1]: text (type: const char *) Param[2]: fontSize (type: int) -Function 407: MeasureTextEx() (4 input parameters) +Function 408: MeasureTextEx() (4 input parameters) Name: MeasureTextEx Return type: Vector2 Description: Measure string size for Font @@ -3568,195 +3574,195 @@ Function 407: MeasureTextEx() (4 input parameters) Param[2]: text (type: const char *) Param[3]: fontSize (type: float) Param[4]: spacing (type: float) -Function 408: GetGlyphIndex() (2 input parameters) +Function 409: GetGlyphIndex() (2 input parameters) Name: GetGlyphIndex Return type: int Description: Get glyph index position in font for a codepoint (unicode character), fallback to '?' if not found Param[1]: font (type: Font) Param[2]: codepoint (type: int) -Function 409: GetGlyphInfo() (2 input parameters) +Function 410: GetGlyphInfo() (2 input parameters) Name: GetGlyphInfo Return type: GlyphInfo Description: Get glyph font info data for a codepoint (unicode character), fallback to '?' if not found Param[1]: font (type: Font) Param[2]: codepoint (type: int) -Function 410: GetGlyphAtlasRec() (2 input parameters) +Function 411: GetGlyphAtlasRec() (2 input parameters) Name: GetGlyphAtlasRec Return type: Rectangle Description: Get glyph rectangle in font atlas for a codepoint (unicode character), fallback to '?' if not found Param[1]: font (type: Font) Param[2]: codepoint (type: int) -Function 411: LoadUTF8() (2 input parameters) +Function 412: LoadUTF8() (2 input parameters) Name: LoadUTF8 Return type: char * Description: Load UTF-8 text encoded from codepoints array Param[1]: codepoints (type: const int *) Param[2]: length (type: int) -Function 412: UnloadUTF8() (1 input parameters) +Function 413: UnloadUTF8() (1 input parameters) Name: UnloadUTF8 Return type: void Description: Unload UTF-8 text encoded from codepoints array Param[1]: text (type: char *) -Function 413: LoadCodepoints() (2 input parameters) +Function 414: LoadCodepoints() (2 input parameters) Name: LoadCodepoints Return type: int * Description: Load all codepoints from a UTF-8 text string, codepoints count returned by parameter Param[1]: text (type: const char *) Param[2]: count (type: int *) -Function 414: UnloadCodepoints() (1 input parameters) +Function 415: UnloadCodepoints() (1 input parameters) Name: UnloadCodepoints Return type: void Description: Unload codepoints data from memory Param[1]: codepoints (type: int *) -Function 415: GetCodepointCount() (1 input parameters) +Function 416: GetCodepointCount() (1 input parameters) Name: GetCodepointCount Return type: int Description: Get total number of codepoints in a UTF-8 encoded string Param[1]: text (type: const char *) -Function 416: GetCodepoint() (2 input parameters) +Function 417: GetCodepoint() (2 input parameters) Name: GetCodepoint Return type: int Description: Get next codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure Param[1]: text (type: const char *) Param[2]: codepointSize (type: int *) -Function 417: GetCodepointNext() (2 input parameters) +Function 418: GetCodepointNext() (2 input parameters) Name: GetCodepointNext Return type: int Description: Get next codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure Param[1]: text (type: const char *) Param[2]: codepointSize (type: int *) -Function 418: GetCodepointPrevious() (2 input parameters) +Function 419: GetCodepointPrevious() (2 input parameters) Name: GetCodepointPrevious Return type: int Description: Get previous codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure Param[1]: text (type: const char *) Param[2]: codepointSize (type: int *) -Function 419: CodepointToUTF8() (2 input parameters) +Function 420: CodepointToUTF8() (2 input parameters) Name: CodepointToUTF8 Return type: const char * Description: Encode one codepoint into UTF-8 byte array (array length returned as parameter) Param[1]: codepoint (type: int) Param[2]: utf8Size (type: int *) -Function 420: TextCopy() (2 input parameters) +Function 421: TextCopy() (2 input parameters) Name: TextCopy Return type: int Description: Copy one string to another, returns bytes copied Param[1]: dst (type: char *) Param[2]: src (type: const char *) -Function 421: TextIsEqual() (2 input parameters) +Function 422: TextIsEqual() (2 input parameters) Name: TextIsEqual Return type: bool Description: Check if two text string are equal Param[1]: text1 (type: const char *) Param[2]: text2 (type: const char *) -Function 422: TextLength() (1 input parameters) +Function 423: TextLength() (1 input parameters) Name: TextLength Return type: unsigned int Description: Get text length, checks for '\0' ending Param[1]: text (type: const char *) -Function 423: TextFormat() (2 input parameters) +Function 424: TextFormat() (2 input parameters) Name: TextFormat Return type: const char * Description: Text formatting with variables (sprintf() style) Param[1]: text (type: const char *) Param[2]: args (type: ...) -Function 424: TextSubtext() (3 input parameters) +Function 425: TextSubtext() (3 input parameters) Name: TextSubtext Return type: const char * Description: Get a piece of a text string Param[1]: text (type: const char *) Param[2]: position (type: int) Param[3]: length (type: int) -Function 425: TextReplace() (3 input parameters) +Function 426: TextReplace() (3 input parameters) Name: TextReplace Return type: char * Description: Replace text string (WARNING: memory must be freed!) Param[1]: text (type: const char *) Param[2]: replace (type: const char *) Param[3]: by (type: const char *) -Function 426: TextInsert() (3 input parameters) +Function 427: TextInsert() (3 input parameters) Name: TextInsert Return type: char * Description: Insert text in a position (WARNING: memory must be freed!) Param[1]: text (type: const char *) Param[2]: insert (type: const char *) Param[3]: position (type: int) -Function 427: TextJoin() (3 input parameters) +Function 428: TextJoin() (3 input parameters) Name: TextJoin Return type: const char * Description: Join text strings with delimiter Param[1]: textList (type: const char **) Param[2]: count (type: int) Param[3]: delimiter (type: const char *) -Function 428: TextSplit() (3 input parameters) +Function 429: TextSplit() (3 input parameters) Name: TextSplit Return type: const char ** Description: Split text into multiple strings Param[1]: text (type: const char *) Param[2]: delimiter (type: char) Param[3]: count (type: int *) -Function 429: TextAppend() (3 input parameters) +Function 430: TextAppend() (3 input parameters) Name: TextAppend Return type: void Description: Append text at specific position and move cursor! Param[1]: text (type: char *) Param[2]: append (type: const char *) Param[3]: position (type: int *) -Function 430: TextFindIndex() (2 input parameters) +Function 431: TextFindIndex() (2 input parameters) Name: TextFindIndex Return type: int Description: Find first text occurrence within a string Param[1]: text (type: const char *) Param[2]: find (type: const char *) -Function 431: TextToUpper() (1 input parameters) +Function 432: TextToUpper() (1 input parameters) Name: TextToUpper Return type: const char * Description: Get upper case version of provided string Param[1]: text (type: const char *) -Function 432: TextToLower() (1 input parameters) +Function 433: TextToLower() (1 input parameters) Name: TextToLower Return type: const char * Description: Get lower case version of provided string Param[1]: text (type: const char *) -Function 433: TextToPascal() (1 input parameters) +Function 434: TextToPascal() (1 input parameters) Name: TextToPascal Return type: const char * Description: Get Pascal case notation version of provided string Param[1]: text (type: const char *) -Function 434: TextToSnake() (1 input parameters) +Function 435: TextToSnake() (1 input parameters) Name: TextToSnake Return type: const char * Description: Get Snake case notation version of provided string Param[1]: text (type: const char *) -Function 435: TextToCamel() (1 input parameters) +Function 436: TextToCamel() (1 input parameters) Name: TextToCamel Return type: const char * Description: Get Camel case notation version of provided string Param[1]: text (type: const char *) -Function 436: TextToInteger() (1 input parameters) +Function 437: TextToInteger() (1 input parameters) Name: TextToInteger Return type: int Description: Get integer value from text (negative values not supported) Param[1]: text (type: const char *) -Function 437: TextToFloat() (1 input parameters) +Function 438: TextToFloat() (1 input parameters) Name: TextToFloat Return type: float Description: Get float value from text (negative values not supported) Param[1]: text (type: const char *) -Function 438: DrawLine3D() (3 input parameters) +Function 439: DrawLine3D() (3 input parameters) Name: DrawLine3D Return type: void Description: Draw a line in 3D world space Param[1]: startPos (type: Vector3) Param[2]: endPos (type: Vector3) Param[3]: color (type: Color) -Function 439: DrawPoint3D() (2 input parameters) +Function 440: DrawPoint3D() (2 input parameters) Name: DrawPoint3D Return type: void Description: Draw a point in 3D space, actually a small line Param[1]: position (type: Vector3) Param[2]: color (type: Color) -Function 440: DrawCircle3D() (5 input parameters) +Function 441: DrawCircle3D() (5 input parameters) Name: DrawCircle3D Return type: void Description: Draw a circle in 3D world space @@ -3765,7 +3771,7 @@ Function 440: DrawCircle3D() (5 input parameters) Param[3]: rotationAxis (type: Vector3) Param[4]: rotationAngle (type: float) Param[5]: color (type: Color) -Function 441: DrawTriangle3D() (4 input parameters) +Function 442: DrawTriangle3D() (4 input parameters) Name: DrawTriangle3D Return type: void Description: Draw a color-filled triangle (vertex in counter-clockwise order!) @@ -3773,14 +3779,14 @@ Function 441: DrawTriangle3D() (4 input parameters) Param[2]: v2 (type: Vector3) Param[3]: v3 (type: Vector3) Param[4]: color (type: Color) -Function 442: DrawTriangleStrip3D() (3 input parameters) +Function 443: DrawTriangleStrip3D() (3 input parameters) Name: DrawTriangleStrip3D Return type: void Description: Draw a triangle strip defined by points Param[1]: points (type: const Vector3 *) Param[2]: pointCount (type: int) Param[3]: color (type: Color) -Function 443: DrawCube() (5 input parameters) +Function 444: DrawCube() (5 input parameters) Name: DrawCube Return type: void Description: Draw cube @@ -3789,14 +3795,14 @@ Function 443: DrawCube() (5 input parameters) Param[3]: height (type: float) Param[4]: length (type: float) Param[5]: color (type: Color) -Function 444: DrawCubeV() (3 input parameters) +Function 445: DrawCubeV() (3 input parameters) Name: DrawCubeV Return type: void Description: Draw cube (Vector version) Param[1]: position (type: Vector3) Param[2]: size (type: Vector3) Param[3]: color (type: Color) -Function 445: DrawCubeWires() (5 input parameters) +Function 446: DrawCubeWires() (5 input parameters) Name: DrawCubeWires Return type: void Description: Draw cube wires @@ -3805,21 +3811,21 @@ Function 445: DrawCubeWires() (5 input parameters) Param[3]: height (type: float) Param[4]: length (type: float) Param[5]: color (type: Color) -Function 446: DrawCubeWiresV() (3 input parameters) +Function 447: DrawCubeWiresV() (3 input parameters) Name: DrawCubeWiresV Return type: void Description: Draw cube wires (Vector version) Param[1]: position (type: Vector3) Param[2]: size (type: Vector3) Param[3]: color (type: Color) -Function 447: DrawSphere() (3 input parameters) +Function 448: DrawSphere() (3 input parameters) Name: DrawSphere Return type: void Description: Draw sphere Param[1]: centerPos (type: Vector3) Param[2]: radius (type: float) Param[3]: color (type: Color) -Function 448: DrawSphereEx() (5 input parameters) +Function 449: DrawSphereEx() (5 input parameters) Name: DrawSphereEx Return type: void Description: Draw sphere with extended parameters @@ -3828,7 +3834,7 @@ Function 448: DrawSphereEx() (5 input parameters) Param[3]: rings (type: int) Param[4]: slices (type: int) Param[5]: color (type: Color) -Function 449: DrawSphereWires() (5 input parameters) +Function 450: DrawSphereWires() (5 input parameters) Name: DrawSphereWires Return type: void Description: Draw sphere wires @@ -3837,7 +3843,7 @@ Function 449: DrawSphereWires() (5 input parameters) Param[3]: rings (type: int) Param[4]: slices (type: int) Param[5]: color (type: Color) -Function 450: DrawCylinder() (6 input parameters) +Function 451: DrawCylinder() (6 input parameters) Name: DrawCylinder Return type: void Description: Draw a cylinder/cone @@ -3847,7 +3853,7 @@ Function 450: DrawCylinder() (6 input parameters) Param[4]: height (type: float) Param[5]: slices (type: int) Param[6]: color (type: Color) -Function 451: DrawCylinderEx() (6 input parameters) +Function 452: DrawCylinderEx() (6 input parameters) Name: DrawCylinderEx Return type: void Description: Draw a cylinder with base at startPos and top at endPos @@ -3857,7 +3863,7 @@ Function 451: DrawCylinderEx() (6 input parameters) Param[4]: endRadius (type: float) Param[5]: sides (type: int) Param[6]: color (type: Color) -Function 452: DrawCylinderWires() (6 input parameters) +Function 453: DrawCylinderWires() (6 input parameters) Name: DrawCylinderWires Return type: void Description: Draw a cylinder/cone wires @@ -3867,7 +3873,7 @@ Function 452: DrawCylinderWires() (6 input parameters) Param[4]: height (type: float) Param[5]: slices (type: int) Param[6]: color (type: Color) -Function 453: DrawCylinderWiresEx() (6 input parameters) +Function 454: DrawCylinderWiresEx() (6 input parameters) Name: DrawCylinderWiresEx Return type: void Description: Draw a cylinder wires with base at startPos and top at endPos @@ -3877,7 +3883,7 @@ Function 453: DrawCylinderWiresEx() (6 input parameters) Param[4]: endRadius (type: float) Param[5]: sides (type: int) Param[6]: color (type: Color) -Function 454: DrawCapsule() (6 input parameters) +Function 455: DrawCapsule() (6 input parameters) Name: DrawCapsule Return type: void Description: Draw a capsule with the center of its sphere caps at startPos and endPos @@ -3887,7 +3893,7 @@ Function 454: DrawCapsule() (6 input parameters) Param[4]: slices (type: int) Param[5]: rings (type: int) Param[6]: color (type: Color) -Function 455: DrawCapsuleWires() (6 input parameters) +Function 456: DrawCapsuleWires() (6 input parameters) Name: DrawCapsuleWires Return type: void Description: Draw capsule wireframe with the center of its sphere caps at startPos and endPos @@ -3897,51 +3903,51 @@ Function 455: DrawCapsuleWires() (6 input parameters) Param[4]: slices (type: int) Param[5]: rings (type: int) Param[6]: color (type: Color) -Function 456: DrawPlane() (3 input parameters) +Function 457: DrawPlane() (3 input parameters) Name: DrawPlane Return type: void Description: Draw a plane XZ Param[1]: centerPos (type: Vector3) Param[2]: size (type: Vector2) Param[3]: color (type: Color) -Function 457: DrawRay() (2 input parameters) +Function 458: DrawRay() (2 input parameters) Name: DrawRay Return type: void Description: Draw a ray line Param[1]: ray (type: Ray) Param[2]: color (type: Color) -Function 458: DrawGrid() (2 input parameters) +Function 459: DrawGrid() (2 input parameters) Name: DrawGrid Return type: void Description: Draw a grid (centered at (0, 0, 0)) Param[1]: slices (type: int) Param[2]: spacing (type: float) -Function 459: LoadModel() (1 input parameters) +Function 460: LoadModel() (1 input parameters) Name: LoadModel Return type: Model Description: Load model from files (meshes and materials) Param[1]: fileName (type: const char *) -Function 460: LoadModelFromMesh() (1 input parameters) +Function 461: LoadModelFromMesh() (1 input parameters) Name: LoadModelFromMesh Return type: Model Description: Load model from generated mesh (default material) Param[1]: mesh (type: Mesh) -Function 461: IsModelValid() (1 input parameters) +Function 462: IsModelValid() (1 input parameters) Name: IsModelValid Return type: bool Description: Check if a model is valid (loaded in GPU, VAO/VBOs) Param[1]: model (type: Model) -Function 462: UnloadModel() (1 input parameters) +Function 463: UnloadModel() (1 input parameters) Name: UnloadModel Return type: void Description: Unload model (including meshes) from memory (RAM and/or VRAM) Param[1]: model (type: Model) -Function 463: GetModelBoundingBox() (1 input parameters) +Function 464: GetModelBoundingBox() (1 input parameters) Name: GetModelBoundingBox Return type: BoundingBox Description: Compute model bounding box limits (considers all meshes) Param[1]: model (type: Model) -Function 464: DrawModel() (4 input parameters) +Function 465: DrawModel() (4 input parameters) Name: DrawModel Return type: void Description: Draw a model (with texture if set) @@ -3949,7 +3955,7 @@ Function 464: DrawModel() (4 input parameters) Param[2]: position (type: Vector3) Param[3]: scale (type: float) Param[4]: tint (type: Color) -Function 465: DrawModelEx() (6 input parameters) +Function 466: DrawModelEx() (6 input parameters) Name: DrawModelEx Return type: void Description: Draw a model with extended parameters @@ -3959,7 +3965,7 @@ Function 465: DrawModelEx() (6 input parameters) Param[4]: rotationAngle (type: float) Param[5]: scale (type: Vector3) Param[6]: tint (type: Color) -Function 466: DrawModelWires() (4 input parameters) +Function 467: DrawModelWires() (4 input parameters) Name: DrawModelWires Return type: void Description: Draw a model wires (with texture if set) @@ -3967,7 +3973,7 @@ Function 466: DrawModelWires() (4 input parameters) Param[2]: position (type: Vector3) Param[3]: scale (type: float) Param[4]: tint (type: Color) -Function 467: DrawModelWiresEx() (6 input parameters) +Function 468: DrawModelWiresEx() (6 input parameters) Name: DrawModelWiresEx Return type: void Description: Draw a model wires (with texture if set) with extended parameters @@ -3977,7 +3983,7 @@ Function 467: DrawModelWiresEx() (6 input parameters) Param[4]: rotationAngle (type: float) Param[5]: scale (type: Vector3) Param[6]: tint (type: Color) -Function 468: DrawModelPoints() (4 input parameters) +Function 469: DrawModelPoints() (4 input parameters) Name: DrawModelPoints Return type: void Description: Draw a model as points @@ -3985,7 +3991,7 @@ Function 468: DrawModelPoints() (4 input parameters) Param[2]: position (type: Vector3) Param[3]: scale (type: float) Param[4]: tint (type: Color) -Function 469: DrawModelPointsEx() (6 input parameters) +Function 470: DrawModelPointsEx() (6 input parameters) Name: DrawModelPointsEx Return type: void Description: Draw a model as points with extended parameters @@ -3995,13 +4001,13 @@ Function 469: DrawModelPointsEx() (6 input parameters) Param[4]: rotationAngle (type: float) Param[5]: scale (type: Vector3) Param[6]: tint (type: Color) -Function 470: DrawBoundingBox() (2 input parameters) +Function 471: DrawBoundingBox() (2 input parameters) Name: DrawBoundingBox Return type: void Description: Draw bounding box (wires) Param[1]: box (type: BoundingBox) Param[2]: color (type: Color) -Function 471: DrawBillboard() (5 input parameters) +Function 472: DrawBillboard() (5 input parameters) Name: DrawBillboard Return type: void Description: Draw a billboard texture @@ -4010,7 +4016,7 @@ Function 471: DrawBillboard() (5 input parameters) Param[3]: position (type: Vector3) Param[4]: scale (type: float) Param[5]: tint (type: Color) -Function 472: DrawBillboardRec() (6 input parameters) +Function 473: DrawBillboardRec() (6 input parameters) Name: DrawBillboardRec Return type: void Description: Draw a billboard texture defined by source @@ -4020,7 +4026,7 @@ Function 472: DrawBillboardRec() (6 input parameters) Param[4]: position (type: Vector3) Param[5]: size (type: Vector2) Param[6]: tint (type: Color) -Function 473: DrawBillboardPro() (9 input parameters) +Function 474: DrawBillboardPro() (9 input parameters) Name: DrawBillboardPro Return type: void Description: Draw a billboard texture defined by source and rotation @@ -4033,13 +4039,13 @@ Function 473: DrawBillboardPro() (9 input parameters) Param[7]: origin (type: Vector2) Param[8]: rotation (type: float) Param[9]: tint (type: Color) -Function 474: UploadMesh() (2 input parameters) +Function 475: UploadMesh() (2 input parameters) Name: UploadMesh Return type: void Description: Upload mesh vertex data in GPU and provide VAO/VBO ids Param[1]: mesh (type: Mesh *) Param[2]: dynamic (type: bool) -Function 475: UpdateMeshBuffer() (5 input parameters) +Function 476: UpdateMeshBuffer() (5 input parameters) Name: UpdateMeshBuffer Return type: void Description: Update mesh vertex data in GPU for a specific buffer index @@ -4048,19 +4054,19 @@ Function 475: UpdateMeshBuffer() (5 input parameters) Param[3]: data (type: const void *) Param[4]: dataSize (type: int) Param[5]: offset (type: int) -Function 476: UnloadMesh() (1 input parameters) +Function 477: UnloadMesh() (1 input parameters) Name: UnloadMesh Return type: void Description: Unload mesh data from CPU and GPU Param[1]: mesh (type: Mesh) -Function 477: DrawMesh() (3 input parameters) +Function 478: DrawMesh() (3 input parameters) Name: DrawMesh Return type: void Description: Draw a 3d mesh with material and transform Param[1]: mesh (type: Mesh) Param[2]: material (type: Material) Param[3]: transform (type: Matrix) -Function 478: DrawMeshInstanced() (4 input parameters) +Function 479: DrawMeshInstanced() (4 input parameters) Name: DrawMeshInstanced Return type: void Description: Draw multiple mesh instances with material and different transforms @@ -4068,35 +4074,35 @@ Function 478: DrawMeshInstanced() (4 input parameters) Param[2]: material (type: Material) Param[3]: transforms (type: const Matrix *) Param[4]: instances (type: int) -Function 479: GetMeshBoundingBox() (1 input parameters) +Function 480: GetMeshBoundingBox() (1 input parameters) Name: GetMeshBoundingBox Return type: BoundingBox Description: Compute mesh bounding box limits Param[1]: mesh (type: Mesh) -Function 480: GenMeshTangents() (1 input parameters) +Function 481: GenMeshTangents() (1 input parameters) Name: GenMeshTangents Return type: void Description: Compute mesh tangents Param[1]: mesh (type: Mesh *) -Function 481: ExportMesh() (2 input parameters) +Function 482: ExportMesh() (2 input parameters) Name: ExportMesh Return type: bool Description: Export mesh data to file, returns true on success Param[1]: mesh (type: Mesh) Param[2]: fileName (type: const char *) -Function 482: ExportMeshAsCode() (2 input parameters) +Function 483: ExportMeshAsCode() (2 input parameters) Name: ExportMeshAsCode Return type: bool Description: Export mesh as code file (.h) defining multiple arrays of vertex attributes Param[1]: mesh (type: Mesh) Param[2]: fileName (type: const char *) -Function 483: GenMeshPoly() (2 input parameters) +Function 484: GenMeshPoly() (2 input parameters) Name: GenMeshPoly Return type: Mesh Description: Generate polygonal mesh Param[1]: sides (type: int) Param[2]: radius (type: float) -Function 484: GenMeshPlane() (4 input parameters) +Function 485: GenMeshPlane() (4 input parameters) Name: GenMeshPlane Return type: Mesh Description: Generate plane mesh (with subdivisions) @@ -4104,42 +4110,42 @@ Function 484: GenMeshPlane() (4 input parameters) Param[2]: length (type: float) Param[3]: resX (type: int) Param[4]: resZ (type: int) -Function 485: GenMeshCube() (3 input parameters) +Function 486: GenMeshCube() (3 input parameters) Name: GenMeshCube Return type: Mesh Description: Generate cuboid mesh Param[1]: width (type: float) Param[2]: height (type: float) Param[3]: length (type: float) -Function 486: GenMeshSphere() (3 input parameters) +Function 487: GenMeshSphere() (3 input parameters) Name: GenMeshSphere Return type: Mesh Description: Generate sphere mesh (standard sphere) Param[1]: radius (type: float) Param[2]: rings (type: int) Param[3]: slices (type: int) -Function 487: GenMeshHemiSphere() (3 input parameters) +Function 488: GenMeshHemiSphere() (3 input parameters) Name: GenMeshHemiSphere Return type: Mesh Description: Generate half-sphere mesh (no bottom cap) Param[1]: radius (type: float) Param[2]: rings (type: int) Param[3]: slices (type: int) -Function 488: GenMeshCylinder() (3 input parameters) +Function 489: GenMeshCylinder() (3 input parameters) Name: GenMeshCylinder Return type: Mesh Description: Generate cylinder mesh Param[1]: radius (type: float) Param[2]: height (type: float) Param[3]: slices (type: int) -Function 489: GenMeshCone() (3 input parameters) +Function 490: GenMeshCone() (3 input parameters) Name: GenMeshCone Return type: Mesh Description: Generate cone/pyramid mesh Param[1]: radius (type: float) Param[2]: height (type: float) Param[3]: slices (type: int) -Function 490: GenMeshTorus() (4 input parameters) +Function 491: GenMeshTorus() (4 input parameters) Name: GenMeshTorus Return type: Mesh Description: Generate torus mesh @@ -4147,7 +4153,7 @@ Function 490: GenMeshTorus() (4 input parameters) Param[2]: size (type: float) Param[3]: radSeg (type: int) Param[4]: sides (type: int) -Function 491: GenMeshKnot() (4 input parameters) +Function 492: GenMeshKnot() (4 input parameters) Name: GenMeshKnot Return type: Mesh Description: Generate trefoil knot mesh @@ -4155,91 +4161,91 @@ Function 491: GenMeshKnot() (4 input parameters) Param[2]: size (type: float) Param[3]: radSeg (type: int) Param[4]: sides (type: int) -Function 492: GenMeshHeightmap() (2 input parameters) +Function 493: GenMeshHeightmap() (2 input parameters) Name: GenMeshHeightmap Return type: Mesh Description: Generate heightmap mesh from image data Param[1]: heightmap (type: Image) Param[2]: size (type: Vector3) -Function 493: GenMeshCubicmap() (2 input parameters) +Function 494: GenMeshCubicmap() (2 input parameters) Name: GenMeshCubicmap Return type: Mesh Description: Generate cubes-based map mesh from image data Param[1]: cubicmap (type: Image) Param[2]: cubeSize (type: Vector3) -Function 494: LoadMaterials() (2 input parameters) +Function 495: LoadMaterials() (2 input parameters) Name: LoadMaterials Return type: Material * Description: Load materials from model file Param[1]: fileName (type: const char *) Param[2]: materialCount (type: int *) -Function 495: LoadMaterialDefault() (0 input parameters) +Function 496: LoadMaterialDefault() (0 input parameters) Name: LoadMaterialDefault Return type: Material Description: Load default material (Supports: DIFFUSE, SPECULAR, NORMAL maps) No input parameters -Function 496: IsMaterialValid() (1 input parameters) +Function 497: IsMaterialValid() (1 input parameters) Name: IsMaterialValid Return type: bool Description: Check if a material is valid (shader assigned, map textures loaded in GPU) Param[1]: material (type: Material) -Function 497: UnloadMaterial() (1 input parameters) +Function 498: UnloadMaterial() (1 input parameters) Name: UnloadMaterial Return type: void Description: Unload material from GPU memory (VRAM) Param[1]: material (type: Material) -Function 498: SetMaterialTexture() (3 input parameters) +Function 499: SetMaterialTexture() (3 input parameters) Name: SetMaterialTexture Return type: void Description: Set texture for a material map type (MATERIAL_MAP_DIFFUSE, MATERIAL_MAP_SPECULAR...) Param[1]: material (type: Material *) Param[2]: mapType (type: int) Param[3]: texture (type: Texture2D) -Function 499: SetModelMeshMaterial() (3 input parameters) +Function 500: SetModelMeshMaterial() (3 input parameters) Name: SetModelMeshMaterial Return type: void Description: Set material for a mesh Param[1]: model (type: Model *) Param[2]: meshId (type: int) Param[3]: materialId (type: int) -Function 500: LoadModelAnimations() (2 input parameters) +Function 501: LoadModelAnimations() (2 input parameters) Name: LoadModelAnimations Return type: ModelAnimation * Description: Load model animations from file Param[1]: fileName (type: const char *) Param[2]: animCount (type: int *) -Function 501: UpdateModelAnimation() (3 input parameters) +Function 502: UpdateModelAnimation() (3 input parameters) Name: UpdateModelAnimation Return type: void Description: Update model animation pose Param[1]: model (type: Model) Param[2]: anim (type: ModelAnimation) Param[3]: frame (type: int) -Function 502: UnloadModelAnimation() (1 input parameters) +Function 503: UnloadModelAnimation() (1 input parameters) Name: UnloadModelAnimation Return type: void Description: Unload animation data Param[1]: anim (type: ModelAnimation) -Function 503: UnloadModelAnimations() (2 input parameters) +Function 504: UnloadModelAnimations() (2 input parameters) Name: UnloadModelAnimations Return type: void Description: Unload animation array data Param[1]: animations (type: ModelAnimation *) Param[2]: animCount (type: int) -Function 504: IsModelAnimationValid() (2 input parameters) +Function 505: IsModelAnimationValid() (2 input parameters) Name: IsModelAnimationValid Return type: bool Description: Check model animation skeleton match Param[1]: model (type: Model) Param[2]: anim (type: ModelAnimation) -Function 505: UpdateModelAnimationBoneMatrices() (3 input parameters) +Function 506: UpdateModelAnimationBoneMatrices() (3 input parameters) Name: UpdateModelAnimationBoneMatrices Return type: void Description: Update model animation mesh bone matrices (Note GPU skinning does not work on Mac) Param[1]: model (type: Model) Param[2]: anim (type: ModelAnimation) Param[3]: frame (type: int) -Function 506: CheckCollisionSpheres() (4 input parameters) +Function 507: CheckCollisionSpheres() (4 input parameters) Name: CheckCollisionSpheres Return type: bool Description: Check collision between two spheres @@ -4247,40 +4253,40 @@ Function 506: CheckCollisionSpheres() (4 input parameters) Param[2]: radius1 (type: float) Param[3]: center2 (type: Vector3) Param[4]: radius2 (type: float) -Function 507: CheckCollisionBoxes() (2 input parameters) +Function 508: CheckCollisionBoxes() (2 input parameters) Name: CheckCollisionBoxes Return type: bool Description: Check collision between two bounding boxes Param[1]: box1 (type: BoundingBox) Param[2]: box2 (type: BoundingBox) -Function 508: CheckCollisionBoxSphere() (3 input parameters) +Function 509: CheckCollisionBoxSphere() (3 input parameters) Name: CheckCollisionBoxSphere Return type: bool Description: Check collision between box and sphere Param[1]: box (type: BoundingBox) Param[2]: center (type: Vector3) Param[3]: radius (type: float) -Function 509: GetRayCollisionSphere() (3 input parameters) +Function 510: GetRayCollisionSphere() (3 input parameters) Name: GetRayCollisionSphere Return type: RayCollision Description: Get collision info between ray and sphere Param[1]: ray (type: Ray) Param[2]: center (type: Vector3) Param[3]: radius (type: float) -Function 510: GetRayCollisionBox() (2 input parameters) +Function 511: GetRayCollisionBox() (2 input parameters) Name: GetRayCollisionBox Return type: RayCollision Description: Get collision info between ray and box Param[1]: ray (type: Ray) Param[2]: box (type: BoundingBox) -Function 511: GetRayCollisionMesh() (3 input parameters) +Function 512: GetRayCollisionMesh() (3 input parameters) Name: GetRayCollisionMesh Return type: RayCollision Description: Get collision info between ray and mesh Param[1]: ray (type: Ray) Param[2]: mesh (type: Mesh) Param[3]: transform (type: Matrix) -Function 512: GetRayCollisionTriangle() (4 input parameters) +Function 513: GetRayCollisionTriangle() (4 input parameters) Name: GetRayCollisionTriangle Return type: RayCollision Description: Get collision info between ray and triangle @@ -4288,7 +4294,7 @@ Function 512: GetRayCollisionTriangle() (4 input parameters) Param[2]: p1 (type: Vector3) Param[3]: p2 (type: Vector3) Param[4]: p3 (type: Vector3) -Function 513: GetRayCollisionQuad() (5 input parameters) +Function 514: GetRayCollisionQuad() (5 input parameters) Name: GetRayCollisionQuad Return type: RayCollision Description: Get collision info between ray and quad @@ -4297,158 +4303,158 @@ Function 513: GetRayCollisionQuad() (5 input parameters) Param[3]: p2 (type: Vector3) Param[4]: p3 (type: Vector3) Param[5]: p4 (type: Vector3) -Function 514: InitAudioDevice() (0 input parameters) +Function 515: InitAudioDevice() (0 input parameters) Name: InitAudioDevice Return type: void Description: Initialize audio device and context No input parameters -Function 515: CloseAudioDevice() (0 input parameters) +Function 516: CloseAudioDevice() (0 input parameters) Name: CloseAudioDevice Return type: void Description: Close the audio device and context No input parameters -Function 516: IsAudioDeviceReady() (0 input parameters) +Function 517: IsAudioDeviceReady() (0 input parameters) Name: IsAudioDeviceReady Return type: bool Description: Check if audio device has been initialized successfully No input parameters -Function 517: SetMasterVolume() (1 input parameters) +Function 518: SetMasterVolume() (1 input parameters) Name: SetMasterVolume Return type: void Description: Set master volume (listener) Param[1]: volume (type: float) -Function 518: GetMasterVolume() (0 input parameters) +Function 519: GetMasterVolume() (0 input parameters) Name: GetMasterVolume Return type: float Description: Get master volume (listener) No input parameters -Function 519: LoadWave() (1 input parameters) +Function 520: LoadWave() (1 input parameters) Name: LoadWave Return type: Wave Description: Load wave data from file Param[1]: fileName (type: const char *) -Function 520: LoadWaveFromMemory() (3 input parameters) +Function 521: LoadWaveFromMemory() (3 input parameters) Name: LoadWaveFromMemory Return type: Wave Description: Load wave from memory buffer, fileType refers to extension: i.e. '.wav' Param[1]: fileType (type: const char *) Param[2]: fileData (type: const unsigned char *) Param[3]: dataSize (type: int) -Function 521: IsWaveValid() (1 input parameters) +Function 522: IsWaveValid() (1 input parameters) Name: IsWaveValid Return type: bool Description: Checks if wave data is valid (data loaded and parameters) Param[1]: wave (type: Wave) -Function 522: LoadSound() (1 input parameters) +Function 523: LoadSound() (1 input parameters) Name: LoadSound Return type: Sound Description: Load sound from file Param[1]: fileName (type: const char *) -Function 523: LoadSoundFromWave() (1 input parameters) +Function 524: LoadSoundFromWave() (1 input parameters) Name: LoadSoundFromWave Return type: Sound Description: Load sound from wave data Param[1]: wave (type: Wave) -Function 524: LoadSoundAlias() (1 input parameters) +Function 525: LoadSoundAlias() (1 input parameters) Name: LoadSoundAlias Return type: Sound Description: Create a new sound that shares the same sample data as the source sound, does not own the sound data Param[1]: source (type: Sound) -Function 525: IsSoundValid() (1 input parameters) +Function 526: IsSoundValid() (1 input parameters) Name: IsSoundValid Return type: bool Description: Checks if a sound is valid (data loaded and buffers initialized) Param[1]: sound (type: Sound) -Function 526: UpdateSound() (3 input parameters) +Function 527: UpdateSound() (3 input parameters) Name: UpdateSound Return type: void Description: Update sound buffer with new data Param[1]: sound (type: Sound) Param[2]: data (type: const void *) Param[3]: sampleCount (type: int) -Function 527: UnloadWave() (1 input parameters) +Function 528: UnloadWave() (1 input parameters) Name: UnloadWave Return type: void Description: Unload wave data Param[1]: wave (type: Wave) -Function 528: UnloadSound() (1 input parameters) +Function 529: UnloadSound() (1 input parameters) Name: UnloadSound Return type: void Description: Unload sound Param[1]: sound (type: Sound) -Function 529: UnloadSoundAlias() (1 input parameters) +Function 530: UnloadSoundAlias() (1 input parameters) Name: UnloadSoundAlias Return type: void Description: Unload a sound alias (does not deallocate sample data) Param[1]: alias (type: Sound) -Function 530: ExportWave() (2 input parameters) +Function 531: ExportWave() (2 input parameters) Name: ExportWave Return type: bool Description: Export wave data to file, returns true on success Param[1]: wave (type: Wave) Param[2]: fileName (type: const char *) -Function 531: ExportWaveAsCode() (2 input parameters) +Function 532: ExportWaveAsCode() (2 input parameters) Name: ExportWaveAsCode Return type: bool Description: Export wave sample data to code (.h), returns true on success Param[1]: wave (type: Wave) Param[2]: fileName (type: const char *) -Function 532: PlaySound() (1 input parameters) +Function 533: PlaySound() (1 input parameters) Name: PlaySound Return type: void Description: Play a sound Param[1]: sound (type: Sound) -Function 533: StopSound() (1 input parameters) +Function 534: StopSound() (1 input parameters) Name: StopSound Return type: void Description: Stop playing a sound Param[1]: sound (type: Sound) -Function 534: PauseSound() (1 input parameters) +Function 535: PauseSound() (1 input parameters) Name: PauseSound Return type: void Description: Pause a sound Param[1]: sound (type: Sound) -Function 535: ResumeSound() (1 input parameters) +Function 536: ResumeSound() (1 input parameters) Name: ResumeSound Return type: void Description: Resume a paused sound Param[1]: sound (type: Sound) -Function 536: IsSoundPlaying() (1 input parameters) +Function 537: IsSoundPlaying() (1 input parameters) Name: IsSoundPlaying Return type: bool Description: Check if a sound is currently playing Param[1]: sound (type: Sound) -Function 537: SetSoundVolume() (2 input parameters) +Function 538: SetSoundVolume() (2 input parameters) Name: SetSoundVolume Return type: void Description: Set volume for a sound (1.0 is max level) Param[1]: sound (type: Sound) Param[2]: volume (type: float) -Function 538: SetSoundPitch() (2 input parameters) +Function 539: SetSoundPitch() (2 input parameters) Name: SetSoundPitch Return type: void Description: Set pitch for a sound (1.0 is base level) Param[1]: sound (type: Sound) Param[2]: pitch (type: float) -Function 539: SetSoundPan() (2 input parameters) +Function 540: SetSoundPan() (2 input parameters) Name: SetSoundPan Return type: void Description: Set pan for a sound (0.5 is center) Param[1]: sound (type: Sound) Param[2]: pan (type: float) -Function 540: WaveCopy() (1 input parameters) +Function 541: WaveCopy() (1 input parameters) Name: WaveCopy Return type: Wave Description: Copy a wave to a new wave Param[1]: wave (type: Wave) -Function 541: WaveCrop() (3 input parameters) +Function 542: WaveCrop() (3 input parameters) Name: WaveCrop Return type: void Description: Crop a wave to defined frames range Param[1]: wave (type: Wave *) Param[2]: initFrame (type: int) Param[3]: finalFrame (type: int) -Function 542: WaveFormat() (4 input parameters) +Function 543: WaveFormat() (4 input parameters) Name: WaveFormat Return type: void Description: Convert wave data to desired format @@ -4456,203 +4462,203 @@ Function 542: WaveFormat() (4 input parameters) Param[2]: sampleRate (type: int) Param[3]: sampleSize (type: int) Param[4]: channels (type: int) -Function 543: LoadWaveSamples() (1 input parameters) +Function 544: LoadWaveSamples() (1 input parameters) Name: LoadWaveSamples Return type: float * Description: Load samples data from wave as a 32bit float data array Param[1]: wave (type: Wave) -Function 544: UnloadWaveSamples() (1 input parameters) +Function 545: UnloadWaveSamples() (1 input parameters) Name: UnloadWaveSamples Return type: void Description: Unload samples data loaded with LoadWaveSamples() Param[1]: samples (type: float *) -Function 545: LoadMusicStream() (1 input parameters) +Function 546: LoadMusicStream() (1 input parameters) Name: LoadMusicStream Return type: Music Description: Load music stream from file Param[1]: fileName (type: const char *) -Function 546: LoadMusicStreamFromMemory() (3 input parameters) +Function 547: LoadMusicStreamFromMemory() (3 input parameters) Name: LoadMusicStreamFromMemory Return type: Music Description: Load music stream from data Param[1]: fileType (type: const char *) Param[2]: data (type: const unsigned char *) Param[3]: dataSize (type: int) -Function 547: IsMusicValid() (1 input parameters) +Function 548: IsMusicValid() (1 input parameters) Name: IsMusicValid Return type: bool Description: Checks if a music stream is valid (context and buffers initialized) Param[1]: music (type: Music) -Function 548: UnloadMusicStream() (1 input parameters) +Function 549: UnloadMusicStream() (1 input parameters) Name: UnloadMusicStream Return type: void Description: Unload music stream Param[1]: music (type: Music) -Function 549: PlayMusicStream() (1 input parameters) +Function 550: PlayMusicStream() (1 input parameters) Name: PlayMusicStream Return type: void Description: Start music playing Param[1]: music (type: Music) -Function 550: IsMusicStreamPlaying() (1 input parameters) +Function 551: IsMusicStreamPlaying() (1 input parameters) Name: IsMusicStreamPlaying Return type: bool Description: Check if music is playing Param[1]: music (type: Music) -Function 551: UpdateMusicStream() (1 input parameters) +Function 552: UpdateMusicStream() (1 input parameters) Name: UpdateMusicStream Return type: void Description: Updates buffers for music streaming Param[1]: music (type: Music) -Function 552: StopMusicStream() (1 input parameters) +Function 553: StopMusicStream() (1 input parameters) Name: StopMusicStream Return type: void Description: Stop music playing Param[1]: music (type: Music) -Function 553: PauseMusicStream() (1 input parameters) +Function 554: PauseMusicStream() (1 input parameters) Name: PauseMusicStream Return type: void Description: Pause music playing Param[1]: music (type: Music) -Function 554: ResumeMusicStream() (1 input parameters) +Function 555: ResumeMusicStream() (1 input parameters) Name: ResumeMusicStream Return type: void Description: Resume playing paused music Param[1]: music (type: Music) -Function 555: SeekMusicStream() (2 input parameters) +Function 556: SeekMusicStream() (2 input parameters) Name: SeekMusicStream Return type: void Description: Seek music to a position (in seconds) Param[1]: music (type: Music) Param[2]: position (type: float) -Function 556: SetMusicVolume() (2 input parameters) +Function 557: SetMusicVolume() (2 input parameters) Name: SetMusicVolume Return type: void Description: Set volume for music (1.0 is max level) Param[1]: music (type: Music) Param[2]: volume (type: float) -Function 557: SetMusicPitch() (2 input parameters) +Function 558: SetMusicPitch() (2 input parameters) Name: SetMusicPitch Return type: void Description: Set pitch for a music (1.0 is base level) Param[1]: music (type: Music) Param[2]: pitch (type: float) -Function 558: SetMusicPan() (2 input parameters) +Function 559: SetMusicPan() (2 input parameters) Name: SetMusicPan Return type: void Description: Set pan for a music (0.5 is center) Param[1]: music (type: Music) Param[2]: pan (type: float) -Function 559: GetMusicTimeLength() (1 input parameters) +Function 560: GetMusicTimeLength() (1 input parameters) Name: GetMusicTimeLength Return type: float Description: Get music time length (in seconds) Param[1]: music (type: Music) -Function 560: GetMusicTimePlayed() (1 input parameters) +Function 561: GetMusicTimePlayed() (1 input parameters) Name: GetMusicTimePlayed Return type: float Description: Get current music time played (in seconds) Param[1]: music (type: Music) -Function 561: LoadAudioStream() (3 input parameters) +Function 562: LoadAudioStream() (3 input parameters) Name: LoadAudioStream Return type: AudioStream Description: Load audio stream (to stream raw audio pcm data) Param[1]: sampleRate (type: unsigned int) Param[2]: sampleSize (type: unsigned int) Param[3]: channels (type: unsigned int) -Function 562: IsAudioStreamValid() (1 input parameters) +Function 563: IsAudioStreamValid() (1 input parameters) Name: IsAudioStreamValid Return type: bool Description: Checks if an audio stream is valid (buffers initialized) Param[1]: stream (type: AudioStream) -Function 563: UnloadAudioStream() (1 input parameters) +Function 564: UnloadAudioStream() (1 input parameters) Name: UnloadAudioStream Return type: void Description: Unload audio stream and free memory Param[1]: stream (type: AudioStream) -Function 564: UpdateAudioStream() (3 input parameters) +Function 565: UpdateAudioStream() (3 input parameters) Name: UpdateAudioStream Return type: void Description: Update audio stream buffers with data Param[1]: stream (type: AudioStream) Param[2]: data (type: const void *) Param[3]: frameCount (type: int) -Function 565: IsAudioStreamProcessed() (1 input parameters) +Function 566: IsAudioStreamProcessed() (1 input parameters) Name: IsAudioStreamProcessed Return type: bool Description: Check if any audio stream buffers requires refill Param[1]: stream (type: AudioStream) -Function 566: PlayAudioStream() (1 input parameters) +Function 567: PlayAudioStream() (1 input parameters) Name: PlayAudioStream Return type: void Description: Play audio stream Param[1]: stream (type: AudioStream) -Function 567: PauseAudioStream() (1 input parameters) +Function 568: PauseAudioStream() (1 input parameters) Name: PauseAudioStream Return type: void Description: Pause audio stream Param[1]: stream (type: AudioStream) -Function 568: ResumeAudioStream() (1 input parameters) +Function 569: ResumeAudioStream() (1 input parameters) Name: ResumeAudioStream Return type: void Description: Resume audio stream Param[1]: stream (type: AudioStream) -Function 569: IsAudioStreamPlaying() (1 input parameters) +Function 570: IsAudioStreamPlaying() (1 input parameters) Name: IsAudioStreamPlaying Return type: bool Description: Check if audio stream is playing Param[1]: stream (type: AudioStream) -Function 570: StopAudioStream() (1 input parameters) +Function 571: StopAudioStream() (1 input parameters) Name: StopAudioStream Return type: void Description: Stop audio stream Param[1]: stream (type: AudioStream) -Function 571: SetAudioStreamVolume() (2 input parameters) +Function 572: SetAudioStreamVolume() (2 input parameters) Name: SetAudioStreamVolume Return type: void Description: Set volume for audio stream (1.0 is max level) Param[1]: stream (type: AudioStream) Param[2]: volume (type: float) -Function 572: SetAudioStreamPitch() (2 input parameters) +Function 573: SetAudioStreamPitch() (2 input parameters) Name: SetAudioStreamPitch Return type: void Description: Set pitch for audio stream (1.0 is base level) Param[1]: stream (type: AudioStream) Param[2]: pitch (type: float) -Function 573: SetAudioStreamPan() (2 input parameters) +Function 574: SetAudioStreamPan() (2 input parameters) Name: SetAudioStreamPan Return type: void Description: Set pan for audio stream (0.5 is centered) Param[1]: stream (type: AudioStream) Param[2]: pan (type: float) -Function 574: SetAudioStreamBufferSizeDefault() (1 input parameters) +Function 575: SetAudioStreamBufferSizeDefault() (1 input parameters) Name: SetAudioStreamBufferSizeDefault Return type: void Description: Default size for new audio streams Param[1]: size (type: int) -Function 575: SetAudioStreamCallback() (2 input parameters) +Function 576: SetAudioStreamCallback() (2 input parameters) Name: SetAudioStreamCallback Return type: void Description: Audio thread callback to request new data Param[1]: stream (type: AudioStream) Param[2]: callback (type: AudioCallback) -Function 576: AttachAudioStreamProcessor() (2 input parameters) +Function 577: AttachAudioStreamProcessor() (2 input parameters) Name: AttachAudioStreamProcessor Return type: void Description: Attach audio stream processor to stream, receives the samples as 'float' Param[1]: stream (type: AudioStream) Param[2]: processor (type: AudioCallback) -Function 577: DetachAudioStreamProcessor() (2 input parameters) +Function 578: DetachAudioStreamProcessor() (2 input parameters) Name: DetachAudioStreamProcessor Return type: void Description: Detach audio stream processor from stream Param[1]: stream (type: AudioStream) Param[2]: processor (type: AudioCallback) -Function 578: AttachAudioMixedProcessor() (1 input parameters) +Function 579: AttachAudioMixedProcessor() (1 input parameters) Name: AttachAudioMixedProcessor Return type: void Description: Attach audio stream processor to the entire audio pipeline, receives the samples as 'float' Param[1]: processor (type: AudioCallback) -Function 579: DetachAudioMixedProcessor() (1 input parameters) +Function 580: DetachAudioMixedProcessor() (1 input parameters) Name: DetachAudioMixedProcessor Return type: void Description: Detach audio stream processor from the entire audio pipeline diff --git a/parser/output/raylib_api.xml b/parser/output/raylib_api.xml index eb53437eb..17d5a81e3 100644 --- a/parser/output/raylib_api.xml +++ b/parser/output/raylib_api.xml @@ -675,7 +675,7 @@ - + @@ -1134,6 +1134,10 @@ + + + + From dc5e6e0ad089f8eda932efb4646d6bbafe0713cc Mon Sep 17 00:00:00 2001 From: Sage Hane Date: Sat, 19 Oct 2024 04:03:27 +0900 Subject: [PATCH 134/208] build.zig: Clean up my mess (#4387) --- src/build.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/build.zig b/src/build.zig index 2a8b88262..3ca1e4c6a 100644 --- a/src/build.zig +++ b/src/build.zig @@ -68,7 +68,7 @@ fn srcDir(b: *std.Build) []const u8 { @compileError("Please take a look at this function again"); } - const src_file = std.fs.path.relative(b.allocator, @src().file, ".") catch @panic("OOM"); + const src_file = std.fs.path.relative(b.allocator, ".", @src().file) catch @panic("OOM"); return std.fs.path.dirname(src_file) orelse "."; } From 902d3c92e369bb66613c363833287e9220579ee4 Mon Sep 17 00:00:00 2001 From: Nikolas Date: Mon, 21 Oct 2024 01:25:33 +0300 Subject: [PATCH 135/208] [rl_gputex] Correctly load mipmaps from DDS files (#4399) --- src/external/rl_gputex.h | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/external/rl_gputex.h b/src/external/rl_gputex.h index 6b26d1c8d..4043a9239 100644 --- a/src/external/rl_gputex.h +++ b/src/external/rl_gputex.h @@ -185,6 +185,7 @@ void *rl_load_dds_from_memory(const unsigned char *file_data, unsigned int file_ if (header->ddspf.flags == 0x40) // No alpha channel { int data_size = image_pixel_size*sizeof(unsigned short); + if (header->mipmap_count > 1) data_size = data_size + data_size / 3; image_data = RL_MALLOC(data_size); memcpy(image_data, file_data_ptr, data_size); @@ -196,6 +197,7 @@ void *rl_load_dds_from_memory(const unsigned char *file_data, unsigned int file_ if (header->ddspf.a_bit_mask == 0x8000) // 1bit alpha { int data_size = image_pixel_size*sizeof(unsigned short); + if (header->mipmap_count > 1) data_size = data_size + data_size / 3; image_data = RL_MALLOC(data_size); memcpy(image_data, file_data_ptr, data_size); @@ -215,6 +217,7 @@ void *rl_load_dds_from_memory(const unsigned char *file_data, unsigned int file_ else if (header->ddspf.a_bit_mask == 0xf000) // 4bit alpha { int data_size = image_pixel_size*sizeof(unsigned short); + if (header->mipmap_count > 1) data_size = data_size + data_size / 3; image_data = RL_MALLOC(data_size); memcpy(image_data, file_data_ptr, data_size); @@ -236,6 +239,7 @@ void *rl_load_dds_from_memory(const unsigned char *file_data, unsigned int file_ else if ((header->ddspf.flags == 0x40) && (header->ddspf.rgb_bit_count == 24)) // DDS_RGB, no compressed { int data_size = image_pixel_size*3*sizeof(unsigned char); + if (header->mipmap_count > 1) data_size = data_size + data_size / 3; image_data = RL_MALLOC(data_size); memcpy(image_data, file_data_ptr, data_size); @@ -245,6 +249,7 @@ void *rl_load_dds_from_memory(const unsigned char *file_data, unsigned int file_ else if ((header->ddspf.flags == 0x41) && (header->ddspf.rgb_bit_count == 32)) // DDS_RGBA, no compressed { int data_size = image_pixel_size*4*sizeof(unsigned char); + if (header->mipmap_count > 1) data_size = data_size + data_size / 3; image_data = RL_MALLOC(data_size); memcpy(image_data, file_data_ptr, data_size); @@ -265,9 +270,11 @@ void *rl_load_dds_from_memory(const unsigned char *file_data, unsigned int file_ } else if (((header->ddspf.flags == 0x04) || (header->ddspf.flags == 0x05)) && (header->ddspf.fourcc > 0)) // Compressed { - // NOTE: This forces only 1 mipmap to be loaded which is not really correct but it works - int data_size = (header->pitch_or_linear_size < file_size - 0x80) ? header->pitch_or_linear_size : file_size - 0x80; - *mips = 1; + int data_size = 0; + + // Calculate data size, including all mipmaps + if (header->mipmap_count > 1) data_size = header->pitch_or_linear_size + header->pitch_or_linear_size / 3; + else data_size = header->pitch_or_linear_size; image_data = RL_MALLOC(data_size*sizeof(unsigned char)); From 23354e1551ebf4987d4bba7bdbf2627b6e09e8ba Mon Sep 17 00:00:00 2001 From: Le Juez Victor <90587919+Bigfoot71@users.noreply.github.com> Date: Mon, 21 Oct 2024 00:26:15 +0200 Subject: [PATCH 136/208] correction of comments (#4400) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The indication of locations for bone ids and bone weights did not correspond to their default values ​​in config.h --- src/rmodels.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rmodels.c b/src/rmodels.c index 9d9c47519..e7208e1aa 100644 --- a/src/rmodels.c +++ b/src/rmodels.c @@ -1362,7 +1362,7 @@ void UploadMesh(Mesh *mesh, bool dynamic) #ifdef RL_SUPPORT_MESH_GPU_SKINNING if (mesh->boneIds != NULL) { - // Enable vertex attribute: boneIds (shader-location = 6) + // Enable vertex attribute: boneIds (shader-location = 7) mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS] = rlLoadVertexBuffer(mesh->boneIds, mesh->vertexCount*4*sizeof(unsigned char), dynamic); rlSetVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS, 4, RL_UNSIGNED_BYTE, 0, 0, 0); rlEnableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS); @@ -1378,7 +1378,7 @@ void UploadMesh(Mesh *mesh, bool dynamic) if (mesh->boneWeights != NULL) { - // Enable vertex attribute: boneWeights (shader-location = 7) + // Enable vertex attribute: boneWeights (shader-location = 8) mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS] = rlLoadVertexBuffer(mesh->boneWeights, mesh->vertexCount*4*sizeof(float), dynamic); rlSetVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS, 4, RL_FLOAT, 0, 0, 0); rlEnableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS); From ce9259cd02e719fcef38e919cf69814d0973136a Mon Sep 17 00:00:00 2001 From: Sage Hane Date: Mon, 21 Oct 2024 07:27:25 +0900 Subject: [PATCH 137/208] build.zig: Fix various issues around `-Dconfig` (#4398) * build.zig: Fix various issues around `-Dconfig` * build.zig: Parse all relevant flags from `src/config.h` at comptime --- src/build.zig | 112 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 74 insertions(+), 38 deletions(-) diff --git a/src/build.zig b/src/build.zig index 3ca1e4c6a..23b4d66b7 100644 --- a/src/build.zig +++ b/src/build.zig @@ -72,6 +72,36 @@ fn srcDir(b: *std.Build) []const u8 { return std.fs.path.dirname(src_file) orelse "."; } +/// A list of all flags from `src/config.h` that one may override +const config_h_flags = outer: { + // Set this value higher if compile errors happen as `src/config.h` gets larger + @setEvalBranchQuota(1 << 20); + + const config_h = @embedFile("config.h"); + var flags: [std.mem.count(u8, config_h, "\n") + 1][]const u8 = undefined; + + var i = 0; + var lines = std.mem.tokenizeScalar(u8, config_h, '\n'); + while (lines.next()) |line| { + if (!std.mem.containsAtLeast(u8, line, 1, "SUPPORT")) continue; + if (std.mem.startsWith(u8, line, "//")) continue; + if (std.mem.startsWith(u8, line, "#if")) continue; + + var flag = std.mem.trimLeft(u8, line, " \t"); // Trim whitespace + flag = flag["#define ".len - 1 ..]; // Remove #define + flag = std.mem.trimLeft(u8, flag, " \t"); // Trim whitespace + flag = flag[0 .. std.mem.indexOf(u8, flag, " ") orelse continue]; // Flag is only one word, so capture till space + flag = "-D" ++ flag; // Prepend with -D + + flags[i] = flag; + i += 1; + } + + // Uncomment this to check what flags normally get passed + //@compileLog(flags[0..i].*); + break :outer flags[0..i].*; +}; + fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, options: Options) !*std.Build.Step.Compile { raylib_flags_arr.clearRetainingCapacity(); @@ -86,33 +116,36 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std. "-fno-sanitize=undefined", // https://github.com/raysan5/raylib/issues/3674 }); if (options.config.len > 0) { - const file = b.pathJoin(&.{ srcDir(b), "config.h" }); - const content = try std.fs.cwd().readFileAlloc(b.allocator, file, std.math.maxInt(usize)); - defer b.allocator.free(content); + // Sets a flag indiciating the use of a custom `config.h` + try raylib_flags_arr.append(b.allocator, "-DEXTERNAL_CONFIG_FLAGS"); - var lines = std.mem.splitScalar(u8, content, '\n'); - while (lines.next()) |line| { - if (!std.mem.containsAtLeast(u8, line, 1, "SUPPORT")) continue; - if (std.mem.startsWith(u8, line, "//")) continue; - if (std.mem.startsWith(u8, line, "#if")) continue; + // Splits a space-separated list of config flags into multiple flags + // + // Note: This means certain flags like `-x c++` won't be processed properly. + // `-xc++` or similar should be used when possible + var config_iter = std.mem.tokenizeScalar(u8, options.config, ' '); - var flag = std.mem.trimLeft(u8, line, " \t"); // Trim whitespace - flag = flag["#define ".len - 1 ..]; // Remove #define - flag = std.mem.trimLeft(u8, flag, " \t"); // Trim whitespace - flag = flag[0 .. std.mem.indexOf(u8, flag, " ") orelse continue]; // Flag is only one word, so capture till space - flag = try std.fmt.allocPrint(b.allocator, "-D{s}", .{flag}); // Prepend with -D + // Apply config flags supplied by the user + while (config_iter.next()) |config_flag| + try raylib_flags_arr.append(b.allocator, config_flag); - // If user specifies the flag skip it - if (std.mem.containsAtLeast(u8, options.config, 1, flag)) continue; + // Apply all relevant configs from `src/config.h` *except* the user-specified ones + // + // Note: Currently using a suboptimal `O(m*n)` time algorithm where: + // `m` corresponds roughly to the number of lines in `src/config.h` + // `n` corresponds to the number of user-specified flags + outer: for (config_h_flags) |flag| { + // If a user already specified the flag, skip it + while (config_iter.next()) |config_flag| { + // For a user-specified flag to match, it must share the same prefix and have the + // same length or be followed by an equals sign + if (!std.mem.startsWith(u8, config_flag, flag)) continue; + if (config_flag.len == flag.len or config_flag[flag.len] == '=') continue :outer; + } - // Append default value from config.h to compile flags + // Otherwise, append default value from config.h to compile flags try raylib_flags_arr.append(b.allocator, flag); } - - // Append config flags supplied by user to compile flags - try raylib_flags_arr.append(b.allocator, options.config); - - try raylib_flags_arr.append(b.allocator, "-DEXTERNAL_CONFIG_FLAGS"); } if (options.shared) { @@ -319,10 +352,28 @@ pub const Options = struct { shared: bool = false, linux_display_backend: LinuxDisplayBackend = .Both, opengl_version: OpenglVersion = .auto, - /// config should be a list of cflags, eg, "-DSUPPORT_CUSTOM_FRAME_CONTROL" + /// config should be a list of space-separated cflags, eg, "-DSUPPORT_CUSTOM_FRAME_CONTROL" config: []const u8 = &.{}, raygui_dependency_name: []const u8 = "raygui", + + const defaults = Options{}; + + fn getOptions(b: *std.Build) Options { + return .{ + .platform = b.option(PlatformBackend, "platform", "Choose the platform backedn for desktop target") orelse defaults.platform, + .raudio = b.option(bool, "raudio", "Compile with audio support") orelse defaults.raudio, + .raygui = b.option(bool, "raygui", "Compile with raygui support") orelse defaults.raygui, + .rmodels = b.option(bool, "rmodels", "Compile with models support") orelse defaults.rmodels, + .rtext = b.option(bool, "rtext", "Compile with text support") orelse defaults.rtext, + .rtextures = b.option(bool, "rtextures", "Compile with textures support") orelse defaults.rtextures, + .rshapes = b.option(bool, "rshapes", "Compile with shapes support") orelse defaults.rshapes, + .shared = b.option(bool, "shared", "Compile as shared library") orelse defaults.shared, + .linux_display_backend = b.option(LinuxDisplayBackend, "linux_display_backend", "Linux display backend to use") orelse defaults.linux_display_backend, + .opengl_version = b.option(OpenglVersion, "opengl_version", "OpenGL version to use") orelse defaults.opengl_version, + .config = b.option([]const u8, "config", "Compile with custom define macros overriding config.h") orelse &.{}, + }; + } }; pub const OpenglVersion = enum { @@ -371,22 +422,7 @@ pub fn build(b: *std.Build) !void { // set a preferred release mode, allowing the user to decide how to optimize. const optimize = b.standardOptimizeOption(.{}); - const defaults = Options{}; - const options = Options{ - .platform = b.option(PlatformBackend, "platform", "Choose the platform backedn for desktop target") orelse defaults.platform, - .raudio = b.option(bool, "raudio", "Compile with audio support") orelse defaults.raudio, - .raygui = b.option(bool, "raygui", "Compile with raygui support") orelse defaults.raygui, - .rmodels = b.option(bool, "rmodels", "Compile with models support") orelse defaults.rmodels, - .rtext = b.option(bool, "rtext", "Compile with text support") orelse defaults.rtext, - .rtextures = b.option(bool, "rtextures", "Compile with textures support") orelse defaults.rtextures, - .rshapes = b.option(bool, "rshapes", "Compile with shapes support") orelse defaults.rshapes, - .shared = b.option(bool, "shared", "Compile as shared library") orelse defaults.shared, - .linux_display_backend = b.option(LinuxDisplayBackend, "linux_display_backend", "Linux display backend to use") orelse defaults.linux_display_backend, - .opengl_version = b.option(OpenglVersion, "opengl_version", "OpenGL version to use") orelse defaults.opengl_version, - .config = b.option([]const u8, "config", "Compile with custom define macros overriding config.h") orelse &.{}, - }; - - const lib = try compileRaylib(b, target, optimize, options); + const lib = try compileRaylib(b, target, optimize, Options.getOptions(b)); lib.installHeader(b.path(b.pathJoin(&.{ srcDir(b), "raylib.h" })), "raylib.h"); lib.installHeader(b.path(b.pathJoin(&.{ srcDir(b), "raymath.h" })), "raymath.h"); From 3dbbe60376e4f6055bfc11e28b069f61ab37525c Mon Sep 17 00:00:00 2001 From: Asdqwe Date: Sun, 20 Oct 2024 19:29:32 -0300 Subject: [PATCH 138/208] Adds MaximizeWindow() and RestoreWindow() implementation for PLATFORM_WEB (#4397) --- src/platforms/rcore_web.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/platforms/rcore_web.c b/src/platforms/rcore_web.c index 35c15a6b6..73513d8e4 100644 --- a/src/platforms/rcore_web.c +++ b/src/platforms/rcore_web.c @@ -74,6 +74,8 @@ typedef struct { GLFWwindow *handle; // GLFW window handle (graphic device) bool ourFullscreen; // Internal var to filter our handling of fullscreen vs the user handling of fullscreen + int unmaximizedWidth; // Internal var to store the unmaximized window (canvas) width + int unmaximizedHeight; // Internal var to store the unmaximized window (canvas) height } PlatformData; //---------------------------------------------------------------------------------- @@ -317,7 +319,16 @@ void ToggleBorderlessWindowed(void) // Set window state: maximized, if resizable void MaximizeWindow(void) { - TRACELOG(LOG_WARNING, "MaximizeWindow() not available on target platform"); + if (glfwGetWindowAttrib(platform.handle, GLFW_RESIZABLE) == GLFW_TRUE) + { + platform.unmaximizedWidth = CORE.Window.screen.width; + platform.unmaximizedHeight = CORE.Window.screen.height; + + const int tabWidth = EM_ASM_INT( { return window.innerWidth; }, 0); + const int tabHeight = EM_ASM_INT( { return window.innerHeight; }, 0); + + if (tabWidth && tabHeight) glfwSetWindowSize(platform.handle, tabWidth, tabHeight); + } } // Set window state: minimized @@ -329,7 +340,10 @@ void MinimizeWindow(void) // Set window state: not minimized/maximized void RestoreWindow(void) { - TRACELOG(LOG_WARNING, "RestoreWindow() not available on target platform"); + if (glfwGetWindowAttrib(platform.handle, GLFW_RESIZABLE) == GLFW_TRUE) + { + if (platform.unmaximizedWidth && platform.unmaximizedHeight) glfwSetWindowSize(platform.handle, platform.unmaximizedWidth, platform.unmaximizedHeight); + } } // Set window configuration state using flags From 51ff6586f441314b49be3bf686bf3880040d0be9 Mon Sep 17 00:00:00 2001 From: Nikolas Date: Mon, 21 Oct 2024 01:31:01 +0300 Subject: [PATCH 139/208] [rtextures] ImageDraw(): Don't try to blend images without alpha (#4395) --- src/rtextures.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/rtextures.c b/src/rtextures.c index 294eeb6ad..9fc633274 100644 --- a/src/rtextures.c +++ b/src/rtextures.c @@ -3969,13 +3969,21 @@ void ImageDraw(Image *dst, Image src, Rectangle srcRec, Rectangle dstRec, Color // [-] GetPixelColor(): Get Vector4 instead of Color, easier for ColorAlphaBlend() // [ ] Support f32bit channels drawing - // TODO: Support PIXELFORMAT_UNCOMPRESSED_R32, PIXELFORMAT_UNCOMPRESSED_R32G32B32, PIXELFORMAT_UNCOMPRESSED_R32G32B32A32 and 16-bit equivalents + // TODO: Support PIXELFORMAT_UNCOMPRESSED_R32G32B32A32 and PIXELFORMAT_UNCOMPRESSED_R1616B16A16 Color colSrc, colDst, blend; bool blendRequired = true; // Fast path: Avoid blend if source has no alpha to blend - if ((tint.a == 255) && ((srcPtr->format == PIXELFORMAT_UNCOMPRESSED_GRAYSCALE) || (srcPtr->format == PIXELFORMAT_UNCOMPRESSED_R8G8B8) || (srcPtr->format == PIXELFORMAT_UNCOMPRESSED_R5G6B5))) blendRequired = false; + if ((tint.a == 255) && + ((srcPtr->format == PIXELFORMAT_UNCOMPRESSED_GRAYSCALE) || + (srcPtr->format == PIXELFORMAT_UNCOMPRESSED_R5G6B5) || + (srcPtr->format == PIXELFORMAT_UNCOMPRESSED_R8G8B8) || + (srcPtr->format == PIXELFORMAT_UNCOMPRESSED_R32) || + (srcPtr->format == PIXELFORMAT_UNCOMPRESSED_R32G32B32) || + (srcPtr->format == PIXELFORMAT_UNCOMPRESSED_R16) || + (srcPtr->format == PIXELFORMAT_UNCOMPRESSED_R16G16B16))) + blendRequired = false; int strideDst = GetPixelDataSize(dst->width, 1, dst->format); int bytesPerPixelDst = strideDst/(dst->width); From 680238689baf4d88153173d18c855337706b2e4e Mon Sep 17 00:00:00 2001 From: Anthony Carbajal <5776225+CrackedPixel@users.noreply.github.com> Date: Sun, 20 Oct 2024 18:03:01 -0500 Subject: [PATCH 140/208] removed extra update command (#4401) --- examples/models/models_gpu_skinning.c | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/models/models_gpu_skinning.c b/examples/models/models_gpu_skinning.c index 846f0a890..b6296c96a 100644 --- a/examples/models/models_gpu_skinning.c +++ b/examples/models/models_gpu_skinning.c @@ -81,7 +81,6 @@ int main(void) // Update model animation ModelAnimation anim = modelAnimations[animIndex]; animCurrentFrame = (animCurrentFrame + 1)%anim.frameCount; - UpdateModelAnimationBoneMatrices(characterModel, anim, animCurrentFrame); //---------------------------------------------------------------------------------- // Draw From 4290a0d9f21bbca118c2bba0c910fbe9a28366bd Mon Sep 17 00:00:00 2001 From: Asdqwe Date: Sun, 20 Oct 2024 20:04:32 -0300 Subject: [PATCH 141/208] [rcore] [web] Updates `SetWindowState()` and `ClearWindowState()` to handle `FLAG_WINDOW_MAXIMIZED` for `PLATFORM_WEB` (#4402) * Updates SetWindowState() and ClearWindowState() to handle FLAG_WINDOW_MAXIMIZED for PLATFORM_WEB * Update MaximizeWindow() and RestoreWindow() to set/unset the FLAG_WINDOW_MAXIMIZED --- src/platforms/rcore_web.c | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/src/platforms/rcore_web.c b/src/platforms/rcore_web.c index 73513d8e4..70623166d 100644 --- a/src/platforms/rcore_web.c +++ b/src/platforms/rcore_web.c @@ -328,6 +328,8 @@ void MaximizeWindow(void) const int tabHeight = EM_ASM_INT( { return window.innerHeight; }, 0); if (tabWidth && tabHeight) glfwSetWindowSize(platform.handle, tabWidth, tabHeight); + + CORE.Window.flags |= FLAG_WINDOW_MAXIMIZED; } } @@ -343,6 +345,8 @@ void RestoreWindow(void) if (glfwGetWindowAttrib(platform.handle, GLFW_RESIZABLE) == GLFW_TRUE) { if (platform.unmaximizedWidth && platform.unmaximizedHeight) glfwSetWindowSize(platform.handle, platform.unmaximizedWidth, platform.unmaximizedHeight); + + CORE.Window.flags &= ~FLAG_WINDOW_MAXIMIZED; } } @@ -412,9 +416,20 @@ void SetWindowState(unsigned int flags) } // State change: FLAG_WINDOW_MAXIMIZED - if ((flags & FLAG_WINDOW_MAXIMIZED) > 0) + if (((CORE.Window.flags & FLAG_WINDOW_MAXIMIZED) != (flags & FLAG_WINDOW_MAXIMIZED)) && ((flags & FLAG_WINDOW_MAXIMIZED) > 0)) { - TRACELOG(LOG_WARNING, "SetWindowState(FLAG_WINDOW_MAXIMIZED) not available on target platform"); + if (glfwGetWindowAttrib(platform.handle, GLFW_RESIZABLE) == GLFW_TRUE) + { + platform.unmaximizedWidth = CORE.Window.screen.width; + platform.unmaximizedHeight = CORE.Window.screen.height; + + const int tabWidth = EM_ASM_INT( { return window.innerWidth; }, 0); + const int tabHeight = EM_ASM_INT( { return window.innerHeight; }, 0); + + if (tabWidth && tabHeight) glfwSetWindowSize(platform.handle, tabWidth, tabHeight); + + CORE.Window.flags |= FLAG_WINDOW_MAXIMIZED; + } } // State change: FLAG_WINDOW_UNFOCUSED @@ -530,9 +545,14 @@ void ClearWindowState(unsigned int flags) } // State change: FLAG_WINDOW_MAXIMIZED - if ((flags & FLAG_WINDOW_MAXIMIZED) > 0) + if (((CORE.Window.flags & FLAG_WINDOW_MAXIMIZED) > 0) && ((flags & FLAG_WINDOW_MAXIMIZED) > 0)) { - TRACELOG(LOG_WARNING, "ClearWindowState(FLAG_WINDOW_MAXIMIZED) not available on target platform"); + if (glfwGetWindowAttrib(platform.handle, GLFW_RESIZABLE) == GLFW_TRUE) + { + if (platform.unmaximizedWidth && platform.unmaximizedHeight) glfwSetWindowSize(platform.handle, platform.unmaximizedWidth, platform.unmaximizedHeight); + + CORE.Window.flags &= ~FLAG_WINDOW_MAXIMIZED; + } } // State change: FLAG_WINDOW_UNDECORATED From cb21fe88d3cc10f9c4c5ec83a5ad0a8c90c934da Mon Sep 17 00:00:00 2001 From: Asdqwe Date: Mon, 21 Oct 2024 04:45:46 -0300 Subject: [PATCH 142/208] Fix MaximizeWindow() for PLATFORM_WEB (#4404) --- src/platforms/rcore_web.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/platforms/rcore_web.c b/src/platforms/rcore_web.c index 70623166d..c41094446 100644 --- a/src/platforms/rcore_web.c +++ b/src/platforms/rcore_web.c @@ -319,7 +319,7 @@ void ToggleBorderlessWindowed(void) // Set window state: maximized, if resizable void MaximizeWindow(void) { - if (glfwGetWindowAttrib(platform.handle, GLFW_RESIZABLE) == GLFW_TRUE) + if (glfwGetWindowAttrib(platform.handle, GLFW_RESIZABLE) == GLFW_TRUE && !(CORE.Window.flags & FLAG_WINDOW_MAXIMIZED)) { platform.unmaximizedWidth = CORE.Window.screen.width; platform.unmaximizedHeight = CORE.Window.screen.height; @@ -342,7 +342,7 @@ void MinimizeWindow(void) // Set window state: not minimized/maximized void RestoreWindow(void) { - if (glfwGetWindowAttrib(platform.handle, GLFW_RESIZABLE) == GLFW_TRUE) + if (glfwGetWindowAttrib(platform.handle, GLFW_RESIZABLE) == GLFW_TRUE && (CORE.Window.flags & FLAG_WINDOW_MAXIMIZED)) { if (platform.unmaximizedWidth && platform.unmaximizedHeight) glfwSetWindowSize(platform.handle, platform.unmaximizedWidth, platform.unmaximizedHeight); From 9d0b1f0171b2f072a573143c68f3a589de70efd5 Mon Sep 17 00:00:00 2001 From: Asdqwe Date: Mon, 21 Oct 2024 04:47:19 -0300 Subject: [PATCH 143/208] Adds SetWindowOpacity() implementation for PLATFORM_WEB (#4403) --- src/platforms/rcore_web.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/platforms/rcore_web.c b/src/platforms/rcore_web.c index c41094446..36af66a47 100644 --- a/src/platforms/rcore_web.c +++ b/src/platforms/rcore_web.c @@ -673,7 +673,9 @@ void SetWindowSize(int width, int height) // Set window opacity, value opacity is between 0.0 and 1.0 void SetWindowOpacity(float opacity) { - TRACELOG(LOG_WARNING, "SetWindowOpacity() not available on target platform"); + if (opacity >= 1.0f) opacity = 1.0f; + else if (opacity <= 0.0f) opacity = 0.0f; + EM_ASM({ document.getElementById('canvas').style.opacity = $0; }, opacity); } // Set window focused From 110ee74875412beb41ffb53330b47ec9cb052b2d Mon Sep 17 00:00:00 2001 From: Sage Hane Date: Mon, 21 Oct 2024 19:57:11 +0900 Subject: [PATCH 144/208] build.zig: Merge `src/build.zig` to `build.zig` (#4393) * build.zig: Move `src/build.zig` to `build.zig` * build.zig: Remove uses of `@src` * build.zig: Update entry point --- build.zig | 438 +++++++++++++++++++++++++++++++++++++++++++++++- src/build.zig | 455 -------------------------------------------------- 2 files changed, 429 insertions(+), 464 deletions(-) delete mode 100644 src/build.zig diff --git a/build.zig b/build.zig index 029482608..56e69caf4 100644 --- a/build.zig +++ b/build.zig @@ -1,14 +1,434 @@ const std = @import("std"); -const raylib = @import("src/build.zig"); +const builtin = @import("builtin"); -// This has been tested to work with zig 0.12.0 -pub fn build(b: *std.Build) !void { - try raylib.build(b); +/// Minimum supported version of Zig +const min_ver = "0.12.0"; + +comptime { + const order = std.SemanticVersion.order; + const parse = std.SemanticVersion.parse; + if (order(builtin.zig_version, parse(min_ver) catch unreachable) == .lt) + @compileError("Raylib requires zig version " ++ min_ver); } -// expose helper functions to user's build.zig -pub const addRaylib = raylib.addRaylib; -pub const addRaygui = raylib.addRaygui; +// NOTE(freakmangd): I don't like using a global here, but it prevents having to +// get the flags a second time when adding raygui +var raylib_flags_arr: std.ArrayListUnmanaged([]const u8) = .{}; -// expose options for compiling -pub const RaylibOptions = raylib.Options; +// This has been tested with zig version 0.12.0 +pub fn addRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, options: Options) !*std.Build.Step.Compile { + const raylib_dep = b.dependencyFromBuildZig(@This(), .{ + .target = target, + .optimize = optimize, + .raudio = options.raudio, + .rmodels = options.rmodels, + .rshapes = options.rshapes, + .rtext = options.rtext, + .rtextures = options.rtextures, + .platform = options.platform, + .shared = options.shared, + .linux_display_backend = options.linux_display_backend, + .opengl_version = options.opengl_version, + .config = options.config, + }); + const raylib = raylib_dep.artifact("raylib"); + + if (options.raygui) { + const raygui_dep = b.dependency(options.raygui_dependency_name, .{}); + addRaygui(b, raylib, raygui_dep); + } + + return raylib; +} + +fn setDesktopPlatform(raylib: *std.Build.Step.Compile, platform: PlatformBackend) void { + raylib.defineCMacro("PLATFORM_DESKTOP", null); + + switch (platform) { + .glfw => raylib.defineCMacro("PLATFORM_DESKTOP_GLFW", null), + .rgfw => raylib.defineCMacro("PLATFORM_DESKTOP_RGFW", null), + .sdl => raylib.defineCMacro("PLATFORM_DESKTOP_SDL", null), + else => {}, + } +} + +/// A list of all flags from `src/config.h` that one may override +const config_h_flags = outer: { + // Set this value higher if compile errors happen as `src/config.h` gets larger + @setEvalBranchQuota(1 << 20); + + const config_h = @embedFile("src/config.h"); + var flags: [std.mem.count(u8, config_h, "\n") + 1][]const u8 = undefined; + + var i = 0; + var lines = std.mem.tokenizeScalar(u8, config_h, '\n'); + while (lines.next()) |line| { + if (!std.mem.containsAtLeast(u8, line, 1, "SUPPORT")) continue; + if (std.mem.startsWith(u8, line, "//")) continue; + if (std.mem.startsWith(u8, line, "#if")) continue; + + var flag = std.mem.trimLeft(u8, line, " \t"); // Trim whitespace + flag = flag["#define ".len - 1 ..]; // Remove #define + flag = std.mem.trimLeft(u8, flag, " \t"); // Trim whitespace + flag = flag[0 .. std.mem.indexOf(u8, flag, " ") orelse continue]; // Flag is only one word, so capture till space + flag = "-D" ++ flag; // Prepend with -D + + flags[i] = flag; + i += 1; + } + + // Uncomment this to check what flags normally get passed + //@compileLog(flags[0..i].*); + break :outer flags[0..i].*; +}; + +fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, options: Options) !*std.Build.Step.Compile { + raylib_flags_arr.clearRetainingCapacity(); + + const shared_flags = &[_][]const u8{ + "-fPIC", + "-DBUILD_LIBTYPE_SHARED", + }; + try raylib_flags_arr.appendSlice(b.allocator, &[_][]const u8{ + "-std=gnu99", + "-D_GNU_SOURCE", + "-DGL_SILENCE_DEPRECATION=199309L", + "-fno-sanitize=undefined", // https://github.com/raysan5/raylib/issues/3674 + }); + if (options.config.len > 0) { + // Sets a flag indiciating the use of a custom `config.h` + try raylib_flags_arr.append(b.allocator, "-DEXTERNAL_CONFIG_FLAGS"); + + // Splits a space-separated list of config flags into multiple flags + // + // Note: This means certain flags like `-x c++` won't be processed properly. + // `-xc++` or similar should be used when possible + var config_iter = std.mem.tokenizeScalar(u8, options.config, ' '); + + // Apply config flags supplied by the user + while (config_iter.next()) |config_flag| + try raylib_flags_arr.append(b.allocator, config_flag); + + // Apply all relevant configs from `src/config.h` *except* the user-specified ones + // + // Note: Currently using a suboptimal `O(m*n)` time algorithm where: + // `m` corresponds roughly to the number of lines in `src/config.h` + // `n` corresponds to the number of user-specified flags + outer: for (config_h_flags) |flag| { + // If a user already specified the flag, skip it + while (config_iter.next()) |config_flag| { + // For a user-specified flag to match, it must share the same prefix and have the + // same length or be followed by an equals sign + if (!std.mem.startsWith(u8, config_flag, flag)) continue; + if (config_flag.len == flag.len or config_flag[flag.len] == '=') continue :outer; + } + + // Otherwise, append default value from config.h to compile flags + try raylib_flags_arr.append(b.allocator, flag); + } + } + + if (options.shared) { + try raylib_flags_arr.appendSlice(b.allocator, shared_flags); + } + + const raylib = if (options.shared) + b.addSharedLibrary(.{ + .name = "raylib", + .target = target, + .optimize = optimize, + }) + else + b.addStaticLibrary(.{ + .name = "raylib", + .target = target, + .optimize = optimize, + }); + raylib.linkLibC(); + + // No GLFW required on PLATFORM_DRM + if (options.platform != .drm) { + raylib.addIncludePath(b.path("src/external/glfw/include")); + } + + var c_source_files = try std.ArrayList([]const u8).initCapacity(b.allocator, 2); + c_source_files.appendSliceAssumeCapacity(&.{ "src/rcore.c", "src/utils.c" }); + + if (options.raudio) { + try c_source_files.append("src/raudio.c"); + } + if (options.rmodels) { + try c_source_files.append("src/rmodels.c"); + } + if (options.rshapes) { + try c_source_files.append("src/rshapes.c"); + } + if (options.rtext) { + try c_source_files.append("src/rtext.c"); + } + if (options.rtextures) { + try c_source_files.append("src/rtextures.c"); + } + + if (options.opengl_version != .auto) { + raylib.defineCMacro(options.opengl_version.toCMacroStr(), null); + } + + switch (target.result.os.tag) { + .windows => { + try c_source_files.append("src/rglfw.c"); + raylib.linkSystemLibrary("winmm"); + raylib.linkSystemLibrary("gdi32"); + raylib.linkSystemLibrary("opengl32"); + + setDesktopPlatform(raylib, options.platform); + }, + .linux => { + if (options.platform != .drm) { + try c_source_files.append("src/rglfw.c"); + raylib.linkSystemLibrary("GL"); + raylib.linkSystemLibrary("rt"); + raylib.linkSystemLibrary("dl"); + raylib.linkSystemLibrary("m"); + + raylib.addLibraryPath(.{ .cwd_relative = "/usr/lib" }); + raylib.addIncludePath(.{ .cwd_relative = "/usr/include" }); + if (options.linux_display_backend == .X11 or options.linux_display_backend == .Both) { + raylib.defineCMacro("_GLFW_X11", null); + raylib.linkSystemLibrary("X11"); + } + + if (options.linux_display_backend == .Wayland or options.linux_display_backend == .Both) { + _ = b.findProgram(&.{"wayland-scanner"}, &.{}) catch { + std.log.err( + \\ `wayland-scanner` may not be installed on the system. + \\ You can switch to X11 in your `build.zig` by changing `Options.linux_display_backend` + , .{}); + @panic("`wayland-scanner` not found"); + }; + raylib.defineCMacro("_GLFW_WAYLAND", null); + raylib.linkSystemLibrary("wayland-client"); + raylib.linkSystemLibrary("wayland-cursor"); + raylib.linkSystemLibrary("wayland-egl"); + raylib.linkSystemLibrary("xkbcommon"); + waylandGenerate(b, raylib, "wayland.xml", "wayland-client-protocol"); + waylandGenerate(b, raylib, "xdg-shell.xml", "xdg-shell-client-protocol"); + waylandGenerate(b, raylib, "xdg-decoration-unstable-v1.xml", "xdg-decoration-unstable-v1-client-protocol"); + waylandGenerate(b, raylib, "viewporter.xml", "viewporter-client-protocol"); + waylandGenerate(b, raylib, "relative-pointer-unstable-v1.xml", "relative-pointer-unstable-v1-client-protocol"); + waylandGenerate(b, raylib, "pointer-constraints-unstable-v1.xml", "pointer-constraints-unstable-v1-client-protocol"); + waylandGenerate(b, raylib, "fractional-scale-v1.xml", "fractional-scale-v1-client-protocol"); + waylandGenerate(b, raylib, "xdg-activation-v1.xml", "xdg-activation-v1-client-protocol"); + waylandGenerate(b, raylib, "idle-inhibit-unstable-v1.xml", "idle-inhibit-unstable-v1-client-protocol"); + } + setDesktopPlatform(raylib, options.platform); + } else { + if (options.opengl_version == .auto) { + raylib.linkSystemLibrary("GLESv2"); + raylib.defineCMacro("GRAPHICS_API_OPENGL_ES2", null); + } + + raylib.linkSystemLibrary("EGL"); + raylib.linkSystemLibrary("drm"); + raylib.linkSystemLibrary("gbm"); + raylib.linkSystemLibrary("pthread"); + raylib.linkSystemLibrary("rt"); + raylib.linkSystemLibrary("m"); + raylib.linkSystemLibrary("dl"); + raylib.addIncludePath(.{ .cwd_relative = "/usr/include/libdrm" }); + + raylib.defineCMacro("PLATFORM_DRM", null); + raylib.defineCMacro("EGL_NO_X11", null); + raylib.defineCMacro("DEFAULT_BATCH_BUFFER_ELEMENT", "2048"); + } + }, + .freebsd, .openbsd, .netbsd, .dragonfly => { + try c_source_files.append("rglfw.c"); + raylib.linkSystemLibrary("GL"); + raylib.linkSystemLibrary("rt"); + raylib.linkSystemLibrary("dl"); + raylib.linkSystemLibrary("m"); + raylib.linkSystemLibrary("X11"); + raylib.linkSystemLibrary("Xrandr"); + raylib.linkSystemLibrary("Xinerama"); + raylib.linkSystemLibrary("Xi"); + raylib.linkSystemLibrary("Xxf86vm"); + raylib.linkSystemLibrary("Xcursor"); + + setDesktopPlatform(raylib, options.platform); + }, + .macos => { + // On macos rglfw.c include Objective-C files. + try raylib_flags_arr.append(b.allocator, "-ObjC"); + raylib.root_module.addCSourceFile(.{ + .file = b.path("src/rglfw.c"), + .flags = raylib_flags_arr.items, + }); + _ = raylib_flags_arr.pop(); + raylib.linkFramework("Foundation"); + raylib.linkFramework("CoreServices"); + raylib.linkFramework("CoreGraphics"); + raylib.linkFramework("AppKit"); + raylib.linkFramework("IOKit"); + + setDesktopPlatform(raylib, options.platform); + }, + .emscripten => { + raylib.defineCMacro("PLATFORM_WEB", null); + if (options.opengl_version == .auto) { + raylib.defineCMacro("GRAPHICS_API_OPENGL_ES2", null); + } + + if (b.sysroot == null) { + @panic("Pass '--sysroot \"$EMSDK/upstream/emscripten\"'"); + } + + const cache_include = b.pathJoin(&.{ b.sysroot.?, "cache", "sysroot", "include" }); + + var dir = std.fs.openDirAbsolute(cache_include, std.fs.Dir.OpenDirOptions{ .access_sub_paths = true, .no_follow = true }) catch @panic("No emscripten cache. Generate it!"); + dir.close(); + raylib.addIncludePath(.{ .cwd_relative = cache_include }); + }, + else => { + @panic("Unsupported OS"); + }, + } + + raylib.root_module.addCSourceFiles(.{ + .files = c_source_files.items, + .flags = raylib_flags_arr.items, + }); + + return raylib; +} + +/// This function does not need to be called if you passed .raygui = true to addRaylib +pub fn addRaygui(b: *std.Build, raylib: *std.Build.Step.Compile, raygui_dep: *std.Build.Dependency) void { + if (raylib_flags_arr.items.len == 0) { + @panic( + \\argument 2 `raylib` in `addRaygui` must come from b.dependency("raylib", ...).artifact("raylib") + ); + } + + var gen_step = b.addWriteFiles(); + raylib.step.dependOn(&gen_step.step); + + const raygui_c_path = gen_step.add("raygui.c", "#define RAYGUI_IMPLEMENTATION\n#include \"raygui.h\"\n"); + raylib.addCSourceFile(.{ .file = raygui_c_path, .flags = raylib_flags_arr.items }); + raylib.addIncludePath(raygui_dep.path("src")); + + raylib.installHeader(raygui_dep.path("src/raygui.h"), "raygui.h"); +} + +pub const Options = struct { + raudio: bool = true, + rmodels: bool = true, + rshapes: bool = true, + rtext: bool = true, + rtextures: bool = true, + raygui: bool = false, + platform: PlatformBackend = .glfw, + shared: bool = false, + linux_display_backend: LinuxDisplayBackend = .Both, + opengl_version: OpenglVersion = .auto, + /// config should be a list of space-separated cflags, eg, "-DSUPPORT_CUSTOM_FRAME_CONTROL" + config: []const u8 = &.{}, + + raygui_dependency_name: []const u8 = "raygui", + + const defaults = Options{}; + + fn getOptions(b: *std.Build) Options { + return .{ + .platform = b.option(PlatformBackend, "platform", "Choose the platform backedn for desktop target") orelse defaults.platform, + .raudio = b.option(bool, "raudio", "Compile with audio support") orelse defaults.raudio, + .raygui = b.option(bool, "raygui", "Compile with raygui support") orelse defaults.raygui, + .rmodels = b.option(bool, "rmodels", "Compile with models support") orelse defaults.rmodels, + .rtext = b.option(bool, "rtext", "Compile with text support") orelse defaults.rtext, + .rtextures = b.option(bool, "rtextures", "Compile with textures support") orelse defaults.rtextures, + .rshapes = b.option(bool, "rshapes", "Compile with shapes support") orelse defaults.rshapes, + .shared = b.option(bool, "shared", "Compile as shared library") orelse defaults.shared, + .linux_display_backend = b.option(LinuxDisplayBackend, "linux_display_backend", "Linux display backend to use") orelse defaults.linux_display_backend, + .opengl_version = b.option(OpenglVersion, "opengl_version", "OpenGL version to use") orelse defaults.opengl_version, + .config = b.option([]const u8, "config", "Compile with custom define macros overriding config.h") orelse &.{}, + }; + } +}; + +pub const OpenglVersion = enum { + auto, + gl_1_1, + gl_2_1, + gl_3_3, + gl_4_3, + gles_2, + gles_3, + + pub fn toCMacroStr(self: @This()) []const u8 { + switch (self) { + .auto => @panic("OpenglVersion.auto cannot be turned into a C macro string"), + .gl_1_1 => return "GRAPHICS_API_OPENGL_11", + .gl_2_1 => return "GRAPHICS_API_OPENGL_21", + .gl_3_3 => return "GRAPHICS_API_OPENGL_33", + .gl_4_3 => return "GRAPHICS_API_OPENGL_43", + .gles_2 => return "GRAPHICS_API_OPENGL_ES2", + .gles_3 => return "GRAPHICS_API_OPENGL_ES3", + } + } +}; + +pub const LinuxDisplayBackend = enum { + X11, + Wayland, + Both, +}; + +pub const PlatformBackend = enum { + glfw, + rgfw, + sdl, + drm, +}; + +pub fn build(b: *std.Build) !void { + // Standard target options allows the person running `zig build` to choose + // what target to build for. Here we do not override the defaults, which + // means any target is allowed, and the default is native. Other options + // for restricting supported target set are available. + const target = b.standardTargetOptions(.{}); + // Standard optimization options allow the person running `zig build` to select + // between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall. Here we do not + // set a preferred release mode, allowing the user to decide how to optimize. + const optimize = b.standardOptimizeOption(.{}); + + const lib = try compileRaylib(b, target, optimize, Options.getOptions(b)); + + lib.installHeader(b.path("src/raylib.h"), "raylib.h"); + lib.installHeader(b.path("src/raymath.h"), "raymath.h"); + lib.installHeader(b.path("src/rlgl.h"), "rlgl.h"); + + b.installArtifact(lib); +} + +fn waylandGenerate( + b: *std.Build, + raylib: *std.Build.Step.Compile, + comptime protocol: []const u8, + comptime basename: []const u8, +) void { + const waylandDir = "src/external/glfw/deps/wayland"; + const protocolDir = b.pathJoin(&.{ waylandDir, protocol }); + const clientHeader = basename ++ ".h"; + const privateCode = basename ++ "-code.h"; + + const client_step = b.addSystemCommand(&.{ "wayland-scanner", "client-header" }); + client_step.addFileArg(b.path(protocolDir)); + raylib.addIncludePath(client_step.addOutputFileArg(clientHeader).dirname()); + + const private_step = b.addSystemCommand(&.{ "wayland-scanner", "private-code" }); + private_step.addFileArg(b.path(protocolDir)); + raylib.addIncludePath(private_step.addOutputFileArg(privateCode).dirname()); + + raylib.step.dependOn(&client_step.step); + raylib.step.dependOn(&private_step.step); +} diff --git a/src/build.zig b/src/build.zig deleted file mode 100644 index 23b4d66b7..000000000 --- a/src/build.zig +++ /dev/null @@ -1,455 +0,0 @@ -const std = @import("std"); -const builtin = @import("builtin"); - -/// Minimum supported version of Zig -const min_ver = "0.12.0"; - -comptime { - const order = std.SemanticVersion.order; - const parse = std.SemanticVersion.parse; - if (order(builtin.zig_version, parse(min_ver) catch unreachable) == .lt) - @compileError("Raylib requires zig version " ++ min_ver); -} - -// NOTE(freakmangd): I don't like using a global here, but it prevents having to -// get the flags a second time when adding raygui -var raylib_flags_arr: std.ArrayListUnmanaged([]const u8) = .{}; - -/// we're not inside the actual build script recognized by the -/// zig build system; use this type where one would otherwise -/// use `@This()` when inside the actual entrypoint file. -const BuildScript = @import("../build.zig"); - -// This has been tested with zig version 0.12.0 -pub fn addRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, options: Options) !*std.Build.Step.Compile { - const raylib_dep = b.dependencyFromBuildZig(BuildScript, .{ - .target = target, - .optimize = optimize, - .raudio = options.raudio, - .rmodels = options.rmodels, - .rshapes = options.rshapes, - .rtext = options.rtext, - .rtextures = options.rtextures, - .platform = options.platform, - .shared = options.shared, - .linux_display_backend = options.linux_display_backend, - .opengl_version = options.opengl_version, - .config = options.config, - }); - const raylib = raylib_dep.artifact("raylib"); - - if (options.raygui) { - const raygui_dep = b.dependency(options.raygui_dependency_name, .{}); - addRaygui(b, raylib, raygui_dep); - } - - return raylib; -} - -fn setDesktopPlatform(raylib: *std.Build.Step.Compile, platform: PlatformBackend) void { - raylib.defineCMacro("PLATFORM_DESKTOP", null); - - switch (platform) { - .glfw => raylib.defineCMacro("PLATFORM_DESKTOP_GLFW", null), - .rgfw => raylib.defineCMacro("PLATFORM_DESKTOP_RGFW", null), - .sdl => raylib.defineCMacro("PLATFORM_DESKTOP_SDL", null), - else => {}, - } -} - -/// TODO: Once the minimum supported version is bumped to 0.14.0, it can be simplified again: -/// https://github.com/raysan5/raylib/pull/4375#issuecomment-2408998315 -/// https://github.com/raysan5/raylib/blob/9b9c72eb0dc705cde194b053a366a40396acfb67/src/build.zig#L54-L56 -fn srcDir(b: *std.Build) []const u8 { - comptime { - const order = std.SemanticVersion.order; - const parse = std.SemanticVersion.parse; - if (order(parse(min_ver) catch unreachable, parse("0.14.0") catch unreachable) != .lt) - @compileError("Please take a look at this function again"); - } - - const src_file = std.fs.path.relative(b.allocator, ".", @src().file) catch @panic("OOM"); - return std.fs.path.dirname(src_file) orelse "."; -} - -/// A list of all flags from `src/config.h` that one may override -const config_h_flags = outer: { - // Set this value higher if compile errors happen as `src/config.h` gets larger - @setEvalBranchQuota(1 << 20); - - const config_h = @embedFile("config.h"); - var flags: [std.mem.count(u8, config_h, "\n") + 1][]const u8 = undefined; - - var i = 0; - var lines = std.mem.tokenizeScalar(u8, config_h, '\n'); - while (lines.next()) |line| { - if (!std.mem.containsAtLeast(u8, line, 1, "SUPPORT")) continue; - if (std.mem.startsWith(u8, line, "//")) continue; - if (std.mem.startsWith(u8, line, "#if")) continue; - - var flag = std.mem.trimLeft(u8, line, " \t"); // Trim whitespace - flag = flag["#define ".len - 1 ..]; // Remove #define - flag = std.mem.trimLeft(u8, flag, " \t"); // Trim whitespace - flag = flag[0 .. std.mem.indexOf(u8, flag, " ") orelse continue]; // Flag is only one word, so capture till space - flag = "-D" ++ flag; // Prepend with -D - - flags[i] = flag; - i += 1; - } - - // Uncomment this to check what flags normally get passed - //@compileLog(flags[0..i].*); - break :outer flags[0..i].*; -}; - -fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, options: Options) !*std.Build.Step.Compile { - raylib_flags_arr.clearRetainingCapacity(); - - const shared_flags = &[_][]const u8{ - "-fPIC", - "-DBUILD_LIBTYPE_SHARED", - }; - try raylib_flags_arr.appendSlice(b.allocator, &[_][]const u8{ - "-std=gnu99", - "-D_GNU_SOURCE", - "-DGL_SILENCE_DEPRECATION=199309L", - "-fno-sanitize=undefined", // https://github.com/raysan5/raylib/issues/3674 - }); - if (options.config.len > 0) { - // Sets a flag indiciating the use of a custom `config.h` - try raylib_flags_arr.append(b.allocator, "-DEXTERNAL_CONFIG_FLAGS"); - - // Splits a space-separated list of config flags into multiple flags - // - // Note: This means certain flags like `-x c++` won't be processed properly. - // `-xc++` or similar should be used when possible - var config_iter = std.mem.tokenizeScalar(u8, options.config, ' '); - - // Apply config flags supplied by the user - while (config_iter.next()) |config_flag| - try raylib_flags_arr.append(b.allocator, config_flag); - - // Apply all relevant configs from `src/config.h` *except* the user-specified ones - // - // Note: Currently using a suboptimal `O(m*n)` time algorithm where: - // `m` corresponds roughly to the number of lines in `src/config.h` - // `n` corresponds to the number of user-specified flags - outer: for (config_h_flags) |flag| { - // If a user already specified the flag, skip it - while (config_iter.next()) |config_flag| { - // For a user-specified flag to match, it must share the same prefix and have the - // same length or be followed by an equals sign - if (!std.mem.startsWith(u8, config_flag, flag)) continue; - if (config_flag.len == flag.len or config_flag[flag.len] == '=') continue :outer; - } - - // Otherwise, append default value from config.h to compile flags - try raylib_flags_arr.append(b.allocator, flag); - } - } - - if (options.shared) { - try raylib_flags_arr.appendSlice(b.allocator, shared_flags); - } - - const raylib = if (options.shared) - b.addSharedLibrary(.{ - .name = "raylib", - .target = target, - .optimize = optimize, - }) - else - b.addStaticLibrary(.{ - .name = "raylib", - .target = target, - .optimize = optimize, - }); - raylib.linkLibC(); - - // No GLFW required on PLATFORM_DRM - if (options.platform != .drm) { - raylib.addIncludePath(b.path(b.pathJoin(&.{ srcDir(b), "external/glfw/include" }))); - } - - var c_source_files = try std.ArrayList([]const u8).initCapacity(b.allocator, 2); - c_source_files.appendSliceAssumeCapacity(&.{ "rcore.c", "utils.c" }); - - if (options.raudio) { - try c_source_files.append("raudio.c"); - } - if (options.rmodels) { - try c_source_files.append("rmodels.c"); - } - if (options.rshapes) { - try c_source_files.append("rshapes.c"); - } - if (options.rtext) { - try c_source_files.append("rtext.c"); - } - if (options.rtextures) { - try c_source_files.append("rtextures.c"); - } - - if (options.opengl_version != .auto) { - raylib.defineCMacro(options.opengl_version.toCMacroStr(), null); - } - - switch (target.result.os.tag) { - .windows => { - try c_source_files.append("rglfw.c"); - raylib.linkSystemLibrary("winmm"); - raylib.linkSystemLibrary("gdi32"); - raylib.linkSystemLibrary("opengl32"); - - setDesktopPlatform(raylib, options.platform); - }, - .linux => { - if (options.platform != .drm) { - try c_source_files.append("rglfw.c"); - raylib.linkSystemLibrary("GL"); - raylib.linkSystemLibrary("rt"); - raylib.linkSystemLibrary("dl"); - raylib.linkSystemLibrary("m"); - - raylib.addLibraryPath(.{ .cwd_relative = "/usr/lib" }); - raylib.addIncludePath(.{ .cwd_relative = "/usr/include" }); - if (options.linux_display_backend == .X11 or options.linux_display_backend == .Both) { - raylib.defineCMacro("_GLFW_X11", null); - raylib.linkSystemLibrary("X11"); - } - - if (options.linux_display_backend == .Wayland or options.linux_display_backend == .Both) { - _ = b.findProgram(&.{"wayland-scanner"}, &.{}) catch { - std.log.err( - \\ `wayland-scanner` may not be installed on the system. - \\ You can switch to X11 in your `build.zig` by changing `Options.linux_display_backend` - , .{}); - @panic("`wayland-scanner` not found"); - }; - raylib.defineCMacro("_GLFW_WAYLAND", null); - raylib.linkSystemLibrary("wayland-client"); - raylib.linkSystemLibrary("wayland-cursor"); - raylib.linkSystemLibrary("wayland-egl"); - raylib.linkSystemLibrary("xkbcommon"); - waylandGenerate(b, raylib, "wayland.xml", "wayland-client-protocol"); - waylandGenerate(b, raylib, "xdg-shell.xml", "xdg-shell-client-protocol"); - waylandGenerate(b, raylib, "xdg-decoration-unstable-v1.xml", "xdg-decoration-unstable-v1-client-protocol"); - waylandGenerate(b, raylib, "viewporter.xml", "viewporter-client-protocol"); - waylandGenerate(b, raylib, "relative-pointer-unstable-v1.xml", "relative-pointer-unstable-v1-client-protocol"); - waylandGenerate(b, raylib, "pointer-constraints-unstable-v1.xml", "pointer-constraints-unstable-v1-client-protocol"); - waylandGenerate(b, raylib, "fractional-scale-v1.xml", "fractional-scale-v1-client-protocol"); - waylandGenerate(b, raylib, "xdg-activation-v1.xml", "xdg-activation-v1-client-protocol"); - waylandGenerate(b, raylib, "idle-inhibit-unstable-v1.xml", "idle-inhibit-unstable-v1-client-protocol"); - } - setDesktopPlatform(raylib, options.platform); - } else { - if (options.opengl_version == .auto) { - raylib.linkSystemLibrary("GLESv2"); - raylib.defineCMacro("GRAPHICS_API_OPENGL_ES2", null); - } - - raylib.linkSystemLibrary("EGL"); - raylib.linkSystemLibrary("drm"); - raylib.linkSystemLibrary("gbm"); - raylib.linkSystemLibrary("pthread"); - raylib.linkSystemLibrary("rt"); - raylib.linkSystemLibrary("m"); - raylib.linkSystemLibrary("dl"); - raylib.addIncludePath(.{ .cwd_relative = "/usr/include/libdrm" }); - - raylib.defineCMacro("PLATFORM_DRM", null); - raylib.defineCMacro("EGL_NO_X11", null); - raylib.defineCMacro("DEFAULT_BATCH_BUFFER_ELEMENT", "2048"); - } - }, - .freebsd, .openbsd, .netbsd, .dragonfly => { - try c_source_files.append("rglfw.c"); - raylib.linkSystemLibrary("GL"); - raylib.linkSystemLibrary("rt"); - raylib.linkSystemLibrary("dl"); - raylib.linkSystemLibrary("m"); - raylib.linkSystemLibrary("X11"); - raylib.linkSystemLibrary("Xrandr"); - raylib.linkSystemLibrary("Xinerama"); - raylib.linkSystemLibrary("Xi"); - raylib.linkSystemLibrary("Xxf86vm"); - raylib.linkSystemLibrary("Xcursor"); - - setDesktopPlatform(raylib, options.platform); - }, - .macos => { - // On macos rglfw.c include Objective-C files. - try raylib_flags_arr.append(b.allocator, "-ObjC"); - raylib.root_module.addCSourceFile(.{ - .file = b.path(b.pathJoin(&.{ srcDir(b), "rglfw.c" })), - .flags = raylib_flags_arr.items, - }); - _ = raylib_flags_arr.pop(); - raylib.linkFramework("Foundation"); - raylib.linkFramework("CoreServices"); - raylib.linkFramework("CoreGraphics"); - raylib.linkFramework("AppKit"); - raylib.linkFramework("IOKit"); - - setDesktopPlatform(raylib, options.platform); - }, - .emscripten => { - raylib.defineCMacro("PLATFORM_WEB", null); - if (options.opengl_version == .auto) { - raylib.defineCMacro("GRAPHICS_API_OPENGL_ES2", null); - } - - if (b.sysroot == null) { - @panic("Pass '--sysroot \"$EMSDK/upstream/emscripten\"'"); - } - - const cache_include = b.pathJoin(&.{ b.sysroot.?, "cache", "sysroot", "include" }); - - var dir = std.fs.openDirAbsolute(cache_include, std.fs.Dir.OpenDirOptions{ .access_sub_paths = true, .no_follow = true }) catch @panic("No emscripten cache. Generate it!"); - dir.close(); - raylib.addIncludePath(.{ .cwd_relative = cache_include }); - }, - else => { - @panic("Unsupported OS"); - }, - } - - raylib.root_module.addCSourceFiles(.{ - .root = b.path(srcDir(b)), - .files = c_source_files.items, - .flags = raylib_flags_arr.items, - }); - - return raylib; -} - -/// This function does not need to be called if you passed .raygui = true to addRaylib -pub fn addRaygui(b: *std.Build, raylib: *std.Build.Step.Compile, raygui_dep: *std.Build.Dependency) void { - if (raylib_flags_arr.items.len == 0) { - @panic( - \\argument 2 `raylib` in `addRaygui` must come from b.dependency("raylib", ...).artifact("raylib") - ); - } - - var gen_step = b.addWriteFiles(); - raylib.step.dependOn(&gen_step.step); - - const raygui_c_path = gen_step.add("raygui.c", "#define RAYGUI_IMPLEMENTATION\n#include \"raygui.h\"\n"); - raylib.addCSourceFile(.{ .file = raygui_c_path, .flags = raylib_flags_arr.items }); - raylib.addIncludePath(raygui_dep.path("src")); - - raylib.installHeader(raygui_dep.path("src/raygui.h"), "raygui.h"); -} - -pub const Options = struct { - raudio: bool = true, - rmodels: bool = true, - rshapes: bool = true, - rtext: bool = true, - rtextures: bool = true, - raygui: bool = false, - platform: PlatformBackend = .glfw, - shared: bool = false, - linux_display_backend: LinuxDisplayBackend = .Both, - opengl_version: OpenglVersion = .auto, - /// config should be a list of space-separated cflags, eg, "-DSUPPORT_CUSTOM_FRAME_CONTROL" - config: []const u8 = &.{}, - - raygui_dependency_name: []const u8 = "raygui", - - const defaults = Options{}; - - fn getOptions(b: *std.Build) Options { - return .{ - .platform = b.option(PlatformBackend, "platform", "Choose the platform backedn for desktop target") orelse defaults.platform, - .raudio = b.option(bool, "raudio", "Compile with audio support") orelse defaults.raudio, - .raygui = b.option(bool, "raygui", "Compile with raygui support") orelse defaults.raygui, - .rmodels = b.option(bool, "rmodels", "Compile with models support") orelse defaults.rmodels, - .rtext = b.option(bool, "rtext", "Compile with text support") orelse defaults.rtext, - .rtextures = b.option(bool, "rtextures", "Compile with textures support") orelse defaults.rtextures, - .rshapes = b.option(bool, "rshapes", "Compile with shapes support") orelse defaults.rshapes, - .shared = b.option(bool, "shared", "Compile as shared library") orelse defaults.shared, - .linux_display_backend = b.option(LinuxDisplayBackend, "linux_display_backend", "Linux display backend to use") orelse defaults.linux_display_backend, - .opengl_version = b.option(OpenglVersion, "opengl_version", "OpenGL version to use") orelse defaults.opengl_version, - .config = b.option([]const u8, "config", "Compile with custom define macros overriding config.h") orelse &.{}, - }; - } -}; - -pub const OpenglVersion = enum { - auto, - gl_1_1, - gl_2_1, - gl_3_3, - gl_4_3, - gles_2, - gles_3, - - pub fn toCMacroStr(self: @This()) []const u8 { - switch (self) { - .auto => @panic("OpenglVersion.auto cannot be turned into a C macro string"), - .gl_1_1 => return "GRAPHICS_API_OPENGL_11", - .gl_2_1 => return "GRAPHICS_API_OPENGL_21", - .gl_3_3 => return "GRAPHICS_API_OPENGL_33", - .gl_4_3 => return "GRAPHICS_API_OPENGL_43", - .gles_2 => return "GRAPHICS_API_OPENGL_ES2", - .gles_3 => return "GRAPHICS_API_OPENGL_ES3", - } - } -}; - -pub const LinuxDisplayBackend = enum { - X11, - Wayland, - Both, -}; - -pub const PlatformBackend = enum { - glfw, - rgfw, - sdl, - drm, -}; - -pub fn build(b: *std.Build) !void { - // Standard target options allows the person running `zig build` to choose - // what target to build for. Here we do not override the defaults, which - // means any target is allowed, and the default is native. Other options - // for restricting supported target set are available. - const target = b.standardTargetOptions(.{}); - // Standard optimization options allow the person running `zig build` to select - // between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall. Here we do not - // set a preferred release mode, allowing the user to decide how to optimize. - const optimize = b.standardOptimizeOption(.{}); - - const lib = try compileRaylib(b, target, optimize, Options.getOptions(b)); - - lib.installHeader(b.path(b.pathJoin(&.{ srcDir(b), "raylib.h" })), "raylib.h"); - lib.installHeader(b.path(b.pathJoin(&.{ srcDir(b), "raymath.h" })), "raymath.h"); - lib.installHeader(b.path(b.pathJoin(&.{ srcDir(b), "rlgl.h" })), "rlgl.h"); - - b.installArtifact(lib); -} - -fn waylandGenerate( - b: *std.Build, - raylib: *std.Build.Step.Compile, - comptime protocol: []const u8, - comptime basename: []const u8, -) void { - const waylandDir = b.pathJoin(&.{ srcDir(b), "external/glfw/deps/wayland" }); - const protocolDir = b.pathJoin(&.{ waylandDir, protocol }); - const clientHeader = basename ++ ".h"; - const privateCode = basename ++ "-code.h"; - - const client_step = b.addSystemCommand(&.{ "wayland-scanner", "client-header" }); - client_step.addFileArg(b.path(protocolDir)); - raylib.addIncludePath(client_step.addOutputFileArg(clientHeader).dirname()); - - const private_step = b.addSystemCommand(&.{ "wayland-scanner", "private-code" }); - private_step.addFileArg(b.path(protocolDir)); - raylib.addIncludePath(private_step.addOutputFileArg(privateCode).dirname()); - - raylib.step.dependOn(&client_step.step); - raylib.step.dependOn(&private_step.step); -} From 72f8c354b0a7a701a17448aad8b216aacb682846 Mon Sep 17 00:00:00 2001 From: Jeffery Myers Date: Mon, 21 Oct 2024 07:17:50 -0700 Subject: [PATCH 145/208] [Raymath] Add C++ operator overloads for common math function (#4385) * Update raylib_api.* by CI * Add math operators for C++ to raymath * better #define for disabling C++ operators --------- Co-authored-by: github-actions[bot] --- src/raymath.h | 319 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 318 insertions(+), 1 deletion(-) diff --git a/src/raymath.h b/src/raymath.h index 62d52f8fd..84e1ff806 100644 --- a/src/raymath.h +++ b/src/raymath.h @@ -26,7 +26,9 @@ * #define RAYMATH_STATIC_INLINE * Define static inline functions code, so #include header suffices for use. * This may use up lots of memory. -* +* +* #define RAYMATH_DISABLE_OPERATORS +* Disables C++ operator overloads for raymath types. * * LICENSE: zlib/libpng * @@ -2580,4 +2582,319 @@ RMAPI void MatrixDecompose(Matrix mat, Vector3 *translation, Quaternion *rotatio } } + +// optional C++ math operators +// define RAYLIB_DISABLE_VECTOR_OPERATORS to disable +#if defined(__cplusplus) && !defined(RAYMATH_DISABLE_OPERATORS) + +//------------------Vector2-----------------// +static constexpr Vector2 Vector2Zeros = { 0, 0 }; +static constexpr Vector2 Vector2Ones = { 1, 1 }; +static constexpr Vector2 Vector2UnitX = { 1, 0 }; +static constexpr Vector2 Vector2UnitY = { 0, 1 }; + +inline Vector2 operator + (const Vector2& lhs, const Vector2& rhs) +{ + return Vector2Add(lhs, rhs); +} + +inline const Vector2& operator += (Vector2& lhs, const Vector2& rhs) +{ + lhs = Vector2Add(lhs, rhs); + return lhs; +} + +inline Vector2 operator - (const Vector2& lhs, const Vector2& rhs) +{ + return Vector2Subtract(lhs, rhs); +} + +inline const Vector2& operator -= (Vector2& lhs, const Vector2& rhs) +{ + lhs = Vector2Subtract(lhs, rhs); + return lhs; +} + +inline Vector2 operator * (const Vector2& lhs, const float& rhs) +{ + return Vector2Scale(lhs, rhs); +} + +inline const Vector2& operator *= (Vector2& lhs, const float& rhs) +{ + lhs = Vector2Scale(lhs, rhs); + return lhs; +} + +inline Vector2 operator * (const Vector2& lhs, const Vector2& rhs) +{ + return Vector2Multiply(lhs, rhs); +} + +inline const Vector2& operator *= (Vector2& lhs, const Vector2& rhs) +{ + lhs = Vector2Multiply(lhs, rhs); + return lhs; +} + +inline Vector2 operator * (const Vector2& lhs, const Matrix& rhs) +{ + return Vector2Transform(lhs, rhs); +} + +inline const Vector2& operator -= (Vector2& lhs, const Matrix& rhs) +{ + lhs = Vector2Transform(lhs, rhs); + return lhs; +} + +inline Vector2 operator / (const Vector2& lhs, const float& rhs) +{ + return Vector2Scale(lhs, 1.0f / rhs); +} + +inline const Vector2& operator /= (Vector2& lhs, const float& rhs) +{ + lhs = Vector2Scale(lhs, rhs); + return lhs; +} + +inline Vector2 operator / (const Vector2& lhs, const Vector2& rhs) +{ + return Vector2Divide(lhs, rhs); +} + +inline const Vector2& operator /= (Vector2& lhs, const Vector2& rhs) +{ + lhs = Vector2Divide(lhs, rhs); + return lhs; +} + +inline bool operator == (const Vector2& lhs, const Vector2& rhs) +{ + return FloatEquals(lhs.x, rhs.x) && FloatEquals(lhs.y, rhs.y); +} + +inline bool operator != (const Vector2& lhs, const Vector2& rhs) +{ + return !FloatEquals(lhs.x, rhs.x) || !FloatEquals(lhs.y, rhs.y); +} + +//------------------Vector3-----------------// +static constexpr Vector3 Vector3Zeros = { 0, 0, 0 }; +static constexpr Vector3 Vector3Ones = { 1, 1, 1 }; +static constexpr Vector3 Vector3UnitX = { 1, 0, 0 }; +static constexpr Vector3 Vector3UnitY = { 0, 1, 0 }; +static constexpr Vector3 Vector3UnitZ = { 0, 0, 1 }; + +inline Vector3 operator + (const Vector3& lhs, const Vector3& rhs) +{ + return Vector3Add(lhs, rhs); +} + +inline const Vector3& operator += (Vector3& lhs, const Vector3& rhs) +{ + lhs = Vector3Add(lhs, rhs); + return lhs; +} + +inline Vector3 operator - (const Vector3& lhs, const Vector3& rhs) +{ + return Vector3Subtract(lhs, rhs); +} + +inline const Vector3& operator -= (Vector3& lhs, const Vector3& rhs) +{ + lhs = Vector3Subtract(lhs, rhs); + return lhs; +} + +inline Vector3 operator * (const Vector3& lhs, const float& rhs) +{ + return Vector3Scale(lhs, rhs); +} + +inline const Vector3& operator *= (Vector3& lhs, const float& rhs) +{ + lhs = Vector3Scale(lhs, rhs); + return lhs; +} + +inline Vector3 operator * (const Vector3& lhs, const Vector3& rhs) +{ + return Vector3Multiply(lhs, rhs); +} + +inline const Vector3& operator *= (Vector3& lhs, const Vector3& rhs) +{ + lhs = Vector3Multiply(lhs, rhs); + return lhs; +} + +inline Vector3 operator * (const Vector3& lhs, const Matrix& rhs) +{ + return Vector3Transform(lhs, rhs); +} + +inline const Vector3& operator -= (Vector3& lhs, const Matrix& rhs) +{ + lhs = Vector3Transform(lhs, rhs); + return lhs; +} + +inline Vector3 operator / (const Vector3& lhs, const float& rhs) +{ + return Vector3Scale(lhs, 1.0f / rhs); +} + +inline const Vector3& operator /= (Vector3& lhs, const float& rhs) +{ + lhs = Vector3Scale(lhs, rhs); + return lhs; +} + +inline Vector3 operator / (const Vector3& lhs, const Vector3& rhs) +{ + return Vector3Divide(lhs, rhs); +} + +inline const Vector3& operator /= (Vector3& lhs, const Vector3& rhs) +{ + lhs = Vector3Divide(lhs, rhs); + return lhs; +} + +inline bool operator == (const Vector3& lhs, const Vector3& rhs) +{ + return FloatEquals(lhs.x, rhs.x) && FloatEquals(lhs.y, rhs.y) && FloatEquals(lhs.z, rhs.z); +} + +inline bool operator != (const Vector3& lhs, const Vector3& rhs) +{ + return !FloatEquals(lhs.x, rhs.x) || !FloatEquals(lhs.y, rhs.y) || !FloatEquals(lhs.z, rhs.z); +} + +//------------------Vector4-----------------// +static constexpr Vector4 Vector4Zeros = { 0, 0, 0, 0 }; +static constexpr Vector4 Vector4Ones = { 1, 1, 1, 1 }; +static constexpr Vector4 Vector4UnitX = { 1, 0, 0, 0 }; +static constexpr Vector4 Vector4UnitY = { 0, 1, 0, 0 }; +static constexpr Vector4 Vector4UnitZ = { 0, 0, 1, 0 }; +static constexpr Vector4 Vector4UnitW = { 0, 0, 0, 1 }; + +inline Vector4 operator + (const Vector4& lhs, const Vector4& rhs) +{ + return Vector4Add(lhs, rhs); +} + +inline const Vector4& operator += (Vector4& lhs, const Vector4& rhs) +{ + lhs = Vector4Add(lhs, rhs); + return lhs; +} + +inline Vector4 operator - (const Vector4& lhs, const Vector4& rhs) +{ + return Vector4Subtract(lhs, rhs); +} + +inline const Vector4& operator -= (Vector4& lhs, const Vector4& rhs) +{ + lhs = Vector4Subtract(lhs, rhs); + return lhs; +} + +inline Vector4 operator * (const Vector4& lhs, const float& rhs) +{ + return Vector4Scale(lhs, rhs); +} + +inline const Vector4& operator *= (Vector4& lhs, const float& rhs) +{ + lhs = Vector4Scale(lhs, rhs); + return lhs; +} + +inline Vector4 operator * (const Vector4& lhs, const Vector4& rhs) +{ + return Vector4Multiply(lhs, rhs); +} + +inline const Vector4& operator *= (Vector4& lhs, const Vector4& rhs) +{ + lhs = Vector4Multiply(lhs, rhs); + return lhs; +} + +inline Vector4 operator / (const Vector4& lhs, const float& rhs) +{ + return Vector4Scale(lhs, 1.0f / rhs); +} + +inline const Vector4& operator /= (Vector4& lhs, const float& rhs) +{ + lhs = Vector4Scale(lhs, rhs); + return lhs; +} + +inline Vector4 operator / (const Vector4& lhs, const Vector4& rhs) +{ + return Vector4Divide(lhs, rhs); +} + +inline const Vector4& operator /= (Vector4& lhs, const Vector4& rhs) +{ + lhs = Vector4Divide(lhs, rhs); + return lhs; +} + +inline bool operator == (const Vector4& lhs, const Vector4& rhs) +{ + return FloatEquals(lhs.x, rhs.x) && FloatEquals(lhs.y, rhs.y) && FloatEquals(lhs.z, rhs.z) && FloatEquals(lhs.w, rhs.w); +} + +inline bool operator != (const Vector4& lhs, const Vector4& rhs) +{ + return !FloatEquals(lhs.x, rhs.x) || !FloatEquals(lhs.y, rhs.y) || !FloatEquals(lhs.z, rhs.z) || !FloatEquals(lhs.w, rhs.w); +} + +//------------------Quaternion-----------------// +static constexpr Quaternion QuaternionZeros = { 0, 0, 0, 0 }; +static constexpr Quaternion QuaternionOnes = { 1, 1, 1, 1 }; +static constexpr Quaternion QuaternionUnitX = { 0, 0, 0, 1 }; + +inline Quaternion operator + (const Quaternion& lhs, const float& rhs) +{ + return QuaternionAddValue(lhs, rhs); +} + +inline const Quaternion& operator += (Quaternion& lhs, const float& rhs) +{ + lhs = QuaternionAddValue(lhs, rhs); + return lhs; +} + +inline Quaternion operator - (const Quaternion& lhs, const float& rhs) +{ + return QuaternionSubtractValue(lhs, rhs); +} + +inline const Quaternion& operator -= (Quaternion& lhs, const float& rhs) +{ + lhs = QuaternionSubtractValue(lhs, rhs); + return lhs; +} + +inline Quaternion operator * (const Quaternion& lhs, const Matrix& rhs) +{ + return QuaternionTransform(lhs, rhs); +} + +inline const Quaternion& operator *= (Quaternion& lhs, const Matrix& rhs) +{ + lhs = QuaternionTransform(lhs, rhs); + return lhs; +} +#endif // C++ operators + #endif // RAYMATH_H From 760146821144cd2c5f4828431aee15cc8c9903f9 Mon Sep 17 00:00:00 2001 From: Ray Date: Mon, 21 Oct 2024 16:25:45 +0200 Subject: [PATCH 146/208] REVIEWED: Formatting and raymath version #4385 --- src/raymath.h | 174 +++++++++++++++++++++++++------------------------- 1 file changed, 88 insertions(+), 86 deletions(-) diff --git a/src/raymath.h b/src/raymath.h index 84e1ff806..835ce8126 100644 --- a/src/raymath.h +++ b/src/raymath.h @@ -1,6 +1,6 @@ /********************************************************************************************** * -* raymath v1.5 - Math functions to work with Vector2, Vector3, Matrix and Quaternions +* raymath v2.0 - Math functions to work with Vector2, Vector3, Matrix and Quaternions * * CONVENTIONS: * - Matrix structure is defined as row-major (memory layout) but parameters naming AND all @@ -12,7 +12,7 @@ * - Functions are always self-contained, no function use another raymath function inside, * required code is directly re-implemented inside * - Functions input parameters are always received by value (2 unavoidable exceptions) -* - Functions use always a "result" variable for return +* - Functions use always a "result" variable for return (except C++ operators) * - Functions are always defined inline * - Angles are always in radians (DEG2RAD/RAD2DEG macros provided for convenience) * - No compound literals used to make sure libray is compatible with C++ @@ -27,7 +27,7 @@ * Define static inline functions code, so #include header suffices for use. * This may use up lots of memory. * -* #define RAYMATH_DISABLE_OPERATORS +* #define RAYMATH_DISABLE_CPP_OPERATORS * Disables C++ operator overloads for raymath types. * * LICENSE: zlib/libpng @@ -2582,12 +2582,12 @@ RMAPI void MatrixDecompose(Matrix mat, Vector3 *translation, Quaternion *rotatio } } +#if defined(__cplusplus) && !defined(RAYMATH_DISABLE_CPP_OPERATORS) -// optional C++ math operators -// define RAYLIB_DISABLE_VECTOR_OPERATORS to disable -#if defined(__cplusplus) && !defined(RAYMATH_DISABLE_OPERATORS) +// Optional C++ math operators +//------------------------------------------------------------------------------- -//------------------Vector2-----------------// +// Vector2 operators static constexpr Vector2 Vector2Zeros = { 0, 0 }; static constexpr Vector2 Vector2Ones = { 1, 1 }; static constexpr Vector2 Vector2UnitX = { 1, 0 }; @@ -2595,92 +2595,92 @@ static constexpr Vector2 Vector2UnitY = { 0, 1 }; inline Vector2 operator + (const Vector2& lhs, const Vector2& rhs) { - return Vector2Add(lhs, rhs); + return Vector2Add(lhs, rhs); } inline const Vector2& operator += (Vector2& lhs, const Vector2& rhs) { - lhs = Vector2Add(lhs, rhs); - return lhs; + lhs = Vector2Add(lhs, rhs); + return lhs; } inline Vector2 operator - (const Vector2& lhs, const Vector2& rhs) { - return Vector2Subtract(lhs, rhs); + return Vector2Subtract(lhs, rhs); } inline const Vector2& operator -= (Vector2& lhs, const Vector2& rhs) { - lhs = Vector2Subtract(lhs, rhs); - return lhs; + lhs = Vector2Subtract(lhs, rhs); + return lhs; } inline Vector2 operator * (const Vector2& lhs, const float& rhs) { - return Vector2Scale(lhs, rhs); + return Vector2Scale(lhs, rhs); } inline const Vector2& operator *= (Vector2& lhs, const float& rhs) { - lhs = Vector2Scale(lhs, rhs); - return lhs; + lhs = Vector2Scale(lhs, rhs); + return lhs; } inline Vector2 operator * (const Vector2& lhs, const Vector2& rhs) { - return Vector2Multiply(lhs, rhs); + return Vector2Multiply(lhs, rhs); } inline const Vector2& operator *= (Vector2& lhs, const Vector2& rhs) { - lhs = Vector2Multiply(lhs, rhs); - return lhs; + lhs = Vector2Multiply(lhs, rhs); + return lhs; } inline Vector2 operator * (const Vector2& lhs, const Matrix& rhs) { - return Vector2Transform(lhs, rhs); + return Vector2Transform(lhs, rhs); } inline const Vector2& operator -= (Vector2& lhs, const Matrix& rhs) { - lhs = Vector2Transform(lhs, rhs); - return lhs; + lhs = Vector2Transform(lhs, rhs); + return lhs; } inline Vector2 operator / (const Vector2& lhs, const float& rhs) { - return Vector2Scale(lhs, 1.0f / rhs); + return Vector2Scale(lhs, 1.0f / rhs); } inline const Vector2& operator /= (Vector2& lhs, const float& rhs) { - lhs = Vector2Scale(lhs, rhs); - return lhs; + lhs = Vector2Scale(lhs, rhs); + return lhs; } inline Vector2 operator / (const Vector2& lhs, const Vector2& rhs) { - return Vector2Divide(lhs, rhs); + return Vector2Divide(lhs, rhs); } inline const Vector2& operator /= (Vector2& lhs, const Vector2& rhs) { - lhs = Vector2Divide(lhs, rhs); - return lhs; + lhs = Vector2Divide(lhs, rhs); + return lhs; } inline bool operator == (const Vector2& lhs, const Vector2& rhs) { - return FloatEquals(lhs.x, rhs.x) && FloatEquals(lhs.y, rhs.y); + return FloatEquals(lhs.x, rhs.x) && FloatEquals(lhs.y, rhs.y); } inline bool operator != (const Vector2& lhs, const Vector2& rhs) { - return !FloatEquals(lhs.x, rhs.x) || !FloatEquals(lhs.y, rhs.y); + return !FloatEquals(lhs.x, rhs.x) || !FloatEquals(lhs.y, rhs.y); } -//------------------Vector3-----------------// +// Vector3 operators static constexpr Vector3 Vector3Zeros = { 0, 0, 0 }; static constexpr Vector3 Vector3Ones = { 1, 1, 1 }; static constexpr Vector3 Vector3UnitX = { 1, 0, 0 }; @@ -2689,92 +2689,92 @@ static constexpr Vector3 Vector3UnitZ = { 0, 0, 1 }; inline Vector3 operator + (const Vector3& lhs, const Vector3& rhs) { - return Vector3Add(lhs, rhs); + return Vector3Add(lhs, rhs); } inline const Vector3& operator += (Vector3& lhs, const Vector3& rhs) { - lhs = Vector3Add(lhs, rhs); - return lhs; + lhs = Vector3Add(lhs, rhs); + return lhs; } inline Vector3 operator - (const Vector3& lhs, const Vector3& rhs) { - return Vector3Subtract(lhs, rhs); + return Vector3Subtract(lhs, rhs); } inline const Vector3& operator -= (Vector3& lhs, const Vector3& rhs) { - lhs = Vector3Subtract(lhs, rhs); - return lhs; + lhs = Vector3Subtract(lhs, rhs); + return lhs; } inline Vector3 operator * (const Vector3& lhs, const float& rhs) { - return Vector3Scale(lhs, rhs); + return Vector3Scale(lhs, rhs); } inline const Vector3& operator *= (Vector3& lhs, const float& rhs) { - lhs = Vector3Scale(lhs, rhs); - return lhs; + lhs = Vector3Scale(lhs, rhs); + return lhs; } inline Vector3 operator * (const Vector3& lhs, const Vector3& rhs) { - return Vector3Multiply(lhs, rhs); + return Vector3Multiply(lhs, rhs); } inline const Vector3& operator *= (Vector3& lhs, const Vector3& rhs) { - lhs = Vector3Multiply(lhs, rhs); - return lhs; + lhs = Vector3Multiply(lhs, rhs); + return lhs; } inline Vector3 operator * (const Vector3& lhs, const Matrix& rhs) { - return Vector3Transform(lhs, rhs); + return Vector3Transform(lhs, rhs); } inline const Vector3& operator -= (Vector3& lhs, const Matrix& rhs) { - lhs = Vector3Transform(lhs, rhs); - return lhs; + lhs = Vector3Transform(lhs, rhs); + return lhs; } inline Vector3 operator / (const Vector3& lhs, const float& rhs) { - return Vector3Scale(lhs, 1.0f / rhs); + return Vector3Scale(lhs, 1.0f / rhs); } inline const Vector3& operator /= (Vector3& lhs, const float& rhs) { - lhs = Vector3Scale(lhs, rhs); - return lhs; + lhs = Vector3Scale(lhs, rhs); + return lhs; } inline Vector3 operator / (const Vector3& lhs, const Vector3& rhs) { - return Vector3Divide(lhs, rhs); + return Vector3Divide(lhs, rhs); } inline const Vector3& operator /= (Vector3& lhs, const Vector3& rhs) { - lhs = Vector3Divide(lhs, rhs); - return lhs; + lhs = Vector3Divide(lhs, rhs); + return lhs; } inline bool operator == (const Vector3& lhs, const Vector3& rhs) { - return FloatEquals(lhs.x, rhs.x) && FloatEquals(lhs.y, rhs.y) && FloatEquals(lhs.z, rhs.z); + return FloatEquals(lhs.x, rhs.x) && FloatEquals(lhs.y, rhs.y) && FloatEquals(lhs.z, rhs.z); } inline bool operator != (const Vector3& lhs, const Vector3& rhs) { - return !FloatEquals(lhs.x, rhs.x) || !FloatEquals(lhs.y, rhs.y) || !FloatEquals(lhs.z, rhs.z); + return !FloatEquals(lhs.x, rhs.x) || !FloatEquals(lhs.y, rhs.y) || !FloatEquals(lhs.z, rhs.z); } -//------------------Vector4-----------------// +// Vector4 operators static constexpr Vector4 Vector4Zeros = { 0, 0, 0, 0 }; static constexpr Vector4 Vector4Ones = { 1, 1, 1, 1 }; static constexpr Vector4 Vector4UnitX = { 1, 0, 0, 0 }; @@ -2784,117 +2784,119 @@ static constexpr Vector4 Vector4UnitW = { 0, 0, 0, 1 }; inline Vector4 operator + (const Vector4& lhs, const Vector4& rhs) { - return Vector4Add(lhs, rhs); + return Vector4Add(lhs, rhs); } inline const Vector4& operator += (Vector4& lhs, const Vector4& rhs) { - lhs = Vector4Add(lhs, rhs); - return lhs; + lhs = Vector4Add(lhs, rhs); + return lhs; } inline Vector4 operator - (const Vector4& lhs, const Vector4& rhs) { - return Vector4Subtract(lhs, rhs); + return Vector4Subtract(lhs, rhs); } inline const Vector4& operator -= (Vector4& lhs, const Vector4& rhs) { - lhs = Vector4Subtract(lhs, rhs); - return lhs; + lhs = Vector4Subtract(lhs, rhs); + return lhs; } inline Vector4 operator * (const Vector4& lhs, const float& rhs) { - return Vector4Scale(lhs, rhs); + return Vector4Scale(lhs, rhs); } inline const Vector4& operator *= (Vector4& lhs, const float& rhs) { - lhs = Vector4Scale(lhs, rhs); - return lhs; + lhs = Vector4Scale(lhs, rhs); + return lhs; } inline Vector4 operator * (const Vector4& lhs, const Vector4& rhs) { - return Vector4Multiply(lhs, rhs); + return Vector4Multiply(lhs, rhs); } inline const Vector4& operator *= (Vector4& lhs, const Vector4& rhs) { - lhs = Vector4Multiply(lhs, rhs); - return lhs; + lhs = Vector4Multiply(lhs, rhs); + return lhs; } inline Vector4 operator / (const Vector4& lhs, const float& rhs) { - return Vector4Scale(lhs, 1.0f / rhs); + return Vector4Scale(lhs, 1.0f / rhs); } inline const Vector4& operator /= (Vector4& lhs, const float& rhs) { - lhs = Vector4Scale(lhs, rhs); - return lhs; + lhs = Vector4Scale(lhs, rhs); + return lhs; } inline Vector4 operator / (const Vector4& lhs, const Vector4& rhs) { - return Vector4Divide(lhs, rhs); + return Vector4Divide(lhs, rhs); } inline const Vector4& operator /= (Vector4& lhs, const Vector4& rhs) { - lhs = Vector4Divide(lhs, rhs); - return lhs; + lhs = Vector4Divide(lhs, rhs); + return lhs; } inline bool operator == (const Vector4& lhs, const Vector4& rhs) { - return FloatEquals(lhs.x, rhs.x) && FloatEquals(lhs.y, rhs.y) && FloatEquals(lhs.z, rhs.z) && FloatEquals(lhs.w, rhs.w); + return FloatEquals(lhs.x, rhs.x) && FloatEquals(lhs.y, rhs.y) && FloatEquals(lhs.z, rhs.z) && FloatEquals(lhs.w, rhs.w); } inline bool operator != (const Vector4& lhs, const Vector4& rhs) { - return !FloatEquals(lhs.x, rhs.x) || !FloatEquals(lhs.y, rhs.y) || !FloatEquals(lhs.z, rhs.z) || !FloatEquals(lhs.w, rhs.w); + return !FloatEquals(lhs.x, rhs.x) || !FloatEquals(lhs.y, rhs.y) || !FloatEquals(lhs.z, rhs.z) || !FloatEquals(lhs.w, rhs.w); } -//------------------Quaternion-----------------// +// Quaternion operators static constexpr Quaternion QuaternionZeros = { 0, 0, 0, 0 }; static constexpr Quaternion QuaternionOnes = { 1, 1, 1, 1 }; static constexpr Quaternion QuaternionUnitX = { 0, 0, 0, 1 }; inline Quaternion operator + (const Quaternion& lhs, const float& rhs) { - return QuaternionAddValue(lhs, rhs); + return QuaternionAddValue(lhs, rhs); } inline const Quaternion& operator += (Quaternion& lhs, const float& rhs) { - lhs = QuaternionAddValue(lhs, rhs); - return lhs; + lhs = QuaternionAddValue(lhs, rhs); + return lhs; } inline Quaternion operator - (const Quaternion& lhs, const float& rhs) { - return QuaternionSubtractValue(lhs, rhs); + return QuaternionSubtractValue(lhs, rhs); } inline const Quaternion& operator -= (Quaternion& lhs, const float& rhs) { - lhs = QuaternionSubtractValue(lhs, rhs); - return lhs; + lhs = QuaternionSubtractValue(lhs, rhs); + return lhs; } inline Quaternion operator * (const Quaternion& lhs, const Matrix& rhs) { - return QuaternionTransform(lhs, rhs); + return QuaternionTransform(lhs, rhs); } inline const Quaternion& operator *= (Quaternion& lhs, const Matrix& rhs) { - lhs = QuaternionTransform(lhs, rhs); - return lhs; + lhs = QuaternionTransform(lhs, rhs); + return lhs; } -#endif // C++ operators +//------------------------------------------------------------------------------- +#endif // C++ operators + #endif // RAYMATH_H From f402147a6388608853e9b5ca7b509e4723d455b1 Mon Sep 17 00:00:00 2001 From: Rapha <134700614+rapha-s@users.noreply.github.com> Date: Mon, 21 Oct 2024 11:56:19 -0300 Subject: [PATCH 147/208] Updated instanced rendering support loading (#4408) --- src/rlgl.h | 42 +++++++++++++++++++++++++++--------------- 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/src/rlgl.h b/src/rlgl.h index e4e659ac9..3d211d8c8 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -2472,25 +2472,37 @@ void rlLoadExtensions(void *loader) } // Check instanced rendering support - if (strcmp(extList[i], (const char *)"GL_ANGLE_instanced_arrays") == 0) // Web ANGLE - { - glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawArraysInstancedANGLE"); - glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawElementsInstancedANGLE"); - glVertexAttribDivisor = (PFNGLVERTEXATTRIBDIVISOREXTPROC)((rlglLoadProc)loader)("glVertexAttribDivisorANGLE"); - - if ((glDrawArraysInstanced != NULL) && (glDrawElementsInstanced != NULL) && (glVertexAttribDivisor != NULL)) RLGL.ExtSupported.instancing = true; - } - else - { - if ((strcmp(extList[i], (const char *)"GL_EXT_draw_instanced") == 0) && // Standard EXT - (strcmp(extList[i], (const char *)"GL_EXT_instanced_arrays") == 0)) - { + if (strstr(extList[i], (const char*)"instanced_arrays") != NULL) { //Broad check for instanced_arrays + //Specific check + if (strcmp(extList[i], (const char*)"GL_ANGLE_instanced_arrays") == 0) { //ANGLE + glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawArraysInstancedANGLE"); + glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawElementsInstancedANGLE"); + glVertexAttribDivisor = (PFNGLVERTEXATTRIBDIVISOREXTPROC)((rlglLoadProc)loader)("glVertexAttribDivisorANGLE"); + } + else if (strcmp(extList[i], (const char*)"GL_EXT_instanced_arrays") == 0) { //EXT glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawArraysInstancedEXT"); glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawElementsInstancedEXT"); glVertexAttribDivisor = (PFNGLVERTEXATTRIBDIVISOREXTPROC)((rlglLoadProc)loader)("glVertexAttribDivisorEXT"); - - if ((glDrawArraysInstanced != NULL) && (glDrawElementsInstanced != NULL) && (glVertexAttribDivisor != NULL)) RLGL.ExtSupported.instancing = true; + } else if (strcmp(extList[i], (const char*)"GL_NV_instanced_arrays") == 0) { //NVIDIA GLES + glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawArraysInstancedNV"); + glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawElementsInstancedNV"); + glVertexAttribDivisor = (PFNGLVERTEXATTRIBDIVISOREXTPROC)((rlglLoadProc)loader)("glVertexAttribDivisorNV"); } + //The feature will only be marked as supported if the elements from GL_XXX_instanced_arrays are present + if ((glDrawArraysInstanced != NULL) && (glDrawElementsInstanced != NULL) && (glVertexAttribDivisor != NULL)) RLGL.ExtSupported.instancing = true; + } else if (strstr(extList[i], (const char*)"draw_instanced") != NULL) { + + //GL_ANGLE_draw_instanced doesn't exist + if (strcmp(extList[i], (const char*)"GL_EXT_draw_instanced") == 0) { + glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawArraysInstancedEXT"); + glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawElementsInstancedEXT"); + } else if (strcmp(extList[i], (const char*)"GL_NV_draw_instanced") == 0) { + glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawArraysInstancedNV"); + glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawElementsInstancedNV"); + } + + //But the functions will at least be loaded if only GL_XX_EXT_draw_instanced exist + if ((glDrawArraysInstanced != NULL) && (glDrawElementsInstanced != NULL) && (glVertexAttribDivisor != NULL)) RLGL.ExtSupported.instancing = true; } // Check NPOT textures support From c935ca3168795415972fb30ef60765746867b3e7 Mon Sep 17 00:00:00 2001 From: Ray Date: Mon, 21 Oct 2024 16:59:55 +0200 Subject: [PATCH 148/208] Reviewed formatting #4408 --- src/rlgl.h | 40 +++++++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/src/rlgl.h b/src/rlgl.h index 3d211d8c8..e0c667303 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -2472,37 +2472,47 @@ void rlLoadExtensions(void *loader) } // Check instanced rendering support - if (strstr(extList[i], (const char*)"instanced_arrays") != NULL) { //Broad check for instanced_arrays - //Specific check - if (strcmp(extList[i], (const char*)"GL_ANGLE_instanced_arrays") == 0) { //ANGLE + if (strstr(extList[i], (const char*)"instanced_arrays") != NULL) // Broad check for instanced_arrays + { + // Specific check + if (strcmp(extList[i], (const char *)"GL_ANGLE_instanced_arrays") == 0) // ANGLE + { glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawArraysInstancedANGLE"); glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawElementsInstancedANGLE"); glVertexAttribDivisor = (PFNGLVERTEXATTRIBDIVISOREXTPROC)((rlglLoadProc)loader)("glVertexAttribDivisorANGLE"); } - else if (strcmp(extList[i], (const char*)"GL_EXT_instanced_arrays") == 0) { //EXT + else if (strcmp(extList[i], (const char *)"GL_EXT_instanced_arrays") == 0) // EXT + { glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawArraysInstancedEXT"); glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawElementsInstancedEXT"); glVertexAttribDivisor = (PFNGLVERTEXATTRIBDIVISOREXTPROC)((rlglLoadProc)loader)("glVertexAttribDivisorEXT"); - } else if (strcmp(extList[i], (const char*)"GL_NV_instanced_arrays") == 0) { //NVIDIA GLES + } + else if (strcmp(extList[i], (const char *)"GL_NV_instanced_arrays") == 0) // NVIDIA GLES + { glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawArraysInstancedNV"); - glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawElementsInstancedNV"); - glVertexAttribDivisor = (PFNGLVERTEXATTRIBDIVISOREXTPROC)((rlglLoadProc)loader)("glVertexAttribDivisorNV"); + glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawElementsInstancedNV"); + glVertexAttribDivisor = (PFNGLVERTEXATTRIBDIVISOREXTPROC)((rlglLoadProc)loader)("glVertexAttribDivisorNV"); } - //The feature will only be marked as supported if the elements from GL_XXX_instanced_arrays are present + + // The feature will only be marked as supported if the elements from GL_XXX_instanced_arrays are present if ((glDrawArraysInstanced != NULL) && (glDrawElementsInstanced != NULL) && (glVertexAttribDivisor != NULL)) RLGL.ExtSupported.instancing = true; - } else if (strstr(extList[i], (const char*)"draw_instanced") != NULL) { - - //GL_ANGLE_draw_instanced doesn't exist - if (strcmp(extList[i], (const char*)"GL_EXT_draw_instanced") == 0) { + } + else if (strstr(extList[i], (const char *)"draw_instanced") != NULL) + { + // GL_ANGLE_draw_instanced doesn't exist + if (strcmp(extList[i], (const char *)"GL_EXT_draw_instanced") == 0) + { glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawArraysInstancedEXT"); glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawElementsInstancedEXT"); - } else if (strcmp(extList[i], (const char*)"GL_NV_draw_instanced") == 0) { + } + else if (strcmp(extList[i], (const char*)"GL_NV_draw_instanced") == 0) + { glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawArraysInstancedNV"); glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawElementsInstancedNV"); } - //But the functions will at least be loaded if only GL_XX_EXT_draw_instanced exist - if ((glDrawArraysInstanced != NULL) && (glDrawElementsInstanced != NULL) && (glVertexAttribDivisor != NULL)) RLGL.ExtSupported.instancing = true; + // But the functions will at least be loaded if only GL_XX_EXT_draw_instanced exist + if ((glDrawArraysInstanced != NULL) && (glDrawElementsInstanced != NULL) && (glVertexAttribDivisor != NULL)) RLGL.ExtSupported.instancing = true; } // Check NPOT textures support From f141c75cde8da26515bef8c52ab635bc57e47d47 Mon Sep 17 00:00:00 2001 From: Ray Date: Mon, 21 Oct 2024 17:00:52 +0200 Subject: [PATCH 149/208] Removed trailing spaces --- src/platforms/rcore_desktop_glfw.c | 6 ++-- src/raymath.h | 2 +- src/rcore.c | 6 ++-- src/rlgl.h | 10 +++--- src/rmodels.c | 58 +++++++++++++++--------------- src/rtext.c | 2 +- src/rtextures.c | 10 +++--- 7 files changed, 47 insertions(+), 47 deletions(-) diff --git a/src/platforms/rcore_desktop_glfw.c b/src/platforms/rcore_desktop_glfw.c index d42274d14..0bc52ac9e 100644 --- a/src/platforms/rcore_desktop_glfw.c +++ b/src/platforms/rcore_desktop_glfw.c @@ -149,7 +149,7 @@ void ToggleFullscreen(void) { // Store previous window position (in case we exit fullscreen) CORE.Window.previousPosition = CORE.Window.position; - + int monitorCount = 0; int monitorIndex = GetCurrentMonitor(); GLFWmonitor **monitors = glfwGetMonitors(&monitorCount); @@ -1289,7 +1289,7 @@ int InitPlatform(void) // Disable GlFW auto iconify behaviour // Auto Iconify automatically minimizes (iconifies) the window if the window loses focus // additionally auto iconify restores the hardware resolution of the monitor if the window that loses focus is a fullscreen window - glfwWindowHint(GLFW_AUTO_ICONIFY, 0); + glfwWindowHint(GLFW_AUTO_ICONIFY, 0); // Check window creation flags if ((CORE.Window.flags & FLAG_FULLSCREEN_MODE) > 0) CORE.Window.fullscreen = true; @@ -1579,7 +1579,7 @@ int InitPlatform(void) int monitorWidth = 0; int monitorHeight = 0; glfwGetMonitorWorkarea(monitor, &monitorX, &monitorY, &monitorWidth, &monitorHeight); - + // Here CORE.Window.render.width/height should be used instead of CORE.Window.screen.width/height to center the window correctly when the high dpi flag is enabled. int posX = monitorX + (monitorWidth - (int)CORE.Window.render.width)/2; int posY = monitorY + (monitorHeight - (int)CORE.Window.render.height)/2; diff --git a/src/raymath.h b/src/raymath.h index 835ce8126..b1e0f1af0 100644 --- a/src/raymath.h +++ b/src/raymath.h @@ -26,7 +26,7 @@ * #define RAYMATH_STATIC_INLINE * Define static inline functions code, so #include header suffices for use. * This may use up lots of memory. -* +* * #define RAYMATH_DISABLE_CPP_OPERATORS * Disables C++ operator overloads for raymath types. * diff --git a/src/rcore.c b/src/rcore.c index 9b3eeee80..a1771d18e 100644 --- a/src/rcore.c +++ b/src/rcore.c @@ -691,7 +691,7 @@ void InitWindow(int width, int height, const char *title) // Initialize random seed SetRandomSeed((unsigned int)time(NULL)); - + TRACELOG(LOG_INFO, "SYSTEM: Working Directory: %s", GetWorkingDirectory()); } @@ -3716,14 +3716,14 @@ static void ScanDirectoryFilesRecursively(const char *basePath, FilePathList *fi break; } } - else + else { if ((filter != NULL) && (TextFindIndex(filter, DIRECTORY_FILTER_TAG) >= 0)) { strcpy(files->paths[files->count], path); files->count++; } - + if (files->count >= files->capacity) { TRACELOG(LOG_WARNING, "FILEIO: Maximum filepath scan capacity reached (%i files)", files->capacity); diff --git a/src/rlgl.h b/src/rlgl.h index e0c667303..6cfc2dcfb 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -2486,17 +2486,17 @@ void rlLoadExtensions(void *loader) glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawArraysInstancedEXT"); glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawElementsInstancedEXT"); glVertexAttribDivisor = (PFNGLVERTEXATTRIBDIVISOREXTPROC)((rlglLoadProc)loader)("glVertexAttribDivisorEXT"); - } + } else if (strcmp(extList[i], (const char *)"GL_NV_instanced_arrays") == 0) // NVIDIA GLES { glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawArraysInstancedNV"); glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawElementsInstancedNV"); glVertexAttribDivisor = (PFNGLVERTEXATTRIBDIVISOREXTPROC)((rlglLoadProc)loader)("glVertexAttribDivisorNV"); } - + // The feature will only be marked as supported if the elements from GL_XXX_instanced_arrays are present if ((glDrawArraysInstanced != NULL) && (glDrawElementsInstanced != NULL) && (glVertexAttribDivisor != NULL)) RLGL.ExtSupported.instancing = true; - } + } else if (strstr(extList[i], (const char *)"draw_instanced") != NULL) { // GL_ANGLE_draw_instanced doesn't exist @@ -2504,13 +2504,13 @@ void rlLoadExtensions(void *loader) { glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawArraysInstancedEXT"); glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawElementsInstancedEXT"); - } + } else if (strcmp(extList[i], (const char*)"GL_NV_draw_instanced") == 0) { glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawArraysInstancedNV"); glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawElementsInstancedNV"); } - + // But the functions will at least be loaded if only GL_XX_EXT_draw_instanced exist if ((glDrawArraysInstanced != NULL) && (glDrawElementsInstanced != NULL) && (glVertexAttribDivisor != NULL)) RLGL.ExtSupported.instancing = true; } diff --git a/src/rmodels.c b/src/rmodels.c index e7208e1aa..30130d9e0 100644 --- a/src/rmodels.c +++ b/src/rmodels.c @@ -426,14 +426,14 @@ void DrawSphereEx(Vector3 centerPos, float radius, int rings, int slices, Color { #if 0 // Basic implementation, do not use it! - // For a sphere with 16 rings and 16 slices it requires 8640 cos()/sin() function calls! + // For a sphere with 16 rings and 16 slices it requires 8640 cos()/sin() function calls! // New optimized version below only requires 4 cos()/sin() calls - + rlPushMatrix(); // NOTE: Transformation is applied in inverse order (scale -> translate) rlTranslatef(centerPos.x, centerPos.y, centerPos.z); rlScalef(radius, radius, radius); - + rlBegin(RL_TRIANGLES); rlColor4ub(color.r, color.g, color.b, color.a); @@ -488,7 +488,7 @@ void DrawSphereEx(Vector3 centerPos, float radius, int rings, int slices, Color for (int i = 0; i < rings + 1; i++) { - for (int j = 0; j < slices; j++) + for (int j = 0; j < slices; j++) { vertices[0] = vertices[2]; // Rotate around y axis to set up vertices for next face vertices[1] = vertices[3]; @@ -1165,7 +1165,7 @@ bool IsModelValid(Model model) (model.meshMaterial != NULL) && // Validate mesh-material linkage (model.meshCount > 0) && // Validate mesh count (model.materialCount > 0)) result = true; // Validate material count - + // NOTE: Many elements could be validated from a model, including every model mesh VAO/VBOs // but some VBOs could not be used, it depends on Mesh vertex data for (int i = 0; i < model.meshCount; i++) @@ -1179,7 +1179,7 @@ bool IsModelValid(Model model) if ((model.meshes[i].indices != NULL) && (model.meshes[i].vboId[6] == 0)) { result = false; break; } // Vertex indices buffer not uploaded to GPU if ((model.meshes[i].boneIds != NULL) && (model.meshes[i].vboId[7] == 0)) { result = false; break; } // Vertex boneIds buffer not uploaded to GPU if ((model.meshes[i].boneWeights != NULL) && (model.meshes[i].vboId[8] == 0)) { result = false; break; } // Vertex boneWeights buffer not uploaded to GPU - + // NOTE: Some OpenGL versions do not support VAO, so we don't check it //if (model.meshes[i].vaoId == 0) { result = false; break } } @@ -1375,7 +1375,7 @@ void UploadMesh(Mesh *mesh, bool dynamic) rlSetVertexAttributeDefault(RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS, value, SHADER_ATTRIB_VEC4, 4); rlDisableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS); } - + if (mesh->boneWeights != NULL) { // Enable vertex attribute: boneWeights (shader-location = 8) @@ -1507,7 +1507,7 @@ void DrawMesh(Mesh mesh, Material material, Matrix transform) if (material.shader.locs[SHADER_LOC_MATRIX_NORMAL] != -1) rlSetUniformMatrix(material.shader.locs[SHADER_LOC_MATRIX_NORMAL], MatrixTranspose(MatrixInvert(matModel))); #ifdef RL_SUPPORT_MESH_GPU_SKINNING - // Upload Bone Transforms + // Upload Bone Transforms if (material.shader.locs[SHADER_LOC_BONE_MATRICES] != -1 && mesh.boneMatrices) { rlSetUniformMatrices(material.shader.locs[SHADER_LOC_BONE_MATRICES], mesh.boneMatrices, mesh.boneCount); @@ -1600,7 +1600,7 @@ void DrawMesh(Mesh mesh, Material material, Matrix transform) rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_BONEIDS], 4, RL_UNSIGNED_BYTE, 0, 0, 0); rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_BONEIDS]); } - + // Bind mesh VBO data: vertex bone weights (shader-location = 7, if available) if (material.shader.locs[SHADER_LOC_VERTEX_BONEWEIGHTS] != -1) { @@ -1751,15 +1751,15 @@ void DrawMeshInstanced(Mesh mesh, Material material, const Matrix *transforms, i // Upload model normal matrix (if locations available) if (material.shader.locs[SHADER_LOC_MATRIX_NORMAL] != -1) rlSetUniformMatrix(material.shader.locs[SHADER_LOC_MATRIX_NORMAL], MatrixTranspose(MatrixInvert(matModel))); - + #ifdef RL_SUPPORT_MESH_GPU_SKINNING - // Upload Bone Transforms + // Upload Bone Transforms if (material.shader.locs[SHADER_LOC_BONE_MATRICES] != -1 && mesh.boneMatrices) { rlSetUniformMatrices(material.shader.locs[SHADER_LOC_BONE_MATRICES], mesh.boneMatrices, mesh.boneCount); } #endif - + //----------------------------------------------------- // Bind active texture maps (if available) @@ -1845,7 +1845,7 @@ void DrawMeshInstanced(Mesh mesh, Material material, const Matrix *transforms, i rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_BONEIDS], 4, RL_UNSIGNED_BYTE, 0, 0, 0); rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_BONEIDS]); } - + // Bind mesh VBO data: vertex bone weights (shader-location = 7, if available) if (material.shader.locs[SHADER_LOC_VERTEX_BONEWEIGHTS] != -1) { @@ -2205,7 +2205,7 @@ bool IsMaterialValid(Material material) if ((material.maps != NULL) && // Validate material contain some map (material.shader.id > 0)) result = true; // Validate material shader is valid - + // TODO: Check if available maps contain loaded textures return result; @@ -2368,20 +2368,20 @@ void UpdateModelAnimationBoneMatrices(Model model, ModelAnimation anim, int fram { if ((anim.frameCount > 0) && (anim.bones != NULL) && (anim.framePoses != NULL)) { - if (frame >= anim.frameCount) frame = frame%anim.frameCount; - + if (frame >= anim.frameCount) frame = frame%anim.frameCount; + for (int i = 0; i < model.meshCount; i++) { if (model.meshes[i].boneMatrices) { assert(model.meshes[i].boneCount == anim.boneCount); - + for (int boneId = 0; boneId < model.meshes[i].boneCount; boneId++) { Vector3 inTranslation = model.bindPose[boneId].translation; Quaternion inRotation = model.bindPose[boneId].rotation; Vector3 inScale = model.bindPose[boneId].scale; - + Vector3 outTranslation = anim.framePoses[frame][boneId].translation; Quaternion outRotation = anim.framePoses[frame][boneId].rotation; Vector3 outScale = anim.framePoses[frame][boneId].scale; @@ -2392,15 +2392,15 @@ void UpdateModelAnimationBoneMatrices(Model model, ModelAnimation anim, int fram Vector3 boneTranslation = Vector3Add( Vector3RotateByQuaternion(Vector3Multiply(outScale, invTranslation), - outRotation), outTranslation); + outRotation), outTranslation); Quaternion boneRotation = QuaternionMultiply(outRotation, invRotation); Vector3 boneScale = Vector3Multiply(outScale, invScale); - + Matrix boneMatrix = MatrixMultiply(MatrixMultiply( QuaternionToMatrix(boneRotation), MatrixTranslate(boneTranslation.x, boneTranslation.y, boneTranslation.z)), MatrixScale(boneScale.x, boneScale.y, boneScale.z)); - + model.meshes[i].boneMatrices[boneId] = boneMatrix; } } @@ -4824,12 +4824,12 @@ static Model LoadIQM(const char *fileName) } BuildPoseFromParentJoints(model.bones, model.boneCount, model.bindPose); - + for (int i = 0; i < model.meshCount; i++) { model.meshes[i].boneCount = model.boneCount; model.meshes[i].boneMatrices = RL_CALLOC(model.meshes[i].boneCount, sizeof(Matrix)); - + for (int j = 0; j < model.meshes[i].boneCount; j++) { model.meshes[i].boneMatrices[j] = MatrixIdentity(); @@ -5244,7 +5244,7 @@ static Model LoadGLTF(const char *fileName) ***********************************************************************************************/ // Macro to simplify attributes loading code - #define LOAD_ATTRIBUTE(accesor, numComp, srcType, dstPtr) LOAD_ATTRIBUTE_CAST(accesor, numComp, srcType, dstPtr, srcType) + #define LOAD_ATTRIBUTE(accesor, numComp, srcType, dstPtr) LOAD_ATTRIBUTE_CAST(accesor, numComp, srcType, dstPtr, srcType) #define LOAD_ATTRIBUTE_CAST(accesor, numComp, srcType, dstPtr, dstType) \ { \ @@ -5732,7 +5732,7 @@ static Model LoadGLTF(const char *fileName) TRACELOG(LOG_WARNING, "MODEL: [%s] Indices data converted from u32 to u16, possible loss of data", fileName); } - else + else { TRACELOG(LOG_WARNING, "MODEL: [%s] Indices data format not supported, use u16", fileName); } @@ -5920,11 +5920,11 @@ static Model LoadGLTF(const char *fileName) { memcpy(model.meshes[meshIndex].animNormals, model.meshes[meshIndex].normals, model.meshes[meshIndex].vertexCount*3*sizeof(float)); } - + // Bone Transform Matrices model.meshes[meshIndex].boneCount = model.boneCount; model.meshes[meshIndex].boneMatrices = RL_CALLOC(model.meshes[meshIndex].boneCount, sizeof(Matrix)); - + for (int j = 0; j < model.meshes[meshIndex].boneCount; j++) { model.meshes[meshIndex].boneMatrices[j] = MatrixIdentity(); @@ -6245,7 +6245,7 @@ static ModelAnimation *LoadModelAnimationsGLTF(const char *fileName, int *animCo RL_FREE(boneChannels); } } - + if (data->skins_count > 1) { TRACELOG(LOG_WARNING, "MODEL: [%s] expected exactly one skin to load animation data from, but found %i", fileName, data->skins_count); @@ -6701,7 +6701,7 @@ static Model LoadM3D(const char *fileName) { memcpy(model.meshes[i].animVertices, model.meshes[i].vertices, model.meshes[i].vertexCount*3*sizeof(float)); memcpy(model.meshes[i].animNormals, model.meshes[i].normals, model.meshes[i].vertexCount*3*sizeof(float)); - + model.meshes[i].boneCount = model.boneCount; model.meshes[i].boneMatrices = RL_CALLOC(model.meshes[i].boneCount, sizeof(Matrix)); for (j = 0; j < model.meshes[i].boneCount; j++) diff --git a/src/rtext.c b/src/rtext.c index 86aeb0047..3510671be 100644 --- a/src/rtext.c +++ b/src/rtext.c @@ -676,7 +676,7 @@ GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSiz { stbtt_GetCodepointHMetrics(&fontInfo, ch, &chars[i].advanceX, NULL); chars[i].advanceX = (int)((float)chars[i].advanceX*scaleFactor); - + if (chh > fontSize) TRACELOG(LOG_WARNING, "FONT: Character [0x%08x] size is bigger than expected font size", ch); // Load characters images diff --git a/src/rtextures.c b/src/rtextures.c index 9fc633274..a4534a7a2 100644 --- a/src/rtextures.c +++ b/src/rtextures.c @@ -1007,7 +1007,7 @@ Image GenImagePerlinNoise(int width, int height, int offsetX, int offsetY, float // Apply aspect ratio compensation to wider side if (width > height) nx *= aspectRatio; else ny /= aspectRatio; - + // Basic perlin noise implementation (not used) //float p = (stb_perlin_noise3(nx, ny, 0.0f, 0, 0, 0); @@ -4457,7 +4457,7 @@ void DrawTexturePro(Texture2D texture, Rectangle source, Rectangle dest, Vector2 if (source.width < 0) { flipX = true; source.width *= -1; } if (source.height < 0) source.y -= source.height; - + if (dest.width < 0) dest.width *= -1; if (dest.height < 0) dest.height *= -1; @@ -5079,10 +5079,10 @@ Color ColorAlphaBlend(Color dst, Color src, Color tint) } // Get color lerp interpolation between two colors, factor [0.0f..1.0f] -Color ColorLerp(Color color1, Color color2, float factor) -{ +Color ColorLerp(Color color1, Color color2, float factor) +{ Color color = { 0 }; - + if (factor < 0.0f) factor = 0.0f; else if (factor > 1.0f) factor = 1.0f; From f60c6d472c05212d02c715a77e068c75b0534233 Mon Sep 17 00:00:00 2001 From: Ray Date: Mon, 21 Oct 2024 17:26:42 +0200 Subject: [PATCH 150/208] Update raymath.h --- src/raymath.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/raymath.h b/src/raymath.h index b1e0f1af0..71b17cc2e 100644 --- a/src/raymath.h +++ b/src/raymath.h @@ -2898,5 +2898,4 @@ inline const Quaternion& operator *= (Quaternion& lhs, const Matrix& rhs) //------------------------------------------------------------------------------- #endif // C++ operators - #endif // RAYMATH_H From a2fcbc94fd38a2703a75fbb6310a3827f97c09d5 Mon Sep 17 00:00:00 2001 From: Jeffery Myers Date: Mon, 21 Oct 2024 09:38:42 -0700 Subject: [PATCH 151/208] [Raymath] Add matrix operators to raymath for C++ (#4409) * Add matrix operators to raymath for C++ * Fix spaces --- src/raymath.h | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/src/raymath.h b/src/raymath.h index 71b17cc2e..d1b5ab01e 100644 --- a/src/raymath.h +++ b/src/raymath.h @@ -2895,6 +2895,40 @@ inline const Quaternion& operator *= (Quaternion& lhs, const Matrix& rhs) lhs = QuaternionTransform(lhs, rhs); return lhs; } + +// Matrix operators +inline Matrix operator + (const Matrix& lhs, const Matrix& rhs) +{ + return MatrixAdd(lhs, rhs); +} + +inline const Matrix& operator += (Matrix& lhs, const Matrix& rhs) +{ + lhs = MatrixAdd(lhs, rhs); + return lhs; +} + +inline Matrix operator - (const Matrix& lhs, const Matrix& rhs) +{ + return MatrixSubtract(lhs, rhs); +} + +inline const Matrix& operator -= (Matrix& lhs, const Matrix& rhs) +{ + lhs = MatrixSubtract(lhs, rhs); + return lhs; +} + +inline Matrix operator * (const Matrix& lhs, const Matrix& rhs) +{ + return MatrixMultiply(lhs, rhs); +} + +inline const Matrix& operator *= (Matrix& lhs, const Matrix& rhs) +{ + lhs = MatrixMultiply(lhs, rhs); + return lhs; +} //------------------------------------------------------------------------------- #endif // C++ operators From f4cbc1fbaebfc92cf5a6786c8639d3788de12163 Mon Sep 17 00:00:00 2001 From: Ray Date: Mon, 21 Oct 2024 20:47:08 +0200 Subject: [PATCH 152/208] REVIEWED: `GetGestureHoldDuration()` comments --- src/raylib.h | 2 +- src/rgestures.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/raylib.h b/src/raylib.h index 5ae45fa9d..25ee6943f 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -1215,7 +1215,7 @@ RLAPI int GetTouchPointCount(void); // Get number of t RLAPI void SetGesturesEnabled(unsigned int flags); // Enable a set of gestures using flags RLAPI bool IsGestureDetected(unsigned int gesture); // Check if a gesture have been detected RLAPI int GetGestureDetected(void); // Get latest detected gesture -RLAPI float GetGestureHoldDuration(void); // Get gesture hold time in milliseconds +RLAPI float GetGestureHoldDuration(void); // Get gesture hold time in seconds RLAPI Vector2 GetGestureDragVector(void); // Get gesture drag vector RLAPI float GetGestureDragAngle(void); // Get gesture drag angle RLAPI Vector2 GetGesturePinchVector(void); // Get gesture pinch delta diff --git a/src/rgestures.h b/src/rgestures.h index 664a6e1cc..b5624be56 100644 --- a/src/rgestures.h +++ b/src/rgestures.h @@ -434,7 +434,7 @@ int GetGestureDetected(void) return (GESTURES.enabledFlags & GESTURES.current); } -// Hold time measured in ms +// Hold time measured in seconds float GetGestureHoldDuration(void) { // NOTE: time is calculated on current gesture HOLD @@ -517,7 +517,7 @@ static double rgGetCurrentTime(void) #if defined(_WIN32) unsigned long long int clockFrequency, currentTime; - QueryPerformanceFrequency(&clockFrequency); // BE CAREFUL: Costly operation! + QueryPerformanceFrequency(&clockFrequency); // BE CAREFUL: Costly operation! QueryPerformanceCounter(¤tTime); time = (double)currentTime/clockFrequency; // Time in seconds From ae150e9640bfa5696f63d7cbc76f8504a05bb341 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 21 Oct 2024 18:47:41 +0000 Subject: [PATCH 153/208] Update raylib_api.* by CI --- parser/output/raylib_api.json | 2 +- parser/output/raylib_api.lua | 2 +- parser/output/raylib_api.txt | 2 +- parser/output/raylib_api.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/parser/output/raylib_api.json b/parser/output/raylib_api.json index fca3ef72c..591fef737 100644 --- a/parser/output/raylib_api.json +++ b/parser/output/raylib_api.json @@ -5231,7 +5231,7 @@ }, { "name": "GetGestureHoldDuration", - "description": "Get gesture hold time in milliseconds", + "description": "Get gesture hold time in seconds", "returnType": "float" }, { diff --git a/parser/output/raylib_api.lua b/parser/output/raylib_api.lua index 572b4332a..b84e3c08c 100644 --- a/parser/output/raylib_api.lua +++ b/parser/output/raylib_api.lua @@ -4577,7 +4577,7 @@ return { }, { name = "GetGestureHoldDuration", - description = "Get gesture hold time in milliseconds", + description = "Get gesture hold time in seconds", returnType = "float" }, { diff --git a/parser/output/raylib_api.txt b/parser/output/raylib_api.txt index 1fd591151..e0d5f36b4 100644 --- a/parser/output/raylib_api.txt +++ b/parser/output/raylib_api.txt @@ -2065,7 +2065,7 @@ Function 200: GetGestureDetected() (0 input parameters) Function 201: GetGestureHoldDuration() (0 input parameters) Name: GetGestureHoldDuration Return type: float - Description: Get gesture hold time in milliseconds + Description: Get gesture hold time in seconds No input parameters Function 202: GetGestureDragVector() (0 input parameters) Name: GetGestureDragVector diff --git a/parser/output/raylib_api.xml b/parser/output/raylib_api.xml index 17d5a81e3..f59faf754 100644 --- a/parser/output/raylib_api.xml +++ b/parser/output/raylib_api.xml @@ -1281,7 +1281,7 @@ - + From f8f6aa09075dc1719a8f6063062a3bdba74a7c3e Mon Sep 17 00:00:00 2001 From: Asdqwe Date: Mon, 21 Oct 2024 19:06:37 -0300 Subject: [PATCH 154/208] [rcore] Adds implementation to `SetGamepadVibration()` on `PLATFORM_WEB` and updates it on `PLATFORM_DESKTOP_SDL` to handle duration (#4410) * Updates SetGamepadVibration() * Handle MAX_GAMEPAD_VIBRATION_TIME * Revert low/high parameters back to left/rightMotor * Fix missin semicolon * Convert duration to seconds * Add SetGamepadVibration() implementation to PLATFORM_WEB --- src/platforms/rcore_android.c | 2 +- src/platforms/rcore_desktop_glfw.c | 2 +- src/platforms/rcore_desktop_sdl.c | 18 +++++++++--------- src/platforms/rcore_drm.c | 4 ++-- src/platforms/rcore_web.c | 29 +++++++++++++++++++++++++++-- src/raylib.h | 2 +- 6 files changed, 41 insertions(+), 16 deletions(-) diff --git a/src/platforms/rcore_android.c b/src/platforms/rcore_android.c index 88438c9b0..85ce82a3a 100644 --- a/src/platforms/rcore_android.c +++ b/src/platforms/rcore_android.c @@ -615,7 +615,7 @@ int SetGamepadMappings(const char *mappings) } // Set gamepad vibration -void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor) +void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor, float duration) { TRACELOG(LOG_WARNING, "GamepadSetVibration() not implemented on target platform"); } diff --git a/src/platforms/rcore_desktop_glfw.c b/src/platforms/rcore_desktop_glfw.c index 0bc52ac9e..41f7fac39 100644 --- a/src/platforms/rcore_desktop_glfw.c +++ b/src/platforms/rcore_desktop_glfw.c @@ -1060,7 +1060,7 @@ int SetGamepadMappings(const char *mappings) } // Set gamepad vibration -void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor) +void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor, float duration) { TRACELOG(LOG_WARNING, "GamepadSetVibration() not available on target platform"); } diff --git a/src/platforms/rcore_desktop_sdl.c b/src/platforms/rcore_desktop_sdl.c index b4ceb78eb..7cbe0354e 100644 --- a/src/platforms/rcore_desktop_sdl.c +++ b/src/platforms/rcore_desktop_sdl.c @@ -953,17 +953,17 @@ int SetGamepadMappings(const char *mappings) } // Set gamepad vibration -void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor) +void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor, float duration) { - // Limit input values to between 0.0f and 1.0f - leftMotor = (0.0f > leftMotor)? 0.0f : leftMotor; - rightMotor = (0.0f > rightMotor)? 0.0f : rightMotor; - leftMotor = (1.0f < leftMotor)? 1.0f : leftMotor; - rightMotor = (1.0f < rightMotor)? 1.0f : rightMotor; - - if (IsGamepadAvailable(gamepad)) + if ((gamepad < MAX_GAMEPADS) && CORE.Input.Gamepad.ready[gamepad] && (duration > 0.0f)) { - SDL_GameControllerRumble(platform.gamepad[gamepad], (Uint16)(leftMotor*65535.0f), (Uint16)(rightMotor*65535.0f), (Uint32)(MAX_GAMEPAD_VIBRATION_TIME*1000.0f)); + if (leftMotor < 0.0f) leftMotor = 0.0f; + if (leftMotor > 1.0f) leftMotor = 1.0f; + if (rightMotor < 0.0f) rightMotor = 0.0f; + if (rightMotor > 1.0f) rightMotor = 1.0f; + if (duration > MAX_GAMEPAD_VIBRATION_TIME) duration = MAX_GAMEPAD_VIBRATION_TIME; + + SDL_GameControllerRumble(platform.gamepad[gamepad], (Uint16)(leftMotor*65535.0f), (Uint16)(rightMotor*65535.0f), (Uint32)(duration*1000.0f)); } } diff --git a/src/platforms/rcore_drm.c b/src/platforms/rcore_drm.c index e77457b1b..eb8ef0103 100644 --- a/src/platforms/rcore_drm.c +++ b/src/platforms/rcore_drm.c @@ -610,7 +610,7 @@ int SetGamepadMappings(const char *mappings) } // Set gamepad vibration -void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor) +void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor, float duration) { TRACELOG(LOG_WARNING, "GamepadSetVibration() not implemented on target platform"); } @@ -763,7 +763,7 @@ int InitPlatform(void) drmModeConnector *con = drmModeGetConnector(platform.fd, res->connectors[i]); TRACELOG(LOG_TRACE, "DISPLAY: Connector modes detected: %i", con->count_modes); - + // In certain cases the status of the conneciton is reported as UKNOWN, but it is still connected. // This might be a hardware or software limitation like on Raspberry Pi Zero with composite output. if (((con->connection == DRM_MODE_CONNECTED) || (con->connection == DRM_MODE_UNKNOWNCONNECTION)) && (con->encoder_id)) diff --git a/src/platforms/rcore_web.c b/src/platforms/rcore_web.c index 36af66a47..5fddbb371 100644 --- a/src/platforms/rcore_web.c +++ b/src/platforms/rcore_web.c @@ -892,9 +892,34 @@ int SetGamepadMappings(const char *mappings) } // Set gamepad vibration -void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor) +void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor, float duration) { - TRACELOG(LOG_WARNING, "GamepadSetVibration() not implemented on target platform"); + if ((gamepad < MAX_GAMEPADS) && CORE.Input.Gamepad.ready[gamepad] && (duration > 0.0f)) + { + if (leftMotor < 0.0f) leftMotor = 0.0f; + if (leftMotor > 1.0f) leftMotor = 1.0f; + if (rightMotor < 0.0f) rightMotor = 0.0f; + if (rightMotor > 1.0f) rightMotor = 1.0f; + if (duration > MAX_GAMEPAD_VIBRATION_TIME) duration = MAX_GAMEPAD_VIBRATION_TIME; + duration *= 1000.0f; // Convert duration to ms + + // Note: At the moment (2024.10.21) Chrome, Edge, Opera, Safari, Android Chrome, Android Webview only support the vibrationActuator API, + // and Firefox only supports the hapticActuators API + EM_ASM({ + try + { + navigator.getGamepads()[$0].vibrationActuator.playEffect('dual-rumble', { startDelay: 0, duration: $3, weakMagnitude: $1, strongMagnitude: $2 }); + } + catch (e) + { + try + { + navigator.getGamepads()[$0].hapticActuators[0].pulse($2, $3); + } + catch (e) { } + } + }, gamepad, leftMotor, rightMotor, duration); + } } // Set mouse position XY diff --git a/src/raylib.h b/src/raylib.h index 25ee6943f..fc505f787 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -1184,7 +1184,7 @@ RLAPI int GetGamepadButtonPressed(void); RLAPI int GetGamepadAxisCount(int gamepad); // Get gamepad axis count for a gamepad RLAPI float GetGamepadAxisMovement(int gamepad, int axis); // Get axis movement value for a gamepad axis RLAPI int SetGamepadMappings(const char *mappings); // Set internal gamepad mappings (SDL_GameControllerDB) -RLAPI void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor); // Set gamepad vibration for both motors +RLAPI void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor, float duration); // Set gamepad vibration for both motors (duration in seconds) // Input-related functions: mouse RLAPI bool IsMouseButtonPressed(int button); // Check if a mouse button has been pressed once From 2a0963ce0936abe0cd3ec32882638d860e435d16 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 21 Oct 2024 22:06:52 +0000 Subject: [PATCH 155/208] Update raylib_api.* by CI --- parser/output/raylib_api.json | 6 +++++- parser/output/raylib_api.lua | 5 +++-- parser/output/raylib_api.txt | 5 +++-- parser/output/raylib_api.xml | 3 ++- 4 files changed, 13 insertions(+), 6 deletions(-) diff --git a/parser/output/raylib_api.json b/parser/output/raylib_api.json index 591fef737..cca7241f2 100644 --- a/parser/output/raylib_api.json +++ b/parser/output/raylib_api.json @@ -5018,7 +5018,7 @@ }, { "name": "SetGamepadVibration", - "description": "Set gamepad vibration for both motors", + "description": "Set gamepad vibration for both motors (duration in seconds)", "returnType": "void", "params": [ { @@ -5032,6 +5032,10 @@ { "type": "float", "name": "rightMotor" + }, + { + "type": "float", + "name": "duration" } ] }, diff --git a/parser/output/raylib_api.lua b/parser/output/raylib_api.lua index b84e3c08c..f1ff0aa7b 100644 --- a/parser/output/raylib_api.lua +++ b/parser/output/raylib_api.lua @@ -4418,12 +4418,13 @@ return { }, { name = "SetGamepadVibration", - description = "Set gamepad vibration for both motors", + description = "Set gamepad vibration for both motors (duration in seconds)", returnType = "void", params = { {type = "int", name = "gamepad"}, {type = "float", name = "leftMotor"}, - {type = "float", name = "rightMotor"} + {type = "float", name = "rightMotor"}, + {type = "float", name = "duration"} } }, { diff --git a/parser/output/raylib_api.txt b/parser/output/raylib_api.txt index e0d5f36b4..faddc6008 100644 --- a/parser/output/raylib_api.txt +++ b/parser/output/raylib_api.txt @@ -1942,13 +1942,14 @@ Function 177: SetGamepadMappings() (1 input parameters) Return type: int Description: Set internal gamepad mappings (SDL_GameControllerDB) Param[1]: mappings (type: const char *) -Function 178: SetGamepadVibration() (3 input parameters) +Function 178: SetGamepadVibration() (4 input parameters) Name: SetGamepadVibration Return type: void - Description: Set gamepad vibration for both motors + Description: Set gamepad vibration for both motors (duration in seconds) Param[1]: gamepad (type: int) Param[2]: leftMotor (type: float) Param[3]: rightMotor (type: float) + Param[4]: duration (type: float) Function 179: IsMouseButtonPressed() (1 input parameters) Name: IsMouseButtonPressed Return type: bool diff --git a/parser/output/raylib_api.xml b/parser/output/raylib_api.xml index f59faf754..20d2b9a47 100644 --- a/parser/output/raylib_api.xml +++ b/parser/output/raylib_api.xml @@ -1217,10 +1217,11 @@ - + + From fe66bfb7850d3b599af2c6c502176871239487a5 Mon Sep 17 00:00:00 2001 From: Anthony Carbajal <5776225+CrackedPixel@users.noreply.github.com> Date: Tue, 22 Oct 2024 03:31:44 -0500 Subject: [PATCH 156/208] moved update out of draw area (#4413) --- examples/models/models_gpu_skinning.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/models/models_gpu_skinning.c b/examples/models/models_gpu_skinning.c index b6296c96a..6868a62d3 100644 --- a/examples/models/models_gpu_skinning.c +++ b/examples/models/models_gpu_skinning.c @@ -81,6 +81,8 @@ int main(void) // Update model animation ModelAnimation anim = modelAnimations[animIndex]; animCurrentFrame = (animCurrentFrame + 1)%anim.frameCount; + characterModel.transform = MatrixTranslate(position.x, position.y, position.z); + UpdateModelAnimationBoneMatrices(characterModel, anim, animCurrentFrame); //---------------------------------------------------------------------------------- // Draw @@ -92,8 +94,6 @@ int main(void) BeginMode3D(camera); // Draw character - characterModel.transform = MatrixTranslate(position.x, position.y, position.z); - UpdateModelAnimationBoneMatrices(characterModel, anim, animCurrentFrame); DrawMesh(characterModel.meshes[0], characterModel.materials[1], characterModel.transform); DrawGrid(10, 1.0f); From b2dca724c7c5a9720dc789cc39529a9341bcbbfb Mon Sep 17 00:00:00 2001 From: Ray Date: Tue, 22 Oct 2024 10:41:43 +0200 Subject: [PATCH 157/208] REVIEWED: skinning shader for GLSL 100 #4412 --- .../resources/shaders/glsl100/skinning.fs | 15 +++++---- .../resources/shaders/glsl100/skinning.vs | 33 ++++++++++--------- 2 files changed, 27 insertions(+), 21 deletions(-) diff --git a/examples/models/resources/shaders/glsl100/skinning.fs b/examples/models/resources/shaders/glsl100/skinning.fs index ef6568036..98a9e5bad 100644 --- a/examples/models/resources/shaders/glsl100/skinning.fs +++ b/examples/models/resources/shaders/glsl100/skinning.fs @@ -1,17 +1,20 @@ #version 100 +precision mediump float; + // Input vertex attributes (from vertex shader) -in vec2 fragTexCoord; -in vec4 fragColor; - -// Output fragment color -out vec4 finalColor; +varying vec2 fragTexCoord; +varying vec4 fragColor; +// Input uniform values uniform sampler2D texture0; uniform vec4 colDiffuse; void main() { + // Fetch color from texture sampler vec4 texelColor = texture(texture0, fragTexCoord); - finalColor = texelColor*colDiffuse*fragColor; + + // Calculate final fragment color + gl_FragColor = texelColor*colDiffuse*fragColor; } diff --git a/examples/models/resources/shaders/glsl100/skinning.vs b/examples/models/resources/shaders/glsl100/skinning.vs index 9c92e2a8c..456079102 100644 --- a/examples/models/resources/shaders/glsl100/skinning.vs +++ b/examples/models/resources/shaders/glsl100/skinning.vs @@ -1,18 +1,21 @@ #version 100 -in vec3 vertexPosition; -in vec2 vertexTexCoord; -in vec4 vertexColor; -in vec4 vertexBoneIds; -in vec4 vertexBoneWeights; +#define MAX_BONE_NUM 64 -#define MAX_BONE_NUM 128 +// Input vertex attributes +attribute vec3 vertexPosition; +attribute vec2 vertexTexCoord; +attribute vec4 vertexColor; +attribute vec4 vertexBoneIds; +attribute vec4 vertexBoneWeights; + +// Input uniform values +uniform mat4 mvp; uniform mat4 boneMatrices[MAX_BONE_NUM]; -uniform mat4 mvp; - -out vec2 fragTexCoord; -out vec4 fragColor; +// Output vertex attributes (to fragment shader) +varying vec2 fragTexCoord; +varying vec4 fragColor; void main() { @@ -22,13 +25,13 @@ void main() int boneIndex3 = int(vertexBoneIds.w); vec4 skinnedPosition = - vertexBoneWeights.x * (boneMatrices[boneIndex0] * vec4(vertexPosition, 1.0f)) + - vertexBoneWeights.y * (boneMatrices[boneIndex1] * vec4(vertexPosition, 1.0f)) + - vertexBoneWeights.z * (boneMatrices[boneIndex2] * vec4(vertexPosition, 1.0f)) + - vertexBoneWeights.w * (boneMatrices[boneIndex3] * vec4(vertexPosition, 1.0f)); + vertexBoneWeights.x*(boneMatrices[boneIndex0]*vec4(vertexPosition, 1.0f)) + + vertexBoneWeights.y*(boneMatrices[boneIndex1]*vec4(vertexPosition, 1.0f)) + + vertexBoneWeights.z*(boneMatrices[boneIndex2]*vec4(vertexPosition, 1.0f)) + + vertexBoneWeights.w*(boneMatrices[boneIndex3]*vec4(vertexPosition, 1.0f)); fragTexCoord = vertexTexCoord; fragColor = vertexColor; - gl_Position = mvp * skinnedPosition; + gl_Position = mvp*skinnedPosition; } \ No newline at end of file From b89bf0185a2ff4fd86035a2d3abed29b0552dc7b Mon Sep 17 00:00:00 2001 From: Sage Hane Date: Tue, 22 Oct 2024 20:20:09 +0900 Subject: [PATCH 158/208] build.zig: Better specify Linux dependencies (#4406) --- build.zig | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/build.zig b/build.zig index 56e69caf4..1f3c83162 100644 --- a/build.zig +++ b/build.zig @@ -186,16 +186,16 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std. .linux => { if (options.platform != .drm) { try c_source_files.append("src/rglfw.c"); - raylib.linkSystemLibrary("GL"); - raylib.linkSystemLibrary("rt"); - raylib.linkSystemLibrary("dl"); - raylib.linkSystemLibrary("m"); - - raylib.addLibraryPath(.{ .cwd_relative = "/usr/lib" }); - raylib.addIncludePath(.{ .cwd_relative = "/usr/include" }); if (options.linux_display_backend == .X11 or options.linux_display_backend == .Both) { raylib.defineCMacro("_GLFW_X11", null); raylib.linkSystemLibrary("X11"); + raylib.linkSystemLibrary("Xcursor"); + raylib.linkSystemLibrary("Xext"); + raylib.linkSystemLibrary("Xfixes"); + raylib.linkSystemLibrary("Xi"); + raylib.linkSystemLibrary("Xinerama"); + raylib.linkSystemLibrary("Xrandr"); + raylib.linkSystemLibrary("Xrender"); } if (options.linux_display_backend == .Wayland or options.linux_display_backend == .Both) { @@ -208,8 +208,6 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std. }; raylib.defineCMacro("_GLFW_WAYLAND", null); raylib.linkSystemLibrary("wayland-client"); - raylib.linkSystemLibrary("wayland-cursor"); - raylib.linkSystemLibrary("wayland-egl"); raylib.linkSystemLibrary("xkbcommon"); waylandGenerate(b, raylib, "wayland.xml", "wayland-client-protocol"); waylandGenerate(b, raylib, "xdg-shell.xml", "xdg-shell-client-protocol"); @@ -228,14 +226,8 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std. raylib.defineCMacro("GRAPHICS_API_OPENGL_ES2", null); } - raylib.linkSystemLibrary("EGL"); - raylib.linkSystemLibrary("drm"); raylib.linkSystemLibrary("gbm"); - raylib.linkSystemLibrary("pthread"); - raylib.linkSystemLibrary("rt"); - raylib.linkSystemLibrary("m"); - raylib.linkSystemLibrary("dl"); - raylib.addIncludePath(.{ .cwd_relative = "/usr/include/libdrm" }); + raylib.linkSystemLibrary2("libdrm", .{ .use_pkg_config = .force }); raylib.defineCMacro("PLATFORM_DRM", null); raylib.defineCMacro("EGL_NO_X11", null); From 4cd243f0a3a8e9f59e5d5453f88360f5acbc29f7 Mon Sep 17 00:00:00 2001 From: Asdqwe Date: Tue, 22 Oct 2024 08:44:53 -0300 Subject: [PATCH 159/208] Simplify EmscriptenResizeCallback() (#4415) --- src/platforms/rcore_web.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/platforms/rcore_web.c b/src/platforms/rcore_web.c index 5fddbb371..e15d3f5bf 100644 --- a/src/platforms/rcore_web.c +++ b/src/platforms/rcore_web.c @@ -324,8 +324,8 @@ void MaximizeWindow(void) platform.unmaximizedWidth = CORE.Window.screen.width; platform.unmaximizedHeight = CORE.Window.screen.height; - const int tabWidth = EM_ASM_INT( { return window.innerWidth; }, 0); - const int tabHeight = EM_ASM_INT( { return window.innerHeight; }, 0); + const int tabWidth = EM_ASM_INT( return window.innerWidth; ); + const int tabHeight = EM_ASM_INT( return window.innerHeight; ); if (tabWidth && tabHeight) glfwSetWindowSize(platform.handle, tabWidth, tabHeight); @@ -423,8 +423,8 @@ void SetWindowState(unsigned int flags) platform.unmaximizedWidth = CORE.Window.screen.width; platform.unmaximizedHeight = CORE.Window.screen.height; - const int tabWidth = EM_ASM_INT( { return window.innerWidth; }, 0); - const int tabHeight = EM_ASM_INT( { return window.innerHeight; }, 0); + const int tabWidth = EM_ASM_INT( return window.innerWidth; ); + const int tabHeight = EM_ASM_INT( return window.innerHeight; ); if (tabWidth && tabHeight) glfwSetWindowSize(platform.handle, tabWidth, tabHeight); @@ -1639,9 +1639,6 @@ static EM_BOOL EmscriptenFullscreenChangeCallback(int eventType, const Emscripte // return 1; // The event was consumed by the callback handler // } -EM_JS(int, GetWindowInnerWidth, (), { return window.innerWidth; }); -EM_JS(int, GetWindowInnerHeight, (), { return window.innerHeight; }); - // Register DOM element resize event static EM_BOOL EmscriptenResizeCallback(int eventType, const EmscriptenUiEvent *event, void *userData) { @@ -1650,8 +1647,8 @@ static EM_BOOL EmscriptenResizeCallback(int eventType, const EmscriptenUiEvent * // This event is called whenever the window changes sizes, // so the size of the canvas object is explicitly retrieved below - int width = GetWindowInnerWidth(); - int height = GetWindowInnerHeight(); + int width = EM_ASM_INT( return window.innerWidth; ); + int height = EM_ASM_INT( return window.innerHeight; ); if (width < (int)CORE.Window.screenMin.width) width = CORE.Window.screenMin.width; else if (width > (int)CORE.Window.screenMax.width && CORE.Window.screenMax.width > 0) width = CORE.Window.screenMax.width; From 55249faa5861a468f763318edf58ca49e5cae491 Mon Sep 17 00:00:00 2001 From: Sage Hane Date: Wed, 23 Oct 2024 00:35:08 +0900 Subject: [PATCH 160/208] build.zig: Re-add OpenGL to Linux deps (#4417) --- build.zig | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/build.zig b/build.zig index 1f3c83162..054d1644d 100644 --- a/build.zig +++ b/build.zig @@ -186,8 +186,10 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std. .linux => { if (options.platform != .drm) { try c_source_files.append("src/rglfw.c"); + if (options.linux_display_backend == .X11 or options.linux_display_backend == .Both) { raylib.defineCMacro("_GLFW_X11", null); + raylib.linkSystemLibrary("GLX"); raylib.linkSystemLibrary("X11"); raylib.linkSystemLibrary("Xcursor"); raylib.linkSystemLibrary("Xext"); @@ -207,6 +209,7 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std. @panic("`wayland-scanner` not found"); }; raylib.defineCMacro("_GLFW_WAYLAND", null); + raylib.linkSystemLibrary("EGL"); raylib.linkSystemLibrary("wayland-client"); raylib.linkSystemLibrary("xkbcommon"); waylandGenerate(b, raylib, "wayland.xml", "wayland-client-protocol"); @@ -226,6 +229,7 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std. raylib.defineCMacro("GRAPHICS_API_OPENGL_ES2", null); } + raylib.linkSystemLibrary("EGL"); raylib.linkSystemLibrary("gbm"); raylib.linkSystemLibrary2("libdrm", .{ .use_pkg_config = .force }); From 53f7da2506329f1a00a4e0ef3e66c5b7d7843f6f Mon Sep 17 00:00:00 2001 From: Sage Hane Date: Wed, 23 Oct 2024 01:31:26 +0900 Subject: [PATCH 161/208] build.zig: Fix a minor issue with `-Dconfig` (#4418) --- build.zig | 1 + 1 file changed, 1 insertion(+) diff --git a/build.zig b/build.zig index 054d1644d..75a77dd51 100644 --- a/build.zig +++ b/build.zig @@ -116,6 +116,7 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std. // `n` corresponds to the number of user-specified flags outer: for (config_h_flags) |flag| { // If a user already specified the flag, skip it + config_iter.reset(); while (config_iter.next()) |config_flag| { // For a user-specified flag to match, it must share the same prefix and have the // same length or be followed by an equals sign From 79e2be68c2ff3eea4f9af2036d02856c86256e57 Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 23 Oct 2024 00:20:59 +0200 Subject: [PATCH 162/208] Reviewed skinning shaders #4412 --- .../resources/shaders/glsl100/skinning.vs | 8 ++++---- .../resources/shaders/glsl330/skinning.vs | 19 +++++++++++-------- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/examples/models/resources/shaders/glsl100/skinning.vs b/examples/models/resources/shaders/glsl100/skinning.vs index 456079102..f7b6d8fb2 100644 --- a/examples/models/resources/shaders/glsl100/skinning.vs +++ b/examples/models/resources/shaders/glsl100/skinning.vs @@ -25,10 +25,10 @@ void main() int boneIndex3 = int(vertexBoneIds.w); vec4 skinnedPosition = - vertexBoneWeights.x*(boneMatrices[boneIndex0]*vec4(vertexPosition, 1.0f)) + - vertexBoneWeights.y*(boneMatrices[boneIndex1]*vec4(vertexPosition, 1.0f)) + - vertexBoneWeights.z*(boneMatrices[boneIndex2]*vec4(vertexPosition, 1.0f)) + - vertexBoneWeights.w*(boneMatrices[boneIndex3]*vec4(vertexPosition, 1.0f)); + vertexBoneWeights.x*(boneMatrices[boneIndex0]*vec4(vertexPosition, 1.0)) + + vertexBoneWeights.y*(boneMatrices[boneIndex1]*vec4(vertexPosition, 1.0)) + + vertexBoneWeights.z*(boneMatrices[boneIndex2]*vec4(vertexPosition, 1.0)) + + vertexBoneWeights.w*(boneMatrices[boneIndex3]*vec4(vertexPosition, 1.0)); fragTexCoord = vertexTexCoord; fragColor = vertexColor; diff --git a/examples/models/resources/shaders/glsl330/skinning.vs b/examples/models/resources/shaders/glsl330/skinning.vs index 2dc976c48..73ecca51e 100644 --- a/examples/models/resources/shaders/glsl330/skinning.vs +++ b/examples/models/resources/shaders/glsl330/skinning.vs @@ -1,16 +1,19 @@ #version 330 +#define MAX_BONE_NUM 128 + +// Input vertex attributes in vec3 vertexPosition; in vec2 vertexTexCoord; in vec4 vertexColor; in vec4 vertexBoneIds; in vec4 vertexBoneWeights; -#define MAX_BONE_NUM 128 +// Input uniform values +uniform mat4 mvp; uniform mat4 boneMatrices[MAX_BONE_NUM]; -uniform mat4 mvp; - +// Output vertex attributes (to fragment shader) out vec2 fragTexCoord; out vec4 fragColor; @@ -22,13 +25,13 @@ void main() int boneIndex3 = int(vertexBoneIds.w); vec4 skinnedPosition = - vertexBoneWeights.x * (boneMatrices[boneIndex0] * vec4(vertexPosition, 1.0f)) + - vertexBoneWeights.y * (boneMatrices[boneIndex1] * vec4(vertexPosition, 1.0f)) + - vertexBoneWeights.z * (boneMatrices[boneIndex2] * vec4(vertexPosition, 1.0f)) + - vertexBoneWeights.w * (boneMatrices[boneIndex3] * vec4(vertexPosition, 1.0f)); + vertexBoneWeights.x*(boneMatrices[boneIndex0]*vec4(vertexPosition, 1.0)) + + vertexBoneWeights.y*(boneMatrices[boneIndex1]*vec4(vertexPosition, 1.0)) + + vertexBoneWeights.z*(boneMatrices[boneIndex2]*vec4(vertexPosition, 1.0)) + + vertexBoneWeights.w*(boneMatrices[boneIndex3]*vec4(vertexPosition, 1.0)); fragTexCoord = vertexTexCoord; fragColor = vertexColor; - gl_Position = mvp * skinnedPosition; + gl_Position = mvp*skinnedPosition; } \ No newline at end of file From 352f4ce2c435251826d9f28467910bd298934b1e Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 23 Oct 2024 00:21:06 +0200 Subject: [PATCH 163/208] Update config.h --- src/config.h | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/config.h b/src/config.h index 9123a2291..f37a9de3e 100644 --- a/src/config.h +++ b/src/config.h @@ -100,6 +100,8 @@ // Show OpenGL extensions and capabilities detailed logs on init //#define RLGL_SHOW_GL_DETAILS_INFO 1 +#define RL_SUPPORT_MESH_GPU_SKINNING 1 // GPU skinning, comment if your GPU does not support more than 8 VBOs + //#define RL_DEFAULT_BATCH_BUFFER_ELEMENTS 4096 // Default internal render batch elements limits #define RL_DEFAULT_BATCH_BUFFERS 1 // Default number of batch buffers (multi-buffering) #define RL_DEFAULT_BATCH_DRAWCALLS 256 // Default number of batch draw calls (by state changes: mode, texture) @@ -120,16 +122,11 @@ #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT 4 #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2 5 #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_INDICES 6 - - -#define RL_SUPPORT_MESH_GPU_SKINNING // Remove this if your GPU does not support more than 8 VBOs - -#ifdef RL_SUPPORT_MESH_GPU_SKINNING -#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS 7 -#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS 8 +#if defined(RL_SUPPORT_MESH_GPU_SKINNING) + #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS 7 + #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS 8 #endif - // Default shader vertex attribute names to set location points // NOTE: When a new shader is loaded, the following locations are tried to be set for convenience #define RL_DEFAULT_SHADER_ATTRIB_NAME_POSITION "vertexPosition" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION From 4b60ce700f827bbca58eb7e952b8b07f0cc9c121 Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 23 Oct 2024 00:21:14 +0200 Subject: [PATCH 164/208] Update raylib.h --- src/raylib.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/raylib.h b/src/raylib.h index fc505f787..536b441b4 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -1299,13 +1299,13 @@ RLAPI Vector2 GetSplinePointBezierCubic(Vector2 p1, Vector2 c2, Vector2 c3, Vect RLAPI bool CheckCollisionRecs(Rectangle rec1, Rectangle rec2); // Check collision between two rectangles RLAPI bool CheckCollisionCircles(Vector2 center1, float radius1, Vector2 center2, float radius2); // Check collision between two circles RLAPI bool CheckCollisionCircleRec(Vector2 center, float radius, Rectangle rec); // Check collision between circle and rectangle +RLAPI bool CheckCollisionCircleLine(Vector2 center, float radius, Vector2 p1, Vector2 p2); // Check if circle collides with a line created betweeen two points [p1] and [p2] RLAPI bool CheckCollisionPointRec(Vector2 point, Rectangle rec); // Check if point is inside rectangle RLAPI bool CheckCollisionPointCircle(Vector2 point, Vector2 center, float radius); // Check if point is inside circle RLAPI bool CheckCollisionPointTriangle(Vector2 point, Vector2 p1, Vector2 p2, Vector2 p3); // Check if point is inside a triangle +RLAPI bool CheckCollisionPointLine(Vector2 point, Vector2 p1, Vector2 p2, int threshold); // Check if point belongs to line created between two points [p1] and [p2] with defined margin in pixels [threshold] RLAPI bool CheckCollisionPointPoly(Vector2 point, const Vector2 *points, int pointCount); // Check if point is within a polygon described by array of vertices RLAPI bool CheckCollisionLines(Vector2 startPos1, Vector2 endPos1, Vector2 startPos2, Vector2 endPos2, Vector2 *collisionPoint); // Check the collision between two lines defined by two points each, returns collision point by reference -RLAPI bool CheckCollisionPointLine(Vector2 point, Vector2 p1, Vector2 p2, int threshold); // Check if point belongs to line created between two points [p1] and [p2] with defined margin in pixels [threshold] -RLAPI bool CheckCollisionCircleLine(Vector2 center, float radius, Vector2 p1, Vector2 p2); // Check if circle collides with a line created betweeen two points [p1] and [p2] RLAPI Rectangle GetCollisionRec(Rectangle rec1, Rectangle rec2); // Get collision rectangle for two rectangles collision //------------------------------------------------------------------------------------ From ebcfc7f49e925f0ff5ddfa744e44bdc1c50ed2a2 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 22 Oct 2024 22:21:35 +0000 Subject: [PATCH 165/208] Update raylib_api.* by CI --- parser/output/raylib_api.json | 92 +++++++++++++++++------------------ parser/output/raylib_api.lua | 44 ++++++++--------- parser/output/raylib_api.txt | 42 ++++++++-------- parser/output/raylib_api.xml | 24 ++++----- 4 files changed, 101 insertions(+), 101 deletions(-) diff --git a/parser/output/raylib_api.json b/parser/output/raylib_api.json index cca7241f2..9db3d7ac0 100644 --- a/parser/output/raylib_api.json +++ b/parser/output/raylib_api.json @@ -6662,6 +6662,29 @@ } ] }, + { + "name": "CheckCollisionCircleLine", + "description": "Check if circle collides with a line created betweeen two points [p1] and [p2]", + "returnType": "bool", + "params": [ + { + "type": "Vector2", + "name": "center" + }, + { + "type": "float", + "name": "radius" + }, + { + "type": "Vector2", + "name": "p1" + }, + { + "type": "Vector2", + "name": "p2" + } + ] + }, { "name": "CheckCollisionPointRec", "description": "Check if point is inside rectangle", @@ -6719,6 +6742,29 @@ } ] }, + { + "name": "CheckCollisionPointLine", + "description": "Check if point belongs to line created between two points [p1] and [p2] with defined margin in pixels [threshold]", + "returnType": "bool", + "params": [ + { + "type": "Vector2", + "name": "point" + }, + { + "type": "Vector2", + "name": "p1" + }, + { + "type": "Vector2", + "name": "p2" + }, + { + "type": "int", + "name": "threshold" + } + ] + }, { "name": "CheckCollisionPointPoly", "description": "Check if point is within a polygon described by array of vertices", @@ -6765,52 +6811,6 @@ } ] }, - { - "name": "CheckCollisionPointLine", - "description": "Check if point belongs to line created between two points [p1] and [p2] with defined margin in pixels [threshold]", - "returnType": "bool", - "params": [ - { - "type": "Vector2", - "name": "point" - }, - { - "type": "Vector2", - "name": "p1" - }, - { - "type": "Vector2", - "name": "p2" - }, - { - "type": "int", - "name": "threshold" - } - ] - }, - { - "name": "CheckCollisionCircleLine", - "description": "Check if circle collides with a line created betweeen two points [p1] and [p2]", - "returnType": "bool", - "params": [ - { - "type": "Vector2", - "name": "center" - }, - { - "type": "float", - "name": "radius" - }, - { - "type": "Vector2", - "name": "p1" - }, - { - "type": "Vector2", - "name": "p2" - } - ] - }, { "name": "GetCollisionRec", "description": "Get collision rectangle for two rectangles collision", diff --git a/parser/output/raylib_api.lua b/parser/output/raylib_api.lua index f1ff0aa7b..d5492cb9b 100644 --- a/parser/output/raylib_api.lua +++ b/parser/output/raylib_api.lua @@ -5264,6 +5264,17 @@ return { {type = "Rectangle", name = "rec"} } }, + { + name = "CheckCollisionCircleLine", + description = "Check if circle collides with a line created betweeen two points [p1] and [p2]", + returnType = "bool", + params = { + {type = "Vector2", name = "center"}, + {type = "float", name = "radius"}, + {type = "Vector2", name = "p1"}, + {type = "Vector2", name = "p2"} + } + }, { name = "CheckCollisionPointRec", description = "Check if point is inside rectangle", @@ -5294,6 +5305,17 @@ return { {type = "Vector2", name = "p3"} } }, + { + name = "CheckCollisionPointLine", + description = "Check if point belongs to line created between two points [p1] and [p2] with defined margin in pixels [threshold]", + returnType = "bool", + params = { + {type = "Vector2", name = "point"}, + {type = "Vector2", name = "p1"}, + {type = "Vector2", name = "p2"}, + {type = "int", name = "threshold"} + } + }, { name = "CheckCollisionPointPoly", description = "Check if point is within a polygon described by array of vertices", @@ -5316,28 +5338,6 @@ return { {type = "Vector2 *", name = "collisionPoint"} } }, - { - name = "CheckCollisionPointLine", - description = "Check if point belongs to line created between two points [p1] and [p2] with defined margin in pixels [threshold]", - returnType = "bool", - params = { - {type = "Vector2", name = "point"}, - {type = "Vector2", name = "p1"}, - {type = "Vector2", name = "p2"}, - {type = "int", name = "threshold"} - } - }, - { - name = "CheckCollisionCircleLine", - description = "Check if circle collides with a line created betweeen two points [p1] and [p2]", - returnType = "bool", - params = { - {type = "Vector2", name = "center"}, - {type = "float", name = "radius"}, - {type = "Vector2", name = "p1"}, - {type = "Vector2", name = "p2"} - } - }, { name = "GetCollisionRec", description = "Get collision rectangle for two rectangles collision", diff --git a/parser/output/raylib_api.txt b/parser/output/raylib_api.txt index faddc6008..f6c79f85e 100644 --- a/parser/output/raylib_api.txt +++ b/parser/output/raylib_api.txt @@ -2577,20 +2577,28 @@ Function 265: CheckCollisionCircleRec() (3 input parameters) Param[1]: center (type: Vector2) Param[2]: radius (type: float) Param[3]: rec (type: Rectangle) -Function 266: CheckCollisionPointRec() (2 input parameters) +Function 266: CheckCollisionCircleLine() (4 input parameters) + Name: CheckCollisionCircleLine + Return type: bool + Description: Check if circle collides with a line created betweeen two points [p1] and [p2] + Param[1]: center (type: Vector2) + Param[2]: radius (type: float) + Param[3]: p1 (type: Vector2) + Param[4]: p2 (type: Vector2) +Function 267: CheckCollisionPointRec() (2 input parameters) Name: CheckCollisionPointRec Return type: bool Description: Check if point is inside rectangle Param[1]: point (type: Vector2) Param[2]: rec (type: Rectangle) -Function 267: CheckCollisionPointCircle() (3 input parameters) +Function 268: CheckCollisionPointCircle() (3 input parameters) Name: CheckCollisionPointCircle Return type: bool Description: Check if point is inside circle Param[1]: point (type: Vector2) Param[2]: center (type: Vector2) Param[3]: radius (type: float) -Function 268: CheckCollisionPointTriangle() (4 input parameters) +Function 269: CheckCollisionPointTriangle() (4 input parameters) Name: CheckCollisionPointTriangle Return type: bool Description: Check if point is inside a triangle @@ -2598,14 +2606,22 @@ Function 268: CheckCollisionPointTriangle() (4 input parameters) Param[2]: p1 (type: Vector2) Param[3]: p2 (type: Vector2) Param[4]: p3 (type: Vector2) -Function 269: CheckCollisionPointPoly() (3 input parameters) +Function 270: CheckCollisionPointLine() (4 input parameters) + Name: CheckCollisionPointLine + Return type: bool + Description: Check if point belongs to line created between two points [p1] and [p2] with defined margin in pixels [threshold] + Param[1]: point (type: Vector2) + Param[2]: p1 (type: Vector2) + Param[3]: p2 (type: Vector2) + Param[4]: threshold (type: int) +Function 271: CheckCollisionPointPoly() (3 input parameters) Name: CheckCollisionPointPoly Return type: bool Description: Check if point is within a polygon described by array of vertices Param[1]: point (type: Vector2) Param[2]: points (type: const Vector2 *) Param[3]: pointCount (type: int) -Function 270: CheckCollisionLines() (5 input parameters) +Function 272: CheckCollisionLines() (5 input parameters) Name: CheckCollisionLines Return type: bool Description: Check the collision between two lines defined by two points each, returns collision point by reference @@ -2614,22 +2630,6 @@ Function 270: CheckCollisionLines() (5 input parameters) Param[3]: startPos2 (type: Vector2) Param[4]: endPos2 (type: Vector2) Param[5]: collisionPoint (type: Vector2 *) -Function 271: CheckCollisionPointLine() (4 input parameters) - Name: CheckCollisionPointLine - Return type: bool - Description: Check if point belongs to line created between two points [p1] and [p2] with defined margin in pixels [threshold] - Param[1]: point (type: Vector2) - Param[2]: p1 (type: Vector2) - Param[3]: p2 (type: Vector2) - Param[4]: threshold (type: int) -Function 272: CheckCollisionCircleLine() (4 input parameters) - Name: CheckCollisionCircleLine - Return type: bool - Description: Check if circle collides with a line created betweeen two points [p1] and [p2] - Param[1]: center (type: Vector2) - Param[2]: radius (type: float) - Param[3]: p1 (type: Vector2) - Param[4]: p2 (type: Vector2) Function 273: GetCollisionRec() (2 input parameters) Name: GetCollisionRec Return type: Rectangle diff --git a/parser/output/raylib_api.xml b/parser/output/raylib_api.xml index 20d2b9a47..6de5933d4 100644 --- a/parser/output/raylib_api.xml +++ b/parser/output/raylib_api.xml @@ -1659,6 +1659,12 @@ + + + + + + @@ -1674,6 +1680,12 @@ + + + + + + @@ -1686,18 +1698,6 @@ - - - - - - - - - - - - From 75a4c5bf20ff3ef75b64362f007227489d7e08d4 Mon Sep 17 00:00:00 2001 From: Asdqwe Date: Tue, 22 Oct 2024 19:28:20 -0300 Subject: [PATCH 166/208] Update core_input_gamepad example (#4416) --- examples/core/core_input_gamepad.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/core/core_input_gamepad.c b/examples/core/core_input_gamepad.c index 656f7c244..7a8b7e4bb 100644 --- a/examples/core/core_input_gamepad.c +++ b/examples/core/core_input_gamepad.c @@ -20,9 +20,9 @@ #include "raylib.h" // NOTE: Gamepad name ID depends on drivers and OS -#define XBOX360_LEGACY_NAME_ID "Xbox Controller" -#define XBOX360_NAME_ID "Xbox 360 Controller" -#define PS3_NAME_ID "Sony PLAYSTATION(R)3 Controller" +#define XBOX_ALIAS_1 "xbox" +#define XBOX_ALIAS_2 "x-box" +#define PS_ALIAS "playstation" //------------------------------------------------------------------------------------ // Program main entry point @@ -67,7 +67,7 @@ int main(void) { DrawText(TextFormat("GP%d: %s", gamepad, GetGamepadName(gamepad)), 10, 10, 10, BLACK); - if (TextIsEqual(GetGamepadName(gamepad), XBOX360_LEGACY_NAME_ID) || TextIsEqual(GetGamepadName(gamepad), XBOX360_NAME_ID)) + if (TextFindIndex(TextToLower(GetGamepadName(gamepad)), XBOX_ALIAS_1) > -1 || TextFindIndex(TextToLower(GetGamepadName(gamepad)), XBOX_ALIAS_2) > -1) { DrawTexture(texXboxPad, 0, 0, DARKGRAY); @@ -120,7 +120,7 @@ int main(void) //DrawText(TextFormat("Xbox axis LT: %02.02f", GetGamepadAxisMovement(gamepad, GAMEPAD_AXIS_LEFT_TRIGGER)), 10, 40, 10, BLACK); //DrawText(TextFormat("Xbox axis RT: %02.02f", GetGamepadAxisMovement(gamepad, GAMEPAD_AXIS_RIGHT_TRIGGER)), 10, 60, 10, BLACK); } - else if (TextIsEqual(GetGamepadName(gamepad), PS3_NAME_ID)) + else if (TextFindIndex(TextToLower(GetGamepadName(gamepad)), PS_ALIAS) > -1) { DrawTexture(texPs3Pad, 0, 0, DARKGRAY); From 7a4a84a5619754b8170737726a14b368e8cbc5bf Mon Sep 17 00:00:00 2001 From: Asdqwe Date: Tue, 22 Oct 2024 19:59:50 -0300 Subject: [PATCH 167/208] [rcore] Fix #4405 (#4420) * Fix #4405 at runtime * Add parameter validation * Remove default global deadzone --- src/rcore.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/rcore.c b/src/rcore.c index a1771d18e..9734972cf 100644 --- a/src/rcore.c +++ b/src/rcore.c @@ -3295,8 +3295,7 @@ float GetGamepadAxisMovement(int gamepad, int axis) if ((gamepad < MAX_GAMEPADS) && CORE.Input.Gamepad.ready[gamepad] && (axis < MAX_GAMEPAD_AXIS)) { float movement = value < 0.0f ? CORE.Input.Gamepad.axisState[gamepad][axis] : fabsf(CORE.Input.Gamepad.axisState[gamepad][axis]); - // 0.1f = GAMEPAD_AXIS_MINIMUM_DRIFT/DELTA - if (movement > value + 0.1f) value = CORE.Input.Gamepad.axisState[gamepad][axis]; + if (movement > value) value = CORE.Input.Gamepad.axisState[gamepad][axis]; } return value; From fe6da67066bcbb6e43e719ce5ef3e9f424e7cbdf Mon Sep 17 00:00:00 2001 From: Asdqwe Date: Wed, 23 Oct 2024 11:31:27 -0300 Subject: [PATCH 168/208] [examples] Add deadzone handling to `core_input_gamepad` example (#4422) * Add deadzone handling to core_input_gamepad example * Rename variables --- examples/core/core_input_gamepad.c | 50 ++++++++++++++++++++++-------- 1 file changed, 37 insertions(+), 13 deletions(-) diff --git a/examples/core/core_input_gamepad.c b/examples/core/core_input_gamepad.c index 7a8b7e4bb..43dc65499 100644 --- a/examples/core/core_input_gamepad.c +++ b/examples/core/core_input_gamepad.c @@ -41,6 +41,14 @@ int main(void) Texture2D texPs3Pad = LoadTexture("resources/ps3.png"); Texture2D texXboxPad = LoadTexture("resources/xbox.png"); + // Set axis deadzones + const float leftStickDeadzoneX = 0.1f; + const float leftStickDeadzoneY = 0.1f; + const float rightStickDeadzoneX = 0.1f; + const float rightStickDeadzoneY = 0.1f; + const float leftTriggerDeadzone = -0.9f; + const float rightTriggerDeadzone = -0.9f; + SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- @@ -67,6 +75,22 @@ int main(void) { DrawText(TextFormat("GP%d: %s", gamepad, GetGamepadName(gamepad)), 10, 10, 10, BLACK); + // Get axis values + float leftStickX = GetGamepadAxisMovement(gamepad, GAMEPAD_AXIS_LEFT_X); + float leftStickY = GetGamepadAxisMovement(gamepad, GAMEPAD_AXIS_LEFT_Y); + float rightStickX = GetGamepadAxisMovement(gamepad, GAMEPAD_AXIS_RIGHT_X); + float rightStickY = GetGamepadAxisMovement(gamepad, GAMEPAD_AXIS_RIGHT_Y); + float leftTrigger = GetGamepadAxisMovement(gamepad, GAMEPAD_AXIS_LEFT_TRIGGER); + float rightTrigger = GetGamepadAxisMovement(gamepad, GAMEPAD_AXIS_RIGHT_TRIGGER); + + // Calculate deadzones + if (leftStickX > -leftStickDeadzoneX && leftStickX < leftStickDeadzoneX) leftStickX = 0.0f; + if (leftStickY > -leftStickDeadzoneY && leftStickY < leftStickDeadzoneY) leftStickY = 0.0f; + if (rightStickX > -rightStickDeadzoneX && rightStickX < rightStickDeadzoneX) rightStickX = 0.0f; + if (rightStickY > -rightStickDeadzoneY && rightStickY < rightStickDeadzoneY) rightStickY = 0.0f; + if (leftTrigger < leftTriggerDeadzone) leftTrigger = -1.0f; + if (rightTrigger < rightTriggerDeadzone) rightTrigger = -1.0f; + if (TextFindIndex(TextToLower(GetGamepadName(gamepad)), XBOX_ALIAS_1) > -1 || TextFindIndex(TextToLower(GetGamepadName(gamepad)), XBOX_ALIAS_2) > -1) { DrawTexture(texXboxPad, 0, 0, DARKGRAY); @@ -100,22 +124,22 @@ int main(void) if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_LEFT_THUMB)) leftGamepadColor = RED; DrawCircle(259, 152, 39, BLACK); DrawCircle(259, 152, 34, LIGHTGRAY); - DrawCircle(259 + (int)(GetGamepadAxisMovement(gamepad, GAMEPAD_AXIS_LEFT_X)*20), - 152 + (int)(GetGamepadAxisMovement(gamepad, GAMEPAD_AXIS_LEFT_Y)*20), 25, leftGamepadColor); + DrawCircle(259 + (int)(leftStickX*20), + 152 + (int)(leftStickY*20), 25, leftGamepadColor); // Draw axis: right joystick Color rightGamepadColor = BLACK; if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_RIGHT_THUMB)) rightGamepadColor = RED; DrawCircle(461, 237, 38, BLACK); DrawCircle(461, 237, 33, LIGHTGRAY); - DrawCircle(461 + (int)(GetGamepadAxisMovement(gamepad, GAMEPAD_AXIS_RIGHT_X)*20), - 237 + (int)(GetGamepadAxisMovement(gamepad, GAMEPAD_AXIS_RIGHT_Y)*20), 25, rightGamepadColor); + DrawCircle(461 + (int)(rightStickX*20), + 237 + (int)(rightStickY*20), 25, rightGamepadColor); // Draw axis: left-right triggers DrawRectangle(170, 30, 15, 70, GRAY); DrawRectangle(604, 30, 15, 70, GRAY); - DrawRectangle(170, 30, 15, (int)(((1 + GetGamepadAxisMovement(gamepad, GAMEPAD_AXIS_LEFT_TRIGGER))/2)*70), RED); - DrawRectangle(604, 30, 15, (int)(((1 + GetGamepadAxisMovement(gamepad, GAMEPAD_AXIS_RIGHT_TRIGGER))/2)*70), RED); + DrawRectangle(170, 30, 15, (int)(((1 + leftTrigger)/2)*70), RED); + DrawRectangle(604, 30, 15, (int)(((1 + rightTrigger)/2)*70), RED); //DrawText(TextFormat("Xbox axis LT: %02.02f", GetGamepadAxisMovement(gamepad, GAMEPAD_AXIS_LEFT_TRIGGER)), 10, 40, 10, BLACK); //DrawText(TextFormat("Xbox axis RT: %02.02f", GetGamepadAxisMovement(gamepad, GAMEPAD_AXIS_RIGHT_TRIGGER)), 10, 60, 10, BLACK); @@ -150,24 +174,24 @@ int main(void) // Draw axis: left joystick Color leftGamepadColor = BLACK; if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_LEFT_THUMB)) leftGamepadColor = RED; - DrawCircle(319, 255, 35, leftGamepadColor); + DrawCircle(319, 255, 35, BLACK); DrawCircle(319, 255, 31, LIGHTGRAY); - DrawCircle(319 + (int)(GetGamepadAxisMovement(gamepad, GAMEPAD_AXIS_LEFT_X) * 20), - 255 + (int)(GetGamepadAxisMovement(gamepad, GAMEPAD_AXIS_LEFT_Y) * 20), 25, leftGamepadColor); + DrawCircle(319 + (int)(leftStickX*20), + 255 + (int)(leftStickY*20), 25, leftGamepadColor); // Draw axis: right joystick Color rightGamepadColor = BLACK; if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_RIGHT_THUMB)) rightGamepadColor = RED; DrawCircle(475, 255, 35, BLACK); DrawCircle(475, 255, 31, LIGHTGRAY); - DrawCircle(475 + (int)(GetGamepadAxisMovement(gamepad, GAMEPAD_AXIS_RIGHT_X) * 20), - 255 + (int)(GetGamepadAxisMovement(gamepad, GAMEPAD_AXIS_RIGHT_Y) * 20), 25, rightGamepadColor); + DrawCircle(475 + (int)(rightStickX*20), + 255 + (int)(rightStickY*20), 25, rightGamepadColor); // Draw axis: left-right triggers DrawRectangle(169, 48, 15, 70, GRAY); DrawRectangle(611, 48, 15, 70, GRAY); - DrawRectangle(169, 48, 15, (int)(((1 - GetGamepadAxisMovement(gamepad, GAMEPAD_AXIS_LEFT_TRIGGER)) / 2) * 70), RED); - DrawRectangle(611, 48, 15, (int)(((1 - GetGamepadAxisMovement(gamepad, GAMEPAD_AXIS_RIGHT_TRIGGER)) / 2) * 70), RED); + DrawRectangle(169, 48, 15, (int)(((1 + leftTrigger)/2)*70), RED); + DrawRectangle(611, 48, 15, (int)(((1 + rightTrigger)/2)*70), RED); } else { From df38564f62de55bff8ba06575e597aef9581fc25 Mon Sep 17 00:00:00 2001 From: Cypress <140924725+cypressru@users.noreply.github.com> Date: Wed, 23 Oct 2024 15:03:50 +0000 Subject: [PATCH 169/208] Grammar fix in CONTRIBUTING.md (#4423) "Can you write some tutorial/example?" "Can you write some tutorials/examples?" --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 78f953baf..d70617c13 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -5,7 +5,7 @@ Hello contributors! Welcome to raylib! Do you enjoy raylib and want to contribute? Nice! You can help with the following points: - `C programming` - Can you write/review/test/improve the code? -- `Documentation/Tutorials/Example` - Can you write some tutorial/example? +- `Documentation/Tutorials/Example` - Can you write some tutorials/examples? - `Porting to other platforms` - Can you port/adapt/compile raylib on other systems? - `Web Development` - Can you help [with the website](https://github.com/raysan5/raylib.com)? - `Testing` - Can you find some bugs in raylib? From 6f4407cb1575f1c7528403c935267a59bd71f5e3 Mon Sep 17 00:00:00 2001 From: Franz Date: Wed, 23 Oct 2024 17:04:15 +0200 Subject: [PATCH 170/208] Fix typo in rshapes.c (#4421) --- src/rshapes.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rshapes.c b/src/rshapes.c index e9b5ca87b..1479a6f37 100644 --- a/src/rshapes.c +++ b/src/rshapes.c @@ -1650,7 +1650,7 @@ void DrawSplineLinear(const Vector2 *points, int pointCount, float thick, Color prevNormal = normal; } -#else // !SUPPORT_SPLINE_MITTERS +#else // !SUPPORT_SPLINE_MITERS Vector2 delta = { 0 }; float length = 0.0f; From 157ee79a8ee31f722a5c208d3ec095c8021ebf76 Mon Sep 17 00:00:00 2001 From: Asdqwe Date: Wed, 23 Oct 2024 15:31:57 -0300 Subject: [PATCH 171/208] Add drawing for generic gamepad on core_input_gamepad example (#4424) --- examples/core/core_input_gamepad.c | 60 ++++++++++++++++++++++++++++-- 1 file changed, 57 insertions(+), 3 deletions(-) diff --git a/examples/core/core_input_gamepad.c b/examples/core/core_input_gamepad.c index 43dc65499..538e1c389 100644 --- a/examples/core/core_input_gamepad.c +++ b/examples/core/core_input_gamepad.c @@ -119,7 +119,6 @@ int main(void) if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_RIGHT_TRIGGER_1)) DrawCircle(536, 61, 20, RED); // Draw axis: left joystick - Color leftGamepadColor = BLACK; if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_LEFT_THUMB)) leftGamepadColor = RED; DrawCircle(259, 152, 39, BLACK); @@ -195,9 +194,64 @@ int main(void) } else { - DrawText("- GENERIC GAMEPAD -", 280, 180, 20, GRAY); - // TODO: Draw generic gamepad + // Draw background: generic + DrawRectangleRounded((Rectangle){ 175, 110, 460, 220}, 0.3f, 0.0f, DARKGRAY); + + // Draw buttons: basic + DrawCircle(365, 170, 12, RAYWHITE); + DrawCircle(405, 170, 12, RAYWHITE); + DrawCircle(445, 170, 12, RAYWHITE); + DrawCircle(516, 191, 17, RAYWHITE); + DrawCircle(551, 227, 17, RAYWHITE); + DrawCircle(587, 191, 17, RAYWHITE); + DrawCircle(551, 155, 17, RAYWHITE); + if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_MIDDLE_LEFT)) DrawCircle(365, 170, 10, RED); + if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_MIDDLE)) DrawCircle(405, 170, 10, GREEN); + if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_MIDDLE_RIGHT)) DrawCircle(445, 170, 10, BLUE); + if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_RIGHT_FACE_LEFT)) DrawCircle(516, 191, 15, GOLD); + if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_RIGHT_FACE_DOWN)) DrawCircle(551, 227, 15, BLUE); + if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_RIGHT_FACE_RIGHT)) DrawCircle(587, 191, 15, GREEN); + if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_RIGHT_FACE_UP)) DrawCircle(551, 155, 15, RED); + + // Draw buttons: d-pad + DrawRectangle(245, 145, 28, 88, RAYWHITE); + DrawRectangle(215, 174, 88, 29, RAYWHITE); + DrawRectangle(247, 147, 24, 84, BLACK); + DrawRectangle(217, 176, 84, 25, BLACK); + if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_LEFT_FACE_UP)) DrawRectangle(247, 147, 24, 29, RED); + if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_LEFT_FACE_DOWN)) DrawRectangle(247, 147 + 54, 24, 30, RED); + if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_LEFT_FACE_LEFT)) DrawRectangle(217, 176, 30, 25, RED); + if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_LEFT_FACE_RIGHT)) DrawRectangle(217 + 54, 176, 30, 25, RED); + + // Draw buttons: left-right back + DrawRectangleRounded((Rectangle){ 215, 98, 100, 10}, 0.5f, 0.0f, DARKGRAY); + DrawRectangleRounded((Rectangle){ 495, 98, 100, 10}, 0.5f, 0.0f, DARKGRAY); + if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_LEFT_TRIGGER_1)) DrawRectangleRounded((Rectangle){ 215, 98, 100, 10}, 0.5f, 0.0f, RED); + if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_RIGHT_TRIGGER_1)) DrawRectangleRounded((Rectangle){ 495, 98, 100, 10}, 0.5f, 0.0f, RED); + + // Draw axis: left joystick + Color leftGamepadColor = BLACK; + if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_LEFT_THUMB)) leftGamepadColor = RED; + DrawCircle(345, 260, 40, BLACK); + DrawCircle(345, 260, 35, LIGHTGRAY); + DrawCircle(345 + (int)(leftStickX*20), + 260 + (int)(leftStickY*20), 25, leftGamepadColor); + + // Draw axis: right joystick + Color rightGamepadColor = BLACK; + if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_RIGHT_THUMB)) rightGamepadColor = RED; + DrawCircle(465, 260, 40, BLACK); + DrawCircle(465, 260, 35, LIGHTGRAY); + DrawCircle(465 + (int)(rightStickX*20), + 260 + (int)(rightStickY*20), 25, rightGamepadColor); + + // Draw axis: left-right triggers + DrawRectangle(151, 110, 15, 70, GRAY); + DrawRectangle(644, 110, 15, 70, GRAY); + DrawRectangle(151, 110, 15, (int)(((1 + leftTrigger)/2)*70), RED); + DrawRectangle(644, 110, 15, (int)(((1 + rightTrigger)/2)*70), RED); + } DrawText(TextFormat("DETECTED AXIS [%i]:", GetGamepadAxisCount(0)), 10, 50, 10, MAROON); From cd845368d8aca27ca99e3b9fbec8eff7904f5d65 Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 23 Oct 2024 23:28:01 +0200 Subject: [PATCH 172/208] Update skinning.fs --- examples/models/resources/shaders/glsl100/skinning.fs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/models/resources/shaders/glsl100/skinning.fs b/examples/models/resources/shaders/glsl100/skinning.fs index 98a9e5bad..96bcabe01 100644 --- a/examples/models/resources/shaders/glsl100/skinning.fs +++ b/examples/models/resources/shaders/glsl100/skinning.fs @@ -13,7 +13,7 @@ uniform vec4 colDiffuse; void main() { // Fetch color from texture sampler - vec4 texelColor = texture(texture0, fragTexCoord); + vec4 texelColor = texture2D(texture0, fragTexCoord); // Calculate final fragment color gl_FragColor = texelColor*colDiffuse*fragColor; From 708089f5602c5134d641a8f16850f31b8fb2798d Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 23 Oct 2024 23:29:05 +0200 Subject: [PATCH 173/208] Reviewed and reverted unneeded module check, `rtextures` should not depend on `rtext` --- src/rtextures.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/rtextures.c b/src/rtextures.c index a4534a7a2..23b32c1b8 100644 --- a/src/rtextures.c +++ b/src/rtextures.c @@ -1111,8 +1111,7 @@ Image GenImageText(int width, int height, const char *text) { Image image = { 0 }; -#if defined(SUPPORT_MODULE_RTEXT) - int textLength = TextLength(text); + int textLength = (int)strlen(text); int imageViewSize = width*height; image.width = width; @@ -1122,10 +1121,6 @@ Image GenImageText(int width, int height, const char *text) image.mipmaps = 1; memcpy(image.data, text, (textLength > imageViewSize)? imageViewSize : textLength); -#else - TRACELOG(LOG_WARNING, "IMAGE: GenImageText() requires module: rtext"); - image = GenImageColor(width, height, BLACK); // Generating placeholder black image rectangle -#endif return image; } From 6184a2db3d2104a1fa22dda470820f7387bf1007 Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 23 Oct 2024 23:29:49 +0200 Subject: [PATCH 174/208] ADDED: CHANGELOG for raylib 5.5 -WIP- --- CHANGELOG | 419 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 415 insertions(+), 4 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index b5b50e4d7..d215dcbc4 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -7,12 +7,423 @@ Current Release: raylib 5.0 (18 November 2023) Release: raylib 5.5 - 11th Anniversary Edition? (18 November 2024?) ------------------------------------------------------------------------- KEY CHANGES: - - - - - - + - New rcore backend: RGFW + - New raylib project creator tool + - New platforms supported: Dreamcast, N64, PSP, PSVita, PS4 + - GPU Skinning (all platforms and GPU versions) + - raymath C++ operators Detailed changes: -... +[rcore] ADDED: Working directory info at initialization by @Ray +[rcore] ADDED: `MakeDirectory()`, supporting recursive directory creation by @Ray +[rcore] ADDED: `ComputeSHA1()` (#4390) by @Anthony Carbajal +[rcore] ADDED: `ComputeCRC32()` and `ComputeMD5()` by @Ray +[rcore] ADDED: `GetKeyName()` (#4161) by @MrScautHD +[rcore] ADDED: `IsFileNameValid()` by @Ray +[rcore] ADDED: `GetViewRay()`, viewport independent raycast (#3709) by @Luís Almeida +[rcore] ADDED: Directory filtering to `LoadDirectoryFilesEx()`/`ScanDirectoryFiles()` (#4302) by @foxblock +[rcore] RENAMED: `GetMouseRay()` to `GetScreenToWorldRay()` (#3830) by @Ray +[rcore] RENAMED: `GetViewRay()` to `GetScreenToWorldRayEx()` (#3830) by @Ray +[rcore] REVIEWED: `GetApplicationDirectory()` for FreeBSD (#4318) by @base +[rcore] REVIEWED: Update comments on fullscreen and boderless window to describe what they do (#4280) by @Jeffery Myers +[rcore] REVIEWED: Automation events mouse wheel #4263 by @Ray +[rcore] REVIEWED: Fix gamepad axis movement and its automation event recording (#4184) by @maxmutant +[rcore] REVIEWED: Do not set RL_TEXTURE_FILTER_LINEAR when high dpi flag is enabled (#4189) by @Dave Green +[rcore] REVIEWED: `GetScreenWidth()`/`GetScreenHeight()` (#4074) by @Anthony Carbajal +[rcore] REVIEWED: Initial window dimensions checks (#3950) by @Christian Haas +[rcore] REVIEWED: Set default init values for random #3954 by @Ray +[rcore] REVIEWED: Window positioning, avoid out-of-screen window-bar by @Ray +[rcore] REVIEWED: Fix framerate recording for .gif (#3894) by @Rob Loach +[rcore] REVIEWED: Screen space related functions consistency (#3830) by @aiafrasinei +[rcore] REVIEWED: `GetFileNameWithoutExt()` (#3771) by @oblerion +[rcore] REVIEWED: `GetWindowScaleDPI()`, simplified (#3701) by @Karl Zylinski +[rcore] REVIEWED: `UnloadAutomationEventList()` (#3658) by @Antonis Geralis +[rcore] REVIEWED: Flip VR screens (#3633) by @Matthew Oros +[rcore] REVIEWED: Remove unused vScreenCenter (#3632) by @Matthew Oros +[rcore] REVIEWED: `LoadRandomSequence()`, issue in sequence generation #3612 by @Ray +[rcore] REVIEWED: `IsMouseButtonUp()` (#3609) by @Kenneth M +[rcore] REVIEWED: Fix typos in src/platforms/rcore_*.c (#3581) by @RadsammyT +[rcore] REVIEWED: `ExportDataAsCode()`, change sanitization check (#3837) by @Laurentino Luna +[rcore] REVIEWED: `ExportDataAsCode()`, add little sanitization to indentifier names (#3832) by @4rk +[rcore][rlgl] REVIEWED: Fix scale issues when ending a view mode (#3746) by @Jeffery Myers +[rcore][GLFW] REVIEWED: Keep CORE.Window.position properly in sync with glfw window position (#4190) by @Dave Green +[rcore][GLFW] REVIEWED: Set AUTO_ICONIFY flag to false per default (#4188) by @Dave Green +[rcore][GLFW] REVIEWED: `InitPlatform()`, add workaround for NetBSD (#4139) by @NishiOwO +[rcore][GLFW] REVIEWED: Fix window not initializing on primary monitor (#3923) by @Rafael Bordoni +[rcore][GLFW] REVIEWED: Set relative mouse mode when the cursor is disabled (#3874) by @Jeffery Myers +[rcore][GLFW] REVIEWED: Remove GLFW mouse passthrough hack and increase GLFW version in CMake (#3852) by @Alexandre Almeida +[rcore][GLFW] REVIEWED: Updated GLFW to 3.4 (#3827) by @Alexandre Almeida +[rcore][GLFW] REVIEWED: Feature test macros before include (#3737) by @John +[rcore][Web] ADDED: `SetWindowOpacity()` implementation (#4403) by @Asdqwe +[rcore][Web] ADDED: `MaximizeWindow()` and `RestoreWindow()` implementations (#4397) by @Asdqwe +[rcore][Web] ADDED: `ToggleFullscreen()` implementation (#3634) by @ubkp +[rcore][Web] ADDED: `GetWindowPosition()` implementation (#3637) by @ubkp +[rcore][Web] ADDED: `ToggleBorderlessWindowed()` implementation (#3622) by @ubkp +[rcore][Web] ADDED: `GetMonitorWidth()` and `GetMonitorHeight()` implementations (#3636) by @ubkp +[rcore][Web] REVIEWED: Update `SetWindowState()` and `ClearWindowState()` to handle `FLAG_WINDOW_MAXIMIZED` (#4402) by @Asdqwe +[rcore][Web] REVIEWED: `WindowSizeCallback()`, do not try to handle DPI, already managed by GLFW (#4143) by @SuperUserNameMan +[rcore][Web] REVIEWED: Relative mouse mode issues (#3940) by @Cemal Gönültaş +[rcore][Web] REVIEWED: `ShowCursor()`, `HideCursor()` and `SetMouseCursor()` (#3647) by @ubkp +[rcore][Web] REVIEWED: Fix CORE.Input.Mouse.cursorHidden with callbacks (#3644) by @ubkp +[rcore][Web] REVIEWED: Fix `IsMouseButtonUp()` (#3611) by @ubkp +[rcore][Web] REVIEWED: HighDPI support #3372 by @Ray +[rcore][SDL] ADDED: `IsCursorOnScreen()` (#3862) by @Peter0x44 +[rcore][SDL] ADDED: Gamepad rumble/vibration support (#3819) by @GideonSerf +[rcore][SDL] REVIEWED: Gamepad support (#3776) by @A +[rcore][SDL] REVIEWED: `GetWorkingDirectory()`, return correct path (#4392) by @Asdqwe +[rcore][SDL] REVIEWED: `GetClipboardText()`, fix memory leak (#4354) by @Asdqwe +[rcore][SDL] REVIEWED: Change SDL_Joystick to SDL_GameController (#4129) by @Frank Kartheuser +[rcore][SDL] REVIEWED: Update storage base path, use provided SDL base path by @Ray +[rcore][SDL] REVIEWED: Call SDL_GL_SetSwapInterval() after GL context creation (#3997) by @JupiterRider +[rcore][SDL] REVIEWED: `GetKeyPressed()` (#3869) by @Arthur +[rcore][SDL] REVIEWED: Fix SDL multitouch tracking (#3810) by @mooff +[rcore][SDL] REVIEWED: Fix `SUPPORT_WINMM_HIGHRES_TIMER` (#3679) by @ubkp +[rcore][SDL] REVIEWED: SDL text input to Unicode codepoints #3650 by @Ray +[rcore][SDL] REVIEWED: `IsMouseButtonUp()` and add touch events (#3610) by @ubkp +[rcore][SDL] REVIEWED: Fix real touch gestures (#3614) by @ubkp +[rcore][SDL] REVIEWED: `IsKeyPressedRepeat()` (#3605) by @ubkp +[rcore][SDL] REVIEWED: `GetKeyPressed()` and `GetCharPressed()` for SDL (#3604) by @ubkp +[rcore][SDL] REVIEWED: `SetMousePosition()` for SDL (#3580) by @ubkp +[rcore][SDL] REVIEWED: `SetWindowIcon()` for SDL (#3578) by @ubkp +[rcore][SDL][rlgl] REVIEWED: Fix for running gles2 with SDL on desktop (#3542) by @_Tradam +[rcore][Android] REVIEWED: Issue with isGpuReady flag (#4340) by @Menno van der Graaf +[rcore][Android] REVIEWED: Allow main() to return it its caller on configuration changes (#4288) by @Hesham Abourgheba +[rcore][Android] REVIEWED: Replace deprecated Android function ALooper_pollAll with ALooper_pollOnce (#4275) by @Menno van der Graaf +[rcore][Android] REVIEWED: `PollInputEvents()`, register previous gamepad events (#3910) by @Aria +[rcore][Android] REVIEWED: Fix Android keycode translation and duplicate key constants (#3733) by @Alexandre Almeida +[rcore][DRM] ADDED: uConsole keys mapping (#4297) by @carverdamien +[rcore][DRM] ADDED: `GetMonitorWidth/Height()` (#3956) by @gabriel-marques +[rcore][DRM] REVIEWED: `IsMouseButtonUp()` (#3611) by @ubkp +[rcore][DRM] REVIEWED: Optimize gesture handling (#3616) by @ubkp +[rcore][DRM] REVIEWED: `IsKeyPressedRepeat()` for PLATFORM_DRM direct input (#3583) by @ubkp +[rcore][DRM] REVIEWED: Fix gamepad buttons not working in drm backend (#3888) by @MrMugame +[rcore][DRM] REVIEWED: DRM backend to only use one api to allow for more devices (#3879) by @MrMugame +[rcore][DRM] REVIEWED: Avoid separate thread when polling for gamepad events (#3641) by @Cinghy Creations +[rcore][DRM] REVIEWED: Connector status reported as UNKNOWN but should be considered as CONNECTED (#4305) by @Michał Jaskólski +[rcore][RGFW] ADDED: RGFW, new rcore backend platform (#3941) by @Colleague Riley +[rcore][RGFW] REVIEWED: RGFW 1.0 (#4144) by @Colleague Riley +[rcore][RGFW] REVIEWED: Fix errors when compiling with mingw (#4282) by @Colleague Riley +[rcore][RGFW] REVIEWED: Replace long switch with a lookup table (#4108) by @Colleague Riley +[rlgl] ADDED: More uniform data type options #4137 by @Ray +[rlgl] ADDED: Vertex normals for RLGL immediate drawing mode (#3866) by @bohonghuang +[rlgl] ADDED: `rlCullDistance*()` variables and getters (#3912) by @KotzaBoss +[rlgl] ADDED: `rlSetClipPlanes()` function (#3912) by @KotzaBoss +[rlgl] ADDED: `isGpuReady` flag, allow font loading with no GPU acceleration by @Ray -WARNING- +[rlgl] REVIEWED: Changed RLGL_VERSION from 4.5 to 5.0 (#3914) by @Mute +[rlgl] REVIEWED: Shader load failing returns 0, instead of fallback by @Ray -WARNING- +[rlgl] REVIEWED: Standalone mode default flags (#4334) by @Asdqwe +[rlgl] REVIEWED: Fix hardcoded index values in vboID array (#4312) by @Jett +[rlgl] REVIEWED: GLint64 did not exist before OpenGL 3.2 (#4284) by @Tchan0 +[rlgl] REVIEWED: Extra warnings in case OpenGL 4.3 is not enabled (#4202) by @Maxim Knyazkin +[rlgl] REVIEWED: Using GLint64 for glGetBufferParameteri64v() (#4197) by @Randy Palamar +[rlgl] REVIEWED: Replace `glGetInteger64v()` with `glGetBufferParameteri64v()` (#4154) by @Kai Kitagawa-Jones +[rlgl] REVIEWED: `rlMultMatrixf()`, fix matrix multiplication order (#3935) by @bohonghuang +[rlgl] REVIEWED: `rlSetVertexAttribute()`, define last parameter as offset #3800 by @Ray +[rlgl] REVIEWED: `rlDisableVertexAttribute()`, remove redundat calls for SHADER_LOC_VERTEX_COLOR (#3871) by @Kacper Zybała +[rlgl] REVIEWED: `rlLoadFramebuffer()`, parameters not required by @Ray +[rlgl] REVIEWED: `rlSetUniformSampler()` (#3759) by @veins1 +[rlgl] REVIEWED: Renamed near/far variables (#4039) by @jgabaut +[rlgl] REVIEWED: Expose OpenGL symbols (#3588) by @Peter0x44 +[rlgl] REVIEWED: Fix OpenGL 1.1 build issues (#3876) by @Ray +[rlgl] REVIEWED: Fixed compilation for OpenGL ES (#4243) by @Maxim Knyazkin +[rlgl] REVIEWED: rlgl function description and comments by @Ray +[rlgl] REVIEWED: Expose glad functions when building raylib as a shared lib (#3572) by @Peter0x44 +[rlgl] REVIEWED: Fix version info in rlgl.h (#3558) by @Steven Schveighoffer +[rcamera] REVIEWED: Make camera movement independant of framerate (#4247) by @hanaxars -WARNING- +[rcamera] REVIEWED: Updated camera speeds with GetFrameTime() (#4362) by @Anthony Carbajal +[rcamera] REVIEWED: `UpdateCamera()`, added CAMERA_CUSTOM check (#3938) by @Tomas Fabrizio Orsi +[rcamera] REVIEWED: Support mouse/keyboard and gamepad coexistence for input (#3579) by @ubkp +[rcamera] REVIEWED: Cleaned away unused macros(#3762) by @Brian E +[rcamera] REVIEWED: Fix for free camera mode (#3603) by @lesleyrs +[rcamera] REVIEWED: `GetCameraRight()` (#3784) by @Danil +[raymath] ADDED: C++ operator overloads for common math function (#4385) by @Jeffery Myers +[raymath] ADDED: Vector4 math functions and Vector2 variants of some Vector3 functions (#3828) by @Bowserinator +[raymath] REVIEWED: Fix MSVC warnings/errors in C++ (#4125) by @Jeffery Myers +[raymath] REVIEWED: Add extern "C" to raymath header for C++ (#3978) by @Jeffery Myers +[raymath] REVIEWED: `QuaternionFromAxisAngle()`, remove redundant axis length calculation (#3900) by @jtainer +[raymath] REVIEWED: `Vector3Perpendicular()`, avoid implicit conversion from float to double (#3799) by @João Foscarini +[raymath] REVIEWED: Small code refactor (#3753) by @Idir Carlos Aliane +[rshapes] ADDED: `CheckCollisionCircleLine()` (#4018) by @kai-z99 +[rshapes] REVIEWED: Multisegment Bezier splines (#3744) by @Santiago Pelufo +[rshapes] REVIEWED: Expose shapes drawing texture and rectangle (#3677) by @Jeffery Myers +[rshapes] REVIEWED: `DrawLine()` #4075 by @Ray +[rshapes] REVIEWED: `DrawPixel()` drawing by @Ray +[rshapes] REVIEWED: `DrawLine()` to avoid pixel rounding issues #3931 by @Ray +[rshapes] REVIEWED: `DrawRectangleLinesEx()`, make sure accounts for square tiles (#4382) by @Jojaby +[rshapes] REVIEWED: `DrawRectangleLines()`, pixel offset when scaling (#3884) by @Ray +[rshapes] REVIEWED: `Draw*Gradient()` color parameter names (#4270) by @Paperdomo101 +[rshapes] REVIEWED: `DrawGrid()`, remove duplicate color calls (#4148) by @Jeffery Myers +[rshapes] REVIEWED: `DrawSplineLinear()` to `SUPPORT_SPLINE_MITERS` by @Ray +[rshapes] REVIEWED: `DrawSplineLinear()`, implement miters (#3585) by @Toctave +[rshapes] REVIEWED: `CheckCollisionPointRec()` by @Ray +[rshapes] REVIEWED: `CheckCollisionPointCircle()`, new implementation (#4135) by @kai-z99 +[rshapes] REVIEWED: `CheckCollisionCircles()`, optimized (#4065) by @kai-z99 +[rshapes] REVIEWED: `CheckCollisionPointPoly()` (#3750) by @Antonio Raúl +[rshapes] REVIEWED: `CheckCollisionCircleRec()` (#3584) by @ubkp +[rshapes] REVIEWED: Add more detail to function comment (#4344) by @Jeffery Myers +[rshapes] REVIEWED: Functions that draw point arrays take them as const (#4051) by @Jeffery Myers +[rtextures] ADDED: `ColorIsEqual()` by @Ray +[rtextures] ADDED: `ColorLerp()`, to mix 2 colors together (#4310) by @SusgUY446 +[rtextures] ADDED: `LoadImageAnimFromMemory()` (#3681) by @IoIxD +[rtextures] ADDED: `ImageKernelConvolution()` (#3528) by @Karim +[rtextures] ADDED: `ImageFromChannel()` (#4105) by @Bruno Cabral +[rtextures] ADDED: `ImageDrawLineEx()` (#4097) by @Le Juez Victor +[rtextures] ADDED: `ImageDrawTriangle()` (#4094) by @Le Juez Victor +[rtextures] REMOVED: SVG files loading and drawing, moving it to raylib-extras by @Ray -WARNING- +[rtextures] REVIEWED: `LoadImage()`, added support for 3-channel QOI images (#4384) by @R-YaTian +[rtextures] REVIEWED: `LoadImageRaw()` #3926 by @Ray +[rtextures] REVIEWED: `LoadImageColors()`, advance k in loop (#4120) by @Bruno Cabral +[rtextures] REVIEWED: `LoadTextureCubemap()`, added `mipmaps` #3665 by @Ray +[rtextures] REVIEWED: `LoadTextureCubemap(), assign format to cubemap (#3823) by @Gary M +[rtextures] REVIEWED: `LoadImageFromScreen()`, fix scaling (#3881) by @proberge-dev +[rtextures] REVIEWED: `LoadImageFromMemory()`, warnings on invalid image data (#4179) by @Jutastre +[rtextures] REVIEWED: `LoadImageAnimFromMemory()`, added security checks (#3924) by @Ray +[rtextures] REVIEWED: `ImageColorTint()` and `ColorTint()`, optimized (#4015) by @Le Juez Victor +[rtextures] REVIEWED: `ImageKernelConvolution()`, formating and warnings by @Ray +[rtextures] REVIEWED: `ImageDrawRectangleRec`, fix bounds check (#3732) by @Blockguy24 +[rtextures] REVIEWED: `ImageResizeCanvas()`, implemented fill color (#3720) by @Lieven Petersen +[rtextures] REVIEWED: `ImageDrawRectangleRec()` (#3721) by @Le Juez Victor +[rtextures] REVIEWED: `ImageDraw()`, don't try to blend images without alpha (#4395) by @Nikolas +[rtextures] REVIEWED: `GenImagePerlinNoise()` being stretched (#4276) by @Bugsia +[rtextures] REVIEWED: `DrawTexturePro()` to avoid negative dest rec #4316 by @Ray +[rtextures] REVIEWED: `ColorToInt()`, fix undefined behaviour (#3996) by @OetkenPurveyorOfCode +[rtextures] REVIEWED: Simplified for loop for some image manipulation functions (#3712) by @Alice Nyaa +[rtext] ADDED: BDF fonts support (#3735) by @Stanley Fuller -WARNING- +[rtext] ADDED: `TextToCamel()` (#4033) by @IoIxD +[rtext] ADDED: `TextToSnake()` (#4033) by @IoIxD +[rtext] REDESIGNED: `SetTextLineSpacing()` by @Ray -WARNING- +[rtext] REVIEWED: `LoadFontDataBDF()` name and formating by @Ray +[rtext] REVIEWED: `LoadFontDefault()`, initialize glyphs and recs to zero #4319 by @Ray +[rtext] REVIEWED: `LoadFontEx()`, avoid default font fallback (#4077) by @Peter0x44 -WARNING- +[rtext] REVIEWED: `LoadBMFont()`, extended functionality (#3536) by @Dongkun Lee +[rtext] REVIEWED: `LoadBMFont()`, issue on not glyph data initialized by @Ray +[rtext] REVIEWED: `LoadFontFromMemory()`, use strncpy() to fix buffer overflow (#3795) by @Mingjie Shen +[rtext] REVIEWED: `LoadCodepoints()` returning a freed ptr when count is 0 (#4089) by @Alice Nyaa +[rtext] REVIEWED: `LoadFontData()` avoid fallback glyphs by @Ray -WARNING- +[rtext] REVIEWED: `LoadFontData()`, load image only if glyph has been found in font by @Ray +[rtext] REVIEWED: `ExportFontAsCode()`, fix C++ compiler errors (#4013) by @DarkAssassin23 +[rtext] REVIEWED: `MeasureTextEx()` height calculation (#3770) by @Marrony Neris +[rtext] REVIEWED: `CodepointToUTF8()`, clean static buffer #4379 by @Ray +[rtext] REVIEWED: `TextToFloat()`, always multiply by sign (#4273) by @listeria +[rtext] REVIEWED: `TextReplace()` const correctness (#3678) by @maverikou +[rtext] REVIEWED: `TextToFloat()`, coding style (#3627) by @Benjamin Schmid Ties +[rtext] REVIEWED: Some comments to align to style (#3756) by @Idir Carlos Aliane +[rtext] REVIEWED: Adjust font atlas area calculation so padding area is not underestimated at small font sizes (#3719) by @Tim Romero +[rmodels] ADDED: GPU skinning support for models animations (#4321) by @Daniel Holden -WARNING- +[rmodels] ADDED: Support 16-bit unsigned short vec4 format for gltf joint loading (#3821) by @Gary M +[rmodels] ADDED: Support animation names for the m3d model format (#3714) by @kolunmi +[rmodels] ADDED: `DrawModelPoints()`, more performant point cloud rendering (#4203) by @Reese Gallagher +[rmodels] ADDED: `ExportMeshAsCode()` by @Ray +[rmodels] REVIEWED: Multiple updates to gltf loading, improved macro (#4373) by @Harald Scheirich +[rmodels] REVIEWED: `LoadOBJ()`, correctly split obj meshes by material (#4285) by @Jeffery Myers +[rmodels] REVIEWED: `LoadOBJ()`, add warning when loading an OBJ with multiple materials (#4271) by @Jeffery Myers +[rmodels] REVIEWED: `LoadIQM()`, set model.meshMaterial[] (#4092) by @SuperUserNameMan +[rmodels] REVIEWED: `LoadIQM()`, attempt to load texture from IQM at loadtime (#4029) by @Jett +[rmodels] REVIEWED: `LoadM3D(), fix vertex colors for m3d files (#3859) by @Jeffery Myers +[rmodels] REVIEWED: `LoadGLTF()`, supporting additional vertex data formats (#3546) by @MrScautHD +[rmodels] REVIEWED: `LoadGLTF()`, correctly handle the node hierarchy in a glTF file (#4037) by @Paul Melis +[rmodels] REVIEWED: `LoadGLTF()`, replaced SQUAD quat interpolation with cubic hermite (gltf 2.0 specs) (#3920) by @Benji +[rmodels] REVIEWED: `LoadGLTF()`, support 2nd texture coordinates loading by @Ray +[rmodels] REVIEWED: `LoadGLTF()`, support additional vertex attributes data formats #3890 by @Ray +[rmodels] REVIEWED: `LoadGLTF()`, set cgltf callbacks to use `LoadFileData()` and `UnloadFileData()` (#3652) by @kolunmi +[rmodels] REVIEWED: `LoadGLTF()`, JOINTS loading #3836 by @Ray +[rmodels] REVIEWED: `LoadImageFromCgltfImage()`, fix base64 padding support (#4112) by @SuperUserNameMan +[rmodels] REVIEWED: `LoadModelAnimationsIQM()`, fix corrupted animation names (#4026) by @Jett +[rmodels] REVIEWED: `LoadModelAnimationsGLTF()`, load animations with 1 frame (#3804) by @Nikita Blizniuk +[rmodels] REVIEWED: `LoadModelAnimationsGLTF()`, added missing interpolation types (#3919) by @Benji +[rmodels] REVIEWED: `LoadModelAnimationsGLTF()` (#4107) by @VitoTringolo +[rmodels] REVIEWED: `LoadBoneInfoGLTF()`, add check for animation name being NULL (#4053) by @VitoTringolo +[rmodels] REVIEWED: `GenMeshTangents()`, read uninitialized values, fix bounding case (#4066) by @kai-z99 +[rmodels] REVIEWED: `GenMeshTangents()`, fixed out of bounds error (#3990) by @Salvador Galindo +[rmodels] REVIEWED: `DrawCylinder()`, fix drawing due to imprecise angle (#4034) by @Paul Melis +[rmodels] REVIEWED: `DrawMesh()`, send full matModel to shader in DrawMesh (#4005) (#4022) by @David Holland +[rmodels] REVIEWED: `DrawMesh()`, fix material specular map retrieval (#3758) by @Victor Gallet +[rmodels] REVIEWED: `DrawModelEx()`, simplified multiplication of colors (#4002) by @Le Juez Victor +[rmodels] REVIEWED: `DrawBillboardPro()`, to be consistend with `DrawTexturePro()` (#4132) by @bohonghuang +[rmodels] REVIEWED: `DrawSphereEx()` optimization (#4106) by @smalltimewizard +[raudio] REVIEWED: `LoadMusicStreamFromMemory()`, support 24-bit FLACs (#4279) by @konstruktor227 +[raudio] REVIEWED: `LoadWaveSamples()`, fix mapping of wave data (#4062) by @listeria +[raudio] REVIEWED: `LoadMusicStream()`, remove drwav_uninit() (#3986) by @FishingHacks +[raudio] REVIEWED: `LoadMusicStream()` qoa and wav loading (#3966) by @veins1 +[raudio] REVIEWED: `ExportWaveAsCode()`, segfault (#3769) by @IoIxD +[raudio] REVIEWED: `WaveCrop()`, fix issues and use frames instead of samples (#3994) by @listeria +[raudio] REVIEWED: Crash from multithreading issues (#3907) by @Christian Haas +[raudio] REVIEWED: Reset music.ctxType if loading wasn't succesful (#3917) by @veins1 +[raudio] REVIEWED: Added missing functions in "standalone" mode (#3760) by @Alessandro Nikolaev +[raudio] REVIEWED: Disable unused miniaudio features (#3544) by @Alexandre Almeida +[raudio] REVIEWED: Fix crash when switching playback device at runtime (#4102) by @jkaup +[raudio] REVIEWED: Support 24 bits samples for FLAC format (#4058) by @Alexey Kutepov +[examples] ADDED: `core_random_sequence` (#3846) by @Dalton Overmyer +[examples] ADDED: `models_bone_socket` (#3833) by @iP +[examples] ADDED: `shaders_vertex_displacement` (#4186) by @Alex ZH +[examples] ADDED: `shaders_shadowmap` (#3653) by @TheManTheMythTheGameDev +[examples] REVIEWED: `core_2d_camera_platformer` by @Ray +[examples] REVIEWED: `core_2d_camera_mouse_zoom`, use logarithmic scaling for a 2d zoom functionality (#3977) by @Mike Will +[examples] REVIEWED: `core_input_gamepad_info`, all buttons displayed within the window (#4241) by @Asdqwe +[examples] REVIEWED: `core_input_gamepad_info`, show ps3 controller (#4040) by @Konrad Gutvik Grande +[examples] REVIEWED: `shapes_bouncing_ball` (#4226) by @Anthony Carbajal +[examples] REVIEWED: `shapes_following_eyes` (#3710) by @Hongyu Ouyang +[examples] REVIEWED: `shapes_draw_rectangle_rounded` by @Ray +[examples] REVIEWED: `shapes_draw_ring`, fix other examples (#4211) by @kai-z99 +[examples] REVIEWED: `shapes_lines_bezier` by @Ray +[examples] REVIEWED: `textures_image_kernel` #3556 by @Ray +[examples] REVIEWED: `text_input_box` (#4229) by @Anthony Carbajal +[examples] REVIEWED: `text_writing_anim` (#4230) by @Anthony Carbajal +[examples] REVIEWED: `models_billboard` by @Ray +[examples] REVIEWED: `models_cubicmap` by @Ray +[examples] REVIEWED: `models_point_rendering` by @Ray +[examples] REVIEWED: `models_box_collisions` (#4224) by @Anthony Carbajal +[examples] REVIEWED: `models_skybox`, do not use HDR by default (#4115) by @Jeffery Myers +[examples] REVIEWED: `shaders_basic_pbr` (#4225) by @Anthony Carbajal +[examples] REVIEWED: `shaders_palette_switch` by @Ray +[examples] REVIEWED: `shaders_hybrid_render` (#3908) by @Yousif +[examples] REVIEWED: `shaders_lighting_instancing`, fix vertex shader (#4056) by @Karl Zylinski +[examples] REVIEWED: `shaders_raymarching`, add `raymarching.fs` for GLSL120 (#4183) by @CDM15y +[examples] REVIEWED: `shaders_shadowmap`, fix shaders for GLSL 1.20 (#4167) by @CDM15y +[examples] REVIEWED: `shaders_deferred_render` (#3655) by @Jett +[examples] REVIEWED: `shaders_basic_pbr` (#3621) by @devdad +[examples] REVIEWED: `shaders_basic_pbr`, remove dependencies (#3649) by @TheManTheMythTheGameDev +[examples] REVIEWED: `shaders_basic_pbr`, added more comments by @Ray +[examples] REVIEWED: `audio_stream_effects` (#3618) by @lipx +[examples] REVIEWED: `audio_raw_stream` (#3624) by @riadbettole +[examples] REVIEWED: `audio_mixed_processor` (#4214) by @Anthony Carbajal +[examples] REVIEWED: `raylib_opengl_interop`, fix building on PLATFORM_DESKTOP_SDL (#3826) by @Peter0x44 +[examples] REVIEWED: Update examples missing UnloadTexture() calls (#4234) by @Anthony Carbajal +[examples] REVIEWED: Added GLSL 100 and 120 shaders to lightmap example (#3543) by @Jussi Viitala +[examples] REVIEWED: Set FPS to always 60 in all exampels (#4235) by @Anthony Carbajal +[build] REVIEWED: Makefile by @Ray +[build] REVIEWED: Makefile, fix wrong flag #3593 by @Ray +[build] REVIEWED: Makefile, disable wayland by default (#4369) by @Anthony Carbajal +[build] REVIEWED: Makefile, VSCode, fix to support multiple .c files (#4391) by @Alan Arrecis +[build] REVIEWED: Makefile, fix -Wstringop-truncation warning (#4096) by @Peter0x44 +[build] REVIEWED: Makefile, fix issues for RGFW on Linux/macOS (#3969) by @Colleague Riley +[build] REVIEWED: Makefile, update RAYLIB_VERSION (#3901) by @Belllg +[build] REVIEWED: Makefile (#4054) by @Lázaro Albuquerque +[build] REVIEWED: Makefile examples, align /usr/local with /src Makefile (#4286) by @Tchan0 +[build] REVIEWED: Makefile examples, added `textures_image_kernel` (#3555) by @Sergey Zapunidi +[build] REVIEWED: Makefile examples (#4209) by @Anthony Carbajal +[build] REVIEWED: build.zig, fix various issues around `-Dconfig` (#4398) by @Sage Hane +[build] REVIEWED: build.zig, fix type mismatch (#4383) by @yuval_dev +[build] REVIEWED: build.zig, minor fixes (#4381) by @Sage Hane +[build] REVIEWED: build.zig, fix @src logic and a few things (#4380) by @Sage Hane +[build] REVIEWED: build.zig, improve logic (#4375) by @Sage Hane +[build] REVIEWED: build.zig, issues (#4374) by @William Culver +[build] REVIEWED: build.zig, issues (#4366) by @Visen +[build] REVIEWED: build.zig, support desktop backend change (#4358) by @Nikolas +[build] REVIEWED: build.zig, use zig fmt (#4242) by @freakmangd +[build] REVIEWED: build.zig, check if wayland-scanner is installed (#4217) by @lnc3l0t +[build] REVIEWED: build.zig, override config.h definitions (#4193) by @lnc3l0t +[build] REVIEWED: build.zig, support GLFW platform detection (#4150) by @InventorXtreme +[build] REVIEWED: build.zig, make emscripten build compatible with Zig 0.13.0 (#4121) by @Mike Will +[build] REVIEWED: build.zig, pass the real build.zig file (#4113) by @InKryption +[build] REVIEWED: build.zig, leverage `dependencyFromBuildZig` (#4109) by @InKryption +[build] REVIEWED: build.zig, run examples from their directories (#4063) by @Mike Will +[build] REVIEWED: build.zig, fix raygui build when using addRaygui externally (#4027) by @Viktor Pocedulić +[build] REVIEWED: build.zig, fix emscripten build (#4012) by @Dylan +[build] REVIEWED: build.zig, update to zig 0.12.0dev while keeping 0.11.0 compatibility (#3715) by @freakmangd +[build] REVIEWED: build.zig, drop support for 0.11.0 and use more idiomatic build script code (#3927) by @freakmangd +[build] REVIEWED: build.zig, sdd shared library build option and update to zig 0.12.0-dev.2139 (#3727) by @Andrew Lee +[build] REVIEWED: build.zig, add `opengl_version` option (#3979) by @Alexei Mozaidze +[build] REVIEWED: build.zig, fix local dependency break (#3913) by @freakmangd +[build] REVIEWED: build.zig, fix breaking builds for Zig v0.11.0 (#3896) by @iarkn +[build] REVIEWED: build.zig, update to latest version and simplify (#3905) by @freakmangd +[build] REVIEWED: build.zig, remove all uses of deps/mingw (#3805) by @Peter0x44 +[build] REVIEWED: build.zig, fixed illegal instruction crash (#3682) by @WisonYe +[build] REVIEWED: build.zig, fix broken build on #3863 (#3891) by @Nikolas Mauropoulos +[build] REVIEWED: CMake, update to raylib 5.0 (#3623) by @Peter0x44 +[build] REVIEWED: CMake, added PLATFORM option for Desktop SDL (#3809) by @mooff +[build] REVIEWED: CMake, fix GRAPHICS_* check (#4359) by @Kacper Zybała +[build] REVIEWED: CMake, examples projects (#4332) by @Ridge3Dproductions +[build] REVIEWED: CMake, fix warnings in projects/CMake/CMakeLists.txt (#4278) by @Peter0x44 +[build] REVIEWED: CMake, delete BuildOptions.cmake (#4277) by @Peter0x44 +[build] REVIEWED: CMake, update version to 5.0 so libraries are correctly versioned (#3615) by @David Williams +[build] REVIEWED: CMake, improved linkage flags to save 28KB on the final bundle (#4177) by @Lázaro Albuquerque +[build] REVIEWED: CMake, support OpenGL ES3 in `LibraryConfigurations.cmake` (#4079) by @manuel5975p +[build] REVIEWED: CMake, `config.h` fully available to users (#4044) by @Lázaro Albuquerque +[build] REVIEWED: CMake, pass -sFULL_ES3 instead of -sFULL_ES3=1 (#4090) by @manuel5975p +[build] REVIEWED: CMake, SDL build link the glfw dependency (#3860) by @Rob Loach +[build] REVIEWED: CMake, infer CMAKE_MODULE_PATH in super-build (#4042) by @fruzitent +[build] REVIEWED: CMake, remove USE_WAYLAND option (#3851) by @Alexandre Almeida +[build] REVIEWED: CMake, disable SDL rlgl_standalone example (#3861) by @Rob Loach +[build] REVIEWED: CMake, bump version required to avoid deprecated #3639 by @Ray +[build] REVIEWED: CMake, fix examples linking -DPLATFORM=SDL (#3825) by @Peter0x44 +[build] REVIEWED: VS2022 project by @Ray +[build] REVIEWED: VS2022, fix build warnings (#4095) by @Jeffery Myers +[build] REVIEWED: Fix fix-build-paths (#3849) by @Caleb Barger +[build] REVIEWED: Fix build paths (#3835) by @Steve Biedermann +[build] REVIEWED: Fix VSCode sample project for macOS (#3666) by @Tim Romero +[build] REVIEWED: Fix some warnings on web builds and remove some redundant flags (#4069) by @Lázaro Albuquerque +[build] REVIEWED: Fix examples not building with gestures system disabled (#4020) by @Sprix +[build] REVIEWED: Fix GLFW runtime platform detection (#3863) by @Alexandre Almeida +[build] REVIEWED: Fix DRM cross-compile without sysroot (#3839) by @Christian W. Zuckschwerdt +[build] REVIEWED: Fix cmake-built libraylib.a to properly include GLFW's object files (#3598) by @Peter0x44 +[build] REVIEWED: Hide unneeded internal symbols when building raylib as an so or dylib (#3573) by @Peter0x44 +[build] REVIEWED: Corrected the path of android ndk toolchains for OSX platforms (#3574) by @Emmanuel Méra +[build][CI] ADDED: Automatic update for raylib_api.* (#3692) by @seiren +[build][CI] REVIEWED: Update workflows to use latest actions/upload-artifact by @Ray +[build][CI] REVIEWED: CodeQL minor tweaks to avoid some warnings by @Ray +[build][CI] REVIEWED: Update linux_examples.yml by @Ray +[build][CI] REVIEWED: Update linux.yml by @Ray +[build][CI] REVIEWED: Update webassembly.yml by @Ray +[build][CI] REVIEWED: Update cmake.yml by @Ray +[build][CI] REVIEWED: Update codeql.yml, exclude src/external files by @Ray +[bindings] ADDED: raylib-APL (#4253) by @Brian E +[bindings] ADDED: raylib-bqn, moved rayed-bqn (#4331) by @Brian E +[bindings] ADDED: brainfuck binding (#4169) by @_Tradam +[bindings] ADDED: raylib-zig-bindings (#4004) by @Lionel Briand +[bindings] ADDED: Raylib-CSharp wrapper (#3963) by @MrScautHD +[bindings] ADDED: COBOL binding (#3661) by @glowiak +[bindings] ADDED: raylib-beef binding (#3640) by @Braedon Lewis +[bindings] ADDED: Raylib-CSharp-Vinculum (#3571) by @Danil +[bindings] REVIEWED: Remove broken-link bindings #3899 by @Ray +[bindings] REVIEWED: Updated some versions on BINDINGS.md by @Ray +[bindings] REVIEWED: Removed umaintained repos (#3999) by @Antonis Geralis +[bindings] REDESIGNED: Add binding link to name, instead of separate column (#3995) by @Carmine Pietroluongo +[bindings] UPDATED: h-raylib (#4378) by @Anand Swaroop +[bindings] UPDATED: Raylib.lean, to master version (#4337) by @Daniil Kisel +[bindings] UPDATED: raybit, to latest master (#4311) by @Alex +[bindings] UPDATED: dray binding (#4163) by @red thing +[bindings] UPDATED: Julia (#4068) by @ShalokShalom +[bindings] UPDATED: nim to latest master (#3999) by @Antonis Geralis +[bindings] UPDATED: raylib-rs (#3991) by @IoIxD +[bindings] UPDATED: raylib-zig version (#3902) by @Nikolas +[bindings] UPDATED: raylib-odin (#3868) by @joyousblunder +[bindings] UPDATED: Raylib VAPI (#3829) by @Alex Macafee +[bindings] UPDATED: Raylib-cs (#3774) by @Brandon Baker +[bindings] UPDATED: h-raylib (#3739) by @Anand Swaroop +[bindings] UPDATED: OCaml bindings version (#3730) by @Tobias Mock +[bindings] UPDATED: Raylib.c3 (#3689) by @Kenta +[bindings] UPDATED: ray-cyber to 5.0 (#3654) by @fubark +[bindings] UPDATED: raylib-freebasic binding (#3591) by @WIITD +[bindings] UPDATED: SmallBASIC (#3562) by @Chris Warren-Smith +[bindings] UPDATED: Python raylib-py v5.0.0beta1 (#3557) by @Jorge A. Gomes +[bindings] UPDATED: raylib-d binding (#3561) by @Steven Schveighoffer +[bindings] UPDATED: Janet (#3553) by @Dmitry Matveyev +[bindings] UPDATED: Raylib.nelua (#3552) by @Auz +[bindings] UPDATED: raylib-cpp to 5.0 (#3551) by @Rob Loach +[bindings] UPDATED: Pascal binding (#3548) by @Gunko Vadim +[external] REVIEWED: rl_gputex, correctly load mipmaps from DDS files (#4399) by @Nikolas +[external] REVIEWED: stb_image_resize2, dix vld1q_f16 undeclared in arm (#4309) by @masnm +[external] REVIEWED: miniaudio, fix library and Makefile for NetBSD (#4212) by @NishiOwO +[external] REVIEWED: raygui, update to latest version 4.5-dev (#4238) by @Anthony Carbajal +[external] REVIEWED: jar_xml, replace unicode characters by ascii characters to avoid warning in MSVC (#4196) by @Rico P +[external] REVIEWED: vox_loader, normals and new voxels shader (#3843) by @johann nadalutti +[parser] REVIEWED: README.md, to mirror fixed help text (#4336) by @Daniil Kisel +[parser] REVIEWED: Fix seg fault with long comment lines (#4306) by @Chris Warren-Smith +[parser] REVIEWED: Don't crash for files that don't end in newlines (#3981) by @Peter0x44 +[parser] REVIEWED: Issues in usage example help text (#4084) by @Peter0x44 +[parser] REVIEWED: Fix parsing of empty parentheses (#3974) by @Filyus +[parser] REVIEWED: Address parsing issue when generating XML #3893 by @Ray +[parser] REVIEWED: `MemoryCopy()`, prevent buffer overflow by replacing hard-coded arguments (#4011) by @avx0 +[misc] ADDED: Create logo/raylib.icns by @Ray +[misc] ADDED: Create logo/raylib_1024x1024.png by @Ray +[misc] ADDED: Default vertex/fragment shader for OpenGL ES 3.0 (#4178) by @Lázaro Albuquerque +[misc] REVIEWED: README.md, fix Reddit badge (#4136) by @Ninad Sachania +[misc] REVIEWED: .gitignore, ignore compiled dll binaries (#3628) by @2Bear +[misc] REVIEWED: Fix undesired scrollbars on web shell files (#4104) by @jspast +[misc] REVIEWED: Made comments on raylib.h match comments in rcamera.h (#3942) by @Tomas Fabrizio Orsi +[misc] REVIEWED: Make raylib/raygui work better on touchscreen (#3728) by @Hongyu Ouyang +[misc] REVIEWED: Update config.h by @Ray ------------------------------------------------------------------------- Release: raylib 5.0 - 10th Anniversary Edition (18 November 2023) From ea81436befffe16b2898c6f0874a16525c2a1afe Mon Sep 17 00:00:00 2001 From: Ray Date: Thu, 24 Oct 2024 00:14:36 +0200 Subject: [PATCH 175/208] Update CHANGELOG --- CHANGELOG | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index d215dcbc4..e78f26c93 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -10,10 +10,13 @@ KEY CHANGES: - New rcore backend: RGFW - New raylib project creator tool - New platforms supported: Dreamcast, N64, PSP, PSVita, PS4 - - GPU Skinning (all platforms and GPU versions) + - GPU Skinning (all platforms and GL versions) - raymath C++ operators Detailed changes: + +WIP: Last update with commit from 21-Oct-2024 + [rcore] ADDED: Working directory info at initialization by @Ray [rcore] ADDED: `MakeDirectory()`, supporting recursive directory creation by @Ray [rcore] ADDED: `ComputeSHA1()` (#4390) by @Anthony Carbajal From 00c1f0836becda57e10917ca64cbf743ff0d8069 Mon Sep 17 00:00:00 2001 From: Ray Date: Thu, 24 Oct 2024 01:35:37 +0200 Subject: [PATCH 176/208] Update Makefile --- src/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Makefile b/src/Makefile index 137c28b53..15ec74634 100644 --- a/src/Makefile +++ b/src/Makefile @@ -184,8 +184,8 @@ ifeq ($(TARGET_PLATFORM),PLATFORM_WEB) EMSDK_PATH ?= C:/emsdk EMSCRIPTEN_PATH ?= $(EMSDK_PATH)/upstream/emscripten CLANG_PATH := $(EMSDK_PATH)/upstream/bin - PYTHON_PATH := $(EMSDK_PATH)/python/3.9.2-1_64bit - NODE_PATH := $(EMSDK_PATH)/node/14.15.5_64bit/bin + PYTHON_PATH := $(EMSDK_PATH)/python/3.9.2-nuget_64bit + NODE_PATH := $(EMSDK_PATH)/node/20.18.0_64bit/bin export PATH := $(EMSDK_PATH);$(EMSCRIPTEN_PATH);$(CLANG_PATH);$(NODE_PATH);$(PYTHON_PATH);C:/raylib/MinGW/bin;$(PATH) endif endif From eb04154c98616f0355b0035945a58fa7b56d59e2 Mon Sep 17 00:00:00 2001 From: Ray Date: Thu, 24 Oct 2024 01:35:44 +0200 Subject: [PATCH 177/208] Update Makefile --- examples/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/Makefile b/examples/Makefile index 65ee4fb80..cf4c3b389 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -197,7 +197,7 @@ ifeq ($(TARGET_PLATFORM),PLATFORM_ANDROID) MAKE = mingw32-make endif ifeq ($(TARGET_PLATFORM),PLATFORM_WEB) - MAKE = emmake make + MAKE = mingw32-make endif # Define compiler flags: CFLAGS From 0b650f62a6d185bc56970b3d8a0f8e1830bc3a2d Mon Sep 17 00:00:00 2001 From: Jeffery Myers Date: Thu, 24 Oct 2024 00:06:24 -0700 Subject: [PATCH 178/208] [RTEXTURES] Remove the panorama cubemap layout option (#4425) * Remove the panorama cubemap layout, it was not implemented. Left a todo in the code for some aspiring developer to finish. * Update raylib_api.* by CI --------- Co-authored-by: github-actions[bot] --- parser/output/raylib_api.json | 5 ----- parser/output/raylib_api.lua | 5 ----- parser/output/raylib_api.txt | 3 +-- parser/output/raylib_api.xml | 3 +-- src/raylib.h | 3 +-- src/rtextures.c | 8 +++----- 6 files changed, 6 insertions(+), 21 deletions(-) diff --git a/parser/output/raylib_api.json b/parser/output/raylib_api.json index 9db3d7ac0..948ff45e7 100644 --- a/parser/output/raylib_api.json +++ b/parser/output/raylib_api.json @@ -2839,11 +2839,6 @@ "name": "CUBEMAP_LAYOUT_CROSS_FOUR_BY_THREE", "value": 4, "description": "Layout is defined by a 4x3 cross with cubemap faces" - }, - { - "name": "CUBEMAP_LAYOUT_PANORAMA", - "value": 5, - "description": "Layout is defined by a panorama image (equirrectangular map)" } ] }, diff --git a/parser/output/raylib_api.lua b/parser/output/raylib_api.lua index d5492cb9b..fb16decc4 100644 --- a/parser/output/raylib_api.lua +++ b/parser/output/raylib_api.lua @@ -2839,11 +2839,6 @@ return { name = "CUBEMAP_LAYOUT_CROSS_FOUR_BY_THREE", value = 4, description = "Layout is defined by a 4x3 cross with cubemap faces" - }, - { - name = "CUBEMAP_LAYOUT_PANORAMA", - value = 5, - description = "Layout is defined by a panorama image (equirrectangular map)" } } }, diff --git a/parser/output/raylib_api.txt b/parser/output/raylib_api.txt index f6c79f85e..2c107a894 100644 --- a/parser/output/raylib_api.txt +++ b/parser/output/raylib_api.txt @@ -889,7 +889,7 @@ Enum 14: TextureWrap (4 values) Value[TEXTURE_WRAP_CLAMP]: 1 Value[TEXTURE_WRAP_MIRROR_REPEAT]: 2 Value[TEXTURE_WRAP_MIRROR_CLAMP]: 3 -Enum 15: CubemapLayout (6 values) +Enum 15: CubemapLayout (5 values) Name: CubemapLayout Description: Cubemap layouts Value[CUBEMAP_LAYOUT_AUTO_DETECT]: 0 @@ -897,7 +897,6 @@ Enum 15: CubemapLayout (6 values) Value[CUBEMAP_LAYOUT_LINE_HORIZONTAL]: 2 Value[CUBEMAP_LAYOUT_CROSS_THREE_BY_FOUR]: 3 Value[CUBEMAP_LAYOUT_CROSS_FOUR_BY_THREE]: 4 - Value[CUBEMAP_LAYOUT_PANORAMA]: 5 Enum 16: FontType (3 values) Name: FontType Description: Font type, defines generation method diff --git a/parser/output/raylib_api.xml b/parser/output/raylib_api.xml index 6de5933d4..29689bf69 100644 --- a/parser/output/raylib_api.xml +++ b/parser/output/raylib_api.xml @@ -595,13 +595,12 @@
- + - diff --git a/src/raylib.h b/src/raylib.h index 536b441b4..aceb458ce 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -877,8 +877,7 @@ typedef enum { CUBEMAP_LAYOUT_LINE_VERTICAL, // Layout is defined by a vertical line with faces CUBEMAP_LAYOUT_LINE_HORIZONTAL, // Layout is defined by a horizontal line with faces CUBEMAP_LAYOUT_CROSS_THREE_BY_FOUR, // Layout is defined by a 3x4 cross with cubemap faces - CUBEMAP_LAYOUT_CROSS_FOUR_BY_THREE, // Layout is defined by a 4x3 cross with cubemap faces - CUBEMAP_LAYOUT_PANORAMA // Layout is defined by a panorama image (equirrectangular map) + CUBEMAP_LAYOUT_CROSS_FOUR_BY_THREE // Layout is defined by a 4x3 cross with cubemap faces } CubemapLayout; // Font type, defines generation method diff --git a/src/rtextures.c b/src/rtextures.c index 23b32c1b8..ca3ad0990 100644 --- a/src/rtextures.c +++ b/src/rtextures.c @@ -4100,7 +4100,6 @@ TextureCubemap LoadTextureCubemap(Image image, int layout) { if ((image.width/6) == image.height) { layout = CUBEMAP_LAYOUT_LINE_HORIZONTAL; cubemap.width = image.width/6; } else if ((image.width/4) == (image.height/3)) { layout = CUBEMAP_LAYOUT_CROSS_FOUR_BY_THREE; cubemap.width = image.width/4; } - else if (image.width >= (int)((float)image.height*1.85f)) { layout = CUBEMAP_LAYOUT_PANORAMA; cubemap.width = image.width/4; } } else if (image.height > image.width) { @@ -4114,7 +4113,6 @@ TextureCubemap LoadTextureCubemap(Image image, int layout) if (layout == CUBEMAP_LAYOUT_LINE_HORIZONTAL) cubemap.width = image.width/6; if (layout == CUBEMAP_LAYOUT_CROSS_THREE_BY_FOUR) cubemap.width = image.width/3; if (layout == CUBEMAP_LAYOUT_CROSS_FOUR_BY_THREE) cubemap.width = image.width/4; - if (layout == CUBEMAP_LAYOUT_PANORAMA) cubemap.width = image.width/4; } cubemap.height = cubemap.width; @@ -4133,11 +4131,11 @@ TextureCubemap LoadTextureCubemap(Image image, int layout) { faces = ImageCopy(image); // Image data already follows expected convention } - else if (layout == CUBEMAP_LAYOUT_PANORAMA) + /*else if (layout == CUBEMAP_LAYOUT_PANORAMA) { - // TODO: Convert panorama image to square faces... + // TODO: implement panorama by converting image to square faces... // Ref: https://github.com/denivip/panorama/blob/master/panorama.cpp - } + } */ else { if (layout == CUBEMAP_LAYOUT_LINE_HORIZONTAL) for (int i = 0; i < 6; i++) faceRecs[i].x = (float)size*i; From f80a44c7294e1fe3e0a4c54d97a450c2981f6074 Mon Sep 17 00:00:00 2001 From: Ray Date: Thu, 24 Oct 2024 09:58:37 +0200 Subject: [PATCH 179/208] Update HISTORY.md --- HISTORY.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/HISTORY.md b/HISTORY.md index 035054dbe..555e81b38 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -471,3 +471,20 @@ Make sure to check raylib [CHANGELOG]([CHANGELOG](https://github.com/raysan5/ray Undoubtedly, this is the **biggest raylib update in 10 years**. Many new features and improvements with a special focus on maintainability and long-term sustainability. **Undoubtedly, this is the raylib of the future**. **Enjoy programming!** :) + +notes on raylib 5.5 +------------------- + +It's been **1 year** since latest raylib release and **11 years** since raylib 1.0 was officially released... + +Some numbers for this release: + + - **+260** closed issues (for a TOTAL of **+1800**!) + - **+700** commits since previous RELEASE (for a TOTAL of **+7670**!) + - **+30** functions ADDED to raylib API (for a TOTAL of **580**!) + - **+110** functions REVIEWED with fixes and improvements + - **+135** new contributors (for a TOTAL of **+635**!) + +Highlights for `raylib 5.5`: + +TODO. From 4abc6c39897755d01e4c620d56944ea4a3b47f60 Mon Sep 17 00:00:00 2001 From: Ray Date: Thu, 24 Oct 2024 09:59:21 +0200 Subject: [PATCH 180/208] Update CHANGELOG --- CHANGELOG | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index e78f26c93..da66bf6a9 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -24,12 +24,12 @@ WIP: Last update with commit from 21-Oct-2024 [rcore] ADDED: `GetKeyName()` (#4161) by @MrScautHD [rcore] ADDED: `IsFileNameValid()` by @Ray [rcore] ADDED: `GetViewRay()`, viewport independent raycast (#3709) by @Luís Almeida -[rcore] ADDED: Directory filtering to `LoadDirectoryFilesEx()`/`ScanDirectoryFiles()` (#4302) by @foxblock [rcore] RENAMED: `GetMouseRay()` to `GetScreenToWorldRay()` (#3830) by @Ray [rcore] RENAMED: `GetViewRay()` to `GetScreenToWorldRayEx()` (#3830) by @Ray [rcore] REVIEWED: `GetApplicationDirectory()` for FreeBSD (#4318) by @base +[rcore] REVIEWED: `LoadDirectoryFilesEx()`/`ScanDirectoryFiles()`, support directory on filter (#4302) by @foxblock [rcore] REVIEWED: Update comments on fullscreen and boderless window to describe what they do (#4280) by @Jeffery Myers -[rcore] REVIEWED: Automation events mouse wheel #4263 by @Ray +[rcore] REVIEWED: Correct processing of mouse wheel on Automation events #4263 by @Ray [rcore] REVIEWED: Fix gamepad axis movement and its automation event recording (#4184) by @maxmutant [rcore] REVIEWED: Do not set RL_TEXTURE_FILTER_LINEAR when high dpi flag is enabled (#4189) by @Dave Green [rcore] REVIEWED: `GetScreenWidth()`/`GetScreenHeight()` (#4074) by @Anthony Carbajal @@ -194,6 +194,7 @@ WIP: Last update with commit from 21-Oct-2024 [rtext] ADDED: BDF fonts support (#3735) by @Stanley Fuller -WARNING- [rtext] ADDED: `TextToCamel()` (#4033) by @IoIxD [rtext] ADDED: `TextToSnake()` (#4033) by @IoIxD +[rtext] ADDED: `TextToFloat()` (#3627) by @Benjamin Schmid Ties [rtext] REDESIGNED: `SetTextLineSpacing()` by @Ray -WARNING- [rtext] REVIEWED: `LoadFontDataBDF()` name and formating by @Ray [rtext] REVIEWED: `LoadFontDefault()`, initialize glyphs and recs to zero #4319 by @Ray From 2072b4fa04eedcb181dea7545ad675464a11c02d Mon Sep 17 00:00:00 2001 From: Ray Date: Thu, 24 Oct 2024 09:59:54 +0200 Subject: [PATCH 181/208] Update raylib.h --- src/raylib.h | 60 +++++++++++++++++++++++++++++----------------------- 1 file changed, 33 insertions(+), 27 deletions(-) diff --git a/src/raylib.h b/src/raylib.h index aceb458ce..c5d1912e4 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -1,22 +1,22 @@ /********************************************************************************************** * -* raylib v5.5-dev - A simple and easy-to-use library to enjoy videogames programming (www.raylib.com) +* raylib v5.5 - A simple and easy-to-use library to enjoy videogames programming (www.raylib.com) * * FEATURES: * - NO external dependencies, all required libraries included with raylib * - Multiplatform: Windows, Linux, FreeBSD, OpenBSD, NetBSD, DragonFly, * MacOS, Haiku, Android, Raspberry Pi, DRM native, HTML5. * - Written in plain C code (C99) in PascalCase/camelCase notation -* - Hardware accelerated with OpenGL (1.1, 2.1, 3.3, 4.3 or ES2 - choose at compile) +* - Hardware accelerated with OpenGL (1.1, 2.1, 3.3, 4.3, ES2, ES3 - choose at compile) * - Unique OpenGL abstraction layer (usable as standalone module): [rlgl] -* - Multiple Fonts formats supported (TTF, XNA fonts, AngelCode fonts) +* - Multiple Fonts formats supported (TTF, OTF, FNT, BDF, Sprite fonts) * - Outstanding texture formats support, including compressed formats (DXT, ETC, ASTC) * - Full 3d support for 3d Shapes, Models, Billboards, Heightmaps and more! * - Flexible Materials system, supporting classic maps and PBR maps -* - Animated 3D models supported (skeletal bones animation) (IQM) +* - Animated 3D models supported (skeletal bones animation) (IQM, M3D, GLTF) * - Shaders support, including Model shaders and Postprocessing shaders * - Powerful math module for Vector, Matrix and Quaternion operations: [raymath] -* - Audio loading and playing with streaming support (WAV, OGG, MP3, FLAC, XM, MOD) +* - Audio loading and playing with streaming support (WAV, OGG, MP3, FLAC, QOA, XM, MOD) * - VR stereo rendering with configurable HMD device parameters * - Bindings to multiple programming languages available! * @@ -27,29 +27,35 @@ * - One default RenderBatch is loaded on rlglInit()->rlLoadRenderBatch() [rlgl] (OpenGL 3.3 or ES2) * * DEPENDENCIES (included): -* [rcore] rglfw (Camilla Löwy - github.com/glfw/glfw) for window/context management and input (PLATFORM_DESKTOP) -* [rlgl] glad (David Herberth - github.com/Dav1dde/glad) for OpenGL 3.3 extensions loading (PLATFORM_DESKTOP) +* [rcore][GLFW] rglfw (Camilla Löwy - github.com/glfw/glfw) for window/context management and input +* [rcore][RGFW] rgfw (ColleagueRiley - github.com/ColleagueRiley/RGFW) for window/context management and input +* [rlgl] glad/glad_gles2 (David Herberth - github.com/Dav1dde/glad) for OpenGL 3.3 extensions loading * [raudio] miniaudio (David Reid - github.com/mackron/miniaudio) for audio device/context management * * OPTIONAL DEPENDENCIES (included): * [rcore] msf_gif (Miles Fogle) for GIF recording * [rcore] sinfl (Micha Mettke) for DEFLATE decompression algorithm * [rcore] sdefl (Micha Mettke) for DEFLATE compression algorithm +* [rcore] rprand (Ramon Snatamaria) for pseudo-random numbers generation +* [rtextures] qoi (Dominic Szablewski - https://phoboslab.org) for QOI image manage * [rtextures] stb_image (Sean Barret) for images loading (BMP, TGA, PNG, JPEG, HDR...) * [rtextures] stb_image_write (Sean Barret) for image writing (BMP, TGA, PNG, JPG) -* [rtextures] stb_image_resize (Sean Barret) for image resizing algorithms +* [rtextures] stb_image_resize2 (Sean Barret) for image resizing algorithms +* [rtextures] stb_perlin (Sean Barret) for Perlin Noise image generation * [rtext] stb_truetype (Sean Barret) for ttf fonts loading * [rtext] stb_rect_pack (Sean Barret) for rectangles packing * [rmodels] par_shapes (Philip Rideout) for parametric 3d shapes generation * [rmodels] tinyobj_loader_c (Syoyo Fujita) for models loading (OBJ, MTL) * [rmodels] cgltf (Johannes Kuhlmann) for models loading (glTF) -* [rmodels] Model3D (bzt) for models loading (M3D, https://bztsrc.gitlab.io/model3d) +* [rmodels] m3d (bzt) for models loading (M3D, https://bztsrc.gitlab.io/model3d) +* [rmodels] vox_loader (Johann Nadalutti) for models loading (VOX) * [raudio] dr_wav (David Reid) for WAV audio file loading * [raudio] dr_flac (David Reid) for FLAC audio file loading * [raudio] dr_mp3 (David Reid) for MP3 audio file loading * [raudio] stb_vorbis (Sean Barret) for OGG audio loading * [raudio] jar_xm (Joshua Reisenauer) for XM audio module loading * [raudio] jar_mod (Joshua Reisenauer) for MOD audio module loading +* [raudio] qoa (Dominic Szablewski - https://phoboslab.org) for QOA audio manage * * * LICENSE: zlib/libpng @@ -84,7 +90,7 @@ #define RAYLIB_VERSION_MAJOR 5 #define RAYLIB_VERSION_MINOR 5 #define RAYLIB_VERSION_PATCH 0 -#define RAYLIB_VERSION "5.5-dev" +#define RAYLIB_VERSION "5.5" // Function specifiers in case library is build/used as a shared library // NOTE: Microsoft specifiers to tell compiler that symbols are imported/exported from a .dll @@ -964,29 +970,29 @@ RLAPI void CloseWindow(void); // Close windo RLAPI bool WindowShouldClose(void); // Check if application should close (KEY_ESCAPE pressed or windows close icon clicked) RLAPI bool IsWindowReady(void); // Check if window has been initialized successfully RLAPI bool IsWindowFullscreen(void); // Check if window is currently fullscreen -RLAPI bool IsWindowHidden(void); // Check if window is currently hidden (only PLATFORM_DESKTOP) -RLAPI bool IsWindowMinimized(void); // Check if window is currently minimized (only PLATFORM_DESKTOP) -RLAPI bool IsWindowMaximized(void); // Check if window is currently maximized (only PLATFORM_DESKTOP) -RLAPI bool IsWindowFocused(void); // Check if window is currently focused (only PLATFORM_DESKTOP) +RLAPI bool IsWindowHidden(void); // Check if window is currently hidden +RLAPI bool IsWindowMinimized(void); // Check if window is currently minimized +RLAPI bool IsWindowMaximized(void); // Check if window is currently maximized +RLAPI bool IsWindowFocused(void); // Check if window is currently focused RLAPI bool IsWindowResized(void); // Check if window has been resized last frame RLAPI bool IsWindowState(unsigned int flag); // Check if one specific window flag is enabled -RLAPI void SetWindowState(unsigned int flags); // Set window configuration state using flags (only PLATFORM_DESKTOP) +RLAPI void SetWindowState(unsigned int flags); // Set window configuration state using flags RLAPI void ClearWindowState(unsigned int flags); // Clear window configuration state flags -RLAPI void ToggleFullscreen(void); // Toggle window state: fullscreen/windowed [resizes monitor to match window resolution] (only PLATFORM_DESKTOP) -RLAPI void ToggleBorderlessWindowed(void); // Toggle window state: borderless windowed [resizes window to match monitor resolution] (only PLATFORM_DESKTOP) -RLAPI void MaximizeWindow(void); // Set window state: maximized, if resizable (only PLATFORM_DESKTOP) -RLAPI void MinimizeWindow(void); // Set window state: minimized, if resizable (only PLATFORM_DESKTOP) -RLAPI void RestoreWindow(void); // Set window state: not minimized/maximized (only PLATFORM_DESKTOP) -RLAPI void SetWindowIcon(Image image); // Set icon for window (single image, RGBA 32bit, only PLATFORM_DESKTOP) -RLAPI void SetWindowIcons(Image *images, int count); // Set icon for window (multiple images, RGBA 32bit, only PLATFORM_DESKTOP) -RLAPI void SetWindowTitle(const char *title); // Set title for window (only PLATFORM_DESKTOP and PLATFORM_WEB) -RLAPI void SetWindowPosition(int x, int y); // Set window position on screen (only PLATFORM_DESKTOP) +RLAPI void ToggleFullscreen(void); // Toggle window state: fullscreen/windowed, resizes monitor to match window resolution +RLAPI void ToggleBorderlessWindowed(void); // Toggle window state: borderless windowed, resizes window to match monitor resolution +RLAPI void MaximizeWindow(void); // Set window state: maximized, if resizable +RLAPI void MinimizeWindow(void); // Set window state: minimized, if resizable +RLAPI void RestoreWindow(void); // Set window state: not minimized/maximized +RLAPI void SetWindowIcon(Image image); // Set icon for window (single image, RGBA 32bit) +RLAPI void SetWindowIcons(Image *images, int count); // Set icon for window (multiple images, RGBA 32bit) +RLAPI void SetWindowTitle(const char *title); // Set title for window +RLAPI void SetWindowPosition(int x, int y); // Set window position on screen RLAPI void SetWindowMonitor(int monitor); // Set monitor for the current window RLAPI void SetWindowMinSize(int width, int height); // Set window minimum dimensions (for FLAG_WINDOW_RESIZABLE) RLAPI void SetWindowMaxSize(int width, int height); // Set window maximum dimensions (for FLAG_WINDOW_RESIZABLE) RLAPI void SetWindowSize(int width, int height); // Set window dimensions -RLAPI void SetWindowOpacity(float opacity); // Set window opacity [0.0f..1.0f] (only PLATFORM_DESKTOP) -RLAPI void SetWindowFocused(void); // Set window focused (only PLATFORM_DESKTOP) +RLAPI void SetWindowOpacity(float opacity); // Set window opacity [0.0f..1.0f] +RLAPI void SetWindowFocused(void); // Set window focused RLAPI void *GetWindowHandle(void); // Get native window handle RLAPI int GetScreenWidth(void); // Get current screen width RLAPI int GetScreenHeight(void); // Get current screen height @@ -1164,7 +1170,7 @@ RLAPI void PlayAutomationEvent(AutomationEvent event); // Input-related functions: keyboard RLAPI bool IsKeyPressed(int key); // Check if a key has been pressed once -RLAPI bool IsKeyPressedRepeat(int key); // Check if a key has been pressed again (Only PLATFORM_DESKTOP) +RLAPI bool IsKeyPressedRepeat(int key); // Check if a key has been pressed again RLAPI bool IsKeyDown(int key); // Check if a key is being pressed 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 From c6a58d974429e57deb244828c63f13e8bff59cf5 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 24 Oct 2024 08:00:11 +0000 Subject: [PATCH 182/208] Update raylib_api.* by CI --- parser/output/raylib_api.json | 36 +++++++++++++++++------------------ parser/output/raylib_api.lua | 36 +++++++++++++++++------------------ parser/output/raylib_api.txt | 36 +++++++++++++++++------------------ parser/output/raylib_api.xml | 36 +++++++++++++++++------------------ 4 files changed, 72 insertions(+), 72 deletions(-) diff --git a/parser/output/raylib_api.json b/parser/output/raylib_api.json index 948ff45e7..34474bdf4 100644 --- a/parser/output/raylib_api.json +++ b/parser/output/raylib_api.json @@ -27,7 +27,7 @@ { "name": "RAYLIB_VERSION", "type": "STRING", - "value": "5.5-dev", + "value": "5.5", "description": "" }, { @@ -3177,22 +3177,22 @@ }, { "name": "IsWindowHidden", - "description": "Check if window is currently hidden (only PLATFORM_DESKTOP)", + "description": "Check if window is currently hidden", "returnType": "bool" }, { "name": "IsWindowMinimized", - "description": "Check if window is currently minimized (only PLATFORM_DESKTOP)", + "description": "Check if window is currently minimized", "returnType": "bool" }, { "name": "IsWindowMaximized", - "description": "Check if window is currently maximized (only PLATFORM_DESKTOP)", + "description": "Check if window is currently maximized", "returnType": "bool" }, { "name": "IsWindowFocused", - "description": "Check if window is currently focused (only PLATFORM_DESKTOP)", + "description": "Check if window is currently focused", "returnType": "bool" }, { @@ -3213,7 +3213,7 @@ }, { "name": "SetWindowState", - "description": "Set window configuration state using flags (only PLATFORM_DESKTOP)", + "description": "Set window configuration state using flags", "returnType": "void", "params": [ { @@ -3235,32 +3235,32 @@ }, { "name": "ToggleFullscreen", - "description": "Toggle window state: fullscreen/windowed [resizes monitor to match window resolution] (only PLATFORM_DESKTOP)", + "description": "Toggle window state: fullscreen/windowed, resizes monitor to match window resolution", "returnType": "void" }, { "name": "ToggleBorderlessWindowed", - "description": "Toggle window state: borderless windowed [resizes window to match monitor resolution] (only PLATFORM_DESKTOP)", + "description": "Toggle window state: borderless windowed, resizes window to match monitor resolution", "returnType": "void" }, { "name": "MaximizeWindow", - "description": "Set window state: maximized, if resizable (only PLATFORM_DESKTOP)", + "description": "Set window state: maximized, if resizable", "returnType": "void" }, { "name": "MinimizeWindow", - "description": "Set window state: minimized, if resizable (only PLATFORM_DESKTOP)", + "description": "Set window state: minimized, if resizable", "returnType": "void" }, { "name": "RestoreWindow", - "description": "Set window state: not minimized/maximized (only PLATFORM_DESKTOP)", + "description": "Set window state: not minimized/maximized", "returnType": "void" }, { "name": "SetWindowIcon", - "description": "Set icon for window (single image, RGBA 32bit, only PLATFORM_DESKTOP)", + "description": "Set icon for window (single image, RGBA 32bit)", "returnType": "void", "params": [ { @@ -3271,7 +3271,7 @@ }, { "name": "SetWindowIcons", - "description": "Set icon for window (multiple images, RGBA 32bit, only PLATFORM_DESKTOP)", + "description": "Set icon for window (multiple images, RGBA 32bit)", "returnType": "void", "params": [ { @@ -3286,7 +3286,7 @@ }, { "name": "SetWindowTitle", - "description": "Set title for window (only PLATFORM_DESKTOP and PLATFORM_WEB)", + "description": "Set title for window", "returnType": "void", "params": [ { @@ -3297,7 +3297,7 @@ }, { "name": "SetWindowPosition", - "description": "Set window position on screen (only PLATFORM_DESKTOP)", + "description": "Set window position on screen", "returnType": "void", "params": [ { @@ -3368,7 +3368,7 @@ }, { "name": "SetWindowOpacity", - "description": "Set window opacity [0.0f..1.0f] (only PLATFORM_DESKTOP)", + "description": "Set window opacity [0.0f..1.0f]", "returnType": "void", "params": [ { @@ -3379,7 +3379,7 @@ }, { "name": "SetWindowFocused", - "description": "Set window focused (only PLATFORM_DESKTOP)", + "description": "Set window focused", "returnType": "void" }, { @@ -4824,7 +4824,7 @@ }, { "name": "IsKeyPressedRepeat", - "description": "Check if a key has been pressed again (Only PLATFORM_DESKTOP)", + "description": "Check if a key has been pressed again", "returnType": "bool", "params": [ { diff --git a/parser/output/raylib_api.lua b/parser/output/raylib_api.lua index fb16decc4..dfdf69147 100644 --- a/parser/output/raylib_api.lua +++ b/parser/output/raylib_api.lua @@ -27,7 +27,7 @@ return { { name = "RAYLIB_VERSION", type = "STRING", - value = "5.5-dev", + value = "5.5", description = "" }, { @@ -3129,22 +3129,22 @@ return { }, { name = "IsWindowHidden", - description = "Check if window is currently hidden (only PLATFORM_DESKTOP)", + description = "Check if window is currently hidden", returnType = "bool" }, { name = "IsWindowMinimized", - description = "Check if window is currently minimized (only PLATFORM_DESKTOP)", + description = "Check if window is currently minimized", returnType = "bool" }, { name = "IsWindowMaximized", - description = "Check if window is currently maximized (only PLATFORM_DESKTOP)", + description = "Check if window is currently maximized", returnType = "bool" }, { name = "IsWindowFocused", - description = "Check if window is currently focused (only PLATFORM_DESKTOP)", + description = "Check if window is currently focused", returnType = "bool" }, { @@ -3162,7 +3162,7 @@ return { }, { name = "SetWindowState", - description = "Set window configuration state using flags (only PLATFORM_DESKTOP)", + description = "Set window configuration state using flags", returnType = "void", params = { {type = "unsigned int", name = "flags"} @@ -3178,32 +3178,32 @@ return { }, { name = "ToggleFullscreen", - description = "Toggle window state: fullscreen/windowed [resizes monitor to match window resolution] (only PLATFORM_DESKTOP)", + description = "Toggle window state: fullscreen/windowed, resizes monitor to match window resolution", returnType = "void" }, { name = "ToggleBorderlessWindowed", - description = "Toggle window state: borderless windowed [resizes window to match monitor resolution] (only PLATFORM_DESKTOP)", + description = "Toggle window state: borderless windowed, resizes window to match monitor resolution", returnType = "void" }, { name = "MaximizeWindow", - description = "Set window state: maximized, if resizable (only PLATFORM_DESKTOP)", + description = "Set window state: maximized, if resizable", returnType = "void" }, { name = "MinimizeWindow", - description = "Set window state: minimized, if resizable (only PLATFORM_DESKTOP)", + description = "Set window state: minimized, if resizable", returnType = "void" }, { name = "RestoreWindow", - description = "Set window state: not minimized/maximized (only PLATFORM_DESKTOP)", + description = "Set window state: not minimized/maximized", returnType = "void" }, { name = "SetWindowIcon", - description = "Set icon for window (single image, RGBA 32bit, only PLATFORM_DESKTOP)", + description = "Set icon for window (single image, RGBA 32bit)", returnType = "void", params = { {type = "Image", name = "image"} @@ -3211,7 +3211,7 @@ return { }, { name = "SetWindowIcons", - description = "Set icon for window (multiple images, RGBA 32bit, only PLATFORM_DESKTOP)", + description = "Set icon for window (multiple images, RGBA 32bit)", returnType = "void", params = { {type = "Image *", name = "images"}, @@ -3220,7 +3220,7 @@ return { }, { name = "SetWindowTitle", - description = "Set title for window (only PLATFORM_DESKTOP and PLATFORM_WEB)", + description = "Set title for window", returnType = "void", params = { {type = "const char *", name = "title"} @@ -3228,7 +3228,7 @@ return { }, { name = "SetWindowPosition", - description = "Set window position on screen (only PLATFORM_DESKTOP)", + description = "Set window position on screen", returnType = "void", params = { {type = "int", name = "x"}, @@ -3272,7 +3272,7 @@ return { }, { name = "SetWindowOpacity", - description = "Set window opacity [0.0f..1.0f] (only PLATFORM_DESKTOP)", + description = "Set window opacity [0.0f..1.0f]", returnType = "void", params = { {type = "float", name = "opacity"} @@ -3280,7 +3280,7 @@ return { }, { name = "SetWindowFocused", - description = "Set window focused (only PLATFORM_DESKTOP)", + description = "Set window focused", returnType = "void" }, { @@ -4281,7 +4281,7 @@ return { }, { name = "IsKeyPressedRepeat", - description = "Check if a key has been pressed again (Only PLATFORM_DESKTOP)", + description = "Check if a key has been pressed again", returnType = "bool", params = { {type = "int", name = "key"} diff --git a/parser/output/raylib_api.txt b/parser/output/raylib_api.txt index 2c107a894..d2f70fe39 100644 --- a/parser/output/raylib_api.txt +++ b/parser/output/raylib_api.txt @@ -24,7 +24,7 @@ Define 004: RAYLIB_VERSION_PATCH Define 005: RAYLIB_VERSION Name: RAYLIB_VERSION Type: STRING - Value: "5.5-dev" + Value: "5.5" Description: Define 006: __declspec(x) Name: __declspec(x) @@ -1020,22 +1020,22 @@ Function 005: IsWindowFullscreen() (0 input parameters) Function 006: IsWindowHidden() (0 input parameters) Name: IsWindowHidden Return type: bool - Description: Check if window is currently hidden (only PLATFORM_DESKTOP) + Description: Check if window is currently hidden No input parameters Function 007: IsWindowMinimized() (0 input parameters) Name: IsWindowMinimized Return type: bool - Description: Check if window is currently minimized (only PLATFORM_DESKTOP) + Description: Check if window is currently minimized No input parameters Function 008: IsWindowMaximized() (0 input parameters) Name: IsWindowMaximized Return type: bool - Description: Check if window is currently maximized (only PLATFORM_DESKTOP) + Description: Check if window is currently maximized No input parameters Function 009: IsWindowFocused() (0 input parameters) Name: IsWindowFocused Return type: bool - Description: Check if window is currently focused (only PLATFORM_DESKTOP) + Description: Check if window is currently focused No input parameters Function 010: IsWindowResized() (0 input parameters) Name: IsWindowResized @@ -1050,7 +1050,7 @@ Function 011: IsWindowState() (1 input parameters) Function 012: SetWindowState() (1 input parameters) Name: SetWindowState Return type: void - Description: Set window configuration state using flags (only PLATFORM_DESKTOP) + Description: Set window configuration state using flags Param[1]: flags (type: unsigned int) Function 013: ClearWindowState() (1 input parameters) Name: ClearWindowState @@ -1060,48 +1060,48 @@ Function 013: ClearWindowState() (1 input parameters) Function 014: ToggleFullscreen() (0 input parameters) Name: ToggleFullscreen Return type: void - Description: Toggle window state: fullscreen/windowed [resizes monitor to match window resolution] (only PLATFORM_DESKTOP) + Description: Toggle window state: fullscreen/windowed, resizes monitor to match window resolution No input parameters Function 015: ToggleBorderlessWindowed() (0 input parameters) Name: ToggleBorderlessWindowed Return type: void - Description: Toggle window state: borderless windowed [resizes window to match monitor resolution] (only PLATFORM_DESKTOP) + Description: Toggle window state: borderless windowed, resizes window to match monitor resolution No input parameters Function 016: MaximizeWindow() (0 input parameters) Name: MaximizeWindow Return type: void - Description: Set window state: maximized, if resizable (only PLATFORM_DESKTOP) + Description: Set window state: maximized, if resizable No input parameters Function 017: MinimizeWindow() (0 input parameters) Name: MinimizeWindow Return type: void - Description: Set window state: minimized, if resizable (only PLATFORM_DESKTOP) + Description: Set window state: minimized, if resizable No input parameters Function 018: RestoreWindow() (0 input parameters) Name: RestoreWindow Return type: void - Description: Set window state: not minimized/maximized (only PLATFORM_DESKTOP) + Description: Set window state: not minimized/maximized No input parameters Function 019: SetWindowIcon() (1 input parameters) Name: SetWindowIcon Return type: void - Description: Set icon for window (single image, RGBA 32bit, only PLATFORM_DESKTOP) + Description: Set icon for window (single image, RGBA 32bit) Param[1]: image (type: Image) Function 020: SetWindowIcons() (2 input parameters) Name: SetWindowIcons Return type: void - Description: Set icon for window (multiple images, RGBA 32bit, only PLATFORM_DESKTOP) + Description: Set icon for window (multiple images, RGBA 32bit) Param[1]: images (type: Image *) Param[2]: count (type: int) Function 021: SetWindowTitle() (1 input parameters) Name: SetWindowTitle Return type: void - Description: Set title for window (only PLATFORM_DESKTOP and PLATFORM_WEB) + Description: Set title for window Param[1]: title (type: const char *) Function 022: SetWindowPosition() (2 input parameters) Name: SetWindowPosition Return type: void - Description: Set window position on screen (only PLATFORM_DESKTOP) + Description: Set window position on screen Param[1]: x (type: int) Param[2]: y (type: int) Function 023: SetWindowMonitor() (1 input parameters) @@ -1130,12 +1130,12 @@ Function 026: SetWindowSize() (2 input parameters) Function 027: SetWindowOpacity() (1 input parameters) Name: SetWindowOpacity Return type: void - Description: Set window opacity [0.0f..1.0f] (only PLATFORM_DESKTOP) + Description: Set window opacity [0.0f..1.0f] Param[1]: opacity (type: float) Function 028: SetWindowFocused() (0 input parameters) Name: SetWindowFocused Return type: void - Description: Set window focused (only PLATFORM_DESKTOP) + Description: Set window focused No input parameters Function 029: GetWindowHandle() (0 input parameters) Name: GetWindowHandle @@ -1854,7 +1854,7 @@ Function 160: IsKeyPressed() (1 input parameters) Function 161: IsKeyPressedRepeat() (1 input parameters) Name: IsKeyPressedRepeat Return type: bool - Description: Check if a key has been pressed again (Only PLATFORM_DESKTOP) + Description: Check if a key has been pressed again Param[1]: key (type: int) Function 162: IsKeyDown() (1 input parameters) Name: IsKeyDown diff --git a/parser/output/raylib_api.xml b/parser/output/raylib_api.xml index 29689bf69..11e4dc7f4 100644 --- a/parser/output/raylib_api.xml +++ b/parser/output/raylib_api.xml @@ -5,7 +5,7 @@ - + @@ -688,46 +688,46 @@
- + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -746,10 +746,10 @@ - + - + @@ -1163,7 +1163,7 @@ - + From 0f5e76f91fc51ccc647766bbbded47d1f51a0ea8 Mon Sep 17 00:00:00 2001 From: Ray Date: Thu, 24 Oct 2024 10:00:57 +0200 Subject: [PATCH 183/208] Update CHANGELOG --- CHANGELOG | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index da66bf6a9..7ec73066f 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -4,7 +4,7 @@ changelog Current Release: raylib 5.0 (18 November 2023) ------------------------------------------------------------------------- -Release: raylib 5.5 - 11th Anniversary Edition? (18 November 2024?) +Release: raylib 5.5 (November 2024?) ------------------------------------------------------------------------- KEY CHANGES: - New rcore backend: RGFW From d85c6fe2c05dea42efbe036de9d36fb6a3660dd1 Mon Sep 17 00:00:00 2001 From: Ray Date: Thu, 24 Oct 2024 11:50:30 +0200 Subject: [PATCH 184/208] Update raylib.h --- src/raylib.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/raylib.h b/src/raylib.h index c5d1912e4..e850fbc08 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -999,7 +999,7 @@ RLAPI int GetScreenHeight(void); // Get current RLAPI int GetRenderWidth(void); // Get current render width (it considers HiDPI) RLAPI int GetRenderHeight(void); // Get current render height (it considers HiDPI) RLAPI int GetMonitorCount(void); // Get number of connected monitors -RLAPI int GetCurrentMonitor(void); // Get current connected monitor +RLAPI int GetCurrentMonitor(void); // Get primary system monitor RLAPI Vector2 GetMonitorPosition(int monitor); // Get specified monitor position RLAPI int GetMonitorWidth(int monitor); // Get specified monitor width (current video mode used by monitor) RLAPI int GetMonitorHeight(int monitor); // Get specified monitor height (current video mode used by monitor) From 5706cfd600f141fe08963a7ed191a2d22673b6ab Mon Sep 17 00:00:00 2001 From: Ray Date: Thu, 24 Oct 2024 11:50:42 +0200 Subject: [PATCH 185/208] Update Makefile --- src/Makefile | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/Makefile b/src/Makefile index 15ec74634..84be9f5a0 100644 --- a/src/Makefile +++ b/src/Makefile @@ -230,8 +230,8 @@ ifeq ($(TARGET_PLATFORM),PLATFORM_ANDROID) endif # Define raylib graphics api depending on selected platform +# NOTE: By default use OpenGL 3.3 on desktop platforms ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW) - # By default use OpenGL 3.3 on desktop platforms GRAPHICS ?= GRAPHICS_API_OPENGL_33 #GRAPHICS = GRAPHICS_API_OPENGL_11 # Uncomment to use OpenGL 1.1 #GRAPHICS = GRAPHICS_API_OPENGL_21 # Uncomment to use OpenGL 2.1 @@ -239,11 +239,9 @@ ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW) #GRAPHICS = GRAPHICS_API_OPENGL_ES2 # Uncomment to use OpenGL ES 2.0 (ANGLE) endif ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_SDL) - # By default use OpenGL 3.3 on desktop platform with SDL backend GRAPHICS ?= GRAPHICS_API_OPENGL_33 endif ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_RGFW) - # By default use OpenGL 3.3 on desktop platforms GRAPHICS ?= GRAPHICS_API_OPENGL_33 #GRAPHICS = GRAPHICS_API_OPENGL_11 # Uncomment to use OpenGL 1.1 #GRAPHICS = GRAPHICS_API_OPENGL_21 # Uncomment to use OpenGL 2.1 @@ -257,7 +255,7 @@ endif ifeq ($(TARGET_PLATFORM),PLATFORM_WEB) # On HTML5 OpenGL ES 2.0 is used, emscripten translates it to WebGL 1.0 GRAPHICS = GRAPHICS_API_OPENGL_ES2 - #GRAPHICS = GRAPHICS_API_OPENGL_ES3 # Uncomment to use ES3/WebGL2 (preliminary support). + #GRAPHICS = GRAPHICS_API_OPENGL_ES3 # Uncomment to use ES3/WebGL2 (preliminary support) endif ifeq ($(TARGET_PLATFORM),PLATFORM_ANDROID) # By default use OpenGL ES 2.0 on Android From b0e77c7afd8a2dc62025080bbe89ec1a5ecffd40 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 24 Oct 2024 09:50:59 +0000 Subject: [PATCH 186/208] Update raylib_api.* by CI --- parser/output/raylib_api.json | 2 +- parser/output/raylib_api.lua | 2 +- parser/output/raylib_api.txt | 2 +- parser/output/raylib_api.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/parser/output/raylib_api.json b/parser/output/raylib_api.json index 34474bdf4..f171a7900 100644 --- a/parser/output/raylib_api.json +++ b/parser/output/raylib_api.json @@ -3414,7 +3414,7 @@ }, { "name": "GetCurrentMonitor", - "description": "Get current connected monitor", + "description": "Get primary system monitor", "returnType": "int" }, { diff --git a/parser/output/raylib_api.lua b/parser/output/raylib_api.lua index dfdf69147..b1a379aa7 100644 --- a/parser/output/raylib_api.lua +++ b/parser/output/raylib_api.lua @@ -3315,7 +3315,7 @@ return { }, { name = "GetCurrentMonitor", - description = "Get current connected monitor", + description = "Get primary system monitor", returnType = "int" }, { diff --git a/parser/output/raylib_api.txt b/parser/output/raylib_api.txt index d2f70fe39..e099f3ba4 100644 --- a/parser/output/raylib_api.txt +++ b/parser/output/raylib_api.txt @@ -1170,7 +1170,7 @@ Function 034: GetMonitorCount() (0 input parameters) Function 035: GetCurrentMonitor() (0 input parameters) Name: GetCurrentMonitor Return type: int - Description: Get current connected monitor + Description: Get primary system monitor No input parameters Function 036: GetMonitorPosition() (1 input parameters) Name: GetMonitorPosition diff --git a/parser/output/raylib_api.xml b/parser/output/raylib_api.xml index 11e4dc7f4..a43600961 100644 --- a/parser/output/raylib_api.xml +++ b/parser/output/raylib_api.xml @@ -763,7 +763,7 @@ - + From 3483a4d9cb4fecbe9313f80e53890e3911f663f7 Mon Sep 17 00:00:00 2001 From: Ray Date: Thu, 24 Oct 2024 11:57:36 +0200 Subject: [PATCH 187/208] Update raylib.h --- src/raylib.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/raylib.h b/src/raylib.h index e850fbc08..bc7bc372c 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -999,7 +999,7 @@ RLAPI int GetScreenHeight(void); // Get current RLAPI int GetRenderWidth(void); // Get current render width (it considers HiDPI) RLAPI int GetRenderHeight(void); // Get current render height (it considers HiDPI) RLAPI int GetMonitorCount(void); // Get number of connected monitors -RLAPI int GetCurrentMonitor(void); // Get primary system monitor +RLAPI int GetCurrentMonitor(void); // Get current monitor where window is placed RLAPI Vector2 GetMonitorPosition(int monitor); // Get specified monitor position RLAPI int GetMonitorWidth(int monitor); // Get specified monitor width (current video mode used by monitor) RLAPI int GetMonitorHeight(int monitor); // Get specified monitor height (current video mode used by monitor) From 865265b83226037f93c0c9c3115730500283342d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 24 Oct 2024 09:58:05 +0000 Subject: [PATCH 188/208] Update raylib_api.* by CI --- parser/output/raylib_api.json | 2 +- parser/output/raylib_api.lua | 2 +- parser/output/raylib_api.txt | 2 +- parser/output/raylib_api.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/parser/output/raylib_api.json b/parser/output/raylib_api.json index f171a7900..47ede2e5a 100644 --- a/parser/output/raylib_api.json +++ b/parser/output/raylib_api.json @@ -3414,7 +3414,7 @@ }, { "name": "GetCurrentMonitor", - "description": "Get primary system monitor", + "description": "Get current monitor where window is placed", "returnType": "int" }, { diff --git a/parser/output/raylib_api.lua b/parser/output/raylib_api.lua index b1a379aa7..20f2a8f0c 100644 --- a/parser/output/raylib_api.lua +++ b/parser/output/raylib_api.lua @@ -3315,7 +3315,7 @@ return { }, { name = "GetCurrentMonitor", - description = "Get primary system monitor", + description = "Get current monitor where window is placed", returnType = "int" }, { diff --git a/parser/output/raylib_api.txt b/parser/output/raylib_api.txt index e099f3ba4..e409a0116 100644 --- a/parser/output/raylib_api.txt +++ b/parser/output/raylib_api.txt @@ -1170,7 +1170,7 @@ Function 034: GetMonitorCount() (0 input parameters) Function 035: GetCurrentMonitor() (0 input parameters) Name: GetCurrentMonitor Return type: int - Description: Get primary system monitor + Description: Get current monitor where window is placed No input parameters Function 036: GetMonitorPosition() (1 input parameters) Name: GetMonitorPosition diff --git a/parser/output/raylib_api.xml b/parser/output/raylib_api.xml index a43600961..9ab4b52cc 100644 --- a/parser/output/raylib_api.xml +++ b/parser/output/raylib_api.xml @@ -763,7 +763,7 @@ - + From b0140b876bf3670034bba67b1de2c5248d51a456 Mon Sep 17 00:00:00 2001 From: Ray Date: Thu, 24 Oct 2024 12:25:05 +0200 Subject: [PATCH 189/208] REVIEWED: GPU skninning on Web, some gotchas! #4412 --- examples/Makefile | 4 +-- examples/Makefile.Web | 11 +++++-- .../resources/shaders/glsl100/skinning.vs | 30 ++++++++++++++++--- src/rlgl.h | 8 +++-- 4 files changed, 43 insertions(+), 10 deletions(-) diff --git a/examples/Makefile b/examples/Makefile index cf4c3b389..be9751db1 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -157,8 +157,8 @@ ifeq ($(TARGET_PLATFORM),PLATFORM_WEB) EMSDK_PATH ?= C:/emsdk EMSCRIPTEN_PATH ?= $(EMSDK_PATH)/upstream/emscripten CLANG_PATH = $(EMSDK_PATH)/upstream/bin - PYTHON_PATH = $(EMSDK_PATH)/python/3.9.2-1_64bit - NODE_PATH = $(EMSDK_PATH)/node/14.15.5_64bit/bin + PYTHON_PATH = $(EMSDK_PATH)/python/3.9.2-nuget_64bit + NODE_PATH = $(EMSDK_PATH)/node/20.18.0_64bit/bin export PATH = $(EMSDK_PATH);$(EMSCRIPTEN_PATH);$(CLANG_PATH);$(NODE_PATH);$(PYTHON_PATH):$$(PATH) endif endif diff --git a/examples/Makefile.Web b/examples/Makefile.Web index f6c8b785a..5155458e0 100644 --- a/examples/Makefile.Web +++ b/examples/Makefile.Web @@ -110,8 +110,8 @@ ifeq ($(PLATFORM),PLATFORM_WEB) EMSDK_PATH ?= C:/emsdk EMSCRIPTEN_PATH ?= $(EMSDK_PATH)/upstream/emscripten CLANG_PATH = $(EMSDK_PATH)/upstream/bin - PYTHON_PATH = $(EMSDK_PATH)/python/3.9.2-1_64bit - NODE_PATH = $(EMSDK_PATH)/node/14.15.5_64bit/bin + PYTHON_PATH = $(EMSDK_PATH)/python/3.9.2-nuget_64bit + NODE_PATH = $(EMSDK_PATH)/node/20.18.0_64bit/bin export PATH = $(EMSDK_PATH);$(EMSCRIPTEN_PATH);$(CLANG_PATH);$(NODE_PATH);$(PYTHON_PATH):$$(PATH) endif endif @@ -434,6 +434,7 @@ TEXT = \ MODELS = \ models/models_animation \ + models/models_gpu_skinning \ models/models_billboard \ models/models_box_collisions \ models/models_cubicmap \ @@ -853,6 +854,12 @@ models/models_animation: models/models_animation.c --preload-file models/resources/models/iqm/guy.iqm@resources/models/iqm/guy.iqm \ --preload-file models/resources/models/iqm/guytex.png@resources/models/iqm/guytex.png \ --preload-file models/resources/models/iqm/guyanim.iqm@resources/models/iqm/guyanim.iqm + +models/models_gpu_skinning: models/models_gpu_skinning.c + $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) -sTOTAL_MEMORY=67108864 \ + --preload-file models/resources/models/gltf/greenman.glb@resources/models/gltf/greenman.glb \ + --preload-file models/resources/shaders/glsl100/skinning.vs@resources/shaders/glsl100/skinning.vs \ + --preload-file models/resources/shaders/glsl100/skinning.fs@resources/shaders/glsl100/skinning.fs models/models_billboard: models/models_billboard.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \ diff --git a/examples/models/resources/shaders/glsl100/skinning.vs b/examples/models/resources/shaders/glsl100/skinning.vs index f7b6d8fb2..627a7dda4 100644 --- a/examples/models/resources/shaders/glsl100/skinning.vs +++ b/examples/models/resources/shaders/glsl100/skinning.vs @@ -24,11 +24,33 @@ void main() int boneIndex2 = int(vertexBoneIds.z); int boneIndex3 = int(vertexBoneIds.w); + // WARNING: OpenGL ES 2.0 does not support automatic matrix transposing, neither transpose() function + mat4 boneMatrixTransposed0 = mat4( + vec4(boneMatrices[boneIndex0][0].x, boneMatrices[boneIndex0][1].x, boneMatrices[boneIndex0][2].x, boneMatrices[boneIndex0][3].x), + vec4(boneMatrices[boneIndex0][0].y, boneMatrices[boneIndex0][1].y, boneMatrices[boneIndex0][2].y, boneMatrices[boneIndex0][3].y), + vec4(boneMatrices[boneIndex0][0].z, boneMatrices[boneIndex0][1].z, boneMatrices[boneIndex0][2].z, boneMatrices[boneIndex0][3].z), + vec4(boneMatrices[boneIndex0][0].w, boneMatrices[boneIndex0][1].w, boneMatrices[boneIndex0][2].w, boneMatrices[boneIndex0][3].w)); + mat4 boneMatrixTransposed1 = mat4( + vec4(boneMatrices[boneIndex1][0].x, boneMatrices[boneIndex1][1].x, boneMatrices[boneIndex1][2].x, boneMatrices[boneIndex1][3].x), + vec4(boneMatrices[boneIndex1][0].y, boneMatrices[boneIndex1][1].y, boneMatrices[boneIndex1][2].y, boneMatrices[boneIndex1][3].y), + vec4(boneMatrices[boneIndex1][0].z, boneMatrices[boneIndex1][1].z, boneMatrices[boneIndex1][2].z, boneMatrices[boneIndex1][3].z), + vec4(boneMatrices[boneIndex1][0].w, boneMatrices[boneIndex1][1].w, boneMatrices[boneIndex1][2].w, boneMatrices[boneIndex1][3].w)); + mat4 boneMatrixTransposed2 = mat4( + vec4(boneMatrices[boneIndex2][0].x, boneMatrices[boneIndex2][1].x, boneMatrices[boneIndex2][2].x, boneMatrices[boneIndex2][3].x), + vec4(boneMatrices[boneIndex2][0].y, boneMatrices[boneIndex2][1].y, boneMatrices[boneIndex2][2].y, boneMatrices[boneIndex2][3].y), + vec4(boneMatrices[boneIndex2][0].z, boneMatrices[boneIndex2][1].z, boneMatrices[boneIndex2][2].z, boneMatrices[boneIndex2][3].z), + vec4(boneMatrices[boneIndex2][0].w, boneMatrices[boneIndex2][1].w, boneMatrices[boneIndex2][2].w, boneMatrices[boneIndex2][3].w)); + mat4 boneMatrixTransposed3 = mat4( + vec4(boneMatrices[boneIndex3][0].x, boneMatrices[boneIndex3][1].x, boneMatrices[boneIndex3][2].x, boneMatrices[boneIndex3][3].x), + vec4(boneMatrices[boneIndex3][0].y, boneMatrices[boneIndex3][1].y, boneMatrices[boneIndex3][2].y, boneMatrices[boneIndex3][3].y), + vec4(boneMatrices[boneIndex3][0].z, boneMatrices[boneIndex3][1].z, boneMatrices[boneIndex3][2].z, boneMatrices[boneIndex3][3].z), + vec4(boneMatrices[boneIndex3][0].w, boneMatrices[boneIndex3][1].w, boneMatrices[boneIndex3][2].w, boneMatrices[boneIndex3][3].w)); + vec4 skinnedPosition = - vertexBoneWeights.x*(boneMatrices[boneIndex0]*vec4(vertexPosition, 1.0)) + - vertexBoneWeights.y*(boneMatrices[boneIndex1]*vec4(vertexPosition, 1.0)) + - vertexBoneWeights.z*(boneMatrices[boneIndex2]*vec4(vertexPosition, 1.0)) + - vertexBoneWeights.w*(boneMatrices[boneIndex3]*vec4(vertexPosition, 1.0)); + vertexBoneWeights.x*(boneMatrixTransposed0*vec4(vertexPosition, 1.0)) + + vertexBoneWeights.y*(boneMatrixTransposed1*vec4(vertexPosition, 1.0)) + + vertexBoneWeights.z*(boneMatrixTransposed2*vec4(vertexPosition, 1.0)) + + vertexBoneWeights.w*(boneMatrixTransposed3*vec4(vertexPosition, 1.0)); fragTexCoord = vertexTexCoord; fragColor = vertexColor; diff --git a/src/rlgl.h b/src/rlgl.h index 6cfc2dcfb..56462b8f8 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -4337,8 +4337,12 @@ void rlSetUniformMatrix(int locIndex, Matrix mat) // Set shader value uniform matrix void rlSetUniformMatrices(int locIndex, const Matrix *matrices, int count) { -#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - glUniformMatrix4fv(locIndex, count, true, (const float*)matrices); +#if defined(GRAPHICS_API_OPENGL_33) + glUniformMatrix4fv(locIndex, count, true, (const float *)matrices); +#elif defined(GRAPHICS_API_OPENGL_ES2) + // WARNING: WebGL does not support Matrix transpose ("true" parameter) + // REF: https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/uniformMatrix + glUniformMatrix4fv(locIndex, count, true, (const float *)matrices); #endif } From 5065b85d33ce6d7d696b7347bad4ba1ce70a1845 Mon Sep 17 00:00:00 2001 From: Ray Date: Thu, 24 Oct 2024 12:45:12 +0200 Subject: [PATCH 190/208] Update rlgl.h --- src/rlgl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rlgl.h b/src/rlgl.h index 56462b8f8..3730e1702 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -4342,7 +4342,7 @@ void rlSetUniformMatrices(int locIndex, const Matrix *matrices, int count) #elif defined(GRAPHICS_API_OPENGL_ES2) // WARNING: WebGL does not support Matrix transpose ("true" parameter) // REF: https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/uniformMatrix - glUniformMatrix4fv(locIndex, count, true, (const float *)matrices); + glUniformMatrix4fv(locIndex, count, false, (const float *)matrices); #endif } From 6ff0b03629bec6452d4576e1ffdc91864ef7db03 Mon Sep 17 00:00:00 2001 From: Ray Date: Thu, 24 Oct 2024 12:46:02 +0200 Subject: [PATCH 191/208] REVIEWED: `UpdateModelAnimationBoneMatrices()` comments --- examples/models/models_gpu_skinning.c | 11 ++++++----- src/raylib.h | 4 ++-- src/rmodels.c | 3 +++ 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/examples/models/models_gpu_skinning.c b/examples/models/models_gpu_skinning.c index 6868a62d3..7e81b0d82 100644 --- a/examples/models/models_gpu_skinning.c +++ b/examples/models/models_gpu_skinning.c @@ -93,10 +93,11 @@ int main(void) BeginMode3D(camera); - // Draw character + // Draw character mesh, pose calculation is done in shader (GPU skinning) DrawMesh(characterModel.meshes[0], characterModel.materials[1], characterModel.transform); DrawGrid(10, 1.0f); + EndMode3D(); DrawText("Use the T/G to switch animation", 10, 10, 20, GRAY); @@ -107,11 +108,11 @@ int main(void) // De-Initialization //-------------------------------------------------------------------------------------- - UnloadModelAnimations(modelAnimations, animsCount); - UnloadModel(characterModel); // Unload character model and meshes/material - UnloadShader(skinningShader); + UnloadModelAnimations(modelAnimations, animsCount); // Unload model animation + UnloadModel(characterModel); // Unload model and meshes/material + UnloadShader(skinningShader); // Unload GPU skinning shader - CloseWindow(); // Close window and OpenGL context + CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; diff --git a/src/raylib.h b/src/raylib.h index bc7bc372c..c9d9f6e54 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -1601,11 +1601,11 @@ RLAPI void SetModelMeshMaterial(Model *model, int meshId, int materialId); // Model animations loading/unloading functions RLAPI ModelAnimation *LoadModelAnimations(const char *fileName, int *animCount); // Load model animations from file -RLAPI void UpdateModelAnimation(Model model, ModelAnimation anim, int frame); // Update model animation pose +RLAPI void UpdateModelAnimation(Model model, ModelAnimation anim, int frame); // Update model animation pose (CPU) +RLAPI void UpdateModelAnimationBoneMatrices(Model model, ModelAnimation anim, int frame); // Update model animation mesh bone matrices (GPU skinning) RLAPI void UnloadModelAnimation(ModelAnimation anim); // Unload animation data RLAPI void UnloadModelAnimations(ModelAnimation *animations, int animCount); // Unload animation array data RLAPI bool IsModelAnimationValid(Model model, ModelAnimation anim); // Check model animation skeleton match -RLAPI void UpdateModelAnimationBoneMatrices(Model model, ModelAnimation anim, int frame); // Update model animation mesh bone matrices (Note GPU skinning does not work on Mac) // Collision detection functions RLAPI bool CheckCollisionSpheres(Vector3 center1, float radius1, Vector3 center2, float radius2); // Check collision between two spheres diff --git a/src/rmodels.c b/src/rmodels.c index 30130d9e0..ed15d9658 100644 --- a/src/rmodels.c +++ b/src/rmodels.c @@ -2364,6 +2364,9 @@ void UpdateModelAnimation(Model model, ModelAnimation anim, int frame) } } +// Update model animated bones transform matrices for a given frame +// NOTE: Updated data is not uploaded to GPU but kept at model.meshes[i].boneMatrices[boneId], +// to be uploaded to shader at drawing, in case GPU skinning is enabled void UpdateModelAnimationBoneMatrices(Model model, ModelAnimation anim, int frame) { if ((anim.frameCount > 0) && (anim.bones != NULL) && (anim.framePoses != NULL)) From cb73970f084e73a8f76a408fab8e5376b877ecbe Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 24 Oct 2024 10:46:22 +0000 Subject: [PATCH 192/208] Update raylib_api.* by CI --- parser/output/raylib_api.json | 40 +++++++++++++++++------------------ parser/output/raylib_api.lua | 22 +++++++++---------- parser/output/raylib_api.txt | 22 +++++++++---------- parser/output/raylib_api.xml | 12 +++++------ 4 files changed, 48 insertions(+), 48 deletions(-) diff --git a/parser/output/raylib_api.json b/parser/output/raylib_api.json index 47ede2e5a..37b0a16a6 100644 --- a/parser/output/raylib_api.json +++ b/parser/output/raylib_api.json @@ -11069,7 +11069,26 @@ }, { "name": "UpdateModelAnimation", - "description": "Update model animation pose", + "description": "Update model animation pose (CPU)", + "returnType": "void", + "params": [ + { + "type": "Model", + "name": "model" + }, + { + "type": "ModelAnimation", + "name": "anim" + }, + { + "type": "int", + "name": "frame" + } + ] + }, + { + "name": "UpdateModelAnimationBoneMatrices", + "description": "Update model animation mesh bone matrices (GPU skinning)", "returnType": "void", "params": [ { @@ -11127,25 +11146,6 @@ } ] }, - { - "name": "UpdateModelAnimationBoneMatrices", - "description": "Update model animation mesh bone matrices (Note GPU skinning does not work on Mac)", - "returnType": "void", - "params": [ - { - "type": "Model", - "name": "model" - }, - { - "type": "ModelAnimation", - "name": "anim" - }, - { - "type": "int", - "name": "frame" - } - ] - }, { "name": "CheckCollisionSpheres", "description": "Check collision between two spheres", diff --git a/parser/output/raylib_api.lua b/parser/output/raylib_api.lua index 20f2a8f0c..934c08eb7 100644 --- a/parser/output/raylib_api.lua +++ b/parser/output/raylib_api.lua @@ -7598,7 +7598,17 @@ return { }, { name = "UpdateModelAnimation", - description = "Update model animation pose", + description = "Update model animation pose (CPU)", + returnType = "void", + params = { + {type = "Model", name = "model"}, + {type = "ModelAnimation", name = "anim"}, + {type = "int", name = "frame"} + } + }, + { + name = "UpdateModelAnimationBoneMatrices", + description = "Update model animation mesh bone matrices (GPU skinning)", returnType = "void", params = { {type = "Model", name = "model"}, @@ -7632,16 +7642,6 @@ return { {type = "ModelAnimation", name = "anim"} } }, - { - name = "UpdateModelAnimationBoneMatrices", - description = "Update model animation mesh bone matrices (Note GPU skinning does not work on Mac)", - returnType = "void", - params = { - {type = "Model", name = "model"}, - {type = "ModelAnimation", name = "anim"}, - {type = "int", name = "frame"} - } - }, { name = "CheckCollisionSpheres", description = "Check collision between two spheres", diff --git a/parser/output/raylib_api.txt b/parser/output/raylib_api.txt index e409a0116..541b5caf3 100644 --- a/parser/output/raylib_api.txt +++ b/parser/output/raylib_api.txt @@ -4217,34 +4217,34 @@ Function 501: LoadModelAnimations() (2 input parameters) Function 502: UpdateModelAnimation() (3 input parameters) Name: UpdateModelAnimation Return type: void - Description: Update model animation pose + Description: Update model animation pose (CPU) Param[1]: model (type: Model) Param[2]: anim (type: ModelAnimation) Param[3]: frame (type: int) -Function 503: UnloadModelAnimation() (1 input parameters) +Function 503: UpdateModelAnimationBoneMatrices() (3 input parameters) + Name: UpdateModelAnimationBoneMatrices + Return type: void + Description: Update model animation mesh bone matrices (GPU skinning) + Param[1]: model (type: Model) + Param[2]: anim (type: ModelAnimation) + Param[3]: frame (type: int) +Function 504: UnloadModelAnimation() (1 input parameters) Name: UnloadModelAnimation Return type: void Description: Unload animation data Param[1]: anim (type: ModelAnimation) -Function 504: UnloadModelAnimations() (2 input parameters) +Function 505: UnloadModelAnimations() (2 input parameters) Name: UnloadModelAnimations Return type: void Description: Unload animation array data Param[1]: animations (type: ModelAnimation *) Param[2]: animCount (type: int) -Function 505: IsModelAnimationValid() (2 input parameters) +Function 506: IsModelAnimationValid() (2 input parameters) Name: IsModelAnimationValid Return type: bool Description: Check model animation skeleton match Param[1]: model (type: Model) Param[2]: anim (type: ModelAnimation) -Function 506: UpdateModelAnimationBoneMatrices() (3 input parameters) - Name: UpdateModelAnimationBoneMatrices - Return type: void - Description: Update model animation mesh bone matrices (Note GPU skinning does not work on Mac) - Param[1]: model (type: Model) - Param[2]: anim (type: ModelAnimation) - Param[3]: frame (type: int) Function 507: CheckCollisionSpheres() (4 input parameters) Name: CheckCollisionSpheres Return type: bool diff --git a/parser/output/raylib_api.xml b/parser/output/raylib_api.xml index 9ab4b52cc..58794b4eb 100644 --- a/parser/output/raylib_api.xml +++ b/parser/output/raylib_api.xml @@ -2821,7 +2821,12 @@ - + + + + + + @@ -2837,11 +2842,6 @@ - - - - - From 6962364bfb8f21a867e70e6a35a9bbbe255a8889 Mon Sep 17 00:00:00 2001 From: Ray Date: Thu, 24 Oct 2024 12:53:16 +0200 Subject: [PATCH 193/208] Update emsdk paths to latest versions --- projects/4coder/Makefile | 4 ++-- projects/VSCode/Makefile | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/projects/4coder/Makefile b/projects/4coder/Makefile index f2091f0e3..8e64702a6 100644 --- a/projects/4coder/Makefile +++ b/projects/4coder/Makefile @@ -117,8 +117,8 @@ ifeq ($(PLATFORM),PLATFORM_WEB) EMSDK_PATH ?= C:/emsdk EMSCRIPTEN_PATH ?= $(EMSDK_PATH)/upstream/emscripten CLANG_PATH = $(EMSDK_PATH)/upstream/bin - PYTHON_PATH = $(EMSDK_PATH)/python/3.9.2-1_64bit - NODE_PATH = $(EMSDK_PATH)/node/14.15.5_64bit/bin + PYTHON_PATH = $(EMSDK_PATH)/python/3.9.2-nuget_64bit + NODE_PATH = $(EMSDK_PATH)/node/20.18.0_64bit/bin export PATH = $(EMSDK_PATH);$(EMSCRIPTEN_PATH);$(CLANG_PATH);$(NODE_PATH);$(PYTHON_PATH);C:\raylib\MinGW\bin:$$(PATH) endif diff --git a/projects/VSCode/Makefile b/projects/VSCode/Makefile index 86febfba0..65a6f9544 100644 --- a/projects/VSCode/Makefile +++ b/projects/VSCode/Makefile @@ -120,8 +120,8 @@ ifeq ($(PLATFORM),PLATFORM_WEB) EMSDK_PATH ?= C:/emsdk EMSCRIPTEN_PATH ?= $(EMSDK_PATH)/upstream/emscripten CLANG_PATH = $(EMSDK_PATH)/upstream/bin - PYTHON_PATH = $(EMSDK_PATH)/python/3.9.2-1_64bit - NODE_PATH = $(EMSDK_PATH)/node/14.18.2_64bit/bin + PYTHON_PATH = $(EMSDK_PATH)/python/3.9.2-nuget_64bit + NODE_PATH = $(EMSDK_PATH)/node/20.18.0_64bit/bin export PATH = $(EMSDK_PATH);$(EMSCRIPTEN_PATH);$(CLANG_PATH);$(NODE_PATH);$(PYTHON_PATH):$$(PATH) endif From 385187f795bdeaf810099e004c59883a39b4d9b4 Mon Sep 17 00:00:00 2001 From: RadsammyT <32146976+RadsammyT@users.noreply.github.com> Date: Thu, 24 Oct 2024 07:08:12 -0400 Subject: [PATCH 194/208] [rshapes] Review `DrawRectangleLines()` pixel offset (#4261) * [rshapes] Remove `DrawRectangleLines()`'s + 1 offset * ... and replace it with a -/+ 0.5 offset divided by current cam's zoom. --- src/rshapes.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/rshapes.c b/src/rshapes.c index 1479a6f37..f62778e83 100644 --- a/src/rshapes.c +++ b/src/rshapes.c @@ -807,19 +807,21 @@ void DrawRectangleGradientEx(Rectangle rec, Color topLeft, Color bottomLeft, Col // but it solves another issue: https://github.com/raysan5/raylib/issues/3884 void DrawRectangleLines(int posX, int posY, int width, int height, Color color) { + Matrix mat = rlGetMatrixModelview(); + float zoomElement = 0.5f / mat.m0; rlBegin(RL_LINES); rlColor4ub(color.r, color.g, color.b, color.a); - rlVertex2f((float)posX, (float)posY); - rlVertex2f((float)posX + (float)width, (float)posY + 1); + rlVertex2f((float)posX - zoomElement, (float)posY); + rlVertex2f((float)posX + (float)width + zoomElement, (float)posY); - rlVertex2f((float)posX + (float)width, (float)posY + 1); - rlVertex2f((float)posX + (float)width, (float)posY + (float)height); + rlVertex2f((float)posX + (float)width, (float)posY - zoomElement); + rlVertex2f((float)posX + (float)width, (float)posY + (float)height + zoomElement); - rlVertex2f((float)posX + (float)width, (float)posY + (float)height); - rlVertex2f((float)posX + 1, (float)posY + (float)height); + rlVertex2f((float)posX + (float)width + zoomElement, (float)posY + (float)height); + rlVertex2f((float)posX - zoomElement, (float)posY + (float)height); - rlVertex2f((float)posX + 1, (float)posY + (float)height); - rlVertex2f((float)posX + 1, (float)posY + 1); + rlVertex2f((float)posX, (float)posY + (float)height + zoomElement); + rlVertex2f((float)posX, (float)posY - zoomElement); rlEnd(); } From 16368cd3539c1f9ed09e9491964d3f945072e137 Mon Sep 17 00:00:00 2001 From: Ray Date: Thu, 24 Oct 2024 13:11:39 +0200 Subject: [PATCH 195/208] REVIEWED: `DrawRectangleLines()`, considering view matrix for lines "alignment" --- src/rshapes.c | 42 +++++++++++++++++++++++++++++++++--------- 1 file changed, 33 insertions(+), 9 deletions(-) diff --git a/src/rshapes.c b/src/rshapes.c index f62778e83..ece5513b3 100644 --- a/src/rshapes.c +++ b/src/rshapes.c @@ -808,21 +808,45 @@ void DrawRectangleGradientEx(Rectangle rec, Color topLeft, Color bottomLeft, Col void DrawRectangleLines(int posX, int posY, int width, int height, Color color) { Matrix mat = rlGetMatrixModelview(); - float zoomElement = 0.5f / mat.m0; + float zoomFactor = 0.5f/mat.m0; rlBegin(RL_LINES); rlColor4ub(color.r, color.g, color.b, color.a); - rlVertex2f((float)posX - zoomElement, (float)posY); - rlVertex2f((float)posX + (float)width + zoomElement, (float)posY); + rlVertex2f((float)posX - zoomFactor, (float)posY); + rlVertex2f((float)posX + (float)width + zoomFactor, (float)posY); - rlVertex2f((float)posX + (float)width, (float)posY - zoomElement); - rlVertex2f((float)posX + (float)width, (float)posY + (float)height + zoomElement); + rlVertex2f((float)posX + (float)width, (float)posY - zoomFactor); + rlVertex2f((float)posX + (float)width, (float)posY + (float)height + zoomFactor); - rlVertex2f((float)posX + (float)width + zoomElement, (float)posY + (float)height); - rlVertex2f((float)posX - zoomElement, (float)posY + (float)height); + rlVertex2f((float)posX + (float)width + zoomFactor, (float)posY + (float)height); + rlVertex2f((float)posX - zoomFactor, (float)posY + (float)height); - rlVertex2f((float)posX, (float)posY + (float)height + zoomElement); - rlVertex2f((float)posX, (float)posY - zoomElement); + rlVertex2f((float)posX, (float)posY + (float)height + zoomFactor); + rlVertex2f((float)posX, (float)posY - zoomFactor); rlEnd(); +/* +// Previous implementation, it has issues... but it does not require view matrix... +#if defined(SUPPORT_QUADS_DRAW_MODE) + DrawRectangle(posX, posY, width, 1, color); + DrawRectangle(posX + width - 1, posY + 1, 1, height - 2, color); + DrawRectangle(posX, posY + height - 1, width, 1, color); + DrawRectangle(posX, posY + 1, 1, height - 2, color); +#else + rlBegin(RL_LINES); + rlColor4ub(color.r, color.g, color.b, color.a); + rlVertex2f((float)posX, (float)posY); + rlVertex2f((float)posX + (float)width, (float)posY + 1); + + rlVertex2f((float)posX + (float)width, (float)posY + 1); + rlVertex2f((float)posX + (float)width, (float)posY + (float)height); + + rlVertex2f((float)posX + (float)width, (float)posY + (float)height); + rlVertex2f((float)posX + 1, (float)posY + (float)height); + + rlVertex2f((float)posX + 1, (float)posY + (float)height); + rlVertex2f((float)posX + 1, (float)posY + 1); + rlEnd(); +//#endif +*/ } // Draw rectangle outline with extended parameters From 15f6c47f0715afd1fce52d760053026c2b92214c Mon Sep 17 00:00:00 2001 From: IcyLeave6109 <33421921+juliohq@users.noreply.github.com> Date: Thu, 24 Oct 2024 12:49:47 -0300 Subject: [PATCH 196/208] Use free camera in model shader example (#4428) --- examples/shaders/shaders_model_shader.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/shaders/shaders_model_shader.c b/examples/shaders/shaders_model_shader.c index bf2c112be..9faa2d589 100644 --- a/examples/shaders/shaders_model_shader.c +++ b/examples/shaders/shaders_model_shader.c @@ -69,7 +69,7 @@ int main(void) { // Update //---------------------------------------------------------------------------------- - UpdateCamera(&camera, CAMERA_FIRST_PERSON); + UpdateCamera(&camera, CAMERA_FREE); //---------------------------------------------------------------------------------- // Draw From 6c3b1fa1de340df67189839e372ce03bea5c625e Mon Sep 17 00:00:00 2001 From: Jeffery Myers Date: Thu, 24 Oct 2024 14:37:23 -0700 Subject: [PATCH 197/208] Add shadow map example to MSVC projects (#4430) --- .../VS2022/examples/shaders_shadowmap.vcxproj | 387 ++++++++++++++++++ projects/VS2022/raylib.sln | 36 +- 2 files changed, 406 insertions(+), 17 deletions(-) create mode 100644 projects/VS2022/examples/shaders_shadowmap.vcxproj diff --git a/projects/VS2022/examples/shaders_shadowmap.vcxproj b/projects/VS2022/examples/shaders_shadowmap.vcxproj new file mode 100644 index 000000000..d1ec9b23a --- /dev/null +++ b/projects/VS2022/examples/shaders_shadowmap.vcxproj @@ -0,0 +1,387 @@ + + + + + Debug.DLL + Win32 + + + Debug.DLL + x64 + + + Debug + Win32 + + + Debug + x64 + + + Release.DLL + Win32 + + + Release.DLL + x64 + + + Release + Win32 + + + Release + x64 + + + + {41BBCC10-6FDE-48A1-B2E0-A0EC6A668629} + Win32Proj + shaders_shadowmap + 10.0 + shaders_shadowmap + + + + Application + true + $(DefaultPlatformToolset) + Unicode + + + Application + true + $(DefaultPlatformToolset) + Unicode + + + Application + true + $(DefaultPlatformToolset) + Unicode + + + Application + true + $(DefaultPlatformToolset) + Unicode + + + Application + false + $(DefaultPlatformToolset) + true + Unicode + + + Application + false + $(DefaultPlatformToolset) + true + Unicode + + + Application + false + $(DefaultPlatformToolset) + true + Unicode + + + Application + false + $(DefaultPlatformToolset) + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ + $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ + + + true + $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ + $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ + + + true + $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ + $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ + + + true + $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ + $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ + + + false + $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ + $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ + + + false + $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ + $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ + + + false + $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ + $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ + + + false + $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ + $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ + + + $(SolutionDir)..\..\examples\shaders + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shaders + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shaders + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shaders + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shaders + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shaders + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shaders + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shaders + WindowsLocalDebugger + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions) + CompileAsC + $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories) + + + Console + true + $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\ + raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions) + CompileAsC + $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories) + /FS %(AdditionalOptions) + + + Console + true + $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\ + raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions) + CompileAsC + $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories) + + + Console + true + $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\ + raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)" + Copy Debug DLL to output directory + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions) + CompileAsC + $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories) + + + Console + true + $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\ + raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)" + Copy Debug DLL to output directory + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP + $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories) + CompileAsC + true + + + Console + true + true + true + raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\ + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP + $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories) + CompileAsC + true + + + Console + true + true + true + raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\ + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP + $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories) + CompileAsC + true + + + Console + true + true + true + raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\ + + + xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)" + + + Copy Release DLL to output directory + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP + $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories) + CompileAsC + true + + + Console + true + true + true + raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\ + + + xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)" + + + Copy Release DLL to output directory + + + + + + + + {e89d61ac-55de-4482-afd4-df7242ebc859} + + + + + + \ No newline at end of file diff --git a/projects/VS2022/raylib.sln b/projects/VS2022/raylib.sln index 1dbd38984..9ce0521ee 100644 --- a/projects/VS2022/raylib.sln +++ b/projects/VS2022/raylib.sln @@ -299,6 +299,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shapes_top_down_lights", "e EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "models_gpu_skinning", "examples\models_gpu_skinning.vcxproj", "{8245DAD9-D402-4D5C-8F45-32229CD3B263}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shaders_shadowmap", "examples\shaders_shadowmap.vcxproj", "{41BBCC10-6FDE-48A1-B2E0-A0EC6A668629}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug.DLL|x64 = Debug.DLL|x64 @@ -2483,22 +2485,6 @@ Global {EFA150D4-F93B-4D7D-A69C-9E8B4663BECD}.Release|x64.Build.0 = Release|x64 {EFA150D4-F93B-4D7D-A69C-9E8B4663BECD}.Release|x86.ActiveCfg = Release|Win32 {EFA150D4-F93B-4D7D-A69C-9E8B4663BECD}.Release|x86.Build.0 = Release|Win32 - {D8026C60-CCBC-45DF-9085-BF21569EB414}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 - {D8026C60-CCBC-45DF-9085-BF21569EB414}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 - {D8026C60-CCBC-45DF-9085-BF21569EB414}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 - {D8026C60-CCBC-45DF-9085-BF21569EB414}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 - {D8026C60-CCBC-45DF-9085-BF21569EB414}.Debug|x64.ActiveCfg = Debug|x64 - {D8026C60-CCBC-45DF-9085-BF21569EB414}.Debug|x64.Build.0 = Debug|x64 - {D8026C60-CCBC-45DF-9085-BF21569EB414}.Debug|x86.ActiveCfg = Debug|Win32 - {D8026C60-CCBC-45DF-9085-BF21569EB414}.Debug|x86.Build.0 = Debug|Win32 - {D8026C60-CCBC-45DF-9085-BF21569EB414}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 - {D8026C60-CCBC-45DF-9085-BF21569EB414}.Release.DLL|x64.Build.0 = Release.DLL|x64 - {D8026C60-CCBC-45DF-9085-BF21569EB414}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 - {D8026C60-CCBC-45DF-9085-BF21569EB414}.Release.DLL|x86.Build.0 = Release.DLL|Win32 - {D8026C60-CCBC-45DF-9085-BF21569EB414}.Release|x64.ActiveCfg = Release|x64 - {D8026C60-CCBC-45DF-9085-BF21569EB414}.Release|x64.Build.0 = Release|x64 - {D8026C60-CCBC-45DF-9085-BF21569EB414}.Release|x86.ActiveCfg = Release|Win32 - {D8026C60-CCBC-45DF-9085-BF21569EB414}.Release|x86.Build.0 = Release|Win32 {DF25E545-00FF-4E64-844C-7DF98991F901}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 {DF25E545-00FF-4E64-844C-7DF98991F901}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 {DF25E545-00FF-4E64-844C-7DF98991F901}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 @@ -2547,6 +2533,22 @@ Global {8245DAD9-D402-4D5C-8F45-32229CD3B263}.Release|x64.Build.0 = Release|x64 {8245DAD9-D402-4D5C-8F45-32229CD3B263}.Release|x86.ActiveCfg = Release|Win32 {8245DAD9-D402-4D5C-8F45-32229CD3B263}.Release|x86.Build.0 = Release|Win32 + {41BBCC10-6FDE-48A1-B2E0-A0EC6A668629}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 + {41BBCC10-6FDE-48A1-B2E0-A0EC6A668629}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 + {41BBCC10-6FDE-48A1-B2E0-A0EC6A668629}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 + {41BBCC10-6FDE-48A1-B2E0-A0EC6A668629}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 + {41BBCC10-6FDE-48A1-B2E0-A0EC6A668629}.Debug|x64.ActiveCfg = Debug|x64 + {41BBCC10-6FDE-48A1-B2E0-A0EC6A668629}.Debug|x64.Build.0 = Debug|x64 + {41BBCC10-6FDE-48A1-B2E0-A0EC6A668629}.Debug|x86.ActiveCfg = Debug|Win32 + {41BBCC10-6FDE-48A1-B2E0-A0EC6A668629}.Debug|x86.Build.0 = Debug|Win32 + {41BBCC10-6FDE-48A1-B2E0-A0EC6A668629}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 + {41BBCC10-6FDE-48A1-B2E0-A0EC6A668629}.Release.DLL|x64.Build.0 = Release.DLL|x64 + {41BBCC10-6FDE-48A1-B2E0-A0EC6A668629}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 + {41BBCC10-6FDE-48A1-B2E0-A0EC6A668629}.Release.DLL|x86.Build.0 = Release.DLL|Win32 + {41BBCC10-6FDE-48A1-B2E0-A0EC6A668629}.Release|x64.ActiveCfg = Release|x64 + {41BBCC10-6FDE-48A1-B2E0-A0EC6A668629}.Release|x64.Build.0 = Release|x64 + {41BBCC10-6FDE-48A1-B2E0-A0EC6A668629}.Release|x86.ActiveCfg = Release|Win32 + {41BBCC10-6FDE-48A1-B2E0-A0EC6A668629}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -2695,10 +2697,10 @@ Global {88DE5AD6-0074-4A5A-BE22-C840153E35D5} = {5317807F-61D4-4E0F-B6DC-2D9F12621ED9} {A546E75A-5242-46E6-9A9E-6C91554EAB84} = {5317807F-61D4-4E0F-B6DC-2D9F12621ED9} {EFA150D4-F93B-4D7D-A69C-9E8B4663BECD} = {5317807F-61D4-4E0F-B6DC-2D9F12621ED9} - {D8026C60-CCBC-45DF-9085-BF21569EB414} = {DA049009-21FF-4AC0-84E4-830DD1BCD0CE} {DF25E545-00FF-4E64-844C-7DF98991F901} = {278D8859-20B1-428F-8448-064F46E1F021} {703BE7BA-5B99-4F70-806D-3A259F6A991E} = {278D8859-20B1-428F-8448-064F46E1F021} {8245DAD9-D402-4D5C-8F45-32229CD3B263} = {AF5BEC5C-1F2B-4DA8-B12D-D09FE569237C} + {41BBCC10-6FDE-48A1-B2E0-A0EC6A668629} = {5317807F-61D4-4E0F-B6DC-2D9F12621ED9} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {E926C768-6307-4423-A1EC-57E95B1FAB29} From 728ccc96bcbcd631f7523cff9c87e1b581db209a Mon Sep 17 00:00:00 2001 From: Jeffery Myers Date: Thu, 24 Oct 2024 14:49:30 -0700 Subject: [PATCH 198/208] Use the vertex color as part of the base shader in GLSL330 (#4431) --- examples/shaders/resources/shaders/glsl330/base.fs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/examples/shaders/resources/shaders/glsl330/base.fs b/examples/shaders/resources/shaders/glsl330/base.fs index 6b5006224..813f32b1d 100644 --- a/examples/shaders/resources/shaders/glsl330/base.fs +++ b/examples/shaders/resources/shaders/glsl330/base.fs @@ -20,6 +20,9 @@ void main() // NOTE: Implement here your fragment shader code - finalColor = texelColor*colDiffuse; + // final color is the color from the texture + // times the tint color (colDiffuse) + // times the fragment color (interpolated vertex color) + finalColor = texelColor*colDiffuse*fragColor; } From f03f093909ec899eecbc298063afd2ca37ce6b07 Mon Sep 17 00:00:00 2001 From: Jeffery Myers Date: Fri, 25 Oct 2024 00:47:04 -0700 Subject: [PATCH 199/208] Add input_virtual_controls to MSVC projects (#4433) Fix input_virtual_controls example to use correct default font sizes --- examples/core/core_input_virtual_controls.c | 22 +++++++++--------- examples/core/core_input_virtual_controls.png | Bin 9604 -> 9094 bytes projects/VS2022/raylib.sln | 19 +++++++++++++++ 3 files changed, 30 insertions(+), 11 deletions(-) diff --git a/examples/core/core_input_virtual_controls.c b/examples/core/core_input_virtual_controls.c index ae7f770aa..2d2b91e67 100644 --- a/examples/core/core_input_virtual_controls.c +++ b/examples/core/core_input_virtual_controls.c @@ -54,8 +54,8 @@ int main(void) // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { - // Update - //-------------------------------------------------------------------------- + // Update + //-------------------------------------------------------------------------- dpadKeydown = -1; //reset float inputX=0; float inputY=0; @@ -89,10 +89,9 @@ int main(void) case 3: playerY += 50*GetFrameTime(); default:; }; - //-------------------------------------------------------------------------- - - // Draw - //-------------------------------------------------------------------------- + //-------------------------------------------------------------------------- + // Draw + //-------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); for(int i=0;i<4;i++) @@ -103,14 +102,15 @@ int main(void) { //draw label DrawText(TextSubtext(dpadLabel,i,1), - dpadCollider[i][0]-5, - dpadCollider[i][1]-5,16,BLACK); + dpadCollider[i][0]-7, + dpadCollider[i][1]-8,20,BLACK); } - } - DrawText("Player",playerX,playerY,16,BLACK); + + DrawRectangle(playerX-4,playerY-4,75,28,RED); + DrawText("Player",playerX,playerY,20,WHITE); EndDrawing(); - //-------------------------------------------------------------------------- + //-------------------------------------------------------------------------- } // De-Initialization diff --git a/examples/core/core_input_virtual_controls.png b/examples/core/core_input_virtual_controls.png index a9776e68a3dfdd01f5b8afc51859ace27a150622..cb1444598017b9d7ff83480f66909c8523ece519 100644 GIT binary patch literal 9094 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 H{`@}x#HYs# literal 9604 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 bk Date: Fri, 25 Oct 2024 08:47:35 +0100 Subject: [PATCH 200/208] [build] CMake: Don't build for wayland by default (#4432) This is to align with the behavior of #4369, see #4371 for rationale on disabling Wayland by default. --- CMakeOptions.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeOptions.txt b/CMakeOptions.txt index ce9141e22..b387922b4 100644 --- a/CMakeOptions.txt +++ b/CMakeOptions.txt @@ -21,7 +21,7 @@ cmake_dependent_option(USE_AUDIO "Build raylib with audio module" ON CUSTOMIZE_B enum_option(USE_EXTERNAL_GLFW "OFF;IF_POSSIBLE;ON" "Link raylib against system GLFW instead of embedded one") # GLFW build options -option(GLFW_BUILD_WAYLAND "Build the bundled GLFW with Wayland support" ON) +option(GLFW_BUILD_WAYLAND "Build the bundled GLFW with Wayland support" OFF) option(GLFW_BUILD_X11 "Build the bundled GLFW with X11 support" ON) option(INCLUDE_EVERYTHING "Include everything disabled by default (for CI usage" OFF) From 8b36253e2f735da42ee895b3ef51b33ca3f0fed4 Mon Sep 17 00:00:00 2001 From: Asdqwe Date: Fri, 25 Oct 2024 18:47:55 -0300 Subject: [PATCH 201/208] [build] [web] Fix examples `Makefile` for `PLATFORM_WEB` (#4434) * Fix examples Makefile for PLATFORM_WEB * Replace shell with assignment operator * Replace tab with spaces --- examples/Makefile | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/examples/Makefile b/examples/Makefile index be9751db1..3961152c2 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -197,7 +197,12 @@ ifeq ($(TARGET_PLATFORM),PLATFORM_ANDROID) MAKE = mingw32-make endif ifeq ($(TARGET_PLATFORM),PLATFORM_WEB) - MAKE = mingw32-make + EMMAKE != type emmake + ifneq (, $(EMMAKE)) + MAKE = emmake make + else + MAKE = mingw32-make + endif endif # Define compiler flags: CFLAGS @@ -451,7 +456,7 @@ ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_RGFW) ifeq ($(PLATFORM_OS),OSX) # Libraries for Debian GNU/Linux desktop compiling # NOTE: Required packages: libegl1-mesa-dev - LDLIBS = ../src/libraylib.a -lm + LDLIBS = ../src/libraylib.a -lm LDLIBS += -framework Foundation -framework AppKit -framework OpenGL -framework CoreVideo endif endif From 7ac36e20cd1e4c6c6f6d5cbf2439927fcced5c0b Mon Sep 17 00:00:00 2001 From: Ray Date: Fri, 25 Oct 2024 23:55:31 +0200 Subject: [PATCH 202/208] Update Makefile.Web --- examples/Makefile.Web | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/examples/Makefile.Web b/examples/Makefile.Web index 5155458e0..0e1337fb0 100644 --- a/examples/Makefile.Web +++ b/examples/Makefile.Web @@ -139,7 +139,7 @@ endif # Define default make program: MAKE #------------------------------------------------------------------------------------------------ -MAKE ?= emmake make +MAKE ?= make ifeq ($(PLATFORM),PLATFORM_DESKTOP) ifeq ($(PLATFORM_OS),WINDOWS) @@ -149,8 +149,13 @@ endif ifeq ($(PLATFORM),PLATFORM_ANDROID) MAKE = mingw32-make endif -ifeq ($(PLATFORM),PLATFORM_WEB) - MAKE = emmake make +ifeq ($(TARGET_PLATFORM),PLATFORM_WEB) + EMMAKE != type emmake + ifneq (, $(EMMAKE)) + MAKE = emmake make + else + MAKE = mingw32-make + endif endif # Define compiler flags: CFLAGS From 22c77d17b7204c4f680d10c93e41d66f645ef32e Mon Sep 17 00:00:00 2001 From: Ray Date: Sat, 26 Oct 2024 00:51:37 +0200 Subject: [PATCH 203/208] REVIEWED: WebGL2 (OpenGL ES 3.0) backend flags (PLATFORM_WEB) #4330 --- examples/Makefile.Web | 10 ++++++++++ src/Makefile | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/examples/Makefile.Web b/examples/Makefile.Web index 0e1337fb0..ade9bfc26 100644 --- a/examples/Makefile.Web +++ b/examples/Makefile.Web @@ -52,6 +52,10 @@ USE_EXTERNAL_GLFW ?= FALSE # NOTE: This variable is only used for PLATFORM_OS: LINUX USE_WAYLAND_DISPLAY ?= FALSE +# Use WebGL2 backend (OpenGL 3.0) +# WARNING: Requires raylib compiled with GRAPHICS_API_OPENGL_ES3 +USE_WEBGL2 ?= FALSE + # Determine PLATFORM_OS in case PLATFORM_DESKTOP or PLATFORM_WEB selected ifeq ($(PLATFORM),$(filter $(PLATFORM),PLATFORM_DESKTOP PLATFORM_WEB)) # No uname.exe on MinGW!, but OS=Windows_NT on Windows! @@ -265,6 +269,12 @@ ifeq ($(PLATFORM),PLATFORM_WEB) # --preload-file resources # specify a resources folder for data compilation # --source-map-base # allow debugging in browser with source map LDFLAGS += -sUSE_GLFW=3 -sASYNCIFY -sEXPORTED_RUNTIME_METHODS=ccall + + # NOTE: Flags required for WebGL 2.0 (OpenGL ES 3.0) + # WARNING: Requires raylib compiled with GRAPHICS_API_OPENGL_ES3 + ifeq ($(USE_WEBGL2),TRUE) + LDFLAGS += -sMIN_WEBGL_VERSION=2 -sMAX_WEBGL_VERSION=2 + endif # 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 diff --git a/src/Makefile b/src/Makefile index 84be9f5a0..1f0b730c6 100644 --- a/src/Makefile +++ b/src/Makefile @@ -255,7 +255,7 @@ endif ifeq ($(TARGET_PLATFORM),PLATFORM_WEB) # On HTML5 OpenGL ES 2.0 is used, emscripten translates it to WebGL 1.0 GRAPHICS = GRAPHICS_API_OPENGL_ES2 - #GRAPHICS = GRAPHICS_API_OPENGL_ES3 # Uncomment to use ES3/WebGL2 (preliminary support) + #GRAPHICS = GRAPHICS_API_OPENGL_ES3 endif ifeq ($(TARGET_PLATFORM),PLATFORM_ANDROID) # By default use OpenGL ES 2.0 on Android From 4e3fc84050b1f30469dd08e8e910604dc817cc64 Mon Sep 17 00:00:00 2001 From: Ray Date: Sat, 26 Oct 2024 00:52:22 +0200 Subject: [PATCH 204/208] Minor format tweaks --- src/rlgl.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/rlgl.h b/src/rlgl.h index 3730e1702..3d6a00628 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -3060,15 +3060,15 @@ void rlDrawRenderBatch(rlRenderBatch *batch) if ((batch->draws[i].mode == RL_LINES) || (batch->draws[i].mode == RL_TRIANGLES)) glDrawArrays(batch->draws[i].mode, vertexOffset, batch->draws[i].vertexCount); else { -#if defined(GRAPHICS_API_OPENGL_33) + #if defined(GRAPHICS_API_OPENGL_33) // We need to define the number of indices to be processed: elementCount*6 // NOTE: The final parameter tells the GPU the offset in bytes from the // start of the index buffer to the location of the first index to process glDrawElements(GL_TRIANGLES, batch->draws[i].vertexCount/4*6, GL_UNSIGNED_INT, (GLvoid *)(vertexOffset/4*6*sizeof(GLuint))); -#endif -#if defined(GRAPHICS_API_OPENGL_ES2) + #endif + #if defined(GRAPHICS_API_OPENGL_ES2) glDrawElements(GL_TRIANGLES, batch->draws[i].vertexCount/4*6, GL_UNSIGNED_SHORT, (GLvoid *)(vertexOffset/4*6*sizeof(GLushort))); -#endif + #endif } vertexOffset += (batch->draws[i].vertexCount + batch->draws[i].vertexAlignment); @@ -4946,7 +4946,7 @@ static void rlLoadShaderDefault(void) RLGL.State.defaultShaderLocs[RL_SHADER_LOC_VERTEX_COLOR] = glGetAttribLocation(RLGL.State.defaultShaderId, RL_DEFAULT_SHADER_ATTRIB_NAME_COLOR); // Set default shader locations: uniform locations - RLGL.State.defaultShaderLocs[RL_SHADER_LOC_MATRIX_MVP] = glGetUniformLocation(RLGL.State.defaultShaderId, RL_DEFAULT_SHADER_UNIFORM_NAME_MVP); + RLGL.State.defaultShaderLocs[RL_SHADER_LOC_MATRIX_MVP] = glGetUniformLocation(RLGL.State.defaultShaderId, RL_DEFAULT_SHADER_UNIFORM_NAME_MVP); RLGL.State.defaultShaderLocs[RL_SHADER_LOC_COLOR_DIFFUSE] = glGetUniformLocation(RLGL.State.defaultShaderId, RL_DEFAULT_SHADER_UNIFORM_NAME_COLOR); RLGL.State.defaultShaderLocs[RL_SHADER_LOC_MAP_DIFFUSE] = glGetUniformLocation(RLGL.State.defaultShaderId, RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE0); } From 91a4f047942b4eb261c47291496a2cbed03e5c0d Mon Sep 17 00:00:00 2001 From: Asdqwe Date: Sat, 26 Oct 2024 06:39:24 -0300 Subject: [PATCH 205/208] Use mingw32-make for Windows (#4436) --- examples/Makefile | 12 ++++++++---- examples/Makefile.Web | 38 +++++++++++++++++++++----------------- 2 files changed, 29 insertions(+), 21 deletions(-) diff --git a/examples/Makefile b/examples/Makefile index 3961152c2..969c246e1 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -197,11 +197,15 @@ ifeq ($(TARGET_PLATFORM),PLATFORM_ANDROID) MAKE = mingw32-make endif ifeq ($(TARGET_PLATFORM),PLATFORM_WEB) - EMMAKE != type emmake - ifneq (, $(EMMAKE)) - MAKE = emmake make - else + ifeq ($(OS),Windows_NT) MAKE = mingw32-make + else + EMMAKE != type emmake + ifneq (, $(EMMAKE)) + MAKE = emmake make + else + MAKE = mingw32-make + endif endif endif diff --git a/examples/Makefile.Web b/examples/Makefile.Web index ade9bfc26..7e2aaacc5 100644 --- a/examples/Makefile.Web +++ b/examples/Makefile.Web @@ -154,11 +154,15 @@ ifeq ($(PLATFORM),PLATFORM_ANDROID) MAKE = mingw32-make endif ifeq ($(TARGET_PLATFORM),PLATFORM_WEB) - EMMAKE != type emmake - ifneq (, $(EMMAKE)) - MAKE = emmake make - else + ifeq ($(OS),Windows_NT) MAKE = mingw32-make + else + EMMAKE != type emmake + ifneq (, $(EMMAKE)) + MAKE = emmake make + else + MAKE = mingw32-make + endif endif endif @@ -269,7 +273,7 @@ ifeq ($(PLATFORM),PLATFORM_WEB) # --preload-file resources # specify a resources folder for data compilation # --source-map-base # allow debugging in browser with source map LDFLAGS += -sUSE_GLFW=3 -sASYNCIFY -sEXPORTED_RUNTIME_METHODS=ccall - + # NOTE: Flags required for WebGL 2.0 (OpenGL ES 3.0) # WARNING: Requires raylib compiled with GRAPHICS_API_OPENGL_ES3 ifeq ($(USE_WEBGL2),TRUE) @@ -556,10 +560,10 @@ core/core_3d_camera_split_screen: core/core_3d_camera_split_screen.c core/core_3d_picking: core/core_3d_picking.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) - + core/core_automation_events : core/core_automation_events.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) - + core/core_basic_window: core/core_basic_window.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) @@ -658,7 +662,7 @@ shapes/shapes_draw_circle_sector: shapes/shapes_draw_circle_sector.c shapes/shapes_draw_rectangle_rounded: shapes/shapes_draw_rectangle_rounded.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) - + shapes/shapes_draw_ring: shapes/shapes_draw_ring.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) @@ -728,7 +732,7 @@ textures/textures_image_drawing: textures/textures_image_drawing.c textures/textures_image_generation: textures/textures_image_generation.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) -sTOTAL_MEMORY=67108864 - + textures/textures_image_kernel: textures/textures_image_kernel.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \ --preload-file textures/resources/cat.png@resources/cat.png @@ -804,7 +808,7 @@ textures/textures_to_image: textures/textures_to_image.c text/text_codepoints_loading: text/text_codepoints_loading.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \ --preload-file text/resources/DotGothic16-Regular.ttf@resources/DotGothic16-Regular.ttf - + text/text_draw_3d: text/text_draw_3d.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \ --preload-file text/resources/shaders/glsl100/alpha_discard.fs@resources/shaders/glsl100/alpha_discard.fs @@ -869,7 +873,7 @@ models/models_animation: models/models_animation.c --preload-file models/resources/models/iqm/guy.iqm@resources/models/iqm/guy.iqm \ --preload-file models/resources/models/iqm/guytex.png@resources/models/iqm/guytex.png \ --preload-file models/resources/models/iqm/guyanim.iqm@resources/models/iqm/guyanim.iqm - + models/models_gpu_skinning: models/models_gpu_skinning.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) -sTOTAL_MEMORY=67108864 \ --preload-file models/resources/models/gltf/greenman.glb@resources/models/gltf/greenman.glb \ @@ -899,7 +903,7 @@ models/models_first_person_maze: models/models_first_person_maze.c models/models_geometric_shapes: models/models_geometric_shapes.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) - + models/models_heightmap: models/models_heightmap.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \ --preload-file models/resources/heightmap.png@resources/heightmap.png @@ -908,7 +912,7 @@ models/models_loading: models/models_loading.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) -sTOTAL_MEMORY=67108864 \ --preload-file models/resources/models/obj/castle.obj@resources/models/obj/castle.obj \ --preload-file models/resources/models/obj/castle_diffuse.png@resources/models/obj/castle_diffuse.png - + models/models_loading_gltf: models/models_loading_gltf.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) -sTOTAL_MEMORY=67108864 \ --preload-file models/resources/models/gltf/robot.glb@resources/models/gltf/robot.glb @@ -916,12 +920,12 @@ models/models_loading_gltf: models/models_loading_gltf.c models/models_loading_m3d: models/models_loading_m3d.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) -sTOTAL_MEMORY=67108864 \ --preload-file models/resources/models/m3d/cesium_man.m3d@resources/models/m3d/cesium_man.m3d - + models/models_loading_vox: models/models_loading_vox.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) -sTOTAL_MEMORY=67108864 \ --preload-file models/resources/models/vox/chr_knight.vox@resources/models/vox/chr_knight.vox \ --preload-file models/resources/models/vox/chr_sword.vox@resources/models/vox/chr_sword.vox \ - --preload-file models/resources/models/vox/monu9.vox@resources/models/vox/monu9.vox + --preload-file models/resources/models/vox/monu9.vox@resources/models/vox/monu9.vox models/models_mesh_generation: models/models_mesh_generation.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) @@ -947,7 +951,7 @@ models/models_skybox: models/models_skybox.c models/models_waving_cubes: models/models_waving_cubes.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) - + models/models_yaw_pitch_roll: models/models_yaw_pitch_roll.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) -sTOTAL_MEMORY=67108864 \ --preload-file models/resources/models/obj/plane.obj@resources/models/obj/plane.obj \ @@ -1080,7 +1084,7 @@ audio/audio_mixed_processor: audio/audio_mixed_processor.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) -sTOTAL_MEMORY=67108864 \ --preload-file audio/resources/country.mp3@resources/country.mp3 \ --preload-file audio/resources/coin.wav@resources/coin.wav - + audio/audio_module_playing: audio/audio_module_playing.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \ --preload-file audio/resources/mini1111.xm@resources/mini1111.xm From 7fedf9e0b865acb1be48b8a1a4a306401105365e Mon Sep 17 00:00:00 2001 From: Nikolas Date: Sat, 26 Oct 2024 12:09:38 +0200 Subject: [PATCH 206/208] [rtextures/rlgl] Load mipmaps for cubemaps (#4429) * [rlgl] Load cubemap mipmaps * [rtextures] Only generate mipmaps that don't already exist * [rtextures] ImageDraw(): Implement drawing to mipmaps * [rtextures] Load cubemap mipmaps --- examples/models/models_skybox.c | 2 +- src/rlgl.h | 39 +++++++++++++++++----- src/rtextures.c | 57 ++++++++++++++++++++++++++------- 3 files changed, 78 insertions(+), 20 deletions(-) diff --git a/examples/models/models_skybox.c b/examples/models/models_skybox.c index fc9627b42..4689acd77 100644 --- a/examples/models/models_skybox.c +++ b/examples/models/models_skybox.c @@ -191,7 +191,7 @@ static TextureCubemap GenTextureCubemap(Shader shader, Texture2D panorama, int s // STEP 1: Setup framebuffer //------------------------------------------------------------------------------------------ unsigned int rbo = rlLoadTextureDepth(size, size, true); - cubemap.id = rlLoadTextureCubemap(0, size, format); + cubemap.id = rlLoadTextureCubemap(0, size, format, 1); unsigned int fbo = rlLoadFramebuffer(); rlFramebufferAttach(fbo, rbo, RL_ATTACHMENT_DEPTH, RL_ATTACHMENT_RENDERBUFFER, 0); diff --git a/src/rlgl.h b/src/rlgl.h index 3d6a00628..56f01e5f4 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -749,7 +749,7 @@ RLAPI void rlDrawVertexArrayElementsInstanced(int offset, int count, const void // Textures management RLAPI unsigned int rlLoadTexture(const void *data, int width, int height, int format, int mipmapCount); // Load texture data RLAPI unsigned int rlLoadTextureDepth(int width, int height, bool useRenderBuffer); // Load depth texture/renderbuffer (to be attached to fbo) -RLAPI unsigned int rlLoadTextureCubemap(const void *data, int size, int format); // Load texture cubemap data +RLAPI unsigned int rlLoadTextureCubemap(const void *data, int size, int format, int mipmapCount); // Load texture cubemap data RLAPI void rlUpdateTexture(unsigned int id, int offsetX, int offsetY, int width, int height, int format, const void *data); // Update texture with new data on GPU RLAPI void rlGetGlTextureFormats(int format, unsigned int *glInternalFormat, unsigned int *glFormat, unsigned int *glType); // Get OpenGL internal formats RLAPI const char *rlGetPixelFormatName(unsigned int format); // Get name string for pixel format @@ -3386,11 +3386,17 @@ unsigned int rlLoadTextureDepth(int width, int height, bool useRenderBuffer) // Load texture cubemap // NOTE: Cubemap data is expected to be 6 images in a single data array (one after the other), // expected the following convention: +X, -X, +Y, -Y, +Z, -Z -unsigned int rlLoadTextureCubemap(const void *data, int size, int format) +unsigned int rlLoadTextureCubemap(const void *data, int size, int format, int mipmapCount) { unsigned int id = 0; #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + int mipSize = size; + + // NOTE: Added pointer math separately from function to avoid UBSAN complaining + unsigned char *dataPtr = NULL; + if (data != NULL) dataPtr = (unsigned char *)data; + unsigned int dataSize = rlGetPixelDataSize(size, size, format); glGenTextures(1, &id); @@ -3401,9 +3407,12 @@ unsigned int rlLoadTextureCubemap(const void *data, int size, int format) if (glInternalFormat != 0) { - // Load cubemap faces - for (unsigned int i = 0; i < 6; i++) + // Load cubemap faces/mipmaps + for (unsigned int i = 0; i < 6 * mipmapCount; i++) { + int mipmapLevel = i / 6; + int face = i % 6; + if (data == NULL) { if (format < RL_PIXELFORMAT_COMPRESSED_DXT1_RGB) @@ -3411,14 +3420,14 @@ unsigned int rlLoadTextureCubemap(const void *data, int size, int format) if ((format == RL_PIXELFORMAT_UNCOMPRESSED_R32) || (format == RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32) || (format == RL_PIXELFORMAT_UNCOMPRESSED_R16) || (format == RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16)) TRACELOG(RL_LOG_WARNING, "TEXTURES: Cubemap requested format not supported"); - else glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glInternalFormat, size, size, 0, glFormat, glType, NULL); + else glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, mipmapLevel, glInternalFormat, mipSize, mipSize, 0, glFormat, glType, NULL); } else TRACELOG(RL_LOG_WARNING, "TEXTURES: Empty cubemap creation does not support compressed format"); } else { - if (format < RL_PIXELFORMAT_COMPRESSED_DXT1_RGB) glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glInternalFormat, size, size, 0, glFormat, glType, (unsigned char *)data + i*dataSize); - else glCompressedTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glInternalFormat, size, size, 0, dataSize, (unsigned char *)data + i*dataSize); + if (format < RL_PIXELFORMAT_COMPRESSED_DXT1_RGB) glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, mipmapLevel, glInternalFormat, mipSize, mipSize, 0, glFormat, glType, (unsigned char *)dataPtr + face*dataSize); + else glCompressedTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, mipmapLevel, glInternalFormat, mipSize, mipSize, 0, dataSize, (unsigned char *)dataPtr + face*dataSize); } #if defined(GRAPHICS_API_OPENGL_33) @@ -3437,11 +3446,25 @@ unsigned int rlLoadTextureCubemap(const void *data, int size, int format) glTexParameteriv(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); } #endif + if (face == 5) { + mipSize /= 2; + if (data != NULL) + dataPtr += dataSize * 6; // Increment data pointer to next mipmap + + // Security check for NPOT textures + if (mipSize < 1) mipSize = 1; + + dataSize = rlGetPixelDataSize(mipSize, mipSize, format); + } } } // Set cubemap texture sampling parameters - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + if (mipmapCount > 1) { + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + } else { + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + } glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); diff --git a/src/rtextures.c b/src/rtextures.c index ca3ad0990..d0f9d4a9e 100644 --- a/src/rtextures.c +++ b/src/rtextures.c @@ -2390,22 +2390,16 @@ void ImageMipmaps(Image *image) else TRACELOG(LOG_WARNING, "IMAGE: Mipmaps required memory could not be allocated"); // Pointer to allocated memory point where store next mipmap level data - unsigned char *nextmip = (unsigned char *)image->data + GetPixelDataSize(image->width, image->height, image->format); + unsigned char *nextmip = image->data; - mipWidth = image->width/2; - mipHeight = image->height/2; + mipWidth = image->width; + mipHeight = image->height; mipSize = GetPixelDataSize(mipWidth, mipHeight, image->format); Image imCopy = ImageCopy(*image); for (int i = 1; i < mipCount; i++) { - TRACELOGD("IMAGE: Generating mipmap level: %i (%i x %i) - size: %i - offset: 0x%x", i, mipWidth, mipHeight, mipSize, nextmip); - - ImageResize(&imCopy, mipWidth, mipHeight); // Uses internally Mitchell cubic downscale filter - - memcpy(nextmip, imCopy.data, mipSize); nextmip += mipSize; - image->mipmaps++; mipWidth /= 2; mipHeight /= 2; @@ -2415,9 +2409,20 @@ void ImageMipmaps(Image *image) if (mipHeight < 1) mipHeight = 1; mipSize = GetPixelDataSize(mipWidth, mipHeight, image->format); + + if (i < image->mipmaps) + continue; + + TRACELOGD("IMAGE: Generating mipmap level: %i (%i x %i) - size: %i - offset: 0x%x", i, mipWidth, mipHeight, mipSize, nextmip); + + ImageResize(&imCopy, mipWidth, mipHeight); // Uses internally Mitchell cubic downscale filter + + memcpy(nextmip, imCopy.data, mipSize); } UnloadImage(imCopy); + + image->mipmaps = mipCount; } else TRACELOG(LOG_WARNING, "IMAGE: Mipmaps already available"); } @@ -3906,7 +3911,6 @@ void ImageDraw(Image *dst, Image src, Rectangle srcRec, Rectangle dstRec, Color if ((dst->data == NULL) || (dst->width == 0) || (dst->height == 0) || (src.data == NULL) || (src.width == 0) || (src.height == 0)) return; - if (dst->mipmaps > 1) TRACELOG(LOG_WARNING, "Image drawing only applied to base mipmap level"); if (dst->format >= PIXELFORMAT_COMPRESSED_DXT1_RGB) TRACELOG(LOG_WARNING, "Image drawing not supported for compressed formats"); else { @@ -4019,6 +4023,34 @@ void ImageDraw(Image *dst, Image src, Rectangle srcRec, Rectangle dstRec, Color } if (useSrcMod) UnloadImage(srcMod); // Unload source modified image + + if (dst->mipmaps > 1 && src.mipmaps > 1) { + Image mipmapDst = *dst; + mipmapDst.data = (char *) mipmapDst.data + GetPixelDataSize(mipmapDst.width, mipmapDst.height, mipmapDst.format); + mipmapDst.width /= 2; + mipmapDst.height /= 2; + mipmapDst.mipmaps--; + + Image mipmapSrc = src; + mipmapSrc.data = (char *) mipmapSrc.data + GetPixelDataSize(mipmapSrc.width, mipmapSrc.height, mipmapSrc.format); + mipmapSrc.width /= 2; + mipmapSrc.height /= 2; + mipmapSrc.mipmaps--; + + Rectangle mipmapSrcRec = srcRec; + mipmapSrcRec.width /= 2; + mipmapSrcRec.height /= 2; + mipmapSrcRec.x /= 2; + mipmapSrcRec.y /= 2; + + Rectangle mipmapDstRec = dstRec; + mipmapDstRec.width /= 2; + mipmapDstRec.height /= 2; + mipmapDstRec.x /= 2; + mipmapDstRec.y /= 2; + + ImageDraw(&mipmapDst, mipmapSrc, mipmapSrcRec, mipmapDstRec, tint); + } } } @@ -4162,6 +4194,9 @@ TextureCubemap LoadTextureCubemap(Image image, int layout) faces = GenImageColor(size, size*6, MAGENTA); ImageFormat(&faces, image.format); + ImageMipmaps(&image); + ImageMipmaps(&faces); + // NOTE: Image formatting does not work with compressed textures for (int i = 0; i < 6; i++) ImageDraw(&faces, image, faceRecs[i], (Rectangle){ 0, (float)size*i, (float)size, (float)size }, WHITE); @@ -4169,7 +4204,7 @@ TextureCubemap LoadTextureCubemap(Image image, int layout) // NOTE: Cubemap data is expected to be provided as 6 images in a single data array, // one after the other (that's a vertical image), following convention: +X, -X, +Y, -Y, +Z, -Z - cubemap.id = rlLoadTextureCubemap(faces.data, size, faces.format); + cubemap.id = rlLoadTextureCubemap(faces.data, size, faces.format, faces.mipmaps); if (cubemap.id != 0) { From 80b490c8f1e09c7fd846252926ffe72af4b076b1 Mon Sep 17 00:00:00 2001 From: Ray Date: Sat, 26 Oct 2024 12:15:06 +0200 Subject: [PATCH 207/208] Reviewed formating to follow raylib conventions #4429 --- src/rlgl.h | 27 +++++++++++++-------------- src/rtextures.c | 12 ++++++------ 2 files changed, 19 insertions(+), 20 deletions(-) diff --git a/src/rlgl.h b/src/rlgl.h index 56f01e5f4..a7fedf0e4 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -3408,18 +3408,19 @@ unsigned int rlLoadTextureCubemap(const void *data, int size, int format, int mi if (glInternalFormat != 0) { // Load cubemap faces/mipmaps - for (unsigned int i = 0; i < 6 * mipmapCount; i++) + for (unsigned int i = 0; i < 6*mipmapCount; i++) { - int mipmapLevel = i / 6; - int face = i % 6; + int mipmapLevel = i/6; + int face = i%6; if (data == NULL) { if (format < RL_PIXELFORMAT_COMPRESSED_DXT1_RGB) { - if ((format == RL_PIXELFORMAT_UNCOMPRESSED_R32) || (format == RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32) - || (format == RL_PIXELFORMAT_UNCOMPRESSED_R16) || (format == RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16)) - TRACELOG(RL_LOG_WARNING, "TEXTURES: Cubemap requested format not supported"); + if ((format == RL_PIXELFORMAT_UNCOMPRESSED_R32) || + (format == RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32) || + (format == RL_PIXELFORMAT_UNCOMPRESSED_R16) || + (format == RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16)) TRACELOG(RL_LOG_WARNING, "TEXTURES: Cubemap requested format not supported"); else glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, mipmapLevel, glInternalFormat, mipSize, mipSize, 0, glFormat, glType, NULL); } else TRACELOG(RL_LOG_WARNING, "TEXTURES: Empty cubemap creation does not support compressed format"); @@ -3446,10 +3447,10 @@ unsigned int rlLoadTextureCubemap(const void *data, int size, int format, int mi glTexParameteriv(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); } #endif - if (face == 5) { + if (face == 5) + { mipSize /= 2; - if (data != NULL) - dataPtr += dataSize * 6; // Increment data pointer to next mipmap + if (data != NULL) dataPtr += dataSize*6; // Increment data pointer to next mipmap // Security check for NPOT textures if (mipSize < 1) mipSize = 1; @@ -3460,11 +3461,9 @@ unsigned int rlLoadTextureCubemap(const void *data, int size, int format, int mi } // Set cubemap texture sampling parameters - if (mipmapCount > 1) { - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - } else { - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - } + if (mipmapCount > 1) glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + else glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); diff --git a/src/rtextures.c b/src/rtextures.c index d0f9d4a9e..076452311 100644 --- a/src/rtextures.c +++ b/src/rtextures.c @@ -2410,12 +2410,11 @@ void ImageMipmaps(Image *image) mipSize = GetPixelDataSize(mipWidth, mipHeight, image->format); - if (i < image->mipmaps) - continue; + if (i < image->mipmaps) continue; TRACELOGD("IMAGE: Generating mipmap level: %i (%i x %i) - size: %i - offset: 0x%x", i, mipWidth, mipHeight, mipSize, nextmip); - ImageResize(&imCopy, mipWidth, mipHeight); // Uses internally Mitchell cubic downscale filter + ImageResize(&imCopy, mipWidth, mipHeight); // Uses internally Mitchell cubic downscale filter memcpy(nextmip, imCopy.data, mipSize); } @@ -4024,15 +4023,16 @@ void ImageDraw(Image *dst, Image src, Rectangle srcRec, Rectangle dstRec, Color if (useSrcMod) UnloadImage(srcMod); // Unload source modified image - if (dst->mipmaps > 1 && src.mipmaps > 1) { + if ((dst->mipmaps > 1) && (src.mipmaps > 1)) + { Image mipmapDst = *dst; - mipmapDst.data = (char *) mipmapDst.data + GetPixelDataSize(mipmapDst.width, mipmapDst.height, mipmapDst.format); + mipmapDst.data = (char *)mipmapDst.data + GetPixelDataSize(mipmapDst.width, mipmapDst.height, mipmapDst.format); mipmapDst.width /= 2; mipmapDst.height /= 2; mipmapDst.mipmaps--; Image mipmapSrc = src; - mipmapSrc.data = (char *) mipmapSrc.data + GetPixelDataSize(mipmapSrc.width, mipmapSrc.height, mipmapSrc.format); + mipmapSrc.data = (char *)mipmapSrc.data + GetPixelDataSize(mipmapSrc.width, mipmapSrc.height, mipmapSrc.format); mipmapSrc.width /= 2; mipmapSrc.height /= 2; mipmapSrc.mipmaps--; From 1f6b3384fa1c6ec2743f76f4df8dd4ec10e86ddd Mon Sep 17 00:00:00 2001 From: Ray Date: Sat, 26 Oct 2024 12:26:00 +0200 Subject: [PATCH 208/208] Reviewed formatting, remove end-line points, for consistency with comments --- src/rlgl.h | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/src/rlgl.h b/src/rlgl.h index a7fedf0e4..34cae97e8 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -8,17 +8,17 @@ * * ADDITIONAL NOTES: * When choosing an OpenGL backend different than OpenGL 1.1, some internal buffer are -* initialized on rlglInit() to accumulate vertex data. +* initialized on rlglInit() to accumulate vertex data * * When an internal state change is required all the stored vertex data is renderer in batch, -* additionally, rlDrawRenderBatchActive() could be called to force flushing of the batch. +* additionally, rlDrawRenderBatchActive() could be called to force flushing of the batch * * Some resources are also loaded for convenience, here the complete list: * - Default batch (RLGL.defaultBatch): RenderBatch system to accumulate vertex data * - Default texture (RLGL.defaultTextureId): 1x1 white pixel R8G8B8A8 * - Default shader (RLGL.State.defaultShaderId, RLGL.State.defaultShaderLocs) * -* Internal buffer (and resources) must be manually unloaded calling rlglClose(). +* Internal buffer (and resources) must be manually unloaded calling rlglClose() * * CONFIGURATION: * #define GRAPHICS_API_OPENGL_11 @@ -32,9 +32,9 @@ * required by any other module, use rlGetVersion() to check it * * #define RLGL_IMPLEMENTATION -* Generates the implementation of the library into the included file. +* Generates the implementation of the library into the included file * If not defined, the library is in header only mode and can be included in other headers -* or source files without problems. But only ONE file should hold the implementation. +* or source files without problems. But only ONE file should hold the implementation * * #define RLGL_RENDER_TEXTURES_HINT * Enable framebuffer objects (fbo) support (enabled by default) @@ -1503,8 +1503,8 @@ void rlVertex3f(float x, float y, float z) tz = RLGL.State.transform.m2*x + RLGL.State.transform.m6*y + RLGL.State.transform.m10*z + RLGL.State.transform.m14; } - // WARNING: We can't break primitives when launching a new batch. - // RL_LINES comes in pairs, RL_TRIANGLES come in groups of 3 vertices and RL_QUADS come in groups of 4 vertices. + // WARNING: We can't break primitives when launching a new batch + // RL_LINES comes in pairs, RL_TRIANGLES come in groups of 3 vertices and RL_QUADS come in groups of 4 vertices // We must check current draw.mode when a new vertex is required and finish the batch only if the draw.mode draw.vertexCount is %2, %3 or %4 if (RLGL.State.vertexCounter > (RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].elementCount*4 - 4)) { @@ -2933,11 +2933,11 @@ void rlDrawRenderBatch(rlRenderBatch *batch) glBufferSubData(GL_ARRAY_BUFFER, 0, RLGL.State.vertexCounter*4*sizeof(unsigned char), batch->vertexBuffer[batch->currentBuffer].colors); //glBufferData(GL_ARRAY_BUFFER, sizeof(float)*4*4*batch->vertexBuffer[batch->currentBuffer].elementCount, batch->vertexBuffer[batch->currentBuffer].colors, GL_DYNAMIC_DRAW); // Update all buffer - // NOTE: glMapBuffer() causes sync issue. - // If GPU is working with this buffer, glMapBuffer() will wait(stall) until GPU to finish its job. - // To avoid waiting (idle), you can call first glBufferData() with NULL pointer before glMapBuffer(). + // NOTE: glMapBuffer() causes sync issue + // If GPU is working with this buffer, glMapBuffer() will wait(stall) until GPU to finish its job + // To avoid waiting (idle), you can call first glBufferData() with NULL pointer before glMapBuffer() // If you do that, the previous data in PBO will be discarded and glMapBuffer() returns a new - // allocated pointer immediately even if GPU is still working with the previous data. + // allocated pointer immediately even if GPU is still working with the previous data // Another option: map the buffer object into client's memory // Probably this code could be moved somewhere else... @@ -2990,7 +2990,7 @@ void rlDrawRenderBatch(rlRenderBatch *batch) } // WARNING: For the following setup of the view, model, and normal matrices, it is expected that - // transformations and rendering occur between rlPushMatrix and rlPopMatrix. + // transformations and rendering occur between rlPushMatrix() and rlPopMatrix() if (RLGL.State.currentShaderLocs[RL_SHADER_LOC_MATRIX_VIEW] != -1) { @@ -3622,8 +3622,8 @@ void *rlReadTexturePixels(unsigned int id, int width, int height, int format) //glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height); //glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &format); - // NOTE: Each row written to or read from by OpenGL pixel operations like glGetTexImage are aligned to a 4 byte boundary by default, which may add some padding. - // Use glPixelStorei to modify padding with the GL_[UN]PACK_ALIGNMENT setting. + // NOTE: Each row written to or read from by OpenGL pixel operations like glGetTexImage are aligned to a 4 byte boundary by default, which may add some padding + // Use glPixelStorei to modify padding with the GL_[UN]PACK_ALIGNMENT setting // GL_PACK_ALIGNMENT affects operations that read from OpenGL memory (glReadPixels, glGetTexImage, etc.) // GL_UNPACK_ALIGNMENT affects operations that write to OpenGL memory (glTexImage, etc.) glPixelStorei(GL_PACK_ALIGNMENT, 1); @@ -3644,7 +3644,7 @@ void *rlReadTexturePixels(unsigned int id, int width, int height, int format) #if defined(GRAPHICS_API_OPENGL_ES2) // glGetTexImage() is not available on OpenGL ES 2.0 - // Texture width and height are required on OpenGL ES 2.0. There is no way to get it from texture id. + // Texture width and height are required on OpenGL ES 2.0, there is no way to get it from texture id // Two possible Options: // 1 - Bind texture to color fbo attachment and glReadPixels() // 2 - Create an fbo, activate it, render quad with texture, glReadPixels() @@ -3810,7 +3810,7 @@ void rlUnloadFramebuffer(unsigned int id) else if (depthType == GL_TEXTURE) glDeleteTextures(1, &depthIdU); // NOTE: If a texture object is deleted while its image is attached to the *currently bound* framebuffer, - // the texture image is automatically detached from the currently bound framebuffer. + // the texture image is automatically detached from the currently bound framebuffer glBindFramebuffer(GL_FRAMEBUFFER, 0); glDeleteFramebuffers(1, &id); @@ -4253,7 +4253,7 @@ unsigned int rlLoadShaderProgram(unsigned int vShaderId, unsigned int fShaderId) else { // Get the size of compiled shader program (not available on OpenGL ES 2.0) - // NOTE: If GL_LINK_STATUS is GL_FALSE, program binary length is zero. + // NOTE: If GL_LINK_STATUS is GL_FALSE, program binary length is zero //GLint binarySize = 0; //glGetProgramiv(id, GL_PROGRAM_BINARY_LENGTH, &binarySize); @@ -4447,7 +4447,7 @@ unsigned int rlLoadComputeShaderProgram(unsigned int shaderId) else { // Get the size of compiled shader program (not available on OpenGL ES 2.0) - // NOTE: If GL_LINK_STATUS is GL_FALSE, program binary length is zero. + // NOTE: If GL_LINK_STATUS is GL_FALSE, program binary length is zero //GLint binarySize = 0; //glGetProgramiv(id, GL_PROGRAM_BINARY_LENGTH, &binarySize);